summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/CODEOWNERS3
-rw-r--r--.github/ISSUE_TEMPLATE/bug_report.yml7
-rw-r--r--.github/workflows/linux_builds.yml21
-rw-r--r--.gitignore7
-rw-r--r--.mailmap8
-rw-r--r--AUTHORS.md11
-rw-r--r--CONTRIBUTING.md4
-rw-r--r--COPYRIGHT.txt10
-rw-r--r--DONORS.md155
-rw-r--r--SConstruct12
-rw-r--r--core/config/engine.cpp9
-rw-r--r--core/config/engine.h4
-rw-r--r--core/config/project_settings.cpp26
-rw-r--r--core/config/project_settings.h2
-rw-r--r--core/core_bind.cpp22
-rw-r--r--core/core_bind.h6
-rw-r--r--core/core_constants.cpp4
-rw-r--r--core/debugger/remote_debugger.cpp87
-rw-r--r--core/debugger/remote_debugger.h2
-rw-r--r--core/extension/SCsub4
-rw-r--r--core/extension/extension_api_dump.cpp233
-rw-r--r--core/extension/extension_api_dump.h4
-rw-r--r--core/extension/gdextension.cpp (renamed from core/extension/native_extension.cpp)336
-rw-r--r--core/extension/gdextension.h (renamed from core/extension/native_extension.h)60
-rw-r--r--core/extension/gdextension_interface.cpp1105
-rw-r--r--core/extension/gdextension_interface.h619
-rw-r--r--core/extension/gdextension_manager.cpp (renamed from core/extension/native_extension_manager.cpp)76
-rw-r--r--core/extension/gdextension_manager.h (renamed from core/extension/native_extension_manager.h)30
-rw-r--r--core/extension/gdnative_interface.cpp1083
-rw-r--r--core/extension/gdnative_interface.h589
-rw-r--r--core/extension/make_interface_dumper.py14
-rw-r--r--core/input/gamecontrollerdb.txt120
-rw-r--r--core/input/input_event.cpp2
-rw-r--r--core/input/shortcut.cpp2
-rw-r--r--core/io/file_access.cpp7
-rw-r--r--core/io/file_access.h5
-rw-r--r--core/io/image.cpp227
-rw-r--r--core/io/image.h18
-rw-r--r--core/io/packet_peer.h4
-rw-r--r--core/io/pck_packer.cpp4
-rw-r--r--core/io/resource.cpp2
-rw-r--r--core/io/resource_loader.cpp29
-rw-r--r--core/io/resource_loader.h2
-rw-r--r--core/io/stream_peer.h8
-rw-r--r--core/io/xml_parser.cpp69
-rw-r--r--core/io/xml_parser.h8
-rw-r--r--core/math/a_star_grid_2d.cpp60
-rw-r--r--core/math/a_star_grid_2d.h15
-rw-r--r--core/math/basis.cpp8
-rw-r--r--core/math/color.h10
-rw-r--r--core/math/convex_hull.cpp3
-rw-r--r--core/math/expression.cpp2
-rw-r--r--core/math/math_defs.h1
-rw-r--r--core/math/math_funcs.h30
-rw-r--r--core/math/projection.cpp14
-rw-r--r--core/math/vector2.h24
-rw-r--r--core/math/vector2i.cpp6
-rw-r--r--core/math/vector2i.h1
-rw-r--r--core/math/vector3.h29
-rw-r--r--core/math/vector3i.cpp7
-rw-r--r--core/math/vector3i.h1
-rw-r--r--core/math/vector4.cpp11
-rw-r--r--core/math/vector4i.cpp8
-rw-r--r--core/math/vector4i.h1
-rw-r--r--core/object/class_db.cpp20
-rw-r--r--core/object/class_db.h4
-rw-r--r--core/object/make_virtuals.py14
-rw-r--r--core/object/method_bind.h34
-rw-r--r--core/object/object.cpp20
-rw-r--r--core/object/object.h96
-rw-r--r--core/object/ref_counted.h3
-rw-r--r--core/object/script_language.cpp6
-rw-r--r--core/object/script_language_extension.h80
-rw-r--r--core/object/undo_redo.cpp4
-rw-r--r--core/object/undo_redo.h1
-rw-r--r--core/object/worker_thread_pool.cpp4
-rw-r--r--core/os/os.cpp32
-rw-r--r--core/os/os.h5
-rw-r--r--core/register_core_types.cpp34
-rw-r--r--core/string/optimized_translation.cpp33
-rw-r--r--core/string/optimized_translation.h1
-rw-r--r--core/string/string_name.cpp4
-rw-r--r--core/string/string_name.h1
-rw-r--r--core/string/translation.cpp13
-rw-r--r--core/string/translation.h1
-rw-r--r--core/string/translation_po.cpp17
-rw-r--r--core/string/translation_po.h1
-rw-r--r--core/string/ustring.cpp51
-rw-r--r--core/string/ustring.h4
-rw-r--r--core/templates/hashfuncs.h1
-rw-r--r--core/variant/array.cpp101
-rw-r--r--core/variant/array.h1
-rw-r--r--core/variant/container_type_validate.h23
-rw-r--r--core/variant/dictionary.cpp56
-rw-r--r--core/variant/native_ptr.h92
-rw-r--r--core/variant/type_info.h1
-rw-r--r--core/variant/variant.cpp25
-rw-r--r--core/variant/variant.h4
-rw-r--r--core/variant/variant_call.cpp351
-rw-r--r--core/variant/variant_construct.cpp2
-rw-r--r--core/variant/variant_construct.h58
-rw-r--r--core/variant/variant_internal.h30
-rw-r--r--core/variant/variant_op.cpp117
-rw-r--r--core/variant/variant_op.h89
-rw-r--r--core/variant/variant_parser.cpp84
-rw-r--r--core/variant/variant_parser.h42
-rw-r--r--core/variant/variant_utility.cpp95
-rw-r--r--doc/classes/@GlobalScope.xml188
-rw-r--r--doc/classes/AStarGrid2D.xml40
-rw-r--r--doc/classes/Animation.xml54
-rw-r--r--doc/classes/AnimationLibrary.xml7
-rw-r--r--doc/classes/AnimationNode.xml11
-rw-r--r--doc/classes/AnimationNodeStateMachineTransition.xml18
-rw-r--r--doc/classes/AnimationTree.xml78
-rw-r--r--doc/classes/Area2D.xml60
-rw-r--r--doc/classes/Area3D.xml60
-rw-r--r--doc/classes/Array.xml7
-rw-r--r--doc/classes/ArrayMesh.xml16
-rw-r--r--doc/classes/AudioEffectDistortion.xml12
-rw-r--r--doc/classes/AudioStreamPlayer2D.xml4
-rw-r--r--doc/classes/AudioStreamPlayer3D.xml4
-rw-r--r--doc/classes/AudioStreamRandomizer.xml10
-rw-r--r--doc/classes/BackBufferCopy.xml12
-rw-r--r--doc/classes/BaseMaterial3D.xml17
-rw-r--r--doc/classes/Button.xml1
-rw-r--r--doc/classes/ButtonGroup.xml4
-rw-r--r--doc/classes/Callable.xml38
-rw-r--r--doc/classes/CanvasGroup.xml20
-rw-r--r--doc/classes/CanvasItem.xml24
-rw-r--r--doc/classes/CanvasLayer.xml6
-rw-r--r--doc/classes/CharFXTransform.xml3
-rw-r--r--doc/classes/CharacterBody2D.xml2
-rw-r--r--doc/classes/CheckBox.xml1
-rw-r--r--doc/classes/CheckButton.xml1
-rw-r--r--doc/classes/CodeEdit.xml1
-rw-r--r--doc/classes/CollisionObject2D.xml4
-rw-r--r--doc/classes/CollisionObject3D.xml4
-rw-r--r--doc/classes/Color.xml180
-rw-r--r--doc/classes/ColorPicker.xml3
-rw-r--r--doc/classes/ColorPickerButton.xml1
-rw-r--r--doc/classes/Control.xml12
-rw-r--r--doc/classes/Curve2D.xml16
-rw-r--r--doc/classes/Curve3D.xml22
-rw-r--r--doc/classes/Dictionary.xml167
-rw-r--r--doc/classes/DirectionalLight2D.xml4
-rw-r--r--doc/classes/DisplayServer.xml43
-rw-r--r--doc/classes/EditorDebuggerPlugin.xml116
-rw-r--r--doc/classes/EditorDebuggerSession.xml86
-rw-r--r--doc/classes/EditorInspector.xml2
-rw-r--r--doc/classes/EditorInterface.xml12
-rw-r--r--doc/classes/EditorNode3DGizmoPlugin.xml2
-rw-r--r--doc/classes/EditorPaths.xml2
-rw-r--r--doc/classes/EditorPlugin.xml24
-rw-r--r--doc/classes/EditorProperty.xml2
-rw-r--r--doc/classes/EditorSceneFormatImporter.xml1
-rw-r--r--doc/classes/EditorScenePostImport.xml6
-rw-r--r--doc/classes/EditorSettings.xml6
-rw-r--r--doc/classes/EditorSpinSlider.xml22
-rw-r--r--doc/classes/EditorUndoRedoManager.xml5
-rw-r--r--doc/classes/EditorVCSInterface.xml4
-rw-r--r--doc/classes/Engine.xml5
-rw-r--r--doc/classes/FileAccess.xml14
-rw-r--r--doc/classes/FileSystemDock.xml2
-rw-r--r--doc/classes/Font.xml12
-rw-r--r--doc/classes/FontFile.xml23
-rw-r--r--doc/classes/GDExtension.xml (renamed from doc/classes/NativeExtension.xml)6
-rw-r--r--doc/classes/GDExtensionManager.xml (renamed from doc/classes/NativeExtensionManager.xml)10
-rw-r--r--doc/classes/GeometryInstance3D.xml15
-rw-r--r--doc/classes/GraphEdit.xml2
-rw-r--r--doc/classes/HSlider.xml1
-rw-r--r--doc/classes/Image.xml31
-rw-r--r--doc/classes/Input.xml14
-rw-r--r--doc/classes/ItemList.xml1
-rw-r--r--doc/classes/Label.xml4
-rw-r--r--doc/classes/LabelSettings.xml11
-rw-r--r--doc/classes/Light2D.xml13
-rw-r--r--doc/classes/Light3D.xml2
-rw-r--r--doc/classes/LineEdit.xml1
-rw-r--r--doc/classes/LinkButton.xml19
-rw-r--r--doc/classes/MenuBar.xml1
-rw-r--r--doc/classes/MenuButton.xml1
-rw-r--r--doc/classes/Mesh.xml4
-rw-r--r--doc/classes/MeshLibrary.xml27
-rw-r--r--doc/classes/MissingNode.xml2
-rw-r--r--doc/classes/MissingResource.xml2
-rw-r--r--doc/classes/NavigationAgent2D.xml49
-rw-r--r--doc/classes/NavigationAgent3D.xml49
-rw-r--r--doc/classes/NavigationLink2D.xml4
-rw-r--r--doc/classes/NavigationLink3D.xml4
-rw-r--r--doc/classes/NavigationMesh.xml14
-rw-r--r--doc/classes/NavigationMeshGenerator.xml10
-rw-r--r--doc/classes/NavigationObstacle2D.xml2
-rw-r--r--doc/classes/NavigationObstacle3D.xml2
-rw-r--r--doc/classes/NavigationPathQueryParameters2D.xml24
-rw-r--r--doc/classes/NavigationPathQueryParameters3D.xml24
-rw-r--r--doc/classes/NavigationPathQueryResult2D.xml19
-rw-r--r--doc/classes/NavigationPathQueryResult3D.xml19
-rw-r--r--doc/classes/NavigationPolygon.xml14
-rw-r--r--doc/classes/NavigationRegion2D.xml10
-rw-r--r--doc/classes/NavigationRegion3D.xml10
-rw-r--r--doc/classes/NavigationServer2D.xml44
-rw-r--r--doc/classes/NavigationServer3D.xml50
-rw-r--r--doc/classes/Node.xml9
-rw-r--r--doc/classes/Node2D.xml16
-rw-r--r--doc/classes/Node3D.xml6
-rw-r--r--doc/classes/NodePath.xml2
-rw-r--r--doc/classes/OS.xml36
-rw-r--r--doc/classes/Object.xml604
-rw-r--r--doc/classes/OfflineMultiplayerPeer.xml12
-rw-r--r--doc/classes/OmniLight3D.xml2
-rw-r--r--doc/classes/OptionButton.xml5
-rw-r--r--doc/classes/PathFollow3D.xml13
-rw-r--r--doc/classes/PhysicalSkyMaterial.xml11
-rw-r--r--doc/classes/PhysicsBody2D.xml10
-rw-r--r--doc/classes/PhysicsBody3D.xml10
-rw-r--r--doc/classes/PhysicsPointQueryParameters2D.xml4
-rw-r--r--doc/classes/PhysicsPointQueryParameters3D.xml4
-rw-r--r--doc/classes/PhysicsRayQueryParameters2D.xml2
-rw-r--r--doc/classes/PhysicsRayQueryParameters3D.xml6
-rw-r--r--doc/classes/PhysicsServer2D.xml15
-rw-r--r--doc/classes/PhysicsServer3D.xml15
-rw-r--r--doc/classes/PhysicsServer3DExtension.xml13
-rw-r--r--doc/classes/PhysicsShapeQueryParameters2D.xml2
-rw-r--r--doc/classes/PhysicsShapeQueryParameters3D.xml4
-rw-r--r--doc/classes/PhysicsTestMotionParameters2D.xml4
-rw-r--r--doc/classes/PhysicsTestMotionParameters3D.xml6
-rw-r--r--doc/classes/PointLight2D.xml3
-rw-r--r--doc/classes/Popup.xml2
-rw-r--r--doc/classes/PopupMenu.xml6
-rw-r--r--doc/classes/PortableCompressedTexture2D.xml2
-rw-r--r--doc/classes/PrimitiveMesh.xml6
-rw-r--r--doc/classes/ProgressBar.xml1
-rw-r--r--doc/classes/ProjectSettings.xml73
-rw-r--r--doc/classes/RDTextureFormat.xml2
-rw-r--r--doc/classes/RID.xml13
-rw-r--r--doc/classes/Rect2.xml4
-rw-r--r--doc/classes/Rect2i.xml4
-rw-r--r--doc/classes/RenderingDevice.xml85
-rw-r--r--doc/classes/RenderingServer.xml28
-rw-r--r--doc/classes/RichTextLabel.xml16
-rw-r--r--doc/classes/SceneTree.xml1
-rw-r--r--doc/classes/ScrollContainer.xml1
-rw-r--r--doc/classes/Signal.xml40
-rw-r--r--doc/classes/SpinBox.xml1
-rw-r--r--doc/classes/SpotLight3D.xml1
-rw-r--r--doc/classes/Sprite3D.xml1
-rw-r--r--doc/classes/String.xml539
-rw-r--r--doc/classes/StringName.xml921
-rw-r--r--doc/classes/SystemFont.xml15
-rw-r--r--doc/classes/TabBar.xml1
-rw-r--r--doc/classes/TabContainer.xml1
-rw-r--r--doc/classes/TextEdit.xml1
-rw-r--r--doc/classes/TextLine.xml2
-rw-r--r--doc/classes/TextParagraph.xml2
-rw-r--r--doc/classes/TextServer.xml64
-rw-r--r--doc/classes/TextServerExtension.xml47
-rw-r--r--doc/classes/TextureButton.xml10
-rw-r--r--doc/classes/TextureProgressBar.xml2
-rw-r--r--doc/classes/TileData.xml13
-rw-r--r--doc/classes/TileMap.xml5
-rw-r--r--doc/classes/TileSet.xml1
-rw-r--r--doc/classes/Translation.xml6
-rw-r--r--doc/classes/Tree.xml18
-rw-r--r--doc/classes/TreeItem.xml4
-rw-r--r--doc/classes/TubeTrailMesh.xml6
-rw-r--r--doc/classes/VSlider.xml2
-rw-r--r--doc/classes/Vector2.xml31
-rw-r--r--doc/classes/Vector2i.xml11
-rw-r--r--doc/classes/Vector3.xml27
-rw-r--r--doc/classes/Vector3i.xml11
-rw-r--r--doc/classes/Vector4.xml13
-rw-r--r--doc/classes/Vector4i.xml11
-rw-r--r--doc/classes/Viewport.xml13
-rw-r--r--doc/classes/VisualInstance3D.xml7
-rw-r--r--doc/classes/Window.xml218
-rw-r--r--doc/classes/XRInterfaceExtension.xml9
-rw-r--r--doc/classes/float.xml9
-rw-r--r--doc/classes/int.xml7
-rwxr-xr-xdoc/tools/make_rst.py512
-rw-r--r--doc/translations/ar.po396
-rw-r--r--doc/translations/ca.po255
-rw-r--r--doc/translations/classes.pot255
-rw-r--r--doc/translations/cs.po268
-rw-r--r--doc/translations/de.po349
-rw-r--r--doc/translations/el.po255
-rw-r--r--doc/translations/es.po307
-rw-r--r--doc/translations/et.po255
-rw-r--r--doc/translations/fa.po256
-rw-r--r--doc/translations/fi.po255
-rw-r--r--doc/translations/fil.po255
-rw-r--r--doc/translations/fr.po438
-rw-r--r--doc/translations/gl.po255
-rw-r--r--doc/translations/hi.po255
-rw-r--r--doc/translations/hu.po255
-rw-r--r--doc/translations/id.po262
-rw-r--r--doc/translations/is.po255
-rw-r--r--doc/translations/it.po1241
-rw-r--r--doc/translations/ja.po312
-rw-r--r--doc/translations/ko.po268
-rw-r--r--doc/translations/lt.po255
-rw-r--r--doc/translations/lv.po255
-rw-r--r--doc/translations/mr.po255
-rw-r--r--doc/translations/nb.po255
-rw-r--r--doc/translations/ne.po255
-rw-r--r--doc/translations/nl.po255
-rw-r--r--doc/translations/pl.po337
-rw-r--r--doc/translations/pt.po275
-rw-r--r--doc/translations/pt_BR.po391
-rw-r--r--doc/translations/ro.po255
-rw-r--r--doc/translations/ru.po1741
-rw-r--r--doc/translations/sk.po255
-rw-r--r--doc/translations/sr_Cyrl.po255
-rw-r--r--doc/translations/sv.po255
-rw-r--r--doc/translations/th.po255
-rw-r--r--doc/translations/tl.po255
-rw-r--r--doc/translations/tr.po262
-rw-r--r--doc/translations/uk.po266
-rw-r--r--doc/translations/vi.po256
-rw-r--r--doc/translations/zh_CN.po1442
-rw-r--r--doc/translations/zh_TW.po267
-rw-r--r--drivers/SCsub1
-rw-r--r--drivers/gl_context/SCsub2
-rw-r--r--drivers/gles3/effects/copy_effects.cpp22
-rw-r--r--drivers/gles3/rasterizer_canvas_gles3.cpp373
-rw-r--r--drivers/gles3/rasterizer_canvas_gles3.h17
-rw-r--r--drivers/gles3/rasterizer_gles3.cpp42
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.cpp267
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.h33
-rw-r--r--drivers/gles3/shader_gles3.cpp29
-rw-r--r--drivers/gles3/shader_gles3.h18
-rw-r--r--drivers/gles3/shaders/SCsub3
-rw-r--r--drivers/gles3/shaders/canvas.glsl280
-rw-r--r--drivers/gles3/shaders/canvas_uniforms_inc.glsl36
-rw-r--r--drivers/gles3/shaders/cubemap_filter.glsl4
-rw-r--r--drivers/gles3/shaders/particles.glsl501
-rw-r--r--drivers/gles3/shaders/particles_copy.glsl122
-rw-r--r--drivers/gles3/shaders/scene.glsl91
-rw-r--r--drivers/gles3/shaders/skeleton.glsl269
-rw-r--r--drivers/gles3/shaders/stdlib_inc.glsl18
-rw-r--r--drivers/gles3/storage/config.cpp2
-rw-r--r--drivers/gles3/storage/config.h2
-rw-r--r--drivers/gles3/storage/light_storage.cpp4
-rw-r--r--drivers/gles3/storage/light_storage.h1
-rw-r--r--drivers/gles3/storage/material_storage.cpp552
-rw-r--r--drivers/gles3/storage/material_storage.h95
-rw-r--r--drivers/gles3/storage/mesh_storage.cpp594
-rw-r--r--drivers/gles3/storage/mesh_storage.h44
-rw-r--r--drivers/gles3/storage/particles_storage.cpp1220
-rw-r--r--drivers/gles3/storage/particles_storage.h315
-rw-r--r--drivers/gles3/storage/texture_storage.cpp108
-rw-r--r--drivers/gles3/storage/texture_storage.h5
-rw-r--r--drivers/gles3/storage/utilities.cpp64
-rw-r--r--drivers/register_driver_types.cpp2
-rw-r--r--drivers/unix/os_unix.cpp8
-rw-r--r--drivers/unix/os_unix.h2
-rw-r--r--drivers/vulkan/rendering_device_vulkan.cpp855
-rw-r--r--drivers/vulkan/rendering_device_vulkan.h46
-rw-r--r--drivers/vulkan/vulkan_context.cpp638
-rw-r--r--drivers/vulkan/vulkan_context.h43
-rw-r--r--editor/action_map_editor.cpp15
-rw-r--r--editor/action_map_editor.h11
-rw-r--r--editor/animation_bezier_editor.cpp53
-rw-r--r--editor/animation_bezier_editor.h3
-rw-r--r--editor/animation_track_editor.cpp2316
-rw-r--r--editor/animation_track_editor.h114
-rw-r--r--editor/animation_track_editor_plugins.cpp111
-rw-r--r--editor/audio_stream_preview.cpp8
-rw-r--r--editor/code_editor.cpp330
-rw-r--r--editor/code_editor.h1
-rw-r--r--editor/connections_dialog.cpp19
-rw-r--r--editor/create_dialog.cpp13
-rw-r--r--editor/create_dialog.h2
-rw-r--r--editor/debugger/editor_debugger_inspector.cpp2
-rw-r--r--editor/debugger/editor_debugger_node.cpp100
-rw-r--r--editor/debugger/editor_debugger_node.h18
-rw-r--r--editor/debugger/editor_debugger_tree.cpp1
-rw-r--r--editor/debugger/editor_profiler.cpp13
-rw-r--r--editor/debugger/editor_profiler.h3
-rw-r--r--editor/debugger/editor_visual_profiler.cpp20
-rw-r--r--editor/debugger/editor_visual_profiler.h3
-rw-r--r--editor/debugger/script_editor_debugger.cpp112
-rw-r--r--editor/debugger/script_editor_debugger.h18
-rw-r--r--editor/doc_tools.cpp4
-rw-r--r--editor/editor_audio_buses.cpp1
-rw-r--r--editor/editor_audio_buses.h1
-rw-r--r--editor/editor_autoload_settings.cpp49
-rw-r--r--editor/editor_build_profile.h1
-rw-r--r--editor/editor_command_palette.cpp20
-rw-r--r--editor/editor_command_palette.h1
-rw-r--r--editor/editor_data.cpp13
-rw-r--r--editor/editor_data.h2
-rw-r--r--editor/editor_feature_profile.cpp8
-rw-r--r--editor/editor_feature_profile.h2
-rw-r--r--editor/editor_file_dialog.cpp5
-rw-r--r--editor/editor_file_dialog.h13
-rw-r--r--editor/editor_file_system.cpp87
-rw-r--r--editor/editor_fonts.cpp4
-rw-r--r--editor/editor_help.cpp157
-rw-r--r--editor/editor_help.h2
-rw-r--r--editor/editor_help_search.cpp4
-rw-r--r--editor/editor_inspector.cpp145
-rw-r--r--editor/editor_inspector.h21
-rw-r--r--editor/editor_layouts_dialog.cpp12
-rw-r--r--editor/editor_log.cpp2
-rw-r--r--editor/editor_node.cpp286
-rw-r--r--editor/editor_node.h24
-rw-r--r--editor/editor_plugin.cpp25
-rw-r--r--editor/editor_plugin.h41
-rw-r--r--editor/editor_properties.cpp65
-rw-r--r--editor/editor_properties.h32
-rw-r--r--editor/editor_properties_array_dict.cpp13
-rw-r--r--editor/editor_property_name_processor.cpp33
-rw-r--r--editor/editor_property_name_processor.h1
-rw-r--r--editor/editor_quick_open.cpp28
-rw-r--r--editor/editor_quick_open.h6
-rw-r--r--editor/editor_resource_picker.cpp4
-rw-r--r--editor/editor_run.cpp1
-rw-r--r--editor/editor_run.h2
-rw-r--r--editor/editor_sectioned_inspector.cpp4
-rw-r--r--editor/editor_settings.cpp6
-rw-r--r--editor/editor_settings_dialog.cpp6
-rw-r--r--editor/editor_spin_slider.cpp155
-rw-r--r--editor/editor_spin_slider.h2
-rw-r--r--editor/editor_themes.cpp88
-rw-r--r--editor/editor_undo_redo_manager.cpp127
-rw-r--r--editor/editor_undo_redo_manager.h4
-rw-r--r--editor/editor_vcs_interface.cpp4
-rw-r--r--editor/editor_vcs_interface.h4
-rw-r--r--editor/event_listener_line_edit.cpp68
-rw-r--r--editor/event_listener_line_edit.h3
-rw-r--r--editor/export/editor_export_platform.cpp35
-rw-r--r--editor/export/editor_export_plugin.cpp24
-rw-r--r--editor/export/editor_export_plugin.h2
-rw-r--r--editor/export/export_template_manager.cpp1
-rw-r--r--editor/export/project_export.cpp7
-rw-r--r--editor/fbx_importer_manager.cpp158
-rw-r--r--editor/fbx_importer_manager.h66
-rw-r--r--editor/filesystem_dock.cpp37
-rw-r--r--editor/filesystem_dock.h10
-rw-r--r--editor/find_in_files.cpp50
-rw-r--r--editor/history_dock.cpp4
-rw-r--r--editor/icons/ArrowDown.svg2
-rw-r--r--editor/icons/ArrowLeft.svg2
-rw-r--r--editor/icons/ArrowRight.svg2
-rw-r--r--editor/icons/ArrowUp.svg2
-rw-r--r--editor/icons/AutoKey.svg2
-rw-r--r--editor/icons/Blend.svg2
-rw-r--r--editor/icons/Bone.svg2
-rw-r--r--editor/icons/CPUParticles3D.svg2
-rw-r--r--editor/icons/CameraTexture.svg2
-rw-r--r--editor/icons/CanvasItem.svg2
-rw-r--r--editor/icons/CanvasLayer.svg2
-rw-r--r--editor/icons/CharacterBody3D.svg2
-rw-r--r--editor/icons/Clear.svg2
-rw-r--r--editor/icons/CollisionPolygon3D.svg2
-rw-r--r--editor/icons/CollisionShape3D.svg2
-rw-r--r--editor/icons/CompressedTexture2D.svg2
-rw-r--r--editor/icons/CurveTexture.svg2
-rw-r--r--editor/icons/DebugSkipBreakpointsOff.svg3
-rw-r--r--editor/icons/DebugSkipBreakpointsOn.svg3
-rw-r--r--editor/icons/DirectionalLight3D.svg2
-rw-r--r--editor/icons/EditorPlugin.svg2
-rw-r--r--editor/icons/Eraser.svg2
-rw-r--r--editor/icons/FogVolume.svg2
-rw-r--r--editor/icons/GPUParticles3D.svg2
-rw-r--r--editor/icons/GPUParticlesAttractorBox3D.svg2
-rw-r--r--editor/icons/GPUParticlesAttractorSphere3D.svg2
-rw-r--r--editor/icons/GPUParticlesAttractorVectorField3D.svg2
-rw-r--r--editor/icons/GPUParticlesCollisionBox3D.svg2
-rw-r--r--editor/icons/GPUParticlesCollisionSDF3D.svg2
-rw-r--r--editor/icons/GPUParticlesCollisionSphere3D.svg2
-rw-r--r--editor/icons/GradientTexture1D.svg2
-rw-r--r--editor/icons/GuiVisibilityHidden.svg2
-rw-r--r--editor/icons/GuiVisibilityVisible.svg2
-rw-r--r--editor/icons/GuiVisibilityXray.svg2
-rw-r--r--editor/icons/HTTPRequest.svg2
-rw-r--r--editor/icons/History.svg2
-rw-r--r--editor/icons/Hsize.svg2
-rw-r--r--editor/icons/Image.svg2
-rw-r--r--editor/icons/ImageTexture.svg2
-rw-r--r--editor/icons/JoyAxis.svg2
-rw-r--r--editor/icons/JoyButton.svg2
-rw-r--r--editor/icons/Joypad.svg2
-rw-r--r--editor/icons/Key.svg2
-rw-r--r--editor/icons/KeyNext.svg2
-rw-r--r--editor/icons/KeyPosition.svg2
-rw-r--r--editor/icons/KeyRotation.svg2
-rw-r--r--editor/icons/KeyScale.svg2
-rw-r--r--editor/icons/LightmapProbe.svg2
-rw-r--r--editor/icons/ListSelect.svg2
-rw-r--r--editor/icons/Loop.svg2
-rw-r--r--editor/icons/Marker3D.svg2
-rw-r--r--editor/icons/MeshInstance3D.svg2
-rw-r--r--editor/icons/MeshTexture.svg2
-rw-r--r--editor/icons/MirrorX.svg2
-rw-r--r--editor/icons/MirrorY.svg2
-rw-r--r--editor/icons/MoveDown.svg2
-rw-r--r--editor/icons/MoveLeft.svg2
-rw-r--r--editor/icons/MoveRight.svg2
-rw-r--r--editor/icons/MoveUp.svg2
-rw-r--r--editor/icons/MultiMeshInstance3D.svg2
-rw-r--r--editor/icons/Navigation3D.svg2
-rw-r--r--editor/icons/NavigationLink2D.svg4
-rw-r--r--editor/icons/NavigationLink3D.svg4
-rw-r--r--editor/icons/NavigationRegion3D.svg2
-rw-r--r--editor/icons/Node3D.svg2
-rw-r--r--editor/icons/OccluderInstance3D.svg2
-rw-r--r--editor/icons/OmniLight3D.svg2
-rw-r--r--editor/icons/OneWayTile.svg1
-rw-r--r--editor/icons/ParallaxBackground.svg2
-rw-r--r--editor/icons/Path3D.svg2
-rw-r--r--editor/icons/PathFollow3D.svg2
-rw-r--r--editor/icons/Progress1.svg2
-rw-r--r--editor/icons/Progress2.svg2
-rw-r--r--editor/icons/Progress3.svg2
-rw-r--r--editor/icons/Progress4.svg2
-rw-r--r--editor/icons/Progress5.svg2
-rw-r--r--editor/icons/Progress6.svg2
-rw-r--r--editor/icons/Progress7.svg2
-rw-r--r--editor/icons/Progress8.svg2
-rw-r--r--editor/icons/ProxyTexture.svg2
-rw-r--r--editor/icons/Quad.svg2
-rw-r--r--editor/icons/RayCast3D.svg2
-rw-r--r--editor/icons/ReflectionProbe.svg2
-rw-r--r--editor/icons/Reload.svg2
-rw-r--r--editor/icons/ReloadSmall.svg2
-rw-r--r--editor/icons/Remove.svg2
-rw-r--r--editor/icons/RigidBody3D.svg2
-rw-r--r--editor/icons/RotateLeft.svg2
-rw-r--r--editor/icons/RotateRight.svg2
-rw-r--r--editor/icons/Search.svg2
-rw-r--r--editor/icons/Shortcut.svg2
-rw-r--r--editor/icons/Skeleton3D.svg2
-rw-r--r--editor/icons/SoftBody3D.svg2
-rw-r--r--editor/icons/SpotLight3D.svg2
-rw-r--r--editor/icons/StaticBody3D.svg2
-rw-r--r--editor/icons/SubViewport.svg2
-rw-r--r--editor/icons/Texture2DArray.svg2
-rw-r--r--editor/icons/TileSelection.svg57
-rw-r--r--editor/icons/ToolMove.svg2
-rw-r--r--editor/icons/ToolPan.svg2
-rw-r--r--editor/icons/ToolRotate.svg2
-rw-r--r--editor/icons/ToolScale.svg2
-rw-r--r--editor/icons/TrackTrigger.svg1
-rw-r--r--editor/icons/TripleBar.svg2
-rw-r--r--editor/icons/VehicleBody3D.svg2
-rw-r--r--editor/icons/VehicleWheel3D.svg2
-rw-r--r--editor/icons/Viewport.svg2
-rw-r--r--editor/icons/ViewportSpeed.svg2
-rw-r--r--editor/icons/ViewportTexture.svg2
-rw-r--r--editor/icons/VisibleOnScreenEnabler3D.svg2
-rw-r--r--editor/icons/VisibleOnScreenNotifier3D.svg2
-rw-r--r--editor/icons/VoxelGI.svg2
-rw-r--r--editor/icons/WorldEnvironment.svg2
-rw-r--r--editor/icons/Zoom.svg2
-rw-r--r--editor/import/audio_stream_import_settings.cpp45
-rw-r--r--editor/import/audio_stream_import_settings.h3
-rw-r--r--editor/import/dynamic_font_import_settings.cpp197
-rw-r--r--editor/import/dynamic_font_import_settings.h16
-rw-r--r--editor/import/editor_import_collada.cpp6
-rw-r--r--editor/import/editor_import_collada.h2
-rw-r--r--editor/import/post_import_plugin_skeleton_renamer.cpp208
-rw-r--r--editor/import/post_import_plugin_skeleton_renamer.h2
-rw-r--r--editor/import/resource_importer_bmfont.cpp3
-rw-r--r--editor/import/resource_importer_dynamic_font.cpp7
-rw-r--r--editor/import/resource_importer_imagefont.cpp52
-rw-r--r--editor/import/resource_importer_obj.cpp2
-rw-r--r--editor/import/resource_importer_obj.h2
-rw-r--r--editor/import/resource_importer_scene.cpp30
-rw-r--r--editor/import/resource_importer_scene.h10
-rw-r--r--editor/import/resource_importer_wav.cpp10
-rw-r--r--editor/import/scene_import_settings.cpp7
-rw-r--r--editor/input_event_configuration_dialog.cpp85
-rw-r--r--editor/input_event_configuration_dialog.h2
-rw-r--r--editor/inspector_dock.cpp6
-rw-r--r--editor/plugin_config_dialog.cpp9
-rw-r--r--editor/plugins/abstract_polygon_2d_editor.h1
-rw-r--r--editor/plugins/animation_blend_space_1d_editor.cpp46
-rw-r--r--editor/plugins/animation_blend_space_1d_editor.h5
-rw-r--r--editor/plugins/animation_blend_space_2d_editor.cpp51
-rw-r--r--editor/plugins/animation_blend_space_2d_editor.h6
-rw-r--r--editor/plugins/animation_blend_tree_editor_plugin.cpp85
-rw-r--r--editor/plugins/animation_blend_tree_editor_plugin.h12
-rw-r--r--editor/plugins/animation_library_editor.cpp25
-rw-r--r--editor/plugins/animation_player_editor_plugin.cpp97
-rw-r--r--editor/plugins/animation_player_editor_plugin.h30
-rw-r--r--editor/plugins/animation_state_machine_editor.cpp136
-rw-r--r--editor/plugins/animation_state_machine_editor.h19
-rw-r--r--editor/plugins/animation_tree_editor_plugin.cpp25
-rw-r--r--editor/plugins/animation_tree_editor_plugin.h6
-rw-r--r--editor/plugins/asset_library_editor_plugin.cpp29
-rw-r--r--editor/plugins/asset_library_editor_plugin.h3
-rw-r--r--editor/plugins/audio_stream_editor_plugin.cpp280
-rw-r--r--editor/plugins/audio_stream_editor_plugin.h93
-rw-r--r--editor/plugins/audio_stream_randomizer_editor_plugin.cpp4
-rw-r--r--editor/plugins/bit_map_editor_plugin.cpp2
-rw-r--r--editor/plugins/bit_map_editor_plugin.h3
-rw-r--r--editor/plugins/bone_map_editor_plugin.cpp10
-rw-r--r--editor/plugins/bone_map_editor_plugin.h3
-rw-r--r--editor/plugins/canvas_item_editor_plugin.cpp45
-rw-r--r--editor/plugins/canvas_item_editor_plugin.h26
-rw-r--r--editor/plugins/cast_2d_editor_plugin.cpp5
-rw-r--r--editor/plugins/cast_2d_editor_plugin.h4
-rw-r--r--editor/plugins/collision_shape_2d_editor_plugin.cpp3
-rw-r--r--editor/plugins/collision_shape_2d_editor_plugin.h2
-rw-r--r--editor/plugins/control_editor_plugin.cpp7
-rw-r--r--editor/plugins/control_editor_plugin.h4
-rw-r--r--editor/plugins/cpu_particles_2d_editor_plugin.cpp6
-rw-r--r--editor/plugins/cpu_particles_2d_editor_plugin.h7
-rw-r--r--editor/plugins/curve_editor_plugin.h1
-rw-r--r--editor/plugins/debugger_editor_plugin.cpp16
-rw-r--r--editor/plugins/debugger_editor_plugin.h1
-rw-r--r--editor/plugins/editor_debugger_plugin.cpp159
-rw-r--r--editor/plugins/editor_debugger_plugin.h51
-rw-r--r--editor/plugins/editor_preview_plugins.h20
-rw-r--r--editor/plugins/font_config_plugin.cpp5
-rw-r--r--editor/plugins/gdextension_export_plugin.h99
-rw-r--r--editor/plugins/gpu_particles_2d_editor_plugin.cpp3
-rw-r--r--editor/plugins/gpu_particles_2d_editor_plugin.h6
-rw-r--r--editor/plugins/gpu_particles_3d_editor_plugin.cpp2
-rw-r--r--editor/plugins/gpu_particles_3d_editor_plugin.h4
-rw-r--r--editor/plugins/gpu_particles_collision_sdf_editor_plugin.h1
-rw-r--r--editor/plugins/gradient_editor.cpp46
-rw-r--r--editor/plugins/gradient_editor.h4
-rw-r--r--editor/plugins/gradient_editor_plugin.h1
-rw-r--r--editor/plugins/gradient_texture_2d_editor_plugin.cpp6
-rw-r--r--editor/plugins/gradient_texture_2d_editor_plugin.h5
-rw-r--r--editor/plugins/material_editor_plugin.cpp18
-rw-r--r--editor/plugins/material_editor_plugin.h5
-rw-r--r--editor/plugins/mesh_editor_plugin.cpp10
-rw-r--r--editor/plugins/mesh_editor_plugin.h4
-rw-r--r--editor/plugins/mesh_instance_3d_editor_plugin.cpp32
-rw-r--r--editor/plugins/mesh_instance_3d_editor_plugin.h4
-rw-r--r--editor/plugins/mesh_library_editor_plugin.cpp18
-rw-r--r--editor/plugins/multimesh_editor_plugin.cpp2
-rw-r--r--editor/plugins/multimesh_editor_plugin.h4
-rw-r--r--editor/plugins/navigation_link_2d_editor_plugin.cpp5
-rw-r--r--editor/plugins/navigation_link_2d_editor_plugin.h4
-rw-r--r--editor/plugins/node_3d_editor_gizmos.cpp78
-rw-r--r--editor/plugins/node_3d_editor_gizmos.h3
-rw-r--r--editor/plugins/node_3d_editor_plugin.cpp352
-rw-r--r--editor/plugins/node_3d_editor_plugin.h72
-rw-r--r--editor/plugins/packed_scene_editor_plugin.cpp81
-rw-r--r--editor/plugins/packed_scene_editor_plugin.h68
-rw-r--r--editor/plugins/path_2d_editor_plugin.cpp7
-rw-r--r--editor/plugins/path_2d_editor_plugin.h5
-rw-r--r--editor/plugins/path_3d_editor_plugin.cpp61
-rw-r--r--editor/plugins/path_3d_editor_plugin.h2
-rw-r--r--editor/plugins/physical_bone_3d_editor_plugin.cpp1
-rw-r--r--editor/plugins/polygon_2d_editor_plugin.cpp4
-rw-r--r--editor/plugins/polygon_2d_editor_plugin.h6
-rw-r--r--editor/plugins/polygon_3d_editor_plugin.cpp6
-rw-r--r--editor/plugins/polygon_3d_editor_plugin.h4
-rw-r--r--editor/plugins/resource_preloader_editor_plugin.cpp10
-rw-r--r--editor/plugins/resource_preloader_editor_plugin.h6
-rw-r--r--editor/plugins/root_motion_editor_plugin.cpp115
-rw-r--r--editor/plugins/root_motion_editor_plugin.h5
-rw-r--r--editor/plugins/script_editor_plugin.cpp2
-rw-r--r--editor/plugins/script_editor_plugin.h25
-rw-r--r--editor/plugins/script_text_editor.cpp104
-rw-r--r--editor/plugins/script_text_editor.h6
-rw-r--r--editor/plugins/shader_editor_plugin.cpp3
-rw-r--r--editor/plugins/shader_editor_plugin.h2
-rw-r--r--editor/plugins/shader_file_editor_plugin.cpp3
-rw-r--r--editor/plugins/skeleton_2d_editor_plugin.cpp1
-rw-r--r--editor/plugins/skeleton_2d_editor_plugin.h3
-rw-r--r--editor/plugins/skeleton_3d_editor_plugin.cpp30
-rw-r--r--editor/plugins/skeleton_3d_editor_plugin.h6
-rw-r--r--editor/plugins/sprite_2d_editor_plugin.cpp1
-rw-r--r--editor/plugins/sprite_2d_editor_plugin.h4
-rw-r--r--editor/plugins/sprite_frames_editor_plugin.cpp24
-rw-r--r--editor/plugins/sprite_frames_editor_plugin.h5
-rw-r--r--editor/plugins/style_box_editor_plugin.cpp7
-rw-r--r--editor/plugins/style_box_editor_plugin.h2
-rw-r--r--editor/plugins/text_editor.cpp5
-rw-r--r--editor/plugins/text_editor.h2
-rw-r--r--editor/plugins/texture_3d_editor_plugin.cpp2
-rw-r--r--editor/plugins/texture_3d_editor_plugin.h1
-rw-r--r--editor/plugins/texture_editor_plugin.cpp2
-rw-r--r--editor/plugins/texture_editor_plugin.h4
-rw-r--r--editor/plugins/texture_layered_editor_plugin.cpp2
-rw-r--r--editor/plugins/texture_layered_editor_plugin.h1
-rw-r--r--editor/plugins/texture_region_editor_plugin.cpp4
-rw-r--r--editor/plugins/texture_region_editor_plugin.h6
-rw-r--r--editor/plugins/theme_editor_plugin.cpp2
-rw-r--r--editor/plugins/theme_editor_plugin.h2
-rw-r--r--editor/plugins/theme_editor_preview.cpp3
-rw-r--r--editor/plugins/tiles/atlas_merging_dialog.cpp6
-rw-r--r--editor/plugins/tiles/atlas_merging_dialog.h3
-rw-r--r--editor/plugins/tiles/tile_data_editors.cpp91
-rw-r--r--editor/plugins/tiles/tile_data_editors.h14
-rw-r--r--editor/plugins/tiles/tile_map_editor.cpp50
-rw-r--r--editor/plugins/tiles/tile_map_editor.h7
-rw-r--r--editor/plugins/tiles/tile_proxies_manager_dialog.cpp21
-rw-r--r--editor/plugins/tiles/tile_proxies_manager_dialog.h6
-rw-r--r--editor/plugins/tiles/tile_set_atlas_source_editor.cpp294
-rw-r--r--editor/plugins/tiles/tile_set_atlas_source_editor.h15
-rw-r--r--editor/plugins/tiles/tile_set_editor.cpp20
-rw-r--r--editor/plugins/tiles/tile_set_editor.h4
-rw-r--r--editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp1
-rw-r--r--editor/plugins/tiles/tiles_editor_plugin.cpp16
-rw-r--r--editor/plugins/tiles/tiles_editor_plugin.h4
-rw-r--r--editor/plugins/version_control_editor_plugin.cpp112
-rw-r--r--editor/plugins/version_control_editor_plugin.h8
-rw-r--r--editor/plugins/visual_shader_editor_plugin.cpp371
-rw-r--r--editor/plugins/visual_shader_editor_plugin.h24
-rw-r--r--editor/plugins/voxel_gi_editor_plugin.h1
-rw-r--r--editor/project_converter_3_to_4.cpp23
-rw-r--r--editor/project_manager.cpp135
-rw-r--r--editor/project_manager.h1
-rw-r--r--editor/project_settings_editor.cpp18
-rw-r--r--editor/project_settings_editor.h3
-rw-r--r--editor/register_editor_types.cpp224
-rw-r--r--editor/register_editor_types.h37
-rw-r--r--editor/rename_dialog.cpp7
-rw-r--r--editor/rename_dialog.h6
-rw-r--r--editor/reparent_dialog.cpp1
-rw-r--r--editor/scene_create_dialog.cpp2
-rw-r--r--editor/scene_tree_dock.cpp426
-rw-r--r--editor/scene_tree_dock.h22
-rw-r--r--editor/scene_tree_editor.cpp14
-rw-r--r--editor/scene_tree_editor.h2
-rw-r--r--editor/script_create_dialog.cpp38
-rw-r--r--editor/script_create_dialog.h1
-rw-r--r--editor/shader_globals_editor.cpp45
-rw-r--r--editor/translations/af.po24
-rw-r--r--editor/translations/ar.po650
-rw-r--r--editor/translations/az.po21
-rw-r--r--editor/translations/bg.po87
-rw-r--r--editor/translations/bn.po23
-rw-r--r--editor/translations/br.po21
-rw-r--r--editor/translations/ca.po25
-rw-r--r--editor/translations/cs.po591
-rw-r--r--editor/translations/da.po33
-rw-r--r--editor/translations/de.po37
-rw-r--r--editor/translations/editor.pot20
-rw-r--r--editor/translations/el.po26
-rw-r--r--editor/translations/en_Shaw.po21
-rw-r--r--editor/translations/eo.po25
-rw-r--r--editor/translations/es.po892
-rw-r--r--editor/translations/es_AR.po112
-rw-r--r--editor/translations/et.po21
-rw-r--r--editor/translations/eu.po33
-rwxr-xr-xeditor/translations/extract.py26
-rw-r--r--editor/translations/fa.po38
-rw-r--r--editor/translations/fi.po300
-rw-r--r--editor/translations/fil.po123
-rw-r--r--editor/translations/fr.po499
-rw-r--r--editor/translations/ga.po21
-rw-r--r--editor/translations/gl.po25
-rw-r--r--editor/translations/he.po350
-rw-r--r--editor/translations/hi.po335
-rw-r--r--editor/translations/hr.po21
-rw-r--r--editor/translations/hu.po24
-rw-r--r--editor/translations/id.po26
-rw-r--r--editor/translations/ig.po20
-rw-r--r--editor/translations/is.po21
-rw-r--r--editor/translations/it.po1048
-rw-r--r--editor/translations/ja.po452
-rw-r--r--editor/translations/ka.po21
-rw-r--r--editor/translations/km.po20
-rw-r--r--editor/translations/ko.po1571
-rw-r--r--editor/translations/lt.po21
-rw-r--r--editor/translations/lv.po21
-rw-r--r--editor/translations/mk.po43
-rw-r--r--editor/translations/ml.po20
-rw-r--r--editor/translations/mr.po20
-rw-r--r--editor/translations/ms.po21
-rw-r--r--editor/translations/nb.po41
-rw-r--r--editor/translations/nl.po25
-rw-r--r--editor/translations/pl.po415
-rw-r--r--editor/translations/pr.po21
-rw-r--r--editor/translations/pt.po2577
-rw-r--r--editor/translations/pt_BR.po484
-rw-r--r--editor/translations/ro.po219
-rw-r--r--editor/translations/ru.po72
-rw-r--r--editor/translations/si.po21
-rw-r--r--editor/translations/sk.po21
-rw-r--r--editor/translations/sl.po24
-rw-r--r--editor/translations/sq.po21
-rw-r--r--editor/translations/sr_Cyrl.po23
-rw-r--r--editor/translations/sr_Latn.po21
-rw-r--r--editor/translations/sv.po36
-rw-r--r--editor/translations/te.po21
-rw-r--r--editor/translations/th.po52
-rw-r--r--editor/translations/tl.po21
-rw-r--r--editor/translations/tr.po114
-rw-r--r--editor/translations/uk.po32
-rw-r--r--editor/translations/ur_PK.po21
-rw-r--r--editor/translations/vi.po38
-rw-r--r--editor/translations/zh_CN.po75
-rw-r--r--editor/translations/zh_HK.po24
-rw-r--r--editor/translations/zh_TW.po64
-rw-r--r--gles3_builders.py49
-rw-r--r--main/main.cpp284
-rw-r--r--methods.py6
-rw-r--r--misc/dist/html/full-size.html2
-rw-r--r--misc/dist/icon_console.svg120
-rw-r--r--misc/dist/ios_xcode/godot_ios.xcodeproj/project.pbxproj2
-rw-r--r--misc/dist/linux/godot.62
-rw-r--r--misc/dist/shell/_godot.zsh-completion8
-rw-r--r--misc/dist/shell/godot.bash-completion9
-rw-r--r--misc/dist/shell/godot.fish7
-rwxr-xr-xmisc/scripts/compare_extension_api.py11
-rwxr-xr-xmisc/scripts/file_format.sh4
-rw-r--r--modules/basis_universal/register_types.cpp1
-rw-r--r--modules/etcpak/image_compress_etcpak.cpp3
-rw-r--r--modules/gdscript/doc_classes/@GDScript.xml3
-rw-r--r--modules/gdscript/editor/gdscript_highlighter.cpp2
-rw-r--r--modules/gdscript/gdscript.cpp497
-rw-r--r--modules/gdscript/gdscript.h29
-rw-r--r--modules/gdscript/gdscript_analyzer.cpp1018
-rw-r--r--modules/gdscript/gdscript_analyzer.h23
-rw-r--r--modules/gdscript/gdscript_byte_codegen.cpp2
-rw-r--r--modules/gdscript/gdscript_cache.cpp240
-rw-r--r--modules/gdscript/gdscript_cache.h26
-rw-r--r--modules/gdscript/gdscript_codegen.h2
-rw-r--r--modules/gdscript/gdscript_compiler.cpp466
-rw-r--r--modules/gdscript/gdscript_compiler.h10
-rw-r--r--modules/gdscript/gdscript_editor.cpp139
-rw-r--r--modules/gdscript/gdscript_function.cpp7
-rw-r--r--modules/gdscript/gdscript_function.h1
-rw-r--r--modules/gdscript/gdscript_parser.cpp94
-rw-r--r--modules/gdscript/gdscript_parser.h89
-rw-r--r--modules/gdscript/gdscript_utility_functions.cpp5
-rw-r--r--modules/gdscript/gdscript_vm.cpp2
-rw-r--r--modules/gdscript/gdscript_warning.cpp6
-rw-r--r--modules/gdscript/language_server/gdscript_extend_parser.cpp3
-rw-r--r--modules/gdscript/language_server/gdscript_language_protocol.cpp1
-rw-r--r--modules/gdscript/language_server/godot_lsp.h2
-rw-r--r--modules/gdscript/tests/gdscript_test_runner.cpp50
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/assign_signal.gd4
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/assign_signal.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/class_name_shadows_builtin_type.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/constructor_call_type.gd10
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/constructor_call_type.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/cyclic_inheritance.gd8
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/cyclic_inheritance.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/cyclic_ref_const.gd5
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/cyclic_ref_const.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/cyclic_ref_enum.gd5
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/cyclic_ref_enum.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/cyclic_ref_enum_value.gd5
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/cyclic_ref_enum_value.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/cyclic_ref_external.gd6
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/cyclic_ref_external.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/cyclic_ref_external_a.notest.gd3
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/cyclic_ref_func.gd9
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/cyclic_ref_func.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/cyclic_ref_override.gd12
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/cyclic_ref_override.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/cyclic_ref_var.gd5
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/cyclic_ref_var.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/dictionary_string_stringname_equivalent.gd9
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/dictionary_string_stringname_equivalent.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_parameter_count_less.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_parameter_count_more.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_parameter_default_values.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_parameter_type.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_return_type.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/outer_class_lookup.gd12
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/outer_class_lookup.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/overload_script_variable.gd6
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/overload_script_variable.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/variable_overloads_superclass_function.gd9
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/variable_overloads_superclass_function.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/array_string_stringname_equivalent.gd15
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/array_string_stringname_equivalent.out5
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/base_outer_resolution.gd14
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/base_outer_resolution.out7
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/base_outer_resolution_a.notest.gd2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/base_outer_resolution_b.notest.gd0
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/base_outer_resolution_base.notest.gd4
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/base_outer_resolution_c.notest.gd3
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/base_outer_resolution_extend.notest.gd23
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/cast_non_null.gd5
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/cast_non_null.out3
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/enum_as_const.gd29
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/enum_as_const.out17
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/external_enum_as_constant.gd6
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/external_enum_as_constant.out3
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/external_enum_as_constant_external.notest.gd4
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/external_inner_base.gd4
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/external_inner_base.out3
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/external_inner_class_as_constant.gd7
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/external_inner_class_as_constant.out (renamed from modules/gdscript/tests/scripts/analyzer/features/gdscript_to_preload.out)1
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/external_inner_class_as_constant_external.notest.gd2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/gdscript_to_preload.notest.gd (renamed from modules/gdscript/tests/scripts/analyzer/features/gdscript_to_preload.gd)3
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/inferred_return_type.gd9
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/inferred_return_type.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/inner_base.gd18
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/inner_base.out4
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/out_of_order.gd51
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/out_of_order.out15
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/out_of_order_external.gd39
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/out_of_order_external.out15
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/out_of_order_external_a.notest.gd12
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/preload_constant_types_are_inferred.gd2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/preload_cyclic_reference.gd4
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/preload_cyclic_reference.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/preload_cyclic_reference_a.notest.gd12
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/preload_cyclic_reference_b.notest.gd10
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/use_preload_script_as_type.gd2
-rw-r--r--modules/gdscript/tests/scripts/parser/warnings/return_value_discarded.out2
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/array_string_stringname_equivalent.gd35
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/array_string_stringname_equivalent.out11
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/dictionary_string_stringname_equivalent.gd17
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/dictionary_string_stringname_equivalent.out6
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/match_string_stringname_equivalent.gd14
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/match_string_stringname_equivalent.out3
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/parameter_shadowing.gd25
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/parameter_shadowing.out17
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/string_stringname_equivalent.gd11
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/string_stringname_equivalent.out8
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/typed_assignment.gd9
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/typed_assignment.out12
-rw-r--r--modules/gltf/doc_classes/GLTFDocument.xml37
-rw-r--r--modules/gltf/doc_classes/GLTFDocumentExtension.xml51
-rw-r--r--modules/gltf/doc_classes/GLTFState.xml4
-rw-r--r--modules/gltf/editor/editor_scene_exporter_gltf_plugin.cpp10
-rw-r--r--modules/gltf/editor/editor_scene_exporter_gltf_plugin.h2
-rw-r--r--modules/gltf/editor/editor_scene_importer_blend.cpp10
-rw-r--r--modules/gltf/editor/editor_scene_importer_blend.h2
-rw-r--r--modules/gltf/editor/editor_scene_importer_fbx.cpp36
-rw-r--r--modules/gltf/editor/editor_scene_importer_fbx.h13
-rw-r--r--modules/gltf/editor/editor_scene_importer_gltf.cpp14
-rw-r--r--modules/gltf/editor/editor_scene_importer_gltf.h5
-rw-r--r--modules/gltf/extensions/gltf_document_extension.cpp (renamed from modules/gltf/gltf_document_extension.cpp)70
-rw-r--r--modules/gltf/extensions/gltf_document_extension.h (renamed from modules/gltf/gltf_document_extension.h)26
-rw-r--r--modules/gltf/extensions/gltf_document_extension_convert_importer_mesh.cpp (renamed from modules/gltf/gltf_document_extension_convert_importer_mesh.cpp)4
-rw-r--r--modules/gltf/extensions/gltf_document_extension_convert_importer_mesh.h (renamed from modules/gltf/gltf_document_extension_convert_importer_mesh.h)4
-rw-r--r--modules/gltf/extensions/gltf_light.cpp2
-rw-r--r--modules/gltf/extensions/gltf_light.h4
-rw-r--r--modules/gltf/extensions/gltf_spec_gloss.cpp2
-rw-r--r--modules/gltf/extensions/gltf_spec_gloss.h3
-rw-r--r--modules/gltf/gltf_defines.h3
-rw-r--r--modules/gltf/gltf_document.cpp2652
-rw-r--r--modules/gltf/gltf_document.h336
-rw-r--r--modules/gltf/gltf_state.cpp6
-rw-r--r--modules/gltf/gltf_state.h28
-rw-r--r--modules/gltf/register_types.cpp47
-rw-r--r--modules/gltf/structures/gltf_accessor.h3
-rw-r--r--modules/gltf/structures/gltf_animation.h2
-rw-r--r--modules/gltf/structures/gltf_buffer_view.cpp2
-rw-r--r--modules/gltf/structures/gltf_camera.cpp2
-rw-r--r--modules/gltf/structures/gltf_camera.h5
-rw-r--r--modules/gltf/structures/gltf_mesh.h4
-rw-r--r--modules/gltf/structures/gltf_texture_sampler.h1
-rw-r--r--modules/gridmap/doc_classes/GridMap.xml27
-rw-r--r--modules/gridmap/editor/grid_map_editor_plugin.cpp9
-rw-r--r--modules/gridmap/editor/grid_map_editor_plugin.h5
-rw-r--r--modules/gridmap/grid_map.cpp134
-rw-r--r--modules/gridmap/grid_map.h19
-rw-r--r--modules/lightmapper_rd/register_types.cpp1
-rw-r--r--modules/mbedtls/packet_peer_mbed_dtls.cpp7
-rw-r--r--modules/mono/README.md6
-rwxr-xr-xmodules/mono/build_scripts/build_assemblies.py18
-rw-r--r--modules/mono/csharp_script.cpp31
-rw-r--r--modules/mono/csharp_script.h4
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Sdk/Sdk.props3
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/ExportedFields.cs7
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/ExportedProperties.cs91
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/MoreExportedFields.cs19
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Common.cs4
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ExtensionMethods.cs79
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotEnums.cs77
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotMemberData.cs14
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MarshalType.cs2
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MarshalUtils.cs393
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MethodInfo.cs2
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/PropertyInfo.cs2
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptMethodsGenerator.cs24
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPathAttributeGenerator.cs13
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertiesGenerator.cs38
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertyDefValGenerator.cs100
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSerializationGenerator.cs12
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSignalsGenerator.cs28
-rw-r--r--modules/mono/editor/GodotTools/GodotTools.IdeMessaging/Utils/SemaphoreExtensions.cs2
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Export/AotBuilder.cs2
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs16
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Internals/Globals.cs28
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Internals/GodotSharpDirs.cs10
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/PlaySettings.cs2
-rw-r--r--modules/mono/editor/bindings_generator.cpp81
-rw-r--r--modules/mono/editor/bindings_generator.h9
-rw-r--r--modules/mono/glue/GodotSharp/Godot.SourceGenerators.Internal/CallbacksInfo.cs2
-rw-r--r--modules/mono/glue/GodotSharp/Godot.SourceGenerators.Internal/Common.cs4
-rw-r--r--modules/mono/glue/GodotSharp/Godot.SourceGenerators.Internal/ExtensionMethods.cs28
-rw-r--r--modules/mono/glue/GodotSharp/Godot.SourceGenerators.Internal/UnmanagedCallbacksGenerator.cs26
-rw-r--r--modules/mono/glue/GodotSharp/GodotPlugins/Main.cs32
-rw-r--r--modules/mono/glue/GodotSharp/GodotPlugins/PluginLoadContext.cs4
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp.sln.DotSettings2
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/AABB.cs62
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Array.cs69
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/AssemblyHasScriptsAttribute.cs21
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ExportAttribute.cs21
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ExportCategoryAttribute.cs7
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ExportGroupAttribute.cs17
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ExportSubgroupAttribute.cs17
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/RPCAttribute.cs6
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ScriptPathAttribute.cs3
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs77
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/MethodInfo.cs2
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/PropertyInfo.cs2
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs73
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Callable.cs18
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Callable.generics.cs200
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs225
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/DelegateUtils.cs295
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Dictionary.cs105
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Mathf.cs23
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/Marshaling.cs539
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.cs17
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantConversionCallbacks.cs1057
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantSpanHelpers.cs33
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantUtils.cs102
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantUtils.generic.cs414
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Plane.cs38
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Projection.cs566
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Quaternion.cs46
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/RID.cs4
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2.cs46
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2i.cs44
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Signal.cs (renamed from modules/mono/glue/GodotSharp/GodotSharp/Core/SignalInfo.cs)11
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs720
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs60
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs32
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Variant.cs (renamed from modules/mono/glue/GodotSharp/GodotSharp/Variant.cs)88
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs126
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs52
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs122
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs38
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4.cs60
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4i.cs28
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj7
-rw-r--r--modules/mono/glue/runtime_interop.cpp38
-rw-r--r--modules/multiplayer/doc_classes/MultiplayerSynchronizer.xml2
-rw-r--r--modules/multiplayer/editor/editor_network_profiler.cpp (renamed from editor/debugger/editor_network_profiler.cpp)200
-rw-r--r--modules/multiplayer/editor/editor_network_profiler.h (renamed from editor/debugger/editor_network_profiler.h)41
-rw-r--r--modules/multiplayer/editor/multiplayer_editor_plugin.cpp175
-rw-r--r--modules/multiplayer/editor/multiplayer_editor_plugin.h85
-rw-r--r--modules/multiplayer/editor/replication_editor.cpp (renamed from modules/multiplayer/editor/replication_editor_plugin.cpp)71
-rw-r--r--modules/multiplayer/editor/replication_editor.h (renamed from modules/multiplayer/editor/replication_editor_plugin.h)43
-rw-r--r--modules/multiplayer/multiplayer_debugger.cpp333
-rw-r--r--modules/multiplayer/multiplayer_debugger.h134
-rw-r--r--modules/multiplayer/register_types.cpp10
-rw-r--r--modules/multiplayer/scene_cache_interface.cpp8
-rw-r--r--modules/multiplayer/scene_multiplayer.cpp46
-rw-r--r--modules/multiplayer/scene_multiplayer.h39
-rw-r--r--modules/multiplayer/scene_replication_interface.cpp67
-rw-r--r--modules/multiplayer/scene_replication_interface.h6
-rw-r--r--modules/multiplayer/scene_rpc_interface.cpp79
-rw-r--r--modules/multiplayer/scene_rpc_interface.h5
-rw-r--r--modules/navigation/editor/navigation_mesh_editor_plugin.h2
-rw-r--r--modules/navigation/godot_navigation_server.cpp80
-rw-r--r--modules/navigation/godot_navigation_server.h11
-rw-r--r--modules/navigation/nav_base.h8
-rw-r--r--modules/navigation/nav_link.h8
-rw-r--r--modules/navigation/nav_map.cpp85
-rw-r--r--modules/navigation/nav_map.h4
-rw-r--r--modules/navigation/nav_region.h4
-rw-r--r--modules/navigation/navigation_mesh_generator.cpp102
-rw-r--r--modules/navigation/navigation_mesh_generator.h8
-rw-r--r--modules/noise/editor/noise_editor_plugin.cpp3
-rw-r--r--modules/openxr/action_map/openxr_action.cpp8
-rw-r--r--modules/openxr/action_map/openxr_action_map.cpp34
-rw-r--r--modules/openxr/action_map/openxr_action_map.h4
-rw-r--r--modules/openxr/action_map/openxr_action_set.cpp10
-rw-r--r--modules/openxr/action_map/openxr_defs.cpp671
-rw-r--r--modules/openxr/action_map/openxr_defs.h124
-rw-r--r--modules/openxr/action_map/openxr_interaction_profile.cpp26
-rw-r--r--modules/openxr/action_map/openxr_interaction_profile.h3
-rw-r--r--modules/openxr/action_map/openxr_interaction_profile_meta_data.cpp713
-rw-r--r--modules/openxr/action_map/openxr_interaction_profile_meta_data.h118
-rw-r--r--modules/openxr/config.py2
-rw-r--r--modules/openxr/editor/openxr_action_editor.cpp87
-rw-r--r--modules/openxr/editor/openxr_action_editor.h9
-rw-r--r--modules/openxr/editor/openxr_action_map_editor.cpp203
-rw-r--r--modules/openxr/editor/openxr_action_map_editor.h17
-rw-r--r--modules/openxr/editor/openxr_action_set_editor.cpp130
-rw-r--r--modules/openxr/editor/openxr_action_set_editor.h11
-rw-r--r--modules/openxr/editor/openxr_interaction_profile_editor.cpp91
-rw-r--r--modules/openxr/editor/openxr_interaction_profile_editor.h15
-rw-r--r--modules/openxr/editor/openxr_select_action_dialog.cpp4
-rw-r--r--modules/openxr/editor/openxr_select_interaction_profile_dialog.cpp8
-rw-r--r--modules/openxr/editor/openxr_select_interaction_profile_dialog.h2
-rw-r--r--modules/openxr/extensions/openxr_android_extension.cpp30
-rw-r--r--modules/openxr/extensions/openxr_android_extension.h4
-rw-r--r--modules/openxr/extensions/openxr_extension_wrapper.h6
-rw-r--r--modules/openxr/extensions/openxr_htc_vive_tracker_extension.cpp37
-rw-r--r--modules/openxr/extensions/openxr_htc_vive_tracker_extension.h1
-rw-r--r--modules/openxr/extensions/openxr_opengl_extension.cpp154
-rw-r--r--modules/openxr/extensions/openxr_opengl_extension.h5
-rw-r--r--modules/openxr/extensions/openxr_palm_pose_extension.cpp13
-rw-r--r--modules/openxr/extensions/openxr_palm_pose_extension.h2
-rw-r--r--modules/openxr/openxr_api.cpp142
-rw-r--r--modules/openxr/openxr_api.h18
-rw-r--r--modules/openxr/openxr_interface.cpp10
-rw-r--r--modules/openxr/register_types.cpp22
-rw-r--r--modules/raycast/SCsub17
-rw-r--r--modules/raycast/config.py12
-rw-r--r--modules/raycast/godot_update_embree.py24
-rw-r--r--modules/regex/regex.cpp3
-rw-r--r--modules/register_module_types.h10
-rw-r--r--modules/svg/image_loader_svg.cpp62
-rw-r--r--modules/svg/image_loader_svg.h3
-rw-r--r--modules/text_server_adv/SCsub6
-rw-r--r--modules/text_server_adv/gdextension_build/SConstruct74
-rw-r--r--modules/text_server_adv/register_types.cpp2
-rw-r--r--modules/text_server_adv/text_server_adv.cpp406
-rw-r--r--modules/text_server_adv/text_server_adv.h152
-rw-r--r--modules/text_server_adv/thorvg_bounds_iterator.cpp70
-rw-r--r--modules/text_server_adv/thorvg_bounds_iterator.h58
-rw-r--r--modules/text_server_adv/thorvg_svg_in_ot.cpp320
-rw-r--r--modules/text_server_adv/thorvg_svg_in_ot.h86
-rw-r--r--modules/text_server_fb/SCsub3
-rw-r--r--modules/text_server_fb/gdextension_build/SConstruct74
-rw-r--r--modules/text_server_fb/register_types.cpp2
-rw-r--r--modules/text_server_fb/text_server_fb.cpp341
-rw-r--r--modules/text_server_fb/text_server_fb.h151
-rw-r--r--modules/text_server_fb/thorvg_bounds_iterator.cpp70
-rw-r--r--modules/text_server_fb/thorvg_bounds_iterator.h58
-rw-r--r--modules/text_server_fb/thorvg_svg_in_ot.cpp320
-rw-r--r--modules/text_server_fb/thorvg_svg_in_ot.h86
-rw-r--r--modules/theora/SCsub7
-rw-r--r--modules/vorbis/audio_stream_ogg_vorbis.cpp2
-rw-r--r--modules/webp/webp_common.cpp50
-rw-r--r--modules/webp/webp_common.h2
-rw-r--r--modules/webrtc/doc_classes/WebRTCDataChannel.xml4
-rw-r--r--modules/webrtc/webrtc_data_channel_extension.h4
-rw-r--r--modules/webxr/doc_classes/WebXRInterface.xml105
-rw-r--r--modules/webxr/godot_webxr.h41
-rw-r--r--modules/webxr/native/library_godot_webxr.js464
-rw-r--r--modules/webxr/native/webxr.externs.js682
-rw-r--r--modules/webxr/webxr_interface.cpp23
-rw-r--r--modules/webxr/webxr_interface.h14
-rw-r--r--modules/webxr/webxr_interface_js.cpp487
-rw-r--r--modules/webxr/webxr_interface_js.h156
-rw-r--r--modules/zip/doc_classes/ZIPReader.xml2
-rw-r--r--modules/zip/zip_packer.cpp12
-rw-r--r--platform/android/api/jni_singleton.h23
-rw-r--r--platform/android/detect.py36
-rw-r--r--platform/android/display_server_android.cpp90
-rw-r--r--platform/android/display_server_android.h15
-rw-r--r--platform/android/export/export_plugin.cpp160
-rw-r--r--platform/android/export/export_plugin.h2
-rw-r--r--platform/android/java/app/AndroidManifest.xml2
-rw-r--r--platform/android/java/app/config.gradle9
-rw-r--r--platform/android/java/editor/src/main/AndroidManifest.xml10
-rw-r--r--platform/android/java/editor/src/main/java/org/godotengine/editor/GodotEditor.kt19
-rw-r--r--platform/android/java/editor/src/main/res/values/themes.xml5
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/Godot.java5
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/GodotGLRenderView.java49
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/GodotRenderView.java2
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/GodotVulkanRenderView.java47
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java2
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/io/StorageScope.kt5
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/io/directory/DirectoryAccessHandler.kt3
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPlugin.java30
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPluginInfoProvider.java6
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/xr/regular/RegularConfigChooser.java14
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/xr/regular/RegularContextFactory.java11
-rw-r--r--platform/android/java/nativeSrcsConfigs/CMakeLists.txt2
-rw-r--r--platform/android/java_godot_lib_jni.cpp57
-rw-r--r--platform/android/java_godot_view_wrapper.cpp13
-rw-r--r--platform/android/java_godot_view_wrapper.h5
-rw-r--r--platform/android/jni_utils.cpp35
-rw-r--r--platform/android/os_android.cpp233
-rw-r--r--platform/android/os_android.h21
-rw-r--r--platform/android/plugin/godot_plugin_jni.cpp20
-rw-r--r--platform/android/plugin/godot_plugin_jni.h2
-rw-r--r--platform/ios/app_delegate.mm9
-rw-r--r--platform/ios/display_server_ios.h7
-rw-r--r--platform/ios/display_server_ios.mm60
-rw-r--r--platform/ios/export/export_plugin.cpp146
-rw-r--r--platform/ios/godot_ios.mm8
-rw-r--r--platform/ios/godot_view.mm2
-rw-r--r--platform/ios/keyboard_input_view.mm36
-rw-r--r--platform/ios/os_ios.h15
-rw-r--r--platform/ios/os_ios.mm218
-rw-r--r--platform/linuxbsd/dbus-so_wrap.c4
-rw-r--r--platform/linuxbsd/detect.py16
-rw-r--r--platform/linuxbsd/fontconfig-so_wrap.c382
-rw-r--r--platform/linuxbsd/fontconfig-so_wrap.h142
-rw-r--r--platform/linuxbsd/joypad_linux.cpp2
-rw-r--r--platform/linuxbsd/os_linuxbsd.cpp174
-rw-r--r--platform/linuxbsd/os_linuxbsd.h15
-rw-r--r--platform/linuxbsd/platform_config.h2
-rw-r--r--platform/linuxbsd/tts_linux.cpp11
-rw-r--r--platform/linuxbsd/x11/SCsub10
-rw-r--r--platform/linuxbsd/x11/detect_prime_x11.cpp25
-rw-r--r--platform/linuxbsd/x11/display_server_x11.cpp168
-rw-r--r--platform/linuxbsd/x11/display_server_x11.h20
-rw-r--r--platform/linuxbsd/x11/dynwrappers/xcursor-so_wrap.c676
-rw-r--r--platform/linuxbsd/x11/dynwrappers/xcursor-so_wrap.h258
-rw-r--r--platform/linuxbsd/x11/dynwrappers/xext-so_wrap.c154
-rw-r--r--platform/linuxbsd/x11/dynwrappers/xext-so_wrap.h72
-rw-r--r--platform/linuxbsd/x11/dynwrappers/xinerama-so_wrap.c71
-rw-r--r--platform/linuxbsd/x11/dynwrappers/xinerama-so_wrap.h38
-rw-r--r--platform/linuxbsd/x11/dynwrappers/xinput2-so_wrap.c401
-rw-r--r--platform/linuxbsd/x11/dynwrappers/xinput2-so_wrap.h158
-rw-r--r--platform/linuxbsd/x11/dynwrappers/xlib-so_wrap.c6664
-rw-r--r--platform/linuxbsd/x11/dynwrappers/xlib-so_wrap.h2439
-rw-r--r--platform/linuxbsd/x11/dynwrappers/xrandr-so_wrap.c797
-rw-r--r--platform/linuxbsd/x11/dynwrappers/xrandr-so_wrap.h302
-rw-r--r--platform/linuxbsd/x11/dynwrappers/xrender-so_wrap.c511
-rw-r--r--platform/linuxbsd/x11/dynwrappers/xrender-so_wrap.h198
-rw-r--r--platform/linuxbsd/x11/gl_manager_x11.cpp34
-rw-r--r--platform/linuxbsd/x11/gl_manager_x11.h7
-rw-r--r--platform/macos/detect.py20
-rw-r--r--platform/macos/display_server_macos.h5
-rw-r--r--platform/macos/display_server_macos.mm128
-rw-r--r--platform/macos/export/export_plugin.cpp149
-rw-r--r--platform/macos/export/export_plugin.h2
-rw-r--r--platform/macos/export/plist.cpp292
-rw-r--r--platform/macos/export/plist.h25
-rw-r--r--platform/macos/godot_application_delegate.mm4
-rw-r--r--platform/macos/godot_window_delegate.mm14
-rw-r--r--platform/macos/os_macos.h7
-rw-r--r--platform/macos/os_macos.mm196
-rw-r--r--platform/macos/platform_config.h2
-rw-r--r--platform/web/SCsub9
-rw-r--r--platform/web/display_server_web.cpp12
-rw-r--r--platform/web/display_server_web.h5
-rw-r--r--platform/web/export/export_plugin.cpp2
-rw-r--r--platform/web/js/engine/config.js4
-rw-r--r--platform/web/js/engine/engine.js4
-rw-r--r--platform/web/js/engine/features.js10
-rw-r--r--platform/web/js/libs/library_godot_webgl2.externs.js36
-rw-r--r--platform/web/js/libs/library_godot_webgl2.js5
-rw-r--r--platform/windows/console_wrapper_windows.cpp2
-rw-r--r--platform/windows/crash_handler_windows.cpp2
-rw-r--r--platform/windows/detect.py11
-rw-r--r--platform/windows/display_server_windows.cpp73
-rw-r--r--platform/windows/display_server_windows.h3
-rw-r--r--platform/windows/export/export_plugin.cpp145
-rw-r--r--platform/windows/export/export_plugin.h3
-rw-r--r--platform/windows/gl_manager_windows.cpp59
-rw-r--r--platform/windows/gl_manager_windows.h10
-rw-r--r--platform/windows/godot.icobin359559 -> 142638 bytes
-rw-r--r--platform/windows/godot_console.icobin0 -> 140380 bytes
-rw-r--r--platform/windows/godot_res_wrap.rc2
-rw-r--r--platform/windows/os_windows.cpp354
-rw-r--r--platform/windows/os_windows.h20
-rw-r--r--platform/windows/platform_config.h2
-rw-r--r--platform/windows/platform_windows_builders.py13
-rw-r--r--scene/2d/audio_stream_player_2d.cpp3
-rw-r--r--scene/2d/audio_stream_player_2d.h2
-rw-r--r--scene/2d/back_buffer_copy.cpp7
-rw-r--r--scene/2d/back_buffer_copy.h1
-rw-r--r--scene/2d/camera_2d.cpp7
-rw-r--r--scene/2d/canvas_group.cpp2
-rw-r--r--scene/2d/gpu_particles_2d.cpp10
-rw-r--r--scene/2d/gpu_particles_2d.h2
-rw-r--r--scene/2d/joint_2d.cpp18
-rw-r--r--scene/2d/multimesh_instance_2d.cpp10
-rw-r--r--scene/2d/navigation_agent_2d.cpp99
-rw-r--r--scene/2d/navigation_agent_2d.h25
-rw-r--r--scene/2d/navigation_link_2d.cpp2
-rw-r--r--scene/2d/navigation_link_2d.h6
-rw-r--r--scene/2d/navigation_region_2d.cpp388
-rw-r--r--scene/2d/navigation_region_2d.h71
-rw-r--r--scene/2d/node_2d.cpp76
-rw-r--r--scene/2d/node_2d.h17
-rw-r--r--scene/2d/path_2d.cpp61
-rw-r--r--scene/2d/path_2d.h1
-rw-r--r--scene/2d/physics_body_2d.cpp18
-rw-r--r--scene/2d/physics_body_2d.h4
-rw-r--r--scene/2d/polygon_2d.cpp4
-rw-r--r--scene/2d/skeleton_2d.cpp2
-rw-r--r--scene/2d/tile_map.cpp141
-rw-r--r--scene/2d/tile_map.h24
-rw-r--r--scene/2d/touch_screen_button.cpp4
-rw-r--r--scene/3d/audio_stream_player_3d.cpp3
-rw-r--r--scene/3d/audio_stream_player_3d.h2
-rw-r--r--scene/3d/bone_attachment_3d.cpp4
-rw-r--r--scene/3d/bone_attachment_3d.h2
-rw-r--r--scene/3d/camera_3d.cpp11
-rw-r--r--scene/3d/collision_object_3d.cpp1
-rw-r--r--scene/3d/collision_shape_3d.cpp11
-rw-r--r--scene/3d/cpu_particles_3d.cpp2
-rw-r--r--scene/3d/gpu_particles_3d.cpp4
-rw-r--r--scene/3d/gpu_particles_3d.h2
-rw-r--r--scene/3d/gpu_particles_collision_3d.cpp4
-rw-r--r--scene/3d/light_3d.cpp14
-rw-r--r--scene/3d/light_3d.h3
-rw-r--r--scene/3d/mesh_instance_3d.cpp12
-rw-r--r--scene/3d/mesh_instance_3d.h1
-rw-r--r--scene/3d/navigation_agent_3d.cpp99
-rw-r--r--scene/3d/navigation_agent_3d.h25
-rw-r--r--scene/3d/navigation_link_3d.cpp2
-rw-r--r--scene/3d/navigation_link_3d.h6
-rw-r--r--scene/3d/navigation_region_3d.cpp65
-rw-r--r--scene/3d/navigation_region_3d.h11
-rw-r--r--scene/3d/node_3d.cpp34
-rw-r--r--scene/3d/node_3d.h4
-rw-r--r--scene/3d/path_3d.cpp177
-rw-r--r--scene/3d/path_3d.h7
-rw-r--r--scene/3d/physics_body_3d.cpp16
-rw-r--r--scene/3d/physics_body_3d.h4
-rw-r--r--scene/3d/skeleton_3d.cpp2
-rw-r--r--scene/3d/soft_body_3d.cpp4
-rw-r--r--scene/3d/spring_arm_3d.cpp1
-rw-r--r--scene/3d/sprite_3d.cpp4
-rw-r--r--scene/3d/visual_instance_3d.cpp47
-rw-r--r--scene/3d/visual_instance_3d.h12
-rw-r--r--scene/3d/xr_nodes.cpp40
-rw-r--r--scene/3d/xr_nodes.h2
-rw-r--r--scene/animation/animation_blend_space_1d.cpp10
-rw-r--r--scene/animation/animation_blend_space_1d.h2
-rw-r--r--scene/animation/animation_blend_space_2d.cpp22
-rw-r--r--scene/animation/animation_blend_space_2d.h2
-rw-r--r--scene/animation/animation_blend_tree.cpp159
-rw-r--r--scene/animation/animation_blend_tree.h24
-rw-r--r--scene/animation/animation_node_state_machine.cpp99
-rw-r--r--scene/animation/animation_node_state_machine.h25
-rw-r--r--scene/animation/animation_player.cpp241
-rw-r--r--scene/animation/animation_player.h6
-rw-r--r--scene/animation/animation_tree.cpp267
-rw-r--r--scene/animation/animation_tree.h26
-rw-r--r--scene/animation/root_motion_view.cpp8
-rw-r--r--scene/debugger/scene_debugger.cpp107
-rw-r--r--scene/debugger/scene_debugger.h20
-rw-r--r--scene/gui/base_button.cpp12
-rw-r--r--scene/gui/base_button.h2
-rw-r--r--scene/gui/button.cpp2
-rw-r--r--scene/gui/code_edit.cpp34
-rw-r--r--scene/gui/code_edit.h1
-rw-r--r--scene/gui/color_picker.cpp9
-rw-r--r--scene/gui/color_picker.h4
-rw-r--r--scene/gui/control.cpp209
-rw-r--r--scene/gui/control.h18
-rw-r--r--scene/gui/dialogs.cpp2
-rw-r--r--scene/gui/file_dialog.cpp7
-rw-r--r--scene/gui/graph_edit.cpp91
-rw-r--r--scene/gui/graph_edit.h4
-rw-r--r--scene/gui/graph_node.cpp66
-rw-r--r--scene/gui/item_list.cpp1
-rw-r--r--scene/gui/line_edit.cpp73
-rw-r--r--scene/gui/line_edit.h3
-rw-r--r--scene/gui/link_button.cpp19
-rw-r--r--scene/gui/link_button.h4
-rw-r--r--scene/gui/option_button.cpp6
-rw-r--r--scene/gui/popup_menu.cpp4
-rw-r--r--scene/gui/progress_bar.cpp7
-rw-r--r--scene/gui/range.cpp23
-rw-r--r--scene/gui/range.h1
-rw-r--r--scene/gui/rich_text_effect.cpp4
-rw-r--r--scene/gui/rich_text_effect.h6
-rw-r--r--scene/gui/rich_text_label.cpp152
-rw-r--r--scene/gui/rich_text_label.h8
-rw-r--r--scene/gui/scroll_bar.cpp2
-rw-r--r--scene/gui/scroll_bar.h2
-rw-r--r--scene/gui/scroll_container.cpp4
-rw-r--r--scene/gui/spin_box.cpp5
-rw-r--r--scene/gui/split_container.cpp3
-rw-r--r--scene/gui/subviewport_container.cpp12
-rw-r--r--scene/gui/subviewport_container.h3
-rw-r--r--scene/gui/tab_bar.cpp3
-rw-r--r--scene/gui/text_edit.cpp27
-rw-r--r--scene/gui/texture_button.cpp52
-rw-r--r--scene/gui/texture_button.h20
-rw-r--r--scene/gui/tree.cpp132
-rw-r--r--scene/gui/tree.h5
-rw-r--r--scene/main/canvas_item.cpp60
-rw-r--r--scene/main/canvas_item.h17
-rw-r--r--scene/main/canvas_layer.cpp15
-rw-r--r--scene/main/canvas_layer.h1
-rw-r--r--scene/main/http_request.cpp49
-rw-r--r--scene/main/multiplayer_api.cpp2
-rw-r--r--scene/main/multiplayer_peer.h4
-rw-r--r--scene/main/node.cpp98
-rw-r--r--scene/main/node.h5
-rw-r--r--scene/main/scene_tree.cpp13
-rw-r--r--scene/main/viewport.cpp44
-rw-r--r--scene/main/viewport.h5
-rw-r--r--scene/main/window.cpp538
-rw-r--r--scene/main/window.h64
-rw-r--r--scene/property_utils.h2
-rw-r--r--scene/register_scene_types.cpp21
-rw-r--r--scene/resources/animation.cpp750
-rw-r--r--scene/resources/animation.h48
-rw-r--r--scene/resources/animation_library.cpp13
-rw-r--r--scene/resources/animation_library.h2
-rw-r--r--scene/resources/bit_map.cpp105
-rw-r--r--scene/resources/bit_map.h2
-rw-r--r--scene/resources/bone_map.cpp2
-rw-r--r--scene/resources/camera_attributes.cpp4
-rw-r--r--scene/resources/curve.cpp865
-rw-r--r--scene/resources/curve.h41
-rw-r--r--scene/resources/default_theme/default_theme.cpp8
-rw-r--r--scene/resources/font.cpp183
-rw-r--r--scene/resources/font.h27
-rw-r--r--scene/resources/importer_mesh.cpp6
-rw-r--r--scene/resources/importer_mesh.h2
-rw-r--r--scene/resources/label_settings.cpp6
-rw-r--r--scene/resources/material.cpp24
-rw-r--r--scene/resources/mesh.cpp128
-rw-r--r--scene/resources/mesh.h10
-rw-r--r--scene/resources/mesh_library.cpp77
-rw-r--r--scene/resources/mesh_library.h17
-rw-r--r--scene/resources/multimesh.cpp1
-rw-r--r--scene/resources/navigation_mesh.cpp51
-rw-r--r--scene/resources/navigation_mesh.h12
-rw-r--r--scene/resources/navigation_polygon.cpp354
-rw-r--r--scene/resources/navigation_polygon.h94
-rw-r--r--scene/resources/packed_scene.cpp73
-rw-r--r--scene/resources/packed_scene.h5
-rw-r--r--scene/resources/primitive_meshes.cpp782
-rw-r--r--scene/resources/primitive_meshes.h43
-rw-r--r--scene/resources/resource_format_text.cpp51
-rw-r--r--scene/resources/shader.cpp2
-rw-r--r--scene/resources/shader_include.cpp2
-rw-r--r--scene/resources/shape_2d.cpp1
-rw-r--r--scene/resources/shape_3d.cpp1
-rw-r--r--scene/resources/skeleton_modification_2d_fabrik.h4
-rw-r--r--scene/resources/skeleton_modification_3d_fabrik.h6
-rw-r--r--scene/resources/style_box.cpp12
-rw-r--r--scene/resources/syntax_highlighter.cpp2
-rw-r--r--scene/resources/text_line.cpp12
-rw-r--r--scene/resources/text_line.h4
-rw-r--r--scene/resources/text_paragraph.cpp12
-rw-r--r--scene/resources/text_paragraph.h4
-rw-r--r--scene/resources/texture.cpp154
-rw-r--r--scene/resources/tile_set.cpp59
-rw-r--r--scene/resources/tile_set.h4
-rw-r--r--scene/resources/visual_shader.cpp90
-rw-r--r--scene/resources/visual_shader_nodes.cpp4
-rw-r--r--scene/resources/visual_shader_particle_nodes.cpp59
-rw-r--r--scene/scene_string_names.cpp2
-rw-r--r--scene/scene_string_names.h2
-rw-r--r--scene/theme/theme_db.cpp9
-rw-r--r--scene/theme/theme_owner.cpp69
-rw-r--r--scene/theme/theme_owner.h1
-rw-r--r--servers/audio/audio_effect.cpp10
-rw-r--r--servers/audio/audio_effect.h2
-rw-r--r--servers/audio/audio_stream.cpp36
-rw-r--r--servers/audio/audio_stream.h6
-rw-r--r--servers/audio/effects/audio_effect_distortion.cpp4
-rw-r--r--servers/audio_server.cpp8
-rw-r--r--servers/display_server.cpp8
-rw-r--r--servers/display_server.h5
-rw-r--r--servers/display_server_headless.h3
-rw-r--r--servers/extensions/physics_server_2d_extension.h18
-rw-r--r--servers/extensions/physics_server_3d_extension.cpp3
-rw-r--r--servers/extensions/physics_server_3d_extension.h14
-rw-r--r--servers/movie_writer/movie_writer.cpp43
-rw-r--r--servers/movie_writer/movie_writer.h2
-rw-r--r--servers/navigation/navigation_path_query_parameters_2d.cpp22
-rw-r--r--servers/navigation/navigation_path_query_parameters_2d.h12
-rw-r--r--servers/navigation/navigation_path_query_parameters_3d.cpp18
-rw-r--r--servers/navigation/navigation_path_query_parameters_3d.h12
-rw-r--r--servers/navigation/navigation_path_query_result_2d.cpp42
-rw-r--r--servers/navigation/navigation_path_query_result_2d.h19
-rw-r--r--servers/navigation/navigation_path_query_result_3d.cpp42
-rw-r--r--servers/navigation/navigation_path_query_result_3d.h20
-rw-r--r--servers/navigation/navigation_utilities.h22
-rw-r--r--servers/navigation_server_2d.cpp31
-rw-r--r--servers/navigation_server_2d.h14
-rw-r--r--servers/navigation_server_3d.cpp15
-rw-r--r--servers/navigation_server_3d.h14
-rw-r--r--servers/physics_2d/godot_body_pair_2d.cpp25
-rw-r--r--servers/physics_2d/godot_shape_2d.cpp10
-rw-r--r--servers/physics_2d/godot_step_2d.cpp6
-rw-r--r--servers/physics_2d/godot_step_2d.h2
-rw-r--r--servers/physics_3d/godot_body_pair_3d.cpp29
-rw-r--r--servers/physics_3d/godot_collision_solver_3d_sat.cpp2
-rw-r--r--servers/physics_3d/godot_shape_3d.cpp12
-rw-r--r--servers/physics_3d/godot_soft_body_3d.cpp1
-rw-r--r--servers/physics_3d/godot_step_3d.cpp6
-rw-r--r--servers/physics_3d/godot_step_3d.h2
-rw-r--r--servers/physics_server_2d.cpp9
-rw-r--r--servers/physics_server_2d.h4
-rw-r--r--servers/physics_server_3d.cpp53
-rw-r--r--servers/physics_server_3d.h26
-rw-r--r--servers/rendering/dummy/rasterizer_scene_dummy.h2
-rw-r--r--servers/rendering/dummy/storage/light_storage.h1
-rw-r--r--servers/rendering/dummy/storage/mesh_storage.cpp7
-rw-r--r--servers/rendering/dummy/storage/mesh_storage.h2
-rw-r--r--servers/rendering/dummy/storage/particles_storage.h3
-rw-r--r--servers/rendering/dummy/storage/texture_storage.h1
-rw-r--r--servers/rendering/renderer_canvas_cull.cpp46
-rw-r--r--servers/rendering/renderer_canvas_cull.h2
-rw-r--r--servers/rendering/renderer_canvas_render.cpp4
-rw-r--r--servers/rendering/renderer_geometry_instance.cpp5
-rw-r--r--servers/rendering/renderer_geometry_instance.h8
-rw-r--r--servers/rendering/renderer_rd/SCsub1
-rw-r--r--servers/rendering/renderer_rd/effects/copy_effects.cpp115
-rw-r--r--servers/rendering/renderer_rd/effects/copy_effects.h36
-rw-r--r--servers/rendering/renderer_rd/effects/resolve.h4
-rw-r--r--servers/rendering/renderer_rd/effects/ss_effects.cpp1
-rw-r--r--servers/rendering/renderer_rd/effects/ss_effects.h4
-rw-r--r--servers/rendering/renderer_rd/effects/vrs.cpp17
-rw-r--r--servers/rendering/renderer_rd/environment/fog.cpp97
-rw-r--r--servers/rendering/renderer_rd/environment/fog.h9
-rw-r--r--servers/rendering/renderer_rd/environment/gi.cpp6
-rw-r--r--servers/rendering/renderer_rd/environment/sky.cpp462
-rw-r--r--servers/rendering/renderer_rd/environment/sky.h76
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp253
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h17
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp117
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h16
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp158
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h16
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp105
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h14
-rw-r--r--servers/rendering/renderer_rd/framebuffer_cache_rd.h4
-rw-r--r--servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp133
-rw-r--r--servers/rendering/renderer_rd/renderer_canvas_render_rd.h23
-rw-r--r--servers/rendering/renderer_rd/renderer_compositor_rd.cpp9
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_rd.cpp128
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_rd.h10
-rw-r--r--servers/rendering/renderer_rd/shaders/canvas.glsl42
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/blur_raster.glsl49
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/copy.glsl38
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/copy_to_fb.glsl61
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/cubemap_roughness_inc.glsl11
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/screen_space_reflection.glsl21
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/vrs.glsl14
-rw-r--r--servers/rendering/renderer_rd/shaders/environment/gi.glsl6
-rw-r--r--servers/rendering/renderer_rd/shaders/environment/sky.glsl61
-rw-r--r--servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl14
-rw-r--r--servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl13
-rw-r--r--servers/rendering/renderer_rd/shaders/particles.glsl13
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_data_inc.glsl2
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_aa_inc.glsl7
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl5
-rw-r--r--servers/rendering/renderer_rd/shaders/skeleton.glsl13
-rw-r--r--servers/rendering/renderer_rd/spirv-reflect/SCsub (renamed from drivers/spirv-reflect/SCsub)2
-rw-r--r--servers/rendering/renderer_rd/storage_rd/light_storage.cpp44
-rw-r--r--servers/rendering/renderer_rd/storage_rd/light_storage.h4
-rw-r--r--servers/rendering/renderer_rd/storage_rd/material_storage.cpp109
-rw-r--r--servers/rendering/renderer_rd/storage_rd/material_storage.h24
-rw-r--r--servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp19
-rw-r--r--servers/rendering/renderer_rd/storage_rd/mesh_storage.h4
-rw-r--r--servers/rendering/renderer_rd/storage_rd/particles_storage.cpp109
-rw-r--r--servers/rendering/renderer_rd/storage_rd/particles_storage.h30
-rw-r--r--servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.cpp24
-rw-r--r--servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h1
-rw-r--r--servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.cpp1
-rw-r--r--servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.h3
-rw-r--r--servers/rendering/renderer_rd/storage_rd/texture_storage.cpp101
-rw-r--r--servers/rendering/renderer_rd/storage_rd/texture_storage.h3
-rw-r--r--servers/rendering/renderer_scene_cull.cpp33
-rw-r--r--servers/rendering/renderer_scene_cull.h10
-rw-r--r--servers/rendering/renderer_scene_render.cpp4
-rw-r--r--servers/rendering/renderer_scene_render.h4
-rw-r--r--servers/rendering/renderer_viewport.cpp3
-rw-r--r--servers/rendering/rendering_device.cpp409
-rw-r--r--servers/rendering/rendering_device.h82
-rw-r--r--servers/rendering/rendering_device_binds.h2
-rw-r--r--servers/rendering/rendering_method.h2
-rw-r--r--servers/rendering/rendering_server_default.h4
-rw-r--r--servers/rendering/shader_compiler.cpp61
-rw-r--r--servers/rendering/shader_language.cpp184
-rw-r--r--servers/rendering/shader_language.h9
-rw-r--r--servers/rendering/shader_types.cpp2
-rw-r--r--servers/rendering/storage/environment_storage.cpp2
-rw-r--r--servers/rendering/storage/environment_storage.h4
-rw-r--r--servers/rendering/storage/light_storage.h2
-rw-r--r--servers/rendering/storage/particles_storage.h3
-rw-r--r--servers/rendering_server.cpp29
-rw-r--r--servers/rendering_server.h4
-rw-r--r--servers/text/text_server_extension.cpp69
-rw-r--r--servers/text/text_server_extension.h40
-rw-r--r--servers/text_server.cpp15
-rw-r--r--servers/text_server.h17
-rw-r--r--servers/xr/xr_interface.cpp7
-rw-r--r--servers/xr/xr_interface.h2
-rw-r--r--servers/xr/xr_interface_extension.cpp6
-rw-r--r--servers/xr/xr_interface_extension.h3
-rw-r--r--tests/core/config/test_project_settings.h102
-rw-r--r--tests/core/math/test_math_funcs.h659
-rw-r--r--tests/core/math/test_vector2i.h8
-rw-r--r--tests/core/math/test_vector3i.h8
-rw-r--r--tests/core/math/test_vector4i.h8
-rw-r--r--tests/core/os/test_os.h12
-rw-r--r--tests/core/string/test_string.h25
-rw-r--r--tests/core/variant/test_dictionary.h13
-rw-r--r--tests/python_build/fixtures/gles3/vertex_fragment_expected_full.glsl5
-rw-r--r--tests/python_build/fixtures/gles3/vertex_fragment_expected_parts.json1
-rw-r--r--tests/scene/test_arraymesh.h4
-rw-r--r--tests/scene/test_bit_map.h66
-rw-r--r--tests/scene/test_code_edit.h86
-rw-r--r--tests/scene/test_curve.h8
-rw-r--r--tests/scene/test_text_edit.h4
-rw-r--r--tests/scene/test_visual_shader.h151
-rw-r--r--tests/servers/test_text_server.h50
-rw-r--r--tests/test_main.cpp2
-rw-r--r--thirdparty/README.md52
-rw-r--r--thirdparty/basis_universal/encoder/basisu_comp.cpp178
-rw-r--r--thirdparty/basis_universal/encoder/basisu_comp.h21
-rw-r--r--thirdparty/basis_universal/encoder/basisu_enc.cpp4
-rw-r--r--thirdparty/basis_universal/encoder/basisu_frontend.cpp4
-rw-r--r--thirdparty/basis_universal/transcoder/basisu_transcoder.cpp2
-rw-r--r--thirdparty/certs/ca-certificates.crt50
-rw-r--r--thirdparty/cvtt/ConvectionKernels_BC67.cpp14
-rw-r--r--thirdparty/embree/common/algorithms/parallel_for.h1
-rw-r--r--thirdparty/embree/common/algorithms/parallel_for_for.h23
-rw-r--r--thirdparty/embree/common/algorithms/parallel_for_for_prefix_sum.h50
-rw-r--r--thirdparty/embree/common/algorithms/parallel_reduce.h2
-rw-r--r--thirdparty/embree/common/math/bbox.h10
-rw-r--r--thirdparty/embree/common/math/color.h19
-rw-r--r--thirdparty/embree/common/math/constants.cpp19
-rw-r--r--thirdparty/embree/common/math/constants.h54
-rw-r--r--thirdparty/embree/common/math/math.h104
-rw-r--r--thirdparty/embree/common/math/quaternion.h12
-rw-r--r--thirdparty/embree/common/math/transcendental.h6
-rw-r--r--thirdparty/embree/common/math/vec2.h8
-rw-r--r--thirdparty/embree/common/math/vec2fa.h29
-rw-r--r--thirdparty/embree/common/math/vec3.h11
-rw-r--r--thirdparty/embree/common/math/vec3fa.h92
-rw-r--r--thirdparty/embree/common/math/vec3ia.h46
-rw-r--r--thirdparty/embree/common/math/vec4.h6
-rw-r--r--thirdparty/embree/common/simd/arm/avx2neon.h1196
-rw-r--r--thirdparty/embree/common/simd/arm/emulation.h71
-rw-r--r--thirdparty/embree/common/simd/arm/sse2neon.h10961
-rw-r--r--thirdparty/embree/common/simd/simd.h2
-rw-r--r--thirdparty/embree/common/simd/sse.h2
-rw-r--r--thirdparty/embree/common/simd/vboold4_avx.h7
-rw-r--r--thirdparty/embree/common/simd/vboolf16_avx512.h2
-rw-r--r--thirdparty/embree/common/simd/vboolf4_sse2.h24
-rw-r--r--thirdparty/embree/common/simd/vboolf8_avx.h2
-rw-r--r--thirdparty/embree/common/simd/vdouble4_avx.h9
-rw-r--r--thirdparty/embree/common/simd/vfloat16_avx512.h5
-rw-r--r--thirdparty/embree/common/simd/vfloat4_sse2.h135
-rw-r--r--thirdparty/embree/common/simd/vfloat8_avx.h87
-rw-r--r--thirdparty/embree/common/simd/vint4_sse2.h100
-rw-r--r--thirdparty/embree/common/simd/vint8_avx.h4
-rw-r--r--thirdparty/embree/common/simd/vint8_avx2.h4
-rw-r--r--thirdparty/embree/common/simd/vuint4_sse2.h38
-rw-r--r--thirdparty/embree/common/simd/vuint8_avx.h4
-rw-r--r--thirdparty/embree/common/simd/vuint8_avx2.h2
-rw-r--r--thirdparty/embree/common/simd/wasm/emulation.h13
-rw-r--r--thirdparty/embree/common/sys/array.h12
-rw-r--r--thirdparty/embree/common/sys/barrier.h4
-rw-r--r--thirdparty/embree/common/sys/intrinsics.h124
-rw-r--r--thirdparty/embree/common/sys/mutex.cpp1
-rw-r--r--thirdparty/embree/common/sys/mutex.h6
-rw-r--r--thirdparty/embree/common/sys/platform.h20
-rw-r--r--thirdparty/embree/common/sys/sysinfo.cpp56
-rw-r--r--thirdparty/embree/common/sys/sysinfo.h13
-rw-r--r--thirdparty/embree/common/sys/thread.cpp35
-rw-r--r--thirdparty/embree/common/sys/vector.h14
-rw-r--r--thirdparty/embree/common/tasking/taskschedulerinternal.h2
-rw-r--r--thirdparty/embree/common/tasking/taskschedulertbb.h8
-rw-r--r--thirdparty/embree/include/embree3/rtcore_common.h4
-rw-r--r--thirdparty/embree/include/embree3/rtcore_config.h17
-rw-r--r--thirdparty/embree/include/embree3/rtcore_quaternion.h2
-rw-r--r--thirdparty/embree/include/embree3/rtcore_scene.h5
-rw-r--r--thirdparty/embree/kernels/builders/bvh_builder_morton.h2
-rw-r--r--thirdparty/embree/kernels/builders/bvh_builder_msmblur.h4
-rw-r--r--thirdparty/embree/kernels/builders/bvh_builder_sah.h2
-rw-r--r--thirdparty/embree/kernels/builders/heuristic_binning.h6
-rw-r--r--thirdparty/embree/kernels/builders/heuristic_openmerge_array.h2
-rw-r--r--thirdparty/embree/kernels/builders/heuristic_spatial.h111
-rw-r--r--thirdparty/embree/kernels/builders/heuristic_spatial_array.h15
-rw-r--r--thirdparty/embree/kernels/builders/primrefgen.cpp4
-rw-r--r--thirdparty/embree/kernels/builders/primrefgen_presplit.h13
-rw-r--r--thirdparty/embree/kernels/builders/splitter.h28
-rw-r--r--thirdparty/embree/kernels/bvh/bvh.cpp2
-rw-r--r--thirdparty/embree/kernels/bvh/bvh_intersector_hybrid.cpp4
-rw-r--r--thirdparty/embree/kernels/bvh/bvh_intersector_stream.h11
-rw-r--r--thirdparty/embree/kernels/bvh/bvh_node_aabb.h16
-rw-r--r--thirdparty/embree/kernels/bvh/bvh_node_aabb_mb.h8
-rw-r--r--thirdparty/embree/kernels/bvh/bvh_node_aabb_mb4d.h8
-rw-r--r--thirdparty/embree/kernels/bvh/bvh_node_qaabb.h8
-rw-r--r--thirdparty/embree/kernels/bvh/bvh_statistics.cpp2
-rw-r--r--thirdparty/embree/kernels/bvh/node_intersector1.h117
-rw-r--r--thirdparty/embree/kernels/bvh/node_intersector_frustum.h22
-rw-r--r--thirdparty/embree/kernels/bvh/node_intersector_packet.h53
-rw-r--r--thirdparty/embree/kernels/bvh/node_intersector_packet_stream.h26
-rw-r--r--thirdparty/embree/kernels/common/accel.h4
-rw-r--r--thirdparty/embree/kernels/common/acceln.cpp6
-rw-r--r--thirdparty/embree/kernels/common/accelset.h23
-rw-r--r--thirdparty/embree/kernels/common/alloc.cpp3
-rw-r--r--thirdparty/embree/kernels/common/alloc.h72
-rw-r--r--thirdparty/embree/kernels/common/device.cpp4
-rw-r--r--thirdparty/embree/kernels/common/geometry.h4
-rw-r--r--thirdparty/embree/kernels/common/isa.h2
-rw-r--r--thirdparty/embree/kernels/common/ray.h2
-rw-r--r--thirdparty/embree/kernels/common/rtcore.cpp26
-rw-r--r--thirdparty/embree/kernels/common/rtcore.h141
-rw-r--r--thirdparty/embree/kernels/common/rtcore_builder.cpp2
-rw-r--r--thirdparty/embree/kernels/common/scene.cpp4
-rw-r--r--thirdparty/embree/kernels/common/scene_curves.h8
-rw-r--r--thirdparty/embree/kernels/common/state.cpp15
-rw-r--r--thirdparty/embree/kernels/config.h4
-rw-r--r--thirdparty/embree/kernels/geometry/curve_intersector_oriented.h2
-rw-r--r--thirdparty/embree/kernels/geometry/curve_intersector_sweep.h2
-rw-r--r--thirdparty/embree/kernels/geometry/disc_intersector.h28
-rw-r--r--thirdparty/embree/kernels/geometry/filter.h34
-rw-r--r--thirdparty/embree/kernels/geometry/object_intersector.h8
-rw-r--r--thirdparty/embree/kernels/geometry/quadv.h2
-rw-r--r--thirdparty/embree/kernels/geometry/roundline_intersector.h4
-rw-r--r--thirdparty/embree/kernels/geometry/subgrid_intersector.h10
-rw-r--r--thirdparty/embree/kernels/hash.h5
-rw-r--r--thirdparty/embree/kernels/subdiv/bezier_patch.h2
-rw-r--r--thirdparty/embree/kernels/subdiv/catmullclark_ring.h8
-rw-r--r--thirdparty/embree/kernels/subdiv/catmullrom_curve.h6
-rw-r--r--thirdparty/embree/kernels/subdiv/linear_bezier_patch.h10
-rw-r--r--thirdparty/embree/patches/emscripten-nthreads.patch42
-rw-r--r--thirdparty/embree/patches/godot-changes-android.patch103
-rw-r--r--thirdparty/embree/patches/godot-changes-misc.patch105
-rw-r--r--thirdparty/embree/patches/godot-changes-noexcept.patch193
-rw-r--r--thirdparty/embree/patches/godot-changes-ubsan.patch24
-rw-r--r--thirdparty/glad/LICENSE83
-rw-r--r--thirdparty/glad/gl.c1995
-rw-r--r--thirdparty/glad/glad.c1951
-rw-r--r--thirdparty/glad/glad/gl.h3884
-rw-r--r--thirdparty/glad/glad/glad.h3801
-rw-r--r--thirdparty/glad/glad/glx.h605
-rw-r--r--thirdparty/glad/glx.c395
-rw-r--r--thirdparty/graphite/include/graphite2/Font.h28
-rw-r--r--thirdparty/graphite/include/graphite2/Log.h28
-rw-r--r--thirdparty/graphite/include/graphite2/Segment.h28
-rw-r--r--thirdparty/graphite/include/graphite2/Types.h28
-rw-r--r--thirdparty/graphite/src/CmapCache.cpp29
-rw-r--r--thirdparty/graphite/src/Code.cpp29
-rw-r--r--thirdparty/graphite/src/Collider.cpp29
-rw-r--r--thirdparty/graphite/src/Decompressor.cpp29
-rw-r--r--thirdparty/graphite/src/Face.cpp29
-rw-r--r--thirdparty/graphite/src/FeatureMap.cpp29
-rw-r--r--thirdparty/graphite/src/FileFace.cpp29
-rw-r--r--thirdparty/graphite/src/Font.cpp27
-rw-r--r--thirdparty/graphite/src/GlyphCache.cpp37
-rw-r--r--thirdparty/graphite/src/GlyphFace.cpp27
-rw-r--r--thirdparty/graphite/src/Intervals.cpp29
-rw-r--r--thirdparty/graphite/src/Justifier.cpp27
-rw-r--r--thirdparty/graphite/src/NameTable.cpp27
-rw-r--r--thirdparty/graphite/src/Pass.cpp35
-rw-r--r--thirdparty/graphite/src/Position.cpp27
-rw-r--r--thirdparty/graphite/src/Segment.cpp29
-rw-r--r--thirdparty/graphite/src/Silf.cpp29
-rw-r--r--thirdparty/graphite/src/Slot.cpp29
-rw-r--r--thirdparty/graphite/src/Sparse.cpp29
-rw-r--r--thirdparty/graphite/src/TtfUtil.cpp33
-rw-r--r--thirdparty/graphite/src/UtfCodec.cpp27
-rw-r--r--thirdparty/graphite/src/call_machine.cpp29
-rw-r--r--thirdparty/graphite/src/direct_machine.cpp29
-rw-r--r--thirdparty/graphite/src/gr_char_info.cpp27
-rw-r--r--thirdparty/graphite/src/gr_face.cpp29
-rw-r--r--thirdparty/graphite/src/gr_features.cpp29
-rw-r--r--thirdparty/graphite/src/gr_font.cpp27
-rw-r--r--thirdparty/graphite/src/gr_logging.cpp27
-rw-r--r--thirdparty/graphite/src/gr_segment.cpp29
-rw-r--r--thirdparty/graphite/src/gr_slot.cpp29
-rw-r--r--thirdparty/graphite/src/inc/CharInfo.h27
-rw-r--r--thirdparty/graphite/src/inc/CmapCache.h27
-rw-r--r--thirdparty/graphite/src/inc/Code.h29
-rw-r--r--thirdparty/graphite/src/inc/Collider.h29
-rw-r--r--thirdparty/graphite/src/inc/Compression.h27
-rw-r--r--thirdparty/graphite/src/inc/Decompressor.h27
-rw-r--r--thirdparty/graphite/src/inc/Endian.h29
-rw-r--r--thirdparty/graphite/src/inc/Error.h33
-rw-r--r--thirdparty/graphite/src/inc/Face.h29
-rw-r--r--thirdparty/graphite/src/inc/FeatureMap.h29
-rw-r--r--thirdparty/graphite/src/inc/FeatureVal.h27
-rw-r--r--thirdparty/graphite/src/inc/FileFace.h29
-rw-r--r--thirdparty/graphite/src/inc/Font.h27
-rw-r--r--thirdparty/graphite/src/inc/GlyphCache.h29
-rw-r--r--thirdparty/graphite/src/inc/GlyphFace.h27
-rw-r--r--thirdparty/graphite/src/inc/Intervals.h29
-rw-r--r--thirdparty/graphite/src/inc/List.h29
-rw-r--r--thirdparty/graphite/src/inc/Machine.h29
-rw-r--r--thirdparty/graphite/src/inc/Main.h29
-rw-r--r--thirdparty/graphite/src/inc/NameTable.h27
-rw-r--r--thirdparty/graphite/src/inc/Pass.h27
-rw-r--r--thirdparty/graphite/src/inc/Position.h27
-rw-r--r--thirdparty/graphite/src/inc/Rule.h29
-rw-r--r--thirdparty/graphite/src/inc/Segment.h29
-rw-r--r--thirdparty/graphite/src/inc/Silf.h29
-rw-r--r--thirdparty/graphite/src/inc/Slot.h29
-rw-r--r--thirdparty/graphite/src/inc/Sparse.h29
-rw-r--r--thirdparty/graphite/src/inc/TtfTypes.h35
-rw-r--r--thirdparty/graphite/src/inc/TtfUtil.h36
-rw-r--r--thirdparty/graphite/src/inc/UtfCodec.h29
-rw-r--r--thirdparty/graphite/src/inc/bits.h29
-rw-r--r--thirdparty/graphite/src/inc/debug.h29
-rw-r--r--thirdparty/graphite/src/inc/json.h29
-rw-r--r--thirdparty/graphite/src/inc/locale2lcid.h27
-rw-r--r--thirdparty/graphite/src/inc/opcode_table.h27
-rw-r--r--thirdparty/graphite/src/inc/opcodes.h29
-rw-r--r--thirdparty/graphite/src/json.cpp29
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/Common/Coverage.hh42
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/Common/CoverageFormat1.hh9
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/Common/CoverageFormat2.hh35
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkBasePos.hh4
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkLigPos.hh4
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkMarkPos.hh4
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/PairPos.hh4
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/PairPosFormat1.hh26
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/PairPosFormat2.hh27
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/PairSet.hh20
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GSUB/AlternateSet.hh2
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GSUB/AlternateSubst.hh4
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GSUB/Ligature.hh2
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GSUB/LigatureSubst.hh4
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GSUB/MultipleSubst.hh4
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GSUB/Sequence.hh2
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GSUB/SingleSubst.hh8
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GSUB/SingleSubstFormat1.hh2
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GSUB/SingleSubstFormat2.hh20
-rw-r--r--thirdparty/harfbuzz/src/OT/glyf/CompositeGlyph.hh67
-rw-r--r--thirdparty/harfbuzz/src/OT/glyf/Glyph.hh139
-rw-r--r--thirdparty/harfbuzz/src/OT/glyf/SimpleGlyph.hh49
-rw-r--r--thirdparty/harfbuzz/src/OT/glyf/SubsetGlyph.hh10
-rw-r--r--thirdparty/harfbuzz/src/OT/glyf/VarCompositeGlyph.hh353
-rw-r--r--thirdparty/harfbuzz/src/OT/glyf/composite-iter.hh68
-rw-r--r--thirdparty/harfbuzz/src/OT/glyf/coord-setter.hh34
-rw-r--r--thirdparty/harfbuzz/src/OT/glyf/glyf.hh66
-rw-r--r--thirdparty/harfbuzz/src/graph/classdef-graph.hh2
-rw-r--r--thirdparty/harfbuzz/src/graph/coverage-graph.hh2
-rw-r--r--thirdparty/harfbuzz/src/graph/graph.hh149
-rw-r--r--thirdparty/harfbuzz/src/graph/gsubgpos-graph.hh6
-rw-r--r--thirdparty/harfbuzz/src/graph/markbasepos-graph.hh10
-rw-r--r--thirdparty/harfbuzz/src/graph/pairpos-graph.hh6
-rw-r--r--thirdparty/harfbuzz/src/graph/serialize.hh23
-rw-r--r--thirdparty/harfbuzz/src/hb-aat-layout-morx-table.hh8
-rw-r--r--thirdparty/harfbuzz/src/hb-aat-layout.cc2
-rw-r--r--thirdparty/harfbuzz/src/hb-aat-map.hh2
-rw-r--r--thirdparty/harfbuzz/src/hb-algs.hh137
-rw-r--r--thirdparty/harfbuzz/src/hb-array.hh94
-rw-r--r--thirdparty/harfbuzz/src/hb-bit-page.hh90
-rw-r--r--thirdparty/harfbuzz/src/hb-bit-set-invertible.hh6
-rw-r--r--thirdparty/harfbuzz/src/hb-bit-set.hh72
-rw-r--r--thirdparty/harfbuzz/src/hb-blob.cc2
-rw-r--r--thirdparty/harfbuzz/src/hb-buffer-deserialize-json.hh12
-rw-r--r--thirdparty/harfbuzz/src/hb-buffer-deserialize-text.hh490
-rw-r--r--thirdparty/harfbuzz/src/hb-buffer-serialize.cc8
-rw-r--r--thirdparty/harfbuzz/src/hb-buffer-verify.cc5
-rw-r--r--thirdparty/harfbuzz/src/hb-buffer.cc99
-rw-r--r--thirdparty/harfbuzz/src/hb-buffer.hh11
-rw-r--r--thirdparty/harfbuzz/src/hb-cache.hh2
-rw-r--r--thirdparty/harfbuzz/src/hb-cff-interp-common.hh95
-rw-r--r--thirdparty/harfbuzz/src/hb-cff2-interp-cs.hh16
-rw-r--r--thirdparty/harfbuzz/src/hb-common.cc14
-rw-r--r--thirdparty/harfbuzz/src/hb-config.hh14
-rw-r--r--thirdparty/harfbuzz/src/hb-coretext.cc13
-rw-r--r--thirdparty/harfbuzz/src/hb-draw.cc91
-rw-r--r--thirdparty/harfbuzz/src/hb-face.cc17
-rw-r--r--thirdparty/harfbuzz/src/hb-face.hh2
-rw-r--r--thirdparty/harfbuzz/src/hb-fallback-shape.cc10
-rw-r--r--thirdparty/harfbuzz/src/hb-font.cc154
-rw-r--r--thirdparty/harfbuzz/src/hb-font.hh6
-rw-r--r--thirdparty/harfbuzz/src/hb-ft.cc32
-rw-r--r--thirdparty/harfbuzz/src/hb-glib.cc77
-rw-r--r--thirdparty/harfbuzz/src/hb-graphite2.cc2
-rw-r--r--thirdparty/harfbuzz/src/hb-iter.hh16
-rw-r--r--thirdparty/harfbuzz/src/hb-machinery.hh14
-rw-r--r--thirdparty/harfbuzz/src/hb-map.hh219
-rw-r--r--thirdparty/harfbuzz/src/hb-meta.hh3
-rw-r--r--thirdparty/harfbuzz/src/hb-ms-feature-ranges.hh2
-rw-r--r--thirdparty/harfbuzz/src/hb-multimap.hh92
-rw-r--r--thirdparty/harfbuzz/src/hb-mutex.hh7
-rw-r--r--thirdparty/harfbuzz/src/hb-number-parser.hh8
-rw-r--r--thirdparty/harfbuzz/src/hb-object.hh4
-rw-r--r--thirdparty/harfbuzz/src/hb-open-file.hh4
-rw-r--r--thirdparty/harfbuzz/src/hb-open-type.hh67
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-cff-common.hh156
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-cff1-table.hh10
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-cff2-table.hh11
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-cmap-table.hh224
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-color-cbdt-table.hh8
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-color-colr-table.hh113
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-face-table-list.hh28
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-font.cc5
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-layout-common.hh350
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-layout-gdef-table.hh4
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-layout-gsubgpos.hh258
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-layout.cc112
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-layout.hh7
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-map.cc79
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-map.hh16
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-math-table.hh8
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-meta-table.hh2
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-name-table.hh211
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-name.cc51
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-os2-table.hh23
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-post-table-v2subset.hh4
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-post-table.hh2
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape-normalize.cc2
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape.cc4
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape.hh2
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shaper-arabic.cc19
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shaper-default.cc2
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shaper-indic-machine.hh610
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shaper-indic-table.cc21
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shaper-indic.cc73
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shaper-khmer-machine.hh16
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shaper-khmer.cc21
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shaper-myanmar-machine.hh16
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shaper-myanmar.cc48
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shaper-syllabic.cc12
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shaper-syllabic.hh4
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shaper-thai.cc6
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shaper-use-machine.hh16
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shaper-use-table.hh270
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shaper-use.cc33
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shaper.hh2
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-stat-table.hh2
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-tag.cc2
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-var-avar-table.hh6
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-var-common.hh21
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-var-fvar-table.hh12
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-var-gvar-table.hh229
-rw-r--r--thirdparty/harfbuzz/src/hb-pool.hh12
-rw-r--r--thirdparty/harfbuzz/src/hb-priority-queue.hh14
-rw-r--r--thirdparty/harfbuzz/src/hb-repacker.hh27
-rw-r--r--thirdparty/harfbuzz/src/hb-sanitize.hh15
-rw-r--r--thirdparty/harfbuzz/src/hb-serialize.hh64
-rw-r--r--thirdparty/harfbuzz/src/hb-set-digest.hh35
-rw-r--r--thirdparty/harfbuzz/src/hb-set.hh6
-rw-r--r--thirdparty/harfbuzz/src/hb-shape-plan.cc7
-rw-r--r--thirdparty/harfbuzz/src/hb-shape.cc5
-rw-r--r--thirdparty/harfbuzz/src/hb-shaper.cc2
-rw-r--r--thirdparty/harfbuzz/src/hb-static.cc2
-rw-r--r--thirdparty/harfbuzz/src/hb-subset-accelerator.hh61
-rw-r--r--thirdparty/harfbuzz/src/hb-subset-cff-common.cc11
-rw-r--r--thirdparty/harfbuzz/src/hb-subset-cff-common.hh491
-rw-r--r--thirdparty/harfbuzz/src/hb-subset-cff1.cc38
-rw-r--r--thirdparty/harfbuzz/src/hb-subset-cff2.cc23
-rw-r--r--thirdparty/harfbuzz/src/hb-subset-input.cc141
-rw-r--r--thirdparty/harfbuzz/src/hb-subset-input.hh55
-rw-r--r--thirdparty/harfbuzz/src/hb-subset-plan.cc108
-rw-r--r--thirdparty/harfbuzz/src/hb-subset-plan.hh39
-rw-r--r--thirdparty/harfbuzz/src/hb-subset.cc95
-rw-r--r--thirdparty/harfbuzz/src/hb-subset.h17
-rw-r--r--thirdparty/harfbuzz/src/hb-ucd-table.hh2564
-rw-r--r--thirdparty/harfbuzz/src/hb-ucd.cc16
-rw-r--r--thirdparty/harfbuzz/src/hb-unicode.cc26
-rw-r--r--thirdparty/harfbuzz/src/hb-uniscribe.cc6
-rw-r--r--thirdparty/harfbuzz/src/hb-vector.hh100
-rw-r--r--thirdparty/harfbuzz/src/hb-version.h8
-rw-r--r--thirdparty/harfbuzz/src/hb.hh1
-rw-r--r--thirdparty/libpng/arm/arm_init.c5
-rw-r--r--thirdparty/libpng/png.c6
-rw-r--r--thirdparty/libpng/png.h16
-rw-r--r--thirdparty/libpng/pngconf.h2
-rw-r--r--thirdparty/libpng/pnglibconf.h2
-rw-r--r--thirdparty/libpng/pngpriv.h2
-rw-r--r--thirdparty/libpng/pngread.c4
-rw-r--r--thirdparty/libpng/pngrutil.c2
-rw-r--r--thirdparty/libpng/pngwrite.c8
-rw-r--r--thirdparty/libpng/pngwutil.c6
-rw-r--r--thirdparty/libtheora/LICENSE8
-rw-r--r--thirdparty/libtheora/analyze.c2283
-rw-r--r--thirdparty/libtheora/apiwrapper.c2
-rw-r--r--thirdparty/libtheora/apiwrapper.h2
-rw-r--r--thirdparty/libtheora/bitpack.c23
-rw-r--r--thirdparty/libtheora/bitpack.h27
-rw-r--r--thirdparty/libtheora/collect.c974
-rw-r--r--thirdparty/libtheora/collect.h109
-rw-r--r--thirdparty/libtheora/dct.h2
-rw-r--r--thirdparty/libtheora/decinfo.c40
-rw-r--r--thirdparty/libtheora/decint.h152
-rw-r--r--thirdparty/libtheora/decode.c1993
-rw-r--r--thirdparty/libtheora/dequant.c2
-rw-r--r--thirdparty/libtheora/dequant.h2
-rw-r--r--thirdparty/libtheora/encfrag.c159
-rw-r--r--thirdparty/libtheora/encinfo.c2
-rw-r--r--thirdparty/libtheora/encint.h502
-rw-r--r--thirdparty/libtheora/encode.c428
-rw-r--r--thirdparty/libtheora/encoder_disabled.c5
-rw-r--r--thirdparty/libtheora/enquant.c198
-rw-r--r--thirdparty/libtheora/enquant.h7
-rw-r--r--thirdparty/libtheora/fdct.c9
-rw-r--r--thirdparty/libtheora/fragment.c43
-rw-r--r--thirdparty/libtheora/huffdec.c694
-rw-r--r--thirdparty/libtheora/huffdec.h72
-rw-r--r--thirdparty/libtheora/huffenc.c112
-rw-r--r--thirdparty/libtheora/huffenc.h3
-rw-r--r--thirdparty/libtheora/huffman.h4
-rw-r--r--thirdparty/libtheora/idct.c59
-rw-r--r--thirdparty/libtheora/info.c10
-rw-r--r--thirdparty/libtheora/internal.c92
-rw-r--r--thirdparty/libtheora/internal.h445
-rw-r--r--thirdparty/libtheora/mathops.c68
-rw-r--r--thirdparty/libtheora/mathops.h44
-rw-r--r--thirdparty/libtheora/mcenc.c215
-rw-r--r--thirdparty/libtheora/modedec.h4389
-rw-r--r--thirdparty/libtheora/ocintrin.h2
-rw-r--r--thirdparty/libtheora/patches/theora.git-0ae66d565e6bead8604d312bc1a4e9dccf245c88.patch38
-rw-r--r--thirdparty/libtheora/quant.c10
-rw-r--r--thirdparty/libtheora/quant.h2
-rw-r--r--thirdparty/libtheora/rate.c26
-rw-r--r--thirdparty/libtheora/state.c298
-rw-r--r--thirdparty/libtheora/state.h552
-rw-r--r--thirdparty/libtheora/theora/codec.h77
-rw-r--r--thirdparty/libtheora/theora/theora.h114
-rw-r--r--thirdparty/libtheora/theora/theoradec.h22
-rw-r--r--thirdparty/libtheora/theora/theoraenc.h112
-rw-r--r--thirdparty/libtheora/tokenize.c1006
-rw-r--r--thirdparty/libtheora/x86/mmxencfrag.c284
-rw-r--r--thirdparty/libtheora/x86/mmxfdct.c127
-rw-r--r--thirdparty/libtheora/x86/mmxfrag.c81
-rw-r--r--thirdparty/libtheora/x86/mmxfrag.h64
-rw-r--r--thirdparty/libtheora/x86/mmxidct.c292
-rw-r--r--thirdparty/libtheora/x86/mmxloop.h271
-rw-r--r--thirdparty/libtheora/x86/mmxstate.c162
-rw-r--r--thirdparty/libtheora/x86/sse2encfrag.c501
-rw-r--r--thirdparty/libtheora/x86/sse2fdct.c111
-rw-r--r--thirdparty/libtheora/x86/sse2idct.c456
-rw-r--r--thirdparty/libtheora/x86/sse2trans.h242
-rw-r--r--thirdparty/libtheora/x86/x86cpu.c182
-rw-r--r--thirdparty/libtheora/x86/x86cpu.h (renamed from thirdparty/libtheora/cpu.h)10
-rw-r--r--thirdparty/libtheora/x86/x86enc.c34
-rw-r--r--thirdparty/libtheora/x86/x86enc.h93
-rw-r--r--thirdparty/libtheora/x86/x86enquant.c149
-rw-r--r--thirdparty/libtheora/x86/x86int.h96
-rw-r--r--thirdparty/libtheora/x86/x86state.c47
-rw-r--r--thirdparty/libtheora/x86/x86zigzag.h244
-rw-r--r--thirdparty/libtheora/x86_vc/mmxencfrag.c122
-rw-r--r--thirdparty/libtheora/x86_vc/mmxfdct.c128
-rw-r--r--thirdparty/libtheora/x86_vc/mmxfrag.c83
-rw-r--r--thirdparty/libtheora/x86_vc/mmxfrag.h61
-rw-r--r--thirdparty/libtheora/x86_vc/mmxidct.c230
-rw-r--r--thirdparty/libtheora/x86_vc/mmxstate.c75
-rw-r--r--thirdparty/libtheora/x86_vc/x86cpu.c (renamed from thirdparty/libtheora/cpu.c)60
-rw-r--r--thirdparty/libtheora/x86_vc/x86cpu.h36
-rw-r--r--thirdparty/libtheora/x86_vc/x86enc.c14
-rw-r--r--thirdparty/libtheora/x86_vc/x86enc.h22
-rw-r--r--thirdparty/libtheora/x86_vc/x86int.h23
-rw-r--r--thirdparty/libtheora/x86_vc/x86state.c11
-rw-r--r--thirdparty/libtheora/x86_vc/x86zigzag.h244
-rw-r--r--thirdparty/mbedtls/include/mbedtls/asn1write.h2
-rw-r--r--thirdparty/mbedtls/include/mbedtls/bignum.h69
-rw-r--r--thirdparty/mbedtls/include/mbedtls/bn_mul.h32
-rw-r--r--thirdparty/mbedtls/include/mbedtls/check_config.h30
-rw-r--r--thirdparty/mbedtls/include/mbedtls/config.h15
-rw-r--r--thirdparty/mbedtls/include/mbedtls/ecdsa.h4
-rw-r--r--thirdparty/mbedtls/include/mbedtls/md.h2
-rw-r--r--thirdparty/mbedtls/include/mbedtls/platform.h7
-rw-r--r--thirdparty/mbedtls/include/mbedtls/ripemd160.h2
-rw-r--r--thirdparty/mbedtls/include/mbedtls/rsa.h2
-rw-r--r--thirdparty/mbedtls/include/mbedtls/ssl.h6
-rw-r--r--thirdparty/mbedtls/include/mbedtls/ssl_internal.h2
-rw-r--r--thirdparty/mbedtls/include/mbedtls/version.h8
-rw-r--r--thirdparty/mbedtls/library/aes.c12
-rw-r--r--thirdparty/mbedtls/library/arc4.c7
-rw-r--r--thirdparty/mbedtls/library/aria.c61
-rw-r--r--thirdparty/mbedtls/library/asn1parse.c6
-rw-r--r--thirdparty/mbedtls/library/asn1write.c12
-rw-r--r--thirdparty/mbedtls/library/base64.c5
-rw-r--r--thirdparty/mbedtls/library/bignum.c230
-rw-r--r--thirdparty/mbedtls/library/camellia.c7
-rw-r--r--thirdparty/mbedtls/library/ccm.c7
-rw-r--r--thirdparty/mbedtls/library/chacha20.c12
-rw-r--r--thirdparty/mbedtls/library/chachapoly.c7
-rw-r--r--thirdparty/mbedtls/library/cipher.c5
-rw-r--r--thirdparty/mbedtls/library/cipher_wrap.c6
-rw-r--r--thirdparty/mbedtls/library/common.h45
-rw-r--r--thirdparty/mbedtls/library/constant_time.c11
-rw-r--r--thirdparty/mbedtls/library/constant_time_internal.h9
-rw-r--r--thirdparty/mbedtls/library/ctr_drbg.c7
-rw-r--r--thirdparty/mbedtls/library/debug.c14
-rw-r--r--thirdparty/mbedtls/library/des.c7
-rw-r--r--thirdparty/mbedtls/library/dhm.c8
-rw-r--r--thirdparty/mbedtls/library/ecdh.c6
-rw-r--r--thirdparty/mbedtls/library/ecdsa.c6
-rw-r--r--thirdparty/mbedtls/library/ecjpake.c5
-rw-r--r--thirdparty/mbedtls/library/ecp.c55
-rw-r--r--thirdparty/mbedtls/library/ecp_curves.c5
-rw-r--r--thirdparty/mbedtls/library/entropy.c9
-rw-r--r--thirdparty/mbedtls/library/entropy_poll.c2
-rw-r--r--thirdparty/mbedtls/library/error.c6
-rw-r--r--thirdparty/mbedtls/library/gcm.c10
-rw-r--r--thirdparty/mbedtls/library/hmac_drbg.c7
-rw-r--r--thirdparty/mbedtls/library/md.c6
-rw-r--r--thirdparty/mbedtls/library/md2.c7
-rw-r--r--thirdparty/mbedtls/library/md4.c7
-rw-r--r--thirdparty/mbedtls/library/md5.c7
-rw-r--r--thirdparty/mbedtls/library/mps_reader.c7
-rw-r--r--thirdparty/mbedtls/library/mps_trace.h6
-rw-r--r--thirdparty/mbedtls/library/net_sockets.c4
-rw-r--r--thirdparty/mbedtls/library/nist_kw.c7
-rw-r--r--thirdparty/mbedtls/library/oid.c4
-rw-r--r--thirdparty/mbedtls/library/pem.c6
-rw-r--r--thirdparty/mbedtls/library/pk_wrap.c8
-rw-r--r--thirdparty/mbedtls/library/pkcs11.c6
-rw-r--r--thirdparty/mbedtls/library/pkcs5.c5
-rw-r--r--thirdparty/mbedtls/library/pkparse.c6
-rw-r--r--thirdparty/mbedtls/library/pkwrite.c6
-rw-r--r--thirdparty/mbedtls/library/poly1305.c12
-rw-r--r--thirdparty/mbedtls/library/ripemd160.c7
-rw-r--r--thirdparty/mbedtls/library/rsa.c7
-rw-r--r--thirdparty/mbedtls/library/sha1.c7
-rw-r--r--thirdparty/mbedtls/library/sha256.c10
-rw-r--r--thirdparty/mbedtls/library/sha512.c14
-rw-r--r--thirdparty/mbedtls/library/ssl_cache.c6
-rw-r--r--thirdparty/mbedtls/library/ssl_ciphersuites.c4
-rw-r--r--thirdparty/mbedtls/library/ssl_cli.c94
-rw-r--r--thirdparty/mbedtls/library/ssl_cookie.c5
-rw-r--r--thirdparty/mbedtls/library/ssl_msg.c25
-rw-r--r--thirdparty/mbedtls/library/ssl_srv.c24
-rw-r--r--thirdparty/mbedtls/library/ssl_ticket.c42
-rw-r--r--thirdparty/mbedtls/library/ssl_tls.c79
-rw-r--r--thirdparty/mbedtls/library/ssl_tls13_keys.c8
-rw-r--r--thirdparty/mbedtls/library/timing.c7
-rw-r--r--thirdparty/mbedtls/library/x509.c52
-rw-r--r--thirdparty/mbedtls/library/x509_crl.c10
-rw-r--r--thirdparty/mbedtls/library/x509_crt.c46
-rw-r--r--thirdparty/mbedtls/library/x509_csr.c8
-rw-r--r--thirdparty/mbedtls/library/x509write_csr.c6
-rw-r--r--thirdparty/mbedtls/library/xtea.c9
-rw-r--r--thirdparty/mbedtls/patches/1453.diff28
-rw-r--r--thirdparty/mbedtls/patches/windows-arm64-hardclock.diff16
-rw-r--r--thirdparty/miniupnpc/LICENSE39
-rw-r--r--thirdparty/miniupnpc/include/miniupnpc.h8
-rw-r--r--thirdparty/miniupnpc/src/miniupnpcstrings.h2
-rw-r--r--thirdparty/miniupnpc/src/minixml.c2
-rw-r--r--thirdparty/openxr/include/openxr/openxr.h177
-rw-r--r--thirdparty/openxr/include/openxr/openxr_reflection.h490
-rw-r--r--thirdparty/openxr/include/openxr/openxr_reflection_parent_structs.h261
-rw-r--r--thirdparty/openxr/include/openxr/openxr_reflection_structs.h427
-rw-r--r--thirdparty/openxr/src/loader/loader_core.cpp4
-rw-r--r--thirdparty/openxr/src/loader/manifest_file.cpp12
-rw-r--r--thirdparty/openxr/src/xr_generated_dispatch_table.c14
-rw-r--r--thirdparty/openxr/src/xr_generated_dispatch_table.h14
-rw-r--r--thirdparty/recastnavigation/Recast/Include/Recast.h25
-rw-r--r--thirdparty/recastnavigation/Recast/Include/RecastAlloc.h6
-rw-r--r--thirdparty/recastnavigation/Recast/Source/Recast.cpp5
-rw-r--r--thirdparty/recastnavigation/Recast/Source/RecastMesh.cpp2
-rw-r--r--thirdparty/recastnavigation/Recast/Source/RecastMeshDetail.cpp2
-rw-r--r--thirdparty/recastnavigation/Recast/Source/RecastRasterization.cpp12
-rw-r--r--thirdparty/thorvg/inc/config.h2
-rw-r--r--thirdparty/thorvg/inc/thorvg.h18
-rw-r--r--thirdparty/thorvg/src/lib/sw_engine/tvgSwRaster.cpp6
-rw-r--r--thirdparty/thorvg/src/lib/sw_engine/tvgSwRasterTexmapInternal.h2
-rw-r--r--thirdparty/thorvg/src/lib/tvgLoadModule.h1
-rw-r--r--thirdparty/thorvg/src/loaders/jpg/tvgJpgLoader.cpp6
-rw-r--r--thirdparty/thorvg/src/loaders/jpg/tvgJpgd.cpp2
-rw-r--r--thirdparty/thorvg/src/loaders/raw/tvgRawLoader.cpp6
-rw-r--r--thirdparty/thorvg/src/loaders/svg/tvgSvgCssStyle.cpp20
-rw-r--r--thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.cpp164
-rw-r--r--thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.h3
-rw-r--r--thirdparty/thorvg/src/loaders/svg/tvgSvgLoaderCommon.h26
-rw-r--r--thirdparty/thorvg/src/loaders/svg/tvgSvgSceneBuilder.cpp148
-rw-r--r--thirdparty/thorvg/src/loaders/svg/tvgSvgSceneBuilder.h2
-rw-r--r--thirdparty/thorvg/src/loaders/svg/tvgXmlParser.cpp6
-rw-r--r--thirdparty/thorvg/src/loaders/tvg/tvgTvgBinInterpreter.cpp6
-rw-r--r--thirdparty/thorvg/src/savers/tvg/tvgTvgSaver.cpp6
-rwxr-xr-xthirdparty/thorvg/update-thorvg.sh5
2143 files changed, 112415 insertions, 63309 deletions
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index 7dfc3bccc3..031582bc63 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -118,13 +118,12 @@ doc_classes/* @godotengine/documentation
## Text
/modules/freetype/ @godotengine/buildsystem
-/modules/gdnative/text/ @godotengine/gui-nodes
/modules/text_server_adv/ @godotengine/gui-nodes
/modules/text_server_fb/ @godotengine/gui-nodes
## XR
/modules/camera/ @godotengine/xr
-/modules/gdnative/xr/ @godotengine/xr
+/modules/gdextension/xr/ @godotengine/xr
/modules/mobile_vr/ @godotengine/xr
/modules/webxr/ @godotengine/xr
diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml
index 690e74855f..0b4abac1af 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.yml
+++ b/.github/ISSUE_TEMPLATE/bug_report.yml
@@ -52,5 +52,8 @@ body:
attributes:
label: Minimal reproduction project
description: |
- A small Godot project which reproduces the issue. Highly recommended to speed up troubleshooting.
- Drag and drop a ZIP archive to upload it. Be sure to not include the ".godot" folder in the archive.
+ A small Godot project which reproduces the issue, with no unnecessary files included. Be sure to not include the `.godot` folder in the archive (but keep `project.godot`).
+ Required, unless the reproduction steps are trivial and don't require any project files to be followed. In this case, write "N/A" in the field.
+ Drag and drop a ZIP archive to upload it. **Do not select another field until the project is done uploading.**
+ validations:
+ required: true
diff --git a/.github/workflows/linux_builds.yml b/.github/workflows/linux_builds.yml
index 95d216deb3..84fdb2180b 100644
--- a/.github/workflows/linux_builds.yml
+++ b/.github/workflows/linux_builds.yml
@@ -32,11 +32,11 @@ jobs:
proj-conv: true
artifact: true
- - name: Editor with doubles and GCC sanitizers (target=editor, tests=yes, dev_build=yes, float=64, use_asan=yes, use_ubsan=yes, linker=gold)
+ - name: Editor with doubles and GCC sanitizers (target=editor, tests=yes, dev_build=yes, precision=double, use_asan=yes, use_ubsan=yes, linker=gold)
cache-name: linux-editor-double-sanitizers
target: editor
tests: true
- sconsflags: dev_build=yes float=64 use_asan=yes use_ubsan=yes linker=gold
+ sconsflags: dev_build=yes precision=double 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.
@@ -198,20 +198,13 @@ jobs:
submodules: 'recursive'
path: 'godot-cpp'
- # Check extension API
- - name: Check for extension api updates
+ # Dump GDExtension interface and API
+ - name: Dump GDExtension interface and API for godot-cpp build
if: ${{ matrix.godot-cpp-test }}
run: |
- echo "Running --dump-extension-api to create extensions api."
- VK_ICD_FILENAMES=$(pwd)/vk_swiftshader_icd.json DRI_PRIME=0 xvfb-run ${{ matrix.bin }} --audio-driver Dummy --dump-extension-api 2>&1 > /dev/null || true
- misc/scripts/compare_extension_api.py godot-cpp/godot-headers/extension_api.json extension_api.json
-
- # Copy new extension API files into place
- - name: Copy new extension API files into place
- if: ${{ matrix.godot-cpp-test }}
- run: |
- cp -f extension_api.json godot-cpp/godot-headers/
- cp -f core/extension/gdnative_interface.h godot-cpp/godot-headers/godot/
+ ${{ matrix.bin }} --headless --dump-gdextension-interface --dump-extension-api
+ cp -f gdextension_interface.h godot-cpp/gdextension/
+ cp -f extension_api.json godot-cpp/gdextension/
# Build godot-cpp test extension
- name: Build godot-cpp test extension
diff --git a/.gitignore b/.gitignore
index ca7d850f9e..ca96220570 100644
--- a/.gitignore
+++ b/.gitignore
@@ -37,7 +37,7 @@ platform/windows/godot_res.res
# Generated by Godot binary
.import/
-/gdnative_interface.h
+/gdextension_interface.h
extension_api.json
logs/
@@ -242,6 +242,10 @@ xcuserdata/
[Rr]eleases/
x64/
x86/
+
+# Do not ignore x86 folders anywhere under thirdparty libraries
+!thirdparty/**/x86/
+
[Ww][Ii][Nn]32/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
@@ -318,6 +322,7 @@ _ReSharper*/
# Others
ClientBin/
+enc_temp_folder/
~$*
*.dbmdl
*.dbproj.schemaview
diff --git a/.mailmap b/.mailmap
index 4976c96ba9..aa57299278 100644
--- a/.mailmap
+++ b/.mailmap
@@ -2,6 +2,7 @@ Aaron Record <aaronjrecord@gmail.com>
Alexander Holland <alexander.holland@live.de>
Alexander Holland <alexander.holland@live.de> <alexander.holland@haw-hamburg.de>
Alexander Holland <alexander.holland@live.de> <AlexHolly>
+Alfred Reinold Baudisch <alfred@alfredbaudisch.com>
Andrea Catania <info@andreacatania.com>
Anish Bhobe <anishbhobe@hotmail.com>
Anutrix <numaanzaheerahmed@yahoo.com>
@@ -26,6 +27,7 @@ dankan1890 <mewuidev2@gmail.com>
Daniel J. Ramirez <djrmuv@gmail.com>
David Cambré <david.cambre@gmail.com> <David.Cambre@gmail.com>
Dominik 'dreamsComeTrue' Jasiński <dominikjasinski@o2.pl>
+DeeJayLSP <djlsplays@gmail.com> <60024671+DeeJayLSP@users.noreply.github.com>
Emmanuel Barroga <emmanuelbarroga@gmail.com>
Eric M <itsjusteza@gmail.com>
Eric Rybicki <info@ericrybicki.com> <stratos695@googlemail.com>
@@ -41,6 +43,7 @@ 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>
+Fredia Huya-Kouadio <fhuyakou@gmail.com> <fhuya@meta.com>
Geequlim <geequlim@gmail.com>
Gilles Roudiere <gilles.roudiere@gmail.com>
Gilles Roudiere <gilles.roudiere@gmail.com> <gilles.roudiere@laas.fr>
@@ -112,6 +115,7 @@ Nils ANDRÉ-CHANG <nils@nilsand.re> <nils.andre.chang@gmail.com>
Nuno Donato <nunodonato@gmail.com> <n.donato@estrelasustentavel.pt>
Pawel Kowal <pkowal1982@gmail.com>
Pedro J. Estébanez <pedrojrulez@gmail.com> <RandomShaper@users.noreply.github.com>
+Patrick <firefly2442@gmail.com>
Paul Batty <p_batty@hotmail.co.uk>
Paul Batty <p_batty@hotmail.co.uk> <Paulb23@users.noreply.github.com>
Pawel Kowal <pkowal1982@gmail.com> <pawel.kowal@javart.eu>
@@ -131,14 +135,18 @@ 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>
+Riteo Siuga <riteo@posteo.net>
Robin Hübner <profan@prfn.se> <robinhubner@gmail.com>
romulox_x <romulox_x@yahoo.com>
+rune-scape <allie.smith.epic@gmail.com>
+rune-scape <allie.smith.epic@gmail.com> <spartacrafter@gmail.com>
Ruslan Mustakov <r.mustakov@gmail.com> <ruslan.mustakov@xored.com>
Saracen <SaracenOne@gmail.com>
sheepandshepherd <sheepandshepherd@hotmail.com> <sheepandshepherd@users.noreply.github.com>
Silc 'Tokage' Renew <tokage.it.lab@gmail.com>
Silc 'Tokage' Renew <tokage.it.lab@gmail.com> <61938263+TokageItLab@users.noreply.github.com>
Swarnim Arun <swarnimarun11@gmail.com>
+TechnoPorg <jonah.janzen@gmail.com> <69441745+TechnoPorg@users.noreply.github.com>
Theo Hallenius <redsymbzone@hotmail.com>
Tomasz Chabora <kobewi4e@gmail.com>
Twarit <wtwarit@gmail.com>
diff --git a/AUTHORS.md b/AUTHORS.md
index 6f6ac48db2..7079180274 100644
--- a/AUTHORS.md
+++ b/AUTHORS.md
@@ -29,8 +29,10 @@ name is available.
Aaron Franke (aaronfranke)
Aaron Record (LightningAA)
+ Adam Scott (adamscott)
Alexander Holland (AlexHolly)
Alexey Khoroshavin (allkhor)
+ Alfred Reinold Baudisch (alfredbaudisch)
Alket Rexhepi (alketii)
Andrea Catania (AndreaCatania)
Andrii Doroshenko (Xrayez)
@@ -64,6 +66,7 @@ name is available.
Dana Olson (adolson)
Daniel J. Ramirez (djrm)
Daniel Rakos (aqnuep)
+ Daniel Zilberleyb (dzil123)
Danil Alexeev (dalexeev)
dankan1890
David Cambré (Gallilus)
@@ -72,6 +75,7 @@ name is available.
Dharkael (lupoDharkael)
Dmitry Koteroff (Krakean)
Dominik Jasiński (dreamsComeTrue)
+ Douglas Leão (DeeJayLSP)
DualMatrix
Ellen Poe (ellenhp)
Emmanuel Barroga (codecustard)
@@ -118,13 +122,16 @@ name is available.
Jake Young (Duroxxigar)
Jakub Grzesik (kubecz3k)
James Buck (jbuck3)
+ Jason Knight (jasonwinterpixel)
Jean-Michel Bernard (jmb462)
Jérôme Gully (Nutriz)
Jia Jun Chai (SkyLucilfer)
Joan Fons Sanchez (JFonS)
Johan Manuel (29jm)
Johannes Witt (HaSa1002)
+ Jonathan Nicholl (jtnicholl)
Jordan Schidlowsky (winterpixelgames)
+ Josh Jones (DarkKilauea)
Joshua Grams (JoshuaGrams)
Juan Linietsky (reduz)
Julian Murgia (StraToN)
@@ -180,6 +187,7 @@ name is available.
Nathan Lovato (NathanLovato)
Nathan Warden (NathanWarden)
Nicholas Huelin (SirQuartz)
+ Nikita Lita (nikitalita)
Nils André-Chang (NilsIrl)
Noah Beard (TwistedTwigleg)
Nuno Donato (nunodonato)
@@ -210,9 +218,11 @@ name is available.
Rhody Lugo (rraallvv)
Ricardo Buring (rburing)
Ricardo Subtil (Ev1lbl0w)
+ Riteo Siuga (Riteo)
Roberto F. Arroyo (robfram)
Robin Hübner (profan)
romulox-x
+ Rune Smith (rune-scape)
Ruslan Mustakov (endragor)
Ryan Roden-Corrent (rrcore)
Saniko (sanikoyes)
@@ -227,6 +237,7 @@ name is available.
Stijn Hinlopen (hinlopen)
Swarnim Arun (minraws)
TC (floppyhammer)
+ TechnoPorg
Thakee Nathees (ThakeeNathees)
thebestnom
Theo Hallenius (TheoXD)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index a1e8d3a59d..63e6a89e64 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -63,6 +63,8 @@ understand that:
- What happens to you may not happen to other users.
- We can't take the time to look at your project, understand how it is set up
and then figure out why it's failing.
+- On the contributors' end, recreating a test project from scratch takes valuable
+ time that can be saved by uploading a *minimal* project.
To speed up our work, **please upload a minimal project** that isolates
and reproduces the issue. This is always the **best way for us to fix it**.
@@ -74,7 +76,7 @@ if your ZIP file isn't accepted by GitHub because it's too large.
We recommend always attaching a minimal reproduction project, even if the issue
may seem simple to reproduce manually.
-**Note for C# users:** If your issue is not .NET-specific, please upload a
+**Note for C# users:** If your issue is *not* .NET-specific, please upload a
minimal reproduction project written in GDScript.
This will make it easier for contributors to reproduce the issue
locally as not everyone has a .NET setup available.
diff --git a/COPYRIGHT.txt b/COPYRIGHT.txt
index 3f4981b7fb..d41f40a78b 100644
--- a/COPYRIGHT.txt
+++ b/COPYRIGHT.txt
@@ -202,6 +202,12 @@ Comment: The FreeType Project
Copyright: 1996-2022, David Turner, Robert Wilhelm, and Werner Lemberg.
License: FTL
+Files: ./thirdparty/glad/
+Comment: glad
+Copyright: 2013-2022, David Herberth
+ 2013-2020, The Khronos Group Inc.
+License: CC0-1.0 and Apache-2.0
+
Files: ./thirdparty/glslang/
Comment: glslang
Copyright: 2015-2020, Google, Inc.
@@ -212,7 +218,7 @@ License: glslang
Files: ./thirdparty/graphite/
Comment: Graphite engine
Copyright: 2010, SIL International
-License: MPL-2.0
+License: Expat
Files: ./thirdparty/harfbuzz/
Comment: HarfBuzz text shaping library
@@ -287,7 +293,7 @@ License: CC0-1.0
Files: ./thirdparty/miniupnpc/
Comment: MiniUPnP Project
-Copyright: 2005-2021, Thomas Bernard
+Copyright: 2005-2022, Thomas Bernard
License: BSD-3-clause
Files: ./thirdparty/minizip/
diff --git a/DONORS.md b/DONORS.md
index 04b4352b0e..5ce096b778 100644
--- a/DONORS.md
+++ b/DONORS.md
@@ -13,6 +13,7 @@ generous deed immortalized in the next stable release of Godot Engine.
## Platinum sponsors
Gamblify <https://www.gamblify.com>
+ Heroic Labs <https://heroiclabs.com>
Spiffcode <http://spiffcode.com>
## Gold sponsors
@@ -25,20 +26,24 @@ generous deed immortalized in the next stable release of Godot Engine.
ASIFA-Hollywood <https://www.asifa-hollywood.org>
Playful Studios <https://playfulstudios.com>
Robot Gentleman <http://robotgentleman.com>
+ Striked <https://developers.join-striked.com>
## Bronze sponsors
Basically Games
+ Bippinbits <https://bippinbits.com>
Brandon Lamb
Bri
Garry Newman
Gordon MacPherson
Hunter Dickson
Isaiah smith
+ Jb Evain
Keepsake Games <https://keepsake.games>
Kenney <https://kenney.nl>
Kitcat490
Kyle Szklenski
+ Matthew Campbell
Maxim Karsten
Moonwards <https://www.moonwards.com>
Nik Rudenko
@@ -49,12 +54,12 @@ generous deed immortalized in the next stable release of Godot Engine.
AD Ford
Albin Lundahl
Andres Hernandez
- Andrew Bowen
Andrew Dunai
anti666
Christian Baune
Christopher Montesano
Christopher Shifflett
+ Christoph Woinke
Daniel Edwards
Darrin Massena
David Mydlarz
@@ -68,6 +73,7 @@ generous deed immortalized in the next stable release of Godot Engine.
Justin Arnold
Justo Delgado Baudí
Kossi Selom Banybah
+ Lloyd Bond
Marcel Kräml
Marek Belski
Markus Ort
@@ -75,13 +81,13 @@ generous deed immortalized in the next stable release of Godot Engine.
Michael
Mike King
Nassor Paulino da Silva
+ nate-wilkins
Nathan Warden
Neal Gompa (Conan Kudo)
Ninja_5tyl3
Patrick Horn
Patrick Schmidt
Rami
- René Habermann
Ronnie Cheng
Ryan Heath
Samantha
@@ -106,13 +112,14 @@ generous deed immortalized in the next stable release of Godot Engine.
Benito
Carlo Cabanilla
Daniel James
+ David Fedorchak
David Gehrig
David Hubber
David Snopek
Ed Morley
First Last
Frank Kurka
- Hunter Jones
+ Guy Kay Jay
Jacobus Dens
Javier Roman
Joan Fons
@@ -124,19 +131,17 @@ generous deed immortalized in the next stable release of Godot Engine.
Manuele Finocchiaro
Markus Wiesner
Mateo Navarrete
- Mathieu
Matthew Hillier
- Mert Kasar
Officine Pixel S.n.c.
Pedro Silva
Retro Village
Rob Messick
Roland Fredenhagen
Ronan Zeegers
+ Rudi
Sarksus
Sean
Sergey
- Sergio Airaldi
Sofox
Stephan Kessler
Stephen Molyneaux
@@ -148,11 +153,9 @@ generous deed immortalized in the next stable release of Godot Engine.
Victor
Xeno Coliseum
+ â£
23BLUENINJA
- Adam Mill
- Adam Nakonieczny
- Adam Nelson
- Adam Stankiewicz
+ AdamRatai
Alexander Erlemann
Alexandre VALIN
Alexej Kowalew
@@ -164,6 +167,7 @@ generous deed immortalized in the next stable release of Godot Engine.
Andriy
Antanas Paskauskas
Antoni Batchelli
+ Ari
Arthur S. Muszynski
BasicIncomePlz
Brandon Hawkinson
@@ -178,14 +182,14 @@ generous deed immortalized in the next stable release of Godot Engine.
Craig Smith
Cristopher
CT
- CzechBlueBear
+ CzechBlueBea
+ CzłowiekImadło
Daniel Reed
Daniel Tebbutt
Darrian Little
- David Thomason
+ DATSAGE
Daylon J Williams
Dennis Belfrage
- Dimitri Nüscheler
Donn Eddy
Duncan
Eric Brand
@@ -194,9 +198,7 @@ generous deed immortalized in the next stable release of Godot Engine.
flesk
foxydevloper
Fransiska
- FroggEater
Gabrielius Vaiškūnas
- Garpur
Gary Hulst
Geoffroy Warin
George Venizelos
@@ -209,8 +211,6 @@ generous deed immortalized in the next stable release of Godot Engine.
Heath Hayes
Horváth-Lázár Péter
Hu Hund
- Hunter Barabas
- ihereou
illuxxium
Jaap Marsman
Jamal Bencharki
@@ -225,22 +225,17 @@ generous deed immortalized in the next stable release of Godot Engine.
Johnathan Kupferer
John Stinson
Josef Stumpfegger
- Jose Manuel Muñoz Perez
Joshie Sparks
Joshua Flores
Joshua Lesperance
Juan Velandia
Judd
Julian Todd
- Juraj Móza
JUSTIN CARROLL
- Justin Palmer
Kelteseth
- Kevan
Khora
kickmaniac
kinfox
- Lakshaya Goel
Laszlo Kiss
leetNightshade
Leo Fidel R Liban
@@ -264,26 +259,24 @@ generous deed immortalized in the next stable release of Godot Engine.
Michael Policastro
MikadoSC
nate etan
+ Nicola Cocchiaro
Nikita Blizniuk
Oliver Dick
- Oscar Campos
Otis Clark
+ Patrick Wuttke
Paul Hocker
Paul Von Zimmerman
- Pedro
Pete Goodwin
Petr Malac
Petrus Prinsloo
Philip Woods
- R
- RaiRu
RAMupgrade
+ red1939
Reilt
Rene Tailleur
Rhodochrone
Rickard Hermanson
Rob
- Robert McDermott
Rob McInroy
RodZilla
Romeo Disca
@@ -297,11 +290,8 @@ generous deed immortalized in the next stable release of Godot Engine.
Samuel Hummerstone
Samuel Judd
schroedinger's possum
- Serban Serafimescu
- Sergey Fonaryov
Shishir Tandale
Sing Chun Lee
- Skides
SKison
Song Junwoo
spacechase0
@@ -309,6 +299,7 @@ generous deed immortalized in the next stable release of Godot Engine.
Steven Landow
Stoned Xander
Sven Carstensen
+ Talii
Teslatech
Thomas Bjarnelöf
Thomas Kurz
@@ -321,17 +312,17 @@ generous deed immortalized in the next stable release of Godot Engine.
Turntsnaco
UltyX
Valryia
- Vincent Cloutier
VoidPointer
+ whatever
Winston
- Wojciech Chojnacki
Yifan Lai
Yuancheng Zhang
+ zkip lan
## Silver donors
+ Aaron Mayfield
Aaron Oldenburg
- A. B.
Adam Brunnmeier
Adam Carr
Adam Long
@@ -353,18 +344,17 @@ generous deed immortalized in the next stable release of Godot Engine.
Alejandro Saucedo
AleMax
Alessandro Senese
- Alex Chan
Alex Clavelle
+ Alex de la Mare
alex raeside
Allan Davis
- Allen Schade
Amar Šahinović
Andre Altmueller
Andrei Pufu
Andre Stackhouse
+ Andrew
Andrew Groot
andrew james morris
- Andrew Thomas
angrykoala
Ano Nim
Anthony Avina
@@ -373,28 +363,23 @@ generous deed immortalized in the next stable release of Godot Engine.
Arda Erol
Arthur Brainville
Arturo Rosales
- Ashley Claymore
Aubrey Falconer
Auré Franky
aurelien condomines
- Austin Finlinson
Austin Miller
Azar Gurbanov
AzulCrescent
Balázs Batári
Beau Seymour
- Behzad Ghaffari
Benedikt
Ben Vercammen
Ben Visness
- Bernd Jänichen
Bernhard Werner
Bill Thibault
bitbrain
Bjarne Voigtländer
Black Block
Blunderjack
- BoiLudens
Bram
Brian
Brian Ford
@@ -402,15 +387,16 @@ generous deed immortalized in the next stable release of Godot Engine.
Bronson Zgeb
bugcaptor
Burney Waring
- Caleb Gartner
Caleb Makela
Caliburn
Cameron Meyer
Carlos Rios
Carl van der Geest
Casey
+ Cesar Ruiz
Chad Steadman
Checkpoint Charlie
+ Chris Cavalluzzi
Chris Jagusch
Chris Langford
Chris Ridenour
@@ -420,8 +406,6 @@ generous deed immortalized in the next stable release of Godot Engine.
Christian Winter
Christoffer Dahlblom
Christophe Gagnier
- Christoph Woinke
- codedius
Codex404
Cody Parker
Conall O
@@ -429,26 +413,23 @@ generous deed immortalized in the next stable release of Godot Engine.
Corchari
Corey W
Craig Post
+ CrimsonZA
CrispyPin
- Cullen Canejo
cynwav
Dakota Watkins
Daniel H. Bahr
- Danielle Cheney
+ Danielle
Dare Looks
Daren Scot Wilson
- Dave Walker
+ Davesnothere
David Baker
David Bôle
David May
David Maziarka
- David Rapisarda
Devin Carraway
Devin R
Dimitri Roche
- Dmytro Korchynskyi
Dominik Wetzel
- Don B
Donovan Hutcheon
Douglas Plumley
Dragontrapper
@@ -460,7 +441,6 @@ generous deed immortalized in the next stable release of Godot Engine.
Edward Herbert
Edward Swartz
Egon Elbre
- Elgenzay
Elias Nykrem
Elijah Anderson
Emerson MX
@@ -469,20 +449,15 @@ generous deed immortalized in the next stable release of Godot Engine.
Eric Stokes
Eric Walkingshaw
Eric Williams
- Erika Sanders
Erkki Seppälä
Ewan Holmes
- EZL games
Faisal Alkubaisi
Fault Boy
fby
- Fekinox
Felix Adam
- Felix Bohmann
Fer DC
Filip Lundby
Frank
- FrostMarble
fumangy
Game Endeavor
Gary Thomas
@@ -497,18 +472,14 @@ generous deed immortalized in the next stable release of Godot Engine.
Guo Hongci
Hans Jorgensen
Haplo
- Hayden Foley
Heribert Hirth
Hylian Ensemble
Ian Richard Kunert
Ian Williams
- IndustrialRobot
- Inki Crow
Interstice
iveks
Jacob D
Jaguar
- JAJAJA JA
Jake D
Jako Danar
James
@@ -518,40 +489,33 @@ generous deed immortalized in the next stable release of Godot Engine.
James Thomas
Jamie Massey
Janis Skuja
- JanPaul Bergeson
Jan Vetulani
JARKKO PARVIAINEN
- Jason Bolton
Jason Evans
Jason Uechi
Jeff Hungerford
Jeffrey Berube
Jennifer Graves
- Jeramie
Jesse Dubay
João Pedro Braz
Joe Hurdle
Joe Klemmer
- John Anders Stav
John Barlex
John Bruce
+ John Palgut
Jonas
Jonas Arndt
Jonas Bernemann
+ Jonas LHOSTE
Jonas Rudlang
Jonas Yamazaki
- Jonatan R
Jonathan Bieber
Jonathan Ellis
Jonathan G
- Jon Oakes
Jon Sully
- Jordan West
Jordy Goodridge
- Jorge Antunes
Jose Francisco 'Yiro' Vera Girona
Joseph Catrambone
- Josh P
Josh Segall
Josh Taylor
Joshua Heidrich
@@ -563,12 +527,11 @@ generous deed immortalized in the next stable release of Godot Engine.
Julian Murgia
Justin Hamilton
Justin Spedding
- KaDokta
+ Justin Zander
Kalydi Balázs
Katsuomi Kobayashi
Keedong Park
Keegan Scott
- Keinan Powers
Keith Bradner
Kenji Kawabata
Ken Minardo
@@ -576,22 +539,19 @@ generous deed immortalized in the next stable release of Godot Engine.
Kerotasma
Ketafuki
killaQueen
+ kimbring2
Kodera Software
Kolandrious
- Kristian Nygaard Jensen
KsyTek Games
kycho
Kyle Burnett
Kyle Jacobs
- Kyle Szklenski
Lasse le Dous
Laurent CHEA
Laurent Dethoor
Laxman Pradhan
Lech Rozanski
Leland Vakarian
- Lemin
- LEMMiNO
Leonardo Baumle
Levi Lindsey
LF
@@ -605,7 +565,7 @@ generous deed immortalized in the next stable release of Godot Engine.
Luke Kasz
Major Haul
Malcolm
- Marco Lardelli
+ Mara Huldra
Marcos Heitor Carvalho
Markie Music
Mark Jad
@@ -614,7 +574,6 @@ generous deed immortalized in the next stable release of Godot Engine.
Markus Michael Egger
Markus Strompen
Martin Holas
- Martin Linklater
Martin Liška
Martin Trbola
Martin Zabinski
@@ -623,14 +582,11 @@ generous deed immortalized in the next stable release of Godot Engine.
Matthew Booe
Maverick
Maxime Blade
- Maxime Santerre
Maxwell
McStuffings
- Melchor Morales
+ Melchor
Melissa Mears
- Merlyn Morgan-Graham
Metal Demon 2000
- mhilbrunner
Michael
Michael Haney
Michael Morrison
@@ -640,6 +596,7 @@ generous deed immortalized in the next stable release of Godot Engine.
Mikayla
Mike Birkhead
Mike Copley
+ Mike McRoberts
Miss
Mitchell J. Wagner
MJacred
@@ -652,23 +609,17 @@ generous deed immortalized in the next stable release of Godot Engine.
MrAZIE
Mrjemandem
Nathaniel
- neighty
+ neguse
Neil Blakey-Milner
Neil Wang
Nerdforge
Nerdyninja
Nicholas La Roux
- Nicholas Orlowski
Nick Eldrenkamp
Nick Macholl
Nico Greve
- Nicolas Goll-Perrier
Nicolas Rosset
- Nicolò Brigadoi Calamari
Nils Nordmark
- Nima Farid
- Noah Shomette
- Noel Billig
Noesis
obscuresteel
Okatima
@@ -676,13 +627,10 @@ generous deed immortalized in the next stable release of Godot Engine.
Oliver Ambrose
oscar1000108
Oscar Domingo
- Panagiotis Xynos
Parth Patel
- Pascal
Patrick Indermühle
Patrickm
Patrick Nafarrete
- Patrick Wuttke
Paul Gieske
Paul Mozet
Paweł Kowal
@@ -690,6 +638,7 @@ generous deed immortalized in the next stable release of Godot Engine.
Pedro Henrique Martins Garcia
Peter Höglund
Philip Ludington (MrPhil)
+ Phoenix Jauregui
Pierre Caye
Pille
Pixel Archipel
@@ -697,23 +646,20 @@ generous deed immortalized in the next stable release of Godot Engine.
Point08
Portponky
Preethi Vaidyanathan
+ Price Comstock
PsycHead
Puntigames
pwab
Quincy Quincy
Quinn Morrison
- RackBar Dingum
Rafa Laguna
+ RagingRoosevelt
Ragnar Pettersson
Rainer Amler
Rammeow
- red1939
Relintai
Remi Rampin
- Remtaine
Reneator
- Riccardo Marini
- Richard Hayes
Richard Ivánek
Riley
Robin Ward
@@ -725,7 +671,6 @@ generous deed immortalized in the next stable release of Godot Engine.
Roka
Roland RzÄ…sa
Roman Papush
- Ronald Ho Hip (CrimsonZA)
Roy Scayged
Russ
Ryan Groom
@@ -733,6 +678,7 @@ generous deed immortalized in the next stable release of Godot Engine.
Rykk
Sammy Fischer
Sangeeth Pavithran
+ Sasha Schwartz
Sean Dee
Sebastian Michailidis
SeongWan Kim
@@ -742,7 +688,6 @@ generous deed immortalized in the next stable release of Godot Engine.
Shane
Shane Lillie
Shane Spoor
- Silver1063
simdee
Simon Jonas Larsen
Simon Schoenenberger
@@ -757,22 +702,19 @@ generous deed immortalized in the next stable release of Godot Engine.
Soheib El-Harrache
Solene Waked
Sophie Winter
- Sparky
Squidgy
Squirrel
- Stéphane Roussel
+ SSebigo
Stephen Rice
Stephen Schlie
Steven Drovie
summerblind
Sung soo Choi
- Svenne Krap
SxP
tadashi endo
Tarch
Techwizz
Terry
- Theodore Lindsey
TheVoiceInMyHead
TheWint
Thibaut DECROMBECQUE
@@ -789,10 +731,8 @@ generous deed immortalized in the next stable release of Godot Engine.
Timothy B. MacDonald
Tim Riley
Toadile
- Tobias Bradtke
Tom Coxon
Tom Webster
- Torgeir Lilleskog
Torsten Crass
travis f w
Travis O'Brien
@@ -808,13 +748,15 @@ generous deed immortalized in the next stable release of Godot Engine.
v01tech
Vaida
Vaughan Ling
+ Vavin.X
VikFro
Vincent Barkmann
+ Vincent Cloutier
Vincent Foulon
Vitaliy Sapronenko
- Vi Watch
Vladimir Savin
- Vuli Nux
+ volklobo@live.com
+ Vulinux
Wapiti .
Wiley Thompson
William Bodin
@@ -826,6 +768,7 @@ generous deed immortalized in the next stable release of Godot Engine.
Yan Shi
Zekim
Zher Huei Lee
+ Zoee Silcock
ケルベロス
è²´å® å°æ¾
éƒæ™¨ç…œ
diff --git a/SConstruct b/SConstruct
index 6847a7c937..1eb6c0adc8 100644
--- a/SConstruct
+++ b/SConstruct
@@ -179,7 +179,7 @@ opts.Add(BoolVariable("production", "Set defaults to build Godot for use in prod
# Components
opts.Add(BoolVariable("deprecated", "Enable compatibility code for deprecated and removed features", True))
-opts.Add(EnumVariable("float", "Floating-point precision", "32", ("32", "64")))
+opts.Add(EnumVariable("precision", "Set the floating-point precision level", "single", ("single", "double")))
opts.Add(BoolVariable("minizip", "Enable ZIP archive support using minizip", True))
opts.Add(BoolVariable("xaudio2", "Enable the XAudio2 audio driver", False))
opts.Add(BoolVariable("vulkan", "Enable the vulkan rendering driver", True))
@@ -442,7 +442,7 @@ if env_base["no_editor_splash"]:
if not env_base["deprecated"]:
env_base.Append(CPPDEFINES=["DISABLE_DEPRECATED"])
-if env_base["float"] == "64":
+if env_base["precision"] == "double":
env_base.Append(CPPDEFINES=["REAL_T_IS_DOUBLE"])
if selected_platform in platform_list:
@@ -544,6 +544,12 @@ if selected_platform in platform_list:
env.Append(CCFLAGS=["-g3"])
else:
env.Append(CCFLAGS=["-g2"])
+ else:
+ if methods.using_clang(env) and not methods.is_vanilla_clang(env):
+ # Apple Clang, its linker doesn't like -s.
+ env.Append(LINKFLAGS=["-Wl,-S", "-Wl,-x", "-Wl,-dead_strip"])
+ else:
+ env.Append(LINKFLAGS=["-s"])
if env["optimize"] == "speed":
env.Append(CCFLAGS=["-O3"])
@@ -741,7 +747,7 @@ if selected_platform in platform_list:
if env.dev_build:
suffix += ".dev"
- if env_base["float"] == "64":
+ if env_base["precision"] == "double":
suffix += ".double"
suffix += "." + env["arch"]
diff --git a/core/config/engine.cpp b/core/config/engine.cpp
index 21e910be5b..7aa5f4d06d 100644
--- a/core/config/engine.cpp
+++ b/core/config/engine.cpp
@@ -48,6 +48,15 @@ int Engine::get_physics_ticks_per_second() const {
return ips;
}
+void Engine::set_max_physics_steps_per_frame(int p_max_physics_steps) {
+ ERR_FAIL_COND_MSG(p_max_physics_steps <= 0, "Maximum number of physics steps per frame must be greater than 0.");
+ max_physics_steps_per_frame = p_max_physics_steps;
+}
+
+int Engine::get_max_physics_steps_per_frame() const {
+ return max_physics_steps_per_frame;
+}
+
void Engine::set_physics_jitter_fix(double p_threshold) {
if (p_threshold < 0) {
p_threshold = 0;
diff --git a/core/config/engine.h b/core/config/engine.h
index 21517e46b7..1b179c5727 100644
--- a/core/config/engine.h
+++ b/core/config/engine.h
@@ -63,6 +63,7 @@ private:
int _max_fps = 0;
double _time_scale = 1.0;
uint64_t _physics_frames = 0;
+ int max_physics_steps_per_frame = 8;
double _physics_interpolation_fraction = 0.0f;
bool abort_on_gpu_errors = false;
bool use_validation_layers = false;
@@ -93,6 +94,9 @@ public:
virtual void set_physics_ticks_per_second(int p_ips);
virtual int get_physics_ticks_per_second() const;
+ virtual void set_max_physics_steps_per_frame(int p_max_physics_steps);
+ virtual int get_max_physics_steps_per_frame() const;
+
void set_physics_jitter_fix(double p_threshold);
double get_physics_jitter_fix() const;
diff --git a/core/config/project_settings.cpp b/core/config/project_settings.cpp
index 4d2006d42a..385cd2b2fd 100644
--- a/core/config/project_settings.cpp
+++ b/core/config/project_settings.cpp
@@ -82,7 +82,7 @@ String ProjectSettings::get_imported_files_path() const {
// Returns the features that a project must have when opened with this build of Godot.
// This is used by the project manager to provide the initial_settings for config/features.
const PackedStringArray ProjectSettings::get_required_features() {
- PackedStringArray features = PackedStringArray();
+ PackedStringArray features;
features.append(VERSION_BRANCH);
#ifdef REAL_T_IS_DOUBLE
features.append("Double Precision");
@@ -115,7 +115,7 @@ const PackedStringArray ProjectSettings::_get_supported_features() {
// Returns the features that this project needs but this build of Godot lacks.
const PackedStringArray ProjectSettings::get_unsupported_features(const PackedStringArray &p_project_features) {
- PackedStringArray unsupported_features = PackedStringArray();
+ PackedStringArray unsupported_features;
PackedStringArray supported_features = singleton->_get_supported_features();
for (int i = 0; i < p_project_features.size(); i++) {
if (!supported_features.has(p_project_features[i])) {
@@ -1124,8 +1124,12 @@ void ProjectSettings::set_setting(const String &p_setting, const Variant &p_valu
set(p_setting, p_value);
}
-Variant ProjectSettings::get_setting(const String &p_setting) const {
- return get(p_setting);
+Variant ProjectSettings::get_setting(const String &p_setting, const Variant &p_default_value) const {
+ if (has_setting(p_setting)) {
+ return get(p_setting);
+ } else {
+ return p_default_value;
+ }
}
bool ProjectSettings::has_custom_feature(const String &p_feature) const {
@@ -1158,7 +1162,7 @@ ProjectSettings::AutoloadInfo ProjectSettings::get_autoload(const StringName &p_
void ProjectSettings::_bind_methods() {
ClassDB::bind_method(D_METHOD("has_setting", "name"), &ProjectSettings::has_setting);
ClassDB::bind_method(D_METHOD("set_setting", "name", "value"), &ProjectSettings::set_setting);
- ClassDB::bind_method(D_METHOD("get_setting", "name"), &ProjectSettings::get_setting);
+ ClassDB::bind_method(D_METHOD("get_setting", "name", "default_value"), &ProjectSettings::get_setting, DEFVAL(Variant()));
ClassDB::bind_method(D_METHOD("set_order", "name", "position"), &ProjectSettings::set_order);
ClassDB::bind_method(D_METHOD("get_order", "name"), &ProjectSettings::get_order);
ClassDB::bind_method(D_METHOD("set_initial_value", "name", "value"), &ProjectSettings::set_initial_value);
@@ -1200,6 +1204,7 @@ ProjectSettings::ProjectSettings() {
// Initialization of engine variables should be done in the setup() method,
// so that the values can be overridden from project.godot or project.binary.
+ CRASH_COND_MSG(singleton != nullptr, "Instantiating a new ProjectSettings singleton is not supported.");
singleton = this;
GLOBAL_DEF_BASIC("application/config/name", "");
@@ -1246,12 +1251,12 @@ ProjectSettings::ProjectSettings() {
GLOBAL_DEF_BASIC("audio/buses/default_bus_layout", "res://default_bus_layout.tres");
custom_prop_info["audio/buses/default_bus_layout"] = PropertyInfo(Variant::STRING, "audio/buses/default_bus_layout", PROPERTY_HINT_FILE, "*.tres");
- GLOBAL_DEF_RST("audio/general/2d_panning_strength", 1.0f);
- custom_prop_info["audio/general/2d_panning_strength"] = PropertyInfo(Variant::FLOAT, "audio/general/2d_panning_strength", PROPERTY_HINT_RANGE, "0,4,0.01");
- GLOBAL_DEF_RST("audio/general/3d_panning_strength", 1.0f);
- custom_prop_info["audio/general/3d_panning_strength"] = PropertyInfo(Variant::FLOAT, "audio/general/3d_panning_strength", PROPERTY_HINT_RANGE, "0,4,0.01");
+ GLOBAL_DEF_RST("audio/general/2d_panning_strength", 0.5f);
+ custom_prop_info["audio/general/2d_panning_strength"] = PropertyInfo(Variant::FLOAT, "audio/general/2d_panning_strength", PROPERTY_HINT_RANGE, "0,2,0.01");
+ GLOBAL_DEF_RST("audio/general/3d_panning_strength", 0.5f);
+ custom_prop_info["audio/general/3d_panning_strength"] = PropertyInfo(Variant::FLOAT, "audio/general/3d_panning_strength", PROPERTY_HINT_RANGE, "0,2,0.01");
- PackedStringArray extensions = PackedStringArray();
+ PackedStringArray extensions;
extensions.push_back("gd");
if (Engine::get_singleton()->has_singleton("GodotSharp")) {
extensions.push_back("cs");
@@ -1276,7 +1281,6 @@ ProjectSettings::ProjectSettings() {
GLOBAL_DEF("physics/2d/run_on_separate_thread", false);
GLOBAL_DEF("physics/3d/run_on_separate_thread", false);
- GLOBAL_DEF("debug/disable_touch", false);
GLOBAL_DEF("debug/settings/profiler/max_functions", 16384);
custom_prop_info["debug/settings/profiler/max_functions"] = PropertyInfo(Variant::INT, "debug/settings/profiler/max_functions", PROPERTY_HINT_RANGE, "128,65535,1");
diff --git a/core/config/project_settings.h b/core/config/project_settings.h
index 960dfe0395..2ffbda9cea 100644
--- a/core/config/project_settings.h
+++ b/core/config/project_settings.h
@@ -141,7 +141,7 @@ public:
static const int CONFIG_VERSION = 5;
void set_setting(const String &p_setting, const Variant &p_value);
- Variant get_setting(const String &p_setting) const;
+ Variant get_setting(const String &p_setting, const Variant &p_default_value = Variant()) const;
bool has_setting(String p_var) const;
String localize_path(const String &p_path) const;
diff --git a/core/core_bind.cpp b/core/core_bind.cpp
index 87b36f7a21..9503bd2575 100644
--- a/core/core_bind.cpp
+++ b/core/core_bind.cpp
@@ -236,8 +236,12 @@ 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_system_font_path(const String &p_font_name, int p_weight, int p_stretch, bool p_italic) const {
+ return ::OS::get_singleton()->get_system_font_path(p_font_name, p_weight, p_stretch, p_italic);
+}
+
+Vector<String> OS::get_system_font_path_for_text(const String &p_font_name, const String &p_text, const String &p_locale, const String &p_script, int p_weight, int p_stretch, bool p_italic) const {
+ return ::OS::get_singleton()->get_system_font_path_for_text(p_font_name, p_text, p_locale, p_script, p_weight, p_stretch, p_italic);
}
String OS::get_executable_path() const {
@@ -532,7 +536,8 @@ void OS::_bind_methods() {
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_system_font_path", "font_name", "weight", "stretch", "italic"), &OS::get_system_font_path, DEFVAL(400), DEFVAL(100), DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("get_system_font_path_for_text", "font_name", "text", "locale", "script", "weight", "stretch", "italic"), &OS::get_system_font_path_for_text, DEFVAL(String()), DEFVAL(String()), DEFVAL(400), DEFVAL(100), DEFVAL(false));
ClassDB::bind_method(D_METHOD("get_executable_path"), &OS::get_executable_path);
ClassDB::bind_method(D_METHOD("read_string_from_stdin", "block"), &OS::read_string_from_stdin, DEFVAL(true));
ClassDB::bind_method(D_METHOD("execute", "path", "arguments", "output", "read_stderr", "open_console"), &OS::execute, DEFVAL(Array()), DEFVAL(false), DEFVAL(false));
@@ -1477,6 +1482,14 @@ int Engine::get_physics_ticks_per_second() const {
return ::Engine::get_singleton()->get_physics_ticks_per_second();
}
+void Engine::set_max_physics_steps_per_frame(int p_max_physics_steps) {
+ ::Engine::get_singleton()->set_max_physics_steps_per_frame(p_max_physics_steps);
+}
+
+int Engine::get_max_physics_steps_per_frame() const {
+ return ::Engine::get_singleton()->get_max_physics_steps_per_frame();
+}
+
void Engine::set_physics_jitter_fix(double p_threshold) {
::Engine::get_singleton()->set_physics_jitter_fix(p_threshold);
}
@@ -1628,6 +1641,8 @@ bool Engine::is_printing_error_messages() const {
void Engine::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_physics_ticks_per_second", "physics_ticks_per_second"), &Engine::set_physics_ticks_per_second);
ClassDB::bind_method(D_METHOD("get_physics_ticks_per_second"), &Engine::get_physics_ticks_per_second);
+ ClassDB::bind_method(D_METHOD("set_max_physics_steps_per_frame", "max_physics_steps"), &Engine::set_max_physics_steps_per_frame);
+ ClassDB::bind_method(D_METHOD("get_max_physics_steps_per_frame"), &Engine::get_max_physics_steps_per_frame);
ClassDB::bind_method(D_METHOD("set_physics_jitter_fix", "physics_jitter_fix"), &Engine::set_physics_jitter_fix);
ClassDB::bind_method(D_METHOD("get_physics_jitter_fix"), &Engine::get_physics_jitter_fix);
ClassDB::bind_method(D_METHOD("get_physics_interpolation_fraction"), &Engine::get_physics_interpolation_fraction);
@@ -1675,6 +1690,7 @@ void Engine::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "print_error_messages"), "set_print_error_messages", "is_printing_error_messages");
ADD_PROPERTY(PropertyInfo(Variant::INT, "physics_ticks_per_second"), "set_physics_ticks_per_second", "get_physics_ticks_per_second");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "max_physics_steps_per_frame"), "set_max_physics_steps_per_frame", "get_max_physics_steps_per_frame");
ADD_PROPERTY(PropertyInfo(Variant::INT, "max_fps"), "set_max_fps", "get_max_fps");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "time_scale"), "set_time_scale", "get_time_scale");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "physics_jitter_fix"), "set_physics_jitter_fix", "get_physics_jitter_fix");
diff --git a/core/core_bind.h b/core/core_bind.h
index 784f3e63b1..c863a8094c 100644
--- a/core/core_bind.h
+++ b/core/core_bind.h
@@ -170,7 +170,8 @@ public:
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_system_font_path(const String &p_font_name, int p_weight = 400, int p_stretch = 100, bool p_italic = false) const;
+ Vector<String> get_system_font_path_for_text(const String &p_font_name, const String &p_text, const String &p_locale = String(), const String &p_script = String(), int p_weight = 400, int p_stretch = 100, bool p_italic = false) const;
String get_executable_path() const;
String read_string_from_stdin(bool p_block = true);
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);
@@ -486,6 +487,9 @@ public:
void set_physics_ticks_per_second(int p_ips);
int get_physics_ticks_per_second() const;
+ void set_max_physics_steps_per_frame(int p_max_physics_steps);
+ int get_max_physics_steps_per_frame() const;
+
void set_physics_jitter_fix(double p_threshold);
double get_physics_jitter_fix() const;
double get_physics_interpolation_fraction() const;
diff --git a/core/core_constants.cpp b/core/core_constants.cpp
index 0e8532a327..c72b6212d7 100644
--- a/core/core_constants.cpp
+++ b/core/core_constants.cpp
@@ -153,6 +153,7 @@ void register_global_constants() {
BIND_CORE_ENUM_CONSTANT(INLINE_ALIGNMENT_TOP_TO);
BIND_CORE_ENUM_CONSTANT(INLINE_ALIGNMENT_CENTER_TO);
+ BIND_CORE_ENUM_CONSTANT(INLINE_ALIGNMENT_BASELINE_TO);
BIND_CORE_ENUM_CONSTANT(INLINE_ALIGNMENT_BOTTOM_TO);
BIND_CORE_ENUM_CONSTANT(INLINE_ALIGNMENT_TO_TOP);
@@ -595,8 +596,6 @@ void register_global_constants() {
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_EXPRESSION);
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_PLACEHOLDER_TEXT);
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_COLOR_NO_ALPHA);
- BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_IMAGE_COMPRESS_LOSSY);
- BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_IMAGE_COMPRESS_LOSSLESS);
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_OBJECT_ID);
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_TYPE_STRING);
@@ -639,7 +638,6 @@ void register_global_constants() {
BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_SCRIPT_VARIABLE);
BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_STORE_IF_NULL);
- BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_ANIMATE_AS_TRIGGER);
BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED);
BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_SCRIPT_DEFAULT_VALUE);
BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_CLASS_IS_ENUM);
diff --git a/core/debugger/remote_debugger.cpp b/core/debugger/remote_debugger.cpp
index 23ee977df4..a2e3fab82c 100644
--- a/core/debugger/remote_debugger.cpp
+++ b/core/debugger/remote_debugger.cpp
@@ -39,89 +39,6 @@
#include "core/object/script_language.h"
#include "core/os/os.h"
-class RemoteDebugger::MultiplayerProfiler : public EngineProfiler {
- struct BandwidthFrame {
- uint32_t timestamp;
- int packet_size;
- };
-
- int bandwidth_in_ptr = 0;
- Vector<BandwidthFrame> bandwidth_in;
- int bandwidth_out_ptr = 0;
- Vector<BandwidthFrame> bandwidth_out;
- uint64_t last_bandwidth_time = 0;
-
- int bandwidth_usage(const Vector<BandwidthFrame> &p_buffer, int p_pointer) {
- ERR_FAIL_COND_V(p_buffer.size() == 0, 0);
- int total_bandwidth = 0;
-
- uint64_t timestamp = OS::get_singleton()->get_ticks_msec();
- uint64_t final_timestamp = timestamp - 1000;
-
- int i = (p_pointer + p_buffer.size() - 1) % p_buffer.size();
-
- while (i != p_pointer && p_buffer[i].packet_size > 0) {
- if (p_buffer[i].timestamp < final_timestamp) {
- return total_bandwidth;
- }
- total_bandwidth += p_buffer[i].packet_size;
- i = (i + p_buffer.size() - 1) % p_buffer.size();
- }
-
- ERR_FAIL_COND_V_MSG(i == p_pointer, total_bandwidth, "Reached the end of the bandwidth profiler buffer, values might be inaccurate.");
- return total_bandwidth;
- }
-
-public:
- void toggle(bool p_enable, const Array &p_opts) {
- if (!p_enable) {
- bandwidth_in.clear();
- bandwidth_out.clear();
- } else {
- bandwidth_in_ptr = 0;
- bandwidth_in.resize(16384); // ~128kB
- for (int i = 0; i < bandwidth_in.size(); ++i) {
- bandwidth_in.write[i].packet_size = -1;
- }
- bandwidth_out_ptr = 0;
- bandwidth_out.resize(16384); // ~128kB
- for (int i = 0; i < bandwidth_out.size(); ++i) {
- bandwidth_out.write[i].packet_size = -1;
- }
- }
- }
-
- void add(const Array &p_data) {
- ERR_FAIL_COND(p_data.size() < 3);
- const String inout = p_data[0];
- int time = p_data[1];
- int size = p_data[2];
- if (inout == "in") {
- bandwidth_in.write[bandwidth_in_ptr].timestamp = time;
- bandwidth_in.write[bandwidth_in_ptr].packet_size = size;
- bandwidth_in_ptr = (bandwidth_in_ptr + 1) % bandwidth_in.size();
- } else if (inout == "out") {
- bandwidth_out.write[bandwidth_out_ptr].timestamp = time;
- bandwidth_out.write[bandwidth_out_ptr].packet_size = size;
- bandwidth_out_ptr = (bandwidth_out_ptr + 1) % bandwidth_out.size();
- }
- }
-
- void tick(double p_frame_time, double p_process_time, double p_physics_time, double p_physics_frame_time) {
- uint64_t pt = OS::get_singleton()->get_ticks_msec();
- if (pt - last_bandwidth_time > 200) {
- last_bandwidth_time = pt;
- int incoming_bandwidth = bandwidth_usage(bandwidth_in, bandwidth_in_ptr);
- int outgoing_bandwidth = bandwidth_usage(bandwidth_out, bandwidth_out_ptr);
-
- Array arr;
- arr.push_back(incoming_bandwidth);
- arr.push_back(outgoing_bandwidth);
- EngineDebugger::get_singleton()->send_message("multiplayer:bandwidth", arr);
- }
- }
-};
-
class RemoteDebugger::PerformanceProfiler : public EngineProfiler {
Object *performance = nullptr;
int last_perf_time = 0;
@@ -659,10 +576,6 @@ RemoteDebugger::RemoteDebugger(Ref<RemoteDebuggerPeer> p_peer) {
max_errors_per_second = GLOBAL_GET("network/limits/debugger/max_errors_per_second");
max_warnings_per_second = GLOBAL_GET("network/limits/debugger/max_warnings_per_second");
- // Multiplayer Profiler
- multiplayer_profiler.instantiate();
- multiplayer_profiler->bind("multiplayer");
-
// Performance Profiler
Object *perf = Engine::get_singleton()->get_singleton_object("Performance");
if (perf) {
diff --git a/core/debugger/remote_debugger.h b/core/debugger/remote_debugger.h
index fe4bbe86ea..944229d361 100644
--- a/core/debugger/remote_debugger.h
+++ b/core/debugger/remote_debugger.h
@@ -50,10 +50,8 @@ public:
private:
typedef DebuggerMarshalls::OutputError ErrorMessage;
- class MultiplayerProfiler;
class PerformanceProfiler;
- Ref<MultiplayerProfiler> multiplayer_profiler;
Ref<PerformanceProfiler> performance_profiler;
Ref<RemoteDebuggerPeer> peer;
diff --git a/core/extension/SCsub b/core/extension/SCsub
index a8f68a1533..361ce43a2c 100644
--- a/core/extension/SCsub
+++ b/core/extension/SCsub
@@ -8,8 +8,8 @@ from platform_methods import run_in_subprocess
env.CommandNoCache(["ext_wrappers.gen.inc"], "make_wrappers.py", run_in_subprocess(make_wrappers.run))
env.CommandNoCache(
- "gdnative_interface_dump.gen.h",
- ["gdnative_interface.h", "make_interface_dumper.py"],
+ "gdextension_interface_dump.gen.h",
+ ["gdextension_interface.h", "make_interface_dumper.py"],
run_in_subprocess(make_interface_dumper.run),
)
diff --git a/core/extension/extension_api_dump.cpp b/core/extension/extension_api_dump.cpp
index a2c507e350..a0e3778dcc 100644
--- a/core/extension/extension_api_dump.cpp
+++ b/core/extension/extension_api_dump.cpp
@@ -82,7 +82,7 @@ static String get_property_info_type_name(const PropertyInfo &p_info) {
return get_builtin_or_variant_type_name(p_info.type);
}
-Dictionary NativeExtensionAPIDump::generate_extension_api() {
+Dictionary GDExtensionAPIDump::generate_extension_api() {
Dictionary api_dump;
{
@@ -177,8 +177,8 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() {
};
// Validate sizes at compile time for the current build configuration.
- static_assert(type_size_array[Variant::BOOL][sizeof(void *)] == sizeof(GDNativeBool), "Size of bool mismatch");
- static_assert(type_size_array[Variant::INT][sizeof(void *)] == sizeof(GDNativeInt), "Size of int mismatch");
+ static_assert(type_size_array[Variant::BOOL][sizeof(void *)] == sizeof(GDExtensionBool), "Size of bool mismatch");
+ static_assert(type_size_array[Variant::INT][sizeof(void *)] == sizeof(GDExtensionInt), "Size of int mismatch");
static_assert(type_size_array[Variant::FLOAT][sizeof(void *)] == sizeof(double), "Size of float mismatch");
static_assert(type_size_array[Variant::STRING][sizeof(void *)] == sizeof(String), "Size of String mismatch");
static_assert(type_size_array[Variant::VECTOR2][sizeof(void *)] == sizeof(Vector2), "Size of Vector2 mismatch");
@@ -252,63 +252,140 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() {
}
{
- // Member offsets sizes.
+ // Member offsets, meta types and sizes.
+
+#define REAL_MEMBER_OFFSET(type, member) \
+ { \
+ type, \
+ member, \
+ "float", \
+ sizeof(float), \
+ "float", \
+ sizeof(float), \
+ "double", \
+ sizeof(double), \
+ "double", \
+ sizeof(double), \
+ }
+
+#define INT32_MEMBER_OFFSET(type, member) \
+ { \
+ type, \
+ member, \
+ "int32", \
+ sizeof(int32_t), \
+ "int32", \
+ sizeof(int32_t), \
+ "int32", \
+ sizeof(int32_t), \
+ "int32", \
+ sizeof(int32_t), \
+ }
+
+#define INT32_BASED_BUILTIN_MEMBER_OFFSET(type, member, member_type, member_elems) \
+ { \
+ type, \
+ member, \
+ member_type, \
+ sizeof(int32_t) * member_elems, \
+ member_type, \
+ sizeof(int32_t) * member_elems, \
+ member_type, \
+ sizeof(int32_t) * member_elems, \
+ member_type, \
+ sizeof(int32_t) * member_elems, \
+ }
+
+#define REAL_BASED_BUILTIN_MEMBER_OFFSET(type, member, member_type, member_elems) \
+ { \
+ type, \
+ member, \
+ member_type, \
+ sizeof(float) * member_elems, \
+ member_type, \
+ sizeof(float) * member_elems, \
+ member_type, \
+ sizeof(double) * member_elems, \
+ member_type, \
+ sizeof(double) * member_elems, \
+ }
+
struct {
Variant::Type type;
const char *member;
- uint32_t offset_32_bits_real_float;
- uint32_t offset_64_bits_real_float;
- uint32_t offset_32_bits_real_double;
- uint32_t offset_64_bits_real_double;
+ const char *member_meta_32_bits_real_float;
+ const uint32_t member_size_32_bits_real_float;
+ const char *member_meta_64_bits_real_float;
+ const uint32_t member_size_64_bits_real_float;
+ const char *member_meta_32_bits_real_double;
+ const uint32_t member_size_32_bits_real_double;
+ const char *member_meta_64_bits_real_double;
+ const uint32_t member_size_64_bits_real_double;
} member_offset_array[] = {
- { Variant::VECTOR2, "x", 0, 0, 0, 0 },
- { Variant::VECTOR2, "y", sizeof(float), sizeof(float), sizeof(double), sizeof(double) },
- { Variant::VECTOR2I, "x", 0, 0, 0, 0 },
- { Variant::VECTOR2I, "y", sizeof(int32_t), sizeof(int32_t), sizeof(int32_t), sizeof(int32_t) },
- { Variant::RECT2, "position", 0, 0, 0, 0 },
- { Variant::RECT2, "size", 2 * sizeof(Vector2), 2 * sizeof(float), 2 * sizeof(double), 2 * sizeof(double) },
- { Variant::RECT2I, "position", 0, 0, 0, 0 },
- { Variant::RECT2I, "size", 2 * sizeof(int32_t), 2 * sizeof(int32_t), 2 * sizeof(int32_t), 2 * sizeof(int32_t) },
- { Variant::VECTOR3, "x", 0, 0, 0, 0 },
- { Variant::VECTOR3, "y", sizeof(float), sizeof(float), sizeof(double), sizeof(double) },
- { Variant::VECTOR3, "z", 2 * sizeof(float), 2 * sizeof(float), 2 * sizeof(double), 2 * sizeof(double) },
- { Variant::VECTOR3I, "x", 0, 0, 0, 0 },
- { Variant::VECTOR3I, "y", sizeof(int32_t), sizeof(int32_t), sizeof(int32_t), sizeof(int32_t) },
- { Variant::VECTOR3I, "z", 2 * sizeof(int32_t), 2 * sizeof(int32_t), 2 * sizeof(int32_t), 2 * sizeof(int32_t) },
- { 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 },
- { Variant::QUATERNION, "y", sizeof(float), sizeof(float), sizeof(double), sizeof(double) },
- { Variant::QUATERNION, "z", 2 * sizeof(float), 2 * sizeof(float), 2 * sizeof(double), 2 * sizeof(double) },
- { Variant::QUATERNION, "w", 3 * sizeof(float), 3 * sizeof(float), 3 * sizeof(double), 3 * sizeof(double) },
- { Variant::AABB, "position", 0, 0, 0, 0 },
- { Variant::AABB, "size", vec3_elems * sizeof(float), vec3_elems * sizeof(float), vec3_elems * sizeof(double), vec3_elems * sizeof(double) },
- // Remember that basis vectors are flipped!
- { Variant::BASIS, "x", 0, 0, 0, 0 },
- { Variant::BASIS, "y", vec3_elems * sizeof(float), vec3_elems * sizeof(float), vec3_elems * sizeof(double), vec3_elems * sizeof(double) },
- { Variant::BASIS, "z", vec3_elems * 2 * sizeof(float), vec3_elems * 2 * sizeof(float), vec3_elems * 2 * sizeof(double), vec3_elems * 2 * sizeof(double) },
- { Variant::TRANSFORM3D, "basis", 0, 0, 0, 0 },
- { Variant::TRANSFORM3D, "origin", (vec3_elems * 3) * sizeof(float), (vec3_elems * 3) * sizeof(float), (vec3_elems * 3) * sizeof(double), (vec3_elems * 3) * sizeof(double) },
- { Variant::PROJECTION, "x", 0, 0, 0, 0 },
- { Variant::PROJECTION, "y", vec4_elems * sizeof(float), vec4_elems * sizeof(float), vec4_elems * sizeof(double), vec4_elems * sizeof(double) },
- { Variant::PROJECTION, "z", vec4_elems * 2 * sizeof(float), vec4_elems * 2 * sizeof(float), vec4_elems * 2 * sizeof(double), vec4_elems * 2 * sizeof(double) },
- { Variant::PROJECTION, "w", vec4_elems * 3 * sizeof(float), vec4_elems * 3 * sizeof(float), vec4_elems * 3 * sizeof(double), vec4_elems * 3 * sizeof(double) },
- { Variant::COLOR, "r", 0, 0, 0, 0 },
- { Variant::COLOR, "g", sizeof(float), sizeof(float), sizeof(float), sizeof(float) },
- { Variant::COLOR, "b", 2 * sizeof(float), 2 * sizeof(float), 2 * sizeof(float), 2 * sizeof(float) },
- { Variant::COLOR, "a", 3 * sizeof(float), 3 * sizeof(float), 3 * sizeof(float), 3 * sizeof(float) },
- { Variant::NIL, nullptr, 0, 0, 0, 0 },
+ // Vector2
+ REAL_MEMBER_OFFSET(Variant::VECTOR2, "x"),
+ REAL_MEMBER_OFFSET(Variant::VECTOR2, "y"),
+ // Vector2i
+ INT32_MEMBER_OFFSET(Variant::VECTOR2I, "x"),
+ INT32_MEMBER_OFFSET(Variant::VECTOR2I, "y"),
+ // Rect2
+ REAL_BASED_BUILTIN_MEMBER_OFFSET(Variant::RECT2, "position", "Vector2", 2),
+ REAL_BASED_BUILTIN_MEMBER_OFFSET(Variant::RECT2, "size", "Vector2", 2),
+ // Rect2i
+ INT32_BASED_BUILTIN_MEMBER_OFFSET(Variant::RECT2I, "position", "Vector2i", 2),
+ INT32_BASED_BUILTIN_MEMBER_OFFSET(Variant::RECT2I, "size", "Vector2i", 2),
+ // Vector3
+ REAL_MEMBER_OFFSET(Variant::VECTOR3, "x"),
+ REAL_MEMBER_OFFSET(Variant::VECTOR3, "y"),
+ REAL_MEMBER_OFFSET(Variant::VECTOR3, "z"),
+ // Vector3i
+ INT32_MEMBER_OFFSET(Variant::VECTOR3I, "x"),
+ INT32_MEMBER_OFFSET(Variant::VECTOR3I, "y"),
+ INT32_MEMBER_OFFSET(Variant::VECTOR3I, "z"),
+ // Transform2D
+ REAL_BASED_BUILTIN_MEMBER_OFFSET(Variant::TRANSFORM2D, "x", "Vector2", 2),
+ REAL_BASED_BUILTIN_MEMBER_OFFSET(Variant::TRANSFORM2D, "y", "Vector2", 2),
+ REAL_BASED_BUILTIN_MEMBER_OFFSET(Variant::TRANSFORM2D, "origin", "Vector2", 2),
+ // Vector4
+ REAL_MEMBER_OFFSET(Variant::VECTOR4, "x"),
+ REAL_MEMBER_OFFSET(Variant::VECTOR4, "y"),
+ REAL_MEMBER_OFFSET(Variant::VECTOR4, "z"),
+ REAL_MEMBER_OFFSET(Variant::VECTOR4, "w"),
+ // Vector4i
+ INT32_MEMBER_OFFSET(Variant::VECTOR4I, "x"),
+ INT32_MEMBER_OFFSET(Variant::VECTOR4I, "y"),
+ INT32_MEMBER_OFFSET(Variant::VECTOR4I, "z"),
+ INT32_MEMBER_OFFSET(Variant::VECTOR4I, "w"),
+ // Plane
+ REAL_BASED_BUILTIN_MEMBER_OFFSET(Variant::PLANE, "normal", "Vector3", vec3_elems),
+ REAL_MEMBER_OFFSET(Variant::PLANE, "d"),
+ // Quaternion
+ REAL_MEMBER_OFFSET(Variant::QUATERNION, "x"),
+ REAL_MEMBER_OFFSET(Variant::QUATERNION, "y"),
+ REAL_MEMBER_OFFSET(Variant::QUATERNION, "z"),
+ REAL_MEMBER_OFFSET(Variant::QUATERNION, "w"),
+ // AABB
+ REAL_BASED_BUILTIN_MEMBER_OFFSET(Variant::AABB, "position", "Vector3", vec3_elems),
+ REAL_BASED_BUILTIN_MEMBER_OFFSET(Variant::AABB, "size", "Vector3", vec3_elems),
+ // Basis (remember that basis vectors are flipped!)
+ REAL_BASED_BUILTIN_MEMBER_OFFSET(Variant::BASIS, "x", "Vector3", vec3_elems),
+ REAL_BASED_BUILTIN_MEMBER_OFFSET(Variant::BASIS, "y", "Vector3", vec3_elems),
+ REAL_BASED_BUILTIN_MEMBER_OFFSET(Variant::BASIS, "z", "Vector3", vec3_elems),
+ // Transform3D
+ REAL_BASED_BUILTIN_MEMBER_OFFSET(Variant::TRANSFORM3D, "basis", "Basis", vec3_elems * 3),
+ REAL_BASED_BUILTIN_MEMBER_OFFSET(Variant::TRANSFORM3D, "origin", "Vector3", vec3_elems),
+ // Projection
+ REAL_BASED_BUILTIN_MEMBER_OFFSET(Variant::PROJECTION, "x", "Vector4", vec4_elems),
+ REAL_BASED_BUILTIN_MEMBER_OFFSET(Variant::PROJECTION, "y", "Vector4", vec4_elems),
+ REAL_BASED_BUILTIN_MEMBER_OFFSET(Variant::PROJECTION, "z", "Vector4", vec4_elems),
+ REAL_BASED_BUILTIN_MEMBER_OFFSET(Variant::PROJECTION, "w", "Vector4", vec4_elems),
+ // Color (always composed of 4bytes floats)
+ { Variant::COLOR, "r", "float", sizeof(float), "float", sizeof(float), "float", sizeof(float), "float", sizeof(float) },
+ { Variant::COLOR, "g", "float", sizeof(float), "float", sizeof(float), "float", sizeof(float), "float", sizeof(float) },
+ { Variant::COLOR, "b", "float", sizeof(float), "float", sizeof(float), "float", sizeof(float), "float", sizeof(float) },
+ { Variant::COLOR, "a", "float", sizeof(float), "float", sizeof(float), "float", sizeof(float), "float", sizeof(float) },
+ // End marker, must stay last
+ { Variant::NIL, nullptr, nullptr, 0, nullptr, 0, nullptr, 0, nullptr, 0 },
};
Array core_type_member_offsets;
@@ -319,15 +396,16 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() {
Array type_offsets;
uint32_t idx = 0;
- Variant::Type last_type = Variant::NIL;
+ Variant::Type previous_type = Variant::NIL;
Dictionary d2;
Array members;
+ uint32_t offset = 0;
while (true) {
Variant::Type t = member_offset_array[idx].type;
- if (t != last_type) {
- if (last_type != Variant::NIL) {
+ if (t != previous_type) {
+ if (previous_type != Variant::NIL) {
d2["members"] = members;
type_offsets.push_back(d2);
}
@@ -338,27 +416,35 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() {
String name = t == Variant::VARIANT_MAX ? String("Variant") : Variant::get_type_name(t);
d2 = Dictionary();
members = Array();
+ offset = 0;
d2["name"] = name;
- last_type = t;
+ previous_type = t;
}
Dictionary d3;
- uint32_t offset = 0;
+ const char *member_meta = nullptr;
+ uint32_t member_size = 0;
switch (i) {
case 0:
- offset = member_offset_array[idx].offset_32_bits_real_float;
+ member_meta = member_offset_array[idx].member_meta_32_bits_real_float;
+ member_size = member_offset_array[idx].member_size_32_bits_real_float;
break;
case 1:
- offset = member_offset_array[idx].offset_64_bits_real_float;
+ member_meta = member_offset_array[idx].member_meta_64_bits_real_float;
+ member_size = member_offset_array[idx].member_size_64_bits_real_float;
break;
case 2:
- offset = member_offset_array[idx].offset_32_bits_real_double;
+ member_meta = member_offset_array[idx].member_meta_32_bits_real_double;
+ member_size = member_offset_array[idx].member_size_32_bits_real_double;
break;
case 3:
- offset = member_offset_array[idx].offset_64_bits_real_double;
+ member_meta = member_offset_array[idx].member_meta_64_bits_real_double;
+ member_size = member_offset_array[idx].member_size_64_bits_real_double;
break;
}
d3["member"] = member_offset_array[idx].member;
d3["offset"] = offset;
+ d3["meta"] = member_meta;
+ offset += member_size;
members.push_back(d3);
idx++;
}
@@ -871,9 +957,18 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() {
Dictionary d2;
d2["type"] = get_property_info_type_name(F);
d2["name"] = String(property_name);
- d2["setter"] = ClassDB::get_property_setter(class_name, F.name);
- d2["getter"] = ClassDB::get_property_getter(class_name, F.name);
- d2["index"] = ClassDB::get_property_index(class_name, F.name);
+ StringName setter = ClassDB::get_property_setter(class_name, F.name);
+ if (!(setter == "")) {
+ d2["setter"] = setter;
+ }
+ StringName getter = ClassDB::get_property_getter(class_name, F.name);
+ if (!(getter == "")) {
+ d2["getter"] = getter;
+ }
+ int index = ClassDB::get_property_index(class_name, F.name);
+ if (index != -1) {
+ d2["index"] = index;
+ }
properties.push_back(d2);
}
@@ -934,7 +1029,7 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() {
return api_dump;
}
-void NativeExtensionAPIDump::generate_extension_json_file(const String &p_path) {
+void GDExtensionAPIDump::generate_extension_json_file(const String &p_path) {
Dictionary api = generate_extension_api();
Ref<JSON> json;
json.instantiate();
diff --git a/core/extension/extension_api_dump.h b/core/extension/extension_api_dump.h
index 1bc455ea67..e488d8a086 100644
--- a/core/extension/extension_api_dump.h
+++ b/core/extension/extension_api_dump.h
@@ -31,11 +31,11 @@
#ifndef EXTENSION_API_DUMP_H
#define EXTENSION_API_DUMP_H
-#include "core/extension/native_extension.h"
+#include "core/extension/gdextension.h"
#ifdef TOOLS_ENABLED
-class NativeExtensionAPIDump {
+class GDExtensionAPIDump {
public:
static Dictionary generate_extension_api();
static void generate_extension_json_file(const String &p_path);
diff --git a/core/extension/native_extension.cpp b/core/extension/gdextension.cpp
index 8bbb72fd82..0c5c736efe 100644
--- a/core/extension/native_extension.cpp
+++ b/core/extension/gdextension.cpp
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* native_extension.cpp */
+/* gdextension.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,20 +28,125 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "native_extension.h"
+#include "gdextension.h"
#include "core/config/project_settings.h"
-#include "core/io/config_file.h"
+#include "core/io/dir_access.h"
#include "core/object/class_db.h"
#include "core/object/method_bind.h"
#include "core/os/os.h"
-String NativeExtension::get_extension_list_config_file() {
+String GDExtension::get_extension_list_config_file() {
return ProjectSettings::get_singleton()->get_project_data_path().path_join("extension_list.cfg");
}
-class NativeExtensionMethodBind : public MethodBind {
- GDNativeExtensionClassMethodCall call_func;
- GDNativeExtensionClassMethodPtrCall ptrcall_func;
+String GDExtension::find_extension_library(const String &p_path, Ref<ConfigFile> p_config, std::function<bool(String)> p_has_feature, PackedStringArray *r_tags) {
+ // First, check the explicit libraries.
+ if (p_config->has_section("libraries")) {
+ List<String> libraries;
+ p_config->get_section_keys("libraries", &libraries);
+
+ // Iterate the libraries, finding the best matching tags.
+ String best_library_path;
+ Vector<String> best_library_tags;
+ for (const String &E : libraries) {
+ Vector<String> tags = E.split(".");
+ bool all_tags_met = true;
+ for (int i = 0; i < tags.size(); i++) {
+ String tag = tags[i].strip_edges();
+ if (!p_has_feature(tag)) {
+ all_tags_met = false;
+ break;
+ }
+ }
+
+ if (all_tags_met && tags.size() > best_library_tags.size()) {
+ best_library_path = p_config->get_value("libraries", E);
+ best_library_tags = tags;
+ }
+ }
+
+ if (!best_library_path.is_empty()) {
+ if (best_library_path.is_relative_path()) {
+ best_library_path = p_path.get_base_dir().path_join(best_library_path);
+ }
+ if (r_tags != nullptr) {
+ r_tags->append_array(best_library_tags);
+ }
+ return best_library_path;
+ }
+ }
+
+ // Second, try to autodetect
+ String autodetect_library_prefix;
+ if (p_config->has_section_key("configuration", "autodetect_library_prefix")) {
+ autodetect_library_prefix = p_config->get_value("configuration", "autodetect_library_prefix");
+ }
+ if (!autodetect_library_prefix.is_empty()) {
+ String autodetect_path = autodetect_library_prefix;
+ if (autodetect_path.is_relative_path()) {
+ autodetect_path = p_path.get_base_dir().path_join(autodetect_path);
+ }
+
+ // Find the folder and file parts of the prefix.
+ String folder;
+ String file_prefix;
+ if (DirAccess::dir_exists_absolute(autodetect_path)) {
+ folder = autodetect_path;
+ } else if (DirAccess::dir_exists_absolute(autodetect_path.get_base_dir())) {
+ folder = autodetect_path.get_base_dir();
+ file_prefix = autodetect_path.get_file();
+ } else {
+ ERR_FAIL_V_MSG(String(), vformat("Error in extension: %s. Could not find folder for automatic detection of libraries files. autodetect_library_prefix=\"%s\"", p_path, autodetect_library_prefix));
+ }
+
+ // Open the folder.
+ Ref<DirAccess> dir = DirAccess::open(folder);
+ ERR_FAIL_COND_V_MSG(!dir.is_valid(), String(), vformat("Error in extension: %s. Could not open folder for automatic detection of libraries files. autodetect_library_prefix=\"%s\"", p_path, autodetect_library_prefix));
+
+ // Iterate the files and check the prefixes, finding the best matching file.
+ String best_file;
+ Vector<String> best_file_tags;
+ dir->list_dir_begin();
+ String file_name = dir->_get_next();
+ while (file_name != "") {
+ if (!dir->current_is_dir() && file_name.begins_with(file_prefix)) {
+ // Check if the files matches all requested feature tags.
+ String tags_str = file_name.trim_prefix(file_prefix);
+ tags_str = tags_str.trim_suffix(tags_str.get_extension());
+
+ Vector<String> tags = tags_str.split(".", false);
+ bool all_tags_met = true;
+ for (int i = 0; i < tags.size(); i++) {
+ String tag = tags[i].strip_edges();
+ if (!p_has_feature(tag)) {
+ all_tags_met = false;
+ break;
+ }
+ }
+
+ // If all tags are found in the feature list, and we found more tags than before, use this file.
+ if (all_tags_met && tags.size() > best_file_tags.size()) {
+ best_file_tags = tags;
+ best_file = file_name;
+ }
+ }
+ file_name = dir->_get_next();
+ }
+
+ if (!best_file.is_empty()) {
+ String library_path = folder.path_join(best_file);
+ if (r_tags != nullptr) {
+ r_tags->append_array(best_file_tags);
+ }
+ return library_path;
+ }
+ }
+ return String();
+}
+
+class GDExtensionMethodBind : public MethodBind {
+ GDExtensionClassMethodCall call_func;
+ GDExtensionClassMethodPtrCall ptrcall_func;
void *method_userdata;
bool vararg;
PropertyInfo return_value_info;
@@ -76,27 +181,27 @@ public:
}
#endif
- virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) override {
+ virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) const override {
Variant ret;
GDExtensionClassInstancePtr extension_instance = is_static() ? nullptr : p_object->_get_extension_instance();
- GDNativeCallError ce{ GDNATIVE_CALL_OK, 0, 0 };
- call_func(method_userdata, extension_instance, (const GDNativeVariantPtr *)p_args, p_arg_count, (GDNativeVariantPtr)&ret, &ce);
+ GDExtensionCallError ce{ GDEXTENSION_CALL_OK, 0, 0 };
+ call_func(method_userdata, extension_instance, reinterpret_cast<GDExtensionConstVariantPtr *>(p_args), p_arg_count, (GDExtensionVariantPtr)&ret, &ce);
r_error.error = Callable::CallError::Error(ce.error);
r_error.argument = ce.argument;
r_error.expected = ce.expected;
return ret;
}
- virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) override {
+ virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) const override {
ERR_FAIL_COND_MSG(vararg, "Vararg methods don't have ptrcall support. This is most likely an engine bug.");
GDExtensionClassInstancePtr extension_instance = p_object->_get_extension_instance();
- ptrcall_func(method_userdata, extension_instance, (const GDNativeTypePtr *)p_args, (GDNativeTypePtr)r_ret);
+ ptrcall_func(method_userdata, extension_instance, reinterpret_cast<GDExtensionConstTypePtr *>(p_args), (GDExtensionTypePtr)r_ret);
}
virtual bool is_vararg() const override {
return false;
}
- explicit NativeExtensionMethodBind(const GDNativeExtensionClassMethodInfo *p_method_info) {
+ explicit GDExtensionMethodBind(const GDExtensionClassMethodInfo *p_method_info) {
method_userdata = p_method_info->method_userdata;
call_func = p_method_info->call_func;
ptrcall_func = p_method_info->ptrcall_func;
@@ -108,16 +213,16 @@ public:
}
for (uint32_t i = 0; i < p_method_info->argument_count; i++) {
- arguments_info.push_back(PropertyInfo(p_method_info->aguments_info[i]));
- arguments_metadata.push_back(GodotTypeInfo::Metadata(p_method_info->aguments_metadata[i]));
+ arguments_info.push_back(PropertyInfo(p_method_info->arguments_info[i]));
+ arguments_metadata.push_back(GodotTypeInfo::Metadata(p_method_info->arguments_metadata[i]));
}
set_hint_flags(p_method_info->method_flags);
- vararg = p_method_info->method_flags & GDNATIVE_EXTENSION_METHOD_FLAG_VARARG;
+ vararg = p_method_info->method_flags & GDEXTENSION_METHOD_FLAG_VARARG;
_set_returns(p_method_info->has_return_value);
- _set_const(p_method_info->method_flags & GDNATIVE_EXTENSION_METHOD_FLAG_CONST);
- _set_static(p_method_info->method_flags & GDNATIVE_EXTENSION_METHOD_FLAG_STATIC);
+ _set_const(p_method_info->method_flags & GDEXTENSION_METHOD_FLAG_CONST);
+ _set_static(p_method_info->method_flags & GDEXTENSION_METHOD_FLAG_STATIC);
#ifdef DEBUG_METHODS_ENABLED
_generate_argument_types(p_method_info->argument_count);
#endif
@@ -133,13 +238,13 @@ public:
}
};
-static GDNativeInterface gdnative_interface;
+static GDExtensionInterface gdextension_interface;
-void NativeExtension::_register_extension_class(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativeStringNamePtr p_parent_class_name, const GDNativeExtensionClassCreationInfo *p_extension_funcs) {
- NativeExtension *self = static_cast<NativeExtension *>(p_library);
+void GDExtension::_register_extension_class(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_parent_class_name, const GDExtensionClassCreationInfo *p_extension_funcs) {
+ GDExtension *self = reinterpret_cast<GDExtension *>(p_library);
- StringName class_name = *reinterpret_cast<StringName *>(p_class_name);
- StringName parent_class_name = *reinterpret_cast<StringName *>(p_parent_class_name);
+ StringName class_name = *reinterpret_cast<const StringName *>(p_class_name);
+ StringName parent_class_name = *reinterpret_cast<const StringName *>(p_parent_class_name);
ERR_FAIL_COND_MSG(!String(class_name).is_valid_identifier(), "Attempt to register extension class '" + class_name + "', which is not a valid class identifier.");
ERR_FAIL_COND_MSG(ClassDB::class_exists(class_name), "Attempt to register extension class '" + class_name + "', which appears to be already registered.");
@@ -163,35 +268,35 @@ void NativeExtension::_register_extension_class(const GDNativeExtensionClassLibr
Extension *extension = &self->extension_classes[class_name];
if (parent_extension) {
- extension->native_extension.parent = &parent_extension->native_extension;
- parent_extension->native_extension.children.push_back(&extension->native_extension);
+ extension->gdextension.parent = &parent_extension->gdextension;
+ parent_extension->gdextension.children.push_back(&extension->gdextension);
}
- extension->native_extension.parent_class_name = parent_class_name;
- extension->native_extension.class_name = class_name;
- extension->native_extension.editor_class = self->level_initialized == INITIALIZATION_LEVEL_EDITOR;
- extension->native_extension.is_virtual = p_extension_funcs->is_virtual;
- extension->native_extension.is_abstract = p_extension_funcs->is_abstract;
- extension->native_extension.set = p_extension_funcs->set_func;
- extension->native_extension.get = p_extension_funcs->get_func;
- extension->native_extension.get_property_list = p_extension_funcs->get_property_list_func;
- extension->native_extension.free_property_list = p_extension_funcs->free_property_list_func;
- extension->native_extension.property_can_revert = p_extension_funcs->property_can_revert_func;
- extension->native_extension.property_get_revert = p_extension_funcs->property_get_revert_func;
- extension->native_extension.notification = p_extension_funcs->notification_func;
- extension->native_extension.to_string = p_extension_funcs->to_string_func;
- extension->native_extension.reference = p_extension_funcs->reference_func;
- extension->native_extension.unreference = p_extension_funcs->unreference_func;
- extension->native_extension.class_userdata = p_extension_funcs->class_userdata;
- extension->native_extension.create_instance = p_extension_funcs->create_instance_func;
- extension->native_extension.free_instance = p_extension_funcs->free_instance_func;
- extension->native_extension.get_virtual = p_extension_funcs->get_virtual_func;
- extension->native_extension.get_rid = p_extension_funcs->get_rid_func;
-
- ClassDB::register_extension_class(&extension->native_extension);
+ extension->gdextension.parent_class_name = parent_class_name;
+ extension->gdextension.class_name = class_name;
+ extension->gdextension.editor_class = self->level_initialized == INITIALIZATION_LEVEL_EDITOR;
+ extension->gdextension.is_virtual = p_extension_funcs->is_virtual;
+ extension->gdextension.is_abstract = p_extension_funcs->is_abstract;
+ extension->gdextension.set = p_extension_funcs->set_func;
+ extension->gdextension.get = p_extension_funcs->get_func;
+ extension->gdextension.get_property_list = p_extension_funcs->get_property_list_func;
+ extension->gdextension.free_property_list = p_extension_funcs->free_property_list_func;
+ extension->gdextension.property_can_revert = p_extension_funcs->property_can_revert_func;
+ extension->gdextension.property_get_revert = p_extension_funcs->property_get_revert_func;
+ extension->gdextension.notification = p_extension_funcs->notification_func;
+ extension->gdextension.to_string = p_extension_funcs->to_string_func;
+ extension->gdextension.reference = p_extension_funcs->reference_func;
+ extension->gdextension.unreference = p_extension_funcs->unreference_func;
+ extension->gdextension.class_userdata = p_extension_funcs->class_userdata;
+ extension->gdextension.create_instance = p_extension_funcs->create_instance_func;
+ extension->gdextension.free_instance = p_extension_funcs->free_instance_func;
+ extension->gdextension.get_virtual = p_extension_funcs->get_virtual_func;
+ extension->gdextension.get_rid = p_extension_funcs->get_rid_func;
+
+ ClassDB::register_extension_class(&extension->gdextension);
}
-void NativeExtension::_register_extension_class_method(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativeExtensionClassMethodInfo *p_method_info) {
- NativeExtension *self = static_cast<NativeExtension *>(p_library);
+void GDExtension::_register_extension_class_method(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, const GDExtensionClassMethodInfo *p_method_info) {
+ GDExtension *self = reinterpret_cast<GDExtension *>(p_library);
StringName class_name = *reinterpret_cast<const StringName *>(p_class_name);
StringName method_name = *reinterpret_cast<const StringName *>(p_method_info->name);
@@ -199,13 +304,13 @@ void NativeExtension::_register_extension_class_method(const GDNativeExtensionCl
//Extension *extension = &self->extension_classes[class_name];
- NativeExtensionMethodBind *method = memnew(NativeExtensionMethodBind(p_method_info));
+ GDExtensionMethodBind *method = memnew(GDExtensionMethodBind(p_method_info));
method->set_instance_class(class_name);
ClassDB::bind_method_custom(class_name, method);
}
-void NativeExtension::_register_extension_class_integer_constant(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativeStringNamePtr p_enum_name, const GDNativeStringNamePtr p_constant_name, GDNativeInt p_constant_value, GDNativeBool p_is_bitfield) {
- NativeExtension *self = static_cast<NativeExtension *>(p_library);
+void GDExtension::_register_extension_class_integer_constant(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_enum_name, GDExtensionConstStringNamePtr p_constant_name, GDExtensionInt p_constant_value, GDExtensionBool p_is_bitfield) {
+ GDExtension *self = reinterpret_cast<GDExtension *>(p_library);
StringName class_name = *reinterpret_cast<const StringName *>(p_class_name);
StringName enum_name = *reinterpret_cast<const StringName *>(p_enum_name);
@@ -215,8 +320,8 @@ void NativeExtension::_register_extension_class_integer_constant(const GDNativeE
ClassDB::bind_integer_constant(class_name, enum_name, constant_name, p_constant_value, p_is_bitfield);
}
-void NativeExtension::_register_extension_class_property(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativePropertyInfo *p_info, const GDNativeStringNamePtr p_setter, const GDNativeStringNamePtr p_getter) {
- NativeExtension *self = static_cast<NativeExtension *>(p_library);
+void GDExtension::_register_extension_class_property(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, const GDExtensionPropertyInfo *p_info, GDExtensionConstStringNamePtr p_setter, GDExtensionConstStringNamePtr p_getter) {
+ GDExtension *self = reinterpret_cast<GDExtension *>(p_library);
StringName class_name = *reinterpret_cast<const StringName *>(p_class_name);
StringName setter = *reinterpret_cast<const StringName *>(p_setter);
@@ -230,8 +335,8 @@ void NativeExtension::_register_extension_class_property(const GDNativeExtension
ClassDB::add_property(class_name, pinfo, setter, getter);
}
-void NativeExtension::_register_extension_class_property_group(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativeStringPtr p_group_name, const GDNativeStringPtr p_prefix) {
- NativeExtension *self = static_cast<NativeExtension *>(p_library);
+void GDExtension::_register_extension_class_property_group(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringPtr p_group_name, GDExtensionConstStringPtr p_prefix) {
+ GDExtension *self = reinterpret_cast<GDExtension *>(p_library);
StringName class_name = *reinterpret_cast<const StringName *>(p_class_name);
String group_name = *reinterpret_cast<const String *>(p_group_name);
@@ -241,8 +346,8 @@ void NativeExtension::_register_extension_class_property_group(const GDNativeExt
ClassDB::add_property_group(class_name, group_name, prefix);
}
-void NativeExtension::_register_extension_class_property_subgroup(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativeStringPtr p_subgroup_name, const GDNativeStringPtr p_prefix) {
- NativeExtension *self = static_cast<NativeExtension *>(p_library);
+void GDExtension::_register_extension_class_property_subgroup(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringPtr p_subgroup_name, GDExtensionConstStringPtr p_prefix) {
+ GDExtension *self = reinterpret_cast<GDExtension *>(p_library);
StringName class_name = *reinterpret_cast<const StringName *>(p_class_name);
String subgroup_name = *reinterpret_cast<const String *>(p_subgroup_name);
@@ -252,8 +357,8 @@ void NativeExtension::_register_extension_class_property_subgroup(const GDNative
ClassDB::add_property_subgroup(class_name, subgroup_name, prefix);
}
-void NativeExtension::_register_extension_class_signal(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativeStringNamePtr p_signal_name, const GDNativePropertyInfo *p_argument_info, GDNativeInt p_argument_count) {
- NativeExtension *self = static_cast<NativeExtension *>(p_library);
+void GDExtension::_register_extension_class_signal(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_signal_name, const GDExtensionPropertyInfo *p_argument_info, GDExtensionInt p_argument_count) {
+ GDExtension *self = reinterpret_cast<GDExtension *>(p_library);
StringName class_name = *reinterpret_cast<const StringName *>(p_class_name);
StringName signal_name = *reinterpret_cast<const StringName *>(p_signal_name);
@@ -268,28 +373,28 @@ void NativeExtension::_register_extension_class_signal(const GDNativeExtensionCl
ClassDB::add_signal(class_name, s);
}
-void NativeExtension::_unregister_extension_class(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name) {
- NativeExtension *self = static_cast<NativeExtension *>(p_library);
+void GDExtension::_unregister_extension_class(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name) {
+ GDExtension *self = reinterpret_cast<GDExtension *>(p_library);
StringName class_name = *reinterpret_cast<const StringName *>(p_class_name);
ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), "Attempt to unregister unexisting extension class '" + class_name + "'.");
Extension *ext = &self->extension_classes[class_name];
- ERR_FAIL_COND_MSG(ext->native_extension.children.size(), "Attempt to unregister class '" + class_name + "' while other extension classes inherit from it.");
+ ERR_FAIL_COND_MSG(ext->gdextension.children.size(), "Attempt to unregister class '" + class_name + "' while other extension classes inherit from it.");
ClassDB::unregister_extension_class(class_name);
- if (ext->native_extension.parent != nullptr) {
- ext->native_extension.parent->children.erase(&ext->native_extension);
+ if (ext->gdextension.parent != nullptr) {
+ ext->gdextension.parent->children.erase(&ext->gdextension);
}
self->extension_classes.erase(class_name);
}
-void NativeExtension::_get_library_path(const GDNativeExtensionClassLibraryPtr p_library, GDNativeStringPtr r_path) {
- NativeExtension *self = static_cast<NativeExtension *>(p_library);
+void GDExtension::_get_library_path(GDExtensionClassLibraryPtr p_library, GDExtensionStringPtr r_path) {
+ GDExtension *self = reinterpret_cast<GDExtension *>(p_library);
*(String *)r_path = self->library_path;
}
-Error NativeExtension::open_library(const String &p_path, const String &p_entry_symbol) {
+Error GDExtension::open_library(const String &p_path, const String &p_entry_symbol) {
Error err = OS::get_singleton()->open_dynamic_library(p_path, library, true, &library_path);
if (err != OK) {
ERR_PRINT("GDExtension dynamic library not found: " + p_path);
@@ -306,9 +411,9 @@ Error NativeExtension::open_library(const String &p_path, const String &p_entry_
return err;
}
- GDNativeInitializationFunction initialization_function = (GDNativeInitializationFunction)entry_funcptr;
+ GDExtensionInitializationFunction initialization_function = (GDExtensionInitializationFunction)entry_funcptr;
- if (initialization_function(&gdnative_interface, this, &initialization)) {
+ if (initialization_function(&gdextension_interface, this, &initialization)) {
level_initialized = -1;
return OK;
} else {
@@ -317,23 +422,23 @@ Error NativeExtension::open_library(const String &p_path, const String &p_entry_
}
}
-void NativeExtension::close_library() {
+void GDExtension::close_library() {
ERR_FAIL_COND(library == nullptr);
OS::get_singleton()->close_dynamic_library(library);
library = nullptr;
}
-bool NativeExtension::is_library_open() const {
+bool GDExtension::is_library_open() const {
return library != nullptr;
}
-NativeExtension::InitializationLevel NativeExtension::get_minimum_library_initialization_level() const {
+GDExtension::InitializationLevel GDExtension::get_minimum_library_initialization_level() const {
ERR_FAIL_COND_V(library == nullptr, INITIALIZATION_LEVEL_CORE);
return InitializationLevel(initialization.minimum_initialization_level);
}
-void NativeExtension::initialize_library(InitializationLevel p_level) {
+void GDExtension::initialize_library(InitializationLevel p_level) {
ERR_FAIL_COND(library == nullptr);
ERR_FAIL_COND_MSG(p_level <= int32_t(level_initialized), vformat("Level '%d' must be higher than the current level '%d'", p_level, level_initialized));
@@ -341,23 +446,23 @@ void NativeExtension::initialize_library(InitializationLevel p_level) {
ERR_FAIL_COND(initialization.initialize == nullptr);
- initialization.initialize(initialization.userdata, GDNativeInitializationLevel(p_level));
+ initialization.initialize(initialization.userdata, GDExtensionInitializationLevel(p_level));
}
-void NativeExtension::deinitialize_library(InitializationLevel p_level) {
+void GDExtension::deinitialize_library(InitializationLevel p_level) {
ERR_FAIL_COND(library == nullptr);
ERR_FAIL_COND(p_level > int32_t(level_initialized));
level_initialized = int32_t(p_level) - 1;
- initialization.deinitialize(initialization.userdata, GDNativeInitializationLevel(p_level));
+ initialization.deinitialize(initialization.userdata, GDExtensionInitializationLevel(p_level));
}
-void NativeExtension::_bind_methods() {
- ClassDB::bind_method(D_METHOD("open_library", "path", "entry_symbol"), &NativeExtension::open_library);
- ClassDB::bind_method(D_METHOD("close_library"), &NativeExtension::close_library);
- ClassDB::bind_method(D_METHOD("is_library_open"), &NativeExtension::is_library_open);
+void GDExtension::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("open_library", "path", "entry_symbol"), &GDExtension::open_library);
+ ClassDB::bind_method(D_METHOD("close_library"), &GDExtension::close_library);
+ ClassDB::bind_method(D_METHOD("is_library_open"), &GDExtension::is_library_open);
- ClassDB::bind_method(D_METHOD("get_minimum_library_initialization_level"), &NativeExtension::get_minimum_library_initialization_level);
- ClassDB::bind_method(D_METHOD("initialize_library", "level"), &NativeExtension::initialize_library);
+ ClassDB::bind_method(D_METHOD("get_minimum_library_initialization_level"), &GDExtension::get_minimum_library_initialization_level);
+ ClassDB::bind_method(D_METHOD("initialize_library", "level"), &GDExtension::initialize_library);
BIND_ENUM_CONSTANT(INITIALIZATION_LEVEL_CORE);
BIND_ENUM_CONSTANT(INITIALIZATION_LEVEL_SERVERS);
@@ -365,32 +470,32 @@ void NativeExtension::_bind_methods() {
BIND_ENUM_CONSTANT(INITIALIZATION_LEVEL_EDITOR);
}
-NativeExtension::NativeExtension() {
+GDExtension::GDExtension() {
}
-NativeExtension::~NativeExtension() {
+GDExtension::~GDExtension() {
if (library != nullptr) {
close_library();
}
}
-extern void gdnative_setup_interface(GDNativeInterface *p_interface);
+extern void gdextension_setup_interface(GDExtensionInterface *p_interface);
-void NativeExtension::initialize_native_extensions() {
- gdnative_setup_interface(&gdnative_interface);
+void GDExtension::initialize_gdextensions() {
+ gdextension_setup_interface(&gdextension_interface);
- gdnative_interface.classdb_register_extension_class = _register_extension_class;
- gdnative_interface.classdb_register_extension_class_method = _register_extension_class_method;
- gdnative_interface.classdb_register_extension_class_integer_constant = _register_extension_class_integer_constant;
- gdnative_interface.classdb_register_extension_class_property = _register_extension_class_property;
- gdnative_interface.classdb_register_extension_class_property_group = _register_extension_class_property_group;
- gdnative_interface.classdb_register_extension_class_property_subgroup = _register_extension_class_property_subgroup;
- gdnative_interface.classdb_register_extension_class_signal = _register_extension_class_signal;
- gdnative_interface.classdb_unregister_extension_class = _unregister_extension_class;
- gdnative_interface.get_library_path = _get_library_path;
+ gdextension_interface.classdb_register_extension_class = _register_extension_class;
+ gdextension_interface.classdb_register_extension_class_method = _register_extension_class_method;
+ gdextension_interface.classdb_register_extension_class_integer_constant = _register_extension_class_integer_constant;
+ gdextension_interface.classdb_register_extension_class_property = _register_extension_class_property;
+ gdextension_interface.classdb_register_extension_class_property_group = _register_extension_class_property_group;
+ gdextension_interface.classdb_register_extension_class_property_subgroup = _register_extension_class_property_subgroup;
+ gdextension_interface.classdb_register_extension_class_signal = _register_extension_class_signal;
+ gdextension_interface.classdb_unregister_extension_class = _unregister_extension_class;
+ gdextension_interface.get_library_path = _get_library_path;
}
-Ref<Resource> NativeExtensionResourceLoader::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) {
+Ref<Resource> GDExtensionResourceLoader::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) {
Ref<ConfigFile> config;
config.instantiate();
@@ -415,28 +520,7 @@ Ref<Resource> NativeExtensionResourceLoader::load(const String &p_path, const St
String entry_symbol = config->get_value("configuration", "entry_symbol");
- List<String> libraries;
-
- config->get_section_keys("libraries", &libraries);
-
- String library_path;
-
- for (const String &E : libraries) {
- Vector<String> tags = E.split(".");
- bool all_tags_met = true;
- for (int i = 0; i < tags.size(); i++) {
- String tag = tags[i].strip_edges();
- if (!OS::get_singleton()->has_feature(tag)) {
- all_tags_met = false;
- break;
- }
- }
-
- if (all_tags_met) {
- library_path = config->get_value("libraries", E);
- break;
- }
- }
+ String library_path = GDExtension::find_extension_library(p_path, config, [](String p_feature) { return OS::get_singleton()->has_feature(p_feature); });
if (library_path.is_empty()) {
if (r_error) {
@@ -451,7 +535,7 @@ Ref<Resource> NativeExtensionResourceLoader::load(const String &p_path, const St
library_path = p_path.get_base_dir().path_join(library_path);
}
- Ref<NativeExtension> lib;
+ Ref<GDExtension> lib;
lib.instantiate();
String abs_path = ProjectSettings::get_singleton()->globalize_path(library_path);
err = lib->open_library(abs_path, entry_symbol);
@@ -468,18 +552,18 @@ Ref<Resource> NativeExtensionResourceLoader::load(const String &p_path, const St
return lib;
}
-void NativeExtensionResourceLoader::get_recognized_extensions(List<String> *p_extensions) const {
+void GDExtensionResourceLoader::get_recognized_extensions(List<String> *p_extensions) const {
p_extensions->push_back("gdextension");
}
-bool NativeExtensionResourceLoader::handles_type(const String &p_type) const {
- return p_type == "NativeExtension";
+bool GDExtensionResourceLoader::handles_type(const String &p_type) const {
+ return p_type == "GDExtension";
}
-String NativeExtensionResourceLoader::get_resource_type(const String &p_path) const {
+String GDExtensionResourceLoader::get_resource_type(const String &p_path) const {
String el = p_path.get_extension().to_lower();
if (el == "gdextension") {
- return "NativeExtension";
+ return "GDExtension";
}
return "";
}
diff --git a/core/extension/native_extension.h b/core/extension/gdextension.h
index 70f6f9f039..26ebdc9a08 100644
--- a/core/extension/native_extension.h
+++ b/core/extension/gdextension.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* native_extension.h */
+/* gdextension.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,36 +28,39 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef NATIVE_EXTENSION_H
-#define NATIVE_EXTENSION_H
+#ifndef GDEXTENSION_H
+#define GDEXTENSION_H
-#include "core/extension/gdnative_interface.h"
+#include <functional>
+
+#include "core/extension/gdextension_interface.h"
+#include "core/io/config_file.h"
#include "core/io/resource_loader.h"
#include "core/object/ref_counted.h"
-class NativeExtension : public Resource {
- GDCLASS(NativeExtension, Resource)
+class GDExtension : public Resource {
+ GDCLASS(GDExtension, Resource)
void *library = nullptr; // pointer if valid,
String library_path;
struct Extension {
- ObjectNativeExtension native_extension;
+ ObjectGDExtension gdextension;
};
HashMap<StringName, Extension> extension_classes;
- static void _register_extension_class(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativeStringNamePtr p_parent_class_name, const GDNativeExtensionClassCreationInfo *p_extension_funcs);
- static void _register_extension_class_method(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativeExtensionClassMethodInfo *p_method_info);
- static void _register_extension_class_integer_constant(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativeStringNamePtr p_enum_name, const GDNativeStringNamePtr p_constant_name, GDNativeInt p_constant_value, GDNativeBool p_is_bitfield);
- static void _register_extension_class_property(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativePropertyInfo *p_info, const GDNativeStringNamePtr p_setter, const GDNativeStringNamePtr p_getter);
- static void _register_extension_class_property_group(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativeStringNamePtr p_group_name, const GDNativeStringNamePtr p_prefix);
- static void _register_extension_class_property_subgroup(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativeStringNamePtr p_subgroup_name, const GDNativeStringNamePtr p_prefix);
- static void _register_extension_class_signal(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativeStringNamePtr p_signal_name, const GDNativePropertyInfo *p_argument_info, GDNativeInt p_argument_count);
- static void _unregister_extension_class(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name);
- static void _get_library_path(const GDNativeExtensionClassLibraryPtr p_library, GDNativeStringPtr r_path);
-
- GDNativeInitialization initialization;
+ static void _register_extension_class(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_parent_class_name, const GDExtensionClassCreationInfo *p_extension_funcs);
+ static void _register_extension_class_method(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, const GDExtensionClassMethodInfo *p_method_info);
+ static void _register_extension_class_integer_constant(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_enum_name, GDExtensionConstStringNamePtr p_constant_name, GDExtensionInt p_constant_value, GDExtensionBool p_is_bitfield);
+ static void _register_extension_class_property(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, const GDExtensionPropertyInfo *p_info, GDExtensionConstStringNamePtr p_setter, GDExtensionConstStringNamePtr p_getter);
+ static void _register_extension_class_property_group(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_group_name, GDExtensionConstStringNamePtr p_prefix);
+ static void _register_extension_class_property_subgroup(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_subgroup_name, GDExtensionConstStringNamePtr p_prefix);
+ static void _register_extension_class_signal(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_signal_name, const GDExtensionPropertyInfo *p_argument_info, GDExtensionInt p_argument_count);
+ static void _unregister_extension_class(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name);
+ static void _get_library_path(GDExtensionClassLibraryPtr p_library, GDExtensionStringPtr r_path);
+
+ GDExtensionInitialization initialization;
int32_t level_initialized = -1;
protected:
@@ -65,15 +68,16 @@ protected:
public:
static String get_extension_list_config_file();
+ static String find_extension_library(const String &p_path, Ref<ConfigFile> p_config, std::function<bool(String)> p_has_feature, PackedStringArray *r_tags = nullptr);
Error open_library(const String &p_path, const String &p_entry_symbol);
void close_library();
enum InitializationLevel {
- INITIALIZATION_LEVEL_CORE = GDNATIVE_INITIALIZATION_CORE,
- INITIALIZATION_LEVEL_SERVERS = GDNATIVE_INITIALIZATION_SERVERS,
- INITIALIZATION_LEVEL_SCENE = GDNATIVE_INITIALIZATION_SCENE,
- INITIALIZATION_LEVEL_EDITOR = GDNATIVE_INITIALIZATION_EDITOR
+ INITIALIZATION_LEVEL_CORE = GDEXTENSION_INITIALIZATION_CORE,
+ INITIALIZATION_LEVEL_SERVERS = GDEXTENSION_INITIALIZATION_SERVERS,
+ INITIALIZATION_LEVEL_SCENE = GDEXTENSION_INITIALIZATION_SCENE,
+ INITIALIZATION_LEVEL_EDITOR = GDEXTENSION_INITIALIZATION_EDITOR
};
bool is_library_open() const;
@@ -82,14 +86,14 @@ public:
void initialize_library(InitializationLevel p_level);
void deinitialize_library(InitializationLevel p_level);
- static void initialize_native_extensions();
- NativeExtension();
- ~NativeExtension();
+ static void initialize_gdextensions();
+ GDExtension();
+ ~GDExtension();
};
-VARIANT_ENUM_CAST(NativeExtension::InitializationLevel)
+VARIANT_ENUM_CAST(GDExtension::InitializationLevel)
-class NativeExtensionResourceLoader : public ResourceFormatLoader {
+class GDExtensionResourceLoader : public ResourceFormatLoader {
public:
virtual Ref<Resource> load(const String &p_path, const String &p_original_path, Error *r_error, 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;
@@ -97,4 +101,4 @@ public:
virtual String get_resource_type(const String &p_path) const;
};
-#endif // NATIVE_EXTENSION_H
+#endif // GDEXTENSION_H
diff --git a/core/extension/gdextension_interface.cpp b/core/extension/gdextension_interface.cpp
new file mode 100644
index 0000000000..2074495aa9
--- /dev/null
+++ b/core/extension/gdextension_interface.cpp
@@ -0,0 +1,1105 @@
+/*************************************************************************/
+/* gdextension_interface.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 "gdextension_interface.h"
+
+#include "core/config/engine.h"
+#include "core/object/class_db.h"
+#include "core/object/script_language_extension.h"
+#include "core/os/memory.h"
+#include "core/variant/variant.h"
+#include "core/version.h"
+
+// Memory Functions
+static void *gdextension_alloc(size_t p_size) {
+ return memalloc(p_size);
+}
+
+static void *gdextension_realloc(void *p_mem, size_t p_size) {
+ return memrealloc(p_mem, p_size);
+}
+
+static void gdextension_free(void *p_mem) {
+ memfree(p_mem);
+}
+
+// Helper print functions.
+static void gdextension_print_error(const char *p_description, const char *p_function, const char *p_file, int32_t p_line) {
+ _err_print_error(p_function, p_file, p_line, p_description, false, ERR_HANDLER_ERROR);
+}
+static void gdextension_print_warning(const char *p_description, const char *p_function, const char *p_file, int32_t p_line) {
+ _err_print_error(p_function, p_file, p_line, p_description, false, ERR_HANDLER_WARNING);
+}
+static void gdextension_print_script_error(const char *p_description, const char *p_function, const char *p_file, int32_t p_line) {
+ _err_print_error(p_function, p_file, p_line, p_description, false, ERR_HANDLER_SCRIPT);
+}
+
+uint64_t gdextension_get_native_struct_size(GDExtensionConstStringNamePtr p_name) {
+ const StringName name = *reinterpret_cast<const StringName *>(p_name);
+ return ClassDB::get_native_struct_size(name);
+}
+
+// Variant functions
+
+static void gdextension_variant_new_copy(GDExtensionVariantPtr r_dest, GDExtensionConstVariantPtr p_src) {
+ memnew_placement(reinterpret_cast<Variant *>(r_dest), Variant(*reinterpret_cast<const Variant *>(p_src)));
+}
+static void gdextension_variant_new_nil(GDExtensionVariantPtr r_dest) {
+ memnew_placement(reinterpret_cast<Variant *>(r_dest), Variant);
+}
+static void gdextension_variant_destroy(GDExtensionVariantPtr p_self) {
+ reinterpret_cast<Variant *>(p_self)->~Variant();
+}
+
+// variant type
+
+static void gdextension_variant_call(GDExtensionVariantPtr p_self, GDExtensionConstStringNamePtr p_method, const GDExtensionConstVariantPtr *p_args, GDExtensionInt p_argcount, GDExtensionVariantPtr r_return, GDExtensionCallError *r_error) {
+ Variant *self = (Variant *)p_self;
+ const StringName method = *reinterpret_cast<const StringName *>(p_method);
+ const Variant **args = (const Variant **)p_args;
+ Variant ret;
+ Callable::CallError error;
+ self->callp(method, args, p_argcount, ret, error);
+ memnew_placement(r_return, Variant(ret));
+
+ if (r_error) {
+ r_error->error = (GDExtensionCallErrorType)(error.error);
+ r_error->argument = error.argument;
+ r_error->expected = error.expected;
+ }
+}
+
+static void gdextension_variant_call_static(GDExtensionVariantType p_type, GDExtensionConstStringNamePtr p_method, const GDExtensionConstVariantPtr *p_args, GDExtensionInt p_argcount, GDExtensionVariantPtr r_return, GDExtensionCallError *r_error) {
+ Variant::Type type = (Variant::Type)p_type;
+ const StringName method = *reinterpret_cast<const StringName *>(p_method);
+ const Variant **args = (const Variant **)p_args;
+ Variant ret;
+ Callable::CallError error;
+ Variant::call_static(type, method, args, p_argcount, ret, error);
+ memnew_placement(r_return, Variant(ret));
+
+ if (r_error) {
+ r_error->error = (GDExtensionCallErrorType)error.error;
+ r_error->argument = error.argument;
+ r_error->expected = error.expected;
+ }
+}
+
+static void gdextension_variant_evaluate(GDExtensionVariantOperator p_op, GDExtensionConstVariantPtr p_a, GDExtensionConstVariantPtr p_b, GDExtensionVariantPtr r_return, GDExtensionBool *r_valid) {
+ Variant::Operator op = (Variant::Operator)p_op;
+ const Variant *a = (const Variant *)p_a;
+ const Variant *b = (const Variant *)p_b;
+ Variant *ret = (Variant *)r_return;
+ bool valid;
+ Variant::evaluate(op, *a, *b, *ret, valid);
+ *r_valid = valid;
+}
+
+static void gdextension_variant_set(GDExtensionVariantPtr p_self, GDExtensionConstVariantPtr p_key, GDExtensionConstVariantPtr p_value, GDExtensionBool *r_valid) {
+ Variant *self = (Variant *)p_self;
+ const Variant *key = (const Variant *)p_key;
+ const Variant *value = (const Variant *)p_value;
+
+ bool valid;
+ self->set(*key, *value, &valid);
+ *r_valid = valid;
+}
+
+static void gdextension_variant_set_named(GDExtensionVariantPtr p_self, GDExtensionConstStringNamePtr p_key, GDExtensionConstVariantPtr p_value, GDExtensionBool *r_valid) {
+ Variant *self = (Variant *)p_self;
+ const StringName *key = (const StringName *)p_key;
+ const Variant *value = (const Variant *)p_value;
+
+ bool valid;
+ self->set_named(*key, *value, valid);
+ *r_valid = valid;
+}
+
+static void gdextension_variant_set_keyed(GDExtensionVariantPtr p_self, GDExtensionConstVariantPtr p_key, GDExtensionConstVariantPtr p_value, GDExtensionBool *r_valid) {
+ Variant *self = (Variant *)p_self;
+ const Variant *key = (const Variant *)p_key;
+ const Variant *value = (const Variant *)p_value;
+
+ bool valid;
+ self->set_keyed(*key, *value, valid);
+ *r_valid = valid;
+}
+
+static void gdextension_variant_set_indexed(GDExtensionVariantPtr p_self, GDExtensionInt p_index, GDExtensionConstVariantPtr p_value, GDExtensionBool *r_valid, GDExtensionBool *r_oob) {
+ Variant *self = (Variant *)p_self;
+ const Variant *value = (const Variant *)p_value;
+
+ bool valid;
+ bool oob;
+ self->set_indexed(p_index, *value, valid, oob);
+ *r_valid = valid;
+ *r_oob = oob;
+}
+
+static void gdextension_variant_get(GDExtensionConstVariantPtr p_self, GDExtensionConstVariantPtr p_key, GDExtensionVariantPtr r_ret, GDExtensionBool *r_valid) {
+ const Variant *self = (const Variant *)p_self;
+ const Variant *key = (const Variant *)p_key;
+
+ bool valid;
+ memnew_placement(r_ret, Variant(self->get(*key, &valid)));
+ *r_valid = valid;
+}
+
+static void gdextension_variant_get_named(GDExtensionConstVariantPtr p_self, GDExtensionConstStringNamePtr p_key, GDExtensionVariantPtr r_ret, GDExtensionBool *r_valid) {
+ const Variant *self = (const Variant *)p_self;
+ const StringName *key = (const StringName *)p_key;
+
+ bool valid;
+ memnew_placement(r_ret, Variant(self->get_named(*key, valid)));
+ *r_valid = valid;
+}
+
+static void gdextension_variant_get_keyed(GDExtensionConstVariantPtr p_self, GDExtensionConstVariantPtr p_key, GDExtensionVariantPtr r_ret, GDExtensionBool *r_valid) {
+ const Variant *self = (const Variant *)p_self;
+ const Variant *key = (const Variant *)p_key;
+
+ bool valid;
+ memnew_placement(r_ret, Variant(self->get_keyed(*key, valid)));
+ *r_valid = valid;
+}
+
+static void gdextension_variant_get_indexed(GDExtensionConstVariantPtr p_self, GDExtensionInt p_index, GDExtensionVariantPtr r_ret, GDExtensionBool *r_valid, GDExtensionBool *r_oob) {
+ const Variant *self = (const Variant *)p_self;
+
+ bool valid;
+ bool oob;
+ memnew_placement(r_ret, Variant(self->get_indexed(p_index, valid, oob)));
+ *r_valid = valid;
+ *r_oob = oob;
+}
+
+/// Iteration.
+static GDExtensionBool gdextension_variant_iter_init(GDExtensionConstVariantPtr p_self, GDExtensionVariantPtr r_iter, GDExtensionBool *r_valid) {
+ const Variant *self = (const Variant *)p_self;
+ Variant *iter = (Variant *)r_iter;
+
+ bool valid;
+ bool ret = self->iter_init(*iter, valid);
+ *r_valid = valid;
+ return ret;
+}
+
+static GDExtensionBool gdextension_variant_iter_next(GDExtensionConstVariantPtr p_self, GDExtensionVariantPtr r_iter, GDExtensionBool *r_valid) {
+ const Variant *self = (const Variant *)p_self;
+ Variant *iter = (Variant *)r_iter;
+
+ bool valid;
+ bool ret = self->iter_next(*iter, valid);
+ *r_valid = valid;
+ return ret;
+}
+
+static void gdextension_variant_iter_get(GDExtensionConstVariantPtr p_self, GDExtensionVariantPtr r_iter, GDExtensionVariantPtr r_ret, GDExtensionBool *r_valid) {
+ const Variant *self = (const Variant *)p_self;
+ Variant *iter = (Variant *)r_iter;
+
+ bool valid;
+ memnew_placement(r_ret, Variant(self->iter_next(*iter, valid)));
+ *r_valid = valid;
+}
+
+/// Variant functions.
+static GDExtensionInt gdextension_variant_hash(GDExtensionConstVariantPtr p_self) {
+ const Variant *self = (const Variant *)p_self;
+ return self->hash();
+}
+
+static GDExtensionInt gdextension_variant_recursive_hash(GDExtensionConstVariantPtr p_self, GDExtensionInt p_recursion_count) {
+ const Variant *self = (const Variant *)p_self;
+ return self->recursive_hash(p_recursion_count);
+}
+
+static GDExtensionBool gdextension_variant_hash_compare(GDExtensionConstVariantPtr p_self, GDExtensionConstVariantPtr p_other) {
+ const Variant *self = (const Variant *)p_self;
+ const Variant *other = (const Variant *)p_other;
+ return self->hash_compare(*other);
+}
+
+static GDExtensionBool gdextension_variant_booleanize(GDExtensionConstVariantPtr p_self) {
+ const Variant *self = (const Variant *)p_self;
+ return self->booleanize();
+}
+
+static void gdextension_variant_duplicate(GDExtensionConstVariantPtr p_self, GDExtensionVariantPtr r_ret, GDExtensionBool p_deep) {
+ const Variant *self = (const Variant *)p_self;
+ memnew_placement(r_ret, Variant(self->duplicate(p_deep)));
+}
+
+static void gdextension_variant_stringify(GDExtensionConstVariantPtr p_self, GDExtensionStringPtr r_ret) {
+ const Variant *self = (const Variant *)p_self;
+ memnew_placement(r_ret, String(*self));
+}
+
+static GDExtensionVariantType gdextension_variant_get_type(GDExtensionConstVariantPtr p_self) {
+ const Variant *self = (const Variant *)p_self;
+ return (GDExtensionVariantType)self->get_type();
+}
+
+static GDExtensionBool gdextension_variant_has_method(GDExtensionConstVariantPtr p_self, GDExtensionConstStringNamePtr p_method) {
+ const Variant *self = (const Variant *)p_self;
+ const StringName *method = (const StringName *)p_method;
+ return self->has_method(*method);
+}
+
+static GDExtensionBool gdextension_variant_has_member(GDExtensionVariantType p_type, GDExtensionConstStringNamePtr p_member) {
+ return Variant::has_member((Variant::Type)p_type, *((const StringName *)p_member));
+}
+
+static GDExtensionBool gdextension_variant_has_key(GDExtensionConstVariantPtr p_self, GDExtensionConstVariantPtr p_key, GDExtensionBool *r_valid) {
+ const Variant *self = (const Variant *)p_self;
+ const Variant *key = (const Variant *)p_key;
+ bool valid;
+ bool ret = self->has_key(*key, valid);
+ *r_valid = valid;
+ return ret;
+}
+
+static void gdextension_variant_get_type_name(GDExtensionVariantType p_type, GDExtensionStringPtr r_ret) {
+ String name = Variant::get_type_name((Variant::Type)p_type);
+ memnew_placement(r_ret, String(name));
+}
+
+static GDExtensionBool gdextension_variant_can_convert(GDExtensionVariantType p_from, GDExtensionVariantType p_to) {
+ return Variant::can_convert((Variant::Type)p_from, (Variant::Type)p_to);
+}
+
+static GDExtensionBool gdextension_variant_can_convert_strict(GDExtensionVariantType p_from, GDExtensionVariantType p_to) {
+ return Variant::can_convert_strict((Variant::Type)p_from, (Variant::Type)p_to);
+}
+
+// Variant interaction.
+static GDExtensionVariantFromTypeConstructorFunc gdextension_get_variant_from_type_constructor(GDExtensionVariantType p_type) {
+ switch (p_type) {
+ case GDEXTENSION_VARIANT_TYPE_BOOL:
+ return VariantTypeConstructor<bool>::variant_from_type;
+ case GDEXTENSION_VARIANT_TYPE_INT:
+ return VariantTypeConstructor<int64_t>::variant_from_type;
+ case GDEXTENSION_VARIANT_TYPE_FLOAT:
+ return VariantTypeConstructor<double>::variant_from_type;
+ case GDEXTENSION_VARIANT_TYPE_STRING:
+ return VariantTypeConstructor<String>::variant_from_type;
+ case GDEXTENSION_VARIANT_TYPE_VECTOR2:
+ return VariantTypeConstructor<Vector2>::variant_from_type;
+ case GDEXTENSION_VARIANT_TYPE_VECTOR2I:
+ return VariantTypeConstructor<Vector2i>::variant_from_type;
+ case GDEXTENSION_VARIANT_TYPE_RECT2:
+ return VariantTypeConstructor<Rect2>::variant_from_type;
+ case GDEXTENSION_VARIANT_TYPE_RECT2I:
+ return VariantTypeConstructor<Rect2i>::variant_from_type;
+ case GDEXTENSION_VARIANT_TYPE_VECTOR3:
+ return VariantTypeConstructor<Vector3>::variant_from_type;
+ case GDEXTENSION_VARIANT_TYPE_VECTOR3I:
+ return VariantTypeConstructor<Vector3i>::variant_from_type;
+ case GDEXTENSION_VARIANT_TYPE_TRANSFORM2D:
+ return VariantTypeConstructor<Transform2D>::variant_from_type;
+ case GDEXTENSION_VARIANT_TYPE_VECTOR4:
+ return VariantTypeConstructor<Vector4>::variant_from_type;
+ case GDEXTENSION_VARIANT_TYPE_VECTOR4I:
+ return VariantTypeConstructor<Vector4i>::variant_from_type;
+ case GDEXTENSION_VARIANT_TYPE_PLANE:
+ return VariantTypeConstructor<Plane>::variant_from_type;
+ case GDEXTENSION_VARIANT_TYPE_QUATERNION:
+ return VariantTypeConstructor<Quaternion>::variant_from_type;
+ case GDEXTENSION_VARIANT_TYPE_AABB:
+ return VariantTypeConstructor<AABB>::variant_from_type;
+ case GDEXTENSION_VARIANT_TYPE_BASIS:
+ return VariantTypeConstructor<Basis>::variant_from_type;
+ case GDEXTENSION_VARIANT_TYPE_TRANSFORM3D:
+ return VariantTypeConstructor<Transform3D>::variant_from_type;
+ case GDEXTENSION_VARIANT_TYPE_PROJECTION:
+ return VariantTypeConstructor<Projection>::variant_from_type;
+ case GDEXTENSION_VARIANT_TYPE_COLOR:
+ return VariantTypeConstructor<Color>::variant_from_type;
+ case GDEXTENSION_VARIANT_TYPE_STRING_NAME:
+ return VariantTypeConstructor<StringName>::variant_from_type;
+ case GDEXTENSION_VARIANT_TYPE_NODE_PATH:
+ return VariantTypeConstructor<NodePath>::variant_from_type;
+ case GDEXTENSION_VARIANT_TYPE_RID:
+ return VariantTypeConstructor<RID>::variant_from_type;
+ case GDEXTENSION_VARIANT_TYPE_OBJECT:
+ return VariantTypeConstructor<Object *>::variant_from_type;
+ case GDEXTENSION_VARIANT_TYPE_CALLABLE:
+ return VariantTypeConstructor<Callable>::variant_from_type;
+ case GDEXTENSION_VARIANT_TYPE_SIGNAL:
+ return VariantTypeConstructor<Signal>::variant_from_type;
+ case GDEXTENSION_VARIANT_TYPE_DICTIONARY:
+ return VariantTypeConstructor<Dictionary>::variant_from_type;
+ case GDEXTENSION_VARIANT_TYPE_ARRAY:
+ return VariantTypeConstructor<Array>::variant_from_type;
+ case GDEXTENSION_VARIANT_TYPE_PACKED_BYTE_ARRAY:
+ return VariantTypeConstructor<PackedByteArray>::variant_from_type;
+ case GDEXTENSION_VARIANT_TYPE_PACKED_INT32_ARRAY:
+ return VariantTypeConstructor<PackedInt32Array>::variant_from_type;
+ case GDEXTENSION_VARIANT_TYPE_PACKED_INT64_ARRAY:
+ return VariantTypeConstructor<PackedInt64Array>::variant_from_type;
+ case GDEXTENSION_VARIANT_TYPE_PACKED_FLOAT32_ARRAY:
+ return VariantTypeConstructor<PackedFloat32Array>::variant_from_type;
+ case GDEXTENSION_VARIANT_TYPE_PACKED_FLOAT64_ARRAY:
+ return VariantTypeConstructor<PackedFloat64Array>::variant_from_type;
+ case GDEXTENSION_VARIANT_TYPE_PACKED_STRING_ARRAY:
+ return VariantTypeConstructor<PackedStringArray>::variant_from_type;
+ case GDEXTENSION_VARIANT_TYPE_PACKED_VECTOR2_ARRAY:
+ return VariantTypeConstructor<PackedVector2Array>::variant_from_type;
+ case GDEXTENSION_VARIANT_TYPE_PACKED_VECTOR3_ARRAY:
+ return VariantTypeConstructor<PackedVector3Array>::variant_from_type;
+ case GDEXTENSION_VARIANT_TYPE_PACKED_COLOR_ARRAY:
+ return VariantTypeConstructor<PackedColorArray>::variant_from_type;
+ case GDEXTENSION_VARIANT_TYPE_NIL:
+ case GDEXTENSION_VARIANT_TYPE_VARIANT_MAX:
+ ERR_FAIL_V_MSG(nullptr, "Getting Variant conversion function with invalid type");
+ }
+ ERR_FAIL_V_MSG(nullptr, "Getting Variant conversion function with invalid type");
+}
+
+static GDExtensionTypeFromVariantConstructorFunc gdextension_get_type_from_variant_constructor(GDExtensionVariantType p_type) {
+ switch (p_type) {
+ case GDEXTENSION_VARIANT_TYPE_BOOL:
+ return VariantTypeConstructor<bool>::type_from_variant;
+ case GDEXTENSION_VARIANT_TYPE_INT:
+ return VariantTypeConstructor<int64_t>::type_from_variant;
+ case GDEXTENSION_VARIANT_TYPE_FLOAT:
+ return VariantTypeConstructor<double>::type_from_variant;
+ case GDEXTENSION_VARIANT_TYPE_STRING:
+ return VariantTypeConstructor<String>::type_from_variant;
+ case GDEXTENSION_VARIANT_TYPE_VECTOR2:
+ return VariantTypeConstructor<Vector2>::type_from_variant;
+ case GDEXTENSION_VARIANT_TYPE_VECTOR2I:
+ return VariantTypeConstructor<Vector2i>::type_from_variant;
+ case GDEXTENSION_VARIANT_TYPE_RECT2:
+ return VariantTypeConstructor<Rect2>::type_from_variant;
+ case GDEXTENSION_VARIANT_TYPE_RECT2I:
+ return VariantTypeConstructor<Rect2i>::type_from_variant;
+ case GDEXTENSION_VARIANT_TYPE_VECTOR3:
+ return VariantTypeConstructor<Vector3>::type_from_variant;
+ case GDEXTENSION_VARIANT_TYPE_VECTOR3I:
+ return VariantTypeConstructor<Vector3i>::type_from_variant;
+ case GDEXTENSION_VARIANT_TYPE_TRANSFORM2D:
+ return VariantTypeConstructor<Transform2D>::type_from_variant;
+ case GDEXTENSION_VARIANT_TYPE_VECTOR4:
+ return VariantTypeConstructor<Vector4>::type_from_variant;
+ case GDEXTENSION_VARIANT_TYPE_VECTOR4I:
+ return VariantTypeConstructor<Vector4i>::type_from_variant;
+ case GDEXTENSION_VARIANT_TYPE_PLANE:
+ return VariantTypeConstructor<Plane>::type_from_variant;
+ case GDEXTENSION_VARIANT_TYPE_QUATERNION:
+ return VariantTypeConstructor<Quaternion>::type_from_variant;
+ case GDEXTENSION_VARIANT_TYPE_AABB:
+ return VariantTypeConstructor<AABB>::type_from_variant;
+ case GDEXTENSION_VARIANT_TYPE_BASIS:
+ return VariantTypeConstructor<Basis>::type_from_variant;
+ case GDEXTENSION_VARIANT_TYPE_TRANSFORM3D:
+ return VariantTypeConstructor<Transform3D>::type_from_variant;
+ case GDEXTENSION_VARIANT_TYPE_PROJECTION:
+ return VariantTypeConstructor<Projection>::type_from_variant;
+ case GDEXTENSION_VARIANT_TYPE_COLOR:
+ return VariantTypeConstructor<Color>::type_from_variant;
+ case GDEXTENSION_VARIANT_TYPE_STRING_NAME:
+ return VariantTypeConstructor<StringName>::type_from_variant;
+ case GDEXTENSION_VARIANT_TYPE_NODE_PATH:
+ return VariantTypeConstructor<NodePath>::type_from_variant;
+ case GDEXTENSION_VARIANT_TYPE_RID:
+ return VariantTypeConstructor<RID>::type_from_variant;
+ case GDEXTENSION_VARIANT_TYPE_OBJECT:
+ return VariantTypeConstructor<Object *>::type_from_variant;
+ case GDEXTENSION_VARIANT_TYPE_CALLABLE:
+ return VariantTypeConstructor<Callable>::type_from_variant;
+ case GDEXTENSION_VARIANT_TYPE_SIGNAL:
+ return VariantTypeConstructor<Signal>::type_from_variant;
+ case GDEXTENSION_VARIANT_TYPE_DICTIONARY:
+ return VariantTypeConstructor<Dictionary>::type_from_variant;
+ case GDEXTENSION_VARIANT_TYPE_ARRAY:
+ return VariantTypeConstructor<Array>::type_from_variant;
+ case GDEXTENSION_VARIANT_TYPE_PACKED_BYTE_ARRAY:
+ return VariantTypeConstructor<PackedByteArray>::type_from_variant;
+ case GDEXTENSION_VARIANT_TYPE_PACKED_INT32_ARRAY:
+ return VariantTypeConstructor<PackedInt32Array>::type_from_variant;
+ case GDEXTENSION_VARIANT_TYPE_PACKED_INT64_ARRAY:
+ return VariantTypeConstructor<PackedInt64Array>::type_from_variant;
+ case GDEXTENSION_VARIANT_TYPE_PACKED_FLOAT32_ARRAY:
+ return VariantTypeConstructor<PackedFloat32Array>::type_from_variant;
+ case GDEXTENSION_VARIANT_TYPE_PACKED_FLOAT64_ARRAY:
+ return VariantTypeConstructor<PackedFloat64Array>::type_from_variant;
+ case GDEXTENSION_VARIANT_TYPE_PACKED_STRING_ARRAY:
+ return VariantTypeConstructor<PackedStringArray>::type_from_variant;
+ case GDEXTENSION_VARIANT_TYPE_PACKED_VECTOR2_ARRAY:
+ return VariantTypeConstructor<PackedVector2Array>::type_from_variant;
+ case GDEXTENSION_VARIANT_TYPE_PACKED_VECTOR3_ARRAY:
+ return VariantTypeConstructor<PackedVector3Array>::type_from_variant;
+ case GDEXTENSION_VARIANT_TYPE_PACKED_COLOR_ARRAY:
+ return VariantTypeConstructor<PackedColorArray>::type_from_variant;
+ case GDEXTENSION_VARIANT_TYPE_NIL:
+ case GDEXTENSION_VARIANT_TYPE_VARIANT_MAX:
+ ERR_FAIL_V_MSG(nullptr, "Getting Variant conversion function with invalid type");
+ }
+ ERR_FAIL_V_MSG(nullptr, "Getting Variant conversion function with invalid type");
+}
+
+// ptrcalls
+static GDExtensionPtrOperatorEvaluator gdextension_variant_get_ptr_operator_evaluator(GDExtensionVariantOperator p_operator, GDExtensionVariantType p_type_a, GDExtensionVariantType p_type_b) {
+ return (GDExtensionPtrOperatorEvaluator)Variant::get_ptr_operator_evaluator(Variant::Operator(p_operator), Variant::Type(p_type_a), Variant::Type(p_type_b));
+}
+static GDExtensionPtrBuiltInMethod gdextension_variant_get_ptr_builtin_method(GDExtensionVariantType p_type, GDExtensionConstStringNamePtr p_method, GDExtensionInt p_hash) {
+ const StringName method = *reinterpret_cast<const StringName *>(p_method);
+ uint32_t hash = Variant::get_builtin_method_hash(Variant::Type(p_type), method);
+ if (hash != p_hash) {
+ ERR_PRINT_ONCE("Error getting method " + method + ", hash mismatch.");
+ return nullptr;
+ }
+
+ return (GDExtensionPtrBuiltInMethod)Variant::get_ptr_builtin_method(Variant::Type(p_type), method);
+}
+static GDExtensionPtrConstructor gdextension_variant_get_ptr_constructor(GDExtensionVariantType p_type, int32_t p_constructor) {
+ return (GDExtensionPtrConstructor)Variant::get_ptr_constructor(Variant::Type(p_type), p_constructor);
+}
+static GDExtensionPtrDestructor gdextension_variant_get_ptr_destructor(GDExtensionVariantType p_type) {
+ return (GDExtensionPtrDestructor)Variant::get_ptr_destructor(Variant::Type(p_type));
+}
+static void gdextension_variant_construct(GDExtensionVariantType p_type, GDExtensionVariantPtr p_base, const GDExtensionConstVariantPtr *p_args, int32_t p_argument_count, GDExtensionCallError *r_error) {
+ memnew_placement(p_base, Variant);
+
+ Callable::CallError error;
+ Variant::construct(Variant::Type(p_type), *(Variant *)p_base, (const Variant **)p_args, p_argument_count, error);
+
+ if (r_error) {
+ r_error->error = (GDExtensionCallErrorType)(error.error);
+ r_error->argument = error.argument;
+ r_error->expected = error.expected;
+ }
+}
+static GDExtensionPtrSetter gdextension_variant_get_ptr_setter(GDExtensionVariantType p_type, GDExtensionConstStringNamePtr p_member) {
+ const StringName member = *reinterpret_cast<const StringName *>(p_member);
+ return (GDExtensionPtrSetter)Variant::get_member_ptr_setter(Variant::Type(p_type), member);
+}
+static GDExtensionPtrGetter gdextension_variant_get_ptr_getter(GDExtensionVariantType p_type, GDExtensionConstStringNamePtr p_member) {
+ const StringName member = *reinterpret_cast<const StringName *>(p_member);
+ return (GDExtensionPtrGetter)Variant::get_member_ptr_getter(Variant::Type(p_type), member);
+}
+static GDExtensionPtrIndexedSetter gdextension_variant_get_ptr_indexed_setter(GDExtensionVariantType p_type) {
+ return (GDExtensionPtrIndexedSetter)Variant::get_member_ptr_indexed_setter(Variant::Type(p_type));
+}
+static GDExtensionPtrIndexedGetter gdextension_variant_get_ptr_indexed_getter(GDExtensionVariantType p_type) {
+ return (GDExtensionPtrIndexedGetter)Variant::get_member_ptr_indexed_getter(Variant::Type(p_type));
+}
+static GDExtensionPtrKeyedSetter gdextension_variant_get_ptr_keyed_setter(GDExtensionVariantType p_type) {
+ return (GDExtensionPtrKeyedSetter)Variant::get_member_ptr_keyed_setter(Variant::Type(p_type));
+}
+static GDExtensionPtrKeyedGetter gdextension_variant_get_ptr_keyed_getter(GDExtensionVariantType p_type) {
+ return (GDExtensionPtrKeyedGetter)Variant::get_member_ptr_keyed_getter(Variant::Type(p_type));
+}
+static GDExtensionPtrKeyedChecker gdextension_variant_get_ptr_keyed_checker(GDExtensionVariantType p_type) {
+ return (GDExtensionPtrKeyedChecker)Variant::get_member_ptr_keyed_checker(Variant::Type(p_type));
+}
+static void gdextension_variant_get_constant_value(GDExtensionVariantType p_type, GDExtensionConstStringNamePtr p_constant, GDExtensionVariantPtr r_ret) {
+ StringName constant = *reinterpret_cast<const StringName *>(p_constant);
+ memnew_placement(r_ret, Variant(Variant::get_constant_value(Variant::Type(p_type), constant)));
+}
+static GDExtensionPtrUtilityFunction gdextension_variant_get_ptr_utility_function(GDExtensionConstStringNamePtr p_function, GDExtensionInt p_hash) {
+ StringName function = *reinterpret_cast<const StringName *>(p_function);
+ uint32_t hash = Variant::get_utility_function_hash(function);
+ if (hash != p_hash) {
+ ERR_PRINT_ONCE("Error getting utility function " + function + ", hash mismatch.");
+ return nullptr;
+ }
+ return (GDExtensionPtrUtilityFunction)Variant::get_ptr_utility_function(function);
+}
+
+//string helpers
+
+static void gdextension_string_new_with_latin1_chars(GDExtensionStringPtr r_dest, const char *p_contents) {
+ String *dest = (String *)r_dest;
+ memnew_placement(dest, String);
+ *dest = String(p_contents);
+}
+
+static void gdextension_string_new_with_utf8_chars(GDExtensionStringPtr r_dest, const char *p_contents) {
+ String *dest = (String *)r_dest;
+ memnew_placement(dest, String);
+ dest->parse_utf8(p_contents);
+}
+
+static void gdextension_string_new_with_utf16_chars(GDExtensionStringPtr r_dest, const char16_t *p_contents) {
+ String *dest = (String *)r_dest;
+ memnew_placement(dest, String);
+ dest->parse_utf16(p_contents);
+}
+
+static void gdextension_string_new_with_utf32_chars(GDExtensionStringPtr r_dest, const char32_t *p_contents) {
+ String *dest = (String *)r_dest;
+ memnew_placement(dest, String);
+ *dest = String((const char32_t *)p_contents);
+}
+
+static void gdextension_string_new_with_wide_chars(GDExtensionStringPtr r_dest, const wchar_t *p_contents) {
+ String *dest = (String *)r_dest;
+ if constexpr (sizeof(wchar_t) == 2) {
+ // wchar_t is 16 bit, parse.
+ memnew_placement(dest, String);
+ dest->parse_utf16((const char16_t *)p_contents);
+ } else {
+ // wchar_t is 32 bit, copy.
+ memnew_placement(dest, String);
+ *dest = String((const char32_t *)p_contents);
+ }
+}
+
+static void gdextension_string_new_with_latin1_chars_and_len(GDExtensionStringPtr r_dest, const char *p_contents, GDExtensionInt p_size) {
+ String *dest = (String *)r_dest;
+ memnew_placement(dest, String);
+ *dest = String(p_contents, p_size);
+}
+
+static void gdextension_string_new_with_utf8_chars_and_len(GDExtensionStringPtr r_dest, const char *p_contents, GDExtensionInt p_size) {
+ String *dest = (String *)r_dest;
+ memnew_placement(dest, String);
+ dest->parse_utf8(p_contents, p_size);
+}
+
+static void gdextension_string_new_with_utf16_chars_and_len(GDExtensionStringPtr r_dest, const char16_t *p_contents, GDExtensionInt p_size) {
+ String *dest = (String *)r_dest;
+ memnew_placement(dest, String);
+ dest->parse_utf16(p_contents, p_size);
+}
+
+static void gdextension_string_new_with_utf32_chars_and_len(GDExtensionStringPtr r_dest, const char32_t *p_contents, GDExtensionInt p_size) {
+ String *dest = (String *)r_dest;
+ memnew_placement(dest, String);
+ *dest = String((const char32_t *)p_contents, p_size);
+}
+
+static void gdextension_string_new_with_wide_chars_and_len(GDExtensionStringPtr r_dest, const wchar_t *p_contents, GDExtensionInt p_size) {
+ String *dest = (String *)r_dest;
+ if constexpr (sizeof(wchar_t) == 2) {
+ // wchar_t is 16 bit, parse.
+ memnew_placement(dest, String);
+ dest->parse_utf16((const char16_t *)p_contents, p_size);
+ } else {
+ // wchar_t is 32 bit, copy.
+ memnew_placement(dest, String);
+ *dest = String((const char32_t *)p_contents, p_size);
+ }
+}
+
+static GDExtensionInt gdextension_string_to_latin1_chars(GDExtensionConstStringPtr p_self, char *r_text, GDExtensionInt p_max_write_length) {
+ String *self = (String *)p_self;
+ CharString cs = self->ascii(true);
+ GDExtensionInt len = cs.length();
+ if (r_text) {
+ const char *s_text = cs.ptr();
+ for (GDExtensionInt i = 0; i < MIN(len, p_max_write_length); i++) {
+ r_text[i] = s_text[i];
+ }
+ }
+ return len;
+}
+static GDExtensionInt gdextension_string_to_utf8_chars(GDExtensionConstStringPtr p_self, char *r_text, GDExtensionInt p_max_write_length) {
+ String *self = (String *)p_self;
+ CharString cs = self->utf8();
+ GDExtensionInt len = cs.length();
+ if (r_text) {
+ const char *s_text = cs.ptr();
+ for (GDExtensionInt i = 0; i < MIN(len, p_max_write_length); i++) {
+ r_text[i] = s_text[i];
+ }
+ }
+ return len;
+}
+static GDExtensionInt gdextension_string_to_utf16_chars(GDExtensionConstStringPtr p_self, char16_t *r_text, GDExtensionInt p_max_write_length) {
+ String *self = (String *)p_self;
+ Char16String cs = self->utf16();
+ GDExtensionInt len = cs.length();
+ if (r_text) {
+ const char16_t *s_text = cs.ptr();
+ for (GDExtensionInt i = 0; i < MIN(len, p_max_write_length); i++) {
+ r_text[i] = s_text[i];
+ }
+ }
+ return len;
+}
+static GDExtensionInt gdextension_string_to_utf32_chars(GDExtensionConstStringPtr p_self, char32_t *r_text, GDExtensionInt p_max_write_length) {
+ String *self = (String *)p_self;
+ GDExtensionInt len = self->length();
+ if (r_text) {
+ const char32_t *s_text = self->ptr();
+ for (GDExtensionInt i = 0; i < MIN(len, p_max_write_length); i++) {
+ r_text[i] = s_text[i];
+ }
+ }
+ return len;
+}
+static GDExtensionInt gdextension_string_to_wide_chars(GDExtensionConstStringPtr p_self, wchar_t *r_text, GDExtensionInt p_max_write_length) {
+ if constexpr (sizeof(wchar_t) == 4) {
+ return gdextension_string_to_utf32_chars(p_self, (char32_t *)r_text, p_max_write_length);
+ } else {
+ return gdextension_string_to_utf16_chars(p_self, (char16_t *)r_text, p_max_write_length);
+ }
+}
+
+static char32_t *gdextension_string_operator_index(GDExtensionStringPtr p_self, GDExtensionInt p_index) {
+ String *self = (String *)p_self;
+ ERR_FAIL_INDEX_V(p_index, self->length() + 1, nullptr);
+ return &self->ptrw()[p_index];
+}
+
+static const char32_t *gdextension_string_operator_index_const(GDExtensionConstStringPtr p_self, GDExtensionInt p_index) {
+ const String *self = (const String *)p_self;
+ ERR_FAIL_INDEX_V(p_index, self->length() + 1, nullptr);
+ return &self->ptr()[p_index];
+}
+
+/* Packed array functions */
+
+static uint8_t *gdextension_packed_byte_array_operator_index(GDExtensionTypePtr p_self, GDExtensionInt p_index) {
+ PackedByteArray *self = (PackedByteArray *)p_self;
+ ERR_FAIL_INDEX_V(p_index, self->size(), nullptr);
+ return &self->ptrw()[p_index];
+}
+
+static const uint8_t *gdextension_packed_byte_array_operator_index_const(GDExtensionConstTypePtr p_self, GDExtensionInt p_index) {
+ const PackedByteArray *self = (const PackedByteArray *)p_self;
+ ERR_FAIL_INDEX_V(p_index, self->size(), nullptr);
+ return &self->ptr()[p_index];
+}
+
+static GDExtensionTypePtr gdextension_packed_color_array_operator_index(GDExtensionTypePtr p_self, GDExtensionInt p_index) {
+ PackedColorArray *self = (PackedColorArray *)p_self;
+ ERR_FAIL_INDEX_V(p_index, self->size(), nullptr);
+ return (GDExtensionTypePtr)&self->ptrw()[p_index];
+}
+
+static GDExtensionTypePtr gdextension_packed_color_array_operator_index_const(GDExtensionConstTypePtr p_self, GDExtensionInt p_index) {
+ const PackedColorArray *self = (const PackedColorArray *)p_self;
+ ERR_FAIL_INDEX_V(p_index, self->size(), nullptr);
+ return (GDExtensionTypePtr)&self->ptr()[p_index];
+}
+
+static float *gdextension_packed_float32_array_operator_index(GDExtensionTypePtr p_self, GDExtensionInt p_index) {
+ PackedFloat32Array *self = (PackedFloat32Array *)p_self;
+ ERR_FAIL_INDEX_V(p_index, self->size(), nullptr);
+ return &self->ptrw()[p_index];
+}
+
+static const float *gdextension_packed_float32_array_operator_index_const(GDExtensionConstTypePtr p_self, GDExtensionInt p_index) {
+ const PackedFloat32Array *self = (const PackedFloat32Array *)p_self;
+ ERR_FAIL_INDEX_V(p_index, self->size(), nullptr);
+ return &self->ptr()[p_index];
+}
+
+static double *gdextension_packed_float64_array_operator_index(GDExtensionTypePtr p_self, GDExtensionInt p_index) {
+ PackedFloat64Array *self = (PackedFloat64Array *)p_self;
+ ERR_FAIL_INDEX_V(p_index, self->size(), nullptr);
+ return &self->ptrw()[p_index];
+}
+
+static const double *gdextension_packed_float64_array_operator_index_const(GDExtensionConstTypePtr p_self, GDExtensionInt p_index) {
+ const PackedFloat64Array *self = (const PackedFloat64Array *)p_self;
+ ERR_FAIL_INDEX_V(p_index, self->size(), nullptr);
+ return &self->ptr()[p_index];
+}
+
+static int32_t *gdextension_packed_int32_array_operator_index(GDExtensionTypePtr p_self, GDExtensionInt p_index) {
+ PackedInt32Array *self = (PackedInt32Array *)p_self;
+ ERR_FAIL_INDEX_V(p_index, self->size(), nullptr);
+ return &self->ptrw()[p_index];
+}
+
+static const int32_t *gdextension_packed_int32_array_operator_index_const(GDExtensionConstTypePtr p_self, GDExtensionInt p_index) {
+ const PackedInt32Array *self = (const PackedInt32Array *)p_self;
+ ERR_FAIL_INDEX_V(p_index, self->size(), nullptr);
+ return &self->ptr()[p_index];
+}
+
+static int64_t *gdextension_packed_int64_array_operator_index(GDExtensionTypePtr p_self, GDExtensionInt p_index) {
+ PackedInt64Array *self = (PackedInt64Array *)p_self;
+ ERR_FAIL_INDEX_V(p_index, self->size(), nullptr);
+ return &self->ptrw()[p_index];
+}
+
+static const int64_t *gdextension_packed_int64_array_operator_index_const(GDExtensionConstTypePtr p_self, GDExtensionInt p_index) {
+ const PackedInt64Array *self = (const PackedInt64Array *)p_self;
+ ERR_FAIL_INDEX_V(p_index, self->size(), nullptr);
+ return &self->ptr()[p_index];
+}
+
+static GDExtensionStringPtr gdextension_packed_string_array_operator_index(GDExtensionTypePtr p_self, GDExtensionInt p_index) {
+ PackedStringArray *self = (PackedStringArray *)p_self;
+ ERR_FAIL_INDEX_V(p_index, self->size(), nullptr);
+ return (GDExtensionStringPtr)&self->ptrw()[p_index];
+}
+
+static GDExtensionStringPtr gdextension_packed_string_array_operator_index_const(GDExtensionConstTypePtr p_self, GDExtensionInt p_index) {
+ const PackedStringArray *self = (const PackedStringArray *)p_self;
+ ERR_FAIL_INDEX_V(p_index, self->size(), nullptr);
+ return (GDExtensionStringPtr)&self->ptr()[p_index];
+}
+
+static GDExtensionTypePtr gdextension_packed_vector2_array_operator_index(GDExtensionTypePtr p_self, GDExtensionInt p_index) {
+ PackedVector2Array *self = (PackedVector2Array *)p_self;
+ ERR_FAIL_INDEX_V(p_index, self->size(), nullptr);
+ return (GDExtensionTypePtr)&self->ptrw()[p_index];
+}
+
+static GDExtensionTypePtr gdextension_packed_vector2_array_operator_index_const(GDExtensionConstTypePtr p_self, GDExtensionInt p_index) {
+ const PackedVector2Array *self = (const PackedVector2Array *)p_self;
+ ERR_FAIL_INDEX_V(p_index, self->size(), nullptr);
+ return (GDExtensionTypePtr)&self->ptr()[p_index];
+}
+
+static GDExtensionTypePtr gdextension_packed_vector3_array_operator_index(GDExtensionTypePtr p_self, GDExtensionInt p_index) {
+ PackedVector3Array *self = (PackedVector3Array *)p_self;
+ ERR_FAIL_INDEX_V(p_index, self->size(), nullptr);
+ return (GDExtensionTypePtr)&self->ptrw()[p_index];
+}
+
+static GDExtensionTypePtr gdextension_packed_vector3_array_operator_index_const(GDExtensionConstTypePtr p_self, GDExtensionInt p_index) {
+ const PackedVector3Array *self = (const PackedVector3Array *)p_self;
+ ERR_FAIL_INDEX_V(p_index, self->size(), nullptr);
+ return (GDExtensionTypePtr)&self->ptr()[p_index];
+}
+
+static GDExtensionVariantPtr gdextension_array_operator_index(GDExtensionTypePtr p_self, GDExtensionInt p_index) {
+ Array *self = (Array *)p_self;
+ ERR_FAIL_INDEX_V(p_index, self->size(), nullptr);
+ return (GDExtensionVariantPtr)&self->operator[](p_index);
+}
+
+static GDExtensionVariantPtr gdextension_array_operator_index_const(GDExtensionConstTypePtr p_self, GDExtensionInt p_index) {
+ const Array *self = (const Array *)p_self;
+ ERR_FAIL_INDEX_V(p_index, self->size(), nullptr);
+ return (GDExtensionVariantPtr)&self->operator[](p_index);
+}
+
+/* Dictionary functions */
+
+static GDExtensionVariantPtr gdextension_dictionary_operator_index(GDExtensionTypePtr p_self, GDExtensionConstVariantPtr p_key) {
+ Dictionary *self = (Dictionary *)p_self;
+ return (GDExtensionVariantPtr)&self->operator[](*(const Variant *)p_key);
+}
+
+static GDExtensionVariantPtr gdextension_dictionary_operator_index_const(GDExtensionConstTypePtr p_self, GDExtensionConstVariantPtr p_key) {
+ const Dictionary *self = (const Dictionary *)p_self;
+ return (GDExtensionVariantPtr)&self->operator[](*(const Variant *)p_key);
+}
+
+/* OBJECT API */
+
+static void gdextension_object_method_bind_call(GDExtensionMethodBindPtr p_method_bind, GDExtensionObjectPtr p_instance, const GDExtensionConstVariantPtr *p_args, GDExtensionInt p_arg_count, GDExtensionVariantPtr r_return, GDExtensionCallError *r_error) {
+ const MethodBind *mb = reinterpret_cast<const MethodBind *>(p_method_bind);
+ Object *o = (Object *)p_instance;
+ const Variant **args = (const Variant **)p_args;
+ Callable::CallError error;
+
+ Variant ret = mb->call(o, args, p_arg_count, error);
+ memnew_placement(r_return, Variant(ret));
+
+ if (r_error) {
+ r_error->error = (GDExtensionCallErrorType)(error.error);
+ r_error->argument = error.argument;
+ r_error->expected = error.expected;
+ }
+}
+
+static void gdextension_object_method_bind_ptrcall(GDExtensionMethodBindPtr p_method_bind, GDExtensionObjectPtr p_instance, const GDExtensionConstTypePtr *p_args, GDExtensionTypePtr p_ret) {
+ const MethodBind *mb = reinterpret_cast<const MethodBind *>(p_method_bind);
+ Object *o = (Object *)p_instance;
+ mb->ptrcall(o, (const void **)p_args, p_ret);
+}
+
+static void gdextension_object_destroy(GDExtensionObjectPtr p_o) {
+ memdelete((Object *)p_o);
+}
+
+static GDExtensionObjectPtr gdextension_global_get_singleton(GDExtensionConstStringNamePtr p_name) {
+ const StringName name = *reinterpret_cast<const StringName *>(p_name);
+ return (GDExtensionObjectPtr)Engine::get_singleton()->get_singleton_object(name);
+}
+
+static void *gdextension_object_get_instance_binding(GDExtensionObjectPtr p_object, void *p_token, const GDExtensionInstanceBindingCallbacks *p_callbacks) {
+ Object *o = (Object *)p_object;
+ return o->get_instance_binding(p_token, p_callbacks);
+}
+
+static void gdextension_object_set_instance_binding(GDExtensionObjectPtr p_object, void *p_token, void *p_binding, const GDExtensionInstanceBindingCallbacks *p_callbacks) {
+ Object *o = (Object *)p_object;
+ o->set_instance_binding(p_token, p_binding, p_callbacks);
+}
+
+static void gdextension_object_set_instance(GDExtensionObjectPtr p_object, GDExtensionConstStringNamePtr p_classname, GDExtensionClassInstancePtr p_instance) {
+ const StringName classname = *reinterpret_cast<const StringName *>(p_classname);
+ Object *o = (Object *)p_object;
+ ClassDB::set_object_extension_instance(o, classname, p_instance);
+}
+
+static GDExtensionObjectPtr gdextension_object_get_instance_from_id(GDObjectInstanceID p_instance_id) {
+ return (GDExtensionObjectPtr)ObjectDB::get_instance(ObjectID(p_instance_id));
+}
+
+static GDExtensionObjectPtr gdextension_object_cast_to(GDExtensionConstObjectPtr p_object, void *p_class_tag) {
+ if (!p_object) {
+ return nullptr;
+ }
+ Object *o = (Object *)p_object;
+
+ return o->is_class_ptr(p_class_tag) ? (GDExtensionObjectPtr)o : (GDExtensionObjectPtr) nullptr;
+}
+
+static GDObjectInstanceID gdextension_object_get_instance_id(GDExtensionConstObjectPtr p_object) {
+ const Object *o = (const Object *)p_object;
+ return (GDObjectInstanceID)o->get_instance_id();
+}
+
+static GDExtensionObjectPtr gdextension_ref_get_object(GDExtensionConstRefPtr p_ref) {
+ const Ref<RefCounted> *ref = (const Ref<RefCounted> *)p_ref;
+ if (ref == nullptr || ref->is_null()) {
+ return (GDExtensionObjectPtr) nullptr;
+ } else {
+ return (GDExtensionObjectPtr)ref->ptr();
+ }
+}
+
+static void gdextension_ref_set_object(GDExtensionRefPtr p_ref, GDExtensionObjectPtr p_object) {
+ Ref<RefCounted> *ref = (Ref<RefCounted> *)p_ref;
+ ERR_FAIL_NULL(ref);
+
+ Object *o = (RefCounted *)p_object;
+ ref->reference_ptr(o);
+}
+
+static GDExtensionScriptInstancePtr gdextension_script_instance_create(const GDExtensionScriptInstanceInfo *p_info, GDExtensionScriptInstanceDataPtr p_instance_data) {
+ ScriptInstanceExtension *script_instance_extension = memnew(ScriptInstanceExtension);
+ script_instance_extension->instance = p_instance_data;
+ script_instance_extension->native_info = p_info;
+ return reinterpret_cast<GDExtensionScriptInstancePtr>(script_instance_extension);
+}
+
+static GDExtensionMethodBindPtr gdextension_classdb_get_method_bind(GDExtensionConstStringNamePtr p_classname, GDExtensionConstStringNamePtr p_methodname, GDExtensionInt p_hash) {
+ const StringName classname = *reinterpret_cast<const StringName *>(p_classname);
+ const StringName methodname = *reinterpret_cast<const StringName *>(p_methodname);
+ MethodBind *mb = ClassDB::get_method(classname, methodname);
+ ERR_FAIL_COND_V(!mb, nullptr);
+ if (mb->get_hash() != p_hash) {
+ ERR_PRINT("Hash mismatch for method '" + classname + "." + methodname + "'.");
+ return nullptr;
+ }
+ return (GDExtensionMethodBindPtr)mb;
+}
+
+static GDExtensionObjectPtr gdextension_classdb_construct_object(GDExtensionConstStringNamePtr p_classname) {
+ const StringName classname = *reinterpret_cast<const StringName *>(p_classname);
+ return (GDExtensionObjectPtr)ClassDB::instantiate(classname);
+}
+
+static void *gdextension_classdb_get_class_tag(GDExtensionConstStringNamePtr p_classname) {
+ const StringName classname = *reinterpret_cast<const StringName *>(p_classname);
+ ClassDB::ClassInfo *class_info = ClassDB::classes.getptr(classname);
+ return class_info ? class_info->class_ptr : nullptr;
+}
+
+void gdextension_setup_interface(GDExtensionInterface *p_interface) {
+ GDExtensionInterface &gde_interface = *p_interface;
+
+ gde_interface.version_major = VERSION_MAJOR;
+ gde_interface.version_minor = VERSION_MINOR;
+#if VERSION_PATCH
+ gde_interface.version_patch = VERSION_PATCH;
+#else
+ gde_interface.version_patch = 0;
+#endif
+ gde_interface.version_string = VERSION_FULL_NAME;
+
+ /* GODOT CORE */
+
+ gde_interface.mem_alloc = gdextension_alloc;
+ gde_interface.mem_realloc = gdextension_realloc;
+ gde_interface.mem_free = gdextension_free;
+
+ gde_interface.print_error = gdextension_print_error;
+ gde_interface.print_warning = gdextension_print_warning;
+ gde_interface.print_script_error = gdextension_print_script_error;
+
+ gde_interface.get_native_struct_size = gdextension_get_native_struct_size;
+
+ /* GODOT VARIANT */
+
+ // variant general
+ gde_interface.variant_new_copy = gdextension_variant_new_copy;
+ gde_interface.variant_new_nil = gdextension_variant_new_nil;
+ gde_interface.variant_destroy = gdextension_variant_destroy;
+
+ gde_interface.variant_call = gdextension_variant_call;
+ gde_interface.variant_call_static = gdextension_variant_call_static;
+ gde_interface.variant_evaluate = gdextension_variant_evaluate;
+ gde_interface.variant_set = gdextension_variant_set;
+ gde_interface.variant_set_named = gdextension_variant_set_named;
+ gde_interface.variant_set_keyed = gdextension_variant_set_keyed;
+ gde_interface.variant_set_indexed = gdextension_variant_set_indexed;
+ gde_interface.variant_get = gdextension_variant_get;
+ gde_interface.variant_get_named = gdextension_variant_get_named;
+ gde_interface.variant_get_keyed = gdextension_variant_get_keyed;
+ gde_interface.variant_get_indexed = gdextension_variant_get_indexed;
+ gde_interface.variant_iter_init = gdextension_variant_iter_init;
+ gde_interface.variant_iter_next = gdextension_variant_iter_next;
+ gde_interface.variant_iter_get = gdextension_variant_iter_get;
+ gde_interface.variant_hash = gdextension_variant_hash;
+ gde_interface.variant_recursive_hash = gdextension_variant_recursive_hash;
+ gde_interface.variant_hash_compare = gdextension_variant_hash_compare;
+ gde_interface.variant_booleanize = gdextension_variant_booleanize;
+ gde_interface.variant_duplicate = gdextension_variant_duplicate;
+ gde_interface.variant_stringify = gdextension_variant_stringify;
+
+ gde_interface.variant_get_type = gdextension_variant_get_type;
+ gde_interface.variant_has_method = gdextension_variant_has_method;
+ gde_interface.variant_has_member = gdextension_variant_has_member;
+ gde_interface.variant_has_key = gdextension_variant_has_key;
+ gde_interface.variant_get_type_name = gdextension_variant_get_type_name;
+ gde_interface.variant_can_convert = gdextension_variant_can_convert;
+ gde_interface.variant_can_convert_strict = gdextension_variant_can_convert_strict;
+
+ gde_interface.get_variant_from_type_constructor = gdextension_get_variant_from_type_constructor;
+ gde_interface.get_variant_to_type_constructor = gdextension_get_type_from_variant_constructor;
+
+ // ptrcalls.
+
+ gde_interface.variant_get_ptr_operator_evaluator = gdextension_variant_get_ptr_operator_evaluator;
+ gde_interface.variant_get_ptr_builtin_method = gdextension_variant_get_ptr_builtin_method;
+ gde_interface.variant_get_ptr_constructor = gdextension_variant_get_ptr_constructor;
+ gde_interface.variant_get_ptr_destructor = gdextension_variant_get_ptr_destructor;
+ gde_interface.variant_construct = gdextension_variant_construct;
+ gde_interface.variant_get_ptr_setter = gdextension_variant_get_ptr_setter;
+ gde_interface.variant_get_ptr_getter = gdextension_variant_get_ptr_getter;
+ gde_interface.variant_get_ptr_indexed_setter = gdextension_variant_get_ptr_indexed_setter;
+ gde_interface.variant_get_ptr_indexed_getter = gdextension_variant_get_ptr_indexed_getter;
+ gde_interface.variant_get_ptr_keyed_setter = gdextension_variant_get_ptr_keyed_setter;
+ gde_interface.variant_get_ptr_keyed_getter = gdextension_variant_get_ptr_keyed_getter;
+ gde_interface.variant_get_ptr_keyed_checker = gdextension_variant_get_ptr_keyed_checker;
+ gde_interface.variant_get_constant_value = gdextension_variant_get_constant_value;
+ gde_interface.variant_get_ptr_utility_function = gdextension_variant_get_ptr_utility_function;
+
+ // extra utilities
+
+ gde_interface.string_new_with_latin1_chars = gdextension_string_new_with_latin1_chars;
+ gde_interface.string_new_with_utf8_chars = gdextension_string_new_with_utf8_chars;
+ gde_interface.string_new_with_utf16_chars = gdextension_string_new_with_utf16_chars;
+ gde_interface.string_new_with_utf32_chars = gdextension_string_new_with_utf32_chars;
+ gde_interface.string_new_with_wide_chars = gdextension_string_new_with_wide_chars;
+ gde_interface.string_new_with_latin1_chars_and_len = gdextension_string_new_with_latin1_chars_and_len;
+ gde_interface.string_new_with_utf8_chars_and_len = gdextension_string_new_with_utf8_chars_and_len;
+ gde_interface.string_new_with_utf16_chars_and_len = gdextension_string_new_with_utf16_chars_and_len;
+ gde_interface.string_new_with_utf32_chars_and_len = gdextension_string_new_with_utf32_chars_and_len;
+ gde_interface.string_new_with_wide_chars_and_len = gdextension_string_new_with_wide_chars_and_len;
+ gde_interface.string_to_latin1_chars = gdextension_string_to_latin1_chars;
+ gde_interface.string_to_utf8_chars = gdextension_string_to_utf8_chars;
+ gde_interface.string_to_utf16_chars = gdextension_string_to_utf16_chars;
+ gde_interface.string_to_utf32_chars = gdextension_string_to_utf32_chars;
+ gde_interface.string_to_wide_chars = gdextension_string_to_wide_chars;
+ gde_interface.string_operator_index = gdextension_string_operator_index;
+ gde_interface.string_operator_index_const = gdextension_string_operator_index_const;
+
+ /* Packed array functions */
+
+ gde_interface.packed_byte_array_operator_index = gdextension_packed_byte_array_operator_index;
+ gde_interface.packed_byte_array_operator_index_const = gdextension_packed_byte_array_operator_index_const;
+
+ gde_interface.packed_color_array_operator_index = gdextension_packed_color_array_operator_index;
+ gde_interface.packed_color_array_operator_index_const = gdextension_packed_color_array_operator_index_const;
+
+ gde_interface.packed_float32_array_operator_index = gdextension_packed_float32_array_operator_index;
+ gde_interface.packed_float32_array_operator_index_const = gdextension_packed_float32_array_operator_index_const;
+ gde_interface.packed_float64_array_operator_index = gdextension_packed_float64_array_operator_index;
+ gde_interface.packed_float64_array_operator_index_const = gdextension_packed_float64_array_operator_index_const;
+
+ gde_interface.packed_int32_array_operator_index = gdextension_packed_int32_array_operator_index;
+ gde_interface.packed_int32_array_operator_index_const = gdextension_packed_int32_array_operator_index_const;
+ gde_interface.packed_int64_array_operator_index = gdextension_packed_int64_array_operator_index;
+ gde_interface.packed_int64_array_operator_index_const = gdextension_packed_int64_array_operator_index_const;
+
+ gde_interface.packed_string_array_operator_index = gdextension_packed_string_array_operator_index;
+ gde_interface.packed_string_array_operator_index_const = gdextension_packed_string_array_operator_index_const;
+
+ gde_interface.packed_vector2_array_operator_index = gdextension_packed_vector2_array_operator_index;
+ gde_interface.packed_vector2_array_operator_index_const = gdextension_packed_vector2_array_operator_index_const;
+ gde_interface.packed_vector3_array_operator_index = gdextension_packed_vector3_array_operator_index;
+ gde_interface.packed_vector3_array_operator_index_const = gdextension_packed_vector3_array_operator_index_const;
+
+ gde_interface.array_operator_index = gdextension_array_operator_index;
+ gde_interface.array_operator_index_const = gdextension_array_operator_index_const;
+
+ /* Dictionary functions */
+
+ gde_interface.dictionary_operator_index = gdextension_dictionary_operator_index;
+ gde_interface.dictionary_operator_index_const = gdextension_dictionary_operator_index_const;
+
+ /* OBJECT */
+
+ gde_interface.object_method_bind_call = gdextension_object_method_bind_call;
+ gde_interface.object_method_bind_ptrcall = gdextension_object_method_bind_ptrcall;
+ gde_interface.object_destroy = gdextension_object_destroy;
+ gde_interface.global_get_singleton = gdextension_global_get_singleton;
+ gde_interface.object_get_instance_binding = gdextension_object_get_instance_binding;
+ gde_interface.object_set_instance_binding = gdextension_object_set_instance_binding;
+ gde_interface.object_set_instance = gdextension_object_set_instance;
+
+ gde_interface.object_cast_to = gdextension_object_cast_to;
+ gde_interface.object_get_instance_from_id = gdextension_object_get_instance_from_id;
+ gde_interface.object_get_instance_id = gdextension_object_get_instance_id;
+
+ /* REFERENCE */
+
+ gde_interface.ref_get_object = gdextension_ref_get_object;
+ gde_interface.ref_set_object = gdextension_ref_set_object;
+
+ /* SCRIPT INSTANCE */
+
+ gde_interface.script_instance_create = gdextension_script_instance_create;
+
+ /* CLASSDB */
+
+ gde_interface.classdb_construct_object = gdextension_classdb_construct_object;
+ gde_interface.classdb_get_method_bind = gdextension_classdb_get_method_bind;
+ gde_interface.classdb_get_class_tag = gdextension_classdb_get_class_tag;
+
+ /* CLASSDB EXTENSION */
+
+ //these are filled by implementation, since it will want to keep track of registered classes
+ gde_interface.classdb_register_extension_class = nullptr;
+ gde_interface.classdb_register_extension_class_method = nullptr;
+ gde_interface.classdb_register_extension_class_integer_constant = nullptr;
+ gde_interface.classdb_register_extension_class_property = nullptr;
+ gde_interface.classdb_register_extension_class_property_group = nullptr;
+ gde_interface.classdb_register_extension_class_property_subgroup = nullptr;
+ gde_interface.classdb_register_extension_class_signal = nullptr;
+ gde_interface.classdb_unregister_extension_class = nullptr;
+
+ gde_interface.get_library_path = nullptr;
+}
diff --git a/core/extension/gdextension_interface.h b/core/extension/gdextension_interface.h
new file mode 100644
index 0000000000..0b7615ffdd
--- /dev/null
+++ b/core/extension/gdextension_interface.h
@@ -0,0 +1,619 @@
+/*************************************************************************/
+/* gdextension_interface.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 GDEXTENSION_INTERFACE_H
+#define GDEXTENSION_INTERFACE_H
+
+/* This is a C class header, you can copy it and use it directly in your own binders.
+ * Together with the JSON file, you should be able to generate any binder.
+ */
+
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+
+#ifndef __cplusplus
+typedef uint32_t char32_t;
+typedef uint16_t char16_t;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* VARIANT TYPES */
+
+typedef enum {
+ GDEXTENSION_VARIANT_TYPE_NIL,
+
+ /* atomic types */
+ GDEXTENSION_VARIANT_TYPE_BOOL,
+ GDEXTENSION_VARIANT_TYPE_INT,
+ GDEXTENSION_VARIANT_TYPE_FLOAT,
+ GDEXTENSION_VARIANT_TYPE_STRING,
+
+ /* math types */
+ GDEXTENSION_VARIANT_TYPE_VECTOR2,
+ GDEXTENSION_VARIANT_TYPE_VECTOR2I,
+ GDEXTENSION_VARIANT_TYPE_RECT2,
+ GDEXTENSION_VARIANT_TYPE_RECT2I,
+ GDEXTENSION_VARIANT_TYPE_VECTOR3,
+ GDEXTENSION_VARIANT_TYPE_VECTOR3I,
+ GDEXTENSION_VARIANT_TYPE_TRANSFORM2D,
+ GDEXTENSION_VARIANT_TYPE_VECTOR4,
+ GDEXTENSION_VARIANT_TYPE_VECTOR4I,
+ GDEXTENSION_VARIANT_TYPE_PLANE,
+ GDEXTENSION_VARIANT_TYPE_QUATERNION,
+ GDEXTENSION_VARIANT_TYPE_AABB,
+ GDEXTENSION_VARIANT_TYPE_BASIS,
+ GDEXTENSION_VARIANT_TYPE_TRANSFORM3D,
+ GDEXTENSION_VARIANT_TYPE_PROJECTION,
+
+ /* misc types */
+ GDEXTENSION_VARIANT_TYPE_COLOR,
+ GDEXTENSION_VARIANT_TYPE_STRING_NAME,
+ GDEXTENSION_VARIANT_TYPE_NODE_PATH,
+ GDEXTENSION_VARIANT_TYPE_RID,
+ GDEXTENSION_VARIANT_TYPE_OBJECT,
+ GDEXTENSION_VARIANT_TYPE_CALLABLE,
+ GDEXTENSION_VARIANT_TYPE_SIGNAL,
+ GDEXTENSION_VARIANT_TYPE_DICTIONARY,
+ GDEXTENSION_VARIANT_TYPE_ARRAY,
+
+ /* typed arrays */
+ GDEXTENSION_VARIANT_TYPE_PACKED_BYTE_ARRAY,
+ GDEXTENSION_VARIANT_TYPE_PACKED_INT32_ARRAY,
+ GDEXTENSION_VARIANT_TYPE_PACKED_INT64_ARRAY,
+ GDEXTENSION_VARIANT_TYPE_PACKED_FLOAT32_ARRAY,
+ GDEXTENSION_VARIANT_TYPE_PACKED_FLOAT64_ARRAY,
+ GDEXTENSION_VARIANT_TYPE_PACKED_STRING_ARRAY,
+ GDEXTENSION_VARIANT_TYPE_PACKED_VECTOR2_ARRAY,
+ GDEXTENSION_VARIANT_TYPE_PACKED_VECTOR3_ARRAY,
+ GDEXTENSION_VARIANT_TYPE_PACKED_COLOR_ARRAY,
+
+ GDEXTENSION_VARIANT_TYPE_VARIANT_MAX
+} GDExtensionVariantType;
+
+typedef enum {
+ /* comparison */
+ GDEXTENSION_VARIANT_OP_EQUAL,
+ GDEXTENSION_VARIANT_OP_NOT_EQUAL,
+ GDEXTENSION_VARIANT_OP_LESS,
+ GDEXTENSION_VARIANT_OP_LESS_EQUAL,
+ GDEXTENSION_VARIANT_OP_GREATER,
+ GDEXTENSION_VARIANT_OP_GREATER_EQUAL,
+
+ /* mathematic */
+ GDEXTENSION_VARIANT_OP_ADD,
+ GDEXTENSION_VARIANT_OP_SUBTRACT,
+ GDEXTENSION_VARIANT_OP_MULTIPLY,
+ GDEXTENSION_VARIANT_OP_DIVIDE,
+ GDEXTENSION_VARIANT_OP_NEGATE,
+ GDEXTENSION_VARIANT_OP_POSITIVE,
+ GDEXTENSION_VARIANT_OP_MODULE,
+ GDEXTENSION_VARIANT_OP_POWER,
+
+ /* bitwise */
+ GDEXTENSION_VARIANT_OP_SHIFT_LEFT,
+ GDEXTENSION_VARIANT_OP_SHIFT_RIGHT,
+ GDEXTENSION_VARIANT_OP_BIT_AND,
+ GDEXTENSION_VARIANT_OP_BIT_OR,
+ GDEXTENSION_VARIANT_OP_BIT_XOR,
+ GDEXTENSION_VARIANT_OP_BIT_NEGATE,
+
+ /* logic */
+ GDEXTENSION_VARIANT_OP_AND,
+ GDEXTENSION_VARIANT_OP_OR,
+ GDEXTENSION_VARIANT_OP_XOR,
+ GDEXTENSION_VARIANT_OP_NOT,
+
+ /* containment */
+ GDEXTENSION_VARIANT_OP_IN,
+ GDEXTENSION_VARIANT_OP_MAX
+
+} GDExtensionVariantOperator;
+
+typedef void *GDExtensionVariantPtr;
+typedef const void *GDExtensionConstVariantPtr;
+typedef void *GDExtensionStringNamePtr;
+typedef const void *GDExtensionConstStringNamePtr;
+typedef void *GDExtensionStringPtr;
+typedef const void *GDExtensionConstStringPtr;
+typedef void *GDExtensionObjectPtr;
+typedef const void *GDExtensionConstObjectPtr;
+typedef void *GDExtensionTypePtr;
+typedef const void *GDExtensionConstTypePtr;
+typedef const void *GDExtensionMethodBindPtr;
+typedef int64_t GDExtensionInt;
+typedef uint8_t GDExtensionBool;
+typedef uint64_t GDObjectInstanceID;
+typedef void *GDExtensionRefPtr;
+typedef const void *GDExtensionConstRefPtr;
+
+/* VARIANT DATA I/O */
+
+typedef enum {
+ GDEXTENSION_CALL_OK,
+ GDEXTENSION_CALL_ERROR_INVALID_METHOD,
+ GDEXTENSION_CALL_ERROR_INVALID_ARGUMENT, // Expected a different variant type.
+ GDEXTENSION_CALL_ERROR_TOO_MANY_ARGUMENTS, // Expected lower number of arguments.
+ GDEXTENSION_CALL_ERROR_TOO_FEW_ARGUMENTS, // Expected higher number of arguments.
+ GDEXTENSION_CALL_ERROR_INSTANCE_IS_NULL,
+ GDEXTENSION_CALL_ERROR_METHOD_NOT_CONST, // Used for const call.
+} GDExtensionCallErrorType;
+
+typedef struct {
+ GDExtensionCallErrorType error;
+ int32_t argument;
+ int32_t expected;
+} GDExtensionCallError;
+
+typedef void (*GDExtensionVariantFromTypeConstructorFunc)(GDExtensionVariantPtr, GDExtensionTypePtr);
+typedef void (*GDExtensionTypeFromVariantConstructorFunc)(GDExtensionTypePtr, GDExtensionVariantPtr);
+typedef void (*GDExtensionPtrOperatorEvaluator)(GDExtensionConstTypePtr p_left, GDExtensionConstTypePtr p_right, GDExtensionTypePtr r_result);
+typedef void (*GDExtensionPtrBuiltInMethod)(GDExtensionTypePtr p_base, const GDExtensionConstTypePtr *p_args, GDExtensionTypePtr r_return, int p_argument_count);
+typedef void (*GDExtensionPtrConstructor)(GDExtensionTypePtr p_base, const GDExtensionConstTypePtr *p_args);
+typedef void (*GDExtensionPtrDestructor)(GDExtensionTypePtr p_base);
+typedef void (*GDExtensionPtrSetter)(GDExtensionTypePtr p_base, GDExtensionConstTypePtr p_value);
+typedef void (*GDExtensionPtrGetter)(GDExtensionConstTypePtr p_base, GDExtensionTypePtr r_value);
+typedef void (*GDExtensionPtrIndexedSetter)(GDExtensionTypePtr p_base, GDExtensionInt p_index, GDExtensionConstTypePtr p_value);
+typedef void (*GDExtensionPtrIndexedGetter)(GDExtensionConstTypePtr p_base, GDExtensionInt p_index, GDExtensionTypePtr r_value);
+typedef void (*GDExtensionPtrKeyedSetter)(GDExtensionTypePtr p_base, GDExtensionConstTypePtr p_key, GDExtensionConstTypePtr p_value);
+typedef void (*GDExtensionPtrKeyedGetter)(GDExtensionConstTypePtr p_base, GDExtensionConstTypePtr p_key, GDExtensionTypePtr r_value);
+typedef uint32_t (*GDExtensionPtrKeyedChecker)(GDExtensionConstVariantPtr p_base, GDExtensionConstVariantPtr p_key);
+typedef void (*GDExtensionPtrUtilityFunction)(GDExtensionTypePtr r_return, const GDExtensionConstTypePtr *p_args, int p_argument_count);
+
+typedef GDExtensionObjectPtr (*GDExtensionClassConstructor)();
+
+typedef void *(*GDExtensionInstanceBindingCreateCallback)(void *p_token, void *p_instance);
+typedef void (*GDExtensionInstanceBindingFreeCallback)(void *p_token, void *p_instance, void *p_binding);
+typedef GDExtensionBool (*GDExtensionInstanceBindingReferenceCallback)(void *p_token, void *p_binding, GDExtensionBool p_reference);
+
+typedef struct {
+ GDExtensionInstanceBindingCreateCallback create_callback;
+ GDExtensionInstanceBindingFreeCallback free_callback;
+ GDExtensionInstanceBindingReferenceCallback reference_callback;
+} GDExtensionInstanceBindingCallbacks;
+
+/* EXTENSION CLASSES */
+
+typedef void *GDExtensionClassInstancePtr;
+
+typedef GDExtensionBool (*GDExtensionClassSet)(GDExtensionClassInstancePtr p_instance, GDExtensionConstStringNamePtr p_name, GDExtensionConstVariantPtr p_value);
+typedef GDExtensionBool (*GDExtensionClassGet)(GDExtensionClassInstancePtr p_instance, GDExtensionConstStringNamePtr p_name, GDExtensionVariantPtr r_ret);
+typedef uint64_t (*GDExtensionClassGetRID)(GDExtensionClassInstancePtr p_instance);
+
+typedef struct {
+ GDExtensionVariantType type;
+ GDExtensionStringNamePtr name;
+ GDExtensionStringNamePtr class_name;
+ uint32_t hint; // Bitfield of `PropertyHint` (defined in `extension_api.json`).
+ GDExtensionStringPtr hint_string;
+ uint32_t usage; // Bitfield of `PropertyUsageFlags` (defined in `extension_api.json`).
+} GDExtensionPropertyInfo;
+
+typedef struct {
+ GDExtensionStringNamePtr name;
+ GDExtensionPropertyInfo return_value;
+ uint32_t flags; // Bitfield of `GDExtensionClassMethodFlags`.
+ int32_t id;
+
+ /* Arguments: `default_arguments` is an array of size `argument_count`. */
+ uint32_t argument_count;
+ GDExtensionPropertyInfo *arguments;
+
+ /* Default arguments: `default_arguments` is an array of size `default_argument_count`. */
+ uint32_t default_argument_count;
+ GDExtensionVariantPtr *default_arguments;
+} GDExtensionMethodInfo;
+
+typedef const GDExtensionPropertyInfo *(*GDExtensionClassGetPropertyList)(GDExtensionClassInstancePtr p_instance, uint32_t *r_count);
+typedef void (*GDExtensionClassFreePropertyList)(GDExtensionClassInstancePtr p_instance, const GDExtensionPropertyInfo *p_list);
+typedef GDExtensionBool (*GDExtensionClassPropertyCanRevert)(GDExtensionClassInstancePtr p_instance, GDExtensionConstStringNamePtr p_name);
+typedef GDExtensionBool (*GDExtensionClassPropertyGetRevert)(GDExtensionClassInstancePtr p_instance, GDExtensionConstStringNamePtr p_name, GDExtensionVariantPtr r_ret);
+typedef void (*GDExtensionClassNotification)(GDExtensionClassInstancePtr p_instance, int32_t p_what);
+typedef void (*GDExtensionClassToString)(GDExtensionClassInstancePtr p_instance, GDExtensionBool *r_is_valid, GDExtensionStringPtr p_out);
+typedef void (*GDExtensionClassReference)(GDExtensionClassInstancePtr p_instance);
+typedef void (*GDExtensionClassUnreference)(GDExtensionClassInstancePtr p_instance);
+typedef void (*GDExtensionClassCallVirtual)(GDExtensionClassInstancePtr p_instance, const GDExtensionConstTypePtr *p_args, GDExtensionTypePtr r_ret);
+typedef GDExtensionObjectPtr (*GDExtensionClassCreateInstance)(void *p_userdata);
+typedef void (*GDExtensionClassFreeInstance)(void *p_userdata, GDExtensionClassInstancePtr p_instance);
+typedef GDExtensionClassCallVirtual (*GDExtensionClassGetVirtual)(void *p_userdata, GDExtensionConstStringNamePtr p_name);
+
+typedef struct {
+ GDExtensionBool is_virtual;
+ GDExtensionBool is_abstract;
+ GDExtensionClassSet set_func;
+ GDExtensionClassGet get_func;
+ GDExtensionClassGetPropertyList get_property_list_func;
+ GDExtensionClassFreePropertyList free_property_list_func;
+ GDExtensionClassPropertyCanRevert property_can_revert_func;
+ GDExtensionClassPropertyGetRevert property_get_revert_func;
+ GDExtensionClassNotification notification_func;
+ GDExtensionClassToString to_string_func;
+ GDExtensionClassReference reference_func;
+ GDExtensionClassUnreference unreference_func;
+ GDExtensionClassCreateInstance create_instance_func; // (Default) constructor; mandatory. If the class is not instantiable, consider making it virtual or abstract.
+ GDExtensionClassFreeInstance free_instance_func; // Destructor; mandatory.
+ GDExtensionClassGetVirtual get_virtual_func; // Queries a virtual function by name and returns a callback to invoke the requested virtual function.
+ GDExtensionClassGetRID get_rid_func;
+ void *class_userdata; // Per-class user data, later accessible in instance bindings.
+} GDExtensionClassCreationInfo;
+
+typedef void *GDExtensionClassLibraryPtr;
+
+/* Method */
+
+typedef enum {
+ GDEXTENSION_METHOD_FLAG_NORMAL = 1,
+ GDEXTENSION_METHOD_FLAG_EDITOR = 2,
+ GDEXTENSION_METHOD_FLAG_CONST = 4,
+ GDEXTENSION_METHOD_FLAG_VIRTUAL = 8,
+ GDEXTENSION_METHOD_FLAG_VARARG = 16,
+ GDEXTENSION_METHOD_FLAG_STATIC = 32,
+ GDEXTENSION_METHOD_FLAGS_DEFAULT = GDEXTENSION_METHOD_FLAG_NORMAL,
+} GDExtensionClassMethodFlags;
+
+typedef enum {
+ GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE,
+ GDEXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_INT8,
+ GDEXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_INT16,
+ GDEXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_INT32,
+ GDEXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_INT64,
+ GDEXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_UINT8,
+ GDEXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_UINT16,
+ GDEXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_UINT32,
+ GDEXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_UINT64,
+ GDEXTENSION_METHOD_ARGUMENT_METADATA_REAL_IS_FLOAT,
+ GDEXTENSION_METHOD_ARGUMENT_METADATA_REAL_IS_DOUBLE
+} GDExtensionClassMethodArgumentMetadata;
+
+typedef void (*GDExtensionClassMethodCall)(void *method_userdata, GDExtensionClassInstancePtr p_instance, const GDExtensionConstVariantPtr *p_args, GDExtensionInt p_argument_count, GDExtensionVariantPtr r_return, GDExtensionCallError *r_error);
+typedef void (*GDExtensionClassMethodPtrCall)(void *method_userdata, GDExtensionClassInstancePtr p_instance, const GDExtensionConstTypePtr *p_args, GDExtensionTypePtr r_ret);
+
+typedef struct {
+ GDExtensionStringNamePtr name;
+ void *method_userdata;
+ GDExtensionClassMethodCall call_func;
+ GDExtensionClassMethodPtrCall ptrcall_func;
+ uint32_t method_flags; // Bitfield of `GDExtensionClassMethodFlags`.
+
+ /* If `has_return_value` is false, `return_value_info` and `return_value_metadata` are ignored. */
+ GDExtensionBool has_return_value;
+ GDExtensionPropertyInfo *return_value_info;
+ GDExtensionClassMethodArgumentMetadata return_value_metadata;
+
+ /* Arguments: `arguments_info` and `arguments_metadata` are array of size `argument_count`.
+ * Name and hint information for the argument can be omitted in release builds. Class name should always be present if it applies.
+ */
+ uint32_t argument_count;
+ GDExtensionPropertyInfo *arguments_info;
+ GDExtensionClassMethodArgumentMetadata *arguments_metadata;
+
+ /* Default arguments: `default_arguments` is an array of size `default_argument_count`. */
+ uint32_t default_argument_count;
+ GDExtensionVariantPtr *default_arguments;
+} GDExtensionClassMethodInfo;
+
+/* SCRIPT INSTANCE EXTENSION */
+
+typedef void *GDExtensionScriptInstanceDataPtr; // Pointer to custom ScriptInstance native implementation.
+
+typedef GDExtensionBool (*GDExtensionScriptInstanceSet)(GDExtensionScriptInstanceDataPtr p_instance, GDExtensionConstStringNamePtr p_name, GDExtensionConstVariantPtr p_value);
+typedef GDExtensionBool (*GDExtensionScriptInstanceGet)(GDExtensionScriptInstanceDataPtr p_instance, GDExtensionConstStringNamePtr p_name, GDExtensionVariantPtr r_ret);
+typedef const GDExtensionPropertyInfo *(*GDExtensionScriptInstanceGetPropertyList)(GDExtensionScriptInstanceDataPtr p_instance, uint32_t *r_count);
+typedef void (*GDExtensionScriptInstanceFreePropertyList)(GDExtensionScriptInstanceDataPtr p_instance, const GDExtensionPropertyInfo *p_list);
+typedef GDExtensionVariantType (*GDExtensionScriptInstanceGetPropertyType)(GDExtensionScriptInstanceDataPtr p_instance, GDExtensionConstStringNamePtr p_name, GDExtensionBool *r_is_valid);
+
+typedef GDExtensionBool (*GDExtensionScriptInstancePropertyCanRevert)(GDExtensionScriptInstanceDataPtr p_instance, GDExtensionConstStringNamePtr p_name);
+typedef GDExtensionBool (*GDExtensionScriptInstancePropertyGetRevert)(GDExtensionScriptInstanceDataPtr p_instance, GDExtensionConstStringNamePtr p_name, GDExtensionVariantPtr r_ret);
+
+typedef GDExtensionObjectPtr (*GDExtensionScriptInstanceGetOwner)(GDExtensionScriptInstanceDataPtr p_instance);
+typedef void (*GDExtensionScriptInstancePropertyStateAdd)(GDExtensionConstStringNamePtr p_name, GDExtensionConstVariantPtr p_value, void *p_userdata);
+typedef void (*GDExtensionScriptInstanceGetPropertyState)(GDExtensionScriptInstanceDataPtr p_instance, GDExtensionScriptInstancePropertyStateAdd p_add_func, void *p_userdata);
+
+typedef const GDExtensionMethodInfo *(*GDExtensionScriptInstanceGetMethodList)(GDExtensionScriptInstanceDataPtr p_instance, uint32_t *r_count);
+typedef void (*GDExtensionScriptInstanceFreeMethodList)(GDExtensionScriptInstanceDataPtr p_instance, const GDExtensionMethodInfo *p_list);
+
+typedef GDExtensionBool (*GDExtensionScriptInstanceHasMethod)(GDExtensionScriptInstanceDataPtr p_instance, GDExtensionConstStringNamePtr p_name);
+
+typedef void (*GDExtensionScriptInstanceCall)(GDExtensionScriptInstanceDataPtr p_self, GDExtensionConstStringNamePtr p_method, const GDExtensionConstVariantPtr *p_args, GDExtensionInt p_argument_count, GDExtensionVariantPtr r_return, GDExtensionCallError *r_error);
+typedef void (*GDExtensionScriptInstanceNotification)(GDExtensionScriptInstanceDataPtr p_instance, int32_t p_what);
+typedef void (*GDExtensionScriptInstanceToString)(GDExtensionScriptInstanceDataPtr p_instance, GDExtensionBool *r_is_valid, GDExtensionStringPtr r_out);
+
+typedef void (*GDExtensionScriptInstanceRefCountIncremented)(GDExtensionScriptInstanceDataPtr p_instance);
+typedef GDExtensionBool (*GDExtensionScriptInstanceRefCountDecremented)(GDExtensionScriptInstanceDataPtr p_instance);
+
+typedef GDExtensionObjectPtr (*GDExtensionScriptInstanceGetScript)(GDExtensionScriptInstanceDataPtr p_instance);
+typedef GDExtensionBool (*GDExtensionScriptInstanceIsPlaceholder)(GDExtensionScriptInstanceDataPtr p_instance);
+
+typedef void *GDExtensionScriptLanguagePtr;
+
+typedef GDExtensionScriptLanguagePtr (*GDExtensionScriptInstanceGetLanguage)(GDExtensionScriptInstanceDataPtr p_instance);
+
+typedef void (*GDExtensionScriptInstanceFree)(GDExtensionScriptInstanceDataPtr p_instance);
+
+typedef void *GDExtensionScriptInstancePtr; // Pointer to ScriptInstance.
+
+typedef struct {
+ GDExtensionScriptInstanceSet set_func;
+ GDExtensionScriptInstanceGet get_func;
+ GDExtensionScriptInstanceGetPropertyList get_property_list_func;
+ GDExtensionScriptInstanceFreePropertyList free_property_list_func;
+
+ GDExtensionScriptInstancePropertyCanRevert property_can_revert_func;
+ GDExtensionScriptInstancePropertyGetRevert property_get_revert_func;
+
+ GDExtensionScriptInstanceGetOwner get_owner_func;
+ GDExtensionScriptInstanceGetPropertyState get_property_state_func;
+
+ GDExtensionScriptInstanceGetMethodList get_method_list_func;
+ GDExtensionScriptInstanceFreeMethodList free_method_list_func;
+ GDExtensionScriptInstanceGetPropertyType get_property_type_func;
+
+ GDExtensionScriptInstanceHasMethod has_method_func;
+
+ GDExtensionScriptInstanceCall call_func;
+ GDExtensionScriptInstanceNotification notification_func;
+
+ GDExtensionScriptInstanceToString to_string_func;
+
+ GDExtensionScriptInstanceRefCountIncremented refcount_incremented_func;
+ GDExtensionScriptInstanceRefCountDecremented refcount_decremented_func;
+
+ GDExtensionScriptInstanceGetScript get_script_func;
+
+ GDExtensionScriptInstanceIsPlaceholder is_placeholder_func;
+
+ GDExtensionScriptInstanceSet set_fallback_func;
+ GDExtensionScriptInstanceGet get_fallback_func;
+
+ GDExtensionScriptInstanceGetLanguage get_language_func;
+
+ GDExtensionScriptInstanceFree free_func;
+
+} GDExtensionScriptInstanceInfo;
+
+/* INTERFACE */
+
+typedef struct {
+ uint32_t version_major;
+ uint32_t version_minor;
+ uint32_t version_patch;
+ const char *version_string;
+
+ /* GODOT CORE */
+
+ void *(*mem_alloc)(size_t p_bytes);
+ void *(*mem_realloc)(void *p_ptr, size_t p_bytes);
+ void (*mem_free)(void *p_ptr);
+
+ void (*print_error)(const char *p_description, const char *p_function, const char *p_file, int32_t p_line);
+ void (*print_warning)(const char *p_description, const char *p_function, const char *p_file, int32_t p_line);
+ void (*print_script_error)(const char *p_description, const char *p_function, const char *p_file, int32_t p_line);
+
+ uint64_t (*get_native_struct_size)(GDExtensionConstStringNamePtr p_name);
+
+ /* GODOT VARIANT */
+
+ /* variant general */
+ void (*variant_new_copy)(GDExtensionVariantPtr r_dest, GDExtensionConstVariantPtr p_src);
+ void (*variant_new_nil)(GDExtensionVariantPtr r_dest);
+ void (*variant_destroy)(GDExtensionVariantPtr p_self);
+
+ /* variant type */
+ void (*variant_call)(GDExtensionVariantPtr p_self, GDExtensionConstStringNamePtr p_method, const GDExtensionConstVariantPtr *p_args, GDExtensionInt p_argument_count, GDExtensionVariantPtr r_return, GDExtensionCallError *r_error);
+ void (*variant_call_static)(GDExtensionVariantType p_type, GDExtensionConstStringNamePtr p_method, const GDExtensionConstVariantPtr *p_args, GDExtensionInt p_argument_count, GDExtensionVariantPtr r_return, GDExtensionCallError *r_error);
+ void (*variant_evaluate)(GDExtensionVariantOperator p_op, GDExtensionConstVariantPtr p_a, GDExtensionConstVariantPtr p_b, GDExtensionVariantPtr r_return, GDExtensionBool *r_valid);
+ void (*variant_set)(GDExtensionVariantPtr p_self, GDExtensionConstVariantPtr p_key, GDExtensionConstVariantPtr p_value, GDExtensionBool *r_valid);
+ void (*variant_set_named)(GDExtensionVariantPtr p_self, GDExtensionConstStringNamePtr p_key, GDExtensionConstVariantPtr p_value, GDExtensionBool *r_valid);
+ void (*variant_set_keyed)(GDExtensionVariantPtr p_self, GDExtensionConstVariantPtr p_key, GDExtensionConstVariantPtr p_value, GDExtensionBool *r_valid);
+ void (*variant_set_indexed)(GDExtensionVariantPtr p_self, GDExtensionInt p_index, GDExtensionConstVariantPtr p_value, GDExtensionBool *r_valid, GDExtensionBool *r_oob);
+ void (*variant_get)(GDExtensionConstVariantPtr p_self, GDExtensionConstVariantPtr p_key, GDExtensionVariantPtr r_ret, GDExtensionBool *r_valid);
+ void (*variant_get_named)(GDExtensionConstVariantPtr p_self, GDExtensionConstStringNamePtr p_key, GDExtensionVariantPtr r_ret, GDExtensionBool *r_valid);
+ void (*variant_get_keyed)(GDExtensionConstVariantPtr p_self, GDExtensionConstVariantPtr p_key, GDExtensionVariantPtr r_ret, GDExtensionBool *r_valid);
+ void (*variant_get_indexed)(GDExtensionConstVariantPtr p_self, GDExtensionInt p_index, GDExtensionVariantPtr r_ret, GDExtensionBool *r_valid, GDExtensionBool *r_oob);
+ GDExtensionBool (*variant_iter_init)(GDExtensionConstVariantPtr p_self, GDExtensionVariantPtr r_iter, GDExtensionBool *r_valid);
+ GDExtensionBool (*variant_iter_next)(GDExtensionConstVariantPtr p_self, GDExtensionVariantPtr r_iter, GDExtensionBool *r_valid);
+ void (*variant_iter_get)(GDExtensionConstVariantPtr p_self, GDExtensionVariantPtr r_iter, GDExtensionVariantPtr r_ret, GDExtensionBool *r_valid);
+ GDExtensionInt (*variant_hash)(GDExtensionConstVariantPtr p_self);
+ GDExtensionInt (*variant_recursive_hash)(GDExtensionConstVariantPtr p_self, GDExtensionInt p_recursion_count);
+ GDExtensionBool (*variant_hash_compare)(GDExtensionConstVariantPtr p_self, GDExtensionConstVariantPtr p_other);
+ GDExtensionBool (*variant_booleanize)(GDExtensionConstVariantPtr p_self);
+ void (*variant_duplicate)(GDExtensionConstVariantPtr p_self, GDExtensionVariantPtr r_ret, GDExtensionBool p_deep);
+ void (*variant_stringify)(GDExtensionConstVariantPtr p_self, GDExtensionStringPtr r_ret);
+
+ GDExtensionVariantType (*variant_get_type)(GDExtensionConstVariantPtr p_self);
+ GDExtensionBool (*variant_has_method)(GDExtensionConstVariantPtr p_self, GDExtensionConstStringNamePtr p_method);
+ GDExtensionBool (*variant_has_member)(GDExtensionVariantType p_type, GDExtensionConstStringNamePtr p_member);
+ GDExtensionBool (*variant_has_key)(GDExtensionConstVariantPtr p_self, GDExtensionConstVariantPtr p_key, GDExtensionBool *r_valid);
+ void (*variant_get_type_name)(GDExtensionVariantType p_type, GDExtensionStringPtr r_name);
+ GDExtensionBool (*variant_can_convert)(GDExtensionVariantType p_from, GDExtensionVariantType p_to);
+ GDExtensionBool (*variant_can_convert_strict)(GDExtensionVariantType p_from, GDExtensionVariantType p_to);
+
+ /* ptrcalls */
+ GDExtensionVariantFromTypeConstructorFunc (*get_variant_from_type_constructor)(GDExtensionVariantType p_type);
+ GDExtensionTypeFromVariantConstructorFunc (*get_variant_to_type_constructor)(GDExtensionVariantType p_type);
+ GDExtensionPtrOperatorEvaluator (*variant_get_ptr_operator_evaluator)(GDExtensionVariantOperator p_operator, GDExtensionVariantType p_type_a, GDExtensionVariantType p_type_b);
+ GDExtensionPtrBuiltInMethod (*variant_get_ptr_builtin_method)(GDExtensionVariantType p_type, GDExtensionConstStringNamePtr p_method, GDExtensionInt p_hash);
+ GDExtensionPtrConstructor (*variant_get_ptr_constructor)(GDExtensionVariantType p_type, int32_t p_constructor);
+ GDExtensionPtrDestructor (*variant_get_ptr_destructor)(GDExtensionVariantType p_type);
+ void (*variant_construct)(GDExtensionVariantType p_type, GDExtensionVariantPtr p_base, const GDExtensionConstVariantPtr *p_args, int32_t p_argument_count, GDExtensionCallError *r_error);
+ GDExtensionPtrSetter (*variant_get_ptr_setter)(GDExtensionVariantType p_type, GDExtensionConstStringNamePtr p_member);
+ GDExtensionPtrGetter (*variant_get_ptr_getter)(GDExtensionVariantType p_type, GDExtensionConstStringNamePtr p_member);
+ GDExtensionPtrIndexedSetter (*variant_get_ptr_indexed_setter)(GDExtensionVariantType p_type);
+ GDExtensionPtrIndexedGetter (*variant_get_ptr_indexed_getter)(GDExtensionVariantType p_type);
+ GDExtensionPtrKeyedSetter (*variant_get_ptr_keyed_setter)(GDExtensionVariantType p_type);
+ GDExtensionPtrKeyedGetter (*variant_get_ptr_keyed_getter)(GDExtensionVariantType p_type);
+ GDExtensionPtrKeyedChecker (*variant_get_ptr_keyed_checker)(GDExtensionVariantType p_type);
+ void (*variant_get_constant_value)(GDExtensionVariantType p_type, GDExtensionConstStringNamePtr p_constant, GDExtensionVariantPtr r_ret);
+ GDExtensionPtrUtilityFunction (*variant_get_ptr_utility_function)(GDExtensionConstStringNamePtr p_function, GDExtensionInt p_hash);
+
+ /* extra utilities */
+ void (*string_new_with_latin1_chars)(GDExtensionStringPtr r_dest, const char *p_contents);
+ void (*string_new_with_utf8_chars)(GDExtensionStringPtr r_dest, const char *p_contents);
+ void (*string_new_with_utf16_chars)(GDExtensionStringPtr r_dest, const char16_t *p_contents);
+ void (*string_new_with_utf32_chars)(GDExtensionStringPtr r_dest, const char32_t *p_contents);
+ void (*string_new_with_wide_chars)(GDExtensionStringPtr r_dest, const wchar_t *p_contents);
+ void (*string_new_with_latin1_chars_and_len)(GDExtensionStringPtr r_dest, const char *p_contents, GDExtensionInt p_size);
+ void (*string_new_with_utf8_chars_and_len)(GDExtensionStringPtr r_dest, const char *p_contents, GDExtensionInt p_size);
+ void (*string_new_with_utf16_chars_and_len)(GDExtensionStringPtr r_dest, const char16_t *p_contents, GDExtensionInt p_size);
+ void (*string_new_with_utf32_chars_and_len)(GDExtensionStringPtr r_dest, const char32_t *p_contents, GDExtensionInt p_size);
+ void (*string_new_with_wide_chars_and_len)(GDExtensionStringPtr r_dest, const wchar_t *p_contents, GDExtensionInt p_size);
+ /* Information about the following functions:
+ * - The return value is the resulting encoded string length.
+ * - The length returned is in characters, not in bytes. It also does not include a trailing zero.
+ * - These functions also do not write trailing zero, If you need it, write it yourself at the position indicated by the length (and make sure to allocate it).
+ * - Passing NULL in r_text means only the length is computed (again, without including trailing zero).
+ * - p_max_write_length argument is in characters, not bytes. It will be ignored if r_text is NULL.
+ * - p_max_write_length argument does not affect the return value, it's only to cap write length.
+ */
+ GDExtensionInt (*string_to_latin1_chars)(GDExtensionConstStringPtr p_self, char *r_text, GDExtensionInt p_max_write_length);
+ GDExtensionInt (*string_to_utf8_chars)(GDExtensionConstStringPtr p_self, char *r_text, GDExtensionInt p_max_write_length);
+ GDExtensionInt (*string_to_utf16_chars)(GDExtensionConstStringPtr p_self, char16_t *r_text, GDExtensionInt p_max_write_length);
+ GDExtensionInt (*string_to_utf32_chars)(GDExtensionConstStringPtr p_self, char32_t *r_text, GDExtensionInt p_max_write_length);
+ GDExtensionInt (*string_to_wide_chars)(GDExtensionConstStringPtr p_self, wchar_t *r_text, GDExtensionInt p_max_write_length);
+ char32_t *(*string_operator_index)(GDExtensionStringPtr p_self, GDExtensionInt p_index);
+ const char32_t *(*string_operator_index_const)(GDExtensionConstStringPtr p_self, GDExtensionInt p_index);
+
+ /* Packed array functions */
+
+ uint8_t *(*packed_byte_array_operator_index)(GDExtensionTypePtr p_self, GDExtensionInt p_index); // p_self should be a PackedByteArray
+ const uint8_t *(*packed_byte_array_operator_index_const)(GDExtensionConstTypePtr p_self, GDExtensionInt p_index); // p_self should be a PackedByteArray
+
+ GDExtensionTypePtr (*packed_color_array_operator_index)(GDExtensionTypePtr p_self, GDExtensionInt p_index); // p_self should be a PackedColorArray, returns Color ptr
+ GDExtensionTypePtr (*packed_color_array_operator_index_const)(GDExtensionConstTypePtr p_self, GDExtensionInt p_index); // p_self should be a PackedColorArray, returns Color ptr
+
+ float *(*packed_float32_array_operator_index)(GDExtensionTypePtr p_self, GDExtensionInt p_index); // p_self should be a PackedFloat32Array
+ const float *(*packed_float32_array_operator_index_const)(GDExtensionConstTypePtr p_self, GDExtensionInt p_index); // p_self should be a PackedFloat32Array
+ double *(*packed_float64_array_operator_index)(GDExtensionTypePtr p_self, GDExtensionInt p_index); // p_self should be a PackedFloat64Array
+ const double *(*packed_float64_array_operator_index_const)(GDExtensionConstTypePtr p_self, GDExtensionInt p_index); // p_self should be a PackedFloat64Array
+
+ int32_t *(*packed_int32_array_operator_index)(GDExtensionTypePtr p_self, GDExtensionInt p_index); // p_self should be a PackedInt32Array
+ const int32_t *(*packed_int32_array_operator_index_const)(GDExtensionConstTypePtr p_self, GDExtensionInt p_index); // p_self should be a PackedInt32Array
+ int64_t *(*packed_int64_array_operator_index)(GDExtensionTypePtr p_self, GDExtensionInt p_index); // p_self should be a PackedInt32Array
+ const int64_t *(*packed_int64_array_operator_index_const)(GDExtensionConstTypePtr p_self, GDExtensionInt p_index); // p_self should be a PackedInt32Array
+
+ GDExtensionStringPtr (*packed_string_array_operator_index)(GDExtensionTypePtr p_self, GDExtensionInt p_index); // p_self should be a PackedStringArray
+ GDExtensionStringPtr (*packed_string_array_operator_index_const)(GDExtensionConstTypePtr p_self, GDExtensionInt p_index); // p_self should be a PackedStringArray
+
+ GDExtensionTypePtr (*packed_vector2_array_operator_index)(GDExtensionTypePtr p_self, GDExtensionInt p_index); // p_self should be a PackedVector2Array, returns Vector2 ptr
+ GDExtensionTypePtr (*packed_vector2_array_operator_index_const)(GDExtensionConstTypePtr p_self, GDExtensionInt p_index); // p_self should be a PackedVector2Array, returns Vector2 ptr
+ GDExtensionTypePtr (*packed_vector3_array_operator_index)(GDExtensionTypePtr p_self, GDExtensionInt p_index); // p_self should be a PackedVector3Array, returns Vector3 ptr
+ GDExtensionTypePtr (*packed_vector3_array_operator_index_const)(GDExtensionConstTypePtr p_self, GDExtensionInt p_index); // p_self should be a PackedVector3Array, returns Vector3 ptr
+
+ GDExtensionVariantPtr (*array_operator_index)(GDExtensionTypePtr p_self, GDExtensionInt p_index); // p_self should be an Array ptr
+ GDExtensionVariantPtr (*array_operator_index_const)(GDExtensionConstTypePtr p_self, GDExtensionInt p_index); // p_self should be an Array ptr
+
+ /* Dictionary functions */
+
+ GDExtensionVariantPtr (*dictionary_operator_index)(GDExtensionTypePtr p_self, GDExtensionConstVariantPtr p_key); // p_self should be an Dictionary ptr
+ GDExtensionVariantPtr (*dictionary_operator_index_const)(GDExtensionConstTypePtr p_self, GDExtensionConstVariantPtr p_key); // p_self should be an Dictionary ptr
+
+ /* OBJECT */
+
+ void (*object_method_bind_call)(GDExtensionMethodBindPtr p_method_bind, GDExtensionObjectPtr p_instance, const GDExtensionConstVariantPtr *p_args, GDExtensionInt p_arg_count, GDExtensionVariantPtr r_ret, GDExtensionCallError *r_error);
+ void (*object_method_bind_ptrcall)(GDExtensionMethodBindPtr p_method_bind, GDExtensionObjectPtr p_instance, const GDExtensionConstTypePtr *p_args, GDExtensionTypePtr r_ret);
+ void (*object_destroy)(GDExtensionObjectPtr p_o);
+ GDExtensionObjectPtr (*global_get_singleton)(GDExtensionConstStringNamePtr p_name);
+
+ void *(*object_get_instance_binding)(GDExtensionObjectPtr p_o, void *p_token, const GDExtensionInstanceBindingCallbacks *p_callbacks);
+ void (*object_set_instance_binding)(GDExtensionObjectPtr p_o, void *p_token, void *p_binding, const GDExtensionInstanceBindingCallbacks *p_callbacks);
+
+ void (*object_set_instance)(GDExtensionObjectPtr p_o, GDExtensionConstStringNamePtr p_classname, GDExtensionClassInstancePtr p_instance); /* p_classname should be a registered extension class and should extend the p_o object's class. */
+
+ GDExtensionObjectPtr (*object_cast_to)(GDExtensionConstObjectPtr p_object, void *p_class_tag);
+ GDExtensionObjectPtr (*object_get_instance_from_id)(GDObjectInstanceID p_instance_id);
+ GDObjectInstanceID (*object_get_instance_id)(GDExtensionConstObjectPtr p_object);
+
+ /* REFERENCE */
+
+ GDExtensionObjectPtr (*ref_get_object)(GDExtensionConstRefPtr p_ref);
+ void (*ref_set_object)(GDExtensionRefPtr p_ref, GDExtensionObjectPtr p_object);
+
+ /* SCRIPT INSTANCE */
+
+ GDExtensionScriptInstancePtr (*script_instance_create)(const GDExtensionScriptInstanceInfo *p_info, GDExtensionScriptInstanceDataPtr p_instance_data);
+
+ /* CLASSDB */
+
+ GDExtensionObjectPtr (*classdb_construct_object)(GDExtensionConstStringNamePtr p_classname); /* The passed class must be a built-in godot class, or an already-registered extension class. In both case, object_set_instance should be called to fully initialize the object. */
+ GDExtensionMethodBindPtr (*classdb_get_method_bind)(GDExtensionConstStringNamePtr p_classname, GDExtensionConstStringNamePtr p_methodname, GDExtensionInt p_hash);
+ void *(*classdb_get_class_tag)(GDExtensionConstStringNamePtr p_classname);
+
+ /* CLASSDB EXTENSION */
+
+ /* Provided parameters for `classdb_register_extension_*` can be safely freed once the function returns. */
+ void (*classdb_register_extension_class)(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_parent_class_name, const GDExtensionClassCreationInfo *p_extension_funcs);
+ void (*classdb_register_extension_class_method)(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, const GDExtensionClassMethodInfo *p_method_info);
+ void (*classdb_register_extension_class_integer_constant)(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_enum_name, GDExtensionConstStringNamePtr p_constant_name, GDExtensionInt p_constant_value, GDExtensionBool p_is_bitfield);
+ void (*classdb_register_extension_class_property)(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, const GDExtensionPropertyInfo *p_info, GDExtensionConstStringNamePtr p_setter, GDExtensionConstStringNamePtr p_getter);
+ void (*classdb_register_extension_class_property_group)(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringPtr p_group_name, GDExtensionConstStringPtr p_prefix);
+ void (*classdb_register_extension_class_property_subgroup)(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringPtr p_subgroup_name, GDExtensionConstStringPtr p_prefix);
+ void (*classdb_register_extension_class_signal)(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_signal_name, const GDExtensionPropertyInfo *p_argument_info, GDExtensionInt p_argument_count);
+ void (*classdb_unregister_extension_class)(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name); /* Unregistering a parent class before a class that inherits it will result in failure. Inheritors must be unregistered first. */
+
+ void (*get_library_path)(GDExtensionClassLibraryPtr p_library, GDExtensionStringPtr r_path);
+
+} GDExtensionInterface;
+
+/* INITIALIZATION */
+
+typedef enum {
+ GDEXTENSION_INITIALIZATION_CORE,
+ GDEXTENSION_INITIALIZATION_SERVERS,
+ GDEXTENSION_INITIALIZATION_SCENE,
+ GDEXTENSION_INITIALIZATION_EDITOR,
+ GDEXTENSION_MAX_INITIALIZATION_LEVEL,
+} GDExtensionInitializationLevel;
+
+typedef struct {
+ /* Minimum initialization level required.
+ * If Core or Servers, the extension needs editor or game restart to take effect */
+ GDExtensionInitializationLevel minimum_initialization_level;
+ /* Up to the user to supply when initializing */
+ void *userdata;
+ /* This function will be called multiple times for each initialization level. */
+ void (*initialize)(void *userdata, GDExtensionInitializationLevel p_level);
+ void (*deinitialize)(void *userdata, GDExtensionInitializationLevel p_level);
+} GDExtensionInitialization;
+
+/* Define a C function prototype that implements the function below and expose it to dlopen() (or similar).
+ * This is the entry point of the GDExtension library and will be called on initialization.
+ * It can be used to set up different init levels, which are called during various stages of initialization/shutdown.
+ * The function name must be a unique one specified in the .gdextension config file.
+ */
+typedef GDExtensionBool (*GDExtensionInitializationFunction)(const GDExtensionInterface *p_interface, GDExtensionClassLibraryPtr p_library, GDExtensionInitialization *r_initialization);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // GDEXTENSION_INTERFACE_H
diff --git a/core/extension/native_extension_manager.cpp b/core/extension/gdextension_manager.cpp
index 186fcc44f6..5bdde78793 100644
--- a/core/extension/native_extension_manager.cpp
+++ b/core/extension/gdextension_manager.cpp
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* native_extension_manager.cpp */
+/* gdextension_manager.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,91 +28,91 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "native_extension_manager.h"
+#include "gdextension_manager.h"
#include "core/io/file_access.h"
-NativeExtensionManager::LoadStatus NativeExtensionManager::load_extension(const String &p_path) {
- if (native_extension_map.has(p_path)) {
+GDExtensionManager::LoadStatus GDExtensionManager::load_extension(const String &p_path) {
+ if (gdextension_map.has(p_path)) {
return LOAD_STATUS_ALREADY_LOADED;
}
- Ref<NativeExtension> extension = ResourceLoader::load(p_path);
+ Ref<GDExtension> extension = ResourceLoader::load(p_path);
if (extension.is_null()) {
return LOAD_STATUS_FAILED;
}
if (level >= 0) { // Already initialized up to some level.
int32_t minimum_level = extension->get_minimum_library_initialization_level();
- if (minimum_level < MIN(level, NativeExtension::INITIALIZATION_LEVEL_SCENE)) {
+ if (minimum_level < MIN(level, GDExtension::INITIALIZATION_LEVEL_SCENE)) {
return LOAD_STATUS_NEEDS_RESTART;
}
// Initialize up to current level.
for (int32_t i = minimum_level; i <= level; i++) {
- extension->initialize_library(NativeExtension::InitializationLevel(i));
+ extension->initialize_library(GDExtension::InitializationLevel(i));
}
}
- native_extension_map[p_path] = extension;
+ gdextension_map[p_path] = extension;
return LOAD_STATUS_OK;
}
-NativeExtensionManager::LoadStatus NativeExtensionManager::reload_extension(const String &p_path) {
+GDExtensionManager::LoadStatus GDExtensionManager::reload_extension(const String &p_path) {
return LOAD_STATUS_OK; //TODO
}
-NativeExtensionManager::LoadStatus NativeExtensionManager::unload_extension(const String &p_path) {
- if (!native_extension_map.has(p_path)) {
+GDExtensionManager::LoadStatus GDExtensionManager::unload_extension(const String &p_path) {
+ if (!gdextension_map.has(p_path)) {
return LOAD_STATUS_NOT_LOADED;
}
- Ref<NativeExtension> extension = native_extension_map[p_path];
+ Ref<GDExtension> extension = gdextension_map[p_path];
if (level >= 0) { // Already initialized up to some level.
int32_t minimum_level = extension->get_minimum_library_initialization_level();
- if (minimum_level < MIN(level, NativeExtension::INITIALIZATION_LEVEL_SCENE)) {
+ if (minimum_level < MIN(level, GDExtension::INITIALIZATION_LEVEL_SCENE)) {
return LOAD_STATUS_NEEDS_RESTART;
}
// Deinitialize down to current level.
for (int32_t i = level; i >= minimum_level; i--) {
- extension->deinitialize_library(NativeExtension::InitializationLevel(i));
+ extension->deinitialize_library(GDExtension::InitializationLevel(i));
}
}
- native_extension_map.erase(p_path);
+ gdextension_map.erase(p_path);
return LOAD_STATUS_OK;
}
-bool NativeExtensionManager::is_extension_loaded(const String &p_path) const {
- return native_extension_map.has(p_path);
+bool GDExtensionManager::is_extension_loaded(const String &p_path) const {
+ return gdextension_map.has(p_path);
}
-Vector<String> NativeExtensionManager::get_loaded_extensions() const {
+Vector<String> GDExtensionManager::get_loaded_extensions() const {
Vector<String> ret;
- for (const KeyValue<String, Ref<NativeExtension>> &E : native_extension_map) {
+ for (const KeyValue<String, Ref<GDExtension>> &E : gdextension_map) {
ret.push_back(E.key);
}
return ret;
}
-Ref<NativeExtension> NativeExtensionManager::get_extension(const String &p_path) {
- HashMap<String, Ref<NativeExtension>>::Iterator E = native_extension_map.find(p_path);
- ERR_FAIL_COND_V(!E, Ref<NativeExtension>());
+Ref<GDExtension> GDExtensionManager::get_extension(const String &p_path) {
+ HashMap<String, Ref<GDExtension>>::Iterator E = gdextension_map.find(p_path);
+ ERR_FAIL_COND_V(!E, Ref<GDExtension>());
return E->value;
}
-void NativeExtensionManager::initialize_extensions(NativeExtension::InitializationLevel p_level) {
+void GDExtensionManager::initialize_extensions(GDExtension::InitializationLevel p_level) {
ERR_FAIL_COND(int32_t(p_level) - 1 != level);
- for (KeyValue<String, Ref<NativeExtension>> &E : native_extension_map) {
+ for (KeyValue<String, Ref<GDExtension>> &E : gdextension_map) {
E.value->initialize_library(p_level);
}
level = p_level;
}
-void NativeExtensionManager::deinitialize_extensions(NativeExtension::InitializationLevel p_level) {
+void GDExtensionManager::deinitialize_extensions(GDExtension::InitializationLevel p_level) {
ERR_FAIL_COND(int32_t(p_level) != level);
- for (KeyValue<String, Ref<NativeExtension>> &E : native_extension_map) {
+ for (KeyValue<String, Ref<GDExtension>> &E : gdextension_map) {
E.value->deinitialize_library(p_level);
}
level = int32_t(p_level) - 1;
}
-void NativeExtensionManager::load_extensions() {
- Ref<FileAccess> f = FileAccess::open(NativeExtension::get_extension_list_config_file(), FileAccess::READ);
+void GDExtensionManager::load_extensions() {
+ Ref<FileAccess> f = FileAccess::open(GDExtension::get_extension_list_config_file(), FileAccess::READ);
while (f.is_valid() && !f->eof_reached()) {
String s = f->get_line().strip_edges();
if (!s.is_empty()) {
@@ -122,17 +122,17 @@ void NativeExtensionManager::load_extensions() {
}
}
-NativeExtensionManager *NativeExtensionManager::get_singleton() {
+GDExtensionManager *GDExtensionManager::get_singleton() {
return singleton;
}
-void NativeExtensionManager::_bind_methods() {
- ClassDB::bind_method(D_METHOD("load_extension", "path"), &NativeExtensionManager::load_extension);
- ClassDB::bind_method(D_METHOD("reload_extension", "path"), &NativeExtensionManager::reload_extension);
- ClassDB::bind_method(D_METHOD("unload_extension", "path"), &NativeExtensionManager::unload_extension);
- ClassDB::bind_method(D_METHOD("is_extension_loaded", "path"), &NativeExtensionManager::is_extension_loaded);
+void GDExtensionManager::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("load_extension", "path"), &GDExtensionManager::load_extension);
+ ClassDB::bind_method(D_METHOD("reload_extension", "path"), &GDExtensionManager::reload_extension);
+ ClassDB::bind_method(D_METHOD("unload_extension", "path"), &GDExtensionManager::unload_extension);
+ ClassDB::bind_method(D_METHOD("is_extension_loaded", "path"), &GDExtensionManager::is_extension_loaded);
- ClassDB::bind_method(D_METHOD("get_loaded_extensions"), &NativeExtensionManager::get_loaded_extensions);
- ClassDB::bind_method(D_METHOD("get_extension", "path"), &NativeExtensionManager::get_extension);
+ ClassDB::bind_method(D_METHOD("get_loaded_extensions"), &GDExtensionManager::get_loaded_extensions);
+ ClassDB::bind_method(D_METHOD("get_extension", "path"), &GDExtensionManager::get_extension);
BIND_ENUM_CONSTANT(LOAD_STATUS_OK);
BIND_ENUM_CONSTANT(LOAD_STATUS_FAILED);
@@ -141,9 +141,9 @@ void NativeExtensionManager::_bind_methods() {
BIND_ENUM_CONSTANT(LOAD_STATUS_NEEDS_RESTART);
}
-NativeExtensionManager *NativeExtensionManager::singleton = nullptr;
+GDExtensionManager *GDExtensionManager::singleton = nullptr;
-NativeExtensionManager::NativeExtensionManager() {
+GDExtensionManager::GDExtensionManager() {
ERR_FAIL_COND(singleton != nullptr);
singleton = this;
}
diff --git a/core/extension/native_extension_manager.h b/core/extension/gdextension_manager.h
index ed80cd6b7a..2f2aa0e0d4 100644
--- a/core/extension/native_extension_manager.h
+++ b/core/extension/gdextension_manager.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* native_extension_manager.h */
+/* gdextension_manager.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,20 +28,20 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef NATIVE_EXTENSION_MANAGER_H
-#define NATIVE_EXTENSION_MANAGER_H
+#ifndef GDEXTENSION_MANAGER_H
+#define GDEXTENSION_MANAGER_H
-#include "core/extension/native_extension.h"
+#include "core/extension/gdextension.h"
-class NativeExtensionManager : public Object {
- GDCLASS(NativeExtensionManager, Object);
+class GDExtensionManager : public Object {
+ GDCLASS(GDExtensionManager, Object);
int32_t level = -1;
- HashMap<String, Ref<NativeExtension>> native_extension_map;
+ HashMap<String, Ref<GDExtension>> gdextension_map;
static void _bind_methods();
- static NativeExtensionManager *singleton;
+ static GDExtensionManager *singleton;
public:
enum LoadStatus {
@@ -57,18 +57,18 @@ public:
LoadStatus unload_extension(const String &p_path);
bool is_extension_loaded(const String &p_path) const;
Vector<String> get_loaded_extensions() const;
- Ref<NativeExtension> get_extension(const String &p_path);
+ Ref<GDExtension> get_extension(const String &p_path);
- void initialize_extensions(NativeExtension::InitializationLevel p_level);
- void deinitialize_extensions(NativeExtension::InitializationLevel p_level);
+ void initialize_extensions(GDExtension::InitializationLevel p_level);
+ void deinitialize_extensions(GDExtension::InitializationLevel p_level);
- static NativeExtensionManager *get_singleton();
+ static GDExtensionManager *get_singleton();
void load_extensions();
- NativeExtensionManager();
+ GDExtensionManager();
};
-VARIANT_ENUM_CAST(NativeExtensionManager::LoadStatus)
+VARIANT_ENUM_CAST(GDExtensionManager::LoadStatus)
-#endif // NATIVE_EXTENSION_MANAGER_H
+#endif // GDEXTENSION_MANAGER_H
diff --git a/core/extension/gdnative_interface.cpp b/core/extension/gdnative_interface.cpp
deleted file mode 100644
index 864f2fa86b..0000000000
--- a/core/extension/gdnative_interface.cpp
+++ /dev/null
@@ -1,1083 +0,0 @@
-/*************************************************************************/
-/* gdnative_interface.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 "gdnative_interface.h"
-
-#include "core/config/engine.h"
-#include "core/object/class_db.h"
-#include "core/object/script_language_extension.h"
-#include "core/os/memory.h"
-#include "core/variant/variant.h"
-#include "core/version.h"
-
-// Memory Functions
-static void *gdnative_alloc(size_t p_size) {
- return memalloc(p_size);
-}
-
-static void *gdnative_realloc(void *p_mem, size_t p_size) {
- return memrealloc(p_mem, p_size);
-}
-
-static void gdnative_free(void *p_mem) {
- memfree(p_mem);
-}
-
-// Helper print functions.
-static void gdnative_print_error(const char *p_description, const char *p_function, const char *p_file, int32_t p_line) {
- _err_print_error(p_function, p_file, p_line, p_description, false, ERR_HANDLER_ERROR);
-}
-static void gdnative_print_warning(const char *p_description, const char *p_function, const char *p_file, int32_t p_line) {
- _err_print_error(p_function, p_file, p_line, p_description, false, ERR_HANDLER_WARNING);
-}
-static void gdnative_print_script_error(const char *p_description, const char *p_function, const char *p_file, int32_t p_line) {
- _err_print_error(p_function, p_file, p_line, p_description, false, ERR_HANDLER_SCRIPT);
-}
-
-uint64_t gdnative_get_native_struct_size(const GDNativeStringNamePtr p_name) {
- const StringName name = *reinterpret_cast<const StringName *>(p_name);
- return ClassDB::get_native_struct_size(name);
-}
-
-// Variant functions
-
-static void gdnative_variant_new_copy(GDNativeVariantPtr r_dest, const GDNativeVariantPtr p_src) {
- memnew_placement(reinterpret_cast<Variant *>(r_dest), Variant(*reinterpret_cast<Variant *>(p_src)));
-}
-static void gdnative_variant_new_nil(GDNativeVariantPtr r_dest) {
- memnew_placement(reinterpret_cast<Variant *>(r_dest), Variant);
-}
-static void gdnative_variant_destroy(GDNativeVariantPtr p_self) {
- reinterpret_cast<Variant *>(p_self)->~Variant();
-}
-
-// variant type
-
-static void gdnative_variant_call(GDNativeVariantPtr p_self, const GDNativeStringNamePtr p_method, const GDNativeVariantPtr *p_args, const GDNativeInt p_argcount, GDNativeVariantPtr r_return, GDNativeCallError *r_error) {
- Variant *self = (Variant *)p_self;
- const StringName method = *reinterpret_cast<const StringName *>(p_method);
- const Variant **args = (const Variant **)p_args;
- Variant ret;
- Callable::CallError error;
- self->callp(method, args, p_argcount, ret, error);
- memnew_placement(r_return, Variant(ret));
-
- if (r_error) {
- r_error->error = (GDNativeCallErrorType)(error.error);
- r_error->argument = error.argument;
- r_error->expected = error.expected;
- }
-}
-
-static void gdnative_variant_call_static(GDNativeVariantType p_type, const GDNativeStringNamePtr p_method, const GDNativeVariantPtr *p_args, const GDNativeInt p_argcount, GDNativeVariantPtr r_return, GDNativeCallError *r_error) {
- Variant::Type type = (Variant::Type)p_type;
- const StringName method = *reinterpret_cast<const StringName *>(p_method);
- const Variant **args = (const Variant **)p_args;
- Variant ret;
- Callable::CallError error;
- Variant::call_static(type, method, args, p_argcount, ret, error);
- memnew_placement(r_return, Variant(ret));
-
- if (r_error) {
- r_error->error = (GDNativeCallErrorType)error.error;
- r_error->argument = error.argument;
- r_error->expected = error.expected;
- }
-}
-
-static void gdnative_variant_evaluate(GDNativeVariantOperator p_op, const GDNativeVariantPtr p_a, const GDNativeVariantPtr p_b, GDNativeVariantPtr r_return, GDNativeBool *r_valid) {
- Variant::Operator op = (Variant::Operator)p_op;
- const Variant *a = (const Variant *)p_a;
- const Variant *b = (const Variant *)p_b;
- Variant *ret = (Variant *)r_return;
- bool valid;
- Variant::evaluate(op, *a, *b, *ret, valid);
- *r_valid = valid;
-}
-
-static void gdnative_variant_set(GDNativeVariantPtr p_self, const GDNativeVariantPtr p_key, const GDNativeVariantPtr p_value, GDNativeBool *r_valid) {
- Variant *self = (Variant *)p_self;
- const Variant *key = (const Variant *)p_key;
- const Variant *value = (const Variant *)p_value;
-
- bool valid;
- self->set(*key, *value, &valid);
- *r_valid = valid;
-}
-
-static void gdnative_variant_set_named(GDNativeVariantPtr p_self, const GDNativeStringNamePtr p_key, const GDNativeVariantPtr p_value, GDNativeBool *r_valid) {
- Variant *self = (Variant *)p_self;
- const StringName *key = (const StringName *)p_key;
- const Variant *value = (const Variant *)p_value;
-
- bool valid;
- self->set_named(*key, *value, valid);
- *r_valid = valid;
-}
-
-static void gdnative_variant_set_keyed(GDNativeVariantPtr p_self, const GDNativeVariantPtr p_key, const GDNativeVariantPtr p_value, GDNativeBool *r_valid) {
- Variant *self = (Variant *)p_self;
- const Variant *key = (const Variant *)p_key;
- const Variant *value = (const Variant *)p_value;
-
- bool valid;
- self->set_keyed(*key, *value, valid);
- *r_valid = valid;
-}
-
-static void gdnative_variant_set_indexed(GDNativeVariantPtr p_self, GDNativeInt p_index, const GDNativeVariantPtr p_value, GDNativeBool *r_valid, GDNativeBool *r_oob) {
- Variant *self = (Variant *)p_self;
- const Variant *value = (const Variant *)p_value;
-
- bool valid;
- bool oob;
- self->set_indexed(p_index, *value, valid, oob);
- *r_valid = valid;
- *r_oob = oob;
-}
-
-static void gdnative_variant_get(const GDNativeVariantPtr p_self, const GDNativeVariantPtr p_key, GDNativeVariantPtr r_ret, GDNativeBool *r_valid) {
- const Variant *self = (const Variant *)p_self;
- const Variant *key = (const Variant *)p_key;
-
- bool valid;
- memnew_placement(r_ret, Variant(self->get(*key, &valid)));
- *r_valid = valid;
-}
-
-static void gdnative_variant_get_named(const GDNativeVariantPtr p_self, const GDNativeStringNamePtr p_key, GDNativeVariantPtr r_ret, GDNativeBool *r_valid) {
- const Variant *self = (const Variant *)p_self;
- const StringName *key = (const StringName *)p_key;
-
- bool valid;
- memnew_placement(r_ret, Variant(self->get_named(*key, valid)));
- *r_valid = valid;
-}
-
-static void gdnative_variant_get_keyed(const GDNativeVariantPtr p_self, const GDNativeVariantPtr p_key, GDNativeVariantPtr r_ret, GDNativeBool *r_valid) {
- const Variant *self = (const Variant *)p_self;
- const Variant *key = (const Variant *)p_key;
-
- bool valid;
- memnew_placement(r_ret, Variant(self->get_keyed(*key, valid)));
- *r_valid = valid;
-}
-
-static void gdnative_variant_get_indexed(const GDNativeVariantPtr p_self, GDNativeInt p_index, GDNativeVariantPtr r_ret, GDNativeBool *r_valid, GDNativeBool *r_oob) {
- const Variant *self = (const Variant *)p_self;
-
- bool valid;
- bool oob;
- memnew_placement(r_ret, Variant(self->get_indexed(p_index, valid, oob)));
- *r_valid = valid;
- *r_oob = oob;
-}
-
-/// Iteration.
-static GDNativeBool gdnative_variant_iter_init(const GDNativeVariantPtr p_self, GDNativeVariantPtr r_iter, GDNativeBool *r_valid) {
- const Variant *self = (const Variant *)p_self;
- Variant *iter = (Variant *)r_iter;
-
- bool valid;
- bool ret = self->iter_init(*iter, valid);
- *r_valid = valid;
- return ret;
-}
-
-static GDNativeBool gdnative_variant_iter_next(const GDNativeVariantPtr p_self, GDNativeVariantPtr r_iter, GDNativeBool *r_valid) {
- const Variant *self = (const Variant *)p_self;
- Variant *iter = (Variant *)r_iter;
-
- bool valid;
- bool ret = self->iter_next(*iter, valid);
- *r_valid = valid;
- return ret;
-}
-
-static void gdnative_variant_iter_get(const GDNativeVariantPtr p_self, GDNativeVariantPtr r_iter, GDNativeVariantPtr r_ret, GDNativeBool *r_valid) {
- const Variant *self = (const Variant *)p_self;
- Variant *iter = (Variant *)r_iter;
-
- bool valid;
- memnew_placement(r_ret, Variant(self->iter_next(*iter, valid)));
- *r_valid = valid;
-}
-
-/// Variant functions.
-static GDNativeInt gdnative_variant_hash(const GDNativeVariantPtr p_self) {
- const Variant *self = (const Variant *)p_self;
- return self->hash();
-}
-
-static GDNativeInt gdnative_variant_recursive_hash(const GDNativeVariantPtr p_self, GDNativeInt p_recursion_count) {
- const Variant *self = (const Variant *)p_self;
- return self->recursive_hash(p_recursion_count);
-}
-
-static GDNativeBool gdnative_variant_hash_compare(const GDNativeVariantPtr p_self, const GDNativeVariantPtr p_other) {
- const Variant *self = (const Variant *)p_self;
- const Variant *other = (const Variant *)p_other;
- return self->hash_compare(*other);
-}
-
-static GDNativeBool gdnative_variant_booleanize(const GDNativeVariantPtr p_self) {
- const Variant *self = (const Variant *)p_self;
- return self->booleanize();
-}
-
-static void gdnative_variant_duplicate(const GDNativeVariantPtr p_self, GDNativeVariantPtr r_ret, GDNativeBool p_deep) {
- const Variant *self = (const Variant *)p_self;
- memnew_placement(r_ret, Variant(self->duplicate(p_deep)));
-}
-
-static void gdnative_variant_stringify(const GDNativeVariantPtr p_self, GDNativeStringPtr r_ret) {
- const Variant *self = (const Variant *)p_self;
- memnew_placement(r_ret, String(*self));
-}
-
-static GDNativeVariantType gdnative_variant_get_type(const GDNativeVariantPtr p_self) {
- const Variant *self = (const Variant *)p_self;
- return (GDNativeVariantType)self->get_type();
-}
-
-static GDNativeBool gdnative_variant_has_method(const GDNativeVariantPtr p_self, const GDNativeStringNamePtr p_method) {
- const Variant *self = (const Variant *)p_self;
- const StringName *method = (const StringName *)p_method;
- return self->has_method(*method);
-}
-
-static GDNativeBool gdnative_variant_has_member(GDNativeVariantType p_type, const GDNativeStringNamePtr p_member) {
- return Variant::has_member((Variant::Type)p_type, *((const StringName *)p_member));
-}
-
-static GDNativeBool gdnative_variant_has_key(const GDNativeVariantPtr p_self, const GDNativeVariantPtr p_key, GDNativeBool *r_valid) {
- const Variant *self = (const Variant *)p_self;
- const Variant *key = (const Variant *)p_key;
- bool valid;
- bool ret = self->has_key(*key, valid);
- *r_valid = valid;
- return ret;
-}
-
-static void gdnative_variant_get_type_name(GDNativeVariantType p_type, GDNativeStringPtr r_ret) {
- String name = Variant::get_type_name((Variant::Type)p_type);
- memnew_placement(r_ret, String(name));
-}
-
-static GDNativeBool gdnative_variant_can_convert(GDNativeVariantType p_from, GDNativeVariantType p_to) {
- return Variant::can_convert((Variant::Type)p_from, (Variant::Type)p_to);
-}
-
-static GDNativeBool gdnative_variant_can_convert_strict(GDNativeVariantType p_from, GDNativeVariantType p_to) {
- return Variant::can_convert_strict((Variant::Type)p_from, (Variant::Type)p_to);
-}
-
-// Variant interaction.
-static GDNativeVariantFromTypeConstructorFunc gdnative_get_variant_from_type_constructor(GDNativeVariantType p_type) {
- switch (p_type) {
- case GDNATIVE_VARIANT_TYPE_BOOL:
- return VariantTypeConstructor<bool>::variant_from_type;
- case GDNATIVE_VARIANT_TYPE_INT:
- return VariantTypeConstructor<int64_t>::variant_from_type;
- case GDNATIVE_VARIANT_TYPE_FLOAT:
- return VariantTypeConstructor<double>::variant_from_type;
- case GDNATIVE_VARIANT_TYPE_STRING:
- return VariantTypeConstructor<String>::variant_from_type;
- case GDNATIVE_VARIANT_TYPE_VECTOR2:
- return VariantTypeConstructor<Vector2>::variant_from_type;
- case GDNATIVE_VARIANT_TYPE_VECTOR2I:
- return VariantTypeConstructor<Vector2i>::variant_from_type;
- case GDNATIVE_VARIANT_TYPE_RECT2:
- return VariantTypeConstructor<Rect2>::variant_from_type;
- case GDNATIVE_VARIANT_TYPE_RECT2I:
- return VariantTypeConstructor<Rect2i>::variant_from_type;
- case GDNATIVE_VARIANT_TYPE_VECTOR3:
- return VariantTypeConstructor<Vector3>::variant_from_type;
- case GDNATIVE_VARIANT_TYPE_VECTOR3I:
- 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:
- return VariantTypeConstructor<Quaternion>::variant_from_type;
- case GDNATIVE_VARIANT_TYPE_AABB:
- return VariantTypeConstructor<AABB>::variant_from_type;
- case GDNATIVE_VARIANT_TYPE_BASIS:
- 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:
- return VariantTypeConstructor<StringName>::variant_from_type;
- case GDNATIVE_VARIANT_TYPE_NODE_PATH:
- return VariantTypeConstructor<NodePath>::variant_from_type;
- case GDNATIVE_VARIANT_TYPE_RID:
- return VariantTypeConstructor<RID>::variant_from_type;
- case GDNATIVE_VARIANT_TYPE_OBJECT:
- return VariantTypeConstructor<Object *>::variant_from_type;
- case GDNATIVE_VARIANT_TYPE_CALLABLE:
- return VariantTypeConstructor<Callable>::variant_from_type;
- case GDNATIVE_VARIANT_TYPE_SIGNAL:
- return VariantTypeConstructor<Signal>::variant_from_type;
- case GDNATIVE_VARIANT_TYPE_DICTIONARY:
- return VariantTypeConstructor<Dictionary>::variant_from_type;
- case GDNATIVE_VARIANT_TYPE_ARRAY:
- return VariantTypeConstructor<Array>::variant_from_type;
- case GDNATIVE_VARIANT_TYPE_PACKED_BYTE_ARRAY:
- return VariantTypeConstructor<PackedByteArray>::variant_from_type;
- case GDNATIVE_VARIANT_TYPE_PACKED_INT32_ARRAY:
- return VariantTypeConstructor<PackedInt32Array>::variant_from_type;
- case GDNATIVE_VARIANT_TYPE_PACKED_INT64_ARRAY:
- return VariantTypeConstructor<PackedInt64Array>::variant_from_type;
- case GDNATIVE_VARIANT_TYPE_PACKED_FLOAT32_ARRAY:
- return VariantTypeConstructor<PackedFloat32Array>::variant_from_type;
- case GDNATIVE_VARIANT_TYPE_PACKED_FLOAT64_ARRAY:
- return VariantTypeConstructor<PackedFloat64Array>::variant_from_type;
- case GDNATIVE_VARIANT_TYPE_PACKED_STRING_ARRAY:
- return VariantTypeConstructor<PackedStringArray>::variant_from_type;
- case GDNATIVE_VARIANT_TYPE_PACKED_VECTOR2_ARRAY:
- return VariantTypeConstructor<PackedVector2Array>::variant_from_type;
- case GDNATIVE_VARIANT_TYPE_PACKED_VECTOR3_ARRAY:
- return VariantTypeConstructor<PackedVector3Array>::variant_from_type;
- case GDNATIVE_VARIANT_TYPE_PACKED_COLOR_ARRAY:
- return VariantTypeConstructor<PackedColorArray>::variant_from_type;
- case GDNATIVE_VARIANT_TYPE_NIL:
- case GDNATIVE_VARIANT_TYPE_VARIANT_MAX:
- ERR_FAIL_V_MSG(nullptr, "Getting Variant conversion function with invalid type");
- }
- ERR_FAIL_V_MSG(nullptr, "Getting Variant conversion function with invalid type");
-}
-
-static GDNativeTypeFromVariantConstructorFunc gdnative_get_type_from_variant_constructor(GDNativeVariantType p_type) {
- switch (p_type) {
- case GDNATIVE_VARIANT_TYPE_BOOL:
- return VariantTypeConstructor<bool>::type_from_variant;
- case GDNATIVE_VARIANT_TYPE_INT:
- return VariantTypeConstructor<int64_t>::type_from_variant;
- case GDNATIVE_VARIANT_TYPE_FLOAT:
- return VariantTypeConstructor<double>::type_from_variant;
- case GDNATIVE_VARIANT_TYPE_STRING:
- return VariantTypeConstructor<String>::type_from_variant;
- case GDNATIVE_VARIANT_TYPE_VECTOR2:
- return VariantTypeConstructor<Vector2>::type_from_variant;
- case GDNATIVE_VARIANT_TYPE_VECTOR2I:
- return VariantTypeConstructor<Vector2i>::type_from_variant;
- case GDNATIVE_VARIANT_TYPE_RECT2:
- return VariantTypeConstructor<Rect2>::type_from_variant;
- case GDNATIVE_VARIANT_TYPE_RECT2I:
- return VariantTypeConstructor<Rect2i>::type_from_variant;
- case GDNATIVE_VARIANT_TYPE_VECTOR3:
- return VariantTypeConstructor<Vector3>::type_from_variant;
- case GDNATIVE_VARIANT_TYPE_VECTOR3I:
- 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:
- return VariantTypeConstructor<Quaternion>::type_from_variant;
- case GDNATIVE_VARIANT_TYPE_AABB:
- return VariantTypeConstructor<AABB>::type_from_variant;
- case GDNATIVE_VARIANT_TYPE_BASIS:
- 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:
- return VariantTypeConstructor<StringName>::type_from_variant;
- case GDNATIVE_VARIANT_TYPE_NODE_PATH:
- return VariantTypeConstructor<NodePath>::type_from_variant;
- case GDNATIVE_VARIANT_TYPE_RID:
- return VariantTypeConstructor<RID>::type_from_variant;
- case GDNATIVE_VARIANT_TYPE_OBJECT:
- return VariantTypeConstructor<Object *>::type_from_variant;
- case GDNATIVE_VARIANT_TYPE_CALLABLE:
- return VariantTypeConstructor<Callable>::type_from_variant;
- case GDNATIVE_VARIANT_TYPE_SIGNAL:
- return VariantTypeConstructor<Signal>::type_from_variant;
- case GDNATIVE_VARIANT_TYPE_DICTIONARY:
- return VariantTypeConstructor<Dictionary>::type_from_variant;
- case GDNATIVE_VARIANT_TYPE_ARRAY:
- return VariantTypeConstructor<Array>::type_from_variant;
- case GDNATIVE_VARIANT_TYPE_PACKED_BYTE_ARRAY:
- return VariantTypeConstructor<PackedByteArray>::type_from_variant;
- case GDNATIVE_VARIANT_TYPE_PACKED_INT32_ARRAY:
- return VariantTypeConstructor<PackedInt32Array>::type_from_variant;
- case GDNATIVE_VARIANT_TYPE_PACKED_INT64_ARRAY:
- return VariantTypeConstructor<PackedInt64Array>::type_from_variant;
- case GDNATIVE_VARIANT_TYPE_PACKED_FLOAT32_ARRAY:
- return VariantTypeConstructor<PackedFloat32Array>::type_from_variant;
- case GDNATIVE_VARIANT_TYPE_PACKED_FLOAT64_ARRAY:
- return VariantTypeConstructor<PackedFloat64Array>::type_from_variant;
- case GDNATIVE_VARIANT_TYPE_PACKED_STRING_ARRAY:
- return VariantTypeConstructor<PackedStringArray>::type_from_variant;
- case GDNATIVE_VARIANT_TYPE_PACKED_VECTOR2_ARRAY:
- return VariantTypeConstructor<PackedVector2Array>::type_from_variant;
- case GDNATIVE_VARIANT_TYPE_PACKED_VECTOR3_ARRAY:
- return VariantTypeConstructor<PackedVector3Array>::type_from_variant;
- case GDNATIVE_VARIANT_TYPE_PACKED_COLOR_ARRAY:
- return VariantTypeConstructor<PackedColorArray>::type_from_variant;
- case GDNATIVE_VARIANT_TYPE_NIL:
- case GDNATIVE_VARIANT_TYPE_VARIANT_MAX:
- ERR_FAIL_V_MSG(nullptr, "Getting Variant conversion function with invalid type");
- }
- ERR_FAIL_V_MSG(nullptr, "Getting Variant conversion function with invalid type");
-}
-
-// ptrcalls
-static GDNativePtrOperatorEvaluator gdnative_variant_get_ptr_operator_evaluator(GDNativeVariantOperator p_operator, GDNativeVariantType p_type_a, GDNativeVariantType p_type_b) {
- return (GDNativePtrOperatorEvaluator)Variant::get_ptr_operator_evaluator(Variant::Operator(p_operator), Variant::Type(p_type_a), Variant::Type(p_type_b));
-}
-static GDNativePtrBuiltInMethod gdnative_variant_get_ptr_builtin_method(GDNativeVariantType p_type, const GDNativeStringNamePtr p_method, GDNativeInt p_hash) {
- const StringName method = *reinterpret_cast<const StringName *>(p_method);
- uint32_t hash = Variant::get_builtin_method_hash(Variant::Type(p_type), method);
- if (hash != p_hash) {
- ERR_PRINT_ONCE("Error getting method " + method + ", hash mismatch.");
- return nullptr;
- }
-
- return (GDNativePtrBuiltInMethod)Variant::get_ptr_builtin_method(Variant::Type(p_type), method);
-}
-static GDNativePtrConstructor gdnative_variant_get_ptr_constructor(GDNativeVariantType p_type, int32_t p_constructor) {
- return (GDNativePtrConstructor)Variant::get_ptr_constructor(Variant::Type(p_type), p_constructor);
-}
-static GDNativePtrDestructor gdnative_variant_get_ptr_destructor(GDNativeVariantType p_type) {
- return (GDNativePtrDestructor)Variant::get_ptr_destructor(Variant::Type(p_type));
-}
-static void gdnative_variant_construct(GDNativeVariantType p_type, GDNativeVariantPtr p_base, const GDNativeVariantPtr *p_args, int32_t p_argument_count, GDNativeCallError *r_error) {
- memnew_placement(p_base, Variant);
-
- Callable::CallError error;
- Variant::construct(Variant::Type(p_type), *(Variant *)p_base, (const Variant **)p_args, p_argument_count, error);
-
- if (r_error) {
- r_error->error = (GDNativeCallErrorType)(error.error);
- r_error->argument = error.argument;
- r_error->expected = error.expected;
- }
-}
-static GDNativePtrSetter gdnative_variant_get_ptr_setter(GDNativeVariantType p_type, const GDNativeStringNamePtr p_member) {
- const StringName member = *reinterpret_cast<const StringName *>(p_member);
- return (GDNativePtrSetter)Variant::get_member_ptr_setter(Variant::Type(p_type), member);
-}
-static GDNativePtrGetter gdnative_variant_get_ptr_getter(GDNativeVariantType p_type, const GDNativeStringNamePtr p_member) {
- const StringName member = *reinterpret_cast<const StringName *>(p_member);
- return (GDNativePtrGetter)Variant::get_member_ptr_getter(Variant::Type(p_type), member);
-}
-static GDNativePtrIndexedSetter gdnative_variant_get_ptr_indexed_setter(GDNativeVariantType p_type) {
- return (GDNativePtrIndexedSetter)Variant::get_member_ptr_indexed_setter(Variant::Type(p_type));
-}
-static GDNativePtrIndexedGetter gdnative_variant_get_ptr_indexed_getter(GDNativeVariantType p_type) {
- return (GDNativePtrIndexedGetter)Variant::get_member_ptr_indexed_getter(Variant::Type(p_type));
-}
-static GDNativePtrKeyedSetter gdnative_variant_get_ptr_keyed_setter(GDNativeVariantType p_type) {
- return (GDNativePtrKeyedSetter)Variant::get_member_ptr_keyed_setter(Variant::Type(p_type));
-}
-static GDNativePtrKeyedGetter gdnative_variant_get_ptr_keyed_getter(GDNativeVariantType p_type) {
- return (GDNativePtrKeyedGetter)Variant::get_member_ptr_keyed_getter(Variant::Type(p_type));
-}
-static GDNativePtrKeyedChecker gdnative_variant_get_ptr_keyed_checker(GDNativeVariantType p_type) {
- return (GDNativePtrKeyedChecker)Variant::get_member_ptr_keyed_checker(Variant::Type(p_type));
-}
-static void gdnative_variant_get_constant_value(GDNativeVariantType p_type, const GDNativeStringNamePtr p_constant, GDNativeVariantPtr r_ret) {
- StringName constant = *reinterpret_cast<const StringName *>(p_constant);
- memnew_placement(r_ret, Variant(Variant::get_constant_value(Variant::Type(p_type), constant)));
-}
-static GDNativePtrUtilityFunction gdnative_variant_get_ptr_utility_function(const GDNativeStringNamePtr p_function, GDNativeInt p_hash) {
- StringName function = *reinterpret_cast<const StringName *>(p_function);
- uint32_t hash = Variant::get_utility_function_hash(function);
- if (hash != p_hash) {
- ERR_PRINT_ONCE("Error getting utility function " + function + ", hash mismatch.");
- return nullptr;
- }
- return (GDNativePtrUtilityFunction)Variant::get_ptr_utility_function(function);
-}
-
-//string helpers
-
-static void gdnative_string_new_with_latin1_chars(GDNativeStringPtr r_dest, const char *p_contents) {
- String *dest = (String *)r_dest;
- memnew_placement(dest, String);
- *dest = String(p_contents);
-}
-
-static void gdnative_string_new_with_utf8_chars(GDNativeStringPtr r_dest, const char *p_contents) {
- String *dest = (String *)r_dest;
- memnew_placement(dest, String);
- dest->parse_utf8(p_contents);
-}
-
-static void gdnative_string_new_with_utf16_chars(GDNativeStringPtr r_dest, const char16_t *p_contents) {
- String *dest = (String *)r_dest;
- memnew_placement(dest, String);
- dest->parse_utf16(p_contents);
-}
-
-static void gdnative_string_new_with_utf32_chars(GDNativeStringPtr r_dest, const char32_t *p_contents) {
- String *dest = (String *)r_dest;
- memnew_placement(dest, String);
- *dest = String((const char32_t *)p_contents);
-}
-
-static void gdnative_string_new_with_wide_chars(GDNativeStringPtr r_dest, const wchar_t *p_contents) {
- String *dest = (String *)r_dest;
- if constexpr (sizeof(wchar_t) == 2) {
- // wchar_t is 16 bit, parse.
- memnew_placement(dest, String);
- dest->parse_utf16((const char16_t *)p_contents);
- } else {
- // wchar_t is 32 bit, copy.
- memnew_placement(dest, String);
- *dest = String((const char32_t *)p_contents);
- }
-}
-
-static void gdnative_string_new_with_latin1_chars_and_len(GDNativeStringPtr r_dest, const char *p_contents, const GDNativeInt p_size) {
- String *dest = (String *)r_dest;
- memnew_placement(dest, String);
- *dest = String(p_contents, p_size);
-}
-
-static void gdnative_string_new_with_utf8_chars_and_len(GDNativeStringPtr r_dest, const char *p_contents, const GDNativeInt p_size) {
- String *dest = (String *)r_dest;
- memnew_placement(dest, String);
- dest->parse_utf8(p_contents, p_size);
-}
-
-static void gdnative_string_new_with_utf16_chars_and_len(GDNativeStringPtr r_dest, const char16_t *p_contents, const GDNativeInt p_size) {
- String *dest = (String *)r_dest;
- memnew_placement(dest, String);
- dest->parse_utf16(p_contents, p_size);
-}
-
-static void gdnative_string_new_with_utf32_chars_and_len(GDNativeStringPtr r_dest, const char32_t *p_contents, const GDNativeInt p_size) {
- String *dest = (String *)r_dest;
- memnew_placement(dest, String);
- *dest = String((const char32_t *)p_contents, p_size);
-}
-
-static void gdnative_string_new_with_wide_chars_and_len(GDNativeStringPtr r_dest, const wchar_t *p_contents, const GDNativeInt p_size) {
- String *dest = (String *)r_dest;
- if constexpr (sizeof(wchar_t) == 2) {
- // wchar_t is 16 bit, parse.
- memnew_placement(dest, String);
- dest->parse_utf16((const char16_t *)p_contents, p_size);
- } else {
- // wchar_t is 32 bit, copy.
- memnew_placement(dest, String);
- *dest = String((const char32_t *)p_contents, p_size);
- }
-}
-
-static GDNativeInt gdnative_string_to_latin1_chars(const GDNativeStringPtr p_self, char *r_text, GDNativeInt p_max_write_length) {
- String *self = (String *)p_self;
- CharString cs = self->ascii(true);
- GDNativeInt len = cs.length();
- if (r_text) {
- const char *s_text = cs.ptr();
- for (GDNativeInt i = 0; i < MIN(len, p_max_write_length); i++) {
- r_text[i] = s_text[i];
- }
- }
- return len;
-}
-static GDNativeInt gdnative_string_to_utf8_chars(const GDNativeStringPtr p_self, char *r_text, GDNativeInt p_max_write_length) {
- String *self = (String *)p_self;
- CharString cs = self->utf8();
- GDNativeInt len = cs.length();
- if (r_text) {
- const char *s_text = cs.ptr();
- for (GDNativeInt i = 0; i < MIN(len, p_max_write_length); i++) {
- r_text[i] = s_text[i];
- }
- }
- return len;
-}
-static GDNativeInt gdnative_string_to_utf16_chars(const GDNativeStringPtr p_self, char16_t *r_text, GDNativeInt p_max_write_length) {
- String *self = (String *)p_self;
- Char16String cs = self->utf16();
- GDNativeInt len = cs.length();
- if (r_text) {
- const char16_t *s_text = cs.ptr();
- for (GDNativeInt i = 0; i < MIN(len, p_max_write_length); i++) {
- r_text[i] = s_text[i];
- }
- }
- return len;
-}
-static GDNativeInt gdnative_string_to_utf32_chars(const GDNativeStringPtr p_self, char32_t *r_text, GDNativeInt p_max_write_length) {
- String *self = (String *)p_self;
- GDNativeInt len = self->length();
- if (r_text) {
- const char32_t *s_text = self->ptr();
- for (GDNativeInt i = 0; i < MIN(len, p_max_write_length); i++) {
- r_text[i] = s_text[i];
- }
- }
- return len;
-}
-static GDNativeInt gdnative_string_to_wide_chars(const GDNativeStringPtr p_self, wchar_t *r_text, GDNativeInt p_max_write_length) {
- if constexpr (sizeof(wchar_t) == 4) {
- return gdnative_string_to_utf32_chars(p_self, (char32_t *)r_text, p_max_write_length);
- } else {
- return gdnative_string_to_utf16_chars(p_self, (char16_t *)r_text, p_max_write_length);
- }
-}
-
-static char32_t *gdnative_string_operator_index(GDNativeStringPtr p_self, GDNativeInt p_index) {
- String *self = (String *)p_self;
- ERR_FAIL_INDEX_V(p_index, self->length() + 1, nullptr);
- return &self->ptrw()[p_index];
-}
-
-static const char32_t *gdnative_string_operator_index_const(const GDNativeStringPtr p_self, GDNativeInt p_index) {
- const String *self = (const String *)p_self;
- ERR_FAIL_INDEX_V(p_index, self->length() + 1, nullptr);
- return &self->ptr()[p_index];
-}
-
-/* Packed array functions */
-
-static uint8_t *gdnative_packed_byte_array_operator_index(GDNativeTypePtr p_self, GDNativeInt p_index) {
- PackedByteArray *self = (PackedByteArray *)p_self;
- ERR_FAIL_INDEX_V(p_index, self->size(), nullptr);
- return &self->ptrw()[p_index];
-}
-
-static const uint8_t *gdnative_packed_byte_array_operator_index_const(const GDNativeTypePtr p_self, GDNativeInt p_index) {
- const PackedByteArray *self = (const PackedByteArray *)p_self;
- ERR_FAIL_INDEX_V(p_index, self->size(), nullptr);
- return &self->ptr()[p_index];
-}
-
-static GDNativeTypePtr gdnative_packed_color_array_operator_index(GDNativeTypePtr p_self, GDNativeInt p_index) {
- PackedColorArray *self = (PackedColorArray *)p_self;
- ERR_FAIL_INDEX_V(p_index, self->size(), nullptr);
- return (GDNativeTypePtr)&self->ptrw()[p_index];
-}
-
-static GDNativeTypePtr gdnative_packed_color_array_operator_index_const(const GDNativeTypePtr p_self, GDNativeInt p_index) {
- const PackedColorArray *self = (const PackedColorArray *)p_self;
- ERR_FAIL_INDEX_V(p_index, self->size(), nullptr);
- return (GDNativeTypePtr)&self->ptr()[p_index];
-}
-
-static float *gdnative_packed_float32_array_operator_index(GDNativeTypePtr p_self, GDNativeInt p_index) {
- PackedFloat32Array *self = (PackedFloat32Array *)p_self;
- ERR_FAIL_INDEX_V(p_index, self->size(), nullptr);
- return &self->ptrw()[p_index];
-}
-
-static const float *gdnative_packed_float32_array_operator_index_const(const GDNativeTypePtr p_self, GDNativeInt p_index) {
- const PackedFloat32Array *self = (const PackedFloat32Array *)p_self;
- ERR_FAIL_INDEX_V(p_index, self->size(), nullptr);
- return &self->ptr()[p_index];
-}
-
-static double *gdnative_packed_float64_array_operator_index(GDNativeTypePtr p_self, GDNativeInt p_index) {
- PackedFloat64Array *self = (PackedFloat64Array *)p_self;
- ERR_FAIL_INDEX_V(p_index, self->size(), nullptr);
- return &self->ptrw()[p_index];
-}
-
-static const double *gdnative_packed_float64_array_operator_index_const(const GDNativeTypePtr p_self, GDNativeInt p_index) {
- const PackedFloat64Array *self = (const PackedFloat64Array *)p_self;
- ERR_FAIL_INDEX_V(p_index, self->size(), nullptr);
- return &self->ptr()[p_index];
-}
-
-static int32_t *gdnative_packed_int32_array_operator_index(GDNativeTypePtr p_self, GDNativeInt p_index) {
- PackedInt32Array *self = (PackedInt32Array *)p_self;
- ERR_FAIL_INDEX_V(p_index, self->size(), nullptr);
- return &self->ptrw()[p_index];
-}
-
-static const int32_t *gdnative_packed_int32_array_operator_index_const(const GDNativeTypePtr p_self, GDNativeInt p_index) {
- const PackedInt32Array *self = (const PackedInt32Array *)p_self;
- ERR_FAIL_INDEX_V(p_index, self->size(), nullptr);
- return &self->ptr()[p_index];
-}
-
-static int64_t *gdnative_packed_int64_array_operator_index(GDNativeTypePtr p_self, GDNativeInt p_index) {
- PackedInt64Array *self = (PackedInt64Array *)p_self;
- ERR_FAIL_INDEX_V(p_index, self->size(), nullptr);
- return &self->ptrw()[p_index];
-}
-
-static const int64_t *gdnative_packed_int64_array_operator_index_const(const GDNativeTypePtr p_self, GDNativeInt p_index) {
- const PackedInt64Array *self = (const PackedInt64Array *)p_self;
- ERR_FAIL_INDEX_V(p_index, self->size(), nullptr);
- return &self->ptr()[p_index];
-}
-
-static GDNativeStringPtr gdnative_packed_string_array_operator_index(GDNativeTypePtr p_self, GDNativeInt p_index) {
- PackedStringArray *self = (PackedStringArray *)p_self;
- ERR_FAIL_INDEX_V(p_index, self->size(), nullptr);
- return (GDNativeStringPtr)&self->ptrw()[p_index];
-}
-
-static GDNativeStringPtr gdnative_packed_string_array_operator_index_const(const GDNativeTypePtr p_self, GDNativeInt p_index) {
- const PackedStringArray *self = (const PackedStringArray *)p_self;
- ERR_FAIL_INDEX_V(p_index, self->size(), nullptr);
- return (GDNativeStringPtr)&self->ptr()[p_index];
-}
-
-static GDNativeTypePtr gdnative_packed_vector2_array_operator_index(GDNativeTypePtr p_self, GDNativeInt p_index) {
- PackedVector2Array *self = (PackedVector2Array *)p_self;
- ERR_FAIL_INDEX_V(p_index, self->size(), nullptr);
- return (GDNativeTypePtr)&self->ptrw()[p_index];
-}
-
-static GDNativeTypePtr gdnative_packed_vector2_array_operator_index_const(const GDNativeTypePtr p_self, GDNativeInt p_index) {
- const PackedVector2Array *self = (const PackedVector2Array *)p_self;
- ERR_FAIL_INDEX_V(p_index, self->size(), nullptr);
- return (GDNativeTypePtr)&self->ptr()[p_index];
-}
-
-static GDNativeTypePtr gdnative_packed_vector3_array_operator_index(GDNativeTypePtr p_self, GDNativeInt p_index) {
- PackedVector3Array *self = (PackedVector3Array *)p_self;
- ERR_FAIL_INDEX_V(p_index, self->size(), nullptr);
- return (GDNativeTypePtr)&self->ptrw()[p_index];
-}
-
-static GDNativeTypePtr gdnative_packed_vector3_array_operator_index_const(const GDNativeTypePtr p_self, GDNativeInt p_index) {
- const PackedVector3Array *self = (const PackedVector3Array *)p_self;
- ERR_FAIL_INDEX_V(p_index, self->size(), nullptr);
- return (GDNativeTypePtr)&self->ptr()[p_index];
-}
-
-static GDNativeVariantPtr gdnative_array_operator_index(GDNativeTypePtr p_self, GDNativeInt p_index) {
- Array *self = (Array *)p_self;
- ERR_FAIL_INDEX_V(p_index, self->size(), nullptr);
- return (GDNativeVariantPtr)&self->operator[](p_index);
-}
-
-static GDNativeVariantPtr gdnative_array_operator_index_const(const GDNativeTypePtr p_self, GDNativeInt p_index) {
- const Array *self = (const Array *)p_self;
- ERR_FAIL_INDEX_V(p_index, self->size(), nullptr);
- return (GDNativeVariantPtr)&self->operator[](p_index);
-}
-
-/* Dictionary functions */
-
-static GDNativeVariantPtr gdnative_dictionary_operator_index(GDNativeTypePtr p_self, const GDNativeVariantPtr p_key) {
- Dictionary *self = (Dictionary *)p_self;
- return (GDNativeVariantPtr)&self->operator[](*(const Variant *)p_key);
-}
-
-static GDNativeVariantPtr gdnative_dictionary_operator_index_const(const GDNativeTypePtr p_self, const GDNativeVariantPtr p_key) {
- const Dictionary *self = (const Dictionary *)p_self;
- return (GDNativeVariantPtr)&self->operator[](*(const Variant *)p_key);
-}
-
-/* OBJECT API */
-
-static void gdnative_object_method_bind_call(const GDNativeMethodBindPtr p_method_bind, GDNativeObjectPtr p_instance, const GDNativeVariantPtr *p_args, GDNativeInt p_arg_count, GDNativeVariantPtr r_return, GDNativeCallError *r_error) {
- MethodBind *mb = (MethodBind *)p_method_bind;
- Object *o = (Object *)p_instance;
- const Variant **args = (const Variant **)p_args;
- Callable::CallError error;
-
- Variant ret = mb->call(o, args, p_arg_count, error);
- memnew_placement(r_return, Variant(ret));
-
- if (r_error) {
- r_error->error = (GDNativeCallErrorType)(error.error);
- r_error->argument = error.argument;
- r_error->expected = error.expected;
- }
-}
-
-static void gdnative_object_method_bind_ptrcall(const GDNativeMethodBindPtr p_method_bind, GDNativeObjectPtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr p_ret) {
- MethodBind *mb = (MethodBind *)p_method_bind;
- Object *o = (Object *)p_instance;
- mb->ptrcall(o, (const void **)p_args, p_ret);
-}
-
-static void gdnative_object_destroy(GDNativeObjectPtr p_o) {
- memdelete((Object *)p_o);
-}
-
-static GDNativeObjectPtr gdnative_global_get_singleton(const GDNativeStringNamePtr p_name) {
- const StringName name = *reinterpret_cast<const StringName *>(p_name);
- return (GDNativeObjectPtr)Engine::get_singleton()->get_singleton_object(name);
-}
-
-static void *gdnative_object_get_instance_binding(GDNativeObjectPtr p_object, void *p_token, const GDNativeInstanceBindingCallbacks *p_callbacks) {
- Object *o = (Object *)p_object;
- return o->get_instance_binding(p_token, p_callbacks);
-}
-
-static void gdnative_object_set_instance_binding(GDNativeObjectPtr p_object, void *p_token, void *p_binding, const GDNativeInstanceBindingCallbacks *p_callbacks) {
- Object *o = (Object *)p_object;
- o->set_instance_binding(p_token, p_binding, p_callbacks);
-}
-
-static void gdnative_object_set_instance(GDNativeObjectPtr p_object, const GDNativeStringNamePtr p_classname, GDExtensionClassInstancePtr p_instance) {
- const StringName classname = *reinterpret_cast<const StringName *>(p_classname);
- Object *o = (Object *)p_object;
- ClassDB::set_object_extension_instance(o, classname, p_instance);
-}
-
-static GDNativeObjectPtr gdnative_object_get_instance_from_id(GDObjectInstanceID p_instance_id) {
- return (GDNativeObjectPtr)ObjectDB::get_instance(ObjectID(p_instance_id));
-}
-
-static GDNativeObjectPtr gdnative_object_cast_to(const GDNativeObjectPtr p_object, void *p_class_tag) {
- if (!p_object) {
- return nullptr;
- }
- Object *o = (Object *)p_object;
-
- return o->is_class_ptr(p_class_tag) ? (GDNativeObjectPtr)o : (GDNativeObjectPtr) nullptr;
-}
-
-static GDObjectInstanceID gdnative_object_get_instance_id(const GDNativeObjectPtr p_object) {
- const Object *o = (const Object *)p_object;
- return (GDObjectInstanceID)o->get_instance_id();
-}
-
-static GDNativeScriptInstancePtr gdnative_script_instance_create(const GDNativeExtensionScriptInstanceInfo *p_info, GDNativeExtensionScriptInstanceDataPtr p_instance_data) {
- ScriptInstanceExtension *script_instance_extension = memnew(ScriptInstanceExtension);
- script_instance_extension->instance = p_instance_data;
- script_instance_extension->native_info = p_info;
- return reinterpret_cast<GDNativeScriptInstancePtr>(script_instance_extension);
-}
-
-static GDNativeMethodBindPtr gdnative_classdb_get_method_bind(const GDNativeStringNamePtr p_classname, const GDNativeStringNamePtr p_methodname, GDNativeInt p_hash) {
- const StringName classname = *reinterpret_cast<const StringName *>(p_classname);
- const StringName methodname = *reinterpret_cast<const StringName *>(p_methodname);
- MethodBind *mb = ClassDB::get_method(classname, methodname);
- ERR_FAIL_COND_V(!mb, nullptr);
- if (mb->get_hash() != p_hash) {
- ERR_PRINT("Hash mismatch for method '" + classname + "." + methodname + "'.");
- return nullptr;
- }
- return (GDNativeMethodBindPtr)mb;
-}
-
-static GDNativeObjectPtr gdnative_classdb_construct_object(const GDNativeStringNamePtr p_classname) {
- const StringName classname = *reinterpret_cast<const StringName *>(p_classname);
- return (GDNativeObjectPtr)ClassDB::instantiate(classname);
-}
-
-static void *gdnative_classdb_get_class_tag(const GDNativeStringNamePtr p_classname) {
- const StringName classname = *reinterpret_cast<const StringName *>(p_classname);
- ClassDB::ClassInfo *class_info = ClassDB::classes.getptr(classname);
- return class_info ? class_info->class_ptr : nullptr;
-}
-
-void gdnative_setup_interface(GDNativeInterface *p_interface) {
- GDNativeInterface &gdni = *p_interface;
-
- gdni.version_major = VERSION_MAJOR;
- gdni.version_minor = VERSION_MINOR;
-#if VERSION_PATCH
- gdni.version_patch = VERSION_PATCH;
-#else
- gdni.version_patch = 0;
-#endif
- gdni.version_string = VERSION_FULL_NAME;
-
- /* GODOT CORE */
-
- gdni.mem_alloc = gdnative_alloc;
- gdni.mem_realloc = gdnative_realloc;
- gdni.mem_free = gdnative_free;
-
- gdni.print_error = gdnative_print_error;
- gdni.print_warning = gdnative_print_warning;
- gdni.print_script_error = gdnative_print_script_error;
-
- gdni.get_native_struct_size = gdnative_get_native_struct_size;
-
- /* GODOT VARIANT */
-
- // variant general
- gdni.variant_new_copy = gdnative_variant_new_copy;
- gdni.variant_new_nil = gdnative_variant_new_nil;
- gdni.variant_destroy = gdnative_variant_destroy;
-
- gdni.variant_call = gdnative_variant_call;
- gdni.variant_call_static = gdnative_variant_call_static;
- gdni.variant_evaluate = gdnative_variant_evaluate;
- gdni.variant_set = gdnative_variant_set;
- gdni.variant_set_named = gdnative_variant_set_named;
- gdni.variant_set_keyed = gdnative_variant_set_keyed;
- gdni.variant_set_indexed = gdnative_variant_set_indexed;
- gdni.variant_get = gdnative_variant_get;
- gdni.variant_get_named = gdnative_variant_get_named;
- gdni.variant_get_keyed = gdnative_variant_get_keyed;
- gdni.variant_get_indexed = gdnative_variant_get_indexed;
- gdni.variant_iter_init = gdnative_variant_iter_init;
- gdni.variant_iter_next = gdnative_variant_iter_next;
- gdni.variant_iter_get = gdnative_variant_iter_get;
- gdni.variant_hash = gdnative_variant_hash;
- gdni.variant_recursive_hash = gdnative_variant_recursive_hash;
- gdni.variant_hash_compare = gdnative_variant_hash_compare;
- gdni.variant_booleanize = gdnative_variant_booleanize;
- gdni.variant_duplicate = gdnative_variant_duplicate;
- gdni.variant_stringify = gdnative_variant_stringify;
-
- gdni.variant_get_type = gdnative_variant_get_type;
- gdni.variant_has_method = gdnative_variant_has_method;
- gdni.variant_has_member = gdnative_variant_has_member;
- gdni.variant_has_key = gdnative_variant_has_key;
- gdni.variant_get_type_name = gdnative_variant_get_type_name;
- gdni.variant_can_convert = gdnative_variant_can_convert;
- gdni.variant_can_convert_strict = gdnative_variant_can_convert_strict;
-
- gdni.get_variant_from_type_constructor = gdnative_get_variant_from_type_constructor;
- gdni.get_variant_to_type_constructor = gdnative_get_type_from_variant_constructor;
-
- // ptrcalls.
-
- gdni.variant_get_ptr_operator_evaluator = gdnative_variant_get_ptr_operator_evaluator;
- gdni.variant_get_ptr_builtin_method = gdnative_variant_get_ptr_builtin_method;
- gdni.variant_get_ptr_constructor = gdnative_variant_get_ptr_constructor;
- gdni.variant_get_ptr_destructor = gdnative_variant_get_ptr_destructor;
- gdni.variant_construct = gdnative_variant_construct;
- gdni.variant_get_ptr_setter = gdnative_variant_get_ptr_setter;
- gdni.variant_get_ptr_getter = gdnative_variant_get_ptr_getter;
- gdni.variant_get_ptr_indexed_setter = gdnative_variant_get_ptr_indexed_setter;
- gdni.variant_get_ptr_indexed_getter = gdnative_variant_get_ptr_indexed_getter;
- gdni.variant_get_ptr_keyed_setter = gdnative_variant_get_ptr_keyed_setter;
- gdni.variant_get_ptr_keyed_getter = gdnative_variant_get_ptr_keyed_getter;
- gdni.variant_get_ptr_keyed_checker = gdnative_variant_get_ptr_keyed_checker;
- gdni.variant_get_constant_value = gdnative_variant_get_constant_value;
- gdni.variant_get_ptr_utility_function = gdnative_variant_get_ptr_utility_function;
-
- // extra utilities
-
- gdni.string_new_with_latin1_chars = gdnative_string_new_with_latin1_chars;
- gdni.string_new_with_utf8_chars = gdnative_string_new_with_utf8_chars;
- gdni.string_new_with_utf16_chars = gdnative_string_new_with_utf16_chars;
- gdni.string_new_with_utf32_chars = gdnative_string_new_with_utf32_chars;
- gdni.string_new_with_wide_chars = gdnative_string_new_with_wide_chars;
- gdni.string_new_with_latin1_chars_and_len = gdnative_string_new_with_latin1_chars_and_len;
- gdni.string_new_with_utf8_chars_and_len = gdnative_string_new_with_utf8_chars_and_len;
- gdni.string_new_with_utf16_chars_and_len = gdnative_string_new_with_utf16_chars_and_len;
- gdni.string_new_with_utf32_chars_and_len = gdnative_string_new_with_utf32_chars_and_len;
- gdni.string_new_with_wide_chars_and_len = gdnative_string_new_with_wide_chars_and_len;
- gdni.string_to_latin1_chars = gdnative_string_to_latin1_chars;
- gdni.string_to_utf8_chars = gdnative_string_to_utf8_chars;
- gdni.string_to_utf16_chars = gdnative_string_to_utf16_chars;
- gdni.string_to_utf32_chars = gdnative_string_to_utf32_chars;
- gdni.string_to_wide_chars = gdnative_string_to_wide_chars;
- gdni.string_operator_index = gdnative_string_operator_index;
- gdni.string_operator_index_const = gdnative_string_operator_index_const;
-
- /* Packed array functions */
-
- gdni.packed_byte_array_operator_index = gdnative_packed_byte_array_operator_index;
- gdni.packed_byte_array_operator_index_const = gdnative_packed_byte_array_operator_index_const;
-
- gdni.packed_color_array_operator_index = gdnative_packed_color_array_operator_index;
- gdni.packed_color_array_operator_index_const = gdnative_packed_color_array_operator_index_const;
-
- gdni.packed_float32_array_operator_index = gdnative_packed_float32_array_operator_index;
- gdni.packed_float32_array_operator_index_const = gdnative_packed_float32_array_operator_index_const;
- gdni.packed_float64_array_operator_index = gdnative_packed_float64_array_operator_index;
- gdni.packed_float64_array_operator_index_const = gdnative_packed_float64_array_operator_index_const;
-
- gdni.packed_int32_array_operator_index = gdnative_packed_int32_array_operator_index;
- gdni.packed_int32_array_operator_index_const = gdnative_packed_int32_array_operator_index_const;
- gdni.packed_int64_array_operator_index = gdnative_packed_int64_array_operator_index;
- gdni.packed_int64_array_operator_index_const = gdnative_packed_int64_array_operator_index_const;
-
- gdni.packed_string_array_operator_index = gdnative_packed_string_array_operator_index;
- gdni.packed_string_array_operator_index_const = gdnative_packed_string_array_operator_index_const;
-
- gdni.packed_vector2_array_operator_index = gdnative_packed_vector2_array_operator_index;
- gdni.packed_vector2_array_operator_index_const = gdnative_packed_vector2_array_operator_index_const;
- gdni.packed_vector3_array_operator_index = gdnative_packed_vector3_array_operator_index;
- gdni.packed_vector3_array_operator_index_const = gdnative_packed_vector3_array_operator_index_const;
-
- gdni.array_operator_index = gdnative_array_operator_index;
- gdni.array_operator_index_const = gdnative_array_operator_index_const;
-
- /* Dictionary functions */
-
- gdni.dictionary_operator_index = gdnative_dictionary_operator_index;
- gdni.dictionary_operator_index_const = gdnative_dictionary_operator_index_const;
-
- /* OBJECT */
-
- gdni.object_method_bind_call = gdnative_object_method_bind_call;
- gdni.object_method_bind_ptrcall = gdnative_object_method_bind_ptrcall;
- gdni.object_destroy = gdnative_object_destroy;
- gdni.global_get_singleton = gdnative_global_get_singleton;
- gdni.object_get_instance_binding = gdnative_object_get_instance_binding;
- gdni.object_set_instance_binding = gdnative_object_set_instance_binding;
- gdni.object_set_instance = gdnative_object_set_instance;
-
- gdni.object_cast_to = gdnative_object_cast_to;
- gdni.object_get_instance_from_id = gdnative_object_get_instance_from_id;
- gdni.object_get_instance_id = gdnative_object_get_instance_id;
-
- /* SCRIPT INSTANCE */
-
- gdni.script_instance_create = gdnative_script_instance_create;
-
- /* CLASSDB */
-
- gdni.classdb_construct_object = gdnative_classdb_construct_object;
- gdni.classdb_get_method_bind = gdnative_classdb_get_method_bind;
- gdni.classdb_get_class_tag = gdnative_classdb_get_class_tag;
-
- /* CLASSDB EXTENSION */
-
- //these are filled by implementation, since it will want to keep track of registered classes
- gdni.classdb_register_extension_class = nullptr;
- gdni.classdb_register_extension_class_method = nullptr;
- gdni.classdb_register_extension_class_integer_constant = nullptr;
- gdni.classdb_register_extension_class_property = nullptr;
- gdni.classdb_register_extension_class_property_group = nullptr;
- gdni.classdb_register_extension_class_property_subgroup = nullptr;
- gdni.classdb_register_extension_class_signal = nullptr;
- gdni.classdb_unregister_extension_class = nullptr;
-
- gdni.get_library_path = nullptr;
-}
diff --git a/core/extension/gdnative_interface.h b/core/extension/gdnative_interface.h
deleted file mode 100644
index 68eed5a161..0000000000
--- a/core/extension/gdnative_interface.h
+++ /dev/null
@@ -1,589 +0,0 @@
-/*************************************************************************/
-/* gdnative_interface.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 GDNATIVE_INTERFACE_H
-#define GDNATIVE_INTERFACE_H
-
-/* This is a C class header, you can copy it and use it directly in your own binders.
- * Together with the JSON file, you should be able to generate any binder.
- */
-
-#include <stddef.h>
-#include <stdint.h>
-#include <stdio.h>
-
-#ifndef __cplusplus
-typedef uint32_t char32_t;
-typedef uint16_t char16_t;
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* VARIANT TYPES */
-
-typedef enum {
- GDNATIVE_VARIANT_TYPE_NIL,
-
- /* atomic types */
- GDNATIVE_VARIANT_TYPE_BOOL,
- GDNATIVE_VARIANT_TYPE_INT,
- GDNATIVE_VARIANT_TYPE_FLOAT,
- GDNATIVE_VARIANT_TYPE_STRING,
-
- /* math types */
- GDNATIVE_VARIANT_TYPE_VECTOR2,
- GDNATIVE_VARIANT_TYPE_VECTOR2I,
- GDNATIVE_VARIANT_TYPE_RECT2,
- GDNATIVE_VARIANT_TYPE_RECT2I,
- 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,
- GDNATIVE_VARIANT_TYPE_STRING_NAME,
- GDNATIVE_VARIANT_TYPE_NODE_PATH,
- GDNATIVE_VARIANT_TYPE_RID,
- GDNATIVE_VARIANT_TYPE_OBJECT,
- GDNATIVE_VARIANT_TYPE_CALLABLE,
- GDNATIVE_VARIANT_TYPE_SIGNAL,
- GDNATIVE_VARIANT_TYPE_DICTIONARY,
- GDNATIVE_VARIANT_TYPE_ARRAY,
-
- /* typed arrays */
- GDNATIVE_VARIANT_TYPE_PACKED_BYTE_ARRAY,
- GDNATIVE_VARIANT_TYPE_PACKED_INT32_ARRAY,
- GDNATIVE_VARIANT_TYPE_PACKED_INT64_ARRAY,
- GDNATIVE_VARIANT_TYPE_PACKED_FLOAT32_ARRAY,
- GDNATIVE_VARIANT_TYPE_PACKED_FLOAT64_ARRAY,
- GDNATIVE_VARIANT_TYPE_PACKED_STRING_ARRAY,
- GDNATIVE_VARIANT_TYPE_PACKED_VECTOR2_ARRAY,
- GDNATIVE_VARIANT_TYPE_PACKED_VECTOR3_ARRAY,
- GDNATIVE_VARIANT_TYPE_PACKED_COLOR_ARRAY,
-
- GDNATIVE_VARIANT_TYPE_VARIANT_MAX
-} GDNativeVariantType;
-
-typedef enum {
- /* comparison */
- GDNATIVE_VARIANT_OP_EQUAL,
- GDNATIVE_VARIANT_OP_NOT_EQUAL,
- GDNATIVE_VARIANT_OP_LESS,
- GDNATIVE_VARIANT_OP_LESS_EQUAL,
- GDNATIVE_VARIANT_OP_GREATER,
- GDNATIVE_VARIANT_OP_GREATER_EQUAL,
- /* mathematic */
- GDNATIVE_VARIANT_OP_ADD,
- GDNATIVE_VARIANT_OP_SUBTRACT,
- GDNATIVE_VARIANT_OP_MULTIPLY,
- GDNATIVE_VARIANT_OP_DIVIDE,
- GDNATIVE_VARIANT_OP_NEGATE,
- GDNATIVE_VARIANT_OP_POSITIVE,
- GDNATIVE_VARIANT_OP_MODULE,
- GDNATIVE_VARIANT_OP_POWER,
- /* bitwise */
- GDNATIVE_VARIANT_OP_SHIFT_LEFT,
- GDNATIVE_VARIANT_OP_SHIFT_RIGHT,
- GDNATIVE_VARIANT_OP_BIT_AND,
- GDNATIVE_VARIANT_OP_BIT_OR,
- GDNATIVE_VARIANT_OP_BIT_XOR,
- GDNATIVE_VARIANT_OP_BIT_NEGATE,
- /* logic */
- GDNATIVE_VARIANT_OP_AND,
- GDNATIVE_VARIANT_OP_OR,
- GDNATIVE_VARIANT_OP_XOR,
- GDNATIVE_VARIANT_OP_NOT,
- /* containment */
- GDNATIVE_VARIANT_OP_IN,
- GDNATIVE_VARIANT_OP_MAX
-
-} GDNativeVariantOperator;
-
-typedef void *GDNativeVariantPtr;
-typedef void *GDNativeStringNamePtr;
-typedef void *GDNativeStringPtr;
-typedef void *GDNativeObjectPtr;
-typedef void *GDNativeTypePtr;
-typedef void *GDNativeExtensionPtr;
-typedef void *GDNativeMethodBindPtr;
-typedef int64_t GDNativeInt;
-typedef uint8_t GDNativeBool;
-typedef uint64_t GDObjectInstanceID;
-
-/* VARIANT DATA I/O */
-
-typedef enum {
- GDNATIVE_CALL_OK,
- GDNATIVE_CALL_ERROR_INVALID_METHOD,
- GDNATIVE_CALL_ERROR_INVALID_ARGUMENT, /* expected is variant type */
- GDNATIVE_CALL_ERROR_TOO_MANY_ARGUMENTS, /* expected is number of arguments */
- GDNATIVE_CALL_ERROR_TOO_FEW_ARGUMENTS, /* expected is number of arguments */
- GDNATIVE_CALL_ERROR_INSTANCE_IS_NULL,
- GDNATIVE_CALL_ERROR_METHOD_NOT_CONST, /* used for const call */
-} GDNativeCallErrorType;
-
-typedef struct {
- GDNativeCallErrorType error;
- int32_t argument;
- int32_t expected;
-} GDNativeCallError;
-
-typedef void (*GDNativeVariantFromTypeConstructorFunc)(GDNativeVariantPtr, GDNativeTypePtr);
-typedef void (*GDNativeTypeFromVariantConstructorFunc)(GDNativeTypePtr, GDNativeVariantPtr);
-typedef void (*GDNativePtrOperatorEvaluator)(const GDNativeTypePtr p_left, const GDNativeTypePtr p_right, GDNativeTypePtr r_result);
-typedef void (*GDNativePtrBuiltInMethod)(GDNativeTypePtr p_base, const GDNativeTypePtr *p_args, GDNativeTypePtr r_return, int p_argument_count);
-typedef void (*GDNativePtrConstructor)(GDNativeTypePtr p_base, const GDNativeTypePtr *p_args);
-typedef void (*GDNativePtrDestructor)(GDNativeTypePtr p_base);
-typedef void (*GDNativePtrSetter)(GDNativeTypePtr p_base, const GDNativeTypePtr p_value);
-typedef void (*GDNativePtrGetter)(const GDNativeTypePtr p_base, GDNativeTypePtr r_value);
-typedef void (*GDNativePtrIndexedSetter)(GDNativeTypePtr p_base, GDNativeInt p_index, const GDNativeTypePtr p_value);
-typedef void (*GDNativePtrIndexedGetter)(const GDNativeTypePtr p_base, GDNativeInt p_index, GDNativeTypePtr r_value);
-typedef void (*GDNativePtrKeyedSetter)(GDNativeTypePtr p_base, const GDNativeTypePtr p_key, const GDNativeTypePtr p_value);
-typedef void (*GDNativePtrKeyedGetter)(const GDNativeTypePtr p_base, const GDNativeTypePtr p_key, GDNativeTypePtr r_value);
-typedef uint32_t (*GDNativePtrKeyedChecker)(const GDNativeVariantPtr p_base, const GDNativeVariantPtr p_key);
-typedef void (*GDNativePtrUtilityFunction)(GDNativeTypePtr r_return, const GDNativeTypePtr *p_arguments, int p_argument_count);
-
-typedef GDNativeObjectPtr (*GDNativeClassConstructor)();
-
-typedef void *(*GDNativeInstanceBindingCreateCallback)(void *p_token, void *p_instance);
-typedef void (*GDNativeInstanceBindingFreeCallback)(void *p_token, void *p_instance, void *p_binding);
-typedef GDNativeBool (*GDNativeInstanceBindingReferenceCallback)(void *p_token, void *p_binding, GDNativeBool p_reference);
-
-typedef struct {
- GDNativeInstanceBindingCreateCallback create_callback;
- GDNativeInstanceBindingFreeCallback free_callback;
- GDNativeInstanceBindingReferenceCallback reference_callback;
-} GDNativeInstanceBindingCallbacks;
-
-/* EXTENSION CLASSES */
-
-typedef void *GDExtensionClassInstancePtr;
-
-typedef GDNativeBool (*GDNativeExtensionClassSet)(GDExtensionClassInstancePtr p_instance, const GDNativeStringNamePtr p_name, const GDNativeVariantPtr p_value);
-typedef GDNativeBool (*GDNativeExtensionClassGet)(GDExtensionClassInstancePtr p_instance, const GDNativeStringNamePtr p_name, GDNativeVariantPtr r_ret);
-typedef uint64_t (*GDNativeExtensionClassGetRID)(GDExtensionClassInstancePtr p_instance);
-
-typedef struct {
- GDNativeVariantType type;
- GDNativeStringNamePtr name;
- GDNativeStringNamePtr class_name;
- uint32_t hint; // Bitfield of `PropertyHint` (defined in `extension_api.json`)
- GDNativeStringPtr hint_string;
- uint32_t usage; // Bitfield of `PropertyUsageFlags` (defined in `extension_api.json`)
-} GDNativePropertyInfo;
-
-typedef struct {
- GDNativeStringNamePtr name;
- GDNativePropertyInfo return_value;
- uint32_t flags; // Bitfield of `GDNativeExtensionClassMethodFlags`
- int32_t id;
- GDNativePropertyInfo *arguments; // array of `argument_count` size
- uint32_t argument_count;
- GDNativeVariantPtr *default_arguments; // array of `default_argument_count` size
- uint32_t default_argument_count;
-} GDNativeMethodInfo;
-
-typedef const GDNativePropertyInfo *(*GDNativeExtensionClassGetPropertyList)(GDExtensionClassInstancePtr p_instance, uint32_t *r_count);
-typedef void (*GDNativeExtensionClassFreePropertyList)(GDExtensionClassInstancePtr p_instance, const GDNativePropertyInfo *p_list);
-typedef GDNativeBool (*GDNativeExtensionClassPropertyCanRevert)(GDExtensionClassInstancePtr p_instance, const GDNativeStringNamePtr p_name);
-typedef GDNativeBool (*GDNativeExtensionClassPropertyGetRevert)(GDExtensionClassInstancePtr p_instance, const GDNativeStringNamePtr p_name, GDNativeVariantPtr r_ret);
-typedef void (*GDNativeExtensionClassNotification)(GDExtensionClassInstancePtr p_instance, int32_t p_what);
-typedef void (*GDNativeExtensionClassToString)(GDExtensionClassInstancePtr p_instance, GDNativeBool *r_is_valid, GDNativeStringPtr p_out);
-typedef void (*GDNativeExtensionClassReference)(GDExtensionClassInstancePtr p_instance);
-typedef void (*GDNativeExtensionClassUnreference)(GDExtensionClassInstancePtr p_instance);
-typedef void (*GDNativeExtensionClassCallVirtual)(GDExtensionClassInstancePtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr r_ret);
-typedef GDNativeObjectPtr (*GDNativeExtensionClassCreateInstance)(void *p_userdata);
-typedef void (*GDNativeExtensionClassFreeInstance)(void *p_userdata, GDExtensionClassInstancePtr p_instance);
-typedef GDNativeExtensionClassCallVirtual (*GDNativeExtensionClassGetVirtual)(void *p_userdata, const GDNativeStringNamePtr p_name);
-
-typedef struct {
- GDNativeBool is_virtual;
- GDNativeBool is_abstract;
- GDNativeExtensionClassSet set_func;
- GDNativeExtensionClassGet get_func;
- GDNativeExtensionClassGetPropertyList get_property_list_func;
- GDNativeExtensionClassFreePropertyList free_property_list_func;
- GDNativeExtensionClassPropertyCanRevert property_can_revert_func;
- GDNativeExtensionClassPropertyGetRevert property_get_revert_func;
- GDNativeExtensionClassNotification notification_func;
- GDNativeExtensionClassToString to_string_func;
- GDNativeExtensionClassReference reference_func;
- GDNativeExtensionClassUnreference unreference_func;
- GDNativeExtensionClassCreateInstance create_instance_func; /* this one is mandatory */
- GDNativeExtensionClassFreeInstance free_instance_func; /* this one is mandatory */
- GDNativeExtensionClassGetVirtual get_virtual_func;
- GDNativeExtensionClassGetRID get_rid_func;
- void *class_userdata;
-} GDNativeExtensionClassCreationInfo;
-
-typedef void *GDNativeExtensionClassLibraryPtr;
-
-/* Method */
-
-typedef enum {
- GDNATIVE_EXTENSION_METHOD_FLAG_NORMAL = 1,
- GDNATIVE_EXTENSION_METHOD_FLAG_EDITOR = 2,
- 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;
-
-typedef enum {
- GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_NONE,
- GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_INT8,
- GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_INT16,
- GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_INT32,
- GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_INT64,
- GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_UINT8,
- GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_UINT16,
- GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_UINT32,
- GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_UINT64,
- GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_REAL_IS_FLOAT,
- GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_REAL_IS_DOUBLE
-} GDNativeExtensionClassMethodArgumentMetadata;
-
-typedef void (*GDNativeExtensionClassMethodCall)(void *method_userdata, GDExtensionClassInstancePtr p_instance, const GDNativeVariantPtr *p_args, const GDNativeInt p_argument_count, GDNativeVariantPtr r_return, GDNativeCallError *r_error);
-typedef void (*GDNativeExtensionClassMethodPtrCall)(void *method_userdata, GDExtensionClassInstancePtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr r_ret);
-
-typedef struct {
- GDNativeStringNamePtr name;
- void *method_userdata;
- GDNativeExtensionClassMethodCall call_func;
- GDNativeExtensionClassMethodPtrCall ptrcall_func;
- uint32_t method_flags; // Bitfield of `GDNativeExtensionClassMethodFlags`
- uint32_t argument_count;
- GDNativeBool has_return_value;
- GDNativePropertyInfo *return_value_info; // Ignored if `has_return_value` is false
- GDNativeExtensionClassMethodArgumentMetadata return_value_metadata; // Ignored if `has_return_value` is false
- /* name and hint information for the argument can be omitted in release builds. Class name should always be present if it applies. */
- GDNativePropertyInfo *aguments_info; // array of `argument_count` size
- GDNativeExtensionClassMethodArgumentMetadata *aguments_metadata; // array of `argument_count` size
- uint32_t default_argument_count;
- GDNativeVariantPtr *default_arguments; // array of `default_argument_count` size
-} GDNativeExtensionClassMethodInfo;
-
-/* SCRIPT INSTANCE EXTENSION */
-
-typedef void *GDNativeExtensionScriptInstanceDataPtr; // Pointer to custom ScriptInstance native implementation
-
-typedef GDNativeBool (*GDNativeExtensionScriptInstanceSet)(GDNativeExtensionScriptInstanceDataPtr p_instance, const GDNativeStringNamePtr p_name, const GDNativeVariantPtr p_value);
-typedef GDNativeBool (*GDNativeExtensionScriptInstanceGet)(GDNativeExtensionScriptInstanceDataPtr p_instance, const GDNativeStringNamePtr p_name, GDNativeVariantPtr r_ret);
-typedef const GDNativePropertyInfo *(*GDNativeExtensionScriptInstanceGetPropertyList)(GDNativeExtensionScriptInstanceDataPtr p_instance, uint32_t *r_count);
-typedef void (*GDNativeExtensionScriptInstanceFreePropertyList)(GDNativeExtensionScriptInstanceDataPtr p_instance, const GDNativePropertyInfo *p_list);
-
-typedef GDNativeBool (*GDNativeExtensionScriptInstancePropertyCanRevert)(GDNativeExtensionScriptInstanceDataPtr p_instance, const GDNativeStringNamePtr p_name);
-typedef GDNativeBool (*GDNativeExtensionScriptInstancePropertyGetRevert)(GDNativeExtensionScriptInstanceDataPtr p_instance, const GDNativeStringNamePtr p_name, GDNativeVariantPtr r_ret);
-
-typedef GDNativeObjectPtr (*GDNativeExtensionScriptInstanceGetOwner)(GDNativeExtensionScriptInstanceDataPtr p_instance);
-typedef void (*GDNativeExtensionScriptInstancePropertyStateAdd)(const GDNativeStringNamePtr p_name, const GDNativeVariantPtr p_value, void *p_userdata);
-typedef void (*GDNativeExtensionScriptInstanceGetPropertyState)(GDNativeExtensionScriptInstanceDataPtr p_instance, GDNativeExtensionScriptInstancePropertyStateAdd p_add_func, void *p_userdata);
-
-typedef const GDNativeMethodInfo *(*GDNativeExtensionScriptInstanceGetMethodList)(GDNativeExtensionScriptInstanceDataPtr p_instance, uint32_t *r_count);
-typedef void (*GDNativeExtensionScriptInstanceFreeMethodList)(GDNativeExtensionScriptInstanceDataPtr p_instance, const GDNativeMethodInfo *p_list);
-
-typedef GDNativeBool (*GDNativeExtensionScriptInstanceHasMethod)(GDNativeExtensionScriptInstanceDataPtr p_instance, const GDNativeStringNamePtr p_name);
-
-typedef void (*GDNativeExtensionScriptInstanceCall)(GDNativeExtensionScriptInstanceDataPtr p_self, const GDNativeStringNamePtr p_method, const GDNativeVariantPtr *p_args, const GDNativeInt p_argument_count, GDNativeVariantPtr r_return, GDNativeCallError *r_error);
-typedef void (*GDNativeExtensionScriptInstanceNotification)(GDNativeExtensionScriptInstanceDataPtr p_instance, int32_t p_what);
-typedef void (*GDNativeExtensionScriptInstanceToString)(GDNativeExtensionScriptInstanceDataPtr p_instance, GDNativeBool *r_is_valid, GDNativeStringPtr r_out);
-
-typedef void (*GDNativeExtensionScriptInstanceRefCountIncremented)(GDNativeExtensionScriptInstanceDataPtr p_instance);
-typedef GDNativeBool (*GDNativeExtensionScriptInstanceRefCountDecremented)(GDNativeExtensionScriptInstanceDataPtr p_instance);
-
-typedef GDNativeObjectPtr (*GDNativeExtensionScriptInstanceGetScript)(GDNativeExtensionScriptInstanceDataPtr p_instance);
-typedef GDNativeBool (*GDNativeExtensionScriptInstanceIsPlaceholder)(GDNativeExtensionScriptInstanceDataPtr p_instance);
-
-typedef void *GDNativeExtensionScriptLanguagePtr;
-
-typedef GDNativeExtensionScriptLanguagePtr (*GDNativeExtensionScriptInstanceGetLanguage)(GDNativeExtensionScriptInstanceDataPtr p_instance);
-
-typedef void (*GDNativeExtensionScriptInstanceFree)(GDNativeExtensionScriptInstanceDataPtr p_instance);
-
-typedef void *GDNativeScriptInstancePtr; // Pointer to ScriptInstance.
-
-typedef struct {
- GDNativeExtensionScriptInstanceSet set_func;
- GDNativeExtensionScriptInstanceGet get_func;
- GDNativeExtensionScriptInstanceGetPropertyList get_property_list_func;
- GDNativeExtensionScriptInstanceFreePropertyList free_property_list_func;
-
- GDNativeExtensionScriptInstancePropertyCanRevert property_can_revert_func;
- GDNativeExtensionScriptInstancePropertyGetRevert property_get_revert_func;
-
- GDNativeExtensionScriptInstanceGetOwner get_owner_func;
- GDNativeExtensionScriptInstanceGetPropertyState get_property_state_func;
-
- GDNativeExtensionScriptInstanceGetMethodList get_method_list_func;
- GDNativeExtensionScriptInstanceFreeMethodList free_method_list_func;
-
- GDNativeExtensionScriptInstanceHasMethod has_method_func;
-
- GDNativeExtensionScriptInstanceCall call_func;
- GDNativeExtensionScriptInstanceNotification notification_func;
-
- GDNativeExtensionScriptInstanceToString to_string_func;
-
- GDNativeExtensionScriptInstanceRefCountIncremented refcount_incremented_func;
- GDNativeExtensionScriptInstanceRefCountDecremented refcount_decremented_func;
-
- GDNativeExtensionScriptInstanceGetScript get_script_func;
-
- GDNativeExtensionScriptInstanceIsPlaceholder is_placeholder_func;
-
- GDNativeExtensionScriptInstanceSet set_fallback_func;
- GDNativeExtensionScriptInstanceGet get_fallback_func;
-
- GDNativeExtensionScriptInstanceGetLanguage get_language_func;
-
- GDNativeExtensionScriptInstanceFree free_func;
-
-} GDNativeExtensionScriptInstanceInfo;
-
-/* INTERFACE */
-
-typedef struct {
- uint32_t version_major;
- uint32_t version_minor;
- uint32_t version_patch;
- const char *version_string;
-
- /* GODOT CORE */
- void *(*mem_alloc)(size_t p_bytes);
- void *(*mem_realloc)(void *p_ptr, size_t p_bytes);
- void (*mem_free)(void *p_ptr);
-
- void (*print_error)(const char *p_description, const char *p_function, const char *p_file, int32_t p_line);
- void (*print_warning)(const char *p_description, const char *p_function, const char *p_file, int32_t p_line);
- void (*print_script_error)(const char *p_description, const char *p_function, const char *p_file, int32_t p_line);
-
- uint64_t (*get_native_struct_size)(const GDNativeStringNamePtr p_name);
-
- /* GODOT VARIANT */
-
- /* variant general */
- void (*variant_new_copy)(GDNativeVariantPtr r_dest, const GDNativeVariantPtr p_src);
- void (*variant_new_nil)(GDNativeVariantPtr r_dest);
- void (*variant_destroy)(GDNativeVariantPtr p_self);
-
- /* variant type */
- void (*variant_call)(GDNativeVariantPtr p_self, const GDNativeStringNamePtr p_method, const GDNativeVariantPtr *p_args, const GDNativeInt p_argument_count, GDNativeVariantPtr r_return, GDNativeCallError *r_error);
- void (*variant_call_static)(GDNativeVariantType p_type, const GDNativeStringNamePtr p_method, const GDNativeVariantPtr *p_args, const GDNativeInt p_argument_count, GDNativeVariantPtr r_return, GDNativeCallError *r_error);
- void (*variant_evaluate)(GDNativeVariantOperator p_op, const GDNativeVariantPtr p_a, const GDNativeVariantPtr p_b, GDNativeVariantPtr r_return, GDNativeBool *r_valid);
- void (*variant_set)(GDNativeVariantPtr p_self, const GDNativeVariantPtr p_key, const GDNativeVariantPtr p_value, GDNativeBool *r_valid);
- void (*variant_set_named)(GDNativeVariantPtr p_self, const GDNativeStringNamePtr p_key, const GDNativeVariantPtr p_value, GDNativeBool *r_valid);
- void (*variant_set_keyed)(GDNativeVariantPtr p_self, const GDNativeVariantPtr p_key, const GDNativeVariantPtr p_value, GDNativeBool *r_valid);
- void (*variant_set_indexed)(GDNativeVariantPtr p_self, GDNativeInt p_index, const GDNativeVariantPtr p_value, GDNativeBool *r_valid, GDNativeBool *r_oob);
- void (*variant_get)(const GDNativeVariantPtr p_self, const GDNativeVariantPtr p_key, GDNativeVariantPtr r_ret, GDNativeBool *r_valid);
- void (*variant_get_named)(const GDNativeVariantPtr p_self, const GDNativeStringNamePtr p_key, GDNativeVariantPtr r_ret, GDNativeBool *r_valid);
- void (*variant_get_keyed)(const GDNativeVariantPtr p_self, const GDNativeVariantPtr p_key, GDNativeVariantPtr r_ret, GDNativeBool *r_valid);
- void (*variant_get_indexed)(const GDNativeVariantPtr p_self, GDNativeInt p_index, GDNativeVariantPtr r_ret, GDNativeBool *r_valid, GDNativeBool *r_oob);
- GDNativeBool (*variant_iter_init)(const GDNativeVariantPtr p_self, GDNativeVariantPtr r_iter, GDNativeBool *r_valid);
- GDNativeBool (*variant_iter_next)(const GDNativeVariantPtr p_self, GDNativeVariantPtr r_iter, GDNativeBool *r_valid);
- void (*variant_iter_get)(const GDNativeVariantPtr p_self, GDNativeVariantPtr r_iter, GDNativeVariantPtr r_ret, GDNativeBool *r_valid);
- GDNativeInt (*variant_hash)(const GDNativeVariantPtr p_self);
- GDNativeInt (*variant_recursive_hash)(const GDNativeVariantPtr p_self, GDNativeInt p_recursion_count);
- GDNativeBool (*variant_hash_compare)(const GDNativeVariantPtr p_self, const GDNativeVariantPtr p_other);
- GDNativeBool (*variant_booleanize)(const GDNativeVariantPtr p_self);
- void (*variant_duplicate)(const GDNativeVariantPtr p_self, GDNativeVariantPtr r_ret, GDNativeBool p_deep);
- void (*variant_stringify)(const GDNativeVariantPtr p_self, GDNativeStringPtr r_ret);
-
- GDNativeVariantType (*variant_get_type)(const GDNativeVariantPtr p_self);
- GDNativeBool (*variant_has_method)(const GDNativeVariantPtr p_self, const GDNativeStringNamePtr p_method);
- GDNativeBool (*variant_has_member)(GDNativeVariantType p_type, const GDNativeStringNamePtr p_member);
- GDNativeBool (*variant_has_key)(const GDNativeVariantPtr p_self, const GDNativeVariantPtr p_key, GDNativeBool *r_valid);
- void (*variant_get_type_name)(GDNativeVariantType p_type, GDNativeStringPtr r_name);
- GDNativeBool (*variant_can_convert)(GDNativeVariantType p_from, GDNativeVariantType p_to);
- GDNativeBool (*variant_can_convert_strict)(GDNativeVariantType p_from, GDNativeVariantType p_to);
-
- /* ptrcalls */
- GDNativeVariantFromTypeConstructorFunc (*get_variant_from_type_constructor)(GDNativeVariantType p_type);
- GDNativeTypeFromVariantConstructorFunc (*get_variant_to_type_constructor)(GDNativeVariantType p_type);
- GDNativePtrOperatorEvaluator (*variant_get_ptr_operator_evaluator)(GDNativeVariantOperator p_operator, GDNativeVariantType p_type_a, GDNativeVariantType p_type_b);
- GDNativePtrBuiltInMethod (*variant_get_ptr_builtin_method)(GDNativeVariantType p_type, const GDNativeStringNamePtr p_method, GDNativeInt p_hash);
- GDNativePtrConstructor (*variant_get_ptr_constructor)(GDNativeVariantType p_type, int32_t p_constructor);
- GDNativePtrDestructor (*variant_get_ptr_destructor)(GDNativeVariantType p_type);
- void (*variant_construct)(GDNativeVariantType p_type, GDNativeVariantPtr p_base, const GDNativeVariantPtr *p_args, int32_t p_argument_count, GDNativeCallError *r_error);
- GDNativePtrSetter (*variant_get_ptr_setter)(GDNativeVariantType p_type, const GDNativeStringNamePtr p_member);
- GDNativePtrGetter (*variant_get_ptr_getter)(GDNativeVariantType p_type, const GDNativeStringNamePtr p_member);
- GDNativePtrIndexedSetter (*variant_get_ptr_indexed_setter)(GDNativeVariantType p_type);
- GDNativePtrIndexedGetter (*variant_get_ptr_indexed_getter)(GDNativeVariantType p_type);
- GDNativePtrKeyedSetter (*variant_get_ptr_keyed_setter)(GDNativeVariantType p_type);
- GDNativePtrKeyedGetter (*variant_get_ptr_keyed_getter)(GDNativeVariantType p_type);
- GDNativePtrKeyedChecker (*variant_get_ptr_keyed_checker)(GDNativeVariantType p_type);
- void (*variant_get_constant_value)(GDNativeVariantType p_type, const GDNativeStringNamePtr p_constant, GDNativeVariantPtr r_ret);
- GDNativePtrUtilityFunction (*variant_get_ptr_utility_function)(const GDNativeStringNamePtr p_function, GDNativeInt p_hash);
-
- /* extra utilities */
-
- void (*string_new_with_latin1_chars)(GDNativeStringPtr r_dest, const char *p_contents);
- void (*string_new_with_utf8_chars)(GDNativeStringPtr r_dest, const char *p_contents);
- void (*string_new_with_utf16_chars)(GDNativeStringPtr r_dest, const char16_t *p_contents);
- void (*string_new_with_utf32_chars)(GDNativeStringPtr r_dest, const char32_t *p_contents);
- void (*string_new_with_wide_chars)(GDNativeStringPtr r_dest, const wchar_t *p_contents);
- void (*string_new_with_latin1_chars_and_len)(GDNativeStringPtr r_dest, const char *p_contents, const GDNativeInt p_size);
- void (*string_new_with_utf8_chars_and_len)(GDNativeStringPtr r_dest, const char *p_contents, const GDNativeInt p_size);
- void (*string_new_with_utf16_chars_and_len)(GDNativeStringPtr r_dest, const char16_t *p_contents, const GDNativeInt p_size);
- void (*string_new_with_utf32_chars_and_len)(GDNativeStringPtr r_dest, const char32_t *p_contents, const GDNativeInt p_size);
- void (*string_new_with_wide_chars_and_len)(GDNativeStringPtr r_dest, const wchar_t *p_contents, const GDNativeInt p_size);
- /* Information about the following functions:
- * - The return value is the resulting encoded string length.
- * - The length returned is in characters, not in bytes. It also does not include a trailing zero.
- * - These functions also do not write trailing zero, If you need it, write it yourself at the position indicated by the length (and make sure to allocate it).
- * - Passing NULL in r_text means only the length is computed (again, without including trailing zero).
- * - p_max_write_length argument is in characters, not bytes. It will be ignored if r_text is NULL.
- * - p_max_write_length argument does not affect the return value, it's only to cap write length.
- */
- GDNativeInt (*string_to_latin1_chars)(const GDNativeStringPtr p_self, char *r_text, GDNativeInt p_max_write_length);
- GDNativeInt (*string_to_utf8_chars)(const GDNativeStringPtr p_self, char *r_text, GDNativeInt p_max_write_length);
- GDNativeInt (*string_to_utf16_chars)(const GDNativeStringPtr p_self, char16_t *r_text, GDNativeInt p_max_write_length);
- GDNativeInt (*string_to_utf32_chars)(const GDNativeStringPtr p_self, char32_t *r_text, GDNativeInt p_max_write_length);
- GDNativeInt (*string_to_wide_chars)(const GDNativeStringPtr p_self, wchar_t *r_text, GDNativeInt p_max_write_length);
- char32_t *(*string_operator_index)(GDNativeStringPtr p_self, GDNativeInt p_index);
- const char32_t *(*string_operator_index_const)(const GDNativeStringPtr p_self, GDNativeInt p_index);
-
- /* Packed array functions */
-
- uint8_t *(*packed_byte_array_operator_index)(GDNativeTypePtr p_self, GDNativeInt p_index); // p_self should be a PackedByteArray
- const uint8_t *(*packed_byte_array_operator_index_const)(const GDNativeTypePtr p_self, GDNativeInt p_index); // p_self should be a PackedByteArray
-
- GDNativeTypePtr (*packed_color_array_operator_index)(GDNativeTypePtr p_self, GDNativeInt p_index); // p_self should be a PackedColorArray, returns Color ptr
- GDNativeTypePtr (*packed_color_array_operator_index_const)(const GDNativeTypePtr p_self, GDNativeInt p_index); // p_self should be a PackedColorArray, returns Color ptr
-
- float *(*packed_float32_array_operator_index)(GDNativeTypePtr p_self, GDNativeInt p_index); // p_self should be a PackedFloat32Array
- const float *(*packed_float32_array_operator_index_const)(const GDNativeTypePtr p_self, GDNativeInt p_index); // p_self should be a PackedFloat32Array
- double *(*packed_float64_array_operator_index)(GDNativeTypePtr p_self, GDNativeInt p_index); // p_self should be a PackedFloat64Array
- const double *(*packed_float64_array_operator_index_const)(const GDNativeTypePtr p_self, GDNativeInt p_index); // p_self should be a PackedFloat64Array
-
- int32_t *(*packed_int32_array_operator_index)(GDNativeTypePtr p_self, GDNativeInt p_index); // p_self should be a PackedInt32Array
- const int32_t *(*packed_int32_array_operator_index_const)(const GDNativeTypePtr p_self, GDNativeInt p_index); // p_self should be a PackedInt32Array
- int64_t *(*packed_int64_array_operator_index)(GDNativeTypePtr p_self, GDNativeInt p_index); // p_self should be a PackedInt32Array
- const int64_t *(*packed_int64_array_operator_index_const)(const GDNativeTypePtr p_self, GDNativeInt p_index); // p_self should be a PackedInt32Array
-
- GDNativeStringPtr (*packed_string_array_operator_index)(GDNativeTypePtr p_self, GDNativeInt p_index); // p_self should be a PackedStringArray
- GDNativeStringPtr (*packed_string_array_operator_index_const)(const GDNativeTypePtr p_self, GDNativeInt p_index); // p_self should be a PackedStringArray
-
- GDNativeTypePtr (*packed_vector2_array_operator_index)(GDNativeTypePtr p_self, GDNativeInt p_index); // p_self should be a PackedVector2Array, returns Vector2 ptr
- GDNativeTypePtr (*packed_vector2_array_operator_index_const)(const GDNativeTypePtr p_self, GDNativeInt p_index); // p_self should be a PackedVector2Array, returns Vector2 ptr
- GDNativeTypePtr (*packed_vector3_array_operator_index)(GDNativeTypePtr p_self, GDNativeInt p_index); // p_self should be a PackedVector3Array, returns Vector3 ptr
- GDNativeTypePtr (*packed_vector3_array_operator_index_const)(const GDNativeTypePtr p_self, GDNativeInt p_index); // p_self should be a PackedVector3Array, returns Vector3 ptr
-
- GDNativeVariantPtr (*array_operator_index)(GDNativeTypePtr p_self, GDNativeInt p_index); // p_self should be an Array ptr
- GDNativeVariantPtr (*array_operator_index_const)(const GDNativeTypePtr p_self, GDNativeInt p_index); // p_self should be an Array ptr
-
- /* Dictionary functions */
-
- GDNativeVariantPtr (*dictionary_operator_index)(GDNativeTypePtr p_self, const GDNativeVariantPtr p_key); // p_self should be an Dictionary ptr
- GDNativeVariantPtr (*dictionary_operator_index_const)(const GDNativeTypePtr p_self, const GDNativeVariantPtr p_key); // p_self should be an Dictionary ptr
-
- /* OBJECT */
-
- void (*object_method_bind_call)(const GDNativeMethodBindPtr p_method_bind, GDNativeObjectPtr p_instance, const GDNativeVariantPtr *p_args, GDNativeInt p_arg_count, GDNativeVariantPtr r_ret, GDNativeCallError *r_error);
- void (*object_method_bind_ptrcall)(const GDNativeMethodBindPtr p_method_bind, GDNativeObjectPtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr r_ret);
- void (*object_destroy)(GDNativeObjectPtr p_o);
- GDNativeObjectPtr (*global_get_singleton)(const GDNativeStringNamePtr p_name);
-
- void *(*object_get_instance_binding)(GDNativeObjectPtr p_o, void *p_token, const GDNativeInstanceBindingCallbacks *p_callbacks);
- void (*object_set_instance_binding)(GDNativeObjectPtr p_o, void *p_token, void *p_binding, const GDNativeInstanceBindingCallbacks *p_callbacks);
-
- void (*object_set_instance)(GDNativeObjectPtr p_o, const GDNativeStringNamePtr p_classname, GDExtensionClassInstancePtr p_instance); /* p_classname should be a registered extension class and should extend the p_o object's class. */
-
- GDNativeObjectPtr (*object_cast_to)(const GDNativeObjectPtr p_object, void *p_class_tag);
- GDNativeObjectPtr (*object_get_instance_from_id)(GDObjectInstanceID p_instance_id);
- GDObjectInstanceID (*object_get_instance_id)(const GDNativeObjectPtr p_object);
-
- /* SCRIPT INSTANCE */
-
- GDNativeScriptInstancePtr (*script_instance_create)(const GDNativeExtensionScriptInstanceInfo *p_info, GDNativeExtensionScriptInstanceDataPtr p_instance_data);
-
- /* CLASSDB */
- GDNativeObjectPtr (*classdb_construct_object)(const GDNativeStringNamePtr p_classname); /* The passed class must be a built-in godot class, or an already-registered extension class. In both case, object_set_instance should be called to fully initialize the object. */
- GDNativeMethodBindPtr (*classdb_get_method_bind)(const GDNativeStringNamePtr p_classname, const GDNativeStringNamePtr p_methodname, GDNativeInt p_hash);
- void *(*classdb_get_class_tag)(const GDNativeStringNamePtr p_classname);
-
- /* CLASSDB EXTENSION */
-
- // Provided parameters for `classdb_register_extension_*` can be safely freed once the function returns
- void (*classdb_register_extension_class)(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativeStringNamePtr p_parent_class_name, const GDNativeExtensionClassCreationInfo *p_extension_funcs);
- void (*classdb_register_extension_class_method)(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativeExtensionClassMethodInfo *p_method_info);
- void (*classdb_register_extension_class_integer_constant)(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativeStringNamePtr p_enum_name, const GDNativeStringNamePtr p_constant_name, GDNativeInt p_constant_value, GDNativeBool p_is_bitfield);
- void (*classdb_register_extension_class_property)(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativePropertyInfo *p_info, const GDNativeStringNamePtr p_setter, const GDNativeStringNamePtr p_getter);
- void (*classdb_register_extension_class_property_group)(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativeStringPtr p_group_name, const GDNativeStringPtr p_prefix);
- void (*classdb_register_extension_class_property_subgroup)(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativeStringPtr p_subgroup_name, const GDNativeStringPtr p_prefix);
- void (*classdb_register_extension_class_signal)(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativeStringNamePtr p_signal_name, const GDNativePropertyInfo *p_argument_info, GDNativeInt p_argument_count);
- void (*classdb_unregister_extension_class)(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name); /* Unregistering a parent class before a class that inherits it will result in failure. Inheritors must be unregistered first. */
-
- void (*get_library_path)(const GDNativeExtensionClassLibraryPtr p_library, GDNativeStringPtr r_path);
-
-} GDNativeInterface;
-
-/* INITIALIZATION */
-
-typedef enum {
- GDNATIVE_INITIALIZATION_CORE,
- GDNATIVE_INITIALIZATION_SERVERS,
- GDNATIVE_INITIALIZATION_SCENE,
- GDNATIVE_INITIALIZATION_EDITOR,
- GDNATIVE_MAX_INITIALIZATION_LEVEL,
-} GDNativeInitializationLevel;
-
-typedef struct {
- /* Minimum initialization level required.
- * If Core or Servers, the extension needs editor or game restart to take effect */
- GDNativeInitializationLevel minimum_initialization_level;
- /* Up to the user to supply when initializing */
- void *userdata;
- /* This function will be called multiple times for each initialization level. */
- void (*initialize)(void *userdata, GDNativeInitializationLevel p_level);
- void (*deinitialize)(void *userdata, GDNativeInitializationLevel p_level);
-} GDNativeInitialization;
-
-/* Define a C function prototype that implements the function below and expose it to dlopen() (or similar).
- * It will be called on initialization. The name must be an unique one specified in the .gdextension config file.
- */
-
-typedef GDNativeBool (*GDNativeInitializationFunction)(const GDNativeInterface *p_interface, const GDNativeExtensionClassLibraryPtr p_library, GDNativeInitialization *r_initialization);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif // GDNATIVE_INTERFACE_H
diff --git a/core/extension/make_interface_dumper.py b/core/extension/make_interface_dumper.py
index cc85c728d5..a8af0e9ff6 100644
--- a/core/extension/make_interface_dumper.py
+++ b/core/extension/make_interface_dumper.py
@@ -6,17 +6,17 @@ def run(target, source, env):
g.write(
"""/* THIS FILE IS GENERATED DO NOT EDIT */
-#ifndef GDNATIVE_INTERFACE_DUMP_H
-#define GDNATIVE_INTERFACE_DUMP_H
+#ifndef GDEXTENSION_INTERFACE_DUMP_H
+#define GDEXTENSION_INTERFACE_DUMP_H
#ifdef TOOLS_ENABLED
#include "core/io/file_access.h"
#include "core/string/ustring.h"
-class GDNativeInterfaceDump {
+class GDExtensionInterfaceDump {
private:
- static constexpr char const *gdnative_interface_dump ="""
+ static constexpr char const *gdextension_interface_dump ="""
)
for line in f:
g.write('"' + line.rstrip().replace('"', '\\"') + '\\n"\n')
@@ -25,16 +25,16 @@ class GDNativeInterfaceDump {
g.write(
"""
public:
- static void generate_gdnative_interface_file(const String &p_path) {
+ static void generate_gdextension_interface_file(const String &p_path) {
Ref<FileAccess> fa = FileAccess::open(p_path, FileAccess::WRITE);
- CharString cs(gdnative_interface_dump);
+ CharString cs(gdextension_interface_dump);
fa->store_buffer((const uint8_t *)cs.ptr(), cs.length());
};
};
#endif // TOOLS_ENABLED
-#endif // GDNATIVE_INTERFACE_DUMP_H
+#endif // GDEXTENSION_INTERFACE_DUMP_H
"""
)
g.close()
diff --git a/core/input/gamecontrollerdb.txt b/core/input/gamecontrollerdb.txt
index 774d1be6b5..dcb6aefb00 100644
--- a/core/input/gamecontrollerdb.txt
+++ b/core/input/gamecontrollerdb.txt
@@ -67,9 +67,11 @@
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,
03000000c82d00000121000000000000,8BitDo SN30 Pro for Android,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,
-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,
-03000000c82d00001330000000000000,8BitDo Ultimate Wireless,a:b0,b:b1,x:b3,y:b4,back:b10,guide:b12,start:b11,leftstick:b13,rightstick:b14,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:b8,righttrigger:b9,paddle1:b23,paddle2:b19,platform:Windows,
+03000000c82d00000260000000000000,8BitDo SN30 Pro Plus,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 Plus,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,
+03000000c82d00001130000000000000,8BitDo Ultimate Wired,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,
+03000000c82d00001230000000000000,8BitDo Ultimate Wireless,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,
+03000000c82d00001330000000000000,8BitDo Ultimate Wireless,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:b26,paddle1:b23,paddle2:b19,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,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,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,
@@ -201,6 +203,7 @@
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,
03000000ac0500004d04000000000000,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:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
+03000000ac0500001a06000000000000,GameSir-T3 2.02,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:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
030000004c0e00001035000000000000,Gamester,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,
030000000d0f00001110000000000000,GameStick Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows,
0300000047530000616d000000000000,GameStop,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,
@@ -296,7 +299,8 @@
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,
+03000000242e00000b20000000000000,Hyperkin Admiral N64 Controller,+rightx:b11,+righty:b13,-rightx:b8,-righty:b12,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b14,leftx:a0,lefty:a1,rightshoulder:b5,start:b9,platform:Windows,
+03000000242e0000ff0b000000000000,Hyperkin N64 Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a2,righty:a3,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,
@@ -369,6 +373,7 @@
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,
+030000008f0e00001330000000000000,Mayflash Controller Adapter,a:b1,b:b2,back:b8,dpdown:h0.8,dpleft:h0.2,dpright:h0.1,dpup:h0.4,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a3~,righty:a2,start:b9,x:b0,y:b3,platform:Windows,
03000000242f00003700000000000000,Mayflash F101,a:b1,b:b2,back:b8,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,
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,
@@ -377,8 +382,9 @@
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,
+03000000790000007918000000000000,Mayflash N64 Controller Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b9,leftx:a0,lefty:a1,righttrigger:b7,rightx:a3,righty:a2,start:b8,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 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,
+0300000025090000e803000000000000,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: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,
@@ -443,6 +449,7 @@
030000006f0e00008501000000000000,PDP Fightpad Pro,a:b2,b:b3,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:b1,y:b0,platform:Windows,
030000006f0e00000901000000000000,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:Windows,
030000008f0e00004100000000000000,PlaySega,a:b1,b:b0,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b2,start:b8,x:b4,y:b3,platform:Windows,
+03000000666600006706000000000000,PlayStation Adapter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a2,righty:a3,start:b11,x:b3,y:b0,platform:Windows,
03000000e30500009605000000000000,PlayStation 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:Windows,
030000004c050000da0c000000000000,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:Windows,
03000000632500002306000000000000,PlayStation 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:a3,start:b11,x:b3,y:b4,platform:Windows,
@@ -464,7 +471,6 @@
03000000250900000088000000000000,PS2 Controller,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,
03000000250900006888000000000000,PS2 Controller,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b6,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows,
03000000250900008888000000000000,PS2 Controller,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,
-03000000666600006706000000000000,PS2 Controller,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a2,righty:a3,start:b11,x:b3,y:b0,platform:Windows,
030000006b1400000303000000000000,PS2 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:Windows,
030000009d0d00001330000000000000,PS2 Controller,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:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
03000000151a00006222000000000000,PS2 Dual Plus 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,
@@ -505,7 +511,8 @@
030000004c050000a00b000000000000,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:Windows,
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,touchpad:b13,x:b0,y:b3,platform:Windows,
030000004c050000cc09000000000000,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:Windows,
-030000004c050000e60c000000000000,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:Windows,
+030000004c050000e60c000000000000,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,misc1:b14,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows,
+030000004c050000f20d000000000000,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,misc1:b14,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows,
03000000830500005020000000000000,PSX,a:b0,b:b1,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:a3,start:b11,x:b2,y:b3,platform:Windows,
03000000300f00000111000000000000,Qanba 2,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,
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,
@@ -554,6 +561,7 @@
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,
+03000000341200000400000000000000,RetroUSB N64 RetroPort,+rightx:b8,+righty:b10,-rightx:b9,-righty:b11,a:b7,b:b6,dpdown:b2,dpleft:b1,dpright:b0,dpup:b3,leftshoulder:b13,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b12,start: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,
@@ -741,9 +749,8 @@
03000000450c00002043000000000000,Xeox SL6556BK,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,
030000006f0e00000300000000000000,XGear,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:a5,righty:a2,start:b9,x:b3,y:b0,platform:Windows,
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,
-03000000bc2000005060000000000000,Xiaomi XMGP01YM,a:b0,b:b1,x:b3,y:b4,back:b10,guide:b12,start:b11,leftstick:b13,rightstick:b14,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,-lefty:-a1,+lefty:+a2,rightx:a3,-righty:-a4,+righty:+a5,lefttrigger:b8,righttrigger:b9,platform:Windows,
-03000000172700003350000000000000,Xiaomi XMGP01YM,a:b0,b:b1,x:b3,y:b4,back:b10,guide:b12,start:b11,leftstick:b13,rightstick:b14,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,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,
+03000000172700003350000000000000,Xiaomi XMGP01YM,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
+03000000bc2000005060000000000000,Xiaomi XMGP01YM,+lefty:+a2,+righty:+a5,-lefty:-a1,-righty:-a4,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,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,start:b11,x:b3,y:b4,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,
@@ -789,8 +796,11 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
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,
-03000000c82d00000260000001000000,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,
-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,
+03000000c82d00000260000001000000,8BitDo SN30 Pro Plus,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,
+03000000c82d00000261000000010000,8BitDo SN30 Pro Plus,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,
+03000000c82d00001130000000020000,8BitDo Ultimate Wired,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,
+03000000c82d00001330000001000000,8BitDo Ultimate Wireless,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:b26,paddle1:b23,paddle2:b19,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
+03000000c82d00001330000000020000,8BitDo Ultimate 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,misc1:b26,paddle1:b23,paddle2:b19,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,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,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X,
@@ -817,10 +827,12 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
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,
+03000000ac0500001a06000002020000,GameSir-T3 2.02,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: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,
03000000ad1b000001f9000000000000,Gamestop BB070 X360 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,
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,
+03000000ff1100003133000007010000,GameWare PC Control Pad,a:b2,b:b1,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:a4,start:b11,x:b3,y:b0,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,
@@ -836,11 +848,12 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
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,
+030000000d0f0000aa00000072050000,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: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,
+03000000242e0000ff0b000000010000,Hyperkin N64 Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a2,righty:a3,start:b9,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,
@@ -858,10 +871,11 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
030000006d0400001fc2000000000000,Logitech F710,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,
030000006d04000018c2000000010000,Logitech RumblePad 2,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:Mac OS X,
03000000380700005032000000010000,Mad Catz PS3 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: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,
-03000000380700008433000000010000,Mad Catz PS3 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: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,
+03000000380700008433000000010000,Mad Catz PS3 Fightstick TE S Plus,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,
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,
+03000000380700008483000000010000,Mad Catz PS4 Fightstick TE S Plus,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,
+030000008f0e00001330000011010000,Mayflash Controller Adapter,a:b2,b:b4,back:b16,dpdown:h0.8,dpleft:h0.2,dpright:h0.1,dpup:h0.4,leftshoulder:b12,lefttrigger:b16,leftx:a0,lefty:a2,rightshoulder:b14,rightx:a6~,righty:a4,start:b18,x:b0,y:b6,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,
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,
@@ -886,8 +900,10 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
030000007e0500001920000001000000,NSO N64 Controller,+rightx:b8,+righty:b7,-rightx:b3,-righty:b2,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,righttrigger:b10,start:b9,platform:Mac OS X,
030000007e0500001720000001000000,NSO SNES Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b15,start:b9,x:b2,y:b3,platform:Mac OS X,
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,
+030000004b120000014d000000010000,Nyko Airflo EX,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:a3,righty:a2,start:b9,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,
+03000000666600006706000088020000,PlayStation Adapter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b11,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,
@@ -899,8 +915,10 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
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,
+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,misc1:b14,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X,
+030000004c050000f20d000000010000,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,misc1:b14,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,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,
+050000004c050000f20d000000010000,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,
@@ -919,6 +937,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
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,
03000000790000001100000006010000,Retrolink SNES Controller,a:b2,b:b1,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Mac OS X,
+03000000341200000400000000000000,RetroUSB N64 RetroPort,+rightx:b8,+righty:b10,-rightx:b9,-righty:b11,a:b7,b:b6,dpdown:b2,dpleft:b1,dpright:b0,dpup:b3,leftshoulder:b13,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b12,start:b4,platform:Mac OS X,
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,
@@ -937,14 +956,13 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
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,
+03000000790000001c18000003100000,TGZ Controller,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: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,
@@ -954,6 +972,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
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,
+03000000632500002605000000010000,Uberwith Controller,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: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,
050000005769696d6f74652028303000,Wii Remote,a:b4,b:b5,back:b7,dpdown:b3,dpleft:b0,dpright:b1,dpup:b2,guide:b8,leftshoulder:b11,lefttrigger:b12,leftx:a0,lefty:a1,start:b6,x:b10,y:b9,platform:Mac OS X,
@@ -965,6 +984,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
030000005e040000050b000003090000,Xbox Elite Controller Series 2,a:b0,b:b1,back:b31,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b53,leftshoulder:b6,leftstick:b13,lefttrigger:a6,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
030000005e040000130b000011050000,Xbox One 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,
030000005e040000200b000011050000,Xbox One 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,
+030000005e040000200b000013050000,Xbox One 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,
030000005e040000d102000000000000,Xbox One 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,
030000005e040000dd02000000000000,Xbox One 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,
030000005e040000e002000000000000,Xbox One 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:Mac OS X,
@@ -975,8 +995,9 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000c62400003a54000000000000,Xbox One PowerA 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,
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,
+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,misc1:b15,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,
+030000005e040000130b000015050000,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,
@@ -1008,6 +1029,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
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,
+03000000c82d00001030000011010000,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,
@@ -1028,9 +1050,13 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000c82d00001290000011010000,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,
05000000c82d00000161000000010000,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:Linux,
05000000c82d00006228000000010000,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,
-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,
+03000000c82d00000260000011010000,8BitDo SN30 Pro Plus,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 Plus,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,
+03000000c82d00001130000011010000,8BitDo Ultimate Wired,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,
+03000000c82d00000760000011010000,8BitDo Ultimate Wireless,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:Linux,
+03000000c82d00001230000011010000,8BitDo Ultimate Wireless,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,
+03000000c82d00001330000011010000,8BitDo Ultimate Wireless,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:b26,paddle1:b23,paddle2:b19,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,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,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux,
@@ -1069,10 +1095,10 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
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,
03000000c31100000791000011010000,Be1 GC101 Controller 1.03,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,
030000005e0400008e02000003030000,Be1 GC101 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,
+03000000bc2000004d50000011010000,BEITONG A1T2 BFM,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:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
05000000bc2000000055000001000000,BETOP AX1 BFM,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:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
03000000bc2000006412000011010000,Betop Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b30,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,
030000006b1400000209000011010000,Bigben,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,
-03000000666600006706000000010000,Boom PSX to PC Converter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a2,righty:a3,start:b11,x:b3,y:b0,platform:Linux,
03000000120c0000200e000011010000,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:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,
03000000120c0000210e000011010000,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:Linux,
03000000120c0000f70e000011010000,Brook Universal Fighting Board,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,
@@ -1090,6 +1116,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
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,
+19000000030000000300000002030000,GameForce Controller,a:b1,b:b0,back:b8,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,guide:b16,leftshoulder:b4,leftstick:b14,lefttrigger:b6,leftx:a1,lefty:a0,rightshoulder:b5,rightstick:b15,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Linux,
03000000ac0500005b05000010010000,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:Linux,
03000000bc2000000055000011010000,GameSir G3w,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,
03000000558500001b06000010010000,GameSir G4 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:a3,start:b11,x:b3,y:b4,platform:Linux,
@@ -1099,6 +1126,9 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
030000006f0e00000104000000010000,Gamestop Logic3 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,
030000008f0e00000800000010010000,Gasia PlayStation 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,
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,
+190000004b4800000010000000010000,GO-Advance Controller,a:b1,b:b0,back:b10,dpdown:b7,dpleft:b8,dpright:b9,dpup:b6,leftshoulder:b4,lefttrigger:b12,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b13,start:b15,x:b2,y:b3,platform:Linux,
+190000004b4800000010000001010000,GO-Advance Controller,a:b1,b:b0,back:b12,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,leftshoulder:b4,leftstick:b13,lefttrigger:b14,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b16,righttrigger:b15,start:b17,x:b2,y:b3,platform:Linux,
+190000004b4800000011000000010000,GO-Super Controller,a:b1,b:b0,back:b12,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b16,leftshoulder:b4,leftstick:b14,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b15,righttrigger:b7,rightx:a2,righty:a3,start:b13,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,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,
@@ -1113,6 +1143,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
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,
+030000000d0f00008400000011010000,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:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,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,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,
@@ -1139,7 +1170,8 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
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,
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,
+05000000242e00000b20000001000000,Hyperkin Admiral N64 Controller,+rightx:b11,+righty:b13,-rightx:b8,-righty:b12,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b14,leftx:a0,lefty:a1,rightshoulder:b5,start:b9,platform:Linux,
+03000000242e0000ff0b000011010000,Hyperkin N64 Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a2,righty:a3,start:b9,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,
@@ -1191,6 +1223,7 @@ 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,
+030000008f0e00001330000010010000,Mayflash Controller Adapter,a:b1,b:b2,back:b8,dpdown:h0.8,dpleft:h0.2,dpright:h0.1,dpup:h0.4,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a3~,righty:a2,start:b9,x:b0,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,
@@ -1240,6 +1273,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
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,
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,
+030000009b2800008000000020020000,Nintendo Classic Controller,a:b1,b:b4,back:b2,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,leftshoulder:b6,rightshoulder:b7,start:b3,x:b0,y:b5,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,
060000007e0500000620000000000000,Nintendo Switch Combined Joy-Cons,a:b0,b:b1,back:b9,dpdown:b15,dpleft:b16,dpright:b17,dpup:b14,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,
@@ -1268,7 +1302,6 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
05000000362800000100000003010000,OUYA Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,platform:Linux,
05000000362800000100000004010000,OUYA Controller,a:b0,b:b3,back:b14,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,leftshoulder:b4,leftstick:b6,lefttrigger:b12,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:b13,rightx:a3,righty:a4,start:b16,x:b1,y:b2,platform:Linux,
03000000830500005020000010010000,Padix Rockfire PlayStation Bridge,a:b0,b:b1,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:a3,start:b11,x:b2,y:b3,platform:Linux,
-03000000790000001c18000011010000,PC 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,
03000000ff1100003133000010010000,PC 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,
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,
@@ -1283,6 +1316,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
030000006f0e00000901000011010000,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:Linux,
030000006f0e0000a802000023020000,PDP Xbox One 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:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
030000006f0e0000a702000023020000,PDP Xbox One Raven Black,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,
+03000000666600006706000000010000,PlayStation Adapter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a2,righty:a3,start:b11,x:b3,y:b0,platform:Linux,
030000004c050000da0c000011010000,PlayStation 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,
03000000d9040000160f000000010000,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:Linux,
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,
@@ -1326,10 +1360,12 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
050000004c050000cc09000000010000,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:Linux,
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,
+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,misc1:b14,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,
+030000004c050000f20d000011010000,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,misc1:b14,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,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,
+050000004c050000f20d000000010000,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,
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,
@@ -1341,7 +1377,6 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
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,
030000009b2800006000000001010000,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,
030000008916000001fd000024010000,Razer Onza Classic Edition,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,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,
-030000008916000000fd000024010000,Razer Onza Tournament Edition,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,
03000000321500000204000011010000,Razer Panthera 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,
03000000321500000104000011010000,Razer Panthera 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,
03000000321500000810000011010000,Razer Panthera PS4 Evo Arcade Stick,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:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,
@@ -1356,9 +1391,11 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
050000003215000000090000163a0000,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:Linux,
0300000032150000030a000001010000,Razer Wildcat,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,
03000000790000001100000010010000,Retro Controller,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b4,righttrigger:b5,start:b9,x:b0,y:b3,platform:Linux,
+190000004b4800000111000000010000,RetroGame Joypad,a:b1,b:b0,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,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,
0300000081170000990a000001010000,Retronic Adapter,a:b0,leftx:a0,lefty:a1,platform:Linux,
0300000000f000000300000000010000,RetroPad,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Linux,
00000000526574726f53746f6e653200,RetroStone 2 Controller,a:b1,b:b0,back:b10,dpdown:b15,dpleft:b16,dpright:b17,dpup:b14,leftshoulder:b6,lefttrigger:b8,rightshoulder:b7,righttrigger:b9,start:b11,x:b4,y:b3,platform:Linux,
+03000000341200000400000000010000,RetroUSB N64 RetroPort,+rightx:b8,+righty:b10,-rightx:b9,-righty:b11,a:b7,b:b6,dpdown:b2,dpleft:b1,dpright:b0,dpup:b3,leftshoulder:b13,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b12,start:b4,platform:Linux,
030000006b140000010d000011010000,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:Linux,
030000006b140000130d000011010000,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:Linux,
030000006f0e00001f01000000010000,Rock Candy,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,
@@ -1414,9 +1451,11 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
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,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,
+03000000457500000401000011010000,SZMY Power DS4 Wired 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,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,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,
03000000ba2200000701000001010000,Technology Innovation PS2 Adapter,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:a5,righty:a2,start:b9,x:b3,y:b2,platform:Linux,
+03000000790000001c18000011010000,TGZ 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:a3,start:b11,x:b3,y:b4,platform:Linux,
030000004f04000015b3000001010000,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:Linux,
030000004f04000015b3000010010000,Thrustmaster Dual Analog 4,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,
030000004f04000020b3000010010000,Thrustmaster Dual Trigger,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,
@@ -1449,6 +1488,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
030000006f0e00000302000011010000,Victrix Pro Fightstick 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:Linux,
030000006f0e00000702000011010000,Victrix Pro Fightstick 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,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,
05000000ac0500003232000001000000,VR Box Controller,a:b0,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:b2,y:b3,platform:Linux,
+05000000434f4d4d414e440000000000,VX Gaming Command Series,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,
0000000058626f782033363020576900,Xbox 360 Controller,a:b0,b:b1,back:b14,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,guide:b7,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Linux,
030000005e0400001907000000010000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,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,
030000005e0400008e02000010010000,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,
@@ -1486,8 +1526,8 @@ 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,
030000005e040000120b000007050000,Xbox Series X 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,misc1:b11,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+050000005e040000130b000007050000,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,
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,
-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,
050000005e040000200b000013050000,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,
@@ -1551,13 +1591,13 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
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,
+05000000c82d000002600000ffff0f00,8BitDo SN30 Pro Plus,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,
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,
38303232393133383836366330346462,8BitDo SN30 Pro Plus,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,
38346630346135363335366265656666,8BitDo SN30 Pro Plus,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,
38426974446f20534e33302050726f2b,8BitDo SN30 Pro Plus,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,
536f6e7920436f6d707574657220456e,8BitDo SN30 Pro Plus,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,
66306331643531333230306437353936,8BitDo SN30 Pro Plus,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,
-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,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,rightshoulder:b10,start:b6,x:b2,y:b3,platform:Android,
@@ -1580,7 +1620,6 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
34323662653333636330306631326233,Google Nexus,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,
35383633353935396534393230616564,Google Stadia Controller,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,
05000000d6020000e5890000dfff3f00,GPD XD Plus,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Android,
-0500000031366332860c44aadfff0f00,GS Gamepad,a:b0,b:b1,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:b2,y:b3,platform:Android,
66633030656131663837396562323935,Hori Battle,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Android,
35623466343433653739346434636330,Hori Fighting Commander 3 Pro,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android,
484f524920434f2e2c4c54442e203130,Hori Fighting Commander 3 Pro,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b20,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b3,righttrigger:b9,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android,
@@ -1588,6 +1627,10 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
65656436646661313232656661616130,Hori PC Engine Mini Controller,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b18,platform:Android,
31303433326562636431653534636633,Hori Real Arcade Pro 3,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android,
30306539356238653637313730656134,HORIPAD Switch Pro Controller,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,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,
+48797065726b696e2050616400000000,Hyperkin Admiral N64 Controller,+rightx:b6,+righty:b7,-rightx:b17,-righty:b5,a:b1,b:b0,leftshoulder:b3,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b20,start:b18,platform:Android,
+62333331353131353034386136626636,Hyperkin Admiral N64 Controller,+rightx:b6,+righty:b7,-rightx:b17,-righty:b5,a:b1,b:b0,leftshoulder:b3,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b20,start:b18,platform:Android,
+31306635363562663834633739396333,Hyperkin N64 Adapter,a:b1,b:b19,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightx:a2,righty:a3,start:b18,platform:Android,
+5368616e57616e202020202048797065,Hyperkin N64 Adapter,a:b1,b:b19,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightx:a2,righty:a3,start:b18,platform:Android,
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,
@@ -1604,6 +1647,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
35623364393661626231343866613337,Logitech F710,a:b0,b:b1,back:b4,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,
4c6f6769746563682047616d65706164,Logitech F710,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,
64396331333230326333313330336533,Logitech F710,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,
+39653365373864633935383236363438,Logitech G Cloud,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,
416d617a6f6e2047616d6520436f6e74,Luna 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:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Android,
4c756e612047616d6570616400000000,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,start:b6,x:b2,y:b3,platform:Android,
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,
@@ -1642,6 +1686,8 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
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,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,lefttrigger:b3,rightshoulder:b10,righttrigger:b20,start:b18,x:b2,y:b0,platform:Android,
+536f6e7920496e746572616374697665,PlayStation 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,misc1:b8,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+576972656c65737320436f6e74726f6c,PlayStation 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,
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,
@@ -1661,20 +1707,21 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
34613139376634626133336530386430,PS4 Controller,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,
35643031303033326130316330353564,PS4 Controller,a:b1,b:b17,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,
37626233336235343937333961353732,PS4 Controller,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,
+37626464343430636562316661643863,PS4 Controller,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,
38393161636261653636653532386639,PS4 Controller,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,
-536f6e7920496e746572616374697665,PS4 Controller,a:b0,b:b0,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,
-576972656c65737320436f6e74726f6c,PS4 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,
63313733393535663339656564343962,PS4 Controller,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,
63393662363836383439353064663939,PS4 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,start:b6,x:b2,y:b3,platform:Android,
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,
+050000004c050000e60c0000ffff3f00,PS5 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,
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,
+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,misc1:b8,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,
+05000000f8270000bf0b0000ffff3f00,Razer Kishi,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,
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,
050000003215000005070000ffff3f00,Razer Raiju Mobile,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,
050000003215000007070000ffff3f00,Razer Raiju Mobile,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,
@@ -1686,6 +1733,10 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
61343739353764363165343237303336,Retro Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b17,lefttrigger:b18,leftx:a0,lefty:a1,start:b10,x:b2,y:b3,platform:Android,
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,
+37393234373533633333323633646531,RetroUSB N64 RetroPort,+rightx:b17,+righty:b15,-rightx:b18,-righty:b6,a:b10,b:b9,dpdown:b19,dpleft:b1,dpright:b0,dpup:b2,leftshoulder:b7,lefttrigger:b20,leftx:a0,lefty:a1,rightshoulder:b5,start:b3,platform:Android,
+5365616c6965436f6d707574696e6720,RetroUSB N64 RetroPort,+rightx:b17,+righty:b15,-rightx:b18,-righty:b6,a:b10,b:b9,dpdown:b19,dpleft:b1,dpright:b0,dpup:b2,leftshoulder:b7,lefttrigger:b20,leftx:a0,lefty:a1,rightshoulder:b5,start:b3,platform:Android,
+526574726f5553422e636f6d20534e45,RetroUSB SNES RetroPort,a:b1,b:b20,back:b19,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,rightshoulder:b10,start:b2,x:b0,y:b3,platform:Android,
+64643037633038386238303966376137,RetroUSB SNES RetroPort,a:b1,b:b20,back:b19,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,rightshoulder:b10,start:b2,x:b0,y:b3,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 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,
@@ -1706,6 +1757,8 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
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,
0500000011010000201400000f7e0f00,SteelSeries Nimbus,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,rightx:a2,righty:a3,x:b19,y:b2,platform:Android,
35306436396437373135383665646464,SteelSeries Nimbus Plus,a:b0,b:b1,leftshoulder:b3,leftstick:b17,lefttrigger:b9,leftx:a0,rightshoulder:b20,rightstick:b18,righttrigger:b10,rightx:a2,x:b19,y:b2,platform:Android,
+54475a20436f6e74726f6c6c65720000,TGZ Controller,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,
+62363434353532386238336663643836,TGZ Controller,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,
050000004f0400000ed00000fffe3f00,ThrustMaster eSwap Pro 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,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
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,
@@ -1749,9 +1802,12 @@ 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,
+050000007e050000062000000f060000,Nintendo Switch Joy-Con (L),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b2,leftshoulder:b4,rightshoulder:b5,x:b1,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,
+050000007e05000008200000df070000,Nintendo Switch Joy-Con (L/R),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,
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,
+050000007e05000009200000df870000,Nintendo Switch Pro Controller,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,misc1:b10,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,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,
diff --git a/core/input/input_event.cpp b/core/input/input_event.cpp
index 9dc071de9c..0a32b4bf68 100644
--- a/core/input/input_event.cpp
+++ b/core/input/input_event.cpp
@@ -1562,7 +1562,7 @@ String InputEventMIDI::as_text() const {
}
String InputEventMIDI::to_string() {
- return vformat("InputEventMIDI: channel=%d, message=%d, pitch=%d, velocity=%d, pressure=%d", channel, message, pitch, velocity, pressure);
+ return vformat("InputEventMIDI: channel=%d, message=%d, pitch=%d, velocity=%d, pressure=%d, controller_number=%d, controller_value=%d", channel, message, pitch, velocity, pressure, controller_number, controller_value);
}
void InputEventMIDI::_bind_methods() {
diff --git a/core/input/shortcut.cpp b/core/input/shortcut.cpp
index 9eeeb449ba..e74ccb11bb 100644
--- a/core/input/shortcut.cpp
+++ b/core/input/shortcut.cpp
@@ -107,7 +107,7 @@ void Shortcut::_bind_methods() {
ClassDB::bind_method(D_METHOD("matches_event", "event"), &Shortcut::matches_event);
ClassDB::bind_method(D_METHOD("get_as_text"), &Shortcut::get_as_text);
- ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "events", PROPERTY_HINT_ARRAY_TYPE, vformat("%s/%s:%s", Variant::OBJECT, PROPERTY_HINT_RESOURCE_TYPE, "InputEvent")), "set_events", "get_events");
+ ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "events", PROPERTY_HINT_ARRAY_TYPE, MAKE_RESOURCE_TYPE_HINT("InputEvent")), "set_events", "get_events");
}
bool Shortcut::is_event_array_equal(const Array &p_event_array1, const Array &p_event_array2) {
diff --git a/core/io/file_access.cpp b/core/io/file_access.cpp
index cb25564342..0ceb300f97 100644
--- a/core/io/file_access.cpp
+++ b/core/io/file_access.cpp
@@ -690,7 +690,7 @@ void FileAccess::store_var(const Variant &p_var, bool p_full_objects) {
_store_buffer(buff);
}
-Vector<uint8_t> FileAccess::get_file_as_array(const String &p_path, Error *r_error) {
+Vector<uint8_t> FileAccess::get_file_as_bytes(const String &p_path, Error *r_error) {
Ref<FileAccess> f = FileAccess::open(p_path, READ, r_error);
if (f.is_null()) {
if (r_error) { // if error requested, do not throw error
@@ -706,7 +706,7 @@ Vector<uint8_t> FileAccess::get_file_as_array(const String &p_path, Error *r_err
String FileAccess::get_file_as_string(const String &p_path, Error *r_error) {
Error err;
- Vector<uint8_t> array = get_file_as_array(p_path, &err);
+ Vector<uint8_t> array = get_file_as_bytes(p_path, &err);
if (r_error) {
*r_error = err;
}
@@ -810,6 +810,9 @@ void FileAccess::_bind_methods() {
ClassDB::bind_static_method("FileAccess", D_METHOD("open_compressed", "path", "mode_flags", "compression_mode"), &FileAccess::open_compressed, DEFVAL(0));
ClassDB::bind_static_method("FileAccess", D_METHOD("get_open_error"), &FileAccess::get_open_error);
+ ClassDB::bind_static_method("FileAccess", D_METHOD("get_file_as_bytes", "path"), &FileAccess::_get_file_as_bytes);
+ ClassDB::bind_static_method("FileAccess", D_METHOD("get_file_as_string", "path"), &FileAccess::_get_file_as_string);
+
ClassDB::bind_method(D_METHOD("flush"), &FileAccess::flush);
ClassDB::bind_method(D_METHOD("get_path"), &FileAccess::get_path);
ClassDB::bind_method(D_METHOD("get_path_absolute"), &FileAccess::get_path_absolute);
diff --git a/core/io/file_access.h b/core/io/file_access.h
index 8ca44306a0..54a0235333 100644
--- a/core/io/file_access.h
+++ b/core/io/file_access.h
@@ -192,9 +192,12 @@ public:
static String get_sha256(const String &p_file);
static String get_multiple_md5(const Vector<String> &p_file);
- static Vector<uint8_t> get_file_as_array(const String &p_path, Error *r_error = nullptr);
+ static Vector<uint8_t> get_file_as_bytes(const String &p_path, Error *r_error = nullptr);
static String get_file_as_string(const String &p_path, Error *r_error = nullptr);
+ static PackedByteArray _get_file_as_bytes(const String &p_path) { return get_file_as_bytes(p_path); }
+ static String _get_file_as_string(const String &p_path) { return get_file_as_string(p_path); };
+
template <class T>
static void make_default(AccessType p_access) {
create_func[p_access] = _create_builtin<T>;
diff --git a/core/io/image.cpp b/core/io/image.cpp
index 65addaf964..a2e1bc22be 100644
--- a/core/io/image.cpp
+++ b/core/io/image.cpp
@@ -173,6 +173,14 @@ int Image::get_format_pixel_size(Format p_format) {
return 1;
case FORMAT_DXT5_RA_AS_RG:
return 1;
+ case FORMAT_ASTC_4x4:
+ return 1;
+ case FORMAT_ASTC_4x4_HDR:
+ return 1;
+ case FORMAT_ASTC_8x8:
+ return 1;
+ case FORMAT_ASTC_8x8_HDR:
+ return 1;
case FORMAT_MAX: {
}
}
@@ -213,7 +221,18 @@ void Image::get_format_min_pixel_size(Format p_format, int &r_w, int &r_h) {
r_h = 4;
} break;
+ case FORMAT_ASTC_4x4:
+ case FORMAT_ASTC_4x4_HDR: {
+ r_w = 4;
+ r_h = 4;
+
+ } break;
+ case FORMAT_ASTC_8x8:
+ case FORMAT_ASTC_8x8_HDR: {
+ r_w = 8;
+ r_h = 8;
+ } break;
default: {
r_w = 1;
r_h = 1;
@@ -222,7 +241,9 @@ void Image::get_format_min_pixel_size(Format p_format, int &r_w, int &r_h) {
}
int Image::get_format_pixel_rshift(Format p_format) {
- if (p_format == FORMAT_DXT1 || p_format == FORMAT_RGTC_R || p_format == FORMAT_ETC || p_format == FORMAT_ETC2_R11 || p_format == FORMAT_ETC2_R11S || p_format == FORMAT_ETC2_RGB8 || p_format == FORMAT_ETC2_RGB8A1) {
+ if (p_format == FORMAT_ASTC_8x8) {
+ return 2;
+ } else if (p_format == FORMAT_DXT1 || p_format == FORMAT_RGTC_R || p_format == FORMAT_ETC || p_format == FORMAT_ETC2_R11 || p_format == FORMAT_ETC2_R11S || p_format == FORMAT_ETC2_RGB8 || p_format == FORMAT_ETC2_RGB8A1) {
return 1;
} else {
return 0;
@@ -260,6 +281,14 @@ int Image::get_format_block_size(Format p_format) {
{
return 4;
}
+ case FORMAT_ASTC_4x4:
+ case FORMAT_ASTC_4x4_HDR: {
+ return 4;
+ }
+ case FORMAT_ASTC_8x8:
+ case FORMAT_ASTC_8x8_HDR: {
+ return 8;
+ }
default: {
}
}
@@ -1341,78 +1370,126 @@ void Image::crop(int p_width, int 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);
- }
+ ERR_FAIL_COND_MSG(width <= 0, "The Image width specified (" + itos(width) + " pixels) must be greater than 0 pixels.");
+ ERR_FAIL_COND_MSG(height <= 0, "The Image height specified (" + itos(height) + " pixels) must be greater than 0 pixels.");
bool used_mipmaps = has_mipmaps();
if (used_mipmaps) {
clear_mipmaps();
}
+ // In-place 90 degrees rotation by following the permutation cycles.
{
- uint8_t *w = data.ptrw();
- uint8_t src[16];
- uint8_t dst[16];
+ // Explanation by example (clockwise):
+ //
+ // abc da
+ // def -> eb
+ // fc
+ //
+ // In memory:
+ // 012345 012345
+ // abcdef -> daebfc
+ //
+ // Permutation cycles:
+ // (0 --a--> 1 --b--> 3 --d--> 0)
+ // (2 --c--> 5 --f--> 4 --e--> 2)
+ //
+ // Applying cycles (backwards):
+ // 0->s s=a (store)
+ // 3->0 abcdef -> dbcdef
+ // 1->3 dbcdef -> dbcbef
+ // s->1 dbcbef -> dacbef
+ //
+ // 2->s s=c
+ // 4->2 dacbef -> daebef
+ // 5->4 daebef -> daebff
+ // s->5 daebff -> daebfc
+
+ const int w = width;
+ const int h = height;
+ const int size = w * h;
+
+ uint8_t *data_ptr = data.ptrw();
uint32_t pixel_size = get_format_pixel_size(format);
- // Flip.
+ uint8_t single_pixel_buffer[16];
- 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);
+#define PREV_INDEX_IN_CYCLE(index) (p_direction == CLOCKWISE) ? ((h - 1 - (index % h)) * w + (index / h)) : ((index % h) * w + (w - 1 - (index / h)))
- _put_pixelb(x, height - y - 1, pixel_size, w, src);
- _put_pixelb(x, y, pixel_size, w, dst);
+ if (w == h) { // Square case, 4-length cycles only (plus irrelevant thus skipped 1-length cycle in the middle for odd-sized squares).
+ for (int y = 0; y < h / 2; y++) {
+ for (int x = 0; x < (w + 1) / 2; x++) {
+ int current = y * w + x;
+ memcpy(single_pixel_buffer, data_ptr + current * pixel_size, pixel_size);
+ for (int i = 0; i < 3; i++) {
+ int prev = PREV_INDEX_IN_CYCLE(current);
+ memcpy(data_ptr + current * pixel_size, data_ptr + prev * pixel_size, pixel_size);
+ current = prev;
+ }
+ memcpy(data_ptr + current * pixel_size, single_pixel_buffer, pixel_size);
}
}
- } 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);
+ } else { // Rectangular case (w != h), kinda unpredictable cycles.
+ int permuted_pixels_count = 0;
+
+ for (int i = 0; i < size; i++) {
+ int prev = PREV_INDEX_IN_CYCLE(i);
+ if (prev == i) {
+ // 1-length cycle, pixel remains at the same index.
+ permuted_pixels_count++;
+ continue;
+ }
- _put_pixelb(width - x - 1, y, pixel_size, w, src);
- _put_pixelb(x, y, pixel_size, w, dst);
+ // Check whether we already processed this cycle.
+ // We iterate over it and if we'll find an index smaller than `i` then we already
+ // processed this cycle because we always start at the smallest index in the cycle.
+ // TODO: Improve this naive approach, can be done better.
+ while (prev > i) {
+ prev = PREV_INDEX_IN_CYCLE(prev);
+ }
+ if (prev < i) {
+ continue;
}
- }
- }
- // Transpose.
+ // Save the in-cycle pixel with the smallest index (`i`).
+ memcpy(single_pixel_buffer, data_ptr + i * pixel_size, pixel_size);
- 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);
+ // Overwrite pixels one by one by the preceding pixel in the cycle.
+ int current = i;
+ prev = PREV_INDEX_IN_CYCLE(current);
+ while (prev != i) {
+ memcpy(data_ptr + current * pixel_size, data_ptr + prev * pixel_size, pixel_size);
+ permuted_pixels_count++;
- _put_pixelb(y, x, pixel_size, w, src);
- _put_pixelb(x, y, pixel_size, w, dst);
+ current = prev;
+ prev = PREV_INDEX_IN_CYCLE(current);
+ };
+
+ // Overwrite the remaining pixel in the cycle by the saved pixel with the smallest index.
+ memcpy(data_ptr + current * pixel_size, single_pixel_buffer, pixel_size);
+ permuted_pixels_count++;
+
+ if (permuted_pixels_count == size) {
+ break;
}
}
+
+ width = h;
+ height = w;
}
+
+#undef PREV_INDEX_IN_CYCLE
}
- if (saved_width != saved_height) {
- resize(saved_width, saved_height, INTERPOLATE_NEAREST);
- } else if (used_mipmaps) {
+ 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.");
+ ERR_FAIL_COND_MSG(width <= 0, "The Image width specified (" + itos(width) + " pixels) must be greater than 0 pixels.");
+ ERR_FAIL_COND_MSG(height <= 0, "The Image height specified (" + itos(height) + " pixels) must be greater than 0 pixels.");
bool used_mipmaps = has_mipmaps();
if (used_mipmaps) {
@@ -1420,19 +1497,21 @@ void Image::rotate_180() {
}
{
- uint8_t *w = data.ptrw();
- uint8_t src[16];
- uint8_t dst[16];
+ uint8_t *data_ptr = data.ptrw();
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);
+ uint8_t single_pixel_buffer[16];
- _put_pixelb(width - x - 1, height - y - 1, pixel_size, w, src);
- _put_pixelb(x, y, pixel_size, w, dst);
- }
+ uint8_t *from_begin_ptr = data_ptr;
+ uint8_t *from_end_ptr = data_ptr + (width * height - 1) * pixel_size;
+
+ while (from_begin_ptr < from_end_ptr) {
+ memcpy(single_pixel_buffer, from_begin_ptr, pixel_size);
+ memcpy(from_begin_ptr, from_end_ptr, pixel_size);
+ memcpy(from_end_ptr, single_pixel_buffer, pixel_size);
+
+ from_begin_ptr += pixel_size;
+ from_end_ptr -= pixel_size;
}
}
@@ -2531,19 +2610,23 @@ Error Image::decompress() {
_image_decompress_etc1(this);
} else if (format >= FORMAT_ETC2_R11 && format <= FORMAT_ETC2_RA_AS_RG && _image_decompress_etc2) {
_image_decompress_etc2(this);
+ } else if (format >= FORMAT_ASTC_4x4 && format <= FORMAT_ASTC_8x8_HDR && _image_decompress_astc) {
+ _image_decompress_astc(this);
} else {
return ERR_UNAVAILABLE;
}
return OK;
}
-Error Image::compress(CompressMode p_mode, CompressSource p_source, float p_lossy_quality) {
+Error Image::compress(CompressMode p_mode, CompressSource p_source, float p_lossy_quality, ASTCFormat p_astc_format) {
ERR_FAIL_INDEX_V_MSG(p_mode, COMPRESS_MAX, ERR_INVALID_PARAMETER, "Invalid compress mode.");
ERR_FAIL_INDEX_V_MSG(p_source, COMPRESS_SOURCE_MAX, ERR_INVALID_PARAMETER, "Invalid compress source.");
- return compress_from_channels(p_mode, detect_used_channels(p_source), p_lossy_quality);
+ return compress_from_channels(p_mode, detect_used_channels(p_source), p_lossy_quality, p_astc_format);
}
-Error Image::compress_from_channels(CompressMode p_mode, UsedChannels p_channels, float p_lossy_quality) {
+Error Image::compress_from_channels(CompressMode p_mode, UsedChannels p_channels, float p_lossy_quality, ASTCFormat p_astc_format) {
+ ERR_FAIL_COND_V(data.is_empty(), ERR_INVALID_DATA);
+
switch (p_mode) {
case COMPRESS_S3TC: {
ERR_FAIL_COND_V(!_image_compress_bc_func, ERR_UNAVAILABLE);
@@ -2561,6 +2644,10 @@ Error Image::compress_from_channels(CompressMode p_mode, UsedChannels p_channels
ERR_FAIL_COND_V(!_image_compress_bptc_func, ERR_UNAVAILABLE);
_image_compress_bptc_func(this, p_lossy_quality, p_channels);
} break;
+ case COMPRESS_ASTC: {
+ ERR_FAIL_COND_V(!_image_compress_bptc_func, ERR_UNAVAILABLE);
+ _image_compress_astc_func(this, p_lossy_quality, p_astc_format);
+ } break;
case COMPRESS_MAX: {
ERR_FAIL_V(ERR_INVALID_PARAMETER);
} break;
@@ -2917,10 +3004,12 @@ void (*Image::_image_compress_bc_func)(Image *, float, Image::UsedChannels) = nu
void (*Image::_image_compress_bptc_func)(Image *, float, Image::UsedChannels) = nullptr;
void (*Image::_image_compress_etc1_func)(Image *, float) = nullptr;
void (*Image::_image_compress_etc2_func)(Image *, float, Image::UsedChannels) = nullptr;
+void (*Image::_image_compress_astc_func)(Image *, float, Image::ASTCFormat) = nullptr;
void (*Image::_image_decompress_bc)(Image *) = nullptr;
void (*Image::_image_decompress_bptc)(Image *) = nullptr;
void (*Image::_image_decompress_etc1)(Image *) = nullptr;
void (*Image::_image_decompress_etc2)(Image *) = nullptr;
+void (*Image::_image_decompress_astc)(Image *) = nullptr;
Vector<uint8_t> (*Image::webp_lossy_packer)(const Ref<Image> &, float) = nullptr;
Vector<uint8_t> (*Image::webp_lossless_packer)(const Ref<Image> &) = nullptr;
@@ -3337,8 +3426,8 @@ void Image::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_invisible"), &Image::is_invisible);
ClassDB::bind_method(D_METHOD("detect_used_channels", "source"), &Image::detect_used_channels, DEFVAL(COMPRESS_SOURCE_GENERIC));
- ClassDB::bind_method(D_METHOD("compress", "mode", "source", "lossy_quality"), &Image::compress, DEFVAL(COMPRESS_SOURCE_GENERIC), DEFVAL(0.7));
- ClassDB::bind_method(D_METHOD("compress_from_channels", "mode", "channels", "lossy_quality"), &Image::compress_from_channels, DEFVAL(0.7));
+ ClassDB::bind_method(D_METHOD("compress", "mode", "source", "lossy_quality", "astc_format"), &Image::compress, DEFVAL(COMPRESS_SOURCE_GENERIC), DEFVAL(0.7), DEFVAL(ASTC_FORMAT_4x4));
+ ClassDB::bind_method(D_METHOD("compress_from_channels", "mode", "channels", "lossy_quality", "astc_format"), &Image::compress_from_channels, DEFVAL(0.7), DEFVAL(ASTC_FORMAT_4x4));
ClassDB::bind_method(D_METHOD("decompress"), &Image::decompress);
ClassDB::bind_method(D_METHOD("is_compressed"), &Image::is_compressed);
@@ -3422,6 +3511,10 @@ void Image::_bind_methods() {
BIND_ENUM_CONSTANT(FORMAT_ETC2_RGB8A1);
BIND_ENUM_CONSTANT(FORMAT_ETC2_RA_AS_RG);
BIND_ENUM_CONSTANT(FORMAT_DXT5_RA_AS_RG);
+ BIND_ENUM_CONSTANT(FORMAT_ASTC_4x4);
+ BIND_ENUM_CONSTANT(FORMAT_ASTC_4x4_HDR);
+ BIND_ENUM_CONSTANT(FORMAT_ASTC_8x8);
+ BIND_ENUM_CONSTANT(FORMAT_ASTC_8x8_HDR);
BIND_ENUM_CONSTANT(FORMAT_MAX);
BIND_ENUM_CONSTANT(INTERPOLATE_NEAREST);
@@ -3449,6 +3542,9 @@ void Image::_bind_methods() {
BIND_ENUM_CONSTANT(COMPRESS_SOURCE_GENERIC);
BIND_ENUM_CONSTANT(COMPRESS_SOURCE_SRGB);
BIND_ENUM_CONSTANT(COMPRESS_SOURCE_NORMAL);
+
+ BIND_ENUM_CONSTANT(ASTC_FORMAT_4x4);
+ BIND_ENUM_CONSTANT(ASTC_FORMAT_8x8);
}
void Image::set_compress_bc_func(void (*p_compress_func)(Image *, float, UsedChannels)) {
@@ -3748,6 +3844,19 @@ void Image::convert_ra_rgba8_to_rg() {
}
}
+void Image::convert_rgba8_to_bgra8() {
+ ERR_FAIL_COND(format != FORMAT_RGBA8);
+ ERR_FAIL_COND(!data.size());
+
+ int s = data.size();
+ uint8_t *w = data.ptrw();
+ for (int i = 0; i < s; i += 4) {
+ uint8_t r = w[i];
+ w[i] = w[i + 2]; // Swap R to B
+ w[i + 2] = r; // Swap B to R
+ }
+}
+
Error Image::_load_from_buffer(const Vector<uint8_t> &p_array, ImageMemLoadFunc p_loader) {
int buffer_size = p_array.size();
diff --git a/core/io/image.h b/core/io/image.h
index 62df81e7c8..8bcee4404b 100644
--- a/core/io/image.h
+++ b/core/io/image.h
@@ -109,6 +109,10 @@ public:
FORMAT_ETC2_RGB8A1,
FORMAT_ETC2_RA_AS_RG, //used to make basis universal happy
FORMAT_DXT5_RA_AS_RG, //used to make basis universal happy
+ FORMAT_ASTC_4x4,
+ FORMAT_ASTC_4x4_HDR,
+ FORMAT_ASTC_8x8,
+ FORMAT_ASTC_8x8_HDR,
FORMAT_MAX
};
@@ -134,6 +138,11 @@ public:
};
//some functions provided by something else
+ enum ASTCFormat {
+ ASTC_FORMAT_4x4,
+ ASTC_FORMAT_8x8,
+ };
+
static ImageMemLoadFunc _png_mem_loader_func;
static ImageMemLoadFunc _jpg_mem_loader_func;
static ImageMemLoadFunc _webp_mem_loader_func;
@@ -144,11 +153,13 @@ public:
static void (*_image_compress_bptc_func)(Image *, float p_lossy_quality, UsedChannels p_channels);
static void (*_image_compress_etc1_func)(Image *, float);
static void (*_image_compress_etc2_func)(Image *, float, UsedChannels p_channels);
+ static void (*_image_compress_astc_func)(Image *, float, ASTCFormat p_format);
static void (*_image_decompress_bc)(Image *);
static void (*_image_decompress_bptc)(Image *);
static void (*_image_decompress_etc1)(Image *);
static void (*_image_decompress_etc2)(Image *);
+ static void (*_image_decompress_astc)(Image *);
static Vector<uint8_t> (*webp_lossy_packer)(const Ref<Image> &p_image, float p_quality);
static Vector<uint8_t> (*webp_lossless_packer)(const Ref<Image> &p_image);
@@ -347,6 +358,7 @@ public:
COMPRESS_ETC,
COMPRESS_ETC2,
COMPRESS_BPTC,
+ COMPRESS_ASTC,
COMPRESS_MAX,
};
enum CompressSource {
@@ -356,8 +368,8 @@ public:
COMPRESS_SOURCE_MAX,
};
- Error compress(CompressMode p_mode, CompressSource p_source = COMPRESS_SOURCE_GENERIC, float p_lossy_quality = 0.7);
- Error compress_from_channels(CompressMode p_mode, UsedChannels p_channels, float p_lossy_quality = 0.7);
+ Error compress(CompressMode p_mode, CompressSource p_source = COMPRESS_SOURCE_GENERIC, float p_lossy_quality = 0.7, ASTCFormat p_astc_format = ASTC_FORMAT_4x4);
+ Error compress_from_channels(CompressMode p_mode, UsedChannels p_channels, float p_lossy_quality = 0.7, ASTCFormat p_astc_format = ASTC_FORMAT_4x4);
Error decompress();
bool is_compressed() const;
@@ -391,6 +403,7 @@ public:
void convert_rg_to_ra_rgba8();
void convert_ra_rgba8_to_rg();
+ void convert_rgba8_to_bgra8();
Image(const uint8_t *p_mem_png_jpg, int p_len = -1);
Image(const char **p_xpm);
@@ -428,5 +441,6 @@ VARIANT_ENUM_CAST(Image::CompressSource)
VARIANT_ENUM_CAST(Image::UsedChannels)
VARIANT_ENUM_CAST(Image::AlphaMode)
VARIANT_ENUM_CAST(Image::RoughnessChannel)
+VARIANT_ENUM_CAST(Image::ASTCFormat)
#endif // IMAGE_H
diff --git a/core/io/packet_peer.h b/core/io/packet_peer.h
index 07045e62a6..4a5f244911 100644
--- a/core/io/packet_peer.h
+++ b/core/io/packet_peer.h
@@ -86,10 +86,10 @@ protected:
public:
virtual Error get_packet(const uint8_t **r_buffer, int &r_buffer_size) override; ///< buffer is GONE after next get_packet
- GDVIRTUAL2R(Error, _get_packet, GDNativeConstPtr<const uint8_t *>, GDNativePtr<int>);
+ GDVIRTUAL2R(Error, _get_packet, GDExtensionConstPtr<const uint8_t *>, GDExtensionPtr<int>);
virtual Error put_packet(const uint8_t *p_buffer, int p_buffer_size) override;
- GDVIRTUAL2R(Error, _put_packet, GDNativeConstPtr<const uint8_t>, int);
+ GDVIRTUAL2R(Error, _put_packet, GDExtensionConstPtr<const uint8_t>, int);
EXBIND0RC(int, get_available_packet_count);
EXBIND0RC(int, get_max_packet_size);
diff --git a/core/io/pck_packer.cpp b/core/io/pck_packer.cpp
index aa1b323db2..0556f45b0c 100644
--- a/core/io/pck_packer.cpp
+++ b/core/io/pck_packer.cpp
@@ -107,6 +107,8 @@ Error PCKPacker::pck_start(const String &p_file, int p_alignment, const String &
}
Error PCKPacker::add_file(const String &p_file, const String &p_src, bool p_encrypt) {
+ ERR_FAIL_COND_V_MSG(file.is_null(), ERR_INVALID_PARAMETER, "File must be opened before use.");
+
Ref<FileAccess> f = FileAccess::open(p_src, FileAccess::READ);
if (f.is_null()) {
return ERR_FILE_CANT_OPEN;
@@ -118,7 +120,7 @@ Error PCKPacker::add_file(const String &p_file, const String &p_src, bool p_encr
pf.ofs = ofs;
pf.size = f->get_length();
- Vector<uint8_t> data = FileAccess::get_file_as_array(p_src);
+ Vector<uint8_t> data = FileAccess::get_file_as_bytes(p_src);
{
unsigned char hash[16];
CryptoCore::md5(data.ptr(), data.size(), hash);
diff --git a/core/io/resource.cpp b/core/io/resource.cpp
index ab30fb1ca3..be75ad7e25 100644
--- a/core/io/resource.cpp
+++ b/core/io/resource.cpp
@@ -436,7 +436,7 @@ void Resource::_bind_methods() {
ADD_GROUP("Resource", "resource_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "resource_local_to_scene"), "set_local_to_scene", "is_local_to_scene");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "resource_path", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_path", "get_path");
- ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "resource_name"), "set_name", "get_name");
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "resource_name"), "set_name", "get_name");
MethodInfo get_rid_bind("_get_rid");
get_rid_bind.return_val.type = Variant::RID;
diff --git a/core/io/resource_loader.cpp b/core/io/resource_loader.cpp
index 6219ea70e4..20445a8b03 100644
--- a/core/io/resource_loader.cpp
+++ b/core/io/resource_loader.cpp
@@ -923,6 +923,35 @@ void ResourceLoader::clear_translation_remaps() {
}
}
+void ResourceLoader::clear_thread_load_tasks() {
+ thread_load_mutex->lock();
+
+ for (KeyValue<String, ResourceLoader::ThreadLoadTask> &E : thread_load_tasks) {
+ switch (E.value.status) {
+ case ResourceLoader::ThreadLoadStatus::THREAD_LOAD_LOADED: {
+ E.value.resource = Ref<Resource>();
+ } break;
+
+ case ResourceLoader::ThreadLoadStatus::THREAD_LOAD_IN_PROGRESS: {
+ if (E.value.thread != nullptr) {
+ E.value.thread->wait_to_finish();
+ memdelete(E.value.thread);
+ E.value.thread = nullptr;
+ }
+ E.value.resource = Ref<Resource>();
+ } break;
+
+ case ResourceLoader::ThreadLoadStatus::THREAD_LOAD_FAILED:
+ default: {
+ // do nothing
+ }
+ }
+ }
+ thread_load_tasks.clear();
+
+ thread_load_mutex->unlock();
+}
+
void ResourceLoader::load_path_remaps() {
if (!ProjectSettings::get_singleton()->has_setting("path_remap/remapped_paths")) {
return;
diff --git a/core/io/resource_loader.h b/core/io/resource_loader.h
index 243670b2d0..af10098bd8 100644
--- a/core/io/resource_loader.h
+++ b/core/io/resource_loader.h
@@ -219,6 +219,8 @@ public:
static void load_translation_remaps();
static void clear_translation_remaps();
+ static void clear_thread_load_tasks();
+
static void set_load_callback(ResourceLoadedCallback p_callback);
static ResourceLoaderImport import;
diff --git a/core/io/stream_peer.h b/core/io/stream_peer.h
index 108a8ce9d9..95cc655b45 100644
--- a/core/io/stream_peer.h
+++ b/core/io/stream_peer.h
@@ -105,16 +105,16 @@ protected:
public:
virtual Error put_data(const uint8_t *p_data, int p_bytes) override;
- GDVIRTUAL3R(Error, _put_data, GDNativeConstPtr<const uint8_t>, int, GDNativePtr<int>);
+ GDVIRTUAL3R(Error, _put_data, GDExtensionConstPtr<const uint8_t>, int, GDExtensionPtr<int>);
virtual Error put_partial_data(const uint8_t *p_data, int p_bytes, int &r_sent) override;
- GDVIRTUAL3R(Error, _put_partial_data, GDNativeConstPtr<const uint8_t>, int, GDNativePtr<int>);
+ GDVIRTUAL3R(Error, _put_partial_data, GDExtensionConstPtr<const uint8_t>, int, GDExtensionPtr<int>);
virtual Error get_data(uint8_t *p_buffer, int p_bytes) override;
- GDVIRTUAL3R(Error, _get_data, GDNativePtr<uint8_t>, int, GDNativePtr<int>);
+ GDVIRTUAL3R(Error, _get_data, GDExtensionPtr<uint8_t>, int, GDExtensionPtr<int>);
virtual Error get_partial_data(uint8_t *p_buffer, int p_bytes, int &r_received) override;
- GDVIRTUAL3R(Error, _get_partial_data, GDNativePtr<uint8_t>, int, GDNativePtr<int>);
+ GDVIRTUAL3R(Error, _get_partial_data, GDExtensionPtr<uint8_t>, int, GDExtensionPtr<int>);
EXBIND0RC(int, get_available_bytes);
};
diff --git a/core/io/xml_parser.cpp b/core/io/xml_parser.cpp
index abae48fdd8..16b7f3a1f6 100644
--- a/core/io/xml_parser.cpp
+++ b/core/io/xml_parser.cpp
@@ -41,11 +41,11 @@ static inline bool _is_white_space(char c) {
}
//! sets the state that text was found. Returns true if set should be set
-bool XMLParser::_set_text(char *start, char *end) {
+bool XMLParser::_set_text(const char *start, const char *end) {
// check if text is more than 2 characters, and if not, check if there is
// only white space, so that this text won't be reported
if (end - start < 3) {
- char *p = start;
+ const char *p = start;
for (; p != end; ++p) {
if (!_is_white_space(*p)) {
break;
@@ -92,7 +92,7 @@ void XMLParser::_parse_closing_xml_element() {
void XMLParser::_ignore_definition() {
node_type = NODE_UNKNOWN;
- char *F = P;
+ const char *F = P;
// move until end marked with '>' reached
while (*P && *P != '>') {
next_char();
@@ -123,8 +123,8 @@ bool XMLParser::_parse_cdata() {
return true;
}
- char *cDataBegin = P;
- char *cDataEnd = nullptr;
+ const char *cDataBegin = P;
+ const char *cDataEnd = nullptr;
// find end of CDATA
while (*P && !cDataEnd) {
@@ -152,9 +152,9 @@ void XMLParser::_parse_comment() {
node_type = NODE_COMMENT;
P += 1;
- char *pEndOfInput = data + length;
- char *pCommentBegin;
- char *pCommentEnd;
+ const char *pEndOfInput = data + length;
+ const char *pCommentBegin;
+ const char *pCommentEnd;
if (P + 1 < pEndOfInput && P[0] == '-' && P[1] == '-') {
// Comment, use '-->' as end.
@@ -293,7 +293,7 @@ void XMLParser::_parse_opening_xml_element() {
}
void XMLParser::_parse_current_node() {
- char *start = P;
+ const char *start = P;
node_offset = P - data;
// more forward until '<' found
@@ -458,15 +458,36 @@ bool XMLParser::is_empty() const {
Error XMLParser::open_buffer(const Vector<uint8_t> &p_buffer) {
ERR_FAIL_COND_V(p_buffer.size() == 0, ERR_INVALID_DATA);
- if (data) {
- memdelete_arr(data);
+ if (data_copy) {
+ memdelete_arr(data_copy);
+ data_copy = nullptr;
}
length = p_buffer.size();
- data = memnew_arr(char, length + 1);
- memcpy(data, p_buffer.ptr(), length);
- data[length] = 0;
+ data_copy = memnew_arr(char, length + 1);
+ memcpy(data_copy, p_buffer.ptr(), length);
+ data_copy[length] = 0;
+ data = data_copy;
+ P = data;
+ current_line = 0;
+
+ return OK;
+}
+
+Error XMLParser::_open_buffer(const uint8_t *p_buffer, size_t p_size) {
+ ERR_FAIL_COND_V(p_size == 0, ERR_INVALID_DATA);
+ ERR_FAIL_COND_V(!p_buffer, ERR_INVALID_DATA);
+
+ if (data_copy) {
+ memdelete_arr(data_copy);
+ data_copy = nullptr;
+ }
+
+ length = p_size;
+ data = (const char *)p_buffer;
P = data;
+ current_line = 0;
+
return OK;
}
@@ -479,13 +500,15 @@ Error XMLParser::open(const String &p_path) {
length = file->get_length();
ERR_FAIL_COND_V(length < 1, ERR_FILE_CORRUPT);
- if (data) {
- memdelete_arr(data);
+ if (data_copy) {
+ memdelete_arr(data_copy);
+ data_copy = nullptr;
}
- data = memnew_arr(char, length + 1);
- file->get_buffer((uint8_t *)data, length);
- data[length] = 0;
+ data_copy = memnew_arr(char, length + 1);
+ file->get_buffer((uint8_t *)data_copy, length);
+ data_copy[length] = 0;
+ data = data_copy;
P = data;
current_line = 0;
@@ -512,8 +535,9 @@ void XMLParser::skip_section() {
}
void XMLParser::close() {
- if (data) {
+ if (data_copy) {
memdelete_arr(data);
+ data_copy = nullptr;
}
data = nullptr;
length = 0;
@@ -528,7 +552,8 @@ int XMLParser::get_current_line() const {
}
XMLParser::~XMLParser() {
- if (data) {
- memdelete_arr(data);
+ if (data_copy) {
+ memdelete_arr(data_copy);
+ data_copy = nullptr;
}
}
diff --git a/core/io/xml_parser.h b/core/io/xml_parser.h
index aea252ddc7..be44f771dc 100644
--- a/core/io/xml_parser.h
+++ b/core/io/xml_parser.h
@@ -65,8 +65,9 @@ public:
};
private:
- char *data = nullptr;
- char *P = nullptr;
+ char *data_copy = nullptr;
+ const char *data = nullptr;
+ const char *P = nullptr;
uint64_t length = 0;
uint64_t current_line = 0;
String node_name;
@@ -81,7 +82,7 @@ private:
Vector<Attribute> attributes;
- bool _set_text(char *start, char *end);
+ bool _set_text(const char *start, const char *end);
void _parse_closing_xml_element();
void _ignore_definition();
bool _parse_cdata();
@@ -118,6 +119,7 @@ public:
Error open(const String &p_path);
Error open_buffer(const Vector<uint8_t> &p_buffer);
+ Error _open_buffer(const uint8_t *p_buffer, size_t p_size);
void close();
diff --git a/core/math/a_star_grid_2d.cpp b/core/math/a_star_grid_2d.cpp
index c30acf32bb..cdcd0ed747 100644
--- a/core/math/a_star_grid_2d.cpp
+++ b/core/math/a_star_grid_2d.cpp
@@ -134,13 +134,22 @@ AStarGrid2D::DiagonalMode AStarGrid2D::get_diagonal_mode() const {
return diagonal_mode;
}
-void AStarGrid2D::set_default_heuristic(Heuristic p_heuristic) {
+void AStarGrid2D::set_default_compute_heuristic(Heuristic p_heuristic) {
ERR_FAIL_INDEX((int)p_heuristic, (int)HEURISTIC_MAX);
- default_heuristic = p_heuristic;
+ default_compute_heuristic = p_heuristic;
}
-AStarGrid2D::Heuristic AStarGrid2D::get_default_heuristic() const {
- return default_heuristic;
+AStarGrid2D::Heuristic AStarGrid2D::get_default_compute_heuristic() const {
+ return default_compute_heuristic;
+}
+
+void AStarGrid2D::set_default_estimate_heuristic(Heuristic p_heuristic) {
+ ERR_FAIL_INDEX((int)p_heuristic, (int)HEURISTIC_MAX);
+ default_estimate_heuristic = p_heuristic;
+}
+
+AStarGrid2D::Heuristic AStarGrid2D::get_default_estimate_heuristic() const {
+ return default_estimate_heuristic;
}
void AStarGrid2D::set_point_solid(const Vector2i &p_id, bool p_solid) {
@@ -155,6 +164,19 @@ bool AStarGrid2D::is_point_solid(const Vector2i &p_id) const {
return points[p_id.y][p_id.x].solid;
}
+void AStarGrid2D::set_point_weight_scale(const Vector2i &p_id, real_t p_weight_scale) {
+ ERR_FAIL_COND_MSG(dirty, "Grid is not initialized. Call the update method.");
+ ERR_FAIL_COND_MSG(!is_in_boundsv(p_id), vformat("Can't set point's weight scale. Point out of bounds (%s/%s, %s/%s).", p_id.x, size.width, p_id.y, size.height));
+ ERR_FAIL_COND_MSG(p_weight_scale < 0.0, vformat("Can't set point's weight scale less than 0.0: %f.", p_weight_scale));
+ points[p_id.y][p_id.x].weight_scale = p_weight_scale;
+}
+
+real_t AStarGrid2D::get_point_weight_scale(const Vector2i &p_id) const {
+ ERR_FAIL_COND_V_MSG(dirty, 0, "Grid is not initialized. Call the update method.");
+ ERR_FAIL_COND_V_MSG(!is_in_boundsv(p_id), 0, vformat("Can't get point's weight scale. Point out of bounds (%s/%s, %s/%s).", p_id.x, size.width, p_id.y, size.height));
+ return points[p_id.y][p_id.x].weight_scale;
+}
+
AStarGrid2D::Point *AStarGrid2D::_jump(Point *p_from, Point *p_to) {
if (!p_to || p_to->solid) {
return nullptr;
@@ -388,7 +410,10 @@ bool AStarGrid2D::_solve(Point *p_begin_point, Point *p_end_point) {
_get_nbors(p, nbors);
for (List<Point *>::Element *E = nbors.front(); E; E = E->next()) {
Point *e = E->get(); // The neighbour point.
+ real_t weight_scale = 1.0;
+
if (jumping_enabled) {
+ // TODO: Make it works with weight_scale.
e = _jump(p, e);
if (!e || e->closed_pass == pass) {
continue;
@@ -397,9 +422,10 @@ bool AStarGrid2D::_solve(Point *p_begin_point, Point *p_end_point) {
if (e->solid || e->closed_pass == pass) {
continue;
}
+ weight_scale = e->weight_scale;
}
- real_t tentative_g_score = p->g_score + _compute_cost(p->id, e->id);
+ real_t tentative_g_score = p->g_score + _compute_cost(p->id, e->id) * weight_scale;
bool new_point = false;
if (e->open_pass != pass) { // The point wasn't inside the open list.
@@ -430,7 +456,7 @@ real_t AStarGrid2D::_estimate_cost(const Vector2i &p_from_id, const Vector2i &p_
if (GDVIRTUAL_CALL(_estimate_cost, p_from_id, p_to_id, scost)) {
return scost;
}
- return heuristics[default_heuristic](p_from_id, p_to_id);
+ return heuristics[default_estimate_heuristic](p_from_id, p_to_id);
}
real_t AStarGrid2D::_compute_cost(const Vector2i &p_from_id, const Vector2i &p_to_id) {
@@ -438,7 +464,7 @@ real_t AStarGrid2D::_compute_cost(const Vector2i &p_from_id, const Vector2i &p_t
if (GDVIRTUAL_CALL(_compute_cost, p_from_id, p_to_id, scost)) {
return scost;
}
- return heuristics[default_heuristic](p_from_id, p_to_id);
+ return heuristics[default_compute_heuristic](p_from_id, p_to_id);
}
void AStarGrid2D::clear() {
@@ -446,6 +472,12 @@ void AStarGrid2D::clear() {
size = Vector2i();
}
+Vector2 AStarGrid2D::get_point_position(const Vector2i &p_id) const {
+ ERR_FAIL_COND_V_MSG(dirty, Vector2(), "Grid is not initialized. Call the update method.");
+ ERR_FAIL_COND_V_MSG(!is_in_boundsv(p_id), Vector2(), vformat("Can't get point's position. Point out of bounds (%s/%s, %s/%s).", p_id.x, size.width, p_id.y, size.height));
+ return points[p_id.y][p_id.x].pos;
+}
+
Vector<Vector2> AStarGrid2D::get_point_path(const Vector2i &p_from_id, const Vector2i &p_to_id) {
ERR_FAIL_COND_V_MSG(dirty, Vector<Vector2>(), "Grid is not initialized. Call the update method.");
ERR_FAIL_COND_V_MSG(!is_in_boundsv(p_from_id), Vector<Vector2>(), vformat("Can't get id path. Point out of bounds (%s/%s, %s/%s)", p_from_id.x, size.width, p_from_id.y, size.height));
@@ -555,12 +587,17 @@ void AStarGrid2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_jumping_enabled"), &AStarGrid2D::is_jumping_enabled);
ClassDB::bind_method(D_METHOD("set_diagonal_mode", "mode"), &AStarGrid2D::set_diagonal_mode);
ClassDB::bind_method(D_METHOD("get_diagonal_mode"), &AStarGrid2D::get_diagonal_mode);
- ClassDB::bind_method(D_METHOD("set_default_heuristic", "heuristic"), &AStarGrid2D::set_default_heuristic);
- ClassDB::bind_method(D_METHOD("get_default_heuristic"), &AStarGrid2D::get_default_heuristic);
+ ClassDB::bind_method(D_METHOD("set_default_compute_heuristic", "heuristic"), &AStarGrid2D::set_default_compute_heuristic);
+ ClassDB::bind_method(D_METHOD("get_default_compute_heuristic"), &AStarGrid2D::get_default_compute_heuristic);
+ ClassDB::bind_method(D_METHOD("set_default_estimate_heuristic", "heuristic"), &AStarGrid2D::set_default_estimate_heuristic);
+ ClassDB::bind_method(D_METHOD("get_default_estimate_heuristic"), &AStarGrid2D::get_default_estimate_heuristic);
ClassDB::bind_method(D_METHOD("set_point_solid", "id", "solid"), &AStarGrid2D::set_point_solid, DEFVAL(true));
ClassDB::bind_method(D_METHOD("is_point_solid", "id"), &AStarGrid2D::is_point_solid);
+ ClassDB::bind_method(D_METHOD("set_point_weight_scale", "id", "weight_scale"), &AStarGrid2D::set_point_weight_scale);
+ ClassDB::bind_method(D_METHOD("get_point_weight_scale", "id"), &AStarGrid2D::get_point_weight_scale);
ClassDB::bind_method(D_METHOD("clear"), &AStarGrid2D::clear);
+ ClassDB::bind_method(D_METHOD("get_point_position", "id"), &AStarGrid2D::get_point_position);
ClassDB::bind_method(D_METHOD("get_point_path", "from_id", "to_id"), &AStarGrid2D::get_point_path);
ClassDB::bind_method(D_METHOD("get_id_path", "from_id", "to_id"), &AStarGrid2D::get_id_path);
@@ -572,8 +609,9 @@ void AStarGrid2D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "cell_size"), "set_cell_size", "get_cell_size");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "jumping_enabled"), "set_jumping_enabled", "is_jumping_enabled");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "default_heuristic", PROPERTY_HINT_ENUM, "Euclidean,Manhattan,Octile,Chebyshev,Max"), "set_default_heuristic", "get_default_heuristic");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "diagonal_mode", PROPERTY_HINT_ENUM, "Never,Always,At Least One Walkable,Only If No Obstacles,Max"), "set_diagonal_mode", "get_diagonal_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "default_compute_heuristic", PROPERTY_HINT_ENUM, "Euclidean,Manhattan,Octile,Chebyshev"), "set_default_compute_heuristic", "get_default_compute_heuristic");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "default_estimate_heuristic", PROPERTY_HINT_ENUM, "Euclidean,Manhattan,Octile,Chebyshev"), "set_default_estimate_heuristic", "get_default_estimate_heuristic");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "diagonal_mode", PROPERTY_HINT_ENUM, "Never,Always,At Least One Walkable,Only If No Obstacles"), "set_diagonal_mode", "get_diagonal_mode");
BIND_ENUM_CONSTANT(HEURISTIC_EUCLIDEAN);
BIND_ENUM_CONSTANT(HEURISTIC_MANHATTAN);
diff --git a/core/math/a_star_grid_2d.h b/core/math/a_star_grid_2d.h
index 1002f18738..ca36013b61 100644
--- a/core/math/a_star_grid_2d.h
+++ b/core/math/a_star_grid_2d.h
@@ -65,13 +65,15 @@ private:
bool jumping_enabled = false;
DiagonalMode diagonal_mode = DIAGONAL_MODE_ALWAYS;
- Heuristic default_heuristic = HEURISTIC_EUCLIDEAN;
+ Heuristic default_compute_heuristic = HEURISTIC_EUCLIDEAN;
+ Heuristic default_estimate_heuristic = HEURISTIC_EUCLIDEAN;
struct Point {
Vector2i id;
bool solid = false;
Vector2 pos;
+ real_t weight_scale = 1.0;
// Used for pathfinding.
Point *prev_point = nullptr;
@@ -160,14 +162,21 @@ public:
void set_diagonal_mode(DiagonalMode p_diagonal_mode);
DiagonalMode get_diagonal_mode() const;
- void set_default_heuristic(Heuristic p_heuristic);
- Heuristic get_default_heuristic() const;
+ void set_default_compute_heuristic(Heuristic p_heuristic);
+ Heuristic get_default_compute_heuristic() const;
+
+ void set_default_estimate_heuristic(Heuristic p_heuristic);
+ Heuristic get_default_estimate_heuristic() const;
void set_point_solid(const Vector2i &p_id, bool p_solid = true);
bool is_point_solid(const Vector2i &p_id) const;
+ void set_point_weight_scale(const Vector2i &p_id, real_t p_weight_scale);
+ real_t get_point_weight_scale(const Vector2i &p_id) const;
+
void clear();
+ Vector2 get_point_position(const Vector2i &p_id) const;
Vector<Vector2> get_point_path(const Vector2i &p_from, const Vector2i &p_to);
TypedArray<Vector2i> get_id_path(const Vector2i &p_from, const Vector2i &p_to);
};
diff --git a/core/math/basis.cpp b/core/math/basis.cpp
index 41ec6d8ce3..d7bb025b69 100644
--- a/core/math/basis.cpp
+++ b/core/math/basis.cpp
@@ -487,7 +487,7 @@ Vector3 Basis::get_euler(EulerOrder p_order) const {
euler.z = 0.0f;
}
return euler;
- } break;
+ }
case EulerOrder::XZY: {
// Euler angles in XZY convention.
// See https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix
@@ -516,7 +516,7 @@ Vector3 Basis::get_euler(EulerOrder p_order) const {
euler.z = -Math_PI / 2.0f;
}
return euler;
- } break;
+ }
case EulerOrder::YXZ: {
// Euler angles in YXZ convention.
// See https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix
@@ -554,7 +554,7 @@ Vector3 Basis::get_euler(EulerOrder p_order) const {
}
return euler;
- } break;
+ }
case EulerOrder::YZX: {
// Euler angles in YZX convention.
// See https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix
@@ -639,7 +639,7 @@ Vector3 Basis::get_euler(EulerOrder p_order) const {
euler.z = -Math::atan2(rows[0][1], rows[1][1]);
}
return euler;
- } break;
+ }
default: {
ERR_FAIL_V_MSG(Vector3(), "Invalid parameter for get_euler(order)");
}
diff --git a/core/math/color.h b/core/math/color.h
index a23a4953ce..5630539aa7 100644
--- a/core/math/color.h
+++ b/core/math/color.h
@@ -105,12 +105,10 @@ struct _NO_DISCARD_ Color {
_FORCE_INLINE_ Color lerp(const Color &p_to, float p_weight) const {
Color res = *this;
-
- res.r += (p_weight * (p_to.r - r));
- res.g += (p_weight * (p_to.g - g));
- res.b += (p_weight * (p_to.b - b));
- res.a += (p_weight * (p_to.a - a));
-
+ res.r = Math::lerp(res.r, p_to.r, p_weight);
+ res.g = Math::lerp(res.g, p_to.g, p_weight);
+ res.b = Math::lerp(res.b, p_to.b, p_weight);
+ res.a = Math::lerp(res.a, p_to.a, p_weight);
return res;
}
diff --git a/core/math/convex_hull.cpp b/core/math/convex_hull.cpp
index 561970d2ee..51d88d8ea0 100644
--- a/core/math/convex_hull.cpp
+++ b/core/math/convex_hull.cpp
@@ -2274,8 +2274,7 @@ Error ConvexHullComputer::convex_hull(const Vector<Vector3> &p_points, Geometry3
// Copy the edges over. There's two "half-edges" for every edge, so we pick only one of them.
r_mesh.edges.resize(ch.edges.size() / 2);
- OAHashMap<uint64_t, int32_t> edge_map;
- edge_map.reserve(ch.edges.size() * 4); // The higher the capacity, the faster the insert
+ OAHashMap<uint64_t, int32_t> edge_map(ch.edges.size() * 4); // The higher the capacity, the faster the insert
uint32_t edges_copied = 0;
for (uint32_t i = 0; i < ch.edges.size(); i++) {
diff --git a/core/math/expression.cpp b/core/math/expression.cpp
index dcec3929fe..26b809e7f2 100644
--- a/core/math/expression.cpp
+++ b/core/math/expression.cpp
@@ -1420,7 +1420,7 @@ bool Expression::_execute(const Array &p_inputs, Object *p_instance, Expression:
Callable::CallError ce;
Variant::call_utility_function(bifunc->func, &r_ret, (const Variant **)argp.ptr(), argp.size(), ce);
if (ce.error != Callable::CallError::CALL_OK) {
- r_error_str = "Builtin Call Failed. " + Variant::get_call_error_text(bifunc->func, (const Variant **)argp.ptr(), argp.size(), ce);
+ r_error_str = "Builtin call failed: " + Variant::get_call_error_text(bifunc->func, (const Variant **)argp.ptr(), argp.size(), ce);
return true;
}
diff --git a/core/math/math_defs.h b/core/math/math_defs.h
index 759667e2d5..1058a47c1a 100644
--- a/core/math/math_defs.h
+++ b/core/math/math_defs.h
@@ -86,6 +86,7 @@ enum InlineAlignment {
// Image alignment points.
INLINE_ALIGNMENT_TOP_TO = 0b0000,
INLINE_ALIGNMENT_CENTER_TO = 0b0001,
+ INLINE_ALIGNMENT_BASELINE_TO = 0b0011,
INLINE_ALIGNMENT_BOTTOM_TO = 0b0010,
INLINE_ALIGNMENT_IMAGE_MASK = 0b0011,
diff --git a/core/math/math_funcs.h b/core/math/math_funcs.h
index 0af529ad98..a998dece2a 100644
--- a/core/math/math_funcs.h
+++ b/core/math/math_funcs.h
@@ -364,6 +364,26 @@ public:
return p_start * omt3 + p_control_1 * omt2 * p_t * 3.0f + p_control_2 * omt * t2 * 3.0f + p_end * t3;
}
+ static _ALWAYS_INLINE_ double bezier_derivative(double p_start, double p_control_1, double p_control_2, double p_end, double p_t) {
+ /* Formula from Wikipedia article on Bezier curves. */
+ double omt = (1.0 - p_t);
+ double omt2 = omt * omt;
+ double t2 = p_t * p_t;
+
+ double d = (p_control_1 - p_start) * 3.0 * omt2 + (p_control_2 - p_control_1) * 6.0 * omt * p_t + (p_end - p_control_2) * 3.0 * t2;
+ return d;
+ }
+
+ static _ALWAYS_INLINE_ float bezier_derivative(float p_start, float p_control_1, float p_control_2, float p_end, float p_t) {
+ /* Formula from Wikipedia article on Bezier curves. */
+ float omt = (1.0f - p_t);
+ float omt2 = omt * omt;
+ float t2 = p_t * p_t;
+
+ float d = (p_control_1 - p_start) * 3.0f * omt2 + (p_control_2 - p_control_1) * 6.0f * omt * p_t + (p_end - p_control_2) * 3.0f * t2;
+ return d;
+ }
+
static _ALWAYS_INLINE_ double lerp_angle(double p_from, double p_to, double p_weight) {
double difference = fmod(p_to - p_from, Math_TAU);
double distance = fmod(2.0 * difference, Math_TAU) - difference;
@@ -433,7 +453,10 @@ public:
}
static _ALWAYS_INLINE_ double wrapf(double value, double min, double max) {
double range = max - min;
- double result = is_zero_approx(range) ? min : value - (range * Math::floor((value - min) / range));
+ if (is_zero_approx(range)) {
+ return min;
+ }
+ double result = value - (range * Math::floor((value - min) / range));
if (is_equal_approx(result, max)) {
return min;
}
@@ -441,7 +464,10 @@ public:
}
static _ALWAYS_INLINE_ float wrapf(float value, float min, float max) {
float range = max - min;
- float result = is_zero_approx(range) ? min : value - (range * Math::floor((value - min) / range));
+ if (is_zero_approx(range)) {
+ return min;
+ }
+ float result = value - (range * Math::floor((value - min) / range));
if (is_equal_approx(result, max)) {
return min;
}
diff --git a/core/math/projection.cpp b/core/math/projection.cpp
index 70cc9b5f7c..c135e1946a 100644
--- a/core/math/projection.cpp
+++ b/core/math/projection.cpp
@@ -134,7 +134,7 @@ Projection Projection::create_for_hmd(int p_eye, real_t p_aspect, real_t p_intra
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);
+ proj.set_orthogonal(p_left, p_right, p_bottom, p_top, p_znear, p_zfar);
return proj;
}
@@ -181,7 +181,7 @@ Plane Projection::get_projection_plane(Planes p_plane) const {
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],
@@ -191,7 +191,7 @@ Plane Projection::get_projection_plane(Planes p_plane) const {
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],
@@ -201,7 +201,7 @@ Plane Projection::get_projection_plane(Planes p_plane) const {
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],
@@ -211,7 +211,7 @@ Plane Projection::get_projection_plane(Planes p_plane) const {
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],
@@ -221,7 +221,7 @@ Plane Projection::get_projection_plane(Planes p_plane) const {
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],
@@ -231,7 +231,7 @@ Plane Projection::get_projection_plane(Planes p_plane) const {
new_plane.normal = -new_plane.normal;
new_plane.normalize();
return new_plane;
- } break;
+ }
}
return Plane();
diff --git a/core/math/vector2.h b/core/math/vector2.h
index 5775d8e735..835c3d1ba6 100644
--- a/core/math/vector2.h
+++ b/core/math/vector2.h
@@ -112,6 +112,7 @@ struct _NO_DISCARD_ Vector2 {
_FORCE_INLINE_ Vector2 cubic_interpolate(const Vector2 &p_b, const Vector2 &p_pre_a, const Vector2 &p_post_b, const real_t p_weight) const;
_FORCE_INLINE_ Vector2 cubic_interpolate_in_time(const Vector2 &p_b, const Vector2 &p_pre_a, const Vector2 &p_post_b, const real_t p_weight, const real_t &p_b_t, const real_t &p_pre_a_t, const real_t &p_post_b_t) const;
_FORCE_INLINE_ Vector2 bezier_interpolate(const Vector2 &p_control_1, const Vector2 &p_control_2, const Vector2 &p_end, const real_t p_t) const;
+ _FORCE_INLINE_ Vector2 bezier_derivative(const Vector2 &p_control_1, const Vector2 &p_control_2, const Vector2 &p_end, const real_t p_t) const;
Vector2 move_toward(const Vector2 &p_to, const real_t p_delta) const;
@@ -242,10 +243,8 @@ _FORCE_INLINE_ bool Vector2::operator!=(const Vector2 &p_vec2) const {
Vector2 Vector2::lerp(const Vector2 &p_to, const real_t p_weight) const {
Vector2 res = *this;
-
- res.x += (p_weight * (p_to.x - x));
- res.y += (p_weight * (p_to.y - y));
-
+ res.x = Math::lerp(res.x, p_to.x, p_weight);
+ res.y = Math::lerp(res.y, p_to.y, p_weight);
return res;
}
@@ -278,15 +277,16 @@ Vector2 Vector2::cubic_interpolate_in_time(const Vector2 &p_b, const Vector2 &p_
Vector2 Vector2::bezier_interpolate(const Vector2 &p_control_1, const Vector2 &p_control_2, const Vector2 &p_end, const real_t p_t) const {
Vector2 res = *this;
+ res.x = Math::bezier_interpolate(res.x, p_control_1.x, p_control_2.x, p_end.x, p_t);
+ res.y = Math::bezier_interpolate(res.y, p_control_1.y, p_control_2.y, p_end.y, p_t);
+ return res;
+}
- /* Formula from Wikipedia article on Bezier curves. */
- real_t omt = (1.0 - p_t);
- real_t omt2 = omt * omt;
- real_t omt3 = omt2 * omt;
- real_t t2 = p_t * p_t;
- real_t t3 = t2 * p_t;
-
- return res * omt3 + p_control_1 * omt2 * p_t * 3.0 + p_control_2 * omt * t2 * 3.0 + p_end * t3;
+Vector2 Vector2::bezier_derivative(const Vector2 &p_control_1, const Vector2 &p_control_2, const Vector2 &p_end, const real_t p_t) const {
+ Vector2 res = *this;
+ res.x = Math::bezier_derivative(res.x, p_control_1.x, p_control_2.x, p_end.x, p_t);
+ res.y = Math::bezier_derivative(res.y, p_control_1.y, p_control_2.y, p_end.y, p_t);
+ return res;
}
Vector2 Vector2::direction_to(const Vector2 &p_to) const {
diff --git a/core/math/vector2i.cpp b/core/math/vector2i.cpp
index dfed42e4d6..ff8693ee5b 100644
--- a/core/math/vector2i.cpp
+++ b/core/math/vector2i.cpp
@@ -39,6 +39,12 @@ Vector2i Vector2i::clamp(const Vector2i &p_min, const Vector2i &p_max) const {
CLAMP(y, p_min.y, p_max.y));
}
+Vector2i Vector2i::snapped(const Vector2i &p_step) const {
+ return Vector2i(
+ Math::snapped(x, p_step.x),
+ Math::snapped(y, p_step.y));
+}
+
int64_t Vector2i::length_squared() const {
return x * (int64_t)x + y * (int64_t)y;
}
diff --git a/core/math/vector2i.h b/core/math/vector2i.h
index e131bdea94..927be11030 100644
--- a/core/math/vector2i.h
+++ b/core/math/vector2i.h
@@ -119,6 +119,7 @@ struct _NO_DISCARD_ Vector2i {
Vector2i sign() const { return Vector2i(SIGN(x), SIGN(y)); }
Vector2i abs() const { return Vector2i(Math::abs(x), Math::abs(y)); }
Vector2i clamp(const Vector2i &p_min, const Vector2i &p_max) const;
+ Vector2i snapped(const Vector2i &p_step) const;
operator String() const;
operator Vector2() const;
diff --git a/core/math/vector3.h b/core/math/vector3.h
index 19771eb312..dc74096690 100644
--- a/core/math/vector3.h
+++ b/core/math/vector3.h
@@ -100,6 +100,7 @@ struct _NO_DISCARD_ Vector3 {
_FORCE_INLINE_ Vector3 cubic_interpolate(const Vector3 &p_b, const Vector3 &p_pre_a, const Vector3 &p_post_b, const real_t p_weight) const;
_FORCE_INLINE_ Vector3 cubic_interpolate_in_time(const Vector3 &p_b, const Vector3 &p_pre_a, const Vector3 &p_post_b, const real_t p_weight, const real_t &p_b_t, const real_t &p_pre_a_t, const real_t &p_post_b_t) const;
_FORCE_INLINE_ Vector3 bezier_interpolate(const Vector3 &p_control_1, const Vector3 &p_control_2, const Vector3 &p_end, const real_t p_t) const;
+ _FORCE_INLINE_ Vector3 bezier_derivative(const Vector3 &p_control_1, const Vector3 &p_control_2, const Vector3 &p_end, const real_t p_t) const;
Vector3 move_toward(const Vector3 &p_to, const real_t p_delta) const;
@@ -208,10 +209,11 @@ Vector3 Vector3::round() const {
}
Vector3 Vector3::lerp(const Vector3 &p_to, const real_t p_weight) const {
- return Vector3(
- x + (p_weight * (p_to.x - x)),
- y + (p_weight * (p_to.y - y)),
- z + (p_weight * (p_to.z - z)));
+ Vector3 res = *this;
+ res.x = Math::lerp(res.x, p_to.x, p_weight);
+ res.y = Math::lerp(res.y, p_to.y, p_weight);
+ res.z = Math::lerp(res.z, p_to.z, p_weight);
+ return res;
}
Vector3 Vector3::slerp(const Vector3 &p_to, const real_t p_weight) const {
@@ -254,15 +256,18 @@ Vector3 Vector3::cubic_interpolate_in_time(const Vector3 &p_b, const Vector3 &p_
Vector3 Vector3::bezier_interpolate(const Vector3 &p_control_1, const Vector3 &p_control_2, const Vector3 &p_end, const real_t p_t) const {
Vector3 res = *this;
+ res.x = Math::bezier_interpolate(res.x, p_control_1.x, p_control_2.x, p_end.x, p_t);
+ res.y = Math::bezier_interpolate(res.y, p_control_1.y, p_control_2.y, p_end.y, p_t);
+ res.z = Math::bezier_interpolate(res.z, p_control_1.z, p_control_2.z, p_end.z, p_t);
+ return res;
+}
- /* Formula from Wikipedia article on Bezier curves. */
- real_t omt = (1.0 - p_t);
- real_t omt2 = omt * omt;
- real_t omt3 = omt2 * omt;
- real_t t2 = p_t * p_t;
- real_t t3 = t2 * p_t;
-
- return res * omt3 + p_control_1 * omt2 * p_t * 3.0 + p_control_2 * omt * t2 * 3.0 + p_end * t3;
+Vector3 Vector3::bezier_derivative(const Vector3 &p_control_1, const Vector3 &p_control_2, const Vector3 &p_end, const real_t p_t) const {
+ Vector3 res = *this;
+ res.x = Math::bezier_derivative(res.x, p_control_1.x, p_control_2.x, p_end.x, p_t);
+ res.y = Math::bezier_derivative(res.y, p_control_1.y, p_control_2.y, p_end.y, p_t);
+ res.z = Math::bezier_derivative(res.z, p_control_1.z, p_control_2.z, p_end.z, p_t);
+ return res;
}
real_t Vector3::distance_to(const Vector3 &p_to) const {
diff --git a/core/math/vector3i.cpp b/core/math/vector3i.cpp
index b248f35035..901f2b5a64 100644
--- a/core/math/vector3i.cpp
+++ b/core/math/vector3i.cpp
@@ -48,6 +48,13 @@ Vector3i Vector3i::clamp(const Vector3i &p_min, const Vector3i &p_max) const {
CLAMP(z, p_min.z, p_max.z));
}
+Vector3i Vector3i::snapped(const Vector3i &p_step) const {
+ return Vector3i(
+ Math::snapped(x, p_step.x),
+ Math::snapped(y, p_step.y),
+ Math::snapped(z, p_step.z));
+}
+
Vector3i::operator String() const {
return "(" + itos(x) + ", " + itos(y) + ", " + itos(z) + ")";
}
diff --git a/core/math/vector3i.h b/core/math/vector3i.h
index 710fd96376..36bac3d8ae 100644
--- a/core/math/vector3i.h
+++ b/core/math/vector3i.h
@@ -77,6 +77,7 @@ struct _NO_DISCARD_ Vector3i {
_FORCE_INLINE_ Vector3i abs() const;
_FORCE_INLINE_ Vector3i sign() const;
Vector3i clamp(const Vector3i &p_min, const Vector3i &p_max) const;
+ Vector3i snapped(const Vector3i &p_step) const;
/* Operators */
diff --git a/core/math/vector4.cpp b/core/math/vector4.cpp
index 3b189f7ed4..5ddf2bb6f6 100644
--- a/core/math/vector4.cpp
+++ b/core/math/vector4.cpp
@@ -130,11 +130,12 @@ Vector4 Vector4::round() const {
}
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 res = *this;
+ res.x = Math::lerp(res.x, p_to.x, p_weight);
+ res.y = Math::lerp(res.y, p_to.y, p_weight);
+ res.z = Math::lerp(res.z, p_to.z, p_weight);
+ res.w = Math::lerp(res.w, p_to.w, p_weight);
+ return res;
}
Vector4 Vector4::cubic_interpolate(const Vector4 &p_b, const Vector4 &p_pre_a, const Vector4 &p_post_b, const real_t p_weight) const {
diff --git a/core/math/vector4i.cpp b/core/math/vector4i.cpp
index 77f6fbd5b7..e906ab45ad 100644
--- a/core/math/vector4i.cpp
+++ b/core/math/vector4i.cpp
@@ -65,6 +65,14 @@ Vector4i Vector4i::clamp(const Vector4i &p_min, const Vector4i &p_max) const {
CLAMP(w, p_min.w, p_max.w));
}
+Vector4i Vector4i::snapped(const Vector4i &p_step) const {
+ return Vector4i(
+ Math::snapped(x, p_step.x),
+ Math::snapped(y, p_step.y),
+ Math::snapped(z, p_step.z),
+ Math::snapped(w, p_step.w));
+}
+
Vector4i::operator String() const {
return "(" + itos(x) + ", " + itos(y) + ", " + itos(z) + ", " + itos(w) + ")";
}
diff --git a/core/math/vector4i.h b/core/math/vector4i.h
index a32414bb18..cb5a48daf9 100644
--- a/core/math/vector4i.h
+++ b/core/math/vector4i.h
@@ -79,6 +79,7 @@ struct _NO_DISCARD_ Vector4i {
_FORCE_INLINE_ Vector4i abs() const;
_FORCE_INLINE_ Vector4i sign() const;
Vector4i clamp(const Vector4i &p_min, const Vector4i &p_max) const;
+ Vector4i snapped(const Vector4i &p_step) const;
/* Operators */
diff --git a/core/object/class_db.cpp b/core/object/class_db.cpp
index ac6ad0fdd2..529d99ec9a 100644
--- a/core/object/class_db.cpp
+++ b/core/object/class_db.cpp
@@ -318,7 +318,7 @@ Object *ClassDB::instantiate(const StringName &p_class) {
{
OBJTYPE_RLOCK;
ti = classes.getptr(p_class);
- if (!ti || ti->disabled || !ti->creation_func || (ti->native_extension && !ti->native_extension->create_instance)) {
+ if (!ti || ti->disabled || !ti->creation_func || (ti->gdextension && !ti->gdextension->create_instance)) {
if (compat_classes.has(p_class)) {
ti = classes.getptr(compat_classes[p_class]);
}
@@ -333,8 +333,8 @@ Object *ClassDB::instantiate(const StringName &p_class) {
return nullptr;
}
#endif
- if (ti->native_extension && ti->native_extension->create_instance) {
- return (Object *)ti->native_extension->create_instance(ti->native_extension->class_userdata);
+ if (ti->gdextension && ti->gdextension->create_instance) {
+ return (Object *)ti->gdextension->create_instance(ti->gdextension->class_userdata);
} else {
return ti->creation_func();
}
@@ -346,17 +346,17 @@ void ClassDB::set_object_extension_instance(Object *p_object, const StringName &
{
OBJTYPE_RLOCK;
ti = classes.getptr(p_class);
- if (!ti || ti->disabled || !ti->creation_func || (ti->native_extension && !ti->native_extension->create_instance)) {
+ if (!ti || ti->disabled || !ti->creation_func || (ti->gdextension && !ti->gdextension->create_instance)) {
if (compat_classes.has(p_class)) {
ti = classes.getptr(compat_classes[p_class]);
}
}
ERR_FAIL_COND_MSG(!ti, "Cannot get class '" + String(p_class) + "'.");
ERR_FAIL_COND_MSG(ti->disabled, "Class '" + String(p_class) + "' is disabled.");
- ERR_FAIL_COND_MSG(!ti->native_extension, "Class '" + String(p_class) + "' has no native extension.");
+ ERR_FAIL_COND_MSG(!ti->gdextension, "Class '" + String(p_class) + "' has no native extension.");
}
- p_object->_extension = ti->native_extension;
+ p_object->_extension = ti->gdextension;
p_object->_extension_instance = p_instance;
}
@@ -370,7 +370,7 @@ bool ClassDB::can_instantiate(const StringName &p_class) {
return false;
}
#endif
- return (!ti->disabled && ti->creation_func != nullptr && !(ti->native_extension && !ti->native_extension->create_instance));
+ return (!ti->disabled && ti->creation_func != nullptr && !(ti->gdextension && !ti->gdextension->create_instance));
}
bool ClassDB::is_virtual(const StringName &p_class) {
@@ -388,7 +388,7 @@ bool ClassDB::is_virtual(const StringName &p_class) {
return false;
}
#endif
- return (!ti->disabled && ti->creation_func != nullptr && !(ti->native_extension && !ti->native_extension->create_instance) && ti->is_virtual);
+ return (!ti->disabled && ti->creation_func != nullptr && !(ti->gdextension && !ti->gdextension->create_instance) && ti->is_virtual);
}
void ClassDB::_add_class2(const StringName &p_class, const StringName &p_inherits) {
@@ -1522,7 +1522,7 @@ Variant ClassDB::class_get_default_property_value(const StringName &p_class, con
return var;
}
-void ClassDB::register_extension_class(ObjectNativeExtension *p_extension) {
+void ClassDB::register_extension_class(ObjectGDExtension *p_extension) {
GLOBAL_LOCK_FUNCTION;
ERR_FAIL_COND_MSG(classes.has(p_extension->class_name), "Class already registered: " + String(p_extension->class_name));
@@ -1532,7 +1532,7 @@ void ClassDB::register_extension_class(ObjectNativeExtension *p_extension) {
ClassInfo c;
c.api = p_extension->editor_class ? API_EDITOR_EXTENSION : API_EXTENSION;
- c.native_extension = p_extension;
+ c.gdextension = p_extension;
c.name = p_extension->class_name;
c.is_virtual = p_extension->is_virtual;
if (!p_extension->is_abstract) {
diff --git a/core/object/class_db.h b/core/object/class_db.h
index 5fba52e23e..4b60079298 100644
--- a/core/object/class_db.h
+++ b/core/object/class_db.h
@@ -100,7 +100,7 @@ public:
ClassInfo *inherits_ptr = nullptr;
void *class_ptr = nullptr;
- ObjectNativeExtension *native_extension = nullptr;
+ ObjectGDExtension *gdextension = nullptr;
HashMap<StringName, MethodBind *> method_map;
HashMap<StringName, int64_t> constant_map;
@@ -203,7 +203,7 @@ public:
//nothing
}
- static void register_extension_class(ObjectNativeExtension *p_extension);
+ static void register_extension_class(ObjectGDExtension *p_extension);
static void unregister_extension_class(const StringName &p_class);
template <class T>
diff --git a/core/object/make_virtuals.py b/core/object/make_virtuals.py
index 61bf6d900a..0ee95835a6 100644
--- a/core/object/make_virtuals.py
+++ b/core/object/make_virtuals.py
@@ -2,7 +2,7 @@ proto = """
#define GDVIRTUAL$VER($RET m_name $ARG) \\
StringName _gdvirtual_##m_name##_sn = #m_name;\\
mutable bool _gdvirtual_##m_name##_initialized = false;\\
-mutable GDNativeExtensionClassCallVirtual _gdvirtual_##m_name = nullptr;\\
+mutable GDExtensionClassCallVirtual _gdvirtual_##m_name = nullptr;\\
template<bool required>\\
_FORCE_INLINE_ bool _gdvirtual_##m_name##_call($CALLARGS) $CONST { \\
ScriptInstance *_script_instance = ((Object*)(this))->get_script_instance();\\
@@ -16,8 +16,8 @@ _FORCE_INLINE_ bool _gdvirtual_##m_name##_call($CALLARGS) $CONST { \\
} \\
}\\
if (unlikely(_get_extension() && !_gdvirtual_##m_name##_initialized)) {\\
- /* TODO: C-style cast because GDNativeStringNamePtr's const qualifier is broken (see https://github.com/godotengine/godot/pull/67751) */\\
- _gdvirtual_##m_name = (_get_extension() && _get_extension()->get_virtual) ? _get_extension()->get_virtual(_get_extension()->class_userdata, (GDNativeStringNamePtr)&_gdvirtual_##m_name##_sn) : (GDNativeExtensionClassCallVirtual) nullptr;\\
+ /* TODO: C-style cast because GDExtensionStringNamePtr's const qualifier is broken (see https://github.com/godotengine/godot/pull/67751) */\\
+ _gdvirtual_##m_name = (_get_extension() && _get_extension()->get_virtual) ? _get_extension()->get_virtual(_get_extension()->class_userdata, (GDExtensionStringNamePtr)&_gdvirtual_##m_name##_sn) : (GDExtensionClassCallVirtual) nullptr;\\
_gdvirtual_##m_name##_initialized = true;\\
}\\
if (_gdvirtual_##m_name) {\\
@@ -41,8 +41,8 @@ _FORCE_INLINE_ bool _gdvirtual_##m_name##_overridden() const { \\
return _script_instance->has_method(_gdvirtual_##m_name##_sn);\\
}\\
if (unlikely(_get_extension() && !_gdvirtual_##m_name##_initialized)) {\\
- /* TODO: C-style cast because GDNativeStringNamePtr's const qualifier is broken (see https://github.com/godotengine/godot/pull/67751) */\\
- _gdvirtual_##m_name = (_get_extension() && _get_extension()->get_virtual) ? _get_extension()->get_virtual(_get_extension()->class_userdata, (GDNativeStringNamePtr)&_gdvirtual_##m_name##_sn) : (GDNativeExtensionClassCallVirtual) nullptr;\\
+ /* TODO: C-style cast because GDExtensionStringNamePtr's const qualifier is broken (see https://github.com/godotengine/godot/pull/67751) */\\
+ _gdvirtual_##m_name = (_get_extension() && _get_extension()->get_virtual) ? _get_extension()->get_virtual(_get_extension()->class_userdata, (GDExtensionStringNamePtr)&_gdvirtual_##m_name##_sn) : (GDExtensionClassCallVirtual) nullptr;\\
_gdvirtual_##m_name##_initialized = true;\\
}\\
if (_gdvirtual_##m_name) {\\
@@ -94,7 +94,7 @@ def generate_version(argcount, const=False, returns=False):
argtext += ", "
callsiargs = "Variant vargs[" + str(argcount) + "]={"
callsiargptrs = "\t\tconst Variant *vargptrs[" + str(argcount) + "]={"
- callptrargsptr = "\t\tconst GDNativeTypePtr argptrs[" + str(argcount) + "]={"
+ callptrargsptr = "\t\tGDExtensionConstTypePtr argptrs[" + str(argcount) + "]={"
callptrargs = ""
for i in range(argcount):
if i > 0:
@@ -121,7 +121,7 @@ def generate_version(argcount, const=False, returns=False):
s = s.replace("$CALLSIARGPASS", "(const Variant **)vargptrs," + str(argcount))
callptrargsptr += "};\\\n"
s = s.replace("$CALLPTRARGS", callptrargs + callptrargsptr)
- s = s.replace("$CALLPTRARGPASS", "(const GDNativeTypePtr*)argptrs")
+ s = s.replace("$CALLPTRARGPASS", "reinterpret_cast<GDExtensionConstTypePtr*>(argptrs)")
else:
s = s.replace("$CALLSIARGS", "")
s = s.replace("$CALLSIARGPASS", "nullptr, 0")
diff --git a/core/object/method_bind.h b/core/object/method_bind.h
index 598e8a224d..0f1366aefd 100644
--- a/core/object/method_bind.h
+++ b/core/object/method_bind.h
@@ -110,8 +110,8 @@ public:
_FORCE_INLINE_ int get_argument_count() const { return argument_count; };
- virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) = 0;
- virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) = 0;
+ virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) const = 0;
+ virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) const = 0;
StringName get_name() const;
void set_name(const StringName &p_name);
@@ -158,7 +158,7 @@ public:
}
#endif
- virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) override {
+ virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) const override {
ERR_FAIL(); // Can't call.
}
@@ -210,7 +210,7 @@ class MethodBindVarArgT : public MethodBindVarArgBase<MethodBindVarArgT<T>, T, v
friend class MethodBindVarArgBase<MethodBindVarArgT<T>, T, void, false>;
public:
- virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) override {
+ virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) const override {
(static_cast<T *>(p_object)->*MethodBindVarArgBase<MethodBindVarArgT<T>, T, void, false>::method)(p_args, p_arg_count, r_error);
return {};
}
@@ -246,7 +246,7 @@ public:
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
#endif
- virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) override {
+ virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) const override {
return (static_cast<T *>(p_object)->*MethodBindVarArgBase<MethodBindVarArgTR<T, R>, T, R, true>::method)(p_args, p_arg_count, r_error);
}
#if defined(SANITIZERS_ENABLED) && defined(__GNUC__) && !defined(__clang__)
@@ -313,7 +313,7 @@ public:
}
#endif
- virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) override {
+ virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) const override {
#ifdef TYPED_METHOD_BIND
call_with_variant_args_dv(static_cast<T *>(p_object), method, p_args, p_arg_count, r_error, get_default_arguments());
#else
@@ -322,7 +322,7 @@ public:
return Variant();
}
- virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) override {
+ virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) const override {
#ifdef TYPED_METHOD_BIND
call_with_ptr_args<T, P...>(static_cast<T *>(p_object), method, p_args);
#else
@@ -380,7 +380,7 @@ public:
}
#endif
- virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) override {
+ virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) const override {
#ifdef TYPED_METHOD_BIND
call_with_variant_argsc_dv(static_cast<T *>(p_object), method, p_args, p_arg_count, r_error, get_default_arguments());
#else
@@ -389,7 +389,7 @@ public:
return Variant();
}
- virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) override {
+ virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) const override {
#ifdef TYPED_METHOD_BIND
call_with_ptr_argsc<T, P...>(static_cast<T *>(p_object), method, p_args);
#else
@@ -457,7 +457,7 @@ public:
}
#endif
- virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) override {
+ virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) const override {
Variant ret;
#ifdef TYPED_METHOD_BIND
call_with_variant_args_ret_dv(static_cast<T *>(p_object), method, p_args, p_arg_count, ret, r_error, get_default_arguments());
@@ -467,7 +467,7 @@ public:
return ret;
}
- virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) override {
+ virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) const override {
#ifdef TYPED_METHOD_BIND
call_with_ptr_args_ret<T, R, P...>(static_cast<T *>(p_object), method, p_args, r_ret);
#else
@@ -536,7 +536,7 @@ public:
}
#endif
- virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) override {
+ virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) const override {
Variant ret;
#ifdef TYPED_METHOD_BIND
call_with_variant_args_retc_dv(static_cast<T *>(p_object), method, p_args, p_arg_count, ret, r_error, get_default_arguments());
@@ -546,7 +546,7 @@ public:
return ret;
}
- virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) override {
+ virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) const override {
#ifdef TYPED_METHOD_BIND
call_with_ptr_args_retc<T, R, P...>(static_cast<T *>(p_object), method, p_args, r_ret);
#else
@@ -604,13 +604,13 @@ public:
}
#endif
- virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) override {
+ virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) const override {
(void)p_object; // unused
call_with_variant_args_static_dv(function, p_args, p_arg_count, r_error, get_default_arguments());
return Variant();
}
- virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) override {
+ virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) const override {
(void)p_object;
(void)r_ret;
call_with_ptr_args_static_method(function, p_args);
@@ -667,13 +667,13 @@ public:
}
#endif
- virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) override {
+ virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) const override {
Variant ret;
call_with_variant_args_static_ret_dv(function, p_args, p_arg_count, ret, r_error, get_default_arguments());
return ret;
}
- virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) override {
+ virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) const override {
(void)p_object;
call_with_ptr_args_static_method_ret(function, p_args, r_ret);
}
diff --git a/core/object/object.cpp b/core/object/object.cpp
index d27e0d7621..cfac36127c 100644
--- a/core/object/object.cpp
+++ b/core/object/object.cpp
@@ -233,7 +233,7 @@ void Object::set(const StringName &p_name, const Variant &p_value, bool *r_valid
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wignored-qualifiers"
#endif
- if (_extension->set(_extension_instance, (const GDNativeStringNamePtr)&p_name, (const GDNativeVariantPtr)&p_value)) {
+ if (_extension->set(_extension_instance, (const GDExtensionStringNamePtr)&p_name, (const GDExtensionVariantPtr)&p_value)) {
if (r_valid) {
*r_valid = true;
}
@@ -321,7 +321,7 @@ Variant Object::get(const StringName &p_name, bool *r_valid) const {
#pragma GCC diagnostic ignored "-Wignored-qualifiers"
#endif
- if (_extension->get(_extension_instance, (const GDNativeStringNamePtr)&p_name, (GDNativeVariantPtr)&ret)) {
+ if (_extension->get(_extension_instance, (const GDExtensionStringNamePtr)&p_name, (GDExtensionVariantPtr)&ret)) {
if (r_valid) {
*r_valid = true;
}
@@ -477,7 +477,7 @@ void Object::get_property_list(List<PropertyInfo> *p_list, bool p_reversed) cons
}
if (_extension) {
- const ObjectNativeExtension *current_extension = _extension;
+ const ObjectGDExtension *current_extension = _extension;
while (current_extension) {
p_list->push_back(PropertyInfo(Variant::NIL, current_extension->class_name, PROPERTY_HINT_NONE, String(), PROPERTY_USAGE_CATEGORY));
ClassDB::get_property_list(current_extension->class_name, p_list, true, this);
@@ -487,7 +487,7 @@ void Object::get_property_list(List<PropertyInfo> *p_list, bool p_reversed) cons
if (_extension && _extension->get_property_list) {
uint32_t pcount;
- const GDNativePropertyInfo *pinfo = _extension->get_property_list(_extension_instance, &pcount);
+ const GDExtensionPropertyInfo *pinfo = _extension->get_property_list(_extension_instance, &pcount);
for (uint32_t i = 0; i < pcount; i++) {
p_list->push_back(PropertyInfo(pinfo[i]));
}
@@ -533,7 +533,7 @@ bool Object::property_can_revert(const StringName &p_name) const {
#pragma GCC diagnostic ignored "-Wignored-qualifiers"
#endif
if (_extension && _extension->property_can_revert) {
- if (_extension->property_can_revert(_extension_instance, (const GDNativeStringNamePtr)&p_name)) {
+ if (_extension->property_can_revert(_extension_instance, (const GDExtensionStringNamePtr)&p_name)) {
return true;
}
}
@@ -559,7 +559,7 @@ Variant Object::property_get_revert(const StringName &p_name) const {
#pragma GCC diagnostic ignored "-Wignored-qualifiers"
#endif
if (_extension && _extension->property_get_revert) {
- if (_extension->property_get_revert(_extension_instance, (const GDNativeStringNamePtr)&p_name, (GDNativeVariantPtr)&ret)) {
+ if (_extension->property_get_revert(_extension_instance, (const GDExtensionStringNamePtr)&p_name, (GDExtensionVariantPtr)&ret)) {
return ret;
}
}
@@ -808,7 +808,7 @@ String Object::to_string() {
}
if (_extension && _extension->to_string) {
String ret;
- GDNativeBool is_valid;
+ GDExtensionBool is_valid;
_extension->to_string(_extension_instance, &is_valid, &ret);
return ret;
}
@@ -1473,6 +1473,8 @@ void Object::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_indexed", "property_path"), &Object::_get_indexed_bind);
ClassDB::bind_method(D_METHOD("get_property_list"), &Object::_get_property_list_bind);
ClassDB::bind_method(D_METHOD("get_method_list"), &Object::_get_method_list_bind);
+ ClassDB::bind_method(D_METHOD("property_can_revert", "property"), &Object::property_can_revert);
+ ClassDB::bind_method(D_METHOD("property_get_revert", "property"), &Object::property_get_revert);
ClassDB::bind_method(D_METHOD("notification", "what", "reversed"), &Object::notification, DEFVAL(false));
ClassDB::bind_method(D_METHOD("to_string"), &Object::to_string);
ClassDB::bind_method(D_METHOD("get_instance_id"), &Object::get_instance_id);
@@ -1699,7 +1701,7 @@ uint32_t Object::get_edited_version() const {
}
#endif
-void Object::set_instance_binding(void *p_token, void *p_binding, const GDNativeInstanceBindingCallbacks *p_callbacks) {
+void Object::set_instance_binding(void *p_token, void *p_binding, const GDExtensionInstanceBindingCallbacks *p_callbacks) {
// This is only meant to be used on creation by the binder.
ERR_FAIL_COND(_instance_bindings != nullptr);
_instance_bindings = (InstanceBinding *)memalloc(sizeof(InstanceBinding));
@@ -1710,7 +1712,7 @@ void Object::set_instance_binding(void *p_token, void *p_binding, const GDNative
_instance_binding_count = 1;
}
-void *Object::get_instance_binding(void *p_token, const GDNativeInstanceBindingCallbacks *p_callbacks) {
+void *Object::get_instance_binding(void *p_token, const GDExtensionInstanceBindingCallbacks *p_callbacks) {
void *binding = nullptr;
_instance_binding_mutex.lock();
for (uint32_t i = 0; i < _instance_binding_count; i++) {
diff --git a/core/object/object.h b/core/object/object.h
index 7bb88998a2..d52cf7d62e 100644
--- a/core/object/object.h
+++ b/core/object/object.h
@@ -31,7 +31,7 @@
#ifndef OBJECT_H
#define OBJECT_H
-#include "core/extension/gdnative_interface.h"
+#include "core/extension/gdextension_interface.h"
#include "core/object/message_queue.h"
#include "core/object/object_id.h"
#include "core/os/rw_lock.h"
@@ -71,8 +71,6 @@ enum PropertyHint {
PROPERTY_HINT_EXPRESSION, ///< used for string properties that can contain multiple lines
PROPERTY_HINT_PLACEHOLDER_TEXT, ///< used to set a placeholder text for string properties
PROPERTY_HINT_COLOR_NO_ALPHA, ///< used for ignoring alpha component when editing a color
- PROPERTY_HINT_IMAGE_COMPRESS_LOSSY,
- PROPERTY_HINT_IMAGE_COMPRESS_LOSSLESS,
PROPERTY_HINT_OBJECT_ID,
PROPERTY_HINT_TYPE_STRING, ///< a type string, the hint is the base type to choose
PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE, ///< so something else can provide this (used in scripts)
@@ -115,22 +113,21 @@ enum PropertyUsageFlags {
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_UPDATE_ALL_IF_MODIFIED = 1 << 14,
+ PROPERTY_USAGE_SCRIPT_DEFAULT_VALUE = 1 << 15,
+ PROPERTY_USAGE_CLASS_IS_ENUM = 1 << 16,
+ PROPERTY_USAGE_NIL_IS_VARIANT = 1 << 17,
+ PROPERTY_USAGE_INTERNAL = 1 << 18,
+ PROPERTY_USAGE_DO_NOT_SHARE_ON_DUPLICATE = 1 << 19, // If the object is duplicated also this property will be duplicated.
+ PROPERTY_USAGE_HIGH_END_GFX = 1 << 20,
+ PROPERTY_USAGE_NODE_PATH_FROM_SCENE_ROOT = 1 << 21,
+ PROPERTY_USAGE_RESOURCE_NOT_PERSISTENT = 1 << 22,
+ PROPERTY_USAGE_KEYING_INCREMENTS = 1 << 23, // Used in inspector to increment property when keyed in animation player.
+ PROPERTY_USAGE_DEFERRED_SET_RESOURCE = 1 << 24, // when loading, the resource for this property can be set at the end of loading.
+ PROPERTY_USAGE_EDITOR_INSTANTIATE_OBJECT = 1 << 25, // For Object properties, instantiate them when creating in editor.
+ PROPERTY_USAGE_EDITOR_BASIC_SETTING = 1 << 26, //for project or editor settings, show when basic settings are selected.
+ PROPERTY_USAGE_READ_ONLY = 1 << 27, // Mark a property as read-only in the inspector.
+ PROPERTY_USAGE_ARRAY = 1 << 28, // 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_DEFAULT | PROPERTY_USAGE_INTERNATIONALIZED,
@@ -151,6 +148,10 @@ enum PropertyUsageFlags {
#define ADD_ARRAY_COUNT_WITH_USAGE_FLAGS(m_label, m_count_property, m_count_property_setter, m_count_property_getter, m_prefix, m_property_usage_flags) ClassDB::add_property_array_count(get_class_static(), m_label, m_count_property, _scs_create(m_count_property_setter), _scs_create(m_count_property_getter), m_prefix, m_property_usage_flags)
#define ADD_ARRAY(m_array_path, m_prefix) ClassDB::add_property_array(get_class_static(), m_array_path, m_prefix)
+// Helper macro to use with PROPERTY_HINT_ARRAY_TYPE for arrays of specific resources:
+// PropertyInfo(Variant::ARRAY, "fallbacks", PROPERTY_HINT_ARRAY_TYPE, MAKE_RESOURCE_TYPE_HINT("Font")
+#define MAKE_RESOURCE_TYPE_HINT(m_type) vformat("%s/%s:%s", Variant::OBJECT, PROPERTY_HINT_RESOURCE_TYPE, m_type)
+
struct PropertyInfo {
Variant::Type type = Variant::NIL;
String name;
@@ -190,7 +191,7 @@ struct PropertyInfo {
type(Variant::OBJECT),
class_name(p_class_name) {}
- explicit PropertyInfo(const GDNativePropertyInfo &pinfo) :
+ explicit PropertyInfo(const GDExtensionPropertyInfo &pinfo) :
type((Variant::Type)pinfo.type),
name(*reinterpret_cast<StringName *>(pinfo.name)),
class_name(*reinterpret_cast<StringName *>(pinfo.class_name)),
@@ -242,7 +243,7 @@ struct MethodInfo {
MethodInfo() {}
- explicit MethodInfo(const GDNativeMethodInfo &pinfo) :
+ explicit MethodInfo(const GDExtensionMethodInfo &pinfo) :
name(*reinterpret_cast<StringName *>(pinfo.name)),
return_val(PropertyInfo(pinfo.return_value)),
flags(pinfo.flags),
@@ -300,31 +301,31 @@ struct MethodInfo {
}
};
-// API used to extend in GDNative and other C compatible compiled languages.
+// API used to extend in GDExtension and other C compatible compiled languages.
class MethodBind;
-struct ObjectNativeExtension {
- ObjectNativeExtension *parent = nullptr;
- List<ObjectNativeExtension *> children;
+struct ObjectGDExtension {
+ ObjectGDExtension *parent = nullptr;
+ List<ObjectGDExtension *> children;
StringName parent_class_name;
StringName class_name;
bool editor_class = false;
bool is_virtual = false;
bool is_abstract = false;
- GDNativeExtensionClassSet set;
- GDNativeExtensionClassGet get;
- GDNativeExtensionClassGetPropertyList get_property_list;
- GDNativeExtensionClassFreePropertyList free_property_list;
- GDNativeExtensionClassPropertyCanRevert property_can_revert;
- GDNativeExtensionClassPropertyGetRevert property_get_revert;
- GDNativeExtensionClassNotification notification;
- GDNativeExtensionClassToString to_string;
- GDNativeExtensionClassReference reference;
- GDNativeExtensionClassReference unreference;
- GDNativeExtensionClassGetRID get_rid;
+ GDExtensionClassSet set;
+ GDExtensionClassGet get;
+ GDExtensionClassGetPropertyList get_property_list;
+ GDExtensionClassFreePropertyList free_property_list;
+ GDExtensionClassPropertyCanRevert property_can_revert;
+ GDExtensionClassPropertyGetRevert property_get_revert;
+ GDExtensionClassNotification notification;
+ GDExtensionClassToString to_string;
+ GDExtensionClassReference reference;
+ GDExtensionClassReference unreference;
+ GDExtensionClassGetRID get_rid;
_FORCE_INLINE_ bool is_class(const String &p_class) const {
- const ObjectNativeExtension *e = this;
+ const ObjectGDExtension *e = this;
while (e) {
if (p_class == e->class_name.operator String()) {
return true;
@@ -335,9 +336,9 @@ struct ObjectNativeExtension {
}
void *class_userdata = nullptr;
- GDNativeExtensionClassCreateInstance create_instance;
- GDNativeExtensionClassFreeInstance free_instance;
- GDNativeExtensionClassGetVirtual get_virtual;
+ GDExtensionClassCreateInstance create_instance;
+ GDExtensionClassFreeInstance free_instance;
+ GDExtensionClassGetVirtual get_virtual;
};
#define GDVIRTUAL_CALL(m_name, ...) _gdvirtual_##m_name##_call<false>(__VA_ARGS__)
@@ -555,6 +556,7 @@ public:
CONNECT_PERSIST = 2, // hint for scene to save this connection
CONNECT_ONE_SHOT = 4,
CONNECT_REFERENCE_COUNTED = 8,
+ CONNECT_INHERITED = 16, // Used in editor builds.
};
struct Connection {
@@ -577,7 +579,7 @@ private:
friend bool predelete_handler(Object *);
friend void postinitialize_handler(Object *);
- ObjectNativeExtension *_extension = nullptr;
+ ObjectGDExtension *_extension = nullptr;
GDExtensionClassInstancePtr _extension_instance = nullptr;
struct SignalData {
@@ -635,8 +637,8 @@ private:
struct InstanceBinding {
void *binding = nullptr;
void *token = nullptr;
- GDNativeInstanceBindingFreeCallback free_callback = nullptr;
- GDNativeInstanceBindingReferenceCallback reference_callback = nullptr;
+ GDExtensionInstanceBindingFreeCallback free_callback = nullptr;
+ GDExtensionInstanceBindingReferenceCallback reference_callback = nullptr;
};
InstanceBinding *_instance_bindings = nullptr;
uint32_t _instance_binding_count = 0;
@@ -660,8 +662,8 @@ protected:
return can_die;
}
- friend class NativeExtensionMethodBind;
- _ALWAYS_INLINE_ const ObjectNativeExtension *_get_extension() const { return _extension; }
+ friend class GDExtensionMethodBind;
+ _ALWAYS_INLINE_ const ObjectGDExtension *_get_extension() const { return _extension; }
_ALWAYS_INLINE_ GDExtensionClassInstancePtr _get_extension_instance() const { return _extension_instance; }
virtual void _initialize_classv() { initialize_class(); }
virtual bool _setv(const StringName &p_name, const Variant &p_property) { return false; };
@@ -915,9 +917,9 @@ public:
#endif
// Used by script languages to store binding data.
- void *get_instance_binding(void *p_token, const GDNativeInstanceBindingCallbacks *p_callbacks);
+ void *get_instance_binding(void *p_token, const GDExtensionInstanceBindingCallbacks *p_callbacks);
// Used on creation by binding only.
- void set_instance_binding(void *p_token, void *p_binding, const GDNativeInstanceBindingCallbacks *p_callbacks);
+ void set_instance_binding(void *p_token, void *p_binding, const GDExtensionInstanceBindingCallbacks *p_callbacks);
bool has_instance_binding(void *p_token);
void clear_internal_resource_paths();
diff --git a/core/object/ref_counted.h b/core/object/ref_counted.h
index 71790fb825..411c589739 100644
--- a/core/object/ref_counted.h
+++ b/core/object/ref_counted.h
@@ -253,12 +253,14 @@ public:
template <class T>
struct PtrToArg<Ref<T>> {
_FORCE_INLINE_ static Ref<T> convert(const void *p_ptr) {
+ // p_ptr points to a RefCounted object
return Ref<T>(const_cast<T *>(reinterpret_cast<const T *>(p_ptr)));
}
typedef Ref<T> EncodeT;
_FORCE_INLINE_ static void encode(Ref<T> p_val, const void *p_ptr) {
+ // p_ptr points to an EncodeT object which is a Ref<T> object.
*(const_cast<Ref<RefCounted> *>(reinterpret_cast<const Ref<RefCounted> *>(p_ptr))) = p_val;
}
};
@@ -268,6 +270,7 @@ struct PtrToArg<const Ref<T> &> {
typedef Ref<T> EncodeT;
_FORCE_INLINE_ static Ref<T> convert(const void *p_ptr) {
+ // p_ptr points to a RefCounted object
return Ref<T>((T *)p_ptr);
}
};
diff --git a/core/object/script_language.cpp b/core/object/script_language.cpp
index 056c57a5f1..36a0d03aaf 100644
--- a/core/object/script_language.cpp
+++ b/core/object/script_language.cpp
@@ -409,7 +409,9 @@ bool PlaceHolderScriptInstance::set(const StringName &p_name, const Variant &p_v
if (values.has(p_name)) {
Variant defval;
if (script->get_property_default_value(p_name, defval)) {
- if (defval == p_value) {
+ // The evaluate function ensures that a NIL variant is equal to e.g. an empty Resource.
+ // Simply doing defval == p_value does not do this.
+ if (Variant::evaluate(Variant::OP_EQUAL, defval, p_value)) {
values.erase(p_name);
return true;
}
@@ -419,7 +421,7 @@ bool PlaceHolderScriptInstance::set(const StringName &p_name, const Variant &p_v
} else {
Variant defval;
if (script->get_property_default_value(p_name, defval)) {
- if (defval != p_value) {
+ if (Variant::evaluate(Variant::OP_NOT_EQUAL, defval, p_value)) {
values[p_name] = p_value;
}
return true;
diff --git a/core/object/script_language_extension.h b/core/object/script_language_extension.h
index c287a6f71a..0ecd98152a 100644
--- a/core/object/script_language_extension.h
+++ b/core/object/script_language_extension.h
@@ -43,7 +43,7 @@ class ScriptExtension : public Script {
protected:
EXBIND0R(bool, editor_can_reload_from_file)
- GDVIRTUAL1(_placeholder_erased, GDNativePtr<void>)
+ GDVIRTUAL1(_placeholder_erased, GDExtensionPtr<void>)
virtual void _placeholder_erased(PlaceHolderScriptInstance *p_placeholder) override {
GDVIRTUAL_CALL(_placeholder_erased, p_placeholder);
}
@@ -56,15 +56,15 @@ public:
EXBIND1RC(bool, inherits_script, const Ref<Script> &)
EXBIND0RC(StringName, get_instance_base_type)
- GDVIRTUAL1RC(GDNativePtr<void>, _instance_create, Object *)
+ GDVIRTUAL1RC(GDExtensionPtr<void>, _instance_create, Object *)
virtual ScriptInstance *instance_create(Object *p_this) override {
- GDNativePtr<void> ret = nullptr;
+ GDExtensionPtr<void> ret = nullptr;
GDVIRTUAL_REQUIRED_CALL(_instance_create, p_this, ret);
return reinterpret_cast<ScriptInstance *>(ret.operator void *());
}
- GDVIRTUAL1RC(GDNativePtr<void>, _placeholder_instance_create, Object *)
+ GDVIRTUAL1RC(GDExtensionPtr<void>, _placeholder_instance_create, Object *)
PlaceHolderScriptInstance *placeholder_instance_create(Object *p_this) override {
- GDNativePtr<void> ret = nullptr;
+ GDExtensionPtr<void> ret = nullptr;
GDVIRTUAL_REQUIRED_CALL(_placeholder_instance_create, p_this, ret);
return reinterpret_cast<PlaceHolderScriptInstance *>(ret.operator void *());
}
@@ -482,10 +482,10 @@ public:
}
}
}
- GDVIRTUAL1R(GDNativePtr<void>, _debug_get_stack_level_instance, int)
+ GDVIRTUAL1R(GDExtensionPtr<void>, _debug_get_stack_level_instance, int)
virtual ScriptInstance *debug_get_stack_level_instance(int p_level) override {
- GDNativePtr<void> ret = nullptr;
+ GDExtensionPtr<void> ret = nullptr;
GDVIRTUAL_REQUIRED_CALL(_debug_get_stack_level_instance, p_level, ret);
return reinterpret_cast<ScriptInstance *>(ret.operator void *());
}
@@ -578,7 +578,7 @@ public:
EXBIND0(profiling_start)
EXBIND0(profiling_stop)
- GDVIRTUAL2R(int, _profiling_get_accumulated_data, GDNativePtr<ScriptLanguageExtensionProfilingInfo>, int)
+ GDVIRTUAL2R(int, _profiling_get_accumulated_data, GDExtensionPtr<ScriptLanguageExtensionProfilingInfo>, int)
virtual int profiling_get_accumulated_data(ProfilingInfo *p_info_arr, int p_info_max) override {
int ret = 0;
@@ -586,7 +586,7 @@ public:
return ret;
}
- GDVIRTUAL2R(int, _profiling_get_frame_data, GDNativePtr<ScriptLanguageExtensionProfilingInfo>, int)
+ GDVIRTUAL2R(int, _profiling_get_frame_data, GDExtensionPtr<ScriptLanguageExtensionProfilingInfo>, int)
virtual int profiling_get_frame_data(ProfilingInfo *p_info_arr, int p_info_max) override {
int ret = 0;
@@ -594,15 +594,15 @@ public:
return ret;
}
- GDVIRTUAL1R(GDNativePtr<void>, _alloc_instance_binding_data, Object *)
+ GDVIRTUAL1R(GDExtensionPtr<void>, _alloc_instance_binding_data, Object *)
virtual void *alloc_instance_binding_data(Object *p_object) override {
- GDNativePtr<void> ret = nullptr;
+ GDExtensionPtr<void> ret = nullptr;
GDVIRTUAL_REQUIRED_CALL(_alloc_instance_binding_data, p_object, ret);
return ret.operator void *();
}
- GDVIRTUAL1(_free_instance_binding_data, GDNativePtr<void>)
+ GDVIRTUAL1(_free_instance_binding_data, GDExtensionPtr<void>)
virtual void free_instance_binding_data(void *p_data) override {
GDVIRTUAL_REQUIRED_CALL(_free_instance_binding_data, p_data);
@@ -639,8 +639,8 @@ VARIANT_ENUM_CAST(ScriptLanguageExtension::CodeCompletionLocation)
class ScriptInstanceExtension : public ScriptInstance {
public:
- const GDNativeExtensionScriptInstanceInfo *native_info;
- GDNativeExtensionScriptInstanceDataPtr instance = nullptr;
+ const GDExtensionScriptInstanceInfo *native_info;
+ GDExtensionScriptInstanceDataPtr instance = nullptr;
// There should not be warnings on explicit casts.
#if defined(__GNUC__) && !defined(__clang__)
@@ -650,20 +650,20 @@ public:
virtual bool set(const StringName &p_name, const Variant &p_value) override {
if (native_info->set_func) {
- return native_info->set_func(instance, (const GDNativeStringNamePtr)&p_name, (const GDNativeVariantPtr)&p_value);
+ return native_info->set_func(instance, (GDExtensionConstStringNamePtr)&p_name, (GDExtensionConstVariantPtr)&p_value);
}
return false;
}
virtual bool get(const StringName &p_name, Variant &r_ret) const override {
if (native_info->get_func) {
- return native_info->get_func(instance, (const GDNativeStringNamePtr)&p_name, (GDNativeVariantPtr)&r_ret);
+ return native_info->get_func(instance, (GDExtensionConstStringNamePtr)&p_name, (GDExtensionVariantPtr)&r_ret);
}
return false;
}
virtual void get_property_list(List<PropertyInfo> *p_list) const override {
if (native_info->get_property_list_func) {
uint32_t pcount;
- const GDNativePropertyInfo *pinfo = native_info->get_property_list_func(instance, &pcount);
+ const GDExtensionPropertyInfo *pinfo = native_info->get_property_list_func(instance, &pcount);
#ifdef TOOLS_ENABLED
Ref<Script> script = get_script();
@@ -681,32 +681,26 @@ public:
}
}
virtual Variant::Type get_property_type(const StringName &p_name, bool *r_is_valid = nullptr) const override {
- Variant::Type type = Variant::Type::NIL;
- if (native_info->get_property_list_func) {
- uint32_t pcount;
- const GDNativePropertyInfo *pinfo = native_info->get_property_list_func(instance, &pcount);
- for (uint32_t i = 0; i < pcount; i++) {
- if (p_name == *reinterpret_cast<StringName *>(pinfo->name)) {
- type = Variant::Type(pinfo->type);
- break;
- }
- }
- if (native_info->free_property_list_func) {
- native_info->free_property_list_func(instance, pinfo);
+ if (native_info->get_property_type_func) {
+ GDExtensionBool is_valid = 0;
+ GDExtensionVariantType type = native_info->get_property_type_func(instance, (GDExtensionConstStringNamePtr)&p_name, &is_valid);
+ if (r_is_valid) {
+ *r_is_valid = is_valid != 0;
}
+ return Variant::Type(type);
}
- return type;
+ return Variant::NIL;
}
virtual bool property_can_revert(const StringName &p_name) const override {
if (native_info->property_can_revert_func) {
- return native_info->property_can_revert_func(instance, (const GDNativeStringNamePtr)&p_name);
+ return native_info->property_can_revert_func(instance, (GDExtensionConstStringNamePtr)&p_name);
}
return false;
}
virtual bool property_get_revert(const StringName &p_name, Variant &r_ret) const override {
if (native_info->property_get_revert_func) {
- return native_info->property_get_revert_func(instance, (const GDNativeStringNamePtr)&p_name, (GDNativeVariantPtr)&r_ret);
+ return native_info->property_get_revert_func(instance, (GDExtensionConstStringNamePtr)&p_name, (GDExtensionVariantPtr)&r_ret);
}
return false;
}
@@ -717,7 +711,7 @@ public:
}
return nullptr;
}
- static void _add_property_with_state(const GDNativeStringNamePtr p_name, const GDNativeVariantPtr p_value, void *p_userdata) {
+ static void _add_property_with_state(GDExtensionConstStringNamePtr p_name, GDExtensionConstVariantPtr p_value, void *p_userdata) {
List<Pair<StringName, Variant>> *state = (List<Pair<StringName, Variant>> *)p_userdata;
state->push_back(Pair<StringName, Variant>(*(const StringName *)p_name, *(const Variant *)p_value));
}
@@ -730,7 +724,7 @@ public:
virtual void get_method_list(List<MethodInfo> *p_list) const override {
if (native_info->get_method_list_func) {
uint32_t mcount;
- const GDNativeMethodInfo *minfo = native_info->get_method_list_func(instance, &mcount);
+ const GDExtensionMethodInfo *minfo = native_info->get_method_list_func(instance, &mcount);
for (uint32_t i = 0; i < mcount; i++) {
p_list->push_back(MethodInfo(minfo[i]));
}
@@ -741,7 +735,7 @@ public:
}
virtual bool has_method(const StringName &p_method) const override {
if (native_info->has_method_func) {
- return native_info->has_method_func(instance, (GDNativeStringNamePtr)&p_method);
+ return native_info->has_method_func(instance, (GDExtensionStringNamePtr)&p_method);
}
return false;
}
@@ -749,8 +743,8 @@ public:
virtual Variant callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) override {
Variant ret;
if (native_info->call_func) {
- GDNativeCallError ce;
- native_info->call_func(instance, (const GDNativeStringNamePtr)&p_method, (const GDNativeVariantPtr *)p_args, p_argcount, (GDNativeVariantPtr)&ret, &ce);
+ GDExtensionCallError ce;
+ native_info->call_func(instance, (GDExtensionConstStringNamePtr)&p_method, (GDExtensionConstVariantPtr *)p_args, p_argcount, (GDExtensionVariantPtr)&ret, &ce);
r_error.error = Callable::CallError::Error(ce.error);
r_error.argument = ce.argument;
r_error.expected = ce.expected;
@@ -765,9 +759,9 @@ public:
}
virtual String to_string(bool *r_valid) override {
if (native_info->to_string_func) {
- GDNativeBool valid;
+ GDExtensionBool valid;
String ret;
- native_info->to_string_func(instance, &valid, reinterpret_cast<GDNativeStringPtr>(&ret));
+ native_info->to_string_func(instance, &valid, reinterpret_cast<GDExtensionStringPtr>(&ret));
if (r_valid) {
*r_valid = valid != 0;
}
@@ -790,7 +784,7 @@ public:
virtual Ref<Script> get_script() const override {
if (native_info->get_script_func) {
- GDNativeObjectPtr script = native_info->get_script_func(instance);
+ GDExtensionObjectPtr script = native_info->get_script_func(instance);
return Ref<Script>(reinterpret_cast<Script *>(script));
}
return Ref<Script>();
@@ -805,7 +799,7 @@ public:
virtual void property_set_fallback(const StringName &p_name, const Variant &p_value, bool *r_valid) override {
if (native_info->set_fallback_func) {
- bool ret = native_info->set_fallback_func(instance, (const GDNativeStringNamePtr)&p_name, (const GDNativeVariantPtr)&p_value);
+ bool ret = native_info->set_fallback_func(instance, (GDExtensionConstStringNamePtr)&p_name, (GDExtensionConstVariantPtr)&p_value);
if (r_valid) {
*r_valid = ret;
}
@@ -814,7 +808,7 @@ public:
virtual Variant property_get_fallback(const StringName &p_name, bool *r_valid) override {
Variant ret;
if (native_info->get_fallback_func) {
- bool valid = native_info->get_fallback_func(instance, (const GDNativeStringNamePtr)&p_name, (GDNativeVariantPtr)&ret);
+ bool valid = native_info->get_fallback_func(instance, (GDExtensionConstStringNamePtr)&p_name, (GDExtensionVariantPtr)&ret);
if (r_valid) {
*r_valid = valid;
}
@@ -824,7 +818,7 @@ public:
virtual ScriptLanguage *get_language() override {
if (native_info->get_language_func) {
- GDNativeExtensionScriptLanguagePtr lang = native_info->get_language_func(instance);
+ GDExtensionScriptLanguagePtr lang = native_info->get_language_func(instance);
return reinterpret_cast<ScriptLanguage *>(lang);
}
return nullptr;
diff --git a/core/object/undo_redo.cpp b/core/object/undo_redo.cpp
index aa66e86bc0..9f8a1de697 100644
--- a/core/object/undo_redo.cpp
+++ b/core/object/undo_redo.cpp
@@ -423,6 +423,10 @@ String UndoRedo::get_current_action_name() const {
return actions[current_action].name;
}
+int UndoRedo::get_action_level() const {
+ return action_level;
+}
+
bool UndoRedo::has_undo() const {
return current_action >= 0;
}
diff --git a/core/object/undo_redo.h b/core/object/undo_redo.h
index c7c58697c3..9c6d2d10ed 100644
--- a/core/object/undo_redo.h
+++ b/core/object/undo_redo.h
@@ -120,6 +120,7 @@ public:
bool redo();
bool undo();
String get_current_action_name() const;
+ int get_action_level() const;
int get_history_count();
int get_current_action();
diff --git a/core/object/worker_thread_pool.cpp b/core/object/worker_thread_pool.cpp
index 9b3dc6833e..0218a4c8f6 100644
--- a/core/object/worker_thread_pool.cpp
+++ b/core/object/worker_thread_pool.cpp
@@ -402,7 +402,9 @@ void WorkerThreadPool::wait_for_group_task_completion(GroupID p_group) {
}
}
- groups.erase(p_group); // Threads do not access this, so safe to erase here.
+ task_mutex.lock(); // This mutex is needed when Physics 2D and/or 3D is selected to run on a separate thread.
+ groups.erase(p_group);
+ task_mutex.unlock();
}
void WorkerThreadPool::init(int p_thread_count, bool p_use_native_threads_low_priority, float p_low_priority_task_ratio) {
diff --git a/core/os/os.cpp b/core/os/os.cpp
index bbb2a94fe7..6b199e883f 100644
--- a/core/os/os.cpp
+++ b/core/os/os.cpp
@@ -155,10 +155,6 @@ int OS::get_process_id() const {
return -1;
}
-void OS::vibrate_handheld(int p_duration_ms) {
- WARN_PRINT("vibrate_handheld() only works with Android, iOS and Web");
-}
-
bool OS::is_stdout_verbose() const {
return _verbose_stdout;
}
@@ -353,20 +349,36 @@ bool OS::has_feature(const String &p_feature) {
if (p_feature == "debug") {
return true;
}
+#endif // DEBUG_ENABLED
+
+#ifdef TOOLS_ENABLED
+ if (p_feature == "editor") {
+ return true;
+ }
#else
- if (p_feature == "release") {
+ if (p_feature == "template") {
return true;
}
-#endif
-#ifdef TOOLS_ENABLED
- if (p_feature == "editor") {
+#ifdef DEBUG_ENABLED
+ if (p_feature == "template_debug") {
return true;
}
#else
- if (p_feature == "standalone") {
+ if (p_feature == "template_release" || p_feature == "release") {
return true;
}
-#endif
+#endif // DEBUG_ENABLED
+#endif // TOOLS_ENABLED
+
+#ifdef REAL_T_IS_DOUBLE
+ if (p_feature == "double") {
+ return true;
+ }
+#else
+ if (p_feature == "single") {
+ return true;
+ }
+#endif // REAL_T_IS_DOUBLE
if (sizeof(void *) == 8 && p_feature == "64") {
return true;
diff --git a/core/os/os.h b/core/os/os.h
index af7b40f3ec..07e9020a51 100644
--- a/core/os/os.h
+++ b/core/os/os.h
@@ -150,7 +150,8 @@ public:
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_system_font_path(const String &p_font_name, int p_weight = 400, int p_stretch = 100, bool p_italic = false) const { return String(); };
+ virtual Vector<String> get_system_font_path_for_text(const String &p_font_name, const String &p_text, const String &p_locale = String(), const String &p_script = String(), int p_weight = 400, int p_stretch = 100, bool p_italic = false) const { return Vector<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;
@@ -158,7 +159,7 @@ public:
virtual Error kill(const ProcessID &p_pid) = 0;
virtual int get_process_id() const;
virtual bool is_process_running(const ProcessID &p_pid) const = 0;
- virtual void vibrate_handheld(int p_duration_ms = 500);
+ virtual void vibrate_handheld(int p_duration_ms = 500) {}
virtual Error shell_open(String p_uri);
virtual Error set_cwd(const String &p_cwd);
diff --git a/core/register_core_types.cpp b/core/register_core_types.cpp
index 2e144a4c9a..7a7e45f752 100644
--- a/core/register_core_types.cpp
+++ b/core/register_core_types.cpp
@@ -38,8 +38,8 @@
#include "core/crypto/crypto.h"
#include "core/crypto/hashing_context.h"
#include "core/debugger/engine_profiler.h"
-#include "core/extension/native_extension.h"
-#include "core/extension/native_extension_manager.h"
+#include "core/extension/gdextension.h"
+#include "core/extension/gdextension_manager.h"
#include "core/input/input.h"
#include "core/input/input_map.h"
#include "core/input/shortcut.h"
@@ -88,7 +88,7 @@ static Ref<ResourceFormatLoaderImage> resource_format_image;
static Ref<TranslationLoaderPO> resource_format_po;
static Ref<ResourceFormatSaverCrypto> resource_format_saver_crypto;
static Ref<ResourceFormatLoaderCrypto> resource_format_loader_crypto;
-static Ref<NativeExtensionResourceLoader> resource_loader_native_extension;
+static Ref<GDExtensionResourceLoader> resource_loader_gdextension;
static Ref<ResourceFormatSaverJSON> resource_saver_json;
static Ref<ResourceFormatLoaderJSON> resource_loader_json;
@@ -109,7 +109,7 @@ static WorkerThreadPool *worker_thread_pool = nullptr;
extern Mutex _global_mutex;
-static NativeExtensionManager *native_extension_manager = nullptr;
+static GDExtensionManager *gdextension_manager = nullptr;
extern void register_global_constants();
extern void unregister_global_constants();
@@ -256,9 +256,9 @@ void register_core_types() {
GDREGISTER_CLASS(ImageFormatLoaderExtension);
GDREGISTER_ABSTRACT_CLASS(ResourceImporter);
- GDREGISTER_CLASS(NativeExtension);
+ GDREGISTER_CLASS(GDExtension);
- GDREGISTER_ABSTRACT_CLASS(NativeExtensionManager);
+ GDREGISTER_ABSTRACT_CLASS(GDExtensionManager);
GDREGISTER_ABSTRACT_CLASS(ResourceUID);
@@ -266,10 +266,10 @@ void register_core_types() {
resource_uid = memnew(ResourceUID);
- native_extension_manager = memnew(NativeExtensionManager);
+ gdextension_manager = memnew(GDExtensionManager);
- resource_loader_native_extension.instantiate();
- ResourceLoader::add_resource_format_loader(resource_loader_native_extension);
+ resource_loader_gdextension.instantiate();
+ ResourceLoader::add_resource_format_loader(resource_loader_gdextension);
ip = IP::create();
@@ -344,27 +344,27 @@ void register_core_singletons() {
Engine::get_singleton()->add_singleton(Engine::Singleton("InputMap", InputMap::get_singleton()));
Engine::get_singleton()->add_singleton(Engine::Singleton("EngineDebugger", core_bind::EngineDebugger::get_singleton()));
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("GDExtensionManager", GDExtensionManager::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() {
// Hardcoded for now.
- NativeExtension::initialize_native_extensions();
- native_extension_manager->load_extensions();
- native_extension_manager->initialize_extensions(NativeExtension::INITIALIZATION_LEVEL_CORE);
+ GDExtension::initialize_gdextensions();
+ gdextension_manager->load_extensions();
+ gdextension_manager->initialize_extensions(GDExtension::INITIALIZATION_LEVEL_CORE);
_is_core_extensions_registered = true;
}
void unregister_core_extensions() {
if (_is_core_extensions_registered) {
- native_extension_manager->deinitialize_extensions(NativeExtension::INITIALIZATION_LEVEL_CORE);
+ gdextension_manager->deinitialize_extensions(GDExtension::INITIALIZATION_LEVEL_CORE);
}
}
void unregister_core_types() {
- memdelete(native_extension_manager);
+ memdelete(gdextension_manager);
memdelete(resource_uid);
memdelete(_resource_loader);
@@ -410,8 +410,8 @@ void unregister_core_types() {
memdelete(ip);
}
- ResourceLoader::remove_resource_format_loader(resource_loader_native_extension);
- resource_loader_native_extension.unref();
+ ResourceLoader::remove_resource_format_loader(resource_loader_gdextension);
+ resource_loader_gdextension.unref();
ResourceLoader::finalize();
diff --git a/core/string/optimized_translation.cpp b/core/string/optimized_translation.cpp
index b130c2fc79..2fb3b54e27 100644
--- a/core/string/optimized_translation.cpp
+++ b/core/string/optimized_translation.cpp
@@ -267,6 +267,39 @@ StringName OptimizedTranslation::get_message(const StringName &p_src_text, const
}
}
+Vector<String> OptimizedTranslation::get_translated_message_list() const {
+ Vector<String> msgs;
+
+ const int *htr = hash_table.ptr();
+ const uint32_t *htptr = (const uint32_t *)&htr[0];
+ const int *btr = bucket_table.ptr();
+ const uint32_t *btptr = (const uint32_t *)&btr[0];
+ const uint8_t *sr = strings.ptr();
+ const char *sptr = (const char *)&sr[0];
+
+ for (int i = 0; i < hash_table.size(); i++) {
+ uint32_t p = htptr[i];
+ if (p != 0xFFFFFFFF) {
+ const Bucket &bucket = *(const Bucket *)&btptr[p];
+ for (int j = 0; j < bucket.size; j++) {
+ if (bucket.elem[j].comp_size == bucket.elem[j].uncomp_size) {
+ String rstr;
+ rstr.parse_utf8(&sptr[bucket.elem[j].str_offset], bucket.elem[j].uncomp_size);
+ msgs.push_back(rstr);
+ } else {
+ CharString uncomp;
+ uncomp.resize(bucket.elem[j].uncomp_size + 1);
+ smaz_decompress(&sptr[bucket.elem[j].str_offset], bucket.elem[j].comp_size, uncomp.ptrw(), bucket.elem[j].uncomp_size);
+ String rstr;
+ rstr.parse_utf8(uncomp.get_data());
+ msgs.push_back(rstr);
+ }
+ }
+ }
+ }
+ return msgs;
+}
+
StringName OptimizedTranslation::get_plural_message(const StringName &p_src_text, const StringName &p_plural_text, int p_n, const StringName &p_context) const {
// The use of plurals translation is not yet supported in OptimizedTranslation.
return get_message(p_src_text, p_context);
diff --git a/core/string/optimized_translation.h b/core/string/optimized_translation.h
index f3dbfe8f5c..1cd12782d0 100644
--- a/core/string/optimized_translation.h
+++ b/core/string/optimized_translation.h
@@ -81,6 +81,7 @@ protected:
public:
virtual StringName get_message(const StringName &p_src_text, const StringName &p_context = "") const override; //overridable for other implementations
virtual StringName get_plural_message(const StringName &p_src_text, const StringName &p_plural_text, int p_n, const StringName &p_context = "") const override;
+ virtual Vector<String> get_translated_message_list() const override;
void generate(const Ref<Translation> &p_from);
OptimizedTranslation() {}
diff --git a/core/string/string_name.cpp b/core/string/string_name.cpp
index 9c4fc4e1b7..64d49b8b93 100644
--- a/core/string/string_name.cpp
+++ b/core/string/string_name.cpp
@@ -169,6 +169,10 @@ bool StringName::operator!=(const String &p_name) const {
return !(operator==(p_name));
}
+bool StringName::operator!=(const char *p_name) const {
+ return !(operator==(p_name));
+}
+
bool StringName::operator!=(const StringName &p_name) const {
// the real magic of all this mess happens here.
// this is why path comparisons are very fast
diff --git a/core/string/string_name.h b/core/string/string_name.h
index ff4c41af94..6a2420e02a 100644
--- a/core/string/string_name.h
+++ b/core/string/string_name.h
@@ -102,6 +102,7 @@ public:
bool operator==(const String &p_name) const;
bool operator==(const char *p_name) const;
bool operator!=(const String &p_name) const;
+ bool operator!=(const char *p_name) const;
_FORCE_INLINE_ bool is_node_unique_name() const {
if (!_data) {
diff --git a/core/string/translation.cpp b/core/string/translation.cpp
index 2bed3543dc..d1ac91957a 100644
--- a/core/string/translation.cpp
+++ b/core/string/translation.cpp
@@ -59,6 +59,18 @@ Vector<String> Translation::_get_message_list() const {
return msgs;
}
+Vector<String> Translation::get_translated_message_list() const {
+ Vector<String> msgs;
+ msgs.resize(translation_map.size());
+ int idx = 0;
+ for (const KeyValue<StringName, StringName> &E : translation_map) {
+ msgs.set(idx, E.value);
+ idx += 1;
+ }
+
+ return msgs;
+}
+
void Translation::_set_messages(const Dictionary &p_messages) {
List<Variant> keys;
p_messages.get_key_list(&keys);
@@ -140,6 +152,7 @@ void Translation::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_plural_message", "src_message", "src_plural_message", "n", "context"), &Translation::get_plural_message, DEFVAL(""));
ClassDB::bind_method(D_METHOD("erase_message", "src_message", "context"), &Translation::erase_message, DEFVAL(""));
ClassDB::bind_method(D_METHOD("get_message_list"), &Translation::_get_message_list);
+ ClassDB::bind_method(D_METHOD("get_translated_message_list"), &Translation::get_translated_message_list);
ClassDB::bind_method(D_METHOD("get_message_count"), &Translation::get_message_count);
ClassDB::bind_method(D_METHOD("_set_messages", "messages"), &Translation::_set_messages);
ClassDB::bind_method(D_METHOD("_get_messages"), &Translation::_get_messages);
diff --git a/core/string/translation.h b/core/string/translation.h
index 9a369b0b05..5e8344baac 100644
--- a/core/string/translation.h
+++ b/core/string/translation.h
@@ -64,6 +64,7 @@ public:
virtual void erase_message(const StringName &p_src_text, const StringName &p_context = "");
virtual void get_message_list(List<StringName> *r_messages) const;
virtual int get_message_count() const;
+ virtual Vector<String> get_translated_message_list() const;
Translation() {}
};
diff --git a/core/string/translation_po.cpp b/core/string/translation_po.cpp
index fa656b634d..724c1d42bc 100644
--- a/core/string/translation_po.cpp
+++ b/core/string/translation_po.cpp
@@ -103,6 +103,23 @@ void TranslationPO::_set_messages(const Dictionary &p_messages) {
}
}
+Vector<String> TranslationPO::get_translated_message_list() const {
+ Vector<String> msgs;
+ for (const KeyValue<StringName, HashMap<StringName, Vector<StringName>>> &E : translation_map) {
+ if (E.key != StringName()) {
+ continue;
+ }
+
+ for (const KeyValue<StringName, Vector<StringName>> &E2 : E.value) {
+ for (const StringName &E3 : E2.value) {
+ msgs.push_back(E3);
+ }
+ }
+ }
+
+ return msgs;
+}
+
Vector<String> TranslationPO::_get_message_list() const {
// Return all keys in translation_map.
diff --git a/core/string/translation_po.h b/core/string/translation_po.h
index 7d63af2246..c50ea85744 100644
--- a/core/string/translation_po.h
+++ b/core/string/translation_po.h
@@ -70,6 +70,7 @@ protected:
static void _bind_methods();
public:
+ Vector<String> get_translated_message_list() const override;
void get_message_list(List<StringName> *r_messages) const override;
int get_message_count() const override;
void add_message(const StringName &p_src_text, const StringName &p_xlated_text, const StringName &p_context = "") override;
diff --git a/core/string/ustring.cpp b/core/string/ustring.cpp
index 2ba389fc4d..adab6d07c7 100644
--- a/core/string/ustring.cpp
+++ b/core/string/ustring.cpp
@@ -161,6 +161,18 @@ bool CharString::operator<(const CharString &p_right) const {
return is_str_less(get_data(), p_right.get_data());
}
+bool CharString::operator==(const CharString &p_right) const {
+ if (length() == 0) {
+ // True if both have length 0, false if only p_right has a length
+ return p_right.length() == 0;
+ } else if (p_right.length() == 0) {
+ // False due to unequal length
+ return false;
+ }
+
+ return strcmp(ptr(), p_right.ptr()) == 0;
+}
+
CharString &CharString::operator+=(char p_char) {
const int lhs_len = length();
resize(lhs_len + 2);
@@ -208,37 +220,6 @@ void CharString::copy_from(const char *p_cstr) {
/* String */
/*************************************************************************/
-//kind of poor should be rewritten properly
-String String::word_wrap(int p_chars_per_line) const {
- int from = 0;
- int last_space = 0;
- String ret;
- for (int i = 0; i < length(); i++) {
- if (i - from >= p_chars_per_line) {
- if (last_space == -1) {
- ret += substr(from, i - from + 1) + "\n";
- } else {
- ret += substr(from, last_space - from) + "\n";
- i = last_space; //rewind
- }
- from = i + 1;
- last_space = -1;
- } else if (operator[](i) == ' ' || operator[](i) == '\t') {
- last_space = i;
- } else if (operator[](i) == '\n') {
- ret += substr(from, i - from) + "\n";
- from = i + 1;
- last_space = -1;
- }
- }
-
- if (from < length()) {
- ret += substr(from, length());
- }
-
- return ret;
-}
-
Error String::parse_url(String &r_scheme, String &r_host, int &r_port, String &r_path) const {
// Splits the URL into scheme, host, port, path. Strip credentials when present.
String base = *this;
@@ -1256,8 +1237,8 @@ Vector<String> String::rsplit(const String &p_splitter, bool p_allow_empty, int
return ret;
}
-Vector<float> String::split_floats(const String &p_splitter, bool p_allow_empty) const {
- Vector<float> ret;
+Vector<double> String::split_floats(const String &p_splitter, bool p_allow_empty) const {
+ Vector<double> ret;
int from = 0;
int len = length();
@@ -2839,7 +2820,7 @@ String String::substr(int p_from, int p_chars) const {
return String(*this);
}
- String s = String();
+ String s;
s.copy_from_unchecked(&get_data()[p_from], p_chars);
return s;
}
@@ -3922,7 +3903,6 @@ String String::c_unescape() const {
escaped = escaped.replace("\\v", "\v");
escaped = escaped.replace("\\'", "\'");
escaped = escaped.replace("\\\"", "\"");
- escaped = escaped.replace("\\?", "\?");
escaped = escaped.replace("\\\\", "\\");
return escaped;
@@ -3939,7 +3919,6 @@ String String::c_escape() const {
escaped = escaped.replace("\t", "\\t");
escaped = escaped.replace("\v", "\\v");
escaped = escaped.replace("\'", "\\'");
- escaped = escaped.replace("\?", "\\?");
escaped = escaped.replace("\"", "\\\"");
return escaped;
diff --git a/core/string/ustring.h b/core/string/ustring.h
index 8af74584f3..559f679f0f 100644
--- a/core/string/ustring.h
+++ b/core/string/ustring.h
@@ -156,6 +156,7 @@ public:
void operator=(const char *p_cstr);
bool operator<(const CharString &p_right) const;
+ bool operator==(const CharString &p_right) const;
CharString &operator+=(char p_char);
int length() const { return size() ? size() - 1 : 0; }
const char *get_data() const;
@@ -348,7 +349,7 @@ public:
Vector<String> split(const String &p_splitter = "", bool p_allow_empty = true, int p_maxsplit = 0) const;
Vector<String> rsplit(const String &p_splitter = "", bool p_allow_empty = true, int p_maxsplit = 0) const;
Vector<String> split_spaces() const;
- Vector<float> split_floats(const String &p_splitter, bool p_allow_empty = true) const;
+ Vector<double> split_floats(const String &p_splitter, bool p_allow_empty = true) const;
Vector<float> split_floats_mk(const Vector<String> &p_splitters, bool p_allow_empty = true) const;
Vector<int> split_ints(const String &p_splitter, bool p_allow_empty = true) const;
Vector<int> split_ints_mk(const Vector<String> &p_splitters, bool p_allow_empty = true) const;
@@ -424,7 +425,6 @@ public:
String c_escape_multiline() const;
String c_unescape() const;
String json_escape() const;
- String word_wrap(int p_chars_per_line) const;
Error parse_url(String &r_scheme, String &r_host, int &r_port, String &r_path) const;
String property_name_encode() const;
diff --git a/core/templates/hashfuncs.h b/core/templates/hashfuncs.h
index 456a7b01ed..059f30df38 100644
--- a/core/templates/hashfuncs.h
+++ b/core/templates/hashfuncs.h
@@ -310,6 +310,7 @@ struct HashMapHasherDefault {
static _FORCE_INLINE_ uint32_t hash(const char16_t p_uchar) { return hash_fmix32(p_uchar); }
static _FORCE_INLINE_ uint32_t hash(const char32_t p_uchar) { return hash_fmix32(p_uchar); }
static _FORCE_INLINE_ uint32_t hash(const RID &p_rid) { return hash_one_uint64(p_rid.get_id()); }
+ static _FORCE_INLINE_ uint32_t hash(const CharString &p_char_string) { return hash_djb2(p_char_string.ptr()); }
static _FORCE_INLINE_ uint32_t hash(const StringName &p_string_name) { return p_string_name.hash(); }
static _FORCE_INLINE_ uint32_t hash(const NodePath &p_path) { return p_path.hash(); }
static _FORCE_INLINE_ uint32_t hash(const ObjectID &p_id) { return hash_one_uint64(p_id); }
diff --git a/core/variant/array.cpp b/core/variant/array.cpp
index c6bbd43dc4..53891a9823 100644
--- a/core/variant/array.cpp
+++ b/core/variant/array.cpp
@@ -38,6 +38,7 @@
#include "core/templates/search_array.h"
#include "core/templates/vector.h"
#include "core/variant/callable.h"
+#include "core/variant/dictionary.h"
#include "core/variant/variant.h"
class ArrayPrivate {
@@ -201,16 +202,21 @@ uint32_t Array::recursive_hash(int recursion_count) const {
}
bool Array::_assign(const Array &p_array) {
+ bool can_convert = p_array._p->typed.type == Variant::NIL;
+ can_convert |= _p->typed.type == Variant::STRING && p_array._p->typed.type == Variant::STRING_NAME;
+ can_convert |= _p->typed.type == Variant::STRING_NAME && p_array._p->typed.type == Variant::STRING;
+
if (_p->typed.type != Variant::OBJECT && _p->typed.type == p_array._p->typed.type) {
//same type or untyped, just reference, should be fine
_ref(p_array);
} else if (_p->typed.type == Variant::NIL) { //from typed to untyped, must copy, but this is cheap anyway
_p->array = p_array._p->array;
- } else if (p_array._p->typed.type == Variant::NIL) { //from untyped to typed, must try to check if they are all valid
+ } else if (can_convert) { //from untyped to typed, must try to check if they are all valid
if (_p->typed.type == Variant::OBJECT) {
//for objects, it needs full validation, either can be converted or fail
for (int i = 0; i < p_array._p->array.size(); i++) {
- if (!_p->typed.validate(p_array._p->array[i], "assign")) {
+ const Variant &element = p_array._p->array[i];
+ if (element.get_type() != Variant::OBJECT || !_p->typed.validate_object(element, "assign")) {
return false;
}
}
@@ -255,16 +261,20 @@ void Array::operator=(const Array &p_array) {
void Array::push_back(const Variant &p_value) {
ERR_FAIL_COND_MSG(_p->read_only, "Array is in read-only state.");
- ERR_FAIL_COND(!_p->typed.validate(p_value, "push_back"));
- _p->array.push_back(p_value);
+ Variant value = p_value;
+ ERR_FAIL_COND(!_p->typed.validate(value, "push_back"));
+ _p->array.push_back(value);
}
void Array::append_array(const Array &p_array) {
ERR_FAIL_COND_MSG(_p->read_only, "Array is in read-only state.");
- for (int i = 0; i < p_array.size(); ++i) {
- ERR_FAIL_COND(!_p->typed.validate(p_array[i], "append_array"));
+
+ Vector<Variant> validated_array = p_array._p->array;
+ for (int i = 0; i < validated_array.size(); ++i) {
+ ERR_FAIL_COND(!_p->typed.validate(validated_array.write[i], "append_array"));
}
- _p->array.append_array(p_array._p->array);
+
+ _p->array.append_array(validated_array);
}
Error Array::resize(int p_new_size) {
@@ -274,20 +284,23 @@ Error Array::resize(int p_new_size) {
Error Array::insert(int p_pos, const Variant &p_value) {
ERR_FAIL_COND_V_MSG(_p->read_only, ERR_LOCKED, "Array is in read-only state.");
- ERR_FAIL_COND_V(!_p->typed.validate(p_value, "insert"), ERR_INVALID_PARAMETER);
- return _p->array.insert(p_pos, p_value);
+ Variant value = p_value;
+ ERR_FAIL_COND_V(!_p->typed.validate(value, "insert"), ERR_INVALID_PARAMETER);
+ return _p->array.insert(p_pos, value);
}
void Array::fill(const Variant &p_value) {
ERR_FAIL_COND_MSG(_p->read_only, "Array is in read-only state.");
- ERR_FAIL_COND(!_p->typed.validate(p_value, "fill"));
- _p->array.fill(p_value);
+ Variant value = p_value;
+ ERR_FAIL_COND(!_p->typed.validate(value, "fill"));
+ _p->array.fill(value);
}
void Array::erase(const Variant &p_value) {
ERR_FAIL_COND_MSG(_p->read_only, "Array is in read-only state.");
- ERR_FAIL_COND(!_p->typed.validate(p_value, "erase"));
- _p->array.erase(p_value);
+ Variant value = p_value;
+ ERR_FAIL_COND(!_p->typed.validate(value, "erase"));
+ _p->array.erase(value);
}
Variant Array::front() const {
@@ -306,15 +319,34 @@ Variant Array::pick_random() const {
}
int Array::find(const Variant &p_value, int p_from) const {
- ERR_FAIL_COND_V(!_p->typed.validate(p_value, "find"), -1);
- return _p->array.find(p_value, p_from);
+ if (_p->array.size() == 0) {
+ return -1;
+ }
+ Variant value = p_value;
+ ERR_FAIL_COND_V(!_p->typed.validate(value, "find"), -1);
+
+ int ret = -1;
+
+ if (p_from < 0 || size() == 0) {
+ return ret;
+ }
+
+ for (int i = p_from; i < size(); i++) {
+ if (StringLikeVariantComparator::compare(_p->array[i], value)) {
+ ret = i;
+ break;
+ }
+ }
+
+ return ret;
}
int Array::rfind(const Variant &p_value, int p_from) const {
if (_p->array.size() == 0) {
return -1;
}
- ERR_FAIL_COND_V(!_p->typed.validate(p_value, "rfind"), -1);
+ Variant value = p_value;
+ ERR_FAIL_COND_V(!_p->typed.validate(value, "rfind"), -1);
if (p_from < 0) {
// Relative offset from the end
@@ -326,7 +358,7 @@ int Array::rfind(const Variant &p_value, int p_from) const {
}
for (int i = p_from; i >= 0; i--) {
- if (_p->array[i] == p_value) {
+ if (StringLikeVariantComparator::compare(_p->array[i], value)) {
return i;
}
}
@@ -334,20 +366,16 @@ int Array::rfind(const Variant &p_value, int p_from) const {
return -1;
}
-int Array::find_last(const Variant &p_value) const {
- ERR_FAIL_COND_V(!_p->typed.validate(p_value, "find_last"), -1);
- return rfind(p_value);
-}
-
int Array::count(const Variant &p_value) const {
- ERR_FAIL_COND_V(!_p->typed.validate(p_value, "count"), 0);
+ Variant value = p_value;
+ ERR_FAIL_COND_V(!_p->typed.validate(value, "count"), 0);
if (_p->array.size() == 0) {
return 0;
}
int amount = 0;
for (int i = 0; i < _p->array.size(); i++) {
- if (_p->array[i] == p_value) {
+ if (StringLikeVariantComparator::compare(_p->array[i], value)) {
amount++;
}
}
@@ -356,9 +384,10 @@ int Array::count(const Variant &p_value) const {
}
bool Array::has(const Variant &p_value) const {
- ERR_FAIL_COND_V(!_p->typed.validate(p_value, "use 'has'"), false);
+ Variant value = p_value;
+ ERR_FAIL_COND_V(!_p->typed.validate(value, "use 'has'"), false);
- return _p->array.find(p_value, 0) != -1;
+ return find(value) != -1;
}
void Array::remove_at(int p_pos) {
@@ -368,9 +397,10 @@ void Array::remove_at(int p_pos) {
void Array::set(int p_idx, const Variant &p_value) {
ERR_FAIL_COND_MSG(_p->read_only, "Array is in read-only state.");
- ERR_FAIL_COND(!_p->typed.validate(p_value, "set"));
+ Variant value = p_value;
+ ERR_FAIL_COND(!_p->typed.validate(value, "set"));
- operator[](p_idx) = p_value;
+ operator[](p_idx) = value;
}
const Variant &Array::get(int p_idx) const {
@@ -593,15 +623,17 @@ void Array::shuffle() {
}
int Array::bsearch(const Variant &p_value, bool p_before) {
- ERR_FAIL_COND_V(!_p->typed.validate(p_value, "binary search"), -1);
+ Variant value = p_value;
+ ERR_FAIL_COND_V(!_p->typed.validate(value, "binary search"), -1);
SearchArray<Variant, _ArrayVariantSort> avs;
- return avs.bisect(_p->array.ptrw(), _p->array.size(), p_value, p_before);
+ return avs.bisect(_p->array.ptrw(), _p->array.size(), value, p_before);
}
int Array::bsearch_custom(const Variant &p_value, const Callable &p_callable, bool p_before) {
- ERR_FAIL_COND_V(!_p->typed.validate(p_value, "custom binary search"), -1);
+ Variant value = p_value;
+ ERR_FAIL_COND_V(!_p->typed.validate(value, "custom binary search"), -1);
- return _p->array.bsearch_custom<CallableComparator>(p_value, p_before, p_callable);
+ return _p->array.bsearch_custom<CallableComparator>(value, p_before, p_callable);
}
void Array::reverse() {
@@ -611,8 +643,9 @@ void Array::reverse() {
void Array::push_front(const Variant &p_value) {
ERR_FAIL_COND_MSG(_p->read_only, "Array is in read-only state.");
- ERR_FAIL_COND(!_p->typed.validate(p_value, "push_front"));
- _p->array.insert(0, p_value);
+ Variant value = p_value;
+ ERR_FAIL_COND(!_p->typed.validate(value, "push_front"));
+ _p->array.insert(0, value);
}
Variant Array::pop_back() {
diff --git a/core/variant/array.h b/core/variant/array.h
index ee265a9ffd..2dd3dde2d1 100644
--- a/core/variant/array.h
+++ b/core/variant/array.h
@@ -90,7 +90,6 @@ public:
int find(const Variant &p_value, int p_from = 0) const;
int rfind(const Variant &p_value, int p_from = -1) const;
- int find_last(const Variant &p_value) const;
int count(const Variant &p_value) const;
bool has(const Variant &p_value) const;
diff --git a/core/variant/container_type_validate.h b/core/variant/container_type_validate.h
index 427a337aab..9976fce47f 100644
--- a/core/variant/container_type_validate.h
+++ b/core/variant/container_type_validate.h
@@ -74,22 +74,37 @@ struct ContainerTypeValidate {
return true;
}
- _FORCE_INLINE_ bool validate(const Variant &p_variant, const char *p_operation = "use") {
+ // Coerces String and StringName into each other when needed.
+ _FORCE_INLINE_ bool validate(Variant &inout_variant, const char *p_operation = "use") {
if (type == Variant::NIL) {
return true;
}
- if (type != p_variant.get_type()) {
- if (p_variant.get_type() == Variant::NIL && type == Variant::OBJECT) {
+ if (type != inout_variant.get_type()) {
+ if (inout_variant.get_type() == Variant::NIL && type == Variant::OBJECT) {
+ return true;
+ }
+ if (type == Variant::STRING && inout_variant.get_type() == Variant::STRING_NAME) {
+ inout_variant = String(inout_variant);
+ return true;
+ } else if (type == Variant::STRING_NAME && inout_variant.get_type() == Variant::STRING) {
+ inout_variant = StringName(inout_variant);
return true;
}
- ERR_FAIL_V_MSG(false, "Attempted to " + String(p_operation) + " a variable of type '" + Variant::get_type_name(p_variant.get_type()) + "' into a " + where + " of type '" + Variant::get_type_name(type) + "'.");
+ ERR_FAIL_V_MSG(false, "Attempted to " + String(p_operation) + " a variable of type '" + Variant::get_type_name(inout_variant.get_type()) + "' into a " + where + " of type '" + Variant::get_type_name(type) + "'.");
}
if (type != Variant::OBJECT) {
return true;
}
+
+ return validate_object(inout_variant, p_operation);
+ }
+
+ _FORCE_INLINE_ bool validate_object(const Variant &p_variant, const char *p_operation = "use") {
+ ERR_FAIL_COND_V(p_variant.get_type() != Variant::OBJECT, false);
+
#ifdef DEBUG_ENABLED
ObjectID object_id = p_variant;
if (object_id == ObjectID()) {
diff --git a/core/variant/dictionary.cpp b/core/variant/dictionary.cpp
index c1cb782a57..77d9fb0bc2 100644
--- a/core/variant/dictionary.cpp
+++ b/core/variant/dictionary.cpp
@@ -42,7 +42,7 @@
struct DictionaryPrivate {
SafeRefCount refcount;
Variant *read_only = nullptr; // If enabled, a pointer is used to a temporary value that is used to return read-only values.
- HashMap<Variant, Variant, VariantHasher, VariantComparator> variant_map;
+ HashMap<Variant, Variant, VariantHasher, StringLikeVariantComparator> variant_map;
};
void Dictionary::get_key_list(List<Variant> *p_keys) const {
@@ -100,24 +100,12 @@ Variant &Dictionary::operator[](const Variant &p_key) {
}
const Variant &Dictionary::operator[](const Variant &p_key) const {
- if (p_key.get_type() == Variant::STRING_NAME) {
- const StringName *sn = VariantInternal::get_string_name(&p_key);
- return _p->variant_map[sn->operator String()];
- } else {
- return _p->variant_map[p_key];
- }
+ // Will not insert key, so no conversion is necessary.
+ return _p->variant_map[p_key];
}
const Variant *Dictionary::getptr(const Variant &p_key) const {
- HashMap<Variant, Variant, VariantHasher, VariantComparator>::ConstIterator E;
-
- if (p_key.get_type() == Variant::STRING_NAME) {
- const StringName *sn = VariantInternal::get_string_name(&p_key);
- E = ((const HashMap<Variant, Variant, VariantHasher, VariantComparator> *)&_p->variant_map)->find(sn->operator String());
- } else {
- E = ((const HashMap<Variant, Variant, VariantHasher, VariantComparator> *)&_p->variant_map)->find(p_key);
- }
-
+ HashMap<Variant, Variant, VariantHasher, StringLikeVariantComparator>::ConstIterator E(_p->variant_map.find(p_key));
if (!E) {
return nullptr;
}
@@ -125,14 +113,7 @@ const Variant *Dictionary::getptr(const Variant &p_key) const {
}
Variant *Dictionary::getptr(const Variant &p_key) {
- HashMap<Variant, Variant, VariantHasher, VariantComparator>::Iterator E;
-
- if (p_key.get_type() == Variant::STRING_NAME) {
- const StringName *sn = VariantInternal::get_string_name(&p_key);
- E = ((HashMap<Variant, Variant, VariantHasher, VariantComparator> *)&_p->variant_map)->find(sn->operator String());
- } else {
- E = ((HashMap<Variant, Variant, VariantHasher, VariantComparator> *)&_p->variant_map)->find(p_key);
- }
+ HashMap<Variant, Variant, VariantHasher, StringLikeVariantComparator>::Iterator E(_p->variant_map.find(p_key));
if (!E) {
return nullptr;
}
@@ -145,14 +126,7 @@ Variant *Dictionary::getptr(const Variant &p_key) {
}
Variant Dictionary::get_valid(const Variant &p_key) const {
- HashMap<Variant, Variant, VariantHasher, VariantComparator>::ConstIterator E;
-
- if (p_key.get_type() == Variant::STRING_NAME) {
- const StringName *sn = VariantInternal::get_string_name(&p_key);
- E = ((const HashMap<Variant, Variant, VariantHasher, VariantComparator> *)&_p->variant_map)->find(sn->operator String());
- } else {
- E = ((const HashMap<Variant, Variant, VariantHasher, VariantComparator> *)&_p->variant_map)->find(p_key);
- }
+ HashMap<Variant, Variant, VariantHasher, StringLikeVariantComparator>::ConstIterator E(_p->variant_map.find(p_key));
if (!E) {
return Variant();
@@ -178,12 +152,7 @@ bool Dictionary::is_empty() const {
}
bool Dictionary::has(const Variant &p_key) const {
- if (p_key.get_type() == Variant::STRING_NAME) {
- const StringName *sn = VariantInternal::get_string_name(&p_key);
- return _p->variant_map.has(sn->operator String());
- } else {
- return _p->variant_map.has(p_key);
- }
+ return _p->variant_map.has(p_key);
}
bool Dictionary::has_all(const Array &p_keys) const {
@@ -206,12 +175,7 @@ Variant Dictionary::find_key(const Variant &p_value) const {
bool Dictionary::erase(const Variant &p_key) {
ERR_FAIL_COND_V_MSG(_p->read_only, false, "Dictionary is in read-only state.");
- if (p_key.get_type() == Variant::STRING_NAME) {
- const StringName *sn = VariantInternal::get_string_name(&p_key);
- return _p->variant_map.erase(sn->operator String());
- } else {
- return _p->variant_map.erase(p_key);
- }
+ return _p->variant_map.erase(p_key);
}
bool Dictionary::operator==(const Dictionary &p_dictionary) const {
@@ -238,7 +202,7 @@ bool Dictionary::recursive_equal(const Dictionary &p_dictionary, int recursion_c
}
recursion_count++;
for (const KeyValue<Variant, Variant> &this_E : _p->variant_map) {
- HashMap<Variant, Variant, VariantHasher, VariantComparator>::ConstIterator other_E = ((const HashMap<Variant, Variant, VariantHasher, VariantComparator> *)&p_dictionary._p->variant_map)->find(this_E.key);
+ HashMap<Variant, Variant, VariantHasher, StringLikeVariantComparator>::ConstIterator other_E(p_dictionary._p->variant_map.find(this_E.key));
if (!other_E || !this_E.value.hash_compare(other_E->value, recursion_count)) {
return false;
}
@@ -360,7 +324,7 @@ const Variant *Dictionary::next(const Variant *p_key) const {
}
return nullptr;
}
- HashMap<Variant, Variant, VariantHasher, VariantComparator>::Iterator E = _p->variant_map.find(*p_key);
+ HashMap<Variant, Variant, VariantHasher, StringLikeVariantComparator>::Iterator E = _p->variant_map.find(*p_key);
if (!E) {
return nullptr;
diff --git a/core/variant/native_ptr.h b/core/variant/native_ptr.h
index ed68e0f6c9..18670310b0 100644
--- a/core/variant/native_ptr.h
+++ b/core/variant/native_ptr.h
@@ -36,90 +36,90 @@
#include "core/variant/type_info.h"
template <class T>
-struct GDNativeConstPtr {
+struct GDExtensionConstPtr {
const T *data = nullptr;
- GDNativeConstPtr(const T *p_assign) { data = p_assign; }
+ GDExtensionConstPtr(const T *p_assign) { data = p_assign; }
static const char *get_name() { return "const void"; }
operator const T *() const { return data; }
operator Variant() const { return uint64_t(data); }
};
template <class T>
-struct GDNativePtr {
+struct GDExtensionPtr {
T *data = nullptr;
- GDNativePtr(T *p_assign) { data = p_assign; }
+ GDExtensionPtr(T *p_assign) { data = p_assign; }
static const char *get_name() { return "void"; }
operator T *() const { return data; }
operator Variant() const { return uint64_t(data); }
};
-#define GDVIRTUAL_NATIVE_PTR(m_type) \
- template <> \
- struct GDNativeConstPtr<const m_type> { \
- const m_type *data = nullptr; \
- GDNativeConstPtr() {} \
- GDNativeConstPtr(const m_type *p_assign) { data = p_assign; } \
- static const char *get_name() { return "const " #m_type; } \
- operator const m_type *() const { return data; } \
- operator Variant() const { return uint64_t(data); } \
- }; \
- template <> \
- struct VariantCaster<GDNativeConstPtr<const m_type>> { \
- static _FORCE_INLINE_ GDNativeConstPtr<const m_type> cast(const Variant &p_variant) { \
- return GDNativeConstPtr<const m_type>((const m_type *)p_variant.operator uint64_t()); \
- } \
- }; \
- template <> \
- struct GDNativePtr<m_type> { \
- m_type *data = nullptr; \
- GDNativePtr() {} \
- GDNativePtr(m_type *p_assign) { data = p_assign; } \
- static const char *get_name() { return #m_type; } \
- operator m_type *() const { return data; } \
- operator Variant() const { return uint64_t(data); } \
- }; \
- template <> \
- struct VariantCaster<GDNativePtr<m_type>> { \
- static _FORCE_INLINE_ GDNativePtr<m_type> cast(const Variant &p_variant) { \
- return GDNativePtr<m_type>((m_type *)p_variant.operator uint64_t()); \
- } \
+#define GDVIRTUAL_NATIVE_PTR(m_type) \
+ template <> \
+ struct GDExtensionConstPtr<const m_type> { \
+ const m_type *data = nullptr; \
+ GDExtensionConstPtr() {} \
+ GDExtensionConstPtr(const m_type *p_assign) { data = p_assign; } \
+ static const char *get_name() { return "const " #m_type; } \
+ operator const m_type *() const { return data; } \
+ operator Variant() const { return uint64_t(data); } \
+ }; \
+ template <> \
+ struct VariantCaster<GDExtensionConstPtr<const m_type>> { \
+ static _FORCE_INLINE_ GDExtensionConstPtr<const m_type> cast(const Variant &p_variant) { \
+ return GDExtensionConstPtr<const m_type>((const m_type *)p_variant.operator uint64_t()); \
+ } \
+ }; \
+ template <> \
+ struct GDExtensionPtr<m_type> { \
+ m_type *data = nullptr; \
+ GDExtensionPtr() {} \
+ GDExtensionPtr(m_type *p_assign) { data = p_assign; } \
+ static const char *get_name() { return #m_type; } \
+ operator m_type *() const { return data; } \
+ operator Variant() const { return uint64_t(data); } \
+ }; \
+ template <> \
+ struct VariantCaster<GDExtensionPtr<m_type>> { \
+ static _FORCE_INLINE_ GDExtensionPtr<m_type> cast(const Variant &p_variant) { \
+ return GDExtensionPtr<m_type>((m_type *)p_variant.operator uint64_t()); \
+ } \
};
template <class T>
-struct GetTypeInfo<GDNativeConstPtr<T>> {
+struct GetTypeInfo<GDExtensionConstPtr<T>> {
static const Variant::Type VARIANT_TYPE = Variant::NIL;
static const GodotTypeInfo::Metadata METADATA = GodotTypeInfo::METADATA_NONE;
static inline PropertyInfo get_class_info() {
- return PropertyInfo(Variant::INT, String(), PROPERTY_HINT_INT_IS_POINTER, GDNativeConstPtr<T>::get_name());
+ return PropertyInfo(Variant::INT, String(), PROPERTY_HINT_INT_IS_POINTER, GDExtensionConstPtr<T>::get_name());
}
};
template <class T>
-struct GetTypeInfo<GDNativePtr<T>> {
+struct GetTypeInfo<GDExtensionPtr<T>> {
static const Variant::Type VARIANT_TYPE = Variant::NIL;
static const GodotTypeInfo::Metadata METADATA = GodotTypeInfo::METADATA_NONE;
static inline PropertyInfo get_class_info() {
- return PropertyInfo(Variant::INT, String(), PROPERTY_HINT_INT_IS_POINTER, GDNativePtr<T>::get_name());
+ return PropertyInfo(Variant::INT, String(), PROPERTY_HINT_INT_IS_POINTER, GDExtensionPtr<T>::get_name());
}
};
template <class T>
-struct PtrToArg<GDNativeConstPtr<T>> {
- _FORCE_INLINE_ static GDNativeConstPtr<T> convert(const void *p_ptr) {
- return GDNativeConstPtr<T>(reinterpret_cast<const T *>(p_ptr));
+struct PtrToArg<GDExtensionConstPtr<T>> {
+ _FORCE_INLINE_ static GDExtensionConstPtr<T> convert(const void *p_ptr) {
+ return GDExtensionConstPtr<T>(reinterpret_cast<const T *>(p_ptr));
}
typedef const T *EncodeT;
- _FORCE_INLINE_ static void encode(GDNativeConstPtr<T> p_val, void *p_ptr) {
+ _FORCE_INLINE_ static void encode(GDExtensionConstPtr<T> p_val, void *p_ptr) {
*((const T **)p_ptr) = p_val.data;
}
};
template <class T>
-struct PtrToArg<GDNativePtr<T>> {
- _FORCE_INLINE_ static GDNativePtr<T> convert(const void *p_ptr) {
- return GDNativePtr<T>(reinterpret_cast<const T *>(p_ptr));
+struct PtrToArg<GDExtensionPtr<T>> {
+ _FORCE_INLINE_ static GDExtensionPtr<T> convert(const void *p_ptr) {
+ return GDExtensionPtr<T>(reinterpret_cast<const T *>(p_ptr));
}
typedef T *EncodeT;
- _FORCE_INLINE_ static void encode(GDNativePtr<T> p_val, void *p_ptr) {
+ _FORCE_INLINE_ static void encode(GDExtensionPtr<T> p_val, void *p_ptr) {
*((T **)p_ptr) = p_val.data;
}
};
diff --git a/core/variant/type_info.h b/core/variant/type_info.h
index e355053296..8e2d150430 100644
--- a/core/variant/type_info.h
+++ b/core/variant/type_info.h
@@ -290,6 +290,7 @@ 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() = default;
_FORCE_INLINE_ BitField(int64_t p_value) { value = p_value; }
_FORCE_INLINE_ operator int64_t() const { return value; }
_FORCE_INLINE_ operator Variant() const { return value; }
diff --git a/core/variant/variant.cpp b/core/variant/variant.cpp
index b4528e67d1..39b7cbee0d 100644
--- a/core/variant/variant.cpp
+++ b/core/variant/variant.cpp
@@ -940,7 +940,7 @@ bool Variant::is_zero() const {
return reinterpret_cast<const Signal *>(_data._mem)->is_null();
}
case STRING_NAME: {
- return *reinterpret_cast<const StringName *>(_data._mem) != StringName();
+ return *reinterpret_cast<const StringName *>(_data._mem) == StringName();
}
case NODE_PATH: {
return reinterpret_cast<const NodePath *>(_data._mem)->is_empty();
@@ -3491,6 +3491,19 @@ bool Variant::hash_compare(const Variant &p_variant, int recursion_count) const
}
}
+bool StringLikeVariantComparator::compare(const Variant &p_lhs, const Variant &p_rhs) {
+ if (p_lhs.hash_compare(p_rhs)) {
+ return true;
+ }
+ if (p_lhs.get_type() == Variant::STRING && p_rhs.get_type() == Variant::STRING_NAME) {
+ return *VariantInternal::get_string(&p_lhs) == *VariantInternal::get_string_name(&p_rhs);
+ }
+ if (p_lhs.get_type() == Variant::STRING_NAME && p_rhs.get_type() == Variant::STRING) {
+ return *VariantInternal::get_string_name(&p_lhs) == *VariantInternal::get_string(&p_rhs);
+ }
+ return false;
+}
+
bool Variant::is_ref_counted() const {
return type == OBJECT && _get_obj().id.is_ref_counted();
}
@@ -3609,16 +3622,16 @@ String Variant::get_call_error_text(Object *p_base, const StringName &p_method,
if (ce.error == Callable::CallError::CALL_ERROR_INVALID_ARGUMENT) {
int errorarg = ce.argument;
if (p_argptrs) {
- err_text = "Cannot convert argument " + itos(errorarg + 1) + " from " + Variant::get_type_name(p_argptrs[errorarg]->get_type()) + " to " + Variant::get_type_name(Variant::Type(ce.expected)) + ".";
+ err_text = "Cannot convert argument " + itos(errorarg + 1) + " from " + Variant::get_type_name(p_argptrs[errorarg]->get_type()) + " to " + Variant::get_type_name(Variant::Type(ce.expected));
} else {
- err_text = "Cannot convert argument " + itos(errorarg + 1) + " from [missing argptr, type unknown] to " + Variant::get_type_name(Variant::Type(ce.expected)) + ".";
+ err_text = "Cannot convert argument " + itos(errorarg + 1) + " from [missing argptr, type unknown] to " + Variant::get_type_name(Variant::Type(ce.expected));
}
} else if (ce.error == Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS) {
- err_text = "Method expected " + itos(ce.argument) + " arguments, but called with " + itos(p_argcount) + ".";
+ err_text = "Method expected " + itos(ce.argument) + " arguments, but called with " + itos(p_argcount);
} else if (ce.error == Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS) {
- err_text = "Method expected " + itos(ce.argument) + " arguments, but called with " + itos(p_argcount) + ".";
+ err_text = "Method expected " + itos(ce.argument) + " arguments, but called with " + itos(p_argcount);
} else if (ce.error == Callable::CallError::CALL_ERROR_INVALID_METHOD) {
- err_text = "Method not found.";
+ err_text = "Method not found";
} else if (ce.error == Callable::CallError::CALL_ERROR_INSTANCE_IS_NULL) {
err_text = "Instance is null";
} else if (ce.error == Callable::CallError::CALL_ERROR_METHOD_NOT_CONST) {
diff --git a/core/variant/variant.h b/core/variant/variant.h
index c5be609184..f7221e206f 100644
--- a/core/variant/variant.h
+++ b/core/variant/variant.h
@@ -797,6 +797,10 @@ struct VariantComparator {
static _FORCE_INLINE_ bool compare(const Variant &p_lhs, const Variant &p_rhs) { return p_lhs.hash_compare(p_rhs); }
};
+struct StringLikeVariantComparator {
+ static bool compare(const Variant &p_lhs, const Variant &p_rhs);
+};
+
Variant::ObjData &Variant::_get_obj() {
return *reinterpret_cast<ObjData *>(&_data._mem[0]);
}
diff --git a/core/variant/variant_call.cpp b/core/variant/variant_call.cpp
index 91af2bab85..ac569941bf 100644
--- a/core/variant/variant_call.cpp
+++ b/core/variant/variant_call.cpp
@@ -73,6 +73,30 @@ static _FORCE_INLINE_ void vc_method_call(void (T::*method)(P...) const, Variant
call_with_variant_argsc_dv(VariantGetInternalPtr<T>::get_ptr(base), method, p_args, p_argcount, r_error, p_defvals);
}
+template <class From, class R, class T, class... P>
+static _FORCE_INLINE_ void vc_convert_method_call(R (T::*method)(P...), Variant *base, const Variant **p_args, int p_argcount, Variant &r_ret, const Vector<Variant> &p_defvals, Callable::CallError &r_error) {
+ T converted(static_cast<T>(*VariantGetInternalPtr<From>::get_ptr(base)));
+ call_with_variant_args_ret_dv(&converted, method, p_args, p_argcount, r_ret, r_error, p_defvals);
+}
+
+template <class From, class R, class T, class... P>
+static _FORCE_INLINE_ void vc_convert_method_call(R (T::*method)(P...) const, Variant *base, const Variant **p_args, int p_argcount, Variant &r_ret, const Vector<Variant> &p_defvals, Callable::CallError &r_error) {
+ T converted(static_cast<T>(*VariantGetInternalPtr<From>::get_ptr(base)));
+ call_with_variant_args_retc_dv(&converted, method, p_args, p_argcount, r_ret, r_error, p_defvals);
+}
+
+template <class From, class T, class... P>
+static _FORCE_INLINE_ void vc_convert_method_call(void (T::*method)(P...), Variant *base, const Variant **p_args, int p_argcount, Variant &r_ret, const Vector<Variant> &p_defvals, Callable::CallError &r_error) {
+ T converted(static_cast<T>(*VariantGetInternalPtr<From>::get_ptr(base)));
+ call_with_variant_args_dv(&converted, method, p_args, p_argcount, r_error, p_defvals);
+}
+
+template <class From, class T, class... P>
+static _FORCE_INLINE_ void vc_convert_method_call(void (T::*method)(P...) const, Variant *base, const Variant **p_args, int p_argcount, Variant &r_ret, const Vector<Variant> &p_defvals, Callable::CallError &r_error) {
+ T converted(static_cast<T>(*VariantGetInternalPtr<From>::get_ptr(base)));
+ call_with_variant_argsc_dv(&converted, method, p_args, p_argcount, r_error, p_defvals);
+}
+
template <class R, class T, class... P>
static _FORCE_INLINE_ void vc_method_call_static(R (*method)(T *, P...), Variant *base, const Variant **p_args, int p_argcount, Variant &r_ret, const Vector<Variant> &p_defvals, Callable::CallError &r_error) {
call_with_variant_args_retc_static_helper_dv(VariantGetInternalPtr<T>::get_ptr(base), method, p_args, p_argcount, r_ret, p_defvals, r_error);
@@ -102,6 +126,29 @@ static _FORCE_INLINE_ void vc_validated_call(void (T::*method)(P...) const, Vari
call_with_validated_variant_argsc(base, method, p_args);
}
+template <class From, class R, class T, class... P>
+static _FORCE_INLINE_ void vc_convert_validated_call(R (T::*method)(P...), Variant *base, const Variant **p_args, Variant *r_ret) {
+ T converted(static_cast<T>(*VariantGetInternalPtr<From>::get_ptr(base)));
+ call_with_validated_variant_args_ret_helper<T, R, P...>(&converted, method, p_args, r_ret, BuildIndexSequence<sizeof...(P)>{});
+}
+
+template <class From, class R, class T, class... P>
+static _FORCE_INLINE_ void vc_convert_validated_call(R (T::*method)(P...) const, Variant *base, const Variant **p_args, Variant *r_ret) {
+ T converted(static_cast<T>(*VariantGetInternalPtr<From>::get_ptr(base)));
+ call_with_validated_variant_args_retc_helper<T, R, P...>(&converted, method, p_args, r_ret, BuildIndexSequence<sizeof...(P)>{});
+}
+template <class From, class T, class... P>
+static _FORCE_INLINE_ void vc_convert_validated_call(void (T::*method)(P...), Variant *base, const Variant **p_args, Variant *r_ret) {
+ T converted(static_cast<T>(*VariantGetInternalPtr<From>::get_ptr(base)));
+ call_with_validated_variant_args_helper<T, P...>(&converted, method, p_args, r_ret, BuildIndexSequence<sizeof...(P)>{});
+}
+
+template <class From, class T, class... P>
+static _FORCE_INLINE_ void vc_convert_validated_call(void (T::*method)(P...) const, Variant *base, const Variant **p_args, Variant *r_ret) {
+ T converted(static_cast<T>(*VariantGetInternalPtr<From>::get_ptr(base)));
+ call_with_validated_variant_argsc_helper<T, P...>(&converted, method, p_args, r_ret, BuildIndexSequence<sizeof...(P)>{});
+}
+
template <class R, class T, class... P>
static _FORCE_INLINE_ void vc_validated_call_static(R (*method)(T *, P...), Variant *base, const Variant **p_args, Variant *r_ret) {
call_with_validated_variant_args_static_retc(base, method, p_args, r_ret);
@@ -142,6 +189,30 @@ static _FORCE_INLINE_ void vc_ptrcall(void (T::*method)(P...) const, void *p_bas
call_with_ptr_argsc(reinterpret_cast<T *>(p_base), method, p_args);
}
+template <class From, class R, class T, class... P>
+static _FORCE_INLINE_ void vc_convert_ptrcall(R (T::*method)(P...), void *p_base, const void **p_args, void *r_ret) {
+ T converted(*reinterpret_cast<From *>(p_base));
+ call_with_ptr_args_ret(&converted, method, p_args, r_ret);
+}
+
+template <class From, class R, class T, class... P>
+static _FORCE_INLINE_ void vc_convert_ptrcall(R (T::*method)(P...) const, void *p_base, const void **p_args, void *r_ret) {
+ T converted(*reinterpret_cast<From *>(p_base));
+ call_with_ptr_args_retc(&converted, method, p_args, r_ret);
+}
+
+template <class From, class T, class... P>
+static _FORCE_INLINE_ void vc_convert_ptrcall(void (T::*method)(P...), void *p_base, const void **p_args, void *r_ret) {
+ T converted(*reinterpret_cast<From *>(p_base));
+ call_with_ptr_args(&converted, method, p_args);
+}
+
+template <class From, class T, class... P>
+static _FORCE_INLINE_ void vc_convert_ptrcall(void (T::*method)(P...) const, void *p_base, const void **p_args, void *r_ret) {
+ T converted(*reinterpret_cast<From *>(p_base));
+ call_with_ptr_argsc(&converted, method, p_args);
+}
+
template <class R, class T, class... P>
static _FORCE_INLINE_ int vc_get_argument_count(R (T::*method)(P...)) {
return sizeof...(P);
@@ -337,6 +408,46 @@ static _FORCE_INLINE_ Variant::Type vc_get_base_type(void (T::*method)(P...) con
} \
};
+#define CONVERT_METHOD_CLASS(m_class, m_method_name, m_method_ptr) \
+ struct Method_##m_class##_##m_method_name { \
+ static void call(Variant *base, const Variant **p_args, int p_argcount, Variant &r_ret, const Vector<Variant> &p_defvals, Callable::CallError &r_error) { \
+ vc_convert_method_call<m_class>(m_method_ptr, base, p_args, p_argcount, r_ret, p_defvals, r_error); \
+ } \
+ static void validated_call(Variant *base, const Variant **p_args, int p_argcount, Variant *r_ret) { \
+ vc_convert_validated_call<m_class>(m_method_ptr, base, p_args, r_ret); \
+ } \
+ static void ptrcall(void *p_base, const void **p_args, void *r_ret, int p_argcount) { \
+ vc_convert_ptrcall<m_class>(m_method_ptr, p_base, p_args, r_ret); \
+ } \
+ static int get_argument_count() { \
+ return vc_get_argument_count(m_method_ptr); \
+ } \
+ static Variant::Type get_argument_type(int p_arg) { \
+ return vc_get_argument_type(m_method_ptr, p_arg); \
+ } \
+ static Variant::Type get_return_type() { \
+ return vc_get_return_type(m_method_ptr); \
+ } \
+ static bool has_return_type() { \
+ return vc_has_return_type(m_method_ptr); \
+ } \
+ static bool is_const() { \
+ return vc_is_const(m_method_ptr); \
+ } \
+ static bool is_static() { \
+ return false; \
+ } \
+ static bool is_vararg() { \
+ return false; \
+ } \
+ static Variant::Type get_base_type() { \
+ return GetTypeInfo<m_class>::VARIANT_TYPE; \
+ } \
+ static StringName get_name() { \
+ return #m_method_name; \
+ } \
+ };
+
template <class R, class... P>
static _FORCE_INLINE_ void vc_static_ptrcall(R (*method)(P...), const void **p_args, void *r_ret) {
call_with_ptr_args_static_method_ret<R, P...>(method, p_args, r_ret);
@@ -1422,6 +1533,16 @@ int Variant::get_enum_value(Variant::Type p_type, StringName p_enum_name, String
#endif
#ifdef DEBUG_METHODS_ENABLED
+#define bind_convert_method(m_type_from, m_type_to, m_method, m_arg_names, m_default_args) \
+ CONVERT_METHOD_CLASS(m_type_from, m_method, &m_type_to::m_method); \
+ register_builtin_method<Method_##m_type_from##_##m_method>(m_arg_names, m_default_args);
+#else
+#define bind_convert_method(m_type_from, m_type_to, m_method, m_arg_names, m_default_args) \
+ CONVERT_METHOD_CLASS(m_type_from, m_method, &m_type_to ::m_method); \
+ register_builtin_method<Method_##m_type_from##_##m_method>(sarray(), m_default_args);
+#endif
+
+#ifdef DEBUG_METHODS_ENABLED
#define bind_static_method(m_type, m_method, m_arg_names, m_default_args) \
STATIC_METHOD_CLASS(m_type, m_method, m_type::m_method); \
register_builtin_method<Method_##m_type##_##m_method>(m_arg_names, m_default_args);
@@ -1442,6 +1563,16 @@ int Variant::get_enum_value(Variant::Type p_type, StringName p_enum_name, String
#endif
#ifdef DEBUG_METHODS_ENABLED
+#define bind_convert_methodv(m_type_from, m_type_to, m_name, m_method, m_arg_names, m_default_args) \
+ CONVERT_METHOD_CLASS(m_type_from, m_name, m_method); \
+ register_builtin_method<Method_##m_type_from##_##m_name>(m_arg_names, m_default_args);
+#else
+#define bind_convert_methodv(m_type_from, m_type_to, m_name, m_method, m_arg_names, m_default_args) \
+ CONVERT_METHOD_CLASS(m_type_from, m_name, m_method); \
+ register_builtin_method<Method_##m_type_from##_##m_name>(sarray(), m_default_args);
+#endif
+
+#ifdef DEBUG_METHODS_ENABLED
#define bind_function(m_type, m_name, m_method, m_arg_names, m_default_args) \
FUNCTION_CLASS(m_type, m_name, m_method, true); \
register_builtin_method<Method_##m_type##_##m_name>(m_arg_names, m_default_args);
@@ -1461,6 +1592,14 @@ int Variant::get_enum_value(Variant::Type p_type, StringName p_enum_name, String
register_builtin_method<Method_##m_type##_##m_name>(sarray(), m_default_args);
#endif
+#define bind_string_method(m_method, m_arg_names, m_default_args) \
+ bind_method(String, m_method, m_arg_names, m_default_args); \
+ bind_convert_method(StringName, String, m_method, m_arg_names, m_default_args);
+
+#define bind_string_methodv(m_name, m_method, m_arg_names, m_default_args) \
+ bind_methodv(String, m_name, m_method, m_arg_names, m_default_args); \
+ bind_convert_methodv(StringName, String, m_name, m_method, m_arg_names, m_default_args);
+
#define bind_custom(m_type, m_name, m_method, m_has_return, m_ret_type) \
VARARG_CLASS(m_type, m_name, m_method, m_has_return, m_ret_type) \
register_builtin_method<Method_##m_type##_##m_name>(sarray(), Vector<Variant>());
@@ -1477,108 +1616,108 @@ static void _register_variant_builtin_methods() {
/* String */
- bind_method(String, casecmp_to, sarray("to"), varray());
- bind_method(String, nocasecmp_to, sarray("to"), varray());
- bind_method(String, naturalnocasecmp_to, sarray("to"), varray());
- bind_method(String, length, sarray(), varray());
- bind_method(String, substr, sarray("from", "len"), varray(-1));
- bind_method(String, get_slice, sarray("delimiter", "slice"), varray());
- bind_method(String, get_slicec, sarray("delimiter", "slice"), varray());
- bind_method(String, get_slice_count, sarray("delimiter"), varray());
- bind_methodv(String, find, static_cast<int (String::*)(const String &, int) const>(&String::find), sarray("what", "from"), varray(0));
- bind_method(String, count, sarray("what", "from", "to"), varray(0, 0));
- bind_method(String, countn, sarray("what", "from", "to"), varray(0, 0));
- bind_method(String, findn, sarray("what", "from"), varray(0));
- bind_method(String, rfind, sarray("what", "from"), varray(-1));
- bind_method(String, rfindn, sarray("what", "from"), varray(-1));
- bind_method(String, match, sarray("expr"), varray());
- bind_method(String, matchn, sarray("expr"), varray());
- bind_methodv(String, begins_with, static_cast<bool (String::*)(const String &) const>(&String::begins_with), sarray("text"), varray());
- bind_method(String, ends_with, sarray("text"), varray());
- bind_method(String, is_subsequence_of, sarray("text"), varray());
- bind_method(String, is_subsequence_ofn, sarray("text"), varray());
- bind_method(String, bigrams, sarray(), varray());
- bind_method(String, similarity, sarray("text"), varray());
-
- bind_method(String, format, sarray("values", "placeholder"), varray("{_}"));
- bind_methodv(String, replace, static_cast<String (String::*)(const String &, const String &) const>(&String::replace), sarray("what", "forwhat"), varray());
- bind_method(String, replacen, sarray("what", "forwhat"), varray());
- bind_method(String, repeat, sarray("count"), varray());
- bind_method(String, insert, sarray("position", "what"), varray());
- bind_method(String, capitalize, sarray(), varray());
- bind_method(String, to_camel_case, sarray(), varray());
- bind_method(String, to_pascal_case, sarray(), varray());
- bind_method(String, to_snake_case, sarray(), varray());
- bind_method(String, split, sarray("delimiter", "allow_empty", "maxsplit"), varray("", true, 0));
- bind_method(String, rsplit, sarray("delimiter", "allow_empty", "maxsplit"), varray("", true, 0));
- bind_method(String, split_floats, sarray("delimiter", "allow_empty"), varray(true));
- bind_method(String, join, sarray("parts"), varray());
-
- bind_method(String, to_upper, sarray(), varray());
- bind_method(String, to_lower, sarray(), varray());
-
- bind_method(String, left, sarray("length"), varray());
- bind_method(String, right, sarray("length"), varray());
-
- bind_method(String, strip_edges, sarray("left", "right"), varray(true, true));
- bind_method(String, strip_escapes, sarray(), varray());
- bind_method(String, lstrip, sarray("chars"), varray());
- bind_method(String, rstrip, sarray("chars"), varray());
- bind_method(String, get_extension, sarray(), varray());
- bind_method(String, get_basename, sarray(), varray());
- bind_method(String, path_join, sarray("file"), varray());
- bind_method(String, unicode_at, sarray("at"), varray());
- bind_method(String, indent, sarray("prefix"), varray());
- bind_method(String, dedent, sarray(), varray());
+ bind_string_method(casecmp_to, sarray("to"), varray());
+ bind_string_method(nocasecmp_to, sarray("to"), varray());
+ bind_string_method(naturalnocasecmp_to, sarray("to"), varray());
+ bind_string_method(length, sarray(), varray());
+ bind_string_method(substr, sarray("from", "len"), varray(-1));
+ bind_string_method(get_slice, sarray("delimiter", "slice"), varray());
+ bind_string_method(get_slicec, sarray("delimiter", "slice"), varray());
+ bind_string_method(get_slice_count, sarray("delimiter"), varray());
+ bind_string_methodv(find, static_cast<int (String::*)(const String &, int) const>(&String::find), sarray("what", "from"), varray(0));
+ bind_string_method(count, sarray("what", "from", "to"), varray(0, 0));
+ bind_string_method(countn, sarray("what", "from", "to"), varray(0, 0));
+ bind_string_method(findn, sarray("what", "from"), varray(0));
+ bind_string_method(rfind, sarray("what", "from"), varray(-1));
+ bind_string_method(rfindn, sarray("what", "from"), varray(-1));
+ bind_string_method(match, sarray("expr"), varray());
+ bind_string_method(matchn, sarray("expr"), varray());
+ bind_string_methodv(begins_with, static_cast<bool (String::*)(const String &) const>(&String::begins_with), sarray("text"), varray());
+ bind_string_method(ends_with, sarray("text"), varray());
+ bind_string_method(is_subsequence_of, sarray("text"), varray());
+ bind_string_method(is_subsequence_ofn, sarray("text"), varray());
+ bind_string_method(bigrams, sarray(), varray());
+ bind_string_method(similarity, sarray("text"), varray());
+
+ bind_string_method(format, sarray("values", "placeholder"), varray("{_}"));
+ bind_string_methodv(replace, static_cast<String (String::*)(const String &, const String &) const>(&String::replace), sarray("what", "forwhat"), varray());
+ bind_string_method(replacen, sarray("what", "forwhat"), varray());
+ bind_string_method(repeat, sarray("count"), varray());
+ bind_string_method(insert, sarray("position", "what"), varray());
+ bind_string_method(capitalize, sarray(), varray());
+ bind_string_method(to_camel_case, sarray(), varray());
+ bind_string_method(to_pascal_case, sarray(), varray());
+ bind_string_method(to_snake_case, sarray(), varray());
+ bind_string_method(split, sarray("delimiter", "allow_empty", "maxsplit"), varray("", true, 0));
+ bind_string_method(rsplit, sarray("delimiter", "allow_empty", "maxsplit"), varray("", true, 0));
+ bind_string_method(split_floats, sarray("delimiter", "allow_empty"), varray(true));
+ bind_string_method(join, sarray("parts"), varray());
+
+ bind_string_method(to_upper, sarray(), varray());
+ bind_string_method(to_lower, sarray(), varray());
+
+ bind_string_method(left, sarray("length"), varray());
+ bind_string_method(right, sarray("length"), varray());
+
+ bind_string_method(strip_edges, sarray("left", "right"), varray(true, true));
+ bind_string_method(strip_escapes, sarray(), varray());
+ bind_string_method(lstrip, sarray("chars"), varray());
+ bind_string_method(rstrip, sarray("chars"), varray());
+ bind_string_method(get_extension, sarray(), varray());
+ bind_string_method(get_basename, sarray(), varray());
+ bind_string_method(path_join, sarray("file"), varray());
+ bind_string_method(unicode_at, sarray("at"), varray());
+ bind_string_method(indent, sarray("prefix"), varray());
+ bind_string_method(dedent, sarray(), varray());
bind_method(String, hash, sarray(), varray());
- bind_method(String, md5_text, sarray(), varray());
- bind_method(String, sha1_text, sarray(), varray());
- bind_method(String, sha256_text, sarray(), varray());
- bind_method(String, md5_buffer, sarray(), varray());
- bind_method(String, sha1_buffer, sarray(), varray());
- bind_method(String, sha256_buffer, sarray(), varray());
- bind_method(String, is_empty, sarray(), varray());
- bind_methodv(String, contains, static_cast<bool (String::*)(const String &) const>(&String::contains), sarray("what"), varray());
-
- bind_method(String, is_absolute_path, sarray(), varray());
- bind_method(String, is_relative_path, sarray(), varray());
- bind_method(String, simplify_path, sarray(), varray());
- bind_method(String, get_base_dir, sarray(), varray());
- bind_method(String, get_file, sarray(), varray());
- bind_method(String, xml_escape, sarray("escape_quotes"), varray(false));
- bind_method(String, xml_unescape, sarray(), varray());
- bind_method(String, uri_encode, sarray(), varray());
- bind_method(String, uri_decode, sarray(), varray());
- bind_method(String, c_escape, sarray(), varray());
- bind_method(String, c_unescape, sarray(), varray());
- bind_method(String, json_escape, sarray(), varray());
-
- bind_method(String, validate_node_name, sarray(), varray());
-
- bind_method(String, is_valid_identifier, sarray(), varray());
- bind_method(String, is_valid_int, sarray(), varray());
- bind_method(String, is_valid_float, sarray(), varray());
- bind_method(String, is_valid_hex_number, sarray("with_prefix"), varray(false));
- bind_method(String, is_valid_html_color, sarray(), varray());
- bind_method(String, is_valid_ip_address, sarray(), varray());
- bind_method(String, is_valid_filename, sarray(), varray());
-
- bind_method(String, to_int, sarray(), varray());
- bind_method(String, to_float, sarray(), varray());
- bind_method(String, hex_to_int, sarray(), varray());
- bind_method(String, bin_to_int, sarray(), varray());
-
- bind_method(String, lpad, sarray("min_length", "character"), varray(" "));
- bind_method(String, rpad, sarray("min_length", "character"), varray(" "));
- bind_method(String, pad_decimals, sarray("digits"), varray());
- bind_method(String, pad_zeros, sarray("digits"), varray());
- bind_method(String, trim_prefix, sarray("prefix"), varray());
- bind_method(String, trim_suffix, sarray("suffix"), varray());
-
- bind_method(String, to_ascii_buffer, sarray(), varray());
- bind_method(String, to_utf8_buffer, sarray(), varray());
- bind_method(String, to_utf16_buffer, sarray(), varray());
- bind_method(String, to_utf32_buffer, sarray(), varray());
+ bind_string_method(md5_text, sarray(), varray());
+ bind_string_method(sha1_text, sarray(), varray());
+ bind_string_method(sha256_text, sarray(), varray());
+ bind_string_method(md5_buffer, sarray(), varray());
+ bind_string_method(sha1_buffer, sarray(), varray());
+ bind_string_method(sha256_buffer, sarray(), varray());
+ bind_string_method(is_empty, sarray(), varray());
+ bind_string_methodv(contains, static_cast<bool (String::*)(const String &) const>(&String::contains), sarray("what"), varray());
+
+ bind_string_method(is_absolute_path, sarray(), varray());
+ bind_string_method(is_relative_path, sarray(), varray());
+ bind_string_method(simplify_path, sarray(), varray());
+ bind_string_method(get_base_dir, sarray(), varray());
+ bind_string_method(get_file, sarray(), varray());
+ bind_string_method(xml_escape, sarray("escape_quotes"), varray(false));
+ bind_string_method(xml_unescape, sarray(), varray());
+ bind_string_method(uri_encode, sarray(), varray());
+ bind_string_method(uri_decode, sarray(), varray());
+ bind_string_method(c_escape, sarray(), varray());
+ bind_string_method(c_unescape, sarray(), varray());
+ bind_string_method(json_escape, sarray(), varray());
+
+ bind_string_method(validate_node_name, sarray(), varray());
+
+ bind_string_method(is_valid_identifier, sarray(), varray());
+ bind_string_method(is_valid_int, sarray(), varray());
+ bind_string_method(is_valid_float, sarray(), varray());
+ bind_string_method(is_valid_hex_number, sarray("with_prefix"), varray(false));
+ bind_string_method(is_valid_html_color, sarray(), varray());
+ bind_string_method(is_valid_ip_address, sarray(), varray());
+ bind_string_method(is_valid_filename, sarray(), varray());
+
+ bind_string_method(to_int, sarray(), varray());
+ bind_string_method(to_float, sarray(), varray());
+ bind_string_method(hex_to_int, sarray(), varray());
+ bind_string_method(bin_to_int, sarray(), varray());
+
+ bind_string_method(lpad, sarray("min_length", "character"), varray(" "));
+ bind_string_method(rpad, sarray("min_length", "character"), varray(" "));
+ bind_string_method(pad_decimals, sarray("digits"), varray());
+ bind_string_method(pad_zeros, sarray("digits"), varray());
+ bind_string_method(trim_prefix, sarray("prefix"), varray());
+ bind_string_method(trim_suffix, sarray("suffix"), varray());
+
+ bind_string_method(to_ascii_buffer, sarray(), varray());
+ bind_string_method(to_utf8_buffer, sarray(), varray());
+ bind_string_method(to_utf16_buffer, sarray(), varray());
+ bind_string_method(to_utf32_buffer, sarray(), varray());
bind_static_method(String, num_scientific, sarray("number"), varray());
bind_static_method(String, num, sarray("number", "decimals"), varray(-1));
@@ -1615,6 +1754,7 @@ static void _register_variant_builtin_methods() {
bind_method(Vector2, cubic_interpolate, sarray("b", "pre_a", "post_b", "weight"), varray());
bind_method(Vector2, cubic_interpolate_in_time, sarray("b", "pre_a", "post_b", "weight", "b_t", "pre_a_t", "post_b_t"), varray());
bind_method(Vector2, bezier_interpolate, sarray("control_1", "control_2", "end", "t"), varray());
+ bind_method(Vector2, bezier_derivative, sarray("control_1", "control_2", "end", "t"), varray());
bind_method(Vector2, max_axis_index, sarray(), varray());
bind_method(Vector2, min_axis_index, sarray(), varray());
bind_method(Vector2, move_toward, sarray("to", "delta"), varray());
@@ -1646,6 +1786,7 @@ static void _register_variant_builtin_methods() {
bind_method(Vector2i, sign, sarray(), varray());
bind_method(Vector2i, abs, sarray(), varray());
bind_method(Vector2i, clamp, sarray("min", "max"), varray());
+ bind_method(Vector2i, snapped, sarray("step"), varray());
/* Rect2 */
@@ -1707,6 +1848,7 @@ static void _register_variant_builtin_methods() {
bind_method(Vector3, cubic_interpolate, sarray("b", "pre_a", "post_b", "weight"), varray());
bind_method(Vector3, cubic_interpolate_in_time, sarray("b", "pre_a", "post_b", "weight", "b_t", "pre_a_t", "post_b_t"), varray());
bind_method(Vector3, bezier_interpolate, sarray("control_1", "control_2", "end", "t"), varray());
+ bind_method(Vector3, bezier_derivative, sarray("control_1", "control_2", "end", "t"), varray());
bind_method(Vector3, move_toward, sarray("to", "delta"), varray());
bind_method(Vector3, dot, sarray("with"), varray());
bind_method(Vector3, cross, sarray("with"), varray());
@@ -1734,6 +1876,7 @@ static void _register_variant_builtin_methods() {
bind_method(Vector3i, sign, sarray(), varray());
bind_method(Vector3i, abs, sarray(), varray());
bind_method(Vector3i, clamp, sarray("min", "max"), varray());
+ bind_method(Vector3i, snapped, sarray("step"), varray());
/* Vector4 */
@@ -1773,6 +1916,7 @@ static void _register_variant_builtin_methods() {
bind_method(Vector4i, sign, sarray(), varray());
bind_method(Vector4i, abs, sarray(), varray());
bind_method(Vector4i, clamp, sarray("min", "max"), varray());
+ bind_method(Vector4i, snapped, sarray("step"), varray());
/* Plane */
@@ -2053,7 +2197,6 @@ static void _register_variant_builtin_methods() {
bind_method(Array, pick_random, sarray(), varray());
bind_method(Array, find, sarray("what", "from"), varray(0));
bind_method(Array, rfind, sarray("what", "from"), varray(-1));
- bind_method(Array, find_last, sarray("value"), varray());
bind_method(Array, count, sarray("value"), varray());
bind_method(Array, has, sarray("value"), varray());
bind_method(Array, pop_back, sarray(), varray());
@@ -2438,7 +2581,7 @@ static void _register_variant_builtin_methods() {
_VariantCall::add_variant_constant(Variant::TRANSFORM2D, "FLIP_X", Transform2D(-1, 0, 0, 1, 0, 0));
_VariantCall::add_variant_constant(Variant::TRANSFORM2D, "FLIP_Y", Transform2D(1, 0, 0, -1, 0, 0));
- Transform3D identity_transform = Transform3D();
+ Transform3D identity_transform;
Transform3D flip_x_transform = Transform3D(-1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0);
Transform3D flip_y_transform = Transform3D(1, 0, 0, 0, -1, 0, 0, 0, 1, 0, 0, 0);
Transform3D flip_z_transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, -1, 0, 0, 0);
@@ -2447,7 +2590,7 @@ static void _register_variant_builtin_methods() {
_VariantCall::add_variant_constant(Variant::TRANSFORM3D, "FLIP_Y", flip_y_transform);
_VariantCall::add_variant_constant(Variant::TRANSFORM3D, "FLIP_Z", flip_z_transform);
- Basis identity_basis = Basis();
+ Basis identity_basis;
Basis flip_x_basis = Basis(-1, 0, 0, 0, 1, 0, 0, 0, 1);
Basis flip_y_basis = Basis(1, 0, 0, 0, -1, 0, 0, 0, 1);
Basis flip_z_basis = Basis(1, 0, 0, 0, 1, 0, 0, 0, -1);
diff --git a/core/variant/variant_construct.cpp b/core/variant/variant_construct.cpp
index ae9727fe79..624a6f5e06 100644
--- a/core/variant/variant_construct.cpp
+++ b/core/variant/variant_construct.cpp
@@ -68,11 +68,13 @@ void Variant::_register_variant_constructors() {
add_constructor<VariantConstructor<int64_t, int64_t>>(sarray("from"));
add_constructor<VariantConstructor<int64_t, double>>(sarray("from"));
add_constructor<VariantConstructor<int64_t, bool>>(sarray("from"));
+ add_constructor<VariantConstructorFromString<int64_t>>(sarray("from"));
add_constructor<VariantConstructNoArgs<double>>(sarray());
add_constructor<VariantConstructor<double, double>>(sarray("from"));
add_constructor<VariantConstructor<double, int64_t>>(sarray("from"));
add_constructor<VariantConstructor<double, bool>>(sarray("from"));
+ add_constructor<VariantConstructorFromString<double>>(sarray("from"));
add_constructor<VariantConstructNoArgs<String>>(sarray());
add_constructor<VariantConstructor<String, String>>(sarray("from"));
diff --git a/core/variant/variant_construct.h b/core/variant/variant_construct.h
index 34d228f4d2..f52cc43914 100644
--- a/core/variant/variant_construct.h
+++ b/core/variant/variant_construct.h
@@ -222,6 +222,64 @@ public:
}
};
+template <class T>
+class VariantConstructorFromString {
+public:
+ static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) {
+ if (p_args[0]->get_type() != Variant::STRING) {
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.argument = 0;
+ r_error.expected = Variant::STRING;
+ return;
+ }
+
+ VariantTypeChanger<T>::change(&r_ret);
+ const String &src_str = *VariantGetInternalPtr<String>::get_ptr(p_args[0]);
+
+ if (r_ret.get_type() == Variant::Type::INT) {
+ r_ret = src_str.to_int();
+ } else if (r_ret.get_type() == Variant::Type::FLOAT) {
+ r_ret = src_str.to_float();
+ }
+ }
+
+ static inline void validated_construct(Variant *r_ret, const Variant **p_args) {
+ VariantTypeChanger<T>::change(r_ret);
+ const String &src_str = *VariantGetInternalPtr<String>::get_ptr(p_args[0]);
+ T ret = Variant();
+ if (r_ret->get_type() == Variant::Type::INT) {
+ ret = src_str.to_int();
+ } else if (r_ret->get_type() == Variant::Type::FLOAT) {
+ ret = src_str.to_float();
+ }
+ *r_ret = ret;
+ }
+
+ static void ptr_construct(void *base, const void **p_args) {
+ String src_str = PtrToArg<String>::convert(p_args[0]);
+ T dst_var = Variant();
+ Variant type_test = Variant(dst_var);
+ if (type_test.get_type() == Variant::Type::INT) {
+ dst_var = src_str.to_int();
+ } else if (type_test.get_type() == Variant::Type::FLOAT) {
+ dst_var = src_str.to_float();
+ }
+ PtrConstruct<T>::construct(dst_var, base);
+ }
+
+ static int get_argument_count() {
+ return 1;
+ }
+
+ static Variant::Type get_argument_type(int p_arg) {
+ return Variant::STRING;
+ }
+
+ static Variant::Type get_base_type() {
+ return GetTypeInfo<T>::VARIANT_TYPE;
+ }
+};
+
class VariantConstructorCallableArgs {
public:
static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) {
diff --git a/core/variant/variant_internal.h b/core/variant/variant_internal.h
index 94e7296a99..f3b9bd235c 100644
--- a/core/variant/variant_internal.h
+++ b/core/variant/variant_internal.h
@@ -1314,7 +1314,7 @@ struct VariantZeroAssigner<float> {
template <>
struct VariantZeroAssigner<String> {
- static _FORCE_INLINE_ void zero(Variant *v) {}
+ static _FORCE_INLINE_ void zero(Variant *v) { *VariantInternal::get_string(v) = String(); }
};
template <>
@@ -1399,12 +1399,12 @@ struct VariantZeroAssigner<Color> {
template <>
struct VariantZeroAssigner<StringName> {
- static _FORCE_INLINE_ void zero(Variant *v) {}
+ static _FORCE_INLINE_ void zero(Variant *v) { *VariantInternal::get_string_name(v) = StringName(); }
};
template <>
struct VariantZeroAssigner<NodePath> {
- static _FORCE_INLINE_ void zero(Variant *v) {}
+ static _FORCE_INLINE_ void zero(Variant *v) { *VariantInternal::get_node_path(v) = NodePath(); }
};
template <>
@@ -1414,12 +1414,12 @@ struct VariantZeroAssigner<::RID> {
template <>
struct VariantZeroAssigner<Callable> {
- static _FORCE_INLINE_ void zero(Variant *v) {}
+ static _FORCE_INLINE_ void zero(Variant *v) { *VariantInternal::get_callable(v) = Callable(); }
};
template <>
struct VariantZeroAssigner<Signal> {
- static _FORCE_INLINE_ void zero(Variant *v) {}
+ static _FORCE_INLINE_ void zero(Variant *v) { *VariantInternal::get_signal(v) = Signal(); }
};
template <>
@@ -1434,47 +1434,47 @@ struct VariantZeroAssigner<Array> {
template <>
struct VariantZeroAssigner<PackedByteArray> {
- static _FORCE_INLINE_ void zero(Variant *v) {}
+ static _FORCE_INLINE_ void zero(Variant *v) { *VariantInternal::get_byte_array(v) = PackedByteArray(); }
};
template <>
struct VariantZeroAssigner<PackedInt32Array> {
- static _FORCE_INLINE_ void zero(Variant *v) {}
+ static _FORCE_INLINE_ void zero(Variant *v) { *VariantInternal::get_int32_array(v) = PackedInt32Array(); }
};
template <>
struct VariantZeroAssigner<PackedInt64Array> {
- static _FORCE_INLINE_ void zero(Variant *v) {}
+ static _FORCE_INLINE_ void zero(Variant *v) { *VariantInternal::get_int64_array(v) = PackedInt64Array(); }
};
template <>
struct VariantZeroAssigner<PackedFloat32Array> {
- static _FORCE_INLINE_ void zero(Variant *v) {}
+ static _FORCE_INLINE_ void zero(Variant *v) { *VariantInternal::get_float32_array(v) = PackedFloat32Array(); }
};
template <>
struct VariantZeroAssigner<PackedFloat64Array> {
- static _FORCE_INLINE_ void zero(Variant *v) {}
+ static _FORCE_INLINE_ void zero(Variant *v) { *VariantInternal::get_float64_array(v) = PackedFloat64Array(); }
};
template <>
struct VariantZeroAssigner<PackedStringArray> {
- static _FORCE_INLINE_ void zero(Variant *v) {}
+ static _FORCE_INLINE_ void zero(Variant *v) { *VariantInternal::get_string_array(v) = PackedStringArray(); }
};
template <>
struct VariantZeroAssigner<PackedVector2Array> {
- static _FORCE_INLINE_ void zero(Variant *v) {}
+ static _FORCE_INLINE_ void zero(Variant *v) { *VariantInternal::get_vector2_array(v) = PackedVector2Array(); }
};
template <>
struct VariantZeroAssigner<PackedVector3Array> {
- static _FORCE_INLINE_ void zero(Variant *v) {}
+ static _FORCE_INLINE_ void zero(Variant *v) { *VariantInternal::get_vector3_array(v) = PackedVector3Array(); }
};
template <>
struct VariantZeroAssigner<PackedColorArray> {
- static _FORCE_INLINE_ void zero(Variant *v) {}
+ static _FORCE_INLINE_ void zero(Variant *v) { *VariantInternal::get_color_array(v) = PackedColorArray(); }
};
template <class T>
@@ -1517,7 +1517,7 @@ struct VariantTypeAdjust<Object *> {
}
};
-// GDNative extension helpers.
+// GDExtension helpers.
template <class T>
struct VariantTypeConstructor {
diff --git a/core/variant/variant_op.cpp b/core/variant/variant_op.cpp
index 25bc241e9b..d4e6dfb4d1 100644
--- a/core/variant/variant_op.cpp
+++ b/core/variant/variant_op.cpp
@@ -229,6 +229,20 @@ public:
static Variant::Type get_return_type() { return GetTypeInfo<Vector4>::VARIANT_TYPE; }
};
+#define register_string_op(m_op_type, m_op_code) \
+ do { \
+ register_op<m_op_type<String, String>>(m_op_code, Variant::STRING, Variant::STRING); \
+ register_op<m_op_type<String, StringName>>(m_op_code, Variant::STRING, Variant::STRING_NAME); \
+ register_op<m_op_type<StringName, String>>(m_op_code, Variant::STRING_NAME, Variant::STRING); \
+ register_op<m_op_type<StringName, StringName>>(m_op_code, Variant::STRING_NAME, Variant::STRING_NAME); \
+ } while (false)
+
+#define register_string_modulo_op(m_class, m_type) \
+ do { \
+ register_op<OperatorEvaluatorStringFormat<String, m_class>>(Variant::OP_MODULE, Variant::STRING, m_type); \
+ register_op<OperatorEvaluatorStringFormat<StringName, m_class>>(Variant::OP_MODULE, Variant::STRING_NAME, m_type); \
+ } while (false)
+
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));
@@ -239,7 +253,7 @@ void Variant::_register_variant_operators() {
register_op<OperatorEvaluatorAdd<double, int64_t, double>>(Variant::OP_ADD, Variant::INT, Variant::FLOAT);
register_op<OperatorEvaluatorAdd<double, double, int64_t>>(Variant::OP_ADD, Variant::FLOAT, Variant::INT);
register_op<OperatorEvaluatorAdd<double, double, double>>(Variant::OP_ADD, Variant::FLOAT, Variant::FLOAT);
- register_op<OperatorEvaluatorAdd<String, String, String>>(Variant::OP_ADD, Variant::STRING, Variant::STRING);
+ register_string_op(OperatorEvaluatorStringConcat, Variant::OP_ADD);
register_op<OperatorEvaluatorAdd<Vector2, Vector2, Vector2>>(Variant::OP_ADD, Variant::VECTOR2, Variant::VECTOR2);
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);
@@ -415,46 +429,46 @@ void Variant::_register_variant_operators() {
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);
- register_op<OperatorEvaluatorStringModT<int64_t>>(Variant::OP_MODULE, Variant::STRING, Variant::INT);
- register_op<OperatorEvaluatorStringModT<double>>(Variant::OP_MODULE, Variant::STRING, Variant::FLOAT);
- register_op<OperatorEvaluatorStringModT<String>>(Variant::OP_MODULE, Variant::STRING, Variant::STRING);
- register_op<OperatorEvaluatorStringModT<Vector2>>(Variant::OP_MODULE, Variant::STRING, Variant::VECTOR2);
- register_op<OperatorEvaluatorStringModT<Vector2i>>(Variant::OP_MODULE, Variant::STRING, Variant::VECTOR2I);
- register_op<OperatorEvaluatorStringModT<Rect2>>(Variant::OP_MODULE, Variant::STRING, Variant::RECT2);
- 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);
- register_op<OperatorEvaluatorStringModT<NodePath>>(Variant::OP_MODULE, Variant::STRING, Variant::NODE_PATH);
- register_op<OperatorEvaluatorStringModObject>(Variant::OP_MODULE, Variant::STRING, Variant::OBJECT);
- register_op<OperatorEvaluatorStringModT<Callable>>(Variant::OP_MODULE, Variant::STRING, Variant::CALLABLE);
- register_op<OperatorEvaluatorStringModT<Signal>>(Variant::OP_MODULE, Variant::STRING, Variant::SIGNAL);
- register_op<OperatorEvaluatorStringModT<Dictionary>>(Variant::OP_MODULE, Variant::STRING, Variant::DICTIONARY);
- register_op<OperatorEvaluatorStringModArray>(Variant::OP_MODULE, Variant::STRING, Variant::ARRAY);
-
- register_op<OperatorEvaluatorStringModT<PackedByteArray>>(Variant::OP_MODULE, Variant::STRING, Variant::PACKED_BYTE_ARRAY);
- register_op<OperatorEvaluatorStringModT<PackedInt32Array>>(Variant::OP_MODULE, Variant::STRING, Variant::PACKED_INT32_ARRAY);
- register_op<OperatorEvaluatorStringModT<PackedInt64Array>>(Variant::OP_MODULE, Variant::STRING, Variant::PACKED_INT64_ARRAY);
- register_op<OperatorEvaluatorStringModT<PackedFloat32Array>>(Variant::OP_MODULE, Variant::STRING, Variant::PACKED_FLOAT32_ARRAY);
- register_op<OperatorEvaluatorStringModT<PackedFloat64Array>>(Variant::OP_MODULE, Variant::STRING, Variant::PACKED_FLOAT64_ARRAY);
- register_op<OperatorEvaluatorStringModT<PackedStringArray>>(Variant::OP_MODULE, Variant::STRING, Variant::PACKED_STRING_ARRAY);
- register_op<OperatorEvaluatorStringModT<PackedVector2Array>>(Variant::OP_MODULE, Variant::STRING, Variant::PACKED_VECTOR2_ARRAY);
- register_op<OperatorEvaluatorStringModT<PackedVector3Array>>(Variant::OP_MODULE, Variant::STRING, Variant::PACKED_VECTOR3_ARRAY);
- register_op<OperatorEvaluatorStringModT<PackedColorArray>>(Variant::OP_MODULE, Variant::STRING, Variant::PACKED_COLOR_ARRAY);
+ register_string_modulo_op(void, Variant::NIL);
+
+ register_string_modulo_op(bool, Variant::BOOL);
+ register_string_modulo_op(int64_t, Variant::INT);
+ register_string_modulo_op(double, Variant::FLOAT);
+ register_string_modulo_op(String, Variant::STRING);
+ register_string_modulo_op(Vector2, Variant::VECTOR2);
+ register_string_modulo_op(Vector2i, Variant::VECTOR2I);
+ register_string_modulo_op(Rect2, Variant::RECT2);
+ register_string_modulo_op(Rect2i, Variant::RECT2I);
+ register_string_modulo_op(Vector3, Variant::VECTOR3);
+ register_string_modulo_op(Vector3i, Variant::VECTOR3I);
+ register_string_modulo_op(Vector4, Variant::VECTOR4);
+ register_string_modulo_op(Vector4i, Variant::VECTOR4I);
+ register_string_modulo_op(Transform2D, Variant::TRANSFORM2D);
+ register_string_modulo_op(Plane, Variant::PLANE);
+ register_string_modulo_op(Quaternion, Variant::QUATERNION);
+ register_string_modulo_op(::AABB, Variant::AABB);
+ register_string_modulo_op(Basis, Variant::BASIS);
+ register_string_modulo_op(Transform3D, Variant::TRANSFORM3D);
+ register_string_modulo_op(Projection, Variant::PROJECTION);
+
+ register_string_modulo_op(Color, Variant::COLOR);
+ register_string_modulo_op(StringName, Variant::STRING_NAME);
+ register_string_modulo_op(NodePath, Variant::NODE_PATH);
+ register_string_modulo_op(Object, Variant::OBJECT);
+ register_string_modulo_op(Callable, Variant::CALLABLE);
+ register_string_modulo_op(Signal, Variant::SIGNAL);
+ register_string_modulo_op(Dictionary, Variant::DICTIONARY);
+ register_string_modulo_op(Array, Variant::ARRAY);
+
+ register_string_modulo_op(PackedByteArray, Variant::PACKED_BYTE_ARRAY);
+ register_string_modulo_op(PackedInt32Array, Variant::PACKED_INT32_ARRAY);
+ register_string_modulo_op(PackedInt64Array, Variant::PACKED_INT64_ARRAY);
+ register_string_modulo_op(PackedFloat32Array, Variant::PACKED_FLOAT32_ARRAY);
+ register_string_modulo_op(PackedFloat64Array, Variant::PACKED_FLOAT64_ARRAY);
+ register_string_modulo_op(PackedStringArray, Variant::PACKED_STRING_ARRAY);
+ register_string_modulo_op(PackedVector2Array, Variant::PACKED_VECTOR2_ARRAY);
+ register_string_modulo_op(PackedVector3Array, Variant::PACKED_VECTOR3_ARRAY);
+ register_string_modulo_op(PackedColorArray, Variant::PACKED_COLOR_ARRAY);
register_op<OperatorEvaluatorPow<int64_t, int64_t, int64_t>>(Variant::OP_POWER, Variant::INT, Variant::INT);
register_op<OperatorEvaluatorPow<double, int64_t, double>>(Variant::OP_POWER, Variant::INT, Variant::FLOAT);
@@ -498,7 +512,7 @@ void Variant::_register_variant_operators() {
register_op<OperatorEvaluatorEqual<int64_t, double>>(Variant::OP_EQUAL, Variant::INT, Variant::FLOAT);
register_op<OperatorEvaluatorEqual<double, int64_t>>(Variant::OP_EQUAL, Variant::FLOAT, Variant::INT);
register_op<OperatorEvaluatorEqual<double, double>>(Variant::OP_EQUAL, Variant::FLOAT, Variant::FLOAT);
- register_op<OperatorEvaluatorEqual<String, String>>(Variant::OP_EQUAL, Variant::STRING, Variant::STRING);
+ register_string_op(OperatorEvaluatorEqual, Variant::OP_EQUAL);
register_op<OperatorEvaluatorEqual<Vector2, Vector2>>(Variant::OP_EQUAL, Variant::VECTOR2, Variant::VECTOR2);
register_op<OperatorEvaluatorEqual<Vector2i, Vector2i>>(Variant::OP_EQUAL, Variant::VECTOR2I, Variant::VECTOR2I);
register_op<OperatorEvaluatorEqual<Rect2, Rect2>>(Variant::OP_EQUAL, Variant::RECT2, Variant::RECT2);
@@ -516,10 +530,6 @@ void Variant::_register_variant_operators() {
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);
- register_op<OperatorEvaluatorEqual<String, StringName>>(Variant::OP_EQUAL, Variant::STRING, Variant::STRING_NAME);
- register_op<OperatorEvaluatorEqual<StringName, StringName>>(Variant::OP_EQUAL, Variant::STRING_NAME, Variant::STRING_NAME);
-
register_op<OperatorEvaluatorEqual<NodePath, NodePath>>(Variant::OP_EQUAL, Variant::NODE_PATH, Variant::NODE_PATH);
register_op<OperatorEvaluatorEqual<::RID, ::RID>>(Variant::OP_EQUAL, Variant::RID, Variant::RID);
@@ -621,7 +631,7 @@ void Variant::_register_variant_operators() {
register_op<OperatorEvaluatorNotEqual<int64_t, double>>(Variant::OP_NOT_EQUAL, Variant::INT, Variant::FLOAT);
register_op<OperatorEvaluatorNotEqual<double, int64_t>>(Variant::OP_NOT_EQUAL, Variant::FLOAT, Variant::INT);
register_op<OperatorEvaluatorNotEqual<double, double>>(Variant::OP_NOT_EQUAL, Variant::FLOAT, Variant::FLOAT);
- register_op<OperatorEvaluatorNotEqual<String, String>>(Variant::OP_NOT_EQUAL, Variant::STRING, Variant::STRING);
+ register_string_op(OperatorEvaluatorNotEqual, Variant::OP_NOT_EQUAL);
register_op<OperatorEvaluatorNotEqual<Vector2, Vector2>>(Variant::OP_NOT_EQUAL, Variant::VECTOR2, Variant::VECTOR2);
register_op<OperatorEvaluatorNotEqual<Vector2i, Vector2i>>(Variant::OP_NOT_EQUAL, Variant::VECTOR2I, Variant::VECTOR2I);
register_op<OperatorEvaluatorNotEqual<Rect2, Rect2>>(Variant::OP_NOT_EQUAL, Variant::RECT2, Variant::RECT2);
@@ -639,10 +649,6 @@ void Variant::_register_variant_operators() {
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);
- register_op<OperatorEvaluatorNotEqual<String, StringName>>(Variant::OP_NOT_EQUAL, Variant::STRING, Variant::STRING_NAME);
- register_op<OperatorEvaluatorNotEqual<StringName, StringName>>(Variant::OP_NOT_EQUAL, Variant::STRING_NAME, Variant::STRING_NAME);
-
register_op<OperatorEvaluatorNotEqual<NodePath, NodePath>>(Variant::OP_NOT_EQUAL, Variant::NODE_PATH, Variant::NODE_PATH);
register_op<OperatorEvaluatorNotEqual<::RID, ::RID>>(Variant::OP_NOT_EQUAL, Variant::RID, Variant::RID);
@@ -895,10 +901,7 @@ void Variant::_register_variant_operators() {
register_op<OperatorEvaluatorNotFloat>(Variant::OP_NOT, Variant::FLOAT, Variant::NIL);
register_op<OperatorEvaluatorNotObject>(Variant::OP_NOT, Variant::OBJECT, Variant::NIL);
- register_op<OperatorEvaluatorInStringFind<String>>(Variant::OP_IN, Variant::STRING, Variant::STRING);
- register_op<OperatorEvaluatorInStringFind<StringName>>(Variant::OP_IN, Variant::STRING_NAME, Variant::STRING);
- register_op<OperatorEvaluatorInStringNameFind<String>>(Variant::OP_IN, Variant::STRING, Variant::STRING_NAME);
- register_op<OperatorEvaluatorInStringNameFind<StringName>>(Variant::OP_IN, Variant::STRING_NAME, Variant::STRING_NAME);
+ register_string_op(OperatorEvaluatorInStringFind, Variant::OP_IN);
register_op<OperatorEvaluatorInDictionaryHasNil>(Variant::OP_IN, Variant::NIL, Variant::DICTIONARY);
register_op<OperatorEvaluatorInDictionaryHas<bool>>(Variant::OP_IN, Variant::BOOL, Variant::DICTIONARY);
@@ -996,6 +999,7 @@ void Variant::_register_variant_operators() {
register_op<OperatorEvaluatorInArrayFind<float, PackedFloat64Array>>(Variant::OP_IN, Variant::FLOAT, Variant::PACKED_FLOAT64_ARRAY);
register_op<OperatorEvaluatorInArrayFind<String, PackedStringArray>>(Variant::OP_IN, Variant::STRING, Variant::PACKED_STRING_ARRAY);
+ register_op<OperatorEvaluatorInArrayFind<StringName, PackedStringArray>>(Variant::OP_IN, Variant::STRING_NAME, Variant::PACKED_STRING_ARRAY);
register_op<OperatorEvaluatorInArrayFind<Vector2, PackedVector2Array>>(Variant::OP_IN, Variant::VECTOR2, Variant::PACKED_VECTOR2_ARRAY);
register_op<OperatorEvaluatorInArrayFind<Vector3, PackedVector3Array>>(Variant::OP_IN, Variant::VECTOR3, Variant::PACKED_VECTOR3_ARRAY);
@@ -1006,6 +1010,9 @@ void Variant::_register_variant_operators() {
register_op<OperatorEvaluatorObjectHasPropertyStringName>(Variant::OP_IN, Variant::STRING_NAME, Variant::OBJECT);
}
+#undef register_string_op
+#undef register_string_modulo_op
+
void Variant::_unregister_variant_operators() {
}
diff --git a/core/variant/variant_op.h b/core/variant/variant_op.h
index ec1ce67445..ea4216322c 100644
--- a/core/variant/variant_op.h
+++ b/core/variant/variant_op.h
@@ -875,7 +875,33 @@ public:
static Variant::Type get_return_type() { return GetTypeInfo<Vector<T>>::VARIANT_TYPE; }
};
-class OperatorEvaluatorStringModNil {
+template <class Left, class Right>
+class OperatorEvaluatorStringConcat {
+public:
+ static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
+ const String a(*VariantGetInternalPtr<Left>::get_ptr(&p_left));
+ const String b(*VariantGetInternalPtr<Right>::get_ptr(&p_right));
+ *r_ret = a + b;
+ r_valid = true;
+ }
+ static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+ const String a(*VariantGetInternalPtr<Left>::get_ptr(left));
+ const String b(*VariantGetInternalPtr<Right>::get_ptr(right));
+ *VariantGetInternalPtr<String>::get_ptr(r_ret) = a + b;
+ }
+ static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
+ const String a(PtrToArg<Left>::convert(left));
+ const String b(PtrToArg<Right>::convert(right));
+ PtrToArg<String>::encode(a + b, r_ret);
+ }
+ static Variant::Type get_return_type() { return Variant::STRING; }
+};
+
+template <class S, class T>
+class OperatorEvaluatorStringFormat;
+
+template <class S>
+class OperatorEvaluatorStringFormat<S, void> {
public:
_FORCE_INLINE_ static String do_mod(const String &s, bool *r_valid) {
Array values;
@@ -888,20 +914,22 @@ public:
return a;
}
static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
- const String &a = *VariantGetInternalPtr<String>::get_ptr(&p_left);
- *r_ret = do_mod(a, &r_valid);
- r_valid = true;
+ *r_ret = do_mod(*VariantGetInternalPtr<S>::get_ptr(&p_left), &r_valid);
}
static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
- *VariantGetInternalPtr<String>::get_ptr(r_ret) = do_mod(*VariantGetInternalPtr<String>::get_ptr(left), nullptr);
+ bool valid = true;
+ String result = do_mod(*VariantGetInternalPtr<S>::get_ptr(left), &valid);
+ ERR_FAIL_COND_MSG(!valid, result);
+ *VariantGetInternalPtr<String>::get_ptr(r_ret) = result;
}
static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
- PtrToArg<String>::encode(do_mod(PtrToArg<String>::convert(left), nullptr), r_ret);
+ PtrToArg<String>::encode(do_mod(PtrToArg<S>::convert(left), nullptr), r_ret);
}
static Variant::Type get_return_type() { return Variant::STRING; }
};
-class OperatorEvaluatorStringModArray {
+template <class S>
+class OperatorEvaluatorStringFormat<S, Array> {
public:
_FORCE_INLINE_ static String do_mod(const String &s, const Array &p_values, bool *r_valid) {
String a = s.sprintf(p_values, r_valid);
@@ -911,20 +939,22 @@ public:
return a;
}
static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
- const String &a = *VariantGetInternalPtr<String>::get_ptr(&p_left);
- *r_ret = do_mod(a, *VariantGetInternalPtr<Array>::get_ptr(&p_right), &r_valid);
- r_valid = true;
+ *r_ret = do_mod(*VariantGetInternalPtr<S>::get_ptr(&p_left), *VariantGetInternalPtr<Array>::get_ptr(&p_right), &r_valid);
}
static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
- *VariantGetInternalPtr<String>::get_ptr(r_ret) = do_mod(*VariantGetInternalPtr<String>::get_ptr(left), *VariantGetInternalPtr<Array>::get_ptr(right), nullptr);
+ bool valid = true;
+ String result = do_mod(*VariantGetInternalPtr<S>::get_ptr(left), *VariantGetInternalPtr<Array>::get_ptr(right), &valid);
+ ERR_FAIL_COND_MSG(!valid, result);
+ *VariantGetInternalPtr<String>::get_ptr(r_ret) = result;
}
static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
- PtrToArg<String>::encode(do_mod(PtrToArg<String>::convert(left), PtrToArg<Array>::convert(right), nullptr), r_ret);
+ PtrToArg<String>::encode(do_mod(PtrToArg<S>::convert(left), PtrToArg<Array>::convert(right), nullptr), r_ret);
}
static Variant::Type get_return_type() { return Variant::STRING; }
};
-class OperatorEvaluatorStringModObject {
+template <class S>
+class OperatorEvaluatorStringFormat<S, Object> {
public:
_FORCE_INLINE_ static String do_mod(const String &s, const Object *p_object, bool *r_valid) {
Array values;
@@ -937,21 +967,22 @@ public:
return a;
}
static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
- const String &a = *VariantGetInternalPtr<String>::get_ptr(&p_left);
- *r_ret = do_mod(a, p_right.get_validated_object(), &r_valid);
- r_valid = true;
+ *r_ret = do_mod(*VariantGetInternalPtr<S>::get_ptr(&p_left), p_right.get_validated_object(), &r_valid);
}
static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
- *VariantGetInternalPtr<String>::get_ptr(r_ret) = do_mod(*VariantGetInternalPtr<String>::get_ptr(left), right->get_validated_object(), nullptr);
+ bool valid = true;
+ String result = do_mod(*VariantGetInternalPtr<S>::get_ptr(left), right->get_validated_object(), &valid);
+ ERR_FAIL_COND_MSG(!valid, result);
+ *VariantGetInternalPtr<String>::get_ptr(r_ret) = result;
}
static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
- PtrToArg<String>::encode(do_mod(PtrToArg<String>::convert(left), PtrToArg<Object *>::convert(right), nullptr), r_ret);
+ PtrToArg<String>::encode(do_mod(PtrToArg<S>::convert(left), PtrToArg<Object *>::convert(right), nullptr), r_ret);
}
static Variant::Type get_return_type() { return Variant::STRING; }
};
-template <class T>
-class OperatorEvaluatorStringModT {
+template <class S, class T>
+class OperatorEvaluatorStringFormat {
public:
_FORCE_INLINE_ static String do_mod(const String &s, const T &p_value, bool *r_valid) {
Array values;
@@ -963,15 +994,16 @@ public:
return a;
}
static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
- const String &a = *VariantGetInternalPtr<String>::get_ptr(&p_left);
- *r_ret = do_mod(a, *VariantGetInternalPtr<T>::get_ptr(&p_right), &r_valid);
- r_valid = true;
+ *r_ret = do_mod(*VariantGetInternalPtr<S>::get_ptr(&p_left), *VariantGetInternalPtr<T>::get_ptr(&p_right), &r_valid);
}
static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
- *VariantGetInternalPtr<String>::get_ptr(r_ret) = do_mod(*VariantGetInternalPtr<String>::get_ptr(left), *VariantGetInternalPtr<T>::get_ptr(right), nullptr);
+ bool valid = true;
+ String result = do_mod(*VariantGetInternalPtr<S>::get_ptr(left), *VariantGetInternalPtr<T>::get_ptr(right), &valid);
+ ERR_FAIL_COND_MSG(!valid, result);
+ *VariantGetInternalPtr<String>::get_ptr(r_ret) = result;
}
static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
- PtrToArg<String>::encode(do_mod(PtrToArg<String>::convert(left), PtrToArg<T>::convert(right), nullptr), r_ret);
+ PtrToArg<String>::encode(do_mod(PtrToArg<S>::convert(left), PtrToArg<T>::convert(right), nullptr), r_ret);
}
static Variant::Type get_return_type() { return Variant::STRING; }
};
@@ -1280,8 +1312,11 @@ public:
////
+template <class Left, class Right>
+class OperatorEvaluatorInStringFind;
+
template <class Left>
-class OperatorEvaluatorInStringFind {
+class OperatorEvaluatorInStringFind<Left, String> {
public:
static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
const Left &str_a = *VariantGetInternalPtr<Left>::get_ptr(&p_left);
@@ -1302,7 +1337,7 @@ public:
};
template <class Left>
-class OperatorEvaluatorInStringNameFind {
+class OperatorEvaluatorInStringFind<Left, StringName> {
public:
static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
const Left &str_a = *VariantGetInternalPtr<Left>::get_ptr(&p_left);
diff --git a/core/variant/variant_parser.cpp b/core/variant/variant_parser.cpp
index d2e4d752a4..f122ed5f8f 100644
--- a/core/variant/variant_parser.cpp
+++ b/core/variant/variant_parser.cpp
@@ -35,39 +35,93 @@
#include "core/os/keyboard.h"
#include "core/string/string_buffer.h"
-char32_t VariantParser::StreamFile::get_char() {
- return f->get_8();
+char32_t VariantParser::Stream::get_char() {
+ // is within buffer?
+ if (readahead_pointer < readahead_filled) {
+ return readahead_buffer[readahead_pointer++];
+ }
+
+ // attempt to readahead
+ readahead_filled = _read_buffer(readahead_buffer, readahead_enabled ? READAHEAD_SIZE : 1);
+ if (readahead_filled) {
+ readahead_pointer = 0;
+ } else {
+ // EOF
+ readahead_pointer = 1;
+ eof = true;
+ return 0;
+ }
+ return get_char();
+}
+
+bool VariantParser::Stream::is_eof() const {
+ if (readahead_enabled) {
+ return eof;
+ }
+ return _is_eof();
}
bool VariantParser::StreamFile::is_utf8() const {
return true;
}
-bool VariantParser::StreamFile::is_eof() const {
+bool VariantParser::StreamFile::_is_eof() const {
return f->eof_reached();
}
-char32_t VariantParser::StreamString::get_char() {
- if (pos > s.length()) {
- return 0;
- } else if (pos == s.length()) {
- // You need to try to read again when you have reached the end for EOF to be reported,
- // so this works the same as files (like StreamFile does)
- pos++;
- return 0;
- } else {
- return s[pos++];
+uint32_t VariantParser::StreamFile::_read_buffer(char32_t *p_buffer, uint32_t p_num_chars) {
+ // The buffer is assumed to include at least one character (for null terminator)
+ ERR_FAIL_COND_V(!p_num_chars, 0);
+
+ uint8_t *temp = (uint8_t *)alloca(p_num_chars);
+ uint64_t num_read = f->get_buffer(temp, p_num_chars);
+ ERR_FAIL_COND_V(num_read == UINT64_MAX, 0);
+
+ // translate to wchar
+ for (uint32_t n = 0; n < num_read; n++) {
+ p_buffer[n] = temp[n];
}
+
+ // could be less than p_num_chars, or zero
+ return num_read;
}
bool VariantParser::StreamString::is_utf8() const {
return false;
}
-bool VariantParser::StreamString::is_eof() const {
+bool VariantParser::StreamString::_is_eof() const {
return pos > s.length();
}
+uint32_t VariantParser::StreamString::_read_buffer(char32_t *p_buffer, uint32_t p_num_chars) {
+ // The buffer is assumed to include at least one character (for null terminator)
+ ERR_FAIL_COND_V(!p_num_chars, 0);
+
+ int available = MAX(s.length() - pos, 0);
+ if (available >= (int)p_num_chars) {
+ const char32_t *src = s.ptr();
+ src += pos;
+ memcpy(p_buffer, src, p_num_chars * sizeof(char32_t));
+ pos += p_num_chars;
+
+ return p_num_chars;
+ }
+
+ // going to reach EOF
+ if (available) {
+ const char32_t *src = s.ptr();
+ src += pos;
+ memcpy(p_buffer, src, available * sizeof(char32_t));
+ pos += available;
+ }
+
+ // add a zero
+ p_buffer[available] = 0;
+
+ return available;
+}
+
/////////////////////////////////////////////////////////////////////////////////////////////////
const char *VariantParser::tk_name[TK_MAX] = {
@@ -1283,7 +1337,7 @@ Error VariantParser::_parse_dictionary(Dictionary &object, Stream *p_stream, int
Variant v;
err = parse_value(token, v, p_stream, line, r_err_str, p_res_parser);
- if (err) {
+ if (err && err != ERR_FILE_MISSING_DEPENDENCIES) {
return err;
}
object[key] = v;
diff --git a/core/variant/variant_parser.h b/core/variant/variant_parser.h
index 56b484c8bc..fdea355c4b 100644
--- a/core/variant/variant_parser.h
+++ b/core/variant/variant_parser.h
@@ -38,35 +38,55 @@
class VariantParser {
public:
struct Stream {
- virtual char32_t get_char() = 0;
- virtual bool is_utf8() const = 0;
- virtual bool is_eof() const = 0;
-
+ private:
+ enum { READAHEAD_SIZE = 2048 };
+ char32_t readahead_buffer[READAHEAD_SIZE];
+ uint32_t readahead_pointer = 0;
+ uint32_t readahead_filled = 0;
+ bool eof = false;
+
+ protected:
+ bool readahead_enabled = true;
+ virtual uint32_t _read_buffer(char32_t *p_buffer, uint32_t p_num_chars) = 0;
+ virtual bool _is_eof() const = 0;
+
+ public:
char32_t saved = 0;
+ char32_t get_char();
+ virtual bool is_utf8() const = 0;
+ bool is_eof() const;
+
Stream() {}
virtual ~Stream() {}
};
struct StreamFile : public Stream {
+ protected:
+ virtual uint32_t _read_buffer(char32_t *p_buffer, uint32_t p_num_chars) override;
+ virtual bool _is_eof() const override;
+
+ public:
Ref<FileAccess> f;
- virtual char32_t get_char() override;
virtual bool is_utf8() const override;
- virtual bool is_eof() const override;
- StreamFile() {}
+ StreamFile(bool p_readahead_enabled = true) { readahead_enabled = p_readahead_enabled; }
};
struct StreamString : public Stream {
String s;
+
+ private:
int pos = 0;
- virtual char32_t get_char() override;
- virtual bool is_utf8() const override;
- virtual bool is_eof() const override;
+ protected:
+ virtual uint32_t _read_buffer(char32_t *p_buffer, uint32_t p_num_chars) override;
+ virtual bool _is_eof() const override;
- StreamString() {}
+ public:
+ virtual bool is_utf8() const override;
+ StreamString(bool p_readahead_enabled = true) { readahead_enabled = p_readahead_enabled; }
};
typedef Error (*ParseResourceFunc)(void *p_self, Stream *p_stream, Ref<Resource> &r_res, int &line, String &r_err_str);
diff --git a/core/variant/variant_utility.cpp b/core/variant/variant_utility.cpp
index 3843c32bcc..4b82981fa9 100644
--- a/core/variant/variant_utility.cpp
+++ b/core/variant/variant_utility.cpp
@@ -322,8 +322,52 @@ struct VariantUtilityFunctions {
return Math::step_decimals(step);
}
- static inline double snapped(double value, double step) {
- return Math::snapped(value, step);
+ static inline Variant snapped(const Variant &x, const Variant &step, Callable::CallError &r_error) {
+ r_error.error = Callable::CallError::CALL_OK;
+ if (x.get_type() != step.get_type() && !((x.get_type() == Variant::INT && step.get_type() == Variant::FLOAT) || (x.get_type() == Variant::FLOAT && step.get_type() == Variant::INT))) {
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.argument = 1;
+ return Variant();
+ }
+
+ switch (step.get_type()) {
+ case Variant::INT: {
+ return snappedi(x, VariantInternalAccessor<int64_t>::get(&step));
+ } break;
+ case Variant::FLOAT: {
+ return snappedf(x, VariantInternalAccessor<double>::get(&step));
+ } break;
+ case Variant::VECTOR2: {
+ return VariantInternalAccessor<Vector2>::get(&x).snapped(VariantInternalAccessor<Vector2>::get(&step));
+ } break;
+ case Variant::VECTOR2I: {
+ return VariantInternalAccessor<Vector2i>::get(&x).snapped(VariantInternalAccessor<Vector2i>::get(&step));
+ } break;
+ case Variant::VECTOR3: {
+ return VariantInternalAccessor<Vector3>::get(&x).snapped(VariantInternalAccessor<Vector3>::get(&step));
+ } break;
+ case Variant::VECTOR3I: {
+ return VariantInternalAccessor<Vector3i>::get(&x).snapped(VariantInternalAccessor<Vector3i>::get(&step));
+ } break;
+ case Variant::VECTOR4: {
+ return VariantInternalAccessor<Vector4>::get(&x).snapped(VariantInternalAccessor<Vector4>::get(&step));
+ } break;
+ case Variant::VECTOR4I: {
+ return VariantInternalAccessor<Vector4i>::get(&x).snapped(VariantInternalAccessor<Vector4i>::get(&step));
+ } break;
+ default: {
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
+ return Variant();
+ }
+ }
+ }
+
+ static inline double snappedf(double x, double step) {
+ return Math::snapped(x, step);
+ }
+
+ static inline int64_t snappedi(double x, int64_t step) {
+ return Math::snapped(x, step);
}
static inline Variant lerp(const Variant &from, const Variant &to, double weight, Callable::CallError &r_error) {
@@ -335,6 +379,9 @@ struct VariantUtilityFunctions {
}
switch (from.get_type()) {
+ case Variant::INT: {
+ return lerpf(VariantInternalAccessor<int64_t>::get(&from), to, weight);
+ } break;
case Variant::FLOAT: {
return lerpf(VariantInternalAccessor<double>::get(&from), to, weight);
} break;
@@ -389,6 +436,10 @@ struct VariantUtilityFunctions {
return Math::bezier_interpolate(p_start, p_control_1, p_control_2, p_end, p_t);
}
+ static inline double bezier_derivative(double p_start, double p_control_1, double p_control_2, double p_end, double p_t) {
+ return Math::bezier_derivative(p_start, p_control_1, p_control_2, p_end, p_t);
+ }
+
static inline double lerp_angle(double from, double to, double weight) {
return Math::lerp_angle(from, to, weight);
}
@@ -1132,6 +1183,40 @@ static _FORCE_INLINE_ Variant::Type get_ret_type_helper(void (*p_func)(P...)) {
}; \
register_utility_function<Func_##m_func>(#m_func, m_args)
+#define FUNCBINDVR2(m_func, m_args, m_category) \
+ class Func_##m_func { \
+ public: \
+ static void call(Variant *r_ret, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { \
+ r_error.error = Callable::CallError::CALL_OK; \
+ *r_ret = VariantUtilityFunctions::m_func(*p_args[0], *p_args[1], r_error); \
+ } \
+ static void validated_call(Variant *r_ret, const Variant **p_args, int p_argcount) { \
+ Callable::CallError ce; \
+ *r_ret = VariantUtilityFunctions::m_func(*p_args[0], *p_args[1], ce); \
+ } \
+ static void ptrcall(void *ret, const void **p_args, int p_argcount) { \
+ Callable::CallError ce; \
+ Variant r; \
+ r = VariantUtilityFunctions::m_func(PtrToArg<Variant>::convert(p_args[0]), PtrToArg<Variant>::convert(p_args[1]), ce); \
+ PtrToArg<Variant>::encode(r, ret); \
+ } \
+ static int get_argument_count() { \
+ return 2; \
+ } \
+ static Variant::Type get_argument_type(int p_arg) { \
+ return Variant::NIL; \
+ } \
+ static Variant::Type get_return_type() { \
+ return Variant::NIL; \
+ } \
+ static bool has_return_type() { \
+ return true; \
+ } \
+ static bool is_vararg() { return false; } \
+ static Variant::UtilityFunctionType get_type() { return m_category; } \
+ }; \
+ register_utility_function<Func_##m_func>(#m_func, m_args)
+
#define FUNCBINDVR3(m_func, m_args, m_category) \
class Func_##m_func { \
public: \
@@ -1415,6 +1500,10 @@ void Variant::_register_variant_utility_functions() {
FUNCBINDR(signf, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH);
FUNCBINDR(signi, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH);
+ FUNCBINDVR2(snapped, sarray("x", "step"), Variant::UTILITY_FUNC_TYPE_MATH);
+ FUNCBINDR(snappedf, sarray("x", "step"), Variant::UTILITY_FUNC_TYPE_MATH);
+ FUNCBINDR(snappedi, sarray("x", "step"), Variant::UTILITY_FUNC_TYPE_MATH);
+
FUNCBINDR(pow, sarray("base", "exp"), Variant::UTILITY_FUNC_TYPE_MATH);
FUNCBINDR(log, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH);
FUNCBINDR(exp, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH);
@@ -1428,7 +1517,6 @@ void Variant::_register_variant_utility_functions() {
FUNCBINDR(ease, sarray("x", "curve"), Variant::UTILITY_FUNC_TYPE_MATH);
FUNCBINDR(step_decimals, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH);
- FUNCBINDR(snapped, sarray("x", "step"), 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);
@@ -1437,6 +1525,7 @@ void Variant::_register_variant_utility_functions() {
FUNCBINDR(cubic_interpolate_in_time, sarray("from", "to", "pre", "post", "weight", "to_t", "pre_t", "post_t"), Variant::UTILITY_FUNC_TYPE_MATH);
FUNCBINDR(cubic_interpolate_angle_in_time, sarray("from", "to", "pre", "post", "weight", "to_t", "pre_t", "post_t"), Variant::UTILITY_FUNC_TYPE_MATH);
FUNCBINDR(bezier_interpolate, sarray("start", "control_1", "control_2", "end", "t"), Variant::UTILITY_FUNC_TYPE_MATH);
+ FUNCBINDR(bezier_derivative, 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);
FUNCBINDR(inverse_lerp, sarray("from", "to", "weight"), Variant::UTILITY_FUNC_TYPE_MATH);
FUNCBINDR(remap, sarray("value", "istart", "istop", "ostart", "ostop"), Variant::UTILITY_FUNC_TYPE_MATH);
diff --git a/doc/classes/@GlobalScope.xml b/doc/classes/@GlobalScope.xml
index ed404ea504..6b0dccd7fc 100644
--- a/doc/classes/@GlobalScope.xml
+++ b/doc/classes/@GlobalScope.xml
@@ -16,7 +16,7 @@
<return type="Variant" />
<param index="0" name="x" type="Variant" />
<description>
- Returns the absolute value of a [Variant] parameter [param x] (i.e. non-negative value). Variant types [int], [float], [Vector2], [Vector2i], [Vector3] and [Vector3i] are supported.
+ Returns the absolute value of a [Variant] parameter [param x] (i.e. non-negative value). Supported types: [int], [float], [Vector2], [Vector2i], [Vector3], [Vector3i], [Vector4], [Vector4i].
[codeblock]
var a = abs(-1)
# a is 1
@@ -36,6 +36,7 @@
var f = abs(Vector3i(-7, -8, -9))
# f is (7, 8, 9)
[/codeblock]
+ [b]Note:[/b] For better type safety, use [method absf], [method absi], [method Vector2.abs], [method Vector2i.abs], [method Vector3.abs], [method Vector3i.abs], [method Vector4.abs], or [method Vector4i.abs].
</description>
</method>
<method name="absf">
@@ -106,6 +107,17 @@
[/codeblock]
</description>
</method>
+ <method name="bezier_derivative">
+ <return type="float" />
+ <param index="0" name="start" type="float" />
+ <param index="1" name="control_1" type="float" />
+ <param index="2" name="control_2" type="float" />
+ <param index="3" name="end" type="float" />
+ <param index="4" name="t" type="float" />
+ <description>
+ Returns the derivative at the given [param t] on a one-dimensional [url=https://en.wikipedia.org/wiki/B%C3%A9zier_curve]Bézier curve[/url] defined by the given [param control_1], [param control_2], and [param end] points.
+ </description>
+ </method>
<method name="bezier_interpolate">
<return type="float" />
<param index="0" name="start" type="float" />
@@ -114,7 +126,7 @@
<param index="3" name="end" type="float" />
<param index="4" name="t" type="float" />
<description>
- Returns the point at the given [param t] on a one-dimensional [url=https://en.wikipedia.org/wiki/B%C3%A9zier_curve]Bezier curve[/url] defined by the given [param control_1], [param control_2], and [param end] points.
+ Returns the point at the given [param t] on a one-dimensional [url=https://en.wikipedia.org/wiki/B%C3%A9zier_curve]Bézier curve[/url] defined by the given [param control_1], [param control_2], and [param end] points.
</description>
</method>
<method name="bytes_to_var">
@@ -143,7 +155,7 @@
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, see [method ceilf], [method ceili], [method Vector2.ceil], [method Vector3.ceil] and [method Vector4.ceil].
+ [b]Note:[/b] For better type safety, use [method ceilf], [method ceili], [method Vector2.ceil], [method Vector3.ceil], or [method Vector4.ceil].
</description>
</method>
<method name="ceilf">
@@ -168,7 +180,7 @@
<param index="1" name="min" type="Variant" />
<param index="2" name="max" type="Variant" />
<description>
- Clamps the [param value], returning a [Variant] not less than [param min] and not more than [param max]. Variant types [int], [float], [Vector2], [Vector2i], [Vector3] and [Vector3i] are supported.
+ Clamps the [param value], returning a [Variant] not less than [param min] and not more than [param max]. Supported types: [int], [float], [Vector2], [Vector2i], [Vector3], [Vector3i], [Vector4], [Vector4i].
[codeblock]
var a = clamp(-10, -1, 5)
# a is -1
@@ -188,6 +200,7 @@
var f = clamp(Vector3i(-7, -8, -9), Vector3i(-1, 2, 3), Vector3i(-4, -5, -6))
# f is (-4, -5, -6)
[/codeblock]
+ [b]Note:[/b] For better type safety, use [method clampf], [method clampi], [method Vector2.clamp], [method Vector2i.clamp], [method Vector3.clamp], [method Vector3i.clamp], [method Vector4.clamp], or [method Vector4i.clamp].
</description>
</method>
<method name="clampf">
@@ -367,7 +380,7 @@
a = floor(-2.99) # a is -3.0
[/codeblock]
See also [method ceil], [method round], and [method snapped].
- [b]Note:[/b] For better type safety, see [method floorf], [method floori], [method Vector2.floor], [method Vector3.floor] and [method Vector4.floor].
+ [b]Note:[/b] For better type safety, use [method floorf], [method floori], [method Vector2.floor], [method Vector3.floor], or [method Vector4.floor].
</description>
</method>
<method name="floorf">
@@ -527,7 +540,7 @@
<param index="2" name="weight" type="Variant" />
<description>
Linearly interpolates between two values by the factor defined in [param weight]. To perform interpolation, [param weight] 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]. If this is not desired, use [method clamp] on the result of this function.
- Both [param from] and [param to] must be the same type. Supported types: [float], [Vector2], [Vector3], [Vector4], [Color], [Quaternion], [Basis].
+ Both [param from] and [param to] must be the same type. Supported types: [int], [float], [Vector2], [Vector3], [Vector4], [Color], [Quaternion], [Basis].
[codeblock]
lerp(0, 4, 0.75) # Returns 3.0
[/codeblock]
@@ -783,14 +796,13 @@
</method>
<method name="printraw" qualifiers="vararg">
<description>
- Prints one or more arguments to strings in the best way possible to console. Unlike [method print], no newline is automatically added at the end.
+ Prints one or more arguments to strings in the best way possible to the OS terminal. Unlike [method print], no newline is automatically added at the end.
[codeblock]
printraw("A")
printraw("B")
printraw("C")
- # Prints ABC
+ # Prints ABC to terminal
[/codeblock]
- [b]Note:[/b] Due to limitations with Godot's built-in console, this only prints to the terminal. If you need to print in the editor, use another method, such as [method print].
</description>
</method>
<method name="prints" qualifiers="vararg">
@@ -950,7 +962,7 @@
round(2.6) # Returns 3
[/codeblock]
See also [method floor], [method ceil], and [method snapped].
- [b]Note:[/b] For better type safety, use [method roundf], [method roundi], [method Vector2.round], [method Vector3.round] or [method Vector4.round], instead.
+ [b]Note:[/b] For better type safety, use [method roundf], [method roundi], [method Vector2.round], [method Vector3.round], or [method Vector4.round].
</description>
</method>
<method name="roundf">
@@ -987,21 +999,22 @@
<return type="Variant" />
<param index="0" name="x" type="Variant" />
<description>
- Returns the sign of [param x] as same type of [Variant] as [param x] with each component being -1, 0 and 1 for each negative, zero and positive values respectively. Variant types [int], [float], [Vector2], [Vector2i], [Vector3] and [Vector3i] are supported.
+ Returns the same type of [Variant] as [param x], with [code]-1[/code] for negative values, [code]1[/code] for positive values, and [code]0[/code] for zeros. Supported types: [int], [float], [Vector2], [Vector2i], [Vector3], [Vector3i], [Vector4], [Vector4i].
[codeblock]
sign(-6.0) # Returns -1
sign(0.0) # Returns 0
sign(6.0) # Returns 1
- sign(Vector3(-6.0, 0.0, 6.0) # Returns (-1, 0, 1)
+ sign(Vector3(-6.0, 0.0, 6.0)) # Returns (-1, 0, 1)
[/codeblock]
+ [b]Note:[/b] For better type safety, use [method signf], [method signi], [method Vector2.sign], [method Vector2i.sign], [method Vector3.sign], [method Vector3i.sign], [method Vector4.sign], or [method Vector4i.sign].
</description>
</method>
<method name="signf">
<return type="float" />
<param index="0" name="x" type="float" />
<description>
- Returns the sign of [param x] as a [float]: -1.0 or 1.0. Returns 0.0 if [param x] is 0.0.
+ Returns [code]-1.0[/code] if [param x] is negative, [code]1.0[/code] if [param x] is positive, and [code]0.0[/code] if if [param x] is zero.
[codeblock]
sign(-6.5) # Returns -1.0
sign(0.0) # Returns 0.0
@@ -1013,7 +1026,7 @@
<return type="int" />
<param index="0" name="x" type="int" />
<description>
- Returns the sign of [param x] as an [int]: -1 or 1. Returns 0 if [param x] is 0.
+ Returns [code]-1[/code] if [param x] is negative, [code]1[/code] if [param x] is positive, and [code]0[/code] if if [param x] is zero.
[codeblock]
sign(-6) # Returns -1
sign(0) # Returns 0
@@ -1063,16 +1076,46 @@
</description>
</method>
<method name="snapped">
+ <return type="Variant" />
+ <param index="0" name="x" type="Variant" />
+ <param index="1" name="step" type="Variant" />
+ <description>
+ Returns the multiple of [param step] that is the closest to [param x]. This can also be used to round a floating point number to an arbitrary number of decimals.
+ The returned value is the same type of [Variant] as [param step]. Supported types: [int], [float], [Vector2], [Vector2i], [Vector3], [Vector3i], [Vector4], [Vector4i].
+ [codeblock]
+ snapped(100, 32) # Returns 96
+ snapped(3.14159, 0.01) # Returns 3.14
+
+ snapped(Vector2(34, 70), Vector2(8, 8)) # Returns (32, 72)
+ [/codeblock]
+ See also [method ceil], [method floor], and [method round].
+ [b]Note:[/b] For better type safety, use [method snappedf], [method snappedi], [method Vector2.snapped], [method Vector2i.snapped], [method Vector3.snapped], [method Vector3i.snapped], [method Vector4.snapped], or [method Vector4i.snapped].
+ </description>
+ </method>
+ <method name="snappedf">
<return type="float" />
<param index="0" name="x" type="float" />
<param index="1" name="step" type="float" />
<description>
- Snaps the float value [param x] to a given [param step]. This can also be used to round a floating point number to an arbitrary number of decimals.
+ Returns the multiple of [param step] that is the closest to [param x]. This can also be used to round a floating point number to an arbitrary number of decimals.
+ A type-safe version of [method snapped], returning a [float].
[codeblock]
- snapped(100, 32) # Returns 96
- snapped(3.14159, 0.01) # Returns 3.14
+ snapped(32.0, 2.5) # Returns 32.5
+ snapped(3.14159, 0.01) # Returns 3.14
+ [/codeblock]
+ </description>
+ </method>
+ <method name="snappedi">
+ <return type="int" />
+ <param index="0" name="x" type="float" />
+ <param index="1" name="step" type="int" />
+ <description>
+ Returns the multiple of [param step] that is the closest to [param x].
+ A type-safe version of [method snapped], returning an [int].
+ [codeblock]
+ snapped(53, 16) # Returns 48
+ snapped(4096, 100) # Returns 4100
[/codeblock]
- See also [method ceil], [method floor], and [method round].
</description>
</method>
<method name="sqrt">
@@ -1276,6 +1319,9 @@
<member name="EngineDebugger" type="EngineDebugger" setter="" getter="">
The [EngineDebugger] singleton.
</member>
+ <member name="GDExtensionManager" type="GDExtensionManager" setter="" getter="">
+ The [GDExtensionManager] singleton.
+ </member>
<member name="Geometry2D" type="Geometry2D" setter="" getter="">
The [Geometry2D] singleton.
</member>
@@ -1305,9 +1351,6 @@
<member name="Marshalls" type="Marshalls" setter="" getter="">
The [Marshalls] singleton.
</member>
- <member name="NativeExtensionManager" type="NativeExtensionManager" setter="" getter="">
- The [NativeExtensionManager] singleton.
- </member>
<member name="NavigationMeshGenerator" type="NavigationMeshGenerator" setter="" getter="">
The [NavigationMeshGenerator] singleton.
</member>
@@ -1436,6 +1479,9 @@
<constant name="INLINE_ALIGNMENT_CENTER_TO" value="1" enum="InlineAlignment">
Aligns the center of the inline object (e.g. image, table) to the position of the text specified by [code]INLINE_ALIGNMENT_TO_*[/code] constant.
</constant>
+ <constant name="INLINE_ALIGNMENT_BASELINE_TO" value="3" enum="InlineAlignment">
+ Aligns the baseline (user defined) of the inline object (e.g. image, table) to the position of the text specified by [code]INLINE_ALIGNMENT_TO_*[/code] constant.
+ </constant>
<constant name="INLINE_ALIGNMENT_BOTTOM_TO" value="2" enum="InlineAlignment">
Aligns the bottom of the inline object (e.g. image, table) to the position of the text specified by [code]INLINE_ALIGNMENT_TO_*[/code] constant.
</constant>
@@ -2734,17 +2780,10 @@
<constant name="PROPERTY_HINT_COLOR_NO_ALPHA" value="21" enum="PropertyHint">
Hints that a [Color] property should be edited without affecting its transparency ([member Color.a] is not editable).
</constant>
- <constant name="PROPERTY_HINT_IMAGE_COMPRESS_LOSSY" value="22" enum="PropertyHint">
- Hints that an image is compressed using lossy compression. The editor does not internally use this property hint.
+ <constant name="PROPERTY_HINT_OBJECT_ID" value="22" enum="PropertyHint">
</constant>
- <constant name="PROPERTY_HINT_IMAGE_COMPRESS_LOSSLESS" value="23" enum="PropertyHint">
- Hints that an image is compressed using lossless compression. The editor does not internally use this property hint.
- </constant>
- <constant name="PROPERTY_HINT_OBJECT_ID" value="24" enum="PropertyHint">
- </constant>
- <constant name="PROPERTY_HINT_TYPE_STRING" value="25" enum="PropertyHint">
- Hints 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.
- [b]Example:[/b]
+ <constant name="PROPERTY_HINT_TYPE_STRING" value="23" 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 integers.
hint_string = "%s:%s:" % [TYPE_ARRAY, TYPE_REAL] # Two-dimensional array of floats.
@@ -2753,56 +2792,53 @@
[/codeblock]
[b]Note:[/b] The final colon is required for properly detecting built-in types.
</constant>
- <constant name="PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE" value="26" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE" value="24" enum="PropertyHint">
</constant>
- <constant name="PROPERTY_HINT_METHOD_OF_VARIANT_TYPE" value="27" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_METHOD_OF_VARIANT_TYPE" value="25" enum="PropertyHint">
</constant>
- <constant name="PROPERTY_HINT_METHOD_OF_BASE_TYPE" value="28" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_METHOD_OF_BASE_TYPE" value="26" enum="PropertyHint">
</constant>
- <constant name="PROPERTY_HINT_METHOD_OF_INSTANCE" value="29" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_METHOD_OF_INSTANCE" value="27" enum="PropertyHint">
</constant>
- <constant name="PROPERTY_HINT_METHOD_OF_SCRIPT" value="30" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_METHOD_OF_SCRIPT" value="28" enum="PropertyHint">
</constant>
- <constant name="PROPERTY_HINT_PROPERTY_OF_VARIANT_TYPE" value="31" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_PROPERTY_OF_VARIANT_TYPE" value="29" enum="PropertyHint">
</constant>
- <constant name="PROPERTY_HINT_PROPERTY_OF_BASE_TYPE" value="32" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_PROPERTY_OF_BASE_TYPE" value="30" enum="PropertyHint">
</constant>
- <constant name="PROPERTY_HINT_PROPERTY_OF_INSTANCE" value="33" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_PROPERTY_OF_INSTANCE" value="31" enum="PropertyHint">
</constant>
- <constant name="PROPERTY_HINT_PROPERTY_OF_SCRIPT" value="34" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_PROPERTY_OF_SCRIPT" value="32" enum="PropertyHint">
</constant>
- <constant name="PROPERTY_HINT_OBJECT_TOO_BIG" value="35" enum="PropertyHint">
- Hints that a property's size (in bytes) is too big to be displayed, when debugging a running project. The debugger uses this hint internally.
+ <constant name="PROPERTY_HINT_OBJECT_TOO_BIG" value="33" enum="PropertyHint">
</constant>
- <constant name="PROPERTY_HINT_NODE_PATH_VALID_TYPES" value="36" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_NODE_PATH_VALID_TYPES" value="34" enum="PropertyHint">
</constant>
- <constant name="PROPERTY_HINT_SAVE_FILE" value="37" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_SAVE_FILE" value="35" enum="PropertyHint">
</constant>
- <constant name="PROPERTY_HINT_GLOBAL_SAVE_FILE" value="38" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_GLOBAL_SAVE_FILE" value="36" enum="PropertyHint">
</constant>
- <constant name="PROPERTY_HINT_INT_IS_OBJECTID" value="39" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_INT_IS_OBJECTID" value="37" enum="PropertyHint">
</constant>
- <constant name="PROPERTY_HINT_INT_IS_POINTER" value="40" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_INT_IS_POINTER" value="38" enum="PropertyHint">
</constant>
- <constant name="PROPERTY_HINT_ARRAY_TYPE" value="41" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_ARRAY_TYPE" value="39" enum="PropertyHint">
</constant>
- <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 name="PROPERTY_HINT_LOCALE_ID" value="40" 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="43" enum="PropertyHint">
- Hints that a [Dictionary] property is string translation map. Dictionary keys are locale codes and, values are translated strings.
+ <constant name="PROPERTY_HINT_LOCALIZABLE_STRING" value="41" 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="44" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_NODE_TYPE" value="42" enum="PropertyHint">
</constant>
- <constant name="PROPERTY_HINT_HIDE_QUATERNION_EDIT" value="45" enum="PropertyHint">
- Hints that a [Quaternion] property should disable the temporary euler editor.
+ <constant name="PROPERTY_HINT_HIDE_QUATERNION_EDIT" value="43" enum="PropertyHint">
+ Hints that a quaternion property should disable the temporary euler editor.
</constant>
- <constant name="PROPERTY_HINT_PASSWORD" value="46" enum="PropertyHint">
- Hints that a [String] property is a password. Every character of the string is displayed as the secret character (typically [code]*[/code]).
- An optional placeholder text can be shown on its input field, similarly to [constant PROPERTY_HINT_PLACEHOLDER_TEXT].
+ <constant name="PROPERTY_HINT_PASSWORD" value="44" enum="PropertyHint">
+ Hints that a string property is a password, and every character is replaced with the secret character.
</constant>
- <constant name="PROPERTY_HINT_MAX" value="47" enum="PropertyHint">
- Represents the size of the [enum PropertyHint] enum.
+ <constant name="PROPERTY_HINT_MAX" value="45" enum="PropertyHint">
</constant>
<constant name="PROPERTY_USAGE_NONE" value="0" enum="PropertyUsageFlags">
The property is not stored, and does not display in the editor. This is the default for non-exported properties.
@@ -2844,40 +2880,38 @@
</constant>
<constant name="PROPERTY_USAGE_STORE_IF_NULL" value="8192" enum="PropertyUsageFlags">
</constant>
- <constant name="PROPERTY_USAGE_ANIMATE_AS_TRIGGER" value="16384" enum="PropertyUsageFlags">
- </constant>
- <constant name="PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED" value="32768" enum="PropertyUsageFlags">
+ <constant name="PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED" value="16384" enum="PropertyUsageFlags">
</constant>
- <constant name="PROPERTY_USAGE_SCRIPT_DEFAULT_VALUE" value="65536" enum="PropertyUsageFlags">
+ <constant name="PROPERTY_USAGE_SCRIPT_DEFAULT_VALUE" value="32768" enum="PropertyUsageFlags">
</constant>
- <constant name="PROPERTY_USAGE_CLASS_IS_ENUM" value="131072" enum="PropertyUsageFlags">
+ <constant name="PROPERTY_USAGE_CLASS_IS_ENUM" value="65536" enum="PropertyUsageFlags">
</constant>
- <constant name="PROPERTY_USAGE_NIL_IS_VARIANT" value="262144" enum="PropertyUsageFlags">
+ <constant name="PROPERTY_USAGE_NIL_IS_VARIANT" value="131072" enum="PropertyUsageFlags">
</constant>
- <constant name="PROPERTY_USAGE_INTERNAL" value="524288" enum="PropertyUsageFlags">
+ <constant name="PROPERTY_USAGE_INTERNAL" value="262144" enum="PropertyUsageFlags">
</constant>
- <constant name="PROPERTY_USAGE_DO_NOT_SHARE_ON_DUPLICATE" value="1048576" enum="PropertyUsageFlags">
+ <constant name="PROPERTY_USAGE_DO_NOT_SHARE_ON_DUPLICATE" value="524288" enum="PropertyUsageFlags">
If the property is a [Resource], a new copy of it is always created when calling [method Node.duplicate] or [method Resource.duplicate].
</constant>
- <constant name="PROPERTY_USAGE_HIGH_END_GFX" value="2097152" enum="PropertyUsageFlags">
+ <constant name="PROPERTY_USAGE_HIGH_END_GFX" value="1048576" enum="PropertyUsageFlags">
The property is only shown in the editor if modern renderers are supported (GLES3 is excluded).
</constant>
- <constant name="PROPERTY_USAGE_NODE_PATH_FROM_SCENE_ROOT" value="4194304" enum="PropertyUsageFlags">
+ <constant name="PROPERTY_USAGE_NODE_PATH_FROM_SCENE_ROOT" value="2097152" enum="PropertyUsageFlags">
</constant>
- <constant name="PROPERTY_USAGE_RESOURCE_NOT_PERSISTENT" value="8388608" enum="PropertyUsageFlags">
+ <constant name="PROPERTY_USAGE_RESOURCE_NOT_PERSISTENT" value="4194304" enum="PropertyUsageFlags">
</constant>
- <constant name="PROPERTY_USAGE_KEYING_INCREMENTS" value="16777216" enum="PropertyUsageFlags">
+ <constant name="PROPERTY_USAGE_KEYING_INCREMENTS" value="8388608" enum="PropertyUsageFlags">
</constant>
- <constant name="PROPERTY_USAGE_DEFERRED_SET_RESOURCE" value="33554432" enum="PropertyUsageFlags">
+ <constant name="PROPERTY_USAGE_DEFERRED_SET_RESOURCE" value="16777216" enum="PropertyUsageFlags">
</constant>
- <constant name="PROPERTY_USAGE_EDITOR_INSTANTIATE_OBJECT" value="67108864" enum="PropertyUsageFlags">
+ <constant name="PROPERTY_USAGE_EDITOR_INSTANTIATE_OBJECT" value="33554432" enum="PropertyUsageFlags">
</constant>
- <constant name="PROPERTY_USAGE_EDITOR_BASIC_SETTING" value="134217728" enum="PropertyUsageFlags">
+ <constant name="PROPERTY_USAGE_EDITOR_BASIC_SETTING" value="67108864" enum="PropertyUsageFlags">
</constant>
- <constant name="PROPERTY_USAGE_READ_ONLY" value="268435456" enum="PropertyUsageFlags">
+ <constant name="PROPERTY_USAGE_READ_ONLY" value="134217728" enum="PropertyUsageFlags">
The property is read-only in the [EditorInspector].
</constant>
- <constant name="PROPERTY_USAGE_ARRAY" value="536870912" enum="PropertyUsageFlags">
+ <constant name="PROPERTY_USAGE_ARRAY" value="268435456" enum="PropertyUsageFlags">
The property is an array.
</constant>
<constant name="PROPERTY_USAGE_DEFAULT" value="6" enum="PropertyUsageFlags">
diff --git a/doc/classes/AStarGrid2D.xml b/doc/classes/AStarGrid2D.xml
index 8dde3748d7..32599d7f7d 100644
--- a/doc/classes/AStarGrid2D.xml
+++ b/doc/classes/AStarGrid2D.xml
@@ -69,6 +69,20 @@
[b]Note:[/b] This method is not thread-safe. If called from a [Thread], it will return an empty [PackedVector3Array] and will print an error message.
</description>
</method>
+ <method name="get_point_position" qualifiers="const">
+ <return type="Vector2" />
+ <param index="0" name="id" type="Vector2i" />
+ <description>
+ Returns the position of the point associated with the given [param id].
+ </description>
+ </method>
+ <method name="get_point_weight_scale" qualifiers="const">
+ <return type="float" />
+ <param index="0" name="id" type="Vector2i" />
+ <description>
+ Returns the weight scale of the point associated with the given [param id].
+ </description>
+ </method>
<method name="is_dirty" qualifiers="const">
<return type="bool" />
<description>
@@ -103,6 +117,16 @@
<param index="1" name="solid" type="bool" default="true" />
<description>
Disables or enables the specified point for pathfinding. Useful for making an obstacle. By default, all points are enabled.
+ [b]Note:[/b] Calling [method update] is not needed after the call of this function.
+ </description>
+ </method>
+ <method name="set_point_weight_scale">
+ <return type="void" />
+ <param index="0" name="id" type="Vector2i" />
+ <param index="1" name="weight_scale" type="float" />
+ <description>
+ Sets the [param weight_scale] for the point with the given [param id]. The [param weight_scale] is multiplied by the result of [method _compute_cost] when determining the overall cost of traveling across a segment from a neighboring point to this point.
+ [b]Note:[/b] Calling [method update] is not needed after the call of this function.
</description>
</method>
<method name="update">
@@ -116,14 +140,18 @@
<member name="cell_size" type="Vector2" setter="set_cell_size" getter="get_cell_size" default="Vector2(1, 1)">
The size of the point cell which will be applied to calculate the resulting point position returned by [method get_point_path]. If changed, [method update] needs to be called before finding the next path.
</member>
- <member name="default_heuristic" type="int" setter="set_default_heuristic" getter="get_default_heuristic" enum="AStarGrid2D.Heuristic" default="0">
- The default [enum Heuristic] which will be used to calculate the path if [method _compute_cost] and/or [method _estimate_cost] were not overridden.
+ <member name="default_compute_heuristic" type="int" setter="set_default_compute_heuristic" getter="get_default_compute_heuristic" enum="AStarGrid2D.Heuristic" default="0">
+ The default [enum Heuristic] which will be used to calculate the cost between two points if [method _compute_cost] was not overridden.
+ </member>
+ <member name="default_estimate_heuristic" type="int" setter="set_default_estimate_heuristic" getter="get_default_estimate_heuristic" enum="AStarGrid2D.Heuristic" default="0">
+ The default [enum Heuristic] which will be used to calculate the cost between the point and the end point if [method _estimate_cost] was not overridden.
</member>
<member name="diagonal_mode" type="int" setter="set_diagonal_mode" getter="get_diagonal_mode" enum="AStarGrid2D.DiagonalMode" default="0">
A specific [enum DiagonalMode] mode which will force the path to avoid or accept the specified diagonals.
</member>
<member name="jumping_enabled" type="bool" setter="set_jumping_enabled" getter="is_jumping_enabled" default="false">
Enables or disables jumping to skip up the intermediate points and speeds up the searching algorithm.
+ [b]Note:[/b] Currently, toggling it on disables the consideration of weight scaling in pathfinding.
</member>
<member name="offset" type="Vector2" setter="set_offset" getter="get_offset" default="Vector2(0, 0)">
The offset of the grid which will be applied to calculate the resulting point position returned by [method get_point_path]. If changed, [method update] needs to be called before finding the next path.
@@ -134,20 +162,22 @@
</members>
<constants>
<constant name="HEURISTIC_EUCLIDEAN" value="0" enum="Heuristic">
- The Euclidean heuristic to be used for the pathfinding using the following formula:
+ The [url=https://en.wikipedia.org/wiki/Euclidean_distance]Euclidean heuristic[/url] to be used for the pathfinding using the following formula:
[codeblock]
dx = abs(to_id.x - from_id.x)
dy = abs(to_id.y - from_id.y)
result = sqrt(dx * dx + dy * dy)
[/codeblock]
+ [b]Note:[/b] This is also the internal heuristic used in [AStar3D] and [AStar2D] by default (with the inclusion of possible z-axis coordinate).
</constant>
<constant name="HEURISTIC_MANHATTAN" value="1" enum="Heuristic">
- The Manhattan heuristic to be used for the pathfinding using the following formula:
+ The [url=https://en.wikipedia.org/wiki/Taxicab_geometry]Manhattan heuristic[/url] to be used for the pathfinding using the following formula:
[codeblock]
dx = abs(to_id.x - from_id.x)
dy = abs(to_id.y - from_id.y)
result = dx + dy
[/codeblock]
+ [b]Note:[/b] This heuristic is intended to be used with 4-side orthogonal movements, provided by setting the [member diagonal_mode] to [constant DIAGONAL_MODE_NEVER].
</constant>
<constant name="HEURISTIC_OCTILE" value="2" enum="Heuristic">
The Octile heuristic to be used for the pathfinding using the following formula:
@@ -159,7 +189,7 @@
[/codeblock]
</constant>
<constant name="HEURISTIC_CHEBYSHEV" value="3" enum="Heuristic">
- The Chebyshev heuristic to be used for the pathfinding using the following formula:
+ The [url=https://en.wikipedia.org/wiki/Chebyshev_distance]Chebyshev heuristic[/url] to be used for the pathfinding using the following formula:
[codeblock]
dx = abs(to_id.x - from_id.x)
dy = abs(to_id.y - from_id.y)
diff --git a/doc/classes/Animation.xml b/doc/classes/Animation.xml
index 008296713d..c0626dcfe4 100644
--- a/doc/classes/Animation.xml
+++ b/doc/classes/Animation.xml
@@ -251,15 +251,6 @@
Returns the amount of tracks in the animation.
</description>
</method>
- <method name="method_track_get_key_indices" qualifiers="const">
- <return type="PackedInt32Array" />
- <param index="0" name="track_idx" type="int" />
- <param index="1" name="time_sec" type="float" />
- <param index="2" name="delta" type="float" />
- <description>
- Returns all the key indices of a method track, given a position and delta time.
- </description>
- </method>
<method name="method_track_get_name" qualifiers="const">
<return type="StringName" />
<param index="0" name="track_idx" type="int" />
@@ -314,9 +305,9 @@
<return type="int" />
<param index="0" name="track_idx" type="int" />
<param index="1" name="time" type="float" />
- <param index="2" name="exact" type="bool" default="false" />
+ <param index="2" name="find_mode" type="int" enum="Animation.FindMode" default="0" />
<description>
- Finds the key index by time in a given track. Optionally, only find it if the exact time is given.
+ Finds the key index by time in a given track. Optionally, only find it if the approx/exact time is given.
</description>
</method>
<method name="track_get_interpolation_loop_wrap" qualifiers="const">
@@ -523,15 +514,6 @@
Swaps the track [param track_idx]'s index position with the track [param with_idx].
</description>
</method>
- <method name="value_track_get_key_indices" qualifiers="const">
- <return type="PackedInt32Array" />
- <param index="0" name="track_idx" type="int" />
- <param index="1" name="time_sec" type="float" />
- <param index="2" name="delta" type="float" />
- <description>
- Returns all the key indices of a value track, given a position and delta time.
- </description>
- </method>
<method name="value_track_get_update_mode" qualifiers="const">
<return type="int" enum="Animation.UpdateMode" />
<param index="0" name="track_idx" type="int" />
@@ -568,13 +550,6 @@
The animation step value.
</member>
</members>
- <signals>
- <signal name="tracks_changed">
- <description>
- Emitted when there's a change in the list of tracks, e.g. tracks are added, moved or have changed paths.
- </description>
- </signal>
- </signals>
<constants>
<constant name="TYPE_VALUE" value="0" enum="TrackType">
Value tracks set values in node properties, but only those which can be interpolated. For 3D position/rotation/scale, using the dedicated [constant TYPE_POSITION_3D], [constant TYPE_ROTATION_3D] and [constant TYPE_SCALE_3D] track types instead of [constant TYPE_VALUE] is recommended for performance reasons.
@@ -621,15 +596,12 @@
[b]Note:[/b] The result value is always normalized and may not match the key value.
</constant>
<constant name="UPDATE_CONTINUOUS" value="0" enum="UpdateMode">
- Update between keyframes.
+ Update between keyframes and hold the value.
</constant>
<constant name="UPDATE_DISCRETE" value="1" enum="UpdateMode">
- Update at the keyframes and hold the value.
- </constant>
- <constant name="UPDATE_TRIGGER" value="2" enum="UpdateMode">
Update at the keyframes.
</constant>
- <constant name="UPDATE_CAPTURE" value="3" enum="UpdateMode">
+ <constant name="UPDATE_CAPTURE" value="2" enum="UpdateMode">
Same as linear interpolation, but also interpolates from the current value (i.e. dynamically at runtime) if the first key isn't at 0 seconds.
</constant>
<constant name="LOOP_NONE" value="0" enum="LoopMode">
@@ -641,5 +613,23 @@
<constant name="LOOP_PINGPONG" value="2" enum="LoopMode">
Repeats playback and reverse playback at both ends of the animation.
</constant>
+ <constant name="LOOPED_FLAG_NONE" value="0" enum="LoopedFlag">
+ This flag indicates that the animation proceeds without any looping.
+ </constant>
+ <constant name="LOOPED_FLAG_END" value="1" enum="LoopedFlag">
+ This flag indicates that the animation has reached the end of the animation and just after loop processed.
+ </constant>
+ <constant name="LOOPED_FLAG_START" value="2" enum="LoopedFlag">
+ This flag indicates that the animation has reached the start of the animation and just after loop processed.
+ </constant>
+ <constant name="FIND_MODE_NEAREST" value="0" enum="FindMode">
+ Finds the nearest time key.
+ </constant>
+ <constant name="FIND_MODE_APPROX" value="1" enum="FindMode">
+ Finds only the key with approximating the time.
+ </constant>
+ <constant name="FIND_MODE_EXACT" value="2" enum="FindMode">
+ Finds only the key with matching the time.
+ </constant>
</constants>
</class>
diff --git a/doc/classes/AnimationLibrary.xml b/doc/classes/AnimationLibrary.xml
index 769b338063..9be4cda5d6 100644
--- a/doc/classes/AnimationLibrary.xml
+++ b/doc/classes/AnimationLibrary.xml
@@ -65,6 +65,13 @@
Emitted when an [Animation] is added, under the key [param name].
</description>
</signal>
+ <signal name="animation_changed">
+ <param index="0" name="name" type="StringName" />
+ <description>
+ Emitted when there's a change in one of the animations, e.g. tracks are added, moved or have changed paths. [param name] is the key of the animation that was changed.
+ See also [signal Resource.changed], which this acts as a relay for.
+ </description>
+ </signal>
<signal name="animation_removed">
<param index="0" name="name" type="StringName" />
<description>
diff --git a/doc/classes/AnimationNode.xml b/doc/classes/AnimationNode.xml
index b856b5f208..79deb008d2 100644
--- a/doc/classes/AnimationNode.xml
+++ b/doc/classes/AnimationNode.xml
@@ -53,7 +53,7 @@
<return type="float" />
<param index="0" name="time" type="float" />
<param index="1" name="seek" type="bool" />
- <param index="2" name="seek_root" type="bool" />
+ <param index="2" name="is_external_seeking" type="bool" />
<description>
When inheriting from [AnimationRootNode], implement this virtual method to run some code when this node is processed. The [param time] parameter is a relative delta, unless [param seek] is [code]true[/code], in which case it is absolute.
Here, call the [method blend_input], [method blend_node] or [method blend_animation] functions. You can also use [method get_parameter] and [method set_parameter] to modify local memory.
@@ -73,11 +73,12 @@
<param index="1" name="time" type="float" />
<param index="2" name="delta" type="float" />
<param index="3" name="seeked" type="bool" />
- <param index="4" name="seek_root" type="bool" />
+ <param index="4" name="is_external_seeking" type="bool" />
<param index="5" name="blend" type="float" />
- <param index="6" name="pingponged" type="int" default="0" />
+ <param index="6" name="looped_flag" type="int" enum="Animation.LoopedFlag" default="0" />
<description>
Blend an animation by [param blend] amount (name must be valid in the linked [AnimationPlayer]). A [param time] and [param delta] may be passed, as well as whether [param seeked] happened.
+ A [param looped_flag] is used by internal processing immediately after the loop. See also [enum Animation.LoopedFlag].
</description>
</method>
<method name="blend_input">
@@ -85,7 +86,7 @@
<param index="0" name="input_index" type="int" />
<param index="1" name="time" type="float" />
<param index="2" name="seek" type="bool" />
- <param index="3" name="seek_root" type="bool" />
+ <param index="3" name="is_external_seeking" type="bool" />
<param index="4" name="blend" type="float" />
<param index="5" name="filter" type="int" enum="AnimationNode.FilterAction" default="0" />
<param index="6" name="sync" type="bool" default="true" />
@@ -99,7 +100,7 @@
<param index="1" name="node" type="AnimationNode" />
<param index="2" name="time" type="float" />
<param index="3" name="seek" type="bool" />
- <param index="4" name="seek_root" type="bool" />
+ <param index="4" name="is_external_seeking" type="bool" />
<param index="5" name="blend" type="float" />
<param index="6" name="filter" type="int" enum="AnimationNode.FilterAction" default="0" />
<param index="7" name="sync" type="bool" default="true" />
diff --git a/doc/classes/AnimationNodeStateMachineTransition.xml b/doc/classes/AnimationNodeStateMachineTransition.xml
index 4c2a30030b..814b2d0052 100644
--- a/doc/classes/AnimationNodeStateMachineTransition.xml
+++ b/doc/classes/AnimationNodeStateMachineTransition.xml
@@ -22,14 +22,11 @@
<member name="advance_expression" type="String" setter="set_advance_expression" getter="get_advance_expression" default="&quot;&quot;">
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="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].
- </member>
- <member name="disabled" type="bool" setter="set_disabled" getter="is_disabled" default="false">
- Don't use this transition during [method AnimationNodeStateMachinePlayback.travel] or [member auto_advance].
+ <member name="advance_mode" type="int" setter="set_advance_mode" getter="get_advance_mode" enum="AnimationNodeStateMachineTransition.AdvanceMode" default="1">
+ Determines whether the transition should disabled, enabled when using [method AnimationNodeStateMachinePlayback.travel], or traversed automatically if the [member advance_condition] and [member advance_expression] checks are true (if assigned).
</member>
<member name="priority" type="int" setter="set_priority" getter="get_priority" default="1">
- Lower priority transitions are preferred when travelling through the tree via [method AnimationNodeStateMachinePlayback.travel] or [member auto_advance].
+ Lower priority transitions are preferred when travelling through the tree via [method AnimationNodeStateMachinePlayback.travel] or [member advance_mode] is set to [constant ADVANCE_MODE_AUTO].
</member>
<member name="switch_mode" type="int" setter="set_switch_mode" getter="get_switch_mode" enum="AnimationNodeStateMachineTransition.SwitchMode" default="0">
The transition type.
@@ -58,5 +55,14 @@
<constant name="SWITCH_MODE_AT_END" value="2" enum="SwitchMode">
Wait for the current state playback to end, then switch to the beginning of the next state animation.
</constant>
+ <constant name="ADVANCE_MODE_DISABLED" value="0" enum="AdvanceMode">
+ Don't use this transition.
+ </constant>
+ <constant name="ADVANCE_MODE_ENABLED" value="1" enum="AdvanceMode">
+ Only use this transition during [method AnimationNodeStateMachinePlayback.travel].
+ </constant>
+ <constant name="ADVANCE_MODE_AUTO" value="2" enum="AdvanceMode">
+ Automatically use this transition if the [member advance_condition] and [member advance_expression] checks are true (if assigned).
+ </constant>
</constants>
</class>
diff --git a/doc/classes/AnimationTree.xml b/doc/classes/AnimationTree.xml
index 27797b00b5..a17a727d7e 100644
--- a/doc/classes/AnimationTree.xml
+++ b/doc/classes/AnimationTree.xml
@@ -19,10 +19,66 @@
Manually advance the animations by the specified time (in seconds).
</description>
</method>
- <method name="get_root_motion_transform" qualifiers="const">
- <return type="Transform3D" />
+ <method name="get_root_motion_position" qualifiers="const">
+ <return type="Vector3" />
<description>
- Retrieve the motion of the [member root_motion_track] as a [Transform3D] that can be used elsewhere. If [member root_motion_track] is not a path to a track of type [constant Animation.TYPE_POSITION_3D], [constant Animation.TYPE_SCALE_3D] or [constant Animation.TYPE_ROTATION_3D], returns an identity transformation. See also [member root_motion_track] and [RootMotionView].
+ Retrieve the motion of position with the [member root_motion_track] as a [Vector3] that can be used elsewhere.
+ If [member root_motion_track] is not a path to a track of type [constant Animation.TYPE_POSITION_3D], returns [code]Vector3(0, 0, 0)[/code].
+ See also [member root_motion_track] and [RootMotionView].
+ The most basic example is applying position to [CharacterBody3D]:
+ [codeblocks]
+ [gdscript]
+ var current_rotation: Quaternion
+
+ func _process(delta):
+ if Input.is_action_just_pressed("animate"):
+ current_rotation = get_quaternion()
+ state_machine.travel("Animate")
+ var velocity: Vector3 = current_rotation * animation_tree.get_root_motion_position() / delta
+ set_velocity(velocity)
+ move_and_slide()
+ [/gdscript]
+ [/codeblocks]
+ </description>
+ </method>
+ <method name="get_root_motion_rotation" qualifiers="const">
+ <return type="Quaternion" />
+ <description>
+ Retrieve the motion of rotation with the [member root_motion_track] as a [Quaternion] that can be used elsewhere.
+ If [member root_motion_track] is not a path to a track of type [constant Animation.TYPE_ROTATION_3D], returns [code]Quaternion(0, 0, 0, 1)[/code].
+ See also [member root_motion_track] and [RootMotionView].
+ The most basic example is applying rotation to [CharacterBody3D]:
+ [codeblocks]
+ [gdscript]
+ func _process(delta):
+ if Input.is_action_just_pressed("animate"):
+ state_machine.travel("Animate")
+ set_quaternion(get_quaternion() * animation_tree.get_root_motion_rotation())
+ [/gdscript]
+ [/codeblocks]
+ </description>
+ </method>
+ <method name="get_root_motion_scale" qualifiers="const">
+ <return type="Vector3" />
+ <description>
+ Retrieve the motion of scale with the [member root_motion_track] as a [Vector3] that can be used elsewhere.
+ If [member root_motion_track] is not a path to a track of type [constant Animation.TYPE_SCALE_3D], returns [code]Vector3(0, 0, 0)[/code].
+ See also [member root_motion_track] and [RootMotionView].
+ The most basic example is applying scale to [CharacterBody3D]:
+ [codeblocks]
+ [gdscript]
+ var current_scale: Vector3 = Vector3(1, 1, 1)
+ var scale_accum: Vector3 = Vector3(1, 1, 1)
+
+ func _process(delta):
+ if Input.is_action_just_pressed("animate"):
+ current_scale = get_scale()
+ scale_accum = Vector3(1, 1, 1)
+ state_machine.travel("Animate")
+ scale_accum += animation_tree.get_root_motion_scale()
+ set_scale(current_scale * scale_accum)
+ [/gdscript]
+ [/codeblocks]
</description>
</method>
<method name="rename_parameter">
@@ -48,18 +104,32 @@
</member>
<member name="root_motion_track" type="NodePath" setter="set_root_motion_track" getter="get_root_motion_track" default="NodePath(&quot;&quot;)">
The path to the Animation track used for root motion. Paths must be valid scene-tree paths to a node, and must be specified starting from the parent node of the node that will reproduce the animation. To specify a track that controls properties or bones, append its name after the path, separated by [code]":"[/code]. For example, [code]"character/skeleton:ankle"[/code] or [code]"character/mesh:transform/local"[/code].
- If the track has type [constant Animation.TYPE_POSITION_3D], [constant Animation.TYPE_ROTATION_3D] or [constant Animation.TYPE_SCALE_3D] the transformation will be cancelled visually, and the animation will appear to stay in place. See also [method get_root_motion_transform] and [RootMotionView].
+ If the track has type [constant Animation.TYPE_POSITION_3D], [constant Animation.TYPE_ROTATION_3D] or [constant Animation.TYPE_SCALE_3D] the transformation will be cancelled visually, and the animation will appear to stay in place. See also [method get_root_motion_position], [method get_root_motion_rotation], [method get_root_motion_scale] and [RootMotionView].
</member>
<member name="tree_root" type="AnimationNode" setter="set_tree_root" getter="get_tree_root">
The root animation node of this [AnimationTree]. See [AnimationNode].
</member>
</members>
<signals>
+ <signal name="animation_finished">
+ <param 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 or aborted. Also be aware of the possibility of unseen playback by sync and xfade.
+ </description>
+ </signal>
<signal name="animation_player_changed">
<description>
Emitted when the [member anim_player] is changed.
</description>
</signal>
+ <signal name="animation_started">
+ <param index="0" name="anim_name" type="StringName" />
+ <description>
+ Notifies when an animation starts playing.
+ [b]Note:[/b] This signal is not emitted if an animation is looping or playbacked from the middle. Also be aware of the possibility of unseen playback by sync and xfade.
+ </description>
+ </signal>
</signals>
<constants>
<constant name="ANIMATION_PROCESS_PHYSICS" value="0" enum="AnimationProcessCallback">
diff --git a/doc/classes/Area2D.xml b/doc/classes/Area2D.xml
index 29592f133d..3f76cc16ec 100644
--- a/doc/classes/Area2D.xml
+++ b/doc/classes/Area2D.xml
@@ -114,15 +114,13 @@
<signal name="area_entered">
<param index="0" name="area" type="Area2D" />
<description>
- Emitted when another Area2D enters this Area2D. Requires [member monitoring] to be set to [code]true[/code].
- [param area] the other Area2D.
+ Emitted when the received [param area] enters this area. Requires [member monitoring] to be set to [code]true[/code].
</description>
</signal>
<signal name="area_exited">
<param index="0" name="area" type="Area2D" />
<description>
- Emitted when another Area2D exits this Area2D. Requires [member monitoring] to be set to [code]true[/code].
- [param area] the other Area2D.
+ Emitted when the received [param area] exits this area. Requires [member monitoring] to be set to [code]true[/code].
</description>
</signal>
<signal name="area_shape_entered">
@@ -131,11 +129,18 @@
<param index="2" name="area_shape_index" type="int" />
<param index="3" name="local_shape_index" type="int" />
<description>
- Emitted when one of another Area2D's [Shape2D]s enters one of this Area2D's [Shape2D]s. Requires [member monitoring] to be set to [code]true[/code].
- [param area_rid] the [RID] of the other Area2D's [CollisionObject2D] used by the [PhysicsServer2D].
- [param area] the other Area2D.
- [param area_shape_index] the index of the [Shape2D] of the other Area2D used by the [PhysicsServer2D]. Get the [CollisionShape2D] node with [code]area.shape_owner_get_owner(area.shape_find_owner(area_shape_index))[/code].
- [param local_shape_index] the index of the [Shape2D] of this Area2D used by the [PhysicsServer2D]. Get the [CollisionShape2D] node with [code]self.shape_owner_get_owner(self.shape_find_owner(local_shape_index))[/code].
+ Emitted when a [Shape2D] of the received [param area] enters a shape of this area. Requires [member monitoring] to be set to [code]true[/code].
+ [param local_shape_index] and [param area_shape_index] contain indices of the interacting shapes from this area and the other area, respectively. [param area_rid] contains the [RID] of the other area. These values can be used with the [PhysicsServer2D].
+ [b]Example of getting the[/b] [CollisionShape2D] [b]node from the shape index:[/b]
+ [codeblocks]
+ [gdscript]
+ var other_shape_owner = area.shape_find_owner(area_shape_index)
+ var other_shape_node = area.shape_owner_get_owner(other_shape_owner)
+
+ var local_shape_owner = shape_find_owner(local_shape_index)
+ var local_shape_node = shape_owner_get_owner(local_shape_owner)
+ [/gdscript]
+ [/codeblocks]
</description>
</signal>
<signal name="area_shape_exited">
@@ -144,25 +149,20 @@
<param index="2" name="area_shape_index" type="int" />
<param index="3" name="local_shape_index" type="int" />
<description>
- Emitted when one of another Area2D's [Shape2D]s exits one of this Area2D's [Shape2D]s. Requires [member monitoring] to be set to [code]true[/code].
- [param area_rid] the [RID] of the other Area2D's [CollisionObject2D] used by the [PhysicsServer2D].
- [param area] the other Area2D.
- [param area_shape_index] the index of the [Shape2D] of the other Area2D used by the [PhysicsServer2D]. Get the [CollisionShape2D] node with [code]area.shape_owner_get_owner(area.shape_find_owner(area_shape_index))[/code].
- [param local_shape_index] the index of the [Shape2D] of this Area2D used by the [PhysicsServer2D]. Get the [CollisionShape2D] node with [code]self.shape_owner_get_owner(self.shape_find_owner(local_shape_index))[/code].
+ Emitted when a [Shape2D] of the received [param area] exits a shape of this area. Requires [member monitoring] to be set to [code]true[/code].
+ See also [signal area_shape_entered].
</description>
</signal>
<signal name="body_entered">
<param index="0" name="body" type="Node2D" />
<description>
- Emitted when a [PhysicsBody2D] or [TileMap] enters this Area2D. Requires [member monitoring] to be set to [code]true[/code]. [TileMap]s are detected if the [TileSet] has Collision [Shape2D]s.
- [param body] the [Node], if it exists in the tree, of the other [PhysicsBody2D] or [TileMap].
+ Emitted when the received [param body] enters this area. [param body] can be a [PhysicsBody2D] or a [TileMap]. [TileMap]s are detected if their [TileSet] has collision shapes configured. Requires [member monitoring] to be set to [code]true[/code].
</description>
</signal>
<signal name="body_exited">
<param index="0" name="body" type="Node2D" />
<description>
- Emitted when a [PhysicsBody2D] or [TileMap] exits this Area2D. Requires [member monitoring] to be set to [code]true[/code]. [TileMap]s are detected if the [TileSet] has Collision [Shape2D]s.
- [param body] the [Node], if it exists in the tree, of the other [PhysicsBody2D] or [TileMap].
+ Emitted when the received [param body] exits this area. [param body] can be a [PhysicsBody2D] or a [TileMap]. [TileMap]s are detected if their [TileSet] has collision shapes configured. Requires [member monitoring] to be set to [code]true[/code].
</description>
</signal>
<signal name="body_shape_entered">
@@ -171,11 +171,18 @@
<param index="2" name="body_shape_index" type="int" />
<param index="3" name="local_shape_index" type="int" />
<description>
- Emitted when one of a [PhysicsBody2D] or [TileMap]'s [Shape2D]s enters one of this Area2D's [Shape2D]s. Requires [member monitoring] to be set to [code]true[/code]. [TileMap]s are detected if the [TileSet] has Collision [Shape2D]s.
- [param body_rid] the [RID] of the [PhysicsBody2D] or [TileSet]'s [CollisionObject2D] used by the [PhysicsServer2D].
- [param body] the [Node], if it exists in the tree, of the [PhysicsBody2D] or [TileMap].
- [param body_shape_index] the index of the [Shape2D] of the [PhysicsBody2D] or [TileMap] used by the [PhysicsServer2D]. Get the [CollisionShape2D] node with [code]body.shape_owner_get_owner(body.shape_find_owner(body_shape_index))[/code].
- [param local_shape_index] the index of the [Shape2D] of this Area2D used by the [PhysicsServer2D]. Get the [CollisionShape2D] node with [code]self.shape_owner_get_owner(self.shape_find_owner(local_shape_index))[/code].
+ Emitted when a [Shape2D] of the received [param body] enters a shape of this area. [param body] can be a [PhysicsBody2D] or a [TileMap]. [TileMap]s are detected if their [TileSet] has collision shapes configured. Requires [member monitoring] to be set to [code]true[/code].
+ [param local_shape_index] and [param body_shape_index] contain indices of the interacting shapes from this area and the interacting body, respectively. [param body_rid] contains the [RID] of the body. These values can be used with the [PhysicsServer2D].
+ [b]Example of getting the[/b] [CollisionShape2D] [b]node from the shape index:[/b]
+ [codeblocks]
+ [gdscript]
+ var body_shape_owner = body.shape_find_owner(body_shape_index)
+ var body_shape_node = body.shape_owner_get_owner(body_shape_owner)
+
+ var local_shape_owner = shape_find_owner(local_shape_index)
+ var local_shape_node = shape_owner_get_owner(local_shape_owner)
+ [/gdscript]
+ [/codeblocks]
</description>
</signal>
<signal name="body_shape_exited">
@@ -184,11 +191,8 @@
<param index="2" name="body_shape_index" type="int" />
<param index="3" name="local_shape_index" type="int" />
<description>
- Emitted when one of a [PhysicsBody2D] or [TileMap]'s [Shape2D]s exits one of this Area2D's [Shape2D]s. Requires [member monitoring] to be set to [code]true[/code]. [TileMap]s are detected if the [TileSet] has Collision [Shape2D]s.
- [param body_rid] the [RID] of the [PhysicsBody2D] or [TileSet]'s [CollisionObject2D] used by the [PhysicsServer2D].
- [param body] the [Node], if it exists in the tree, of the [PhysicsBody2D] or [TileMap].
- [param body_shape_index] the index of the [Shape2D] of the [PhysicsBody2D] or [TileMap] used by the [PhysicsServer2D]. Get the [CollisionShape2D] node with [code]body.shape_owner_get_owner(body.shape_find_owner(body_shape_index))[/code].
- [param local_shape_index] the index of the [Shape2D] of this Area2D used by the [PhysicsServer2D]. Get the [CollisionShape2D] node with [code]self.shape_owner_get_owner(self.shape_find_owner(local_shape_index))[/code].
+ Emitted when a [Shape2D] of the received [param body] exits a shape of this area. [param body] can be a [PhysicsBody2D] or a [TileMap]. [TileMap]s are detected if their [TileSet] has collision shapes configured. Requires [member monitoring] to be set to [code]true[/code].
+ See also [signal body_shape_entered].
</description>
</signal>
</signals>
diff --git a/doc/classes/Area3D.xml b/doc/classes/Area3D.xml
index ea8cab324d..8923ac8aae 100644
--- a/doc/classes/Area3D.xml
+++ b/doc/classes/Area3D.xml
@@ -133,15 +133,13 @@
<signal name="area_entered">
<param index="0" name="area" type="Area3D" />
<description>
- Emitted when another Area3D enters this Area3D. Requires [member monitoring] to be set to [code]true[/code].
- [param area] the other Area3D.
+ Emitted when the received [param area] enters this area. Requires [member monitoring] to be set to [code]true[/code].
</description>
</signal>
<signal name="area_exited">
<param index="0" name="area" type="Area3D" />
<description>
- Emitted when another Area3D exits this Area3D. Requires [member monitoring] to be set to [code]true[/code].
- [param area] the other Area3D.
+ Emitted when the received [param area] exits this area. Requires [member monitoring] to be set to [code]true[/code].
</description>
</signal>
<signal name="area_shape_entered">
@@ -150,11 +148,18 @@
<param index="2" name="area_shape_index" type="int" />
<param index="3" name="local_shape_index" type="int" />
<description>
- Emitted when one of another Area3D's [Shape3D]s enters one of this Area3D's [Shape3D]s. Requires [member monitoring] to be set to [code]true[/code].
- [param area_rid] the [RID] of the other Area3D's [CollisionObject3D] used by the [PhysicsServer3D].
- [param area] the other Area3D.
- [param area_shape_index] the index of the [Shape3D] of the other Area3D used by the [PhysicsServer3D]. Get the [CollisionShape3D] node with [code]area.shape_owner_get_owner(area.shape_find_owner(area_shape_index))[/code].
- [param local_shape_index] the index of the [Shape3D] of this Area3D used by the [PhysicsServer3D]. Get the [CollisionShape3D] node with [code]self.shape_owner_get_owner(self.shape_find_owner(local_shape_index))[/code].
+ Emitted when a [Shape3D] of the received [param area] enters a shape of this area. Requires [member monitoring] to be set to [code]true[/code].
+ [param local_shape_index] and [param area_shape_index] contain indices of the interacting shapes from this area and the other area, respectively. [param area_rid] contains the [RID] of the other area. These values can be used with the [PhysicsServer3D].
+ [b]Example of getting the[/b] [CollisionShape3D] [b]node from the shape index:[/b]
+ [codeblocks]
+ [gdscript]
+ var other_shape_owner = area.shape_find_owner(area_shape_index)
+ var other_shape_node = area.shape_owner_get_owner(other_shape_owner)
+
+ var local_shape_owner = shape_find_owner(local_shape_index)
+ var local_shape_node = shape_owner_get_owner(local_shape_owner)
+ [/gdscript]
+ [/codeblocks]
</description>
</signal>
<signal name="area_shape_exited">
@@ -163,25 +168,20 @@
<param index="2" name="area_shape_index" type="int" />
<param index="3" name="local_shape_index" type="int" />
<description>
- Emitted when one of another Area3D's [Shape3D]s exits one of this Area3D's [Shape3D]s. Requires [member monitoring] to be set to [code]true[/code].
- [param area_rid] the [RID] of the other Area3D's [CollisionObject3D] used by the [PhysicsServer3D].
- [param area] the other Area3D.
- [param area_shape_index] the index of the [Shape3D] of the other Area3D used by the [PhysicsServer3D]. Get the [CollisionShape3D] node with [code]area.shape_owner_get_owner(area.shape_find_owner(area_shape_index))[/code].
- [param local_shape_index] the index of the [Shape3D] of this Area3D used by the [PhysicsServer3D]. Get the [CollisionShape3D] node with [code]self.shape_owner_get_owner(self.shape_find_owner(local_shape_index))[/code].
+ Emitted when a [Shape3D] of the received [param area] exits a shape of this area. Requires [member monitoring] to be set to [code]true[/code].
+ See also [signal area_shape_entered].
</description>
</signal>
<signal name="body_entered">
<param index="0" name="body" type="Node3D" />
<description>
- Emitted when a [PhysicsBody3D] or [GridMap] enters this Area3D. Requires [member monitoring] to be set to [code]true[/code]. [GridMap]s are detected if the [MeshLibrary] has Collision [Shape3D]s.
- [param body] the [Node], if it exists in the tree, of the other [PhysicsBody3D] or [GridMap].
+ Emitted when the received [param body] enters this area. [param body] can be a [PhysicsBody3D] or a [GridMap]. [GridMap]s are detected if their [MeshLibrary] has collision shapes configured. Requires [member monitoring] to be set to [code]true[/code].
</description>
</signal>
<signal name="body_exited">
<param index="0" name="body" type="Node3D" />
<description>
- Emitted when a [PhysicsBody3D] or [GridMap] exits this Area3D. Requires [member monitoring] to be set to [code]true[/code]. [GridMap]s are detected if the [MeshLibrary] has Collision [Shape3D]s.
- [param body] the [Node], if it exists in the tree, of the other [PhysicsBody3D] or [GridMap].
+ Emitted when the received [param body] exits this area. [param body] can be a [PhysicsBody3D] or a [GridMap]. [GridMap]s are detected if their [MeshLibrary] has collision shapes configured. Requires [member monitoring] to be set to [code]true[/code].
</description>
</signal>
<signal name="body_shape_entered">
@@ -190,11 +190,18 @@
<param index="2" name="body_shape_index" type="int" />
<param index="3" name="local_shape_index" type="int" />
<description>
- Emitted when one of a [PhysicsBody3D] or [GridMap]'s [Shape3D]s enters one of this Area3D's [Shape3D]s. Requires [member monitoring] to be set to [code]true[/code]. [GridMap]s are detected if the [MeshLibrary] has Collision [Shape3D]s.
- [param body_rid] the [RID] of the [PhysicsBody3D] or [MeshLibrary]'s [CollisionObject3D] used by the [PhysicsServer3D].
- [param body] the [Node], if it exists in the tree, of the [PhysicsBody3D] or [GridMap].
- [param body_shape_index] the index of the [Shape3D] of the [PhysicsBody3D] or [GridMap] used by the [PhysicsServer3D]. Get the [CollisionShape3D] node with [code]body.shape_owner_get_owner(body.shape_find_owner(body_shape_index))[/code].
- [param local_shape_index] the index of the [Shape3D] of this Area3D used by the [PhysicsServer3D]. Get the [CollisionShape3D] node with [code]self.shape_owner_get_owner(self.shape_find_owner(local_shape_index))[/code].
+ Emitted when a [Shape3D] of the received [param body] enters a shape of this area. [param body] can be a [PhysicsBody3D] or a [GridMap]. [GridMap]s are detected if their [MeshLibrary] has collision shapes configured. Requires [member monitoring] to be set to [code]true[/code].
+ [param local_shape_index] and [param body_shape_index] contain indices of the interacting shapes from this area and the interacting body, respectively. [param body_rid] contains the [RID] of the body. These values can be used with the [PhysicsServer3D].
+ [b]Example of getting the[/b] [CollisionShape3D] [b]node from the shape index:[/b]
+ [codeblocks]
+ [gdscript]
+ var body_shape_owner = body.shape_find_owner(body_shape_index)
+ var body_shape_node = body.shape_owner_get_owner(body_shape_owner)
+
+ var local_shape_owner = shape_find_owner(local_shape_index)
+ var local_shape_node = shape_owner_get_owner(local_shape_owner)
+ [/gdscript]
+ [/codeblocks]
</description>
</signal>
<signal name="body_shape_exited">
@@ -203,11 +210,8 @@
<param index="2" name="body_shape_index" type="int" />
<param index="3" name="local_shape_index" type="int" />
<description>
- Emitted when one of a [PhysicsBody3D] or [GridMap]'s [Shape3D]s enters one of this Area3D's [Shape3D]s. Requires [member monitoring] to be set to [code]true[/code]. [GridMap]s are detected if the [MeshLibrary] has Collision [Shape3D]s.
- [param body_rid] the [RID] of the [PhysicsBody3D] or [MeshLibrary]'s [CollisionObject3D] used by the [PhysicsServer3D].
- [param body] the [Node], if it exists in the tree, of the [PhysicsBody3D] or [GridMap].
- [param body_shape_index] the index of the [Shape3D] of the [PhysicsBody3D] or [GridMap] used by the [PhysicsServer3D]. Get the [CollisionShape3D] node with [code]body.shape_owner_get_owner(body.shape_find_owner(body_shape_index))[/code].
- [param local_shape_index] the index of the [Shape3D] of this Area3D used by the [PhysicsServer3D]. Get the [CollisionShape3D] node with [code]self.shape_owner_get_owner(self.shape_find_owner(local_shape_index))[/code].
+ Emitted when a [Shape3D] of the received [param body] exits a shape of this area. [param body] can be a [PhysicsBody3D] or a [GridMap]. [GridMap]s are detected if their [MeshLibrary] has collision shapes configured. Requires [member monitoring] to be set to [code]true[/code].
+ See also [signal body_shape_entered].
</description>
</signal>
</signals>
diff --git a/doc/classes/Array.xml b/doc/classes/Array.xml
index 2ec37651f7..603974d619 100644
--- a/doc/classes/Array.xml
+++ b/doc/classes/Array.xml
@@ -300,13 +300,6 @@
Searches the array for a value and returns its index or [code]-1[/code] if not found. Optionally, the initial search index can be passed.
</description>
</method>
- <method name="find_last" qualifiers="const">
- <return type="int" />
- <param index="0" name="value" type="Variant" />
- <description>
- Searches the array in reverse order for a value and returns its index or [code]-1[/code] if not found.
- </description>
- </method>
<method name="front" qualifiers="const">
<return type="Variant" />
<description>
diff --git a/doc/classes/ArrayMesh.xml b/doc/classes/ArrayMesh.xml
index ab948dd0de..70ce4ad516 100644
--- a/doc/classes/ArrayMesh.xml
+++ b/doc/classes/ArrayMesh.xml
@@ -25,10 +25,12 @@
m.mesh = arr_mesh
[/gdscript]
[csharp]
- var vertices = new Godot.Collections.Array&lt;Vector3&gt;();
- vertices.Add(new Vector3(0, 1, 0));
- vertices.Add(new Vector3(1, 0, 0));
- vertices.Add(new Vector3(0, 0, 1));
+ var vertices = new Vector3[]
+ {
+ new Vector3(0, 1, 0),
+ new Vector3(1, 0, 0),
+ new Vector3(0, 0, 1),
+ };
// Initialize the ArrayMesh.
var arrMesh = new ArrayMesh();
@@ -38,7 +40,7 @@
// Create the Mesh.
arrMesh.AddSurfaceFromArrays(Mesh.PrimitiveType.Triangles, arrays);
- var m = new MeshInstance();
+ var m = new MeshInstance3D();
m.Mesh = arrMesh;
[/csharp]
[/codeblocks]
@@ -100,13 +102,13 @@
<param index="0" name="transform" type="Transform3D" />
<param index="1" name="texel_size" type="float" />
<description>
- Will perform a UV unwrap on the [ArrayMesh] to prepare the mesh for lightmapping.
+ Performs a UV unwrap on the [ArrayMesh] to prepare the mesh for lightmapping.
</description>
</method>
<method name="regen_normal_maps">
<return type="void" />
<description>
- Will regenerate normal maps for the [ArrayMesh].
+ Regenerates tangents for each of the [ArrayMesh]'s surfaces.
</description>
</method>
<method name="set_blend_shape_name">
diff --git a/doc/classes/AudioEffectDistortion.xml b/doc/classes/AudioEffectDistortion.xml
index 6bd8522459..ef39a9c60e 100644
--- a/doc/classes/AudioEffectDistortion.xml
+++ b/doc/classes/AudioEffectDistortion.xml
@@ -2,11 +2,11 @@
<class name="AudioEffectDistortion" inherits="AudioEffect" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
Adds a distortion audio effect to an Audio bus.
- Modify the sound to make it distorted.
+ Modifies the sound to make it distorted.
</brief_description>
<description>
Different types are available: clip, tan, lo-fi (bit crushing), overdrive, or waveshape.
- By distorting the waveform the frequency content change, which will often make the sound "crunchy" or "abrasive". For games, it can simulate sound coming from some saturated device or speaker very efficiently.
+ By distorting the waveform the frequency content changes, which will often make the sound "crunchy" or "abrasive". For games, it can simulate sound coming from some saturated device or speaker very efficiently.
</description>
<tutorials>
<link title="Audio buses">$DOCS_URL/tutorials/audio/audio_buses.html</link>
@@ -22,10 +22,10 @@
Distortion type.
</member>
<member name="post_gain" type="float" setter="set_post_gain" getter="get_post_gain" default="0.0">
- Increases or decreases the volume after the effect. Value can range from -80 to 24.
+ Increases or decreases the volume after the effect, in decibels. Value can range from -80 to 24.
</member>
<member name="pre_gain" type="float" setter="set_pre_gain" getter="get_pre_gain" default="0.0">
- Increases or decreases the volume before the effect. Value can range from -60 to 60.
+ Increases or decreases the volume before the effect, in decibels. Value can range from -60 to 60.
</member>
</members>
<constants>
@@ -35,10 +35,10 @@
<constant name="MODE_ATAN" value="1" enum="Mode">
</constant>
<constant name="MODE_LOFI" value="2" enum="Mode">
- Low-resolution digital distortion effect. You can use it to emulate the sound of early digital audio devices.
+ Low-resolution digital distortion effect (bit depth reduction). You can use it to emulate the sound of early digital audio devices.
</constant>
<constant name="MODE_OVERDRIVE" value="3" enum="Mode">
- Emulates the warm distortion produced by a field effect transistor, which is commonly used in solid-state musical instrument amplifiers.
+ Emulates the warm distortion produced by a field effect transistor, which is commonly used in solid-state musical instrument amplifiers. The [member drive] property has no effect in this mode.
</constant>
<constant name="MODE_WAVESHAPE" value="4" enum="Mode">
Waveshaper distortions are used mainly by electronic musicians to achieve an extra-abrasive sound.
diff --git a/doc/classes/AudioStreamPlayer2D.xml b/doc/classes/AudioStreamPlayer2D.xml
index ae86fd0e66..81755b580f 100644
--- a/doc/classes/AudioStreamPlayer2D.xml
+++ b/doc/classes/AudioStreamPlayer2D.xml
@@ -29,7 +29,7 @@
<return type="void" />
<param index="0" name="from_position" type="float" default="0.0" />
<description>
- Plays the audio from the given position [param from_position], in seconds.
+ Queues the audio to play on the next physics frame, from the given position [param from_position], in seconds.
</description>
</method>
<method name="seek">
@@ -73,7 +73,7 @@
The pitch and the tempo of the audio, as a multiplier of the audio sample's sample rate.
</member>
<member name="playing" type="bool" setter="_set_playing" getter="is_playing" default="false">
- If [code]true[/code], audio is playing.
+ If [code]true[/code], audio is playing or is queued to be played (see [method play]).
</member>
<member name="stream" type="AudioStream" setter="set_stream" getter="get_stream">
The [AudioStream] object to be played.
diff --git a/doc/classes/AudioStreamPlayer3D.xml b/doc/classes/AudioStreamPlayer3D.xml
index 11d6e9cc7a..f711210ca1 100644
--- a/doc/classes/AudioStreamPlayer3D.xml
+++ b/doc/classes/AudioStreamPlayer3D.xml
@@ -29,7 +29,7 @@
<return type="void" />
<param index="0" name="from_position" type="float" default="0.0" />
<description>
- Plays the audio from the given position [param from_position], in seconds.
+ Queues the audio to play on the next physics frame, from the given position [param from_position], in seconds.
</description>
</method>
<method name="seek">
@@ -94,7 +94,7 @@
The pitch and the tempo of the audio, as a multiplier of the audio sample's sample rate.
</member>
<member name="playing" type="bool" setter="_set_playing" getter="is_playing" default="false">
- If [code]true[/code], audio is playing.
+ If [code]true[/code], audio is playing or is queued to be played (see [method play]).
</member>
<member name="stream" type="AudioStream" setter="set_stream" getter="get_stream">
The [AudioStream] resource to be played.
diff --git a/doc/classes/AudioStreamRandomizer.xml b/doc/classes/AudioStreamRandomizer.xml
index 5490770b7d..d93f853c89 100644
--- a/doc/classes/AudioStreamRandomizer.xml
+++ b/doc/classes/AudioStreamRandomizer.xml
@@ -12,8 +12,10 @@
<method name="add_stream">
<return type="void" />
<param index="0" name="index" type="int" />
+ <param index="1" name="stream" type="AudioStream" />
+ <param index="2" name="weight" type="float" default="1.0" />
<description>
- Insert a stream at the specified index.
+ Insert a stream at the specified index. If the index is less than zero, the insertion occurs at the end of the underlying pool.
</description>
</method>
<method name="get_stream" qualifiers="const">
@@ -78,13 +80,13 @@
</members>
<constants>
<constant name="PLAYBACK_RANDOM_NO_REPEATS" value="0" enum="PlaybackMode">
- Pick a stream at random according to the probability weights chosen for each stream, but avoid playing the same stream twice in a row whenever possible.
+ Pick a stream at random according to the probability weights chosen for each stream, but avoid playing the same stream twice in a row whenever possible. If only 1 sound is present in the pool, the same sound will always play, effectively allowing repeats to occur.
</constant>
<constant name="PLAYBACK_RANDOM" value="1" enum="PlaybackMode">
- Pick a stream at random according to the probability weights chosen for each stream.
+ Pick a stream at random according to the probability weights chosen for each stream. If only 1 sound is present in the pool, the same sound will always play.
</constant>
<constant name="PLAYBACK_SEQUENTIAL" value="2" enum="PlaybackMode">
- Play streams in the order they appear in the stream pool.
+ Play streams in the order they appear in the stream pool. If only 1 sound is present in the pool, the same sound will always play.
</constant>
</constants>
</class>
diff --git a/doc/classes/BackBufferCopy.xml b/doc/classes/BackBufferCopy.xml
index 3c811e6226..b2c5a1756f 100644
--- a/doc/classes/BackBufferCopy.xml
+++ b/doc/classes/BackBufferCopy.xml
@@ -4,8 +4,8 @@
Copies a region of the screen (or the whole screen) to a buffer so it can be accessed in your shader scripts through the [code]texture(SCREEN_TEXTURE, ...)[/code] function.
</brief_description>
<description>
- Node for back-buffering the currently-displayed screen. The region defined in the BackBufferCopy node is buffered with the content of the screen it covers, or the entire screen according to the copy mode set. Use the [code]texture(SCREEN_TEXTURE, ...)[/code] function in your shader scripts to access the buffer.
- [b]Note:[/b] Since this node inherits from [Node2D] (and not [Control]), anchors and margins won't apply to child [Control]-derived nodes. This can be problematic when resizing the window. To avoid this, add [Control]-derived nodes as [i]siblings[/i] to the BackBufferCopy node instead of adding them as children.
+ Node for back-buffering the currently-displayed screen. The region defined in the [BackBufferCopy] node is buffered with the content of the screen it covers, or the entire screen according to the copy mode set. Use the [code]texture(SCREEN_TEXTURE, ...)[/code] function in your shader scripts to access the buffer.
+ [b]Note:[/b] Since this node inherits from [Node2D] (and not [Control]), anchors and margins won't apply to child [Control]-derived nodes. This can be problematic when resizing the window. To avoid this, add [Control]-derived nodes as [i]siblings[/i] to the [BackBufferCopy] node instead of adding them as children.
</description>
<tutorials>
</tutorials>
@@ -14,18 +14,18 @@
Buffer mode. See [enum CopyMode] constants.
</member>
<member name="rect" type="Rect2" setter="set_rect" getter="get_rect" default="Rect2(-100, -100, 200, 200)">
- The area covered by the BackBufferCopy. Only used if [member copy_mode] is [constant COPY_MODE_RECT].
+ The area covered by the [BackBufferCopy]. Only used if [member copy_mode] is [constant COPY_MODE_RECT].
</member>
</members>
<constants>
<constant name="COPY_MODE_DISABLED" value="0" enum="CopyMode">
- Disables the buffering mode. This means the BackBufferCopy node will directly use the portion of screen it covers.
+ Disables the buffering mode. This means the [BackBufferCopy] node will directly use the portion of screen it covers.
</constant>
<constant name="COPY_MODE_RECT" value="1" enum="CopyMode">
- BackBufferCopy buffers a rectangular region.
+ [BackBufferCopy] buffers a rectangular region.
</constant>
<constant name="COPY_MODE_VIEWPORT" value="2" enum="CopyMode">
- BackBufferCopy buffers the entire screen.
+ [BackBufferCopy] buffers the entire screen.
</constant>
</constants>
</class>
diff --git a/doc/classes/BaseMaterial3D.xml b/doc/classes/BaseMaterial3D.xml
index de980eab0c..8a5048de6b 100644
--- a/doc/classes/BaseMaterial3D.xml
+++ b/doc/classes/BaseMaterial3D.xml
@@ -319,7 +319,7 @@
Texture that controls the strength of the refraction per-pixel. Multiplied by [member refraction_scale].
</member>
<member name="refraction_texture_channel" type="int" setter="set_refraction_texture_channel" getter="get_refraction_texture_channel" enum="BaseMaterial3D.TextureChannel" default="0">
- Specifies the channel of the [member ao_texture] in which the ambient occlusion information is stored. This is useful when you store the information for multiple effects in a single texture. For example if you stored metallic in the red channel, roughness in the blue, and ambient occlusion in the green you could reduce the number of textures you use.
+ Specifies the channel of the [member refraction_texture] in which the refraction information is stored. This is useful when you store the information for multiple effects in a single texture. For example if you stored refraction in the red channel, roughness in the blue, and ambient occlusion in the green you could reduce the number of textures you use.
</member>
<member name="rim" type="float" setter="set_rim" getter="get_rim" default="1.0">
Sets the strength of the rim lighting effect.
@@ -341,7 +341,7 @@
Texture used to control the roughness per-pixel. Multiplied by [member roughness].
</member>
<member name="roughness_texture_channel" type="int" setter="set_roughness_texture_channel" getter="get_roughness_texture_channel" enum="BaseMaterial3D.TextureChannel" default="0">
- Specifies the channel of the [member ao_texture] in which the ambient occlusion information is stored. This is useful when you store the information for multiple effects in a single texture. For example if you stored metallic in the red channel, roughness in the blue, and ambient occlusion in the green you could reduce the number of textures you use.
+ Specifies the channel of the [member roughness_texture] in which the roughness information is stored. This is useful when you store the information for multiple effects in a single texture. For example if you stored metallic in the red channel, roughness in the blue, and ambient occlusion in the green you could reduce the number of textures you use.
</member>
<member name="shading_mode" type="int" setter="set_shading_mode" getter="get_shading_mode" enum="BaseMaterial3D.ShadingMode" default="1">
Sets whether the shading takes place per-pixel or per-vertex. Per-vertex lighting is faster, making it the best choice for mobile applications, however it looks considerably worse than per-pixel.
@@ -529,13 +529,13 @@
The material will use the texture's alpha values for transparency.
</constant>
<constant name="TRANSPARENCY_ALPHA_SCISSOR" value="2" enum="Transparency">
- The material will cut off all values below a threshold, the rest will remain opaque.
+ The material will cut off all values below a threshold, the rest will remain opaque. The opaque portions will be rendering in the depth prepass.
</constant>
<constant name="TRANSPARENCY_ALPHA_HASH" value="3" enum="Transparency">
The material will cut off all values below a spatially-deterministic threshold, the rest will remain opaque.
</constant>
<constant name="TRANSPARENCY_ALPHA_DEPTH_PRE_PASS" value="4" enum="Transparency">
- The material will use the texture's alpha value for transparency, but will still be rendered in the pre-pass.
+ The material will use the texture's alpha value for transparency, but will still be rendered in the depth prepass.
</constant>
<constant name="TRANSPARENCY_MAX" value="5" enum="Transparency">
Represents the size of the [enum Transparency] enum.
@@ -613,13 +613,14 @@
Enables AlphaToCoverage and forces all non-zero alpha values to [code]1[/code]. Alpha values in the material are passed to the AntiAliasing sample mask.
</constant>
<constant name="DEPTH_DRAW_OPAQUE_ONLY" value="0" enum="DepthDrawMode">
- Default depth draw mode. Depth is drawn only for opaque objects.
+ Default depth draw mode. Depth is drawn only for opaque objects during the opaque prepass (if any) and during the opaque pass.
</constant>
<constant name="DEPTH_DRAW_ALWAYS" value="1" enum="DepthDrawMode">
- Depth draw is calculated for both opaque and transparent objects.
+ Objects will write to depth during the opaque and the transparent passes. Transparent objects that are close to the camera may obscure other transparent objects behind them.
+ [b]Note:[/b] This does not influence whether transparent objects are included in the depth prepass or not. For that, see [enum Transparency].
</constant>
<constant name="DEPTH_DRAW_DISABLED" value="2" enum="DepthDrawMode">
- No depth draw.
+ Objects will not write their depth to the depth buffer, even during the depth prepass (if enabled).
</constant>
<constant name="CULL_BACK" value="0" enum="CullMode">
Default cull mode. The back of the object is culled when not visible. Back face triangles will be culled when facing the camera. This results in only the front side of triangles being drawn. For closed-surface meshes this means that only the exterior of the mesh will be visible.
@@ -631,7 +632,7 @@
No culling is performed.
</constant>
<constant name="FLAG_DISABLE_DEPTH_TEST" value="0" enum="Flags">
- 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.
+ Disables the depth test, so this object is drawn on top of all others drawn before it. This puts the object in the transparent draw pass where it is sorted based on distance to camera. Objects drawn after it in the draw order may cover it. This also disables writing to depth.
</constant>
<constant name="FLAG_ALBEDO_FROM_VERTEX_COLOR" value="1" enum="Flags">
Set [code]ALBEDO[/code] to the per-vertex color specified in the mesh.
diff --git a/doc/classes/Button.xml b/doc/classes/Button.xml
index d2c9a77486..961f3c495a 100644
--- a/doc/classes/Button.xml
+++ b/doc/classes/Button.xml
@@ -118,6 +118,7 @@
</theme_item>
<theme_item name="outline_size" data_type="constant" type="int" default="0">
The size of the text outline.
+ [b]Note:[/b] If using a font with [member FontFile.multichannel_signed_distance_field] enabled, its [member FontFile.msdf_pixel_range] must be set to at least [i]twice[/i] the value of [theme_item outline_size] for outline rendering to look correct. Otherwise, the outline may appear to be cut off earlier than intended.
</theme_item>
<theme_item name="font" data_type="font" type="Font">
[Font] of the [Button]'s text.
diff --git a/doc/classes/ButtonGroup.xml b/doc/classes/ButtonGroup.xml
index 277bda2836..8195669b10 100644
--- a/doc/classes/ButtonGroup.xml
+++ b/doc/classes/ButtonGroup.xml
@@ -4,8 +4,8 @@
Group of Buttons.
</brief_description>
<description>
- Group of [Button]. All direct and indirect children buttons become radios. Only one allows being pressed.
- [member BaseButton.toggle_mode] should be [code]true[/code].
+ Group of [BaseButton]. The members of this group are treated like radio buttons in the sense that only one button can be pressed at the same time.
+ Every member of the ButtonGroup should have [member BaseButton.toggle_mode] set to [code]true[/code].
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/Callable.xml b/doc/classes/Callable.xml
index dd48ee6790..1fb4f91920 100644
--- a/doc/classes/Callable.xml
+++ b/doc/classes/Callable.xml
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="Callable" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
- An object representing a method in a certain object that can be called.
+ Built-in type representing a method in an object instance or a standalone function.
</brief_description>
<description>
- [Callable] is a first class object which can be held in variables and passed to functions. It represents a given method in an [Object], and is typically used for signal callbacks.
+ [Callable] is a built-in [Variant] type that represents a function. It can either be a method within an [Object] instance, or a standalone function not related to any object, like a lambda function. Like all [Variant] types, it can be stored in variables and passed to other functions. It is most commonly used for signal callbacks.
[b]Example:[/b]
[codeblocks]
[gdscript]
@@ -32,6 +32,18 @@
}
[/csharp]
[/codeblocks]
+ In GDScript, it's possible to create lambda functions within a method. Lambda functions are custom callables that are not associated with an [Object] instance. Optionally, lambda functions can also be named. The name will be displayed in the debugger, or when calling [method get_method].
+ [codeblock]
+ func _init():
+ var my_lambda = func (message):
+ print(message)
+
+ # Prints Hello everyone!
+ my_lambda.call("Hello everyone!")
+
+ # Prints "Attack!", when the button_pressed signal is emitted.
+ button_pressed.connect(func(): print("Attack!"))
+ [/codeblock]
</description>
<tutorials>
</tutorials>
@@ -39,7 +51,7 @@
<constructor name="Callable">
<return type="Callable" />
<description>
- Constructs a null [Callable] with no object nor method bound.
+ Constructs an empty [Callable], with no object nor method bound.
</description>
</constructor>
<constructor name="Callable">
@@ -54,7 +66,7 @@
<param index="0" name="object" type="Object" />
<param index="1" name="method" type="StringName" />
<description>
- Creates a new [Callable] for the method called [param method] in the specified [param object].
+ Creates a new [Callable] for the method named [param method] in the specified [param object].
</description>
</constructor>
</constructors>
@@ -62,7 +74,7 @@
<method name="bind" qualifiers="vararg const">
<return type="Callable" />
<description>
- Returns a copy of this [Callable] with the arguments bound. Bound arguments are passed after the arguments supplied by [method call].
+ Returns a copy of this [Callable] with one or more arguments bound. When called, the bound arguments are passed [i]after[/i] the arguments supplied by [method call].
</description>
</method>
<method name="call" qualifiers="vararg const">
@@ -85,13 +97,13 @@
<return type="Variant" />
<param index="0" name="arguments" type="Array" />
<description>
- Calls the method represented by this [Callable]. Contrary to [method call], this method does not take a variable number of arguments but expects all arguments to be passed via a single [Array].
+ Calls the method represented by this [Callable]. Unlike [method call], this method expects all arguments to be contained inside the [param arguments] [Array].
</description>
</method>
<method name="get_method" qualifiers="const">
<return type="StringName" />
<description>
- Returns the name of the method represented by this [Callable].
+ Returns the name of the method represented by this [Callable]. If the callable is a lambda function, returns the function's name.
</description>
</method>
<method name="get_object" qualifiers="const">
@@ -116,7 +128,7 @@
<method name="is_custom" qualifiers="const">
<return type="bool" />
<description>
- Returns [code]true[/code] if this [Callable] is a custom callable whose behavior differs based on implementation details. Custom callables are used in the engine for various reasons. If [code]true[/code], you can't use [method get_method].
+ Returns [code]true[/code] if this [Callable] is a custom callable. Custom callables are created from [method bind] or [method unbind]. In GDScript, lambda functions are also custom callables.
</description>
</method>
<method name="is_null" qualifiers="const">
@@ -128,33 +140,33 @@
<method name="is_standard" qualifiers="const">
<return type="bool" />
<description>
- Returns [code]true[/code] if this [Callable] is a standard callable, referencing an object and a method using a [StringName].
+ Returns [code]true[/code] if this [Callable] is a standard callable. This method is the opposite of [method is_custom]. Returns [code]false[/code] if this callable is a lambda function.
</description>
</method>
<method name="is_valid" qualifiers="const">
<return type="bool" />
<description>
- Returns [code]true[/code] if the object exists and has a valid function assigned, or is a custom callable.
+ Returns [code]true[/code] if the callable's object exists and has a valid method name assigned, or is a custom callable.
</description>
</method>
<method name="rpc" qualifiers="vararg const">
<return type="void" />
<description>
- Perform an RPC (Remote Procedure Call). This is used for multiplayer and is normally not available unless the function being called has been marked as [i]RPC[/i]. Calling it on unsupported functions will result in an error.
+ Perform an RPC (Remote Procedure Call). This is used for multiplayer and is normally not available, unless the function being called has been marked as [i]RPC[/i]. Calling this method on unsupported functions will result in an error.
</description>
</method>
<method name="rpc_id" qualifiers="vararg const">
<return type="void" />
<param index="0" name="peer_id" type="int" />
<description>
- Perform an RPC (Remote Procedure Call) on a specific peer ID (see multiplayer documentation for reference). This is used for multiplayer and is normally not available unless the function being called has been marked as [i]RPC[/i]. Calling it on unsupported functions will result in an error.
+ Perform an RPC (Remote Procedure Call) on a specific peer ID (see multiplayer documentation for reference). This is used for multiplayer and is normally not available unless the function being called has been marked as [i]RPC[/i]. Calling this method on unsupported functions will result in an error.
</description>
</method>
<method name="unbind" qualifiers="const">
<return type="Callable" />
<param index="0" name="argcount" type="int" />
<description>
- Returns a copy of this [Callable] with the arguments unbound. Calling the returned [Callable] will call the method without the extra arguments that are supplied in the [Callable] on which you are calling this method.
+ Returns a copy of this [Callable] with the arguments unbound, as defined by [param argcount]. Calling the returned [Callable] will call the method without the extra arguments that are supplied in the [Callable] on which you are calling this method.
</description>
</method>
</methods>
diff --git a/doc/classes/CanvasGroup.xml b/doc/classes/CanvasGroup.xml
index 3bea8cde21..37827defec 100644
--- a/doc/classes/CanvasGroup.xml
+++ b/doc/classes/CanvasGroup.xml
@@ -1,17 +1,37 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="CanvasGroup" inherits="Node2D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
+ Merges several 2D nodes into a single draw operation.
</brief_description>
<description>
+ Child [CanvasItem] nodes of a [CanvasGroup] are drawn as a single object. It allows to e.g. draw overlapping translucent 2D nodes without blending (set [member CanvasItem.self_modulate] property of [CanvasGroup] to achieve this effect).
+ [b]Note:[/b] The [CanvasGroup] uses a custom shader to read from the backbuffer to draw its children. Assigning a [Material] to the [CanvasGroup] overrides the builtin shader. To duplicate the behavior of the builtin shader in a custom [Shader] use the following:
+ [codeblock]
+ shader_type canvas_item;
+
+ void fragment() {
+ vec4 c = textureLod(SCREEN_TEXTURE, SCREEN_UV, 0.0);
+
+ if (c.a &gt; 0.0001) {
+ c.rgb /= c.a;
+ }
+
+ COLOR *= c;
+ }
+ [/codeblock]
+ [b]Note:[/b] Since [CanvasGroup] and [member CanvasItem.clip_children] both utilize the backbuffer, children of a [CanvasGroup] who have their [member CanvasItem.clip_children] set to anything other than [constant CanvasItem.CLIP_CHILDREN_DISABLED] will not function correctly.
</description>
<tutorials>
</tutorials>
<members>
<member name="clear_margin" type="float" setter="set_clear_margin" getter="get_clear_margin" default="10.0">
+ Sets the size of the margin used to expand the clearing rect of this [CanvasGroup]. This expands the area of the backbuffer that will be used by the [CanvasGroup]. A smaller margin will reduce the area of the backbuffer used which can increase performance, however if [member use_mipmaps] is enabled, a small margin may result in mipmap errors at the edge of the [CanvasGroup]. Accordingly, this should be left as small as possible, but should be increased if artifacts appear along the edges of the canvas group.
</member>
<member name="fit_margin" type="float" setter="set_fit_margin" getter="get_fit_margin" default="10.0">
+ Sets the size of a margin used to expand the drawable rect of this [CanvasGroup]. The size of the [CanvasGroup] is determined by fitting a rect around its children then expanding that rect by [member fit_margin]. This increases both the backbuffer area used and the area covered by the [CanvasGroup] both of which can reduce performance. This should be kept as small as possible and should only be expanded when an increased size is needed (e.g. for custom shader effects).
</member>
<member name="use_mipmaps" type="bool" setter="set_use_mipmaps" getter="is_using_mipmaps" default="false">
+ If [code]true[/code], calculates mipmaps for the backbuffer before drawing the [CanvasGroup] so that mipmaps can be used in a custom [ShaderMaterial] attached to the [CanvasGroup]. Generating mipmaps has a performance cost so this should not be enabled unless required.
</member>
</members>
</class>
diff --git a/doc/classes/CanvasItem.xml b/doc/classes/CanvasItem.xml
index a2859552a9..5171e0acbe 100644
--- a/doc/classes/CanvasItem.xml
+++ b/doc/classes/CanvasItem.xml
@@ -153,6 +153,7 @@
<param index="3" name="modulate" type="Color" default="Color(1, 1, 1, 1)" />
<param index="4" name="outline" type="float" default="0.0" />
<param index="5" name="pixel_range" type="float" default="4.0" />
+ <param index="6" name="scale" type="float" default="1.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 FontFile.multichannel_signed_distance_field] for more information and caveats about MSDF font rendering.
If [param outline] is positive, each alpha channel value of pixel in region is set to maximum value of true distance in the [param outline] radius.
@@ -404,7 +405,7 @@
<method name="get_canvas_transform" qualifiers="const">
<return type="Transform2D" />
<description>
- Returns the transform matrix of this item's canvas.
+ Returns the transform from the coordinate system of the canvas, this item is in, to the [Viewport]s coordinate system.
</description>
</method>
<method name="get_global_mouse_position" qualifiers="const">
@@ -422,7 +423,7 @@
<method name="get_global_transform_with_canvas" qualifiers="const">
<return type="Transform2D" />
<description>
- Returns the global transform matrix of this item in relation to the canvas.
+ Returns the transform from the local coordinate system of this [CanvasItem] to the [Viewport]s coordinate system.
</description>
</method>
<method name="get_local_mouse_position" qualifiers="const">
@@ -453,7 +454,7 @@
<method name="get_viewport_transform" qualifiers="const">
<return type="Transform2D" />
<description>
- Returns this item's transform in relation to the viewport.
+ Returns the transform from the coordinate system of the canvas, this item is in, to the [Viewport]s embedders coordinate system.
</description>
</method>
<method name="get_visibility_layer_bit" qualifiers="const">
@@ -510,7 +511,7 @@
<method name="move_to_front">
<return type="void" />
<description>
- Moves this node to display on top of its siblings. This has more use in [Control], as [Node2D] can be ordered with [member Node2D.z_index].
+ Moves this node to display on top of its siblings.
Internally, the node is moved to the bottom of parent's children list. The method has no effect on nodes without a parent.
</description>
</method>
@@ -587,6 +588,17 @@
If [code]true[/code], this [CanvasItem] is drawn. The node is only visible if all of its antecedents are visible as well (in other words, [method is_visible_in_tree] must return [code]true[/code]).
[b]Note:[/b] For controls that inherit [Popup], the correct way to make them visible is to call one of the multiple [code]popup*()[/code] functions instead.
</member>
+ <member name="y_sort_enabled" type="bool" setter="set_y_sort_enabled" getter="is_y_sort_enabled" default="false">
+ If [code]true[/code], child nodes with the lowest Y position are drawn before those with a higher Y position. If [code]false[/code], Y-sorting is disabled. Y-sorting only affects children that inherit from [CanvasItem].
+ You can nest nodes with Y-sorting. Child Y-sorted nodes are sorted in the same space as the parent Y-sort. This feature allows you to organize a scene better or divide it into multiple ones without changing your scene tree.
+ </member>
+ <member name="z_as_relative" type="bool" setter="set_z_as_relative" getter="is_z_relative" default="true">
+ If [code]true[/code], the node's Z index is relative to its parent's Z index. If this node's Z index is 2 and its parent's effective Z index is 3, then this node's effective Z index will be 2 + 3 = 5.
+ </member>
+ <member name="z_index" type="int" setter="set_z_index" getter="get_z_index" default="0">
+ Z index. Controls the order in which the nodes render. A node with a higher Z index will display in front of others. Must be between [constant RenderingServer.CANVAS_ITEM_Z_MIN] and [constant RenderingServer.CANVAS_ITEM_Z_MAX] (inclusive).
+ [b]Note:[/b] Changing the Z index of a [Control] only affects the drawing order, not the order in which input events are handled. This can be useful to implement certain UI animations, e.g. a menu where hovered items are scaled and should overlap others.
+ </member>
</members>
<signals>
<signal name="draw">
@@ -672,12 +684,16 @@
Represents the size of the [enum TextureRepeat] enum.
</constant>
<constant name="CLIP_CHILDREN_DISABLED" value="0" enum="ClipChildrenMode">
+ Child draws over parent and is not clipped.
</constant>
<constant name="CLIP_CHILDREN_ONLY" value="1" enum="ClipChildrenMode">
+ Parent is used for the purposes of clipping only. Child is clipped to the parent's visible area, parent is not drawn.
</constant>
<constant name="CLIP_CHILDREN_AND_DRAW" value="2" enum="ClipChildrenMode">
+ Parent is used for clipping child, but parent is also drawn underneath child as normal before clipping child to its visible area.
</constant>
<constant name="CLIP_CHILDREN_MAX" value="3" enum="ClipChildrenMode">
+ Represents the size of the [enum ClipChildrenMode] enum.
</constant>
</constants>
</class>
diff --git a/doc/classes/CanvasLayer.xml b/doc/classes/CanvasLayer.xml
index 7c1b19b961..ce999c06d3 100644
--- a/doc/classes/CanvasLayer.xml
+++ b/doc/classes/CanvasLayer.xml
@@ -19,6 +19,12 @@
Returns the RID of the canvas used by this layer.
</description>
</method>
+ <method name="get_final_transform" qualifiers="const">
+ <return type="Transform2D" />
+ <description>
+ Returns the transform from the [CanvasLayer]s coordinate system to the [Viewport]s coordinate system.
+ </description>
+ </method>
<method name="hide">
<return type="void" />
<description>
diff --git a/doc/classes/CharFXTransform.xml b/doc/classes/CharFXTransform.xml
index c98b194a4d..a6f707383f 100644
--- a/doc/classes/CharFXTransform.xml
+++ b/doc/classes/CharFXTransform.xml
@@ -46,6 +46,9 @@
<member name="range" type="Vector2i" setter="set_range" getter="get_range" default="Vector2i(0, 0)">
Absolute character range in the string, corresponding to the glyph. Setting this property won't affect drawing.
</member>
+ <member name="relative_index" type="int" setter="set_relative_index" getter="get_relative_index" default="0">
+ The character offset of the glyph, relative to the current [RichTextEffect] custom block. Setting this property won't affect drawing.
+ </member>
<member name="visible" type="bool" setter="set_visibility" getter="is_visible" default="true">
If [code]true[/code], the character will be drawn. If [code]false[/code], the character will be hidden. Characters around hidden characters will reflow to take the space of hidden characters. If this is not desired, set their [member color] to [code]Color(1, 1, 1, 0)[/code] instead.
</member>
diff --git a/doc/classes/CharacterBody2D.xml b/doc/classes/CharacterBody2D.xml
index 0111ef804e..7395556d05 100644
--- a/doc/classes/CharacterBody2D.xml
+++ b/doc/classes/CharacterBody2D.xml
@@ -10,7 +10,7 @@
</description>
<tutorials>
<link title="Kinematic character (2D)">$DOCS_URL/tutorials/physics/kinematic_character_2d.html</link>
- <link title="Using KinematicBody2D">$DOCS_URL/tutorials/physics/using_kinematic_body_2d.html</link>
+ <link title="Using CharacterBody2D">$DOCS_URL/tutorials/physics/using_character_body_2d.html</link>
<link title="2D Kinematic Character Demo">https://godotengine.org/asset-library/asset/113</link>
<link title="2D Platformer Demo">https://godotengine.org/asset-library/asset/120</link>
</tutorials>
diff --git a/doc/classes/CheckBox.xml b/doc/classes/CheckBox.xml
index 699e872e99..3ee18cf351 100644
--- a/doc/classes/CheckBox.xml
+++ b/doc/classes/CheckBox.xml
@@ -43,6 +43,7 @@
</theme_item>
<theme_item name="outline_size" data_type="constant" type="int" default="0">
The size of the text outline.
+ [b]Note:[/b] If using a font with [member FontFile.multichannel_signed_distance_field] enabled, its [member FontFile.msdf_pixel_range] must be set to at least [i]twice[/i] the value of [theme_item outline_size] for outline rendering to look correct. Otherwise, the outline may appear to be cut off earlier than intended.
</theme_item>
<theme_item name="font" data_type="font" type="Font">
The [Font] to use for the [CheckBox] text.
diff --git a/doc/classes/CheckButton.xml b/doc/classes/CheckButton.xml
index dfbaa7cbee..03578cafd0 100644
--- a/doc/classes/CheckButton.xml
+++ b/doc/classes/CheckButton.xml
@@ -43,6 +43,7 @@
</theme_item>
<theme_item name="outline_size" data_type="constant" type="int" default="0">
The size of the text outline.
+ [b]Note:[/b] If using a font with [member FontFile.multichannel_signed_distance_field] enabled, its [member FontFile.msdf_pixel_range] must be set to at least [i]twice[/i] the value of [theme_item outline_size] for outline rendering to look correct. Otherwise, the outline may appear to be cut off earlier than intended.
</theme_item>
<theme_item name="font" data_type="font" type="Font">
The [Font] to use for the [CheckButton] text.
diff --git a/doc/classes/CodeEdit.xml b/doc/classes/CodeEdit.xml
index e7ef5fb289..c313e6c875 100644
--- a/doc/classes/CodeEdit.xml
+++ b/doc/classes/CodeEdit.xml
@@ -651,6 +651,7 @@
</theme_item>
<theme_item name="outline_size" data_type="constant" type="int" default="0">
The size of the text outline.
+ [b]Note:[/b] If using a font with [member FontFile.multichannel_signed_distance_field] enabled, its [member FontFile.msdf_pixel_range] must be set to at least [i]twice[/i] the value of [theme_item outline_size] for outline rendering to look correct. Otherwise, the outline may appear to be cut off earlier than intended.
</theme_item>
<theme_item name="font" data_type="font" type="Font">
Sets the default [Font].
diff --git a/doc/classes/CollisionObject2D.xml b/doc/classes/CollisionObject2D.xml
index ee69015ae1..3ed2c9d3de 100644
--- a/doc/classes/CollisionObject2D.xml
+++ b/doc/classes/CollisionObject2D.xml
@@ -157,7 +157,7 @@
<param index="0" name="owner_id" type="int" />
<param index="1" name="shape_id" type="int" />
<description>
- Returns the [Shape2D] with the given id from the given shape owner.
+ Returns the [Shape2D] with the given ID from the given shape owner.
</description>
</method>
<method name="shape_owner_get_shape_count" qualifiers="const">
@@ -172,7 +172,7 @@
<param index="0" name="owner_id" type="int" />
<param index="1" name="shape_id" type="int" />
<description>
- Returns the child index of the [Shape2D] with the given id from the given shape owner.
+ Returns the child index of the [Shape2D] with the given ID from the given shape owner.
</description>
</method>
<method name="shape_owner_get_transform" qualifiers="const">
diff --git a/doc/classes/CollisionObject3D.xml b/doc/classes/CollisionObject3D.xml
index f10136521a..c302963b92 100644
--- a/doc/classes/CollisionObject3D.xml
+++ b/doc/classes/CollisionObject3D.xml
@@ -130,7 +130,7 @@
<param index="0" name="owner_id" type="int" />
<param index="1" name="shape_id" type="int" />
<description>
- Returns the [Shape3D] with the given id from the given shape owner.
+ Returns the [Shape3D] with the given ID from the given shape owner.
</description>
</method>
<method name="shape_owner_get_shape_count" qualifiers="const">
@@ -145,7 +145,7 @@
<param index="0" name="owner_id" type="int" />
<param index="1" name="shape_id" type="int" />
<description>
- Returns the child index of the [Shape3D] with the given id from the given shape owner.
+ Returns the child index of the [Shape3D] with the given ID from the given shape owner.
</description>
</method>
<method name="shape_owner_get_transform" qualifiers="const">
diff --git a/doc/classes/Color.xml b/doc/classes/Color.xml
index 90fbdcc622..d1387d088d 100644
--- a/doc/classes/Color.xml
+++ b/doc/classes/Color.xml
@@ -1,12 +1,11 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="Color" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
- Color in RGBA format using floats on the range of 0 to 1.
+ Color built-in type, in RGBA format.
</brief_description>
<description>
- A color represented by red, green, blue, and alpha (RGBA) components. The alpha component is often used for opacity. Values are in floating-point and usually range from 0 to 1. Some properties (such as CanvasItem.modulate) may accept values greater than 1 (overbright or HDR colors).
- You can also create a color from standardized color names by using the string constructor or directly using the color constants defined here. The standardized color set is based on the [url=https://en.wikipedia.org/wiki/X11_color_names]X11 color names[/url].
- If you want to supply values in a range of 0 to 255, you should use [method @GDScript.Color8].
+ A color represented in RGBA format by red ([member r]), green ([member g]), blue ([member b]), and alpha ([member a]) components. Each component is a 16-bit floating-point value, usually ranging from 0 to 1. Some properties (such as [member CanvasItem.modulate]) may support values greater than 1, for overbright or High Dynamic Range colors. If you want to supply values in a range of 0 to 255, you should use [method @GDScript.Color8].
+ Colors can also be created by name from a set of standardized colors, through the [String] constructor, [method from_string], or by directly fetching the color constants documented here. The standardized color set is based on the [url=https://en.wikipedia.org/wiki/X11_color_names]X11 color names[/url], with the addition of [constant TRANSPARENT].
[b]Note:[/b] In a boolean context, a Color will evaluate to [code]false[/code] if it's equal to [code]Color(0, 0, 0, 1)[/code] (opaque black). Otherwise, a Color will always evaluate to [code]true[/code].
[url=https://raw.githubusercontent.com/godotengine/godot-docs/master/img/color_constants.png]Color constants cheatsheet[/url]
</description>
@@ -19,7 +18,8 @@
<constructor name="Color">
<return type="Color" />
<description>
- Constructs a default-initialized [Color] with all components set to [code]0[/code].
+ Constructs a default [Color] from opaque black. This is the same as [constant BLACK].
+ [b]Note:[/b] in C#, constructs an empty color with all of its components set to [code]0.0[/code] (transparent black).
</description>
</constructor>
<constructor name="Color">
@@ -27,10 +27,10 @@
<param index="0" name="from" type="Color" />
<param index="1" name="alpha" type="float" />
<description>
- Constructs a [Color] from an existing color, but with a custom alpha value.
+ Constructs a [Color] from the existing color, with [member a] set to the given [param alpha] value.
[codeblocks]
[gdscript]
- var red = Color(Color.red, 0.2) # 20% opaque red.
+ var red = Color(Color.RED, 0.2) # 20% opaque red.
[/gdscript]
[csharp]
var red = new Color(Colors.Red, 0.2f); // 20% opaque red.
@@ -49,7 +49,7 @@
<return type="Color" />
<param index="0" name="code" type="String" />
<description>
- Constructs a [Color] either from an HTML color code or from a standardized color name. Supported color names are the same as the constants.
+ Constructs a [Color] either from an HTML color code or from a standardized color name. The supported color names are the same as the constants.
</description>
</constructor>
<constructor name="Color">
@@ -57,7 +57,7 @@
<param index="0" name="code" type="String" />
<param index="1" name="alpha" type="float" />
<description>
- Constructs a [Color] either from an HTML color code or from a standardized color name, with [param alpha] on the range of 0 to 1. Supported color names are the same as the constants.
+ Constructs a [Color] either from an HTML color code or from a standardized color name, with [param alpha] on the range of 0.0 to 1.0. The supported color names are the same as the constants.
</description>
</constructor>
<constructor name="Color">
@@ -66,7 +66,7 @@
<param index="1" name="g" type="float" />
<param index="2" name="b" type="float" />
<description>
- Constructs a [Color] from RGB values, typically between 0 and 1. Alpha will be 1.
+ Constructs a [Color] from RGB values, typically between 0.0 and 1.0. [member a] is set to 1.0.
[codeblocks]
[gdscript]
var color = Color(0.2, 1.0, 0.7) # Similar to `Color8(51, 255, 178, 255)`
@@ -84,7 +84,7 @@
<param index="2" name="b" type="float" />
<param index="3" name="a" type="float" />
<description>
- Constructs a [Color] from RGBA values, typically between 0 and 1.
+ Constructs a [Color] from RGBA values, typically between 0.0 and 1.0.
[codeblocks]
[gdscript]
var color = Color(0.2, 1.0, 0.7, 0.8) # Similar to `Color8(51, 255, 178, 204)`
@@ -101,7 +101,7 @@
<return type="Color" />
<param index="0" name="over" type="Color" />
<description>
- Returns a new color resulting from blending this color over another. If the color is opaque, the result is also opaque. The second color may have a range of alpha values.
+ Returns a new color resulting from overlaying this color over the given color. In a painting program, you can imagine it as the [param over] color painted over this colour (including alpha).
[codeblocks]
[gdscript]
var bg = Color(0.0, 1.0, 0.0, 0.5) # Green with alpha of 50%
@@ -128,7 +128,7 @@
<return type="Color" />
<param index="0" name="amount" type="float" />
<description>
- Returns a new color resulting from making this color darker by the specified percentage (ratio from 0 to 1).
+ Returns a new color resulting from making this color darker by the specified [param amount] (ratio from 0.0 to 1.0). See also [method lightened].
[codeblocks]
[gdscript]
var green = Color(0.0, 1.0, 0.0)
@@ -148,7 +148,7 @@
<param index="2" name="v" type="float" />
<param index="3" name="alpha" type="float" default="1.0" />
<description>
- Constructs a color from an [url=https://en.wikipedia.org/wiki/HSL_and_HSV]HSV profile[/url]. [param h] (hue), [param s] (saturation), and [param v] (value) are typically between 0 and 1.
+ Constructs a color from an [url=https://en.wikipedia.org/wiki/HSL_and_HSV]HSV profile[/url]. The hue ([param h]), saturation ([param s]), and value ([param v]) are typically between 0.0 and 1.0.
[codeblocks]
[gdscript]
var color = Color.from_hsv(0.58, 0.5, 0.79, 0.8)
@@ -166,7 +166,7 @@
<param index="2" name="l" type="float" />
<param index="3" name="alpha" type="float" default="1.0" />
<description>
- Constructs a color from an [url=https://bottosson.github.io/posts/colorpicker/]OK HSL profile[/url]. [param h] (hue), [param s] (saturation), and [param l] (lightness) are typically between 0 and 1.
+ Constructs a color from an [url=https://bottosson.github.io/posts/colorpicker/]OK HSL profile[/url]. The hue ([param h]), saturation ([param s]), and lightness ([param l]) are typically between 0.0 and 1.0.
[codeblocks]
[gdscript]
var color = Color.from_ok_hsl(0.58, 0.5, 0.79, 0.8)
@@ -189,14 +189,13 @@
<param index="0" name="str" type="String" />
<param index="1" name="default" type="Color" />
<description>
- Creates a [Color] from string, which can be either a HTML color code or a named color. Fallbacks to [param default] if the string does not denote any valid color.
+ Creates a [Color] from the given string, which can be either an HTML color code or a named color (case-insensitive). Returns [param default] if the color cannot be inferred from the string.
</description>
</method>
<method name="get_luminance" qualifiers="const">
<return type="float" />
<description>
- Returns the luminance of the color in the [code][0.0, 1.0][/code] range.
- This is useful when determining light or dark color. Colors with a luminance smaller than 0.5 can be generally considered dark.
+ Returns the light intensity of the color, as a value between 0.0 and 1.0 (inclusive). This is useful when determining light or dark color. Colors with a luminance smaller than 0.5 can be generally considered dark.
[b]Note:[/b] [method get_luminance] relies on the color being in the linear color space to return an accurate relative luminance value. If the color is in the sRGB color space, use [method srgb_to_linear] to convert it to the linear color space first.
</description>
</method>
@@ -204,35 +203,47 @@
<return type="Color" />
<param index="0" name="hex" type="int" />
<description>
- Returns the [Color] associated with the provided integer number, with 8 bits per channel in ARGB order. The integer should be 32-bit. Best used with hexadecimal notation.
- [codeblock]
- modulate = Color.hex(0xffff0000) # red
- [/codeblock]
+ Returns the [Color] associated with the provided [param hex] integer in 32-bit ARGB format (8 bits per channel, alpha channel first).
+ In GDScript and C#, the [int] is best visualized with hexadecimal notation ([code]"0x"[/code] prefix).
+ [codeblocks]
+ [gdscript]
+ var red = Color.hex(0xffff0000)
+ var dark_cyan = Color.hex(0xff008b8b)
+ var my_color = Color.hex(0xa4bbefd2)
+ [/gdscript]
+ [csharp]
+ var red = new Color(0xffff0000);
+ var dark_cyan = new Color(0xff008b8b);
+ var my_color = new Color(0xa4bbefd2);
+ [/csharp]
+ [/codeblocks]
</description>
</method>
<method name="hex64" qualifiers="static">
<return type="Color" />
<param index="0" name="hex" type="int" />
<description>
- Same as [method hex], but takes 64-bit integer and the color uses 16 bits per channel.
+ Returns the [Color] associated with the provided [param hex] integer in 64-bit ARGB format (16 bits per channel, alpha channel first).
+ In GDScript and C#, the [int] is best visualized with hexadecimal notation ([code]"0x"[/code] prefix).
</description>
</method>
<method name="html" qualifiers="static">
<return type="Color" />
<param index="0" name="rgba" type="String" />
<description>
- Returns a new color from [param rgba], an HTML hexadecimal color string. [param rgba] is not case sensitive, and may be prefixed with a '#' character.
- [param rgba] must be a valid three-digit or six-digit hexadecimal color string, and may contain an alpha channel value. If [param rgba] does not contain an alpha channel value, an alpha channel value of 1.0 is applied.
- If [param rgba] is invalid a Color(0.0, 0.0, 0.0, 1.0) is returned.
- [b]Note:[/b] This method is not implemented in C#, but the same functionality is provided in the class constructor.
+ Returns a new color from [param rgba], an HTML hexadecimal color string. [param rgba] is not case-sensitive, and may be prefixed by a hash sign ([code]#[/code]).
+ [param rgba] must be a valid three-digit or six-digit hexadecimal color string, and may contain an alpha channel value. If [param rgba] does not contain an alpha channel value, an alpha channel value of 1.0 is applied. If [param rgba] is invalid, returns an empty color.
+ [b]Note:[/b] In C#, this method is not implemented. The same functionality is provided by the Color constructor.
[codeblocks]
[gdscript]
- var green = Color.html("#00FF00FF") # set green to Color(0.0, 1.0, 0.0, 1.0)
- var blue = Color.html("#0000FF") # set blue to Color(0.0, 0.0, 1.0, 1.0)
+ var blue = Color.html("#0000ff") # blue is Color(0.0, 0.0, 1.0, 1.0)
+ var green = Color.html("#0F0") # green is Color(0.0, 1.0, 0.0, 1.0)
+ var col = Color.html("663399cc") # col is Color(0.4, 0.2, 0.6, 0.8)
[/gdscript]
[csharp]
- var green = new Color("#00FF00FF"); // set green to Color(0.0, 1.0, 0.0, 1.0)
- var blue = new Color("#0000FF"); // set blue to Color(0.0, 0.0, 1.0, 1.0)
+ var blue = Color.FromHtml("#0000ff"); // blue is Color(0.0, 0.0, 1.0, 1.0)
+ var green = Color.FromHtml("#0F0"); // green is Color(0.0, 1.0, 0.0, 1.0)
+ var col = Color.FromHtml("663399cc"); // col is Color(0.4, 0.2, 0.6, 0.8)
[/csharp]
[/codeblocks]
</description>
@@ -241,24 +252,25 @@
<return type="bool" />
<param index="0" name="color" type="String" />
<description>
- Returns [code]true[/code] if [param color] is a valid HTML hexadecimal color string. [param color] is not case sensitive, and may be prefixed with a '#' character.
- For a string to be valid it must be three-digit or six-digit hexadecimal, and may contain an alpha channel value.
+ Returns [code]true[/code] if [param color] is a valid HTML hexadecimal color string. The string must be a hexadecimal value (case-insensitive) of either 3, 4, 6 or 8 digits, and may be prefixed by a hash sign ([code]#[/code]). This method is identical to [method String.is_valid_html_color].
[codeblocks]
[gdscript]
- var result = Color.html_is_valid("#55aaFF") # result is true
- result = Color.html_is_valid("#55AAFF20") # result is true
- result = Color.html_is_valid("55AAFF") # result is true
- result = Color.html_is_valid("#F2C") # result is true
- result = Color.html_is_valid("#AABBC) # result is false
- result = Color.html_is_valid("#55aaFF5") # result is false
+ Color.html_is_valid("#55aaFF") # Returns true
+ Color.html_is_valid("#55AAFF20") # Returns true
+ Color.html_is_valid("55AAFF") # Returns true
+ Color.html_is_valid("#F2C") # Returns true
+
+ Color.html_is_valid("#AABBC) # Returns false
+ Color.html_is_valid("#55aaFF5") # Returns false
[/gdscript]
[csharp]
- var result = Color.HtmlIsValid("#55AAFF"); // result is true
- result = Color.HtmlIsValid("#55AAFF20"); // result is true
- result = Color.HtmlIsValid("55AAFF); // result is true
- result = Color.HtmlIsValid("#F2C"); // result is true
- result = Color.HtmlIsValid("#AABBC"); // result is false
- result = Color.HtmlIsValid("#55aaFF5"); // result is false
+ Color.IsHtmlValid("#55AAFF"); // Returns true
+ Color.IsHtmlValid("#55AAFF20"); // Returns true
+ Color.IsHtmlValid("55AAFF"); // Returns true
+ Color.IsHtmlValid("#F2C"); // Returns true
+
+ Color.IsHtmlValid("#AABBC"); // Returns false
+ Color.IsHtmlValid("#55aaFF5"); // Returns false
[/csharp]
[/codeblocks]
</description>
@@ -266,13 +278,15 @@
<method name="inverted" qualifiers="const">
<return type="Color" />
<description>
- Returns the inverted color [code](1 - r, 1 - g, 1 - b, a)[/code].
+ Returns the color with its [member r], [member g], and [member b] components inverted ([code](1 - r, 1 - g, 1 - b, a)[/code]).
[codeblocks]
[gdscript]
+ var black = Color.WHITE.inverted()
var color = Color(0.3, 0.4, 0.9)
var inverted_color = color.inverted() # Equivalent to `Color(0.7, 0.6, 0.1)`
[/gdscript]
[csharp]
+ var black = Colors.White.Inverted();
var color = new Color(0.3f, 0.4f, 0.9f);
Color invertedColor = color.Inverted(); // Equivalent to `new Color(0.7f, 0.6f, 0.1f)`
[/csharp]
@@ -291,17 +305,23 @@
<param index="0" name="to" type="Color" />
<param index="1" name="weight" type="float" />
<description>
- Returns the linear interpolation with another color. The interpolation factor [param weight] is between 0 and 1.
+ Returns the linear interpolation between this color's components and [param to]'s components. The interpolation factor [param weight] should be between 0.0 and 1.0 (inclusive). See also [method @GlobalScope.lerp].
[codeblocks]
[gdscript]
- var c1 = Color(1.0, 0.0, 0.0)
- var c2 = Color(0.0, 1.0, 0.0)
- var lerp_color = c1.lerp(c2, 0.5) # Equivalent to `Color(0.5, 0.5, 0.0)`
+ var red = Color(1.0, 0.0, 0.0)
+ var aqua = Color(0.0, 1.0, 0.8)
+
+ red.lerp(aqua, 0.2) # Returns Color(0.8, 0.2, 0.16)
+ red.lerp(aqua, 0.5) # Returns Color(0.5, 0.5, 0.4)
+ red.lerp(aqua, 1.0) # Returns Color(0.0, 1.0, 0.8)
[/gdscript]
[csharp]
- var c1 = new Color(1.0f, 0.0f, 0.0f);
- var c2 = new Color(0.0f, 1.0f, 0.0f);
- Color lerpColor = c1.Lerp(c2, 0.5f); // Equivalent to `new Color(0.5f, 0.5f, 0.0f)`
+ var red = new Color(1.0f, 0.0f, 0.0f);
+ var aqua = new Color(0.0f, 1.0f, 0.8f);
+
+ red.Lerp(aqua, 0.2f); // Returns Color(0.8f, 0.2f, 0.16f)
+ red.Lerp(aqua, 0.5f); // Returns Color(0.5f, 0.5f, 0.4f)
+ red.Lerp(aqua, 1.0f); // Returns Color(0.0f, 1.0f, 0.8f)
[/csharp]
[/codeblocks]
</description>
@@ -310,15 +330,15 @@
<return type="Color" />
<param index="0" name="amount" type="float" />
<description>
- Returns a new color resulting from making this color lighter by the specified percentage (ratio from 0 to 1).
+ Returns a new color resulting from making this color lighter by the specified [param amount], which should be a ratio from 0.0 to 1.0. See also [method darkened].
[codeblocks]
[gdscript]
var green = Color(0.0, 1.0, 0.0)
- var lightgreen = green.lightened(0.2) # 20% lighter than regular green
+ var light_green = green.lightened(0.2) # 20% lighter than regular green
[/gdscript]
[csharp]
var green = new Color(0.0f, 1.0f, 0.0f);
- Color lightgreen = green.Lightened(0.2f); // 20% lighter than regular green
+ Color lightGreen = green.Lightened(0.2f); // 20% lighter than regular green
[/csharp]
[/codeblocks]
</description>
@@ -326,19 +346,19 @@
<method name="linear_to_srgb" qualifiers="const">
<return type="Color" />
<description>
- Returns the color converted to the [url=https://en.wikipedia.org/wiki/SRGB]sRGB[/url] color space. This assumes the original color is in the linear color space. See also [method srgb_to_linear] which performs the opposite operation.
+ Returns the color converted to the [url=https://en.wikipedia.org/wiki/SRGB]sRGB[/url] color space. This method assumes the original color is in the linear color space. See also [method srgb_to_linear] which performs the opposite operation.
</description>
</method>
<method name="srgb_to_linear" qualifiers="const">
<return type="Color" />
<description>
- Returns the color converted to the linear color space. This assumes the original color is in the sRGB color space. See also [method linear_to_srgb] which performs the opposite operation.
+ Returns the color converted to the linear color space. This method assumes the original color already is in the sRGB color space. See also [method linear_to_srgb] which performs the opposite operation.
</description>
</method>
<method name="to_abgr32" qualifiers="const">
<return type="int" />
<description>
- Returns the color converted to a 32-bit integer in ABGR format (each byte represents a color channel). ABGR is the reversed version of the default format.
+ Returns the color converted to a 32-bit integer in ABGR format (each component is 8 bits). ABGR is the reversed version of the default RGBA format.
[codeblocks]
[gdscript]
var color = Color(1, 0.5, 0.2)
@@ -354,7 +374,7 @@
<method name="to_abgr64" qualifiers="const">
<return type="int" />
<description>
- Returns the color converted to a 64-bit integer in ABGR format (each word represents a color channel). ABGR is the reversed version of the default format.
+ Returns the color converted to a 64-bit integer in ABGR format (each component is 16 bits). ABGR is the reversed version of the default RGBA format.
[codeblocks]
[gdscript]
var color = Color(1, 0.5, 0.2)
@@ -370,7 +390,7 @@
<method name="to_argb32" qualifiers="const">
<return type="int" />
<description>
- Returns the color converted to a 32-bit integer in ARGB format (each byte represents a color channel). ARGB is more compatible with DirectX.
+ Returns the color converted to a 32-bit integer in ARGB format (each component is 8 bits). ARGB is more compatible with DirectX.
[codeblocks]
[gdscript]
var color = Color(1, 0.5, 0.2)
@@ -386,7 +406,7 @@
<method name="to_argb64" qualifiers="const">
<return type="int" />
<description>
- Returns the color converted to a 64-bit integer in ARGB format (each word represents a color channel). ARGB is more compatible with DirectX.
+ Returns the color converted to a 64-bit integer in ARGB format (each component is 16 bits). ARGB is more compatible with DirectX.
[codeblocks]
[gdscript]
var color = Color(1, 0.5, 0.2)
@@ -403,18 +423,18 @@
<return type="String" />
<param index="0" name="with_alpha" type="bool" default="true" />
<description>
- Returns the color converted to an HTML hexadecimal color string in RGBA format (ex: [code]ff34f822[/code]).
- Setting [param with_alpha] to [code]false[/code] excludes alpha from the hexadecimal string (and uses RGB instead of RGBA format).
+ Returns the color converted to an HTML hexadecimal color [String] in RGBA format, without the hash ([code]#[/code]) prefix.
+ Setting [param with_alpha] to [code]false[/code], excludes alpha from the hexadecimal string, using RGB format instead of RGBA format.
[codeblocks]
[gdscript]
- var color = Color(1, 1, 1, 0.5)
- var with_alpha = color.to_html() # Returns "ffffff7f"
- var without_alpha = color.to_html(false) # Returns "ffffff"
+ var white = Color(1, 1, 1, 0.5)
+ var with_alpha = white.to_html() # Returns "ffffff7f"
+ var without_alpha = white.to_html(false) # Returns "ffffff"
[/gdscript]
[csharp]
- var color = new Color(1, 1, 1, 0.5f);
- String withAlpha = color.ToHtml(); // Returns "ffffff7f"
- String withoutAlpha = color.ToHtml(false); // Returns "ffffff"
+ var white = new Color(1, 1, 1, 0.5f);
+ string withAlpha = white.ToHtml(); // Returns "ffffff7f"
+ string withoutAlpha = white.ToHtml(false); // Returns "ffffff"
[/csharp]
[/codeblocks]
</description>
@@ -422,7 +442,7 @@
<method name="to_rgba32" qualifiers="const">
<return type="int" />
<description>
- Returns the color converted to a 32-bit integer in RGBA format (each byte represents a color channel). RGBA is Godot's default format.
+ Returns the color converted to a 32-bit integer in RGBA format (each component is 8 bits). RGBA is Godot's default format.
[codeblocks]
[gdscript]
var color = Color(1, 0.5, 0.2)
@@ -438,7 +458,7 @@
<method name="to_rgba64" qualifiers="const">
<return type="int" />
<description>
- Returns the color converted to a 64-bit integer in RGBA format (each word represents a color channel). RGBA is Godot's default format.
+ Returns the color converted to a 64-bit integer in RGBA format (each component is 16 bits). RGBA is Godot's default format.
[codeblocks]
[gdscript]
var color = Color(1, 0.5, 0.2)
@@ -457,19 +477,19 @@
The color's alpha component, typically on the range of 0 to 1. A value of 0 means that the color is fully transparent. A value of 1 means that the color is fully opaque.
</member>
<member name="a8" type="int" setter="" getter="" default="255">
- Wrapper for [member a] that uses the range 0 to 255 instead of 0 to 1.
+ Wrapper for [member a] that uses the range 0 to 255, instead of 0 to 1.
</member>
<member name="b" type="float" setter="" getter="" default="0.0">
The color's blue component, typically on the range of 0 to 1.
</member>
<member name="b8" type="int" setter="" getter="" default="0">
- Wrapper for [member b] that uses the range 0 to 255 instead of 0 to 1.
+ Wrapper for [member b] that uses the range 0 to 255, instead of 0 to 1.
</member>
<member name="g" type="float" setter="" getter="" default="0.0">
The color's green component, typically on the range of 0 to 1.
</member>
<member name="g8" type="int" setter="" getter="" default="0">
- Wrapper for [member g] that uses the range 0 to 255 instead of 0 to 1.
+ Wrapper for [member g] that uses the range 0 to 255, instead of 0 to 1.
</member>
<member name="h" type="float" setter="" getter="" default="0.0">
The HSV hue of this color, on the range 0 to 1.
@@ -478,7 +498,7 @@
The color's red component, typically on the range of 0 to 1.
</member>
<member name="r8" type="int" setter="" getter="" default="0">
- Wrapper for [member r] that uses the range 0 to 255 instead of 0 to 1.
+ Wrapper for [member r] that uses the range 0 to 255, instead of 0 to 1.
</member>
<member name="s" type="float" setter="" getter="" default="0.0">
The HSV saturation of this color, on the range 0 to 1.
@@ -510,7 +530,7 @@
Bisque color.
</constant>
<constant name="BLACK" value="Color(0, 0, 0, 1)">
- Black color.
+ Black color. In GDScript, this is the default value of any color.
</constant>
<constant name="BLANCHED_ALMOND" value="Color(1, 0.921569, 0.803922, 1)">
Blanched almond color.
@@ -932,7 +952,7 @@
<return type="bool" />
<param index="0" name="right" type="Color" />
<description>
- Returns [code]true[/code] if the colors are not equal.
+ Returns [code]true[/code] if the colors are not exactly equal.
[b]Note:[/b] Due to floating-point precision errors, consider using [method is_equal_approx] instead, which is more reliable.
</description>
</operator>
@@ -1004,7 +1024,7 @@
<return type="float" />
<param index="0" name="index" type="int" />
<description>
- Access color components using their index. [code]c[0][/code] is equivalent to [code]c.r[/code], [code]c[1][/code] is equivalent to [code]c.g[/code], [code]c[2][/code] is equivalent to [code]c.b[/code], and [code]c[3][/code] is equivalent to [code]c.a[/code].
+ Access color components using their index. [code][0][/code] is equivalent to [member r], [code][1][/code] is equivalent to [member g], [code][2][/code] is equivalent to [member b], and [code][3][/code] is equivalent to [member a].
</description>
</operator>
<operator name="operator unary+">
@@ -1016,7 +1036,7 @@
<operator name="operator unary-">
<return type="Color" />
<description>
- Inverts the given color. This is equivalent to [code]Color.WHITE - c[/code] or [code]Color(1 - c.r, 1 - c.g, 1 - c.b, 1 - c.a)[/code].
+ Inverts the given color. This is equivalent to [code]Color.WHITE - c[/code] or [code]Color(1 - c.r, 1 - c.g, 1 - c.b, 1 - c.a)[/code]. Unlike with [method inverted], the [member a] component is inverted, too.
</description>
</operator>
</operators>
diff --git a/doc/classes/ColorPicker.xml b/doc/classes/ColorPicker.xml
index 2b287d7546..823433c2df 100644
--- a/doc/classes/ColorPicker.xml
+++ b/doc/classes/ColorPicker.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="ColorPicker" inherits="BoxContainer" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+<class name="ColorPicker" inherits="VBoxContainer" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
Color picker control.
</brief_description>
@@ -88,7 +88,6 @@
<member name="sliders_visible" type="bool" setter="set_sliders_visible" getter="are_sliders_visible" default="true">
If [code]true[/code], the color sliders are visible.
</member>
- <member name="vertical" type="bool" setter="set_vertical" getter="is_vertical" overrides="BoxContainer" default="true" />
</members>
<signals>
<signal name="color_changed">
diff --git a/doc/classes/ColorPickerButton.xml b/doc/classes/ColorPickerButton.xml
index b7a0bdfb0c..2a37cc162a 100644
--- a/doc/classes/ColorPickerButton.xml
+++ b/doc/classes/ColorPickerButton.xml
@@ -79,6 +79,7 @@
</theme_item>
<theme_item name="outline_size" data_type="constant" type="int" default="0">
The size of the text outline.
+ [b]Note:[/b] If using a font with [member FontFile.multichannel_signed_distance_field] enabled, its [member FontFile.msdf_pixel_range] must be set to at least [i]twice[/i] the value of [theme_item outline_size] for outline rendering to look correct. Otherwise, the outline may appear to be cut off earlier than intended.
</theme_item>
<theme_item name="font" data_type="font" type="Font">
[Font] of the [ColorPickerButton]'s text.
diff --git a/doc/classes/Control.xml b/doc/classes/Control.xml
index e1dd2819b2..b0351559ee 100644
--- a/doc/classes/Control.xml
+++ b/doc/classes/Control.xml
@@ -1010,6 +1010,10 @@
<member name="layout_direction" type="int" setter="set_layout_direction" getter="get_layout_direction" enum="Control.LayoutDirection" default="0">
Controls layout direction and text writing direction. Right-to-left layouts are necessary for certain languages (e.g. Arabic and Hebrew).
</member>
+ <member name="localize_numeral_system" type="bool" setter="set_localize_numeral_system" getter="is_localizing_numeral_system" default="true">
+ If [code]true[/code], automatically converts code line numbers, list indices, [SpinBox] and [ProgressBar] values from the Western Arabic (0..9) to the numeral systems used in current locale.
+ [b]Note:[/b] Numbers within the text are not automatically converted, it can be done manually, using [method TextServer.format_number].
+ </member>
<member name="mouse_default_cursor_shape" type="int" setter="set_default_cursor_shape" getter="get_default_cursor_shape" enum="Control.CursorShape" default="0">
The default cursor shape for this control. Useful for Godot plugins and applications or games that use the system's mouse cursors.
[b]Note:[/b] On Linux, shapes may vary depending on the cursor theme of the system.
@@ -1046,9 +1050,12 @@
<member name="rotation" type="float" setter="set_rotation" getter="get_rotation" default="0.0">
The node's rotation around its pivot, in radians. See [member pivot_offset] to change the pivot's position.
</member>
+ <member name="rotation_degrees" type="float" setter="set_rotation_degrees" getter="get_rotation_degrees">
+ Helper property to access [member rotation] in degrees instead of radians.
+ </member>
<member name="scale" type="Vector2" setter="set_scale" getter="get_scale" default="Vector2(1, 1)">
The node's scale, relative to its [member size]. Change this property to scale the node around its [member pivot_offset]. The Control's [member tooltip_text] will also scale according to this value.
- [b]Note:[/b] This property is mainly intended to be used for animation purposes. Text inside the Control will look pixelated or blurry when the Control is scaled. To support multiple resolutions in your project, use an appropriate viewport stretch mode as described in the [url=$DOCS_URL/tutorials/viewports/multiple_resolutions.html]documentation[/url] instead of scaling Controls individually.
+ [b]Note:[/b] This property is mainly intended to be used for animation purposes. Text inside the Control will look pixelated or blurry when the Control is scaled. To support multiple resolutions in your project, use an appropriate viewport stretch mode as described in the [url=$DOCS_URL/tutorials/rendering/multiple_resolutions.html]documentation[/url] instead of scaling Controls individually.
[b]Note:[/b] If the Control node is a child of a [Container] node, the scale will be reset to [code]Vector2(1, 1)[/code] when the scene is instantiated. To set the Control's scale when it's instantiated, wait for one frame using [code]await get_tree().process_frame[/code] then set its [member scale] property.
</member>
<member name="shortcut_context" type="Node" setter="set_shortcut_context" getter="get_shortcut_context">
@@ -1067,7 +1074,8 @@
Tells the parent [Container] nodes how they should resize and place the node on the Y axis. Use one of the [enum SizeFlags] constants to change the flags. See the constants to learn what each does.
</member>
<member name="theme" type="Theme" setter="set_theme" getter="get_theme">
- The [Theme] resource this node and all its [Control] children use. If a child node has its own [Theme] resource set, theme items are merged with child's definitions having higher priority.
+ The [Theme] resource this node and all its [Control] and [Window] children use. If a child node has its own [Theme] resource set, theme items are merged with child's definitions having higher priority.
+ [b]Note:[/b] [Window] styles will have no effect unless the window is embedded.
</member>
<member name="theme_type_variation" type="StringName" setter="set_theme_type_variation" getter="get_theme_type_variation" default="&amp;&quot;&quot;">
The name of a theme type variation used by this [Control] to look up its own theme items. When empty, the class name of the node is used (e.g. [code]Button[/code] for the [Button] control), as well as the class names of all parent classes (in order of inheritance).
diff --git a/doc/classes/Curve2D.xml b/doc/classes/Curve2D.xml
index ccdf085319..b5e75dff68 100644
--- a/doc/classes/Curve2D.xml
+++ b/doc/classes/Curve2D.xml
@@ -51,7 +51,7 @@
<return type="Vector2" />
<param index="0" name="to_point" type="Vector2" />
<description>
- Returns the closest baked point (in curve's local space) to [param to_point].
+ Returns the closest point on baked segments (in curve's local space) to [param to_point].
[param to_point] must be in this curve's local space.
</description>
</method>
@@ -94,7 +94,7 @@
</method>
<method name="sample_baked" qualifiers="const">
<return type="Vector2" />
- <param index="0" name="offset" type="float" />
+ <param index="0" name="offset" type="float" default="0.0" />
<param index="1" name="cubic" type="bool" default="false" />
<description>
Returns a point within the curve at position [param offset], where [param offset] is measured as a pixel distance along the curve.
@@ -104,13 +104,10 @@
</method>
<method name="sample_baked_with_rotation" qualifiers="const">
<return type="Transform2D" />
- <param index="0" name="offset" type="float" />
+ <param index="0" name="offset" type="float" default="0.0" />
<param index="1" name="cubic" type="bool" default="false" />
- <param index="2" name="loop" type="bool" default="true" />
- <param index="3" name="lookahead" type="float" default="4.0" />
<description>
Similar to [method sample_baked], but returns [Transform2D] that includes a rotation along the curve. Returns empty transform if length of the curve is [code]0[/code].
- Use [param loop] to smooth the tangent at the end of the curve. [param lookahead] defines the distance to a nearby point for calculating the tangent vector.
[codeblock]
var transform = curve.sample_baked_with_rotation(offset)
position = transform.get_origin()
@@ -160,6 +157,13 @@
[param tolerance_degrees] controls how many degrees the midpoint of a segment may deviate from the real curve, before the segment has to be subdivided.
</description>
</method>
+ <method name="tessellate_even_length" qualifiers="const">
+ <return type="PackedVector2Array" />
+ <param index="0" name="max_stages" type="int" default="5" />
+ <param index="1" name="tolerance_length" type="float" default="20.0" />
+ <description>
+ </description>
+ </method>
</methods>
<members>
<member name="bake_interval" type="float" setter="set_bake_interval" getter="get_bake_interval" default="5.0">
diff --git a/doc/classes/Curve3D.xml b/doc/classes/Curve3D.xml
index 3e4e05f51a..362d792b39 100644
--- a/doc/classes/Curve3D.xml
+++ b/doc/classes/Curve3D.xml
@@ -64,7 +64,7 @@
<return type="Vector3" />
<param index="0" name="to_point" type="Vector3" />
<description>
- Returns the closest baked point (in curve's local space) to [param to_point].
+ Returns the closest point on baked segments (in curve's local space) to [param to_point].
[param to_point] must be in this curve's local space.
</description>
</method>
@@ -114,7 +114,7 @@
</method>
<method name="sample_baked" qualifiers="const">
<return type="Vector3" />
- <param index="0" name="offset" type="float" />
+ <param index="0" name="offset" type="float" default="0.0" />
<param index="1" name="cubic" type="bool" default="false" />
<description>
Returns a point within the curve at position [param offset], where [param offset] is measured as a distance in 3D units along the curve.
@@ -132,6 +132,15 @@
If the curve has no up vectors, the function sends an error to the console, and returns [code](0, 1, 0)[/code].
</description>
</method>
+ <method name="sample_baked_with_rotation" qualifiers="const">
+ <return type="Transform3D" />
+ <param index="0" name="offset" type="float" default="0.0" />
+ <param index="1" name="cubic" type="bool" default="false" />
+ <param index="2" name="apply_tilt" type="bool" default="false" />
+ <description>
+ Similar with [code]interpolate_baked()[/code]. The the return value is [code]Transform3D[/code], with [code]origin[/code] as point position, [code]basis.x[/code] as sideway vector, [code]basis.y[/code] as up vector, [code]basis.z[/code] as forward vector. When the curve length is 0, there is no reasonable way to calculate the rotation, all vectors aligned with global space axes.
+ </description>
+ </method>
<method name="samplef" qualifiers="const">
<return type="Vector3" />
<param index="0" name="fofs" type="float" />
@@ -183,6 +192,15 @@
[param tolerance_degrees] controls how many degrees the midpoint of a segment may deviate from the real curve, before the segment has to be subdivided.
</description>
</method>
+ <method name="tessellate_even_length" qualifiers="const">
+ <return type="PackedVector3Array" />
+ <param index="0" name="max_stages" type="int" default="5" />
+ <param index="1" name="tolerance_length" type="float" default="0.2" />
+ <description>
+ Returns a list of points along the curve, with almost uniform density. [param max_stages] controls how many subdivisions a curve segment may face before it is considered approximate enough. Each subdivision splits the segment in half, so the default 5 stages may mean up to 32 subdivisions per curve segment. Increase with care!
+ [param tolerance_length] controls the maximal distance between two neighbouring points, before the segment has to be subdivided.
+ </description>
+ </method>
</methods>
<members>
<member name="bake_interval" type="float" setter="set_bake_interval" getter="get_bake_interval" default="0.2">
diff --git a/doc/classes/Dictionary.xml b/doc/classes/Dictionary.xml
index 9842288d35..5f99ba82b8 100644
--- a/doc/classes/Dictionary.xml
+++ b/doc/classes/Dictionary.xml
@@ -4,9 +4,8 @@
Dictionary type.
</brief_description>
<description>
- Dictionary type. Associative container, which contains values referenced by unique keys. Dictionaries are composed of pairs of keys (which must be unique) and values. Dictionaries will preserve the insertion order when adding elements. In other programming languages, this data structure is sometimes referred to as a hash map or associative array.
+ Dictionary type. Associative container, which contains values referenced by unique keys. Dictionaries are composed of pairs of keys (which must be unique) and values. Dictionaries will preserve the insertion order when adding new entries. In other programming languages, this data structure is sometimes referred to as a hash map or associative array.
You can define a dictionary by placing a comma-separated list of [code]key: value[/code] pairs in curly braces [code]{}[/code].
- Erasing elements while iterating over them [b]is not supported[/b] and will result in undefined behavior.
[b]Note:[/b] Dictionaries are always passed by reference. To get a copy of a dictionary which can be modified independently of the original dictionary, use [method duplicate].
Creating a dictionary:
[codeblocks]
@@ -40,10 +39,10 @@
};
[/csharp]
[/codeblocks]
- You can access a dictionary's values by referencing the appropriate key. In the above example, [code]points_dict["White"][/code] will return [code]50[/code]. You can also write [code]points_dict.White[/code], which is equivalent. However, you'll have to use the bracket syntax if the key you're accessing the dictionary with isn't a fixed string (such as a number or variable).
+ You can access a dictionary's value by referencing its corresponding key. In the above example, [code]points_dict["White"][/code] will return [code]50[/code]. You can also write [code]points_dict.White[/code], which is equivalent. However, you'll have to use the bracket syntax if the key you're accessing the dictionary with isn't a fixed string (such as a number or variable).
[codeblocks]
[gdscript]
- export(String, "White", "Yellow", "Orange") var my_color
+ @export(String, "White", "Yellow", "Orange") var my_color
var points_dict = {"White": 50, "Yellow": 75, "Orange": 100}
func _ready():
# We can't use dot syntax here as `my_color` is a variable.
@@ -69,7 +68,9 @@
Dictionaries can contain more complex data:
[codeblocks]
[gdscript]
- my_dict = {"First Array": [1, 2, 3, 4]} # Assigns an Array to a String key.
+ var my_dict = {
+ "First Array": [1, 2, 3, 4] # Assigns an Array to a String key.
+ }
[/gdscript]
[csharp]
var myDict = new Godot.Collections.Dictionary
@@ -91,7 +92,7 @@
{"Yellow", 75},
{"Orange", 100}
};
- pointsDict["blue"] = 150; // Add "Blue" as a key and assign 150 as its value.
+ pointsDict["Blue"] = 150; // Add "Blue" as a key and assign 150 as its value.
[/csharp]
[/codeblocks]
Finally, dictionaries can contain different types of keys and values in the same dictionary:
@@ -118,63 +119,23 @@
};
[/csharp]
[/codeblocks]
- [b]Note:[/b] Unlike [Array]s, you can't compare dictionaries directly:
+ The keys of a dictionary can be iterated with the [code]for[/code] keyword:
[codeblocks]
[gdscript]
- var array1 = [1, 2, 3]
- var array2 = [1, 2, 3]
-
- func compare_arrays():
- print(array1 == array2) # Will print true.
-
- var dict1 = {"a": 1, "b": 2, "c": 3}
- var dict2 = {"a": 1, "b": 2, "c": 3}
-
- func compare_dictionaries():
- print(dict1 == dict2) # Will NOT print true.
+ var groceries = {"Orange": 20, "Apple": 2, "Banana": 4}
+ for fruit in groceries:
+ var amount = groceries[fruit]
[/gdscript]
[csharp]
- // You have to use GD.Hash().
-
- public Godot.Collections.Array array1 = new Godot.Collections.Array{1, 2, 3};
- public Godot.Collections.Array array2 = new Godot.Collections.Array{1, 2, 3};
-
- public void CompareArrays()
+ var groceries = new Godot.Collections.Dictionary{{"Orange", 20}, {"Apple", 2}, {"Banana", 4}};
+ foreach (var (fruit, amount) in groceries)
{
- GD.Print(array1 == array2); // Will print FALSE!!
- GD.Print(GD.Hash(array1) == GD.Hash(array2)); // Will print true.
- }
-
- public Godot.Collections.Dictionary dict1 = new Godot.Collections.Dictionary{{"a", 1}, {"b", 2}, {"c", 3}};
- public Godot.Collections.Dictionary dict2 = new Godot.Collections.Dictionary{{"a", 1}, {"b", 2}, {"c", 3}};
-
- public void CompareDictionaries()
- {
- GD.Print(dict1 == dict2); // Will NOT print true.
+ // `fruit` is the key, `amount` is the value.
}
[/csharp]
[/codeblocks]
- You need to first calculate the dictionary's hash with [method hash] before you can compare them:
- [codeblocks]
- [gdscript]
- var dict1 = {"a": 1, "b": 2, "c": 3}
- var dict2 = {"a": 1, "b": 2, "c": 3}
-
- func compare_dictionaries():
- print(dict1.hash() == dict2.hash()) # Will print true.
- [/gdscript]
- [csharp]
- // You have to use GD.Hash().
- public Godot.Collections.Dictionary dict1 = new Godot.Collections.Dictionary{{"a", 1}, {"b", 2}, {"c", 3}};
- public Godot.Collections.Dictionary dict2 = new Godot.Collections.Dictionary{{"a", 1}, {"b", 2}, {"c", 3}};
-
- public void CompareDictionaries()
- {
- GD.Print(GD.Hash(dict1) == GD.Hash(dict2)); // Will print true.
- }
- [/csharp]
- [/codeblocks]
- [b]Note:[/b] When declaring a dictionary with [code]const[/code], the dictionary itself can still be mutated by defining the values of individual keys. Using [code]const[/code] will only prevent assigning the constant with another value after it was initialized.
+ [b]Note:[/b] Erasing elements while iterating over dictionaries is [b]not[/b] supported and will result in unpredictable behavior.
+ [b]Note:[/b] When declaring a dictionary with [code]const[/code], the dictionary becomes read-only. A read-only Dictionary's entries cannot be overridden at run-time. This does [i]not[/i] affect nested [Array] and [Dictionary] values.
</description>
<tutorials>
<link title="GDScript basics: Dictionary">$DOCS_URL/tutorials/scripting/gdscript/gdscript_basics.html#dictionary</link>
@@ -192,7 +153,7 @@
<return type="Dictionary" />
<param index="0" name="from" type="Dictionary" />
<description>
- Constructs a [Dictionary] as a copy of the given [Dictionary].
+ Returns the same array as [param from]. If you need a copy of the array, use [method duplicate].
</description>
</constructor>
</constructors>
@@ -200,30 +161,30 @@
<method name="clear">
<return type="void" />
<description>
- Clear the dictionary, removing all key/value pairs.
+ Clears the dictionary, removing all entries from it.
</description>
</method>
<method name="duplicate" qualifiers="const">
<return type="Dictionary" />
<param index="0" name="deep" type="bool" default="false" />
<description>
- Creates a copy of the dictionary, and returns it. The [param deep] parameter causes inner dictionaries and arrays to be copied recursively, but does not apply to objects.
+ Creates and returns a new copy of the dictionary. If [param deep] is [code]true[/code], inner [Dictionary] and [Array] keys and values are also copied, recursively.
</description>
</method>
<method name="erase">
<return type="bool" />
<param index="0" name="key" type="Variant" />
<description>
- Erase a dictionary key/value pair by key. Returns [code]true[/code] if the given key was present in the dictionary, [code]false[/code] otherwise.
- [b]Note:[/b] Don't erase elements while iterating over the dictionary. You can iterate over the [method keys] array instead.
+ Removes the dictionary entry by key, if it exists. Returns [code]true[/code] if the given [param key] existed in the dictionary, otherwise [code]false[/code].
+ [b]Note:[/b] Do not erase entries while iterating over the dictionary. You can iterate over the [method keys] array instead.
</description>
</method>
<method name="find_key" qualifiers="const">
<return type="Variant" />
<param index="0" name="value" type="Variant" />
<description>
- Returns the first key whose associated value is equal to [param value], or [code]null[/code] if no such value is found.
- [b]Note:[/b] [code]null[/code] is also a valid key. If you have it in your [Dictionary], the [method find_key] method can give misleading results.
+ Finds and returns the first key whose associated value is equal to [param value], or [code]null[/code] if it is not found.
+ [b]Note:[/b] [code]null[/code] is also a valid key. If inside the dictionary, [method find_key] may give misleading results.
</description>
</method>
<method name="get" qualifiers="const">
@@ -231,72 +192,89 @@
<param index="0" name="key" type="Variant" />
<param index="1" name="default" type="Variant" default="null" />
<description>
- Returns the current value for the specified key in the [Dictionary]. If the key does not exist, the method returns the value of the optional default argument, or [code]null[/code] if it is omitted.
+ Returns the corresponding value for the given [param key] in the dictionary. If the [param key] does not exist, returns [param default], or [code]null[/code] if the parameter is omitted.
</description>
</method>
<method name="has" qualifiers="const">
<return type="bool" />
<param index="0" name="key" type="Variant" />
<description>
- Returns [code]true[/code] if the dictionary has a given key.
- [b]Note:[/b] This is equivalent to using the [code]in[/code] operator as follows:
+ Returns [code]true[/code] if the dictionary contains an entry with the given [param key].
[codeblocks]
[gdscript]
- # Will evaluate to `true`.
- if "godot" in {"godot": "engine"}:
- pass
+ var my_dict = {
+ "Godot" : 4,
+ 210 : null,
+ }
+
+ print(my_dict.has("Godot")) # Prints true
+ print(my_dict.has(210)) # Prints true
+ print(my_dict.has(4)) # Prints false
[/gdscript]
[csharp]
- // You have to use Contains() here as an alternative to GDScript's `in` operator.
- if (new Godot.Collections.Dictionary{{"godot", "engine"}}.Contains("godot"))
+ var myDict = new Godot.Collections.Dictionary
{
- // I am executed.
- }
+ { "Godot", 4 },
+ { 210, default },
+ };
+
+ GD.Print(myDict.Contains("Godot")); // Prints true
+ GD.Print(myDict.Contains(210)); // Prints true
+ GD.Print(myDict.Contains(4)); // Prints false
[/csharp]
[/codeblocks]
- This method (like the [code]in[/code] operator) will evaluate to [code]true[/code] as long as the key exists, even if the associated value is [code]null[/code].
+ In GDScript, this is equivalent to the [code]in[/code] operator:
+ [codeblock]
+ if "Godot" in {"Godot": 4}:
+ print("The key is here!") # Will be printed.
+ [/codeblock]
+ [b]Note:[/b] This method returns [code]true[/code] as long as the [param key] exists, even if its corresponding value is [code]null[/code].
</description>
</method>
<method name="has_all" qualifiers="const">
<return type="bool" />
<param index="0" name="keys" type="Array" />
<description>
- Returns [code]true[/code] if the dictionary has all the keys in the given array.
+ Returns [code]true[/code] if the dictionary contains all keys in the given [param keys] array.
+ [codeblock]
+ var data = {"width" : 10, "height" : 20}
+ data.has_all(["height", "width"]) # Returns true
+ [/codeblock]
</description>
</method>
<method name="hash" qualifiers="const">
<return type="int" />
<description>
- Returns a hashed 32-bit integer value representing the dictionary contents. This can be used to compare dictionaries by value:
+ Returns a hashed 32-bit integer value representing the dictionary contents.
[codeblocks]
[gdscript]
- var dict1 = {0: 10}
- var dict2 = {0: 10}
- # The line below prints `true`, whereas it would have printed `false` if both variables were compared directly.
- print(dict1.hash() == dict2.hash())
+ var dict1 = {"A": 10, "B": 2}
+ var dict2 = {"A": 10, "B": 2}
+
+ print(dict1.hash() == dict2.hash()) # Prints true
[/gdscript]
[csharp]
- var dict1 = new Godot.Collections.Dictionary{{0, 10}};
- var dict2 = new Godot.Collections.Dictionary{{0, 10}};
- // The line below prints `true`, whereas it would have printed `false` if both variables were compared directly.
- // Dictionary has no Hash() method. Use GD.Hash() instead.
- GD.Print(GD.Hash(dict1) == GD.Hash(dict2));
+ var dict1 = new Godot.Collections.Dictionary{{"A", 10}, {"B", 2}};
+ var dict2 = new Godot.Collections.Dictionary{{"A", 10}, {"B", 2}};
+
+ // Godot.Collections.Dictionary has no Hash() method. Use GD.Hash() instead.
+ GD.Print(GD.Hash(dict1) == GD.Hash(dict2)); // Prints true
[/csharp]
[/codeblocks]
- [b]Note:[/b] Dictionaries with the same keys/values but in a different order will have a different hash.
- [b]Note:[/b] Dictionaries with equal content will always produce identical hash values. However, the reverse is not true. Returning identical hash values does [i]not[/i] imply the dictionaries are equal, because different dictionaries can have identical hash values due to hash collisions.
+ [b]Note:[/b] Dictionaries with the same entries but in a different order will not have the same hash.
+ [b]Note:[/b] Dictionaries with equal hash values are [i]not[/i] guaranteed to be the same, because of hash collisions. On the countrary, dictionaries with different hash values are guaranteed to be different.
</description>
</method>
<method name="is_empty" qualifiers="const">
<return type="bool" />
<description>
- Returns [code]true[/code] if the dictionary is empty.
+ Returns [code]true[/code] if the dictionary is empty (its size is [code]0[/code]). See also [method size].
</description>
</method>
<method name="keys" qualifiers="const">
<return type="Array" />
<description>
- Returns the list of keys in the [Dictionary].
+ Returns the list of keys in the dictionary.
</description>
</method>
<method name="merge">
@@ -304,19 +282,19 @@
<param index="0" name="dictionary" type="Dictionary" />
<param index="1" name="overwrite" type="bool" default="false" />
<description>
- Adds elements from [param dictionary] to this [Dictionary]. By default, duplicate keys will not be copied over, unless [param overwrite] is [code]true[/code].
+ Adds entries from [param dictionary] to this dictionary. By default, duplicate keys are not copied over, unless [param overwrite] is [code]true[/code].
</description>
</method>
<method name="size" qualifiers="const">
<return type="int" />
<description>
- Returns the number of keys in the dictionary.
+ Returns the number of entries in the dictionary. Empty dictionaries ([code]{ }[/code]) always return [code]0[/code]. See also [method is_empty].
</description>
</method>
<method name="values" qualifiers="const">
<return type="Array" />
<description>
- Returns the list of values in the [Dictionary].
+ Returns the list of values in this dictionary.
</description>
</method>
</methods>
@@ -325,21 +303,22 @@
<return type="bool" />
<param index="0" name="right" type="Dictionary" />
<description>
- Returns [code]true[/code] if the dictionaries differ, i.e. their key or value lists are different (including the order).
+ Returns [code]true[/code] if the two dictionaries do not contain the same keys and values.
</description>
</operator>
<operator name="operator ==">
<return type="bool" />
<param index="0" name="right" type="Dictionary" />
<description>
- Returns [code]true[/code] if both dictionaries have the same contents, i.e. their keys list and value list are equal.
+ Returns [code]true[/code] if the two dictionaries contain the same keys and values. The order of the entries does not matter.
+ [b]Note:[/b] In C#, by convention, this operator compares by [b]reference[/b]. If you need to compare by value, iterate over both dictionaries.
</description>
</operator>
<operator name="operator []">
<return type="Variant" />
<param index="0" name="key" type="Variant" />
<description>
- Returns a value at the given [param key] or [code]null[/code] and error if the key does not exist. For safe access, use [method get] or [method has].
+ Returns the corresponding value for the given [param key] in the dictionary. If the entry does not exist, fails and returns [code]null[/code]. For safe access, use [method get] or [method has].
</description>
</operator>
</operators>
diff --git a/doc/classes/DirectionalLight2D.xml b/doc/classes/DirectionalLight2D.xml
index a1b8ea86be..f825a9e082 100644
--- a/doc/classes/DirectionalLight2D.xml
+++ b/doc/classes/DirectionalLight2D.xml
@@ -1,16 +1,20 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="DirectionalLight2D" inherits="Light2D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
+ Directional 2D light from a distance.
</brief_description>
<description>
+ A directional light is a type of [Light2D] node that models an infinite number of parallel rays covering the entire scene. It is used for lights with strong intensity that are located far away from the scene (for example: to model sunlight or moonlight).
</description>
<tutorials>
+ <link title="2D lights and shadows">$DOCS_URL/tutorials/2d/2d_lights_and_shadows.html</link>
</tutorials>
<members>
<member name="height" type="float" setter="set_height" getter="get_height" default="0.0">
The height of the light. Used with 2D normal mapping. Ranges from 0 (parallel to the plane) to 1 (perpendicular to the plane).
</member>
<member name="max_distance" type="float" setter="set_max_distance" getter="get_max_distance" default="10000.0">
+ The maximum distance from the camera center objects can be before their shadows are culled (in pixels). Decreasing this value can prevent objects located outside the camera from casting shadows (while also improving performance). [member Camera2D.zoom] is not taken into account by [member max_distance], which means that at higher zoom values, shadows will appear to fade out sooner when zooming onto a given point.
</member>
</members>
</class>
diff --git a/doc/classes/DisplayServer.xml b/doc/classes/DisplayServer.xml
index 76c67fd704..29135376c5 100644
--- a/doc/classes/DisplayServer.xml
+++ b/doc/classes/DisplayServer.xml
@@ -719,6 +719,12 @@
[b]Note:[/b] This method is implemented on macOS, Windows and Linux (X11).
</description>
</method>
+ <method name="is_touchscreen_available" qualifiers="const">
+ <return type="bool" />
+ <description>
+ Returns [code]true[/code] if touch events are available (Android or iOS), the capability is detected on the Webplatform or if [member ProjectSettings.input_devices/pointing/emulate_touch_from_mouse] is [code]true[/code].
+ </description>
+ </method>
<method name="keyboard_get_current_layout" qualifiers="const">
<return type="int" />
<description>
@@ -889,13 +895,6 @@
Returns [code]true[/code] if the screen should never be turned off by the operating system's power-saving measures. See also [method screen_set_keep_on].
</description>
</method>
- <method name="screen_is_touchscreen" qualifiers="const">
- <return type="bool" />
- <param index="0" name="screen" type="int" default="-1" />
- <description>
- Returns [code]true[/code] if the screen can send touch events or if [member ProjectSettings.input_devices/pointing/emulate_touch_from_mouse] is [code]true[/code].
- </description>
- </method>
<method name="screen_set_keep_on">
<return type="void" />
<param index="0" name="enable" type="bool" />
@@ -1156,14 +1155,14 @@
<return type="Vector2i" />
<param index="0" name="window_id" type="int" default="0" />
<description>
- Returns the position of the given window to on the screen.
+ Returns the position of the client area of the given window on the screen.
</description>
</method>
- <method name="window_get_real_size" qualifiers="const">
+ <method name="window_get_position_with_decorations" qualifiers="const">
<return type="Vector2i" />
<param index="0" name="window_id" type="int" default="0" />
<description>
- Returns the size of the window specified by [param window_id] (in pixels), including the borders drawn by the operating system. See also [method window_get_size].
+ Returns the position of the given window on the screen including the borders drawn by the operating system. See also [method window_get_position].
</description>
</method>
<method name="window_get_safe_title_margins" qualifiers="const">
@@ -1177,7 +1176,14 @@
<return type="Vector2i" />
<param index="0" name="window_id" type="int" default="0" />
<description>
- Returns the size of the window specified by [param window_id] (in pixels), excluding the borders drawn by the operating system. This is also called the "client area". See also [method window_get_real_size], [method window_set_size] and [method window_get_position].
+ Returns the size of the window specified by [param window_id] (in pixels), excluding the borders drawn by the operating system. This is also called the "client area". See also [method window_get_size_with_decorations], [method window_set_size] and [method window_get_position].
+ </description>
+ </method>
+ <method name="window_get_size_with_decorations" qualifiers="const">
+ <return type="Vector2i" />
+ <param index="0" name="window_id" type="int" default="0" />
+ <description>
+ Returns the size of the window specified by [param window_id] (in pixels), including the borders drawn by the operating system. See also [method window_get_size].
</description>
</method>
<method name="window_get_vsync_mode" qualifiers="const">
@@ -1634,13 +1640,17 @@
Maximized window mode, i.e. [Window] will occupy whole screen area except task bar and still display its borders. Normally happens when the minimize button is pressed.
</constant>
<constant name="WINDOW_MODE_FULLSCREEN" value="3" enum="WindowMode">
- Full screen window mode. Note that this is not [i]exclusive[/i] full screen. On Windows and Linux (X11), a borderless window is used to emulate full screen. On macOS, a new desktop is used to display the running project.
- Regardless of the platform, enabling full screen will change the window size to match the monitor's size. Therefore, make sure your project supports [url=$DOCS_URL/tutorials/rendering/multiple_resolutions.html]multiple resolutions[/url] when enabling full screen mode.
+ Full screen mode with full multi-window support.
+ Full screen window cover the entire display area of a screen, have no border or decorations. Display video mode is not changed.
+ [b]Note:[/b] Regardless of the platform, enabling full screen will change the window size to match the monitor's size. Therefore, make sure your project supports [url=$DOCS_URL/tutorials/rendering/multiple_resolutions.html]multiple resolutions[/url] when enabling full screen mode.
</constant>
<constant name="WINDOW_MODE_EXCLUSIVE_FULLSCREEN" value="4" enum="WindowMode">
- Exclusive full screen window mode. This mode is implemented on Windows only. On other platforms, it is equivalent to [constant WINDOW_MODE_FULLSCREEN].
- Only one window in exclusive full screen mode can be visible on a given screen at a time. If multiple windows are in exclusive full screen mode for the same screen, the last one being set to this mode takes precedence.
- Regardless of the platform, enabling full screen will change the window size to match the monitor's size. Therefore, make sure your project supports [url=$DOCS_URL/tutorials/rendering/multiple_resolutions.html]multiple resolutions[/url] when enabling full screen mode.
+ A single window full screen mode. This mode has less overhead, but only one window can be open on a given screen at a time (opening a child window or application switching will trigger a full screen transition).
+ Full screen window cover the entire display area of a screen, have no border or decorations. Display video mode is not changed.
+ [b]On Windows:[/b] Depending on video driver, full screen transition might cause screens to go black for a moment.
+ [b]On macOS:[/b] Exclusive full screen mode prevents Dock and Menu from showing up when the mouse pointer is hovering the edge of the screen.
+ [b]On Linux (X11):[/b] Exclusive full screen mode bypasses compositor.
+ [b]Note:[/b] Regardless of the platform, enabling full screen will change the window size to match the monitor's size. Therefore, make sure your project supports [url=$DOCS_URL/tutorials/rendering/multiple_resolutions.html]multiple resolutions[/url] when enabling full screen mode.
</constant>
<constant name="WINDOW_FLAG_RESIZE_DISABLED" value="0" enum="WindowFlags">
The window can't be resizing by dragging its resize grip. It's still possible to resize the window using [method window_set_size]. This flag is ignored for full screen windows.
@@ -1714,6 +1724,7 @@
<constant name="DISPLAY_HANDLE" value="0" enum="HandleType">
Display handle:
- Linux (X11): [code]X11::Display*[/code] for the display.
+ - Android: [code]EGLDisplay[/code] for the display.
</constant>
<constant name="WINDOW_HANDLE" value="1" enum="HandleType">
Window handle:
diff --git a/doc/classes/EditorDebuggerPlugin.xml b/doc/classes/EditorDebuggerPlugin.xml
index c3e0a995c6..10da1edd56 100644
--- a/doc/classes/EditorDebuggerPlugin.xml
+++ b/doc/classes/EditorDebuggerPlugin.xml
@@ -1,88 +1,88 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="EditorDebuggerPlugin" inherits="Control" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+<class name="EditorDebuggerPlugin" inherits="RefCounted" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
A base class to implement debugger plugins.
</brief_description>
<description>
[EditorDebuggerPlugin] provides functions related to the editor side of the debugger.
- You don't need to instantiate this class; that is automatically handled by the debugger. [Control] nodes can be added as child nodes to provide a GUI for the plugin.
- Do not free or reparent this node, otherwise it becomes unusable.
- To use [EditorDebuggerPlugin], register it using the [method EditorPlugin.add_debugger_plugin] method first.
+ To interact with the debugger, an instance of this class must be added to the editor via [method EditorPlugin.add_debugger_plugin].
+ Once added, the [method _setup_session] callback will be called for every [EditorDebuggerSession] available to the plugin, and when new ones are created (the sessions may be inactive during this stage).
+ You can retrieve the available [EditorDebuggerSession]s via [method get_sessions] or get a specific one via [method get_session].
+ [codeblocks]
+ [gdscript]
+ @tool
+ extends EditorPlugin
+
+ class ExampleEditorDebugger extends EditorDebuggerPlugin:
+
+ func _has_capture(prefix):
+ # Return true if you wish to handle message with this prefix.
+ return prefix == "my_plugin"
+
+ func _capture(message, data, session_id):
+ if message == "my_plugin:ping":
+ get_session(session_id).send_message("my_plugin:echo", data)
+
+ func _setup_session(session_id):
+ # Add a new tab in the debugger session UI containing a label.
+ var label = Label.new()
+ label.name = "Example plugin"
+ label.text = "Example plugin"
+ var session = get_session(session_id)
+ # Listens to the session started and stopped signals.
+ session.started.connect(func (): print("Session started"))
+ session.stopped.connect(func (): print("Session stopped"))
+ session.add_session_tab(label)
+
+ var debugger = ExampleEditorDebugger.new()
+
+ func _enter_tree():
+ add_debugger_plugin(debugger)
+
+ func _exit_tree():
+ remove_debugger_plugin(debugger)
+ [/gdscript]
+ [/codeblocks]
</description>
<tutorials>
</tutorials>
<methods>
- <method name="has_capture">
- <return type="bool" />
- <param index="0" name="name" type="StringName" />
- <description>
- Returns [code]true[/code] if a message capture with given name is present otherwise [code]false[/code].
- </description>
- </method>
- <method name="is_breaked">
- <return type="bool" />
- <description>
- Returns [code]true[/code] if the game is in break state otherwise [code]false[/code].
- </description>
- </method>
- <method name="is_debuggable">
+ <method name="_capture" qualifiers="virtual">
<return type="bool" />
+ <param index="0" name="message" type="String" />
+ <param index="1" name="data" type="Array" />
+ <param index="2" name="session_id" type="int" />
<description>
- Returns [code]true[/code] if the game can be debugged otherwise [code]false[/code].
+ Override this method to process incoming messages. The [param session_id] is the ID of the [EditorDebuggerSession] that received the message (which you can retrieve via [method get_session]).
</description>
</method>
- <method name="is_session_active">
+ <method name="_has_capture" qualifiers="virtual const">
<return type="bool" />
+ <param index="0" name="capture" type="String" />
<description>
- Returns [code]true[/code] if there is an instance of the game running with the attached debugger otherwise [code]false[/code].
+ Override this method to enable receiving messages from the debugger. If [param capture] is "my_message" then messages starting with "my_message:" will be passes to the [method _capture] method.
</description>
</method>
- <method name="register_message_capture">
+ <method name="_setup_session" qualifiers="virtual">
<return type="void" />
- <param index="0" name="name" type="StringName" />
- <param index="1" name="callable" type="Callable" />
+ <param index="0" name="session_id" type="int" />
<description>
- Registers a message capture with given [param name]. If [param name] is "my_message" then messages starting with "my_message:" will be called with the given callable.
- Callable must accept a message string and a data array as argument. If the message and data are valid then callable must return [code]true[/code] otherwise [code]false[/code].
+ Override this method to be notified whenever a new [EditorDebuggerSession] is created (the session may be inactive during this stage).
</description>
</method>
- <method name="send_message">
- <return type="void" />
- <param index="0" name="message" type="String" />
- <param index="1" name="data" type="Array" />
+ <method name="get_session">
+ <return type="EditorDebuggerSession" />
+ <param index="0" name="id" type="int" />
<description>
- Sends a message with given [param message] and [param data] array.
+ Returns the [EditorDebuggerSession] with the given [param id].
</description>
</method>
- <method name="unregister_message_capture">
- <return type="void" />
- <param index="0" name="name" type="StringName" />
+ <method name="get_sessions">
+ <return type="Array" />
<description>
- Unregisters the message capture with given name.
+ Returns an array of [EditorDebuggerSession] currently available to this debugger plugin.
+ Note: Not sessions in the array may be inactive, check their state via [method EditorDebuggerSession.is_active]
</description>
</method>
</methods>
- <signals>
- <signal name="breaked">
- <param index="0" name="can_debug" type="bool" />
- <description>
- Emitted when the game enters a break state.
- </description>
- </signal>
- <signal name="continued">
- <description>
- Emitted when the game exists a break state.
- </description>
- </signal>
- <signal name="started">
- <description>
- Emitted when the debugging starts.
- </description>
- </signal>
- <signal name="stopped">
- <description>
- Emitted when the debugging stops.
- </description>
- </signal>
- </signals>
</class>
diff --git a/doc/classes/EditorDebuggerSession.xml b/doc/classes/EditorDebuggerSession.xml
new file mode 100644
index 0000000000..faf528c143
--- /dev/null
+++ b/doc/classes/EditorDebuggerSession.xml
@@ -0,0 +1,86 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="EditorDebuggerSession" inherits="RefCounted" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+ <brief_description>
+ A class to interact with the editor debugger.
+ </brief_description>
+ <description>
+ This class cannot be directly instantiated and must be retrieved via a [EditorDebuggerPlugin].
+ You can add tabs to the session UI via [method add_session_tab], send messages via [method send_message], and toggle [EngineProfiler]s via [method toggle_profiler].
+ </description>
+ <tutorials>
+ </tutorials>
+ <methods>
+ <method name="add_session_tab">
+ <return type="void" />
+ <param index="0" name="control" type="Control" />
+ <description>
+ Adds the given [param control] to the debug session UI in the debugger bottom panel.
+ </description>
+ </method>
+ <method name="is_active">
+ <return type="bool" />
+ <description>
+ Returns [code]true[/code] if the debug session is currently attached to a remote instance.
+ </description>
+ </method>
+ <method name="is_breaked">
+ <return type="bool" />
+ <description>
+ Returns [code]true[/code] if the attached remote instance is currently in the debug loop.
+ </description>
+ </method>
+ <method name="is_debuggable">
+ <return type="bool" />
+ <description>
+ Returns [code]true[/code] if the attached remote instance can be debugged.
+ </description>
+ </method>
+ <method name="remove_session_tab">
+ <return type="void" />
+ <param index="0" name="control" type="Control" />
+ <description>
+ Removes the given [param control] from the debug session UI in the debugger bottom panel.
+ </description>
+ </method>
+ <method name="send_message">
+ <return type="void" />
+ <param index="0" name="message" type="String" />
+ <param index="1" name="data" type="Array" default="[]" />
+ <description>
+ Sends the given [param message] to the attached remote instance, optionally passing additionally [param data]. See [EngineDebugger] for how to retrieve those messages.
+ </description>
+ </method>
+ <method name="toggle_profiler">
+ <return type="void" />
+ <param index="0" name="profiler" type="String" />
+ <param index="1" name="enable" type="bool" />
+ <param index="2" name="data" type="Array" default="[]" />
+ <description>
+ Toggle the given [param profiler] on the attached remote instance, optionally passing additionally [param data]. See [EngineProfiler] for more details.
+ </description>
+ </method>
+ </methods>
+ <signals>
+ <signal name="breaked">
+ <param index="0" name="can_debug" type="bool" />
+ <description>
+ Emitted when the attached remote instance enters a break state. If [param can_debug] is [code]true[/code], the remote instance will enter the debug loop.
+ </description>
+ </signal>
+ <signal name="continued">
+ <description>
+ Emitted when the attached remote instance exits a break state.
+ </description>
+ </signal>
+ <signal name="started">
+ <description>
+ Emitted when a remote instance is attached to this session (i.e. the session becomes active).
+ </description>
+ </signal>
+ <signal name="stopped">
+ <description>
+ Emitted when a remote instance is detached from this session (i.e. the session becomes inactive).
+ </description>
+ </signal>
+ </signals>
+</class>
diff --git a/doc/classes/EditorInspector.xml b/doc/classes/EditorInspector.xml
index 0cda49f1bf..ab35a62794 100644
--- a/doc/classes/EditorInspector.xml
+++ b/doc/classes/EditorInspector.xml
@@ -7,7 +7,7 @@
This is the control that implements property editing in the editor's Settings dialogs, the Inspector dock, etc. To get the [EditorInspector] used in the editor's Inspector dock, use [method EditorInterface.get_inspector].
[EditorInspector] will show properties in the same order as the array returned by [method Object.get_property_list].
If a property's name is path-like (i.e. if it contains forward slashes), [EditorInspector] will create nested sections for "directories" along the path. For example, if a property is named [code]highlighting/gdscript/node_path_color[/code], it will be shown as "Node Path Color" inside the "GDScript" section nested inside the "Highlighting" section.
- If a property has [constant PROPERTY_USAGE_GROUP] usage, it will group subsequent properties whose name starts with the property's hint string. The group ends when a property does not start with that hint string or when a new group starts. An empty group name effectively ends the current group. [EditorInspector] will create a top-level section for each group. For example, if a property with group usage is named [code]Collide With[/code] and its hint string is [code]collide_with_[/code], a subsequent [code]collide_with_area[/code] property will be shown as "Area" inside the "Collide With" section.
+ If a property has [constant PROPERTY_USAGE_GROUP] usage, it will group subsequent properties whose name starts with the property's hint string. The group ends when a property does not start with that hint string or when a new group starts. An empty group name effectively ends the current group. [EditorInspector] will create a top-level section for each group. For example, if a property with group usage is named [code]Collide With[/code] and its hint string is [code]collide_with_[/code], a subsequent [code]collide_with_area[/code] property will be shown as "Area" inside the "Collide With" section. There is also a special case: when the hint string contains the name of a property, that property is grouped too. This is mainly to help grouping properties like [code]font[/code], [code]font_color[/code] and [code]font_size[/code] (using the hint string [code]font_[/code]).
If a property has [constant PROPERTY_USAGE_SUBGROUP] usage, a subgroup will be created in the same way as a group, and a second-level section will be created for each subgroup.
[b]Note:[/b] Unlike sections created from path-like property names, [EditorInspector] won't capitalize the name for sections created from groups. So properties with group usage usually use capitalized names instead of snake_cased names.
</description>
diff --git a/doc/classes/EditorInterface.xml b/doc/classes/EditorInterface.xml
index bb319cb5a3..5d4b83bc27 100644
--- a/doc/classes/EditorInterface.xml
+++ b/doc/classes/EditorInterface.xml
@@ -48,6 +48,12 @@
[b]Warning:[/b] Removing and freeing this node will render a part of the editor useless and may cause a crash.
</description>
</method>
+ <method name="get_current_directory" qualifiers="const">
+ <return type="String" />
+ <description>
+ Returns the current directory being viewed in the [FileSystemDock]. If a file is selected, its base directory will be returned using [method String.get_base_dir] instead.
+ </description>
+ </method>
<method name="get_current_path" qualifiers="const">
<return type="String" />
<description>
@@ -131,10 +137,10 @@
[b]Warning:[/b] Removing and freeing this node will render a part of the editor useless and may cause a crash.
</description>
</method>
- <method name="get_selected_path" qualifiers="const">
- <return type="String" />
+ <method name="get_selected_paths" qualifiers="const">
+ <return type="PackedStringArray" />
<description>
- Returns the path of the directory currently selected in the [FileSystemDock]. If a file is selected, its base directory will be returned using [method String.get_base_dir] instead.
+ Returns an array containing the paths of the currently selected files (and directories) in the [FileSystemDock].
</description>
</method>
<method name="get_selection">
diff --git a/doc/classes/EditorNode3DGizmoPlugin.xml b/doc/classes/EditorNode3DGizmoPlugin.xml
index 24e1a2da7c..3ab13ec5c0 100644
--- a/doc/classes/EditorNode3DGizmoPlugin.xml
+++ b/doc/classes/EditorNode3DGizmoPlugin.xml
@@ -8,7 +8,7 @@
To use [EditorNode3DGizmoPlugin], register it using the [method EditorPlugin.add_node_3d_gizmo_plugin] method first.
</description>
<tutorials>
- <link title="Node3D gizmo plugins">$DOCS_URL/tutorials/plugins/editor/spatial_gizmos.html</link>
+ <link title="Node3D gizmo plugins">$DOCS_URL/tutorials/plugins/editor/3d_gizmos.html</link>
</tutorials>
<methods>
<method name="_can_be_hidden" qualifiers="virtual const">
diff --git a/doc/classes/EditorPaths.xml b/doc/classes/EditorPaths.xml
index 2975ea6d75..929cf767a6 100644
--- a/doc/classes/EditorPaths.xml
+++ b/doc/classes/EditorPaths.xml
@@ -6,7 +6,7 @@
<description>
This editor-only singleton returns OS-specific paths to various data folders and files. It can be used in editor plugins to ensure files are saved in the correct location on each operating system.
[b]Note:[/b] This singleton is not accessible in exported projects. Attempting to access it in an exported project will result in a script error as the singleton won't be declared. To prevent script errors in exported projects, use [method Engine.has_singleton] to check whether the singleton is available before using it.
- [b]Note:[/b] Godot complies with the [url=https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html]XDG Base Directory Specification[/url] on [i]all[/i] platforms. You can override environment variables following the specification to change the editor and project data paths.
+ [b]Note:[/b] On the Linux/BSD platform, Godot complies with the [url=https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html]XDG Base Directory Specification[/url]. You can override environment variables following the specification to change the editor and project data paths.
</description>
<tutorials>
<link title="File paths in Godot projects">https://docs.godotengine.org/en/latest/tutorials/io/data_paths.html</link>
diff --git a/doc/classes/EditorPlugin.xml b/doc/classes/EditorPlugin.xml
index 2289a373bf..adcc87d062 100644
--- a/doc/classes/EditorPlugin.xml
+++ b/doc/classes/EditorPlugin.xml
@@ -415,7 +415,7 @@
</method>
<method name="add_debugger_plugin">
<return type="void" />
- <param index="0" name="script" type="Script" />
+ <param index="0" name="script" type="EditorDebuggerPlugin" />
<description>
Adds a [Script] as debugger plugin to the Debugger. The script must extend [EditorDebuggerPlugin].
</description>
@@ -599,7 +599,7 @@
</method>
<method name="remove_debugger_plugin">
<return type="void" />
- <param index="0" name="script" type="Script" />
+ <param index="0" name="script" type="EditorDebuggerPlugin" />
<description>
Removes the debugger plugin with given script from the Debugger.
</description>
@@ -719,44 +719,64 @@
</signals>
<constants>
<constant name="CONTAINER_TOOLBAR" value="0" enum="CustomControlContainer">
+ Main editor toolbar, next to play buttons.
</constant>
<constant name="CONTAINER_SPATIAL_EDITOR_MENU" value="1" enum="CustomControlContainer">
+ The toolbar that appears when 3D editor is active.
</constant>
<constant name="CONTAINER_SPATIAL_EDITOR_SIDE_LEFT" value="2" enum="CustomControlContainer">
+ Left sidebar of the 3D editor.
</constant>
<constant name="CONTAINER_SPATIAL_EDITOR_SIDE_RIGHT" value="3" enum="CustomControlContainer">
+ Right sidebar of the 3D editor.
</constant>
<constant name="CONTAINER_SPATIAL_EDITOR_BOTTOM" value="4" enum="CustomControlContainer">
+ Bottom panel of the 3D editor.
</constant>
<constant name="CONTAINER_CANVAS_EDITOR_MENU" value="5" enum="CustomControlContainer">
+ The toolbar that appears when 2D editor is active.
</constant>
<constant name="CONTAINER_CANVAS_EDITOR_SIDE_LEFT" value="6" enum="CustomControlContainer">
+ Left sidebar of the 2D editor.
</constant>
<constant name="CONTAINER_CANVAS_EDITOR_SIDE_RIGHT" value="7" enum="CustomControlContainer">
+ Right sidebar of the 2D editor.
</constant>
<constant name="CONTAINER_CANVAS_EDITOR_BOTTOM" value="8" enum="CustomControlContainer">
+ Bottom panel of the 2D editor.
</constant>
<constant name="CONTAINER_INSPECTOR_BOTTOM" value="9" enum="CustomControlContainer">
+ Bottom section of the inspector.
</constant>
<constant name="CONTAINER_PROJECT_SETTING_TAB_LEFT" value="10" enum="CustomControlContainer">
+ Tab of Project Settings dialog, to the left of other tabs.
</constant>
<constant name="CONTAINER_PROJECT_SETTING_TAB_RIGHT" value="11" enum="CustomControlContainer">
+ Tab of Project Settings dialog, to the right of other tabs.
</constant>
<constant name="DOCK_SLOT_LEFT_UL" value="0" enum="DockSlot">
+ Dock slot, left side, upper-left (empty in default layout).
</constant>
<constant name="DOCK_SLOT_LEFT_BL" value="1" enum="DockSlot">
+ Dock slot, left side, bottom-left (empty in default layout).
</constant>
<constant name="DOCK_SLOT_LEFT_UR" value="2" enum="DockSlot">
+ Dock slot, left side, upper-right (in default layout includes Scene and Import docks).
</constant>
<constant name="DOCK_SLOT_LEFT_BR" value="3" enum="DockSlot">
+ Dock slot, left side, bottom-right (in default layout includes FileSystem dock).
</constant>
<constant name="DOCK_SLOT_RIGHT_UL" value="4" enum="DockSlot">
+ Dock slot, right side, upper-left (empty in default layout).
</constant>
<constant name="DOCK_SLOT_RIGHT_BL" value="5" enum="DockSlot">
+ Dock slot, right side, bottom-left (empty in default layout).
</constant>
<constant name="DOCK_SLOT_RIGHT_UR" value="6" enum="DockSlot">
+ Dock slot, right side, upper-right (in default layout includes Inspector, Node and History docks).
</constant>
<constant name="DOCK_SLOT_RIGHT_BR" value="7" enum="DockSlot">
+ Dock slot, right side, bottom-right (empty in default layout).
</constant>
<constant name="DOCK_SLOT_MAX" value="8" enum="DockSlot">
Represents the size of the [enum DockSlot] enum.
diff --git a/doc/classes/EditorProperty.xml b/doc/classes/EditorProperty.xml
index 2aca19510b..e18bea1f67 100644
--- a/doc/classes/EditorProperty.xml
+++ b/doc/classes/EditorProperty.xml
@@ -150,7 +150,7 @@
<param index="1" name="pinned" type="bool" />
<description>
Emit it if you want to mark (or unmark) the value of a property for being saved regardless of being equal to the default value.
- The default value is the one the property will get when the node is just instantiated and can come from an ancestor scene in the inheritance/instancing chain, a script or a builtin class.
+ The default value is the one the property will get when the node is just instantiated and can come from an ancestor scene in the inheritance/instantiation chain, a script or a builtin class.
</description>
</signal>
<signal name="resource_selected">
diff --git a/doc/classes/EditorSceneFormatImporter.xml b/doc/classes/EditorSceneFormatImporter.xml
index 6de9c2c5dc..db93cab14c 100644
--- a/doc/classes/EditorSceneFormatImporter.xml
+++ b/doc/classes/EditorSceneFormatImporter.xml
@@ -39,7 +39,6 @@
<param index="0" name="path" type="String" />
<param index="1" name="flags" type="int" />
<param index="2" name="options" type="Dictionary" />
- <param index="3" name="bake_fps" type="int" />
<description>
</description>
</method>
diff --git a/doc/classes/EditorScenePostImport.xml b/doc/classes/EditorScenePostImport.xml
index 2bf2accf17..d2ad8d1bed 100644
--- a/doc/classes/EditorScenePostImport.xml
+++ b/doc/classes/EditorScenePostImport.xml
@@ -28,12 +28,12 @@
// This sample changes all node names.
// Called right after the scene is imported and gets the root node.
[Tool]
- public class NodeRenamer : EditorScenePostImport
+ public partial class NodeRenamer : EditorScenePostImport
{
- public override Object PostImport(Object scene)
+ public override Object _PostImport(Node scene)
{
// Change all node names to "modified_[oldnodename]"
- Iterate(scene as Node);
+ Iterate(scene);
return scene; // Remember to return the imported scene
}
public void Iterate(Node node)
diff --git a/doc/classes/EditorSettings.xml b/doc/classes/EditorSettings.xml
index 07457387a0..98f4789163 100644
--- a/doc/classes/EditorSettings.xml
+++ b/doc/classes/EditorSettings.xml
@@ -592,6 +592,9 @@
<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/draw_extra_borders" type="bool" setter="" getter="">
+ If [code]true[/code], draws additional borders around interactive UI elements in the editor. This is automatically enabled when using the [b]Black (OLED)[/b] theme preset, as this theme preset uses a fully black background.
+ </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].
@@ -625,6 +628,9 @@
<member name="network/tls/editor_tls_certificates" type="String" setter="" getter="">
The TLS 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/default_renderer" type="String" setter="" getter="">
+ The renderer type that will be checked off by default when creating a new project. Accepted strings are "forward_plus", "mobile" or "gl_compatibility".
+ </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>
diff --git a/doc/classes/EditorSpinSlider.xml b/doc/classes/EditorSpinSlider.xml
index de105b32e1..d270d32df7 100644
--- a/doc/classes/EditorSpinSlider.xml
+++ b/doc/classes/EditorSpinSlider.xml
@@ -28,4 +28,26 @@
The suffix to display after the value (in a faded color). This should generally be a plural word. You may have to use an abbreviation if the suffix is too long to be displayed.
</member>
</members>
+ <signals>
+ <signal name="grabbed">
+ <description>
+ Emitted when the spinner/slider is grabbed.
+ </description>
+ </signal>
+ <signal name="ungrabbed">
+ <description>
+ Emitted when the spinner/slider is ungrabbed.
+ </description>
+ </signal>
+ <signal name="value_focus_entered">
+ <description>
+ Emitted when the value form gains focus.
+ </description>
+ </signal>
+ <signal name="value_focus_exited">
+ <description>
+ Emitted when the value form loses focus.
+ </description>
+ </signal>
+ </signals>
</class>
diff --git a/doc/classes/EditorUndoRedoManager.xml b/doc/classes/EditorUndoRedoManager.xml
index c1e771d653..cd96e740e8 100644
--- a/doc/classes/EditorUndoRedoManager.xml
+++ b/doc/classes/EditorUndoRedoManager.xml
@@ -110,7 +110,7 @@
<signals>
<signal name="history_changed">
<description>
- Emitted when the list of actions in any history has changed, either when an action is commited or a history is cleared.
+ Emitted when the list of actions in any history has changed, either when an action is committed or a history is cleared.
</description>
</signal>
<signal name="version_changed">
@@ -123,6 +123,9 @@
<constant name="GLOBAL_HISTORY" value="0" enum="SpecialHistory">
Global history not associated with any scene, but with external resources etc.
</constant>
+ <constant name="REMOTE_HISTORY" value="-9" enum="SpecialHistory">
+ History associated with remote inspector. Used when live editing a running project.
+ </constant>
<constant name="INVALID_HISTORY" value="-99" enum="SpecialHistory">
Invalid "null" history. It's a special value, not associated with any object.
</constant>
diff --git a/doc/classes/EditorVCSInterface.xml b/doc/classes/EditorVCSInterface.xml
index b766978c04..85c10fefd9 100644
--- a/doc/classes/EditorVCSInterface.xml
+++ b/doc/classes/EditorVCSInterface.xml
@@ -53,7 +53,7 @@
</description>
</method>
<method name="_get_branch_list" qualifiers="virtual">
- <return type="Dictionary[]" />
+ <return type="String[]" />
<description>
Gets an instance of an [Array] of [String]s containing available branch names in the VCS.
</description>
@@ -94,7 +94,7 @@
</description>
</method>
<method name="_get_remotes" qualifiers="virtual">
- <return type="Dictionary[]" />
+ <return type="String[]" />
<description>
Returns an [Array] of [String]s, each containing the name of a remote configured in the VCS.
</description>
diff --git a/doc/classes/Engine.xml b/doc/classes/Engine.xml
index 821fae37a6..d583e07f59 100644
--- a/doc/classes/Engine.xml
+++ b/doc/classes/Engine.xml
@@ -275,13 +275,16 @@
If [member ProjectSettings.display/window/vsync/vsync_mode] is [code]Disabled[/code], limiting the FPS to a high value that can be consistently reached on the system can reduce input lag compared to an uncapped framerate. Since this works by ensuring the GPU load is lower than 100%, this latency reduction is only effective in GPU-bottlenecked scenarios, not CPU-bottlenecked scenarios.
See also [member physics_ticks_per_second] and [member ProjectSettings.application/run/max_fps].
</member>
+ <member name="max_physics_steps_per_frame" type="int" setter="set_max_physics_steps_per_frame" getter="get_max_physics_steps_per_frame" default="8">
+ Controls the maximum number of physics steps that can be simulated each rendered frame. The default value is tuned to avoid "spiral of death" situations where expensive physics simulations trigger more expensive simulations indefinitely. However, the game will appear to slow down if the rendering FPS is less than [code]1 / max_physics_steps_per_frame[/code] of [member physics_ticks_per_second]. This occurs even if [code]delta[/code] is consistently used in physics calculations. To avoid this, increase [member max_physics_steps_per_frame] if you have increased [member physics_ticks_per_second] significantly above its default value.
+ </member>
<member name="physics_jitter_fix" type="float" setter="set_physics_jitter_fix" getter="get_physics_jitter_fix" default="0.5">
Controls how much physics ticks are synchronized with real time. For 0 or less, the ticks are synchronized. Such values are recommended for network games, where clock synchronization matters. Higher values cause higher deviation of the in-game clock and real clock but smooth out framerate jitters. The default value of 0.5 should be fine for most; values above 2 could cause the game to react to dropped frames with a noticeable delay and are not recommended.
[b]Note:[/b] For best results, when using a custom physics interpolation solution, the physics jitter fix should be disabled by setting [member physics_jitter_fix] to [code]0[/code].
</member>
<member name="physics_ticks_per_second" type="int" setter="set_physics_ticks_per_second" getter="get_physics_ticks_per_second" default="60">
The number of fixed iterations per second. This controls how often physics simulation and [method Node._physics_process] methods are run. This value should generally always be set to [code]60[/code] or above, as Godot doesn't interpolate the physics step. As a result, values lower than [code]60[/code] will look stuttery. This value can be increased to make input more reactive or work around collision tunneling issues, but keep in mind doing so will increase CPU usage. See also [member max_fps] and [member ProjectSettings.physics/common/physics_ticks_per_second].
- [b]Note:[/b] Only 8 physics ticks may be simulated per rendered frame at most. If more than 8 physics ticks have to be simulated per rendered frame to keep up with rendering, the game will appear to slow down (even if [code]delta[/code] is used consistently in physics calculations). Therefore, it is recommended not to increase [member physics_ticks_per_second] above 240. Otherwise, the game will slow down when the rendering framerate goes below 30 FPS.
+ [b]Note:[/b] Only [member max_physics_steps_per_frame] physics ticks may be simulated per rendered frame at most. If more physics ticks have to be simulated per rendered frame to keep up with rendering, the project will appear to slow down (even if [code]delta[/code] is used consistently in physics calculations). Therefore, it is recommended to also increase [member max_physics_steps_per_frame] if increasing [member physics_ticks_per_second] significantly above its default value.
</member>
<member name="print_error_messages" type="bool" setter="set_print_error_messages" getter="is_printing_error_messages" default="true">
If [code]false[/code], stops printing error and warning messages to the console and editor Output log. This can be used to hide error and warning messages during unit test suite runs. This property is equivalent to the [member ProjectSettings.application/run/disable_stderr] project setting.
diff --git a/doc/classes/FileAccess.xml b/doc/classes/FileAccess.xml
index e52f897164..be0c8fd6ca 100644
--- a/doc/classes/FileAccess.xml
+++ b/doc/classes/FileAccess.xml
@@ -153,6 +153,20 @@
Returns the last error that happened when trying to perform operations. Compare with the [code]ERR_FILE_*[/code] constants from [enum Error].
</description>
</method>
+ <method name="get_file_as_bytes" qualifiers="static">
+ <return type="PackedByteArray" />
+ <param index="0" name="path" type="String" />
+ <description>
+ Returns the whole [param path] file contents as a [PackedByteArray] without any decoding.
+ </description>
+ </method>
+ <method name="get_file_as_string" qualifiers="static">
+ <return type="String" />
+ <param index="0" name="path" type="String" />
+ <description>
+ Returns the whole [param path] file contents as a [String]. Text is interpreted as being UTF-8 encoded.
+ </description>
+ </method>
<method name="get_float" qualifiers="const">
<return type="float" />
<description>
diff --git a/doc/classes/FileSystemDock.xml b/doc/classes/FileSystemDock.xml
index 5578f449b3..00f5c7ddff 100644
--- a/doc/classes/FileSystemDock.xml
+++ b/doc/classes/FileSystemDock.xml
@@ -46,7 +46,7 @@
<description>
</description>
</signal>
- <signal name="instance">
+ <signal name="instantiate">
<param index="0" name="files" type="PackedStringArray" />
<description>
</description>
diff --git a/doc/classes/Font.xml b/doc/classes/Font.xml
index 6a42b62bcf..761e75339a 100644
--- a/doc/classes/Font.xml
+++ b/doc/classes/Font.xml
@@ -161,6 +161,12 @@
Returns font family name.
</description>
</method>
+ <method name="get_font_stretch" qualifiers="const">
+ <return type="int" />
+ <description>
+ Returns font stretch amount, compared to a normal width. A percentage value between [code]50%[/code] and [code]200%[/code].
+ </description>
+ </method>
<method name="get_font_style" qualifiers="const">
<return type="int" enum="TextServer.FontStyle" />
<description>
@@ -173,6 +179,12 @@
Returns font style name.
</description>
</method>
+ <method name="get_font_weight" qualifiers="const">
+ <return type="int" />
+ <description>
+ Returns weight (boldness) of the font. A value in the [code]100...999[/code] range, normal font weight is [code]400[/code], bold font weight is [code]700[/code].
+ </description>
+ </method>
<method name="get_height" qualifiers="const">
<return type="float" />
<param index="0" name="font_size" type="int" default="16" />
diff --git a/doc/classes/FontFile.xml b/doc/classes/FontFile.xml
index 271f6a13e0..69a7627774 100644
--- a/doc/classes/FontFile.xml
+++ b/doc/classes/FontFile.xml
@@ -542,6 +542,9 @@
</method>
</methods>
<members>
+ <member name="allow_system_fallback" type="bool" setter="set_allow_system_fallback" getter="is_allow_system_fallback" default="true">
+ If set to [code]true[/code], system fonts can be automatically used as fallbacks.
+ </member>
<member name="antialiasing" type="int" setter="set_antialiasing" getter="get_antialiasing" enum="TextServer.FontAntialiasing" default="1">
Font anti-aliasing mode.
</member>
@@ -557,11 +560,17 @@
<member name="font_name" type="String" setter="set_font_name" getter="get_font_name" default="&quot;&quot;">
Font family name.
</member>
+ <member name="font_stretch" type="int" setter="set_font_stretch" getter="get_font_stretch" default="100">
+ Font stretch amount, compared to a normal width. A percentage value between [code]50%[/code] and [code]200%[/code].
+ </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="font_weight" type="int" setter="set_font_weight" getter="get_font_weight" default="400">
+ Weight (boldness) of the font. A value in the [code]100...999[/code] range, normal font weight is [code]400[/code], bold font weight is [code]700[/code].
+ </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. Used by dynamic fonts only.
+ If set to [code]true[/code], auto-hinting is supported and preferred over font built-in hinting. Used by dynamic fonts only (MSDF fonts don't support 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.
@@ -570,25 +579,27 @@
Font hinting mode. Used by dynamic fonts only.
</member>
<member name="msdf_pixel_range" type="int" setter="set_msdf_pixel_range" getter="get_msdf_pixel_range" default="16">
- The width of the range around the shape between the minimum and maximum representable signed distance.
+ The width of the range around the shape between the minimum and maximum representable signed distance. If using font outlines, [member msdf_pixel_range] must be set to at least [i]twice[/i] the size of the largest font outline. The default [member msdf_pixel_range] value of [code]16[/code] allows outline sizes up to [code]8[/code] to look correct.
</member>
<member name="msdf_size" type="int" setter="set_msdf_size" getter="get_msdf_size" default="48">
- Source font size used to generate MSDF textures.
+ Source font size used to generate MSDF textures. Higher values allow for more precision, but are slower to render and require more memory. Only increase this value if you notice a visible lack of precision in glyph rendering.
</member>
<member name="multichannel_signed_distance_field" type="bool" setter="set_multichannel_signed_distance_field" getter="is_multichannel_signed_distance_field" default="false">
- If set to [code]true[/code], glyphs of all sizes are rendered using single multichannel signed distance field generated from the dynamic font vector data.
+ If set to [code]true[/code], glyphs of all sizes are rendered using single multichannel signed distance field (MSDF) generated from the dynamic font vector data. 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). As a downside, font hinting is not available with MSDF. The lack of font hinting may result in less crisp and less readable fonts at small sizes.
+ [b]Note:[/b] If using font outlines, [member msdf_pixel_range] must be set to at least [i]twice[/i] the size of the largest font outline.
+ [b]Note:[/b] MSDF font rendering does not render glyphs with overlapping shapes correctly. Overlapping shapes are not valid per the OpenType standard, but are still commonly found in many font files, especially those converted by Google Fonts. To avoid issues with overlapping glyphs, consider downloading the font file directly from the type foundry instead of relying on Google Fonts.
</member>
<member name="opentype_feature_overrides" type="Dictionary" setter="set_opentype_feature_overrides" getter="get_opentype_feature_overrides" default="{}">
Font OpenType feature set override.
</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. Used by dynamic fonts only.
+ Font oversampling factor. If set to [code]0.0[/code], the global oversampling factor is used instead. Used by dynamic fonts only (MSDF fonts ignore oversampling).
</member>
<member name="style_name" type="String" setter="set_font_style_name" getter="get_font_style_name" default="&quot;&quot;">
Font style name.
</member>
<member name="subpixel_positioning" type="int" setter="set_subpixel_positioning" getter="get_subpixel_positioning" enum="TextServer.SubpixelPositioning" default="1">
- Font glyph subpixel 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.
+ Font glyph subpixel positioning mode. Subpixel positioning provides shaper text and better kerning for smaller font sizes, at the cost of higher memory usage and lower 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/NativeExtension.xml b/doc/classes/GDExtension.xml
index 50f976ca6f..9791290bd9 100644
--- a/doc/classes/NativeExtension.xml
+++ b/doc/classes/GDExtension.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="NativeExtension" inherits="Resource" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+<class name="GDExtension" inherits="Resource" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
</brief_description>
<description>
@@ -13,13 +13,13 @@
</description>
</method>
<method name="get_minimum_library_initialization_level" qualifiers="const">
- <return type="int" enum="NativeExtension.InitializationLevel" />
+ <return type="int" enum="GDExtension.InitializationLevel" />
<description>
</description>
</method>
<method name="initialize_library">
<return type="void" />
- <param index="0" name="level" type="int" enum="NativeExtension.InitializationLevel" />
+ <param index="0" name="level" type="int" enum="GDExtension.InitializationLevel" />
<description>
</description>
</method>
diff --git a/doc/classes/NativeExtensionManager.xml b/doc/classes/GDExtensionManager.xml
index 7d6eefa94f..f682d800c6 100644
--- a/doc/classes/NativeExtensionManager.xml
+++ b/doc/classes/GDExtensionManager.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="NativeExtensionManager" inherits="Object" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+<class name="GDExtensionManager" inherits="Object" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
</brief_description>
<description>
@@ -8,7 +8,7 @@
</tutorials>
<methods>
<method name="get_extension">
- <return type="NativeExtension" />
+ <return type="GDExtension" />
<param index="0" name="path" type="String" />
<description>
</description>
@@ -25,19 +25,19 @@
</description>
</method>
<method name="load_extension">
- <return type="int" enum="NativeExtensionManager.LoadStatus" />
+ <return type="int" enum="GDExtensionManager.LoadStatus" />
<param index="0" name="path" type="String" />
<description>
</description>
</method>
<method name="reload_extension">
- <return type="int" enum="NativeExtensionManager.LoadStatus" />
+ <return type="int" enum="GDExtensionManager.LoadStatus" />
<param index="0" name="path" type="String" />
<description>
</description>
</method>
<method name="unload_extension">
- <return type="int" enum="NativeExtensionManager.LoadStatus" />
+ <return type="int" enum="GDExtensionManager.LoadStatus" />
<param index="0" name="path" type="String" />
<description>
</description>
diff --git a/doc/classes/GeometryInstance3D.xml b/doc/classes/GeometryInstance3D.xml
index 86d52ae9be..1ae4718536 100644
--- a/doc/classes/GeometryInstance3D.xml
+++ b/doc/classes/GeometryInstance3D.xml
@@ -13,13 +13,7 @@
<return type="Variant" />
<param index="0" name="name" type="StringName" />
<description>
- </description>
- </method>
- <method name="set_custom_aabb">
- <return type="void" />
- <param index="0" name="aabb" type="AABB" />
- <description>
- Overrides the bounding box of this node with a custom one. To remove it, set an [AABB] with all fields set to zero.
+ Get the value of a shader parameter as set on this instance.
</description>
</method>
<method name="set_instance_shader_parameter">
@@ -27,6 +21,7 @@
<param index="0" name="name" type="StringName" />
<param index="1" name="value" type="Variant" />
<description>
+ Set the value of a shader parameter for this instance only.
</description>
</method>
</methods>
@@ -34,6 +29,9 @@
<member name="cast_shadow" type="int" setter="set_cast_shadows_setting" getter="get_cast_shadows_setting" enum="GeometryInstance3D.ShadowCastingSetting" default="1">
The selected shadow casting flag. See [enum ShadowCastingSetting] for possible values.
</member>
+ <member name="custom_aabb" type="AABB" setter="set_custom_aabb" getter="get_custom_aabb" default="AABB(0, 0, 0, 0, 0, 0)">
+ Overrides the bounding box of this node with a custom one. This can be used to avoid the expensive [AABB] recalculation that happens when a skeleton is used with a [MeshInstance3D] or to have fine control over the [MeshInstance3D]'s bounding box. To remove this, set value to an [AABB] with all fields set to zero.
+ </member>
<member name="extra_cull_margin" type="float" setter="set_extra_cull_margin" getter="get_extra_cull_margin" default="0.0">
The extra distance added to the GeometryInstance3D's bounding box ([AABB]) to increase its cull box.
</member>
@@ -45,8 +43,11 @@
[b]Note:[/b] Lights' bake mode will also affect the global illumination rendering. See [member Light3D.light_bake_mode].
</member>
<member name="ignore_occlusion_culling" type="bool" setter="set_ignore_occlusion_culling" getter="is_ignoring_occlusion_culling" default="false">
+ If [code]true[/code], disables occlusion culling for this instance. Useful for gizmos that must be rendered even when occlusion culling is in use.
</member>
<member name="lod_bias" type="float" setter="set_lod_bias" getter="get_lod_bias" default="1.0">
+ Changes how quickly the mesh transitions to a lower level of detail. A value of 0 will force the mesh to its lowest level of detail, a value of 1 will use the default settings, and larger values will keep the mesh in a higher level of detail at farther distances.
+ Useful for testing level of detail transitions in the editor.
</member>
<member name="material_overlay" type="Material" setter="set_material_overlay" getter="get_material_overlay">
The material overlay for the whole geometry.
diff --git a/doc/classes/GraphEdit.xml b/doc/classes/GraphEdit.xml
index 5050ce7715..ea4e4b53ba 100644
--- a/doc/classes/GraphEdit.xml
+++ b/doc/classes/GraphEdit.xml
@@ -291,7 +291,7 @@
</description>
</signal>
<signal name="connection_drag_started">
- <param index="0" name="from_node" type="String" />
+ <param index="0" name="from_node" type="StringName" />
<param index="1" name="from_port" type="int" />
<param index="2" name="is_output" type="bool" />
<description>
diff --git a/doc/classes/HSlider.xml b/doc/classes/HSlider.xml
index cb0a8b34db..19bb26a1b0 100644
--- a/doc/classes/HSlider.xml
+++ b/doc/classes/HSlider.xml
@@ -29,6 +29,7 @@
The background of the area to the left of the grabber.
</theme_item>
<theme_item name="grabber_area_highlight" data_type="style" type="StyleBox">
+ The background of the area to the left of the grabber that displays when it's being hovered or focused.
</theme_item>
<theme_item name="slider" data_type="style" type="StyleBox">
The background for the whole slider. Determines the height of the [code]grabber_area[/code].
diff --git a/doc/classes/Image.xml b/doc/classes/Image.xml
index be66b8a7b9..ed1b40488e 100644
--- a/doc/classes/Image.xml
+++ b/doc/classes/Image.xml
@@ -76,8 +76,12 @@
<param index="0" name="mode" type="int" enum="Image.CompressMode" />
<param index="1" name="source" type="int" enum="Image.CompressSource" default="0" />
<param index="2" name="lossy_quality" type="float" default="0.7" />
+ <param index="3" name="astc_format" type="int" enum="Image.ASTCFormat" default="0" />
<description>
- Compresses the image to use less memory. Can not directly access pixel data while the image is compressed. Returns error if the chosen compression mode is not available. See [enum CompressMode] and [enum CompressSource] constants.
+ Compresses the image to use less memory. Can not directly access pixel data while the image is compressed. Returns error if the chosen compression mode is not available.
+ The [param mode] parameter helps to pick the best compression method for DXT and ETC2 formats. It is ignored for ASTC compression.
+ The [param lossy_quality] parameter is optional for compressors that support it.
+ For ASTC compression, the [param astc_format] parameter must be supplied.
</description>
</method>
<method name="compress_from_channels">
@@ -85,7 +89,12 @@
<param index="0" name="mode" type="int" enum="Image.CompressMode" />
<param index="1" name="channels" type="int" enum="Image.UsedChannels" />
<param index="2" name="lossy_quality" type="float" default="0.7" />
+ <param index="3" name="astc_format" type="int" enum="Image.ASTCFormat" default="0" />
<description>
+ Compresses the image to use less memory. Can not directly access pixel data while the image is compressed. Returns error if the chosen compression mode is not available.
+ This is an alternative to [method compress] that lets the user supply the channels used in order for the compressor to pick the best DXT and ETC2 formats. For other formats (non DXT or ETC2), this argument is ignored.
+ The [param lossy_quality] parameter is optional for compressors that support it.
+ For ASTC compression, the [param astc_format] parameter must be supplied.
</description>
</method>
<method name="compute_image_metrics">
@@ -658,7 +667,19 @@
</constant>
<constant name="FORMAT_DXT5_RA_AS_RG" value="34" enum="Format">
</constant>
- <constant name="FORMAT_MAX" value="35" enum="Format">
+ <constant name="FORMAT_ASTC_4x4" value="35" enum="Format">
+ [url=https://en.wikipedia.org/wiki/Adaptive_scalable_texture_compression]Adaptive Scalable Texutre Compression[/url]. This implements the 4x4 (high quality) mode.
+ </constant>
+ <constant name="FORMAT_ASTC_4x4_HDR" value="36" enum="Format">
+ Same format as [constant FORMAT_ASTC_4x4], but with the hint to let the GPU know it is used for HDR.
+ </constant>
+ <constant name="FORMAT_ASTC_8x8" value="37" enum="Format">
+ [url=https://en.wikipedia.org/wiki/Adaptive_scalable_texture_compression]Adaptive Scalable Texutre Compression[/url]. This implements the 8x8 (low quality) mode.
+ </constant>
+ <constant name="FORMAT_ASTC_8x8_HDR" value="38" enum="Format">
+ Same format as [constant FORMAT_ASTC_8x8], but with the hint to let the GPU know it is used for HDR.
+ </constant>
+ <constant name="FORMAT_MAX" value="39" enum="Format">
Represents the size of the [enum Format] enum.
</constant>
<constant name="INTERPOLATE_NEAREST" value="0" enum="Interpolation">
@@ -722,5 +743,11 @@
<constant name="COMPRESS_SOURCE_NORMAL" value="2" enum="CompressSource">
Source texture (before compression) is a normal texture (e.g. it can be compressed into two channels).
</constant>
+ <constant name="ASTC_FORMAT_4x4" value="0" enum="ASTCFormat">
+ Hint to indicate that the high quality 4x4 ASTC compression format should be used.
+ </constant>
+ <constant name="ASTC_FORMAT_8x8" value="1" enum="ASTCFormat">
+ Hint to indicate that the low quality 8x8 ASTC compression format should be used.
+ </constant>
</constants>
</class>
diff --git a/doc/classes/Input.xml b/doc/classes/Input.xml
index d246e64251..be8c8ff83f 100644
--- a/doc/classes/Input.xml
+++ b/doc/classes/Input.xml
@@ -339,7 +339,7 @@
<param index="2" name="strong_magnitude" type="float" />
<param index="3" name="duration" type="float" default="0" />
<description>
- Starts to vibrate the joypad. Joypads usually come with two rumble motors, a strong and a weak one. [param weak_magnitude] is the strength of the weak motor (between 0 and 1) and [param strong_magnitude] is the strength of the strong motor (between 0 and 1). [param duration] is the duration of the effect in seconds (a duration of 0 will try to play the vibration indefinitely).
+ Starts to vibrate the joypad. Joypads usually come with two rumble motors, a strong and a weak one. [param weak_magnitude] is the strength of the weak motor (between 0 and 1) and [param strong_magnitude] is the strength of the strong motor (between 0 and 1). [param duration] is the duration of the effect in seconds (a duration of 0 will try to play the vibration indefinitely). The vibration can be stopped early by calling [method stop_joy_vibration].
[b]Note:[/b] Not every hardware is compatible with long effect durations; it is recommended to restart an effect if it has to be played for more than a few seconds.
</description>
</method>
@@ -347,18 +347,18 @@
<return type="void" />
<param index="0" name="device" type="int" />
<description>
- Stops the vibration of the joypad.
+ Stops the vibration of the joypad started with [method start_joy_vibration].
</description>
</method>
<method name="vibrate_handheld">
<return type="void" />
<param index="0" name="duration_ms" type="int" default="500" />
<description>
- Vibrate handheld devices.
- [b]Note:[/b] This method is implemented on Android, iOS, and Web.
- [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.
+ Vibrate the handheld device for the specified duration in milliseconds.
+ [b]Note:[/b] This method is implemented on Android, iOS, and Web. It has no effect on other platforms.
+ [b]Note:[/b] For Android, [method vibrate_handheld] requires enabling the [code]VIBRATE[/code] permission in the export preset. Otherwise, [method vibrate_handheld] will have no effect.
+ [b]Note:[/b] For iOS, specifying the duration is only supported in iOS 13 and later.
+ [b]Note:[/b] Some web browsers such as Safari and Firefox for Android do not support [method vibrate_handheld].
</description>
</method>
<method name="warp_mouse">
diff --git a/doc/classes/ItemList.xml b/doc/classes/ItemList.xml
index 844f260971..c485d26e0c 100644
--- a/doc/classes/ItemList.xml
+++ b/doc/classes/ItemList.xml
@@ -459,6 +459,7 @@
</theme_item>
<theme_item name="outline_size" data_type="constant" type="int" default="0">
The size of the item text outline.
+ [b]Note:[/b] If using a font with [member FontFile.multichannel_signed_distance_field] enabled, its [member FontFile.msdf_pixel_range] must be set to at least [i]twice[/i] the value of [theme_item outline_size] for outline rendering to look correct. Otherwise, the outline may appear to be cut off earlier than intended.
</theme_item>
<theme_item name="v_separation" data_type="constant" type="int" default="2">
The vertical spacing between items.
diff --git a/doc/classes/Label.xml b/doc/classes/Label.xml
index 615aceac53..1a8cbf0584 100644
--- a/doc/classes/Label.xml
+++ b/doc/classes/Label.xml
@@ -50,6 +50,7 @@
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">
+ A [LabelSettings] resource that can be shared between multiple [Label] nodes. Takes priority over theme properties.
</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.
@@ -100,7 +101,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 text outline.
+ The color 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.
@@ -110,6 +111,7 @@
</theme_item>
<theme_item name="outline_size" data_type="constant" type="int" default="0">
Text outline size.
+ [b]Note:[/b] If using a font with [member FontFile.multichannel_signed_distance_field] enabled, its [member FontFile.msdf_pixel_range] must be set to at least [i]twice[/i] the value of [theme_item outline_size] for outline rendering to look correct. Otherwise, the outline may appear to be cut off earlier than intended.
</theme_item>
<theme_item name="shadow_offset_x" data_type="constant" type="int" default="1">
The horizontal offset of the text's shadow.
diff --git a/doc/classes/LabelSettings.xml b/doc/classes/LabelSettings.xml
index aa972f2cf3..d73cb78295 100644
--- a/doc/classes/LabelSettings.xml
+++ b/doc/classes/LabelSettings.xml
@@ -1,29 +1,40 @@
<?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>
+ Collection of common settings to customize label text.
</brief_description>
<description>
+ [LabelSettings] is a resource that can be assigned to a [Label] node to customize it. It will take priority over the properties defined in theme. The resource can be shared between multiple labels and swapped on the fly, so it's convenient and flexible way to setup text style.
</description>
<tutorials>
</tutorials>
<members>
<member name="font" type="Font" setter="set_font" getter="get_font">
+ [Font] used for the text.
</member>
<member name="font_color" type="Color" setter="set_font_color" getter="get_font_color" default="Color(1, 1, 1, 1)">
+ Color of the text.
</member>
<member name="font_size" type="int" setter="set_font_size" getter="get_font_size" default="16">
+ Size of the text.
</member>
<member name="line_spacing" type="float" setter="set_line_spacing" getter="get_line_spacing" default="3.0">
+ Vertical space between lines when the text is multiline.
</member>
<member name="outline_color" type="Color" setter="set_outline_color" getter="get_outline_color" default="Color(1, 1, 1, 1)">
+ The color of the outline.
</member>
<member name="outline_size" type="int" setter="set_outline_size" getter="get_outline_size" default="0">
+ Text outline size.
</member>
<member name="shadow_color" type="Color" setter="set_shadow_color" getter="get_shadow_color" default="Color(0, 0, 0, 0)">
+ Color of the shadow effect. If alpha is [code]0[/code], no shadow will be drawn.
</member>
<member name="shadow_offset" type="Vector2" setter="set_shadow_offset" getter="get_shadow_offset" default="Vector2(1, 1)">
+ Offset of the shadow effect, in pixels.
</member>
<member name="shadow_size" type="int" setter="set_shadow_size" getter="get_shadow_size" default="1">
+ Size of the shadow effect.
</member>
</members>
</class>
diff --git a/doc/classes/Light2D.xml b/doc/classes/Light2D.xml
index 00815758a1..062d532464 100644
--- a/doc/classes/Light2D.xml
+++ b/doc/classes/Light2D.xml
@@ -4,8 +4,7 @@
Casts light in a 2D environment.
</brief_description>
<description>
- Casts light in a 2D environment. Light is defined by a (usually grayscale) texture, a color, an energy value, a mode (see constants), and various other parameters (range and shadows-related).
- [b]Note:[/b] Light2D can also be used as a mask.
+ Casts light in a 2D environment. A light is defined as a color, an energy value, a mode (see constants), and various other parameters (range and shadows-related).
</description>
<tutorials>
<link title="2D lights and shadows">$DOCS_URL/tutorials/2d/2d_lights_and_shadows.html</link>
@@ -14,12 +13,14 @@
<method name="get_height" qualifiers="const">
<return type="float" />
<description>
+ Returns the light's height, which is used in 2D normal mapping. See [member PointLight2D.height] and [member DirectionalLight2D.height].
</description>
</method>
<method name="set_height">
<return type="void" />
<param index="0" name="height" type="float" />
<description>
+ Sets the light's height, which is used in 2D normal mapping. See [member PointLight2D.height] and [member DirectionalLight2D.height].
</description>
</method>
</methods>
@@ -64,7 +65,7 @@
Shadow filter type. See [enum ShadowFilter] for possible values.
</member>
<member name="shadow_filter_smooth" type="float" setter="set_shadow_smooth" getter="get_shadow_smooth" default="0.0">
- Smoothing value for shadows.
+ Smoothing value for shadows. Higher values will result in softer shadows, at the cost of visible streaks that can appear in shadow rendering. [member shadow_filter_smooth] only has an effect if [member shadow_filter] is [constant SHADOW_FILTER_PCF5] or [constant SHADOW_FILTER_PCF13].
</member>
<member name="shadow_item_cull_mask" type="int" setter="set_item_shadow_cull_mask" getter="get_item_shadow_cull_mask" default="1">
The shadow mask. Used with [LightOccluder2D] to cast shadows. Only occluders with a matching light mask will cast shadows.
@@ -72,13 +73,13 @@
</members>
<constants>
<constant name="SHADOW_FILTER_NONE" value="0" enum="ShadowFilter">
- No filter applies to the shadow map. See [member shadow_filter].
+ No filter applies to the shadow map. This provides hard shadow edges and is the fastest to render. See [member shadow_filter].
</constant>
<constant name="SHADOW_FILTER_PCF5" value="1" enum="ShadowFilter">
- Percentage closer filtering (5 samples) applies to the shadow map. See [member shadow_filter].
+ Percentage closer filtering (5 samples) applies to the shadow map. This is slower compared to hard shadow rendering. See [member shadow_filter].
</constant>
<constant name="SHADOW_FILTER_PCF13" value="2" enum="ShadowFilter">
- Percentage closer filtering (13 samples) applies to the shadow map. See [member shadow_filter].
+ Percentage closer filtering (13 samples) applies to the shadow map. This is the slowest shadow filtereing mode, and should be used sparingly. See [member shadow_filter].
</constant>
<constant name="BLEND_MODE_ADD" value="0" enum="BlendMode">
Adds the value of pixels corresponding to the Light2D to the values of pixels under it. This is the common behavior of a light.
diff --git a/doc/classes/Light3D.xml b/doc/classes/Light3D.xml
index 60e20cd97d..fe7756faaf 100644
--- a/doc/classes/Light3D.xml
+++ b/doc/classes/Light3D.xml
@@ -114,7 +114,7 @@
<member name="shadow_enabled" type="bool" setter="set_shadow" getter="has_shadow" default="false">
If [code]true[/code], the light will cast real-time shadows. This has a significant performance cost. Only enable shadow rendering when it makes a noticeable difference in the scene's appearance, and consider using [member distance_fade_enabled] to hide the light when far away from the [Camera3D].
</member>
- <member name="shadow_normal_bias" type="float" setter="set_param" getter="get_param" default="1.0">
+ <member name="shadow_normal_bias" type="float" setter="set_param" getter="get_param" default="2.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">
diff --git a/doc/classes/LineEdit.xml b/doc/classes/LineEdit.xml
index e57cc68b36..b8383aaed9 100644
--- a/doc/classes/LineEdit.xml
+++ b/doc/classes/LineEdit.xml
@@ -424,6 +424,7 @@
</theme_item>
<theme_item name="outline_size" data_type="constant" type="int" default="0">
The size of the text outline.
+ [b]Note:[/b] If using a font with [member FontFile.multichannel_signed_distance_field] enabled, its [member FontFile.msdf_pixel_range] must be set to at least [i]twice[/i] the value of [theme_item outline_size] for outline rendering to look correct. Otherwise, the outline may appear to be cut off earlier than intended.
</theme_item>
<theme_item name="font" data_type="font" type="Font">
Font used for the text.
diff --git a/doc/classes/LinkButton.xml b/doc/classes/LinkButton.xml
index d7701ea184..b3938999f3 100644
--- a/doc/classes/LinkButton.xml
+++ b/doc/classes/LinkButton.xml
@@ -28,7 +28,23 @@
Base text writing direction.
</member>
<member name="underline" type="int" setter="set_underline_mode" getter="get_underline_mode" enum="LinkButton.UnderlineMode" default="0">
- Determines when to show the underline. See [enum UnderlineMode] for options.
+ The underline mode to use for the text. See [enum LinkButton.UnderlineMode] for the available modes.
+ </member>
+ <member name="uri" type="String" setter="set_uri" getter="get_uri" default="&quot;&quot;">
+ The [url=https://en.wikipedia.org/wiki/Uniform_Resource_Identifier]URI[/url] for this [LinkButton]. If set to a valid URI, pressing the button opens the URI using the operating system's default program for the protocol (via [method OS.shell_open]). HTTP and HTTPS URLs open the default web browser.
+ [b]Examples:[/b]
+ [codeblocks]
+ [gdscript]
+ uri = "https://godotengine.org" # Opens the URL in the default web browser.
+ uri = "C:\SomeFolder" # Opens the file explorer at the given path.
+ uri = "C:\SomeImage.png" # Opens the given image in the default viewing app.
+ [/gdscript]
+ [csharp]
+ Uri = "https://godotengine.org"; // Opens the URL in the default web browser.
+ Uri = "C:\SomeFolder"; // Opens the file explorer at the given path.
+ Uri = "C:\SomeImage.png"; // Opens the given image in the default viewing app.
+ [/csharp]
+ [/codeblocks]
</member>
</members>
<constants>
@@ -60,6 +76,7 @@
</theme_item>
<theme_item name="outline_size" data_type="constant" type="int" default="0">
The size of the text outline.
+ [b]Note:[/b] If using a font with [member FontFile.multichannel_signed_distance_field] enabled, its [member FontFile.msdf_pixel_range] must be set to at least [i]twice[/i] the value of [theme_item outline_size] for outline rendering to look correct. Otherwise, the outline may appear to be cut off earlier than intended.
</theme_item>
<theme_item name="underline_spacing" data_type="constant" type="int" default="2">
The vertical space between the baseline of text and the underline.
diff --git a/doc/classes/MenuBar.xml b/doc/classes/MenuBar.xml
index e8505937ff..79876e56a3 100644
--- a/doc/classes/MenuBar.xml
+++ b/doc/classes/MenuBar.xml
@@ -143,6 +143,7 @@
</theme_item>
<theme_item name="outline_size" data_type="constant" type="int" default="0">
The size of the text outline.
+ [b]Note:[/b] If using a font with [member FontFile.multichannel_signed_distance_field] enabled, its [member FontFile.msdf_pixel_range] must be set to at least [i]twice[/i] the value of [theme_item outline_size] for outline rendering to look correct. Otherwise, the outline may appear to be cut off earlier than intended.
</theme_item>
<theme_item name="font" data_type="font" type="Font">
[Font] of the menu item's text.
diff --git a/doc/classes/MenuButton.xml b/doc/classes/MenuButton.xml
index 4d5d5a011b..3061149570 100644
--- a/doc/classes/MenuButton.xml
+++ b/doc/classes/MenuButton.xml
@@ -75,6 +75,7 @@
</theme_item>
<theme_item name="outline_size" data_type="constant" type="int" default="0">
The size of the text outline.
+ [b]Note:[/b] If using a font with [member FontFile.multichannel_signed_distance_field] enabled, its [member FontFile.msdf_pixel_range] must be set to at least [i]twice[/i] the value of [theme_item outline_size] for outline rendering to look correct. Otherwise, the outline may appear to be cut off earlier than intended.
</theme_item>
<theme_item name="font" data_type="font" type="Font">
[Font] of the [MenuButton]'s text.
diff --git a/doc/classes/Mesh.xml b/doc/classes/Mesh.xml
index 640fa9efec..4d3fb7ed5c 100644
--- a/doc/classes/Mesh.xml
+++ b/doc/classes/Mesh.xml
@@ -97,7 +97,7 @@
</description>
</method>
<method name="create_convex_shape" qualifiers="const">
- <return type="Shape3D" />
+ <return type="ConvexPolygonShape3D" />
<param index="0" name="clean" type="bool" default="true" />
<param index="1" name="simplify" type="bool" default="false" />
<description>
@@ -115,7 +115,7 @@
</description>
</method>
<method name="create_trimesh_shape" qualifiers="const">
- <return type="Shape3D" />
+ <return type="ConcavePolygonShape3D" />
<description>
Calculate a [ConcavePolygonShape3D] from the mesh.
</description>
diff --git a/doc/classes/MeshLibrary.xml b/doc/classes/MeshLibrary.xml
index 85e57dd0f3..7c93ba5dce 100644
--- a/doc/classes/MeshLibrary.xml
+++ b/doc/classes/MeshLibrary.xml
@@ -59,14 +59,21 @@
Returns the item's name.
</description>
</method>
- <method name="get_item_navmesh" qualifiers="const">
+ <method name="get_item_navigation_layers" qualifiers="const">
+ <return type="int" />
+ <param index="0" name="id" type="int" />
+ <description>
+ Returns the item's navigation layers bitmask.
+ </description>
+ </method>
+ <method name="get_item_navigation_mesh" qualifiers="const">
<return type="NavigationMesh" />
<param index="0" name="id" type="int" />
<description>
Returns the item's navigation mesh.
</description>
</method>
- <method name="get_item_navmesh_transform" qualifiers="const">
+ <method name="get_item_navigation_mesh_transform" qualifiers="const">
<return type="Transform3D" />
<param index="0" name="id" type="int" />
<description>
@@ -126,18 +133,26 @@
This name is shown in the editor. It can also be used to look up the item later using [method find_item_by_name].
</description>
</method>
- <method name="set_item_navmesh">
+ <method name="set_item_navigation_layers">
+ <return type="void" />
+ <param index="0" name="id" type="int" />
+ <param index="1" name="navigation_layers" type="int" />
+ <description>
+ Sets the item's navigation layers bitmask.
+ </description>
+ </method>
+ <method name="set_item_navigation_mesh">
<return type="void" />
<param index="0" name="id" type="int" />
- <param index="1" name="navmesh" type="NavigationMesh" />
+ <param index="1" name="navigation_mesh" type="NavigationMesh" />
<description>
Sets the item's navigation mesh.
</description>
</method>
- <method name="set_item_navmesh_transform">
+ <method name="set_item_navigation_mesh_transform">
<return type="void" />
<param index="0" name="id" type="int" />
- <param index="1" name="navmesh" type="Transform3D" />
+ <param index="1" name="navigation_mesh" type="Transform3D" />
<description>
Sets the transform to apply to the item's navigation mesh.
</description>
diff --git a/doc/classes/MissingNode.xml b/doc/classes/MissingNode.xml
index b5aa02cfd6..ac54329313 100644
--- a/doc/classes/MissingNode.xml
+++ b/doc/classes/MissingNode.xml
@@ -4,7 +4,7 @@
This is an internal editor class intended for keeping data of nodes of unknown type.
</brief_description>
<description>
- This is an internal editor class intended for keeping data of nodes of unknown type (most likely this type was supplied by an extension that is no longer loaded). It can´t be manually instantiated or placed in the scene. Ignore it if you don't know what it is.
+ This is an internal editor class intended for keeping data of nodes of unknown type (most likely this type was supplied by an extension that is no longer loaded). It can't be manually instantiated or placed in the scene. Ignore it if you don't know what it is.
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/MissingResource.xml b/doc/classes/MissingResource.xml
index eede6350d8..e5a6c4d064 100644
--- a/doc/classes/MissingResource.xml
+++ b/doc/classes/MissingResource.xml
@@ -4,7 +4,7 @@
This is an internal editor class intended for keeping data of resources of unknown type.
</brief_description>
<description>
- This is an internal editor class intended for keeping data of resources of unknown type (most likely this type was supplied by an extension that is no longer loaded). It can´t be manually instantiated or placed in the scene. Ignore it if you don't know what it is.
+ This is an internal editor class intended for keeping data of resources of unknown type (most likely this type was supplied by an extension that is no longer loaded). It can't be manually instantiated or placed in the scene. Ignore it if you don't know what it is.
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/NavigationAgent2D.xml b/doc/classes/NavigationAgent2D.xml
index 8cf7824ff7..31d347d76c 100644
--- a/doc/classes/NavigationAgent2D.xml
+++ b/doc/classes/NavigationAgent2D.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="NavigationAgent2D" inherits="Node" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+<class name="NavigationAgent2D" inherits="Node" is_experimental="true" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
2D Agent used in navigation for collision avoidance.
</brief_description>
@@ -16,24 +16,30 @@
Returns the distance to the target location, using the agent's global position. The user must set [member target_location] in order for this to be accurate.
</description>
</method>
- <method name="get_final_location">
- <return type="Vector2" />
- <description>
- Returns the reachable final location in global coordinates. This can change if the navigation path is altered in any way. Because of this, it would be best to check this each frame.
- </description>
- </method>
- <method name="get_nav_path" qualifiers="const">
+ <method name="get_current_navigation_path" qualifiers="const">
<return type="PackedVector2Array" />
<description>
Returns this agent's current path from start to finish in global coordinates. The path only updates when the target location is changed or the agent requires a repath. The path array is not intended to be used in direct path movement as the agent has its own internal path logic that would get corrupted by changing the path array manually. Use the intended [method get_next_location] once every physics frame to receive the next path point for the agents movement as this function also updates the internal path logic.
</description>
</method>
- <method name="get_nav_path_index" qualifiers="const">
+ <method name="get_current_navigation_path_index" qualifiers="const">
<return type="int" />
<description>
Returns which index the agent is currently on in the navigation path's [PackedVector2Array].
</description>
</method>
+ <method name="get_current_navigation_result" qualifiers="const">
+ <return type="NavigationPathQueryResult2D" />
+ <description>
+ Returns the path query result for the path the agent is currently following.
+ </description>
+ </method>
+ <method name="get_final_location">
+ <return type="Vector2" />
+ <description>
+ Returns the reachable final location in global coordinates. This can change if the navigation path is altered in any way. Because of this, it would be best to check this each frame.
+ </description>
+ </method>
<method name="get_navigation_layer_value" qualifiers="const">
<return type="bool" />
<param index="0" name="layer_number" type="int" />
@@ -122,6 +128,9 @@
<member name="path_max_distance" type="float" setter="set_path_max_distance" getter="get_path_max_distance" default="3.0">
The maximum distance the agent is allowed away from the ideal path to the final location. This can happen due to trying to avoid collisions. When the maximum distance is exceeded, it recalculates the ideal path.
</member>
+ <member name="path_metadata_flags" type="int" setter="set_path_metadata_flags" getter="get_path_metadata_flags" enum="NavigationPathQueryParameters2D.PathMetadataFlags" default="7">
+ Additional information to return with the navigation path.
+ </member>
<member name="radius" type="float" setter="set_radius" getter="get_radius" default="10.0">
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_distance]).
Does not affect normal pathfinding. To change an actor's pathfinding radius bake [NavigationMesh] resources with a different [member NavigationMesh.agent_radius] property and use different navigation maps for each actor size.
@@ -137,6 +146,17 @@
</member>
</members>
<signals>
+ <signal name="link_reached">
+ <param index="0" name="details" type="Dictionary" />
+ <description>
+ Notifies when a navigation link has been reached.
+ The details dictionary may contain the following keys depending on the value of [member path_metadata_flags]:
+ - [code]location[/code]: The start location of the link that was reached.
+ - [code]type[/code]: Always [constant NavigationPathQueryResult2D.PATH_SEGMENT_TYPE_LINK].
+ - [code]rid[/code]: The [RID] of the link.
+ - [code]owner[/code]: The object which manages the link (usually [NavigationLink2D]).
+ </description>
+ </signal>
<signal name="navigation_finished">
<description>
Notifies when the final location is reached.
@@ -158,5 +178,16 @@
Notifies when the collision avoidance velocity is calculated. Emitted by [method set_velocity]. Only emitted when [member avoidance_enabled] is true.
</description>
</signal>
+ <signal name="waypoint_reached">
+ <param index="0" name="details" type="Dictionary" />
+ <description>
+ Notifies when a waypoint along the path has been reached.
+ The details dictionary may contain the following keys depending on the value of [member path_metadata_flags]:
+ - [code]location[/code]: The location of the waypoint that was reached.
+ - [code]type[/code]: The type of navigation primitive (region or link) that contains this waypoint.
+ - [code]rid[/code]: The [RID] of the containing navigation primitive (region or link).
+ - [code]owner[/code]: The object which manages the containing navigation primitive (region or link).
+ </description>
+ </signal>
</signals>
</class>
diff --git a/doc/classes/NavigationAgent3D.xml b/doc/classes/NavigationAgent3D.xml
index 44c17647f7..c3f4809b5e 100644
--- a/doc/classes/NavigationAgent3D.xml
+++ b/doc/classes/NavigationAgent3D.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="NavigationAgent3D" inherits="Node" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+<class name="NavigationAgent3D" inherits="Node" is_experimental="true" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
3D Agent used in navigation for collision avoidance.
</brief_description>
@@ -16,24 +16,30 @@
Returns the distance to the target location, using the agent's global position. The user must set [member target_location] in order for this to be accurate.
</description>
</method>
- <method name="get_final_location">
- <return type="Vector3" />
- <description>
- Returns the reachable final location in global coordinates. This can change if the navigation path is altered in any way. Because of this, it would be best to check this each frame.
- </description>
- </method>
- <method name="get_nav_path" qualifiers="const">
+ <method name="get_current_navigation_path" qualifiers="const">
<return type="PackedVector3Array" />
<description>
Returns this agent's current path from start to finish in global coordinates. The path only updates when the target location is changed or the agent requires a repath. The path array is not intended to be used in direct path movement as the agent has its own internal path logic that would get corrupted by changing the path array manually. Use the intended [method get_next_location] once every physics frame to receive the next path point for the agents movement as this function also updates the internal path logic.
</description>
</method>
- <method name="get_nav_path_index" qualifiers="const">
+ <method name="get_current_navigation_path_index" qualifiers="const">
<return type="int" />
<description>
Returns which index the agent is currently on in the navigation path's [PackedVector3Array].
</description>
</method>
+ <method name="get_current_navigation_result" qualifiers="const">
+ <return type="NavigationPathQueryResult3D" />
+ <description>
+ Returns the path query result for the path the agent is currently following.
+ </description>
+ </method>
+ <method name="get_final_location">
+ <return type="Vector3" />
+ <description>
+ Returns the reachable final location in global coordinates. This can change if the navigation path is altered in any way. Because of this, it would be best to check this each frame.
+ </description>
+ </method>
<method name="get_navigation_layer_value" qualifiers="const">
<return type="bool" />
<param index="0" name="layer_number" type="int" />
@@ -128,6 +134,9 @@
<member name="path_max_distance" type="float" setter="set_path_max_distance" getter="get_path_max_distance" default="3.0">
The maximum distance the agent is allowed away from the ideal path to the final location. This can happen due to trying to avoid collisions. When the maximum distance is exceeded, it recalculates the ideal path.
</member>
+ <member name="path_metadata_flags" type="int" setter="set_path_metadata_flags" getter="get_path_metadata_flags" enum="NavigationPathQueryParameters3D.PathMetadataFlags" default="7">
+ Additional information to return with the navigation path.
+ </member>
<member name="radius" type="float" setter="set_radius" getter="get_radius" default="1.0">
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_distance]).
Does not affect normal pathfinding. To change an actor's pathfinding radius bake [NavigationMesh] resources with a different [member NavigationMesh.agent_radius] property and use different navigation maps for each actor size.
@@ -143,6 +152,17 @@
</member>
</members>
<signals>
+ <signal name="link_reached">
+ <param index="0" name="details" type="Dictionary" />
+ <description>
+ Notifies when a navigation link has been reached.
+ The details dictionary may contain the following keys depending on the value of [member path_metadata_flags]:
+ - [code]location[/code]: The start location of the link that was reached.
+ - [code]type[/code]: Always [constant NavigationPathQueryResult3D.PATH_SEGMENT_TYPE_LINK].
+ - [code]rid[/code]: The [RID] of the link.
+ - [code]owner[/code]: The object which manages the link (usually [NavigationLink3D]).
+ </description>
+ </signal>
<signal name="navigation_finished">
<description>
Notifies when the final location is reached.
@@ -164,5 +184,16 @@
Notifies when the collision avoidance velocity is calculated. Emitted by [method set_velocity]. Only emitted when [member avoidance_enabled] is true.
</description>
</signal>
+ <signal name="waypoint_reached">
+ <param index="0" name="details" type="Dictionary" />
+ <description>
+ Notifies when a waypoint along the path has been reached.
+ The details dictionary may contain the following keys depending on the value of [member path_metadata_flags]:
+ - [code]location[/code]: The location of the waypoint that was reached.
+ - [code]type[/code]: The type of navigation primitive (region or link) that contains this waypoint.
+ - [code]rid[/code]: The [RID] of the containing navigation primitive (region or link).
+ - [code]owner[/code]: The object which manages the containing navigation primitive (region or link).
+ </description>
+ </signal>
</signals>
</class>
diff --git a/doc/classes/NavigationLink2D.xml b/doc/classes/NavigationLink2D.xml
index 1e086fb730..9d75694360 100644
--- a/doc/classes/NavigationLink2D.xml
+++ b/doc/classes/NavigationLink2D.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="NavigationLink2D" inherits="Node2D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+<class name="NavigationLink2D" inherits="Node2D" is_experimental="true" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
Creates a link between two locations that [NavigationServer2D] can route agents through.
</brief_description>
@@ -38,7 +38,7 @@
The distance the link will search is controlled by [method NavigationServer2D.map_set_link_connection_radius].
</member>
<member name="enter_cost" type="float" setter="set_enter_cost" getter="get_enter_cost" default="0.0">
- When pathfinding enters this link from another regions navmesh the [code]enter_cost[/code] value is added to the path distance for determining the shortest path.
+ When pathfinding enters this link from another regions navigation mesh the [code]enter_cost[/code] value is added to the path distance for determining the shortest path.
</member>
<member name="navigation_layers" type="int" setter="set_navigation_layers" getter="get_navigation_layers" default="1">
A bitfield determining all navigation layers the link belongs to. These navigation layers will be checked when requesting a path with [method NavigationServer2D.map_get_path].
diff --git a/doc/classes/NavigationLink3D.xml b/doc/classes/NavigationLink3D.xml
index 4d5d81bec5..730c43c5a8 100644
--- a/doc/classes/NavigationLink3D.xml
+++ b/doc/classes/NavigationLink3D.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="NavigationLink3D" inherits="Node3D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+<class name="NavigationLink3D" inherits="Node3D" is_experimental="true" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
Creates a link between two locations that [NavigationServer3D] can route agents through.
</brief_description>
@@ -38,7 +38,7 @@
The distance the link will search is controlled by [method NavigationServer3D.map_set_link_connection_radius].
</member>
<member name="enter_cost" type="float" setter="set_enter_cost" getter="get_enter_cost" default="0.0">
- When pathfinding enters this link from another regions navmesh the [code]enter_cost[/code] value is added to the path distance for determining the shortest path.
+ When pathfinding enters this link from another regions navigation mesh the [code]enter_cost[/code] value is added to the path distance for determining the shortest path.
</member>
<member name="navigation_layers" type="int" setter="set_navigation_layers" getter="get_navigation_layers" default="1">
A bitfield determining all navigation layers the link belongs to. These navigation layers will be checked when requesting a path with [method NavigationServer3D.map_get_path].
diff --git a/doc/classes/NavigationMesh.xml b/doc/classes/NavigationMesh.xml
index c86bc47e04..ff898551d4 100644
--- a/doc/classes/NavigationMesh.xml
+++ b/doc/classes/NavigationMesh.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="NavigationMesh" inherits="Resource" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+<class name="NavigationMesh" inherits="Resource" is_experimental="true" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
A mesh to approximate the walkable areas and obstacles.
</brief_description>
@@ -133,13 +133,10 @@
<member name="geometry_source_geometry_mode" type="int" setter="set_source_geometry_mode" getter="get_source_geometry_mode" enum="NavigationMesh.SourceGeometryMode" default="0">
The source of the geometry used when baking. See [enum SourceGeometryMode] for possible values.
</member>
- <member name="geometry_source_group_name" type="StringName" setter="set_source_group_name" getter="get_source_group_name" default="&amp;&quot;navmesh&quot;">
+ <member name="geometry_source_group_name" type="StringName" setter="set_source_group_name" getter="get_source_group_name" default="&amp;&quot;navigation_mesh_source_group&quot;">
The name of the group to scan for geometry.
Only used when [member geometry_source_geometry_mode] is [constant SOURCE_GEOMETRY_GROUPS_WITH_CHILDREN] or [constant SOURCE_GEOMETRY_GROUPS_EXPLICIT].
</member>
- <member name="polygon_verts_per_poly" type="float" setter="set_verts_per_poly" getter="get_verts_per_poly" default="6.0">
- The maximum number of vertices allowed for polygons generated during the contour to polygon conversion process.
- </member>
<member name="region_merge_size" type="float" setter="set_region_merge_size" getter="get_region_merge_size" default="20.0">
Any regions with a size smaller than this will be merged with larger regions if possible.
[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.
@@ -151,6 +148,9 @@
<member name="sample_partition_type" type="int" setter="set_sample_partition_type" getter="get_sample_partition_type" enum="NavigationMesh.SamplePartitionType" default="0">
Partitioning algorithm for creating the navigation mesh polys. See [enum SamplePartitionType] for possible values.
</member>
+ <member name="vertices_per_polygon" type="float" setter="set_vertices_per_polygon" getter="get_vertices_per_polygon" default="6.0">
+ The maximum number of vertices allowed for polygons generated during the contour to polygon conversion process.
+ </member>
</members>
<constants>
<constant name="SAMPLE_PARTITION_WATERSHED" value="0" enum="SamplePartitionType">
@@ -177,8 +177,8 @@
<constant name="PARSED_GEOMETRY_MAX" value="3" enum="ParsedGeometryType">
Represents the size of the [enum ParsedGeometryType] enum.
</constant>
- <constant name="SOURCE_GEOMETRY_NAVMESH_CHILDREN" value="0" enum="SourceGeometryMode">
- Scans the child nodes of [NavigationRegion3D] recursively for geometry.
+ <constant name="SOURCE_GEOMETRY_ROOT_NODE_CHILDREN" value="0" enum="SourceGeometryMode">
+ Scans the child nodes of the root node recursively for geometry.
</constant>
<constant name="SOURCE_GEOMETRY_GROUPS_WITH_CHILDREN" value="1" enum="SourceGeometryMode">
Scans nodes in a group and their child nodes recursively for geometry. The group is specified by [member geometry_source_group_name].
diff --git a/doc/classes/NavigationMeshGenerator.xml b/doc/classes/NavigationMeshGenerator.xml
index 4c337db90f..15d149a229 100644
--- a/doc/classes/NavigationMeshGenerator.xml
+++ b/doc/classes/NavigationMeshGenerator.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="NavigationMeshGenerator" inherits="Object" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+<class name="NavigationMeshGenerator" inherits="Object" is_experimental="true" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
Helper class for creating and clearing navigation meshes.
</brief_description>
@@ -15,17 +15,17 @@
<methods>
<method name="bake">
<return type="void" />
- <param index="0" name="nav_mesh" type="NavigationMesh" />
+ <param index="0" name="navigation_mesh" type="NavigationMesh" />
<param index="1" name="root_node" type="Node" />
<description>
- Bakes navigation data to the provided [param nav_mesh] by parsing child nodes under the provided [param root_node] or a specific group of nodes for potential source geometry. The parse behavior can be controlled with the [member NavigationMesh.geometry_parsed_geometry_type] and [member NavigationMesh.geometry_source_geometry_mode] properties on the [NavigationMesh] resource.
+ Bakes navigation data to the provided [param navigation_mesh] by parsing child nodes under the provided [param root_node] or a specific group of nodes for potential source geometry. The parse behavior can be controlled with the [member NavigationMesh.geometry_parsed_geometry_type] and [member NavigationMesh.geometry_source_geometry_mode] properties on the [NavigationMesh] resource.
</description>
</method>
<method name="clear">
<return type="void" />
- <param index="0" name="nav_mesh" type="NavigationMesh" />
+ <param index="0" name="navigation_mesh" type="NavigationMesh" />
<description>
- Removes all polygons and vertices from the provided [param nav_mesh] resource.
+ Removes all polygons and vertices from the provided [param navigation_mesh] resource.
</description>
</method>
</methods>
diff --git a/doc/classes/NavigationObstacle2D.xml b/doc/classes/NavigationObstacle2D.xml
index 68d9691ccf..ce0f05ad28 100644
--- a/doc/classes/NavigationObstacle2D.xml
+++ b/doc/classes/NavigationObstacle2D.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="NavigationObstacle2D" inherits="Node" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+<class name="NavigationObstacle2D" inherits="Node" is_experimental="true" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
2D Obstacle used in navigation for collision avoidance.
</brief_description>
diff --git a/doc/classes/NavigationObstacle3D.xml b/doc/classes/NavigationObstacle3D.xml
index 90eb55887f..78bbb788d9 100644
--- a/doc/classes/NavigationObstacle3D.xml
+++ b/doc/classes/NavigationObstacle3D.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="NavigationObstacle3D" inherits="Node" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+<class name="NavigationObstacle3D" inherits="Node" is_experimental="true" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
3D Obstacle used in navigation for collision avoidance.
</brief_description>
diff --git a/doc/classes/NavigationPathQueryParameters2D.xml b/doc/classes/NavigationPathQueryParameters2D.xml
index 397ca8b713..511b2e7a8c 100644
--- a/doc/classes/NavigationPathQueryParameters2D.xml
+++ b/doc/classes/NavigationPathQueryParameters2D.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="NavigationPathQueryParameters2D" inherits="RefCounted" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+<class name="NavigationPathQueryParameters2D" inherits="RefCounted" is_experimental="true" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
Parameters to be sent to a 2D navigation path query.
</brief_description>
@@ -12,6 +12,9 @@
<member name="map" type="RID" setter="set_map" getter="get_map">
The navigation [code]map[/code] [RID] used in the path query.
</member>
+ <member name="metadata_flags" type="int" setter="set_metadata_flags" getter="get_metadata_flags" enum="NavigationPathQueryParameters2D.PathMetadataFlags" default="7">
+ Additional information to include with the navigation path.
+ </member>
<member name="navigation_layers" type="int" setter="set_navigation_layers" getter="get_navigation_layers" default="1">
The navigation layers the query will use (as a bitmask).
</member>
@@ -33,10 +36,25 @@
The path query uses the default A* pathfinding algorithm.
</constant>
<constant name="PATH_POSTPROCESSING_CORRIDORFUNNEL" value="0" enum="PathPostProcessing">
- Applies a funnel algorithm to the raw path corridor found by the pathfinding algorithm. This will result in the shortest path possible inside the path corridor. This postprocessing very much depends on the navmesh polygon layout and the created corridor. Especially tile- or gridbased layouts can face artificial corners with diagonal movement due to a jagged path corridor imposed by the cell shapes.
+ Applies a funnel algorithm to the raw path corridor found by the pathfinding algorithm. This will result in the shortest path possible inside the path corridor. This postprocessing very much depends on the navigation mesh polygon layout and the created corridor. Especially tile- or gridbased layouts can face artificial corners with diagonal movement due to a jagged path corridor imposed by the cell shapes.
</constant>
<constant name="PATH_POSTPROCESSING_EDGECENTERED" value="1" enum="PathPostProcessing">
- Centers every path position in the middle of the traveled navmesh polygon edge. This creates better paths for tile- or gridbased layouts that restrict the movement to the cells center.
+ Centers every path position in the middle of the traveled navigation mesh polygon edge. This creates better paths for tile- or gridbased layouts that restrict the movement to the cells center.
+ </constant>
+ <constant name="PATH_METADATA_INCLUDE_NONE" value="0" enum="PathMetadataFlags" is_bitfield="true">
+ Don't include any additional metadata about the returned path.
+ </constant>
+ <constant name="PATH_METADATA_INCLUDE_TYPES" value="1" enum="PathMetadataFlags" is_bitfield="true">
+ Include the type of navigation primitive (region or link) that each point of the path goes through.
+ </constant>
+ <constant name="PATH_METADATA_INCLUDE_RIDS" value="2" enum="PathMetadataFlags" is_bitfield="true">
+ Include the [RID]s of the regions and links that each point of the path goes through.
+ </constant>
+ <constant name="PATH_METADATA_INCLUDE_OWNERS" value="4" enum="PathMetadataFlags" is_bitfield="true">
+ Include the [code]ObjectID[/code]s of the [Object]s which manage the regions and links each point of the path goes through.
+ </constant>
+ <constant name="PATH_METADATA_INCLUDE_ALL" value="7" enum="PathMetadataFlags" is_bitfield="true">
+ Include all available metadata about the returned path.
</constant>
</constants>
</class>
diff --git a/doc/classes/NavigationPathQueryParameters3D.xml b/doc/classes/NavigationPathQueryParameters3D.xml
index 29faa5561b..b5031f60f2 100644
--- a/doc/classes/NavigationPathQueryParameters3D.xml
+++ b/doc/classes/NavigationPathQueryParameters3D.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="NavigationPathQueryParameters3D" inherits="RefCounted" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+<class name="NavigationPathQueryParameters3D" inherits="RefCounted" is_experimental="true" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
Parameters to be sent to a 3D navigation path query.
</brief_description>
@@ -12,6 +12,9 @@
<member name="map" type="RID" setter="set_map" getter="get_map">
The navigation [code]map[/code] [RID] used in the path query.
</member>
+ <member name="metadata_flags" type="int" setter="set_metadata_flags" getter="get_metadata_flags" enum="NavigationPathQueryParameters3D.PathMetadataFlags" default="7">
+ Additional information to include with the navigation path.
+ </member>
<member name="navigation_layers" type="int" setter="set_navigation_layers" getter="get_navigation_layers" default="1">
The navigation layers the query will use (as a bitmask).
</member>
@@ -33,10 +36,25 @@
The path query uses the default A* pathfinding algorithm.
</constant>
<constant name="PATH_POSTPROCESSING_CORRIDORFUNNEL" value="0" enum="PathPostProcessing">
- Applies a funnel algorithm to the raw path corridor found by the pathfinding algorithm. This will result in the shortest path possible inside the path corridor. This postprocessing very much depends on the navmesh polygon layout and the created corridor. Especially tile- or gridbased layouts can face artificial corners with diagonal movement due to a jagged path corridor imposed by the cell shapes.
+ Applies a funnel algorithm to the raw path corridor found by the pathfinding algorithm. This will result in the shortest path possible inside the path corridor. This postprocessing very much depends on the navigation mesh polygon layout and the created corridor. Especially tile- or gridbased layouts can face artificial corners with diagonal movement due to a jagged path corridor imposed by the cell shapes.
</constant>
<constant name="PATH_POSTPROCESSING_EDGECENTERED" value="1" enum="PathPostProcessing">
- Centers every path position in the middle of the traveled navmesh polygon edge. This creates better paths for tile- or gridbased layouts that restrict the movement to the cells center.
+ Centers every path position in the middle of the traveled navigation mesh polygon edge. This creates better paths for tile- or gridbased layouts that restrict the movement to the cells center.
+ </constant>
+ <constant name="PATH_METADATA_INCLUDE_NONE" value="0" enum="PathMetadataFlags" is_bitfield="true">
+ Don't include any additional metadata about the returned path.
+ </constant>
+ <constant name="PATH_METADATA_INCLUDE_TYPES" value="1" enum="PathMetadataFlags" is_bitfield="true">
+ Include the type of navigation primitive (region or link) that each point of the path goes through.
+ </constant>
+ <constant name="PATH_METADATA_INCLUDE_RIDS" value="2" enum="PathMetadataFlags" is_bitfield="true">
+ Include the [RID]s of the regions and links that each point of the path goes through.
+ </constant>
+ <constant name="PATH_METADATA_INCLUDE_OWNERS" value="4" enum="PathMetadataFlags" is_bitfield="true">
+ Include the [code]ObjectID[/code]s of the [Object]s which manage the regions and links each point of the path goes through.
+ </constant>
+ <constant name="PATH_METADATA_INCLUDE_ALL" value="7" enum="PathMetadataFlags" is_bitfield="true">
+ Include all available metadata about the returned path.
</constant>
</constants>
</class>
diff --git a/doc/classes/NavigationPathQueryResult2D.xml b/doc/classes/NavigationPathQueryResult2D.xml
index 95b90e9383..75f7cc47aa 100644
--- a/doc/classes/NavigationPathQueryResult2D.xml
+++ b/doc/classes/NavigationPathQueryResult2D.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="NavigationPathQueryResult2D" inherits="RefCounted" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+<class name="NavigationPathQueryResult2D" inherits="RefCounted" is_experimental="true" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
Result from a [NavigationPathQueryParameters2D] navigation path query.
</brief_description>
@@ -20,5 +20,22 @@
<member name="path" type="PackedVector2Array" setter="set_path" getter="get_path" default="PackedVector2Array()">
The resulting path array from the navigation query. All path array positions are in global coordinates. Without customized query parameters this is the same path as returned by [method NavigationServer2D.map_get_path].
</member>
+ <member name="path_owner_ids" type="PackedInt64Array" setter="set_path_owner_ids" getter="get_path_owner_ids" default="PackedInt64Array()">
+ The [code]ObjectID[/code]s of the [Object]s which manage the regions and links each point of the path goes through.
+ </member>
+ <member name="path_rids" type="RID[]" setter="set_path_rids" getter="get_path_rids" default="[]">
+ The [RID]s of the regions and links that each point of the path goes through.
+ </member>
+ <member name="path_types" type="PackedInt32Array" setter="set_path_types" getter="get_path_types" default="PackedInt32Array()">
+ The type of navigation primitive (region or link) that each point of the path goes through.
+ </member>
</members>
+ <constants>
+ <constant name="PATH_SEGMENT_TYPE_REGION" value="0" enum="PathSegmentType">
+ This segment of the path goes through a region.
+ </constant>
+ <constant name="PATH_SEGMENT_TYPE_LINK" value="1" enum="PathSegmentType">
+ This segment of the path goes through a link.
+ </constant>
+ </constants>
</class>
diff --git a/doc/classes/NavigationPathQueryResult3D.xml b/doc/classes/NavigationPathQueryResult3D.xml
index b4ca8288db..03d41cb230 100644
--- a/doc/classes/NavigationPathQueryResult3D.xml
+++ b/doc/classes/NavigationPathQueryResult3D.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="NavigationPathQueryResult3D" inherits="RefCounted" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+<class name="NavigationPathQueryResult3D" inherits="RefCounted" is_experimental="true" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
Result from a [NavigationPathQueryParameters3D] navigation path query.
</brief_description>
@@ -20,5 +20,22 @@
<member name="path" type="PackedVector3Array" setter="set_path" getter="get_path" default="PackedVector3Array()">
The resulting path array from the navigation query. All path array positions are in global coordinates. Without customized query parameters this is the same path as returned by [method NavigationServer3D.map_get_path].
</member>
+ <member name="path_owner_ids" type="PackedInt64Array" setter="set_path_owner_ids" getter="get_path_owner_ids" default="PackedInt64Array()">
+ The [code]ObjectID[/code]s of the [Object]s which manage the regions and links each point of the path goes through.
+ </member>
+ <member name="path_rids" type="RID[]" setter="set_path_rids" getter="get_path_rids" default="[]">
+ The [RID]s of the regions and links that each point of the path goes through.
+ </member>
+ <member name="path_types" type="PackedInt32Array" setter="set_path_types" getter="get_path_types" default="PackedInt32Array()">
+ The type of navigation primitive (region or link) that each point of the path goes through.
+ </member>
</members>
+ <constants>
+ <constant name="PATH_SEGMENT_TYPE_REGION" value="0" enum="PathSegmentType">
+ This segment of the path goes through a region.
+ </constant>
+ <constant name="PATH_SEGMENT_TYPE_LINK" value="1" enum="PathSegmentType">
+ This segment of the path goes through a link.
+ </constant>
+ </constants>
</class>
diff --git a/doc/classes/NavigationPolygon.xml b/doc/classes/NavigationPolygon.xml
index 19466c171f..b30dd2703a 100644
--- a/doc/classes/NavigationPolygon.xml
+++ b/doc/classes/NavigationPolygon.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="NavigationPolygon" inherits="Resource" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+<class name="NavigationPolygon" inherits="Resource" is_experimental="true" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
A node that has methods to draw outlines or use indices of vertices to create navigation polygons.
</brief_description>
@@ -12,14 +12,14 @@
var outline = PackedVector2Array([Vector2(0, 0), Vector2(0, 50), Vector2(50, 50), Vector2(50, 0)])
polygon.add_outline(outline)
polygon.make_polygons_from_outlines()
- $NavigationRegion2D.navpoly = polygon
+ $NavigationRegion2D.navigation_polygon = polygon
[/gdscript]
[csharp]
var polygon = new NavigationPolygon();
var outline = new Vector2[] { new Vector2(0, 0), new Vector2(0, 50), new Vector2(50, 50), new Vector2(50, 0) };
polygon.AddOutline(outline);
polygon.MakePolygonsFromOutlines();
- GetNode&lt;NavigationRegion2D&gt;("NavigationRegion2D").Navpoly = polygon;
+ GetNode&lt;NavigationRegion2D&gt;("NavigationRegion2D").NavigationPolygon = polygon;
[/csharp]
[/codeblocks]
Using [method add_polygon] and indices of the vertices array.
@@ -30,7 +30,7 @@
polygon.vertices = vertices
var indices = PackedInt32Array([0, 1, 2, 3])
polygon.add_polygon(indices)
- $NavigationRegion2D.navpoly = polygon
+ $NavigationRegion2D.navigation_polygon = polygon
[/gdscript]
[csharp]
var polygon = new NavigationPolygon();
@@ -38,7 +38,7 @@
polygon.Vertices = vertices;
var indices = new int[] { 0, 1, 2, 3 };
polygon.AddPolygon(indices);
- GetNode&lt;NavigationRegion2D&gt;("NavigationRegion2D").Navpoly = polygon;
+ GetNode&lt;NavigationRegion2D&gt;("NavigationRegion2D").NavigationPolygon = polygon;
[/csharp]
[/codeblocks]
</description>
@@ -80,10 +80,10 @@
Clears the array of polygons, but it doesn't clear the array of outlines and vertices.
</description>
</method>
- <method name="get_mesh">
+ <method name="get_navigation_mesh">
<return type="NavigationMesh" />
<description>
- Returns the [NavigationMesh] resulting from this navigation polygon. This navmesh can be used to update the navmesh of a region with the [method NavigationServer3D.region_set_navmesh] API directly (as 2D uses the 3D server behind the scene).
+ Returns the [NavigationMesh] resulting from this navigation polygon. This navigation mesh can be used to update the navigation mesh of a region with the [method NavigationServer3D.region_set_navigation_mesh] API directly (as 2D uses the 3D server behind the scene).
</description>
</method>
<method name="get_outline" qualifiers="const">
diff --git a/doc/classes/NavigationRegion2D.xml b/doc/classes/NavigationRegion2D.xml
index 0f28081201..8b8793b3b4 100644
--- a/doc/classes/NavigationRegion2D.xml
+++ b/doc/classes/NavigationRegion2D.xml
@@ -1,12 +1,12 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="NavigationRegion2D" inherits="Node2D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+<class name="NavigationRegion2D" inherits="Node2D" is_experimental="true" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
A region of the 2D navigation map.
</brief_description>
<description>
A region of the navigation map. It tells the [NavigationServer2D] what can be navigated and what cannot, based on its [NavigationPolygon] resource.
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.
+ [b]Note:[/b] Overlapping two regions' navigation 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.
The pathfinding cost of traveling distances inside this region can be controlled with the [member travel_cost] multiplier.
@@ -42,16 +42,16 @@
Determines if the [NavigationRegion2D] is enabled or disabled.
</member>
<member name="enter_cost" type="float" setter="set_enter_cost" getter="get_enter_cost" default="0.0">
- When pathfinding enters this region's navmesh from another regions navmesh the [code]enter_cost[/code] value is added to the path distance for determining the shortest path.
+ When pathfinding enters this region's navigation mesh from another regions navigation mesh the [code]enter_cost[/code] value is added to the path distance for determining the shortest path.
</member>
<member name="navigation_layers" type="int" setter="set_navigation_layers" getter="get_navigation_layers" default="1">
A bitfield determining all navigation layers the region belongs to. These navigation layers can be checked upon when requesting a path with [method NavigationServer2D.map_get_path].
</member>
- <member name="navpoly" type="NavigationPolygon" setter="set_navigation_polygon" getter="get_navigation_polygon">
+ <member name="navigation_polygon" type="NavigationPolygon" setter="set_navigation_polygon" getter="get_navigation_polygon">
The [NavigationPolygon] resource to use.
</member>
<member name="travel_cost" type="float" setter="set_travel_cost" getter="get_travel_cost" default="1.0">
- When pathfinding moves inside this region's navmesh the traveled distances are multiplied with [code]travel_cost[/code] for determining the shortest path.
+ When pathfinding moves inside this region's navigation mesh the traveled distances are multiplied with [code]travel_cost[/code] for determining the shortest path.
</member>
</members>
</class>
diff --git a/doc/classes/NavigationRegion3D.xml b/doc/classes/NavigationRegion3D.xml
index 85f163b3c2..10662db869 100644
--- a/doc/classes/NavigationRegion3D.xml
+++ b/doc/classes/NavigationRegion3D.xml
@@ -1,12 +1,12 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="NavigationRegion3D" inherits="Node3D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+<class name="NavigationRegion3D" inherits="Node3D" is_experimental="true" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
A region of the navigation map.
</brief_description>
<description>
A region of the navigation map. It tells the [NavigationServer3D] what can be navigated and what cannot, based on its [NavigationMesh] resource.
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.
+ [b]Note:[/b] Overlapping two regions' navigation meshes 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.
The cost of traveling distances inside this region can be controlled with the [member travel_cost] multiplier.
@@ -49,16 +49,16 @@
Determines if the [NavigationRegion3D] is enabled or disabled.
</member>
<member name="enter_cost" type="float" setter="set_enter_cost" getter="get_enter_cost" default="0.0">
- When pathfinding enters this region's navmesh from another regions navmesh the [code]enter_cost[/code] value is added to the path distance for determining the shortest path.
+ When pathfinding enters this region's navigation mesh from another regions navigation mesh the [code]enter_cost[/code] value is added to the path distance for determining the shortest path.
</member>
<member name="navigation_layers" type="int" setter="set_navigation_layers" getter="get_navigation_layers" default="1">
A bitfield determining all navigation layers the region belongs to. These navigation layers can be checked upon when requesting a path with [method NavigationServer3D.map_get_path].
</member>
- <member name="navmesh" type="NavigationMesh" setter="set_navigation_mesh" getter="get_navigation_mesh">
+ <member name="navigation_mesh" type="NavigationMesh" setter="set_navigation_mesh" getter="get_navigation_mesh">
The [NavigationMesh] resource to use.
</member>
<member name="travel_cost" type="float" setter="set_travel_cost" getter="get_travel_cost" default="1.0">
- When pathfinding moves inside this region's navmesh the traveled distances are multiplied with [code]travel_cost[/code] for determining the shortest path.
+ When pathfinding moves inside this region's navigation mesh the traveled distances are multiplied with [code]travel_cost[/code] for determining the shortest path.
</member>
</members>
<signals>
diff --git a/doc/classes/NavigationServer2D.xml b/doc/classes/NavigationServer2D.xml
index 981ab8a5e1..32e48cde54 100644
--- a/doc/classes/NavigationServer2D.xml
+++ b/doc/classes/NavigationServer2D.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="NavigationServer2D" inherits="Object" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+<class name="NavigationServer2D" inherits="Object" is_experimental="true" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
Server interface for low-level 2D navigation access
</brief_description>
@@ -40,12 +40,12 @@
<method name="agent_set_callback" qualifiers="const">
<return type="void" />
<param index="0" name="agent" type="RID" />
- <param index="1" name="receiver" type="Object" />
+ <param index="1" name="object_id" type="int" />
<param index="2" name="method" type="StringName" />
<param index="3" name="userdata" type="Variant" default="null" />
<description>
- Callback called at the end of the RVO process. If a callback is created manually and the agent is placed on a navigation map it will calculate avoidance for the agent and dispatch the calculated [code]safe_velocity[/code] to the [param receiver] object with a signal to the chosen [param method] name.
- [b]Note:[/b] Created callbacks are always processed independently of the SceneTree state as long as the agent is on a navigation map and not freed. To disable the dispatch of a callback from an agent use [method agent_set_callback] again with a [code]null[/code] object as the [param receiver].
+ Sets the callback [param object_id] and [param method] that gets called after each avoidance processing step for the [param agent]. The calculated [code]safe_velocity[/code] will be dispatched with a signal to the object just before the physics calculations.
+ [b]Note:[/b] Created callbacks are always processed independently of the SceneTree state as long as the agent is on a navigation map and not freed. To disable the dispatch of a callback from an agent use [method agent_set_callback] again with a [code]0[/code] ObjectID as the [param object_id].
</description>
</method>
<method name="agent_set_map" qualifiers="const">
@@ -167,6 +167,13 @@
Returns the navigation layers for this [code]link[/code].
</description>
</method>
+ <method name="link_get_owner_id" qualifiers="const">
+ <return type="int" />
+ <param index="0" name="link" type="RID" />
+ <description>
+ Returns the [code]ObjectID[/code] of the object which manages this link.
+ </description>
+ </method>
<method name="link_get_start_location" qualifiers="const">
<return type="Vector2" />
<param index="0" name="link" type="RID" />
@@ -228,6 +235,14 @@
Set the links's navigation layers. This allows selecting links from a path request (when using [method NavigationServer2D.map_get_path]).
</description>
</method>
+ <method name="link_set_owner_id" qualifiers="const">
+ <return type="void" />
+ <param index="0" name="link" type="RID" />
+ <param index="1" name="owner_id" type="int" />
+ <description>
+ Set the [code]ObjectID[/code] of the object which manages this link.
+ </description>
+ </method>
<method name="link_set_start_location" qualifiers="const">
<return type="void" />
<param index="0" name="link" type="RID" />
@@ -426,6 +441,13 @@
Returns the region's navigation layers.
</description>
</method>
+ <method name="region_get_owner_id" qualifiers="const">
+ <return type="int" />
+ <param index="0" name="region" type="RID" />
+ <description>
+ Returns the [code]ObjectID[/code] of the object which manages this region.
+ </description>
+ </method>
<method name="region_get_travel_cost" qualifiers="const">
<return type="float" />
<param index="0" name="region" type="RID" />
@@ -467,12 +489,20 @@
Set the region's navigation layers. This allows selecting regions from a path request (when using [method NavigationServer2D.map_get_path]).
</description>
</method>
- <method name="region_set_navpoly" qualifiers="const">
+ <method name="region_set_navigation_polygon" qualifiers="const">
+ <return type="void" />
+ <param index="0" name="region" type="RID" />
+ <param index="1" name="navigation_polygon" type="NavigationPolygon" />
+ <description>
+ Sets the [param navigation_polygon] for the region.
+ </description>
+ </method>
+ <method name="region_set_owner_id" qualifiers="const">
<return type="void" />
<param index="0" name="region" type="RID" />
- <param index="1" name="nav_poly" type="NavigationPolygon" />
+ <param index="1" name="owner_id" type="int" />
<description>
- Sets the navigation mesh for the region.
+ Set the [code]ObjectID[/code] of the object which manages this region.
</description>
</method>
<method name="region_set_transform" qualifiers="const">
diff --git a/doc/classes/NavigationServer3D.xml b/doc/classes/NavigationServer3D.xml
index 943aa03ef7..c156dfac16 100644
--- a/doc/classes/NavigationServer3D.xml
+++ b/doc/classes/NavigationServer3D.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="NavigationServer3D" inherits="Object" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+<class name="NavigationServer3D" inherits="Object" is_experimental="true" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
Server interface for low-level 3D navigation access
</brief_description>
@@ -40,12 +40,12 @@
<method name="agent_set_callback" qualifiers="const">
<return type="void" />
<param index="0" name="agent" type="RID" />
- <param index="1" name="receiver" type="Object" />
+ <param index="1" name="object_id" type="int" />
<param index="2" name="method" type="StringName" />
<param index="3" name="userdata" type="Variant" default="null" />
<description>
- Callback called at the end of the RVO process. If a callback is created manually and the agent is placed on a navigation map it will calculate avoidance for the agent and dispatch the calculated [code]safe_velocity[/code] to the [param receiver] object with a signal to the chosen [param method] name.
- [b]Note:[/b] Created callbacks are always processed independently of the SceneTree state as long as the agent is on a navigation map and not freed. To disable the dispatch of a callback from an agent use [method agent_set_callback] again with a [code]null[/code] object as the [param receiver].
+ Sets the callback [param object_id] and [param method] that gets called after each avoidance processing step for the [param agent]. The calculated [code]safe_velocity[/code] will be dispatched with a signal to the object just before the physics calculations.
+ [b]Note:[/b] Created callbacks are always processed independently of the SceneTree state as long as the agent is on a navigation map and not freed. To disable the dispatch of a callback from an agent use [method agent_set_callback] again with a [code]0[/code] ObjectID as the [param object_id].
</description>
</method>
<method name="agent_set_map" qualifiers="const">
@@ -167,6 +167,13 @@
Returns the navigation layers for this [code]link[/code].
</description>
</method>
+ <method name="link_get_owner_id" qualifiers="const">
+ <return type="int" />
+ <param index="0" name="link" type="RID" />
+ <description>
+ Returns the [code]ObjectID[/code] of the object which manages this link.
+ </description>
+ </method>
<method name="link_get_start_location" qualifiers="const">
<return type="Vector3" />
<param index="0" name="link" type="RID" />
@@ -228,6 +235,14 @@
Set the links's navigation layers. This allows selecting links from a path request (when using [method NavigationServer3D.map_get_path]).
</description>
</method>
+ <method name="link_set_owner_id" qualifiers="const">
+ <return type="void" />
+ <param index="0" name="link" type="RID" />
+ <param index="1" name="owner_id" type="int" />
+ <description>
+ Set the [code]ObjectID[/code] of the object which manages this link.
+ </description>
+ </method>
<method name="link_set_start_location" qualifiers="const">
<return type="void" />
<param index="0" name="link" type="RID" />
@@ -418,12 +433,12 @@
Queries a path in a given navigation map. Start and target position and other parameters are defined through [NavigationPathQueryParameters3D]. Updates the provided [NavigationPathQueryResult3D] result object with the path among other results requested by the query.
</description>
</method>
- <method name="region_bake_navmesh" qualifiers="const">
+ <method name="region_bake_navigation_mesh" qualifiers="const">
<return type="void" />
- <param index="0" name="mesh" type="NavigationMesh" />
- <param index="1" name="node" type="Node" />
+ <param index="0" name="navigation_mesh" type="NavigationMesh" />
+ <param index="1" name="root_node" type="Node" />
<description>
- Bakes the navigation mesh.
+ Bakes the [param navigation_mesh] with bake source geometry collected starting from the [param root_node].
</description>
</method>
<method name="region_create" qualifiers="const">
@@ -476,6 +491,13 @@
Returns the region's navigation layers.
</description>
</method>
+ <method name="region_get_owner_id" qualifiers="const">
+ <return type="int" />
+ <param index="0" name="region" type="RID" />
+ <description>
+ Returns the [code]ObjectID[/code] of the object which manages this region.
+ </description>
+ </method>
<method name="region_get_travel_cost" qualifiers="const">
<return type="float" />
<param index="0" name="region" type="RID" />
@@ -517,14 +539,22 @@
Set the region's navigation layers. This allows selecting regions from a path request (when using [method NavigationServer3D.map_get_path]).
</description>
</method>
- <method name="region_set_navmesh" qualifiers="const">
+ <method name="region_set_navigation_mesh" qualifiers="const">
<return type="void" />
<param index="0" name="region" type="RID" />
- <param index="1" name="nav_mesh" type="NavigationMesh" />
+ <param index="1" name="navigation_mesh" type="NavigationMesh" />
<description>
Sets the navigation mesh for the region.
</description>
</method>
+ <method name="region_set_owner_id" qualifiers="const">
+ <return type="void" />
+ <param index="0" name="region" type="RID" />
+ <param index="1" name="owner_id" type="int" />
+ <description>
+ Set the [code]ObjectID[/code] of the object which manages this region.
+ </description>
+ </method>
<method name="region_set_transform" qualifiers="const">
<return type="void" />
<param index="0" name="region" type="RID" />
diff --git a/doc/classes/Node.xml b/doc/classes/Node.xml
index b83bff5d5e..24df5977f9 100644
--- a/doc/classes/Node.xml
+++ b/doc/classes/Node.xml
@@ -384,8 +384,11 @@
<method name="get_path_to" qualifiers="const">
<return type="NodePath" />
<param index="0" name="node" type="Node" />
+ <param index="1" name="use_unique_path" type="bool" default="false" />
<description>
Returns the relative [NodePath] from this node to the specified [param node]. Both nodes must be in the same scene or the function will fail.
+ If [param use_unique_path] is [code]true[/code], returns the shortest path considering unique node.
+ [b]Note:[/b] If you get a relative path which starts from a unique node, the path may be longer than a normal relative path due to the addition of the unique node's name.
</description>
</method>
<method name="get_physics_process_delta_time" qualifiers="const">
@@ -535,7 +538,7 @@
[b]Note:[/b] Internal children can only be moved within their expected "internal range" (see [code]internal[/code] parameter in [method add_child]).
</description>
</method>
- <method name="print_orphan_nodes">
+ <method name="print_orphan_nodes" qualifiers="static">
<return type="void" />
<description>
Prints all orphan nodes (nodes outside the [SceneTree]). Used for debugging.
@@ -606,7 +609,7 @@
<return type="void" />
<param index="0" name="group" type="StringName" />
<description>
- Removes a node from a group. See notes in the description, and the group methods in [SceneTree].
+ Removes a node from the [param group]. Does nothing if the node is not in the [param group]. See notes in the description, and the group methods in [SceneTree].
</description>
</method>
<method name="replace_by">
@@ -991,7 +994,7 @@
<constant name="DUPLICATE_SCRIPTS" value="4" enum="DuplicateFlags">
Duplicate the node's scripts.
</constant>
- <constant name="DUPLICATE_USE_INSTANCING" value="8" enum="DuplicateFlags">
+ <constant name="DUPLICATE_USE_INSTANTIATION" value="8" enum="DuplicateFlags">
Duplicate using instancing.
An instance stays linked to the original so when the original changes, the instance changes too.
</constant>
diff --git a/doc/classes/Node2D.xml b/doc/classes/Node2D.xml
index 054ab532af..9d224f09b1 100644
--- a/doc/classes/Node2D.xml
+++ b/doc/classes/Node2D.xml
@@ -99,6 +99,9 @@
<member name="global_rotation" type="float" setter="set_global_rotation" getter="get_global_rotation">
Global rotation in radians.
</member>
+ <member name="global_rotation_degrees" type="float" setter="set_global_rotation_degrees" getter="get_global_rotation_degrees">
+ Helper property to access [member global_rotation] in degrees instead of radians.
+ </member>
<member name="global_scale" type="Vector2" setter="set_global_scale" getter="get_global_scale">
Global scale.
</member>
@@ -114,6 +117,9 @@
<member name="rotation" type="float" setter="set_rotation" getter="get_rotation" default="0.0">
Rotation in radians, relative to the node's parent.
</member>
+ <member name="rotation_degrees" type="float" setter="set_rotation_degrees" getter="get_rotation_degrees">
+ Helper property to access [member rotation] in degrees instead of radians.
+ </member>
<member name="scale" type="Vector2" setter="set_scale" getter="get_scale" default="Vector2(1, 1)">
The node's scale. Unscaled value: [code](1, 1)[/code].
[b]Note:[/b] Negative X scales in 2D are not decomposable from the transformation matrix. Due to the way scale is represented with transformation matrices in Godot, negative scales on the X axis will be changed to negative scales on the Y axis and a rotation of 180 degrees when decomposed.
@@ -125,15 +131,5 @@
<member name="transform" type="Transform2D" setter="set_transform" getter="get_transform">
Local [Transform2D].
</member>
- <member name="y_sort_enabled" type="bool" setter="set_y_sort_enabled" getter="is_y_sort_enabled" default="false">
- If [code]true[/code], child nodes with the lowest Y position are drawn before those with a higher Y position. If [code]false[/code], Y-sorting is disabled. Y-sorting only affects children that inherit from [CanvasItem].
- You can nest nodes with Y-sorting. Child Y-sorted nodes are sorted in the same space as the parent Y-sort. This feature allows you to organize a scene better or divide it into multiple ones without changing your scene tree.
- </member>
- <member name="z_as_relative" type="bool" setter="set_z_as_relative" getter="is_z_relative" default="true">
- If [code]true[/code], the node's Z index is relative to its parent's Z index. If this node's Z index is 2 and its parent's effective Z index is 3, then this node's effective Z index will be 2 + 3 = 5.
- </member>
- <member name="z_index" type="int" setter="set_z_index" getter="get_z_index" default="0">
- Z index. Controls the order in which the nodes render. A node with a higher Z index will display in front of others. Must be between [constant RenderingServer.CANVAS_ITEM_Z_MIN] and [constant RenderingServer.CANVAS_ITEM_Z_MAX] (inclusive).
- </member>
</members>
</class>
diff --git a/doc/classes/Node3D.xml b/doc/classes/Node3D.xml
index b6024b1887..1aa71113e9 100644
--- a/doc/classes/Node3D.xml
+++ b/doc/classes/Node3D.xml
@@ -274,6 +274,9 @@
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_rotation_degrees" type="Vector3" setter="set_global_rotation_degrees" getter="get_global_rotation_degrees">
+ Helper property to access [member global_rotation] in degrees instead of radians.
+ </member>
<member name="global_transform" type="Transform3D" setter="set_global_transform" getter="get_global_transform">
World3D space (global) [Transform3D] of this node.
</member>
@@ -287,6 +290,9 @@
Rotation part of the local transformation in radians, specified in terms of Euler angles. The angles construct a rotaton in the order specified by the [member rotation_order] property.
[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a vector. The three Euler angles, which are the three independent parameters of the Euler-angle parametrization of the rotation matrix, are stored in a [Vector3] data structure not because the rotation is a vector, but only because [Vector3] exists as a convenient data-structure to store 3 floating-point numbers. Therefore, applying affine operations on the rotation "vector" is not meaningful.
</member>
+ <member name="rotation_degrees" type="Vector3" setter="set_rotation_degrees" getter="get_rotation_degrees">
+ Helper property to access [member rotation] in degrees instead of radians.
+ </member>
<member name="rotation_edit_mode" type="int" setter="set_rotation_edit_mode" getter="get_rotation_edit_mode" enum="Node3D.RotationEditMode" default="0">
Specify how rotation (and scale) will be presented in the editor.
</member>
diff --git a/doc/classes/NodePath.xml b/doc/classes/NodePath.xml
index 022b4826ea..c82ed5f143 100644
--- a/doc/classes/NodePath.xml
+++ b/doc/classes/NodePath.xml
@@ -187,12 +187,14 @@
<return type="bool" />
<param index="0" name="right" type="NodePath" />
<description>
+ Returns [code]true[/code] if two node paths are not equal.
</description>
</operator>
<operator name="operator ==">
<return type="bool" />
<param index="0" name="right" type="NodePath" />
<description>
+ Returns [code]true[/code] if two node paths are equal, i.e. all node names in the path are the same and in the same order.
</description>
</operator>
</operators>
diff --git a/doc/classes/OS.xml b/doc/classes/OS.xml
index f4a5288481..0efc6ab399 100644
--- a/doc/classes/OS.xml
+++ b/doc/classes/OS.xml
@@ -182,10 +182,12 @@
<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.
+ Similar to [method get_cmdline_args], but this returns the user arguments (any argument passed after the double dash [code]--[/code] or double plus [code]++[/code] argument). These are left untouched by Godot for the user. [code]++[/code] can be used in situations where [code]--[/code] is intercepted by another program (such as [code]startx[/code]).
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
+ # Or:
+ godot --fullscreen ++ --level 1
[/codeblock]
</description>
</method>
@@ -392,18 +394,38 @@
<method name="get_system_font_path" qualifiers="const">
<return type="String" />
<param index="0" name="font_name" type="String" />
- <param index="1" name="bold" type="bool" default="false" />
- <param index="2" name="italic" type="bool" default="false" />
+ <param index="1" name="weight" type="int" default="400" />
+ <param index="2" name="stretch" type="int" default="100" />
+ <param index="3" name="italic" type="bool" default="false" />
<description>
- Returns path to the system font file with [param font_name] and style. Return empty string if no matching fonts found.
- [b]Note:[/b] This method is implemented on iOS, Linux, macOS and Windows.
+ Returns path to the system font file with [param font_name] and style. Returns empty string if no matching fonts found.
+ The following aliases can be used to request default fonts: "sans-serif", "serif", "monospace", "cursive", and "fantasy".
+ [b]Note:[/b] Returned font might have different style if the requested style is not available.
+ [b]Note:[/b] This method is implemented on Android, iOS, Linux, macOS and Windows.
+ </description>
+ </method>
+ <method name="get_system_font_path_for_text" qualifiers="const">
+ <return type="PackedStringArray" />
+ <param index="0" name="font_name" type="String" />
+ <param index="1" name="text" type="String" />
+ <param index="2" name="locale" type="String" default="&quot;&quot;" />
+ <param index="3" name="script" type="String" default="&quot;&quot;" />
+ <param index="4" name="weight" type="int" default="400" />
+ <param index="5" name="stretch" type="int" default="100" />
+ <param index="6" name="italic" type="bool" default="false" />
+ <description>
+ Returns an array of the system substitute font file paths, which are similar to the font with [param font_name] and style for the specified text, locale and script. Returns empty array if no matching fonts found.
+ The following aliases can be used to request default fonts: "sans-serif", "serif", "monospace", "cursive", and "fantasy".
+ [b]Note:[/b] Depending on OS, it's not guaranteed that any of the returned fonts is suitable for rendering specified text. Fonts should be loaded and checked in the order they are returned, and the first suitable one used.
+ [b]Note:[/b] Returned fonts might have different style if the requested style is not available or belong to a different font family.
+ [b]Note:[/b] This method is implemented on Android, 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.
+ [b]Note:[/b] This method is implemented on Android, iOS, Linux, macOS and Windows.
</description>
</method>
<method name="get_thread_caller_id" qualifiers="const">
@@ -467,7 +489,7 @@
<return type="bool" />
<param index="0" name="tag_name" type="String" />
<description>
- Returns [code]true[/code] if the feature for the given feature tag is supported in the currently running instance, depending on the platform, build, etc. Can be used to check whether you're currently running a debug build, on a certain platform or arch, etc. Refer to the [url=$DOCS_URL/getting_started/workflow/export/feature_tags.html]Feature Tags[/url] documentation for more details.
+ Returns [code]true[/code] if the feature for the given feature tag is supported in the currently running instance, depending on the platform, build, etc. Can be used to check whether you're currently running a debug build, on a certain platform or arch, etc. Refer to the [url=$DOCS_URL/tutorials/export/feature_tags.html]Feature Tags[/url] documentation for more details.
[b]Note:[/b] Tag names are case-sensitive.
</description>
</method>
diff --git a/doc/classes/Object.xml b/doc/classes/Object.xml
index 318f2cfade..e015bec134 100644
--- a/doc/classes/Object.xml
+++ b/doc/classes/Object.xml
@@ -1,33 +1,27 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="Object" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
- Base class for all non-built-in types.
+ Base class for all other classes in the engine.
</brief_description>
<description>
- Every class which is not a built-in type inherits from this class.
- You can construct Objects from scripting languages, using [code]Object.new()[/code] in GDScript, or [code]new Object[/code] in C#.
- Objects do not manage memory. If a class inherits from Object, you will have to delete instances of it manually. To do so, call the [method free] method from your script or delete the instance from C++.
- Some classes that extend Object add memory management. This is the case of [RefCounted], which counts references and deletes itself automatically when no longer referenced. [Node], another fundamental type, deletes all its children when freed from memory.
- Objects export properties, which are mainly useful for storage and editing, but not really so much in programming. Properties are exported in [method _get_property_list] and handled in [method _get] and [method _set]. However, scripting languages and C++ have simpler means to export them.
- Property membership can be tested directly in GDScript using [code]in[/code]:
- [codeblocks]
- [gdscript]
- var n = Node2D.new()
- print("position" in n) # Prints "true".
- print("other_property" in n) # Prints "false".
- [/gdscript]
- [csharp]
- var node = new Node2D();
- // C# has no direct equivalent to GDScript's `in` operator here, but we
- // can achieve the same behavior by performing `Get` with a null check.
- GD.Print(node.Get("position") != null); // Prints "true".
- GD.Print(node.Get("other_property") != null); // Prints "false".
- [/csharp]
- [/codeblocks]
- The [code]in[/code] operator will evaluate to [code]true[/code] as long as the key exists, even if the value is [code]null[/code].
- Objects also receive notifications. Notifications are a simple way to notify the object about different events, so they can all be handled together. See [method _notification].
- [b]Note:[/b] Unlike references to a [RefCounted], references to an Object stored in a variable can become invalid without warning. Therefore, it's recommended to use [RefCounted] for data classes instead of [Object].
- [b]Note:[/b] The [code]script[/code] property is not exposed like most properties, but it does have a setter and getter ([code]set_script()[/code] and [code]get_script()[/code]).
+ An advanced [Variant] type. All classes in the engine inherit from Object. Each class may define new properties, methods or signals, which are available to all inheriting classes. For example, a [Sprite2D] instance is able to call [method Node.add_child] because it inherits from [Node].
+ You can create new instances, using [code]Object.new()[/code] in GDScript, or [code]new Object[/code] in C#.
+ To delete an Object instance, call [method free]. This is necessary for most classes inheriting Object, because they do not manage memory on their own, and will otherwise cause memory leaks when no longer in use. There are a few classes that perform memory management. For example, [RefCounted] (and by extension [Resource]) deletes itself when no longer referenced, and [Node] deletes its children when freed.
+ Objects can have a [Script] attached to them. Once the [Script] is instantiated, it effectively acts as an extension to the base class, allowing it to define and inherit new properties, methods and signals.
+ Inside a [Script], [method _get_property_list] may be overridden to customize properties in several ways. This allows them to be available to the editor, display as lists of options, sub-divide into groups, save on disk, etc. Scripting languages offer easier ways to customize properties, such as with the [annotation @GDScript.@export] annotation.
+ Godot is very dynamic. An object's script, and therefore its properties, methods and signals, can be changed at run-time. Because of this, there can be occasions where, for example, a property required by a method may not exist. To prevent run-time errors, see methods such as [method set], [method get], [method call], [method has_method], [method has_signal], etc. Note that these methods are [b]much[/b] slower than direct references.
+ In GDScript, you can also check if a given property, method, or signal name exists in an object with the [code]in[/code] operator:
+ [codeblock]
+ var node = Node.new()
+ print("name" in node) # Prints true
+ print("get_parent" in node) # Prints true
+ print("tree_entered" in node) # Prints true
+ print("unknown" in node) # Prints false
+ [/codeblock]
+ Notifications are [int] constants commonly sent and received by objects. For example, on every rendered frame, the [SceneTree] notifies nodes inside the tree with a [constant Node.NOTIFICATION_PROCESS]. The nodes receive it and may call [method Node._process] to update. To make use of notifications, see [method notification] and [method _notification].
+ Lastly, every object can also contain metadata (data about data). [method set_meta] can be useful to store information that the object itself does not depend on. To keep your code clean, making excessive use of metadata is discouraged.
+ [b]Note:[/b] Unlike references to a [RefCounted], references to an object stored in a variable can become invalid without being set to [code]null[/code]. To check if an object has been deleted, do [i]not[/i] compare it against [code]null[/code]. Instead, use [method @GlobalScope.is_instance_valid]. It's also recommended to inherit from [RefCounted] for classes storing data instead of [Object].
+ [b]Note:[/b] The [code]script[/code] is not exposed like most properties. To set or get an object's [Script] in code, use [method set_script] and [method get_script], respectively.
</description>
<tutorials>
<link title="When and how to avoid using nodes for everything">$DOCS_URL/tutorials/best_practices/node_alternatives.html</link>
@@ -38,46 +32,174 @@
<return type="Variant" />
<param index="0" name="property" type="StringName" />
<description>
- Virtual method which can be overridden to customize the return value of [method get].
- Returns the given property. Returns [code]null[/code] if the [param property] does not exist.
+ Override this method to customize the behavior of [method get]. Should return the given [param property]'s value, or [code]null[/code] if the [param property] should be handled normally.
+ Combined with [method _set] and [method _get_property_list], this method allows defining custom properties, which is particularly useful for editor plugins. Note that a property must be present in [method get_property_list], otherwise this method will not be called.
+ [codeblocks]
+ [gdscript]
+ func _get(property):
+ if (property == "fake_property"):
+ print("Getting my property!")
+ return 4
+
+ func _get_property_list():
+ return [
+ { "name": "fake_property", "type": TYPE_INT }
+ ]
+ [/gdscript]
+ [csharp]
+ public override Variant _Get(StringName property)
+ {
+ if (property == "FakeProperty")
+ {
+ GD.Print("Getting my property!");
+ return 4;
+ }
+ return default;
+ }
+
+ public override Godot.Collections.Array&lt;Godot.Collections.Dictionary&gt; _GetPropertyList()
+ {
+ return new Godot.Collections.Array&lt;Godot.Collections.Dictionary&gt;()
+ {
+ new Godot.Collections.Dictionary()
+ {
+ { "name", "FakeProperty" },
+ { "type", (int)Variant.Type.Int }
+ }
+ };
+ }
+ [/csharp]
+ [/codeblocks]
</description>
</method>
<method name="_get_property_list" qualifiers="virtual">
<return type="Dictionary[]" />
<description>
- Virtual method which can be overridden to customize the return value of [method get_property_list].
- Returns the object's property list as an [Array] of dictionaries.
- Each property's [Dictionary] must contain at least [code]name: String[/code] and [code]type: int[/code] (see [enum Variant.Type]) entries. Optionally, it can also include [code]hint: int[/code] (see [enum PropertyHint]), [code]hint_string: String[/code], and [code]usage: int[/code] (see [enum PropertyUsageFlags]).
+ Override this method to customize how script properties should be handled by the engine.
+ Should return a property list, as an [Array] of dictionaries. The result is added to the array of [method get_property_list], and should be formatted in the same way. Each [Dictionary] must at least contain the [code]name[/code] and [code]type[/code] entries.
+ The example below displays [code]hammer_type[/code] in the Inspector dock, only if [code]holding_hammer[/code] is [code]true[/code]:
+ [codeblocks]
+ [gdscript]
+ @tool
+ extends Node2D
+
+ @export var holding_hammer = false:
+ set(value):
+ holding_hammer = value
+ notify_property_list_changed()
+ var hammer_type = 0
+
+ func _get_property_list():
+ # By default, `hammer_type` is not visible in the editor.
+ var property_usage = PROPERTY_USAGE_NO_EDITOR
+
+ if holding_hammer:
+ property_usage = PROPERTY_USAGE_DEFAULT
+
+ var properties = []
+ properties.append({
+ "name": "hammer_type",
+ "type": TYPE_INT,
+ "usage": property_usage, # See above assignment.
+ "hint": PROPERTY_HINT_ENUM,
+ "hint_string": "Wooden,Iron,Golden,Enchanted"
+ })
+
+ return properties
+ [/gdscript]
+ [csharp]
+ [Tool]
+ public class MyNode2D : Node2D
+ {
+ private bool _holdingHammer;
+
+ [Export]
+ public bool HoldingHammer
+ {
+ get =&gt; _holdingHammer;
+ set
+ {
+ _holdingHammer = value;
+ NotifyPropertyListChanged();
+ }
+ }
+
+ public int HammerType { get; set; }
+
+ public override Godot.Collections.Array&lt;Godot.Collections.Dictionary&gt; _GetPropertyList()
+ {
+ // By default, `HammerType` is not visible in the editor.
+ var propertyUsage = PropertyUsageFlags.NoEditor;
+
+ if (HoldingHammer)
+ {
+ propertyUsage = PropertyUsageFlags.Default;
+ }
+
+ var properties = new Godot.Collections.Array&lt;Godot.Collections.Dictionary&gt;();
+ properties.Add(new Godot.Collections.Dictionary()
+ {
+ { "name", "HammerType" },
+ { "type", (int)Variant.Type.Int },
+ { "usage", (int)propertyUsage }, // See above assignment.
+ { "hint", (int)PropertyHint.Enum },
+ { "hint_string", "Wooden,Iron,Golden,Enchanted" }
+ });
+
+ return properties;
+ }
+ }
+ [/csharp]
+ [/codeblocks]
+ [b]Note:[/b] This method is intended for advanced purposes. For most common use cases, the scripting languages offer easier ways to handle properties. See [annotation @GDScript.@export], [annotation @GDScript.@export_enum], [annotation @GDScript.@export_group], etc.
+ [b]Note:[/b] If the object's script is not [annotation @GDScript.@tool], this method will not be called in the editor.
</description>
</method>
<method name="_init" qualifiers="virtual">
<return type="void" />
<description>
- Called when the object is initialized in memory. Can be defined to take in parameters, that are passed in when constructing.
- [b]Note:[/b] If [method _init] is defined with required parameters, then explicit construction is the only valid means of creating an Object of the class. If any other means (such as [method PackedScene.instantiate]) is used, then initialization will fail.
+ Called when the object's script is instantiated, oftentimes after the object is initialized in memory (through [code]Object.new()[/code] in GDScript, or [code]new Object[/code] in C#). It can be also defined to take in parameters. This method is similar to a constructor in most programming languages.
+ [b]Note:[/b] If [method _init] is defined with [i]required[/i] parameters, the Object with script may only be created directly. If any other means (such as [method PackedScene.instantiate] or [method Node.duplicate]) are used, the script's initialization will fail.
</description>
</method>
<method name="_notification" qualifiers="virtual">
<return type="void" />
<param index="0" name="what" type="int" />
<description>
- Called whenever the object receives a notification, which is identified in [param what] by a constant. The base [Object] has two constants [constant NOTIFICATION_POSTINITIALIZE] and [constant NOTIFICATION_PREDELETE], but subclasses such as [Node] define a lot more notifications which are also received by this method.
+ Called when the object receives a notification, which can be identified in [param what] by comparing it with a constant. See also [method notification].
+ [codeblocks]
+ [gdscript]
+ func _notification(what):
+ if what == NOTIFICATION_PREDELETE:
+ print("Goodbye!")
+ [/gdscript]
+ [csharp]
+ public override void _Notification(long what)
+ {
+ if (what == NotificationPredelete)
+ {
+ GD.Print("Goodbye!");
+ }
+ }
+ [/csharp]
+ [/codeblocks]
+ [b]Note:[/b] The base [Object] defines a few notifications ([constant NOTIFICATION_POSTINITIALIZE] and [constant NOTIFICATION_PREDELETE]). Inheriting classes such as [Node] define a lot more notifications, which are also received by this method.
</description>
</method>
<method name="_property_can_revert" qualifiers="virtual">
<return type="bool" />
<param index="0" name="property" type="StringName" />
<description>
- Virtual methods that can be overridden to customize the property revert behavior in the editor.
- Returns [code]true[/code] if the property identified by [code]name[/code] can be reverted to a default value. Override [method _property_get_revert] to return the actual value.
+ Override this method to customize the given [param property]'s revert behavior. Should return [code]true[/code] if the [param property] can be reverted in the Inspector dock. Use [method _property_get_revert] to specify the [param property]'s default value.
+ [b]Note:[/b] This method must return consistently, regardless of the current value of the [param property].
</description>
</method>
<method name="_property_get_revert" qualifiers="virtual">
<return type="Variant" />
<param index="0" name="property" type="StringName" />
<description>
- Virtual methods that can be overridden to customize the property revert behavior in the editor.
- Returns the default value of the property identified by [code]name[/code]. [method _property_can_revert] must be overridden as well for this method to be called.
+ Override this method to customize the given [param property]'s revert behavior. Should return the default value for the [param property]. If the default value differs from the [param property]'s current value, a revert icon is displayed in the Inspector dock.
+ [b]Note:[/b] [method _property_can_revert] must also be overridden for this method to be called.
</description>
</method>
<method name="_set" qualifiers="virtual">
@@ -85,15 +207,58 @@
<param index="0" name="property" type="StringName" />
<param index="1" name="value" type="Variant" />
<description>
- Virtual method which can be overridden to customize the return value of [method set].
- Sets a property. Returns [code]true[/code] if the [param property] exists.
+ Override this method to customize the behavior of [method set]. Should set the [param property] to [param value] and return [code]true[/code], or [code]false[/code] if the [param property] should be handled normally. The [i]exact[/i] way to set the [param property] is up to this method's implementation.
+ Combined with [method _get] and [method _get_property_list], this method allows defining custom properties, which is particularly useful for editor plugins. Note that a property [i]must[/i] be present in [method get_property_list], otherwise this method will not be called.
+ [codeblocks]
+ [gdscript]
+ func _set(property, value):
+ if (property == "fake_property"):
+ print("Setting my property to ", value)
+
+ func _get_property_list():
+ return [
+ { "name": "fake_property", "type": TYPE_INT }
+ ]
+ [/gdscript]
+ [csharp]
+ public override void _Set(StringName property, Variant value)
+ {
+ if (property == "FakeProperty")
+ {
+ GD.Print($"Setting my property to {value}");
+ return true;
+ }
+
+ return false;
+ }
+
+ public override Godot.Collections.Array&lt;Godot.Collections.Dictionary&gt; _GetPropertyList()
+ {
+ return new Godot.Collections.Array&lt;Godot.Collections.Dictionary&gt;()
+ {
+ new Godot.Collections.Dictionary()
+ {
+ { "name", "FakeProperty" },
+ { "type", (int)Variant.Type.Int }
+ }
+ };
+ }
+ [/csharp]
+ [/codeblocks]
</description>
</method>
<method name="_to_string" qualifiers="virtual">
<return type="String" />
<description>
- Virtual method which can be overridden to customize the return value of [method to_string], and thus the object's representation where it is converted to a string, e.g. with [code]print(obj)[/code].
- Returns a [String] representing the object. If not overridden, defaults to [code]"[ClassName:RID]"[/code].
+ Override this method to customize the return value of [method to_string], and therefore the object's representation as a [String].
+ [codeblock]
+ func _to_string():
+ return "Welcome to Godot 4!"
+
+ func _init():
+ print(self) # Prints Welcome to Godot 4!"
+ var a = str(self) # a is "Welcome to Godot 4!"
+ [/codeblock]
</description>
</method>
<method name="add_user_signal">
@@ -101,15 +266,37 @@
<param index="0" name="signal" type="String" />
<param index="1" name="arguments" type="Array" default="[]" />
<description>
- Adds a user-defined [param signal]. Arguments are optional, but can be added as an [Array] of dictionaries, each containing [code]name: String[/code] and [code]type: int[/code] (see [enum Variant.Type]) entries.
+ Adds a user-defined [param signal]. Optional arguments for the signal can be added as an [Array] of dictionaries, each defining a [code]name[/code] [String] and a [code]type[/code] [int] (see [enum Variant.Type]). See also [method has_user_signal].
+ [codeblocks]
+ [gdscript]
+ add_user_signal("hurt", [
+ { "name": "damage", "type": TYPE_INT },
+ { "name": "source", "type": TYPE_OBJECT }
+ ])
+ [/gdscript]
+ [csharp]
+ AddUserSignal("Hurt", new Godot.Collections.Array()
+ {
+ new Godot.Collections.Dictionary()
+ {
+ { "name", "damage" },
+ { "type", (int)Variant.Type.Int }
+ },
+ new Godot.Collections.Dictionary()
+ {
+ { "name", "source" },
+ { "type", (int)Variant.Type.Object }
+ }
+ });
+ [/csharp]
+ [/codeblocks]
</description>
</method>
<method name="call" qualifiers="vararg">
<return type="Variant" />
<param index="0" name="method" type="StringName" />
<description>
- Calls the [param method] on the object and returns the result. This method supports a variable number of arguments, so parameters are passed as a comma separated list.
- [b]Example:[/b]
+ Calls the [param method] on the object and returns the result. This method supports a variable number of arguments, so parameters can be passed as a comma separated list.
[codeblocks]
[gdscript]
var node = Node3D.new()
@@ -120,15 +307,14 @@
node.Call("rotate", new Vector3(1f, 0f, 0f), 1.571f);
[/csharp]
[/codeblocks]
- [b]Note:[/b] In C#, the method name must be specified as snake_case if it is defined by a built-in Godot node. This doesn't apply to user-defined methods where you should use the same convention as in the C# source (typically PascalCase).
+ [b]Note:[/b] In C#, [param method] must be in snake_case when referring to built-in Godot methods. Prefer using the names exposed in the [code]MethodName[/code] class to avoid allocating a new [StringName] on each call.
</description>
</method>
<method name="call_deferred" qualifiers="vararg">
<return type="Variant" />
<param index="0" name="method" type="StringName" />
<description>
- Calls the [param method] on the object during idle time. This method supports a variable number of arguments, so parameters are passed as a comma separated list.
- [b]Example:[/b]
+ Calls the [param method] on the object during idle time. This method supports a variable number of arguments, so parameters can be passed as a comma separated list.
[codeblocks]
[gdscript]
var node = Node3D.new()
@@ -139,7 +325,7 @@
node.CallDeferred("rotate", new Vector3(1f, 0f, 0f), 1.571f);
[/csharp]
[/codeblocks]
- [b]Note:[/b] In C#, the method name must be specified as snake_case if it is defined by a built-in Godot node. This doesn't apply to user-defined methods where you should use the same convention as in the C# source (typically PascalCase).
+ [b]Note:[/b] In C#, [param method] must be in snake_case when referring to built-in Godot methods. Prefer using the names exposed in the [code]MethodName[/code] class to avoid allocating a new [StringName] on each call.
</description>
</method>
<method name="callv">
@@ -147,7 +333,7 @@
<param index="0" name="method" type="StringName" />
<param index="1" name="arg_array" type="Array" />
<description>
- Calls the [param method] on the object and returns the result. Contrarily to [method call], this method does not support a variable number of arguments but expects all parameters to be via a single [Array].
+ Calls the [param method] on the object and returns the result. Unlike [method call], this method expects all parameters to be contained inside [param arg_array].
[codeblocks]
[gdscript]
var node = Node3D.new()
@@ -158,12 +344,13 @@
node.Callv("rotate", new Godot.Collections.Array { new Vector3(1f, 0f, 0f), 1.571f });
[/csharp]
[/codeblocks]
+ [b]Note:[/b] In C#, [param method] must be in snake_case when referring to built-in Godot methods. Prefer using the names exposed in the [code]MethodName[/code] class to avoid allocating a new [StringName] on each call
</description>
</method>
<method name="can_translate_messages" qualifiers="const">
<return type="bool" />
<description>
- Returns [code]true[/code] if the object can translate strings. See [method set_message_translation] and [method tr].
+ Returns [code]true[/code] if the object is allowed to translate messages with [method tr] and [method tr_n]. See also [method set_message_translation].
</description>
</method>
<method name="connect">
@@ -172,23 +359,23 @@
<param index="1" name="callable" type="Callable" />
<param index="2" name="flags" type="int" default="0" />
<description>
- Connects a [param signal] to a [param callable]. Use [param flags] 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.
+ Connects a [param signal] by name to a [param callable]. Optional [param flags] can be also added to configure the connection's behavior (see [enum ConnectFlags] constants).
+ A signal can only be connected once to the same [Callable]. If the signal is already connected, this method returns [constant ERR_INVALID_PARAMETER] and pushes an error message, unless the signal is connected with [constant CONNECT_REFERENCE_COUNTED]. To prevent this, use [method is_connected] first to check for existing connections.
+ If the [param callable]'s object is freed, the connection will be lost.
[b]Examples with recommended syntax:[/b]
- Connecting signals is one of the most common operations in Godot and the API gives many options to do so, which are described further down. The code block below shows the recommended approach for both GDScript and C#.
+ Connecting signals is one of the most common operations in Godot and the API gives many options to do so, which are described further down. The code block below shows the recommended approach.
[codeblocks]
[gdscript]
func _ready():
var button = Button.new()
- # `button_down` here is a Signal object, and we thus call the Signal.connect() method,
- # not Object.connect(). See discussion below for a more in-depth overview of the API.
+ # `button_down` here is a Signal variant type, and we thus call the Signal.connect() method, not Object.connect().
+ # See discussion below for a more in-depth overview of the API.
button.button_down.connect(_on_button_down)
- # This assumes that a `Player` class exists which defines a `hit` signal.
+ # This assumes that a `Player` class exists, which defines a `hit` signal.
var player = Player.new()
- # We use Signal.connect() again, and we also use the Callable.bind() method which
- # returns a new Callable with the parameter binds.
+ # We use Signal.connect() again, and we also use the Callable.bind() method,
+ # which returns a new Callable with the parameter binds.
player.hit.connect(_on_player_hit.bind("sword", 100))
func _on_button_down():
@@ -204,7 +391,7 @@
// C# supports passing signals as events, so we can use this idiomatic construct:
button.ButtonDown += OnButtonDown;
- // This assumes that a `Player` class exists which defines a `Hit` signal.
+ // This assumes that a `Player` class exists, which defines a `Hit` signal.
var player = new Player();
// Signals as events (`player.Hit += OnPlayerHit;`) do not support argument binding. You have to use:
player.Hit.Connect(OnPlayerHit, new Godot.Collections.Array {"sword", 100 });
@@ -261,44 +448,41 @@
}
[/csharp]
[/codeblocks]
- While all options have the same outcome ([code]button[/code]'s [signal BaseButton.button_down] signal will be connected to [code]_on_button_down[/code]), option 3 offers the best validation: it will print a compile-time error if either the [code]button_down[/code] signal or the [code]_on_button_down[/code] callable are undefined. On the other hand, option 2 only relies on string names and will only be able to validate either names at runtime: it will print a runtime error if [code]"button_down"[/code] doesn't correspond to a signal, or if [code]"_on_button_down"[/code] is not a registered method in the object [code]self[/code]. The main reason for using options 1, 2, or 4 would be if you actually need to use strings (e.g. to connect signals programmatically based on strings read from a configuration file). Otherwise, option 3 is the recommended (and fastest) method.
- [b]Parameter bindings and passing:[/b]
- For legacy or language-specific reasons, there are also several ways to bind parameters to signals. One can pass a [code]binds[/code] [Array] to [method Object.connect] or [method Signal.connect], or use the recommended [method Callable.bind] method to create a new callable from an existing one, with the given parameter binds.
- One can also pass additional parameters when emitting the signal with [method emit_signal]. The examples below show the relationship between those two types of parameters.
+ While all options have the same outcome ([code]button[/code]'s [signal BaseButton.button_down] signal will be connected to [code]_on_button_down[/code]), [b]option 3[/b] offers the best validation: it will print a compile-time error if either the [code]button_down[/code] [Signal] or the [code]_on_button_down[/code] [Callable] are not defined. On the other hand, [b]option 2[/b] only relies on string names and will only be able to validate either names at runtime: it will print a runtime error if [code]"button_down"[/code] doesn't correspond to a signal, or if [code]"_on_button_down"[/code] is not a registered method in the object [code]self[/code]. The main reason for using options 1, 2, or 4 would be if you actually need to use strings (e.g. to connect signals programmatically based on strings read from a configuration file). Otherwise, option 3 is the recommended (and fastest) method.
+ [b]Binding and passing parameters:[/b]
+ The syntax to bind parameters is through [method Callable.bind], which returns a copy of the [Callable] with its parameters bound.
+ When calling [method emit_signal], the signal parameters can be also passed. The examples below show the relationship between these signal parameters and bound parameters.
[codeblocks]
[gdscript]
func _ready():
- # This assumes that a `Player` class exists which defines a `hit` signal.
+ # This assumes that a `Player` class exists, which defines a `hit` signal.
var player = Player.new()
- # Option 1: Using Callable.bind().
player.hit.connect(_on_player_hit.bind("sword", 100))
- # Option 2: Using a `binds` Array in Signal.connect() (same syntax for Object.connect()).
- player.hit.connect(_on_player_hit, ["sword", 100])
# Parameters added when emitting the signal are passed first.
player.emit_signal("hit", "Dark lord", 5)
- # Four arguments, since we pass two when emitting (hit_by, level)
- # and two when connecting (weapon_type, damage).
+ # We pass two arguments when emitting (`hit_by`, `level`),
+ # and bind two more arguments when connecting (`weapon_type`, `damage`).
func _on_player_hit(hit_by, level, weapon_type, damage):
print("Hit by %s (level %d) with weapon %s for %d damage." % [hit_by, level, weapon_type, damage])
[/gdscript]
[csharp]
public override void _Ready()
{
- // This assumes that a `Player` class exists which defines a `Hit` signal.
+ // This assumes that a `Player` class exists, which defines a `Hit` signal.
var player = new Player();
// Option 1: Using Callable.Bind(). This way we can still use signals as events.
player.Hit += OnPlayerHit.Bind("sword", 100);
- // Option 2: Using a `binds` Array in Signal.Connect() (same syntax for Object.Connect()).
+ // Option 2: Using a `binds` Array in Signal.Connect().
player.Hit.Connect(OnPlayerHit, new Godot.Collections.Array{ "sword", 100 });
// Parameters added when emitting the signal are passed first.
player.EmitSignal("hit", "Dark lord", 5);
}
- // Four arguments, since we pass two when emitting (hitBy, level)
- // and two when connecting (weaponType, damage).
+ // We pass two arguments when emitting (`hit_by`, `level`),
+ // and bind two more arguments when connecting (`weapon_type`, `damage`).
private void OnPlayerHit(string hitBy, int level, string weaponType, int damage)
{
GD.Print(String.Format("Hit by {0} (level {1}) with weapon {2} for {3} damage.", hitBy, level, weaponType, damage));
@@ -312,57 +496,68 @@
<param index="0" name="signal" type="StringName" />
<param index="1" name="callable" type="Callable" />
<description>
- Disconnects a [param signal] from a given [param callable].
- If you try to disconnect a connection that does not exist, the method will print an error. Use [method is_connected] to ensure that the connection exists.
+ Disconnects a [param signal] by name from a given [param callable]. If the connection does not exist, generates an error. Use [method is_connected] to make sure that the connection exists.
</description>
</method>
<method name="emit_signal" qualifiers="vararg">
<return type="int" enum="Error" />
<param index="0" name="signal" type="StringName" />
<description>
- Emits the given [param signal]. The signal must exist, so it should be a built-in signal of this class or one of its parent classes, or a user-defined signal. This method supports a variable number of arguments, so parameters are passed as a comma separated list.
- [b]Example:[/b]
+ Emits the given [param signal] by name. The signal must exist, so it should be a built-in signal of this class or one of its inherited classes, or a user-defined signal (see [method add_user_signal]). This method supports a variable number of arguments, so parameters can be passed as a comma separated list.
+ Returns [constant ERR_UNAVAILABLE] if [param signal] does not exist or the parameters are invalid.
[codeblocks]
[gdscript]
emit_signal("hit", "sword", 100)
emit_signal("game_over")
[/gdscript]
[csharp]
- EmitSignal("hit", "sword", 100);
- EmitSignal("game_over");
+ EmitSignal("Hit", "sword", 100);
+ EmitSignal("GameOver");
[/csharp]
[/codeblocks]
+ [b]Note:[/b] In C#, [param signal] must be in snake_case when referring to built-in Godot signals. Prefer using the names exposed in the [code]SignalName[/code] class to avoid allocating a new [StringName] on each call.
</description>
</method>
<method name="free">
<return type="void" />
<description>
- Deletes the object from memory. Any pre-existing reference to the freed object will become invalid, e.g. [code]is_instance_valid(object)[/code] will return [code]false[/code].
+ Deletes the object from memory. Pre-existing references to the object become invalid, and any attempt to access them will result in a run-time error. Checking the references with [method @GlobalScope.is_instance_valid] will return [code]false[/code].
</description>
</method>
<method name="get" qualifiers="const">
<return type="Variant" />
<param index="0" name="property" type="StringName" />
<description>
- Returns the [Variant] value of the given [param property]. If the [param property] doesn't exist, this will return [code]null[/code].
- [b]Note:[/b] In C#, the property name must be specified as snake_case if it is defined by a built-in Godot node. This doesn't apply to user-defined properties where you should use the same convention as in the C# source (typically PascalCase).
+ Returns the [Variant] value of the given [param property]. If the [param property] does not exist, this method returns [code]null[/code].
+ [codeblocks]
+ [gdscript]
+ var node = Node2D.new()
+ node.rotation = 1.5
+ var a = node.get("rotation") # a is 1.5
+ [/gdscript]
+ [csharp]
+ var node = new Node2D();
+ node.Rotation = 1.5f;
+ var a = node.Get("rotation"); // a is 1.5
+ [/csharp]
+ [/codeblocks]
+ [b]Note:[/b] In C#, [param property] must be in snake_case when referring to built-in Godot properties. Prefer using the names exposed in the [code]PropertyName[/code] class to avoid allocating a new [StringName] on each call.
</description>
</method>
<method name="get_class" qualifiers="const">
<return type="String" />
<description>
- Returns the object's class as a [String]. See also [method is_class].
- [b]Note:[/b] [method get_class] does not take [code]class_name[/code] declarations into account. If the object has a [code]class_name[/code] defined, the base class name will be returned instead.
+ Returns the object's built-in class name, as a [String]. See also [method is_class].
+ [b]Note:[/b] This method ignores [code]class_name[/code] declarations. If this object's script has defined a [code]class_name[/code], the base, built-in class name is returned instead.
</description>
</method>
<method name="get_incoming_connections" qualifiers="const">
<return type="Dictionary[]" />
<description>
- Returns an [Array] of dictionaries with information about signals that are connected to the object.
- Each [Dictionary] contains three String entries:
- - [code]source[/code] is a reference to the signal emitter.
- - [code]signal_name[/code] is the name of the connected signal.
- - [code]method_name[/code] is the name of the method to which the signal is connected.
+ Returns an [Array] of signal connections received by this object. Each connection is represented as a [Dictionary] that contains three entries:
+ - [code]signal[/code] is a reference to the [Signal];
+ - [code]callable[/code] is a reference to the [Callable];
+ - [code]flags[/code] is a combination of [enum ConnectFlags].
</description>
</method>
<method name="get_indexed" qualifiers="const">
@@ -371,14 +566,28 @@
<description>
Gets the object's property indexed by the given [param property_path]. The path should be a [NodePath] relative to the current object and can use the colon character ([code]:[/code]) to access nested properties.
[b]Examples:[/b] [code]"position:x"[/code] or [code]"material:next_pass:blend_mode"[/code].
- [b]Note:[/b] Even though the method takes [NodePath] argument, it doesn't support actual paths to [Node]s in the scene tree, only colon-separated sub-property paths. For the purpose of nodes, use [method Node.get_node_and_resource] instead.
+ [codeblocks]
+ [gdscript]
+ var node = Node2D.new()
+ node.position = Vector2(5, -10)
+ var a = node.get_indexed("position") # a is Vector2(5, -10)
+ var b = node.get_indexed("position:y") # b is -10
+ [/gdscript]
+ [csharp]
+ var node = new Node2D();
+ node.Position = new Vector2(5, -10);
+ var a = node.GetIndexed("position"); // a is Vector2(5, -10)
+ var b = node.GetIndexed("position:y"); // b is -10
+ [/csharp]
+ [/codeblocks]
+ [b]Note:[/b] In C#, [param property_path] must be in snake_case when referring to built-in Godot properties.
+ [b]Note:[/b] This method does not support actual paths to nodes in the [SceneTree], only sub-property paths. In the context of nodes, use [method Node.get_node_and_resource] instead.
</description>
</method>
<method name="get_instance_id" qualifiers="const">
<return type="int" />
<description>
- Returns the object's unique instance ID.
- This ID can be saved in [EncodedObjectAsID], and can be used to retrieve the object instance with [method @GlobalScope.instance_from_id].
+ Returns the object's unique instance ID. This ID can be saved in [EncodedObjectAsID], and can be used to retrieve this object instance with [method @GlobalScope.instance_from_id].
</description>
</method>
<method name="get_meta" qualifiers="const">
@@ -386,47 +595,62 @@
<param index="0" name="name" type="StringName" />
<param index="1" name="default" type="Variant" default="null" />
<description>
- Returns the object's metadata entry for the given [param name].
- Throws error if the entry does not exist, unless [param default] is not [code]null[/code] (in which case the default value will be returned). See also [method has_meta], [method set_meta] and [method remove_meta].
- [b]Note:[/b] Metadata that has a [param name] starting with an underscore ([code]_[/code]) is considered editor-only. Editor-only metadata is not displayed in the Inspector and should not be edited.
+ Returns the object's metadata value for the given entry [param name]. If the entry does not exist, returns [param default]. If [param default] is [code]null[/code], an error is also generated.
+ [b]Note:[/b] Metadata that has a [param name] starting with an underscore ([code]_[/code]) is considered editor-only. Editor-only metadata is not displayed in the Inspector dock and should not be edited.
</description>
</method>
<method name="get_meta_list" qualifiers="const">
<return type="PackedStringArray" />
<description>
- Returns the object's metadata as a [PackedStringArray].
+ Returns the object's metadata entry names as a [PackedStringArray].
</description>
</method>
<method name="get_method_list" qualifiers="const">
<return type="Dictionary[]" />
<description>
- Returns the object's methods and their signatures as an [Array].
+ Returns this object's methods and their signatures as an [Array] of dictionaries. Each [Dictionary] contains the following entries:
+ - [code]name[/code] is the name of the method, as a [String];
+ - [code]args[/code] is an [Array] of dictionaries representing the arguments;
+ - [code]default_args[/code] is the default arguments as an [Array] of variants;
+ - [code]flags[/code] is a combination of [enum MethodFlags];
+ - [code]id[/code] is the method's internal identifier [int];
+ - [code]return[/code] is the returned value, as a [Dictionary];
+ [b]Note:[/b] The dictionaries of [code]args[/code] and [code]return[/code] are formatted identically to the results of [method get_property_list], although not all entries are used.
</description>
</method>
<method name="get_property_list" qualifiers="const">
<return type="Dictionary[]" />
<description>
- Returns the object's property list as an [Array] of dictionaries.
- Each property's [Dictionary] contain at least [code]name: String[/code] and [code]type: int[/code] (see [enum Variant.Type]) entries. Optionally, it can also include [code]hint: int[/code] (see [enum PropertyHint]), [code]hint_string: String[/code], and [code]usage: int[/code] (see [enum PropertyUsageFlags]).
+ Returns the object's property list as an [Array] of dictionaries. Each [Dictionary] contains the following entries:
+ - [code]name[/code] is the property's name, as a [String];
+ - [code]class_name[/code] is an empty [StringName], unless the property is [constant TYPE_OBJECT] and it inherits from a class;
+ - [code]type[/code] is the property's type, as an [int] (see [enum Variant.Type]);
+ - [code]hint[/code] is [i]how[/i] the property is meant to be edited (see [enum PropertyHint]);
+ - [code]hint_string[/code] depends on the hint (see [enum PropertyHint]);
+ - [code]usage[/code] is a combination of [enum PropertyUsageFlags].
</description>
</method>
<method name="get_script" qualifiers="const">
<return type="Variant" />
<description>
- Returns the object's [Script] instance, or [code]null[/code] if none is assigned.
+ Returns the object's [Script] instance, or [code]null[/code] if no script is attached.
</description>
</method>
<method name="get_signal_connection_list" qualifiers="const">
<return type="Dictionary[]" />
<param index="0" name="signal" type="StringName" />
<description>
- Returns an [Array] of connections for the given [param signal].
+ Returns an [Array] of connections for the given [param signal] name. Each connection is represented as a [Dictionary] that contains three entries:
+ - [code]signal[/code] is a reference to the [Signal];
+ - [code]callable[/code] is a reference to the [Callable];
+ - [code]flags[/code] is a combination of [enum ConnectFlags].
</description>
</method>
<method name="get_signal_list" qualifiers="const">
<return type="Dictionary[]" />
<description>
- Returns the list of signals as an [Array] of dictionaries.
+ Returns the list of existing signals as an [Array] of dictionaries.
+ [b]Note:[/b] Due of the implementation, each [Dictionary] is formatted very similarly to the returned values of [method get_method_list].
</description>
</method>
<method name="has_meta" qualifiers="const">
@@ -434,34 +658,36 @@
<param index="0" name="name" type="StringName" />
<description>
Returns [code]true[/code] if a metadata entry is found with the given [param name]. See also [method get_meta], [method set_meta] and [method remove_meta].
- [b]Note:[/b] Metadata that has a [param name] starting with an underscore ([code]_[/code]) is considered editor-only. Editor-only metadata is not displayed in the Inspector and should not be edited.
+ [b]Note:[/b] Metadata that has a [param name] starting with an underscore ([code]_[/code]) is considered editor-only. Editor-only metadata is not displayed in the Inspector and should not be edited, although it can still be found by this method.
</description>
</method>
<method name="has_method" qualifiers="const">
<return type="bool" />
<param index="0" name="method" type="StringName" />
<description>
- Returns [code]true[/code] if the object contains the given [param method].
+ Returns [code]true[/code] if the the given [param method] name exists in the object.
+ [b]Note:[/b] In C#, [param method] must be in snake_case when referring to built-in Godot methods. Prefer using the names exposed in the [code]MethodName[/code] class to avoid allocating a new [StringName] on each call.
</description>
</method>
<method name="has_signal" qualifiers="const">
<return type="bool" />
<param index="0" name="signal" type="StringName" />
<description>
- Returns [code]true[/code] if the given [param signal] exists.
+ Returns [code]true[/code] if the given [param signal] name exists in the object.
+ [b]Note:[/b] In C#, [param signal] must be in snake_case when referring to built-in Godot methods. Prefer using the names exposed in the [code]SignalName[/code] class to avoid allocating a new [StringName] on each call.
</description>
</method>
<method name="has_user_signal" qualifiers="const">
<return type="bool" />
<param index="0" name="signal" type="StringName" />
<description>
- Returns [code]true[/code] if the given user-defined [param signal] exists. Only signals added using [method add_user_signal] are taken into account.
+ Returns [code]true[/code] if the given user-defined [param signal] name exists. Only signals added with [method add_user_signal] are included.
</description>
</method>
<method name="is_blocking_signals" qualifiers="const">
<return type="bool" />
<description>
- Returns [code]true[/code] if signal emission blocking is enabled.
+ Returns [code]true[/code] if the object is blocking its signals from being emitted. See [method set_block_signals].
</description>
</method>
<method name="is_class" qualifiers="const">
@@ -469,7 +695,21 @@
<param index="0" name="class" type="String" />
<description>
Returns [code]true[/code] if the object inherits from the given [param class]. See also [method get_class].
- [b]Note:[/b] [method is_class] does not take [code]class_name[/code] declarations into account. If the object has a [code]class_name[/code] defined, [method is_class] will return [code]false[/code] for that name.
+ [codeblocks]
+ [gdscript]
+ var sprite2d = Sprite2D.new()
+ sprite2d.is_class("Sprite2D") # Returns true
+ sprite2d.is_class("Node") # Returns true
+ sprite2d.is_class("Node3D") # Returns false
+ [/gdscript]
+ [csharp]
+ var sprite2d = new Sprite2D();
+ sprite2d.IsClass("Sprite2D"); // Returns true
+ sprite2d.IsClass("Node"); // Returns true
+ sprite2d.IsClass("Node3D"); // Returns false
+ [/csharp]
+ [/codeblocks]
+ [b]Note:[/b] This method ignores [code]class_name[/code] declarations in the object's script.
</description>
</method>
<method name="is_connected" qualifiers="const">
@@ -477,7 +717,8 @@
<param index="0" name="signal" type="StringName" />
<param index="1" name="callable" type="Callable" />
<description>
- Returns [code]true[/code] if a connection exists for a given [param signal] and [param callable].
+ Returns [code]true[/code] if a connection exists between the given [param signal] name and [param callable].
+ [b]Note:[/b] In C#, [param signal] must be in snake_case when referring to built-in Godot methods. Prefer using the names exposed in the [code]SignalName[/code] class to avoid allocating a new [StringName] on each call.
</description>
</method>
<method name="is_queued_for_deletion" qualifiers="const">
@@ -491,21 +732,59 @@
<param index="0" name="what" type="int" />
<param index="1" name="reversed" type="bool" default="false" />
<description>
- Send a given notification to the object, which will also trigger a call to the [method _notification] method of all classes that the object inherits from.
- If [param reversed] is [code]true[/code], [method _notification] is called first on the object's own class, and then up to its successive parent classes. If [param reversed] is [code]false[/code], [method _notification] is called first on the highest ancestor ([Object] itself), and then down to its successive inheriting classes.
+ Sends the given [param what] notification to all classes inherited by the object, triggering calls to [method _notification], starting from the highest ancestor (the [Object] class) and going down to the object's script.
+ If [param reversed] is [code]true[/code], the call order is reversed.
+ [codeblocks]
+ [gdscript]
+ var player = Node2D.new()
+ player.set_script(load("res://player.gd"))
+
+ player.notification(NOTIFICATION_ENTER_TREE)
+ # The call order is Object -&gt; Node -&gt; Node2D -&gt; player.gd.
+
+ player.notification(NOTIFICATION_ENTER_TREE, true)
+ # The call order is player.gd -&gt; Node2D -&gt; Node -&gt; Object.
+ [/gdscript]
+ [csharp]
+ var player = new Node2D();
+ player.SetScript(GD.Load("res://player.gd"));
+
+ player.Notification(NotificationEnterTree);
+ // The call order is Object -&gt; Node -&gt; Node2D -&gt; player.gd.
+
+ player.notification(NotificationEnterTree, true);
+ // The call order is player.gd -&gt; Node2D -&gt; Node -&gt; Object.
+ [/csharp]
+ [/codeblocks]
</description>
</method>
<method name="notify_property_list_changed">
<return type="void" />
<description>
- Notify the editor that the property list has changed by emitting the [signal property_list_changed] signal, so that editor plugins can take the new values into account.
+ Emits the [signal property_list_changed] signal. This is mainly used to refresh the editor, so that the Inspector and editor plugins are properly updated.
+ </description>
+ </method>
+ <method name="property_can_revert" qualifiers="const">
+ <return type="bool" />
+ <param index="0" name="property" type="StringName" />
+ <description>
+ Returns [code]true[/code] if the given [param property] has a custom default value. Use [method property_get_revert] to get the [param property]'s default value.
+ [b]Note:[/b] This method is used by the Inspector dock to display a revert icon. The object must implement [method _property_can_revert] to customize the default value. If [method _property_can_revert] is not implemented, this method returns [code]false[/code].
+ </description>
+ </method>
+ <method name="property_get_revert" qualifiers="const">
+ <return type="Variant" />
+ <param index="0" name="property" type="StringName" />
+ <description>
+ Returns the custom default value of the given [param property]. Use [method property_can_revert] to check if the [param property] has a custom default value.
+ [b]Note:[/b] This method is used by the Inspector dock to display a revert icon. The object must implement [method _property_get_revert] to customize the default value. If [method _property_get_revert] is not implemented, this method returns [code]null[/code].
</description>
</method>
<method name="remove_meta">
<return type="void" />
<param index="0" name="name" type="StringName" />
<description>
- Removes a given entry from the object's metadata. See also [method has_meta], [method get_meta] and [method set_meta].
+ Removes the given entry [param name] from the object's metadata. See also [method has_meta], [method get_meta] and [method set_meta].
[b]Note:[/b] Metadata that has a [param name] starting with an underscore ([code]_[/code]) is considered editor-only. Editor-only metadata is not displayed in the Inspector and should not be edited.
</description>
</method>
@@ -514,15 +793,27 @@
<param index="0" name="property" type="StringName" />
<param index="1" name="value" type="Variant" />
<description>
- Assigns a new value to the given property. If the [param property] does not exist or the given value's type doesn't match, nothing will happen.
- [b]Note:[/b] In C#, the property name must be specified as snake_case if it is defined by a built-in Godot node. This doesn't apply to user-defined properties where you should use the same convention as in the C# source (typically PascalCase).
+ Assigns [param value] to the given [param property]. If the property does not exist or the given [param value]'s type doesn't match, nothing happens.
+ [codeblocks]
+ [gdscript]
+ var node = Node2D.new()
+ node.set("global_scale", Vector2(8, 2.5))
+ print(node.global_scale) # Prints (8, 2.5)
+ [/gdscript]
+ [csharp]
+ var node = new Node2D();
+ node.Set("global_scale", new Vector2(8, 2.5));
+ GD.Print(node.GlobalScale); // Prints Vector2(8, 2.5)
+ [/csharp]
+ [/codeblocks]
+ [b]Note:[/b] In C#, [param property] must be in snake_case when referring to built-in Godot properties. Prefer using the names exposed in the [code]PropertyName[/code] class to avoid allocating a new [StringName] on each call.
</description>
</method>
<method name="set_block_signals">
<return type="void" />
<param index="0" name="enable" type="bool" />
<description>
- If set to [code]true[/code], signal emission is blocked.
+ If set to [code]true[/code], the object becomes unable to emit signals. As such, [method emit_signal] and signal connections will not work, until it is set to [code]false[/code].
</description>
</method>
<method name="set_deferred">
@@ -530,8 +821,30 @@
<param index="0" name="property" type="StringName" />
<param index="1" name="value" type="Variant" />
<description>
- Assigns a new value to the given property, after the current frame's physics step. This is equivalent to calling [method set] via [method call_deferred], i.e. [code]call_deferred("set", property, value)[/code].
- [b]Note:[/b] In C#, the property name must be specified as snake_case if it is defined by a built-in Godot node. This doesn't apply to user-defined properties where you should use the same convention as in the C# source (typically PascalCase).
+ Assigns [param value] to the given [param property], after the current frame's physics step. This is equivalent to calling [method set] through [method call_deferred].
+ [codeblocks]
+ [gdscript]
+ var node = Node2D.new()
+ add_child(node)
+
+ node.rotation = 45.0
+ node.set_deferred("rotation", 90.0)
+ print(node.rotation) # Prints 45.0
+
+ await get_tree().process_frame
+ print(node.rotation) # Prints 90.0
+ [/gdscript]
+ [csharp]
+ var node = new Node2D();
+ node.Rotation = 45f;
+ node.SetDeferred("rotation", 90f);
+ GD.Print(node.Rotation); // Prints 45.0
+
+ await ToSignal(GetTree(), SceneTree.SignalName.ProcessFrame);
+ GD.Print(node.Rotation); // Prints 90.0
+ [/csharp]
+ [/codeblocks]
+ [b]Note:[/b] In C#, [param property] must be in snake_case when referring to built-in Godot properties. Prefer using the names exposed in the [code]PropertyName[/code] class to avoid allocating a new [StringName] on each call.
</description>
</method>
<method name="set_indexed">
@@ -539,29 +852,29 @@
<param index="0" name="property_path" type="NodePath" />
<param index="1" name="value" type="Variant" />
<description>
- Assigns a new value to the property identified by the [param property_path]. The path should be a [NodePath] relative to the current object and can use the colon character ([code]:[/code]) to access nested properties.
- [b]Example:[/b]
+ Assigns a new [param value] to the property identified by the [param property_path]. The path should be a [NodePath] relative to this object, and can use the colon character ([code]:[/code]) to access nested properties.
[codeblocks]
[gdscript]
var node = Node2D.new()
node.set_indexed("position", Vector2(42, 0))
node.set_indexed("position:y", -10)
- print(node.position) # (42, -10)
+ print(node.position) # Prints (42, -10)
[/gdscript]
[csharp]
var node = new Node2D();
node.SetIndexed("position", new Vector2(42, 0));
node.SetIndexed("position:y", -10);
- GD.Print(node.Position); // (42, -10)
+ GD.Print(node.Position); // Prints (42, -10)
[/csharp]
[/codeblocks]
+ [b]Note:[/b] In C#, [param property_path] must be in snake_case when referring to built-in Godot properties.
</description>
</method>
<method name="set_message_translation">
<return type="void" />
<param index="0" name="enable" type="bool" />
<description>
- Defines whether the object can translate strings (with calls to [method tr]). Enabled by default.
+ If set to [code]true[/code], allows the object to translate messages with [method tr] and [method tr_n]. Enabled by default. See also [method can_translate_messages].
</description>
</method>
<method name="set_meta">
@@ -569,24 +882,23 @@
<param index="0" name="name" type="StringName" />
<param index="1" name="value" type="Variant" />
<description>
- Adds, changes or removes a given entry in the object's metadata. Metadata are serialized and can take any [Variant] value.
- To remove a given entry from the object's metadata, use [method remove_meta]. Metadata is also removed if its value is set to [code]null[/code]. This means you can also use [code]set_meta("name", null)[/code] to remove metadata for [code]"name"[/code]. See also [method has_meta] and [method get_meta].
- [b]Note:[/b] Metadata that has a [param name] starting with an underscore ([code]_[/code]) is considered editor-only. Editor-only metadata is not displayed in the Inspector and should not be edited.
+ Adds or changes the entry [param name] inside the object's metadata. The metadata [param value] can be any [Variant], although some types cannot be serialised correctly.
+ If [param value] is [code]null[/code], the entry is removed. This is the equivalent of using [method remove_meta]. See also [method has_meta] and [method get_meta].
+ [b]Note:[/b] Metadata that has a [param name] starting with an underscore ([code]_[/code]) is considered editor-only. Editor-only metadata is not displayed in the Inspector dock and should not be edited.
</description>
</method>
<method name="set_script">
<return type="void" />
<param index="0" name="script" type="Variant" />
<description>
- Assigns a script to the object. Each object can have a single script assigned to it, which are used to extend its functionality.
- If the object already had a script, the previous script instance will be freed and its variables and state will be lost. The new script's [method _init] method will be called.
+ Attaches [param script] to the object, and instantiates it. As a result, the script's [method _init] is called. A [Script] is used to extend the object's functionality.
+ If a script already exists, its instance is detached, and its property values and state are lost. Built-in property values are still kept.
</description>
</method>
<method name="to_string">
<return type="String" />
<description>
- Returns a [String] representing the object. If not overridden, defaults to [code]"[ClassName:RID]"[/code].
- Override the method [method _to_string] to customize the [String] representation.
+ Returns a [String] representing the object. Defaults to [code]"&lt;ClassName#RID&gt;"[/code]. Override [method _to_string] to customize the string representation of the object.
</description>
</method>
<method name="tr" qualifiers="const">
@@ -594,9 +906,9 @@
<param index="0" name="message" type="StringName" />
<param index="1" name="context" type="StringName" default="&quot;&quot;" />
<description>
- Translates a message using translation catalogs configured in the Project Settings. An additional context could be used to specify the translation context.
- Only works if message translation is enabled (which it is by default), otherwise it returns the [param message] unchanged. See [method set_message_translation].
- See [url=$DOCS_URL/tutorials/i18n/internationalizing_games.html]Internationalizing games[/url] for examples of the usage of this method.
+ Translates a [param message], using the translation catalogs configured in the Project Settings. Further [param context] can be specified to help with the translation.
+ If [method can_translate_messages] is [code]false[/code], or no translation is available, this method returns the [param message] without changes. See [method set_message_translation].
+ For detailed examples, see [url=$DOCS_URL/tutorials/i18n/internationalizing_games.html]Internationalizing games[/url].
</description>
</method>
<method name="tr_n" qualifiers="const">
@@ -606,43 +918,45 @@
<param index="2" name="n" type="int" />
<param index="3" name="context" type="StringName" default="&quot;&quot;" />
<description>
- Translates a message involving plurals using translation catalogs configured in the Project Settings. An additional context could be used to specify the translation context.
- Only works if message translation is enabled (which it is by default), otherwise it returns the [param message] or [param plural_message] unchanged. See [method set_message_translation].
- The number [param n] is the number or quantity of the plural object. It will be used to guide the translation system to fetch the correct plural form for the selected language.
- [b]Note:[/b] Negative and floating-point values usually represent physical entities for which singular and plural don't clearly apply. In such cases, use [method tr].
- See [url=$DOCS_URL/tutorials/i18n/localization_using_gettext.html]Localization using gettext[/url] for examples of the usage of this method.
+ Translates a [param message] or [param plural_message], using the translation catalogs configured in the Project Settings. Further [param context] can be specified to help with the translation.
+ If [method can_translate_messages] is [code]false[/code], or no translation is available, this method returns [param message] or [param plural_message], without changes. See [method set_message_translation].
+ The [param n] is the number, or amount, of the message's subject. It is used by the translation system to fetch the correct plural form for the current language.
+ For detailed examples, see [url=$DOCS_URL/tutorials/i18n/localization_using_gettext.html]Localization using gettext[/url].
+ [b]Note:[/b] Negative and [float] numbers may not properly apply to some countable subjects. It's recommended handling these cases with [method tr].
</description>
</method>
</methods>
<signals>
<signal name="property_list_changed">
<description>
+ Emitted when [method notify_property_list_changed] is called.
</description>
</signal>
<signal name="script_changed">
<description>
- Emitted whenever the object's script is changed.
+ Emitted when the object's script is changed.
+ [b]Note:[/b] When this signal is emitted, the new script is not initialized yet. If you need to access the new script, defer connections to this signal with [constant CONNECT_DEFERRED].
</description>
</signal>
</signals>
<constants>
<constant name="NOTIFICATION_POSTINITIALIZE" value="0">
- Called right when the object is initialized. Not available in script.
+ Notification received when the object is initialized, before its script is attached. Used internally.
</constant>
<constant name="NOTIFICATION_PREDELETE" value="1">
- Called before the object is about to be deleted.
+ Notification received when the object is about to be deleted. Can act as the deconstructor of some programming languages.
</constant>
<constant name="CONNECT_DEFERRED" value="1" enum="ConnectFlags">
- Connects a signal in deferred mode. This way, signal emissions are stored in a queue, then set on idle time.
+ Deferred connections trigger their [Callable]s on idle time, rather than instantly.
</constant>
<constant name="CONNECT_PERSIST" value="2" enum="ConnectFlags">
- Persisting connections are saved when the object is serialized to file.
+ Persisting connections are stored when the object is serialized (such as when using [method PackedScene.pack]). In the editor, connections created through the Node dock are always persisting.
</constant>
<constant name="CONNECT_ONE_SHOT" value="4" enum="ConnectFlags">
One-shot connections disconnect themselves after emission.
</constant>
<constant name="CONNECT_REFERENCE_COUNTED" value="8" enum="ConnectFlags">
- Connect a signal as reference-counted. This means that a given signal can be connected several times to the same target, and will only be fully disconnected once no references are left.
+ Reference-counted connections can be assigned to the same [Callable] multiple times. Each disconnection decreases the internal counter. The signal fully disconnects only when the counter reaches 0.
</constant>
</constants>
</class>
diff --git a/doc/classes/OfflineMultiplayerPeer.xml b/doc/classes/OfflineMultiplayerPeer.xml
new file mode 100644
index 0000000000..5e15992d54
--- /dev/null
+++ b/doc/classes/OfflineMultiplayerPeer.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="OfflineMultiplayerPeer" inherits="MultiplayerPeer" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+ <brief_description>
+ A [MultiplayerPeer] which is always connected and acts as a server.
+ </brief_description>
+ <description>
+ This is the default [member MultiplayerAPI.multiplayer_peer] for the [member Node.multiplayer]. It mimics the behavior of a server with no peers connected.
+ This means that the [SceneTree] will act as the multiplayer authority by default. Calls to [method MultiplayerAPI.is_server] will return [code]true[/code], and calls to [method MultiplayerAPI.get_unique_id] will return [constant MultiplayerPeer.TARGET_PEER_SERVER].
+ </description>
+ <tutorials>
+ </tutorials>
+</class>
diff --git a/doc/classes/OmniLight3D.xml b/doc/classes/OmniLight3D.xml
index 193ae8deeb..f71c81e713 100644
--- a/doc/classes/OmniLight3D.xml
+++ b/doc/classes/OmniLight3D.xml
@@ -20,7 +20,7 @@
<member name="omni_shadow_mode" type="int" setter="set_shadow_mode" getter="get_shadow_mode" enum="OmniLight3D.ShadowMode" default="1">
See [enum ShadowMode].
</member>
- <member name="shadow_bias" type="float" setter="set_param" getter="get_param" overrides="Light3D" default="0.2" />
+ <member name="shadow_normal_bias" type="float" setter="set_param" getter="get_param" overrides="Light3D" default="1.0" />
</members>
<constants>
<constant name="SHADOW_DUAL_PARABOLOID" value="0" enum="ShadowMode">
diff --git a/doc/classes/OptionButton.xml b/doc/classes/OptionButton.xml
index e63e822648..fdf0fff0fb 100644
--- a/doc/classes/OptionButton.xml
+++ b/doc/classes/OptionButton.xml
@@ -94,6 +94,8 @@
<return type="int" />
<param index="0" name="from_last" type="bool" default="false" />
<description>
+ Returns the index of the first item which is not disabled, or marked as a separator. If [param from_last] is [code]true[/code], the items will be searched in reverse order.
+ Returns [code]-1[/code] if no item is found.
</description>
</method>
<method name="get_selected_id" qualifiers="const">
@@ -111,6 +113,7 @@
<method name="has_selectable_items" qualifiers="const">
<return type="bool" />
<description>
+ Returns [code]true[/code] if this button contains at least one item which is not disabled, or marked as a separator.
</description>
</method>
<method name="is_item_disabled" qualifiers="const">
@@ -124,6 +127,7 @@
<return type="bool" />
<param index="0" name="idx" type="int" />
<description>
+ Returns [code]true[/code] if the item at index [param idx] is marked as a separator.
</description>
</method>
<method name="remove_item">
@@ -259,6 +263,7 @@
</theme_item>
<theme_item name="outline_size" data_type="constant" type="int" default="0">
The size of the text outline.
+ [b]Note:[/b] If using a font with [member FontFile.multichannel_signed_distance_field] enabled, its [member FontFile.msdf_pixel_range] must be set to at least [i]twice[/i] the value of [theme_item outline_size] for outline rendering to look correct. Otherwise, the outline may appear to be cut off earlier than intended.
</theme_item>
<theme_item name="font" data_type="font" type="Font">
[Font] of the [OptionButton]'s text.
diff --git a/doc/classes/PathFollow3D.xml b/doc/classes/PathFollow3D.xml
index ba7207be8f..01275471d0 100644
--- a/doc/classes/PathFollow3D.xml
+++ b/doc/classes/PathFollow3D.xml
@@ -9,6 +9,16 @@
</description>
<tutorials>
</tutorials>
+ <methods>
+ <method name="correct_posture" qualifiers="static">
+ <return type="Transform3D" />
+ <param index="0" name="transform" type="Transform3D" />
+ <param index="1" name="rotation_mode" type="int" enum="PathFollow3D.RotationMode" />
+ <description>
+ Correct the [code]transform[/code]. [code]rotation_mode[/code] implicitly specifies how posture (forward, up and sideway direction) is calculated.
+ </description>
+ </method>
+ </methods>
<members>
<member name="cubic_interp" type="bool" setter="set_cubic_interpolation" getter="get_cubic_interpolation" default="true">
If [code]true[/code], the position between two cached points is interpolated cubically, and linearly otherwise.
@@ -30,6 +40,9 @@
<member name="rotation_mode" type="int" setter="set_rotation_mode" getter="get_rotation_mode" enum="PathFollow3D.RotationMode" default="3">
Allows or forbids rotation on one or more axes, depending on the [enum RotationMode] constants being used.
</member>
+ <member name="tilt_enabled" type="bool" setter="set_tilt_enabled" getter="is_tilt_enabled" default="true">
+ If [code]true[/code], the tilt property of [Curve3D] takes effect.
+ </member>
<member name="v_offset" type="float" setter="set_v_offset" getter="get_v_offset" default="0.0">
The node's offset perpendicular to the curve.
</member>
diff --git a/doc/classes/PhysicalSkyMaterial.xml b/doc/classes/PhysicalSkyMaterial.xml
index 9d303d80e5..a8cfb9abc2 100644
--- a/doc/classes/PhysicalSkyMaterial.xml
+++ b/doc/classes/PhysicalSkyMaterial.xml
@@ -12,27 +12,28 @@
</tutorials>
<members>
<member name="energy_multiplier" type="float" setter="set_energy_multiplier" getter="get_energy_multiplier" default="1.0">
+ The sky's overall brightness multiplier. Higher values result in a brighter sky.
</member>
<member name="ground_color" type="Color" setter="set_ground_color" getter="get_ground_color" default="Color(0.1, 0.07, 0.034, 1)">
Modulates the [Color] on the bottom half of the sky to represent the ground.
</member>
<member name="mie_coefficient" type="float" setter="set_mie_coefficient" getter="get_mie_coefficient" default="0.005">
- Controls the strength of mie scattering for the sky. Mie scattering results from light colliding with larger particles (like water). On earth, mie scattering results in a whitish color around the sun and horizon.
+ Controls the strength of [url=https://en.wikipedia.org/wiki/Mie_scattering]Mie scattering[/url] for the sky. Mie scattering results from light colliding with larger particles (like water). On earth, Mie scattering results in a whitish color around the sun and horizon.
</member>
<member name="mie_color" type="Color" setter="set_mie_color" getter="get_mie_color" default="Color(0.69, 0.729, 0.812, 1)">
- Controls the [Color] of the mie scattering effect. While not physically accurate, this allows for the creation of alien-looking planets.
+ Controls the [Color] of the [url=https://en.wikipedia.org/wiki/Mie_scattering]Mie scattering[/url] effect. While not physically accurate, this allows for the creation of alien-looking planets.
</member>
<member name="mie_eccentricity" type="float" setter="set_mie_eccentricity" getter="get_mie_eccentricity" default="0.8">
- Controls the direction of the mie scattering. A value of [code]1[/code] means that when light hits a particle it's passing through straight forward. A value of [code]-1[/code] means that all light is scatter backwards.
+ Controls the direction of the [url=https://en.wikipedia.org/wiki/Mie_scattering]Mie scattering[/url]. A value of [code]1[/code] means that when light hits a particle it's passing through straight forward. A value of [code]-1[/code] means that all light is scatter backwards.
</member>
<member name="night_sky" type="Texture2D" setter="set_night_sky" getter="get_night_sky">
[Texture2D] for the night sky. This is added to the sky, so if it is bright enough, it may be visible during the day.
</member>
<member name="rayleigh_coefficient" type="float" setter="set_rayleigh_coefficient" getter="get_rayleigh_coefficient" default="2.0">
- Controls the strength of the Rayleigh scattering. Rayleigh scattering results from light colliding with small particles. It is responsible for the blue color of the sky.
+ Controls the strength of the [url=https://en.wikipedia.org/wiki/Rayleigh_scattering]Rayleigh scattering[/url]. Rayleigh scattering results from light colliding with small particles. It is responsible for the blue color of the sky.
</member>
<member name="rayleigh_color" type="Color" setter="set_rayleigh_color" getter="get_rayleigh_color" default="Color(0.3, 0.405, 0.6, 1)">
- Controls the [Color] of the Rayleigh scattering. While not physically accurate, this allows for the creation of alien-looking planets. For example, setting this to a red [Color] results in a Mars-looking atmosphere with a corresponding blue sunset.
+ Controls the [Color] of the [url=https://en.wikipedia.org/wiki/Rayleigh_scattering]Rayleigh scattering[/url]. While not physically accurate, this allows for the creation of alien-looking planets. For example, setting this to a red [Color] results in a Mars-looking atmosphere with a corresponding blue sunset.
</member>
<member name="sun_disk_scale" type="float" setter="set_sun_disk_scale" getter="get_sun_disk_scale" default="1.0">
Sets the size of the sun disk. Default value is based on Sol's perceived size from Earth.
diff --git a/doc/classes/PhysicsBody2D.xml b/doc/classes/PhysicsBody2D.xml
index 59660b4de5..30fa54d669 100644
--- a/doc/classes/PhysicsBody2D.xml
+++ b/doc/classes/PhysicsBody2D.xml
@@ -25,12 +25,12 @@
</method>
<method name="move_and_collide">
<return type="KinematicCollision2D" />
- <param index="0" name="distance" type="Vector2" />
+ <param index="0" name="motion" type="Vector2" />
<param index="1" name="test_only" type="bool" default="false" />
<param index="2" name="safe_margin" type="float" default="0.08" />
<param index="3" name="recovery_as_collision" type="bool" default="false" />
<description>
- Moves the body along the vector [param distance]. In order to be frame rate independent in [method Node._physics_process] or [method Node._process], [param distance] should be computed using [code]delta[/code].
+ Moves the body along the vector [param motion]. In order to be frame rate independent in [method Node._physics_process] or [method Node._process], [param motion] should be computed using [code]delta[/code].
Returns a [KinematicCollision2D], which contains information about the collision when stopped, or when touching another body along the motion.
If [param test_only] is [code]true[/code], the body does not move but the would-be collision information is given.
[param safe_margin] is the extra margin used for collision recovery (see [member CharacterBody2D.safe_margin] for more details).
@@ -47,13 +47,13 @@
<method name="test_move">
<return type="bool" />
<param index="0" name="from" type="Transform2D" />
- <param index="1" name="distance" type="Vector2" />
+ <param index="1" name="motion" type="Vector2" />
<param index="2" name="collision" type="KinematicCollision2D" default="null" />
<param index="3" name="safe_margin" type="float" default="0.08" />
<param index="4" name="recovery_as_collision" type="bool" default="false" />
<description>
- Checks for collisions without moving the body. In order to be frame rate independent in [method Node._physics_process] or [method Node._process], [param distance] should be computed using [code]delta[/code].
- Virtually sets the node's position, scale and rotation to that of the given [Transform2D], then tries to move the body along the vector [param distance]. Returns [code]true[/code] if a collision would stop the body from moving along the whole path.
+ Checks for collisions without moving the body. In order to be frame rate independent in [method Node._physics_process] or [method Node._process], [param motion] should be computed using [code]delta[/code].
+ Virtually sets the node's position, scale and rotation to that of the given [Transform2D], then tries to move the body along the vector [param motion]. Returns [code]true[/code] if a collision would stop the body from moving along the whole path.
[param collision] is an optional object of type [KinematicCollision2D], which contains additional information about the collision when stopped, or when touching another body along the motion.
[param safe_margin] is the extra margin used for collision recovery (see [member CharacterBody2D.safe_margin] for more details).
If [param recovery_as_collision] is [code]true[/code], any depenetration from the recovery phase is also reported as a collision; this is useful for checking whether the body would [i]touch[/i] any other bodies.
diff --git a/doc/classes/PhysicsBody3D.xml b/doc/classes/PhysicsBody3D.xml
index bf7882a1ea..2ef54683f2 100644
--- a/doc/classes/PhysicsBody3D.xml
+++ b/doc/classes/PhysicsBody3D.xml
@@ -32,13 +32,13 @@
</method>
<method name="move_and_collide">
<return type="KinematicCollision3D" />
- <param index="0" name="distance" type="Vector3" />
+ <param index="0" name="motion" type="Vector3" />
<param index="1" name="test_only" type="bool" default="false" />
<param index="2" name="safe_margin" type="float" default="0.001" />
<param index="3" name="recovery_as_collision" type="bool" default="false" />
<param index="4" name="max_collisions" type="int" default="1" />
<description>
- Moves the body along the vector [param distance]. In order to be frame rate independent in [method Node._physics_process] or [method Node._process], [param distance] should be computed using [code]delta[/code].
+ Moves the body along the vector [param motion]. In order to be frame rate independent in [method Node._physics_process] or [method Node._process], [param motion] should be computed using [code]delta[/code].
The body will stop if it collides. Returns a [KinematicCollision3D], which contains information about the collision when stopped, or when touching another body along the motion.
If [param test_only] is [code]true[/code], the body does not move but the would-be collision information is given.
[param safe_margin] is the extra margin used for collision recovery (see [member CharacterBody3D.safe_margin] for more details).
@@ -64,14 +64,14 @@
<method name="test_move">
<return type="bool" />
<param index="0" name="from" type="Transform3D" />
- <param index="1" name="distance" type="Vector3" />
+ <param index="1" name="motion" type="Vector3" />
<param index="2" name="collision" type="KinematicCollision3D" default="null" />
<param index="3" name="safe_margin" type="float" default="0.001" />
<param index="4" name="recovery_as_collision" type="bool" default="false" />
<param index="5" name="max_collisions" type="int" default="1" />
<description>
- Checks for collisions without moving the body. In order to be frame rate independent in [method Node._physics_process] or [method Node._process], [param distance] should be computed using [code]delta[/code].
- Virtually sets the node's position, scale and rotation to that of the given [Transform3D], then tries to move the body along the vector [param distance]. Returns [code]true[/code] if a collision would stop the body from moving along the whole path.
+ Checks for collisions without moving the body. In order to be frame rate independent in [method Node._physics_process] or [method Node._process], [param motion] should be computed using [code]delta[/code].
+ Virtually sets the node's position, scale and rotation to that of the given [Transform3D], then tries to move the body along the vector [param motion]. Returns [code]true[/code] if a collision would stop the body from moving along the whole path.
[param collision] is an optional object of type [KinematicCollision3D], which contains additional information about the collision when stopped, or when touching another body along the motion.
[param safe_margin] is the extra margin used for collision recovery (see [member CharacterBody3D.safe_margin] for more details).
If [param recovery_as_collision] is [code]true[/code], any depenetration from the recovery phase is also reported as a collision; this is useful for checking whether the body would [i]touch[/i] any other bodies.
diff --git a/doc/classes/PhysicsPointQueryParameters2D.xml b/doc/classes/PhysicsPointQueryParameters2D.xml
index a6cbe2d574..76dc816dab 100644
--- a/doc/classes/PhysicsPointQueryParameters2D.xml
+++ b/doc/classes/PhysicsPointQueryParameters2D.xml
@@ -10,7 +10,7 @@
</tutorials>
<members>
<member name="canvas_instance_id" type="int" setter="set_canvas_instance_id" getter="get_canvas_instance_id" default="0">
- If different from [code]0[/code], restricts the query to a specific canvas layer specified by its instance id. See [method Object.get_instance_id].
+ If different from [code]0[/code], restricts the query to a specific canvas layer specified by its instance ID. See [method Object.get_instance_id].
</member>
<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.
@@ -22,7 +22,7 @@
The physics layers the query will detect (as a bitmask). By default, all collision layers are 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="exclude" type="RID[]" setter="set_exclude" getter="get_exclude" default="[]">
- The list of objects or object [RID]s that will be excluded from collisions.
+ The list of object [RID]s that will be excluded from collisions. Use [method CollisionObject2D.get_rid] to get the [RID] associated with a [CollisionObject2D]-derived node.
</member>
<member name="position" type="Vector2" setter="set_position" getter="get_position" default="Vector2(0, 0)">
The position being queried for, in global coordinates.
diff --git a/doc/classes/PhysicsPointQueryParameters3D.xml b/doc/classes/PhysicsPointQueryParameters3D.xml
index bedf05ce99..3270d3686d 100644
--- a/doc/classes/PhysicsPointQueryParameters3D.xml
+++ b/doc/classes/PhysicsPointQueryParameters3D.xml
@@ -18,8 +18,8 @@
<member name="collision_mask" type="int" setter="set_collision_mask" getter="get_collision_mask" default="4294967295">
The physics layers the query will detect (as a bitmask). By default, all collision layers are 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="exclude" type="Array" setter="set_exclude" getter="get_exclude" default="[]">
- The list of objects or object [RID]s that will be excluded from collisions.
+ <member name="exclude" type="RID[]" setter="set_exclude" getter="get_exclude" default="[]">
+ The list of object [RID]s that will be excluded from collisions. Use [method CollisionObject3D.get_rid] to get the [RID] associated with a [CollisionObject3D]-derived node.
</member>
<member name="position" type="Vector3" setter="set_position" getter="get_position" default="Vector3(0, 0, 0)">
The position being queried for, in global coordinates.
diff --git a/doc/classes/PhysicsRayQueryParameters2D.xml b/doc/classes/PhysicsRayQueryParameters2D.xml
index d6a2662adc..cf5c31d9ec 100644
--- a/doc/classes/PhysicsRayQueryParameters2D.xml
+++ b/doc/classes/PhysicsRayQueryParameters2D.xml
@@ -35,7 +35,7 @@
The physics layers the query will detect (as a bitmask). By default, all collision layers are 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="exclude" type="RID[]" setter="set_exclude" getter="get_exclude" default="[]">
- The list of objects or object [RID]s that will be excluded from collisions.
+ The list of object [RID]s that will be excluded from collisions. Use [method CollisionObject2D.get_rid] to get the [RID] associated with a [CollisionObject2D]-derived node.
</member>
<member name="from" type="Vector2" setter="set_from" getter="get_from" default="Vector2(0, 0)">
The starting point of the ray being queried for, in global coordinates.
diff --git a/doc/classes/PhysicsRayQueryParameters3D.xml b/doc/classes/PhysicsRayQueryParameters3D.xml
index 620aa6bf5f..4f70eedb21 100644
--- a/doc/classes/PhysicsRayQueryParameters3D.xml
+++ b/doc/classes/PhysicsRayQueryParameters3D.xml
@@ -14,7 +14,7 @@
<param index="0" name="from" type="Vector3" />
<param index="1" name="to" type="Vector3" />
<param index="2" name="collision_mask" type="int" default="4294967295" />
- <param index="3" name="exclude" type="Array" default="[]" />
+ <param index="3" name="exclude" type="RID[]" default="[]" />
<description>
Returns a new, pre-configured [PhysicsRayQueryParameters3D] object. Use it to quickly create query parameters using the most common options.
[codeblock]
@@ -34,8 +34,8 @@
<member name="collision_mask" type="int" setter="set_collision_mask" getter="get_collision_mask" default="4294967295">
The physics layers the query will detect (as a bitmask). By default, all collision layers are 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="exclude" type="Array" setter="set_exclude" getter="get_exclude" default="[]">
- The list of objects or object [RID]s that will be excluded from collisions.
+ <member name="exclude" type="RID[]" setter="set_exclude" getter="get_exclude" default="[]">
+ The list of object [RID]s that will be excluded from collisions. Use [method CollisionObject3D.get_rid] to get the [RID] associated with a [CollisionObject3D]-derived node.
</member>
<member name="from" type="Vector3" setter="set_from" getter="get_from" default="Vector3(0, 0, 0)">
The starting point of the ray being queried for, in global coordinates.
diff --git a/doc/classes/PhysicsServer2D.xml b/doc/classes/PhysicsServer2D.xml
index 18ac8a11df..2d25965180 100644
--- a/doc/classes/PhysicsServer2D.xml
+++ b/doc/classes/PhysicsServer2D.xml
@@ -736,6 +736,14 @@
<description>
</description>
</method>
+ <method name="joint_disable_collisions_between_bodies">
+ <return type="void" />
+ <param index="0" name="joint" type="RID" />
+ <param index="1" name="disable" type="bool" />
+ <description>
+ Sets whether the bodies attached to the [Joint2D] will collide with each other.
+ </description>
+ </method>
<method name="joint_get_param" qualifiers="const">
<return type="float" />
<param index="0" name="joint" type="RID" />
@@ -751,6 +759,13 @@
Returns a joint's type (see [enum JointType]).
</description>
</method>
+ <method name="joint_is_disabled_collisions_between_bodies" qualifiers="const">
+ <return type="bool" />
+ <param index="0" name="joint" type="RID" />
+ <description>
+ Returns whether the bodies attached to the [Joint2D] will collide with each other.
+ </description>
+ </method>
<method name="joint_make_damped_spring">
<return type="void" />
<param index="0" name="joint" type="RID" />
diff --git a/doc/classes/PhysicsServer3D.xml b/doc/classes/PhysicsServer3D.xml
index 95f7fb69a2..e62bda0dd3 100644
--- a/doc/classes/PhysicsServer3D.xml
+++ b/doc/classes/PhysicsServer3D.xml
@@ -815,6 +815,14 @@
<description>
</description>
</method>
+ <method name="joint_disable_collisions_between_bodies">
+ <return type="void" />
+ <param index="0" name="joint" type="RID" />
+ <param index="1" name="disable" type="bool" />
+ <description>
+ Sets whether the bodies attached to the [Joint3D] will collide with each other.
+ </description>
+ </method>
<method name="joint_get_solver_priority" qualifiers="const">
<return type="int" />
<param index="0" name="joint" type="RID" />
@@ -829,6 +837,13 @@
Returns the type of the Joint3D.
</description>
</method>
+ <method name="joint_is_disabled_collisions_between_bodies" qualifiers="const">
+ <return type="bool" />
+ <param index="0" name="joint" type="RID" />
+ <description>
+ Returns whether the bodies attached to the [Joint3D] will collide with each other.
+ </description>
+ </method>
<method name="joint_make_cone_twist">
<return type="void" />
<param index="0" name="joint" type="RID" />
diff --git a/doc/classes/PhysicsServer3DExtension.xml b/doc/classes/PhysicsServer3DExtension.xml
index 1e9df54de5..d45cb17510 100644
--- a/doc/classes/PhysicsServer3DExtension.xml
+++ b/doc/classes/PhysicsServer3DExtension.xml
@@ -772,6 +772,13 @@
<description>
</description>
</method>
+ <method name="_joint_disable_collisions_between_bodies" qualifiers="virtual">
+ <return type="void" />
+ <param index="0" name="joint" type="RID" />
+ <param index="1" name="disable" type="bool" />
+ <description>
+ </description>
+ </method>
<method name="_joint_get_solver_priority" qualifiers="virtual const">
<return type="int" />
<param index="0" name="joint" type="RID" />
@@ -784,6 +791,12 @@
<description>
</description>
</method>
+ <method name="_joint_is_disabled_collisions_between_bodies" qualifiers="virtual const">
+ <return type="bool" />
+ <param index="0" name="joint" type="RID" />
+ <description>
+ </description>
+ </method>
<method name="_joint_make_cone_twist" qualifiers="virtual">
<return type="void" />
<param index="0" name="joint" type="RID" />
diff --git a/doc/classes/PhysicsShapeQueryParameters2D.xml b/doc/classes/PhysicsShapeQueryParameters2D.xml
index 8dcb329e7e..a73e60c6f5 100644
--- a/doc/classes/PhysicsShapeQueryParameters2D.xml
+++ b/doc/classes/PhysicsShapeQueryParameters2D.xml
@@ -19,7 +19,7 @@
The physics layers the query will detect (as a bitmask). By default, all collision layers are 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="exclude" type="RID[]" setter="set_exclude" getter="get_exclude" default="[]">
- The list of objects or object [RID]s that will be excluded from collisions.
+ The list of object [RID]s that will be excluded from collisions. Use [method CollisionObject2D.get_rid] to get the [RID] associated with a [CollisionObject2D]-derived node.
</member>
<member name="margin" type="float" setter="set_margin" getter="get_margin" default="0.0">
The collision margin for the shape.
diff --git a/doc/classes/PhysicsShapeQueryParameters3D.xml b/doc/classes/PhysicsShapeQueryParameters3D.xml
index 64100f847b..a3ff1765f9 100644
--- a/doc/classes/PhysicsShapeQueryParameters3D.xml
+++ b/doc/classes/PhysicsShapeQueryParameters3D.xml
@@ -18,8 +18,8 @@
<member name="collision_mask" type="int" setter="set_collision_mask" getter="get_collision_mask" default="4294967295">
The physics layers the query will detect (as a bitmask). By default, all collision layers are 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="exclude" type="Array" setter="set_exclude" getter="get_exclude" default="[]">
- The list of objects or object [RID]s that will be excluded from collisions.
+ <member name="exclude" type="RID[]" setter="set_exclude" getter="get_exclude" default="[]">
+ The list of object [RID]s that will be excluded from collisions. Use [method CollisionObject3D.get_rid] to get the [RID] associated with a [CollisionObject3D]-derived node.
</member>
<member name="margin" type="float" setter="set_margin" getter="get_margin" default="0.0">
The collision margin for the shape.
diff --git a/doc/classes/PhysicsTestMotionParameters2D.xml b/doc/classes/PhysicsTestMotionParameters2D.xml
index 5b969ea869..be5e5a3617 100644
--- a/doc/classes/PhysicsTestMotionParameters2D.xml
+++ b/doc/classes/PhysicsTestMotionParameters2D.xml
@@ -14,9 +14,9 @@
If set to [code]false[/code], shapes of type [constant PhysicsServer2D.SHAPE_SEPARATION_RAY] are only used for separation when overlapping with other bodies. That's the main use for separation ray shapes.
</member>
<member name="exclude_bodies" type="RID[]" setter="set_exclude_bodies" getter="get_exclude_bodies" default="[]">
- Optional array of body [RID] to exclude from collision.
+ Optional array of body [RID] to exclude from collision. Use [method CollisionObject2D.get_rid] to get the [RID] associated with a [CollisionObject2D]-derived node.
</member>
- <member name="exclude_objects" type="Array" setter="set_exclude_objects" getter="get_exclude_objects" default="[]">
+ <member name="exclude_objects" type="int[]" setter="set_exclude_objects" getter="get_exclude_objects" default="[]">
Optional array of object unique instance ID to exclude from collision. See [method Object.get_instance_id].
</member>
<member name="from" type="Transform2D" setter="set_from" getter="get_from" default="Transform2D(1, 0, 0, 1, 0, 0)">
diff --git a/doc/classes/PhysicsTestMotionParameters3D.xml b/doc/classes/PhysicsTestMotionParameters3D.xml
index ea9bca6a35..be7d05691e 100644
--- a/doc/classes/PhysicsTestMotionParameters3D.xml
+++ b/doc/classes/PhysicsTestMotionParameters3D.xml
@@ -13,10 +13,10 @@
If set to [code]true[/code], shapes of type [constant PhysicsServer3D.SHAPE_SEPARATION_RAY] are used to detect collisions and can stop the motion. Can be useful when snapping to the ground.
If set to [code]false[/code], shapes of type [constant PhysicsServer3D.SHAPE_SEPARATION_RAY] are only used for separation when overlapping with other bodies. That's the main use for separation ray shapes.
</member>
- <member name="exclude_bodies" type="Array" setter="set_exclude_bodies" getter="get_exclude_bodies" default="[]">
- Optional array of body [RID] to exclude from collision.
+ <member name="exclude_bodies" type="RID[]" setter="set_exclude_bodies" getter="get_exclude_bodies" default="[]">
+ Optional array of body [RID] to exclude from collision. Use [method CollisionObject3D.get_rid] to get the [RID] associated with a [CollisionObject3D]-derived node.
</member>
- <member name="exclude_objects" type="Array" setter="set_exclude_objects" getter="get_exclude_objects" default="[]">
+ <member name="exclude_objects" type="int[]" setter="set_exclude_objects" getter="get_exclude_objects" default="[]">
Optional array of object unique instance ID to exclude from collision. See [method Object.get_instance_id].
</member>
<member name="from" type="Transform3D" setter="set_from" getter="get_from" default="Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0)">
diff --git a/doc/classes/PointLight2D.xml b/doc/classes/PointLight2D.xml
index 89cabbd428..0c51a78e49 100644
--- a/doc/classes/PointLight2D.xml
+++ b/doc/classes/PointLight2D.xml
@@ -1,10 +1,13 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="PointLight2D" inherits="Light2D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
+ Positional 2D light source.
</brief_description>
<description>
+ Casts light in a 2D environment. This light's shape is defined by a (usually grayscale) texture
</description>
<tutorials>
+ <link title="2D lights and shadows">$DOCS_URL/tutorials/2d/2d_lights_and_shadows.html</link>
</tutorials>
<members>
<member name="height" type="float" setter="set_height" getter="get_height" default="0.0">
diff --git a/doc/classes/Popup.xml b/doc/classes/Popup.xml
index 3fcf0a9b8f..a56bf77774 100644
--- a/doc/classes/Popup.xml
+++ b/doc/classes/Popup.xml
@@ -4,7 +4,7 @@
Popup is a base window container for popup-like subwindows.
</brief_description>
<description>
- Popup is a base window container for popup-like subwindows. It's a modal by default (see [member popup_window]) and has helpers for custom popup behavior.
+ Popup is a base window container for popup-like subwindows. It's a modal by default (see [member Window.popup_window]) and has helpers for custom popup behavior.
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/PopupMenu.xml b/doc/classes/PopupMenu.xml
index 0dcb33ac4c..8dec4eaf86 100644
--- a/doc/classes/PopupMenu.xml
+++ b/doc/classes/PopupMenu.xml
@@ -206,7 +206,7 @@
<return type="int" />
<param index="0" name="index" type="int" />
<description>
- Returns the id of the item at the given [param index]. [code]id[/code] can be manually assigned, while index can not.
+ Returns the ID of the item at the given [param index]. [code]id[/code] can be manually assigned, while index can not.
</description>
</method>
<method name="get_item_indent" qualifiers="const">
@@ -544,6 +544,7 @@
</signal>
<signal name="menu_changed">
<description>
+ Emitted when any item is added, modified or removed.
</description>
</signal>
</signals>
@@ -576,11 +577,14 @@
Width of the single indentation level.
</theme_item>
<theme_item name="item_end_padding" data_type="constant" type="int" default="2">
+ Horizontal padding to the right of the items (or left, in RTL layout).
</theme_item>
<theme_item name="item_start_padding" data_type="constant" type="int" default="2">
+ Horizontal padding to the left of the items (or right, in RTL layout).
</theme_item>
<theme_item name="outline_size" data_type="constant" type="int" default="0">
The size of the item text outline.
+ [b]Note:[/b] If using a font with [member FontFile.multichannel_signed_distance_field] enabled, its [member FontFile.msdf_pixel_range] must be set to at least [i]twice[/i] the value of [theme_item outline_size] for outline rendering to look correct. Otherwise, the outline may appear to be cut off earlier than intended.
</theme_item>
<theme_item name="separator_outline_size" data_type="constant" type="int" default="0">
The size of the labeled separator text outline.
diff --git a/doc/classes/PortableCompressedTexture2D.xml b/doc/classes/PortableCompressedTexture2D.xml
index b64cda6df5..693eaafad3 100644
--- a/doc/classes/PortableCompressedTexture2D.xml
+++ b/doc/classes/PortableCompressedTexture2D.xml
@@ -21,7 +21,7 @@
<param index="3" name="lossy_quality" type="float" default="0.8" />
<description>
Initializes the compressed texture from a base image. The compression mode must be provided.
- If this image will be used as a normal map, the "normal map" flag is recommended, to ensure optimum quality.
+ [param normal_map] is recommended to ensure optimum quality if this image will be used as a normal map.
If lossy compression is requested, the quality setting can optionally be provided. This maps to Lossy WebP compression quality.
</description>
</method>
diff --git a/doc/classes/PrimitiveMesh.xml b/doc/classes/PrimitiveMesh.xml
index 7a411b27ac..b1c8907d8e 100644
--- a/doc/classes/PrimitiveMesh.xml
+++ b/doc/classes/PrimitiveMesh.xml
@@ -34,6 +34,9 @@
</method>
</methods>
<members>
+ <member name="add_uv2" type="bool" setter="set_add_uv2" getter="get_add_uv2" default="false">
+ If set, generates UV2 UV coordinates applying a padding using the [member uv2_padding] setting. UV2 is needed for lightmapping.
+ </member>
<member name="custom_aabb" type="AABB" setter="set_custom_aabb" getter="get_custom_aabb" default="AABB(0, 0, 0, 0, 0, 0)">
Overrides the [AABB] with one defined by user for use with frustum culling. Especially useful to avoid unexpected culling when using a shader to offset vertices.
</member>
@@ -44,5 +47,8 @@
<member name="material" type="Material" setter="set_material" getter="get_material">
The current [Material] of the primitive mesh.
</member>
+ <member name="uv2_padding" type="float" setter="set_uv2_padding" getter="get_uv2_padding" default="2.0">
+ If [member add_uv2] is set, specifies the padding in pixels applied along seams of the mesh. If at generation the size of the lightmap texture can't be determined, the UVs are calculated assuming a texture size of 1024x1024.
+ </member>
</members>
</class>
diff --git a/doc/classes/ProgressBar.xml b/doc/classes/ProgressBar.xml
index 510b8d5bd1..9f89a4e4c3 100644
--- a/doc/classes/ProgressBar.xml
+++ b/doc/classes/ProgressBar.xml
@@ -42,6 +42,7 @@
</theme_item>
<theme_item name="outline_size" data_type="constant" type="int" default="0">
The size of the text outline.
+ [b]Note:[/b] If using a font with [member FontFile.multichannel_signed_distance_field] enabled, its [member FontFile.msdf_pixel_range] must be set to at least [i]twice[/i] the value of [theme_item outline_size] for outline rendering to look correct. Otherwise, the outline may appear to be cut off earlier than intended.
</theme_item>
<theme_item name="font" data_type="font" type="Font">
Font used to draw the fill percentage if [member show_percentage] is [code]true[/code].
diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml
index 4699131c41..67b692a7a0 100644
--- a/doc/classes/ProjectSettings.xml
+++ b/doc/classes/ProjectSettings.xml
@@ -70,15 +70,18 @@
<method name="get_setting" qualifiers="const">
<return type="Variant" />
<param index="0" name="name" type="String" />
+ <param index="1" name="default_value" type="Variant" default="null" />
<description>
- Returns the value of a setting.
+ Returns the value of the setting identified by [param name]. If the setting doesn't exist and [param default_value] is specified, the value of [param default_value] is returned. Otherwise, [code]null[/code] is returned.
[b]Example:[/b]
[codeblocks]
[gdscript]
print(ProjectSettings.get_setting("application/config/name"))
+ print(ProjectSettings.get_setting("application/config/custom_description", "No description specified."))
[/gdscript]
[csharp]
GD.Print(ProjectSettings.GetSetting("application/config/name"));
+ GD.Print(ProjectSettings.GetSetting("application/config/custom_description", "No description specified."));
[/csharp]
[/codeblocks]
</description>
@@ -208,7 +211,7 @@
If [code]true[/code], applies linear filtering when scaling the image (recommended for high-resolution artwork). If [code]false[/code], uses nearest-neighbor interpolation (recommended for pixel art).
</member>
<member name="application/config/custom_user_dir_name" type="String" setter="" getter="" default="&quot;&quot;">
- This user directory is used for storing persistent data ([code]user://[/code] filesystem). If left empty, [code]user://[/code] resolves to a project-specific folder in Godot's own configuration folder (see [method OS.get_user_data_dir]). If a custom directory name is defined, this name will be used instead and appended to the system-specific user data directory (same parent folder as the Godot configuration folder documented in [method OS.get_user_data_dir]).
+ This user directory is used for storing persistent data ([code]user://[/code] filesystem). If a custom directory name is defined, this name will be appended to the system-specific user data directory (same parent folder as the Godot configuration folder documented in [method OS.get_user_data_dir]).
The [member application/config/use_custom_user_dir] setting must be enabled for this to take effect.
</member>
<member name="application/config/description" type="String" setter="" getter="" default="&quot;&quot;">
@@ -235,7 +238,8 @@
[b]Note:[/b] Regardless of this setting's value, [code]res://override.cfg[/code] will still be read to override the project settings.
</member>
<member name="application/config/use_custom_user_dir" type="bool" setter="" getter="" default="false">
- If [code]true[/code], the project will save user data to its own user directory (see [member application/config/custom_user_dir_name]). This setting is only effective on desktop platforms. A name must be set in the [member application/config/custom_user_dir_name] setting for this to take effect. If [code]false[/code], the project will save user data to [code](OS user data directory)/Godot/app_userdata/(project name)[/code].
+ If [code]true[/code], the project will save user data to its own user directory. If [member application/config/custom_user_dir_name] is empty, [code]&lt;OS user data directory&gt;/&lt;project name&gt;[/code] directory will be used. If [code]false[/code], the project will save user data to [code]&lt;OS user data directory&gt;/Godot/app_userdata/&lt;project name&gt;[/code].
+ See also [url=$DOCS_URL/tutorials/io/data_paths.html#accessing-persistent-user-data-user]File paths in Godot projects[/url]. This setting is only effective on desktop platforms.
</member>
<member name="application/config/use_hidden_project_data_directory" type="bool" setter="" getter="" default="true">
If [code]true[/code], the project will use a hidden directory ([code].godot[/code]) for storing project-specific data (metadata, shader cache, etc.).
@@ -317,11 +321,13 @@
<member name="audio/driver/output_latency.web" type="int" setter="" getter="" default="50">
Safer override for [member audio/driver/output_latency] in the Web platform, to avoid audio issues especially on mobile devices.
</member>
- <member name="audio/general/2d_panning_strength" type="float" setter="" getter="" default="1.0">
- The base strength of the panning effect for all AudioStreamPlayer2D nodes. The panning strength can be further scaled on each Node using [member AudioStreamPlayer2D.panning_strength].
+ <member name="audio/general/2d_panning_strength" type="float" setter="" getter="" default="0.5">
+ The base strength of the panning effect for all [AudioStreamPlayer2D] nodes. The panning strength can be further scaled on each Node using [member AudioStreamPlayer2D.panning_strength]. A value of [code]0.0[/code] disables stereo panning entirely, leaving only volume attenuation in place. A value of [code]1.0[/code] completely mutes one of the channels if the sound is located exactly to the left (or right) of the listener.
+ The default value of [code]0.5[/code] is tuned for headphones. When using speakers, you may find lower values to sound better as speakers have a lower stereo separation compared to headphones.
</member>
- <member name="audio/general/3d_panning_strength" type="float" setter="" getter="" default="1.0">
- The base strength of the panning effect for all AudioStreamPlayer3D nodes. The panning strength can be further scaled on each Node using [member AudioStreamPlayer3D.panning_strength].
+ <member name="audio/general/3d_panning_strength" type="float" setter="" getter="" default="0.5">
+ The base strength of the panning effect for all [AudioStreamPlayer3D] nodes. The panning strength can be further scaled on each Node using [member AudioStreamPlayer3D.panning_strength]. A value of [code]0.0[/code] disables stereo panning entirely, leaving only volume attenuation in place. A value of [code]1.0[/code] completely mutes one of the channels if the sound is located exactly to the left (or right) of the listener.
+ The default value of [code]0.5[/code] is tuned for headphones. When using speakers, you may find lower values to sound better as speakers have a lower stereo separation compared to headphones.
</member>
<member name="audio/video/video_delay_compensation_ms" type="int" setter="" getter="" default="0">
Setting to hardcode audio delay when playing video. Best to leave this untouched unless you know what you are doing.
@@ -341,9 +347,6 @@
<member name="compression/formats/zstd/window_log_size" type="int" setter="" getter="" default="27">
Largest size limit (in power of 2) allowed when compressing using long-distance matching with Zstandard. Higher values can result in better compression, but will require more memory when compressing and decompressing.
</member>
- <member name="debug/disable_touch" type="bool" setter="" getter="" default="false">
- Disable touch input. Only has effect on iOS.
- </member>
<member name="debug/file_logging/enable_file_logging" type="bool" setter="" getter="" default="false">
If [code]true[/code], logs all output to files.
</member>
@@ -398,7 +401,7 @@
<member name="debug/gdscript/warnings/redundant_await" type="int" setter="" getter="" default="1">
When set to [code]warn[/code] or [code]error[/code], produces a warning or an error respectively when a function that is not a coroutine is called with await.
</member>
- <member name="debug/gdscript/warnings/return_value_discarded" type="int" setter="" getter="" default="1">
+ <member name="debug/gdscript/warnings/return_value_discarded" type="int" setter="" getter="" default="0">
When set to [code]warn[/code] or [code]error[/code], produces a warning or an error respectively when calling a function without using its return value (by assigning it to a variable or using it as a function argument). Such return values are sometimes used to denote possible errors using the [enum Error] enum.
</member>
<member name="debug/gdscript/warnings/shadowed_global_identifier" type="int" setter="" getter="" default="1">
@@ -555,7 +558,7 @@
Position offset for tooltips, relative to the mouse cursor's hotspot.
</member>
<member name="display/window/dpi/allow_hidpi" type="bool" setter="" getter="" default="true">
- If [code]true[/code], allows HiDPI display on Windows, macOS, Android, iOS and Web. If [code]false[/code], the platform's low-DPI fallback will be used on HiDPI displays, which causes the window to be displayed in a blurry or pixelated manner (and can cause various window management bugs). Therefore, it is recommended to make your project scale to [url=$DOCS_URL/tutorials/viewports/multiple_resolutions.html]multiple resolutions[/url] instead of disabling this setting.
+ If [code]true[/code], allows HiDPI display on Windows, macOS, Android, iOS and Web. If [code]false[/code], the platform's low-DPI fallback will be used on HiDPI displays, which causes the window to be displayed in a blurry or pixelated manner (and can cause various window management bugs). Therefore, it is recommended to make your project scale to [url=$DOCS_URL/tutorials/rendering/multiple_resolutions.html]multiple resolutions[/url] instead of disabling this setting.
[b]Note:[/b] This setting has no effect on Linux as DPI-awareness fallbacks are not supported there.
</member>
<member name="display/window/energy_saving/keep_screen_on" type="bool" setter="" getter="" default="true">
@@ -582,7 +585,7 @@
[b]Note:[/b] This setting has no effect on the home indicator if [code]hide_home_indicator[/code] is [code]true[/code].
</member>
<member name="display/window/per_pixel_transparency/allowed" type="bool" setter="" getter="" default="false">
- If [code]true[/code], allows per-pixel transparency for the window background. This affects performance, so leave it on [code]false[/code] unless you need it. See also [member display/window/size/transparent] and [member rendering/transparent_background].
+ If [code]true[/code], allows per-pixel transparency for the window background. This affects performance, so leave it on [code]false[/code] unless you need it. See also [member display/window/size/transparent] and [member rendering/viewport/transparent_background].
</member>
<member name="display/window/size/always_on_top" type="bool" setter="" getter="" default="false">
Forces the main window to be always on top.
@@ -607,7 +610,7 @@
[b]Note:[/b] This setting is ignored on iOS.
</member>
<member name="display/window/size/transparent" type="bool" setter="" getter="" default="false">
- If [code]true[/code], enables a window manager hint that the main window background [i]can[/i] be transparent. This does not make the background actually transparent. For the background to be transparent, the root viewport must also be made transparent by enabling [member rendering/transparent_background].
+ If [code]true[/code], enables a window manager hint that the main window background [i]can[/i] be transparent. This does not make the background actually transparent. For the background to be transparent, the root viewport must also be made transparent by enabling [member rendering/viewport/transparent_background].
[b]Note:[/b] To use a transparent splash screen, set [member application/boot_splash/bg_color] to [code]Color(0, 0, 0, 0)[/code].
[b]Note:[/b] This setting has no effect if [member display/window/per_pixel_transparency/allowed] is set to [code]false[/code].
</member>
@@ -836,6 +839,7 @@
[b]Note:[/b] Default [code]ui_*[/code] actions cannot be removed as they are necessary for the internal logic of several [Control]s. The events assigned to the action can however be modified.
</member>
<member name="input/ui_swap_input_direction" type="Dictionary" setter="" getter="">
+ Default [InputEventAction] to swap input direction, i.e. change between left-to-right to right-to-left modes. Affects text-editting controls ([LineEdit], [TextEdit]).
</member>
<member name="input/ui_text_add_selection_for_next_occurrence" type="Dictionary" setter="" getter="">
If a selection is currently active with the last caret in text fields, searches for the next occurrence of the selection, adds a caret and selects the next occurrence.
@@ -1811,6 +1815,10 @@
<member name="physics/common/enable_object_picking" type="bool" setter="" getter="" default="true">
Enables [member Viewport.physics_object_picking] on the root viewport.
</member>
+ <member name="physics/common/max_physics_steps_per_frame" type="int" setter="" getter="" default="8">
+ Controls the maximum number of physics steps that can be simulated each rendered frame. The default value is tuned to avoid "spiral of death" situations where expensive physics simulations trigger more expensive simulations indefinitely. However, the game will appear to slow down if the rendering FPS is less than [code]1 / max_physics_steps_per_frame[/code] of [member physics/common/physics_ticks_per_second]. This occurs even if [code]delta[/code] is consistently used in physics calculations. To avoid this, increase [member physics/common/max_physics_steps_per_frame] if you have increased [member physics/common/physics_ticks_per_second] significantly above its default value.
+ [b]Note:[/b] This property is only read when the project starts. To change the maximum number of simulated physics steps per frame at runtime, set [member Engine.max_physics_steps_per_frame] instead.
+ </member>
<member name="physics/common/physics_jitter_fix" type="float" setter="" getter="" default="0.5">
Controls how much physics ticks are synchronized with real time. For 0 or less, the ticks are synchronized. Such values are recommended for network games, where clock synchronization matters. Higher values cause higher deviation of in-game clock and real clock, but allows smoothing out framerate jitters. The default value of 0.5 should be fine for most; values above 2 could cause the game to react to dropped frames with a noticeable delay and are not recommended.
[b]Note:[/b] For best results, when using a custom physics interpolation solution, the physics jitter fix should be disabled by setting [member physics/common/physics_jitter_fix] to [code]0[/code].
@@ -1819,7 +1827,7 @@
<member name="physics/common/physics_ticks_per_second" type="int" setter="" getter="" default="60">
The number of fixed iterations per second. This controls how often physics simulation and [method Node._physics_process] methods are run. See also [member application/run/max_fps].
[b]Note:[/b] This property is only read when the project starts. To change the physics FPS at runtime, set [member Engine.physics_ticks_per_second] instead.
- [b]Note:[/b] Only 8 physics ticks may be simulated per rendered frame at most. If more than 8 physics ticks have to be simulated per rendered frame to keep up with rendering, the game will appear to slow down (even if [code]delta[/code] is used consistently in physics calculations). Therefore, it is recommended not to increase [member physics/common/physics_ticks_per_second] above 240. Otherwise, the game will slow down when the rendering framerate goes below 30 FPS.
+ [b]Note:[/b] Only [member physics/common/max_physics_steps_per_frame] physics ticks may be simulated per rendered frame at most. If more physics ticks have to be simulated per rendered frame to keep up with rendering, the project will appear to slow down (even if [code]delta[/code] is used consistently in physics calculations). Therefore, it is recommended to also increase [member physics/common/max_physics_steps_per_frame] if increasing [member physics/common/physics_ticks_per_second] significantly above its default value.
</member>
<member name="rendering/2d/sdf/oversize" type="int" setter="" getter="" default="1">
</member>
@@ -1887,9 +1895,6 @@
<member name="rendering/environment/glow/upscale_mode.mobile" type="int" setter="" getter="" default="0">
Lower-end override for [member rendering/environment/glow/upscale_mode] on mobile devices, due to performance concerns or driver support.
</member>
- <member name="rendering/environment/glow/use_high_quality" type="bool" setter="" getter="" default="false">
- Takes more samples during downsample pass of glow. This ensures that single pixels are captured by glow which makes the glow look smoother and more stable during movement. However, it is very expensive and makes the glow post process take twice as long.
- </member>
<member name="rendering/environment/screen_space_reflection/roughness_quality" type="int" setter="" getter="" default="1">
Sets the quality for rough screen-space reflections. Turning off will make all screen space reflections sharp, while higher values make rough reflections look better.
</member>
@@ -2016,6 +2021,9 @@
<member name="rendering/lightmapping/bake_quality/ultra_quality_ray_count" type="int" setter="" getter="" default="1024">
The number of rays to use for baking lightmaps with [LightmapGI] when [member LightmapGI.quality] is [constant LightmapGI.BAKE_QUALITY_ULTRA].
</member>
+ <member name="rendering/lightmapping/primitive_meshes/texel_size" type="float" setter="" getter="" default="0.2">
+ The texel_size that is used to calculate the [member Mesh.lightmap_size_hint] on [PrimitiveMesh] resources if [member PrimitiveMesh.add_uv2] is enabled.
+ </member>
<member name="rendering/lightmapping/probe_capture/update_speed" type="float" setter="" getter="" default="15">
The framerate-independent update speed when representing dynamic object lighting from [LightmapProbe]s. Higher values make dynamic object lighting update faster. Higher values can prevent fast-moving objects from having "outdated" indirect lighting displayed on them, at the cost of possible flickering when an object moves from a bright area to a shaded area.
</member>
@@ -2226,9 +2234,6 @@
<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.
</member>
- <member name="rendering/textures/lossless_compression/webp_compression_level" type="int" setter="" getter="" default="2">
- The default compression level for lossless WebP. Higher levels result in smaller files at the cost of compression speed. Decompression speed is mostly unaffected by the compression level. Supported values are 0 to 9. Note that compression levels above 6 are very slow and offer very little savings.
- </member>
<member name="rendering/textures/vram_compression/import_bptc" type="bool" setter="" getter="" default="false">
If [code]true[/code], the texture importer will import VRAM-compressed textures using the BPTC algorithm. This texture compression algorithm is only supported on desktop platforms, and only when using the Vulkan renderer.
[b]Note:[/b] Changing this setting does [i]not[/i] impact textures that were already imported before. To make this setting apply to textures that were already imported, exit the editor, remove the [code].godot/imported/[/code] folder located inside the project folder then restart the editor (see [member application/config/use_hidden_project_data_directory]).
@@ -2245,14 +2250,33 @@
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/transparent_background" type="bool" setter="" getter="" default="false">
+ <member name="rendering/textures/webp_compression/compression_method" type="int" setter="" getter="" default="2">
+ The default compression method for WebP. Affects both lossy and lossless WebP. A higher value results in smaller files at the cost of compression speed. Decompression speed is mostly unaffected by the compression method. Supported values are 0 to 6. Note that compression methods above 4 are very slow and offer very little savings.
+ </member>
+ <member name="rendering/textures/webp_compression/lossless_compression_factor" type="float" setter="" getter="" default="25">
+ The default compression factor for lossless WebP. Decompression speed is mostly unaffected by the compression factor. Supported values are 0 to 100.
+ </member>
+ <member name="rendering/viewport/transparent_background" type="bool" setter="" getter="" default="false">
If [code]true[/code], enables [member Viewport.transparent_bg] on the root viewport. This allows per-pixel transparency to be effective after also enabling [member display/window/size/transparent] and [member display/window/per_pixel_transparency/allowed].
</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.
+ If [member rendering/vrs/mode] is set to [b]Texture[/b], this is the path to default texture loaded as the VRS image.
+ The texture [i]must[/i] use a lossless compression format so that colors can be matched precisely. The following VRS densities are mapped to various colors, with brighter colors representing a lower level of shading precision:
+ [codeblock]
+ - 1x1 = rgb(0, 0, 0) - #000000
+ - 1x2 = rgb(0, 85, 0) - #005500
+ - 2x1 = rgb(85, 0, 0) - #550000
+ - 2x2 = rgb(85, 85, 0) - #555500
+ - 2x4 = rgb(85, 170, 0) - #55aa00
+ - 4x2 = rgb(170, 85, 0) - #aa5500
+ - 4x4 = rgb(170, 170, 0) - #aaaa00
+ - 4x8 = rgb(170, 255, 0) - #aaff00 - Not supported on most hardware
+ - 8x4 = rgb(255, 170, 0) - #ffaa00 - Not supported on most hardware
+ - 8x8 = rgb(255, 255, 0) - #ffff00 - Not supported on most hardware
+ [/codeblock]
</member>
<member name="threading/worker_pool/low_priority_thread_ratio" type="float" setter="" getter="" default="0.3">
</member>
@@ -2272,6 +2296,9 @@
<member name="xr/openxr/reference_space" type="int" setter="" getter="" default="&quot;1&quot;">
Specify the default reference space.
</member>
+ <member name="xr/openxr/submit_depth_buffer" type="bool" setter="" getter="" default="false">
+ If [code]true[/code], OpenXR will manage the depth buffer and use the depth buffer for advanced reprojection provided this is supported by the XR runtime. Note that some rendering features in Godot can't be used with this feature.
+ </member>
<member name="xr/openxr/view_configuration" type="int" setter="" getter="" default="&quot;1&quot;">
Specify the view configuration with which to configure OpenXR setting up either Mono or Stereo rendering.
</member>
diff --git a/doc/classes/RDTextureFormat.xml b/doc/classes/RDTextureFormat.xml
index 1b70303d2d..3bfcd610a4 100644
--- a/doc/classes/RDTextureFormat.xml
+++ b/doc/classes/RDTextureFormat.xml
@@ -35,7 +35,7 @@
</member>
<member name="texture_type" type="int" setter="set_texture_type" getter="get_texture_type" enum="RenderingDevice.TextureType" default="1">
</member>
- <member name="usage_bits" type="int" setter="set_usage_bits" getter="get_usage_bits" default="0">
+ <member name="usage_bits" type="int" setter="set_usage_bits" getter="get_usage_bits" enum="RenderingDevice.TextureUsageBits" default="0">
</member>
<member name="width" type="int" setter="set_width" getter="get_width" default="1">
</member>
diff --git a/doc/classes/RID.xml b/doc/classes/RID.xml
index a6523e4c8b..2d40a7be57 100644
--- a/doc/classes/RID.xml
+++ b/doc/classes/RID.xml
@@ -4,7 +4,8 @@
Handle for a [Resource]'s unique ID.
</brief_description>
<description>
- The RID type is used to access the unique integer ID of a resource. They are opaque, which means they do not grant access to the associated resource by themselves. They are used by and with the low-level Server classes such as [RenderingServer].
+ The RID [Variant] type is used to access a low-level resource by its unique ID. RIDs are opaque, which means they do not grant access to the resource by themselves. They are used by the low-level server classes, such as [DisplayServer], [RenderingServer], [TextServer], etc.
+ A low-level resource may correspond to a high-level [Resource], such as [Texture] or [Mesh].
</description>
<tutorials>
</tutorials>
@@ -27,13 +28,13 @@
<method name="get_id" qualifiers="const">
<return type="int" />
<description>
- Returns the ID of the referenced resource.
+ Returns the ID of the referenced low-level resource.
</description>
</method>
<method name="is_valid" qualifiers="const">
<return type="bool" />
<description>
- Returns [code]true[/code] if [RID] is valid.
+ Returns [code]true[/code] if the [RID] is not [code]0[/code].
</description>
</method>
</methods>
@@ -42,36 +43,42 @@
<return type="bool" />
<param index="0" name="right" type="RID" />
<description>
+ Returns [code]true[/code] if the [RID]s are not equal.
</description>
</operator>
<operator name="operator &lt;">
<return type="bool" />
<param index="0" name="right" type="RID" />
<description>
+ Returns [code]true[/code] if the [RID]'s ID is less than [param right]'s ID.
</description>
</operator>
<operator name="operator &lt;=">
<return type="bool" />
<param index="0" name="right" type="RID" />
<description>
+ Returns [code]true[/code] if the [RID]'s ID is less than or equal to [param right]'s ID.
</description>
</operator>
<operator name="operator ==">
<return type="bool" />
<param index="0" name="right" type="RID" />
<description>
+ Returns [code]true[/code] if both [RID]s are equal, which means they both refer to the same low-level resource.
</description>
</operator>
<operator name="operator &gt;">
<return type="bool" />
<param index="0" name="right" type="RID" />
<description>
+ Returns [code]true[/code] if the [RID]'s ID is greater than [param right]'s ID.
</description>
</operator>
<operator name="operator &gt;=">
<return type="bool" />
<param index="0" name="right" type="RID" />
<description>
+ Returns [code]true[/code] if the [RID]'s ID is greater than or equal to [param right]'s ID.
</description>
</operator>
</operators>
diff --git a/doc/classes/Rect2.xml b/doc/classes/Rect2.xml
index 28fe42afae..d39e50d5f0 100644
--- a/doc/classes/Rect2.xml
+++ b/doc/classes/Rect2.xml
@@ -82,9 +82,9 @@
var rect2 = rect.expand(Vector2(0, -1))
[/gdscript]
[csharp]
- # position (-3, 2), size (1, 1)
+ // position (-3, 2), size (1, 1)
var rect = new Rect2(new Vector2(-3, 2), new Vector2(1, 1));
- # position (-3, -1), size (3, 4), so we fit both rect and Vector2(0, -1)
+ // position (-3, -1), size (3, 4), so we fit both rect and Vector2(0, -1)
var rect2 = rect.Expand(new Vector2(0, -1));
[/csharp]
[/codeblocks]
diff --git a/doc/classes/Rect2i.xml b/doc/classes/Rect2i.xml
index 6d4c113609..325ead0cfa 100644
--- a/doc/classes/Rect2i.xml
+++ b/doc/classes/Rect2i.xml
@@ -79,9 +79,9 @@
var rect2 = rect.expand(Vector2i(0, -1))
[/gdscript]
[csharp]
- # position (-3, 2), size (1, 1)
+ // position (-3, 2), size (1, 1)
var rect = new Rect2i(new Vector2i(-3, 2), new Vector2i(1, 1));
- # position (-3, -1), size (3, 4), so we fit both rect and Vector2i(0, -1)
+ // position (-3, -1), size (3, 4), so we fit both rect and Vector2i(0, -1)
var rect2 = rect.Expand(new Vector2i(0, -1));
[/csharp]
[/codeblocks]
diff --git a/doc/classes/RenderingDevice.xml b/doc/classes/RenderingDevice.xml
index 2de812f5fc..f318430611 100644
--- a/doc/classes/RenderingDevice.xml
+++ b/doc/classes/RenderingDevice.xml
@@ -9,8 +9,8 @@
<methods>
<method name="barrier">
<return type="void" />
- <param index="0" name="from" type="int" default="7" />
- <param index="1" name="to" type="int" default="7" />
+ <param index="0" name="from" type="int" enum="RenderingDevice.BarrierMask" default="7" />
+ <param index="1" name="to" type="int" enum="RenderingDevice.BarrierMask" default="7" />
<description>
</description>
</method>
@@ -19,7 +19,7 @@
<param index="0" name="buffer" type="RID" />
<param index="1" name="offset" type="int" />
<param index="2" name="size_bytes" type="int" />
- <param index="3" name="post_barrier" type="int" default="7" />
+ <param index="3" name="post_barrier" type="int" enum="RenderingDevice.BarrierMask" default="7" />
<description>
</description>
</method>
@@ -35,7 +35,7 @@
<param index="1" name="offset" type="int" />
<param index="2" name="size_bytes" type="int" />
<param index="3" name="data" type="PackedByteArray" />
- <param index="4" name="post_barrier" type="int" default="7" />
+ <param index="4" name="post_barrier" type="int" enum="RenderingDevice.BarrierMask" default="7" />
<description>
</description>
</method>
@@ -83,7 +83,7 @@
</method>
<method name="compute_list_end">
<return type="void" />
- <param index="0" name="post_barrier" type="int" default="7" />
+ <param index="0" name="post_barrier" type="int" enum="RenderingDevice.BarrierMask" default="7" />
<description>
</description>
</method>
@@ -223,7 +223,7 @@
</method>
<method name="draw_list_end">
<return type="void" />
- <param index="0" name="post_barrier" type="int" default="7" />
+ <param index="0" name="post_barrier" type="int" enum="RenderingDevice.BarrierMask" default="7" />
<description>
</description>
</method>
@@ -425,7 +425,7 @@
<param index="5" name="multisample_state" type="RDPipelineMultisampleState" />
<param index="6" name="stencil_state" type="RDPipelineDepthStencilState" />
<param index="7" name="color_blend_state" type="RDPipelineColorBlendState" />
- <param index="8" name="dynamic_state_flags" type="int" default="0" />
+ <param index="8" name="dynamic_state_flags" type="int" enum="RenderingDevice.PipelineDynamicStateFlags" default="0" />
<param index="9" name="for_render_pass" type="int" default="0" />
<param index="10" name="specialization_constants" type="RDPipelineSpecializationConstant[]" default="[]" />
<description>
@@ -504,7 +504,7 @@
<return type="RID" />
<param index="0" name="size_bytes" type="int" />
<param index="1" name="data" type="PackedByteArray" default="PackedByteArray()" />
- <param index="2" name="usage" type="int" default="0" />
+ <param index="2" name="usage" type="int" enum="RenderingDevice.StorageBufferUsage" default="0" />
<description>
</description>
</method>
@@ -534,7 +534,7 @@
<param index="3" name="mipmap_count" type="int" />
<param index="4" name="base_layer" type="int" />
<param index="5" name="layer_count" type="int" />
- <param index="6" name="post_barrier" type="int" default="7" />
+ <param index="6" name="post_barrier" type="int" enum="RenderingDevice.BarrierMask" default="7" />
<description>
</description>
</method>
@@ -549,7 +549,7 @@
<param index="6" name="dst_mipmap" type="int" />
<param index="7" name="src_layer" type="int" />
<param index="8" name="dst_layer" type="int" />
- <param index="9" name="post_barrier" type="int" default="7" />
+ <param index="9" name="post_barrier" type="int" enum="RenderingDevice.BarrierMask" default="7" />
<description>
</description>
</method>
@@ -589,7 +589,7 @@
<method name="texture_is_format_supported_for_usage" qualifiers="const">
<return type="bool" />
<param index="0" name="format" type="int" enum="RenderingDevice.DataFormat" />
- <param index="1" name="usage_flags" type="int" />
+ <param index="1" name="usage_flags" type="int" enum="RenderingDevice.TextureUsageBits" />
<description>
</description>
</method>
@@ -609,7 +609,7 @@
<return type="int" enum="Error" />
<param index="0" name="from_texture" type="RID" />
<param index="1" name="to_texture" type="RID" />
- <param index="2" name="post_barrier" type="int" default="7" />
+ <param index="2" name="post_barrier" type="int" enum="RenderingDevice.BarrierMask" default="7" />
<description>
</description>
</method>
@@ -618,7 +618,7 @@
<param index="0" name="texture" type="RID" />
<param index="1" name="layer" type="int" />
<param index="2" name="data" type="PackedByteArray" />
- <param index="3" name="post_barrier" type="int" default="7" />
+ <param index="3" name="post_barrier" type="int" enum="RenderingDevice.BarrierMask" default="7" />
<description>
</description>
</method>
@@ -648,8 +648,9 @@
<param index="0" name="vertex_count" type="int" />
<param index="1" name="vertex_format" type="int" />
<param index="2" name="src_buffers" type="RID[]" />
+ <param index="3" name="offsets" type="PackedInt64Array" default="PackedInt64Array()" />
<description>
- Creates a vertex array based on the specified buffers.
+ Creates a vertex array based on the specified buffers. Optionally, [param offsets] (in bytes) may be defined for each buffer.
</description>
</method>
<method name="vertex_buffer_create">
@@ -668,16 +669,6 @@
</method>
</methods>
<constants>
- <constant name="BARRIER_MASK_RASTER" value="1">
- </constant>
- <constant name="BARRIER_MASK_COMPUTE" value="2">
- </constant>
- <constant name="BARRIER_MASK_TRANSFER" value="4">
- </constant>
- <constant name="BARRIER_MASK_ALL" value="7">
- </constant>
- <constant name="BARRIER_MASK_NO_BARRIER" value="8">
- </constant>
<constant name="DEVICE_TYPE_OTHER" value="0" enum="DeviceType">
Rendering device type does not match any of the other enum values or is unknown.
</constant>
@@ -1160,6 +1151,16 @@
</constant>
<constant name="DATA_FORMAT_MAX" value="218" enum="DataFormat">
</constant>
+ <constant name="BARRIER_MASK_RASTER" value="1" enum="BarrierMask" is_bitfield="true">
+ </constant>
+ <constant name="BARRIER_MASK_COMPUTE" value="2" enum="BarrierMask" is_bitfield="true">
+ </constant>
+ <constant name="BARRIER_MASK_TRANSFER" value="4" enum="BarrierMask" is_bitfield="true">
+ </constant>
+ <constant name="BARRIER_MASK_ALL_BARRIERS" value="7" enum="BarrierMask" is_bitfield="true">
+ </constant>
+ <constant name="BARRIER_MASK_NO_BARRIER" value="8" enum="BarrierMask" is_bitfield="true">
+ </constant>
<constant name="TEXTURE_TYPE_1D" value="0" enum="TextureType">
</constant>
<constant name="TEXTURE_TYPE_2D" value="1" enum="TextureType">
@@ -1192,25 +1193,25 @@
</constant>
<constant name="TEXTURE_SAMPLES_MAX" value="7" enum="TextureSamples">
</constant>
- <constant name="TEXTURE_USAGE_SAMPLING_BIT" value="1" enum="TextureUsageBits">
+ <constant name="TEXTURE_USAGE_SAMPLING_BIT" value="1" enum="TextureUsageBits" is_bitfield="true">
</constant>
- <constant name="TEXTURE_USAGE_COLOR_ATTACHMENT_BIT" value="2" enum="TextureUsageBits">
+ <constant name="TEXTURE_USAGE_COLOR_ATTACHMENT_BIT" value="2" enum="TextureUsageBits" is_bitfield="true">
</constant>
- <constant name="TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT" value="4" enum="TextureUsageBits">
+ <constant name="TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT" value="4" enum="TextureUsageBits" is_bitfield="true">
</constant>
- <constant name="TEXTURE_USAGE_STORAGE_BIT" value="8" enum="TextureUsageBits">
+ <constant name="TEXTURE_USAGE_STORAGE_BIT" value="8" enum="TextureUsageBits" is_bitfield="true">
</constant>
- <constant name="TEXTURE_USAGE_STORAGE_ATOMIC_BIT" value="16" enum="TextureUsageBits">
+ <constant name="TEXTURE_USAGE_STORAGE_ATOMIC_BIT" value="16" enum="TextureUsageBits" is_bitfield="true">
</constant>
- <constant name="TEXTURE_USAGE_CPU_READ_BIT" value="32" enum="TextureUsageBits">
+ <constant name="TEXTURE_USAGE_CPU_READ_BIT" value="32" enum="TextureUsageBits" is_bitfield="true">
</constant>
- <constant name="TEXTURE_USAGE_CAN_UPDATE_BIT" value="64" enum="TextureUsageBits">
+ <constant name="TEXTURE_USAGE_CAN_UPDATE_BIT" value="64" enum="TextureUsageBits" is_bitfield="true">
</constant>
- <constant name="TEXTURE_USAGE_CAN_COPY_FROM_BIT" value="128" enum="TextureUsageBits">
+ <constant name="TEXTURE_USAGE_CAN_COPY_FROM_BIT" value="128" enum="TextureUsageBits" is_bitfield="true">
</constant>
- <constant name="TEXTURE_USAGE_CAN_COPY_TO_BIT" value="256" enum="TextureUsageBits">
+ <constant name="TEXTURE_USAGE_CAN_COPY_TO_BIT" value="256" enum="TextureUsageBits" is_bitfield="true">
</constant>
- <constant name="TEXTURE_USAGE_INPUT_ATTACHMENT_BIT" value="512" enum="TextureUsageBits">
+ <constant name="TEXTURE_USAGE_INPUT_ATTACHMENT_BIT" value="512" enum="TextureUsageBits" is_bitfield="true">
</constant>
<constant name="TEXTURE_SWIZZLE_IDENTITY" value="0" enum="TextureSwizzle">
</constant>
@@ -1272,7 +1273,7 @@
</constant>
<constant name="INDEX_BUFFER_FORMAT_UINT32" value="1" enum="IndexBufferFormat">
</constant>
- <constant name="STORAGE_BUFFER_USAGE_DISPATCH_INDIRECT" value="1" enum="StorageBufferUsage">
+ <constant name="STORAGE_BUFFER_USAGE_DISPATCH_INDIRECT" value="1" enum="StorageBufferUsage" is_bitfield="true">
</constant>
<constant name="UNIFORM_TYPE_SAMPLER" value="0" enum="UniformType">
</constant>
@@ -1452,19 +1453,19 @@
</constant>
<constant name="BLEND_OP_MAX" value="5" enum="BlendOperation">
</constant>
- <constant name="DYNAMIC_STATE_LINE_WIDTH" value="1" enum="PipelineDynamicStateFlags">
+ <constant name="DYNAMIC_STATE_LINE_WIDTH" value="1" enum="PipelineDynamicStateFlags" is_bitfield="true">
</constant>
- <constant name="DYNAMIC_STATE_DEPTH_BIAS" value="2" enum="PipelineDynamicStateFlags">
+ <constant name="DYNAMIC_STATE_DEPTH_BIAS" value="2" enum="PipelineDynamicStateFlags" is_bitfield="true">
</constant>
- <constant name="DYNAMIC_STATE_BLEND_CONSTANTS" value="4" enum="PipelineDynamicStateFlags">
+ <constant name="DYNAMIC_STATE_BLEND_CONSTANTS" value="4" enum="PipelineDynamicStateFlags" is_bitfield="true">
</constant>
- <constant name="DYNAMIC_STATE_DEPTH_BOUNDS" value="8" enum="PipelineDynamicStateFlags">
+ <constant name="DYNAMIC_STATE_DEPTH_BOUNDS" value="8" enum="PipelineDynamicStateFlags" is_bitfield="true">
</constant>
- <constant name="DYNAMIC_STATE_STENCIL_COMPARE_MASK" value="16" enum="PipelineDynamicStateFlags">
+ <constant name="DYNAMIC_STATE_STENCIL_COMPARE_MASK" value="16" enum="PipelineDynamicStateFlags" is_bitfield="true">
</constant>
- <constant name="DYNAMIC_STATE_STENCIL_WRITE_MASK" value="32" enum="PipelineDynamicStateFlags">
+ <constant name="DYNAMIC_STATE_STENCIL_WRITE_MASK" value="32" enum="PipelineDynamicStateFlags" is_bitfield="true">
</constant>
- <constant name="DYNAMIC_STATE_STENCIL_REFERENCE" value="64" enum="PipelineDynamicStateFlags">
+ <constant name="DYNAMIC_STATE_STENCIL_REFERENCE" value="64" enum="PipelineDynamicStateFlags" is_bitfield="true">
</constant>
<constant name="INITIAL_ACTION_CLEAR" value="0" enum="InitialAction">
</constant>
diff --git a/doc/classes/RenderingServer.xml b/doc/classes/RenderingServer.xml
index 13e5470a56..87e569ba20 100644
--- a/doc/classes/RenderingServer.xml
+++ b/doc/classes/RenderingServer.xml
@@ -241,6 +241,7 @@
<param index="4" name="modulate" type="Color" default="Color(1, 1, 1, 1)" />
<param index="5" name="outline_size" type="int" default="0" />
<param index="6" name="px_range" type="float" default="1.0" />
+ <param index="7" name="scale" type="float" default="1.0" />
<description>
</description>
</method>
@@ -838,6 +839,8 @@
<method name="create_local_rendering_device" qualifiers="const">
<return type="RenderingDevice" />
<description>
+ Creates a RenderingDevice that can be used to do draw and compute operations on a separate thread. Cannot draw to the screen nor share data with the global RenderingDevice.
+ [b]Note:[/b] When using the OpenGL backend or when running in headless mode, this function always returns [code]null[/code].
</description>
</method>
<method name="decal_create">
@@ -960,12 +963,6 @@
<description>
</description>
</method>
- <method name="environment_glow_set_use_high_quality">
- <return type="void" />
- <param index="0" name="enable" type="bool" />
- <description>
- </description>
- </method>
<method name="environment_set_adjustment">
<return type="void" />
<param index="0" name="env" type="RID" />
@@ -1273,6 +1270,8 @@
<method name="get_rendering_device" qualifiers="const">
<return type="RenderingDevice" />
<description>
+ Returns the global RenderingDevice.
+ [b]Note:[/b] When using the OpenGL backend or when running in headless mode, this function always returns [code]null[/code].
</description>
</method>
<method name="get_rendering_info">
@@ -1291,13 +1290,13 @@
<method name="get_test_cube">
<return type="RID" />
<description>
- Returns the id of the test cube. Creates one if none exists.
+ Returns the ID of the test cube. Creates one if none exists.
</description>
</method>
<method name="get_test_texture">
<return type="RID" />
<description>
- Returns the id of the test texture. Creates one if none exists.
+ Returns the ID of the test texture. Creates one if none exists.
</description>
</method>
<method name="get_video_adapter_api_version" qualifiers="const">
@@ -1331,7 +1330,7 @@
<method name="get_white_texture">
<return type="RID" />
<description>
- Returns the id of a white texture. Creates one if none exists.
+ Returns the ID of a white texture. Creates one if none exists.
</description>
</method>
<method name="gi_set_use_half_resolution">
@@ -1561,7 +1560,7 @@
<param index="0" name="instance" type="RID" />
<param index="1" name="aabb" type="AABB" />
<description>
- Sets a custom AABB to use when culling objects from the view frustum. Equivalent to [method GeometryInstance3D.set_custom_aabb].
+ Sets a custom AABB to use when culling objects from the view frustum. Equivalent to setting [member GeometryInstance3D.custom_aabb].
</description>
</method>
<method name="instance_set_extra_visibility_margin">
@@ -1587,6 +1586,15 @@
Sets the render layers that this instance will be drawn to. Equivalent to [member VisualInstance3D.layers].
</description>
</method>
+ <method name="instance_set_pivot_data">
+ <return type="void" />
+ <param index="0" name="instance" type="RID" />
+ <param index="1" name="sorting_offset" type="float" />
+ <param index="2" name="use_aabb_center" type="bool" />
+ <description>
+ Sets the sorting offset and switches between using the bounding box or instance origin for depth sorting.
+ </description>
+ </method>
<method name="instance_set_scenario">
<return type="void" />
<param index="0" name="instance" type="RID" />
diff --git a/doc/classes/RichTextLabel.xml b/doc/classes/RichTextLabel.xml
index cb2481f705..dd291a425d 100644
--- a/doc/classes/RichTextLabel.xml
+++ b/doc/classes/RichTextLabel.xml
@@ -367,6 +367,7 @@
<return type="void" />
<param index="0" name="columns" type="int" />
<param index="1" name="inline_align" type="int" enum="InlineAlignment" default="0" />
+ <param index="2" name="align_to_row" type="int" default="-1" />
<description>
Adds a [code][table=columns,inline_align][/code] tag to the tag stack.
</description>
@@ -377,12 +378,12 @@
Adds a [code][u][/code] tag to the tag stack.
</description>
</method>
- <method name="remove_line">
+ <method name="remove_paragraph">
<return type="bool" />
- <param index="0" name="line" type="int" />
+ <param index="0" name="paragraph" type="int" />
<description>
- Removes a line of content from the label. Returns [code]true[/code] if the line exists.
- The [param line] argument is the index of the line to remove, it can take values in the interval [code][0, get_line_count() - 1][/code].
+ Removes a paragraph of content from the label. Returns [code]true[/code] if the paragraph exists.
+ The [param paragraph] argument is the index of the paragraph to remove, it can take values in the interval [code][0, get_paragraph_count() - 1][/code].
</description>
</method>
<method name="scroll_to_line">
@@ -399,6 +400,12 @@
Scrolls the window's top line to match first line of the [param paragraph].
</description>
</method>
+ <method name="scroll_to_selection">
+ <return type="void" />
+ <description>
+ Scrolls to the beginning of the current selection.
+ </description>
+ </method>
<method name="select_all">
<return type="void" />
<description>
@@ -649,6 +656,7 @@
</theme_item>
<theme_item name="outline_size" data_type="constant" type="int" default="0">
The size of the text outline.
+ [b]Note:[/b] If using a font with [member FontFile.multichannel_signed_distance_field] enabled, its [member FontFile.msdf_pixel_range] must be set to at least [i]twice[/i] the value of [theme_item outline_size] for outline rendering to look correct. Otherwise, the outline may appear to be cut off earlier than intended.
</theme_item>
<theme_item name="shadow_offset_x" data_type="constant" type="int" default="1">
The horizontal offset of the font's shadow.
diff --git a/doc/classes/SceneTree.xml b/doc/classes/SceneTree.xml
index 070b98f21d..bd5b656e1a 100644
--- a/doc/classes/SceneTree.xml
+++ b/doc/classes/SceneTree.xml
@@ -308,6 +308,7 @@
</constant>
<constant name="GROUP_CALL_UNIQUE" value="4" enum="GroupCallFlags">
Call a group only once even if the call is executed many times.
+ [b]Note:[/b] Arguments are not taken into account when deciding whether the call is unique or not. Therefore when the same method is called with different arguments, only the first call will be performed.
</constant>
</constants>
</class>
diff --git a/doc/classes/ScrollContainer.xml b/doc/classes/ScrollContainer.xml
index b96b7187e4..af39261e81 100644
--- a/doc/classes/ScrollContainer.xml
+++ b/doc/classes/ScrollContainer.xml
@@ -49,6 +49,7 @@
Controls whether horizontal scrollbar can be used and when it should be visible. See [enum ScrollMode] for options.
</member>
<member name="scroll_deadzone" type="int" setter="set_deadzone" getter="get_deadzone" default="0">
+ Deadzone for touch scrolling. Lower deadzone makes the scrolling more sensitive.
</member>
<member name="scroll_horizontal" type="int" setter="set_h_scroll" getter="get_h_scroll" default="0">
The current horizontal scroll value.
diff --git a/doc/classes/Signal.xml b/doc/classes/Signal.xml
index d99477ee95..3412cd2140 100644
--- a/doc/classes/Signal.xml
+++ b/doc/classes/Signal.xml
@@ -1,9 +1,29 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="Signal" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
- Class representing a signal defined in an object.
+ Built-in type representing a signal defined in an object.
</brief_description>
<description>
+ [Signal] is a built-in [Variant] type that represents a signal of an [Object] instance. Like all [Variant] types, it can be stored in variables and passed to functions. Signals allow all connected [Callable]s (and by extension their respective objects) to listen and react to events, without directly referencing one another. This keeps the code flexible and easier to manage.
+ In GDScript, signals can be declared with the [code]signal[/code] keyword. In C#, you may use the [code][Signal][/code] attribute on a delegate.
+ [codeblocks]
+ [gdscript]
+ signal attacked
+
+ # Additional arguments may be declared.
+ # These arguments must be passed when the signal is emitted.
+ signal item_dropped(item_name, amount)
+ [/gdscript]
+ [csharp]
+ [Signal]
+ delegate void Attacked();
+
+ // Additional arguments may be declared.
+ // These arguments must be passed when the signal is emitted.
+ [Signal]
+ delegate void ItemDropped(itemName: string, amount: int);
+ [/csharp]
+ [/codeblocks]
</description>
<tutorials>
<link title="Using Signals">$DOCS_URL/getting_started/step_by_step/signals.html</link>
@@ -13,7 +33,7 @@
<constructor name="Signal">
<return type="Signal" />
<description>
- Constructs a null [Signal] with no object nor signal name bound.
+ Constructs an empty [Signal] with no object nor signal name bound.
</description>
</constructor>
<constructor name="Signal">
@@ -28,7 +48,7 @@
<param index="0" name="object" type="Object" />
<param index="1" name="signal" type="StringName" />
<description>
- Creates a new [Signal] with the name [param signal] in the specified [param object].
+ Creates a new [Signal] named [param signal] in the specified [param object].
</description>
</constructor>
</constructors>
@@ -38,12 +58,13 @@
<param index="0" name="callable" type="Callable" />
<param index="1" name="flags" type="int" default="0" />
<description>
- Connects this signal to the specified [Callable], optionally providing connection flags. You can provide additional arguments to the connected method call by using [method Callable.bind].
+ Connects this signal to the specified [param callable]. Optional [param flags] can be also added to configure the connection's behavior (see [enum Object.ConnectFlags] constants). You can provide additional arguments to the connected [param callable] by using [method Callable.bind].
+ A signal can only be connected once to the same [Callable]. If the signal is already connected, returns [constant ERR_INVALID_PARAMETER] and pushes an error message, unless the signal is connected with [constant Object.CONNECT_REFERENCE_COUNTED]. To prevent this, use [method is_connected] first to check for existing connections.
[codeblock]
for button in $Buttons.get_children():
- button.pressed.connect(on_pressed.bind(button))
+ button.pressed.connect(_on_pressed.bind(button))
- func on_pressed(button):
+ func _on_pressed(button):
print(button.name, " was pressed")
[/codeblock]
</description>
@@ -52,13 +73,13 @@
<return type="void" />
<param index="0" name="callable" type="Callable" />
<description>
- Disconnects this signal from the specified [Callable].
+ Disconnects this signal from the specified [Callable]. If the connection does not exist, generates an error. Use [method is_connected] to make sure that the connection exists.
</description>
</method>
<method name="emit" qualifiers="vararg const">
<return type="void" />
<description>
- Emits this signal to all connected objects.
+ Emits this signal. All [Callable]s connected to this signal will be triggered. This method supports a variable number of arguments, so parameters can be passed as a comma separated list.
</description>
</method>
<method name="get_connections" qualifiers="const">
@@ -95,6 +116,7 @@
<method name="is_null" qualifiers="const">
<return type="bool" />
<description>
+ Returns [code]true[/code] if the signal's name does not exist in its object, or the object is not valid.
</description>
</method>
</methods>
@@ -103,12 +125,14 @@
<return type="bool" />
<param index="0" name="right" type="Signal" />
<description>
+ Returns [code]true[/code] if the signals do not share the same object and name.
</description>
</operator>
<operator name="operator ==">
<return type="bool" />
<param index="0" name="right" type="Signal" />
<description>
+ Returns [code]true[/code] if both signals share the same object and name.
</description>
</operator>
</operators>
diff --git a/doc/classes/SpinBox.xml b/doc/classes/SpinBox.xml
index e214867890..7d63747bd2 100644
--- a/doc/classes/SpinBox.xml
+++ b/doc/classes/SpinBox.xml
@@ -46,6 +46,7 @@
</methods>
<members>
<member name="alignment" type="int" setter="set_horizontal_alignment" getter="get_horizontal_alignment" enum="HorizontalAlignment" default="0">
+ Changes the alignment of the underlying [LineEdit].
</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].
diff --git a/doc/classes/SpotLight3D.xml b/doc/classes/SpotLight3D.xml
index 28e2ef0d95..59d36aefab 100644
--- a/doc/classes/SpotLight3D.xml
+++ b/doc/classes/SpotLight3D.xml
@@ -12,6 +12,7 @@
</tutorials>
<members>
<member name="shadow_bias" type="float" setter="set_param" getter="get_param" overrides="Light3D" default="0.03" />
+ <member name="shadow_normal_bias" type="float" setter="set_param" getter="get_param" overrides="Light3D" default="1.0" />
<member name="spot_angle" type="float" setter="set_param" getter="get_param" default="45.0">
The spotlight's angle in degrees.
[b]Note:[/b] [member spot_angle] is not affected by [member Node3D.scale] (the light's scale or its parent's scale).
diff --git a/doc/classes/Sprite3D.xml b/doc/classes/Sprite3D.xml
index 956e646702..01671aa04e 100644
--- a/doc/classes/Sprite3D.xml
+++ b/doc/classes/Sprite3D.xml
@@ -19,6 +19,7 @@
The number of columns in the sprite sheet.
</member>
<member name="region_enabled" type="bool" setter="set_region_enabled" getter="is_region_enabled" default="false">
+ If [code]true[/code], the sprite will use [member region_rect] and display only the specified part of its texture.
</member>
<member name="region_rect" type="Rect2" setter="set_region_rect" getter="get_region_rect" default="Rect2(0, 0, 0, 0)">
The region of the atlas texture to display. [member region_enabled] must be [code]true[/code].
diff --git a/doc/classes/String.xml b/doc/classes/String.xml
index b0b4f74b46..97466e7860 100644
--- a/doc/classes/String.xml
+++ b/doc/classes/String.xml
@@ -1,10 +1,12 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="String" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
- Built-in string class.
+ Built-in string Variant type.
</brief_description>
<description>
- This is the built-in string class (and the one used by GDScript). It supports Unicode and provides all necessary means for string handling. Strings are reference-counted and use a copy-on-write approach, so passing them around is cheap in resources.
+ This is the built-in string Variant type (and the one used by GDScript). Strings may contain any number of Unicode characters, and expose methods useful for manipulating and generating strings. Strings are reference-counted and use a copy-on-write approach (every modification to a string returns a new [String]), so passing them around is cheap in resources.
+ Some string methods have corresponding variations. Variations suffixed with [code]n[/code] ([method countn], [method findn], [method replacen], etc.) are [b]case-insensitive[/b] (they make no distinction between uppercase and lowercase letters). Method variations prefixed with [code]r[/code] ([method rfind], [method rsplit], etc.) are reversed, and start from the end of the string, instead of the beginning.
+ [b]Note:[/b] In a boolean context, a string will evaluate to [code]false[/code] if it is empty ([code]""[/code]). Otherwise, a string will always evaluate to [code]true[/code].
</description>
<tutorials>
<link title="GDScript format strings">$DOCS_URL/tutorials/scripting/gdscript/gdscript_format_string.html</link>
@@ -27,14 +29,14 @@
<return type="String" />
<param index="0" name="from" type="NodePath" />
<description>
- Constructs a new String from the given [NodePath].
+ Constructs a new [String] from the given [NodePath].
</description>
</constructor>
<constructor name="String">
<return type="String" />
<param index="0" name="from" type="StringName" />
<description>
- Constructs a new String from the given [StringName].
+ Constructs a new [String] from the given [StringName].
</description>
</constructor>
</constructors>
@@ -43,30 +45,32 @@
<return type="bool" />
<param index="0" name="text" type="String" />
<description>
- Returns [code]true[/code] if the string begins with the given string.
+ Returns [code]true[/code] if the string begins with the given [param text]. See also [method ends_with].
</description>
</method>
<method name="bigrams" qualifiers="const">
<return type="PackedStringArray" />
<description>
- Returns an array containing the bigrams (pairs of consecutive letters) of this string.
+ Returns an array containing the bigrams (pairs of consecutive characters) of this string.
[codeblock]
- print("Bigrams".bigrams()) # Prints "[Bi, ig, gr, ra, am, ms]"
+ print("Get up!".bigrams()) # Prints ["Ge", "et", "t ", " u", "up", "p!"]
[/codeblock]
</description>
</method>
<method name="bin_to_int" qualifiers="const">
<return type="int" />
<description>
- Converts a string containing a binary number into an integer. Binary strings can either be prefixed with [code]0b[/code] or not, and they can also start with a [code]-[/code] before the optional prefix.
+ Converts the string representing a binary number into an [int]. The string may optionally be prefixed with [code]"0b"[/code], and an additional [code]-[/code] prefix for negative numbers.
[codeblocks]
[gdscript]
- print("0b101".bin_to_int()) # Prints "5".
- print("101".bin_to_int()) # Prints "5".
+ print("101".bin_to_int()) # Prints 5
+ print("0b101".bin_to_int()) # Prints 5
+ print("-0b10".bin_to_int()) # Prints -2
[/gdscript]
[csharp]
- GD.Print("0b101".BinToInt()); // Prints "5".
- GD.Print("101".BinToInt()); // Prints "5".
+ GD.Print("101".BinToInt()); // Prints 5
+ GD.Print("0b101".BinToInt()); // Prints 5
+ GD.Print("-0b10".BinToInt()); // Prints -2
[/csharp]
[/codeblocks]
</description>
@@ -80,33 +84,43 @@
<method name="c_unescape" qualifiers="const">
<return type="String" />
<description>
- Returns a copy of the string with escaped characters replaced by their meanings. Supported escape sequences are [code]\'[/code], [code]\"[/code], [code]\?[/code], [code]\\[/code], [code]\a[/code], [code]\b[/code], [code]\f[/code], [code]\n[/code], [code]\r[/code], [code]\t[/code], [code]\v[/code].
+ Returns a copy of the string with escaped characters replaced by their meanings. Supported escape sequences are [code]\'[/code], [code]\"[/code], [code]\\[/code], [code]\a[/code], [code]\b[/code], [code]\f[/code], [code]\n[/code], [code]\r[/code], [code]\t[/code], [code]\v[/code].
[b]Note:[/b] Unlike the GDScript parser, this method doesn't support the [code]\uXXXX[/code] escape sequence.
</description>
</method>
<method name="capitalize" qualifiers="const">
<return type="String" />
<description>
- Changes the case of some letters. Replaces underscores with spaces, adds spaces before in-word uppercase characters, converts all letters to lowercase, then capitalizes the first letter and every letter following a space character. For [code]capitalize camelCase mixed_with_underscores[/code], it will return [code]Capitalize Camel Case Mixed With Underscores[/code].
+ Changes the appearance of the string: replaces underscores ([code]_[/code]) with spaces, adds spaces before uppercase letters in the middle of a word, converts all letters to lowercase, then converts the first one and each one following a space to uppercase.
+ [codeblocks]
+ [gdscript]
+ "move_local_x".capitalize() # Returns "Move Local X"
+ "sceneFile_path".capitalize() # Returns "Scene File Path"
+ [/gdscript]
+ [csharp]
+ "move_local_x".Capitalize(); // Returns "Move Local X"
+ "sceneFile_path".Capitalize(); // Returns "Scene File Path"
+ [/csharp]
+ [/codeblocks]
+ [b]Note:[/b] This method not the same as the default appearance of properties in the Inspector dock, as it does not capitalize acronyms ([code]"2D"[/code], [code]"FPS"[/code], [code]"PNG"[/code], etc.) as you may expect.
</description>
</method>
<method name="casecmp_to" qualifiers="const">
<return type="int" />
<param index="0" name="to" type="String" />
<description>
- Performs a case-sensitive comparison to another string. Returns [code]-1[/code] if less than, [code]1[/code] if greater than, or [code]0[/code] if equal. "less than" or "greater than" are determined by the [url=https://en.wikipedia.org/wiki/List_of_Unicode_characters]Unicode code points[/url] of each string, which roughly matches the alphabetical order.
- [b]Behavior with different string lengths:[/b] Returns [code]1[/code] if the "base" string is longer than the [param to] string or [code]-1[/code] if the "base" string is shorter than the [param to] string. Keep in mind this length is determined by the number of Unicode codepoints, [i]not[/i] the actual visible characters.
- [b]Behavior with empty strings:[/b] Returns [code]-1[/code] if the "base" string is empty, [code]1[/code] if the [param to] string is empty or [code]0[/code] if both strings are empty.
- To get a boolean result from a string comparison, use the [code]==[/code] operator instead. See also [method nocasecmp_to] and [method naturalnocasecmp_to].
+ Performs a case-sensitive comparison to another string. Returns [code]-1[/code] if less than, [code]1[/code] if greater than, or [code]0[/code] if equal. "Less than" and "greater than" are determined by the [url=https://en.wikipedia.org/wiki/List_of_Unicode_characters]Unicode code points[/url] of each string, which roughly matches the alphabetical order.
+ With different string lengths, returns [code]1[/code] if this string is longer than the [param to] string, or [code]-1[/code] if shorter. Note that the length of empty strings is [i]always[/i] [code]0[/code].
+ To get a [bool] result from a string comparison, use the [code]==[/code] operator instead. See also [method nocasecmp_to] and [method naturalnocasecmp_to].
</description>
</method>
<method name="chr" qualifiers="static">
<return type="String" />
<param index="0" name="char" type="int" />
<description>
- Directly converts an decimal integer to a unicode character. Tables of these characters can be found in various locations, for example [url=https://unicodelookup.com/]here.[/url]
+ Returns a single Unicode character from the decimal [param char]. You may use [url=https://unicodelookup.com/]unicodelookup.com[/url] or [url=https://www.unicode.org/charts/]unicode.org[/url] as points of reference.
[codeblock]
- print(String.chr(65)) # Prints "A"
+ print(String.chr(65)) # Prints "A"
print(String.chr(129302)) # Prints "🤖" (robot face emoji)
[/codeblock]
</description>
@@ -115,7 +129,19 @@
<return type="bool" />
<param index="0" name="what" type="String" />
<description>
- Returns [code]true[/code] if the string contains the given string.
+ Returns [code]true[/code] if the string contains [param what]. In GDScript, this corresponds to the [code]in[/code] operator.
+ [codeblocks]
+ [gdscript]
+ print("Node".contains("de")) # Prints true
+ print("team".contains("I")) # Prints false
+ print("I" in "team") # Prints false
+ [/gdscript]
+ [csharp]
+ GD.Print("Node".Contains("de")); // Prints true
+ GD.Print("team".Contains("I")); // Prints false
+ [/csharp]
+ [/codeblocks]
+ If you need to know where [param what] is within the string, use [method find].
</description>
</method>
<method name="count" qualifiers="const">
@@ -124,7 +150,7 @@
<param index="1" name="from" type="int" default="0" />
<param index="2" name="to" type="int" default="0" />
<description>
- Returns the number of occurrences of substring [param what] between [param from] and [param to] positions. If [param from] and [param to] equals 0 the whole string will be used. If only [param to] equals 0 the remained substring will be used.
+ Returns the number of occurrences of the substring [param what] between [param from] and [param to] positions. If [param to] is 0, the search continues until the end of the string.
</description>
</method>
<method name="countn" qualifiers="const">
@@ -133,7 +159,7 @@
<param index="1" name="from" type="int" default="0" />
<param index="2" name="to" type="int" default="0" />
<description>
- Returns the number of occurrences of substring [param what] (ignoring case) between [param from] and [param to] positions. If [param from] and [param to] equals 0 the whole string will be used. If only [param to] equals 0 the remained substring will be used.
+ Returns the number of occurrences of the substring [param what] between [param from] and [param to] positions, [b]ignoring case[/b]. If [param to] is 0, the search continues until the end of the string.
</description>
</method>
<method name="dedent" qualifiers="const">
@@ -146,7 +172,7 @@
<return type="bool" />
<param index="0" name="text" type="String" />
<description>
- Returns [code]true[/code] if the string ends with the given string.
+ Returns [code]true[/code] if the string ends with the given [param text]. See also [method begins_with].
</description>
</method>
<method name="find" qualifiers="const">
@@ -154,17 +180,24 @@
<param index="0" name="what" type="String" />
<param index="1" name="from" type="int" default="0" />
<description>
- Returns the index of the [b]first[/b] case-sensitive occurrence of the specified string in this instance, or [code]-1[/code]. Optionally, the starting search index can be specified, continuing to the end of the string.
- [b]Note:[/b] If you just want to know whether a string contains a substring, use the [code]in[/code] operator as follows:
+ Returns the index of the [b]first[/b] occurrence of [param what] in this string, or [code]-1[/code] if there are none. The search's start can be specified with [param from], continuing to the end of the string.
[codeblocks]
[gdscript]
- print("i" in "team") # Will print `false`.
+ print("Team".find("I")) # Prints -1
+
+ print("Potato".find("t")) # Prints 2
+ print("Potato".find("t", 3)) # Prints 4
+ print("Potato".find("t", 5)) # Prints -1
[/gdscript]
[csharp]
- // C# has no in operator, but we can use `Contains()`.
- GD.Print("team".Contains("i")); // Will print `false`.
+ GD.Print("Team".Find("I")); // Prints -1
+
+ GD.Print("Potato".Find("t")); // Prints 2
+ GD.print("Potato".Find("t", 3)); // Prints 4
+ GD.print("Potato".Find("t", 5)); // Prints -1
[/csharp]
[/codeblocks]
+ [b]Note:[/b] If you just want to know whether the string contains [param what], use [method contains]. In GDScript, you may also use the [code]in[/code] operator.
</description>
</method>
<method name="findn" qualifiers="const">
@@ -172,7 +205,7 @@
<param index="0" name="what" type="String" />
<param index="1" name="from" type="int" default="0" />
<description>
- Returns the index of the [b]first[/b] case-insensitive occurrence of the specified string in this instance, or [code]-1[/code]. Optionally, the starting search index can be specified, continuing to the end of the string.
+ Returns the index of the [b]first[/b] [b]case-insensitive[/b] occurrence of [param what] in this string, or [code]-1[/code] if there are none. The starting search index can be specified with [param from], continuing to the end of the string.
</description>
</method>
<method name="format" qualifiers="const">
@@ -183,53 +216,64 @@
Formats the string by replacing all occurrences of [param placeholder] with the elements of [param values].
[param values] can be a [Dictionary] or an [Array]. Any underscores in [param placeholder] 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.
+ # 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.
+ # Prints "User 42 is Godot."
print("User {id} is {name}.".format({"id": 42, "name": "Godot"}))
[/codeblock]
- Some additional handling is performed when [param values] is an array. If [param placeholder] 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.
+ Some additional handling is performed when [param values] is an [Array]. If [param placeholder] does not contain an underscore, the elements of the [param values] array will be used to replace one occurrence of the placeholder in order; If an element of [param values] is another 2-element array, it'll be interpreted as a key-value pair.
[codeblock]
- # Prints: User 42 is Godot.
+ # Prints "User 42 is Godot."
print("User {} is {}.".format([42, "Godot"], "{}"))
print("User {id} is {name}.".format([["id", 42], ["name", "Godot"]]))
[/codeblock]
+ See also the [url=$DOCS_URL/tutorials/scripting/gdscript/gdscript_format_string.html]GDScript format string[/url] tutorial.
</description>
</method>
<method name="get_base_dir" qualifiers="const">
<return type="String" />
<description>
If the string is a valid file path, returns the base directory name.
+ [codeblock]
+ var dir_path = "/path/to/file.txt".get_base_dir() # dir_path is "/path/to"
+ [/codeblock]
</description>
</method>
<method name="get_basename" qualifiers="const">
<return type="String" />
<description>
- If the string is a valid file path, returns the full file path without the extension.
+ If the string is a valid file path, returns the full file path, without the extension.
+ [codeblock]
+ var base = "/path/to/file.txt".get_basename() # base is "/path/to/file"
+ [/codeblock]
</description>
</method>
<method name="get_extension" qualifiers="const">
<return type="String" />
<description>
- Returns the extension without the leading period character ([code].[/code]) if the string is a valid file name or path. If the string does not contain an extension, returns an empty string instead.
+ If the string is a valid file name or path, returns the file extension without the leading period ([code].[/code]). Otherwise, returns an empty string.
[codeblock]
- print("/path/to/file.txt".get_extension()) # "txt"
- print("file.txt".get_extension()) # "txt"
- print("file.sample.txt".get_extension()) # "txt"
- print(".txt".get_extension()) # "txt"
- print("file.txt.".get_extension()) # "" (empty string)
- print("file.txt..".get_extension()) # "" (empty string)
- print("txt".get_extension()) # "" (empty string)
- print("".get_extension()) # "" (empty string)
+ var a = "/path/to/file.txt".get_extension() # a is "txt"
+ var b = "cool.txt".get_extension() # b is "txt"
+ var c = "cool.font.tres".get_extension() # c is "tres"
+ var d = ".pack1".get_extension() # d is "pack1"
+
+ var e = "file.txt.".get_extension() # e is ""
+ var f = "file.txt..".get_extension() # f is ""
+ var g = "txt".get_extension() # g is ""
+ var h = "".get_extension() # h is ""
[/codeblock]
</description>
</method>
<method name="get_file" qualifiers="const">
<return type="String" />
<description>
- If the string is a valid file path, returns the filename.
+ If the string is a valid file path, returns the file name, including the extension.
+ [codeblock]
+ var file = "/path/to/icon.png".get_file() # file is "icon.png"
+ [/codeblock]
</description>
</method>
<method name="get_slice" qualifiers="const">
@@ -237,11 +281,11 @@
<param index="0" name="delimiter" type="String" />
<param index="1" name="slice" type="int" />
<description>
- Splits a string using a [param delimiter] and returns a substring at index [param slice]. Returns an empty string if the index doesn't exist.
- This is a more performant alternative to [method split] for cases when you need only one element from the array at a fixed index.
+ Splits the string using a [param delimiter] and returns the substring at index [param slice]. Returns an empty string if the [param slice] does not exist.
+ This is faster than [method split], if you only need one substring.
[b]Example:[/b]
[codeblock]
- print("i/am/example/string".get_slice("/", 2)) # Prints 'example'.
+ print("i/am/example/hi".get_slice("/", 2)) # Prints "example"
[/codeblock]
</description>
</method>
@@ -249,7 +293,7 @@
<return type="int" />
<param index="0" name="delimiter" type="String" />
<description>
- Splits a string using a [param delimiter] and returns a number of slices.
+ Returns the total number of slices when the string is split with the given [param delimiter] (see [method split]).
</description>
</method>
<method name="get_slicec" qualifiers="const">
@@ -257,29 +301,29 @@
<param index="0" name="delimiter" type="int" />
<param index="1" name="slice" type="int" />
<description>
- Splits a string using a Unicode character with code [param delimiter] and returns a substring at index [param slice]. Returns an empty string if the index doesn't exist.
- This is a more performant alternative to [method split] for cases when you need only one element from the array at a fixed index.
+ Splits the string using a Unicode character with code [param delimiter] and returns the substring at index [param slice]. Returns an empty string if the [param slice] does not exist.
+ This is faster than [method split], if you only need one substring.
</description>
</method>
<method name="hash" qualifiers="const">
<return type="int" />
<description>
Returns the 32-bit hash value representing the string's contents.
- [b]Note:[/b] [String]s with equal content will always produce identical hash values. However, the reverse is not true. Returning identical hash values does [i]not[/i] imply the strings are equal, because different strings can have identical hash values due to hash collisions.
+ [b]Note:[/b] Strings with equal hash values are [i]not[/i] guaranteed to be the same, as a result of hash collisions. On the countrary, strings with different hash values are guaranteed to be different.
</description>
</method>
<method name="hex_to_int" qualifiers="const">
<return type="int" />
<description>
- Converts a string containing a hexadecimal number into an integer. Hexadecimal strings can either be prefixed with [code]0x[/code] or not, and they can also start with a [code]-[/code] before the optional prefix.
+ Converts the string representing a hexadecimal number into an [int]. The string may be optionally prefixed with [code]"0x"[/code], and an additional [code]-[/code] prefix for negative numbers.
[codeblocks]
[gdscript]
- print("0xff".hex_to_int()) # Prints "255".
- print("ab".hex_to_int()) # Prints "171".
+ print("0xff".hex_to_int()) # Prints 255
+ print("ab".hex_to_int()) # Prints 171
[/gdscript]
[csharp]
- GD.Print("0xff".HexToInt()); // Prints "255".
- GD.Print("ab".HexToInt()); // Prints "171".
+ GD.Print("0xff".HexToInt()); // Prints 255
+ GD.Print("ab".HexToInt()); // Prints 171
[/csharp]
[/codeblocks]
</description>
@@ -288,17 +332,16 @@
<return type="String" />
<param index="0" name="size" type="int" />
<description>
- Converts an integer representing a number of bytes into a human-readable form.
- Note that this output is in [url=https://en.wikipedia.org/wiki/Binary_prefix#IEC_prefixes]IEC prefix format[/url], and includes [code]B[/code], [code]KiB[/code], [code]MiB[/code], [code]GiB[/code], [code]TiB[/code], [code]PiB[/code], and [code]EiB[/code].
+ Converts [param size] which represents a number of bytes into a human-readable form.
+ The result is in [url=https://en.wikipedia.org/wiki/Binary_prefix#IEC_prefixes]IEC prefix format[/url], which may end in either [code]"B"[/code], [code]"KiB"[/code], [code]"MiB"[/code], [code]"GiB"[/code], [code]"TiB"[/code], [code]"PiB"[/code], or [code]"EiB"[/code].
</description>
</method>
<method name="indent" qualifiers="const">
<return type="String" />
<param index="0" name="prefix" type="String" />
<description>
- Returns a copy of the string with lines indented with [param prefix].
- For example, the string can be indented with two tabs using [code]"\t\t"[/code], or four spaces using [code]" "[/code]. The prefix can be any string so it can also be used to comment out strings with e.g. [code]"# "[/code]. See also [method dedent] to remove indentation.
- [b]Note:[/b] Empty lines are kept empty.
+ Indents every line of the string with the given [param prefix]. Empty lines are not indented. See also [method dedent] to remove indentation.
+ For example, the string can be indented with two tabulations using [code]"\t\t"[/code], or four spaces using [code]" "[/code].
</description>
</method>
<method name="insert" qualifiers="const">
@@ -306,57 +349,65 @@
<param index="0" name="position" type="int" />
<param index="1" name="what" type="String" />
<description>
- Returns a copy of the string with the substring [param what] inserted at the given [param position].
+ Inserts [param what] at the given [param position] in the string.
</description>
</method>
<method name="is_absolute_path" qualifiers="const">
<return type="bool" />
<description>
- Returns [code]true[/code] if the string is a path to a file or directory and its starting point is explicitly defined. This includes [code]res://[/code], [code]user://[/code], [code]C:\[/code], [code]/[/code], etc.
+ Returns [code]true[/code] if the string is a path to a file or directory, and its starting point is explicitly defined. This method is the opposite of [method is_relative_path].
+ This includes all paths starting with [code]"res://"[/code], [code]"user://"[/code], [code]"C:\"[/code], [code]"/"[/code], etc.
</description>
</method>
<method name="is_empty" qualifiers="const">
<return type="bool" />
<description>
- Returns [code]true[/code] if the length of the string equals [code]0[/code].
+ Returns [code]true[/code] if the string's length is [code]0[/code] ([code]""[/code]). See also [method length].
</description>
</method>
<method name="is_relative_path" qualifiers="const">
<return type="bool" />
<description>
- Returns [code]true[/code] if the string is a path to a file or directory and its starting point is implicitly defined within the context it is being used. The starting point may refer to the current directory ([code]./[/code]), or the current [Node].
+ Returns [code]true[/code] if the string is a path, and its starting point is dependent on context. The path could begin from the current directory, or the current [Node] (if the string is derived from a [NodePath]), and may sometimes be prefixed with [code]"./"[/code]. This method is the opposite of [method is_absolute_path].
</description>
</method>
<method name="is_subsequence_of" qualifiers="const">
<return type="bool" />
<param index="0" name="text" type="String" />
<description>
- Returns [code]true[/code] if this string is a subsequence of the given string.
+ Returns [code]true[/code] if all characters of this string can be found in [param text] in their original order.
+ [codeblock]
+ var text = "Wow, incredible!"
+
+ print("inedible".is_subsequence_of(text)) # Prints true
+ print("Word!".is_subsequence_of(text)) # Prints true
+ print("Window".is_subsequence_of(text)) # Prints false
+ print("".is_subsequence_of(text)) # Prints true
+ [/codeblock]
</description>
</method>
<method name="is_subsequence_ofn" qualifiers="const">
<return type="bool" />
<param index="0" name="text" type="String" />
<description>
- Returns [code]true[/code] if this string is a subsequence of the given string, without considering case.
+ Returns [code]true[/code] if all characters of this string can be found in [param text] in their original order, [b]ignoring case[/b].
</description>
</method>
<method name="is_valid_filename" qualifiers="const">
<return type="bool" />
<description>
- Returns [code]true[/code] if this string is free from characters that aren't allowed in file names, those being:
- [code]: / \ ? * " | % &lt; &gt;[/code]
+ Returns [code]true[/code] if this string does not contain characters that are not allowed in file names ([code]:[/code] [code]/[/code] [code]\[/code] [code]?[/code] [code]*[/code] [code]"[/code] [code]|[/code] [code]%[/code] [code]&lt;[/code] [code]&gt;[/code]).
</description>
</method>
<method name="is_valid_float" qualifiers="const">
<return type="bool" />
<description>
- Returns [code]true[/code] if this string contains a valid float. This is inclusive of integers, and also supports exponents:
+ Returns [code]true[/code] if this string represents a valid floating-point number. A valid float may contain only digits, one decimal point ([code].[/code]), and the exponent letter ([code]e[/code]). It may also be prefixed with a positive ([code]+[/code]) or negative ([code]-[/code]) sign. Any valid integer is also a valid float (see [method is_valid_int]). See also [method to_float].
[codeblock]
- print("1.7".is_valid_float()) # Prints "true"
- print("24".is_valid_float()) # Prints "true"
- print("7e3".is_valid_float()) # Prints "true"
- print("Hello".is_valid_float()) # Prints "false"
+ print("1.7".is_valid_float()) # Prints true
+ print("24".is_valid_float()) # Prints true
+ print("7e3".is_valid_float()) # Prints true
+ print("Hello".is_valid_float()) # Prints false
[/codeblock]
</description>
</method>
@@ -364,57 +415,73 @@
<return type="bool" />
<param index="0" name="with_prefix" type="bool" default="false" />
<description>
- Returns [code]true[/code] if this string contains a valid hexadecimal number. If [param with_prefix] is [code]true[/code], then a validity of the hexadecimal number is determined by the [code]0x[/code] prefix, for example: [code]0xDEADC0DE[/code].
+ Returns [code]true[/code] if this string is a valid hexadecimal number. A valid hexadecimal number only contains digits or letters [code]A[/code] to [code]F[/code] (either uppercase or lowercase), and may be prefixed with a positive ([code]+[/code]) or negative ([code]-[/code]) sign.
+ If [param with_prefix] is [code]true[/code], the hexadecimal number needs to prefixed by [code]"0x"[/code] to be considered valid.
+ [codeblock]
+ print("A08E".is_valid_hex_number()) # Prints true
+ print("-AbCdEf".is_valid_hex_number()) # Prints true
+ print("2.5".is_valid_hex_number()) # Prints false
+
+ print("0xDEADC0DE".is_valid_hex_number(true)) # Prints true
+ [/codeblock]
</description>
</method>
<method name="is_valid_html_color" qualifiers="const">
<return type="bool" />
<description>
- Returns [code]true[/code] if this string contains a valid color in hexadecimal HTML notation. Other HTML notations such as named colors or [code]hsl()[/code] colors aren't considered valid by this method and will return [code]false[/code].
+ Returns [code]true[/code] if this string is a valid color in hexadecimal HTML notation. The string must be a hexadecimal value (see [method is_valid_hex_number]) of either 3, 4, 6 or 8 digits, and may be prefixed by a hash sign ([code]#[/code]). Other HTML notations for colors, such as names or [code]hsl()[/code], are not considered valid. See also [method Color.html].
</description>
</method>
<method name="is_valid_identifier" qualifiers="const">
<return type="bool" />
<description>
- Returns [code]true[/code] if this string is a valid identifier. A valid identifier may contain only letters, digits and underscores ([code]_[/code]) and the first character may not be a digit.
+ Returns [code]true[/code] if this string is a valid identifier. A valid identifier may contain only letters, digits and underscores ([code]_[/code]), and the first character may not be a digit.
[codeblock]
- print("good_ident_1".is_valid_identifier()) # Prints "true"
- print("1st_bad_ident".is_valid_identifier()) # Prints "false"
- print("bad_ident_#2".is_valid_identifier()) # Prints "false"
+ print("node_2d".is_valid_identifier()) # Prints true
+ print("TYPE_FLOAT".is_valid_identifier()) # Prints true
+ print("1st_method".is_valid_identifier()) # Prints false
+ print("MyMethod#2".is_valid_identifier()) # Prints false
[/codeblock]
</description>
</method>
<method name="is_valid_int" qualifiers="const">
<return type="bool" />
<description>
- Returns [code]true[/code] if this string contains a valid integer.
+ Returns [code]true[/code] if this string represents a valid integer. A valid integer only contains digits, and may be prefixed with a positive ([code]+[/code]) or negative ([code]-[/code]) sign. See also [method to_int].
[codeblock]
- print("7".is_valid_int()) # Prints "true"
- print("14.6".is_valid_int()) # Prints "false"
- print("L".is_valid_int()) # Prints "false"
- print("+3".is_valid_int()) # Prints "true"
- print("-12".is_valid_int()) # Prints "true"
+ print("7".is_valid_int()) # Prints true
+ print("1.65".is_valid_int()) # Prints false
+ print("Hi".is_valid_int()) # Prints false
+ print("+3".is_valid_int()) # Prints true
+ print("-12".is_valid_int()) # Prints true
[/codeblock]
</description>
</method>
<method name="is_valid_ip_address" qualifiers="const">
<return type="bool" />
<description>
- Returns [code]true[/code] if this string contains only a well-formatted IPv4 or IPv6 address. This method considers [url=https://en.wikipedia.org/wiki/Reserved_IP_addresses]reserved IP addresses[/url] such as [code]0.0.0.0[/code] as valid.
+ Returns [code]true[/code] if this string represents a well-formatted IPv4 or IPv6 address. This method considers [url=https://en.wikipedia.org/wiki/Reserved_IP_addresses]reserved IP addresses[/url] such as [code]"0.0.0.0"[/code] and [code]"ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"[/code] as valid.
</description>
</method>
<method name="join" qualifiers="const">
<return type="String" />
<param index="0" name="parts" type="PackedStringArray" />
<description>
- Returns a [String] which is the concatenation of the [param parts]. The separator between elements is the string providing this method.
+ Returns the concatenation of [param parts]' elements, with each element separated by the string calling this method. This method is the opposite of [method split].
[b]Example:[/b]
[codeblocks]
[gdscript]
- print(", ".join(["One", "Two", "Three", "Four"]))
+ var fruits = ["Apple", "Orange", "Pear", "Kiwi"]
+
+ print(", ".join(fruits)) # Prints "Apple, Orange, Pear, Kiwi"
+ print("---".join(fruits)) # Prints "Apple---Orange---Pear---Kiwi"
[/gdscript]
[csharp]
- GD.Print(String.Join(",", new string[] {"One", "Two", "Three", "Four"}));
+ var fruits = new string[] {"Apple", "Orange", "Pear", "Kiwi"};
+
+ // In C#, this method is static.
+ GD.Print(string.Join(", ", fruits); // Prints "Apple, Orange, Pear, Kiwi"
+ GD.Print(string.Join("---", fruits)); // Prints "Apple---Orange---Pear---Kiwi"
[/csharp]
[/codeblocks]
</description>
@@ -422,25 +489,24 @@
<method name="json_escape" qualifiers="const">
<return type="String" />
<description>
- Returns a copy of the string with special characters escaped using the JSON standard.
+ Returns a copy of the string with special characters escaped using the JSON standard. Because it closely matches the C standard, it is possible to use [method c_unescape] to unescape the string, if necessary.
</description>
</method>
<method name="left" qualifiers="const">
<return type="String" />
<param index="0" name="length" type="int" />
<description>
- Returns a number of characters from the left of the string. If negative [param length] is used, the characters are counted downwards from [String]'s length.
- [b]Example:[/b]
+ Returns the first [param length] characters from the beginning of the string. If [param length] is negative, strips the last [param length] characters from the string's end.
[codeblock]
- print("sample text".left(3)) #prints "sam"
- print("sample text".left(-3)) #prints "sample t"
+ print("Hello World!".left(3)) # Prints "Hel"
+ print("Hello World!".left(-4)) # Prints "Hello Wo"
[/codeblock]
</description>
</method>
<method name="length" qualifiers="const">
<return type="int" />
<description>
- Returns the number of characters in the string.
+ Returns the number of characters in the string. Empty strings ([code]""[/code]) always return [code]0[/code]. See also [method is_empty].
</description>
</method>
<method name="lpad" qualifiers="const">
@@ -448,62 +514,60 @@
<param index="0" name="min_length" type="int" />
<param index="1" name="character" type="String" default="&quot; &quot;" />
<description>
- Formats a string to be at least [param min_length] long by adding [param character]s to the left of the string.
+ Formats the string to be at least [param min_length] long by adding [param character]s to the left of the string, if necessary. See also [method rpad].
</description>
</method>
<method name="lstrip" qualifiers="const">
<return type="String" />
<param index="0" name="chars" type="String" />
<description>
- Returns a copy of the string with characters removed from the left. The [param chars] argument is a string specifying the set of characters to be removed.
- [b]Note:[/b] The [param chars] is not a prefix. See [method trim_prefix] method that will remove a single prefix string rather than a set of characters.
+ Removes a set of characters defined in [param chars] from the string's beginning. See also [method rstrip].
+ [b]Note:[/b] [param chars] is not a prefix. Use [method trim_prefix] to remove a single prefix, rather than a set of characters.
</description>
</method>
<method name="match" qualifiers="const">
<return type="bool" />
<param index="0" name="expr" type="String" />
<description>
- Does a simple case-sensitive expression match, where [code]"*"[/code] matches zero or more arbitrary characters and [code]"?"[/code] matches any single character except a period ([code]"."[/code]). An empty string or empty expression always evaluates to [code]false[/code].
+ Does a simple expression match, where [code]*[/code] matches zero or more arbitrary characters and [code]?[/code] matches any single character except a period ([code].[/code]). An empty string or empty expression always evaluates to [code]false[/code].
</description>
</method>
<method name="matchn" qualifiers="const">
<return type="bool" />
<param index="0" name="expr" type="String" />
<description>
- Does a simple case-insensitive expression match, where [code]"*"[/code] matches zero or more arbitrary characters and [code]"?"[/code] matches any single character except a period ([code]"."[/code]). An empty string or empty expression always evaluates to [code]false[/code].
+ Does a simple [b]case-insensitive[/b] expression match, where [code]*[/code] matches zero or more arbitrary characters and [code]?[/code] matches any single character except a period ([code].[/code]). An empty string or empty expression always evaluates to [code]false[/code].
</description>
</method>
<method name="md5_buffer" qualifiers="const">
<return type="PackedByteArray" />
<description>
- Returns the MD5 hash of the string as an array of bytes.
+ Returns the [url=https://en.wikipedia.org/wiki/MD5]MD5 hash[/url] of the string as a [PackedByteArray].
</description>
</method>
<method name="md5_text" qualifiers="const">
<return type="String" />
<description>
- Returns the MD5 hash of the string as a string.
+ Returns the [url=https://en.wikipedia.org/wiki/MD5]MD5 hash[/url] of the string as another [String].
</description>
</method>
<method name="naturalnocasecmp_to" qualifiers="const">
<return type="int" />
<param index="0" name="to" type="String" />
<description>
- Performs a case-insensitive [i]natural order[/i] comparison to another string. Returns [code]-1[/code] if less than, [code]1[/code] if greater than, or [code]0[/code] if equal. "less than" or "greater than" are determined by the [url=https://en.wikipedia.org/wiki/List_of_Unicode_characters]Unicode code points[/url] of each string, which roughly matches the alphabetical order. Internally, lowercase characters will be converted to uppercase during the comparison.
- When used for sorting, natural order comparison will order suites of numbers as expected by most people. If you sort the numbers from 1 to 10 using natural order, you will get [code][1, 2, 3, ...][/code] instead of [code][1, 10, 2, 3, ...][/code].
- [b]Behavior with different string lengths:[/b] Returns [code]1[/code] if the "base" string is longer than the [param to] string or [code]-1[/code] if the "base" string is shorter than the [param to] string. Keep in mind this length is determined by the number of Unicode codepoints, [i]not[/i] the actual visible characters.
- [b]Behavior with empty strings:[/b] Returns [code]-1[/code] if the "base" string is empty, [code]1[/code] if the [param to] string is empty or [code]0[/code] if both strings are empty.
- To get a boolean result from a string comparison, use the [code]==[/code] operator instead. See also [method nocasecmp_to] and [method casecmp_to].
+ Performs a [b]case-insensitive[/b], [i]natural order[/i] comparison to another string. Returns [code]-1[/code] if less than, [code]1[/code] if greater than, or [code]0[/code] if equal. "Less than" or "greater than" are determined by the [url=https://en.wikipedia.org/wiki/List_of_Unicode_characters]Unicode code points[/url] of each string, which roughly matches the alphabetical order. Internally, lowercase characters are converted to uppercase for the comparison.
+ When used for sorting, natural order comparison orders sequences of numbers by the combined value of each digit as is often expected, instead of the single digit's value. A sorted sequence of numbered strings will be [code]["1", "2", "3", ...][/code], not [code]["1", "10", "2", "3", ...][/code].
+ With different string lengths, returns [code]1[/code] if this string is longer than the [param to] string, or [code]-1[/code] if shorter. Note that the length of empty strings is [i]always[/i] [code]0[/code].
+ To get a [bool] result from a string comparison, use the [code]==[/code] operator instead. See also [method nocasecmp_to] and [method casecmp_to].
</description>
</method>
<method name="nocasecmp_to" qualifiers="const">
<return type="int" />
<param index="0" name="to" type="String" />
<description>
- Performs a case-insensitive comparison to another string. Returns [code]-1[/code] if less than, [code]1[/code] if greater than, or [code]0[/code] if equal. "less than" or "greater than" are determined by the [url=https://en.wikipedia.org/wiki/List_of_Unicode_characters]Unicode code points[/url] of each string, which roughly matches the alphabetical order. Internally, lowercase characters will be converted to uppercase during the comparison.
- [b]Behavior with different string lengths:[/b] Returns [code]1[/code] if the "base" string is longer than the [param to] string or [code]-1[/code] if the "base" string is shorter than the [param to] string. Keep in mind this length is determined by the number of Unicode codepoints, [i]not[/i] the actual visible characters.
- [b]Behavior with empty strings:[/b] Returns [code]-1[/code] if the "base" string is empty, [code]1[/code] if the [param to] string is empty or [code]0[/code] if both strings are empty.
- To get a boolean result from a string comparison, use the [code]==[/code] operator instead. See also [method casecmp_to] and [method naturalnocasecmp_to].
+ Performs a [b]case-insensitive[/b] comparison to another string. Returns [code]-1[/code] if less than, [code]1[/code] if greater than, or [code]0[/code] if equal. "Less than" or "greater than" are determined by the [url=https://en.wikipedia.org/wiki/List_of_Unicode_characters]Unicode code points[/url] of each string, which roughly matches the alphabetical order. Internally, lowercase characters are converted to uppercase for the comparison.
+ With different string lengths, returns [code]1[/code] if this string is longer than the [param to] string, or [code]-1[/code] if shorter. Note that the length of empty strings is [i]always[/i] [code]0[/code].
+ To get a [bool] result from a string comparison, use the [code]==[/code] operator instead. See also [method casecmp_to] and [method naturalnocasecmp_to].
</description>
</method>
<method name="num" qualifiers="static">
@@ -511,20 +575,22 @@
<param index="0" name="number" type="float" />
<param index="1" name="decimals" type="int" default="-1" />
<description>
- Converts a [float] to a string representation of a decimal number.
- The number of decimal places can be specified with [param decimals]. If [param decimals] is [code]-1[/code] (default), decimal places will be automatically adjusted so that the string representation has 14 significant digits (counting both digits to the left and the right of the decimal point).
- Trailing zeros are not included in the string. The last digit will be rounded and not truncated.
+ Converts a [float] to a string representation of a decimal number, with the number of decimal places specified in [param decimals].
+ If [param decimals] is [code]-1[/code] as by default, the string representation may only have up to 14 significant digits, with digits before the decimal point having priority over digits after.
+ Trailing zeros are not included in the string. The last digit is rounded, not truncated.
[b]Example:[/b]
[codeblock]
- String.num(3.141593) # "3.141593"
- String.num(3.141593, 3) # "3.142"
- String.num(3.14159300) # "3.141593", no trailing zeros.
- # Last digit will be rounded up here, which reduces total digit count since
- # trailing zeros are removed:
- String.num(42.129999, 5) # "42.13"
- # If `decimals` is not specified, the total number of significant digits is 14:
- String.num(-0.0000012345432123454321) # "-0.00000123454321"
- String.num(-10000.0000012345432123454321) # "-10000.0000012345"
+ String.num(3.141593) # Returns "3.141593"
+ String.num(3.141593, 3) # Returns "3.142"
+ String.num(3.14159300) # Returns "3.141593"
+
+ # Here, the last digit will be rounded up,
+ # which reduces the total digit count, since trailing zeros are removed:
+ String.num(42.129999, 5) # Returns "42.13"
+
+ # If `decimals` is not specified, the maximum number of significant digits is 14:
+ String.num(-0.0000012345432123454321) # Returns "-0.00000123454321"
+ String.num(-10000.0000012345432123454321) # Returns "-10000.0000012345"
[/codeblock]
</description>
</method>
@@ -534,13 +600,31 @@
<param index="1" name="base" type="int" default="10" />
<param index="2" name="capitalize_hex" type="bool" default="false" />
<description>
- Converts a signed [int] to a string representation of a number.
+ Converts the given [param number] to a string representation, with the given [param base].
+ By default, [param base] is set to decimal ([code]10[/code]). Other common bases in programming include binary ([code]2[/code]), [url=https://en.wikipedia.org/wiki/Octal]octal[/url] ([code]8[/code]), hexadecimal ([code]16[/code]).
+ If [param capitalize_hex] is [code]true[/code], digits higher than 9 are represented in uppercase.
</description>
</method>
<method name="num_scientific" qualifiers="static">
<return type="String" />
<param index="0" name="number" type="float" />
<description>
+ Converts the given [param number] to a string representation, in scientific notation.
+ [codeblocks]
+ [gdscript]
+ var n = -5.2e8
+ print(n) # Prints -520000000
+ print(String.NumScientific(n)) # Prints -5.2e+08
+ [/gdscript]
+ [csharp]
+ // This method is not implemented in C#.
+ // Use `string.ToString()` with "e" to achieve similar results.
+ var n = -5.2e8f;
+ GD.Print(n); // Prints -520000000
+ GD.Print(n.ToString("e1")); // Prints -5.2e+008
+ [/csharp]
+ [/codeblocks]
+ [b]Note:[/b] In C#, this method is not implemented. To achieve similar results, see C#'s [url=https://learn.microsoft.com/en-us/dotnet/standard/base-types/standard-numeric-format-strings]Standard numeric format strings[/url]
</description>
</method>
<method name="num_uint64" qualifiers="static">
@@ -549,35 +633,38 @@
<param index="1" name="base" type="int" default="10" />
<param index="2" name="capitalize_hex" type="bool" default="false" />
<description>
- Converts a unsigned [int] to a string representation of a number.
+ Converts the given unsigned [int] to a string representation, with the given [param base].
+ By default, [param base] is set to decimal ([code]10[/code]). Other common bases in programming include binary ([code]2[/code]), [url=https://en.wikipedia.org/wiki/Octal]octal[/url] ([code]8[/code]), hexadecimal ([code]16[/code]).
+ If [param capitalize_hex] is [code]true[/code], digits higher than 9 are represented in uppercase.
</description>
</method>
<method name="pad_decimals" qualifiers="const">
<return type="String" />
<param index="0" name="digits" type="int" />
<description>
- Formats a number to have an exact number of [param digits] after the decimal point.
+ Formats the string representing a number to have an exact number of [param digits] [i]after[/i] the decimal point.
</description>
</method>
<method name="pad_zeros" qualifiers="const">
<return type="String" />
<param index="0" name="digits" type="int" />
<description>
- Formats a number to have an exact number of [param digits] before the decimal point.
+ Formats the string representing a number to have an exact number of [param digits] [i]before[/i] the decimal point.
</description>
</method>
<method name="path_join" qualifiers="const">
<return type="String" />
<param index="0" name="file" type="String" />
<description>
- If the string is a path, this concatenates [param file] at the end of the string as a subpath. E.g. [code]"this/is".path_join("path") == "this/is/path"[/code].
+ Concatenates [param file] at the end of the string as a subpath, adding [code]/[/code] if necessary.
+ [b]Example:[/b] [code]"this/is".path_join("path") == "this/is/path"[/code].
</description>
</method>
<method name="repeat" qualifiers="const">
<return type="String" />
<param index="0" name="count" type="int" />
<description>
- Returns original string repeated a number of times. The number of repetitions is given by the argument.
+ Repeats this string a number of times. [param count] needs to be greater than [code]0[/code]. Otherwise, returns an empty string.
</description>
</method>
<method name="replace" qualifiers="const">
@@ -585,7 +672,7 @@
<param index="0" name="what" type="String" />
<param index="1" name="forwhat" type="String" />
<description>
- Replaces occurrences of a case-sensitive substring with the given one inside the string.
+ Replaces all occurrences of [param what] inside the string with the given [param forwhat].
</description>
</method>
<method name="replacen" qualifiers="const">
@@ -593,7 +680,7 @@
<param index="0" name="what" type="String" />
<param index="1" name="forwhat" type="String" />
<description>
- Replaces occurrences of a case-insensitive substring with the given one inside the string.
+ Replaces all [b]case-insensitive[/b] occurrences of [param what] inside the string with the given [param forwhat].
</description>
</method>
<method name="rfind" qualifiers="const">
@@ -601,7 +688,7 @@
<param index="0" name="what" type="String" />
<param index="1" name="from" type="int" default="-1" />
<description>
- Returns the index of the [b]last[/b] case-sensitive occurrence of the specified string in this instance, or [code]-1[/code]. Optionally, the starting search index can be specified, continuing to the beginning of the string.
+ Returns the index of the [b]last[/b] occurrence of [param what] in this string, or [code]-1[/code] if there are none. The search's start can be specified with [param from], continuing to the beginning of the string. This method is the reverse of [method find].
</description>
</method>
<method name="rfindn" qualifiers="const">
@@ -609,18 +696,17 @@
<param index="0" name="what" type="String" />
<param index="1" name="from" type="int" default="-1" />
<description>
- Returns the index of the [b]last[/b] case-insensitive occurrence of the specified string in this instance, or [code]-1[/code]. Optionally, the starting search index can be specified, continuing to the beginning of the string.
+ Returns the index of the [b]last[/b] [b]case-insensitive[/b] occurrence of [param what] in this string, or [code]-1[/code] if there are none. The starting search index can be specified with [param from], continuing to the beginning of the string. This method is the reverse of [method findn].
</description>
</method>
<method name="right" qualifiers="const">
<return type="String" />
<param index="0" name="length" type="int" />
<description>
- Returns a number of characters from the right of the string. If negative [param length] is used, the characters are counted downwards from [String]'s length.
- [b]Example:[/b]
+ Returns the last [param length] characters from the end of the string. If [param length] is negative, strips the first [param length] characters from the string's beginning.
[codeblock]
- print("sample text".right(3)) #prints "ext"
- print("sample text".right(-3)) #prints "ple text"
+ print("Hello World!".right(3)) # Prints "ld!"
+ print("Hello World!".right(-4)) # Prints "o World!"
[/codeblock]
</description>
</method>
@@ -629,7 +715,7 @@
<param index="0" name="min_length" type="int" />
<param index="1" name="character" type="String" default="&quot; &quot;" />
<description>
- Formats a string to be at least [param min_length] long by adding [param character]s to the right of the string.
+ Formats the string to be at least [param min_length] long, by adding [param character]s to the right of the string, if necessary. See also [method lpad].
</description>
</method>
<method name="rsplit" qualifiers="const">
@@ -638,21 +724,21 @@
<param index="1" name="allow_empty" type="bool" default="true" />
<param index="2" name="maxsplit" type="int" default="0" />
<description>
- Splits the string by a [param delimiter] string and returns an array of the substrings, starting from right. If [param delimiter] is an empty string, each substring will be a single character.
- The splits in the returned array are sorted in the same order as the original string, from left to right.
- If [param allow_empty] 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 [param maxsplit] is specified, it defines the number of splits to do from the right up to [param maxsplit]. The default value of 0 means that all items are split, thus giving the same result as [method split].
+ Splits the string using a [param delimiter] and returns an array of the substrings, starting from the end of the string. The splits in the returned array appear in the same order as the original string. If [param delimiter] is an empty string, each substring will be a single character.
+ If [param allow_empty] is [code]false[/code], empty strings between adjacent delimiters are excluded from the array.
+ If [param maxsplit] is greater than [code]0[/code], the number of splits may not exceed [param maxsplit]. By default, the entire string is split, which is mostly identical to [method split].
[b]Example:[/b]
[codeblocks]
[gdscript]
var some_string = "One,Two,Three,Four"
var some_array = some_string.rsplit(",", true, 1)
+
print(some_array.size()) # Prints 2
- print(some_array[0]) # Prints "One,Two,Three"
- print(some_array[1]) # Prints "Four"
+ print(some_array[0]) # Prints "One,Two,Three"
+ print(some_array[1]) # Prints "Four"
[/gdscript]
[csharp]
- // There is no Rsplit.
+ // In C#, there is no String.RSplit() method.
[/csharp]
[/codeblocks]
</description>
@@ -661,51 +747,55 @@
<return type="String" />
<param index="0" name="chars" type="String" />
<description>
- Returns a copy of the string with characters removed from the right. The [param chars] argument is a string specifying the set of characters to be removed.
- [b]Note:[/b] The [param chars] is not a suffix. See [method trim_suffix] method that will remove a single suffix string rather than a set of characters.
+ Removes a set of characters defined in [param chars] from the string's end. See also [method lstrip].
+ [b]Note:[/b] [param chars] is not a suffix. Use [method trim_suffix] to remove a single suffix, rather than a set of characters.
</description>
</method>
<method name="sha1_buffer" qualifiers="const">
<return type="PackedByteArray" />
<description>
- Returns the SHA-1 hash of the string as an array of bytes.
+ Returns the [url=https://en.wikipedia.org/wiki/SHA-1]SHA-1[/url] hash of the string as a [PackedByteArray].
</description>
</method>
<method name="sha1_text" qualifiers="const">
<return type="String" />
<description>
- Returns the SHA-1 hash of the string as a string.
+ Returns the [url=https://en.wikipedia.org/wiki/SHA-1]SHA-1[/url] hash of the string as another [String].
</description>
</method>
<method name="sha256_buffer" qualifiers="const">
<return type="PackedByteArray" />
<description>
- Returns the SHA-256 hash of the string as an array of bytes.
+ Returns the [url=https://en.wikipedia.org/wiki/SHA-2]SHA-256[/url] hash of the string as a [PackedByteArray].
</description>
</method>
<method name="sha256_text" qualifiers="const">
<return type="String" />
<description>
- Returns the SHA-256 hash of the string as a string.
+ Returns the [url=https://en.wikipedia.org/wiki/SHA-2]SHA-256[/url] hash of the string as another [String].
</description>
</method>
<method name="similarity" qualifiers="const">
<return type="float" />
<param index="0" name="text" type="String" />
<description>
- Returns the similarity index ([url=https://en.wikipedia.org/wiki/S%C3%B8rensen%E2%80%93Dice_coefficient]Sorensen-Dice coefficient[/url]) of this string compared to another. A result of 1.0 means totally similar, while 0.0 means totally dissimilar.
+ Returns the similarity index ([url=https://en.wikipedia.org/wiki/S%C3%B8rensen%E2%80%93Dice_coefficient]Sorensen-Dice coefficient[/url]) of this string compared to another. A result of [code]1.0[/code] means totally similar, while [code]0.0[/code] means totally dissimilar.
[codeblock]
- print("ABC123".similarity("ABC123")) # Prints "1"
- print("ABC123".similarity("XYZ456")) # Prints "0"
- print("ABC123".similarity("123ABC")) # Prints "0.8"
- print("ABC123".similarity("abc123")) # Prints "0.4"
+ print("ABC123".similarity("ABC123")) # Prints 1.0
+ print("ABC123".similarity("XYZ456")) # Prints 0.0
+ print("ABC123".similarity("123ABC")) # Prints 0.8
+ print("ABC123".similarity("abc123")) # Prints 0.4
[/codeblock]
</description>
</method>
<method name="simplify_path" qualifiers="const">
<return type="String" />
<description>
- Returns a simplified canonical path.
+ If the string is a valid file path, converts the string into a canonical path. This is the shortest possible path, without [code]"./"[/code], and all the unnecessary [code]".."[/code] and [code]"/"[/code].
+ [codeblock]
+ var simple_path = "./path/to///../file".simplify_path()
+ print(simple_path) # Prints "path/file"
+ [/codeblock]
</description>
</method>
<method name="split" qualifiers="const">
@@ -714,37 +804,43 @@
<param index="1" name="allow_empty" type="bool" default="true" />
<param index="2" name="maxsplit" type="int" default="0" />
<description>
- Splits the string by a [param delimiter] string and returns an array of the substrings. The [param delimiter] can be of any length. If [param delimiter] is an empty string, each substring will be a single character.
- If [param allow_empty] 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 [param maxsplit] is specified, it defines the number of splits to do from the left up to [param maxsplit]. 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.
+ Splits the string using a [param delimiter] and returns an array of the substrings. If [param delimiter] is an empty string, each substring will be a single character. This method is the opposite of [method join].
+ If [param allow_empty] is [code]false[/code], empty strings between adjacent delimiters are excluded from the array.
+ If [param maxsplit] is greater than [code]0[/code], the number of splits may not exceed [param maxsplit]. By default, the entire string is split.
[b]Example:[/b]
[codeblocks]
[gdscript]
- var some_string = "One,Two,Three,Four"
- var some_array = some_string.split(",", true, 1)
- print(some_array.size()) # Prints 2
- print(some_array[0]) # Prints "Four"
- print(some_array[1]) # Prints "Three,Two,One"
+ var some_array = "One,Two,Three,Four".split(",", true, 2)
+
+ print(some_array.size()) # Prints 3
+ print(some_array[0]) # Prints "One"
+ print(some_array[1]) # Prints "Two"
+ print(some_array[2]) # Prints "Three,Four"
[/gdscript]
[csharp]
- var someString = "One,Two,Three,Four";
- var someArray = someString.Split(",", true); // This is as close as it gets to Godots API.
- GD.Print(someArray[0]); // Prints "Four"
- GD.Print(someArray[1]); // Prints "Three,Two,One"
+ // C#'s `Split()` does not support the `maxsplit` parameter.
+ var someArray = "One,Two,Three".Split(",");
+
+ GD.Print(someArray[0]); // Prints "One"
+ GD.Print(someArray[1]); // Prints "Two"
+ GD.Print(someArray[2]); // Prints "Three"
[/csharp]
[/codeblocks]
- If you need to split strings with more complex rules, use the [RegEx] class instead.
+ [b]Note:[/b] If you only need one substring from the array, consider using [method get_slice] which is faster. If you need to split strings with more complex rules, use the [RegEx] class instead.
</description>
</method>
<method name="split_floats" qualifiers="const">
- <return type="PackedFloat32Array" />
+ <return type="PackedFloat64Array" />
<param index="0" name="delimiter" type="String" />
<param index="1" name="allow_empty" type="bool" default="true" />
<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 [param allow_empty] 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.
+ Splits the string into floats by using a [param delimiter] and returns a [PackedFloat64Array].
+ If [param allow_empty] is [code]false[/code], empty or invalid [float] conversions between adjacent delimiters are excluded.
+ [codeblock]
+ var a = "1,2,4.5".split_floats(",") # a is [1.0, 2.0, 4.5]
+ var c = "1| ||4.5".split_floats("|") # c is [1.0, 0.0, 0.0, 4.5]
+ var b = "1| ||4.5".split_floats("|", false) # b is [1.0, 4.5]
+ [/codeblock]
</description>
</method>
<method name="strip_edges" qualifiers="const">
@@ -752,13 +848,14 @@
<param index="0" name="left" type="bool" default="true" />
<param index="1" name="right" type="bool" default="true" />
<description>
- Returns a copy of the string stripped of any non-printable character (including tabulations, spaces and line breaks) at the beginning and the end. The optional arguments are used to toggle stripping on the left and right edges respectively.
+ Strips all non-printable characters from the beginning and the end of the string. These include spaces, tabulations ([code]\t[/code]), and newlines ([code]\n[/code] [code]\r[/code]).
+ If [param left] is [code]false[/code], ignores the string's beginning. Likewise, if [param right] is [code]false[/code], ignores the string's end.
</description>
</method>
<method name="strip_escapes" qualifiers="const">
<return type="String" />
<description>
- Returns a copy of the string stripped of any escape character. These include all non-printable control characters of the first page of the ASCII table (&lt; 32), such as tabulation ([code]\t[/code] in C) and newline ([code]\n[/code] and [code]\r[/code]) characters, but not spaces.
+ Strips all escape characters from the string. These include all non-printable control characters of the first page of the ASCII table (values from 0 to 31), such as tabulation ([code]\t[/code]) and newline ([code]\n[/code], [code]\r[/code]) characters, but [i]not[/i] spaces.
</description>
</method>
<method name="substr" qualifiers="const">
@@ -766,13 +863,13 @@
<param index="0" name="from" type="int" />
<param index="1" name="len" type="int" default="-1" />
<description>
- Returns part of the string from the position [param from] with length [param len]. Argument [param len] is optional and using [code]-1[/code] will return remaining characters from given position.
+ Returns part of the string from the position [param from] with length [param len]. If [param len] is [code]-1[/code] (as by default), returns the rest of the string starting from the given position.
</description>
</method>
<method name="to_ascii_buffer" qualifiers="const">
<return type="PackedByteArray" />
<description>
- Converts the String (which is a character array) to ASCII/Latin-1 encoded [PackedByteArray] (which is an array of bytes). The conversion is faster compared to [method to_utf8_buffer], as this method assumes that all the characters in the String are ASCII/Latin-1 characters, unsupported characters are replaced with spaces.
+ Converts the string to an [url=https://en.wikipedia.org/wiki/ASCII]ASCII[/url]/Latin-1 encoded [PackedByteArray]. This method is slightly faster than [method to_utf8_buffer], but replaces all unsupported characters with spaces.
</description>
</method>
<method name="to_camel_case" qualifiers="const">
@@ -784,23 +881,25 @@
<method name="to_float" qualifiers="const">
<return type="float" />
<description>
- Converts a string containing a decimal number into a [code]float[/code]. The method will stop on the first non-number character except the first [code].[/code] (decimal point), and [code]e[/code] which is used for exponential.
+ Converts the string representing a decimal number into a [float]. This method stops on the first non-number character, except the first decimal point ([code].[/code]) and the exponent letter ([code]e[/code]). See also [method is_valid_float].
[codeblock]
- print("12.3".to_float()) # 12.3
- print("1.2.3".to_float()) # 1.2
- print("12ab3".to_float()) # 12
- print("1e3".to_float()) # 1000
+ var a = "12.35".to_float() # a is 12.35
+ var b = "1.2.3".to_float() # b is 1.2
+ var c = "12xy3".to_float() # c is 12.0
+ var d = "1e3".to_float() # d is 1000.0
+ var e = "Hello!".to_int() # e is 0.0
[/codeblock]
</description>
</method>
<method name="to_int" qualifiers="const">
<return type="int" />
<description>
- Converts a string containing an integer number into an [code]int[/code]. The method will remove any non-number character and stop if it encounters a [code].[/code].
+ Converts the string representing an integer number into an [int]. This method removes any non-number character and stops at the first decimal point ([code].[/code]). See also [method is_valid_int].
[codeblock]
- print("123".to_int()) # 123
- print("a1b2c3".to_int()) # 123
- print("1.2.3".to_int()) # 1
+ var a = "123".to_int() # a is 123
+ var b = "x1y2z3".to_int() # b is 123
+ var c = "-1.2.3".to_int() # c is -1
+ var d = "Hello!".to_int() # d is 0
[/codeblock]
</description>
</method>
@@ -831,33 +930,33 @@
<method name="to_utf16_buffer" qualifiers="const">
<return type="PackedByteArray" />
<description>
- Converts the String (which is an array of characters) to UTF-16 encoded [PackedByteArray] (which is an array of bytes).
+ Converts the string to a [url=https://en.wikipedia.org/wiki/UTF-16]UTF-16[/url] encoded [PackedByteArray].
</description>
</method>
<method name="to_utf32_buffer" qualifiers="const">
<return type="PackedByteArray" />
<description>
- Converts the String (which is an array of characters) to UTF-32 encoded [PackedByteArray] (which is an array of bytes).
+ Converts the string to a [url=https://en.wikipedia.org/wiki/UTF-32]UTF-32[/url] encoded [PackedByteArray].
</description>
</method>
<method name="to_utf8_buffer" qualifiers="const">
<return type="PackedByteArray" />
<description>
- Converts the String (which is an array of characters) to UTF-8 encode [PackedByteArray] (which is an array of bytes). The conversion is a bit slower than [method to_ascii_buffer], but supports all UTF-8 characters. Therefore, you should prefer this function over [method to_ascii_buffer].
+ Converts the string to a [url=https://en.wikipedia.org/wiki/UTF-8]UTF-8[/url] encoded [PackedByteArray]. This method is slightly slower than [method to_ascii_buffer], but supports all UTF-8 characters. For most cases, prefer using this method.
</description>
</method>
<method name="trim_prefix" qualifiers="const">
<return type="String" />
<param index="0" name="prefix" type="String" />
<description>
- Removes a given string from the start if it starts with it or leaves the string unchanged.
+ Removes the given [param prefix] from the start of the string, or returns the string unchanged.
</description>
</method>
<method name="trim_suffix" qualifiers="const">
<return type="String" />
<param index="0" name="suffix" type="String" />
<description>
- Removes a given string from the end if it ends with it or leaves the string unchanged.
+ Removes the given [param suffix] from the end of the string, or returns the string unchanged.
</description>
</method>
<method name="unicode_at" qualifiers="const">
@@ -870,13 +969,15 @@
<method name="uri_decode" qualifiers="const">
<return type="String" />
<description>
- Decodes a string in URL encoded format. This is meant to decode parameters in a URL when receiving an HTTP request.
+ Decodes the string from its URL-encoded format. This method is meant to properly decode the parameters in a URL when receiving an HTTP request.
[codeblocks]
[gdscript]
- print("https://example.org/?escaped=" + "Godot%20Engine%3A%27docs%27".uri_decode())
+ var url = "$DOCS_URL/?highlight=Godot%20Engine%3%docs"
+ print(url.uri_decode()) # Prints "$DOCS_URL/?highlight=Godot Engine:docs"
[/gdscript]
[csharp]
- GD.Print("https://example.org/?escaped=" + "Godot%20Engine%3a%27Docs%27".URIDecode());
+ var url = "$DOCS_URL/?highlight=Godot%20Engine%3%docs"
+ GD.Print(url.URIDecode()) // Prints "$DOCS_URL/?highlight=Godot Engine:docs"
[/csharp]
[/codeblocks]
</description>
@@ -884,13 +985,19 @@
<method name="uri_encode" qualifiers="const">
<return type="String" />
<description>
- Encodes a string to URL friendly format. This is meant to encode parameters in a URL when sending an HTTP request.
+ Encodes the string to URL-friendly format. This method is meant to properly encode the parameters in a URL when sending an HTTP request.
[codeblocks]
[gdscript]
- print("https://example.org/?escaped=" + "Godot Engine:'docs'".uri_encode())
+ var prefix = "$DOCS_URL/?highlight="
+ var url = prefix + "Godot Engine:docs".uri_encode()
+
+ print(url) # Prints "$DOCS_URL/?highlight=Godot%20Engine%3%docs"
[/gdscript]
[csharp]
- GD.Print("https://example.org/?escaped=" + "Godot Engine:'docs'".URIEncode());
+ var prefix = "$DOCS_URL/?highlight=";
+ var url = prefix + "Godot Engine:docs".URIEncode();
+
+ GD.Print(url); // Prints "$DOCS_URL/?highlight=Godot%20Engine%3%docs"
[/csharp]
[/codeblocks]
</description>
@@ -898,7 +1005,7 @@
<method name="validate_node_name" qualifiers="const">
<return type="String" />
<description>
- Removes any characters from the string that are prohibited in [Node] names ([code].[/code] [code]:[/code] [code]@[/code] [code]/[/code] [code]"[/code]).
+ Removes all characters that are not allowed in [member Node.name] from the string ([code].[/code] [code]:[/code] [code]@[/code] [code]/[/code] [code]"[/code] [code]%[/code]).
</description>
</method>
<method name="xml_escape" qualifiers="const">
@@ -920,66 +1027,94 @@
<return type="bool" />
<param index="0" name="right" type="String" />
<description>
+ Returns [code]true[/code] if both strings do not contain the same sequence of characters.
</description>
</operator>
<operator name="operator !=">
<return type="bool" />
<param index="0" name="right" type="StringName" />
<description>
+ Returns [code]true[/code] if this [String] is not equivalent to the given [StringName].
</description>
</operator>
<operator name="operator %">
<return type="String" />
<param index="0" name="right" type="Variant" />
<description>
+ Formats the [String], replacing the placeholders with one or more parameters.
+ To pass multiple parameters, [param right] needs to be an [Array].
+ [codeblock]
+ print("I caught %d fishes!" % 2) # Prints "I caught 2 fishes!"
+
+ var my_message = "Travelling to %s, at %2.2f per second."
+ var location = "Deep Valley"
+ var speed = 40.3485
+ print(my_message % [location, speed]) # Prints "Travelling to Deep Valley, at 40.35 km/h."
+ [/codeblock]
+ In C#, there is no direct equivalent to this operator. Use the [method format] method, instead.
+ For more information, see the [url=$DOCS_URL/tutorials/scripting/gdscript/gdscript_format_string.html]GDScript format strings[/url] tutorial.
</description>
</operator>
<operator name="operator +">
<return type="String" />
<param index="0" name="right" type="String" />
<description>
+ Appends [param right] at the end of this [String], also known as a string concatenation.
+ </description>
+ </operator>
+ <operator name="operator +">
+ <return type="String" />
+ <param index="0" name="right" type="StringName" />
+ <description>
</description>
</operator>
<operator name="operator &lt;">
<return type="bool" />
<param index="0" name="right" type="String" />
<description>
+ Returns [code]true[/code] if the left [String] comes before [param right] in [url=https://en.wikipedia.org/wiki/List_of_Unicode_characters]Unicode order[/url], which roughly matches the alphabetical order. Useful for sorting.
</description>
</operator>
<operator name="operator &lt;=">
<return type="bool" />
<param index="0" name="right" type="String" />
<description>
+ Returns [code]true[/code] if the left [String] comes before [param right] in [url=https://en.wikipedia.org/wiki/List_of_Unicode_characters]Unicode order[/url], which roughly matches the alphabetical order, or if both are equal.
</description>
</operator>
<operator name="operator ==">
<return type="bool" />
<param index="0" name="right" type="String" />
<description>
+ Returns [code]true[/code] if both strings contain the same sequence of characters.
</description>
</operator>
<operator name="operator ==">
<return type="bool" />
<param index="0" name="right" type="StringName" />
<description>
+ Returns [code]true[/code] if this [String] is equivalent to the given [StringName].
</description>
</operator>
<operator name="operator &gt;">
<return type="bool" />
<param index="0" name="right" type="String" />
<description>
+ Returns [code]true[/code] if the left [String] comes after [param right] in [url=https://en.wikipedia.org/wiki/List_of_Unicode_characters]Unicode order[/url], which roughly matches the alphabetical order. Useful for sorting.
</description>
</operator>
<operator name="operator &gt;=">
<return type="bool" />
<param index="0" name="right" type="String" />
<description>
+ Returns [code]true[/code] if the left [String] comes after [param right] in [url=https://en.wikipedia.org/wiki/List_of_Unicode_characters]Unicode order[/url], which roughly matches the alphabetical order, or if both are equal.
</description>
</operator>
<operator name="operator []">
<return type="String" />
<param index="0" name="index" type="int" />
<description>
+ Returns a new [String] that only contains the character at [param index]. Indices start from [code]0[/code]. If [param index] is greater or equal to [code]0[/code], the character is fetched starting from the beginning of the string. If [param index] is a negative value, it is fetched starting from the end. Accessing a string out-of-bounds will cause a run-time error, pausing the project execution if run from the editor.
</description>
</operator>
</operators>
diff --git a/doc/classes/StringName.xml b/doc/classes/StringName.xml
index c40d8929fc..b46e39b8d7 100644
--- a/doc/classes/StringName.xml
+++ b/doc/classes/StringName.xml
@@ -5,8 +5,10 @@
</brief_description>
<description>
[StringName]s are immutable strings designed for general-purpose representation of unique names (also called "string interning"). [StringName] ensures that only one instance of a given name exists (so two [StringName]s with the same value are the same object). Comparing them is much faster than with regular [String]s, because only the pointers are compared, not the whole strings.
- You will usually just pass a [String] to methods expecting a [StringName] and it will be automatically converted, but you may occasionally want to construct a [StringName] ahead of time with [StringName] or the literal syntax [code]&amp;"example"[/code].
+ You will usually just pass a [String] to methods expecting a [StringName] and it will be automatically converted, but you may occasionally want to construct a [StringName] ahead of time with [StringName] or, in GDScript, the literal syntax [code]&amp;"example"[/code].
See also [NodePath], which is a similar concept specifically designed to store pre-parsed node paths.
+ Some string methods have corresponding variations. Variations suffixed with [code]n[/code] ([method countn], [method findn], [method replacen], etc.) are [b]case-insensitive[/b] (they make no distinction between uppercase and lowercase letters). Method variations prefixed with [code]r[/code] ([method rfind], [method rsplit], etc.) are reversed, and start from the end of the string, instead of the beginning.
+ [b]Note:[/b] In a boolean context, a [StringName] will evaluate to [code]false[/code] if it is empty ([code]StringName("")[/code]). Otherwise, a [StringName] will always evaluate to [code]true[/code].
</description>
<tutorials>
</tutorials>
@@ -28,15 +30,902 @@
<return type="StringName" />
<param index="0" name="from" type="String" />
<description>
- Creates a new [StringName] from the given [String]. [code]StringName("example")[/code] is equivalent to [code]&amp;"example"[/code].
+ Creates a new [StringName] from the given [String]. In GDScript, [code]StringName("example")[/code] is equivalent to [code]&amp;"example"[/code].
</description>
</constructor>
</constructors>
<methods>
+ <method name="begins_with" qualifiers="const">
+ <return type="bool" />
+ <param index="0" name="text" type="String" />
+ <description>
+ Returns [code]true[/code] if the string begins with the given [param text]. See also [method ends_with].
+ </description>
+ </method>
+ <method name="bigrams" qualifiers="const">
+ <return type="PackedStringArray" />
+ <description>
+ Returns an array containing the bigrams (pairs of consecutive characters) of this string.
+ [codeblock]
+ print("Get up!".bigrams()) # Prints ["Ge", "et", "t ", " u", "up", "p!"]
+ [/codeblock]
+ </description>
+ </method>
+ <method name="bin_to_int" qualifiers="const">
+ <return type="int" />
+ <description>
+ Converts the string representing a binary number into an [int]. The string may optionally be prefixed with [code]"0b"[/code], and an additional [code]-[/code] prefix for negative numbers.
+ [codeblocks]
+ [gdscript]
+ print("101".bin_to_int()) # Prints 5
+ print("0b101".bin_to_int()) # Prints 5
+ print("-0b10".bin_to_int()) # Prints -2
+ [/gdscript]
+ [csharp]
+ GD.Print("101".BinToInt()); // Prints 5
+ GD.Print("0b101".BinToInt()); // Prints 5
+ GD.Print("-0b10".BinToInt()); // Prints -2
+ [/csharp]
+ [/codeblocks]
+ </description>
+ </method>
+ <method name="c_escape" qualifiers="const">
+ <return type="String" />
+ <description>
+ Returns a copy of the string with special characters escaped using the C language standard.
+ </description>
+ </method>
+ <method name="c_unescape" qualifiers="const">
+ <return type="String" />
+ <description>
+ Returns a copy of the string with escaped characters replaced by their meanings. Supported escape sequences are [code]\'[/code], [code]\"[/code], [code]\\[/code], [code]\a[/code], [code]\b[/code], [code]\f[/code], [code]\n[/code], [code]\r[/code], [code]\t[/code], [code]\v[/code].
+ [b]Note:[/b] Unlike the GDScript parser, this method doesn't support the [code]\uXXXX[/code] escape sequence.
+ </description>
+ </method>
+ <method name="capitalize" qualifiers="const">
+ <return type="String" />
+ <description>
+ Changes the appearance of the string: replaces underscores ([code]_[/code]) with spaces, adds spaces before uppercase letters in the middle of a word, converts all letters to lowercase, then converts the first one and each one following a space to uppercase.
+ [codeblocks]
+ [gdscript]
+ "move_local_x".capitalize() # Returns "Move Local X"
+ "sceneFile_path".capitalize() # Returns "Scene File Path"
+ [/gdscript]
+ [csharp]
+ "move_local_x".Capitalize(); // Returns "Move Local X"
+ "sceneFile_path".Capitalize(); // Returns "Scene File Path"
+ [/csharp]
+ [/codeblocks]
+ [b]Note:[/b] This method not the same as the default appearance of properties in the Inspector dock, as it does not capitalize acronyms ([code]"2D"[/code], [code]"FPS"[/code], [code]"PNG"[/code], etc.) as you may expect.
+ </description>
+ </method>
+ <method name="casecmp_to" qualifiers="const">
+ <return type="int" />
+ <param index="0" name="to" type="String" />
+ <description>
+ Performs a case-sensitive comparison to another string. Returns [code]-1[/code] if less than, [code]1[/code] if greater than, or [code]0[/code] if equal. "Less than" and "greater than" are determined by the [url=https://en.wikipedia.org/wiki/List_of_Unicode_characters]Unicode code points[/url] of each string, which roughly matches the alphabetical order.
+ With different string lengths, returns [code]1[/code] if this string is longer than the [param to] string, or [code]-1[/code] if shorter. Note that the length of empty strings is [i]always[/i] [code]0[/code].
+ To get a [bool] result from a string comparison, use the [code]==[/code] operator instead. See also [method nocasecmp_to] and [method naturalnocasecmp_to].
+ </description>
+ </method>
+ <method name="contains" qualifiers="const">
+ <return type="bool" />
+ <param index="0" name="what" type="String" />
+ <description>
+ Returns [code]true[/code] if the string contains [param what]. In GDScript, this corresponds to the [code]in[/code] operator.
+ [codeblocks]
+ [gdscript]
+ print("Node".contains("de")) # Prints true
+ print("team".contains("I")) # Prints false
+ print("I" in "team") # Prints false
+ [/gdscript]
+ [csharp]
+ GD.Print("Node".Contains("de")); // Prints true
+ GD.Print("team".Contains("I")); // Prints false
+ [/csharp]
+ [/codeblocks]
+ If you need to know where [param what] is within the string, use [method find].
+ </description>
+ </method>
+ <method name="count" qualifiers="const">
+ <return type="int" />
+ <param index="0" name="what" type="String" />
+ <param index="1" name="from" type="int" default="0" />
+ <param index="2" name="to" type="int" default="0" />
+ <description>
+ Returns the number of occurrences of the substring [param what] between [param from] and [param to] positions. If [param to] is 0, the search continues until the end of the string.
+ </description>
+ </method>
+ <method name="countn" qualifiers="const">
+ <return type="int" />
+ <param index="0" name="what" type="String" />
+ <param index="1" name="from" type="int" default="0" />
+ <param index="2" name="to" type="int" default="0" />
+ <description>
+ Returns the number of occurrences of the substring [param what] between [param from] and [param to] positions, [b]ignoring case[/b]. If [param to] is 0, the search continues until the end of the string.
+ </description>
+ </method>
+ <method name="dedent" qualifiers="const">
+ <return type="String" />
+ <description>
+ Returns a copy of the string with indentation (leading tabs and spaces) removed. See also [method indent] to add indentation.
+ </description>
+ </method>
+ <method name="ends_with" qualifiers="const">
+ <return type="bool" />
+ <param index="0" name="text" type="String" />
+ <description>
+ Returns [code]true[/code] if the string ends with the given [param text]. See also [method begins_with].
+ </description>
+ </method>
+ <method name="find" qualifiers="const">
+ <return type="int" />
+ <param index="0" name="what" type="String" />
+ <param index="1" name="from" type="int" default="0" />
+ <description>
+ Returns the index of the [b]first[/b] occurrence of [param what] in this string, or [code]-1[/code] if there are none. The search's start can be specified with [param from], continuing to the end of the string.
+ [codeblocks]
+ [gdscript]
+ print("Team".find("I")) # Prints -1
+
+ print("Potato".find("t")) # Prints 2
+ print("Potato".find("t", 3)) # Prints 4
+ print("Potato".find("t", 5)) # Prints -1
+ [/gdscript]
+ [csharp]
+ GD.Print("Team".Find("I")); // Prints -1
+
+ GD.Print("Potato".Find("t")); // Prints 2
+ GD.print("Potato".Find("t", 3)); // Prints 4
+ GD.print("Potato".Find("t", 5)); // Prints -1
+ [/csharp]
+ [/codeblocks]
+ [b]Note:[/b] If you just want to know whether the string contains [param what], use [method contains]. In GDScript, you may also use the [code]in[/code] operator.
+ </description>
+ </method>
+ <method name="findn" qualifiers="const">
+ <return type="int" />
+ <param index="0" name="what" type="String" />
+ <param index="1" name="from" type="int" default="0" />
+ <description>
+ Returns the index of the [b]first[/b] [b]case-insensitive[/b] occurrence of [param what] in this string, or [code]-1[/code] if there are none. The starting search index can be specified with [param from], continuing to the end of the string.
+ </description>
+ </method>
+ <method name="format" qualifiers="const">
+ <return type="String" />
+ <param index="0" name="values" type="Variant" />
+ <param index="1" name="placeholder" type="String" default="&quot;{_}&quot;" />
+ <description>
+ Formats the string by replacing all occurrences of [param placeholder] with the elements of [param values].
+ [param values] can be a [Dictionary] or an [Array]. Any underscores in [param placeholder] 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 [param values] is an [Array]. If [param placeholder] does not contain an underscore, the elements of the [param values] array will be used to replace one occurrence of the placeholder in order; If an element of [param values] 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]
+ See also the [url=$DOCS_URL/tutorials/scripting/gdscript/gdscript_format_string.html]GDScript format string[/url] tutorial.
+ </description>
+ </method>
+ <method name="get_base_dir" qualifiers="const">
+ <return type="String" />
+ <description>
+ If the string is a valid file path, returns the base directory name.
+ [codeblock]
+ var dir_path = "/path/to/file.txt".get_base_dir() # dir_path is "/path/to"
+ [/codeblock]
+ </description>
+ </method>
+ <method name="get_basename" qualifiers="const">
+ <return type="String" />
+ <description>
+ If the string is a valid file path, returns the full file path, without the extension.
+ [codeblock]
+ var base = "/path/to/file.txt".get_basename() # base is "/path/to/file"
+ [/codeblock]
+ </description>
+ </method>
+ <method name="get_extension" qualifiers="const">
+ <return type="String" />
+ <description>
+ If the string is a valid file name or path, returns the file extension without the leading period ([code].[/code]). Otherwise, returns an empty string.
+ [codeblock]
+ var a = "/path/to/file.txt".get_extension() # a is "txt"
+ var b = "cool.txt".get_extension() # b is "txt"
+ var c = "cool.font.tres".get_extension() # c is "tres"
+ var d = ".pack1".get_extension() # d is "pack1"
+
+ var e = "file.txt.".get_extension() # e is ""
+ var f = "file.txt..".get_extension() # f is ""
+ var g = "txt".get_extension() # g is ""
+ var h = "".get_extension() # h is ""
+ [/codeblock]
+ </description>
+ </method>
+ <method name="get_file" qualifiers="const">
+ <return type="String" />
+ <description>
+ If the string is a valid file path, returns the file name, including the extension.
+ [codeblock]
+ var file = "/path/to/icon.png".get_file() # file is "icon.png"
+ [/codeblock]
+ </description>
+ </method>
+ <method name="get_slice" qualifiers="const">
+ <return type="String" />
+ <param index="0" name="delimiter" type="String" />
+ <param index="1" name="slice" type="int" />
+ <description>
+ Splits the string using a [param delimiter] and returns the substring at index [param slice]. Returns an empty string if the [param slice] does not exist.
+ This is faster than [method split], if you only need one substring.
+ [b]Example:[/b]
+ [codeblock]
+ print("i/am/example/hi".get_slice("/", 2)) # Prints "example"
+ [/codeblock]
+ </description>
+ </method>
+ <method name="get_slice_count" qualifiers="const">
+ <return type="int" />
+ <param index="0" name="delimiter" type="String" />
+ <description>
+ Returns the total number of slices when the string is split with the given [param delimiter] (see [method split]).
+ </description>
+ </method>
+ <method name="get_slicec" qualifiers="const">
+ <return type="String" />
+ <param index="0" name="delimiter" type="int" />
+ <param index="1" name="slice" type="int" />
+ <description>
+ Splits the string using a Unicode character with code [param delimiter] and returns the substring at index [param slice]. Returns an empty string if the [param slice] does not exist.
+ This is faster than [method split], if you only need one substring.
+ </description>
+ </method>
<method name="hash" qualifiers="const">
<return type="int" />
<description>
- Returns the 32-bit hash value representing the [StringName]'s contents.
+ Returns the 32-bit hash value representing the string's contents.
+ [b]Note:[/b] Strings with equal hash values are [i]not[/i] guaranteed to be the same, as a result of hash collisions. On the countrary, strings with different hash values are guaranteed to be different.
+ </description>
+ </method>
+ <method name="hex_to_int" qualifiers="const">
+ <return type="int" />
+ <description>
+ Converts the string representing a hexadecimal number into an [int]. The string may be optionally prefixed with [code]"0x"[/code], and an additional [code]-[/code] prefix for negative numbers.
+ [codeblocks]
+ [gdscript]
+ print("0xff".hex_to_int()) # Prints 255
+ print("ab".hex_to_int()) # Prints 171
+ [/gdscript]
+ [csharp]
+ GD.Print("0xff".HexToInt()); // Prints 255
+ GD.Print("ab".HexToInt()); // Prints 171
+ [/csharp]
+ [/codeblocks]
+ </description>
+ </method>
+ <method name="indent" qualifiers="const">
+ <return type="String" />
+ <param index="0" name="prefix" type="String" />
+ <description>
+ Indents every line of the string with the given [param prefix]. Empty lines are not indented. See also [method dedent] to remove indentation.
+ For example, the string can be indented with two tabulations using [code]"\t\t"[/code], or four spaces using [code]" "[/code].
+ </description>
+ </method>
+ <method name="insert" qualifiers="const">
+ <return type="String" />
+ <param index="0" name="position" type="int" />
+ <param index="1" name="what" type="String" />
+ <description>
+ Inserts [param what] at the given [param position] in the string.
+ </description>
+ </method>
+ <method name="is_absolute_path" qualifiers="const">
+ <return type="bool" />
+ <description>
+ Returns [code]true[/code] if the string is a path to a file or directory, and its starting point is explicitly defined. This method is the opposite of [method is_relative_path].
+ This includes all paths starting with [code]"res://"[/code], [code]"user://"[/code], [code]"C:\"[/code], [code]"/"[/code], etc.
+ </description>
+ </method>
+ <method name="is_empty" qualifiers="const">
+ <return type="bool" />
+ <description>
+ Returns [code]true[/code] if the string's length is [code]0[/code] ([code]""[/code]). See also [method length].
+ </description>
+ </method>
+ <method name="is_relative_path" qualifiers="const">
+ <return type="bool" />
+ <description>
+ Returns [code]true[/code] if the string is a path, and its starting point is dependent on context. The path could begin from the current directory, or the current [Node] (if the string is derived from a [NodePath]), and may sometimes be prefixed with [code]"./"[/code]. This method is the opposite of [method is_absolute_path].
+ </description>
+ </method>
+ <method name="is_subsequence_of" qualifiers="const">
+ <return type="bool" />
+ <param index="0" name="text" type="String" />
+ <description>
+ Returns [code]true[/code] if all characters of this string can be found in [param text] in their original order.
+ [codeblock]
+ var text = "Wow, incredible!"
+
+ print("inedible".is_subsequence_of(text)) # Prints true
+ print("Word!".is_subsequence_of(text)) # Prints true
+ print("Window".is_subsequence_of(text)) # Prints false
+ print("".is_subsequence_of(text)) # Prints true
+ [/codeblock]
+ </description>
+ </method>
+ <method name="is_subsequence_ofn" qualifiers="const">
+ <return type="bool" />
+ <param index="0" name="text" type="String" />
+ <description>
+ Returns [code]true[/code] if all characters of this string can be found in [param text] in their original order, [b]ignoring case[/b].
+ </description>
+ </method>
+ <method name="is_valid_filename" qualifiers="const">
+ <return type="bool" />
+ <description>
+ Returns [code]true[/code] if this string does not contain characters that are not allowed in file names ([code]:[/code] [code]/[/code] [code]\[/code] [code]?[/code] [code]*[/code] [code]"[/code] [code]|[/code] [code]%[/code] [code]&lt;[/code] [code]&gt;[/code]).
+ </description>
+ </method>
+ <method name="is_valid_float" qualifiers="const">
+ <return type="bool" />
+ <description>
+ Returns [code]true[/code] if this string represents a valid floating-point number. A valid float may contain only digits, one decimal point ([code].[/code]), and the exponent letter ([code]e[/code]). It may also be prefixed with a positive ([code]+[/code]) or negative ([code]-[/code]) sign. Any valid integer is also a valid float (see [method is_valid_int]). See also [method to_float].
+ [codeblock]
+ print("1.7".is_valid_float()) # Prints true
+ print("24".is_valid_float()) # Prints true
+ print("7e3".is_valid_float()) # Prints true
+ print("Hello".is_valid_float()) # Prints false
+ [/codeblock]
+ </description>
+ </method>
+ <method name="is_valid_hex_number" qualifiers="const">
+ <return type="bool" />
+ <param index="0" name="with_prefix" type="bool" default="false" />
+ <description>
+ Returns [code]true[/code] if this string is a valid hexadecimal number. A valid hexadecimal number only contains digits or letters [code]A[/code] to [code]F[/code] (either uppercase or lowercase), and may be prefixed with a positive ([code]+[/code]) or negative ([code]-[/code]) sign.
+ If [param with_prefix] is [code]true[/code], the hexadecimal number needs to prefixed by [code]"0x"[/code] to be considered valid.
+ [codeblock]
+ print("A08E".is_valid_hex_number()) # Prints true
+ print("-AbCdEf".is_valid_hex_number()) # Prints true
+ print("2.5".is_valid_hex_number()) # Prints false
+
+ print("0xDEADC0DE".is_valid_hex_number(true)) # Prints true
+ [/codeblock]
+ </description>
+ </method>
+ <method name="is_valid_html_color" qualifiers="const">
+ <return type="bool" />
+ <description>
+ Returns [code]true[/code] if this string is a valid color in hexadecimal HTML notation. The string must be a hexadecimal value (see [method is_valid_hex_number]) of either 3, 4, 6 or 8 digits, and may be prefixed by a hash sign ([code]#[/code]). Other HTML notations for colors, such as names or [code]hsl()[/code], are not considered valid. See also [method Color.html].
+ </description>
+ </method>
+ <method name="is_valid_identifier" qualifiers="const">
+ <return type="bool" />
+ <description>
+ Returns [code]true[/code] if this string is a valid identifier. A valid identifier may contain only letters, digits and underscores ([code]_[/code]), and the first character may not be a digit.
+ [codeblock]
+ print("node_2d".is_valid_identifier()) # Prints true
+ print("TYPE_FLOAT".is_valid_identifier()) # Prints true
+ print("1st_method".is_valid_identifier()) # Prints false
+ print("MyMethod#2".is_valid_identifier()) # Prints false
+ [/codeblock]
+ </description>
+ </method>
+ <method name="is_valid_int" qualifiers="const">
+ <return type="bool" />
+ <description>
+ Returns [code]true[/code] if this string represents a valid integer. A valid integer only contains digits, and may be prefixed with a positive ([code]+[/code]) or negative ([code]-[/code]) sign. See also [method to_int].
+ [codeblock]
+ print("7".is_valid_int()) # Prints true
+ print("1.65".is_valid_int()) # Prints false
+ print("Hi".is_valid_int()) # Prints false
+ print("+3".is_valid_int()) # Prints true
+ print("-12".is_valid_int()) # Prints true
+ [/codeblock]
+ </description>
+ </method>
+ <method name="is_valid_ip_address" qualifiers="const">
+ <return type="bool" />
+ <description>
+ Returns [code]true[/code] if this string represents a well-formatted IPv4 or IPv6 address. This method considers [url=https://en.wikipedia.org/wiki/Reserved_IP_addresses]reserved IP addresses[/url] such as [code]"0.0.0.0"[/code] and [code]"ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"[/code] as valid.
+ </description>
+ </method>
+ <method name="join" qualifiers="const">
+ <return type="String" />
+ <param index="0" name="parts" type="PackedStringArray" />
+ <description>
+ Returns the concatenation of [param parts]' elements, with each element separated by the string calling this method. This method is the opposite of [method split].
+ [b]Example:[/b]
+ [codeblocks]
+ [gdscript]
+ var fruits = ["Apple", "Orange", "Pear", "Kiwi"]
+
+ print(", ".join(fruits)) # Prints "Apple, Orange, Pear, Kiwi"
+ print("---".join(fruits)) # Prints "Apple---Orange---Pear---Kiwi"
+ [/gdscript]
+ [csharp]
+ var fruits = new string[] {"Apple", "Orange", "Pear", "Kiwi"};
+
+ // In C#, this method is static.
+ GD.Print(string.Join(", ", fruits); // Prints "Apple, Orange, Pear, Kiwi"
+ GD.Print(string.Join("---", fruits)); // Prints "Apple---Orange---Pear---Kiwi"
+ [/csharp]
+ [/codeblocks]
+ </description>
+ </method>
+ <method name="json_escape" qualifiers="const">
+ <return type="String" />
+ <description>
+ Returns a copy of the string with special characters escaped using the JSON standard. Because it closely matches the C standard, it is possible to use [method c_unescape] to unescape the string, if necessary.
+ </description>
+ </method>
+ <method name="left" qualifiers="const">
+ <return type="String" />
+ <param index="0" name="length" type="int" />
+ <description>
+ Returns the first [param length] characters from the beginning of the string. If [param length] is negative, strips the last [param length] characters from the string's end.
+ [codeblock]
+ print("Hello World!".left(3)) # Prints "Hel"
+ print("Hello World!".left(-4)) # Prints "Hello Wo"
+ [/codeblock]
+ </description>
+ </method>
+ <method name="length" qualifiers="const">
+ <return type="int" />
+ <description>
+ Returns the number of characters in the string. Empty strings ([code]""[/code]) always return [code]0[/code]. See also [method is_empty].
+ </description>
+ </method>
+ <method name="lpad" qualifiers="const">
+ <return type="String" />
+ <param index="0" name="min_length" type="int" />
+ <param index="1" name="character" type="String" default="&quot; &quot;" />
+ <description>
+ Formats the string to be at least [param min_length] long by adding [param character]s to the left of the string, if necessary. See also [method rpad].
+ </description>
+ </method>
+ <method name="lstrip" qualifiers="const">
+ <return type="String" />
+ <param index="0" name="chars" type="String" />
+ <description>
+ Removes a set of characters defined in [param chars] from the string's beginning. See also [method rstrip].
+ [b]Note:[/b] [param chars] is not a prefix. Use [method trim_prefix] to remove a single prefix, rather than a set of characters.
+ </description>
+ </method>
+ <method name="match" qualifiers="const">
+ <return type="bool" />
+ <param index="0" name="expr" type="String" />
+ <description>
+ Does a simple expression match, where [code]*[/code] matches zero or more arbitrary characters and [code]?[/code] matches any single character except a period ([code].[/code]). An empty string or empty expression always evaluates to [code]false[/code].
+ </description>
+ </method>
+ <method name="matchn" qualifiers="const">
+ <return type="bool" />
+ <param index="0" name="expr" type="String" />
+ <description>
+ Does a simple [b]case-insensitive[/b] expression match, where [code]*[/code] matches zero or more arbitrary characters and [code]?[/code] matches any single character except a period ([code].[/code]). An empty string or empty expression always evaluates to [code]false[/code].
+ </description>
+ </method>
+ <method name="md5_buffer" qualifiers="const">
+ <return type="PackedByteArray" />
+ <description>
+ Returns the [url=https://en.wikipedia.org/wiki/MD5]MD5 hash[/url] of the string as a [PackedByteArray].
+ </description>
+ </method>
+ <method name="md5_text" qualifiers="const">
+ <return type="String" />
+ <description>
+ Returns the [url=https://en.wikipedia.org/wiki/MD5]MD5 hash[/url] of the string as another [String].
+ </description>
+ </method>
+ <method name="naturalnocasecmp_to" qualifiers="const">
+ <return type="int" />
+ <param index="0" name="to" type="String" />
+ <description>
+ Performs a [b]case-insensitive[/b], [i]natural order[/i] comparison to another string. Returns [code]-1[/code] if less than, [code]1[/code] if greater than, or [code]0[/code] if equal. "Less than" or "greater than" are determined by the [url=https://en.wikipedia.org/wiki/List_of_Unicode_characters]Unicode code points[/url] of each string, which roughly matches the alphabetical order. Internally, lowercase characters are converted to uppercase for the comparison.
+ When used for sorting, natural order comparison orders sequences of numbers by the combined value of each digit as is often expected, instead of the single digit's value. A sorted sequence of numbered strings will be [code]["1", "2", "3", ...][/code], not [code]["1", "10", "2", "3", ...][/code].
+ With different string lengths, returns [code]1[/code] if this string is longer than the [param to] string, or [code]-1[/code] if shorter. Note that the length of empty strings is [i]always[/i] [code]0[/code].
+ To get a [bool] result from a string comparison, use the [code]==[/code] operator instead. See also [method nocasecmp_to] and [method casecmp_to].
+ </description>
+ </method>
+ <method name="nocasecmp_to" qualifiers="const">
+ <return type="int" />
+ <param index="0" name="to" type="String" />
+ <description>
+ Performs a [b]case-insensitive[/b] comparison to another string. Returns [code]-1[/code] if less than, [code]1[/code] if greater than, or [code]0[/code] if equal. "Less than" or "greater than" are determined by the [url=https://en.wikipedia.org/wiki/List_of_Unicode_characters]Unicode code points[/url] of each string, which roughly matches the alphabetical order. Internally, lowercase characters are converted to uppercase for the comparison.
+ With different string lengths, returns [code]1[/code] if this string is longer than the [param to] string, or [code]-1[/code] if shorter. Note that the length of empty strings is [i]always[/i] [code]0[/code].
+ To get a [bool] result from a string comparison, use the [code]==[/code] operator instead. See also [method casecmp_to] and [method naturalnocasecmp_to].
+ </description>
+ </method>
+ <method name="pad_decimals" qualifiers="const">
+ <return type="String" />
+ <param index="0" name="digits" type="int" />
+ <description>
+ Formats the string representing a number to have an exact number of [param digits] [i]after[/i] the decimal point.
+ </description>
+ </method>
+ <method name="pad_zeros" qualifiers="const">
+ <return type="String" />
+ <param index="0" name="digits" type="int" />
+ <description>
+ Formats the string representing a number to have an exact number of [param digits] [i]before[/i] the decimal point.
+ </description>
+ </method>
+ <method name="path_join" qualifiers="const">
+ <return type="String" />
+ <param index="0" name="file" type="String" />
+ <description>
+ Concatenates [param file] at the end of the string as a subpath, adding [code]/[/code] if necessary.
+ [b]Example:[/b] [code]"this/is".path_join("path") == "this/is/path"[/code].
+ </description>
+ </method>
+ <method name="repeat" qualifiers="const">
+ <return type="String" />
+ <param index="0" name="count" type="int" />
+ <description>
+ Repeats this string a number of times. [param count] needs to be greater than [code]0[/code]. Otherwise, returns an empty string.
+ </description>
+ </method>
+ <method name="replace" qualifiers="const">
+ <return type="String" />
+ <param index="0" name="what" type="String" />
+ <param index="1" name="forwhat" type="String" />
+ <description>
+ Replaces all occurrences of [param what] inside the string with the given [param forwhat].
+ </description>
+ </method>
+ <method name="replacen" qualifiers="const">
+ <return type="String" />
+ <param index="0" name="what" type="String" />
+ <param index="1" name="forwhat" type="String" />
+ <description>
+ Replaces all [b]case-insensitive[/b] occurrences of [param what] inside the string with the given [param forwhat].
+ </description>
+ </method>
+ <method name="rfind" qualifiers="const">
+ <return type="int" />
+ <param index="0" name="what" type="String" />
+ <param index="1" name="from" type="int" default="-1" />
+ <description>
+ Returns the index of the [b]last[/b] occurrence of [param what] in this string, or [code]-1[/code] if there are none. The search's start can be specified with [param from], continuing to the beginning of the string. This method is the reverse of [method find].
+ </description>
+ </method>
+ <method name="rfindn" qualifiers="const">
+ <return type="int" />
+ <param index="0" name="what" type="String" />
+ <param index="1" name="from" type="int" default="-1" />
+ <description>
+ Returns the index of the [b]last[/b] [b]case-insensitive[/b] occurrence of [param what] in this string, or [code]-1[/code] if there are none. The starting search index can be specified with [param from], continuing to the beginning of the string. This method is the reverse of [method findn].
+ </description>
+ </method>
+ <method name="right" qualifiers="const">
+ <return type="String" />
+ <param index="0" name="length" type="int" />
+ <description>
+ Returns the last [param length] characters from the end of the string. If [param length] is negative, strips the first [param length] characters from the string's beginning.
+ [codeblock]
+ print("Hello World!".right(3)) # Prints "ld!"
+ print("Hello World!".right(-4)) # Prints "o World!"
+ [/codeblock]
+ </description>
+ </method>
+ <method name="rpad" qualifiers="const">
+ <return type="String" />
+ <param index="0" name="min_length" type="int" />
+ <param index="1" name="character" type="String" default="&quot; &quot;" />
+ <description>
+ Formats the string to be at least [param min_length] long, by adding [param character]s to the right of the string, if necessary. See also [method lpad].
+ </description>
+ </method>
+ <method name="rsplit" qualifiers="const">
+ <return type="PackedStringArray" />
+ <param index="0" name="delimiter" type="String" default="&quot;&quot;" />
+ <param index="1" name="allow_empty" type="bool" default="true" />
+ <param index="2" name="maxsplit" type="int" default="0" />
+ <description>
+ Splits the string using a [param delimiter] and returns an array of the substrings, starting from the end of the string. The splits in the returned array appear in the same order as the original string. If [param delimiter] is an empty string, each substring will be a single character.
+ If [param allow_empty] is [code]false[/code], empty strings between adjacent delimiters are excluded from the array.
+ If [param maxsplit] is greater than [code]0[/code], the number of splits may not exceed [param maxsplit]. By default, the entire string is split, which is mostly identical to [method split].
+ [b]Example:[/b]
+ [codeblocks]
+ [gdscript]
+ var some_string = "One,Two,Three,Four"
+ var some_array = some_string.rsplit(",", true, 1)
+
+ print(some_array.size()) # Prints 2
+ print(some_array[0]) # Prints "One,Two,Three"
+ print(some_array[1]) # Prints "Four"
+ [/gdscript]
+ [csharp]
+ // In C#, there is no String.RSplit() method.
+ [/csharp]
+ [/codeblocks]
+ </description>
+ </method>
+ <method name="rstrip" qualifiers="const">
+ <return type="String" />
+ <param index="0" name="chars" type="String" />
+ <description>
+ Removes a set of characters defined in [param chars] from the string's end. See also [method lstrip].
+ [b]Note:[/b] [param chars] is not a suffix. Use [method trim_suffix] to remove a single suffix, rather than a set of characters.
+ </description>
+ </method>
+ <method name="sha1_buffer" qualifiers="const">
+ <return type="PackedByteArray" />
+ <description>
+ Returns the [url=https://en.wikipedia.org/wiki/SHA-1]SHA-1[/url] hash of the string as a [PackedByteArray].
+ </description>
+ </method>
+ <method name="sha1_text" qualifiers="const">
+ <return type="String" />
+ <description>
+ Returns the [url=https://en.wikipedia.org/wiki/SHA-1]SHA-1[/url] hash of the string as another [String].
+ </description>
+ </method>
+ <method name="sha256_buffer" qualifiers="const">
+ <return type="PackedByteArray" />
+ <description>
+ Returns the [url=https://en.wikipedia.org/wiki/SHA-2]SHA-256[/url] hash of the string as a [PackedByteArray].
+ </description>
+ </method>
+ <method name="sha256_text" qualifiers="const">
+ <return type="String" />
+ <description>
+ Returns the [url=https://en.wikipedia.org/wiki/SHA-2]SHA-256[/url] hash of the string as another [String].
+ </description>
+ </method>
+ <method name="similarity" qualifiers="const">
+ <return type="float" />
+ <param index="0" name="text" type="String" />
+ <description>
+ Returns the similarity index ([url=https://en.wikipedia.org/wiki/S%C3%B8rensen%E2%80%93Dice_coefficient]Sorensen-Dice coefficient[/url]) of this string compared to another. A result of [code]1.0[/code] means totally similar, while [code]0.0[/code] means totally dissimilar.
+ [codeblock]
+ print("ABC123".similarity("ABC123")) # Prints 1.0
+ print("ABC123".similarity("XYZ456")) # Prints 0.0
+ print("ABC123".similarity("123ABC")) # Prints 0.8
+ print("ABC123".similarity("abc123")) # Prints 0.4
+ [/codeblock]
+ </description>
+ </method>
+ <method name="simplify_path" qualifiers="const">
+ <return type="String" />
+ <description>
+ If the string is a valid file path, converts the string into a canonical path. This is the shortest possible path, without [code]"./"[/code], and all the unnecessary [code]".."[/code] and [code]"/"[/code].
+ [codeblock]
+ var simple_path = "./path/to///../file".simplify_path()
+ print(simple_path) # Prints "path/file"
+ [/codeblock]
+ </description>
+ </method>
+ <method name="split" qualifiers="const">
+ <return type="PackedStringArray" />
+ <param index="0" name="delimiter" type="String" default="&quot;&quot;" />
+ <param index="1" name="allow_empty" type="bool" default="true" />
+ <param index="2" name="maxsplit" type="int" default="0" />
+ <description>
+ Splits the string using a [param delimiter] and returns an array of the substrings. If [param delimiter] is an empty string, each substring will be a single character. This method is the opposite of [method join].
+ If [param allow_empty] is [code]false[/code], empty strings between adjacent delimiters are excluded from the array.
+ If [param maxsplit] is greater than [code]0[/code], the number of splits may not exceed [param maxsplit]. By default, the entire string is split.
+ [b]Example:[/b]
+ [codeblocks]
+ [gdscript]
+ var some_array = "One,Two,Three,Four".split(",", true, 2)
+
+ print(some_array.size()) # Prints 3
+ print(some_array[0]) # Prints "One"
+ print(some_array[1]) # Prints "Two"
+ print(some_array[2]) # Prints "Three,Four"
+ [/gdscript]
+ [csharp]
+ // C#'s `Split()` does not support the `maxsplit` parameter.
+ var someArray = "One,Two,Three".Split(",");
+
+ GD.Print(someArray[0]); // Prints "One"
+ GD.Print(someArray[1]); // Prints "Two"
+ GD.Print(someArray[2]); // Prints "Three"
+ [/csharp]
+ [/codeblocks]
+ [b]Note:[/b] If you only need one substring from the array, consider using [method get_slice] which is faster. If you need to split strings with more complex rules, use the [RegEx] class instead.
+ </description>
+ </method>
+ <method name="split_floats" qualifiers="const">
+ <return type="PackedFloat64Array" />
+ <param index="0" name="delimiter" type="String" />
+ <param index="1" name="allow_empty" type="bool" default="true" />
+ <description>
+ Splits the string into floats by using a [param delimiter] and returns a [PackedFloat64Array].
+ If [param allow_empty] is [code]false[/code], empty or invalid [float] conversions between adjacent delimiters are excluded.
+ [codeblock]
+ var a = "1,2,4.5".split_floats(",") # a is [1.0, 2.0, 4.5]
+ var c = "1| ||4.5".split_floats("|") # c is [1.0, 0.0, 0.0, 4.5]
+ var b = "1| ||4.5".split_floats("|", false) # b is [1.0, 4.5]
+ [/codeblock]
+ </description>
+ </method>
+ <method name="strip_edges" qualifiers="const">
+ <return type="String" />
+ <param index="0" name="left" type="bool" default="true" />
+ <param index="1" name="right" type="bool" default="true" />
+ <description>
+ Strips all non-printable characters from the beginning and the end of the string. These include spaces, tabulations ([code]\t[/code]), and newlines ([code]\n[/code] [code]\r[/code]).
+ If [param left] is [code]false[/code], ignores the string's beginning. Likewise, if [param right] is [code]false[/code], ignores the string's end.
+ </description>
+ </method>
+ <method name="strip_escapes" qualifiers="const">
+ <return type="String" />
+ <description>
+ Strips all escape characters from the string. These include all non-printable control characters of the first page of the ASCII table (values from 0 to 31), such as tabulation ([code]\t[/code]) and newline ([code]\n[/code], [code]\r[/code]) characters, but [i]not[/i] spaces.
+ </description>
+ </method>
+ <method name="substr" qualifiers="const">
+ <return type="String" />
+ <param index="0" name="from" type="int" />
+ <param index="1" name="len" type="int" default="-1" />
+ <description>
+ Returns part of the string from the position [param from] with length [param len]. If [param len] is [code]-1[/code] (as by default), returns the rest of the string starting from the given position.
+ </description>
+ </method>
+ <method name="to_ascii_buffer" qualifiers="const">
+ <return type="PackedByteArray" />
+ <description>
+ Converts the string to an [url=https://en.wikipedia.org/wiki/ASCII]ASCII[/url]/Latin-1 encoded [PackedByteArray]. This method is slightly faster than [method to_utf8_buffer], but replaces all unsupported characters with spaces.
+ </description>
+ </method>
+ <method name="to_camel_case" qualifiers="const">
+ <return type="String" />
+ <description>
+ Returns the string converted to [code]camelCase[/code].
+ </description>
+ </method>
+ <method name="to_float" qualifiers="const">
+ <return type="float" />
+ <description>
+ Converts the string representing a decimal number into a [float]. This method stops on the first non-number character, except the first decimal point ([code].[/code]) and the exponent letter ([code]e[/code]). See also [method is_valid_float].
+ [codeblock]
+ var a = "12.35".to_float() # a is 12.35
+ var b = "1.2.3".to_float() # b is 1.2
+ var c = "12xy3".to_float() # c is 12.0
+ var d = "1e3".to_float() # d is 1000.0
+ var e = "Hello!".to_int() # e is 0.0
+ [/codeblock]
+ </description>
+ </method>
+ <method name="to_int" qualifiers="const">
+ <return type="int" />
+ <description>
+ Converts the string representing an integer number into an [int]. This method removes any non-number character and stops at the first decimal point ([code].[/code]). See also [method is_valid_int].
+ [codeblock]
+ var a = "123".to_int() # a is 123
+ var b = "x1y2z3".to_int() # b is 123
+ var c = "-1.2.3".to_int() # c is -1
+ var d = "Hello!".to_int() # d is 0
+ [/codeblock]
+ </description>
+ </method>
+ <method name="to_lower" qualifiers="const">
+ <return type="String" />
+ <description>
+ Returns the string converted to lowercase.
+ </description>
+ </method>
+ <method name="to_pascal_case" qualifiers="const">
+ <return type="String" />
+ <description>
+ Returns the string converted to [code]PascalCase[/code].
+ </description>
+ </method>
+ <method name="to_snake_case" qualifiers="const">
+ <return type="String" />
+ <description>
+ Returns the string converted to [code]snake_case[/code].
+ </description>
+ </method>
+ <method name="to_upper" qualifiers="const">
+ <return type="String" />
+ <description>
+ Returns the string converted to uppercase.
+ </description>
+ </method>
+ <method name="to_utf16_buffer" qualifiers="const">
+ <return type="PackedByteArray" />
+ <description>
+ Converts the string to a [url=https://en.wikipedia.org/wiki/UTF-16]UTF-16[/url] encoded [PackedByteArray].
+ </description>
+ </method>
+ <method name="to_utf32_buffer" qualifiers="const">
+ <return type="PackedByteArray" />
+ <description>
+ Converts the string to a [url=https://en.wikipedia.org/wiki/UTF-32]UTF-32[/url] encoded [PackedByteArray].
+ </description>
+ </method>
+ <method name="to_utf8_buffer" qualifiers="const">
+ <return type="PackedByteArray" />
+ <description>
+ Converts the string to a [url=https://en.wikipedia.org/wiki/UTF-8]UTF-8[/url] encoded [PackedByteArray]. This method is slightly slower than [method to_ascii_buffer], but supports all UTF-8 characters. For most cases, prefer using this method.
+ </description>
+ </method>
+ <method name="trim_prefix" qualifiers="const">
+ <return type="String" />
+ <param index="0" name="prefix" type="String" />
+ <description>
+ Removes the given [param prefix] from the start of the string, or returns the string unchanged.
+ </description>
+ </method>
+ <method name="trim_suffix" qualifiers="const">
+ <return type="String" />
+ <param index="0" name="suffix" type="String" />
+ <description>
+ Removes the given [param suffix] from the end of the string, or returns the string unchanged.
+ </description>
+ </method>
+ <method name="unicode_at" qualifiers="const">
+ <return type="int" />
+ <param index="0" name="at" type="int" />
+ <description>
+ Returns the character code at position [param at].
+ </description>
+ </method>
+ <method name="uri_decode" qualifiers="const">
+ <return type="String" />
+ <description>
+ Decodes the string from its URL-encoded format. This method is meant to properly decode the parameters in a URL when receiving an HTTP request.
+ [codeblocks]
+ [gdscript]
+ var url = "$DOCS_URL/?highlight=Godot%20Engine%3%docs"
+ print(url.uri_decode()) # Prints "$DOCS_URL/?highlight=Godot Engine:docs"
+ [/gdscript]
+ [csharp]
+ var url = "$DOCS_URL/?highlight=Godot%20Engine%3%docs"
+ GD.Print(url.URIDecode()) // Prints "$DOCS_URL/?highlight=Godot Engine:docs"
+ [/csharp]
+ [/codeblocks]
+ </description>
+ </method>
+ <method name="uri_encode" qualifiers="const">
+ <return type="String" />
+ <description>
+ Encodes the string to URL-friendly format. This method is meant to properly encode the parameters in a URL when sending an HTTP request.
+ [codeblocks]
+ [gdscript]
+ var prefix = "$DOCS_URL/?highlight="
+ var url = prefix + "Godot Engine:docs".uri_encode()
+
+ print(url) # Prints "$DOCS_URL/?highlight=Godot%20Engine%3%docs"
+ [/gdscript]
+ [csharp]
+ var prefix = "$DOCS_URL/?highlight=";
+ var url = prefix + "Godot Engine:docs".URIEncode();
+
+ GD.Print(url); // Prints "$DOCS_URL/?highlight=Godot%20Engine%3%docs"
+ [/csharp]
+ [/codeblocks]
+ </description>
+ </method>
+ <method name="validate_node_name" qualifiers="const">
+ <return type="String" />
+ <description>
+ Removes all characters that are not allowed in [member Node.name] from the string ([code].[/code] [code]:[/code] [code]@[/code] [code]/[/code] [code]"[/code] [code]%[/code]).
+ </description>
+ </method>
+ <method name="xml_escape" qualifiers="const">
+ <return type="String" />
+ <param index="0" name="escape_quotes" type="bool" default="false" />
+ <description>
+ Returns a copy of the string with special characters escaped using the XML standard. If [param escape_quotes] is [code]true[/code], the single quote ([code]'[/code]) and double quote ([code]"[/code]) characters are also escaped.
+ </description>
+ </method>
+ <method name="xml_unescape" qualifiers="const">
+ <return type="String" />
+ <description>
+ Returns a copy of the string with escaped characters replaced by their meanings according to the XML standard.
</description>
</method>
</methods>
@@ -45,48 +934,74 @@
<return type="bool" />
<param index="0" name="right" type="String" />
<description>
+ Returns [code]true[/code] if this [StringName] is not equivalent to the given [String].
</description>
</operator>
<operator name="operator !=">
<return type="bool" />
<param index="0" name="right" type="StringName" />
<description>
+ Returns [code]true[/code] if the [StringName] and [param right] do not refer to the same name. Comparisons between [StringName]s are much faster than regular [String] comparisons.
+ </description>
+ </operator>
+ <operator name="operator %">
+ <return type="String" />
+ <param index="0" name="right" type="Variant" />
+ <description>
+ </description>
+ </operator>
+ <operator name="operator +">
+ <return type="String" />
+ <param index="0" name="right" type="String" />
+ <description>
+ </description>
+ </operator>
+ <operator name="operator +">
+ <return type="String" />
+ <param index="0" name="right" type="StringName" />
+ <description>
</description>
</operator>
<operator name="operator &lt;">
<return type="bool" />
<param index="0" name="right" type="StringName" />
<description>
+ Returns [code]true[/code] if the left [String] comes before [param right] in [url=https://en.wikipedia.org/wiki/List_of_Unicode_characters]Unicode order[/url], which roughly matches the alphabetical order. Useful for sorting.
</description>
</operator>
<operator name="operator &lt;=">
<return type="bool" />
<param index="0" name="right" type="StringName" />
<description>
+ Returns [code]true[/code] if the left [String] comes before [param right] in [url=https://en.wikipedia.org/wiki/List_of_Unicode_characters]Unicode order[/url], which roughly matches the alphabetical order, or if both are equal.
</description>
</operator>
<operator name="operator ==">
<return type="bool" />
<param index="0" name="right" type="String" />
<description>
+ Returns [code]true[/code] if this [StringName] is equivalent to the given [String].
</description>
</operator>
<operator name="operator ==">
<return type="bool" />
<param index="0" name="right" type="StringName" />
<description>
+ Returns [code]true[/code] if the [StringName] and [param right] refer to the same name. Comparisons between [StringName]s are much faster than regular [String] comparisons.
</description>
</operator>
<operator name="operator &gt;">
<return type="bool" />
<param index="0" name="right" type="StringName" />
<description>
+ Returns [code]true[/code] if the left [StringName] comes after [param right] in [url=https://en.wikipedia.org/wiki/List_of_Unicode_characters]Unicode order[/url], which roughly matches the alphabetical order. Useful for sorting.
</description>
</operator>
<operator name="operator &gt;=">
<return type="bool" />
<param index="0" name="right" type="StringName" />
<description>
+ Returns [code]true[/code] if the left [StringName] comes after [param right] in [url=https://en.wikipedia.org/wiki/List_of_Unicode_characters]Unicode order[/url], which roughly matches the alphabetical order, or if both are equal.
</description>
</operator>
</operators>
diff --git a/doc/classes/SystemFont.xml b/doc/classes/SystemFont.xml
index b47d6ded7d..20bfd0d8ae 100644
--- a/doc/classes/SystemFont.xml
+++ b/doc/classes/SystemFont.xml
@@ -7,23 +7,32 @@
<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.
+ The returned font might be part of a font collection or be a variable font with OpenType "weight", "width" 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="allow_system_fallback" type="bool" setter="set_allow_system_fallback" getter="is_allow_system_fallback" default="true">
+ If set to [code]true[/code], system fonts can be automatically used as fallbacks.
+ </member>
<member name="antialiasing" type="int" setter="set_antialiasing" getter="get_antialiasing" enum="TextServer.FontAntialiasing" default="1">
Font anti-aliasing mode.
</member>
<member name="fallbacks" type="Font[]" setter="set_fallbacks" getter="get_fallbacks" default="[]">
Array of fallback [Font]s.
</member>
+ <member name="font_italic" type="bool" setter="set_font_italic" getter="get_font_italic" default="false">
+ If set to [code]true[/code], italic or oblique font is preferred.
+ </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 name="font_stretch" type="int" setter="set_font_stretch" getter="get_font_stretch" default="100">
+ Preferred font stretch amount, compared to a normal width. A percentage value between [code]50%[/code] and [code]200%[/code].
+ </member>
+ <member name="font_weight" type="int" setter="set_font_weight" getter="get_font_weight" default="400">
+ Preferred weight (boldness) of the font. A value in the [code]100...999[/code] range, normal font weight is [code]400[/code], bold font weight is [code]700[/code].
</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.
diff --git a/doc/classes/TabBar.xml b/doc/classes/TabBar.xml
index 713c016651..8d56cbda13 100644
--- a/doc/classes/TabBar.xml
+++ b/doc/classes/TabBar.xml
@@ -319,6 +319,7 @@
</theme_item>
<theme_item name="outline_size" data_type="constant" type="int" default="0">
The size of the tab text outline.
+ [b]Note:[/b] If using a font with [member FontFile.multichannel_signed_distance_field] enabled, its [member FontFile.msdf_pixel_range] must be set to at least [i]twice[/i] the value of [theme_item outline_size] for outline rendering to look correct. Otherwise, the outline may appear to be cut off earlier than intended.
</theme_item>
<theme_item name="font" data_type="font" type="Font">
The font used to draw tab names.
diff --git a/doc/classes/TabContainer.xml b/doc/classes/TabContainer.xml
index e2e7a0c37e..c744c9b439 100644
--- a/doc/classes/TabContainer.xml
+++ b/doc/classes/TabContainer.xml
@@ -214,6 +214,7 @@
</theme_item>
<theme_item name="outline_size" data_type="constant" type="int" default="0">
The size of the tab text outline.
+ [b]Note:[/b] If using a font with [member FontFile.multichannel_signed_distance_field] enabled, its [member FontFile.msdf_pixel_range] must be set to at least [i]twice[/i] the value of [theme_item outline_size] for outline rendering to look correct. Otherwise, the outline may appear to be cut off earlier than intended.
</theme_item>
<theme_item name="side_margin" data_type="constant" type="int" default="8">
The space at the left or right edges of the tab bar, accordingly with the current [member tab_alignment].
diff --git a/doc/classes/TextEdit.xml b/doc/classes/TextEdit.xml
index d4f5233438..1efd0f9326 100644
--- a/doc/classes/TextEdit.xml
+++ b/doc/classes/TextEdit.xml
@@ -1396,6 +1396,7 @@
</theme_item>
<theme_item name="outline_size" data_type="constant" type="int" default="0">
The size of the text outline.
+ [b]Note:[/b] If using a font with [member FontFile.multichannel_signed_distance_field] enabled, its [member FontFile.msdf_pixel_range] must be set to at least [i]twice[/i] the value of [theme_item outline_size] for outline rendering to look correct. Otherwise, the outline may appear to be cut off earlier than intended.
</theme_item>
<theme_item name="font" data_type="font" type="Font">
Sets the default [Font].
diff --git a/doc/classes/TextLine.xml b/doc/classes/TextLine.xml
index d1dfdecbd2..1ebae9889d 100644
--- a/doc/classes/TextLine.xml
+++ b/doc/classes/TextLine.xml
@@ -15,6 +15,7 @@
<param index="1" name="size" type="Vector2" />
<param index="2" name="inline_align" type="int" enum="InlineAlignment" default="5" />
<param index="3" name="length" type="int" default="1" />
+ <param index="4" name="baseline" type="float" default="0.0" />
<description>
Adds inline object to the text buffer, [param key] must be unique. In the text, object is represented as [param length] object replacement characters.
</description>
@@ -122,6 +123,7 @@
<param index="0" name="key" type="Variant" />
<param index="1" name="size" type="Vector2" />
<param index="2" name="inline_align" type="int" enum="InlineAlignment" default="5" />
+ <param index="3" name="baseline" type="float" default="0.0" />
<description>
Sets new size and alignment of embedded object.
</description>
diff --git a/doc/classes/TextParagraph.xml b/doc/classes/TextParagraph.xml
index e0729ba844..38afd9b5f8 100644
--- a/doc/classes/TextParagraph.xml
+++ b/doc/classes/TextParagraph.xml
@@ -15,6 +15,7 @@
<param index="1" name="size" type="Vector2" />
<param index="2" name="inline_align" type="int" enum="InlineAlignment" default="5" />
<param index="3" name="length" type="int" default="1" />
+ <param index="4" name="baseline" type="float" default="0.0" />
<description>
Adds inline object to the text buffer, [param key] must be unique. In the text, object is represented as [param length] object replacement characters.
</description>
@@ -228,6 +229,7 @@
<param index="0" name="key" type="Variant" />
<param index="1" name="size" type="Vector2" />
<param index="2" name="inline_align" type="int" enum="InlineAlignment" default="5" />
+ <param index="3" name="baseline" type="float" default="0.0" />
<description>
Sets new size and alignment of embedded object.
</description>
diff --git a/doc/classes/TextServer.xml b/doc/classes/TextServer.xml
index f4d92ab9b6..d2c6dee373 100644
--- a/doc/classes/TextServer.xml
+++ b/doc/classes/TextServer.xml
@@ -235,7 +235,7 @@
<param index="1" name="size" type="Vector2i" />
<param index="2" name="glyph" type="int" />
<description>
- Returns resource id of the cache texture containing the glyph.
+ Returns resource ID of the cache texture containing the glyph.
[b]Note:[/b] If there are pending glyphs to render, calling this function might trigger the texture cache update.
</description>
</method>
@@ -362,6 +362,13 @@
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_stretch" qualifiers="const">
+ <return type="int" />
+ <param index="0" name="font_rid" type="RID" />
+ <description>
+ Returns font stretch amount, compared to a normal width. A percentage value between [code]50%[/code] and [code]200%[/code].
+ </description>
+ </method>
<method name="font_get_style" qualifiers="const">
<return type="int" enum="TextServer.FontStyle" />
<param index="0" name="font_rid" type="RID" />
@@ -446,6 +453,13 @@
Returns variation coordinates for the specified font cache entry. See [method font_supported_variation_list] for more info.
</description>
</method>
+ <method name="font_get_weight" qualifiers="const">
+ <return type="int" />
+ <param index="0" name="font_rid" type="RID" />
+ <description>
+ Returns weight (boldness) of the font. A value in the [code]100...999[/code] range, normal font weight is [code]400[/code], bold font weight is [code]700[/code].
+ </description>
+ </method>
<method name="font_has_char" qualifiers="const">
<return type="bool" />
<param index="0" name="font_rid" type="RID" />
@@ -454,6 +468,13 @@
Returns [code]true[/code] if a Unicode [param char] is available in the font.
</description>
</method>
+ <method name="font_is_allow_system_fallback" qualifiers="const">
+ <return type="bool" />
+ <param index="0" name="font_rid" type="RID" />
+ <description>
+ Returns [code]true[/code] if system fonts can be automatically used as fallbacks.
+ </description>
+ </method>
<method name="font_is_force_autohinter" qualifiers="const">
<return type="bool" />
<param index="0" name="font_rid" type="RID" />
@@ -556,6 +577,14 @@
Renders the range of characters to the font cache texture.
</description>
</method>
+ <method name="font_set_allow_system_fallback">
+ <return type="void" />
+ <param index="0" name="font_rid" type="RID" />
+ <param index="1" name="allow_system_fallback" type="bool" />
+ <description>
+ If set to [code]true[/code], system fonts can be automatically used as fallbacks.
+ </description>
+ </method>
<method name="font_set_antialiasing">
<return type="void" />
<param index="0" name="font_rid" type="RID" />
@@ -783,12 +812,22 @@
Adds override for [method font_is_script_supported].
</description>
</method>
+ <method name="font_set_stretch">
+ <return type="void" />
+ <param index="0" name="font_rid" type="RID" />
+ <param index="1" name="weight" type="int" />
+ <description>
+ Sets font stretch amount, compared to a normal width. A percentage value between [code]50%[/code] and [code]200%[/code].
+ [b]Note:[/b] This value is used for font matching only and will not affect font rendering. Use [method font_set_face_index], [method font_set_variation_coordinates], or [method font_set_transform] instead.
+ </description>
+ </method>
<method name="font_set_style">
<return type="void" />
<param index="0" name="font_rid" type="RID" />
<param index="1" name="style" type="int" enum="TextServer.FontStyle" />
<description>
Sets the font style flags, see [enum FontStyle].
+ [b]Note:[/b] This value is used for font matching only and will not affect font rendering. Use [method font_set_face_index], [method font_set_variation_coordinates], [method font_set_embolden], or [method font_set_transform] instead.
</description>
</method>
<method name="font_set_style_name">
@@ -862,6 +901,15 @@
Sets variation coordinates for the specified font cache entry. See [method font_supported_variation_list] for more info.
</description>
</method>
+ <method name="font_set_weight">
+ <return type="void" />
+ <param index="0" name="font_rid" type="RID" />
+ <param index="1" name="weight" type="int" />
+ <description>
+ Sets weight (boldness) of the font. A value in the [code]100...999[/code] range, normal font weight is [code]400[/code], bold font weight is [code]700[/code].
+ [b]Note:[/b] This value is used for font matching only and will not affect font rendering. Use [method font_set_face_index], [method font_set_variation_coordinates], or [method font_set_embolden] instead.
+ </description>
+ </method>
<method name="font_supported_feature_list" qualifiers="const">
<return type="Dictionary" />
<param index="0" name="font_rid" type="RID" />
@@ -882,6 +930,7 @@
<param index="1" name="language" type="String" default="&quot;&quot;" />
<description>
Converts a number from the Western Arabic (0..9) to the numeral systems used in [param language].
+ If [param language] is omitted, the active locale will be used.
</description>
</method>
<method name="free_rid">
@@ -1049,6 +1098,7 @@
<param index="2" name="size" type="Vector2" />
<param index="3" name="inline_align" type="int" enum="InlineAlignment" default="5" />
<param index="4" name="length" type="int" default="1" />
+ <param index="5" name="baseline" type="float" default="0.0" />
<description>
Adds inline object to the text buffer, [param key] must be unique. In the text, object is represented as [param length] object replacement characters.
</description>
@@ -1390,6 +1440,7 @@
<param index="1" name="key" type="Variant" />
<param index="2" name="size" type="Vector2" />
<param index="3" name="inline_align" type="int" enum="InlineAlignment" default="5" />
+ <param index="4" name="baseline" type="float" default="0.0" />
<description>
Sets new size and alignment of embedded object.
</description>
@@ -1498,8 +1549,15 @@
<return type="PackedInt32Array" />
<param index="0" name="string" type="String" />
<param index="1" name="language" type="String" default="&quot;&quot;" />
- <description>
- Returns array of the word break character offsets.
+ <param index="2" name="chars_per_line" type="int" default="0" />
+ <description>
+ Returns an array of the word break boundaries. Elements in the returned array are the offsets of the start and end of words. Therefore the length of the array is always even.
+ When [param chars_per_line] is greater than zero, line break boundaries are returned instead.
+ [codeblock]
+ var ts = TextServerManager.get_primary_interface()
+ print(ts.string_get_word_breaks("Godot Engine")) # Prints [0, 5, 6, 12]
+ print(ts.string_get_word_breaks("Godot Engine", "en", 5)) # Prints [0, 5, 6, 11, 11, 12]
+ [/codeblock]
</description>
</method>
<method name="string_to_lower" qualifiers="const">
diff --git a/doc/classes/TextServerExtension.xml b/doc/classes/TextServerExtension.xml
index 37d2698dd4..e144b09eb6 100644
--- a/doc/classes/TextServerExtension.xml
+++ b/doc/classes/TextServerExtension.xml
@@ -9,6 +9,11 @@
<tutorials>
</tutorials>
<methods>
+ <method name="_cleanup" qualifiers="virtual">
+ <return type="void" />
+ <description>
+ </description>
+ </method>
<method name="_create_font" qualifiers="virtual">
<return type="RID" />
<description>
@@ -306,6 +311,12 @@
<description>
</description>
</method>
+ <method name="_font_get_stretch" qualifiers="virtual const">
+ <return type="int" />
+ <param index="0" name="font_rid" type="RID" />
+ <description>
+ </description>
+ </method>
<method name="_font_get_style" qualifiers="virtual const">
<return type="int" enum="TextServer.FontStyle" />
<param index="0" name="font_rid" type="RID" />
@@ -379,6 +390,12 @@
<description>
</description>
</method>
+ <method name="_font_get_weight" qualifiers="virtual const">
+ <return type="int" />
+ <param index="0" name="font_rid" type="RID" />
+ <description>
+ </description>
+ </method>
<method name="_font_has_char" qualifiers="virtual const">
<return type="bool" />
<param index="0" name="font_rid" type="RID" />
@@ -386,6 +403,12 @@
<description>
</description>
</method>
+ <method name="_font_is_allow_system_fallback" qualifiers="virtual const">
+ <return type="bool" />
+ <param index="0" name="font_rid" type="RID" />
+ <description>
+ </description>
+ </method>
<method name="_font_is_force_autohinter" qualifiers="virtual const">
<return type="bool" />
<param index="0" name="font_rid" type="RID" />
@@ -474,6 +497,13 @@
<description>
</description>
</method>
+ <method name="_font_set_allow_system_fallback" qualifiers="virtual">
+ <return type="void" />
+ <param index="0" name="font_rid" type="RID" />
+ <param index="1" name="allow_system_fallback" type="bool" />
+ <description>
+ </description>
+ </method>
<method name="_font_set_antialiasing" qualifiers="virtual">
<return type="void" />
<param index="0" name="font_rid" type="RID" />
@@ -680,6 +710,13 @@
<description>
</description>
</method>
+ <method name="_font_set_stretch" qualifiers="virtual">
+ <return type="void" />
+ <param index="0" name="font_rid" type="RID" />
+ <param index="1" name="stretch" type="int" />
+ <description>
+ </description>
+ </method>
<method name="_font_set_style" qualifiers="virtual">
<return type="void" />
<param index="0" name="font_rid" type="RID" />
@@ -749,6 +786,13 @@
<description>
</description>
</method>
+ <method name="_font_set_weight" qualifiers="virtual">
+ <return type="void" />
+ <param index="0" name="font_rid" type="RID" />
+ <param index="1" name="weight" type="int" />
+ <description>
+ </description>
+ </method>
<method name="_font_supported_feature_list" qualifiers="virtual const">
<return type="Dictionary" />
<param index="0" name="font_rid" type="RID" />
@@ -901,6 +945,7 @@
<param index="2" name="size" type="Vector2" />
<param index="3" name="inline_align" type="int" enum="InlineAlignment" />
<param index="4" name="length" type="int" />
+ <param index="5" name="baseline" type="float" />
<description>
</description>
</method>
@@ -1198,6 +1243,7 @@
<param index="1" name="key" type="Variant" />
<param index="2" name="size" type="Vector2" />
<param index="3" name="inline_align" type="int" enum="InlineAlignment" />
+ <param index="4" name="baseline" type="float" />
<description>
</description>
</method>
@@ -1300,6 +1346,7 @@
<return type="PackedInt32Array" />
<param index="0" name="string" type="String" />
<param index="1" name="language" type="String" />
+ <param index="2" name="chars_per_line" type="int" />
<description>
</description>
</method>
diff --git a/doc/classes/TextureButton.xml b/doc/classes/TextureButton.xml
index 043eeb9a80..b185828577 100644
--- a/doc/classes/TextureButton.xml
+++ b/doc/classes/TextureButton.xml
@@ -27,19 +27,19 @@
<member name="texture_click_mask" type="BitMap" setter="set_click_mask" getter="get_click_mask">
Pure black and white [BitMap] image to use for click detection. On the mask, white pixels represent the button's clickable area. Use it to create buttons with curved shapes.
</member>
- <member name="texture_disabled" type="Texture2D" setter="set_disabled_texture" getter="get_disabled_texture">
+ <member name="texture_disabled" type="Texture2D" setter="set_texture_disabled" getter="get_texture_disabled">
Texture to display when the node is disabled. See [member BaseButton.disabled].
</member>
- <member name="texture_focused" type="Texture2D" setter="set_focused_texture" getter="get_focused_texture">
+ <member name="texture_focused" type="Texture2D" setter="set_texture_focused" getter="get_texture_focused">
Texture to display when the node has mouse or keyboard focus. [member texture_focused] is displayed [i]over[/i] the base texture, so a partially transparent texture should be used to ensure the base texture remains visible. A texture that represents an outline or an underline works well for this purpose. To disable the focus visual effect, assign a fully transparent texture of any size. Note that disabling the focus visual effect will harm keyboard/controller navigation usability, so this is not recommended for accessibility reasons.
</member>
- <member name="texture_hover" type="Texture2D" setter="set_hover_texture" getter="get_hover_texture">
+ <member name="texture_hover" type="Texture2D" setter="set_texture_hover" getter="get_texture_hover">
Texture to display when the mouse hovers the node.
</member>
- <member name="texture_normal" type="Texture2D" setter="set_normal_texture" getter="get_normal_texture">
+ <member name="texture_normal" type="Texture2D" setter="set_texture_normal" getter="get_texture_normal">
Texture to display by default, when the node is [b]not[/b] in the disabled, focused, hover or pressed state.
</member>
- <member name="texture_pressed" type="Texture2D" setter="set_pressed_texture" getter="get_pressed_texture">
+ <member name="texture_pressed" type="Texture2D" setter="set_texture_pressed" getter="get_texture_pressed">
Texture to display on mouse down over the node, if the node has keyboard focus and the player presses the Enter key or if the player presses the [member BaseButton.shortcut] key.
</member>
</members>
diff --git a/doc/classes/TextureProgressBar.xml b/doc/classes/TextureProgressBar.xml
index 54b77bf5eb..d7a9d06a15 100644
--- a/doc/classes/TextureProgressBar.xml
+++ b/doc/classes/TextureProgressBar.xml
@@ -13,6 +13,7 @@
<return type="int" />
<param index="0" name="margin" type="int" enum="Side" />
<description>
+ Returns the stretch margin with the specified index. See [member stretch_margin_bottom] and related properties.
</description>
</method>
<method name="set_stretch_margin">
@@ -20,6 +21,7 @@
<param index="0" name="margin" type="int" enum="Side" />
<param index="1" name="value" type="int" />
<description>
+ Sets the stretch margin with the specified index. See [member stretch_margin_bottom] and related properties.
</description>
</method>
</methods>
diff --git a/doc/classes/TileData.xml b/doc/classes/TileData.xml
index 798a536a88..f815b8d0c3 100644
--- a/doc/classes/TileData.xml
+++ b/doc/classes/TileData.xml
@@ -1,8 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="TileData" inherits="Object" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
+ Settings for a single tile in a [TileSet].
</brief_description>
<description>
+ [TileData] object represents a single tile in a [TileSet]. It is usually edited using the tileset editor, but it can be modified at runtime using [method TileMap._tile_data_runtime_update].
</description>
<tutorials>
</tutorials>
@@ -196,32 +198,43 @@
</methods>
<members>
<member name="flip_h" type="bool" setter="set_flip_h" getter="get_flip_h" default="false">
+ If [code]true[/code], the tile will have its texture flipped horizontally.
</member>
<member name="flip_v" type="bool" setter="set_flip_v" getter="get_flip_v" default="false">
+ If [code]true[/code], the tile will have its texture flipped vertically.
</member>
<member name="material" type="Material" setter="set_material" getter="get_material">
The [Material] to use for this [TileData]. This can be a [CanvasItemMaterial] to use the default shader, or a [ShaderMaterial] to use a custom shader.
</member>
<member name="modulate" type="Color" setter="set_modulate" getter="get_modulate" default="Color(1, 1, 1, 1)">
+ Color modulation of the tile.
</member>
<member name="probability" type="float" setter="set_probability" getter="get_probability" default="1.0">
+ Relative probability of this tile being selected when drawing a pattern of random tiles.
</member>
<member name="terrain" type="int" setter="set_terrain" getter="get_terrain" default="-1">
+ ID of the terrain from the terrain set that the tile uses.
</member>
<member name="terrain_set" type="int" setter="set_terrain_set" getter="get_terrain_set" default="-1">
+ ID of the terrain set that the tile uses.
</member>
<member name="texture_offset" type="Vector2i" setter="set_texture_offset" getter="get_texture_offset" default="Vector2i(0, 0)">
+ Offsets the position of where the tile is drawn.
</member>
<member name="transpose" type="bool" setter="set_transpose" getter="get_transpose" default="false">
+ If [code]true[/code], the tile will display transposed, i.e. with horizontal and vertical texture UVs swapped.
</member>
<member name="y_sort_origin" type="int" setter="set_y_sort_origin" getter="get_y_sort_origin" default="0">
+ Vertical point of the tile used for determining y-sorted order.
</member>
<member name="z_index" type="int" setter="set_z_index" getter="get_z_index" default="0">
+ Ordering index of this tile, relative to [TileMap].
</member>
</members>
<signals>
<signal name="changed">
<description>
+ Emitted when any of the properties are changed.
</description>
</signal>
</signals>
diff --git a/doc/classes/TileMap.xml b/doc/classes/TileMap.xml
index 01246f0c2e..8b537545bc 100644
--- a/doc/classes/TileMap.xml
+++ b/doc/classes/TileMap.xml
@@ -174,7 +174,7 @@
Creates a new [TileMapPattern] from the given layer and set of cells.
</description>
</method>
- <method name="get_surrounding_tiles">
+ <method name="get_surrounding_cells">
<return type="Vector2i[]" />
<param index="0" name="coords" type="Vector2i" />
<description>
@@ -257,8 +257,9 @@
<description>
Sets the tile indentifiers for the cell on layer [param layer] at coordinates [param coords]. Each tile of the [TileSet] is identified using three parts:
- The source identifier [param source_id] identifies a [TileSetSource] identifier. See [method TileSet.set_source_id],
- - The atlas coordinates identifier [param atlas_coords] identifies a tile coordinates in the atlas (if the source is a [TileSetAtlasSource]. For [TileSetScenesCollectionSource] it should be 0),
+ - The atlas coordinates identifier [param atlas_coords] identifies a tile coordinates in the atlas (if the source is a [TileSetAtlasSource]. For [TileSetScenesCollectionSource] it should always be [code]Vector2i(0, 0)[/code]),
- The alternative tile identifier [param alternative_tile] identifies a tile alternative the source is a [TileSetAtlasSource], and the scene for a [TileSetScenesCollectionSource].
+ If [param source_id] is set to [code]-1[/code], [param atlas_coords] to [code]Vector2i(-1, -1)[/code] or [param alternative_tile] to [code]-1[/code], the cell will be erased. An erased cell gets [b]all[/b] its identifiers automatically set to their respective invalid values, namely [code]-1[/code], [code]Vector2i(-1, -1)[/code] and [code]-1[/code].
</description>
</method>
<method name="set_cells_terrain_connect">
diff --git a/doc/classes/TileSet.xml b/doc/classes/TileSet.xml
index 5a24483774..7fc6ba8161 100644
--- a/doc/classes/TileSet.xml
+++ b/doc/classes/TileSet.xml
@@ -616,6 +616,7 @@
</constant>
<constant name="TILE_SHAPE_ISOMETRIC" value="1" enum="TileShape">
Diamond tile shape (for isometric look).
+ [b]Note:[/b] Isometric [TileSet] works best if [TileMap] and all its layers have Y-sort enabled.
</constant>
<constant name="TILE_SHAPE_HALF_OFFSET_SQUARE" value="2" enum="TileShape">
Rectangular tile shape with one row/column out of two offset by half a tile.
diff --git a/doc/classes/Translation.xml b/doc/classes/Translation.xml
index 314be9adf8..ae2f8d8dff 100644
--- a/doc/classes/Translation.xml
+++ b/doc/classes/Translation.xml
@@ -88,6 +88,12 @@
The number [param n] is the number or quantity of the plural object. It will be used to guide the translation system to fetch the correct plural form for the selected language.
</description>
</method>
+ <method name="get_translated_message_list" qualifiers="const">
+ <return type="PackedStringArray" />
+ <description>
+ Returns all the messages (translated text).
+ </description>
+ </method>
</methods>
<members>
<member name="locale" type="String" setter="set_locale" getter="get_locale" default="&quot;en&quot;">
diff --git a/doc/classes/Tree.xml b/doc/classes/Tree.xml
index 532f6703b2..584a2a2a7b 100644
--- a/doc/classes/Tree.xml
+++ b/doc/classes/Tree.xml
@@ -70,7 +70,7 @@
<return type="int" />
<param index="0" name="position" type="Vector2" />
<description>
- Returns the button id at [param position], or -1 if no button is there.
+ Returns the button ID at [param position], or -1 if no button is there.
</description>
</method>
<method name="get_column_at_position" qualifiers="const">
@@ -84,6 +84,7 @@
<return type="int" />
<param index="0" name="column" type="int" />
<description>
+ Returns the expand ratio assigned to the column.
</description>
</method>
<method name="get_column_title" qualifiers="const">
@@ -223,12 +224,14 @@
<return type="bool" />
<param index="0" name="column" type="int" />
<description>
+ Returns [code]true[/code] if the column has enabled clipping (see [method set_column_clip_content]).
</description>
</method>
<method name="is_column_expanding" qualifiers="const">
<return type="bool" />
<param index="0" name="column" type="int" />
<description>
+ Returns [code]true[/code] if the column has enabled expanding (see [method set_column_expand]).
</description>
</method>
<method name="scroll_to_item">
@@ -244,6 +247,7 @@
<param index="0" name="column" type="int" />
<param index="1" name="enable" type="bool" />
<description>
+ Allows to enable clipping for column's content, making the content size ignored.
</description>
</method>
<method name="set_column_custom_minimum_width">
@@ -259,7 +263,7 @@
<param index="0" name="column" type="int" />
<param index="1" name="expand" type="bool" />
<description>
- If [code]true[/code], the column will have the "Expand" flag of [Control]. Columns that have the "Expand" flag will use their "min_width" in a similar fashion to [member Control.size_flags_stretch_ratio].
+ If [code]true[/code], the column will have the "Expand" flag of [Control]. Columns that have the "Expand" flag will use their expand ratio in a similar fashion to [member Control.size_flags_stretch_ratio] (see [method set_column_expand_ratio]).
</description>
</method>
<method name="set_column_expand_ratio">
@@ -267,6 +271,7 @@
<param index="0" name="column" type="int" />
<param index="1" name="ratio" type="int" />
<description>
+ Sets the relative expand ratio for a column. See [method set_column_expand].
</description>
</method>
<method name="set_column_title">
@@ -293,6 +298,14 @@
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_selected">
+ <return type="void" />
+ <param index="0" name="item" type="TreeItem" />
+ <param index="1" name="column" type="int" />
+ <description>
+ Selects the specified [TreeItem] and column.
+ </description>
+ </method>
</methods>
<members>
<member name="allow_reselect" type="bool" setter="set_allow_reselect" getter="get_allow_reselect" default="false">
@@ -509,6 +522,7 @@
</theme_item>
<theme_item name="outline_size" data_type="constant" type="int" default="0">
The size of the text outline.
+ [b]Note:[/b] If using a font with [member FontFile.multichannel_signed_distance_field] enabled, its [member FontFile.msdf_pixel_range] must be set to at least [i]twice[/i] the value of [theme_item outline_size] for outline rendering to look correct. Otherwise, the outline may appear to be cut off earlier than intended.
</theme_item>
<theme_item name="parent_hl_line_margin" data_type="constant" type="int" default="0">
The space between the parent relationship lines for the selected [TreeItem] and the relationship lines to its siblings that are not selected.
diff --git a/doc/classes/TreeItem.xml b/doc/classes/TreeItem.xml
index a8ffef427f..ec6b166e57 100644
--- a/doc/classes/TreeItem.xml
+++ b/doc/classes/TreeItem.xml
@@ -78,7 +78,7 @@
<param index="0" name="column" type="int" />
<param index="1" name="id" type="int" />
<description>
- Returns the button index if there is a button with id [param id] in column [param column], otherwise returns -1.
+ Returns the button index if there is a button with ID [param id] in column [param column], otherwise returns -1.
</description>
</method>
<method name="get_button_count" qualifiers="const">
@@ -93,7 +93,7 @@
<param index="0" name="column" type="int" />
<param index="1" name="button_idx" type="int" />
<description>
- Returns the id for the button at index [param button_idx] in column [param column].
+ Returns the ID for the button at index [param button_idx] in column [param column].
</description>
</method>
<method name="get_button_tooltip_text" qualifiers="const">
diff --git a/doc/classes/TubeTrailMesh.xml b/doc/classes/TubeTrailMesh.xml
index ddc544dc97..7457aa4050 100644
--- a/doc/classes/TubeTrailMesh.xml
+++ b/doc/classes/TubeTrailMesh.xml
@@ -7,6 +7,12 @@
<tutorials>
</tutorials>
<members>
+ <member name="cap_bottom" type="bool" setter="set_cap_bottom" getter="is_cap_bottom" default="true">
+ If [code]true[/code], generates a cap at the bottom of the tube. This can be set to [code]false[/code] to speed up generation and rendering when the cap is never seen by the camera.
+ </member>
+ <member name="cap_top" type="bool" setter="set_cap_top" getter="is_cap_top" default="true">
+ If [code]true[/code], generates a cap at the top of the tube. This can be set to [code]false[/code] to speed up generation and rendering when the cap is never seen by the camera.
+ </member>
<member name="curve" type="Curve" setter="set_curve" getter="get_curve">
</member>
<member name="radial_steps" type="int" setter="set_radial_steps" getter="get_radial_steps" default="8">
diff --git a/doc/classes/VSlider.xml b/doc/classes/VSlider.xml
index 488154106f..4bc98dea6f 100644
--- a/doc/classes/VSlider.xml
+++ b/doc/classes/VSlider.xml
@@ -33,7 +33,7 @@
The background of the area below the grabber.
</theme_item>
<theme_item name="grabber_area_highlight" data_type="style" type="StyleBox">
- The background of the area below the grabber, to the left of the grabber.
+ The background of the area below the grabber that displays when it's being hovered or focused.
</theme_item>
<theme_item name="slider" data_type="style" type="StyleBox">
The background for the whole slider. Determines the width of the [code]grabber_area[/code].
diff --git a/doc/classes/Vector2.xml b/doc/classes/Vector2.xml
index 5590f82336..c47933ccb7 100644
--- a/doc/classes/Vector2.xml
+++ b/doc/classes/Vector2.xml
@@ -5,7 +5,8 @@
</brief_description>
<description>
2-element structure that can be used to represent positions in 2D space or any other pair of numeric values.
- It uses floating-point coordinates. See [Vector2i] for its integer counterpart.
+ It uses floating-point coordinates. By default, these floating-point values use 32-bit precision, unlike [float] which is always 64-bit. If double precision is needed, compile the engine with the option [code]precision=double[/code].
+ See [Vector2i] for its integer counterpart.
[b]Note:[/b] In a boolean context, a Vector2 will evaluate to [code]false[/code] if it's equal to [code]Vector2(0, 0)[/code]. Otherwise, a Vector2 will always evaluate to [code]true[/code].
</description>
<tutorials>
@@ -85,6 +86,16 @@
Returns the aspect ratio of this vector, the ratio of [member x] to [member y].
</description>
</method>
+ <method name="bezier_derivative" qualifiers="const">
+ <return type="Vector2" />
+ <param index="0" name="control_1" type="Vector2" />
+ <param index="1" name="control_2" type="Vector2" />
+ <param index="2" name="end" type="Vector2" />
+ <param index="3" name="t" type="float" />
+ <description>
+ Returns the derivative at the given [param t] on the [url=https://en.wikipedia.org/wiki/B%C3%A9zier_curve]Bézier curve[/url] defined by this vector and the given [param control_1], [param control_2], and [param end] points.
+ </description>
+ </method>
<method name="bezier_interpolate" qualifiers="const">
<return type="Vector2" />
<param index="0" name="control_1" type="Vector2" />
@@ -92,14 +103,14 @@
<param index="2" name="end" type="Vector2" />
<param index="3" name="t" type="float" />
<description>
- Returns the point at the given [param t] on the [url=https://en.wikipedia.org/wiki/B%C3%A9zier_curve]Bezier curve[/url] defined by this vector and the given [param control_1], [param control_2], and [param end] points.
+ Returns the point at the given [param t] on the [url=https://en.wikipedia.org/wiki/B%C3%A9zier_curve]Bézier curve[/url] defined by this vector and the given [param control_1], [param control_2], and [param end] points.
</description>
</method>
<method name="bounce" qualifiers="const">
<return type="Vector2" />
<param index="0" name="n" type="Vector2" />
<description>
- Returns the vector "bounced off" from a plane defined by the given normal.
+ Returns a new vector "bounced off" from a plane defined by the given normal.
</description>
</method>
<method name="ceil" qualifiers="const">
@@ -276,7 +287,7 @@
<method name="normalized" qualifiers="const">
<return type="Vector2" />
<description>
- Returns the vector scaled to unit length. Equivalent to [code]v / v.length()[/code].
+ Returns a new vector scaled to unit length. Equivalent to [code]v / v.length()[/code].
</description>
</method>
<method name="orthogonal" qualifiers="const">
@@ -303,21 +314,21 @@
<return type="Vector2" />
<param index="0" name="b" type="Vector2" />
<description>
- Returns this vector projected onto the vector [code]b[/code].
+ Returns the result of projecting the vector onto the given vector [param b].
</description>
</method>
<method name="reflect" qualifiers="const">
<return type="Vector2" />
<param index="0" name="n" type="Vector2" />
<description>
- Returns the vector reflected (i.e. mirrored, or symmetric) over a line defined by the given direction vector [param n].
+ Returns the result of reflecting the vector from a line defined by the given direction vector [param n].
</description>
</method>
<method name="rotated" qualifiers="const">
<return type="Vector2" />
<param index="0" name="angle" type="float" />
<description>
- Returns the vector rotated by [param angle] (in radians). See also [method @GlobalScope.deg_to_rad].
+ Returns the result of rotating this vector by [param angle] (in radians). See also [method @GlobalScope.deg_to_rad].
</description>
</method>
<method name="round" qualifiers="const">
@@ -329,7 +340,7 @@
<method name="sign" qualifiers="const">
<return type="Vector2" />
<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.
+ Returns a new vector with each component set to [code]1.0[/code] if it's positive, [code]-1.0[/code] if it's negative, and [code]0.0[/code] if it's zero. The result is identical to calling [method @GlobalScope.sign] on each component.
</description>
</method>
<method name="slerp" qualifiers="const">
@@ -345,14 +356,14 @@
<return type="Vector2" />
<param index="0" name="n" type="Vector2" />
<description>
- Returns this vector slid along a plane defined by the given normal.
+ Returns the result of sliding the vector along a plane defined by the given normal.
</description>
</method>
<method name="snapped" qualifiers="const">
<return type="Vector2" />
<param index="0" name="step" type="Vector2" />
<description>
- Returns this vector with each component snapped to the nearest multiple of [param step]. This can also be used to round to an arbitrary number of decimals.
+ Returns a new vector with each component snapped to the nearest multiple of the corresponding component in [param step]. This can also be used to round the components to an arbitrary number of decimals.
</description>
</method>
</methods>
diff --git a/doc/classes/Vector2i.xml b/doc/classes/Vector2i.xml
index eab880e57f..db6bc8f237 100644
--- a/doc/classes/Vector2i.xml
+++ b/doc/classes/Vector2i.xml
@@ -5,7 +5,7 @@
</brief_description>
<description>
2-element structure that can be used to represent positions in 2D space or any other pair of numeric values.
- It uses integer coordinates and is therefore preferable to [Vector2] when exact precision is required.
+ It uses integer coordinates and is therefore preferable to [Vector2] when exact precision is required. Note that the values are limited to 32 bits, and unlike [Vector2] this cannot be configured with an engine build option. Use [int] or [PackedInt64Array] if 64-bit values are needed.
[b]Note:[/b] In a boolean context, a Vector2i will evaluate to [code]false[/code] if it's equal to [code]Vector2i(0, 0)[/code]. Otherwise, a Vector2i will always evaluate to [code]true[/code].
</description>
<tutorials>
@@ -92,7 +92,14 @@
<method name="sign" qualifiers="const">
<return type="Vector2i" />
<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.
+ Returns a new vector with each component set to [code]1[/code] if it's positive, [code]-1[/code] if it's negative, and [code]0[/code] if it's zero. The result is identical to calling [method @GlobalScope.sign] on each component.
+ </description>
+ </method>
+ <method name="snapped" qualifiers="const">
+ <return type="Vector2i" />
+ <param index="0" name="step" type="Vector2i" />
+ <description>
+ Returns a new vector with each component snapped to the closest multiple of the corresponding component in [param step].
</description>
</method>
</methods>
diff --git a/doc/classes/Vector3.xml b/doc/classes/Vector3.xml
index 1a2cdfe10e..c961825ab3 100644
--- a/doc/classes/Vector3.xml
+++ b/doc/classes/Vector3.xml
@@ -5,7 +5,8 @@
</brief_description>
<description>
3-element structure that can be used to represent positions in 3D space or any other triplet of numeric values.
- It uses floating-point coordinates. See [Vector3i] for its integer counterpart.
+ It uses floating-point coordinates. By default, these floating-point values use 32-bit precision, unlike [float] which is always 64-bit. If double precision is needed, compile the engine with the option [code]precision=double[/code].
+ See [Vector3i] for its integer counterpart.
[b]Note:[/b] In a boolean context, a Vector3 will evaluate to [code]false[/code] if it's equal to [code]Vector3(0, 0, 0)[/code]. Otherwise, a Vector3 will always evaluate to [code]true[/code].
</description>
<tutorials>
@@ -61,6 +62,16 @@
Returns the unsigned minimum angle to the given vector, in radians.
</description>
</method>
+ <method name="bezier_derivative" qualifiers="const">
+ <return type="Vector3" />
+ <param index="0" name="control_1" type="Vector3" />
+ <param index="1" name="control_2" type="Vector3" />
+ <param index="2" name="end" type="Vector3" />
+ <param index="3" name="t" type="float" />
+ <description>
+ Returns the derivative at the given [param t] on the [url=https://en.wikipedia.org/wiki/B%C3%A9zier_curve]Bézier curve[/url] defined by this vector and the given [param control_1], [param control_2], and [param end] points.
+ </description>
+ </method>
<method name="bezier_interpolate" qualifiers="const">
<return type="Vector3" />
<param index="0" name="control_1" type="Vector3" />
@@ -68,7 +79,7 @@
<param index="2" name="end" type="Vector3" />
<param index="3" name="t" type="float" />
<description>
- Returns the point at the given [param t] on the [url=https://en.wikipedia.org/wiki/B%C3%A9zier_curve]Bezier curve[/url] defined by this vector and the given [param control_1], [param control_2], and [param end] points.
+ Returns the point at the given [param t] on the [url=https://en.wikipedia.org/wiki/B%C3%A9zier_curve]Bézier curve[/url] defined by this vector and the given [param control_1], [param control_2], and [param end] points.
</description>
</method>
<method name="bounce" qualifiers="const">
@@ -287,14 +298,14 @@
<return type="Vector3" />
<param index="0" name="b" type="Vector3" />
<description>
- Returns this vector projected onto the vector [param b].
+ Returns the result of projecting the vector onto the given vector [param b].
</description>
</method>
<method name="reflect" qualifiers="const">
<return type="Vector3" />
<param index="0" name="n" type="Vector3" />
<description>
- Returns this vector reflected from a plane defined by the given normal.
+ Returns the result of reflecting the vector from a plane defined by the given normal [param n].
</description>
</method>
<method name="rotated" qualifiers="const">
@@ -302,7 +313,7 @@
<param index="0" name="axis" type="Vector3" />
<param index="1" name="angle" type="float" />
<description>
- Rotates this vector around a given axis by [param angle] (in radians). The axis must be a normalized vector.
+ Returns the result of rotating this vector around a given axis by [param angle] (in radians). The axis must be a normalized vector. See also [method @GlobalScope.deg_to_rad].
</description>
</method>
<method name="round" qualifiers="const">
@@ -314,7 +325,7 @@
<method name="sign" qualifiers="const">
<return type="Vector3" />
<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.
+ Returns a new vector with each component set to [code]1.0[/code] if it's positive, [code]-1.0[/code] if it's negative, and [code]0.0[/code] if it's zero. The result is identical to calling [method @GlobalScope.sign] on each component.
</description>
</method>
<method name="signed_angle_to" qualifiers="const">
@@ -338,14 +349,14 @@
<return type="Vector3" />
<param index="0" name="n" type="Vector3" />
<description>
- Returns this vector slid along a plane defined by the given normal.
+ Returns a new vector slid along a plane defined by the given normal.
</description>
</method>
<method name="snapped" qualifiers="const">
<return type="Vector3" />
<param index="0" name="step" type="Vector3" />
<description>
- Returns this vector with each component snapped to the nearest multiple of [param step]. This can also be used to round to an arbitrary number of decimals.
+ Returns a new vector with each component snapped to the nearest multiple of the corresponding component in [param step]. This can also be used to round the components to an arbitrary number of decimals.
</description>
</method>
</methods>
diff --git a/doc/classes/Vector3i.xml b/doc/classes/Vector3i.xml
index 1c2a033f7a..5c6dc3c1c5 100644
--- a/doc/classes/Vector3i.xml
+++ b/doc/classes/Vector3i.xml
@@ -5,7 +5,7 @@
</brief_description>
<description>
3-element structure that can be used to represent positions in 3D space or any other triplet of numeric values.
- It uses integer coordinates and is therefore preferable to [Vector3] when exact precision is required.
+ It uses integer coordinates and is therefore preferable to [Vector3] when exact precision is required. Note that the values are limited to 32 bits, and unlike [Vector3] this cannot be configured with an engine build option. Use [int] or [PackedInt64Array] if 64-bit values are needed.
[b]Note:[/b] In a boolean context, a Vector3i will evaluate to [code]false[/code] if it's equal to [code]Vector3i(0, 0, 0)[/code]. Otherwise, a Vector3i will always evaluate to [code]true[/code].
</description>
<tutorials>
@@ -87,7 +87,14 @@
<method name="sign" qualifiers="const">
<return type="Vector3i" />
<description>
- Returns the vector with each component set to one or negative one, depending on the signs of the components.
+ Returns a new vector with each component set to [code]1[/code] if it's positive, [code]-1[/code] if it's negative, and [code]0[/code] if it's zero. The result is identical to calling [method @GlobalScope.sign] on each component.
+ </description>
+ </method>
+ <method name="snapped" qualifiers="const">
+ <return type="Vector3i" />
+ <param index="0" name="step" type="Vector3i" />
+ <description>
+ Returns a new vector with each component snapped to the closest multiple of the corresponding component in [param step].
</description>
</method>
</methods>
diff --git a/doc/classes/Vector4.xml b/doc/classes/Vector4.xml
index 662d0bce3a..c811817bdc 100644
--- a/doc/classes/Vector4.xml
+++ b/doc/classes/Vector4.xml
@@ -5,7 +5,8 @@
</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.
+ It uses floating-point coordinates. By default, these floating-point values use 32-bit precision, unlike [float] which is always 64-bit. If double precision is needed, compile the engine with the option [code]precision=double[/code].
+ 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>
@@ -189,21 +190,21 @@
<method name="normalized" qualifiers="const">
<return type="Vector4" />
<description>
- Returns the vector scaled to unit length. Equivalent to [code]v / v.length()[/code].
+ Returns the result of scaling the vector to unit length. Equivalent to [code]v / v.length()[/code].
</description>
</method>
<method name="posmod" qualifiers="const">
<return type="Vector4" />
<param index="0" name="mod" type="float" />
<description>
- Returns a vector composed of the [method @GlobalScope.fposmod] of this vector's components and [param mod].
+ Returns a new vector composed of the [method @GlobalScope.fposmod] of this vector's components and [param mod].
</description>
</method>
<method name="posmodv" qualifiers="const">
<return type="Vector4" />
<param index="0" name="modv" type="Vector4" />
<description>
- Returns a vector composed of the [method @GlobalScope.fposmod] of this vector's components and [param modv]'s components.
+ Returns a new vector composed of the [method @GlobalScope.fposmod] of this vector's components and [param modv]'s components.
</description>
</method>
<method name="round" qualifiers="const">
@@ -215,14 +216,14 @@
<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.
+ Returns a new vector with each component set to [code]1.0[/code] if it's positive, [code]-1.0[/code] if it's negative, and [code]0.0[/code] if it's zero. The result is identical to calling [method @GlobalScope.sign] on each component.
</description>
</method>
<method name="snapped" qualifiers="const">
<return type="Vector4" />
<param index="0" name="step" type="Vector4" />
<description>
- Returns this vector with each component snapped to the nearest multiple of [param step]. This can also be used to round to an arbitrary number of decimals.
+ Returns a new vector with each component snapped to the nearest multiple of the corresponding component in [param step]. This can also be used to round the components to an arbitrary number of decimals.
</description>
</method>
</methods>
diff --git a/doc/classes/Vector4i.xml b/doc/classes/Vector4i.xml
index e9ac5b9475..95797df90a 100644
--- a/doc/classes/Vector4i.xml
+++ b/doc/classes/Vector4i.xml
@@ -5,7 +5,7 @@
</brief_description>
<description>
4-element structure that can be used to represent 4D grid coordinates or sets of integers.
- It uses integer coordinates. See [Vector4] for its floating-point counterpart.
+ It uses integer coordinates and is therefore preferable to [Vector4] when exact precision is required. Note that the values are limited to 32 bits, and unlike [Vector4] this cannot be configured with an engine build option. Use [int] or [PackedInt64Array] if 64-bit values are needed.
</description>
<tutorials>
</tutorials>
@@ -83,7 +83,14 @@
<method name="sign" qualifiers="const">
<return type="Vector4i" />
<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.
+ Returns a new vector with each component set to [code]1[/code] if it's positive, [code]-1[/code] if it's negative, and [code]0[/code] if it's zero. The result is identical to calling [method @GlobalScope.sign] on each component.
+ </description>
+ </method>
+ <method name="snapped" qualifiers="const">
+ <return type="Vector4i" />
+ <param index="0" name="step" type="Vector4i" />
+ <description>
+ Returns a new vector with each component snapped to the closest multiple of the corresponding component in [param step].
</description>
</method>
</methods>
diff --git a/doc/classes/Viewport.xml b/doc/classes/Viewport.xml
index 78013a8f4b..236d34383f 100644
--- a/doc/classes/Viewport.xml
+++ b/doc/classes/Viewport.xml
@@ -343,6 +343,19 @@
</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].
+ The texture [i]must[/i] use a lossless compression format so that colors can be matched precisely. The following VRS densities are mapped to various colors, with brighter colors representing a lower level of shading precision:
+ [codeblock]
+ - 1x1 = rgb(0, 0, 0) - #000000
+ - 1x2 = rgb(0, 85, 0) - #005500
+ - 2x1 = rgb(85, 0, 0) - #550000
+ - 2x2 = rgb(85, 85, 0) - #555500
+ - 2x4 = rgb(85, 170, 0) - #55aa00
+ - 4x2 = rgb(170, 85, 0) - #aa5500
+ - 4x4 = rgb(170, 170, 0) - #aaaa00
+ - 4x8 = rgb(170, 255, 0) - #aaff00 - Not supported on most hardware
+ - 8x4 = rgb(255, 170, 0) - #ffaa00 - Not supported on most hardware
+ - 8x8 = rgb(255, 255, 0) - #ffff00 - Not supported on most hardware
+ [/codeblock]
</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.
diff --git a/doc/classes/VisualInstance3D.xml b/doc/classes/VisualInstance3D.xml
index 31811f817b..e069642e50 100644
--- a/doc/classes/VisualInstance3D.xml
+++ b/doc/classes/VisualInstance3D.xml
@@ -61,5 +61,12 @@
This object will only be visible for [Camera3D]s whose cull mask includes the render object this [VisualInstance3D] is set to.
For [Light3D]s, this can be used to control which [VisualInstance3D]s are affected by a specific light. For [GPUParticles3D], this can be used to control which particles are effected by a specific attractor. For [Decal]s, this can be used to control which [VisualInstance3D]s are affected by a specific decal.
</member>
+ <member name="sorting_offset" type="float" setter="set_sorting_offset" getter="get_sorting_offset" default="0.0">
+ The sorting offset used by this [VisualInstance3D]. Adjusting it to a higher value will make the [VisualInstance3D] reliably draw on top of other [VisualInstance3D]s that are otherwise positioned at the same spot.
+ </member>
+ <member name="sorting_use_aabb_center" type="bool" setter="set_sorting_use_aabb_center" getter="is_sorting_use_aabb_center" default="true">
+ If [code]true[/code], the object is sorted based on the [AABB] center. The object will be sorted based on the global position otherwise.
+ The [AABB] center based sorting is generally more accurate for 3D models. The position based sorting instead allows to better control the drawing order when working with [GPUParticles3D] and [CPUParticles3D].
+ </member>
</members>
</class>
diff --git a/doc/classes/Window.xml b/doc/classes/Window.xml
index 8707ef003a..16ca486e4a 100644
--- a/doc/classes/Window.xml
+++ b/doc/classes/Window.xml
@@ -10,6 +10,66 @@
<tutorials>
</tutorials>
<methods>
+ <method name="add_theme_color_override">
+ <return type="void" />
+ <param index="0" name="name" type="StringName" />
+ <param index="1" name="color" type="Color" />
+ <description>
+ Creates a local override for a theme [Color] with the specified [param name]. Local overrides always take precedence when fetching theme items for the control. An override can be removed with [method remove_theme_color_override].
+ See also [method get_theme_color] and [method Control.add_theme_color_override] for more details.
+ </description>
+ </method>
+ <method name="add_theme_constant_override">
+ <return type="void" />
+ <param index="0" name="name" type="StringName" />
+ <param index="1" name="constant" type="int" />
+ <description>
+ Creates a local override for a theme constant with the specified [param name]. Local overrides always take precedence when fetching theme items for the control. An override can be removed with [method remove_theme_constant_override].
+ See also [method get_theme_constant].
+ </description>
+ </method>
+ <method name="add_theme_font_override">
+ <return type="void" />
+ <param index="0" name="name" type="StringName" />
+ <param index="1" name="font" type="Font" />
+ <description>
+ Creates a local override for a theme [Font] with the specified [param name]. Local overrides always take precedence when fetching theme items for the control. An override can be removed with [method remove_theme_font_override].
+ See also [method get_theme_font].
+ </description>
+ </method>
+ <method name="add_theme_font_size_override">
+ <return type="void" />
+ <param index="0" name="name" type="StringName" />
+ <param index="1" name="font_size" type="int" />
+ <description>
+ Creates a local override for a theme font size with the specified [param name]. Local overrides always take precedence when fetching theme items for the control. An override can be removed with [method remove_theme_font_size_override].
+ See also [method get_theme_font_size].
+ </description>
+ </method>
+ <method name="add_theme_icon_override">
+ <return type="void" />
+ <param index="0" name="name" type="StringName" />
+ <param index="1" name="texture" type="Texture2D" />
+ <description>
+ Creates a local override for a theme icon with the specified [param name]. Local overrides always take precedence when fetching theme items for the control. An override can be removed with [method remove_theme_icon_override].
+ See also [method get_theme_icon].
+ </description>
+ </method>
+ <method name="add_theme_stylebox_override">
+ <return type="void" />
+ <param index="0" name="name" type="StringName" />
+ <param index="1" name="stylebox" type="StyleBox" />
+ <description>
+ Creates a local override for a theme [StyleBox] with the specified [param name]. Local overrides always take precedence when fetching theme items for the control. An override can be removed with [method remove_theme_stylebox_override].
+ See also [method get_theme_stylebox] and [method Control.add_theme_stylebox_override] for more details.
+ </description>
+ </method>
+ <method name="begin_bulk_theme_override">
+ <return type="void" />
+ <description>
+ Prevents [code]*_theme_*_override[/code] methods from emitting [constant NOTIFICATION_THEME_CHANGED] until [method end_bulk_theme_override] is called.
+ </description>
+ </method>
<method name="can_draw" qualifiers="const">
<return type="bool" />
<description>
@@ -22,6 +82,12 @@
Requests an update of the [Window] size to fit underlying [Control] nodes.
</description>
</method>
+ <method name="end_bulk_theme_override">
+ <return type="void" />
+ <description>
+ Ends a bulk theme override update. See [method begin_bulk_theme_override].
+ </description>
+ </method>
<method name="get_contents_minimum_size" qualifiers="const">
<return type="Vector2" />
<description>
@@ -41,7 +107,13 @@
Returns layout direction and text writing direction.
</description>
</method>
- <method name="get_real_size" qualifiers="const">
+ <method name="get_position_with_decorations" qualifiers="const">
+ <return type="Vector2i" />
+ <description>
+ Returns the window's position including its border.
+ </description>
+ </method>
+ <method name="get_size_with_decorations" qualifiers="const">
<return type="Vector2i" />
<description>
Returns the window's size including its border.
@@ -52,7 +124,7 @@
<param index="0" name="name" type="StringName" />
<param index="1" name="theme_type" type="StringName" default="&quot;&quot;" />
<description>
- Returns the [Color] at [param name] if the theme has [param theme_type].
+ Returns a [Color] from the first matching [Theme] in the tree if that [Theme] has a color item with the specified [param name] and [param theme_type].
See [method Control.get_theme_color] for more details.
</description>
</method>
@@ -61,29 +133,29 @@
<param index="0" name="name" type="StringName" />
<param index="1" name="theme_type" type="StringName" default="&quot;&quot;" />
<description>
- Returns the constant at [param name] if the theme has [param theme_type].
+ Returns a constant from the first matching [Theme] in the tree if that [Theme] has a constant item with the specified [param name] and [param theme_type].
See [method Control.get_theme_color] for more details.
</description>
</method>
<method name="get_theme_default_base_scale" qualifiers="const">
<return type="float" />
<description>
- Returns the default base scale defined in the attached [Theme].
- See [member Theme.default_base_scale] for more details.
+ Returns the default base scale value from the first matching [Theme] in the tree if that [Theme] has a valid [member Theme.default_base_scale] value.
+ See [method Control.get_theme_color] for details.
</description>
</method>
<method name="get_theme_default_font" qualifiers="const">
<return type="Font" />
<description>
- Returns the default [Font] defined in the attached [Theme].
- See [member Theme.default_font] for more details.
+ Returns the default font from the first matching [Theme] in the tree if that [Theme] has a valid [member Theme.default_font] value.
+ See [method Control.get_theme_color] for details.
</description>
</method>
<method name="get_theme_default_font_size" qualifiers="const">
<return type="int" />
<description>
- Returns the default font size defined in the attached [Theme].
- See [member Theme.default_font_size] for more details.
+ Returns the default font size value from the first matching [Theme] in the tree if that [Theme] has a valid [member Theme.default_font_size] value.
+ See [method Control.get_theme_color] for details.
</description>
</method>
<method name="get_theme_font" qualifiers="const">
@@ -91,8 +163,8 @@
<param index="0" name="name" type="StringName" />
<param index="1" name="theme_type" type="StringName" default="&quot;&quot;" />
<description>
- Returns the [Font] at [param name] if the theme has [param theme_type].
- See [method Control.get_theme_color] for more details.
+ Returns a [Font] from the first matching [Theme] in the tree if that [Theme] has a font item with the specified [param name] and [param theme_type].
+ See [method Control.get_theme_color] for details.
</description>
</method>
<method name="get_theme_font_size" qualifiers="const">
@@ -100,8 +172,8 @@
<param index="0" name="name" type="StringName" />
<param index="1" name="theme_type" type="StringName" default="&quot;&quot;" />
<description>
- Returns the font size at [param name] if the theme has [param theme_type].
- See [method Control.get_theme_color] for more details.
+ Returns a font size from the first matching [Theme] in the tree if that [Theme] has a font size item with the specified [param name] and [param theme_type].
+ See [method Control.get_theme_color] for details.
</description>
</method>
<method name="get_theme_icon" qualifiers="const">
@@ -109,8 +181,8 @@
<param index="0" name="name" type="StringName" />
<param index="1" name="theme_type" type="StringName" default="&quot;&quot;" />
<description>
- Returns the icon at [param name] if the theme has [param theme_type].
- See [method Control.get_theme_color] for more details.
+ Returns an icon from the first matching [Theme] in the tree if that [Theme] has an icon item with the specified [param name] and [param theme_type].
+ See [method Control.get_theme_color] for details.
</description>
</method>
<method name="get_theme_stylebox" qualifiers="const">
@@ -118,8 +190,8 @@
<param index="0" name="name" type="StringName" />
<param index="1" name="theme_type" type="StringName" default="&quot;&quot;" />
<description>
- Returns the [StyleBox] at [param name] if the theme has [param theme_type].
- See [method Control.get_theme_color] for more details.
+ Returns a [StyleBox] from the first matching [Theme] in the tree if that [Theme] has a stylebox item with the specified [param name] and [param theme_type].
+ See [method Control.get_theme_color] for details.
</description>
</method>
<method name="grab_focus">
@@ -139,7 +211,16 @@
<param index="0" name="name" type="StringName" />
<param index="1" name="theme_type" type="StringName" default="&quot;&quot;" />
<description>
- Returns [code]true[/code] if [Color] with [param name] is in [param theme_type].
+ Returns [code]true[/code] if there is a matching [Theme] in the tree that has a color item with the specified [param name] and [param theme_type].
+ See [method Control.get_theme_color] for details.
+ </description>
+ </method>
+ <method name="has_theme_color_override" qualifiers="const">
+ <return type="bool" />
+ <param index="0" name="name" type="StringName" />
+ <description>
+ Returns [code]true[/code] if there is a local override for a theme [Color] with the specified [param name] in this [Control] node.
+ See [method add_theme_color_override].
</description>
</method>
<method name="has_theme_constant" qualifiers="const">
@@ -147,7 +228,16 @@
<param index="0" name="name" type="StringName" />
<param index="1" name="theme_type" type="StringName" default="&quot;&quot;" />
<description>
- Returns [code]true[/code] if constant with [param name] is in [param theme_type].
+ Returns [code]true[/code] if there is a matching [Theme] in the tree that has a constant item with the specified [param name] and [param theme_type].
+ See [method Control.get_theme_color] for details.
+ </description>
+ </method>
+ <method name="has_theme_constant_override" qualifiers="const">
+ <return type="bool" />
+ <param index="0" name="name" type="StringName" />
+ <description>
+ Returns [code]true[/code] if there is a local override for a theme constant with the specified [param name] in this [Control] node.
+ See [method add_theme_constant_override].
</description>
</method>
<method name="has_theme_font" qualifiers="const">
@@ -155,7 +245,16 @@
<param index="0" name="name" type="StringName" />
<param index="1" name="theme_type" type="StringName" default="&quot;&quot;" />
<description>
- Returns [code]true[/code] if [Font] with [param name] is in [param theme_type].
+ Returns [code]true[/code] if there is a matching [Theme] in the tree that has a font item with the specified [param name] and [param theme_type].
+ See [method Control.get_theme_color] for details.
+ </description>
+ </method>
+ <method name="has_theme_font_override" qualifiers="const">
+ <return type="bool" />
+ <param index="0" name="name" type="StringName" />
+ <description>
+ Returns [code]true[/code] if there is a local override for a theme [Font] with the specified [param name] in this [Control] node.
+ See [method add_theme_font_override].
</description>
</method>
<method name="has_theme_font_size" qualifiers="const">
@@ -163,7 +262,16 @@
<param index="0" name="name" type="StringName" />
<param index="1" name="theme_type" type="StringName" default="&quot;&quot;" />
<description>
- Returns [code]true[/code] if font size with [param name] is in [param theme_type].
+ Returns [code]true[/code] if there is a matching [Theme] in the tree that has a font size item with the specified [param name] and [param theme_type].
+ See [method Control.get_theme_color] for details.
+ </description>
+ </method>
+ <method name="has_theme_font_size_override" qualifiers="const">
+ <return type="bool" />
+ <param index="0" name="name" type="StringName" />
+ <description>
+ Returns [code]true[/code] if there is a local override for a theme font size with the specified [param name] in this [Control] node.
+ See [method add_theme_font_size_override].
</description>
</method>
<method name="has_theme_icon" qualifiers="const">
@@ -171,7 +279,16 @@
<param index="0" name="name" type="StringName" />
<param index="1" name="theme_type" type="StringName" default="&quot;&quot;" />
<description>
- Returns [code]true[/code] if icon with [param name] is in [param theme_type].
+ Returns [code]true[/code] if there is a matching [Theme] in the tree that has an icon item with the specified [param name] and [param theme_type].
+ See [method Control.get_theme_color] for details.
+ </description>
+ </method>
+ <method name="has_theme_icon_override" qualifiers="const">
+ <return type="bool" />
+ <param index="0" name="name" type="StringName" />
+ <description>
+ Returns [code]true[/code] if there is a local override for a theme icon with the specified [param name] in this [Control] node.
+ See [method add_theme_icon_override].
</description>
</method>
<method name="has_theme_stylebox" qualifiers="const">
@@ -179,7 +296,16 @@
<param index="0" name="name" type="StringName" />
<param index="1" name="theme_type" type="StringName" default="&quot;&quot;" />
<description>
- Returns [code]true[/code] if [StyleBox] with [param name] is in [param theme_type].
+ Returns [code]true[/code] if there is a matching [Theme] in the tree that has a stylebox item with the specified [param name] and [param theme_type].
+ See [method Control.get_theme_color] for details.
+ </description>
+ </method>
+ <method name="has_theme_stylebox_override" qualifiers="const">
+ <return type="bool" />
+ <param index="0" name="name" type="StringName" />
+ <description>
+ Returns [code]true[/code] if there is a local override for a theme [StyleBox] with the specified [param name] in this [Control] node.
+ See [method add_theme_stylebox_override].
</description>
</method>
<method name="hide">
@@ -258,6 +384,48 @@
If the [Window] is embedded, has the same effect as [method popup].
</description>
</method>
+ <method name="remove_theme_color_override">
+ <return type="void" />
+ <param index="0" name="name" type="StringName" />
+ <description>
+ Removes a local override for a theme [Color] with the specified [param name] previously added by [method add_theme_color_override] or via the Inspector dock.
+ </description>
+ </method>
+ <method name="remove_theme_constant_override">
+ <return type="void" />
+ <param index="0" name="name" type="StringName" />
+ <description>
+ Removes a local override for a theme constant with the specified [param name] previously added by [method add_theme_constant_override] or via the Inspector dock.
+ </description>
+ </method>
+ <method name="remove_theme_font_override">
+ <return type="void" />
+ <param index="0" name="name" type="StringName" />
+ <description>
+ Removes a local override for a theme [Font] with the specified [param name] previously added by [method add_theme_font_override] or via the Inspector dock.
+ </description>
+ </method>
+ <method name="remove_theme_font_size_override">
+ <return type="void" />
+ <param index="0" name="name" type="StringName" />
+ <description>
+ Removes a local override for a theme font size with the specified [param name] previously added by [method add_theme_font_size_override] or via the Inspector dock.
+ </description>
+ </method>
+ <method name="remove_theme_icon_override">
+ <return type="void" />
+ <param index="0" name="name" type="StringName" />
+ <description>
+ Removes a local override for a theme icon with the specified [param name] previously added by [method add_theme_icon_override] or via the Inspector dock.
+ </description>
+ </method>
+ <method name="remove_theme_stylebox_override">
+ <return type="void" />
+ <param index="0" name="name" type="StringName" />
+ <description>
+ Removes a local override for a theme [StyleBox] with the specified [param name] previously added by [method add_theme_stylebox_override] or via the Inspector dock.
+ </description>
+ </method>
<method name="request_attention">
<return type="void" />
<description>
@@ -367,8 +535,8 @@
The window's size in pixels.
</member>
<member name="theme" type="Theme" setter="set_theme" getter="get_theme">
- The [Theme] resource that determines the style of the underlying [Control] nodes.
- [Window] styles will have no effect unless the window is embedded.
+ The [Theme] resource this node and all its [Control] and [Window] children use. If a child node has its own [Theme] resource set, theme items are merged with child's definitions having higher priority.
+ [b]Note:[/b] [Window] styles will have no effect unless the window is embedded.
</member>
<member name="theme_type_variation" type="StringName" setter="set_theme_type_variation" getter="get_theme_type_variation" default="&amp;&quot;&quot;">
The name of a theme type variation used by this [Window] to look up its own theme items. See [member Control.theme_type_variation] for more details.
diff --git a/doc/classes/XRInterfaceExtension.xml b/doc/classes/XRInterfaceExtension.xml
index c6b215daa3..5ad67a7ea9 100644
--- a/doc/classes/XRInterfaceExtension.xml
+++ b/doc/classes/XRInterfaceExtension.xml
@@ -24,7 +24,7 @@
<method name="_get_camera_feed_id" qualifiers="virtual const">
<return type="int" />
<description>
- Returns the camera feed id for the [CameraFeed] registered with the [CameraServer] that should be presented as the background on an AR capable device (if applicable).
+ Returns the camera feed ID for the [CameraFeed] registered with the [CameraServer] that should be presented as the background on an AR capable device (if applicable).
</description>
</method>
<method name="_get_camera_transform" qualifiers="virtual">
@@ -141,13 +141,6 @@
Returns [code]true[/code] if this interface has been initialized.
</description>
</method>
- <method name="_notification" qualifiers="virtual">
- <return type="void" />
- <param index="0" name="what" type="int" />
- <description>
- Informs the interface of an applicable system notification.
- </description>
- </method>
<method name="_post_draw_viewport" qualifiers="virtual">
<return type="void" />
<param index="0" name="render_target" type="RID" />
diff --git a/doc/classes/float.xml b/doc/classes/float.xml
index e3938fb5d5..755ce1200d 100644
--- a/doc/classes/float.xml
+++ b/doc/classes/float.xml
@@ -5,7 +5,7 @@
</brief_description>
<description>
The [float] built-in type is a 64-bit double-precision floating-point number, equivalent to [code]double[/code] in C++. This type has 14 reliable decimal digits of precision. The [float] type can be stored in [Variant], which is the generic type used by the engine. The maximum value of [float] is approximately [code]1.79769e308[/code], and the minimum is approximately [code]-1.79769e308[/code].
- Many methods and properties in the engine use 32-bit single-precision floating-point numbers instead, equivalent to [code]float[/code] in C++, which have 6 reliable decimal digits of precision. For data structures such as [Vector2] and [Vector3], Godot uses 32-bit floating-point numbers by default, but it can be changed to use 64-bit doubles if Godot is compiled with the [code]float=64[/code] option.
+ Many methods and properties in the engine use 32-bit single-precision floating-point numbers instead, equivalent to [code]float[/code] in C++, which have 6 reliable decimal digits of precision. For data structures such as [Vector2] and [Vector3], Godot uses 32-bit floating-point numbers by default, but it can be changed to use 64-bit doubles if Godot is compiled with the [code]precision=double[/code] option.
Math done using the [float] type is not guaranteed to be exact or deterministic, and will often result in small errors. You should usually use the [method @GlobalScope.is_equal_approx] and [method @GlobalScope.is_zero_approx] methods instead of [code]==[/code] to compare [float] values for equality.
</description>
<tutorials>
@@ -28,6 +28,13 @@
</constructor>
<constructor name="float">
<return type="float" />
+ <param index="0" name="from" type="String" />
+ <description>
+ Converts a [String] to a [float], following the same rules as [method String.to_float].
+ </description>
+ </constructor>
+ <constructor name="float">
+ <return type="float" />
<param index="0" name="from" type="bool" />
<description>
Cast a [bool] value to a floating-point value, [code]float(true)[/code] will be equal to 1.0 and [code]float(false)[/code] will be equal to 0.0.
diff --git a/doc/classes/int.xml b/doc/classes/int.xml
index 65ab5d4656..93fc8386c6 100644
--- a/doc/classes/int.xml
+++ b/doc/classes/int.xml
@@ -54,6 +54,13 @@
</constructor>
<constructor name="int">
<return type="int" />
+ <param index="0" name="from" type="String" />
+ <description>
+ Converts a [String] to an [int], following the same rules as [method String.to_int].
+ </description>
+ </constructor>
+ <constructor name="int">
+ <return type="int" />
<param index="0" name="from" type="bool" />
<description>
Cast a [bool] value to an integer value, [code]int(true)[/code] will be equals to 1 and [code]int(false)[/code] will be equals to 0.
diff --git a/doc/tools/make_rst.py b/doc/tools/make_rst.py
index 492a438d9b..1f71b77cbd 100755
--- a/doc/tools/make_rst.py
+++ b/doc/tools/make_rst.py
@@ -29,6 +29,12 @@ MARKUP_ALLOWED_SUBSEQUENT = " -.,:;!?\\/'\")]}>"
# write in this script (check `translate()` uses), and also hardcoded in
# `doc/translations/extract.py` to include them in the source POT file.
BASE_STRINGS = [
+ "All classes",
+ "Globals",
+ "Nodes",
+ "Resources",
+ "Other objects",
+ "Variant types",
"Description",
"Tutorials",
"Properties",
@@ -63,6 +69,19 @@ strings_l10n: Dict[str, str] = {}
STYLES: Dict[str, str] = {}
+CLASS_GROUPS: Dict[str, str] = {
+ "global": "Globals",
+ "node": "Nodes",
+ "resource": "Resources",
+ "object": "Other objects",
+ "variant": "Variant types",
+}
+CLASS_GROUPS_BASE: Dict[str, str] = {
+ "node": "Node",
+ "resource": "Resource",
+ "object": "Object",
+}
+
class State:
def __init__(self) -> None:
@@ -221,7 +240,7 @@ class State:
enum_def = class_def.enums[enum]
else:
- enum_def = EnumDef(enum, is_bitfield)
+ enum_def = EnumDef(enum, TypeName("int", enum), is_bitfield)
class_def.enums[enum] = enum_def
enum_def.values[constant_name] = constant_def
@@ -329,7 +348,7 @@ class State:
return cast
def sort_classes(self) -> None:
- self.classes = OrderedDict(sorted(self.classes.items(), key=lambda t: t[0]))
+ self.classes = OrderedDict(sorted(self.classes.items(), key=lambda t: t[0].lower()))
class TypeName:
@@ -439,9 +458,10 @@ class ConstantDef(DefinitionBase):
class EnumDef(DefinitionBase):
- def __init__(self, name: str, bitfield: bool) -> None:
+ def __init__(self, name: str, type_name: TypeName, bitfield: bool) -> None:
super().__init__("enum", name)
+ self.type_name = type_name
self.values: OrderedDict[str, ConstantDef] = OrderedDict()
self.is_bitfield = bitfield
@@ -601,12 +621,25 @@ def main() -> None:
print("Generating the RST class reference...")
+ grouped_classes: Dict[str, List[str]] = {}
+
for class_name, class_def in state.classes.items():
if args.filter and not pattern.search(class_def.filepath):
continue
state.current_class = class_name
make_rst_class(class_def, state, args.dry_run, args.output)
+ group_name = get_class_group(class_def, state)
+
+ if group_name not in grouped_classes:
+ grouped_classes[group_name] = []
+ grouped_classes[group_name].append(class_name)
+
+ print("")
+ print("Generating the index file...")
+
+ make_rst_index(grouped_classes, args.dry_run, args.output)
+
print("")
if state.num_warnings >= 2:
@@ -655,6 +688,42 @@ def translate(string: str) -> str:
return strings_l10n.get(string, string)
+def get_git_branch() -> str:
+ if hasattr(version, "docs") and version.docs != "latest":
+ return version.docs
+
+ return "master"
+
+
+def get_class_group(class_def: ClassDef, state: State) -> str:
+ group_name = "variant"
+ class_name = class_def.name
+
+ if class_name.startswith("@"):
+ group_name = "global"
+ elif class_def.inherits:
+ inherits = class_def.inherits.strip()
+
+ while inherits in state.classes:
+ if inherits == "Node":
+ group_name = "node"
+ break
+ if inherits == "Resource":
+ group_name = "resource"
+ break
+ if inherits == "Object":
+ group_name = "object"
+ break
+
+ inode = state.classes[inherits].inherits
+ if inode:
+ inherits = inode.strip()
+ else:
+ break
+
+ return group_name
+
+
# Generator methods.
@@ -672,10 +741,7 @@ def make_rst_class(class_def: ClassDef, state: State, dry_run: bool, output_dir:
# 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
-
+ git_branch = get_git_branch()
source_xml_path = os.path.relpath(class_def.filepath, root_directory).replace("\\", "/")
source_github_url = f"https://github.com/godotengine/godot/tree/{git_branch}/{source_xml_path}"
generator_github_url = f"https://github.com/godotengine/godot/tree/{git_branch}/doc/tools/make_rst.py"
@@ -689,7 +755,8 @@ def make_rst_class(class_def: ClassDef, state: State, dry_run: bool, output_dir:
f.write(f".. _class_{class_name}:\n\n")
f.write(make_heading(class_name, "=", False))
- # Inheritance tree
+ ### INHERITANCE TREE ###
+
# Ascendants
if class_def.inherits:
inherits = class_def.inherits.strip()
@@ -723,25 +790,52 @@ def make_rst_class(class_def: ClassDef, state: State, dry_run: bool, output_dir:
f.write(make_type(child, state))
f.write("\n\n")
+ ### INTRODUCTION ###
+
+ has_description = False
+
# Brief description
- if class_def.brief_description is not None:
+ if class_def.brief_description is not None and class_def.brief_description.strip() != "":
+ has_description = True
+
f.write(f"{format_text_block(class_def.brief_description.strip(), class_def, state)}\n\n")
# Class description
if class_def.description is not None and class_def.description.strip() != "":
+ has_description = True
+
+ f.write(".. rst-class:: classref-introduction-group\n\n")
f.write(make_heading("Description", "-"))
+
f.write(f"{format_text_block(class_def.description.strip(), class_def, state)}\n\n")
+ if not has_description:
+ f.write(".. container:: contribute\n\n\t")
+ f.write(
+ translate(
+ "There is currently no description for this class. Please help us by :ref:`contributing one <doc_updating_the_class_reference>`!"
+ )
+ + "\n\n"
+ )
+
# Online tutorials
if len(class_def.tutorials) > 0:
+ f.write(".. rst-class:: classref-introduction-group\n\n")
f.write(make_heading("Tutorials", "-"))
+
for url, title in class_def.tutorials:
f.write(f"- {make_link(url, title)}\n\n")
- # Properties overview
+ ### REFERENCE TABLES ###
+
+ # Reused container for reference tables.
ml: List[Tuple[Optional[str], ...]] = []
+
+ # Properties reference table
if len(class_def.properties) > 0:
+ f.write(".. rst-class:: classref-reftable-group\n\n")
f.write(make_heading("Properties", "-"))
+
ml = []
for property_def in class_def.properties.values():
type_rst = property_def.type_name.to_rst(state)
@@ -753,76 +847,108 @@ def make_rst_class(class_def: ClassDef, state: State, dry_run: bool, output_dir:
else:
ref = f":ref:`{property_def.name}<class_{class_name}_property_{property_def.name}>`"
ml.append((type_rst, ref, default))
+
format_table(f, ml, True)
- # Constructors, Methods, Operators overview
+ # Constructors, Methods, Operators reference tables
if len(class_def.constructors) > 0:
+ f.write(".. rst-class:: classref-reftable-group\n\n")
f.write(make_heading("Constructors", "-"))
+
ml = []
for method_list in class_def.constructors.values():
for m in method_list:
ml.append(make_method_signature(class_def, m, "constructor", state))
+
format_table(f, ml)
if len(class_def.methods) > 0:
+ f.write(".. rst-class:: classref-reftable-group\n\n")
f.write(make_heading("Methods", "-"))
+
ml = []
for method_list in class_def.methods.values():
for m in method_list:
ml.append(make_method_signature(class_def, m, "method", state))
+
format_table(f, ml)
if len(class_def.operators) > 0:
+ f.write(".. rst-class:: classref-reftable-group\n\n")
f.write(make_heading("Operators", "-"))
+
ml = []
for method_list in class_def.operators.values():
for m in method_list:
ml.append(make_method_signature(class_def, m, "operator", state))
+
format_table(f, ml)
- # Theme properties
+ # Theme properties reference table
if len(class_def.theme_items) > 0:
+ f.write(".. rst-class:: classref-reftable-group\n\n")
f.write(make_heading("Theme Properties", "-"))
- pl: List[Tuple[Optional[str], ...]] = []
+
+ ml = []
for theme_item_def in class_def.theme_items.values():
ref = f":ref:`{theme_item_def.name}<class_{class_name}_theme_{theme_item_def.data_name}_{theme_item_def.name}>`"
- pl.append((theme_item_def.type_name.to_rst(state), ref, theme_item_def.default_value))
- format_table(f, pl, True)
+ ml.append((theme_item_def.type_name.to_rst(state), ref, theme_item_def.default_value))
+
+ format_table(f, ml, True)
+
+ ### DETAILED DESCRIPTIONS ###
- # Signals
+ # Signal descriptions
if len(class_def.signals) > 0:
+ f.write(make_separator(True))
+ f.write(".. rst-class:: classref-descriptions-group\n\n")
f.write(make_heading("Signals", "-"))
+
index = 0
for signal in class_def.signals.values():
if index != 0:
- f.write("----\n\n")
+ f.write(make_separator())
+
+ # Create signal signature and anchor point.
f.write(f".. _class_{class_name}_signal_{signal.name}:\n\n")
+ f.write(".. rst-class:: classref-signal\n\n")
+
_, signature = make_method_signature(class_def, signal, "", state)
- f.write(f"- {signature}\n\n")
+ f.write(f"{signature}\n\n")
+
+ # Add signal description, or a call to action if it's missing.
if signal.description is not None and signal.description.strip() != "":
f.write(f"{format_text_block(signal.description.strip(), signal, state)}\n\n")
+ else:
+ f.write(".. container:: contribute\n\n\t")
+ f.write(
+ translate(
+ "There is currently no description for this signal. Please help us by :ref:`contributing one <doc_updating_the_class_reference>`!"
+ )
+ + "\n\n"
+ )
index += 1
- # Enums
+ # Enumeration descriptions
if len(class_def.enums) > 0:
+ f.write(make_separator(True))
+ f.write(".. rst-class:: classref-descriptions-group\n\n")
f.write(make_heading("Enumerations", "-"))
+
index = 0
for e in class_def.enums.values():
if index != 0:
- f.write("----\n\n")
+ f.write(make_separator())
+
+ # Create enumeration signature and anchor point.
f.write(f".. _enum_{class_name}_{e.name}:\n\n")
- # Sphinx seems to divide the bullet list into individual <ul> tags if we weave the labels into it.
- # As such I'll put them all above the list. Won't be perfect but better than making the list visually broken.
- # As to why I'm not modifying the reference parser to directly link to the _enum label:
- # If somebody gets annoyed enough to fix it, all existing references will magically improve.
- for value in e.values.values():
- f.write(f".. _class_{class_name}_constant_{value.name}:\n\n")
+ f.write(".. rst-class:: classref-enumeration\n\n")
if e.is_bitfield:
f.write(f"flags **{e.name}**:\n\n")
@@ -830,54 +956,86 @@ def make_rst_class(class_def: ClassDef, state: State, dry_run: bool, output_dir:
f.write(f"enum **{e.name}**:\n\n")
for value in e.values.values():
- f.write(f"- **{value.name}** = **{value.value}**")
+ # Also create signature and anchor point for each enum constant.
+
+ f.write(f".. _class_{class_name}_constant_{value.name}:\n\n")
+ f.write(".. rst-class:: classref-enumeration-constant\n\n")
+
+ f.write(f"{e.type_name.to_rst(state)} **{value.name}** = ``{value.value}``\n\n")
+
+ # Add enum constant description.
+
if value.text is not None and value.text.strip() != "":
- # If value.text contains a bullet point list, each entry needs additional indentation
- f.write(f" --- {indent_bullets(format_text_block(value.text.strip(), value, state))}")
+ f.write(f"{format_text_block(value.text.strip(), value, state)}")
f.write("\n\n")
index += 1
- # Constants
+ # Constant descriptions
if len(class_def.constants) > 0:
+ f.write(make_separator(True))
+ f.write(".. rst-class:: classref-descriptions-group\n\n")
f.write(make_heading("Constants", "-"))
- # Sphinx seems to divide the bullet list into individual <ul> tags if we weave the labels into it.
- # As such I'll put them all above the list. Won't be perfect but better than making the list visually broken.
+
for constant in class_def.constants.values():
+ # Create constant signature and anchor point.
+
f.write(f".. _class_{class_name}_constant_{constant.name}:\n\n")
+ f.write(".. rst-class:: classref-constant\n\n")
+
+ f.write(f"**{constant.name}** = ``{constant.value}``\n\n")
+
+ # Add enum constant description.
- for constant in class_def.constants.values():
- f.write(f"- **{constant.name}** = **{constant.value}**")
if constant.text is not None and constant.text.strip() != "":
- f.write(f" --- {format_text_block(constant.text.strip(), constant, state)}")
+ f.write(f"{format_text_block(constant.text.strip(), constant, state)}")
f.write("\n\n")
- # Annotations
+ # Annotation descriptions
if len(class_def.annotations) > 0:
+ f.write(make_separator(True))
f.write(make_heading("Annotations", "-"))
+
index = 0
for method_list in class_def.annotations.values(): # type: ignore
for i, m in enumerate(method_list):
if index != 0:
- f.write("----\n\n")
+ f.write(make_separator())
+
+ # Create annotation signature and anchor point.
if i == 0:
f.write(f".. _class_{class_name}_annotation_{m.name}:\n\n")
+ f.write(".. rst-class:: classref-annotation\n\n")
+
_, signature = make_method_signature(class_def, m, "", state)
- f.write(f"- {signature}\n\n")
+ f.write(f"{signature}\n\n")
+
+ # Add annotation description, or a call to action if it's missing.
if m.description is not None and m.description.strip() != "":
f.write(f"{format_text_block(m.description.strip(), m, state)}\n\n")
+ else:
+ f.write(".. container:: contribute\n\n\t")
+ f.write(
+ translate(
+ "There is currently no description for this annotation. Please help us by :ref:`contributing one <doc_updating_the_class_reference>`!"
+ )
+ + "\n\n"
+ )
index += 1
# Property descriptions
if any(not p.overrides for p in class_def.properties.values()) > 0:
+ f.write(make_separator(True))
+ f.write(".. rst-class:: classref-descriptions-group\n\n")
f.write(make_heading("Property Descriptions", "-"))
+
index = 0
for property_def in class_def.properties.values():
@@ -885,113 +1043,199 @@ def make_rst_class(class_def: ClassDef, state: State, dry_run: bool, output_dir:
continue
if index != 0:
- f.write("----\n\n")
+ f.write(make_separator())
+
+ # Create property signature and anchor point.
f.write(f".. _class_{class_name}_property_{property_def.name}:\n\n")
- f.write(f"- {property_def.type_name.to_rst(state)} **{property_def.name}**\n\n")
+ f.write(".. rst-class:: classref-property\n\n")
- info: List[Tuple[Optional[str], ...]] = []
- # Not using translate() for now as it breaks table formatting.
+ property_default = ""
if property_def.default_value is not None:
- info.append(("*Default*", property_def.default_value))
+ property_default = f" = {property_def.default_value}"
+ f.write(f"{property_def.type_name.to_rst(state)} **{property_def.name}**{property_default}\n\n")
+
+ # Create property setter and getter records.
+
+ property_setget = ""
+
if property_def.setter is not None and not property_def.setter.startswith("_"):
- info.append(("*Setter*", f"{property_def.setter}(value)"))
+ property_setter = make_setter_signature(class_def, property_def, state)
+ property_setget += f"- {property_setter}\n"
+
if property_def.getter is not None and not property_def.getter.startswith("_"):
- info.append(("*Getter*", f"{property_def.getter}()"))
+ property_getter = make_getter_signature(class_def, property_def, state)
+ property_setget += f"- {property_getter}\n"
+
+ if property_setget != "":
+ f.write(".. rst-class:: classref-property-setget\n\n")
+ f.write(property_setget)
+ f.write("\n")
- if len(info) > 0:
- format_table(f, info)
+ # Add property description, or a call to action if it's missing.
if property_def.text is not None and property_def.text.strip() != "":
f.write(f"{format_text_block(property_def.text.strip(), property_def, state)}\n\n")
+ else:
+ f.write(".. container:: contribute\n\n\t")
+ f.write(
+ translate(
+ "There is currently no description for this property. Please help us by :ref:`contributing one <doc_updating_the_class_reference>`!"
+ )
+ + "\n\n"
+ )
index += 1
# Constructor, Method, Operator descriptions
if len(class_def.constructors) > 0:
+ f.write(make_separator(True))
+ f.write(".. rst-class:: classref-descriptions-group\n\n")
f.write(make_heading("Constructor Descriptions", "-"))
+
index = 0
for method_list in class_def.constructors.values():
for i, m in enumerate(method_list):
if index != 0:
- f.write("----\n\n")
+ f.write(make_separator())
+
+ # Create constructor signature and anchor point.
if i == 0:
f.write(f".. _class_{class_name}_constructor_{m.name}:\n\n")
+ f.write(".. rst-class:: classref-constructor\n\n")
+
ret_type, signature = make_method_signature(class_def, m, "", state)
- f.write(f"- {ret_type} {signature}\n\n")
+ f.write(f"{ret_type} {signature}\n\n")
+
+ # Add constructor description, or a call to action if it's missing.
if m.description is not None and m.description.strip() != "":
f.write(f"{format_text_block(m.description.strip(), m, state)}\n\n")
+ else:
+ f.write(".. container:: contribute\n\n\t")
+ f.write(
+ translate(
+ "There is currently no description for this constructor. Please help us by :ref:`contributing one <doc_updating_the_class_reference>`!"
+ )
+ + "\n\n"
+ )
index += 1
if len(class_def.methods) > 0:
+ f.write(make_separator(True))
+ f.write(".. rst-class:: classref-descriptions-group\n\n")
f.write(make_heading("Method Descriptions", "-"))
+
index = 0
for method_list in class_def.methods.values():
for i, m in enumerate(method_list):
if index != 0:
- f.write("----\n\n")
+ f.write(make_separator())
+
+ # Create method signature and anchor point.
if i == 0:
f.write(f".. _class_{class_name}_method_{m.name}:\n\n")
+ f.write(".. rst-class:: classref-method\n\n")
+
ret_type, signature = make_method_signature(class_def, m, "", state)
- f.write(f"- {ret_type} {signature}\n\n")
+ f.write(f"{ret_type} {signature}\n\n")
+
+ # Add method description, or a call to action if it's missing.
if m.description is not None and m.description.strip() != "":
f.write(f"{format_text_block(m.description.strip(), m, state)}\n\n")
+ else:
+ f.write(".. container:: contribute\n\n\t")
+ f.write(
+ translate(
+ "There is currently no description for this method. Please help us by :ref:`contributing one <doc_updating_the_class_reference>`!"
+ )
+ + "\n\n"
+ )
index += 1
if len(class_def.operators) > 0:
+ f.write(make_separator(True))
+ f.write(".. rst-class:: classref-descriptions-group\n\n")
f.write(make_heading("Operator Descriptions", "-"))
+
index = 0
for method_list in class_def.operators.values():
for i, m in enumerate(method_list):
if index != 0:
- f.write("----\n\n")
+ f.write(make_separator())
- if i == 0:
- f.write(
- f".. _class_{class_name}_operator_{sanitize_operator_name(m.name, state)}_{m.return_type.type_name}:\n\n"
- )
+ # Create operator signature and anchor point.
+
+ operator_anchor = f".. _class_{class_name}_operator_{sanitize_operator_name(m.name, state)}"
+ for parameter in m.parameters:
+ operator_anchor += f"_{parameter.type_name.type_name}"
+ operator_anchor += f":\n\n"
+ f.write(operator_anchor)
+
+ f.write(".. rst-class:: classref-operator\n\n")
ret_type, signature = make_method_signature(class_def, m, "", state)
- f.write(f"- {ret_type} {signature}\n\n")
+ f.write(f"{ret_type} {signature}\n\n")
+
+ # Add operator description, or a call to action if it's missing.
if m.description is not None and m.description.strip() != "":
f.write(f"{format_text_block(m.description.strip(), m, state)}\n\n")
+ else:
+ f.write(".. container:: contribute\n\n\t")
+ f.write(
+ translate(
+ "There is currently no description for this operator. Please help us by :ref:`contributing one <doc_updating_the_class_reference>`!"
+ )
+ + "\n\n"
+ )
index += 1
# Theme property descriptions
if len(class_def.theme_items) > 0:
+ f.write(make_separator(True))
+ f.write(".. rst-class:: classref-descriptions-group\n\n")
f.write(make_heading("Theme Property Descriptions", "-"))
+
index = 0
for theme_item_def in class_def.theme_items.values():
if index != 0:
- f.write("----\n\n")
+ f.write(make_separator())
+
+ # Create theme property signature and anchor point.
f.write(f".. _class_{class_name}_theme_{theme_item_def.data_name}_{theme_item_def.name}:\n\n")
- f.write(f"- {theme_item_def.type_name.to_rst(state)} **{theme_item_def.name}**\n\n")
+ f.write(".. rst-class:: classref-themeproperty\n\n")
- info = []
+ theme_item_default = ""
if theme_item_def.default_value is not None:
- # Not using translate() for now as it breaks table formatting.
- info.append(("*Default*", theme_item_def.default_value))
+ theme_item_default = f" = {theme_item_def.default_value}"
+ f.write(f"{theme_item_def.type_name.to_rst(state)} **{theme_item_def.name}**{theme_item_default}\n\n")
- if len(info) > 0:
- format_table(f, info)
+ # Add theme property description, or a call to action if it's missing.
if theme_item_def.text is not None and theme_item_def.text.strip() != "":
f.write(f"{format_text_block(theme_item_def.text.strip(), theme_item_def, state)}\n\n")
+ else:
+ f.write(".. container:: contribute\n\n\t")
+ f.write(
+ translate(
+ "There is currently no description for this theme property. Please help us by :ref:`contributing one <doc_updating_the_class_reference>`!"
+ )
+ + "\n\n"
+ )
index += 1
@@ -1051,7 +1295,10 @@ def make_method_signature(
if isinstance(definition, MethodDef) and ref_type != "":
if ref_type == "operator":
op_name = definition.name.replace("<", "\\<") # So operator "<" gets correctly displayed.
- out += f":ref:`{op_name}<class_{class_def.name}_{ref_type}_{sanitize_operator_name(definition.name, state)}_{definition.return_type.type_name}>` "
+ out += f":ref:`{op_name}<class_{class_def.name}_{ref_type}_{sanitize_operator_name(definition.name, state)}"
+ for parameter in definition.parameters:
+ out += f"_{parameter.type_name.type_name}"
+ out += f">` "
else:
out += f":ref:`{definition.name}<class_{class_def.name}_{ref_type}_{definition.name}>` "
else:
@@ -1086,6 +1333,39 @@ def make_method_signature(
return ret_type, out
+def make_setter_signature(class_def: ClassDef, property_def: PropertyDef, state: State) -> str:
+ if property_def.setter is None:
+ return ""
+
+ # If setter is a method available as a method definition, we use that.
+ if property_def.setter in class_def.methods:
+ setter = class_def.methods[property_def.setter][0]
+ # Otherwise we fake it with the information we have available.
+ else:
+ setter_params: List[ParameterDef] = []
+ setter_params.append(ParameterDef("value", property_def.type_name, None))
+ setter = MethodDef(property_def.setter, TypeName("void"), setter_params, None, None)
+
+ ret_type, signature = make_method_signature(class_def, setter, "", state)
+ return f"{ret_type} {signature}"
+
+
+def make_getter_signature(class_def: ClassDef, property_def: PropertyDef, state: State) -> str:
+ if property_def.getter is None:
+ return ""
+
+ # If getter is a method available as a method definition, we use that.
+ if property_def.getter in class_def.methods:
+ getter = class_def.methods[property_def.getter][0]
+ # Otherwise we fake it with the information we have available.
+ else:
+ getter_params: List[ParameterDef] = []
+ getter = MethodDef(property_def.getter, property_def.type_name, getter_params, None, None)
+
+ ret_type, signature = make_method_signature(class_def, getter, "", state)
+ return f"{ret_type} {signature}"
+
+
def make_heading(title: str, underline: str, l10n: bool = True) -> str:
if l10n:
new_title = translate(title)
@@ -1117,6 +1397,14 @@ def make_footer() -> str:
)
+def make_separator(section_level: bool = False) -> str:
+ separator_class = "item"
+ if section_level:
+ separator_class = "section"
+
+ return f".. rst-class:: classref-{separator_class}-separator\n\n----\n\n"
+
+
def make_link(url: str, title: str) -> str:
match = GODOT_DOCS_PATTERN.search(url)
if match:
@@ -1142,6 +1430,53 @@ def make_link(url: str, title: str) -> str:
return f"`{url} <{url}>`__"
+def make_rst_index(grouped_classes: Dict[str, List[str]], dry_run: bool, output_dir: str) -> None:
+
+ if dry_run:
+ f = open(os.devnull, "w", encoding="utf-8")
+ else:
+ f = open(os.path.join(output_dir, "index.rst"), "w", encoding="utf-8")
+
+ # Remove the "Edit on Github" button from the online docs page.
+ f.write(":github_url: hide\n\n")
+
+ # Warn contributors not to edit this file directly.
+ # Also provide links to the source files for reference.
+
+ git_branch = get_git_branch()
+ generator_github_url = f"https://github.com/godotengine/godot/tree/{git_branch}/doc/tools/make_rst.py"
+
+ f.write(".. DO NOT EDIT THIS FILE!!!\n")
+ f.write(".. Generated automatically from Godot engine sources.\n")
+ f.write(f".. Generator: {generator_github_url}.\n\n")
+
+ f.write(".. _doc_class_reference:\n\n")
+
+ main_title = translate("All classes")
+ f.write(f"{main_title}\n")
+ f.write(f"{'=' * len(main_title)}\n\n")
+
+ for group_name in CLASS_GROUPS:
+ if group_name in grouped_classes:
+ group_title = translate(CLASS_GROUPS[group_name])
+
+ f.write(f"{group_title}\n")
+ f.write(f"{'=' * len(group_title)}\n\n")
+
+ f.write(".. toctree::\n")
+ f.write(" :maxdepth: 1\n")
+ f.write(f" :name: toc-class-ref-{group_name}s\n")
+ f.write("\n")
+
+ if group_name in CLASS_GROUPS_BASE:
+ f.write(f" class_{CLASS_GROUPS_BASE[group_name].lower()}\n")
+
+ for class_name in grouped_classes[group_name]:
+ f.write(f" class_{class_name.lower()}\n")
+
+ f.write("\n")
+
+
# Formatting helpers.
@@ -1230,10 +1565,10 @@ def format_text_block(
escape_post = False
# Tag is a reference to a class.
- if tag_text in state.classes:
+ if tag_text in state.classes and not inside_code:
if tag_text == state.current_class:
- # Don't create a link to the same class, format it as inline code.
- tag_text = f"``{tag_text}``"
+ # Don't create a link to the same class, format it as strong emphasis.
+ tag_text = f"**{tag_text}**"
else:
tag_text = make_type(tag_text, state)
escape_pre = True
@@ -1695,6 +2030,11 @@ def format_table(f: TextIO, data: List[Tuple[Optional[str], ...]], remove_empty_
if len(data) == 0:
return
+ f.write(".. table::\n")
+ f.write(" :widths: auto\n\n")
+
+ # Calculate the width of each column first, we will use this information
+ # to properly format RST-style tables.
column_sizes = [0] * len(data[0])
for row in data:
for i, text in enumerate(row):
@@ -1702,14 +2042,21 @@ def format_table(f: TextIO, data: List[Tuple[Optional[str], ...]], remove_empty_
if text_length > column_sizes[i]:
column_sizes[i] = text_length
+ # Each table row is wrapped in two separators, consecutive rows share the same separator.
+ # All separators, or rather borders, have the same shape and content. We compose it once,
+ # then reuse it.
+
sep = ""
for size in column_sizes:
if size == 0 and remove_empty_columns:
continue
- sep += "+" + "-" * (size + 2)
+ sep += "+" + "-" * (size + 2) # Content of each cell is padded by 1 on each side.
sep += "+\n"
- f.write(sep)
+ # Draw the first separator.
+ f.write(f" {sep}")
+
+ # Draw each row and close it with a separator.
for row in data:
row_text = "|"
for i, text in enumerate(row):
@@ -1717,8 +2064,10 @@ def format_table(f: TextIO, data: List[Tuple[Optional[str], ...]], remove_empty_
continue
row_text += f' {(text or "").ljust(column_sizes[i])} |'
row_text += "\n"
- f.write(row_text)
- f.write(sep)
+
+ f.write(f" {row_text}")
+ f.write(f" {sep}")
+
f.write("\n")
@@ -1780,24 +2129,5 @@ def sanitize_operator_name(dirty_name: str, state: State) -> str:
return clear_name
-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.
- # Ignore the first line - text will be prepended to it so bullet points wouldn't work anyway.
- bullet_points = "-"
-
- lines = text.splitlines(keepends=True)
- for line_index, line in enumerate(lines[1:], start=1):
- pos = 0
- while pos < len(line) and line[pos] == "\t":
- pos += 1
-
- if pos < len(line) and line[pos] in bullet_points:
- lines[line_index] = f"{line[:pos]}\t{line[pos:]}"
-
- return "".join(lines)
-
-
if __name__ == "__main__":
main()
diff --git a/doc/translations/ar.po b/doc/translations/ar.po
index ae292d4035..751017b573 100644
--- a/doc/translations/ar.po
+++ b/doc/translations/ar.po
@@ -20,13 +20,14 @@
# ywmaa <ywmaa.personal@gmail.com>, 2022.
# TabbyDev <Mandomody25@gmail.com>, 2022.
# عبد الرحمن أبو سعدة ||Abd Alrahman abo saada <abdalrahmanabs2005@gmail.com>, 2022.
+# NEDAL NNEE <ASEL1234543210@gmail.com>, 2022.
+# Abdallah <azzouni2007abd@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-07-23 03:56+0000\n"
-"Last-Translator: عبد الرحمن أبو سعدة ||Abd Alrahman abo saada "
-"<abdalrahmanabs2005@gmail.com>\n"
+"PO-Revision-Date: 2022-11-03 11:48+0000\n"
+"Last-Translator: Abdallah <azzouni2007abd@gmail.com>\n"
"Language-Team: Arabic <https://hosted.weblate.org/projects/godot-engine/"
"godot-class-reference/ar/>\n"
"Language: ar\n"
@@ -35,7 +36,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.14-dev\n"
+"X-Generator: Weblate 4.14.2-dev\n"
#: doc/tools/make_rst.py
msgid "Description"
@@ -110,10 +111,9 @@ msgid "Getter"
msgstr "جالب"
#: doc/tools/make_rst.py
-#, fuzzy
msgid ""
"This method should typically be overridden by the user to have any effect."
-msgstr "يجب تجاوز هذه الطريقة من المستخدم ليكون لها أي تأثير."
+msgstr "عادة يجب تجاوز هذه الدالة من قبل المستخدم ليكون لها أي تأثير."
#: doc/tools/make_rst.py
msgid ""
@@ -198,7 +198,6 @@ msgstr ""
"أسماء الألوان المدعومة هي Ù†ÙØ³ الثوابت Ø§Ù„Ù…Ø¹Ø±Ù‘ÙØ© ÙÙŠ [Color]."
#: modules/gdscript/doc_classes/@GDScript.xml
-#, fuzzy
msgid ""
"Returns the absolute value of parameter [code]s[/code] (i.e. positive "
"value).\n"
@@ -209,7 +208,7 @@ msgstr ""
"لعرض القيمة المطلقة Ù„Ù„Ù…ÙØ¹Ø§Ù…Ù„ [code]s[/code] (القيمة المطلقة أي القيمة "
"الموجبة).\n"
"[codeblock]\n"
-"(a = abs(-1 #القيمة المطلقة لـ(1-) هي 1ØŒ وبالتالي ÙØ¥Ù† قيمة a ستكون 1\n"
+"(a = abs(-1 #القيمة المطلقة لـ(1-) هي 1ØŒ وبالتالي ÙØ¥Ù† قيمة a ستكون 1\n"
"[/codeblock]"
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -628,7 +627,8 @@ msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
-"Returns an array of dictionaries representing the current call stack.\n"
+"Returns an array of dictionaries representing the current call stack. See "
+"also [method print_stack].\n"
"[codeblock]\n"
"func _ready():\n"
" foo()\n"
@@ -643,7 +643,11 @@ msgid ""
"[codeblock]\n"
"[{function:bar, line:12, source:res://script.gd}, {function:foo, line:9, "
"source:res://script.gd}, {function:_ready, line:6, source:res://script.gd}]\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] [method get_stack] only works if the running instance is "
+"connected to a debugging server (i.e. an editor instance). [method "
+"get_stack] will not work in projects exported in release mode, or in "
+"projects exported in debug mode if not connected to a debugging server."
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -1022,12 +1026,16 @@ msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
-"Prints a stack track at code location, only works when running with debugger "
-"turned on.\n"
+"Prints a stack trace at the current code location. See also [method "
+"get_stack].\n"
"Output in the console would look something like this:\n"
"[codeblock]\n"
"Frame 0 - res://test.gd:16 in function '_process'\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] [method print_stack] only works if the running instance is "
+"connected to a debugging server (i.e. an editor instance). [method "
+"print_stack] will not work in projects exported in release mode, or in "
+"projects exported in debug mode if not connected to a debugging server."
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -3645,6 +3653,26 @@ msgid "Hints that an image is compressed using lossless compression."
msgstr ""
#: doc/classes/@GlobalScope.xml
+msgid ""
+"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:\n"
+"[codeblock]\n"
+"hint_string = \"%s:\" % [TYPE_INT] # Array of inteters.\n"
+"hint_string = \"%s:%s:\" % [TYPE_ARRAY, TYPE_REAL] # Two-dimensional array "
+"of floats.\n"
+"hint_string = \"%s/%s:Resource\" % [TYPE_OBJECT, TYPE_OBJECT] # Array of "
+"resources.\n"
+"hint_string = \"%s:%s/%s:Resource\" % [TYPE_ARRAY, TYPE_OBJECT, TYPE_OBJECT] "
+"# Two-dimensional array of resources.\n"
+"[/codeblock]\n"
+"[b]Note:[/b] The final colon is required to specify for properly detecting "
+"built-in types."
+msgstr ""
+
+#: doc/classes/@GlobalScope.xml
msgid "The property is serialized and saved in the scene file (default)."
msgstr ""
@@ -4329,8 +4357,7 @@ msgstr ""
#: doc/classes/AudioStreamPlayer.xml doc/classes/Button.xml
#: doc/classes/CanvasLayer.xml doc/classes/CollisionShape2D.xml
#: doc/classes/ColorRect.xml doc/classes/Input.xml doc/classes/InputEvent.xml
-#: doc/classes/InputEventAction.xml doc/classes/Label.xml
-#: doc/classes/Particles2D.xml doc/classes/Timer.xml
+#: doc/classes/InputEventAction.xml doc/classes/Label.xml doc/classes/Timer.xml
#: doc/classes/VisibilityNotifier2D.xml
msgid "2D Dodge The Creeps Demo"
msgstr ""
@@ -7249,7 +7276,10 @@ msgid ""
"var array = []\n"
"array.resize(10)\n"
"array.fill(0) # Initialize the 10 elements to 0.\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] If [code]value[/code] is of a reference type ([Object]-derived, "
+"[Array], [Dictionary], etc.) then the array is filled with the references to "
+"the same object, i.e. no duplicates are created."
msgstr ""
#: doc/classes/Array.xml doc/classes/PoolByteArray.xml
@@ -7434,6 +7464,9 @@ msgstr ""
#: doc/classes/Array.xml
msgid ""
"Sorts the array.\n"
+"[b]Note:[/b] The sorting algorithm used is not [url=https://en.wikipedia.org/"
+"wiki/Sorting_algorithm#Stability]stable[/url]. This means that values "
+"considered equal may have their order changed when using [method sort].\n"
"[b]Note:[/b] Strings are sorted in alphabetical order (as opposed to natural "
"order). This may lead to unexpected behavior when sorting an array of "
"strings ending with a sequence of numbers. Consider the following example:\n"
@@ -7453,9 +7486,13 @@ msgid ""
"For two elements [code]a[/code] and [code]b[/code], if the given method "
"returns [code]true[/code], element [code]b[/code] will be after element "
"[code]a[/code] in the array.\n"
+"[b]Note:[/b] The sorting algorithm used is not [url=https://en.wikipedia.org/"
+"wiki/Sorting_algorithm#Stability]stable[/url]. This means that values "
+"considered equal may have their order changed when using [method "
+"sort_custom].\n"
"[b]Note:[/b] You cannot randomize the return value as the heapsort algorithm "
-"expects a deterministic result. Doing so will result in unexpected "
-"behavior.\n"
+"expects a deterministic result. Randomizing the return value will result in "
+"unexpected behavior.\n"
"[codeblock]\n"
"class MyCustomSorter:\n"
" static func sort_ascending(a, b):\n"
@@ -10094,10 +10131,9 @@ msgstr ""
#: doc/classes/AudioStreamGeneratorPlayback.xml
msgid ""
-"Returns the number of audio data frames left to play. If this returned "
-"number reaches [code]0[/code], the audio will stop playing until frames are "
-"added again. Therefore, make sure your script can always generate and push "
-"new audio frames fast enough to avoid audio cracking."
+"Returns the number of frames that can be pushed to the audio sample data "
+"buffer without overflowing it. If the result is [code]0[/code], the buffer "
+"is full."
msgstr ""
#: doc/classes/AudioStreamGeneratorPlayback.xml
@@ -10629,14 +10665,14 @@ msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
"Node for back-buffering the currently-displayed screen. The region defined "
-"in the BackBufferCopy node is buffered with the content of the screen it "
+"in the [BackBufferCopy] node is buffered with the content of the screen it "
"covers, or the entire screen according to the copy mode set. Use the "
"[code]texture(SCREEN_TEXTURE, ...)[/code] function in your shader scripts to "
"access the buffer.\n"
"[b]Note:[/b] Since this node inherits from [Node2D] (and not [Control]), "
"anchors and margins won't apply to child [Control]-derived nodes. This can "
"be problematic when resizing the window. To avoid this, add [Control]-"
-"derived nodes as [i]siblings[/i] to the BackBufferCopy node instead of "
+"derived nodes as [i]siblings[/i] to the [BackBufferCopy] node instead of "
"adding them as children."
msgstr ""
@@ -10646,22 +10682,22 @@ msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
-"The area covered by the BackBufferCopy. Only used if [member copy_mode] is "
+"The area covered by the [BackBufferCopy]. Only used if [member copy_mode] is "
"[constant COPY_MODE_RECT]."
msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
-"Disables the buffering mode. This means the BackBufferCopy node will "
+"Disables the buffering mode. This means the [BackBufferCopy] node will "
"directly use the portion of screen it covers."
msgstr ""
#: doc/classes/BackBufferCopy.xml
-msgid "BackBufferCopy buffers a rectangular region."
+msgid "[BackBufferCopy] buffers a rectangular region."
msgstr ""
#: doc/classes/BackBufferCopy.xml
-msgid "BackBufferCopy buffers the entire screen."
+msgid "[BackBufferCopy] buffers the entire screen."
msgstr ""
#: doc/classes/BakedLightmap.xml
@@ -19456,6 +19492,14 @@ msgid "Cylinder shape for collisions."
msgstr ""
#: doc/classes/CylinderShape.xml
+msgid ""
+"Cylinder shape for collisions.\n"
+"[b]Note:[/b] When using GodotPhysics instead of the default Bullet physics "
+"engine, there are several known bugs with cylinder collision shapes. Using "
+"[CapsuleShape] or [BoxShape] instead is recommended."
+msgstr ""
+
+#: doc/classes/CylinderShape.xml
msgid "The cylinder's height."
msgstr ""
@@ -22290,7 +22334,10 @@ msgid ""
"[/codeblock]\n"
"[b]Note:[/b] The script is run in the Editor context, which means the output "
"is visible in the console window started with the Editor (stdout) instead of "
-"the usual Godot [b]Output[/b] dock."
+"the usual Godot [b]Output[/b] dock.\n"
+"[b]Note:[/b] EditorScript is reference counted, meaning it is destroyed when "
+"nothing references it. This can cause errors during asynchronous operations "
+"if there are no references to the script."
msgstr ""
#: doc/classes/EditorScript.xml
@@ -33021,7 +33068,9 @@ msgid ""
"The size of the light in Godot units. Only considered in baked lightmaps and "
"only if [member light_bake_mode] is set to [constant BAKE_ALL]. Increasing "
"this value will make the shadows appear blurrier. This can be used to "
-"simulate area lights to an extent."
+"simulate area lights to an extent.\n"
+"[b]Note:[/b] [member light_size] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/Light.xml
@@ -36349,7 +36398,10 @@ msgid ""
"use the [method get_next_location] function once every physics frame to "
"update the internal path logic of the NavigationAgent. The returned vector "
"position from this function should be used as the next movement position for "
-"the agent's parent Node."
+"the agent's parent Node.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues."
msgstr ""
#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
@@ -36599,7 +36651,10 @@ msgid ""
"use the [method get_next_location] function once every physics frame to "
"update the internal path logic of the NavigationAgent. The returned vector "
"position from this function should be used as the next movement position for "
-"the agent's parent Node."
+"the agent's parent Node.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues."
msgstr ""
#: doc/classes/NavigationAgent2D.xml
@@ -37316,6 +37371,9 @@ msgid ""
"modified velocity as-is might lead to pushing and agent outside of a "
"navigable area. This is a limitation of the collision avoidance system, any "
"more complex situation may require the use of the physics engine.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues.\n"
"This server keeps tracks of any call and executes them during the sync "
"phase. This means that you can request any change to the map, using any "
"thread, without worrying."
@@ -40126,7 +40184,9 @@ msgid ""
"The light's radius. Note that the effectively lit area may appear to be "
"smaller depending on the [member omni_attenuation] in use. No matter the "
"[member omni_attenuation] in use, the light will never reach anything "
-"outside this radius."
+"outside this radius.\n"
+"[b]Note:[/b] [member omni_range] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -40642,11 +40702,11 @@ msgstr "ÙŠÙØ±Ø¬Ø¹ قيمة الجيب العكسية للمَعلم."
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] cache data directory according to the operating "
-"system's standards. On desktop platforms, this path can be overridden by "
-"setting the [code]XDG_CACHE_HOME[/code] environment variable before starting "
-"the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in "
-"Godot projects[/url] in the documentation for more information. See also "
-"[method get_config_dir] and [method get_data_dir].\n"
+"system's standards. On Linux, this path can be overridden by setting the "
+"[code]XDG_CACHE_HOME[/code] environment variable before starting the "
+"project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot "
+"projects[/url] in the documentation for more information. See also [method "
+"get_config_dir] and [method get_data_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -40680,11 +40740,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] user configuration directory according to the "
-"operating system's standards. On desktop platforms, this path can be "
-"overridden by setting the [code]XDG_CONFIG_HOME[/code] environment variable "
-"before starting the project. See [url=$DOCS_URL/tutorials/io/data_paths."
-"html]File paths in Godot projects[/url] in the documentation for more "
-"information. See also [method get_cache_dir] and [method get_data_dir].\n"
+"operating system's standards. On Linux, this path can be overridden by "
+"setting the [code]XDG_CONFIG_HOME[/code] environment variable before "
+"starting the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File "
+"paths in Godot projects[/url] in the documentation for more information. See "
+"also [method get_cache_dir] and [method get_data_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -40706,11 +40766,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] user data directory according to the operating "
-"system's standards. On desktop platforms, this path can be overridden by "
-"setting the [code]XDG_DATA_HOME[/code] environment variable before starting "
-"the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in "
-"Godot projects[/url] in the documentation for more information. See also "
-"[method get_cache_dir] and [method get_config_dir].\n"
+"system's standards. On Linux, this path can be overridden by setting the "
+"[code]XDG_DATA_HOME[/code] environment variable before starting the project. "
+"See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot "
+"projects[/url] in the documentation for more information. See also [method "
+"get_cache_dir] and [method get_config_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -41688,31 +41748,31 @@ msgstr ""
#: doc/classes/OS.xml
msgid "Sunday."
-msgstr ""
+msgstr "الأحد."
#: doc/classes/OS.xml
msgid "Monday."
-msgstr ""
+msgstr "الإثنين."
#: doc/classes/OS.xml
msgid "Tuesday."
-msgstr ""
+msgstr "الثلاثاء."
#: doc/classes/OS.xml
msgid "Wednesday."
-msgstr ""
+msgstr "الإربعاء."
#: doc/classes/OS.xml
msgid "Thursday."
-msgstr ""
+msgstr "الخميس."
#: doc/classes/OS.xml
msgid "Friday."
-msgstr ""
+msgstr "الجمعة."
#: doc/classes/OS.xml
msgid "Saturday."
-msgstr ""
+msgstr "السبت."
#: doc/classes/OS.xml
msgid "January."
@@ -42573,6 +42633,16 @@ msgid "Particle systems (2D)"
msgstr ""
#: doc/classes/Particles2D.xml
+msgid "2D Particles Demo"
+msgstr ""
+
+#: doc/classes/Particles2D.xml
+msgid ""
+"2D Dodge The Creeps Demo (uses GPUParticles2D for the trail behind the "
+"player)"
+msgstr ""
+
+#: doc/classes/Particles2D.xml
msgid "Returns a rectangle containing the positions of all existing particles."
msgstr ""
@@ -50174,15 +50244,22 @@ msgstr ""
#: doc/classes/ProjectSettings.xml
msgid ""
"If [code]true[/code], uses a fast post-processing filter to make banding "
-"significantly less visible. In some cases, debanding may introduce a "
-"slightly noticeable dithering pattern. It's recommended to enable debanding "
-"only when actually needed since the dithering pattern will make lossless-"
-"compressed screenshots larger.\n"
+"significantly less visible in 3D. 2D rendering is [i]not[/i] affected by "
+"debanding unless the [member Environment.background_mode] is [constant "
+"Environment.BG_CANVAS]. In this case, [member rendering/quality/"
+"intended_usage/framebuffer_allocation] must also be set to [b]3D[/b].\n"
+"In some cases, debanding may introduce a slightly noticeable dithering "
+"pattern. It's recommended to enable debanding only when actually needed "
+"since the dithering pattern will make lossless-compressed screenshots "
+"larger.\n"
"[b]Note:[/b] Only available on the GLES3 backend. [member rendering/quality/"
"depth/hdr] must also be [code]true[/code] for debanding to be effective.\n"
"[b]Note:[/b] There are known issues with debanding breaking rendering on "
"mobile platforms. Due to this, it is recommended to leave this option "
-"disabled when targeting mobile platforms."
+"disabled when targeting mobile platforms.\n"
+"[b]Note:[/b] This property is only read when the project starts. To set "
+"debanding at run-time, set [member Viewport.debanding] on the root "
+"[Viewport] instead."
msgstr ""
#: doc/classes/ProjectSettings.xml
@@ -51779,17 +51856,28 @@ msgstr ""
#: modules/regex/doc_classes/RegEx.xml
msgid ""
"Searches the text for the compiled pattern. Returns a [RegExMatch] container "
-"of the first matching result if found, otherwise [code]null[/code]. The "
-"region to search within can be specified without modifying where the start "
-"and end anchor would be."
+"of the first matching result if found, otherwise [code]null[/code].\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegEx.xml
msgid ""
"Searches the text for the compiled pattern. Returns an array of [RegExMatch] "
"containers for each non-overlapping result. If no results were found, an "
-"empty array is returned instead. The region to search within can be "
-"specified without modifying where the start and end anchor would be."
+"empty array is returned instead.\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegEx.xml
@@ -51798,8 +51886,14 @@ msgid ""
"specified string. Escapes and backreferences such as [code]$1[/code] and "
"[code]$name[/code] are expanded and resolved. By default, only the first "
"instance is replaced, but it can be changed for all instances (global "
-"replacement). The region to search within can be specified without modifying "
-"where the start and end anchor would be."
+"replacement).\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegExMatch.xml
@@ -54515,7 +54609,11 @@ msgid "Call a group immediately (calls are normally made on idle)."
msgstr ""
#: doc/classes/SceneTree.xml
-msgid "Call a group only once even if the call is executed many times."
+msgid ""
+"Call a group only once even if the call is executed many times.\n"
+"[b]Note:[/b] Arguments are not taken into account when deciding whether the "
+"call is unique or not. Therefore when the same method is called with "
+"different arguments, only the first call will be performed."
msgstr ""
#: doc/classes/SceneTree.xml
@@ -56352,7 +56450,9 @@ msgid ""
"[b]Note:[/b] Mixed negative scales in 3D are not decomposable from the "
"transformation matrix. Due to the way scale is represented with "
"transformation matrices in Godot, the scale values will either be all "
-"positive or all negative."
+"positive or all negative.\n"
+"[b]Note:[/b] Not all nodes are visually scaled by the [member scale] "
+"property. For example, [Light]s are not visually affected by [member scale]."
msgstr ""
#: doc/classes/Spatial.xml
@@ -57730,7 +57830,10 @@ msgid ""
msgstr ""
#: doc/classes/SpotLight.xml
-msgid "The spotlight's angle in degrees."
+msgid ""
+"The spotlight's angle in degrees.\n"
+"[b]Note:[/b] [member spot_angle] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/SpotLight.xml
@@ -57746,7 +57849,9 @@ msgid ""
"The maximal range that can be reached by the spotlight. Note that the "
"effectively lit area may appear to be smaller depending on the [member "
"spot_attenuation] in use. No matter the [member spot_attenuation] in use, "
-"the light will never reach anything outside this range."
+"the light will never reach anything outside this range.\n"
+"[b]Note:[/b] [member spot_range] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/SpringArm.xml
@@ -67018,10 +67123,15 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
"If [code]true[/code], uses a fast post-processing filter to make banding "
-"significantly less visible. In some cases, debanding may introduce a "
-"slightly noticeable dithering pattern. It's recommended to enable debanding "
-"only when actually needed since the dithering pattern will make lossless-"
-"compressed screenshots larger.\n"
+"significantly less visible in 3D. 2D rendering is [i]not[/i] affected by "
+"debanding unless the [member Environment.background_mode] is [constant "
+"Environment.BG_CANVAS]. In this case, [member usage] must also be set to "
+"[constant USAGE_3D]. See also [member ProjectSettings.rendering/quality/"
+"filters/use_debanding].\n"
+"In some cases, debanding may introduce a slightly noticeable dithering "
+"pattern. It's recommended to enable debanding only when actually needed "
+"since the dithering pattern will make lossless-compressed screenshots "
+"larger.\n"
"[b]Note:[/b] Only available on the GLES3 backend. [member hdr] must also be "
"[code]true[/code] for debanding to be effective."
msgstr ""
@@ -67032,8 +67142,8 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
-"If [code]true[/code], the viewport will disable 3D rendering. For actual "
-"disabling use [code]usage[/code]."
+"If [code]true[/code], the viewport will disable 3D rendering. To actually "
+"disable allocation of 3D buffers, set [member usage] instead."
msgstr ""
#: doc/classes/Viewport.xml
@@ -67185,7 +67295,9 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
-"The rendering mode of viewport.\n"
+"The viewport's rendering mode. This controls which buffers are allocated for "
+"the viewport (2D only, or 2D + 3D). 2D-only options can reduce memory usage "
+"and improve performance slightly, especially on low-end devices.\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."
@@ -67717,6 +67829,22 @@ msgid ""
"render object this [VisualInstance] is set to."
msgstr ""
+#: doc/classes/VisualInstance.xml
+msgid ""
+"The sorting offset used by this [VisualInstance]. Adjusting it to a higher "
+"value will make the [VisualInstance] reliably draw on top of other "
+"[VisualInstance]s that are otherwise positioned at the same spot."
+msgstr ""
+
+#: doc/classes/VisualInstance.xml
+msgid ""
+"If [code]true[/code], the object is sorted based on the [AABB] center. "
+"Sorted based on the global position otherwise.\n"
+"The [AABB] center based sorting is generally more accurate for 3D models. "
+"The position based sorting instead allows to better control the drawing "
+"order when working with [Particles] and [CPUParticles]."
+msgstr ""
+
#: modules/visual_script/doc_classes/VisualScript.xml
msgid "A script implemented in the Visual Script programming environment."
msgstr ""
@@ -75277,6 +75405,118 @@ msgid ""
"a wider or narrower set of devices and input methods, or to allow more "
"advanced interactions with more advanced devices."
msgstr ""
+"WebXR هو معيار Ù…ÙØªÙˆØ­ يسمح بإنشاء تطبيقات VR Ùˆ AR تعمل ÙÙŠ Ù…ØªØµÙØ­ الويب.\n"
+"على هذا النحو ØŒ لا ØªØªÙˆÙØ± هذه الواجهة إلا عند التشغيل ÙÙŠ تصدير HTML5.\n"
+"يدعم WebXR مجموعة واسعة من الأجهزة ، من الأجهزة ذات القدرات العالية (مثل "
+"Valve Index و HTC Vive و Oculus Rift و Quest) وصولاً إلى الأجهزة الأقل قدرة "
+"(مثل Google Cardboard أو Oculus Go أو GearVR أو الهوات٠الذكية العادية).\n"
+"نظرًا لأن WebXR يعتمد على Javascript ØŒ ÙØ¥Ù†Ù‡ يستخدم بشكل مكث٠عمليات "
+"الاسترجاعات ، مما يعني أن [WebXRInterface] مضطر لاستخدام الإشارات ، حيث "
+"تستخدم واجهات AR / VR الأخرى وظائ٠تعيد النتيجة على الÙور. هذا يجعل "
+"[WebXRInterface] أكثر تعقيدًا ÙÙŠ التهيئة من واجهات AR / VR الأخرى.\n"
+"إليك الحد الأدنى من Ø§Ù„Ø´ÙØ±Ø© المطلوبة لبدء جلسة VR غامرة:\n"
+"[كودبلوك]\n"
+"يمتد المكاني\n"
+"\n"
+"var webxr_interface\n"
+"var vr_supported = خطأ\n"
+"\n"
+"func _ready ():\n"
+" # Ù†ÙØªØ±Ø¶ أن هذه العقدة بها زر عندما كان Ø·Ùلاً.\n"
+" # هذا الزر للمستخدم للمواÙقة على الدخول ÙÙŠ وضع VR الغامر.\n"
+" $ Button.connect (\"pressed\"، self، \"_on_Button_pressed\")\n"
+"\n"
+" webxr_interface = ARVRServer.find_interface (\"WebXR\")\n"
+" إذا كان webxr_interface:\n"
+" # تعيين Ù…Ø¹Ø±Ù‘ÙØ§Øª الزر / المحور القياسي عندما يكون ذلك ممكنًا.\n"
+" webxr_interface.xr_standard_mapping = صحيح\n"
+"\n"
+" # يستخدم WebXR الكثير من عمليات الاسترجاعات غير المتزامنة ، لذلك "
+"نتصل بمختلÙ\n"
+" # إشارات لتلقيها.\n"
+" webxr_interface.connect (\"session_supported\"، self، "
+"\"_webxr_session_supported\")\n"
+" webxr_interface.connect (\"Session_started\" ، self ، "
+"\"_webxr_session_started\")\n"
+" webxr_interface.connect (\"session_ended\"، self، "
+"\"_webxr_session_ended\")\n"
+" webxr_interface.connect (\"session_failed\"، self، "
+"\"_webxr_session_failed\")\n"
+"\n"
+" # يعود هذا على الÙور - طريقة _webxr_session_supported ()\n"
+" # (التي ربطناها بإشارة \"session_supported\" أعلاه) سوÙ\n"
+" # يتم الاتصال بنا ÙÙŠ وقت لاحق لإعلامنا إذا كان مدعومًا أم لا.\n"
+" webxr_interface.is_session_supported (\"الواقع Ø§Ù„Ø§ÙØªØ±Ø§Ø¶ÙŠ Ø§Ù„ØºØ§Ù…Ø±\")\n"
+"\n"
+"func _webxr_session_supported (وضع الجلسة ، مدعوم):\n"
+" إذا كانت Session_mode == 'immersive-vr':\n"
+" vr_supported = مدعوم\n"
+"\n"
+"func _on_Button_pressed ():\n"
+" إذا لم يكن vr_supported:\n"
+" OS.alert (\"Ù…ØªØµÙØ­Ùƒ لا يدعم VR\")\n"
+" إرجاع\n"
+"\n"
+" # نريد جلسة VR غامرة ، على عكس AR ('غامرة-ar') أو a\n"
+" # عارض 3DoF بسيط (\"عارض\").\n"
+" webxr_interface.session_mode = \"الواقع Ø§Ù„Ø§ÙØªØ±Ø§Ø¶ÙŠ Ø§Ù„ØºØ§Ù…Ø±\"\n"
+" # \"الأرضية المحددة\" عبارة عن مقياس Ù„Ù„ØºØ±ÙØ© ØŒ أما \"الأرضية المحلية\" "
+"Ùهي عبارة عن مكان أو جلوس\n"
+" # تجربة (تضعك على Ø§Ø±ØªÙØ§Ø¹ 1.6 متر Ùوق سطح الأرض إذا كان لديك سماعة رأس "
+"3DoF) ،\n"
+" # ÙÙŠ حين أن \"محلي\" يضعك ÙÙŠ موقع ARVROrigin.\n"
+" # تعني هذه القائمة أنها ستحاول أولاً طلب \"أرضية محدودة\" ، بعد ذلك\n"
+" # الرجوع إلى \"local-floor\" ÙˆÙÙŠ النهاية \"المحلي\" ØŒ إذا لم يكن هناك "
+"شيء آخر\n"
+" # أيد.\n"
+" webxr_interface.requested_reference_space_types = 'bounded-floor، local-"
+"floor، local'\n"
+" # من أجل استخدام \"أرضية محلية\" أو \"أرضية محدودة\" يجب علينا أيضًا\n"
+" # ضع علامة على الميزات كما هو مطلوب أو اختياري.\n"
+" webxr_interface.required_features = \"local-floor\"\n"
+" webxr_interface.optional_features = \"bounded-floor\"\n"
+"\n"
+" # سيعود هذا خطأ إذا لم نتمكن حتى من طلب الجلسة ،\n"
+" # ومع ذلك ØŒ لا يزال من الممكن أن ØªÙØ´Ù„ بشكل غير متزامن ÙÙŠ وقت لاحق من "
+"العملية ، لذلك نحن\n"
+" # تعر٠Ùقط ما إذا كان قد نجح حقًا أو ÙØ´Ù„ عندما\n"
+" # _webxr_session_started () أو _webxr_session_failed () تسمى.\n"
+" إذا لم يكن webxr_interface.initialize ():\n"
+" OS.alert (\"ÙØ´Ù„ التهيئة\")\n"
+" إرجاع\n"
+"\n"
+"func _webxr_session_started ():\n"
+" $ Button.visible = false\n"
+" # هذا يخبر Godot أن يبدأ التقديم إلى سماعة الرأس.\n"
+" get_viewport (). arvr = صحيح\n"
+" # سيكون هذا هو نوع المساحة المرجعية التي حصلت عليها ÙÙŠ النهاية ØŒ من\n"
+" # أنواع طلبتها أعلاه. هذا Ù…Ùيد إذا كنت تريد اللعبة\n"
+" # العمل بشكل مختل٠قليلاً ÙÙŠ \"الأرضية المحدودة\" مقابل \"الأرضية "
+"المحلية\".\n"
+" طباعة (\"نوع المساحة المرجعية:\" + webxr_interface."
+"reference_space_type)\n"
+"\n"
+"func _webxr_session_ended ():\n"
+" $ Button.visible = صحيح\n"
+" # إذا خرج المستخدم من الوضع المجسم ØŒ ÙØ¥Ù†Ù†Ø§ نطلب من Godot عرضه على الويب\n"
+" # ØµÙØ­Ø© مرة أخرى.\n"
+" get_viewport (). arvr = خطأ\n"
+"\n"
+"func _webxr_session_failed (رسالة):\n"
+" OS.alert (\"ÙØ´Ù„ التهيئة:\" + رسالة)\n"
+"[/ codeblock]\n"
+"هناك عدة طرق للتعامل مع إدخال \"وحدة التحكم\":\n"
+"- استخدام عقد [ARVRController] وإشارات [إشارة ARVRController.button_pressed] "
+"و [إشارة ARVRController.button_release]. هذه هي الطريقة التي يتم بها التعامل "
+"مع وحدات التحكم عادةً ÙÙŠ تطبيقات AR / VR ÙÙŠ Godot ØŒ ومع ذلك ØŒ لن يعمل هذا إلا "
+"مع وحدات تحكم VR المتقدمة مثل Oculus Touch أو أجهزة التحكم ÙÙŠ الÙهرس ØŒ على "
+"سبيل المثال. يتم تحديد رموز الأزرار بواسطة [url = https: //immersive-web."
+"github.io/webxr-gamepads-module/#xr-standard-gamepad-mapping] القسم 3.3 من "
+"وحدة WebXR Gamepads Module [/ url].\n"
+"- استخدام [method Node._unhandled_input] و [InputEventJoypadButton] أو "
+"[InputEventJoypadMotion]. يعمل هذا Ø¨Ù†ÙØ³ طريقة عمل لوحات التحكم العادية ØŒ "
+"باستثناء أن [العضو InputEvent.device] يبدأ عند 100 ØŒ لذا ÙØ¥Ù† وحدة التحكم "
+"اليسرى هي 100 ÙˆÙ…ÙØªØ§Ø­ التحكم الأيمن."
#: modules/webxr/doc_classes/WebXRInterface.xml
msgid "How to make a VR game for WebXR with Godot"
diff --git a/doc/translations/ca.po b/doc/translations/ca.po
index ff63e7f808..1552c15271 100644
--- a/doc/translations/ca.po
+++ b/doc/translations/ca.po
@@ -588,7 +588,8 @@ msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
-"Returns an array of dictionaries representing the current call stack.\n"
+"Returns an array of dictionaries representing the current call stack. See "
+"also [method print_stack].\n"
"[codeblock]\n"
"func _ready():\n"
" foo()\n"
@@ -603,7 +604,11 @@ msgid ""
"[codeblock]\n"
"[{function:bar, line:12, source:res://script.gd}, {function:foo, line:9, "
"source:res://script.gd}, {function:_ready, line:6, source:res://script.gd}]\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] [method get_stack] only works if the running instance is "
+"connected to a debugging server (i.e. an editor instance). [method "
+"get_stack] will not work in projects exported in release mode, or in "
+"projects exported in debug mode if not connected to a debugging server."
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -976,12 +981,16 @@ msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
-"Prints a stack track at code location, only works when running with debugger "
-"turned on.\n"
+"Prints a stack trace at the current code location. See also [method "
+"get_stack].\n"
"Output in the console would look something like this:\n"
"[codeblock]\n"
"Frame 0 - res://test.gd:16 in function '_process'\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] [method print_stack] only works if the running instance is "
+"connected to a debugging server (i.e. an editor instance). [method "
+"print_stack] will not work in projects exported in release mode, or in "
+"projects exported in debug mode if not connected to a debugging server."
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -3592,6 +3601,26 @@ msgid "Hints that an image is compressed using lossless compression."
msgstr ""
#: doc/classes/@GlobalScope.xml
+msgid ""
+"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:\n"
+"[codeblock]\n"
+"hint_string = \"%s:\" % [TYPE_INT] # Array of inteters.\n"
+"hint_string = \"%s:%s:\" % [TYPE_ARRAY, TYPE_REAL] # Two-dimensional array "
+"of floats.\n"
+"hint_string = \"%s/%s:Resource\" % [TYPE_OBJECT, TYPE_OBJECT] # Array of "
+"resources.\n"
+"hint_string = \"%s:%s/%s:Resource\" % [TYPE_ARRAY, TYPE_OBJECT, TYPE_OBJECT] "
+"# Two-dimensional array of resources.\n"
+"[/codeblock]\n"
+"[b]Note:[/b] The final colon is required to specify for properly detecting "
+"built-in types."
+msgstr ""
+
+#: doc/classes/@GlobalScope.xml
msgid "The property is serialized and saved in the scene file (default)."
msgstr ""
@@ -4276,8 +4305,7 @@ msgstr ""
#: doc/classes/AudioStreamPlayer.xml doc/classes/Button.xml
#: doc/classes/CanvasLayer.xml doc/classes/CollisionShape2D.xml
#: doc/classes/ColorRect.xml doc/classes/Input.xml doc/classes/InputEvent.xml
-#: doc/classes/InputEventAction.xml doc/classes/Label.xml
-#: doc/classes/Particles2D.xml doc/classes/Timer.xml
+#: doc/classes/InputEventAction.xml doc/classes/Label.xml doc/classes/Timer.xml
#: doc/classes/VisibilityNotifier2D.xml
msgid "2D Dodge The Creeps Demo"
msgstr ""
@@ -7194,7 +7222,10 @@ msgid ""
"var array = []\n"
"array.resize(10)\n"
"array.fill(0) # Initialize the 10 elements to 0.\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] If [code]value[/code] is of a reference type ([Object]-derived, "
+"[Array], [Dictionary], etc.) then the array is filled with the references to "
+"the same object, i.e. no duplicates are created."
msgstr ""
#: doc/classes/Array.xml doc/classes/PoolByteArray.xml
@@ -7379,6 +7410,9 @@ msgstr ""
#: doc/classes/Array.xml
msgid ""
"Sorts the array.\n"
+"[b]Note:[/b] The sorting algorithm used is not [url=https://en.wikipedia.org/"
+"wiki/Sorting_algorithm#Stability]stable[/url]. This means that values "
+"considered equal may have their order changed when using [method sort].\n"
"[b]Note:[/b] Strings are sorted in alphabetical order (as opposed to natural "
"order). This may lead to unexpected behavior when sorting an array of "
"strings ending with a sequence of numbers. Consider the following example:\n"
@@ -7398,9 +7432,13 @@ msgid ""
"For two elements [code]a[/code] and [code]b[/code], if the given method "
"returns [code]true[/code], element [code]b[/code] will be after element "
"[code]a[/code] in the array.\n"
+"[b]Note:[/b] The sorting algorithm used is not [url=https://en.wikipedia.org/"
+"wiki/Sorting_algorithm#Stability]stable[/url]. This means that values "
+"considered equal may have their order changed when using [method "
+"sort_custom].\n"
"[b]Note:[/b] You cannot randomize the return value as the heapsort algorithm "
-"expects a deterministic result. Doing so will result in unexpected "
-"behavior.\n"
+"expects a deterministic result. Randomizing the return value will result in "
+"unexpected behavior.\n"
"[codeblock]\n"
"class MyCustomSorter:\n"
" static func sort_ascending(a, b):\n"
@@ -10038,10 +10076,9 @@ msgstr ""
#: doc/classes/AudioStreamGeneratorPlayback.xml
msgid ""
-"Returns the number of audio data frames left to play. If this returned "
-"number reaches [code]0[/code], the audio will stop playing until frames are "
-"added again. Therefore, make sure your script can always generate and push "
-"new audio frames fast enough to avoid audio cracking."
+"Returns the number of frames that can be pushed to the audio sample data "
+"buffer without overflowing it. If the result is [code]0[/code], the buffer "
+"is full."
msgstr ""
#: doc/classes/AudioStreamGeneratorPlayback.xml
@@ -10573,14 +10610,14 @@ msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
"Node for back-buffering the currently-displayed screen. The region defined "
-"in the BackBufferCopy node is buffered with the content of the screen it "
+"in the [BackBufferCopy] node is buffered with the content of the screen it "
"covers, or the entire screen according to the copy mode set. Use the "
"[code]texture(SCREEN_TEXTURE, ...)[/code] function in your shader scripts to "
"access the buffer.\n"
"[b]Note:[/b] Since this node inherits from [Node2D] (and not [Control]), "
"anchors and margins won't apply to child [Control]-derived nodes. This can "
"be problematic when resizing the window. To avoid this, add [Control]-"
-"derived nodes as [i]siblings[/i] to the BackBufferCopy node instead of "
+"derived nodes as [i]siblings[/i] to the [BackBufferCopy] node instead of "
"adding them as children."
msgstr ""
@@ -10590,22 +10627,22 @@ msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
-"The area covered by the BackBufferCopy. Only used if [member copy_mode] is "
+"The area covered by the [BackBufferCopy]. Only used if [member copy_mode] is "
"[constant COPY_MODE_RECT]."
msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
-"Disables the buffering mode. This means the BackBufferCopy node will "
+"Disables the buffering mode. This means the [BackBufferCopy] node will "
"directly use the portion of screen it covers."
msgstr ""
#: doc/classes/BackBufferCopy.xml
-msgid "BackBufferCopy buffers a rectangular region."
+msgid "[BackBufferCopy] buffers a rectangular region."
msgstr ""
#: doc/classes/BackBufferCopy.xml
-msgid "BackBufferCopy buffers the entire screen."
+msgid "[BackBufferCopy] buffers the entire screen."
msgstr ""
#: doc/classes/BakedLightmap.xml
@@ -19385,6 +19422,14 @@ msgid "Cylinder shape for collisions."
msgstr ""
#: doc/classes/CylinderShape.xml
+msgid ""
+"Cylinder shape for collisions.\n"
+"[b]Note:[/b] When using GodotPhysics instead of the default Bullet physics "
+"engine, there are several known bugs with cylinder collision shapes. Using "
+"[CapsuleShape] or [BoxShape] instead is recommended."
+msgstr ""
+
+#: doc/classes/CylinderShape.xml
msgid "The cylinder's height."
msgstr ""
@@ -22217,7 +22262,10 @@ msgid ""
"[/codeblock]\n"
"[b]Note:[/b] The script is run in the Editor context, which means the output "
"is visible in the console window started with the Editor (stdout) instead of "
-"the usual Godot [b]Output[/b] dock."
+"the usual Godot [b]Output[/b] dock.\n"
+"[b]Note:[/b] EditorScript is reference counted, meaning it is destroyed when "
+"nothing references it. This can cause errors during asynchronous operations "
+"if there are no references to the script."
msgstr ""
#: doc/classes/EditorScript.xml
@@ -32932,7 +32980,9 @@ msgid ""
"The size of the light in Godot units. Only considered in baked lightmaps and "
"only if [member light_bake_mode] is set to [constant BAKE_ALL]. Increasing "
"this value will make the shadows appear blurrier. This can be used to "
-"simulate area lights to an extent."
+"simulate area lights to an extent.\n"
+"[b]Note:[/b] [member light_size] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/Light.xml
@@ -36230,7 +36280,10 @@ msgid ""
"use the [method get_next_location] function once every physics frame to "
"update the internal path logic of the NavigationAgent. The returned vector "
"position from this function should be used as the next movement position for "
-"the agent's parent Node."
+"the agent's parent Node.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues."
msgstr ""
#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
@@ -36478,7 +36531,10 @@ msgid ""
"use the [method get_next_location] function once every physics frame to "
"update the internal path logic of the NavigationAgent. The returned vector "
"position from this function should be used as the next movement position for "
-"the agent's parent Node."
+"the agent's parent Node.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues."
msgstr ""
#: doc/classes/NavigationAgent2D.xml
@@ -37188,6 +37244,9 @@ msgid ""
"modified velocity as-is might lead to pushing and agent outside of a "
"navigable area. This is a limitation of the collision avoidance system, any "
"more complex situation may require the use of the physics engine.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues.\n"
"This server keeps tracks of any call and executes them during the sync "
"phase. This means that you can request any change to the map, using any "
"thread, without worrying."
@@ -39994,7 +40053,9 @@ msgid ""
"The light's radius. Note that the effectively lit area may appear to be "
"smaller depending on the [member omni_attenuation] in use. No matter the "
"[member omni_attenuation] in use, the light will never reach anything "
-"outside this radius."
+"outside this radius.\n"
+"[b]Note:[/b] [member omni_range] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -40505,11 +40566,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] cache data directory according to the operating "
-"system's standards. On desktop platforms, this path can be overridden by "
-"setting the [code]XDG_CACHE_HOME[/code] environment variable before starting "
-"the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in "
-"Godot projects[/url] in the documentation for more information. See also "
-"[method get_config_dir] and [method get_data_dir].\n"
+"system's standards. On Linux, this path can be overridden by setting the "
+"[code]XDG_CACHE_HOME[/code] environment variable before starting the "
+"project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot "
+"projects[/url] in the documentation for more information. See also [method "
+"get_config_dir] and [method get_data_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -40543,11 +40604,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] user configuration directory according to the "
-"operating system's standards. On desktop platforms, this path can be "
-"overridden by setting the [code]XDG_CONFIG_HOME[/code] environment variable "
-"before starting the project. See [url=$DOCS_URL/tutorials/io/data_paths."
-"html]File paths in Godot projects[/url] in the documentation for more "
-"information. See also [method get_cache_dir] and [method get_data_dir].\n"
+"operating system's standards. On Linux, this path can be overridden by "
+"setting the [code]XDG_CONFIG_HOME[/code] environment variable before "
+"starting the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File "
+"paths in Godot projects[/url] in the documentation for more information. See "
+"also [method get_cache_dir] and [method get_data_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -40569,11 +40630,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] user data directory according to the operating "
-"system's standards. On desktop platforms, this path can be overridden by "
-"setting the [code]XDG_DATA_HOME[/code] environment variable before starting "
-"the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in "
-"Godot projects[/url] in the documentation for more information. See also "
-"[method get_cache_dir] and [method get_config_dir].\n"
+"system's standards. On Linux, this path can be overridden by setting the "
+"[code]XDG_DATA_HOME[/code] environment variable before starting the project. "
+"See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot "
+"projects[/url] in the documentation for more information. See also [method "
+"get_cache_dir] and [method get_config_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -42420,6 +42481,16 @@ msgid "Particle systems (2D)"
msgstr ""
#: doc/classes/Particles2D.xml
+msgid "2D Particles Demo"
+msgstr ""
+
+#: doc/classes/Particles2D.xml
+msgid ""
+"2D Dodge The Creeps Demo (uses GPUParticles2D for the trail behind the "
+"player)"
+msgstr ""
+
+#: doc/classes/Particles2D.xml
msgid "Returns a rectangle containing the positions of all existing particles."
msgstr ""
@@ -50012,15 +50083,22 @@ msgstr ""
#: doc/classes/ProjectSettings.xml
msgid ""
"If [code]true[/code], uses a fast post-processing filter to make banding "
-"significantly less visible. In some cases, debanding may introduce a "
-"slightly noticeable dithering pattern. It's recommended to enable debanding "
-"only when actually needed since the dithering pattern will make lossless-"
-"compressed screenshots larger.\n"
+"significantly less visible in 3D. 2D rendering is [i]not[/i] affected by "
+"debanding unless the [member Environment.background_mode] is [constant "
+"Environment.BG_CANVAS]. In this case, [member rendering/quality/"
+"intended_usage/framebuffer_allocation] must also be set to [b]3D[/b].\n"
+"In some cases, debanding may introduce a slightly noticeable dithering "
+"pattern. It's recommended to enable debanding only when actually needed "
+"since the dithering pattern will make lossless-compressed screenshots "
+"larger.\n"
"[b]Note:[/b] Only available on the GLES3 backend. [member rendering/quality/"
"depth/hdr] must also be [code]true[/code] for debanding to be effective.\n"
"[b]Note:[/b] There are known issues with debanding breaking rendering on "
"mobile platforms. Due to this, it is recommended to leave this option "
-"disabled when targeting mobile platforms."
+"disabled when targeting mobile platforms.\n"
+"[b]Note:[/b] This property is only read when the project starts. To set "
+"debanding at run-time, set [member Viewport.debanding] on the root "
+"[Viewport] instead."
msgstr ""
#: doc/classes/ProjectSettings.xml
@@ -51616,17 +51694,28 @@ msgstr ""
#: modules/regex/doc_classes/RegEx.xml
msgid ""
"Searches the text for the compiled pattern. Returns a [RegExMatch] container "
-"of the first matching result if found, otherwise [code]null[/code]. The "
-"region to search within can be specified without modifying where the start "
-"and end anchor would be."
+"of the first matching result if found, otherwise [code]null[/code].\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegEx.xml
msgid ""
"Searches the text for the compiled pattern. Returns an array of [RegExMatch] "
"containers for each non-overlapping result. If no results were found, an "
-"empty array is returned instead. The region to search within can be "
-"specified without modifying where the start and end anchor would be."
+"empty array is returned instead.\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegEx.xml
@@ -51635,8 +51724,14 @@ msgid ""
"specified string. Escapes and backreferences such as [code]$1[/code] and "
"[code]$name[/code] are expanded and resolved. By default, only the first "
"instance is replaced, but it can be changed for all instances (global "
-"replacement). The region to search within can be specified without modifying "
-"where the start and end anchor would be."
+"replacement).\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegExMatch.xml
@@ -54351,7 +54446,11 @@ msgid "Call a group immediately (calls are normally made on idle)."
msgstr ""
#: doc/classes/SceneTree.xml
-msgid "Call a group only once even if the call is executed many times."
+msgid ""
+"Call a group only once even if the call is executed many times.\n"
+"[b]Note:[/b] Arguments are not taken into account when deciding whether the "
+"call is unique or not. Therefore when the same method is called with "
+"different arguments, only the first call will be performed."
msgstr ""
#: doc/classes/SceneTree.xml
@@ -56188,7 +56287,9 @@ msgid ""
"[b]Note:[/b] Mixed negative scales in 3D are not decomposable from the "
"transformation matrix. Due to the way scale is represented with "
"transformation matrices in Godot, the scale values will either be all "
-"positive or all negative."
+"positive or all negative.\n"
+"[b]Note:[/b] Not all nodes are visually scaled by the [member scale] "
+"property. For example, [Light]s are not visually affected by [member scale]."
msgstr ""
#: doc/classes/Spatial.xml
@@ -57566,7 +57667,10 @@ msgid ""
msgstr ""
#: doc/classes/SpotLight.xml
-msgid "The spotlight's angle in degrees."
+msgid ""
+"The spotlight's angle in degrees.\n"
+"[b]Note:[/b] [member spot_angle] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/SpotLight.xml
@@ -57582,7 +57686,9 @@ msgid ""
"The maximal range that can be reached by the spotlight. Note that the "
"effectively lit area may appear to be smaller depending on the [member "
"spot_attenuation] in use. No matter the [member spot_attenuation] in use, "
-"the light will never reach anything outside this range."
+"the light will never reach anything outside this range.\n"
+"[b]Note:[/b] [member spot_range] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/SpringArm.xml
@@ -66819,10 +66925,15 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
"If [code]true[/code], uses a fast post-processing filter to make banding "
-"significantly less visible. In some cases, debanding may introduce a "
-"slightly noticeable dithering pattern. It's recommended to enable debanding "
-"only when actually needed since the dithering pattern will make lossless-"
-"compressed screenshots larger.\n"
+"significantly less visible in 3D. 2D rendering is [i]not[/i] affected by "
+"debanding unless the [member Environment.background_mode] is [constant "
+"Environment.BG_CANVAS]. In this case, [member usage] must also be set to "
+"[constant USAGE_3D]. See also [member ProjectSettings.rendering/quality/"
+"filters/use_debanding].\n"
+"In some cases, debanding may introduce a slightly noticeable dithering "
+"pattern. It's recommended to enable debanding only when actually needed "
+"since the dithering pattern will make lossless-compressed screenshots "
+"larger.\n"
"[b]Note:[/b] Only available on the GLES3 backend. [member hdr] must also be "
"[code]true[/code] for debanding to be effective."
msgstr ""
@@ -66833,8 +66944,8 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
-"If [code]true[/code], the viewport will disable 3D rendering. For actual "
-"disabling use [code]usage[/code]."
+"If [code]true[/code], the viewport will disable 3D rendering. To actually "
+"disable allocation of 3D buffers, set [member usage] instead."
msgstr ""
#: doc/classes/Viewport.xml
@@ -66986,7 +67097,9 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
-"The rendering mode of viewport.\n"
+"The viewport's rendering mode. This controls which buffers are allocated for "
+"the viewport (2D only, or 2D + 3D). 2D-only options can reduce memory usage "
+"and improve performance slightly, especially on low-end devices.\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."
@@ -67518,6 +67631,22 @@ msgid ""
"render object this [VisualInstance] is set to."
msgstr ""
+#: doc/classes/VisualInstance.xml
+msgid ""
+"The sorting offset used by this [VisualInstance]. Adjusting it to a higher "
+"value will make the [VisualInstance] reliably draw on top of other "
+"[VisualInstance]s that are otherwise positioned at the same spot."
+msgstr ""
+
+#: doc/classes/VisualInstance.xml
+msgid ""
+"If [code]true[/code], the object is sorted based on the [AABB] center. "
+"Sorted based on the global position otherwise.\n"
+"The [AABB] center based sorting is generally more accurate for 3D models. "
+"The position based sorting instead allows to better control the drawing "
+"order when working with [Particles] and [CPUParticles]."
+msgstr ""
+
#: modules/visual_script/doc_classes/VisualScript.xml
msgid "A script implemented in the Visual Script programming environment."
msgstr ""
diff --git a/doc/translations/classes.pot b/doc/translations/classes.pot
index 6ee35f0a74..40ab5e3413 100644
--- a/doc/translations/classes.pot
+++ b/doc/translations/classes.pot
@@ -468,7 +468,8 @@ msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
-"Returns an array of dictionaries representing the current call stack.\n"
+"Returns an array of dictionaries representing the current call stack. See "
+"also [method print_stack].\n"
"[codeblock]\n"
"func _ready():\n"
" foo()\n"
@@ -483,7 +484,11 @@ msgid ""
"[codeblock]\n"
"[{function:bar, line:12, source:res://script.gd}, {function:foo, line:9, "
"source:res://script.gd}, {function:_ready, line:6, source:res://script.gd}]\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] [method get_stack] only works if the running instance is "
+"connected to a debugging server (i.e. an editor instance). [method "
+"get_stack] will not work in projects exported in release mode, or in "
+"projects exported in debug mode if not connected to a debugging server."
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -856,12 +861,16 @@ msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
-"Prints a stack track at code location, only works when running with debugger "
-"turned on.\n"
+"Prints a stack trace at the current code location. See also [method "
+"get_stack].\n"
"Output in the console would look something like this:\n"
"[codeblock]\n"
"Frame 0 - res://test.gd:16 in function '_process'\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] [method print_stack] only works if the running instance is "
+"connected to a debugging server (i.e. an editor instance). [method "
+"print_stack] will not work in projects exported in release mode, or in "
+"projects exported in debug mode if not connected to a debugging server."
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -3472,6 +3481,26 @@ msgid "Hints that an image is compressed using lossless compression."
msgstr ""
#: doc/classes/@GlobalScope.xml
+msgid ""
+"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:\n"
+"[codeblock]\n"
+"hint_string = \"%s:\" % [TYPE_INT] # Array of inteters.\n"
+"hint_string = \"%s:%s:\" % [TYPE_ARRAY, TYPE_REAL] # Two-dimensional array "
+"of floats.\n"
+"hint_string = \"%s/%s:Resource\" % [TYPE_OBJECT, TYPE_OBJECT] # Array of "
+"resources.\n"
+"hint_string = \"%s:%s/%s:Resource\" % [TYPE_ARRAY, TYPE_OBJECT, TYPE_OBJECT] "
+"# Two-dimensional array of resources.\n"
+"[/codeblock]\n"
+"[b]Note:[/b] The final colon is required to specify for properly detecting "
+"built-in types."
+msgstr ""
+
+#: doc/classes/@GlobalScope.xml
msgid "The property is serialized and saved in the scene file (default)."
msgstr ""
@@ -4156,8 +4185,7 @@ msgstr ""
#: doc/classes/AudioStreamPlayer.xml doc/classes/Button.xml
#: doc/classes/CanvasLayer.xml doc/classes/CollisionShape2D.xml
#: doc/classes/ColorRect.xml doc/classes/Input.xml doc/classes/InputEvent.xml
-#: doc/classes/InputEventAction.xml doc/classes/Label.xml
-#: doc/classes/Particles2D.xml doc/classes/Timer.xml
+#: doc/classes/InputEventAction.xml doc/classes/Label.xml doc/classes/Timer.xml
#: doc/classes/VisibilityNotifier2D.xml
msgid "2D Dodge The Creeps Demo"
msgstr ""
@@ -7074,7 +7102,10 @@ msgid ""
"var array = []\n"
"array.resize(10)\n"
"array.fill(0) # Initialize the 10 elements to 0.\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] If [code]value[/code] is of a reference type ([Object]-derived, "
+"[Array], [Dictionary], etc.) then the array is filled with the references to "
+"the same object, i.e. no duplicates are created."
msgstr ""
#: doc/classes/Array.xml doc/classes/PoolByteArray.xml
@@ -7259,6 +7290,9 @@ msgstr ""
#: doc/classes/Array.xml
msgid ""
"Sorts the array.\n"
+"[b]Note:[/b] The sorting algorithm used is not [url=https://en.wikipedia.org/"
+"wiki/Sorting_algorithm#Stability]stable[/url]. This means that values "
+"considered equal may have their order changed when using [method sort].\n"
"[b]Note:[/b] Strings are sorted in alphabetical order (as opposed to natural "
"order). This may lead to unexpected behavior when sorting an array of "
"strings ending with a sequence of numbers. Consider the following example:\n"
@@ -7278,9 +7312,13 @@ msgid ""
"For two elements [code]a[/code] and [code]b[/code], if the given method "
"returns [code]true[/code], element [code]b[/code] will be after element "
"[code]a[/code] in the array.\n"
+"[b]Note:[/b] The sorting algorithm used is not [url=https://en.wikipedia.org/"
+"wiki/Sorting_algorithm#Stability]stable[/url]. This means that values "
+"considered equal may have their order changed when using [method "
+"sort_custom].\n"
"[b]Note:[/b] You cannot randomize the return value as the heapsort algorithm "
-"expects a deterministic result. Doing so will result in unexpected "
-"behavior.\n"
+"expects a deterministic result. Randomizing the return value will result in "
+"unexpected behavior.\n"
"[codeblock]\n"
"class MyCustomSorter:\n"
" static func sort_ascending(a, b):\n"
@@ -9918,10 +9956,9 @@ msgstr ""
#: doc/classes/AudioStreamGeneratorPlayback.xml
msgid ""
-"Returns the number of audio data frames left to play. If this returned "
-"number reaches [code]0[/code], the audio will stop playing until frames are "
-"added again. Therefore, make sure your script can always generate and push "
-"new audio frames fast enough to avoid audio cracking."
+"Returns the number of frames that can be pushed to the audio sample data "
+"buffer without overflowing it. If the result is [code]0[/code], the buffer "
+"is full."
msgstr ""
#: doc/classes/AudioStreamGeneratorPlayback.xml
@@ -10453,14 +10490,14 @@ msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
"Node for back-buffering the currently-displayed screen. The region defined "
-"in the BackBufferCopy node is buffered with the content of the screen it "
+"in the [BackBufferCopy] node is buffered with the content of the screen it "
"covers, or the entire screen according to the copy mode set. Use the "
"[code]texture(SCREEN_TEXTURE, ...)[/code] function in your shader scripts to "
"access the buffer.\n"
"[b]Note:[/b] Since this node inherits from [Node2D] (and not [Control]), "
"anchors and margins won't apply to child [Control]-derived nodes. This can "
"be problematic when resizing the window. To avoid this, add [Control]-"
-"derived nodes as [i]siblings[/i] to the BackBufferCopy node instead of "
+"derived nodes as [i]siblings[/i] to the [BackBufferCopy] node instead of "
"adding them as children."
msgstr ""
@@ -10470,22 +10507,22 @@ msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
-"The area covered by the BackBufferCopy. Only used if [member copy_mode] is "
+"The area covered by the [BackBufferCopy]. Only used if [member copy_mode] is "
"[constant COPY_MODE_RECT]."
msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
-"Disables the buffering mode. This means the BackBufferCopy node will "
+"Disables the buffering mode. This means the [BackBufferCopy] node will "
"directly use the portion of screen it covers."
msgstr ""
#: doc/classes/BackBufferCopy.xml
-msgid "BackBufferCopy buffers a rectangular region."
+msgid "[BackBufferCopy] buffers a rectangular region."
msgstr ""
#: doc/classes/BackBufferCopy.xml
-msgid "BackBufferCopy buffers the entire screen."
+msgid "[BackBufferCopy] buffers the entire screen."
msgstr ""
#: doc/classes/BakedLightmap.xml
@@ -19265,6 +19302,14 @@ msgid "Cylinder shape for collisions."
msgstr ""
#: doc/classes/CylinderShape.xml
+msgid ""
+"Cylinder shape for collisions.\n"
+"[b]Note:[/b] When using GodotPhysics instead of the default Bullet physics "
+"engine, there are several known bugs with cylinder collision shapes. Using "
+"[CapsuleShape] or [BoxShape] instead is recommended."
+msgstr ""
+
+#: doc/classes/CylinderShape.xml
msgid "The cylinder's height."
msgstr ""
@@ -22097,7 +22142,10 @@ msgid ""
"[/codeblock]\n"
"[b]Note:[/b] The script is run in the Editor context, which means the output "
"is visible in the console window started with the Editor (stdout) instead of "
-"the usual Godot [b]Output[/b] dock."
+"the usual Godot [b]Output[/b] dock.\n"
+"[b]Note:[/b] EditorScript is reference counted, meaning it is destroyed when "
+"nothing references it. This can cause errors during asynchronous operations "
+"if there are no references to the script."
msgstr ""
#: doc/classes/EditorScript.xml
@@ -32809,7 +32857,9 @@ msgid ""
"The size of the light in Godot units. Only considered in baked lightmaps and "
"only if [member light_bake_mode] is set to [constant BAKE_ALL]. Increasing "
"this value will make the shadows appear blurrier. This can be used to "
-"simulate area lights to an extent."
+"simulate area lights to an extent.\n"
+"[b]Note:[/b] [member light_size] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/Light.xml
@@ -36107,7 +36157,10 @@ msgid ""
"use the [method get_next_location] function once every physics frame to "
"update the internal path logic of the NavigationAgent. The returned vector "
"position from this function should be used as the next movement position for "
-"the agent's parent Node."
+"the agent's parent Node.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues."
msgstr ""
#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
@@ -36355,7 +36408,10 @@ msgid ""
"use the [method get_next_location] function once every physics frame to "
"update the internal path logic of the NavigationAgent. The returned vector "
"position from this function should be used as the next movement position for "
-"the agent's parent Node."
+"the agent's parent Node.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues."
msgstr ""
#: doc/classes/NavigationAgent2D.xml
@@ -37065,6 +37121,9 @@ msgid ""
"modified velocity as-is might lead to pushing and agent outside of a "
"navigable area. This is a limitation of the collision avoidance system, any "
"more complex situation may require the use of the physics engine.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues.\n"
"This server keeps tracks of any call and executes them during the sync "
"phase. This means that you can request any change to the map, using any "
"thread, without worrying."
@@ -39871,7 +39930,9 @@ msgid ""
"The light's radius. Note that the effectively lit area may appear to be "
"smaller depending on the [member omni_attenuation] in use. No matter the "
"[member omni_attenuation] in use, the light will never reach anything "
-"outside this radius."
+"outside this radius.\n"
+"[b]Note:[/b] [member omni_range] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -40382,11 +40443,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] cache data directory according to the operating "
-"system's standards. On desktop platforms, this path can be overridden by "
-"setting the [code]XDG_CACHE_HOME[/code] environment variable before starting "
-"the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in "
-"Godot projects[/url] in the documentation for more information. See also "
-"[method get_config_dir] and [method get_data_dir].\n"
+"system's standards. On Linux, this path can be overridden by setting the "
+"[code]XDG_CACHE_HOME[/code] environment variable before starting the "
+"project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot "
+"projects[/url] in the documentation for more information. See also [method "
+"get_config_dir] and [method get_data_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -40420,11 +40481,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] user configuration directory according to the "
-"operating system's standards. On desktop platforms, this path can be "
-"overridden by setting the [code]XDG_CONFIG_HOME[/code] environment variable "
-"before starting the project. See [url=$DOCS_URL/tutorials/io/data_paths."
-"html]File paths in Godot projects[/url] in the documentation for more "
-"information. See also [method get_cache_dir] and [method get_data_dir].\n"
+"operating system's standards. On Linux, this path can be overridden by "
+"setting the [code]XDG_CONFIG_HOME[/code] environment variable before "
+"starting the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File "
+"paths in Godot projects[/url] in the documentation for more information. See "
+"also [method get_cache_dir] and [method get_data_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -40446,11 +40507,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] user data directory according to the operating "
-"system's standards. On desktop platforms, this path can be overridden by "
-"setting the [code]XDG_DATA_HOME[/code] environment variable before starting "
-"the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in "
-"Godot projects[/url] in the documentation for more information. See also "
-"[method get_cache_dir] and [method get_config_dir].\n"
+"system's standards. On Linux, this path can be overridden by setting the "
+"[code]XDG_DATA_HOME[/code] environment variable before starting the project. "
+"See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot "
+"projects[/url] in the documentation for more information. See also [method "
+"get_cache_dir] and [method get_config_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -42297,6 +42358,16 @@ msgid "Particle systems (2D)"
msgstr ""
#: doc/classes/Particles2D.xml
+msgid "2D Particles Demo"
+msgstr ""
+
+#: doc/classes/Particles2D.xml
+msgid ""
+"2D Dodge The Creeps Demo (uses GPUParticles2D for the trail behind the "
+"player)"
+msgstr ""
+
+#: doc/classes/Particles2D.xml
msgid "Returns a rectangle containing the positions of all existing particles."
msgstr ""
@@ -49889,15 +49960,22 @@ msgstr ""
#: doc/classes/ProjectSettings.xml
msgid ""
"If [code]true[/code], uses a fast post-processing filter to make banding "
-"significantly less visible. In some cases, debanding may introduce a "
-"slightly noticeable dithering pattern. It's recommended to enable debanding "
-"only when actually needed since the dithering pattern will make lossless-"
-"compressed screenshots larger.\n"
+"significantly less visible in 3D. 2D rendering is [i]not[/i] affected by "
+"debanding unless the [member Environment.background_mode] is [constant "
+"Environment.BG_CANVAS]. In this case, [member rendering/quality/"
+"intended_usage/framebuffer_allocation] must also be set to [b]3D[/b].\n"
+"In some cases, debanding may introduce a slightly noticeable dithering "
+"pattern. It's recommended to enable debanding only when actually needed "
+"since the dithering pattern will make lossless-compressed screenshots "
+"larger.\n"
"[b]Note:[/b] Only available on the GLES3 backend. [member rendering/quality/"
"depth/hdr] must also be [code]true[/code] for debanding to be effective.\n"
"[b]Note:[/b] There are known issues with debanding breaking rendering on "
"mobile platforms. Due to this, it is recommended to leave this option "
-"disabled when targeting mobile platforms."
+"disabled when targeting mobile platforms.\n"
+"[b]Note:[/b] This property is only read when the project starts. To set "
+"debanding at run-time, set [member Viewport.debanding] on the root "
+"[Viewport] instead."
msgstr ""
#: doc/classes/ProjectSettings.xml
@@ -51493,17 +51571,28 @@ msgstr ""
#: modules/regex/doc_classes/RegEx.xml
msgid ""
"Searches the text for the compiled pattern. Returns a [RegExMatch] container "
-"of the first matching result if found, otherwise [code]null[/code]. The "
-"region to search within can be specified without modifying where the start "
-"and end anchor would be."
+"of the first matching result if found, otherwise [code]null[/code].\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegEx.xml
msgid ""
"Searches the text for the compiled pattern. Returns an array of [RegExMatch] "
"containers for each non-overlapping result. If no results were found, an "
-"empty array is returned instead. The region to search within can be "
-"specified without modifying where the start and end anchor would be."
+"empty array is returned instead.\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegEx.xml
@@ -51512,8 +51601,14 @@ msgid ""
"specified string. Escapes and backreferences such as [code]$1[/code] and "
"[code]$name[/code] are expanded and resolved. By default, only the first "
"instance is replaced, but it can be changed for all instances (global "
-"replacement). The region to search within can be specified without modifying "
-"where the start and end anchor would be."
+"replacement).\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegExMatch.xml
@@ -54228,7 +54323,11 @@ msgid "Call a group immediately (calls are normally made on idle)."
msgstr ""
#: doc/classes/SceneTree.xml
-msgid "Call a group only once even if the call is executed many times."
+msgid ""
+"Call a group only once even if the call is executed many times.\n"
+"[b]Note:[/b] Arguments are not taken into account when deciding whether the "
+"call is unique or not. Therefore when the same method is called with "
+"different arguments, only the first call will be performed."
msgstr ""
#: doc/classes/SceneTree.xml
@@ -56065,7 +56164,9 @@ msgid ""
"[b]Note:[/b] Mixed negative scales in 3D are not decomposable from the "
"transformation matrix. Due to the way scale is represented with "
"transformation matrices in Godot, the scale values will either be all "
-"positive or all negative."
+"positive or all negative.\n"
+"[b]Note:[/b] Not all nodes are visually scaled by the [member scale] "
+"property. For example, [Light]s are not visually affected by [member scale]."
msgstr ""
#: doc/classes/Spatial.xml
@@ -57443,7 +57544,10 @@ msgid ""
msgstr ""
#: doc/classes/SpotLight.xml
-msgid "The spotlight's angle in degrees."
+msgid ""
+"The spotlight's angle in degrees.\n"
+"[b]Note:[/b] [member spot_angle] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/SpotLight.xml
@@ -57459,7 +57563,9 @@ msgid ""
"The maximal range that can be reached by the spotlight. Note that the "
"effectively lit area may appear to be smaller depending on the [member "
"spot_attenuation] in use. No matter the [member spot_attenuation] in use, "
-"the light will never reach anything outside this range."
+"the light will never reach anything outside this range.\n"
+"[b]Note:[/b] [member spot_range] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/SpringArm.xml
@@ -66696,10 +66802,15 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
"If [code]true[/code], uses a fast post-processing filter to make banding "
-"significantly less visible. In some cases, debanding may introduce a "
-"slightly noticeable dithering pattern. It's recommended to enable debanding "
-"only when actually needed since the dithering pattern will make lossless-"
-"compressed screenshots larger.\n"
+"significantly less visible in 3D. 2D rendering is [i]not[/i] affected by "
+"debanding unless the [member Environment.background_mode] is [constant "
+"Environment.BG_CANVAS]. In this case, [member usage] must also be set to "
+"[constant USAGE_3D]. See also [member ProjectSettings.rendering/quality/"
+"filters/use_debanding].\n"
+"In some cases, debanding may introduce a slightly noticeable dithering "
+"pattern. It's recommended to enable debanding only when actually needed "
+"since the dithering pattern will make lossless-compressed screenshots "
+"larger.\n"
"[b]Note:[/b] Only available on the GLES3 backend. [member hdr] must also be "
"[code]true[/code] for debanding to be effective."
msgstr ""
@@ -66710,8 +66821,8 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
-"If [code]true[/code], the viewport will disable 3D rendering. For actual "
-"disabling use [code]usage[/code]."
+"If [code]true[/code], the viewport will disable 3D rendering. To actually "
+"disable allocation of 3D buffers, set [member usage] instead."
msgstr ""
#: doc/classes/Viewport.xml
@@ -66863,7 +66974,9 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
-"The rendering mode of viewport.\n"
+"The viewport's rendering mode. This controls which buffers are allocated for "
+"the viewport (2D only, or 2D + 3D). 2D-only options can reduce memory usage "
+"and improve performance slightly, especially on low-end devices.\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."
@@ -67395,6 +67508,22 @@ msgid ""
"render object this [VisualInstance] is set to."
msgstr ""
+#: doc/classes/VisualInstance.xml
+msgid ""
+"The sorting offset used by this [VisualInstance]. Adjusting it to a higher "
+"value will make the [VisualInstance] reliably draw on top of other "
+"[VisualInstance]s that are otherwise positioned at the same spot."
+msgstr ""
+
+#: doc/classes/VisualInstance.xml
+msgid ""
+"If [code]true[/code], the object is sorted based on the [AABB] center. "
+"Sorted based on the global position otherwise.\n"
+"The [AABB] center based sorting is generally more accurate for 3D models. "
+"The position based sorting instead allows to better control the drawing "
+"order when working with [Particles] and [CPUParticles]."
+msgstr ""
+
#: modules/visual_script/doc_classes/VisualScript.xml
msgid "A script implemented in the Visual Script programming environment."
msgstr ""
diff --git a/doc/translations/cs.po b/doc/translations/cs.po
index 92e3272798..1bd920e19b 100644
--- a/doc/translations/cs.po
+++ b/doc/translations/cs.po
@@ -15,12 +15,13 @@
# Tomas Dostal <tomas.dostal.cz@gmail.com>, 2021.
# JoeMoos <josephmoose13@gmail.com>, 2022.
# Mirinek <mirek.nozicka77@gmail.com>, 2022.
+# Dominik Strnad <domi.str@seznam.cz>, 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-08-28 00:17+0000\n"
-"Last-Translator: Mirinek <mirek.nozicka77@gmail.com>\n"
+"PO-Revision-Date: 2022-11-13 03:28+0000\n"
+"Last-Translator: Dominik Strnad <domi.str@seznam.cz>\n"
"Language-Team: Czech <https://hosted.weblate.org/projects/godot-engine/godot-"
"class-reference/cs/>\n"
"Language: cs\n"
@@ -28,7 +29,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8-bit\n"
"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
-"X-Generator: Weblate 4.14.1-dev\n"
+"X-Generator: Weblate 4.15-dev\n"
#: doc/tools/make_rst.py
msgid "Description"
@@ -682,8 +683,10 @@ msgstr ""
"[/codeblock]"
#: modules/gdscript/doc_classes/@GDScript.xml
+#, fuzzy
msgid ""
-"Returns an array of dictionaries representing the current call stack.\n"
+"Returns an array of dictionaries representing the current call stack. See "
+"also [method print_stack].\n"
"[codeblock]\n"
"func _ready():\n"
" foo()\n"
@@ -698,7 +701,11 @@ msgid ""
"[codeblock]\n"
"[{function:bar, line:12, source:res://script.gd}, {function:foo, line:9, "
"source:res://script.gd}, {function:_ready, line:6, source:res://script.gd}]\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] [method get_stack] only works if the running instance is "
+"connected to a debugging server (i.e. an editor instance). [method "
+"get_stack] will not work in projects exported in release mode, or in "
+"projects exported in debug mode if not connected to a debugging server."
msgstr ""
"Vrátí pole slovníků, které reprezentují aktuální zásobník volání.\n"
"[codeblock]\n"
@@ -1248,12 +1255,16 @@ msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
-"Prints a stack track at code location, only works when running with debugger "
-"turned on.\n"
+"Prints a stack trace at the current code location. See also [method "
+"get_stack].\n"
"Output in the console would look something like this:\n"
"[codeblock]\n"
"Frame 0 - res://test.gd:16 in function '_process'\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] [method print_stack] only works if the running instance is "
+"connected to a debugging server (i.e. an editor instance). [method "
+"print_stack] will not work in projects exported in release mode, or in "
+"projects exported in debug mode if not connected to a debugging server."
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -3974,6 +3985,26 @@ msgid "Hints that an image is compressed using lossless compression."
msgstr ""
#: doc/classes/@GlobalScope.xml
+msgid ""
+"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:\n"
+"[codeblock]\n"
+"hint_string = \"%s:\" % [TYPE_INT] # Array of inteters.\n"
+"hint_string = \"%s:%s:\" % [TYPE_ARRAY, TYPE_REAL] # Two-dimensional array "
+"of floats.\n"
+"hint_string = \"%s/%s:Resource\" % [TYPE_OBJECT, TYPE_OBJECT] # Array of "
+"resources.\n"
+"hint_string = \"%s:%s/%s:Resource\" % [TYPE_ARRAY, TYPE_OBJECT, TYPE_OBJECT] "
+"# Two-dimensional array of resources.\n"
+"[/codeblock]\n"
+"[b]Note:[/b] The final colon is required to specify for properly detecting "
+"built-in types."
+msgstr ""
+
+#: doc/classes/@GlobalScope.xml
msgid "The property is serialized and saved in the scene file (default)."
msgstr ""
@@ -4303,7 +4334,7 @@ msgstr "Vektorová matematika"
#: doc/classes/AABB.xml doc/classes/Rect2.xml doc/classes/Vector2.xml
#: doc/classes/Vector3.xml
msgid "Advanced vector math"
-msgstr ""
+msgstr "PokroÄilá vektorová matematika"
#: doc/classes/AABB.xml
msgid "Constructs an [AABB] from a position and size."
@@ -4658,8 +4689,7 @@ msgstr ""
#: doc/classes/AudioStreamPlayer.xml doc/classes/Button.xml
#: doc/classes/CanvasLayer.xml doc/classes/CollisionShape2D.xml
#: doc/classes/ColorRect.xml doc/classes/Input.xml doc/classes/InputEvent.xml
-#: doc/classes/InputEventAction.xml doc/classes/Label.xml
-#: doc/classes/Particles2D.xml doc/classes/Timer.xml
+#: doc/classes/InputEventAction.xml doc/classes/Label.xml doc/classes/Timer.xml
#: doc/classes/VisibilityNotifier2D.xml
msgid "2D Dodge The Creeps Demo"
msgstr ""
@@ -7580,7 +7610,10 @@ msgid ""
"var array = []\n"
"array.resize(10)\n"
"array.fill(0) # Initialize the 10 elements to 0.\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] If [code]value[/code] is of a reference type ([Object]-derived, "
+"[Array], [Dictionary], etc.) then the array is filled with the references to "
+"the same object, i.e. no duplicates are created."
msgstr ""
#: doc/classes/Array.xml doc/classes/PoolByteArray.xml
@@ -7765,6 +7798,9 @@ msgstr ""
#: doc/classes/Array.xml
msgid ""
"Sorts the array.\n"
+"[b]Note:[/b] The sorting algorithm used is not [url=https://en.wikipedia.org/"
+"wiki/Sorting_algorithm#Stability]stable[/url]. This means that values "
+"considered equal may have their order changed when using [method sort].\n"
"[b]Note:[/b] Strings are sorted in alphabetical order (as opposed to natural "
"order). This may lead to unexpected behavior when sorting an array of "
"strings ending with a sequence of numbers. Consider the following example:\n"
@@ -7784,9 +7820,13 @@ msgid ""
"For two elements [code]a[/code] and [code]b[/code], if the given method "
"returns [code]true[/code], element [code]b[/code] will be after element "
"[code]a[/code] in the array.\n"
+"[b]Note:[/b] The sorting algorithm used is not [url=https://en.wikipedia.org/"
+"wiki/Sorting_algorithm#Stability]stable[/url]. This means that values "
+"considered equal may have their order changed when using [method "
+"sort_custom].\n"
"[b]Note:[/b] You cannot randomize the return value as the heapsort algorithm "
-"expects a deterministic result. Doing so will result in unexpected "
-"behavior.\n"
+"expects a deterministic result. Randomizing the return value will result in "
+"unexpected behavior.\n"
"[codeblock]\n"
"class MyCustomSorter:\n"
" static func sort_ascending(a, b):\n"
@@ -10431,12 +10471,14 @@ msgid "Clears the audio sample data buffer."
msgstr ""
#: doc/classes/AudioStreamGeneratorPlayback.xml
+#, fuzzy
msgid ""
-"Returns the number of audio data frames left to play. If this returned "
-"number reaches [code]0[/code], the audio will stop playing until frames are "
-"added again. Therefore, make sure your script can always generate and push "
-"new audio frames fast enough to avoid audio cracking."
+"Returns the number of frames that can be pushed to the audio sample data "
+"buffer without overflowing it. If the result is [code]0[/code], the buffer "
+"is full."
msgstr ""
+"Vrací [code]true[/code] pokud si jsou [code]a[/code] a [code]b[/code] "
+"přiblížně rovny."
#: doc/classes/AudioStreamGeneratorPlayback.xml
msgid ""
@@ -10967,14 +11009,14 @@ msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
"Node for back-buffering the currently-displayed screen. The region defined "
-"in the BackBufferCopy node is buffered with the content of the screen it "
+"in the [BackBufferCopy] node is buffered with the content of the screen it "
"covers, or the entire screen according to the copy mode set. Use the "
"[code]texture(SCREEN_TEXTURE, ...)[/code] function in your shader scripts to "
"access the buffer.\n"
"[b]Note:[/b] Since this node inherits from [Node2D] (and not [Control]), "
"anchors and margins won't apply to child [Control]-derived nodes. This can "
"be problematic when resizing the window. To avoid this, add [Control]-"
-"derived nodes as [i]siblings[/i] to the BackBufferCopy node instead of "
+"derived nodes as [i]siblings[/i] to the [BackBufferCopy] node instead of "
"adding them as children."
msgstr ""
@@ -10984,22 +11026,22 @@ msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
-"The area covered by the BackBufferCopy. Only used if [member copy_mode] is "
+"The area covered by the [BackBufferCopy]. Only used if [member copy_mode] is "
"[constant COPY_MODE_RECT]."
msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
-"Disables the buffering mode. This means the BackBufferCopy node will "
+"Disables the buffering mode. This means the [BackBufferCopy] node will "
"directly use the portion of screen it covers."
msgstr ""
#: doc/classes/BackBufferCopy.xml
-msgid "BackBufferCopy buffers a rectangular region."
+msgid "[BackBufferCopy] buffers a rectangular region."
msgstr ""
#: doc/classes/BackBufferCopy.xml
-msgid "BackBufferCopy buffers the entire screen."
+msgid "[BackBufferCopy] buffers the entire screen."
msgstr ""
#: doc/classes/BakedLightmap.xml
@@ -19828,6 +19870,14 @@ msgid "Cylinder shape for collisions."
msgstr ""
#: doc/classes/CylinderShape.xml
+msgid ""
+"Cylinder shape for collisions.\n"
+"[b]Note:[/b] When using GodotPhysics instead of the default Bullet physics "
+"engine, there are several known bugs with cylinder collision shapes. Using "
+"[CapsuleShape] or [BoxShape] instead is recommended."
+msgstr ""
+
+#: doc/classes/CylinderShape.xml
msgid "The cylinder's height."
msgstr ""
@@ -22664,7 +22714,10 @@ msgid ""
"[/codeblock]\n"
"[b]Note:[/b] The script is run in the Editor context, which means the output "
"is visible in the console window started with the Editor (stdout) instead of "
-"the usual Godot [b]Output[/b] dock."
+"the usual Godot [b]Output[/b] dock.\n"
+"[b]Note:[/b] EditorScript is reference counted, meaning it is destroyed when "
+"nothing references it. This can cause errors during asynchronous operations "
+"if there are no references to the script."
msgstr ""
#: doc/classes/EditorScript.xml
@@ -33412,7 +33465,9 @@ msgid ""
"The size of the light in Godot units. Only considered in baked lightmaps and "
"only if [member light_bake_mode] is set to [constant BAKE_ALL]. Increasing "
"this value will make the shadows appear blurrier. This can be used to "
-"simulate area lights to an extent."
+"simulate area lights to an extent.\n"
+"[b]Note:[/b] [member light_size] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/Light.xml
@@ -36744,7 +36799,10 @@ msgid ""
"use the [method get_next_location] function once every physics frame to "
"update the internal path logic of the NavigationAgent. The returned vector "
"position from this function should be used as the next movement position for "
-"the agent's parent Node."
+"the agent's parent Node.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues."
msgstr ""
#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
@@ -36996,7 +37054,10 @@ msgid ""
"use the [method get_next_location] function once every physics frame to "
"update the internal path logic of the NavigationAgent. The returned vector "
"position from this function should be used as the next movement position for "
-"the agent's parent Node."
+"the agent's parent Node.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues."
msgstr ""
#: doc/classes/NavigationAgent2D.xml
@@ -37716,6 +37777,9 @@ msgid ""
"modified velocity as-is might lead to pushing and agent outside of a "
"navigable area. This is a limitation of the collision avoidance system, any "
"more complex situation may require the use of the physics engine.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues.\n"
"This server keeps tracks of any call and executes them during the sync "
"phase. This means that you can request any change to the map, using any "
"thread, without worrying."
@@ -40529,7 +40593,9 @@ msgid ""
"The light's radius. Note that the effectively lit area may appear to be "
"smaller depending on the [member omni_attenuation] in use. No matter the "
"[member omni_attenuation] in use, the light will never reach anything "
-"outside this radius."
+"outside this radius.\n"
+"[b]Note:[/b] [member omni_range] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -41046,11 +41112,11 @@ msgstr "Vrátí tangens parametru."
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] cache data directory according to the operating "
-"system's standards. On desktop platforms, this path can be overridden by "
-"setting the [code]XDG_CACHE_HOME[/code] environment variable before starting "
-"the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in "
-"Godot projects[/url] in the documentation for more information. See also "
-"[method get_config_dir] and [method get_data_dir].\n"
+"system's standards. On Linux, this path can be overridden by setting the "
+"[code]XDG_CACHE_HOME[/code] environment variable before starting the "
+"project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot "
+"projects[/url] in the documentation for more information. See also [method "
+"get_config_dir] and [method get_data_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -41084,11 +41150,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] user configuration directory according to the "
-"operating system's standards. On desktop platforms, this path can be "
-"overridden by setting the [code]XDG_CONFIG_HOME[/code] environment variable "
-"before starting the project. See [url=$DOCS_URL/tutorials/io/data_paths."
-"html]File paths in Godot projects[/url] in the documentation for more "
-"information. See also [method get_cache_dir] and [method get_data_dir].\n"
+"operating system's standards. On Linux, this path can be overridden by "
+"setting the [code]XDG_CONFIG_HOME[/code] environment variable before "
+"starting the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File "
+"paths in Godot projects[/url] in the documentation for more information. See "
+"also [method get_cache_dir] and [method get_data_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -41110,11 +41176,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] user data directory according to the operating "
-"system's standards. On desktop platforms, this path can be overridden by "
-"setting the [code]XDG_DATA_HOME[/code] environment variable before starting "
-"the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in "
-"Godot projects[/url] in the documentation for more information. See also "
-"[method get_cache_dir] and [method get_config_dir].\n"
+"system's standards. On Linux, this path can be overridden by setting the "
+"[code]XDG_DATA_HOME[/code] environment variable before starting the project. "
+"See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot "
+"projects[/url] in the documentation for more information. See also [method "
+"get_cache_dir] and [method get_config_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -42984,6 +43050,16 @@ msgid "Particle systems (2D)"
msgstr ""
#: doc/classes/Particles2D.xml
+msgid "2D Particles Demo"
+msgstr ""
+
+#: doc/classes/Particles2D.xml
+msgid ""
+"2D Dodge The Creeps Demo (uses GPUParticles2D for the trail behind the "
+"player)"
+msgstr ""
+
+#: doc/classes/Particles2D.xml
msgid "Returns a rectangle containing the positions of all existing particles."
msgstr ""
@@ -50590,15 +50666,22 @@ msgstr ""
#: doc/classes/ProjectSettings.xml
msgid ""
"If [code]true[/code], uses a fast post-processing filter to make banding "
-"significantly less visible. In some cases, debanding may introduce a "
-"slightly noticeable dithering pattern. It's recommended to enable debanding "
-"only when actually needed since the dithering pattern will make lossless-"
-"compressed screenshots larger.\n"
+"significantly less visible in 3D. 2D rendering is [i]not[/i] affected by "
+"debanding unless the [member Environment.background_mode] is [constant "
+"Environment.BG_CANVAS]. In this case, [member rendering/quality/"
+"intended_usage/framebuffer_allocation] must also be set to [b]3D[/b].\n"
+"In some cases, debanding may introduce a slightly noticeable dithering "
+"pattern. It's recommended to enable debanding only when actually needed "
+"since the dithering pattern will make lossless-compressed screenshots "
+"larger.\n"
"[b]Note:[/b] Only available on the GLES3 backend. [member rendering/quality/"
"depth/hdr] must also be [code]true[/code] for debanding to be effective.\n"
"[b]Note:[/b] There are known issues with debanding breaking rendering on "
"mobile platforms. Due to this, it is recommended to leave this option "
-"disabled when targeting mobile platforms."
+"disabled when targeting mobile platforms.\n"
+"[b]Note:[/b] This property is only read when the project starts. To set "
+"debanding at run-time, set [member Viewport.debanding] on the root "
+"[Viewport] instead."
msgstr ""
#: doc/classes/ProjectSettings.xml
@@ -52199,17 +52282,28 @@ msgstr ""
#: modules/regex/doc_classes/RegEx.xml
msgid ""
"Searches the text for the compiled pattern. Returns a [RegExMatch] container "
-"of the first matching result if found, otherwise [code]null[/code]. The "
-"region to search within can be specified without modifying where the start "
-"and end anchor would be."
+"of the first matching result if found, otherwise [code]null[/code].\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegEx.xml
msgid ""
"Searches the text for the compiled pattern. Returns an array of [RegExMatch] "
"containers for each non-overlapping result. If no results were found, an "
-"empty array is returned instead. The region to search within can be "
-"specified without modifying where the start and end anchor would be."
+"empty array is returned instead.\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegEx.xml
@@ -52218,8 +52312,14 @@ msgid ""
"specified string. Escapes and backreferences such as [code]$1[/code] and "
"[code]$name[/code] are expanded and resolved. By default, only the first "
"instance is replaced, but it can be changed for all instances (global "
-"replacement). The region to search within can be specified without modifying "
-"where the start and end anchor would be."
+"replacement).\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegExMatch.xml
@@ -54939,7 +55039,11 @@ msgid "Call a group immediately (calls are normally made on idle)."
msgstr ""
#: doc/classes/SceneTree.xml
-msgid "Call a group only once even if the call is executed many times."
+msgid ""
+"Call a group only once even if the call is executed many times.\n"
+"[b]Note:[/b] Arguments are not taken into account when deciding whether the "
+"call is unique or not. Therefore when the same method is called with "
+"different arguments, only the first call will be performed."
msgstr ""
#: doc/classes/SceneTree.xml
@@ -56777,7 +56881,9 @@ msgid ""
"[b]Note:[/b] Mixed negative scales in 3D are not decomposable from the "
"transformation matrix. Due to the way scale is represented with "
"transformation matrices in Godot, the scale values will either be all "
-"positive or all negative."
+"positive or all negative.\n"
+"[b]Note:[/b] Not all nodes are visually scaled by the [member scale] "
+"property. For example, [Light]s are not visually affected by [member scale]."
msgstr ""
#: doc/classes/Spatial.xml
@@ -58155,7 +58261,10 @@ msgid ""
msgstr ""
#: doc/classes/SpotLight.xml
-msgid "The spotlight's angle in degrees."
+msgid ""
+"The spotlight's angle in degrees.\n"
+"[b]Note:[/b] [member spot_angle] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/SpotLight.xml
@@ -58171,7 +58280,9 @@ msgid ""
"The maximal range that can be reached by the spotlight. Note that the "
"effectively lit area may appear to be smaller depending on the [member "
"spot_attenuation] in use. No matter the [member spot_attenuation] in use, "
-"the light will never reach anything outside this range."
+"the light will never reach anything outside this range.\n"
+"[b]Note:[/b] [member spot_range] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/SpringArm.xml
@@ -67523,10 +67634,15 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
"If [code]true[/code], uses a fast post-processing filter to make banding "
-"significantly less visible. In some cases, debanding may introduce a "
-"slightly noticeable dithering pattern. It's recommended to enable debanding "
-"only when actually needed since the dithering pattern will make lossless-"
-"compressed screenshots larger.\n"
+"significantly less visible in 3D. 2D rendering is [i]not[/i] affected by "
+"debanding unless the [member Environment.background_mode] is [constant "
+"Environment.BG_CANVAS]. In this case, [member usage] must also be set to "
+"[constant USAGE_3D]. See also [member ProjectSettings.rendering/quality/"
+"filters/use_debanding].\n"
+"In some cases, debanding may introduce a slightly noticeable dithering "
+"pattern. It's recommended to enable debanding only when actually needed "
+"since the dithering pattern will make lossless-compressed screenshots "
+"larger.\n"
"[b]Note:[/b] Only available on the GLES3 backend. [member hdr] must also be "
"[code]true[/code] for debanding to be effective."
msgstr ""
@@ -67537,8 +67653,8 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
-"If [code]true[/code], the viewport will disable 3D rendering. For actual "
-"disabling use [code]usage[/code]."
+"If [code]true[/code], the viewport will disable 3D rendering. To actually "
+"disable allocation of 3D buffers, set [member usage] instead."
msgstr ""
#: doc/classes/Viewport.xml
@@ -67692,7 +67808,9 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
-"The rendering mode of viewport.\n"
+"The viewport's rendering mode. This controls which buffers are allocated for "
+"the viewport (2D only, or 2D + 3D). 2D-only options can reduce memory usage "
+"and improve performance slightly, especially on low-end devices.\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."
@@ -68224,6 +68342,22 @@ msgid ""
"render object this [VisualInstance] is set to."
msgstr ""
+#: doc/classes/VisualInstance.xml
+msgid ""
+"The sorting offset used by this [VisualInstance]. Adjusting it to a higher "
+"value will make the [VisualInstance] reliably draw on top of other "
+"[VisualInstance]s that are otherwise positioned at the same spot."
+msgstr ""
+
+#: doc/classes/VisualInstance.xml
+msgid ""
+"If [code]true[/code], the object is sorted based on the [AABB] center. "
+"Sorted based on the global position otherwise.\n"
+"The [AABB] center based sorting is generally more accurate for 3D models. "
+"The position based sorting instead allows to better control the drawing "
+"order when working with [Particles] and [CPUParticles]."
+msgstr ""
+
#: modules/visual_script/doc_classes/VisualScript.xml
msgid "A script implemented in the Visual Script programming environment."
msgstr ""
diff --git a/doc/translations/de.po b/doc/translations/de.po
index 0da2ce9bc1..1533aa651d 100644
--- a/doc/translations/de.po
+++ b/doc/translations/de.po
@@ -53,12 +53,14 @@
# Felix Bitsch <felix.a.bitsch@gmail.com>, 2022.
# Coxcopi <master.vogel2015@gmail.com>, 2022.
# Harusakii <spieleok@gmail.com>, 2022.
+# GadMas <c.vavra@web.de>, 2022.
+# JodliDev <jodlidev@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-09-12 01:18+0000\n"
-"Last-Translator: Harusakii <spieleok@gmail.com>\n"
+"PO-Revision-Date: 2022-11-10 23:27+0000\n"
+"Last-Translator: JodliDev <jodlidev@gmail.com>\n"
"Language-Team: German <https://hosted.weblate.org/projects/godot-engine/"
"godot-class-reference/de/>\n"
"Language: de\n"
@@ -66,7 +68,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.14.1-dev\n"
+"X-Generator: Weblate 4.15-dev\n"
#: doc/tools/make_rst.py
msgid "Description"
@@ -596,7 +598,6 @@ msgstr ""
"zurück in eine Instanz. Nützlich für die Deserialisierung."
#: 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 "
@@ -616,23 +617,24 @@ msgid ""
"See also [method smoothstep]. If you need to perform more advanced "
"transitions, use [Tween] or [AnimationPlayer]."
msgstr ""
-"Gibt einen interpolierten Wert von [code]x[/code] basiert auf einer Funktion "
-"die durch [code]curve[/code] definiert wird. Die Funktion basiert auf einem "
-"Exponent. Die [code]curve[/code] kann jegliche Gleitkommazahl sein, von "
-"welchen diese spezifische Werte zu folgendem Verhalten führen:\n"
+"Gibt einen interpolierten Wert von [code]x[/code] basierend auf einer "
+"Übergangsfunktion die durch [code]curve[/code] definiert wird. Diese "
+"Übergangsfunktion basiert auf einem Exponenten. Die [code]curve[/code] kann "
+"eine beliebige Fließkommazahl sein, wobei bestimmte Werte zu folgendem "
+"Verhalten führen:\n"
"[codeblock]\n"
-"- Weniger als -1.0 (exclusiv): Beschleunige in-out\n"
+"- Weniger als -1.0 (exklusiv): Ease in-out\n"
"- 1.0: Linear\n"
-"- Zwischen -1.0 und 0.0 (exclusiv): Beschleunige out-in\n"
+"- Zwischen -1.0 und 0.0 (exklusiv): Ease out-in\n"
"- 0.0: Konstant\n"
-"- Zwischen 0.0 und 1.0 (exclusiv): Beschleunige in\n"
+"- Zwischen 0.0 und 1.0 (exklusiv): Ease in\n"
"- 1.0: Linear\n"
-"- Mehr als 1.0 (exclusive): Beschleunige out\n"
+"- Mehr als 1.0 (exklusive): Beschleunige out\n"
"[/codeblock]\n"
"[url=https://raw.githubusercontent.com/godotengine/godot-docs/3.4/img/"
"ease_cheatsheet.png]ease() curve values cheatsheet[/url]\n"
-"Siehe auch [method smoothstep]. Falls du fortgeschrittene Übergänge "
-"erstellen möchtest, benutze [Tween] oder [AnimationPlayer]."
+"Siehe auch [method smoothstep]. Wenn du noch komplexere Übergänge erstellen "
+"möchtest, benutze [Tween] oder [AnimationPlayer]."
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
@@ -762,8 +764,10 @@ msgstr ""
"[/codeblock]"
#: modules/gdscript/doc_classes/@GDScript.xml
+#, fuzzy
msgid ""
-"Returns an array of dictionaries representing the current call stack.\n"
+"Returns an array of dictionaries representing the current call stack. See "
+"also [method print_stack].\n"
"[codeblock]\n"
"func _ready():\n"
" foo()\n"
@@ -778,7 +782,11 @@ msgid ""
"[codeblock]\n"
"[{function:bar, line:12, source:res://script.gd}, {function:foo, line:9, "
"source:res://script.gd}, {function:_ready, line:6, source:res://script.gd}]\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] [method get_stack] only works if the running instance is "
+"connected to a debugging server (i.e. an editor instance). [method "
+"get_stack] will not work in projects exported in release mode, or in "
+"projects exported in debug mode if not connected to a debugging server."
msgstr ""
"Gibt ein Array von Wörterbüchern zurück, das den aktuellen Aufrufstapel "
"darstellt.\n"
@@ -864,7 +872,6 @@ msgstr ""
"[/codeblock]"
#: modules/gdscript/doc_classes/@GDScript.xml
-#, fuzzy
msgid ""
"Returns an interpolation or extrapolation factor considering the range "
"specified in [code]from[/code] and [code]to[/code], and the interpolated "
@@ -887,24 +894,25 @@ msgid ""
"See also [method lerp] which performs the reverse of this operation, and "
"[method range_lerp] to map a continuous series of values to another."
msgstr ""
-"Gibt zurück einen Inter- bzw. Extrapolationsfaktor unter Berücksichtigung "
-"des Zahlenraums von [code]from[/code] bis [code]to[/code], und dem "
-"interpolierten Wert in [code]weight[/code]. Der Rückgabewert liegt zwischen "
-"[code]0.0[/code] und [code]1.0[/code] wenn [code]weight[/code] zwischen "
-"[code]from[/code] und [code]to[/code] (einschließlich). Liegt [code]weight[/"
-"code] außerhalb dieses Bereichs, wird ein Extrapolationsfaktor zurückgegeben "
-"(Rückgabewert kleiner als [code]0.0[/code] oder größer als [code]1.0[/"
-"code]).\n"
+"Gibt einen Inter- bzw. Extrapolationsfaktor unter Berücksichtigung des "
+"Zahlenraums von [code]from[/code] bis [code]to[/code], und dem "
+"interpolierten Wert in [code]weight[/code] zurück. Der Rückgabewert liegt "
+"zwischen [code]0.0[/code] und [code]1.0[/code] wenn [code]weight[/code] "
+"zwischen [code]from[/code] und [code]to[/code] (einschließlich). Liegt "
+"[code]weight[/code] außerhalb dieses Bereichs, wird ein Extrapolationsfaktor "
+"zurückgegeben (Rückgabewert kleiner als [code]0.0[/code] oder größer als "
+"[code]1.0[/code]).\n"
"[codeblock]\n"
-"# Die Interpolationsratio im `lerp()`-Aufruf unten beträgt 0.75.\n"
+"# Der Interpolationsfaktor im `lerp()`-Aufruf unten beträgt 0.75.\n"
"var middle = lerp(20, 30, 0.75)\n"
"# `middle` beträgt nun 27.5.\n"
-"# Angenommen, die ursprüngliche Ratio ist nun nicht mehr bekannt und soll "
-"zurückerrechnet werden.\n"
+"# Angenommen, der ursprüngliche Faktor ist nun nicht mehr bekannt und soll "
+"zurück errechnet werden.\n"
"var ratio = inverse_lerp(20, 30, 27.5)\n"
"# `ratio` beträgt nun 0.75.\n"
"[/codeblock]\n"
-"Siehe auch [method lerp] für die Umkehrung dieser Funktion."
+"Siehe auch [method lerp] für die Umkehrung dieser Funktion und [method "
+"range_lerp] um Zahlenbereiche aufeinander abzubilden."
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
@@ -976,7 +984,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 "
@@ -999,12 +1006,13 @@ msgid ""
"continuous series of values to another."
msgstr ""
"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 "
+"definierten Faktor. Um eine Interpolation durchzuführen, sollte [code]weigh[/"
+"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. Falls dies nicht "
+"gewünscht ist, kann [method clamp] auf dem Ergebnis von [method lerp] "
+"angewendet werden.\n"
+"Wenn die Argumente [code]from[/code] und [code]to[/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 "
@@ -1013,9 +1021,10 @@ msgstr ""
"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]."
+"Siehe auch [method inverse_lerp], welche die Umkehrung dieser Operation "
+"durchführt. Um eine \"eased Interpolation\" mit [method lerp] durchzuführen, "
+"kombiniere sie mit [method ease] oder [method smoothstep]. Siehe auch "
+"[method range_lerp] um eine Serie von Werten ineinander abzubilden."
#: modules/gdscript/doc_classes/@GDScript.xml
#, fuzzy
@@ -1346,7 +1355,6 @@ msgstr ""
"[/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"
@@ -1356,7 +1364,7 @@ msgid ""
msgstr ""
"Liefert das Ergebnis von [code]x[/code] hoch [code]y[/code].\n"
"[codeblock]\n"
-"pow(2, 5) # liefert 32\n"
+"pow(2, 5) # liefert 32.0\n"
"[/codeblock]"
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -1433,19 +1441,17 @@ msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
-"Prints a stack track at code location, only works when running with debugger "
-"turned on.\n"
+"Prints a stack trace at the current code location. See also [method "
+"get_stack].\n"
"Output in the console would look something like this:\n"
"[codeblock]\n"
"Frame 0 - res://test.gd:16 in function '_process'\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] [method print_stack] only works if the running instance is "
+"connected to a debugging server (i.e. an editor instance). [method "
+"print_stack] will not work in projects exported in release mode, or in "
+"projects exported in debug mode if not connected to a debugging server."
msgstr ""
-"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 ""
@@ -4656,6 +4662,26 @@ msgstr ""
"wurde."
#: doc/classes/@GlobalScope.xml
+msgid ""
+"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:\n"
+"[codeblock]\n"
+"hint_string = \"%s:\" % [TYPE_INT] # Array of inteters.\n"
+"hint_string = \"%s:%s:\" % [TYPE_ARRAY, TYPE_REAL] # Two-dimensional array "
+"of floats.\n"
+"hint_string = \"%s/%s:Resource\" % [TYPE_OBJECT, TYPE_OBJECT] # Array of "
+"resources.\n"
+"hint_string = \"%s:%s/%s:Resource\" % [TYPE_ARRAY, TYPE_OBJECT, TYPE_OBJECT] "
+"# Two-dimensional array of resources.\n"
+"[/codeblock]\n"
+"[b]Note:[/b] The final colon is required to specify for properly detecting "
+"built-in types."
+msgstr ""
+
+#: doc/classes/@GlobalScope.xml
msgid "The property is serialized and saved in the scene file (default)."
msgstr ""
"Die Eigenschaft wird serialisiert und in der Szenendatei gespeichert "
@@ -5519,8 +5545,7 @@ msgstr "2D Sprite Animation"
#: doc/classes/AudioStreamPlayer.xml doc/classes/Button.xml
#: doc/classes/CanvasLayer.xml doc/classes/CollisionShape2D.xml
#: doc/classes/ColorRect.xml doc/classes/Input.xml doc/classes/InputEvent.xml
-#: doc/classes/InputEventAction.xml doc/classes/Label.xml
-#: doc/classes/Particles2D.xml doc/classes/Timer.xml
+#: doc/classes/InputEventAction.xml doc/classes/Label.xml doc/classes/Timer.xml
#: doc/classes/VisibilityNotifier2D.xml
msgid "2D Dodge The Creeps Demo"
msgstr "2D „Dodge The Creeps“ Demo"
@@ -9635,6 +9660,7 @@ msgstr ""
"neu indiziert werden müssen."
#: doc/classes/Array.xml
+#, fuzzy
msgid ""
"Assigns the given value to all elements in the array. This can typically be "
"used together with [method resize] to create an array with a given size and "
@@ -9643,7 +9669,10 @@ msgid ""
"var array = []\n"
"array.resize(10)\n"
"array.fill(0) # Initialize the 10 elements to 0.\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] If [code]value[/code] is of a reference type ([Object]-derived, "
+"[Array], [Dictionary], etc.) then the array is filled with the references to "
+"the same object, i.e. no duplicates are created."
msgstr ""
"Weist allen Elementen des Arrays den angegebenen Wert zu. Dies kann "
"normalerweise zusammen mit [method resize] verwendet werden, um ein Array "
@@ -9935,8 +9964,12 @@ msgstr ""
"beschreibt."
#: doc/classes/Array.xml
+#, fuzzy
msgid ""
"Sorts the array.\n"
+"[b]Note:[/b] The sorting algorithm used is not [url=https://en.wikipedia.org/"
+"wiki/Sorting_algorithm#Stability]stable[/url]. This means that values "
+"considered equal may have their order changed when using [method sort].\n"
"[b]Note:[/b] Strings are sorted in alphabetical order (as opposed to natural "
"order). This may lead to unexpected behavior when sorting an array of "
"strings ending with a sequence of numbers. Consider the following example:\n"
@@ -9958,6 +9991,7 @@ msgstr ""
"[/codeblock]"
#: doc/classes/Array.xml
+#, fuzzy
msgid ""
"Sorts the array using a custom method. The arguments are an object that "
"holds the method and the name of such method. The custom method receives two "
@@ -9966,9 +10000,13 @@ msgid ""
"For two elements [code]a[/code] and [code]b[/code], if the given method "
"returns [code]true[/code], element [code]b[/code] will be after element "
"[code]a[/code] in the array.\n"
+"[b]Note:[/b] The sorting algorithm used is not [url=https://en.wikipedia.org/"
+"wiki/Sorting_algorithm#Stability]stable[/url]. This means that values "
+"considered equal may have their order changed when using [method "
+"sort_custom].\n"
"[b]Note:[/b] You cannot randomize the return value as the heapsort algorithm "
-"expects a deterministic result. Doing so will result in unexpected "
-"behavior.\n"
+"expects a deterministic result. Randomizing the return value will result in "
+"unexpected behavior.\n"
"[codeblock]\n"
"class MyCustomSorter:\n"
" static func sort_ascending(a, b):\n"
@@ -13374,12 +13412,14 @@ msgid "Clears the audio sample data buffer."
msgstr "Enthält die Audio Daten in Bytes."
#: doc/classes/AudioStreamGeneratorPlayback.xml
+#, fuzzy
msgid ""
-"Returns the number of audio data frames left to play. If this returned "
-"number reaches [code]0[/code], the audio will stop playing until frames are "
-"added again. Therefore, make sure your script can always generate and push "
-"new audio frames fast enough to avoid audio cracking."
+"Returns the number of frames that can be pushed to the audio sample data "
+"buffer without overflowing it. If the result is [code]0[/code], the buffer "
+"is full."
msgstr ""
+"Gibt [code]true[/code] zurück wenn Einstellung welche durch [code]name[/"
+"code]angegeben ist, existiert, ansonsten [code]false[/code]."
#: doc/classes/AudioStreamGeneratorPlayback.xml
msgid ""
@@ -13914,14 +13954,14 @@ msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
"Node for back-buffering the currently-displayed screen. The region defined "
-"in the BackBufferCopy node is buffered with the content of the screen it "
+"in the [BackBufferCopy] node is buffered with the content of the screen it "
"covers, or the entire screen according to the copy mode set. Use the "
"[code]texture(SCREEN_TEXTURE, ...)[/code] function in your shader scripts to "
"access the buffer.\n"
"[b]Note:[/b] Since this node inherits from [Node2D] (and not [Control]), "
"anchors and margins won't apply to child [Control]-derived nodes. This can "
"be problematic when resizing the window. To avoid this, add [Control]-"
-"derived nodes as [i]siblings[/i] to the BackBufferCopy node instead of "
+"derived nodes as [i]siblings[/i] to the [BackBufferCopy] node instead of "
"adding them as children."
msgstr ""
@@ -13931,22 +13971,22 @@ msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
-"The area covered by the BackBufferCopy. Only used if [member copy_mode] is "
+"The area covered by the [BackBufferCopy]. Only used if [member copy_mode] is "
"[constant COPY_MODE_RECT]."
msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
-"Disables the buffering mode. This means the BackBufferCopy node will "
+"Disables the buffering mode. This means the [BackBufferCopy] node will "
"directly use the portion of screen it covers."
msgstr ""
#: doc/classes/BackBufferCopy.xml
-msgid "BackBufferCopy buffers a rectangular region."
+msgid "[BackBufferCopy] buffers a rectangular region."
msgstr ""
#: doc/classes/BackBufferCopy.xml
-msgid "BackBufferCopy buffers the entire screen."
+msgid "[BackBufferCopy] buffers the entire screen."
msgstr ""
#: doc/classes/BakedLightmap.xml
@@ -22941,6 +22981,14 @@ msgid "Cylinder shape for collisions."
msgstr ""
#: doc/classes/CylinderShape.xml
+msgid ""
+"Cylinder shape for collisions.\n"
+"[b]Note:[/b] When using GodotPhysics instead of the default Bullet physics "
+"engine, there are several known bugs with cylinder collision shapes. Using "
+"[CapsuleShape] or [BoxShape] instead is recommended."
+msgstr ""
+
+#: doc/classes/CylinderShape.xml
msgid "The cylinder's height."
msgstr ""
@@ -25784,7 +25832,10 @@ msgid ""
"[/codeblock]\n"
"[b]Note:[/b] The script is run in the Editor context, which means the output "
"is visible in the console window started with the Editor (stdout) instead of "
-"the usual Godot [b]Output[/b] dock."
+"the usual Godot [b]Output[/b] dock.\n"
+"[b]Note:[/b] EditorScript is reference counted, meaning it is destroyed when "
+"nothing references it. This can cause errors during asynchronous operations "
+"if there are no references to the script."
msgstr ""
#: doc/classes/EditorScript.xml
@@ -36673,7 +36724,9 @@ msgid ""
"The size of the light in Godot units. Only considered in baked lightmaps and "
"only if [member light_bake_mode] is set to [constant BAKE_ALL]. Increasing "
"this value will make the shadows appear blurrier. This can be used to "
-"simulate area lights to an extent."
+"simulate area lights to an extent.\n"
+"[b]Note:[/b] [member light_size] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/Light.xml
@@ -40028,7 +40081,10 @@ msgid ""
"use the [method get_next_location] function once every physics frame to "
"update the internal path logic of the NavigationAgent. The returned vector "
"position from this function should be used as the next movement position for "
-"the agent's parent Node."
+"the agent's parent Node.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues."
msgstr ""
#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
@@ -40284,7 +40340,10 @@ msgid ""
"use the [method get_next_location] function once every physics frame to "
"update the internal path logic of the NavigationAgent. The returned vector "
"position from this function should be used as the next movement position for "
-"the agent's parent Node."
+"the agent's parent Node.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues."
msgstr ""
#: doc/classes/NavigationAgent2D.xml
@@ -41016,6 +41075,9 @@ msgid ""
"modified velocity as-is might lead to pushing and agent outside of a "
"navigable area. This is a limitation of the collision avoidance system, any "
"more complex situation may require the use of the physics engine.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues.\n"
"This server keeps tracks of any call and executes them during the sync "
"phase. This means that you can request any change to the map, using any "
"thread, without worrying."
@@ -43838,7 +43900,9 @@ msgid ""
"The light's radius. Note that the effectively lit area may appear to be "
"smaller depending on the [member omni_attenuation] in use. No matter the "
"[member omni_attenuation] in use, the light will never reach anything "
-"outside this radius."
+"outside this radius.\n"
+"[b]Note:[/b] [member omni_range] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -44358,11 +44422,11 @@ msgstr "Gibt das AnimationNode mit dem gegebenen Namen zurück."
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] cache data directory according to the operating "
-"system's standards. On desktop platforms, this path can be overridden by "
-"setting the [code]XDG_CACHE_HOME[/code] environment variable before starting "
-"the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in "
-"Godot projects[/url] in the documentation for more information. See also "
-"[method get_config_dir] and [method get_data_dir].\n"
+"system's standards. On Linux, this path can be overridden by setting the "
+"[code]XDG_CACHE_HOME[/code] environment variable before starting the "
+"project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot "
+"projects[/url] in the documentation for more information. See also [method "
+"get_config_dir] and [method get_data_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -44396,11 +44460,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] user configuration directory according to the "
-"operating system's standards. On desktop platforms, this path can be "
-"overridden by setting the [code]XDG_CONFIG_HOME[/code] environment variable "
-"before starting the project. See [url=$DOCS_URL/tutorials/io/data_paths."
-"html]File paths in Godot projects[/url] in the documentation for more "
-"information. See also [method get_cache_dir] and [method get_data_dir].\n"
+"operating system's standards. On Linux, this path can be overridden by "
+"setting the [code]XDG_CONFIG_HOME[/code] environment variable before "
+"starting the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File "
+"paths in Godot projects[/url] in the documentation for more information. See "
+"also [method get_cache_dir] and [method get_data_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -44422,11 +44486,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] user data directory according to the operating "
-"system's standards. On desktop platforms, this path can be overridden by "
-"setting the [code]XDG_DATA_HOME[/code] environment variable before starting "
-"the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in "
-"Godot projects[/url] in the documentation for more information. See also "
-"[method get_cache_dir] and [method get_config_dir].\n"
+"system's standards. On Linux, this path can be overridden by setting the "
+"[code]XDG_DATA_HOME[/code] environment variable before starting the project. "
+"See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot "
+"projects[/url] in the documentation for more information. See also [method "
+"get_cache_dir] and [method get_config_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -46320,6 +46384,17 @@ msgid "Particle systems (2D)"
msgstr ""
#: doc/classes/Particles2D.xml
+#, fuzzy
+msgid "2D Particles Demo"
+msgstr "2D Platformer Demo"
+
+#: doc/classes/Particles2D.xml
+msgid ""
+"2D Dodge The Creeps Demo (uses GPUParticles2D for the trail behind the "
+"player)"
+msgstr ""
+
+#: doc/classes/Particles2D.xml
msgid "Returns a rectangle containing the positions of all existing particles."
msgstr ""
@@ -53998,15 +54073,22 @@ msgstr ""
#: doc/classes/ProjectSettings.xml
msgid ""
"If [code]true[/code], uses a fast post-processing filter to make banding "
-"significantly less visible. In some cases, debanding may introduce a "
-"slightly noticeable dithering pattern. It's recommended to enable debanding "
-"only when actually needed since the dithering pattern will make lossless-"
-"compressed screenshots larger.\n"
+"significantly less visible in 3D. 2D rendering is [i]not[/i] affected by "
+"debanding unless the [member Environment.background_mode] is [constant "
+"Environment.BG_CANVAS]. In this case, [member rendering/quality/"
+"intended_usage/framebuffer_allocation] must also be set to [b]3D[/b].\n"
+"In some cases, debanding may introduce a slightly noticeable dithering "
+"pattern. It's recommended to enable debanding only when actually needed "
+"since the dithering pattern will make lossless-compressed screenshots "
+"larger.\n"
"[b]Note:[/b] Only available on the GLES3 backend. [member rendering/quality/"
"depth/hdr] must also be [code]true[/code] for debanding to be effective.\n"
"[b]Note:[/b] There are known issues with debanding breaking rendering on "
"mobile platforms. Due to this, it is recommended to leave this option "
-"disabled when targeting mobile platforms."
+"disabled when targeting mobile platforms.\n"
+"[b]Note:[/b] This property is only read when the project starts. To set "
+"debanding at run-time, set [member Viewport.debanding] on the root "
+"[Viewport] instead."
msgstr ""
#: doc/classes/ProjectSettings.xml
@@ -55641,17 +55723,28 @@ msgstr ""
#: modules/regex/doc_classes/RegEx.xml
msgid ""
"Searches the text for the compiled pattern. Returns a [RegExMatch] container "
-"of the first matching result if found, otherwise [code]null[/code]. The "
-"region to search within can be specified without modifying where the start "
-"and end anchor would be."
+"of the first matching result if found, otherwise [code]null[/code].\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegEx.xml
msgid ""
"Searches the text for the compiled pattern. Returns an array of [RegExMatch] "
"containers for each non-overlapping result. If no results were found, an "
-"empty array is returned instead. The region to search within can be "
-"specified without modifying where the start and end anchor would be."
+"empty array is returned instead.\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegEx.xml
@@ -55660,8 +55753,14 @@ msgid ""
"specified string. Escapes and backreferences such as [code]$1[/code] and "
"[code]$name[/code] are expanded and resolved. By default, only the first "
"instance is replaced, but it can be changed for all instances (global "
-"replacement). The region to search within can be specified without modifying "
-"where the start and end anchor would be."
+"replacement).\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegExMatch.xml
@@ -58401,7 +58500,11 @@ msgid "Call a group immediately (calls are normally made on idle)."
msgstr ""
#: doc/classes/SceneTree.xml
-msgid "Call a group only once even if the call is executed many times."
+msgid ""
+"Call a group only once even if the call is executed many times.\n"
+"[b]Note:[/b] Arguments are not taken into account when deciding whether the "
+"call is unique or not. Therefore when the same method is called with "
+"different arguments, only the first call will be performed."
msgstr ""
#: doc/classes/SceneTree.xml
@@ -60251,7 +60354,9 @@ msgid ""
"[b]Note:[/b] Mixed negative scales in 3D are not decomposable from the "
"transformation matrix. Due to the way scale is represented with "
"transformation matrices in Godot, the scale values will either be all "
-"positive or all negative."
+"positive or all negative.\n"
+"[b]Note:[/b] Not all nodes are visually scaled by the [member scale] "
+"property. For example, [Light]s are not visually affected by [member scale]."
msgstr ""
#: doc/classes/Spatial.xml
@@ -61650,7 +61755,10 @@ msgid ""
msgstr ""
#: doc/classes/SpotLight.xml
-msgid "The spotlight's angle in degrees."
+msgid ""
+"The spotlight's angle in degrees.\n"
+"[b]Note:[/b] [member spot_angle] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/SpotLight.xml
@@ -61666,7 +61774,9 @@ msgid ""
"The maximal range that can be reached by the spotlight. Note that the "
"effectively lit area may appear to be smaller depending on the [member "
"spot_attenuation] in use. No matter the [member spot_attenuation] in use, "
-"the light will never reach anything outside this range."
+"the light will never reach anything outside this range.\n"
+"[b]Note:[/b] [member spot_range] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/SpringArm.xml
@@ -71268,10 +71378,15 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
"If [code]true[/code], uses a fast post-processing filter to make banding "
-"significantly less visible. In some cases, debanding may introduce a "
-"slightly noticeable dithering pattern. It's recommended to enable debanding "
-"only when actually needed since the dithering pattern will make lossless-"
-"compressed screenshots larger.\n"
+"significantly less visible in 3D. 2D rendering is [i]not[/i] affected by "
+"debanding unless the [member Environment.background_mode] is [constant "
+"Environment.BG_CANVAS]. In this case, [member usage] must also be set to "
+"[constant USAGE_3D]. See also [member ProjectSettings.rendering/quality/"
+"filters/use_debanding].\n"
+"In some cases, debanding may introduce a slightly noticeable dithering "
+"pattern. It's recommended to enable debanding only when actually needed "
+"since the dithering pattern will make lossless-compressed screenshots "
+"larger.\n"
"[b]Note:[/b] Only available on the GLES3 backend. [member hdr] must also be "
"[code]true[/code] for debanding to be effective."
msgstr ""
@@ -71282,8 +71397,8 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
-"If [code]true[/code], the viewport will disable 3D rendering. For actual "
-"disabling use [code]usage[/code]."
+"If [code]true[/code], the viewport will disable 3D rendering. To actually "
+"disable allocation of 3D buffers, set [member usage] instead."
msgstr ""
#: doc/classes/Viewport.xml
@@ -71442,7 +71557,9 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
-"The rendering mode of viewport.\n"
+"The viewport's rendering mode. This controls which buffers are allocated for "
+"the viewport (2D only, or 2D + 3D). 2D-only options can reduce memory usage "
+"and improve performance slightly, especially on low-end devices.\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."
@@ -71985,6 +72102,22 @@ msgid ""
"render object this [VisualInstance] is set to."
msgstr ""
+#: doc/classes/VisualInstance.xml
+msgid ""
+"The sorting offset used by this [VisualInstance]. Adjusting it to a higher "
+"value will make the [VisualInstance] reliably draw on top of other "
+"[VisualInstance]s that are otherwise positioned at the same spot."
+msgstr ""
+
+#: doc/classes/VisualInstance.xml
+msgid ""
+"If [code]true[/code], the object is sorted based on the [AABB] center. "
+"Sorted based on the global position otherwise.\n"
+"The [AABB] center based sorting is generally more accurate for 3D models. "
+"The position based sorting instead allows to better control the drawing "
+"order when working with [Particles] and [CPUParticles]."
+msgstr ""
+
#: modules/visual_script/doc_classes/VisualScript.xml
msgid "A script implemented in the Visual Script programming environment."
msgstr ""
diff --git a/doc/translations/el.po b/doc/translations/el.po
index 2044a45e60..13c4fbfe68 100644
--- a/doc/translations/el.po
+++ b/doc/translations/el.po
@@ -483,7 +483,8 @@ msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
-"Returns an array of dictionaries representing the current call stack.\n"
+"Returns an array of dictionaries representing the current call stack. See "
+"also [method print_stack].\n"
"[codeblock]\n"
"func _ready():\n"
" foo()\n"
@@ -498,7 +499,11 @@ msgid ""
"[codeblock]\n"
"[{function:bar, line:12, source:res://script.gd}, {function:foo, line:9, "
"source:res://script.gd}, {function:_ready, line:6, source:res://script.gd}]\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] [method get_stack] only works if the running instance is "
+"connected to a debugging server (i.e. an editor instance). [method "
+"get_stack] will not work in projects exported in release mode, or in "
+"projects exported in debug mode if not connected to a debugging server."
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -871,12 +876,16 @@ msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
-"Prints a stack track at code location, only works when running with debugger "
-"turned on.\n"
+"Prints a stack trace at the current code location. See also [method "
+"get_stack].\n"
"Output in the console would look something like this:\n"
"[codeblock]\n"
"Frame 0 - res://test.gd:16 in function '_process'\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] [method print_stack] only works if the running instance is "
+"connected to a debugging server (i.e. an editor instance). [method "
+"print_stack] will not work in projects exported in release mode, or in "
+"projects exported in debug mode if not connected to a debugging server."
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -3487,6 +3496,26 @@ msgid "Hints that an image is compressed using lossless compression."
msgstr ""
#: doc/classes/@GlobalScope.xml
+msgid ""
+"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:\n"
+"[codeblock]\n"
+"hint_string = \"%s:\" % [TYPE_INT] # Array of inteters.\n"
+"hint_string = \"%s:%s:\" % [TYPE_ARRAY, TYPE_REAL] # Two-dimensional array "
+"of floats.\n"
+"hint_string = \"%s/%s:Resource\" % [TYPE_OBJECT, TYPE_OBJECT] # Array of "
+"resources.\n"
+"hint_string = \"%s:%s/%s:Resource\" % [TYPE_ARRAY, TYPE_OBJECT, TYPE_OBJECT] "
+"# Two-dimensional array of resources.\n"
+"[/codeblock]\n"
+"[b]Note:[/b] The final colon is required to specify for properly detecting "
+"built-in types."
+msgstr ""
+
+#: doc/classes/@GlobalScope.xml
msgid "The property is serialized and saved in the scene file (default)."
msgstr ""
@@ -4171,8 +4200,7 @@ msgstr ""
#: doc/classes/AudioStreamPlayer.xml doc/classes/Button.xml
#: doc/classes/CanvasLayer.xml doc/classes/CollisionShape2D.xml
#: doc/classes/ColorRect.xml doc/classes/Input.xml doc/classes/InputEvent.xml
-#: doc/classes/InputEventAction.xml doc/classes/Label.xml
-#: doc/classes/Particles2D.xml doc/classes/Timer.xml
+#: doc/classes/InputEventAction.xml doc/classes/Label.xml doc/classes/Timer.xml
#: doc/classes/VisibilityNotifier2D.xml
msgid "2D Dodge The Creeps Demo"
msgstr ""
@@ -7091,7 +7119,10 @@ msgid ""
"var array = []\n"
"array.resize(10)\n"
"array.fill(0) # Initialize the 10 elements to 0.\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] If [code]value[/code] is of a reference type ([Object]-derived, "
+"[Array], [Dictionary], etc.) then the array is filled with the references to "
+"the same object, i.e. no duplicates are created."
msgstr ""
#: doc/classes/Array.xml doc/classes/PoolByteArray.xml
@@ -7276,6 +7307,9 @@ msgstr ""
#: doc/classes/Array.xml
msgid ""
"Sorts the array.\n"
+"[b]Note:[/b] The sorting algorithm used is not [url=https://en.wikipedia.org/"
+"wiki/Sorting_algorithm#Stability]stable[/url]. This means that values "
+"considered equal may have their order changed when using [method sort].\n"
"[b]Note:[/b] Strings are sorted in alphabetical order (as opposed to natural "
"order). This may lead to unexpected behavior when sorting an array of "
"strings ending with a sequence of numbers. Consider the following example:\n"
@@ -7295,9 +7329,13 @@ msgid ""
"For two elements [code]a[/code] and [code]b[/code], if the given method "
"returns [code]true[/code], element [code]b[/code] will be after element "
"[code]a[/code] in the array.\n"
+"[b]Note:[/b] The sorting algorithm used is not [url=https://en.wikipedia.org/"
+"wiki/Sorting_algorithm#Stability]stable[/url]. This means that values "
+"considered equal may have their order changed when using [method "
+"sort_custom].\n"
"[b]Note:[/b] You cannot randomize the return value as the heapsort algorithm "
-"expects a deterministic result. Doing so will result in unexpected "
-"behavior.\n"
+"expects a deterministic result. Randomizing the return value will result in "
+"unexpected behavior.\n"
"[codeblock]\n"
"class MyCustomSorter:\n"
" static func sort_ascending(a, b):\n"
@@ -9936,10 +9974,9 @@ msgstr ""
#: doc/classes/AudioStreamGeneratorPlayback.xml
msgid ""
-"Returns the number of audio data frames left to play. If this returned "
-"number reaches [code]0[/code], the audio will stop playing until frames are "
-"added again. Therefore, make sure your script can always generate and push "
-"new audio frames fast enough to avoid audio cracking."
+"Returns the number of frames that can be pushed to the audio sample data "
+"buffer without overflowing it. If the result is [code]0[/code], the buffer "
+"is full."
msgstr ""
#: doc/classes/AudioStreamGeneratorPlayback.xml
@@ -10471,14 +10508,14 @@ msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
"Node for back-buffering the currently-displayed screen. The region defined "
-"in the BackBufferCopy node is buffered with the content of the screen it "
+"in the [BackBufferCopy] node is buffered with the content of the screen it "
"covers, or the entire screen according to the copy mode set. Use the "
"[code]texture(SCREEN_TEXTURE, ...)[/code] function in your shader scripts to "
"access the buffer.\n"
"[b]Note:[/b] Since this node inherits from [Node2D] (and not [Control]), "
"anchors and margins won't apply to child [Control]-derived nodes. This can "
"be problematic when resizing the window. To avoid this, add [Control]-"
-"derived nodes as [i]siblings[/i] to the BackBufferCopy node instead of "
+"derived nodes as [i]siblings[/i] to the [BackBufferCopy] node instead of "
"adding them as children."
msgstr ""
@@ -10488,22 +10525,22 @@ msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
-"The area covered by the BackBufferCopy. Only used if [member copy_mode] is "
+"The area covered by the [BackBufferCopy]. Only used if [member copy_mode] is "
"[constant COPY_MODE_RECT]."
msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
-"Disables the buffering mode. This means the BackBufferCopy node will "
+"Disables the buffering mode. This means the [BackBufferCopy] node will "
"directly use the portion of screen it covers."
msgstr ""
#: doc/classes/BackBufferCopy.xml
-msgid "BackBufferCopy buffers a rectangular region."
+msgid "[BackBufferCopy] buffers a rectangular region."
msgstr ""
#: doc/classes/BackBufferCopy.xml
-msgid "BackBufferCopy buffers the entire screen."
+msgid "[BackBufferCopy] buffers the entire screen."
msgstr ""
#: doc/classes/BakedLightmap.xml
@@ -19299,6 +19336,14 @@ msgid "Cylinder shape for collisions."
msgstr ""
#: doc/classes/CylinderShape.xml
+msgid ""
+"Cylinder shape for collisions.\n"
+"[b]Note:[/b] When using GodotPhysics instead of the default Bullet physics "
+"engine, there are several known bugs with cylinder collision shapes. Using "
+"[CapsuleShape] or [BoxShape] instead is recommended."
+msgstr ""
+
+#: doc/classes/CylinderShape.xml
msgid "The cylinder's height."
msgstr ""
@@ -22133,7 +22178,10 @@ msgid ""
"[/codeblock]\n"
"[b]Note:[/b] The script is run in the Editor context, which means the output "
"is visible in the console window started with the Editor (stdout) instead of "
-"the usual Godot [b]Output[/b] dock."
+"the usual Godot [b]Output[/b] dock.\n"
+"[b]Note:[/b] EditorScript is reference counted, meaning it is destroyed when "
+"nothing references it. This can cause errors during asynchronous operations "
+"if there are no references to the script."
msgstr ""
#: doc/classes/EditorScript.xml
@@ -32864,7 +32912,9 @@ msgid ""
"The size of the light in Godot units. Only considered in baked lightmaps and "
"only if [member light_bake_mode] is set to [constant BAKE_ALL]. Increasing "
"this value will make the shadows appear blurrier. This can be used to "
-"simulate area lights to an extent."
+"simulate area lights to an extent.\n"
+"[b]Note:[/b] [member light_size] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/Light.xml
@@ -36186,7 +36236,10 @@ msgid ""
"use the [method get_next_location] function once every physics frame to "
"update the internal path logic of the NavigationAgent. The returned vector "
"position from this function should be used as the next movement position for "
-"the agent's parent Node."
+"the agent's parent Node.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues."
msgstr ""
#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
@@ -36436,7 +36489,10 @@ msgid ""
"use the [method get_next_location] function once every physics frame to "
"update the internal path logic of the NavigationAgent. The returned vector "
"position from this function should be used as the next movement position for "
-"the agent's parent Node."
+"the agent's parent Node.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues."
msgstr ""
#: doc/classes/NavigationAgent2D.xml
@@ -37153,6 +37209,9 @@ msgid ""
"modified velocity as-is might lead to pushing and agent outside of a "
"navigable area. This is a limitation of the collision avoidance system, any "
"more complex situation may require the use of the physics engine.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues.\n"
"This server keeps tracks of any call and executes them during the sync "
"phase. This means that you can request any change to the map, using any "
"thread, without worrying."
@@ -39963,7 +40022,9 @@ msgid ""
"The light's radius. Note that the effectively lit area may appear to be "
"smaller depending on the [member omni_attenuation] in use. No matter the "
"[member omni_attenuation] in use, the light will never reach anything "
-"outside this radius."
+"outside this radius.\n"
+"[b]Note:[/b] [member omni_range] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -40479,11 +40540,11 @@ msgstr "ΕπιστÏέφει το τόξο ημιτόνου της παÏαμέÏ
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] cache data directory according to the operating "
-"system's standards. On desktop platforms, this path can be overridden by "
-"setting the [code]XDG_CACHE_HOME[/code] environment variable before starting "
-"the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in "
-"Godot projects[/url] in the documentation for more information. See also "
-"[method get_config_dir] and [method get_data_dir].\n"
+"system's standards. On Linux, this path can be overridden by setting the "
+"[code]XDG_CACHE_HOME[/code] environment variable before starting the "
+"project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot "
+"projects[/url] in the documentation for more information. See also [method "
+"get_config_dir] and [method get_data_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -40517,11 +40578,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] user configuration directory according to the "
-"operating system's standards. On desktop platforms, this path can be "
-"overridden by setting the [code]XDG_CONFIG_HOME[/code] environment variable "
-"before starting the project. See [url=$DOCS_URL/tutorials/io/data_paths."
-"html]File paths in Godot projects[/url] in the documentation for more "
-"information. See also [method get_cache_dir] and [method get_data_dir].\n"
+"operating system's standards. On Linux, this path can be overridden by "
+"setting the [code]XDG_CONFIG_HOME[/code] environment variable before "
+"starting the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File "
+"paths in Godot projects[/url] in the documentation for more information. See "
+"also [method get_cache_dir] and [method get_data_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -40543,11 +40604,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] user data directory according to the operating "
-"system's standards. On desktop platforms, this path can be overridden by "
-"setting the [code]XDG_DATA_HOME[/code] environment variable before starting "
-"the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in "
-"Godot projects[/url] in the documentation for more information. See also "
-"[method get_cache_dir] and [method get_config_dir].\n"
+"system's standards. On Linux, this path can be overridden by setting the "
+"[code]XDG_DATA_HOME[/code] environment variable before starting the project. "
+"See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot "
+"projects[/url] in the documentation for more information. See also [method "
+"get_cache_dir] and [method get_config_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -42397,6 +42458,16 @@ msgid "Particle systems (2D)"
msgstr ""
#: doc/classes/Particles2D.xml
+msgid "2D Particles Demo"
+msgstr ""
+
+#: doc/classes/Particles2D.xml
+msgid ""
+"2D Dodge The Creeps Demo (uses GPUParticles2D for the trail behind the "
+"player)"
+msgstr ""
+
+#: doc/classes/Particles2D.xml
msgid "Returns a rectangle containing the positions of all existing particles."
msgstr ""
@@ -49998,15 +50069,22 @@ msgstr ""
#: doc/classes/ProjectSettings.xml
msgid ""
"If [code]true[/code], uses a fast post-processing filter to make banding "
-"significantly less visible. In some cases, debanding may introduce a "
-"slightly noticeable dithering pattern. It's recommended to enable debanding "
-"only when actually needed since the dithering pattern will make lossless-"
-"compressed screenshots larger.\n"
+"significantly less visible in 3D. 2D rendering is [i]not[/i] affected by "
+"debanding unless the [member Environment.background_mode] is [constant "
+"Environment.BG_CANVAS]. In this case, [member rendering/quality/"
+"intended_usage/framebuffer_allocation] must also be set to [b]3D[/b].\n"
+"In some cases, debanding may introduce a slightly noticeable dithering "
+"pattern. It's recommended to enable debanding only when actually needed "
+"since the dithering pattern will make lossless-compressed screenshots "
+"larger.\n"
"[b]Note:[/b] Only available on the GLES3 backend. [member rendering/quality/"
"depth/hdr] must also be [code]true[/code] for debanding to be effective.\n"
"[b]Note:[/b] There are known issues with debanding breaking rendering on "
"mobile platforms. Due to this, it is recommended to leave this option "
-"disabled when targeting mobile platforms."
+"disabled when targeting mobile platforms.\n"
+"[b]Note:[/b] This property is only read when the project starts. To set "
+"debanding at run-time, set [member Viewport.debanding] on the root "
+"[Viewport] instead."
msgstr ""
#: doc/classes/ProjectSettings.xml
@@ -51603,17 +51681,28 @@ msgstr ""
#: modules/regex/doc_classes/RegEx.xml
msgid ""
"Searches the text for the compiled pattern. Returns a [RegExMatch] container "
-"of the first matching result if found, otherwise [code]null[/code]. The "
-"region to search within can be specified without modifying where the start "
-"and end anchor would be."
+"of the first matching result if found, otherwise [code]null[/code].\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegEx.xml
msgid ""
"Searches the text for the compiled pattern. Returns an array of [RegExMatch] "
"containers for each non-overlapping result. If no results were found, an "
-"empty array is returned instead. The region to search within can be "
-"specified without modifying where the start and end anchor would be."
+"empty array is returned instead.\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegEx.xml
@@ -51622,8 +51711,14 @@ msgid ""
"specified string. Escapes and backreferences such as [code]$1[/code] and "
"[code]$name[/code] are expanded and resolved. By default, only the first "
"instance is replaced, but it can be changed for all instances (global "
-"replacement). The region to search within can be specified without modifying "
-"where the start and end anchor would be."
+"replacement).\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegExMatch.xml
@@ -54339,7 +54434,11 @@ msgid "Call a group immediately (calls are normally made on idle)."
msgstr ""
#: doc/classes/SceneTree.xml
-msgid "Call a group only once even if the call is executed many times."
+msgid ""
+"Call a group only once even if the call is executed many times.\n"
+"[b]Note:[/b] Arguments are not taken into account when deciding whether the "
+"call is unique or not. Therefore when the same method is called with "
+"different arguments, only the first call will be performed."
msgstr ""
#: doc/classes/SceneTree.xml
@@ -56176,7 +56275,9 @@ msgid ""
"[b]Note:[/b] Mixed negative scales in 3D are not decomposable from the "
"transformation matrix. Due to the way scale is represented with "
"transformation matrices in Godot, the scale values will either be all "
-"positive or all negative."
+"positive or all negative.\n"
+"[b]Note:[/b] Not all nodes are visually scaled by the [member scale] "
+"property. For example, [Light]s are not visually affected by [member scale]."
msgstr ""
#: doc/classes/Spatial.xml
@@ -57554,7 +57655,10 @@ msgid ""
msgstr ""
#: doc/classes/SpotLight.xml
-msgid "The spotlight's angle in degrees."
+msgid ""
+"The spotlight's angle in degrees.\n"
+"[b]Note:[/b] [member spot_angle] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/SpotLight.xml
@@ -57570,7 +57674,9 @@ msgid ""
"The maximal range that can be reached by the spotlight. Note that the "
"effectively lit area may appear to be smaller depending on the [member "
"spot_attenuation] in use. No matter the [member spot_attenuation] in use, "
-"the light will never reach anything outside this range."
+"the light will never reach anything outside this range.\n"
+"[b]Note:[/b] [member spot_range] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/SpringArm.xml
@@ -66842,10 +66948,15 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
"If [code]true[/code], uses a fast post-processing filter to make banding "
-"significantly less visible. In some cases, debanding may introduce a "
-"slightly noticeable dithering pattern. It's recommended to enable debanding "
-"only when actually needed since the dithering pattern will make lossless-"
-"compressed screenshots larger.\n"
+"significantly less visible in 3D. 2D rendering is [i]not[/i] affected by "
+"debanding unless the [member Environment.background_mode] is [constant "
+"Environment.BG_CANVAS]. In this case, [member usage] must also be set to "
+"[constant USAGE_3D]. See also [member ProjectSettings.rendering/quality/"
+"filters/use_debanding].\n"
+"In some cases, debanding may introduce a slightly noticeable dithering "
+"pattern. It's recommended to enable debanding only when actually needed "
+"since the dithering pattern will make lossless-compressed screenshots "
+"larger.\n"
"[b]Note:[/b] Only available on the GLES3 backend. [member hdr] must also be "
"[code]true[/code] for debanding to be effective."
msgstr ""
@@ -66856,8 +66967,8 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
-"If [code]true[/code], the viewport will disable 3D rendering. For actual "
-"disabling use [code]usage[/code]."
+"If [code]true[/code], the viewport will disable 3D rendering. To actually "
+"disable allocation of 3D buffers, set [member usage] instead."
msgstr ""
#: doc/classes/Viewport.xml
@@ -67009,7 +67120,9 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
-"The rendering mode of viewport.\n"
+"The viewport's rendering mode. This controls which buffers are allocated for "
+"the viewport (2D only, or 2D + 3D). 2D-only options can reduce memory usage "
+"and improve performance slightly, especially on low-end devices.\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."
@@ -67541,6 +67654,22 @@ msgid ""
"render object this [VisualInstance] is set to."
msgstr ""
+#: doc/classes/VisualInstance.xml
+msgid ""
+"The sorting offset used by this [VisualInstance]. Adjusting it to a higher "
+"value will make the [VisualInstance] reliably draw on top of other "
+"[VisualInstance]s that are otherwise positioned at the same spot."
+msgstr ""
+
+#: doc/classes/VisualInstance.xml
+msgid ""
+"If [code]true[/code], the object is sorted based on the [AABB] center. "
+"Sorted based on the global position otherwise.\n"
+"The [AABB] center based sorting is generally more accurate for 3D models. "
+"The position based sorting instead allows to better control the drawing "
+"order when working with [Particles] and [CPUParticles]."
+msgstr ""
+
#: modules/visual_script/doc_classes/VisualScript.xml
msgid "A script implemented in the Visual Script programming environment."
msgstr ""
diff --git a/doc/translations/es.po b/doc/translations/es.po
index 12a03991b8..8ed223238d 100644
--- a/doc/translations/es.po
+++ b/doc/translations/es.po
@@ -37,12 +37,14 @@
# emnrx <emanuelermancia@gmail.com>, 2022.
# BlackNoizE404 <blacknoize404@gmail.com>, 2022.
# Keyla Arroyos <keylaarroyos@protonmail.com>, 2022.
+# Victor Stancioiu <victorstancioiu@gmail.com>, 2022.
+# yohanger <yohangerariel@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-09-26 05:24+0000\n"
-"Last-Translator: Keyla Arroyos <keylaarroyos@protonmail.com>\n"
+"PO-Revision-Date: 2022-11-29 20:23+0000\n"
+"Last-Translator: yohanger <yohangerariel@gmail.com>\n"
"Language-Team: Spanish <https://hosted.weblate.org/projects/godot-engine/"
"godot-class-reference/es/>\n"
"Language: es\n"
@@ -50,7 +52,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.14.1\n"
+"X-Generator: Weblate 4.15-dev\n"
#: doc/tools/make_rst.py
msgid "Description"
@@ -749,8 +751,10 @@ msgstr ""
"[/codeblock]"
#: modules/gdscript/doc_classes/@GDScript.xml
+#, fuzzy
msgid ""
-"Returns an array of dictionaries representing the current call stack.\n"
+"Returns an array of dictionaries representing the current call stack. See "
+"also [method print_stack].\n"
"[codeblock]\n"
"func _ready():\n"
" foo()\n"
@@ -765,7 +769,11 @@ msgid ""
"[codeblock]\n"
"[{function:bar, line:12, source:res://script.gd}, {function:foo, line:9, "
"source:res://script.gd}, {function:_ready, line:6, source:res://script.gd}]\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] [method get_stack] only works if the running instance is "
+"connected to a debugging server (i.e. an editor instance). [method "
+"get_stack] will not work in projects exported in release mode, or in "
+"projects exported in debug mode if not connected to a debugging server."
msgstr ""
"Devuelve un conjunto de diccionarios que representan la pila de llamadas "
"actual.\n"
@@ -852,7 +860,6 @@ msgstr ""
"[/codeblock]"
#: modules/gdscript/doc_classes/@GDScript.xml
-#, fuzzy
msgid ""
"Returns an interpolation or extrapolation factor considering the range "
"specified in [code]from[/code] and [code]to[/code], and the interpolated "
@@ -886,7 +893,7 @@ msgstr ""
"# La razón de interpolación en la llamada a `lerp()` de más abajo es 0.75.\n"
"var middle = lerp(20, 30, 0.75)\n"
"# `middle` ahora es 27.5.\n"
-"# Ahora, suponemos haber olvidado la razón original y queremos obtererla de "
+"# Ahora, suponemos haber olvidado la razón original y queremos obtenerla de "
"vuelta.\n"
"var ratio = inverse_lerp(20, 30, 27.5)\n"
"# `ratio` ahora es 0.75.\n"
@@ -1382,7 +1389,6 @@ msgstr ""
"mientras muestra un trazo de cuando un error o advertencia se muestra."
#: modules/gdscript/doc_classes/@GDScript.xml
-#, fuzzy
msgid ""
"Like [method print], but includes the current stack frame when running with "
"the debugger turned on.\n"
@@ -1392,7 +1398,7 @@ msgid ""
" At: res://test.gd:15:_process()\n"
"[/codeblock]"
msgstr ""
-"Imprime una registro de la pila en la ubicación del código, sólo funciona "
+"Imprime una registro de la pila en la ubicación del código, solo funciona "
"cuando se ejecuta con el depurador activado.\n"
"La salida en la consola se vería algo así:\n"
"[codeblock]\n"
@@ -1401,19 +1407,17 @@ msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
-"Prints a stack track at code location, only works when running with debugger "
-"turned on.\n"
+"Prints a stack trace at the current code location. See also [method "
+"get_stack].\n"
"Output in the console would look something like this:\n"
"[codeblock]\n"
"Frame 0 - res://test.gd:16 in function '_process'\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] [method print_stack] only works if the running instance is "
+"connected to a debugging server (i.e. an editor instance). [method "
+"print_stack] will not work in projects exported in release mode, or in "
+"projects exported in debug mode if not connected to a debugging server."
msgstr ""
-"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 ""
@@ -1533,7 +1537,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"
@@ -1542,10 +1545,10 @@ msgid ""
"[/codeblock]\n"
"[b]Note:[/b] This is equivalent to [code]randf() * (to - from) + from[/code]."
msgstr ""
-"Rango aleatorio de cualquier numero real entre [code]from[/code] y [code]to[/"
+"Rango aleatorio de cualquier número real entre [code]from[/code] y [code]to[/"
"code].\n"
"[codeblock]\n"
-"prints(rand_range(0, 1), rand_range(0, 1)) # Imprime dos numeros aleatorios\n"
+"prints(rand_range(0, 1), rand_range(0, 1)) # Imprime dos números aleatorios\n"
"[/codeblock]"
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -4570,6 +4573,26 @@ msgid "Hints that an image is compressed using lossless compression."
msgstr "Sugiere que una imagen se comprime usando una compresión sin pérdidas."
#: doc/classes/@GlobalScope.xml
+msgid ""
+"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:\n"
+"[codeblock]\n"
+"hint_string = \"%s:\" % [TYPE_INT] # Array of inteters.\n"
+"hint_string = \"%s:%s:\" % [TYPE_ARRAY, TYPE_REAL] # Two-dimensional array "
+"of floats.\n"
+"hint_string = \"%s/%s:Resource\" % [TYPE_OBJECT, TYPE_OBJECT] # Array of "
+"resources.\n"
+"hint_string = \"%s:%s/%s:Resource\" % [TYPE_ARRAY, TYPE_OBJECT, TYPE_OBJECT] "
+"# Two-dimensional array of resources.\n"
+"[/codeblock]\n"
+"[b]Note:[/b] The final colon is required to specify for properly detecting "
+"built-in types."
+msgstr ""
+
+#: doc/classes/@GlobalScope.xml
msgid "The property is serialized and saved in the scene file (default)."
msgstr ""
"La propiedad se serializa y se guarda en el archivo de la escena (por "
@@ -5406,8 +5429,7 @@ msgstr ""
#: doc/classes/AudioStreamPlayer.xml doc/classes/Button.xml
#: doc/classes/CanvasLayer.xml doc/classes/CollisionShape2D.xml
#: doc/classes/ColorRect.xml doc/classes/Input.xml doc/classes/InputEvent.xml
-#: doc/classes/InputEventAction.xml doc/classes/Label.xml
-#: doc/classes/Particles2D.xml doc/classes/Timer.xml
+#: doc/classes/InputEventAction.xml doc/classes/Label.xml doc/classes/Timer.xml
#: doc/classes/VisibilityNotifier2D.xml
msgid "2D Dodge The Creeps Demo"
msgstr ""
@@ -9212,7 +9234,10 @@ msgid ""
"var array = []\n"
"array.resize(10)\n"
"array.fill(0) # Initialize the 10 elements to 0.\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] If [code]value[/code] is of a reference type ([Object]-derived, "
+"[Array], [Dictionary], etc.) then the array is filled with the references to "
+"the same object, i.e. no duplicates are created."
msgstr ""
#: doc/classes/Array.xml doc/classes/PoolByteArray.xml
@@ -9448,8 +9473,12 @@ msgstr ""
"cambio entre indices mientras se trocean."
#: doc/classes/Array.xml
+#, fuzzy
msgid ""
"Sorts the array.\n"
+"[b]Note:[/b] The sorting algorithm used is not [url=https://en.wikipedia.org/"
+"wiki/Sorting_algorithm#Stability]stable[/url]. This means that values "
+"considered equal may have their order changed when using [method sort].\n"
"[b]Note:[/b] Strings are sorted in alphabetical order (as opposed to natural "
"order). This may lead to unexpected behavior when sorting an array of "
"strings ending with a sequence of numbers. Consider the following example:\n"
@@ -9480,9 +9509,13 @@ msgid ""
"For two elements [code]a[/code] and [code]b[/code], if the given method "
"returns [code]true[/code], element [code]b[/code] will be after element "
"[code]a[/code] in the array.\n"
+"[b]Note:[/b] The sorting algorithm used is not [url=https://en.wikipedia.org/"
+"wiki/Sorting_algorithm#Stability]stable[/url]. This means that values "
+"considered equal may have their order changed when using [method "
+"sort_custom].\n"
"[b]Note:[/b] You cannot randomize the return value as the heapsort algorithm "
-"expects a deterministic result. Doing so will result in unexpected "
-"behavior.\n"
+"expects a deterministic result. Randomizing the return value will result in "
+"unexpected behavior.\n"
"[codeblock]\n"
"class MyCustomSorter:\n"
" static func sort_ascending(a, b):\n"
@@ -13080,12 +13113,14 @@ msgid "Clears the audio sample data buffer."
msgstr "Contiene los datos de audio en bytes."
#: doc/classes/AudioStreamGeneratorPlayback.xml
+#, fuzzy
msgid ""
-"Returns the number of audio data frames left to play. If this returned "
-"number reaches [code]0[/code], the audio will stop playing until frames are "
-"added again. Therefore, make sure your script can always generate and push "
-"new audio frames fast enough to avoid audio cracking."
+"Returns the number of frames that can be pushed to the audio sample data "
+"buffer without overflowing it. If the result is [code]0[/code], the buffer "
+"is full."
msgstr ""
+"Devuelve [code]true[/code] si el [code]layer[/code] dado en el [member "
+"cull_mask] está activado, [code]false[/code] en caso contrario."
#: doc/classes/AudioStreamGeneratorPlayback.xml
msgid ""
@@ -13699,14 +13734,14 @@ msgstr ""
#, fuzzy
msgid ""
"Node for back-buffering the currently-displayed screen. The region defined "
-"in the BackBufferCopy node is buffered with the content of the screen it "
+"in the [BackBufferCopy] node is buffered with the content of the screen it "
"covers, or the entire screen according to the copy mode set. Use the "
"[code]texture(SCREEN_TEXTURE, ...)[/code] function in your shader scripts to "
"access the buffer.\n"
"[b]Note:[/b] Since this node inherits from [Node2D] (and not [Control]), "
"anchors and margins won't apply to child [Control]-derived nodes. This can "
"be problematic when resizing the window. To avoid this, add [Control]-"
-"derived nodes as [i]siblings[/i] to the BackBufferCopy node instead of "
+"derived nodes as [i]siblings[/i] to the [BackBufferCopy] node instead of "
"adding them as children."
msgstr ""
"Nodo para hacer un back-buffer en la pantalla que se muestra actualmente. La "
@@ -13725,27 +13760,31 @@ msgid "Buffer mode. See [enum CopyMode] constants."
msgstr "Modo de búfer. Ver las constantes de [enum CopyMode]."
#: doc/classes/BackBufferCopy.xml
+#, fuzzy
msgid ""
-"The area covered by the BackBufferCopy. Only used if [member copy_mode] is "
+"The area covered by the [BackBufferCopy]. Only used if [member copy_mode] is "
"[constant COPY_MODE_RECT]."
msgstr ""
"El área cubierta por el BackBufferCopy. Sólo se usa si [member copy_mode] es "
"[constant COPY_MODE_RECT]."
#: doc/classes/BackBufferCopy.xml
+#, fuzzy
msgid ""
-"Disables the buffering mode. This means the BackBufferCopy node will "
+"Disables the buffering mode. This means the [BackBufferCopy] node will "
"directly use the portion of screen it covers."
msgstr ""
"Deshabilita el modo de almacenamiento intermedio. Esto significa que el nodo "
"BackBufferCopy utilizará directamente la parte de la pantalla que cubre."
#: doc/classes/BackBufferCopy.xml
-msgid "BackBufferCopy buffers a rectangular region."
+#, fuzzy
+msgid "[BackBufferCopy] buffers a rectangular region."
msgstr "BackBufferCopy almacena una región rectangular."
#: doc/classes/BackBufferCopy.xml
-msgid "BackBufferCopy buffers the entire screen."
+#, fuzzy
+msgid "[BackBufferCopy] buffers the entire screen."
msgstr "BackBufferCopy almacena toda la pantalla."
#: doc/classes/BakedLightmap.xml
@@ -25237,6 +25276,14 @@ msgid "Cylinder shape for collisions."
msgstr "Forma de cilindro para colisiones."
#: doc/classes/CylinderShape.xml
+msgid ""
+"Cylinder shape for collisions.\n"
+"[b]Note:[/b] When using GodotPhysics instead of the default Bullet physics "
+"engine, there are several known bugs with cylinder collision shapes. Using "
+"[CapsuleShape] or [BoxShape] instead is recommended."
+msgstr ""
+
+#: doc/classes/CylinderShape.xml
msgid "The cylinder's height."
msgstr "La altura del cilindro."
@@ -29140,7 +29187,10 @@ msgid ""
"[/codeblock]\n"
"[b]Note:[/b] The script is run in the Editor context, which means the output "
"is visible in the console window started with the Editor (stdout) instead of "
-"the usual Godot [b]Output[/b] dock."
+"the usual Godot [b]Output[/b] dock.\n"
+"[b]Note:[/b] EditorScript is reference counted, meaning it is destroyed when "
+"nothing references it. This can cause errors during asynchronous operations "
+"if there are no references to the script."
msgstr ""
"Los scripts que extienden esta clase e implementan su método [method _run] "
"pueden ser ejecutados desde la opción de menú [b]File > Run[/b] del editor "
@@ -43439,7 +43489,9 @@ msgid ""
"The size of the light in Godot units. Only considered in baked lightmaps and "
"only if [member light_bake_mode] is set to [constant BAKE_ALL]. Increasing "
"this value will make the shadows appear blurrier. This can be used to "
-"simulate area lights to an extent."
+"simulate area lights to an extent.\n"
+"[b]Note:[/b] [member light_size] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
"El tamaño de la luz en unidades Godot. Sólo disponible para [OmniLight] y "
"[SpotLight]. Aumentar este valor hará que la luz se desvanezca más "
@@ -47664,7 +47716,10 @@ msgid ""
"use the [method get_next_location] function once every physics frame to "
"update the internal path logic of the NavigationAgent. The returned vector "
"position from this function should be used as the next movement position for "
-"the agent's parent Node."
+"the agent's parent Node.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues."
msgstr ""
#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
@@ -47924,7 +47979,10 @@ msgid ""
"use the [method get_next_location] function once every physics frame to "
"update the internal path logic of the NavigationAgent. The returned vector "
"position from this function should be used as the next movement position for "
-"the agent's parent Node."
+"the agent's parent Node.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues."
msgstr ""
#: doc/classes/NavigationAgent2D.xml
@@ -48736,6 +48794,9 @@ msgid ""
"modified velocity as-is might lead to pushing and agent outside of a "
"navigable area. This is a limitation of the collision avoidance system, any "
"more complex situation may require the use of the physics engine.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues.\n"
"This server keeps tracks of any call and executes them during the sync "
"phase. This means that you can request any change to the map, using any "
"thread, without worrying."
@@ -50988,7 +51049,6 @@ msgstr ""
"será renombrado automáticamente."
#: doc/classes/Node.xml
-#, fuzzy
msgid ""
"The node owner. A node can have any other node as owner (as long as it is a "
"valid parent, grandparent, etc. ascending in the tree). When saving a node "
@@ -51016,7 +51076,7 @@ msgstr ""
"ejemplo:\n"
"[codeblock]\n"
"if child_node.get_parent():\n"
-" child_node.get_parent().remove_child(child_node)\n"
+" child_node.get_parent().remove_child(child_node)\n"
"add_child(child_node)\n"
"[/codeblock]\n"
"Si necesita que el nodo hijo se añada debajo de un nodo específico en la "
@@ -52769,11 +52829,14 @@ msgstr ""
"curva."
#: doc/classes/OmniLight.xml
+#, fuzzy
msgid ""
"The light's radius. Note that the effectively lit area may appear to be "
"smaller depending on the [member omni_attenuation] in use. No matter the "
"[member omni_attenuation] in use, the light will never reach anything "
-"outside this radius."
+"outside this radius.\n"
+"[b]Note:[/b] [member omni_range] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
"El radio de la luz. Tenga en cuenta que el área efectivamente iluminada "
"puede parecer más pequeña dependiendo del [member omni_attenuation] en uso. "
@@ -53445,11 +53508,11 @@ msgstr "Devuelve el vértice en un índice determinado."
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] cache data directory according to the operating "
-"system's standards. On desktop platforms, this path can be overridden by "
-"setting the [code]XDG_CACHE_HOME[/code] environment variable before starting "
-"the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in "
-"Godot projects[/url] in the documentation for more information. See also "
-"[method get_config_dir] and [method get_data_dir].\n"
+"system's standards. On Linux, this path can be overridden by setting the "
+"[code]XDG_CACHE_HOME[/code] environment variable before starting the "
+"project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot "
+"projects[/url] in the documentation for more information. See also [method "
+"get_config_dir] and [method get_data_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -53505,11 +53568,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] user configuration directory according to the "
-"operating system's standards. On desktop platforms, this path can be "
-"overridden by setting the [code]XDG_CONFIG_HOME[/code] environment variable "
-"before starting the project. See [url=$DOCS_URL/tutorials/io/data_paths."
-"html]File paths in Godot projects[/url] in the documentation for more "
-"information. See also [method get_cache_dir] and [method get_data_dir].\n"
+"operating system's standards. On Linux, this path can be overridden by "
+"setting the [code]XDG_CONFIG_HOME[/code] environment variable before "
+"starting the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File "
+"paths in Godot projects[/url] in the documentation for more information. See "
+"also [method get_cache_dir] and [method get_data_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -53538,11 +53601,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] user data directory according to the operating "
-"system's standards. On desktop platforms, this path can be overridden by "
-"setting the [code]XDG_DATA_HOME[/code] environment variable before starting "
-"the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in "
-"Godot projects[/url] in the documentation for more information. See also "
-"[method get_cache_dir] and [method get_config_dir].\n"
+"system's standards. On Linux, this path can be overridden by setting the "
+"[code]XDG_DATA_HOME[/code] environment variable before starting the project. "
+"See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot "
+"projects[/url] in the documentation for more information. See also [method "
+"get_cache_dir] and [method get_config_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -55970,6 +56033,16 @@ msgid "Particle systems (2D)"
msgstr ""
#: doc/classes/Particles2D.xml
+msgid "2D Particles Demo"
+msgstr ""
+
+#: doc/classes/Particles2D.xml
+msgid ""
+"2D Dodge The Creeps Demo (uses GPUParticles2D for the trail behind the "
+"player)"
+msgstr ""
+
+#: doc/classes/Particles2D.xml
msgid "Returns a rectangle containing the positions of all existing particles."
msgstr ""
"Devuelve un rectángulo que contiene las posiciones de todas las partículas "
@@ -65727,15 +65800,22 @@ msgstr ""
#: doc/classes/ProjectSettings.xml
msgid ""
"If [code]true[/code], uses a fast post-processing filter to make banding "
-"significantly less visible. In some cases, debanding may introduce a "
-"slightly noticeable dithering pattern. It's recommended to enable debanding "
-"only when actually needed since the dithering pattern will make lossless-"
-"compressed screenshots larger.\n"
+"significantly less visible in 3D. 2D rendering is [i]not[/i] affected by "
+"debanding unless the [member Environment.background_mode] is [constant "
+"Environment.BG_CANVAS]. In this case, [member rendering/quality/"
+"intended_usage/framebuffer_allocation] must also be set to [b]3D[/b].\n"
+"In some cases, debanding may introduce a slightly noticeable dithering "
+"pattern. It's recommended to enable debanding only when actually needed "
+"since the dithering pattern will make lossless-compressed screenshots "
+"larger.\n"
"[b]Note:[/b] Only available on the GLES3 backend. [member rendering/quality/"
"depth/hdr] must also be [code]true[/code] for debanding to be effective.\n"
"[b]Note:[/b] There are known issues with debanding breaking rendering on "
"mobile platforms. Due to this, it is recommended to leave this option "
-"disabled when targeting mobile platforms."
+"disabled when targeting mobile platforms.\n"
+"[b]Note:[/b] This property is only read when the project starts. To set "
+"debanding at run-time, set [member Viewport.debanding] on the root "
+"[Viewport] instead."
msgstr ""
#: doc/classes/ProjectSettings.xml
@@ -67818,36 +67898,45 @@ msgstr "Devuelve si este objeto tiene asignado un patrón de búsqueda válido."
#: modules/regex/doc_classes/RegEx.xml
msgid ""
"Searches the text for the compiled pattern. Returns a [RegExMatch] container "
-"of the first matching result if found, otherwise [code]null[/code]. The "
-"region to search within can be specified without modifying where the start "
-"and end anchor would be."
+"of the first matching result if found, otherwise [code]null[/code].\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
-"Busca en el texto el patrón compilado. Devuelve un contenedor [RegExMatch] "
-"del primer resultado coincidente si se encuentra, de lo contrario "
-"[code]null[/code]. La región en la que se debe buscar puede especificarse "
-"sin modificar el lugar en el que se encuentra el anclaje de inicio y fin."
#: modules/regex/doc_classes/RegEx.xml
msgid ""
"Searches the text for the compiled pattern. Returns an array of [RegExMatch] "
"containers for each non-overlapping result. If no results were found, an "
-"empty array is returned instead. The region to search within can be "
-"specified without modifying where the start and end anchor would be."
+"empty array is returned instead.\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
-"Busca en el texto el patrón compilado. Devuelve un array de contenedores "
-"[RegExMatch] para cada resultado no superpuesto. Si no se encuentran "
-"resultados, se devuelve un array vacío. La región en la que se debe buscar "
-"puede ser especificada sin modificar el lugar donde se encuentran el ancla "
-"de inicio y el ancla de fin."
#: modules/regex/doc_classes/RegEx.xml
+#, fuzzy
msgid ""
"Searches the text for the compiled pattern and replaces it with the "
"specified string. Escapes and backreferences such as [code]$1[/code] and "
"[code]$name[/code] are expanded and resolved. By default, only the first "
"instance is replaced, but it can be changed for all instances (global "
-"replacement). The region to search within can be specified without modifying "
-"where the start and end anchor would be."
+"replacement).\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
"Busca en el texto el patrón compilado y lo reemplaza con la string "
"especificada. Escapadas y retro-referencias como [code]$1[/code] y "
@@ -71417,9 +71506,12 @@ msgstr ""
"reposo)."
#: doc/classes/SceneTree.xml
-msgid "Call a group only once even if the call is executed many times."
+msgid ""
+"Call a group only once even if the call is executed many times.\n"
+"[b]Note:[/b] Arguments are not taken into account when deciding whether the "
+"call is unique or not. Therefore when the same method is called with "
+"different arguments, only the first call will be performed."
msgstr ""
-"Llama a un grupo sólo una vez aunque la llamada se ejecute muchas veces."
#: doc/classes/SceneTree.xml
#, fuzzy
@@ -73637,7 +73729,9 @@ msgid ""
"[b]Note:[/b] Mixed negative scales in 3D are not decomposable from the "
"transformation matrix. Due to the way scale is represented with "
"transformation matrices in Godot, the scale values will either be all "
-"positive or all negative."
+"positive or all negative.\n"
+"[b]Note:[/b] Not all nodes are visually scaled by the [member scale] "
+"property. For example, [Light]s are not visually affected by [member scale]."
msgstr ""
#: doc/classes/Spatial.xml
@@ -75379,8 +75473,11 @@ msgid ""
msgstr ""
#: doc/classes/SpotLight.xml
-msgid "The spotlight's angle in degrees."
-msgstr "El ángulo del foco en grados."
+msgid ""
+"The spotlight's angle in degrees.\n"
+"[b]Note:[/b] [member spot_angle] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
+msgstr ""
#: doc/classes/SpotLight.xml
msgid "The spotlight's angular attenuation curve."
@@ -75391,11 +75488,14 @@ msgid "The spotlight's light energy attenuation curve."
msgstr "La curva de atenuación de la energía de la luz del foco."
#: doc/classes/SpotLight.xml
+#, fuzzy
msgid ""
"The maximal range that can be reached by the spotlight. Note that the "
"effectively lit area may appear to be smaller depending on the [member "
"spot_attenuation] in use. No matter the [member spot_attenuation] in use, "
-"the light will never reach anything outside this range."
+"the light will never reach anything outside this range.\n"
+"[b]Note:[/b] [member spot_range] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
"El máximo rango que puede ser alcanzado por el foco. Tenga en cuenta que el "
"área efectivamente iluminada puede parecer más pequeña dependiendo del "
@@ -87445,10 +87545,15 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
"If [code]true[/code], uses a fast post-processing filter to make banding "
-"significantly less visible. In some cases, debanding may introduce a "
-"slightly noticeable dithering pattern. It's recommended to enable debanding "
-"only when actually needed since the dithering pattern will make lossless-"
-"compressed screenshots larger.\n"
+"significantly less visible in 3D. 2D rendering is [i]not[/i] affected by "
+"debanding unless the [member Environment.background_mode] is [constant "
+"Environment.BG_CANVAS]. In this case, [member usage] must also be set to "
+"[constant USAGE_3D]. See also [member ProjectSettings.rendering/quality/"
+"filters/use_debanding].\n"
+"In some cases, debanding may introduce a slightly noticeable dithering "
+"pattern. It's recommended to enable debanding only when actually needed "
+"since the dithering pattern will make lossless-compressed screenshots "
+"larger.\n"
"[b]Note:[/b] Only available on the GLES3 backend. [member hdr] must also be "
"[code]true[/code] for debanding to be effective."
msgstr ""
@@ -87462,8 +87567,8 @@ msgstr ""
#: doc/classes/Viewport.xml
#, fuzzy
msgid ""
-"If [code]true[/code], the viewport will disable 3D rendering. For actual "
-"disabling use [code]usage[/code]."
+"If [code]true[/code], the viewport will disable 3D rendering. To actually "
+"disable allocation of 3D buffers, set [member usage] instead."
msgstr ""
"Si [code]true[/code], la etiqueta subraya las metaetiquetas como [code][url]"
"{text}[/url][/code]."
@@ -87654,7 +87759,9 @@ msgstr "Si [code]true[/code], el viewport debería hacer su fondo transparente."
#: doc/classes/Viewport.xml
msgid ""
-"The rendering mode of viewport.\n"
+"The viewport's rendering mode. This controls which buffers are allocated for "
+"the viewport (2D only, or 2D + 3D). 2D-only options can reduce memory usage "
+"and improve performance slightly, especially on low-end devices.\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."
@@ -88350,6 +88457,22 @@ msgstr ""
"Este objeto sólo será visible para [Camera] cuya máscara de selección "
"incluya el objeto renderizado que este [VisualInstance] tiene configurado."
+#: doc/classes/VisualInstance.xml
+msgid ""
+"The sorting offset used by this [VisualInstance]. Adjusting it to a higher "
+"value will make the [VisualInstance] reliably draw on top of other "
+"[VisualInstance]s that are otherwise positioned at the same spot."
+msgstr ""
+
+#: doc/classes/VisualInstance.xml
+msgid ""
+"If [code]true[/code], the object is sorted based on the [AABB] center. "
+"Sorted based on the global position otherwise.\n"
+"The [AABB] center based sorting is generally more accurate for 3D models. "
+"The position based sorting instead allows to better control the drawing "
+"order when working with [Particles] and [CPUParticles]."
+msgstr ""
+
#: modules/visual_script/doc_classes/VisualScript.xml
msgid "A script implemented in the Visual Script programming environment."
msgstr "Un script implementado en el entorno de programación de Visual Script."
diff --git a/doc/translations/et.po b/doc/translations/et.po
index 40bf471522..7f92671d8f 100644
--- a/doc/translations/et.po
+++ b/doc/translations/et.po
@@ -481,7 +481,8 @@ msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
-"Returns an array of dictionaries representing the current call stack.\n"
+"Returns an array of dictionaries representing the current call stack. See "
+"also [method print_stack].\n"
"[codeblock]\n"
"func _ready():\n"
" foo()\n"
@@ -496,7 +497,11 @@ msgid ""
"[codeblock]\n"
"[{function:bar, line:12, source:res://script.gd}, {function:foo, line:9, "
"source:res://script.gd}, {function:_ready, line:6, source:res://script.gd}]\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] [method get_stack] only works if the running instance is "
+"connected to a debugging server (i.e. an editor instance). [method "
+"get_stack] will not work in projects exported in release mode, or in "
+"projects exported in debug mode if not connected to a debugging server."
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -869,12 +874,16 @@ msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
-"Prints a stack track at code location, only works when running with debugger "
-"turned on.\n"
+"Prints a stack trace at the current code location. See also [method "
+"get_stack].\n"
"Output in the console would look something like this:\n"
"[codeblock]\n"
"Frame 0 - res://test.gd:16 in function '_process'\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] [method print_stack] only works if the running instance is "
+"connected to a debugging server (i.e. an editor instance). [method "
+"print_stack] will not work in projects exported in release mode, or in "
+"projects exported in debug mode if not connected to a debugging server."
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -3485,6 +3494,26 @@ msgid "Hints that an image is compressed using lossless compression."
msgstr ""
#: doc/classes/@GlobalScope.xml
+msgid ""
+"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:\n"
+"[codeblock]\n"
+"hint_string = \"%s:\" % [TYPE_INT] # Array of inteters.\n"
+"hint_string = \"%s:%s:\" % [TYPE_ARRAY, TYPE_REAL] # Two-dimensional array "
+"of floats.\n"
+"hint_string = \"%s/%s:Resource\" % [TYPE_OBJECT, TYPE_OBJECT] # Array of "
+"resources.\n"
+"hint_string = \"%s:%s/%s:Resource\" % [TYPE_ARRAY, TYPE_OBJECT, TYPE_OBJECT] "
+"# Two-dimensional array of resources.\n"
+"[/codeblock]\n"
+"[b]Note:[/b] The final colon is required to specify for properly detecting "
+"built-in types."
+msgstr ""
+
+#: doc/classes/@GlobalScope.xml
msgid "The property is serialized and saved in the scene file (default)."
msgstr ""
@@ -4169,8 +4198,7 @@ msgstr ""
#: doc/classes/AudioStreamPlayer.xml doc/classes/Button.xml
#: doc/classes/CanvasLayer.xml doc/classes/CollisionShape2D.xml
#: doc/classes/ColorRect.xml doc/classes/Input.xml doc/classes/InputEvent.xml
-#: doc/classes/InputEventAction.xml doc/classes/Label.xml
-#: doc/classes/Particles2D.xml doc/classes/Timer.xml
+#: doc/classes/InputEventAction.xml doc/classes/Label.xml doc/classes/Timer.xml
#: doc/classes/VisibilityNotifier2D.xml
msgid "2D Dodge The Creeps Demo"
msgstr ""
@@ -7087,7 +7115,10 @@ msgid ""
"var array = []\n"
"array.resize(10)\n"
"array.fill(0) # Initialize the 10 elements to 0.\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] If [code]value[/code] is of a reference type ([Object]-derived, "
+"[Array], [Dictionary], etc.) then the array is filled with the references to "
+"the same object, i.e. no duplicates are created."
msgstr ""
#: doc/classes/Array.xml doc/classes/PoolByteArray.xml
@@ -7272,6 +7303,9 @@ msgstr ""
#: doc/classes/Array.xml
msgid ""
"Sorts the array.\n"
+"[b]Note:[/b] The sorting algorithm used is not [url=https://en.wikipedia.org/"
+"wiki/Sorting_algorithm#Stability]stable[/url]. This means that values "
+"considered equal may have their order changed when using [method sort].\n"
"[b]Note:[/b] Strings are sorted in alphabetical order (as opposed to natural "
"order). This may lead to unexpected behavior when sorting an array of "
"strings ending with a sequence of numbers. Consider the following example:\n"
@@ -7291,9 +7325,13 @@ msgid ""
"For two elements [code]a[/code] and [code]b[/code], if the given method "
"returns [code]true[/code], element [code]b[/code] will be after element "
"[code]a[/code] in the array.\n"
+"[b]Note:[/b] The sorting algorithm used is not [url=https://en.wikipedia.org/"
+"wiki/Sorting_algorithm#Stability]stable[/url]. This means that values "
+"considered equal may have their order changed when using [method "
+"sort_custom].\n"
"[b]Note:[/b] You cannot randomize the return value as the heapsort algorithm "
-"expects a deterministic result. Doing so will result in unexpected "
-"behavior.\n"
+"expects a deterministic result. Randomizing the return value will result in "
+"unexpected behavior.\n"
"[codeblock]\n"
"class MyCustomSorter:\n"
" static func sort_ascending(a, b):\n"
@@ -9931,10 +9969,9 @@ msgstr ""
#: doc/classes/AudioStreamGeneratorPlayback.xml
msgid ""
-"Returns the number of audio data frames left to play. If this returned "
-"number reaches [code]0[/code], the audio will stop playing until frames are "
-"added again. Therefore, make sure your script can always generate and push "
-"new audio frames fast enough to avoid audio cracking."
+"Returns the number of frames that can be pushed to the audio sample data "
+"buffer without overflowing it. If the result is [code]0[/code], the buffer "
+"is full."
msgstr ""
#: doc/classes/AudioStreamGeneratorPlayback.xml
@@ -10466,14 +10503,14 @@ msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
"Node for back-buffering the currently-displayed screen. The region defined "
-"in the BackBufferCopy node is buffered with the content of the screen it "
+"in the [BackBufferCopy] node is buffered with the content of the screen it "
"covers, or the entire screen according to the copy mode set. Use the "
"[code]texture(SCREEN_TEXTURE, ...)[/code] function in your shader scripts to "
"access the buffer.\n"
"[b]Note:[/b] Since this node inherits from [Node2D] (and not [Control]), "
"anchors and margins won't apply to child [Control]-derived nodes. This can "
"be problematic when resizing the window. To avoid this, add [Control]-"
-"derived nodes as [i]siblings[/i] to the BackBufferCopy node instead of "
+"derived nodes as [i]siblings[/i] to the [BackBufferCopy] node instead of "
"adding them as children."
msgstr ""
@@ -10483,22 +10520,22 @@ msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
-"The area covered by the BackBufferCopy. Only used if [member copy_mode] is "
+"The area covered by the [BackBufferCopy]. Only used if [member copy_mode] is "
"[constant COPY_MODE_RECT]."
msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
-"Disables the buffering mode. This means the BackBufferCopy node will "
+"Disables the buffering mode. This means the [BackBufferCopy] node will "
"directly use the portion of screen it covers."
msgstr ""
#: doc/classes/BackBufferCopy.xml
-msgid "BackBufferCopy buffers a rectangular region."
+msgid "[BackBufferCopy] buffers a rectangular region."
msgstr ""
#: doc/classes/BackBufferCopy.xml
-msgid "BackBufferCopy buffers the entire screen."
+msgid "[BackBufferCopy] buffers the entire screen."
msgstr ""
#: doc/classes/BakedLightmap.xml
@@ -19278,6 +19315,14 @@ msgid "Cylinder shape for collisions."
msgstr ""
#: doc/classes/CylinderShape.xml
+msgid ""
+"Cylinder shape for collisions.\n"
+"[b]Note:[/b] When using GodotPhysics instead of the default Bullet physics "
+"engine, there are several known bugs with cylinder collision shapes. Using "
+"[CapsuleShape] or [BoxShape] instead is recommended."
+msgstr ""
+
+#: doc/classes/CylinderShape.xml
msgid "The cylinder's height."
msgstr ""
@@ -22110,7 +22155,10 @@ msgid ""
"[/codeblock]\n"
"[b]Note:[/b] The script is run in the Editor context, which means the output "
"is visible in the console window started with the Editor (stdout) instead of "
-"the usual Godot [b]Output[/b] dock."
+"the usual Godot [b]Output[/b] dock.\n"
+"[b]Note:[/b] EditorScript is reference counted, meaning it is destroyed when "
+"nothing references it. This can cause errors during asynchronous operations "
+"if there are no references to the script."
msgstr ""
#: doc/classes/EditorScript.xml
@@ -32822,7 +32870,9 @@ msgid ""
"The size of the light in Godot units. Only considered in baked lightmaps and "
"only if [member light_bake_mode] is set to [constant BAKE_ALL]. Increasing "
"this value will make the shadows appear blurrier. This can be used to "
-"simulate area lights to an extent."
+"simulate area lights to an extent.\n"
+"[b]Note:[/b] [member light_size] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/Light.xml
@@ -36120,7 +36170,10 @@ msgid ""
"use the [method get_next_location] function once every physics frame to "
"update the internal path logic of the NavigationAgent. The returned vector "
"position from this function should be used as the next movement position for "
-"the agent's parent Node."
+"the agent's parent Node.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues."
msgstr ""
#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
@@ -36368,7 +36421,10 @@ msgid ""
"use the [method get_next_location] function once every physics frame to "
"update the internal path logic of the NavigationAgent. The returned vector "
"position from this function should be used as the next movement position for "
-"the agent's parent Node."
+"the agent's parent Node.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues."
msgstr ""
#: doc/classes/NavigationAgent2D.xml
@@ -37078,6 +37134,9 @@ msgid ""
"modified velocity as-is might lead to pushing and agent outside of a "
"navigable area. This is a limitation of the collision avoidance system, any "
"more complex situation may require the use of the physics engine.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues.\n"
"This server keeps tracks of any call and executes them during the sync "
"phase. This means that you can request any change to the map, using any "
"thread, without worrying."
@@ -39884,7 +39943,9 @@ msgid ""
"The light's radius. Note that the effectively lit area may appear to be "
"smaller depending on the [member omni_attenuation] in use. No matter the "
"[member omni_attenuation] in use, the light will never reach anything "
-"outside this radius."
+"outside this radius.\n"
+"[b]Note:[/b] [member omni_range] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -40395,11 +40456,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] cache data directory according to the operating "
-"system's standards. On desktop platforms, this path can be overridden by "
-"setting the [code]XDG_CACHE_HOME[/code] environment variable before starting "
-"the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in "
-"Godot projects[/url] in the documentation for more information. See also "
-"[method get_config_dir] and [method get_data_dir].\n"
+"system's standards. On Linux, this path can be overridden by setting the "
+"[code]XDG_CACHE_HOME[/code] environment variable before starting the "
+"project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot "
+"projects[/url] in the documentation for more information. See also [method "
+"get_config_dir] and [method get_data_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -40433,11 +40494,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] user configuration directory according to the "
-"operating system's standards. On desktop platforms, this path can be "
-"overridden by setting the [code]XDG_CONFIG_HOME[/code] environment variable "
-"before starting the project. See [url=$DOCS_URL/tutorials/io/data_paths."
-"html]File paths in Godot projects[/url] in the documentation for more "
-"information. See also [method get_cache_dir] and [method get_data_dir].\n"
+"operating system's standards. On Linux, this path can be overridden by "
+"setting the [code]XDG_CONFIG_HOME[/code] environment variable before "
+"starting the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File "
+"paths in Godot projects[/url] in the documentation for more information. See "
+"also [method get_cache_dir] and [method get_data_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -40459,11 +40520,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] user data directory according to the operating "
-"system's standards. On desktop platforms, this path can be overridden by "
-"setting the [code]XDG_DATA_HOME[/code] environment variable before starting "
-"the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in "
-"Godot projects[/url] in the documentation for more information. See also "
-"[method get_cache_dir] and [method get_config_dir].\n"
+"system's standards. On Linux, this path can be overridden by setting the "
+"[code]XDG_DATA_HOME[/code] environment variable before starting the project. "
+"See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot "
+"projects[/url] in the documentation for more information. See also [method "
+"get_cache_dir] and [method get_config_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -42310,6 +42371,16 @@ msgid "Particle systems (2D)"
msgstr ""
#: doc/classes/Particles2D.xml
+msgid "2D Particles Demo"
+msgstr ""
+
+#: doc/classes/Particles2D.xml
+msgid ""
+"2D Dodge The Creeps Demo (uses GPUParticles2D for the trail behind the "
+"player)"
+msgstr ""
+
+#: doc/classes/Particles2D.xml
msgid "Returns a rectangle containing the positions of all existing particles."
msgstr ""
@@ -49902,15 +49973,22 @@ msgstr ""
#: doc/classes/ProjectSettings.xml
msgid ""
"If [code]true[/code], uses a fast post-processing filter to make banding "
-"significantly less visible. In some cases, debanding may introduce a "
-"slightly noticeable dithering pattern. It's recommended to enable debanding "
-"only when actually needed since the dithering pattern will make lossless-"
-"compressed screenshots larger.\n"
+"significantly less visible in 3D. 2D rendering is [i]not[/i] affected by "
+"debanding unless the [member Environment.background_mode] is [constant "
+"Environment.BG_CANVAS]. In this case, [member rendering/quality/"
+"intended_usage/framebuffer_allocation] must also be set to [b]3D[/b].\n"
+"In some cases, debanding may introduce a slightly noticeable dithering "
+"pattern. It's recommended to enable debanding only when actually needed "
+"since the dithering pattern will make lossless-compressed screenshots "
+"larger.\n"
"[b]Note:[/b] Only available on the GLES3 backend. [member rendering/quality/"
"depth/hdr] must also be [code]true[/code] for debanding to be effective.\n"
"[b]Note:[/b] There are known issues with debanding breaking rendering on "
"mobile platforms. Due to this, it is recommended to leave this option "
-"disabled when targeting mobile platforms."
+"disabled when targeting mobile platforms.\n"
+"[b]Note:[/b] This property is only read when the project starts. To set "
+"debanding at run-time, set [member Viewport.debanding] on the root "
+"[Viewport] instead."
msgstr ""
#: doc/classes/ProjectSettings.xml
@@ -51506,17 +51584,28 @@ msgstr ""
#: modules/regex/doc_classes/RegEx.xml
msgid ""
"Searches the text for the compiled pattern. Returns a [RegExMatch] container "
-"of the first matching result if found, otherwise [code]null[/code]. The "
-"region to search within can be specified without modifying where the start "
-"and end anchor would be."
+"of the first matching result if found, otherwise [code]null[/code].\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegEx.xml
msgid ""
"Searches the text for the compiled pattern. Returns an array of [RegExMatch] "
"containers for each non-overlapping result. If no results were found, an "
-"empty array is returned instead. The region to search within can be "
-"specified without modifying where the start and end anchor would be."
+"empty array is returned instead.\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegEx.xml
@@ -51525,8 +51614,14 @@ msgid ""
"specified string. Escapes and backreferences such as [code]$1[/code] and "
"[code]$name[/code] are expanded and resolved. By default, only the first "
"instance is replaced, but it can be changed for all instances (global "
-"replacement). The region to search within can be specified without modifying "
-"where the start and end anchor would be."
+"replacement).\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegExMatch.xml
@@ -54241,7 +54336,11 @@ msgid "Call a group immediately (calls are normally made on idle)."
msgstr ""
#: doc/classes/SceneTree.xml
-msgid "Call a group only once even if the call is executed many times."
+msgid ""
+"Call a group only once even if the call is executed many times.\n"
+"[b]Note:[/b] Arguments are not taken into account when deciding whether the "
+"call is unique or not. Therefore when the same method is called with "
+"different arguments, only the first call will be performed."
msgstr ""
#: doc/classes/SceneTree.xml
@@ -56078,7 +56177,9 @@ msgid ""
"[b]Note:[/b] Mixed negative scales in 3D are not decomposable from the "
"transformation matrix. Due to the way scale is represented with "
"transformation matrices in Godot, the scale values will either be all "
-"positive or all negative."
+"positive or all negative.\n"
+"[b]Note:[/b] Not all nodes are visually scaled by the [member scale] "
+"property. For example, [Light]s are not visually affected by [member scale]."
msgstr ""
#: doc/classes/Spatial.xml
@@ -57456,7 +57557,10 @@ msgid ""
msgstr ""
#: doc/classes/SpotLight.xml
-msgid "The spotlight's angle in degrees."
+msgid ""
+"The spotlight's angle in degrees.\n"
+"[b]Note:[/b] [member spot_angle] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/SpotLight.xml
@@ -57472,7 +57576,9 @@ msgid ""
"The maximal range that can be reached by the spotlight. Note that the "
"effectively lit area may appear to be smaller depending on the [member "
"spot_attenuation] in use. No matter the [member spot_attenuation] in use, "
-"the light will never reach anything outside this range."
+"the light will never reach anything outside this range.\n"
+"[b]Note:[/b] [member spot_range] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/SpringArm.xml
@@ -66709,10 +66815,15 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
"If [code]true[/code], uses a fast post-processing filter to make banding "
-"significantly less visible. In some cases, debanding may introduce a "
-"slightly noticeable dithering pattern. It's recommended to enable debanding "
-"only when actually needed since the dithering pattern will make lossless-"
-"compressed screenshots larger.\n"
+"significantly less visible in 3D. 2D rendering is [i]not[/i] affected by "
+"debanding unless the [member Environment.background_mode] is [constant "
+"Environment.BG_CANVAS]. In this case, [member usage] must also be set to "
+"[constant USAGE_3D]. See also [member ProjectSettings.rendering/quality/"
+"filters/use_debanding].\n"
+"In some cases, debanding may introduce a slightly noticeable dithering "
+"pattern. It's recommended to enable debanding only when actually needed "
+"since the dithering pattern will make lossless-compressed screenshots "
+"larger.\n"
"[b]Note:[/b] Only available on the GLES3 backend. [member hdr] must also be "
"[code]true[/code] for debanding to be effective."
msgstr ""
@@ -66723,8 +66834,8 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
-"If [code]true[/code], the viewport will disable 3D rendering. For actual "
-"disabling use [code]usage[/code]."
+"If [code]true[/code], the viewport will disable 3D rendering. To actually "
+"disable allocation of 3D buffers, set [member usage] instead."
msgstr ""
#: doc/classes/Viewport.xml
@@ -66876,7 +66987,9 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
-"The rendering mode of viewport.\n"
+"The viewport's rendering mode. This controls which buffers are allocated for "
+"the viewport (2D only, or 2D + 3D). 2D-only options can reduce memory usage "
+"and improve performance slightly, especially on low-end devices.\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."
@@ -67408,6 +67521,22 @@ msgid ""
"render object this [VisualInstance] is set to."
msgstr ""
+#: doc/classes/VisualInstance.xml
+msgid ""
+"The sorting offset used by this [VisualInstance]. Adjusting it to a higher "
+"value will make the [VisualInstance] reliably draw on top of other "
+"[VisualInstance]s that are otherwise positioned at the same spot."
+msgstr ""
+
+#: doc/classes/VisualInstance.xml
+msgid ""
+"If [code]true[/code], the object is sorted based on the [AABB] center. "
+"Sorted based on the global position otherwise.\n"
+"The [AABB] center based sorting is generally more accurate for 3D models. "
+"The position based sorting instead allows to better control the drawing "
+"order when working with [Particles] and [CPUParticles]."
+msgstr ""
+
#: modules/visual_script/doc_classes/VisualScript.xml
msgid "A script implemented in the Visual Script programming environment."
msgstr ""
diff --git a/doc/translations/fa.po b/doc/translations/fa.po
index 31077d1e54..787c7ff937 100644
--- a/doc/translations/fa.po
+++ b/doc/translations/fa.po
@@ -698,8 +698,10 @@ msgstr ""
"[/ codeblock]"
#: modules/gdscript/doc_classes/@GDScript.xml
+#, fuzzy
msgid ""
-"Returns an array of dictionaries representing the current call stack.\n"
+"Returns an array of dictionaries representing the current call stack. See "
+"also [method print_stack].\n"
"[codeblock]\n"
"func _ready():\n"
" foo()\n"
@@ -714,7 +716,11 @@ msgid ""
"[codeblock]\n"
"[{function:bar, line:12, source:res://script.gd}, {function:foo, line:9, "
"source:res://script.gd}, {function:_ready, line:6, source:res://script.gd}]\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] [method get_stack] only works if the running instance is "
+"connected to a debugging server (i.e. an editor instance). [method "
+"get_stack] will not work in projects exported in release mode, or in "
+"projects exported in debug mode if not connected to a debugging server."
msgstr ""
"آرایه ای از ÙØ±Ù‡Ù†Ú¯ لغت ها را نشان Ù…ÛŒ دهد Ú©Ù‡ پشته تماس ÙØ¹Ù„ÛŒ را نشان Ù…ÛŒ دهد.\n"
"[codeblock]\n"
@@ -1292,12 +1298,16 @@ msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
-"Prints a stack track at code location, only works when running with debugger "
-"turned on.\n"
+"Prints a stack trace at the current code location. See also [method "
+"get_stack].\n"
"Output in the console would look something like this:\n"
"[codeblock]\n"
"Frame 0 - res://test.gd:16 in function '_process'\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] [method print_stack] only works if the running instance is "
+"connected to a debugging server (i.e. an editor instance). [method "
+"print_stack] will not work in projects exported in release mode, or in "
+"projects exported in debug mode if not connected to a debugging server."
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -3920,6 +3930,26 @@ msgid "Hints that an image is compressed using lossless compression."
msgstr ""
#: doc/classes/@GlobalScope.xml
+msgid ""
+"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:\n"
+"[codeblock]\n"
+"hint_string = \"%s:\" % [TYPE_INT] # Array of inteters.\n"
+"hint_string = \"%s:%s:\" % [TYPE_ARRAY, TYPE_REAL] # Two-dimensional array "
+"of floats.\n"
+"hint_string = \"%s/%s:Resource\" % [TYPE_OBJECT, TYPE_OBJECT] # Array of "
+"resources.\n"
+"hint_string = \"%s:%s/%s:Resource\" % [TYPE_ARRAY, TYPE_OBJECT, TYPE_OBJECT] "
+"# Two-dimensional array of resources.\n"
+"[/codeblock]\n"
+"[b]Note:[/b] The final colon is required to specify for properly detecting "
+"built-in types."
+msgstr ""
+
+#: doc/classes/@GlobalScope.xml
msgid "The property is serialized and saved in the scene file (default)."
msgstr ""
@@ -4604,8 +4634,7 @@ msgstr ""
#: doc/classes/AudioStreamPlayer.xml doc/classes/Button.xml
#: doc/classes/CanvasLayer.xml doc/classes/CollisionShape2D.xml
#: doc/classes/ColorRect.xml doc/classes/Input.xml doc/classes/InputEvent.xml
-#: doc/classes/InputEventAction.xml doc/classes/Label.xml
-#: doc/classes/Particles2D.xml doc/classes/Timer.xml
+#: doc/classes/InputEventAction.xml doc/classes/Label.xml doc/classes/Timer.xml
#: doc/classes/VisibilityNotifier2D.xml
msgid "2D Dodge The Creeps Demo"
msgstr ""
@@ -7522,7 +7551,10 @@ msgid ""
"var array = []\n"
"array.resize(10)\n"
"array.fill(0) # Initialize the 10 elements to 0.\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] If [code]value[/code] is of a reference type ([Object]-derived, "
+"[Array], [Dictionary], etc.) then the array is filled with the references to "
+"the same object, i.e. no duplicates are created."
msgstr ""
#: doc/classes/Array.xml doc/classes/PoolByteArray.xml
@@ -7707,6 +7739,9 @@ msgstr ""
#: doc/classes/Array.xml
msgid ""
"Sorts the array.\n"
+"[b]Note:[/b] The sorting algorithm used is not [url=https://en.wikipedia.org/"
+"wiki/Sorting_algorithm#Stability]stable[/url]. This means that values "
+"considered equal may have their order changed when using [method sort].\n"
"[b]Note:[/b] Strings are sorted in alphabetical order (as opposed to natural "
"order). This may lead to unexpected behavior when sorting an array of "
"strings ending with a sequence of numbers. Consider the following example:\n"
@@ -7726,9 +7761,13 @@ msgid ""
"For two elements [code]a[/code] and [code]b[/code], if the given method "
"returns [code]true[/code], element [code]b[/code] will be after element "
"[code]a[/code] in the array.\n"
+"[b]Note:[/b] The sorting algorithm used is not [url=https://en.wikipedia.org/"
+"wiki/Sorting_algorithm#Stability]stable[/url]. This means that values "
+"considered equal may have their order changed when using [method "
+"sort_custom].\n"
"[b]Note:[/b] You cannot randomize the return value as the heapsort algorithm "
-"expects a deterministic result. Doing so will result in unexpected "
-"behavior.\n"
+"expects a deterministic result. Randomizing the return value will result in "
+"unexpected behavior.\n"
"[codeblock]\n"
"class MyCustomSorter:\n"
" static func sort_ascending(a, b):\n"
@@ -10366,10 +10405,9 @@ msgstr ""
#: doc/classes/AudioStreamGeneratorPlayback.xml
msgid ""
-"Returns the number of audio data frames left to play. If this returned "
-"number reaches [code]0[/code], the audio will stop playing until frames are "
-"added again. Therefore, make sure your script can always generate and push "
-"new audio frames fast enough to avoid audio cracking."
+"Returns the number of frames that can be pushed to the audio sample data "
+"buffer without overflowing it. If the result is [code]0[/code], the buffer "
+"is full."
msgstr ""
#: doc/classes/AudioStreamGeneratorPlayback.xml
@@ -10901,14 +10939,14 @@ msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
"Node for back-buffering the currently-displayed screen. The region defined "
-"in the BackBufferCopy node is buffered with the content of the screen it "
+"in the [BackBufferCopy] node is buffered with the content of the screen it "
"covers, or the entire screen according to the copy mode set. Use the "
"[code]texture(SCREEN_TEXTURE, ...)[/code] function in your shader scripts to "
"access the buffer.\n"
"[b]Note:[/b] Since this node inherits from [Node2D] (and not [Control]), "
"anchors and margins won't apply to child [Control]-derived nodes. This can "
"be problematic when resizing the window. To avoid this, add [Control]-"
-"derived nodes as [i]siblings[/i] to the BackBufferCopy node instead of "
+"derived nodes as [i]siblings[/i] to the [BackBufferCopy] node instead of "
"adding them as children."
msgstr ""
@@ -10918,22 +10956,22 @@ msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
-"The area covered by the BackBufferCopy. Only used if [member copy_mode] is "
+"The area covered by the [BackBufferCopy]. Only used if [member copy_mode] is "
"[constant COPY_MODE_RECT]."
msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
-"Disables the buffering mode. This means the BackBufferCopy node will "
+"Disables the buffering mode. This means the [BackBufferCopy] node will "
"directly use the portion of screen it covers."
msgstr ""
#: doc/classes/BackBufferCopy.xml
-msgid "BackBufferCopy buffers a rectangular region."
+msgid "[BackBufferCopy] buffers a rectangular region."
msgstr ""
#: doc/classes/BackBufferCopy.xml
-msgid "BackBufferCopy buffers the entire screen."
+msgid "[BackBufferCopy] buffers the entire screen."
msgstr ""
#: doc/classes/BakedLightmap.xml
@@ -19713,6 +19751,14 @@ msgid "Cylinder shape for collisions."
msgstr ""
#: doc/classes/CylinderShape.xml
+msgid ""
+"Cylinder shape for collisions.\n"
+"[b]Note:[/b] When using GodotPhysics instead of the default Bullet physics "
+"engine, there are several known bugs with cylinder collision shapes. Using "
+"[CapsuleShape] or [BoxShape] instead is recommended."
+msgstr ""
+
+#: doc/classes/CylinderShape.xml
msgid "The cylinder's height."
msgstr ""
@@ -22545,7 +22591,10 @@ msgid ""
"[/codeblock]\n"
"[b]Note:[/b] The script is run in the Editor context, which means the output "
"is visible in the console window started with the Editor (stdout) instead of "
-"the usual Godot [b]Output[/b] dock."
+"the usual Godot [b]Output[/b] dock.\n"
+"[b]Note:[/b] EditorScript is reference counted, meaning it is destroyed when "
+"nothing references it. This can cause errors during asynchronous operations "
+"if there are no references to the script."
msgstr ""
#: doc/classes/EditorScript.xml
@@ -33260,7 +33309,9 @@ msgid ""
"The size of the light in Godot units. Only considered in baked lightmaps and "
"only if [member light_bake_mode] is set to [constant BAKE_ALL]. Increasing "
"this value will make the shadows appear blurrier. This can be used to "
-"simulate area lights to an extent."
+"simulate area lights to an extent.\n"
+"[b]Note:[/b] [member light_size] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/Light.xml
@@ -36564,7 +36615,10 @@ msgid ""
"use the [method get_next_location] function once every physics frame to "
"update the internal path logic of the NavigationAgent. The returned vector "
"position from this function should be used as the next movement position for "
-"the agent's parent Node."
+"the agent's parent Node.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues."
msgstr ""
#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
@@ -36812,7 +36866,10 @@ msgid ""
"use the [method get_next_location] function once every physics frame to "
"update the internal path logic of the NavigationAgent. The returned vector "
"position from this function should be used as the next movement position for "
-"the agent's parent Node."
+"the agent's parent Node.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues."
msgstr ""
#: doc/classes/NavigationAgent2D.xml
@@ -37522,6 +37579,9 @@ msgid ""
"modified velocity as-is might lead to pushing and agent outside of a "
"navigable area. This is a limitation of the collision avoidance system, any "
"more complex situation may require the use of the physics engine.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues.\n"
"This server keeps tracks of any call and executes them during the sync "
"phase. This means that you can request any change to the map, using any "
"thread, without worrying."
@@ -40328,7 +40388,9 @@ msgid ""
"The light's radius. Note that the effectively lit area may appear to be "
"smaller depending on the [member omni_attenuation] in use. No matter the "
"[member omni_attenuation] in use, the light will never reach anything "
-"outside this radius."
+"outside this radius.\n"
+"[b]Note:[/b] [member omni_range] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -40839,11 +40901,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] cache data directory according to the operating "
-"system's standards. On desktop platforms, this path can be overridden by "
-"setting the [code]XDG_CACHE_HOME[/code] environment variable before starting "
-"the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in "
-"Godot projects[/url] in the documentation for more information. See also "
-"[method get_config_dir] and [method get_data_dir].\n"
+"system's standards. On Linux, this path can be overridden by setting the "
+"[code]XDG_CACHE_HOME[/code] environment variable before starting the "
+"project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot "
+"projects[/url] in the documentation for more information. See also [method "
+"get_config_dir] and [method get_data_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -40877,11 +40939,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] user configuration directory according to the "
-"operating system's standards. On desktop platforms, this path can be "
-"overridden by setting the [code]XDG_CONFIG_HOME[/code] environment variable "
-"before starting the project. See [url=$DOCS_URL/tutorials/io/data_paths."
-"html]File paths in Godot projects[/url] in the documentation for more "
-"information. See also [method get_cache_dir] and [method get_data_dir].\n"
+"operating system's standards. On Linux, this path can be overridden by "
+"setting the [code]XDG_CONFIG_HOME[/code] environment variable before "
+"starting the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File "
+"paths in Godot projects[/url] in the documentation for more information. See "
+"also [method get_cache_dir] and [method get_data_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -40903,11 +40965,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] user data directory according to the operating "
-"system's standards. On desktop platforms, this path can be overridden by "
-"setting the [code]XDG_DATA_HOME[/code] environment variable before starting "
-"the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in "
-"Godot projects[/url] in the documentation for more information. See also "
-"[method get_cache_dir] and [method get_config_dir].\n"
+"system's standards. On Linux, this path can be overridden by setting the "
+"[code]XDG_DATA_HOME[/code] environment variable before starting the project. "
+"See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot "
+"projects[/url] in the documentation for more information. See also [method "
+"get_cache_dir] and [method get_config_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -42766,6 +42828,16 @@ msgid "Particle systems (2D)"
msgstr ""
#: doc/classes/Particles2D.xml
+msgid "2D Particles Demo"
+msgstr ""
+
+#: doc/classes/Particles2D.xml
+msgid ""
+"2D Dodge The Creeps Demo (uses GPUParticles2D for the trail behind the "
+"player)"
+msgstr ""
+
+#: doc/classes/Particles2D.xml
msgid "Returns a rectangle containing the positions of all existing particles."
msgstr ""
@@ -50358,15 +50430,22 @@ msgstr ""
#: doc/classes/ProjectSettings.xml
msgid ""
"If [code]true[/code], uses a fast post-processing filter to make banding "
-"significantly less visible. In some cases, debanding may introduce a "
-"slightly noticeable dithering pattern. It's recommended to enable debanding "
-"only when actually needed since the dithering pattern will make lossless-"
-"compressed screenshots larger.\n"
+"significantly less visible in 3D. 2D rendering is [i]not[/i] affected by "
+"debanding unless the [member Environment.background_mode] is [constant "
+"Environment.BG_CANVAS]. In this case, [member rendering/quality/"
+"intended_usage/framebuffer_allocation] must also be set to [b]3D[/b].\n"
+"In some cases, debanding may introduce a slightly noticeable dithering "
+"pattern. It's recommended to enable debanding only when actually needed "
+"since the dithering pattern will make lossless-compressed screenshots "
+"larger.\n"
"[b]Note:[/b] Only available on the GLES3 backend. [member rendering/quality/"
"depth/hdr] must also be [code]true[/code] for debanding to be effective.\n"
"[b]Note:[/b] There are known issues with debanding breaking rendering on "
"mobile platforms. Due to this, it is recommended to leave this option "
-"disabled when targeting mobile platforms."
+"disabled when targeting mobile platforms.\n"
+"[b]Note:[/b] This property is only read when the project starts. To set "
+"debanding at run-time, set [member Viewport.debanding] on the root "
+"[Viewport] instead."
msgstr ""
#: doc/classes/ProjectSettings.xml
@@ -51966,17 +52045,28 @@ msgstr ""
#: modules/regex/doc_classes/RegEx.xml
msgid ""
"Searches the text for the compiled pattern. Returns a [RegExMatch] container "
-"of the first matching result if found, otherwise [code]null[/code]. The "
-"region to search within can be specified without modifying where the start "
-"and end anchor would be."
+"of the first matching result if found, otherwise [code]null[/code].\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegEx.xml
msgid ""
"Searches the text for the compiled pattern. Returns an array of [RegExMatch] "
"containers for each non-overlapping result. If no results were found, an "
-"empty array is returned instead. The region to search within can be "
-"specified without modifying where the start and end anchor would be."
+"empty array is returned instead.\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegEx.xml
@@ -51985,8 +52075,14 @@ msgid ""
"specified string. Escapes and backreferences such as [code]$1[/code] and "
"[code]$name[/code] are expanded and resolved. By default, only the first "
"instance is replaced, but it can be changed for all instances (global "
-"replacement). The region to search within can be specified without modifying "
-"where the start and end anchor would be."
+"replacement).\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegExMatch.xml
@@ -54701,7 +54797,11 @@ msgid "Call a group immediately (calls are normally made on idle)."
msgstr ""
#: doc/classes/SceneTree.xml
-msgid "Call a group only once even if the call is executed many times."
+msgid ""
+"Call a group only once even if the call is executed many times.\n"
+"[b]Note:[/b] Arguments are not taken into account when deciding whether the "
+"call is unique or not. Therefore when the same method is called with "
+"different arguments, only the first call will be performed."
msgstr ""
#: doc/classes/SceneTree.xml
@@ -56538,7 +56638,9 @@ msgid ""
"[b]Note:[/b] Mixed negative scales in 3D are not decomposable from the "
"transformation matrix. Due to the way scale is represented with "
"transformation matrices in Godot, the scale values will either be all "
-"positive or all negative."
+"positive or all negative.\n"
+"[b]Note:[/b] Not all nodes are visually scaled by the [member scale] "
+"property. For example, [Light]s are not visually affected by [member scale]."
msgstr ""
#: doc/classes/Spatial.xml
@@ -57916,7 +58018,10 @@ msgid ""
msgstr ""
#: doc/classes/SpotLight.xml
-msgid "The spotlight's angle in degrees."
+msgid ""
+"The spotlight's angle in degrees.\n"
+"[b]Note:[/b] [member spot_angle] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/SpotLight.xml
@@ -57932,7 +58037,9 @@ msgid ""
"The maximal range that can be reached by the spotlight. Note that the "
"effectively lit area may appear to be smaller depending on the [member "
"spot_attenuation] in use. No matter the [member spot_attenuation] in use, "
-"the light will never reach anything outside this range."
+"the light will never reach anything outside this range.\n"
+"[b]Note:[/b] [member spot_range] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/SpringArm.xml
@@ -67169,10 +67276,15 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
"If [code]true[/code], uses a fast post-processing filter to make banding "
-"significantly less visible. In some cases, debanding may introduce a "
-"slightly noticeable dithering pattern. It's recommended to enable debanding "
-"only when actually needed since the dithering pattern will make lossless-"
-"compressed screenshots larger.\n"
+"significantly less visible in 3D. 2D rendering is [i]not[/i] affected by "
+"debanding unless the [member Environment.background_mode] is [constant "
+"Environment.BG_CANVAS]. In this case, [member usage] must also be set to "
+"[constant USAGE_3D]. See also [member ProjectSettings.rendering/quality/"
+"filters/use_debanding].\n"
+"In some cases, debanding may introduce a slightly noticeable dithering "
+"pattern. It's recommended to enable debanding only when actually needed "
+"since the dithering pattern will make lossless-compressed screenshots "
+"larger.\n"
"[b]Note:[/b] Only available on the GLES3 backend. [member hdr] must also be "
"[code]true[/code] for debanding to be effective."
msgstr ""
@@ -67183,8 +67295,8 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
-"If [code]true[/code], the viewport will disable 3D rendering. For actual "
-"disabling use [code]usage[/code]."
+"If [code]true[/code], the viewport will disable 3D rendering. To actually "
+"disable allocation of 3D buffers, set [member usage] instead."
msgstr ""
#: doc/classes/Viewport.xml
@@ -67336,7 +67448,9 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
-"The rendering mode of viewport.\n"
+"The viewport's rendering mode. This controls which buffers are allocated for "
+"the viewport (2D only, or 2D + 3D). 2D-only options can reduce memory usage "
+"and improve performance slightly, especially on low-end devices.\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."
@@ -67868,6 +67982,22 @@ msgid ""
"render object this [VisualInstance] is set to."
msgstr ""
+#: doc/classes/VisualInstance.xml
+msgid ""
+"The sorting offset used by this [VisualInstance]. Adjusting it to a higher "
+"value will make the [VisualInstance] reliably draw on top of other "
+"[VisualInstance]s that are otherwise positioned at the same spot."
+msgstr ""
+
+#: doc/classes/VisualInstance.xml
+msgid ""
+"If [code]true[/code], the object is sorted based on the [AABB] center. "
+"Sorted based on the global position otherwise.\n"
+"The [AABB] center based sorting is generally more accurate for 3D models. "
+"The position based sorting instead allows to better control the drawing "
+"order when working with [Particles] and [CPUParticles]."
+msgstr ""
+
#: modules/visual_script/doc_classes/VisualScript.xml
msgid "A script implemented in the Visual Script programming environment."
msgstr ""
diff --git a/doc/translations/fi.po b/doc/translations/fi.po
index 811d77f710..fc517a6ff5 100644
--- a/doc/translations/fi.po
+++ b/doc/translations/fi.po
@@ -550,7 +550,8 @@ msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
-"Returns an array of dictionaries representing the current call stack.\n"
+"Returns an array of dictionaries representing the current call stack. See "
+"also [method print_stack].\n"
"[codeblock]\n"
"func _ready():\n"
" foo()\n"
@@ -565,7 +566,11 @@ msgid ""
"[codeblock]\n"
"[{function:bar, line:12, source:res://script.gd}, {function:foo, line:9, "
"source:res://script.gd}, {function:_ready, line:6, source:res://script.gd}]\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] [method get_stack] only works if the running instance is "
+"connected to a debugging server (i.e. an editor instance). [method "
+"get_stack] will not work in projects exported in release mode, or in "
+"projects exported in debug mode if not connected to a debugging server."
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -938,12 +943,16 @@ msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
-"Prints a stack track at code location, only works when running with debugger "
-"turned on.\n"
+"Prints a stack trace at the current code location. See also [method "
+"get_stack].\n"
"Output in the console would look something like this:\n"
"[codeblock]\n"
"Frame 0 - res://test.gd:16 in function '_process'\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] [method print_stack] only works if the running instance is "
+"connected to a debugging server (i.e. an editor instance). [method "
+"print_stack] will not work in projects exported in release mode, or in "
+"projects exported in debug mode if not connected to a debugging server."
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -3554,6 +3563,26 @@ msgid "Hints that an image is compressed using lossless compression."
msgstr ""
#: doc/classes/@GlobalScope.xml
+msgid ""
+"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:\n"
+"[codeblock]\n"
+"hint_string = \"%s:\" % [TYPE_INT] # Array of inteters.\n"
+"hint_string = \"%s:%s:\" % [TYPE_ARRAY, TYPE_REAL] # Two-dimensional array "
+"of floats.\n"
+"hint_string = \"%s/%s:Resource\" % [TYPE_OBJECT, TYPE_OBJECT] # Array of "
+"resources.\n"
+"hint_string = \"%s:%s/%s:Resource\" % [TYPE_ARRAY, TYPE_OBJECT, TYPE_OBJECT] "
+"# Two-dimensional array of resources.\n"
+"[/codeblock]\n"
+"[b]Note:[/b] The final colon is required to specify for properly detecting "
+"built-in types."
+msgstr ""
+
+#: doc/classes/@GlobalScope.xml
msgid "The property is serialized and saved in the scene file (default)."
msgstr ""
@@ -4238,8 +4267,7 @@ msgstr ""
#: doc/classes/AudioStreamPlayer.xml doc/classes/Button.xml
#: doc/classes/CanvasLayer.xml doc/classes/CollisionShape2D.xml
#: doc/classes/ColorRect.xml doc/classes/Input.xml doc/classes/InputEvent.xml
-#: doc/classes/InputEventAction.xml doc/classes/Label.xml
-#: doc/classes/Particles2D.xml doc/classes/Timer.xml
+#: doc/classes/InputEventAction.xml doc/classes/Label.xml doc/classes/Timer.xml
#: doc/classes/VisibilityNotifier2D.xml
msgid "2D Dodge The Creeps Demo"
msgstr ""
@@ -7164,7 +7192,10 @@ msgid ""
"var array = []\n"
"array.resize(10)\n"
"array.fill(0) # Initialize the 10 elements to 0.\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] If [code]value[/code] is of a reference type ([Object]-derived, "
+"[Array], [Dictionary], etc.) then the array is filled with the references to "
+"the same object, i.e. no duplicates are created."
msgstr ""
#: doc/classes/Array.xml doc/classes/PoolByteArray.xml
@@ -7349,6 +7380,9 @@ msgstr ""
#: doc/classes/Array.xml
msgid ""
"Sorts the array.\n"
+"[b]Note:[/b] The sorting algorithm used is not [url=https://en.wikipedia.org/"
+"wiki/Sorting_algorithm#Stability]stable[/url]. This means that values "
+"considered equal may have their order changed when using [method sort].\n"
"[b]Note:[/b] Strings are sorted in alphabetical order (as opposed to natural "
"order). This may lead to unexpected behavior when sorting an array of "
"strings ending with a sequence of numbers. Consider the following example:\n"
@@ -7368,9 +7402,13 @@ msgid ""
"For two elements [code]a[/code] and [code]b[/code], if the given method "
"returns [code]true[/code], element [code]b[/code] will be after element "
"[code]a[/code] in the array.\n"
+"[b]Note:[/b] The sorting algorithm used is not [url=https://en.wikipedia.org/"
+"wiki/Sorting_algorithm#Stability]stable[/url]. This means that values "
+"considered equal may have their order changed when using [method "
+"sort_custom].\n"
"[b]Note:[/b] You cannot randomize the return value as the heapsort algorithm "
-"expects a deterministic result. Doing so will result in unexpected "
-"behavior.\n"
+"expects a deterministic result. Randomizing the return value will result in "
+"unexpected behavior.\n"
"[codeblock]\n"
"class MyCustomSorter:\n"
" static func sort_ascending(a, b):\n"
@@ -10009,10 +10047,9 @@ msgstr ""
#: doc/classes/AudioStreamGeneratorPlayback.xml
msgid ""
-"Returns the number of audio data frames left to play. If this returned "
-"number reaches [code]0[/code], the audio will stop playing until frames are "
-"added again. Therefore, make sure your script can always generate and push "
-"new audio frames fast enough to avoid audio cracking."
+"Returns the number of frames that can be pushed to the audio sample data "
+"buffer without overflowing it. If the result is [code]0[/code], the buffer "
+"is full."
msgstr ""
#: doc/classes/AudioStreamGeneratorPlayback.xml
@@ -10544,14 +10581,14 @@ msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
"Node for back-buffering the currently-displayed screen. The region defined "
-"in the BackBufferCopy node is buffered with the content of the screen it "
+"in the [BackBufferCopy] node is buffered with the content of the screen it "
"covers, or the entire screen according to the copy mode set. Use the "
"[code]texture(SCREEN_TEXTURE, ...)[/code] function in your shader scripts to "
"access the buffer.\n"
"[b]Note:[/b] Since this node inherits from [Node2D] (and not [Control]), "
"anchors and margins won't apply to child [Control]-derived nodes. This can "
"be problematic when resizing the window. To avoid this, add [Control]-"
-"derived nodes as [i]siblings[/i] to the BackBufferCopy node instead of "
+"derived nodes as [i]siblings[/i] to the [BackBufferCopy] node instead of "
"adding them as children."
msgstr ""
@@ -10561,22 +10598,22 @@ msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
-"The area covered by the BackBufferCopy. Only used if [member copy_mode] is "
+"The area covered by the [BackBufferCopy]. Only used if [member copy_mode] is "
"[constant COPY_MODE_RECT]."
msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
-"Disables the buffering mode. This means the BackBufferCopy node will "
+"Disables the buffering mode. This means the [BackBufferCopy] node will "
"directly use the portion of screen it covers."
msgstr ""
#: doc/classes/BackBufferCopy.xml
-msgid "BackBufferCopy buffers a rectangular region."
+msgid "[BackBufferCopy] buffers a rectangular region."
msgstr ""
#: doc/classes/BackBufferCopy.xml
-msgid "BackBufferCopy buffers the entire screen."
+msgid "[BackBufferCopy] buffers the entire screen."
msgstr ""
#: doc/classes/BakedLightmap.xml
@@ -19375,6 +19412,14 @@ msgid "Cylinder shape for collisions."
msgstr ""
#: doc/classes/CylinderShape.xml
+msgid ""
+"Cylinder shape for collisions.\n"
+"[b]Note:[/b] When using GodotPhysics instead of the default Bullet physics "
+"engine, there are several known bugs with cylinder collision shapes. Using "
+"[CapsuleShape] or [BoxShape] instead is recommended."
+msgstr ""
+
+#: doc/classes/CylinderShape.xml
msgid "The cylinder's height."
msgstr ""
@@ -22209,7 +22254,10 @@ msgid ""
"[/codeblock]\n"
"[b]Note:[/b] The script is run in the Editor context, which means the output "
"is visible in the console window started with the Editor (stdout) instead of "
-"the usual Godot [b]Output[/b] dock."
+"the usual Godot [b]Output[/b] dock.\n"
+"[b]Note:[/b] EditorScript is reference counted, meaning it is destroyed when "
+"nothing references it. This can cause errors during asynchronous operations "
+"if there are no references to the script."
msgstr ""
#: doc/classes/EditorScript.xml
@@ -32948,7 +32996,9 @@ msgid ""
"The size of the light in Godot units. Only considered in baked lightmaps and "
"only if [member light_bake_mode] is set to [constant BAKE_ALL]. Increasing "
"this value will make the shadows appear blurrier. This can be used to "
-"simulate area lights to an extent."
+"simulate area lights to an extent.\n"
+"[b]Note:[/b] [member light_size] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/Light.xml
@@ -36271,7 +36321,10 @@ msgid ""
"use the [method get_next_location] function once every physics frame to "
"update the internal path logic of the NavigationAgent. The returned vector "
"position from this function should be used as the next movement position for "
-"the agent's parent Node."
+"the agent's parent Node.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues."
msgstr ""
#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
@@ -36521,7 +36574,10 @@ msgid ""
"use the [method get_next_location] function once every physics frame to "
"update the internal path logic of the NavigationAgent. The returned vector "
"position from this function should be used as the next movement position for "
-"the agent's parent Node."
+"the agent's parent Node.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues."
msgstr ""
#: doc/classes/NavigationAgent2D.xml
@@ -37238,6 +37294,9 @@ msgid ""
"modified velocity as-is might lead to pushing and agent outside of a "
"navigable area. This is a limitation of the collision avoidance system, any "
"more complex situation may require the use of the physics engine.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues.\n"
"This server keeps tracks of any call and executes them during the sync "
"phase. This means that you can request any change to the map, using any "
"thread, without worrying."
@@ -40048,7 +40107,9 @@ msgid ""
"The light's radius. Note that the effectively lit area may appear to be "
"smaller depending on the [member omni_attenuation] in use. No matter the "
"[member omni_attenuation] in use, the light will never reach anything "
-"outside this radius."
+"outside this radius.\n"
+"[b]Note:[/b] [member omni_range] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -40564,11 +40625,11 @@ msgstr "Palauttaa kahden vektorin jäännöksen."
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] cache data directory according to the operating "
-"system's standards. On desktop platforms, this path can be overridden by "
-"setting the [code]XDG_CACHE_HOME[/code] environment variable before starting "
-"the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in "
-"Godot projects[/url] in the documentation for more information. See also "
-"[method get_config_dir] and [method get_data_dir].\n"
+"system's standards. On Linux, this path can be overridden by setting the "
+"[code]XDG_CACHE_HOME[/code] environment variable before starting the "
+"project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot "
+"projects[/url] in the documentation for more information. See also [method "
+"get_config_dir] and [method get_data_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -40602,11 +40663,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] user configuration directory according to the "
-"operating system's standards. On desktop platforms, this path can be "
-"overridden by setting the [code]XDG_CONFIG_HOME[/code] environment variable "
-"before starting the project. See [url=$DOCS_URL/tutorials/io/data_paths."
-"html]File paths in Godot projects[/url] in the documentation for more "
-"information. See also [method get_cache_dir] and [method get_data_dir].\n"
+"operating system's standards. On Linux, this path can be overridden by "
+"setting the [code]XDG_CONFIG_HOME[/code] environment variable before "
+"starting the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File "
+"paths in Godot projects[/url] in the documentation for more information. See "
+"also [method get_cache_dir] and [method get_data_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -40628,11 +40689,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] user data directory according to the operating "
-"system's standards. On desktop platforms, this path can be overridden by "
-"setting the [code]XDG_DATA_HOME[/code] environment variable before starting "
-"the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in "
-"Godot projects[/url] in the documentation for more information. See also "
-"[method get_cache_dir] and [method get_config_dir].\n"
+"system's standards. On Linux, this path can be overridden by setting the "
+"[code]XDG_DATA_HOME[/code] environment variable before starting the project. "
+"See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot "
+"projects[/url] in the documentation for more information. See also [method "
+"get_cache_dir] and [method get_config_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -42482,6 +42543,16 @@ msgid "Particle systems (2D)"
msgstr ""
#: doc/classes/Particles2D.xml
+msgid "2D Particles Demo"
+msgstr ""
+
+#: doc/classes/Particles2D.xml
+msgid ""
+"2D Dodge The Creeps Demo (uses GPUParticles2D for the trail behind the "
+"player)"
+msgstr ""
+
+#: doc/classes/Particles2D.xml
msgid "Returns a rectangle containing the positions of all existing particles."
msgstr ""
@@ -50083,15 +50154,22 @@ msgstr ""
#: doc/classes/ProjectSettings.xml
msgid ""
"If [code]true[/code], uses a fast post-processing filter to make banding "
-"significantly less visible. In some cases, debanding may introduce a "
-"slightly noticeable dithering pattern. It's recommended to enable debanding "
-"only when actually needed since the dithering pattern will make lossless-"
-"compressed screenshots larger.\n"
+"significantly less visible in 3D. 2D rendering is [i]not[/i] affected by "
+"debanding unless the [member Environment.background_mode] is [constant "
+"Environment.BG_CANVAS]. In this case, [member rendering/quality/"
+"intended_usage/framebuffer_allocation] must also be set to [b]3D[/b].\n"
+"In some cases, debanding may introduce a slightly noticeable dithering "
+"pattern. It's recommended to enable debanding only when actually needed "
+"since the dithering pattern will make lossless-compressed screenshots "
+"larger.\n"
"[b]Note:[/b] Only available on the GLES3 backend. [member rendering/quality/"
"depth/hdr] must also be [code]true[/code] for debanding to be effective.\n"
"[b]Note:[/b] There are known issues with debanding breaking rendering on "
"mobile platforms. Due to this, it is recommended to leave this option "
-"disabled when targeting mobile platforms."
+"disabled when targeting mobile platforms.\n"
+"[b]Note:[/b] This property is only read when the project starts. To set "
+"debanding at run-time, set [member Viewport.debanding] on the root "
+"[Viewport] instead."
msgstr ""
#: doc/classes/ProjectSettings.xml
@@ -51688,17 +51766,28 @@ msgstr ""
#: modules/regex/doc_classes/RegEx.xml
msgid ""
"Searches the text for the compiled pattern. Returns a [RegExMatch] container "
-"of the first matching result if found, otherwise [code]null[/code]. The "
-"region to search within can be specified without modifying where the start "
-"and end anchor would be."
+"of the first matching result if found, otherwise [code]null[/code].\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegEx.xml
msgid ""
"Searches the text for the compiled pattern. Returns an array of [RegExMatch] "
"containers for each non-overlapping result. If no results were found, an "
-"empty array is returned instead. The region to search within can be "
-"specified without modifying where the start and end anchor would be."
+"empty array is returned instead.\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegEx.xml
@@ -51707,8 +51796,14 @@ msgid ""
"specified string. Escapes and backreferences such as [code]$1[/code] and "
"[code]$name[/code] are expanded and resolved. By default, only the first "
"instance is replaced, but it can be changed for all instances (global "
-"replacement). The region to search within can be specified without modifying "
-"where the start and end anchor would be."
+"replacement).\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegExMatch.xml
@@ -54424,7 +54519,11 @@ msgid "Call a group immediately (calls are normally made on idle)."
msgstr ""
#: doc/classes/SceneTree.xml
-msgid "Call a group only once even if the call is executed many times."
+msgid ""
+"Call a group only once even if the call is executed many times.\n"
+"[b]Note:[/b] Arguments are not taken into account when deciding whether the "
+"call is unique or not. Therefore when the same method is called with "
+"different arguments, only the first call will be performed."
msgstr ""
#: doc/classes/SceneTree.xml
@@ -56262,7 +56361,9 @@ msgid ""
"[b]Note:[/b] Mixed negative scales in 3D are not decomposable from the "
"transformation matrix. Due to the way scale is represented with "
"transformation matrices in Godot, the scale values will either be all "
-"positive or all negative."
+"positive or all negative.\n"
+"[b]Note:[/b] Not all nodes are visually scaled by the [member scale] "
+"property. For example, [Light]s are not visually affected by [member scale]."
msgstr ""
#: doc/classes/Spatial.xml
@@ -57640,7 +57741,10 @@ msgid ""
msgstr ""
#: doc/classes/SpotLight.xml
-msgid "The spotlight's angle in degrees."
+msgid ""
+"The spotlight's angle in degrees.\n"
+"[b]Note:[/b] [member spot_angle] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/SpotLight.xml
@@ -57656,7 +57760,9 @@ msgid ""
"The maximal range that can be reached by the spotlight. Note that the "
"effectively lit area may appear to be smaller depending on the [member "
"spot_attenuation] in use. No matter the [member spot_attenuation] in use, "
-"the light will never reach anything outside this range."
+"the light will never reach anything outside this range.\n"
+"[b]Note:[/b] [member spot_range] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/SpringArm.xml
@@ -66944,10 +67050,15 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
"If [code]true[/code], uses a fast post-processing filter to make banding "
-"significantly less visible. In some cases, debanding may introduce a "
-"slightly noticeable dithering pattern. It's recommended to enable debanding "
-"only when actually needed since the dithering pattern will make lossless-"
-"compressed screenshots larger.\n"
+"significantly less visible in 3D. 2D rendering is [i]not[/i] affected by "
+"debanding unless the [member Environment.background_mode] is [constant "
+"Environment.BG_CANVAS]. In this case, [member usage] must also be set to "
+"[constant USAGE_3D]. See also [member ProjectSettings.rendering/quality/"
+"filters/use_debanding].\n"
+"In some cases, debanding may introduce a slightly noticeable dithering "
+"pattern. It's recommended to enable debanding only when actually needed "
+"since the dithering pattern will make lossless-compressed screenshots "
+"larger.\n"
"[b]Note:[/b] Only available on the GLES3 backend. [member hdr] must also be "
"[code]true[/code] for debanding to be effective."
msgstr ""
@@ -66958,8 +67069,8 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
-"If [code]true[/code], the viewport will disable 3D rendering. For actual "
-"disabling use [code]usage[/code]."
+"If [code]true[/code], the viewport will disable 3D rendering. To actually "
+"disable allocation of 3D buffers, set [member usage] instead."
msgstr ""
#: doc/classes/Viewport.xml
@@ -67111,7 +67222,9 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
-"The rendering mode of viewport.\n"
+"The viewport's rendering mode. This controls which buffers are allocated for "
+"the viewport (2D only, or 2D + 3D). 2D-only options can reduce memory usage "
+"and improve performance slightly, especially on low-end devices.\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."
@@ -67643,6 +67756,22 @@ msgid ""
"render object this [VisualInstance] is set to."
msgstr ""
+#: doc/classes/VisualInstance.xml
+msgid ""
+"The sorting offset used by this [VisualInstance]. Adjusting it to a higher "
+"value will make the [VisualInstance] reliably draw on top of other "
+"[VisualInstance]s that are otherwise positioned at the same spot."
+msgstr ""
+
+#: doc/classes/VisualInstance.xml
+msgid ""
+"If [code]true[/code], the object is sorted based on the [AABB] center. "
+"Sorted based on the global position otherwise.\n"
+"The [AABB] center based sorting is generally more accurate for 3D models. "
+"The position based sorting instead allows to better control the drawing "
+"order when working with [Particles] and [CPUParticles]."
+msgstr ""
+
#: modules/visual_script/doc_classes/VisualScript.xml
msgid "A script implemented in the Visual Script programming environment."
msgstr ""
diff --git a/doc/translations/fil.po b/doc/translations/fil.po
index 2bbab40941..749fea9ef9 100644
--- a/doc/translations/fil.po
+++ b/doc/translations/fil.po
@@ -484,7 +484,8 @@ msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
-"Returns an array of dictionaries representing the current call stack.\n"
+"Returns an array of dictionaries representing the current call stack. See "
+"also [method print_stack].\n"
"[codeblock]\n"
"func _ready():\n"
" foo()\n"
@@ -499,7 +500,11 @@ msgid ""
"[codeblock]\n"
"[{function:bar, line:12, source:res://script.gd}, {function:foo, line:9, "
"source:res://script.gd}, {function:_ready, line:6, source:res://script.gd}]\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] [method get_stack] only works if the running instance is "
+"connected to a debugging server (i.e. an editor instance). [method "
+"get_stack] will not work in projects exported in release mode, or in "
+"projects exported in debug mode if not connected to a debugging server."
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -872,12 +877,16 @@ msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
-"Prints a stack track at code location, only works when running with debugger "
-"turned on.\n"
+"Prints a stack trace at the current code location. See also [method "
+"get_stack].\n"
"Output in the console would look something like this:\n"
"[codeblock]\n"
"Frame 0 - res://test.gd:16 in function '_process'\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] [method print_stack] only works if the running instance is "
+"connected to a debugging server (i.e. an editor instance). [method "
+"print_stack] will not work in projects exported in release mode, or in "
+"projects exported in debug mode if not connected to a debugging server."
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -3488,6 +3497,26 @@ msgid "Hints that an image is compressed using lossless compression."
msgstr ""
#: doc/classes/@GlobalScope.xml
+msgid ""
+"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:\n"
+"[codeblock]\n"
+"hint_string = \"%s:\" % [TYPE_INT] # Array of inteters.\n"
+"hint_string = \"%s:%s:\" % [TYPE_ARRAY, TYPE_REAL] # Two-dimensional array "
+"of floats.\n"
+"hint_string = \"%s/%s:Resource\" % [TYPE_OBJECT, TYPE_OBJECT] # Array of "
+"resources.\n"
+"hint_string = \"%s:%s/%s:Resource\" % [TYPE_ARRAY, TYPE_OBJECT, TYPE_OBJECT] "
+"# Two-dimensional array of resources.\n"
+"[/codeblock]\n"
+"[b]Note:[/b] The final colon is required to specify for properly detecting "
+"built-in types."
+msgstr ""
+
+#: doc/classes/@GlobalScope.xml
msgid "The property is serialized and saved in the scene file (default)."
msgstr ""
@@ -4172,8 +4201,7 @@ msgstr ""
#: doc/classes/AudioStreamPlayer.xml doc/classes/Button.xml
#: doc/classes/CanvasLayer.xml doc/classes/CollisionShape2D.xml
#: doc/classes/ColorRect.xml doc/classes/Input.xml doc/classes/InputEvent.xml
-#: doc/classes/InputEventAction.xml doc/classes/Label.xml
-#: doc/classes/Particles2D.xml doc/classes/Timer.xml
+#: doc/classes/InputEventAction.xml doc/classes/Label.xml doc/classes/Timer.xml
#: doc/classes/VisibilityNotifier2D.xml
msgid "2D Dodge The Creeps Demo"
msgstr ""
@@ -7090,7 +7118,10 @@ msgid ""
"var array = []\n"
"array.resize(10)\n"
"array.fill(0) # Initialize the 10 elements to 0.\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] If [code]value[/code] is of a reference type ([Object]-derived, "
+"[Array], [Dictionary], etc.) then the array is filled with the references to "
+"the same object, i.e. no duplicates are created."
msgstr ""
#: doc/classes/Array.xml doc/classes/PoolByteArray.xml
@@ -7275,6 +7306,9 @@ msgstr ""
#: doc/classes/Array.xml
msgid ""
"Sorts the array.\n"
+"[b]Note:[/b] The sorting algorithm used is not [url=https://en.wikipedia.org/"
+"wiki/Sorting_algorithm#Stability]stable[/url]. This means that values "
+"considered equal may have their order changed when using [method sort].\n"
"[b]Note:[/b] Strings are sorted in alphabetical order (as opposed to natural "
"order). This may lead to unexpected behavior when sorting an array of "
"strings ending with a sequence of numbers. Consider the following example:\n"
@@ -7294,9 +7328,13 @@ msgid ""
"For two elements [code]a[/code] and [code]b[/code], if the given method "
"returns [code]true[/code], element [code]b[/code] will be after element "
"[code]a[/code] in the array.\n"
+"[b]Note:[/b] The sorting algorithm used is not [url=https://en.wikipedia.org/"
+"wiki/Sorting_algorithm#Stability]stable[/url]. This means that values "
+"considered equal may have their order changed when using [method "
+"sort_custom].\n"
"[b]Note:[/b] You cannot randomize the return value as the heapsort algorithm "
-"expects a deterministic result. Doing so will result in unexpected "
-"behavior.\n"
+"expects a deterministic result. Randomizing the return value will result in "
+"unexpected behavior.\n"
"[codeblock]\n"
"class MyCustomSorter:\n"
" static func sort_ascending(a, b):\n"
@@ -9934,10 +9972,9 @@ msgstr ""
#: doc/classes/AudioStreamGeneratorPlayback.xml
msgid ""
-"Returns the number of audio data frames left to play. If this returned "
-"number reaches [code]0[/code], the audio will stop playing until frames are "
-"added again. Therefore, make sure your script can always generate and push "
-"new audio frames fast enough to avoid audio cracking."
+"Returns the number of frames that can be pushed to the audio sample data "
+"buffer without overflowing it. If the result is [code]0[/code], the buffer "
+"is full."
msgstr ""
#: doc/classes/AudioStreamGeneratorPlayback.xml
@@ -10469,14 +10506,14 @@ msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
"Node for back-buffering the currently-displayed screen. The region defined "
-"in the BackBufferCopy node is buffered with the content of the screen it "
+"in the [BackBufferCopy] node is buffered with the content of the screen it "
"covers, or the entire screen according to the copy mode set. Use the "
"[code]texture(SCREEN_TEXTURE, ...)[/code] function in your shader scripts to "
"access the buffer.\n"
"[b]Note:[/b] Since this node inherits from [Node2D] (and not [Control]), "
"anchors and margins won't apply to child [Control]-derived nodes. This can "
"be problematic when resizing the window. To avoid this, add [Control]-"
-"derived nodes as [i]siblings[/i] to the BackBufferCopy node instead of "
+"derived nodes as [i]siblings[/i] to the [BackBufferCopy] node instead of "
"adding them as children."
msgstr ""
@@ -10486,22 +10523,22 @@ msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
-"The area covered by the BackBufferCopy. Only used if [member copy_mode] is "
+"The area covered by the [BackBufferCopy]. Only used if [member copy_mode] is "
"[constant COPY_MODE_RECT]."
msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
-"Disables the buffering mode. This means the BackBufferCopy node will "
+"Disables the buffering mode. This means the [BackBufferCopy] node will "
"directly use the portion of screen it covers."
msgstr ""
#: doc/classes/BackBufferCopy.xml
-msgid "BackBufferCopy buffers a rectangular region."
+msgid "[BackBufferCopy] buffers a rectangular region."
msgstr ""
#: doc/classes/BackBufferCopy.xml
-msgid "BackBufferCopy buffers the entire screen."
+msgid "[BackBufferCopy] buffers the entire screen."
msgstr ""
#: doc/classes/BakedLightmap.xml
@@ -19281,6 +19318,14 @@ msgid "Cylinder shape for collisions."
msgstr ""
#: doc/classes/CylinderShape.xml
+msgid ""
+"Cylinder shape for collisions.\n"
+"[b]Note:[/b] When using GodotPhysics instead of the default Bullet physics "
+"engine, there are several known bugs with cylinder collision shapes. Using "
+"[CapsuleShape] or [BoxShape] instead is recommended."
+msgstr ""
+
+#: doc/classes/CylinderShape.xml
msgid "The cylinder's height."
msgstr ""
@@ -22113,7 +22158,10 @@ msgid ""
"[/codeblock]\n"
"[b]Note:[/b] The script is run in the Editor context, which means the output "
"is visible in the console window started with the Editor (stdout) instead of "
-"the usual Godot [b]Output[/b] dock."
+"the usual Godot [b]Output[/b] dock.\n"
+"[b]Note:[/b] EditorScript is reference counted, meaning it is destroyed when "
+"nothing references it. This can cause errors during asynchronous operations "
+"if there are no references to the script."
msgstr ""
#: doc/classes/EditorScript.xml
@@ -32828,7 +32876,9 @@ msgid ""
"The size of the light in Godot units. Only considered in baked lightmaps and "
"only if [member light_bake_mode] is set to [constant BAKE_ALL]. Increasing "
"this value will make the shadows appear blurrier. This can be used to "
-"simulate area lights to an extent."
+"simulate area lights to an extent.\n"
+"[b]Note:[/b] [member light_size] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/Light.xml
@@ -36126,7 +36176,10 @@ msgid ""
"use the [method get_next_location] function once every physics frame to "
"update the internal path logic of the NavigationAgent. The returned vector "
"position from this function should be used as the next movement position for "
-"the agent's parent Node."
+"the agent's parent Node.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues."
msgstr ""
#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
@@ -36374,7 +36427,10 @@ msgid ""
"use the [method get_next_location] function once every physics frame to "
"update the internal path logic of the NavigationAgent. The returned vector "
"position from this function should be used as the next movement position for "
-"the agent's parent Node."
+"the agent's parent Node.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues."
msgstr ""
#: doc/classes/NavigationAgent2D.xml
@@ -37084,6 +37140,9 @@ msgid ""
"modified velocity as-is might lead to pushing and agent outside of a "
"navigable area. This is a limitation of the collision avoidance system, any "
"more complex situation may require the use of the physics engine.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues.\n"
"This server keeps tracks of any call and executes them during the sync "
"phase. This means that you can request any change to the map, using any "
"thread, without worrying."
@@ -39890,7 +39949,9 @@ msgid ""
"The light's radius. Note that the effectively lit area may appear to be "
"smaller depending on the [member omni_attenuation] in use. No matter the "
"[member omni_attenuation] in use, the light will never reach anything "
-"outside this radius."
+"outside this radius.\n"
+"[b]Note:[/b] [member omni_range] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -40401,11 +40462,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] cache data directory according to the operating "
-"system's standards. On desktop platforms, this path can be overridden by "
-"setting the [code]XDG_CACHE_HOME[/code] environment variable before starting "
-"the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in "
-"Godot projects[/url] in the documentation for more information. See also "
-"[method get_config_dir] and [method get_data_dir].\n"
+"system's standards. On Linux, this path can be overridden by setting the "
+"[code]XDG_CACHE_HOME[/code] environment variable before starting the "
+"project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot "
+"projects[/url] in the documentation for more information. See also [method "
+"get_config_dir] and [method get_data_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -40439,11 +40500,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] user configuration directory according to the "
-"operating system's standards. On desktop platforms, this path can be "
-"overridden by setting the [code]XDG_CONFIG_HOME[/code] environment variable "
-"before starting the project. See [url=$DOCS_URL/tutorials/io/data_paths."
-"html]File paths in Godot projects[/url] in the documentation for more "
-"information. See also [method get_cache_dir] and [method get_data_dir].\n"
+"operating system's standards. On Linux, this path can be overridden by "
+"setting the [code]XDG_CONFIG_HOME[/code] environment variable before "
+"starting the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File "
+"paths in Godot projects[/url] in the documentation for more information. See "
+"also [method get_cache_dir] and [method get_data_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -40465,11 +40526,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] user data directory according to the operating "
-"system's standards. On desktop platforms, this path can be overridden by "
-"setting the [code]XDG_DATA_HOME[/code] environment variable before starting "
-"the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in "
-"Godot projects[/url] in the documentation for more information. See also "
-"[method get_cache_dir] and [method get_config_dir].\n"
+"system's standards. On Linux, this path can be overridden by setting the "
+"[code]XDG_DATA_HOME[/code] environment variable before starting the project. "
+"See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot "
+"projects[/url] in the documentation for more information. See also [method "
+"get_cache_dir] and [method get_config_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -42316,6 +42377,16 @@ msgid "Particle systems (2D)"
msgstr ""
#: doc/classes/Particles2D.xml
+msgid "2D Particles Demo"
+msgstr ""
+
+#: doc/classes/Particles2D.xml
+msgid ""
+"2D Dodge The Creeps Demo (uses GPUParticles2D for the trail behind the "
+"player)"
+msgstr ""
+
+#: doc/classes/Particles2D.xml
msgid "Returns a rectangle containing the positions of all existing particles."
msgstr ""
@@ -49908,15 +49979,22 @@ msgstr ""
#: doc/classes/ProjectSettings.xml
msgid ""
"If [code]true[/code], uses a fast post-processing filter to make banding "
-"significantly less visible. In some cases, debanding may introduce a "
-"slightly noticeable dithering pattern. It's recommended to enable debanding "
-"only when actually needed since the dithering pattern will make lossless-"
-"compressed screenshots larger.\n"
+"significantly less visible in 3D. 2D rendering is [i]not[/i] affected by "
+"debanding unless the [member Environment.background_mode] is [constant "
+"Environment.BG_CANVAS]. In this case, [member rendering/quality/"
+"intended_usage/framebuffer_allocation] must also be set to [b]3D[/b].\n"
+"In some cases, debanding may introduce a slightly noticeable dithering "
+"pattern. It's recommended to enable debanding only when actually needed "
+"since the dithering pattern will make lossless-compressed screenshots "
+"larger.\n"
"[b]Note:[/b] Only available on the GLES3 backend. [member rendering/quality/"
"depth/hdr] must also be [code]true[/code] for debanding to be effective.\n"
"[b]Note:[/b] There are known issues with debanding breaking rendering on "
"mobile platforms. Due to this, it is recommended to leave this option "
-"disabled when targeting mobile platforms."
+"disabled when targeting mobile platforms.\n"
+"[b]Note:[/b] This property is only read when the project starts. To set "
+"debanding at run-time, set [member Viewport.debanding] on the root "
+"[Viewport] instead."
msgstr ""
#: doc/classes/ProjectSettings.xml
@@ -51512,17 +51590,28 @@ msgstr ""
#: modules/regex/doc_classes/RegEx.xml
msgid ""
"Searches the text for the compiled pattern. Returns a [RegExMatch] container "
-"of the first matching result if found, otherwise [code]null[/code]. The "
-"region to search within can be specified without modifying where the start "
-"and end anchor would be."
+"of the first matching result if found, otherwise [code]null[/code].\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegEx.xml
msgid ""
"Searches the text for the compiled pattern. Returns an array of [RegExMatch] "
"containers for each non-overlapping result. If no results were found, an "
-"empty array is returned instead. The region to search within can be "
-"specified without modifying where the start and end anchor would be."
+"empty array is returned instead.\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegEx.xml
@@ -51531,8 +51620,14 @@ msgid ""
"specified string. Escapes and backreferences such as [code]$1[/code] and "
"[code]$name[/code] are expanded and resolved. By default, only the first "
"instance is replaced, but it can be changed for all instances (global "
-"replacement). The region to search within can be specified without modifying "
-"where the start and end anchor would be."
+"replacement).\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegExMatch.xml
@@ -54247,7 +54342,11 @@ msgid "Call a group immediately (calls are normally made on idle)."
msgstr ""
#: doc/classes/SceneTree.xml
-msgid "Call a group only once even if the call is executed many times."
+msgid ""
+"Call a group only once even if the call is executed many times.\n"
+"[b]Note:[/b] Arguments are not taken into account when deciding whether the "
+"call is unique or not. Therefore when the same method is called with "
+"different arguments, only the first call will be performed."
msgstr ""
#: doc/classes/SceneTree.xml
@@ -56084,7 +56183,9 @@ msgid ""
"[b]Note:[/b] Mixed negative scales in 3D are not decomposable from the "
"transformation matrix. Due to the way scale is represented with "
"transformation matrices in Godot, the scale values will either be all "
-"positive or all negative."
+"positive or all negative.\n"
+"[b]Note:[/b] Not all nodes are visually scaled by the [member scale] "
+"property. For example, [Light]s are not visually affected by [member scale]."
msgstr ""
#: doc/classes/Spatial.xml
@@ -57462,7 +57563,10 @@ msgid ""
msgstr ""
#: doc/classes/SpotLight.xml
-msgid "The spotlight's angle in degrees."
+msgid ""
+"The spotlight's angle in degrees.\n"
+"[b]Note:[/b] [member spot_angle] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/SpotLight.xml
@@ -57478,7 +57582,9 @@ msgid ""
"The maximal range that can be reached by the spotlight. Note that the "
"effectively lit area may appear to be smaller depending on the [member "
"spot_attenuation] in use. No matter the [member spot_attenuation] in use, "
-"the light will never reach anything outside this range."
+"the light will never reach anything outside this range.\n"
+"[b]Note:[/b] [member spot_range] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/SpringArm.xml
@@ -66715,10 +66821,15 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
"If [code]true[/code], uses a fast post-processing filter to make banding "
-"significantly less visible. In some cases, debanding may introduce a "
-"slightly noticeable dithering pattern. It's recommended to enable debanding "
-"only when actually needed since the dithering pattern will make lossless-"
-"compressed screenshots larger.\n"
+"significantly less visible in 3D. 2D rendering is [i]not[/i] affected by "
+"debanding unless the [member Environment.background_mode] is [constant "
+"Environment.BG_CANVAS]. In this case, [member usage] must also be set to "
+"[constant USAGE_3D]. See also [member ProjectSettings.rendering/quality/"
+"filters/use_debanding].\n"
+"In some cases, debanding may introduce a slightly noticeable dithering "
+"pattern. It's recommended to enable debanding only when actually needed "
+"since the dithering pattern will make lossless-compressed screenshots "
+"larger.\n"
"[b]Note:[/b] Only available on the GLES3 backend. [member hdr] must also be "
"[code]true[/code] for debanding to be effective."
msgstr ""
@@ -66729,8 +66840,8 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
-"If [code]true[/code], the viewport will disable 3D rendering. For actual "
-"disabling use [code]usage[/code]."
+"If [code]true[/code], the viewport will disable 3D rendering. To actually "
+"disable allocation of 3D buffers, set [member usage] instead."
msgstr ""
#: doc/classes/Viewport.xml
@@ -66882,7 +66993,9 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
-"The rendering mode of viewport.\n"
+"The viewport's rendering mode. This controls which buffers are allocated for "
+"the viewport (2D only, or 2D + 3D). 2D-only options can reduce memory usage "
+"and improve performance slightly, especially on low-end devices.\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."
@@ -67414,6 +67527,22 @@ msgid ""
"render object this [VisualInstance] is set to."
msgstr ""
+#: doc/classes/VisualInstance.xml
+msgid ""
+"The sorting offset used by this [VisualInstance]. Adjusting it to a higher "
+"value will make the [VisualInstance] reliably draw on top of other "
+"[VisualInstance]s that are otherwise positioned at the same spot."
+msgstr ""
+
+#: doc/classes/VisualInstance.xml
+msgid ""
+"If [code]true[/code], the object is sorted based on the [AABB] center. "
+"Sorted based on the global position otherwise.\n"
+"The [AABB] center based sorting is generally more accurate for 3D models. "
+"The position based sorting instead allows to better control the drawing "
+"order when working with [Particles] and [CPUParticles]."
+msgstr ""
+
#: modules/visual_script/doc_classes/VisualScript.xml
msgid "A script implemented in the Visual Script programming environment."
msgstr ""
diff --git a/doc/translations/fr.po b/doc/translations/fr.po
index e22ff9db67..2898e9ec19 100644
--- a/doc/translations/fr.po
+++ b/doc/translations/fr.po
@@ -56,13 +56,17 @@
# KikooDX <kikoodx@paranoici.org>, 2022.
# Kevin Bouancheau <kevin.bouancheau@gmail.com>, 2022.
# Maxim Lopez <maxim.lopez.02@gmail.com>, 2022.
+# Philippe Lamare <ph.lamare@free.fr>, 2022.
+# Augustin Ambiehl <ambiehlaugustin@gmail.com>, 2022.
+# Landry Simo <landrysimo99@gmail.com>, 2022.
+# Alexis Coudert <coudert.alex@gmail.com>, 2022.
msgid ""
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-08-19 12:56+0000\n"
-"Last-Translator: Maxime Leroy <lisacintosh@gmail.com>\n"
+"PO-Revision-Date: 2022-12-03 00:47+0000\n"
+"Last-Translator: Alexis Coudert <coudert.alex@gmail.com>\n"
"Language-Team: French <https://hosted.weblate.org/projects/godot-engine/"
"godot-class-reference/fr/>\n"
"Language: fr\n"
@@ -70,7 +74,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.14-dev\n"
+"X-Generator: Weblate 4.15-dev\n"
#: doc/tools/make_rst.py
msgid "Description"
@@ -133,6 +137,7 @@ msgid "Default"
msgstr "Défaut"
#: doc/tools/make_rst.py
+#, fuzzy
msgid "Setter"
msgstr "Setter"
@@ -774,8 +779,10 @@ msgstr ""
"[/codeblock]"
#: modules/gdscript/doc_classes/@GDScript.xml
+#, fuzzy
msgid ""
-"Returns an array of dictionaries representing the current call stack.\n"
+"Returns an array of dictionaries representing the current call stack. See "
+"also [method print_stack].\n"
"[codeblock]\n"
"func _ready():\n"
" foo()\n"
@@ -790,7 +797,11 @@ msgid ""
"[codeblock]\n"
"[{function:bar, line:12, source:res://script.gd}, {function:foo, line:9, "
"source:res://script.gd}, {function:_ready, line:6, source:res://script.gd}]\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] [method get_stack] only works if the running instance is "
+"connected to a debugging server (i.e. an editor instance). [method "
+"get_stack] will not work in projects exported in release mode, or in "
+"projects exported in debug mode if not connected to a debugging server."
msgstr ""
"Renvoie un tableau de dictionnaires représentant la pile d'appels en cours.\n"
"[codeblock]\n"
@@ -876,7 +887,6 @@ msgstr ""
"[/codeblock]"
#: modules/gdscript/doc_classes/@GDScript.xml
-#, fuzzy
msgid ""
"Returns an interpolation or extrapolation factor considering the range "
"specified in [code]from[/code] and [code]to[/code], and the interpolated "
@@ -899,24 +909,26 @@ msgid ""
"See also [method lerp] which performs the reverse of this operation, and "
"[method range_lerp] to map a continuous series of values to another."
msgstr ""
-"Retourne le facteur d'interpolation ou d'extrapolation suivant l'intervalle "
-"spécifié dans [code]from[/code] et [code]to[/code], et la valeur interpolée "
-"spécifiée par [code]weight[/code]. La valeur retournée sera entre [code]0.0[/"
-"code] et [code]1.0[/code] si [code]weight[/code] est entre [code]from[/code] "
-"et [code]to[/code] (inclus). Si [code]weight[/code] est en dehors de cet "
+"Retourne un facteur d'interpolation ou d'extrapolation suivant l'intervalle "
+"spécifié dans [code]de[/code] et [code]à[/code], et la valeur interpolée "
+"spécifiée par [code]poids[/code]. La valeur retournée sera entre [code]0.0[/"
+"code] et [code]1.0[/code] si [code]poids[/code] est entre [code]de[/code] et "
+"[code]à[/code] (inclus). Si [code]poids[/code] se trouve en dehors de cet "
"intervalle, un facteur d'extrapolation sera retourné (une valeur inférieure "
-"à [code]0.0[/code] ou supérieure à [code]1.0[/code]).\n"
+"à [code]0.0[/code] ou supérieure à [code]1.0[/code]). Utilisez [method "
+"clamp] sur le resultat de [method inverse_lerp] si cela n'est pas souhaité.\n"
"[codeblock]\n"
-"# Le facteur d'interpolation de cet appel à `lerp()` ci-dessous est le "
+"# Le facteur d'interpolation de cet appel à `lerp()` ci-dessous est de "
"0.75.\n"
"var middle = lerp(20, 30, 0.75)\n"
-"# `middle` est maintenant 27.5.\n"
-"# Maintenant, on fait comme si on avait oublié le facteur d'interpolation "
-"original et qu'on veut le calculer.\n"
+"# `middle` vaut maintenant 27.5.\n"
+"# Admettons maintenant que l'on ait oublié le facteur d'interpolation "
+"original et que l'on veut le calculer.\n"
"var ratio = inverse_lerp(20, 30, 27.5)\n"
-"# `ratio` est maintenant 0.75.\n"
+"# `ratio` vaut maintenant 0.75.\n"
"[/codeblock]\n"
-"Voir aussi [method lerp] qui fait l'opération inverse."
+"Voir aussi [method lerp] qui fait l'opération inverse et [method range_lerp] "
+"qui fait correspondre une série de valeurs continues à une autre."
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
@@ -988,7 +1000,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 "
@@ -1010,12 +1021,13 @@ msgid ""
"ease] or [method smoothstep]. See also [method range_lerp] to map a "
"continuous series of values to another."
msgstr ""
-"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 "
+"Effectue une interpolation linéaire entre deux valeurs par un facteur défini "
+"dans [code]poids[/code]. Pour effectuer l'interpolation, [code]poids[/code] "
+"se situer entre [code]0.0[/code] et [code]1.0[/code] (inclus). Pour autant, "
+"des valeurs en dehors de cet intervalle sont autorisés pour effectuer une "
+"[i]extrapolation[/i]. Utilisez [method clamp] sur le résultat de [method "
+"lerp] si cela n'est pas souhaité.\n"
+"Si les arguments [code]de[/code] et [code]à[/code] sont de type [int] ou "
"[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 (puisque [code]lerp[/code] appelle "
@@ -1024,9 +1036,10 @@ msgstr ""
"lerp(0, 4, 0.75) # Retourne 3.0\n"
"lerp(Vector2(1, 5), Vector2(3, 2), 0.5) # Retourne Vector2(2, 3.5)\n"
"[/codeblock]\n"
-"Voir aussi [method inverse_lerp] qui fait l'opération inverse. Pour fait une "
-"interpolation plus douce avec [method lerp], combinez l'appel avec [method "
-"ease] ou [method smoothstep]."
+"Voir aussi [method inverse_lerp] qui effectue l'opération inverse. Pour "
+"effectuer une interpolation adoucie avec [method lerp], combinez l'appel "
+"avec [method ease] ou [method smoothstep]. Voir aussi [method range_lerp] "
+"pour faire correspondre une série de valeurs continues à une autre."
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
@@ -1448,19 +1461,17 @@ msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
-"Prints a stack track at code location, only works when running with debugger "
-"turned on.\n"
+"Prints a stack trace at the current code location. See also [method "
+"get_stack].\n"
"Output in the console would look something like this:\n"
"[codeblock]\n"
"Frame 0 - res://test.gd:16 in function '_process'\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] [method print_stack] only works if the running instance is "
+"connected to a debugging server (i.e. an editor instance). [method "
+"print_stack] will not work in projects exported in release mode, or in "
+"projects exported in debug mode if not connected to a debugging server."
msgstr ""
-"Affiche la trace d'appels à l'emplacement du code, ne fonctionne que lorsque "
-"le débogueur est activé.\n"
-"La sortie dans la console ressemblerait à ceci :\n"
-"[codeblock]\n"
-"Frame 0 - res://test.gd:16 in function '_process'\n"
-"[/codeblock]"
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
@@ -1749,6 +1760,17 @@ msgid ""
"For complex use cases where you need multiple ranges, consider using [Curve] "
"or [Gradient] instead."
msgstr ""
+"Fait correspondre une [code]valeur[/code] de l'intervalle [code][idebut, "
+"ifin][/code] à [code][odebut, ofin][/code]. Voir aussi [method lerp] et "
+"[method inverse_lerp]. Si la [code]valeur[/code] est en dehors de [code]"
+"[idebut, ifin][/code], la valeur résultante sera aussi en dehors de [code]"
+"[odebut, ofin][/code]. Utilisez [method clamp] sur le résultat de [method "
+"range_lerp] si cela n'est pas souhaité.\n"
+"[codeblock]\n"
+"range_lerp(75, 0, 100, -1, 1) # Retourne 0.5\n"
+"[/codeblock]\n"
+"Pour les cas d'utilisation plus complexes avec plusieurs intervalles, "
+"favorisez plutôt [Curve] ou [Gradient]."
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
@@ -4162,10 +4184,13 @@ msgid "MIDI stop message. Stop the current sequence."
msgstr "Le message d'arrêt en MIDI. Arrête la séquence actuelle."
#: doc/classes/@GlobalScope.xml
+#, fuzzy
msgid ""
"MIDI active sensing message. This message is intended to be sent repeatedly "
"to tell the receiver that a connection is alive."
msgstr ""
+"Message de détection d'activité MIDI. Ce message est destiné à être envoyé à "
+"plusieurs reprises pour indiquer au récepteur qu'une connexion est active."
#: doc/classes/@GlobalScope.xml
msgid ""
@@ -4638,6 +4663,26 @@ msgstr ""
"Indique qu'une image est comprimé en utlisant la compression sans perte."
#: doc/classes/@GlobalScope.xml
+msgid ""
+"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:\n"
+"[codeblock]\n"
+"hint_string = \"%s:\" % [TYPE_INT] # Array of inteters.\n"
+"hint_string = \"%s:%s:\" % [TYPE_ARRAY, TYPE_REAL] # Two-dimensional array "
+"of floats.\n"
+"hint_string = \"%s/%s:Resource\" % [TYPE_OBJECT, TYPE_OBJECT] # Array of "
+"resources.\n"
+"hint_string = \"%s:%s/%s:Resource\" % [TYPE_ARRAY, TYPE_OBJECT, TYPE_OBJECT] "
+"# Two-dimensional array of resources.\n"
+"[/codeblock]\n"
+"[b]Note:[/b] The final colon is required to specify for properly detecting "
+"built-in types."
+msgstr ""
+
+#: doc/classes/@GlobalScope.xml
msgid "The property is serialized and saved in the scene file (default)."
msgstr ""
"Le propriété est sérialisé et sauvegardé dans le fichier de la scène(défaut)."
@@ -5489,8 +5534,7 @@ msgstr "Animation Sprite 2D"
#: doc/classes/AudioStreamPlayer.xml doc/classes/Button.xml
#: doc/classes/CanvasLayer.xml doc/classes/CollisionShape2D.xml
#: doc/classes/ColorRect.xml doc/classes/Input.xml doc/classes/InputEvent.xml
-#: doc/classes/InputEventAction.xml doc/classes/Label.xml
-#: doc/classes/Particles2D.xml doc/classes/Timer.xml
+#: doc/classes/InputEventAction.xml doc/classes/Label.xml doc/classes/Timer.xml
#: doc/classes/VisibilityNotifier2D.xml
msgid "2D Dodge The Creeps Demo"
msgstr "Démo 2D « Dodge The Creeps »"
@@ -6427,18 +6471,25 @@ msgid ""
"When inheriting from [AnimationRootNode], implement this virtual method to "
"override the text caption for this node."
msgstr ""
+"Lorsque vous héritez d'[AnimationRootNode], implémentez cette méthode "
+"virtuelle pour remplacer le texte de légende de ce nœud."
#: doc/classes/AnimationNode.xml
msgid ""
"When inheriting from [AnimationRootNode], implement this virtual method to "
"return a child node by its [code]name[/code]."
msgstr ""
+"Lorsque vous héritez d'[AnimationRootNode], implémentez cette méthode "
+"virtuelle pour retourner un nœud enfant par [code]nom[/code]."
#: doc/classes/AnimationNode.xml
msgid ""
"When inheriting from [AnimationRootNode], implement this virtual method to "
"return all children nodes in order as a [code]name: node[/code] dictionary."
msgstr ""
+"Lorsque vous héritez d'[AnimationRootNode], implémentez cette méthode "
+"virtuelle pour retourner tous les nœuds enfants en tant que dictionnaire "
+"[code]nom : nœud[/code]."
#: doc/classes/AnimationNode.xml
msgid ""
@@ -6462,16 +6513,17 @@ msgstr ""
"réutilisé dans plusieurs arbres de nœuds."
#: doc/classes/AnimationNode.xml
-#, fuzzy
msgid ""
"When inheriting from [AnimationRootNode], implement this virtual method to "
"return the default value of parameter \"[code]name[/code]\". Parameters are "
"custom local memory used for your nodes, given a resource can be reused in "
"multiple trees."
msgstr ""
-"Obtient la valeur par défaut d'un paramètre. Les paramètres sont la mémoire "
-"locale personnalisé utilisé pour vos nœuds, étant donné qu'une ressource "
-"peut être réutilisé dans plusieurs arbres de nœuds."
+"Lors de l'héritage de [AnimationRootNode], implémente cette méthode "
+"virtuelle pour obtenirla valeur par défaut du paramètre \"[code]name[/"
+"code]\". Les paramètres sont de la mémoire locale personnalisée utilisée "
+"pour vos nœuds, étant donné qu'une ressource peut être réutilisée dans "
+"plusieurs arbres."
#: doc/classes/AnimationNode.xml
#, fuzzy
@@ -9430,6 +9482,7 @@ msgstr ""
"les éléments placés après devront tous être décalés."
#: doc/classes/Array.xml
+#, fuzzy
msgid ""
"Assigns the given value to all elements in the array. This can typically be "
"used together with [method resize] to create an array with a given size and "
@@ -9438,7 +9491,10 @@ msgid ""
"var array = []\n"
"array.resize(10)\n"
"array.fill(0) # Initialize the 10 elements to 0.\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] If [code]value[/code] is of a reference type ([Object]-derived, "
+"[Array], [Dictionary], etc.) then the array is filled with the references to "
+"the same object, i.e. no duplicates are created."
msgstr ""
"Assigne la valeur donnée à tous les éléments du tableau. C'est souvent "
"utilisé avec [method resize] pour créer un tableau d'une taille donnée avec "
@@ -9725,8 +9781,12 @@ msgstr ""
"découpage."
#: doc/classes/Array.xml
+#, fuzzy
msgid ""
"Sorts the array.\n"
+"[b]Note:[/b] The sorting algorithm used is not [url=https://en.wikipedia.org/"
+"wiki/Sorting_algorithm#Stability]stable[/url]. This means that values "
+"considered equal may have their order changed when using [method sort].\n"
"[b]Note:[/b] Strings are sorted in alphabetical order (as opposed to natural "
"order). This may lead to unexpected behavior when sorting an array of "
"strings ending with a sequence of numbers. Consider the following example:\n"
@@ -9749,6 +9809,7 @@ msgstr ""
"[/codeblock]"
#: doc/classes/Array.xml
+#, fuzzy
msgid ""
"Sorts the array using a custom method. The arguments are an object that "
"holds the method and the name of such method. The custom method receives two "
@@ -9757,9 +9818,13 @@ msgid ""
"For two elements [code]a[/code] and [code]b[/code], if the given method "
"returns [code]true[/code], element [code]b[/code] will be after element "
"[code]a[/code] in the array.\n"
+"[b]Note:[/b] The sorting algorithm used is not [url=https://en.wikipedia.org/"
+"wiki/Sorting_algorithm#Stability]stable[/url]. This means that values "
+"considered equal may have their order changed when using [method "
+"sort_custom].\n"
"[b]Note:[/b] You cannot randomize the return value as the heapsort algorithm "
-"expects a deterministic result. Doing so will result in unexpected "
-"behavior.\n"
+"expects a deterministic result. Randomizing the return value will result in "
+"unexpected behavior.\n"
"[codeblock]\n"
"class MyCustomSorter:\n"
" static func sort_ascending(a, b):\n"
@@ -9894,13 +9959,23 @@ msgstr ""
"deviendra l'index [code]surf_idx[/code] pour cette nouvelle surface.\n"
"L'argument [code]arrays[/code] est un tableau de tableaux. Voir [enum "
"ArrayType] pour les valeurs utilisées dans ce tableau. Par exemple, "
-"l'argument [code]arrays[/code] est le tableau des sommets. Ce premier sous-"
-"tableau de sommets est nécessaire ; les autres sont facultatifs. L'ajout "
-"d'un tableau d'indices met cette fonction en \"mode index\" où les sommets "
-"et d'autres tableaux deviennent les sources de données et le tableau d'index "
-"définit l'ordre des vertex. Tous les sous-tableau doivent avoir la même "
-"longueur que le tableau des sommets, ou être vides, sauf pour [constant "
-"ARRAY_INDEX] s'il est utilisé."
+"l'argument [code]arrays[0]/code] est le tableau des sommets. Ce premier sous-"
+"tableau de sommets est toujours requis ; les autres sont facultatifs. "
+"L'ajout d'un tableau d'indices met cette fonction en \"mode index\" où les "
+"sommets et d'autres tableaux deviennent les sources de données et le tableau "
+"d'index définit l'ordre des vertex. Tous les sous-tableau doivent avoir la "
+"même longueur que le tableau des sommets, ou être vides, sauf pour [constant "
+"ARRAY_INDEX] s'il est utilisé.\n"
+"[code]compress_flags[/code] est un champ de bits fait de valeurs [enum Mesh."
+"ArrayFormat]. Il prend par défaut la valeur de [constant Mesh."
+"ARRAY_COMPRESS_DEFAULT].\n"
+"[b]Note:[/b] Le [code]compress_flags[/code] par défaut valide [constant Mesh."
+"ARRAY_COMPRESS_COLOR], qui rend les couleurs de sommet stockées sous forme "
+"d'entiers non signés 8 bits. Cela bloquera les couleurs de sommet trop "
+"lumineuses à [code]Color(1, 1, 1, 1)[/code] et réduira leur précision. Pour "
+"stocker des couleurs de sommet HDR, enlever le flag de compression de "
+"couleur de sommet en passant [code]Mesh.ARRAY_COMPRESS_DEFAULT ^ Mesh."
+"ARRAY_COMPRESS_COLOR[/code] comme la valeur de [code]compress_flags[/code]."
#: doc/classes/ArrayMesh.xml
msgid "Removes all blend shapes from this [ArrayMesh]."
@@ -13145,12 +13220,16 @@ msgid ""
"settings."
msgstr ""
"Le nom du périphérique actuel pour l'entrée audio (voir [method "
-"get_device_list)]. Sur les systèmes avec plusieurs entrées audio (comme "
-"l'analogique, l'USB et l'audio par HDMI), cela peut être utilisé pour "
-"sélectionner le périphérique d'entrée pour l'audio. La valeur "
-"[code]\"Defaut\"[/code] enregistrera l'audio sur l'entrée audio par défaut "
-"du système. Si un nom de périphérique invalide est défini, la valeur sera "
-"retournée à [code]\"Defaut\"[/code]."
+"capture_get_device_list]. Sur les systèmes avec plusieurs entrées audio "
+"(comme l'analogique, l'USB et l'audio par HDMI), ceci peut être utilisé pour "
+"sélectionner le périphérique d'entrée audio. La valeur [code]\"Default\"[/"
+"code] enregistrera l'audio sur l'entrée audio par défaut du système. Si un "
+"nom de périphérique invalide est défini, la valeur sera retournée à "
+"[code]\"Default\"[/code].\n"
+"[b]Note:[/b] [member ProjectSettings.audio/enable_audio_input] doit être "
+"[code]true[/code] pour que l'entrée audio fonctionne. Voir aussi la "
+"description de ce paramètre pour les avertissements liés aux autorisations "
+"et aux paramètres de confidentialité du système d'exploitation."
#: doc/classes/AudioServer.xml
msgid ""
@@ -13317,16 +13396,10 @@ msgstr "Efface la mémoire tampon des échantillons audio."
#: doc/classes/AudioStreamGeneratorPlayback.xml
msgid ""
-"Returns the number of audio data frames left to play. If this returned "
-"number reaches [code]0[/code], the audio will stop playing until frames are "
-"added again. Therefore, make sure your script can always generate and push "
-"new audio frames fast enough to avoid audio cracking."
+"Returns the number of frames that can be pushed to the audio sample data "
+"buffer without overflowing it. If the result is [code]0[/code], the buffer "
+"is full."
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 ""
@@ -13999,14 +14072,14 @@ msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
"Node for back-buffering the currently-displayed screen. The region defined "
-"in the BackBufferCopy node is buffered with the content of the screen it "
+"in the [BackBufferCopy] node is buffered with the content of the screen it "
"covers, or the entire screen according to the copy mode set. Use the "
"[code]texture(SCREEN_TEXTURE, ...)[/code] function in your shader scripts to "
"access the buffer.\n"
"[b]Note:[/b] Since this node inherits from [Node2D] (and not [Control]), "
"anchors and margins won't apply to child [Control]-derived nodes. This can "
"be problematic when resizing the window. To avoid this, add [Control]-"
-"derived nodes as [i]siblings[/i] to the BackBufferCopy node instead of "
+"derived nodes as [i]siblings[/i] to the [BackBufferCopy] node instead of "
"adding them as children."
msgstr ""
@@ -14015,23 +14088,28 @@ msgid "Buffer mode. See [enum CopyMode] constants."
msgstr "Le mode de mémoire tampon. Voir les constantes [enum CopyMode]."
#: doc/classes/BackBufferCopy.xml
+#, fuzzy
msgid ""
-"The area covered by the BackBufferCopy. Only used if [member copy_mode] is "
+"The area covered by the [BackBufferCopy]. Only used if [member copy_mode] is "
"[constant COPY_MODE_RECT]."
msgstr ""
+"Le type de base à utiliser lorsque [member call_mode] est défini à [constant "
+"CALL_MODE_INSTANCE]."
#: doc/classes/BackBufferCopy.xml
msgid ""
-"Disables the buffering mode. This means the BackBufferCopy node will "
+"Disables the buffering mode. This means the [BackBufferCopy] node will "
"directly use the portion of screen it covers."
msgstr ""
#: doc/classes/BackBufferCopy.xml
-msgid "BackBufferCopy buffers a rectangular region."
+#, fuzzy
+msgid "[BackBufferCopy] buffers a rectangular region."
msgstr "BackBufferCopy met en tampon une région rectangulaire."
#: doc/classes/BackBufferCopy.xml
-msgid "BackBufferCopy buffers the entire screen."
+#, fuzzy
+msgid "[BackBufferCopy] buffers the entire screen."
msgstr "BackBufferCopy met en mémoire tampon tout l'écran."
#: doc/classes/BakedLightmap.xml
@@ -16719,17 +16797,20 @@ msgid ""
"antialiasing. 2D batching is also still supported with those antialiased "
"lines."
msgstr ""
-"Dessine des segments de ligne interconnectés avec une [code]width[/code] "
-"uniforme et une coloration segment par segment. Les couleurs attribuées aux "
-"segments de ligne correspondent par index entre [code]points[/code] et "
-"[code]colors[/code].\n"
-"[b]Note :[/b] Le fonctionnement interne peut provoquer des problèmes de "
-"rendu de l'anti-crénelage lors de l'affichage de polygones transparents voir "
-"peut ne pas fonctionner sur certaines plateformes. Pour corriger cela, "
+"Dessine des lignes déconnectées avec une [code]width[/code] uniforme et une "
+"coloration segment par segment. Les couleurs attribuées aux segments de "
+"ligne correspondent par index entre [code]points[/code] et [code]colors[/"
+"code]. Lorsque vous dessinez de grandes quantités de lignes, cela est plus "
+"rapide que d'utiliser des appels individuels[method draw_line]. Pour tracer "
+"des lignes interconnectées, utiliser [method draw_polyline_colors] à la "
+"place.\n"
+"[b]Note :[/b] [code]width[/code] et [code]antialiased[/code] ne sont pas "
+"actuellement implémentés et ne produisent aucun effet. Comme contournement, "
"installez le greffon [url=https://github.com/godot-extended-libraries/godot-"
"antialiased-line2d]Antialiased Line2D[/url] et créez un nœud "
"AntialiasedPolygon2D. Ce nœud utilise une texture avec différents niveaux de "
-"mipmap pour l'anti-crénelage."
+"mipmap pour l'anti-crénelage. Le traitement par lots 2D est également "
+"supporté avec ces lignes anti-crénelage."
#: doc/classes/CanvasItem.xml
msgid ""
@@ -25852,6 +25933,14 @@ msgid "Cylinder shape for collisions."
msgstr "Une forme cylindrique pour les collisions."
#: doc/classes/CylinderShape.xml
+msgid ""
+"Cylinder shape for collisions.\n"
+"[b]Note:[/b] When using GodotPhysics instead of the default Bullet physics "
+"engine, there are several known bugs with cylinder collision shapes. Using "
+"[CapsuleShape] or [BoxShape] instead is recommended."
+msgstr ""
+
+#: doc/classes/CylinderShape.xml
msgid "The cylinder's height."
msgstr "La hauteur du cylindre."
@@ -30031,6 +30120,7 @@ msgid "Base script that can be used to add extension functions to the editor."
msgstr "Script de base qui permet d'étendre les fonctionnalités de l'éditeur."
#: doc/classes/EditorScript.xml
+#, fuzzy
msgid ""
"Scripts extending this class and implementing its [method _run] method can "
"be executed from the Script Editor's [b]File > Run[/b] menu option (or by "
@@ -30048,7 +30138,10 @@ msgid ""
"[/codeblock]\n"
"[b]Note:[/b] The script is run in the Editor context, which means the output "
"is visible in the console window started with the Editor (stdout) instead of "
-"the usual Godot [b]Output[/b] dock."
+"the usual Godot [b]Output[/b] dock.\n"
+"[b]Note:[/b] EditorScript is reference counted, meaning it is destroyed when "
+"nothing references it. This can cause errors during asynchronous operations "
+"if there are no references to the script."
msgstr ""
"Les scripts héritant de cette classe et implémentant la méthode [method "
"_run] peuvent être exécutés depuis l'éditeur de script avec l'option de menu "
@@ -42766,7 +42859,9 @@ msgid ""
"The size of the light in Godot units. Only considered in baked lightmaps and "
"only if [member light_bake_mode] is set to [constant BAKE_ALL]. Increasing "
"this value will make the shadows appear blurrier. This can be used to "
-"simulate area lights to an extent."
+"simulate area lights to an extent.\n"
+"[b]Note:[/b] [member light_size] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/Light.xml
@@ -47014,6 +47109,7 @@ msgid "3D agent used in navigation for collision avoidance."
msgstr "Un agent 3D utilisé dans les navigations pour esquiver les collisions."
#: doc/classes/NavigationAgent.xml
+#, fuzzy
msgid ""
"3D agent that is used in navigation to reach a location while avoiding "
"static and dynamic obstacles. The dynamic obstacles are avoided using RVO "
@@ -47027,7 +47123,10 @@ msgid ""
"use the [method get_next_location] function once every physics frame to "
"update the internal path logic of the NavigationAgent. The returned vector "
"position from this function should be used as the next movement position for "
-"the agent's parent Node."
+"the agent's parent Node.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues."
msgstr ""
"Agent 3D utilisé dans la navigation pour atteindre un emplacement tout en "
"évitant les obstacles statiques et dynamiques. Les obstacles dynamiques sont "
@@ -47386,6 +47485,7 @@ msgid "2D agent used in navigation for collision avoidance."
msgstr "Un agent 2D utilisé en navigation pour éviter les collisions."
#: doc/classes/NavigationAgent2D.xml
+#, fuzzy
msgid ""
"2D agent that is used in navigation to reach a location while avoiding "
"static and dynamic obstacles. The dynamic obstacles are avoided using RVO "
@@ -47399,7 +47499,10 @@ msgid ""
"use the [method get_next_location] function once every physics frame to "
"update the internal path logic of the NavigationAgent. The returned vector "
"position from this function should be used as the next movement position for "
-"the agent's parent Node."
+"the agent's parent Node.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues."
msgstr ""
"L'agent 2D utilisé dans la navigation pour atteindre un emplacement tout en "
"évitant les obstacles statiques et dynamiques. Les obstacles dynamiques sont "
@@ -48399,6 +48502,7 @@ msgid "Server interface for low-level 3D navigation access."
msgstr "Interface serveur pour un accès de navigation 3D de bas niveau."
#: doc/classes/NavigationServer.xml
+#, fuzzy
msgid ""
"NavigationServer is the server responsible for all 3D navigation. It handles "
"several objects, namely maps, regions and agents.\n"
@@ -48419,6 +48523,9 @@ msgid ""
"modified velocity as-is might lead to pushing and agent outside of a "
"navigable area. This is a limitation of the collision avoidance system, any "
"more complex situation may require the use of the physics engine.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues.\n"
"This server keeps tracks of any call and executes them during the sync "
"phase. This means that you can request any change to the map, using any "
"thread, without worrying."
@@ -52507,7 +52614,9 @@ msgid ""
"The light's radius. Note that the effectively lit area may appear to be "
"smaller depending on the [member omni_attenuation] in use. No matter the "
"[member omni_attenuation] in use, the light will never reach anything "
-"outside this radius."
+"outside this radius.\n"
+"[b]Note:[/b] [member omni_range] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -53164,11 +53273,11 @@ msgstr "Retourne le nom du pilote audio à l'index donné."
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] cache data directory according to the operating "
-"system's standards. On desktop platforms, this path can be overridden by "
-"setting the [code]XDG_CACHE_HOME[/code] environment variable before starting "
-"the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in "
-"Godot projects[/url] in the documentation for more information. See also "
-"[method get_config_dir] and [method get_data_dir].\n"
+"system's standards. On Linux, this path can be overridden by setting the "
+"[code]XDG_CACHE_HOME[/code] environment variable before starting the "
+"project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot "
+"projects[/url] in the documentation for more information. See also [method "
+"get_config_dir] and [method get_data_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -53202,11 +53311,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] user configuration directory according to the "
-"operating system's standards. On desktop platforms, this path can be "
-"overridden by setting the [code]XDG_CONFIG_HOME[/code] environment variable "
-"before starting the project. See [url=$DOCS_URL/tutorials/io/data_paths."
-"html]File paths in Godot projects[/url] in the documentation for more "
-"information. See also [method get_cache_dir] and [method get_data_dir].\n"
+"operating system's standards. On Linux, this path can be overridden by "
+"setting the [code]XDG_CONFIG_HOME[/code] environment variable before "
+"starting the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File "
+"paths in Godot projects[/url] in the documentation for more information. See "
+"also [method get_cache_dir] and [method get_data_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -53234,11 +53343,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] user data directory according to the operating "
-"system's standards. On desktop platforms, this path can be overridden by "
-"setting the [code]XDG_DATA_HOME[/code] environment variable before starting "
-"the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in "
-"Godot projects[/url] in the documentation for more information. See also "
-"[method get_cache_dir] and [method get_config_dir].\n"
+"system's standards. On Linux, this path can be overridden by setting the "
+"[code]XDG_DATA_HOME[/code] environment variable before starting the project. "
+"See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot "
+"projects[/url] in the documentation for more information. See also [method "
+"get_cache_dir] and [method get_config_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -55600,6 +55709,17 @@ msgid "Particle systems (2D)"
msgstr ""
#: doc/classes/Particles2D.xml
+#, fuzzy
+msgid "2D Particles Demo"
+msgstr "Démo 2D isométrique"
+
+#: doc/classes/Particles2D.xml
+msgid ""
+"2D Dodge The Creeps Demo (uses GPUParticles2D for the trail behind the "
+"player)"
+msgstr ""
+
+#: doc/classes/Particles2D.xml
msgid "Returns a rectangle containing the positions of all existing particles."
msgstr ""
"Retourne un rectangle contenant la position de toutes les particules "
@@ -64195,15 +64315,22 @@ msgstr ""
#: doc/classes/ProjectSettings.xml
msgid ""
"If [code]true[/code], uses a fast post-processing filter to make banding "
-"significantly less visible. In some cases, debanding may introduce a "
-"slightly noticeable dithering pattern. It's recommended to enable debanding "
-"only when actually needed since the dithering pattern will make lossless-"
-"compressed screenshots larger.\n"
+"significantly less visible in 3D. 2D rendering is [i]not[/i] affected by "
+"debanding unless the [member Environment.background_mode] is [constant "
+"Environment.BG_CANVAS]. In this case, [member rendering/quality/"
+"intended_usage/framebuffer_allocation] must also be set to [b]3D[/b].\n"
+"In some cases, debanding may introduce a slightly noticeable dithering "
+"pattern. It's recommended to enable debanding only when actually needed "
+"since the dithering pattern will make lossless-compressed screenshots "
+"larger.\n"
"[b]Note:[/b] Only available on the GLES3 backend. [member rendering/quality/"
"depth/hdr] must also be [code]true[/code] for debanding to be effective.\n"
"[b]Note:[/b] There are known issues with debanding breaking rendering on "
"mobile platforms. Due to this, it is recommended to leave this option "
-"disabled when targeting mobile platforms."
+"disabled when targeting mobile platforms.\n"
+"[b]Note:[/b] This property is only read when the project starts. To set "
+"debanding at run-time, set [member Viewport.debanding] on the root "
+"[Viewport] instead."
msgstr ""
#: doc/classes/ProjectSettings.xml
@@ -66153,17 +66280,28 @@ msgstr ""
#: modules/regex/doc_classes/RegEx.xml
msgid ""
"Searches the text for the compiled pattern. Returns a [RegExMatch] container "
-"of the first matching result if found, otherwise [code]null[/code]. The "
-"region to search within can be specified without modifying where the start "
-"and end anchor would be."
+"of the first matching result if found, otherwise [code]null[/code].\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegEx.xml
msgid ""
"Searches the text for the compiled pattern. Returns an array of [RegExMatch] "
"containers for each non-overlapping result. If no results were found, an "
-"empty array is returned instead. The region to search within can be "
-"specified without modifying where the start and end anchor would be."
+"empty array is returned instead.\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegEx.xml
@@ -66172,8 +66310,14 @@ msgid ""
"specified string. Escapes and backreferences such as [code]$1[/code] and "
"[code]$name[/code] are expanded and resolved. By default, only the first "
"instance is replaced, but it can be changed for all instances (global "
-"replacement). The region to search within can be specified without modifying "
-"where the start and end anchor would be."
+"replacement).\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegExMatch.xml
@@ -69059,9 +69203,12 @@ msgid "Call a group immediately (calls are normally made on idle)."
msgstr "Appelle un groupe immédiatement (au lieu de le faire durant le repos)."
#: doc/classes/SceneTree.xml
-msgid "Call a group only once even if the call is executed many times."
+msgid ""
+"Call a group only once even if the call is executed many times.\n"
+"[b]Note:[/b] Arguments are not taken into account when deciding whether the "
+"call is unique or not. Therefore when the same method is called with "
+"different arguments, only the first call will be performed."
msgstr ""
-"Appelle un groupe une seule fois même si l'appel a était fait plusieurs fois."
#: doc/classes/SceneTree.xml
msgid "No stretching."
@@ -69139,8 +69286,8 @@ msgstr ""
" yield(get_tree().create_timer(1.0), \"timeout\")\n"
" print(\"Minuteur terminé.\")\n"
"[/codeblock]\n"
-"Le minuteur sera automatiquement une fois terminé. Pour garder le minuteur, "
-"vous pouvez maintenir une référence vers lui. Voir [Reference]."
+"Le minuteur sera automatiquement déréférencé 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)."
@@ -71188,7 +71335,9 @@ msgid ""
"[b]Note:[/b] Mixed negative scales in 3D are not decomposable from the "
"transformation matrix. Due to the way scale is represented with "
"transformation matrices in Godot, the scale values will either be all "
-"positive or all negative."
+"positive or all negative.\n"
+"[b]Note:[/b] Not all nodes are visually scaled by the [member scale] "
+"property. For example, [Light]s are not visually affected by [member scale]."
msgstr ""
#: doc/classes/Spatial.xml
@@ -72764,8 +72913,11 @@ msgid ""
msgstr ""
#: doc/classes/SpotLight.xml
-msgid "The spotlight's angle in degrees."
-msgstr "L’angle du projecteur en degrés."
+msgid ""
+"The spotlight's angle in degrees.\n"
+"[b]Note:[/b] [member spot_angle] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
+msgstr ""
#: doc/classes/SpotLight.xml
msgid "The spotlight's angular attenuation curve."
@@ -72780,7 +72932,9 @@ msgid ""
"The maximal range that can be reached by the spotlight. Note that the "
"effectively lit area may appear to be smaller depending on the [member "
"spot_attenuation] in use. No matter the [member spot_attenuation] in use, "
-"the light will never reach anything outside this range."
+"the light will never reach anything outside this range.\n"
+"[b]Note:[/b] [member spot_range] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/SpringArm.xml
@@ -74278,7 +74432,7 @@ msgid ""
"[/codeblock]"
msgstr ""
"Échappe (code) une chaine de caractères dans un format compatible avec les "
-"URL. Est aussi référé au 'codage de URL' ('URL encode').\n"
+"URL. Aussi appelé 'encodage d'URL' ('URL encode').\n"
"[codeblock]\n"
"print(\"https://example.org/?escaped=\" + \"Le Moteur Godot:'docs'\"."
"http_escape())\n"
@@ -83997,10 +84151,15 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
"If [code]true[/code], uses a fast post-processing filter to make banding "
-"significantly less visible. In some cases, debanding may introduce a "
-"slightly noticeable dithering pattern. It's recommended to enable debanding "
-"only when actually needed since the dithering pattern will make lossless-"
-"compressed screenshots larger.\n"
+"significantly less visible in 3D. 2D rendering is [i]not[/i] affected by "
+"debanding unless the [member Environment.background_mode] is [constant "
+"Environment.BG_CANVAS]. In this case, [member usage] must also be set to "
+"[constant USAGE_3D]. See also [member ProjectSettings.rendering/quality/"
+"filters/use_debanding].\n"
+"In some cases, debanding may introduce a slightly noticeable dithering "
+"pattern. It's recommended to enable debanding only when actually needed "
+"since the dithering pattern will make lossless-compressed screenshots "
+"larger.\n"
"[b]Note:[/b] Only available on the GLES3 backend. [member hdr] must also be "
"[code]true[/code] for debanding to be effective."
msgstr ""
@@ -84012,9 +84171,10 @@ msgstr ""
"débogage."
#: doc/classes/Viewport.xml
+#, fuzzy
msgid ""
-"If [code]true[/code], the viewport will disable 3D rendering. For actual "
-"disabling use [code]usage[/code]."
+"If [code]true[/code], the viewport will disable 3D rendering. To actually "
+"disable allocation of 3D buffers, set [member usage] instead."
msgstr ""
"Si [code]true[/code], le viewport désactivera le rendu 3D. Pour le "
"désactiver réellement, utilisez [code]usage[/code]."
@@ -84198,7 +84358,9 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
-"The rendering mode of viewport.\n"
+"The viewport's rendering mode. This controls which buffers are allocated for "
+"the viewport (2D only, or 2D + 3D). 2D-only options can reduce memory usage "
+"and improve performance slightly, especially on low-end devices.\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."
@@ -84784,6 +84946,22 @@ msgstr ""
"Cet objet ne sera visible que pour les [Camera] où le masque de cull inclut "
"l'objet de rendu auquel [VisualInstance] est défini."
+#: doc/classes/VisualInstance.xml
+msgid ""
+"The sorting offset used by this [VisualInstance]. Adjusting it to a higher "
+"value will make the [VisualInstance] reliably draw on top of other "
+"[VisualInstance]s that are otherwise positioned at the same spot."
+msgstr ""
+
+#: doc/classes/VisualInstance.xml
+msgid ""
+"If [code]true[/code], the object is sorted based on the [AABB] center. "
+"Sorted based on the global position otherwise.\n"
+"The [AABB] center based sorting is generally more accurate for 3D models. "
+"The position based sorting instead allows to better control the drawing "
+"order when working with [Particles] and [CPUParticles]."
+msgstr ""
+
#: modules/visual_script/doc_classes/VisualScript.xml
msgid "A script implemented in the Visual Script programming environment."
msgstr ""
diff --git a/doc/translations/gl.po b/doc/translations/gl.po
index 4ad17bba17..67bd7d902f 100644
--- a/doc/translations/gl.po
+++ b/doc/translations/gl.po
@@ -476,7 +476,8 @@ msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
-"Returns an array of dictionaries representing the current call stack.\n"
+"Returns an array of dictionaries representing the current call stack. See "
+"also [method print_stack].\n"
"[codeblock]\n"
"func _ready():\n"
" foo()\n"
@@ -491,7 +492,11 @@ msgid ""
"[codeblock]\n"
"[{function:bar, line:12, source:res://script.gd}, {function:foo, line:9, "
"source:res://script.gd}, {function:_ready, line:6, source:res://script.gd}]\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] [method get_stack] only works if the running instance is "
+"connected to a debugging server (i.e. an editor instance). [method "
+"get_stack] will not work in projects exported in release mode, or in "
+"projects exported in debug mode if not connected to a debugging server."
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -864,12 +869,16 @@ msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
-"Prints a stack track at code location, only works when running with debugger "
-"turned on.\n"
+"Prints a stack trace at the current code location. See also [method "
+"get_stack].\n"
"Output in the console would look something like this:\n"
"[codeblock]\n"
"Frame 0 - res://test.gd:16 in function '_process'\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] [method print_stack] only works if the running instance is "
+"connected to a debugging server (i.e. an editor instance). [method "
+"print_stack] will not work in projects exported in release mode, or in "
+"projects exported in debug mode if not connected to a debugging server."
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -3480,6 +3489,26 @@ msgid "Hints that an image is compressed using lossless compression."
msgstr ""
#: doc/classes/@GlobalScope.xml
+msgid ""
+"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:\n"
+"[codeblock]\n"
+"hint_string = \"%s:\" % [TYPE_INT] # Array of inteters.\n"
+"hint_string = \"%s:%s:\" % [TYPE_ARRAY, TYPE_REAL] # Two-dimensional array "
+"of floats.\n"
+"hint_string = \"%s/%s:Resource\" % [TYPE_OBJECT, TYPE_OBJECT] # Array of "
+"resources.\n"
+"hint_string = \"%s:%s/%s:Resource\" % [TYPE_ARRAY, TYPE_OBJECT, TYPE_OBJECT] "
+"# Two-dimensional array of resources.\n"
+"[/codeblock]\n"
+"[b]Note:[/b] The final colon is required to specify for properly detecting "
+"built-in types."
+msgstr ""
+
+#: doc/classes/@GlobalScope.xml
msgid "The property is serialized and saved in the scene file (default)."
msgstr ""
@@ -4164,8 +4193,7 @@ msgstr ""
#: doc/classes/AudioStreamPlayer.xml doc/classes/Button.xml
#: doc/classes/CanvasLayer.xml doc/classes/CollisionShape2D.xml
#: doc/classes/ColorRect.xml doc/classes/Input.xml doc/classes/InputEvent.xml
-#: doc/classes/InputEventAction.xml doc/classes/Label.xml
-#: doc/classes/Particles2D.xml doc/classes/Timer.xml
+#: doc/classes/InputEventAction.xml doc/classes/Label.xml doc/classes/Timer.xml
#: doc/classes/VisibilityNotifier2D.xml
msgid "2D Dodge The Creeps Demo"
msgstr ""
@@ -7082,7 +7110,10 @@ msgid ""
"var array = []\n"
"array.resize(10)\n"
"array.fill(0) # Initialize the 10 elements to 0.\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] If [code]value[/code] is of a reference type ([Object]-derived, "
+"[Array], [Dictionary], etc.) then the array is filled with the references to "
+"the same object, i.e. no duplicates are created."
msgstr ""
#: doc/classes/Array.xml doc/classes/PoolByteArray.xml
@@ -7267,6 +7298,9 @@ msgstr ""
#: doc/classes/Array.xml
msgid ""
"Sorts the array.\n"
+"[b]Note:[/b] The sorting algorithm used is not [url=https://en.wikipedia.org/"
+"wiki/Sorting_algorithm#Stability]stable[/url]. This means that values "
+"considered equal may have their order changed when using [method sort].\n"
"[b]Note:[/b] Strings are sorted in alphabetical order (as opposed to natural "
"order). This may lead to unexpected behavior when sorting an array of "
"strings ending with a sequence of numbers. Consider the following example:\n"
@@ -7286,9 +7320,13 @@ msgid ""
"For two elements [code]a[/code] and [code]b[/code], if the given method "
"returns [code]true[/code], element [code]b[/code] will be after element "
"[code]a[/code] in the array.\n"
+"[b]Note:[/b] The sorting algorithm used is not [url=https://en.wikipedia.org/"
+"wiki/Sorting_algorithm#Stability]stable[/url]. This means that values "
+"considered equal may have their order changed when using [method "
+"sort_custom].\n"
"[b]Note:[/b] You cannot randomize the return value as the heapsort algorithm "
-"expects a deterministic result. Doing so will result in unexpected "
-"behavior.\n"
+"expects a deterministic result. Randomizing the return value will result in "
+"unexpected behavior.\n"
"[codeblock]\n"
"class MyCustomSorter:\n"
" static func sort_ascending(a, b):\n"
@@ -9926,10 +9964,9 @@ msgstr ""
#: doc/classes/AudioStreamGeneratorPlayback.xml
msgid ""
-"Returns the number of audio data frames left to play. If this returned "
-"number reaches [code]0[/code], the audio will stop playing until frames are "
-"added again. Therefore, make sure your script can always generate and push "
-"new audio frames fast enough to avoid audio cracking."
+"Returns the number of frames that can be pushed to the audio sample data "
+"buffer without overflowing it. If the result is [code]0[/code], the buffer "
+"is full."
msgstr ""
#: doc/classes/AudioStreamGeneratorPlayback.xml
@@ -10461,14 +10498,14 @@ msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
"Node for back-buffering the currently-displayed screen. The region defined "
-"in the BackBufferCopy node is buffered with the content of the screen it "
+"in the [BackBufferCopy] node is buffered with the content of the screen it "
"covers, or the entire screen according to the copy mode set. Use the "
"[code]texture(SCREEN_TEXTURE, ...)[/code] function in your shader scripts to "
"access the buffer.\n"
"[b]Note:[/b] Since this node inherits from [Node2D] (and not [Control]), "
"anchors and margins won't apply to child [Control]-derived nodes. This can "
"be problematic when resizing the window. To avoid this, add [Control]-"
-"derived nodes as [i]siblings[/i] to the BackBufferCopy node instead of "
+"derived nodes as [i]siblings[/i] to the [BackBufferCopy] node instead of "
"adding them as children."
msgstr ""
@@ -10478,22 +10515,22 @@ msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
-"The area covered by the BackBufferCopy. Only used if [member copy_mode] is "
+"The area covered by the [BackBufferCopy]. Only used if [member copy_mode] is "
"[constant COPY_MODE_RECT]."
msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
-"Disables the buffering mode. This means the BackBufferCopy node will "
+"Disables the buffering mode. This means the [BackBufferCopy] node will "
"directly use the portion of screen it covers."
msgstr ""
#: doc/classes/BackBufferCopy.xml
-msgid "BackBufferCopy buffers a rectangular region."
+msgid "[BackBufferCopy] buffers a rectangular region."
msgstr ""
#: doc/classes/BackBufferCopy.xml
-msgid "BackBufferCopy buffers the entire screen."
+msgid "[BackBufferCopy] buffers the entire screen."
msgstr ""
#: doc/classes/BakedLightmap.xml
@@ -19273,6 +19310,14 @@ msgid "Cylinder shape for collisions."
msgstr ""
#: doc/classes/CylinderShape.xml
+msgid ""
+"Cylinder shape for collisions.\n"
+"[b]Note:[/b] When using GodotPhysics instead of the default Bullet physics "
+"engine, there are several known bugs with cylinder collision shapes. Using "
+"[CapsuleShape] or [BoxShape] instead is recommended."
+msgstr ""
+
+#: doc/classes/CylinderShape.xml
msgid "The cylinder's height."
msgstr ""
@@ -22105,7 +22150,10 @@ msgid ""
"[/codeblock]\n"
"[b]Note:[/b] The script is run in the Editor context, which means the output "
"is visible in the console window started with the Editor (stdout) instead of "
-"the usual Godot [b]Output[/b] dock."
+"the usual Godot [b]Output[/b] dock.\n"
+"[b]Note:[/b] EditorScript is reference counted, meaning it is destroyed when "
+"nothing references it. This can cause errors during asynchronous operations "
+"if there are no references to the script."
msgstr ""
#: doc/classes/EditorScript.xml
@@ -32817,7 +32865,9 @@ msgid ""
"The size of the light in Godot units. Only considered in baked lightmaps and "
"only if [member light_bake_mode] is set to [constant BAKE_ALL]. Increasing "
"this value will make the shadows appear blurrier. This can be used to "
-"simulate area lights to an extent."
+"simulate area lights to an extent.\n"
+"[b]Note:[/b] [member light_size] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/Light.xml
@@ -36115,7 +36165,10 @@ msgid ""
"use the [method get_next_location] function once every physics frame to "
"update the internal path logic of the NavigationAgent. The returned vector "
"position from this function should be used as the next movement position for "
-"the agent's parent Node."
+"the agent's parent Node.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues."
msgstr ""
#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
@@ -36363,7 +36416,10 @@ msgid ""
"use the [method get_next_location] function once every physics frame to "
"update the internal path logic of the NavigationAgent. The returned vector "
"position from this function should be used as the next movement position for "
-"the agent's parent Node."
+"the agent's parent Node.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues."
msgstr ""
#: doc/classes/NavigationAgent2D.xml
@@ -37073,6 +37129,9 @@ msgid ""
"modified velocity as-is might lead to pushing and agent outside of a "
"navigable area. This is a limitation of the collision avoidance system, any "
"more complex situation may require the use of the physics engine.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues.\n"
"This server keeps tracks of any call and executes them during the sync "
"phase. This means that you can request any change to the map, using any "
"thread, without worrying."
@@ -39879,7 +39938,9 @@ msgid ""
"The light's radius. Note that the effectively lit area may appear to be "
"smaller depending on the [member omni_attenuation] in use. No matter the "
"[member omni_attenuation] in use, the light will never reach anything "
-"outside this radius."
+"outside this radius.\n"
+"[b]Note:[/b] [member omni_range] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -40390,11 +40451,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] cache data directory according to the operating "
-"system's standards. On desktop platforms, this path can be overridden by "
-"setting the [code]XDG_CACHE_HOME[/code] environment variable before starting "
-"the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in "
-"Godot projects[/url] in the documentation for more information. See also "
-"[method get_config_dir] and [method get_data_dir].\n"
+"system's standards. On Linux, this path can be overridden by setting the "
+"[code]XDG_CACHE_HOME[/code] environment variable before starting the "
+"project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot "
+"projects[/url] in the documentation for more information. See also [method "
+"get_config_dir] and [method get_data_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -40428,11 +40489,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] user configuration directory according to the "
-"operating system's standards. On desktop platforms, this path can be "
-"overridden by setting the [code]XDG_CONFIG_HOME[/code] environment variable "
-"before starting the project. See [url=$DOCS_URL/tutorials/io/data_paths."
-"html]File paths in Godot projects[/url] in the documentation for more "
-"information. See also [method get_cache_dir] and [method get_data_dir].\n"
+"operating system's standards. On Linux, this path can be overridden by "
+"setting the [code]XDG_CONFIG_HOME[/code] environment variable before "
+"starting the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File "
+"paths in Godot projects[/url] in the documentation for more information. See "
+"also [method get_cache_dir] and [method get_data_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -40454,11 +40515,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] user data directory according to the operating "
-"system's standards. On desktop platforms, this path can be overridden by "
-"setting the [code]XDG_DATA_HOME[/code] environment variable before starting "
-"the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in "
-"Godot projects[/url] in the documentation for more information. See also "
-"[method get_cache_dir] and [method get_config_dir].\n"
+"system's standards. On Linux, this path can be overridden by setting the "
+"[code]XDG_DATA_HOME[/code] environment variable before starting the project. "
+"See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot "
+"projects[/url] in the documentation for more information. See also [method "
+"get_cache_dir] and [method get_config_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -42305,6 +42366,16 @@ msgid "Particle systems (2D)"
msgstr ""
#: doc/classes/Particles2D.xml
+msgid "2D Particles Demo"
+msgstr ""
+
+#: doc/classes/Particles2D.xml
+msgid ""
+"2D Dodge The Creeps Demo (uses GPUParticles2D for the trail behind the "
+"player)"
+msgstr ""
+
+#: doc/classes/Particles2D.xml
msgid "Returns a rectangle containing the positions of all existing particles."
msgstr ""
@@ -49897,15 +49968,22 @@ msgstr ""
#: doc/classes/ProjectSettings.xml
msgid ""
"If [code]true[/code], uses a fast post-processing filter to make banding "
-"significantly less visible. In some cases, debanding may introduce a "
-"slightly noticeable dithering pattern. It's recommended to enable debanding "
-"only when actually needed since the dithering pattern will make lossless-"
-"compressed screenshots larger.\n"
+"significantly less visible in 3D. 2D rendering is [i]not[/i] affected by "
+"debanding unless the [member Environment.background_mode] is [constant "
+"Environment.BG_CANVAS]. In this case, [member rendering/quality/"
+"intended_usage/framebuffer_allocation] must also be set to [b]3D[/b].\n"
+"In some cases, debanding may introduce a slightly noticeable dithering "
+"pattern. It's recommended to enable debanding only when actually needed "
+"since the dithering pattern will make lossless-compressed screenshots "
+"larger.\n"
"[b]Note:[/b] Only available on the GLES3 backend. [member rendering/quality/"
"depth/hdr] must also be [code]true[/code] for debanding to be effective.\n"
"[b]Note:[/b] There are known issues with debanding breaking rendering on "
"mobile platforms. Due to this, it is recommended to leave this option "
-"disabled when targeting mobile platforms."
+"disabled when targeting mobile platforms.\n"
+"[b]Note:[/b] This property is only read when the project starts. To set "
+"debanding at run-time, set [member Viewport.debanding] on the root "
+"[Viewport] instead."
msgstr ""
#: doc/classes/ProjectSettings.xml
@@ -51501,17 +51579,28 @@ msgstr ""
#: modules/regex/doc_classes/RegEx.xml
msgid ""
"Searches the text for the compiled pattern. Returns a [RegExMatch] container "
-"of the first matching result if found, otherwise [code]null[/code]. The "
-"region to search within can be specified without modifying where the start "
-"and end anchor would be."
+"of the first matching result if found, otherwise [code]null[/code].\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegEx.xml
msgid ""
"Searches the text for the compiled pattern. Returns an array of [RegExMatch] "
"containers for each non-overlapping result. If no results were found, an "
-"empty array is returned instead. The region to search within can be "
-"specified without modifying where the start and end anchor would be."
+"empty array is returned instead.\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegEx.xml
@@ -51520,8 +51609,14 @@ msgid ""
"specified string. Escapes and backreferences such as [code]$1[/code] and "
"[code]$name[/code] are expanded and resolved. By default, only the first "
"instance is replaced, but it can be changed for all instances (global "
-"replacement). The region to search within can be specified without modifying "
-"where the start and end anchor would be."
+"replacement).\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegExMatch.xml
@@ -54236,7 +54331,11 @@ msgid "Call a group immediately (calls are normally made on idle)."
msgstr ""
#: doc/classes/SceneTree.xml
-msgid "Call a group only once even if the call is executed many times."
+msgid ""
+"Call a group only once even if the call is executed many times.\n"
+"[b]Note:[/b] Arguments are not taken into account when deciding whether the "
+"call is unique or not. Therefore when the same method is called with "
+"different arguments, only the first call will be performed."
msgstr ""
#: doc/classes/SceneTree.xml
@@ -56073,7 +56172,9 @@ msgid ""
"[b]Note:[/b] Mixed negative scales in 3D are not decomposable from the "
"transformation matrix. Due to the way scale is represented with "
"transformation matrices in Godot, the scale values will either be all "
-"positive or all negative."
+"positive or all negative.\n"
+"[b]Note:[/b] Not all nodes are visually scaled by the [member scale] "
+"property. For example, [Light]s are not visually affected by [member scale]."
msgstr ""
#: doc/classes/Spatial.xml
@@ -57451,7 +57552,10 @@ msgid ""
msgstr ""
#: doc/classes/SpotLight.xml
-msgid "The spotlight's angle in degrees."
+msgid ""
+"The spotlight's angle in degrees.\n"
+"[b]Note:[/b] [member spot_angle] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/SpotLight.xml
@@ -57467,7 +57571,9 @@ msgid ""
"The maximal range that can be reached by the spotlight. Note that the "
"effectively lit area may appear to be smaller depending on the [member "
"spot_attenuation] in use. No matter the [member spot_attenuation] in use, "
-"the light will never reach anything outside this range."
+"the light will never reach anything outside this range.\n"
+"[b]Note:[/b] [member spot_range] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/SpringArm.xml
@@ -66704,10 +66810,15 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
"If [code]true[/code], uses a fast post-processing filter to make banding "
-"significantly less visible. In some cases, debanding may introduce a "
-"slightly noticeable dithering pattern. It's recommended to enable debanding "
-"only when actually needed since the dithering pattern will make lossless-"
-"compressed screenshots larger.\n"
+"significantly less visible in 3D. 2D rendering is [i]not[/i] affected by "
+"debanding unless the [member Environment.background_mode] is [constant "
+"Environment.BG_CANVAS]. In this case, [member usage] must also be set to "
+"[constant USAGE_3D]. See also [member ProjectSettings.rendering/quality/"
+"filters/use_debanding].\n"
+"In some cases, debanding may introduce a slightly noticeable dithering "
+"pattern. It's recommended to enable debanding only when actually needed "
+"since the dithering pattern will make lossless-compressed screenshots "
+"larger.\n"
"[b]Note:[/b] Only available on the GLES3 backend. [member hdr] must also be "
"[code]true[/code] for debanding to be effective."
msgstr ""
@@ -66718,8 +66829,8 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
-"If [code]true[/code], the viewport will disable 3D rendering. For actual "
-"disabling use [code]usage[/code]."
+"If [code]true[/code], the viewport will disable 3D rendering. To actually "
+"disable allocation of 3D buffers, set [member usage] instead."
msgstr ""
#: doc/classes/Viewport.xml
@@ -66871,7 +66982,9 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
-"The rendering mode of viewport.\n"
+"The viewport's rendering mode. This controls which buffers are allocated for "
+"the viewport (2D only, or 2D + 3D). 2D-only options can reduce memory usage "
+"and improve performance slightly, especially on low-end devices.\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."
@@ -67403,6 +67516,22 @@ msgid ""
"render object this [VisualInstance] is set to."
msgstr ""
+#: doc/classes/VisualInstance.xml
+msgid ""
+"The sorting offset used by this [VisualInstance]. Adjusting it to a higher "
+"value will make the [VisualInstance] reliably draw on top of other "
+"[VisualInstance]s that are otherwise positioned at the same spot."
+msgstr ""
+
+#: doc/classes/VisualInstance.xml
+msgid ""
+"If [code]true[/code], the object is sorted based on the [AABB] center. "
+"Sorted based on the global position otherwise.\n"
+"The [AABB] center based sorting is generally more accurate for 3D models. "
+"The position based sorting instead allows to better control the drawing "
+"order when working with [Particles] and [CPUParticles]."
+msgstr ""
+
#: modules/visual_script/doc_classes/VisualScript.xml
msgid "A script implemented in the Visual Script programming environment."
msgstr ""
diff --git a/doc/translations/hi.po b/doc/translations/hi.po
index 945befe58b..75318a4554 100644
--- a/doc/translations/hi.po
+++ b/doc/translations/hi.po
@@ -475,7 +475,8 @@ msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
-"Returns an array of dictionaries representing the current call stack.\n"
+"Returns an array of dictionaries representing the current call stack. See "
+"also [method print_stack].\n"
"[codeblock]\n"
"func _ready():\n"
" foo()\n"
@@ -490,7 +491,11 @@ msgid ""
"[codeblock]\n"
"[{function:bar, line:12, source:res://script.gd}, {function:foo, line:9, "
"source:res://script.gd}, {function:_ready, line:6, source:res://script.gd}]\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] [method get_stack] only works if the running instance is "
+"connected to a debugging server (i.e. an editor instance). [method "
+"get_stack] will not work in projects exported in release mode, or in "
+"projects exported in debug mode if not connected to a debugging server."
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -863,12 +868,16 @@ msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
-"Prints a stack track at code location, only works when running with debugger "
-"turned on.\n"
+"Prints a stack trace at the current code location. See also [method "
+"get_stack].\n"
"Output in the console would look something like this:\n"
"[codeblock]\n"
"Frame 0 - res://test.gd:16 in function '_process'\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] [method print_stack] only works if the running instance is "
+"connected to a debugging server (i.e. an editor instance). [method "
+"print_stack] will not work in projects exported in release mode, or in "
+"projects exported in debug mode if not connected to a debugging server."
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -3479,6 +3488,26 @@ msgid "Hints that an image is compressed using lossless compression."
msgstr ""
#: doc/classes/@GlobalScope.xml
+msgid ""
+"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:\n"
+"[codeblock]\n"
+"hint_string = \"%s:\" % [TYPE_INT] # Array of inteters.\n"
+"hint_string = \"%s:%s:\" % [TYPE_ARRAY, TYPE_REAL] # Two-dimensional array "
+"of floats.\n"
+"hint_string = \"%s/%s:Resource\" % [TYPE_OBJECT, TYPE_OBJECT] # Array of "
+"resources.\n"
+"hint_string = \"%s:%s/%s:Resource\" % [TYPE_ARRAY, TYPE_OBJECT, TYPE_OBJECT] "
+"# Two-dimensional array of resources.\n"
+"[/codeblock]\n"
+"[b]Note:[/b] The final colon is required to specify for properly detecting "
+"built-in types."
+msgstr ""
+
+#: doc/classes/@GlobalScope.xml
msgid "The property is serialized and saved in the scene file (default)."
msgstr ""
@@ -4163,8 +4192,7 @@ msgstr ""
#: doc/classes/AudioStreamPlayer.xml doc/classes/Button.xml
#: doc/classes/CanvasLayer.xml doc/classes/CollisionShape2D.xml
#: doc/classes/ColorRect.xml doc/classes/Input.xml doc/classes/InputEvent.xml
-#: doc/classes/InputEventAction.xml doc/classes/Label.xml
-#: doc/classes/Particles2D.xml doc/classes/Timer.xml
+#: doc/classes/InputEventAction.xml doc/classes/Label.xml doc/classes/Timer.xml
#: doc/classes/VisibilityNotifier2D.xml
msgid "2D Dodge The Creeps Demo"
msgstr ""
@@ -7081,7 +7109,10 @@ msgid ""
"var array = []\n"
"array.resize(10)\n"
"array.fill(0) # Initialize the 10 elements to 0.\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] If [code]value[/code] is of a reference type ([Object]-derived, "
+"[Array], [Dictionary], etc.) then the array is filled with the references to "
+"the same object, i.e. no duplicates are created."
msgstr ""
#: doc/classes/Array.xml doc/classes/PoolByteArray.xml
@@ -7266,6 +7297,9 @@ msgstr ""
#: doc/classes/Array.xml
msgid ""
"Sorts the array.\n"
+"[b]Note:[/b] The sorting algorithm used is not [url=https://en.wikipedia.org/"
+"wiki/Sorting_algorithm#Stability]stable[/url]. This means that values "
+"considered equal may have their order changed when using [method sort].\n"
"[b]Note:[/b] Strings are sorted in alphabetical order (as opposed to natural "
"order). This may lead to unexpected behavior when sorting an array of "
"strings ending with a sequence of numbers. Consider the following example:\n"
@@ -7285,9 +7319,13 @@ msgid ""
"For two elements [code]a[/code] and [code]b[/code], if the given method "
"returns [code]true[/code], element [code]b[/code] will be after element "
"[code]a[/code] in the array.\n"
+"[b]Note:[/b] The sorting algorithm used is not [url=https://en.wikipedia.org/"
+"wiki/Sorting_algorithm#Stability]stable[/url]. This means that values "
+"considered equal may have their order changed when using [method "
+"sort_custom].\n"
"[b]Note:[/b] You cannot randomize the return value as the heapsort algorithm "
-"expects a deterministic result. Doing so will result in unexpected "
-"behavior.\n"
+"expects a deterministic result. Randomizing the return value will result in "
+"unexpected behavior.\n"
"[codeblock]\n"
"class MyCustomSorter:\n"
" static func sort_ascending(a, b):\n"
@@ -9925,10 +9963,9 @@ msgstr ""
#: doc/classes/AudioStreamGeneratorPlayback.xml
msgid ""
-"Returns the number of audio data frames left to play. If this returned "
-"number reaches [code]0[/code], the audio will stop playing until frames are "
-"added again. Therefore, make sure your script can always generate and push "
-"new audio frames fast enough to avoid audio cracking."
+"Returns the number of frames that can be pushed to the audio sample data "
+"buffer without overflowing it. If the result is [code]0[/code], the buffer "
+"is full."
msgstr ""
#: doc/classes/AudioStreamGeneratorPlayback.xml
@@ -10460,14 +10497,14 @@ msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
"Node for back-buffering the currently-displayed screen. The region defined "
-"in the BackBufferCopy node is buffered with the content of the screen it "
+"in the [BackBufferCopy] node is buffered with the content of the screen it "
"covers, or the entire screen according to the copy mode set. Use the "
"[code]texture(SCREEN_TEXTURE, ...)[/code] function in your shader scripts to "
"access the buffer.\n"
"[b]Note:[/b] Since this node inherits from [Node2D] (and not [Control]), "
"anchors and margins won't apply to child [Control]-derived nodes. This can "
"be problematic when resizing the window. To avoid this, add [Control]-"
-"derived nodes as [i]siblings[/i] to the BackBufferCopy node instead of "
+"derived nodes as [i]siblings[/i] to the [BackBufferCopy] node instead of "
"adding them as children."
msgstr ""
@@ -10477,22 +10514,22 @@ msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
-"The area covered by the BackBufferCopy. Only used if [member copy_mode] is "
+"The area covered by the [BackBufferCopy]. Only used if [member copy_mode] is "
"[constant COPY_MODE_RECT]."
msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
-"Disables the buffering mode. This means the BackBufferCopy node will "
+"Disables the buffering mode. This means the [BackBufferCopy] node will "
"directly use the portion of screen it covers."
msgstr ""
#: doc/classes/BackBufferCopy.xml
-msgid "BackBufferCopy buffers a rectangular region."
+msgid "[BackBufferCopy] buffers a rectangular region."
msgstr ""
#: doc/classes/BackBufferCopy.xml
-msgid "BackBufferCopy buffers the entire screen."
+msgid "[BackBufferCopy] buffers the entire screen."
msgstr ""
#: doc/classes/BakedLightmap.xml
@@ -19272,6 +19309,14 @@ msgid "Cylinder shape for collisions."
msgstr ""
#: doc/classes/CylinderShape.xml
+msgid ""
+"Cylinder shape for collisions.\n"
+"[b]Note:[/b] When using GodotPhysics instead of the default Bullet physics "
+"engine, there are several known bugs with cylinder collision shapes. Using "
+"[CapsuleShape] or [BoxShape] instead is recommended."
+msgstr ""
+
+#: doc/classes/CylinderShape.xml
msgid "The cylinder's height."
msgstr ""
@@ -22104,7 +22149,10 @@ msgid ""
"[/codeblock]\n"
"[b]Note:[/b] The script is run in the Editor context, which means the output "
"is visible in the console window started with the Editor (stdout) instead of "
-"the usual Godot [b]Output[/b] dock."
+"the usual Godot [b]Output[/b] dock.\n"
+"[b]Note:[/b] EditorScript is reference counted, meaning it is destroyed when "
+"nothing references it. This can cause errors during asynchronous operations "
+"if there are no references to the script."
msgstr ""
#: doc/classes/EditorScript.xml
@@ -32816,7 +32864,9 @@ msgid ""
"The size of the light in Godot units. Only considered in baked lightmaps and "
"only if [member light_bake_mode] is set to [constant BAKE_ALL]. Increasing "
"this value will make the shadows appear blurrier. This can be used to "
-"simulate area lights to an extent."
+"simulate area lights to an extent.\n"
+"[b]Note:[/b] [member light_size] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/Light.xml
@@ -36114,7 +36164,10 @@ msgid ""
"use the [method get_next_location] function once every physics frame to "
"update the internal path logic of the NavigationAgent. The returned vector "
"position from this function should be used as the next movement position for "
-"the agent's parent Node."
+"the agent's parent Node.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues."
msgstr ""
#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
@@ -36362,7 +36415,10 @@ msgid ""
"use the [method get_next_location] function once every physics frame to "
"update the internal path logic of the NavigationAgent. The returned vector "
"position from this function should be used as the next movement position for "
-"the agent's parent Node."
+"the agent's parent Node.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues."
msgstr ""
#: doc/classes/NavigationAgent2D.xml
@@ -37072,6 +37128,9 @@ msgid ""
"modified velocity as-is might lead to pushing and agent outside of a "
"navigable area. This is a limitation of the collision avoidance system, any "
"more complex situation may require the use of the physics engine.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues.\n"
"This server keeps tracks of any call and executes them during the sync "
"phase. This means that you can request any change to the map, using any "
"thread, without worrying."
@@ -39878,7 +39937,9 @@ msgid ""
"The light's radius. Note that the effectively lit area may appear to be "
"smaller depending on the [member omni_attenuation] in use. No matter the "
"[member omni_attenuation] in use, the light will never reach anything "
-"outside this radius."
+"outside this radius.\n"
+"[b]Note:[/b] [member omni_range] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -40389,11 +40450,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] cache data directory according to the operating "
-"system's standards. On desktop platforms, this path can be overridden by "
-"setting the [code]XDG_CACHE_HOME[/code] environment variable before starting "
-"the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in "
-"Godot projects[/url] in the documentation for more information. See also "
-"[method get_config_dir] and [method get_data_dir].\n"
+"system's standards. On Linux, this path can be overridden by setting the "
+"[code]XDG_CACHE_HOME[/code] environment variable before starting the "
+"project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot "
+"projects[/url] in the documentation for more information. See also [method "
+"get_config_dir] and [method get_data_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -40427,11 +40488,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] user configuration directory according to the "
-"operating system's standards. On desktop platforms, this path can be "
-"overridden by setting the [code]XDG_CONFIG_HOME[/code] environment variable "
-"before starting the project. See [url=$DOCS_URL/tutorials/io/data_paths."
-"html]File paths in Godot projects[/url] in the documentation for more "
-"information. See also [method get_cache_dir] and [method get_data_dir].\n"
+"operating system's standards. On Linux, this path can be overridden by "
+"setting the [code]XDG_CONFIG_HOME[/code] environment variable before "
+"starting the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File "
+"paths in Godot projects[/url] in the documentation for more information. See "
+"also [method get_cache_dir] and [method get_data_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -40453,11 +40514,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] user data directory according to the operating "
-"system's standards. On desktop platforms, this path can be overridden by "
-"setting the [code]XDG_DATA_HOME[/code] environment variable before starting "
-"the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in "
-"Godot projects[/url] in the documentation for more information. See also "
-"[method get_cache_dir] and [method get_config_dir].\n"
+"system's standards. On Linux, this path can be overridden by setting the "
+"[code]XDG_DATA_HOME[/code] environment variable before starting the project. "
+"See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot "
+"projects[/url] in the documentation for more information. See also [method "
+"get_cache_dir] and [method get_config_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -42304,6 +42365,16 @@ msgid "Particle systems (2D)"
msgstr ""
#: doc/classes/Particles2D.xml
+msgid "2D Particles Demo"
+msgstr ""
+
+#: doc/classes/Particles2D.xml
+msgid ""
+"2D Dodge The Creeps Demo (uses GPUParticles2D for the trail behind the "
+"player)"
+msgstr ""
+
+#: doc/classes/Particles2D.xml
msgid "Returns a rectangle containing the positions of all existing particles."
msgstr ""
@@ -49896,15 +49967,22 @@ msgstr ""
#: doc/classes/ProjectSettings.xml
msgid ""
"If [code]true[/code], uses a fast post-processing filter to make banding "
-"significantly less visible. In some cases, debanding may introduce a "
-"slightly noticeable dithering pattern. It's recommended to enable debanding "
-"only when actually needed since the dithering pattern will make lossless-"
-"compressed screenshots larger.\n"
+"significantly less visible in 3D. 2D rendering is [i]not[/i] affected by "
+"debanding unless the [member Environment.background_mode] is [constant "
+"Environment.BG_CANVAS]. In this case, [member rendering/quality/"
+"intended_usage/framebuffer_allocation] must also be set to [b]3D[/b].\n"
+"In some cases, debanding may introduce a slightly noticeable dithering "
+"pattern. It's recommended to enable debanding only when actually needed "
+"since the dithering pattern will make lossless-compressed screenshots "
+"larger.\n"
"[b]Note:[/b] Only available on the GLES3 backend. [member rendering/quality/"
"depth/hdr] must also be [code]true[/code] for debanding to be effective.\n"
"[b]Note:[/b] There are known issues with debanding breaking rendering on "
"mobile platforms. Due to this, it is recommended to leave this option "
-"disabled when targeting mobile platforms."
+"disabled when targeting mobile platforms.\n"
+"[b]Note:[/b] This property is only read when the project starts. To set "
+"debanding at run-time, set [member Viewport.debanding] on the root "
+"[Viewport] instead."
msgstr ""
#: doc/classes/ProjectSettings.xml
@@ -51500,17 +51578,28 @@ msgstr ""
#: modules/regex/doc_classes/RegEx.xml
msgid ""
"Searches the text for the compiled pattern. Returns a [RegExMatch] container "
-"of the first matching result if found, otherwise [code]null[/code]. The "
-"region to search within can be specified without modifying where the start "
-"and end anchor would be."
+"of the first matching result if found, otherwise [code]null[/code].\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegEx.xml
msgid ""
"Searches the text for the compiled pattern. Returns an array of [RegExMatch] "
"containers for each non-overlapping result. If no results were found, an "
-"empty array is returned instead. The region to search within can be "
-"specified without modifying where the start and end anchor would be."
+"empty array is returned instead.\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegEx.xml
@@ -51519,8 +51608,14 @@ msgid ""
"specified string. Escapes and backreferences such as [code]$1[/code] and "
"[code]$name[/code] are expanded and resolved. By default, only the first "
"instance is replaced, but it can be changed for all instances (global "
-"replacement). The region to search within can be specified without modifying "
-"where the start and end anchor would be."
+"replacement).\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegExMatch.xml
@@ -54235,7 +54330,11 @@ msgid "Call a group immediately (calls are normally made on idle)."
msgstr ""
#: doc/classes/SceneTree.xml
-msgid "Call a group only once even if the call is executed many times."
+msgid ""
+"Call a group only once even if the call is executed many times.\n"
+"[b]Note:[/b] Arguments are not taken into account when deciding whether the "
+"call is unique or not. Therefore when the same method is called with "
+"different arguments, only the first call will be performed."
msgstr ""
#: doc/classes/SceneTree.xml
@@ -56072,7 +56171,9 @@ msgid ""
"[b]Note:[/b] Mixed negative scales in 3D are not decomposable from the "
"transformation matrix. Due to the way scale is represented with "
"transformation matrices in Godot, the scale values will either be all "
-"positive or all negative."
+"positive or all negative.\n"
+"[b]Note:[/b] Not all nodes are visually scaled by the [member scale] "
+"property. For example, [Light]s are not visually affected by [member scale]."
msgstr ""
#: doc/classes/Spatial.xml
@@ -57450,7 +57551,10 @@ msgid ""
msgstr ""
#: doc/classes/SpotLight.xml
-msgid "The spotlight's angle in degrees."
+msgid ""
+"The spotlight's angle in degrees.\n"
+"[b]Note:[/b] [member spot_angle] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/SpotLight.xml
@@ -57466,7 +57570,9 @@ msgid ""
"The maximal range that can be reached by the spotlight. Note that the "
"effectively lit area may appear to be smaller depending on the [member "
"spot_attenuation] in use. No matter the [member spot_attenuation] in use, "
-"the light will never reach anything outside this range."
+"the light will never reach anything outside this range.\n"
+"[b]Note:[/b] [member spot_range] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/SpringArm.xml
@@ -66703,10 +66809,15 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
"If [code]true[/code], uses a fast post-processing filter to make banding "
-"significantly less visible. In some cases, debanding may introduce a "
-"slightly noticeable dithering pattern. It's recommended to enable debanding "
-"only when actually needed since the dithering pattern will make lossless-"
-"compressed screenshots larger.\n"
+"significantly less visible in 3D. 2D rendering is [i]not[/i] affected by "
+"debanding unless the [member Environment.background_mode] is [constant "
+"Environment.BG_CANVAS]. In this case, [member usage] must also be set to "
+"[constant USAGE_3D]. See also [member ProjectSettings.rendering/quality/"
+"filters/use_debanding].\n"
+"In some cases, debanding may introduce a slightly noticeable dithering "
+"pattern. It's recommended to enable debanding only when actually needed "
+"since the dithering pattern will make lossless-compressed screenshots "
+"larger.\n"
"[b]Note:[/b] Only available on the GLES3 backend. [member hdr] must also be "
"[code]true[/code] for debanding to be effective."
msgstr ""
@@ -66717,8 +66828,8 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
-"If [code]true[/code], the viewport will disable 3D rendering. For actual "
-"disabling use [code]usage[/code]."
+"If [code]true[/code], the viewport will disable 3D rendering. To actually "
+"disable allocation of 3D buffers, set [member usage] instead."
msgstr ""
#: doc/classes/Viewport.xml
@@ -66870,7 +66981,9 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
-"The rendering mode of viewport.\n"
+"The viewport's rendering mode. This controls which buffers are allocated for "
+"the viewport (2D only, or 2D + 3D). 2D-only options can reduce memory usage "
+"and improve performance slightly, especially on low-end devices.\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."
@@ -67402,6 +67515,22 @@ msgid ""
"render object this [VisualInstance] is set to."
msgstr ""
+#: doc/classes/VisualInstance.xml
+msgid ""
+"The sorting offset used by this [VisualInstance]. Adjusting it to a higher "
+"value will make the [VisualInstance] reliably draw on top of other "
+"[VisualInstance]s that are otherwise positioned at the same spot."
+msgstr ""
+
+#: doc/classes/VisualInstance.xml
+msgid ""
+"If [code]true[/code], the object is sorted based on the [AABB] center. "
+"Sorted based on the global position otherwise.\n"
+"The [AABB] center based sorting is generally more accurate for 3D models. "
+"The position based sorting instead allows to better control the drawing "
+"order when working with [Particles] and [CPUParticles]."
+msgstr ""
+
#: modules/visual_script/doc_classes/VisualScript.xml
msgid "A script implemented in the Visual Script programming environment."
msgstr ""
diff --git a/doc/translations/hu.po b/doc/translations/hu.po
index a962de15e5..e99babd548 100644
--- a/doc/translations/hu.po
+++ b/doc/translations/hu.po
@@ -495,7 +495,8 @@ msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
-"Returns an array of dictionaries representing the current call stack.\n"
+"Returns an array of dictionaries representing the current call stack. See "
+"also [method print_stack].\n"
"[codeblock]\n"
"func _ready():\n"
" foo()\n"
@@ -510,7 +511,11 @@ msgid ""
"[codeblock]\n"
"[{function:bar, line:12, source:res://script.gd}, {function:foo, line:9, "
"source:res://script.gd}, {function:_ready, line:6, source:res://script.gd}]\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] [method get_stack] only works if the running instance is "
+"connected to a debugging server (i.e. an editor instance). [method "
+"get_stack] will not work in projects exported in release mode, or in "
+"projects exported in debug mode if not connected to a debugging server."
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -883,12 +888,16 @@ msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
-"Prints a stack track at code location, only works when running with debugger "
-"turned on.\n"
+"Prints a stack trace at the current code location. See also [method "
+"get_stack].\n"
"Output in the console would look something like this:\n"
"[codeblock]\n"
"Frame 0 - res://test.gd:16 in function '_process'\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] [method print_stack] only works if the running instance is "
+"connected to a debugging server (i.e. an editor instance). [method "
+"print_stack] will not work in projects exported in release mode, or in "
+"projects exported in debug mode if not connected to a debugging server."
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -3499,6 +3508,26 @@ msgid "Hints that an image is compressed using lossless compression."
msgstr ""
#: doc/classes/@GlobalScope.xml
+msgid ""
+"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:\n"
+"[codeblock]\n"
+"hint_string = \"%s:\" % [TYPE_INT] # Array of inteters.\n"
+"hint_string = \"%s:%s:\" % [TYPE_ARRAY, TYPE_REAL] # Two-dimensional array "
+"of floats.\n"
+"hint_string = \"%s/%s:Resource\" % [TYPE_OBJECT, TYPE_OBJECT] # Array of "
+"resources.\n"
+"hint_string = \"%s:%s/%s:Resource\" % [TYPE_ARRAY, TYPE_OBJECT, TYPE_OBJECT] "
+"# Two-dimensional array of resources.\n"
+"[/codeblock]\n"
+"[b]Note:[/b] The final colon is required to specify for properly detecting "
+"built-in types."
+msgstr ""
+
+#: doc/classes/@GlobalScope.xml
msgid "The property is serialized and saved in the scene file (default)."
msgstr ""
@@ -4183,8 +4212,7 @@ msgstr ""
#: doc/classes/AudioStreamPlayer.xml doc/classes/Button.xml
#: doc/classes/CanvasLayer.xml doc/classes/CollisionShape2D.xml
#: doc/classes/ColorRect.xml doc/classes/Input.xml doc/classes/InputEvent.xml
-#: doc/classes/InputEventAction.xml doc/classes/Label.xml
-#: doc/classes/Particles2D.xml doc/classes/Timer.xml
+#: doc/classes/InputEventAction.xml doc/classes/Label.xml doc/classes/Timer.xml
#: doc/classes/VisibilityNotifier2D.xml
msgid "2D Dodge The Creeps Demo"
msgstr ""
@@ -7101,7 +7129,10 @@ msgid ""
"var array = []\n"
"array.resize(10)\n"
"array.fill(0) # Initialize the 10 elements to 0.\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] If [code]value[/code] is of a reference type ([Object]-derived, "
+"[Array], [Dictionary], etc.) then the array is filled with the references to "
+"the same object, i.e. no duplicates are created."
msgstr ""
#: doc/classes/Array.xml doc/classes/PoolByteArray.xml
@@ -7286,6 +7317,9 @@ msgstr ""
#: doc/classes/Array.xml
msgid ""
"Sorts the array.\n"
+"[b]Note:[/b] The sorting algorithm used is not [url=https://en.wikipedia.org/"
+"wiki/Sorting_algorithm#Stability]stable[/url]. This means that values "
+"considered equal may have their order changed when using [method sort].\n"
"[b]Note:[/b] Strings are sorted in alphabetical order (as opposed to natural "
"order). This may lead to unexpected behavior when sorting an array of "
"strings ending with a sequence of numbers. Consider the following example:\n"
@@ -7305,9 +7339,13 @@ msgid ""
"For two elements [code]a[/code] and [code]b[/code], if the given method "
"returns [code]true[/code], element [code]b[/code] will be after element "
"[code]a[/code] in the array.\n"
+"[b]Note:[/b] The sorting algorithm used is not [url=https://en.wikipedia.org/"
+"wiki/Sorting_algorithm#Stability]stable[/url]. This means that values "
+"considered equal may have their order changed when using [method "
+"sort_custom].\n"
"[b]Note:[/b] You cannot randomize the return value as the heapsort algorithm "
-"expects a deterministic result. Doing so will result in unexpected "
-"behavior.\n"
+"expects a deterministic result. Randomizing the return value will result in "
+"unexpected behavior.\n"
"[codeblock]\n"
"class MyCustomSorter:\n"
" static func sort_ascending(a, b):\n"
@@ -9945,10 +9983,9 @@ msgstr ""
#: doc/classes/AudioStreamGeneratorPlayback.xml
msgid ""
-"Returns the number of audio data frames left to play. If this returned "
-"number reaches [code]0[/code], the audio will stop playing until frames are "
-"added again. Therefore, make sure your script can always generate and push "
-"new audio frames fast enough to avoid audio cracking."
+"Returns the number of frames that can be pushed to the audio sample data "
+"buffer without overflowing it. If the result is [code]0[/code], the buffer "
+"is full."
msgstr ""
#: doc/classes/AudioStreamGeneratorPlayback.xml
@@ -10480,14 +10517,14 @@ msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
"Node for back-buffering the currently-displayed screen. The region defined "
-"in the BackBufferCopy node is buffered with the content of the screen it "
+"in the [BackBufferCopy] node is buffered with the content of the screen it "
"covers, or the entire screen according to the copy mode set. Use the "
"[code]texture(SCREEN_TEXTURE, ...)[/code] function in your shader scripts to "
"access the buffer.\n"
"[b]Note:[/b] Since this node inherits from [Node2D] (and not [Control]), "
"anchors and margins won't apply to child [Control]-derived nodes. This can "
"be problematic when resizing the window. To avoid this, add [Control]-"
-"derived nodes as [i]siblings[/i] to the BackBufferCopy node instead of "
+"derived nodes as [i]siblings[/i] to the [BackBufferCopy] node instead of "
"adding them as children."
msgstr ""
@@ -10497,22 +10534,22 @@ msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
-"The area covered by the BackBufferCopy. Only used if [member copy_mode] is "
+"The area covered by the [BackBufferCopy]. Only used if [member copy_mode] is "
"[constant COPY_MODE_RECT]."
msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
-"Disables the buffering mode. This means the BackBufferCopy node will "
+"Disables the buffering mode. This means the [BackBufferCopy] node will "
"directly use the portion of screen it covers."
msgstr ""
#: doc/classes/BackBufferCopy.xml
-msgid "BackBufferCopy buffers a rectangular region."
+msgid "[BackBufferCopy] buffers a rectangular region."
msgstr ""
#: doc/classes/BackBufferCopy.xml
-msgid "BackBufferCopy buffers the entire screen."
+msgid "[BackBufferCopy] buffers the entire screen."
msgstr ""
#: doc/classes/BakedLightmap.xml
@@ -19292,6 +19329,14 @@ msgid "Cylinder shape for collisions."
msgstr ""
#: doc/classes/CylinderShape.xml
+msgid ""
+"Cylinder shape for collisions.\n"
+"[b]Note:[/b] When using GodotPhysics instead of the default Bullet physics "
+"engine, there are several known bugs with cylinder collision shapes. Using "
+"[CapsuleShape] or [BoxShape] instead is recommended."
+msgstr ""
+
+#: doc/classes/CylinderShape.xml
msgid "The cylinder's height."
msgstr ""
@@ -22124,7 +22169,10 @@ msgid ""
"[/codeblock]\n"
"[b]Note:[/b] The script is run in the Editor context, which means the output "
"is visible in the console window started with the Editor (stdout) instead of "
-"the usual Godot [b]Output[/b] dock."
+"the usual Godot [b]Output[/b] dock.\n"
+"[b]Note:[/b] EditorScript is reference counted, meaning it is destroyed when "
+"nothing references it. This can cause errors during asynchronous operations "
+"if there are no references to the script."
msgstr ""
#: doc/classes/EditorScript.xml
@@ -32836,7 +32884,9 @@ msgid ""
"The size of the light in Godot units. Only considered in baked lightmaps and "
"only if [member light_bake_mode] is set to [constant BAKE_ALL]. Increasing "
"this value will make the shadows appear blurrier. This can be used to "
-"simulate area lights to an extent."
+"simulate area lights to an extent.\n"
+"[b]Note:[/b] [member light_size] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/Light.xml
@@ -36134,7 +36184,10 @@ msgid ""
"use the [method get_next_location] function once every physics frame to "
"update the internal path logic of the NavigationAgent. The returned vector "
"position from this function should be used as the next movement position for "
-"the agent's parent Node."
+"the agent's parent Node.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues."
msgstr ""
#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
@@ -36382,7 +36435,10 @@ msgid ""
"use the [method get_next_location] function once every physics frame to "
"update the internal path logic of the NavigationAgent. The returned vector "
"position from this function should be used as the next movement position for "
-"the agent's parent Node."
+"the agent's parent Node.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues."
msgstr ""
#: doc/classes/NavigationAgent2D.xml
@@ -37092,6 +37148,9 @@ msgid ""
"modified velocity as-is might lead to pushing and agent outside of a "
"navigable area. This is a limitation of the collision avoidance system, any "
"more complex situation may require the use of the physics engine.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues.\n"
"This server keeps tracks of any call and executes them during the sync "
"phase. This means that you can request any change to the map, using any "
"thread, without worrying."
@@ -39898,7 +39957,9 @@ msgid ""
"The light's radius. Note that the effectively lit area may appear to be "
"smaller depending on the [member omni_attenuation] in use. No matter the "
"[member omni_attenuation] in use, the light will never reach anything "
-"outside this radius."
+"outside this radius.\n"
+"[b]Note:[/b] [member omni_range] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -40409,11 +40470,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] cache data directory according to the operating "
-"system's standards. On desktop platforms, this path can be overridden by "
-"setting the [code]XDG_CACHE_HOME[/code] environment variable before starting "
-"the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in "
-"Godot projects[/url] in the documentation for more information. See also "
-"[method get_config_dir] and [method get_data_dir].\n"
+"system's standards. On Linux, this path can be overridden by setting the "
+"[code]XDG_CACHE_HOME[/code] environment variable before starting the "
+"project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot "
+"projects[/url] in the documentation for more information. See also [method "
+"get_config_dir] and [method get_data_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -40447,11 +40508,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] user configuration directory according to the "
-"operating system's standards. On desktop platforms, this path can be "
-"overridden by setting the [code]XDG_CONFIG_HOME[/code] environment variable "
-"before starting the project. See [url=$DOCS_URL/tutorials/io/data_paths."
-"html]File paths in Godot projects[/url] in the documentation for more "
-"information. See also [method get_cache_dir] and [method get_data_dir].\n"
+"operating system's standards. On Linux, this path can be overridden by "
+"setting the [code]XDG_CONFIG_HOME[/code] environment variable before "
+"starting the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File "
+"paths in Godot projects[/url] in the documentation for more information. See "
+"also [method get_cache_dir] and [method get_data_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -40473,11 +40534,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] user data directory according to the operating "
-"system's standards. On desktop platforms, this path can be overridden by "
-"setting the [code]XDG_DATA_HOME[/code] environment variable before starting "
-"the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in "
-"Godot projects[/url] in the documentation for more information. See also "
-"[method get_cache_dir] and [method get_config_dir].\n"
+"system's standards. On Linux, this path can be overridden by setting the "
+"[code]XDG_DATA_HOME[/code] environment variable before starting the project. "
+"See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot "
+"projects[/url] in the documentation for more information. See also [method "
+"get_cache_dir] and [method get_config_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -42324,6 +42385,16 @@ msgid "Particle systems (2D)"
msgstr ""
#: doc/classes/Particles2D.xml
+msgid "2D Particles Demo"
+msgstr ""
+
+#: doc/classes/Particles2D.xml
+msgid ""
+"2D Dodge The Creeps Demo (uses GPUParticles2D for the trail behind the "
+"player)"
+msgstr ""
+
+#: doc/classes/Particles2D.xml
msgid "Returns a rectangle containing the positions of all existing particles."
msgstr ""
@@ -49916,15 +49987,22 @@ msgstr ""
#: doc/classes/ProjectSettings.xml
msgid ""
"If [code]true[/code], uses a fast post-processing filter to make banding "
-"significantly less visible. In some cases, debanding may introduce a "
-"slightly noticeable dithering pattern. It's recommended to enable debanding "
-"only when actually needed since the dithering pattern will make lossless-"
-"compressed screenshots larger.\n"
+"significantly less visible in 3D. 2D rendering is [i]not[/i] affected by "
+"debanding unless the [member Environment.background_mode] is [constant "
+"Environment.BG_CANVAS]. In this case, [member rendering/quality/"
+"intended_usage/framebuffer_allocation] must also be set to [b]3D[/b].\n"
+"In some cases, debanding may introduce a slightly noticeable dithering "
+"pattern. It's recommended to enable debanding only when actually needed "
+"since the dithering pattern will make lossless-compressed screenshots "
+"larger.\n"
"[b]Note:[/b] Only available on the GLES3 backend. [member rendering/quality/"
"depth/hdr] must also be [code]true[/code] for debanding to be effective.\n"
"[b]Note:[/b] There are known issues with debanding breaking rendering on "
"mobile platforms. Due to this, it is recommended to leave this option "
-"disabled when targeting mobile platforms."
+"disabled when targeting mobile platforms.\n"
+"[b]Note:[/b] This property is only read when the project starts. To set "
+"debanding at run-time, set [member Viewport.debanding] on the root "
+"[Viewport] instead."
msgstr ""
#: doc/classes/ProjectSettings.xml
@@ -51520,17 +51598,28 @@ msgstr ""
#: modules/regex/doc_classes/RegEx.xml
msgid ""
"Searches the text for the compiled pattern. Returns a [RegExMatch] container "
-"of the first matching result if found, otherwise [code]null[/code]. The "
-"region to search within can be specified without modifying where the start "
-"and end anchor would be."
+"of the first matching result if found, otherwise [code]null[/code].\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegEx.xml
msgid ""
"Searches the text for the compiled pattern. Returns an array of [RegExMatch] "
"containers for each non-overlapping result. If no results were found, an "
-"empty array is returned instead. The region to search within can be "
-"specified without modifying where the start and end anchor would be."
+"empty array is returned instead.\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegEx.xml
@@ -51539,8 +51628,14 @@ msgid ""
"specified string. Escapes and backreferences such as [code]$1[/code] and "
"[code]$name[/code] are expanded and resolved. By default, only the first "
"instance is replaced, but it can be changed for all instances (global "
-"replacement). The region to search within can be specified without modifying "
-"where the start and end anchor would be."
+"replacement).\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegExMatch.xml
@@ -54255,7 +54350,11 @@ msgid "Call a group immediately (calls are normally made on idle)."
msgstr ""
#: doc/classes/SceneTree.xml
-msgid "Call a group only once even if the call is executed many times."
+msgid ""
+"Call a group only once even if the call is executed many times.\n"
+"[b]Note:[/b] Arguments are not taken into account when deciding whether the "
+"call is unique or not. Therefore when the same method is called with "
+"different arguments, only the first call will be performed."
msgstr ""
#: doc/classes/SceneTree.xml
@@ -56092,7 +56191,9 @@ msgid ""
"[b]Note:[/b] Mixed negative scales in 3D are not decomposable from the "
"transformation matrix. Due to the way scale is represented with "
"transformation matrices in Godot, the scale values will either be all "
-"positive or all negative."
+"positive or all negative.\n"
+"[b]Note:[/b] Not all nodes are visually scaled by the [member scale] "
+"property. For example, [Light]s are not visually affected by [member scale]."
msgstr ""
#: doc/classes/Spatial.xml
@@ -57470,7 +57571,10 @@ msgid ""
msgstr ""
#: doc/classes/SpotLight.xml
-msgid "The spotlight's angle in degrees."
+msgid ""
+"The spotlight's angle in degrees.\n"
+"[b]Note:[/b] [member spot_angle] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/SpotLight.xml
@@ -57486,7 +57590,9 @@ msgid ""
"The maximal range that can be reached by the spotlight. Note that the "
"effectively lit area may appear to be smaller depending on the [member "
"spot_attenuation] in use. No matter the [member spot_attenuation] in use, "
-"the light will never reach anything outside this range."
+"the light will never reach anything outside this range.\n"
+"[b]Note:[/b] [member spot_range] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/SpringArm.xml
@@ -66723,10 +66829,15 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
"If [code]true[/code], uses a fast post-processing filter to make banding "
-"significantly less visible. In some cases, debanding may introduce a "
-"slightly noticeable dithering pattern. It's recommended to enable debanding "
-"only when actually needed since the dithering pattern will make lossless-"
-"compressed screenshots larger.\n"
+"significantly less visible in 3D. 2D rendering is [i]not[/i] affected by "
+"debanding unless the [member Environment.background_mode] is [constant "
+"Environment.BG_CANVAS]. In this case, [member usage] must also be set to "
+"[constant USAGE_3D]. See also [member ProjectSettings.rendering/quality/"
+"filters/use_debanding].\n"
+"In some cases, debanding may introduce a slightly noticeable dithering "
+"pattern. It's recommended to enable debanding only when actually needed "
+"since the dithering pattern will make lossless-compressed screenshots "
+"larger.\n"
"[b]Note:[/b] Only available on the GLES3 backend. [member hdr] must also be "
"[code]true[/code] for debanding to be effective."
msgstr ""
@@ -66737,8 +66848,8 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
-"If [code]true[/code], the viewport will disable 3D rendering. For actual "
-"disabling use [code]usage[/code]."
+"If [code]true[/code], the viewport will disable 3D rendering. To actually "
+"disable allocation of 3D buffers, set [member usage] instead."
msgstr ""
#: doc/classes/Viewport.xml
@@ -66890,7 +67001,9 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
-"The rendering mode of viewport.\n"
+"The viewport's rendering mode. This controls which buffers are allocated for "
+"the viewport (2D only, or 2D + 3D). 2D-only options can reduce memory usage "
+"and improve performance slightly, especially on low-end devices.\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."
@@ -67422,6 +67535,22 @@ msgid ""
"render object this [VisualInstance] is set to."
msgstr ""
+#: doc/classes/VisualInstance.xml
+msgid ""
+"The sorting offset used by this [VisualInstance]. Adjusting it to a higher "
+"value will make the [VisualInstance] reliably draw on top of other "
+"[VisualInstance]s that are otherwise positioned at the same spot."
+msgstr ""
+
+#: doc/classes/VisualInstance.xml
+msgid ""
+"If [code]true[/code], the object is sorted based on the [AABB] center. "
+"Sorted based on the global position otherwise.\n"
+"The [AABB] center based sorting is generally more accurate for 3D models. "
+"The position based sorting instead allows to better control the drawing "
+"order when working with [Particles] and [CPUParticles]."
+msgstr ""
+
#: modules/visual_script/doc_classes/VisualScript.xml
msgid "A script implemented in the Visual Script programming environment."
msgstr ""
diff --git a/doc/translations/id.po b/doc/translations/id.po
index 249ed80079..ad63a828e5 100644
--- a/doc/translations/id.po
+++ b/doc/translations/id.po
@@ -695,7 +695,8 @@ msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
-"Returns an array of dictionaries representing the current call stack.\n"
+"Returns an array of dictionaries representing the current call stack. See "
+"also [method print_stack].\n"
"[codeblock]\n"
"func _ready():\n"
" foo()\n"
@@ -710,7 +711,11 @@ msgid ""
"[codeblock]\n"
"[{function:bar, line:12, source:res://script.gd}, {function:foo, line:9, "
"source:res://script.gd}, {function:_ready, line:6, source:res://script.gd}]\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] [method get_stack] only works if the running instance is "
+"connected to a debugging server (i.e. an editor instance). [method "
+"get_stack] will not work in projects exported in release mode, or in "
+"projects exported in debug mode if not connected to a debugging server."
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -1220,21 +1225,18 @@ msgstr ""
"[/codeblock]"
#: modules/gdscript/doc_classes/@GDScript.xml
-#, fuzzy
msgid ""
-"Prints a stack track at code location, only works when running with debugger "
-"turned on.\n"
+"Prints a stack trace at the current code location. See also [method "
+"get_stack].\n"
"Output in the console would look something like this:\n"
"[codeblock]\n"
"Frame 0 - res://test.gd:16 in function '_process'\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] [method print_stack] only works if the running instance is "
+"connected to a debugging server (i.e. an editor instance). [method "
+"print_stack] will not work in projects exported in release mode, or in "
+"projects exported in debug mode if not connected to a debugging server."
msgstr ""
-"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
@@ -3889,6 +3891,26 @@ msgid "Hints that an image is compressed using lossless compression."
msgstr ""
#: doc/classes/@GlobalScope.xml
+msgid ""
+"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:\n"
+"[codeblock]\n"
+"hint_string = \"%s:\" % [TYPE_INT] # Array of inteters.\n"
+"hint_string = \"%s:%s:\" % [TYPE_ARRAY, TYPE_REAL] # Two-dimensional array "
+"of floats.\n"
+"hint_string = \"%s/%s:Resource\" % [TYPE_OBJECT, TYPE_OBJECT] # Array of "
+"resources.\n"
+"hint_string = \"%s:%s/%s:Resource\" % [TYPE_ARRAY, TYPE_OBJECT, TYPE_OBJECT] "
+"# Two-dimensional array of resources.\n"
+"[/codeblock]\n"
+"[b]Note:[/b] The final colon is required to specify for properly detecting "
+"built-in types."
+msgstr ""
+
+#: doc/classes/@GlobalScope.xml
msgid "The property is serialized and saved in the scene file (default)."
msgstr ""
@@ -4573,8 +4595,7 @@ msgstr ""
#: doc/classes/AudioStreamPlayer.xml doc/classes/Button.xml
#: doc/classes/CanvasLayer.xml doc/classes/CollisionShape2D.xml
#: doc/classes/ColorRect.xml doc/classes/Input.xml doc/classes/InputEvent.xml
-#: doc/classes/InputEventAction.xml doc/classes/Label.xml
-#: doc/classes/Particles2D.xml doc/classes/Timer.xml
+#: doc/classes/InputEventAction.xml doc/classes/Label.xml doc/classes/Timer.xml
#: doc/classes/VisibilityNotifier2D.xml
msgid "2D Dodge The Creeps Demo"
msgstr ""
@@ -7492,7 +7513,10 @@ msgid ""
"var array = []\n"
"array.resize(10)\n"
"array.fill(0) # Initialize the 10 elements to 0.\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] If [code]value[/code] is of a reference type ([Object]-derived, "
+"[Array], [Dictionary], etc.) then the array is filled with the references to "
+"the same object, i.e. no duplicates are created."
msgstr ""
#: doc/classes/Array.xml doc/classes/PoolByteArray.xml
@@ -7677,6 +7701,9 @@ msgstr ""
#: doc/classes/Array.xml
msgid ""
"Sorts the array.\n"
+"[b]Note:[/b] The sorting algorithm used is not [url=https://en.wikipedia.org/"
+"wiki/Sorting_algorithm#Stability]stable[/url]. This means that values "
+"considered equal may have their order changed when using [method sort].\n"
"[b]Note:[/b] Strings are sorted in alphabetical order (as opposed to natural "
"order). This may lead to unexpected behavior when sorting an array of "
"strings ending with a sequence of numbers. Consider the following example:\n"
@@ -7696,9 +7723,13 @@ msgid ""
"For two elements [code]a[/code] and [code]b[/code], if the given method "
"returns [code]true[/code], element [code]b[/code] will be after element "
"[code]a[/code] in the array.\n"
+"[b]Note:[/b] The sorting algorithm used is not [url=https://en.wikipedia.org/"
+"wiki/Sorting_algorithm#Stability]stable[/url]. This means that values "
+"considered equal may have their order changed when using [method "
+"sort_custom].\n"
"[b]Note:[/b] You cannot randomize the return value as the heapsort algorithm "
-"expects a deterministic result. Doing so will result in unexpected "
-"behavior.\n"
+"expects a deterministic result. Randomizing the return value will result in "
+"unexpected behavior.\n"
"[codeblock]\n"
"class MyCustomSorter:\n"
" static func sort_ascending(a, b):\n"
@@ -10336,10 +10367,9 @@ msgstr ""
#: doc/classes/AudioStreamGeneratorPlayback.xml
msgid ""
-"Returns the number of audio data frames left to play. If this returned "
-"number reaches [code]0[/code], the audio will stop playing until frames are "
-"added again. Therefore, make sure your script can always generate and push "
-"new audio frames fast enough to avoid audio cracking."
+"Returns the number of frames that can be pushed to the audio sample data "
+"buffer without overflowing it. If the result is [code]0[/code], the buffer "
+"is full."
msgstr ""
#: doc/classes/AudioStreamGeneratorPlayback.xml
@@ -10871,14 +10901,14 @@ msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
"Node for back-buffering the currently-displayed screen. The region defined "
-"in the BackBufferCopy node is buffered with the content of the screen it "
+"in the [BackBufferCopy] node is buffered with the content of the screen it "
"covers, or the entire screen according to the copy mode set. Use the "
"[code]texture(SCREEN_TEXTURE, ...)[/code] function in your shader scripts to "
"access the buffer.\n"
"[b]Note:[/b] Since this node inherits from [Node2D] (and not [Control]), "
"anchors and margins won't apply to child [Control]-derived nodes. This can "
"be problematic when resizing the window. To avoid this, add [Control]-"
-"derived nodes as [i]siblings[/i] to the BackBufferCopy node instead of "
+"derived nodes as [i]siblings[/i] to the [BackBufferCopy] node instead of "
"adding them as children."
msgstr ""
@@ -10888,22 +10918,22 @@ msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
-"The area covered by the BackBufferCopy. Only used if [member copy_mode] is "
+"The area covered by the [BackBufferCopy]. Only used if [member copy_mode] is "
"[constant COPY_MODE_RECT]."
msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
-"Disables the buffering mode. This means the BackBufferCopy node will "
+"Disables the buffering mode. This means the [BackBufferCopy] node will "
"directly use the portion of screen it covers."
msgstr ""
#: doc/classes/BackBufferCopy.xml
-msgid "BackBufferCopy buffers a rectangular region."
+msgid "[BackBufferCopy] buffers a rectangular region."
msgstr ""
#: doc/classes/BackBufferCopy.xml
-msgid "BackBufferCopy buffers the entire screen."
+msgid "[BackBufferCopy] buffers the entire screen."
msgstr ""
#: doc/classes/BakedLightmap.xml
@@ -19685,6 +19715,14 @@ msgid "Cylinder shape for collisions."
msgstr ""
#: doc/classes/CylinderShape.xml
+msgid ""
+"Cylinder shape for collisions.\n"
+"[b]Note:[/b] When using GodotPhysics instead of the default Bullet physics "
+"engine, there are several known bugs with cylinder collision shapes. Using "
+"[CapsuleShape] or [BoxShape] instead is recommended."
+msgstr ""
+
+#: doc/classes/CylinderShape.xml
msgid "The cylinder's height."
msgstr ""
@@ -22517,7 +22555,10 @@ msgid ""
"[/codeblock]\n"
"[b]Note:[/b] The script is run in the Editor context, which means the output "
"is visible in the console window started with the Editor (stdout) instead of "
-"the usual Godot [b]Output[/b] dock."
+"the usual Godot [b]Output[/b] dock.\n"
+"[b]Note:[/b] EditorScript is reference counted, meaning it is destroyed when "
+"nothing references it. This can cause errors during asynchronous operations "
+"if there are no references to the script."
msgstr ""
#: doc/classes/EditorScript.xml
@@ -33240,7 +33281,9 @@ msgid ""
"The size of the light in Godot units. Only considered in baked lightmaps and "
"only if [member light_bake_mode] is set to [constant BAKE_ALL]. Increasing "
"this value will make the shadows appear blurrier. This can be used to "
-"simulate area lights to an extent."
+"simulate area lights to an extent.\n"
+"[b]Note:[/b] [member light_size] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/Light.xml
@@ -36561,7 +36604,10 @@ msgid ""
"use the [method get_next_location] function once every physics frame to "
"update the internal path logic of the NavigationAgent. The returned vector "
"position from this function should be used as the next movement position for "
-"the agent's parent Node."
+"the agent's parent Node.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues."
msgstr ""
#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
@@ -36810,7 +36856,10 @@ msgid ""
"use the [method get_next_location] function once every physics frame to "
"update the internal path logic of the NavigationAgent. The returned vector "
"position from this function should be used as the next movement position for "
-"the agent's parent Node."
+"the agent's parent Node.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues."
msgstr ""
#: doc/classes/NavigationAgent2D.xml
@@ -37521,6 +37570,9 @@ msgid ""
"modified velocity as-is might lead to pushing and agent outside of a "
"navigable area. This is a limitation of the collision avoidance system, any "
"more complex situation may require the use of the physics engine.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues.\n"
"This server keeps tracks of any call and executes them during the sync "
"phase. This means that you can request any change to the map, using any "
"thread, without worrying."
@@ -40329,7 +40381,9 @@ msgid ""
"The light's radius. Note that the effectively lit area may appear to be "
"smaller depending on the [member omni_attenuation] in use. No matter the "
"[member omni_attenuation] in use, the light will never reach anything "
-"outside this radius."
+"outside this radius.\n"
+"[b]Note:[/b] [member omni_range] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -40842,11 +40896,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] cache data directory according to the operating "
-"system's standards. On desktop platforms, this path can be overridden by "
-"setting the [code]XDG_CACHE_HOME[/code] environment variable before starting "
-"the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in "
-"Godot projects[/url] in the documentation for more information. See also "
-"[method get_config_dir] and [method get_data_dir].\n"
+"system's standards. On Linux, this path can be overridden by setting the "
+"[code]XDG_CACHE_HOME[/code] environment variable before starting the "
+"project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot "
+"projects[/url] in the documentation for more information. See also [method "
+"get_config_dir] and [method get_data_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -40880,11 +40934,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] user configuration directory according to the "
-"operating system's standards. On desktop platforms, this path can be "
-"overridden by setting the [code]XDG_CONFIG_HOME[/code] environment variable "
-"before starting the project. See [url=$DOCS_URL/tutorials/io/data_paths."
-"html]File paths in Godot projects[/url] in the documentation for more "
-"information. See also [method get_cache_dir] and [method get_data_dir].\n"
+"operating system's standards. On Linux, this path can be overridden by "
+"setting the [code]XDG_CONFIG_HOME[/code] environment variable before "
+"starting the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File "
+"paths in Godot projects[/url] in the documentation for more information. See "
+"also [method get_cache_dir] and [method get_data_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -40906,11 +40960,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] user data directory according to the operating "
-"system's standards. On desktop platforms, this path can be overridden by "
-"setting the [code]XDG_DATA_HOME[/code] environment variable before starting "
-"the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in "
-"Godot projects[/url] in the documentation for more information. See also "
-"[method get_cache_dir] and [method get_config_dir].\n"
+"system's standards. On Linux, this path can be overridden by setting the "
+"[code]XDG_DATA_HOME[/code] environment variable before starting the project. "
+"See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot "
+"projects[/url] in the documentation for more information. See also [method "
+"get_cache_dir] and [method get_config_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -42770,6 +42824,16 @@ msgid "Particle systems (2D)"
msgstr ""
#: doc/classes/Particles2D.xml
+msgid "2D Particles Demo"
+msgstr ""
+
+#: doc/classes/Particles2D.xml
+msgid ""
+"2D Dodge The Creeps Demo (uses GPUParticles2D for the trail behind the "
+"player)"
+msgstr ""
+
+#: doc/classes/Particles2D.xml
msgid "Returns a rectangle containing the positions of all existing particles."
msgstr ""
@@ -50367,15 +50431,22 @@ msgstr ""
#: doc/classes/ProjectSettings.xml
msgid ""
"If [code]true[/code], uses a fast post-processing filter to make banding "
-"significantly less visible. In some cases, debanding may introduce a "
-"slightly noticeable dithering pattern. It's recommended to enable debanding "
-"only when actually needed since the dithering pattern will make lossless-"
-"compressed screenshots larger.\n"
+"significantly less visible in 3D. 2D rendering is [i]not[/i] affected by "
+"debanding unless the [member Environment.background_mode] is [constant "
+"Environment.BG_CANVAS]. In this case, [member rendering/quality/"
+"intended_usage/framebuffer_allocation] must also be set to [b]3D[/b].\n"
+"In some cases, debanding may introduce a slightly noticeable dithering "
+"pattern. It's recommended to enable debanding only when actually needed "
+"since the dithering pattern will make lossless-compressed screenshots "
+"larger.\n"
"[b]Note:[/b] Only available on the GLES3 backend. [member rendering/quality/"
"depth/hdr] must also be [code]true[/code] for debanding to be effective.\n"
"[b]Note:[/b] There are known issues with debanding breaking rendering on "
"mobile platforms. Due to this, it is recommended to leave this option "
-"disabled when targeting mobile platforms."
+"disabled when targeting mobile platforms.\n"
+"[b]Note:[/b] This property is only read when the project starts. To set "
+"debanding at run-time, set [member Viewport.debanding] on the root "
+"[Viewport] instead."
msgstr ""
#: doc/classes/ProjectSettings.xml
@@ -51971,17 +52042,28 @@ msgstr ""
#: modules/regex/doc_classes/RegEx.xml
msgid ""
"Searches the text for the compiled pattern. Returns a [RegExMatch] container "
-"of the first matching result if found, otherwise [code]null[/code]. The "
-"region to search within can be specified without modifying where the start "
-"and end anchor would be."
+"of the first matching result if found, otherwise [code]null[/code].\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegEx.xml
msgid ""
"Searches the text for the compiled pattern. Returns an array of [RegExMatch] "
"containers for each non-overlapping result. If no results were found, an "
-"empty array is returned instead. The region to search within can be "
-"specified without modifying where the start and end anchor would be."
+"empty array is returned instead.\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegEx.xml
@@ -51990,8 +52072,14 @@ msgid ""
"specified string. Escapes and backreferences such as [code]$1[/code] and "
"[code]$name[/code] are expanded and resolved. By default, only the first "
"instance is replaced, but it can be changed for all instances (global "
-"replacement). The region to search within can be specified without modifying "
-"where the start and end anchor would be."
+"replacement).\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegExMatch.xml
@@ -54707,7 +54795,11 @@ msgid "Call a group immediately (calls are normally made on idle)."
msgstr ""
#: doc/classes/SceneTree.xml
-msgid "Call a group only once even if the call is executed many times."
+msgid ""
+"Call a group only once even if the call is executed many times.\n"
+"[b]Note:[/b] Arguments are not taken into account when deciding whether the "
+"call is unique or not. Therefore when the same method is called with "
+"different arguments, only the first call will be performed."
msgstr ""
#: doc/classes/SceneTree.xml
@@ -56544,7 +56636,9 @@ msgid ""
"[b]Note:[/b] Mixed negative scales in 3D are not decomposable from the "
"transformation matrix. Due to the way scale is represented with "
"transformation matrices in Godot, the scale values will either be all "
-"positive or all negative."
+"positive or all negative.\n"
+"[b]Note:[/b] Not all nodes are visually scaled by the [member scale] "
+"property. For example, [Light]s are not visually affected by [member scale]."
msgstr ""
#: doc/classes/Spatial.xml
@@ -57922,7 +58016,10 @@ msgid ""
msgstr ""
#: doc/classes/SpotLight.xml
-msgid "The spotlight's angle in degrees."
+msgid ""
+"The spotlight's angle in degrees.\n"
+"[b]Note:[/b] [member spot_angle] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/SpotLight.xml
@@ -57938,7 +58035,9 @@ msgid ""
"The maximal range that can be reached by the spotlight. Note that the "
"effectively lit area may appear to be smaller depending on the [member "
"spot_attenuation] in use. No matter the [member spot_attenuation] in use, "
-"the light will never reach anything outside this range."
+"the light will never reach anything outside this range.\n"
+"[b]Note:[/b] [member spot_range] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/SpringArm.xml
@@ -67192,10 +67291,15 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
"If [code]true[/code], uses a fast post-processing filter to make banding "
-"significantly less visible. In some cases, debanding may introduce a "
-"slightly noticeable dithering pattern. It's recommended to enable debanding "
-"only when actually needed since the dithering pattern will make lossless-"
-"compressed screenshots larger.\n"
+"significantly less visible in 3D. 2D rendering is [i]not[/i] affected by "
+"debanding unless the [member Environment.background_mode] is [constant "
+"Environment.BG_CANVAS]. In this case, [member usage] must also be set to "
+"[constant USAGE_3D]. See also [member ProjectSettings.rendering/quality/"
+"filters/use_debanding].\n"
+"In some cases, debanding may introduce a slightly noticeable dithering "
+"pattern. It's recommended to enable debanding only when actually needed "
+"since the dithering pattern will make lossless-compressed screenshots "
+"larger.\n"
"[b]Note:[/b] Only available on the GLES3 backend. [member hdr] must also be "
"[code]true[/code] for debanding to be effective."
msgstr ""
@@ -67206,8 +67310,8 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
-"If [code]true[/code], the viewport will disable 3D rendering. For actual "
-"disabling use [code]usage[/code]."
+"If [code]true[/code], the viewport will disable 3D rendering. To actually "
+"disable allocation of 3D buffers, set [member usage] instead."
msgstr ""
#: doc/classes/Viewport.xml
@@ -67359,7 +67463,9 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
-"The rendering mode of viewport.\n"
+"The viewport's rendering mode. This controls which buffers are allocated for "
+"the viewport (2D only, or 2D + 3D). 2D-only options can reduce memory usage "
+"and improve performance slightly, especially on low-end devices.\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."
@@ -67891,6 +67997,22 @@ msgid ""
"render object this [VisualInstance] is set to."
msgstr ""
+#: doc/classes/VisualInstance.xml
+msgid ""
+"The sorting offset used by this [VisualInstance]. Adjusting it to a higher "
+"value will make the [VisualInstance] reliably draw on top of other "
+"[VisualInstance]s that are otherwise positioned at the same spot."
+msgstr ""
+
+#: doc/classes/VisualInstance.xml
+msgid ""
+"If [code]true[/code], the object is sorted based on the [AABB] center. "
+"Sorted based on the global position otherwise.\n"
+"The [AABB] center based sorting is generally more accurate for 3D models. "
+"The position based sorting instead allows to better control the drawing "
+"order when working with [Particles] and [CPUParticles]."
+msgstr ""
+
#: modules/visual_script/doc_classes/VisualScript.xml
msgid "A script implemented in the Visual Script programming environment."
msgstr ""
diff --git a/doc/translations/is.po b/doc/translations/is.po
index 2facd468d9..6bf49858f4 100644
--- a/doc/translations/is.po
+++ b/doc/translations/is.po
@@ -475,7 +475,8 @@ msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
-"Returns an array of dictionaries representing the current call stack.\n"
+"Returns an array of dictionaries representing the current call stack. See "
+"also [method print_stack].\n"
"[codeblock]\n"
"func _ready():\n"
" foo()\n"
@@ -490,7 +491,11 @@ msgid ""
"[codeblock]\n"
"[{function:bar, line:12, source:res://script.gd}, {function:foo, line:9, "
"source:res://script.gd}, {function:_ready, line:6, source:res://script.gd}]\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] [method get_stack] only works if the running instance is "
+"connected to a debugging server (i.e. an editor instance). [method "
+"get_stack] will not work in projects exported in release mode, or in "
+"projects exported in debug mode if not connected to a debugging server."
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -863,12 +868,16 @@ msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
-"Prints a stack track at code location, only works when running with debugger "
-"turned on.\n"
+"Prints a stack trace at the current code location. See also [method "
+"get_stack].\n"
"Output in the console would look something like this:\n"
"[codeblock]\n"
"Frame 0 - res://test.gd:16 in function '_process'\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] [method print_stack] only works if the running instance is "
+"connected to a debugging server (i.e. an editor instance). [method "
+"print_stack] will not work in projects exported in release mode, or in "
+"projects exported in debug mode if not connected to a debugging server."
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -3479,6 +3488,26 @@ msgid "Hints that an image is compressed using lossless compression."
msgstr ""
#: doc/classes/@GlobalScope.xml
+msgid ""
+"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:\n"
+"[codeblock]\n"
+"hint_string = \"%s:\" % [TYPE_INT] # Array of inteters.\n"
+"hint_string = \"%s:%s:\" % [TYPE_ARRAY, TYPE_REAL] # Two-dimensional array "
+"of floats.\n"
+"hint_string = \"%s/%s:Resource\" % [TYPE_OBJECT, TYPE_OBJECT] # Array of "
+"resources.\n"
+"hint_string = \"%s:%s/%s:Resource\" % [TYPE_ARRAY, TYPE_OBJECT, TYPE_OBJECT] "
+"# Two-dimensional array of resources.\n"
+"[/codeblock]\n"
+"[b]Note:[/b] The final colon is required to specify for properly detecting "
+"built-in types."
+msgstr ""
+
+#: doc/classes/@GlobalScope.xml
msgid "The property is serialized and saved in the scene file (default)."
msgstr ""
@@ -4163,8 +4192,7 @@ msgstr ""
#: doc/classes/AudioStreamPlayer.xml doc/classes/Button.xml
#: doc/classes/CanvasLayer.xml doc/classes/CollisionShape2D.xml
#: doc/classes/ColorRect.xml doc/classes/Input.xml doc/classes/InputEvent.xml
-#: doc/classes/InputEventAction.xml doc/classes/Label.xml
-#: doc/classes/Particles2D.xml doc/classes/Timer.xml
+#: doc/classes/InputEventAction.xml doc/classes/Label.xml doc/classes/Timer.xml
#: doc/classes/VisibilityNotifier2D.xml
msgid "2D Dodge The Creeps Demo"
msgstr ""
@@ -7081,7 +7109,10 @@ msgid ""
"var array = []\n"
"array.resize(10)\n"
"array.fill(0) # Initialize the 10 elements to 0.\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] If [code]value[/code] is of a reference type ([Object]-derived, "
+"[Array], [Dictionary], etc.) then the array is filled with the references to "
+"the same object, i.e. no duplicates are created."
msgstr ""
#: doc/classes/Array.xml doc/classes/PoolByteArray.xml
@@ -7266,6 +7297,9 @@ msgstr ""
#: doc/classes/Array.xml
msgid ""
"Sorts the array.\n"
+"[b]Note:[/b] The sorting algorithm used is not [url=https://en.wikipedia.org/"
+"wiki/Sorting_algorithm#Stability]stable[/url]. This means that values "
+"considered equal may have their order changed when using [method sort].\n"
"[b]Note:[/b] Strings are sorted in alphabetical order (as opposed to natural "
"order). This may lead to unexpected behavior when sorting an array of "
"strings ending with a sequence of numbers. Consider the following example:\n"
@@ -7285,9 +7319,13 @@ msgid ""
"For two elements [code]a[/code] and [code]b[/code], if the given method "
"returns [code]true[/code], element [code]b[/code] will be after element "
"[code]a[/code] in the array.\n"
+"[b]Note:[/b] The sorting algorithm used is not [url=https://en.wikipedia.org/"
+"wiki/Sorting_algorithm#Stability]stable[/url]. This means that values "
+"considered equal may have their order changed when using [method "
+"sort_custom].\n"
"[b]Note:[/b] You cannot randomize the return value as the heapsort algorithm "
-"expects a deterministic result. Doing so will result in unexpected "
-"behavior.\n"
+"expects a deterministic result. Randomizing the return value will result in "
+"unexpected behavior.\n"
"[codeblock]\n"
"class MyCustomSorter:\n"
" static func sort_ascending(a, b):\n"
@@ -9925,10 +9963,9 @@ msgstr ""
#: doc/classes/AudioStreamGeneratorPlayback.xml
msgid ""
-"Returns the number of audio data frames left to play. If this returned "
-"number reaches [code]0[/code], the audio will stop playing until frames are "
-"added again. Therefore, make sure your script can always generate and push "
-"new audio frames fast enough to avoid audio cracking."
+"Returns the number of frames that can be pushed to the audio sample data "
+"buffer without overflowing it. If the result is [code]0[/code], the buffer "
+"is full."
msgstr ""
#: doc/classes/AudioStreamGeneratorPlayback.xml
@@ -10460,14 +10497,14 @@ msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
"Node for back-buffering the currently-displayed screen. The region defined "
-"in the BackBufferCopy node is buffered with the content of the screen it "
+"in the [BackBufferCopy] node is buffered with the content of the screen it "
"covers, or the entire screen according to the copy mode set. Use the "
"[code]texture(SCREEN_TEXTURE, ...)[/code] function in your shader scripts to "
"access the buffer.\n"
"[b]Note:[/b] Since this node inherits from [Node2D] (and not [Control]), "
"anchors and margins won't apply to child [Control]-derived nodes. This can "
"be problematic when resizing the window. To avoid this, add [Control]-"
-"derived nodes as [i]siblings[/i] to the BackBufferCopy node instead of "
+"derived nodes as [i]siblings[/i] to the [BackBufferCopy] node instead of "
"adding them as children."
msgstr ""
@@ -10477,22 +10514,22 @@ msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
-"The area covered by the BackBufferCopy. Only used if [member copy_mode] is "
+"The area covered by the [BackBufferCopy]. Only used if [member copy_mode] is "
"[constant COPY_MODE_RECT]."
msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
-"Disables the buffering mode. This means the BackBufferCopy node will "
+"Disables the buffering mode. This means the [BackBufferCopy] node will "
"directly use the portion of screen it covers."
msgstr ""
#: doc/classes/BackBufferCopy.xml
-msgid "BackBufferCopy buffers a rectangular region."
+msgid "[BackBufferCopy] buffers a rectangular region."
msgstr ""
#: doc/classes/BackBufferCopy.xml
-msgid "BackBufferCopy buffers the entire screen."
+msgid "[BackBufferCopy] buffers the entire screen."
msgstr ""
#: doc/classes/BakedLightmap.xml
@@ -19272,6 +19309,14 @@ msgid "Cylinder shape for collisions."
msgstr ""
#: doc/classes/CylinderShape.xml
+msgid ""
+"Cylinder shape for collisions.\n"
+"[b]Note:[/b] When using GodotPhysics instead of the default Bullet physics "
+"engine, there are several known bugs with cylinder collision shapes. Using "
+"[CapsuleShape] or [BoxShape] instead is recommended."
+msgstr ""
+
+#: doc/classes/CylinderShape.xml
msgid "The cylinder's height."
msgstr ""
@@ -22104,7 +22149,10 @@ msgid ""
"[/codeblock]\n"
"[b]Note:[/b] The script is run in the Editor context, which means the output "
"is visible in the console window started with the Editor (stdout) instead of "
-"the usual Godot [b]Output[/b] dock."
+"the usual Godot [b]Output[/b] dock.\n"
+"[b]Note:[/b] EditorScript is reference counted, meaning it is destroyed when "
+"nothing references it. This can cause errors during asynchronous operations "
+"if there are no references to the script."
msgstr ""
#: doc/classes/EditorScript.xml
@@ -32816,7 +32864,9 @@ msgid ""
"The size of the light in Godot units. Only considered in baked lightmaps and "
"only if [member light_bake_mode] is set to [constant BAKE_ALL]. Increasing "
"this value will make the shadows appear blurrier. This can be used to "
-"simulate area lights to an extent."
+"simulate area lights to an extent.\n"
+"[b]Note:[/b] [member light_size] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/Light.xml
@@ -36114,7 +36164,10 @@ msgid ""
"use the [method get_next_location] function once every physics frame to "
"update the internal path logic of the NavigationAgent. The returned vector "
"position from this function should be used as the next movement position for "
-"the agent's parent Node."
+"the agent's parent Node.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues."
msgstr ""
#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
@@ -36362,7 +36415,10 @@ msgid ""
"use the [method get_next_location] function once every physics frame to "
"update the internal path logic of the NavigationAgent. The returned vector "
"position from this function should be used as the next movement position for "
-"the agent's parent Node."
+"the agent's parent Node.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues."
msgstr ""
#: doc/classes/NavigationAgent2D.xml
@@ -37072,6 +37128,9 @@ msgid ""
"modified velocity as-is might lead to pushing and agent outside of a "
"navigable area. This is a limitation of the collision avoidance system, any "
"more complex situation may require the use of the physics engine.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues.\n"
"This server keeps tracks of any call and executes them during the sync "
"phase. This means that you can request any change to the map, using any "
"thread, without worrying."
@@ -39878,7 +39937,9 @@ msgid ""
"The light's radius. Note that the effectively lit area may appear to be "
"smaller depending on the [member omni_attenuation] in use. No matter the "
"[member omni_attenuation] in use, the light will never reach anything "
-"outside this radius."
+"outside this radius.\n"
+"[b]Note:[/b] [member omni_range] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -40389,11 +40450,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] cache data directory according to the operating "
-"system's standards. On desktop platforms, this path can be overridden by "
-"setting the [code]XDG_CACHE_HOME[/code] environment variable before starting "
-"the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in "
-"Godot projects[/url] in the documentation for more information. See also "
-"[method get_config_dir] and [method get_data_dir].\n"
+"system's standards. On Linux, this path can be overridden by setting the "
+"[code]XDG_CACHE_HOME[/code] environment variable before starting the "
+"project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot "
+"projects[/url] in the documentation for more information. See also [method "
+"get_config_dir] and [method get_data_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -40427,11 +40488,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] user configuration directory according to the "
-"operating system's standards. On desktop platforms, this path can be "
-"overridden by setting the [code]XDG_CONFIG_HOME[/code] environment variable "
-"before starting the project. See [url=$DOCS_URL/tutorials/io/data_paths."
-"html]File paths in Godot projects[/url] in the documentation for more "
-"information. See also [method get_cache_dir] and [method get_data_dir].\n"
+"operating system's standards. On Linux, this path can be overridden by "
+"setting the [code]XDG_CONFIG_HOME[/code] environment variable before "
+"starting the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File "
+"paths in Godot projects[/url] in the documentation for more information. See "
+"also [method get_cache_dir] and [method get_data_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -40453,11 +40514,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] user data directory according to the operating "
-"system's standards. On desktop platforms, this path can be overridden by "
-"setting the [code]XDG_DATA_HOME[/code] environment variable before starting "
-"the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in "
-"Godot projects[/url] in the documentation for more information. See also "
-"[method get_cache_dir] and [method get_config_dir].\n"
+"system's standards. On Linux, this path can be overridden by setting the "
+"[code]XDG_DATA_HOME[/code] environment variable before starting the project. "
+"See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot "
+"projects[/url] in the documentation for more information. See also [method "
+"get_cache_dir] and [method get_config_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -42304,6 +42365,16 @@ msgid "Particle systems (2D)"
msgstr ""
#: doc/classes/Particles2D.xml
+msgid "2D Particles Demo"
+msgstr ""
+
+#: doc/classes/Particles2D.xml
+msgid ""
+"2D Dodge The Creeps Demo (uses GPUParticles2D for the trail behind the "
+"player)"
+msgstr ""
+
+#: doc/classes/Particles2D.xml
msgid "Returns a rectangle containing the positions of all existing particles."
msgstr ""
@@ -49896,15 +49967,22 @@ msgstr ""
#: doc/classes/ProjectSettings.xml
msgid ""
"If [code]true[/code], uses a fast post-processing filter to make banding "
-"significantly less visible. In some cases, debanding may introduce a "
-"slightly noticeable dithering pattern. It's recommended to enable debanding "
-"only when actually needed since the dithering pattern will make lossless-"
-"compressed screenshots larger.\n"
+"significantly less visible in 3D. 2D rendering is [i]not[/i] affected by "
+"debanding unless the [member Environment.background_mode] is [constant "
+"Environment.BG_CANVAS]. In this case, [member rendering/quality/"
+"intended_usage/framebuffer_allocation] must also be set to [b]3D[/b].\n"
+"In some cases, debanding may introduce a slightly noticeable dithering "
+"pattern. It's recommended to enable debanding only when actually needed "
+"since the dithering pattern will make lossless-compressed screenshots "
+"larger.\n"
"[b]Note:[/b] Only available on the GLES3 backend. [member rendering/quality/"
"depth/hdr] must also be [code]true[/code] for debanding to be effective.\n"
"[b]Note:[/b] There are known issues with debanding breaking rendering on "
"mobile platforms. Due to this, it is recommended to leave this option "
-"disabled when targeting mobile platforms."
+"disabled when targeting mobile platforms.\n"
+"[b]Note:[/b] This property is only read when the project starts. To set "
+"debanding at run-time, set [member Viewport.debanding] on the root "
+"[Viewport] instead."
msgstr ""
#: doc/classes/ProjectSettings.xml
@@ -51500,17 +51578,28 @@ msgstr ""
#: modules/regex/doc_classes/RegEx.xml
msgid ""
"Searches the text for the compiled pattern. Returns a [RegExMatch] container "
-"of the first matching result if found, otherwise [code]null[/code]. The "
-"region to search within can be specified without modifying where the start "
-"and end anchor would be."
+"of the first matching result if found, otherwise [code]null[/code].\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegEx.xml
msgid ""
"Searches the text for the compiled pattern. Returns an array of [RegExMatch] "
"containers for each non-overlapping result. If no results were found, an "
-"empty array is returned instead. The region to search within can be "
-"specified without modifying where the start and end anchor would be."
+"empty array is returned instead.\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegEx.xml
@@ -51519,8 +51608,14 @@ msgid ""
"specified string. Escapes and backreferences such as [code]$1[/code] and "
"[code]$name[/code] are expanded and resolved. By default, only the first "
"instance is replaced, but it can be changed for all instances (global "
-"replacement). The region to search within can be specified without modifying "
-"where the start and end anchor would be."
+"replacement).\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegExMatch.xml
@@ -54235,7 +54330,11 @@ msgid "Call a group immediately (calls are normally made on idle)."
msgstr ""
#: doc/classes/SceneTree.xml
-msgid "Call a group only once even if the call is executed many times."
+msgid ""
+"Call a group only once even if the call is executed many times.\n"
+"[b]Note:[/b] Arguments are not taken into account when deciding whether the "
+"call is unique or not. Therefore when the same method is called with "
+"different arguments, only the first call will be performed."
msgstr ""
#: doc/classes/SceneTree.xml
@@ -56072,7 +56171,9 @@ msgid ""
"[b]Note:[/b] Mixed negative scales in 3D are not decomposable from the "
"transformation matrix. Due to the way scale is represented with "
"transformation matrices in Godot, the scale values will either be all "
-"positive or all negative."
+"positive or all negative.\n"
+"[b]Note:[/b] Not all nodes are visually scaled by the [member scale] "
+"property. For example, [Light]s are not visually affected by [member scale]."
msgstr ""
#: doc/classes/Spatial.xml
@@ -57450,7 +57551,10 @@ msgid ""
msgstr ""
#: doc/classes/SpotLight.xml
-msgid "The spotlight's angle in degrees."
+msgid ""
+"The spotlight's angle in degrees.\n"
+"[b]Note:[/b] [member spot_angle] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/SpotLight.xml
@@ -57466,7 +57570,9 @@ msgid ""
"The maximal range that can be reached by the spotlight. Note that the "
"effectively lit area may appear to be smaller depending on the [member "
"spot_attenuation] in use. No matter the [member spot_attenuation] in use, "
-"the light will never reach anything outside this range."
+"the light will never reach anything outside this range.\n"
+"[b]Note:[/b] [member spot_range] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/SpringArm.xml
@@ -66703,10 +66809,15 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
"If [code]true[/code], uses a fast post-processing filter to make banding "
-"significantly less visible. In some cases, debanding may introduce a "
-"slightly noticeable dithering pattern. It's recommended to enable debanding "
-"only when actually needed since the dithering pattern will make lossless-"
-"compressed screenshots larger.\n"
+"significantly less visible in 3D. 2D rendering is [i]not[/i] affected by "
+"debanding unless the [member Environment.background_mode] is [constant "
+"Environment.BG_CANVAS]. In this case, [member usage] must also be set to "
+"[constant USAGE_3D]. See also [member ProjectSettings.rendering/quality/"
+"filters/use_debanding].\n"
+"In some cases, debanding may introduce a slightly noticeable dithering "
+"pattern. It's recommended to enable debanding only when actually needed "
+"since the dithering pattern will make lossless-compressed screenshots "
+"larger.\n"
"[b]Note:[/b] Only available on the GLES3 backend. [member hdr] must also be "
"[code]true[/code] for debanding to be effective."
msgstr ""
@@ -66717,8 +66828,8 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
-"If [code]true[/code], the viewport will disable 3D rendering. For actual "
-"disabling use [code]usage[/code]."
+"If [code]true[/code], the viewport will disable 3D rendering. To actually "
+"disable allocation of 3D buffers, set [member usage] instead."
msgstr ""
#: doc/classes/Viewport.xml
@@ -66870,7 +66981,9 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
-"The rendering mode of viewport.\n"
+"The viewport's rendering mode. This controls which buffers are allocated for "
+"the viewport (2D only, or 2D + 3D). 2D-only options can reduce memory usage "
+"and improve performance slightly, especially on low-end devices.\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."
@@ -67402,6 +67515,22 @@ msgid ""
"render object this [VisualInstance] is set to."
msgstr ""
+#: doc/classes/VisualInstance.xml
+msgid ""
+"The sorting offset used by this [VisualInstance]. Adjusting it to a higher "
+"value will make the [VisualInstance] reliably draw on top of other "
+"[VisualInstance]s that are otherwise positioned at the same spot."
+msgstr ""
+
+#: doc/classes/VisualInstance.xml
+msgid ""
+"If [code]true[/code], the object is sorted based on the [AABB] center. "
+"Sorted based on the global position otherwise.\n"
+"The [AABB] center based sorting is generally more accurate for 3D models. "
+"The position based sorting instead allows to better control the drawing "
+"order when working with [Particles] and [CPUParticles]."
+msgstr ""
+
#: modules/visual_script/doc_classes/VisualScript.xml
msgid "A script implemented in the Visual Script programming environment."
msgstr ""
diff --git a/doc/translations/it.po b/doc/translations/it.po
index ed4ec9ddc7..37488c9ebd 100644
--- a/doc/translations/it.po
+++ b/doc/translations/it.po
@@ -20,18 +20,19 @@
# Daniele Basso <tiziodcaio@gmail.com>, 2021.
# Jacopo Farina <jacopo1.farina@gmail.com>, 2021.
# Riteo Siuga <riteo@posteo.net>, 2021.
-# ZeroKun265 <davidegiambirtone265@gmail.com>, 2021.
+# ZeroKun265 <davidegiambirtone265@gmail.com>, 2021, 2022.
# Andrea Montagna <fullmontis@gmail.com>, 2021.
# Andrea Leganza <neogene@gmail.com>, 2021.
# Federico Caprini <caprinifede@gmail.com>, 2022.
# Alessandro Casalino <alessandro.casalino93@gmail.com>, 2022.
# AndreWharn <andrewharnofficial@gmail.com>, 2022.
+# Silvia Scaglione <sissisoad@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-09-14 18:45+0000\n"
-"Last-Translator: Federico Caprini <caprinifede@gmail.com>\n"
+"PO-Revision-Date: 2022-10-16 11:17+0000\n"
+"Last-Translator: Silvia Scaglione <sissisoad@gmail.com>\n"
"Language-Team: Italian <https://hosted.weblate.org/projects/godot-engine/"
"godot-class-reference/it/>\n"
"Language: it\n"
@@ -39,7 +40,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.14.1-dev\n"
+"X-Generator: Weblate 4.15-dev\n"
#: doc/tools/make_rst.py
msgid "Description"
@@ -47,7 +48,7 @@ msgstr "Descrizione"
#: doc/tools/make_rst.py
msgid "Tutorials"
-msgstr "Guide"
+msgstr "Tutorials"
#: doc/tools/make_rst.py
msgid "Properties"
@@ -253,8 +254,8 @@ msgid ""
"s = asin(0.5)\n"
"[/codeblock]"
msgstr ""
-"Ritorna l'arcoseno di [code]s[/code] in radianti. Usato per prendere "
-"l'angolo del seno [code]s[/code]. [code]s[/code] deve essere compreso tra "
+"Ritorna l'arcoseno di [code]s[/code] in radianti. Utilizza [code]s[/code] "
+"per prendere l'angolo del seno. [code]s[/code] deve essere compreso tra "
"[code]-1.0[/code] e [code]1.0[/code] (inclusi), altrimenti, [method asin] "
"ritornerà [constant NAN].\n"
"[codeblock]\n"
@@ -288,20 +289,20 @@ msgid ""
"a message with clarifying details\n"
"[/codeblock]"
msgstr ""
-"Controlla che [code]condition[/code] sia [code]true[/code]. Se "
-"[code]condition[/code] è [code]false[/code], un errore è generato. Mentre si "
-"sta eseguendo dall'editor, il progetto corrente verrà interrotto finché non "
-"lo riprenderai. Questo può essere usato come una forma più forte di [method "
-"push_error] per riportare gli errori allo sviluppatore del progetto o agli "
-"utilizzatori di add-on.\n"
-"[b]Note:[/b] Per ragioni di performance, il codice dentro [method assert] "
-"viene eseguito sono nelle versione di debug o mentre si sta eseguendo il "
-"progetto dall'editor. Non includere codice che ha effetti collaterali mentre "
-"[method assert] viene chiamato. Altrimenti il progetto si comporterà "
-"diversamente quando viene esportato nella modalità di rilascio.\n"
-"Il parametro [code]message[/code] opzionale, se passato, è mostrato insieme "
-"al messaggio generico \"Assertion failed\". Puoi usarlo per dare dettagli "
-"addizionali sul perché l'asserzione sia fallita.\n"
+"Controlla che [code]condizion[/code] sia [code]true[/code](vero). Se "
+"[code]condition[/code] è [code]false[/code](falso), un errore è generato."
+"Quando eseguito all'interno dell'editor, il progetto verrà anche messo in "
+"pausa, finchè non lo farai ripartire. Ciò può essere usato come un migliore "
+"sistema di [method push_error] per riportare errori agli sviluppatori del "
+"progetto o ulteriori utenti.\n"
+"[b]Nota bene:[/b] Per motivi di prestazioni, il codice all'interno di "
+"[method assert] è eseguito solo nelle build di debug o quando il progetto è "
+"eseguito dall'editor. Non scrivere codice che dovrà avere effetti "
+"collaterali in una chiamata [method assert]. Altrimenti il progetto si "
+"comporterà in modo diverso quando esportato in modalità release.\n"
+"L'argomento opzionale [code]message[/code], se dato, è mostrato in aggiunta "
+"al generico messaggio \"Assertion failed\" (Asserzione fallita). Può essere "
+"usato per fornire più dettagli sul motivo per cui un asserzione ha fallito.\n"
"[codeblock]\n"
"# Immaginati di voler sempre avere una velocità (speed nel caso nostro) "
"sempre tra 0 e 20\n"
@@ -734,8 +735,10 @@ msgstr ""
"[/codeblock]"
#: modules/gdscript/doc_classes/@GDScript.xml
+#, fuzzy
msgid ""
-"Returns an array of dictionaries representing the current call stack.\n"
+"Returns an array of dictionaries representing the current call stack. See "
+"also [method print_stack].\n"
"[codeblock]\n"
"func _ready():\n"
" foo()\n"
@@ -750,7 +753,11 @@ msgid ""
"[codeblock]\n"
"[{function:bar, line:12, source:res://script.gd}, {function:foo, line:9, "
"source:res://script.gd}, {function:_ready, line:6, source:res://script.gd}]\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] [method get_stack] only works if the running instance is "
+"connected to a debugging server (i.e. an editor instance). [method "
+"get_stack] will not work in projects exported in release mode, or in "
+"projects exported in debug mode if not connected to a debugging server."
msgstr ""
"Restituisce un vettore di dizionari rappresentanti il call stack corrente.\n"
"[codeblock]\n"
@@ -947,7 +954,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 "
@@ -971,7 +977,10 @@ msgid ""
msgstr ""
"Interpola linearmente tra due valori mediante un valore definito in "
"[code]weight[/code]. Per interpolare, [code]weight[/code] dovrebbe rimanere "
-"tra [code]0.0[/code] e [code]1.0[/code] (inclusi).\n"
+"tra [code]0.0[/code] e [code]1.0[/code] (inclusi). Tuttavia, i valori fuori "
+"da questo range sono permessi e possono essere utilizzati per eseguire "
+"[i]extrapolation[/i]. Utilizza [method clamp] sul risultato di [method lerp] "
+"se non lo si desidera.\n"
"Se gli argomenti [code]from[/code] e [code]to[/code] sono di tipo [int] o "
"[float], il valore di ritorno è un [float].\n"
"Se entrambi sono dello stesso tipo di vettore ([Vector2], [Vector3] o "
@@ -987,7 +996,6 @@ msgstr ""
"combinalo con [method ease] o [method smoothstep]."
#: modules/gdscript/doc_classes/@GDScript.xml
-#, fuzzy
msgid ""
"Linearly interpolates between two angles (in radians) by a normalized "
"value.\n"
@@ -1012,18 +1020,25 @@ msgid ""
msgstr ""
"Interpola linearmente tra due angoli (in radianti) con un valore "
"normalizzato.\n"
-"Simile a [metodo lerp], ma interpola correttamente quando gli angoli sono "
+"Simile a [method lerp], ma interpola correttamente quando gli angoli sono "
"attorno [costante @GDScript.TAU]. Per eseguire un'interpolazione alleggerita "
"con [method lerp_angle], combinalo con [method ease] o [method smoothstep].\n"
"[codeblock]\n"
"extends Sprite\n"
"var elapsed = 0.0\n"
"func _process(delta):\n"
-" var min_angle = deg2rad(0.0)\n"
-" var max_angle = deg2rad(90.0)\n"
-" rotation = lerp_angle(min_angle, max_angle, elapsed)\n"
-" elapsed += delta\n"
-"[/codeblock]"
+" var min_angle = deg2rad(0.0)\n"
+" var max_angle = deg2rad(90.0)\n"
+" rotation = lerp_angle(min_angle, max_angle, elapsed)\n"
+" elapsed += delta\n"
+"[/codeblock]\n"
+"[b]Nota:[/b] Questo metodo interpola linearmente tra [code]da[/code] e "
+"[code]a[/code]. Tuttavia, quando questi due angoli sono approssimativamente "
+"[code]PI + k * TAU[/code] distanti per qualsiasi numero intero [code]k[/"
+"code], non è ovvio in quale modo si interpolano a causa di errori di "
+"precisione a virgola mobile. Per esempio, [code]lerp_angle(0, PI, weight)[/"
+"code] interpola in senso anti-orario, mentre [code]lerp_angle(0, PI + 5 * "
+"TAU, weight)[/code] interpola in senso orario."
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
@@ -1272,7 +1287,6 @@ msgstr ""
"coordinate cartesiane (assi X e 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"
@@ -1297,7 +1311,7 @@ msgstr ""
"for i in range(-3, 4):\n"
" print(\"%2d %2d %2d\" % [i, i % 3, posmod(i, 3)])\n"
"[/codeblock]\n"
-"Produces:\n"
+"Produce:\n"
"[codeblock]\n"
"-3 0 0\n"
"-2 -2 1\n"
@@ -1375,7 +1389,6 @@ msgstr ""
"messaggi di debug ed errore che vengono mostrati con la stack trace."
#: modules/gdscript/doc_classes/@GDScript.xml
-#, fuzzy
msgid ""
"Like [method print], but includes the current stack frame when running with "
"the debugger turned on.\n"
@@ -1385,28 +1398,27 @@ msgid ""
" At: res://test.gd:15:_process()\n"
"[/codeblock]"
msgstr ""
-"Stampa un stack trace nella posizione del codice, funziona solo quando il "
-"debugger è attivato.\n"
+"Come [method print], ma include l'attuale stack frame quando si avvia con il "
+"debugger attivato.\n"
"L'output nella console apparirà come:\n"
"[codeblock]\n"
-"Frame 0 - res://test.gd:16 in function '_process'\n"
+"Test print\n"
+" At: res://test.gd:15:_process()\n"
"[/codeblock]"
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
-"Prints a stack track at code location, only works when running with debugger "
-"turned on.\n"
+"Prints a stack trace at the current code location. See also [method "
+"get_stack].\n"
"Output in the console would look something like this:\n"
"[codeblock]\n"
"Frame 0 - res://test.gd:16 in function '_process'\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] [method print_stack] only works if the running instance is "
+"connected to a debugging server (i.e. an editor instance). [method "
+"print_stack] will not work in projects exported in release mode, or in "
+"projects exported in debug mode if not connected to a debugging server."
msgstr ""
-"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 ""
@@ -1524,7 +1536,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"
@@ -1533,11 +1544,12 @@ msgid ""
"[/codeblock]\n"
"[b]Note:[/b] This is equivalent to [code]randf() * (to - from) + from[/code]."
msgstr ""
-"Un range casuale, un qualsiasi numero in virgola mobile tra [code]from[/"
-"code] e [code]to[/code]\n"
+"Ritorna in modo casuale un numero a virgola mobile tra [code]from[/code] e "
+"[code]to[/code] (incluse entrambe le estremità).\n"
"[codeblock]\n"
"prints(rand_range(0, 1), rand_range(0, 1)) # Stampa 0.135591 0.405263\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Nota:[/b] Ciò equivale a [code]randf() * (to - from) + from[/code]."
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
@@ -1559,8 +1571,8 @@ msgid ""
"randf() # Returns e.g. 0.375671\n"
"[/codeblock]"
msgstr ""
-"Restituisce un numero casuale in virgola mobile nell'intervallo [code][0, 1]"
-"[/code].\n"
+"Restituisce un numero casuale a virgola mobile nell'intervallo [code][0, 1][/"
+"code].\n"
"[codeblock]\n"
"randf() # Restituisce ad esempio 0.375671\n"
"[/codeblock]"
@@ -1695,6 +1707,17 @@ msgid ""
"For complex use cases where you need multiple ranges, consider using [Curve] "
"or [Gradient] instead."
msgstr ""
+"Mostra un [code]value[/code] da [code][istart, istop][/code] a [code]"
+"[ostart, ostop][/code]. Vedi anche [methop lerp] e [method inverse_lerp]. Se "
+"[code]value[/code] è fuori da [code][istart, istop][/code], allora il numero "
+"che risulterà sarà anche esso fuori da [code][ostart, ostop][/code]. "
+"Utilizza [method clamp] sul risultato di [method range_lerp] se non lo si "
+"desidera.\n"
+"[codeblock]\n"
+"range_lerp(75, 0, 100, -1, 1) # Returns 0.5\n"
+"[/codeblock]\n"
+"Per utilizzi complessi in cui ti servono molteplici range, considera "
+"piuttosto l'utilizzo di [Curve] o [Gradient]."
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
@@ -1799,6 +1822,29 @@ msgid ""
"smoothstep_ease_comparison.png]Comparison between smoothstep() and ease(x, "
"-1.6521) return values[/url]"
msgstr ""
+"Ritorna il risultato della regolare interpolazione del valore di [code]s[/"
+"code] tra [code]0[/code] e [code]1[/code], basata sulla posizione di "
+"[code]s[/code] rispetto agli angoli [code]from[/code] e [code]to[/code].\n"
+"Il valore di ritorno è [code]0[/code] if [code]s <= from[/code], e [code]1[/"
+"code] if [code]s >= to[/code]. Se [code]s[/code] è posizionato tra "
+"[code]from[/code] e [code]to[/code], il valore di ritorno seguirà una curva "
+"a forma di S che mostrerà [code]s[/code] tra [code]0[/code] e [code]1[/"
+"code].\n"
+"La curva a forma di S è l'interpolatore cubico Hermite, dato da [code]f(y) = "
+"3*y^2 - 2*y^3[/code] dove [code]y = (x-from) / (to-from)[/code].\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]\n"
+"Rispetto a [method ease] con un valore di curva di [code]-1.6521[/code], "
+"[method smoothstep] ritorna la curva più regolare possibile senza improvvisi "
+"cambiamenti sulla derivata. Se hai bisogno di effettuare transizioni più "
+"avanzate, usa [Tween] o [AnimationPlayer].\n"
+"[url=https://raw.githubusercontent.com/godotengine/godot-docs/3.5/img/"
+"smoothstep_ease_comparison.png] Confronto tra smoothstep() e ease(x, "
+"-1.6521) fa tornare i valori[/url]"
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
@@ -1840,7 +1886,6 @@ msgstr ""
"[/codeblock]"
#: modules/gdscript/doc_classes/@GDScript.xml
-#, fuzzy
msgid ""
"Snaps float value [code]s[/code] to a given [code]step[/code]. This can also "
"be used to round a floating point number to an arbitrary number of "
@@ -1851,12 +1896,12 @@ msgid ""
"[/codeblock]\n"
"See also [method ceil], [method floor], [method round], and [int]."
msgstr ""
-"Arrotonda un valore float [code]s[/code] ad un valore [code]step[/code] su "
-"una scala. Questo può essere anche utilizzato per arrotondare un valore "
-"float ad un numero arbitrario di cifre decimali.\n"
+"Scatta un valore float [code]s[/code] ad un valore [code]step[/code]. Questo "
+"può essere anche utilizzato per arrotondare un valore float ad un numero "
+"arbitrario di cifre decimali.\n"
"[codeblock]\n"
"stepify(100, 32) # Ritorna 96.0\n"
-"stepify(3.14159, 0.01) # Ritorna3.14\n"
+"stepify(3.14159, 0.01) # Ritorna 3.14\n"
"[/codeblock]\n"
"Guarda anche [method ceil], [method floor], [method round] e [int]."
@@ -1985,6 +2030,15 @@ msgid ""
" print(\"unexpected results\")\n"
"[/codeblock]"
msgstr ""
+"Ritorna l'internal type della Variant dell'oggetto, utilizzando i valori "
+"[enum Variant.Type].\n"
+"[codeblock]\n"
+"p = parse_json('[\"a\", \"b\", \"c\"]')\n"
+"if typeof(p) == TYPE_ARRAY:\n"
+" print(p[0]) # Prints a\n"
+"oppure:\n"
+" print(\"unexpected results\")\n"
+"[/codeblock]"
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
@@ -2088,6 +2142,26 @@ msgid ""
"[code]wrapf[/code] is more flexible than using the [method fposmod] approach "
"by giving the user control over the minimum value."
msgstr ""
+"Avvolge il float [code]value[/code] tra [code]min[/code] e [code]max[/"
+"code].\n"
+"Utilizzabile per creare dei funzionamenti simili a loop o infinite "
+"superfici.\n"
+"[codeblock]\n"
+"# Infinite loop between 5.0 and 9.9\n"
+"value = wrapf(value + 0.1, 5.0, 10.0)\n"
+"[/codeblock]\n"
+"[codeblock]\n"
+"# Infinite rotation (in radians)\n"
+"angle = wrapf(angle + 0.1, 0.0, TAU)\n"
+"[/codeblock]\n"
+"[codeblock]\n"
+"# Infinite rotation (in radians)\n"
+"angle = wrapf(angle + 0.1, -PI, PI)\n"
+"[/codeblock]\n"
+"[b]Nota:[/b] Se [code]min[/code] è [code]0[/code], ciò è equivalente a "
+"[method fposmod], quindi utilizza quello preferibilmente.\n"
+"[code]wrapf[/code] è più flessibile rispetto all'approccio [method fposmod] "
+"dando l'user control sopra il valore minimo."
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
@@ -2238,6 +2312,16 @@ msgid ""
"code] will not result in [constant INF] and will result in a run-time error "
"instead."
msgstr ""
+"L'infinità positiva della virgola mobile. Questo è il risultato della "
+"divisione in virgola mobile quando il divisore è [code]0.0[/code]. Per "
+"infinità negativa, utilizza [code]-INF[/code]. Dividere per [code]-0.0[/"
+"code] risulterà in infinità negativa se è il numeratore è positivo, quindi "
+"dividere per [code]0.0[/code] non è lo stesso di dividere per [code]-0.0[/"
+"code] (nonostante [code]0.0 == -0.0[/code] ritorni [code]true[/code]).\n"
+"[b]Nota:[/b] L'infinità numerica è solo un concetto per numeri a virgola "
+"mobile, e non ha equivalenti per numeri interi. Dividere un numero intero "
+"per [code]0[/code] non risulterà in [constant INF] e risulterà, invece, in "
+"un errore di avviamento."
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
@@ -2263,7 +2347,7 @@ msgstr ""
#: doc/classes/@GlobalScope.xml
msgid "Global scope constants and variables."
-msgstr ""
+msgstr "Costanti e variabili degli ambiti globali."
#: doc/classes/@GlobalScope.xml
msgid ""
@@ -2272,6 +2356,11 @@ msgid ""
"Singletons are also documented here, since they can be accessed from "
"anywhere."
msgstr ""
+"Costanti e varianti degli ambiti globali. Questo è ciò che risiede nei "
+"globali, le costanti riguardano gli errori di codice, scancodes, property "
+"hints, ecc...\n"
+"I Singletons sono documentati anche qui, dato che sono accessibili da "
+"qualsiasi parte."
#: doc/classes/@GlobalScope.xml
msgid "The [ARVRServer] singleton."
@@ -2334,19 +2423,16 @@ msgid "The [Marshalls] singleton."
msgstr "Il singleton [Marshalls]."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "The [Navigation2DServer] singleton."
-msgstr "Il singleton [TranslationServer]."
+msgstr "Il singleton [Navigation2DServer]."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "The [NavigationMeshGenerator] singleton."
-msgstr "Il singleton [EditorNavigationMeshGenerator]."
+msgstr "Il singleton [NavigationMeshGenerator]."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "The [NavigationServer] singleton."
-msgstr "Il singleton [TranslationServer]."
+msgstr "Il singleton [NavigationServer]."
#: doc/classes/@GlobalScope.xml
msgid "The [OS] singleton."
@@ -2377,9 +2463,8 @@ msgid "The [ResourceSaver] singleton."
msgstr "Il singleton [ResourceSaver]."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "The [Time] singleton."
-msgstr "Il singleton [Engine]."
+msgstr "Il singleton [Time]."
#: doc/classes/@GlobalScope.xml
msgid "The [TranslationServer] singleton."
@@ -2439,16 +2524,22 @@ msgid ""
"General vertical alignment, usually used for [Separator], [ScrollBar], "
"[Slider], etc."
msgstr ""
+"L'allineamento generale verticale, solitamente utilizzato per [Separator], "
+"[Scrollbar], [Slider], ecc."
#: doc/classes/@GlobalScope.xml
msgid ""
"General horizontal alignment, usually used for [Separator], [ScrollBar], "
"[Slider], etc."
msgstr ""
+"L'allineamento orizzontale generale, solitamente utilizzato per [Separator], "
+"[Scrollbar], [Slider], etc."
#: doc/classes/@GlobalScope.xml
+#, fuzzy
msgid "Horizontal left alignment, usually for text-derived classes."
msgstr ""
+"L'allineamento orizzontale sinistro, solitamente per text-derived classes."
#: doc/classes/@GlobalScope.xml
msgid "Horizontal center alignment, usually for text-derived classes."
@@ -2721,26 +2812,24 @@ msgid "Context menu key."
msgstr "Tasto menu contestuale."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "Left Hyper key."
msgstr "Tasto Hyper sinistro."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "Right Hyper key."
msgstr "Tasto Hyper destro."
#: doc/classes/@GlobalScope.xml
msgid "Help key."
-msgstr ""
+msgstr "Tasto help."
#: doc/classes/@GlobalScope.xml
msgid "Left Direction key."
-msgstr ""
+msgstr "Il tasto direzionale sinistro."
#: doc/classes/@GlobalScope.xml
msgid "Right Direction key."
-msgstr ""
+msgstr "Il tasto direzionale destro."
#: doc/classes/@GlobalScope.xml
msgid ""
@@ -2776,7 +2865,7 @@ msgstr "Tasto del volume su."
#: doc/classes/@GlobalScope.xml
msgid "Bass Boost key."
-msgstr ""
+msgstr "Il tasto Bass Boost."
#: doc/classes/@GlobalScope.xml
msgid "Bass up key."
@@ -2810,7 +2899,7 @@ msgstr "Tasto brano successivo."
#: doc/classes/@GlobalScope.xml
msgid "Media record key."
-msgstr ""
+msgstr "Tasto di registrazione."
#: doc/classes/@GlobalScope.xml
#, fuzzy
@@ -2818,98 +2907,96 @@ msgid "Home page key."
msgstr "Tasto pagina iniziale."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "Favorites key."
msgstr "Tasto Preferiti."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "Search key."
msgstr "Tasto Ricerca."
#: doc/classes/@GlobalScope.xml
msgid "Standby key."
-msgstr ""
+msgstr "Tasto Modalità Riposo."
#: doc/classes/@GlobalScope.xml
msgid "Open URL / Launch Browser key."
-msgstr ""
+msgstr "Tasto Apri URL / Avvia Browser."
#: doc/classes/@GlobalScope.xml
msgid "Launch Mail key."
-msgstr ""
+msgstr "Tasto Avvia Mail."
#: doc/classes/@GlobalScope.xml
msgid "Launch Media key."
-msgstr ""
+msgstr "Tasto Avvia Media."
#: doc/classes/@GlobalScope.xml
msgid "Launch Shortcut 0 key."
-msgstr ""
+msgstr "Tasto Avvia Shortcut 0."
#: doc/classes/@GlobalScope.xml
msgid "Launch Shortcut 1 key."
-msgstr ""
+msgstr "Tasto Avvia Shortcut 1."
#: doc/classes/@GlobalScope.xml
msgid "Launch Shortcut 2 key."
-msgstr ""
+msgstr "Tasto Avvia Shortcut 2."
#: doc/classes/@GlobalScope.xml
msgid "Launch Shortcut 3 key."
-msgstr ""
+msgstr "Tasto Avvia Shortcut 3."
#: doc/classes/@GlobalScope.xml
msgid "Launch Shortcut 4 key."
-msgstr ""
+msgstr "Tasto Avvia Shortcut 4."
#: doc/classes/@GlobalScope.xml
msgid "Launch Shortcut 5 key."
-msgstr ""
+msgstr "Tasto Avvia Shortcut 5."
#: doc/classes/@GlobalScope.xml
msgid "Launch Shortcut 6 key."
-msgstr ""
+msgstr "Tasto Avvia Shortcut 6."
#: doc/classes/@GlobalScope.xml
msgid "Launch Shortcut 7 key."
-msgstr ""
+msgstr "Tasto Avvia Shortcut 7."
#: doc/classes/@GlobalScope.xml
msgid "Launch Shortcut 8 key."
-msgstr ""
+msgstr "Tasto Avvia Shortcut 8."
#: doc/classes/@GlobalScope.xml
msgid "Launch Shortcut 9 key."
-msgstr ""
+msgstr "Tasto Avvia Shortcut 9."
#: doc/classes/@GlobalScope.xml
msgid "Launch Shortcut A key."
-msgstr ""
+msgstr "Tasto Avvia Shortcut A."
#: doc/classes/@GlobalScope.xml
msgid "Launch Shortcut B key."
-msgstr ""
+msgstr "Tasto Avvia Shortcut B."
#: doc/classes/@GlobalScope.xml
msgid "Launch Shortcut C key."
-msgstr ""
+msgstr "Tasto Avvia Shortcut C."
#: doc/classes/@GlobalScope.xml
msgid "Launch Shortcut D key."
-msgstr ""
+msgstr "Tasto Avvia Shortcut D."
#: doc/classes/@GlobalScope.xml
msgid "Launch Shortcut E key."
-msgstr ""
+msgstr "Tasto Avvia Shortcut E."
#: doc/classes/@GlobalScope.xml
msgid "Launch Shortcut F key."
-msgstr ""
+msgstr "Tasto Avvia Shortcut F."
#: doc/classes/@GlobalScope.xml
msgid "Unknown key."
-msgstr ""
+msgstr "Tasto Sconosciuto."
#: doc/classes/@GlobalScope.xml
#, fuzzy
@@ -2927,117 +3014,94 @@ msgid "\" key."
msgstr "Tasto \"."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "# key."
msgstr "Tasto #."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "$ key."
msgstr "Tasto $."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "% key."
msgstr "Tasto %."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "& key."
msgstr "Tasto &."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "' key."
msgstr "Tasto '."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "( key."
msgstr "Tasto (."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid ") key."
msgstr "Tasto )."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "* key."
msgstr "Tasto *."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "+ key."
msgstr "Tasto +."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid ", key."
msgstr "Tasto ,."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "- key."
msgstr "Tasto -."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid ". key."
msgstr "Tasto \".\"."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "/ key."
msgstr "Tasto /."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "Number 0."
msgstr "Numero 0."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "Number 1."
msgstr "Numero 1."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "Number 2."
msgstr "Numero 2."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "Number 3."
msgstr "Numero 3."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "Number 4."
msgstr "Numero 4."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "Number 5."
msgstr "Numero 5."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "Number 6."
msgstr "Numero 6."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "Number 7."
msgstr "Numero 7."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "Number 8."
msgstr "Numero 8."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "Number 9."
msgstr "Numero 9."
@@ -3047,127 +3111,102 @@ msgid ": key."
msgstr "Tasto :."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "; key."
msgstr "Tasto ;."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "< key."
msgstr "Tasto <."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "= key."
msgstr "Tasto =."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "> key."
msgstr "Tasto >."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "? key."
msgstr "Tasto ?."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "@ key."
msgstr "Tasto @."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "A key."
msgstr "Tasto A."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "B key."
msgstr "Tasto B."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "C key."
msgstr "Tasto C."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "D key."
msgstr "Tasto D."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "E key."
msgstr "Tasto E."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "F key."
msgstr "Tasto F."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "G key."
msgstr "Tasto G."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "H key."
msgstr "Tasto H."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "I key."
msgstr "Tasto I."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "J key."
msgstr "Tasto J."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "K key."
msgstr "Tasto K."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "L key."
msgstr "Tasto L."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "M key."
msgstr "Tasto M."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "N key."
msgstr "Tasto N."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "O key."
msgstr "Tasto O."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "P key."
msgstr "Tasto P."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "Q key."
msgstr "Tasto Q."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "R key."
msgstr "Tasto R."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "S key."
msgstr "Tasto S."
@@ -3177,88 +3216,72 @@ msgid "T key."
msgstr "Tasto T."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "U key."
msgstr "Tasto U."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "V key."
msgstr "Tasto V."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "W key."
msgstr "Tasto W."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "X key."
msgstr "Tasto X."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "Y key."
msgstr "Tasto Y."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "Z key."
msgstr "Tasto Z."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "[ key."
msgstr "Tasto [."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "\\ key."
msgstr "Tasto \\."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "] key."
msgstr "Tasto ]."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "^ key."
msgstr "Tasto ^."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "_ key."
msgstr "Tasto _."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "` key."
msgstr "Tasto '."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "{ key."
msgstr "Tasto {."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "| key."
msgstr "Tasto |."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "} key."
msgstr "Tasto }."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "~ key."
msgstr "Tasto ~."
#: doc/classes/@GlobalScope.xml
msgid "Non-breakable space key."
-msgstr ""
+msgstr "Tasto spazio Non-breakable."
#: doc/classes/@GlobalScope.xml
#, fuzzy
@@ -3286,307 +3309,248 @@ msgid "Â¥ key."
msgstr "Tasto ¥."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "¦ key."
msgstr "Tasto ¦."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "§ key."
msgstr "Tasto §."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "¨ key."
msgstr "Tasto ¨."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "© key."
msgstr "Tasto ©."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "ª key."
msgstr "Tasto ª."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "« key."
msgstr "Tasto «."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "¬ key."
msgstr "Tasto ¬."
#: doc/classes/@GlobalScope.xml
msgid "Soft hyphen key."
-msgstr ""
+msgstr "Tasto trattino morbido."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "® key."
msgstr "Tasto ®."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "¯ key."
msgstr "Tasto ¯."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "° key."
msgstr "Tasto °."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "± key."
msgstr "Tasto ±."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "² key."
msgstr "Tasto ²."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "³ key."
msgstr "Tasto ³."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "´ key."
msgstr "Tasto ´."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "µ key."
msgstr "Tasto µ."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "¶ key."
msgstr "Tasto ¶."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "· key."
msgstr "Tasto ·."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "¸ key."
msgstr "Tasto ¸."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "¹ key."
msgstr "Tasto ¹."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "º key."
msgstr "Tasto º."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "» key."
msgstr "Tasto »."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "¼ key."
msgstr "Tasto ¼."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "½ key."
msgstr "Tasto ½."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "¾ key."
msgstr "Tasto ¾."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "¿ key."
msgstr "Tasto ¿."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "À key."
msgstr "Tasto À."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "Ã key."
msgstr "Tasto Ã."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "Â key."
msgstr "Tasto Â."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "Ã key."
msgstr "Tasto Ã."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "Ä key."
msgstr "Tasto Ä."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "Ã… key."
msgstr "Tasto Ã…."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "Æ key."
msgstr "Tasto Æ."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "Ç key."
msgstr "Tasto Ç."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "È key."
msgstr "Tasto È."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "É key."
msgstr "Tasto É."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "Ê key."
msgstr "Tasto Ê."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "Ë key."
msgstr "Tasto Ë."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "Ì key."
msgstr "Tasto Ì."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "Ã key."
msgstr "Tasto Ã."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "ÃŽ key."
msgstr "Tasto ÃŽ."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "Ã key."
msgstr "Tasto Ã."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "Ã key."
msgstr "Tasto Ã."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "Ñ key."
msgstr "Tasto Ñ."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "Ã’ key."
msgstr "Tasto Ã’."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "Ó key."
msgstr "Tasto Ó."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "Ô key."
msgstr "Tasto Ô."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "Õ key."
msgstr "Tasto Õ."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "Ö key."
msgstr "Tasto Ö."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "× key."
msgstr "Tasto ×."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "Ø key."
msgstr "Tasto Ø."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "Ù key."
msgstr "Tasto Ù."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "Ú key."
msgstr "Tasto Ú."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "Û key."
msgstr "Tasto Û."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "Ü key."
msgstr "Tasto Ü."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "Ã key."
msgstr "Tasto Ã."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "Þ key."
msgstr "Tasto Þ."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "ß key."
msgstr "Tasto ß."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "÷ key."
msgstr "Tasto ÷."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "ÿ key."
msgstr "Tasto ÿ."
#: doc/classes/@GlobalScope.xml
msgid "Key Code mask."
-msgstr ""
+msgstr "Tasto Code mask."
#: doc/classes/@GlobalScope.xml
msgid "Modifier key mask."
@@ -3594,11 +3558,11 @@ msgstr ""
#: doc/classes/@GlobalScope.xml
msgid "Shift key mask."
-msgstr ""
+msgstr "Tasto Shift."
#: doc/classes/@GlobalScope.xml
msgid "Alt key mask."
-msgstr ""
+msgstr "Tasto Alt."
#: doc/classes/@GlobalScope.xml
msgid "Meta key mask."
@@ -3606,7 +3570,7 @@ msgstr ""
#: doc/classes/@GlobalScope.xml
msgid "Ctrl key mask."
-msgstr ""
+msgstr "Tasto Ctrl."
#: doc/classes/@GlobalScope.xml
msgid ""
@@ -3615,61 +3579,62 @@ msgid ""
"mask should be preferred to [constant KEY_MASK_META] or [constant "
"KEY_MASK_CTRL] for system shortcuts as it handles all platforms correctly."
msgstr ""
+"Tasto Comandi. Su macOS, ciò equivale a [constant KEY_MASK_META]. Su altre "
+"piattaforme, ciò equivale a [constant KEY_MASK_CTRL]. Questo tasto dovrebbe "
+"essere preferito a [constant KEY_MASK_META] o [constant KEY_MASK_CTRL] per "
+"sistemi di shortcut in quanto gestito correttamente da tutte le piattaforme."
#: doc/classes/@GlobalScope.xml
msgid "Keypad key mask."
-msgstr ""
+msgstr "Tasto Keypad."
#: doc/classes/@GlobalScope.xml
msgid "Group Switch key mask."
-msgstr ""
+msgstr "Tasto Group Switch."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "Left mouse button."
msgstr "Tasto sinistro del mouse."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "Right mouse button."
msgstr "Tasto destro del mouse."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "Middle mouse button."
msgstr "Tasto centrale del mouse."
#: doc/classes/@GlobalScope.xml
msgid "Extra mouse button 1 (only present on some mice)."
-msgstr ""
+msgstr "Tasto Mouse Extra 1 (presente solo su alcuni mouse)."
#: doc/classes/@GlobalScope.xml
msgid "Extra mouse button 2 (only present on some mice)."
-msgstr ""
+msgstr "Tasto Mouse Extra 1 (presente solo su alcuni mouse)."
#: doc/classes/@GlobalScope.xml
msgid "Mouse wheel up."
-msgstr ""
+msgstr "Rotella del Mouse in su'."
#: doc/classes/@GlobalScope.xml
msgid "Mouse wheel down."
-msgstr ""
+msgstr "Rotella del mouse in giu'."
#: doc/classes/@GlobalScope.xml
msgid "Mouse wheel left button (only present on some mice)."
-msgstr ""
+msgstr "Tasto rotella sinistra del mouse (presente solo su alcuni mouse)."
#: doc/classes/@GlobalScope.xml
msgid "Mouse wheel right button (only present on some mice)."
-msgstr ""
+msgstr "Tasto rotella del mouse destra (presente solo su alcuni mouse)."
#: doc/classes/@GlobalScope.xml
msgid "Left mouse button mask."
-msgstr ""
+msgstr "Tasto sinistro del mouse."
#: doc/classes/@GlobalScope.xml
msgid "Right mouse button mask."
-msgstr ""
+msgstr "Tasto destro del mouse."
#: doc/classes/@GlobalScope.xml
msgid "Middle mouse button mask."
@@ -3689,95 +3654,95 @@ msgstr ""
#: doc/classes/@GlobalScope.xml
msgid "Gamepad button 0."
-msgstr ""
+msgstr "Tasto 0 Gamepad."
#: doc/classes/@GlobalScope.xml
msgid "Gamepad button 1."
-msgstr ""
+msgstr "Tasto 1 Gamepad."
#: doc/classes/@GlobalScope.xml
msgid "Gamepad button 2."
-msgstr ""
+msgstr "Tasto 2 Gamepad."
#: doc/classes/@GlobalScope.xml
msgid "Gamepad button 3."
-msgstr ""
+msgstr "Tasto 3 Gamepad."
#: doc/classes/@GlobalScope.xml
msgid "Gamepad button 4."
-msgstr ""
+msgstr "Tasto 4 Gamepad."
#: doc/classes/@GlobalScope.xml
msgid "Gamepad button 5."
-msgstr ""
+msgstr "Tasto 5 Gamepad."
#: doc/classes/@GlobalScope.xml
msgid "Gamepad button 6."
-msgstr ""
+msgstr "Tasto 6 Gamepad."
#: doc/classes/@GlobalScope.xml
msgid "Gamepad button 7."
-msgstr ""
+msgstr "Tasto 7 Gamepad."
#: doc/classes/@GlobalScope.xml
msgid "Gamepad button 8."
-msgstr ""
+msgstr "Tasto 8 Gamepad."
#: doc/classes/@GlobalScope.xml
msgid "Gamepad button 9."
-msgstr ""
+msgstr "Tasto 9 Gamepad."
#: doc/classes/@GlobalScope.xml
msgid "Gamepad button 10."
-msgstr ""
+msgstr "Tasto 10 Gamepad."
#: doc/classes/@GlobalScope.xml
msgid "Gamepad button 11."
-msgstr ""
+msgstr "Tasto 11 Gamepad."
#: doc/classes/@GlobalScope.xml
msgid "Gamepad button 12."
-msgstr ""
+msgstr "Tasto 12 Gamepad."
#: doc/classes/@GlobalScope.xml
msgid "Gamepad button 13."
-msgstr ""
+msgstr "Tasto 13 Gamepad."
#: doc/classes/@GlobalScope.xml
msgid "Gamepad button 14."
-msgstr ""
+msgstr "Tasto 14 Gamepad."
#: doc/classes/@GlobalScope.xml
msgid "Gamepad button 15."
-msgstr ""
+msgstr "Tasto 15 Gamepad."
#: doc/classes/@GlobalScope.xml
msgid "Gamepad button 16."
-msgstr ""
+msgstr "Tasto 16 Gamepad."
#: doc/classes/@GlobalScope.xml
msgid "Gamepad button 17."
-msgstr ""
+msgstr "Tasto 17 Gamepad."
#: doc/classes/@GlobalScope.xml
msgid "Gamepad button 18."
-msgstr ""
+msgstr "Tasto 18 Gamepad."
#: doc/classes/@GlobalScope.xml
msgid "Gamepad button 19."
-msgstr ""
+msgstr "Tasto 19 Gamepad."
#: doc/classes/@GlobalScope.xml
msgid "Gamepad button 20."
-msgstr ""
+msgstr "Tasto 20 Gamepad."
#: doc/classes/@GlobalScope.xml
msgid "Gamepad button 21."
-msgstr ""
+msgstr "Tasto 21 Gamepad."
#: doc/classes/@GlobalScope.xml
msgid "Gamepad button 22."
-msgstr ""
+msgstr "Tasto 22 Gamepad."
#: doc/classes/@GlobalScope.xml
msgid ""
@@ -3787,114 +3752,125 @@ msgid ""
"- Linux: Up to 80 buttons.\n"
"- Windows and macOS: Up to 128 buttons."
msgstr ""
+"Il numero massimo di tasti di controller di gioco supportati dal motore. Il "
+"reale limite potrebbe essere inferiore su piattaforme specifiche:\n"
+"- Android: Fino a 36 tasti.\n"
+"- Linux: Fino a 80 tasti.\n"
+"- Windows e macOS: Fino a 128 tasti."
#: doc/classes/@GlobalScope.xml
msgid "DualShock circle button."
-msgstr ""
+msgstr "Tasto Cerchio del DualShock."
#: doc/classes/@GlobalScope.xml
msgid "DualShock X button."
-msgstr ""
+msgstr "Tasto X del DualShock."
#: doc/classes/@GlobalScope.xml
msgid "DualShock square button."
-msgstr ""
+msgstr "Tasto Quadrato del DualShock."
#: doc/classes/@GlobalScope.xml
msgid "DualShock triangle button."
-msgstr ""
+msgstr "Tasto Triangolo del DualShock."
#: doc/classes/@GlobalScope.xml
msgid "Xbox controller B button."
-msgstr ""
+msgstr "Tasto B del controller Xbox."
#: doc/classes/@GlobalScope.xml
msgid "Xbox controller A button."
-msgstr ""
+msgstr "Tasto A del controller Xbox."
#: doc/classes/@GlobalScope.xml
msgid "Xbox controller X button."
-msgstr ""
+msgstr "Tasto X del controller Xbox."
#: doc/classes/@GlobalScope.xml
msgid "Xbox controller Y button."
-msgstr ""
+msgstr "Tasto Y del controller Xbox."
#: doc/classes/@GlobalScope.xml
msgid "Nintendo controller A button."
-msgstr ""
+msgstr "Tasto A del controller Nintendo."
#: doc/classes/@GlobalScope.xml
msgid "Nintendo controller B button."
-msgstr ""
+msgstr "Tasto B del controller Nintendo."
#: doc/classes/@GlobalScope.xml
msgid "Nintendo controller X button."
-msgstr ""
+msgstr "Tasto X del controller Nintendo."
#: doc/classes/@GlobalScope.xml
msgid "Nintendo controller Y button."
-msgstr ""
+msgstr "Tasto Y del controller Nintendo."
#: doc/classes/@GlobalScope.xml
msgid "Grip (side) buttons on a VR controller."
-msgstr ""
+msgstr "Tasti Grip (di lato) su un controller VR."
#: doc/classes/@GlobalScope.xml
msgid "Push down on the touchpad or main joystick on a VR controller."
-msgstr ""
+msgstr "Premi giù sul touchpad o il joystick principale su un controller VR."
#: doc/classes/@GlobalScope.xml
msgid "Trigger on a VR controller."
-msgstr ""
+msgstr "Trigger su un controller VR."
#: doc/classes/@GlobalScope.xml
msgid ""
"A button on the right Oculus Touch controller, X button on the left "
"controller (also when used in OpenVR)."
msgstr ""
+"Tasto A sul controller destro Oculus Touch, tasto X sul controller sinistro "
+"(anche quando utilizzato in OpenVR)."
#: doc/classes/@GlobalScope.xml
msgid ""
"B button on the right Oculus Touch controller, Y button on the left "
"controller (also when used in OpenVR)."
msgstr ""
+"Tasto B sul controller destro Oculus Touch, tasto Y sul controller sinistro "
+"(anche quando utilizzando in OpenVR)."
#: doc/classes/@GlobalScope.xml
msgid "Menu button on either Oculus Touch controller."
-msgstr ""
+msgstr "Tasto Menu su entrambi i controller Oculus Touch."
#: doc/classes/@GlobalScope.xml
msgid "Menu button in OpenVR (Except when Oculus Touch controllers are used)."
msgstr ""
+"Tasto Menu in OpenVR (tranne quando sono in utilizzo i controller Oculus "
+"Touch)."
#: doc/classes/@GlobalScope.xml
msgid "Gamepad button Select."
-msgstr ""
+msgstr "Tasto Select del Gamepad."
#: doc/classes/@GlobalScope.xml
msgid "Gamepad button Start."
-msgstr ""
+msgstr "Tasto Start del Gamepad."
#: doc/classes/@GlobalScope.xml
msgid "Gamepad DPad up."
-msgstr ""
+msgstr "Tasto in su' DPad del Gamepad."
#: doc/classes/@GlobalScope.xml
msgid "Gamepad DPad down."
-msgstr ""
+msgstr "Tasto in giu' DPad del Gamepad."
#: doc/classes/@GlobalScope.xml
msgid "Gamepad DPad left."
-msgstr ""
+msgstr "Tasto sinistro DPad del Gamepad."
#: doc/classes/@GlobalScope.xml
msgid "Gamepad DPad right."
-msgstr ""
+msgstr "Tasto destro DPad del Gamepad."
#: doc/classes/@GlobalScope.xml
msgid "Gamepad SDL guide button."
-msgstr ""
+msgstr "Tasto Guida SDL del Gamepad."
#: doc/classes/@GlobalScope.xml
msgid "Gamepad SDL miscellaneous button."
@@ -4122,6 +4098,7 @@ msgid ""
msgstr ""
#: doc/classes/@GlobalScope.xml
+#, fuzzy
msgid ""
"Methods that return [enum Error] return [constant OK] when no error "
"occurred. Note that many functions don't return an error code but will print "
@@ -4137,30 +4114,39 @@ msgid ""
" print(\"Still failing!\")\n"
"[/codeblock]"
msgstr ""
+"Metodi che ritornano [enum Error] ritornano [constant OK] quando non risulta "
+"alcun errore. Nota che molte funzioni non ritornano un errore di codice ma "
+"stampano messaggi di errore come standard output.\n"
+"Dato che [constant OK] ha valore 0, e tutti gli altri codici mancati sono "
+"interi positivi, può essere utilizzato anche nei controlli booleani, e.g.:\n"
+"[codeblock]\n"
+"var err = method_that_returns_error()\n"
+"if err != OK:\n"
+" print(\"Failure!\")\n"
+"# O, equivalente:\n"
+"if err:\n"
+" print(\"Still failing!\")\n"
+"[/codeblock]"
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "Generic error."
msgstr "Errore generico."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "Unavailable error."
msgstr "Errore non disponibile."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "Unconfigured error."
msgstr "Errore non configurato."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "Unauthorized error."
msgstr "Errore non autorizzato."
#: doc/classes/@GlobalScope.xml
msgid "Parameter range error."
-msgstr ""
+msgstr "Errore di parametro del range."
#: doc/classes/@GlobalScope.xml
msgid "Out of memory (OOM) error."
@@ -4180,11 +4166,11 @@ msgstr ""
#: doc/classes/@GlobalScope.xml
msgid "File: No permission error."
-msgstr ""
+msgstr "File: Errore nessun permesso."
#: doc/classes/@GlobalScope.xml
msgid "File: Already in use error."
-msgstr ""
+msgstr "File: Errore già in uso."
#: doc/classes/@GlobalScope.xml
msgid "File: Can't open error."
@@ -4199,13 +4185,12 @@ msgid "File: Can't read error."
msgstr ""
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "File: Unrecognized error."
msgstr "File: Errore non riconosciuto."
#: doc/classes/@GlobalScope.xml
msgid "File: Corrupt error."
-msgstr ""
+msgstr "File: Errore corrotto."
#: doc/classes/@GlobalScope.xml
msgid "File: Missing dependencies error."
@@ -4216,14 +4201,12 @@ msgid "File: End of file (EOF) error."
msgstr ""
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "Can't open error."
-msgstr "Impossibile aprire l'errore."
+msgstr "Impossibile aprire errore."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "Can't create error."
-msgstr "Impossibile creare l'errore."
+msgstr "Impossibile creare errore."
#: doc/classes/@GlobalScope.xml
msgid "Query failed error."
@@ -4231,35 +4214,31 @@ msgstr ""
#: doc/classes/@GlobalScope.xml
msgid "Already in use error."
-msgstr ""
+msgstr "Errore già in uso."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "Locked error."
msgstr "Errore bloccato."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "Timeout error."
msgstr "Errore di timeout."
#: doc/classes/@GlobalScope.xml
msgid "Can't connect error."
-msgstr ""
+msgstr "Errore impossibile connettersi."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "Can't resolve error."
msgstr "Impossibile risolvere l'errore."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "Connection error."
msgstr "Errore di connessione."
#: doc/classes/@GlobalScope.xml
msgid "Can't acquire resource error."
-msgstr ""
+msgstr "Impossibile acquisire fonte dell'errore."
#: doc/classes/@GlobalScope.xml
msgid "Can't fork process error."
@@ -4270,36 +4249,32 @@ msgid "Invalid data error."
msgstr ""
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "Invalid parameter error."
msgstr "Errore di parametro non valido."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "Already exists error."
-msgstr "Esiste già l'errore."
+msgstr "Errore già esistente."
#: doc/classes/@GlobalScope.xml
msgid "Does not exist error."
-msgstr ""
+msgstr "Errore inesistente."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "Database: Read error."
msgstr "Database: Errore di lettura."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "Database: Write error."
msgstr "Database: Errore di scrittura."
#: doc/classes/@GlobalScope.xml
msgid "Compilation failed error."
-msgstr ""
+msgstr "Errore compilazione fallita."
#: doc/classes/@GlobalScope.xml
msgid "Method not found error."
-msgstr ""
+msgstr "Errore metodo non trovato."
#: doc/classes/@GlobalScope.xml
msgid "Linking failed error."
@@ -4307,24 +4282,23 @@ msgstr ""
#: doc/classes/@GlobalScope.xml
msgid "Script failed error."
-msgstr ""
+msgstr "Errore script fallito."
#: doc/classes/@GlobalScope.xml
msgid "Cycling link (import cycle) error."
msgstr ""
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "Invalid declaration error."
msgstr "Errore di dichiarazione non valida."
#: doc/classes/@GlobalScope.xml
msgid "Duplicate symbol error."
-msgstr ""
+msgstr "Errore simbolo duplicato."
#: doc/classes/@GlobalScope.xml
msgid "Parse error."
-msgstr ""
+msgstr "Errore di analizzazione."
#: doc/classes/@GlobalScope.xml
msgid "Busy error."
@@ -4336,21 +4310,23 @@ msgstr ""
#: doc/classes/@GlobalScope.xml
msgid "Help error."
-msgstr ""
+msgstr "Errore aiuto."
#: doc/classes/@GlobalScope.xml
msgid "Bug error."
-msgstr ""
+msgstr "Errore bug."
#: doc/classes/@GlobalScope.xml
msgid ""
"Printer on fire error. (This is an easter egg, no engine methods return this "
"error code.)"
msgstr ""
+"Errore stampante a fuoco. (E' un easter egg, nessun motore di metodi riporta "
+"questo codice di errore.)"
#: doc/classes/@GlobalScope.xml
msgid "No hint for the edited property."
-msgstr ""
+msgstr "Nessun indizio sulle proprietà modificate."
#: doc/classes/@GlobalScope.xml
msgid ""
@@ -4361,6 +4337,13 @@ msgid ""
"above the max or below the min values. Example: [code]\"-360,360,1,"
"or_greater,or_lesser\"[/code]."
msgstr ""
+"Indica che un numero intero o proprietà mobile dovrebbe essere in un range "
+"specifico tramite la stringa indicativa [code]\"min,max\"[/code] o "
+"[code]\"min,max,step\"[/code]. La stringa indicativa può, opzionalmente, "
+"includere [code]\"or_greater\"[/code] e/o [code]\"or_lesser\"[/code] per "
+"permettere un input manuale che vada rispettivamente sopra il massimo o "
+"sotto il minimo dei valori. Esempio: [code]\"-360,360,1,or_greater,"
+"or_lesser\"[/code]."
#: doc/classes/@GlobalScope.xml
msgid ""
@@ -4371,6 +4354,13 @@ msgid ""
"above the max or below the min values. Example: [code]\"0.01,100,0.01,"
"or_greater\"[/code]."
msgstr ""
+"Indica che una proprietà mobile dovrebbe essere in un range esponenziale "
+"specificato tramite la stringa indicativa [code]\"min,max\"[/code] "
+"o[code]\"min,max,step\"[/code]. La stringa indicativa può, opzionalmente, "
+"includere [code]\"or_greater\"[/code] e/o [code]\"or_lesser\"[/code] per "
+"permettere un input manuale di andare rispettivamente sopra il massimo o "
+"sotto il minimo dei valori. Esempio: [code]\"0.01,100,0.01,or_greater\"[/"
+"code]."
#: doc/classes/@GlobalScope.xml
msgid ""
@@ -4382,6 +4372,13 @@ msgid ""
"specified by appending [code]:integer[/code] to the name, e.g. [code]\"Zero,"
"One,Three:3,Four,Six:6\"[/code]."
msgstr ""
+"Indica che una proprietà intera, mobile o stringa sia un valore innumerato "
+"da scegliere tramite una specifica stringa indicativa.\n"
+"La stringa indicativa è un elenco di nomi come [code]\"Hello,Something,"
+"Else\"[/code]. Per proprietà intere o mobili, il primo nome sulla lista ha "
+"valore 0, il successivo 1, e così via. I valori espliciti possono anche "
+"essere specificati aggiungendo [code]:integer[/code] al nome, p.e. "
+"[code]\"Zero,One,Three:3,Four,Six:6\"[/code]."
#: doc/classes/@GlobalScope.xml
msgid ""
@@ -4509,6 +4506,26 @@ msgid "Hints that an image is compressed using lossless compression."
msgstr ""
#: doc/classes/@GlobalScope.xml
+msgid ""
+"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:\n"
+"[codeblock]\n"
+"hint_string = \"%s:\" % [TYPE_INT] # Array of inteters.\n"
+"hint_string = \"%s:%s:\" % [TYPE_ARRAY, TYPE_REAL] # Two-dimensional array "
+"of floats.\n"
+"hint_string = \"%s/%s:Resource\" % [TYPE_OBJECT, TYPE_OBJECT] # Array of "
+"resources.\n"
+"hint_string = \"%s:%s/%s:Resource\" % [TYPE_ARRAY, TYPE_OBJECT, TYPE_OBJECT] "
+"# Two-dimensional array of resources.\n"
+"[/codeblock]\n"
+"[b]Note:[/b] The final colon is required to specify for properly detecting "
+"built-in types."
+msgstr ""
+
+#: doc/classes/@GlobalScope.xml
msgid "The property is serialized and saved in the scene file (default)."
msgstr ""
@@ -5194,8 +5211,7 @@ msgstr ""
#: doc/classes/AudioStreamPlayer.xml doc/classes/Button.xml
#: doc/classes/CanvasLayer.xml doc/classes/CollisionShape2D.xml
#: doc/classes/ColorRect.xml doc/classes/Input.xml doc/classes/InputEvent.xml
-#: doc/classes/InputEventAction.xml doc/classes/Label.xml
-#: doc/classes/Particles2D.xml doc/classes/Timer.xml
+#: doc/classes/InputEventAction.xml doc/classes/Label.xml doc/classes/Timer.xml
#: doc/classes/VisibilityNotifier2D.xml
msgid "2D Dodge The Creeps Demo"
msgstr ""
@@ -7160,13 +7176,12 @@ msgid ""
msgstr ""
#: doc/classes/AnimationTreePlayer.xml
-#, fuzzy
msgid ""
"Returns whether node [code]id[/code] and [code]dst_id[/code] are connected "
"at the specified slot."
msgstr ""
-"Restituisce [code]true[/code] se [code]a[/code] e [code]b[/code] sono "
-"approssimativamente uguali tra di loro."
+"Restituisce se nodo [code]id[/code] e [code]dst_id[/code] sono connessi "
+"nella specifica casella."
#: doc/classes/AnimationTreePlayer.xml
msgid "Returns the blend amount of a Blend2 node given its name."
@@ -8132,7 +8147,10 @@ msgid ""
"var array = []\n"
"array.resize(10)\n"
"array.fill(0) # Initialize the 10 elements to 0.\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] If [code]value[/code] is of a reference type ([Object]-derived, "
+"[Array], [Dictionary], etc.) then the array is filled with the references to "
+"the same object, i.e. no duplicates are created."
msgstr ""
#: doc/classes/Array.xml doc/classes/PoolByteArray.xml
@@ -8317,6 +8335,9 @@ msgstr ""
#: doc/classes/Array.xml
msgid ""
"Sorts the array.\n"
+"[b]Note:[/b] The sorting algorithm used is not [url=https://en.wikipedia.org/"
+"wiki/Sorting_algorithm#Stability]stable[/url]. This means that values "
+"considered equal may have their order changed when using [method sort].\n"
"[b]Note:[/b] Strings are sorted in alphabetical order (as opposed to natural "
"order). This may lead to unexpected behavior when sorting an array of "
"strings ending with a sequence of numbers. Consider the following example:\n"
@@ -8336,9 +8357,13 @@ msgid ""
"For two elements [code]a[/code] and [code]b[/code], if the given method "
"returns [code]true[/code], element [code]b[/code] will be after element "
"[code]a[/code] in the array.\n"
+"[b]Note:[/b] The sorting algorithm used is not [url=https://en.wikipedia.org/"
+"wiki/Sorting_algorithm#Stability]stable[/url]. This means that values "
+"considered equal may have their order changed when using [method "
+"sort_custom].\n"
"[b]Note:[/b] You cannot randomize the return value as the heapsort algorithm "
-"expects a deterministic result. Doing so will result in unexpected "
-"behavior.\n"
+"expects a deterministic result. Randomizing the return value will result in "
+"unexpected behavior.\n"
"[codeblock]\n"
"class MyCustomSorter:\n"
" static func sort_ascending(a, b):\n"
@@ -8756,12 +8781,14 @@ msgid ""
msgstr ""
#: doc/classes/ARVRController.xml
-#, fuzzy
msgid ""
"Returns [code]true[/code] if the button at index [code]button[/code] is "
"pressed. See [enum JoystickList], in particular the [code]JOY_VR_*[/code] "
"constants."
-msgstr "Ritorna [code]true[/code] se [code]s[/code] è zero o quasi zero."
+msgstr ""
+"Ritorna [code]true[/code]se il tasto sull'indice [code]button[/code] è stato "
+"premuto. Vedi [enum JoystickList], in particolare i [code]JOY_VR_*[/code] "
+"costanti."
#: doc/classes/ARVRController.xml
msgid ""
@@ -9305,9 +9332,8 @@ 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 "Contenitore a schede."
+msgstr "Contenitore a schede"
#: doc/classes/AspectRatioContainer.xml
msgid "Specifies the horizontal relative position of child controls."
@@ -9894,13 +9920,12 @@ msgid "Audio buses"
msgstr ""
#: doc/classes/AudioEffectCapture.xml
-#, fuzzy
msgid ""
"Returns [code]true[/code] if at least [code]frames[/code] audio frames are "
"available to read in the internal ring buffer."
msgstr ""
-"Restituisce [code]true[/code] se [code]a[/code] e [code]b[/code] sono "
-"approssimativamente uguali tra di loro."
+"Restituisce [code]true[/code] se almeno [code]frames[/code] frame audio sono "
+"disponibili per la lettura nell'internal ring buffer."
#: doc/classes/AudioEffectCapture.xml
msgid "Clears the internal ring buffer."
@@ -10986,12 +11011,14 @@ msgid "Clears the audio sample data buffer."
msgstr ""
#: doc/classes/AudioStreamGeneratorPlayback.xml
+#, fuzzy
msgid ""
-"Returns the number of audio data frames left to play. If this returned "
-"number reaches [code]0[/code], the audio will stop playing until frames are "
-"added again. Therefore, make sure your script can always generate and push "
-"new audio frames fast enough to avoid audio cracking."
+"Returns the number of frames that can be pushed to the audio sample data "
+"buffer without overflowing it. If the result is [code]0[/code], the buffer "
+"is full."
msgstr ""
+"Ritorna [code]true[/code] se l'impostazione specificata da [code]name[/code] "
+"esiste, [code]false[/code] altrimenti."
#: doc/classes/AudioStreamGeneratorPlayback.xml
msgid ""
@@ -11522,14 +11549,14 @@ msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
"Node for back-buffering the currently-displayed screen. The region defined "
-"in the BackBufferCopy node is buffered with the content of the screen it "
+"in the [BackBufferCopy] node is buffered with the content of the screen it "
"covers, or the entire screen according to the copy mode set. Use the "
"[code]texture(SCREEN_TEXTURE, ...)[/code] function in your shader scripts to "
"access the buffer.\n"
"[b]Note:[/b] Since this node inherits from [Node2D] (and not [Control]), "
"anchors and margins won't apply to child [Control]-derived nodes. This can "
"be problematic when resizing the window. To avoid this, add [Control]-"
-"derived nodes as [i]siblings[/i] to the BackBufferCopy node instead of "
+"derived nodes as [i]siblings[/i] to the [BackBufferCopy] node instead of "
"adding them as children."
msgstr ""
@@ -11539,22 +11566,22 @@ msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
-"The area covered by the BackBufferCopy. Only used if [member copy_mode] is "
+"The area covered by the [BackBufferCopy]. Only used if [member copy_mode] is "
"[constant COPY_MODE_RECT]."
msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
-"Disables the buffering mode. This means the BackBufferCopy node will "
+"Disables the buffering mode. This means the [BackBufferCopy] node will "
"directly use the portion of screen it covers."
msgstr ""
#: doc/classes/BackBufferCopy.xml
-msgid "BackBufferCopy buffers a rectangular region."
+msgid "[BackBufferCopy] buffers a rectangular region."
msgstr ""
#: doc/classes/BackBufferCopy.xml
-msgid "BackBufferCopy buffers the entire screen."
+msgid "[BackBufferCopy] buffers the entire screen."
msgstr ""
#: doc/classes/BakedLightmap.xml
@@ -13261,9 +13288,9 @@ msgid "The camera's process callback. See [enum Camera2DProcessMode]."
msgstr ""
#: doc/classes/Camera2D.xml
-#, fuzzy
msgid "If [code]true[/code], the camera view rotates with the target."
-msgstr "Ritorna [code]true[/code] se [code]s[/code] è zero o quasi zero."
+msgstr ""
+"Se [code]true[/code], la visuale della telecamera ruota insieme al target."
#: doc/classes/Camera2D.xml
msgid ""
@@ -13401,11 +13428,12 @@ msgid "Returns an array of [CameraFeed]s."
msgstr ""
#: doc/classes/CameraServer.xml
-#, fuzzy
msgid ""
"Returns the [CameraFeed] corresponding to the camera with the given "
"[code]index[/code]."
-msgstr "Ritorna [code]true[/code] se [code]s[/code] è zero o quasi zero."
+msgstr ""
+"Restituisce il [CameraFeed] corrispondente alla telecamera con il dato "
+"[code]index[/code]."
#: doc/classes/CameraServer.xml
msgid "Returns the number of [CameraFeed]s registered."
@@ -14740,9 +14768,8 @@ msgid ""
msgstr ""
#: doc/classes/ClippedCamera.xml
-#, fuzzy
msgid "If [code]true[/code], the camera stops on contact with [Area]s."
-msgstr "Ritorna [code]true[/code] se [code]s[/code] è zero o quasi zero."
+msgstr "Se [code]true[/code], la telecamera si ferma al contatto con [Area]s."
#: doc/classes/ClippedCamera.xml
msgid "If [code]true[/code], the camera stops on contact with [PhysicsBody]s."
@@ -15160,9 +15187,8 @@ msgstr ""
#: doc/classes/Physics2DDirectSpaceState.xml
#: doc/classes/PhysicsDirectBodyState.xml
#: doc/classes/PhysicsDirectSpaceState.xml doc/classes/RigidBody.xml
-#, fuzzy
msgid "Physics introduction"
-msgstr "Interpolazione cubica."
+msgstr "Introduzione fisica"
#: doc/classes/CollisionShape.xml
msgid ""
@@ -16792,7 +16818,7 @@ msgstr ""
#: doc/classes/Control.xml
#, fuzzy
msgid "Control node gallery"
-msgstr "Tasto Control/CTRL."
+msgstr "Galleria controllo nodo"
#: doc/classes/Control.xml
msgid "All GUI Demos"
@@ -16902,15 +16928,16 @@ msgid ""
msgstr ""
#: 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 ""
-"Ritorna [code]true[/code] se l'impostazione specificata da [code]name[/code] "
-"esiste, [code]false[/code] altrimenti."
+"Crea un override locale per un tema costante con lo specifico [code]name[/"
+"code]. I local overrides hanno sempre la precedenza quando si recuperano "
+"elementi del tema per il controllo.\n"
+"Vedi anche [method get_constant], [method remove_constant_override]."
#: doc/classes/Control.xml
msgid ""
@@ -17210,14 +17237,14 @@ msgid ""
msgstr ""
#: doc/classes/Control.xml
-#, fuzzy
msgid ""
"Returns [code]true[/code] if there is a local override for a theme [Color] "
"with the specified [code]name[/code] in this [Control] node.\n"
"See [method add_color_override]."
msgstr ""
-"Ritorna [code]true[/code] se l'impostazione specificata da [code]name[/code] "
-"esiste, [code]false[/code] altrimenti."
+"Restituisce [code]true[/code] se è presente un locale override per un tema "
+"[Color] con lo specifico [code]name[/code] in questo [Control] nodo.\n"
+"Vedi [method add_color_override]."
#: doc/classes/Control.xml
msgid ""
@@ -17228,14 +17255,14 @@ msgid ""
msgstr ""
#: doc/classes/Control.xml
-#, fuzzy
msgid ""
"Returns [code]true[/code] if there is a local override for a theme constant "
"with the specified [code]name[/code] in this [Control] node.\n"
"See [method add_constant_override]."
msgstr ""
-"Ritorna [code]true[/code] se l'impostazione specificata da [code]name[/code] "
-"esiste, [code]false[/code] altrimenti."
+"Restituisce [code]true[/code] se c'è un override locale per un tema costante "
+"nello specifico [code]name[/code] in questo [Control] nodo.\n"
+"Vedi [method add_constant_override]."
#: doc/classes/Control.xml
msgid ""
@@ -17255,14 +17282,14 @@ msgstr ""
"esiste, [code]false[/code] altrimenti."
#: doc/classes/Control.xml
-#, fuzzy
msgid ""
"Returns [code]true[/code] if there is a local override for a theme [Font] "
"with the specified [code]name[/code] in this [Control] node.\n"
"See [method add_font_override]."
msgstr ""
-"Ritorna [code]true[/code] se l'impostazione specificata da [code]name[/code] "
-"esiste, [code]false[/code] altrimenti."
+"Restituisce [code]true[/code] se è presente un override locale per un tema "
+"[Font] con lo specifico [code]name[/code] in questo [Control] nodo.\n"
+"Vedi [method add_font_override]."
#: doc/classes/Control.xml
#, fuzzy
@@ -17276,14 +17303,14 @@ msgstr ""
"esiste, [code]false[/code] altrimenti."
#: doc/classes/Control.xml
-#, fuzzy
msgid ""
"Returns [code]true[/code] if there is a local override for a theme icon with "
"the specified [code]name[/code] in this [Control] node.\n"
"See [method add_icon_override]."
msgstr ""
-"Ritorna [code]true[/code] se l'impostazione specificata da [code]name[/code] "
-"esiste, [code]false[/code] altrimenti."
+"Restituisce [code]true[/code] se è presente un override locale per un'icona "
+"a tema con lo specifico [code]name[/code] in questo [Control] nodo.\n"
+"Vedi [method add_icon_override]."
#: doc/classes/Control.xml
msgid ""
@@ -17296,14 +17323,15 @@ msgid ""
msgstr ""
#: doc/classes/Control.xml
-#, fuzzy
msgid ""
"Returns [code]true[/code] if there is a local override for a theme shader "
"with the specified [code]name[/code] in this [Control] node.\n"
"See [method add_shader_override]."
msgstr ""
-"Ritorna [code]true[/code] se l'impostazione specificata da [code]name[/code] "
-"esiste, [code]false[/code] altrimenti."
+"Restituisce [code]true[/code] se è un presente un override locale per un "
+"ombreggiatore di tema con lo specifico [code]name[/code] in questo [Control] "
+"nodo.\n"
+"Vedi [method add_shader_override]."
#: doc/classes/Control.xml
msgid ""
@@ -17314,14 +17342,14 @@ msgid ""
msgstr ""
#: doc/classes/Control.xml
-#, fuzzy
msgid ""
"Returns [code]true[/code] if there is a local override for a theme "
"[StyleBox] with the specified [code]name[/code] in this [Control] node.\n"
"See [method add_stylebox_override]."
msgstr ""
-"Ritorna [code]true[/code] se l'impostazione specificata da [code]name[/code] "
-"esiste, [code]false[/code] altrimenti."
+"Restituisce [code]true[/code] se è presente un override locale per un tema "
+"[StyleBox] con lo specifico [code]name[/code] in questo [Control] nodo.\n"
+"Vedi [method add_stylebox_override]."
#: doc/classes/Control.xml
msgid ""
@@ -20445,6 +20473,14 @@ msgid "Cylinder shape for collisions."
msgstr ""
#: doc/classes/CylinderShape.xml
+msgid ""
+"Cylinder shape for collisions.\n"
+"[b]Note:[/b] When using GodotPhysics instead of the default Bullet physics "
+"engine, there are several known bugs with cylinder collision shapes. Using "
+"[CapsuleShape] or [BoxShape] instead is recommended."
+msgstr ""
+
+#: doc/classes/CylinderShape.xml
msgid "The cylinder's height."
msgstr ""
@@ -23285,7 +23321,10 @@ msgid ""
"[/codeblock]\n"
"[b]Note:[/b] The script is run in the Editor context, which means the output "
"is visible in the console window started with the Editor (stdout) instead of "
-"the usual Godot [b]Output[/b] dock."
+"the usual Godot [b]Output[/b] dock.\n"
+"[b]Note:[/b] EditorScript is reference counted, meaning it is destroyed when "
+"nothing references it. This can cause errors during asynchronous operations "
+"if there are no references to the script."
msgstr ""
#: doc/classes/EditorScript.xml
@@ -28290,11 +28329,12 @@ msgid ""
msgstr ""
#: 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 "Ritorna [code]true[/code] se [code]s[/code] è zero o quasi zero."
+msgstr ""
+"Restituisce un vettore di tutte le celle con il dato elemento indice "
+"specificato in [code]item[/code]."
#: modules/gridmap/doc_classes/GridMap.xml
msgid ""
@@ -28326,11 +28366,12 @@ 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 "Ritorna [code]true[/code] se [code]s[/code] è zero o quasi zero."
+msgstr ""
+"Se [code]true[/code], questa GridMap utilizza celle navmesh come fonti per "
+"creare regioni di navigazione."
#: modules/gridmap/doc_classes/GridMap.xml
msgid "If [code]true[/code], grid items are centered on the X axis."
@@ -30986,11 +31027,12 @@ msgid ""
msgstr ""
#: doc/classes/Input.xml
-#, fuzzy
msgid ""
"Returns [code]true[/code] if you are pressing the joypad button (see [enum "
"JoystickList])."
-msgstr "Ritorna [code]true[/code] se [code]s[/code] è zero o quasi zero."
+msgstr ""
+"Restituisce [code]true[/code] se premi un tasto del joypad (vedi [enum "
+"JoystickList])."
#: doc/classes/Input.xml
msgid ""
@@ -31774,11 +31816,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."
+msgstr ""
+"Restituisce [code]true[/code] quando è in utilizzo la gomma di una penna "
+"stilo.\n"
+"[b]Nota:[/b] Questa proprietà è implementata su Linux, macOS e Windows."
#: doc/classes/InputEventMouseMotion.xml
msgid ""
@@ -33974,9 +34018,8 @@ msgid "Returns the offset of the piece with the index [code]idx[/code]."
msgstr ""
#: doc/classes/LargeTexture.xml
-#, fuzzy
msgid "Returns the [Texture] of the piece with the index [code]idx[/code]."
-msgstr "Ritorna [code]true[/code] se [code]s[/code] è zero o quasi zero."
+msgstr "Restituisce la [Texture] del pezzo con l'indice [code]idx[/code]."
#: doc/classes/LargeTexture.xml
msgid ""
@@ -34063,7 +34106,9 @@ msgid ""
"The size of the light in Godot units. Only considered in baked lightmaps and "
"only if [member light_bake_mode] is set to [constant BAKE_ALL]. Increasing "
"this value will make the shadows appear blurrier. This can be used to "
-"simulate area lights to an extent."
+"simulate area lights to an extent.\n"
+"[b]Note:[/b] [member light_size] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/Light.xml
@@ -37223,9 +37268,10 @@ msgid ""
msgstr ""
#: doc/classes/Navigation2DServer.xml
-#, fuzzy
msgid "Returns the map cell height. [b]Note:[/b] Currently not implemented."
-msgstr "Prende la linea corrente nel file analizzato (non ancora implementato)"
+msgstr ""
+"Prende la linea corrente nel file analizzato. [b]Note:[/b] Attualmente non "
+"implementato."
#: doc/classes/Navigation2DServer.xml doc/classes/NavigationServer.xml
#, fuzzy
@@ -37399,7 +37445,10 @@ msgid ""
"use the [method get_next_location] function once every physics frame to "
"update the internal path logic of the NavigationAgent. The returned vector "
"position from this function should be used as the next movement position for "
-"the agent's parent Node."
+"the agent's parent Node.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues."
msgstr ""
#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
@@ -37652,7 +37701,10 @@ msgid ""
"use the [method get_next_location] function once every physics frame to "
"update the internal path logic of the NavigationAgent. The returned vector "
"position from this function should be used as the next movement position for "
-"the agent's parent Node."
+"the agent's parent Node.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues."
msgstr ""
#: doc/classes/NavigationAgent2D.xml
@@ -37733,13 +37785,12 @@ msgid ""
msgstr ""
#: doc/classes/NavigationMesh.xml
-#, fuzzy
msgid ""
"Returns whether the specified [code]bit[/code] of the [member "
"geometry_collision_mask] is set."
msgstr ""
-"Ritorna [code]true[/code] se l'impostazione specificata da [code]name[/code] "
-"esiste, [code]false[/code] altrimenti."
+"Restituisce se lo specifico [code]bit[/code] del [member "
+"geometry_collision_mask] è impostato."
#: doc/classes/NavigationMesh.xml doc/classes/NavigationPolygon.xml
msgid ""
@@ -38377,6 +38428,9 @@ msgid ""
"modified velocity as-is might lead to pushing and agent outside of a "
"navigable area. This is a limitation of the collision avoidance system, any "
"more complex situation may require the use of the physics engine.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues.\n"
"This server keeps tracks of any call and executes them during the sync "
"phase. This means that you can request any change to the map, using any "
"thread, without worrying."
@@ -40866,13 +40920,12 @@ msgid ""
msgstr ""
#: doc/classes/Object.xml
-#, fuzzy
msgid ""
"Returns [code]true[/code] if a connection exists for a given [code]signal[/"
"code], [code]target[/code], and [code]method[/code]."
msgstr ""
-"Ritorna [code]true[/code] se l'impostazione specificata da [code]name[/code] "
-"esiste, [code]false[/code] altrimenti."
+"Restituisce [code]true[/code] se la connessione esiste per un dato "
+"[code]signal[/code], [code]target[/code], e [code]method[/code]."
#: doc/classes/Object.xml
msgid ""
@@ -41195,7 +41248,9 @@ msgid ""
"The light's radius. Note that the effectively lit area may appear to be "
"smaller depending on the [member omni_attenuation] in use. No matter the "
"[member omni_attenuation] in use, the light will never reach anything "
-"outside this radius."
+"outside this radius.\n"
+"[b]Note:[/b] [member omni_range] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -41712,11 +41767,11 @@ msgstr "Restituisce l'angolo al vettore dato, in radianti."
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] cache data directory according to the operating "
-"system's standards. On desktop platforms, this path can be overridden by "
-"setting the [code]XDG_CACHE_HOME[/code] environment variable before starting "
-"the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in "
-"Godot projects[/url] in the documentation for more information. See also "
-"[method get_config_dir] and [method get_data_dir].\n"
+"system's standards. On Linux, this path can be overridden by setting the "
+"[code]XDG_CACHE_HOME[/code] environment variable before starting the "
+"project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot "
+"projects[/url] in the documentation for more information. See also [method "
+"get_config_dir] and [method get_data_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -41750,11 +41805,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] user configuration directory according to the "
-"operating system's standards. On desktop platforms, this path can be "
-"overridden by setting the [code]XDG_CONFIG_HOME[/code] environment variable "
-"before starting the project. See [url=$DOCS_URL/tutorials/io/data_paths."
-"html]File paths in Godot projects[/url] in the documentation for more "
-"information. See also [method get_cache_dir] and [method get_data_dir].\n"
+"operating system's standards. On Linux, this path can be overridden by "
+"setting the [code]XDG_CONFIG_HOME[/code] environment variable before "
+"starting the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File "
+"paths in Godot projects[/url] in the documentation for more information. See "
+"also [method get_cache_dir] and [method get_data_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -41776,11 +41831,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] user data directory according to the operating "
-"system's standards. On desktop platforms, this path can be overridden by "
-"setting the [code]XDG_DATA_HOME[/code] environment variable before starting "
-"the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in "
-"Godot projects[/url] in the documentation for more information. See also "
-"[method get_cache_dir] and [method get_config_dir].\n"
+"system's standards. On Linux, this path can be overridden by setting the "
+"[code]XDG_DATA_HOME[/code] environment variable before starting the project. "
+"See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot "
+"projects[/url] in the documentation for more information. See also [method "
+"get_cache_dir] and [method get_config_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -42304,11 +42359,12 @@ msgid ""
msgstr ""
#: doc/classes/OS.xml
-#, fuzzy
msgid ""
"Returns [code]true[/code] if the [b]OK[/b] button should appear on the left "
"and [b]Cancel[/b] on the right."
-msgstr "Ritorna [code]true[/code] se [code]s[/code] è zero o quasi zero."
+msgstr ""
+"Restituisce [code]true[/code] se il tasto [b]OK[/b] debba apparire a "
+"sinistra e [b]Cancel[/b] a destra."
#: doc/classes/OS.xml
msgid ""
@@ -42320,11 +42376,12 @@ msgid ""
msgstr ""
#: doc/classes/OS.xml
-#, fuzzy
msgid ""
"Returns [code]true[/code] if the input scancode corresponds to a Unicode "
"character."
-msgstr "Ritorna [code]true[/code] se [code]s[/code] è zero o quasi zero."
+msgstr ""
+"Restituisce [code]true[/code] se l'input scancode corrisponde a un carattere "
+"Unicode."
#: doc/classes/OS.xml
msgid ""
@@ -43140,7 +43197,6 @@ msgid ""
msgstr ""
#: doc/classes/PacketPeer.xml
-#, fuzzy
msgid ""
"[i]Deprecated.[/i] Use [code]get_var[/code] and [code]put_var[/code] "
"parameters instead.\n"
@@ -43150,12 +43206,14 @@ 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 ""
-"Decodifica un byte array in un valore. Quando [code]allow_objects[/code] è "
-"[code]true[/code], decodificare gli oggetti è permesso.\n"
-"[b]ATTENZIONE:[/b] Deserializzare un oggetto può contenere codice che verrà "
+"[i]Deprecated.[/i] Usa i parametri [code]get_var[/code] e [code]put_var[/"
+"code] piuttosto.\n"
+"Se [code]true[/code], il PacketPeer consentirà la codifica e decodifica di "
+"oggetti tramite [method get_var] and [method put_var].\n"
+"[b]Attenzione:[/b] Oggetti deserializzati possono contenere codice che verrà "
"eseguito. Non usare questa opzione se l'oggetto serializzato arriva da fonti "
-"sconosciute per evitare potenziali pericoli di sicurezza (remote code "
-"execution, esecuzione di codice remoto)."
+"inaffidabili per evitare potenziali minacce di sicurezza come esecuzione di "
+"codice remoto."
#: doc/classes/PacketPeer.xml
msgid ""
@@ -43659,6 +43717,16 @@ msgid "Particle systems (2D)"
msgstr ""
#: doc/classes/Particles2D.xml
+msgid "2D Particles Demo"
+msgstr ""
+
+#: doc/classes/Particles2D.xml
+msgid ""
+"2D Dodge The Creeps Demo (uses GPUParticles2D for the trail behind the "
+"player)"
+msgstr ""
+
+#: doc/classes/Particles2D.xml
msgid "Returns a rectangle containing the positions of all existing particles."
msgstr ""
@@ -46826,11 +46894,12 @@ msgstr ""
#: doc/classes/PoolIntArray.xml doc/classes/PoolRealArray.xml
#: doc/classes/PoolStringArray.xml doc/classes/PoolVector2Array.xml
#: doc/classes/PoolVector3Array.xml
-#, fuzzy
msgid ""
"Returns [code]true[/code] if the array contains the given value.\n"
"[b]Note:[/b] This is equivalent to using the [code]in[/code] operator."
-msgstr "Ritorna [code]true[/code] se [code]s[/code] è zero o quasi zero."
+msgstr ""
+"Ritorna [code]true[/code] se il vettore contiene il dato valore.\n"
+"[b]Nota:[/b] Ciò equivale ad utilizzare il [code]in[/code] operatore."
#: doc/classes/PoolByteArray.xml
msgid ""
@@ -47084,11 +47153,12 @@ msgid "Appends a [PoolStringArray] at the end of this array."
msgstr ""
#: doc/classes/PoolStringArray.xml
-#, fuzzy
msgid ""
"Returns a [String] with each element of the array joined with the given "
"[code]delimiter[/code]."
-msgstr "Ritorna [code]true[/code] se [code]s[/code] è zero o quasi zero."
+msgstr ""
+"Restituisce una [String] con cui ogni elemento del vettore aderì con il dato "
+"[code]delimiter[/code]."
#: doc/classes/PoolStringArray.xml
msgid "Appends a string element at end of the array."
@@ -47570,11 +47640,13 @@ msgid ""
msgstr ""
#: doc/classes/PopupMenu.xml
-#, fuzzy
msgid ""
"Sets the currently focused item as the given [code]index[/code].\n"
"Passing [code]-1[/code] as the index makes so that no item is focused."
-msgstr "Calcola il prodotto vettoriale di questo vettore e [code]with[/code]."
+msgstr ""
+"Imposta l'attuale elemento focalizzato come il dato [code]index[/code].\n"
+"Passando [code]-1[/code] come indice fa in modo che nessun elemento venga "
+"focalizzato."
#: doc/classes/PopupMenu.xml
msgid "Hides the [PopupMenu] when the window loses focus."
@@ -51264,15 +51336,22 @@ msgstr ""
#: doc/classes/ProjectSettings.xml
msgid ""
"If [code]true[/code], uses a fast post-processing filter to make banding "
-"significantly less visible. In some cases, debanding may introduce a "
-"slightly noticeable dithering pattern. It's recommended to enable debanding "
-"only when actually needed since the dithering pattern will make lossless-"
-"compressed screenshots larger.\n"
+"significantly less visible in 3D. 2D rendering is [i]not[/i] affected by "
+"debanding unless the [member Environment.background_mode] is [constant "
+"Environment.BG_CANVAS]. In this case, [member rendering/quality/"
+"intended_usage/framebuffer_allocation] must also be set to [b]3D[/b].\n"
+"In some cases, debanding may introduce a slightly noticeable dithering "
+"pattern. It's recommended to enable debanding only when actually needed "
+"since the dithering pattern will make lossless-compressed screenshots "
+"larger.\n"
"[b]Note:[/b] Only available on the GLES3 backend. [member rendering/quality/"
"depth/hdr] must also be [code]true[/code] for debanding to be effective.\n"
"[b]Note:[/b] There are known issues with debanding breaking rendering on "
"mobile platforms. Due to this, it is recommended to leave this option "
-"disabled when targeting mobile platforms."
+"disabled when targeting mobile platforms.\n"
+"[b]Note:[/b] This property is only read when the project starts. To set "
+"debanding at run-time, set [member Viewport.debanding] on the root "
+"[Viewport] instead."
msgstr ""
#: doc/classes/ProjectSettings.xml
@@ -51911,14 +51990,14 @@ msgid "Returns the inverse of the quaternion."
msgstr ""
#: doc/classes/Quat.xml
-#, fuzzy
msgid ""
"Returns [code]true[/code] if this quaternion and [code]quat[/code] are "
"approximately equal, by running [method @GDScript.is_equal_approx] on each "
"component."
msgstr ""
-"Restituisce [code]true[/code] se [code]a[/code] e [code]b[/code] sono "
-"approssimativamente uguali tra di loro."
+"Restituisce [code]true[/code] se questo quaternione e [code]quat[/code] "
+"sono approssimativament eguali, avviando [method @GDScript.is_equal_approx] "
+"su ogni componente."
#: doc/classes/Quat.xml
msgid "Returns whether the quaternion is normalized or not."
@@ -52875,17 +52954,28 @@ msgstr ""
#: modules/regex/doc_classes/RegEx.xml
msgid ""
"Searches the text for the compiled pattern. Returns a [RegExMatch] container "
-"of the first matching result if found, otherwise [code]null[/code]. The "
-"region to search within can be specified without modifying where the start "
-"and end anchor would be."
+"of the first matching result if found, otherwise [code]null[/code].\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegEx.xml
msgid ""
"Searches the text for the compiled pattern. Returns an array of [RegExMatch] "
"containers for each non-overlapping result. If no results were found, an "
-"empty array is returned instead. The region to search within can be "
-"specified without modifying where the start and end anchor would be."
+"empty array is returned instead.\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegEx.xml
@@ -52894,8 +52984,14 @@ msgid ""
"specified string. Escapes and backreferences such as [code]$1[/code] and "
"[code]$name[/code] are expanded and resolved. By default, only the first "
"instance is replaced, but it can be changed for all instances (global "
-"replacement). The region to search within can be specified without modifying "
-"where the start and end anchor would be."
+"replacement).\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegExMatch.xml
@@ -53299,11 +53395,12 @@ msgid ""
msgstr ""
#: doc/classes/ResourceInteractiveLoader.xml
-#, fuzzy
msgid ""
"Returns the loaded resource if the load operation completed successfully, "
"[code]null[/code] otherwise."
-msgstr "Ritorna [code]true[/code] se [code]s[/code] è zero o quasi zero."
+msgstr ""
+"Restituisce la fonte caricata se l'operazione caricata è stata completata "
+"con successo, [code]null[/code] altrimenti."
#: doc/classes/ResourceInteractiveLoader.xml
msgid ""
@@ -55614,7 +55711,11 @@ msgid "Call a group immediately (calls are normally made on idle)."
msgstr ""
#: doc/classes/SceneTree.xml
-msgid "Call a group only once even if the call is executed many times."
+msgid ""
+"Call a group only once even if the call is executed many times.\n"
+"[b]Note:[/b] Arguments are not taken into account when deciding whether the "
+"call is unique or not. Therefore when the same method is called with "
+"different arguments, only the first call will be performed."
msgstr ""
#: doc/classes/SceneTree.xml
@@ -57453,7 +57554,9 @@ msgid ""
"[b]Note:[/b] Mixed negative scales in 3D are not decomposable from the "
"transformation matrix. Due to the way scale is represented with "
"transformation matrices in Godot, the scale values will either be all "
-"positive or all negative."
+"positive or all negative.\n"
+"[b]Note:[/b] Not all nodes are visually scaled by the [member scale] "
+"property. For example, [Light]s are not visually affected by [member scale]."
msgstr ""
#: doc/classes/Spatial.xml
@@ -58835,7 +58938,10 @@ msgid ""
msgstr ""
#: doc/classes/SpotLight.xml
-msgid "The spotlight's angle in degrees."
+msgid ""
+"The spotlight's angle in degrees.\n"
+"[b]Note:[/b] [member spot_angle] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/SpotLight.xml
@@ -58851,7 +58957,9 @@ msgid ""
"The maximal range that can be reached by the spotlight. Note that the "
"effectively lit area may appear to be smaller depending on the [member "
"spot_attenuation] in use. No matter the [member spot_attenuation] in use, "
-"the light will never reach anything outside this range."
+"the light will never reach anything outside this range.\n"
+"[b]Note:[/b] [member spot_range] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/SpringArm.xml
@@ -61956,20 +62064,20 @@ msgid ""
msgstr "Ritorna [code]true[/code] se [code]s[/code] è zero o quasi zero."
#: doc/classes/TextEdit.xml
-#, fuzzy
msgid ""
"Returns [code]true[/code] when the specified [code]line[/code] has a "
"breakpoint."
-msgstr "Ritorna [code]true[/code] se [Rect2i] contiene un punto."
+msgstr ""
+"Restituisce [code]true[/code] quando lo specificato [code]line[/code] ha un "
+"breakpoint."
#: doc/classes/TextEdit.xml
-#, fuzzy
msgid ""
"Returns [code]true[/code] when the specified [code]line[/code] is marked as "
"safe."
msgstr ""
-"Ritorna [code]true[/code] se l'impostazione specificata da [code]name[/code] "
-"esiste, [code]false[/code] altrimenti."
+"Restituisce [code]true[/code] quando lo specifico [code]line[/code] è "
+"marcato come sicuro."
#: doc/classes/TextEdit.xml
#, fuzzy
@@ -61977,13 +62085,12 @@ msgid "Returns if the given line is wrapped."
msgstr "Restituisce la tangente del parametro."
#: 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 ""
-"Restituisce [code]true[/code] se [code]a[/code] e [code]b[/code] sono "
-"approssimativamente uguali tra di loro."
+"Restituisce se il mouse è sotto selezione. Se [code]edges[/code] è "
+"[code]true[/code], gli angoli sono considerati parte della selezione"
#: doc/classes/TextEdit.xml
msgid "Returns [code]true[/code] if the selection is active."
@@ -63034,11 +63141,12 @@ msgid ""
msgstr "Ritorna [code]true[/code] se [code]s[/code] è zero o quasi zero."
#: doc/classes/Theme.xml
-#, fuzzy
msgid ""
"Clears the theme item of [code]data_type[/code] at [code]name[/code] if the "
"theme has [code]theme_type[/code]."
-msgstr "Ritorna [code]true[/code] se [code]s[/code] è zero o quasi zero."
+msgstr ""
+"Pulisce l'elemento del tema di [code]data_type[/code] a [code]name[/code] se "
+"il tema contiene [code]theme_type[/code]."
#: doc/classes/Theme.xml
msgid ""
@@ -63062,12 +63170,14 @@ msgid ""
msgstr "Ritorna [code]true[/code] se [code]s[/code] è zero o quasi zero."
#: doc/classes/Theme.xml
-#, fuzzy
msgid ""
"Returns all the [Color]s as a [PoolStringArray] filled with each [Color]'s "
"name, for use in [method get_color], if the theme has [code]theme_type[/"
"code]."
-msgstr "Ritorna [code]true[/code] se [code]s[/code] è zero o quasi zero."
+msgstr ""
+"Restituisce tutto il [Color]s come un [PoolStringArray] riempito di "
+"[Color]'s nomi, per utilizzo in [method get_color], se il tema ha "
+"[code]theme_type[/code]."
#: doc/classes/Theme.xml
msgid ""
@@ -63083,12 +63193,14 @@ msgid ""
msgstr "Ritorna [code]true[/code] se [code]s[/code] è zero o quasi zero."
#: doc/classes/Theme.xml
-#, fuzzy
msgid ""
"Returns all the constants as a [PoolStringArray] filled with each constant's "
"name, for use in [method get_constant], if the theme has [code]theme_type[/"
"code]."
-msgstr "Ritorna [code]true[/code] se [code]s[/code] è zero o quasi zero."
+msgstr ""
+"Restituisce tutte le costanti come [PoolStringArray] carico dei nomi di ogni "
+"costante, per utilizzo in [method get_constant], se il tema contiene "
+"[code]theme_type[/code]."
#: doc/classes/Theme.xml
msgid ""
@@ -63105,11 +63217,12 @@ msgid ""
msgstr ""
#: doc/classes/Theme.xml
-#, fuzzy
msgid ""
"Returns all the [Font]s as a [PoolStringArray] filled with each [Font]'s "
"name, for use in [method get_font], if the theme has [code]theme_type[/code]."
-msgstr "Ritorna [code]true[/code] se [code]s[/code] è zero o quasi zero."
+msgstr ""
+"Restituisce i [Font]s come [PoolStringArray] carico con ogni [Font]'s nomi, "
+"per utilizzo in [method get_font], se il tema ha [code]theme_type[/code]."
#: doc/classes/Theme.xml
msgid ""
@@ -63125,11 +63238,13 @@ msgid ""
msgstr "Ritorna [code]true[/code] se [code]s[/code] è zero o quasi zero."
#: doc/classes/Theme.xml
-#, fuzzy
msgid ""
"Returns all the icons as a [PoolStringArray] filled with each [Texture]'s "
"name, for use in [method get_icon], if the theme has [code]theme_type[/code]."
-msgstr "Ritorna [code]true[/code] se [code]s[/code] è zero o quasi zero."
+msgstr ""
+"Restituisce tutte le icona come [PoolStringArray] cariche di ogni "
+"[Texture]'s nomi, per utilizzo in [method get_icon], se il tema contiene "
+"[code]theme_type[/code]."
#: doc/classes/Theme.xml
msgid ""
@@ -63202,83 +63317,87 @@ msgid ""
msgstr ""
#: doc/classes/Theme.xml
-#, fuzzy
msgid ""
"Returns a list of all type variations for the given [code]base_type[/code]."
-msgstr "Ritorna [code]true[/code] se [code]s[/code] è zero o quasi zero."
+msgstr ""
+"Restituisce una lista di tutti i tipi di variazioni per il dato "
+"[code]base_type[/code]."
#: doc/classes/Theme.xml
-#, fuzzy
msgid ""
"Returns [code]true[/code] if [Color] with [code]name[/code] is in "
"[code]theme_type[/code].\n"
"Returns [code]false[/code] if the theme does not have [code]theme_type[/"
"code]."
msgstr ""
-"Ritorna [code]true[/code] se l'impostazione specificata da [code]name[/code] "
-"esiste, [code]false[/code] altrimenti."
+"Restituisce [code]true[/code] se [Color] con [code]name[/code] è in "
+"[code]theme_type[/code].\n"
+"Restituisce [code]false[/code] se il tema non ha [code]theme_type[/code]."
#: doc/classes/Theme.xml
-#, fuzzy
msgid ""
"Returns [code]true[/code] if constant with [code]name[/code] is in "
"[code]theme_type[/code].\n"
"Returns [code]false[/code] if the theme does not have [code]theme_type[/"
"code]."
msgstr ""
-"Ritorna [code]true[/code] se l'impostazione specificata da [code]name[/code] "
-"esiste, [code]false[/code] altrimenti."
+"Restituisce [code]true[/code] se costante con [code]name[/code] è in "
+"[code]theme_type[/code].\n"
+"Restituisce [code]false[/code] se il tema non contiene [code]theme_type[/"
+"code]."
#: doc/classes/Theme.xml
-#, fuzzy
msgid ""
"Returns [code]true[/code] if this theme has a valid [member default_font] "
"value."
-msgstr "Ritorna [code]true[/code] se [code]s[/code] è zero o quasi zero."
+msgstr ""
+"Restituisce [code]true[/code] se questo tema ha un valido [member "
+"default_font] valore."
#: doc/classes/Theme.xml
-#, fuzzy
msgid ""
"Returns [code]true[/code] if [Font] with [code]name[/code] is in "
"[code]theme_type[/code].\n"
"Returns [code]false[/code] if the theme does not have [code]theme_type[/"
"code]."
msgstr ""
-"Ritorna [code]true[/code] se l'impostazione specificata da [code]name[/code] "
-"esiste, [code]false[/code] altrimenti."
+"Restituisce [code]true[/code] se [Font] con [code]name[/code] è in "
+"[code]theme_type[/code].\n"
+"Restituisce [code]false[/code] se il tema non contiene [code]theme_type[/"
+"code]."
#: doc/classes/Theme.xml
-#, fuzzy
msgid ""
"Returns [code]true[/code] if icon [Texture] with [code]name[/code] is in "
"[code]theme_type[/code].\n"
"Returns [code]false[/code] if the theme does not have [code]theme_type[/"
"code]."
msgstr ""
-"Ritorna [code]true[/code] se l'impostazione specificata da [code]name[/code] "
-"esiste, [code]false[/code] altrimenti."
+"Restituisce [code]true[/code] se l'icona [Texture] con [code]name[/code] è "
+"in [code]theme_type[/code].\n"
+"Restituisce [code]false[/code] se il tema non ha [code]theme_type[/code]."
#: doc/classes/Theme.xml
-#, fuzzy
msgid ""
"Returns [code]true[/code] if [StyleBox] with [code]name[/code] is in "
"[code]theme_type[/code].\n"
"Returns [code]false[/code] if the theme does not have [code]theme_type[/"
"code]."
msgstr ""
-"Ritorna [code]true[/code] se l'impostazione specificata da [code]name[/code] "
-"esiste, [code]false[/code] altrimenti."
+"Restituisce [code]true[/code] se [StyleBox] con [code]name[/code] è in "
+"[code]theme_type[/code].\n"
+"Restituisce [code]false[/code] se il tema non ha [code]theme_type[/code]."
#: doc/classes/Theme.xml
-#, fuzzy
msgid ""
"Returns [code]true[/code] if a theme item of [code]data_type[/code] with "
"[code]name[/code] is in [code]theme_type[/code].\n"
"Returns [code]false[/code] if the theme does not have [code]theme_type[/"
"code]."
msgstr ""
-"Ritorna [code]true[/code] se l'impostazione specificata da [code]name[/code] "
-"esiste, [code]false[/code] altrimenti."
+"Restituisce [code]true[/code] se un elemento del tema di [code]data_type[/"
+"code] con [code]name[/code] è in [code]theme_type[/code].\n"
+"Restituisce [code]false[/code] se il tema non ha [code]theme_type[/code]."
#: doc/classes/Theme.xml
#, fuzzy
@@ -63306,44 +63425,54 @@ msgid ""
msgstr ""
#: doc/classes/Theme.xml
-#, fuzzy
msgid ""
"Renames the [Color] at [code]old_name[/code] to [code]name[/code] if the "
"theme has [code]theme_type[/code]. If [code]name[/code] is already taken, "
"this method fails."
-msgstr "Ritorna [code]true[/code] se [code]s[/code] è zero o quasi zero."
+msgstr ""
+"Rinomina il [Color] da [code]old_name[/code] a [code]name[/code] se il tema "
+"ha [code]theme_type[/code]. Se [code]name[/code] è già occupato, questo "
+"metodo non può funzionare."
#: doc/classes/Theme.xml
-#, fuzzy
msgid ""
"Renames the constant at [code]old_name[/code] to [code]name[/code] if the "
"theme has [code]theme_type[/code]. If [code]name[/code] is already taken, "
"this method fails."
-msgstr "Ritorna [code]true[/code] se [code]s[/code] è zero o quasi zero."
+msgstr ""
+"Rinomina la costante da [code]old_name[/code] a [code]name[/code] se il tema "
+"ha [code]theme_type[/code]. Se [code]name[/code] è già occupato, questo "
+"metodo non può funzionare."
#: doc/classes/Theme.xml
-#, fuzzy
msgid ""
"Renames the [Font] at [code]old_name[/code] to [code]name[/code] if the "
"theme has [code]theme_type[/code]. If [code]name[/code] is already taken, "
"this method fails."
-msgstr "Ritorna [code]true[/code] se [code]s[/code] è zero o quasi zero."
+msgstr ""
+"Rinomina il [Font] da [code]old_name[/code] a [code]name[/code] se il tema "
+"ha [code]theme_type[/code]. Se [code]name[/code] è già occupato, questo "
+"metodo non può funzionare."
#: doc/classes/Theme.xml
-#, fuzzy
msgid ""
"Renames the icon at [code]old_name[/code] to [code]name[/code] if the theme "
"has [code]theme_type[/code]. If [code]name[/code] is already taken, this "
"method fails."
-msgstr "Ritorna [code]true[/code] se [code]s[/code] è zero o quasi zero."
+msgstr ""
+"Rinomina l'icona da [code]old_name[/code] a [code]name[/code] se il tema ha "
+"[code]theme_type[/code]. Se [code]name[/code] è già occupato, questo metodo "
+"non può funzionare."
#: doc/classes/Theme.xml
-#, fuzzy
msgid ""
"Renames [StyleBox] at [code]old_name[/code] to [code]name[/code] if the "
"theme has [code]theme_type[/code]. If [code]name[/code] is already taken, "
"this method fails."
-msgstr "Ritorna [code]true[/code] se [code]s[/code] è zero o quasi zero."
+msgstr ""
+"Rinomina [StyleBox] da [code]old_name[/code] a [code]name[/code] se il tema "
+"ha [code]theme_type[/code]. Se [code]name[/code] è già occupato, questo "
+"metodo non può funzionare."
#: doc/classes/Theme.xml
msgid ""
@@ -63353,57 +63482,56 @@ msgid ""
msgstr ""
#: doc/classes/Theme.xml
-#, fuzzy
msgid ""
"Sets the theme's [Color] to [code]color[/code] at [code]name[/code] in "
"[code]theme_type[/code].\n"
"Creates [code]theme_type[/code] if the theme does not have it."
msgstr ""
-"Ritorna [code]true[/code] se l'impostazione specificata da [code]name[/code] "
-"esiste, [code]false[/code] altrimenti."
+"Imposta il [Color] del tema da [code]color[/code] a [code]name[/code] in "
+"[code]theme_type[/code].\n"
+"Crea [code]theme_type[/code] se il tema non ce l'ha."
#: doc/classes/Theme.xml
-#, fuzzy
msgid ""
"Sets the theme's constant to [code]constant[/code] at [code]name[/code] in "
"[code]theme_type[/code].\n"
"Creates [code]theme_type[/code] if the theme does not have it."
msgstr ""
-"Ritorna [code]true[/code] se l'impostazione specificata da [code]name[/code] "
-"esiste, [code]false[/code] altrimenti."
+"Imposta la costante del tema da [code]constant[/code] a [code]name[/code] in "
+"[code]theme_type[/code].\n"
+"Crea [code]theme_type[/code]se il tema non ce l'ha."
#: doc/classes/Theme.xml
-#, fuzzy
msgid ""
"Sets the theme's [Font] to [code]font[/code] at [code]name[/code] in "
"[code]theme_type[/code].\n"
"Creates [code]theme_type[/code] if the theme does not have it."
msgstr ""
-"Ritorna [code]true[/code] se l'impostazione specificata da [code]name[/code] "
-"esiste, [code]false[/code] altrimenti."
+"Imposta il [Font] del tema da [code]font[/code] a [code]name[/code] in "
+"[code]theme_type[/code].\n"
+"Crea [code]theme_type[/code] se il tema non ce l'ha."
#: doc/classes/Theme.xml
-#, fuzzy
msgid ""
"Sets the theme's icon [Texture] to [code]texture[/code] at [code]name[/code] "
"in [code]theme_type[/code].\n"
"Creates [code]theme_type[/code] if the theme does not have it."
msgstr ""
-"Ritorna [code]true[/code] se l'impostazione specificata da [code]name[/code] "
-"esiste, [code]false[/code] altrimenti."
+"Imposta l'icona del tema [Texture] da [code]texture[/code] a [code]name[/"
+"code] in [code]theme_type[/code].\n"
+"Crea [code]theme_type[/code] se il tema non ce l'ha."
#: doc/classes/Theme.xml
-#, fuzzy
msgid ""
"Sets theme's [StyleBox] to [code]stylebox[/code] at [code]name[/code] in "
"[code]theme_type[/code].\n"
"Creates [code]theme_type[/code] if the theme does not have it."
msgstr ""
-"Ritorna [code]true[/code] se l'impostazione specificata da [code]name[/code] "
-"esiste, [code]false[/code] altrimenti."
+"Imposta lo [StyleBox] del tema da [code]stylebox[/code] a [code]name[/code] "
+"in [code]theme_type[/code].\n"
+"Crea [code]theme_type[/code] se il tema non ce l'ha."
#: doc/classes/Theme.xml
-#, fuzzy
msgid ""
"Sets the theme item of [code]data_type[/code] to [code]value[/code] at "
"[code]name[/code] in [code]theme_type[/code].\n"
@@ -63411,8 +63539,11 @@ msgid ""
"code].\n"
"Creates [code]theme_type[/code] if the theme does not have it."
msgstr ""
-"Ritorna [code]true[/code] se l'impostazione specificata da [code]name[/code] "
-"esiste, [code]false[/code] altrimenti."
+"Imposta l'elemento del tema di [code]data_type[/code] da [code]value[/code] "
+"a [code]name[/code] in [code]theme_type[/code].\n"
+"Non funziona se il modello [code]value[/code] non combacia con "
+"[code]data_type[/code].\n"
+"Crea [code]theme_type[/code] se il tema non ce l'ha."
#: doc/classes/Theme.xml
msgid ""
@@ -65695,9 +65826,8 @@ msgid ""
msgstr "Ritorna [code]true[/code] se [code]s[/code] è zero o quasi zero."
#: doc/classes/TreeItem.xml
-#, fuzzy
msgid "Returns the number of buttons in column [code]column[/code]."
-msgstr "Ritorna [code]true[/code] se [code]s[/code] è zero o quasi zero."
+msgstr "Restituisce il numero dei tasti in colonna [code]column[/code]."
#: doc/classes/TreeItem.xml
#, fuzzy
@@ -67300,12 +67430,12 @@ msgid ""
msgstr ""
#: doc/classes/Vector2.xml doc/classes/Vector3.xml
-#, fuzzy
msgid ""
"Returns [code]true[/code] if the vector is normalized, [code]false[/code] "
"otherwise."
msgstr ""
-"Ritorna [code]true[/code] se il vettore è normalizzato, o falso altrimenti."
+"Restituisce [code]true[/code] se il vettore è normalizzato, [code]false[/"
+"code] altrimenti."
#: doc/classes/Vector2.xml doc/classes/Vector3.xml
msgid "Returns the length (magnitude) of this vector."
@@ -67332,13 +67462,12 @@ msgid ""
msgstr ""
#: doc/classes/Vector2.xml doc/classes/Vector3.xml
-#, fuzzy
msgid ""
"Returns a new vector moved toward [code]to[/code] by the fixed [code]delta[/"
"code] amount. Will not go past the final value."
msgstr ""
-"Restituisce [code]true[/code] se [code]a[/code] e [code]b[/code] sono "
-"approssimativamente uguali tra di loro."
+"Restituisce un nuovo vettore mosso verso [code]to[/code] da una quantità "
+"fissa [code]delta[/code]. Non va oltre il valore finale."
#: doc/classes/Vector2.xml doc/classes/Vector3.xml
msgid ""
@@ -68226,10 +68355,15 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
"If [code]true[/code], uses a fast post-processing filter to make banding "
-"significantly less visible. In some cases, debanding may introduce a "
-"slightly noticeable dithering pattern. It's recommended to enable debanding "
-"only when actually needed since the dithering pattern will make lossless-"
-"compressed screenshots larger.\n"
+"significantly less visible in 3D. 2D rendering is [i]not[/i] affected by "
+"debanding unless the [member Environment.background_mode] is [constant "
+"Environment.BG_CANVAS]. In this case, [member usage] must also be set to "
+"[constant USAGE_3D]. See also [member ProjectSettings.rendering/quality/"
+"filters/use_debanding].\n"
+"In some cases, debanding may introduce a slightly noticeable dithering "
+"pattern. It's recommended to enable debanding only when actually needed "
+"since the dithering pattern will make lossless-compressed screenshots "
+"larger.\n"
"[b]Note:[/b] Only available on the GLES3 backend. [member hdr] must also be "
"[code]true[/code] for debanding to be effective."
msgstr ""
@@ -68240,8 +68374,8 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
-"If [code]true[/code], the viewport will disable 3D rendering. For actual "
-"disabling use [code]usage[/code]."
+"If [code]true[/code], the viewport will disable 3D rendering. To actually "
+"disable allocation of 3D buffers, set [member usage] instead."
msgstr ""
#: doc/classes/Viewport.xml
@@ -68305,11 +68439,12 @@ msgid ""
msgstr ""
#: doc/classes/Viewport.xml
-#, fuzzy
msgid ""
"If [code]true[/code], the viewport will use a unique copy of the [World] "
"defined in [member world]."
-msgstr "Ritorna [code]true[/code] se [code]s[/code] è zero o quasi zero."
+msgstr ""
+"Se [code]true[/code], il viewport utilizzerà una copia unica del [World] "
+"definito in [member world]."
#: doc/classes/Viewport.xml
msgid ""
@@ -68399,7 +68534,9 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
-"The rendering mode of viewport.\n"
+"The viewport's rendering mode. This controls which buffers are allocated for "
+"the viewport (2D only, or 2D + 3D). 2D-only options can reduce memory usage "
+"and improve performance slightly, especially on low-end devices.\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."
@@ -68931,6 +69068,22 @@ msgid ""
"render object this [VisualInstance] is set to."
msgstr ""
+#: doc/classes/VisualInstance.xml
+msgid ""
+"The sorting offset used by this [VisualInstance]. Adjusting it to a higher "
+"value will make the [VisualInstance] reliably draw on top of other "
+"[VisualInstance]s that are otherwise positioned at the same spot."
+msgstr ""
+
+#: doc/classes/VisualInstance.xml
+msgid ""
+"If [code]true[/code], the object is sorted based on the [AABB] center. "
+"Sorted based on the global position otherwise.\n"
+"The [AABB] center based sorting is generally more accurate for 3D models. "
+"The position based sorting instead allows to better control the drawing "
+"order when working with [Particles] and [CPUParticles]."
+msgstr ""
+
#: modules/visual_script/doc_classes/VisualScript.xml
msgid "A script implemented in the Visual Script programming environment."
msgstr ""
@@ -70125,7 +70278,6 @@ msgid "Pi divided by two: [code]1.570796[/code]."
msgstr ""
#: modules/visual_script/doc_classes/VisualScriptMathConstant.xml
-#, fuzzy
msgid "Tau: [code]6.283185[/code]."
msgstr "Tau: [code]6.283185[/code]."
@@ -70140,9 +70292,8 @@ msgid "Square root of two: [code]1.414214[/code]."
msgstr ""
#: modules/visual_script/doc_classes/VisualScriptMathConstant.xml
-#, fuzzy
msgid "Infinity: [code]inf[/code]."
-msgstr "Infinito: [code]inf[/code]."
+msgstr "Infinità: [code]inf[/code]."
#: modules/visual_script/doc_classes/VisualScriptMathConstant.xml
msgid "Not a number: [code]nan[/code]."
@@ -71887,11 +72038,12 @@ msgid "Returns the value of a certain material's parameter."
msgstr ""
#: doc/classes/VisualServer.xml
-#, fuzzy
msgid ""
"Returns the default value for the param if available. Returns [code]null[/"
"code] otherwise."
-msgstr "Ritorna [code]true[/code] se [code]s[/code] è zero o quasi zero."
+msgstr ""
+"Restituisce il valore predefinito per il parametro, se disponibile. "
+"Altrimenti restituisce [code]null[/code]."
#: doc/classes/VisualServer.xml
msgid ""
@@ -76974,19 +77126,21 @@ msgid ""
"Gets the value of the attribute specified by the index in [code]idx[/code] "
"argument."
msgstr ""
-"Prende il nome dell'attributo specificato dall'indice nell'argomento "
+"Prende il valore dell'attributo specificato dall'indice nell'argomento "
"[code]idx[/code]."
#: doc/classes/XMLParser.xml
-#, fuzzy
msgid "Gets the current line in the parsed file (currently not implemented)."
-msgstr "Prende la linea corrente nel file analizzato (non ancora implementato)"
+msgstr ""
+"Prende la linea corrente nel file analizzato (non ancora implementato)."
#: doc/classes/XMLParser.xml
msgid ""
"Gets the value of a certain attribute of the current element by name. This "
"will raise an error if the element has no such attribute."
msgstr ""
+"Prende il valore di un certo attributo dell'elemento corrente usando il "
+"nome. Questo darà errore se l'elemento non ha tale attributo."
#: doc/classes/XMLParser.xml
msgid ""
@@ -77061,13 +77215,12 @@ msgstr ""
"legge il nodo seguente. Questo ritorna un codice errore."
#: doc/classes/XMLParser.xml
-#, fuzzy
msgid ""
"Skips the current section. If the node contains other elements, they will be "
"ignored and the cursor will go to the closing of the current element."
msgstr ""
"Salta la sezione corrente. Se il nodo contiene altri elementi, questi "
-"saranno ignorati e il cursore andrà alla chiusura dell'elemento corrente"
+"saranno ignorati e il cursore andrà alla chiusura dell'elemento corrente."
#: doc/classes/XMLParser.xml
#, fuzzy
diff --git a/doc/translations/ja.po b/doc/translations/ja.po
index f5217e9b83..cabf1da54a 100644
--- a/doc/translations/ja.po
+++ b/doc/translations/ja.po
@@ -12,12 +12,13 @@
# Tarou Yamada <mizuningyou@yahoo.co.jp>, 2021.
# sugusan <sugusan.development@gmail.com>, 2022.
# Juto <mvobujd237@gmail.com>, 2022.
+# ta ko <neji.cion@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-02-14 22:08+0000\n"
-"Last-Translator: Wataru Onuki <bettawat@yahoo.co.jp>\n"
+"PO-Revision-Date: 2022-11-21 00:47+0000\n"
+"Last-Translator: ta ko <neji.cion@gmail.com>\n"
"Language-Team: Japanese <https://hosted.weblate.org/projects/godot-engine/"
"godot-class-reference/ja/>\n"
"Language: ja\n"
@@ -25,7 +26,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.11-dev\n"
+"X-Generator: Weblate 4.15-dev\n"
#: doc/tools/make_rst.py
msgid "Description"
@@ -713,8 +714,10 @@ msgstr ""
"[/codeblock]"
#: modules/gdscript/doc_classes/@GDScript.xml
+#, fuzzy
msgid ""
-"Returns an array of dictionaries representing the current call stack.\n"
+"Returns an array of dictionaries representing the current call stack. See "
+"also [method print_stack].\n"
"[codeblock]\n"
"func _ready():\n"
" foo()\n"
@@ -729,7 +732,11 @@ msgid ""
"[codeblock]\n"
"[{function:bar, line:12, source:res://script.gd}, {function:foo, line:9, "
"source:res://script.gd}, {function:_ready, line:6, source:res://script.gd}]\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] [method get_stack] only works if the running instance is "
+"connected to a debugging server (i.e. an editor instance). [method "
+"get_stack] will not work in projects exported in release mode, or in "
+"projects exported in debug mode if not connected to a debugging server."
msgstr ""
"ç¾åœ¨ã®ã‚³ãƒ¼ãƒ«ã‚¹ã‚¿ãƒƒã‚¯ã‚’辞書ã®é…列ã¨ã—ã¦è¿”ã—ã¾ã™ã€‚\n"
"[codeblock]\n"
@@ -1358,19 +1365,17 @@ msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
-"Prints a stack track at code location, only works when running with debugger "
-"turned on.\n"
+"Prints a stack trace at the current code location. See also [method "
+"get_stack].\n"
"Output in the console would look something like this:\n"
"[codeblock]\n"
"Frame 0 - res://test.gd:16 in function '_process'\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] [method print_stack] only works if the running instance is "
+"connected to a debugging server (i.e. an editor instance). [method "
+"print_stack] will not work in projects exported in release mode, or in "
+"projects exported in debug mode if not connected to a debugging server."
msgstr ""
-"コードä½ç½®ã®ã‚¹ã‚¿ãƒƒã‚¯ãƒˆãƒ©ãƒƒã‚¯ã‚’表示ã—ã¾ã™ã€‚デãƒãƒƒã‚¬ã‚’有効ã«ã—ã¦å®Ÿè¡Œã—ãŸæ™‚ã«ã®"
-"ã¿å‹•作ã—ã¾ã™ã€‚\n"
-"コンソール内ã§ã®å‡ºåŠ›ã¯ã“ã®ã‚ˆã†ã«ãªã‚Šã¾ã™:\n"
-"[codeblock]\n"
-"Frame 0 - res://test.gd:16 in function '_process'\n"
-"[/codeblock]"
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
@@ -1600,6 +1605,41 @@ msgid ""
"3\n"
"[/codeblock]"
msgstr ""
+":指定ã•れãŸç¯„囲ã®é…列を返ã—ã¾ã™ã€‚[method range] ã¯3ã¤ã®æ–¹æ³•ã§å‘¼ã³å‡ºã™ã“ã¨ãŒã§"
+"ãã¾ã™ã€‚\n"
+"[code]range(n: int)[/code]:0ã‹ã‚‰å§‹ã¾ã‚Šã€1ãšã¤å¢—加ã—ã€[code]n[/code]ã®[i]å‰ [/"
+"i] ã§åœæ­¢ã—ã€å¼•æ•°[code]n[/code]ã¯[b]å«ã¾ã‚Œã¾ã›ã‚“[/b]。[i]\n"
+"[code]range(b: int, n: int)[/code]:[code]b[/code]ã‹ã‚‰å§‹ã¾ã‚Šã€1ãšã¤å¢—加ã—ã€"
+"[code]n[/code]ã® [i] å‰ [/i] ã§åœæ­¢ã—ã¾ã™ã€‚引数 [code]b[/code] 㯠[b] å«ã¾ã‚Œ"
+"ã¾ã™[/b] ãŒã€ [code]n[/code] 㯠[b]å«ã¾ã‚Œã¾ã›ã‚“[/b] 。\n"
+"[code]range(b: int, n: int, s: int)[/code]:[code]b[/code]ã‹ã‚‰å§‹ã¾ã‚Šã€"
+"[code]s[/code]ã®ã‚¹ãƒ†ãƒƒãƒ—ã§å¢—加/減少ã—ã€[code]n[/code]ã®[i]å‰ [/i] ã§åœæ­¢ã—ã¾"
+"ã™ã€‚引数 [code]b[/code] 㯠[b] å«ã¾ã‚Œã¾ã™[/b] ãŒã€ [code]n[/code] 㯠[b]å«ã¾"
+"れã¾ã›ã‚“[/b] 。。引数 [code]s[/code] [b]can[/b] ã¯è² ã®å€¤ã‚’指定ã§ãã¾ã™ãŒã€"
+"[code]0[/code] ã¯æŒ‡å®šã§ãã¾ã›ã‚“。[code]s[/code] ㌠[code]0[/code] ã®å ´åˆã€ã‚¨"
+"ラーメッセージãŒå‡ºåŠ›ã•れã¾ã™ã€‚\n"
+"[method range]ã¯ã€å‡¦ç†å‰ã«ã™ã¹ã¦ã®å¼•æ•°ã‚’[int]ã«å¤‰æ›ã—ã¾ã™\n"
+"[b]注:[/b] 値ã®åˆ¶ç´„を満ãŸã™å€¤ãŒãªã„å ´åˆã€ç©ºã®é…列を返ã—ã¾ã™ã€‚(例:"
+"[code]range(2, 5, -1)[/code] ã¾ãŸã¯ [code]range(5, 5, 1)[/code])\n"
+"Examples:\n"
+"[codeblock]\n"
+"print(range(4)) # [0, 1, 2, 3]ã¨å‡ºåŠ›ã™ã‚‹\n"
+"print(range(2, 5)) # [2, 3, 4]ã¨å‡ºåŠ›ã™ã‚‹\n"
+"print(range(0, 6, 2)) # [0, 2, 4]ã¨å‡ºåŠ›ã™ã‚‹\n"
+"print(range(4, 1, -1)) # [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"
+"Output:\n"
+"[codeblock]\n"
+"9\n"
+"6\n"
+"3\n"
+"[/codeblock]"
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
@@ -4465,6 +4505,26 @@ msgid "Hints that an image is compressed using lossless compression."
msgstr "ç”»åƒã¯ãƒ­ã‚¹ãƒ¬ã‚¹åœ§ç¸®ã«ã‚ˆã‚Šåœ§ç¸®ã•れã¦ã„ã‚‹ã¨ã„ã†ãƒ’ント。"
#: doc/classes/@GlobalScope.xml
+msgid ""
+"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:\n"
+"[codeblock]\n"
+"hint_string = \"%s:\" % [TYPE_INT] # Array of inteters.\n"
+"hint_string = \"%s:%s:\" % [TYPE_ARRAY, TYPE_REAL] # Two-dimensional array "
+"of floats.\n"
+"hint_string = \"%s/%s:Resource\" % [TYPE_OBJECT, TYPE_OBJECT] # Array of "
+"resources.\n"
+"hint_string = \"%s:%s/%s:Resource\" % [TYPE_ARRAY, TYPE_OBJECT, TYPE_OBJECT] "
+"# Two-dimensional array of resources.\n"
+"[/codeblock]\n"
+"[b]Note:[/b] The final colon is required to specify for properly detecting "
+"built-in types."
+msgstr ""
+
+#: doc/classes/@GlobalScope.xml
msgid "The property is serialized and saved in the scene file (default)."
msgstr ""
"プロパティã¯ã‚·ãƒªã‚¢ãƒ©ã‚¤ã‚ºã•れã€ã‚·ãƒ¼ãƒ³ãƒ•ァイルã«ä¿å­˜ã•れã¾ã™ (デフォルト) 。"
@@ -5298,8 +5358,7 @@ msgstr ""
#: doc/classes/AudioStreamPlayer.xml doc/classes/Button.xml
#: doc/classes/CanvasLayer.xml doc/classes/CollisionShape2D.xml
#: doc/classes/ColorRect.xml doc/classes/Input.xml doc/classes/InputEvent.xml
-#: doc/classes/InputEventAction.xml doc/classes/Label.xml
-#: doc/classes/Particles2D.xml doc/classes/Timer.xml
+#: doc/classes/InputEventAction.xml doc/classes/Label.xml doc/classes/Timer.xml
#: doc/classes/VisibilityNotifier2D.xml
msgid "2D Dodge The Creeps Demo"
msgstr ""
@@ -9145,7 +9204,10 @@ msgid ""
"var array = []\n"
"array.resize(10)\n"
"array.fill(0) # Initialize the 10 elements to 0.\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] If [code]value[/code] is of a reference type ([Object]-derived, "
+"[Array], [Dictionary], etc.) then the array is filled with the references to "
+"the same object, i.e. no duplicates are created."
msgstr ""
#: doc/classes/Array.xml doc/classes/PoolByteArray.xml
@@ -9370,8 +9432,12 @@ msgstr ""
"[code]step[/code]ã¯ã‚¹ãƒ©ã‚¤ã‚¹ä¸­ã®ã‚¤ãƒ³ãƒ‡ãƒƒã‚¯ã‚¹é–“ã®å¤‰åŒ–を表ã—ã¾ã™ã€‚"
#: doc/classes/Array.xml
+#, fuzzy
msgid ""
"Sorts the array.\n"
+"[b]Note:[/b] The sorting algorithm used is not [url=https://en.wikipedia.org/"
+"wiki/Sorting_algorithm#Stability]stable[/url]. This means that values "
+"considered equal may have their order changed when using [method sort].\n"
"[b]Note:[/b] Strings are sorted in alphabetical order (as opposed to natural "
"order). This may lead to unexpected behavior when sorting an array of "
"strings ending with a sequence of numbers. Consider the following example:\n"
@@ -9401,9 +9467,13 @@ msgid ""
"For two elements [code]a[/code] and [code]b[/code], if the given method "
"returns [code]true[/code], element [code]b[/code] will be after element "
"[code]a[/code] in the array.\n"
+"[b]Note:[/b] The sorting algorithm used is not [url=https://en.wikipedia.org/"
+"wiki/Sorting_algorithm#Stability]stable[/url]. This means that values "
+"considered equal may have their order changed when using [method "
+"sort_custom].\n"
"[b]Note:[/b] You cannot randomize the return value as the heapsort algorithm "
-"expects a deterministic result. Doing so will result in unexpected "
-"behavior.\n"
+"expects a deterministic result. Randomizing the return value will result in "
+"unexpected behavior.\n"
"[codeblock]\n"
"class MyCustomSorter:\n"
" static func sort_ascending(a, b):\n"
@@ -12624,12 +12694,14 @@ msgid "Clears the audio sample data buffer."
msgstr "byteã§æ ¼ç´ã•れãŸã‚ªãƒ¼ãƒ‡ã‚£ã‚ªãƒ‡ãƒ¼ã‚¿ã§ã™ã€‚"
#: doc/classes/AudioStreamGeneratorPlayback.xml
+#, fuzzy
msgid ""
-"Returns the number of audio data frames left to play. If this returned "
-"number reaches [code]0[/code], the audio will stop playing until frames are "
-"added again. Therefore, make sure your script can always generate and push "
-"new audio frames fast enough to avoid audio cracking."
+"Returns the number of frames that can be pushed to the audio sample data "
+"buffer without overflowing it. If the result is [code]0[/code], the buffer "
+"is full."
msgstr ""
+"[code]name[/code] ã¨ã„ã†åå‰ã§æŒ‡å®šã—ãŸè¨­å®šãŒå­˜åœ¨ã™ã‚‹å ´åˆã¯ [code]true[/"
+"code]ã€ãã†ã§ãªã„å ´åˆã¯ [code]false[/code] ã‚’è¿”ã—ã¾ã™ã€‚"
#: doc/classes/AudioStreamGeneratorPlayback.xml
msgid ""
@@ -13234,14 +13306,14 @@ msgstr ""
#, fuzzy
msgid ""
"Node for back-buffering the currently-displayed screen. The region defined "
-"in the BackBufferCopy node is buffered with the content of the screen it "
+"in the [BackBufferCopy] node is buffered with the content of the screen it "
"covers, or the entire screen according to the copy mode set. Use the "
"[code]texture(SCREEN_TEXTURE, ...)[/code] function in your shader scripts to "
"access the buffer.\n"
"[b]Note:[/b] Since this node inherits from [Node2D] (and not [Control]), "
"anchors and margins won't apply to child [Control]-derived nodes. This can "
"be problematic when resizing the window. To avoid this, add [Control]-"
-"derived nodes as [i]siblings[/i] to the BackBufferCopy node instead of "
+"derived nodes as [i]siblings[/i] to the [BackBufferCopy] node instead of "
"adding them as children."
msgstr ""
"ç¾åœ¨è¡¨ç¤ºã•れã¦ã„ã‚‹ç”»é¢ã‚’ãƒãƒƒã‚¯ãƒãƒƒãƒ•ァリングã™ã‚‹ãŸã‚ã®ãƒŽãƒ¼ãƒ‰ã€‚BackBufferCopy "
@@ -13260,27 +13332,31 @@ msgid "Buffer mode. See [enum CopyMode] constants."
msgstr "ãƒãƒƒãƒ•ァモード。 [enum CopyMode]定数をå‚ç…§ã—ã¦ãã ã•ã„。"
#: doc/classes/BackBufferCopy.xml
+#, fuzzy
msgid ""
-"The area covered by the BackBufferCopy. Only used if [member copy_mode] is "
+"The area covered by the [BackBufferCopy]. Only used if [member copy_mode] is "
"[constant COPY_MODE_RECT]."
msgstr ""
"BackBufferCopyã§ã‚«ãƒãƒ¼ã•れる領域。 [member copy_mode]ãŒ[constant "
"COPY_MODE_RECT]ã®å ´åˆã«ã®ã¿ä½¿ç”¨ã•れã¾ã™ã€‚"
#: doc/classes/BackBufferCopy.xml
+#, fuzzy
msgid ""
-"Disables the buffering mode. This means the BackBufferCopy node will "
+"Disables the buffering mode. This means the [BackBufferCopy] node will "
"directly use the portion of screen it covers."
msgstr ""
"ãƒãƒƒãƒ•ァリング モードを無効ã«ã—ã¾ã™ã€‚ã¤ã¾ã‚Šã€BackBufferCopy ノードã¯ã€ã‚«ãƒãƒ¼"
"ã™ã‚‹ç”»é¢ã®éƒ¨åˆ†ã‚’直接使用ã—ã¾ã™ã€‚"
#: doc/classes/BackBufferCopy.xml
-msgid "BackBufferCopy buffers a rectangular region."
+#, fuzzy
+msgid "[BackBufferCopy] buffers a rectangular region."
msgstr "BackBufferCopyã¯çŸ©å½¢é ˜åŸŸã‚’ãƒãƒƒãƒ•ァリングã—ã¾ã™ã€‚"
#: doc/classes/BackBufferCopy.xml
-msgid "BackBufferCopy buffers the entire screen."
+#, fuzzy
+msgid "[BackBufferCopy] buffers the entire screen."
msgstr "BackBufferCopy ã¯ç”»é¢å…¨ä½“ã‚’ãƒãƒƒãƒ•ァリングã—ã¾ã™ã€‚"
#: doc/classes/BakedLightmap.xml
@@ -22403,6 +22479,14 @@ msgid "Cylinder shape for collisions."
msgstr ""
#: doc/classes/CylinderShape.xml
+msgid ""
+"Cylinder shape for collisions.\n"
+"[b]Note:[/b] When using GodotPhysics instead of the default Bullet physics "
+"engine, there are several known bugs with cylinder collision shapes. Using "
+"[CapsuleShape] or [BoxShape] instead is recommended."
+msgstr ""
+
+#: doc/classes/CylinderShape.xml
msgid "The cylinder's height."
msgstr ""
@@ -25251,7 +25335,10 @@ msgid ""
"[/codeblock]\n"
"[b]Note:[/b] The script is run in the Editor context, which means the output "
"is visible in the console window started with the Editor (stdout) instead of "
-"the usual Godot [b]Output[/b] dock."
+"the usual Godot [b]Output[/b] dock.\n"
+"[b]Note:[/b] EditorScript is reference counted, meaning it is destroyed when "
+"nothing references it. This can cause errors during asynchronous operations "
+"if there are no references to the script."
msgstr ""
#: doc/classes/EditorScript.xml
@@ -36132,7 +36219,9 @@ msgid ""
"The size of the light in Godot units. Only considered in baked lightmaps and "
"only if [member light_bake_mode] is set to [constant BAKE_ALL]. Increasing "
"this value will make the shadows appear blurrier. This can be used to "
-"simulate area lights to an extent."
+"simulate area lights to an extent.\n"
+"[b]Note:[/b] [member light_size] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/Light.xml
@@ -39500,7 +39589,10 @@ msgid ""
"use the [method get_next_location] function once every physics frame to "
"update the internal path logic of the NavigationAgent. The returned vector "
"position from this function should be used as the next movement position for "
-"the agent's parent Node."
+"the agent's parent Node.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues."
msgstr ""
#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
@@ -39757,7 +39849,10 @@ msgid ""
"use the [method get_next_location] function once every physics frame to "
"update the internal path logic of the NavigationAgent. The returned vector "
"position from this function should be used as the next movement position for "
-"the agent's parent Node."
+"the agent's parent Node.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues."
msgstr ""
#: doc/classes/NavigationAgent2D.xml
@@ -40489,6 +40584,9 @@ msgid ""
"modified velocity as-is might lead to pushing and agent outside of a "
"navigable area. This is a limitation of the collision avoidance system, any "
"more complex situation may require the use of the physics engine.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues.\n"
"This server keeps tracks of any call and executes them during the sync "
"phase. This means that you can request any change to the map, using any "
"thread, without worrying."
@@ -43312,7 +43410,9 @@ msgid ""
"The light's radius. Note that the effectively lit area may appear to be "
"smaller depending on the [member omni_attenuation] in use. No matter the "
"[member omni_attenuation] in use, the light will never reach anything "
-"outside this radius."
+"outside this radius.\n"
+"[b]Note:[/b] [member omni_range] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -43832,11 +43932,11 @@ msgstr "指定ã•れãŸåå‰ã®ã‚¢ãƒ‹ãƒ¡ãƒ¼ã‚·ãƒ§ãƒ³ãƒŽãƒ¼ãƒ‰ã‚’è¿”ã—ã¾ã™ã€‚
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] cache data directory according to the operating "
-"system's standards. On desktop platforms, this path can be overridden by "
-"setting the [code]XDG_CACHE_HOME[/code] environment variable before starting "
-"the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in "
-"Godot projects[/url] in the documentation for more information. See also "
-"[method get_config_dir] and [method get_data_dir].\n"
+"system's standards. On Linux, this path can be overridden by setting the "
+"[code]XDG_CACHE_HOME[/code] environment variable before starting the "
+"project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot "
+"projects[/url] in the documentation for more information. See also [method "
+"get_config_dir] and [method get_data_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -43870,11 +43970,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] user configuration directory according to the "
-"operating system's standards. On desktop platforms, this path can be "
-"overridden by setting the [code]XDG_CONFIG_HOME[/code] environment variable "
-"before starting the project. See [url=$DOCS_URL/tutorials/io/data_paths."
-"html]File paths in Godot projects[/url] in the documentation for more "
-"information. See also [method get_cache_dir] and [method get_data_dir].\n"
+"operating system's standards. On Linux, this path can be overridden by "
+"setting the [code]XDG_CONFIG_HOME[/code] environment variable before "
+"starting the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File "
+"paths in Godot projects[/url] in the documentation for more information. See "
+"also [method get_cache_dir] and [method get_data_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -43896,11 +43996,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] user data directory according to the operating "
-"system's standards. On desktop platforms, this path can be overridden by "
-"setting the [code]XDG_DATA_HOME[/code] environment variable before starting "
-"the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in "
-"Godot projects[/url] in the documentation for more information. See also "
-"[method get_cache_dir] and [method get_config_dir].\n"
+"system's standards. On Linux, this path can be overridden by setting the "
+"[code]XDG_DATA_HOME[/code] environment variable before starting the project. "
+"See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot "
+"projects[/url] in the documentation for more information. See also [method "
+"get_cache_dir] and [method get_config_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -45792,6 +45892,16 @@ msgid "Particle systems (2D)"
msgstr ""
#: doc/classes/Particles2D.xml
+msgid "2D Particles Demo"
+msgstr ""
+
+#: doc/classes/Particles2D.xml
+msgid ""
+"2D Dodge The Creeps Demo (uses GPUParticles2D for the trail behind the "
+"player)"
+msgstr ""
+
+#: doc/classes/Particles2D.xml
msgid "Returns a rectangle containing the positions of all existing particles."
msgstr ""
@@ -53439,15 +53549,22 @@ msgstr ""
#: doc/classes/ProjectSettings.xml
msgid ""
"If [code]true[/code], uses a fast post-processing filter to make banding "
-"significantly less visible. In some cases, debanding may introduce a "
-"slightly noticeable dithering pattern. It's recommended to enable debanding "
-"only when actually needed since the dithering pattern will make lossless-"
-"compressed screenshots larger.\n"
+"significantly less visible in 3D. 2D rendering is [i]not[/i] affected by "
+"debanding unless the [member Environment.background_mode] is [constant "
+"Environment.BG_CANVAS]. In this case, [member rendering/quality/"
+"intended_usage/framebuffer_allocation] must also be set to [b]3D[/b].\n"
+"In some cases, debanding may introduce a slightly noticeable dithering "
+"pattern. It's recommended to enable debanding only when actually needed "
+"since the dithering pattern will make lossless-compressed screenshots "
+"larger.\n"
"[b]Note:[/b] Only available on the GLES3 backend. [member rendering/quality/"
"depth/hdr] must also be [code]true[/code] for debanding to be effective.\n"
"[b]Note:[/b] There are known issues with debanding breaking rendering on "
"mobile platforms. Due to this, it is recommended to leave this option "
-"disabled when targeting mobile platforms."
+"disabled when targeting mobile platforms.\n"
+"[b]Note:[/b] This property is only read when the project starts. To set "
+"debanding at run-time, set [member Viewport.debanding] on the root "
+"[Viewport] instead."
msgstr ""
#: doc/classes/ProjectSettings.xml
@@ -55065,17 +55182,28 @@ msgstr ""
#: modules/regex/doc_classes/RegEx.xml
msgid ""
"Searches the text for the compiled pattern. Returns a [RegExMatch] container "
-"of the first matching result if found, otherwise [code]null[/code]. The "
-"region to search within can be specified without modifying where the start "
-"and end anchor would be."
+"of the first matching result if found, otherwise [code]null[/code].\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegEx.xml
msgid ""
"Searches the text for the compiled pattern. Returns an array of [RegExMatch] "
"containers for each non-overlapping result. If no results were found, an "
-"empty array is returned instead. The region to search within can be "
-"specified without modifying where the start and end anchor would be."
+"empty array is returned instead.\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegEx.xml
@@ -55084,8 +55212,14 @@ msgid ""
"specified string. Escapes and backreferences such as [code]$1[/code] and "
"[code]$name[/code] are expanded and resolved. By default, only the first "
"instance is replaced, but it can be changed for all instances (global "
-"replacement). The region to search within can be specified without modifying "
-"where the start and end anchor would be."
+"replacement).\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegExMatch.xml
@@ -57829,7 +57963,11 @@ msgid "Call a group immediately (calls are normally made on idle)."
msgstr ""
#: doc/classes/SceneTree.xml
-msgid "Call a group only once even if the call is executed many times."
+msgid ""
+"Call a group only once even if the call is executed many times.\n"
+"[b]Note:[/b] Arguments are not taken into account when deciding whether the "
+"call is unique or not. Therefore when the same method is called with "
+"different arguments, only the first call will be performed."
msgstr ""
#: doc/classes/SceneTree.xml
@@ -59676,7 +59814,9 @@ msgid ""
"[b]Note:[/b] Mixed negative scales in 3D are not decomposable from the "
"transformation matrix. Due to the way scale is represented with "
"transformation matrices in Godot, the scale values will either be all "
-"positive or all negative."
+"positive or all negative.\n"
+"[b]Note:[/b] Not all nodes are visually scaled by the [member scale] "
+"property. For example, [Light]s are not visually affected by [member scale]."
msgstr ""
#: doc/classes/Spatial.xml
@@ -61322,7 +61462,10 @@ msgid ""
msgstr ""
#: doc/classes/SpotLight.xml
-msgid "The spotlight's angle in degrees."
+msgid ""
+"The spotlight's angle in degrees.\n"
+"[b]Note:[/b] [member spot_angle] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/SpotLight.xml
@@ -61338,7 +61481,9 @@ msgid ""
"The maximal range that can be reached by the spotlight. Note that the "
"effectively lit area may appear to be smaller depending on the [member "
"spot_attenuation] in use. No matter the [member spot_attenuation] in use, "
-"the light will never reach anything outside this range."
+"the light will never reach anything outside this range.\n"
+"[b]Note:[/b] [member spot_range] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/SpringArm.xml
@@ -70808,10 +70953,15 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
"If [code]true[/code], uses a fast post-processing filter to make banding "
-"significantly less visible. In some cases, debanding may introduce a "
-"slightly noticeable dithering pattern. It's recommended to enable debanding "
-"only when actually needed since the dithering pattern will make lossless-"
-"compressed screenshots larger.\n"
+"significantly less visible in 3D. 2D rendering is [i]not[/i] affected by "
+"debanding unless the [member Environment.background_mode] is [constant "
+"Environment.BG_CANVAS]. In this case, [member usage] must also be set to "
+"[constant USAGE_3D]. See also [member ProjectSettings.rendering/quality/"
+"filters/use_debanding].\n"
+"In some cases, debanding may introduce a slightly noticeable dithering "
+"pattern. It's recommended to enable debanding only when actually needed "
+"since the dithering pattern will make lossless-compressed screenshots "
+"larger.\n"
"[b]Note:[/b] Only available on the GLES3 backend. [member hdr] must also be "
"[code]true[/code] for debanding to be effective."
msgstr ""
@@ -70822,8 +70972,8 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
-"If [code]true[/code], the viewport will disable 3D rendering. For actual "
-"disabling use [code]usage[/code]."
+"If [code]true[/code], the viewport will disable 3D rendering. To actually "
+"disable allocation of 3D buffers, set [member usage] instead."
msgstr ""
#: doc/classes/Viewport.xml
@@ -70980,7 +71130,9 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
-"The rendering mode of viewport.\n"
+"The viewport's rendering mode. This controls which buffers are allocated for "
+"the viewport (2D only, or 2D + 3D). 2D-only options can reduce memory usage "
+"and improve performance slightly, especially on low-end devices.\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."
@@ -71521,6 +71673,22 @@ msgid ""
"render object this [VisualInstance] is set to."
msgstr ""
+#: doc/classes/VisualInstance.xml
+msgid ""
+"The sorting offset used by this [VisualInstance]. Adjusting it to a higher "
+"value will make the [VisualInstance] reliably draw on top of other "
+"[VisualInstance]s that are otherwise positioned at the same spot."
+msgstr ""
+
+#: doc/classes/VisualInstance.xml
+msgid ""
+"If [code]true[/code], the object is sorted based on the [AABB] center. "
+"Sorted based on the global position otherwise.\n"
+"The [AABB] center based sorting is generally more accurate for 3D models. "
+"The position based sorting instead allows to better control the drawing "
+"order when working with [Particles] and [CPUParticles]."
+msgstr ""
+
#: modules/visual_script/doc_classes/VisualScript.xml
msgid "A script implemented in the Visual Script programming environment."
msgstr ""
diff --git a/doc/translations/ko.po b/doc/translations/ko.po
index a744804896..72a7780a4c 100644
--- a/doc/translations/ko.po
+++ b/doc/translations/ko.po
@@ -18,12 +18,13 @@
# 김태우 <ogosengi3@gmail.com>, 2022.
# ì´ì§€ë¯¼ <jiminaleejung@gmail.com>, 2022.
# nulltable <un5450@naver.com>, 2022.
+# Godoto <aicompose@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-09-26 05:24+0000\n"
-"Last-Translator: nulltable <un5450@naver.com>\n"
+"PO-Revision-Date: 2022-10-18 18:00+0000\n"
+"Last-Translator: Godoto <aicompose@gmail.com>\n"
"Language-Team: Korean <https://hosted.weblate.org/projects/godot-engine/"
"godot-class-reference/ko/>\n"
"Language: ko\n"
@@ -31,7 +32,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.14.1\n"
+"X-Generator: Weblate 4.15-dev\n"
#: doc/tools/make_rst.py
msgid "Description"
@@ -47,7 +48,7 @@ msgstr "ì†ì„±"
#: doc/tools/make_rst.py
msgid "Methods"
-msgstr "메서드"
+msgstr "방법"
#: doc/tools/make_rst.py
msgid "Theme Properties"
@@ -55,11 +56,11 @@ msgstr "테마 ì†ì„±ë“¤"
#: doc/tools/make_rst.py
msgid "Signals"
-msgstr "시그ë„"
+msgstr "신호"
#: doc/tools/make_rst.py
msgid "Enumerations"
-msgstr "열거형"
+msgstr "목ë¡"
#: doc/tools/make_rst.py
msgid "Constants"
@@ -626,7 +627,8 @@ msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
-"Returns an array of dictionaries representing the current call stack.\n"
+"Returns an array of dictionaries representing the current call stack. See "
+"also [method print_stack].\n"
"[codeblock]\n"
"func _ready():\n"
" foo()\n"
@@ -641,7 +643,11 @@ msgid ""
"[codeblock]\n"
"[{function:bar, line:12, source:res://script.gd}, {function:foo, line:9, "
"source:res://script.gd}, {function:_ready, line:6, source:res://script.gd}]\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] [method get_stack] only works if the running instance is "
+"connected to a debugging server (i.e. an editor instance). [method "
+"get_stack] will not work in projects exported in release mode, or in "
+"projects exported in debug mode if not connected to a debugging server."
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -1028,12 +1034,16 @@ msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
-"Prints a stack track at code location, only works when running with debugger "
-"turned on.\n"
+"Prints a stack trace at the current code location. See also [method "
+"get_stack].\n"
"Output in the console would look something like this:\n"
"[codeblock]\n"
"Frame 0 - res://test.gd:16 in function '_process'\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] [method print_stack] only works if the running instance is "
+"connected to a debugging server (i.e. an editor instance). [method "
+"print_stack] will not work in projects exported in release mode, or in "
+"projects exported in debug mode if not connected to a debugging server."
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -3659,6 +3669,26 @@ msgid "Hints that an image is compressed using lossless compression."
msgstr ""
#: doc/classes/@GlobalScope.xml
+msgid ""
+"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:\n"
+"[codeblock]\n"
+"hint_string = \"%s:\" % [TYPE_INT] # Array of inteters.\n"
+"hint_string = \"%s:%s:\" % [TYPE_ARRAY, TYPE_REAL] # Two-dimensional array "
+"of floats.\n"
+"hint_string = \"%s/%s:Resource\" % [TYPE_OBJECT, TYPE_OBJECT] # Array of "
+"resources.\n"
+"hint_string = \"%s:%s/%s:Resource\" % [TYPE_ARRAY, TYPE_OBJECT, TYPE_OBJECT] "
+"# Two-dimensional array of resources.\n"
+"[/codeblock]\n"
+"[b]Note:[/b] The final colon is required to specify for properly detecting "
+"built-in types."
+msgstr ""
+
+#: doc/classes/@GlobalScope.xml
msgid "The property is serialized and saved in the scene file (default)."
msgstr ""
@@ -4343,8 +4373,7 @@ msgstr ""
#: doc/classes/AudioStreamPlayer.xml doc/classes/Button.xml
#: doc/classes/CanvasLayer.xml doc/classes/CollisionShape2D.xml
#: doc/classes/ColorRect.xml doc/classes/Input.xml doc/classes/InputEvent.xml
-#: doc/classes/InputEventAction.xml doc/classes/Label.xml
-#: doc/classes/Particles2D.xml doc/classes/Timer.xml
+#: doc/classes/InputEventAction.xml doc/classes/Label.xml doc/classes/Timer.xml
#: doc/classes/VisibilityNotifier2D.xml
msgid "2D Dodge The Creeps Demo"
msgstr ""
@@ -7264,7 +7293,10 @@ msgid ""
"var array = []\n"
"array.resize(10)\n"
"array.fill(0) # Initialize the 10 elements to 0.\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] If [code]value[/code] is of a reference type ([Object]-derived, "
+"[Array], [Dictionary], etc.) then the array is filled with the references to "
+"the same object, i.e. no duplicates are created."
msgstr ""
#: doc/classes/Array.xml doc/classes/PoolByteArray.xml
@@ -7449,6 +7481,9 @@ msgstr ""
#: doc/classes/Array.xml
msgid ""
"Sorts the array.\n"
+"[b]Note:[/b] The sorting algorithm used is not [url=https://en.wikipedia.org/"
+"wiki/Sorting_algorithm#Stability]stable[/url]. This means that values "
+"considered equal may have their order changed when using [method sort].\n"
"[b]Note:[/b] Strings are sorted in alphabetical order (as opposed to natural "
"order). This may lead to unexpected behavior when sorting an array of "
"strings ending with a sequence of numbers. Consider the following example:\n"
@@ -7468,9 +7503,13 @@ msgid ""
"For two elements [code]a[/code] and [code]b[/code], if the given method "
"returns [code]true[/code], element [code]b[/code] will be after element "
"[code]a[/code] in the array.\n"
+"[b]Note:[/b] The sorting algorithm used is not [url=https://en.wikipedia.org/"
+"wiki/Sorting_algorithm#Stability]stable[/url]. This means that values "
+"considered equal may have their order changed when using [method "
+"sort_custom].\n"
"[b]Note:[/b] You cannot randomize the return value as the heapsort algorithm "
-"expects a deterministic result. Doing so will result in unexpected "
-"behavior.\n"
+"expects a deterministic result. Randomizing the return value will result in "
+"unexpected behavior.\n"
"[codeblock]\n"
"class MyCustomSorter:\n"
" static func sort_ascending(a, b):\n"
@@ -10109,10 +10148,9 @@ msgstr ""
#: doc/classes/AudioStreamGeneratorPlayback.xml
msgid ""
-"Returns the number of audio data frames left to play. If this returned "
-"number reaches [code]0[/code], the audio will stop playing until frames are "
-"added again. Therefore, make sure your script can always generate and push "
-"new audio frames fast enough to avoid audio cracking."
+"Returns the number of frames that can be pushed to the audio sample data "
+"buffer without overflowing it. If the result is [code]0[/code], the buffer "
+"is full."
msgstr ""
#: doc/classes/AudioStreamGeneratorPlayback.xml
@@ -10644,14 +10682,14 @@ msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
"Node for back-buffering the currently-displayed screen. The region defined "
-"in the BackBufferCopy node is buffered with the content of the screen it "
+"in the [BackBufferCopy] node is buffered with the content of the screen it "
"covers, or the entire screen according to the copy mode set. Use the "
"[code]texture(SCREEN_TEXTURE, ...)[/code] function in your shader scripts to "
"access the buffer.\n"
"[b]Note:[/b] Since this node inherits from [Node2D] (and not [Control]), "
"anchors and margins won't apply to child [Control]-derived nodes. This can "
"be problematic when resizing the window. To avoid this, add [Control]-"
-"derived nodes as [i]siblings[/i] to the BackBufferCopy node instead of "
+"derived nodes as [i]siblings[/i] to the [BackBufferCopy] node instead of "
"adding them as children."
msgstr ""
@@ -10661,22 +10699,22 @@ msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
-"The area covered by the BackBufferCopy. Only used if [member copy_mode] is "
+"The area covered by the [BackBufferCopy]. Only used if [member copy_mode] is "
"[constant COPY_MODE_RECT]."
msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
-"Disables the buffering mode. This means the BackBufferCopy node will "
+"Disables the buffering mode. This means the [BackBufferCopy] node will "
"directly use the portion of screen it covers."
msgstr ""
#: doc/classes/BackBufferCopy.xml
-msgid "BackBufferCopy buffers a rectangular region."
+msgid "[BackBufferCopy] buffers a rectangular region."
msgstr ""
#: doc/classes/BackBufferCopy.xml
-msgid "BackBufferCopy buffers the entire screen."
+msgid "[BackBufferCopy] buffers the entire screen."
msgstr ""
#: doc/classes/BakedLightmap.xml
@@ -19513,6 +19551,14 @@ msgid "Cylinder shape for collisions."
msgstr ""
#: doc/classes/CylinderShape.xml
+msgid ""
+"Cylinder shape for collisions.\n"
+"[b]Note:[/b] When using GodotPhysics instead of the default Bullet physics "
+"engine, there are several known bugs with cylinder collision shapes. Using "
+"[CapsuleShape] or [BoxShape] instead is recommended."
+msgstr ""
+
+#: doc/classes/CylinderShape.xml
msgid "The cylinder's height."
msgstr ""
@@ -22408,7 +22454,10 @@ msgid ""
"[/codeblock]\n"
"[b]Note:[/b] The script is run in the Editor context, which means the output "
"is visible in the console window started with the Editor (stdout) instead of "
-"the usual Godot [b]Output[/b] dock."
+"the usual Godot [b]Output[/b] dock.\n"
+"[b]Note:[/b] EditorScript is reference counted, meaning it is destroyed when "
+"nothing references it. This can cause errors during asynchronous operations "
+"if there are no references to the script."
msgstr ""
#: doc/classes/EditorScript.xml
@@ -33147,7 +33196,9 @@ msgid ""
"The size of the light in Godot units. Only considered in baked lightmaps and "
"only if [member light_bake_mode] is set to [constant BAKE_ALL]. Increasing "
"this value will make the shadows appear blurrier. This can be used to "
-"simulate area lights to an extent."
+"simulate area lights to an extent.\n"
+"[b]Note:[/b] [member light_size] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/Light.xml
@@ -36475,7 +36526,10 @@ msgid ""
"use the [method get_next_location] function once every physics frame to "
"update the internal path logic of the NavigationAgent. The returned vector "
"position from this function should be used as the next movement position for "
-"the agent's parent Node."
+"the agent's parent Node.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues."
msgstr ""
#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
@@ -36725,7 +36779,10 @@ msgid ""
"use the [method get_next_location] function once every physics frame to "
"update the internal path logic of the NavigationAgent. The returned vector "
"position from this function should be used as the next movement position for "
-"the agent's parent Node."
+"the agent's parent Node.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues."
msgstr ""
#: doc/classes/NavigationAgent2D.xml
@@ -37442,6 +37499,9 @@ msgid ""
"modified velocity as-is might lead to pushing and agent outside of a "
"navigable area. This is a limitation of the collision avoidance system, any "
"more complex situation may require the use of the physics engine.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues.\n"
"This server keeps tracks of any call and executes them during the sync "
"phase. This means that you can request any change to the map, using any "
"thread, without worrying."
@@ -40378,7 +40438,9 @@ msgid ""
"The light's radius. Note that the effectively lit area may appear to be "
"smaller depending on the [member omni_attenuation] in use. No matter the "
"[member omni_attenuation] in use, the light will never reach anything "
-"outside this radius."
+"outside this radius.\n"
+"[b]Note:[/b] [member omni_range] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -40894,11 +40956,11 @@ msgstr "ë§¤ê°œë³€ìˆ˜ì˜ ì•„í¬ì‚¬ì¸ ê°’ì„ ë°˜í™˜í•©ë‹ˆë‹¤."
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] cache data directory according to the operating "
-"system's standards. On desktop platforms, this path can be overridden by "
-"setting the [code]XDG_CACHE_HOME[/code] environment variable before starting "
-"the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in "
-"Godot projects[/url] in the documentation for more information. See also "
-"[method get_config_dir] and [method get_data_dir].\n"
+"system's standards. On Linux, this path can be overridden by setting the "
+"[code]XDG_CACHE_HOME[/code] environment variable before starting the "
+"project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot "
+"projects[/url] in the documentation for more information. See also [method "
+"get_config_dir] and [method get_data_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -40932,11 +40994,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] user configuration directory according to the "
-"operating system's standards. On desktop platforms, this path can be "
-"overridden by setting the [code]XDG_CONFIG_HOME[/code] environment variable "
-"before starting the project. See [url=$DOCS_URL/tutorials/io/data_paths."
-"html]File paths in Godot projects[/url] in the documentation for more "
-"information. See also [method get_cache_dir] and [method get_data_dir].\n"
+"operating system's standards. On Linux, this path can be overridden by "
+"setting the [code]XDG_CONFIG_HOME[/code] environment variable before "
+"starting the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File "
+"paths in Godot projects[/url] in the documentation for more information. See "
+"also [method get_cache_dir] and [method get_data_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -40958,11 +41020,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] user data directory according to the operating "
-"system's standards. On desktop platforms, this path can be overridden by "
-"setting the [code]XDG_DATA_HOME[/code] environment variable before starting "
-"the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in "
-"Godot projects[/url] in the documentation for more information. See also "
-"[method get_cache_dir] and [method get_config_dir].\n"
+"system's standards. On Linux, this path can be overridden by setting the "
+"[code]XDG_DATA_HOME[/code] environment variable before starting the project. "
+"See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot "
+"projects[/url] in the documentation for more information. See also [method "
+"get_cache_dir] and [method get_config_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -42824,6 +42886,16 @@ msgid "Particle systems (2D)"
msgstr ""
#: doc/classes/Particles2D.xml
+msgid "2D Particles Demo"
+msgstr ""
+
+#: doc/classes/Particles2D.xml
+msgid ""
+"2D Dodge The Creeps Demo (uses GPUParticles2D for the trail behind the "
+"player)"
+msgstr ""
+
+#: doc/classes/Particles2D.xml
msgid "Returns a rectangle containing the positions of all existing particles."
msgstr ""
@@ -50425,15 +50497,22 @@ msgstr ""
#: doc/classes/ProjectSettings.xml
msgid ""
"If [code]true[/code], uses a fast post-processing filter to make banding "
-"significantly less visible. In some cases, debanding may introduce a "
-"slightly noticeable dithering pattern. It's recommended to enable debanding "
-"only when actually needed since the dithering pattern will make lossless-"
-"compressed screenshots larger.\n"
+"significantly less visible in 3D. 2D rendering is [i]not[/i] affected by "
+"debanding unless the [member Environment.background_mode] is [constant "
+"Environment.BG_CANVAS]. In this case, [member rendering/quality/"
+"intended_usage/framebuffer_allocation] must also be set to [b]3D[/b].\n"
+"In some cases, debanding may introduce a slightly noticeable dithering "
+"pattern. It's recommended to enable debanding only when actually needed "
+"since the dithering pattern will make lossless-compressed screenshots "
+"larger.\n"
"[b]Note:[/b] Only available on the GLES3 backend. [member rendering/quality/"
"depth/hdr] must also be [code]true[/code] for debanding to be effective.\n"
"[b]Note:[/b] There are known issues with debanding breaking rendering on "
"mobile platforms. Due to this, it is recommended to leave this option "
-"disabled when targeting mobile platforms."
+"disabled when targeting mobile platforms.\n"
+"[b]Note:[/b] This property is only read when the project starts. To set "
+"debanding at run-time, set [member Viewport.debanding] on the root "
+"[Viewport] instead."
msgstr ""
#: doc/classes/ProjectSettings.xml
@@ -52030,17 +52109,28 @@ msgstr ""
#: modules/regex/doc_classes/RegEx.xml
msgid ""
"Searches the text for the compiled pattern. Returns a [RegExMatch] container "
-"of the first matching result if found, otherwise [code]null[/code]. The "
-"region to search within can be specified without modifying where the start "
-"and end anchor would be."
+"of the first matching result if found, otherwise [code]null[/code].\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegEx.xml
msgid ""
"Searches the text for the compiled pattern. Returns an array of [RegExMatch] "
"containers for each non-overlapping result. If no results were found, an "
-"empty array is returned instead. The region to search within can be "
-"specified without modifying where the start and end anchor would be."
+"empty array is returned instead.\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegEx.xml
@@ -52049,8 +52139,14 @@ msgid ""
"specified string. Escapes and backreferences such as [code]$1[/code] and "
"[code]$name[/code] are expanded and resolved. By default, only the first "
"instance is replaced, but it can be changed for all instances (global "
-"replacement). The region to search within can be specified without modifying "
-"where the start and end anchor would be."
+"replacement).\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegExMatch.xml
@@ -54766,7 +54862,11 @@ msgid "Call a group immediately (calls are normally made on idle)."
msgstr ""
#: doc/classes/SceneTree.xml
-msgid "Call a group only once even if the call is executed many times."
+msgid ""
+"Call a group only once even if the call is executed many times.\n"
+"[b]Note:[/b] Arguments are not taken into account when deciding whether the "
+"call is unique or not. Therefore when the same method is called with "
+"different arguments, only the first call will be performed."
msgstr ""
#: doc/classes/SceneTree.xml
@@ -56603,7 +56703,9 @@ msgid ""
"[b]Note:[/b] Mixed negative scales in 3D are not decomposable from the "
"transformation matrix. Due to the way scale is represented with "
"transformation matrices in Godot, the scale values will either be all "
-"positive or all negative."
+"positive or all negative.\n"
+"[b]Note:[/b] Not all nodes are visually scaled by the [member scale] "
+"property. For example, [Light]s are not visually affected by [member scale]."
msgstr ""
#: doc/classes/Spatial.xml
@@ -57981,7 +58083,10 @@ msgid ""
msgstr ""
#: doc/classes/SpotLight.xml
-msgid "The spotlight's angle in degrees."
+msgid ""
+"The spotlight's angle in degrees.\n"
+"[b]Note:[/b] [member spot_angle] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/SpotLight.xml
@@ -57997,7 +58102,9 @@ msgid ""
"The maximal range that can be reached by the spotlight. Note that the "
"effectively lit area may appear to be smaller depending on the [member "
"spot_attenuation] in use. No matter the [member spot_attenuation] in use, "
-"the light will never reach anything outside this range."
+"the light will never reach anything outside this range.\n"
+"[b]Note:[/b] [member spot_range] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/SpringArm.xml
@@ -67281,10 +67388,15 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
"If [code]true[/code], uses a fast post-processing filter to make banding "
-"significantly less visible. In some cases, debanding may introduce a "
-"slightly noticeable dithering pattern. It's recommended to enable debanding "
-"only when actually needed since the dithering pattern will make lossless-"
-"compressed screenshots larger.\n"
+"significantly less visible in 3D. 2D rendering is [i]not[/i] affected by "
+"debanding unless the [member Environment.background_mode] is [constant "
+"Environment.BG_CANVAS]. In this case, [member usage] must also be set to "
+"[constant USAGE_3D]. See also [member ProjectSettings.rendering/quality/"
+"filters/use_debanding].\n"
+"In some cases, debanding may introduce a slightly noticeable dithering "
+"pattern. It's recommended to enable debanding only when actually needed "
+"since the dithering pattern will make lossless-compressed screenshots "
+"larger.\n"
"[b]Note:[/b] Only available on the GLES3 backend. [member hdr] must also be "
"[code]true[/code] for debanding to be effective."
msgstr ""
@@ -67295,8 +67407,8 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
-"If [code]true[/code], the viewport will disable 3D rendering. For actual "
-"disabling use [code]usage[/code]."
+"If [code]true[/code], the viewport will disable 3D rendering. To actually "
+"disable allocation of 3D buffers, set [member usage] instead."
msgstr ""
#: doc/classes/Viewport.xml
@@ -67448,7 +67560,9 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
-"The rendering mode of viewport.\n"
+"The viewport's rendering mode. This controls which buffers are allocated for "
+"the viewport (2D only, or 2D + 3D). 2D-only options can reduce memory usage "
+"and improve performance slightly, especially on low-end devices.\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."
@@ -67980,6 +68094,22 @@ msgid ""
"render object this [VisualInstance] is set to."
msgstr ""
+#: doc/classes/VisualInstance.xml
+msgid ""
+"The sorting offset used by this [VisualInstance]. Adjusting it to a higher "
+"value will make the [VisualInstance] reliably draw on top of other "
+"[VisualInstance]s that are otherwise positioned at the same spot."
+msgstr ""
+
+#: doc/classes/VisualInstance.xml
+msgid ""
+"If [code]true[/code], the object is sorted based on the [AABB] center. "
+"Sorted based on the global position otherwise.\n"
+"The [AABB] center based sorting is generally more accurate for 3D models. "
+"The position based sorting instead allows to better control the drawing "
+"order when working with [Particles] and [CPUParticles]."
+msgstr ""
+
#: modules/visual_script/doc_classes/VisualScript.xml
msgid "A script implemented in the Visual Script programming environment."
msgstr ""
diff --git a/doc/translations/lt.po b/doc/translations/lt.po
index f744f60e12..1cf0ffef48 100644
--- a/doc/translations/lt.po
+++ b/doc/translations/lt.po
@@ -485,7 +485,8 @@ msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
-"Returns an array of dictionaries representing the current call stack.\n"
+"Returns an array of dictionaries representing the current call stack. See "
+"also [method print_stack].\n"
"[codeblock]\n"
"func _ready():\n"
" foo()\n"
@@ -500,7 +501,11 @@ msgid ""
"[codeblock]\n"
"[{function:bar, line:12, source:res://script.gd}, {function:foo, line:9, "
"source:res://script.gd}, {function:_ready, line:6, source:res://script.gd}]\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] [method get_stack] only works if the running instance is "
+"connected to a debugging server (i.e. an editor instance). [method "
+"get_stack] will not work in projects exported in release mode, or in "
+"projects exported in debug mode if not connected to a debugging server."
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -873,12 +878,16 @@ msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
-"Prints a stack track at code location, only works when running with debugger "
-"turned on.\n"
+"Prints a stack trace at the current code location. See also [method "
+"get_stack].\n"
"Output in the console would look something like this:\n"
"[codeblock]\n"
"Frame 0 - res://test.gd:16 in function '_process'\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] [method print_stack] only works if the running instance is "
+"connected to a debugging server (i.e. an editor instance). [method "
+"print_stack] will not work in projects exported in release mode, or in "
+"projects exported in debug mode if not connected to a debugging server."
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -3489,6 +3498,26 @@ msgid "Hints that an image is compressed using lossless compression."
msgstr ""
#: doc/classes/@GlobalScope.xml
+msgid ""
+"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:\n"
+"[codeblock]\n"
+"hint_string = \"%s:\" % [TYPE_INT] # Array of inteters.\n"
+"hint_string = \"%s:%s:\" % [TYPE_ARRAY, TYPE_REAL] # Two-dimensional array "
+"of floats.\n"
+"hint_string = \"%s/%s:Resource\" % [TYPE_OBJECT, TYPE_OBJECT] # Array of "
+"resources.\n"
+"hint_string = \"%s:%s/%s:Resource\" % [TYPE_ARRAY, TYPE_OBJECT, TYPE_OBJECT] "
+"# Two-dimensional array of resources.\n"
+"[/codeblock]\n"
+"[b]Note:[/b] The final colon is required to specify for properly detecting "
+"built-in types."
+msgstr ""
+
+#: doc/classes/@GlobalScope.xml
msgid "The property is serialized and saved in the scene file (default)."
msgstr ""
@@ -4173,8 +4202,7 @@ msgstr ""
#: doc/classes/AudioStreamPlayer.xml doc/classes/Button.xml
#: doc/classes/CanvasLayer.xml doc/classes/CollisionShape2D.xml
#: doc/classes/ColorRect.xml doc/classes/Input.xml doc/classes/InputEvent.xml
-#: doc/classes/InputEventAction.xml doc/classes/Label.xml
-#: doc/classes/Particles2D.xml doc/classes/Timer.xml
+#: doc/classes/InputEventAction.xml doc/classes/Label.xml doc/classes/Timer.xml
#: doc/classes/VisibilityNotifier2D.xml
msgid "2D Dodge The Creeps Demo"
msgstr ""
@@ -7091,7 +7119,10 @@ msgid ""
"var array = []\n"
"array.resize(10)\n"
"array.fill(0) # Initialize the 10 elements to 0.\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] If [code]value[/code] is of a reference type ([Object]-derived, "
+"[Array], [Dictionary], etc.) then the array is filled with the references to "
+"the same object, i.e. no duplicates are created."
msgstr ""
#: doc/classes/Array.xml doc/classes/PoolByteArray.xml
@@ -7276,6 +7307,9 @@ msgstr ""
#: doc/classes/Array.xml
msgid ""
"Sorts the array.\n"
+"[b]Note:[/b] The sorting algorithm used is not [url=https://en.wikipedia.org/"
+"wiki/Sorting_algorithm#Stability]stable[/url]. This means that values "
+"considered equal may have their order changed when using [method sort].\n"
"[b]Note:[/b] Strings are sorted in alphabetical order (as opposed to natural "
"order). This may lead to unexpected behavior when sorting an array of "
"strings ending with a sequence of numbers. Consider the following example:\n"
@@ -7295,9 +7329,13 @@ msgid ""
"For two elements [code]a[/code] and [code]b[/code], if the given method "
"returns [code]true[/code], element [code]b[/code] will be after element "
"[code]a[/code] in the array.\n"
+"[b]Note:[/b] The sorting algorithm used is not [url=https://en.wikipedia.org/"
+"wiki/Sorting_algorithm#Stability]stable[/url]. This means that values "
+"considered equal may have their order changed when using [method "
+"sort_custom].\n"
"[b]Note:[/b] You cannot randomize the return value as the heapsort algorithm "
-"expects a deterministic result. Doing so will result in unexpected "
-"behavior.\n"
+"expects a deterministic result. Randomizing the return value will result in "
+"unexpected behavior.\n"
"[codeblock]\n"
"class MyCustomSorter:\n"
" static func sort_ascending(a, b):\n"
@@ -9935,10 +9973,9 @@ msgstr ""
#: doc/classes/AudioStreamGeneratorPlayback.xml
msgid ""
-"Returns the number of audio data frames left to play. If this returned "
-"number reaches [code]0[/code], the audio will stop playing until frames are "
-"added again. Therefore, make sure your script can always generate and push "
-"new audio frames fast enough to avoid audio cracking."
+"Returns the number of frames that can be pushed to the audio sample data "
+"buffer without overflowing it. If the result is [code]0[/code], the buffer "
+"is full."
msgstr ""
#: doc/classes/AudioStreamGeneratorPlayback.xml
@@ -10470,14 +10507,14 @@ msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
"Node for back-buffering the currently-displayed screen. The region defined "
-"in the BackBufferCopy node is buffered with the content of the screen it "
+"in the [BackBufferCopy] node is buffered with the content of the screen it "
"covers, or the entire screen according to the copy mode set. Use the "
"[code]texture(SCREEN_TEXTURE, ...)[/code] function in your shader scripts to "
"access the buffer.\n"
"[b]Note:[/b] Since this node inherits from [Node2D] (and not [Control]), "
"anchors and margins won't apply to child [Control]-derived nodes. This can "
"be problematic when resizing the window. To avoid this, add [Control]-"
-"derived nodes as [i]siblings[/i] to the BackBufferCopy node instead of "
+"derived nodes as [i]siblings[/i] to the [BackBufferCopy] node instead of "
"adding them as children."
msgstr ""
@@ -10487,22 +10524,22 @@ msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
-"The area covered by the BackBufferCopy. Only used if [member copy_mode] is "
+"The area covered by the [BackBufferCopy]. Only used if [member copy_mode] is "
"[constant COPY_MODE_RECT]."
msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
-"Disables the buffering mode. This means the BackBufferCopy node will "
+"Disables the buffering mode. This means the [BackBufferCopy] node will "
"directly use the portion of screen it covers."
msgstr ""
#: doc/classes/BackBufferCopy.xml
-msgid "BackBufferCopy buffers a rectangular region."
+msgid "[BackBufferCopy] buffers a rectangular region."
msgstr ""
#: doc/classes/BackBufferCopy.xml
-msgid "BackBufferCopy buffers the entire screen."
+msgid "[BackBufferCopy] buffers the entire screen."
msgstr ""
#: doc/classes/BakedLightmap.xml
@@ -19282,6 +19319,14 @@ msgid "Cylinder shape for collisions."
msgstr ""
#: doc/classes/CylinderShape.xml
+msgid ""
+"Cylinder shape for collisions.\n"
+"[b]Note:[/b] When using GodotPhysics instead of the default Bullet physics "
+"engine, there are several known bugs with cylinder collision shapes. Using "
+"[CapsuleShape] or [BoxShape] instead is recommended."
+msgstr ""
+
+#: doc/classes/CylinderShape.xml
msgid "The cylinder's height."
msgstr ""
@@ -22114,7 +22159,10 @@ msgid ""
"[/codeblock]\n"
"[b]Note:[/b] The script is run in the Editor context, which means the output "
"is visible in the console window started with the Editor (stdout) instead of "
-"the usual Godot [b]Output[/b] dock."
+"the usual Godot [b]Output[/b] dock.\n"
+"[b]Note:[/b] EditorScript is reference counted, meaning it is destroyed when "
+"nothing references it. This can cause errors during asynchronous operations "
+"if there are no references to the script."
msgstr ""
#: doc/classes/EditorScript.xml
@@ -32826,7 +32874,9 @@ msgid ""
"The size of the light in Godot units. Only considered in baked lightmaps and "
"only if [member light_bake_mode] is set to [constant BAKE_ALL]. Increasing "
"this value will make the shadows appear blurrier. This can be used to "
-"simulate area lights to an extent."
+"simulate area lights to an extent.\n"
+"[b]Note:[/b] [member light_size] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/Light.xml
@@ -36124,7 +36174,10 @@ msgid ""
"use the [method get_next_location] function once every physics frame to "
"update the internal path logic of the NavigationAgent. The returned vector "
"position from this function should be used as the next movement position for "
-"the agent's parent Node."
+"the agent's parent Node.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues."
msgstr ""
#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
@@ -36372,7 +36425,10 @@ msgid ""
"use the [method get_next_location] function once every physics frame to "
"update the internal path logic of the NavigationAgent. The returned vector "
"position from this function should be used as the next movement position for "
-"the agent's parent Node."
+"the agent's parent Node.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues."
msgstr ""
#: doc/classes/NavigationAgent2D.xml
@@ -37082,6 +37138,9 @@ msgid ""
"modified velocity as-is might lead to pushing and agent outside of a "
"navigable area. This is a limitation of the collision avoidance system, any "
"more complex situation may require the use of the physics engine.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues.\n"
"This server keeps tracks of any call and executes them during the sync "
"phase. This means that you can request any change to the map, using any "
"thread, without worrying."
@@ -39888,7 +39947,9 @@ msgid ""
"The light's radius. Note that the effectively lit area may appear to be "
"smaller depending on the [member omni_attenuation] in use. No matter the "
"[member omni_attenuation] in use, the light will never reach anything "
-"outside this radius."
+"outside this radius.\n"
+"[b]Note:[/b] [member omni_range] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -40399,11 +40460,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] cache data directory according to the operating "
-"system's standards. On desktop platforms, this path can be overridden by "
-"setting the [code]XDG_CACHE_HOME[/code] environment variable before starting "
-"the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in "
-"Godot projects[/url] in the documentation for more information. See also "
-"[method get_config_dir] and [method get_data_dir].\n"
+"system's standards. On Linux, this path can be overridden by setting the "
+"[code]XDG_CACHE_HOME[/code] environment variable before starting the "
+"project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot "
+"projects[/url] in the documentation for more information. See also [method "
+"get_config_dir] and [method get_data_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -40437,11 +40498,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] user configuration directory according to the "
-"operating system's standards. On desktop platforms, this path can be "
-"overridden by setting the [code]XDG_CONFIG_HOME[/code] environment variable "
-"before starting the project. See [url=$DOCS_URL/tutorials/io/data_paths."
-"html]File paths in Godot projects[/url] in the documentation for more "
-"information. See also [method get_cache_dir] and [method get_data_dir].\n"
+"operating system's standards. On Linux, this path can be overridden by "
+"setting the [code]XDG_CONFIG_HOME[/code] environment variable before "
+"starting the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File "
+"paths in Godot projects[/url] in the documentation for more information. See "
+"also [method get_cache_dir] and [method get_data_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -40463,11 +40524,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] user data directory according to the operating "
-"system's standards. On desktop platforms, this path can be overridden by "
-"setting the [code]XDG_DATA_HOME[/code] environment variable before starting "
-"the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in "
-"Godot projects[/url] in the documentation for more information. See also "
-"[method get_cache_dir] and [method get_config_dir].\n"
+"system's standards. On Linux, this path can be overridden by setting the "
+"[code]XDG_DATA_HOME[/code] environment variable before starting the project. "
+"See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot "
+"projects[/url] in the documentation for more information. See also [method "
+"get_cache_dir] and [method get_config_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -42314,6 +42375,16 @@ msgid "Particle systems (2D)"
msgstr ""
#: doc/classes/Particles2D.xml
+msgid "2D Particles Demo"
+msgstr ""
+
+#: doc/classes/Particles2D.xml
+msgid ""
+"2D Dodge The Creeps Demo (uses GPUParticles2D for the trail behind the "
+"player)"
+msgstr ""
+
+#: doc/classes/Particles2D.xml
msgid "Returns a rectangle containing the positions of all existing particles."
msgstr ""
@@ -49906,15 +49977,22 @@ msgstr ""
#: doc/classes/ProjectSettings.xml
msgid ""
"If [code]true[/code], uses a fast post-processing filter to make banding "
-"significantly less visible. In some cases, debanding may introduce a "
-"slightly noticeable dithering pattern. It's recommended to enable debanding "
-"only when actually needed since the dithering pattern will make lossless-"
-"compressed screenshots larger.\n"
+"significantly less visible in 3D. 2D rendering is [i]not[/i] affected by "
+"debanding unless the [member Environment.background_mode] is [constant "
+"Environment.BG_CANVAS]. In this case, [member rendering/quality/"
+"intended_usage/framebuffer_allocation] must also be set to [b]3D[/b].\n"
+"In some cases, debanding may introduce a slightly noticeable dithering "
+"pattern. It's recommended to enable debanding only when actually needed "
+"since the dithering pattern will make lossless-compressed screenshots "
+"larger.\n"
"[b]Note:[/b] Only available on the GLES3 backend. [member rendering/quality/"
"depth/hdr] must also be [code]true[/code] for debanding to be effective.\n"
"[b]Note:[/b] There are known issues with debanding breaking rendering on "
"mobile platforms. Due to this, it is recommended to leave this option "
-"disabled when targeting mobile platforms."
+"disabled when targeting mobile platforms.\n"
+"[b]Note:[/b] This property is only read when the project starts. To set "
+"debanding at run-time, set [member Viewport.debanding] on the root "
+"[Viewport] instead."
msgstr ""
#: doc/classes/ProjectSettings.xml
@@ -51510,17 +51588,28 @@ msgstr ""
#: modules/regex/doc_classes/RegEx.xml
msgid ""
"Searches the text for the compiled pattern. Returns a [RegExMatch] container "
-"of the first matching result if found, otherwise [code]null[/code]. The "
-"region to search within can be specified without modifying where the start "
-"and end anchor would be."
+"of the first matching result if found, otherwise [code]null[/code].\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegEx.xml
msgid ""
"Searches the text for the compiled pattern. Returns an array of [RegExMatch] "
"containers for each non-overlapping result. If no results were found, an "
-"empty array is returned instead. The region to search within can be "
-"specified without modifying where the start and end anchor would be."
+"empty array is returned instead.\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegEx.xml
@@ -51529,8 +51618,14 @@ msgid ""
"specified string. Escapes and backreferences such as [code]$1[/code] and "
"[code]$name[/code] are expanded and resolved. By default, only the first "
"instance is replaced, but it can be changed for all instances (global "
-"replacement). The region to search within can be specified without modifying "
-"where the start and end anchor would be."
+"replacement).\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegExMatch.xml
@@ -54245,7 +54340,11 @@ msgid "Call a group immediately (calls are normally made on idle)."
msgstr ""
#: doc/classes/SceneTree.xml
-msgid "Call a group only once even if the call is executed many times."
+msgid ""
+"Call a group only once even if the call is executed many times.\n"
+"[b]Note:[/b] Arguments are not taken into account when deciding whether the "
+"call is unique or not. Therefore when the same method is called with "
+"different arguments, only the first call will be performed."
msgstr ""
#: doc/classes/SceneTree.xml
@@ -56082,7 +56181,9 @@ msgid ""
"[b]Note:[/b] Mixed negative scales in 3D are not decomposable from the "
"transformation matrix. Due to the way scale is represented with "
"transformation matrices in Godot, the scale values will either be all "
-"positive or all negative."
+"positive or all negative.\n"
+"[b]Note:[/b] Not all nodes are visually scaled by the [member scale] "
+"property. For example, [Light]s are not visually affected by [member scale]."
msgstr ""
#: doc/classes/Spatial.xml
@@ -57460,7 +57561,10 @@ msgid ""
msgstr ""
#: doc/classes/SpotLight.xml
-msgid "The spotlight's angle in degrees."
+msgid ""
+"The spotlight's angle in degrees.\n"
+"[b]Note:[/b] [member spot_angle] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/SpotLight.xml
@@ -57476,7 +57580,9 @@ msgid ""
"The maximal range that can be reached by the spotlight. Note that the "
"effectively lit area may appear to be smaller depending on the [member "
"spot_attenuation] in use. No matter the [member spot_attenuation] in use, "
-"the light will never reach anything outside this range."
+"the light will never reach anything outside this range.\n"
+"[b]Note:[/b] [member spot_range] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/SpringArm.xml
@@ -66713,10 +66819,15 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
"If [code]true[/code], uses a fast post-processing filter to make banding "
-"significantly less visible. In some cases, debanding may introduce a "
-"slightly noticeable dithering pattern. It's recommended to enable debanding "
-"only when actually needed since the dithering pattern will make lossless-"
-"compressed screenshots larger.\n"
+"significantly less visible in 3D. 2D rendering is [i]not[/i] affected by "
+"debanding unless the [member Environment.background_mode] is [constant "
+"Environment.BG_CANVAS]. In this case, [member usage] must also be set to "
+"[constant USAGE_3D]. See also [member ProjectSettings.rendering/quality/"
+"filters/use_debanding].\n"
+"In some cases, debanding may introduce a slightly noticeable dithering "
+"pattern. It's recommended to enable debanding only when actually needed "
+"since the dithering pattern will make lossless-compressed screenshots "
+"larger.\n"
"[b]Note:[/b] Only available on the GLES3 backend. [member hdr] must also be "
"[code]true[/code] for debanding to be effective."
msgstr ""
@@ -66727,8 +66838,8 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
-"If [code]true[/code], the viewport will disable 3D rendering. For actual "
-"disabling use [code]usage[/code]."
+"If [code]true[/code], the viewport will disable 3D rendering. To actually "
+"disable allocation of 3D buffers, set [member usage] instead."
msgstr ""
#: doc/classes/Viewport.xml
@@ -66880,7 +66991,9 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
-"The rendering mode of viewport.\n"
+"The viewport's rendering mode. This controls which buffers are allocated for "
+"the viewport (2D only, or 2D + 3D). 2D-only options can reduce memory usage "
+"and improve performance slightly, especially on low-end devices.\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."
@@ -67412,6 +67525,22 @@ msgid ""
"render object this [VisualInstance] is set to."
msgstr ""
+#: doc/classes/VisualInstance.xml
+msgid ""
+"The sorting offset used by this [VisualInstance]. Adjusting it to a higher "
+"value will make the [VisualInstance] reliably draw on top of other "
+"[VisualInstance]s that are otherwise positioned at the same spot."
+msgstr ""
+
+#: doc/classes/VisualInstance.xml
+msgid ""
+"If [code]true[/code], the object is sorted based on the [AABB] center. "
+"Sorted based on the global position otherwise.\n"
+"The [AABB] center based sorting is generally more accurate for 3D models. "
+"The position based sorting instead allows to better control the drawing "
+"order when working with [Particles] and [CPUParticles]."
+msgstr ""
+
#: modules/visual_script/doc_classes/VisualScript.xml
msgid "A script implemented in the Visual Script programming environment."
msgstr ""
diff --git a/doc/translations/lv.po b/doc/translations/lv.po
index 1b6d5f9cd5..fd9ddf6f51 100644
--- a/doc/translations/lv.po
+++ b/doc/translations/lv.po
@@ -490,7 +490,8 @@ msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
-"Returns an array of dictionaries representing the current call stack.\n"
+"Returns an array of dictionaries representing the current call stack. See "
+"also [method print_stack].\n"
"[codeblock]\n"
"func _ready():\n"
" foo()\n"
@@ -505,7 +506,11 @@ msgid ""
"[codeblock]\n"
"[{function:bar, line:12, source:res://script.gd}, {function:foo, line:9, "
"source:res://script.gd}, {function:_ready, line:6, source:res://script.gd}]\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] [method get_stack] only works if the running instance is "
+"connected to a debugging server (i.e. an editor instance). [method "
+"get_stack] will not work in projects exported in release mode, or in "
+"projects exported in debug mode if not connected to a debugging server."
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -878,12 +883,16 @@ msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
-"Prints a stack track at code location, only works when running with debugger "
-"turned on.\n"
+"Prints a stack trace at the current code location. See also [method "
+"get_stack].\n"
"Output in the console would look something like this:\n"
"[codeblock]\n"
"Frame 0 - res://test.gd:16 in function '_process'\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] [method print_stack] only works if the running instance is "
+"connected to a debugging server (i.e. an editor instance). [method "
+"print_stack] will not work in projects exported in release mode, or in "
+"projects exported in debug mode if not connected to a debugging server."
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -3494,6 +3503,26 @@ msgid "Hints that an image is compressed using lossless compression."
msgstr ""
#: doc/classes/@GlobalScope.xml
+msgid ""
+"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:\n"
+"[codeblock]\n"
+"hint_string = \"%s:\" % [TYPE_INT] # Array of inteters.\n"
+"hint_string = \"%s:%s:\" % [TYPE_ARRAY, TYPE_REAL] # Two-dimensional array "
+"of floats.\n"
+"hint_string = \"%s/%s:Resource\" % [TYPE_OBJECT, TYPE_OBJECT] # Array of "
+"resources.\n"
+"hint_string = \"%s:%s/%s:Resource\" % [TYPE_ARRAY, TYPE_OBJECT, TYPE_OBJECT] "
+"# Two-dimensional array of resources.\n"
+"[/codeblock]\n"
+"[b]Note:[/b] The final colon is required to specify for properly detecting "
+"built-in types."
+msgstr ""
+
+#: doc/classes/@GlobalScope.xml
msgid "The property is serialized and saved in the scene file (default)."
msgstr ""
@@ -4178,8 +4207,7 @@ msgstr ""
#: doc/classes/AudioStreamPlayer.xml doc/classes/Button.xml
#: doc/classes/CanvasLayer.xml doc/classes/CollisionShape2D.xml
#: doc/classes/ColorRect.xml doc/classes/Input.xml doc/classes/InputEvent.xml
-#: doc/classes/InputEventAction.xml doc/classes/Label.xml
-#: doc/classes/Particles2D.xml doc/classes/Timer.xml
+#: doc/classes/InputEventAction.xml doc/classes/Label.xml doc/classes/Timer.xml
#: doc/classes/VisibilityNotifier2D.xml
msgid "2D Dodge The Creeps Demo"
msgstr ""
@@ -7096,7 +7124,10 @@ msgid ""
"var array = []\n"
"array.resize(10)\n"
"array.fill(0) # Initialize the 10 elements to 0.\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] If [code]value[/code] is of a reference type ([Object]-derived, "
+"[Array], [Dictionary], etc.) then the array is filled with the references to "
+"the same object, i.e. no duplicates are created."
msgstr ""
#: doc/classes/Array.xml doc/classes/PoolByteArray.xml
@@ -7281,6 +7312,9 @@ msgstr ""
#: doc/classes/Array.xml
msgid ""
"Sorts the array.\n"
+"[b]Note:[/b] The sorting algorithm used is not [url=https://en.wikipedia.org/"
+"wiki/Sorting_algorithm#Stability]stable[/url]. This means that values "
+"considered equal may have their order changed when using [method sort].\n"
"[b]Note:[/b] Strings are sorted in alphabetical order (as opposed to natural "
"order). This may lead to unexpected behavior when sorting an array of "
"strings ending with a sequence of numbers. Consider the following example:\n"
@@ -7300,9 +7334,13 @@ msgid ""
"For two elements [code]a[/code] and [code]b[/code], if the given method "
"returns [code]true[/code], element [code]b[/code] will be after element "
"[code]a[/code] in the array.\n"
+"[b]Note:[/b] The sorting algorithm used is not [url=https://en.wikipedia.org/"
+"wiki/Sorting_algorithm#Stability]stable[/url]. This means that values "
+"considered equal may have their order changed when using [method "
+"sort_custom].\n"
"[b]Note:[/b] You cannot randomize the return value as the heapsort algorithm "
-"expects a deterministic result. Doing so will result in unexpected "
-"behavior.\n"
+"expects a deterministic result. Randomizing the return value will result in "
+"unexpected behavior.\n"
"[codeblock]\n"
"class MyCustomSorter:\n"
" static func sort_ascending(a, b):\n"
@@ -9940,10 +9978,9 @@ msgstr ""
#: doc/classes/AudioStreamGeneratorPlayback.xml
msgid ""
-"Returns the number of audio data frames left to play. If this returned "
-"number reaches [code]0[/code], the audio will stop playing until frames are "
-"added again. Therefore, make sure your script can always generate and push "
-"new audio frames fast enough to avoid audio cracking."
+"Returns the number of frames that can be pushed to the audio sample data "
+"buffer without overflowing it. If the result is [code]0[/code], the buffer "
+"is full."
msgstr ""
#: doc/classes/AudioStreamGeneratorPlayback.xml
@@ -10475,14 +10512,14 @@ msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
"Node for back-buffering the currently-displayed screen. The region defined "
-"in the BackBufferCopy node is buffered with the content of the screen it "
+"in the [BackBufferCopy] node is buffered with the content of the screen it "
"covers, or the entire screen according to the copy mode set. Use the "
"[code]texture(SCREEN_TEXTURE, ...)[/code] function in your shader scripts to "
"access the buffer.\n"
"[b]Note:[/b] Since this node inherits from [Node2D] (and not [Control]), "
"anchors and margins won't apply to child [Control]-derived nodes. This can "
"be problematic when resizing the window. To avoid this, add [Control]-"
-"derived nodes as [i]siblings[/i] to the BackBufferCopy node instead of "
+"derived nodes as [i]siblings[/i] to the [BackBufferCopy] node instead of "
"adding them as children."
msgstr ""
@@ -10492,22 +10529,22 @@ msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
-"The area covered by the BackBufferCopy. Only used if [member copy_mode] is "
+"The area covered by the [BackBufferCopy]. Only used if [member copy_mode] is "
"[constant COPY_MODE_RECT]."
msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
-"Disables the buffering mode. This means the BackBufferCopy node will "
+"Disables the buffering mode. This means the [BackBufferCopy] node will "
"directly use the portion of screen it covers."
msgstr ""
#: doc/classes/BackBufferCopy.xml
-msgid "BackBufferCopy buffers a rectangular region."
+msgid "[BackBufferCopy] buffers a rectangular region."
msgstr ""
#: doc/classes/BackBufferCopy.xml
-msgid "BackBufferCopy buffers the entire screen."
+msgid "[BackBufferCopy] buffers the entire screen."
msgstr ""
#: doc/classes/BakedLightmap.xml
@@ -19287,6 +19324,14 @@ msgid "Cylinder shape for collisions."
msgstr ""
#: doc/classes/CylinderShape.xml
+msgid ""
+"Cylinder shape for collisions.\n"
+"[b]Note:[/b] When using GodotPhysics instead of the default Bullet physics "
+"engine, there are several known bugs with cylinder collision shapes. Using "
+"[CapsuleShape] or [BoxShape] instead is recommended."
+msgstr ""
+
+#: doc/classes/CylinderShape.xml
msgid "The cylinder's height."
msgstr ""
@@ -22119,7 +22164,10 @@ msgid ""
"[/codeblock]\n"
"[b]Note:[/b] The script is run in the Editor context, which means the output "
"is visible in the console window started with the Editor (stdout) instead of "
-"the usual Godot [b]Output[/b] dock."
+"the usual Godot [b]Output[/b] dock.\n"
+"[b]Note:[/b] EditorScript is reference counted, meaning it is destroyed when "
+"nothing references it. This can cause errors during asynchronous operations "
+"if there are no references to the script."
msgstr ""
#: doc/classes/EditorScript.xml
@@ -32834,7 +32882,9 @@ msgid ""
"The size of the light in Godot units. Only considered in baked lightmaps and "
"only if [member light_bake_mode] is set to [constant BAKE_ALL]. Increasing "
"this value will make the shadows appear blurrier. This can be used to "
-"simulate area lights to an extent."
+"simulate area lights to an extent.\n"
+"[b]Note:[/b] [member light_size] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/Light.xml
@@ -36132,7 +36182,10 @@ msgid ""
"use the [method get_next_location] function once every physics frame to "
"update the internal path logic of the NavigationAgent. The returned vector "
"position from this function should be used as the next movement position for "
-"the agent's parent Node."
+"the agent's parent Node.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues."
msgstr ""
#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
@@ -36380,7 +36433,10 @@ msgid ""
"use the [method get_next_location] function once every physics frame to "
"update the internal path logic of the NavigationAgent. The returned vector "
"position from this function should be used as the next movement position for "
-"the agent's parent Node."
+"the agent's parent Node.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues."
msgstr ""
#: doc/classes/NavigationAgent2D.xml
@@ -37090,6 +37146,9 @@ msgid ""
"modified velocity as-is might lead to pushing and agent outside of a "
"navigable area. This is a limitation of the collision avoidance system, any "
"more complex situation may require the use of the physics engine.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues.\n"
"This server keeps tracks of any call and executes them during the sync "
"phase. This means that you can request any change to the map, using any "
"thread, without worrying."
@@ -39896,7 +39955,9 @@ msgid ""
"The light's radius. Note that the effectively lit area may appear to be "
"smaller depending on the [member omni_attenuation] in use. No matter the "
"[member omni_attenuation] in use, the light will never reach anything "
-"outside this radius."
+"outside this radius.\n"
+"[b]Note:[/b] [member omni_range] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -40407,11 +40468,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] cache data directory according to the operating "
-"system's standards. On desktop platforms, this path can be overridden by "
-"setting the [code]XDG_CACHE_HOME[/code] environment variable before starting "
-"the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in "
-"Godot projects[/url] in the documentation for more information. See also "
-"[method get_config_dir] and [method get_data_dir].\n"
+"system's standards. On Linux, this path can be overridden by setting the "
+"[code]XDG_CACHE_HOME[/code] environment variable before starting the "
+"project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot "
+"projects[/url] in the documentation for more information. See also [method "
+"get_config_dir] and [method get_data_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -40445,11 +40506,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] user configuration directory according to the "
-"operating system's standards. On desktop platforms, this path can be "
-"overridden by setting the [code]XDG_CONFIG_HOME[/code] environment variable "
-"before starting the project. See [url=$DOCS_URL/tutorials/io/data_paths."
-"html]File paths in Godot projects[/url] in the documentation for more "
-"information. See also [method get_cache_dir] and [method get_data_dir].\n"
+"operating system's standards. On Linux, this path can be overridden by "
+"setting the [code]XDG_CONFIG_HOME[/code] environment variable before "
+"starting the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File "
+"paths in Godot projects[/url] in the documentation for more information. See "
+"also [method get_cache_dir] and [method get_data_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -40471,11 +40532,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] user data directory according to the operating "
-"system's standards. On desktop platforms, this path can be overridden by "
-"setting the [code]XDG_DATA_HOME[/code] environment variable before starting "
-"the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in "
-"Godot projects[/url] in the documentation for more information. See also "
-"[method get_cache_dir] and [method get_config_dir].\n"
+"system's standards. On Linux, this path can be overridden by setting the "
+"[code]XDG_DATA_HOME[/code] environment variable before starting the project. "
+"See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot "
+"projects[/url] in the documentation for more information. See also [method "
+"get_cache_dir] and [method get_config_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -42322,6 +42383,16 @@ msgid "Particle systems (2D)"
msgstr ""
#: doc/classes/Particles2D.xml
+msgid "2D Particles Demo"
+msgstr ""
+
+#: doc/classes/Particles2D.xml
+msgid ""
+"2D Dodge The Creeps Demo (uses GPUParticles2D for the trail behind the "
+"player)"
+msgstr ""
+
+#: doc/classes/Particles2D.xml
msgid "Returns a rectangle containing the positions of all existing particles."
msgstr ""
@@ -49914,15 +49985,22 @@ msgstr ""
#: doc/classes/ProjectSettings.xml
msgid ""
"If [code]true[/code], uses a fast post-processing filter to make banding "
-"significantly less visible. In some cases, debanding may introduce a "
-"slightly noticeable dithering pattern. It's recommended to enable debanding "
-"only when actually needed since the dithering pattern will make lossless-"
-"compressed screenshots larger.\n"
+"significantly less visible in 3D. 2D rendering is [i]not[/i] affected by "
+"debanding unless the [member Environment.background_mode] is [constant "
+"Environment.BG_CANVAS]. In this case, [member rendering/quality/"
+"intended_usage/framebuffer_allocation] must also be set to [b]3D[/b].\n"
+"In some cases, debanding may introduce a slightly noticeable dithering "
+"pattern. It's recommended to enable debanding only when actually needed "
+"since the dithering pattern will make lossless-compressed screenshots "
+"larger.\n"
"[b]Note:[/b] Only available on the GLES3 backend. [member rendering/quality/"
"depth/hdr] must also be [code]true[/code] for debanding to be effective.\n"
"[b]Note:[/b] There are known issues with debanding breaking rendering on "
"mobile platforms. Due to this, it is recommended to leave this option "
-"disabled when targeting mobile platforms."
+"disabled when targeting mobile platforms.\n"
+"[b]Note:[/b] This property is only read when the project starts. To set "
+"debanding at run-time, set [member Viewport.debanding] on the root "
+"[Viewport] instead."
msgstr ""
#: doc/classes/ProjectSettings.xml
@@ -51518,17 +51596,28 @@ msgstr ""
#: modules/regex/doc_classes/RegEx.xml
msgid ""
"Searches the text for the compiled pattern. Returns a [RegExMatch] container "
-"of the first matching result if found, otherwise [code]null[/code]. The "
-"region to search within can be specified without modifying where the start "
-"and end anchor would be."
+"of the first matching result if found, otherwise [code]null[/code].\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegEx.xml
msgid ""
"Searches the text for the compiled pattern. Returns an array of [RegExMatch] "
"containers for each non-overlapping result. If no results were found, an "
-"empty array is returned instead. The region to search within can be "
-"specified without modifying where the start and end anchor would be."
+"empty array is returned instead.\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegEx.xml
@@ -51537,8 +51626,14 @@ msgid ""
"specified string. Escapes and backreferences such as [code]$1[/code] and "
"[code]$name[/code] are expanded and resolved. By default, only the first "
"instance is replaced, but it can be changed for all instances (global "
-"replacement). The region to search within can be specified without modifying "
-"where the start and end anchor would be."
+"replacement).\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegExMatch.xml
@@ -54253,7 +54348,11 @@ msgid "Call a group immediately (calls are normally made on idle)."
msgstr ""
#: doc/classes/SceneTree.xml
-msgid "Call a group only once even if the call is executed many times."
+msgid ""
+"Call a group only once even if the call is executed many times.\n"
+"[b]Note:[/b] Arguments are not taken into account when deciding whether the "
+"call is unique or not. Therefore when the same method is called with "
+"different arguments, only the first call will be performed."
msgstr ""
#: doc/classes/SceneTree.xml
@@ -56090,7 +56189,9 @@ msgid ""
"[b]Note:[/b] Mixed negative scales in 3D are not decomposable from the "
"transformation matrix. Due to the way scale is represented with "
"transformation matrices in Godot, the scale values will either be all "
-"positive or all negative."
+"positive or all negative.\n"
+"[b]Note:[/b] Not all nodes are visually scaled by the [member scale] "
+"property. For example, [Light]s are not visually affected by [member scale]."
msgstr ""
#: doc/classes/Spatial.xml
@@ -57468,7 +57569,10 @@ msgid ""
msgstr ""
#: doc/classes/SpotLight.xml
-msgid "The spotlight's angle in degrees."
+msgid ""
+"The spotlight's angle in degrees.\n"
+"[b]Note:[/b] [member spot_angle] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/SpotLight.xml
@@ -57484,7 +57588,9 @@ msgid ""
"The maximal range that can be reached by the spotlight. Note that the "
"effectively lit area may appear to be smaller depending on the [member "
"spot_attenuation] in use. No matter the [member spot_attenuation] in use, "
-"the light will never reach anything outside this range."
+"the light will never reach anything outside this range.\n"
+"[b]Note:[/b] [member spot_range] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/SpringArm.xml
@@ -66721,10 +66827,15 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
"If [code]true[/code], uses a fast post-processing filter to make banding "
-"significantly less visible. In some cases, debanding may introduce a "
-"slightly noticeable dithering pattern. It's recommended to enable debanding "
-"only when actually needed since the dithering pattern will make lossless-"
-"compressed screenshots larger.\n"
+"significantly less visible in 3D. 2D rendering is [i]not[/i] affected by "
+"debanding unless the [member Environment.background_mode] is [constant "
+"Environment.BG_CANVAS]. In this case, [member usage] must also be set to "
+"[constant USAGE_3D]. See also [member ProjectSettings.rendering/quality/"
+"filters/use_debanding].\n"
+"In some cases, debanding may introduce a slightly noticeable dithering "
+"pattern. It's recommended to enable debanding only when actually needed "
+"since the dithering pattern will make lossless-compressed screenshots "
+"larger.\n"
"[b]Note:[/b] Only available on the GLES3 backend. [member hdr] must also be "
"[code]true[/code] for debanding to be effective."
msgstr ""
@@ -66735,8 +66846,8 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
-"If [code]true[/code], the viewport will disable 3D rendering. For actual "
-"disabling use [code]usage[/code]."
+"If [code]true[/code], the viewport will disable 3D rendering. To actually "
+"disable allocation of 3D buffers, set [member usage] instead."
msgstr ""
#: doc/classes/Viewport.xml
@@ -66888,7 +66999,9 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
-"The rendering mode of viewport.\n"
+"The viewport's rendering mode. This controls which buffers are allocated for "
+"the viewport (2D only, or 2D + 3D). 2D-only options can reduce memory usage "
+"and improve performance slightly, especially on low-end devices.\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."
@@ -67420,6 +67533,22 @@ msgid ""
"render object this [VisualInstance] is set to."
msgstr ""
+#: doc/classes/VisualInstance.xml
+msgid ""
+"The sorting offset used by this [VisualInstance]. Adjusting it to a higher "
+"value will make the [VisualInstance] reliably draw on top of other "
+"[VisualInstance]s that are otherwise positioned at the same spot."
+msgstr ""
+
+#: doc/classes/VisualInstance.xml
+msgid ""
+"If [code]true[/code], the object is sorted based on the [AABB] center. "
+"Sorted based on the global position otherwise.\n"
+"The [AABB] center based sorting is generally more accurate for 3D models. "
+"The position based sorting instead allows to better control the drawing "
+"order when working with [Particles] and [CPUParticles]."
+msgstr ""
+
#: modules/visual_script/doc_classes/VisualScript.xml
msgid "A script implemented in the Visual Script programming environment."
msgstr ""
diff --git a/doc/translations/mr.po b/doc/translations/mr.po
index 3636dbf68f..19db2e5f94 100644
--- a/doc/translations/mr.po
+++ b/doc/translations/mr.po
@@ -473,7 +473,8 @@ msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
-"Returns an array of dictionaries representing the current call stack.\n"
+"Returns an array of dictionaries representing the current call stack. See "
+"also [method print_stack].\n"
"[codeblock]\n"
"func _ready():\n"
" foo()\n"
@@ -488,7 +489,11 @@ msgid ""
"[codeblock]\n"
"[{function:bar, line:12, source:res://script.gd}, {function:foo, line:9, "
"source:res://script.gd}, {function:_ready, line:6, source:res://script.gd}]\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] [method get_stack] only works if the running instance is "
+"connected to a debugging server (i.e. an editor instance). [method "
+"get_stack] will not work in projects exported in release mode, or in "
+"projects exported in debug mode if not connected to a debugging server."
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -861,12 +866,16 @@ msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
-"Prints a stack track at code location, only works when running with debugger "
-"turned on.\n"
+"Prints a stack trace at the current code location. See also [method "
+"get_stack].\n"
"Output in the console would look something like this:\n"
"[codeblock]\n"
"Frame 0 - res://test.gd:16 in function '_process'\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] [method print_stack] only works if the running instance is "
+"connected to a debugging server (i.e. an editor instance). [method "
+"print_stack] will not work in projects exported in release mode, or in "
+"projects exported in debug mode if not connected to a debugging server."
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -3477,6 +3486,26 @@ msgid "Hints that an image is compressed using lossless compression."
msgstr ""
#: doc/classes/@GlobalScope.xml
+msgid ""
+"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:\n"
+"[codeblock]\n"
+"hint_string = \"%s:\" % [TYPE_INT] # Array of inteters.\n"
+"hint_string = \"%s:%s:\" % [TYPE_ARRAY, TYPE_REAL] # Two-dimensional array "
+"of floats.\n"
+"hint_string = \"%s/%s:Resource\" % [TYPE_OBJECT, TYPE_OBJECT] # Array of "
+"resources.\n"
+"hint_string = \"%s:%s/%s:Resource\" % [TYPE_ARRAY, TYPE_OBJECT, TYPE_OBJECT] "
+"# Two-dimensional array of resources.\n"
+"[/codeblock]\n"
+"[b]Note:[/b] The final colon is required to specify for properly detecting "
+"built-in types."
+msgstr ""
+
+#: doc/classes/@GlobalScope.xml
msgid "The property is serialized and saved in the scene file (default)."
msgstr ""
@@ -4161,8 +4190,7 @@ msgstr ""
#: doc/classes/AudioStreamPlayer.xml doc/classes/Button.xml
#: doc/classes/CanvasLayer.xml doc/classes/CollisionShape2D.xml
#: doc/classes/ColorRect.xml doc/classes/Input.xml doc/classes/InputEvent.xml
-#: doc/classes/InputEventAction.xml doc/classes/Label.xml
-#: doc/classes/Particles2D.xml doc/classes/Timer.xml
+#: doc/classes/InputEventAction.xml doc/classes/Label.xml doc/classes/Timer.xml
#: doc/classes/VisibilityNotifier2D.xml
msgid "2D Dodge The Creeps Demo"
msgstr ""
@@ -7079,7 +7107,10 @@ msgid ""
"var array = []\n"
"array.resize(10)\n"
"array.fill(0) # Initialize the 10 elements to 0.\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] If [code]value[/code] is of a reference type ([Object]-derived, "
+"[Array], [Dictionary], etc.) then the array is filled with the references to "
+"the same object, i.e. no duplicates are created."
msgstr ""
#: doc/classes/Array.xml doc/classes/PoolByteArray.xml
@@ -7264,6 +7295,9 @@ msgstr ""
#: doc/classes/Array.xml
msgid ""
"Sorts the array.\n"
+"[b]Note:[/b] The sorting algorithm used is not [url=https://en.wikipedia.org/"
+"wiki/Sorting_algorithm#Stability]stable[/url]. This means that values "
+"considered equal may have their order changed when using [method sort].\n"
"[b]Note:[/b] Strings are sorted in alphabetical order (as opposed to natural "
"order). This may lead to unexpected behavior when sorting an array of "
"strings ending with a sequence of numbers. Consider the following example:\n"
@@ -7283,9 +7317,13 @@ msgid ""
"For two elements [code]a[/code] and [code]b[/code], if the given method "
"returns [code]true[/code], element [code]b[/code] will be after element "
"[code]a[/code] in the array.\n"
+"[b]Note:[/b] The sorting algorithm used is not [url=https://en.wikipedia.org/"
+"wiki/Sorting_algorithm#Stability]stable[/url]. This means that values "
+"considered equal may have their order changed when using [method "
+"sort_custom].\n"
"[b]Note:[/b] You cannot randomize the return value as the heapsort algorithm "
-"expects a deterministic result. Doing so will result in unexpected "
-"behavior.\n"
+"expects a deterministic result. Randomizing the return value will result in "
+"unexpected behavior.\n"
"[codeblock]\n"
"class MyCustomSorter:\n"
" static func sort_ascending(a, b):\n"
@@ -9923,10 +9961,9 @@ msgstr ""
#: doc/classes/AudioStreamGeneratorPlayback.xml
msgid ""
-"Returns the number of audio data frames left to play. If this returned "
-"number reaches [code]0[/code], the audio will stop playing until frames are "
-"added again. Therefore, make sure your script can always generate and push "
-"new audio frames fast enough to avoid audio cracking."
+"Returns the number of frames that can be pushed to the audio sample data "
+"buffer without overflowing it. If the result is [code]0[/code], the buffer "
+"is full."
msgstr ""
#: doc/classes/AudioStreamGeneratorPlayback.xml
@@ -10458,14 +10495,14 @@ msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
"Node for back-buffering the currently-displayed screen. The region defined "
-"in the BackBufferCopy node is buffered with the content of the screen it "
+"in the [BackBufferCopy] node is buffered with the content of the screen it "
"covers, or the entire screen according to the copy mode set. Use the "
"[code]texture(SCREEN_TEXTURE, ...)[/code] function in your shader scripts to "
"access the buffer.\n"
"[b]Note:[/b] Since this node inherits from [Node2D] (and not [Control]), "
"anchors and margins won't apply to child [Control]-derived nodes. This can "
"be problematic when resizing the window. To avoid this, add [Control]-"
-"derived nodes as [i]siblings[/i] to the BackBufferCopy node instead of "
+"derived nodes as [i]siblings[/i] to the [BackBufferCopy] node instead of "
"adding them as children."
msgstr ""
@@ -10475,22 +10512,22 @@ msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
-"The area covered by the BackBufferCopy. Only used if [member copy_mode] is "
+"The area covered by the [BackBufferCopy]. Only used if [member copy_mode] is "
"[constant COPY_MODE_RECT]."
msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
-"Disables the buffering mode. This means the BackBufferCopy node will "
+"Disables the buffering mode. This means the [BackBufferCopy] node will "
"directly use the portion of screen it covers."
msgstr ""
#: doc/classes/BackBufferCopy.xml
-msgid "BackBufferCopy buffers a rectangular region."
+msgid "[BackBufferCopy] buffers a rectangular region."
msgstr ""
#: doc/classes/BackBufferCopy.xml
-msgid "BackBufferCopy buffers the entire screen."
+msgid "[BackBufferCopy] buffers the entire screen."
msgstr ""
#: doc/classes/BakedLightmap.xml
@@ -19270,6 +19307,14 @@ msgid "Cylinder shape for collisions."
msgstr ""
#: doc/classes/CylinderShape.xml
+msgid ""
+"Cylinder shape for collisions.\n"
+"[b]Note:[/b] When using GodotPhysics instead of the default Bullet physics "
+"engine, there are several known bugs with cylinder collision shapes. Using "
+"[CapsuleShape] or [BoxShape] instead is recommended."
+msgstr ""
+
+#: doc/classes/CylinderShape.xml
msgid "The cylinder's height."
msgstr ""
@@ -22102,7 +22147,10 @@ msgid ""
"[/codeblock]\n"
"[b]Note:[/b] The script is run in the Editor context, which means the output "
"is visible in the console window started with the Editor (stdout) instead of "
-"the usual Godot [b]Output[/b] dock."
+"the usual Godot [b]Output[/b] dock.\n"
+"[b]Note:[/b] EditorScript is reference counted, meaning it is destroyed when "
+"nothing references it. This can cause errors during asynchronous operations "
+"if there are no references to the script."
msgstr ""
#: doc/classes/EditorScript.xml
@@ -32814,7 +32862,9 @@ msgid ""
"The size of the light in Godot units. Only considered in baked lightmaps and "
"only if [member light_bake_mode] is set to [constant BAKE_ALL]. Increasing "
"this value will make the shadows appear blurrier. This can be used to "
-"simulate area lights to an extent."
+"simulate area lights to an extent.\n"
+"[b]Note:[/b] [member light_size] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/Light.xml
@@ -36112,7 +36162,10 @@ msgid ""
"use the [method get_next_location] function once every physics frame to "
"update the internal path logic of the NavigationAgent. The returned vector "
"position from this function should be used as the next movement position for "
-"the agent's parent Node."
+"the agent's parent Node.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues."
msgstr ""
#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
@@ -36360,7 +36413,10 @@ msgid ""
"use the [method get_next_location] function once every physics frame to "
"update the internal path logic of the NavigationAgent. The returned vector "
"position from this function should be used as the next movement position for "
-"the agent's parent Node."
+"the agent's parent Node.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues."
msgstr ""
#: doc/classes/NavigationAgent2D.xml
@@ -37070,6 +37126,9 @@ msgid ""
"modified velocity as-is might lead to pushing and agent outside of a "
"navigable area. This is a limitation of the collision avoidance system, any "
"more complex situation may require the use of the physics engine.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues.\n"
"This server keeps tracks of any call and executes them during the sync "
"phase. This means that you can request any change to the map, using any "
"thread, without worrying."
@@ -39876,7 +39935,9 @@ msgid ""
"The light's radius. Note that the effectively lit area may appear to be "
"smaller depending on the [member omni_attenuation] in use. No matter the "
"[member omni_attenuation] in use, the light will never reach anything "
-"outside this radius."
+"outside this radius.\n"
+"[b]Note:[/b] [member omni_range] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -40387,11 +40448,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] cache data directory according to the operating "
-"system's standards. On desktop platforms, this path can be overridden by "
-"setting the [code]XDG_CACHE_HOME[/code] environment variable before starting "
-"the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in "
-"Godot projects[/url] in the documentation for more information. See also "
-"[method get_config_dir] and [method get_data_dir].\n"
+"system's standards. On Linux, this path can be overridden by setting the "
+"[code]XDG_CACHE_HOME[/code] environment variable before starting the "
+"project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot "
+"projects[/url] in the documentation for more information. See also [method "
+"get_config_dir] and [method get_data_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -40425,11 +40486,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] user configuration directory according to the "
-"operating system's standards. On desktop platforms, this path can be "
-"overridden by setting the [code]XDG_CONFIG_HOME[/code] environment variable "
-"before starting the project. See [url=$DOCS_URL/tutorials/io/data_paths."
-"html]File paths in Godot projects[/url] in the documentation for more "
-"information. See also [method get_cache_dir] and [method get_data_dir].\n"
+"operating system's standards. On Linux, this path can be overridden by "
+"setting the [code]XDG_CONFIG_HOME[/code] environment variable before "
+"starting the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File "
+"paths in Godot projects[/url] in the documentation for more information. See "
+"also [method get_cache_dir] and [method get_data_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -40451,11 +40512,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] user data directory according to the operating "
-"system's standards. On desktop platforms, this path can be overridden by "
-"setting the [code]XDG_DATA_HOME[/code] environment variable before starting "
-"the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in "
-"Godot projects[/url] in the documentation for more information. See also "
-"[method get_cache_dir] and [method get_config_dir].\n"
+"system's standards. On Linux, this path can be overridden by setting the "
+"[code]XDG_DATA_HOME[/code] environment variable before starting the project. "
+"See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot "
+"projects[/url] in the documentation for more information. See also [method "
+"get_cache_dir] and [method get_config_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -42302,6 +42363,16 @@ msgid "Particle systems (2D)"
msgstr ""
#: doc/classes/Particles2D.xml
+msgid "2D Particles Demo"
+msgstr ""
+
+#: doc/classes/Particles2D.xml
+msgid ""
+"2D Dodge The Creeps Demo (uses GPUParticles2D for the trail behind the "
+"player)"
+msgstr ""
+
+#: doc/classes/Particles2D.xml
msgid "Returns a rectangle containing the positions of all existing particles."
msgstr ""
@@ -49894,15 +49965,22 @@ msgstr ""
#: doc/classes/ProjectSettings.xml
msgid ""
"If [code]true[/code], uses a fast post-processing filter to make banding "
-"significantly less visible. In some cases, debanding may introduce a "
-"slightly noticeable dithering pattern. It's recommended to enable debanding "
-"only when actually needed since the dithering pattern will make lossless-"
-"compressed screenshots larger.\n"
+"significantly less visible in 3D. 2D rendering is [i]not[/i] affected by "
+"debanding unless the [member Environment.background_mode] is [constant "
+"Environment.BG_CANVAS]. In this case, [member rendering/quality/"
+"intended_usage/framebuffer_allocation] must also be set to [b]3D[/b].\n"
+"In some cases, debanding may introduce a slightly noticeable dithering "
+"pattern. It's recommended to enable debanding only when actually needed "
+"since the dithering pattern will make lossless-compressed screenshots "
+"larger.\n"
"[b]Note:[/b] Only available on the GLES3 backend. [member rendering/quality/"
"depth/hdr] must also be [code]true[/code] for debanding to be effective.\n"
"[b]Note:[/b] There are known issues with debanding breaking rendering on "
"mobile platforms. Due to this, it is recommended to leave this option "
-"disabled when targeting mobile platforms."
+"disabled when targeting mobile platforms.\n"
+"[b]Note:[/b] This property is only read when the project starts. To set "
+"debanding at run-time, set [member Viewport.debanding] on the root "
+"[Viewport] instead."
msgstr ""
#: doc/classes/ProjectSettings.xml
@@ -51498,17 +51576,28 @@ msgstr ""
#: modules/regex/doc_classes/RegEx.xml
msgid ""
"Searches the text for the compiled pattern. Returns a [RegExMatch] container "
-"of the first matching result if found, otherwise [code]null[/code]. The "
-"region to search within can be specified without modifying where the start "
-"and end anchor would be."
+"of the first matching result if found, otherwise [code]null[/code].\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegEx.xml
msgid ""
"Searches the text for the compiled pattern. Returns an array of [RegExMatch] "
"containers for each non-overlapping result. If no results were found, an "
-"empty array is returned instead. The region to search within can be "
-"specified without modifying where the start and end anchor would be."
+"empty array is returned instead.\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegEx.xml
@@ -51517,8 +51606,14 @@ msgid ""
"specified string. Escapes and backreferences such as [code]$1[/code] and "
"[code]$name[/code] are expanded and resolved. By default, only the first "
"instance is replaced, but it can be changed for all instances (global "
-"replacement). The region to search within can be specified without modifying "
-"where the start and end anchor would be."
+"replacement).\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegExMatch.xml
@@ -54233,7 +54328,11 @@ msgid "Call a group immediately (calls are normally made on idle)."
msgstr ""
#: doc/classes/SceneTree.xml
-msgid "Call a group only once even if the call is executed many times."
+msgid ""
+"Call a group only once even if the call is executed many times.\n"
+"[b]Note:[/b] Arguments are not taken into account when deciding whether the "
+"call is unique or not. Therefore when the same method is called with "
+"different arguments, only the first call will be performed."
msgstr ""
#: doc/classes/SceneTree.xml
@@ -56070,7 +56169,9 @@ msgid ""
"[b]Note:[/b] Mixed negative scales in 3D are not decomposable from the "
"transformation matrix. Due to the way scale is represented with "
"transformation matrices in Godot, the scale values will either be all "
-"positive or all negative."
+"positive or all negative.\n"
+"[b]Note:[/b] Not all nodes are visually scaled by the [member scale] "
+"property. For example, [Light]s are not visually affected by [member scale]."
msgstr ""
#: doc/classes/Spatial.xml
@@ -57448,7 +57549,10 @@ msgid ""
msgstr ""
#: doc/classes/SpotLight.xml
-msgid "The spotlight's angle in degrees."
+msgid ""
+"The spotlight's angle in degrees.\n"
+"[b]Note:[/b] [member spot_angle] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/SpotLight.xml
@@ -57464,7 +57568,9 @@ msgid ""
"The maximal range that can be reached by the spotlight. Note that the "
"effectively lit area may appear to be smaller depending on the [member "
"spot_attenuation] in use. No matter the [member spot_attenuation] in use, "
-"the light will never reach anything outside this range."
+"the light will never reach anything outside this range.\n"
+"[b]Note:[/b] [member spot_range] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/SpringArm.xml
@@ -66701,10 +66807,15 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
"If [code]true[/code], uses a fast post-processing filter to make banding "
-"significantly less visible. In some cases, debanding may introduce a "
-"slightly noticeable dithering pattern. It's recommended to enable debanding "
-"only when actually needed since the dithering pattern will make lossless-"
-"compressed screenshots larger.\n"
+"significantly less visible in 3D. 2D rendering is [i]not[/i] affected by "
+"debanding unless the [member Environment.background_mode] is [constant "
+"Environment.BG_CANVAS]. In this case, [member usage] must also be set to "
+"[constant USAGE_3D]. See also [member ProjectSettings.rendering/quality/"
+"filters/use_debanding].\n"
+"In some cases, debanding may introduce a slightly noticeable dithering "
+"pattern. It's recommended to enable debanding only when actually needed "
+"since the dithering pattern will make lossless-compressed screenshots "
+"larger.\n"
"[b]Note:[/b] Only available on the GLES3 backend. [member hdr] must also be "
"[code]true[/code] for debanding to be effective."
msgstr ""
@@ -66715,8 +66826,8 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
-"If [code]true[/code], the viewport will disable 3D rendering. For actual "
-"disabling use [code]usage[/code]."
+"If [code]true[/code], the viewport will disable 3D rendering. To actually "
+"disable allocation of 3D buffers, set [member usage] instead."
msgstr ""
#: doc/classes/Viewport.xml
@@ -66868,7 +66979,9 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
-"The rendering mode of viewport.\n"
+"The viewport's rendering mode. This controls which buffers are allocated for "
+"the viewport (2D only, or 2D + 3D). 2D-only options can reduce memory usage "
+"and improve performance slightly, especially on low-end devices.\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."
@@ -67400,6 +67513,22 @@ msgid ""
"render object this [VisualInstance] is set to."
msgstr ""
+#: doc/classes/VisualInstance.xml
+msgid ""
+"The sorting offset used by this [VisualInstance]. Adjusting it to a higher "
+"value will make the [VisualInstance] reliably draw on top of other "
+"[VisualInstance]s that are otherwise positioned at the same spot."
+msgstr ""
+
+#: doc/classes/VisualInstance.xml
+msgid ""
+"If [code]true[/code], the object is sorted based on the [AABB] center. "
+"Sorted based on the global position otherwise.\n"
+"The [AABB] center based sorting is generally more accurate for 3D models. "
+"The position based sorting instead allows to better control the drawing "
+"order when working with [Particles] and [CPUParticles]."
+msgstr ""
+
#: modules/visual_script/doc_classes/VisualScript.xml
msgid "A script implemented in the Visual Script programming environment."
msgstr ""
diff --git a/doc/translations/nb.po b/doc/translations/nb.po
index 9a861d8287..3b7f482e48 100644
--- a/doc/translations/nb.po
+++ b/doc/translations/nb.po
@@ -485,7 +485,8 @@ msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
-"Returns an array of dictionaries representing the current call stack.\n"
+"Returns an array of dictionaries representing the current call stack. See "
+"also [method print_stack].\n"
"[codeblock]\n"
"func _ready():\n"
" foo()\n"
@@ -500,7 +501,11 @@ msgid ""
"[codeblock]\n"
"[{function:bar, line:12, source:res://script.gd}, {function:foo, line:9, "
"source:res://script.gd}, {function:_ready, line:6, source:res://script.gd}]\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] [method get_stack] only works if the running instance is "
+"connected to a debugging server (i.e. an editor instance). [method "
+"get_stack] will not work in projects exported in release mode, or in "
+"projects exported in debug mode if not connected to a debugging server."
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -873,12 +878,16 @@ msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
-"Prints a stack track at code location, only works when running with debugger "
-"turned on.\n"
+"Prints a stack trace at the current code location. See also [method "
+"get_stack].\n"
"Output in the console would look something like this:\n"
"[codeblock]\n"
"Frame 0 - res://test.gd:16 in function '_process'\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] [method print_stack] only works if the running instance is "
+"connected to a debugging server (i.e. an editor instance). [method "
+"print_stack] will not work in projects exported in release mode, or in "
+"projects exported in debug mode if not connected to a debugging server."
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -3489,6 +3498,26 @@ msgid "Hints that an image is compressed using lossless compression."
msgstr ""
#: doc/classes/@GlobalScope.xml
+msgid ""
+"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:\n"
+"[codeblock]\n"
+"hint_string = \"%s:\" % [TYPE_INT] # Array of inteters.\n"
+"hint_string = \"%s:%s:\" % [TYPE_ARRAY, TYPE_REAL] # Two-dimensional array "
+"of floats.\n"
+"hint_string = \"%s/%s:Resource\" % [TYPE_OBJECT, TYPE_OBJECT] # Array of "
+"resources.\n"
+"hint_string = \"%s:%s/%s:Resource\" % [TYPE_ARRAY, TYPE_OBJECT, TYPE_OBJECT] "
+"# Two-dimensional array of resources.\n"
+"[/codeblock]\n"
+"[b]Note:[/b] The final colon is required to specify for properly detecting "
+"built-in types."
+msgstr ""
+
+#: doc/classes/@GlobalScope.xml
msgid "The property is serialized and saved in the scene file (default)."
msgstr ""
@@ -4173,8 +4202,7 @@ msgstr ""
#: doc/classes/AudioStreamPlayer.xml doc/classes/Button.xml
#: doc/classes/CanvasLayer.xml doc/classes/CollisionShape2D.xml
#: doc/classes/ColorRect.xml doc/classes/Input.xml doc/classes/InputEvent.xml
-#: doc/classes/InputEventAction.xml doc/classes/Label.xml
-#: doc/classes/Particles2D.xml doc/classes/Timer.xml
+#: doc/classes/InputEventAction.xml doc/classes/Label.xml doc/classes/Timer.xml
#: doc/classes/VisibilityNotifier2D.xml
msgid "2D Dodge The Creeps Demo"
msgstr ""
@@ -7091,7 +7119,10 @@ msgid ""
"var array = []\n"
"array.resize(10)\n"
"array.fill(0) # Initialize the 10 elements to 0.\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] If [code]value[/code] is of a reference type ([Object]-derived, "
+"[Array], [Dictionary], etc.) then the array is filled with the references to "
+"the same object, i.e. no duplicates are created."
msgstr ""
#: doc/classes/Array.xml doc/classes/PoolByteArray.xml
@@ -7276,6 +7307,9 @@ msgstr ""
#: doc/classes/Array.xml
msgid ""
"Sorts the array.\n"
+"[b]Note:[/b] The sorting algorithm used is not [url=https://en.wikipedia.org/"
+"wiki/Sorting_algorithm#Stability]stable[/url]. This means that values "
+"considered equal may have their order changed when using [method sort].\n"
"[b]Note:[/b] Strings are sorted in alphabetical order (as opposed to natural "
"order). This may lead to unexpected behavior when sorting an array of "
"strings ending with a sequence of numbers. Consider the following example:\n"
@@ -7295,9 +7329,13 @@ msgid ""
"For two elements [code]a[/code] and [code]b[/code], if the given method "
"returns [code]true[/code], element [code]b[/code] will be after element "
"[code]a[/code] in the array.\n"
+"[b]Note:[/b] The sorting algorithm used is not [url=https://en.wikipedia.org/"
+"wiki/Sorting_algorithm#Stability]stable[/url]. This means that values "
+"considered equal may have their order changed when using [method "
+"sort_custom].\n"
"[b]Note:[/b] You cannot randomize the return value as the heapsort algorithm "
-"expects a deterministic result. Doing so will result in unexpected "
-"behavior.\n"
+"expects a deterministic result. Randomizing the return value will result in "
+"unexpected behavior.\n"
"[codeblock]\n"
"class MyCustomSorter:\n"
" static func sort_ascending(a, b):\n"
@@ -9935,10 +9973,9 @@ msgstr ""
#: doc/classes/AudioStreamGeneratorPlayback.xml
msgid ""
-"Returns the number of audio data frames left to play. If this returned "
-"number reaches [code]0[/code], the audio will stop playing until frames are "
-"added again. Therefore, make sure your script can always generate and push "
-"new audio frames fast enough to avoid audio cracking."
+"Returns the number of frames that can be pushed to the audio sample data "
+"buffer without overflowing it. If the result is [code]0[/code], the buffer "
+"is full."
msgstr ""
#: doc/classes/AudioStreamGeneratorPlayback.xml
@@ -10470,14 +10507,14 @@ msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
"Node for back-buffering the currently-displayed screen. The region defined "
-"in the BackBufferCopy node is buffered with the content of the screen it "
+"in the [BackBufferCopy] node is buffered with the content of the screen it "
"covers, or the entire screen according to the copy mode set. Use the "
"[code]texture(SCREEN_TEXTURE, ...)[/code] function in your shader scripts to "
"access the buffer.\n"
"[b]Note:[/b] Since this node inherits from [Node2D] (and not [Control]), "
"anchors and margins won't apply to child [Control]-derived nodes. This can "
"be problematic when resizing the window. To avoid this, add [Control]-"
-"derived nodes as [i]siblings[/i] to the BackBufferCopy node instead of "
+"derived nodes as [i]siblings[/i] to the [BackBufferCopy] node instead of "
"adding them as children."
msgstr ""
@@ -10487,22 +10524,22 @@ msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
-"The area covered by the BackBufferCopy. Only used if [member copy_mode] is "
+"The area covered by the [BackBufferCopy]. Only used if [member copy_mode] is "
"[constant COPY_MODE_RECT]."
msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
-"Disables the buffering mode. This means the BackBufferCopy node will "
+"Disables the buffering mode. This means the [BackBufferCopy] node will "
"directly use the portion of screen it covers."
msgstr ""
#: doc/classes/BackBufferCopy.xml
-msgid "BackBufferCopy buffers a rectangular region."
+msgid "[BackBufferCopy] buffers a rectangular region."
msgstr ""
#: doc/classes/BackBufferCopy.xml
-msgid "BackBufferCopy buffers the entire screen."
+msgid "[BackBufferCopy] buffers the entire screen."
msgstr ""
#: doc/classes/BakedLightmap.xml
@@ -19282,6 +19319,14 @@ msgid "Cylinder shape for collisions."
msgstr ""
#: doc/classes/CylinderShape.xml
+msgid ""
+"Cylinder shape for collisions.\n"
+"[b]Note:[/b] When using GodotPhysics instead of the default Bullet physics "
+"engine, there are several known bugs with cylinder collision shapes. Using "
+"[CapsuleShape] or [BoxShape] instead is recommended."
+msgstr ""
+
+#: doc/classes/CylinderShape.xml
msgid "The cylinder's height."
msgstr ""
@@ -22114,7 +22159,10 @@ msgid ""
"[/codeblock]\n"
"[b]Note:[/b] The script is run in the Editor context, which means the output "
"is visible in the console window started with the Editor (stdout) instead of "
-"the usual Godot [b]Output[/b] dock."
+"the usual Godot [b]Output[/b] dock.\n"
+"[b]Note:[/b] EditorScript is reference counted, meaning it is destroyed when "
+"nothing references it. This can cause errors during asynchronous operations "
+"if there are no references to the script."
msgstr ""
#: doc/classes/EditorScript.xml
@@ -32826,7 +32874,9 @@ msgid ""
"The size of the light in Godot units. Only considered in baked lightmaps and "
"only if [member light_bake_mode] is set to [constant BAKE_ALL]. Increasing "
"this value will make the shadows appear blurrier. This can be used to "
-"simulate area lights to an extent."
+"simulate area lights to an extent.\n"
+"[b]Note:[/b] [member light_size] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/Light.xml
@@ -36124,7 +36174,10 @@ msgid ""
"use the [method get_next_location] function once every physics frame to "
"update the internal path logic of the NavigationAgent. The returned vector "
"position from this function should be used as the next movement position for "
-"the agent's parent Node."
+"the agent's parent Node.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues."
msgstr ""
#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
@@ -36372,7 +36425,10 @@ msgid ""
"use the [method get_next_location] function once every physics frame to "
"update the internal path logic of the NavigationAgent. The returned vector "
"position from this function should be used as the next movement position for "
-"the agent's parent Node."
+"the agent's parent Node.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues."
msgstr ""
#: doc/classes/NavigationAgent2D.xml
@@ -37082,6 +37138,9 @@ msgid ""
"modified velocity as-is might lead to pushing and agent outside of a "
"navigable area. This is a limitation of the collision avoidance system, any "
"more complex situation may require the use of the physics engine.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues.\n"
"This server keeps tracks of any call and executes them during the sync "
"phase. This means that you can request any change to the map, using any "
"thread, without worrying."
@@ -39888,7 +39947,9 @@ msgid ""
"The light's radius. Note that the effectively lit area may appear to be "
"smaller depending on the [member omni_attenuation] in use. No matter the "
"[member omni_attenuation] in use, the light will never reach anything "
-"outside this radius."
+"outside this radius.\n"
+"[b]Note:[/b] [member omni_range] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -40399,11 +40460,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] cache data directory according to the operating "
-"system's standards. On desktop platforms, this path can be overridden by "
-"setting the [code]XDG_CACHE_HOME[/code] environment variable before starting "
-"the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in "
-"Godot projects[/url] in the documentation for more information. See also "
-"[method get_config_dir] and [method get_data_dir].\n"
+"system's standards. On Linux, this path can be overridden by setting the "
+"[code]XDG_CACHE_HOME[/code] environment variable before starting the "
+"project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot "
+"projects[/url] in the documentation for more information. See also [method "
+"get_config_dir] and [method get_data_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -40437,11 +40498,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] user configuration directory according to the "
-"operating system's standards. On desktop platforms, this path can be "
-"overridden by setting the [code]XDG_CONFIG_HOME[/code] environment variable "
-"before starting the project. See [url=$DOCS_URL/tutorials/io/data_paths."
-"html]File paths in Godot projects[/url] in the documentation for more "
-"information. See also [method get_cache_dir] and [method get_data_dir].\n"
+"operating system's standards. On Linux, this path can be overridden by "
+"setting the [code]XDG_CONFIG_HOME[/code] environment variable before "
+"starting the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File "
+"paths in Godot projects[/url] in the documentation for more information. See "
+"also [method get_cache_dir] and [method get_data_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -40463,11 +40524,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] user data directory according to the operating "
-"system's standards. On desktop platforms, this path can be overridden by "
-"setting the [code]XDG_DATA_HOME[/code] environment variable before starting "
-"the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in "
-"Godot projects[/url] in the documentation for more information. See also "
-"[method get_cache_dir] and [method get_config_dir].\n"
+"system's standards. On Linux, this path can be overridden by setting the "
+"[code]XDG_DATA_HOME[/code] environment variable before starting the project. "
+"See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot "
+"projects[/url] in the documentation for more information. See also [method "
+"get_cache_dir] and [method get_config_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -42314,6 +42375,16 @@ msgid "Particle systems (2D)"
msgstr ""
#: doc/classes/Particles2D.xml
+msgid "2D Particles Demo"
+msgstr ""
+
+#: doc/classes/Particles2D.xml
+msgid ""
+"2D Dodge The Creeps Demo (uses GPUParticles2D for the trail behind the "
+"player)"
+msgstr ""
+
+#: doc/classes/Particles2D.xml
msgid "Returns a rectangle containing the positions of all existing particles."
msgstr ""
@@ -49906,15 +49977,22 @@ msgstr ""
#: doc/classes/ProjectSettings.xml
msgid ""
"If [code]true[/code], uses a fast post-processing filter to make banding "
-"significantly less visible. In some cases, debanding may introduce a "
-"slightly noticeable dithering pattern. It's recommended to enable debanding "
-"only when actually needed since the dithering pattern will make lossless-"
-"compressed screenshots larger.\n"
+"significantly less visible in 3D. 2D rendering is [i]not[/i] affected by "
+"debanding unless the [member Environment.background_mode] is [constant "
+"Environment.BG_CANVAS]. In this case, [member rendering/quality/"
+"intended_usage/framebuffer_allocation] must also be set to [b]3D[/b].\n"
+"In some cases, debanding may introduce a slightly noticeable dithering "
+"pattern. It's recommended to enable debanding only when actually needed "
+"since the dithering pattern will make lossless-compressed screenshots "
+"larger.\n"
"[b]Note:[/b] Only available on the GLES3 backend. [member rendering/quality/"
"depth/hdr] must also be [code]true[/code] for debanding to be effective.\n"
"[b]Note:[/b] There are known issues with debanding breaking rendering on "
"mobile platforms. Due to this, it is recommended to leave this option "
-"disabled when targeting mobile platforms."
+"disabled when targeting mobile platforms.\n"
+"[b]Note:[/b] This property is only read when the project starts. To set "
+"debanding at run-time, set [member Viewport.debanding] on the root "
+"[Viewport] instead."
msgstr ""
#: doc/classes/ProjectSettings.xml
@@ -51510,17 +51588,28 @@ msgstr ""
#: modules/regex/doc_classes/RegEx.xml
msgid ""
"Searches the text for the compiled pattern. Returns a [RegExMatch] container "
-"of the first matching result if found, otherwise [code]null[/code]. The "
-"region to search within can be specified without modifying where the start "
-"and end anchor would be."
+"of the first matching result if found, otherwise [code]null[/code].\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegEx.xml
msgid ""
"Searches the text for the compiled pattern. Returns an array of [RegExMatch] "
"containers for each non-overlapping result. If no results were found, an "
-"empty array is returned instead. The region to search within can be "
-"specified without modifying where the start and end anchor would be."
+"empty array is returned instead.\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegEx.xml
@@ -51529,8 +51618,14 @@ msgid ""
"specified string. Escapes and backreferences such as [code]$1[/code] and "
"[code]$name[/code] are expanded and resolved. By default, only the first "
"instance is replaced, but it can be changed for all instances (global "
-"replacement). The region to search within can be specified without modifying "
-"where the start and end anchor would be."
+"replacement).\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegExMatch.xml
@@ -54245,7 +54340,11 @@ msgid "Call a group immediately (calls are normally made on idle)."
msgstr ""
#: doc/classes/SceneTree.xml
-msgid "Call a group only once even if the call is executed many times."
+msgid ""
+"Call a group only once even if the call is executed many times.\n"
+"[b]Note:[/b] Arguments are not taken into account when deciding whether the "
+"call is unique or not. Therefore when the same method is called with "
+"different arguments, only the first call will be performed."
msgstr ""
#: doc/classes/SceneTree.xml
@@ -56082,7 +56181,9 @@ msgid ""
"[b]Note:[/b] Mixed negative scales in 3D are not decomposable from the "
"transformation matrix. Due to the way scale is represented with "
"transformation matrices in Godot, the scale values will either be all "
-"positive or all negative."
+"positive or all negative.\n"
+"[b]Note:[/b] Not all nodes are visually scaled by the [member scale] "
+"property. For example, [Light]s are not visually affected by [member scale]."
msgstr ""
#: doc/classes/Spatial.xml
@@ -57460,7 +57561,10 @@ msgid ""
msgstr ""
#: doc/classes/SpotLight.xml
-msgid "The spotlight's angle in degrees."
+msgid ""
+"The spotlight's angle in degrees.\n"
+"[b]Note:[/b] [member spot_angle] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/SpotLight.xml
@@ -57476,7 +57580,9 @@ msgid ""
"The maximal range that can be reached by the spotlight. Note that the "
"effectively lit area may appear to be smaller depending on the [member "
"spot_attenuation] in use. No matter the [member spot_attenuation] in use, "
-"the light will never reach anything outside this range."
+"the light will never reach anything outside this range.\n"
+"[b]Note:[/b] [member spot_range] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/SpringArm.xml
@@ -66713,10 +66819,15 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
"If [code]true[/code], uses a fast post-processing filter to make banding "
-"significantly less visible. In some cases, debanding may introduce a "
-"slightly noticeable dithering pattern. It's recommended to enable debanding "
-"only when actually needed since the dithering pattern will make lossless-"
-"compressed screenshots larger.\n"
+"significantly less visible in 3D. 2D rendering is [i]not[/i] affected by "
+"debanding unless the [member Environment.background_mode] is [constant "
+"Environment.BG_CANVAS]. In this case, [member usage] must also be set to "
+"[constant USAGE_3D]. See also [member ProjectSettings.rendering/quality/"
+"filters/use_debanding].\n"
+"In some cases, debanding may introduce a slightly noticeable dithering "
+"pattern. It's recommended to enable debanding only when actually needed "
+"since the dithering pattern will make lossless-compressed screenshots "
+"larger.\n"
"[b]Note:[/b] Only available on the GLES3 backend. [member hdr] must also be "
"[code]true[/code] for debanding to be effective."
msgstr ""
@@ -66727,8 +66838,8 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
-"If [code]true[/code], the viewport will disable 3D rendering. For actual "
-"disabling use [code]usage[/code]."
+"If [code]true[/code], the viewport will disable 3D rendering. To actually "
+"disable allocation of 3D buffers, set [member usage] instead."
msgstr ""
#: doc/classes/Viewport.xml
@@ -66880,7 +66991,9 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
-"The rendering mode of viewport.\n"
+"The viewport's rendering mode. This controls which buffers are allocated for "
+"the viewport (2D only, or 2D + 3D). 2D-only options can reduce memory usage "
+"and improve performance slightly, especially on low-end devices.\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."
@@ -67412,6 +67525,22 @@ msgid ""
"render object this [VisualInstance] is set to."
msgstr ""
+#: doc/classes/VisualInstance.xml
+msgid ""
+"The sorting offset used by this [VisualInstance]. Adjusting it to a higher "
+"value will make the [VisualInstance] reliably draw on top of other "
+"[VisualInstance]s that are otherwise positioned at the same spot."
+msgstr ""
+
+#: doc/classes/VisualInstance.xml
+msgid ""
+"If [code]true[/code], the object is sorted based on the [AABB] center. "
+"Sorted based on the global position otherwise.\n"
+"The [AABB] center based sorting is generally more accurate for 3D models. "
+"The position based sorting instead allows to better control the drawing "
+"order when working with [Particles] and [CPUParticles]."
+msgstr ""
+
#: modules/visual_script/doc_classes/VisualScript.xml
msgid "A script implemented in the Visual Script programming environment."
msgstr ""
diff --git a/doc/translations/ne.po b/doc/translations/ne.po
index 84cf5c569c..c616f7b4e1 100644
--- a/doc/translations/ne.po
+++ b/doc/translations/ne.po
@@ -473,7 +473,8 @@ msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
-"Returns an array of dictionaries representing the current call stack.\n"
+"Returns an array of dictionaries representing the current call stack. See "
+"also [method print_stack].\n"
"[codeblock]\n"
"func _ready():\n"
" foo()\n"
@@ -488,7 +489,11 @@ msgid ""
"[codeblock]\n"
"[{function:bar, line:12, source:res://script.gd}, {function:foo, line:9, "
"source:res://script.gd}, {function:_ready, line:6, source:res://script.gd}]\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] [method get_stack] only works if the running instance is "
+"connected to a debugging server (i.e. an editor instance). [method "
+"get_stack] will not work in projects exported in release mode, or in "
+"projects exported in debug mode if not connected to a debugging server."
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -861,12 +866,16 @@ msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
-"Prints a stack track at code location, only works when running with debugger "
-"turned on.\n"
+"Prints a stack trace at the current code location. See also [method "
+"get_stack].\n"
"Output in the console would look something like this:\n"
"[codeblock]\n"
"Frame 0 - res://test.gd:16 in function '_process'\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] [method print_stack] only works if the running instance is "
+"connected to a debugging server (i.e. an editor instance). [method "
+"print_stack] will not work in projects exported in release mode, or in "
+"projects exported in debug mode if not connected to a debugging server."
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -3477,6 +3486,26 @@ msgid "Hints that an image is compressed using lossless compression."
msgstr ""
#: doc/classes/@GlobalScope.xml
+msgid ""
+"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:\n"
+"[codeblock]\n"
+"hint_string = \"%s:\" % [TYPE_INT] # Array of inteters.\n"
+"hint_string = \"%s:%s:\" % [TYPE_ARRAY, TYPE_REAL] # Two-dimensional array "
+"of floats.\n"
+"hint_string = \"%s/%s:Resource\" % [TYPE_OBJECT, TYPE_OBJECT] # Array of "
+"resources.\n"
+"hint_string = \"%s:%s/%s:Resource\" % [TYPE_ARRAY, TYPE_OBJECT, TYPE_OBJECT] "
+"# Two-dimensional array of resources.\n"
+"[/codeblock]\n"
+"[b]Note:[/b] The final colon is required to specify for properly detecting "
+"built-in types."
+msgstr ""
+
+#: doc/classes/@GlobalScope.xml
msgid "The property is serialized and saved in the scene file (default)."
msgstr ""
@@ -4161,8 +4190,7 @@ msgstr ""
#: doc/classes/AudioStreamPlayer.xml doc/classes/Button.xml
#: doc/classes/CanvasLayer.xml doc/classes/CollisionShape2D.xml
#: doc/classes/ColorRect.xml doc/classes/Input.xml doc/classes/InputEvent.xml
-#: doc/classes/InputEventAction.xml doc/classes/Label.xml
-#: doc/classes/Particles2D.xml doc/classes/Timer.xml
+#: doc/classes/InputEventAction.xml doc/classes/Label.xml doc/classes/Timer.xml
#: doc/classes/VisibilityNotifier2D.xml
msgid "2D Dodge The Creeps Demo"
msgstr ""
@@ -7079,7 +7107,10 @@ msgid ""
"var array = []\n"
"array.resize(10)\n"
"array.fill(0) # Initialize the 10 elements to 0.\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] If [code]value[/code] is of a reference type ([Object]-derived, "
+"[Array], [Dictionary], etc.) then the array is filled with the references to "
+"the same object, i.e. no duplicates are created."
msgstr ""
#: doc/classes/Array.xml doc/classes/PoolByteArray.xml
@@ -7264,6 +7295,9 @@ msgstr ""
#: doc/classes/Array.xml
msgid ""
"Sorts the array.\n"
+"[b]Note:[/b] The sorting algorithm used is not [url=https://en.wikipedia.org/"
+"wiki/Sorting_algorithm#Stability]stable[/url]. This means that values "
+"considered equal may have their order changed when using [method sort].\n"
"[b]Note:[/b] Strings are sorted in alphabetical order (as opposed to natural "
"order). This may lead to unexpected behavior when sorting an array of "
"strings ending with a sequence of numbers. Consider the following example:\n"
@@ -7283,9 +7317,13 @@ msgid ""
"For two elements [code]a[/code] and [code]b[/code], if the given method "
"returns [code]true[/code], element [code]b[/code] will be after element "
"[code]a[/code] in the array.\n"
+"[b]Note:[/b] The sorting algorithm used is not [url=https://en.wikipedia.org/"
+"wiki/Sorting_algorithm#Stability]stable[/url]. This means that values "
+"considered equal may have their order changed when using [method "
+"sort_custom].\n"
"[b]Note:[/b] You cannot randomize the return value as the heapsort algorithm "
-"expects a deterministic result. Doing so will result in unexpected "
-"behavior.\n"
+"expects a deterministic result. Randomizing the return value will result in "
+"unexpected behavior.\n"
"[codeblock]\n"
"class MyCustomSorter:\n"
" static func sort_ascending(a, b):\n"
@@ -9923,10 +9961,9 @@ msgstr ""
#: doc/classes/AudioStreamGeneratorPlayback.xml
msgid ""
-"Returns the number of audio data frames left to play. If this returned "
-"number reaches [code]0[/code], the audio will stop playing until frames are "
-"added again. Therefore, make sure your script can always generate and push "
-"new audio frames fast enough to avoid audio cracking."
+"Returns the number of frames that can be pushed to the audio sample data "
+"buffer without overflowing it. If the result is [code]0[/code], the buffer "
+"is full."
msgstr ""
#: doc/classes/AudioStreamGeneratorPlayback.xml
@@ -10458,14 +10495,14 @@ msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
"Node for back-buffering the currently-displayed screen. The region defined "
-"in the BackBufferCopy node is buffered with the content of the screen it "
+"in the [BackBufferCopy] node is buffered with the content of the screen it "
"covers, or the entire screen according to the copy mode set. Use the "
"[code]texture(SCREEN_TEXTURE, ...)[/code] function in your shader scripts to "
"access the buffer.\n"
"[b]Note:[/b] Since this node inherits from [Node2D] (and not [Control]), "
"anchors and margins won't apply to child [Control]-derived nodes. This can "
"be problematic when resizing the window. To avoid this, add [Control]-"
-"derived nodes as [i]siblings[/i] to the BackBufferCopy node instead of "
+"derived nodes as [i]siblings[/i] to the [BackBufferCopy] node instead of "
"adding them as children."
msgstr ""
@@ -10475,22 +10512,22 @@ msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
-"The area covered by the BackBufferCopy. Only used if [member copy_mode] is "
+"The area covered by the [BackBufferCopy]. Only used if [member copy_mode] is "
"[constant COPY_MODE_RECT]."
msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
-"Disables the buffering mode. This means the BackBufferCopy node will "
+"Disables the buffering mode. This means the [BackBufferCopy] node will "
"directly use the portion of screen it covers."
msgstr ""
#: doc/classes/BackBufferCopy.xml
-msgid "BackBufferCopy buffers a rectangular region."
+msgid "[BackBufferCopy] buffers a rectangular region."
msgstr ""
#: doc/classes/BackBufferCopy.xml
-msgid "BackBufferCopy buffers the entire screen."
+msgid "[BackBufferCopy] buffers the entire screen."
msgstr ""
#: doc/classes/BakedLightmap.xml
@@ -19270,6 +19307,14 @@ msgid "Cylinder shape for collisions."
msgstr ""
#: doc/classes/CylinderShape.xml
+msgid ""
+"Cylinder shape for collisions.\n"
+"[b]Note:[/b] When using GodotPhysics instead of the default Bullet physics "
+"engine, there are several known bugs with cylinder collision shapes. Using "
+"[CapsuleShape] or [BoxShape] instead is recommended."
+msgstr ""
+
+#: doc/classes/CylinderShape.xml
msgid "The cylinder's height."
msgstr ""
@@ -22102,7 +22147,10 @@ msgid ""
"[/codeblock]\n"
"[b]Note:[/b] The script is run in the Editor context, which means the output "
"is visible in the console window started with the Editor (stdout) instead of "
-"the usual Godot [b]Output[/b] dock."
+"the usual Godot [b]Output[/b] dock.\n"
+"[b]Note:[/b] EditorScript is reference counted, meaning it is destroyed when "
+"nothing references it. This can cause errors during asynchronous operations "
+"if there are no references to the script."
msgstr ""
#: doc/classes/EditorScript.xml
@@ -32814,7 +32862,9 @@ msgid ""
"The size of the light in Godot units. Only considered in baked lightmaps and "
"only if [member light_bake_mode] is set to [constant BAKE_ALL]. Increasing "
"this value will make the shadows appear blurrier. This can be used to "
-"simulate area lights to an extent."
+"simulate area lights to an extent.\n"
+"[b]Note:[/b] [member light_size] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/Light.xml
@@ -36112,7 +36162,10 @@ msgid ""
"use the [method get_next_location] function once every physics frame to "
"update the internal path logic of the NavigationAgent. The returned vector "
"position from this function should be used as the next movement position for "
-"the agent's parent Node."
+"the agent's parent Node.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues."
msgstr ""
#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
@@ -36360,7 +36413,10 @@ msgid ""
"use the [method get_next_location] function once every physics frame to "
"update the internal path logic of the NavigationAgent. The returned vector "
"position from this function should be used as the next movement position for "
-"the agent's parent Node."
+"the agent's parent Node.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues."
msgstr ""
#: doc/classes/NavigationAgent2D.xml
@@ -37070,6 +37126,9 @@ msgid ""
"modified velocity as-is might lead to pushing and agent outside of a "
"navigable area. This is a limitation of the collision avoidance system, any "
"more complex situation may require the use of the physics engine.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues.\n"
"This server keeps tracks of any call and executes them during the sync "
"phase. This means that you can request any change to the map, using any "
"thread, without worrying."
@@ -39876,7 +39935,9 @@ msgid ""
"The light's radius. Note that the effectively lit area may appear to be "
"smaller depending on the [member omni_attenuation] in use. No matter the "
"[member omni_attenuation] in use, the light will never reach anything "
-"outside this radius."
+"outside this radius.\n"
+"[b]Note:[/b] [member omni_range] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -40387,11 +40448,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] cache data directory according to the operating "
-"system's standards. On desktop platforms, this path can be overridden by "
-"setting the [code]XDG_CACHE_HOME[/code] environment variable before starting "
-"the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in "
-"Godot projects[/url] in the documentation for more information. See also "
-"[method get_config_dir] and [method get_data_dir].\n"
+"system's standards. On Linux, this path can be overridden by setting the "
+"[code]XDG_CACHE_HOME[/code] environment variable before starting the "
+"project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot "
+"projects[/url] in the documentation for more information. See also [method "
+"get_config_dir] and [method get_data_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -40425,11 +40486,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] user configuration directory according to the "
-"operating system's standards. On desktop platforms, this path can be "
-"overridden by setting the [code]XDG_CONFIG_HOME[/code] environment variable "
-"before starting the project. See [url=$DOCS_URL/tutorials/io/data_paths."
-"html]File paths in Godot projects[/url] in the documentation for more "
-"information. See also [method get_cache_dir] and [method get_data_dir].\n"
+"operating system's standards. On Linux, this path can be overridden by "
+"setting the [code]XDG_CONFIG_HOME[/code] environment variable before "
+"starting the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File "
+"paths in Godot projects[/url] in the documentation for more information. See "
+"also [method get_cache_dir] and [method get_data_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -40451,11 +40512,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] user data directory according to the operating "
-"system's standards. On desktop platforms, this path can be overridden by "
-"setting the [code]XDG_DATA_HOME[/code] environment variable before starting "
-"the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in "
-"Godot projects[/url] in the documentation for more information. See also "
-"[method get_cache_dir] and [method get_config_dir].\n"
+"system's standards. On Linux, this path can be overridden by setting the "
+"[code]XDG_DATA_HOME[/code] environment variable before starting the project. "
+"See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot "
+"projects[/url] in the documentation for more information. See also [method "
+"get_cache_dir] and [method get_config_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -42302,6 +42363,16 @@ msgid "Particle systems (2D)"
msgstr ""
#: doc/classes/Particles2D.xml
+msgid "2D Particles Demo"
+msgstr ""
+
+#: doc/classes/Particles2D.xml
+msgid ""
+"2D Dodge The Creeps Demo (uses GPUParticles2D for the trail behind the "
+"player)"
+msgstr ""
+
+#: doc/classes/Particles2D.xml
msgid "Returns a rectangle containing the positions of all existing particles."
msgstr ""
@@ -49894,15 +49965,22 @@ msgstr ""
#: doc/classes/ProjectSettings.xml
msgid ""
"If [code]true[/code], uses a fast post-processing filter to make banding "
-"significantly less visible. In some cases, debanding may introduce a "
-"slightly noticeable dithering pattern. It's recommended to enable debanding "
-"only when actually needed since the dithering pattern will make lossless-"
-"compressed screenshots larger.\n"
+"significantly less visible in 3D. 2D rendering is [i]not[/i] affected by "
+"debanding unless the [member Environment.background_mode] is [constant "
+"Environment.BG_CANVAS]. In this case, [member rendering/quality/"
+"intended_usage/framebuffer_allocation] must also be set to [b]3D[/b].\n"
+"In some cases, debanding may introduce a slightly noticeable dithering "
+"pattern. It's recommended to enable debanding only when actually needed "
+"since the dithering pattern will make lossless-compressed screenshots "
+"larger.\n"
"[b]Note:[/b] Only available on the GLES3 backend. [member rendering/quality/"
"depth/hdr] must also be [code]true[/code] for debanding to be effective.\n"
"[b]Note:[/b] There are known issues with debanding breaking rendering on "
"mobile platforms. Due to this, it is recommended to leave this option "
-"disabled when targeting mobile platforms."
+"disabled when targeting mobile platforms.\n"
+"[b]Note:[/b] This property is only read when the project starts. To set "
+"debanding at run-time, set [member Viewport.debanding] on the root "
+"[Viewport] instead."
msgstr ""
#: doc/classes/ProjectSettings.xml
@@ -51498,17 +51576,28 @@ msgstr ""
#: modules/regex/doc_classes/RegEx.xml
msgid ""
"Searches the text for the compiled pattern. Returns a [RegExMatch] container "
-"of the first matching result if found, otherwise [code]null[/code]. The "
-"region to search within can be specified without modifying where the start "
-"and end anchor would be."
+"of the first matching result if found, otherwise [code]null[/code].\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegEx.xml
msgid ""
"Searches the text for the compiled pattern. Returns an array of [RegExMatch] "
"containers for each non-overlapping result. If no results were found, an "
-"empty array is returned instead. The region to search within can be "
-"specified without modifying where the start and end anchor would be."
+"empty array is returned instead.\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegEx.xml
@@ -51517,8 +51606,14 @@ msgid ""
"specified string. Escapes and backreferences such as [code]$1[/code] and "
"[code]$name[/code] are expanded and resolved. By default, only the first "
"instance is replaced, but it can be changed for all instances (global "
-"replacement). The region to search within can be specified without modifying "
-"where the start and end anchor would be."
+"replacement).\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegExMatch.xml
@@ -54233,7 +54328,11 @@ msgid "Call a group immediately (calls are normally made on idle)."
msgstr ""
#: doc/classes/SceneTree.xml
-msgid "Call a group only once even if the call is executed many times."
+msgid ""
+"Call a group only once even if the call is executed many times.\n"
+"[b]Note:[/b] Arguments are not taken into account when deciding whether the "
+"call is unique or not. Therefore when the same method is called with "
+"different arguments, only the first call will be performed."
msgstr ""
#: doc/classes/SceneTree.xml
@@ -56070,7 +56169,9 @@ msgid ""
"[b]Note:[/b] Mixed negative scales in 3D are not decomposable from the "
"transformation matrix. Due to the way scale is represented with "
"transformation matrices in Godot, the scale values will either be all "
-"positive or all negative."
+"positive or all negative.\n"
+"[b]Note:[/b] Not all nodes are visually scaled by the [member scale] "
+"property. For example, [Light]s are not visually affected by [member scale]."
msgstr ""
#: doc/classes/Spatial.xml
@@ -57448,7 +57549,10 @@ msgid ""
msgstr ""
#: doc/classes/SpotLight.xml
-msgid "The spotlight's angle in degrees."
+msgid ""
+"The spotlight's angle in degrees.\n"
+"[b]Note:[/b] [member spot_angle] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/SpotLight.xml
@@ -57464,7 +57568,9 @@ msgid ""
"The maximal range that can be reached by the spotlight. Note that the "
"effectively lit area may appear to be smaller depending on the [member "
"spot_attenuation] in use. No matter the [member spot_attenuation] in use, "
-"the light will never reach anything outside this range."
+"the light will never reach anything outside this range.\n"
+"[b]Note:[/b] [member spot_range] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/SpringArm.xml
@@ -66701,10 +66807,15 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
"If [code]true[/code], uses a fast post-processing filter to make banding "
-"significantly less visible. In some cases, debanding may introduce a "
-"slightly noticeable dithering pattern. It's recommended to enable debanding "
-"only when actually needed since the dithering pattern will make lossless-"
-"compressed screenshots larger.\n"
+"significantly less visible in 3D. 2D rendering is [i]not[/i] affected by "
+"debanding unless the [member Environment.background_mode] is [constant "
+"Environment.BG_CANVAS]. In this case, [member usage] must also be set to "
+"[constant USAGE_3D]. See also [member ProjectSettings.rendering/quality/"
+"filters/use_debanding].\n"
+"In some cases, debanding may introduce a slightly noticeable dithering "
+"pattern. It's recommended to enable debanding only when actually needed "
+"since the dithering pattern will make lossless-compressed screenshots "
+"larger.\n"
"[b]Note:[/b] Only available on the GLES3 backend. [member hdr] must also be "
"[code]true[/code] for debanding to be effective."
msgstr ""
@@ -66715,8 +66826,8 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
-"If [code]true[/code], the viewport will disable 3D rendering. For actual "
-"disabling use [code]usage[/code]."
+"If [code]true[/code], the viewport will disable 3D rendering. To actually "
+"disable allocation of 3D buffers, set [member usage] instead."
msgstr ""
#: doc/classes/Viewport.xml
@@ -66868,7 +66979,9 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
-"The rendering mode of viewport.\n"
+"The viewport's rendering mode. This controls which buffers are allocated for "
+"the viewport (2D only, or 2D + 3D). 2D-only options can reduce memory usage "
+"and improve performance slightly, especially on low-end devices.\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."
@@ -67400,6 +67513,22 @@ msgid ""
"render object this [VisualInstance] is set to."
msgstr ""
+#: doc/classes/VisualInstance.xml
+msgid ""
+"The sorting offset used by this [VisualInstance]. Adjusting it to a higher "
+"value will make the [VisualInstance] reliably draw on top of other "
+"[VisualInstance]s that are otherwise positioned at the same spot."
+msgstr ""
+
+#: doc/classes/VisualInstance.xml
+msgid ""
+"If [code]true[/code], the object is sorted based on the [AABB] center. "
+"Sorted based on the global position otherwise.\n"
+"The [AABB] center based sorting is generally more accurate for 3D models. "
+"The position based sorting instead allows to better control the drawing "
+"order when working with [Particles] and [CPUParticles]."
+msgstr ""
+
#: modules/visual_script/doc_classes/VisualScript.xml
msgid "A script implemented in the Visual Script programming environment."
msgstr ""
diff --git a/doc/translations/nl.po b/doc/translations/nl.po
index 6b89702dec..cf40d032cf 100644
--- a/doc/translations/nl.po
+++ b/doc/translations/nl.po
@@ -535,7 +535,8 @@ msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
-"Returns an array of dictionaries representing the current call stack.\n"
+"Returns an array of dictionaries representing the current call stack. See "
+"also [method print_stack].\n"
"[codeblock]\n"
"func _ready():\n"
" foo()\n"
@@ -550,7 +551,11 @@ msgid ""
"[codeblock]\n"
"[{function:bar, line:12, source:res://script.gd}, {function:foo, line:9, "
"source:res://script.gd}, {function:_ready, line:6, source:res://script.gd}]\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] [method get_stack] only works if the running instance is "
+"connected to a debugging server (i.e. an editor instance). [method "
+"get_stack] will not work in projects exported in release mode, or in "
+"projects exported in debug mode if not connected to a debugging server."
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -923,12 +928,16 @@ msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
-"Prints a stack track at code location, only works when running with debugger "
-"turned on.\n"
+"Prints a stack trace at the current code location. See also [method "
+"get_stack].\n"
"Output in the console would look something like this:\n"
"[codeblock]\n"
"Frame 0 - res://test.gd:16 in function '_process'\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] [method print_stack] only works if the running instance is "
+"connected to a debugging server (i.e. an editor instance). [method "
+"print_stack] will not work in projects exported in release mode, or in "
+"projects exported in debug mode if not connected to a debugging server."
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -3547,6 +3556,26 @@ msgid "Hints that an image is compressed using lossless compression."
msgstr ""
#: doc/classes/@GlobalScope.xml
+msgid ""
+"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:\n"
+"[codeblock]\n"
+"hint_string = \"%s:\" % [TYPE_INT] # Array of inteters.\n"
+"hint_string = \"%s:%s:\" % [TYPE_ARRAY, TYPE_REAL] # Two-dimensional array "
+"of floats.\n"
+"hint_string = \"%s/%s:Resource\" % [TYPE_OBJECT, TYPE_OBJECT] # Array of "
+"resources.\n"
+"hint_string = \"%s:%s/%s:Resource\" % [TYPE_ARRAY, TYPE_OBJECT, TYPE_OBJECT] "
+"# Two-dimensional array of resources.\n"
+"[/codeblock]\n"
+"[b]Note:[/b] The final colon is required to specify for properly detecting "
+"built-in types."
+msgstr ""
+
+#: doc/classes/@GlobalScope.xml
msgid "The property is serialized and saved in the scene file (default)."
msgstr ""
@@ -4231,8 +4260,7 @@ msgstr ""
#: doc/classes/AudioStreamPlayer.xml doc/classes/Button.xml
#: doc/classes/CanvasLayer.xml doc/classes/CollisionShape2D.xml
#: doc/classes/ColorRect.xml doc/classes/Input.xml doc/classes/InputEvent.xml
-#: doc/classes/InputEventAction.xml doc/classes/Label.xml
-#: doc/classes/Particles2D.xml doc/classes/Timer.xml
+#: doc/classes/InputEventAction.xml doc/classes/Label.xml doc/classes/Timer.xml
#: doc/classes/VisibilityNotifier2D.xml
msgid "2D Dodge The Creeps Demo"
msgstr ""
@@ -7149,7 +7177,10 @@ msgid ""
"var array = []\n"
"array.resize(10)\n"
"array.fill(0) # Initialize the 10 elements to 0.\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] If [code]value[/code] is of a reference type ([Object]-derived, "
+"[Array], [Dictionary], etc.) then the array is filled with the references to "
+"the same object, i.e. no duplicates are created."
msgstr ""
#: doc/classes/Array.xml doc/classes/PoolByteArray.xml
@@ -7334,6 +7365,9 @@ msgstr ""
#: doc/classes/Array.xml
msgid ""
"Sorts the array.\n"
+"[b]Note:[/b] The sorting algorithm used is not [url=https://en.wikipedia.org/"
+"wiki/Sorting_algorithm#Stability]stable[/url]. This means that values "
+"considered equal may have their order changed when using [method sort].\n"
"[b]Note:[/b] Strings are sorted in alphabetical order (as opposed to natural "
"order). This may lead to unexpected behavior when sorting an array of "
"strings ending with a sequence of numbers. Consider the following example:\n"
@@ -7353,9 +7387,13 @@ msgid ""
"For two elements [code]a[/code] and [code]b[/code], if the given method "
"returns [code]true[/code], element [code]b[/code] will be after element "
"[code]a[/code] in the array.\n"
+"[b]Note:[/b] The sorting algorithm used is not [url=https://en.wikipedia.org/"
+"wiki/Sorting_algorithm#Stability]stable[/url]. This means that values "
+"considered equal may have their order changed when using [method "
+"sort_custom].\n"
"[b]Note:[/b] You cannot randomize the return value as the heapsort algorithm "
-"expects a deterministic result. Doing so will result in unexpected "
-"behavior.\n"
+"expects a deterministic result. Randomizing the return value will result in "
+"unexpected behavior.\n"
"[codeblock]\n"
"class MyCustomSorter:\n"
" static func sort_ascending(a, b):\n"
@@ -9993,10 +10031,9 @@ msgstr ""
#: doc/classes/AudioStreamGeneratorPlayback.xml
msgid ""
-"Returns the number of audio data frames left to play. If this returned "
-"number reaches [code]0[/code], the audio will stop playing until frames are "
-"added again. Therefore, make sure your script can always generate and push "
-"new audio frames fast enough to avoid audio cracking."
+"Returns the number of frames that can be pushed to the audio sample data "
+"buffer without overflowing it. If the result is [code]0[/code], the buffer "
+"is full."
msgstr ""
#: doc/classes/AudioStreamGeneratorPlayback.xml
@@ -10528,14 +10565,14 @@ msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
"Node for back-buffering the currently-displayed screen. The region defined "
-"in the BackBufferCopy node is buffered with the content of the screen it "
+"in the [BackBufferCopy] node is buffered with the content of the screen it "
"covers, or the entire screen according to the copy mode set. Use the "
"[code]texture(SCREEN_TEXTURE, ...)[/code] function in your shader scripts to "
"access the buffer.\n"
"[b]Note:[/b] Since this node inherits from [Node2D] (and not [Control]), "
"anchors and margins won't apply to child [Control]-derived nodes. This can "
"be problematic when resizing the window. To avoid this, add [Control]-"
-"derived nodes as [i]siblings[/i] to the BackBufferCopy node instead of "
+"derived nodes as [i]siblings[/i] to the [BackBufferCopy] node instead of "
"adding them as children."
msgstr ""
@@ -10545,22 +10582,22 @@ msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
-"The area covered by the BackBufferCopy. Only used if [member copy_mode] is "
+"The area covered by the [BackBufferCopy]. Only used if [member copy_mode] is "
"[constant COPY_MODE_RECT]."
msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
-"Disables the buffering mode. This means the BackBufferCopy node will "
+"Disables the buffering mode. This means the [BackBufferCopy] node will "
"directly use the portion of screen it covers."
msgstr ""
#: doc/classes/BackBufferCopy.xml
-msgid "BackBufferCopy buffers a rectangular region."
+msgid "[BackBufferCopy] buffers a rectangular region."
msgstr ""
#: doc/classes/BackBufferCopy.xml
-msgid "BackBufferCopy buffers the entire screen."
+msgid "[BackBufferCopy] buffers the entire screen."
msgstr ""
#: doc/classes/BakedLightmap.xml
@@ -19340,6 +19377,14 @@ msgid "Cylinder shape for collisions."
msgstr ""
#: doc/classes/CylinderShape.xml
+msgid ""
+"Cylinder shape for collisions.\n"
+"[b]Note:[/b] When using GodotPhysics instead of the default Bullet physics "
+"engine, there are several known bugs with cylinder collision shapes. Using "
+"[CapsuleShape] or [BoxShape] instead is recommended."
+msgstr ""
+
+#: doc/classes/CylinderShape.xml
msgid "The cylinder's height."
msgstr ""
@@ -22172,7 +22217,10 @@ msgid ""
"[/codeblock]\n"
"[b]Note:[/b] The script is run in the Editor context, which means the output "
"is visible in the console window started with the Editor (stdout) instead of "
-"the usual Godot [b]Output[/b] dock."
+"the usual Godot [b]Output[/b] dock.\n"
+"[b]Note:[/b] EditorScript is reference counted, meaning it is destroyed when "
+"nothing references it. This can cause errors during asynchronous operations "
+"if there are no references to the script."
msgstr ""
#: doc/classes/EditorScript.xml
@@ -32887,7 +32935,9 @@ msgid ""
"The size of the light in Godot units. Only considered in baked lightmaps and "
"only if [member light_bake_mode] is set to [constant BAKE_ALL]. Increasing "
"this value will make the shadows appear blurrier. This can be used to "
-"simulate area lights to an extent."
+"simulate area lights to an extent.\n"
+"[b]Note:[/b] [member light_size] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/Light.xml
@@ -36185,7 +36235,10 @@ msgid ""
"use the [method get_next_location] function once every physics frame to "
"update the internal path logic of the NavigationAgent. The returned vector "
"position from this function should be used as the next movement position for "
-"the agent's parent Node."
+"the agent's parent Node.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues."
msgstr ""
#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
@@ -36433,7 +36486,10 @@ msgid ""
"use the [method get_next_location] function once every physics frame to "
"update the internal path logic of the NavigationAgent. The returned vector "
"position from this function should be used as the next movement position for "
-"the agent's parent Node."
+"the agent's parent Node.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues."
msgstr ""
#: doc/classes/NavigationAgent2D.xml
@@ -37143,6 +37199,9 @@ msgid ""
"modified velocity as-is might lead to pushing and agent outside of a "
"navigable area. This is a limitation of the collision avoidance system, any "
"more complex situation may require the use of the physics engine.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues.\n"
"This server keeps tracks of any call and executes them during the sync "
"phase. This means that you can request any change to the map, using any "
"thread, without worrying."
@@ -39949,7 +40008,9 @@ msgid ""
"The light's radius. Note that the effectively lit area may appear to be "
"smaller depending on the [member omni_attenuation] in use. No matter the "
"[member omni_attenuation] in use, the light will never reach anything "
-"outside this radius."
+"outside this radius.\n"
+"[b]Note:[/b] [member omni_range] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -40460,11 +40521,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] cache data directory according to the operating "
-"system's standards. On desktop platforms, this path can be overridden by "
-"setting the [code]XDG_CACHE_HOME[/code] environment variable before starting "
-"the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in "
-"Godot projects[/url] in the documentation for more information. See also "
-"[method get_config_dir] and [method get_data_dir].\n"
+"system's standards. On Linux, this path can be overridden by setting the "
+"[code]XDG_CACHE_HOME[/code] environment variable before starting the "
+"project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot "
+"projects[/url] in the documentation for more information. See also [method "
+"get_config_dir] and [method get_data_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -40498,11 +40559,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] user configuration directory according to the "
-"operating system's standards. On desktop platforms, this path can be "
-"overridden by setting the [code]XDG_CONFIG_HOME[/code] environment variable "
-"before starting the project. See [url=$DOCS_URL/tutorials/io/data_paths."
-"html]File paths in Godot projects[/url] in the documentation for more "
-"information. See also [method get_cache_dir] and [method get_data_dir].\n"
+"operating system's standards. On Linux, this path can be overridden by "
+"setting the [code]XDG_CONFIG_HOME[/code] environment variable before "
+"starting the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File "
+"paths in Godot projects[/url] in the documentation for more information. See "
+"also [method get_cache_dir] and [method get_data_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -40524,11 +40585,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] user data directory according to the operating "
-"system's standards. On desktop platforms, this path can be overridden by "
-"setting the [code]XDG_DATA_HOME[/code] environment variable before starting "
-"the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in "
-"Godot projects[/url] in the documentation for more information. See also "
-"[method get_cache_dir] and [method get_config_dir].\n"
+"system's standards. On Linux, this path can be overridden by setting the "
+"[code]XDG_DATA_HOME[/code] environment variable before starting the project. "
+"See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot "
+"projects[/url] in the documentation for more information. See also [method "
+"get_cache_dir] and [method get_config_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -42375,6 +42436,16 @@ msgid "Particle systems (2D)"
msgstr ""
#: doc/classes/Particles2D.xml
+msgid "2D Particles Demo"
+msgstr ""
+
+#: doc/classes/Particles2D.xml
+msgid ""
+"2D Dodge The Creeps Demo (uses GPUParticles2D for the trail behind the "
+"player)"
+msgstr ""
+
+#: doc/classes/Particles2D.xml
msgid "Returns a rectangle containing the positions of all existing particles."
msgstr ""
@@ -49967,15 +50038,22 @@ msgstr ""
#: doc/classes/ProjectSettings.xml
msgid ""
"If [code]true[/code], uses a fast post-processing filter to make banding "
-"significantly less visible. In some cases, debanding may introduce a "
-"slightly noticeable dithering pattern. It's recommended to enable debanding "
-"only when actually needed since the dithering pattern will make lossless-"
-"compressed screenshots larger.\n"
+"significantly less visible in 3D. 2D rendering is [i]not[/i] affected by "
+"debanding unless the [member Environment.background_mode] is [constant "
+"Environment.BG_CANVAS]. In this case, [member rendering/quality/"
+"intended_usage/framebuffer_allocation] must also be set to [b]3D[/b].\n"
+"In some cases, debanding may introduce a slightly noticeable dithering "
+"pattern. It's recommended to enable debanding only when actually needed "
+"since the dithering pattern will make lossless-compressed screenshots "
+"larger.\n"
"[b]Note:[/b] Only available on the GLES3 backend. [member rendering/quality/"
"depth/hdr] must also be [code]true[/code] for debanding to be effective.\n"
"[b]Note:[/b] There are known issues with debanding breaking rendering on "
"mobile platforms. Due to this, it is recommended to leave this option "
-"disabled when targeting mobile platforms."
+"disabled when targeting mobile platforms.\n"
+"[b]Note:[/b] This property is only read when the project starts. To set "
+"debanding at run-time, set [member Viewport.debanding] on the root "
+"[Viewport] instead."
msgstr ""
#: doc/classes/ProjectSettings.xml
@@ -51571,17 +51649,28 @@ msgstr ""
#: modules/regex/doc_classes/RegEx.xml
msgid ""
"Searches the text for the compiled pattern. Returns a [RegExMatch] container "
-"of the first matching result if found, otherwise [code]null[/code]. The "
-"region to search within can be specified without modifying where the start "
-"and end anchor would be."
+"of the first matching result if found, otherwise [code]null[/code].\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegEx.xml
msgid ""
"Searches the text for the compiled pattern. Returns an array of [RegExMatch] "
"containers for each non-overlapping result. If no results were found, an "
-"empty array is returned instead. The region to search within can be "
-"specified without modifying where the start and end anchor would be."
+"empty array is returned instead.\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegEx.xml
@@ -51590,8 +51679,14 @@ msgid ""
"specified string. Escapes and backreferences such as [code]$1[/code] and "
"[code]$name[/code] are expanded and resolved. By default, only the first "
"instance is replaced, but it can be changed for all instances (global "
-"replacement). The region to search within can be specified without modifying "
-"where the start and end anchor would be."
+"replacement).\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegExMatch.xml
@@ -54307,7 +54402,11 @@ msgid "Call a group immediately (calls are normally made on idle)."
msgstr ""
#: doc/classes/SceneTree.xml
-msgid "Call a group only once even if the call is executed many times."
+msgid ""
+"Call a group only once even if the call is executed many times.\n"
+"[b]Note:[/b] Arguments are not taken into account when deciding whether the "
+"call is unique or not. Therefore when the same method is called with "
+"different arguments, only the first call will be performed."
msgstr ""
#: doc/classes/SceneTree.xml
@@ -56144,7 +56243,9 @@ msgid ""
"[b]Note:[/b] Mixed negative scales in 3D are not decomposable from the "
"transformation matrix. Due to the way scale is represented with "
"transformation matrices in Godot, the scale values will either be all "
-"positive or all negative."
+"positive or all negative.\n"
+"[b]Note:[/b] Not all nodes are visually scaled by the [member scale] "
+"property. For example, [Light]s are not visually affected by [member scale]."
msgstr ""
#: doc/classes/Spatial.xml
@@ -57522,7 +57623,10 @@ msgid ""
msgstr ""
#: doc/classes/SpotLight.xml
-msgid "The spotlight's angle in degrees."
+msgid ""
+"The spotlight's angle in degrees.\n"
+"[b]Note:[/b] [member spot_angle] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/SpotLight.xml
@@ -57538,7 +57642,9 @@ msgid ""
"The maximal range that can be reached by the spotlight. Note that the "
"effectively lit area may appear to be smaller depending on the [member "
"spot_attenuation] in use. No matter the [member spot_attenuation] in use, "
-"the light will never reach anything outside this range."
+"the light will never reach anything outside this range.\n"
+"[b]Note:[/b] [member spot_range] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/SpringArm.xml
@@ -66775,10 +66881,15 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
"If [code]true[/code], uses a fast post-processing filter to make banding "
-"significantly less visible. In some cases, debanding may introduce a "
-"slightly noticeable dithering pattern. It's recommended to enable debanding "
-"only when actually needed since the dithering pattern will make lossless-"
-"compressed screenshots larger.\n"
+"significantly less visible in 3D. 2D rendering is [i]not[/i] affected by "
+"debanding unless the [member Environment.background_mode] is [constant "
+"Environment.BG_CANVAS]. In this case, [member usage] must also be set to "
+"[constant USAGE_3D]. See also [member ProjectSettings.rendering/quality/"
+"filters/use_debanding].\n"
+"In some cases, debanding may introduce a slightly noticeable dithering "
+"pattern. It's recommended to enable debanding only when actually needed "
+"since the dithering pattern will make lossless-compressed screenshots "
+"larger.\n"
"[b]Note:[/b] Only available on the GLES3 backend. [member hdr] must also be "
"[code]true[/code] for debanding to be effective."
msgstr ""
@@ -66789,8 +66900,8 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
-"If [code]true[/code], the viewport will disable 3D rendering. For actual "
-"disabling use [code]usage[/code]."
+"If [code]true[/code], the viewport will disable 3D rendering. To actually "
+"disable allocation of 3D buffers, set [member usage] instead."
msgstr ""
#: doc/classes/Viewport.xml
@@ -66942,7 +67053,9 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
-"The rendering mode of viewport.\n"
+"The viewport's rendering mode. This controls which buffers are allocated for "
+"the viewport (2D only, or 2D + 3D). 2D-only options can reduce memory usage "
+"and improve performance slightly, especially on low-end devices.\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."
@@ -67474,6 +67587,22 @@ msgid ""
"render object this [VisualInstance] is set to."
msgstr ""
+#: doc/classes/VisualInstance.xml
+msgid ""
+"The sorting offset used by this [VisualInstance]. Adjusting it to a higher "
+"value will make the [VisualInstance] reliably draw on top of other "
+"[VisualInstance]s that are otherwise positioned at the same spot."
+msgstr ""
+
+#: doc/classes/VisualInstance.xml
+msgid ""
+"If [code]true[/code], the object is sorted based on the [AABB] center. "
+"Sorted based on the global position otherwise.\n"
+"The [AABB] center based sorting is generally more accurate for 3D models. "
+"The position based sorting instead allows to better control the drawing "
+"order when working with [Particles] and [CPUParticles]."
+msgstr ""
+
#: modules/visual_script/doc_classes/VisualScript.xml
msgid "A script implemented in the Visual Script programming environment."
msgstr ""
diff --git a/doc/translations/pl.po b/doc/translations/pl.po
index 0bc778f703..cd2bedd302 100644
--- a/doc/translations/pl.po
+++ b/doc/translations/pl.po
@@ -23,13 +23,14 @@
# Katarzyna Twardowska <katarina.twardowska@gmail.com>, 2022.
# Mateusz Zdrzałek <matjozohd@gmail.com>, 2022.
# Pixel Zone - Godot Engine Tutorials <karoltomaszewskimusic@gmail.com>, 2022.
+# Filip Gliszczyński <filipgliszczynski@gmail.com>, 2022.
+# Piotr Åšlusarz <piotrekslusarz@outlook.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-15 20:00+0000\n"
-"Last-Translator: Pixel Zone - Godot Engine Tutorials "
-"<karoltomaszewskimusic@gmail.com>\n"
+"PO-Revision-Date: 2022-10-30 01:15+0000\n"
+"Last-Translator: Piotr Åšlusarz <piotrekslusarz@outlook.com>\n"
"Language-Team: Polish <https://hosted.weblate.org/projects/godot-engine/"
"godot-class-reference/pl/>\n"
"Language: pl\n"
@@ -38,7 +39,7 @@ msgstr ""
"Content-Transfer-Encoding: 8-bit\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.2-dev\n"
#: doc/tools/make_rst.py
msgid "Description"
@@ -500,7 +501,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"
@@ -523,17 +523,17 @@ msgstr ""
"Porównuje dwie wartości, sprawdzając ich rzeczywistą zawartość, przechodząc "
"do dowolnej „tablicy†lub „słownika†aż do najgłębszego poziomu.\n"
"Można to porównać do [code]==[/code] na kilka sposobów:\n"
-"— Dla [kod]null[/code], [kod]int[/code], [code]float[/code], [code]String[/"
+"— Dla [code]null[/code], [code]int[/code], [code]float[/code], [code]String[/"
"code], [code]Object[/code] i [code] RID[/code] zarówno [code]deep_equal[/"
"code], jak i [code]==[/code] działają tak samo.\n"
"— W przypadku [code]Słownik[/code] [code]==[/code] uwzględnia równość wtedy "
"i tylko wtedy, gdy obie zmienne wskazują ten sam [code]Słownik[/code], bez "
"rekurencji lub świadomości zawartość w ogóle.\n"
-"— W przypadku [kod]Tablica[/kod] [kod]==[/kod] uwzględnia równość wtedy i "
-"tylko wtedy, gdy każdy element w pierwszej [kod]Tablica[/kod] jest równy "
-"swojemu odpowiednikowi w drugiej [ kod]Tablica[/kod], jak mówi sam [kod]==[/"
-"kod]. Oznacza to, że [code]==[/code] jest rekursywny w [code]Tablicy[/code], "
-"ale nie w [code]Słowniku[/code].\n"
+"— W przypadku [code]Tablica[/code] [code]==[/code] uwzględnia równość wtedy "
+"i tylko wtedy, gdy każdy element w pierwszej [code]Tablica[/code] jest równy "
+"swojemu odpowiednikowi w drugiej [code]Tablica[/code], jak mówi sam "
+"[code]==[/code]. Oznacza to, że [code]==[/code] jest rekursywny w "
+"[code]Tablicy[/code], ale nie w [code]Słowniku[/code].\n"
"Krótko mówiąc, za każdym razem, gdy potencjalnie zaangażowany jest "
"[code]Słownik[/code], jeśli chcesz prawdziwego porównania uwzględniającego "
"zawartość, musisz użyć [code]deep_equal[/code]."
@@ -619,7 +619,6 @@ msgstr ""
"[/codeblock]"
#: modules/gdscript/doc_classes/@GDScript.xml
-#, fuzzy
msgid ""
"Rounds [code]s[/code] downward (towards negative infinity), returning the "
"largest whole number that is not more than [code]s[/code].\n"
@@ -633,13 +632,12 @@ msgid ""
"[code]s[/code] is a non-negative number, you can use [code]int(s)[/code] "
"directly."
msgstr ""
-"Zaokrągla [code]s[/code] w dół (do nieskończoności ujemnej), zwraca "
+"Zaokrągla [code]s[/code] w dół (do ujemnej nieskończoności), zwraca "
"najwyższą liczbę całkowitą która jest nie większa niż [code]s[/code].\n"
"[codeblock]\n"
-"# a to 2.0\n"
-"a = floor(2.99)\n"
-"# a to-3.0\n"
-"a = floor(-2.99)\n"
+"a = floor(2.45) # a to 2.0\n"
+"a = floor(2.99) # a to 2.0\n"
+"a = floor(-2.99) # a to-3.0\n"
"[/codeblock]\n"
"[b]Informacja:[/b] Ta metoda zwraca liczbę zmiennoprzecinkową, jeżeli chcesz "
"liczby całkowitej użyj bezpośrednio metody [code]int(s)[/code]."
@@ -725,8 +723,10 @@ msgstr ""
"[/codeblock]"
#: modules/gdscript/doc_classes/@GDScript.xml
+#, fuzzy
msgid ""
-"Returns an array of dictionaries representing the current call stack.\n"
+"Returns an array of dictionaries representing the current call stack. See "
+"also [method print_stack].\n"
"[codeblock]\n"
"func _ready():\n"
" foo()\n"
@@ -741,7 +741,11 @@ msgid ""
"[codeblock]\n"
"[{function:bar, line:12, source:res://script.gd}, {function:foo, line:9, "
"source:res://script.gd}, {function:_ready, line:6, source:res://script.gd}]\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] [method get_stack] only works if the running instance is "
+"connected to a debugging server (i.e. an editor instance). [method "
+"get_stack] will not work in projects exported in release mode, or in "
+"projects exported in debug mode if not connected to a debugging server."
msgstr ""
"Zwraca tablicę słowników reprezentującą obecny stos wykonywanych funkcji.\n"
"[codeblock]\n"
@@ -849,6 +853,26 @@ msgid ""
"See also [method lerp] which performs the reverse of this operation, and "
"[method range_lerp] to map a continuous series of values to another."
msgstr ""
+"Zwraca współczynnik interpolacji lub ekstrapolacji w zależności od zakresu "
+"zdefiniowanego w [code]from[/code] i [code]to[/code] oraz wartość "
+"interopolowaną zdefiniowaną w [code]weight[/code]. Zwrócona wartość znajduje "
+"się pomiędzy [code]0.0[/code] i [code]1.0[/code] jeśli [code]weight[/code] "
+"jest pomiędzy [code]from[/code] i [code]to[/code] (włącznie). Jeśli "
+"[code]weight[/code] znajduje się poza zakresem, współczynnik ekstrapolacji "
+"zostanie zwrócony (zwraca wartość mniejszą od [code]0.0[/code] lub większą "
+"od [code]1.0[/code]). Użyj [method clamp] na wyniku [method inverse_lerp] "
+"jeśli chcesz tego uniknąć. \n"
+"[codeblock] \n"
+"# Stosunek interpolacji w zawołaniu `lerp()` poniżej to 0.75. \n"
+"var middle = lerp(20, 30, 0.75) \n"
+"# `middle` ma teraz wartość 27.5. \n"
+"# Teraz udajemy że zapomnieliśmy oryginalnego stosunku i chcemy go "
+"spowrotem. \n"
+"var ratio = inverse_lerp(20,30,27.5) \n"
+"# `ratio` ma teraz wartość 0.75.\n"
+"[/codeblock]\n"
+"Zobacz również [method lerp] która powoduje odwrócenie tej operacji i "
+"[method range_lerp] aby zmapować ciągłą serie wartości do następnej."
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
@@ -1150,6 +1174,22 @@ msgid ""
"[code]0[/code] rather than [code]1[/code] for non-positive values of "
"[code]value[/code] (in reality, 1 is the smallest integer power of 2)."
msgstr ""
+"Zwraca najbliższą wartość całkowitą [code]value[/code] równą lub wyższą "
+"potędze dwójki.\n"
+"Innymi słowy, zwraca najmniejszą wartość [code]a[/code] gdzie [code]a = "
+"pow(2, n)[/code] wtedy i tylko wtedy gdy [code]value <= a[/code] dla jakiejÅ› "
+"dodatniej liczby całkowitej [code]n[/code].\n"
+"[codeblock]\n"
+"nearest_po2(3) # zwraca 4\n"
+"nearest_po2(4) # zwraca 4\n"
+"nearest_po2(5) # zwraca 8\n"
+"\n"
+"nearest_po2(0) # zwraca 0 (niekoniecznie czego byś się spodziewał)\n"
+"nearest_po2(-1) # zwraca 0 (niekoniecznie czego byś się spodziewał)\n"
+"[/codeblock]\n"
+"[b]UWAGA:[/b] Z powodu sposobu implementacji, ta funkcja zwraca [code]0[/"
+"code] w przeciwieństwie do [code]1[/code] dla ujemnych wartości [code]value[/"
+"code] (w rzeczywistości, 1 jest najmniejszą liczbą całkowitą dla potęgi z 2)."
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
@@ -1162,6 +1202,13 @@ msgid ""
"[/codeblock]\n"
"This is the inverse of [method char]."
msgstr ""
+"Zwraca liczbę całkowitą reprezentującą punkt kodu Unicode danego znaku "
+"Unicode [code]char[/code]. [codeblock]\n"
+"a = ord(\"A\") # a wynosi 65\n"
+"a = ord(\"a\") # a wynosi 97\n"
+"a = ord(\"€\") # a wynosi 8364\n"
+"[/codeblock]\n"
+"To jest odwrotność [metody char]."
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
@@ -1302,19 +1349,17 @@ msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
-"Prints a stack track at code location, only works when running with debugger "
-"turned on.\n"
+"Prints a stack trace at the current code location. See also [method "
+"get_stack].\n"
"Output in the console would look something like this:\n"
"[codeblock]\n"
"Frame 0 - res://test.gd:16 in function '_process'\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] [method print_stack] only works if the running instance is "
+"connected to a debugging server (i.e. an editor instance). [method "
+"print_stack] will not work in projects exported in release mode, or in "
+"projects exported in debug mode if not connected to a debugging server."
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 ""
@@ -3981,6 +4026,26 @@ msgid "Hints that an image is compressed using lossless compression."
msgstr ""
#: doc/classes/@GlobalScope.xml
+msgid ""
+"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:\n"
+"[codeblock]\n"
+"hint_string = \"%s:\" % [TYPE_INT] # Array of inteters.\n"
+"hint_string = \"%s:%s:\" % [TYPE_ARRAY, TYPE_REAL] # Two-dimensional array "
+"of floats.\n"
+"hint_string = \"%s/%s:Resource\" % [TYPE_OBJECT, TYPE_OBJECT] # Array of "
+"resources.\n"
+"hint_string = \"%s:%s/%s:Resource\" % [TYPE_ARRAY, TYPE_OBJECT, TYPE_OBJECT] "
+"# Two-dimensional array of resources.\n"
+"[/codeblock]\n"
+"[b]Note:[/b] The final colon is required to specify for properly detecting "
+"built-in types."
+msgstr ""
+
+#: doc/classes/@GlobalScope.xml
msgid "The property is serialized and saved in the scene file (default)."
msgstr ""
@@ -4665,8 +4730,7 @@ msgstr ""
#: doc/classes/AudioStreamPlayer.xml doc/classes/Button.xml
#: doc/classes/CanvasLayer.xml doc/classes/CollisionShape2D.xml
#: doc/classes/ColorRect.xml doc/classes/Input.xml doc/classes/InputEvent.xml
-#: doc/classes/InputEventAction.xml doc/classes/Label.xml
-#: doc/classes/Particles2D.xml doc/classes/Timer.xml
+#: doc/classes/InputEventAction.xml doc/classes/Label.xml doc/classes/Timer.xml
#: doc/classes/VisibilityNotifier2D.xml
msgid "2D Dodge The Creeps Demo"
msgstr ""
@@ -7593,7 +7657,10 @@ msgid ""
"var array = []\n"
"array.resize(10)\n"
"array.fill(0) # Initialize the 10 elements to 0.\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] If [code]value[/code] is of a reference type ([Object]-derived, "
+"[Array], [Dictionary], etc.) then the array is filled with the references to "
+"the same object, i.e. no duplicates are created."
msgstr ""
#: doc/classes/Array.xml doc/classes/PoolByteArray.xml
@@ -7778,6 +7845,9 @@ msgstr ""
#: doc/classes/Array.xml
msgid ""
"Sorts the array.\n"
+"[b]Note:[/b] The sorting algorithm used is not [url=https://en.wikipedia.org/"
+"wiki/Sorting_algorithm#Stability]stable[/url]. This means that values "
+"considered equal may have their order changed when using [method sort].\n"
"[b]Note:[/b] Strings are sorted in alphabetical order (as opposed to natural "
"order). This may lead to unexpected behavior when sorting an array of "
"strings ending with a sequence of numbers. Consider the following example:\n"
@@ -7797,9 +7867,13 @@ msgid ""
"For two elements [code]a[/code] and [code]b[/code], if the given method "
"returns [code]true[/code], element [code]b[/code] will be after element "
"[code]a[/code] in the array.\n"
+"[b]Note:[/b] The sorting algorithm used is not [url=https://en.wikipedia.org/"
+"wiki/Sorting_algorithm#Stability]stable[/url]. This means that values "
+"considered equal may have their order changed when using [method "
+"sort_custom].\n"
"[b]Note:[/b] You cannot randomize the return value as the heapsort algorithm "
-"expects a deterministic result. Doing so will result in unexpected "
-"behavior.\n"
+"expects a deterministic result. Randomizing the return value will result in "
+"unexpected behavior.\n"
"[codeblock]\n"
"class MyCustomSorter:\n"
" static func sort_ascending(a, b):\n"
@@ -10438,10 +10512,9 @@ msgstr ""
#: doc/classes/AudioStreamGeneratorPlayback.xml
msgid ""
-"Returns the number of audio data frames left to play. If this returned "
-"number reaches [code]0[/code], the audio will stop playing until frames are "
-"added again. Therefore, make sure your script can always generate and push "
-"new audio frames fast enough to avoid audio cracking."
+"Returns the number of frames that can be pushed to the audio sample data "
+"buffer without overflowing it. If the result is [code]0[/code], the buffer "
+"is full."
msgstr ""
#: doc/classes/AudioStreamGeneratorPlayback.xml
@@ -10973,14 +11046,14 @@ msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
"Node for back-buffering the currently-displayed screen. The region defined "
-"in the BackBufferCopy node is buffered with the content of the screen it "
+"in the [BackBufferCopy] node is buffered with the content of the screen it "
"covers, or the entire screen according to the copy mode set. Use the "
"[code]texture(SCREEN_TEXTURE, ...)[/code] function in your shader scripts to "
"access the buffer.\n"
"[b]Note:[/b] Since this node inherits from [Node2D] (and not [Control]), "
"anchors and margins won't apply to child [Control]-derived nodes. This can "
"be problematic when resizing the window. To avoid this, add [Control]-"
-"derived nodes as [i]siblings[/i] to the BackBufferCopy node instead of "
+"derived nodes as [i]siblings[/i] to the [BackBufferCopy] node instead of "
"adding them as children."
msgstr ""
@@ -10990,22 +11063,22 @@ msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
-"The area covered by the BackBufferCopy. Only used if [member copy_mode] is "
+"The area covered by the [BackBufferCopy]. Only used if [member copy_mode] is "
"[constant COPY_MODE_RECT]."
msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
-"Disables the buffering mode. This means the BackBufferCopy node will "
+"Disables the buffering mode. This means the [BackBufferCopy] node will "
"directly use the portion of screen it covers."
msgstr ""
#: doc/classes/BackBufferCopy.xml
-msgid "BackBufferCopy buffers a rectangular region."
+msgid "[BackBufferCopy] buffers a rectangular region."
msgstr ""
#: doc/classes/BackBufferCopy.xml
-msgid "BackBufferCopy buffers the entire screen."
+msgid "[BackBufferCopy] buffers the entire screen."
msgstr ""
#: doc/classes/BakedLightmap.xml
@@ -19814,6 +19887,14 @@ msgid "Cylinder shape for collisions."
msgstr ""
#: doc/classes/CylinderShape.xml
+msgid ""
+"Cylinder shape for collisions.\n"
+"[b]Note:[/b] When using GodotPhysics instead of the default Bullet physics "
+"engine, there are several known bugs with cylinder collision shapes. Using "
+"[CapsuleShape] or [BoxShape] instead is recommended."
+msgstr ""
+
+#: doc/classes/CylinderShape.xml
msgid "The cylinder's height."
msgstr ""
@@ -22656,7 +22737,10 @@ msgid ""
"[/codeblock]\n"
"[b]Note:[/b] The script is run in the Editor context, which means the output "
"is visible in the console window started with the Editor (stdout) instead of "
-"the usual Godot [b]Output[/b] dock."
+"the usual Godot [b]Output[/b] dock.\n"
+"[b]Note:[/b] EditorScript is reference counted, meaning it is destroyed when "
+"nothing references it. This can cause errors during asynchronous operations "
+"if there are no references to the script."
msgstr ""
#: doc/classes/EditorScript.xml
@@ -33427,7 +33511,9 @@ msgid ""
"The size of the light in Godot units. Only considered in baked lightmaps and "
"only if [member light_bake_mode] is set to [constant BAKE_ALL]. Increasing "
"this value will make the shadows appear blurrier. This can be used to "
-"simulate area lights to an extent."
+"simulate area lights to an extent.\n"
+"[b]Note:[/b] [member light_size] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/Light.xml
@@ -36767,7 +36853,10 @@ msgid ""
"use the [method get_next_location] function once every physics frame to "
"update the internal path logic of the NavigationAgent. The returned vector "
"position from this function should be used as the next movement position for "
-"the agent's parent Node."
+"the agent's parent Node.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues."
msgstr ""
#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
@@ -37023,7 +37112,10 @@ msgid ""
"use the [method get_next_location] function once every physics frame to "
"update the internal path logic of the NavigationAgent. The returned vector "
"position from this function should be used as the next movement position for "
-"the agent's parent Node."
+"the agent's parent Node.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues."
msgstr ""
#: doc/classes/NavigationAgent2D.xml
@@ -37745,6 +37837,9 @@ msgid ""
"modified velocity as-is might lead to pushing and agent outside of a "
"navigable area. This is a limitation of the collision avoidance system, any "
"more complex situation may require the use of the physics engine.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues.\n"
"This server keeps tracks of any call and executes them during the sync "
"phase. This means that you can request any change to the map, using any "
"thread, without worrying."
@@ -40555,7 +40650,9 @@ msgid ""
"The light's radius. Note that the effectively lit area may appear to be "
"smaller depending on the [member omni_attenuation] in use. No matter the "
"[member omni_attenuation] in use, the light will never reach anything "
-"outside this radius."
+"outside this radius.\n"
+"[b]Note:[/b] [member omni_range] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -41074,11 +41171,11 @@ msgstr "Zwraca kÄ…t w radianach danego wektora."
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] cache data directory according to the operating "
-"system's standards. On desktop platforms, this path can be overridden by "
-"setting the [code]XDG_CACHE_HOME[/code] environment variable before starting "
-"the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in "
-"Godot projects[/url] in the documentation for more information. See also "
-"[method get_config_dir] and [method get_data_dir].\n"
+"system's standards. On Linux, this path can be overridden by setting the "
+"[code]XDG_CACHE_HOME[/code] environment variable before starting the "
+"project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot "
+"projects[/url] in the documentation for more information. See also [method "
+"get_config_dir] and [method get_data_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -41112,11 +41209,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] user configuration directory according to the "
-"operating system's standards. On desktop platforms, this path can be "
-"overridden by setting the [code]XDG_CONFIG_HOME[/code] environment variable "
-"before starting the project. See [url=$DOCS_URL/tutorials/io/data_paths."
-"html]File paths in Godot projects[/url] in the documentation for more "
-"information. See also [method get_cache_dir] and [method get_data_dir].\n"
+"operating system's standards. On Linux, this path can be overridden by "
+"setting the [code]XDG_CONFIG_HOME[/code] environment variable before "
+"starting the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File "
+"paths in Godot projects[/url] in the documentation for more information. See "
+"also [method get_cache_dir] and [method get_data_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -41138,11 +41235,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] user data directory according to the operating "
-"system's standards. On desktop platforms, this path can be overridden by "
-"setting the [code]XDG_DATA_HOME[/code] environment variable before starting "
-"the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in "
-"Godot projects[/url] in the documentation for more information. See also "
-"[method get_cache_dir] and [method get_config_dir].\n"
+"system's standards. On Linux, this path can be overridden by setting the "
+"[code]XDG_DATA_HOME[/code] environment variable before starting the project. "
+"See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot "
+"projects[/url] in the documentation for more information. See also [method "
+"get_cache_dir] and [method get_config_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -43021,6 +43118,16 @@ msgid "Particle systems (2D)"
msgstr ""
#: doc/classes/Particles2D.xml
+msgid "2D Particles Demo"
+msgstr ""
+
+#: doc/classes/Particles2D.xml
+msgid ""
+"2D Dodge The Creeps Demo (uses GPUParticles2D for the trail behind the "
+"player)"
+msgstr ""
+
+#: doc/classes/Particles2D.xml
msgid "Returns a rectangle containing the positions of all existing particles."
msgstr ""
@@ -50624,15 +50731,22 @@ msgstr ""
#: doc/classes/ProjectSettings.xml
msgid ""
"If [code]true[/code], uses a fast post-processing filter to make banding "
-"significantly less visible. In some cases, debanding may introduce a "
-"slightly noticeable dithering pattern. It's recommended to enable debanding "
-"only when actually needed since the dithering pattern will make lossless-"
-"compressed screenshots larger.\n"
+"significantly less visible in 3D. 2D rendering is [i]not[/i] affected by "
+"debanding unless the [member Environment.background_mode] is [constant "
+"Environment.BG_CANVAS]. In this case, [member rendering/quality/"
+"intended_usage/framebuffer_allocation] must also be set to [b]3D[/b].\n"
+"In some cases, debanding may introduce a slightly noticeable dithering "
+"pattern. It's recommended to enable debanding only when actually needed "
+"since the dithering pattern will make lossless-compressed screenshots "
+"larger.\n"
"[b]Note:[/b] Only available on the GLES3 backend. [member rendering/quality/"
"depth/hdr] must also be [code]true[/code] for debanding to be effective.\n"
"[b]Note:[/b] There are known issues with debanding breaking rendering on "
"mobile platforms. Due to this, it is recommended to leave this option "
-"disabled when targeting mobile platforms."
+"disabled when targeting mobile platforms.\n"
+"[b]Note:[/b] This property is only read when the project starts. To set "
+"debanding at run-time, set [member Viewport.debanding] on the root "
+"[Viewport] instead."
msgstr ""
#: doc/classes/ProjectSettings.xml
@@ -52237,17 +52351,28 @@ msgstr ""
#: modules/regex/doc_classes/RegEx.xml
msgid ""
"Searches the text for the compiled pattern. Returns a [RegExMatch] container "
-"of the first matching result if found, otherwise [code]null[/code]. The "
-"region to search within can be specified without modifying where the start "
-"and end anchor would be."
+"of the first matching result if found, otherwise [code]null[/code].\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegEx.xml
msgid ""
"Searches the text for the compiled pattern. Returns an array of [RegExMatch] "
"containers for each non-overlapping result. If no results were found, an "
-"empty array is returned instead. The region to search within can be "
-"specified without modifying where the start and end anchor would be."
+"empty array is returned instead.\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegEx.xml
@@ -52256,8 +52381,14 @@ msgid ""
"specified string. Escapes and backreferences such as [code]$1[/code] and "
"[code]$name[/code] are expanded and resolved. By default, only the first "
"instance is replaced, but it can be changed for all instances (global "
-"replacement). The region to search within can be specified without modifying "
-"where the start and end anchor would be."
+"replacement).\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegExMatch.xml
@@ -54976,7 +55107,11 @@ msgid "Call a group immediately (calls are normally made on idle)."
msgstr ""
#: doc/classes/SceneTree.xml
-msgid "Call a group only once even if the call is executed many times."
+msgid ""
+"Call a group only once even if the call is executed many times.\n"
+"[b]Note:[/b] Arguments are not taken into account when deciding whether the "
+"call is unique or not. Therefore when the same method is called with "
+"different arguments, only the first call will be performed."
msgstr ""
#: doc/classes/SceneTree.xml
@@ -56814,7 +56949,9 @@ msgid ""
"[b]Note:[/b] Mixed negative scales in 3D are not decomposable from the "
"transformation matrix. Due to the way scale is represented with "
"transformation matrices in Godot, the scale values will either be all "
-"positive or all negative."
+"positive or all negative.\n"
+"[b]Note:[/b] Not all nodes are visually scaled by the [member scale] "
+"property. For example, [Light]s are not visually affected by [member scale]."
msgstr ""
#: doc/classes/Spatial.xml
@@ -58195,7 +58332,10 @@ msgid ""
msgstr ""
#: doc/classes/SpotLight.xml
-msgid "The spotlight's angle in degrees."
+msgid ""
+"The spotlight's angle in degrees.\n"
+"[b]Note:[/b] [member spot_angle] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/SpotLight.xml
@@ -58211,7 +58351,9 @@ msgid ""
"The maximal range that can be reached by the spotlight. Note that the "
"effectively lit area may appear to be smaller depending on the [member "
"spot_attenuation] in use. No matter the [member spot_attenuation] in use, "
-"the light will never reach anything outside this range."
+"the light will never reach anything outside this range.\n"
+"[b]Note:[/b] [member spot_range] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/SpringArm.xml
@@ -67513,10 +67655,15 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
"If [code]true[/code], uses a fast post-processing filter to make banding "
-"significantly less visible. In some cases, debanding may introduce a "
-"slightly noticeable dithering pattern. It's recommended to enable debanding "
-"only when actually needed since the dithering pattern will make lossless-"
-"compressed screenshots larger.\n"
+"significantly less visible in 3D. 2D rendering is [i]not[/i] affected by "
+"debanding unless the [member Environment.background_mode] is [constant "
+"Environment.BG_CANVAS]. In this case, [member usage] must also be set to "
+"[constant USAGE_3D]. See also [member ProjectSettings.rendering/quality/"
+"filters/use_debanding].\n"
+"In some cases, debanding may introduce a slightly noticeable dithering "
+"pattern. It's recommended to enable debanding only when actually needed "
+"since the dithering pattern will make lossless-compressed screenshots "
+"larger.\n"
"[b]Note:[/b] Only available on the GLES3 backend. [member hdr] must also be "
"[code]true[/code] for debanding to be effective."
msgstr ""
@@ -67527,8 +67674,8 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
-"If [code]true[/code], the viewport will disable 3D rendering. For actual "
-"disabling use [code]usage[/code]."
+"If [code]true[/code], the viewport will disable 3D rendering. To actually "
+"disable allocation of 3D buffers, set [member usage] instead."
msgstr ""
#: doc/classes/Viewport.xml
@@ -67686,7 +67833,9 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
-"The rendering mode of viewport.\n"
+"The viewport's rendering mode. This controls which buffers are allocated for "
+"the viewport (2D only, or 2D + 3D). 2D-only options can reduce memory usage "
+"and improve performance slightly, especially on low-end devices.\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."
@@ -68218,6 +68367,22 @@ msgid ""
"render object this [VisualInstance] is set to."
msgstr ""
+#: doc/classes/VisualInstance.xml
+msgid ""
+"The sorting offset used by this [VisualInstance]. Adjusting it to a higher "
+"value will make the [VisualInstance] reliably draw on top of other "
+"[VisualInstance]s that are otherwise positioned at the same spot."
+msgstr ""
+
+#: doc/classes/VisualInstance.xml
+msgid ""
+"If [code]true[/code], the object is sorted based on the [AABB] center. "
+"Sorted based on the global position otherwise.\n"
+"The [AABB] center based sorting is generally more accurate for 3D models. "
+"The position based sorting instead allows to better control the drawing "
+"order when working with [Particles] and [CPUParticles]."
+msgstr ""
+
#: modules/visual_script/doc_classes/VisualScript.xml
msgid "A script implemented in the Visual Script programming environment."
msgstr ""
diff --git a/doc/translations/pt.po b/doc/translations/pt.po
index fce62b474f..d3d9b9aadf 100644
--- a/doc/translations/pt.po
+++ b/doc/translations/pt.po
@@ -18,8 +18,8 @@ msgid ""
msgstr ""
"Project-Id-Version: Godot Engine class reference\n"
"Report-Msgid-Bugs-To: https://github.com/godotengine/godot\n"
-"PO-Revision-Date: 2022-08-25 13:04+0000\n"
-"Last-Translator: Baiterson <baiter160@gmail.com>\n"
+"PO-Revision-Date: 2022-11-18 16:48+0000\n"
+"Last-Translator: ssantos <ssantos@web.de>\n"
"Language-Team: Portuguese <https://hosted.weblate.org/projects/godot-engine/"
"godot-class-reference/pt/>\n"
"Language: pt\n"
@@ -27,7 +27,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.14-dev\n"
+"X-Generator: Weblate 4.15-dev\n"
#: doc/tools/make_rst.py
msgid "Description"
@@ -95,7 +95,7 @@ msgstr "Setter"
#: doc/tools/make_rst.py
msgid "value"
-msgstr "valor"
+msgstr "Valor"
#: doc/tools/make_rst.py
msgid "Getter"
@@ -721,8 +721,10 @@ msgstr ""
"[/codeblock]"
#: modules/gdscript/doc_classes/@GDScript.xml
+#, fuzzy
msgid ""
-"Returns an array of dictionaries representing the current call stack.\n"
+"Returns an array of dictionaries representing the current call stack. See "
+"also [method print_stack].\n"
"[codeblock]\n"
"func _ready():\n"
" foo()\n"
@@ -737,7 +739,11 @@ msgid ""
"[codeblock]\n"
"[{function:bar, line:12, source:res://script.gd}, {function:foo, line:9, "
"source:res://script.gd}, {function:_ready, line:6, source:res://script.gd}]\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] [method get_stack] only works if the running instance is "
+"connected to a debugging server (i.e. an editor instance). [method "
+"get_stack] will not work in projects exported in release mode, or in "
+"projects exported in debug mode if not connected to a debugging server."
msgstr ""
"Retorna uma list de dicionários representando a pilha de chamada atual.\n"
"[codeblock]\n"
@@ -1386,19 +1392,17 @@ msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
-"Prints a stack track at code location, only works when running with debugger "
-"turned on.\n"
+"Prints a stack trace at the current code location. See also [method "
+"get_stack].\n"
"Output in the console would look something like this:\n"
"[codeblock]\n"
"Frame 0 - res://test.gd:16 in function '_process'\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] [method print_stack] only works if the running instance is "
+"connected to a debugging server (i.e. an editor instance). [method "
+"print_stack] will not work in projects exported in release mode, or in "
+"projects exported in debug mode if not connected to a debugging server."
msgstr ""
-"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 ""
@@ -4471,6 +4475,26 @@ msgid "Hints that an image is compressed using lossless compression."
msgstr ""
#: doc/classes/@GlobalScope.xml
+msgid ""
+"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:\n"
+"[codeblock]\n"
+"hint_string = \"%s:\" % [TYPE_INT] # Array of inteters.\n"
+"hint_string = \"%s:%s:\" % [TYPE_ARRAY, TYPE_REAL] # Two-dimensional array "
+"of floats.\n"
+"hint_string = \"%s/%s:Resource\" % [TYPE_OBJECT, TYPE_OBJECT] # Array of "
+"resources.\n"
+"hint_string = \"%s:%s/%s:Resource\" % [TYPE_ARRAY, TYPE_OBJECT, TYPE_OBJECT] "
+"# Two-dimensional array of resources.\n"
+"[/codeblock]\n"
+"[b]Note:[/b] The final colon is required to specify for properly detecting "
+"built-in types."
+msgstr ""
+
+#: doc/classes/@GlobalScope.xml
msgid "The property is serialized and saved in the scene file (default)."
msgstr ""
@@ -5159,8 +5183,7 @@ msgstr ""
#: doc/classes/AudioStreamPlayer.xml doc/classes/Button.xml
#: doc/classes/CanvasLayer.xml doc/classes/CollisionShape2D.xml
#: doc/classes/ColorRect.xml doc/classes/Input.xml doc/classes/InputEvent.xml
-#: doc/classes/InputEventAction.xml doc/classes/Label.xml
-#: doc/classes/Particles2D.xml doc/classes/Timer.xml
+#: doc/classes/InputEventAction.xml doc/classes/Label.xml doc/classes/Timer.xml
#: doc/classes/VisibilityNotifier2D.xml
msgid "2D Dodge The Creeps Demo"
msgstr ""
@@ -8090,7 +8113,10 @@ msgid ""
"var array = []\n"
"array.resize(10)\n"
"array.fill(0) # Initialize the 10 elements to 0.\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] If [code]value[/code] is of a reference type ([Object]-derived, "
+"[Array], [Dictionary], etc.) then the array is filled with the references to "
+"the same object, i.e. no duplicates are created."
msgstr ""
#: doc/classes/Array.xml doc/classes/PoolByteArray.xml
@@ -8275,6 +8301,9 @@ msgstr ""
#: doc/classes/Array.xml
msgid ""
"Sorts the array.\n"
+"[b]Note:[/b] The sorting algorithm used is not [url=https://en.wikipedia.org/"
+"wiki/Sorting_algorithm#Stability]stable[/url]. This means that values "
+"considered equal may have their order changed when using [method sort].\n"
"[b]Note:[/b] Strings are sorted in alphabetical order (as opposed to natural "
"order). This may lead to unexpected behavior when sorting an array of "
"strings ending with a sequence of numbers. Consider the following example:\n"
@@ -8294,9 +8323,13 @@ msgid ""
"For two elements [code]a[/code] and [code]b[/code], if the given method "
"returns [code]true[/code], element [code]b[/code] will be after element "
"[code]a[/code] in the array.\n"
+"[b]Note:[/b] The sorting algorithm used is not [url=https://en.wikipedia.org/"
+"wiki/Sorting_algorithm#Stability]stable[/url]. This means that values "
+"considered equal may have their order changed when using [method "
+"sort_custom].\n"
"[b]Note:[/b] You cannot randomize the return value as the heapsort algorithm "
-"expects a deterministic result. Doing so will result in unexpected "
-"behavior.\n"
+"expects a deterministic result. Randomizing the return value will result in "
+"unexpected behavior.\n"
"[codeblock]\n"
"class MyCustomSorter:\n"
" static func sort_ascending(a, b):\n"
@@ -10934,10 +10967,9 @@ msgstr ""
#: doc/classes/AudioStreamGeneratorPlayback.xml
msgid ""
-"Returns the number of audio data frames left to play. If this returned "
-"number reaches [code]0[/code], the audio will stop playing until frames are "
-"added again. Therefore, make sure your script can always generate and push "
-"new audio frames fast enough to avoid audio cracking."
+"Returns the number of frames that can be pushed to the audio sample data "
+"buffer without overflowing it. If the result is [code]0[/code], the buffer "
+"is full."
msgstr ""
#: doc/classes/AudioStreamGeneratorPlayback.xml
@@ -11469,14 +11501,14 @@ msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
"Node for back-buffering the currently-displayed screen. The region defined "
-"in the BackBufferCopy node is buffered with the content of the screen it "
+"in the [BackBufferCopy] node is buffered with the content of the screen it "
"covers, or the entire screen according to the copy mode set. Use the "
"[code]texture(SCREEN_TEXTURE, ...)[/code] function in your shader scripts to "
"access the buffer.\n"
"[b]Note:[/b] Since this node inherits from [Node2D] (and not [Control]), "
"anchors and margins won't apply to child [Control]-derived nodes. This can "
"be problematic when resizing the window. To avoid this, add [Control]-"
-"derived nodes as [i]siblings[/i] to the BackBufferCopy node instead of "
+"derived nodes as [i]siblings[/i] to the [BackBufferCopy] node instead of "
"adding them as children."
msgstr ""
@@ -11486,22 +11518,22 @@ msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
-"The area covered by the BackBufferCopy. Only used if [member copy_mode] is "
+"The area covered by the [BackBufferCopy]. Only used if [member copy_mode] is "
"[constant COPY_MODE_RECT]."
msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
-"Disables the buffering mode. This means the BackBufferCopy node will "
+"Disables the buffering mode. This means the [BackBufferCopy] node will "
"directly use the portion of screen it covers."
msgstr ""
#: doc/classes/BackBufferCopy.xml
-msgid "BackBufferCopy buffers a rectangular region."
+msgid "[BackBufferCopy] buffers a rectangular region."
msgstr ""
#: doc/classes/BackBufferCopy.xml
-msgid "BackBufferCopy buffers the entire screen."
+msgid "[BackBufferCopy] buffers the entire screen."
msgstr ""
#: doc/classes/BakedLightmap.xml
@@ -20332,6 +20364,14 @@ msgid "Cylinder shape for collisions."
msgstr ""
#: doc/classes/CylinderShape.xml
+msgid ""
+"Cylinder shape for collisions.\n"
+"[b]Note:[/b] When using GodotPhysics instead of the default Bullet physics "
+"engine, there are several known bugs with cylinder collision shapes. Using "
+"[CapsuleShape] or [BoxShape] instead is recommended."
+msgstr ""
+
+#: doc/classes/CylinderShape.xml
msgid "The cylinder's height."
msgstr "A altura do cilindro."
@@ -23167,7 +23207,10 @@ msgid ""
"[/codeblock]\n"
"[b]Note:[/b] The script is run in the Editor context, which means the output "
"is visible in the console window started with the Editor (stdout) instead of "
-"the usual Godot [b]Output[/b] dock."
+"the usual Godot [b]Output[/b] dock.\n"
+"[b]Note:[/b] EditorScript is reference counted, meaning it is destroyed when "
+"nothing references it. This can cause errors during asynchronous operations "
+"if there are no references to the script."
msgstr ""
#: doc/classes/EditorScript.xml
@@ -24995,7 +25038,7 @@ msgstr ""
#: doc/classes/File.xml
msgid "File system"
-msgstr ""
+msgstr "Sistema de arquivos"
#: doc/classes/File.xml
msgid ""
@@ -33909,7 +33952,9 @@ msgid ""
"The size of the light in Godot units. Only considered in baked lightmaps and "
"only if [member light_bake_mode] is set to [constant BAKE_ALL]. Increasing "
"this value will make the shadows appear blurrier. This can be used to "
-"simulate area lights to an extent."
+"simulate area lights to an extent.\n"
+"[b]Note:[/b] [member light_size] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/Light.xml
@@ -37237,7 +37282,10 @@ msgid ""
"use the [method get_next_location] function once every physics frame to "
"update the internal path logic of the NavigationAgent. The returned vector "
"position from this function should be used as the next movement position for "
-"the agent's parent Node."
+"the agent's parent Node.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues."
msgstr ""
#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
@@ -37488,7 +37536,10 @@ msgid ""
"use the [method get_next_location] function once every physics frame to "
"update the internal path logic of the NavigationAgent. The returned vector "
"position from this function should be used as the next movement position for "
-"the agent's parent Node."
+"the agent's parent Node.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues."
msgstr ""
#: doc/classes/NavigationAgent2D.xml
@@ -38205,6 +38256,9 @@ msgid ""
"modified velocity as-is might lead to pushing and agent outside of a "
"navigable area. This is a limitation of the collision avoidance system, any "
"more complex situation may require the use of the physics engine.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues.\n"
"This server keeps tracks of any call and executes them during the sync "
"phase. This means that you can request any change to the map, using any "
"thread, without worrying."
@@ -38878,9 +38932,8 @@ msgid ""
msgstr ""
#: doc/classes/Node.xml
-#, fuzzy
msgid "Nodes and Scenes"
-msgstr "Nós e Cenas"
+msgstr "Nós e cenas"
#: doc/classes/Node.xml
msgid "All Demos"
@@ -41015,7 +41068,9 @@ msgid ""
"The light's radius. Note that the effectively lit area may appear to be "
"smaller depending on the [member omni_attenuation] in use. No matter the "
"[member omni_attenuation] in use, the light will never reach anything "
-"outside this radius."
+"outside this radius.\n"
+"[b]Note:[/b] [member omni_range] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -41528,11 +41583,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] cache data directory according to the operating "
-"system's standards. On desktop platforms, this path can be overridden by "
-"setting the [code]XDG_CACHE_HOME[/code] environment variable before starting "
-"the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in "
-"Godot projects[/url] in the documentation for more information. See also "
-"[method get_config_dir] and [method get_data_dir].\n"
+"system's standards. On Linux, this path can be overridden by setting the "
+"[code]XDG_CACHE_HOME[/code] environment variable before starting the "
+"project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot "
+"projects[/url] in the documentation for more information. See also [method "
+"get_config_dir] and [method get_data_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -41566,11 +41621,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] user configuration directory according to the "
-"operating system's standards. On desktop platforms, this path can be "
-"overridden by setting the [code]XDG_CONFIG_HOME[/code] environment variable "
-"before starting the project. See [url=$DOCS_URL/tutorials/io/data_paths."
-"html]File paths in Godot projects[/url] in the documentation for more "
-"information. See also [method get_cache_dir] and [method get_data_dir].\n"
+"operating system's standards. On Linux, this path can be overridden by "
+"setting the [code]XDG_CONFIG_HOME[/code] environment variable before "
+"starting the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File "
+"paths in Godot projects[/url] in the documentation for more information. See "
+"also [method get_cache_dir] and [method get_data_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -41592,11 +41647,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] user data directory according to the operating "
-"system's standards. On desktop platforms, this path can be overridden by "
-"setting the [code]XDG_DATA_HOME[/code] environment variable before starting "
-"the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in "
-"Godot projects[/url] in the documentation for more information. See also "
-"[method get_cache_dir] and [method get_config_dir].\n"
+"system's standards. On Linux, this path can be overridden by setting the "
+"[code]XDG_DATA_HOME[/code] environment variable before starting the project. "
+"See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot "
+"projects[/url] in the documentation for more information. See also [method "
+"get_cache_dir] and [method get_config_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -43446,6 +43501,16 @@ msgid "Particle systems (2D)"
msgstr ""
#: doc/classes/Particles2D.xml
+msgid "2D Particles Demo"
+msgstr ""
+
+#: doc/classes/Particles2D.xml
+msgid ""
+"2D Dodge The Creeps Demo (uses GPUParticles2D for the trail behind the "
+"player)"
+msgstr ""
+
+#: doc/classes/Particles2D.xml
msgid "Returns a rectangle containing the positions of all existing particles."
msgstr ""
@@ -51104,15 +51169,22 @@ msgstr ""
#: doc/classes/ProjectSettings.xml
msgid ""
"If [code]true[/code], uses a fast post-processing filter to make banding "
-"significantly less visible. In some cases, debanding may introduce a "
-"slightly noticeable dithering pattern. It's recommended to enable debanding "
-"only when actually needed since the dithering pattern will make lossless-"
-"compressed screenshots larger.\n"
+"significantly less visible in 3D. 2D rendering is [i]not[/i] affected by "
+"debanding unless the [member Environment.background_mode] is [constant "
+"Environment.BG_CANVAS]. In this case, [member rendering/quality/"
+"intended_usage/framebuffer_allocation] must also be set to [b]3D[/b].\n"
+"In some cases, debanding may introduce a slightly noticeable dithering "
+"pattern. It's recommended to enable debanding only when actually needed "
+"since the dithering pattern will make lossless-compressed screenshots "
+"larger.\n"
"[b]Note:[/b] Only available on the GLES3 backend. [member rendering/quality/"
"depth/hdr] must also be [code]true[/code] for debanding to be effective.\n"
"[b]Note:[/b] There are known issues with debanding breaking rendering on "
"mobile platforms. Due to this, it is recommended to leave this option "
-"disabled when targeting mobile platforms."
+"disabled when targeting mobile platforms.\n"
+"[b]Note:[/b] This property is only read when the project starts. To set "
+"debanding at run-time, set [member Viewport.debanding] on the root "
+"[Viewport] instead."
msgstr ""
#: doc/classes/ProjectSettings.xml
@@ -52708,17 +52780,28 @@ msgstr ""
#: modules/regex/doc_classes/RegEx.xml
msgid ""
"Searches the text for the compiled pattern. Returns a [RegExMatch] container "
-"of the first matching result if found, otherwise [code]null[/code]. The "
-"region to search within can be specified without modifying where the start "
-"and end anchor would be."
+"of the first matching result if found, otherwise [code]null[/code].\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegEx.xml
msgid ""
"Searches the text for the compiled pattern. Returns an array of [RegExMatch] "
"containers for each non-overlapping result. If no results were found, an "
-"empty array is returned instead. The region to search within can be "
-"specified without modifying where the start and end anchor would be."
+"empty array is returned instead.\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegEx.xml
@@ -52727,8 +52810,14 @@ msgid ""
"specified string. Escapes and backreferences such as [code]$1[/code] and "
"[code]$name[/code] are expanded and resolved. By default, only the first "
"instance is replaced, but it can be changed for all instances (global "
-"replacement). The region to search within can be specified without modifying "
-"where the start and end anchor would be."
+"replacement).\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegExMatch.xml
@@ -55446,7 +55535,11 @@ msgid "Call a group immediately (calls are normally made on idle)."
msgstr ""
#: doc/classes/SceneTree.xml
-msgid "Call a group only once even if the call is executed many times."
+msgid ""
+"Call a group only once even if the call is executed many times.\n"
+"[b]Note:[/b] Arguments are not taken into account when deciding whether the "
+"call is unique or not. Therefore when the same method is called with "
+"different arguments, only the first call will be performed."
msgstr ""
#: doc/classes/SceneTree.xml
@@ -57285,7 +57378,9 @@ msgid ""
"[b]Note:[/b] Mixed negative scales in 3D are not decomposable from the "
"transformation matrix. Due to the way scale is represented with "
"transformation matrices in Godot, the scale values will either be all "
-"positive or all negative."
+"positive or all negative.\n"
+"[b]Note:[/b] Not all nodes are visually scaled by the [member scale] "
+"property. For example, [Light]s are not visually affected by [member scale]."
msgstr ""
#: doc/classes/Spatial.xml
@@ -58681,7 +58776,10 @@ msgid ""
msgstr ""
#: doc/classes/SpotLight.xml
-msgid "The spotlight's angle in degrees."
+msgid ""
+"The spotlight's angle in degrees.\n"
+"[b]Note:[/b] [member spot_angle] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/SpotLight.xml
@@ -58697,7 +58795,9 @@ msgid ""
"The maximal range that can be reached by the spotlight. Note that the "
"effectively lit area may appear to be smaller depending on the [member "
"spot_attenuation] in use. No matter the [member spot_attenuation] in use, "
-"the light will never reach anything outside this range."
+"the light will never reach anything outside this range.\n"
+"[b]Note:[/b] [member spot_range] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/SpringArm.xml
@@ -67998,10 +68098,15 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
"If [code]true[/code], uses a fast post-processing filter to make banding "
-"significantly less visible. In some cases, debanding may introduce a "
-"slightly noticeable dithering pattern. It's recommended to enable debanding "
-"only when actually needed since the dithering pattern will make lossless-"
-"compressed screenshots larger.\n"
+"significantly less visible in 3D. 2D rendering is [i]not[/i] affected by "
+"debanding unless the [member Environment.background_mode] is [constant "
+"Environment.BG_CANVAS]. In this case, [member usage] must also be set to "
+"[constant USAGE_3D]. See also [member ProjectSettings.rendering/quality/"
+"filters/use_debanding].\n"
+"In some cases, debanding may introduce a slightly noticeable dithering "
+"pattern. It's recommended to enable debanding only when actually needed "
+"since the dithering pattern will make lossless-compressed screenshots "
+"larger.\n"
"[b]Note:[/b] Only available on the GLES3 backend. [member hdr] must also be "
"[code]true[/code] for debanding to be effective."
msgstr ""
@@ -68012,8 +68117,8 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
-"If [code]true[/code], the viewport will disable 3D rendering. For actual "
-"disabling use [code]usage[/code]."
+"If [code]true[/code], the viewport will disable 3D rendering. To actually "
+"disable allocation of 3D buffers, set [member usage] instead."
msgstr ""
#: doc/classes/Viewport.xml
@@ -68165,7 +68270,9 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
-"The rendering mode of viewport.\n"
+"The viewport's rendering mode. This controls which buffers are allocated for "
+"the viewport (2D only, or 2D + 3D). 2D-only options can reduce memory usage "
+"and improve performance slightly, especially on low-end devices.\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."
@@ -68697,6 +68804,22 @@ msgid ""
"render object this [VisualInstance] is set to."
msgstr ""
+#: doc/classes/VisualInstance.xml
+msgid ""
+"The sorting offset used by this [VisualInstance]. Adjusting it to a higher "
+"value will make the [VisualInstance] reliably draw on top of other "
+"[VisualInstance]s that are otherwise positioned at the same spot."
+msgstr ""
+
+#: doc/classes/VisualInstance.xml
+msgid ""
+"If [code]true[/code], the object is sorted based on the [AABB] center. "
+"Sorted based on the global position otherwise.\n"
+"The [AABB] center based sorting is generally more accurate for 3D models. "
+"The position based sorting instead allows to better control the drawing "
+"order when working with [Particles] and [CPUParticles]."
+msgstr ""
+
#: modules/visual_script/doc_classes/VisualScript.xml
msgid "A script implemented in the Visual Script programming environment."
msgstr ""
diff --git a/doc/translations/pt_BR.po b/doc/translations/pt_BR.po
index f6705f5e4c..463bc9c957 100644
--- a/doc/translations/pt_BR.po
+++ b/doc/translations/pt_BR.po
@@ -43,12 +43,14 @@
# lucas rossy brasil coelho <lucasrossy270@gmail.com>, 2022.
# Felipe Kinoshita <kinofhek@gmail.com>, 2022.
# Mr.Albino <ricmorsoleto@gmail.com>, 2022.
+# Zer0-Zer0 <dankmemerson@tutanota.com>, 2022.
+# Julio Yagami <juliohenrique31501234@hotmail.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-08-21 06:02+0000\n"
-"Last-Translator: Jaide Alonso Ambrosio <jaide.sp@gmail.com>\n"
+"PO-Revision-Date: 2022-12-09 19:48+0000\n"
+"Last-Translator: Julio Yagami <juliohenrique31501234@hotmail.com>\n"
"Language-Team: Portuguese (Brazil) <https://hosted.weblate.org/projects/"
"godot-engine/godot-class-reference/pt_BR/>\n"
"Language: pt_BR\n"
@@ -56,7 +58,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.14-dev\n"
+"X-Generator: Weblate 4.15-dev\n"
#: doc/tools/make_rst.py
msgid "Description"
@@ -527,7 +529,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"
@@ -548,13 +549,13 @@ msgid ""
"code]."
msgstr ""
"Compara dois valores, verificando seu conteúdo real, recorrendo a qualquer "
-"`Array` ou `Dicionário` até o seu nível mais profundo.\n"
+"[Array] ou [Dictionary] até o seu nível mais profundo.\n"
"Isso se compara a [code]==[/code] de várias maneiras:\n"
"- Para [code]null[/code], [code]int[/code], [code]float[/code], "
"[code]String[/code], [code]Object[/code] e [code]RID[/code] tanto "
"[code]deep_equal[/code] quanto [code]==[/code] funcionam da mesma maneira.\n"
"- Para [code]Dictionary[/code], [code]==[code] considera igualdade se, e "
-"somente se, ambas as variáveis apontarem para o mesmo [code]Dictionary[/"
+"somente se, ambas as variáveis apontaram para o mesmo [code]Dictionary[/"
"code], sem nenhuma recorrência ou consciência do conteúdo.\n"
"- Para [code]Array[/code], [code]==[/code] considera igualdade se, e somente "
"se, cada item no primeiro [code]Array[/code] for igual a sua contraparte no "
@@ -586,7 +587,6 @@ msgstr ""
"inst2dict]), de volta em uma instância. Útil para desserialização."
#: 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 "
@@ -615,7 +615,7 @@ msgstr ""
"- Menor que -1.0 (exclusivo): Ease in-out\n"
"- 1.0: Linear\n"
"- Entre -1.0 e 0.0 (exclusivo): Ease out-in\n"
-"- 0.0: Constant\n"
+"- 0.0: Constante\n"
"- Entre 0.0 e 1.0 (exclusivo): Ease in\n"
"- 1.0: Linear\n"
"- Maior que 1.0 (exclusivo): Ease out\n"
@@ -752,8 +752,10 @@ msgstr ""
"[/codeblock]"
#: modules/gdscript/doc_classes/@GDScript.xml
+#, fuzzy
msgid ""
-"Returns an array of dictionaries representing the current call stack.\n"
+"Returns an array of dictionaries representing the current call stack. See "
+"also [method print_stack].\n"
"[codeblock]\n"
"func _ready():\n"
" foo()\n"
@@ -768,7 +770,11 @@ msgid ""
"[codeblock]\n"
"[{function:bar, line:12, source:res://script.gd}, {function:foo, line:9, "
"source:res://script.gd}, {function:_ready, line:6, source:res://script.gd}]\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] [method get_stack] only works if the running instance is "
+"connected to a debugging server (i.e. an editor instance). [method "
+"get_stack] will not work in projects exported in release mode, or in "
+"projects exported in debug mode if not connected to a debugging server."
msgstr ""
"Retorna uma list de dicionários representando a pilha de chamada atual.\n"
"[codeblock]\n"
@@ -949,7 +955,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 "
@@ -973,24 +978,25 @@ msgid ""
msgstr ""
"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, "
+"estar entre [code]0.0[/code] e [code]1.0[/code] (inclusivo). No entanto, "
"valores fora desse intervalo são permitidos e podem ser usados para realizar "
-"[i]extrapolação[/i].\n"
+"[i]extrapolação[/i]. Use [method clamp] no resultado de [method lerp] se "
+"isso não é desejado.\n"
"Se os argumentos [code]from[/code] e [code]to[/code] forem do tipo [int] ou "
"[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(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 "
-"ease] ou [method smoothstep]."
+"ease] ou [method smoothstep]. Seja também [method range_lerp] para mapear "
+"uma serie contínua de valores um para o outro."
#: modules/gdscript/doc_classes/@GDScript.xml
-#, fuzzy
msgid ""
"Linearly interpolates between two angles (in radians) by a normalized "
"value.\n"
@@ -1013,19 +1019,30 @@ 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"
+"ângulos passam através de [constant @GDScript.TAU]. Para realizar "
+"interpolação facilitada com [method lerp_angle], combine com [method ease] "
+"ou [method smoothstep].\n"
"[codeblock]\n"
"extends Sprite\n"
-"var elapsed = 0.0\n"
+"var tempo_decorrido = 0.0\n"
"func _process(delta):\n"
-" var min_angle = deg2rad(0.0)\n"
-" var max_angle = deg2rad(90.0)\n"
-" rotation = lerp_angle(min_angle, max_angle, elapsed)\n"
-" elapsed += delta\n"
-"[/codeblock]"
+" var ângulo_mínimo = deg2rad(0.0)\n"
+" var ângulo_máximo = deg2rad(90.0)\n"
+" rotação = ângulo_interpolação(ângulo_mínimo, ângulo_máximo, "
+"tempo_decorrido)\n"
+" tempo_decorrido += delta\n"
+"[/codeblock]\n"
+"[b]Nota:[/b] Esse método interpola linearmente através do caminho mais curto "
+"entre [code]from[/code] e [code]to[/code]. Entretanto, quando esses dois "
+"ângulos estão aproximadamente [code]PI + k * TAU[/code] aparte para qualquer "
+"inteiro [code]k[/code], não é óbvio para qual lado eles interpolam devido à "
+"erros de precisão de pontos flutuantes. Por exemplo, "
+"[code]ângulo_interpolação(0, PI, weight)[/code] interpola no sentido anti-"
+"horário, enquanto [code]ângulo_interpolação(0, PI + 5 * TAU, weight)[/code] "
+"interpola no sentido horário."
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
@@ -1395,19 +1412,17 @@ msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
-"Prints a stack track at code location, only works when running with debugger "
-"turned on.\n"
+"Prints a stack trace at the current code location. See also [method "
+"get_stack].\n"
"Output in the console would look something like this:\n"
"[codeblock]\n"
"Frame 0 - res://test.gd:16 in function '_process'\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] [method print_stack] only works if the running instance is "
+"connected to a debugging server (i.e. an editor instance). [method "
+"print_stack] will not work in projects exported in release mode, or in "
+"projects exported in debug mode if not connected to a debugging server."
msgstr ""
-"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 ""
@@ -1645,8 +1660,46 @@ msgid ""
"3\n"
"[/codeblock]"
msgstr ""
+"Retorna um [i]array[/i] com o alcance dado. [method range] pode ser chamado "
+"de três maneiras:\n"
+"[code]range(n: int)[/code]: Começa do 0, aumenta em passos de 1, e para "
+"[i]antes[/i] do [code]n[/code]. O argumento [code]n[/code] é [b]exclusivo[/"
+"b].\n"
+"[code]range(b: int, n: int)[/code]: Começa do [code]b[/code], aumenta em "
+"passos de 1, e para [i]antes[/i] do [code]n[/code]. Os argumentos [code]b[/"
+"code] e [code]n[/code] são [b]inclusivo[/b] e [b]exclusivo[/b], "
+"respectivamente.\n"
+"[code]range(b: int, n: int, s: int)[/code]: Começa do [code]b[/code], "
+"aumenta/diminui em passos de [code]s[/code], e para [i]antes[/i] do [code]n[/"
+"code]. Os argumentos [code]b[/code] e [code]n[/code] são [b]inclusivo[/b] e "
+"[b]exclusivo[/b], respectivamente. O argumento [code]s[/code] [b]pode[/b] "
+"ser negativo, mas não [code]0[/code]. Se [code]s[/code] é [code]0[/code], "
+"uma mensagem de erro é mostrada.\n"
+"[method range] converte todos os argumentos para [int] antes de processar.\n"
+"[b]Nota:[/b] Retorna um [i]array[/i] vazio se nenhum valor satisfaz o valor "
+"exigido (e.g. [code]range(2, 5, -1)[/code] ou [code]range(5, 5, 1)[/code]).\n"
+"Exemplos:\n"
+"[codeblock]\n"
+"print(range(4)) # Imprime [0, 1, 2, 3]\n"
+"print(range(2, 5)) # Imprime [2, 3, 4]\n"
+"print(range(0, 6, 2)) # Imprime [0, 2, 4]\n"
+"print(range(4, 1, -1)) # Imprime [4, 3, 2]\n"
+"[/codeblock]\n"
+"Para repetir sobre um [Array] ao contrário, use:\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"
+"Saída:\n"
+"[codeblock]\n"
+"9\n"
+"6\n"
+"3\n"
+"[/codeblock]"
#: modules/gdscript/doc_classes/@GDScript.xml
+#, fuzzy
msgid ""
"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 "
@@ -1659,6 +1712,17 @@ msgid ""
"For complex use cases where you need multiple ranges, consider using [Curve] "
"or [Gradient] instead."
msgstr ""
+"Mapeia um [code]value[/code] do intervalo [code][istart, istop][/code] para "
+"[code][ostart, ostop][/code]. Veja também [method lerp] e [method "
+"inverse_lerp]. Se [code]value[/code] estiver fora de [code][istart, istop][/"
+"code], então o valor resultante também será fora de [code][ostart, ostop][/"
+"code]. Use [method clamp] no resultado de [method range-lerp] se não for "
+"desejado.\n"
+"[codeblock]\n"
+"range_lerp(75, 0, 100, -1, 1) # Retorna 0.5\n"
+"[/codeblock]\n"
+"Para casos de uso complexos em que você precise de múltiplos intervalos, "
+"considere usar [Curve] ou [Gradient]."
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
@@ -3956,34 +4020,49 @@ msgstr ""
"Windows MR)."
#: doc/classes/@GlobalScope.xml
+#, fuzzy
msgid ""
"MIDI note OFF message. See the documentation of [InputEventMIDI] for "
"information of how to use MIDI inputs."
msgstr ""
+"Mensagem de nota MIDI OFF. Veja a documentação sobre [InputEventMIDI] para "
+"mais informações sobre como usar entradas MIDI."
#: doc/classes/@GlobalScope.xml
+#, fuzzy
msgid ""
"MIDI note ON message. See the documentation of [InputEventMIDI] for "
"information of how to use MIDI inputs."
msgstr ""
+"Mensagem ON da nota MIDI. Veja a documentação do [InputEventMIDI] para mais "
+"informações sobre como usar entradas MIDI."
#: doc/classes/@GlobalScope.xml
msgid ""
"MIDI aftertouch message. This message is most often sent by pressing down on "
"the key after it \"bottoms out\"."
msgstr ""
+"Mensagem MIDI de toque posterior. Esta mensagem é geralmente enviada ao "
+"pressionar a tecla após ela \"ir de fundo pra fora\"."
#: doc/classes/@GlobalScope.xml
+#, fuzzy
msgid ""
"MIDI control change message. This message is sent when a controller value "
"changes. Controllers include devices such as pedals and levers."
msgstr ""
+"Mensagem de alteração do controlador MIDI. Esta mensagem é enviada quando o "
+"valor de um controlador muda. Controladores incluem dispositivos como pedais "
+"e alavancas."
#: doc/classes/@GlobalScope.xml
+#, fuzzy
msgid ""
"MIDI program change message. This message sent when the program patch number "
"changes."
msgstr ""
+"Mensagem de alteração do programa MIDI. Esta mensagem é enviada quando o "
+"número de patch do programa muda."
#: doc/classes/@GlobalScope.xml
msgid ""
@@ -4498,6 +4577,26 @@ msgid "Hints that an image is compressed using lossless compression."
msgstr ""
#: doc/classes/@GlobalScope.xml
+msgid ""
+"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:\n"
+"[codeblock]\n"
+"hint_string = \"%s:\" % [TYPE_INT] # Array of inteters.\n"
+"hint_string = \"%s:%s:\" % [TYPE_ARRAY, TYPE_REAL] # Two-dimensional array "
+"of floats.\n"
+"hint_string = \"%s/%s:Resource\" % [TYPE_OBJECT, TYPE_OBJECT] # Array of "
+"resources.\n"
+"hint_string = \"%s:%s/%s:Resource\" % [TYPE_ARRAY, TYPE_OBJECT, TYPE_OBJECT] "
+"# Two-dimensional array of resources.\n"
+"[/codeblock]\n"
+"[b]Note:[/b] The final colon is required to specify for properly detecting "
+"built-in types."
+msgstr ""
+
+#: doc/classes/@GlobalScope.xml
msgid "The property is serialized and saved in the scene file (default)."
msgstr "A propriedade é serializada e salva no arquivo de cena (padrão)."
@@ -5195,8 +5294,7 @@ msgstr ""
#: doc/classes/AudioStreamPlayer.xml doc/classes/Button.xml
#: doc/classes/CanvasLayer.xml doc/classes/CollisionShape2D.xml
#: doc/classes/ColorRect.xml doc/classes/Input.xml doc/classes/InputEvent.xml
-#: doc/classes/InputEventAction.xml doc/classes/Label.xml
-#: doc/classes/Particles2D.xml doc/classes/Timer.xml
+#: doc/classes/InputEventAction.xml doc/classes/Label.xml doc/classes/Timer.xml
#: doc/classes/VisibilityNotifier2D.xml
msgid "2D Dodge The Creeps Demo"
msgstr ""
@@ -8144,7 +8242,10 @@ msgid ""
"var array = []\n"
"array.resize(10)\n"
"array.fill(0) # Initialize the 10 elements to 0.\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] If [code]value[/code] is of a reference type ([Object]-derived, "
+"[Array], [Dictionary], etc.) then the array is filled with the references to "
+"the same object, i.e. no duplicates are created."
msgstr ""
#: doc/classes/Array.xml doc/classes/PoolByteArray.xml
@@ -8329,6 +8430,9 @@ msgstr ""
#: doc/classes/Array.xml
msgid ""
"Sorts the array.\n"
+"[b]Note:[/b] The sorting algorithm used is not [url=https://en.wikipedia.org/"
+"wiki/Sorting_algorithm#Stability]stable[/url]. This means that values "
+"considered equal may have their order changed when using [method sort].\n"
"[b]Note:[/b] Strings are sorted in alphabetical order (as opposed to natural "
"order). This may lead to unexpected behavior when sorting an array of "
"strings ending with a sequence of numbers. Consider the following example:\n"
@@ -8348,9 +8452,13 @@ msgid ""
"For two elements [code]a[/code] and [code]b[/code], if the given method "
"returns [code]true[/code], element [code]b[/code] will be after element "
"[code]a[/code] in the array.\n"
+"[b]Note:[/b] The sorting algorithm used is not [url=https://en.wikipedia.org/"
+"wiki/Sorting_algorithm#Stability]stable[/url]. This means that values "
+"considered equal may have their order changed when using [method "
+"sort_custom].\n"
"[b]Note:[/b] You cannot randomize the return value as the heapsort algorithm "
-"expects a deterministic result. Doing so will result in unexpected "
-"behavior.\n"
+"expects a deterministic result. Randomizing the return value will result in "
+"unexpected behavior.\n"
"[codeblock]\n"
"class MyCustomSorter:\n"
" static func sort_ascending(a, b):\n"
@@ -10990,10 +11098,9 @@ msgstr ""
#: doc/classes/AudioStreamGeneratorPlayback.xml
msgid ""
-"Returns the number of audio data frames left to play. If this returned "
-"number reaches [code]0[/code], the audio will stop playing until frames are "
-"added again. Therefore, make sure your script can always generate and push "
-"new audio frames fast enough to avoid audio cracking."
+"Returns the number of frames that can be pushed to the audio sample data "
+"buffer without overflowing it. If the result is [code]0[/code], the buffer "
+"is full."
msgstr ""
#: doc/classes/AudioStreamGeneratorPlayback.xml
@@ -11525,14 +11632,14 @@ msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
"Node for back-buffering the currently-displayed screen. The region defined "
-"in the BackBufferCopy node is buffered with the content of the screen it "
+"in the [BackBufferCopy] node is buffered with the content of the screen it "
"covers, or the entire screen according to the copy mode set. Use the "
"[code]texture(SCREEN_TEXTURE, ...)[/code] function in your shader scripts to "
"access the buffer.\n"
"[b]Note:[/b] Since this node inherits from [Node2D] (and not [Control]), "
"anchors and margins won't apply to child [Control]-derived nodes. This can "
"be problematic when resizing the window. To avoid this, add [Control]-"
-"derived nodes as [i]siblings[/i] to the BackBufferCopy node instead of "
+"derived nodes as [i]siblings[/i] to the [BackBufferCopy] node instead of "
"adding them as children."
msgstr ""
@@ -11542,22 +11649,22 @@ msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
-"The area covered by the BackBufferCopy. Only used if [member copy_mode] is "
+"The area covered by the [BackBufferCopy]. Only used if [member copy_mode] is "
"[constant COPY_MODE_RECT]."
msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
-"Disables the buffering mode. This means the BackBufferCopy node will "
+"Disables the buffering mode. This means the [BackBufferCopy] node will "
"directly use the portion of screen it covers."
msgstr ""
#: doc/classes/BackBufferCopy.xml
-msgid "BackBufferCopy buffers a rectangular region."
+msgid "[BackBufferCopy] buffers a rectangular region."
msgstr ""
#: doc/classes/BackBufferCopy.xml
-msgid "BackBufferCopy buffers the entire screen."
+msgid "[BackBufferCopy] buffers the entire screen."
msgstr ""
#: doc/classes/BakedLightmap.xml
@@ -15656,7 +15763,7 @@ msgstr ""
#: doc/classes/Color.xml
msgid "Chocolate color."
-msgstr "Cor chocolate"
+msgstr "Cor chocolate."
#: doc/classes/Color.xml
msgid "Coral color."
@@ -20442,6 +20549,14 @@ msgid "Cylinder shape for collisions."
msgstr ""
#: doc/classes/CylinderShape.xml
+msgid ""
+"Cylinder shape for collisions.\n"
+"[b]Note:[/b] When using GodotPhysics instead of the default Bullet physics "
+"engine, there are several known bugs with cylinder collision shapes. Using "
+"[CapsuleShape] or [BoxShape] instead is recommended."
+msgstr ""
+
+#: doc/classes/CylinderShape.xml
msgid "The cylinder's height."
msgstr "A altura do cilindro."
@@ -23280,7 +23395,10 @@ msgid ""
"[/codeblock]\n"
"[b]Note:[/b] The script is run in the Editor context, which means the output "
"is visible in the console window started with the Editor (stdout) instead of "
-"the usual Godot [b]Output[/b] dock."
+"the usual Godot [b]Output[/b] dock.\n"
+"[b]Note:[/b] EditorScript is reference counted, meaning it is destroyed when "
+"nothing references it. This can cause errors during asynchronous operations "
+"if there are no references to the script."
msgstr ""
#: doc/classes/EditorScript.xml
@@ -34072,7 +34190,9 @@ msgid ""
"The size of the light in Godot units. Only considered in baked lightmaps and "
"only if [member light_bake_mode] is set to [constant BAKE_ALL]. Increasing "
"this value will make the shadows appear blurrier. This can be used to "
-"simulate area lights to an extent."
+"simulate area lights to an extent.\n"
+"[b]Note:[/b] [member light_size] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/Light.xml
@@ -37411,7 +37531,10 @@ msgid ""
"use the [method get_next_location] function once every physics frame to "
"update the internal path logic of the NavigationAgent. The returned vector "
"position from this function should be used as the next movement position for "
-"the agent's parent Node."
+"the agent's parent Node.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues."
msgstr ""
#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
@@ -37664,7 +37787,10 @@ msgid ""
"use the [method get_next_location] function once every physics frame to "
"update the internal path logic of the NavigationAgent. The returned vector "
"position from this function should be used as the next movement position for "
-"the agent's parent Node."
+"the agent's parent Node.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues."
msgstr ""
#: doc/classes/NavigationAgent2D.xml
@@ -38389,6 +38515,9 @@ msgid ""
"modified velocity as-is might lead to pushing and agent outside of a "
"navigable area. This is a limitation of the collision avoidance system, any "
"more complex situation may require the use of the physics engine.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues.\n"
"This server keeps tracks of any call and executes them during the sync "
"phase. This means that you can request any change to the map, using any "
"thread, without worrying."
@@ -41199,7 +41328,9 @@ msgid ""
"The light's radius. Note that the effectively lit area may appear to be "
"smaller depending on the [member omni_attenuation] in use. No matter the "
"[member omni_attenuation] in use, the light will never reach anything "
-"outside this radius."
+"outside this radius.\n"
+"[b]Note:[/b] [member omni_range] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -41716,11 +41847,11 @@ msgstr "Retorna o ângulo para o vetor dado, em radianos."
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] cache data directory according to the operating "
-"system's standards. On desktop platforms, this path can be overridden by "
-"setting the [code]XDG_CACHE_HOME[/code] environment variable before starting "
-"the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in "
-"Godot projects[/url] in the documentation for more information. See also "
-"[method get_config_dir] and [method get_data_dir].\n"
+"system's standards. On Linux, this path can be overridden by setting the "
+"[code]XDG_CACHE_HOME[/code] environment variable before starting the "
+"project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot "
+"projects[/url] in the documentation for more information. See also [method "
+"get_config_dir] and [method get_data_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -41754,11 +41885,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] user configuration directory according to the "
-"operating system's standards. On desktop platforms, this path can be "
-"overridden by setting the [code]XDG_CONFIG_HOME[/code] environment variable "
-"before starting the project. See [url=$DOCS_URL/tutorials/io/data_paths."
-"html]File paths in Godot projects[/url] in the documentation for more "
-"information. See also [method get_cache_dir] and [method get_data_dir].\n"
+"operating system's standards. On Linux, this path can be overridden by "
+"setting the [code]XDG_CONFIG_HOME[/code] environment variable before "
+"starting the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File "
+"paths in Godot projects[/url] in the documentation for more information. See "
+"also [method get_cache_dir] and [method get_data_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -41780,11 +41911,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] user data directory according to the operating "
-"system's standards. On desktop platforms, this path can be overridden by "
-"setting the [code]XDG_DATA_HOME[/code] environment variable before starting "
-"the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in "
-"Godot projects[/url] in the documentation for more information. See also "
-"[method get_cache_dir] and [method get_config_dir].\n"
+"system's standards. On Linux, this path can be overridden by setting the "
+"[code]XDG_DATA_HOME[/code] environment variable before starting the project. "
+"See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot "
+"projects[/url] in the documentation for more information. See also [method "
+"get_cache_dir] and [method get_config_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -43666,6 +43797,16 @@ msgid "Particle systems (2D)"
msgstr ""
#: doc/classes/Particles2D.xml
+msgid "2D Particles Demo"
+msgstr ""
+
+#: doc/classes/Particles2D.xml
+msgid ""
+"2D Dodge The Creeps Demo (uses GPUParticles2D for the trail behind the "
+"player)"
+msgstr ""
+
+#: doc/classes/Particles2D.xml
msgid "Returns a rectangle containing the positions of all existing particles."
msgstr ""
@@ -51274,15 +51415,22 @@ msgstr ""
#: doc/classes/ProjectSettings.xml
msgid ""
"If [code]true[/code], uses a fast post-processing filter to make banding "
-"significantly less visible. In some cases, debanding may introduce a "
-"slightly noticeable dithering pattern. It's recommended to enable debanding "
-"only when actually needed since the dithering pattern will make lossless-"
-"compressed screenshots larger.\n"
+"significantly less visible in 3D. 2D rendering is [i]not[/i] affected by "
+"debanding unless the [member Environment.background_mode] is [constant "
+"Environment.BG_CANVAS]. In this case, [member rendering/quality/"
+"intended_usage/framebuffer_allocation] must also be set to [b]3D[/b].\n"
+"In some cases, debanding may introduce a slightly noticeable dithering "
+"pattern. It's recommended to enable debanding only when actually needed "
+"since the dithering pattern will make lossless-compressed screenshots "
+"larger.\n"
"[b]Note:[/b] Only available on the GLES3 backend. [member rendering/quality/"
"depth/hdr] must also be [code]true[/code] for debanding to be effective.\n"
"[b]Note:[/b] There are known issues with debanding breaking rendering on "
"mobile platforms. Due to this, it is recommended to leave this option "
-"disabled when targeting mobile platforms."
+"disabled when targeting mobile platforms.\n"
+"[b]Note:[/b] This property is only read when the project starts. To set "
+"debanding at run-time, set [member Viewport.debanding] on the root "
+"[Viewport] instead."
msgstr ""
#: doc/classes/ProjectSettings.xml
@@ -52886,17 +53034,28 @@ msgstr ""
#: modules/regex/doc_classes/RegEx.xml
msgid ""
"Searches the text for the compiled pattern. Returns a [RegExMatch] container "
-"of the first matching result if found, otherwise [code]null[/code]. The "
-"region to search within can be specified without modifying where the start "
-"and end anchor would be."
+"of the first matching result if found, otherwise [code]null[/code].\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegEx.xml
msgid ""
"Searches the text for the compiled pattern. Returns an array of [RegExMatch] "
"containers for each non-overlapping result. If no results were found, an "
-"empty array is returned instead. The region to search within can be "
-"specified without modifying where the start and end anchor would be."
+"empty array is returned instead.\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegEx.xml
@@ -52905,8 +53064,14 @@ msgid ""
"specified string. Escapes and backreferences such as [code]$1[/code] and "
"[code]$name[/code] are expanded and resolved. By default, only the first "
"instance is replaced, but it can be changed for all instances (global "
-"replacement). The region to search within can be specified without modifying "
-"where the start and end anchor would be."
+"replacement).\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegExMatch.xml
@@ -55625,7 +55790,11 @@ msgid "Call a group immediately (calls are normally made on idle)."
msgstr ""
#: doc/classes/SceneTree.xml
-msgid "Call a group only once even if the call is executed many times."
+msgid ""
+"Call a group only once even if the call is executed many times.\n"
+"[b]Note:[/b] Arguments are not taken into account when deciding whether the "
+"call is unique or not. Therefore when the same method is called with "
+"different arguments, only the first call will be performed."
msgstr ""
#: doc/classes/SceneTree.xml
@@ -57467,7 +57636,9 @@ msgid ""
"[b]Note:[/b] Mixed negative scales in 3D are not decomposable from the "
"transformation matrix. Due to the way scale is represented with "
"transformation matrices in Godot, the scale values will either be all "
-"positive or all negative."
+"positive or all negative.\n"
+"[b]Note:[/b] Not all nodes are visually scaled by the [member scale] "
+"property. For example, [Light]s are not visually affected by [member scale]."
msgstr ""
#: doc/classes/Spatial.xml
@@ -58866,7 +59037,10 @@ msgid ""
msgstr ""
#: doc/classes/SpotLight.xml
-msgid "The spotlight's angle in degrees."
+msgid ""
+"The spotlight's angle in degrees.\n"
+"[b]Note:[/b] [member spot_angle] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/SpotLight.xml
@@ -58882,7 +59056,9 @@ msgid ""
"The maximal range that can be reached by the spotlight. Note that the "
"effectively lit area may appear to be smaller depending on the [member "
"spot_attenuation] in use. No matter the [member spot_attenuation] in use, "
-"the light will never reach anything outside this range."
+"the light will never reach anything outside this range.\n"
+"[b]Note:[/b] [member spot_range] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/SpringArm.xml
@@ -68220,10 +68396,15 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
"If [code]true[/code], uses a fast post-processing filter to make banding "
-"significantly less visible. In some cases, debanding may introduce a "
-"slightly noticeable dithering pattern. It's recommended to enable debanding "
-"only when actually needed since the dithering pattern will make lossless-"
-"compressed screenshots larger.\n"
+"significantly less visible in 3D. 2D rendering is [i]not[/i] affected by "
+"debanding unless the [member Environment.background_mode] is [constant "
+"Environment.BG_CANVAS]. In this case, [member usage] must also be set to "
+"[constant USAGE_3D]. See also [member ProjectSettings.rendering/quality/"
+"filters/use_debanding].\n"
+"In some cases, debanding may introduce a slightly noticeable dithering "
+"pattern. It's recommended to enable debanding only when actually needed "
+"since the dithering pattern will make lossless-compressed screenshots "
+"larger.\n"
"[b]Note:[/b] Only available on the GLES3 backend. [member hdr] must also be "
"[code]true[/code] for debanding to be effective."
msgstr ""
@@ -68234,8 +68415,8 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
-"If [code]true[/code], the viewport will disable 3D rendering. For actual "
-"disabling use [code]usage[/code]."
+"If [code]true[/code], the viewport will disable 3D rendering. To actually "
+"disable allocation of 3D buffers, set [member usage] instead."
msgstr ""
#: doc/classes/Viewport.xml
@@ -68393,7 +68574,9 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
-"The rendering mode of viewport.\n"
+"The viewport's rendering mode. This controls which buffers are allocated for "
+"the viewport (2D only, or 2D + 3D). 2D-only options can reduce memory usage "
+"and improve performance slightly, especially on low-end devices.\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."
@@ -68926,6 +69109,22 @@ msgid ""
"render object this [VisualInstance] is set to."
msgstr ""
+#: doc/classes/VisualInstance.xml
+msgid ""
+"The sorting offset used by this [VisualInstance]. Adjusting it to a higher "
+"value will make the [VisualInstance] reliably draw on top of other "
+"[VisualInstance]s that are otherwise positioned at the same spot."
+msgstr ""
+
+#: doc/classes/VisualInstance.xml
+msgid ""
+"If [code]true[/code], the object is sorted based on the [AABB] center. "
+"Sorted based on the global position otherwise.\n"
+"The [AABB] center based sorting is generally more accurate for 3D models. "
+"The position based sorting instead allows to better control the drawing "
+"order when working with [Particles] and [CPUParticles]."
+msgstr ""
+
#: modules/visual_script/doc_classes/VisualScript.xml
msgid "A script implemented in the Visual Script programming environment."
msgstr ""
@@ -77080,10 +77279,10 @@ 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."
+"que têm uma posição Y mais baixa.\n"
+"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 04f1a17b66..dd88e8d66b 100644
--- a/doc/translations/ro.po
+++ b/doc/translations/ro.po
@@ -501,7 +501,8 @@ msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
-"Returns an array of dictionaries representing the current call stack.\n"
+"Returns an array of dictionaries representing the current call stack. See "
+"also [method print_stack].\n"
"[codeblock]\n"
"func _ready():\n"
" foo()\n"
@@ -516,7 +517,11 @@ msgid ""
"[codeblock]\n"
"[{function:bar, line:12, source:res://script.gd}, {function:foo, line:9, "
"source:res://script.gd}, {function:_ready, line:6, source:res://script.gd}]\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] [method get_stack] only works if the running instance is "
+"connected to a debugging server (i.e. an editor instance). [method "
+"get_stack] will not work in projects exported in release mode, or in "
+"projects exported in debug mode if not connected to a debugging server."
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -889,12 +894,16 @@ msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
-"Prints a stack track at code location, only works when running with debugger "
-"turned on.\n"
+"Prints a stack trace at the current code location. See also [method "
+"get_stack].\n"
"Output in the console would look something like this:\n"
"[codeblock]\n"
"Frame 0 - res://test.gd:16 in function '_process'\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] [method print_stack] only works if the running instance is "
+"connected to a debugging server (i.e. an editor instance). [method "
+"print_stack] will not work in projects exported in release mode, or in "
+"projects exported in debug mode if not connected to a debugging server."
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -3509,6 +3518,26 @@ msgid "Hints that an image is compressed using lossless compression."
msgstr ""
#: doc/classes/@GlobalScope.xml
+msgid ""
+"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:\n"
+"[codeblock]\n"
+"hint_string = \"%s:\" % [TYPE_INT] # Array of inteters.\n"
+"hint_string = \"%s:%s:\" % [TYPE_ARRAY, TYPE_REAL] # Two-dimensional array "
+"of floats.\n"
+"hint_string = \"%s/%s:Resource\" % [TYPE_OBJECT, TYPE_OBJECT] # Array of "
+"resources.\n"
+"hint_string = \"%s:%s/%s:Resource\" % [TYPE_ARRAY, TYPE_OBJECT, TYPE_OBJECT] "
+"# Two-dimensional array of resources.\n"
+"[/codeblock]\n"
+"[b]Note:[/b] The final colon is required to specify for properly detecting "
+"built-in types."
+msgstr ""
+
+#: doc/classes/@GlobalScope.xml
msgid "The property is serialized and saved in the scene file (default)."
msgstr ""
@@ -4193,8 +4222,7 @@ msgstr ""
#: doc/classes/AudioStreamPlayer.xml doc/classes/Button.xml
#: doc/classes/CanvasLayer.xml doc/classes/CollisionShape2D.xml
#: doc/classes/ColorRect.xml doc/classes/Input.xml doc/classes/InputEvent.xml
-#: doc/classes/InputEventAction.xml doc/classes/Label.xml
-#: doc/classes/Particles2D.xml doc/classes/Timer.xml
+#: doc/classes/InputEventAction.xml doc/classes/Label.xml doc/classes/Timer.xml
#: doc/classes/VisibilityNotifier2D.xml
msgid "2D Dodge The Creeps Demo"
msgstr ""
@@ -7111,7 +7139,10 @@ msgid ""
"var array = []\n"
"array.resize(10)\n"
"array.fill(0) # Initialize the 10 elements to 0.\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] If [code]value[/code] is of a reference type ([Object]-derived, "
+"[Array], [Dictionary], etc.) then the array is filled with the references to "
+"the same object, i.e. no duplicates are created."
msgstr ""
#: doc/classes/Array.xml doc/classes/PoolByteArray.xml
@@ -7296,6 +7327,9 @@ msgstr ""
#: doc/classes/Array.xml
msgid ""
"Sorts the array.\n"
+"[b]Note:[/b] The sorting algorithm used is not [url=https://en.wikipedia.org/"
+"wiki/Sorting_algorithm#Stability]stable[/url]. This means that values "
+"considered equal may have their order changed when using [method sort].\n"
"[b]Note:[/b] Strings are sorted in alphabetical order (as opposed to natural "
"order). This may lead to unexpected behavior when sorting an array of "
"strings ending with a sequence of numbers. Consider the following example:\n"
@@ -7315,9 +7349,13 @@ msgid ""
"For two elements [code]a[/code] and [code]b[/code], if the given method "
"returns [code]true[/code], element [code]b[/code] will be after element "
"[code]a[/code] in the array.\n"
+"[b]Note:[/b] The sorting algorithm used is not [url=https://en.wikipedia.org/"
+"wiki/Sorting_algorithm#Stability]stable[/url]. This means that values "
+"considered equal may have their order changed when using [method "
+"sort_custom].\n"
"[b]Note:[/b] You cannot randomize the return value as the heapsort algorithm "
-"expects a deterministic result. Doing so will result in unexpected "
-"behavior.\n"
+"expects a deterministic result. Randomizing the return value will result in "
+"unexpected behavior.\n"
"[codeblock]\n"
"class MyCustomSorter:\n"
" static func sort_ascending(a, b):\n"
@@ -9955,10 +9993,9 @@ msgstr ""
#: doc/classes/AudioStreamGeneratorPlayback.xml
msgid ""
-"Returns the number of audio data frames left to play. If this returned "
-"number reaches [code]0[/code], the audio will stop playing until frames are "
-"added again. Therefore, make sure your script can always generate and push "
-"new audio frames fast enough to avoid audio cracking."
+"Returns the number of frames that can be pushed to the audio sample data "
+"buffer without overflowing it. If the result is [code]0[/code], the buffer "
+"is full."
msgstr ""
#: doc/classes/AudioStreamGeneratorPlayback.xml
@@ -10490,14 +10527,14 @@ msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
"Node for back-buffering the currently-displayed screen. The region defined "
-"in the BackBufferCopy node is buffered with the content of the screen it "
+"in the [BackBufferCopy] node is buffered with the content of the screen it "
"covers, or the entire screen according to the copy mode set. Use the "
"[code]texture(SCREEN_TEXTURE, ...)[/code] function in your shader scripts to "
"access the buffer.\n"
"[b]Note:[/b] Since this node inherits from [Node2D] (and not [Control]), "
"anchors and margins won't apply to child [Control]-derived nodes. This can "
"be problematic when resizing the window. To avoid this, add [Control]-"
-"derived nodes as [i]siblings[/i] to the BackBufferCopy node instead of "
+"derived nodes as [i]siblings[/i] to the [BackBufferCopy] node instead of "
"adding them as children."
msgstr ""
@@ -10507,22 +10544,22 @@ msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
-"The area covered by the BackBufferCopy. Only used if [member copy_mode] is "
+"The area covered by the [BackBufferCopy]. Only used if [member copy_mode] is "
"[constant COPY_MODE_RECT]."
msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
-"Disables the buffering mode. This means the BackBufferCopy node will "
+"Disables the buffering mode. This means the [BackBufferCopy] node will "
"directly use the portion of screen it covers."
msgstr ""
#: doc/classes/BackBufferCopy.xml
-msgid "BackBufferCopy buffers a rectangular region."
+msgid "[BackBufferCopy] buffers a rectangular region."
msgstr ""
#: doc/classes/BackBufferCopy.xml
-msgid "BackBufferCopy buffers the entire screen."
+msgid "[BackBufferCopy] buffers the entire screen."
msgstr ""
#: doc/classes/BakedLightmap.xml
@@ -19302,6 +19339,14 @@ msgid "Cylinder shape for collisions."
msgstr ""
#: doc/classes/CylinderShape.xml
+msgid ""
+"Cylinder shape for collisions.\n"
+"[b]Note:[/b] When using GodotPhysics instead of the default Bullet physics "
+"engine, there are several known bugs with cylinder collision shapes. Using "
+"[CapsuleShape] or [BoxShape] instead is recommended."
+msgstr ""
+
+#: doc/classes/CylinderShape.xml
msgid "The cylinder's height."
msgstr ""
@@ -22134,7 +22179,10 @@ msgid ""
"[/codeblock]\n"
"[b]Note:[/b] The script is run in the Editor context, which means the output "
"is visible in the console window started with the Editor (stdout) instead of "
-"the usual Godot [b]Output[/b] dock."
+"the usual Godot [b]Output[/b] dock.\n"
+"[b]Note:[/b] EditorScript is reference counted, meaning it is destroyed when "
+"nothing references it. This can cause errors during asynchronous operations "
+"if there are no references to the script."
msgstr ""
#: doc/classes/EditorScript.xml
@@ -32849,7 +32897,9 @@ msgid ""
"The size of the light in Godot units. Only considered in baked lightmaps and "
"only if [member light_bake_mode] is set to [constant BAKE_ALL]. Increasing "
"this value will make the shadows appear blurrier. This can be used to "
-"simulate area lights to an extent."
+"simulate area lights to an extent.\n"
+"[b]Note:[/b] [member light_size] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/Light.xml
@@ -36147,7 +36197,10 @@ msgid ""
"use the [method get_next_location] function once every physics frame to "
"update the internal path logic of the NavigationAgent. The returned vector "
"position from this function should be used as the next movement position for "
-"the agent's parent Node."
+"the agent's parent Node.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues."
msgstr ""
#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
@@ -36395,7 +36448,10 @@ msgid ""
"use the [method get_next_location] function once every physics frame to "
"update the internal path logic of the NavigationAgent. The returned vector "
"position from this function should be used as the next movement position for "
-"the agent's parent Node."
+"the agent's parent Node.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues."
msgstr ""
#: doc/classes/NavigationAgent2D.xml
@@ -37106,6 +37162,9 @@ msgid ""
"modified velocity as-is might lead to pushing and agent outside of a "
"navigable area. This is a limitation of the collision avoidance system, any "
"more complex situation may require the use of the physics engine.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues.\n"
"This server keeps tracks of any call and executes them during the sync "
"phase. This means that you can request any change to the map, using any "
"thread, without worrying."
@@ -39912,7 +39971,9 @@ msgid ""
"The light's radius. Note that the effectively lit area may appear to be "
"smaller depending on the [member omni_attenuation] in use. No matter the "
"[member omni_attenuation] in use, the light will never reach anything "
-"outside this radius."
+"outside this radius.\n"
+"[b]Note:[/b] [member omni_range] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -40423,11 +40484,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] cache data directory according to the operating "
-"system's standards. On desktop platforms, this path can be overridden by "
-"setting the [code]XDG_CACHE_HOME[/code] environment variable before starting "
-"the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in "
-"Godot projects[/url] in the documentation for more information. See also "
-"[method get_config_dir] and [method get_data_dir].\n"
+"system's standards. On Linux, this path can be overridden by setting the "
+"[code]XDG_CACHE_HOME[/code] environment variable before starting the "
+"project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot "
+"projects[/url] in the documentation for more information. See also [method "
+"get_config_dir] and [method get_data_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -40461,11 +40522,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] user configuration directory according to the "
-"operating system's standards. On desktop platforms, this path can be "
-"overridden by setting the [code]XDG_CONFIG_HOME[/code] environment variable "
-"before starting the project. See [url=$DOCS_URL/tutorials/io/data_paths."
-"html]File paths in Godot projects[/url] in the documentation for more "
-"information. See also [method get_cache_dir] and [method get_data_dir].\n"
+"operating system's standards. On Linux, this path can be overridden by "
+"setting the [code]XDG_CONFIG_HOME[/code] environment variable before "
+"starting the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File "
+"paths in Godot projects[/url] in the documentation for more information. See "
+"also [method get_cache_dir] and [method get_data_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -40487,11 +40548,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] user data directory according to the operating "
-"system's standards. On desktop platforms, this path can be overridden by "
-"setting the [code]XDG_DATA_HOME[/code] environment variable before starting "
-"the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in "
-"Godot projects[/url] in the documentation for more information. See also "
-"[method get_cache_dir] and [method get_config_dir].\n"
+"system's standards. On Linux, this path can be overridden by setting the "
+"[code]XDG_DATA_HOME[/code] environment variable before starting the project. "
+"See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot "
+"projects[/url] in the documentation for more information. See also [method "
+"get_cache_dir] and [method get_config_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -42338,6 +42399,16 @@ msgid "Particle systems (2D)"
msgstr ""
#: doc/classes/Particles2D.xml
+msgid "2D Particles Demo"
+msgstr ""
+
+#: doc/classes/Particles2D.xml
+msgid ""
+"2D Dodge The Creeps Demo (uses GPUParticles2D for the trail behind the "
+"player)"
+msgstr ""
+
+#: doc/classes/Particles2D.xml
msgid "Returns a rectangle containing the positions of all existing particles."
msgstr ""
@@ -49930,15 +50001,22 @@ msgstr ""
#: doc/classes/ProjectSettings.xml
msgid ""
"If [code]true[/code], uses a fast post-processing filter to make banding "
-"significantly less visible. In some cases, debanding may introduce a "
-"slightly noticeable dithering pattern. It's recommended to enable debanding "
-"only when actually needed since the dithering pattern will make lossless-"
-"compressed screenshots larger.\n"
+"significantly less visible in 3D. 2D rendering is [i]not[/i] affected by "
+"debanding unless the [member Environment.background_mode] is [constant "
+"Environment.BG_CANVAS]. In this case, [member rendering/quality/"
+"intended_usage/framebuffer_allocation] must also be set to [b]3D[/b].\n"
+"In some cases, debanding may introduce a slightly noticeable dithering "
+"pattern. It's recommended to enable debanding only when actually needed "
+"since the dithering pattern will make lossless-compressed screenshots "
+"larger.\n"
"[b]Note:[/b] Only available on the GLES3 backend. [member rendering/quality/"
"depth/hdr] must also be [code]true[/code] for debanding to be effective.\n"
"[b]Note:[/b] There are known issues with debanding breaking rendering on "
"mobile platforms. Due to this, it is recommended to leave this option "
-"disabled when targeting mobile platforms."
+"disabled when targeting mobile platforms.\n"
+"[b]Note:[/b] This property is only read when the project starts. To set "
+"debanding at run-time, set [member Viewport.debanding] on the root "
+"[Viewport] instead."
msgstr ""
#: doc/classes/ProjectSettings.xml
@@ -51534,17 +51612,28 @@ msgstr ""
#: modules/regex/doc_classes/RegEx.xml
msgid ""
"Searches the text for the compiled pattern. Returns a [RegExMatch] container "
-"of the first matching result if found, otherwise [code]null[/code]. The "
-"region to search within can be specified without modifying where the start "
-"and end anchor would be."
+"of the first matching result if found, otherwise [code]null[/code].\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegEx.xml
msgid ""
"Searches the text for the compiled pattern. Returns an array of [RegExMatch] "
"containers for each non-overlapping result. If no results were found, an "
-"empty array is returned instead. The region to search within can be "
-"specified without modifying where the start and end anchor would be."
+"empty array is returned instead.\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegEx.xml
@@ -51553,8 +51642,14 @@ msgid ""
"specified string. Escapes and backreferences such as [code]$1[/code] and "
"[code]$name[/code] are expanded and resolved. By default, only the first "
"instance is replaced, but it can be changed for all instances (global "
-"replacement). The region to search within can be specified without modifying "
-"where the start and end anchor would be."
+"replacement).\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegExMatch.xml
@@ -54269,7 +54364,11 @@ msgid "Call a group immediately (calls are normally made on idle)."
msgstr ""
#: doc/classes/SceneTree.xml
-msgid "Call a group only once even if the call is executed many times."
+msgid ""
+"Call a group only once even if the call is executed many times.\n"
+"[b]Note:[/b] Arguments are not taken into account when deciding whether the "
+"call is unique or not. Therefore when the same method is called with "
+"different arguments, only the first call will be performed."
msgstr ""
#: doc/classes/SceneTree.xml
@@ -56106,7 +56205,9 @@ msgid ""
"[b]Note:[/b] Mixed negative scales in 3D are not decomposable from the "
"transformation matrix. Due to the way scale is represented with "
"transformation matrices in Godot, the scale values will either be all "
-"positive or all negative."
+"positive or all negative.\n"
+"[b]Note:[/b] Not all nodes are visually scaled by the [member scale] "
+"property. For example, [Light]s are not visually affected by [member scale]."
msgstr ""
#: doc/classes/Spatial.xml
@@ -57484,7 +57585,10 @@ msgid ""
msgstr ""
#: doc/classes/SpotLight.xml
-msgid "The spotlight's angle in degrees."
+msgid ""
+"The spotlight's angle in degrees.\n"
+"[b]Note:[/b] [member spot_angle] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/SpotLight.xml
@@ -57500,7 +57604,9 @@ msgid ""
"The maximal range that can be reached by the spotlight. Note that the "
"effectively lit area may appear to be smaller depending on the [member "
"spot_attenuation] in use. No matter the [member spot_attenuation] in use, "
-"the light will never reach anything outside this range."
+"the light will never reach anything outside this range.\n"
+"[b]Note:[/b] [member spot_range] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/SpringArm.xml
@@ -66737,10 +66843,15 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
"If [code]true[/code], uses a fast post-processing filter to make banding "
-"significantly less visible. In some cases, debanding may introduce a "
-"slightly noticeable dithering pattern. It's recommended to enable debanding "
-"only when actually needed since the dithering pattern will make lossless-"
-"compressed screenshots larger.\n"
+"significantly less visible in 3D. 2D rendering is [i]not[/i] affected by "
+"debanding unless the [member Environment.background_mode] is [constant "
+"Environment.BG_CANVAS]. In this case, [member usage] must also be set to "
+"[constant USAGE_3D]. See also [member ProjectSettings.rendering/quality/"
+"filters/use_debanding].\n"
+"In some cases, debanding may introduce a slightly noticeable dithering "
+"pattern. It's recommended to enable debanding only when actually needed "
+"since the dithering pattern will make lossless-compressed screenshots "
+"larger.\n"
"[b]Note:[/b] Only available on the GLES3 backend. [member hdr] must also be "
"[code]true[/code] for debanding to be effective."
msgstr ""
@@ -66751,8 +66862,8 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
-"If [code]true[/code], the viewport will disable 3D rendering. For actual "
-"disabling use [code]usage[/code]."
+"If [code]true[/code], the viewport will disable 3D rendering. To actually "
+"disable allocation of 3D buffers, set [member usage] instead."
msgstr ""
#: doc/classes/Viewport.xml
@@ -66904,7 +67015,9 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
-"The rendering mode of viewport.\n"
+"The viewport's rendering mode. This controls which buffers are allocated for "
+"the viewport (2D only, or 2D + 3D). 2D-only options can reduce memory usage "
+"and improve performance slightly, especially on low-end devices.\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."
@@ -67436,6 +67549,22 @@ msgid ""
"render object this [VisualInstance] is set to."
msgstr ""
+#: doc/classes/VisualInstance.xml
+msgid ""
+"The sorting offset used by this [VisualInstance]. Adjusting it to a higher "
+"value will make the [VisualInstance] reliably draw on top of other "
+"[VisualInstance]s that are otherwise positioned at the same spot."
+msgstr ""
+
+#: doc/classes/VisualInstance.xml
+msgid ""
+"If [code]true[/code], the object is sorted based on the [AABB] center. "
+"Sorted based on the global position otherwise.\n"
+"The [AABB] center based sorting is generally more accurate for 3D models. "
+"The position based sorting instead allows to better control the drawing "
+"order when working with [Particles] and [CPUParticles]."
+msgstr ""
+
#: modules/visual_script/doc_classes/VisualScript.xml
msgid "A script implemented in the Visual Script programming environment."
msgstr ""
diff --git a/doc/translations/ru.po b/doc/translations/ru.po
index b590ff4014..9d569d7760 100644
--- a/doc/translations/ru.po
+++ b/doc/translations/ru.po
@@ -24,7 +24,7 @@
# Ð§Ñ‚Ð°Ð±Ñ <chtabs2k19@gmail.com>, 2021.
# Nikita Blizniuk <BliznyukNM@gmail.com>, 2021.
# Сергей Волков <zerosar4@gmail.com>, 2021.
-# Alexander Sinitsyn <almoig747@gmail.com>, 2021.
+# Alexander Sinitsyn <almoig747@gmail.com>, 2021, 2022.
# Ð¢Ð¾Ð»Ñ Ð‘Ð¾Ð³Ð¾Ð¼Ð¾Ð»Ð¾Ð² <tolya.bogomolov2004@gmail.com>, 2021.
# Rustam Alieskerov <rustam.aleskerov7@gmail.com>, 2021, 2022.
# Vladimir Svity <development.openworld@gmail.com>, 2021.
@@ -54,12 +54,15 @@
# Lost Net <pc.mirkn@gmail.com>, 2022.
# Vladimir Kirillovskiy <vladimir.kirillovskiy@gmail.com>, 2022.
# motismob <evt.mixail@ya.ru>, 2022.
+# Handsless coder <yfintktajy1@gmail.com>, 2022.
+# Evgeniy Khramov <thejenjagamertjg@gmail.com>, 2022.
+# Григорий <bolon667@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-09-16 07:12+0000\n"
-"Last-Translator: Rish Alternative <ii4526668@gmail.com>\n"
+"PO-Revision-Date: 2022-12-06 11:48+0000\n"
+"Last-Translator: Григорий <bolon667@gmail.com>\n"
"Language-Team: Russian <https://hosted.weblate.org/projects/godot-engine/"
"godot-class-reference/ru/>\n"
"Language: ru\n"
@@ -68,7 +71,7 @@ msgstr ""
"Content-Transfer-Encoding: 8-bit\n"
"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
-"X-Generator: Weblate 4.14.1-dev\n"
+"X-Generator: Weblate 4.15-dev\n"
#: doc/tools/make_rst.py
msgid "Description"
@@ -598,7 +601,6 @@ msgstr ""
"ÑкземплÑÑ€ объекта. Полезно Ð´Ð»Ñ Ð´ÐµÑериализации."
#: 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 "
@@ -632,7 +634,7 @@ msgstr ""
"- Больше 1,0 (не включаÑ): Облегчение вхождениÑ(только вход)\n"
"[/codeblock]\n"
"[url=https://raw.githubusercontent.com/godotengine/godot-docs/3.4/img/"
-"ease_cheatsheet.png]ease() Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ ÐºÑ€Ð¸Ð²Ð¾Ð¹ шпаргалка[/url]\n"
+"ease_cheatsheet.png]ease() шпаргалка значений кривой[/url]\n"
"См. также [метод smoothstep]. ЕÑли вам нужно выполнить более Ñложные "
"переходы, иÑпользуйте [Tween] или [AnimationPlayer]."
@@ -764,8 +766,10 @@ msgstr ""
"[/codeblock]"
#: modules/gdscript/doc_classes/@GDScript.xml
+#, fuzzy
msgid ""
-"Returns an array of dictionaries representing the current call stack.\n"
+"Returns an array of dictionaries representing the current call stack. See "
+"also [method print_stack].\n"
"[codeblock]\n"
"func _ready():\n"
" foo()\n"
@@ -780,7 +784,11 @@ msgid ""
"[codeblock]\n"
"[{function:bar, line:12, source:res://script.gd}, {function:foo, line:9, "
"source:res://script.gd}, {function:_ready, line:6, source:res://script.gd}]\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] [method get_stack] only works if the running instance is "
+"connected to a debugging server (i.e. an editor instance). [method "
+"get_stack] will not work in projects exported in release mode, or in "
+"projects exported in debug mode if not connected to a debugging server."
msgstr ""
"Возвращает маÑÑив Ñловарей, предÑтавлÑющий текущий Ñтек вызовов.\n"
"[codeblock]\n"
@@ -866,7 +874,6 @@ msgstr ""
"[/codeblock]"
#: modules/gdscript/doc_classes/@GDScript.xml
-#, fuzzy
msgid ""
"Returns an interpolation or extrapolation factor considering the range "
"specified in [code]from[/code] and [code]to[/code], and the interpolated "
@@ -890,13 +897,13 @@ msgid ""
"[method range_lerp] to map a continuous series of values to another."
msgstr ""
"Возвращает коÑффициент интерполÑции или ÑкÑтраполÑции Ñ ÑƒÑ‡ÐµÑ‚Ð¾Ð¼ диапазона, "
-"указанного в [code]от[/code] и [code]до[/code], и интерполированное "
-"значение, указанное в [code]веÑе[/code]. Возвращаемое значение будет "
-"находитьÑÑ Ð² диапазоне [code]0.0[/code] and [code]1.0[/code] еÑли [code]веÑ[/"
-"code] находитÑÑ Ð¼ÐµÐ¶Ð´Ñƒ [code]от[/code] и [code]до[/code] (включительно). ЕÑли "
-"[code]веÑ[/code] находитÑÑ Ð·Ð° пределами Ñтого диапазона, то будет возвращён "
-"коÑффициент ÑкÑтраполÑции (возвращаемое значение меньше [code]0.0[/code] или "
-"больше [code]1.0[/code]).\n"
+"указанного в [code]from[/code] и [code]to[/code], и интерполированное "
+"значение, указанное в [code]weight[/code]. Возвращаемое значение будет "
+"находитьÑÑ Ð² диапазоне от [code]0.0[/code] до [code]1.0[/code], еÑли "
+"[code]weight[/code] находитÑÑ Ð¼ÐµÐ¶Ð´Ñƒ [code]from[/code] и [code]to[/code] "
+"(включительно). ЕÑли [code]weight[/code] находитÑÑ Ð·Ð° пределами Ñтого "
+"диапазона, то будет возвращён коÑффициент ÑкÑтраполÑции (возвращаемое "
+"значение меньше [code]0.0[/code] или больше [code]1.0[/code]).\n"
"[codeblock]\n"
"# КоÑффициент интерполÑции в приведённом ниже вызове `lerp()` ÑоÑтавлÑет "
"0,75.\n"
@@ -979,7 +986,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 "
@@ -1002,11 +1008,11 @@ msgid ""
"continuous series of values to another."
msgstr ""
"Линейно интерполирует между Ð´Ð²ÑƒÐ¼Ñ Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñми Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ коÑффициента, "
-"определенного в [code]weight[/code]. Ð”Ð»Ñ Ð²Ñ‹Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ð¸Ð½Ñ‚ÐµÑ€Ð¿Ð¾Ð»Ñции [code]веÑ[/"
-"code] должен ÑоÑтавлÑть от [code]0.0[/code] до [code]1.0[/code] "
+"определенного в [code]weight[/code]. Ð”Ð»Ñ Ð²Ñ‹Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ð¸Ð½Ñ‚ÐµÑ€Ð¿Ð¾Ð»Ñции "
+"[code]weight[/code] должен быть между [code]0.0[/code] и [code]1.0[/code] "
"(включительно). Однако Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð·Ð° пределами Ñтого диапазона разрешены и "
"могут быть иÑпользованы Ð´Ð»Ñ Ð²Ñ‹Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ [i]ÑкÑтраполÑции[/i].\n"
-"ЕÑли аргументы [code]от[/code] и [code]до[/code] имеют тип [int] или "
+"ЕÑли аргументы [code]from[/code] и [code]to[/code] имеют тип [int] или "
"[float], возвращаемое значение будет [float].\n"
"ЕÑли оба Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð¸Ð¼ÐµÑŽÑ‚ одинаковый векторный тип ([Vector2], [Vector3] или "
"[Color]), возвращаемое значение будет одного типа ([code]lerp[/code], затем "
@@ -1432,18 +1438,17 @@ msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
-"Prints a stack track at code location, only works when running with debugger "
-"turned on.\n"
+"Prints a stack trace at the current code location. See also [method "
+"get_stack].\n"
"Output in the console would look something like this:\n"
"[codeblock]\n"
"Frame 0 - res://test.gd:16 in function '_process'\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] [method print_stack] only works if the running instance is "
+"connected to a debugging server (i.e. an editor instance). [method "
+"print_stack] will not work in projects exported in release mode, or in "
+"projects exported in debug mode if not connected to a debugging server."
msgstr ""
-"Печатает трек Ñтека вызовов, работает только еÑли включён отладчик.\n"
-"Вывод в конÑоли будет выглÑдеть примерно так:\n"
-"[codeblock]\n"
-"Frame 0 - res://test.gd:16 in function '_process'\n"
-"[/codeblock]"
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
@@ -1814,7 +1819,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] "
@@ -1842,33 +1846,28 @@ 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"
+"smoothstep(0, 2, -5.0) # Возвращает 0.0\n"
+"smoothstep(0, 2, 0.5) # Возвращает 0.15625\n"
+"smoothstep(0, 2, 1.0) # Возвращает 0.5\n"
+"smoothstep(0, 2, 2.0) # Возвращает 1.0\n"
"[/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"
+"Ð’ Ñравнении Ñ [method ease] Ñо значение кривой [code]-1.6521[/code], [метод "
+"smoothstep] возвращает наиболее плавную кривую без внезапных изменений "
+"производной. ЕÑли вам нужно выполнить более продвинутые перемещениÑ, "
+"иÑпользуйте [Tween] или [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]"
+"smoothstep_ease_comparison.png]Сравнение возвращаемых значений smoothstep() "
+"и ease(x, -1.6521)[/url]"
#: modules/gdscript/doc_classes/@GDScript.xml
-#, fuzzy
msgid ""
"Returns the square root of [code]s[/code], where [code]s[/code] is a non-"
"negative number.\n"
@@ -1888,7 +1887,6 @@ msgstr ""
"Numerics.Complex[/code] в C#."
#: modules/gdscript/doc_classes/@GDScript.xml
-#, fuzzy
msgid ""
"Returns the position of the first non-zero digit, after the decimal point. "
"Note that the maximum return value is 10, which is a design decision in the "
@@ -1903,12 +1901,9 @@ msgstr ""
"внимание, что макÑимальное возвращаемое значение – Ñто 10, что ÑвлÑетÑÑ "
"проектным решением при реализации.\n"
"[codeblock]\n"
-"# n равно 0\n"
-"n = step_decimals(5)\n"
-"# n равно 4\n"
-"n = step_decimals(1.0005)\n"
-"# n равно 9\n"
-"n = step_decimals(0.000000005)\n"
+"n = step_decimals(5) # n равно 0\n"
+"n = step_decimals(1.0005) # n равно 4\n"
+"n = step_decimals(0.000000005) # n равно 9\n"
"[/codeblock]"
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -1952,7 +1947,6 @@ msgstr ""
"[/codeblock]"
#: modules/gdscript/doc_classes/@GDScript.xml
-#, fuzzy
msgid ""
"Converts a formatted string that was returned by [method var2str] to the "
"original value.\n"
@@ -1962,8 +1956,8 @@ msgid ""
"print(b[\"a\"]) # Prints 1\n"
"[/codeblock]"
msgstr ""
-"Преобразует форматированную Ñтроку, ÐºÐ¾Ñ‚Ð¾Ñ€Ð°Ñ Ð±Ñ‹Ð»Ð° возвращена [method var2str] "
-"в иÑходное значение.\n"
+"Преобразует форматированную Ñтроку, ÐºÐ¾Ñ‚Ð¾Ñ€Ð°Ñ Ð±Ñ‹Ð»Ð° возвращена [методом "
+"var2str] в иÑходное значение.\n"
"[codeblock]\n"
"a = '{ \"a\": 1, \"b\": 2 }'\n"
"b = str2var(a)\n"
@@ -1983,7 +1977,6 @@ msgstr ""
"[/codeblock]"
#: modules/gdscript/doc_classes/@GDScript.xml
-#, fuzzy
msgid ""
"Returns the hyperbolic tangent of [code]s[/code].\n"
"[codeblock]\n"
@@ -1994,7 +1987,7 @@ msgstr ""
"Возвращает гиперболичеÑкий Ñ‚Ð°Ð½Ð³ÐµÐ½Ñ [code]s[/code].\n"
"[codeblock]\n"
"a = log(2.0) # Возвращает 0.693147\n"
-"tanh(a) # Возвращает 0.6\n"
+"b = tanh(a) # Возвращает 0.6\n"
"[/codeblock]"
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -2031,7 +2024,6 @@ msgstr ""
"См. также [JSON] Ð´Ð»Ñ Ð°Ð»ÑŒÑ‚ÐµÑ€Ð½Ð°Ñ‚Ð¸Ð²Ð½Ð¾Ð³Ð¾ Ð¿Ñ€ÐµÐ¾Ð±Ñ€Ð°Ð·Ð¾Ð²Ð°Ð½Ð¸Ñ [Variant] в JSON Ñтроку."
#: modules/gdscript/doc_classes/@GDScript.xml
-#, fuzzy
msgid ""
"Returns whether the given class exists in [ClassDB].\n"
"[codeblock]\n"
@@ -2041,7 +2033,7 @@ msgid ""
msgstr ""
"Возвращает, ÑущеÑтвует ли данный клаÑÑ Ð² [ClassDB].\n"
"[codeblock]\n"
-"type_exists(\"Sprite2D\") # Возвращает true\n"
+"type_exists(\"Sprite\") # Возвращает true\n"
"type_exists(\"Variant\") # Возвращает false\n"
"[/codeblock]"
@@ -2092,13 +2084,12 @@ msgstr ""
"[/codeblock]"
#: modules/gdscript/doc_classes/@GDScript.xml
-#, fuzzy
msgid ""
"Encodes a variable value to a byte array. When [code]full_objects[/code] is "
"[code]true[/code] encoding objects is allowed (and can potentially include "
"code)."
msgstr ""
-"Кодирует значение переменной в маÑÑив байт. ЕÑли [code]full_objects[/code] "
+"Кодирует значение переменной в маÑÑив байтов. ЕÑли [code]full_objects[/code] "
"равен [code]true[/code], кодирование объектов разрешено (и потенциально "
"может включать код)."
@@ -2859,12 +2850,10 @@ msgid "Help key."
msgstr "Клавиша помощи."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "Left Direction key."
msgstr "Клавиша Ð½Ð°Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð²Ð»ÐµÐ²Ð¾."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "Right Direction key."
msgstr "Клавиша Ð½Ð°Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð²Ð¿Ñ€Ð°Ð²Ð¾."
@@ -2876,19 +2865,16 @@ msgstr ""
"уÑтройÑтвах Android."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "Media forward key."
msgstr "Клавиша запиÑи мультимедиа."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "Media stop key."
msgstr "Клавиша оÑтановки мультимедиа."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "Media refresh key."
-msgstr "Клавиша запиÑи мультимедиа."
+msgstr "Клавиша Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ð¼ÑƒÐ»ÑŒÑ‚Ð¸Ð¼ÐµÐ´Ð¸Ð°."
#: doc/classes/@GlobalScope.xml
msgid "Volume down key."
@@ -2907,22 +2893,18 @@ msgid "Bass Boost key."
msgstr "Клавиша уÑÐ¸Ð»ÐµÐ½Ð¸Ñ Ð½Ð¸Ð·ÐºÐ¸Ñ… чаÑтот."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "Bass up key."
msgstr "Клавиша ÑƒÐ²ÐµÐ»Ð¸Ñ‡ÐµÐ½Ð¸Ñ Ð±Ð°Ñов."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "Bass down key."
msgstr "Клавиша ÑƒÐ¼ÐµÐ½ÑŒÑˆÐµÐ½Ð¸Ñ Ð½Ð¸Ð·ÐºÐ¸Ñ… чаÑтот."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "Treble up key."
msgstr "Клавиша ÑƒÐ²ÐµÐ»Ð¸Ñ‡ÐµÐ½Ð¸Ñ Ð²Ñ‹Ñоких чаÑтот."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "Treble down key."
msgstr "Клавиша ÑƒÐ¼ÐµÐ½ÑŒÑˆÐµÐ½Ð¸Ñ Ð²Ñ‹Ñоких чаÑтот."
@@ -2952,12 +2934,10 @@ msgid "Home page key."
msgstr "Клавиша домашней Ñтраницы."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "Favorites key."
-msgstr "Клавиша избранного."
+msgstr "Клавиша \"Избранное\"."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "Search key."
msgstr "Клавиша поиÑка."
@@ -4424,7 +4404,6 @@ msgid "Skip error."
msgstr "Ошибка \"Пропущено\"."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "Help error."
msgstr "Ошибка Ñправки."
@@ -4661,6 +4640,26 @@ msgid "Hints that an image is compressed using lossless compression."
msgstr "Указывает, что изображение иÑпользует Ñжатие без потерь."
#: doc/classes/@GlobalScope.xml
+msgid ""
+"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:\n"
+"[codeblock]\n"
+"hint_string = \"%s:\" % [TYPE_INT] # Array of inteters.\n"
+"hint_string = \"%s:%s:\" % [TYPE_ARRAY, TYPE_REAL] # Two-dimensional array "
+"of floats.\n"
+"hint_string = \"%s/%s:Resource\" % [TYPE_OBJECT, TYPE_OBJECT] # Array of "
+"resources.\n"
+"hint_string = \"%s:%s/%s:Resource\" % [TYPE_ARRAY, TYPE_OBJECT, TYPE_OBJECT] "
+"# Two-dimensional array of resources.\n"
+"[/codeblock]\n"
+"[b]Note:[/b] The final colon is required to specify for properly detecting "
+"built-in types."
+msgstr ""
+
+#: doc/classes/@GlobalScope.xml
msgid "The property is serialized and saved in the scene file (default)."
msgstr "СвойÑтво ÑериализируетÑÑ Ð¸ ÑохранÑетÑÑ Ð² файле Ñцены (по умолчанию)."
@@ -5007,10 +5006,8 @@ msgstr ""
#: doc/classes/AABB.xml doc/classes/Rect2.xml doc/classes/Vector2.xml
#: doc/classes/Vector3.xml
-#, fuzzy
msgid "Vector math"
-msgstr ""
-"Вектор иÑпользуемый Ð´Ð»Ñ 2D математики иÑÐ¿Ð¾Ð»ÑŒÐ·ÑƒÑ Ñ†ÐµÐ»Ð¾Ñ‡Ð¸Ñленные координаты."
+msgstr "Ð’ÐµÐºÑ‚Ð¾Ñ€Ð½Ð°Ñ Ð¼Ð°Ñ‚ÐµÐ¼Ð°Ñ‚Ð¸ÐºÐ°"
#: doc/classes/AABB.xml doc/classes/Rect2.xml doc/classes/Vector2.xml
#: doc/classes/Vector3.xml
@@ -5516,8 +5513,7 @@ msgstr ""
#: doc/classes/AudioStreamPlayer.xml doc/classes/Button.xml
#: doc/classes/CanvasLayer.xml doc/classes/CollisionShape2D.xml
#: doc/classes/ColorRect.xml doc/classes/Input.xml doc/classes/InputEvent.xml
-#: doc/classes/InputEventAction.xml doc/classes/Label.xml
-#: doc/classes/Particles2D.xml doc/classes/Timer.xml
+#: doc/classes/InputEventAction.xml doc/classes/Label.xml doc/classes/Timer.xml
#: doc/classes/VisibilityNotifier2D.xml
msgid "2D Dodge The Creeps Demo"
msgstr ""
@@ -6280,11 +6276,11 @@ msgstr ""
#: doc/classes/Animation.xml doc/classes/Gradient.xml
msgid "Linear interpolation."
-msgstr ""
+msgstr "Ð›Ð¸Ð½ÐµÐ¹Ð½Ð°Ñ Ð¸Ð½Ñ‚ÐµÑ€Ð¿Ð¾Ð»ÑциÑ."
#: doc/classes/Animation.xml doc/classes/Gradient.xml
msgid "Cubic interpolation."
-msgstr ""
+msgstr "КубичеÑÐºÐ°Ñ Ð¸Ð½Ñ‚ÐµÑ€Ð¿Ð¾Ð»ÑциÑ."
#: doc/classes/Animation.xml
msgid "Update between keyframes."
@@ -6510,7 +6506,7 @@ msgstr ""
#: doc/classes/AnimationNodeTimeScale.xml
#: doc/classes/AnimationNodeTransition.xml
msgid "AnimationTree"
-msgstr ""
+msgstr "Дерево анимации"
#: doc/classes/AnimationNodeAdd3.xml doc/classes/AnimationNodeAnimation.xml
#: doc/classes/AnimationNodeBlend2.xml
@@ -7546,7 +7542,7 @@ msgstr ""
#: doc/classes/AnimationTree.xml
msgid "Using AnimationTree"
-msgstr ""
+msgstr "ИÑпользование дерева анимации"
#: doc/classes/AnimationTree.xml
msgid "Manually advance the animations by the specified time (in seconds)."
@@ -7976,43 +7972,43 @@ msgstr ""
#: doc/classes/AnimationTreePlayer.xml
msgid "Output node."
-msgstr ""
+msgstr "Выходной узел."
#: doc/classes/AnimationTreePlayer.xml
msgid "Animation node."
-msgstr ""
+msgstr "Ðнимационный узел."
#: doc/classes/AnimationTreePlayer.xml
msgid "OneShot node."
-msgstr ""
+msgstr "Узел OneShot."
#: doc/classes/AnimationTreePlayer.xml
msgid "Mix node."
-msgstr ""
+msgstr "МикÑ-узел."
#: doc/classes/AnimationTreePlayer.xml
msgid "Blend2 node."
-msgstr ""
+msgstr "Узел Blend2."
#: doc/classes/AnimationTreePlayer.xml
msgid "Blend3 node."
-msgstr ""
+msgstr "Узел Blend3."
#: doc/classes/AnimationTreePlayer.xml
msgid "Blend4 node."
-msgstr ""
+msgstr "Узел Blend4."
#: doc/classes/AnimationTreePlayer.xml
msgid "TimeScale node."
-msgstr ""
+msgstr "Узел TimeScale."
#: doc/classes/AnimationTreePlayer.xml
msgid "TimeSeek node."
-msgstr ""
+msgstr "Узел TimeSeek."
#: doc/classes/AnimationTreePlayer.xml
msgid "Transition node."
-msgstr ""
+msgstr "Переходный узел."
#: doc/classes/Area.xml
msgid "3D area for detection and physics and audio influence."
@@ -8702,7 +8698,10 @@ msgid ""
"var array = []\n"
"array.resize(10)\n"
"array.fill(0) # Initialize the 10 elements to 0.\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] If [code]value[/code] is of a reference type ([Object]-derived, "
+"[Array], [Dictionary], etc.) then the array is filled with the references to "
+"the same object, i.e. no duplicates are created."
msgstr ""
#: doc/classes/Array.xml doc/classes/PoolByteArray.xml
@@ -8931,8 +8930,12 @@ msgstr ""
"опиÑывает шаг между индекÑами Ñреза."
#: doc/classes/Array.xml
+#, fuzzy
msgid ""
"Sorts the array.\n"
+"[b]Note:[/b] The sorting algorithm used is not [url=https://en.wikipedia.org/"
+"wiki/Sorting_algorithm#Stability]stable[/url]. This means that values "
+"considered equal may have their order changed when using [method sort].\n"
"[b]Note:[/b] Strings are sorted in alphabetical order (as opposed to natural "
"order). This may lead to unexpected behavior when sorting an array of "
"strings ending with a sequence of numbers. Consider the following example:\n"
@@ -8963,9 +8966,13 @@ msgid ""
"For two elements [code]a[/code] and [code]b[/code], if the given method "
"returns [code]true[/code], element [code]b[/code] will be after element "
"[code]a[/code] in the array.\n"
+"[b]Note:[/b] The sorting algorithm used is not [url=https://en.wikipedia.org/"
+"wiki/Sorting_algorithm#Stability]stable[/url]. This means that values "
+"considered equal may have their order changed when using [method "
+"sort_custom].\n"
"[b]Note:[/b] You cannot randomize the return value as the heapsort algorithm "
-"expects a deterministic result. Doing so will result in unexpected "
-"behavior.\n"
+"expects a deterministic result. Randomizing the return value will result in "
+"unexpected behavior.\n"
"[codeblock]\n"
"class MyCustomSorter:\n"
" static func sort_ascending(a, b):\n"
@@ -9357,6 +9364,19 @@ msgid ""
"[ARVRServer]. This makes this node ideal to add child nodes to visualize the "
"controller."
msgstr ""
+"Это вÑпомогательный проÑтранÑтвенный узел, ÑвÑзанный Ñ Ð¾Ñ‚Ñлеживанием "
+"контроллеров. Он также предлагает неÑколько удобных переходов к ÑоÑтоÑнию "
+"кнопок и т.п. на контроллерах.\n"
+"Контроллеры ÑвÑзаны по их ID. Ð’Ñ‹ можете Ñоздавать узлы контроллеров до того, "
+"как контроллеры Ñтанут доÑтупны. ЕÑли в вашей игре вÑегда иÑпользуютÑÑ Ð´Ð²Ð° "
+"контроллера (по одному Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð¹ руки), вы можете заранее определить "
+"контроллеры Ñ ID 1 и 2; они Ñтанут активными, как только контроллеры будут "
+"определены. ЕÑли вы ожидаете, что будут иÑпользоватьÑÑ Ð´Ð¾Ð¿Ð¾Ð»Ð½Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ñ‹Ðµ "
+"контроллеры, вы должны реагировать на Ñигналы и добавить узлы ARVRController "
+"в вашу Ñцену.\n"
+"Положение узла контроллера автоматичеÑки обновлÑетÑÑ Ñервером [ARVRServer]. "
+"Это делает данный узел идеальным Ð´Ð»Ñ Ð´Ð¾Ð±Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð´Ð¾Ñ‡ÐµÑ€Ð½Ð¸Ñ… узлов Ð´Ð»Ñ "
+"визуализации контроллера."
#: doc/classes/ARVRController.xml
msgid ""
@@ -9634,6 +9654,21 @@ msgid ""
"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."
msgstr ""
+"Это Ñпециальный узел в ÑиÑтеме AR/VR, который отображает физичеÑкое "
+"меÑтоположение центра нашего проÑтранÑтва отÑÐ»ÐµÐ¶Ð¸Ð²Ð°Ð½Ð¸Ñ Ð½Ð° виртуальное "
+"меÑтоположение в нашем игровом мире.\n"
+"Ð’ вашей Ñцене должен быть только один такой узел, и он обÑзательно должен "
+"быть у ваÑ. Ð’Ñе узлы ARVRCamera, ARVRController и ARVRAnchor должны быть "
+"прÑмыми дочерними узлами Ñтого узла, чтобы проÑтранÑтвенное отÑлеживание "
+"работало правильно.\n"
+"Именно положение Ñтого узла вы обновлÑете, когда перÑонажу нужно "
+"перемещатьÑÑ Ð¿Ð¾ игровому миру, в то Ð²Ñ€ÐµÐ¼Ñ ÐºÐ°Ðº в реальном мире мы не "
+"движемÑÑ. Движение в реальном мире вÑегда проиÑходит отноÑительно Ñтой "
+"иÑходной точки.\n"
+"Ðапример, еÑли ваш перÑонаж управлÑет автомобилем, узел ARVROrigin должен "
+"быть дочерним узлом Ñтого автомобилÑ. Или, еÑли вы реализуете ÑиÑтему "
+"телепортации Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ¼ÐµÑ‰ÐµÐ½Ð¸Ñ Ð¿ÐµÑ€Ñонажа, вы должны изменить положение Ñтого "
+"узла."
#: doc/classes/ARVROrigin.xml
msgid ""
@@ -10176,6 +10211,26 @@ msgid ""
"4, 3][/code] instead, because now even though the distance is longer, it's "
"\"easier\" to get through point 4 than through point 2."
msgstr ""
+"Возвращает маÑÑив Ñ Ð¸Ð´ÐµÐ½Ñ‚Ð¸Ñ„Ð¸ÐºÐ°Ñ‚Ð¾Ñ€Ð°Ð¼Ð¸ точек, которые образуют путь, найденный "
+"AStar между заданными точками. МаÑÑив упорÑдочен от начальной точки до "
+"конечной точки пути.\n"
+"[codeblock].\n"
+"var astar = AStar.new()\n"
+"astar.add_point(1, Vector3(0, 0, 0, 0))\n"
+"astar.add_point(2, Vector3(0, 1, 0), 1) # Ð’ÐµÑ Ð¿Ð¾ умолчанию равен 1\n"
+"astar.add_point(3, Vector3(1, 1, 0))\n"
+"astar.add_point(4, Vector3(2, 0, 0))\n"
+"\n"
+"astar.connect_points(1, 2, false)\n"
+"astar.connect_points(2, 3, false)\n"
+"astar.connect_points(4, 3, false)\n"
+"astar.connect_points(1, 4, false)\n"
+"\n"
+"var res = astar.get_id_path(1, 3) # Возвращает [1, 2, 3]\n"
+"[/codeblock].\n"
+"ЕÑли изменить Ð²ÐµÑ Ð²Ñ‚Ð¾Ñ€Ð¾Ð¹ точки на 3, то результатом будет [code][1, 4, 3][/"
+"code], потому что теперь, неÑÐ¼Ð¾Ñ‚Ñ€Ñ Ð½Ð° то, что раÑÑтоÑние больше, \"легче\" "
+"пройти через точку 4, чем через точку 2."
#: doc/classes/AStar.xml doc/classes/AStar2D.xml
msgid ""
@@ -10424,6 +10479,22 @@ msgid ""
"FLAG_REPEAT] and [constant Texture.FLAG_MIRRORED_REPEAT] flags are ignored "
"when using an AtlasTexture."
msgstr ""
+"РеÑÑƒÑ€Ñ [Texture], который обрезает одну чаÑть текÑтуры [member atlas], "
+"определенной [member region]. ОÑновное применение - вырезание текÑтур из "
+"атлаÑа текÑтур, который предÑтавлÑет Ñобой большой файл текÑтуры, Ñодержащий "
+"неÑколько текÑтур меньшего размера. СоÑтоит из [Texture] Ð´Ð»Ñ [member atlas], "
+"[member region], который определÑет облаÑть [member atlas] Ð´Ð»Ñ "
+"иÑпользованиÑ, и [member margin], который определÑет ширину границы.\n"
+"[AtlasTexture] не может иÑпользоватьÑÑ Ð² [AnimatedTexture], не может быть "
+"плиточным в узлах, таких как [TextureRect], и не работает должным образом, "
+"еÑли иÑпользуетÑÑ Ð²Ð½ÑƒÑ‚Ñ€Ð¸ других реÑурÑов [AtlasTexture]. ÐеÑколько реÑурÑов "
+"[AtlasTexture] можно иÑпользовать Ð´Ð»Ñ Ð¾Ð±Ñ€ÐµÐ·ÐºÐ¸ неÑкольких текÑтур из атлаÑа. "
+"ИÑпользование атлаÑа текÑтур помогает оптимизировать затраты видеопамÑти и "
+"вызовы рендеринга по Ñравнению Ñ Ð¸Ñпользованием неÑкольких небольших "
+"файлов.\n"
+"[b]Примечание:[/b] AtlasTextures не поддерживают повторение. Флаги [constant "
+"Texture.FLAG_REPEAT] и [constant Texture.FLAG_MIRRORED_REPEAT] игнорируютÑÑ "
+"при иÑпользовании AtlasTexture."
#: doc/classes/AtlasTexture.xml
msgid "The texture that contains the atlas. Can be any [Texture] subtype."
@@ -10654,6 +10725,21 @@ msgid ""
"- Accentuates transients by using a wider attack, making effects sound more "
"punchy."
msgstr ""
+"КомпреÑÑор динамичеÑкого диапазона уменьшает уровень звука, когда амплитуда "
+"превышает определенный порог в децибелах. Одно из оÑновных назначений "
+"компреÑÑора - увеличение динамичеÑкого диапазона за Ñчет минимального "
+"ÐºÐ»Ð¸Ð¿Ð¿Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ (когда звук превышает 0 дБ).\n"
+"КомпреÑÑор имеет множеÑтво применений в микÑе:\n"
+"- Ð’ маÑтер-шине Ð´Ð»Ñ ÑÐ¶Ð°Ñ‚Ð¸Ñ Ð²Ñего выхода (Ñ…Ð¾Ñ‚Ñ [AudioEffectLimiter], "
+"вероÑтно, лучше).\n"
+"- Ð’ голоÑовых каналах Ð´Ð»Ñ Ð¾Ð±ÐµÑÐ¿ÐµÑ‡ÐµÐ½Ð¸Ñ Ð¸Ñ… макÑимально ÑбаланÑированного "
+"звучаниÑ.\n"
+"- Ð’ Ñайдчейне. Это позволÑет Ñнизить уровень звука при боковом подключении к "
+"другой аудиошине Ð´Ð»Ñ Ð¾Ð¿Ñ€ÐµÐ´ÐµÐ»ÐµÐ½Ð¸Ñ Ð¿Ð¾Ñ€Ð¾Ð³Ð°. Эта техника раÑпроÑтранена в "
+"микшировании видеоигр Ð´Ð»Ñ ÑÐ½Ð¸Ð¶ÐµÐ½Ð¸Ñ ÑƒÑ€Ð¾Ð²Ð½Ñ Ð¼ÑƒÐ·Ñ‹ÐºÐ¸ и SFX во Ð²Ñ€ÐµÐ¼Ñ Ð·Ð²ÑƒÑ‡Ð°Ð½Ð¸Ñ "
+"голоÑов.\n"
+"- Подчеркивает переходные процеÑÑÑ‹ за Ñчет более широкой атаки, заÑтавлÑÑ "
+"Ñффекты звучать более напориÑто."
#: doc/classes/AudioEffectCompressor.xml
msgid ""
@@ -11632,12 +11718,14 @@ msgid "Clears the audio sample data buffer."
msgstr ""
#: doc/classes/AudioStreamGeneratorPlayback.xml
+#, fuzzy
msgid ""
-"Returns the number of audio data frames left to play. If this returned "
-"number reaches [code]0[/code], the audio will stop playing until frames are "
-"added again. Therefore, make sure your script can always generate and push "
-"new audio frames fast enough to avoid audio cracking."
+"Returns the number of frames that can be pushed to the audio sample data "
+"buffer without overflowing it. If the result is [code]0[/code], the buffer "
+"is full."
msgstr ""
+"Возвращает [code]true[/code] еÑли [code]a[/code] и [code]b[/code] "
+"приблизительно равны друг другу."
#: doc/classes/AudioStreamGeneratorPlayback.xml
msgid ""
@@ -12168,14 +12256,14 @@ msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
"Node for back-buffering the currently-displayed screen. The region defined "
-"in the BackBufferCopy node is buffered with the content of the screen it "
+"in the [BackBufferCopy] node is buffered with the content of the screen it "
"covers, or the entire screen according to the copy mode set. Use the "
"[code]texture(SCREEN_TEXTURE, ...)[/code] function in your shader scripts to "
"access the buffer.\n"
"[b]Note:[/b] Since this node inherits from [Node2D] (and not [Control]), "
"anchors and margins won't apply to child [Control]-derived nodes. This can "
"be problematic when resizing the window. To avoid this, add [Control]-"
-"derived nodes as [i]siblings[/i] to the BackBufferCopy node instead of "
+"derived nodes as [i]siblings[/i] to the [BackBufferCopy] node instead of "
"adding them as children."
msgstr ""
@@ -12185,22 +12273,22 @@ msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
-"The area covered by the BackBufferCopy. Only used if [member copy_mode] is "
+"The area covered by the [BackBufferCopy]. Only used if [member copy_mode] is "
"[constant COPY_MODE_RECT]."
msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
-"Disables the buffering mode. This means the BackBufferCopy node will "
+"Disables the buffering mode. This means the [BackBufferCopy] node will "
"directly use the portion of screen it covers."
msgstr ""
#: doc/classes/BackBufferCopy.xml
-msgid "BackBufferCopy buffers a rectangular region."
+msgid "[BackBufferCopy] buffers a rectangular region."
msgstr ""
#: doc/classes/BackBufferCopy.xml
-msgid "BackBufferCopy buffers the entire screen."
+msgid "[BackBufferCopy] buffers the entire screen."
msgstr ""
#: doc/classes/BakedLightmap.xml
@@ -12413,7 +12501,7 @@ msgstr ""
#: doc/classes/BakedLightmap.xml doc/classes/SpatialMaterial.xml
msgid "Currently unused."
-msgstr ""
+msgstr "Ð’ наÑтоÑщее Ð²Ñ€ÐµÐ¼Ñ Ð½Ðµ иÑпользуетÑÑ."
#: doc/classes/BakedLightmap.xml
#, fuzzy
@@ -12874,7 +12962,7 @@ msgstr ""
#: doc/classes/BitMap.xml
msgid "Boolean matrix."
-msgstr ""
+msgstr "ЛогичеÑÐºÐ°Ñ Ð¼Ð°Ñ‚Ñ€Ð¸Ñ†Ð°."
#: doc/classes/BitMap.xml
msgid ""
@@ -13237,6 +13325,29 @@ msgid ""
"given time. Use [TouchScreenButton] for buttons that trigger gameplay "
"movement or actions, as [TouchScreenButton] supports multitouch."
msgstr ""
+"Кнопка - Ñто ÑÑ‚Ð°Ð½Ð´Ð°Ñ€Ñ‚Ð½Ð°Ñ Ñ‚ÐµÐ¼Ð°Ñ‚Ð¸Ñ‡ÐµÑÐºÐ°Ñ ÐºÐ½Ð¾Ð¿ÐºÐ°. Она может Ñодержать текÑÑ‚ и "
+"иконку, и будет отображать их в ÑоответÑтвии Ñ Ñ‚ÐµÐºÑƒÑ‰ÐµÐ¹ темой [Theme].\n"
+"[b]Пример ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ ÐºÐ½Ð¾Ð¿ÐºÐ¸ и Ð½Ð°Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð´ÐµÐ¹ÑÑ‚Ð²Ð¸Ñ Ð¿Ñ€Ð¸ нажатии Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ кода:[/"
+"b]\n"
+"[codeblock].\n"
+"func _ready():\n"
+" var button = Button.new()\n"
+" button.text = \"Ðажмите на менÑ\"\n"
+" button.connect(\"pressed\", self, \"_button_pressed\")\n"
+" add_child(button)\n"
+"\n"
+"func _button_pressed():\n"
+" print(\"Hello world!\")\n"
+"[/codeblock].\n"
+"Кнопки (как и вÑе узлы Control) также могут быть Ñозданы в редакторе, но "
+"некоторые Ñитуации могут потребовать их ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð¸Ð· кода.\n"
+"См. также [BaseButton], который Ñодержит общие ÑвойÑтва и методы, ÑвÑзанные "
+"Ñ Ñтим узлом.\n"
+"[b]Примечание: Кнопки[/b] не интерпретируют ÑенÑорный ввод и поÑтому не "
+"поддерживают мультитач, поÑкольку ÑмулÑÑ†Ð¸Ñ Ð¼Ñ‹ÑˆÐ¸ позволÑет нажимать только "
+"одну кнопку в данный момент времени. ИÑпользуйте [TouchScreenButton] Ð´Ð»Ñ "
+"кнопок, запуÑкающих движение или дейÑÑ‚Ð²Ð¸Ñ Ð¸Ð³Ñ€Ð¾Ð²Ð¾Ð³Ð¾ процеÑÑа, поÑкольку "
+"[TouchScreenButton] поддерживает мультитач."
#: doc/classes/Button.xml doc/classes/Dictionary.xml
#: doc/classes/GridContainer.xml doc/classes/OS.xml
@@ -13712,6 +13823,20 @@ msgid ""
"limits. You can use [method get_camera_screen_center] to get the real "
"position."
msgstr ""
+"Узел камеры Ð´Ð»Ñ 2D-Ñцен. Он заÑтавлÑет Ñкран (текущий Ñлой) прокручиватьÑÑ "
+"вÑлед за Ñтим узлом. Это позволÑет проще (и быÑтрее) программировать "
+"прокручиваемые Ñцены, чем вручную изменÑть положение узлов на оÑнове "
+"[CanvasItem].\n"
+"Этот узел задуман как проÑтой помощник Ð´Ð»Ñ Ð±Ñ‹Ñтрого начала работы, но Ð´Ð»Ñ "
+"Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ñ€Ð°Ð±Ð¾Ñ‚Ñ‹ камеры может потребоватьÑÑ Ð±Ð¾Ð»ÐµÐµ ÑˆÐ¸Ñ€Ð¾ÐºÐ°Ñ Ñ„ÑƒÐ½ÐºÑ†Ð¸Ð¾Ð½Ð°Ð»ÑŒÐ½Ð¾Ñть. "
+"Чтобы Ñоздать Ñвой ÑобÑтвенный узел камеры, наÑледуйте его от [Node2D] и "
+"измените транÑформацию холÑта, уÑтановив [member Viewport.canvas_transform] "
+"в [Viewport] (текущий [Viewport] можно получить Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ [method Node."
+"get_viewport]).\n"
+"Обратите внимание, что положение узла [Camera2D] [code][/code] не отражает "
+"фактичеÑкое положение Ñкрана, которое может отличатьÑÑ Ð¸Ð·-за примененного "
+"ÑÐ³Ð»Ð°Ð¶Ð¸Ð²Ð°Ð½Ð¸Ñ Ð¸Ð»Ð¸ ограничений. Ð”Ð»Ñ Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ñ€ÐµÐ°Ð»ÑŒÐ½Ð¾Ð³Ð¾ Ð¿Ð¾Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð¼Ð¾Ð¶Ð½Ð¾ "
+"иÑпользовать [метод get_camera_screen_center]."
#: doc/classes/Camera2D.xml doc/classes/TileMap.xml doc/classes/TileSet.xml
msgid "2D Isometric Demo"
@@ -14028,7 +14153,7 @@ msgstr ""
#: doc/classes/CameraFeed.xml
msgid "Unspecified position."
-msgstr ""
+msgstr "ÐÐµÑƒÐºÐ°Ð·Ð°Ð½Ð½Ð°Ñ Ð´Ð¾Ð»Ð¶Ð½Ð¾Ñть."
#: doc/classes/CameraFeed.xml
msgid "Camera is mounted at the front of the device."
@@ -15921,6 +16046,23 @@ msgid ""
"[url=https://raw.githubusercontent.com/godotengine/godot-docs/master/img/"
"color_constants.png]Color constants cheatsheet[/url]"
msgstr ""
+"Цвет, предÑтавленный краÑным, зеленым, Ñиним и альфа-компонентами (RGBA). "
+"Компонент альфа чаÑто иÑпользуетÑÑ Ð´Ð»Ñ Ð½ÐµÐ¿Ñ€Ð¾Ð·Ñ€Ð°Ñ‡Ð½Ð¾Ñти. Ð—Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð·Ð°Ð´Ð°ÑŽÑ‚ÑÑ Ñ "
+"плавающей точкой и обычно находÑÑ‚ÑÑ Ð² диапазоне от 0 до 1. Ðекоторые "
+"ÑвойÑтва (например, CanvasItem.modulate) могут принимать Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð±Ð¾Ð»ÑŒÑˆÐµ 1 "
+"(переÑвет или цвета HDR).\n"
+"Ð’Ñ‹ также можете Ñоздать цвет из Ñтандартизированных имен цветов Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ "
+"[метода @GDScript.ColorN] или непоÑредÑтвенно иÑÐ¿Ð¾Ð»ÑŒÐ·ÑƒÑ Ð¾Ð¿Ñ€ÐµÐ´ÐµÐ»ÐµÐ½Ð½Ñ‹Ðµ здеÑÑŒ "
+"цветовые конÑтанты. Стандартизированный набор цветов оÑнован на [url=https://"
+"en.wikipedia.org/wiki/X11_color_names]именах цветов X11[/url].\n"
+"ЕÑли вы хотите задать Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð² диапазоне от 0 до 255, вам Ñледует "
+"иÑпользовать [метод @GDScript.Color8].\n"
+"[b]Примечание:[/b] Ð’ булевом контекÑте значение Color будет равно "
+"[code]false[/code], еÑли оно равно [code]Color(0, 0, 0, 0, 1)[/code] "
+"(непрозрачный черный). Ð’ противном Ñлучае значение Color вÑегда будет равно "
+"[code]true[/code].\n"
+"[url=https://raw.githubusercontent.com/godotengine/godot-docs/master/img/"
+"color_constants.png]Шпаргалка по конÑтантам цвета[/url]"
#: doc/classes/Color.xml doc/classes/ColorPickerButton.xml
msgid "2D GD Paint Demo"
@@ -16203,15 +16345,15 @@ msgstr ""
#: doc/classes/Color.xml
msgid "Aqua color."
-msgstr ""
+msgstr "Цвет аква."
#: doc/classes/Color.xml
msgid "Aquamarine color."
-msgstr ""
+msgstr "Цвет аквамарина."
#: doc/classes/Color.xml
msgid "Azure color."
-msgstr ""
+msgstr "Лазурный цвет."
#: doc/classes/Color.xml
msgid "Beige color."
@@ -16219,7 +16361,7 @@ msgstr "Бежевый цвет."
#: doc/classes/Color.xml
msgid "Bisque color."
-msgstr ""
+msgstr "Цвет биÑквита."
#: doc/classes/Color.xml
msgid "Black color."
@@ -16251,7 +16393,7 @@ msgstr ""
#: doc/classes/Color.xml
msgid "Chartreuse color."
-msgstr ""
+msgstr "Цвет шартрез."
#: doc/classes/Color.xml
msgid "Chocolate color."
@@ -16259,11 +16401,11 @@ msgstr "Шоколадный цвет."
#: doc/classes/Color.xml
msgid "Coral color."
-msgstr ""
+msgstr "Коралловый цвет."
#: doc/classes/Color.xml
msgid "Cornflower color."
-msgstr ""
+msgstr "ВаÑильковый цвет."
#: doc/classes/Color.xml
msgid "Corn silk color."
@@ -16271,11 +16413,11 @@ msgstr ""
#: doc/classes/Color.xml
msgid "Crimson color."
-msgstr ""
+msgstr "Багровый цвет."
#: doc/classes/Color.xml
msgid "Cyan color."
-msgstr ""
+msgstr "Голубой цвет."
#: doc/classes/Color.xml
msgid "Dark blue color."
@@ -16363,7 +16505,7 @@ msgstr ""
#: doc/classes/Color.xml
msgid "Firebrick color."
-msgstr ""
+msgstr "Кирпичный цвет."
#: doc/classes/Color.xml
msgid "Floral white color."
@@ -16379,7 +16521,7 @@ msgstr "Цвет фукÑии."
#: doc/classes/Color.xml
msgid "Gainsboro color."
-msgstr ""
+msgstr "Цвет ГейнÑборо."
#: doc/classes/Color.xml
msgid "Ghost white color."
@@ -16391,7 +16533,7 @@ msgstr "Золотой цвет."
#: doc/classes/Color.xml
msgid "Goldenrod color."
-msgstr ""
+msgstr "ЗолотиÑто-рыжий цвет."
#: doc/classes/Color.xml
msgid "Gray color."
@@ -16407,7 +16549,7 @@ msgstr ""
#: doc/classes/Color.xml
msgid "Honeydew color."
-msgstr ""
+msgstr "Цвет медовой роÑÑ‹."
#: doc/classes/Color.xml
msgid "Hot pink color."
@@ -16423,15 +16565,15 @@ msgstr "Цвет индиго."
#: doc/classes/Color.xml
msgid "Ivory color."
-msgstr ""
+msgstr "Цвет Ñлоновой коÑти."
#: doc/classes/Color.xml
msgid "Khaki color."
-msgstr ""
+msgstr "Цвет хаки."
#: doc/classes/Color.xml
msgid "Lavender color."
-msgstr ""
+msgstr "Цвет лаванды."
#: doc/classes/Color.xml
msgid "Lavender blush color."
@@ -16499,7 +16641,7 @@ msgstr ""
#: doc/classes/Color.xml
msgid "Lime color."
-msgstr ""
+msgstr "Цвет лайма."
#: doc/classes/Color.xml
msgid "Lime green color."
@@ -16507,15 +16649,15 @@ msgstr ""
#: doc/classes/Color.xml
msgid "Linen color."
-msgstr ""
+msgstr "Цвет льна."
#: doc/classes/Color.xml
msgid "Magenta color."
-msgstr ""
+msgstr "Пурпурный цвет."
#: doc/classes/Color.xml
msgid "Maroon color."
-msgstr ""
+msgstr "Бордовый цвет."
#: doc/classes/Color.xml
msgid "Medium aquamarine color."
@@ -16567,7 +16709,7 @@ msgstr ""
#: doc/classes/Color.xml
msgid "Moccasin color."
-msgstr ""
+msgstr "Цвет мокаÑин."
#: doc/classes/Color.xml
msgid "Navajo white color."
@@ -16627,7 +16769,7 @@ msgstr ""
#: doc/classes/Color.xml
msgid "Peru color."
-msgstr ""
+msgstr "ПеруанÑкий цвет."
#: doc/classes/Color.xml
msgid "Pink color."
@@ -16635,7 +16777,7 @@ msgstr "Розовый цвет."
#: doc/classes/Color.xml
msgid "Plum color."
-msgstr ""
+msgstr "Цвет Ñливы."
#: doc/classes/Color.xml
msgid "Powder blue color."
@@ -16667,7 +16809,7 @@ msgstr ""
#: doc/classes/Color.xml
msgid "Salmon color."
-msgstr ""
+msgstr "Цвет лоÑоÑÑ."
#: doc/classes/Color.xml
msgid "Sandy brown color."
@@ -16683,11 +16825,11 @@ msgstr "Цвет морÑкой раковины."
#: doc/classes/Color.xml
msgid "Sienna color."
-msgstr ""
+msgstr "Цвет Ñиены."
#: doc/classes/Color.xml
msgid "Silver color."
-msgstr ""
+msgstr "СеребрÑный цвет."
#: doc/classes/Color.xml
msgid "Sky blue color."
@@ -16703,7 +16845,7 @@ msgstr ""
#: doc/classes/Color.xml
msgid "Snow color."
-msgstr ""
+msgstr "Цвет Ñнега."
#: doc/classes/Color.xml
msgid "Spring green color."
@@ -16715,19 +16857,19 @@ msgstr ""
#: doc/classes/Color.xml
msgid "Tan color."
-msgstr ""
+msgstr "Цвет загара."
#: doc/classes/Color.xml
msgid "Teal color."
-msgstr ""
+msgstr "Цвет тила."
#: doc/classes/Color.xml
msgid "Thistle color."
-msgstr ""
+msgstr "Цвет чертополоха."
#: doc/classes/Color.xml
msgid "Tomato color."
-msgstr ""
+msgstr "Цвет томатов."
#: doc/classes/Color.xml
msgid "Transparent color (white with no alpha)."
@@ -16735,7 +16877,7 @@ msgstr ""
#: doc/classes/Color.xml
msgid "Turquoise color."
-msgstr ""
+msgstr "Бирюзовый цвет."
#: doc/classes/Color.xml
msgid "Violet color."
@@ -16759,11 +16901,11 @@ msgstr ""
#: doc/classes/Color.xml
msgid "Wheat color."
-msgstr ""
+msgstr "Цвет пшеницы."
#: doc/classes/Color.xml
msgid "White color."
-msgstr ""
+msgstr "Белый цвет."
#: doc/classes/Color.xml
msgid "White smoke color."
@@ -17004,7 +17146,7 @@ msgstr ""
#: doc/classes/ColorRect.xml
msgid "Colored rectangle."
-msgstr ""
+msgstr "Цветной прÑмоугольник."
#: doc/classes/ColorRect.xml
msgid ""
@@ -17040,6 +17182,21 @@ msgid ""
"Physics the area will not detect any collisions with the concave shape at "
"all (this is a known bug)."
msgstr ""
+"РеÑÑƒÑ€Ñ Ñ„Ð¾Ñ€Ð¼Ñ‹ вогнутого многоугольника, который может быть уÑтановлен в "
+"[PhysicsBody] или облаÑть. Эта форма ÑоздаетÑÑ Ð¿ÑƒÑ‚ÐµÐ¼ подачи ÑпиÑка "
+"треугольников.\n"
+"[b]Примечание:[/b] При иÑпользовании Ð´Ð»Ñ Ñтолкновений [ConcavePolygonShape] "
+"предназначен Ð´Ð»Ñ Ñ€Ð°Ð±Ð¾Ñ‚Ñ‹ Ñо ÑтатичеÑкими узлами [PhysicsBody], такими как "
+"[StaticBody], и не будет работать Ñ [KinematicBody] или [RigidBody] Ñ "
+"режимом, отличным от Static.\n"
+"[b]Предупреждение:[/b] ИÑпользование Ñтой формы Ð´Ð»Ñ [Area] (через узел "
+"[CollisionShape], Ñозданный, например. Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ опции [i]Create Trimesh "
+"Collision Sibling[/i] в меню [i]Mesh[/i], которое поÑвлÑетÑÑ Ð¿Ñ€Ð¸ выборе узла "
+"[MeshInstance]) может привеÑти к неожиданным результатам: при иÑпользовании "
+"Godot Physics облаÑть будет обнаруживать ÑÑ‚Ð¾Ð»ÐºÐ½Ð¾Ð²ÐµÐ½Ð¸Ñ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ Ñ Ð³Ñ€Ð°Ð½Ñми "
+"треугольника в [ConcavePolygonShape] (а не Ñ Ð»ÑŽÐ±Ð¾Ð¹ \"внутренней\" чаÑтью "
+"формы, например), а при иÑпользовании Bullet Physics облаÑть вообще не будет "
+"обнаруживать Ñтолкновений Ñ Ð²Ð¾Ð³Ð½ÑƒÑ‚Ð¾Ð¹ формой (Ñто извеÑÑ‚Ð½Ð°Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ°)."
#: doc/classes/ConcavePolygonShape.xml
msgid "Returns the faces (an array of triangles)."
@@ -17070,6 +17227,21 @@ msgid ""
"the segments in the [ConcavePolygonShape2D] (and not with any \"inside\" of "
"the shape, for example)."
msgstr ""
+"РеÑÑƒÑ€Ñ Ð²Ð¾Ð³Ð½ÑƒÑ‚Ð¾Ð¹ многоугольной 2D формы Ð´Ð»Ñ Ñ„Ð¸Ð·Ð¸ÐºÐ¸. Он ÑоÑтоит из Ñегментов и "
+"оптимален Ð´Ð»Ñ Ñложных полигональных вогнутых Ñтолкновений. Однако его не "
+"рекомендуетÑÑ Ð¸Ñпользовать Ð´Ð»Ñ ÑƒÐ·Ð»Ð¾Ð² [RigidBody2D]. ВмеÑто него "
+"рекомендуетÑÑ Ð¸Ñпользовать CollisionPolygon2D в режиме выпуклого Ñ€Ð°Ð·Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ "
+"(твердые тела) или неÑколько выпуклых объектов. Ð’ противном Ñлучае Ð´Ð»Ñ "
+"ÑтатичеÑких Ñтолкновений лучше иÑпользовать вогнутую полигональную 2D-"
+"форму.\n"
+"ОÑновное различие между [ConvexPolygonShape2D] и [ConcavePolygonShape2D] "
+"заключаетÑÑ Ð² том, что вогнутый полигон предполагает, что он вогнутый и "
+"иÑпользует более Ñложный метод Ð¾Ð±Ð½Ð°Ñ€ÑƒÐ¶ÐµÐ½Ð¸Ñ Ñтолкновений, а выпуклый "
+"заÑтавлÑет ÑÐµÐ±Ñ Ð±Ñ‹Ñ‚ÑŒ выпуклым, чтобы уÑкорить обнаружение Ñтолкновений.\n"
+"[b]Предупреждение:[/b] ИÑпользование Ñтой фигуры Ð´Ð»Ñ [Area2D] (через узел "
+"[CollisionShape2D]) может дать неожиданные результаты: облаÑть будет "
+"обнаруживать ÑÑ‚Ð¾Ð»ÐºÐ½Ð¾Ð²ÐµÐ½Ð¸Ñ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ Ñ Ñегментами в [ConcavePolygonShape2D] (а "
+"не Ñ Ð»ÑŽÐ±Ð¾Ð¹ \"внутренней\" чаÑтью фигуры, например)."
#: doc/classes/ConcavePolygonShape2D.xml
msgid ""
@@ -17529,6 +17701,27 @@ msgid ""
"[member rect_clip_content] or [method _clips_input] enabled.\n"
"[b]Note:[/b] Event position is relative to the control origin."
msgstr ""
+"Виртуальный метод, который должен быть реализован пользователем. ИÑпользуйте "
+"Ñтот метод Ð´Ð»Ñ Ð¾Ð±Ñ€Ð°Ð±Ð¾Ñ‚ÐºÐ¸ и приема входных данных на Ñлементах "
+"пользовательÑкого интерфейÑа. См. [метод accept_event].\n"
+"Пример: щелчок по Ñлементу управлениÑ.\n"
+"[codeblock].\n"
+"func _gui_input(event):\n"
+" if event is InputEventMouseButton:\n"
+" if event.button_index == BUTTON_LEFT and event.pressed:\n"
+" print(\"Ðа Ð¼ÐµÐ½Ñ Ð½Ð°Ð¶Ð°Ð»Ð¸ D:\")\n"
+"[/codeblock].\n"
+"Событие не Ñработает, еÑли:\n"
+"* щелчок вне Ñлемента ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ (Ñм. [метод has_point]);\n"
+"* у Ñлемента ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ [member mouse_filter] уÑтановлено значение [constant "
+"MOUSE_FILTER_IGNORE];\n"
+"* Ñлемент ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð·Ð°Ð³Ð¾Ñ€Ð¾Ð¶ÐµÐ½ другим [Control] Ñверху, у которого [member "
+"mouse_filter] не уÑтановлен на [constant MOUSE_FILTER_IGNORE];\n"
+"* родитель Ñлемента ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð¸Ð¼ÐµÐµÑ‚ [member mouse_filter], уÑтановленный на "
+"[constant MOUSE_FILTER_STOP] или принÑл Ñобытие;\n"
+"* Ñобытие проиÑходит вне прÑмоугольника родителÑ, и у Ñ€Ð¾Ð´Ð¸Ñ‚ÐµÐ»Ñ Ð²ÐºÐ»ÑŽÑ‡ÐµÐ½ [член "
+"rect_clip_content] или [метод _clips_input].\n"
+"[b]Примечание:[/b] Положение ÑÐ¾Ð±Ñ‹Ñ‚Ð¸Ñ Ð¾Ñ‚Ð½Ð¾Ñительно начала Ñлемента управлениÑ."
#: doc/classes/Control.xml
msgid ""
@@ -17654,6 +17847,27 @@ msgid ""
"$MyButton.add_stylebox_override(\"normal\", null)\n"
"[/codeblock]"
msgstr ""
+"Создает локальное переопределение Ð´Ð»Ñ Ñ‚ÐµÐ¼Ñ‹ [StyleBox] Ñ ÑƒÐºÐ°Ð·Ð°Ð½Ð½Ñ‹Ð¼ "
+"[code]именем[/code] . Локальные Ð¿ÐµÑ€ÐµÐ¾Ð¿Ñ€ÐµÐ´ÐµÐ»ÐµÐ½Ð¸Ñ Ð²Ñегда имеют приоритет при "
+"получении Ñлементов темы Ð´Ð»Ñ Ñлемента управлениÑ.\n"
+"[b]Примечание:[/b] Переопределение можно удалить, приÑвоив ему значение "
+"[code]null[/code]. Это поведение уÑтарело и будет удалено в верÑии 4.0, "
+"иÑпользуйте [метод remove_stylebox_override] вмеÑто Ñтого.\n"
+"См. также [метод get_stylebox].\n"
+"[b]Пример Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ ÑвойÑтва в StyleBox путем его дублированиÑ:[/b]\n"
+"[codeblock]\n"
+"# Ð’ приведенном ниже фрагменте предполагаетÑÑ, что дочернему узлу MyButton "
+"назначен StyleBoxFlat.\n"
+"# РеÑурÑÑ‹ разделÑÑŽÑ‚ÑÑ Ð¼ÐµÐ¶Ð´Ñƒ ÑкземплÑрами, поÑтому нам нужно продублировать "
+"его.\n"
+"# чтобы избежать Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð²Ð½ÐµÑˆÐ½ÐµÐ³Ð¾ вида вÑех оÑтальных кнопок.\n"
+"var new_stylebox_normal = $MyButton.get_stylebox(\"normal\").duplicate()\n"
+"new_stylebox_normal.border_width_top = 3\n"
+"new_stylebox_normal.border_color = Color(0, 1, 0.5)\n"
+"$MyButton.add_stylebox_override(\"normal\", new_stylebox_normal)\n"
+"# Удалите переопределение Ñтилей.\n"
+"$MyButton.add_stylebox_override(\"normal\", null)\n"
+"[/codeblock]."
#: doc/classes/Control.xml
msgid ""
@@ -18362,6 +18576,27 @@ msgid ""
"theme.set_color(\"font_color\", \"TooltipLabel\", Color(0, 1, 1))\n"
"[/codeblock]"
msgstr ""
+"ИзменÑет текÑÑ‚ вÑплывающей подÑказки. ПодÑказка поÑвлÑетÑÑ, когда курÑор "
+"мыши Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¿Ñ€Ð¾Ñтаивает над Ñтим Ñлементом ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð² течение "
+"неÑкольких мгновений, при уÑловии, что ÑвойÑтво [member mouse_filter] не "
+"ÑвлÑетÑÑ [constant MOUSE_FILTER_IGNORE]. Ð’Ñ‹ можете изменить времÑ, "
+"необходимое Ð´Ð»Ñ Ð¿Ð¾ÑÐ²Ð»ÐµÐ½Ð¸Ñ Ð²Ñплывающей подÑказки Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ опции [code]gui/"
+"timers/tooltip_delay_sec[/code] в ÐаÑтройках проекта.\n"
+"Ð’ÑÐ¿Ð»Ñ‹Ð²Ð°ÑŽÑ‰Ð°Ñ Ð¿Ð¾Ð´Ñказка будет иÑпользовать либо реализацию по умолчанию, либо "
+"пользовательÑкую, которую вы можете Ñоздать, переопределив [метод "
+"_make_custom_tooltip]. Ð’ÑÐ¿Ð»Ñ‹Ð²Ð°ÑŽÑ‰Ð°Ñ Ð¿Ð¾Ð´Ñказка по умолчанию включает "
+"[PopupPanel] и [Label], ÑвойÑтва темы которых можно наÑтроить Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ "
+"методов [Theme] Ñ [code]\"TooltipPanel\"[/code] и [code]\"TooltipLabel\"[/"
+"code] ÑоответÑтвенно. Ðапример:\n"
+"[codeblock]\n"
+"var style_box = StyleBoxFlat.new()\n"
+"style_box.set_bg_color(Color(1, 1, 0))\n"
+"style_box.set_border_width_all(2)\n"
+"# ЗдеÑÑŒ мы предполагаем, что ÑвойÑтву `theme` была предварительно назначена "
+"пользовательÑÐºÐ°Ñ Ñ‚ÐµÐ¼Ð°.\n"
+"theme.set_stylebox(\"panel\", \"TooltipPanel\", style_box)\n"
+"theme.set_color(\"font_color\", \"TooltipLabel\", Color(0, 1, 1))\n"
+"[/codeblock]"
#: doc/classes/Control.xml
msgid ""
@@ -18482,6 +18717,22 @@ msgid ""
"[code]yield(get_tree(), \"idle_frame\")[/code] then set its [member "
"rect_scale] property."
msgstr ""
+"МаÑштаб узла отноÑительно его [member rect_size]. Измените Ñто ÑвойÑтво, "
+"чтобы изменить маÑштаб узла отноÑительно его [член rect_pivot_offset]. "
+"МаÑштаб [member hint_tooltip] Ñлемента ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ñ‚Ð°ÐºÐ¶Ðµ будет изменÑтьÑÑ Ð² "
+"ÑоответÑтвии Ñ Ñтим значением.\n"
+"[b]Примечание:[/b] Это ÑвойÑтво в оÑновном предназначено Ð´Ð»Ñ Ð¸ÑÐ¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Ð² "
+"целÑÑ… анимации. ТекÑÑ‚ внутри Ñлемента ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð±ÑƒÐ´ÐµÑ‚ выглÑдеть "
+"пикÑелированным или размытым при маÑштабировании Ñлемента управлениÑ. Ð”Ð»Ñ "
+"поддержки неÑкольких разрешений в вашем проекте иÑпользуйте ÑоответÑтвующий "
+"режим раÑÑ‚ÑÐ¶ÐµÐ½Ð¸Ñ Ð²Ð¸Ð´Ð¾Ð²Ð¾Ð³Ð¾ Ñкрана, как опиÑано в [url=$DOCS_URL/tutorials/"
+"rendering/multiple_resolutions.html]документации[/url] вмеÑто "
+"маÑÑˆÑ‚Ð°Ð±Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Controls по отдельноÑти.\n"
+"[b]Примечание:[/b] ЕÑли узел Control ÑвлÑетÑÑ Ð´Ð¾Ñ‡ÐµÑ€Ð½Ð¸Ð¼ узлом узла "
+"[Container], маÑштаб будет Ñброшен на [code]Vector2(1, 1)[/code] при "
+"инÑтанÑировании Ñцены. Чтобы уÑтановить маÑштаб Ñлемента ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð¿Ñ€Ð¸ его "
+"инÑтанцировании, подождите один кадр, иÑÐ¿Ð¾Ð»ÑŒÐ·ÑƒÑ [code]yield(get_tree(), "
+"\"idle_frame\")[/code], а затем уÑтановите его ÑвойÑтво [member rect_scale]."
#: doc/classes/Control.xml
msgid ""
@@ -19750,6 +20001,43 @@ msgid ""
"[/codeblock]\n"
"[b]Note:[/b] Not available in HTML5 exports."
msgstr ""
+"КлаÑÑ Crypto позволÑет вам получить доÑтуп к некоторым более продвинутым "
+"криптографичеÑким функциÑм в Godot.\n"
+"Ðа данный момент Ñто Ð³ÐµÐ½ÐµÑ€Ð°Ñ†Ð¸Ñ ÐºÑ€Ð¸Ð¿Ñ‚Ð¾Ð³Ñ€Ð°Ñ„Ð¸Ñ‡ÐµÑки безопаÑных Ñлучайных байтов, "
+"Ð³ÐµÐ½ÐµÑ€Ð°Ñ†Ð¸Ñ RSA-ключей и ÑамоподпиÑанных Ñертификатов X509, шифрование/"
+"дешифрование аÑимметричных ключей, а также подпиÑание/верификациÑ.\n"
+"[codeblock].\n"
+"раÑширÑет Node\n"
+"\n"
+"var crypto = Crypto.new()\n"
+"var key = CryptoKey.new()\n"
+"var cert = X509Certificate.new()\n"
+"\n"
+"func _ready():\n"
+" # Генерируем новый RSA-ключ.\n"
+" key = crypto.generate_rsa(4096)\n"
+" # Генерируем новый ÑамоподпиÑанный Ñертификат Ñ Ð·Ð°Ð´Ð°Ð½Ð½Ñ‹Ð¼ ключом.\n"
+" cert = crypto.generate_self_signed_certificate(key, \"CN=mydomain.com,"
+"O=My Game Company,C=IT\")\n"
+" # Сохраните ключ и Ñертификат в папке пользователÑ.\n"
+" key.save(\"user://generated.key\")\n"
+" cert.save(\"user://generated.crt\")\n"
+" # Шифрование\n"
+" var data = \"Ðекоторые данные\"\n"
+" var encrypted = crypto.encrypt(key, data.to_utf8())\n"
+" # РаÑшифровка\n"
+" var decrypted = crypto.decrypt(key, encrypted)\n"
+" # ПодпиÑание\n"
+" var signature = crypto.sign(HashingContext.HASH_SHA256, data."
+"sha256_buffer(), key)\n"
+" # Проверка\n"
+" verified = crypto.verify(HashingContext.HASH_SHA256, data."
+"sha256_buffer(), signature, key)\n"
+" # ПроверÑет\n"
+" assert(verified)\n"
+" assert(data.to_utf8() == decrypted)\n"
+"[/codeblock].\n"
+"[b]Примечание:[/b] ÐедоÑтупно в ÑкÑпорте HTML5."
#: doc/classes/Crypto.xml
msgid ""
@@ -19936,6 +20224,19 @@ msgid ""
"node also has a significant CPU cost, so it should be avoided during "
"gameplay."
msgstr ""
+"Ð”Ð»Ñ Ñложного раÑÐ¿Ð¾Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ñ„Ð¸Ð³ÑƒÑ€ иногда требуетÑÑ Ð´Ð¾Ð±Ð°Ð²Ð¸Ñ‚ÑŒ Ñтруктуру в узлы "
+"CSG. Узел CSGCombiner позволÑет Ñоздать такую Ñтруктуру. Узел инкапÑулирует "
+"результат операций CSG Ñвоих дочерних узлов. Таким образом, можно выполнить "
+"операции над одним набором фигур, которые ÑвлÑÑŽÑ‚ÑÑ Ð´Ð¾Ñ‡ÐµÑ€Ð½Ð¸Ð¼Ð¸ Ñлементами "
+"одного узла CSGCombiner, и Ñ€Ñд отдельных операций над вторым набором фигур, "
+"которые ÑвлÑÑŽÑ‚ÑÑ Ð´Ð¾Ñ‡ÐµÑ€Ð½Ð¸Ð¼Ð¸ Ñлементами второго узла CSGCombiner, а затем "
+"выполнить операцию, ÐºÐ¾Ñ‚Ð¾Ñ€Ð°Ñ Ð¸Ñпользует Ñти два конечных результата в "
+"качеÑтве входных данных Ð´Ð»Ñ ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð¾ÐºÐ¾Ð½Ñ‡Ð°Ñ‚ÐµÐ»ÑŒÐ½Ð¾Ð¹ фигуры.\n"
+"[b]Примечание:[/b] CSG-узлы предназначены Ð´Ð»Ñ Ð¸ÑÐ¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¿Ñ€Ð¸ Ñоздании "
+"прототипов уровней. Создание CSG-узлов требует значительных затрат "
+"процеÑÑора по Ñравнению Ñ Ñозданием [MeshInstance] Ñ [PrimitiveMesh]. "
+"Перемещение узла CSG внутри другого узла CSG также требует значительных "
+"затрат процеÑÑора, поÑтому Ñтого Ñледует избегать во Ð²Ñ€ÐµÐ¼Ñ Ð¸Ð³Ñ€Ð¾Ð²Ð¾Ð³Ð¾ процеÑÑа."
#: modules/csg/doc_classes/CSGCylinder.xml
msgid "A CSG Cylinder shape."
@@ -21139,6 +21440,14 @@ msgid "Cylinder shape for collisions."
msgstr ""
#: doc/classes/CylinderShape.xml
+msgid ""
+"Cylinder shape for collisions.\n"
+"[b]Note:[/b] When using GodotPhysics instead of the default Bullet physics "
+"engine, there are several known bugs with cylinder collision shapes. Using "
+"[CapsuleShape] or [BoxShape] instead is recommended."
+msgstr ""
+
+#: doc/classes/CylinderShape.xml
msgid "The cylinder's height."
msgstr "Ð’Ñ‹Ñота цилиндра."
@@ -21185,7 +21494,7 @@ msgstr ""
#: doc/classes/Dictionary.xml
msgid "Dictionary type."
-msgstr ""
+msgstr "Тип ÑловарÑ."
#: doc/classes/Dictionary.xml
msgid ""
@@ -23357,6 +23666,25 @@ msgid ""
" return state\n"
"[/codeblock]"
msgstr ""
+"Переопределите Ñтот метод, чтобы предоÑтавить данные ÑоÑтоÑниÑ, которые вы "
+"хотите Ñохранить, например, положение вида, наÑтройки Ñетки, Ñворачивание и "
+"Ñ‚.д. Эти данные иÑпользуютÑÑ Ð¿Ñ€Ð¸ Ñохранении Ñцены (чтобы ÑоÑтоÑние "
+"ÑохранÑлоÑÑŒ при ее повторном открытии) и при переключении вкладок (чтобы "
+"ÑоÑтоÑние можно было воÑÑтановить при возврате на вкладку). Эти данные "
+"автоматичеÑки ÑохранÑÑŽÑ‚ÑÑ Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð¹ Ñцены в файле [code]editstate[/code] в "
+"папке метаданных редактора. ЕÑли вы хотите Ñохранить глобальные (незавиÑимые "
+"от Ñцены) данные редактора Ð´Ð»Ñ Ð²Ð°ÑˆÐµÐ³Ð¾ плагина, вы можете иÑпользовать [метод "
+"get_window_layout] вмеÑто Ñтого.\n"
+"ИÑпользуйте [method set_state] Ð´Ð»Ñ Ð²Ð¾ÑÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ñохраненного ÑоÑтоÑниÑ.\n"
+"[b]Примечание:[/b] Этот метод не Ñледует иÑпользовать Ð´Ð»Ñ ÑÐ¾Ñ…Ñ€Ð°Ð½ÐµÐ½Ð¸Ñ Ð²Ð°Ð¶Ð½Ñ‹Ñ… "
+"наÑтроек, которые должны ÑохранÑтьÑÑ Ð² проекте.\n"
+"[b]Примечание:[/b] Ð”Ð»Ñ ÐºÐ¾Ñ€Ñ€ÐµÐºÑ‚Ð½Ð¾Ð³Ð¾ ÑÐ¾Ñ…Ñ€Ð°Ð½ÐµÐ½Ð¸Ñ Ð¸ воÑÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ ÑоÑтоÑÐ½Ð¸Ñ "
+"необходимо реализовать [метод get_plugin_name].\n"
+"[codeblock].\n"
+"func get_state():\n"
+" var state = {\"zoom\": zoom, \"preferred_color\": my_color}\n"
+" return state\n"
+"[/codeblock]"
#: doc/classes/EditorPlugin.xml
msgid ""
@@ -23907,6 +24235,33 @@ msgid ""
"- Binary format in FBX 2017\n"
"[/codeblock]"
msgstr ""
+"Это импортер 3D-активов FBX Ñ Ð¿Ð¾Ð»Ð½Ð¾Ð¹ поддержкой большинÑтва функций FBX.\n"
+"При ÑкÑпорте FBX-Ñцены из Autodesk Maya иÑпользуйте Ñти наÑтройки ÑкÑпорта "
+"FBX:\n"
+"[codeblock]\n"
+"- Группы ÑглаживаниÑ\n"
+"- Сгладить Ñетку\n"
+"- Triangluate (Ð´Ð»Ñ Ñеток Ñ Ñ„Ð¾Ñ€Ð¼Ð°Ð¼Ð¸ ÑмешениÑ)\n"
+"- Запечь анимацию\n"
+"- ÐŸÐ¾Ð²Ñ‚Ð¾Ñ€Ð½Ð°Ñ Ð²Ñ‹Ð±Ð¾Ñ€ÐºÐ°\n"
+"- Деформированные модели\n"
+"- Скины\n"
+"- Фигуры наложениÑ\n"
+"- Фильтры кривых\n"
+"- Уменьшитель поÑтоÑнного ключа\n"
+"- Только автоматичеÑкие каÑательные\n"
+"- Ðе отмечайте *Ðе отмечайте* Constraints (так как Ñто приведет к поломке "
+"файла)\n"
+"- Можно уÑтановить флажок Embed Media (вÑтраивает текÑтуры в ÑкÑпортируемый "
+"FBX-файл).\n"
+" - Обратите внимание, что при импорте вÑтроенной Ñреды текÑтура и Ñетка "
+"будут одним неизменÑемым файлом.\n"
+" - Вам придетÑÑ Ð¿Ð¾Ð²Ñ‚Ð¾Ñ€Ð½Ð¾ ÑкÑпортировать и повторно импортировать FBX, еÑли "
+"текÑтура изменилаÑÑŒ.\n"
+"- Единицы измерениÑ: Сантиметры\n"
+"- ОÑÑŒ вверх: Y\n"
+"- Двоичный формат в FBX 2017\n"
+"[/codeblock]."
#: modules/gltf/doc_classes/EditorSceneImporterGLTF.xml
msgid ""
@@ -23985,7 +24340,10 @@ msgid ""
"[/codeblock]\n"
"[b]Note:[/b] The script is run in the Editor context, which means the output "
"is visible in the console window started with the Editor (stdout) instead of "
-"the usual Godot [b]Output[/b] dock."
+"the usual Godot [b]Output[/b] dock.\n"
+"[b]Note:[/b] EditorScript is reference counted, meaning it is destroyed when "
+"nothing references it. This can cause errors during asynchronous operations "
+"if there are no references to the script."
msgstr ""
#: doc/classes/EditorScript.xml
@@ -25032,6 +25390,27 @@ msgid ""
"Effects\" by default. It improves the performance on mobile devices, but at "
"the same time affects the screen display on mobile devices."
msgstr ""
+"РеÑÑƒÑ€Ñ Ð´Ð»Ñ ÑƒÐ·Ð»Ð¾Ð² Ð¾ÐºÑ€ÑƒÐ¶ÐµÐ½Ð¸Ñ (например, [WorldEnvironment]), которые "
+"определÑÑŽÑ‚ неÑколько операций Ñ Ð¾ÐºÑ€ÑƒÐ¶ÐµÐ½Ð¸ÐµÐ¼ (например, фон [Sky] или [Color], "
+"окружающий Ñвет, туман, глубина резкоÑти...). Эти параметры влиÑÑŽÑ‚ на "
+"конечный рендеринг Ñцены. ПорÑдок Ñтих операций Ñледующий:\n"
+"- Размытие глубины резкоÑти\n"
+"- Свечение\n"
+"- Ð¢Ð¾Ð½Ð¾Ð²Ð°Ñ ÐºÐ°Ñ€Ñ‚Ð° (автоÑкÑпозициÑ)\n"
+"- Корректировки\n"
+"ЕÑли Ð´Ð»Ñ Ñ†ÐµÐ»ÐµÐ²Ð¾Ð³Ð¾ [Viewport] уÑтановлено значение \"2D без выборки\", вÑе "
+"Ñффекты поÑтобработки будут недоÑтупны. При уÑтановке \"3D без Ñффектов\" "
+"Ñледующие опции будут недоÑтупны:\n"
+"- Ssao\n"
+"- Ss Reflections\n"
+"Это можно наÑтроить Ð´Ð»Ñ ÐºÐ¾Ñ€Ð½ÐµÐ²Ð¾Ð³Ð¾ вьюпорта Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ [member ProjectSettings."
+"rendering/quality/intended_usage/framebuffer_allocation] или Ð´Ð»Ñ "
+"определенных вьюпортов Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ ÑвойÑтва [member Viewport.usage].\n"
+"Обратите внимание, что [member ProjectSettings.rendering/quality/"
+"intended_usage/framebuffer_allocation] имеет переопределение Ð´Ð»Ñ Ð¼Ð¾Ð±Ð¸Ð»ÑŒÐ½Ñ‹Ñ… "
+"платформ, чтобы иÑпользовать \"3D без Ñффектов\" по умолчанию. Это улучшает "
+"производительноÑть на мобильных уÑтройÑтвах, но в то же Ð²Ñ€ÐµÐ¼Ñ Ð²Ð»Ð¸Ñет на "
+"отображение Ñкрана на мобильных уÑтройÑтвах."
#: doc/classes/Environment.xml doc/classes/WorldEnvironment.xml
#, fuzzy
@@ -26431,6 +26810,22 @@ msgid ""
"the [method @GDScript.is_equal_approx] and [method @GDScript.is_zero_approx] "
"methods instead of [code]==[/code] to compare [float] values for equality."
msgstr ""
+"Ð’Ñтроенный тип [float] - Ñто 64-битное чиÑло Ñ Ð¿Ð»Ð°Ð²Ð°ÑŽÑ‰ÐµÐ¹ точкой двойной "
+"точноÑти, Ñквивалентное [code]double[/code] в C++. Этот тип имеет 14 "
+"надежных деÑÑтичных цифр точноÑти. Тип [float] может хранитьÑÑ Ð² [Variant], "
+"который ÑвлÑетÑÑ Ð¾Ð±Ñ‰Ð¸Ð¼ типом, иÑпользуемым движком. МакÑимальное значение "
+"[float] приблизительно равно [code]1.79769e308[/code], а минимальное - "
+"приблизительно [code]-1.79769e308[/code].\n"
+"БольшинÑтво методов и ÑвойÑтв в движке иÑпользуют 32-битные чиÑла Ñ "
+"плавающей точкой одинарной точноÑти, Ñквивалентные [code]float[/code] в C++, "
+"которые имеют 6 надежных деÑÑтичных цифр точноÑти. Ð”Ð»Ñ Ñтруктур данных, "
+"таких как [Vector2] и [Vector3], Godot иÑпользует 32-битные чиÑла Ñ "
+"плавающей точкой.\n"
+"Математика, выполнÑÐµÐ¼Ð°Ñ Ñ Ð¸Ñпользованием типа [float], не гарантирует "
+"точноÑти или детерминированноÑти, и чаÑто будет приводить к небольшим "
+"ошибкам. Обычно Ð´Ð»Ñ ÑÑ€Ð°Ð²Ð½ÐµÐ½Ð¸Ñ Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ð¹ [float] на равенÑтво Ñледует "
+"иÑпользовать методы [method @GDScript.is_equal_approx] и [method @GDScript."
+"is_zero_approx] вмеÑто [code]==[/code]."
#: doc/classes/float.xml
msgid "Wikipedia: Double-precision floating-point format"
@@ -26502,6 +26897,22 @@ msgid ""
"emoji) are [i]not[/i] supported on Windows. They will display as unknown "
"characters instead. This will be resolved in Godot 4.0."
msgstr ""
+"Шрифт Ñодержит набор Ñимволов, ÑовмеÑтимый Ñ Unicode, а также возможноÑть "
+"риÑовать его Ñ Ð¿ÐµÑ€ÐµÐ¼ÐµÐ½Ð½Ð¾Ð¹ шириной, подъемом, ÑпуÑком и кернингом. О Ñоздании "
+"шрифтов из файлов TTF (или других форматов шрифтов) Ñм. раздел \"Поддержка "
+"шрифтов редактором\".\n"
+"[b]Примечание:[/b] ЕÑли [DynamicFont] не Ñодержит Ñимвол, иÑпользуемый в "
+"Ñтроке, то данный Ñимвол будет заменен кодовой точкой [code]0xfffd[/code], "
+"еÑли она доÑтупна в [DynamicFont]. ЕÑли Ñтот заменÑющий Ñимвол недоÑтупен в "
+"DynamicFont, Ñимвол будет Ñкрыт без Ð¾Ñ‚Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ Ð·Ð°Ð¼ÐµÐ½Ñющего Ñимвола в "
+"Ñтроке.\n"
+"[b]Примечание:[/b] ЕÑли [BitmapFont] не Ñодержит Ñимвол, иÑпользуемый в "
+"Ñтроке, то данный Ñимвол будет Ñкрыт без Ð¾Ñ‚Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ Ð·Ð°Ð¼ÐµÐ½Ñющего Ñимвола в "
+"Ñтроке.\n"
+"[b]Примечание:[/b] Символы Юникода поÑле [code]0xffff[/code] (например, "
+"большинÑтво Ñмодзи) [i]не[/i] поддерживаютÑÑ Ð² Windows. ВмеÑто Ñтого они "
+"будут отображатьÑÑ ÐºÐ°Ðº неизвеÑтные Ñимволы. Эта проблема будет решена в "
+"верÑии Godot 4.0."
#: doc/classes/Font.xml
msgid ""
@@ -27432,6 +27843,29 @@ msgid ""
"150), Vector2(50, 150)]\n"
"[/codeblock]"
msgstr ""
+"Раздувает или Ñдувает [code]многоугольник[/code] на [code]дельту[/code] "
+"единиц (пикÑелей). ЕÑли [code]дельта[/code] положительна, полигон "
+"увеличиваетÑÑ Ð½Ð°Ñ€ÑƒÐ¶Ñƒ. ЕÑли [code]дельта[/code] отрицательна, полигон "
+"уменьшаетÑÑ Ð²Ð½ÑƒÑ‚Ñ€ÑŒ. Возвращает маÑÑив полигонов, так как при раздувании/"
+"Ñжатии может получитьÑÑ Ð½ÐµÑколько диÑкретных полигонов. Возвращает пуÑтой "
+"маÑÑив, еÑли [code]delta[/code] отрицательна и ее абÑолютное значение "
+"приблизительно превышает минимальные размеры ограничивающего прÑмоугольника "
+"многоугольника.\n"
+"Вершины каждого многоугольника будут округлены в ÑоответÑтвии Ñ Ñ‚Ð¸Ð¿Ð¾Ð¼ "
+"[code]join_type[/code], Ñм. [enum PolyJoinType].\n"
+"В результате операции может быть получен внешний многоугольник (граница) и "
+"внутренний многоугольник (отверÑтие), которые можно отличить, вызвав [метод "
+"is_polygon_clockwise].\n"
+"[b]Примечание:[/b] Ð”Ð»Ñ Ñпециального перевода вершин многоугольника "
+"иÑпользуйте метод [method Transform2D.xform]:\n"
+"[codeblock].\n"
+"var polygon = PoolVector2Array([Vector2(0, 0), Vector2(100, 0), Vector2(100, "
+"100), Vector2(0, 100)])\n"
+"var offset = Vector2(50, 50)\n"
+"polygon = Transform2D(0, offset).xform(polygon)\n"
+"print(polygon) # печатает [Vector2(50, 50), Vector2(150, 50), Vector2(150, "
+"150), Vector2(50, 150)]\n"
+"[/codeblock]"
#: doc/classes/Geometry.xml
msgid ""
@@ -27813,6 +28247,23 @@ msgid ""
"[code]call_deferred(\"bake\")[/code] instead of calling [method bake] "
"directly."
msgstr ""
+"Запекает Ñффект из вÑех [GeometryInstance]ов, помеченных [member "
+"GeometryInstance.use_in_baked_light] и [Light]ов, помеченных либо [constant "
+"Light.BAKE_INDIRECT], либо [constant Light.BAKE_ALL]. ЕÑли "
+"[code]create_visual_debug[/code] равен [code]true[/code], то поÑле Ð·Ð°Ð¿ÐµÐºÐ°Ð½Ð¸Ñ "
+"Ñвета будет Ñгенерирован [MultiMesh], который имеет куб, предÑтавлÑющий "
+"каждую твердую Ñчейку, причем каждый куб окрашен в цвет альбедо Ñчейки. Это "
+"можно иÑпользовать Ð´Ð»Ñ Ð²Ð¸Ð·ÑƒÐ°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ð¸ данных [GIProbe] и отладки любых "
+"проблем, которые могут возникнуть.\n"
+"[b]Примечание:[/b] [method bake] работает как в редакторе, так и в "
+"ÑкÑпортированных проектах. Это делает его подходÑщим Ð´Ð»Ñ Ð¿Ñ€Ð¾Ñ†ÐµÐ´ÑƒÑ€Ð½Ð¾ "
+"генерируемых или пользовательÑких уровней. Запекание [GIProbe] обычно "
+"занимает от 5 до 20 Ñекунд в большинÑтве Ñцен. Уменьшение [member subdiv] "
+"может уÑкорить запекание.\n"
+"[b]Примечание:[/b] [GeometryInstance]Ñ‹ и [Light]Ñ‹ должны быть полноÑтью "
+"готовы до вызова [метода bake]. ЕÑли вы Ñоздаете их процедурно и некоторые "
+"Ñетки или оÑвещение отÑутÑтвуют в вашем запекаемом [GIProbe], иÑпользуйте "
+"[code]call_deferred(\"bake\")[/code] вмеÑто прÑмого вызова [метода bake]."
#: doc/classes/GIProbe.xml
msgid "Calls [method bake] with [code]create_visual_debug[/code] enabled."
@@ -28180,7 +28631,7 @@ msgstr ""
#: doc/classes/GradientTexture.xml
msgid "Gradient-filled texture."
-msgstr ""
+msgstr "ТекÑтура Ñ Ð³Ñ€Ð°Ð´Ð¸ÐµÐ½Ñ‚Ð½Ñ‹Ð¼ заполнением."
#: doc/classes/GradientTexture.xml
msgid ""
@@ -28944,6 +29395,21 @@ msgid ""
"light not affect the first layer, the whole GridMap won't be lit by the "
"light in question."
msgstr ""
+"GridMap позволÑет размещать Ñетки на Ñетке в интерактивном режиме. Она "
+"работает как из редактора, так и из Ñкриптов, что может помочь вам Ñоздать "
+"внутриигровые редакторы уровней.\n"
+"GridMap иÑпользует [MeshLibrary], ÐºÐ¾Ñ‚Ð¾Ñ€Ð°Ñ Ñодержит ÑпиÑок плиток. ÐšÐ°Ð¶Ð´Ð°Ñ "
+"плитка - Ñто Ñетка Ñ Ð¼Ð°Ñ‚ÐµÑ€Ð¸Ð°Ð»Ð°Ð¼Ð¸ и дополнительными фигурами Ñтолкновений и "
+"навигации.\n"
+"GridMap Ñодержит коллекцию Ñчеек. ÐšÐ°Ð¶Ð´Ð°Ñ Ñчейка Ñетки ÑÑылаетÑÑ Ð½Ð° тайл в "
+"[MeshLibrary]. Ð’Ñе Ñчейки в карте имеют одинаковые размеры.\n"
+"Внутри карта GridMap разбиваетÑÑ Ð½Ð° разреженную коллекцию октантов Ð´Ð»Ñ "
+"Ñффективного рендеринга и обработки физики. Каждый октант имеет одинаковые "
+"размеры и может Ñодержать неÑколько Ñчеек.\n"
+"[b]Примечание:[/b] GridMap не раÑширÑет [VisualInstance] и поÑтому не может "
+"быть Ñкрыт или замаÑкирован на оÑнове [member VisualInstance.layers]. ЕÑли "
+"Ñделать так, чтобы Ñвет не влиÑл на первый Ñлой, то вÑÑ GridMap не будет "
+"оÑвещена данным Ñветом."
#: modules/gridmap/doc_classes/GridMap.xml
msgid "Using gridmaps"
@@ -29168,6 +29634,33 @@ msgid ""
" printt(res.hex_encode(), Array(res))\n"
"[/codeblock]"
msgstr ""
+"КлаÑÑ HashingContext предоÑтавлÑет Ð¸Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñ Ð´Ð»Ñ Ð²Ñ‹Ñ‡Ð¸ÑÐ»ÐµÐ½Ð¸Ñ "
+"криптографичеÑких Ñ…Ñшей за неÑколько итераций. Это полезно, например, при "
+"вычиÑлении Ñ…Ñшей больших файлов (чтобы не загружать их вÑе в памÑть), "
+"Ñетевых потоков и потоков данных в целом (чтобы не держать буферы).\n"
+"ПеречиÑление [enum HashType] показывает поддерживаемые алгоритмы "
+"Ñ…ÑшированиÑ.\n"
+"[codeblock]\n"
+"const CHUNK_SIZE = 1024\n"
+"\n"
+"func hash_file(path):\n"
+" var ctx = HashingContext.new()\n"
+" var file = File.new()\n"
+" # ЗапуÑтите контекÑÑ‚ SHA-256.\n"
+" ctx.start(HashingContext.HASH_SHA256)\n"
+" # Проверьте, ÑущеÑтвует ли файл.\n"
+" if not file.file_exists(path):\n"
+" return\n"
+" # Открываем файл Ð´Ð»Ñ Ñ…ÑшированиÑ.\n"
+" file.open(path, File.READ)\n"
+" # ОбновлÑем контекÑÑ‚ поÑле Ñ‡Ñ‚ÐµÐ½Ð¸Ñ ÐºÐ°Ð¶Ð´Ð¾Ð³Ð¾ чанка.\n"
+" while not file.eof_reached():\n"
+" ctx.update(file.get_buffer(CHUNK_SIZE))\n"
+" # Получение вычиÑленного Ñ…Ñша.\n"
+" var res = ctx.finish()\n"
+" # Выведите результат в виде шеÑтнадцатеричной Ñтроки и маÑÑива.\n"
+" printt(res.hex_encode(), Array(res))\n"
+"[/codeblock]."
#: doc/classes/HashingContext.xml
msgid "Closes the current context, and return the computed hash."
@@ -29453,7 +29946,7 @@ msgstr ""
#: doc/classes/HSeparator.xml
msgid "Horizontal separator."
-msgstr ""
+msgstr "Горизонтальный разделитель."
#: doc/classes/HSeparator.xml
msgid ""
@@ -29473,7 +29966,7 @@ msgstr ""
#: doc/classes/HSlider.xml
msgid "Horizontal slider."
-msgstr ""
+msgstr "Горизонтальный Ñлайдер."
#: doc/classes/HSlider.xml
msgid ""
@@ -30405,6 +30898,22 @@ msgid ""
"url] for more details). As a workaround, you can send data as a query string "
"in the URL. See [method String.http_escape] for an example."
msgstr ""
+"Создает Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° базовом [HTTPClient]. ЕÑли нет ошибок конфигурации, "
+"пытаетÑÑ Ð¿Ð¾Ð´ÐºÐ»ÑŽÑ‡Ð¸Ñ‚ÑŒÑÑ, иÑÐ¿Ð¾Ð»ÑŒÐ·ÑƒÑ [метод HTTPClient.connect_to_host] и "
+"передает параметры в [метод HTTPClient.request].\n"
+"Возвращает [constant OK], еÑли Ð·Ð°Ð¿Ñ€Ð¾Ñ ÑƒÑпешно Ñоздан. (Это не означает, что "
+"Ñервер ответил), [конÑтанта ERR_UNCONFIGURED], еÑли не находитÑÑ Ð² дереве, "
+"[конÑтанта ERR_BUSY], еÑли вÑе еще обрабатывает предыдущий запроÑ, "
+"[конÑтанта ERR_INVALID_PARAMETER], еÑли Ð·Ð°Ð´Ð°Ð½Ð½Ð°Ñ Ñтрока не ÑвлÑетÑÑ "
+"правильным форматом URL, или [конÑтанта ERR_CANT_CONNECT], еÑли не "
+"иÑпользуетÑÑ Ð¿Ð¾Ñ‚Ð¾Ðº и [HTTPClient] не может ÑоединитьÑÑ Ñ Ñ…Ð¾Ñтом.\n"
+"[b]Примечание:[/b] ЕÑли [code]метод[/code] ÑвлÑетÑÑ [constant HTTPClient."
+"METHOD_GET], Ð¿Ð¾Ð»ÐµÐ·Ð½Ð°Ñ Ð½Ð°Ð³Ñ€ÑƒÐ·ÐºÐ°, Ð¾Ñ‚Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ð°Ñ Ñ‡ÐµÑ€ÐµÐ· [code]request_data[/"
+"code], может быть проигнорирована Ñервером или даже привеÑти к отклонению "
+"запроÑа (подробнее Ñм. [url=https://datatracker.ietf.org/doc/html/"
+"rfc7231#section-4.3.1]RFC 7231 раздел 4.3.1[/url]). Ð’ качеÑтве обходного "
+"пути вы можете отправить данные в виде Ñтроки запроÑа в URL. Пример Ñм. в "
+"[method String.http_escape]."
#: doc/classes/HTTPRequest.xml
msgid ""
@@ -30520,7 +31029,7 @@ msgstr ""
#: doc/classes/Image.xml
msgid "Image datatype."
-msgstr ""
+msgstr "Тип данных изображениÑ."
#: doc/classes/Image.xml
msgid ""
@@ -31888,6 +32397,19 @@ msgid ""
"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"
+"Ðакопление ввода можно отключить, чтобы получить немного более точный/"
+"реактивный ввод ценой ÑƒÐ²ÐµÐ»Ð¸Ñ‡ÐµÐ½Ð¸Ñ Ð·Ð°Ð³Ñ€ÑƒÐ·ÐºÐ¸ процеÑÑора. Ð’ приложениÑÑ…, где "
+"требуетÑÑ Ñ€Ð¸Ñовать линии от руки, накопление ввода обычно отключаетÑÑ Ð½Ð° "
+"Ð²Ñ€ÐµÐ¼Ñ Ñ€Ð¸ÑÐ¾Ð²Ð°Ð½Ð¸Ñ Ð»Ð¸Ð½Ð¸Ð¸ пользователем, чтобы получить результаты, точно "
+"ÑоответÑтвующие реальному вводу.\n"
+"[b]Примечание:[/b] Ðакопление ввода [i]включено[/i] по умолчанию. "
+"РекомендуетÑÑ Ð´ÐµÑ€Ð¶Ð°Ñ‚ÑŒ его включенным в играх, которые не требуют очень "
+"реактивного ввода, так как Ñто Ñнизит нагрузку на процеÑÑор."
#: doc/classes/Input.xml
msgid "Emitted when a joypad device has been connected or disconnected."
@@ -32023,7 +32545,7 @@ msgstr ""
#: doc/classes/InputEvent.xml
msgid "InputEvent"
-msgstr ""
+msgstr "InputEvent"
#: doc/classes/InputEvent.xml
msgid ""
@@ -32764,6 +33286,25 @@ msgid ""
"print(max_int) # -9223372036854775808, we overflowed and wrapped around.\n"
"[/codeblock]"
msgstr ""
+"Знаковый 64-битный целочиÑленный тип.\n"
+"Он может принимать Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð² интервале [code][-2^63, 2^63 - 1][/code], Ñ‚.е. "
+"[code][-9223372036854775808, 9223372036854775807][/code]. Превышение Ñтих "
+"границ будет обернуто.\n"
+"[int] ÑвлÑетÑÑ Ñ‚Ð¸Ð¿Ð¾Ð¼ [Variant], и поÑтому будет иÑпользоватьÑÑ Ð¿Ñ€Ð¸ "
+"приÑвоении целочиÑленного Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ [Variant]. Он также может быть применен Ñ "
+"помощью подÑказки типа [code]: int[/code].\n"
+"[codeblock].\n"
+"var my_variant = 0 # int, значение 0.\n"
+"my_variant += 4.2 # float, значение 4.2.\n"
+"var my_int: int = 1 # int, значение 1.\n"
+"my_int = 4.2 # int, значение 4, правое значение неÑвно приводитÑÑ Ðº int.\n"
+"my_int = int(\"6.7\") # int, значение 6, Ñтрока Ñвно приводитÑÑ Ðº int.\n"
+"\n"
+"var max_int = 9223372036854775807\n"
+"print(max_int) # 9223372036854775807, OK.\n"
+"max_int += 1\n"
+"print(max_int) # -9223372036854775808, мы переполнилиÑÑŒ и обернулиÑÑŒ.\n"
+"[/codeblock]"
#: doc/classes/int.xml
msgid ""
@@ -33525,6 +34066,41 @@ msgid ""
"[/codeblock]\n"
"[b]Note:[/b] Only available in the HTML5 platform."
msgstr ""
+"JavaScriptObject иÑпользуетÑÑ Ð´Ð»Ñ Ð²Ð·Ð°Ð¸Ð¼Ð¾Ð´ÐµÐ¹ÑÑ‚Ð²Ð¸Ñ Ñ Ð¾Ð±ÑŠÐµÐºÑ‚Ð°Ð¼Ð¸ JavaScript, "
+"полученными или Ñозданными Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ [метода JavaScript.get_interface], "
+"[метода JavaScript.create_object] или [метода JavaScript.create_callback].\n"
+"Пример:\n"
+"[codeblock]\n"
+"раÑширÑет Node\n"
+"\n"
+"var _my_js_callback = JavaScript.create_callback(self, \"myCallback\") # Эта "
+"ÑÑылка должна быть Ñохранена\n"
+"var console = JavaScript.get_interface(\"console\")\n"
+"\n"
+"func _init():\n"
+" var buf = JavaScript.create_object(\"ArrayBuffer\", 10) # новый "
+"ArrayBuffer(10)\n"
+" print(buf) # печатает [JavaScriptObject:OBJECT_ID]\n"
+" var uint8arr = JavaScript.create_object(\"Uint8Array\", buf) # новый "
+"Uint8Array(buf)\n"
+" uint8arr[1] = 255\n"
+" prints(uint8arr[1], uint8arr.byteLength) # печатает 255 10\n"
+" console.log(uint8arr) # печатает в конÑоли браузера \"Uint8Array(10) "
+"[ 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\"\n"
+"\n"
+" # Эквивалент JavaScript: Array.from(uint8arr).forEach(myCallback)\n"
+" JavaScript.get_interface(\"Array\").from(uint8arr)."
+"forEach(_my_js_callback)\n"
+"\n"
+"func myCallback(args):\n"
+" # Будет вызван Ñ Ð¿Ð°Ñ€Ð°Ð¼ÐµÑ‚Ñ€Ð°Ð¼Ð¸, переданными в обратный вызов \"forEach\".\n"
+" # [0, 0, [JavaScriptObject:1173]]\n"
+" # [255, 1, [JavaScriptObject:1173]]\n"
+" # ...\n"
+" # [0, 9, [JavaScriptObject:1180]]\n"
+" print(args)\n"
+"[/codeblock].\n"
+"[b]Примечание:[/b] ДоÑтупно только в платформе HTML5."
#: doc/classes/JNISingleton.xml
msgid ""
@@ -33714,7 +34290,6 @@ msgid ""
msgstr ""
#: doc/classes/JSONParseResult.xml
-#, fuzzy
msgid ""
"A [Variant] containing the parsed JSON. Use [method @GDScript.typeof] or the "
"[code]is[/code] keyword to check if it is what you expect. For example, if "
@@ -33736,25 +34311,25 @@ msgid ""
" push_error(\"Unexpected results.\")\n"
"[/codeblock]"
msgstr ""
-"ÐŸÐµÑ€ÐµÐ¼ÐµÐ½Ð½Ð°Ñ ([Variant]), ÑÐ¾Ð´ÐµÑ€Ð¶Ð°Ñ‰Ð°Ñ Ñ€Ð°Ð·Ð¾Ð±Ñ€Ð°Ð½Ð½Ñ‹Ð¹ JSON. ИÑпользуйте [method "
-"@GDScript.typeof] или ключевое Ñлово [code]is[/code] чтобы проверить "
-"ожидаемый тип. Ðапример, еÑли иÑходный JSON начинаетÑÑ Ñ Ñ„Ð¸Ð³ÑƒÑ€Ð½Ñ‹Ñ… Ñкобок "
-"([code]{}[/code]), будет возвращён Ñловарь ([Dictionary]). ЕÑли иÑходный "
-"JSON начинаетÑÑ Ñ ÐºÐ²Ð°Ð´Ñ€Ð°Ñ‚Ð½Ñ‹Ñ… Ñкобок ([code][][/code]), будет возвращён "
-"маÑÑив ([Array]).\n"
-"[b]Примечание:[/b] Ð¡Ð¿ÐµÑ†Ð¸Ñ„Ð¸ÐºÐ°Ñ†Ð¸Ñ JSON не определÑет типы integer и float, "
-"только тип[i]number[/i]. Таким образом, при разборе Ñтроки JSON вÑе чиÑловые "
-"Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð±ÑƒÐ´ÑƒÑ‚ преобразованы в тип [float].\n"
-"[b]Примечание:[/b] JSON-объекты не ÑохранÑÑŽÑ‚ порÑдок ключей как Ñловари "
-"Godot, поÑтому вы не должны полагатьÑÑ Ð½Ð° порÑдок ÑÐ»ÐµÐ´Ð¾Ð²Ð°Ð½Ð¸Ñ ÐºÐ»ÑŽÑ‡ÐµÐ¹, еÑли "
-"Ñловарь получен из JSON. МаÑÑивы JSON, напротив, ÑохранÑÑŽÑ‚ порÑдок Ñвоих "
-"Ñлементов:\n"
-"[codeblock]\n"
+"Вариант [Variant], Ñодержащий разобранный JSON. ИÑпользуйте [method "
+"@GDScript.typeof] или ключевое Ñлово [code]is[/code], чтобы проверить, "
+"ÑвлÑетÑÑ Ð»Ð¸ Ñто тем, что вы ожидаете. Ðапример, еÑли иÑточник JSON "
+"начинаетÑÑ Ñ Ñ„Ð¸Ð³ÑƒÑ€Ð½Ñ‹Ñ… Ñкобок ([code]{}[/code]), будет возвращен [Словарь]. "
+"ЕÑли иÑточник JSON начинаетÑÑ Ñо Ñкобок ([code][][/code]), будет возвращен "
+"[МаÑÑив].\n"
+"[b]Примечание:[/b] Ð’ Ñпецификации JSON не определены типы integer или float, "
+"а только тип [i]number[/i]. ПоÑтому при разборе текÑта JSON вÑе чиÑловые "
+"Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð±ÑƒÐ´ÑƒÑ‚ преобразованы в типы [float].\n"
+"[b]Примечание:[/b] Объекты JSON не ÑохранÑÑŽÑ‚ порÑдок ключей, как Ñловари "
+"Godot, поÑтому не Ñледует полагатьÑÑ Ð½Ð° то, что ключи будут раÑположены в "
+"определенном порÑдке, еÑли Ñловарь поÑтроен из JSON. Ðапротив, маÑÑивы JSON "
+"ÑохранÑÑŽÑ‚ порÑдок Ñвоих Ñлементов:\n"
+"[codeblock].\n"
"var p = JSON.parse('[\"hello\", \"world\", \"!\"]')\n"
"if typeof(p.result) == TYPE_ARRAY:\n"
-" print(p.result[0]) # Выведет \"hello\"\n"
+" print(p.result[0]) # Печатает \"hello\".\n"
"else:\n"
-" push_error(\"Ðеожиданный результат.\")\n"
+" push_error(\"Ðеожиданные результаты.\")\n"
"[/codeblock]"
#: doc/classes/JSONRPC.xml
@@ -33849,6 +34424,21 @@ msgid ""
"while performing collision tests. This makes them really useful to implement "
"characters that collide against a world, but don't require advanced physics."
msgstr ""
+"КинематичеÑкие тела - Ñто оÑобые типы тел, которые предназначены Ð´Ð»Ñ "
+"ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»ÐµÐ¼. Ðа них вообще не влиÑет физика; Ð´Ð»Ñ Ð´Ñ€ÑƒÐ³Ð¸Ñ… типов "
+"тел, таких как перÑонаж или жеÑткое тело, Ñто то же Ñамое, что и ÑтатичеÑкое "
+"тело. Однако у них еÑть два оÑновных применениÑ:\n"
+"[b]Ð˜Ð¼Ð¸Ñ‚Ð°Ñ†Ð¸Ñ Ð´Ð²Ð¸Ð¶ÐµÐ½Ð¸Ñ:[/b] Когда Ñти тела перемещаютÑÑ Ð²Ñ€ÑƒÑ‡Ð½ÑƒÑŽ, либо из кода, "
+"либо из [AnimationPlayer] (Ñ [member AnimationPlayer.playback_process_mode], "
+"уÑтановленным на \"physics\"), физика автоматичеÑки вычиÑлÑет оценку их "
+"линейной и угловой ÑкороÑти. Это делает их очень полезными Ð´Ð»Ñ Ð´Ð²Ð¸Ð¶ÑƒÑ‰Ð¸Ñ…ÑÑ "
+"платформ или других объектов, управлÑемых AnimationPlayer (например, дверь, "
+"открывающийÑÑ Ð¼Ð¾ÑÑ‚ и Ñ‚.д.).\n"
+"[b]КинематичеÑкие перÑонажи:[/b] KinematicBody также имеет API Ð´Ð»Ñ "
+"Ð¿ÐµÑ€ÐµÐ¼ÐµÑ‰ÐµÐ½Ð¸Ñ Ð¾Ð±ÑŠÐµÐºÑ‚Ð¾Ð² (методы [method move_and_collide] и [method "
+"move_and_slide]) при выполнении теÑтов на ÑтолкновениÑ. Это делает их "
+"дейÑтвительно полезными Ð´Ð»Ñ Ñ€ÐµÐ°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ð¸ перÑонажей, которые ÑталкиваютÑÑ Ñ "
+"миром, но не требуют продвинутой физики."
#: doc/classes/KinematicBody.xml doc/classes/KinematicBody2D.xml
msgid "Kinematic character (2D)"
@@ -34102,6 +34692,21 @@ msgid ""
"while performing collision tests. This makes them really useful to implement "
"characters that collide against a world, but don't require advanced physics."
msgstr ""
+"КинематичеÑкие тела - Ñто оÑобые типы тел, которые предназначены Ð´Ð»Ñ "
+"ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»ÐµÐ¼. Ðа них вообще не влиÑет физика; Ð´Ð»Ñ Ð´Ñ€ÑƒÐ³Ð¸Ñ… типов "
+"тел, таких как перÑонаж или жеÑткое тело, Ñто то же Ñамое, что и ÑтатичеÑкое "
+"тело. Однако у них еÑть два оÑновных применениÑ:\n"
+"[b]Ð˜Ð¼Ð¸Ñ‚Ð°Ñ†Ð¸Ñ Ð´Ð²Ð¸Ð¶ÐµÐ½Ð¸Ñ:[/b] Когда Ñти тела перемещаютÑÑ Ð²Ñ€ÑƒÑ‡Ð½ÑƒÑŽ, либо из кода, "
+"либо из [AnimationPlayer] (Ñ [member AnimationPlayer.playback_process_mode], "
+"уÑтановленным на \"physics\"), физика автоматичеÑки вычиÑлÑет оценку их "
+"линейной и угловой ÑкороÑти. Это делает их очень полезными Ð´Ð»Ñ Ð´Ð²Ð¸Ð¶ÑƒÑ‰Ð¸Ñ…ÑÑ "
+"платформ или других объектов, управлÑемых AnimationPlayer (например, дверь, "
+"открывающийÑÑ Ð¼Ð¾ÑÑ‚ и Ñ‚.д.).\n"
+"[b]КинематичеÑкие перÑонажи:[/b] KinematicBody2D также имеет API Ð´Ð»Ñ "
+"Ð¿ÐµÑ€ÐµÐ¼ÐµÑ‰ÐµÐ½Ð¸Ñ Ð¾Ð±ÑŠÐµÐºÑ‚Ð¾Ð² (методы [method move_and_collide] и [method "
+"move_and_slide]) при выполнении теÑтов на ÑтолкновениÑ. Это делает их "
+"дейÑтвительно полезными Ð´Ð»Ñ Ñ€ÐµÐ°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ð¸ перÑонажей, которые ÑталкиваютÑÑ Ñ "
+"миром, но не требуют продвинутой физики."
#: doc/classes/KinematicBody2D.xml
msgid "Using KinematicBody2D"
@@ -34791,7 +35396,9 @@ msgid ""
"The size of the light in Godot units. Only considered in baked lightmaps and "
"only if [member light_bake_mode] is set to [constant BAKE_ALL]. Increasing "
"this value will make the shadows appear blurrier. This can be used to "
-"simulate area lights to an extent."
+"simulate area lights to an extent.\n"
+"[b]Note:[/b] [member light_size] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/Light.xml
@@ -38120,6 +38727,7 @@ msgid "3D agent used in navigation for collision avoidance."
msgstr ""
#: doc/classes/NavigationAgent.xml
+#, fuzzy
msgid ""
"3D agent that is used in navigation to reach a location while avoiding "
"static and dynamic obstacles. The dynamic obstacles are avoided using RVO "
@@ -38133,8 +38741,26 @@ msgid ""
"use the [method get_next_location] function once every physics frame to "
"update the internal path logic of the NavigationAgent. The returned vector "
"position from this function should be used as the next movement position for "
-"the agent's parent Node."
-msgstr ""
+"the agent's parent Node.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues."
+msgstr ""
+"3D-агент, который иÑпользуетÑÑ Ð² навигации Ð´Ð»Ñ Ð´Ð¾ÑÑ‚Ð¸Ð¶ÐµÐ½Ð¸Ñ Ð¼ÐµÑтоположениÑ, "
+"Ð¸Ð·Ð±ÐµÐ³Ð°Ñ Ð¿Ñ€Ð¸ Ñтом ÑтатичеÑких и динамичеÑких препÑÑ‚Ñтвий. ДинамичеÑкие "
+"препÑÑ‚ÑÑ‚Ð²Ð¸Ñ Ð¸Ð·Ð±ÐµÐ³Ð°ÑŽÑ‚ÑÑ Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ ÑиÑтемы Ð¿Ñ€ÐµÐ´Ð¾Ñ‚Ð²Ñ€Ð°Ñ‰ÐµÐ½Ð¸Ñ Ñтолкновений RVO "
+"(Reciprocal Velocity Obstacles). Ð”Ð»Ñ ÐºÐ¾Ñ€Ñ€ÐµÐºÑ‚Ð½Ð¾Ð¹ работы агенту необходимы "
+"навигационные данные. По умолчанию Ñтот узел региÑтрируетÑÑ Ð½Ð° навигационной "
+"карте по умолчанию [Мир]. ЕÑли Ñтот узел ÑвлÑетÑÑ Ð´Ð¾Ñ‡ÐµÑ€Ð½Ð¸Ð¼ узлом "
+"[Navigation], он будет региÑтрироватьÑÑ Ð½Ð° навигационной карте "
+"навигационного узла, или можно иÑпользовать функцию [method set_navigation], "
+"чтобы уÑтановить навигационный узел напрÑмую. [NavigationAgent] ÑвлÑетÑÑ "
+"физичеÑки безопаÑным.\n"
+"[b]Примечание:[/b] ПоÑле иÑÐ¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ [method set_target_location] "
+"необходимо иÑпользовать функцию [method get_next_location] раз в каждый кадр "
+"физики Ð´Ð»Ñ Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ð²Ð½ÑƒÑ‚Ñ€ÐµÐ½Ð½ÐµÐ¹ логики пути NavigationAgent. Ð’Ð¾Ð·Ð²Ñ€Ð°Ñ‰Ð°ÐµÐ¼Ð°Ñ "
+"Ð²ÐµÐºÑ‚Ð¾Ñ€Ð½Ð°Ñ Ð¿Ð¾Ð·Ð¸Ñ†Ð¸Ñ Ð¸Ð· Ñтой функции должна иÑпользоватьÑÑ Ð² качеÑтве Ñледующей "
+"позиции Ð´Ð²Ð¸Ð¶ÐµÐ½Ð¸Ñ Ð´Ð»Ñ Ñ€Ð¾Ð´Ð¸Ñ‚ÐµÐ»ÑŒÑкого узла агента."
#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
msgid ""
@@ -38373,6 +38999,7 @@ msgid "2D agent used in navigation for collision avoidance."
msgstr ""
#: doc/classes/NavigationAgent2D.xml
+#, fuzzy
msgid ""
"2D agent that is used in navigation to reach a location while avoiding "
"static and dynamic obstacles. The dynamic obstacles are avoided using RVO "
@@ -38386,8 +39013,26 @@ msgid ""
"use the [method get_next_location] function once every physics frame to "
"update the internal path logic of the NavigationAgent. The returned vector "
"position from this function should be used as the next movement position for "
-"the agent's parent Node."
-msgstr ""
+"the agent's parent Node.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues."
+msgstr ""
+"2D агент, который иÑпользуетÑÑ Ð² навигации Ð´Ð»Ñ Ð´Ð¾ÑÑ‚Ð¸Ð¶ÐµÐ½Ð¸Ñ Ð¼ÐµÑтоположениÑ, "
+"Ð¸Ð·Ð±ÐµÐ³Ð°Ñ Ð¿Ñ€Ð¸ Ñтом ÑтатичеÑких и динамичеÑких препÑÑ‚Ñтвий. ДинамичеÑкие "
+"препÑÑ‚ÑÑ‚Ð²Ð¸Ñ Ð¸Ð·Ð±ÐµÐ³Ð°ÑŽÑ‚ÑÑ Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ ÑиÑтемы Ð¿Ñ€ÐµÐ´Ð¾Ñ‚Ð²Ñ€Ð°Ñ‰ÐµÐ½Ð¸Ñ Ñтолкновений RVO "
+"(Reciprocal Velocity Obstacles). Ð”Ð»Ñ ÐºÐ¾Ñ€Ñ€ÐµÐºÑ‚Ð½Ð¾Ð¹ работы агенту необходимы "
+"навигационные данные. По умолчанию Ñтот узел региÑтрируетÑÑ Ð½Ð° навигационной "
+"карте по умолчанию [World2D]. ЕÑли Ñтот узел ÑвлÑетÑÑ Ð´Ð¾Ñ‡ÐµÑ€Ð½Ð¸Ð¼ Ð´Ð»Ñ ÑƒÐ·Ð»Ð° "
+"[Navigation2D], он будет региÑтрироватьÑÑ Ð½Ð° навигационной карте "
+"навигационного узла, или Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ [method set_navigation] может быть "
+"иÑпользована Ð´Ð»Ñ Ð½ÐµÐ¿Ð¾ÑредÑтвенной уÑтановки навигационного узла. "
+"[NavigationAgent2D] ÑвлÑетÑÑ Ñ„Ð¸Ð·Ð¸Ñ‡ÐµÑки безопаÑным.\n"
+"[b]Примечание:[/b] ПоÑле иÑÐ¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ [method set_target_location] "
+"необходимо иÑпользовать функцию [method get_next_location] один раз в каждый "
+"кадр физики Ð´Ð»Ñ Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ð²Ð½ÑƒÑ‚Ñ€ÐµÐ½Ð½ÐµÐ¹ логики пути NavigationAgent. "
+"Ð’Ð¾Ð·Ð²Ñ€Ð°Ñ‰Ð°ÐµÐ¼Ð°Ñ Ð²ÐµÐºÑ‚Ð¾Ñ€Ð½Ð°Ñ Ð¿Ð¾Ð·Ð¸Ñ†Ð¸Ñ Ð¸Ð· Ñтой функции должна иÑпользоватьÑÑ Ð² "
+"качеÑтве Ñледующей позиции Ð´Ð²Ð¸Ð¶ÐµÐ½Ð¸Ñ Ð´Ð»Ñ Ñ€Ð¾Ð´Ð¸Ñ‚ÐµÐ»ÑŒÑкого узла агента."
#: doc/classes/NavigationAgent2D.xml
#, fuzzy
@@ -39113,6 +39758,9 @@ msgid ""
"modified velocity as-is might lead to pushing and agent outside of a "
"navigable area. This is a limitation of the collision avoidance system, any "
"more complex situation may require the use of the physics engine.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues.\n"
"This server keeps tracks of any call and executes them during the sync "
"phase. This means that you can request any change to the map, using any "
"thread, without worrying."
@@ -39478,6 +40126,21 @@ msgid ""
"COMPRESS_NONE]. Nonetheless, mixing engine versions between clients and "
"server is not recommended and not officially supported."
msgstr ""
+"Метод ÑжатиÑ, иÑпользуемый Ð´Ð»Ñ Ñетевых пакетов. Они имеют различные "
+"компромиÑÑÑ‹ между ÑкороÑтью ÑÐ¶Ð°Ñ‚Ð¸Ñ Ð¸ пропуÑкной ÑпоÑобноÑтью, вам может "
+"потребоватьÑÑ Ð¿Ñ€Ð¾Ð²ÐµÑ€Ð¸Ñ‚ÑŒ, какой из них лучше вÑего подходит Ð´Ð»Ñ Ð²Ð°ÑˆÐµÐ³Ð¾ "
+"ÑлучаÑ, еÑли вы вообще иÑпользуете Ñжатие.\n"
+"[b]Примечание:[/b] Сетевой дизайн большинÑтва игр предполагает чаÑтую "
+"отправку множеÑтва небольших пакетов (размером менее 4 КБ каждый). ЕÑли еÑть "
+"ÑомнениÑ, рекомендуетÑÑ Ð¾Ñтавить алгоритм ÑÐ¶Ð°Ñ‚Ð¸Ñ Ð¿Ð¾ умолчанию, так как он "
+"лучше вÑего работает Ñ Ñ‚Ð°ÐºÐ¸Ð¼Ð¸ маленькими пакетами.\n"
+"[b]Примечание:[/b] [member compression_mode] должен быть уÑтановлен на одно "
+"и то же значение как на Ñервере, так и на вÑех его клиентах. Клиенты не "
+"Ñмогут подключитьÑÑ, еÑли значение [member compression_mode], уÑтановленное "
+"на клиенте, отличаетÑÑ Ð¾Ñ‚ уÑтановленного на Ñервере. До Godot 3.4 по "
+"умолчанию [member compression_mode] был [constant COMPRESS_NONE]. Тем не "
+"менее, Ñмешивать верÑии движка между клиентами и Ñервером не рекомендуетÑÑ Ð¸ "
+"официально не поддерживаетÑÑ."
#: modules/enet/doc_classes/NetworkedMultiplayerENet.xml
msgid ""
@@ -39556,7 +40219,7 @@ msgstr ""
#: modules/enet/doc_classes/NetworkedMultiplayerENet.xml
msgid "[url=https://facebook.github.io/zstd/]Zstandard[/url] compression."
-msgstr ""
+msgstr "[url=https://facebook.github.io/zstd/]Zstandard[/url] cжатие."
#: doc/classes/NetworkedMultiplayerPeer.xml
msgid "A high-level network interface to simplify multiplayer interactions."
@@ -39966,6 +40629,20 @@ msgid ""
"call with [method request_ready], which may be called anywhere before adding "
"the node again."
msgstr ""
+"ВызываетÑÑ, когда узел \"готов\", Ñ‚.е. когда и узел, и его дочерние Ñлементы "
+"вошли в дерево Ñцены. ЕÑли узел имеет дочерние узлы, то Ñначала Ñрабатывают "
+"их обратные вызовы [метода _ready], а затем родительÑкий узел получает "
+"уведомление о готовноÑти.\n"
+"СоответÑтвует уведомлению [constant NOTIFICATION_READY] в [method Object."
+"_notification]. См. также ключевое Ñлово [code]onready[/code] Ð´Ð»Ñ "
+"переменных.\n"
+"Обычно иÑпользуетÑÑ Ð´Ð»Ñ Ð¸Ð½Ð¸Ñ†Ð¸Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ð¸. Ð”Ð»Ñ ÐµÑ‰Ðµ более ранней инициализации "
+"можно иÑпользовать [метод Object._init]. См. также [метод _enter_tree].\n"
+"[b]Примечание:[/b] [метод _ready] может быть вызван только один раз Ð´Ð»Ñ "
+"каждого узла. ПоÑле ÑƒÐ´Ð°Ð»ÐµÐ½Ð¸Ñ ÑƒÐ·Ð»Ð° из дерева Ñцены и Ð´Ð¾Ð±Ð°Ð²Ð»ÐµÐ½Ð¸Ñ ÐµÐ³Ð¾ Ñнова, "
+"[code]_ready[/code] не будет вызван второй раз. Это можно обойти, запроÑив "
+"повторный вызов Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ [метода request_ready], который может быть вызван "
+"в любом меÑте перед повторным добавлением узла."
#: doc/classes/Node.xml
msgid ""
@@ -40095,6 +40772,21 @@ msgid ""
"consider using [method get_node] instead. To avoid using [method find_node] "
"too often, consider caching the node reference into a variable."
msgstr ""
+"Ðаходит потомка Ñтого узла, Ð¸Ð¼Ñ ÐºÐ¾Ñ‚Ð¾Ñ€Ð¾Ð³Ð¾ ÑоответÑтвует [code]маÑке[/code] "
+"как в [методе String.match] (Ñ‚.е. чувÑтвительно к региÑтру, но [code]\"*\"[/"
+"code] ÑоответÑтвует нулю или более Ñимволов, а [code]\"?\"[/code] "
+"ÑоответÑтвует любому одиночному Ñимволу, кроме [code]\".\"[/code]). "
+"Возвращает [code]null[/code], еÑли не найдено ни одного подходÑщего [узла].\n"
+"[b]Примечание:[/b] Ðе ищет ÑÐ¾Ð²Ð¿Ð°Ð´ÐµÐ½Ð¸Ñ Ð¿Ð¾ полному пути, только по именам "
+"отдельных узлов.\n"
+"ЕÑли [code]owned[/code] is [code]true[/code], Ñтот метод находит только "
+"узлы, владельцем которых ÑвлÑетÑÑ Ñтот узел. Это оÑобенно важно Ð´Ð»Ñ Ñцен, "
+"Ñозданных через Ñценарий, поÑкольку у таких Ñцен нет владельца.\n"
+"[b]Примечание:[/b] ПоÑкольку Ñтот метод проходит по вÑем потомкам узла, Ñто "
+"Ñамый медленный ÑпоÑоб получить ÑÑылку на другой узел. По возможноÑти "
+"иÑпользуйте вмеÑто него [method get_node]. Чтобы не иÑпользовать [метод "
+"find_node] Ñлишком чаÑто, подумайте о кÑшировании ÑÑылки на узел в "
+"переменной."
#: doc/classes/Node.xml
msgid ""
@@ -40535,6 +41227,20 @@ msgid ""
"like [code]server_disconnected[/code] or by checking [code]SceneTree."
"network_peer.get_connection_status() == CONNECTION_CONNECTED[/code]."
msgstr ""
+"ОтправлÑет Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° вызов удаленной процедуры Ð´Ð»Ñ Ð·Ð°Ð´Ð°Ð½Ð½Ð¾Ð³Ð¾ [code]метода[/"
+"code] равным узлам в Ñети (и локально), по желанию отправлÑÑ Ð²Ñе "
+"дополнительные аргументы в качеÑтве аргументов метода, вызываемого RPC. "
+"Ð—Ð°Ð¿Ñ€Ð¾Ñ Ð²Ñ‹Ð·Ð¾Ð²Ð° будет получен только узлами Ñ Ð¾Ð´Ð¸Ð½Ð°ÐºÐ¾Ð²Ñ‹Ð¼ [NodePath], Ð²ÐºÐ»ÑŽÑ‡Ð°Ñ "
+"точно такое же Ð¸Ð¼Ñ ÑƒÐ·Ð»Ð°. Поведение завиÑит от конфигурации RPC Ð´Ð»Ñ Ð´Ð°Ð½Ð½Ð¾Ð³Ð¾ "
+"метода, Ñм. [method rpc_config]. По умолчанию методы не открыты Ð´Ð»Ñ RPC. См. "
+"также [method rset] и [method rset_config] Ð´Ð»Ñ ÑвойÑтв. Возвращает "
+"[code]null[/code].\n"
+"[b]Примечание:[/b] Ð’Ñ‹ можете безопаÑно иÑпользовать RPC на клиентах только "
+"поÑле Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ñигнала [code]connected_to_server[/code] от [SceneTree]. Вам "
+"также необходимо отÑлеживать ÑоÑтоÑние ÑоединениÑ, либо по Ñигналам "
+"[SceneTree], таким как [code]server_disconnected[/code], либо проверÑÑ "
+"[code]SceneTree.network_peer.get_connection_status() == "
+"CONNECTION_CONNECTED[/code]."
#: doc/classes/Node.xml
msgid ""
@@ -41079,7 +41785,7 @@ msgstr "Глобальный маÑштаб."
#: doc/classes/Node2D.xml
msgid "Global [Transform2D]."
-msgstr ""
+msgstr "Глобальный [Transform2D]."
#: doc/classes/Node2D.xml
msgid "Position, relative to the node's parent."
@@ -41105,7 +41811,7 @@ msgstr ""
#: doc/classes/Node2D.xml
msgid "Local [Transform2D]."
-msgstr ""
+msgstr "Локальный [Transform2D]."
#: doc/classes/Node2D.xml
msgid ""
@@ -42011,7 +42717,9 @@ msgid ""
"The light's radius. Note that the effectively lit area may appear to be "
"smaller depending on the [member omni_attenuation] in use. No matter the "
"[member omni_attenuation] in use, the light will never reach anything "
-"outside this radius."
+"outside this radius.\n"
+"[b]Note:[/b] [member omni_range] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -42427,6 +43135,21 @@ msgid ""
"the project if it is currently running (since the project is an independent "
"child process)."
msgstr ""
+"Задерживает выполнение текущего потока на [code]мÑек[/code] миллиÑекунд. "
+"[code]мÑек[/code] должно быть больше или равно [code]0[/code]. Ð’ противном "
+"Ñлучае [метод delay_msec] ничего не Ñделает и выведет Ñообщение об ошибке.\n"
+"[b]Примечание:[/b] [method delay_msec] - Ñто [i]блокирующий[/i] ÑпоÑоб "
+"задержки Ð²Ñ‹Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ ÐºÐ¾Ð´Ð°. Чтобы задержать выполнение кода неблокирующим "
+"ÑпоÑобом, Ñмотрите [method SceneTree.create_timer]. Выдача Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ [method "
+"SceneTree.create_timer] задержит выполнение кода, размещенного ниже "
+"[code]выдачи[/code] без влиÑÐ½Ð¸Ñ Ð½Ð° оÑтальную чаÑть проекта (или редактора, "
+"Ð´Ð»Ñ [EditorPlugin]ов и [EditorScript]ов).\n"
+"[b]Примечание:[/b] ЕÑли [метод delay_msec] вызываетÑÑ Ð² главном потоке, он "
+"замораживает проект и не позволÑет ему перериÑовывать и региÑтрировать ввод, "
+"пока не пройдет задержка. При иÑпользовании [method delay_msec] как чаÑти "
+"[EditorPlugin] или [EditorScript], он заморозит редактор, но не заморозит "
+"проект, еÑли он запущен (поÑкольку проект ÑвлÑетÑÑ Ð½ÐµÐ·Ð°Ð²Ð¸Ñимым дочерним "
+"процеÑÑом)."
#: doc/classes/OS.xml
msgid ""
@@ -42447,6 +43170,21 @@ msgid ""
"the project if it is currently running (since the project is an independent "
"child process)."
msgstr ""
+"Задерживает выполнение текущего потока на [code]usec[/code] микроÑекунд. "
+"[code]usec[/code] должно быть больше или равно [code]0[/code]. В противном "
+"Ñлучае [метод delay_usec] ничего не Ñделает и выведет Ñообщение об ошибке.\n"
+"[b]Примечание:[/b] [method delay_usec] - Ñто [i]блокирующий[/i] ÑпоÑоб "
+"задержки Ð²Ñ‹Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ ÐºÐ¾Ð´Ð°. Чтобы задержать выполнение кода неблокирующим "
+"ÑпоÑобом, Ñмотрите [method SceneTree.create_timer]. Выдача Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ [method "
+"SceneTree.create_timer] задержит выполнение кода, размещенного ниже "
+"[code]выдачи[/code] без влиÑÐ½Ð¸Ñ Ð½Ð° оÑтальную чаÑть проекта (или редактора, "
+"Ð´Ð»Ñ [EditorPlugin]ов и [EditorScript]ов).\n"
+"[b]Примечание:[/b] ЕÑли [метод delay_usec] вызываетÑÑ Ð² главном потоке, он "
+"замораживает проект и не позволÑет ему перериÑовывать и региÑтрировать ввод, "
+"пока не пройдет задержка. При иÑпользовании [method delay_usec] как чаÑти "
+"[EditorPlugin] или [EditorScript], он заморозит редактор, но не заморозит "
+"проект, еÑли он запущен (поÑкольку проект ÑвлÑетÑÑ Ð½ÐµÐ·Ð°Ð²Ð¸Ñимым дочерним "
+"процеÑÑом)."
#: doc/classes/OS.xml
msgid ""
@@ -42535,11 +43273,11 @@ msgstr "Возвращает вектор привÑзанный к Ñетке Ñ
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] cache data directory according to the operating "
-"system's standards. On desktop platforms, this path can be overridden by "
-"setting the [code]XDG_CACHE_HOME[/code] environment variable before starting "
-"the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in "
-"Godot projects[/url] in the documentation for more information. See also "
-"[method get_config_dir] and [method get_data_dir].\n"
+"system's standards. On Linux, this path can be overridden by setting the "
+"[code]XDG_CACHE_HOME[/code] environment variable before starting the "
+"project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot "
+"projects[/url] in the documentation for more information. See also [method "
+"get_config_dir] and [method get_data_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -42569,15 +43307,38 @@ msgid ""
" arguments[argument.lstrip(\"--\")] = \"\"\n"
"[/codeblock]"
msgstr ""
+"Возвращает аргументы командной Ñтроки, переданные движку.\n"
+"Ðргументы командной Ñтроки могут быть запиÑаны в любой форме, Ð²ÐºÐ»ÑŽÑ‡Ð°Ñ Ñ„Ð¾Ñ€Ð¼Ñ‹ "
+"[code]--key value[/code] и [code]--key=value[/code], чтобы они могли быть "
+"правильно разобраны, при уÑловии, что пользовательÑкие аргументы командной "
+"Ñтроки не конфликтуют Ñ Ð°Ñ€Ð³ÑƒÐ¼ÐµÐ½Ñ‚Ð°Ð¼Ð¸ движка.\n"
+"Ð’Ñ‹ также можете включить переменные окружениÑ, иÑÐ¿Ð¾Ð»ÑŒÐ·ÑƒÑ Ð¼ÐµÑ‚Ð¾Ð´ [method "
+"get_environment].\n"
+"Ð’Ñ‹ можете уÑтановить [member ProjectSettings.editor/main_run_args] Ð´Ð»Ñ "
+"Ð¾Ð¿Ñ€ÐµÐ´ÐµÐ»ÐµÐ½Ð¸Ñ Ð°Ñ€Ð³ÑƒÐ¼ÐµÐ½Ñ‚Ð¾Ð² командной Ñтроки, которые будут передаватьÑÑ "
+"редактором при запуÑке проекта.\n"
+"Вот минимальный пример того, как разобрать аргументы командной Ñтроки в "
+"Ñловарь, иÑÐ¿Ð¾Ð»ÑŒÐ·ÑƒÑ Ñ„Ð¾Ñ€Ð¼Ñƒ [code]--key=value[/code] Ð´Ð»Ñ Ð°Ñ€Ð³ÑƒÐ¼ÐµÐ½Ñ‚Ð¾Ð²:\n"
+"[codeblock].\n"
+"var arguments = {}\n"
+"for argument in OS.get_cmdline_args():\n"
+" 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
msgid ""
"Returns the [i]global[/i] user configuration directory according to the "
-"operating system's standards. On desktop platforms, this path can be "
-"overridden by setting the [code]XDG_CONFIG_HOME[/code] environment variable "
-"before starting the project. See [url=$DOCS_URL/tutorials/io/data_paths."
-"html]File paths in Godot projects[/url] in the documentation for more "
-"information. See also [method get_cache_dir] and [method get_data_dir].\n"
+"operating system's standards. On Linux, this path can be overridden by "
+"setting the [code]XDG_CONFIG_HOME[/code] environment variable before "
+"starting the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File "
+"paths in Godot projects[/url] in the documentation for more information. See "
+"also [method get_cache_dir] and [method get_data_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -42599,11 +43360,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] user data directory according to the operating "
-"system's standards. On desktop platforms, this path can be overridden by "
-"setting the [code]XDG_DATA_HOME[/code] environment variable before starting "
-"the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in "
-"Godot projects[/url] in the documentation for more information. See also "
-"[method get_cache_dir] and [method get_config_dir].\n"
+"system's standards. On Linux, this path can be overridden by setting the "
+"[code]XDG_DATA_HOME[/code] environment variable before starting the project. "
+"See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot "
+"projects[/url] in the documentation for more information. See also [method "
+"get_cache_dir] and [method get_config_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -43769,9 +44530,8 @@ msgid "Ringtones directory path."
msgstr ""
#: doc/classes/OS.xml
-#, fuzzy
msgid "Unknown powerstate."
-msgstr "ÐеизвеÑÑ‚Ð½Ð°Ñ ÐºÐ»Ð°Ð²Ð¸ÑˆÐ°."
+msgstr "ÐеизвеÑтное ÑоÑтоÑние питаниÑ."
#: doc/classes/OS.xml
msgid "Unplugged, running on battery."
@@ -44485,6 +45245,16 @@ msgid "Particle systems (2D)"
msgstr ""
#: doc/classes/Particles2D.xml
+msgid "2D Particles Demo"
+msgstr ""
+
+#: doc/classes/Particles2D.xml
+msgid ""
+"2D Dodge The Creeps Demo (uses GPUParticles2D for the trail behind the "
+"player)"
+msgstr ""
+
+#: doc/classes/Particles2D.xml
msgid "Returns a rectangle containing the positions of all existing particles."
msgstr ""
@@ -45200,7 +45970,7 @@ msgstr ""
#: doc/classes/PHashTranslation.xml
msgid "Optimized translation."
-msgstr ""
+msgstr "Оптимизированный перевод."
#: doc/classes/PHashTranslation.xml
msgid ""
@@ -45231,7 +46001,7 @@ msgstr ""
#: doc/classes/PhysicsDirectBodyState.xml
#: doc/classes/PhysicsDirectSpaceState.xml doc/classes/RayCast.xml
msgid "Ray-casting"
-msgstr ""
+msgstr "ТраÑÑировка лучей"
#: doc/classes/Physics2DDirectBodyState.xml doc/classes/RigidBody2D.xml
msgid "Adds a constant directional force without affecting rotation."
@@ -45448,6 +46218,23 @@ msgid ""
"[code]rid[/code]: The intersecting object's [RID].\n"
"[code]shape[/code]: The shape index of the colliding shape."
msgstr ""
+"ПроверÑет переÑÐµÑ‡ÐµÐ½Ð¸Ñ Ñ„Ð¸Ð³ÑƒÑ€Ñ‹, заданной через объект "
+"[Physics2DShapeQueryParameters], Ñ Ð¿Ñ€Ð¾ÑтранÑтвом. ЕÑли она переÑекаетÑÑ Ñ "
+"более чем одной фигурой, выбираетÑÑ Ð±Ð»Ð¸Ð¶Ð°Ð¹ÑˆÐ°Ñ. ЕÑли фигура ни Ñ Ñ‡ÐµÐ¼ не "
+"переÑекаетÑÑ, то возвращаетÑÑ Ð¿ÑƒÑтой Ñловарь.\n"
+"[b]Примечание:[/b] Этот метод не учитывает ÑвойÑтво [code]движениÑ[/code] "
+"объекта. Возвращаемый объект предÑтавлÑет Ñобой Ñловарь, Ñодержащий "
+"Ñледующие полÑ:\n"
+"[code]collider_id[/code]: ID ÑталкивающегоÑÑ Ð¾Ð±ÑŠÐµÐºÑ‚Ð°.\n"
+"[code]linear_velocity[/code]: СкороÑть объекта ÑÑ‚Ð¾Ð»ÐºÐ½Ð¾Ð²ÐµÐ½Ð¸Ñ [Vector2]. ЕÑли "
+"объект ÑвлÑетÑÑ [Area2D], то результатом будет [code](0, 0)[/code].\n"
+"[code]метаданные[/code]: Метаданные переÑекающейÑÑ Ñ„Ð¸Ð³ÑƒÑ€Ñ‹. Эти метаданные "
+"отличаютÑÑ Ð¾Ñ‚ [метод Object.get_meta], и уÑтанавливаютÑÑ Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ [метод "
+"Physics2DServer.shape_set_data].\n"
+"[code]normal[/code]: Ðормаль поверхноÑти объекта в точке переÑечениÑ.\n"
+"[code]точка[/code]: Точка переÑечениÑ.\n"
+"[code]rid[/code]: [RID] переÑекающегоÑÑ Ð¾Ð±ÑŠÐµÐºÑ‚Ð°.\n"
+"[code]shape[/code]: Ð˜Ð½Ð´ÐµÐºÑ Ñ„Ð¾Ñ€Ð¼Ñ‹ ÑталкивающейÑÑ Ñ„Ð¸Ð³ÑƒÑ€Ñ‹."
#: doc/classes/Physics2DDirectSpaceState.xml
msgid ""
@@ -45472,6 +46259,26 @@ msgid ""
"[code]Segments[/code] build mode are not solid shapes. Therefore, they will "
"not be detected."
msgstr ""
+"ПроверÑет, находитÑÑ Ð»Ð¸ точка внутри какой-либо твердой фигуры. Фигуры, "
+"внутри которых находитÑÑ Ñ‚Ð¾Ñ‡ÐºÐ°, возвращаютÑÑ Ð² виде маÑÑива, Ñодержащего "
+"Ñловари Ñо Ñледующими полÑми:\n"
+"[code]collider[/code]: Объект ÑтолкновениÑ.\n"
+"[code]collider_id[/code]: ID объекта ÑтолкновениÑ.\n"
+"[code]metadata[/code]: Метаданные переÑекающейÑÑ Ñ„Ð¸Ð³ÑƒÑ€Ñ‹. Эти метаданные "
+"отличаютÑÑ Ð¾Ñ‚ [метод Object.get_meta], и уÑтанавливаютÑÑ Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ [метод "
+"Physics2DServer.shape_set_data].\n"
+"[code]rid[/code]: [RID] переÑекающегоÑÑ Ð¾Ð±ÑŠÐµÐºÑ‚Ð°.\n"
+"[code]shape[/code]: Ð˜Ð½Ð´ÐµÐºÑ Ñ„Ð¾Ñ€Ð¼Ñ‹ ÑталкивающейÑÑ Ñ„Ð¸Ð³ÑƒÑ€Ñ‹.\n"
+"КоличеÑтво переÑечений может быть ограничено Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ параметра "
+"[code]max_results[/code], чтобы уменьшить Ð²Ñ€ÐµÐ¼Ñ Ð¾Ð±Ñ€Ð°Ð±Ð¾Ñ‚ÐºÐ¸.\n"
+"Кроме того, метод может принимать [code]exclude[/code] маÑÑив объектов или "
+"[RID]ов, которые должны быть иÑключены из Ñтолкновений, "
+"[code]collision_mask[/code] битовую маÑку, предÑтавлÑющую физичеÑкие Ñлои "
+"Ð´Ð»Ñ Ð¿Ñ€Ð¾Ð²ÐµÑ€ÐºÐ¸, или булевы Ð´Ð»Ñ Ð¾Ð¿Ñ€ÐµÐ´ÐµÐ»ÐµÐ½Ð¸Ñ Ñ‚Ð¾Ð³Ð¾, должен ли луч ÑтолкнутьÑÑ Ñ "
+"[PhysicsBody2D]s или [Area2D]s, ÑоответÑтвенно.\n"
+"[b]Примечание:[/b] [ConcavePolygonShape2D]s и [CollisionPolygon2D]s в режиме "
+"поÑÑ‚Ñ€Ð¾ÐµÐ½Ð¸Ñ [code]Segments[/code] не ÑвлÑÑŽÑ‚ÑÑ Ñ‚Ð²ÐµÑ€Ð´Ñ‹Ð¼Ð¸ фигурами. ПоÑтому они "
+"не будут обнаружены."
#: doc/classes/Physics2DDirectSpaceState.xml
msgid ""
@@ -45518,6 +46325,24 @@ msgid ""
"determine if the ray should collide with [PhysicsBody2D]s or [Area2D]s, "
"respectively."
msgstr ""
+"ПереÑекает луч в заданном проÑтранÑтве. Возвращаемый объект предÑтавлÑет "
+"Ñобой Ñловарь Ñо Ñледующими полÑми:\n"
+"[code]collider[/code]: Объект ÑтолкновениÑ.\n"
+"[code]collider_id[/code]: Идентификатор объекта ÑтолкновениÑ.\n"
+"[code]metadata[/code]: Метаданные переÑекающейÑÑ Ñ„Ð¸Ð³ÑƒÑ€Ñ‹. Эти метаданные "
+"отличаютÑÑ Ð¾Ñ‚ [метод Object.get_meta], и уÑтанавливаютÑÑ Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ [метод "
+"Physics2DServer.shape_set_data].\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] битовую маÑку, предÑтавлÑющую физичеÑкие Ñлои Ð´Ð»Ñ Ð¿Ñ€Ð¾Ð²ÐµÑ€ÐºÐ¸, или булевы "
+"Ð´Ð»Ñ Ð¾Ð¿Ñ€ÐµÐ´ÐµÐ»ÐµÐ½Ð¸Ñ Ñ‚Ð¾Ð³Ð¾, должен ли луч ÑтолкнутьÑÑ Ñ [PhysicsBody2D]s или "
+"[Area2D]s, ÑоответÑтвенно."
#: doc/classes/Physics2DDirectSpaceState.xml
msgid ""
@@ -47624,6 +48449,22 @@ msgid ""
"will allow for unbounded output. If any positive value is passed, and the "
"decompression exceeds that amount in bytes, then an error will be returned."
msgstr ""
+"Возвращает новый [PoolByteArray] Ñ Ñ€Ð°Ñпакованными данными. УÑтановите режим "
+"ÑжатиÑ, иÑÐ¿Ð¾Ð»ÑŒÐ·ÑƒÑ Ð¾Ð´Ð½Ñƒ из конÑтант [enum File.CompressionMode]. [b]Этот "
+"метод принимает только режимы ÑÐ¶Ð°Ñ‚Ð¸Ñ gzip и deflate.[/b]\n"
+"Этот метод потенциально медленнее, чем [code]decompress[/code], так как ему "
+"может потребоватьÑÑ Ð¼Ð½Ð¾Ð³Ð¾ÐºÑ€Ð°Ñ‚Ð½Ð¾Ðµ перераÑпределение выходного буфера во Ð²Ñ€ÐµÐ¼Ñ "
+"декомпреÑÑии, в то Ð²Ñ€ÐµÐ¼Ñ ÐºÐ°Ðº [code]decompress[/code] знает размер Ñвоего "
+"выходного буфера Ñ Ñамого начала.\n"
+"\n"
+"GZIP имеет макÑимальный коÑффициент ÑÐ¶Ð°Ñ‚Ð¸Ñ 1032:1, что означает, что очень "
+"возможно, что Ð½ÐµÐ±Ð¾Ð»ÑŒÑˆÐ°Ñ ÑÐ¶Ð°Ñ‚Ð°Ñ Ð¿Ð¾Ð»ÐµÐ·Ð½Ð°Ñ Ð½Ð°Ð³Ñ€ÑƒÐ·ÐºÐ° раÑпакуетÑÑ Ð² потенциально "
+"очень большой выходной файл. Чтобы защититьÑÑ Ð¾Ñ‚ Ñтого, вы можете указать "
+"макÑимальный размер, который Ñтой функции разрешено выделÑть в байтах через "
+"[code]max_output_size[/code]. ЕÑли передать значение -1, то можно выводить "
+"неограниченное количеÑтво данных. ЕÑли передано любое положительное "
+"значение, и раÑпаковка превышает Ñтот размер в байтах, то будет возвращена "
+"ошибка."
#: doc/classes/PoolByteArray.xml doc/classes/PoolColorArray.xml
#: doc/classes/PoolIntArray.xml doc/classes/PoolRealArray.xml
@@ -48695,6 +49536,19 @@ msgid ""
"There is no need to place an opposite portal in an adjacent room, links are "
"made two-way automatically."
msgstr ""
+"[Порталы - Ñто оÑобый тип [MeshInstance], который позволÑет ÑиÑтеме отбора "
+"порталов \"видеть\" из одной комнаты в другую. Они чаÑто ÑоответÑтвуют "
+"дверÑм и окнам в геометрии уровнÑ. ПозволÑÑ [Camera]s видеть только через "
+"порталы, Ñто позволÑет ÑиÑтеме отÑеивать вÑе объекты в комнатах, которые не "
+"видны через порталы. Это одна из форм окклюзионной выборки [b][/b] , ÐºÐ¾Ñ‚Ð¾Ñ€Ð°Ñ "
+"может значительно повыÑить производительноÑть.\n"
+"СущеÑтвуют некоторые Ð¾Ð³Ñ€Ð°Ð½Ð¸Ñ‡ÐµÐ½Ð¸Ñ Ð½Ð° форму порталов:\n"
+"Они должны быть одноÑторонними выпуклыми многоугольниками, и обычно вы "
+"должны ориентировать их передние грани [b]наружу[/b] от [Комнаты], в которой "
+"они раÑположены. Вершины должны раÑполагатьÑÑ Ð² одной плоÑкоÑти (Ñ…Ð¾Ñ‚Ñ Ð¸Ñ… "
+"раÑположение не обÑзательно должно быть идеальным).\n"
+"Ðет необходимоÑти размещать противоположный портал в ÑоÑедней комнате, ÑвÑзи "
+"делаютÑÑ Ð´Ð²ÑƒÑторонними автоматичеÑки."
#: doc/classes/Portal.xml doc/classes/Room.xml
msgid "Sets individual points. Primarily for use by the editor."
@@ -49349,6 +50203,21 @@ msgid ""
"([code]stderr[/code]) is always flushed when a line is printed to it.\n"
"Changes to this setting will only be applied upon restarting the application."
msgstr ""
+"ЕÑли [code]true[/code], то поток Ñтандартного вывода очищаетÑÑ ÐºÐ°Ð¶Ð´Ñ‹Ð¹ раз, "
+"когда печатаетÑÑ Ñтрока. Это влиÑет как на ведение журналов в терминале, так "
+"и на ведение журналов в файлах.\n"
+"При запуÑке проекта Ñтот параметр должен быть включен, еÑли вы хотите, чтобы "
+"журналы ÑобиралиÑÑŒ менеджерами Ñлужб, такими как systemd/journalctl. Эта "
+"наÑтройка отключена по умолчанию в Ñборках релизов, поÑкольку промывка "
+"каждой напечатанной Ñтроки негативно ÑкажетÑÑ Ð½Ð° производительноÑти, еÑли "
+"много Ñтрок печатаетÑÑ Ð² быÑтрой поÑледовательноÑти. Кроме того, еÑли Ñта "
+"наÑтройка включена, файлы журналов будут уÑпешно запиÑаны, еÑли приложение "
+"аварийно завершено или иным образом убито пользователем (не будучи закрытым "
+"\"нормально\").\n"
+"[b]Примечание:[/b] ÐезавиÑимо от Ñтой наÑтройки, Ñтандартный поток ошибок "
+"([code]stderr[/code]) вÑегда промываетÑÑ, когда в него печатаетÑÑ Ñтрока.\n"
+"Ð˜Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð² Ñтой наÑтройке будут применены только поÑле перезапуÑка "
+"приложениÑ."
#: doc/classes/ProjectSettings.xml
msgid ""
@@ -51471,6 +52340,23 @@ msgid ""
"[b]Note:[/b] This property is only read when the project starts. To change "
"the value at runtime, set [member Engine.physics_jitter_fix] instead."
msgstr ""
+"УправлÑет тем, наÑколько тики физики Ñинхронизированы Ñ Ñ€ÐµÐ°Ð»ÑŒÐ½Ñ‹Ð¼ временем. "
+"При значении 0 или меньше тики ÑинхронизируютÑÑ. Такие Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ "
+"рекомендуютÑÑ Ð´Ð»Ñ Ñетевых игр, где ÑÐ¸Ð½Ñ…Ñ€Ð¾Ð½Ð¸Ð·Ð°Ñ†Ð¸Ñ Ñ‡Ð°Ñов имеет значение. "
+"Большие Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð¿Ñ€Ð¸Ð²Ð¾Ð´ÑÑ‚ к большему отклонению внутриигровых чаÑов от "
+"реальных, но позволÑÑŽÑ‚ Ñгладить дрожание кадров. Значение по умолчанию 0,5 "
+"должно уÑтраивать большинÑтво; Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð²Ñ‹ÑˆÐµ 2 могут привеÑти к тому, что "
+"игра будет реагировать на выпадение кадров Ñ Ð·Ð°Ð¼ÐµÑ‚Ð½Ð¾Ð¹ задержкой, поÑтому не "
+"рекомендуетÑÑ.\n"
+"[b]Примечание:[/b] Ð”Ð»Ñ Ð´Ð¾ÑÑ‚Ð¸Ð¶ÐµÐ½Ð¸Ñ Ð½Ð°Ð¸Ð»ÑƒÑ‡ÑˆÐ¸Ñ… результатов при иÑпользовании "
+"пользовательÑкого Ñ€ÐµÑˆÐµÐ½Ð¸Ñ Ð¸Ð½Ñ‚ÐµÑ€Ð¿Ð¾Ð»Ñции физики, иÑправление джиттера физики "
+"Ñледует отключить, уÑтановив [member physics/common/physics_jitter_fix] на "
+"[code]0[/code].\n"
+"[b]Примечание:[/b] ФикÑÐ°Ñ†Ð¸Ñ Ð´Ð¶Ð¸Ñ‚Ñ‚ÐµÑ€Ð° автоматичеÑки отключаетÑÑ Ð²Ð¾ Ð²Ñ€ÐµÐ¼Ñ "
+"выполнениÑ, еÑли включен [member physics/common/physics_interpolation].\n"
+"[b]Примечание:[/b] Это ÑвойÑтво ÑчитываетÑÑ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ при запуÑке проекта. "
+"Чтобы изменить значение во Ð²Ñ€ÐµÐ¼Ñ Ð²Ñ‹Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ, уÑтановите [member Engine."
+"physics_jitter_fix] вмеÑто Ñтого."
#: doc/classes/ProjectSettings.xml
msgid ""
@@ -52110,6 +52996,23 @@ msgid ""
"[b]Note:[/b] This property is only read when the project starts. There is "
"currently no way to change this setting at run-time."
msgstr ""
+"МакÑимальный уровень анизотропного фильтра, иÑпользуемый Ð´Ð»Ñ Ñ‚ÐµÐºÑтур Ñ "
+"включенной анизотропией. Более выÑокие Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð¿Ñ€Ð¸Ð²Ð¾Ð´ÑÑ‚ к более четким "
+"текÑтурам при проÑмотре под коÑыми углами, но за Ñчет ÑÐ½Ð¸Ð¶ÐµÐ½Ð¸Ñ "
+"производительноÑти. За иÑключением [code]1[/code], допуÑтимы только "
+"значениÑ, равные двум целым ([code]2[/code], [code]4[/code], [code]8[/code], "
+"[code]16[/code]). Значение [code]1[/code] принудительно отключает "
+"анизотропную фильтрацию, даже на тех текÑтурах, где она включена.\n"
+"[b]Примечание:[/b] По причинам производительноÑти Ð°Ð½Ð¸Ð·Ð¾Ñ‚Ñ€Ð¾Ð¿Ð½Ð°Ñ Ñ„Ð¸Ð»ÑŒÑ‚Ñ€Ð°Ñ†Ð¸Ñ "
+"[i]не включена по умолчанию[/i] на текÑтурах. Чтобы Ñта наÑтройка имела "
+"Ñффект, анизотропную фильтрацию текÑтуры можно включить, выбрав текÑтуру в "
+"доке FileSystem, Ð¿ÐµÑ€ÐµÐ¹Ð´Ñ Ð² док Import, уÑтановив флажок [b]Anisotropic[/b] и "
+"нажав [b]Reimport[/b]. Однако Ð°Ð½Ð¸Ð·Ð¾Ñ‚Ñ€Ð¾Ð¿Ð½Ð°Ñ Ñ„Ð¸Ð»ÑŒÑ‚Ñ€Ð°Ñ†Ð¸Ñ Ñ€ÐµÐ´ÐºÐ¾ бывает полезной "
+"в 2D, поÑтому включайте ее Ð´Ð»Ñ Ñ‚ÐµÐºÑтур в 2D, только еÑли Ñто дает значимую "
+"визуальную разницу.\n"
+"[b]Примечание:[/b] Это ÑвойÑтво ÑчитываетÑÑ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ при запуÑке проекта. Ð’ "
+"наÑтоÑщее Ð²Ñ€ÐµÐ¼Ñ Ð½Ðµ ÑущеÑтвует ÑпоÑоба изменить Ñтот параметр во Ð²Ñ€ÐµÐ¼Ñ "
+"Ð²Ñ‹Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ð¿Ñ€Ð¾ÐµÐºÑ‚Ð°."
#: doc/classes/ProjectSettings.xml
msgid ""
@@ -52131,15 +53034,22 @@ msgstr ""
#: doc/classes/ProjectSettings.xml
msgid ""
"If [code]true[/code], uses a fast post-processing filter to make banding "
-"significantly less visible. In some cases, debanding may introduce a "
-"slightly noticeable dithering pattern. It's recommended to enable debanding "
-"only when actually needed since the dithering pattern will make lossless-"
-"compressed screenshots larger.\n"
+"significantly less visible in 3D. 2D rendering is [i]not[/i] affected by "
+"debanding unless the [member Environment.background_mode] is [constant "
+"Environment.BG_CANVAS]. In this case, [member rendering/quality/"
+"intended_usage/framebuffer_allocation] must also be set to [b]3D[/b].\n"
+"In some cases, debanding may introduce a slightly noticeable dithering "
+"pattern. It's recommended to enable debanding only when actually needed "
+"since the dithering pattern will make lossless-compressed screenshots "
+"larger.\n"
"[b]Note:[/b] Only available on the GLES3 backend. [member rendering/quality/"
"depth/hdr] must also be [code]true[/code] for debanding to be effective.\n"
"[b]Note:[/b] There are known issues with debanding breaking rendering on "
"mobile platforms. Due to this, it is recommended to leave this option "
-"disabled when targeting mobile platforms."
+"disabled when targeting mobile platforms.\n"
+"[b]Note:[/b] This property is only read when the project starts. To set "
+"debanding at run-time, set [member Viewport.debanding] on the root "
+"[Viewport] instead."
msgstr ""
#: doc/classes/ProjectSettings.xml
@@ -52709,7 +53619,7 @@ msgstr ""
#: doc/classes/Quat.xml
msgid "Quaternion."
-msgstr ""
+msgstr "Кватернион."
#: doc/classes/Quat.xml
msgid ""
@@ -52992,6 +53902,24 @@ msgid ""
"state], and not the initial seed value, which is going to be fixed in Godot "
"4.0."
msgstr ""
+"Инициализирует ÑоÑтоÑние генератора Ñлучайных чиÑел на оÑнове заданного "
+"Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ seed. Заданное значение Ñемени дает воÑпроизводимую "
+"поÑледовательноÑть пÑевдоÑлучайных чиÑел.\n"
+"[b]Примечание:[/b] RNG не обладает лавинным Ñффектом и может выдавать "
+"похожие Ñлучайные потоки при одинаковых Ñеменах. РаÑÑмотрите возможноÑть "
+"иÑÐ¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Ñ…Ñш-функции Ð´Ð»Ñ ÑƒÐ»ÑƒÑ‡ÑˆÐµÐ½Ð¸Ñ ÐºÐ°Ñ‡ÐµÑтва ÑемÑн, еÑли они получены "
+"извне.\n"
+"[b]Примечание:[/b] УÑтановка Ñтого ÑвойÑтва приводит к побочному Ñффекту "
+"Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð²Ð½ÑƒÑ‚Ñ€ÐµÐ½Ð½ÐµÐ³Ð¾ [member state], поÑтому убедитеÑÑŒ, что ÑÐµÐ¼Ñ "
+"инициализировано [i], прежде чем[/i] изменÑть [member state]:\n"
+"[блок кода]\n"
+"var rng = RandomNumberGenerator.new()\n"
+"rng.seed = hash(\"Godot\")\n"
+"rng.state = 100 # ВоÑÑтановление к некоторому ранее Ñохраненному ÑоÑтоÑнию.\n"
+"[/codeblock].\n"
+"[b]Предупреждение:[/b] геттер Ñтого ÑвойÑтва возвращает предыдущее ÑоÑтоÑние "
+"[member state], а не начальное значение seed, что будет иÑправлено в Godot "
+"4.0."
#: doc/classes/RandomNumberGenerator.xml
msgid ""
@@ -53131,6 +54059,20 @@ 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]. Он иÑпользуетÑÑ Ð´Ð»Ñ Ð·Ð°Ð¿Ñ€Ð¾Ñа трехмерного проÑтранÑтва, "
+"чтобы найти ближайший объект на пути луча.\n"
+"RayCast может игнорировать некоторые объекты, добавлÑÑ Ð¸Ñ… в ÑпиÑок "
+"иÑключений через [code]add_exception[/code] или уÑÑ‚Ð°Ð½Ð°Ð²Ð»Ð¸Ð²Ð°Ñ Ð½Ð°Ð´Ð»ÐµÐ¶Ð°Ñ‰ÑƒÑŽ "
+"фильтрацию Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ Ñлоев Ñтолкновений и маÑок.\n"
+"RayCast может быть наÑтроен на Ñообщение о ÑтолкновениÑÑ… Ñ [Area]s ([member "
+"collide_with_areas]) и/или [PhysicsBody]s ([member collide_with_bodies]).\n"
+"Только включенные лучевые передачи Ñмогут запрашивать проÑтранÑтво и "
+"Ñообщать о ÑтолкновениÑÑ….\n"
+"RayCast вычиÑлÑет переÑечение каждый кадр физики (Ñм. [Node]), и результат "
+"кÑшируетÑÑ, чтобы его можно было иÑпользовать позже, до Ñледующего кадра. "
+"ЕÑли требуетÑÑ Ð½ÐµÑколько запроÑов между кадрами физики (или в течение одного "
+"кадра), иÑпользуйте [метод force_raycast_update] поÑле наÑтройки Ñ€ÑйкаÑта."
#: doc/classes/RayCast.xml doc/classes/RayCast2D.xml
msgid ""
@@ -53281,6 +54223,22 @@ 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]. Он иÑпользуетÑÑ Ð´Ð»Ñ Ð·Ð°Ð¿Ñ€Ð¾Ñа двумерного проÑтранÑтва Ñ "
+"целью найти ближайший объект на пути луча.\n"
+"RayCast2D может игнорировать некоторые объекты, добавлÑÑ Ð¸Ñ… в ÑпиÑок "
+"иÑключений через [code]add_exception[/code], уÑÑ‚Ð°Ð½Ð°Ð²Ð»Ð¸Ð²Ð°Ñ Ð¿Ñ€Ð°Ð²Ð¸Ð»ÑŒÐ½ÑƒÑŽ "
+"фильтрацию Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ Ñлоев Ñтолкновений или Ñ„Ð¸Ð»ÑŒÑ‚Ñ€ÑƒÑ Ñ‚Ð¸Ð¿Ñ‹ объектов Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ "
+"маÑок типов.\n"
+"RayCast2D может быть наÑтроен на Ñообщение о ÑтолкновениÑÑ… Ñ [Area2D]s "
+"([member collide_with_areas]) и/или [PhysicsBody2D]s ([member "
+"collide_with_bodies]).\n"
+"Только включенные лучевые передачи Ñмогут запрашивать проÑтранÑтво и "
+"Ñообщать о ÑтолкновениÑÑ….\n"
+"RayCast2D вычиÑлÑет переÑечение каждый кадр физики (Ñм. [Node]), и результат "
+"кÑшируетÑÑ, чтобы его можно было иÑпользовать позже, до Ñледующего кадра. "
+"ЕÑли требуетÑÑ Ð½ÐµÑколько запроÑов между кадрами физики (или в течение одного "
+"кадра), иÑпользуйте [метод force_raycast_update] поÑле наÑтройки Ñ€ÑйкаÑта."
#: doc/classes/RayCast2D.xml
msgid ""
@@ -53487,6 +54445,21 @@ msgid ""
"free references that are no longer in use. This means that unused references "
"will linger on for a while before being removed."
msgstr ""
+"Базовый клаÑÑ Ð´Ð»Ñ Ð»ÑŽÐ±Ð¾Ð³Ð¾ объекта, который ведет подÑчет ÑÑылок. [Resource] и "
+"многие другие вÑпомогательные объекты наÑледуют Ñтот клаÑÑ.\n"
+"Ð’ отличие от других типов [Object], ÑÑылки ведут внутренний Ñчетчик ÑÑылок, "
+"поÑтому они автоматичеÑки оÑвобождаютÑÑ, когда больше не иÑпользуютÑÑ, и "
+"только тогда. ПоÑтому ÑÑылки не нужно оÑвобождать вручную Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ [метода "
+"Object.free].\n"
+"Ð’ подавлÑющем большинÑтве Ñлучаев инÑтанцирование и иÑпользование "
+"[Reference]-производных типов - Ñто вÑе, что вам нужно Ñделать. Методы, "
+"предоÑтавлÑемые в Ñтом клаÑÑе, предназначены только Ð´Ð»Ñ Ð¾Ð¿Ñ‹Ñ‚Ð½Ñ‹Ñ… "
+"пользователей и могут вызвать проблемы при неправильном иÑпользовании.\n"
+"[b]Примечание:[/b] Ð’ C# ÑÑылки не оÑвобождаютÑÑ Ð¼Ð³Ð½Ð¾Ð²ÐµÐ½Ð½Ð¾ поÑле того, как "
+"они переÑтают иÑпользоватьÑÑ. ВмеÑто Ñтого Ñборка муÑора будет выполнÑтьÑÑ "
+"периодичеÑки и оÑвобождать ÑÑылки, которые больше не иÑпользуютÑÑ. Это "
+"означает, что неиÑпользуемые ÑÑылки будут ÑущеÑтвовать некоторое времÑ, "
+"прежде чем будут удалены."
#: doc/classes/Reference.xml
msgid ""
@@ -53789,17 +54762,28 @@ msgstr ""
#: modules/regex/doc_classes/RegEx.xml
msgid ""
"Searches the text for the compiled pattern. Returns a [RegExMatch] container "
-"of the first matching result if found, otherwise [code]null[/code]. The "
-"region to search within can be specified without modifying where the start "
-"and end anchor would be."
+"of the first matching result if found, otherwise [code]null[/code].\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegEx.xml
msgid ""
"Searches the text for the compiled pattern. Returns an array of [RegExMatch] "
"containers for each non-overlapping result. If no results were found, an "
-"empty array is returned instead. The region to search within can be "
-"specified without modifying where the start and end anchor would be."
+"empty array is returned instead.\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegEx.xml
@@ -53808,8 +54792,14 @@ msgid ""
"specified string. Escapes and backreferences such as [code]$1[/code] and "
"[code]$name[/code] are expanded and resolved. By default, only the first "
"instance is replaced, but it can be changed for all instances (global "
-"replacement). The region to search within can be specified without modifying "
-"where the start and end anchor would be."
+"replacement).\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegExMatch.xml
@@ -53962,10 +54952,24 @@ msgid ""
"free resources that are no longer in use. This means that unused resources "
"will linger on for a while before being removed."
msgstr ""
+"Resource - Ñто базовый клаÑÑ Ð´Ð»Ñ Ð²Ñех ÑпецифичеÑких Ð´Ð»Ñ Godot типов "
+"реÑурÑов, Ñлужащих в оÑновном в качеÑтве контейнеров данных. ПоÑкольку они "
+"наÑледуютÑÑ Ð¾Ñ‚ [Reference], реÑурÑÑ‹ учитываютÑÑ Ð¿Ð¾ ÑÑылкам и оÑвобождаютÑÑ, "
+"когда больше не иÑпользуютÑÑ. Они также кÑшируютÑÑ Ð¿Ð¾Ñле загрузки Ñ Ð´Ð¸Ñка, "
+"так что вÑе поÑледующие попытки загрузить реÑÑƒÑ€Ñ Ð¿Ð¾ заданному пути будут "
+"возвращать ту же ÑÑылку (в отличие от [Node], который не учитываетÑÑ Ð¿Ð¾ "
+"ÑÑылкам и может инÑтанцироватьÑÑ Ñ Ð´Ð¸Ñка Ñколько угодно раз). РеÑурÑÑ‹ могут "
+"быть Ñохранены на внешнем диÑке или вложены в другой объект, например, "
+"[Node] или другой реÑурÑ.\n"
+"[b]Примечание:[/b] Ð’ C# реÑурÑÑ‹ не будут оÑвобождатьÑÑ Ð¼Ð³Ð½Ð¾Ð²ÐµÐ½Ð½Ð¾ поÑле того, "
+"как они переÑтанут иÑпользоватьÑÑ. ВмеÑто Ñтого Ñборка муÑора будет "
+"выполнÑтьÑÑ Ð¿ÐµÑ€Ð¸Ð¾Ð´Ð¸Ñ‡ÐµÑки и оÑвобождать реÑурÑÑ‹, которые больше не "
+"иÑпользуютÑÑ. Это означает, что неиÑпользуемые реÑурÑÑ‹ будут ÑущеÑтвовать "
+"некоторое времÑ, прежде чем будут удалены."
#: doc/classes/Resource.xml
msgid "Resources"
-msgstr ""
+msgstr "РеÑурÑÑ‹"
#: doc/classes/Resource.xml
msgid ""
@@ -54322,6 +55326,24 @@ msgid ""
"be used in most situations, leaving the use of [ResourceLoader] for more "
"advanced scenarios."
msgstr ""
+"Загружает реÑÑƒÑ€Ñ Ð¿Ð¾ заданному [code]пути[/code] , кÑÑˆÐ¸Ñ€ÑƒÑ Ñ€ÐµÐ·ÑƒÐ»ÑŒÑ‚Ð°Ñ‚ Ð´Ð»Ñ "
+"поÑледующего доÑтупа.\n"
+"ЗарегиÑтрированные [ResourceFormatLoader]Ñ‹ поÑледовательно запрашиваютÑÑ, "
+"чтобы найти первый, который может обрабатывать раÑширение файла, и затем "
+"выполнÑетÑÑ Ð¿Ð¾Ð¿Ñ‹Ñ‚ÐºÐ° загрузки. ЕÑли загрузка не удалаÑÑŒ, оÑтальные "
+"ResourceFormatLoader'ы также будут опрошены.\n"
+"ÐеобÑзательный [code]type_hint[/code] может быть иÑпользован Ð´Ð»Ñ Ð´Ð°Ð»ÑŒÐ½ÐµÐ¹ÑˆÐµÐ³Ð¾ "
+"ÑƒÐºÐ°Ð·Ð°Ð½Ð¸Ñ Ñ‚Ð¸Ð¿Ð° [Resource], который должен обрабатыватьÑÑ "
+"[ResourceFormatLoader]. Ð’ качеÑтве подÑказки типа можно иÑпользовать вÑе, "
+"что наÑледуетÑÑ Ð¾Ñ‚ [Resource], например [Image].\n"
+"ЕÑли [code]no_cache[/code] is [code]true[/code], кÑш реÑурÑа будет обойден и "
+"реÑÑƒÑ€Ñ Ð±ÑƒÐ´ÐµÑ‚ загружен заново. Ð’ противном Ñлучае будет возвращен "
+"кÑшированный реÑурÑ, еÑли он ÑущеÑтвует.\n"
+"Возвращает пуÑтой реÑурÑ, еÑли ни один [ResourceFormatLoader] не Ñмог "
+"обработать файл.\n"
+"GDScript имеет упрощенный вÑтроенный метод [method @GDScript.load], который "
+"можно иÑпользовать в большинÑтве Ñитуаций, оÑтавлÑÑ Ð¸Ñпользование "
+"[ResourceLoader] Ð´Ð»Ñ Ð±Ð¾Ð»ÐµÐµ Ñложных Ñценариев."
#: doc/classes/ResourceLoader.xml
msgid ""
@@ -55237,6 +56259,26 @@ msgid ""
"[ConcavePolygonShape]. Don't use multiple [CollisionShape]s when using a "
"[ConcavePolygonShape] with Bullet physics if you need shape indices."
msgstr ""
+"ВыдаетÑÑ Ð¿Ñ€Ð¸ Ñтолкновении одного из [Shape] Ñтого RigidBody Ñ Ð´Ñ€ÑƒÐ³Ð¸Ð¼ "
+"[PhysicsBody] или [GridMap] [Shape]. ТребуетÑÑ, чтобы [member "
+"contact_monitor] был уÑтановлен в [code]true[/code] и [member "
+"contacts_reported] был уÑтановлен доÑтаточно выÑоким, чтобы обнаружить вÑе "
+"ÑтолкновениÑ. [GridMap]Ñ‹ обнаруживаютÑÑ, еÑли в [MeshLibrary] еÑть [Shape]Ñ‹ "
+"Ñтолкновений.\n"
+"[code]body_rid[/code] [RID] другого [PhysicsBody] или [MeshLibrary] "
+"[CollisionObject], иÑпользуемого [PhysicsServer].\n"
+"[code]body[/code] [Узел], еÑли он ÑущеÑтвует в дереве, другого [PhysicsBody] "
+"или [GridMap].\n"
+"[code]body_shape_index[/code] Ð¸Ð½Ð´ÐµÐºÑ [Shape] другого [PhysicsBody] или "
+"[GridMap], иÑпользуемого [PhysicsServer]. Получите узел [CollisionShape] Ñ "
+"помощью [code]body.shape_owner_get_owner(body_shape_index)[/code].\n"
+"[code]local_shape_index[/code] Ð¸Ð½Ð´ÐµÐºÑ [Shape] Ñтого RigidBody, иÑпользуемый "
+"[PhysicsServer]. Получите узел [CollisionShape] Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ [code]self."
+"shape_owner_get_owner(local_shape_index)[/code].\n"
+"[b]Примечание:[/b] Физика пули не может определить Ð¸Ð½Ð´ÐµÐºÑ Ñ„Ð¾Ñ€Ð¼Ñ‹ при "
+"иÑпользовании [ConcavePolygonShape]. Ðе иÑпользуйте неÑколько "
+"[CollisionShape] при иÑпользовании [ConcavePolygonShape] Ñ Ñ„Ð¸Ð·Ð¸ÐºÐ¾Ð¹ Bullet, "
+"еÑли вам нужны индекÑÑ‹ формы."
#: doc/classes/RigidBody.xml
msgid ""
@@ -55849,6 +56891,19 @@ msgid ""
"your room and object sizes, and movement speeds. The default value should "
"work reasonably in most circumstances."
msgstr ""
+"Чтобы уменьшить обработку данных Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ¼ÐµÑ‰Ð°ÐµÐ¼Ñ‹Ñ… объектов, к их AABB "
+"применÑетÑÑ Ñ€Ð°Ñширение по мере их перемещениÑ. Этот раÑширенный объем "
+"иÑпользуетÑÑ Ð´Ð»Ñ Ñ€Ð°Ñчета комнат, в которых находитÑÑ Ð¿ÐµÑ€ÐµÐ¼ÐµÑ‰Ð°ÐµÐ¼Ñ‹Ð¹ объект. "
+"ЕÑли точный AABB объекта вÑе еще находитÑÑ Ð² пределах Ñтого раÑширенного "
+"объема при Ñледующем перемещении, нет необходимоÑти повторно обрабатывать "
+"объект, что может ÑÑкономить значительное количеÑтво CPU.\n"
+"ÐедоÑтатком ÑвлÑетÑÑ Ñ‚Ð¾, что еÑли раÑширение Ñлишком велико, объект может "
+"неожиданно раÑпроÑтранитьÑÑ Ð² ÑоÑедние комнаты и поÑвитьÑÑ Ñ‚Ð°Ð¼, где в "
+"противном Ñлучае он мог бы быть удален.\n"
+"Чтобы ÑбаланÑировать производительноÑть роуминга и точноÑть выбраковки, Ñтот "
+"Ð·Ð°Ð¿Ð°Ñ Ñ€Ð°ÑÑˆÐ¸Ñ€ÐµÐ½Ð¸Ñ Ð¼Ð¾Ð¶ÐµÑ‚ быть наÑтроен пользователем. Обычно он завиÑит от "
+"размеров комнат и объектов, а также от ÑкороÑти передвижениÑ. Значение по "
+"умолчанию должно работать разумно в большинÑтве Ñлучаев."
#: doc/classes/RoomManager.xml
msgid ""
@@ -55928,6 +56983,19 @@ msgid ""
"[code]extends RootMotionView[/code]. Additionally, it must not be a "
"[code]tool[/code] script."
msgstr ""
+"[i]Корневое движение[/i] отноÑитÑÑ Ðº технике анимации, когда Ñкелет Ñетки "
+"иÑпользуетÑÑ Ð´Ð»Ñ Ð¿Ñ€Ð¸Ð´Ð°Ð½Ð¸Ñ Ð¸Ð¼Ð¿ÑƒÐ»ÑŒÑа перÑонажу. При работе Ñ 3D-анимацией "
+"популÑрной техникой ÑвлÑетÑÑ Ð¸Ñпользование аниматорами корневой коÑти "
+"Ñкелета Ð´Ð»Ñ Ð¿Ñ€Ð¸Ð´Ð°Ð½Ð¸Ñ Ð´Ð²Ð¸Ð¶ÐµÐ½Ð¸Ñ Ð¾Ñтальным чаÑÑ‚Ñм Ñкелета. Это позволÑет "
+"анимировать перÑонажей таким образом, что шаги фактичеÑки ÑоответÑтвуют полу "
+"под ними. Это также позволÑет точно взаимодейÑтвовать Ñ Ð¾Ð±ÑŠÐµÐºÑ‚Ð°Ð¼Ð¸ во Ð²Ñ€ÐµÐ¼Ñ "
+"кинематографа. См. также [AnimationTree].\n"
+"[b]Примечание:[/b] [RootMotionView] виден только в редакторе. Он будет "
+"автоматичеÑки Ñкрыт в работающем проекте, а также будет преобразован в "
+"обычный [Node] в работающем проекте. Это означает, что Ñкрипт, прикрепленный "
+"к узлу [RootMotionView] [i]должен[/i] иметь [code]extends Node[/code] вмеÑто "
+"[code]extends RootMotionView[/code]. Кроме того, он не должен быть Ñкриптом "
+"[code]инÑтрумента[/code]."
#: doc/classes/RootMotionView.xml
msgid "Using AnimationTree - Root motion"
@@ -56530,12 +57598,16 @@ msgid "Call a group immediately (calls are normally made on idle)."
msgstr ""
#: doc/classes/SceneTree.xml
-msgid "Call a group only once even if the call is executed many times."
+msgid ""
+"Call a group only once even if the call is executed many times.\n"
+"[b]Note:[/b] Arguments are not taken into account when deciding whether the "
+"call is unique or not. Therefore when the same method is called with "
+"different arguments, only the first call will be performed."
msgstr ""
#: doc/classes/SceneTree.xml
msgid "No stretching."
-msgstr ""
+msgstr "Ðе раÑÑ‚Ñгивать."
#: doc/classes/SceneTree.xml
msgid "Render stretching in higher resolution (interpolated)."
@@ -56579,7 +57651,7 @@ msgstr ""
#: doc/classes/SceneTreeTimer.xml
msgid "One-shot timer."
-msgstr ""
+msgstr "Таймер на один Ñнимок."
#: doc/classes/SceneTreeTimer.xml
msgid ""
@@ -56769,6 +57841,23 @@ msgid ""
"will always return the final value, regardless of [code]elapsed_time[/code] "
"provided."
msgstr ""
+"Этот метод можно иÑпользовать Ð´Ð»Ñ Ñ€ÑƒÑ‡Ð½Ð¾Ð¹ интерполÑции значениÑ, когда вы не "
+"хотите, чтобы [SceneTreeTween] выполнÑл анимацию за ваÑ. Он похож на [method "
+"@GDScript.lerp], но Ñ Ð¿Ð¾Ð´Ð´ÐµÑ€Ð¶ÐºÐ¾Ð¹ пользовательÑкого перехода и ÑмÑгчениÑ.\n"
+"[code]initial_value[/code] - начальное значение интерполÑции.\n"
+"[code]delta_value[/code] - Ñто изменение Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð² интерполÑции, Ñ‚.е. оно "
+"равно [code]final_value - initial_value[/code].\n"
+"[code]elapsed_time[/code] - Ñто Ð²Ñ€ÐµÐ¼Ñ Ð² Ñекундах, прошедшее поÑле начала "
+"интерполÑции, которое иÑпользуетÑÑ Ð´Ð»Ñ ÐºÐ¾Ð½Ñ‚Ñ€Ð¾Ð»Ñ Ð¿Ð¾Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð¸Ð½Ñ‚ÐµÑ€Ð¿Ð¾Ð»Ñции. "
+"Ðапример, еÑли оно равно половине длительноÑти [code][/code] , "
+"интерполированное значение будет находитьÑÑ Ð½Ð° полпути между начальным и "
+"конечным значениÑми. Это значение также может быть больше, чем "
+"[code]duration[/code] или меньше, чем 0, что приведет к ÑкÑтраполÑции "
+"значениÑ.\n"
+"[code]duration[/code] - общее Ð²Ñ€ÐµÐ¼Ñ Ð¸Ð½Ñ‚ÐµÑ€Ð¿Ð¾Ð»Ñции.\n"
+"[b]Примечание:[/b] ЕÑли [code]duration[/code] равно [code]0[/code], метод "
+"вÑегда будет возвращать конечное значение, незавиÑимо от [code]elapsed_time[/"
+"code] предоÑтавленного значениÑ."
#: doc/classes/SceneTreeTween.xml
msgid ""
@@ -57543,6 +58632,22 @@ msgid ""
"([code]shape_xform[/code]), and the movement to test onto the other object "
"([code]shape_motion[/code])."
msgstr ""
+"Возвращает ÑпиÑок пар точек ÑоприкоÑновениÑ, где Ð´Ð°Ð½Ð½Ð°Ñ Ñ„Ð¸Ð³ÑƒÑ€Ð° могла бы "
+"коÑнутьÑÑ Ð´Ñ€ÑƒÐ³Ð¾Ð¹, еÑли бы было применено заданное движение.\n"
+"ЕÑли Ñтолкновений не будет, возвращаемый ÑпиÑок пуÑÑ‚. Ð’ противном Ñлучае, "
+"возвращаемый ÑпиÑок Ñодержит попарно раÑположенные точки контакта, в которых "
+"чередуютÑÑ Ñ‚Ð¾Ñ‡ÐºÐ¸ на границе данной фигуры и точки на границе "
+"[code]with_shape[/code].\n"
+"Пара Ñтолкновений A, B может быть иÑпользована Ð´Ð»Ñ Ð²Ñ‹Ñ‡Ð¸ÑÐ»ÐµÐ½Ð¸Ñ Ð½Ð¾Ñ€Ð¼Ð°Ð»Ð¸ "
+"ÑÑ‚Ð¾Ð»ÐºÐ½Ð¾Ð²ÐµÐ½Ð¸Ñ Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ [code](B - A).normalized()[/code], и глубины "
+"ÑÑ‚Ð¾Ð»ÐºÐ½Ð¾Ð²ÐµÐ½Ð¸Ñ Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ [code](B - A).length()[/code]. Эта Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾Ð±Ñ‹Ñ‡Ð½Ð¾ "
+"иÑпользуетÑÑ Ð´Ð»Ñ Ñ€Ð°Ð·Ð´ÐµÐ»ÐµÐ½Ð¸Ñ Ñ„Ð¸Ð³ÑƒÑ€, оÑобенно в решателÑÑ… Ñтолкновений.\n"
+"Этому методу нужна матрица транÑформации Ð´Ð»Ñ Ð´Ð°Ð½Ð½Ð¾Ð¹ фигуры "
+"([code]local_xform[/code]), движение Ð´Ð»Ñ Ð¿Ñ€Ð¾Ð²ÐµÑ€ÐºÐ¸ Ñтой фигуры "
+"([code]local_motion[/code]), фигура Ð´Ð»Ñ Ð¿Ñ€Ð¾Ð²ÐµÑ€ÐºÐ¸ Ñтолкновений Ñ Ð½ÐµÐ¹ "
+"([code]with_shape[/code]), матрица транÑформации Ñтой фигуры "
+"([code]shape_xform[/code]) и движение Ð´Ð»Ñ Ð¿Ñ€Ð¾Ð²ÐµÑ€ÐºÐ¸ на другом объекте "
+"([code]shape_motion[/code])."
#: doc/classes/Shape2D.xml
msgid ""
@@ -57614,7 +58719,7 @@ msgstr ""
#: doc/classes/Skeleton.xml
msgid "[i]Deprecated soon.[/i]"
-msgstr ""
+msgstr "[i]Скоро будет уÑтаревшим.[/i]"
#: doc/classes/Skeleton.xml
msgid "Clear all the bones in this skeleton."
@@ -58374,7 +59479,9 @@ msgid ""
"[b]Note:[/b] Mixed negative scales in 3D are not decomposable from the "
"transformation matrix. Due to the way scale is represented with "
"transformation matrices in Godot, the scale values will either be all "
-"positive or all negative."
+"positive or all negative.\n"
+"[b]Note:[/b] Not all nodes are visually scaled by the [member scale] "
+"property. For example, [Light]s are not visually affected by [member scale]."
msgstr ""
#: doc/classes/Spatial.xml
@@ -59756,7 +60863,10 @@ msgid ""
msgstr ""
#: doc/classes/SpotLight.xml
-msgid "The spotlight's angle in degrees."
+msgid ""
+"The spotlight's angle in degrees.\n"
+"[b]Note:[/b] [member spot_angle] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/SpotLight.xml
@@ -59772,7 +60882,9 @@ msgid ""
"The maximal range that can be reached by the spotlight. Note that the "
"effectively lit area may appear to be smaller depending on the [member "
"spot_attenuation] in use. No matter the [member spot_attenuation] in use, "
-"the light will never reach anything outside this range."
+"the light will never reach anything outside this range.\n"
+"[b]Note:[/b] [member spot_range] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/SpringArm.xml
@@ -60780,6 +61892,21 @@ msgid ""
"To get a boolean result from a string comparison, use the [code]==[/code] "
"operator instead. See also [method nocasecmp_to]."
msgstr ""
+"ВыполнÑет Ñравнение Ñ Ð´Ñ€ÑƒÐ³Ð¾Ð¹ Ñтрокой Ñ ÑƒÑ‡ÐµÑ‚Ð¾Ð¼ региÑтра. Возвращает [code]-1[/"
+"code], еÑли меньше, [code]1[/code], еÑли больше, или [code]0[/code], еÑли "
+"равно. \"Меньше\" или \"больше\" определÑÑŽÑ‚ÑÑ [url=https://en.wikipedia.org/"
+"wiki/List_of_Unicode_characters]кодовыми точками Unicode[/url] каждой "
+"Ñтроки, что примерно ÑоответÑтвует алфавитному порÑдку.\n"
+"[b]Поведение при различной длине Ñтроки:[/b] Возвращает [code]1[/code], еÑли "
+"\"базоваÑ\" Ñтрока длиннее Ñтрок [code]-[/code] или [code]-1[/code], еÑли "
+"\"базоваÑ\" Ñтрока короче Ñтрок [code]-[/code]. Следует помнить, что длина "
+"определÑетÑÑ ÐºÐ¾Ð»Ð¸Ñ‡ÐµÑтвом кодовых точек Юникода, [i]а не[/i] реально видимых "
+"Ñимволов.\n"
+"[b]Поведение Ñ Ð¿ÑƒÑтыми Ñтроками:[/b] Возвращает [code]-1[/code], еÑли "
+"\"базоваÑ\" Ñтрока пуÑта, [code]1[/code], еÑли Ñтроки [code]-[/code] пуÑты, "
+"или [code]0[/code], еÑли обе Ñтроки пуÑты.\n"
+"Чтобы получить булев результат ÑÑ€Ð°Ð²Ð½ÐµÐ½Ð¸Ñ Ñтрок, иÑпользуйте вмеÑто Ñтого "
+"оператор [code]==[/code]. См. также [метод nocasecmp_to]."
#: doc/classes/String.xml
msgid ""
@@ -61184,6 +62311,22 @@ msgid ""
"To get a boolean result from a string comparison, use the [code]==[/code] "
"operator instead. See also [method casecmp_to]."
msgstr ""
+"ВыполнÑет Ñравнение Ñ Ð´Ñ€ÑƒÐ³Ð¾Ð¹ Ñтрокой без учета региÑтра. Возвращает "
+"[code]-1[/code], еÑли меньше, [code]1[/code], еÑли больше, или [code]0[/"
+"code], еÑли равно. \"Меньше\" или \"больше\" определÑетÑÑ [url=https://en."
+"wikipedia.org/wiki/List_of_Unicode_characters]кодовыми точками Unicode[/url] "
+"каждой Ñтроки, что примерно ÑоответÑтвует алфавитному порÑдку. При Ñравнении "
+"Ñимволы нижнего региÑтра преобразуютÑÑ Ð² верхний региÑтр.\n"
+"[b]Поведение при различной длине Ñтроки:[/b] Возвращает [code]1[/code], еÑли "
+"\"базоваÑ\" Ñтрока длиннее, чем Ñтроки [code]-[/code] или [code]-1[/code], "
+"еÑли \"базоваÑ\" Ñтрока короче, чем Ñтроки [code]-[/code]. Следует помнить, "
+"что длина определÑетÑÑ ÐºÐ¾Ð»Ð¸Ñ‡ÐµÑтвом кодовых точек Юникода, [i]а не[/i] "
+"реально видимых Ñимволов.\n"
+"[b]Поведение Ñ Ð¿ÑƒÑтыми Ñтроками:[/b] Возвращает [code]-1[/code], еÑли "
+"\"базоваÑ\" Ñтрока пуÑта, [code]1[/code], еÑли Ñтроки [code]-[/code] пуÑты, "
+"или [code]0[/code], еÑли обе Ñтроки пуÑты.\n"
+"Чтобы получить булев результат ÑÑ€Ð°Ð²Ð½ÐµÐ½Ð¸Ñ Ñтрок, иÑпользуйте вмеÑто Ñтого "
+"оператор [code]==[/code]. См. также [метод casecmp_to]."
#: doc/classes/String.xml
msgid "Returns the character code at position [code]at[/code]."
@@ -61273,6 +62416,24 @@ msgid ""
"print(some_array[1]) # Prints \"Four\"\n"
"[/codeblock]"
msgstr ""
+"РазделÑет Ñтроку по [code]разделителю[/code] и возвращает маÑÑив подÑтрок, "
+"Ð½Ð°Ñ‡Ð¸Ð½Ð°Ñ Ñправа.\n"
+"Разделители в возвращаемом маÑÑиве ÑортируютÑÑ Ð² том же порÑдке, что и "
+"иÑÑ…Ð¾Ð´Ð½Ð°Ñ Ñтрока, Ñлева направо.\n"
+"ЕÑли [code]allow_empty[/code] равен [code]true[/code], и в Ñтроке еÑть два "
+"ÑоÑедних разделителÑ, то в маÑÑив подÑтрок в Ñтой позиции будет добавлена "
+"пуÑÑ‚Ð°Ñ Ñтрока.\n"
+"ЕÑли указано [code]maxsplit[/code], то Ñто определÑет количеÑтво разбиений "
+"Ñправа до [code]maxsplit[/code]. Значение по умолчанию 0 означает, что вÑе "
+"Ñлементы разделÑÑŽÑ‚ÑÑ, что дает тот же результат, что и [method split].\n"
+"Пример:\n"
+"[codeblock].\n"
+"var some_string = \"One,Two,Three,Four\"\n"
+"var some_array = some_string.rsplit(\",\", true, 1)\n"
+"print(some_array.size()) # Печатает 2\n"
+"print(some_array[0]) # Печатает \"Один, два, три\"\n"
+"print(some_array[1]) # Печатает \"Four\"\n"
+"[/codeblock]"
#: doc/classes/String.xml
msgid ""
@@ -61341,6 +62502,26 @@ msgid ""
"If you need to split strings with more complex rules, use the [RegEx] class "
"instead."
msgstr ""
+"РазделÑет Ñтроку по разделителю [code][/code] и возвращает маÑÑив подÑтрок. "
+"Разделитель [code][/code] может быть любой длины.\n"
+"ЕÑли [code]allow_empty[/code] равно [code]true[/code], и в Ñтроке еÑть два "
+"ÑоÑедних разделителÑ, то в маÑÑив подÑтрок в Ñтой позиции будет добавлена "
+"пуÑÑ‚Ð°Ñ Ñтрока.\n"
+"ЕÑли указано [code]maxsplit[/code], то Ñто определÑет количеÑтво разбиений "
+"Ñлева до [code]maxsplit[/code]. Значение по умолчанию [code]0[/code] "
+"означает, что вÑе Ñлементы разделÑÑŽÑ‚ÑÑ.\n"
+"ЕÑли вам нужен только один Ñлемент из маÑÑива по определенному индекÑу, "
+"[метод get_slice] ÑвлÑетÑÑ Ð±Ð¾Ð»ÐµÐµ производительным вариантом.\n"
+"Пример:\n"
+"[codeblock].\n"
+"var some_string = \"One,Two,Three,Four\"\n"
+"var some_array = some_string.split(\",\", true, 1)\n"
+"print(some_array.size()) # Печатает 2\n"
+"print(some_array[0]) # Печатает \"Один\"\n"
+"print(some_array[1]) # Печатает \"Два, три, четыре\"\n"
+"[/codeblock].\n"
+"ЕÑли вам нужно разделить Ñтроки по более Ñложным правилам, иÑпользуйте клаÑÑ "
+"[RegEx]."
#: doc/classes/String.xml
msgid ""
@@ -62210,7 +63391,7 @@ msgstr ""
#: doc/classes/TabContainer.xml
msgid "Tabbed container."
-msgstr ""
+msgstr "Контейнер Ñ Ð²ÐºÐ»Ð°Ð´ÐºÐ°Ð¼Ð¸."
#: doc/classes/TabContainer.xml
msgid ""
@@ -62464,7 +63645,7 @@ msgstr ""
#: doc/classes/Tabs.xml
msgid "Tabs control."
-msgstr ""
+msgstr "Управление вкладками."
#: doc/classes/Tabs.xml
msgid ""
@@ -62671,7 +63852,7 @@ msgstr ""
#: doc/classes/TCP_Server.xml
msgid "Stops listening."
-msgstr ""
+msgstr "ПереÑтает Ñлушать."
#: doc/classes/TCP_Server.xml
msgid ""
@@ -65704,7 +66885,7 @@ msgstr ""
#: doc/classes/TouchScreenButton.xml
msgid "Always visible."
-msgstr ""
+msgstr "Ð’Ñегда видно."
#: doc/classes/TouchScreenButton.xml
msgid "Visible on touch screens only."
@@ -65972,7 +67153,7 @@ msgstr ""
#: doc/classes/Translation.xml
msgid "Language Translation."
-msgstr ""
+msgstr "Языковой перевод."
#: doc/classes/Translation.xml
msgid ""
@@ -67797,7 +68978,7 @@ msgstr ""
#: modules/upnp/doc_classes/UPNP.xml
msgid "Inconsistent parameters."
-msgstr ""
+msgstr "ÐеÑоответÑтвующие параметры."
#: modules/upnp/doc_classes/UPNP.xml
msgid ""
@@ -67859,39 +69040,39 @@ msgstr ""
#: modules/upnp/doc_classes/UPNP.xml
msgid "Invalid gateway."
-msgstr ""
+msgstr "Ðеверный шлюз."
#: modules/upnp/doc_classes/UPNP.xml
msgid "Invalid port."
-msgstr ""
+msgstr "Ðеверный порт."
#: modules/upnp/doc_classes/UPNP.xml
msgid "Invalid protocol."
-msgstr ""
+msgstr "Ðеверный протокол."
#: modules/upnp/doc_classes/UPNP.xml
msgid "Invalid duration."
-msgstr ""
+msgstr "ÐÐµÐ²ÐµÑ€Ð½Ð°Ñ Ð¿Ñ€Ð¾Ð´Ð¾Ð»Ð¶Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð¾Ñть."
#: modules/upnp/doc_classes/UPNP.xml
msgid "Invalid arguments."
-msgstr ""
+msgstr "ÐедопуÑтимые аргументы."
#: modules/upnp/doc_classes/UPNP.xml
msgid "Invalid response."
-msgstr ""
+msgstr "Ðеверный ответ."
#: modules/upnp/doc_classes/UPNP.xml
msgid "Invalid parameter."
-msgstr ""
+msgstr "ÐедопуÑтимый параметр."
#: modules/upnp/doc_classes/UPNP.xml modules/upnp/doc_classes/UPNPDevice.xml
msgid "HTTP error."
-msgstr ""
+msgstr "Ошибка HTTP."
#: modules/upnp/doc_classes/UPNP.xml
msgid "Socket error."
-msgstr ""
+msgstr "Ошибка Ñокета."
#: modules/upnp/doc_classes/UPNP.xml
msgid "Error allocating memory."
@@ -67974,11 +69155,11 @@ msgstr ""
#: modules/upnp/doc_classes/UPNPDevice.xml
msgid "Service type."
-msgstr ""
+msgstr "Тип уÑлуг."
#: modules/upnp/doc_classes/UPNPDevice.xml
msgid "OK."
-msgstr ""
+msgstr "OK."
#: modules/upnp/doc_classes/UPNPDevice.xml
msgid "Empty HTTP response."
@@ -67994,15 +69175,15 @@ msgstr ""
#: modules/upnp/doc_classes/UPNPDevice.xml
msgid "Disconnected."
-msgstr ""
+msgstr "Отключен."
#: modules/upnp/doc_classes/UPNPDevice.xml
msgid "Unknown device."
-msgstr ""
+msgstr "ÐеизвеÑтное уÑтройÑтво."
#: modules/upnp/doc_classes/UPNPDevice.xml
msgid "Invalid control."
-msgstr ""
+msgstr "Ðеверный контроль."
#: modules/upnp/doc_classes/UPNPDevice.xml
msgid "Memory allocation error."
@@ -69302,10 +70483,15 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
"If [code]true[/code], uses a fast post-processing filter to make banding "
-"significantly less visible. In some cases, debanding may introduce a "
-"slightly noticeable dithering pattern. It's recommended to enable debanding "
-"only when actually needed since the dithering pattern will make lossless-"
-"compressed screenshots larger.\n"
+"significantly less visible in 3D. 2D rendering is [i]not[/i] affected by "
+"debanding unless the [member Environment.background_mode] is [constant "
+"Environment.BG_CANVAS]. In this case, [member usage] must also be set to "
+"[constant USAGE_3D]. See also [member ProjectSettings.rendering/quality/"
+"filters/use_debanding].\n"
+"In some cases, debanding may introduce a slightly noticeable dithering "
+"pattern. It's recommended to enable debanding only when actually needed "
+"since the dithering pattern will make lossless-compressed screenshots "
+"larger.\n"
"[b]Note:[/b] Only available on the GLES3 backend. [member hdr] must also be "
"[code]true[/code] for debanding to be effective."
msgstr ""
@@ -69316,8 +70502,8 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
-"If [code]true[/code], the viewport will disable 3D rendering. For actual "
-"disabling use [code]usage[/code]."
+"If [code]true[/code], the viewport will disable 3D rendering. To actually "
+"disable allocation of 3D buffers, set [member usage] instead."
msgstr ""
#: doc/classes/Viewport.xml
@@ -69472,7 +70658,9 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
-"The rendering mode of viewport.\n"
+"The viewport's rendering mode. This controls which buffers are allocated for "
+"the viewport (2D only, or 2D + 3D). 2D-only options can reduce memory usage "
+"and improve performance slightly, especially on low-end devices.\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."
@@ -70008,6 +71196,22 @@ msgid ""
"render object this [VisualInstance] is set to."
msgstr ""
+#: doc/classes/VisualInstance.xml
+msgid ""
+"The sorting offset used by this [VisualInstance]. Adjusting it to a higher "
+"value will make the [VisualInstance] reliably draw on top of other "
+"[VisualInstance]s that are otherwise positioned at the same spot."
+msgstr ""
+
+#: doc/classes/VisualInstance.xml
+msgid ""
+"If [code]true[/code], the object is sorted based on the [AABB] center. "
+"Sorted based on the global position otherwise.\n"
+"The [AABB] center based sorting is generally more accurate for 3D models. "
+"The position based sorting instead allows to better control the drawing "
+"order when working with [Particles] and [CPUParticles]."
+msgstr ""
+
#: modules/visual_script/doc_classes/VisualScript.xml
msgid "A script implemented in the Visual Script programming environment."
msgstr ""
@@ -71197,11 +72401,11 @@ msgstr ""
#: modules/visual_script/doc_classes/VisualScriptMathConstant.xml
msgid "Unity: [code]1[/code]."
-msgstr ""
+msgstr "ЕдинÑтво: [code]1[/code]."
#: modules/visual_script/doc_classes/VisualScriptMathConstant.xml
msgid "Pi: [code]3.141593[/code]."
-msgstr ""
+msgstr "Пи: [code]3.141593[/code]."
#: modules/visual_script/doc_classes/VisualScriptMathConstant.xml
msgid "Pi divided by two: [code]1.570796[/code]."
@@ -71209,7 +72413,7 @@ msgstr ""
#: modules/visual_script/doc_classes/VisualScriptMathConstant.xml
msgid "Tau: [code]6.283185[/code]."
-msgstr ""
+msgstr "Тау: [code]6.283185[/code]."
#: modules/visual_script/doc_classes/VisualScriptMathConstant.xml
msgid ""
@@ -71223,7 +72427,7 @@ msgstr ""
#: modules/visual_script/doc_classes/VisualScriptMathConstant.xml
msgid "Infinity: [code]inf[/code]."
-msgstr ""
+msgstr "БеÑконечноÑть: [code]inf[/code]."
#: modules/visual_script/doc_classes/VisualScriptMathConstant.xml
msgid "Not a number: [code]nan[/code]."
@@ -71525,7 +72729,7 @@ msgstr ""
#: modules/visual_script/doc_classes/VisualScriptSceneNode.xml
msgid "Node reference."
-msgstr ""
+msgstr "СÑылка на узел."
#: modules/visual_script/doc_classes/VisualScriptSceneNode.xml
msgid ""
@@ -71686,7 +72890,7 @@ msgstr ""
#: modules/visual_script/doc_classes/VisualScriptWhile.xml
msgid "Conditional loop."
-msgstr ""
+msgstr "УÑловный цикл."
#: modules/visual_script/doc_classes/VisualScriptWhile.xml
msgid ""
@@ -72329,7 +73533,7 @@ msgstr ""
#: doc/classes/VisualServer.xml
msgid "Synchronizes threads."
-msgstr ""
+msgstr "Синхронизирует потоки."
#: doc/classes/VisualServer.xml
msgid "Tries to free an object in the VisualServer."
@@ -73807,6 +75011,24 @@ msgid ""
"manually. For further optimization, see [method "
"viewport_set_render_direct_to_screen]."
msgstr ""
+"Копирует видовой Ñкран в облаÑть Ñкрана, указанную [code]rect[/code]. ЕÑли "
+"[член Viewport.render_direct_to_screen] равен [code]true[/code], то вьюпорт "
+"не иÑпользует фреймбуфер и Ñодержимое вьюпорта выводитÑÑ Ð½ÐµÐ¿Ð¾ÑредÑтвенно на "
+"Ñкран. Однако обратите внимание, что корневой видовой Ñкран риÑуетÑÑ "
+"поÑледним, поÑтому он будет риÑоватьÑÑ Ð¿Ð¾Ð²ÐµÑ€Ñ… Ñкрана. СоответÑтвенно, вы "
+"должны уÑтановить корневой видовой Ñкран на облаÑть, ÐºÐ¾Ñ‚Ð¾Ñ€Ð°Ñ Ð½Ðµ покрывает "
+"облаÑть, к которой вы прикрепили Ñтот видовой Ñкран.\n"
+"Ðапример, вы можете уÑтановить корневой видовой Ñкран так, чтобы он вообще "
+"не отриÑовывалÑÑ, иÑÐ¿Ð¾Ð»ÑŒÐ·ÑƒÑ Ñледующий код:\n"
+"[codeblock].\n"
+"func _ready():\n"
+" get_viewport().set_attach_to_screen_rect(Rect2())\n"
+" $Viewport.set_attach_to_screen_rect(Rect2(0, 0, 600, 600))\n"
+"[/codeblock].\n"
+"ИÑпользование Ñтого метода может привеÑти к значительной оптимизации, "
+"оÑобенно на уÑтройÑтвах низкого клаÑÑа. Однако за Ñто приходитÑÑ "
+"раÑплачиватьÑÑ Ð½ÐµÐ¾Ð±Ñ…Ð¾Ð´Ð¸Ð¼Ð¾Ñтью управлÑть видовыми Ñкранами вручную. Ð”Ð»Ñ "
+"дальнейшей оптимизации Ñмотрите [метод viewport_set_render_direct_to_screen]."
#: doc/classes/VisualServer.xml
msgid ""
@@ -73914,6 +75136,19 @@ msgid ""
"will be drawn, no automatic scaling is possible, even if your game scene is "
"significantly larger than the window size."
msgstr ""
+"ЕÑли [code]true[/code], выведите Ñодержимое видового Ñкрана непоÑредÑтвенно "
+"на Ñкран. Это позволÑет выполнить низкоуровневую оптимизацию, при которой "
+"можно пропуÑтить отриÑовку видового Ñкрана в корневой видовой Ñкран. Ð¥Ð¾Ñ‚Ñ "
+"Ñта Ð¾Ð¿Ñ‚Ð¸Ð¼Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð¼Ð¾Ð¶ÐµÑ‚ привеÑти к значительному увеличению ÑкороÑти (оÑобенно "
+"на Ñтарых уÑтройÑтвах), она обходитÑÑ Ð½ÐµÐ´ÐµÑˆÐµÐ²Ð¾. Когда Ñта Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ Ð²ÐºÐ»ÑŽÑ‡ÐµÐ½Ð°, "
+"вы не можете читать из облаÑти проÑмотра или из [code]SCREEN_TEXTURE[/code]. "
+"Ð’Ñ‹ также терÑете преимущеÑтва некоторых наÑтроек окна, таких как различные "
+"режимы раÑÑ‚ÑжениÑ. Еще одно поÑледÑтвие, о котором Ñледует знать, Ñто то, "
+"что в 2D рендеринг проиÑходит в координатах окна, поÑтому еÑли у Ð²Ð°Ñ ÐµÑть "
+"облаÑть проÑмотра, ÐºÐ¾Ñ‚Ð¾Ñ€Ð°Ñ Ð² два раза больше окна, и вы уÑтановите Ñто, то "
+"будет отриÑована только та чаÑть, ÐºÐ¾Ñ‚Ð¾Ñ€Ð°Ñ Ð¿Ð¾Ð¼ÐµÑ‰Ð°ÐµÑ‚ÑÑ Ð² окно, автоматичеÑкое "
+"маÑштабирование невозможно, даже еÑли ваша Ð¸Ð³Ñ€Ð¾Ð²Ð°Ñ Ñцена значительно больше, "
+"чем размер окна."
#: doc/classes/VisualServer.xml
msgid ""
@@ -76384,7 +77619,7 @@ msgstr "Возвращает значение, противоположное п
#: doc/classes/VisualShaderNodeVectorFunc.xml
msgid "Returns [code]1/vector[/code]."
-msgstr ""
+msgstr "Возвращает [code]1/вектор[/code]."
#: doc/classes/VisualShaderNodeVectorFunc.xml
msgid "Converts RGB vector to HSV equivalent."
@@ -76719,7 +77954,7 @@ msgstr ""
#: doc/classes/VSlider.xml
msgid "Vertical slider."
-msgstr ""
+msgstr "Вертикальный Ñлайдер."
#: doc/classes/VSlider.xml
msgid ""
diff --git a/doc/translations/sk.po b/doc/translations/sk.po
index e5562df057..3a58e3f2a9 100644
--- a/doc/translations/sk.po
+++ b/doc/translations/sk.po
@@ -476,7 +476,8 @@ msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
-"Returns an array of dictionaries representing the current call stack.\n"
+"Returns an array of dictionaries representing the current call stack. See "
+"also [method print_stack].\n"
"[codeblock]\n"
"func _ready():\n"
" foo()\n"
@@ -491,7 +492,11 @@ msgid ""
"[codeblock]\n"
"[{function:bar, line:12, source:res://script.gd}, {function:foo, line:9, "
"source:res://script.gd}, {function:_ready, line:6, source:res://script.gd}]\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] [method get_stack] only works if the running instance is "
+"connected to a debugging server (i.e. an editor instance). [method "
+"get_stack] will not work in projects exported in release mode, or in "
+"projects exported in debug mode if not connected to a debugging server."
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -864,12 +869,16 @@ msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
-"Prints a stack track at code location, only works when running with debugger "
-"turned on.\n"
+"Prints a stack trace at the current code location. See also [method "
+"get_stack].\n"
"Output in the console would look something like this:\n"
"[codeblock]\n"
"Frame 0 - res://test.gd:16 in function '_process'\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] [method print_stack] only works if the running instance is "
+"connected to a debugging server (i.e. an editor instance). [method "
+"print_stack] will not work in projects exported in release mode, or in "
+"projects exported in debug mode if not connected to a debugging server."
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -3480,6 +3489,26 @@ msgid "Hints that an image is compressed using lossless compression."
msgstr ""
#: doc/classes/@GlobalScope.xml
+msgid ""
+"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:\n"
+"[codeblock]\n"
+"hint_string = \"%s:\" % [TYPE_INT] # Array of inteters.\n"
+"hint_string = \"%s:%s:\" % [TYPE_ARRAY, TYPE_REAL] # Two-dimensional array "
+"of floats.\n"
+"hint_string = \"%s/%s:Resource\" % [TYPE_OBJECT, TYPE_OBJECT] # Array of "
+"resources.\n"
+"hint_string = \"%s:%s/%s:Resource\" % [TYPE_ARRAY, TYPE_OBJECT, TYPE_OBJECT] "
+"# Two-dimensional array of resources.\n"
+"[/codeblock]\n"
+"[b]Note:[/b] The final colon is required to specify for properly detecting "
+"built-in types."
+msgstr ""
+
+#: doc/classes/@GlobalScope.xml
msgid "The property is serialized and saved in the scene file (default)."
msgstr ""
@@ -4164,8 +4193,7 @@ msgstr ""
#: doc/classes/AudioStreamPlayer.xml doc/classes/Button.xml
#: doc/classes/CanvasLayer.xml doc/classes/CollisionShape2D.xml
#: doc/classes/ColorRect.xml doc/classes/Input.xml doc/classes/InputEvent.xml
-#: doc/classes/InputEventAction.xml doc/classes/Label.xml
-#: doc/classes/Particles2D.xml doc/classes/Timer.xml
+#: doc/classes/InputEventAction.xml doc/classes/Label.xml doc/classes/Timer.xml
#: doc/classes/VisibilityNotifier2D.xml
msgid "2D Dodge The Creeps Demo"
msgstr ""
@@ -7082,7 +7110,10 @@ msgid ""
"var array = []\n"
"array.resize(10)\n"
"array.fill(0) # Initialize the 10 elements to 0.\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] If [code]value[/code] is of a reference type ([Object]-derived, "
+"[Array], [Dictionary], etc.) then the array is filled with the references to "
+"the same object, i.e. no duplicates are created."
msgstr ""
#: doc/classes/Array.xml doc/classes/PoolByteArray.xml
@@ -7267,6 +7298,9 @@ msgstr ""
#: doc/classes/Array.xml
msgid ""
"Sorts the array.\n"
+"[b]Note:[/b] The sorting algorithm used is not [url=https://en.wikipedia.org/"
+"wiki/Sorting_algorithm#Stability]stable[/url]. This means that values "
+"considered equal may have their order changed when using [method sort].\n"
"[b]Note:[/b] Strings are sorted in alphabetical order (as opposed to natural "
"order). This may lead to unexpected behavior when sorting an array of "
"strings ending with a sequence of numbers. Consider the following example:\n"
@@ -7286,9 +7320,13 @@ msgid ""
"For two elements [code]a[/code] and [code]b[/code], if the given method "
"returns [code]true[/code], element [code]b[/code] will be after element "
"[code]a[/code] in the array.\n"
+"[b]Note:[/b] The sorting algorithm used is not [url=https://en.wikipedia.org/"
+"wiki/Sorting_algorithm#Stability]stable[/url]. This means that values "
+"considered equal may have their order changed when using [method "
+"sort_custom].\n"
"[b]Note:[/b] You cannot randomize the return value as the heapsort algorithm "
-"expects a deterministic result. Doing so will result in unexpected "
-"behavior.\n"
+"expects a deterministic result. Randomizing the return value will result in "
+"unexpected behavior.\n"
"[codeblock]\n"
"class MyCustomSorter:\n"
" static func sort_ascending(a, b):\n"
@@ -9926,10 +9964,9 @@ msgstr ""
#: doc/classes/AudioStreamGeneratorPlayback.xml
msgid ""
-"Returns the number of audio data frames left to play. If this returned "
-"number reaches [code]0[/code], the audio will stop playing until frames are "
-"added again. Therefore, make sure your script can always generate and push "
-"new audio frames fast enough to avoid audio cracking."
+"Returns the number of frames that can be pushed to the audio sample data "
+"buffer without overflowing it. If the result is [code]0[/code], the buffer "
+"is full."
msgstr ""
#: doc/classes/AudioStreamGeneratorPlayback.xml
@@ -10461,14 +10498,14 @@ msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
"Node for back-buffering the currently-displayed screen. The region defined "
-"in the BackBufferCopy node is buffered with the content of the screen it "
+"in the [BackBufferCopy] node is buffered with the content of the screen it "
"covers, or the entire screen according to the copy mode set. Use the "
"[code]texture(SCREEN_TEXTURE, ...)[/code] function in your shader scripts to "
"access the buffer.\n"
"[b]Note:[/b] Since this node inherits from [Node2D] (and not [Control]), "
"anchors and margins won't apply to child [Control]-derived nodes. This can "
"be problematic when resizing the window. To avoid this, add [Control]-"
-"derived nodes as [i]siblings[/i] to the BackBufferCopy node instead of "
+"derived nodes as [i]siblings[/i] to the [BackBufferCopy] node instead of "
"adding them as children."
msgstr ""
@@ -10478,22 +10515,22 @@ msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
-"The area covered by the BackBufferCopy. Only used if [member copy_mode] is "
+"The area covered by the [BackBufferCopy]. Only used if [member copy_mode] is "
"[constant COPY_MODE_RECT]."
msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
-"Disables the buffering mode. This means the BackBufferCopy node will "
+"Disables the buffering mode. This means the [BackBufferCopy] node will "
"directly use the portion of screen it covers."
msgstr ""
#: doc/classes/BackBufferCopy.xml
-msgid "BackBufferCopy buffers a rectangular region."
+msgid "[BackBufferCopy] buffers a rectangular region."
msgstr ""
#: doc/classes/BackBufferCopy.xml
-msgid "BackBufferCopy buffers the entire screen."
+msgid "[BackBufferCopy] buffers the entire screen."
msgstr ""
#: doc/classes/BakedLightmap.xml
@@ -19273,6 +19310,14 @@ msgid "Cylinder shape for collisions."
msgstr ""
#: doc/classes/CylinderShape.xml
+msgid ""
+"Cylinder shape for collisions.\n"
+"[b]Note:[/b] When using GodotPhysics instead of the default Bullet physics "
+"engine, there are several known bugs with cylinder collision shapes. Using "
+"[CapsuleShape] or [BoxShape] instead is recommended."
+msgstr ""
+
+#: doc/classes/CylinderShape.xml
msgid "The cylinder's height."
msgstr ""
@@ -22105,7 +22150,10 @@ msgid ""
"[/codeblock]\n"
"[b]Note:[/b] The script is run in the Editor context, which means the output "
"is visible in the console window started with the Editor (stdout) instead of "
-"the usual Godot [b]Output[/b] dock."
+"the usual Godot [b]Output[/b] dock.\n"
+"[b]Note:[/b] EditorScript is reference counted, meaning it is destroyed when "
+"nothing references it. This can cause errors during asynchronous operations "
+"if there are no references to the script."
msgstr ""
#: doc/classes/EditorScript.xml
@@ -32820,7 +32868,9 @@ msgid ""
"The size of the light in Godot units. Only considered in baked lightmaps and "
"only if [member light_bake_mode] is set to [constant BAKE_ALL]. Increasing "
"this value will make the shadows appear blurrier. This can be used to "
-"simulate area lights to an extent."
+"simulate area lights to an extent.\n"
+"[b]Note:[/b] [member light_size] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/Light.xml
@@ -36118,7 +36168,10 @@ msgid ""
"use the [method get_next_location] function once every physics frame to "
"update the internal path logic of the NavigationAgent. The returned vector "
"position from this function should be used as the next movement position for "
-"the agent's parent Node."
+"the agent's parent Node.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues."
msgstr ""
#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
@@ -36366,7 +36419,10 @@ msgid ""
"use the [method get_next_location] function once every physics frame to "
"update the internal path logic of the NavigationAgent. The returned vector "
"position from this function should be used as the next movement position for "
-"the agent's parent Node."
+"the agent's parent Node.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues."
msgstr ""
#: doc/classes/NavigationAgent2D.xml
@@ -37076,6 +37132,9 @@ msgid ""
"modified velocity as-is might lead to pushing and agent outside of a "
"navigable area. This is a limitation of the collision avoidance system, any "
"more complex situation may require the use of the physics engine.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues.\n"
"This server keeps tracks of any call and executes them during the sync "
"phase. This means that you can request any change to the map, using any "
"thread, without worrying."
@@ -39882,7 +39941,9 @@ msgid ""
"The light's radius. Note that the effectively lit area may appear to be "
"smaller depending on the [member omni_attenuation] in use. No matter the "
"[member omni_attenuation] in use, the light will never reach anything "
-"outside this radius."
+"outside this radius.\n"
+"[b]Note:[/b] [member omni_range] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -40393,11 +40454,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] cache data directory according to the operating "
-"system's standards. On desktop platforms, this path can be overridden by "
-"setting the [code]XDG_CACHE_HOME[/code] environment variable before starting "
-"the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in "
-"Godot projects[/url] in the documentation for more information. See also "
-"[method get_config_dir] and [method get_data_dir].\n"
+"system's standards. On Linux, this path can be overridden by setting the "
+"[code]XDG_CACHE_HOME[/code] environment variable before starting the "
+"project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot "
+"projects[/url] in the documentation for more information. See also [method "
+"get_config_dir] and [method get_data_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -40431,11 +40492,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] user configuration directory according to the "
-"operating system's standards. On desktop platforms, this path can be "
-"overridden by setting the [code]XDG_CONFIG_HOME[/code] environment variable "
-"before starting the project. See [url=$DOCS_URL/tutorials/io/data_paths."
-"html]File paths in Godot projects[/url] in the documentation for more "
-"information. See also [method get_cache_dir] and [method get_data_dir].\n"
+"operating system's standards. On Linux, this path can be overridden by "
+"setting the [code]XDG_CONFIG_HOME[/code] environment variable before "
+"starting the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File "
+"paths in Godot projects[/url] in the documentation for more information. See "
+"also [method get_cache_dir] and [method get_data_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -40457,11 +40518,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] user data directory according to the operating "
-"system's standards. On desktop platforms, this path can be overridden by "
-"setting the [code]XDG_DATA_HOME[/code] environment variable before starting "
-"the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in "
-"Godot projects[/url] in the documentation for more information. See also "
-"[method get_cache_dir] and [method get_config_dir].\n"
+"system's standards. On Linux, this path can be overridden by setting the "
+"[code]XDG_DATA_HOME[/code] environment variable before starting the project. "
+"See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot "
+"projects[/url] in the documentation for more information. See also [method "
+"get_cache_dir] and [method get_config_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -42308,6 +42369,16 @@ msgid "Particle systems (2D)"
msgstr ""
#: doc/classes/Particles2D.xml
+msgid "2D Particles Demo"
+msgstr ""
+
+#: doc/classes/Particles2D.xml
+msgid ""
+"2D Dodge The Creeps Demo (uses GPUParticles2D for the trail behind the "
+"player)"
+msgstr ""
+
+#: doc/classes/Particles2D.xml
msgid "Returns a rectangle containing the positions of all existing particles."
msgstr ""
@@ -49900,15 +49971,22 @@ msgstr ""
#: doc/classes/ProjectSettings.xml
msgid ""
"If [code]true[/code], uses a fast post-processing filter to make banding "
-"significantly less visible. In some cases, debanding may introduce a "
-"slightly noticeable dithering pattern. It's recommended to enable debanding "
-"only when actually needed since the dithering pattern will make lossless-"
-"compressed screenshots larger.\n"
+"significantly less visible in 3D. 2D rendering is [i]not[/i] affected by "
+"debanding unless the [member Environment.background_mode] is [constant "
+"Environment.BG_CANVAS]. In this case, [member rendering/quality/"
+"intended_usage/framebuffer_allocation] must also be set to [b]3D[/b].\n"
+"In some cases, debanding may introduce a slightly noticeable dithering "
+"pattern. It's recommended to enable debanding only when actually needed "
+"since the dithering pattern will make lossless-compressed screenshots "
+"larger.\n"
"[b]Note:[/b] Only available on the GLES3 backend. [member rendering/quality/"
"depth/hdr] must also be [code]true[/code] for debanding to be effective.\n"
"[b]Note:[/b] There are known issues with debanding breaking rendering on "
"mobile platforms. Due to this, it is recommended to leave this option "
-"disabled when targeting mobile platforms."
+"disabled when targeting mobile platforms.\n"
+"[b]Note:[/b] This property is only read when the project starts. To set "
+"debanding at run-time, set [member Viewport.debanding] on the root "
+"[Viewport] instead."
msgstr ""
#: doc/classes/ProjectSettings.xml
@@ -51504,17 +51582,28 @@ msgstr ""
#: modules/regex/doc_classes/RegEx.xml
msgid ""
"Searches the text for the compiled pattern. Returns a [RegExMatch] container "
-"of the first matching result if found, otherwise [code]null[/code]. The "
-"region to search within can be specified without modifying where the start "
-"and end anchor would be."
+"of the first matching result if found, otherwise [code]null[/code].\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegEx.xml
msgid ""
"Searches the text for the compiled pattern. Returns an array of [RegExMatch] "
"containers for each non-overlapping result. If no results were found, an "
-"empty array is returned instead. The region to search within can be "
-"specified without modifying where the start and end anchor would be."
+"empty array is returned instead.\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegEx.xml
@@ -51523,8 +51612,14 @@ msgid ""
"specified string. Escapes and backreferences such as [code]$1[/code] and "
"[code]$name[/code] are expanded and resolved. By default, only the first "
"instance is replaced, but it can be changed for all instances (global "
-"replacement). The region to search within can be specified without modifying "
-"where the start and end anchor would be."
+"replacement).\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegExMatch.xml
@@ -54239,7 +54334,11 @@ msgid "Call a group immediately (calls are normally made on idle)."
msgstr ""
#: doc/classes/SceneTree.xml
-msgid "Call a group only once even if the call is executed many times."
+msgid ""
+"Call a group only once even if the call is executed many times.\n"
+"[b]Note:[/b] Arguments are not taken into account when deciding whether the "
+"call is unique or not. Therefore when the same method is called with "
+"different arguments, only the first call will be performed."
msgstr ""
#: doc/classes/SceneTree.xml
@@ -56076,7 +56175,9 @@ msgid ""
"[b]Note:[/b] Mixed negative scales in 3D are not decomposable from the "
"transformation matrix. Due to the way scale is represented with "
"transformation matrices in Godot, the scale values will either be all "
-"positive or all negative."
+"positive or all negative.\n"
+"[b]Note:[/b] Not all nodes are visually scaled by the [member scale] "
+"property. For example, [Light]s are not visually affected by [member scale]."
msgstr ""
#: doc/classes/Spatial.xml
@@ -57454,7 +57555,10 @@ msgid ""
msgstr ""
#: doc/classes/SpotLight.xml
-msgid "The spotlight's angle in degrees."
+msgid ""
+"The spotlight's angle in degrees.\n"
+"[b]Note:[/b] [member spot_angle] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/SpotLight.xml
@@ -57470,7 +57574,9 @@ msgid ""
"The maximal range that can be reached by the spotlight. Note that the "
"effectively lit area may appear to be smaller depending on the [member "
"spot_attenuation] in use. No matter the [member spot_attenuation] in use, "
-"the light will never reach anything outside this range."
+"the light will never reach anything outside this range.\n"
+"[b]Note:[/b] [member spot_range] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/SpringArm.xml
@@ -66707,10 +66813,15 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
"If [code]true[/code], uses a fast post-processing filter to make banding "
-"significantly less visible. In some cases, debanding may introduce a "
-"slightly noticeable dithering pattern. It's recommended to enable debanding "
-"only when actually needed since the dithering pattern will make lossless-"
-"compressed screenshots larger.\n"
+"significantly less visible in 3D. 2D rendering is [i]not[/i] affected by "
+"debanding unless the [member Environment.background_mode] is [constant "
+"Environment.BG_CANVAS]. In this case, [member usage] must also be set to "
+"[constant USAGE_3D]. See also [member ProjectSettings.rendering/quality/"
+"filters/use_debanding].\n"
+"In some cases, debanding may introduce a slightly noticeable dithering "
+"pattern. It's recommended to enable debanding only when actually needed "
+"since the dithering pattern will make lossless-compressed screenshots "
+"larger.\n"
"[b]Note:[/b] Only available on the GLES3 backend. [member hdr] must also be "
"[code]true[/code] for debanding to be effective."
msgstr ""
@@ -66721,8 +66832,8 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
-"If [code]true[/code], the viewport will disable 3D rendering. For actual "
-"disabling use [code]usage[/code]."
+"If [code]true[/code], the viewport will disable 3D rendering. To actually "
+"disable allocation of 3D buffers, set [member usage] instead."
msgstr ""
#: doc/classes/Viewport.xml
@@ -66874,7 +66985,9 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
-"The rendering mode of viewport.\n"
+"The viewport's rendering mode. This controls which buffers are allocated for "
+"the viewport (2D only, or 2D + 3D). 2D-only options can reduce memory usage "
+"and improve performance slightly, especially on low-end devices.\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."
@@ -67406,6 +67519,22 @@ msgid ""
"render object this [VisualInstance] is set to."
msgstr ""
+#: doc/classes/VisualInstance.xml
+msgid ""
+"The sorting offset used by this [VisualInstance]. Adjusting it to a higher "
+"value will make the [VisualInstance] reliably draw on top of other "
+"[VisualInstance]s that are otherwise positioned at the same spot."
+msgstr ""
+
+#: doc/classes/VisualInstance.xml
+msgid ""
+"If [code]true[/code], the object is sorted based on the [AABB] center. "
+"Sorted based on the global position otherwise.\n"
+"The [AABB] center based sorting is generally more accurate for 3D models. "
+"The position based sorting instead allows to better control the drawing "
+"order when working with [Particles] and [CPUParticles]."
+msgstr ""
+
#: modules/visual_script/doc_classes/VisualScript.xml
msgid "A script implemented in the Visual Script programming environment."
msgstr ""
diff --git a/doc/translations/sr_Cyrl.po b/doc/translations/sr_Cyrl.po
index e202b72696..2846de07bb 100644
--- a/doc/translations/sr_Cyrl.po
+++ b/doc/translations/sr_Cyrl.po
@@ -487,7 +487,8 @@ msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
-"Returns an array of dictionaries representing the current call stack.\n"
+"Returns an array of dictionaries representing the current call stack. See "
+"also [method print_stack].\n"
"[codeblock]\n"
"func _ready():\n"
" foo()\n"
@@ -502,7 +503,11 @@ msgid ""
"[codeblock]\n"
"[{function:bar, line:12, source:res://script.gd}, {function:foo, line:9, "
"source:res://script.gd}, {function:_ready, line:6, source:res://script.gd}]\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] [method get_stack] only works if the running instance is "
+"connected to a debugging server (i.e. an editor instance). [method "
+"get_stack] will not work in projects exported in release mode, or in "
+"projects exported in debug mode if not connected to a debugging server."
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -875,12 +880,16 @@ msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
-"Prints a stack track at code location, only works when running with debugger "
-"turned on.\n"
+"Prints a stack trace at the current code location. See also [method "
+"get_stack].\n"
"Output in the console would look something like this:\n"
"[codeblock]\n"
"Frame 0 - res://test.gd:16 in function '_process'\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] [method print_stack] only works if the running instance is "
+"connected to a debugging server (i.e. an editor instance). [method "
+"print_stack] will not work in projects exported in release mode, or in "
+"projects exported in debug mode if not connected to a debugging server."
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -3491,6 +3500,26 @@ msgid "Hints that an image is compressed using lossless compression."
msgstr ""
#: doc/classes/@GlobalScope.xml
+msgid ""
+"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:\n"
+"[codeblock]\n"
+"hint_string = \"%s:\" % [TYPE_INT] # Array of inteters.\n"
+"hint_string = \"%s:%s:\" % [TYPE_ARRAY, TYPE_REAL] # Two-dimensional array "
+"of floats.\n"
+"hint_string = \"%s/%s:Resource\" % [TYPE_OBJECT, TYPE_OBJECT] # Array of "
+"resources.\n"
+"hint_string = \"%s:%s/%s:Resource\" % [TYPE_ARRAY, TYPE_OBJECT, TYPE_OBJECT] "
+"# Two-dimensional array of resources.\n"
+"[/codeblock]\n"
+"[b]Note:[/b] The final colon is required to specify for properly detecting "
+"built-in types."
+msgstr ""
+
+#: doc/classes/@GlobalScope.xml
msgid "The property is serialized and saved in the scene file (default)."
msgstr ""
@@ -4175,8 +4204,7 @@ msgstr ""
#: doc/classes/AudioStreamPlayer.xml doc/classes/Button.xml
#: doc/classes/CanvasLayer.xml doc/classes/CollisionShape2D.xml
#: doc/classes/ColorRect.xml doc/classes/Input.xml doc/classes/InputEvent.xml
-#: doc/classes/InputEventAction.xml doc/classes/Label.xml
-#: doc/classes/Particles2D.xml doc/classes/Timer.xml
+#: doc/classes/InputEventAction.xml doc/classes/Label.xml doc/classes/Timer.xml
#: doc/classes/VisibilityNotifier2D.xml
msgid "2D Dodge The Creeps Demo"
msgstr ""
@@ -7093,7 +7121,10 @@ msgid ""
"var array = []\n"
"array.resize(10)\n"
"array.fill(0) # Initialize the 10 elements to 0.\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] If [code]value[/code] is of a reference type ([Object]-derived, "
+"[Array], [Dictionary], etc.) then the array is filled with the references to "
+"the same object, i.e. no duplicates are created."
msgstr ""
#: doc/classes/Array.xml doc/classes/PoolByteArray.xml
@@ -7278,6 +7309,9 @@ msgstr ""
#: doc/classes/Array.xml
msgid ""
"Sorts the array.\n"
+"[b]Note:[/b] The sorting algorithm used is not [url=https://en.wikipedia.org/"
+"wiki/Sorting_algorithm#Stability]stable[/url]. This means that values "
+"considered equal may have their order changed when using [method sort].\n"
"[b]Note:[/b] Strings are sorted in alphabetical order (as opposed to natural "
"order). This may lead to unexpected behavior when sorting an array of "
"strings ending with a sequence of numbers. Consider the following example:\n"
@@ -7297,9 +7331,13 @@ msgid ""
"For two elements [code]a[/code] and [code]b[/code], if the given method "
"returns [code]true[/code], element [code]b[/code] will be after element "
"[code]a[/code] in the array.\n"
+"[b]Note:[/b] The sorting algorithm used is not [url=https://en.wikipedia.org/"
+"wiki/Sorting_algorithm#Stability]stable[/url]. This means that values "
+"considered equal may have their order changed when using [method "
+"sort_custom].\n"
"[b]Note:[/b] You cannot randomize the return value as the heapsort algorithm "
-"expects a deterministic result. Doing so will result in unexpected "
-"behavior.\n"
+"expects a deterministic result. Randomizing the return value will result in "
+"unexpected behavior.\n"
"[codeblock]\n"
"class MyCustomSorter:\n"
" static func sort_ascending(a, b):\n"
@@ -9937,10 +9975,9 @@ msgstr ""
#: doc/classes/AudioStreamGeneratorPlayback.xml
msgid ""
-"Returns the number of audio data frames left to play. If this returned "
-"number reaches [code]0[/code], the audio will stop playing until frames are "
-"added again. Therefore, make sure your script can always generate and push "
-"new audio frames fast enough to avoid audio cracking."
+"Returns the number of frames that can be pushed to the audio sample data "
+"buffer without overflowing it. If the result is [code]0[/code], the buffer "
+"is full."
msgstr ""
#: doc/classes/AudioStreamGeneratorPlayback.xml
@@ -10472,14 +10509,14 @@ msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
"Node for back-buffering the currently-displayed screen. The region defined "
-"in the BackBufferCopy node is buffered with the content of the screen it "
+"in the [BackBufferCopy] node is buffered with the content of the screen it "
"covers, or the entire screen according to the copy mode set. Use the "
"[code]texture(SCREEN_TEXTURE, ...)[/code] function in your shader scripts to "
"access the buffer.\n"
"[b]Note:[/b] Since this node inherits from [Node2D] (and not [Control]), "
"anchors and margins won't apply to child [Control]-derived nodes. This can "
"be problematic when resizing the window. To avoid this, add [Control]-"
-"derived nodes as [i]siblings[/i] to the BackBufferCopy node instead of "
+"derived nodes as [i]siblings[/i] to the [BackBufferCopy] node instead of "
"adding them as children."
msgstr ""
@@ -10489,22 +10526,22 @@ msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
-"The area covered by the BackBufferCopy. Only used if [member copy_mode] is "
+"The area covered by the [BackBufferCopy]. Only used if [member copy_mode] is "
"[constant COPY_MODE_RECT]."
msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
-"Disables the buffering mode. This means the BackBufferCopy node will "
+"Disables the buffering mode. This means the [BackBufferCopy] node will "
"directly use the portion of screen it covers."
msgstr ""
#: doc/classes/BackBufferCopy.xml
-msgid "BackBufferCopy buffers a rectangular region."
+msgid "[BackBufferCopy] buffers a rectangular region."
msgstr ""
#: doc/classes/BackBufferCopy.xml
-msgid "BackBufferCopy buffers the entire screen."
+msgid "[BackBufferCopy] buffers the entire screen."
msgstr ""
#: doc/classes/BakedLightmap.xml
@@ -19284,6 +19321,14 @@ msgid "Cylinder shape for collisions."
msgstr ""
#: doc/classes/CylinderShape.xml
+msgid ""
+"Cylinder shape for collisions.\n"
+"[b]Note:[/b] When using GodotPhysics instead of the default Bullet physics "
+"engine, there are several known bugs with cylinder collision shapes. Using "
+"[CapsuleShape] or [BoxShape] instead is recommended."
+msgstr ""
+
+#: doc/classes/CylinderShape.xml
msgid "The cylinder's height."
msgstr ""
@@ -22116,7 +22161,10 @@ msgid ""
"[/codeblock]\n"
"[b]Note:[/b] The script is run in the Editor context, which means the output "
"is visible in the console window started with the Editor (stdout) instead of "
-"the usual Godot [b]Output[/b] dock."
+"the usual Godot [b]Output[/b] dock.\n"
+"[b]Note:[/b] EditorScript is reference counted, meaning it is destroyed when "
+"nothing references it. This can cause errors during asynchronous operations "
+"if there are no references to the script."
msgstr ""
#: doc/classes/EditorScript.xml
@@ -32831,7 +32879,9 @@ msgid ""
"The size of the light in Godot units. Only considered in baked lightmaps and "
"only if [member light_bake_mode] is set to [constant BAKE_ALL]. Increasing "
"this value will make the shadows appear blurrier. This can be used to "
-"simulate area lights to an extent."
+"simulate area lights to an extent.\n"
+"[b]Note:[/b] [member light_size] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/Light.xml
@@ -36129,7 +36179,10 @@ msgid ""
"use the [method get_next_location] function once every physics frame to "
"update the internal path logic of the NavigationAgent. The returned vector "
"position from this function should be used as the next movement position for "
-"the agent's parent Node."
+"the agent's parent Node.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues."
msgstr ""
#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
@@ -36377,7 +36430,10 @@ msgid ""
"use the [method get_next_location] function once every physics frame to "
"update the internal path logic of the NavigationAgent. The returned vector "
"position from this function should be used as the next movement position for "
-"the agent's parent Node."
+"the agent's parent Node.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues."
msgstr ""
#: doc/classes/NavigationAgent2D.xml
@@ -37087,6 +37143,9 @@ msgid ""
"modified velocity as-is might lead to pushing and agent outside of a "
"navigable area. This is a limitation of the collision avoidance system, any "
"more complex situation may require the use of the physics engine.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues.\n"
"This server keeps tracks of any call and executes them during the sync "
"phase. This means that you can request any change to the map, using any "
"thread, without worrying."
@@ -39893,7 +39952,9 @@ msgid ""
"The light's radius. Note that the effectively lit area may appear to be "
"smaller depending on the [member omni_attenuation] in use. No matter the "
"[member omni_attenuation] in use, the light will never reach anything "
-"outside this radius."
+"outside this radius.\n"
+"[b]Note:[/b] [member omni_range] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -40404,11 +40465,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] cache data directory according to the operating "
-"system's standards. On desktop platforms, this path can be overridden by "
-"setting the [code]XDG_CACHE_HOME[/code] environment variable before starting "
-"the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in "
-"Godot projects[/url] in the documentation for more information. See also "
-"[method get_config_dir] and [method get_data_dir].\n"
+"system's standards. On Linux, this path can be overridden by setting the "
+"[code]XDG_CACHE_HOME[/code] environment variable before starting the "
+"project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot "
+"projects[/url] in the documentation for more information. See also [method "
+"get_config_dir] and [method get_data_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -40442,11 +40503,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] user configuration directory according to the "
-"operating system's standards. On desktop platforms, this path can be "
-"overridden by setting the [code]XDG_CONFIG_HOME[/code] environment variable "
-"before starting the project. See [url=$DOCS_URL/tutorials/io/data_paths."
-"html]File paths in Godot projects[/url] in the documentation for more "
-"information. See also [method get_cache_dir] and [method get_data_dir].\n"
+"operating system's standards. On Linux, this path can be overridden by "
+"setting the [code]XDG_CONFIG_HOME[/code] environment variable before "
+"starting the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File "
+"paths in Godot projects[/url] in the documentation for more information. See "
+"also [method get_cache_dir] and [method get_data_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -40468,11 +40529,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] user data directory according to the operating "
-"system's standards. On desktop platforms, this path can be overridden by "
-"setting the [code]XDG_DATA_HOME[/code] environment variable before starting "
-"the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in "
-"Godot projects[/url] in the documentation for more information. See also "
-"[method get_cache_dir] and [method get_config_dir].\n"
+"system's standards. On Linux, this path can be overridden by setting the "
+"[code]XDG_DATA_HOME[/code] environment variable before starting the project. "
+"See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot "
+"projects[/url] in the documentation for more information. See also [method "
+"get_cache_dir] and [method get_config_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -42319,6 +42380,16 @@ msgid "Particle systems (2D)"
msgstr ""
#: doc/classes/Particles2D.xml
+msgid "2D Particles Demo"
+msgstr ""
+
+#: doc/classes/Particles2D.xml
+msgid ""
+"2D Dodge The Creeps Demo (uses GPUParticles2D for the trail behind the "
+"player)"
+msgstr ""
+
+#: doc/classes/Particles2D.xml
msgid "Returns a rectangle containing the positions of all existing particles."
msgstr ""
@@ -49911,15 +49982,22 @@ msgstr ""
#: doc/classes/ProjectSettings.xml
msgid ""
"If [code]true[/code], uses a fast post-processing filter to make banding "
-"significantly less visible. In some cases, debanding may introduce a "
-"slightly noticeable dithering pattern. It's recommended to enable debanding "
-"only when actually needed since the dithering pattern will make lossless-"
-"compressed screenshots larger.\n"
+"significantly less visible in 3D. 2D rendering is [i]not[/i] affected by "
+"debanding unless the [member Environment.background_mode] is [constant "
+"Environment.BG_CANVAS]. In this case, [member rendering/quality/"
+"intended_usage/framebuffer_allocation] must also be set to [b]3D[/b].\n"
+"In some cases, debanding may introduce a slightly noticeable dithering "
+"pattern. It's recommended to enable debanding only when actually needed "
+"since the dithering pattern will make lossless-compressed screenshots "
+"larger.\n"
"[b]Note:[/b] Only available on the GLES3 backend. [member rendering/quality/"
"depth/hdr] must also be [code]true[/code] for debanding to be effective.\n"
"[b]Note:[/b] There are known issues with debanding breaking rendering on "
"mobile platforms. Due to this, it is recommended to leave this option "
-"disabled when targeting mobile platforms."
+"disabled when targeting mobile platforms.\n"
+"[b]Note:[/b] This property is only read when the project starts. To set "
+"debanding at run-time, set [member Viewport.debanding] on the root "
+"[Viewport] instead."
msgstr ""
#: doc/classes/ProjectSettings.xml
@@ -51515,17 +51593,28 @@ msgstr ""
#: modules/regex/doc_classes/RegEx.xml
msgid ""
"Searches the text for the compiled pattern. Returns a [RegExMatch] container "
-"of the first matching result if found, otherwise [code]null[/code]. The "
-"region to search within can be specified without modifying where the start "
-"and end anchor would be."
+"of the first matching result if found, otherwise [code]null[/code].\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegEx.xml
msgid ""
"Searches the text for the compiled pattern. Returns an array of [RegExMatch] "
"containers for each non-overlapping result. If no results were found, an "
-"empty array is returned instead. The region to search within can be "
-"specified without modifying where the start and end anchor would be."
+"empty array is returned instead.\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegEx.xml
@@ -51534,8 +51623,14 @@ msgid ""
"specified string. Escapes and backreferences such as [code]$1[/code] and "
"[code]$name[/code] are expanded and resolved. By default, only the first "
"instance is replaced, but it can be changed for all instances (global "
-"replacement). The region to search within can be specified without modifying "
-"where the start and end anchor would be."
+"replacement).\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegExMatch.xml
@@ -54250,7 +54345,11 @@ msgid "Call a group immediately (calls are normally made on idle)."
msgstr ""
#: doc/classes/SceneTree.xml
-msgid "Call a group only once even if the call is executed many times."
+msgid ""
+"Call a group only once even if the call is executed many times.\n"
+"[b]Note:[/b] Arguments are not taken into account when deciding whether the "
+"call is unique or not. Therefore when the same method is called with "
+"different arguments, only the first call will be performed."
msgstr ""
#: doc/classes/SceneTree.xml
@@ -56087,7 +56186,9 @@ msgid ""
"[b]Note:[/b] Mixed negative scales in 3D are not decomposable from the "
"transformation matrix. Due to the way scale is represented with "
"transformation matrices in Godot, the scale values will either be all "
-"positive or all negative."
+"positive or all negative.\n"
+"[b]Note:[/b] Not all nodes are visually scaled by the [member scale] "
+"property. For example, [Light]s are not visually affected by [member scale]."
msgstr ""
#: doc/classes/Spatial.xml
@@ -57465,7 +57566,10 @@ msgid ""
msgstr ""
#: doc/classes/SpotLight.xml
-msgid "The spotlight's angle in degrees."
+msgid ""
+"The spotlight's angle in degrees.\n"
+"[b]Note:[/b] [member spot_angle] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/SpotLight.xml
@@ -57481,7 +57585,9 @@ msgid ""
"The maximal range that can be reached by the spotlight. Note that the "
"effectively lit area may appear to be smaller depending on the [member "
"spot_attenuation] in use. No matter the [member spot_attenuation] in use, "
-"the light will never reach anything outside this range."
+"the light will never reach anything outside this range.\n"
+"[b]Note:[/b] [member spot_range] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/SpringArm.xml
@@ -66718,10 +66824,15 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
"If [code]true[/code], uses a fast post-processing filter to make banding "
-"significantly less visible. In some cases, debanding may introduce a "
-"slightly noticeable dithering pattern. It's recommended to enable debanding "
-"only when actually needed since the dithering pattern will make lossless-"
-"compressed screenshots larger.\n"
+"significantly less visible in 3D. 2D rendering is [i]not[/i] affected by "
+"debanding unless the [member Environment.background_mode] is [constant "
+"Environment.BG_CANVAS]. In this case, [member usage] must also be set to "
+"[constant USAGE_3D]. See also [member ProjectSettings.rendering/quality/"
+"filters/use_debanding].\n"
+"In some cases, debanding may introduce a slightly noticeable dithering "
+"pattern. It's recommended to enable debanding only when actually needed "
+"since the dithering pattern will make lossless-compressed screenshots "
+"larger.\n"
"[b]Note:[/b] Only available on the GLES3 backend. [member hdr] must also be "
"[code]true[/code] for debanding to be effective."
msgstr ""
@@ -66732,8 +66843,8 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
-"If [code]true[/code], the viewport will disable 3D rendering. For actual "
-"disabling use [code]usage[/code]."
+"If [code]true[/code], the viewport will disable 3D rendering. To actually "
+"disable allocation of 3D buffers, set [member usage] instead."
msgstr ""
#: doc/classes/Viewport.xml
@@ -66885,7 +66996,9 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
-"The rendering mode of viewport.\n"
+"The viewport's rendering mode. This controls which buffers are allocated for "
+"the viewport (2D only, or 2D + 3D). 2D-only options can reduce memory usage "
+"and improve performance slightly, especially on low-end devices.\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."
@@ -67417,6 +67530,22 @@ msgid ""
"render object this [VisualInstance] is set to."
msgstr ""
+#: doc/classes/VisualInstance.xml
+msgid ""
+"The sorting offset used by this [VisualInstance]. Adjusting it to a higher "
+"value will make the [VisualInstance] reliably draw on top of other "
+"[VisualInstance]s that are otherwise positioned at the same spot."
+msgstr ""
+
+#: doc/classes/VisualInstance.xml
+msgid ""
+"If [code]true[/code], the object is sorted based on the [AABB] center. "
+"Sorted based on the global position otherwise.\n"
+"The [AABB] center based sorting is generally more accurate for 3D models. "
+"The position based sorting instead allows to better control the drawing "
+"order when working with [Particles] and [CPUParticles]."
+msgstr ""
+
#: modules/visual_script/doc_classes/VisualScript.xml
msgid "A script implemented in the Visual Script programming environment."
msgstr ""
diff --git a/doc/translations/sv.po b/doc/translations/sv.po
index 1bd56a7518..65cad9bf8a 100644
--- a/doc/translations/sv.po
+++ b/doc/translations/sv.po
@@ -477,7 +477,8 @@ msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
-"Returns an array of dictionaries representing the current call stack.\n"
+"Returns an array of dictionaries representing the current call stack. See "
+"also [method print_stack].\n"
"[codeblock]\n"
"func _ready():\n"
" foo()\n"
@@ -492,7 +493,11 @@ msgid ""
"[codeblock]\n"
"[{function:bar, line:12, source:res://script.gd}, {function:foo, line:9, "
"source:res://script.gd}, {function:_ready, line:6, source:res://script.gd}]\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] [method get_stack] only works if the running instance is "
+"connected to a debugging server (i.e. an editor instance). [method "
+"get_stack] will not work in projects exported in release mode, or in "
+"projects exported in debug mode if not connected to a debugging server."
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -865,12 +870,16 @@ msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
-"Prints a stack track at code location, only works when running with debugger "
-"turned on.\n"
+"Prints a stack trace at the current code location. See also [method "
+"get_stack].\n"
"Output in the console would look something like this:\n"
"[codeblock]\n"
"Frame 0 - res://test.gd:16 in function '_process'\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] [method print_stack] only works if the running instance is "
+"connected to a debugging server (i.e. an editor instance). [method "
+"print_stack] will not work in projects exported in release mode, or in "
+"projects exported in debug mode if not connected to a debugging server."
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -3481,6 +3490,26 @@ msgid "Hints that an image is compressed using lossless compression."
msgstr ""
#: doc/classes/@GlobalScope.xml
+msgid ""
+"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:\n"
+"[codeblock]\n"
+"hint_string = \"%s:\" % [TYPE_INT] # Array of inteters.\n"
+"hint_string = \"%s:%s:\" % [TYPE_ARRAY, TYPE_REAL] # Two-dimensional array "
+"of floats.\n"
+"hint_string = \"%s/%s:Resource\" % [TYPE_OBJECT, TYPE_OBJECT] # Array of "
+"resources.\n"
+"hint_string = \"%s:%s/%s:Resource\" % [TYPE_ARRAY, TYPE_OBJECT, TYPE_OBJECT] "
+"# Two-dimensional array of resources.\n"
+"[/codeblock]\n"
+"[b]Note:[/b] The final colon is required to specify for properly detecting "
+"built-in types."
+msgstr ""
+
+#: doc/classes/@GlobalScope.xml
msgid "The property is serialized and saved in the scene file (default)."
msgstr ""
@@ -4165,8 +4194,7 @@ msgstr ""
#: doc/classes/AudioStreamPlayer.xml doc/classes/Button.xml
#: doc/classes/CanvasLayer.xml doc/classes/CollisionShape2D.xml
#: doc/classes/ColorRect.xml doc/classes/Input.xml doc/classes/InputEvent.xml
-#: doc/classes/InputEventAction.xml doc/classes/Label.xml
-#: doc/classes/Particles2D.xml doc/classes/Timer.xml
+#: doc/classes/InputEventAction.xml doc/classes/Label.xml doc/classes/Timer.xml
#: doc/classes/VisibilityNotifier2D.xml
msgid "2D Dodge The Creeps Demo"
msgstr ""
@@ -7083,7 +7111,10 @@ msgid ""
"var array = []\n"
"array.resize(10)\n"
"array.fill(0) # Initialize the 10 elements to 0.\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] If [code]value[/code] is of a reference type ([Object]-derived, "
+"[Array], [Dictionary], etc.) then the array is filled with the references to "
+"the same object, i.e. no duplicates are created."
msgstr ""
#: doc/classes/Array.xml doc/classes/PoolByteArray.xml
@@ -7268,6 +7299,9 @@ msgstr ""
#: doc/classes/Array.xml
msgid ""
"Sorts the array.\n"
+"[b]Note:[/b] The sorting algorithm used is not [url=https://en.wikipedia.org/"
+"wiki/Sorting_algorithm#Stability]stable[/url]. This means that values "
+"considered equal may have their order changed when using [method sort].\n"
"[b]Note:[/b] Strings are sorted in alphabetical order (as opposed to natural "
"order). This may lead to unexpected behavior when sorting an array of "
"strings ending with a sequence of numbers. Consider the following example:\n"
@@ -7287,9 +7321,13 @@ msgid ""
"For two elements [code]a[/code] and [code]b[/code], if the given method "
"returns [code]true[/code], element [code]b[/code] will be after element "
"[code]a[/code] in the array.\n"
+"[b]Note:[/b] The sorting algorithm used is not [url=https://en.wikipedia.org/"
+"wiki/Sorting_algorithm#Stability]stable[/url]. This means that values "
+"considered equal may have their order changed when using [method "
+"sort_custom].\n"
"[b]Note:[/b] You cannot randomize the return value as the heapsort algorithm "
-"expects a deterministic result. Doing so will result in unexpected "
-"behavior.\n"
+"expects a deterministic result. Randomizing the return value will result in "
+"unexpected behavior.\n"
"[codeblock]\n"
"class MyCustomSorter:\n"
" static func sort_ascending(a, b):\n"
@@ -9927,10 +9965,9 @@ msgstr ""
#: doc/classes/AudioStreamGeneratorPlayback.xml
msgid ""
-"Returns the number of audio data frames left to play. If this returned "
-"number reaches [code]0[/code], the audio will stop playing until frames are "
-"added again. Therefore, make sure your script can always generate and push "
-"new audio frames fast enough to avoid audio cracking."
+"Returns the number of frames that can be pushed to the audio sample data "
+"buffer without overflowing it. If the result is [code]0[/code], the buffer "
+"is full."
msgstr ""
#: doc/classes/AudioStreamGeneratorPlayback.xml
@@ -10462,14 +10499,14 @@ msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
"Node for back-buffering the currently-displayed screen. The region defined "
-"in the BackBufferCopy node is buffered with the content of the screen it "
+"in the [BackBufferCopy] node is buffered with the content of the screen it "
"covers, or the entire screen according to the copy mode set. Use the "
"[code]texture(SCREEN_TEXTURE, ...)[/code] function in your shader scripts to "
"access the buffer.\n"
"[b]Note:[/b] Since this node inherits from [Node2D] (and not [Control]), "
"anchors and margins won't apply to child [Control]-derived nodes. This can "
"be problematic when resizing the window. To avoid this, add [Control]-"
-"derived nodes as [i]siblings[/i] to the BackBufferCopy node instead of "
+"derived nodes as [i]siblings[/i] to the [BackBufferCopy] node instead of "
"adding them as children."
msgstr ""
@@ -10479,22 +10516,22 @@ msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
-"The area covered by the BackBufferCopy. Only used if [member copy_mode] is "
+"The area covered by the [BackBufferCopy]. Only used if [member copy_mode] is "
"[constant COPY_MODE_RECT]."
msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
-"Disables the buffering mode. This means the BackBufferCopy node will "
+"Disables the buffering mode. This means the [BackBufferCopy] node will "
"directly use the portion of screen it covers."
msgstr ""
#: doc/classes/BackBufferCopy.xml
-msgid "BackBufferCopy buffers a rectangular region."
+msgid "[BackBufferCopy] buffers a rectangular region."
msgstr ""
#: doc/classes/BackBufferCopy.xml
-msgid "BackBufferCopy buffers the entire screen."
+msgid "[BackBufferCopy] buffers the entire screen."
msgstr ""
#: doc/classes/BakedLightmap.xml
@@ -19274,6 +19311,14 @@ msgid "Cylinder shape for collisions."
msgstr ""
#: doc/classes/CylinderShape.xml
+msgid ""
+"Cylinder shape for collisions.\n"
+"[b]Note:[/b] When using GodotPhysics instead of the default Bullet physics "
+"engine, there are several known bugs with cylinder collision shapes. Using "
+"[CapsuleShape] or [BoxShape] instead is recommended."
+msgstr ""
+
+#: doc/classes/CylinderShape.xml
msgid "The cylinder's height."
msgstr ""
@@ -22106,7 +22151,10 @@ msgid ""
"[/codeblock]\n"
"[b]Note:[/b] The script is run in the Editor context, which means the output "
"is visible in the console window started with the Editor (stdout) instead of "
-"the usual Godot [b]Output[/b] dock."
+"the usual Godot [b]Output[/b] dock.\n"
+"[b]Note:[/b] EditorScript is reference counted, meaning it is destroyed when "
+"nothing references it. This can cause errors during asynchronous operations "
+"if there are no references to the script."
msgstr ""
#: doc/classes/EditorScript.xml
@@ -32818,7 +32866,9 @@ msgid ""
"The size of the light in Godot units. Only considered in baked lightmaps and "
"only if [member light_bake_mode] is set to [constant BAKE_ALL]. Increasing "
"this value will make the shadows appear blurrier. This can be used to "
-"simulate area lights to an extent."
+"simulate area lights to an extent.\n"
+"[b]Note:[/b] [member light_size] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/Light.xml
@@ -36116,7 +36166,10 @@ msgid ""
"use the [method get_next_location] function once every physics frame to "
"update the internal path logic of the NavigationAgent. The returned vector "
"position from this function should be used as the next movement position for "
-"the agent's parent Node."
+"the agent's parent Node.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues."
msgstr ""
#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
@@ -36364,7 +36417,10 @@ msgid ""
"use the [method get_next_location] function once every physics frame to "
"update the internal path logic of the NavigationAgent. The returned vector "
"position from this function should be used as the next movement position for "
-"the agent's parent Node."
+"the agent's parent Node.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues."
msgstr ""
#: doc/classes/NavigationAgent2D.xml
@@ -37074,6 +37130,9 @@ msgid ""
"modified velocity as-is might lead to pushing and agent outside of a "
"navigable area. This is a limitation of the collision avoidance system, any "
"more complex situation may require the use of the physics engine.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues.\n"
"This server keeps tracks of any call and executes them during the sync "
"phase. This means that you can request any change to the map, using any "
"thread, without worrying."
@@ -39880,7 +39939,9 @@ msgid ""
"The light's radius. Note that the effectively lit area may appear to be "
"smaller depending on the [member omni_attenuation] in use. No matter the "
"[member omni_attenuation] in use, the light will never reach anything "
-"outside this radius."
+"outside this radius.\n"
+"[b]Note:[/b] [member omni_range] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -40391,11 +40452,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] cache data directory according to the operating "
-"system's standards. On desktop platforms, this path can be overridden by "
-"setting the [code]XDG_CACHE_HOME[/code] environment variable before starting "
-"the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in "
-"Godot projects[/url] in the documentation for more information. See also "
-"[method get_config_dir] and [method get_data_dir].\n"
+"system's standards. On Linux, this path can be overridden by setting the "
+"[code]XDG_CACHE_HOME[/code] environment variable before starting the "
+"project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot "
+"projects[/url] in the documentation for more information. See also [method "
+"get_config_dir] and [method get_data_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -40429,11 +40490,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] user configuration directory according to the "
-"operating system's standards. On desktop platforms, this path can be "
-"overridden by setting the [code]XDG_CONFIG_HOME[/code] environment variable "
-"before starting the project. See [url=$DOCS_URL/tutorials/io/data_paths."
-"html]File paths in Godot projects[/url] in the documentation for more "
-"information. See also [method get_cache_dir] and [method get_data_dir].\n"
+"operating system's standards. On Linux, this path can be overridden by "
+"setting the [code]XDG_CONFIG_HOME[/code] environment variable before "
+"starting the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File "
+"paths in Godot projects[/url] in the documentation for more information. See "
+"also [method get_cache_dir] and [method get_data_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -40455,11 +40516,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] user data directory according to the operating "
-"system's standards. On desktop platforms, this path can be overridden by "
-"setting the [code]XDG_DATA_HOME[/code] environment variable before starting "
-"the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in "
-"Godot projects[/url] in the documentation for more information. See also "
-"[method get_cache_dir] and [method get_config_dir].\n"
+"system's standards. On Linux, this path can be overridden by setting the "
+"[code]XDG_DATA_HOME[/code] environment variable before starting the project. "
+"See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot "
+"projects[/url] in the documentation for more information. See also [method "
+"get_cache_dir] and [method get_config_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -42306,6 +42367,16 @@ msgid "Particle systems (2D)"
msgstr ""
#: doc/classes/Particles2D.xml
+msgid "2D Particles Demo"
+msgstr ""
+
+#: doc/classes/Particles2D.xml
+msgid ""
+"2D Dodge The Creeps Demo (uses GPUParticles2D for the trail behind the "
+"player)"
+msgstr ""
+
+#: doc/classes/Particles2D.xml
msgid "Returns a rectangle containing the positions of all existing particles."
msgstr ""
@@ -49898,15 +49969,22 @@ msgstr ""
#: doc/classes/ProjectSettings.xml
msgid ""
"If [code]true[/code], uses a fast post-processing filter to make banding "
-"significantly less visible. In some cases, debanding may introduce a "
-"slightly noticeable dithering pattern. It's recommended to enable debanding "
-"only when actually needed since the dithering pattern will make lossless-"
-"compressed screenshots larger.\n"
+"significantly less visible in 3D. 2D rendering is [i]not[/i] affected by "
+"debanding unless the [member Environment.background_mode] is [constant "
+"Environment.BG_CANVAS]. In this case, [member rendering/quality/"
+"intended_usage/framebuffer_allocation] must also be set to [b]3D[/b].\n"
+"In some cases, debanding may introduce a slightly noticeable dithering "
+"pattern. It's recommended to enable debanding only when actually needed "
+"since the dithering pattern will make lossless-compressed screenshots "
+"larger.\n"
"[b]Note:[/b] Only available on the GLES3 backend. [member rendering/quality/"
"depth/hdr] must also be [code]true[/code] for debanding to be effective.\n"
"[b]Note:[/b] There are known issues with debanding breaking rendering on "
"mobile platforms. Due to this, it is recommended to leave this option "
-"disabled when targeting mobile platforms."
+"disabled when targeting mobile platforms.\n"
+"[b]Note:[/b] This property is only read when the project starts. To set "
+"debanding at run-time, set [member Viewport.debanding] on the root "
+"[Viewport] instead."
msgstr ""
#: doc/classes/ProjectSettings.xml
@@ -51502,17 +51580,28 @@ msgstr ""
#: modules/regex/doc_classes/RegEx.xml
msgid ""
"Searches the text for the compiled pattern. Returns a [RegExMatch] container "
-"of the first matching result if found, otherwise [code]null[/code]. The "
-"region to search within can be specified without modifying where the start "
-"and end anchor would be."
+"of the first matching result if found, otherwise [code]null[/code].\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegEx.xml
msgid ""
"Searches the text for the compiled pattern. Returns an array of [RegExMatch] "
"containers for each non-overlapping result. If no results were found, an "
-"empty array is returned instead. The region to search within can be "
-"specified without modifying where the start and end anchor would be."
+"empty array is returned instead.\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegEx.xml
@@ -51521,8 +51610,14 @@ msgid ""
"specified string. Escapes and backreferences such as [code]$1[/code] and "
"[code]$name[/code] are expanded and resolved. By default, only the first "
"instance is replaced, but it can be changed for all instances (global "
-"replacement). The region to search within can be specified without modifying "
-"where the start and end anchor would be."
+"replacement).\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegExMatch.xml
@@ -54237,7 +54332,11 @@ msgid "Call a group immediately (calls are normally made on idle)."
msgstr ""
#: doc/classes/SceneTree.xml
-msgid "Call a group only once even if the call is executed many times."
+msgid ""
+"Call a group only once even if the call is executed many times.\n"
+"[b]Note:[/b] Arguments are not taken into account when deciding whether the "
+"call is unique or not. Therefore when the same method is called with "
+"different arguments, only the first call will be performed."
msgstr ""
#: doc/classes/SceneTree.xml
@@ -56074,7 +56173,9 @@ msgid ""
"[b]Note:[/b] Mixed negative scales in 3D are not decomposable from the "
"transformation matrix. Due to the way scale is represented with "
"transformation matrices in Godot, the scale values will either be all "
-"positive or all negative."
+"positive or all negative.\n"
+"[b]Note:[/b] Not all nodes are visually scaled by the [member scale] "
+"property. For example, [Light]s are not visually affected by [member scale]."
msgstr ""
#: doc/classes/Spatial.xml
@@ -57452,7 +57553,10 @@ msgid ""
msgstr ""
#: doc/classes/SpotLight.xml
-msgid "The spotlight's angle in degrees."
+msgid ""
+"The spotlight's angle in degrees.\n"
+"[b]Note:[/b] [member spot_angle] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/SpotLight.xml
@@ -57468,7 +57572,9 @@ msgid ""
"The maximal range that can be reached by the spotlight. Note that the "
"effectively lit area may appear to be smaller depending on the [member "
"spot_attenuation] in use. No matter the [member spot_attenuation] in use, "
-"the light will never reach anything outside this range."
+"the light will never reach anything outside this range.\n"
+"[b]Note:[/b] [member spot_range] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/SpringArm.xml
@@ -66705,10 +66811,15 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
"If [code]true[/code], uses a fast post-processing filter to make banding "
-"significantly less visible. In some cases, debanding may introduce a "
-"slightly noticeable dithering pattern. It's recommended to enable debanding "
-"only when actually needed since the dithering pattern will make lossless-"
-"compressed screenshots larger.\n"
+"significantly less visible in 3D. 2D rendering is [i]not[/i] affected by "
+"debanding unless the [member Environment.background_mode] is [constant "
+"Environment.BG_CANVAS]. In this case, [member usage] must also be set to "
+"[constant USAGE_3D]. See also [member ProjectSettings.rendering/quality/"
+"filters/use_debanding].\n"
+"In some cases, debanding may introduce a slightly noticeable dithering "
+"pattern. It's recommended to enable debanding only when actually needed "
+"since the dithering pattern will make lossless-compressed screenshots "
+"larger.\n"
"[b]Note:[/b] Only available on the GLES3 backend. [member hdr] must also be "
"[code]true[/code] for debanding to be effective."
msgstr ""
@@ -66719,8 +66830,8 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
-"If [code]true[/code], the viewport will disable 3D rendering. For actual "
-"disabling use [code]usage[/code]."
+"If [code]true[/code], the viewport will disable 3D rendering. To actually "
+"disable allocation of 3D buffers, set [member usage] instead."
msgstr ""
#: doc/classes/Viewport.xml
@@ -66872,7 +66983,9 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
-"The rendering mode of viewport.\n"
+"The viewport's rendering mode. This controls which buffers are allocated for "
+"the viewport (2D only, or 2D + 3D). 2D-only options can reduce memory usage "
+"and improve performance slightly, especially on low-end devices.\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."
@@ -67404,6 +67517,22 @@ msgid ""
"render object this [VisualInstance] is set to."
msgstr ""
+#: doc/classes/VisualInstance.xml
+msgid ""
+"The sorting offset used by this [VisualInstance]. Adjusting it to a higher "
+"value will make the [VisualInstance] reliably draw on top of other "
+"[VisualInstance]s that are otherwise positioned at the same spot."
+msgstr ""
+
+#: doc/classes/VisualInstance.xml
+msgid ""
+"If [code]true[/code], the object is sorted based on the [AABB] center. "
+"Sorted based on the global position otherwise.\n"
+"The [AABB] center based sorting is generally more accurate for 3D models. "
+"The position based sorting instead allows to better control the drawing "
+"order when working with [Particles] and [CPUParticles]."
+msgstr ""
+
#: modules/visual_script/doc_classes/VisualScript.xml
msgid "A script implemented in the Visual Script programming environment."
msgstr ""
diff --git a/doc/translations/th.po b/doc/translations/th.po
index 6253763623..54fbdbfe27 100644
--- a/doc/translations/th.po
+++ b/doc/translations/th.po
@@ -554,7 +554,8 @@ msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
-"Returns an array of dictionaries representing the current call stack.\n"
+"Returns an array of dictionaries representing the current call stack. See "
+"also [method print_stack].\n"
"[codeblock]\n"
"func _ready():\n"
" foo()\n"
@@ -569,7 +570,11 @@ msgid ""
"[codeblock]\n"
"[{function:bar, line:12, source:res://script.gd}, {function:foo, line:9, "
"source:res://script.gd}, {function:_ready, line:6, source:res://script.gd}]\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] [method get_stack] only works if the running instance is "
+"connected to a debugging server (i.e. an editor instance). [method "
+"get_stack] will not work in projects exported in release mode, or in "
+"projects exported in debug mode if not connected to a debugging server."
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -949,12 +954,16 @@ msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
-"Prints a stack track at code location, only works when running with debugger "
-"turned on.\n"
+"Prints a stack trace at the current code location. See also [method "
+"get_stack].\n"
"Output in the console would look something like this:\n"
"[codeblock]\n"
"Frame 0 - res://test.gd:16 in function '_process'\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] [method print_stack] only works if the running instance is "
+"connected to a debugging server (i.e. an editor instance). [method "
+"print_stack] will not work in projects exported in release mode, or in "
+"projects exported in debug mode if not connected to a debugging server."
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -3574,6 +3583,26 @@ msgid "Hints that an image is compressed using lossless compression."
msgstr ""
#: doc/classes/@GlobalScope.xml
+msgid ""
+"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:\n"
+"[codeblock]\n"
+"hint_string = \"%s:\" % [TYPE_INT] # Array of inteters.\n"
+"hint_string = \"%s:%s:\" % [TYPE_ARRAY, TYPE_REAL] # Two-dimensional array "
+"of floats.\n"
+"hint_string = \"%s/%s:Resource\" % [TYPE_OBJECT, TYPE_OBJECT] # Array of "
+"resources.\n"
+"hint_string = \"%s:%s/%s:Resource\" % [TYPE_ARRAY, TYPE_OBJECT, TYPE_OBJECT] "
+"# Two-dimensional array of resources.\n"
+"[/codeblock]\n"
+"[b]Note:[/b] The final colon is required to specify for properly detecting "
+"built-in types."
+msgstr ""
+
+#: doc/classes/@GlobalScope.xml
msgid "The property is serialized and saved in the scene file (default)."
msgstr ""
@@ -4265,8 +4294,7 @@ msgstr ""
#: doc/classes/AudioStreamPlayer.xml doc/classes/Button.xml
#: doc/classes/CanvasLayer.xml doc/classes/CollisionShape2D.xml
#: doc/classes/ColorRect.xml doc/classes/Input.xml doc/classes/InputEvent.xml
-#: doc/classes/InputEventAction.xml doc/classes/Label.xml
-#: doc/classes/Particles2D.xml doc/classes/Timer.xml
+#: doc/classes/InputEventAction.xml doc/classes/Label.xml doc/classes/Timer.xml
#: doc/classes/VisibilityNotifier2D.xml
msgid "2D Dodge The Creeps Demo"
msgstr ""
@@ -7187,7 +7215,10 @@ msgid ""
"var array = []\n"
"array.resize(10)\n"
"array.fill(0) # Initialize the 10 elements to 0.\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] If [code]value[/code] is of a reference type ([Object]-derived, "
+"[Array], [Dictionary], etc.) then the array is filled with the references to "
+"the same object, i.e. no duplicates are created."
msgstr ""
#: doc/classes/Array.xml doc/classes/PoolByteArray.xml
@@ -7372,6 +7403,9 @@ msgstr ""
#: doc/classes/Array.xml
msgid ""
"Sorts the array.\n"
+"[b]Note:[/b] The sorting algorithm used is not [url=https://en.wikipedia.org/"
+"wiki/Sorting_algorithm#Stability]stable[/url]. This means that values "
+"considered equal may have their order changed when using [method sort].\n"
"[b]Note:[/b] Strings are sorted in alphabetical order (as opposed to natural "
"order). This may lead to unexpected behavior when sorting an array of "
"strings ending with a sequence of numbers. Consider the following example:\n"
@@ -7391,9 +7425,13 @@ msgid ""
"For two elements [code]a[/code] and [code]b[/code], if the given method "
"returns [code]true[/code], element [code]b[/code] will be after element "
"[code]a[/code] in the array.\n"
+"[b]Note:[/b] The sorting algorithm used is not [url=https://en.wikipedia.org/"
+"wiki/Sorting_algorithm#Stability]stable[/url]. This means that values "
+"considered equal may have their order changed when using [method "
+"sort_custom].\n"
"[b]Note:[/b] You cannot randomize the return value as the heapsort algorithm "
-"expects a deterministic result. Doing so will result in unexpected "
-"behavior.\n"
+"expects a deterministic result. Randomizing the return value will result in "
+"unexpected behavior.\n"
"[codeblock]\n"
"class MyCustomSorter:\n"
" static func sort_ascending(a, b):\n"
@@ -10032,10 +10070,9 @@ msgstr ""
#: doc/classes/AudioStreamGeneratorPlayback.xml
msgid ""
-"Returns the number of audio data frames left to play. If this returned "
-"number reaches [code]0[/code], the audio will stop playing until frames are "
-"added again. Therefore, make sure your script can always generate and push "
-"new audio frames fast enough to avoid audio cracking."
+"Returns the number of frames that can be pushed to the audio sample data "
+"buffer without overflowing it. If the result is [code]0[/code], the buffer "
+"is full."
msgstr ""
#: doc/classes/AudioStreamGeneratorPlayback.xml
@@ -10567,14 +10604,14 @@ msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
"Node for back-buffering the currently-displayed screen. The region defined "
-"in the BackBufferCopy node is buffered with the content of the screen it "
+"in the [BackBufferCopy] node is buffered with the content of the screen it "
"covers, or the entire screen according to the copy mode set. Use the "
"[code]texture(SCREEN_TEXTURE, ...)[/code] function in your shader scripts to "
"access the buffer.\n"
"[b]Note:[/b] Since this node inherits from [Node2D] (and not [Control]), "
"anchors and margins won't apply to child [Control]-derived nodes. This can "
"be problematic when resizing the window. To avoid this, add [Control]-"
-"derived nodes as [i]siblings[/i] to the BackBufferCopy node instead of "
+"derived nodes as [i]siblings[/i] to the [BackBufferCopy] node instead of "
"adding them as children."
msgstr ""
@@ -10584,22 +10621,22 @@ msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
-"The area covered by the BackBufferCopy. Only used if [member copy_mode] is "
+"The area covered by the [BackBufferCopy]. Only used if [member copy_mode] is "
"[constant COPY_MODE_RECT]."
msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
-"Disables the buffering mode. This means the BackBufferCopy node will "
+"Disables the buffering mode. This means the [BackBufferCopy] node will "
"directly use the portion of screen it covers."
msgstr ""
#: doc/classes/BackBufferCopy.xml
-msgid "BackBufferCopy buffers a rectangular region."
+msgid "[BackBufferCopy] buffers a rectangular region."
msgstr ""
#: doc/classes/BackBufferCopy.xml
-msgid "BackBufferCopy buffers the entire screen."
+msgid "[BackBufferCopy] buffers the entire screen."
msgstr ""
#: doc/classes/BakedLightmap.xml
@@ -19383,6 +19420,14 @@ msgid "Cylinder shape for collisions."
msgstr ""
#: doc/classes/CylinderShape.xml
+msgid ""
+"Cylinder shape for collisions.\n"
+"[b]Note:[/b] When using GodotPhysics instead of the default Bullet physics "
+"engine, there are several known bugs with cylinder collision shapes. Using "
+"[CapsuleShape] or [BoxShape] instead is recommended."
+msgstr ""
+
+#: doc/classes/CylinderShape.xml
msgid "The cylinder's height."
msgstr ""
@@ -22215,7 +22260,10 @@ msgid ""
"[/codeblock]\n"
"[b]Note:[/b] The script is run in the Editor context, which means the output "
"is visible in the console window started with the Editor (stdout) instead of "
-"the usual Godot [b]Output[/b] dock."
+"the usual Godot [b]Output[/b] dock.\n"
+"[b]Note:[/b] EditorScript is reference counted, meaning it is destroyed when "
+"nothing references it. This can cause errors during asynchronous operations "
+"if there are no references to the script."
msgstr ""
#: doc/classes/EditorScript.xml
@@ -32990,7 +33038,9 @@ msgid ""
"The size of the light in Godot units. Only considered in baked lightmaps and "
"only if [member light_bake_mode] is set to [constant BAKE_ALL]. Increasing "
"this value will make the shadows appear blurrier. This can be used to "
-"simulate area lights to an extent."
+"simulate area lights to an extent.\n"
+"[b]Note:[/b] [member light_size] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/Light.xml
@@ -36306,7 +36356,10 @@ msgid ""
"use the [method get_next_location] function once every physics frame to "
"update the internal path logic of the NavigationAgent. The returned vector "
"position from this function should be used as the next movement position for "
-"the agent's parent Node."
+"the agent's parent Node.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues."
msgstr ""
#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
@@ -36555,7 +36608,10 @@ msgid ""
"use the [method get_next_location] function once every physics frame to "
"update the internal path logic of the NavigationAgent. The returned vector "
"position from this function should be used as the next movement position for "
-"the agent's parent Node."
+"the agent's parent Node.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues."
msgstr ""
#: doc/classes/NavigationAgent2D.xml
@@ -37266,6 +37322,9 @@ msgid ""
"modified velocity as-is might lead to pushing and agent outside of a "
"navigable area. This is a limitation of the collision avoidance system, any "
"more complex situation may require the use of the physics engine.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues.\n"
"This server keeps tracks of any call and executes them during the sync "
"phase. This means that you can request any change to the map, using any "
"thread, without worrying."
@@ -40125,7 +40184,9 @@ msgid ""
"The light's radius. Note that the effectively lit area may appear to be "
"smaller depending on the [member omni_attenuation] in use. No matter the "
"[member omni_attenuation] in use, the light will never reach anything "
-"outside this radius."
+"outside this radius.\n"
+"[b]Note:[/b] [member omni_range] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -40638,11 +40699,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] cache data directory according to the operating "
-"system's standards. On desktop platforms, this path can be overridden by "
-"setting the [code]XDG_CACHE_HOME[/code] environment variable before starting "
-"the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in "
-"Godot projects[/url] in the documentation for more information. See also "
-"[method get_config_dir] and [method get_data_dir].\n"
+"system's standards. On Linux, this path can be overridden by setting the "
+"[code]XDG_CACHE_HOME[/code] environment variable before starting the "
+"project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot "
+"projects[/url] in the documentation for more information. See also [method "
+"get_config_dir] and [method get_data_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -40676,11 +40737,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] user configuration directory according to the "
-"operating system's standards. On desktop platforms, this path can be "
-"overridden by setting the [code]XDG_CONFIG_HOME[/code] environment variable "
-"before starting the project. See [url=$DOCS_URL/tutorials/io/data_paths."
-"html]File paths in Godot projects[/url] in the documentation for more "
-"information. See also [method get_cache_dir] and [method get_data_dir].\n"
+"operating system's standards. On Linux, this path can be overridden by "
+"setting the [code]XDG_CONFIG_HOME[/code] environment variable before "
+"starting the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File "
+"paths in Godot projects[/url] in the documentation for more information. See "
+"also [method get_cache_dir] and [method get_data_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -40702,11 +40763,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] user data directory according to the operating "
-"system's standards. On desktop platforms, this path can be overridden by "
-"setting the [code]XDG_DATA_HOME[/code] environment variable before starting "
-"the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in "
-"Godot projects[/url] in the documentation for more information. See also "
-"[method get_cache_dir] and [method get_config_dir].\n"
+"system's standards. On Linux, this path can be overridden by setting the "
+"[code]XDG_DATA_HOME[/code] environment variable before starting the project. "
+"See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot "
+"projects[/url] in the documentation for more information. See also [method "
+"get_cache_dir] and [method get_config_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -42556,6 +42617,16 @@ msgid "Particle systems (2D)"
msgstr ""
#: doc/classes/Particles2D.xml
+msgid "2D Particles Demo"
+msgstr ""
+
+#: doc/classes/Particles2D.xml
+msgid ""
+"2D Dodge The Creeps Demo (uses GPUParticles2D for the trail behind the "
+"player)"
+msgstr ""
+
+#: doc/classes/Particles2D.xml
msgid "Returns a rectangle containing the positions of all existing particles."
msgstr ""
@@ -50159,15 +50230,22 @@ msgstr ""
#: doc/classes/ProjectSettings.xml
msgid ""
"If [code]true[/code], uses a fast post-processing filter to make banding "
-"significantly less visible. In some cases, debanding may introduce a "
-"slightly noticeable dithering pattern. It's recommended to enable debanding "
-"only when actually needed since the dithering pattern will make lossless-"
-"compressed screenshots larger.\n"
+"significantly less visible in 3D. 2D rendering is [i]not[/i] affected by "
+"debanding unless the [member Environment.background_mode] is [constant "
+"Environment.BG_CANVAS]. In this case, [member rendering/quality/"
+"intended_usage/framebuffer_allocation] must also be set to [b]3D[/b].\n"
+"In some cases, debanding may introduce a slightly noticeable dithering "
+"pattern. It's recommended to enable debanding only when actually needed "
+"since the dithering pattern will make lossless-compressed screenshots "
+"larger.\n"
"[b]Note:[/b] Only available on the GLES3 backend. [member rendering/quality/"
"depth/hdr] must also be [code]true[/code] for debanding to be effective.\n"
"[b]Note:[/b] There are known issues with debanding breaking rendering on "
"mobile platforms. Due to this, it is recommended to leave this option "
-"disabled when targeting mobile platforms."
+"disabled when targeting mobile platforms.\n"
+"[b]Note:[/b] This property is only read when the project starts. To set "
+"debanding at run-time, set [member Viewport.debanding] on the root "
+"[Viewport] instead."
msgstr ""
#: doc/classes/ProjectSettings.xml
@@ -51765,17 +51843,28 @@ msgstr ""
#: modules/regex/doc_classes/RegEx.xml
msgid ""
"Searches the text for the compiled pattern. Returns a [RegExMatch] container "
-"of the first matching result if found, otherwise [code]null[/code]. The "
-"region to search within can be specified without modifying where the start "
-"and end anchor would be."
+"of the first matching result if found, otherwise [code]null[/code].\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegEx.xml
msgid ""
"Searches the text for the compiled pattern. Returns an array of [RegExMatch] "
"containers for each non-overlapping result. If no results were found, an "
-"empty array is returned instead. The region to search within can be "
-"specified without modifying where the start and end anchor would be."
+"empty array is returned instead.\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegEx.xml
@@ -51784,8 +51873,14 @@ msgid ""
"specified string. Escapes and backreferences such as [code]$1[/code] and "
"[code]$name[/code] are expanded and resolved. By default, only the first "
"instance is replaced, but it can be changed for all instances (global "
-"replacement). The region to search within can be specified without modifying "
-"where the start and end anchor would be."
+"replacement).\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegExMatch.xml
@@ -54501,7 +54596,11 @@ msgid "Call a group immediately (calls are normally made on idle)."
msgstr ""
#: doc/classes/SceneTree.xml
-msgid "Call a group only once even if the call is executed many times."
+msgid ""
+"Call a group only once even if the call is executed many times.\n"
+"[b]Note:[/b] Arguments are not taken into account when deciding whether the "
+"call is unique or not. Therefore when the same method is called with "
+"different arguments, only the first call will be performed."
msgstr ""
#: doc/classes/SceneTree.xml
@@ -56338,7 +56437,9 @@ msgid ""
"[b]Note:[/b] Mixed negative scales in 3D are not decomposable from the "
"transformation matrix. Due to the way scale is represented with "
"transformation matrices in Godot, the scale values will either be all "
-"positive or all negative."
+"positive or all negative.\n"
+"[b]Note:[/b] Not all nodes are visually scaled by the [member scale] "
+"property. For example, [Light]s are not visually affected by [member scale]."
msgstr ""
#: doc/classes/Spatial.xml
@@ -57716,7 +57817,10 @@ msgid ""
msgstr ""
#: doc/classes/SpotLight.xml
-msgid "The spotlight's angle in degrees."
+msgid ""
+"The spotlight's angle in degrees.\n"
+"[b]Note:[/b] [member spot_angle] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/SpotLight.xml
@@ -57732,7 +57836,9 @@ msgid ""
"The maximal range that can be reached by the spotlight. Note that the "
"effectively lit area may appear to be smaller depending on the [member "
"spot_attenuation] in use. No matter the [member spot_attenuation] in use, "
-"the light will never reach anything outside this range."
+"the light will never reach anything outside this range.\n"
+"[b]Note:[/b] [member spot_range] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/SpringArm.xml
@@ -66999,10 +67105,15 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
"If [code]true[/code], uses a fast post-processing filter to make banding "
-"significantly less visible. In some cases, debanding may introduce a "
-"slightly noticeable dithering pattern. It's recommended to enable debanding "
-"only when actually needed since the dithering pattern will make lossless-"
-"compressed screenshots larger.\n"
+"significantly less visible in 3D. 2D rendering is [i]not[/i] affected by "
+"debanding unless the [member Environment.background_mode] is [constant "
+"Environment.BG_CANVAS]. In this case, [member usage] must also be set to "
+"[constant USAGE_3D]. See also [member ProjectSettings.rendering/quality/"
+"filters/use_debanding].\n"
+"In some cases, debanding may introduce a slightly noticeable dithering "
+"pattern. It's recommended to enable debanding only when actually needed "
+"since the dithering pattern will make lossless-compressed screenshots "
+"larger.\n"
"[b]Note:[/b] Only available on the GLES3 backend. [member hdr] must also be "
"[code]true[/code] for debanding to be effective."
msgstr ""
@@ -67013,8 +67124,8 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
-"If [code]true[/code], the viewport will disable 3D rendering. For actual "
-"disabling use [code]usage[/code]."
+"If [code]true[/code], the viewport will disable 3D rendering. To actually "
+"disable allocation of 3D buffers, set [member usage] instead."
msgstr ""
#: doc/classes/Viewport.xml
@@ -67166,7 +67277,9 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
-"The rendering mode of viewport.\n"
+"The viewport's rendering mode. This controls which buffers are allocated for "
+"the viewport (2D only, or 2D + 3D). 2D-only options can reduce memory usage "
+"and improve performance slightly, especially on low-end devices.\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."
@@ -67698,6 +67811,22 @@ msgid ""
"render object this [VisualInstance] is set to."
msgstr ""
+#: doc/classes/VisualInstance.xml
+msgid ""
+"The sorting offset used by this [VisualInstance]. Adjusting it to a higher "
+"value will make the [VisualInstance] reliably draw on top of other "
+"[VisualInstance]s that are otherwise positioned at the same spot."
+msgstr ""
+
+#: doc/classes/VisualInstance.xml
+msgid ""
+"If [code]true[/code], the object is sorted based on the [AABB] center. "
+"Sorted based on the global position otherwise.\n"
+"The [AABB] center based sorting is generally more accurate for 3D models. "
+"The position based sorting instead allows to better control the drawing "
+"order when working with [Particles] and [CPUParticles]."
+msgstr ""
+
#: modules/visual_script/doc_classes/VisualScript.xml
msgid "A script implemented in the Visual Script programming environment."
msgstr ""
diff --git a/doc/translations/tl.po b/doc/translations/tl.po
index 0dae96a014..a9b6a9e2a9 100644
--- a/doc/translations/tl.po
+++ b/doc/translations/tl.po
@@ -548,7 +548,8 @@ msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
-"Returns an array of dictionaries representing the current call stack.\n"
+"Returns an array of dictionaries representing the current call stack. See "
+"also [method print_stack].\n"
"[codeblock]\n"
"func _ready():\n"
" foo()\n"
@@ -563,7 +564,11 @@ msgid ""
"[codeblock]\n"
"[{function:bar, line:12, source:res://script.gd}, {function:foo, line:9, "
"source:res://script.gd}, {function:_ready, line:6, source:res://script.gd}]\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] [method get_stack] only works if the running instance is "
+"connected to a debugging server (i.e. an editor instance). [method "
+"get_stack] will not work in projects exported in release mode, or in "
+"projects exported in debug mode if not connected to a debugging server."
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -940,12 +945,16 @@ msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
-"Prints a stack track at code location, only works when running with debugger "
-"turned on.\n"
+"Prints a stack trace at the current code location. See also [method "
+"get_stack].\n"
"Output in the console would look something like this:\n"
"[codeblock]\n"
"Frame 0 - res://test.gd:16 in function '_process'\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] [method print_stack] only works if the running instance is "
+"connected to a debugging server (i.e. an editor instance). [method "
+"print_stack] will not work in projects exported in release mode, or in "
+"projects exported in debug mode if not connected to a debugging server."
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -3556,6 +3565,26 @@ msgid "Hints that an image is compressed using lossless compression."
msgstr ""
#: doc/classes/@GlobalScope.xml
+msgid ""
+"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:\n"
+"[codeblock]\n"
+"hint_string = \"%s:\" % [TYPE_INT] # Array of inteters.\n"
+"hint_string = \"%s:%s:\" % [TYPE_ARRAY, TYPE_REAL] # Two-dimensional array "
+"of floats.\n"
+"hint_string = \"%s/%s:Resource\" % [TYPE_OBJECT, TYPE_OBJECT] # Array of "
+"resources.\n"
+"hint_string = \"%s:%s/%s:Resource\" % [TYPE_ARRAY, TYPE_OBJECT, TYPE_OBJECT] "
+"# Two-dimensional array of resources.\n"
+"[/codeblock]\n"
+"[b]Note:[/b] The final colon is required to specify for properly detecting "
+"built-in types."
+msgstr ""
+
+#: doc/classes/@GlobalScope.xml
msgid "The property is serialized and saved in the scene file (default)."
msgstr ""
@@ -4240,8 +4269,7 @@ msgstr ""
#: doc/classes/AudioStreamPlayer.xml doc/classes/Button.xml
#: doc/classes/CanvasLayer.xml doc/classes/CollisionShape2D.xml
#: doc/classes/ColorRect.xml doc/classes/Input.xml doc/classes/InputEvent.xml
-#: doc/classes/InputEventAction.xml doc/classes/Label.xml
-#: doc/classes/Particles2D.xml doc/classes/Timer.xml
+#: doc/classes/InputEventAction.xml doc/classes/Label.xml doc/classes/Timer.xml
#: doc/classes/VisibilityNotifier2D.xml
msgid "2D Dodge The Creeps Demo"
msgstr ""
@@ -7158,7 +7186,10 @@ msgid ""
"var array = []\n"
"array.resize(10)\n"
"array.fill(0) # Initialize the 10 elements to 0.\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] If [code]value[/code] is of a reference type ([Object]-derived, "
+"[Array], [Dictionary], etc.) then the array is filled with the references to "
+"the same object, i.e. no duplicates are created."
msgstr ""
#: doc/classes/Array.xml doc/classes/PoolByteArray.xml
@@ -7343,6 +7374,9 @@ msgstr ""
#: doc/classes/Array.xml
msgid ""
"Sorts the array.\n"
+"[b]Note:[/b] The sorting algorithm used is not [url=https://en.wikipedia.org/"
+"wiki/Sorting_algorithm#Stability]stable[/url]. This means that values "
+"considered equal may have their order changed when using [method sort].\n"
"[b]Note:[/b] Strings are sorted in alphabetical order (as opposed to natural "
"order). This may lead to unexpected behavior when sorting an array of "
"strings ending with a sequence of numbers. Consider the following example:\n"
@@ -7362,9 +7396,13 @@ msgid ""
"For two elements [code]a[/code] and [code]b[/code], if the given method "
"returns [code]true[/code], element [code]b[/code] will be after element "
"[code]a[/code] in the array.\n"
+"[b]Note:[/b] The sorting algorithm used is not [url=https://en.wikipedia.org/"
+"wiki/Sorting_algorithm#Stability]stable[/url]. This means that values "
+"considered equal may have their order changed when using [method "
+"sort_custom].\n"
"[b]Note:[/b] You cannot randomize the return value as the heapsort algorithm "
-"expects a deterministic result. Doing so will result in unexpected "
-"behavior.\n"
+"expects a deterministic result. Randomizing the return value will result in "
+"unexpected behavior.\n"
"[codeblock]\n"
"class MyCustomSorter:\n"
" static func sort_ascending(a, b):\n"
@@ -10006,10 +10044,9 @@ msgstr ""
#: doc/classes/AudioStreamGeneratorPlayback.xml
msgid ""
-"Returns the number of audio data frames left to play. If this returned "
-"number reaches [code]0[/code], the audio will stop playing until frames are "
-"added again. Therefore, make sure your script can always generate and push "
-"new audio frames fast enough to avoid audio cracking."
+"Returns the number of frames that can be pushed to the audio sample data "
+"buffer without overflowing it. If the result is [code]0[/code], the buffer "
+"is full."
msgstr ""
#: doc/classes/AudioStreamGeneratorPlayback.xml
@@ -10541,14 +10578,14 @@ msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
"Node for back-buffering the currently-displayed screen. The region defined "
-"in the BackBufferCopy node is buffered with the content of the screen it "
+"in the [BackBufferCopy] node is buffered with the content of the screen it "
"covers, or the entire screen according to the copy mode set. Use the "
"[code]texture(SCREEN_TEXTURE, ...)[/code] function in your shader scripts to "
"access the buffer.\n"
"[b]Note:[/b] Since this node inherits from [Node2D] (and not [Control]), "
"anchors and margins won't apply to child [Control]-derived nodes. This can "
"be problematic when resizing the window. To avoid this, add [Control]-"
-"derived nodes as [i]siblings[/i] to the BackBufferCopy node instead of "
+"derived nodes as [i]siblings[/i] to the [BackBufferCopy] node instead of "
"adding them as children."
msgstr ""
@@ -10558,22 +10595,22 @@ msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
-"The area covered by the BackBufferCopy. Only used if [member copy_mode] is "
+"The area covered by the [BackBufferCopy]. Only used if [member copy_mode] is "
"[constant COPY_MODE_RECT]."
msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
-"Disables the buffering mode. This means the BackBufferCopy node will "
+"Disables the buffering mode. This means the [BackBufferCopy] node will "
"directly use the portion of screen it covers."
msgstr ""
#: doc/classes/BackBufferCopy.xml
-msgid "BackBufferCopy buffers a rectangular region."
+msgid "[BackBufferCopy] buffers a rectangular region."
msgstr ""
#: doc/classes/BackBufferCopy.xml
-msgid "BackBufferCopy buffers the entire screen."
+msgid "[BackBufferCopy] buffers the entire screen."
msgstr ""
#: doc/classes/BakedLightmap.xml
@@ -19356,6 +19393,14 @@ msgid "Cylinder shape for collisions."
msgstr ""
#: doc/classes/CylinderShape.xml
+msgid ""
+"Cylinder shape for collisions.\n"
+"[b]Note:[/b] When using GodotPhysics instead of the default Bullet physics "
+"engine, there are several known bugs with cylinder collision shapes. Using "
+"[CapsuleShape] or [BoxShape] instead is recommended."
+msgstr ""
+
+#: doc/classes/CylinderShape.xml
msgid "The cylinder's height."
msgstr ""
@@ -22191,7 +22236,10 @@ msgid ""
"[/codeblock]\n"
"[b]Note:[/b] The script is run in the Editor context, which means the output "
"is visible in the console window started with the Editor (stdout) instead of "
-"the usual Godot [b]Output[/b] dock."
+"the usual Godot [b]Output[/b] dock.\n"
+"[b]Note:[/b] EditorScript is reference counted, meaning it is destroyed when "
+"nothing references it. This can cause errors during asynchronous operations "
+"if there are no references to the script."
msgstr ""
#: doc/classes/EditorScript.xml
@@ -32915,7 +32963,9 @@ msgid ""
"The size of the light in Godot units. Only considered in baked lightmaps and "
"only if [member light_bake_mode] is set to [constant BAKE_ALL]. Increasing "
"this value will make the shadows appear blurrier. This can be used to "
-"simulate area lights to an extent."
+"simulate area lights to an extent.\n"
+"[b]Note:[/b] [member light_size] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/Light.xml
@@ -36231,7 +36281,10 @@ msgid ""
"use the [method get_next_location] function once every physics frame to "
"update the internal path logic of the NavigationAgent. The returned vector "
"position from this function should be used as the next movement position for "
-"the agent's parent Node."
+"the agent's parent Node.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues."
msgstr ""
#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
@@ -36479,7 +36532,10 @@ msgid ""
"use the [method get_next_location] function once every physics frame to "
"update the internal path logic of the NavigationAgent. The returned vector "
"position from this function should be used as the next movement position for "
-"the agent's parent Node."
+"the agent's parent Node.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues."
msgstr ""
#: doc/classes/NavigationAgent2D.xml
@@ -37189,6 +37245,9 @@ msgid ""
"modified velocity as-is might lead to pushing and agent outside of a "
"navigable area. This is a limitation of the collision avoidance system, any "
"more complex situation may require the use of the physics engine.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues.\n"
"This server keeps tracks of any call and executes them during the sync "
"phase. This means that you can request any change to the map, using any "
"thread, without worrying."
@@ -39995,7 +40054,9 @@ msgid ""
"The light's radius. Note that the effectively lit area may appear to be "
"smaller depending on the [member omni_attenuation] in use. No matter the "
"[member omni_attenuation] in use, the light will never reach anything "
-"outside this radius."
+"outside this radius.\n"
+"[b]Note:[/b] [member omni_range] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -40506,11 +40567,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] cache data directory according to the operating "
-"system's standards. On desktop platforms, this path can be overridden by "
-"setting the [code]XDG_CACHE_HOME[/code] environment variable before starting "
-"the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in "
-"Godot projects[/url] in the documentation for more information. See also "
-"[method get_config_dir] and [method get_data_dir].\n"
+"system's standards. On Linux, this path can be overridden by setting the "
+"[code]XDG_CACHE_HOME[/code] environment variable before starting the "
+"project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot "
+"projects[/url] in the documentation for more information. See also [method "
+"get_config_dir] and [method get_data_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -40544,11 +40605,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] user configuration directory according to the "
-"operating system's standards. On desktop platforms, this path can be "
-"overridden by setting the [code]XDG_CONFIG_HOME[/code] environment variable "
-"before starting the project. See [url=$DOCS_URL/tutorials/io/data_paths."
-"html]File paths in Godot projects[/url] in the documentation for more "
-"information. See also [method get_cache_dir] and [method get_data_dir].\n"
+"operating system's standards. On Linux, this path can be overridden by "
+"setting the [code]XDG_CONFIG_HOME[/code] environment variable before "
+"starting the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File "
+"paths in Godot projects[/url] in the documentation for more information. See "
+"also [method get_cache_dir] and [method get_data_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -40570,11 +40631,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] user data directory according to the operating "
-"system's standards. On desktop platforms, this path can be overridden by "
-"setting the [code]XDG_DATA_HOME[/code] environment variable before starting "
-"the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in "
-"Godot projects[/url] in the documentation for more information. See also "
-"[method get_cache_dir] and [method get_config_dir].\n"
+"system's standards. On Linux, this path can be overridden by setting the "
+"[code]XDG_DATA_HOME[/code] environment variable before starting the project. "
+"See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot "
+"projects[/url] in the documentation for more information. See also [method "
+"get_cache_dir] and [method get_config_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -42424,6 +42485,16 @@ msgid "Particle systems (2D)"
msgstr ""
#: doc/classes/Particles2D.xml
+msgid "2D Particles Demo"
+msgstr ""
+
+#: doc/classes/Particles2D.xml
+msgid ""
+"2D Dodge The Creeps Demo (uses GPUParticles2D for the trail behind the "
+"player)"
+msgstr ""
+
+#: doc/classes/Particles2D.xml
msgid "Returns a rectangle containing the positions of all existing particles."
msgstr ""
@@ -50016,15 +50087,22 @@ msgstr ""
#: doc/classes/ProjectSettings.xml
msgid ""
"If [code]true[/code], uses a fast post-processing filter to make banding "
-"significantly less visible. In some cases, debanding may introduce a "
-"slightly noticeable dithering pattern. It's recommended to enable debanding "
-"only when actually needed since the dithering pattern will make lossless-"
-"compressed screenshots larger.\n"
+"significantly less visible in 3D. 2D rendering is [i]not[/i] affected by "
+"debanding unless the [member Environment.background_mode] is [constant "
+"Environment.BG_CANVAS]. In this case, [member rendering/quality/"
+"intended_usage/framebuffer_allocation] must also be set to [b]3D[/b].\n"
+"In some cases, debanding may introduce a slightly noticeable dithering "
+"pattern. It's recommended to enable debanding only when actually needed "
+"since the dithering pattern will make lossless-compressed screenshots "
+"larger.\n"
"[b]Note:[/b] Only available on the GLES3 backend. [member rendering/quality/"
"depth/hdr] must also be [code]true[/code] for debanding to be effective.\n"
"[b]Note:[/b] There are known issues with debanding breaking rendering on "
"mobile platforms. Due to this, it is recommended to leave this option "
-"disabled when targeting mobile platforms."
+"disabled when targeting mobile platforms.\n"
+"[b]Note:[/b] This property is only read when the project starts. To set "
+"debanding at run-time, set [member Viewport.debanding] on the root "
+"[Viewport] instead."
msgstr ""
#: doc/classes/ProjectSettings.xml
@@ -51620,17 +51698,28 @@ msgstr ""
#: modules/regex/doc_classes/RegEx.xml
msgid ""
"Searches the text for the compiled pattern. Returns a [RegExMatch] container "
-"of the first matching result if found, otherwise [code]null[/code]. The "
-"region to search within can be specified without modifying where the start "
-"and end anchor would be."
+"of the first matching result if found, otherwise [code]null[/code].\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegEx.xml
msgid ""
"Searches the text for the compiled pattern. Returns an array of [RegExMatch] "
"containers for each non-overlapping result. If no results were found, an "
-"empty array is returned instead. The region to search within can be "
-"specified without modifying where the start and end anchor would be."
+"empty array is returned instead.\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegEx.xml
@@ -51639,8 +51728,14 @@ msgid ""
"specified string. Escapes and backreferences such as [code]$1[/code] and "
"[code]$name[/code] are expanded and resolved. By default, only the first "
"instance is replaced, but it can be changed for all instances (global "
-"replacement). The region to search within can be specified without modifying "
-"where the start and end anchor would be."
+"replacement).\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegExMatch.xml
@@ -54355,7 +54450,11 @@ msgid "Call a group immediately (calls are normally made on idle)."
msgstr ""
#: doc/classes/SceneTree.xml
-msgid "Call a group only once even if the call is executed many times."
+msgid ""
+"Call a group only once even if the call is executed many times.\n"
+"[b]Note:[/b] Arguments are not taken into account when deciding whether the "
+"call is unique or not. Therefore when the same method is called with "
+"different arguments, only the first call will be performed."
msgstr ""
#: doc/classes/SceneTree.xml
@@ -56192,7 +56291,9 @@ msgid ""
"[b]Note:[/b] Mixed negative scales in 3D are not decomposable from the "
"transformation matrix. Due to the way scale is represented with "
"transformation matrices in Godot, the scale values will either be all "
-"positive or all negative."
+"positive or all negative.\n"
+"[b]Note:[/b] Not all nodes are visually scaled by the [member scale] "
+"property. For example, [Light]s are not visually affected by [member scale]."
msgstr ""
#: doc/classes/Spatial.xml
@@ -57570,7 +57671,10 @@ msgid ""
msgstr ""
#: doc/classes/SpotLight.xml
-msgid "The spotlight's angle in degrees."
+msgid ""
+"The spotlight's angle in degrees.\n"
+"[b]Note:[/b] [member spot_angle] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/SpotLight.xml
@@ -57586,7 +57690,9 @@ msgid ""
"The maximal range that can be reached by the spotlight. Note that the "
"effectively lit area may appear to be smaller depending on the [member "
"spot_attenuation] in use. No matter the [member spot_attenuation] in use, "
-"the light will never reach anything outside this range."
+"the light will never reach anything outside this range.\n"
+"[b]Note:[/b] [member spot_range] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/SpringArm.xml
@@ -66859,10 +66965,15 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
"If [code]true[/code], uses a fast post-processing filter to make banding "
-"significantly less visible. In some cases, debanding may introduce a "
-"slightly noticeable dithering pattern. It's recommended to enable debanding "
-"only when actually needed since the dithering pattern will make lossless-"
-"compressed screenshots larger.\n"
+"significantly less visible in 3D. 2D rendering is [i]not[/i] affected by "
+"debanding unless the [member Environment.background_mode] is [constant "
+"Environment.BG_CANVAS]. In this case, [member usage] must also be set to "
+"[constant USAGE_3D]. See also [member ProjectSettings.rendering/quality/"
+"filters/use_debanding].\n"
+"In some cases, debanding may introduce a slightly noticeable dithering "
+"pattern. It's recommended to enable debanding only when actually needed "
+"since the dithering pattern will make lossless-compressed screenshots "
+"larger.\n"
"[b]Note:[/b] Only available on the GLES3 backend. [member hdr] must also be "
"[code]true[/code] for debanding to be effective."
msgstr ""
@@ -66873,8 +66984,8 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
-"If [code]true[/code], the viewport will disable 3D rendering. For actual "
-"disabling use [code]usage[/code]."
+"If [code]true[/code], the viewport will disable 3D rendering. To actually "
+"disable allocation of 3D buffers, set [member usage] instead."
msgstr ""
#: doc/classes/Viewport.xml
@@ -67026,7 +67137,9 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
-"The rendering mode of viewport.\n"
+"The viewport's rendering mode. This controls which buffers are allocated for "
+"the viewport (2D only, or 2D + 3D). 2D-only options can reduce memory usage "
+"and improve performance slightly, especially on low-end devices.\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."
@@ -67558,6 +67671,22 @@ msgid ""
"render object this [VisualInstance] is set to."
msgstr ""
+#: doc/classes/VisualInstance.xml
+msgid ""
+"The sorting offset used by this [VisualInstance]. Adjusting it to a higher "
+"value will make the [VisualInstance] reliably draw on top of other "
+"[VisualInstance]s that are otherwise positioned at the same spot."
+msgstr ""
+
+#: doc/classes/VisualInstance.xml
+msgid ""
+"If [code]true[/code], the object is sorted based on the [AABB] center. "
+"Sorted based on the global position otherwise.\n"
+"The [AABB] center based sorting is generally more accurate for 3D models. "
+"The position based sorting instead allows to better control the drawing "
+"order when working with [Particles] and [CPUParticles]."
+msgstr ""
+
#: modules/visual_script/doc_classes/VisualScript.xml
msgid "A script implemented in the Visual Script programming environment."
msgstr ""
diff --git a/doc/translations/tr.po b/doc/translations/tr.po
index 4e6f4096d5..5d8f2afe29 100644
--- a/doc/translations/tr.po
+++ b/doc/translations/tr.po
@@ -701,8 +701,10 @@ msgstr ""
"[/codeblock]"
#: modules/gdscript/doc_classes/@GDScript.xml
+#, fuzzy
msgid ""
-"Returns an array of dictionaries representing the current call stack.\n"
+"Returns an array of dictionaries representing the current call stack. See "
+"also [method print_stack].\n"
"[codeblock]\n"
"func _ready():\n"
" foo()\n"
@@ -717,7 +719,11 @@ msgid ""
"[codeblock]\n"
"[{function:bar, line:12, source:res://script.gd}, {function:foo, line:9, "
"source:res://script.gd}, {function:_ready, line:6, source:res://script.gd}]\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] [method get_stack] only works if the running instance is "
+"connected to a debugging server (i.e. an editor instance). [method "
+"get_stack] will not work in projects exported in release mode, or in "
+"projects exported in debug mode if not connected to a debugging server."
msgstr ""
"işlev yığınını temsil eden sözlük dizisi döndürür.\n"
"[codeblock]\n"
@@ -1338,19 +1344,17 @@ msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
-"Prints a stack track at code location, only works when running with debugger "
-"turned on.\n"
+"Prints a stack trace at the current code location. See also [method "
+"get_stack].\n"
"Output in the console would look something like this:\n"
"[codeblock]\n"
"Frame 0 - res://test.gd:16 in function '_process'\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] [method print_stack] only works if the running instance is "
+"connected to a debugging server (i.e. an editor instance). [method "
+"print_stack] will not work in projects exported in release mode, or in "
+"projects exported in debug mode if not connected to a debugging server."
msgstr ""
-"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 ""
@@ -4262,6 +4266,26 @@ msgid "Hints that an image is compressed using lossless compression."
msgstr ""
#: doc/classes/@GlobalScope.xml
+msgid ""
+"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:\n"
+"[codeblock]\n"
+"hint_string = \"%s:\" % [TYPE_INT] # Array of inteters.\n"
+"hint_string = \"%s:%s:\" % [TYPE_ARRAY, TYPE_REAL] # Two-dimensional array "
+"of floats.\n"
+"hint_string = \"%s/%s:Resource\" % [TYPE_OBJECT, TYPE_OBJECT] # Array of "
+"resources.\n"
+"hint_string = \"%s:%s/%s:Resource\" % [TYPE_ARRAY, TYPE_OBJECT, TYPE_OBJECT] "
+"# Two-dimensional array of resources.\n"
+"[/codeblock]\n"
+"[b]Note:[/b] The final colon is required to specify for properly detecting "
+"built-in types."
+msgstr ""
+
+#: doc/classes/@GlobalScope.xml
msgid "The property is serialized and saved in the scene file (default)."
msgstr ""
@@ -4946,8 +4970,7 @@ msgstr ""
#: doc/classes/AudioStreamPlayer.xml doc/classes/Button.xml
#: doc/classes/CanvasLayer.xml doc/classes/CollisionShape2D.xml
#: doc/classes/ColorRect.xml doc/classes/Input.xml doc/classes/InputEvent.xml
-#: doc/classes/InputEventAction.xml doc/classes/Label.xml
-#: doc/classes/Particles2D.xml doc/classes/Timer.xml
+#: doc/classes/InputEventAction.xml doc/classes/Label.xml doc/classes/Timer.xml
#: doc/classes/VisibilityNotifier2D.xml
msgid "2D Dodge The Creeps Demo"
msgstr ""
@@ -7866,7 +7889,10 @@ msgid ""
"var array = []\n"
"array.resize(10)\n"
"array.fill(0) # Initialize the 10 elements to 0.\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] If [code]value[/code] is of a reference type ([Object]-derived, "
+"[Array], [Dictionary], etc.) then the array is filled with the references to "
+"the same object, i.e. no duplicates are created."
msgstr ""
#: doc/classes/Array.xml doc/classes/PoolByteArray.xml
@@ -8051,6 +8077,9 @@ msgstr ""
#: doc/classes/Array.xml
msgid ""
"Sorts the array.\n"
+"[b]Note:[/b] The sorting algorithm used is not [url=https://en.wikipedia.org/"
+"wiki/Sorting_algorithm#Stability]stable[/url]. This means that values "
+"considered equal may have their order changed when using [method sort].\n"
"[b]Note:[/b] Strings are sorted in alphabetical order (as opposed to natural "
"order). This may lead to unexpected behavior when sorting an array of "
"strings ending with a sequence of numbers. Consider the following example:\n"
@@ -8070,9 +8099,13 @@ msgid ""
"For two elements [code]a[/code] and [code]b[/code], if the given method "
"returns [code]true[/code], element [code]b[/code] will be after element "
"[code]a[/code] in the array.\n"
+"[b]Note:[/b] The sorting algorithm used is not [url=https://en.wikipedia.org/"
+"wiki/Sorting_algorithm#Stability]stable[/url]. This means that values "
+"considered equal may have their order changed when using [method "
+"sort_custom].\n"
"[b]Note:[/b] You cannot randomize the return value as the heapsort algorithm "
-"expects a deterministic result. Doing so will result in unexpected "
-"behavior.\n"
+"expects a deterministic result. Randomizing the return value will result in "
+"unexpected behavior.\n"
"[codeblock]\n"
"class MyCustomSorter:\n"
" static func sort_ascending(a, b):\n"
@@ -10711,10 +10744,9 @@ msgstr ""
#: doc/classes/AudioStreamGeneratorPlayback.xml
msgid ""
-"Returns the number of audio data frames left to play. If this returned "
-"number reaches [code]0[/code], the audio will stop playing until frames are "
-"added again. Therefore, make sure your script can always generate and push "
-"new audio frames fast enough to avoid audio cracking."
+"Returns the number of frames that can be pushed to the audio sample data "
+"buffer without overflowing it. If the result is [code]0[/code], the buffer "
+"is full."
msgstr ""
#: doc/classes/AudioStreamGeneratorPlayback.xml
@@ -11246,14 +11278,14 @@ msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
"Node for back-buffering the currently-displayed screen. The region defined "
-"in the BackBufferCopy node is buffered with the content of the screen it "
+"in the [BackBufferCopy] node is buffered with the content of the screen it "
"covers, or the entire screen according to the copy mode set. Use the "
"[code]texture(SCREEN_TEXTURE, ...)[/code] function in your shader scripts to "
"access the buffer.\n"
"[b]Note:[/b] Since this node inherits from [Node2D] (and not [Control]), "
"anchors and margins won't apply to child [Control]-derived nodes. This can "
"be problematic when resizing the window. To avoid this, add [Control]-"
-"derived nodes as [i]siblings[/i] to the BackBufferCopy node instead of "
+"derived nodes as [i]siblings[/i] to the [BackBufferCopy] node instead of "
"adding them as children."
msgstr ""
@@ -11263,22 +11295,22 @@ msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
-"The area covered by the BackBufferCopy. Only used if [member copy_mode] is "
+"The area covered by the [BackBufferCopy]. Only used if [member copy_mode] is "
"[constant COPY_MODE_RECT]."
msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
-"Disables the buffering mode. This means the BackBufferCopy node will "
+"Disables the buffering mode. This means the [BackBufferCopy] node will "
"directly use the portion of screen it covers."
msgstr ""
#: doc/classes/BackBufferCopy.xml
-msgid "BackBufferCopy buffers a rectangular region."
+msgid "[BackBufferCopy] buffers a rectangular region."
msgstr ""
#: doc/classes/BackBufferCopy.xml
-msgid "BackBufferCopy buffers the entire screen."
+msgid "[BackBufferCopy] buffers the entire screen."
msgstr ""
#: doc/classes/BakedLightmap.xml
@@ -20083,6 +20115,14 @@ msgid "Cylinder shape for collisions."
msgstr ""
#: doc/classes/CylinderShape.xml
+msgid ""
+"Cylinder shape for collisions.\n"
+"[b]Note:[/b] When using GodotPhysics instead of the default Bullet physics "
+"engine, there are several known bugs with cylinder collision shapes. Using "
+"[CapsuleShape] or [BoxShape] instead is recommended."
+msgstr ""
+
+#: doc/classes/CylinderShape.xml
msgid "The cylinder's height."
msgstr ""
@@ -22920,7 +22960,10 @@ msgid ""
"[/codeblock]\n"
"[b]Note:[/b] The script is run in the Editor context, which means the output "
"is visible in the console window started with the Editor (stdout) instead of "
-"the usual Godot [b]Output[/b] dock."
+"the usual Godot [b]Output[/b] dock.\n"
+"[b]Note:[/b] EditorScript is reference counted, meaning it is destroyed when "
+"nothing references it. This can cause errors during asynchronous operations "
+"if there are no references to the script."
msgstr ""
#: doc/classes/EditorScript.xml
@@ -33670,7 +33713,9 @@ msgid ""
"The size of the light in Godot units. Only considered in baked lightmaps and "
"only if [member light_bake_mode] is set to [constant BAKE_ALL]. Increasing "
"this value will make the shadows appear blurrier. This can be used to "
-"simulate area lights to an extent."
+"simulate area lights to an extent.\n"
+"[b]Note:[/b] [member light_size] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/Light.xml
@@ -37004,7 +37049,10 @@ msgid ""
"use the [method get_next_location] function once every physics frame to "
"update the internal path logic of the NavigationAgent. The returned vector "
"position from this function should be used as the next movement position for "
-"the agent's parent Node."
+"the agent's parent Node.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues."
msgstr ""
#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
@@ -37254,7 +37302,10 @@ msgid ""
"use the [method get_next_location] function once every physics frame to "
"update the internal path logic of the NavigationAgent. The returned vector "
"position from this function should be used as the next movement position for "
-"the agent's parent Node."
+"the agent's parent Node.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues."
msgstr ""
#: doc/classes/NavigationAgent2D.xml
@@ -37975,6 +38026,9 @@ msgid ""
"modified velocity as-is might lead to pushing and agent outside of a "
"navigable area. This is a limitation of the collision avoidance system, any "
"more complex situation may require the use of the physics engine.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues.\n"
"This server keeps tracks of any call and executes them during the sync "
"phase. This means that you can request any change to the map, using any "
"thread, without worrying."
@@ -40785,7 +40839,9 @@ msgid ""
"The light's radius. Note that the effectively lit area may appear to be "
"smaller depending on the [member omni_attenuation] in use. No matter the "
"[member omni_attenuation] in use, the light will never reach anything "
-"outside this radius."
+"outside this radius.\n"
+"[b]Note:[/b] [member omni_range] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -41301,11 +41357,11 @@ msgstr "Verilen bir değerin ark-sinüsünü döndürür."
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] cache data directory according to the operating "
-"system's standards. On desktop platforms, this path can be overridden by "
-"setting the [code]XDG_CACHE_HOME[/code] environment variable before starting "
-"the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in "
-"Godot projects[/url] in the documentation for more information. See also "
-"[method get_config_dir] and [method get_data_dir].\n"
+"system's standards. On Linux, this path can be overridden by setting the "
+"[code]XDG_CACHE_HOME[/code] environment variable before starting the "
+"project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot "
+"projects[/url] in the documentation for more information. See also [method "
+"get_config_dir] and [method get_data_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -41339,11 +41395,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] user configuration directory according to the "
-"operating system's standards. On desktop platforms, this path can be "
-"overridden by setting the [code]XDG_CONFIG_HOME[/code] environment variable "
-"before starting the project. See [url=$DOCS_URL/tutorials/io/data_paths."
-"html]File paths in Godot projects[/url] in the documentation for more "
-"information. See also [method get_cache_dir] and [method get_data_dir].\n"
+"operating system's standards. On Linux, this path can be overridden by "
+"setting the [code]XDG_CONFIG_HOME[/code] environment variable before "
+"starting the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File "
+"paths in Godot projects[/url] in the documentation for more information. See "
+"also [method get_cache_dir] and [method get_data_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -41365,11 +41421,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] user data directory according to the operating "
-"system's standards. On desktop platforms, this path can be overridden by "
-"setting the [code]XDG_DATA_HOME[/code] environment variable before starting "
-"the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in "
-"Godot projects[/url] in the documentation for more information. See also "
-"[method get_cache_dir] and [method get_config_dir].\n"
+"system's standards. On Linux, this path can be overridden by setting the "
+"[code]XDG_DATA_HOME[/code] environment variable before starting the project. "
+"See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot "
+"projects[/url] in the documentation for more information. See also [method "
+"get_cache_dir] and [method get_config_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -43240,6 +43296,16 @@ msgid "Particle systems (2D)"
msgstr ""
#: doc/classes/Particles2D.xml
+msgid "2D Particles Demo"
+msgstr ""
+
+#: doc/classes/Particles2D.xml
+msgid ""
+"2D Dodge The Creeps Demo (uses GPUParticles2D for the trail behind the "
+"player)"
+msgstr ""
+
+#: doc/classes/Particles2D.xml
msgid "Returns a rectangle containing the positions of all existing particles."
msgstr ""
@@ -50843,15 +50909,22 @@ msgstr ""
#: doc/classes/ProjectSettings.xml
msgid ""
"If [code]true[/code], uses a fast post-processing filter to make banding "
-"significantly less visible. In some cases, debanding may introduce a "
-"slightly noticeable dithering pattern. It's recommended to enable debanding "
-"only when actually needed since the dithering pattern will make lossless-"
-"compressed screenshots larger.\n"
+"significantly less visible in 3D. 2D rendering is [i]not[/i] affected by "
+"debanding unless the [member Environment.background_mode] is [constant "
+"Environment.BG_CANVAS]. In this case, [member rendering/quality/"
+"intended_usage/framebuffer_allocation] must also be set to [b]3D[/b].\n"
+"In some cases, debanding may introduce a slightly noticeable dithering "
+"pattern. It's recommended to enable debanding only when actually needed "
+"since the dithering pattern will make lossless-compressed screenshots "
+"larger.\n"
"[b]Note:[/b] Only available on the GLES3 backend. [member rendering/quality/"
"depth/hdr] must also be [code]true[/code] for debanding to be effective.\n"
"[b]Note:[/b] There are known issues with debanding breaking rendering on "
"mobile platforms. Due to this, it is recommended to leave this option "
-"disabled when targeting mobile platforms."
+"disabled when targeting mobile platforms.\n"
+"[b]Note:[/b] This property is only read when the project starts. To set "
+"debanding at run-time, set [member Viewport.debanding] on the root "
+"[Viewport] instead."
msgstr ""
#: doc/classes/ProjectSettings.xml
@@ -52455,17 +52528,28 @@ msgstr ""
#: modules/regex/doc_classes/RegEx.xml
msgid ""
"Searches the text for the compiled pattern. Returns a [RegExMatch] container "
-"of the first matching result if found, otherwise [code]null[/code]. The "
-"region to search within can be specified without modifying where the start "
-"and end anchor would be."
+"of the first matching result if found, otherwise [code]null[/code].\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegEx.xml
msgid ""
"Searches the text for the compiled pattern. Returns an array of [RegExMatch] "
"containers for each non-overlapping result. If no results were found, an "
-"empty array is returned instead. The region to search within can be "
-"specified without modifying where the start and end anchor would be."
+"empty array is returned instead.\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegEx.xml
@@ -52474,8 +52558,14 @@ msgid ""
"specified string. Escapes and backreferences such as [code]$1[/code] and "
"[code]$name[/code] are expanded and resolved. By default, only the first "
"instance is replaced, but it can be changed for all instances (global "
-"replacement). The region to search within can be specified without modifying "
-"where the start and end anchor would be."
+"replacement).\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegExMatch.xml
@@ -55191,7 +55281,11 @@ msgid "Call a group immediately (calls are normally made on idle)."
msgstr ""
#: doc/classes/SceneTree.xml
-msgid "Call a group only once even if the call is executed many times."
+msgid ""
+"Call a group only once even if the call is executed many times.\n"
+"[b]Note:[/b] Arguments are not taken into account when deciding whether the "
+"call is unique or not. Therefore when the same method is called with "
+"different arguments, only the first call will be performed."
msgstr ""
#: doc/classes/SceneTree.xml
@@ -57028,7 +57122,9 @@ msgid ""
"[b]Note:[/b] Mixed negative scales in 3D are not decomposable from the "
"transformation matrix. Due to the way scale is represented with "
"transformation matrices in Godot, the scale values will either be all "
-"positive or all negative."
+"positive or all negative.\n"
+"[b]Note:[/b] Not all nodes are visually scaled by the [member scale] "
+"property. For example, [Light]s are not visually affected by [member scale]."
msgstr ""
#: doc/classes/Spatial.xml
@@ -58408,7 +58504,10 @@ msgid ""
msgstr ""
#: doc/classes/SpotLight.xml
-msgid "The spotlight's angle in degrees."
+msgid ""
+"The spotlight's angle in degrees.\n"
+"[b]Note:[/b] [member spot_angle] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/SpotLight.xml
@@ -58424,7 +58523,9 @@ msgid ""
"The maximal range that can be reached by the spotlight. Note that the "
"effectively lit area may appear to be smaller depending on the [member "
"spot_attenuation] in use. No matter the [member spot_attenuation] in use, "
-"the light will never reach anything outside this range."
+"the light will never reach anything outside this range.\n"
+"[b]Note:[/b] [member spot_range] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/SpringArm.xml
@@ -67701,10 +67802,15 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
"If [code]true[/code], uses a fast post-processing filter to make banding "
-"significantly less visible. In some cases, debanding may introduce a "
-"slightly noticeable dithering pattern. It's recommended to enable debanding "
-"only when actually needed since the dithering pattern will make lossless-"
-"compressed screenshots larger.\n"
+"significantly less visible in 3D. 2D rendering is [i]not[/i] affected by "
+"debanding unless the [member Environment.background_mode] is [constant "
+"Environment.BG_CANVAS]. In this case, [member usage] must also be set to "
+"[constant USAGE_3D]. See also [member ProjectSettings.rendering/quality/"
+"filters/use_debanding].\n"
+"In some cases, debanding may introduce a slightly noticeable dithering "
+"pattern. It's recommended to enable debanding only when actually needed "
+"since the dithering pattern will make lossless-compressed screenshots "
+"larger.\n"
"[b]Note:[/b] Only available on the GLES3 backend. [member hdr] must also be "
"[code]true[/code] for debanding to be effective."
msgstr ""
@@ -67715,8 +67821,8 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
-"If [code]true[/code], the viewport will disable 3D rendering. For actual "
-"disabling use [code]usage[/code]."
+"If [code]true[/code], the viewport will disable 3D rendering. To actually "
+"disable allocation of 3D buffers, set [member usage] instead."
msgstr ""
#: doc/classes/Viewport.xml
@@ -67872,7 +67978,9 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
-"The rendering mode of viewport.\n"
+"The viewport's rendering mode. This controls which buffers are allocated for "
+"the viewport (2D only, or 2D + 3D). 2D-only options can reduce memory usage "
+"and improve performance slightly, especially on low-end devices.\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."
@@ -68404,6 +68512,22 @@ msgid ""
"render object this [VisualInstance] is set to."
msgstr ""
+#: doc/classes/VisualInstance.xml
+msgid ""
+"The sorting offset used by this [VisualInstance]. Adjusting it to a higher "
+"value will make the [VisualInstance] reliably draw on top of other "
+"[VisualInstance]s that are otherwise positioned at the same spot."
+msgstr ""
+
+#: doc/classes/VisualInstance.xml
+msgid ""
+"If [code]true[/code], the object is sorted based on the [AABB] center. "
+"Sorted based on the global position otherwise.\n"
+"The [AABB] center based sorting is generally more accurate for 3D models. "
+"The position based sorting instead allows to better control the drawing "
+"order when working with [Particles] and [CPUParticles]."
+msgstr ""
+
#: modules/visual_script/doc_classes/VisualScript.xml
msgid "A script implemented in the Visual Script programming environment."
msgstr ""
diff --git a/doc/translations/uk.po b/doc/translations/uk.po
index 613cc32ed3..3714c11d88 100644
--- a/doc/translations/uk.po
+++ b/doc/translations/uk.po
@@ -15,12 +15,13 @@
# Гліб Соколов <ramithes@i.ua>, 2022.
# Yan Chen <cyan97087@gmail.com>, 2022.
# Богдан Матвіїв <bomtvv@gmail.com>, 2022.
+# Лев ДворÑкий <ne3r0n@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-08-23 03:39+0000\n"
-"Last-Translator: Богдан Матвіїв <bomtvv@gmail.com>\n"
+"PO-Revision-Date: 2022-11-25 12:13+0000\n"
+"Last-Translator: Лев ДворÑкий <ne3r0n@gmail.com>\n"
"Language-Team: Ukrainian <https://hosted.weblate.org/projects/godot-engine/"
"godot-class-reference/uk/>\n"
"Language: uk\n"
@@ -29,7 +30,7 @@ msgstr ""
"Content-Transfer-Encoding: 8-bit\n"
"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
-"X-Generator: Weblate 4.14-dev\n"
+"X-Generator: Weblate 4.15-dev\n"
#: doc/tools/make_rst.py
msgid "Description"
@@ -85,7 +86,6 @@ msgid "Inherited By:"
msgstr "УÑпадковано:"
#: doc/tools/make_rst.py
-#, fuzzy
msgid "(overrides %s)"
msgstr "(перевизначає %s)"
@@ -94,17 +94,14 @@ msgid "Default"
msgstr "Типовий"
#: doc/tools/make_rst.py
-#, fuzzy
msgid "Setter"
msgstr "Ð’Ñтановлювач"
#: doc/tools/make_rst.py
-#, fuzzy
msgid "value"
msgstr "значеннÑ"
#: doc/tools/make_rst.py
-#, fuzzy
msgid "Getter"
msgstr "Отримувач"
@@ -609,7 +606,8 @@ msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
-"Returns an array of dictionaries representing the current call stack.\n"
+"Returns an array of dictionaries representing the current call stack. See "
+"also [method print_stack].\n"
"[codeblock]\n"
"func _ready():\n"
" foo()\n"
@@ -624,7 +622,11 @@ msgid ""
"[codeblock]\n"
"[{function:bar, line:12, source:res://script.gd}, {function:foo, line:9, "
"source:res://script.gd}, {function:_ready, line:6, source:res://script.gd}]\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] [method get_stack] only works if the running instance is "
+"connected to a debugging server (i.e. an editor instance). [method "
+"get_stack] will not work in projects exported in release mode, or in "
+"projects exported in debug mode if not connected to a debugging server."
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -1001,12 +1003,16 @@ msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
-"Prints a stack track at code location, only works when running with debugger "
-"turned on.\n"
+"Prints a stack trace at the current code location. See also [method "
+"get_stack].\n"
"Output in the console would look something like this:\n"
"[codeblock]\n"
"Frame 0 - res://test.gd:16 in function '_process'\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] [method print_stack] only works if the running instance is "
+"connected to a debugging server (i.e. an editor instance). [method "
+"print_stack] will not work in projects exported in release mode, or in "
+"projects exported in debug mode if not connected to a debugging server."
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -3624,6 +3630,26 @@ msgid "Hints that an image is compressed using lossless compression."
msgstr ""
#: doc/classes/@GlobalScope.xml
+msgid ""
+"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:\n"
+"[codeblock]\n"
+"hint_string = \"%s:\" % [TYPE_INT] # Array of inteters.\n"
+"hint_string = \"%s:%s:\" % [TYPE_ARRAY, TYPE_REAL] # Two-dimensional array "
+"of floats.\n"
+"hint_string = \"%s/%s:Resource\" % [TYPE_OBJECT, TYPE_OBJECT] # Array of "
+"resources.\n"
+"hint_string = \"%s:%s/%s:Resource\" % [TYPE_ARRAY, TYPE_OBJECT, TYPE_OBJECT] "
+"# Two-dimensional array of resources.\n"
+"[/codeblock]\n"
+"[b]Note:[/b] The final colon is required to specify for properly detecting "
+"built-in types."
+msgstr ""
+
+#: doc/classes/@GlobalScope.xml
msgid "The property is serialized and saved in the scene file (default)."
msgstr ""
@@ -4308,8 +4334,7 @@ msgstr "ÐÐ½Ñ–Ð¼Ð°Ñ†Ñ–Ñ 2D Ñпрайтів"
#: doc/classes/AudioStreamPlayer.xml doc/classes/Button.xml
#: doc/classes/CanvasLayer.xml doc/classes/CollisionShape2D.xml
#: doc/classes/ColorRect.xml doc/classes/Input.xml doc/classes/InputEvent.xml
-#: doc/classes/InputEventAction.xml doc/classes/Label.xml
-#: doc/classes/Particles2D.xml doc/classes/Timer.xml
+#: doc/classes/InputEventAction.xml doc/classes/Label.xml doc/classes/Timer.xml
#: doc/classes/VisibilityNotifier2D.xml
msgid "2D Dodge The Creeps Demo"
msgstr ""
@@ -7234,7 +7259,10 @@ msgid ""
"var array = []\n"
"array.resize(10)\n"
"array.fill(0) # Initialize the 10 elements to 0.\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] If [code]value[/code] is of a reference type ([Object]-derived, "
+"[Array], [Dictionary], etc.) then the array is filled with the references to "
+"the same object, i.e. no duplicates are created."
msgstr ""
#: doc/classes/Array.xml doc/classes/PoolByteArray.xml
@@ -7419,6 +7447,9 @@ msgstr ""
#: doc/classes/Array.xml
msgid ""
"Sorts the array.\n"
+"[b]Note:[/b] The sorting algorithm used is not [url=https://en.wikipedia.org/"
+"wiki/Sorting_algorithm#Stability]stable[/url]. This means that values "
+"considered equal may have their order changed when using [method sort].\n"
"[b]Note:[/b] Strings are sorted in alphabetical order (as opposed to natural "
"order). This may lead to unexpected behavior when sorting an array of "
"strings ending with a sequence of numbers. Consider the following example:\n"
@@ -7438,9 +7469,13 @@ msgid ""
"For two elements [code]a[/code] and [code]b[/code], if the given method "
"returns [code]true[/code], element [code]b[/code] will be after element "
"[code]a[/code] in the array.\n"
+"[b]Note:[/b] The sorting algorithm used is not [url=https://en.wikipedia.org/"
+"wiki/Sorting_algorithm#Stability]stable[/url]. This means that values "
+"considered equal may have their order changed when using [method "
+"sort_custom].\n"
"[b]Note:[/b] You cannot randomize the return value as the heapsort algorithm "
-"expects a deterministic result. Doing so will result in unexpected "
-"behavior.\n"
+"expects a deterministic result. Randomizing the return value will result in "
+"unexpected behavior.\n"
"[codeblock]\n"
"class MyCustomSorter:\n"
" static func sort_ascending(a, b):\n"
@@ -10079,10 +10114,9 @@ msgstr ""
#: doc/classes/AudioStreamGeneratorPlayback.xml
msgid ""
-"Returns the number of audio data frames left to play. If this returned "
-"number reaches [code]0[/code], the audio will stop playing until frames are "
-"added again. Therefore, make sure your script can always generate and push "
-"new audio frames fast enough to avoid audio cracking."
+"Returns the number of frames that can be pushed to the audio sample data "
+"buffer without overflowing it. If the result is [code]0[/code], the buffer "
+"is full."
msgstr ""
#: doc/classes/AudioStreamGeneratorPlayback.xml
@@ -10614,14 +10648,14 @@ msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
"Node for back-buffering the currently-displayed screen. The region defined "
-"in the BackBufferCopy node is buffered with the content of the screen it "
+"in the [BackBufferCopy] node is buffered with the content of the screen it "
"covers, or the entire screen according to the copy mode set. Use the "
"[code]texture(SCREEN_TEXTURE, ...)[/code] function in your shader scripts to "
"access the buffer.\n"
"[b]Note:[/b] Since this node inherits from [Node2D] (and not [Control]), "
"anchors and margins won't apply to child [Control]-derived nodes. This can "
"be problematic when resizing the window. To avoid this, add [Control]-"
-"derived nodes as [i]siblings[/i] to the BackBufferCopy node instead of "
+"derived nodes as [i]siblings[/i] to the [BackBufferCopy] node instead of "
"adding them as children."
msgstr ""
@@ -10631,22 +10665,22 @@ msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
-"The area covered by the BackBufferCopy. Only used if [member copy_mode] is "
+"The area covered by the [BackBufferCopy]. Only used if [member copy_mode] is "
"[constant COPY_MODE_RECT]."
msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
-"Disables the buffering mode. This means the BackBufferCopy node will "
+"Disables the buffering mode. This means the [BackBufferCopy] node will "
"directly use the portion of screen it covers."
msgstr ""
#: doc/classes/BackBufferCopy.xml
-msgid "BackBufferCopy buffers a rectangular region."
+msgid "[BackBufferCopy] buffers a rectangular region."
msgstr ""
#: doc/classes/BackBufferCopy.xml
-msgid "BackBufferCopy buffers the entire screen."
+msgid "[BackBufferCopy] buffers the entire screen."
msgstr ""
#: doc/classes/BakedLightmap.xml
@@ -19445,6 +19479,14 @@ msgid "Cylinder shape for collisions."
msgstr ""
#: doc/classes/CylinderShape.xml
+msgid ""
+"Cylinder shape for collisions.\n"
+"[b]Note:[/b] When using GodotPhysics instead of the default Bullet physics "
+"engine, there are several known bugs with cylinder collision shapes. Using "
+"[CapsuleShape] or [BoxShape] instead is recommended."
+msgstr ""
+
+#: doc/classes/CylinderShape.xml
msgid "The cylinder's height."
msgstr ""
@@ -22279,7 +22321,10 @@ msgid ""
"[/codeblock]\n"
"[b]Note:[/b] The script is run in the Editor context, which means the output "
"is visible in the console window started with the Editor (stdout) instead of "
-"the usual Godot [b]Output[/b] dock."
+"the usual Godot [b]Output[/b] dock.\n"
+"[b]Note:[/b] EditorScript is reference counted, meaning it is destroyed when "
+"nothing references it. This can cause errors during asynchronous operations "
+"if there are no references to the script."
msgstr ""
#: doc/classes/EditorScript.xml
@@ -33015,7 +33060,9 @@ msgid ""
"The size of the light in Godot units. Only considered in baked lightmaps and "
"only if [member light_bake_mode] is set to [constant BAKE_ALL]. Increasing "
"this value will make the shadows appear blurrier. This can be used to "
-"simulate area lights to an extent."
+"simulate area lights to an extent.\n"
+"[b]Note:[/b] [member light_size] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/Light.xml
@@ -36345,7 +36392,10 @@ msgid ""
"use the [method get_next_location] function once every physics frame to "
"update the internal path logic of the NavigationAgent. The returned vector "
"position from this function should be used as the next movement position for "
-"the agent's parent Node."
+"the agent's parent Node.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues."
msgstr ""
#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
@@ -36595,7 +36645,10 @@ msgid ""
"use the [method get_next_location] function once every physics frame to "
"update the internal path logic of the NavigationAgent. The returned vector "
"position from this function should be used as the next movement position for "
-"the agent's parent Node."
+"the agent's parent Node.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues."
msgstr ""
#: doc/classes/NavigationAgent2D.xml
@@ -37312,6 +37365,9 @@ msgid ""
"modified velocity as-is might lead to pushing and agent outside of a "
"navigable area. This is a limitation of the collision avoidance system, any "
"more complex situation may require the use of the physics engine.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues.\n"
"This server keeps tracks of any call and executes them during the sync "
"phase. This means that you can request any change to the map, using any "
"thread, without worrying."
@@ -40122,7 +40178,9 @@ msgid ""
"The light's radius. Note that the effectively lit area may appear to be "
"smaller depending on the [member omni_attenuation] in use. No matter the "
"[member omni_attenuation] in use, the light will never reach anything "
-"outside this radius."
+"outside this radius.\n"
+"[b]Note:[/b] [member omni_range] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -40638,11 +40696,11 @@ msgstr "Повертає кут до заданого вектора у раді
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] cache data directory according to the operating "
-"system's standards. On desktop platforms, this path can be overridden by "
-"setting the [code]XDG_CACHE_HOME[/code] environment variable before starting "
-"the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in "
-"Godot projects[/url] in the documentation for more information. See also "
-"[method get_config_dir] and [method get_data_dir].\n"
+"system's standards. On Linux, this path can be overridden by setting the "
+"[code]XDG_CACHE_HOME[/code] environment variable before starting the "
+"project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot "
+"projects[/url] in the documentation for more information. See also [method "
+"get_config_dir] and [method get_data_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -40676,11 +40734,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] user configuration directory according to the "
-"operating system's standards. On desktop platforms, this path can be "
-"overridden by setting the [code]XDG_CONFIG_HOME[/code] environment variable "
-"before starting the project. See [url=$DOCS_URL/tutorials/io/data_paths."
-"html]File paths in Godot projects[/url] in the documentation for more "
-"information. See also [method get_cache_dir] and [method get_data_dir].\n"
+"operating system's standards. On Linux, this path can be overridden by "
+"setting the [code]XDG_CONFIG_HOME[/code] environment variable before "
+"starting the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File "
+"paths in Godot projects[/url] in the documentation for more information. See "
+"also [method get_cache_dir] and [method get_data_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -40702,11 +40760,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] user data directory according to the operating "
-"system's standards. On desktop platforms, this path can be overridden by "
-"setting the [code]XDG_DATA_HOME[/code] environment variable before starting "
-"the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in "
-"Godot projects[/url] in the documentation for more information. See also "
-"[method get_cache_dir] and [method get_config_dir].\n"
+"system's standards. On Linux, this path can be overridden by setting the "
+"[code]XDG_DATA_HOME[/code] environment variable before starting the project. "
+"See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot "
+"projects[/url] in the documentation for more information. See also [method "
+"get_cache_dir] and [method get_config_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -42571,6 +42629,16 @@ msgid "Particle systems (2D)"
msgstr ""
#: doc/classes/Particles2D.xml
+msgid "2D Particles Demo"
+msgstr ""
+
+#: doc/classes/Particles2D.xml
+msgid ""
+"2D Dodge The Creeps Demo (uses GPUParticles2D for the trail behind the "
+"player)"
+msgstr ""
+
+#: doc/classes/Particles2D.xml
msgid "Returns a rectangle containing the positions of all existing particles."
msgstr ""
@@ -50172,15 +50240,22 @@ msgstr ""
#: doc/classes/ProjectSettings.xml
msgid ""
"If [code]true[/code], uses a fast post-processing filter to make banding "
-"significantly less visible. In some cases, debanding may introduce a "
-"slightly noticeable dithering pattern. It's recommended to enable debanding "
-"only when actually needed since the dithering pattern will make lossless-"
-"compressed screenshots larger.\n"
+"significantly less visible in 3D. 2D rendering is [i]not[/i] affected by "
+"debanding unless the [member Environment.background_mode] is [constant "
+"Environment.BG_CANVAS]. In this case, [member rendering/quality/"
+"intended_usage/framebuffer_allocation] must also be set to [b]3D[/b].\n"
+"In some cases, debanding may introduce a slightly noticeable dithering "
+"pattern. It's recommended to enable debanding only when actually needed "
+"since the dithering pattern will make lossless-compressed screenshots "
+"larger.\n"
"[b]Note:[/b] Only available on the GLES3 backend. [member rendering/quality/"
"depth/hdr] must also be [code]true[/code] for debanding to be effective.\n"
"[b]Note:[/b] There are known issues with debanding breaking rendering on "
"mobile platforms. Due to this, it is recommended to leave this option "
-"disabled when targeting mobile platforms."
+"disabled when targeting mobile platforms.\n"
+"[b]Note:[/b] This property is only read when the project starts. To set "
+"debanding at run-time, set [member Viewport.debanding] on the root "
+"[Viewport] instead."
msgstr ""
#: doc/classes/ProjectSettings.xml
@@ -51777,17 +51852,28 @@ msgstr ""
#: modules/regex/doc_classes/RegEx.xml
msgid ""
"Searches the text for the compiled pattern. Returns a [RegExMatch] container "
-"of the first matching result if found, otherwise [code]null[/code]. The "
-"region to search within can be specified without modifying where the start "
-"and end anchor would be."
+"of the first matching result if found, otherwise [code]null[/code].\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegEx.xml
msgid ""
"Searches the text for the compiled pattern. Returns an array of [RegExMatch] "
"containers for each non-overlapping result. If no results were found, an "
-"empty array is returned instead. The region to search within can be "
-"specified without modifying where the start and end anchor would be."
+"empty array is returned instead.\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegEx.xml
@@ -51796,8 +51882,14 @@ msgid ""
"specified string. Escapes and backreferences such as [code]$1[/code] and "
"[code]$name[/code] are expanded and resolved. By default, only the first "
"instance is replaced, but it can be changed for all instances (global "
-"replacement). The region to search within can be specified without modifying "
-"where the start and end anchor would be."
+"replacement).\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegExMatch.xml
@@ -54513,7 +54605,11 @@ msgid "Call a group immediately (calls are normally made on idle)."
msgstr ""
#: doc/classes/SceneTree.xml
-msgid "Call a group only once even if the call is executed many times."
+msgid ""
+"Call a group only once even if the call is executed many times.\n"
+"[b]Note:[/b] Arguments are not taken into account when deciding whether the "
+"call is unique or not. Therefore when the same method is called with "
+"different arguments, only the first call will be performed."
msgstr ""
#: doc/classes/SceneTree.xml
@@ -56351,7 +56447,9 @@ msgid ""
"[b]Note:[/b] Mixed negative scales in 3D are not decomposable from the "
"transformation matrix. Due to the way scale is represented with "
"transformation matrices in Godot, the scale values will either be all "
-"positive or all negative."
+"positive or all negative.\n"
+"[b]Note:[/b] Not all nodes are visually scaled by the [member scale] "
+"property. For example, [Light]s are not visually affected by [member scale]."
msgstr ""
#: doc/classes/Spatial.xml
@@ -57729,7 +57827,10 @@ msgid ""
msgstr ""
#: doc/classes/SpotLight.xml
-msgid "The spotlight's angle in degrees."
+msgid ""
+"The spotlight's angle in degrees.\n"
+"[b]Note:[/b] [member spot_angle] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/SpotLight.xml
@@ -57745,7 +57846,9 @@ msgid ""
"The maximal range that can be reached by the spotlight. Note that the "
"effectively lit area may appear to be smaller depending on the [member "
"spot_attenuation] in use. No matter the [member spot_attenuation] in use, "
-"the light will never reach anything outside this range."
+"the light will never reach anything outside this range.\n"
+"[b]Note:[/b] [member spot_range] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/SpringArm.xml
@@ -67031,10 +67134,15 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
"If [code]true[/code], uses a fast post-processing filter to make banding "
-"significantly less visible. In some cases, debanding may introduce a "
-"slightly noticeable dithering pattern. It's recommended to enable debanding "
-"only when actually needed since the dithering pattern will make lossless-"
-"compressed screenshots larger.\n"
+"significantly less visible in 3D. 2D rendering is [i]not[/i] affected by "
+"debanding unless the [member Environment.background_mode] is [constant "
+"Environment.BG_CANVAS]. In this case, [member usage] must also be set to "
+"[constant USAGE_3D]. See also [member ProjectSettings.rendering/quality/"
+"filters/use_debanding].\n"
+"In some cases, debanding may introduce a slightly noticeable dithering "
+"pattern. It's recommended to enable debanding only when actually needed "
+"since the dithering pattern will make lossless-compressed screenshots "
+"larger.\n"
"[b]Note:[/b] Only available on the GLES3 backend. [member hdr] must also be "
"[code]true[/code] for debanding to be effective."
msgstr ""
@@ -67045,8 +67153,8 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
-"If [code]true[/code], the viewport will disable 3D rendering. For actual "
-"disabling use [code]usage[/code]."
+"If [code]true[/code], the viewport will disable 3D rendering. To actually "
+"disable allocation of 3D buffers, set [member usage] instead."
msgstr ""
#: doc/classes/Viewport.xml
@@ -67198,7 +67306,9 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
-"The rendering mode of viewport.\n"
+"The viewport's rendering mode. This controls which buffers are allocated for "
+"the viewport (2D only, or 2D + 3D). 2D-only options can reduce memory usage "
+"and improve performance slightly, especially on low-end devices.\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."
@@ -67730,6 +67840,22 @@ msgid ""
"render object this [VisualInstance] is set to."
msgstr ""
+#: doc/classes/VisualInstance.xml
+msgid ""
+"The sorting offset used by this [VisualInstance]. Adjusting it to a higher "
+"value will make the [VisualInstance] reliably draw on top of other "
+"[VisualInstance]s that are otherwise positioned at the same spot."
+msgstr ""
+
+#: doc/classes/VisualInstance.xml
+msgid ""
+"If [code]true[/code], the object is sorted based on the [AABB] center. "
+"Sorted based on the global position otherwise.\n"
+"The [AABB] center based sorting is generally more accurate for 3D models. "
+"The position based sorting instead allows to better control the drawing "
+"order when working with [Particles] and [CPUParticles]."
+msgstr ""
+
#: modules/visual_script/doc_classes/VisualScript.xml
msgid "A script implemented in the Visual Script programming environment."
msgstr ""
diff --git a/doc/translations/vi.po b/doc/translations/vi.po
index 3e74e52436..962440bfab 100644
--- a/doc/translations/vi.po
+++ b/doc/translations/vi.po
@@ -689,8 +689,10 @@ msgstr ""
"[/codeblock]"
#: modules/gdscript/doc_classes/@GDScript.xml
+#, fuzzy
msgid ""
-"Returns an array of dictionaries representing the current call stack.\n"
+"Returns an array of dictionaries representing the current call stack. See "
+"also [method print_stack].\n"
"[codeblock]\n"
"func _ready():\n"
" foo()\n"
@@ -705,7 +707,11 @@ msgid ""
"[codeblock]\n"
"[{function:bar, line:12, source:res://script.gd}, {function:foo, line:9, "
"source:res://script.gd}, {function:_ready, line:6, source:res://script.gd}]\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] [method get_stack] only works if the running instance is "
+"connected to a debugging server (i.e. an editor instance). [method "
+"get_stack] will not work in projects exported in release mode, or in "
+"projects exported in debug mode if not connected to a debugging server."
msgstr ""
"Trả vỠmột mảng từ điển đại diện cho chồng đệ quy hiện tại.\n"
"[codeblock]\n"
@@ -1219,12 +1225,16 @@ msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
-"Prints a stack track at code location, only works when running with debugger "
-"turned on.\n"
+"Prints a stack trace at the current code location. See also [method "
+"get_stack].\n"
"Output in the console would look something like this:\n"
"[codeblock]\n"
"Frame 0 - res://test.gd:16 in function '_process'\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] [method print_stack] only works if the running instance is "
+"connected to a debugging server (i.e. an editor instance). [method "
+"print_stack] will not work in projects exported in release mode, or in "
+"projects exported in debug mode if not connected to a debugging server."
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -3908,6 +3918,26 @@ msgid "Hints that an image is compressed using lossless compression."
msgstr ""
#: doc/classes/@GlobalScope.xml
+msgid ""
+"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:\n"
+"[codeblock]\n"
+"hint_string = \"%s:\" % [TYPE_INT] # Array of inteters.\n"
+"hint_string = \"%s:%s:\" % [TYPE_ARRAY, TYPE_REAL] # Two-dimensional array "
+"of floats.\n"
+"hint_string = \"%s/%s:Resource\" % [TYPE_OBJECT, TYPE_OBJECT] # Array of "
+"resources.\n"
+"hint_string = \"%s:%s/%s:Resource\" % [TYPE_ARRAY, TYPE_OBJECT, TYPE_OBJECT] "
+"# Two-dimensional array of resources.\n"
+"[/codeblock]\n"
+"[b]Note:[/b] The final colon is required to specify for properly detecting "
+"built-in types."
+msgstr ""
+
+#: doc/classes/@GlobalScope.xml
msgid "The property is serialized and saved in the scene file (default)."
msgstr ""
@@ -4601,8 +4631,7 @@ msgstr ""
#: doc/classes/AudioStreamPlayer.xml doc/classes/Button.xml
#: doc/classes/CanvasLayer.xml doc/classes/CollisionShape2D.xml
#: doc/classes/ColorRect.xml doc/classes/Input.xml doc/classes/InputEvent.xml
-#: doc/classes/InputEventAction.xml doc/classes/Label.xml
-#: doc/classes/Particles2D.xml doc/classes/Timer.xml
+#: doc/classes/InputEventAction.xml doc/classes/Label.xml doc/classes/Timer.xml
#: doc/classes/VisibilityNotifier2D.xml
msgid "2D Dodge The Creeps Demo"
msgstr ""
@@ -7539,7 +7568,10 @@ msgid ""
"var array = []\n"
"array.resize(10)\n"
"array.fill(0) # Initialize the 10 elements to 0.\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] If [code]value[/code] is of a reference type ([Object]-derived, "
+"[Array], [Dictionary], etc.) then the array is filled with the references to "
+"the same object, i.e. no duplicates are created."
msgstr ""
#: doc/classes/Array.xml doc/classes/PoolByteArray.xml
@@ -7724,6 +7756,9 @@ msgstr ""
#: doc/classes/Array.xml
msgid ""
"Sorts the array.\n"
+"[b]Note:[/b] The sorting algorithm used is not [url=https://en.wikipedia.org/"
+"wiki/Sorting_algorithm#Stability]stable[/url]. This means that values "
+"considered equal may have their order changed when using [method sort].\n"
"[b]Note:[/b] Strings are sorted in alphabetical order (as opposed to natural "
"order). This may lead to unexpected behavior when sorting an array of "
"strings ending with a sequence of numbers. Consider the following example:\n"
@@ -7743,9 +7778,13 @@ msgid ""
"For two elements [code]a[/code] and [code]b[/code], if the given method "
"returns [code]true[/code], element [code]b[/code] will be after element "
"[code]a[/code] in the array.\n"
+"[b]Note:[/b] The sorting algorithm used is not [url=https://en.wikipedia.org/"
+"wiki/Sorting_algorithm#Stability]stable[/url]. This means that values "
+"considered equal may have their order changed when using [method "
+"sort_custom].\n"
"[b]Note:[/b] You cannot randomize the return value as the heapsort algorithm "
-"expects a deterministic result. Doing so will result in unexpected "
-"behavior.\n"
+"expects a deterministic result. Randomizing the return value will result in "
+"unexpected behavior.\n"
"[codeblock]\n"
"class MyCustomSorter:\n"
" static func sort_ascending(a, b):\n"
@@ -10384,10 +10423,9 @@ msgstr ""
#: doc/classes/AudioStreamGeneratorPlayback.xml
msgid ""
-"Returns the number of audio data frames left to play. If this returned "
-"number reaches [code]0[/code], the audio will stop playing until frames are "
-"added again. Therefore, make sure your script can always generate and push "
-"new audio frames fast enough to avoid audio cracking."
+"Returns the number of frames that can be pushed to the audio sample data "
+"buffer without overflowing it. If the result is [code]0[/code], the buffer "
+"is full."
msgstr ""
#: doc/classes/AudioStreamGeneratorPlayback.xml
@@ -10919,14 +10957,14 @@ msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
"Node for back-buffering the currently-displayed screen. The region defined "
-"in the BackBufferCopy node is buffered with the content of the screen it "
+"in the [BackBufferCopy] node is buffered with the content of the screen it "
"covers, or the entire screen according to the copy mode set. Use the "
"[code]texture(SCREEN_TEXTURE, ...)[/code] function in your shader scripts to "
"access the buffer.\n"
"[b]Note:[/b] Since this node inherits from [Node2D] (and not [Control]), "
"anchors and margins won't apply to child [Control]-derived nodes. This can "
"be problematic when resizing the window. To avoid this, add [Control]-"
-"derived nodes as [i]siblings[/i] to the BackBufferCopy node instead of "
+"derived nodes as [i]siblings[/i] to the [BackBufferCopy] node instead of "
"adding them as children."
msgstr ""
@@ -10936,22 +10974,22 @@ msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
-"The area covered by the BackBufferCopy. Only used if [member copy_mode] is "
+"The area covered by the [BackBufferCopy]. Only used if [member copy_mode] is "
"[constant COPY_MODE_RECT]."
msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
-"Disables the buffering mode. This means the BackBufferCopy node will "
+"Disables the buffering mode. This means the [BackBufferCopy] node will "
"directly use the portion of screen it covers."
msgstr ""
#: doc/classes/BackBufferCopy.xml
-msgid "BackBufferCopy buffers a rectangular region."
+msgid "[BackBufferCopy] buffers a rectangular region."
msgstr ""
#: doc/classes/BackBufferCopy.xml
-msgid "BackBufferCopy buffers the entire screen."
+msgid "[BackBufferCopy] buffers the entire screen."
msgstr ""
#: doc/classes/BakedLightmap.xml
@@ -19754,6 +19792,14 @@ msgid "Cylinder shape for collisions."
msgstr ""
#: doc/classes/CylinderShape.xml
+msgid ""
+"Cylinder shape for collisions.\n"
+"[b]Note:[/b] When using GodotPhysics instead of the default Bullet physics "
+"engine, there are several known bugs with cylinder collision shapes. Using "
+"[CapsuleShape] or [BoxShape] instead is recommended."
+msgstr ""
+
+#: doc/classes/CylinderShape.xml
msgid "The cylinder's height."
msgstr ""
@@ -22589,7 +22635,10 @@ msgid ""
"[/codeblock]\n"
"[b]Note:[/b] The script is run in the Editor context, which means the output "
"is visible in the console window started with the Editor (stdout) instead of "
-"the usual Godot [b]Output[/b] dock."
+"the usual Godot [b]Output[/b] dock.\n"
+"[b]Note:[/b] EditorScript is reference counted, meaning it is destroyed when "
+"nothing references it. This can cause errors during asynchronous operations "
+"if there are no references to the script."
msgstr ""
#: doc/classes/EditorScript.xml
@@ -33325,7 +33374,9 @@ msgid ""
"The size of the light in Godot units. Only considered in baked lightmaps and "
"only if [member light_bake_mode] is set to [constant BAKE_ALL]. Increasing "
"this value will make the shadows appear blurrier. This can be used to "
-"simulate area lights to an extent."
+"simulate area lights to an extent.\n"
+"[b]Note:[/b] [member light_size] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/Light.xml
@@ -36655,7 +36706,10 @@ msgid ""
"use the [method get_next_location] function once every physics frame to "
"update the internal path logic of the NavigationAgent. The returned vector "
"position from this function should be used as the next movement position for "
-"the agent's parent Node."
+"the agent's parent Node.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues."
msgstr ""
#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
@@ -36906,7 +36960,10 @@ msgid ""
"use the [method get_next_location] function once every physics frame to "
"update the internal path logic of the NavigationAgent. The returned vector "
"position from this function should be used as the next movement position for "
-"the agent's parent Node."
+"the agent's parent Node.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues."
msgstr ""
#: doc/classes/NavigationAgent2D.xml
@@ -37626,6 +37683,9 @@ msgid ""
"modified velocity as-is might lead to pushing and agent outside of a "
"navigable area. This is a limitation of the collision avoidance system, any "
"more complex situation may require the use of the physics engine.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues.\n"
"This server keeps tracks of any call and executes them during the sync "
"phase. This means that you can request any change to the map, using any "
"thread, without worrying."
@@ -40436,7 +40496,9 @@ msgid ""
"The light's radius. Note that the effectively lit area may appear to be "
"smaller depending on the [member omni_attenuation] in use. No matter the "
"[member omni_attenuation] in use, the light will never reach anything "
-"outside this radius."
+"outside this radius.\n"
+"[b]Note:[/b] [member omni_range] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -40952,11 +41014,11 @@ msgstr "Trả vỠsin nghịch đảo của tham số."
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] cache data directory according to the operating "
-"system's standards. On desktop platforms, this path can be overridden by "
-"setting the [code]XDG_CACHE_HOME[/code] environment variable before starting "
-"the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in "
-"Godot projects[/url] in the documentation for more information. See also "
-"[method get_config_dir] and [method get_data_dir].\n"
+"system's standards. On Linux, this path can be overridden by setting the "
+"[code]XDG_CACHE_HOME[/code] environment variable before starting the "
+"project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot "
+"projects[/url] in the documentation for more information. See also [method "
+"get_config_dir] and [method get_data_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -40990,11 +41052,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] user configuration directory according to the "
-"operating system's standards. On desktop platforms, this path can be "
-"overridden by setting the [code]XDG_CONFIG_HOME[/code] environment variable "
-"before starting the project. See [url=$DOCS_URL/tutorials/io/data_paths."
-"html]File paths in Godot projects[/url] in the documentation for more "
-"information. See also [method get_cache_dir] and [method get_data_dir].\n"
+"operating system's standards. On Linux, this path can be overridden by "
+"setting the [code]XDG_CONFIG_HOME[/code] environment variable before "
+"starting the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File "
+"paths in Godot projects[/url] in the documentation for more information. See "
+"also [method get_cache_dir] and [method get_data_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -41016,11 +41078,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] user data directory according to the operating "
-"system's standards. On desktop platforms, this path can be overridden by "
-"setting the [code]XDG_DATA_HOME[/code] environment variable before starting "
-"the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in "
-"Godot projects[/url] in the documentation for more information. See also "
-"[method get_cache_dir] and [method get_config_dir].\n"
+"system's standards. On Linux, this path can be overridden by setting the "
+"[code]XDG_DATA_HOME[/code] environment variable before starting the project. "
+"See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot "
+"projects[/url] in the documentation for more information. See also [method "
+"get_cache_dir] and [method get_config_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -42888,6 +42950,16 @@ msgid "Particle systems (2D)"
msgstr ""
#: doc/classes/Particles2D.xml
+msgid "2D Particles Demo"
+msgstr ""
+
+#: doc/classes/Particles2D.xml
+msgid ""
+"2D Dodge The Creeps Demo (uses GPUParticles2D for the trail behind the "
+"player)"
+msgstr ""
+
+#: doc/classes/Particles2D.xml
msgid "Returns a rectangle containing the positions of all existing particles."
msgstr ""
@@ -50497,15 +50569,22 @@ msgstr ""
#: doc/classes/ProjectSettings.xml
msgid ""
"If [code]true[/code], uses a fast post-processing filter to make banding "
-"significantly less visible. In some cases, debanding may introduce a "
-"slightly noticeable dithering pattern. It's recommended to enable debanding "
-"only when actually needed since the dithering pattern will make lossless-"
-"compressed screenshots larger.\n"
+"significantly less visible in 3D. 2D rendering is [i]not[/i] affected by "
+"debanding unless the [member Environment.background_mode] is [constant "
+"Environment.BG_CANVAS]. In this case, [member rendering/quality/"
+"intended_usage/framebuffer_allocation] must also be set to [b]3D[/b].\n"
+"In some cases, debanding may introduce a slightly noticeable dithering "
+"pattern. It's recommended to enable debanding only when actually needed "
+"since the dithering pattern will make lossless-compressed screenshots "
+"larger.\n"
"[b]Note:[/b] Only available on the GLES3 backend. [member rendering/quality/"
"depth/hdr] must also be [code]true[/code] for debanding to be effective.\n"
"[b]Note:[/b] There are known issues with debanding breaking rendering on "
"mobile platforms. Due to this, it is recommended to leave this option "
-"disabled when targeting mobile platforms."
+"disabled when targeting mobile platforms.\n"
+"[b]Note:[/b] This property is only read when the project starts. To set "
+"debanding at run-time, set [member Viewport.debanding] on the root "
+"[Viewport] instead."
msgstr ""
#: doc/classes/ProjectSettings.xml
@@ -52107,17 +52186,28 @@ msgstr ""
#: modules/regex/doc_classes/RegEx.xml
msgid ""
"Searches the text for the compiled pattern. Returns a [RegExMatch] container "
-"of the first matching result if found, otherwise [code]null[/code]. The "
-"region to search within can be specified without modifying where the start "
-"and end anchor would be."
+"of the first matching result if found, otherwise [code]null[/code].\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegEx.xml
msgid ""
"Searches the text for the compiled pattern. Returns an array of [RegExMatch] "
"containers for each non-overlapping result. If no results were found, an "
-"empty array is returned instead. The region to search within can be "
-"specified without modifying where the start and end anchor would be."
+"empty array is returned instead.\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegEx.xml
@@ -52126,8 +52216,14 @@ msgid ""
"specified string. Escapes and backreferences such as [code]$1[/code] and "
"[code]$name[/code] are expanded and resolved. By default, only the first "
"instance is replaced, but it can be changed for all instances (global "
-"replacement). The region to search within can be specified without modifying "
-"where the start and end anchor would be."
+"replacement).\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegExMatch.xml
@@ -54843,7 +54939,11 @@ msgid "Call a group immediately (calls are normally made on idle)."
msgstr ""
#: doc/classes/SceneTree.xml
-msgid "Call a group only once even if the call is executed many times."
+msgid ""
+"Call a group only once even if the call is executed many times.\n"
+"[b]Note:[/b] Arguments are not taken into account when deciding whether the "
+"call is unique or not. Therefore when the same method is called with "
+"different arguments, only the first call will be performed."
msgstr ""
#: doc/classes/SceneTree.xml
@@ -56682,7 +56782,9 @@ msgid ""
"[b]Note:[/b] Mixed negative scales in 3D are not decomposable from the "
"transformation matrix. Due to the way scale is represented with "
"transformation matrices in Godot, the scale values will either be all "
-"positive or all negative."
+"positive or all negative.\n"
+"[b]Note:[/b] Not all nodes are visually scaled by the [member scale] "
+"property. For example, [Light]s are not visually affected by [member scale]."
msgstr ""
#: doc/classes/Spatial.xml
@@ -58062,7 +58164,10 @@ msgid ""
msgstr ""
#: doc/classes/SpotLight.xml
-msgid "The spotlight's angle in degrees."
+msgid ""
+"The spotlight's angle in degrees.\n"
+"[b]Note:[/b] [member spot_angle] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/SpotLight.xml
@@ -58078,7 +58183,9 @@ msgid ""
"The maximal range that can be reached by the spotlight. Note that the "
"effectively lit area may appear to be smaller depending on the [member "
"spot_attenuation] in use. No matter the [member spot_attenuation] in use, "
-"the light will never reach anything outside this range."
+"the light will never reach anything outside this range.\n"
+"[b]Note:[/b] [member spot_range] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/SpringArm.xml
@@ -67357,10 +67464,15 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
"If [code]true[/code], uses a fast post-processing filter to make banding "
-"significantly less visible. In some cases, debanding may introduce a "
-"slightly noticeable dithering pattern. It's recommended to enable debanding "
-"only when actually needed since the dithering pattern will make lossless-"
-"compressed screenshots larger.\n"
+"significantly less visible in 3D. 2D rendering is [i]not[/i] affected by "
+"debanding unless the [member Environment.background_mode] is [constant "
+"Environment.BG_CANVAS]. In this case, [member usage] must also be set to "
+"[constant USAGE_3D]. See also [member ProjectSettings.rendering/quality/"
+"filters/use_debanding].\n"
+"In some cases, debanding may introduce a slightly noticeable dithering "
+"pattern. It's recommended to enable debanding only when actually needed "
+"since the dithering pattern will make lossless-compressed screenshots "
+"larger.\n"
"[b]Note:[/b] Only available on the GLES3 backend. [member hdr] must also be "
"[code]true[/code] for debanding to be effective."
msgstr ""
@@ -67371,8 +67483,8 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
-"If [code]true[/code], the viewport will disable 3D rendering. For actual "
-"disabling use [code]usage[/code]."
+"If [code]true[/code], the viewport will disable 3D rendering. To actually "
+"disable allocation of 3D buffers, set [member usage] instead."
msgstr ""
#: doc/classes/Viewport.xml
@@ -67527,7 +67639,9 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
-"The rendering mode of viewport.\n"
+"The viewport's rendering mode. This controls which buffers are allocated for "
+"the viewport (2D only, or 2D + 3D). 2D-only options can reduce memory usage "
+"and improve performance slightly, especially on low-end devices.\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."
@@ -68063,6 +68177,22 @@ msgid ""
"render object this [VisualInstance] is set to."
msgstr ""
+#: doc/classes/VisualInstance.xml
+msgid ""
+"The sorting offset used by this [VisualInstance]. Adjusting it to a higher "
+"value will make the [VisualInstance] reliably draw on top of other "
+"[VisualInstance]s that are otherwise positioned at the same spot."
+msgstr ""
+
+#: doc/classes/VisualInstance.xml
+msgid ""
+"If [code]true[/code], the object is sorted based on the [AABB] center. "
+"Sorted based on the global position otherwise.\n"
+"The [AABB] center based sorting is generally more accurate for 3D models. "
+"The position based sorting instead allows to better control the drawing "
+"order when working with [Particles] and [CPUParticles]."
+msgstr ""
+
#: modules/visual_script/doc_classes/VisualScript.xml
msgid "A script implemented in the Visual Script programming environment."
msgstr ""
diff --git a/doc/translations/zh_CN.po b/doc/translations/zh_CN.po
index cf0267429a..966ec9b0f9 100644
--- a/doc/translations/zh_CN.po
+++ b/doc/translations/zh_CN.po
@@ -59,11 +59,12 @@
# ErrorDreemurr <diandaokui@qq.com>, 2021.
# 烧风 <hk-shao@foxmail.com>, 2022.
# Yan Chen <cyan97087@gmail.com>, 2022.
+# Caten <catenhu@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-09-26 05:24+0000\n"
+"PO-Revision-Date: 2022-12-12 06:48+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"
@@ -72,7 +73,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.14.1\n"
+"X-Generator: Weblate 4.15-dev\n"
#: doc/tools/make_rst.py
msgid "Description"
@@ -685,7 +686,8 @@ msgid ""
" 1.5 0.0 0.0\n"
"[/codeblock]"
msgstr ""
-"返回 [code]a/b[/code] 的浮点模数,对正负数进行一致的循环。\n"
+",对正负数进行一致的循环返回 [code]a/b[/code] 的浮点模数,对正负数进行一致的"
+"循环。\n"
"[codeblock]\n"
"for i in 7:\n"
" var x = 0.5 * i - 1.5\n"
@@ -696,10 +698,10 @@ msgstr ""
"-1.5 -0.0 0.0\n"
"-1.0 -1.0 0.5\n"
"-0.5 -0.5 1.0\n"
-" 0.0 0.0 0.0\n"
-" 0.5 0.5 0.5\n"
-" 1.0 1.0 1.0\n"
-" 1.5 0.0 0.0\n"
+" 0.0 0.0 0.0\n"
+" 0.5 0.5 0.5\n"
+" 1.0 1.0 1.0\n"
+" 1.5 0.0 0.0\n"
"[/codeblock]"
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -717,8 +719,8 @@ msgid ""
"[/codeblock]"
msgstr ""
"返回对 [code]instance[/code] 节点中指定函数 [code]funcname[/code] 的引用。由"
-"于函数在GDScript䏭䏿˜¯ä¸€çº§å¯¹è±¡ï¼Œå› æ­¤è¯·ä½¿ç”¨ [code]funcref[/code] å°† [FuncRef] "
-"存储在å˜é‡ä¸­ï¼Œç„¶åŽå†è°ƒç”¨å®ƒã€‚\n"
+"于函数在 GDScript 䏭䏿˜¯ä¸€çº§å¯¹è±¡ï¼Œå› æ­¤è¯·ä½¿ç”¨ [code]funcref[/code] å°† "
+"[FuncRef] 存储在å˜é‡ä¸­ï¼Œç„¶åŽå†è¿›è¡Œè°ƒç”¨ã€‚\n"
"[codeblock]\n"
"func foo():\n"
" return(\"bar\")\n"
@@ -728,8 +730,10 @@ msgstr ""
"[/codeblock]"
#: modules/gdscript/doc_classes/@GDScript.xml
+#, fuzzy
msgid ""
-"Returns an array of dictionaries representing the current call stack.\n"
+"Returns an array of dictionaries representing the current call stack. See "
+"also [method print_stack].\n"
"[codeblock]\n"
"func _ready():\n"
" foo()\n"
@@ -744,7 +748,11 @@ msgid ""
"[codeblock]\n"
"[{function:bar, line:12, source:res://script.gd}, {function:foo, line:9, "
"source:res://script.gd}, {function:_ready, line:6, source:res://script.gd}]\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] [method get_stack] only works if the running instance is "
+"connected to a debugging server (i.e. an editor instance). [method "
+"get_stack] will not work in projects exported in release mode, or in "
+"projects exported in debug mode if not connected to a debugging server."
msgstr ""
"返回一个表示当å‰è°ƒç”¨å †æ ˆçš„字典数组。\n"
"[codeblock]\n"
@@ -1262,10 +1270,10 @@ msgstr ""
"-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"
+" 0 0 0\n"
+" 1 1 1\n"
+" 2 2 2\n"
+" 3 0 0\n"
"[/codeblock]"
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -1348,18 +1356,17 @@ msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
-"Prints a stack track at code location, only works when running with debugger "
-"turned on.\n"
+"Prints a stack trace at the current code location. See also [method "
+"get_stack].\n"
"Output in the console would look something like this:\n"
"[codeblock]\n"
"Frame 0 - res://test.gd:16 in function '_process'\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] [method print_stack] only works if the running instance is "
+"connected to a debugging server (i.e. an editor instance). [method "
+"print_stack] will not work in projects exported in release mode, or in "
+"projects exported in debug mode if not connected to a debugging server."
msgstr ""
-"在代ç ä½ç½®æ‰“å°å †æ ˆè½¨è¿¹ï¼Œä»…在打开调试器的情况下è¿è¡Œã€‚\n"
-"控制å°ä¸­çš„输出如下所示:\n"
-"[codeblock]\n"
-"Frame 0 - res://test.gd:16 in function '_process'\n"
-"[/codeblock]"
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
@@ -4382,6 +4389,26 @@ msgid "Hints that an image is compressed using lossless compression."
msgstr "æç¤ºä¸€ä¸ªå›¾ç‰‡ä½¿ç”¨äº†æ— æŸåŽ‹ç¼©è¿›è¡ŒåŽ‹ç¼©ã€‚"
#: doc/classes/@GlobalScope.xml
+msgid ""
+"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:\n"
+"[codeblock]\n"
+"hint_string = \"%s:\" % [TYPE_INT] # Array of inteters.\n"
+"hint_string = \"%s:%s:\" % [TYPE_ARRAY, TYPE_REAL] # Two-dimensional array "
+"of floats.\n"
+"hint_string = \"%s/%s:Resource\" % [TYPE_OBJECT, TYPE_OBJECT] # Array of "
+"resources.\n"
+"hint_string = \"%s:%s/%s:Resource\" % [TYPE_ARRAY, TYPE_OBJECT, TYPE_OBJECT] "
+"# Two-dimensional array of resources.\n"
+"[/codeblock]\n"
+"[b]Note:[/b] The final colon is required to specify for properly detecting "
+"built-in types."
+msgstr ""
+
+#: doc/classes/@GlobalScope.xml
msgid "The property is serialized and saved in the scene file (default)."
msgstr "将属性åºåˆ—化并ä¿å­˜åˆ°åœºæ™¯æ–‡ä»¶ä¸­ï¼ˆé»˜è®¤ï¼‰ã€‚"
@@ -4979,8 +5006,8 @@ msgstr ""
"confirmed] ä¿¡å·æ—¶æ‰§è¡Œç±»ä¼¼è¾“入验è¯çš„æ“ä½œï¼Œåˆ™å¯ä»¥å°†å…¶è®¾ç½®ä¸º [code]false[/"
"code],然åŽåœ¨è‡ªå·±çš„逻辑中处ç†å¯¹è¯æ¡†çš„éšè—。\n"
"[b]注æ„:[/b]从此类派生的æŸäº›èŠ‚ç‚¹å¯ä»¥å…·æœ‰ä¸åŒçš„默认值,并且å¯èƒ½æœ‰è‡ªå·±çš„内置逻"
-"辑会覆盖此设置。例如,[FileDialog] 默认其为 [code]false[/code],并在按下确定"
-"时实现了自己的输入验è¯ä»£ç ï¼Œå¦‚果输入有效,最终将éšè—å¯¹è¯æ¡†ã€‚因此,ä¸èƒ½åœ¨ "
+"辑会覆盖此设置。例如 [FileDialog] 默认其为 [code]false[/code],并在按下确定时"
+"实现了自己的输入验è¯ä»£ç ï¼Œå¦‚果输入有效,最终将éšè—å¯¹è¯æ¡†ã€‚因此,ä¸èƒ½åœ¨ "
"[FileDialog] 中使用此属性æ¥ç¦æ­¢åœ¨æŒ‰ç¡®å®šæ—¶éšè—å¯¹è¯æ¡†ã€‚"
#: doc/classes/AcceptDialog.xml
@@ -5169,8 +5196,7 @@ msgstr "2D ç²¾çµåŠ¨ç”»"
#: doc/classes/AudioStreamPlayer.xml doc/classes/Button.xml
#: doc/classes/CanvasLayer.xml doc/classes/CollisionShape2D.xml
#: doc/classes/ColorRect.xml doc/classes/Input.xml doc/classes/InputEvent.xml
-#: doc/classes/InputEventAction.xml doc/classes/Label.xml
-#: doc/classes/Particles2D.xml doc/classes/Timer.xml
+#: doc/classes/InputEventAction.xml doc/classes/Label.xml doc/classes/Timer.xml
#: doc/classes/VisibilityNotifier2D.xml
msgid "2D Dodge The Creeps Demo"
msgstr "2D Dodge The Creeps 演示"
@@ -5577,16 +5603,16 @@ msgid ""
"Returns the in handle of the key identified by [code]key_idx[/code]. The "
"[code]track_idx[/code] must be the index of a Bezier Track."
msgstr ""
-"返回由 [code]key_idx[/code] è¯†åˆ«çš„é”®çš„è¾“å…¥å¥æŸ„,[code]track_idx[/code] 必须是"
-"è´å¡žå°”轨é“的索引。"
+"返回由 [code]key_idx[/code] 识别的键的入点手柄,[code]track_idx[/code] 必须是"
+"è´èµ›å°”曲线轨é“的索引。"
#: doc/classes/Animation.xml
msgid ""
"Returns the out handle of the key identified by [code]key_idx[/code]. The "
"[code]track_idx[/code] must be the index of a Bezier Track."
msgstr ""
-"返回由 [code]key_idx[/code] è¯†åˆ«çš„é”®çš„è¾“å‡ºå¥æŸ„,[code]track_idx[/code] 必须是"
-"è´å¡žå°”轨é“的索引。"
+"返回由 [code]key_idx[/code] 识别的键的出点手柄,[code]track_idx[/code] 必须是"
+"è´èµ›å°”曲线轨é“的索引。"
#: doc/classes/Animation.xml
msgid ""
@@ -7910,6 +7936,12 @@ msgid ""
"[b]Warning:[/b] See [ConcavePolygonShape] (also called \"trimesh\") for a "
"warning about possibly unexpected behavior when using that shape for an area."
msgstr ""
+"3D 区域å¯ä»¥æ£€æµ‹åˆ° [CollisionObject] 节点间的é‡å ã€è¿›å…¥åŠé€€å‡ºã€‚也å¯ä»¥ä¿®æ”¹æˆ–覆"
+"盖局部的物ç†å‚数(é‡åŠ›ã€é˜»å°¼ï¼‰ã€å°†éŸ³é¢‘导æµè‡³è‡ªå®šä¹‰çš„音频总线。\n"
+"è¦ä¸ºåŒºåŸŸè®¾ç½®å½¢çŠ¶ï¼Œè¯·å°†ä¸€ä¸ª [CollisionShape] 或 [CollisionPolygon] 节点添加为"
+"该区域的[i]直接[/i]å­èŠ‚ç‚¹ï¼ˆæˆ–è€…æ·»åŠ å¤šä¸ªè¿™ç§èŠ‚ç‚¹ä½œä¸ºç›´æŽ¥å­èŠ‚ç‚¹ï¼‰ã€‚\n"
+"[b]警告:[/b]使用凹多边形(也å«â€œä¸‰è§’形网格â€ï¼‰ä½œä¸ºåŒºåŸŸçš„形状时,å¯èƒ½äº§ç”Ÿå‡ºä¹Žé¢„"
+"æ–™çš„è¡Œä¸ºï¼Œè§ [ConcavePolygonShape]。"
#: doc/classes/Area.xml doc/classes/QuadMesh.xml doc/classes/Viewport.xml
#: doc/classes/ViewportTexture.xml
@@ -7999,8 +8031,8 @@ msgid ""
"multiplies the gravity vector. This is useful to alter the force of gravity "
"without altering its direction."
msgstr ""
-"该区域内的é‡åŠ›å¼ºåº¦ï¼ˆå•ä½ï¼šm/s^2)。这个值是é‡åŠ›å‘é‡çš„倿•°ã€‚这个é‡åœ¨æ”¹å˜å¼•力大"
-"å°è€Œä¸æ”¹å˜å…¶æ–¹å‘很有用。"
+"该区域内的é‡åŠ›å¼ºåº¦ï¼ˆå•ä½ä¸ºç±³æ¯ç§’的平方)。这个值是é‡åŠ›å‘é‡çš„倿•°ã€‚这个é‡åœ¨æ”¹"
+"å˜å¼•力大å°è€Œä¸æ”¹å˜å…¶æ–¹å‘很有用。"
#: doc/classes/Area.xml doc/classes/Area2D.xml
msgid ""
@@ -8233,6 +8265,12 @@ msgid ""
"[b]Warning:[/b] See [ConcavePolygonShape2D] for a warning about possibly "
"unexpected behavior when using that shape for an area."
msgstr ""
+"2D 区域å¯ä»¥æ£€æµ‹åˆ° [CollisionObject2D] 节点间的é‡å ã€è¿›å…¥åŠé€€å‡ºã€‚也å¯ä»¥ä¿®æ”¹æˆ–"
+"覆盖局部的物ç†å‚数(é‡åŠ›ã€é˜»å°¼ï¼‰ã€å°†éŸ³é¢‘导æµè‡³è‡ªå®šä¹‰çš„音频总线。\n"
+"è¦ä¸ºåŒºåŸŸè®¾ç½®å½¢çŠ¶ï¼Œè¯·å°†ä¸€ä¸ª [CollisionShape2D] 或 [CollisionPolygon2D] 节点添"
+"加为该区域的[i]直接[/i]å­èŠ‚ç‚¹ï¼ˆæˆ–è€…æ·»åŠ å¤šä¸ªè¿™ç§èŠ‚ç‚¹ä½œä¸ºç›´æŽ¥å­èŠ‚ç‚¹ï¼‰ã€‚\n"
+"[b]警告:[/b]使用凹多边形(也å«â€œä¸‰è§’形网格â€ï¼‰ä½œä¸ºåŒºåŸŸçš„形状时,å¯èƒ½äº§ç”Ÿå‡ºä¹Žé¢„"
+"æ–™çš„è¡Œä¸ºï¼Œè§ [ConcavePolygonShape2D]。"
#: doc/classes/Area2D.xml
msgid "Using Area2D"
@@ -8323,7 +8361,7 @@ msgid ""
"multiplies the gravity vector. This is useful to alter the force of gravity "
"without altering its direction."
msgstr ""
-"该区域的é‡åŠ›å¼ºåº¦ï¼ˆä»¥åƒç´ /秒的平方为å•ä½ï¼‰ã€‚这个值是é‡åŠ›å‘é‡çš„倿•°ã€‚这对改å˜å¼•"
+"该区域的é‡åŠ›å¼ºåº¦ï¼ˆå•ä½ä¸ºåƒç´ æ¯ç§’的平方)。这个值是é‡åŠ›å‘é‡çš„倿•°ã€‚这对改å˜å¼•"
"力大å°è€Œä¸æ”¹å˜å…¶æ–¹å‘很有用。"
#: doc/classes/Area2D.xml
@@ -8770,6 +8808,7 @@ msgstr ""
"较慢。这是因为所有放置在删除元素之åŽçš„å…ƒç´ éƒ½å¿…é¡»é‡æ–°ç´¢å¼•。"
#: doc/classes/Array.xml
+#, fuzzy
msgid ""
"Assigns the given value to all elements in the array. This can typically be "
"used together with [method resize] to create an array with a given size and "
@@ -8778,7 +8817,10 @@ msgid ""
"var array = []\n"
"array.resize(10)\n"
"array.fill(0) # Initialize the 10 elements to 0.\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] If [code]value[/code] is of a reference type ([Object]-derived, "
+"[Array], [Dictionary], etc.) then the array is filled with the references to "
+"the same object, i.e. no duplicates are created."
msgstr ""
"将该数组中的所有元素都设置为给定的值。通常与 [method resize] 一起使用,用于创"
"å»ºç»™å®šå¤§å°æ•°ç»„并对其元素进行åˆå§‹åŒ–:\n"
@@ -9034,8 +9076,12 @@ msgstr ""
"索引之间的å˜åŒ–。"
#: doc/classes/Array.xml
+#, fuzzy
msgid ""
"Sorts the array.\n"
+"[b]Note:[/b] The sorting algorithm used is not [url=https://en.wikipedia.org/"
+"wiki/Sorting_algorithm#Stability]stable[/url]. This means that values "
+"considered equal may have their order changed when using [method sort].\n"
"[b]Note:[/b] Strings are sorted in alphabetical order (as opposed to natural "
"order). This may lead to unexpected behavior when sorting an array of "
"strings ending with a sequence of numbers. Consider the following example:\n"
@@ -9055,6 +9101,7 @@ msgstr ""
"[/codeblock]"
#: doc/classes/Array.xml
+#, fuzzy
msgid ""
"Sorts the array using a custom method. The arguments are an object that "
"holds the method and the name of such method. The custom method receives two "
@@ -9063,9 +9110,13 @@ msgid ""
"For two elements [code]a[/code] and [code]b[/code], if the given method "
"returns [code]true[/code], element [code]b[/code] will be after element "
"[code]a[/code] in the array.\n"
+"[b]Note:[/b] The sorting algorithm used is not [url=https://en.wikipedia.org/"
+"wiki/Sorting_algorithm#Stability]stable[/url]. This means that values "
+"considered equal may have their order changed when using [method "
+"sort_custom].\n"
"[b]Note:[/b] You cannot randomize the return value as the heapsort algorithm "
-"expects a deterministic result. Doing so will result in unexpected "
-"behavior.\n"
+"expects a deterministic result. Randomizing the return value will result in "
+"unexpected behavior.\n"
"[codeblock]\n"
"class MyCustomSorter:\n"
" static func sort_ascending(a, b):\n"
@@ -9161,7 +9212,6 @@ msgstr ""
"加曲é¢ä¹‹å‰è°ƒç”¨ã€‚"
#: doc/classes/ArrayMesh.xml
-#, fuzzy
msgid ""
"Creates a new surface.\n"
"Surfaces are created to be rendered using a [code]primitive[/code], which "
@@ -9195,7 +9245,14 @@ msgstr ""
"ArrayType]。例如,[code]arrays[0][/code] 是顶点的数组。总是需è¦ç¬¬ä¸€ä¸ªé¡¶ç‚¹å­æ•°"
"组,其他的å¯é€‰ã€‚添加一个索引数组使这个函数进入“索引模å¼â€ï¼Œé¡¶ç‚¹å’Œå…¶ä»–数组作为"
"æ•°æ®æ¥æºï¼Œç´¢å¼•数组定义其顶点顺åºã€‚æ‰€æœ‰çš„å­æ•°ç»„必须与顶点数组具有相åŒçš„长度,"
-"或者为空,如果使用了 [constant ARRAY_INDEX] 时除外。"
+"或者为空,如果使用了 [constant ARRAY_INDEX] 时除外。\n"
+"[code]compress_flags[/code] 是由 [enum Mesh.ArrayFormat] 枚举值组æˆçš„ä½åŸŸï¼Œé»˜"
+"认为 [constant Mesh.ARRAY_COMPRESS_DEFAULT]。\n"
+"[b]注æ„:[/b][code]compress_flags[/code] 默认会å¯ç”¨ [constant Mesh."
+"ARRAY_COMPRESS_COLOR],所以顶点颜色会作为 8 使— ç¬¦å·æ•´æ•°å­˜å‚¨ã€‚这会导致过亮颜"
+"色被钳制到 [code]Color(1, 1, 1, 1)[/code],é™ä½Žé¢œè‰²çš„精度。è¦å­˜å‚¨ HDR 顶点颜"
+"色,请将 [code]Mesh.ARRAY_COMPRESS_DEFAULT ^ Mesh.ARRAY_COMPRESS_COLOR[/"
+"code] 传入 [code]compress_flags[/code],移除顶点颜色压缩标志。"
#: doc/classes/ArrayMesh.xml
msgid "Removes all blend shapes from this [ArrayMesh]."
@@ -9731,10 +9788,10 @@ msgid ""
msgstr ""
"调用这个æ¥åˆå§‹åŒ–这个接å£ã€‚第一个被åˆå§‹åŒ–的接å£ç¡®å®šä¸ºä¸»æŽ¥å£ï¼Œç”¨äºŽæ¸²æŸ“输出。\n"
"在åˆå§‹åŒ–了接å£ä¹‹åŽï¼Œéœ€è¦å¯ç”¨è§†çª—çš„ AR/VR 模å¼ï¼Œå°†å¼€å§‹æ¸²æŸ“。\n"
-"[b]注æ„:[/b]对于任何使用 Godot 主输出的设备,如移动 VR,你必须在主视窗上å¯"
+"[b]注æ„:[/b]对于任何使用 Godot 主输出的设备,如移动 VR,你必须在主视å£ä¸Šå¯"
"用 AR/VR 模å¼ã€‚\n"
"如果你为一个处ç†è‡ªå·±è¾“出的平å°è¿™æ ·åšï¼ˆå¦‚ OpenVR),Godot 就会在å±å¹•ä¸Šåªæ˜¾ç¤ºä¸€"
-"åªçœ¼ç›è€Œä¸å¤±çœŸã€‚å¦å¤–,你å¯ä»¥åœ¨åœºæ™¯ä¸­æ·»åŠ ä¸€ä¸ªå•独的视窗节点,在该视窗上å¯ç”¨ "
+"åªçœ¼ç›è€Œä¸å¤±çœŸã€‚å¦å¤–,你å¯ä»¥åœ¨åœºæ™¯ä¸­æ·»åŠ ä¸€ä¸ªå•独的视å£èŠ‚ç‚¹ï¼Œåœ¨è¯¥è§†å£ä¸Šå¯ç”¨ "
"AR/VR。它将被用æ¥è¾“出到 HMD,让你在主窗å£ä¸­åšä½ å–œæ¬¢çš„事情,比如用一个å•独的相"
"机作为æ—观者相机,或者渲染一些完全ä¸åŒçš„东西。\n"
"è™½ç„¶ç›®å‰æ²¡æœ‰ä½¿ç”¨ï¼Œä½†ä½ å¯ä»¥æ¿€æ´»å…¶ä»–接å£ã€‚如果你想跟踪其他平å°çš„æŽ§åˆ¶å™¨ï¼Œå¯èƒ½å¸Œ"
@@ -12345,15 +12402,14 @@ msgid "Clears the audio sample data buffer."
msgstr "清除音频样本数æ®ç¼“冲区。"
#: doc/classes/AudioStreamGeneratorPlayback.xml
+#, fuzzy
msgid ""
-"Returns the number of audio data frames left to play. If this returned "
-"number reaches [code]0[/code], the audio will stop playing until frames are "
-"added again. Therefore, make sure your script can always generate and push "
-"new audio frames fast enough to avoid audio cracking."
+"Returns the number of frames that can be pushed to the audio sample data "
+"buffer without overflowing it. If the result is [code]0[/code], the buffer "
+"is full."
msgstr ""
-"è¿”å›žè¦æ’­æ”¾çš„音频数æ®å¸§æ•°ã€‚如果返回的数字达到 [code]0[/code]ï¼ŒéŸ³é¢‘å°†åœæ­¢æ’­æ”¾ï¼Œ"
-"ç›´åˆ°å†æ¬¡æ·»åŠ å¸§ã€‚å› æ­¤ï¼Œè¯·ç¡®ä¿ä½ çš„脚本始终能够以足够快的速度生æˆå’ŒæŽ¨é€æ–°çš„音频"
-"帧,以é¿å…音频破裂。"
+"如果å¯ä»¥å°†å¤§å°ä¸º [code]amount[/code] 的缓冲区推é€åˆ°éŸ³é¢‘采样数æ®ç¼“冲区而ä¸ä½¿å…¶"
+"溢出,则返回 [code]true[/code],å¦åˆ™è¿”回 [code]false[/code]。"
#: doc/classes/AudioStreamGeneratorPlayback.xml
msgid ""
@@ -12877,8 +12933,8 @@ msgid ""
"PCM8 to signed PCM8, subtract 128 from each byte."
msgstr ""
"包å«ä»¥å­—节为å•ä½çš„音频数æ®ã€‚\n"
-"[b]注æ„:[/b]æ­¤å±žæ€§éœ€è¦æœ‰ç¬¦å·çš„ PCM8æ•°æ®ã€‚è¦å°†æ— ç¬¦å·çš„ PCM8转æ¢ä¸ºæœ‰ç¬¦å·çš„ "
-"PCM8,需è¦ä»Žæ¯ä¸ªå­—节中å‡åŽ»128。"
+"[b]注æ„:[/b]æ­¤å±žæ€§éœ€è¦æœ‰ç¬¦å·çš„ PCM8 æ•°æ®ã€‚è¦å°†æ— ç¬¦å·çš„ PCM8 转æ¢ä¸ºæœ‰ç¬¦å·çš„ "
+"PCM8,需è¦ä»Žæ¯ä¸ªå­—节中å‡åŽ» 128。"
#: doc/classes/AudioStreamSample.xml
msgid "Audio format. See [enum Format] constants for values."
@@ -12986,16 +13042,17 @@ msgstr ""
"[code]texture(SCREEN_TEXTURE, ...)[/code] 函数在ç€è‰²å™¨è„šæœ¬ä¸­å¯¹å…¶è¿›è¡Œè®¿é—®ã€‚"
#: doc/classes/BackBufferCopy.xml
+#, fuzzy
msgid ""
"Node for back-buffering the currently-displayed screen. The region defined "
-"in the BackBufferCopy node is buffered with the content of the screen it "
+"in the [BackBufferCopy] node is buffered with the content of the screen it "
"covers, or the entire screen according to the copy mode set. Use the "
"[code]texture(SCREEN_TEXTURE, ...)[/code] function in your shader scripts to "
"access the buffer.\n"
"[b]Note:[/b] Since this node inherits from [Node2D] (and not [Control]), "
"anchors and margins won't apply to child [Control]-derived nodes. This can "
"be problematic when resizing the window. To avoid this, add [Control]-"
-"derived nodes as [i]siblings[/i] to the BackBufferCopy node instead of "
+"derived nodes as [i]siblings[/i] to the [BackBufferCopy] node instead of "
"adding them as children."
msgstr ""
"用于对当å‰å±å¹•显示进行åŽå°ç¼“冲的节点。BackBufferCopy 节点中定义的区域与其覆盖"
@@ -13011,26 +13068,30 @@ msgid "Buffer mode. See [enum CopyMode] constants."
msgstr "缓冲区模å¼ã€‚è§ [enum CopyMode] 常é‡ã€‚"
#: doc/classes/BackBufferCopy.xml
+#, fuzzy
msgid ""
-"The area covered by the BackBufferCopy. Only used if [member copy_mode] is "
+"The area covered by the [BackBufferCopy]. Only used if [member copy_mode] is "
"[constant COPY_MODE_RECT]."
msgstr ""
"BackBufferCopy è¦†ç›–çš„åŒºåŸŸã€‚åªæœ‰å½“ [member copy_mode] 是 [constant "
"COPY_MODE_RECT] æ—¶æ‰ä½¿ç”¨ã€‚"
#: doc/classes/BackBufferCopy.xml
+#, fuzzy
msgid ""
-"Disables the buffering mode. This means the BackBufferCopy node will "
+"Disables the buffering mode. This means the [BackBufferCopy] node will "
"directly use the portion of screen it covers."
msgstr ""
"ç¦ç”¨ç¼“冲模å¼ã€‚è¿™æ„å‘³ç€ BackBufferCopy 节点将直接使用它所覆盖的å±å¹•部分。"
#: doc/classes/BackBufferCopy.xml
-msgid "BackBufferCopy buffers a rectangular region."
+#, fuzzy
+msgid "[BackBufferCopy] buffers a rectangular region."
msgstr "BackBufferCopy 缓冲一个矩形区域。"
#: doc/classes/BackBufferCopy.xml
-msgid "BackBufferCopy buffers the entire screen."
+#, fuzzy
+msgid "[BackBufferCopy] buffers the entire screen."
msgstr "BackBufferCopy 缓冲整个å±å¹•。"
#: doc/classes/BakedLightmap.xml
@@ -13419,7 +13480,7 @@ msgid ""
"group]."
msgstr ""
"æ”¹å˜æŒ‰é’®çš„ [member pressed] 状æ€ï¼Œä¸è§¦å‘ [signal toggled]ã€‚å½“ä½ åªæƒ³æ”¹å˜æŒ‰é’®çš„"
-"状æ€è€Œä¸å‘逿Œ‰ä¸‹äº‹ä»¶æ—¶ä½¿ç”¨ï¼ˆä¾‹å¦‚,在åˆå§‹åŒ–åœºæ™¯æ—¶ï¼‰ã€‚åªæœ‰å½“ [member "
+"状æ€è€Œä¸å‘逿Œ‰ä¸‹äº‹ä»¶æ—¶ä½¿ç”¨ï¼ˆä¾‹å¦‚在åˆå§‹åŒ–åœºæ™¯æ—¶ï¼‰ã€‚åªæœ‰å½“ [member "
"toggle_mode] 是 [code]true[/code] æ—¶æ‰æœ‰æ•ˆã€‚\n"
"[b]注æ„:[/b]这个方法ä¸ä¼šé‡Šæ”¾å…¶æŒ‰é’® [member group] 中的其他按钮。"
@@ -14028,7 +14089,7 @@ msgstr ""
#: doc/classes/Bone2D.xml
msgid ""
"Length of the bone's representation drawn in the editor's viewport in pixels."
-msgstr "在编辑器的视窗中绘制的骨骼的长度,å•ä½ä¸ºåƒç´ ã€‚"
+msgstr "在编辑器的视å£ä¸­ç»˜åˆ¶çš„骨骼的长度,å•ä½ä¸ºåƒç´ ã€‚"
#: doc/classes/Bone2D.xml
msgid ""
@@ -14735,10 +14796,10 @@ msgstr ""
"相机的视野角度,以度为å•ä½ã€‚仅适用于é€è§†æ¨¡å¼ã€‚由于 [member keep_aspect] é”定"
"一个轴,因此 [code]fov[/code] 设置å¦ä¸€ä¸ªè½´çš„视角。\n"
"作为å‚考,默认的垂直视野值([code]70.0[/code])相当于以下水平 FOV:\n"
-"- 在 4:3 视窗中约86.07 度\n"
-"- 在 16:10 视窗中约 96.50 度\n"
-"- 在 16:9 视窗中约102.45 度\n"
-"- 在 21:9 视窗中约117.06 度"
+"- 在 4:3 视å£ä¸­çº¦86.07 度\n"
+"- 在 16:10 视å£ä¸­çº¦ 96.50 度\n"
+"- 在 16:9 视å£ä¸­çº¦102.45 度\n"
+"- 在 21:9 视å£ä¸­çº¦117.06 度"
#: doc/classes/Camera.xml
msgid ""
@@ -15169,9 +15230,9 @@ 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 ""
-"相机相对于视窗的缩放比例。大于 [code]Vector2(1, 1)[/code] 的值会缩å°å†…容,而"
-"较å°çš„值会起到放大镜的作用。例如,将 [code]Vector2(0.5, 0.5)[/code] 放大 2 "
-"å€ï¼Œç„¶åŽå°† [code]Vector2(4, 4)[/code] 用于 4 å€ç¼©å°ã€‚"
+"相机相对于视å£çš„缩放比例。大于 [code]Vector2(1, 1)[/code] 的值会缩å°å†…容,而"
+"较å°çš„值会起到放大的作用。例如,将 [code]Vector2(0.5, 0.5)[/code] 放大 2 å€ï¼Œ"
+"ç„¶åŽå°† [code]Vector2(4, 4)[/code] 用于 4 å€ç¼©å°ã€‚"
#: doc/classes/Camera2D.xml
msgid ""
@@ -15308,11 +15369,11 @@ msgstr "ç§»é™¤æŒ‡å®šçš„ç›¸æœºæº [code]feed[/code]。"
#: doc/classes/CameraServer.xml
msgid "Emitted when a [CameraFeed] is added (e.g. a webcam is plugged in)."
-msgstr "当添加 [CameraFeed] 时触å‘(例如,æ’入网络摄åƒå¤´ï¼‰ã€‚"
+msgstr "当添加 [CameraFeed] 时触å‘(例如æ’入网络摄åƒå¤´æ—¶ï¼‰ã€‚"
#: doc/classes/CameraServer.xml
msgid "Emitted when a [CameraFeed] is removed (e.g. a webcam is unplugged)."
-msgstr "当移除 [CameraFeed] 时触å‘(例如,拔掉网络摄åƒå¤´ï¼‰ã€‚"
+msgstr "当移除 [CameraFeed] 时触å‘(例如拔掉网络摄åƒå¤´æ—¶ï¼‰ã€‚"
#: doc/classes/CameraServer.xml
msgid "The RGBA camera image."
@@ -16592,7 +16653,7 @@ msgstr ""
"外观ä¸åŒã€‚为了éµå¾ªç”¨æˆ·ä½“验,建议在切æ¢å®ƒå¯¹æŸäº›ä¸œè¥¿æœ‰[b]直接[/b]影哿—¶ä½¿ç”¨"
"CheckButton。例如,如果切æ¢å®ƒå¯ä»¥å¯ç”¨æˆ–ç¦ç”¨è®¾ç½®è€Œä¸éœ€è¦ç”¨æˆ·æŒ‰ä¸‹ç¡®è®¤æŒ‰é’®æ—¶ï¼Œä½¿"
"用它。\n"
-"å‚阅[BaseButton],它包å«äº†ä¸Žè¯¥èŠ‚ç‚¹ç›¸å…³çš„å¸¸è§„å±žæ€§å’Œæ–¹æ³•ã€‚"
+"å¦è¯·å‚阅 [BaseButton],它包å«äº†ä¸Žè¯¥èŠ‚ç‚¹ç›¸å…³çš„å¸¸è§„å±žæ€§å’Œæ–¹æ³•ã€‚"
#: doc/classes/CheckButton.xml
msgid "The [CheckButton] text's font color."
@@ -17030,7 +17091,6 @@ msgid "Removes the given shape owner."
msgstr "移除给定形状的所有者。"
#: doc/classes/CollisionObject.xml doc/classes/CollisionObject2D.xml
-#, fuzzy
msgid ""
"If [code]value[/code] is [code]true[/code], sets the specified [code]bit[/"
"code] in the [member collision_layer].\n"
@@ -17039,11 +17099,10 @@ msgid ""
msgstr ""
"如果 [code]value[/code] 为 [code]true[/code],则设置 [member "
"collision_layer] 中指定的 [code]bit[/code] ä½ã€‚\n"
-"如果 [code]value[/code] 为 [code]false[/code],清除 [member collision_layer] "
-"中指定的 [code]bit[/code] ä½ã€‚"
+"如果 [code]value[/code] 为 [code]false[/code],则清除 [member "
+"collision_layer] 中指定的 [code]bit[/code] ä½ã€‚"
#: doc/classes/CollisionObject.xml doc/classes/CollisionObject2D.xml
-#, fuzzy
msgid ""
"If [code]value[/code] is [code]true[/code], sets the specified [code]bit[/"
"code] in the [member collision_mask].\n"
@@ -17052,8 +17111,8 @@ msgid ""
msgstr ""
"如果 [code]value[/code] 为 [code]true[/code],则设置 [member collision_mask] "
"中指定的 [code]bit[/code] ä½ã€‚\n"
-"如果 [code]value[/code] 为 [code]false[/code],清除 [member collision_mask] "
-"中指定的 [code]bit[/code] ä½ã€‚"
+"如果 [code]value[/code] 为 [code]false[/code],则清除 [member "
+"collision_mask] 中指定的 [code]bit[/code] ä½ã€‚"
#: doc/classes/CollisionObject.xml doc/classes/CollisionObject2D.xml
msgid "Returns the [code]owner_id[/code] of the given shape."
@@ -17427,7 +17486,6 @@ msgid "Node that represents collision shape data in 3D space."
msgstr "表示 3D 空间中的碰撞形状数æ®çš„节点。"
#: doc/classes/CollisionShape.xml
-#, fuzzy
msgid ""
"Editor facility for creating and editing collision shapes in 3D space. Set "
"the [member shape] property to configure the shape. [b]IMPORTANT[/b]: this "
@@ -17437,10 +17495,11 @@ msgid ""
"example, add this to an [Area] to give it a detection shape, or add it to a "
"[PhysicsBody] to create a solid object."
msgstr ""
-"用于在 3D 空间中创建和编辑碰撞形状的编辑工具。您å¯ä»¥ä½¿ç”¨æ­¤èŠ‚ç‚¹è¡¨ç¤ºå„ç§ç¢°æ’žå½¢"
-"状,例如,将其添加到 [Area] 以使其具有检测形状,或将其添加到物ç†ä½“ "
-"[PhysicsBody] 以创建实体对象。[b]é‡è¦[/b]:这是一个编辑器专用的创建形状的助"
-"手,使用 [method CollisionObject.shape_owner_get_shape] 获å–实际形状。"
+"用于在 3D 空间中创建和编辑碰撞形状的编辑工具。请使用 [member shape] 属性é…ç½®"
+"形状。[b]é‡è¦[/b]:这是专为编辑器æä¾›çš„形状创建工具,è¦èŽ·å–实际形状,请使用 "
+"[method CollisionObject.shape_owner_get_shape]。\n"
+"ä½ å¯ä»¥ä½¿ç”¨è¿™ä¸ªèŠ‚ç‚¹è¡¨ç¤ºå„ç§ç¢°æ’žå½¢çŠ¶ï¼Œä¾‹å¦‚ï¼Œå°†å…¶æ·»åŠ åˆ° [Area] 以使其具有检测形"
+"状,或将其添加到物ç†ä½“ [PhysicsBody] 以创建实体对象。"
#: doc/classes/CollisionShape.xml doc/classes/CollisionShape2D.xml
#: doc/classes/Physics2DDirectBodyState.xml
@@ -17475,7 +17534,6 @@ msgid "Node that represents collision shape data in 2D space."
msgstr "表示2D空间中的碰撞形状数æ®çš„节点。"
#: doc/classes/CollisionShape2D.xml
-#, fuzzy
msgid ""
"Editor facility for creating and editing collision shapes in 2D space. Set "
"the [member shape] property to configure the shape. [b]IMPORTANT[/b]: this "
@@ -17485,10 +17543,11 @@ msgid ""
"example, add this to an [Area2D] to give it a detection shape, or add it to "
"a [PhysicsBody2D] to create a solid object."
msgstr ""
-"编辑器功能,用于在2D空间中创建和编辑碰撞形状。您å¯ä»¥ä½¿ç”¨æ­¤èŠ‚ç‚¹è¡¨ç¤ºå„ç§ç¢°æ’žå½¢"
-"状,例如,将其添加到 [Area2D] 以æä¾›æ£€æµ‹å½¢çŠ¶ï¼Œæˆ–å°†å…¶æ·»åŠ åˆ° [PhysicsBody2D] 以"
-"创建实体。[b]é‡è¦äº‹é¡¹[/b]:这是创建形状的仅编辑器助手,请使用 [method "
-"CollisionObject2D.shape_owner_get_shape] 获å–实际形状。"
+"用于在 2D 空间中创建和编辑碰撞形状的编辑工具。请使用 [member shape] 属性é…ç½®"
+"形状。[b]é‡è¦[/b]:这是专为编辑器æä¾›çš„形状创建工具,è¦èŽ·å–实际形状,请使用 "
+"[method CollisionObject2D.shape_owner_get_shape]。\n"
+"ä½ å¯ä»¥ä½¿ç”¨è¿™ä¸ªèŠ‚ç‚¹è¡¨ç¤ºå„ç§ç¢°æ’žå½¢çŠ¶ï¼Œä¾‹å¦‚ï¼Œå°†å…¶æ·»åŠ åˆ° [Area2D] 以使其具有检测"
+"形状,或将其添加到物ç†ä½“ [PhysicsBody2D] 以创建实体对象。"
#: doc/classes/CollisionShape2D.xml doc/classes/KinematicBody2D.xml
#: doc/classes/RectangleShape2D.xml doc/classes/TileMap.xml
@@ -18827,6 +18886,17 @@ msgid ""
"Physics the area will not detect any collisions with the concave shape at "
"all (this is a known bug)."
msgstr ""
+"凹多边形形状资æºï¼Œå¯ä»¥æ”¾åˆ° [PhysicsBody] 和区域之中。这ç§å½¢çŠ¶æ˜¯é€šè¿‡è¾“å…¥ä¸€ç»„ä¸‰"
+"è§’å½¢æ¥åˆ›å»ºçš„。\n"
+"[b]注æ„:[/b]用于碰撞时,[ConcavePolygonShape] 应与 [StaticBody] ç­‰é™æ€ "
+"[PhysicsBody] 节点一起使用,与 [KinematicBody] å’Œéž Static 模å¼çš„ "
+"[RigidBody] 一起使用是无法正常工作的。\n"
+"[b]警告:[/b]将这ç§å½¢çŠ¶ç”¨äºŽ [Area](通过 [CollisionShape] 节点,例如选中 "
+"[MeshInstance] 节点åŽï¼Œé€šè¿‡å‡ºçŽ°çš„[i]网格[/i]èœå•中的[i]创建三角网格碰撞åŒçº§[/"
+"i]æ¥åˆ›å»ºï¼‰å¯èƒ½å¾—到出乎预料的结果:使用 Godot Physics 时,区域åªä¼šæ£€æµ‹ä¸Ž "
+"[ConcavePolygonShape] 的三角形é¢äº§ç”Ÿçš„碰撞(ä¸ä¼šæ£€æµ‹è¯¥å½¢çŠ¶çš„â€œå†…éƒ¨â€ï¼Œè¿™é‡Œåªæ˜¯"
+"举个例å­ï¼‰ï¼Œä½¿ç”¨ Bullet Physics 时根本ä¸ä¼šæ£€æµ‹åˆ°ä»»ä½•与凹形状的碰撞(这是已知"
+"的问题)。"
#: doc/classes/ConcavePolygonShape.xml
msgid "Returns the faces (an array of triangles)."
@@ -18841,7 +18911,6 @@ msgid "Concave polygon 2D shape resource for physics."
msgstr "凹é¢å¤šè¾¹å½¢2D形状资æºç”¨äºŽç‰©ç†ã€‚"
#: doc/classes/ConcavePolygonShape2D.xml
-#, fuzzy
msgid ""
"Concave polygon 2D shape resource for physics. It is made out of segments "
"and is optimal for complex polygonal concave collisions. However, it is not "
@@ -18858,12 +18927,16 @@ msgid ""
"the segments in the [ConcavePolygonShape2D] (and not with any \"inside\" of "
"the shape, for example)."
msgstr ""
-"凹é¢å¤šè¾¹å½¢2D形状资æºç”¨äºŽç‰©ç†ã€‚它是由线段组æˆçš„ï¼Œæ˜¯å¤æ‚的多边形凹é¢ç¢°æ’žçš„æœ€ä½³"
-"选择。但是,建议ä¸è¦å°†å…¶ç”¨äºŽ[RigidBody2D]节点。建议使用凸分解模å¼ï¼ˆå®žä½“)或多"
-"个凸对象的CollisionPolygon2D代替。å¦åˆ™ï¼Œå‡¹å¤šè¾¹å½¢2D形状更适åˆé™æ€ç¢°æ’žã€‚\n"
-"[ConvexPolygonShape2D]å’Œ[ConcavePolygonShape2D]之间的主è¦åŒºåˆ«åœ¨äºŽï¼Œå‡¹é¢å¤šè¾¹å½¢"
-"å‡å®šå…¶ä¸ºå‡¹é¢ï¼Œå¹¶ä½¿ç”¨æ›´å¤æ‚的碰撞检测方法,而凸é¢å¤šè¾¹å½¢åˆ™å°†è‡ªèº«å¼ºåˆ¶å˜ä¸ºå‡¸é¢ï¼Œ"
-"以加快碰撞检测的速度。"
+"用于物ç†çš„凹多边形 2D 形状资æºã€‚它是由线段组æˆçš„ï¼Œæ˜¯å¤æ‚的多边形凹é¢ç¢°æ’žçš„æœ€"
+"佳选择。但是建议ä¸è¦å°†å…¶ç”¨äºŽ [RigidBody2D] 节点。建议使用凸分解模å¼ï¼ˆå®žä½“)或"
+"多个凸对象的 CollisionPolygon2D 代替。å¦åˆ™ï¼Œå‡¹å¤šè¾¹å½¢ 2D 形状更适åˆé™æ€ç¢°"
+"撞。\n"
+"[ConvexPolygonShape2D] å’Œ [ConcavePolygonShape2D] 之间的主è¦åŒºåˆ«åœ¨äºŽï¼Œå‡¹å¤šè¾¹"
+"å½¢å‡å®šå…¶ä¸ºå‡¹é¢ï¼Œå¹¶ä½¿ç”¨æ›´å¤æ‚的碰撞检测方法,而凸多边形则将自身强制å˜ä¸ºå‡¸é¢ï¼Œ"
+"以加快碰撞检测的速度。\n"
+"[b]警告:[/b]将这ç§å½¢çŠ¶ç”¨äºŽ [Area2D](通过 [CollisionShape2D] 节点)å¯èƒ½å¾—到"
+"出乎预料的结果:区域åªä¼šæ£€æµ‹ä¸Ž [ConcavePolygonShape2D] 的线段产生的碰撞(ä¸ä¼š"
+"检测该形状的“内部â€ï¼Œè¿™é‡Œåªæ˜¯ä¸¾ä¸ªä¾‹å­ï¼‰ã€‚"
#: doc/classes/ConcavePolygonShape2D.xml
msgid ""
@@ -19599,7 +19672,7 @@ msgstr ""
"时,本地覆盖项始终优先。\n"
"[b]注æ„:[/b]为覆盖项设 [code]null[/code] 值å¯å°†å…¶åˆ é™¤ã€‚该行为已废弃,将在 "
"4.0 ä¸­ç§»é™¤ï¼Œè¯·æ¢æˆ [method remove_stylebox_override]。\n"
-"å‚阅 [method get_stylebox]。\n"
+"å¦è¯·å‚阅 [method get_stylebox]。\n"
"[b]通过å¤åˆ¶æ¥ä¿®æ”¹ StyleBox 中的属性的示例:[/b]\n"
"[codeblock]\n"
"# 下é¢çš„代ç ç‰‡æ®µå‡è®¾å­èŠ‚ç‚¹ MyButton 分é…了一个 StyleBoxFlat。\n"
@@ -19672,7 +19745,7 @@ msgstr "找到下一个å¯ä»¥æŽ¥å—焦点的 [Control],在树的下方。"
#: doc/classes/Control.xml
msgid ""
"Finds the previous (above in the tree) [Control] that can receive the focus."
-msgstr "找到å¯ä»¥æŽ¥æ”¶ç„¦ç‚¹çš„上一个 [Control],在树的上方。"
+msgstr "找到上一个å¯ä»¥æŽ¥å—焦点的 [Control],在树的上方。"
#: doc/classes/Control.xml
msgid ""
@@ -19735,11 +19808,11 @@ msgstr ""
"code]ï¼Œåˆ™ä½¿ç”¨å½“å‰æŽ§ä»¶çš„ç±»å作为类型,如果定义了 [member "
"theme_type_variation] 则也会使用。如果类型是类åï¼Œåˆ™è¿˜ä¼šæŒ‰ç»§æ‰¿é¡ºåºæ£€æŸ¥å…¶çˆ¶"
"类。\n"
-"å¯¹äºŽå½“å‰æŽ§ä»¶ï¼Œé¦–å…ˆè€ƒè™‘å…¶æœ¬åœ°è¦†ç›–é¡¹ï¼Œå‚阅 [method add_color_override]ï¼Œç„¶åŽæ˜¯"
-"其分é…çš„ [member theme]ã€‚åœ¨å½“å‰æŽ§ä»¶ä¹‹åŽï¼Œè€ƒè™‘æ¯ä¸ªçˆ¶æŽ§ä»¶åŠå…¶åˆ†é…çš„ [member "
-"theme];未分é…[member theme]的控件将被跳过。如果在树中找ä¸åˆ°åŒ¹é…çš„ [Theme],"
-"则使用自定义项目 [Theme]和默认的 [Theme],å‚阅 [member ProjectSettings.gui/"
-"theme/custom]。\n"
+"å¯¹äºŽå½“å‰æŽ§ä»¶ï¼Œä¼šé¦–å…ˆè€ƒè™‘å…¶æœ¬åœ°è¦†ç›–é¡¹ï¼ˆè§ [method add_color_override]),然åŽ"
+"冿˜¯ä¸ºå…¶åˆ†é…çš„ [member theme]ã€‚åœ¨å½“å‰æŽ§ä»¶ä¹‹åŽï¼Œè€ƒè™‘æ¯ä¸ªçˆ¶æŽ§ä»¶åŠå…¶åˆ†é…çš„ "
+"[member theme]ï¼›æœªåˆ†é… [member theme] 的控件将被跳过。如果在树中找ä¸åˆ°åŒ¹é…çš„ "
+"[Theme],则使用自定义项目 [Theme]ï¼ˆè§ [member ProjectSettings.gui/theme/"
+"custom])和默认的 [Theme]。\n"
"[codeblock]\n"
"func _ready():\n"
" # 获å–ä¸ºå½“å‰æŽ§ä»¶ç±»å®šä¹‰çš„å­—ä½“é¢œè‰²ï¼ˆå¦‚æžœå­˜åœ¨ï¼‰ã€‚\n"
@@ -19925,12 +19998,11 @@ msgid ""
"be clicked instead\n"
"[/codeblock]"
msgstr ""
-"创建一个[InputEventMouseButton],å°è¯•点击控件。如果接收到该事件,控件就会获得"
-"焦点。\n"
+"创建å°è¯•点击该控件的 [InputEventMouseButton]。如果接收到该事件,该控件就会获"
+"得焦点。\n"
"[codeblock]\n"
"func _process(delta):\n"
-" grab_click_focus() #when clicking another Control node, this node will "
-"be clicked instead\n"
+" grab_click_focus() # 点击其它 Control 节点时,实际会点到这个节点\n"
"[/codeblock]"
#: doc/classes/Control.xml
@@ -19991,7 +20063,7 @@ msgid ""
"Returns [code]true[/code] if this is the current focused control. See "
"[member focus_mode]."
msgstr ""
-"如果这是当å‰çš„焦点控件,则返回 [code]true[/code]。å‚阅[member focus_mode]。"
+"如果这是当å‰çš„焦点控件,则返回 [code]true[/code]ã€‚è§ [member focus_mode]。"
#: doc/classes/Control.xml
msgid ""
@@ -20057,7 +20129,7 @@ msgid ""
msgstr ""
"如果此 [Control] 节点中具有指定 [code]name[/code] 的主题ç€è‰²å™¨å­˜åœ¨æœ¬åœ°è¦†ç›–"
"项,则返回 [code]true[/code]。\n"
-"å‚阅[method add_shader_override]。"
+"è§ [method add_shader_override]。"
#: doc/classes/Control.xml
msgid ""
@@ -20078,7 +20150,7 @@ msgid ""
msgstr ""
"如果在此 [Control] 节点中具有指定 [code]name[/code] 的主题 [StyleBox] 的本地"
"覆盖项,则返回 [code]true[/code]。\n"
-"å‚阅 [method add_stylebox_override]。"
+"è§ [method add_stylebox_override]。"
#: doc/classes/Control.xml
msgid ""
@@ -20148,15 +20220,15 @@ msgid ""
"[code]push_opposite_anchor[/code] was [code]false[/code], the left anchor "
"would get value 0.5."
msgstr ""
-"将由[enum Margin]枚举的[code]margin[/code]叏釿 ‡è¯†çš„锚设置为值[code]anchor[/"
-"code]。用于[member anchor_bottom],[member anchor_left],[member "
-"anchor_right]和[member anchor_top]的setter方法。\n"
-"如果[code]keep_margin[/code]为 [code]true[/code],则在执行此æ“作åŽä¸ä¼šæ›´æ–°è¾¹"
-"è·ã€‚\n"
-"如果[code]push_opposite_anchor[/code]为 [code]true[/code],并且相对的锚点与该"
-"锚点é‡å ï¼Œåˆ™ç›¸å¯¹çš„锚点将覆盖其值。例如,当将左锚点设置为1且å³é”šç‚¹çš„值为0.5"
-"时,å³é”šç‚¹çš„值也将为1。如果[code]push_opposite_anchor[/code]为 [code]false[/"
-"code],则左锚点将得到值0.5。"
+"将由 [code]margin[/code] 叏釿 ‡è¯†çš„锚点设置为值 [code]anchor[/code],å–值为 "
+"[enum Margin] 枚举。这是 [member anchor_bottom]ã€[member anchor_left]ã€"
+"[member anchor_right]ã€[member anchor_top] çš„ setter 方法。\n"
+"如果 [code]keep_margin[/code] 为 [code]true[/code],则在执行此æ“作åŽä¸ä¼šæ›´æ–°"
+"è¾¹è·ã€‚\n"
+"如果 [code]push_opposite_anchor[/code] 为 [code]true[/code],并且相对的锚点与"
+"该锚点é‡å ï¼Œåˆ™ç›¸å¯¹çš„锚点将覆盖其值。例如,当将左锚点设置为 1 且å³é”šç‚¹çš„值为 "
+"0.5 时,å³é”šç‚¹çš„值也将为 1。如果 [code]push_opposite_anchor[/code] 为 "
+"[code]false[/code],则左锚点将得到值 0.5。"
#: doc/classes/Control.xml
msgid ""
@@ -20165,15 +20237,14 @@ msgid ""
"offset yourself (see [method set_margin])."
msgstr ""
"与 [method set_anchor] 的工作原ç†ç›¸åŒï¼Œä½†æ˜¯å®ƒä»£æ›¿ [code]keep_margin[/code] å‚"
-"数和边è·çš„自动更新,它å…许您自己设置边è·åç§»é‡ï¼ˆè¯·å‚阅 [method "
-"set_margin])。"
+"数和边è·çš„自动更新,它å…许您自己设置边è·åç§»é‡ï¼ˆè§ [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 ""
-"设置锚点预设和边è·é¢„设。请å‚阅 [method set_anchors_preset] å’Œ [method "
+"设置锚点预设和边è·é¢„è®¾ã€‚è§ [method set_anchors_preset] å’Œ [method "
"set_margins_preset]。"
#: doc/classes/Control.xml
@@ -20193,7 +20264,7 @@ msgid ""
"Sets [member margin_left] and [member margin_top] at the same time. "
"Equivalent of changing [member rect_position]."
msgstr ""
-"åŒæ—¶è®¾ç½®[member margin_left]å’Œ[member margin_top]。等效于更改[member "
+"åŒæ—¶è®¾ç½® [member margin_left] å’Œ [member margin_top]。等效于更改 [member "
"rect_position]。"
#: doc/classes/Control.xml
@@ -20285,7 +20356,7 @@ msgstr ""
#: doc/classes/Control.xml
msgid "Sets [member margin_right] and [member margin_bottom] at the same time."
-msgstr "åŒæ—¶è®¾ç½®[member margin_right]å’Œ[member margin_bottom]。"
+msgstr "åŒæ—¶è®¾ç½® [member margin_right] å’Œ [member margin_bottom]。"
#: doc/classes/Control.xml
msgid ""
@@ -20305,9 +20376,9 @@ msgid ""
"If [code]keep_margins[/code] is [code]true[/code], control's anchors will be "
"updated instead of margins."
msgstr ""
-"将[member rect_global_position]设置为给定的[code]position[/code]。\n"
-"如果[code]keep_margins[/code]为 [code]true[/code],则控件的锚点将被更新,而ä¸"
-"是边è·ã€‚"
+"将 [member rect_global_position] 设置为给定的 [code]position[/code]。\n"
+"如果 [code]keep_margins[/code] 为 [code]true[/code],则更新的是控件的锚点,而"
+"䏿˜¯è¾¹è·ã€‚"
#: doc/classes/Control.xml
msgid ""
@@ -20345,9 +20416,9 @@ msgid ""
"If [code]keep_margins[/code] is [code]true[/code], control's anchors will be "
"updated instead of margins."
msgstr ""
-"将[member rect_position]设置为给定的[code]position[/code]。\n"
-"如果[code]keep_margins[/code]为 [code]true[/code],则控件的锚点将被更新,而ä¸"
-"是边è·ã€‚"
+"将 [member rect_position] 设置为给定的 [code]position[/code]。\n"
+"如果 [code]keep_margins[/code] 为 [code]true[/code],则更新的是控件的锚点,而"
+"䏿˜¯è¾¹è·ã€‚"
#: doc/classes/Control.xml
msgid "Sets the rotation (in radians)."
@@ -20431,8 +20502,8 @@ 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 ""
-"控件的焦点访问模å¼ï¼ˆâ€œæ— â€ï¼Œâ€œå•å‡»â€æˆ–“全部â€ï¼‰ã€‚åªèƒ½åŒæ—¶é›†ä¸­ä¸€ä¸ªæŽ§ä»¶ï¼Œå®ƒå°†æŽ¥æ”¶é”®"
-"盘信å·ã€‚"
+"控件的焦点访问模å¼ï¼ˆâ€œæ— â€â€œå•å‡»â€æˆ–“全部â€ï¼‰ã€‚åªèƒ½åŒæ—¶èšç„¦ä¸€ä¸ªæŽ§ä»¶ï¼Œè¯¥æŽ§ä»¶ä¼šæ”¶åˆ°"
+"键盘信å·ã€‚"
#: doc/classes/Control.xml
msgid ""
@@ -20740,7 +20811,7 @@ msgstr ""
msgid ""
"The size of the node's bounding rectangle, in pixels. [Container] nodes "
"update this property automatically."
-msgstr "节点边界矩形的大å°ï¼Œä»¥åƒç´ ä¸ºå•ä½ã€‚[Container]节点会自动更新此属性。"
+msgstr "节点边界矩形的大å°ï¼Œä»¥åƒç´ ä¸ºå•ä½ã€‚[Container] 节点会自动更新此属性。"
#: doc/classes/Control.xml
msgid ""
@@ -20907,11 +20978,11 @@ msgstr "å½“èŠ‚ç‚¹æ›´æ”¹å¤§å°æ—¶å‘é€ã€‚使用 [member rect_size] èŽ·å–æ–°å¤§å
#: doc/classes/Control.xml
msgid "Sent when the mouse pointer enters the node."
-msgstr "当鼠标指针进入节点时å‘é€ã€‚"
+msgstr "当鼠标指针进入该节点时å‘é€ã€‚"
#: doc/classes/Control.xml
msgid "Sent when the mouse pointer exits the node."
-msgstr "当鼠标指针退出节点时å‘é€ã€‚"
+msgstr "当鼠标指针退出该节点时å‘é€ã€‚"
#: doc/classes/Control.xml
msgid "Sent when the node grabs focus."
@@ -20927,8 +20998,8 @@ msgid ""
"control. Happens when you call one of the [code]add_*_override[/code] "
"methods."
msgstr ""
-"当节点的 [member theme] æ”¹å˜æ—¶ï¼Œå°±åœ¨Godoté‡ç»˜æŽ§ä»¶ä¹‹å‰å‘é€ã€‚当你调用"
-"[code]add_*_override[/code]方法之一时å‘生。"
+"当节点的 [member theme] æ”¹å˜æ—¶ï¼Œå°±åœ¨ Godot é‡ç»˜æŽ§ä»¶ä¹‹å‰å‘é€ã€‚当你调用 "
+"[code]add_*_override[/code] 方法之一时å‘生。"
#: doc/classes/Control.xml
msgid "Sent when an open modal dialog closes. See [method show_modal]."
@@ -20960,8 +21031,8 @@ msgid ""
"beam pointer has a shape similar to \"I\". It tells the user they can "
"highlight or insert text."
msgstr ""
-"å½“ç”¨æˆ·å°†èŠ‚ç‚¹æ‚¬åœæ—¶ï¼Œæ˜¾ç¤ºç³»ç»Ÿçš„I型光æŸé¼ æ ‡å…‰æ ‡ã€‚å·¥å­—æ¢æŒ‡é’ˆçš„形状类似于“Iâ€ã€‚它"
-"告诉用户他们å¯ä»¥çªå‡ºæ˜¾ç¤ºæˆ–æ’入文本。"
+"å½“ç”¨æˆ·å°†èŠ‚ç‚¹æ‚¬åœæ—¶ï¼Œæ˜¾ç¤ºç³»ç»Ÿçš„ I 型光æŸé¼ æ ‡å…‰æ ‡ã€‚å·¥å­—æ¢æŒ‡é’ˆçš„形状类似于“Iâ€ã€‚"
+"它告诉用户他们å¯ä»¥çªå‡ºæ˜¾ç¤ºæˆ–æ’入文本。"
#: doc/classes/Control.xml
msgid ""
@@ -21000,7 +21071,7 @@ msgid ""
"grabbing, like a node in the Scene dock."
msgstr ""
"当用户悬åœèŠ‚ç‚¹æ—¶ï¼Œæ˜¾ç¤ºç³»ç»Ÿçš„è½åœ°é¼ æ ‡å…‰æ ‡ã€‚它å¯ä»¥æ˜¯ä¸€ä¸ªå¼ å¼€çš„æ‰‹ã€‚它告诉用户å¯"
-"ä»¥æ”¾ä¸‹ä¸€ä¸ªä»–ä»¬å½“å‰æ­£åœ¨æŠ“å–的物å“,比如场景dock中的一个节点。"
+"ä»¥æ”¾ä¸‹ä¸€ä¸ªä»–ä»¬å½“å‰æ­£åœ¨æŠ“å–的物å“ï¼Œæ¯”å¦‚åœºæ™¯é¢æ¿ä¸­çš„一个节点。"
#: doc/classes/Control.xml
msgid ""
@@ -21053,8 +21124,8 @@ msgid ""
"2 double-headed arrows at a 90 degree angle. It tells the user they can move "
"a UI element freely."
msgstr ""
-"å½“ç”¨æˆ·å°†èŠ‚ç‚¹æ‚¬åœæ—¶ï¼Œæ˜¾ç¤ºç³»ç»Ÿçš„移动鼠标光标。它以90度角显示2个åŒå‘箭头。它告诉"
-"用户他们å¯ä»¥è‡ªç”±ç§»åЍ UI 元素。"
+"å½“ç”¨æˆ·å°†èŠ‚ç‚¹æ‚¬åœæ—¶ï¼Œæ˜¾ç¤ºç³»ç»Ÿçš„移动鼠标光标。它以 90 度角显示 2 个åŒå‘箭头。它"
+"告诉用户他们å¯ä»¥è‡ªç”±ç§»åЍ UI 元素。"
#: doc/classes/Control.xml
msgid ""
@@ -21240,8 +21311,8 @@ msgid ""
"the available space without pushing any other node. Use with [member "
"size_flags_horizontal] and [member size_flags_vertical]."
msgstr ""
-"告诉父[Container]æ‰©å±•æ­¤èŠ‚ç‚¹çš„è¾¹ç•Œï¼Œä»¥åœ¨ä¸æŽ¨å…¶ä»–èŠ‚ç‚¹çš„æƒ…å†µä¸‹å¡«å……æ‰€æœ‰å¯ç”¨ç©ºé—´ã€‚"
-"使用[member size_flags_horizontal]和[member size_flags_vertical]。"
+"告诉父 [Container] æ‰©å±•æ­¤èŠ‚ç‚¹çš„è¾¹ç•Œï¼Œä»¥åœ¨ä¸æŽ¨å…¶ä»–èŠ‚ç‚¹çš„æƒ…å†µä¸‹å¡«å……æ‰€æœ‰å¯ç”¨ç©º"
+"间。用于 [member size_flags_horizontal] 和 [member size_flags_vertical]。"
#: doc/classes/Control.xml
msgid ""
@@ -21251,17 +21322,17 @@ msgid ""
"size_flags_stretch_ratio]. Use with [member size_flags_horizontal] and "
"[member size_flags_vertical]."
msgstr ""
-"告诉父级[Container]让该节点å ç”¨æ‚¨æ ‡è®°çš„轴上的所有å¯ç”¨ç©ºé—´ã€‚如果将多个相邻节点"
-"设置为扩展,它们将根æ®å…¶æ‹‰ä¼¸æ¯”共享空间。å‚阅[member "
-"size_flags_stretch_ratio]。与[member size_flags_horizontal]和[member "
-"size_flags_vertical]一起使用。"
+"告诉父级 [Container] 让该节点å ç”¨æ‚¨æ ‡è®°çš„轴上的所有å¯ç”¨ç©ºé—´ã€‚如果将多个相邻节"
+"点设置为扩展,它们将根æ®å…¶æ‹‰ä¼¸æ¯”å…±äº«ç©ºé—´ã€‚è§ [member "
+"size_flags_stretch_ratio]。用于 [member size_flags_horizontal] 和 [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 ""
-"å°†èŠ‚ç‚¹çš„å¤§å°æ ‡å¿—è®¾ç½®ä¸ºåŒæ—¶å¡«å……和扩展。有关更多信æ¯ï¼Œè¯·å‚阅上é¢çš„2个常é‡ã€‚"
+"å°†èŠ‚ç‚¹çš„å¤§å°æ ‡å¿—è®¾ç½®ä¸ºåŒæ—¶å¡«å……和扩展。有关更多信æ¯ï¼Œè¯·å‚阅上é¢çš„ 2 个常é‡ã€‚"
#: doc/classes/Control.xml
msgid ""
@@ -21271,8 +21342,8 @@ msgid ""
"size_flags_vertical]."
msgstr ""
"告诉父级 [Container] 使节点本身居中。它基于控件的包围框居中,因此它ä¸é€‚用于 "
-"fill 或 expand 尺寸标志。与 [member size_flags_horizontal] 和 [member "
-"size_flags_vertical] 一起使用。"
+"fill 或 expand 尺寸标志。用于 [member size_flags_horizontal] 和 [member "
+"size_flags_vertical]。"
#: doc/classes/Control.xml
msgid ""
@@ -21282,8 +21353,8 @@ msgid ""
"size_flags_vertical]."
msgstr ""
"告诉父级 [Container] 将节点与其末端(底部或å³ä¾§ï¼‰å¯¹é½ã€‚它ä¸é€‚用于 fill 或 "
-"expand size 标志。与 [member size_flags_horizontal] 和 [member "
-"size_flags_vertical] 一起使用。"
+"expand size 标志。用于 [member size_flags_horizontal] 和 [member "
+"size_flags_vertical]。"
#: doc/classes/Control.xml
msgid ""
@@ -21440,7 +21511,8 @@ msgid ""
"and doesn't need to be configured by the user."
msgstr ""
"基于 CPU çš„ 3D ç²’å­èŠ‚ç‚¹ï¼Œç”¨äºŽåˆ›å»ºå„ç§ç²’å­ç³»ç»Ÿå’Œæ•ˆæžœã€‚\n"
-"å‚阅 [Particles],它是以硬件加速æä¾›ç›¸åŒçš„功能,但å¯èƒ½æ— æ³•在旧设备上è¿è¡Œã€‚\n"
+"å¦è¯·å‚阅 [Particles],它是以硬件加速æä¾›ç›¸åŒçš„功能,但å¯èƒ½æ— æ³•在旧设备上è¿"
+"行。\n"
"[b]注æ„:[/b]与 [Particles] ä¸åŒï¼Œå…¶å¯è§æ€§çŸ©å½¢æ˜¯å³æ—¶ç”Ÿæˆçš„,ä¸éœ€è¦ç”¨æˆ·é…置。"
#: doc/classes/CPUParticles.xml
@@ -21703,7 +21775,7 @@ msgstr ""
#: doc/classes/CPUParticles.xml doc/classes/CPUParticles2D.xml
#: doc/classes/ParticlesMaterial.xml
msgid "Align Y axis of particle with the direction of its velocity."
-msgstr "将粒å­çš„Y轴与其速度方å‘对é½ã€‚"
+msgstr "将粒å­çš„ Y 轴与其速度方å‘对é½ã€‚"
#: doc/classes/CPUParticles.xml doc/classes/ParticlesMaterial.xml
msgid "If [code]true[/code], particles will not move on the z axis."
@@ -24007,6 +24079,14 @@ msgid "Cylinder shape for collisions."
msgstr "碰撞用的圆柱体形状。"
#: doc/classes/CylinderShape.xml
+msgid ""
+"Cylinder shape for collisions.\n"
+"[b]Note:[/b] When using GodotPhysics instead of the default Bullet physics "
+"engine, there are several known bugs with cylinder collision shapes. Using "
+"[CapsuleShape] or [BoxShape] instead is recommended."
+msgstr ""
+
+#: doc/classes/CylinderShape.xml
msgid "The cylinder's height."
msgstr "圆柱体的高度。"
@@ -25459,7 +25539,7 @@ msgstr "AssetLib 选项å¡ã€‚如果ç¦ç”¨æ­¤åŠŸèƒ½ï¼Œåˆ™ä¸ä¼šæ˜¾ç¤º AssetLib é€
msgid ""
"Scene tree editing. If this feature is disabled, the Scene tree dock will "
"still be visible but will be read-only."
-msgstr "场景树编辑。如果ç¦ç”¨æ­¤åŠŸèƒ½ï¼Œåœºæ™¯æ ‘åœé ç‚¹ä»å°†å¯è§ï¼Œä½†å°†æ˜¯åªè¯»çš„。"
+msgstr "场景树编辑。如果ç¦ç”¨æ­¤åŠŸèƒ½ï¼Œåœºæ™¯æ ‘é¢æ¿ä»å°†å¯è§ï¼Œä½†å°†æ˜¯åªè¯»çš„。"
#: doc/classes/EditorFeatureProfile.xml
msgid ""
@@ -26049,7 +26129,7 @@ msgstr ""
#: doc/classes/EditorInspector.xml
msgid "A control used to edit properties of an object."
-msgstr "用于编辑所选节点属性的控件。"
+msgstr "用于编辑对象属性的控件。"
#: doc/classes/EditorInspector.xml
msgid ""
@@ -26654,9 +26734,9 @@ 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 ""
-"注册一个新的空间辅助器æ’ä»¶ [EditorSpatialGizmoPlugin]。Gizmoæ’件用于为 "
-"[Spatial] 的 3D预览视窗添加自定义的 gizmos。\n"
-"å‚è§ [method add_inspector_plugin] 以了解如何注册一个æ’件的例å­ã€‚"
+"注册一个新的 [EditorSpatialGizmoPlugin]。å°å·¥å…·æ’ä»¶å¯ä»¥åœ¨ 3D 预览视区中为 "
+"[Spatial] 添加自定义的å°å·¥å…·ã€‚\n"
+"注册æ’ä»¶çš„ç¤ºä¾‹è§ [method add_inspector_plugin]。"
#: doc/classes/EditorPlugin.xml
msgid ""
@@ -27143,7 +27223,7 @@ msgstr "删除由 [method add_scene_import_plugin] 注册的场景导入器。"
#: doc/classes/EditorPlugin.xml
msgid "Removes a gizmo plugin registered by [method add_spatial_gizmo_plugin]."
-msgstr "删除由 [method add_spatial_gizmo_plugin] 注册的控制器æ’件。"
+msgstr "删除由 [method add_spatial_gizmo_plugin] 注册的å°å·¥å…·æ’件。"
#: doc/classes/EditorPlugin.xml
msgid "Removes a menu [code]name[/code] from [b]Project > Tools[/b]."
@@ -27810,6 +27890,7 @@ msgid "Base script that can be used to add extension functions to the editor."
msgstr "å¯ç”¨äºŽä¸ºç¼–辑器添加扩展功能的基础脚本。"
#: doc/classes/EditorScript.xml
+#, fuzzy
msgid ""
"Scripts extending this class and implementing its [method _run] method can "
"be executed from the Script Editor's [b]File > Run[/b] menu option (or by "
@@ -27827,7 +27908,10 @@ msgid ""
"[/codeblock]\n"
"[b]Note:[/b] The script is run in the Editor context, which means the output "
"is visible in the console window started with the Editor (stdout) instead of "
-"the usual Godot [b]Output[/b] dock."
+"the usual Godot [b]Output[/b] dock.\n"
+"[b]Note:[/b] EditorScript is reference counted, meaning it is destroyed when "
+"nothing references it. This can cause errors during asynchronous operations "
+"if there are no references to the script."
msgstr ""
"扩展该类并实现其 [method _run] 方法的脚本å¯ä»¥åœ¨ç¼–辑器è¿è¡Œæ—¶é€šè¿‡è„šæœ¬ç¼–è¾‘å™¨çš„"
"[b]文件 > è¿è¡Œ[/b]èœå•选项(或按 [code]Ctrl+Shift+X[/code]ï¼‰æ‰§è¡Œã€‚è¿™å¯¹äºŽå‘ "
@@ -28165,7 +28249,7 @@ msgstr ""
#: doc/classes/EditorSpatialGizmo.xml
msgid "Custom gizmo for editing Spatial objects."
-msgstr "用于编辑空间对象的自定义å°å·¥å…·ã€‚"
+msgstr "用于编辑 Spatial 对象的自定义å°å·¥å…·ã€‚"
#: doc/classes/EditorSpatialGizmo.xml
msgid ""
@@ -28181,7 +28265,7 @@ msgid ""
"Adds the specified [code]segments[/code] to the gizmo's collision shape for "
"picking. Call this function during [method redraw]."
msgstr ""
-"将指定的 [code]segments[/code] 添加到 gizmo 的碰撞形状中,以便挑选。在 "
+"将指定的线段 [code]segments[/code] 添加到å°å·¥å…·çš„碰撞形状中,用于点选。请在 "
"[method redraw] 时调用此函数。"
#: doc/classes/EditorSpatialGizmo.xml
@@ -28190,8 +28274,8 @@ msgid ""
"generated from a regular [Mesh] too. Call this function during [method "
"redraw]."
msgstr ""
-"将碰撞三角形添加到å°å·¥å…·ä¸­ï¼Œä¾›æŒ‘选。也å¯ä»¥ä»Žæ™®é€šçš„ [Mesh] ç”Ÿæˆ "
-"[TriangleMesh]。在 [method redraw] 时调用此函数。"
+"将碰撞三角形添加到å°å·¥å…·ä¸­ï¼Œç”¨äºŽç‚¹é€‰ã€‚也å¯ä»¥ä»Žæ™®é€šçš„ [Mesh] ç”Ÿæˆ "
+"[TriangleMesh]。请在 [method redraw] 时调用此函数。"
#: doc/classes/EditorSpatialGizmo.xml
msgid ""
@@ -28200,8 +28284,8 @@ msgid ""
"There are virtual functions which will be called upon editing of these "
"handles. Call this function during [method redraw]."
msgstr ""
-"æ·»åŠ ä¸€ä¸ªå¥æŸ„(点)列表,å¯ä»¥ç”¨æ¥å¯¹ç¼–辑的对象进行å˜å½¢ã€‚\n"
-"æœ‰ä¸€äº›è™šå‡½æ•°å°†åœ¨ç¼–è¾‘è¿™äº›å¥æŸ„时被调用。在 [method redraw]时调用这个函数。"
+"添加列表中的手柄(点),å¯ä»¥ç”¨æ¥å¯¹ç¼–辑的对象进行å˜å½¢ã€‚\n"
+"编辑这些手柄时会调用一些虚函数。请在 [method redraw] 时调用这个函数。"
#: doc/classes/EditorSpatialGizmo.xml
msgid ""
@@ -28209,8 +28293,8 @@ msgid ""
"lines are used for visualizing the gizmo. Call this function during [method "
"redraw]."
msgstr ""
-"用给定的æè´¨åœ¨å°å·¥å…·ä¸Šæ·»åŠ çº¿æ¡åˆ° gizmo(作为 2 个点的集åˆï¼‰ã€‚线æ¡ç”¨äºŽå¯è§†åŒ– "
-"gizmo。在 [method redraw] 时调用此函数。"
+"在å°å·¥å…·ä¸Šæ·»åŠ ä½¿ç”¨ç»™å®šæè´¨çš„线æ¡ï¼ˆå½¢å¼ä¸º 2 个点的集åˆï¼‰ã€‚线æ¡å°†ç”¨äºŽæ˜¾ç¤ºå°å·¥"
+"具。请在 [method redraw] 时调用此函数。"
#: doc/classes/EditorSpatialGizmo.xml
msgid ""
@@ -28219,10 +28303,10 @@ msgid ""
"is [code]true[/code], the mesh will rotate to always face the camera. Call "
"this function during [method redraw]."
msgstr ""
-"以指定的 [code]billboard[/code] 状æ€ã€[code]skeleton[/code] å’Œ "
-"[code]materia[/code] 添加网格到å°å·¥å…·ã€‚如果 [code]billboard[/code] 为 "
-"[code]true[/code],则网格将旋转为始终é¢å‘相机。在 [method redraw] 时调用此函"
-"数。"
+"在å°å·¥å…·ä¸Šæ·»åŠ æŒ‡å®šçš„ç½‘æ ¼ï¼Œç½‘æ ¼ä½¿ç”¨çš„æ˜¯æŒ‡å®šçš„ [code]billboard[/code] 状æ€ã€"
+"[code]skeleton[/code] 和 [code]materia[/code]。如果 [code]billboard[/code] "
+"为 [code]true[/code],则网格将旋转为始终é¢å‘相机。请在 [method redraw] 时调用"
+"此函数。"
#: doc/classes/EditorSpatialGizmo.xml
msgid ""
@@ -28233,7 +28317,7 @@ msgstr "添加一个未缩放的广告牌以实现å¯è§†åŒ–。在 [method redraw
#: doc/classes/EditorSpatialGizmo.xml
msgid ""
"Removes everything in the gizmo including meshes, collisions and handles."
-msgstr "移除å°å·¥å…·ä¸­çš„一切,包括网格ã€ç¢°æ’žå’Œå¥æŸ„。"
+msgstr "移除å°å·¥å…·ä¸­çš„一切,包括网格ã€ç¢°æ’žå’Œæ‰‹æŸ„。"
#: doc/classes/EditorSpatialGizmo.xml
msgid ""
@@ -28242,9 +28326,9 @@ msgid ""
"If the [code]cancel[/code] parameter is [code]true[/code], an option to "
"restore the edited value to the original is provided."
msgstr ""
-"æäº¤ä¸€ä¸ªæ­£åœ¨ç¼–è¾‘çš„å¥æŸ„ï¼ˆå¥æŸ„必须是之å‰é€šè¿‡[method add_handles]添加的)。\n"
-"如果[code]cancel[/code]傿•°æ˜¯[code]true[/code],则æä¾›äº†ä¸€ä¸ªå°†ç¼–辑åŽçš„值æ¢å¤"
-"到原始值的选项。"
+"æäº¤æ­£åœ¨ç¼–辑的手柄(手柄必须是之å‰é€šè¿‡ [method add_handles] 添加的)。\n"
+"如果 [code]cancel[/code] 傿•°ä¸º [code]true[/code],则会æä¾›ä¸€ä¸ªå°†ç¼–辑åŽçš„值æ¢"
+"å¤åˆ°åŽŸå§‹å€¼çš„é€‰é¡¹ã€‚"
#: doc/classes/EditorSpatialGizmo.xml
msgid ""
@@ -28252,16 +28336,16 @@ msgid ""
"by [method add_handles]).\n"
"Handles can be named for reference to the user when editing."
msgstr ""
-"获å–å·²ç¼–è¾‘çš„å¥æŸ„çš„åç§°ï¼ˆå¥æŸ„必须是之å‰é€šè¿‡[method add_handles]添加的)。\n"
-"奿Ÿ„çš„åç§°å¯ä»¥åœ¨ç¼–辑时被命å作为用户å‚考。"
+"获å–编辑的手柄的å称(手柄必须是之å‰é€šè¿‡ [method add_handles] 添加的)。\n"
+"手柄的åç§°å¯ä»¥åœ¨ç¼–辑时被命å作为用户å‚考。"
#: 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 ""
-"获å–ä¸€ä¸ªå¥æŸ„的实际值,这个值å¯ä»¥æ˜¯ä»»ä½•东西,用于在调用[method commit_handle]"
-"时最终撤销动作。这个值å¯ä»¥æ˜¯ä»»ä½•东西,用于在调用[method commit_handle]时最终"
+"èŽ·å–æ‰‹æŸ„的实际值。这个值å¯ä»¥æ˜¯ä»»ä½•东西,用于在调用 [method commit_handle] æ—¶"
+"最终撤销动作。这个值å¯ä»¥æ˜¯ä»»ä½•东西,用于在调用 [method commit_handle] 时最终"
"撤销动作。"
#: doc/classes/EditorSpatialGizmo.xml
@@ -28281,15 +28365,16 @@ msgid ""
"Returns [code]true[/code] if the handle at index [code]index[/code] is "
"highlighted by being hovered with the mouse."
msgstr ""
-"如果鼠标悬åœç´¢å¼•为 [code]index[/code] çš„å¥æŸ„高亮,则返回 [code]true[/code]。"
+"如果鼠标悬åœåœ¨ç´¢å¼•为 [code]index[/code] 的手柄上使之高亮,则返回 [code]true[/"
+"code]。"
#: doc/classes/EditorSpatialGizmo.xml
msgid ""
"This function is called when the [Spatial] this gizmo refers to changes (the "
"[method Spatial.update_gizmo] is called)."
msgstr ""
-"当这个工具所指 [Spatial] çš„å˜åŒ–时([method Spatial.update_gizmo] 函数被调"
-"用)。"
+"这个å°å·¥å…·æ‰€å¼•用的 [Spatial] å‘生å˜åŒ–时([method Spatial.update_gizmo] 函数被"
+"调用)会调用这个函数。"
#: doc/classes/EditorSpatialGizmo.xml
msgid ""
@@ -28298,8 +28383,8 @@ msgid ""
"The [Camera] is also provided so screen coordinates can be converted to "
"raycasts."
msgstr ""
-"当用户在å±å¹•åæ ‡ä¸­æ‹–动一个 gizmo 工具手柄时(之å‰ç”¨ [method add_handles] 添加"
-"的),就会使用这个函数。\n"
+"当用户在å±å¹•åæ ‡ä¸­æ‹–动å°å·¥å…·æ‰‹æŸ„时(之å‰ç”¨ [method add_handles] 添加),就会"
+"使用这个函数。\n"
"还æä¾›äº†ç›¸æœº [Camera],以便将å±å¹•åæ ‡è½¬æ¢ä¸ºå°„线投影。"
#: doc/classes/EditorSpatialGizmo.xml
@@ -28307,18 +28392,19 @@ msgid ""
"Sets the gizmo's hidden state. If [code]true[/code], the gizmo will be "
"hidden. If [code]false[/code], it will be shown."
msgstr ""
-"设置工具的éšè—状æ€ã€‚如果为 [code]true[/code]ï¼Œåˆ™å°æŽ§ä»¶å°†è¢«éšè—。如果为 "
-"[code]false[/code],将显示它。"
+"设置该å°å·¥å…·çš„éšè—状æ€ã€‚如果为 [code]true[/code],则该å°å·¥å…·å°†è¢«éšè—。如果为 "
+"[code]false[/code] 则会显示。"
#: doc/classes/EditorSpatialGizmo.xml
msgid ""
"Sets the reference [Spatial] node for the gizmo. [code]node[/code] must "
"inherit from [Spatial]."
-msgstr "设置工具的å‚考 [Spatial] 节点。[code]node[/code]必须继承自 [Spatial]。"
+msgstr ""
+"设置该å°å·¥å…·æ‰€å¼•用的 [Spatial] 节点。[code]node[/code]必须继承自 [Spatial]。"
#: doc/classes/EditorSpatialGizmoPlugin.xml
msgid "Used by the editor to define Spatial gizmo types."
-msgstr "由编辑部用于定义空间å°å·¥å…·çš„类型。"
+msgstr "由编辑部用于定义 Spatial å°å·¥å…·çš„类型。"
#: doc/classes/EditorSpatialGizmoPlugin.xml
msgid ""
@@ -28329,8 +28415,8 @@ msgid ""
"To use [EditorSpatialGizmoPlugin], register it using the [method "
"EditorPlugin.add_spatial_gizmo_plugin] method first."
msgstr ""
-"[EditorSpatialGizmoPlugin] å¯ç”¨äºŽå®šä¹‰æ–°çš„æŽ§åˆ¶å™¨ç±»åž‹ã€‚这样åšçš„ä¸»è¦æ–¹æ³•有两ç§ï¼š"
-"比较简å•的控制器å¯ä»¥æ‰©å±• [EditorSpatialGizmoPlugin],或者å¯ä»¥åˆ›å»ºæ–°çš„ "
+"[EditorSpatialGizmoPlugin] å¯ç”¨äºŽå®šä¹‰æ–°çš„å°å·¥å…·ç±»åž‹ã€‚这样åšçš„ä¸»è¦æ–¹æ³•有两ç§ï¼š"
+"比较简å•çš„å°å·¥å…·å¯ä»¥æ‰©å±• [EditorSpatialGizmoPlugin],或者å¯ä»¥åˆ›å»ºæ–°çš„ "
"[EditorSpatialGizmo] 类型。有关更多信æ¯ï¼Œè¯·å‚阅文档中的教程。\n"
"è¦ä½¿ç”¨ [EditorSpatialGizmoPlugin],请先用 [method EditorPlugin."
"add_spatial_gizmo_plugin] 注册。"
@@ -28348,13 +28434,13 @@ msgid ""
"Override this method to define whether the gizmo can be hidden or not. "
"Returns [code]true[/code] if not overridden."
msgstr ""
-"é‡å†™æ­¤æ–¹æ³•以定义是å¦å¯ä»¥éšè— Gizmo。如果未覆盖,则返回 [code]true[/code]。"
+"é‡å†™æ­¤æ–¹æ³•以定义是å¦å¯ä»¥éšè—该å°å·¥å…·ã€‚如果未覆盖,则返回 [code]true[/code]。"
#: doc/classes/EditorSpatialGizmoPlugin.xml
msgid ""
"Override this method to commit gizmo handles. Called for this plugin's "
"active gizmos."
-msgstr "é‡å†™æ­¤æ–¹æ³•以æäº¤ Gizmo 奿Ÿ„。调用此æ’件的活动辅助工具。"
+msgstr "é‡å†™æ­¤æ–¹æ³•以æäº¤å°å·¥å…·æ‰‹æŸ„。会为这个æ’件的活动å°å·¥å…·è¿›è¡Œè°ƒç”¨ã€‚"
#: doc/classes/EditorSpatialGizmoPlugin.xml
msgid ""
@@ -28405,13 +28491,13 @@ msgstr ""
msgid ""
"Override this method to provide gizmo's handle names. Called for this "
"plugin's active gizmos."
-msgstr "é‡å†™æ­¤æ–¹æ³•以æä¾› Gizmo çš„å¥æŸ„å称。调用此æ’件的活动工具。"
+msgstr "é‡å†™æ­¤æ–¹æ³•以æä¾›å°å·¥å…·çš„æ‰‹æŸ„å称。会为这个æ’件的活动å°å·¥å…·è¿›è¡Œè°ƒç”¨ã€‚"
#: doc/classes/EditorSpatialGizmoPlugin.xml
msgid ""
"Gets actual value of a handle from gizmo. Called for this plugin's active "
"gizmos."
-msgstr "从 Gizmo 获å–奿Ÿ„的实际值。调用此æ’件的活动工具。"
+msgstr "从å°å·¥å…·èŽ·å–æ‰‹æŸ„的实际值。会为这个æ’件的活动å°å·¥å…·è¿›è¡Œè°ƒç”¨ã€‚"
#: doc/classes/EditorSpatialGizmoPlugin.xml
msgid ""
@@ -28426,7 +28512,7 @@ msgstr ""
msgid ""
"Override this method to provide the name that will appear in the gizmo "
"visibility menu."
-msgstr "é‡å†™æ­¤æ–¹æ³•以æä¾›å°†å‡ºçŽ°åœ¨å·¥å…·å¯è§æ€§èœå•中的å称。"
+msgstr "é‡å†™æ­¤æ–¹æ³•以æä¾›å°†å‡ºçŽ°åœ¨å°å·¥å…·å¯è§æ€§èœå•中的å称。"
#: doc/classes/EditorSpatialGizmoPlugin.xml
msgid ""
@@ -28437,10 +28523,10 @@ msgid ""
"overridden, this method will return [code]0[/code], which means custom "
"gizmos will automatically override built-in gizmos."
msgstr ""
-"é‡å†™æ­¤æ–¹æ³•å¯ä»¥è®¾ç½®å·¥å…·çš„优先级。值越高,优先级越高。如果具有较高优先级的工具"
-"与å¦ä¸€ä¸ªå·¥å…·å‘生冲çªï¼Œåˆ™ä»…使用具有较高优先级的工具。\n"
-"æ‰€æœ‰å†…ç½®ç¼–è¾‘å™¨å°æŽ§ä»¶å‡è¿”回 [code]-1[/code]优先级。如果未é‡å†™ï¼Œåˆ™æ­¤æ–¹æ³•将返回 "
-"[code]0[/code],这æ„味ç€è‡ªå®šä¹‰æŽ§ä»¶å°†è‡ªåŠ¨è¦†ç›–å†…ç½®æŽ§ä»¶ã€‚"
+"é‡å†™æ­¤æ–¹æ³•å¯ä»¥è®¾ç½®å°å·¥å…·çš„优先级。值越高,优先级越高。如果具有较高优先级的å°"
+"工具与å¦ä¸€ä¸ªå°å·¥å…·å‘生冲çªï¼Œåˆ™ä»…使用具有较高优先级的å°å·¥å…·ã€‚\n"
+"所有内置编辑器å°å·¥å…·å‡è¿”回 [code]-1[/code] 优先级。如果未é‡å†™ï¼Œåˆ™æ­¤æ–¹æ³•将返"
+"回 [code]0[/code],这æ„味ç€è‡ªå®šä¹‰æŽ§ä»¶å°†è‡ªåŠ¨è¦†ç›–å†…ç½®å°å·¥å…·ã€‚"
#: doc/classes/EditorSpatialGizmoPlugin.xml
msgid ""
@@ -28449,34 +28535,36 @@ msgid ""
"if it returns [code]true[/code] the node gets a generic [EditorSpatialGizmo] "
"assigned and is added to this plugin's list of active gizmos."
msgstr ""
-"覆盖这个方法æ¥å®šä¹‰å“ªäº›ç©ºé—´èŠ‚ç‚¹æœ‰è¿™ä¸ªæ’ä»¶çš„ gizmo。æ¯å½“一个 [Spatial] 节点被添"
-"加到一个场景中时,这个方法就会被调用,如果它返回 [code]true[/code],该节点就"
-"会被分é…一个通用的 [EditorSpatialGizmo],并被添加到这个æ’件的激活 Gizmos列表"
-"中。"
+"覆盖这个方法æ¥å®šä¹‰å“ªäº› Spatial 节点有这个æ’ä»¶çš„å°å·¥å…·ã€‚æ¯å½“一个 [Spatial] 节"
+"点被添加到一个场景中时,这个方法就会被调用,如果它返回 [code]true[/code],该"
+"节点就会被分é…一个通用的 [EditorSpatialGizmo],并被添加到这个æ’件的激活å°å·¥å…·"
+"列表中。"
#: doc/classes/EditorSpatialGizmoPlugin.xml
msgid ""
"Gets whether a handle is highlighted or not. Called for this plugin's active "
"gizmos."
-msgstr "获å–奿Ÿ„是å¦é«˜äº®æ˜¾ç¤ºã€‚调用此æ’件的活动工具。"
+msgstr "èŽ·å–æ‰‹æŸ„是å¦é«˜äº®æ˜¾ç¤ºã€‚会为这个æ’件的活动å°å·¥å…·è¿›è¡Œè°ƒç”¨ã€‚"
#: doc/classes/EditorSpatialGizmoPlugin.xml
msgid ""
"Override this method to define whether a Spatial with this gizmo should be "
"selectable even when the gizmo is hidden."
-msgstr "覆盖此方法,以定义具有此工具的空间是å¦åº”该在工具被éšè—时也å¯ä»¥è¢«é€‰æ‹©ã€‚"
+msgstr ""
+"覆盖此方法,以定义具有此å°å·¥å…·çš„ Spatial 是å¦åº”该在å°å·¥å…·è¢«éšè—时也å¯ä»¥è¢«é€‰"
+"择。"
#: doc/classes/EditorSpatialGizmoPlugin.xml
msgid ""
"Callback to redraw the provided gizmo. Called for this plugin's active "
"gizmos."
-msgstr "å›žè°ƒä»¥é‡æ–°ç»˜åˆ¶æä¾›çš„工具。调用此æ’件的活动工具。"
+msgstr "用以é‡ç»˜ç»™å®šçš„å°å·¥å…·çš„回调。会为这个æ’件的活动å°å·¥å…·è¿›è¡Œè°ƒç”¨ã€‚"
#: doc/classes/EditorSpatialGizmoPlugin.xml
msgid ""
"Update the value of a handle after it has been updated. Called for this "
"plugin's active gizmos."
-msgstr "æ›´æ–°å¥æŸ„åŽæ›´æ–°å…¶å€¼ã€‚调用此æ’件的活动工具。"
+msgstr "æ›´æ–°æ‰‹æŸ„åŽæ›´æ–°å…¶å€¼ã€‚会为这个æ’件的活动å°å·¥å…·è¿›è¡Œè°ƒç”¨ã€‚"
#: doc/classes/EditorSpinSlider.xml
msgid "Godot editor's control for editing numeric values."
@@ -28902,8 +28990,8 @@ msgid ""
"here.\n"
"[/codeblock]"
msgstr ""
-"返回自引擎åˆå§‹åŒ–以æ¥çš„æ€»å¸§æ•°ï¼Œåœ¨æ¯ä¸ª[b]空闲帧[/b]都会进行,无论渲染循环是å¦è¢«"
-"å¯ç”¨ã€‚å‚阅 [method get_frames_drawn] å’Œ [method get_physics_frames]。\n"
+"返回自引擎åˆå§‹åŒ–以æ¥çš„æ€»å¸§æ•°ï¼Œæ— è®ºæ˜¯å¦å¯ç”¨æ¸²æŸ“循环,æ¯ä¸ª[b]空闲帧[/b]都会增"
+"长。å¦è¯·å‚阅 [method get_frames_drawn] å’Œ [method get_physics_frames]。\n"
"[method get_idle_frames] å¯ä»¥ç”¨æ¥å‡å°‘è¿è¡Œé«˜æ¶ˆè€—逻辑的次数,而ä¸éœ€è¦ä¾é  "
"[Timer]。\n"
"[codeblock]\n"
@@ -29143,14 +29231,14 @@ msgstr ""
"ä¿¡æ¯å¯èƒ½ä¼šè¢«éšè—,å³ä½¿å®ƒä»¬æ˜¯ç”±å…¶ä»–脚本触å‘。如果在 [code]tool[/code] 脚本中把"
"这个设置为 [code]false[/code],这也会影å“到编辑器本身。在确ä¿é”™è¯¯ä¿¡æ¯è¢«å¯ç”¨ä¹‹"
"å‰ï¼Œ[i]请勿[/i]报告错误(因为默认情况下是会的)。\n"
-"[b]注æ„:[/b]当从编辑器è¿è¡Œä¸€ä¸ªé¡¹ç›®æ—¶ï¼Œè¿™ä¸ªå±žæ€§ä¸å½±å“编辑器的错误选项å¡ã€‚"
+"[b]注æ„:[/b]从编辑器è¿è¡Œé¡¹ç›®æ—¶ï¼Œè¿™ä¸ªå±žæ€§ä¸å½±å“编辑器的错误选项å¡ã€‚"
#: doc/classes/Engine.xml
msgid ""
"The desired frames per second. If the hardware cannot keep up, this setting "
"may not be respected. A value of 0 means no limit."
msgstr ""
-"所需的æ¯ç§’帧数。如果硬件无法跟上,则å¯èƒ½ä¸éµå®ˆæ­¤è®¾ç½®ã€‚值为0表示没有é™åˆ¶ã€‚"
+"所需的æ¯ç§’帧数。如果硬件无法跟上,则å¯èƒ½ä¸éµå®ˆæ­¤è®¾ç½®ã€‚值为 0 表示没有é™åˆ¶ã€‚"
#: doc/classes/Engine.xml
msgid ""
@@ -29863,7 +29951,7 @@ msgid ""
msgstr ""
"ä½¿ç”¨è‡ªå®šä¹‰çš„é€æ˜Žé¢œè‰²æ¸…除背景,并å…许定义天空的阴影和åå°„ã€‚è¿™ç§æ¨¡å¼æ¯” "
"[constant BG_SKY] ç¨å¿«ï¼Œåº”是在å¯ä»¥çœ‹åˆ°å射,但天空本身ä¸å¯è§çš„场景中的首选"
-"(例如,自上而下的相机)。"
+"(例如俯视角相机)。"
#: doc/classes/Environment.xml
msgid "Displays a [CanvasLayer] in the background."
@@ -30830,7 +30918,7 @@ msgid ""
"will change the window title to \"Open a File\")."
msgstr ""
"如果为 [code]true[/code],更改 [code]Mode[/code] å±žæ€§å°†ç›¸åº”åœ°è®¾ç½®çª—å£æ ‡é¢˜ï¼ˆä¾‹"
-"如,将模å¼è®¾ç½®ä¸º [constant MODE_OPEN_FILE] ä¼šå°†çª—å£æ ‡é¢˜æ›´æ”¹ä¸ºâ€œæ‰“开文件â€ï¼‰ã€‚"
+"如将模å¼è®¾ç½®ä¸º [constant MODE_OPEN_FILE] ä¼šå°†çª—å£æ ‡é¢˜æ›´æ”¹ä¸ºâ€œæ‰“开文件â€ï¼‰ã€‚"
#: doc/classes/FileDialog.xml
msgid "If [code]true[/code], the dialog will show hidden files."
@@ -36983,7 +37071,7 @@ msgstr "原始纹ç†ï¼ˆåœ¨åŽ‹ç¼©å‰ï¼‰ä½¿ç”¨ sRGB 空间。"
msgid ""
"Source texture (before compression) is a normal texture (e.g. it can be "
"compressed into two channels)."
-msgstr "原始纹ç†ï¼ˆåœ¨åŽ‹ç¼©å‰ï¼‰æ˜¯æ³•线纹ç†ï¼ˆä¾‹å¦‚,å¯ä»¥åŽ‹ç¼©ä¸ºä¸¤ä¸ªé€šé“)。"
+msgstr "原始纹ç†ï¼ˆåœ¨åŽ‹ç¼©å‰ï¼‰æ˜¯æ³•线纹ç†ï¼ˆä¾‹å¦‚å¯ä»¥åŽ‹ç¼©ä¸ºä¸¤ä¸ªé€šé“)。"
#: doc/classes/Image.xml
msgid "Source texture (before compression) is a [TextureLayered]."
@@ -41441,11 +41529,14 @@ msgstr ""
"如果为 [code]true[/code]ï¼Œåˆ™å…‰çº¿çš„æ•ˆæžœä¼šé€†è½¬ï¼Œä½¿åŒºåŸŸå˜æš—并投射明亮的阴影。"
#: doc/classes/Light.xml
+#, fuzzy
msgid ""
"The size of the light in Godot units. Only considered in baked lightmaps and "
"only if [member light_bake_mode] is set to [constant BAKE_ALL]. Increasing "
"this value will make the shadows appear blurrier. This can be used to "
-"simulate area lights to an extent."
+"simulate area lights to an extent.\n"
+"[b]Note:[/b] [member light_size] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
"ç¯å…‰çš„大å°ï¼Œä½¿ç”¨ Godot çš„å•ä½ã€‚åªåœ¨çƒ˜ç„™çš„光照贴图中考虑,并且åªåœ¨ [member "
"light_bake_mode] 被设置为 [constant BAKE_ALL] 时考虑。增加这个值会使阴影看起"
@@ -43128,8 +43219,8 @@ msgstr ""
"点击åŽä¼šå¼¹å‡º [PopupMenu] 的特殊按钮。\n"
"å¯ä»¥ä½¿ç”¨ [code]get_popup().add_item(\"èœå•项目åç§°\")[/code] 在这个 "
"[PopupMenu] 中创建新项目。你也å¯ä»¥ç›´æŽ¥ä»Žç¼–辑器中创建它们。è¦åšåˆ°è¿™ç‚¹ï¼Œé€‰æ‹© "
-"[MenuButton] 节点,然åŽåœ¨ 2D 编辑器顶部的工具æ ä¸­ï¼Œç‚¹å‡»[b]项目[/b],然åŽç‚¹å‡»"
-"弹出窗å£ä¸­çš„[b]添加[/b]。你将能够赋予æ¯ä¸ªé¡¹ç›®æ–°çš„属性。\n"
+"[MenuButton] 节点,然åŽåœ¨ 2D 编辑器顶部的工具æ ä¸­ï¼Œç‚¹å‡»[b]列表项[/b],然åŽç‚¹"
+"击弹出窗å£ä¸­çš„[b]添加[/b]。你将能够赋予æ¯ä¸ªé¡¹ç›®æ–°çš„属性。\n"
"与该节点相关的常用属性和方法请å‚阅 [BaseButton]。"
#: doc/classes/MenuButton.xml doc/classes/OptionButton.xml
@@ -43286,23 +43377,23 @@ msgstr ""
msgid ""
"Returns all the vertices that make up the faces of the mesh. Each three "
"vertices represent one triangle."
-msgstr "返回所有在这个网格中,构æˆé¢çš„顶点。æ¯ä¸‰ä¸ªé¡¶ç‚¹ä»£è¡¨ä¸€ä¸ªä¸‰è§’形。"
+msgstr "返回网格中所有构æˆé¢çš„顶点。æ¯ä¸‰ä¸ªé¡¶ç‚¹ä»£è¡¨ä¸€ä¸ªä¸‰è§’形。"
#: doc/classes/Mesh.xml
msgid "Returns the amount of surfaces that the [Mesh] holds."
-msgstr "è¿”å›žè¯¥ç½‘æ ¼çš„é¢æ•°ã€‚"
+msgstr "返回该 [Mesh] 中表é¢çš„个数。"
#: doc/classes/Mesh.xml
msgid ""
"Returns the arrays for the vertices, normals, uvs, etc. that make up the "
"requested surface (see [method ArrayMesh.add_surface_from_arrays])."
msgstr ""
-"返回所有组æˆé¢æ‰€éœ€çš„东西构æˆçš„æ•°ç»„的数组,例如顶点,法å‘,UV等。(å‚阅"
-"[method ArrayMesh.add_surface_from_arrays])。"
+"返回构æˆè¯·æ±‚表é¢çš„é¡¶ç‚¹ã€æ³•线ã€UV ç­‰æ•°ç»„ã€‚ï¼ˆè§ [method ArrayMesh."
+"add_surface_from_arrays])。"
#: doc/classes/Mesh.xml
msgid "Returns the blend shape arrays for the requested surface."
-msgstr "返回所需é¢çš„æ··åˆå½¢çŠ¶æ•°ç»„ã€‚"
+msgstr "返回请求表é¢çš„æ··åˆå½¢çŠ¶æ•°ç»„ã€‚"
#: doc/classes/Mesh.xml
msgid ""
@@ -43326,31 +43417,31 @@ msgstr ""
#: doc/classes/Mesh.xml
msgid "Render array as points (one vertex equals one point)."
-msgstr "将顶点数组渲染为点阵(一个顶点对应一个点阵中的点)。"
+msgstr "将数组渲染为点(一个顶点对应一个点)。"
#: doc/classes/Mesh.xml
msgid "Render array as lines (every two vertices a line is created)."
-msgstr "将顶点组渲染为线æ¡ï¼ˆæ¯ä¸¤ä¸ªé¡¶ç‚¹ä¹‹é—´åˆ›å»ºä¸€æ¡è¿žçº¿ï¼‰ã€‚"
+msgstr "将数组渲染为线(æ¯ä¸¤ä¸ªé¡¶ç‚¹åˆ›å»ºä¸€æ¡è¿žçº¿ï¼‰ã€‚"
#: doc/classes/Mesh.xml
msgid "Render array as line strip."
-msgstr "将顶点组渲染为线æ¡ã€‚"
+msgstr "将数组渲染为线æ¡ã€‚"
#: doc/classes/Mesh.xml
msgid "Render array as line loop (like line strip, but closed)."
-msgstr "将数组渲染æˆçº¿çŠ¶çŽ¯ï¼ˆåƒçº¿æ¡ï¼Œä½†æ˜¯å°é—­çš„)。"
+msgstr "将数组渲染为线环(类似线æ¡ï¼Œä½†æ˜¯å°é—­çš„)。"
#: doc/classes/Mesh.xml
msgid "Render array as triangles (every three vertices a triangle is created)."
-msgstr "将顶点组渲染为三角形(æ¯ä¸‰ä¸ªç›¸é‚»é¡¶ç‚¹åˆ›å»ºä¸€ä¸ªä¸‰è§’形)。"
+msgstr "将数组渲染为三角形(æ¯ä¸‰ä¸ªé¡¶ç‚¹åˆ›å»ºä¸€ä¸ªä¸‰è§’形)。"
#: doc/classes/Mesh.xml
msgid "Render array as triangle strips."
-msgstr "将顶点组渲染为三角形线框。"
+msgstr "将数组渲染为三角形æ¡ã€‚"
#: doc/classes/Mesh.xml
msgid "Render array as triangle fans."
-msgstr "将数组渲染æˆä¸‰è§’形扇形。"
+msgstr "将数组渲染为三角形扇。"
#: doc/classes/Mesh.xml doc/classes/VisualServer.xml
msgid "Blend shapes are normalized."
@@ -43358,46 +43449,45 @@ msgstr "æ··åˆå½¢çŠ¶æ˜¯è¢«å½’ä¸€åŒ–äº†çš„ã€‚"
#: doc/classes/Mesh.xml doc/classes/VisualServer.xml
msgid "Blend shapes are relative to base weight."
-msgstr "æ··åˆå½¢çŠ¶ç›¸å¯¹äºŽåŸºç¡€çš„æƒé‡ã€‚"
+msgstr "æ··åˆå½¢çŠ¶æ˜¯ç›¸å¯¹äºŽåŸºç¡€çš„æƒé‡ã€‚"
#: doc/classes/Mesh.xml
msgid ""
"Mesh array contains vertices. All meshes require a vertex array so this "
"should always be present."
-msgstr ""
-"网格组包å«è®¸å¤šé¡¶ç‚¹ã€‚æ¯ä¸€ä¸ªç½‘格都需è¦ä¸€ä¸ªé¡¶ç‚¹æ•°ç»„,所以这应该æŒä¹…化储存。"
+msgstr "网格数组包å«é¡¶ç‚¹ã€‚æ‰€æœ‰ç½‘æ ¼éƒ½éœ€è¦æœ‰é¡¶ç‚¹æ•°ç»„,所以这应该始终存在。"
#: doc/classes/Mesh.xml
msgid "Mesh array contains normals."
-msgstr "ç½‘æ ¼ç»„åŒ…å«æ³•线。"
+msgstr "ç½‘æ ¼æ•°ç»„åŒ…å«æ³•线。"
#: doc/classes/Mesh.xml
msgid "Mesh array contains tangents."
-msgstr "网格组包å«åˆ‡å‘。"
+msgstr "网格数组包å«åˆ‡çº¿ã€‚"
#: doc/classes/Mesh.xml
msgid "Mesh array contains colors."
-msgstr "网格组包å«é¢œè‰²ã€‚"
+msgstr "网格数组包å«é¢œè‰²ã€‚"
#: doc/classes/Mesh.xml
msgid "Mesh array contains UVs."
-msgstr "ç½‘æ ¼ç»„åŒ…å« UV。"
+msgstr "ç½‘æ ¼æ•°ç»„åŒ…å« UV。"
#: doc/classes/Mesh.xml
msgid "Mesh array contains second UV."
-msgstr "网格组包å«ç¬¬äºŒå¥— UV。"
+msgstr "网格数组包å«ç¬¬äºŒå¥— UV。"
#: doc/classes/Mesh.xml
msgid "Mesh array contains bones."
-msgstr "网格组包å«éª¨éª¼ã€‚"
+msgstr "网格数组包å«éª¨éª¼ã€‚"
#: doc/classes/Mesh.xml
msgid "Mesh array contains bone weights."
-msgstr "网格组包å«éª¨éª¼æƒé‡ã€‚"
+msgstr "网格数组包å«éª¨éª¼æƒé‡ã€‚"
#: doc/classes/Mesh.xml
msgid "Mesh array uses indices."
-msgstr "网格组使用索引。"
+msgstr "网格数组使用索引。"
#: doc/classes/Mesh.xml
msgid ""
@@ -43411,11 +43501,11 @@ msgstr "用于标记压缩(åŠç²¾åº¦æµ®ç‚¹ï¼‰é¡¶ç‚¹æ•°ç»„的标志。"
#: doc/classes/Mesh.xml doc/classes/VisualServer.xml
msgid "Flag used to mark a compressed (half float) normal array."
-msgstr "曾ç»ç”¨äºŽæ ‡è®°åŽ‹ç¼©ï¼ˆåŠç²¾åº¦æµ®ç‚¹ï¼‰æ³•呿•°ç»„的标志。"
+msgstr "用于标记压缩(åŠç²¾åº¦æµ®ç‚¹ï¼‰æ³•呿•°ç»„的标志。"
#: doc/classes/Mesh.xml doc/classes/VisualServer.xml
msgid "Flag used to mark a compressed (half float) tangent array."
-msgstr "曾ç»ç”¨äºŽæ ‡è®°åŽ‹ç¼©ï¼ˆåŠç²¾åº¦æµ®ç‚¹ï¼‰åˆ‡å‘数组的标志。"
+msgstr "用于标记压缩(åŠç²¾åº¦æµ®ç‚¹ï¼‰åˆ‡çº¿æ•°ç»„的标志。"
#: doc/classes/Mesh.xml
msgid ""
@@ -43424,16 +43514,19 @@ msgid ""
"unsigned integers. This will clamp overbright colors to [code]Color(1, 1, 1, "
"1)[/code] and reduce colors' precision."
msgstr ""
+"用于标记压缩(åŠç²¾åº¦æµ®ç‚¹ï¼‰é¢œè‰²æ•°ç»„的标志。\n"
+"[b]注æ„:[/b]如果å¯ç”¨è¿™ä¸ªæ ‡å¿—,顶点颜色会作为 8 使— ç¬¦å·æ•´æ•°å­˜å‚¨ã€‚这会导致过"
+"亮颜色被钳制到 [code]Color(1, 1, 1, 1)[/code],é™ä½Žé¢œè‰²çš„精度。"
#: doc/classes/Mesh.xml doc/classes/VisualServer.xml
msgid "Flag used to mark a compressed (half float) UV coordinates array."
-msgstr "曾用于标记压缩(åŠç²¾åº¦æµ®ç‚¹ï¼‰UV åæ ‡æ•°ç»„的标志。"
+msgstr "用于标记压缩(åŠç²¾åº¦æµ®ç‚¹ï¼‰UV åæ ‡æ•°ç»„的标志。"
#: doc/classes/Mesh.xml doc/classes/VisualServer.xml
msgid ""
"Flag used to mark a compressed (half float) UV coordinates array for the "
"second UV coordinates."
-msgstr "曾用于标记第二套 UV åæ ‡çš„压缩(åŠç²¾åº¦æµ®ç‚¹ï¼‰UV åæ ‡æ•°ç»„的标志。"
+msgstr "用于标记第二套 UV åæ ‡çš„压缩(åŠç²¾åº¦æµ®ç‚¹ï¼‰UV åæ ‡æ•°ç»„的标志。"
#: doc/classes/Mesh.xml doc/classes/VisualServer.xml
msgid "Flag used to mark a compressed bone array."
@@ -43445,11 +43538,11 @@ msgstr "用于标记压缩(åŠç²¾åº¦æµ®ç‚¹ï¼‰æƒé‡æ•°ç»„的标志。"
#: doc/classes/Mesh.xml doc/classes/VisualServer.xml
msgid "Flag used to mark a compressed index array."
-msgstr "曾用于标记压缩索引数组的标志。"
+msgstr "用于标记压缩索引数组的标志。"
#: doc/classes/Mesh.xml doc/classes/VisualServer.xml
msgid "Flag used to mark that the array contains 2D vertices."
-msgstr "æ›¾ç”¨äºŽæ ‡è®°åŒ…å« 2D 顶点的数组的标志。"
+msgstr "ç”¨äºŽæ ‡è®°åŒ…å« 2D 顶点的数组的标志。"
#: doc/classes/Mesh.xml doc/classes/VisualServer.xml
msgid "Flag used to mark that the array uses 16-bit bones instead of 8-bit."
@@ -43462,7 +43555,6 @@ msgid ""
msgstr "标志用于标记数组使用法线和切线å‘é‡çš„å…«é¢è¡¨ç¤ºæ³•ï¼Œè€Œä¸æ˜¯ç¬›å¡å°”å¼ã€‚"
#: doc/classes/Mesh.xml
-#, fuzzy
msgid ""
"Used to set flags [constant ARRAY_COMPRESS_VERTEX], [constant "
"ARRAY_COMPRESS_NORMAL], [constant ARRAY_COMPRESS_TANGENT], [constant "
@@ -43477,7 +43569,10 @@ msgstr ""
"ARRAY_COMPRESS_NORMAL]ã€[constant ARRAY_COMPRESS_TANGENT]ã€[constant "
"ARRAY_COMPRESS_COLOR]ã€[constant ARRAY_COMPRESS_TEX_UV]ã€[constant "
"ARRAY_COMPRESS_TEX_UV2]ã€[constant ARRAY_COMPRESS_WEIGHTS]ã€[constant "
-"ARRAY_FLAG_USE_OCTAHEDRAL_COMPRESSION] 。"
+"ARRAY_FLAG_USE_OCTAHEDRAL_COMPRESSION] 。\n"
+"[b]注æ„:[/b]因为这个标志会å¯ç”¨ [constant ARRAY_COMPRESS_COLOR],所以顶点颜色"
+"会作为 8 使— ç¬¦å·æ•´æ•°å­˜å‚¨ã€‚这会导致过亮颜色被钳制到 [code]Color(1, 1, 1, 1)[/"
+"code],é™ä½Žé¢œè‰²çš„精度。"
#: doc/classes/Mesh.xml
msgid "Array of vertices."
@@ -43489,7 +43584,7 @@ msgstr "法线数组。"
#: doc/classes/Mesh.xml
msgid "Array of tangents as an array of floats, 4 floats per tangent."
-msgstr "åˆ‡å‘æ•°ç»„。æ¯ä¸€ä¸ªåˆ‡å‘æ•°æ®ç”±å››ä¸ª float å˜é‡æè¿°ã€‚"
+msgstr "åˆ‡çº¿æ•°ç»„ï¼Œæ˜¯æµ®ç‚¹æ•°æ•°ç»„ï¼Œæ¯ 4 个浮点数表示一æ¡åˆ‡çº¿ã€‚"
#: doc/classes/Mesh.xml
msgid "Array of colors."
@@ -43505,7 +43600,7 @@ msgstr "第二套 UV åæ ‡æ•°ç»„。"
#: doc/classes/Mesh.xml
msgid "Array of bone data."
-msgstr "骨骼数æ®çš„æ•°ç»„。"
+msgstr "éª¨éª¼æ•°æ®æ•°ç»„。"
#: doc/classes/Mesh.xml
msgid "Array of weights."
@@ -43517,7 +43612,7 @@ msgstr "索引数组。"
#: doc/classes/MeshDataTool.xml
msgid "Helper tool to access and edit [Mesh] data."
-msgstr "用于帮助编辑和使用 [Mesh] 网格数æ®çš„工具。"
+msgstr "用于访问和编辑 [Mesh] æ•°æ®çš„辅助工具。"
#: doc/classes/MeshDataTool.xml
msgid ""
@@ -43587,7 +43682,7 @@ msgstr "å°†å½“å‰ MeshDataTool 中所有的数æ®å…¨éƒ¨æ¸…除。"
#: doc/classes/MeshDataTool.xml
msgid "Adds a new surface to specified [Mesh] with edited data."
-msgstr "使用编辑åŽçš„æ•°æ®ï¼Œå‘特定的[Mesh]中添加一个新的é¢ã€‚"
+msgstr "使用编辑åŽçš„æ•°æ®ï¼Œå‘指定的 [Mesh] 中添加一个新的表é¢ã€‚"
#: doc/classes/MeshDataTool.xml
msgid ""
@@ -43595,11 +43690,11 @@ msgid ""
"Requires [Mesh] with primitive type [constant Mesh.PRIMITIVE_TRIANGLES]."
msgstr ""
"使用给定 [Mesh] çš„æŒ‡å®šè¡¨é¢æ¥å¡«å…… MeshDataTool 的数æ®ã€‚\n"
-"è¦æ±‚ [Mesh] 具有基本类型 [constant Mesh.PRIMITIVE_TRIANGLES]。"
+"è¦æ±‚ [Mesh] 的图元类型为 [constant Mesh.PRIMITIVE_TRIANGLES]。"
#: doc/classes/MeshDataTool.xml
msgid "Returns the number of edges in this [Mesh]."
-msgstr "返回这个[Mesh]的边数。"
+msgstr "返回这个 [Mesh] 的边数。"
#: doc/classes/MeshDataTool.xml
msgid "Returns array of faces that touch given edge."
@@ -43656,15 +43751,15 @@ msgid ""
"ARRAY_FORMAT_NORMAL] is [code]2[/code].\n"
"See [enum ArrayMesh.ArrayFormat] for a list of format flags."
msgstr ""
-"返回 [Mesh] 的格å¼ï¼Œè¯¥æ ¼å¼æ˜¯ç”± [Mesh] æ ¼å¼æ ‡è¯†ç»„åˆè€Œæˆçš„æ•´æ•°ã€‚ä¾‹å¦‚ï¼Œä¸€ä¸ªåŒæ—¶"
-"包å«é¡¶ç‚¹å’Œæ³•线的网格将返回 [code]3[/code]æ ¼å¼ï¼Œå› ä¸º [constant ArrayMesh."
-"ARRAY_FORMAT_VERTEX] = [code]1[/code],[constant ArrayMesh."
-"ARRAY_FORMAT_NORMAL] = [code]2[/code]。\n"
-"å‚阅 [enum ArrayMesh.ArrayFormat] çš„æ ¼å¼æ ‡è¯†åˆ—表。"
+"返回该 [Mesh] 的格å¼ï¼Œè¯¥æ ¼å¼æ˜¯ç”± [Mesh] æ ¼å¼æ ‡è¯†ç»„åˆè€Œæˆçš„æ•´æ•°ã€‚例如,一个åŒ"
+"时包å«é¡¶ç‚¹å’Œæ³•çº¿çš„ç½‘æ ¼è¿”å›žçš„æ ¼å¼æ˜¯ [code]3[/code],因为 [constant ArrayMesh."
+"ARRAY_FORMAT_VERTEX] 是 [code]1[/code] 而 [constant ArrayMesh."
+"ARRAY_FORMAT_NORMAL] 是 [code]2[/code]。\n"
+"æ ¼å¼æ ‡å¿—åˆ—è¡¨è§ [enum ArrayMesh.ArrayFormat]。"
#: doc/classes/MeshDataTool.xml
msgid "Returns the material assigned to the [Mesh]."
-msgstr "返回分é…ç»™ [Mesh] çš„æè´¨ã€‚"
+msgstr "返回分é…给该 [Mesh] çš„æè´¨ã€‚"
#: doc/classes/MeshDataTool.xml
msgid "Returns the vertex at given index."
@@ -43672,7 +43767,7 @@ msgstr "返回给定索引处的顶点。"
#: doc/classes/MeshDataTool.xml
msgid "Returns the bones of the given vertex."
-msgstr "返回给定顶点的骨架。"
+msgstr "返回给定顶点的骨骼。"
#: doc/classes/MeshDataTool.xml
msgid "Returns the color of the given vertex."
@@ -43700,7 +43795,7 @@ msgstr "返回给定顶点的法线。"
#: doc/classes/MeshDataTool.xml
msgid "Returns the tangent of the given vertex."
-msgstr "返回给定顶点的正切值。"
+msgstr "返回给定顶点的切线。"
#: doc/classes/MeshDataTool.xml
msgid "Returns the UV of the given vertex."
@@ -43732,7 +43827,7 @@ msgstr "设置给定顶点的ä½ç½®ã€‚"
#: doc/classes/MeshDataTool.xml
msgid "Sets the bones of the given vertex."
-msgstr "设置给定顶点的骨架。"
+msgstr "设置给定顶点的骨骼。"
#: doc/classes/MeshDataTool.xml
msgid "Sets the color of the given vertex."
@@ -43805,7 +43900,7 @@ msgid ""
"calculated from the mesh geometry. It's mainly used for testing."
msgstr ""
"这个辅助工具创建 [MeshInstance] å­èŠ‚ç‚¹ï¼Œåœ¨æ¯ä¸ªé¡¶ç‚¹éƒ½æœ‰æ ¹æ®ç½‘格几何形状计算的"
-"辅助线框。其主è¦ç”¨äºŽæµ‹è¯•。"
+"å°å·¥å…·ã€‚其主è¦ç”¨äºŽæµ‹è¯•。"
#: doc/classes/MeshInstance.xml
msgid ""
@@ -43954,7 +44049,7 @@ msgstr ""
#: doc/classes/MeshInstance2D.xml
msgid "The [Mesh] that will be drawn by the [MeshInstance2D]."
-msgstr "[Mesh] 将由 [MeshInstance2D] 绘制。"
+msgstr "该 [MeshInstance2D] 绘制的 [Mesh]。"
#: doc/classes/MeshInstance2D.xml doc/classes/MultiMeshInstance2D.xml
msgid ""
@@ -44009,15 +44104,15 @@ msgstr ""
#: doc/classes/MeshLibrary.xml
msgid "Returns the first item with the given name."
-msgstr "返回第一个指定åç§°çš„ item。"
+msgstr "返回第一个具有指定å称的项。"
#: doc/classes/MeshLibrary.xml
msgid "Returns the list of item IDs in use."
-msgstr "返回正在使用的 item id 列表。"
+msgstr "返回正在使用的项目 ID 列表。"
#: doc/classes/MeshLibrary.xml
msgid "Returns the item's mesh."
-msgstr "返回该 item 的网格模型。"
+msgstr "返回该项目的网格。"
#: doc/classes/MeshLibrary.xml
msgid "Returns the transform applied to the item's mesh."
@@ -44025,7 +44120,7 @@ msgstr "è¿”å›žåº”ç”¨åˆ°é¡¹ç›®ç½‘æ ¼çš„å˜æ¢ã€‚"
#: doc/classes/MeshLibrary.xml
msgid "Returns the item's name."
-msgstr "返回项的å称。"
+msgstr "返回该项的å称。"
#: doc/classes/MeshLibrary.xml
msgid "Returns the item's navigation mesh."
@@ -44082,7 +44177,7 @@ msgstr ""
#: doc/classes/MeshLibrary.xml
msgid "Sets the item's navigation mesh."
-msgstr "设置此项的导航网格。"
+msgstr "设置该项的导航网格。"
#: doc/classes/MeshLibrary.xml
msgid "Sets the transform to apply to the item's navigation mesh."
@@ -44117,7 +44212,7 @@ msgstr ""
#: doc/classes/MeshTexture.xml
msgid "Sets the base texture that the Mesh will use to draw."
-msgstr "设置网格用æ¥ç»˜åˆ¶çš„基础纹ç†ã€‚"
+msgstr "设置该 Mesh 用æ¥ç»˜åˆ¶çš„基础纹ç†ã€‚"
#: doc/classes/MeshTexture.xml
msgid "Sets the size of the image, needed for reference."
@@ -44211,7 +44306,7 @@ msgstr "显示器与设备内部镜片之间的è·ç¦»ï¼Œå•ä½ä¸ºåŽ˜ç±³ã€‚"
#: modules/mobile_vr/doc_classes/MobileVRInterface.xml
msgid "The width of the display in centimeters."
-msgstr "显示器的宽度,以厘米为å•ä½ã€‚"
+msgstr "显示器的宽度,å•ä½ä¸ºåŽ˜ç±³ã€‚"
#: modules/mobile_vr/doc_classes/MobileVRInterface.xml
msgid ""
@@ -44244,7 +44339,7 @@ msgid ""
"performance."
msgstr ""
"过采样设置。由于镜头失真,我们必须以比å±å¹•è‡ªç„¶åˆ†è¾¨çŽ‡æ›´é«˜çš„è´¨é‡æ¸²æŸ“我们的缓冲"
-"区。介于1.5å’Œ2.0之间的值通常å¯ä»¥æä¾›è‰¯å¥½çš„结果,但会牺牲性能。"
+"区。介于 1.5 å’Œ 2.0 之间的值通常å¯ä»¥æä¾›è‰¯å¥½çš„结果,但会牺牲性能。"
#: doc/classes/MultiMesh.xml
msgid "Provides high-performance mesh instancing."
@@ -44281,7 +44376,7 @@ msgstr ""
#: doc/classes/MultiMesh.xml
msgid "Gets a specific instance's color."
-msgstr "获å–一个特定实例的颜色。"
+msgstr "获å–特定实例的颜色。"
#: doc/classes/MultiMesh.xml
msgid "Returns the custom data that has been set for a specific instance."
@@ -44289,7 +44384,7 @@ msgstr "返回已ç»ä¸ºç‰¹å®šå®žä¾‹è®¾ç½®çš„自定义数æ®ã€‚"
#: doc/classes/MultiMesh.xml
msgid "Returns the [Transform] of a specific instance."
-msgstr "返回一个特定实例的 [Transform]。"
+msgstr "返回特定实例的 [Transform]。"
#: doc/classes/MultiMesh.xml
msgid "Returns the [Transform2D] of a specific instance."
@@ -44423,7 +44518,7 @@ msgid ""
"Limits the number of instances drawn, -1 draws all instances. Changing this "
"does not change the sizes of the buffers."
msgstr ""
-"é™åˆ¶ç»˜åˆ¶çš„实例数é‡ï¼Œ-1会绘制所有的实例。改å˜è¿™ä¸€ç‚¹å¹¶ä¸æ”¹å˜ç¼“冲区的大å°ã€‚"
+"é™åˆ¶ç»˜åˆ¶çš„实例数é‡ï¼Œ-1 会绘制所有的实例。改å˜è¿™ä¸€ç‚¹å¹¶ä¸æ”¹å˜ç¼“冲区的大å°ã€‚"
#: doc/classes/MultiMesh.xml
msgid "Use this when using 2D transforms."
@@ -44501,7 +44596,7 @@ msgid ""
msgstr ""
"[MultiMeshInstance] 是特有的节点,用于基于 [MultiMesh] 资æºçš„ "
"[GeometryInstance] 的实例。\n"
-"这对于优化给定网格的大é‡å®žä¾‹çš„æ¸²æŸ“是éžå¸¸æœ‰ç”¨çš„(例如,森林中的树木或è‰ä¸›ï¼‰ã€‚"
+"这对于优化给定网格的大é‡å®žä¾‹çš„æ¸²æŸ“是éžå¸¸æœ‰ç”¨çš„(例如森林中的树木或è‰ä¸›ï¼‰ã€‚"
#: doc/classes/MultiMeshInstance.xml
msgid ""
@@ -45452,6 +45547,7 @@ msgid "3D agent used in navigation for collision avoidance."
msgstr "在导航中用于防撞的 3D 代ç†ã€‚"
#: doc/classes/NavigationAgent.xml
+#, fuzzy
msgid ""
"3D agent that is used in navigation to reach a location while avoiding "
"static and dynamic obstacles. The dynamic obstacles are avoided using RVO "
@@ -45465,7 +45561,10 @@ msgid ""
"use the [method get_next_location] function once every physics frame to "
"update the internal path logic of the NavigationAgent. The returned vector "
"position from this function should be used as the next movement position for "
-"the agent's parent Node."
+"the agent's parent Node.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues."
msgstr ""
"导航中使用的 3D 代ç†ï¼Œå¯ä»¥åœ¨å‰å¾€æŸä¸ªä½ç½®æ—¶èº²é¿é™æ€å’ŒåЍæ€éšœç¢ç‰©ã€‚躲é¿åЍæ€éšœç¢"
"物使用的是 RVO(Reciprocal Velocity Obstacles,相对速度障ç¢ç‰©ï¼‰é˜²æ’žç®—法。代ç†"
@@ -45768,6 +45867,7 @@ msgid "2D agent used in navigation for collision avoidance."
msgstr "在导航中用于防撞的 2D 代ç†ã€‚"
#: doc/classes/NavigationAgent2D.xml
+#, fuzzy
msgid ""
"2D agent that is used in navigation to reach a location while avoiding "
"static and dynamic obstacles. The dynamic obstacles are avoided using RVO "
@@ -45781,7 +45881,10 @@ msgid ""
"use the [method get_next_location] function once every physics frame to "
"update the internal path logic of the NavigationAgent. The returned vector "
"position from this function should be used as the next movement position for "
-"the agent's parent Node."
+"the agent's parent Node.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues."
msgstr ""
"导航中使用的 2D 代ç†ï¼Œå¯ä»¥åœ¨å‰å¾€æŸä¸ªä½ç½®æ—¶èº²é¿é™æ€å’ŒåЍæ€éšœç¢ç‰©ã€‚躲é¿åЍæ€éšœç¢"
"物使用的是 RVO(Reciprocal Velocity Obstacles,相对速度障ç¢ç‰©ï¼‰é˜²æ’žç®—法。代ç†"
@@ -46660,6 +46763,7 @@ msgid "Server interface for low-level 3D navigation access."
msgstr "访问底层 3D 导航的æœåŠ¡å™¨æŽ¥å£ã€‚"
#: doc/classes/NavigationServer.xml
+#, fuzzy
msgid ""
"NavigationServer is the server responsible for all 3D navigation. It handles "
"several objects, namely maps, regions and agents.\n"
@@ -46680,6 +46784,9 @@ msgid ""
"modified velocity as-is might lead to pushing and agent outside of a "
"navigable area. This is a limitation of the collision avoidance system, any "
"more complex situation may require the use of the physics engine.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues.\n"
"This server keeps tracks of any call and executes them during the sync "
"phase. This means that you can request any change to the map, using any "
"thread, without worrying."
@@ -46899,19 +47006,19 @@ msgid ""
"code] is specified, the client will also listen to the given port; this is "
"useful for some NAT traversal techniques."
msgstr ""
-"创建客户端,使用指定的[code]端å£[/code]连接到[code]地å€[/code]çš„æœåŠ¡å™¨ä¸Šã€‚ç»™"
-"定的地å€éœ€è¦æ˜¯ä¸€ä¸ªå®Œå…¨åˆæ ¼çš„域å(例如,[code]\"www.example.com\"[/code])或"
-"一个IPv4或IPv6æ ¼å¼çš„IP地å€ï¼ˆä¾‹å¦‚,[code]\"192.168.1.1\"[/code])。"
-"[code]port[/code]是æœåŠ¡å™¨æ‰€ç›‘å¬çš„端å£ã€‚[code]in_bandwidth[/code]å’Œ"
-"[code]out_bandwidth[/code]傿•°å¯ç”¨äºŽå°†ä¼ å…¥å’Œä¼ å‡ºçš„带宽é™åˆ¶åœ¨ç»™å®šçš„字节数/秒。"
-"默认的0æ„å‘³ç€æ— é™çš„带宽。请注æ„,ENet会在对等体之间连接的特定一侧战略性地丢弃"
-"æ•°æ®åŒ…,以确ä¿å¯¹ç­‰ä½“的带宽ä¸è¢«æ·¹æ²¡ã€‚另宽傿•°ä¹Ÿå†³å®šäº†è¿žæŽ¥çš„窗å£å¤§å°ï¼Œå®ƒé™åˆ¶äº†"
-"在任何给定时间内å¯èƒ½æ­£åœ¨ä¼ è¾“çš„å¯é æ•°æ®åŒ…的数é‡ã€‚如果创建了一个客户端,返回"
-"[constant OK];如果这个NetworkedMultiplayerENetå®žä¾‹å·²ç»æœ‰ä¸€ä¸ªå¼€æ”¾çš„连接(在这"
-"ç§æƒ…况下,你需è¦å…ˆè°ƒç”¨[method close_connection]),返回[constant "
-"ERR_CANT_CREATE];如果ä¸èƒ½åˆ›å»ºå®¢æˆ·ç«¯ï¼Œè¿”回[constant ERR_CANT_CREATE]。如果指"
-"定了[code]client_port[/code],客户端也将监å¬ç»™å®šçš„端å£ï¼›è¿™å¯¹ä¸€äº›NAT穿越技术很"
-"有用。"
+"创建客户端,使用指定的 [code]port[/code]连接到[code]address[/code]çš„æœåС噍"
+"上。给定的地å€éœ€è¦æ˜¯ä¸€ä¸ªå®Œå…¨åˆæ ¼çš„域å(例如 [code]\"www.example.com\"[/"
+"code])或一个 IPv4 或 IPv6 æ ¼å¼çš„ IP 地å€ï¼ˆä¾‹å¦‚ [code]\"192.168.1.1\"[/"
+"code])。[code]port[/code] 是æœåŠ¡å™¨æ‰€ç›‘å¬çš„端å£ã€‚[code]in_bandwidth[/code] "
+"å’Œ [code]out_bandwidth[/code] 傿•°å¯ç”¨äºŽå°†ä¼ å…¥å’Œä¼ å‡ºçš„带宽é™åˆ¶åœ¨ç»™å®šçš„字节数/"
+"秒。默认的 0 æ„å‘³ç€æ— é™çš„带宽。请注æ„,ENet 会在对等体之间连接的特定一侧战略"
+"性地丢弃数æ®åŒ…,以确ä¿å¯¹ç­‰ä½“的带宽ä¸è¢«æ·¹æ²¡ã€‚另宽傿•°ä¹Ÿå†³å®šäº†è¿žæŽ¥çš„窗å£å¤§å°ï¼Œ"
+"它é™åˆ¶äº†åœ¨ä»»ä½•给定时间内å¯èƒ½æ­£åœ¨ä¼ è¾“çš„å¯é æ•°æ®åŒ…的数é‡ã€‚如果创建了一个客户"
+"端,返回 [constant OK];如果这个 NetworkedMultiplayerENet å®žä¾‹å·²ç»æœ‰ä¸€ä¸ªå¼€æ”¾"
+"çš„è¿žæŽ¥ï¼ˆåœ¨è¿™ç§æƒ…况下,你需è¦å…ˆè°ƒç”¨ [method close_connection]),返回 "
+"[constant ERR_CANT_CREATE];如果ä¸èƒ½åˆ›å»ºå®¢æˆ·ç«¯ï¼Œåˆ™è¿”回 [constant "
+"ERR_CANT_CREATE]。如果指定了 [code]client_port[/code],客户端也将监å¬ç»™å®šçš„端"
+"å£ï¼›è¿™å¯¹ä¸€äº› NAT 穿越技术很有用。"
#: modules/enet/doc_classes/NetworkedMultiplayerENet.xml
msgid ""
@@ -46930,16 +47037,16 @@ msgid ""
"case you need to call [method close_connection] first) or [constant "
"ERR_CANT_CREATE] if the server could not be created."
msgstr ""
-"创建æœåŠ¡å™¨ï¼Œé€šè¿‡[code]port[/code]监å¬è¿žæŽ¥ã€‚该端å£éœ€è¦æ˜¯ä¸€ä¸ªå¯ç”¨çš„ã€æœªä½¿ç”¨çš„端"
-"å£ï¼Œåœ¨0到65535之间。注æ„,低于1024çš„ç«¯å£æ˜¯ç‰¹æƒç«¯å£ï¼Œæ ¹æ®å¹³å°çš„ä¸åŒå¯èƒ½éœ€è¦æ"
-"高æƒé™ã€‚è¦æ”¹å˜æœåŠ¡å™¨ç›‘å¬çš„æŽ¥å£ï¼Œè¯·ä½¿ç”¨[method set_bind_ip]。默认IP是通é…符"
-"[code]\"*\"[/code]ï¼Œå®ƒç›‘å¬æ‰€æœ‰å¯ç”¨çš„æŽ¥å£ã€‚[code]max_clients[/code]是å…è®¸åŒæ—¶"
-"进行的最大客户数,å¯ä»¥ä½¿ç”¨ä»»ä½•数字,最高å¯è¾¾4095,尽管å¯å®žçŽ°çš„åŒæ—¶è¿›è¡Œçš„客户"
-"æ•°å¯èƒ½è¦ä½Žå¾—多,并且å–å†³äºŽåº”ç”¨ã€‚å…³äºŽå¸¦å®½å‚æ•°çš„其他细节,è§[method "
-"create_client]。如果æœåŠ¡å™¨è¢«åˆ›å»ºï¼Œè¿”å›ž[constant OK];如果这个"
-"NetworkedMultiplayerENetå®žä¾‹å·²ç»æœ‰ä¸€ä¸ªå¼€æ”¾çš„è¿žæŽ¥ï¼ˆåœ¨è¿™ç§æƒ…况下,你需è¦å…ˆè°ƒç”¨"
-"[method close_connection]),返回[constant ERR_CANT_CREATE];如果æœåС噍ä¸èƒ½è¢«"
-"创建,返回[constant ERR_CANT_CREATE]。"
+"创建æœåŠ¡å™¨ï¼Œé€šè¿‡ [code]port[/code] 监å¬è¿žæŽ¥ã€‚该端å£éœ€è¦æ˜¯ä¸€ä¸ªå¯ç”¨çš„ã€æœªä½¿ç”¨çš„"
+"端å£ï¼Œåœ¨ 0 到 65535 之间。注æ„,低于 1024 çš„ç«¯å£æ˜¯ç‰¹æƒç«¯å£ï¼Œæ ¹æ®å¹³å°çš„ä¸åŒå¯"
+"èƒ½éœ€è¦æé«˜æƒé™ã€‚è¦æ”¹å˜æœåŠ¡å™¨ç›‘å¬çš„æŽ¥å£ï¼Œè¯·ä½¿ç”¨ [method set_bind_ip]。默认 IP "
+"是通é…符 [code]\"*\"[/code]ï¼Œä¼šç›‘å¬æ‰€æœ‰å¯ç”¨çš„æŽ¥å£ã€‚[code]max_clients[/code] "
+"是å…è®¸åŒæ—¶è¿›è¡Œçš„æœ€å¤§å®¢æˆ·æ•°ï¼Œå¯ä»¥ä½¿ç”¨ä»»ä½•数字,最高å¯è¾¾ 4095,尽管å¯å®žçŽ°çš„åŒæ—¶"
+"进行的客户数å¯èƒ½è¦ä½Žå¾—多,并且å–å†³äºŽåº”ç”¨ã€‚å…³äºŽå¸¦å®½å‚æ•°çš„å…¶ä»–ç»†èŠ‚ï¼Œè§ [method "
+"create_client]。如果æœåŠ¡å™¨è¢«åˆ›å»ºï¼Œåˆ™è¿”å›ž [constant OK];如果这个 "
+"NetworkedMultiplayerENet å®žä¾‹å·²ç»æœ‰ä¸€ä¸ªå¼€æ”¾çš„è¿žæŽ¥ï¼ˆåœ¨è¿™ç§æƒ…况下,你需è¦å…ˆè°ƒ"
+"用 [method close_connection]),则返回 [constant ERR_CANT_CREATE];如果æœåС噍"
+"ä¸èƒ½è¢«åˆ›å»ºï¼Œåˆ™è¿”回 [constant ERR_CANT_CREATE]。"
#: modules/enet/doc_classes/NetworkedMultiplayerENet.xml
msgid ""
@@ -50429,7 +50536,7 @@ msgstr ""
"[OccluderShape] 是 [Occluder] 节点所使用的资æºï¼Œç”¨äºŽå‡ ä½•鮿Œ¡å‰”除。\n"
"该多边形必须是凸多边形。多边形顶点的创建与删除å¯ä»¥åœ¨ç¼–辑器的检查器中进行,也"
"å¯ä»¥é€šè¿‡è°ƒç”¨ [code]set_polygon_points[/code] 实现。æ¯ä¸€æ¡è¾¹çš„顶点都å¯ä»¥é€šè¿‡åœ¨"
-"ç¼–è¾‘å™¨è§†çª—ä¸­æ‹–æ‹½å¥æŸ„设置。\n"
+"编辑器视窗中拖拽手柄设置。\n"
"å¦å¤–,æ¯ä¸€ä¸ªå¤šè¾¹å½¢é®æŒ¡å™¨éƒ½å¯ä»¥æ”¯æŒå•个空洞。如果你在编辑器的检查器中为空洞添"
"加至少三个顶点,就å¯ä»¥åœ¨ç¼–è¾‘å™¨è§†çª—ä¸­æ‹–æ‹½ç©ºæ´žè¾¹ç¼˜é¡¶ç‚¹çš„å¥æŸ„。\n"
"一般而言,多边形以åŠç©ºæ´žçš„边数越少,è¿è¡Œæ—¶ç³»ç»Ÿçš„处ç†é€Ÿåº¦å°±è¶Šå¿«ï¼Œæ‰€ä»¥åœ¨å¤§å¤šæ•°"
@@ -50525,11 +50632,14 @@ msgstr ""
"光的衰å‡ï¼ˆä¸‹é™ï¼‰æ›²çº¿ã€‚在[b]检查器[/b]中,通过å³é”®ç‚¹å‡»æ›²çº¿ï¼Œå¯ä»¥èŽ·å¾—è®¸å¤šé¢„è®¾ã€‚"
#: doc/classes/OmniLight.xml
+#, fuzzy
msgid ""
"The light's radius. Note that the effectively lit area may appear to be "
"smaller depending on the [member omni_attenuation] in use. No matter the "
"[member omni_attenuation] in use, the light will never reach anything "
-"outside this radius."
+"outside this radius.\n"
+"[b]Note:[/b] [member omni_range] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
"光的åŠå¾„。请注æ„,有效的照明区域å¯èƒ½çœ‹èµ·æ¥æ›´å°ï¼Œè¿™å–决于使用的 [member "
"omni_attenuation]ã€‚æ— è®ºä½¿ç”¨ä½•ç§ [member omni_attenuation],光线都ä¸ä¼šåˆ°è¾¾è¿™ä¸ª"
@@ -51187,13 +51297,14 @@ msgid "Returns the audio driver name for the given index."
msgstr "返回给定索引的音频驱动程åºå称。"
#: doc/classes/OS.xml
+#, fuzzy
msgid ""
"Returns the [i]global[/i] cache data directory according to the operating "
-"system's standards. On desktop platforms, this path can be overridden by "
-"setting the [code]XDG_CACHE_HOME[/code] environment variable before starting "
-"the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in "
-"Godot projects[/url] in the documentation for more information. See also "
-"[method get_config_dir] and [method get_data_dir].\n"
+"system's standards. On Linux, this path can be overridden by setting the "
+"[code]XDG_CACHE_HOME[/code] environment variable before starting the "
+"project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot "
+"projects[/url] in the documentation for more information. See also [method "
+"get_config_dir] and [method get_data_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -51251,13 +51362,14 @@ msgstr ""
"[/codeblock]"
#: doc/classes/OS.xml
+#, fuzzy
msgid ""
"Returns the [i]global[/i] user configuration directory according to the "
-"operating system's standards. On desktop platforms, this path can be "
-"overridden by setting the [code]XDG_CONFIG_HOME[/code] environment variable "
-"before starting the project. See [url=$DOCS_URL/tutorials/io/data_paths."
-"html]File paths in Godot projects[/url] in the documentation for more "
-"information. See also [method get_cache_dir] and [method get_data_dir].\n"
+"operating system's standards. On Linux, this path can be overridden by "
+"setting the [code]XDG_CONFIG_HOME[/code] environment variable before "
+"starting the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File "
+"paths in Godot projects[/url] in the documentation for more information. See "
+"also [method get_cache_dir] and [method get_data_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -51286,13 +51398,14 @@ msgid ""
msgstr "返回当å‰ä½¿ç”¨çš„视频驱动程åºï¼Œä½¿ç”¨[enum VideoDriver]中的一个值。"
#: doc/classes/OS.xml
+#, fuzzy
msgid ""
"Returns the [i]global[/i] user data directory according to the operating "
-"system's standards. On desktop platforms, this path can be overridden by "
-"setting the [code]XDG_DATA_HOME[/code] environment variable before starting "
-"the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in "
-"Godot projects[/url] in the documentation for more information. See also "
-"[method get_cache_dir] and [method get_config_dir].\n"
+"system's standards. On Linux, this path can be overridden by setting the "
+"[code]XDG_DATA_HOME[/code] environment variable before starting the project. "
+"See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot "
+"projects[/url] in the documentation for more information. See also [method "
+"get_cache_dir] and [method get_config_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -53747,6 +53860,17 @@ msgid "Particle systems (2D)"
msgstr "ç²’å­ç³»ç»Ÿï¼ˆ2D)"
#: doc/classes/Particles2D.xml
+#, fuzzy
+msgid "2D Particles Demo"
+msgstr "2D å¹³å°è·³è·ƒæ¼”示"
+
+#: doc/classes/Particles2D.xml
+msgid ""
+"2D Dodge The Creeps Demo (uses GPUParticles2D for the trail behind the "
+"player)"
+msgstr ""
+
+#: doc/classes/Particles2D.xml
msgid "Returns a rectangle containing the positions of all existing particles."
msgstr "è¿”å›žä¸€ä¸ªåŒ…å«æ‰€æœ‰çŽ°å­˜ç²’å­ä½ç½®çš„矩形。"
@@ -58864,7 +58988,7 @@ msgid ""
"visual size by using the gizmo in the 2D editor while the node is selected."
msgstr ""
"用于编辑的通用 2D ä½ç½®æç¤ºã€‚它就åƒä¸€ä¸ªæ™®é€šçš„ [Node2D],但它在 2D 编辑器中始终"
-"显示为一个å字。选择节点时,å¯ä»¥ä½¿ç”¨ 2D ç¼–è¾‘å™¨ä¸­çš„å°æŽ§ä»¶æ¥è®¾ç½®å字的视觉大"
+"显示为一个å字。选中节点时,å¯ä»¥ä½¿ç”¨ 2D 编辑器中的å°å·¥å…·æ¥è®¾ç½®å字的视觉大"
"å°ã€‚"
#: doc/classes/Position3D.xml
@@ -61824,7 +61948,7 @@ msgid ""
"Physics2DServer.AREA_PARAM_GRAVITY, 98)\n"
"[/codeblock]"
msgstr ""
-"2D 中默认的é‡åŠ›å¼ºåº¦ï¼ˆå•ä½ï¼šæ¯ç§’平方åƒç´ ï¼‰ã€‚\n"
+"2D 中默认的é‡åŠ›å¼ºåº¦ï¼ˆå•ä½ä¸ºåƒç´ æ¯ç§’的平方)。\n"
"[b]注æ„:[/b]这个属性åªåœ¨é¡¹ç›®å¯åŠ¨æ—¶è¢«è¯»å–。è¦åœ¨è¿è¡Œæ—¶æ”¹å˜é»˜è®¤çš„é‡åŠ›ï¼Œè¯·ä½¿ç”¨ä»¥"
"下代ç ç¤ºä¾‹ï¼š\n"
"[codeblock]\n"
@@ -61980,7 +62104,7 @@ msgid ""
"PhysicsServer.AREA_PARAM_GRAVITY, 9.8)\n"
"[/codeblock]"
msgstr ""
-"3D 中的默认é‡åŠ›å¼ºåº¦ï¼Œå•ä½ï¼šç±³/秒平方。\n"
+"3D 中的默认é‡åŠ›å¼ºåº¦ï¼ˆå•ä½ä¸ºç±³æ¯ç§’的平方)。\n"
"[b]注æ„:[/b]该属性仅在项目å¯åŠ¨æ—¶è¯»å–。è¦åœ¨è¿è¡Œæ—¶æ›´æ”¹é»˜è®¤é‡åŠ›ï¼Œè¯·ä½¿ç”¨ä»¥ä¸‹ä»£ç "
"示例:\n"
"[codeblock]\n"
@@ -63080,17 +63204,25 @@ msgstr ""
"的值通常会给出最好的结果。å¦è§ [member rendering/quality/filters/use_fxaa]。"
#: doc/classes/ProjectSettings.xml
+#, fuzzy
msgid ""
"If [code]true[/code], uses a fast post-processing filter to make banding "
-"significantly less visible. In some cases, debanding may introduce a "
-"slightly noticeable dithering pattern. It's recommended to enable debanding "
-"only when actually needed since the dithering pattern will make lossless-"
-"compressed screenshots larger.\n"
+"significantly less visible in 3D. 2D rendering is [i]not[/i] affected by "
+"debanding unless the [member Environment.background_mode] is [constant "
+"Environment.BG_CANVAS]. In this case, [member rendering/quality/"
+"intended_usage/framebuffer_allocation] must also be set to [b]3D[/b].\n"
+"In some cases, debanding may introduce a slightly noticeable dithering "
+"pattern. It's recommended to enable debanding only when actually needed "
+"since the dithering pattern will make lossless-compressed screenshots "
+"larger.\n"
"[b]Note:[/b] Only available on the GLES3 backend. [member rendering/quality/"
"depth/hdr] must also be [code]true[/code] for debanding to be effective.\n"
"[b]Note:[/b] There are known issues with debanding breaking rendering on "
"mobile platforms. Due to this, it is recommended to leave this option "
-"disabled when targeting mobile platforms."
+"disabled when targeting mobile platforms.\n"
+"[b]Note:[/b] This property is only read when the project starts. To set "
+"debanding at run-time, set [member Viewport.debanding] on the root "
+"[Viewport] instead."
msgstr ""
"如果为 [code]true[/code],则使用快速åŽå¤„ç†è¿‡æ»¤å™¨ä½¿æ¡å¸¦æ˜Žæ˜¾ä¸é‚£ä¹ˆæ˜Žæ˜¾ã€‚在æŸäº›"
"情况下,去带å¯èƒ½ä¼šå¼•å…¥ç¨å¾®æ˜Žæ˜¾çš„æŠ–动模å¼ã€‚å»ºè®®ä»…åœ¨å®žé™…éœ€è¦æ—¶å¯ç”¨åŽ»æ¡å¸¦ï¼Œå› ä¸º"
@@ -65231,33 +65363,45 @@ msgstr "返回此对象是å¦åˆ†é…了有效的æœç´¢æ¨¡å¼ã€‚"
#: modules/regex/doc_classes/RegEx.xml
msgid ""
"Searches the text for the compiled pattern. Returns a [RegExMatch] container "
-"of the first matching result if found, otherwise [code]null[/code]. The "
-"region to search within can be specified without modifying where the start "
-"and end anchor would be."
+"of the first matching result if found, otherwise [code]null[/code].\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
-"在文本中æœç´¢ç¼–译åŽçš„æ¨¡å¼ã€‚如果找到,返回第一个匹é…结果的 [RegExMatch] 容器,"
-"å¦åˆ™è¿”回 [code]null[/code]。å¯ä»¥æŒ‡å®šè¦æœç´¢çš„区域,而ä¸éœ€è¦ä¿®æ”¹å¼€å§‹å’Œç»“æŸé”šç‚¹"
-"çš„ä½ç½®ã€‚"
#: modules/regex/doc_classes/RegEx.xml
msgid ""
"Searches the text for the compiled pattern. Returns an array of [RegExMatch] "
"containers for each non-overlapping result. If no results were found, an "
-"empty array is returned instead. The region to search within can be "
-"specified without modifying where the start and end anchor would be."
+"empty array is returned instead.\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
-"在文本中æœç´¢ç¼–译过的模å¼ã€‚为æ¯ä¸ªä¸é‡å çš„结果返回一个 [RegExMatch] 容器数组。"
-"如果没有å‘现任何结果,则返回一个空数组。å¯ä»¥æŒ‡å®šè¦æœç´¢çš„区域,而ä¸éœ€è¦ä¿®æ”¹å¼€"
-"始和结æŸé”šç‚¹çš„ä½ç½®ã€‚"
#: modules/regex/doc_classes/RegEx.xml
+#, fuzzy
msgid ""
"Searches the text for the compiled pattern and replaces it with the "
"specified string. Escapes and backreferences such as [code]$1[/code] and "
"[code]$name[/code] are expanded and resolved. By default, only the first "
"instance is replaced, but it can be changed for all instances (global "
-"replacement). The region to search within can be specified without modifying "
-"where the start and end anchor would be."
+"replacement).\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
"æœç´¢æ–‡æœ¬ä¸­çš„编译模å¼ï¼Œå¹¶å°†å…¶æ›¿æ¢ä¸ºæŒ‡å®šçš„字符串。诸如 [code]$1[/code] å’Œ "
"[code]$name[/code] 等转义和åå‘å¼•ç”¨ä¼šè¢«å±•å¼€å’Œè§£å†³ã€‚é»˜è®¤æƒ…å†µä¸‹ï¼Œåªæœ‰ç¬¬ä¸€ä¸ªå®žä¾‹"
@@ -67799,7 +67943,6 @@ msgstr ""
"以é¿å…混淆。有关 portal 模å¼çš„完整说明,请å‚阅 [CullInstance]。"
#: doc/classes/RoomManager.xml
-#, fuzzy
msgid ""
"Switches the portal culling system on and off.\n"
"It is important to note that when portal culling is active, it is "
@@ -67814,11 +67957,13 @@ msgid ""
"[VisualInstance] are expected to show when the system is active."
msgstr ""
"打开和关闭入å£å‰”除系统。\n"
-"éœ€è¦æ³¨æ„的是,当入å£å‰”é™¤å¤„äºŽæ´»åŠ¨çŠ¶æ€æ—¶ï¼Œå®ƒè´Ÿè´£[b]所有[/b] 3d 剔除。æŸäº›ç¼–辑器"
-"功能å¯èƒ½æ›´éš¾ä½¿ç”¨ï¼Œå› æ­¤åˆ‡æ¢æ´»åŠ¨æ ‡å¿—æ—¨åœ¨ç¡®ä¿æ‚¨çš„ [Room] / [Portal] 布局在编辑器"
-"中工作。\n"
+"éœ€è¦æ³¨æ„的是,当入å£å‰”é™¤å¤„äºŽæ´»åŠ¨çŠ¶æ€æ—¶ï¼Œå®ƒè´Ÿè´£è¿›è¡Œ[b]所有[/b] 3d 剔除。活动状"
+"æ€ä¸‹ï¼Œå¯èƒ½æ— æ³•使用编辑器中的部分å¯è§†åŒ–è°ƒè¯•å·¥å…·ï¼Œå› æ­¤æ´»åŠ¨æ ‡å¿—çš„å¼€å…³çš„ç›®çš„åªæ˜¯"
+"ç¡®ä¿æ‚¨çš„ [Room] / [Portal] 布局在编辑器中能够正常工作。\n"
"当 [code]room graph[/code] 被å¸è½½ï¼ˆç©ºé—´å°šæœªè½¬æ¢ï¼‰æ—¶ï¼Œåˆ‡æ¢åˆ° [code]active[/"
-"code] å°†ä¸èµ·ä½œç”¨ã€‚"
+"code] å°†ä¸èµ·ä½œç”¨ã€‚\n"
+"[b]注æ„:[/b]出于效率的考虑,入å£ç³»ç»Ÿåœ¨è®¾è®¡æ—¶åªè€ƒè™‘了核心å¯è§†å¯¹è±¡ç±»åž‹ã€‚具体æ¥"
+"è¯´ï¼Œå°±æ˜¯åªæœ‰ç»§æ‰¿è‡ª [VisualInstance] 的节点æ‰ä¼šåœ¨è¯¥ç³»ç»Ÿå¯ç”¨æ—¶æ˜¾ç¤ºã€‚"
#: doc/classes/RoomManager.xml
msgid ""
@@ -67999,7 +68144,7 @@ msgstr ""
#: doc/classes/RoomManager.xml
msgid "Shows the [Portal] margins when the portal gizmo is used in the editor."
-msgstr "当在编辑器中使用入å£å·¥å…·æ—¶ï¼Œæ˜¾ç¤º [Portal] 的边界。"
+msgstr "当在编辑器中使用入å£å°å·¥å…·æ—¶ï¼Œæ˜¾ç¤º [Portal] 的边界。"
#: doc/classes/RoomManager.xml
msgid ""
@@ -68834,8 +68979,12 @@ msgid "Call a group immediately (calls are normally made on idle)."
msgstr "å¯¹ç»„è¿›è¡Œè°ƒç”¨æ—¶ï¼Œç«‹å³æ‰§è¡Œï¼ˆæ­£å¸¸æƒ…况下是在空闲时调用的)。"
#: doc/classes/SceneTree.xml
-msgid "Call a group only once even if the call is executed many times."
-msgstr "对组进行调用时,å³ä¾¿æ‰§è¡Œäº†å¤šæ¬¡è°ƒç”¨ä¹Ÿåªè°ƒç”¨ä¸€æ¬¡ã€‚"
+msgid ""
+"Call a group only once even if the call is executed many times.\n"
+"[b]Note:[/b] Arguments are not taken into account when deciding whether the "
+"call is unique or not. Therefore when the same method is called with "
+"different arguments, only the first call will be performed."
+msgstr ""
#: doc/classes/SceneTree.xml
msgid "No stretching."
@@ -68928,7 +69077,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"
@@ -69065,6 +69213,16 @@ msgstr ""
" tween.tween_property(sprite, \"position\", Vector2(0, 0), 1)\n"
"[/codeblock]\n"
"上é¢çš„示例中,该节点的所有å­èŠ‚ç‚¹éƒ½ä¼šä¾æ¬¡è¢«ç§»åŠ¨åˆ° (0, 0)。\n"
+"你应该é¿å…在对象的åŒä¸€ä¸ªå±žæ€§ä¸Šä½¿ç”¨å¤šä¸ª [SceneTreeTween]。如果对æŸä¸ªå±žæ€§åŒæ—¶è¿›"
+"行两个或者更多的补间动画,会优先使用最åŽåˆ›å»ºçš„那个设置最终的值。如果你想è¦ä¸­"
+"æ–­å¹¶é‡å¯åŠ¨ç”»ï¼Œè¯·è€ƒè™‘å°†è¯¥ [SceneTreeTween] 赋给å˜é‡ï¼š\n"
+"[codeblock]\n"
+"var tween\n"
+"func animate():\n"
+" if tween:\n"
+" tween.kill() # 终止之å‰çš„补间动画。\n"
+" tween = create_tween()\n"
+"[/codeblock]\n"
"一些 [Tweener] 会用到过渡和缓动。å‰è€…æŽ¥å— [enum Tween.TransitionType] 常é‡ï¼Œ"
"指的是如何处ç†è¯¥åŠ¨ç”»çš„æ—¶é—´ï¼ˆç¤ºä¾‹è§ [url=https://easings.net/]easings.net[/"
"url])。第二个接å—的是 [enum Tween.EaseType] 常é‡ï¼ŒæŽ§åˆ¶ [code]trans_type[/"
@@ -69074,7 +69232,10 @@ msgstr ""
"[url=https://raw.githubusercontent.com/godotengine/godot-docs/master/img/"
"tween_cheatsheet.png]补间缓动与过渡类型速查表[/url]\n"
"[b]注æ„:[/b]所有 [SceneTreeTween] 都默认会自动å¯åŠ¨ã€‚å¦‚æžœè¦é˜»æ­¢æŸä¸ª "
-"[SceneTreeTween] 自动å¯åŠ¨ï¼Œä½ å¯ä»¥åœ¨åˆ›å»ºåŽç«‹å³è°ƒç”¨ [method stop]。"
+"[SceneTreeTween] 自动å¯åŠ¨ï¼Œä½ å¯ä»¥åœ¨åˆ›å»ºåŽç«‹å³è°ƒç”¨ [method stop]。\n"
+"[b]注æ„:[/b][SceneTreeTween] çš„å¤„ç†æ—¶æœºåœ¨å½“å‰å¸§çš„æ‰€æœ‰èŠ‚ç‚¹ä¹‹åŽï¼Œå³åœ¨ [method "
+"Node._process] 或 [method Node._physics_process] 之åŽï¼ˆå–决于 [enum Tween."
+"TweenProcessMode])。"
#: doc/classes/SceneTreeTween.xml
msgid ""
@@ -70806,9 +70967,9 @@ msgid ""
"the optional [code]attachment_path[/code] can define a [Spatial] the pinned "
"vertex will be attached to."
msgstr ""
-"设置表é¢é¡¶ç‚¹çš„固定状æ€ã€‚当设置为 [code]true[/code] 时,å¯é€‰çš„"
-"[code]attachment_path[/code]å¯ä»¥å®šä¹‰ä¸€ä¸ªç©ºé—´[Spatial],被固定的顶点将连接到这"
-"个空间。"
+"设置表é¢é¡¶ç‚¹çš„固定状æ€ã€‚当设置为 [code]true[/code] 时,å¯é€‰çš„ "
+"[code]attachment_path[/code] å¯ä»¥å®šä¹‰ä¸€ä¸ª [Spatial],被固定的顶点将连接到这个"
+"节点。"
#: doc/classes/SoftBody.xml
msgid ""
@@ -71114,7 +71275,7 @@ msgid ""
"editor context and it has a valid gizmo."
msgstr ""
"设置节点是å¦é€šçŸ¥å…¶å…¨å±€å’Œå±€éƒ¨å˜æ¢çš„å˜åŒ–。[Spatial] 默认情况下ä¸ä¼šä¼ æ’­ï¼Œé™¤éžæ˜¯"
-"在编辑器上下文中,并且它有一个有效的控制器。"
+"在编辑器上下文中,并且它有一个有效的å°å·¥å…·ã€‚"
#: doc/classes/Spatial.xml
msgid ""
@@ -71219,12 +71380,15 @@ msgid ""
msgstr "æ—‹è½¬éƒ¨åˆ†å±€éƒ¨å˜æ¢ä¸ºåº¦ï¼ŒæŒ‰ YXZ-Euler è§’æ ¼å¼æŒ‡å®šï¼ˆX è§’ã€Y è§’ã€Z 角)。"
#: doc/classes/Spatial.xml
+#, fuzzy
msgid ""
"Scale part of the local transformation.\n"
"[b]Note:[/b] Mixed negative scales in 3D are not decomposable from the "
"transformation matrix. Due to the way scale is represented with "
"transformation matrices in Godot, the scale values will either be all "
-"positive or all negative."
+"positive or all negative.\n"
+"[b]Note:[/b] Not all nodes are visually scaled by the [member scale] "
+"property. For example, [Light]s are not visually affected by [member scale]."
msgstr ""
"å±€éƒ¨å˜æ¢çš„缩放部分。\n"
"[b]注æ„:[/b]3D ä¸­ï¼Œå˜æ¢çŸ©é˜µæ˜¯æ— æ³•分解出正负混åˆçš„缩放的。由于 Godot 中使用å˜"
@@ -71273,39 +71437,41 @@ msgid ""
"need to ask for it, with [method set_notify_transform]. The notification is "
"also sent if the node is in the editor context and it has a valid gizmo."
msgstr ""
-"å½“ç©ºé—´èŠ‚ç‚¹çš„å…¨å±€å˜æ¢å‘生å˜åŒ–时,空间节点会收到这个通知。这æ„味ç€å½“å‰èŠ‚ç‚¹æˆ–çˆ¶"
-"节点改å˜äº†å®ƒçš„å˜æ¢ã€‚\n"
+"当 Spatial èŠ‚ç‚¹çš„å…¨å±€å˜æ¢å‘生å˜åŒ–时会收到这个通知。这æ„味ç€å½“å‰èŠ‚ç‚¹æˆ–çˆ¶èŠ‚ç‚¹æ”¹"
+"å˜äº†å®ƒçš„å˜æ¢ã€‚\n"
"为了使 [constant NOTIFICATION_TRANSFORM_CHANGED] 生效,用户首先需è¦ç”¨ "
"[method set_notify_transform] å‘é€è¯·æ±‚。如果节点是在编辑器的上下文中,并且它"
-"有一个有效的控制器(Gizmo),那么该通知也会被å‘é€ã€‚"
+"有一个有效的å°å·¥å…·ï¼Œé‚£ä¹ˆè¯¥é€šçŸ¥ä¹Ÿä¼šè¢«å‘é€ã€‚"
#: doc/classes/Spatial.xml
msgid ""
"Spatial nodes receives this notification when they are registered to new "
"[World] resource."
-msgstr "空间节点在注册到新的 [World] èµ„æºæ—¶ä¼šæ”¶åˆ°æ­¤é€šçŸ¥ã€‚"
+msgstr "Spatial 节点在注册到新的 [World] èµ„æºæ—¶ä¼šæ”¶åˆ°æ­¤é€šçŸ¥ã€‚"
#: doc/classes/Spatial.xml
msgid ""
"Spatial nodes receives this notification when they are unregistered from "
"current [World] resource."
-msgstr "当空间节点从当å‰çš„ [World] 资æºä¸­å–消注册时,它们会收到此通知。"
+msgstr "当 Spatial 节点从当å‰çš„ [World] 资æºä¸­å–消注册时,它们会收到此通知。"
#: doc/classes/Spatial.xml
msgid "Spatial nodes receives this notification when their visibility changes."
-msgstr "空间节点在其å¯è§æ€§å‘生å˜åŒ–时会收到此通知。"
+msgstr "Spatial 节点在其å¯è§æ€§å‘生å˜åŒ–时会收到此通知。"
#: doc/classes/Spatial.xml
msgid ""
"Spatial nodes receives this notification if the portal system gameplay "
"monitor detects they have entered the gameplay area."
-msgstr "如果入å£ç³»ç»Ÿæ¸¸æˆç›‘视器检测到它们已进入游æˆåŒºåŸŸï¼Œç©ºé—´èŠ‚ç‚¹ä¼šæ”¶åˆ°æ­¤é€šçŸ¥ã€‚"
+msgstr ""
+"如果入å£ç³»ç»Ÿæ¸¸æˆç›‘视器检测到它们已进入游æˆåŒºåŸŸï¼ŒSpatial 节点会收到此通知。"
#: doc/classes/Spatial.xml
msgid ""
"Spatial nodes receives this notification if the portal system gameplay "
"monitor detects they have exited the gameplay area."
-msgstr "如果入å£ç³»ç»Ÿæ¸¸æˆç›‘视器检测到它们已退出游æˆåŒºåŸŸï¼Œç©ºé—´èŠ‚ç‚¹ä¼šæ”¶åˆ°æ­¤é€šçŸ¥ã€‚"
+msgstr ""
+"如果入å£ç³»ç»Ÿæ¸¸æˆç›‘视器检测到它们已退出游æˆåŒºåŸŸï¼ŒSpatial 节点会收到此通知。"
#: doc/classes/SpatialMaterial.xml
msgid "Default 3D rendering material."
@@ -72867,8 +73033,11 @@ msgstr ""
"max_lights_per_object],以ç€è‰²å™¨ç¼–译时间为代价。"
#: doc/classes/SpotLight.xml
-msgid "The spotlight's angle in degrees."
-msgstr "èšå…‰ç¯çš„角度,å•使˜¯åº¦ã€‚"
+msgid ""
+"The spotlight's angle in degrees.\n"
+"[b]Note:[/b] [member spot_angle] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
+msgstr ""
#: doc/classes/SpotLight.xml
msgid "The spotlight's angular attenuation curve."
@@ -72879,11 +73048,14 @@ msgid "The spotlight's light energy attenuation curve."
msgstr "èšå…‰ç¯çš„å…‰é‡è¡°å‡æ›²çº¿ã€‚"
#: doc/classes/SpotLight.xml
+#, fuzzy
msgid ""
"The maximal range that can be reached by the spotlight. Note that the "
"effectively lit area may appear to be smaller depending on the [member "
"spot_attenuation] in use. No matter the [member spot_attenuation] in use, "
-"the light will never reach anything outside this range."
+"the light will never reach anything outside this range.\n"
+"[b]Note:[/b] [member spot_range] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
"èšå…‰ç¯å¯ä»¥è¾¾åˆ°çš„æœ€å¤§èŒƒå›´ã€‚请注æ„,根æ®ä½¿ç”¨çš„ [member spot_attenuation],有效"
"照明区域å¯èƒ½çœ‹èµ·æ¥æ›´å°ã€‚无论使用[member spot_attenuation],光都ä¸ä¼šåˆ°è¾¾æ­¤èŒƒå›´"
@@ -77961,55 +78133,49 @@ msgid "Clears all values on the theme."
msgstr "清除主题上的所有值。"
#: doc/classes/Theme.xml
-#, fuzzy
msgid ""
"Clears the [Color] at [code]name[/code] if the theme has [code]theme_type[/"
"code]."
msgstr ""
-"å¦‚æžœä¸»é¢˜åŒ…å« [code]node_type[/code],则清除å为 [code]name[/code] çš„ [Color]"
+"å¦‚æžœä¸»é¢˜åŒ…å« [code]theme_type[/code],则清除å为 [code]name[/code] çš„ [Color]"
"颜色。"
#: doc/classes/Theme.xml
-#, fuzzy
msgid ""
"Clears the constant at [code]name[/code] if the theme has [code]theme_type[/"
"code]."
msgstr ""
-"å¦‚æžœä¸»é¢˜åŒ…å« [code]node_type[/code],则清除å为 [code]name[/code] 的常é‡ã€‚"
+"å¦‚æžœä¸»é¢˜åŒ…å« [code]theme_type[/code],则清除å为 [code]name[/code] 的常é‡ã€‚"
#: doc/classes/Theme.xml
-#, fuzzy
msgid ""
"Clears the [Font] at [code]name[/code] if the theme has [code]theme_type[/"
"code]."
msgstr ""
-"å¦‚æžœä¸»é¢˜åŒ…å« [code]node_type[/code],则清除å为 [code]name[/code] çš„ [Font]å­—"
-"体。"
+"å¦‚æžœä¸»é¢˜åŒ…å« [code]theme_type[/code],则清除å为 [code]name[/code] çš„ [Font]"
+"字体。"
#: doc/classes/Theme.xml
-#, fuzzy
msgid ""
"Clears the icon at [code]name[/code] if the theme has [code]theme_type[/"
"code]."
msgstr ""
-"å¦‚æžœä¸»é¢˜åŒ…å« [code]node_type[/code],则清除å为 [code]name[/code] 的图标。"
+"å¦‚æžœä¸»é¢˜åŒ…å« [code]theme_type[/code],则清除å为 [code]name[/code] 的图标。"
#: doc/classes/Theme.xml
-#, fuzzy
msgid ""
"Clears [StyleBox] at [code]name[/code] if the theme has [code]theme_type[/"
"code]."
msgstr ""
-"å¦‚æžœä¸»é¢˜åŒ…å« [code]node_type[/code],则清除å为 [code]name[/code] çš„ "
+"å¦‚æžœä¸»é¢˜åŒ…å« [code]theme_type[/code],则清除å为 [code]name[/code] çš„ "
"[StyleBox]æ ·å¼ç›’。"
#: doc/classes/Theme.xml
-#, fuzzy
msgid ""
"Clears the theme item of [code]data_type[/code] at [code]name[/code] if the "
"theme has [code]theme_type[/code]."
msgstr ""
-"如果主题具有 [code]node_type[/code],则清除 [code]name[/code] 处的 "
+"如果主题具有 [code]theme_type[/code],则清除 [code]name[/code] 处的 "
"[code]data_type[/code] 主题项。"
#: doc/classes/Theme.xml
@@ -78029,21 +78195,20 @@ msgid "Sets the theme's values to a copy of a given theme."
msgstr "将主题的å–值设置为指定主题的副本。"
#: doc/classes/Theme.xml
-#, fuzzy
msgid ""
"Returns the [Color] at [code]name[/code] if the theme has [code]theme_type[/"
"code]."
-msgstr "如果主题有[code]node_type[/code],返回 [code]name[/code]处的[Color]。"
+msgstr ""
+"如果主题有 [code]theme_type[/code],返回 [code]name[/code] 处的 [Color]。"
#: doc/classes/Theme.xml
-#, fuzzy
msgid ""
"Returns all the [Color]s as a [PoolStringArray] filled with each [Color]'s "
"name, for use in [method get_color], if the theme has [code]theme_type[/"
"code]."
msgstr ""
-"如果主题有[code]node_type[/code],将所有的[Color]作为[PoolStringArray]返回,"
-"å¹¶å¡«å……æ¯ä¸ª[Color]çš„å称,用于[method get_color]使用。"
+"如果主题有 [code]theme_type[/code],将所有的 [Color] 作为 [PoolStringArray] "
+"返回,并填充æ¯ä¸ª [Color] çš„å称,用于 [method get_color] 使用。"
#: doc/classes/Theme.xml
msgid ""
@@ -78054,20 +78219,18 @@ msgstr ""
"[method get_color] 和/或 [method get_color_list] 使用。"
#: doc/classes/Theme.xml
-#, fuzzy
msgid ""
"Returns the constant at [code]name[/code] if the theme has [code]theme_type[/"
"code]."
-msgstr "如果主题有 [code]node_type[/code],返回 [code]name[/code] 处的常é‡ã€‚"
+msgstr "如果主题有 [code]theme_type[/code],返回 [code]name[/code] 处的常é‡ã€‚"
#: doc/classes/Theme.xml
-#, fuzzy
msgid ""
"Returns all the constants as a [PoolStringArray] filled with each constant's "
"name, for use in [method get_constant], if the theme has [code]theme_type[/"
"code]."
msgstr ""
-"如果主题有 [code]node_type[/code],将所有常é‡ä½œä¸º [PoolStringArray] 返回,并"
+"如果主题有 [code]theme_type[/code],将所有常é‡ä½œä¸º [PoolStringArray] 返回,并"
"å¡«å……æ¯ä¸ªå¸¸é‡çš„å称,以供 [method get_constant] 使用。"
#: doc/classes/Theme.xml
@@ -78080,23 +78243,21 @@ msgstr ""
"get_constant]和/或[method get_constant_list]使用。"
#: doc/classes/Theme.xml
-#, fuzzy
msgid ""
"Returns the [Font] at [code]name[/code] if the theme has [code]theme_type[/"
"code]. If such item does not exist and [member default_font] is set on the "
"theme, the default font will be returned."
msgstr ""
-"如果主题有 [code]node_type[/code],则返回å为 [code]name[/code] çš„ [Font]。如"
-"æžœä¸å­˜åœ¨è¿™æ ·çš„项目,而该主题设置了 [member default_font],则会返回该默认字"
+"如果主题有 [code]theme_type[/code],则返回å为 [code]name[/code] çš„ [Font]。"
+"如果ä¸å­˜åœ¨è¿™æ ·çš„项目,而该主题设置了 [member default_font],则会返回该默认字"
"体。"
#: doc/classes/Theme.xml
-#, fuzzy
msgid ""
"Returns all the [Font]s as a [PoolStringArray] filled with each [Font]'s "
"name, for use in [method get_font], if the theme has [code]theme_type[/code]."
msgstr ""
-"如果主题有 [code]node_type[/code],将所有的 [Font] 作为 [PoolStringArray] 返"
+"如果主题有 [code]theme_type[/code],将所有的 [Font] 作为 [PoolStringArray] 返"
"回,并填入æ¯ä¸ª [Font] çš„å称,以供 [method get_font] 使用。"
#: doc/classes/Theme.xml
@@ -78108,21 +78269,20 @@ msgstr ""
"get_font]和/或[method get_font_list]使用。"
#: doc/classes/Theme.xml
-#, fuzzy
msgid ""
"Returns the icon [Texture] at [code]name[/code] if the theme has "
"[code]theme_type[/code]."
msgstr ""
-"如果主题有[code]node_type[/code],返回 [code]name[/code]处的图标[Texture]。"
+"如果主题有 [code]theme_type[/code],返回 [code]name[/code] 处的图标 "
+"[Texture]。"
#: doc/classes/Theme.xml
-#, fuzzy
msgid ""
"Returns all the icons as a [PoolStringArray] filled with each [Texture]'s "
"name, for use in [method get_icon], if the theme has [code]theme_type[/code]."
msgstr ""
-"如果主题有[code]node_type[/code],则返回所有的图标为一个[PoolStringArray],并"
-"å¡«å…¥æ¯ä¸ª[Texture]çš„å称,以供[method get_icon]使用。"
+"如果主题有 [code]theme_type[/code],则返回所有的图标为一个 "
+"[PoolStringArray],并填入æ¯ä¸ª [Texture] çš„å称,以供 [method get_icon] 使用。"
#: doc/classes/Theme.xml
msgid ""
@@ -78133,7 +78293,6 @@ msgstr ""
"get_icon]和/或[method get_icon_list]使用。"
#: doc/classes/Theme.xml
-#, fuzzy
msgid ""
"Returns the [StyleBox] at [code]name[/code] if the theme has "
"[code]theme_type[/code].\n"
@@ -78141,12 +78300,12 @@ msgid ""
"Valid [code]theme_type[/code]s may be found using [method "
"get_stylebox_types]."
msgstr ""
-"如果主题有[code]node_type[/code],返回 [code]name[/code]处的[StyleBox]。\n"
-"å¯ä»¥ä½¿ç”¨[method get_stylebox_list]找到有效的[code]name[/code]。å¯ä»¥é€šè¿‡"
-"[method get_stylebox_types]æ¥æ‰¾åˆ°æœ‰æ•ˆçš„[code]node_type[/code]。"
+"如果主题有 [code]theme_type[/code],返回 [code]name[/code] 处的 "
+"[StyleBox]。\n"
+"å¯ä»¥ä½¿ç”¨ [method get_stylebox_list] 找到有效的 [code]name[/code]。å¯ä»¥é€šè¿‡ "
+"[method get_stylebox_types] æ¥æ‰¾åˆ°æœ‰æ•ˆçš„ [code]theme_type[/code]。"
#: doc/classes/Theme.xml
-#, fuzzy
msgid ""
"Returns all the [StyleBox]s as a [PoolStringArray] filled with each "
"[StyleBox]'s name, for use in [method get_stylebox], if the theme has "
@@ -78154,9 +78313,10 @@ msgid ""
"Valid [code]theme_type[/code]s may be found using [method "
"get_stylebox_types]."
msgstr ""
-"如果主题有[code]node_type[/code],则返回所有[StyleBox]的[PoolStringArray],并"
-"å¡«å…¥æ¯ä¸ª[StyleBox]çš„å称,以供[method get_stylebox]使用。\n"
-"å¯ä»¥ä½¿ç”¨[method get_stylebox_types]找到有效的[code]node_type[/code]。"
+"如果主题有 [code]theme_type[/code],则返回所有 [StyleBox] 的 "
+"[PoolStringArray],并填入æ¯ä¸ª [StyleBox] çš„å称,以供 [method get_stylebox] "
+"使用。\n"
+"å¯ä»¥ä½¿ç”¨ [method get_stylebox_types] 找到有效的 [code]theme_type[/code]。"
#: doc/classes/Theme.xml
msgid ""
@@ -78168,7 +78328,6 @@ msgstr ""
"[method get_stylebox]和/或[method get_stylebox_list]使用。"
#: doc/classes/Theme.xml
-#, fuzzy
msgid ""
"Returns the theme item of [code]data_type[/code] at [code]name[/code] if the "
"theme has [code]theme_type[/code].\n"
@@ -78176,14 +78335,13 @@ msgid ""
"a data type specific method. Valid [code]theme_type[/code]s may be found "
"using [method get_theme_item_types] or a data type specific method."
msgstr ""
-"如果主题有 [code]node_type[/code],则以 [code]name[/code] 返回 "
+"如果主题有 [code]theme_type[/code],则以 [code]name[/code] 返回 "
"[code]data_type[/code] 的主题项目。\n"
"使用 [method get_theme_item_list] 或数æ®ç±»åž‹ç‰¹å®šæ–¹æ³•,å¯èƒ½ä¼šæ‰¾åˆ°æœ‰æ•ˆçš„ "
"[code]name[/code]。å¯ä»¥ä½¿ç”¨ [method get_theme_item_types] 或数æ®ç±»åž‹ç‰¹å®šæ–¹"
-"法,找到有效的 [code]node_type[/code]。"
+"法,找到有效的 [code]theme_type[/code]。"
#: doc/classes/Theme.xml
-#, fuzzy
msgid ""
"Returns all the theme items of [code]data_type[/code] as a [PoolStringArray] "
"filled with each theme items's name, for use in [method get_theme_item] or a "
@@ -78191,11 +78349,11 @@ msgid ""
"Valid [code]theme_type[/code]s may be found using [method "
"get_theme_item_types] or a data type specific method."
msgstr ""
-"返回所有[code]data_type[/code]的主题项目,以[PoolStringArray]的形å¼å¡«å…¥æ¯ä¸ªä¸»"
-"题项目的å称,如果主题有[code]node_type[/code],å¯ä»¥åœ¨[method get_theme_item]"
-"或特定数æ®ç±»åž‹æ–¹æ³•中使用。\n"
-"å¯ä»¥é€šè¿‡[method get_theme_item_types]或特定数æ®ç±»åž‹çš„æ–¹æ³•找到有效的"
-"[code]node_type[/code]。"
+"返回所有 [code]data_type[/code] 的主题项目,以 [PoolStringArray] 的形å¼å¡«å…¥æ¯"
+"个主题项目的å称,如果主题有 [code]theme_type[/code],å¯ä»¥åœ¨ [method "
+"get_theme_item] 或特定数æ®ç±»åž‹æ–¹æ³•中使用。\n"
+"å¯ä»¥é€šè¿‡ [method get_theme_item_types] 或特定数æ®ç±»åž‹çš„æ–¹æ³•找到有效的 "
+"[code]theme_type[/code]。"
#: doc/classes/Theme.xml
msgid ""
@@ -78208,16 +78366,15 @@ msgstr ""
"或数æ®ç±»åž‹ç‰¹å®šæ–¹æ³•使用。"
#: doc/classes/Theme.xml
-#, fuzzy
msgid ""
"Returns all the theme types as a [PoolStringArray] filled with unique type "
"names, for use in other [code]get_*[/code] functions of this theme.\n"
"[b]Note:[/b] [code]theme_type[/code] has no effect and will be removed in "
"future version."
msgstr ""
-"将所有的主题类型作为一个[PoolStringArray]返回,其中填入了唯一的类型å称,以供"
-"这个主题的其他[code]get_*[/code]函数使用。\n"
-"[b]注æ„:[/b][code]node_type[/code]没有生效,在未æ¥çš„版本中会被删除。"
+"将所有的主题类型作为一个 [PoolStringArray] 返回,其中填入了唯一的类型å称,以"
+"供这个主题的其他 [code]get_*[/code] 函数使用。\n"
+"[b]注æ„:[/b][code]theme_type[/code] 没有生效,在未æ¥çš„版本中会被删除。"
#: doc/classes/Theme.xml
msgid ""
@@ -78233,28 +78390,26 @@ msgid ""
msgstr "返回给定的基础类型 [code]base_type[/code] 的所有类型å˜ç§ã€‚"
#: doc/classes/Theme.xml
-#, fuzzy
msgid ""
"Returns [code]true[/code] if [Color] with [code]name[/code] is in "
"[code]theme_type[/code].\n"
"Returns [code]false[/code] if the theme does not have [code]theme_type[/"
"code]."
msgstr ""
-"如果带有[code]name[/code]的[Color]在[code]node_type[/code]中,则返回 "
+"如果 [code]theme_type[/code] 中存在å为 [code]name[/code] çš„ [Color],则返回 "
"[code]true[/code]。\n"
-"如果主题没有[code]node_type[/code],则返回 [code]false[/code]。"
+"如果主题没有 [code]theme_type[/code],则返回 [code]false[/code]。"
#: doc/classes/Theme.xml
-#, fuzzy
msgid ""
"Returns [code]true[/code] if constant with [code]name[/code] is in "
"[code]theme_type[/code].\n"
"Returns [code]false[/code] if the theme does not have [code]theme_type[/"
"code]."
msgstr ""
-"如果带有[code]name[/code]的常é‡åœ¨[code]node_type[/code]中,则返回 "
+"如果 [code]theme_type[/code] 中存在å为 [code]name[/code] 的常é‡ï¼Œåˆ™è¿”回 "
"[code]true[/code]。\n"
-"如果主题没有[code]node_type[/code],则返回 [code]false[/code]。"
+"如果主题没有[code]theme_type[/code],则返回 [code]false[/code]。"
#: doc/classes/Theme.xml
msgid ""
@@ -78264,52 +78419,48 @@ msgstr ""
"如果这个主题有一个有效的[member default_font]值,返回 [code]true[/code]。"
#: doc/classes/Theme.xml
-#, fuzzy
msgid ""
"Returns [code]true[/code] if [Font] with [code]name[/code] is in "
"[code]theme_type[/code].\n"
"Returns [code]false[/code] if the theme does not have [code]theme_type[/"
"code]."
msgstr ""
-"如果带有[code]name[/code]的[Font]在[code]node_type[/code]中,则返回 "
+"如果 [code]theme_type[/code] 中存在å为 [code]name[/code] çš„ [Font],则返回 "
"[code]true[/code]。\n"
-"如果主题没有[code]node_type[/code],则返回 [code]false[/code]。"
+"如果主题没有[code]theme_type[/code],则返回 [code]false[/code]。"
#: doc/classes/Theme.xml
-#, fuzzy
msgid ""
"Returns [code]true[/code] if icon [Texture] with [code]name[/code] is in "
"[code]theme_type[/code].\n"
"Returns [code]false[/code] if the theme does not have [code]theme_type[/"
"code]."
msgstr ""
-"如果带有[code]name[/code]的图标[Texture]在[code]node_type[/code]中,则返回 "
-"[code]true[/code]。\n"
-"如果主题没有[code]node_type[/code],则返回 [code]false[/code]。"
+"如果 [code]theme_type[/code] 中存在å为 [code]name[/code] 的图标 [Texture],"
+"则返回 [code]true[/code]。\n"
+"如果主题没有[code]theme_type[/code],则返回 [code]false[/code]。"
#: doc/classes/Theme.xml
-#, fuzzy
msgid ""
"Returns [code]true[/code] if [StyleBox] with [code]name[/code] is in "
"[code]theme_type[/code].\n"
"Returns [code]false[/code] if the theme does not have [code]theme_type[/"
"code]."
msgstr ""
-"如果带有[code]name[/code]的[StyleBox]在[code]node_type[/code]中,返回 "
-"[code]true[/code]。\n"
-"如果主题没有[code]node_type[/code],则返回 [code]false[/code]。"
+"如果 [code]theme_type[/code] 中存在å为 [code]name[/code] çš„ [StyleBox],则返"
+"回 [code]true[/code]。\n"
+"如果主题没有[code]theme_type[/code],则返回 [code]false[/code]。"
#: doc/classes/Theme.xml
-#, fuzzy
msgid ""
"Returns [code]true[/code] if a theme item of [code]data_type[/code] with "
"[code]name[/code] is in [code]theme_type[/code].\n"
"Returns [code]false[/code] if the theme does not have [code]theme_type[/"
"code]."
msgstr ""
-"如果一个 [code]data_type[/code] 的主题项目与 [code]name[/code] 在 "
-"[code]node_type[/code] 中,则返回 [code]true[/code]。\n"
-"如果该主题没有 [code]node_type[/code],则返回 [code]false[/code]。"
+"如果 [code]theme_type[/code] 中存在å为 [code]name[/code] çš„ "
+"[code]data_type[/code] 类型的主题项目,则返回 [code]true[/code]。\n"
+"如果该主题没有 [code]theme_type[/code],则返回 [code]false[/code]。"
#: doc/classes/Theme.xml
msgid ""
@@ -78341,123 +78492,111 @@ msgstr ""
"被消除。如果该类型为类型å˜ç§çš„基础类型,则那些å˜ç§ä¼šå¤±åŽ»å…¶åŸºç¡€ç±»åž‹ã€‚"
#: doc/classes/Theme.xml
-#, fuzzy
msgid ""
"Renames the [Color] at [code]old_name[/code] to [code]name[/code] if the "
"theme has [code]theme_type[/code]. If [code]name[/code] is already taken, "
"this method fails."
msgstr ""
-"如果主题有 [code]node_type[/code],则将 [code]old_name[/code] çš„ [Color] é‡å‘½"
-"å为 [code]name[/code]。如果 [code]name[/code] å·²ç»è¢«å ç”¨ï¼Œåˆ™æ­¤æ–¹æ³•将失败。"
+"如果主题有 [code]theme_type[/code],则将 [code]old_name[/code] çš„ [Color] é‡"
+"命å为 [code]name[/code]。如果 [code]name[/code] å·²ç»è¢«å ç”¨ï¼Œåˆ™æ­¤æ–¹æ³•将失败。"
#: doc/classes/Theme.xml
-#, fuzzy
msgid ""
"Renames the constant at [code]old_name[/code] to [code]name[/code] if the "
"theme has [code]theme_type[/code]. If [code]name[/code] is already taken, "
"this method fails."
msgstr ""
-"如果主题有 [code]node_type[/code],则将 [code]old_name[/code] 的常é‡é‡å‘½å为 "
-"[code]name[/code]。如果 [code]name[/code] å·²ç»è¢«å ç”¨ï¼Œåˆ™æ­¤æ–¹æ³•失败。"
+"如果主题有 [code]theme_type[/code],则将 [code]old_name[/code] 的常é‡é‡å‘½å"
+"为 [code]name[/code]。如果 [code]name[/code] å·²ç»è¢«å ç”¨ï¼Œåˆ™æ­¤æ–¹æ³•失败。"
#: doc/classes/Theme.xml
-#, fuzzy
msgid ""
"Renames the [Font] at [code]old_name[/code] to [code]name[/code] if the "
"theme has [code]theme_type[/code]. If [code]name[/code] is already taken, "
"this method fails."
msgstr ""
-"如果主题有 [code]node_type[/code],则将 [code]old_name[/code] çš„ [Font] é‡å‘½"
+"如果主题有 [code]theme_type[/code],则将 [code]old_name[/code] çš„ [Font] é‡å‘½"
"å为 [code]name[/code]。如果 [code]name[/code] å·²ç»è¢«å ç”¨ï¼Œåˆ™æ­¤æ–¹æ³•失败。"
#: doc/classes/Theme.xml
-#, fuzzy
msgid ""
"Renames the icon at [code]old_name[/code] to [code]name[/code] if the theme "
"has [code]theme_type[/code]. If [code]name[/code] is already taken, this "
"method fails."
msgstr ""
-"如果主题有 [code]node_type[/code],则将 [code]old_name[/code] 的图标é‡å‘½å为 "
-"[code]name[/code]。如果 [code]name[/code] å·²ç»è¢«å ç”¨ï¼Œåˆ™æ­¤æ–¹æ³•失败。"
+"如果主题有 [code]theme_type[/code],则将 [code]old_name[/code] 的图标é‡å‘½å"
+"为 [code]name[/code]。如果 [code]name[/code] å·²ç»è¢«å ç”¨ï¼Œåˆ™æ­¤æ–¹æ³•失败。"
#: doc/classes/Theme.xml
-#, fuzzy
msgid ""
"Renames [StyleBox] at [code]old_name[/code] to [code]name[/code] if the "
"theme has [code]theme_type[/code]. If [code]name[/code] is already taken, "
"this method fails."
msgstr ""
-"如果主题有 [code]node_type[/code],则将 [StyleBox] 在 [code]old_name[/code] "
+"如果主题有 [code]theme_type[/code],则将 [StyleBox] 在 [code]old_name[/code] "
"é‡å‘½å为 [code]name[/code]。如果 [code]name[/code] å·²ç»è¢«å ç”¨ï¼Œæ­¤æ–¹æ³•会失败。"
#: doc/classes/Theme.xml
-#, fuzzy
msgid ""
"Renames the theme item of [code]data_type[/code] at [code]old_name[/code] to "
"[code]name[/code] if the theme has [code]theme_type[/code]. If [code]name[/"
"code] is already taken, this method fails."
msgstr ""
-"如果主题具有 [code]node_type[/code],则将 [code]old_name[/code] 处的 "
+"如果主题具有 [code]theme_type[/code],则将 [code]old_name[/code] 处的 "
"[code]data_type[/code] 的主题项é‡å‘½å为 [code]name[/code]。如果 [code]name[/"
"code] å·²ç»è¢«å ç”¨ï¼Œåˆ™æ­¤æ–¹æ³•失败。"
#: doc/classes/Theme.xml
-#, fuzzy
msgid ""
"Sets the theme's [Color] to [code]color[/code] at [code]name[/code] in "
"[code]theme_type[/code].\n"
"Creates [code]theme_type[/code] if the theme does not have it."
msgstr ""
-"在 [code]node_type[/code] 中的 [code]name[/code] 处,设置主题的[Color]为"
-"[code]color[/code]。\n"
-"如果主题没有[code]node_type[/code],则创建该节点。"
+"在主题的 [code]theme_type[/code] 中,将å为 [code]name[/code] çš„ [Color] 设置"
+"为 [code]color[/code]。\n"
+"如果该主题没有 [code]theme_type[/code],会创建该主题类型。"
#: doc/classes/Theme.xml
-#, fuzzy
msgid ""
"Sets the theme's constant to [code]constant[/code] at [code]name[/code] in "
"[code]theme_type[/code].\n"
"Creates [code]theme_type[/code] if the theme does not have it."
msgstr ""
-"在 [code]node_type[/code] 中的 [code]name[/code] 处,将主题的常é‡è®¾ç½®ä¸º"
+"在主题的 [code]theme_type[/code] 中,将å为 [code]name[/code] 的常é‡è®¾ç½®ä¸º "
"[code]constant[/code]。\n"
-"如果主题没有,则创建[code]node_type[/code]。"
+"如果该主题没有 [code]theme_type[/code],会创建该主题类型。"
#: doc/classes/Theme.xml
-#, fuzzy
msgid ""
"Sets the theme's [Font] to [code]font[/code] at [code]name[/code] in "
"[code]theme_type[/code].\n"
"Creates [code]theme_type[/code] if the theme does not have it."
msgstr ""
-"在 [code]node_type[/code] 中的 [code]name[/code] 处将主题的 [Font] 设置为"
-"[code]font[/code]。\n"
-"如果主题没有[code]node_type[/code],则创建该节点。"
+"在主题的 [code]theme_type[/code] 中,将å为 [code]name[/code] çš„ [Font] 设置"
+"为 [code]font[/code]。\n"
+"如果该主题没有 [code]theme_type[/code],会创建该主题类型。"
#: doc/classes/Theme.xml
-#, fuzzy
msgid ""
"Sets the theme's icon [Texture] to [code]texture[/code] at [code]name[/code] "
"in [code]theme_type[/code].\n"
"Creates [code]theme_type[/code] if the theme does not have it."
msgstr ""
-"在 [code]node_type[/code] 中的 [code]name[/code] 处设置主题的图标[Texture]为"
-"[code]texture[/code]。\n"
-"如果主题没有[code]node_type[/code],则创建该节点。"
+"在主题的 [code]theme_type[/code] 中,将å为 [code]name[/code] 的图标 "
+"[Texture] 设置为 [code]texture[/code]。\n"
+"如果该主题没有 [code]theme_type[/code],会创建该主题类型。"
#: doc/classes/Theme.xml
-#, fuzzy
msgid ""
"Sets theme's [StyleBox] to [code]stylebox[/code] at [code]name[/code] in "
"[code]theme_type[/code].\n"
"Creates [code]theme_type[/code] if the theme does not have it."
msgstr ""
-"将主题的[StyleBox]设置为[code]stylebox[/code],在[code]node_type[/code]的"
-"[code]name[/code]处。\n"
-"如果主题没有[code]node_type[/code],则创建该节点。"
+"在主题的 [code]theme_type[/code] 中,将å为 [code]name[/code] çš„ [StyleBox] "
+"设置为 [code]stylebox[/code]。\n"
+"如果该主题没有 [code]theme_type[/code],会创建该主题类型。"
#: doc/classes/Theme.xml
-#, fuzzy
msgid ""
"Sets the theme item of [code]data_type[/code] to [code]value[/code] at "
"[code]name[/code] in [code]theme_type[/code].\n"
@@ -78465,10 +78604,11 @@ msgid ""
"code].\n"
"Creates [code]theme_type[/code] if the theme does not have it."
msgstr ""
-"将[code]data_type[/code]的主题项目设置为[code]value[/code],在"
-"[code]node_type[/code]中的[code]name[/code]。\n"
-"如果[code]value[/code]类型与[code]data_type[/code]ä¸åŒ¹é…,则ä¸åšä»»ä½•处ç†ã€‚\n"
-"如果主题没有[code]node_type[/code],则创建该类型。"
+"在主题的 [code]theme_type[/code] 中,将å为 [code]name[/code] çš„ "
+"[code]data_type[/code] 类型的主题项目设置为 [code]value[/code]。\n"
+"如果 [code]value[/code]类型与 [code]data_type[/code]ä¸åŒ¹é…,则ä¸åšä»»ä½•处"
+"ç†ã€‚\n"
+"如果该主题没有 [code]theme_type[/code],会创建该主题类型。"
#: doc/classes/Theme.xml
msgid ""
@@ -78743,7 +78883,7 @@ msgid ""
"Optionally, the tilemap's half offset can be ignored."
msgstr ""
"返回与指定的图å—åœ°å›¾ï¼ˆåŸºäºŽç½‘æ ¼ï¼‰åæ ‡ç›¸å¯¹åº”çš„å•å…ƒæ ¼å·¦ä¸Šè§’çš„å±€éƒ¨åæ ‡ã€‚\n"
-"è¦è޷得免局忠‡ï¼Œè¯·ä½¿ç”¨[method Node2D.to_global]。\n"
+"è¦è޷得免局ä½ç½®ï¼Œè¯·ä½¿ç”¨ [method Node2D.to_global]:\n"
"[codeblock]\n"
"var local_position = my_tilemap.map_to_world(map_position)\n"
"var global_position = my_tilemap.to_global(local_position)\n"
@@ -78807,17 +78947,18 @@ msgstr ""
#: doc/classes/TileMap.xml
msgid "Sets the given collision layer bit."
-msgstr "设置指定碰撞层bitä½ã€‚"
+msgstr "设置指定碰撞层比特ä½ã€‚"
#: doc/classes/TileMap.xml
msgid "Sets the given collision mask bit."
-msgstr "设置指定碰撞é®ç½©bitä½ã€‚"
+msgstr "设置指定碰撞é®ç½©æ¯”特ä½ã€‚"
#: doc/classes/TileMap.xml
msgid ""
"Applies autotiling rules to the cell (and its adjacent cells) referenced by "
"its grid-based X and Y coordinates."
-msgstr "对基于网格的Xå’ŒYåæ ‡æ‰€å¼•用的å•元格,åŠå…¶ç›¸é‚»å•元格,应用自动平移规则。"
+msgstr ""
+"对基于网格的 X å’Œ Y åæ ‡æ‰€å¼•用的å•元格(åŠå…¶ç›¸é‚»å•元格)应用自动平移规则。"
#: doc/classes/TileMap.xml
msgid ""
@@ -78826,8 +78967,8 @@ msgid ""
"Calling with invalid (or missing) parameters applies autotiling rules for "
"the entire tilemap."
msgstr ""
-"对指定区域内的å•元格应用自动平移规则,由基于网格的Xå’ŒYåæ ‡æŒ‡å®šã€‚\n"
-"ç”¨æ— æ•ˆçš„æˆ–ç¼ºå¤±çš„å‚æ•°è°ƒç”¨æ—¶ï¼Œè‡ªåŠ¨å¹³é“ºè§„åˆ™åº”ç”¨äºŽæ•´ä¸ªå›¾å—地图。"
+"对指定区域内的å•元格应用自动平移规则(由基于网格的 X å’Œ Y åæ ‡æŒ‡å®šï¼‰ã€‚\n"
+"ç”¨æ— æ•ˆï¼ˆæˆ–ç¼ºå¤±ï¼‰çš„å‚æ•°è°ƒç”¨æ—¶ï¼Œè‡ªåŠ¨å¹³é“ºè§„åˆ™åº”ç”¨äºŽæ•´ä¸ªå›¾å—地图。"
#: doc/classes/TileMap.xml
msgid ""
@@ -78875,15 +79016,15 @@ msgstr "便¬¡æŽ’列的图å—çš„åç§»é‡ã€‚å¯èƒ½çš„å–å€¼è§ [enum HalfOffset]
msgid ""
"The TileMap's quadrant size. Optimizes drawing by batching, using chunks of "
"this size."
-msgstr "图å—地图的象é™å¤§å°ã€‚使用这个尺寸的图å—,通过批处ç†ä¼˜åŒ–绘制。"
+msgstr "该 TileMap 的象é™å¤§å°ã€‚会使用这个大å°çš„区å—对绘制进行批处ç†ä¼˜åŒ–。"
#: doc/classes/TileMap.xml
msgid "The TileMap's cell size."
-msgstr "图å—地图的å•元大å°ã€‚"
+msgstr "该 TileMap çš„å•元格大å°ã€‚"
#: doc/classes/TileMap.xml
msgid "Position for tile origin. See [enum TileOrigin] for possible values."
-msgstr "图å—åŽŸç‚¹çš„åæ ‡ã€‚å¯èƒ½çš„å–å€¼è§ [enum TileOrigin]。"
+msgstr "图å—原点的ä½ç½®ã€‚å¯èƒ½çš„å–å€¼è§ [enum TileOrigin]。"
#: doc/classes/TileMap.xml
msgid ""
@@ -83220,9 +83361,9 @@ msgid ""
"result at position [code]weight[/code]. [code]weight[/code] is on the range "
"of 0.0 to 1.0, representing the amount of interpolation."
msgstr ""
-"用[code]pre_a[/code]å’Œ[code]post_b[/code]ä½œä¸ºå¥æŸ„,在这个å‘é‡å’Œ[code]b[/code]"
-"之间进行三次æ’值,并在[code]weight[/code]ä½ç½®è¿”回结果。[code]weight[/code]çš„"
-"范围是0.0 到 1.0,表示æ’值的é‡ã€‚"
+"用 [code]pre_a[/code] å’Œ [code]post_b[/code] 作为控制柄,在这个å‘é‡å’Œ "
+"[code]b[/code] 之间进行三次æ’值,并在 [code]weight[/code] ä½ç½®è¿”回结果。"
+"[code]weight[/code] 的范围是 0.0 到 1.0,表示æ’值的é‡ã€‚"
#: doc/classes/Vector2.xml doc/classes/Vector3.xml
msgid ""
@@ -83501,9 +83642,9 @@ msgid ""
"result at position [code]weight[/code]. [code]weight[/code] is on the range "
"of 0.0 to 1.0, representing the amount of interpolation."
msgstr ""
-"用 [code]pre_a[/code] å’Œ [code]post_b[/code] ä½œä¸ºå¥æŸ„,在这个å‘é‡å’Œ [code]b[/"
-"code] 之间进行三次æ’值,并在 [code]weight[/code] ä½ç½®è¿”回结果。[code]weight[/"
-"code] 的范围是 0.0 到 1.0,表示æ’值的é‡ã€‚"
+"用 [code]pre_a[/code] å’Œ [code]post_b[/code] 作为控制柄,在这个å‘é‡å’Œ "
+"[code]b[/code] 之间进行三次æ’值,并在 [code]weight[/code] ä½ç½®è¿”回结果。"
+"[code]weight[/code] 的范围是 0.0 到 1.0,表示æ’值的é‡ã€‚"
#: doc/classes/Vector3.xml
msgid "Returns the distance between this vector and [code]b[/code]."
@@ -83524,11 +83665,11 @@ msgid ""
"[b]Note:[/b] [code]a.dot(b)[/code] is equivalent to [code]b.dot(a)[/code]."
msgstr ""
"返回此å‘é‡ä¸Ž [code]b[/code] 的点积。这å¯ä»¥ç”¨æ¥æ¯”较两个å‘é‡ä¹‹é—´çš„角度。例如,"
-"è¿™å¯ä»¥ç”¨æ¥ç¡®å®šä¸€ä¸ªæ•Œäººæ˜¯å¦æ­£é¢å¯¹çŽ©å®¶ã€‚\n"
-"对于直角 90 度,点积将是 [code]0[/code],对于窄于 90 度的角度,点积大于 0,对"
-"于宽于 90 度的角度,点积å°äºŽ 0。\n"
-"当使用归一化å•ä½å‘é‡ï¼Œå‘釿œå‘ç›¸åæ–¹å‘时,结果总是在 [code]-1.0[/code](180 "
-"度角)和 [code]1.0[/code](0 度角)之间,当å‘é‡å¯¹é½ã€‚\n"
+"è¿™å¯ä»¥ç”¨æ¥ç¡®å®šæ•Œäººæ˜¯å¦é¢å¯¹çŽ©å®¶ã€‚\n"
+"直角(90 度)的点积是 [code]0[/code],夹角å°äºŽ 90 度点积大于 0,夹角大于 90 "
+"度点积å°äºŽ 0。\n"
+"使用å•ä½ï¼ˆå½’一化)å‘釿—¶ï¼Œç»“果总是在表示方å‘相åçš„ [code]-1.0[/code](180 度"
+"角)和表示方å‘相åŒçš„ [code]1.0[/code](0 度角)之间。\n"
"[b]注æ„:[/b][code]a.dot(b)[/code] 与 [code]b.dot(a)[/code] 等价。"
#: doc/classes/Vector3.xml
@@ -83554,8 +83695,8 @@ msgid ""
"constants. If all components are equal, this method returns [constant "
"AXIS_X]."
msgstr ""
-"返回å‘é‡çš„æœ€å¤§å€¼çš„轴。å‚阅 [code]AXIS_*[/code] 常é‡ã€‚如果所有分é‡éƒ½ç›¸ç­‰ï¼Œè¯¥æ–¹"
-"法返回 [constant AXIS_X]。"
+"返回该å‘é‡ä¸­å€¼æœ€å¤§çš„è½´ã€‚è§ [code]AXIS_*[/code] 常é‡ã€‚如果所有分é‡éƒ½ç›¸ç­‰ï¼Œåˆ™è¯¥"
+"方法返回 [constant AXIS_X]。"
#: doc/classes/Vector3.xml
msgid ""
@@ -83563,8 +83704,8 @@ msgid ""
"constants. If all components are equal, this method returns [constant "
"AXIS_Z]."
msgstr ""
-"返回矢é‡çš„æœ€å°å€¼çš„轴。å‚阅 [code]AXIS_*[/code] 常é‡ã€‚如果所有分é‡éƒ½ç›¸ç­‰ï¼Œæœ¬æ–¹"
-"法返回 [constant AXIS_Z]。"
+"返回该å‘é‡ä¸­å€¼æœ€å°çš„è½´ã€‚è§ [code]AXIS_*[/code] 常é‡ã€‚如果所有分é‡éƒ½ç›¸ç­‰ï¼Œåˆ™è¯¥"
+"方法返回 [constant AXIS_Z]。"
#: doc/classes/Vector3.xml
msgid "Returns the outer product with [code]b[/code]."
@@ -83589,8 +83730,8 @@ msgid ""
"clockwise direction when viewed from the side specified by the [code]axis[/"
"code]."
msgstr ""
-"返回给定å‘é‡çš„带符å·çš„角度,å•使˜¯å¼§åº¦ã€‚当从[code]axis[/code]指定的一侧看,该"
-"角度的符å·åœ¨é€†æ—¶é’ˆæ–¹å‘æ˜¯æ­£çš„ï¼Œåœ¨é¡ºæ—¶é’ˆæ–¹å‘æ˜¯è´Ÿçš„。"
+"返回给定å‘é‡çš„带符å·çš„角度,å•使˜¯å¼§åº¦ã€‚当从 [code]axis[/code] 指定的一侧看,"
+"该角度的符å·åœ¨é€†æ—¶é’ˆæ–¹å‘æ˜¯æ­£çš„ï¼Œåœ¨é¡ºæ—¶é’ˆæ–¹å‘æ˜¯è´Ÿçš„。"
#: doc/classes/Vector3.xml
msgid ""
@@ -83701,8 +83842,8 @@ msgid ""
"value in the 25 - 30 range for hard braking."
msgstr ""
"通过施加一个制动力使车辆å‡é€Ÿã€‚åªæœ‰å½“è½¦è½®æŽ¥è§¦åˆ°è¡¨é¢æ—¶ï¼Œè½¦è¾†æ‰ä¼šå‡é€Ÿã€‚ä½ éœ€è¦æ–½"
-"加多少力æ¥ä½¿ä½ çš„车辆充分å‡é€Ÿï¼Œå–决于车辆的[member RigidBody.mass]。对于一个质"
-"é‡è®¾ç½®ä¸º1000的车辆,å°è¯•在25-30的范围内进行硬制动。"
+"加多少力æ¥ä½¿ä½ çš„车辆充分å‡é€Ÿï¼Œå–决于车辆的 [member RigidBody.mass]。对于一个"
+"è´¨é‡è®¾ç½®ä¸º 1000 的车辆,å°è¯•在 25 到 30 的范围内进行硬制动。"
#: doc/classes/VehicleBody.xml
msgid ""
@@ -83718,8 +83859,8 @@ msgid ""
msgstr ""
"通过施加一个引擎力æ¥åŠ é€Ÿè½¦è¾†ã€‚åªæœ‰å½“ [member VehicleWheel.use_as_traction] 设"
"置为 [code]true[/code] å¹¶ä¸Žè¡¨é¢æŽ¥è§¦çš„è½¦è½®æ‰ä¼šåŠ é€Ÿã€‚è½¦è¾†çš„ [member RigidBody."
-"mass] 对车辆的加速度有影å“。对于一个质é‡è®¾ç½®ä¸º 1000 的车辆,å¯ä»¥å°è¯•在 25-50 "
-"的范围内选择加速度的值。\n"
+"mass] 对车辆的加速度有影å“。对于一个质é‡è®¾ç½®ä¸º 1000 的车辆,å¯ä»¥å°è¯•在 25 到 "
+"50 的范围内选择加速度的值。\n"
"[b]注æ„:[/b]模拟ä¸è€ƒè™‘齿轮的影å“,如果你想模拟齿轮,将需è¦ä¸ºå…¶æ·»åŠ é€»è¾‘ã€‚\n"
"负值将导致车辆倒车。"
@@ -83730,8 +83871,8 @@ msgid ""
"VehicleWheel.use_as_steering] set to [code]true[/code] will automatically be "
"rotated."
msgstr ""
-"车辆的转å‘角。将此设置为éžé›¶å€¼å°†å¯¼è‡´è½¦è¾†åœ¨ç§»åŠ¨æ—¶è½¬å‘。将[member VehicleWheel."
-"use_as_steering]设置为 [code]true[/code]的车轮会自动旋转。"
+"车辆的转å‘角。将此设置为éžé›¶å€¼å°†å¯¼è‡´è½¦è¾†åœ¨ç§»åŠ¨æ—¶è½¬å‘。将 [member "
+"VehicleWheel.use_as_steering] 设置为 [code]true[/code] 的车轮会自动旋转。"
#: doc/classes/VehicleWheel.xml
msgid "Physics object that simulates the behavior of a wheel."
@@ -83802,9 +83943,9 @@ msgid ""
"car will keep bouncing as the spring keeps its energy. A good value for this "
"is around 0.3 for a normal car, 0.5 for a race car."
msgstr ""
-"当弹簧被压缩时,应用在弹簧上的阻尼。这个值应该在0.0(无阻尼)和1.0之间。0.0的"
-"值æ„å‘³ç€æ±½è½¦å°†æŒç»­å¼¹è·³ï¼Œå› ä¸ºå¼¹ç°§å°†ä¿æŒå…¶èƒ½é‡ã€‚一个好的值是,普通汽车0.3å·¦å³ï¼Œ"
-"赛车0.5å·¦å³ã€‚"
+"当弹簧被压缩时,应用在弹簧上的阻尼。这个值应该在 0.0(无阻尼)和 1.0 之间。"
+"0.0 的值æ„å‘³ç€æ±½è½¦å°†æŒç»­å¼¹è·³ï¼Œå› ä¸ºå¼¹ç°§å°†ä¿æŒå…¶èƒ½é‡ã€‚普通汽车 0.3 å·¦å³ï¼Œèµ›è½¦ "
+"0.5 左峿¯”较好。"
#: doc/classes/VehicleWheel.xml
msgid ""
@@ -83813,9 +83954,9 @@ msgid ""
"higher than the [member damping_compression] property. For a [member "
"damping_compression] value of 0.3, try a relaxation value of 0.5."
msgstr ""
-"æ”¾æ¾æ—¶æ–½åŠ åœ¨å¼¹ç°§ä¸Šçš„é˜»å°¼ã€‚è¿™ä¸ªå€¼åº”è¯¥åœ¨0.0(无阻尼)和1.0之间。这个值应该总是"
-"比 [member damping_compression] 属性ç¨é«˜ã€‚对于 [member damping_compression] "
-"值0.3,å°è¯•放æ¾å€¼ä¸º0.5。"
+"æ”¾æ¾æ—¶æ–½åŠ åœ¨å¼¹ç°§ä¸Šçš„é˜»å°¼ã€‚è¿™ä¸ªå€¼åº”è¯¥åœ¨ 0.0(无阻尼)和 1.0 之间。这个值应该总"
+"是比 [member damping_compression] 属性ç¨é«˜ã€‚对于 [member "
+"damping_compression] 值 0.3,å°è¯•放æ¾å€¼ä¸º 0.5。"
#: doc/classes/VehicleWheel.xml
msgid ""
@@ -83846,9 +83987,9 @@ msgid ""
"will not carry the weight of the vehicle. Good results are often obtained by "
"a value that is about 3× to 4× this number."
msgstr ""
-"弹簧所能抵抗的最大力。此值应该高于[VehicleBody]的[member RigidBody.mass]的四"
-"分之一,å¦åˆ™å¼¹ç°§å°†æ— æ³•承载车辆的é‡é‡ã€‚通常由大约3×到4×这个数字的值,以获得良"
-"好的效果。"
+"弹簧所能抵抗的最大力。此值应该高于 [VehicleBody] 的 [member RigidBody.mass] "
+"的四分之一,å¦åˆ™å¼¹ç°§å°†æ— æ³•承载车辆的é‡é‡ã€‚通常由大约 3× 到 4× 这个数字的值,"
+"以获得良好的效果。"
#: doc/classes/VehicleWheel.xml
msgid ""
@@ -83856,8 +83997,8 @@ msgid ""
"50 for an off-road car, a value between 50 and 100 for a race car and try "
"something around 200 for something like a Formula 1 car."
msgstr ""
-"这个值定义了悬架的刚度。越野车使用低于50的值,赛车使用50至100的值,åƒä¸€çº§æ–¹ç¨‹"
-"å¼èµ›è½¦åˆ™å°è¯•200å·¦å³çš„值。"
+"这个值定义了悬架的刚度。越野车使用低于 50 的值,赛车使用 50 至 100 的值,åƒä¸€"
+"级方程å¼èµ›è½¦åˆ™å°è¯• 200 å·¦å³çš„值。"
#: doc/classes/VehicleWheel.xml
msgid ""
@@ -83898,10 +84039,10 @@ msgid ""
"simulate tire wear.\n"
"It's best to set this to 1.0 when starting out."
msgstr ""
-"这决定了这个轮å­çš„æŠ“地力有多大。它与车轮所接触的表é¢çš„æ‘©æ“¦åŠ›è®¾ç½®ç›¸ç»“åˆã€‚0.0æ„"
-"å‘³ç€æ²¡æœ‰æŠ“地力,1.0是正常抓地力。对于漂移车的设置,å°è¯•å°†åŽè½®çš„æŠ“地力设置得比"
-"å‰è½®ç•¥ä½Žï¼Œæˆ–è€…ä½¿ç”¨è¾ƒä½Žçš„æ•°å€¼æ¥æ¨¡æ‹Ÿè½®èƒŽçš„磨æŸã€‚\n"
-"在开始时最好将其设置为1.0。"
+"这决定了这个轮å­çš„æŠ“地力有多大。它与车轮所接触的表é¢çš„æ‘©æ“¦åŠ›è®¾ç½®ç›¸ç»“åˆã€‚0.0 "
+"æ„å‘³ç€æ²¡æœ‰æŠ“地力,1.0 是正常抓地力。对于漂移车的设置,å°è¯•å°†åŽè½®çš„æŠ“地力设置"
+"得比å‰è½®ç•¥ä½Žï¼Œæˆ–è€…ä½¿ç”¨è¾ƒä½Žçš„æ•°å€¼æ¥æ¨¡æ‹Ÿè½®èƒŽçš„磨æŸã€‚\n"
+"在开始时最好将其设置为 1.0。"
#: doc/classes/VehicleWheel.xml
msgid "The radius of the wheel in meters."
@@ -83915,9 +84056,9 @@ msgid ""
"will take when bottoming out, then use the rest length to move the wheel "
"down to the position it should be in when the car is in rest."
msgstr ""
-"这是轮å­ä»ŽåŽŸç‚¹ä¸‹é™çš„è·ç¦»ï¼Œä»¥ç±³ä¸ºå•ä½ã€‚ä¸è¦æŠŠè¿™ä¸ªè®¾ç½®ä¸º0.0ï¼Œç„¶åŽæŠŠè½¦è½®ç§»åˆ°ä½ç½®"
-"上,而是把车轮的原点(Godot中的Gizmo)移到车轮触底时的ä½ç½®ï¼Œç„¶åŽä½¿ç”¨å‰©ä½™é•¿åº¦"
-"将轮å­å‘ä¸‹ç§»åŠ¨åˆ°æ±½è½¦é™æ­¢æ—¶å®ƒåº”该所处ä½ç½®ã€‚"
+"这是轮å­ä»ŽåŽŸç‚¹ä¸‹é™çš„è·ç¦»ï¼Œä»¥ç±³ä¸ºå•ä½ã€‚ä¸è¦æŠŠè¿™ä¸ªè®¾ç½®ä¸º 0.0ï¼Œç„¶åŽæŠŠè½¦è½®ç§»åˆ°ä½"
+"置上,而是把车轮的原点(Godot 中的å°å·¥å…·ï¼‰ç§»åˆ°è½¦è½®è§¦åº•æ—¶çš„ä½ç½®ï¼Œç„¶åŽä½¿ç”¨å‰©ä½™"
+"长度将轮å­å‘ä¸‹ç§»åŠ¨åˆ°æ±½è½¦é™æ­¢æ—¶å®ƒåº”该所处ä½ç½®ã€‚"
#: doc/classes/VehicleWheel.xml
msgid ""
@@ -83925,8 +84066,8 @@ msgid ""
"your vehicle will be prone to rolling over, while a value of 0.0 will resist "
"body roll."
msgstr ""
-"这个值会影å“车辆的滚动。如果所有车轮都设置为1.0,车辆将容易翻车,而0.0的值将"
-"阻止车身侧倾。"
+"这个值会影å“车辆的滚动。如果所有车轮都设置为 1.0,车辆将容易翻车,而 0.0 的值"
+"将阻止车身侧倾。"
#: doc/classes/VFlowContainer.xml
msgid "Vertical flow container."
@@ -83970,21 +84111,21 @@ msgstr ""
#: doc/classes/VideoPlayer.xml
msgid "Returns the current frame as a [Texture]."
-msgstr "将当å‰å¸§ä½œä¸º[Texture]返回。"
+msgstr "将当å‰å¸§ä½œä¸º [Texture] 返回。"
#: doc/classes/VideoPlayer.xml
msgid ""
"Returns [code]true[/code] if the video is playing.\n"
"[b]Note:[/b] The video is still considered playing if paused during playback."
msgstr ""
-"如果视频正在播放,返回 [code]true[/code] 。\n"
+"如果视频正在播放,返回 [code]true[/code]。\n"
"[b]注æ„:[/b]如果在播放过程中暂åœï¼Œè§†é¢‘ä»è¢«è®¤ä¸ºåœ¨æ’­æ”¾ã€‚"
#: doc/classes/VideoPlayer.xml
msgid ""
"Starts the video playback from the beginning. If the video is paused, this "
"will not unpause the video."
-msgstr "从头开始播放视频。如果视频暂åœï¼Œè¿™ä¸ä¼šå–消暂åœã€‚"
+msgstr "从头开始播放视频。如果视频处于暂åœçжæ€ï¼Œä¸ä¼šå–消暂åœã€‚"
#: doc/classes/VideoPlayer.xml
msgid ""
@@ -83992,8 +84133,8 @@ msgid ""
"[b]Note:[/b] Although the stream position will be set to 0, the first frame "
"of the video stream won't become the current frame."
msgstr ""
-"åœæ­¢è§†é¢‘播放并将视频æµä½ç½®è®¾ç½®ä¸º0。\n"
-"[b]注æ„:[/b]虽然视频æµä½ç½®å°†è¢«è®¾ç½®ä¸º0,但视频æµçš„第一帧ä¸ä¼šæˆä¸ºå½“å‰å¸§ã€‚"
+"åœæ­¢è§†é¢‘播放并将视频æµä½ç½®è®¾ç½®ä¸º 0。\n"
+"[b]注æ„:[/b]虽然视频æµä½ç½®å°†è¢«è®¾ç½®ä¸º 0,但视频æµçš„第一帧ä¸ä¼šæˆä¸ºå½“å‰å¸§ã€‚"
#: doc/classes/VideoPlayer.xml
msgid "The embedded audio track to play."
@@ -84044,7 +84185,7 @@ msgstr "音频音é‡ä¸ºçº¿æ€§å€¼ã€‚"
#: doc/classes/VideoPlayer.xml
msgid "Audio volume in dB."
-msgstr "音频音é‡ï¼Œå•使˜¯dB。"
+msgstr "音频音é‡ï¼Œå•使˜¯ dB。"
#: doc/classes/VideoPlayer.xml
msgid "Emitted when playback is finished."
@@ -84060,8 +84201,8 @@ msgid ""
"[VideoStream] can all be used as resource types to play back videos in "
"[VideoPlayer]."
msgstr ""
-"所有视频æµçš„资æºç±»åž‹åŸºç±»ã€‚派生自[VideoStream]的类都å¯ä»¥ä½œä¸ºèµ„æºç±»åž‹ï¼Œåœ¨"
-"[VideoPlayer]中播放视频。"
+"所有视频æµçš„资æºç±»åž‹åŸºç±»ã€‚派生自 [VideoStream] 的类都å¯ä»¥ä½œä¸ºèµ„æºç±»åž‹ï¼Œåœ¨ "
+"[VideoPlayer] 中播放视频。"
#: modules/gdnative/doc_classes/VideoStreamGDNative.xml
msgid "[VideoStream] resource for video formats implemented via GDNative."
@@ -84081,7 +84222,7 @@ msgstr ""
#: modules/gdnative/doc_classes/VideoStreamGDNative.xml
msgid "Returns the video file handled by this [VideoStreamGDNative]."
-msgstr "返回由这个[VideoStreamGDNative]处ç†çš„视频文件。"
+msgstr "返回由这个 [VideoStreamGDNative] 处ç†çš„视频文件。"
#: modules/gdnative/doc_classes/VideoStreamGDNative.xml
msgid ""
@@ -84089,12 +84230,12 @@ msgid ""
"supported extensions depend on the GDNative plugins used to expose video "
"formats."
msgstr ""
-"设置此[VideoStreamGDNative]资æºå¤„ç†çš„视频文件。支æŒçš„æ‰©å±•å–决于,用于公开视频"
-"æ ¼å¼çš„GDNativeæ’件。"
+"设置此 [VideoStreamGDNative] 资æºå¤„ç†çš„视频文件。支æŒçš„æ‰©å±•å–决于,用于公开视"
+"频格å¼çš„ GDNative æ’件。"
#: modules/theora/doc_classes/VideoStreamTheora.xml
msgid "[VideoStream] resource for Ogg Theora videos."
-msgstr "[VideoStream] Ogg Theora视频的资æºã€‚"
+msgstr "[VideoStream] Ogg Theora 视频的资æºã€‚"
#: modules/theora/doc_classes/VideoStreamTheora.xml
msgid ""
@@ -84227,7 +84368,7 @@ msgid ""
"Returns the first valid [World] for this viewport, searching the [member "
"world] property of itself and any Viewport ancestor."
msgstr ""
-"返回该视窗的首个有效 [World],在它自身åŠä»»ä½• Viewport 祖先节点的 [member "
+"返回该视å£çš„首个有效 [World],在它自身åŠä»»ä½• Viewport 祖先节点的 [member "
"world] 属性中查找。"
#: doc/classes/Viewport.xml
@@ -84235,7 +84376,7 @@ msgid ""
"Returns the first valid [World2D] for this viewport, searching the [member "
"world_2d] property of itself and any Viewport ancestor."
msgstr ""
-"返回该视窗的首个有效 [World2D],在它自身åŠä»»ä½• Viewport 祖先节点的 [member "
+"返回该视å£çš„首个有效 [World2D],在它自身åŠä»»ä½• Viewport 祖先节点的 [member "
"world_2d] 属性中查找。"
#: doc/classes/Viewport.xml
@@ -84290,7 +84431,7 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid "Returns the viewport's RID from the [VisualServer]."
-msgstr "从 [VisualServer] 返回该视窗的 RID。"
+msgstr "从 [VisualServer] 返回该视å£çš„ RID。"
#: doc/classes/Viewport.xml
msgid "Returns the visible rectangle in global screen coordinates."
@@ -84327,8 +84468,7 @@ msgid ""
"Returns [code]true[/code] if the size override is enabled. See [method "
"set_size_override]."
msgstr ""
-"如果å¯ç”¨äº†å°ºå¯¸è¦†ç›–,则返回 [code]true[/code]。请å‚阅 [method "
-"set_size_override]。"
+"如果å¯ç”¨äº†å°ºå¯¸è¦†ç›–,则返回 [code]true[/code]ã€‚è§ [method set_size_override]。"
#: doc/classes/Viewport.xml
msgid ""
@@ -84363,7 +84503,7 @@ msgid ""
"size. If the size parameter is [code](-1, -1)[/code], it won't update the "
"size."
msgstr ""
-"设置该视窗的尺寸覆盖。如果 [code]enable[/code] 傿•°æ˜¯ [code]true[/code],就会"
+"设置该视å£çš„尺寸覆盖。如果 [code]enable[/code] 傿•°æ˜¯ [code]true[/code],就会"
"使用覆盖,å¦åˆ™å°±ä½¿ç”¨é»˜è®¤å°ºå¯¸ã€‚å¦‚æžœå°ºå¯¸å‚æ•°æ˜¯ [code](-1, -1)[/code],它将ä¸ä¼š"
"更新尺寸。"
@@ -84380,15 +84520,15 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid "If [code]true[/code], the viewport will be used in AR/VR process."
-msgstr "如果为 [code]true[/code],该视窗将用于AR/VR进程。"
+msgstr "如果为 [code]true[/code],该视å£å°†ç”¨äºŽAR/VR进程。"
#: doc/classes/Viewport.xml
msgid "If [code]true[/code], the viewport will process 2D audio streams."
-msgstr "如果为 [code]true[/code]ï¼Œè¯¥è§†çª—å°†å¤„ç† 2D 音频æµã€‚"
+msgstr "如果为 [code]true[/code],该视å£å°†å¤„ç† 2D 音频æµã€‚"
#: doc/classes/Viewport.xml
msgid "If [code]true[/code], the viewport will process 3D audio streams."
-msgstr "如果为 [code]true[/code]ï¼Œè¯¥è§†çª—å°†å¤„ç† 3D 音频æµã€‚"
+msgstr "如果为 [code]true[/code],该视å£å°†å¤„ç† 3D 音频æµã€‚"
#: doc/classes/Viewport.xml
msgid ""
@@ -84396,16 +84536,22 @@ msgid ""
"positions of all child [CanvasItem]s. This is relative to the global canvas "
"transform of the viewport."
msgstr ""
-"è¯¥è§†çª—çš„ç”»å¸ƒå˜æ¢ï¼Œå¯¹æ”¹å˜æ‰€æœ‰å­ [CanvasItem] çš„å±å¹•ä½ç½®å¾ˆæœ‰ç”¨ã€‚相对于该视窗的"
+"该视å£çš„ç”»å¸ƒå˜æ¢ï¼Œå¯¹æ”¹å˜æ‰€æœ‰å­ [CanvasItem] çš„å±å¹•ä½ç½®å¾ˆæœ‰ç”¨ã€‚相对于该视å£çš„"
"å…¨å±€ç”»å¸ƒå˜æ¢ã€‚"
#: doc/classes/Viewport.xml
+#, fuzzy
msgid ""
"If [code]true[/code], uses a fast post-processing filter to make banding "
-"significantly less visible. In some cases, debanding may introduce a "
-"slightly noticeable dithering pattern. It's recommended to enable debanding "
-"only when actually needed since the dithering pattern will make lossless-"
-"compressed screenshots larger.\n"
+"significantly less visible in 3D. 2D rendering is [i]not[/i] affected by "
+"debanding unless the [member Environment.background_mode] is [constant "
+"Environment.BG_CANVAS]. In this case, [member usage] must also be set to "
+"[constant USAGE_3D]. See also [member ProjectSettings.rendering/quality/"
+"filters/use_debanding].\n"
+"In some cases, debanding may introduce a slightly noticeable dithering "
+"pattern. It's recommended to enable debanding only when actually needed "
+"since the dithering pattern will make lossless-compressed screenshots "
+"larger.\n"
"[b]Note:[/b] Only available on the GLES3 backend. [member hdr] must also be "
"[code]true[/code] for debanding to be effective."
msgstr ""
@@ -84420,11 +84566,12 @@ msgid "The overlay mode for test rendered geometry in debug purposes."
msgstr "在调试时,用于测试渲染的几何图形的å åŠ æ¨¡å¼ã€‚"
#: doc/classes/Viewport.xml
+#, fuzzy
msgid ""
-"If [code]true[/code], the viewport will disable 3D rendering. For actual "
-"disabling use [code]usage[/code]."
+"If [code]true[/code], the viewport will disable 3D rendering. To actually "
+"disable allocation of 3D buffers, set [member usage] instead."
msgstr ""
-"如果为 [code]true[/code],该视窗将ç¦ç”¨ 3D 渲染。对于实际ç¦ç”¨ï¼Œä½¿ç”¨ "
+"如果为 [code]true[/code],该视å£å°†ç¦ç”¨ 3D 渲染。对于实际ç¦ç”¨ï¼Œä½¿ç”¨ "
"[code]usage[/code]。"
#: doc/classes/Viewport.xml
@@ -84438,24 +84585,24 @@ msgid ""
msgstr ""
"å¯ç”¨å¿«é€Ÿè¿‘似抗锯齿。FXAA æ˜¯ä¸€ç§æµè¡Œçš„å±å¹•空间抗锯齿方法,它的速度很快,但会使"
"图åƒçœ‹èµ·æ¥å¾ˆæ¨¡ç³Šï¼Œç‰¹åˆ«æ˜¯åœ¨è¾ƒä½Žçš„分辨率。在 1440p å’Œ 4K 这样的大分辨率下,它ä»"
-"ç„¶å¯ä»¥è¾ƒå¥½å·¥ä½œã€‚一些æŸå¤±çš„é”度å¯ä»¥é€šè¿‡å¯ç”¨å¯¹æ¯”度适应性é”åŒ–æ¥æ¢å¤ï¼Œå‚阅 "
-"[member sharpen_intensity]。"
+"ç„¶å¯ä»¥è¾ƒå¥½å·¥ä½œã€‚一些æŸå¤±çš„é”度å¯ä»¥é€šè¿‡å¯ç”¨å¯¹æ¯”度适应性é”åŒ–æ¥æ¢å¤ï¼ˆè§ [member "
+"sharpen_intensity])。"
#: doc/classes/Viewport.xml
msgid ""
"The global canvas transform of the viewport. The canvas transform is "
"relative to this."
-msgstr "è¯¥è§†çª—çš„å…¨å±€ç”»å¸ƒå˜æ¢ã€‚ç”»å¸ƒå˜æ¢æ˜¯ç›¸å¯¹äºŽè¿™ä¸ªçš„。"
+msgstr "该视å£çš„å…¨å±€ç”»å¸ƒå˜æ¢ã€‚ç”»å¸ƒå˜æ¢æ˜¯ç›¸å¯¹äºŽè¿™ä¸ªçš„。"
#: doc/classes/Viewport.xml
msgid "If [code]true[/code], the viewport will not receive input events."
-msgstr "如果为 [code]true[/code]ï¼Œè¯¥è§†çª—å°†ä¸æŽ¥æ”¶è¾“å…¥äº‹ä»¶ã€‚"
+msgstr "如果为 [code]true[/code],该视å£å°†ä¸æŽ¥æ”¶è¾“入事件。"
#: doc/classes/Viewport.xml
msgid ""
"If [code]true[/code], the GUI controls on the viewport will lay pixel "
"perfectly."
-msgstr "如果为 [code]true[/code],该视窗上的 GUI 控件将完美地放置åƒç´ ã€‚"
+msgstr "如果为 [code]true[/code],该视å£ä¸Šçš„ GUI 控件将完美地放置åƒç´ ã€‚"
#: doc/classes/Viewport.xml
msgid ""
@@ -84468,7 +84615,7 @@ msgid ""
"[constant USAGE_3D_NO_EFFECTS], since HDR is not supported for 2D.\n"
"[b]Note:[/b] Only available on the GLES3 backend."
msgstr ""
-"如果为 [code]true[/code],视窗的渲染将获益于高动æ€èŒƒå›´ç®—法。高动æ€èŒƒå›´å…许视"
+"如果为 [code]true[/code],视å£çš„æ¸²æŸ“将获益于高动æ€èŒƒå›´ç®—法。高动æ€èŒƒå›´å…许视"
"窗接收 0-1 范围以外的数值。在 Godot 中 HDR 默认使用åŠç²¾åº¦æµ®ç‚¹æ•°ï¼ˆ16 ä½ï¼‰ã€‚è¦"
"使用全精度浮点数(32 ä½ï¼‰ï¼Œè¯·å¯ç”¨ [member use_32_bpc_depth]。\n"
"[b]注æ„:[/b]需è¦å°† [member usage] 设置为 [constant USAGE_3D] 或 [constant "
@@ -84488,11 +84635,11 @@ msgid ""
"require input in linear color space!"
msgstr ""
"如果为 [code]true[/code],3D 渲染åŽçš„结果将ä¸ä¼šåº”用线性到 sRGB 的颜色转æ¢ã€‚当"
-"视窗被用作渲染目标时,这点很é‡è¦ï¼Œå› ä¸ºæ¸²æŸ“结果会被用作å¦ä¸€ä¸ªè§†çª—中渲染的 3D "
-"物体的纹ç†ã€‚如果视窗被用æ¥åˆ›å»ºä¸åŸºäºŽé¢œè‰²çš„æ•°æ®ï¼Œå™ªå£°ã€é«˜åº¦å›¾ã€é‡‡å›¾ç­‰ï¼Œè¿™ä¹Ÿå¾ˆ"
-"é‡è¦ã€‚当视窗被用作 2D å¯¹è±¡çš„çº¹ç†æ—¶ï¼Œæˆ–者视窗是你的最终输出时,请ä¸è¦å¯ç”¨è¿™ä¸ª"
+"视å£è¢«ç”¨ä½œæ¸²æŸ“目标时,这点很é‡è¦ï¼Œå› ä¸ºæ¸²æŸ“结果会被用作å¦ä¸€ä¸ªè§†çª—中渲染的 3D "
+"物体的纹ç†ã€‚如果视å£è¢«ç”¨æ¥åˆ›å»ºä¸åŸºäºŽé¢œè‰²çš„æ•°æ®ï¼Œå™ªå£°ã€é«˜åº¦å›¾ã€é‡‡å›¾ç­‰ï¼Œè¿™ä¹Ÿå¾ˆ"
+"é‡è¦ã€‚当视å£è¢«ç”¨ä½œ 2D å¯¹è±¡çš„çº¹ç†æ—¶ï¼Œæˆ–è€…è§†å£æ˜¯ä½ çš„æœ€ç»ˆè¾“出时,请ä¸è¦å¯ç”¨è¿™ä¸ª"
"功能。对于 GLES2 驱动æ¥è¯´ï¼Œè¿™å°†æŠŠ sRGB 输出转æ¢ä¸ºçº¿æ€§è¾“出,这应该åªç”¨äºŽéœ€è¦çº¿"
-"性色彩空间输入的VRæ’ä»¶!"
+"性色彩空间输入的 VR æ’ä»¶!"
#: doc/classes/Viewport.xml
msgid ""
@@ -84500,22 +84647,22 @@ msgid ""
"edges at the cost of significantly worse performance. A value of 4 is best "
"unless targeting very high-end systems."
msgstr ""
-"多é‡é‡‡æ ·æŠ—锯齿模å¼ã€‚一个较高的数字会使边缘更平滑,但代价是性能明显下é™ã€‚除éž"
-"是针对éžå¸¸é«˜ç«¯çš„系统,å¦åˆ™æ•°å€¼ä¸º4是最好的。"
+"多é‡é‡‡æ ·æŠ—锯齿模å¼ã€‚数字越高边缘越平滑,但代价是性能明显下é™ã€‚é™¤éžæ˜¯é’ˆå¯¹éžå¸¸"
+"高端的系统,å¦åˆ™æ•°å€¼ä¸º 4 是最好的。"
#: doc/classes/Viewport.xml
msgid ""
"If [code]true[/code], the viewport will use a unique copy of the [World] "
"defined in [member world]."
msgstr ""
-"如果为 [code]true[/code],该视窗将使用 [member world] 中定义的 [World] 的唯一"
+"如果为 [code]true[/code],该视å£å°†ä½¿ç”¨ [member world] 中定义的 [World] 的唯一"
"副本。"
#: doc/classes/Viewport.xml
msgid ""
"If [code]true[/code], the objects rendered by viewport become subjects of "
"mouse picking process."
-msgstr "如果为 [code]true[/code],该视窗渲染的对象将æˆä¸ºé¼ æ ‡æ‹¾å–过程的对象。"
+msgstr "如果为 [code]true[/code]ï¼Œè¯¥è§†å£æ¸²æŸ“的对象将æˆä¸ºé¼ æ ‡æ‹¾å–过程的对象。"
#: doc/classes/Viewport.xml
msgid ""
@@ -84526,7 +84673,7 @@ msgid ""
"information see [method VisualServer.viewport_set_render_direct_to_screen]."
msgstr ""
"如果为 [code]true[/code],会直接将该 Viewport 渲染到å±å¹•ä¸Šï¼Œè€Œä¸æ˜¯æ¸²æŸ“到根视"
-"窗上。åªåœ¨ GLES2 中å¯ç”¨ã€‚这是一个低级别的优化,在大多数情况下ä¸åº”该使用。如果"
+"å£ä¸Šã€‚åªåœ¨ GLES2 中å¯ç”¨ã€‚这是一个低级别的优化,在大多数情况下ä¸åº”该使用。如果"
"使用,从该 Viewport 或从 [code]SCREEN_TEXTURE[/code] 读å–å°†å˜å¾—ä¸å¯ç”¨ã€‚更多信"
"æ¯å‚阅 [method VisualServer.viewport_set_render_direct_to_screen]。"
@@ -84535,12 +84682,12 @@ msgid ""
"The clear mode when viewport used as a render target.\n"
"[b]Note:[/b] This property is intended for 2D usage."
msgstr ""
-"视窗用作渲染目标时的清除模å¼ã€‚\n"
+"视å£ç”¨ä½œæ¸²æŸ“目标时的清除模å¼ã€‚\n"
"[b]注æ„:[/b]此属性适用于 2D 使用。"
#: doc/classes/Viewport.xml
msgid "The update mode when viewport used as a render target."
-msgstr "视窗用作渲染目标时的更新模å¼ã€‚"
+msgstr "视å£ç”¨ä½œæ¸²æŸ“目标时的更新模å¼ã€‚"
#: doc/classes/Viewport.xml
msgid ""
@@ -84598,7 +84745,7 @@ msgid ""
"The width and height of viewport. Must be set to a value greater than or "
"equal to 2 pixels on both dimensions. Otherwise, nothing will be displayed."
msgstr ""
-"视窗的宽度和高度。必须在两个维度上设置为大于或等于 2 åƒç´ çš„值。å¦åˆ™ï¼Œå°†ä¸ä¼šæ˜¾"
+"视å£çš„宽度和高度。必须在两个维度上设置为大于或等于 2 åƒç´ çš„值。å¦åˆ™ï¼Œå°†ä¸ä¼šæ˜¾"
"示任何东西。"
#: doc/classes/Viewport.xml
@@ -84609,11 +84756,14 @@ 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
+#, fuzzy
msgid ""
-"The rendering mode of viewport.\n"
+"The viewport's rendering mode. This controls which buffers are allocated for "
+"the viewport (2D only, or 2D + 3D). 2D-only options can reduce memory usage "
+"and improve performance slightly, especially on low-end devices.\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."
@@ -84657,7 +84807,7 @@ msgid ""
"Emitted when the size of the viewport is changed, whether by [method "
"set_size_override], resize of window, or some other means."
msgstr ""
-"当视窗的大å°è¢«æ”¹å˜æ—¶ï¼Œæ— è®ºæ˜¯é€šè¿‡ [method set_size_override]ã€è°ƒæ•´çª—å£çš„大å°ï¼Œ"
+"当视å£çš„大å°è¢«æ”¹å˜æ—¶ï¼Œæ— è®ºæ˜¯é€šè¿‡ [method set_size_override]ã€è°ƒæ•´çª—å£çš„大å°ï¼Œ"
"还是其他方å¼ï¼Œéƒ½ä¼šè§¦å‘。"
#: doc/classes/Viewport.xml
@@ -84877,10 +85027,10 @@ msgid ""
"[b]Note:[/b] [member stretch] must be [code]true[/code] for this property to "
"work."
msgstr ""
-"å°†è§†çª—çš„æœ‰æ•ˆåˆ†è¾¨çŽ‡é™¤ä»¥è¿™ä¸ªå€¼ï¼ŒåŒæ—¶ä¿ç•™å…¶æ¯”例。这å¯ä»¥ç”¨æ¥åŠ å¿«æ¸²æŸ“é€Ÿåº¦ã€‚\n"
-"例如,一个1280×720的视窗,如果[member stretch_shrink]设置为[code]2[/code],将"
-"以640×360çš„å°ºå¯¸è¿›è¡Œæ¸²æŸ“ï¼ŒåŒæ—¶åœ¨å®¹å™¨ä¸­å æ®åŒæ ·çš„尺寸。\n"
-"[b]注æ„:[/b][member stretch]拉伸必须是[code]true[/code],这个属性æ‰èƒ½å‘挥作"
+"将视å£çš„æœ‰æ•ˆåˆ†è¾¨çŽ‡é™¤ä»¥è¿™ä¸ªå€¼ï¼ŒåŒæ—¶ä¿ç•™å…¶æ¯”例。这å¯ä»¥ç”¨æ¥åŠ å¿«æ¸²æŸ“é€Ÿåº¦ã€‚\n"
+"例如,将 1280×720 的视å£çš„ [member stretch_shrink] 设置为 [code]2[/code],将"
+"以 640×360 çš„å°ºå¯¸è¿›è¡Œæ¸²æŸ“ï¼ŒåŒæ—¶åœ¨å®¹å™¨ä¸­å æ®åŒæ ·çš„尺寸。\n"
+"[b]注æ„:[/b][member stretch] 必须是 [code]true[/code],这个属性æ‰èƒ½å‘挥作"
"用。"
#: doc/classes/ViewportTexture.xml
@@ -84945,27 +85095,27 @@ msgstr "返回由给定的 [enum Enabler] 叏釿 ‡è¯†çš„å¯ç”¨ç¨‹åºæ˜¯å¦å¤„äº
#: doc/classes/VisibilityEnabler.xml doc/classes/VisibilityEnabler2D.xml
msgid ""
"Sets active state of the enabler identified by given [enum Enabler] constant."
-msgstr "设置由给定的[enum Enabler]常é‡è¯†åˆ«çš„å¯ç”¨ç¨‹åºçš„æ´»åŠ¨çŠ¶æ€ã€‚"
+msgstr "设置由给定的 [enum Enabler] 常é‡è¯†åˆ«çš„å¯ç”¨ç¨‹åºçš„æ´»åŠ¨çŠ¶æ€ã€‚"
#: doc/classes/VisibilityEnabler.xml
msgid "If [code]true[/code], [RigidBody] nodes will be paused."
-msgstr "如果为 [code]true[/code],[RigidBody]节点将被暂åœã€‚"
+msgstr "如果为 [code]true[/code],[RigidBody] 节点将被暂åœã€‚"
#: doc/classes/VisibilityEnabler.xml doc/classes/VisibilityEnabler2D.xml
msgid "If [code]true[/code], [AnimationPlayer] nodes will be paused."
-msgstr "如果为 [code]true[/code],[AnimationPlayer]节点将被暂åœã€‚"
+msgstr "如果为 [code]true[/code],[AnimationPlayer] 节点将被暂åœã€‚"
#: doc/classes/VisibilityEnabler.xml doc/classes/VisibilityEnabler2D.xml
msgid "This enabler will pause [AnimationPlayer] nodes."
-msgstr "这个å¯ç”¨ç¨‹åºå°†æš‚åœ[AnimationPlayer]节点。"
+msgstr "这个å¯ç”¨ç¨‹åºå°†æš‚åœ [AnimationPlayer] 节点。"
#: doc/classes/VisibilityEnabler.xml
msgid "This enabler will freeze [RigidBody] nodes."
-msgstr "这个å¯ç”¨ç¨‹åºå°†å†»ç»“[RigidBody]节点。"
+msgstr "这个å¯ç”¨ç¨‹åºå°†å†»ç»“ [RigidBody] 节点。"
#: doc/classes/VisibilityEnabler.xml doc/classes/VisibilityEnabler2D.xml
msgid "Represents the size of the [enum Enabler] enum."
-msgstr "表示[enum Enabler]枚举的大å°ã€‚"
+msgstr "表示 [enum Enabler] 枚举的大å°ã€‚"
#: doc/classes/VisibilityEnabler2D.xml
msgid ""
@@ -84981,38 +85131,39 @@ msgid ""
"[b]Note:[/b] VisibilityEnabler2D will not affect nodes added after scene "
"initialization."
msgstr ""
-"VisibilityEnabler2D会在[RigidBody2D]ã€[AnimationPlayer]和其他节点ä¸å¯è§æ—¶ç¦ç”¨"
-"它们。它åªä¼šå½±å“与VisibilityEnabler2D的根节点相åŒçš„èŠ‚ç‚¹ï¼Œä»¥åŠæ ¹èŠ‚ç‚¹æœ¬èº«ã€‚\n"
-"å¦‚æžœä½ åªæƒ³æŽ¥æ”¶é€šçŸ¥ï¼Œè¯·ä½¿ç”¨[VisibilityNotifier2D]代替。\n"
-"[b]注æ„:[/b]由于性能原因,VisibilityEnabler2D使用一个近似的å¯å‘弿–¹æ³•,其精"
+"VisibilityEnabler2D 会在 [RigidBody2D]ã€[AnimationPlayer] 和其他节点ä¸å¯è§æ—¶"
+"ç¦ç”¨å®ƒä»¬ã€‚它åªä¼šå½±å“与 VisibilityEnabler2D 的根节点相åŒçš„èŠ‚ç‚¹ï¼Œä»¥åŠæ ¹èŠ‚ç‚¹æœ¬"
+"身。\n"
+"å¦‚æžœä½ åªæƒ³æŽ¥æ”¶é€šçŸ¥ï¼Œè¯·ä½¿ç”¨ [VisibilityNotifier2D] 代替。\n"
+"[b]注æ„:[/b]由于性能原因,VisibilityEnabler2D 使用一个近似的å¯å‘弿–¹æ³•,其精"
"度由 [member ProjectSettings.world/2d/cell_size] 决定。如果你需è¦ç²¾ç¡®çš„å¯è§æ€§"
-"检查,请使用å¦ä¸€ç§æ–¹æ³•,例如添加一个[Area2D]节点作为[Camera2D]节点的å­èŠ‚"
+"检查,请使用å¦ä¸€ç§æ–¹æ³•,例如添加一个 [Area2D] 节点作为 [Camera2D] 节点的å­èŠ‚"
"点。\n"
-"[b]注æ„:[/b]VisibilityEnabler2Dä¸ä¼šå½±å“场景åˆå§‹åŒ–åŽæ·»åŠ çš„èŠ‚ç‚¹ã€‚"
+"[b]注æ„:[/b]VisibilityEnabler2D ä¸ä¼šå½±å“场景åˆå§‹åŒ–åŽæ·»åŠ çš„èŠ‚ç‚¹ã€‚"
#: doc/classes/VisibilityEnabler2D.xml
msgid "If [code]true[/code], [RigidBody2D] nodes will be paused."
-msgstr "如果为 [code]true[/code],[RigidBody2D]节点将被暂åœã€‚"
+msgstr "如果为 [code]true[/code],[RigidBody2D] 节点将被暂åœã€‚"
#: doc/classes/VisibilityEnabler2D.xml
msgid "If [code]true[/code], [AnimatedSprite] nodes will be paused."
-msgstr "如果为 [code]true[/code],[AnimatedSprite]节点将被暂åœã€‚"
+msgstr "如果为 [code]true[/code],[AnimatedSprite] 节点将被暂åœã€‚"
#: doc/classes/VisibilityEnabler2D.xml
msgid "If [code]true[/code], [Particles2D] nodes will be paused."
-msgstr "如果为 [code]true[/code],[Particles2D]节点将被暂åœã€‚"
+msgstr "如果为 [code]true[/code],[Particles2D] 节点将被暂åœã€‚"
#: doc/classes/VisibilityEnabler2D.xml
msgid ""
"If [code]true[/code], the parent's [method Node._physics_process] will be "
"stopped."
msgstr ""
-"如果为 [code]true[/code],父级的[method Node._physics_process]å°†è¢«åœæ­¢ã€‚"
+"如果为 [code]true[/code],父级的 [method Node._physics_process] å°†è¢«åœæ­¢ã€‚"
#: doc/classes/VisibilityEnabler2D.xml
msgid ""
"If [code]true[/code], the parent's [method Node._process] will be stopped."
-msgstr "如果为 [code]true[/code],父级的[method Node._process]å°†è¢«åœæ­¢ã€‚"
+msgstr "如果为 [code]true[/code],父级的 [method Node._process] å°†è¢«åœæ­¢ã€‚"
#: doc/classes/VisibilityEnabler2D.xml
msgid "This enabler will freeze [RigidBody2D] nodes."
@@ -85075,7 +85226,7 @@ msgstr ""
#: doc/classes/VisibilityNotifier.xml
msgid "The VisibilityNotifier's bounding box."
-msgstr "VisibilityNotifier的边界框。"
+msgstr "VisibilityNotifier 的边界框。"
#: doc/classes/VisibilityNotifier.xml
msgid ""
@@ -85093,19 +85244,19 @@ msgstr ""
#: doc/classes/VisibilityNotifier.xml
msgid "Emitted when the VisibilityNotifier enters a [Camera]'s view."
-msgstr "当VisibilityNotifier进入[Camera]的视图时触å‘。"
+msgstr "当 VisibilityNotifier 进入 [Camera] 的视图时触å‘。"
#: doc/classes/VisibilityNotifier.xml
msgid "Emitted when the VisibilityNotifier exits a [Camera]'s view."
-msgstr "当VisibilityNotifier退出[Camera]的视图时触å‘。"
+msgstr "当 VisibilityNotifier 退出 [Camera] 的视图时触å‘。"
#: doc/classes/VisibilityNotifier.xml
msgid "Emitted when the VisibilityNotifier enters the screen."
-msgstr "当VisibilityNotifier进入å±å¹•时触å‘。"
+msgstr "当 VisibilityNotifier 进入å±å¹•时触å‘。"
#: doc/classes/VisibilityNotifier.xml
msgid "Emitted when the VisibilityNotifier exits the screen."
-msgstr "当VisibilityNotifier退出å±å¹•时触å‘。"
+msgstr "当 VisibilityNotifier 退出å±å¹•时触å‘。"
#: doc/classes/VisibilityNotifier2D.xml
msgid ""
@@ -85119,12 +85270,13 @@ msgid ""
"world/2d/cell_size]. If you need precise visibility checking, use another "
"method such as adding an [Area2D] node as a child of a [Camera2D] node."
msgstr ""
-"VisibilityNotifier2D检测它在å±å¹•上是å¦å¯è§ã€‚当它的边界矩形进入或退出å±å¹•或视"
-"窗时,它也会å‘出通知。\n"
-"如果你想让节点在退出å±å¹•时自动ç¦ç”¨ï¼Œè¯·ä½¿ç”¨[VisibilityEnabler2D]代替。\n"
-"[b]注æ„:[/b]由于性能原因,VisibilityNotifier2D使用一个近似的å¯å‘弿–¹æ³•,其精"
-"度由 [member ProjectSettings.world/2d/cell_size] 决定。如果你需è¦ç²¾ç¡®çš„å¯è§æ€§"
-"检查,请使用å¦ä¸€ç§æ–¹æ³•,如添加一个[Area2D]节点作为[Camera2D]节点的å­èŠ‚ç‚¹ã€‚"
+"VisibilityNotifier2D 检测它在å±å¹•上是å¦å¯è§ã€‚当它的边界矩形进入或退出å±å¹•或视"
+"壿—¶ï¼Œå®ƒä¹Ÿä¼šå‘出通知。\n"
+"如果你想让节点在退出å±å¹•时自动ç¦ç”¨ï¼Œè¯·ä½¿ç”¨ [VisibilityEnabler2D] 代替。\n"
+"[b]注æ„:[/b]由于性能原因,VisibilityNotifier2D 使用一个近似的å¯å‘弿–¹æ³•,其"
+"精度由 [member ProjectSettings.world/2d/cell_size] 决定。如果你需è¦ç²¾ç¡®çš„å¯è§"
+"性检查,请使用å¦ä¸€ç§æ–¹æ³•,如添加一个 [Area2D] 节点作为 [Camera2D] 节点的å­èŠ‚"
+"点。"
#: doc/classes/VisibilityNotifier2D.xml
msgid ""
@@ -85140,27 +85292,27 @@ msgstr ""
#: doc/classes/VisibilityNotifier2D.xml
msgid "The VisibilityNotifier2D's bounding rectangle."
-msgstr "VisibilityNotifier2D的边界矩形。"
+msgstr "VisibilityNotifier2D 的边界矩形。"
#: doc/classes/VisibilityNotifier2D.xml
msgid "Emitted when the VisibilityNotifier2D enters the screen."
-msgstr "当VisibilityNotifier2D进入å±å¹•时触å‘。"
+msgstr "当 VisibilityNotifier2D 进入å±å¹•时触å‘。"
#: doc/classes/VisibilityNotifier2D.xml
msgid "Emitted when the VisibilityNotifier2D exits the screen."
-msgstr "当VisibilityNotifier2D退出å±å¹•时触å‘。"
+msgstr "当 VisibilityNotifier2D 退出å±å¹•时触å‘。"
#: doc/classes/VisibilityNotifier2D.xml
msgid "Emitted when the VisibilityNotifier2D enters a [Viewport]'s view."
-msgstr "当VisibilityNotifier2D进入[Viewport]的视图时触å‘。"
+msgstr "当 VisibilityNotifier2D 进入 [Viewport] 的视图时触å‘。"
#: doc/classes/VisibilityNotifier2D.xml
msgid "Emitted when the VisibilityNotifier2D exits a [Viewport]'s view."
-msgstr "当VisibilityNotifier2D退出[Viewport]的视图时触å‘。"
+msgstr "当 VisibilityNotifier2D 退出 [Viewport] 的视图时触å‘。"
#: doc/classes/VisualInstance.xml
msgid "Parent of all visual 3D nodes."
-msgstr "所有å¯è§†3D节点的父节点。"
+msgstr "所有å¯è§† 3D 节点的父节点。"
#: doc/classes/VisualInstance.xml
msgid ""
@@ -85181,7 +85333,7 @@ msgid ""
"Returns the [AABB] (also known as the bounding box) for this "
"[VisualInstance]. See also [method get_transformed_aabb]."
msgstr ""
-"返回此[VisualInstance]çš„[AABB],也称为边界框。å‚阅[method "
+"返回此 [VisualInstance] çš„ [AABB],也称为边界框。å¦è¯·å‚阅 [method "
"get_transformed_aabb]。"
#: doc/classes/VisualInstance.xml
@@ -85190,8 +85342,8 @@ msgid ""
"example, if the Node is a [MeshInstance], this will return the RID of the "
"associated [Mesh]."
msgstr ""
-"返回与此[VisualInstance]相关的资æºçš„RID。例如,如果该节点是一个"
-"[MeshInstance],这将返回相关的[Mesh]的RID。"
+"返回与此 [VisualInstance] 相关的资æºçš„ RID。例如,如果该节点是一个 "
+"[MeshInstance],这将返回相关的 [Mesh] 的 RID。"
#: doc/classes/VisualInstance.xml
msgid ""
@@ -85199,9 +85351,9 @@ msgid ""
"by [method VisualServer.instance_create]. This RID is needed if you want to "
"call [VisualServer] functions directly on this [VisualInstance]."
msgstr ""
-"返回这个实例的RID。这个RID与[method VisualServer.instance_create]所返回的RID"
-"相åŒã€‚如果你想在这个[VisualInstance]上直接调用[VisualServer]函数,就需è¦è¿™ä¸ª"
-"RID。"
+"返回这个实例的 RID。这个 RID 与 [method VisualServer.instance_create] 所返回"
+"çš„ RID 相åŒã€‚如果你想在这个 [VisualInstance] 上直接调用 [VisualServer] 函数,"
+"就需è¦è¿™ä¸ª RID。"
#: doc/classes/VisualInstance.xml
msgid ""
@@ -85218,9 +85370,9 @@ 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 ""
-"返回此[VisualInstance]çš„å˜æ¢åŽçš„[AABB],也称为边界框。\n"
-"è¿™é‡Œçš„å˜æ¢æ˜¯æŒ‡[AABB]加上[Spatial]çš„[Transform]çš„ä½ç½®ã€æ—‹è½¬å’Œç¼©æ”¾ã€‚å‚阅"
-"[method get_aabb]。"
+"返回此 [VisualInstance] çš„å˜æ¢åŽçš„ [AABB],也称为边界框。\n"
+"è¿™é‡Œçš„å˜æ¢æ˜¯æŒ‡ [AABB] 加上 [Spatial] çš„ [Transform] çš„ä½ç½®ã€æ—‹è½¬å’Œç¼©æ”¾ã€‚å¦è¯·"
+"å‚阅 [method get_aabb]。"
#: doc/classes/VisualInstance.xml
msgid ""
@@ -85242,7 +85394,23 @@ msgid ""
"render object this [VisualInstance] is set to."
msgstr ""
"绘制此 [VisualInstance] 的渲染层。\n"
-"此对象仅对[Camera]å¯è§ï¼Œå…¶å‰”除é®ç½©åŒ…括此[VisualInstance]设置的渲染对象。"
+"此对象仅对 [Camera]å¯è§ï¼Œå…¶å‰”除é®ç½©åŒ…括此 [VisualInstance] 设置的渲染对象。"
+
+#: doc/classes/VisualInstance.xml
+msgid ""
+"The sorting offset used by this [VisualInstance]. Adjusting it to a higher "
+"value will make the [VisualInstance] reliably draw on top of other "
+"[VisualInstance]s that are otherwise positioned at the same spot."
+msgstr ""
+
+#: doc/classes/VisualInstance.xml
+msgid ""
+"If [code]true[/code], the object is sorted based on the [AABB] center. "
+"Sorted based on the global position otherwise.\n"
+"The [AABB] center based sorting is generally more accurate for 3D models. "
+"The position based sorting instead allows to better control the drawing "
+"order when working with [Particles] and [CPUParticles]."
+msgstr ""
#: modules/visual_script/doc_classes/VisualScript.xml
msgid "A script implemented in the Visual Script programming environment."
@@ -85320,13 +85488,13 @@ msgid ""
"[code]from_port[/code] would be fed into [code]to_node[/code]'s "
"[code]to_port[/code]."
msgstr ""
-"连接两个数æ®ç«¯å£ã€‚[code]from_node[/code]çš„[code]from_port[/code]的值将被输入"
-"[code]to_node[/code]的[code]to_port[/code]。"
+"连接两个数æ®ç«¯å£ã€‚[code]from_node[/code] çš„ [code]from_port[/code] 的值将被输"
+"入 [code]to_node[/code] 的 [code]to_port[/code]。"
#: modules/visual_script/doc_classes/VisualScript.xml
msgid ""
"Disconnect two data ports previously connected with [method data_connect]."
-msgstr "断开之å‰ç”¨[method data_connect]连接的两个数æ®ç«¯å£ã€‚"
+msgstr "断开之å‰ç”¨ [method data_connect] 连接的两个数æ®ç«¯å£ã€‚"
#: modules/visual_script/doc_classes/VisualScript.xml
msgid "Returns the id of a function's entry point node."
@@ -85346,7 +85514,7 @@ msgstr "è¿”å›žèŠ‚ç‚¹çš„åæ ‡ï¼Œå•使˜¯åƒç´ ã€‚"
#: modules/visual_script/doc_classes/VisualScript.xml
msgid "Returns the default (initial) value of a variable."
-msgstr "返回å˜é‡çš„åˆå§‹é»˜è®¤å€¼ã€‚"
+msgstr "返回å˜é‡çš„默认(åˆå§‹ï¼‰å€¼ã€‚"
#: modules/visual_script/doc_classes/VisualScript.xml
msgid "Returns whether a variable is exported."
@@ -85418,10 +85586,10 @@ msgid ""
"Unlike [method data_connect], there isn't a [code]to_port[/code], since the "
"target node can have only one sequence port."
msgstr ""
-"连接两个åºåˆ—端å£ã€‚执行将从[code]from_node[/code]çš„[code]from_output[/code]输"
-"入[code]to_node[/code]。\n"
-"与[method data_connect]ä¸åŒï¼Œæ²¡æœ‰[code]to_port[/code],因为目标节点åªèƒ½æœ‰ä¸€ä¸ª"
-"åºåˆ—端å£ã€‚"
+"连接两个åºåˆ—端å£ã€‚执行将从 [code]from_node[/code] çš„ [code]from_output[/"
+"code] 输入 [code]to_node[/code]。\n"
+"与 [method data_connect] ä¸åŒï¼Œæ²¡æœ‰ [code]to_port[/code],因为目标节点åªèƒ½æœ‰"
+"一个åºåˆ—端å£ã€‚"
#: modules/visual_script/doc_classes/VisualScript.xml
msgid ""
@@ -94604,8 +94772,8 @@ msgid ""
"scenario, a navigation map and a sound space. Spatial nodes register their "
"resources into the current world."
msgstr ""
-"拥有与世界相关的一切的类。物ç†ç©ºé—´ã€è§†è§‰åœºæ™¯ã€å¯¼èˆªåœ°å›¾å’Œå£°éŸ³ç©ºé—´ã€‚空间节点将"
-"å…¶èµ„æºæ³¨å†Œåˆ°å½“å‰ä¸–界中。"
+"拥有与世界相关的一切的类。物ç†ç©ºé—´ã€è§†è§‰åœºæ™¯ã€å¯¼èˆªåœ°å›¾å’Œå£°éŸ³ç©ºé—´ã€‚Spatial 节"
+"ç‚¹å°†å…¶èµ„æºæ³¨å†Œåˆ°å½“å‰ä¸–界中。"
#: doc/classes/World.xml
msgid ""
diff --git a/doc/translations/zh_TW.po b/doc/translations/zh_TW.po
index fb62e692a7..a64bd25054 100644
--- a/doc/translations/zh_TW.po
+++ b/doc/translations/zh_TW.po
@@ -4,7 +4,7 @@
# This file is distributed under the same license as the Godot source code.
#
# binotaliu <binota@protonmail.ch>, 2020.
-# BinotaLIU <me@binota.org>, 2020.
+# BinotaLIU <me@binota.org>, 2020, 2022.
# Eric K <eric900601@gmail.com>, 2020.
# Pierre Stempin <pierre.stempin@gmail.com>, 2020.
# Lihan Zhu <lihan@proctorio.com>, 2021.
@@ -19,8 +19,8 @@ msgid ""
msgstr ""
"Project-Id-Version: Godot Engine class reference\n"
"Report-Msgid-Bugs-To: https://github.com/godotengine/godot\n"
-"PO-Revision-Date: 2022-08-25 13:04+0000\n"
-"Last-Translator: Hugel <qihu@nfschina.com>\n"
+"PO-Revision-Date: 2022-10-12 06:50+0000\n"
+"Last-Translator: BinotaLIU <me@binota.org>\n"
"Language-Team: Chinese (Traditional) <https://hosted.weblate.org/projects/"
"godot-engine/godot-class-reference/zh_Hant/>\n"
"Language: zh_TW\n"
@@ -28,7 +28,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.14-dev\n"
+"X-Generator: Weblate 4.15-dev\n"
#: doc/tools/make_rst.py
msgid "Description"
@@ -88,7 +88,7 @@ msgstr ""
#: doc/tools/make_rst.py
msgid "Default"
-msgstr "默èª"
+msgstr "é è¨­"
#: doc/tools/make_rst.py
msgid "Setter"
@@ -120,7 +120,7 @@ msgstr ""
#: doc/tools/make_rst.py
msgid "This method is used to construct a type."
-msgstr "此方法用於構造類型。"
+msgstr "此方法用於建構型別。"
#: doc/tools/make_rst.py
msgid ""
@@ -570,7 +570,8 @@ msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
-"Returns an array of dictionaries representing the current call stack.\n"
+"Returns an array of dictionaries representing the current call stack. See "
+"also [method print_stack].\n"
"[codeblock]\n"
"func _ready():\n"
" foo()\n"
@@ -585,7 +586,11 @@ msgid ""
"[codeblock]\n"
"[{function:bar, line:12, source:res://script.gd}, {function:foo, line:9, "
"source:res://script.gd}, {function:_ready, line:6, source:res://script.gd}]\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] [method get_stack] only works if the running instance is "
+"connected to a debugging server (i.e. an editor instance). [method "
+"get_stack] will not work in projects exported in release mode, or in "
+"projects exported in debug mode if not connected to a debugging server."
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -965,12 +970,16 @@ msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
-"Prints a stack track at code location, only works when running with debugger "
-"turned on.\n"
+"Prints a stack trace at the current code location. See also [method "
+"get_stack].\n"
"Output in the console would look something like this:\n"
"[codeblock]\n"
"Frame 0 - res://test.gd:16 in function '_process'\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] [method print_stack] only works if the running instance is "
+"connected to a debugging server (i.e. an editor instance). [method "
+"print_stack] will not work in projects exported in release mode, or in "
+"projects exported in debug mode if not connected to a debugging server."
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -3589,6 +3598,26 @@ msgid "Hints that an image is compressed using lossless compression."
msgstr ""
#: doc/classes/@GlobalScope.xml
+msgid ""
+"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:\n"
+"[codeblock]\n"
+"hint_string = \"%s:\" % [TYPE_INT] # Array of inteters.\n"
+"hint_string = \"%s:%s:\" % [TYPE_ARRAY, TYPE_REAL] # Two-dimensional array "
+"of floats.\n"
+"hint_string = \"%s/%s:Resource\" % [TYPE_OBJECT, TYPE_OBJECT] # Array of "
+"resources.\n"
+"hint_string = \"%s:%s/%s:Resource\" % [TYPE_ARRAY, TYPE_OBJECT, TYPE_OBJECT] "
+"# Two-dimensional array of resources.\n"
+"[/codeblock]\n"
+"[b]Note:[/b] The final colon is required to specify for properly detecting "
+"built-in types."
+msgstr ""
+
+#: doc/classes/@GlobalScope.xml
msgid "The property is serialized and saved in the scene file (default)."
msgstr ""
@@ -4273,8 +4302,7 @@ msgstr ""
#: doc/classes/AudioStreamPlayer.xml doc/classes/Button.xml
#: doc/classes/CanvasLayer.xml doc/classes/CollisionShape2D.xml
#: doc/classes/ColorRect.xml doc/classes/Input.xml doc/classes/InputEvent.xml
-#: doc/classes/InputEventAction.xml doc/classes/Label.xml
-#: doc/classes/Particles2D.xml doc/classes/Timer.xml
+#: doc/classes/InputEventAction.xml doc/classes/Label.xml doc/classes/Timer.xml
#: doc/classes/VisibilityNotifier2D.xml
msgid "2D Dodge The Creeps Demo"
msgstr ""
@@ -7196,7 +7224,10 @@ msgid ""
"var array = []\n"
"array.resize(10)\n"
"array.fill(0) # Initialize the 10 elements to 0.\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Note:[/b] If [code]value[/code] is of a reference type ([Object]-derived, "
+"[Array], [Dictionary], etc.) then the array is filled with the references to "
+"the same object, i.e. no duplicates are created."
msgstr ""
#: doc/classes/Array.xml doc/classes/PoolByteArray.xml
@@ -7381,6 +7412,9 @@ msgstr ""
#: doc/classes/Array.xml
msgid ""
"Sorts the array.\n"
+"[b]Note:[/b] The sorting algorithm used is not [url=https://en.wikipedia.org/"
+"wiki/Sorting_algorithm#Stability]stable[/url]. This means that values "
+"considered equal may have their order changed when using [method sort].\n"
"[b]Note:[/b] Strings are sorted in alphabetical order (as opposed to natural "
"order). This may lead to unexpected behavior when sorting an array of "
"strings ending with a sequence of numbers. Consider the following example:\n"
@@ -7400,9 +7434,13 @@ msgid ""
"For two elements [code]a[/code] and [code]b[/code], if the given method "
"returns [code]true[/code], element [code]b[/code] will be after element "
"[code]a[/code] in the array.\n"
+"[b]Note:[/b] The sorting algorithm used is not [url=https://en.wikipedia.org/"
+"wiki/Sorting_algorithm#Stability]stable[/url]. This means that values "
+"considered equal may have their order changed when using [method "
+"sort_custom].\n"
"[b]Note:[/b] You cannot randomize the return value as the heapsort algorithm "
-"expects a deterministic result. Doing so will result in unexpected "
-"behavior.\n"
+"expects a deterministic result. Randomizing the return value will result in "
+"unexpected behavior.\n"
"[codeblock]\n"
"class MyCustomSorter:\n"
" static func sort_ascending(a, b):\n"
@@ -10041,10 +10079,9 @@ msgstr ""
#: doc/classes/AudioStreamGeneratorPlayback.xml
msgid ""
-"Returns the number of audio data frames left to play. If this returned "
-"number reaches [code]0[/code], the audio will stop playing until frames are "
-"added again. Therefore, make sure your script can always generate and push "
-"new audio frames fast enough to avoid audio cracking."
+"Returns the number of frames that can be pushed to the audio sample data "
+"buffer without overflowing it. If the result is [code]0[/code], the buffer "
+"is full."
msgstr ""
#: doc/classes/AudioStreamGeneratorPlayback.xml
@@ -10576,14 +10613,14 @@ msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
"Node for back-buffering the currently-displayed screen. The region defined "
-"in the BackBufferCopy node is buffered with the content of the screen it "
+"in the [BackBufferCopy] node is buffered with the content of the screen it "
"covers, or the entire screen according to the copy mode set. Use the "
"[code]texture(SCREEN_TEXTURE, ...)[/code] function in your shader scripts to "
"access the buffer.\n"
"[b]Note:[/b] Since this node inherits from [Node2D] (and not [Control]), "
"anchors and margins won't apply to child [Control]-derived nodes. This can "
"be problematic when resizing the window. To avoid this, add [Control]-"
-"derived nodes as [i]siblings[/i] to the BackBufferCopy node instead of "
+"derived nodes as [i]siblings[/i] to the [BackBufferCopy] node instead of "
"adding them as children."
msgstr ""
@@ -10593,22 +10630,22 @@ msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
-"The area covered by the BackBufferCopy. Only used if [member copy_mode] is "
+"The area covered by the [BackBufferCopy]. Only used if [member copy_mode] is "
"[constant COPY_MODE_RECT]."
msgstr ""
#: doc/classes/BackBufferCopy.xml
msgid ""
-"Disables the buffering mode. This means the BackBufferCopy node will "
+"Disables the buffering mode. This means the [BackBufferCopy] node will "
"directly use the portion of screen it covers."
msgstr ""
#: doc/classes/BackBufferCopy.xml
-msgid "BackBufferCopy buffers a rectangular region."
+msgid "[BackBufferCopy] buffers a rectangular region."
msgstr ""
#: doc/classes/BackBufferCopy.xml
-msgid "BackBufferCopy buffers the entire screen."
+msgid "[BackBufferCopy] buffers the entire screen."
msgstr ""
#: doc/classes/BakedLightmap.xml
@@ -19407,6 +19444,14 @@ msgid "Cylinder shape for collisions."
msgstr ""
#: doc/classes/CylinderShape.xml
+msgid ""
+"Cylinder shape for collisions.\n"
+"[b]Note:[/b] When using GodotPhysics instead of the default Bullet physics "
+"engine, there are several known bugs with cylinder collision shapes. Using "
+"[CapsuleShape] or [BoxShape] instead is recommended."
+msgstr ""
+
+#: doc/classes/CylinderShape.xml
msgid "The cylinder's height."
msgstr ""
@@ -22241,7 +22286,10 @@ msgid ""
"[/codeblock]\n"
"[b]Note:[/b] The script is run in the Editor context, which means the output "
"is visible in the console window started with the Editor (stdout) instead of "
-"the usual Godot [b]Output[/b] dock."
+"the usual Godot [b]Output[/b] dock.\n"
+"[b]Note:[/b] EditorScript is reference counted, meaning it is destroyed when "
+"nothing references it. This can cause errors during asynchronous operations "
+"if there are no references to the script."
msgstr ""
#: doc/classes/EditorScript.xml
@@ -32980,7 +33028,9 @@ msgid ""
"The size of the light in Godot units. Only considered in baked lightmaps and "
"only if [member light_bake_mode] is set to [constant BAKE_ALL]. Increasing "
"this value will make the shadows appear blurrier. This can be used to "
-"simulate area lights to an extent."
+"simulate area lights to an extent.\n"
+"[b]Note:[/b] [member light_size] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/Light.xml
@@ -36309,7 +36359,10 @@ msgid ""
"use the [method get_next_location] function once every physics frame to "
"update the internal path logic of the NavigationAgent. The returned vector "
"position from this function should be used as the next movement position for "
-"the agent's parent Node."
+"the agent's parent Node.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues."
msgstr ""
#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
@@ -36559,7 +36612,10 @@ msgid ""
"use the [method get_next_location] function once every physics frame to "
"update the internal path logic of the NavigationAgent. The returned vector "
"position from this function should be used as the next movement position for "
-"the agent's parent Node."
+"the agent's parent Node.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues."
msgstr ""
#: doc/classes/NavigationAgent2D.xml
@@ -37276,6 +37332,9 @@ msgid ""
"modified velocity as-is might lead to pushing and agent outside of a "
"navigable area. This is a limitation of the collision avoidance system, any "
"more complex situation may require the use of the physics engine.\n"
+"[b]Note:[/b] By default, the expensive calculations for avoidance are done "
+"in a thread. In HTML5 exports without thread support, they will be done on "
+"the main thread, which can lead to performance issues.\n"
"This server keeps tracks of any call and executes them during the sync "
"phase. This means that you can request any change to the map, using any "
"thread, without worrying."
@@ -40086,7 +40145,9 @@ msgid ""
"The light's radius. Note that the effectively lit area may appear to be "
"smaller depending on the [member omni_attenuation] in use. No matter the "
"[member omni_attenuation] in use, the light will never reach anything "
-"outside this radius."
+"outside this radius.\n"
+"[b]Note:[/b] [member omni_range] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -40602,11 +40663,11 @@ msgstr "å›žå‚³åƒæ•¸çš„æ­£åˆ‡å€¼ã€‚"
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] cache data directory according to the operating "
-"system's standards. On desktop platforms, this path can be overridden by "
-"setting the [code]XDG_CACHE_HOME[/code] environment variable before starting "
-"the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in "
-"Godot projects[/url] in the documentation for more information. See also "
-"[method get_config_dir] and [method get_data_dir].\n"
+"system's standards. On Linux, this path can be overridden by setting the "
+"[code]XDG_CACHE_HOME[/code] environment variable before starting the "
+"project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot "
+"projects[/url] in the documentation for more information. See also [method "
+"get_config_dir] and [method get_data_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -40640,11 +40701,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] user configuration directory according to the "
-"operating system's standards. On desktop platforms, this path can be "
-"overridden by setting the [code]XDG_CONFIG_HOME[/code] environment variable "
-"before starting the project. See [url=$DOCS_URL/tutorials/io/data_paths."
-"html]File paths in Godot projects[/url] in the documentation for more "
-"information. See also [method get_cache_dir] and [method get_data_dir].\n"
+"operating system's standards. On Linux, this path can be overridden by "
+"setting the [code]XDG_CONFIG_HOME[/code] environment variable before "
+"starting the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File "
+"paths in Godot projects[/url] in the documentation for more information. See "
+"also [method get_cache_dir] and [method get_data_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -40666,11 +40727,11 @@ msgstr ""
#: doc/classes/OS.xml
msgid ""
"Returns the [i]global[/i] user data directory according to the operating "
-"system's standards. On desktop platforms, this path can be overridden by "
-"setting the [code]XDG_DATA_HOME[/code] environment variable before starting "
-"the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in "
-"Godot projects[/url] in the documentation for more information. See also "
-"[method get_cache_dir] and [method get_config_dir].\n"
+"system's standards. On Linux, this path can be overridden by setting the "
+"[code]XDG_DATA_HOME[/code] environment variable before starting the project. "
+"See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot "
+"projects[/url] in the documentation for more information. See also [method "
+"get_cache_dir] and [method get_config_dir].\n"
"Not to be confused with [method get_user_data_dir], which returns the "
"[i]project-specific[/i] user data path."
msgstr ""
@@ -42532,6 +42593,16 @@ msgid "Particle systems (2D)"
msgstr ""
#: doc/classes/Particles2D.xml
+msgid "2D Particles Demo"
+msgstr ""
+
+#: doc/classes/Particles2D.xml
+msgid ""
+"2D Dodge The Creeps Demo (uses GPUParticles2D for the trail behind the "
+"player)"
+msgstr ""
+
+#: doc/classes/Particles2D.xml
msgid "Returns a rectangle containing the positions of all existing particles."
msgstr ""
@@ -50133,15 +50204,22 @@ msgstr ""
#: doc/classes/ProjectSettings.xml
msgid ""
"If [code]true[/code], uses a fast post-processing filter to make banding "
-"significantly less visible. In some cases, debanding may introduce a "
-"slightly noticeable dithering pattern. It's recommended to enable debanding "
-"only when actually needed since the dithering pattern will make lossless-"
-"compressed screenshots larger.\n"
+"significantly less visible in 3D. 2D rendering is [i]not[/i] affected by "
+"debanding unless the [member Environment.background_mode] is [constant "
+"Environment.BG_CANVAS]. In this case, [member rendering/quality/"
+"intended_usage/framebuffer_allocation] must also be set to [b]3D[/b].\n"
+"In some cases, debanding may introduce a slightly noticeable dithering "
+"pattern. It's recommended to enable debanding only when actually needed "
+"since the dithering pattern will make lossless-compressed screenshots "
+"larger.\n"
"[b]Note:[/b] Only available on the GLES3 backend. [member rendering/quality/"
"depth/hdr] must also be [code]true[/code] for debanding to be effective.\n"
"[b]Note:[/b] There are known issues with debanding breaking rendering on "
"mobile platforms. Due to this, it is recommended to leave this option "
-"disabled when targeting mobile platforms."
+"disabled when targeting mobile platforms.\n"
+"[b]Note:[/b] This property is only read when the project starts. To set "
+"debanding at run-time, set [member Viewport.debanding] on the root "
+"[Viewport] instead."
msgstr ""
#: doc/classes/ProjectSettings.xml
@@ -51738,17 +51816,28 @@ msgstr ""
#: modules/regex/doc_classes/RegEx.xml
msgid ""
"Searches the text for the compiled pattern. Returns a [RegExMatch] container "
-"of the first matching result if found, otherwise [code]null[/code]. The "
-"region to search within can be specified without modifying where the start "
-"and end anchor would be."
+"of the first matching result if found, otherwise [code]null[/code].\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegEx.xml
msgid ""
"Searches the text for the compiled pattern. Returns an array of [RegExMatch] "
"containers for each non-overlapping result. If no results were found, an "
-"empty array is returned instead. The region to search within can be "
-"specified without modifying where the start and end anchor would be."
+"empty array is returned instead.\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegEx.xml
@@ -51757,8 +51846,14 @@ msgid ""
"specified string. Escapes and backreferences such as [code]$1[/code] and "
"[code]$name[/code] are expanded and resolved. By default, only the first "
"instance is replaced, but it can be changed for all instances (global "
-"replacement). The region to search within can be specified without modifying "
-"where the start and end anchor would be."
+"replacement).\n"
+"The region to search within can be specified with [code]offset[/code] and "
+"[code]end[/code]. This is useful when searching for another match in the "
+"same [code]subject[/code] by calling this method again after a previous "
+"success. Setting these parameters differs from passing over a shortened "
+"string. For example, the start anchor [code]^[/code] is not affected by "
+"[code]offset[/code], and the character before [code]offset[/code] will be "
+"checked for the word boundary [code]\\b[/code]."
msgstr ""
#: modules/regex/doc_classes/RegExMatch.xml
@@ -54474,7 +54569,11 @@ msgid "Call a group immediately (calls are normally made on idle)."
msgstr ""
#: doc/classes/SceneTree.xml
-msgid "Call a group only once even if the call is executed many times."
+msgid ""
+"Call a group only once even if the call is executed many times.\n"
+"[b]Note:[/b] Arguments are not taken into account when deciding whether the "
+"call is unique or not. Therefore when the same method is called with "
+"different arguments, only the first call will be performed."
msgstr ""
#: doc/classes/SceneTree.xml
@@ -56312,7 +56411,9 @@ msgid ""
"[b]Note:[/b] Mixed negative scales in 3D are not decomposable from the "
"transformation matrix. Due to the way scale is represented with "
"transformation matrices in Godot, the scale values will either be all "
-"positive or all negative."
+"positive or all negative.\n"
+"[b]Note:[/b] Not all nodes are visually scaled by the [member scale] "
+"property. For example, [Light]s are not visually affected by [member scale]."
msgstr ""
#: doc/classes/Spatial.xml
@@ -57690,7 +57791,10 @@ msgid ""
msgstr ""
#: doc/classes/SpotLight.xml
-msgid "The spotlight's angle in degrees."
+msgid ""
+"The spotlight's angle in degrees.\n"
+"[b]Note:[/b] [member spot_angle] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/SpotLight.xml
@@ -57706,7 +57810,9 @@ msgid ""
"The maximal range that can be reached by the spotlight. Note that the "
"effectively lit area may appear to be smaller depending on the [member "
"spot_attenuation] in use. No matter the [member spot_attenuation] in use, "
-"the light will never reach anything outside this range."
+"the light will never reach anything outside this range.\n"
+"[b]Note:[/b] [member spot_range] is not affected by [member Spatial.scale] "
+"(the light's scale or its parent's scale)."
msgstr ""
#: doc/classes/SpringArm.xml
@@ -66994,10 +67100,15 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
"If [code]true[/code], uses a fast post-processing filter to make banding "
-"significantly less visible. In some cases, debanding may introduce a "
-"slightly noticeable dithering pattern. It's recommended to enable debanding "
-"only when actually needed since the dithering pattern will make lossless-"
-"compressed screenshots larger.\n"
+"significantly less visible in 3D. 2D rendering is [i]not[/i] affected by "
+"debanding unless the [member Environment.background_mode] is [constant "
+"Environment.BG_CANVAS]. In this case, [member usage] must also be set to "
+"[constant USAGE_3D]. See also [member ProjectSettings.rendering/quality/"
+"filters/use_debanding].\n"
+"In some cases, debanding may introduce a slightly noticeable dithering "
+"pattern. It's recommended to enable debanding only when actually needed "
+"since the dithering pattern will make lossless-compressed screenshots "
+"larger.\n"
"[b]Note:[/b] Only available on the GLES3 backend. [member hdr] must also be "
"[code]true[/code] for debanding to be effective."
msgstr ""
@@ -67008,8 +67119,8 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
-"If [code]true[/code], the viewport will disable 3D rendering. For actual "
-"disabling use [code]usage[/code]."
+"If [code]true[/code], the viewport will disable 3D rendering. To actually "
+"disable allocation of 3D buffers, set [member usage] instead."
msgstr ""
#: doc/classes/Viewport.xml
@@ -67161,7 +67272,9 @@ msgstr ""
#: doc/classes/Viewport.xml
msgid ""
-"The rendering mode of viewport.\n"
+"The viewport's rendering mode. This controls which buffers are allocated for "
+"the viewport (2D only, or 2D + 3D). 2D-only options can reduce memory usage "
+"and improve performance slightly, especially on low-end devices.\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."
@@ -67693,6 +67806,22 @@ msgid ""
"render object this [VisualInstance] is set to."
msgstr ""
+#: doc/classes/VisualInstance.xml
+msgid ""
+"The sorting offset used by this [VisualInstance]. Adjusting it to a higher "
+"value will make the [VisualInstance] reliably draw on top of other "
+"[VisualInstance]s that are otherwise positioned at the same spot."
+msgstr ""
+
+#: doc/classes/VisualInstance.xml
+msgid ""
+"If [code]true[/code], the object is sorted based on the [AABB] center. "
+"Sorted based on the global position otherwise.\n"
+"The [AABB] center based sorting is generally more accurate for 3D models. "
+"The position based sorting instead allows to better control the drawing "
+"order when working with [Particles] and [CPUParticles]."
+msgstr ""
+
#: modules/visual_script/doc_classes/VisualScript.xml
msgid "A script implemented in the Visual Script programming environment."
msgstr ""
diff --git a/drivers/SCsub b/drivers/SCsub
index 6cfcb1d18c..276b99e10b 100644
--- a/drivers/SCsub
+++ b/drivers/SCsub
@@ -24,7 +24,6 @@ SConscript("winmidi/SCsub")
# Graphics drivers
if env["vulkan"]:
- SConscript("spirv-reflect/SCsub")
SConscript("vulkan/SCsub")
if env["opengl3"]:
SConscript("gl_context/SCsub")
diff --git a/drivers/gl_context/SCsub b/drivers/gl_context/SCsub
index 7e8bd22960..2204c486c6 100644
--- a/drivers/gl_context/SCsub
+++ b/drivers/gl_context/SCsub
@@ -6,7 +6,7 @@ if env["platform"] in ["haiku", "macos", "windows", "linuxbsd"]:
# Thirdparty source files
thirdparty_dir = "#thirdparty/glad/"
thirdparty_sources = [
- "glad.c",
+ "gl.c",
]
thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources]
diff --git a/drivers/gles3/effects/copy_effects.cpp b/drivers/gles3/effects/copy_effects.cpp
index 3acbcf6b53..58cdc90a7c 100644
--- a/drivers/gles3/effects/copy_effects.cpp
+++ b/drivers/gles3/effects/copy_effects.cpp
@@ -115,13 +115,21 @@ CopyEffects::~CopyEffects() {
}
void CopyEffects::copy_to_rect(const Rect2 &p_rect) {
- copy.shader.version_bind_shader(copy.shader_version, CopyShaderGLES3::MODE_COPY_SECTION);
+ bool success = copy.shader.version_bind_shader(copy.shader_version, CopyShaderGLES3::MODE_COPY_SECTION);
+ if (!success) {
+ return;
+ }
+
copy.shader.version_set_uniform(CopyShaderGLES3::COPY_SECTION, p_rect.position.x, p_rect.position.y, p_rect.size.x, p_rect.size.y, copy.shader_version, CopyShaderGLES3::MODE_COPY_SECTION);
draw_screen_quad();
}
void CopyEffects::copy_screen() {
- copy.shader.version_bind_shader(copy.shader_version, CopyShaderGLES3::MODE_DEFAULT);
+ bool success = copy.shader.version_bind_shader(copy.shader_version, CopyShaderGLES3::MODE_DEFAULT);
+ if (!success) {
+ return;
+ }
+
draw_screen_triangle();
}
@@ -140,8 +148,8 @@ void CopyEffects::bilinear_blur(GLuint p_source_texture, int p_mipmap_count, con
dest_region.size.y = MAX(1, dest_region.size.y >> 1);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffers[i % 2]);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, p_source_texture, i);
- glBlitFramebuffer(source_region.position.x, source_region.position.y, source_region.size.x, source_region.size.y,
- dest_region.position.x, dest_region.position.y, dest_region.size.x, dest_region.size.y, GL_COLOR_BUFFER_BIT, GL_LINEAR);
+ glBlitFramebuffer(source_region.position.x, source_region.position.y, source_region.position.x + source_region.size.x, source_region.position.y + source_region.size.y,
+ dest_region.position.x, dest_region.position.y, dest_region.position.x + dest_region.size.x, dest_region.position.y + dest_region.size.y, GL_COLOR_BUFFER_BIT, GL_LINEAR);
glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffers[i % 2]);
source_region = dest_region;
}
@@ -151,7 +159,11 @@ void CopyEffects::bilinear_blur(GLuint p_source_texture, int p_mipmap_count, con
}
void CopyEffects::set_color(const Color &p_color, const Rect2i &p_region) {
- copy.shader.version_bind_shader(copy.shader_version, CopyShaderGLES3::MODE_SIMPLE_COLOR);
+ bool success = copy.shader.version_bind_shader(copy.shader_version, CopyShaderGLES3::MODE_SIMPLE_COLOR);
+ if (!success) {
+ return;
+ }
+
copy.shader.version_set_uniform(CopyShaderGLES3::COPY_SECTION, p_region.position.x, p_region.position.y, p_region.size.x, p_region.size.y, copy.shader_version, CopyShaderGLES3::MODE_SIMPLE_COLOR);
copy.shader.version_set_uniform(CopyShaderGLES3::COLOR_IN, p_color, copy.shader_version, CopyShaderGLES3::MODE_SIMPLE_COLOR);
draw_screen_quad();
diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp
index 0a64cda787..ecad4b66a5 100644
--- a/drivers/gles3/rasterizer_canvas_gles3.cpp
+++ b/drivers/gles3/rasterizer_canvas_gles3.cpp
@@ -41,6 +41,7 @@
#include "storage/config.h"
#include "storage/material_storage.h"
#include "storage/mesh_storage.h"
+#include "storage/particles_storage.h"
#include "storage/texture_storage.h"
void RasterizerCanvasGLES3::_update_transform_2d_to_mat4(const Transform2D &p_transform, float *p_mat4) {
@@ -105,6 +106,7 @@ void RasterizerCanvasGLES3::_update_transform_to_mat4(const Transform3D &p_trans
void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_item_list, const Color &p_modulate, Light *p_light_list, Light *p_directional_light_list, const Transform2D &p_canvas_transform, RS::CanvasItemTextureFilter p_default_filter, RS::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel, bool &r_sdf_used) {
GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton();
+ GLES3::MeshStorage *mesh_storage = GLES3::MeshStorage::get_singleton();
Transform2D canvas_transform_inverse = p_canvas_transform.affine_inverse();
@@ -310,9 +312,14 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_
Size2i ssize = texture_storage->render_target_get_size(p_to_render_target);
+ // If we've overridden the render target's color texture, then we need
+ // to invert the Y axis, so 2D texture appear right side up.
+ // We're probably rendering directly to an XR device.
+ float y_scale = texture_storage->render_target_get_override_color(p_to_render_target).is_valid() ? -2.0f : 2.0f;
+
Transform3D screen_transform;
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));
+ screen_transform.scale(Vector3(2.0f / ssize.width, y_scale / 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);
@@ -383,6 +390,7 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_
Rect2 back_buffer_rect;
bool backbuffer_copy = false;
bool backbuffer_gen_mipmaps = false;
+ bool update_skeletons = false;
Item *ci = p_item_list;
Item *canvas_group_owner = nullptr;
@@ -424,10 +432,29 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_
}
}
+ if (ci->skeleton.is_valid()) {
+ const Item::Command *c = ci->commands;
+
+ while (c) {
+ if (c->type == Item::Command::TYPE_MESH) {
+ const Item::CommandMesh *cm = static_cast<const Item::CommandMesh *>(c);
+ if (cm->mesh_instance.is_valid()) {
+ mesh_storage->mesh_instance_check_for_update(cm->mesh_instance);
+ update_skeletons = true;
+ }
+ }
+ c = c->next;
+ }
+ }
+
if (ci->canvas_group_owner != nullptr) {
if (canvas_group_owner == nullptr) {
+ if (update_skeletons) {
+ mesh_storage->update_mesh_instances();
+ update_skeletons = false;
+ }
// Canvas group begins here, render until before this item
- _render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list, starting_index, false);
+ _render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list, starting_index, r_sdf_used);
item_count = 0;
if (ci->canvas_group_owner->canvas_group->mode != RS::CANVAS_GROUP_MODE_TRANSPARENT) {
@@ -454,7 +481,11 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_
}
if (ci == canvas_group_owner) {
- _render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list, starting_index, true);
+ if (update_skeletons) {
+ mesh_storage->update_mesh_instances();
+ update_skeletons = false;
+ }
+ _render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list, starting_index, r_sdf_used, true);
item_count = 0;
if (ci->canvas_group->blur_mipmaps) {
@@ -467,9 +498,13 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_
}
if (backbuffer_copy) {
+ if (update_skeletons) {
+ mesh_storage->update_mesh_instances();
+ update_skeletons = false;
+ }
//render anything pending, including clearing if no items
- _render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list, starting_index, false);
+ _render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list, starting_index, r_sdf_used);
item_count = 0;
texture_storage->render_target_copy_to_back_buffer(p_to_render_target, back_buffer_rect, backbuffer_gen_mipmaps);
@@ -491,7 +526,11 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_
items[item_count++] = ci;
if (!ci->next || item_count == MAX_RENDER_ITEMS - 1) {
- _render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list, starting_index, false);
+ if (update_skeletons) {
+ mesh_storage->update_mesh_instances();
+ update_skeletons = false;
+ }
+ _render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list, starting_index, r_sdf_used);
//then reset
item_count = 0;
}
@@ -510,7 +549,7 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_
state.current_buffer = (state.current_buffer + 1) % state.canvas_instance_data_buffers.size();
}
-void RasterizerCanvasGLES3::_render_items(RID p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights, uint32_t &r_last_index, bool p_to_backbuffer) {
+void RasterizerCanvasGLES3::_render_items(RID p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights, uint32_t &r_last_index, bool &r_sdf_used, bool p_to_backbuffer) {
GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton();
canvas_begin(p_to_render_target, p_to_backbuffer);
@@ -529,9 +568,8 @@ void RasterizerCanvasGLES3::_render_items(RID p_to_render_target, int p_item_cou
_new_batch(batch_broken, index);
// Override the start position and index as we want to start from where we finished off last time.
- state.canvas_instance_batches[state.current_batch_index].start = r_last_index * sizeof(InstanceData);
+ state.canvas_instance_batches[state.current_batch_index].start = r_last_index;
index = 0;
- _align_instance_data_buffer(index);
for (int i = 0; i < p_item_count; i++) {
Item *ci = items[i];
@@ -549,10 +587,12 @@ void RasterizerCanvasGLES3::_render_items(RID p_to_render_target, int p_item_cou
material = default_clip_children_material;
}
} else {
- if (ci->canvas_group->mode == RS::CANVAS_GROUP_MODE_CLIP_ONLY) {
- material = default_clip_children_material;
- } else {
- material = default_canvas_group_material;
+ if (material.is_null()) {
+ if (ci->canvas_group->mode == RS::CANVAS_GROUP_MODE_CLIP_ONLY) {
+ material = default_clip_children_material;
+ } else {
+ material = default_canvas_group_material;
+ }
}
}
}
@@ -578,7 +618,7 @@ void RasterizerCanvasGLES3::_render_items(RID p_to_render_target, int p_item_cou
GLES3::CanvasShaderData::BlendMode blend_mode = shader_data_cache ? shader_data_cache->blend_mode : GLES3::CanvasShaderData::BLEND_MODE_MIX;
- _record_item_commands(ci, p_canvas_transform_inverse, current_clip, blend_mode, p_lights, index, batch_broken);
+ _record_item_commands(ci, p_to_render_target, p_canvas_transform_inverse, current_clip, blend_mode, p_lights, index, batch_broken, r_sdf_used);
}
if (index == 0) {
@@ -589,14 +629,14 @@ void RasterizerCanvasGLES3::_render_items(RID p_to_render_target, int p_item_cou
}
// Copy over all data needed for rendering.
- glBindBuffer(GL_UNIFORM_BUFFER, state.canvas_instance_data_buffers[state.current_buffer].ubo);
+ glBindBuffer(GL_ARRAY_BUFFER, state.canvas_instance_data_buffers[state.current_buffer].buffer);
#ifdef WEB_ENABLED
- glBufferSubData(GL_UNIFORM_BUFFER, r_last_index * sizeof(InstanceData), sizeof(InstanceData) * index, state.instance_data_array);
+ glBufferSubData(GL_ARRAY_BUFFER, r_last_index * sizeof(InstanceData), sizeof(InstanceData) * index, state.instance_data_array);
#else
// On Desktop and mobile we map the memory without synchronizing for maximum speed.
- void *ubo = glMapBufferRange(GL_UNIFORM_BUFFER, r_last_index * sizeof(InstanceData), index * sizeof(InstanceData), GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT);
- memcpy(ubo, state.instance_data_array, index * sizeof(InstanceData));
- glUnmapBuffer(GL_UNIFORM_BUFFER);
+ void *buffer = glMapBufferRange(GL_ARRAY_BUFFER, r_last_index * sizeof(InstanceData), index * sizeof(InstanceData), GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT);
+ memcpy(buffer, state.instance_data_array, index * sizeof(InstanceData));
+ glUnmapBuffer(GL_ARRAY_BUFFER);
#endif
glDisable(GL_SCISSOR_TEST);
@@ -623,7 +663,20 @@ void RasterizerCanvasGLES3::_render_items(RID p_to_render_target, int p_item_cou
uint64_t specialization = 0;
specialization |= uint64_t(state.canvas_instance_batches[i].lights_disabled);
specialization |= uint64_t(!GLES3::Config::get_singleton()->float_texture_supported) << 1;
- _bind_material(material_data, variant, specialization);
+ RID shader_version = data.canvas_shader_default_version;
+
+ if (material_data) {
+ if (material_data->shader_data->version.is_valid() && material_data->shader_data->valid) {
+ // Bind uniform buffer and textures
+ material_data->bind_uniforms();
+ shader_version = material_data->shader_data->version;
+ }
+ }
+
+ bool success = GLES3::MaterialStorage::get_singleton()->shaders.canvas_shader.version_bind_shader(shader_version, variant, specialization);
+ if (!success) {
+ continue;
+ }
GLES3::CanvasShaderData::BlendMode blend_mode = state.canvas_instance_batches[i].blend_mode;
@@ -707,7 +760,7 @@ void RasterizerCanvasGLES3::_render_items(RID p_to_render_target, int p_item_cou
r_last_index += index;
}
-void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, const Transform2D &p_canvas_transform_inverse, Item *&current_clip, GLES3::CanvasShaderData::BlendMode p_blend_mode, Light *p_lights, uint32_t &r_index, bool &r_batch_broken) {
+void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_render_target, const Transform2D &p_canvas_transform_inverse, Item *&current_clip, GLES3::CanvasShaderData::BlendMode p_blend_mode, Light *p_lights, uint32_t &r_index, bool &r_batch_broken, bool &r_sdf_used) {
RenderingServer::CanvasItemTextureFilter texture_filter = p_item->texture_filter == RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT ? state.default_filter : p_item->texture_filter;
if (texture_filter != state.canvas_instance_batches[state.current_batch_index].filter) {
@@ -1064,15 +1117,40 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, const Tran
state.canvas_instance_batches[state.current_batch_index].tex = m->texture;
_update_transform_2d_to_mat2x3(base_transform * draw_transform * m->transform, state.instance_data_array[r_index].world);
modulate = m->modulate;
+
} else if (c->type == Item::Command::TYPE_MULTIMESH) {
const Item::CommandMultiMesh *mm = static_cast<const Item::CommandMultiMesh *>(c);
state.canvas_instance_batches[state.current_batch_index].tex = mm->texture;
- uint32_t instance_count = GLES3::MeshStorage::get_singleton()->multimesh_get_instances_to_draw(mm->multimesh);
- if (instance_count > 1) {
- state.canvas_instance_batches[state.current_batch_index].shader_variant = CanvasShaderGLES3::MODE_INSTANCED;
- }
+ state.canvas_instance_batches[state.current_batch_index].shader_variant = CanvasShaderGLES3::MODE_INSTANCED;
+
} else if (c->type == Item::Command::TYPE_PARTICLES) {
- WARN_PRINT_ONCE("Particles not supported yet, sorry :(");
+ GLES3::ParticlesStorage *particles_storage = GLES3::ParticlesStorage::get_singleton();
+ GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
+
+ const Item::CommandParticles *pt = static_cast<const Item::CommandParticles *>(c);
+ RID particles = pt->particles;
+ state.canvas_instance_batches[state.current_batch_index].tex = pt->texture;
+ state.canvas_instance_batches[state.current_batch_index].shader_variant = CanvasShaderGLES3::MODE_INSTANCED;
+
+ if (particles_storage->particles_has_collision(particles) && texture_storage->render_target_is_sdf_enabled(p_render_target)) {
+ // Pass collision information.
+ Transform2D xform = p_item->final_transform;
+
+ GLuint sdf_texture = texture_storage->render_target_get_sdf_texture(p_render_target);
+
+ Rect2 to_screen;
+ {
+ Rect2 sdf_rect = texture_storage->render_target_get_sdf_rect(p_render_target);
+
+ to_screen.size = Vector2(1.0 / sdf_rect.size.width, 1.0 / sdf_rect.size.height);
+ to_screen.position = -sdf_rect.position * to_screen.size;
+ }
+
+ particles_storage->particles_set_canvas_sdf_collision(pt->particles, true, xform, to_screen, sdf_texture);
+ } else {
+ particles_storage->particles_set_canvas_sdf_collision(pt->particles, false, Transform2D(), Rect2(), 0);
+ }
+ r_sdf_used |= particles_storage->particles_has_collision(particles);
}
state.canvas_instance_batches[state.current_batch_index].command = c;
@@ -1142,26 +1220,15 @@ void RasterizerCanvasGLES3::_render_batch(Light *p_lights, uint32_t p_index) {
_bind_canvas_texture(state.canvas_instance_batches[p_index].tex, state.canvas_instance_batches[p_index].filter, state.canvas_instance_batches[p_index].repeat);
- // Bind the region of the UBO used by this batch.
- // If region exceeds the boundary of the UBO, just ignore.
- uint32_t range_bytes = data.max_instances_per_batch * sizeof(InstanceData);
- if (state.canvas_instance_batches[p_index].start >= (data.max_instances_per_ubo - 1) * sizeof(InstanceData)) {
- return;
- } else if (state.canvas_instance_batches[p_index].start >= (data.max_instances_per_ubo - data.max_instances_per_batch) * sizeof(InstanceData)) {
- // If we have less than a full batch at the end, we can just draw it anyway.
- // OpenGL will complain about the UBO being smaller than expected, but it should render fine.
- range_bytes = (data.max_instances_per_ubo - 1) * sizeof(InstanceData) - state.canvas_instance_batches[p_index].start;
- }
-
- uint32_t range_start = state.canvas_instance_batches[p_index].start;
- glBindBufferRange(GL_UNIFORM_BUFFER, INSTANCE_UNIFORM_LOCATION, state.canvas_instance_data_buffers[state.current_buffer].ubo, range_start, range_bytes);
-
switch (state.canvas_instance_batches[p_index].command_type) {
case Item::Command::TYPE_RECT:
case Item::Command::TYPE_NINEPATCH: {
glBindVertexArray(data.indexed_quad_array);
- glDrawElements(GL_TRIANGLES, state.canvas_instance_batches[p_index].instance_count * 6, GL_UNSIGNED_INT, 0);
- glBindBuffer(GL_UNIFORM_BUFFER, 0);
+ glBindBuffer(GL_ARRAY_BUFFER, state.canvas_instance_data_buffers[state.current_buffer].buffer);
+ uint32_t range_start = state.canvas_instance_batches[p_index].start * sizeof(InstanceData);
+ _enable_attributes(range_start, false);
+
+ glDrawElementsInstanced(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0, state.canvas_instance_batches[p_index].instance_count);
glBindVertexArray(0);
} break;
@@ -1173,18 +1240,21 @@ void RasterizerCanvasGLES3::_render_batch(Light *p_lights, uint32_t p_index) {
ERR_FAIL_COND(!pb);
glBindVertexArray(pb->vertex_array);
+ glBindBuffer(GL_ARRAY_BUFFER, state.canvas_instance_data_buffers[state.current_buffer].buffer);
+
+ uint32_t range_start = state.canvas_instance_batches[p_index].start * sizeof(InstanceData);
+ _enable_attributes(range_start, false);
if (pb->color_disabled && pb->color != Color(1.0, 1.0, 1.0, 1.0)) {
glVertexAttrib4f(RS::ARRAY_COLOR, pb->color.r, pb->color.g, pb->color.b, pb->color.a);
}
if (pb->index_buffer != 0) {
- glDrawElements(prim[polygon->primitive], pb->count, GL_UNSIGNED_INT, nullptr);
+ glDrawElementsInstanced(prim[polygon->primitive], pb->count, GL_UNSIGNED_INT, nullptr, 1);
} else {
- glDrawArrays(prim[polygon->primitive], 0, pb->count);
+ glDrawArraysInstanced(prim[polygon->primitive], 0, pb->count, 1);
}
glBindVertexArray(0);
- glBindBuffer(GL_UNIFORM_BUFFER, 0);
if (pb->color_disabled && pb->color != Color(1.0, 1.0, 1.0, 1.0)) {
// Reset so this doesn't pollute other draw calls.
@@ -1194,14 +1264,16 @@ void RasterizerCanvasGLES3::_render_batch(Light *p_lights, uint32_t p_index) {
case Item::Command::TYPE_PRIMITIVE: {
glBindVertexArray(data.canvas_quad_array);
+ glBindBuffer(GL_ARRAY_BUFFER, state.canvas_instance_data_buffers[state.current_buffer].buffer);
+ uint32_t range_start = state.canvas_instance_batches[p_index].start * sizeof(InstanceData);
+ _enable_attributes(range_start, true);
+
const GLenum primitive[5] = { GL_POINTS, GL_POINTS, GL_LINES, GL_TRIANGLES, GL_TRIANGLES };
int instance_count = state.canvas_instance_batches[p_index].instance_count;
- if (instance_count > 1) {
+ ERR_FAIL_COND(instance_count <= 0);
+ if (instance_count >= 1) {
glDrawArraysInstanced(primitive[state.canvas_instance_batches[p_index].primitive_points], 0, state.canvas_instance_batches[p_index].primitive_points, instance_count);
- } else {
- glDrawArrays(primitive[state.canvas_instance_batches[p_index].primitive_points], 0, state.canvas_instance_batches[p_index].primitive_points);
}
- glBindBuffer(GL_UNIFORM_BUFFER, 0);
} break;
@@ -1209,20 +1281,21 @@ void RasterizerCanvasGLES3::_render_batch(Light *p_lights, uint32_t p_index) {
case Item::Command::TYPE_MULTIMESH:
case Item::Command::TYPE_PARTICLES: {
GLES3::MeshStorage *mesh_storage = GLES3::MeshStorage::get_singleton();
+ GLES3::ParticlesStorage *particles_storage = GLES3::ParticlesStorage::get_singleton();
RID mesh;
RID mesh_instance;
- RID texture;
uint32_t instance_count = 1;
- GLuint multimesh_buffer = 0;
- uint32_t multimesh_stride = 0;
- uint32_t multimesh_color_offset = 0;
- bool multimesh_uses_color = false;
- bool multimesh_uses_custom_data = false;
+ GLuint instance_buffer = 0;
+ uint32_t instance_stride = 0;
+ uint32_t instance_color_offset = 0;
+ bool instance_uses_color = false;
+ bool instance_uses_custom_data = false;
if (state.canvas_instance_batches[p_index].command_type == Item::Command::TYPE_MESH) {
const Item::CommandMesh *m = static_cast<const Item::CommandMesh *>(state.canvas_instance_batches[p_index].command);
mesh = m->mesh;
mesh_instance = m->mesh_instance;
+
} else if (state.canvas_instance_batches[p_index].command_type == Item::Command::TYPE_MULTIMESH) {
const Item::CommandMultiMesh *mm = static_cast<const Item::CommandMultiMesh *>(state.canvas_instance_batches[p_index].command);
RID multimesh = mm->multimesh;
@@ -1238,13 +1311,37 @@ void RasterizerCanvasGLES3::_render_batch(Light *p_lights, uint32_t p_index) {
break;
}
- multimesh_buffer = mesh_storage->multimesh_get_gl_buffer(multimesh);
- multimesh_stride = mesh_storage->multimesh_get_stride(multimesh);
- multimesh_color_offset = mesh_storage->multimesh_get_color_offset(multimesh);
- multimesh_uses_color = mesh_storage->multimesh_uses_colors(multimesh);
- multimesh_uses_custom_data = mesh_storage->multimesh_uses_custom_data(multimesh);
+ instance_buffer = mesh_storage->multimesh_get_gl_buffer(multimesh);
+ instance_stride = mesh_storage->multimesh_get_stride(multimesh);
+ instance_color_offset = mesh_storage->multimesh_get_color_offset(multimesh);
+ instance_uses_color = mesh_storage->multimesh_uses_colors(multimesh);
+ instance_uses_custom_data = mesh_storage->multimesh_uses_custom_data(multimesh);
+
} else if (state.canvas_instance_batches[p_index].command_type == Item::Command::TYPE_PARTICLES) {
- // Do nothing for now.
+ const Item::CommandParticles *pt = static_cast<const Item::CommandParticles *>(state.canvas_instance_batches[p_index].command);
+ RID particles = pt->particles;
+ mesh = particles_storage->particles_get_draw_pass_mesh(particles, 0);
+
+ ERR_BREAK(particles_storage->particles_get_mode(particles) != RS::PARTICLES_MODE_2D);
+ particles_storage->particles_request_process(particles);
+
+ if (particles_storage->particles_is_inactive(particles)) {
+ break;
+ }
+
+ RenderingServerDefault::redraw_request(); // Active particles means redraw request.
+
+ int dpc = particles_storage->particles_get_draw_passes(particles);
+ if (dpc == 0) {
+ break; // Nothing to draw.
+ }
+
+ instance_count = particles_storage->particles_get_amount(particles);
+ instance_buffer = particles_storage->particles_get_gl_buffer(particles);
+ instance_stride = 12; // 8 bytes for instance transform and 4 bytes for packed color and custom.
+ instance_color_offset = 8; // 8 bytes for instance transform.
+ instance_uses_color = true;
+ instance_uses_custom_data = true;
}
ERR_FAIL_COND(mesh.is_null());
@@ -1270,43 +1367,44 @@ void RasterizerCanvasGLES3::_render_batch(Light *p_lights, uint32_t p_index) {
index_array_gl = mesh_storage->mesh_surface_get_index_buffer(surface, 0);
bool use_index_buffer = false;
glBindVertexArray(vertex_array_gl);
+ glBindBuffer(GL_ARRAY_BUFFER, state.canvas_instance_data_buffers[state.current_buffer].buffer);
+
+ uint32_t range_start = state.canvas_instance_batches[p_index].start * sizeof(InstanceData);
+ _enable_attributes(range_start, false, instance_count);
+
if (index_array_gl != 0) {
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_array_gl);
use_index_buffer = true;
}
if (instance_count > 1) {
+ if (instance_buffer == 0) {
+ break;
+ }
// Bind instance buffers.
- glBindBuffer(GL_ARRAY_BUFFER, multimesh_buffer);
+ glBindBuffer(GL_ARRAY_BUFFER, instance_buffer);
glEnableVertexAttribArray(1);
- glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, multimesh_stride * sizeof(float), CAST_INT_TO_UCHAR_PTR(0));
+ glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, instance_stride * sizeof(float), CAST_INT_TO_UCHAR_PTR(0));
glVertexAttribDivisor(1, 1);
glEnableVertexAttribArray(2);
- glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, multimesh_stride * sizeof(float), CAST_INT_TO_UCHAR_PTR(4 * 4));
+ glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, instance_stride * sizeof(float), CAST_INT_TO_UCHAR_PTR(4 * 4));
glVertexAttribDivisor(2, 1);
- if (multimesh_uses_color || multimesh_uses_custom_data) {
+ if (instance_uses_color || instance_uses_custom_data) {
glEnableVertexAttribArray(5);
- glVertexAttribIPointer(5, 4, GL_UNSIGNED_INT, multimesh_stride * sizeof(float), CAST_INT_TO_UCHAR_PTR(multimesh_color_offset * sizeof(float)));
+ glVertexAttribIPointer(5, 4, GL_UNSIGNED_INT, instance_stride * sizeof(float), CAST_INT_TO_UCHAR_PTR(instance_color_offset * sizeof(float)));
glVertexAttribDivisor(5, 1);
}
}
GLenum primitive_gl = prim[int(primitive)];
- if (instance_count == 1) {
- if (use_index_buffer) {
- glDrawElements(primitive_gl, mesh_storage->mesh_surface_get_vertices_drawn_count(surface), mesh_storage->mesh_surface_get_index_type(surface), 0);
- } else {
- glDrawArrays(primitive_gl, 0, mesh_storage->mesh_surface_get_vertices_drawn_count(surface));
- }
- } else if (instance_count > 1) {
- 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 {
- glDrawArraysInstanced(primitive_gl, 0, mesh_storage->mesh_surface_get_vertices_drawn_count(surface), instance_count);
- }
- }
+ 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 {
+ glDrawArraysInstanced(primitive_gl, 0, mesh_storage->mesh_surface_get_vertices_drawn_count(surface), instance_count);
+ }
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
if (instance_count > 1) {
glDisableVertexAttribArray(5);
@@ -1326,7 +1424,7 @@ void RasterizerCanvasGLES3::_render_batch(Light *p_lights, uint32_t p_index) {
}
void RasterizerCanvasGLES3::_add_to_batch(uint32_t &r_index, bool &r_batch_broken) {
- if (r_index >= data.max_instances_per_ubo - 1) {
+ if (r_index >= data.max_instances_per_buffer - 1) {
ERR_PRINT_ONCE("Trying to draw too many items. Please increase maximum number of items in the project settings 'rendering/gl_compatibility/item_buffer_size'");
return;
}
@@ -1354,27 +1452,25 @@ void RasterizerCanvasGLES3::_new_batch(bool &r_batch_broken, uint32_t &r_index)
// Copy the properties of the current batch, we will manually update the things that changed.
Batch new_batch = state.canvas_instance_batches[state.current_batch_index];
new_batch.instance_count = 0;
- new_batch.start = state.canvas_instance_batches[state.current_batch_index].start + state.canvas_instance_batches[state.current_batch_index].instance_count * sizeof(InstanceData);
+ new_batch.start = state.canvas_instance_batches[state.current_batch_index].start + state.canvas_instance_batches[state.current_batch_index].instance_count;
state.current_batch_index++;
state.canvas_instance_batches.push_back(new_batch);
- _align_instance_data_buffer(r_index);
}
-void RasterizerCanvasGLES3::_bind_material(GLES3::CanvasMaterialData *p_material_data, CanvasShaderGLES3::ShaderVariant p_variant, uint64_t p_specialization) {
- if (p_material_data) {
- if (p_material_data->shader_data->version.is_valid() && p_material_data->shader_data->valid) {
- // Bind uniform buffer and textures
- p_material_data->bind_uniforms();
- GLES3::MaterialStorage::get_singleton()->shaders.canvas_shader.version_bind_shader(p_material_data->shader_data->version, p_variant, p_specialization);
- } else {
- GLES3::MaterialStorage::get_singleton()->shaders.canvas_shader.version_bind_shader(data.canvas_shader_default_version, p_variant, p_specialization);
- }
- } else {
- GLES3::MaterialStorage::get_singleton()->shaders.canvas_shader.version_bind_shader(data.canvas_shader_default_version, p_variant, p_specialization);
+void RasterizerCanvasGLES3::_enable_attributes(uint32_t p_start, bool p_primitive, uint32_t p_rate) {
+ uint32_t split = p_primitive ? 11 : 12;
+ for (uint32_t i = 6; i < split; i++) {
+ glEnableVertexAttribArray(i);
+ glVertexAttribPointer(i, 4, GL_FLOAT, GL_FALSE, sizeof(InstanceData), CAST_INT_TO_UCHAR_PTR(p_start + (i - 6) * 4 * sizeof(float)));
+ glVertexAttribDivisor(i, p_rate);
+ }
+ for (uint32_t i = split; i <= 13; i++) {
+ glEnableVertexAttribArray(i);
+ glVertexAttribIPointer(i, 4, GL_UNSIGNED_INT, sizeof(InstanceData), CAST_INT_TO_UCHAR_PTR(p_start + (i - 6) * 4 * sizeof(float)));
+ glVertexAttribDivisor(i, p_rate);
}
}
-
RID RasterizerCanvasGLES3::light_create() {
CanvasLight canvas_light;
return canvas_light_owner.make_rid(canvas_light);
@@ -1435,7 +1531,10 @@ void RasterizerCanvasGLES3::light_update_shadow(RID p_rid, int p_shadow_index, c
RS::CanvasOccluderPolygonCullMode cull_mode = RS::CANVAS_OCCLUDER_POLYGON_CULL_DISABLED;
CanvasOcclusionShaderGLES3::ShaderVariant variant = config->float_texture_supported ? CanvasOcclusionShaderGLES3::MODE_SHADOW : CanvasOcclusionShaderGLES3::MODE_SHADOW_RGBA;
- shadow_render.shader.version_bind_shader(shadow_render.shader_version, variant);
+ bool success = shadow_render.shader.version_bind_shader(shadow_render.shader_version, variant);
+ if (!success) {
+ return;
+ }
for (int i = 0; i < 4; i++) {
glViewport((state.shadow_texture_size / 4) * i, p_shadow_index * 2, (state.shadow_texture_size / 4), 2);
@@ -1553,7 +1652,10 @@ void RasterizerCanvasGLES3::light_update_directional_shadow(RID p_rid, int p_sha
RS::CanvasOccluderPolygonCullMode cull_mode = RS::CANVAS_OCCLUDER_POLYGON_CULL_DISABLED;
CanvasOcclusionShaderGLES3::ShaderVariant variant = config->float_texture_supported ? CanvasOcclusionShaderGLES3::MODE_SHADOW : CanvasOcclusionShaderGLES3::MODE_SHADOW_RGBA;
- shadow_render.shader.version_bind_shader(shadow_render.shader_version, variant);
+ bool success = shadow_render.shader.version_bind_shader(shadow_render.shader_version, variant);
+ if (!success) {
+ return;
+ }
Projection projection;
projection.set_orthogonal(-half_size, half_size, -0.5, 0.5, 0.0, distance);
@@ -1685,7 +1787,10 @@ void RasterizerCanvasGLES3::render_sdf(RID p_render_target, LightOccluderInstanc
glClear(GL_COLOR_BUFFER_BIT);
CanvasOcclusionShaderGLES3::ShaderVariant variant = CanvasOcclusionShaderGLES3::MODE_SDF;
- shadow_render.shader.version_bind_shader(shadow_render.shader_version, variant);
+ bool success = shadow_render.shader.version_bind_shader(shadow_render.shader_version, variant);
+ if (!success) {
+ return;
+ }
shadow_render.shader.version_set_uniform(CanvasOcclusionShaderGLES3::PROJECTION, Projection(), shadow_render.shader_version, variant);
shadow_render.shader.version_set_uniform(CanvasOcclusionShaderGLES3::DIRECTION, 0.0, 0.0, shadow_render.shader_version, variant);
@@ -1990,6 +2095,9 @@ void RasterizerCanvasGLES3::_bind_canvas_texture(RID p_texture, RS::CanvasItemTe
if (t) {
ERR_FAIL_COND(!t->canvas_texture);
ct = t->canvas_texture;
+ if (t->render_target) {
+ t->render_target->used_in_frame = true;
+ }
} else {
ct = texture_storage->get_canvas_texture(p_texture);
}
@@ -2017,6 +2125,9 @@ void RasterizerCanvasGLES3::_bind_canvas_texture(RID p_texture, RS::CanvasItemTe
glBindTexture(GL_TEXTURE_2D, texture->tex_id);
texture->gl_set_filter(filter);
texture->gl_set_repeat(repeat);
+ if (texture->render_target) {
+ texture->render_target->used_in_frame = true;
+ }
}
GLES3::Texture *normal_map = texture_storage->get_texture(ct->normal_map);
@@ -2030,6 +2141,9 @@ void RasterizerCanvasGLES3::_bind_canvas_texture(RID p_texture, RS::CanvasItemTe
glBindTexture(GL_TEXTURE_2D, normal_map->tex_id);
normal_map->gl_set_filter(filter);
normal_map->gl_set_repeat(repeat);
+ if (normal_map->render_target) {
+ normal_map->render_target->used_in_frame = true;
+ }
}
GLES3::Texture *specular_map = texture_storage->get_texture(ct->specular);
@@ -2043,6 +2157,9 @@ void RasterizerCanvasGLES3::_bind_canvas_texture(RID p_texture, RS::CanvasItemTe
glBindTexture(GL_TEXTURE_2D, specular_map->tex_id);
specular_map->gl_set_filter(filter);
specular_map->gl_set_repeat(repeat);
+ if (specular_map->render_target) {
+ specular_map->render_target->used_in_frame = true;
+ }
}
}
@@ -2304,8 +2421,8 @@ void RasterizerCanvasGLES3::_allocate_instance_data_buffer() {
GLuint new_buffers[3];
glGenBuffers(3, new_buffers);
// Batch UBO.
- glBindBuffer(GL_UNIFORM_BUFFER, new_buffers[0]);
- glBufferData(GL_UNIFORM_BUFFER, data.max_instance_buffer_size, nullptr, GL_STREAM_DRAW);
+ glBindBuffer(GL_ARRAY_BUFFER, new_buffers[0]);
+ glBufferData(GL_ARRAY_BUFFER, data.max_instance_buffer_size, nullptr, GL_STREAM_DRAW);
// Light uniform buffer.
glBindBuffer(GL_UNIFORM_BUFFER, new_buffers[1]);
glBufferData(GL_UNIFORM_BUFFER, sizeof(LightUniform) * data.max_lights_per_render, nullptr, GL_STREAM_DRAW);
@@ -2315,36 +2432,16 @@ void RasterizerCanvasGLES3::_allocate_instance_data_buffer() {
state.current_buffer = (state.current_buffer + 1);
DataBuffer db;
- db.ubo = new_buffers[0];
+ db.buffer = new_buffers[0];
db.light_ubo = new_buffers[1];
db.state_ubo = new_buffers[2];
db.last_frame_used = RSG::rasterizer->get_frame_number();
state.canvas_instance_data_buffers.insert(state.current_buffer, db);
state.current_buffer = state.current_buffer % state.canvas_instance_data_buffers.size();
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_UNIFORM_BUFFER, 0);
}
-// Batch start positions need to be aligned to the device's GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT.
-// This needs to be called anytime a new batch is created.
-void RasterizerCanvasGLES3::_align_instance_data_buffer(uint32_t &r_index) {
- if (GLES3::Config::get_singleton()->uniform_buffer_offset_alignment > int(sizeof(InstanceData))) {
- uint32_t offset = state.canvas_instance_batches[state.current_batch_index].start % GLES3::Config::get_singleton()->uniform_buffer_offset_alignment;
- if (offset > 0) {
- // uniform_buffer_offset_alignment can be 4, 16, 32, or 256. Our instance batches are 128 bytes.
- // Accordingly, this branch is only triggered if we are 128 bytes off.
- uint32_t offset_bytes = GLES3::Config::get_singleton()->uniform_buffer_offset_alignment - offset;
- state.canvas_instance_batches[state.current_batch_index].start += offset_bytes;
- // Offset the instance array so it stays in sync with batch start points.
- // This creates gaps in the instance buffer with wasted space, but we can't help it.
- r_index += offset_bytes / sizeof(InstanceData);
- if (r_index > 0) {
- // In this case we need to copy over the basic data.
- state.instance_data_array[r_index] = state.instance_data_array[r_index - 1];
- }
- }
- }
-}
-
void RasterizerCanvasGLES3::set_time(double p_time) {
state.time = p_time;
}
@@ -2489,12 +2586,12 @@ RasterizerCanvasGLES3::RasterizerCanvasGLES3() {
data.max_instances_per_batch = 128;
} else {
data.max_lights_per_render = 256;
- data.max_instances_per_batch = 512;
+ data.max_instances_per_batch = 2048;
}
// Reserve 3 Uniform Buffers for instance data Frame N, N+1 and N+2
- data.max_instances_per_ubo = MAX(data.max_instances_per_batch, uint32_t(GLOBAL_GET("rendering/gl_compatibility/item_buffer_size")));
- data.max_instance_buffer_size = data.max_instances_per_ubo * sizeof(InstanceData); // 16,384 instances * 128 bytes = 2,097,152 bytes = 2,048 kb
+ data.max_instances_per_buffer = MAX(data.max_instances_per_batch, uint32_t(GLOBAL_GET("rendering/gl_compatibility/item_buffer_size")));
+ data.max_instance_buffer_size = data.max_instances_per_buffer * sizeof(InstanceData); // 16,384 instances * 128 bytes = 2,097,152 bytes = 2,048 kb
state.canvas_instance_data_buffers.resize(3);
state.canvas_instance_batches.reserve(200);
@@ -2502,8 +2599,8 @@ RasterizerCanvasGLES3::RasterizerCanvasGLES3() {
GLuint new_buffers[3];
glGenBuffers(3, new_buffers);
// Batch UBO.
- glBindBuffer(GL_UNIFORM_BUFFER, new_buffers[0]);
- glBufferData(GL_UNIFORM_BUFFER, data.max_instance_buffer_size, nullptr, GL_STREAM_DRAW);
+ glBindBuffer(GL_ARRAY_BUFFER, new_buffers[0]);
+ glBufferData(GL_ARRAY_BUFFER, data.max_instance_buffer_size, nullptr, GL_STREAM_DRAW);
// Light uniform buffer.
glBindBuffer(GL_UNIFORM_BUFFER, new_buffers[1]);
glBufferData(GL_UNIFORM_BUFFER, sizeof(LightUniform) * data.max_lights_per_render, nullptr, GL_STREAM_DRAW);
@@ -2511,41 +2608,28 @@ RasterizerCanvasGLES3::RasterizerCanvasGLES3() {
glBindBuffer(GL_UNIFORM_BUFFER, new_buffers[2]);
glBufferData(GL_UNIFORM_BUFFER, sizeof(StateBuffer), nullptr, GL_STREAM_DRAW);
DataBuffer db;
- db.ubo = new_buffers[0];
+ db.buffer = new_buffers[0];
db.light_ubo = new_buffers[1];
db.state_ubo = new_buffers[2];
db.last_frame_used = 0;
db.fence = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
state.canvas_instance_data_buffers[i] = db;
}
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_UNIFORM_BUFFER, 0);
- state.instance_data_array = memnew_arr(InstanceData, data.max_instances_per_ubo);
+ state.instance_data_array = memnew_arr(InstanceData, data.max_instances_per_buffer);
state.light_uniforms = memnew_arr(LightUniform, data.max_lights_per_render);
{
- const uint32_t no_of_instances = data.max_instances_per_batch;
-
+ const uint32_t indices[6] = { 0, 2, 1, 3, 2, 0 };
glGenVertexArrays(1, &data.indexed_quad_array);
glBindVertexArray(data.indexed_quad_array);
glBindBuffer(GL_ARRAY_BUFFER, data.canvas_quad_vertices);
-
- const uint32_t num_indices = 6;
- const uint32_t quad_indices[num_indices] = { 0, 2, 1, 3, 2, 0 };
-
- const uint32_t total_indices = no_of_instances * num_indices;
- uint32_t *indices = new uint32_t[total_indices];
- for (uint32_t i = 0; i < total_indices; i++) {
- uint32_t quad = i / num_indices;
- uint32_t quad_local = i % num_indices;
- indices[i] = quad_indices[quad_local] + quad * num_indices;
- }
-
glGenBuffers(1, &data.indexed_quad_buffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, data.indexed_quad_buffer);
- glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(uint32_t) * total_indices, indices, GL_STATIC_DRAW);
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(uint32_t) * 6, indices, GL_STATIC_DRAW);
glBindVertexArray(0);
- delete[] indices;
}
String global_defines;
@@ -2553,9 +2637,8 @@ RasterizerCanvasGLES3::RasterizerCanvasGLES3() {
global_defines += "#define MAX_LIGHTS " + itos(data.max_lights_per_render) + "\n";
global_defines += "#define MAX_DRAW_DATA_INSTANCES " + itos(data.max_instances_per_batch) + "\n";
- GLES3::MaterialStorage::get_singleton()->shaders.canvas_shader.initialize(global_defines);
+ GLES3::MaterialStorage::get_singleton()->shaders.canvas_shader.initialize(global_defines, 1);
data.canvas_shader_default_version = GLES3::MaterialStorage::get_singleton()->shaders.canvas_shader.version_create();
- GLES3::MaterialStorage::get_singleton()->shaders.canvas_shader.version_bind_shader(data.canvas_shader_default_version, CanvasShaderGLES3::MODE_QUAD);
shadow_render.shader.initialize();
shadow_render.shader_version = shadow_render.shader.version_create();
diff --git a/drivers/gles3/rasterizer_canvas_gles3.h b/drivers/gles3/rasterizer_canvas_gles3.h
index d672d05e14..d99a8414f7 100644
--- a/drivers/gles3/rasterizer_canvas_gles3.h
+++ b/drivers/gles3/rasterizer_canvas_gles3.h
@@ -245,7 +245,7 @@ public:
uint32_t max_lights_per_render = 256;
uint32_t max_lights_per_item = 16;
uint32_t max_instances_per_batch = 512;
- uint32_t max_instances_per_ubo = 16384;
+ uint32_t max_instances_per_buffer = 16384;
uint32_t max_instance_buffer_size = 16384 * 128;
} data;
@@ -254,7 +254,7 @@ public:
uint32_t start = 0;
uint32_t instance_count = 0;
- RID tex = RID();
+ RID tex;
RS::CanvasItemTextureFilter filter = RS::CANVAS_ITEM_TEXTURE_FILTER_MAX;
RS::CanvasItemTextureRepeat repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX;
@@ -263,7 +263,7 @@ public:
Item *clip = nullptr;
- RID material = RID();
+ RID material;
GLES3::CanvasMaterialData *material_data = nullptr;
CanvasShaderGLES3::ShaderVariant shader_variant = CanvasShaderGLES3::MODE_QUAD;
@@ -278,7 +278,7 @@ public:
// We track them and ensure that they don't get reused until at least 2 frames have passed
// to avoid the GPU stalling to wait for a resource to become available.
struct DataBuffer {
- GLuint ubo = 0;
+ GLuint buffer = 0;
GLuint light_ubo = 0;
GLuint state_ubo = 0;
uint64_t last_frame_used = -3;
@@ -303,7 +303,7 @@ public:
bool using_directional_lights = false;
- RID current_tex = RID();
+ RID current_tex;
RS::CanvasItemTextureFilter current_filter_mode = RS::CANVAS_ITEM_TEXTURE_FILTER_MAX;
RS::CanvasItemTextureRepeat current_repeat_mode = RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX;
@@ -351,14 +351,15 @@ public:
void _prepare_canvas_texture(RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, uint32_t &r_index, Size2 &r_texpixel_size);
void canvas_render_items(RID p_to_render_target, Item *p_item_list, const Color &p_modulate, Light *p_light_list, Light *p_directional_list, const Transform2D &p_canvas_transform, RS::CanvasItemTextureFilter p_default_filter, RS::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel, bool &r_sdf_used) override;
- void _render_items(RID p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights, uint32_t &r_last_index, bool p_to_backbuffer = false);
- void _record_item_commands(const Item *p_item, const Transform2D &p_canvas_transform_inverse, Item *&current_clip, GLES3::CanvasShaderData::BlendMode p_blend_mode, Light *p_lights, uint32_t &r_index, bool &r_break_batch);
+ void _render_items(RID p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights, uint32_t &r_last_index, bool &r_sdf_used, bool p_to_backbuffer = false);
+ void _record_item_commands(const Item *p_item, RID p_render_target, const Transform2D &p_canvas_transform_inverse, Item *&current_clip, GLES3::CanvasShaderData::BlendMode p_blend_mode, Light *p_lights, uint32_t &r_index, bool &r_break_batch, bool &r_sdf_used);
void _render_batch(Light *p_lights, uint32_t p_index);
- void _bind_material(GLES3::CanvasMaterialData *p_material_data, CanvasShaderGLES3::ShaderVariant p_variant, uint64_t p_specialization);
+ bool _bind_material(GLES3::CanvasMaterialData *p_material_data, CanvasShaderGLES3::ShaderVariant p_variant, uint64_t p_specialization);
void _new_batch(bool &r_batch_broken, uint32_t &r_index);
void _add_to_batch(uint32_t &r_index, bool &r_batch_broken);
void _allocate_instance_data_buffer();
void _align_instance_data_buffer(uint32_t &r_index);
+ void _enable_attributes(uint32_t p_start, bool p_primitive, uint32_t p_rate = 1);
void set_time(double p_time);
diff --git a/drivers/gles3/rasterizer_gles3.cpp b/drivers/gles3/rasterizer_gles3.cpp
index b2d01b02fb..75fc0c8c35 100644
--- a/drivers/gles3/rasterizer_gles3.cpp
+++ b/drivers/gles3/rasterizer_gles3.cpp
@@ -199,7 +199,7 @@ void RasterizerGLES3::finalize() {
RasterizerGLES3::RasterizerGLES3() {
#ifdef GLAD_ENABLED
- if (!gladLoadGL()) {
+ if (!gladLoaderLoadGL()) {
ERR_PRINT("Error initializing GLAD");
// FIXME this is an early return from a constructor. Any other code using this instance will crash or the finalizer will crash, because none of
// the members of this instance are initialized, so this just makes debugging harder. It should either crash here intentionally,
@@ -285,6 +285,15 @@ void RasterizerGLES3::_blit_render_target_to_screen(RID p_render_target, Display
ERR_FAIL_COND(!rt);
+ // We normally render to the render target upside down, so flip Y when blitting to the screen.
+ bool flip_y = true;
+ if (rt->overridden.color.is_valid()) {
+ // If we've overridden the render target's color texture, that means we
+ // didn't render upside down, so we don't need to flip it.
+ // We're probably rendering directly to an XR device.
+ flip_y = false;
+ }
+
GLuint read_fbo = 0;
if (rt->view_count > 1) {
glGenFramebuffers(1, &read_fbo);
@@ -296,10 +305,9 @@ void RasterizerGLES3::_blit_render_target_to_screen(RID p_render_target, Display
glReadBuffer(GL_COLOR_ATTACHMENT0);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, GLES3::TextureStorage::system_fbo);
- // Flip content upside down to correct for coordinates.
Vector2i screen_rect_end = p_screen_rect.get_end();
glBlitFramebuffer(0, 0, rt->size.x, rt->size.y,
- p_screen_rect.position.x, screen_rect_end.y, screen_rect_end.x, p_screen_rect.position.y,
+ p_screen_rect.position.x, flip_y ? screen_rect_end.y : p_screen_rect.position.y, screen_rect_end.x, flip_y ? p_screen_rect.position.y : screen_rect_end.y,
GL_COLOR_BUFFER_BIT, GL_NEAREST);
if (read_fbo != 0) {
@@ -325,18 +333,14 @@ void RasterizerGLES3::set_boot_image(const Ref<Image> &p_image, const Color &p_c
return;
}
- Size2i win_size = DisplayServer::get_singleton()->screen_get_size();
+ Size2i win_size = DisplayServer::get_singleton()->window_get_size();
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glViewport(0, 0, win_size.width, win_size.height);
- glDisable(GL_BLEND);
+ glEnable(GL_BLEND);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE);
glDepthMask(GL_FALSE);
- if (false) {
- // if (OS::get_singleton()->get_window_per_pixel_transparency_enabled()) {
- glClearColor(0.0, 0.0, 0.0, 0.0);
- } else {
- glClearColor(p_color.r, p_color.g, p_color.b, 1.0);
- }
+ glClearColor(p_color.r, p_color.g, p_color.b, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
RID texture = texture_storage->texture_allocate();
@@ -362,14 +366,24 @@ void RasterizerGLES3::set_boot_image(const Ref<Image> &p_image, const Color &p_c
screenrect.position += ((Size2(win_size.width, win_size.height) - screenrect.size) / 2.0).floor();
}
+ // Flip Y.
+ screenrect.position.y = win_size.y - screenrect.position.y;
+ screenrect.size.y = -screenrect.size.y;
+
+ // Normalize texture coordinates to window size.
+ screenrect.position /= win_size;
+ screenrect.size /= win_size;
+
GLES3::Texture *t = texture_storage->get_texture(texture);
- glActiveTexture(GL_TEXTURE0 + config->max_texture_image_units - 1);
+ t->gl_set_filter(p_use_filter ? RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR : RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST);
+ glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, t->tex_id);
+ copy_effects->copy_to_rect(screenrect);
glBindTexture(GL_TEXTURE_2D, 0);
- texture_storage->texture_free(texture);
-
end_frame(true);
+
+ texture_storage->texture_free(texture);
}
#endif // GLES3_ENABLED
diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp
index 734911ccdb..1faecfd4d0 100644
--- a/drivers/gles3/rasterizer_scene_gles3.cpp
+++ b/drivers/gles3/rasterizer_scene_gles3.cpp
@@ -35,6 +35,7 @@
#include "servers/rendering/rendering_server_globals.h"
#include "storage/config.h"
#include "storage/mesh_storage.h"
+#include "storage/particles_storage.h"
#include "storage/texture_storage.h"
#ifdef GLES3_ENABLED
@@ -50,6 +51,9 @@ RenderGeometryInstance *RasterizerSceneGLES3::geometry_instance_create(RID p_bas
ginstance->data->base = p_base;
ginstance->data->base_type = type;
+ ginstance->data->dependency_tracker.userdata = ginstance;
+ ginstance->data->dependency_tracker.changed_callback = _geometry_instance_dependency_changed;
+ ginstance->data->dependency_tracker.deleted_callback = _geometry_instance_dependency_deleted;
ginstance->_mark_dirty();
@@ -314,6 +318,8 @@ void RasterizerSceneGLES3::_geometry_instance_add_surface(GeometryInstanceGLES3
void RasterizerSceneGLES3::_geometry_instance_update(RenderGeometryInstance *p_geometry_instance) {
GLES3::MeshStorage *mesh_storage = GLES3::MeshStorage::get_singleton();
+ GLES3::ParticlesStorage *particles_storage = GLES3::ParticlesStorage::get_singleton();
+
GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance);
if (ginstance->data->dirty_dependencies) {
@@ -361,6 +367,26 @@ void RasterizerSceneGLES3::_geometry_instance_update(RenderGeometryInstance *p_g
} break;
case RS::INSTANCE_PARTICLES: {
+ int draw_passes = particles_storage->particles_get_draw_passes(ginstance->data->base);
+
+ for (int j = 0; j < draw_passes; j++) {
+ RID mesh = particles_storage->particles_get_draw_pass_mesh(ginstance->data->base, j);
+ if (!mesh.is_valid()) {
+ continue;
+ }
+
+ const RID *materials = nullptr;
+ uint32_t surface_count;
+
+ materials = mesh_storage->mesh_get_surface_count_and_materials(mesh, surface_count);
+ if (materials) {
+ for (uint32_t k = 0; k < surface_count; k++) {
+ _geometry_instance_add_surface(ginstance, k, materials[k], mesh);
+ }
+ }
+ }
+
+ ginstance->instance_count = particles_storage->particles_get_amount(ginstance->data->base);
} break;
default: {
@@ -382,10 +408,23 @@ void RasterizerSceneGLES3::_geometry_instance_update(RenderGeometryInstance *p_g
ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH_HAS_CUSTOM_DATA;
}
- //ginstance->transforms_uniform_set = mesh_storage->multimesh_get_3d_uniform_set(ginstance->data->base, scene_globals.default_shader_rd, TRANSFORMS_UNIFORM_SET);
-
} else if (ginstance->data->base_type == RS::INSTANCE_PARTICLES) {
+ ginstance->base_flags |= INSTANCE_DATA_FLAG_PARTICLES;
+ ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH;
+
+ ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH_HAS_COLOR;
+ ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH_HAS_CUSTOM_DATA;
+
+ if (!particles_storage->particles_is_using_local_coords(ginstance->data->base)) {
+ store_transform = false;
+ }
+
} else if (ginstance->data->base_type == RS::INSTANCE_MESH) {
+ if (mesh_storage->skeleton_is_valid(ginstance->data->skeleton)) {
+ if (ginstance->data->dirty_dependencies) {
+ mesh_storage->skeleton_update_dependency(ginstance->data->skeleton, &ginstance->data->dependency_tracker);
+ }
+ }
}
ginstance->store_transform_cache = store_transform;
@@ -749,14 +788,18 @@ void RasterizerSceneGLES3::_draw_sky(RID p_env, const Projection &p_projection,
}
Basis sky_transform = environment_get_sky_orientation(p_env);
sky_transform.invert();
- sky_transform = p_transform.basis * sky_transform;
+ sky_transform = sky_transform * p_transform.basis;
+
+ bool success = material_storage->shaders.sky_shader.version_bind_shader(shader_data->version, SkyShaderGLES3::MODE_BACKGROUND);
+ if (!success) {
+ return;
+ }
- GLES3::MaterialStorage::get_singleton()->shaders.sky_shader.version_bind_shader(shader_data->version, SkyShaderGLES3::MODE_BACKGROUND);
- GLES3::MaterialStorage::get_singleton()->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::ORIENTATION, sky_transform, shader_data->version, SkyShaderGLES3::MODE_BACKGROUND);
- GLES3::MaterialStorage::get_singleton()->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::PROJECTION, camera.columns[2][0], camera.columns[0][0], camera.columns[2][1], camera.columns[1][1], shader_data->version, SkyShaderGLES3::MODE_BACKGROUND);
- GLES3::MaterialStorage::get_singleton()->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::POSITION, p_transform.origin, shader_data->version, SkyShaderGLES3::MODE_BACKGROUND);
- GLES3::MaterialStorage::get_singleton()->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::TIME, time, shader_data->version, SkyShaderGLES3::MODE_BACKGROUND);
- GLES3::MaterialStorage::get_singleton()->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::LUMINANCE_MULTIPLIER, p_luminance_multiplier, shader_data->version, SkyShaderGLES3::MODE_BACKGROUND);
+ material_storage->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::ORIENTATION, sky_transform, shader_data->version, SkyShaderGLES3::MODE_BACKGROUND);
+ material_storage->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::PROJECTION, camera.columns[2][0], camera.columns[0][0], camera.columns[2][1], camera.columns[1][1], shader_data->version, SkyShaderGLES3::MODE_BACKGROUND);
+ material_storage->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::POSITION, p_transform.origin, shader_data->version, SkyShaderGLES3::MODE_BACKGROUND);
+ material_storage->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::TIME, time, shader_data->version, SkyShaderGLES3::MODE_BACKGROUND);
+ material_storage->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::LUMINANCE_MULTIPLIER, p_luminance_multiplier, shader_data->version, SkyShaderGLES3::MODE_BACKGROUND);
glBindVertexArray(sky_globals.screen_triangle_array);
glDrawArrays(GL_TRIANGLES, 0, 3);
@@ -850,12 +893,15 @@ void RasterizerSceneGLES3::_update_sky_radiance(RID p_env, const Projection &p_p
correction.columns[1][1] = -1.0;
cm = correction * cm;
- GLES3::MaterialStorage::get_singleton()->shaders.sky_shader.version_bind_shader(shader_data->version, SkyShaderGLES3::MODE_CUBEMAP);
+ bool success = material_storage->shaders.sky_shader.version_bind_shader(shader_data->version, SkyShaderGLES3::MODE_CUBEMAP);
+ if (!success) {
+ return;
+ }
- GLES3::MaterialStorage::get_singleton()->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::POSITION, p_transform.origin, shader_data->version, SkyShaderGLES3::MODE_CUBEMAP);
- GLES3::MaterialStorage::get_singleton()->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::TIME, time, shader_data->version, SkyShaderGLES3::MODE_CUBEMAP);
- GLES3::MaterialStorage::get_singleton()->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::PROJECTION, cm.columns[2][0], cm.columns[0][0], cm.columns[2][1], cm.columns[1][1], shader_data->version, SkyShaderGLES3::MODE_CUBEMAP);
- GLES3::MaterialStorage::get_singleton()->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::LUMINANCE_MULTIPLIER, p_luminance_multiplier, shader_data->version, SkyShaderGLES3::MODE_CUBEMAP);
+ material_storage->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::POSITION, p_transform.origin, shader_data->version, SkyShaderGLES3::MODE_CUBEMAP);
+ material_storage->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::TIME, time, shader_data->version, SkyShaderGLES3::MODE_CUBEMAP);
+ material_storage->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::PROJECTION, cm.columns[2][0], cm.columns[0][0], cm.columns[2][1], cm.columns[1][1], shader_data->version, SkyShaderGLES3::MODE_CUBEMAP);
+ material_storage->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::LUMINANCE_MULTIPLIER, p_luminance_multiplier, shader_data->version, SkyShaderGLES3::MODE_CUBEMAP);
glBindVertexArray(sky_globals.screen_triangle_array);
@@ -864,7 +910,7 @@ void RasterizerSceneGLES3::_update_sky_radiance(RID p_env, const Projection &p_p
for (int i = 0; i < 6; i++) {
Basis local_view = Basis::looking_at(view_normals[i], view_up[i]);
- GLES3::MaterialStorage::get_singleton()->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::ORIENTATION, local_view, shader_data->version, SkyShaderGLES3::MODE_CUBEMAP);
+ material_storage->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::ORIENTATION, local_view, shader_data->version, SkyShaderGLES3::MODE_CUBEMAP);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, sky->raw_radiance, 0);
glDrawArrays(GL_TRIANGLES, 0, 3);
}
@@ -945,7 +991,10 @@ void RasterizerSceneGLES3::_filter_sky_radiance(Sky *p_sky, int 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);
+ bool success = material_storage->shaders.cubemap_filter_shader.version_bind_shader(scene_globals.cubemap_filter_shader_version, mode);
+ if (!success) {
+ return;
+ }
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 };
@@ -1019,10 +1068,6 @@ void RasterizerSceneGLES3::environment_glow_set_use_bicubic_upscale(bool p_enabl
glow_bicubic_upscale = p_enable;
}
-void RasterizerSceneGLES3::environment_glow_set_use_high_quality(bool p_enable) {
- glow_high_quality = p_enable;
-}
-
void RasterizerSceneGLES3::environment_set_ssr_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality) {
}
@@ -1125,12 +1170,17 @@ void RasterizerSceneGLES3::_fill_render_list(RenderListType p_render_list, const
for (int i = 0; i < (int)p_render_data->instances->size(); i++) {
GeometryInstanceGLES3 *inst = static_cast<GeometryInstanceGLES3 *>((*p_render_data->instances)[i]);
+ Vector3 center = inst->transform.origin;
if (p_render_data->cam_orthogonal) {
- Vector3 support_min = inst->transformed_aabb.get_support(-near_plane.normal);
- inst->depth = near_plane.distance_to(support_min);
+ if (inst->use_aabb_center) {
+ center = inst->transformed_aabb.get_support(-near_plane.normal);
+ }
+ inst->depth = near_plane.distance_to(center) - inst->sorting_offset;
} else {
- Vector3 aabb_center = inst->transformed_aabb.position + (inst->transformed_aabb.size * 0.5);
- inst->depth = p_render_data->cam_transform.origin.distance_to(aabb_center);
+ if (inst->use_aabb_center) {
+ center = inst->transformed_aabb.position + (inst->transformed_aabb.size * 0.5);
+ }
+ inst->depth = p_render_data->cam_transform.origin.distance_to(center) - inst->sorting_offset;
}
uint32_t depth_layer = CLAMP(int(inst->depth * 16 / z_max), 0, 15);
@@ -1272,6 +1322,7 @@ void RasterizerSceneGLES3::_setup_environment(const RenderDataGLES3 *p_render_da
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.camera_visible_layers = p_render_data->camera_visible_layers;
if (p_render_data->view_count > 1) {
for (uint32_t v = 0; v < p_render_data->view_count; v++) {
@@ -1656,6 +1707,7 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_
render_data.inv_cam_transform = render_data.cam_transform.affine_inverse();
render_data.cam_projection = p_camera_data->main_projection;
render_data.cam_orthogonal = p_camera_data->is_orthogonal;
+ render_data.camera_visible_layers = p_camera_data->visible_layers;
render_data.view_count = p_camera_data->view_count;
for (uint32_t v = 0; v < p_camera_data->view_count; v++) {
@@ -1692,7 +1744,7 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_
render_data.reflection_probes = &empty;
}
- bool reverse_cull = false;
+ bool reverse_cull = render_data.cam_transform.basis.determinant() < 0;
///////////
// Fill Light lists here
@@ -1851,8 +1903,11 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_
glColorMask(0, 0, 0, 0);
glClearDepth(1.0f);
glClear(GL_DEPTH_BUFFER_BIT);
+ uint64_t spec_constant = SceneShaderGLES3::DISABLE_FOG | SceneShaderGLES3::DISABLE_LIGHT_DIRECTIONAL |
+ SceneShaderGLES3::DISABLE_LIGHTMAP | SceneShaderGLES3::DISABLE_LIGHT_OMNI |
+ SceneShaderGLES3::DISABLE_LIGHT_SPOT;
- RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, 0, use_wireframe);
+ RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, spec_constant, use_wireframe);
_render_list_template<PASS_MODE_DEPTH>(&render_list_params, &render_data, 0, render_list[RENDER_LIST_OPAQUE].elements.size());
glColorMask(1, 1, 1, 1);
@@ -1889,16 +1944,16 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_
glClearBufferfv(GL_COLOR, 0, clear_color.components);
}
RENDER_TIMESTAMP("Render Opaque Pass");
- uint32_t spec_constant_base_flags = 0;
+ uint64_t spec_constant_base_flags = 0;
{
// Specialization Constants that apply for entire rendering pass.
if (render_data.directional_light_count == 0) {
- spec_constant_base_flags |= 1 << SPEC_CONSTANT_DISABLE_DIRECTIONAL_LIGHTS;
+ spec_constant_base_flags |= SceneShaderGLES3::DISABLE_LIGHT_DIRECTIONAL;
}
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;
+ spec_constant_base_flags |= SceneShaderGLES3::DISABLE_FOG;
}
}
// Render Opaque Objects.
@@ -1947,6 +2002,7 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_
template <PassMode p_pass_mode>
void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params, const RenderDataGLES3 *p_render_data, uint32_t p_from_element, uint32_t p_to_element, bool p_alpha_pass) {
GLES3::MeshStorage *mesh_storage = GLES3::MeshStorage::get_singleton();
+ GLES3::ParticlesStorage *particles_storage = GLES3::ParticlesStorage::get_singleton();
GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton();
GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
GLES3::Config *config = GLES3::Config::get_singleton();
@@ -1959,12 +2015,13 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params,
GeometryInstanceGLES3 *prev_inst = nullptr;
SceneShaderGLES3::ShaderVariant prev_variant = SceneShaderGLES3::ShaderVariant::MODE_COLOR;
SceneShaderGLES3::ShaderVariant shader_variant = SceneShaderGLES3::MODE_COLOR; // Assigned to silence wrong -Wmaybe-initialized
+ uint64_t prev_spec_constants = 0;
- // @todo Get this from p_params->spec_constant_base_flags instead of hardcoding it.
- uint32_t base_spec_constants = 0;
+ // Specializations constants used by all instances in the scene.
+ uint64_t base_spec_constants = p_params->spec_constant_base_flags;
if (p_render_data->view_count > 1) {
- base_spec_constants |= 1 << SPEC_CONSTANT_USE_MULTIVIEW;
+ base_spec_constants |= SceneShaderGLES3::USE_MULTIVIEW;
}
switch (p_pass_mode) {
@@ -1987,7 +2044,7 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params,
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;
+ base_spec_constants |= SceneShaderGLES3::USE_RADIANCE_MAP;
}
glBindTexture(GL_TEXTURE_CUBE_MAP, texture_to_bind);
}
@@ -2154,6 +2211,9 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params,
glBindVertexArray(vertex_array_gl);
}
prev_vertex_array_gl = vertex_array_gl;
+
+ // Invalidate the previous index array
+ prev_index_array_gl = 0;
}
bool use_index_buffer = index_array_gl != 0;
@@ -2177,11 +2237,26 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params,
SceneShaderGLES3::ShaderVariant instance_variant = shader_variant;
if (inst->instance_count > 0) {
+ // Will need to use instancing to draw (either MultiMesh or Particles).
instance_variant = SceneShaderGLES3::ShaderVariant(1 + int(shader_variant));
}
- if (prev_shader != shader || prev_variant != instance_variant) {
- material_storage->shaders.scene_shader.version_bind_shader(shader->version, instance_variant, base_spec_constants);
+ uint64_t spec_constants = base_spec_constants;
+
+ if (inst->omni_light_count == 0) {
+ spec_constants |= SceneShaderGLES3::DISABLE_LIGHT_OMNI;
+ }
+
+ if (inst->spot_light_count == 0) {
+ spec_constants |= SceneShaderGLES3::DISABLE_LIGHT_SPOT;
+ }
+
+ if (prev_shader != shader || prev_variant != instance_variant || spec_constants != prev_spec_constants) {
+ bool success = material_storage->shaders.scene_shader.version_bind_shader(shader->version, instance_variant, spec_constants);
+ if (!success) {
+ continue;
+ }
+
float opaque_prepass_threshold = 0.0;
if constexpr (p_pass_mode == PASS_MODE_DEPTH) {
opaque_prepass_threshold = 0.99;
@@ -2189,49 +2264,67 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params,
opaque_prepass_threshold = 0.1;
}
- material_storage->shaders.scene_shader.version_set_uniform(SceneShaderGLES3::OPAQUE_PREPASS_THRESHOLD, opaque_prepass_threshold, shader->version, instance_variant, base_spec_constants);
+ material_storage->shaders.scene_shader.version_set_uniform(SceneShaderGLES3::OPAQUE_PREPASS_THRESHOLD, opaque_prepass_threshold, shader->version, instance_variant, spec_constants);
prev_shader = shader;
prev_variant = instance_variant;
+ prev_spec_constants = spec_constants;
}
if (prev_inst != inst || prev_shader != shader || prev_variant != instance_variant) {
// Rebind the light indices.
- material_storage->shaders.scene_shader.version_set_uniform(SceneShaderGLES3::OMNI_LIGHT_COUNT, inst->omni_light_count, shader->version, instance_variant, base_spec_constants);
- material_storage->shaders.scene_shader.version_set_uniform(SceneShaderGLES3::SPOT_LIGHT_COUNT, inst->spot_light_count, shader->version, instance_variant, base_spec_constants);
+ material_storage->shaders.scene_shader.version_set_uniform(SceneShaderGLES3::OMNI_LIGHT_COUNT, inst->omni_light_count, shader->version, instance_variant, spec_constants);
+ material_storage->shaders.scene_shader.version_set_uniform(SceneShaderGLES3::SPOT_LIGHT_COUNT, inst->spot_light_count, shader->version, instance_variant, spec_constants);
if (inst->omni_light_count) {
- glUniform1uiv(material_storage->shaders.scene_shader.version_get_uniform(SceneShaderGLES3::OMNI_LIGHT_INDICES, shader->version, instance_variant, base_spec_constants), inst->omni_light_count, inst->omni_light_gl_cache.ptr());
+ glUniform1uiv(material_storage->shaders.scene_shader.version_get_uniform(SceneShaderGLES3::OMNI_LIGHT_INDICES, shader->version, instance_variant, spec_constants), inst->omni_light_count, inst->omni_light_gl_cache.ptr());
}
if (inst->spot_light_count) {
- glUniform1uiv(material_storage->shaders.scene_shader.version_get_uniform(SceneShaderGLES3::SPOT_LIGHT_INDICES, shader->version, instance_variant, base_spec_constants), inst->spot_light_count, inst->spot_light_gl_cache.ptr());
+ glUniform1uiv(material_storage->shaders.scene_shader.version_get_uniform(SceneShaderGLES3::SPOT_LIGHT_INDICES, shader->version, instance_variant, spec_constants), inst->spot_light_count, inst->spot_light_gl_cache.ptr());
}
prev_inst = inst;
}
- material_storage->shaders.scene_shader.version_set_uniform(SceneShaderGLES3::WORLD_TRANSFORM, world_transform, shader->version, instance_variant, base_spec_constants);
+ material_storage->shaders.scene_shader.version_set_uniform(SceneShaderGLES3::WORLD_TRANSFORM, world_transform, shader->version, instance_variant, spec_constants);
if (inst->instance_count > 0) {
- // Using MultiMesh.
+ // Using MultiMesh or Particles.
// Bind instance buffers.
- GLuint multimesh_buffer = mesh_storage->multimesh_get_gl_buffer(inst->data->base);
- glBindBuffer(GL_ARRAY_BUFFER, multimesh_buffer);
- uint32_t multimesh_stride = mesh_storage->multimesh_get_stride(inst->data->base);
+ GLuint instance_buffer = 0;
+ uint32_t stride = 0;
+ if (inst->flags_cache & INSTANCE_DATA_FLAG_PARTICLES) {
+ instance_buffer = particles_storage->particles_get_gl_buffer(inst->data->base);
+ stride = 16; // 12 bytes for instance transform and 4 bytes for packed color and custom.
+ } else {
+ instance_buffer = mesh_storage->multimesh_get_gl_buffer(inst->data->base);
+ stride = mesh_storage->multimesh_get_stride(inst->data->base);
+ }
+
+ if (instance_buffer == 0) {
+ // Instance buffer not initialized yet. Skip rendering for now.
+ continue;
+ }
+
+ glBindBuffer(GL_ARRAY_BUFFER, instance_buffer);
+
glEnableVertexAttribArray(12);
- glVertexAttribPointer(12, 4, GL_FLOAT, GL_FALSE, multimesh_stride * sizeof(float), CAST_INT_TO_UCHAR_PTR(0));
+ glVertexAttribPointer(12, 4, GL_FLOAT, GL_FALSE, stride * sizeof(float), CAST_INT_TO_UCHAR_PTR(0));
glVertexAttribDivisor(12, 1);
glEnableVertexAttribArray(13);
- glVertexAttribPointer(13, 4, GL_FLOAT, GL_FALSE, multimesh_stride * sizeof(float), CAST_INT_TO_UCHAR_PTR(4 * 4));
+ glVertexAttribPointer(13, 4, GL_FLOAT, GL_FALSE, stride * sizeof(float), CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4));
glVertexAttribDivisor(13, 1);
- glEnableVertexAttribArray(14);
- glVertexAttribPointer(14, 4, GL_FLOAT, GL_FALSE, multimesh_stride * sizeof(float), CAST_INT_TO_UCHAR_PTR(4 * 8));
- glVertexAttribDivisor(14, 1);
+ if (!(inst->flags_cache & INSTANCE_DATA_FLAG_MULTIMESH_FORMAT_2D)) {
+ glEnableVertexAttribArray(14);
+ glVertexAttribPointer(14, 4, GL_FLOAT, GL_FALSE, stride * sizeof(float), CAST_INT_TO_UCHAR_PTR(sizeof(float) * 8));
+ glVertexAttribDivisor(14, 1);
+ }
- if (mesh_storage->multimesh_uses_colors(inst->data->base) || mesh_storage->multimesh_uses_custom_data(inst->data->base)) {
+ if ((inst->flags_cache & INSTANCE_DATA_FLAG_MULTIMESH_HAS_COLOR) || (inst->flags_cache & INSTANCE_DATA_FLAG_MULTIMESH_HAS_CUSTOM_DATA)) {
+ uint32_t color_custom_offset = inst->flags_cache & INSTANCE_DATA_FLAG_MULTIMESH_FORMAT_2D ? 8 : 12;
glEnableVertexAttribArray(15);
- glVertexAttribIPointer(15, 4, GL_UNSIGNED_INT, multimesh_stride * sizeof(float), CAST_INT_TO_UCHAR_PTR(mesh_storage->multimesh_get_color_offset(inst->data->base) * sizeof(float)));
+ glVertexAttribIPointer(15, 4, GL_UNSIGNED_INT, stride * sizeof(float), CAST_INT_TO_UCHAR_PTR(color_custom_offset * sizeof(float)));
glVertexAttribDivisor(15, 1);
}
if (use_index_buffer) {
@@ -2265,6 +2358,72 @@ void RasterizerSceneGLES3::render_material(const Transform3D &p_cam_transform, c
}
void RasterizerSceneGLES3::render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<RenderGeometryInstance *> &p_instances) {
+ GLES3::ParticlesStorage *particles_storage = GLES3::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();
+ Projection cm;
+ cm.set_orthogonal(-extents.x, extents.x, -extents.z, extents.z, 0, extents.y * 2.0);
+
+ Vector3 cam_pos = p_transform.origin;
+ cam_pos.y += extents.y;
+
+ Transform3D cam_xform;
+ cam_xform.set_look_at(cam_pos, cam_pos - p_transform.basis.get_column(Vector3::AXIS_Y), -p_transform.basis.get_column(Vector3::AXIS_Z).normalized());
+
+ GLuint fb = particles_storage->particles_collision_get_heightfield_framebuffer(p_collider);
+ Size2i fb_size = particles_storage->particles_collision_get_heightfield_size(p_collider);
+
+ RENDER_TIMESTAMP("Setup GPUParticlesCollisionHeightField3D");
+
+ RenderDataGLES3 render_data;
+
+ render_data.cam_projection = cm;
+ render_data.cam_transform = cam_xform;
+ render_data.view_projection[0] = cm;
+ render_data.inv_cam_transform = render_data.cam_transform.affine_inverse();
+ render_data.cam_orthogonal = true;
+ render_data.z_near = 0.0;
+ render_data.z_far = cm.get_z_far();
+
+ render_data.instances = &p_instances;
+
+ _setup_environment(&render_data, true, Vector2(fb_size), true, Color(), false);
+
+ PassMode pass_mode = PASS_MODE_SHADOW;
+
+ _fill_render_list(RENDER_LIST_SECONDARY, &render_data, pass_mode);
+ render_list[RENDER_LIST_SECONDARY].sort_by_key();
+
+ RENDER_TIMESTAMP("Render Collider Heightfield");
+
+ glBindFramebuffer(GL_FRAMEBUFFER, fb);
+ glViewport(0, 0, fb_size.width, fb_size.height);
+
+ GLuint global_buffer = GLES3::MaterialStorage::get_singleton()->global_shader_parameters_get_uniform_buffer();
+
+ glBindBufferBase(GL_UNIFORM_BUFFER, SCENE_GLOBALS_UNIFORM_LOCATION, global_buffer);
+ glBindBuffer(GL_UNIFORM_BUFFER, 0);
+
+ glDisable(GL_BLEND);
+ glDepthMask(GL_TRUE);
+ glEnable(GL_DEPTH_TEST);
+ glDepthFunc(GL_LESS);
+ glDisable(GL_SCISSOR_TEST);
+ glCullFace(GL_BACK);
+ glEnable(GL_CULL_FACE);
+ scene_state.cull_mode = GLES3::SceneShaderData::CULL_BACK;
+
+ glColorMask(0, 0, 0, 0);
+ glClearDepth(1.0f);
+ glClear(GL_DEPTH_BUFFER_BIT);
+
+ RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), false, 31, false);
+
+ _render_list_template<PASS_MODE_SHADOW>(&render_list_params, &render_data, 0, render_list[RENDER_LIST_SECONDARY].elements.size());
+
+ glColorMask(1, 1, 1, 1);
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
void RasterizerSceneGLES3::set_time(double p_time, double p_step) {
@@ -2415,7 +2574,7 @@ RasterizerSceneGLES3::RasterizerSceneGLES3() {
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";
+ global_defines += "\n#define MAX_FORWARD_LIGHTS uint(" + itos(config->max_lights_per_object) + ")\n";
material_storage->shaders.scene_shader.initialize(global_defines);
scene_globals.shader_default_version = material_storage->shaders.scene_shader.version_create();
material_storage->shaders.scene_shader.version_bind_shader(scene_globals.shader_default_version, SceneShaderGLES3::MODE_COLOR);
@@ -2455,7 +2614,6 @@ void fragment() {
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);
}
{
@@ -2463,7 +2621,6 @@ void fragment() {
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);
}
{
diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h
index 3a759425e2..65cc8606b8 100644
--- a/drivers/gles3/rasterizer_scene_gles3.h
+++ b/drivers/gles3/rasterizer_scene_gles3.h
@@ -85,24 +85,15 @@ enum SkyUniformLocation {
SKY_DIRECTIONAL_LIGHT_UNIFORM_LOCATION,
};
-enum {
- SPEC_CONSTANT_DISABLE_LIGHTMAP = 0,
- SPEC_CONSTANT_DISABLE_DIRECTIONAL_LIGHTS = 1,
- SPEC_CONSTANT_DISABLE_OMNI_LIGHTS = 2,
- SPEC_CONSTANT_DISABLE_SPOT_LIGHTS = 3,
- SPEC_CONSTANT_DISABLE_FOG = 4,
- SPEC_CONSTANT_USE_RADIANCE_MAP = 5,
- SPEC_CONSTANT_USE_MULTIVIEW = 6,
-};
-
struct RenderDataGLES3 {
Ref<RenderSceneBuffersGLES3> render_buffers;
bool transparent_bg = false;
- Transform3D cam_transform = Transform3D();
- Transform3D inv_cam_transform = Transform3D();
- Projection cam_projection = Projection();
+ Transform3D cam_transform;
+ Transform3D inv_cam_transform;
+ Projection cam_projection;
bool cam_orthogonal = false;
+ uint32_t camera_visible_layers = 0xFFFFFFFF;
// For stereo rendering
uint32_t view_count = 1;
@@ -115,9 +106,9 @@ struct RenderDataGLES3 {
const PagedArray<RenderGeometryInstance *> *instances = nullptr;
const PagedArray<RID> *lights = nullptr;
const PagedArray<RID> *reflection_probes = nullptr;
- RID environment = RID();
- RID camera_attributes = RID();
- RID reflection_probe = RID();
+ RID environment;
+ RID camera_attributes;
+ RID reflection_probe;
int reflection_probe_pass = 0;
float lod_distance_multiplier = 0.0;
@@ -343,6 +334,10 @@ private:
float fog_light_color[3];
float fog_sun_scatter;
+ uint32_t camera_visible_layers;
+ uint32_t pad1;
+ uint32_t pad2;
+ uint32_t pad3;
};
static_assert(sizeof(UBO) % 16 == 0, "Scene UBO size must be a multiple of 16 bytes");
@@ -397,10 +392,10 @@ private:
GeometryInstanceSurface **elements = nullptr;
int element_count = 0;
bool reverse_cull = false;
- uint32_t spec_constant_base_flags = 0;
+ uint64_t spec_constant_base_flags = 0;
bool force_wireframe = false;
- RenderListParameters(GeometryInstanceSurface **p_elements, int p_element_count, bool p_reverse_cull, uint32_t p_spec_constant_base_flags, bool p_force_wireframe = false) {
+ RenderListParameters(GeometryInstanceSurface **p_elements, int p_element_count, bool p_reverse_cull, uint64_t p_spec_constant_base_flags, bool p_force_wireframe = false) {
elements = p_elements;
element_count = p_element_count;
reverse_cull = p_reverse_cull;
@@ -502,7 +497,6 @@ protected:
float ssao_fadeout_to = 300.0;
bool glow_bicubic_upscale = false;
- bool glow_high_quality = false;
RS::EnvironmentSSRRoughnessQuality ssr_roughness_quality = RS::ENV_SSR_ROUGHNESS_QUALITY_LOW;
/* Sky */
@@ -615,7 +609,6 @@ public:
/* ENVIRONMENT API */
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_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality) override;
diff --git a/drivers/gles3/shader_gles3.cpp b/drivers/gles3/shader_gles3.cpp
index 2ff7f72180..69c3ff7c8e 100644
--- a/drivers/gles3/shader_gles3.cpp
+++ b/drivers/gles3/shader_gles3.cpp
@@ -36,6 +36,11 @@
#include "core/io/dir_access.h"
#include "core/io/file_access.h"
+static String _mkid(const String &p_id) {
+ String id = "m_" + p_id.replace("__", "_dus_");
+ return id.replace("__", "_dus_"); //doubleunderscore is reserved in glsl
+}
+
void ShaderGLES3::_add_stage(const char *p_code, StageType p_stage_type) {
Vector<String> lines = String(p_code).split("\n");
@@ -92,7 +97,7 @@ void ShaderGLES3::_add_stage(const char *p_code, StageType p_stage_type) {
}
}
-void ShaderGLES3::_setup(const char *p_vertex_code, const char *p_fragment_code, const char *p_name, int p_uniform_count, const char **p_uniform_names, int p_ubo_count, const UBOPair *p_ubos, int p_texture_count, const TexUnitPair *p_tex_units, int p_specialization_count, const Specialization *p_specializations, int p_variant_count, const char **p_variants) {
+void ShaderGLES3::_setup(const char *p_vertex_code, const char *p_fragment_code, const char *p_name, int p_uniform_count, const char **p_uniform_names, int p_ubo_count, const UBOPair *p_ubos, int p_feedback_count, const Feedback *p_feedback, int p_texture_count, const TexUnitPair *p_tex_units, int p_specialization_count, const Specialization *p_specializations, int p_variant_count, const char **p_variants) {
name = p_name;
if (p_vertex_code) {
@@ -118,6 +123,8 @@ void ShaderGLES3::_setup(const char *p_vertex_code, const char *p_fragment_code,
}
variant_defines = p_variants;
variant_count = p_variant_count;
+ feedbacks = p_feedback;
+ feedback_count = p_feedback_count;
StringBuilder tohash;
/*
@@ -339,9 +346,21 @@ void ShaderGLES3::_compile_specialization(Version::Specialization &spec, uint32_
glAttachShader(spec.id, spec.frag_id);
glAttachShader(spec.id, spec.vert_id);
- //for (int i = 0; i < attribute_pair_count; i++) {
- // glBindAttribLocation(v.id, attribute_pairs[i].index, attribute_pairs[i].name);
- //}
+ // If feedback exists, set it up.
+
+ if (feedback_count) {
+ Vector<const char *> feedback;
+ for (int i = 0; i < feedback_count; i++) {
+ if (feedbacks[i].specialization == 0 || (feedbacks[i].specialization & p_specialization)) {
+ // Specialization for this feedback is enabled
+ feedback.push_back(feedbacks[i].name);
+ }
+ }
+
+ if (feedback.size()) {
+ glTransformFeedbackVaryings(spec.id, feedback.size(), feedback.ptr(), GL_INTERLEAVED_ATTRIBS);
+ }
+ }
glLinkProgram(spec.id);
@@ -411,7 +430,7 @@ void ShaderGLES3::_compile_specialization(Version::Specialization &spec, uint32_
}
// textures
for (int i = 0; i < p_version->texture_uniforms.size(); i++) {
- String native_uniform_name = p_version->texture_uniforms[i];
+ String native_uniform_name = _mkid(p_version->texture_uniforms[i]);
GLint location = glGetUniformLocation(spec.id, (native_uniform_name).ascii().get_data());
glUniform1i(location, i + base_texture_index);
}
diff --git a/drivers/gles3/shader_gles3.h b/drivers/gles3/shader_gles3.h
index 3ab7642357..83b950ef45 100644
--- a/drivers/gles3/shader_gles3.h
+++ b/drivers/gles3/shader_gles3.h
@@ -70,6 +70,11 @@ protected:
bool default_value = false;
};
+ struct Feedback {
+ const char *name;
+ uint64_t specialization;
+ };
+
private:
//versions
CharString general_defines;
@@ -165,6 +170,8 @@ private:
int uniform_count = 0;
const UBOPair *ubo_pairs = nullptr;
int ubo_count = 0;
+ const Feedback *feedbacks;
+ int feedback_count = 0;
const TexUnitPair *texunit_pairs = nullptr;
int texunit_pair_count = 0;
int specialization_count = 0;
@@ -178,13 +185,13 @@ private:
protected:
ShaderGLES3();
- void _setup(const char *p_vertex_code, const char *p_fragment_code, const char *p_name, int p_uniform_count, const char **p_uniform_names, int p_ubo_count, const UBOPair *p_ubos, int p_texture_count, const TexUnitPair *p_tex_units, int p_specialization_count, const Specialization *p_specializations, int p_variant_count, const char **p_variants);
+ void _setup(const char *p_vertex_code, const char *p_fragment_code, const char *p_name, int p_uniform_count, const char **p_uniform_names, int p_ubo_count, const UBOPair *p_ubos, int p_feedback_count, const Feedback *p_feedback, int p_texture_count, const TexUnitPair *p_tex_units, int p_specialization_count, const Specialization *p_specializations, int p_variant_count, const char **p_variants);
- _FORCE_INLINE_ void _version_bind_shader(RID p_version, int p_variant, uint64_t p_specialization) {
- ERR_FAIL_INDEX(p_variant, variant_count);
+ _FORCE_INLINE_ bool _version_bind_shader(RID p_version, int p_variant, uint64_t p_specialization) {
+ ERR_FAIL_INDEX_V(p_variant, variant_count, false);
Version *version = version_owner.get_or_null(p_version);
- ERR_FAIL_COND(!version);
+ ERR_FAIL_COND_V(!version, false);
if (version->variants.size() == 0) {
_initialize_version(version); //may lack initialization
@@ -210,11 +217,12 @@ protected:
if (!spec || !spec->ok) {
WARN_PRINT_ONCE("shader failed to compile, unable to bind shader.");
- return;
+ return false;
}
glUseProgram(spec->id);
current_shader = spec;
+ return true;
}
_FORCE_INLINE_ int _version_get_uniform(int p_which, RID p_version, int p_variant, uint64_t p_specialization) {
diff --git a/drivers/gles3/shaders/SCsub b/drivers/gles3/shaders/SCsub
index b8bb08ec34..34713e7e29 100644
--- a/drivers/gles3/shaders/SCsub
+++ b/drivers/gles3/shaders/SCsub
@@ -19,3 +19,6 @@ if "GLES3_GLSL" in env["BUILDERS"]:
env.GLES3_GLSL("cubemap_filter.glsl")
env.GLES3_GLSL("canvas_occlusion.glsl")
env.GLES3_GLSL("canvas_sdf.glsl")
+ env.GLES3_GLSL("particles.glsl")
+ env.GLES3_GLSL("particles_copy.glsl")
+ env.GLES3_GLSL("skeleton.glsl")
diff --git a/drivers/gles3/shaders/canvas.glsl b/drivers/gles3/shaders/canvas.glsl
index ca806304c5..9a90f33674 100644
--- a/drivers/gles3/shaders/canvas.glsl
+++ b/drivers/gles3/shaders/canvas.glsl
@@ -11,6 +11,7 @@ mode_instanced = #define USE_ATTRIBUTES \n#define USE_INSTANCING
DISABLE_LIGHTING = false
USE_RGBA_SHADOWS = false
+SINGLE_INSTANCE = false
#[vertex]
@@ -19,18 +20,80 @@ layout(location = 0) in vec2 vertex_attrib;
layout(location = 3) in vec4 color_attrib;
layout(location = 4) in vec2 uv_attrib;
-layout(location = 10) in uvec4 bone_attrib;
-layout(location = 11) in vec4 weight_attrib;
-
#ifdef USE_INSTANCING
layout(location = 1) in highp vec4 instance_xform0;
layout(location = 2) in highp vec4 instance_xform1;
layout(location = 5) in highp uvec4 instance_color_custom_data; // Color packed into xy, custom_data packed into zw for compatibility with 3D
+#endif // USE_INSTANCING
+
+#endif // USE_ATTRIBUTES
+
+#include "stdlib_inc.glsl"
+
+layout(location = 6) in highp vec4 attrib_A;
+layout(location = 7) in highp vec4 attrib_B;
+layout(location = 8) in highp vec4 attrib_C;
+layout(location = 9) in highp vec4 attrib_D;
+layout(location = 10) in highp vec4 attrib_E;
+#ifdef USE_PRIMITIVE
+layout(location = 11) in highp uvec4 attrib_F;
+#else
+layout(location = 11) in highp vec4 attrib_F;
+#endif
+layout(location = 12) in highp uvec4 attrib_G;
+layout(location = 13) in highp uvec4 attrib_H;
+
+#define read_draw_data_world_x attrib_A.xy
+#define read_draw_data_world_y attrib_A.zw
+#define read_draw_data_world_ofs attrib_B.xy
+#define read_draw_data_color_texture_pixel_size attrib_B.zw
+
+#ifdef USE_PRIMITIVE
+
+#define read_draw_data_point_a attrib_C.xy
+#define read_draw_data_point_b attrib_C.zw
+#define read_draw_data_point_c attrib_D.xy
+#define read_draw_data_uv_a attrib_D.zw
+#define read_draw_data_uv_b attrib_E.xy
+#define read_draw_data_uv_c attrib_E.zw
+
+#define read_draw_data_color_a_rg attrib_F.x
+#define read_draw_data_color_a_ba attrib_F.y
+#define read_draw_data_color_b_rg attrib_F.z
+#define read_draw_data_color_b_ba attrib_F.w
+#define read_draw_data_color_c_rg attrib_G.x
+#define read_draw_data_color_c_ba attrib_G.y
+
+#else
+
+#define read_draw_data_modulation attrib_C
+#define read_draw_data_ninepatch_margins attrib_D
+#define read_draw_data_dst_rect attrib_E
+#define read_draw_data_src_rect attrib_F
+
#endif
+#define read_draw_data_flags attrib_G.z
+#define read_draw_data_specular_shininess attrib_G.w
+#define read_draw_data_lights attrib_H
+
+// Varyings so the per-instance info can be used in the fragment shader
+flat out vec4 varying_A;
+flat out vec2 varying_B;
+#ifndef USE_PRIMITIVE
+flat out vec4 varying_C;
+#ifndef USE_ATTRIBUTES
+#ifdef USE_NINEPATCH
+
+flat out vec2 varying_D;
+#endif
+flat out vec4 varying_E;
#endif
+#endif
+flat out uvec2 varying_F;
+flat out uvec4 varying_G;
// This needs to be outside clang-format so the ubo comment is in the right place
#ifdef MATERIAL_UNIFORMS_USED
@@ -42,14 +105,10 @@ layout(std140) uniform MaterialUniforms{ //ubo:4
#endif
/* clang-format on */
#include "canvas_uniforms_inc.glsl"
-#include "stdlib_inc.glsl"
-
-uniform sampler2D transforms_texture; //texunit:-1
out vec2 uv_interp;
out vec4 color_interp;
out vec2 vertex_interp;
-flat out int draw_data_instance;
#ifdef USE_NINEPATCH
@@ -60,42 +119,48 @@ out vec2 pixel_size_interp;
#GLOBALS
void main() {
+ varying_A = vec4(read_draw_data_world_x, read_draw_data_world_y);
+ varying_B = read_draw_data_color_texture_pixel_size;
+#ifndef USE_PRIMITIVE
+ varying_C = read_draw_data_ninepatch_margins;
+
+#ifndef USE_ATTRIBUTES
+#ifdef USE_NINEPATCH
+ varying_D = vec2(read_draw_data_dst_rect.z, read_draw_data_dst_rect.w);
+#endif // USE_NINEPATCH
+ varying_E = read_draw_data_src_rect;
+#endif // !USE_ATTRIBUTES
+#endif // USE_PRIMITIVE
+
+ varying_F = uvec2(read_draw_data_flags, read_draw_data_specular_shininess);
+ varying_G = read_draw_data_lights;
+
vec4 instance_custom = vec4(0.0);
#ifdef USE_PRIMITIVE
- draw_data_instance = gl_InstanceID;
vec2 vertex;
vec2 uv;
vec4 color;
if (gl_VertexID % 3 == 0) {
- vertex = draw_data[draw_data_instance].point_a;
- uv = draw_data[draw_data_instance].uv_a;
- color = vec4(unpackHalf2x16(draw_data[draw_data_instance].color_a_rg), unpackHalf2x16(draw_data[draw_data_instance].color_a_ba));
+ vertex = read_draw_data_point_a;
+ uv = read_draw_data_uv_a;
+ color = vec4(unpackHalf2x16(read_draw_data_color_a_rg), unpackHalf2x16(read_draw_data_color_a_ba));
} else if (gl_VertexID % 3 == 1) {
- vertex = draw_data[draw_data_instance].point_b;
- uv = draw_data[draw_data_instance].uv_b;
- color = vec4(unpackHalf2x16(draw_data[draw_data_instance].color_b_rg), unpackHalf2x16(draw_data[draw_data_instance].color_b_ba));
+ vertex = read_draw_data_point_b;
+ uv = read_draw_data_uv_b;
+ color = vec4(unpackHalf2x16(read_draw_data_color_b_rg), unpackHalf2x16(read_draw_data_color_b_ba));
} else {
- vertex = draw_data[draw_data_instance].point_c;
- uv = draw_data[draw_data_instance].uv_c;
- color = vec4(unpackHalf2x16(draw_data[draw_data_instance].color_c_rg), unpackHalf2x16(draw_data[draw_data_instance].color_c_ba));
+ vertex = read_draw_data_point_c;
+ uv = read_draw_data_uv_c;
+ color = vec4(unpackHalf2x16(read_draw_data_color_c_rg), unpackHalf2x16(read_draw_data_color_c_ba));
}
- uvec4 bones = uvec4(0, 0, 0, 0);
- vec4 bone_weights = vec4(0.0);
#elif defined(USE_ATTRIBUTES)
- draw_data_instance = gl_InstanceID;
-#ifdef USE_INSTANCING
- draw_data_instance = 0;
-#endif
vec2 vertex = vertex_attrib;
- vec4 color = color_attrib * draw_data[draw_data_instance].modulation;
+ vec4 color = color_attrib * read_draw_data_modulation;
vec2 uv = uv_attrib;
- uvec4 bones = bone_attrib;
- vec4 bone_weights = weight_attrib;
-
#ifdef USE_INSTANCING
vec4 instance_color = vec4(unpackHalf2x16(instance_color_custom_data.x), unpackHalf2x16(instance_color_custom_data.y));
color *= instance_color;
@@ -103,31 +168,29 @@ void main() {
#endif
#else
- draw_data_instance = gl_VertexID / 6;
vec2 vertex_base_arr[6] = vec2[](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0), vec2(0.0, 0.0), vec2(1.0, 1.0));
vec2 vertex_base = vertex_base_arr[gl_VertexID % 6];
- vec2 uv = draw_data[draw_data_instance].src_rect.xy + abs(draw_data[draw_data_instance].src_rect.zw) * ((draw_data[draw_data_instance].flags & FLAGS_TRANSPOSE_RECT) != uint(0) ? vertex_base.yx : vertex_base.xy);
- vec4 color = draw_data[draw_data_instance].modulation;
- vec2 vertex = draw_data[draw_data_instance].dst_rect.xy + abs(draw_data[draw_data_instance].dst_rect.zw) * mix(vertex_base, vec2(1.0, 1.0) - vertex_base, lessThan(draw_data[draw_data_instance].src_rect.zw, vec2(0.0, 0.0)));
- uvec4 bones = uvec4(0, 0, 0, 0);
+ vec2 uv = read_draw_data_src_rect.xy + abs(read_draw_data_src_rect.zw) * ((read_draw_data_flags & FLAGS_TRANSPOSE_RECT) != uint(0) ? vertex_base.yx : vertex_base.xy);
+ vec4 color = read_draw_data_modulation;
+ vec2 vertex = read_draw_data_dst_rect.xy + abs(read_draw_data_dst_rect.zw) * mix(vertex_base, vec2(1.0, 1.0) - vertex_base, lessThan(read_draw_data_src_rect.zw, vec2(0.0, 0.0)));
#endif
- mat4 model_matrix = mat4(vec4(draw_data[draw_data_instance].world_x, 0.0, 0.0), vec4(draw_data[draw_data_instance].world_y, 0.0, 0.0), vec4(0.0, 0.0, 1.0, 0.0), vec4(draw_data[draw_data_instance].world_ofs, 0.0, 1.0));
+ mat4 model_matrix = mat4(vec4(read_draw_data_world_x, 0.0, 0.0), vec4(read_draw_data_world_y, 0.0, 0.0), vec4(0.0, 0.0, 1.0, 0.0), vec4(read_draw_data_world_ofs, 0.0, 1.0));
#ifdef USE_INSTANCING
model_matrix = model_matrix * transpose(mat4(instance_xform0, instance_xform1, vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0)));
#endif // USE_INSTANCING
#if !defined(USE_ATTRIBUTES) && !defined(USE_PRIMITIVE)
- if (bool(draw_data[draw_data_instance].flags & FLAGS_USING_PARTICLES)) {
+ if (bool(read_draw_data_flags & FLAGS_USING_PARTICLES)) {
//scale by texture size
- vertex /= draw_data[draw_data_instance].color_texture_pixel_size;
+ vertex /= read_draw_data_color_texture_pixel_size;
}
#endif
- vec2 color_texture_pixel_size = draw_data[draw_data_instance].color_texture_pixel_size.xy;
+ vec2 color_texture_pixel_size = read_draw_data_color_texture_pixel_size;
#ifdef USE_POINT_SIZE
float point_size = 1.0;
@@ -137,7 +200,7 @@ void main() {
}
#ifdef USE_NINEPATCH
- pixel_size_interp = abs(draw_data[draw_data_instance].dst_rect.zw) * vertex_base;
+ pixel_size_interp = abs(read_draw_data_dst_rect.zw) * vertex_base;
#endif
#if !defined(SKIP_TRANSFORM_USED)
@@ -153,64 +216,62 @@ void main() {
uv += 1e-5;
}
-#ifdef USE_ATTRIBUTES
-#if 0
- if (bool(draw_data[draw_data_instance].flags & FLAGS_USE_SKELETON) && bone_weights != vec4(0.0)) { //must be a valid bone
- //skeleton transform
- ivec4 bone_indicesi = ivec4(bone_indices);
-
- uvec2 tex_ofs = bone_indicesi.x * 2;
+ vertex = (canvas_transform * vec4(vertex, 0.0, 1.0)).xy;
- mat2x4 m;
- m = mat2x4(
- texelFetch(skeleton_buffer, tex_ofs + 0),
- texelFetch(skeleton_buffer, tex_ofs + 1)) *
- bone_weights.x;
+ vertex_interp = vertex;
+ uv_interp = uv;
- tex_ofs = bone_indicesi.y * 2;
+ gl_Position = screen_transform * vec4(vertex, 0.0, 1.0);
- m += mat2x4(
- texelFetch(skeleton_buffer, tex_ofs + 0),
- texelFetch(skeleton_buffer, tex_ofs + 1)) *
- bone_weights.y;
+#ifdef USE_POINT_SIZE
+ gl_PointSize = point_size;
+#endif
+}
- tex_ofs = bone_indicesi.z * 2;
+#[fragment]
- m += mat2x4(
- texelFetch(skeleton_buffer, tex_ofs + 0),
- texelFetch(skeleton_buffer, tex_ofs + 1)) *
- bone_weights.z;
+#include "canvas_uniforms_inc.glsl"
+#include "stdlib_inc.glsl"
- tex_ofs = bone_indicesi.w * 2;
+in vec2 uv_interp;
+in vec2 vertex_interp;
+in vec4 color_interp;
- m += mat2x4(
- texelFetch(skeleton_buffer, tex_ofs + 0),
- texelFetch(skeleton_buffer, tex_ofs + 1)) *
- bone_weights.w;
+#ifdef USE_NINEPATCH
- mat4 bone_matrix = skeleton_data.skeleton_transform * transpose(mat4(m[0], m[1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0))) * skeleton_data.skeleton_transform_inverse;
+in vec2 pixel_size_interp;
- //outvec = bone_matrix * outvec;
- }
-#endif
#endif
- vertex = (canvas_transform * vec4(vertex, 0.0, 1.0)).xy;
+// Can all be flat as they are the same for the whole batched instance
+flat in vec4 varying_A;
+flat in vec2 varying_B;
+#define read_draw_data_world_x varying_A.xy
+#define read_draw_data_world_y varying_A.zw
+#define read_draw_data_color_texture_pixel_size varying_B
- vertex_interp = vertex;
- uv_interp = uv;
+#ifndef USE_PRIMITIVE
+flat in vec4 varying_C;
+#define read_draw_data_ninepatch_margins varying_C
- gl_Position = screen_transform * vec4(vertex, 0.0, 1.0);
+#ifndef USE_ATTRIBUTES
+#ifdef USE_NINEPATCH
-#ifdef USE_POINT_SIZE
- gl_PointSize = point_size;
+flat in vec2 varying_D;
+#define read_draw_data_dst_rect_z varying_D.x
+#define read_draw_data_dst_rect_w varying_D.y
#endif
-}
-#[fragment]
+flat in vec4 varying_E;
+#define read_draw_data_src_rect varying_E
+#endif // USE_ATTRIBUTES
+#endif // USE_PRIMITIVE
-#include "canvas_uniforms_inc.glsl"
-#include "stdlib_inc.glsl"
+flat in uvec2 varying_F;
+flat in uvec4 varying_G;
+#define read_draw_data_flags varying_F.x
+#define read_draw_data_specular_shininess varying_F.y
+#define read_draw_data_lights varying_G
#ifndef DISABLE_LIGHTING
uniform sampler2D atlas_texture; //texunit:-2
@@ -223,17 +284,6 @@ uniform sampler2D specular_texture; //texunit:-7
uniform sampler2D color_texture; //texunit:0
-in vec2 uv_interp;
-in vec4 color_interp;
-in vec2 vertex_interp;
-flat in int draw_data_instance;
-
-#ifdef USE_NINEPATCH
-
-in vec2 pixel_size_interp;
-
-#endif
-
layout(location = 0) out vec4 frag_color;
#ifdef MATERIAL_UNIFORMS_USED
@@ -339,11 +389,9 @@ vec3 light_normal_compute(vec3 light_vec, vec3 normal, vec3 base_color, vec3 lig
#endif
-#define SHADOW_TEST(m_uv) \
- { \
- highp float sd = SHADOW_DEPTH(m_uv); \
- shadow += step(sd, shadow_uv.z / shadow_uv.w); \
- }
+/* clang-format off */
+#define SHADOW_TEST(m_uv) { highp float sd = SHADOW_DEPTH(m_uv); shadow += step(sd, shadow_uv.z / shadow_uv.w); }
+/* clang-format on */
//float distance = length(shadow_pos);
vec4 light_shadow_compute(uint light_base, vec4 light_color, vec4 shadow_uv
@@ -383,7 +431,7 @@ vec4 light_shadow_compute(uint light_base, vec4 light_color, vec4 shadow_uv
shadow /= 13.0;
}
- vec4 shadow_color = unpackUnorm4x8(light_array[light_base].shadow_color);
+ vec4 shadow_color = godot_unpackUnorm4x8(light_array[light_base].shadow_color);
#ifdef LIGHT_CODE_USED
shadow_color.rgb *= shadow_modulate;
#endif
@@ -421,7 +469,7 @@ float map_ninepatch_axis(float pixel, float draw_size, float tex_pixel_size, flo
} else if (pixel >= draw_size - margin_end) {
return (tex_size - (draw_size - pixel)) * tex_pixel_size;
} else {
- if (!bool(draw_data[draw_data_instance].flags & FLAGS_NINEPACH_DRAW_CENTER)) {
+ if (!bool(read_draw_data_flags & FLAGS_NINEPACH_DRAW_CENTER)) {
draw_center--;
}
@@ -469,28 +517,26 @@ void main() {
int draw_center = 2;
uv = vec2(
- map_ninepatch_axis(pixel_size_interp.x, abs(draw_data[draw_data_instance].dst_rect.z), draw_data[draw_data_instance].color_texture_pixel_size.x, draw_data[draw_data_instance].ninepatch_margins.x, draw_data[draw_data_instance].ninepatch_margins.z, int(draw_data[draw_data_instance].flags >> FLAGS_NINEPATCH_H_MODE_SHIFT) & 0x3, draw_center),
- map_ninepatch_axis(pixel_size_interp.y, abs(draw_data[draw_data_instance].dst_rect.w), draw_data[draw_data_instance].color_texture_pixel_size.y, draw_data[draw_data_instance].ninepatch_margins.y, draw_data[draw_data_instance].ninepatch_margins.w, int(draw_data[draw_data_instance].flags >> FLAGS_NINEPATCH_V_MODE_SHIFT) & 0x3, draw_center));
+ map_ninepatch_axis(pixel_size_interp.x, abs(read_draw_data_dst_rect_z), read_draw_data_color_texture_pixel_size.x, read_draw_data_ninepatch_margins.x, read_draw_data_ninepatch_margins.z, int(read_draw_data_flags >> FLAGS_NINEPATCH_H_MODE_SHIFT) & 0x3, draw_center),
+ map_ninepatch_axis(pixel_size_interp.y, abs(read_draw_data_dst_rect_w), read_draw_data_color_texture_pixel_size.y, read_draw_data_ninepatch_margins.y, read_draw_data_ninepatch_margins.w, int(read_draw_data_flags >> FLAGS_NINEPATCH_V_MODE_SHIFT) & 0x3, draw_center));
if (draw_center == 0) {
color.a = 0.0;
}
- uv = uv * draw_data[draw_data_instance].src_rect.zw + draw_data[draw_data_instance].src_rect.xy; //apply region if needed
+ uv = uv * read_draw_data_src_rect.zw + read_draw_data_src_rect.xy; //apply region if needed
#endif
- if (bool(draw_data[draw_data_instance].flags & FLAGS_CLIP_RECT_UV)) {
- uv = clamp(uv, draw_data[draw_data_instance].src_rect.xy, draw_data[draw_data_instance].src_rect.xy + abs(draw_data[draw_data_instance].src_rect.zw));
+ if (bool(read_draw_data_flags & FLAGS_CLIP_RECT_UV)) {
+ uv = clamp(uv, read_draw_data_src_rect.xy, read_draw_data_src_rect.xy + abs(read_draw_data_src_rect.zw));
}
#endif
#ifndef USE_PRIMITIVE
- if (bool(draw_data[draw_data_instance].flags & FLAGS_USE_MSDF)) {
- float px_range = draw_data[draw_data_instance].ninepatch_margins.x;
- float outline_thickness = draw_data[draw_data_instance].ninepatch_margins.y;
- //float reserved1 = draw_data[draw_data_instance].ninepatch_margins.z;
- //float reserved2 = draw_data[draw_data_instance].ninepatch_margins.w;
+ if (bool(read_draw_data_flags & FLAGS_USE_MSDF)) {
+ float px_range = read_draw_data_ninepatch_margins.x;
+ float outline_thickness = read_draw_data_ninepatch_margins.y;
vec4 msdf_sample = texture(color_texture, uv);
vec2 msdf_size = vec2(textureSize(color_texture, 0));
@@ -506,7 +552,7 @@ void main() {
float a = clamp(d * px_size + 0.5, 0.0, 1.0);
color.a = a * color.a;
}
- } else if (bool(draw_data[draw_data_instance].flags & FLAGS_USE_LCD)) {
+ } else if (bool(read_draw_data_flags & FLAGS_USE_LCD)) {
vec4 lcd_sample = texture(color_texture, uv);
if (lcd_sample.a == 1.0) {
color.rgb = lcd_sample.rgb * color.a;
@@ -520,7 +566,7 @@ void main() {
color *= texture(color_texture, uv);
}
- uint light_count = (draw_data[draw_data_instance].flags >> uint(FLAGS_LIGHT_COUNT_SHIFT)) & uint(0xF); //max 16 lights
+ uint light_count = (read_draw_data_flags >> uint(FLAGS_LIGHT_COUNT_SHIFT)) & uint(0xF); //max 16 lights
bool using_light = light_count > 0u || directional_light_count > 0u;
vec3 normal;
@@ -531,7 +577,7 @@ void main() {
bool normal_used = false;
#endif
- if (normal_used || (using_light && bool(draw_data[draw_data_instance].flags & FLAGS_DEFAULT_NORMAL_MAP_USED))) {
+ if (normal_used || (using_light && bool(read_draw_data_flags & FLAGS_DEFAULT_NORMAL_MAP_USED))) {
normal.xy = texture(normal_texture, uv).xy * vec2(2.0, -2.0) - vec2(1.0, -1.0);
normal.z = sqrt(1.0 - dot(normal.xy, normal.xy));
normal_used = true;
@@ -548,9 +594,9 @@ void main() {
bool specular_shininess_used = false;
#endif
- if (specular_shininess_used || (using_light && normal_used && bool(draw_data[draw_data_instance].flags & FLAGS_DEFAULT_SPECULAR_MAP_USED))) {
+ if (specular_shininess_used || (using_light && normal_used && bool(read_draw_data_flags & FLAGS_DEFAULT_SPECULAR_MAP_USED))) {
specular_shininess = texture(specular_texture, uv);
- specular_shininess *= unpackUnorm4x8(draw_data[draw_data_instance].specular_shininess);
+ specular_shininess *= godot_unpackUnorm4x8(read_draw_data_specular_shininess);
specular_shininess_used = true;
} else {
specular_shininess = vec4(1.0);
@@ -562,7 +608,7 @@ void main() {
vec2 screen_uv = vec2(0.0);
#endif
- vec2 color_texture_pixel_size = draw_data[draw_data_instance].color_texture_pixel_size.xy;
+ vec2 color_texture_pixel_size = read_draw_data_color_texture_pixel_size.xy;
vec3 light_vertex = vec3(vertex, 0.0);
vec2 shadow_vertex = vertex;
@@ -584,7 +630,7 @@ void main() {
if (normal_used) {
//convert by item transform
- normal.xy = mat2(normalize(draw_data[draw_data_instance].world_x), normalize(draw_data[draw_data_instance].world_y)) * normal.xy;
+ normal.xy = mat2(normalize(read_draw_data_world_x), normalize(read_draw_data_world_y)) * normal.xy;
//convert by canvas transform
normal = normalize((canvas_normal_transform * vec4(normal, 0.0)).xyz);
}
@@ -646,15 +692,15 @@ void main() {
uint light_base;
if (i < 8u) {
if (i < 4u) {
- light_base = draw_data[draw_data_instance].lights[0];
+ light_base = read_draw_data_lights[0];
} else {
- light_base = draw_data[draw_data_instance].lights[1];
+ light_base = read_draw_data_lights[1];
}
} else {
if (i < 12u) {
- light_base = draw_data[draw_data_instance].lights[2];
+ light_base = read_draw_data_lights[2];
} else {
- light_base = draw_data[draw_data_instance].lights[3];
+ light_base = read_draw_data_lights[3];
}
}
light_base >>= (i & 3u) * 8u;
diff --git a/drivers/gles3/shaders/canvas_uniforms_inc.glsl b/drivers/gles3/shaders/canvas_uniforms_inc.glsl
index dd5ebecb1a..f65558f042 100644
--- a/drivers/gles3/shaders/canvas_uniforms_inc.glsl
+++ b/drivers/gles3/shaders/canvas_uniforms_inc.glsl
@@ -27,38 +27,6 @@
#define FLAGS_USE_MSDF uint(1 << 28)
#define FLAGS_USE_LCD uint(1 << 29)
-// must be always 128 bytes long
-struct DrawData {
- vec2 world_x;
- vec2 world_y;
- vec2 world_ofs;
- vec2 color_texture_pixel_size;
-#ifdef USE_PRIMITIVE
- vec2 point_a;
- vec2 point_b;
- vec2 point_c;
- vec2 uv_a;
- vec2 uv_b;
- vec2 uv_c;
- uint color_a_rg;
- uint color_a_ba;
- uint color_b_rg;
- uint color_b_ba;
- uint color_c_rg;
- uint color_c_ba;
-#else
- vec4 modulation;
- vec4 ninepatch_margins;
- vec4 dst_rect; //for built-in rect and UV
- vec4 src_rect;
- uint pad;
- uint pad2;
-#endif
- uint flags;
- uint specular_shininess;
- uvec4 lights;
-};
-
layout(std140) uniform GlobalShaderUniformData { //ubo:1
vec4 global_shader_uniforms[MAX_GLOBAL_SHADER_UNIFORMS];
};
@@ -116,7 +84,3 @@ layout(std140) uniform LightData { //ubo:2
Light light_array[MAX_LIGHTS];
};
#endif // DISABLE_LIGHTING
-layout(std140) uniform DrawDataInstances { //ubo:3
-
- DrawData draw_data[MAX_DRAW_DATA_INSTANCES];
-};
diff --git a/drivers/gles3/shaders/cubemap_filter.glsl b/drivers/gles3/shaders/cubemap_filter.glsl
index 88464876f1..6fcb23204d 100644
--- a/drivers/gles3/shaders/cubemap_filter.glsl
+++ b/drivers/gles3/shaders/cubemap_filter.glsl
@@ -31,7 +31,7 @@ uniform samplerCube source_cube; //texunit:0
uniform int face_id;
#ifndef MODE_DIRECT_WRITE
-uniform int sample_count;
+uniform uint sample_count;
uniform vec4 sample_directions_mip[MAX_SAMPLE_COUNT];
uniform float weight;
#endif
@@ -105,7 +105,7 @@ void main() {
T[1] = cross(N, T[0]);
T[2] = N;
- for (int sample_num = 0; sample_num < sample_count; sample_num++) {
+ for (uint sample_num = 0u; sample_num < sample_count; sample_num++) {
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;
diff --git a/drivers/gles3/shaders/particles.glsl b/drivers/gles3/shaders/particles.glsl
new file mode 100644
index 0000000000..f8741a22ab
--- /dev/null
+++ b/drivers/gles3/shaders/particles.glsl
@@ -0,0 +1,501 @@
+/* clang-format off */
+#[modes]
+
+mode_default =
+
+#[specializations]
+
+MODE_3D = false
+USERDATA1_USED = false
+USERDATA2_USED = false
+USERDATA3_USED = false
+USERDATA4_USED = false
+USERDATA5_USED = false
+USERDATA6_USED = false
+
+#[vertex]
+
+#define SDF_MAX_LENGTH 16384.0
+
+layout(std140) uniform GlobalShaderUniformData { //ubo:1
+ vec4 global_shader_uniforms[MAX_GLOBAL_SHADER_UNIFORMS];
+};
+
+// This needs to be outside clang-format so the ubo comment is in the right place
+#ifdef MATERIAL_UNIFORMS_USED
+layout(std140) uniform MaterialUniforms{ //ubo:2
+
+#MATERIAL_UNIFORMS
+
+};
+#endif
+
+/* clang-format on */
+
+#define MAX_ATTRACTORS 32
+
+#define ATTRACTOR_TYPE_SPHERE uint(0)
+#define ATTRACTOR_TYPE_BOX uint(1)
+#define ATTRACTOR_TYPE_VECTOR_FIELD uint(2)
+
+struct Attractor {
+ mat4 transform;
+ vec4 extents; // Extents or radius. w-channel is padding.
+
+ uint type;
+ float strength;
+ float attenuation;
+ float directionality;
+};
+
+#define MAX_COLLIDERS 32
+
+#define COLLIDER_TYPE_SPHERE uint(0)
+#define COLLIDER_TYPE_BOX uint(1)
+#define COLLIDER_TYPE_SDF uint(2)
+#define COLLIDER_TYPE_HEIGHT_FIELD uint(3)
+#define COLLIDER_TYPE_2D_SDF uint(4)
+
+struct Collider {
+ mat4 transform;
+ vec4 extents; // Extents or radius. w-channel is padding.
+
+ uint type;
+ float scale;
+ float pad0;
+ float pad1;
+};
+
+layout(std140) uniform FrameData { //ubo:0
+ bool emitting;
+ uint cycle;
+ float system_phase;
+ float prev_system_phase;
+
+ float explosiveness;
+ float randomness;
+ float time;
+ float delta;
+
+ float particle_size;
+ float pad0;
+ float pad1;
+ float pad2;
+
+ uint random_seed;
+ uint attractor_count;
+ uint collider_count;
+ uint frame;
+
+ mat4 emission_transform;
+
+ Attractor attractors[MAX_ATTRACTORS];
+ Collider colliders[MAX_COLLIDERS];
+};
+
+#define PARTICLE_FLAG_ACTIVE uint(1)
+#define PARTICLE_FLAG_STARTED uint(2)
+#define PARTICLE_FLAG_TRAILED uint(4)
+#define PARTICLE_FRAME_MASK uint(0xFFFF)
+#define PARTICLE_FRAME_SHIFT uint(16)
+
+// ParticleData
+layout(location = 0) in highp vec4 color;
+layout(location = 1) in highp vec4 velocity_flags;
+layout(location = 2) in highp vec4 custom;
+layout(location = 3) in highp vec4 xform_1;
+layout(location = 4) in highp vec4 xform_2;
+#ifdef MODE_3D
+layout(location = 5) in highp vec4 xform_3;
+#endif
+#ifdef USERDATA1_USED
+layout(location = 6) in highp vec4 userdata1;
+#endif
+#ifdef USERDATA2_USED
+layout(location = 7) in highp vec4 userdata2;
+#endif
+#ifdef USERDATA3_USED
+layout(location = 8) in highp vec4 userdata3;
+#endif
+#ifdef USERDATA4_USED
+layout(location = 9) in highp vec4 userdata4;
+#endif
+#ifdef USERDATA5_USED
+layout(location = 10) in highp vec4 userdata5;
+#endif
+#ifdef USERDATA6_USED
+layout(location = 11) in highp vec4 userdata6;
+#endif
+
+out highp vec4 out_color; //tfb:
+out highp vec4 out_velocity_flags; //tfb:
+out highp vec4 out_custom; //tfb:
+out highp vec4 out_xform_1; //tfb:
+out highp vec4 out_xform_2; //tfb:
+#ifdef MODE_3D
+out highp vec4 out_xform_3; //tfb:MODE_3D
+#endif
+#ifdef USERDATA1_USED
+out highp vec4 out_userdata1; //tfb:USERDATA1_USED
+#endif
+#ifdef USERDATA2_USED
+out highp vec4 out_userdata2; //tfb:USERDATA2_USED
+#endif
+#ifdef USERDATA3_USED
+out highp vec4 out_userdata3; //tfb:USERDATA3_USED
+#endif
+#ifdef USERDATA4_USED
+out highp vec4 out_userdata4; //tfb:USERDATA4_USED
+#endif
+#ifdef USERDATA5_USED
+out highp vec4 out_userdata5; //tfb:USERDATA5_USED
+#endif
+#ifdef USERDATA6_USED
+out highp vec4 out_userdata6; //tfb:USERDATA6_USED
+#endif
+
+uniform sampler2D height_field_texture; //texunit:0
+
+uniform float lifetime;
+uniform bool clear;
+uniform uint total_particles;
+uniform bool use_fractional_delta;
+
+uint hash(uint x) {
+ x = ((x >> uint(16)) ^ x) * uint(0x45d9f3b);
+ x = ((x >> uint(16)) ^ x) * uint(0x45d9f3b);
+ x = (x >> uint(16)) ^ x;
+ return x;
+}
+
+vec3 safe_normalize(vec3 direction) {
+ const float EPSILON = 0.001;
+ if (length(direction) < EPSILON) {
+ return vec3(0.0);
+ }
+ return normalize(direction);
+}
+
+// Needed whenever 2D sdf texture is read from as it is packed in RGBA8.
+float vec4_to_float(vec4 p_vec) {
+ return dot(p_vec, vec4(1.0 / (255.0 * 255.0 * 255.0), 1.0 / (255.0 * 255.0), 1.0 / 255.0, 1.0)) * 2.0 - 1.0;
+}
+
+#GLOBALS
+
+void main() {
+ bool apply_forces = true;
+ bool apply_velocity = true;
+ float local_delta = delta;
+
+ float mass = 1.0;
+
+ bool restart = false;
+
+ bool restart_position = false;
+ bool restart_rotation_scale = false;
+ bool restart_velocity = false;
+ bool restart_color = false;
+ bool restart_custom = false;
+
+ mat4 xform = mat4(1.0);
+ uint flags = 0u;
+
+ if (clear) {
+ out_color = vec4(1.0);
+ out_custom = vec4(0.0);
+ out_velocity_flags = vec4(0.0);
+ } else {
+ out_color = color;
+ out_velocity_flags = velocity_flags;
+ out_custom = custom;
+ xform[0] = xform_1;
+ xform[1] = xform_2;
+#ifdef MODE_3D
+ xform[2] = xform_3;
+#endif
+ xform = transpose(xform);
+ flags = floatBitsToUint(velocity_flags.w);
+ }
+
+ //clear started flag if set
+ flags &= ~PARTICLE_FLAG_STARTED;
+
+ bool collided = false;
+ vec3 collision_normal = vec3(0.0);
+ float collision_depth = 0.0;
+
+ vec3 attractor_force = vec3(0.0);
+
+#if !defined(DISABLE_VELOCITY)
+
+ if (bool(flags & PARTICLE_FLAG_ACTIVE)) {
+ xform[3].xyz += out_velocity_flags.xyz * local_delta;
+ }
+#endif
+ uint index = uint(gl_VertexID);
+ if (emitting) {
+ float restart_phase = float(index) / float(total_particles);
+
+ if (randomness > 0.0) {
+ uint seed = cycle;
+ if (restart_phase >= system_phase) {
+ seed -= uint(1);
+ }
+ seed *= uint(total_particles);
+ seed += index;
+ float random = float(hash(seed) % uint(65536)) / 65536.0;
+ restart_phase += randomness * random * 1.0 / float(total_particles);
+ }
+
+ restart_phase *= (1.0 - explosiveness);
+
+ if (system_phase > prev_system_phase) {
+ // restart_phase >= prev_system_phase is used so particles emit in the first frame they are processed
+
+ if (restart_phase >= prev_system_phase && restart_phase < system_phase) {
+ restart = true;
+ if (use_fractional_delta) {
+ local_delta = (system_phase - restart_phase) * lifetime;
+ }
+ }
+
+ } else if (delta > 0.0) {
+ if (restart_phase >= prev_system_phase) {
+ restart = true;
+ if (use_fractional_delta) {
+ local_delta = (1.0 - restart_phase + system_phase) * lifetime;
+ }
+
+ } else if (restart_phase < system_phase) {
+ restart = true;
+ if (use_fractional_delta) {
+ local_delta = (system_phase - restart_phase) * lifetime;
+ }
+ }
+ }
+
+ if (restart) {
+ flags = emitting ? (PARTICLE_FLAG_ACTIVE | PARTICLE_FLAG_STARTED | (cycle << PARTICLE_FRAME_SHIFT)) : 0u;
+ restart_position = true;
+ restart_rotation_scale = true;
+ restart_velocity = true;
+ restart_color = true;
+ restart_custom = true;
+ }
+ }
+
+ bool particle_active = bool(flags & PARTICLE_FLAG_ACTIVE);
+
+ uint particle_number = (flags >> PARTICLE_FRAME_SHIFT) * uint(total_particles) + index;
+
+ if (restart && particle_active) {
+#CODE : START
+ }
+
+ if (particle_active) {
+ for (uint i = 0u; i < attractor_count; i++) {
+ vec3 dir;
+ float amount;
+ vec3 rel_vec = xform[3].xyz - attractors[i].transform[3].xyz;
+ vec3 local_pos = rel_vec * mat3(attractors[i].transform);
+
+ switch (attractors[i].type) {
+ case ATTRACTOR_TYPE_SPHERE: {
+ dir = safe_normalize(rel_vec);
+ float d = length(local_pos) / attractors[i].extents.x;
+ if (d > 1.0) {
+ continue;
+ }
+ amount = max(0.0, 1.0 - d);
+ } break;
+ case ATTRACTOR_TYPE_BOX: {
+ dir = safe_normalize(rel_vec);
+
+ vec3 abs_pos = abs(local_pos / attractors[i].extents.xyz);
+ float d = max(abs_pos.x, max(abs_pos.y, abs_pos.z));
+ if (d > 1.0) {
+ continue;
+ }
+ amount = max(0.0, 1.0 - d);
+
+ } break;
+ case ATTRACTOR_TYPE_VECTOR_FIELD: {
+ } break;
+ }
+ amount = pow(amount, attractors[i].attenuation);
+ dir = safe_normalize(mix(dir, attractors[i].transform[2].xyz, attractors[i].directionality));
+ attractor_force -= amount * dir * attractors[i].strength;
+ }
+
+ float particle_size = particle_size;
+
+#ifdef USE_COLLISION_SCALE
+
+ particle_size *= dot(vec3(length(xform[0].xyz), length(xform[1].xyz), length(xform[2].xyz)), vec3(0.33333333333));
+
+#endif
+
+ if (collider_count == 1u && colliders[0].type == COLLIDER_TYPE_2D_SDF) {
+ //2D collision
+
+ vec2 pos = xform[3].xy;
+ vec4 to_sdf_x = colliders[0].transform[0];
+ vec4 to_sdf_y = colliders[0].transform[1];
+ vec2 sdf_pos = vec2(dot(vec4(pos, 0, 1), to_sdf_x), dot(vec4(pos, 0, 1), to_sdf_y));
+
+ vec4 sdf_to_screen = vec4(colliders[0].extents.xyz, colliders[0].scale);
+
+ vec2 uv_pos = sdf_pos * sdf_to_screen.xy + sdf_to_screen.zw;
+
+ if (all(greaterThan(uv_pos, vec2(0.0))) && all(lessThan(uv_pos, vec2(1.0)))) {
+ vec2 pos2 = pos + vec2(0, particle_size);
+ vec2 sdf_pos2 = vec2(dot(vec4(pos2, 0, 1), to_sdf_x), dot(vec4(pos2, 0, 1), to_sdf_y));
+ float sdf_particle_size = distance(sdf_pos, sdf_pos2);
+
+ float d = vec4_to_float(texture(height_field_texture, uv_pos)) * SDF_MAX_LENGTH;
+
+ d -= sdf_particle_size;
+
+ if (d < 0.0) {
+ const float EPSILON = 0.001;
+ vec2 n = normalize(vec2(
+ vec4_to_float(texture(height_field_texture, uv_pos + vec2(EPSILON, 0.0))) - vec4_to_float(texture(height_field_texture, uv_pos - vec2(EPSILON, 0.0))),
+ vec4_to_float(texture(height_field_texture, uv_pos + vec2(0.0, EPSILON))) - vec4_to_float(texture(height_field_texture, uv_pos - vec2(0.0, EPSILON)))));
+
+ collided = true;
+ sdf_pos2 = sdf_pos + n * d;
+ pos2 = vec2(dot(vec4(sdf_pos2, 0, 1), colliders[0].transform[2]), dot(vec4(sdf_pos2, 0, 1), colliders[0].transform[3]));
+
+ n = pos - pos2;
+
+ collision_normal = normalize(vec3(n, 0.0));
+ collision_depth = length(n);
+ }
+ }
+
+ } else {
+ for (uint i = 0u; i < collider_count; i++) {
+ vec3 normal;
+ float depth;
+ bool col = false;
+
+ vec3 rel_vec = xform[3].xyz - colliders[i].transform[3].xyz;
+ vec3 local_pos = rel_vec * mat3(colliders[i].transform);
+
+ switch (colliders[i].type) {
+ case COLLIDER_TYPE_SPHERE: {
+ float d = length(rel_vec) - (particle_size + colliders[i].extents.x);
+
+ if (d < 0.0) {
+ col = true;
+ depth = -d;
+ normal = normalize(rel_vec);
+ }
+
+ } break;
+ case COLLIDER_TYPE_BOX: {
+ vec3 abs_pos = abs(local_pos);
+ vec3 sgn_pos = sign(local_pos);
+
+ if (any(greaterThan(abs_pos, colliders[i].extents.xyz))) {
+ //point outside box
+
+ vec3 closest = min(abs_pos, colliders[i].extents.xyz);
+ vec3 rel = abs_pos - closest;
+ depth = length(rel) - particle_size;
+ if (depth < 0.0) {
+ col = true;
+ normal = mat3(colliders[i].transform) * (normalize(rel) * sgn_pos);
+ depth = -depth;
+ }
+ } else {
+ //point inside box
+ vec3 axis_len = colliders[i].extents.xyz - abs_pos;
+ // there has to be a faster way to do this?
+ if (all(lessThan(axis_len.xx, axis_len.yz))) {
+ normal = vec3(1, 0, 0);
+ } else if (all(lessThan(axis_len.yy, axis_len.xz))) {
+ normal = vec3(0, 1, 0);
+ } else {
+ normal = vec3(0, 0, 1);
+ }
+
+ col = true;
+ depth = dot(normal * axis_len, vec3(1)) + particle_size;
+ normal = mat3(colliders[i].transform) * (normal * sgn_pos);
+ }
+
+ } break;
+ case COLLIDER_TYPE_SDF: {
+ } break;
+ case COLLIDER_TYPE_HEIGHT_FIELD: {
+ vec3 local_pos_bottom = local_pos;
+ local_pos_bottom.y -= particle_size;
+
+ if (any(greaterThan(abs(local_pos_bottom), colliders[i].extents.xyz))) {
+ continue;
+ }
+ const float DELTA = 1.0 / 8192.0;
+
+ vec3 uvw_pos = vec3(local_pos_bottom / colliders[i].extents.xyz) * 0.5 + 0.5;
+
+ float y = 1.0 - texture(height_field_texture, uvw_pos.xz).r;
+
+ if (y > uvw_pos.y) {
+ //inside heightfield
+
+ vec3 pos1 = (vec3(uvw_pos.x, y, uvw_pos.z) * 2.0 - 1.0) * colliders[i].extents.xyz;
+ vec3 pos2 = (vec3(uvw_pos.x + DELTA, 1.0 - texture(height_field_texture, uvw_pos.xz + vec2(DELTA, 0)).r, uvw_pos.z) * 2.0 - 1.0) * colliders[i].extents.xyz;
+ vec3 pos3 = (vec3(uvw_pos.x, 1.0 - texture(height_field_texture, uvw_pos.xz + vec2(0, DELTA)).r, uvw_pos.z + DELTA) * 2.0 - 1.0) * colliders[i].extents.xyz;
+
+ normal = normalize(cross(pos1 - pos2, pos1 - pos3));
+ float local_y = (vec3(local_pos / colliders[i].extents.xyz) * 0.5 + 0.5).y;
+
+ col = true;
+ depth = dot(normal, pos1) - dot(normal, local_pos_bottom);
+ }
+
+ } break;
+ }
+
+ if (col) {
+ if (!collided) {
+ collided = true;
+ collision_normal = normal;
+ collision_depth = depth;
+ } else {
+ vec3 c = collision_normal * collision_depth;
+ c += normal * max(0.0, depth - dot(normal, c));
+ collision_normal = normalize(c);
+ collision_depth = length(c);
+ }
+ }
+ }
+ }
+ }
+
+ if (particle_active) {
+#CODE : PROCESS
+ }
+
+ flags &= ~PARTICLE_FLAG_ACTIVE;
+ if (particle_active) {
+ flags |= PARTICLE_FLAG_ACTIVE;
+ }
+
+ xform = transpose(xform);
+ out_xform_1 = xform[0];
+ out_xform_2 = xform[1];
+#ifdef MODE_3D
+ out_xform_3 = xform[2];
+#endif
+ out_velocity_flags.w = uintBitsToFloat(flags);
+}
+
+/* clang-format off */
+#[fragment]
+
+void main() {
+}
+/* clang-format on */
diff --git a/drivers/gles3/shaders/particles_copy.glsl b/drivers/gles3/shaders/particles_copy.glsl
new file mode 100644
index 0000000000..f273cb7b64
--- /dev/null
+++ b/drivers/gles3/shaders/particles_copy.glsl
@@ -0,0 +1,122 @@
+/* clang-format off */
+#[modes]
+
+mode_default =
+
+#[specializations]
+
+MODE_3D = false
+
+#[vertex]
+
+#include "stdlib_inc.glsl"
+
+// ParticleData
+layout(location = 0) in highp vec4 color;
+layout(location = 1) in highp vec4 velocity_flags;
+layout(location = 2) in highp vec4 custom;
+layout(location = 3) in highp vec4 xform_1;
+layout(location = 4) in highp vec4 xform_2;
+#ifdef MODE_3D
+layout(location = 5) in highp vec4 xform_3;
+#endif
+
+/* clang-format on */
+out highp vec4 out_xform_1; //tfb:
+out highp vec4 out_xform_2; //tfb:
+#ifdef MODE_3D
+out highp vec4 out_xform_3; //tfb:MODE_3D
+#endif
+flat out highp uvec4 instance_color_custom_data; //tfb:
+
+uniform lowp vec3 sort_direction;
+uniform highp float frame_remainder;
+
+uniform highp vec3 align_up;
+uniform highp uint align_mode;
+
+uniform highp mat4 inv_emission_transform;
+
+#define TRANSFORM_ALIGN_DISABLED uint(0)
+#define TRANSFORM_ALIGN_Z_BILLBOARD uint(1)
+#define TRANSFORM_ALIGN_Y_TO_VELOCITY uint(2)
+#define TRANSFORM_ALIGN_Z_BILLBOARD_Y_TO_VELOCITY uint(3)
+
+#define PARTICLE_FLAG_ACTIVE uint(1)
+
+void main() {
+ mat4 txform = mat4(vec4(0.0), vec4(0.0), vec4(0.0), vec4(0.0)); // zero scale, becomes invisible.
+ if (bool(floatBitsToUint(velocity_flags.w) & PARTICLE_FLAG_ACTIVE)) {
+#ifdef MODE_3D
+ txform = transpose(mat4(xform_1, xform_2, xform_3, vec4(0.0, 0.0, 0.0, 1.0)));
+#else
+ txform = transpose(mat4(xform_1, xform_2, vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0)));
+#endif
+
+ switch (align_mode) {
+ case TRANSFORM_ALIGN_DISABLED: {
+ } break; //nothing
+ case TRANSFORM_ALIGN_Z_BILLBOARD: {
+ mat3 local = mat3(normalize(cross(align_up, sort_direction)), align_up, sort_direction);
+ local = local * mat3(txform);
+ txform[0].xyz = local[0];
+ txform[1].xyz = local[1];
+ txform[2].xyz = local[2];
+
+ } break;
+ case TRANSFORM_ALIGN_Y_TO_VELOCITY: {
+ vec3 v = velocity_flags.xyz;
+ float s = (length(txform[0]) + length(txform[1]) + length(txform[2])) / 3.0;
+ if (length(v) > 0.0) {
+ txform[1].xyz = normalize(v);
+ } else {
+ txform[1].xyz = normalize(txform[1].xyz);
+ }
+
+ txform[0].xyz = normalize(cross(txform[1].xyz, txform[2].xyz));
+ txform[2].xyz = vec3(0.0, 0.0, 1.0) * s;
+ txform[0].xyz *= s;
+ txform[1].xyz *= s;
+ } break;
+ case TRANSFORM_ALIGN_Z_BILLBOARD_Y_TO_VELOCITY: {
+ vec3 sv = velocity_flags.xyz - sort_direction * dot(sort_direction, velocity_flags.xyz); //screen velocity
+ float s = (length(txform[0]) + length(txform[1]) + length(txform[2])) / 3.0;
+
+ if (length(sv) == 0.0) {
+ sv = align_up;
+ }
+
+ sv = normalize(sv);
+
+ txform[0].xyz = normalize(cross(sv, sort_direction)) * s;
+ txform[1].xyz = sv * s;
+ txform[2].xyz = sort_direction * s;
+
+ } break;
+ }
+
+ txform[3].xyz += velocity_flags.xyz * frame_remainder;
+
+#ifndef MODE_3D
+ // In global mode, bring 2D particles to local coordinates
+ // as they will be drawn with the node position as origin.
+ txform = inv_emission_transform * txform;
+#endif
+
+ txform = transpose(txform);
+ }
+
+ instance_color_custom_data = uvec4(packHalf2x16(color.xy), packHalf2x16(color.zw), packHalf2x16(custom.xy), packHalf2x16(custom.zw));
+ out_xform_1 = txform[0];
+ out_xform_2 = txform[1];
+#ifdef MODE_3D
+ out_xform_3 = txform[2];
+#endif
+}
+
+/* clang-format off */
+#[fragment]
+
+void main() {
+}
+/* clang-format on */
diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl
index ed176c7829..1b922fa726 100644
--- a/drivers/gles3/shaders/scene.glsl
+++ b/drivers/gles3/shaders/scene.glsl
@@ -102,7 +102,7 @@ vec3 oct_to_vec3(vec2 e) {
vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));
float t = max(-v.z, 0.0);
v.xy += t * -sign(v.xy);
- return v;
+ return normalize(v);
}
#ifdef USE_INSTANCING
@@ -129,7 +129,7 @@ layout(std140) uniform SceneData { // ubo:2
mediump float ambient_color_sky_mix;
bool material_uv2_mode;
- float pad2;
+ float emissive_exposure_normalization;
bool use_ambient_light;
bool use_ambient_cubemap;
bool use_reflection_cubemap;
@@ -142,7 +142,7 @@ layout(std140) uniform SceneData { // ubo:2
uint directional_light_count;
float z_far;
float z_near;
- float pad;
+ float IBL_exposure_normalization;
bool fog_enabled;
float fog_density;
@@ -151,6 +151,10 @@ layout(std140) uniform SceneData { // ubo:2
vec3 fog_light_color;
float fog_sun_scatter;
+ uint camera_visible_layers;
+ uint pad3;
+ uint pad4;
+ uint pad5;
}
scene_data;
@@ -197,7 +201,7 @@ out vec3 tangent_interp;
out vec3 binormal_interp;
#endif
-#if defined(MATERIAL_UNIFORMS_USED)
+#ifdef MATERIAL_UNIFORMS_USED
/* clang-format off */
layout(std140) uniform MaterialUniforms { // ubo:3
@@ -366,7 +370,9 @@ void main() {
#endif
#endif
+#ifndef MODE_RENDER_DEPTH
#include "tonemap_inc.glsl"
+#endif
#include "stdlib_inc.glsl"
/* texture unit usage, N is max_texture_unity-N
@@ -428,7 +434,7 @@ layout(std140) uniform GlobalShaderUniformData { //ubo:1
/* Material Uniforms */
-#if defined(MATERIAL_UNIFORMS_USED)
+#ifdef MATERIAL_UNIFORMS_USED
/* clang-format off */
layout(std140) uniform MaterialUniforms { // ubo:3
@@ -453,7 +459,7 @@ layout(std140) uniform SceneData { // ubo:2
mediump float ambient_color_sky_mix;
bool material_uv2_mode;
- float pad2;
+ float emissive_exposure_normalization;
bool use_ambient_light;
bool use_ambient_cubemap;
bool use_reflection_cubemap;
@@ -466,7 +472,7 @@ layout(std140) uniform SceneData { // ubo:2
uint directional_light_count;
float z_far;
float z_near;
- float pad;
+ float IBL_exposure_normalization;
bool fog_enabled;
float fog_density;
@@ -475,6 +481,10 @@ layout(std140) uniform SceneData { // ubo:2
vec3 fog_light_color;
float fog_sun_scatter;
+ uint camera_visible_layers;
+ uint pad3;
+ uint pad4;
+ uint pad5;
}
scene_data;
@@ -493,8 +503,7 @@ multiview_data;
/* clang-format on */
-//directional light data
-
+// Directional light data.
#ifndef DISABLE_LIGHT_DIRECTIONAL
struct DirectionalLightData {
@@ -510,11 +519,12 @@ layout(std140) uniform DirectionalLights { // ubo:7
DirectionalLightData directional_lights[MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS];
};
-#endif
+#endif // !DISABLE_LIGHT_DIRECTIONAL
+
+// Omni and spot light data.
+#if !defined(DISABLE_LIGHT_OMNI) || !defined(DISABLE_LIGHT_SPOT)
-// omni and spot
-#if !defined(DISABLE_LIGHT_OMNI) && !defined(DISABLE_LIGHT_SPOT)
-struct LightData { //this structure needs to be as packed as possible
+struct LightData { // This structure needs to be as packed as possible.
highp vec3 position;
highp float inv_radius;
@@ -529,30 +539,28 @@ struct LightData { //this structure needs to be as packed as possible
mediump float specular_amount;
mediump float shadow_opacity;
};
+
#ifndef DISABLE_LIGHT_OMNI
layout(std140) uniform OmniLightData { // ubo:5
-
LightData omni_lights[MAX_LIGHT_DATA_STRUCTS];
};
uniform uint omni_light_indices[MAX_FORWARD_LIGHTS];
-uniform int omni_light_count;
+uniform uint omni_light_count;
#endif
#ifndef DISABLE_LIGHT_SPOT
-
layout(std140) uniform SpotLightData { // ubo:6
-
LightData spot_lights[MAX_LIGHT_DATA_STRUCTS];
};
uniform uint spot_light_indices[MAX_FORWARD_LIGHTS];
-uniform int spot_light_count;
+uniform uint spot_light_count;
#endif
#ifdef USE_ADDITIVE_LIGHTING
uniform highp samplerCubeShadow positional_shadow; // texunit:-4
#endif
-#endif // !defined(DISABLE_LIGHT_OMNI) && !defined(DISABLE_LIGHT_SPOT)
+#endif // !defined(DISABLE_LIGHT_OMNI) || !defined(DISABLE_LIGHT_SPOT)
#ifdef USE_MULTIVIEW
uniform highp sampler2DArray depth_buffer; // texunit:-6
@@ -575,6 +583,7 @@ vec3 F0(float metallic, float specular, vec3 albedo) {
}
#if !defined(DISABLE_LIGHT_DIRECTIONAL) || !defined(DISABLE_LIGHT_OMNI) || !defined(DISABLE_LIGHT_SPOT)
+
float D_GGX(float cos_theta_m, float alpha) {
float a = cos_theta_m * alpha;
float k = alpha / (1.0 - cos_theta_m * cos_theta_m + a * a);
@@ -631,7 +640,6 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float atte
/* clang-format off */
-
#CODE : LIGHT
/* clang-format on */
@@ -662,11 +670,8 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float atte
// https://web.archive.org/web/20210228210901/http://blog.stevemcauley.com/2011/12/03/energy-conserving-wrapped-diffuse/
diffuse_brdf_NL = max(0.0, (NdotL + roughness) / ((1.0 + roughness) * (1.0 + roughness))) * (1.0 / M_PI);
#elif defined(DIFFUSE_TOON)
-
diffuse_brdf_NL = smoothstep(-roughness, max(roughness, 0.01), NdotL) * (1.0 / M_PI);
-
#elif defined(DIFFUSE_BURLEY)
-
{
float FD90_minus_1 = 2.0 * cLdotH * cLdotH * roughness - 0.5;
float FdV = 1.0 + FD90_minus_1 * SchlickFresnel(cNdotV);
@@ -674,7 +679,7 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float atte
diffuse_brdf_NL = (1.0 / M_PI) * FdV * FdL * cNdotL;
}
#else
- // lambert
+ // Lambert
diffuse_brdf_NL = cNdotL * (1.0 / M_PI);
#endif
@@ -710,7 +715,6 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float atte
// shlick+ggx as default
float alpha_ggx = roughness * roughness;
#if defined(LIGHT_ANISOTROPY_USED)
-
float aspect = sqrt(1.0 - anisotropy * 0.9);
float ax = alpha_ggx / aspect;
float ay = alpha_ggx * aspect;
@@ -718,7 +722,7 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float atte
float YdotH = dot(B, H);
float D = D_GGX_anisotropic(cNdotH, ax, ay, XdotH, YdotH);
float G = V_GGX_anisotropic(ax, ay, dot(T, V), dot(T, L), dot(B, V), dot(B, L), cNdotV, cNdotL);
-#else // LIGHT_ANISOTROPY_USED
+#else
float D = D_GGX(cNdotH, alpha_ggx);
float G = V_GGX(cNdotL, cNdotV, alpha_ggx);
#endif // LIGHT_ANISOTROPY_USED
@@ -758,10 +762,10 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float atte
alpha = min(alpha, clamp(1.0 - attenuation, 0.0, 1.0));
#endif
-#endif //defined(LIGHT_CODE_USED)
+#endif // LIGHT_CODE_USED
}
-float get_omni_attenuation(float distance, float inv_range, float decay) {
+float get_omni_spot_attenuation(float distance, float inv_range, float decay) {
float nd = distance * inv_range;
nd *= nd;
nd *= nd; // nd^4
@@ -770,6 +774,7 @@ float get_omni_attenuation(float distance, float inv_range, float decay) {
return nd * pow(max(distance, 0.0001), -decay);
}
+#ifndef DISABLE_LIGHT_OMNI
void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 f0, float roughness, float metallic, float shadow, vec3 albedo, inout float alpha,
#ifdef LIGHT_BACKLIGHT_USED
vec3 backlight,
@@ -786,7 +791,7 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 f
inout vec3 diffuse_light, inout vec3 specular_light) {
vec3 light_rel_vec = omni_lights[idx].position - vertex;
float light_length = length(light_rel_vec);
- float omni_attenuation = get_omni_attenuation(light_length, omni_lights[idx].inv_radius, omni_lights[idx].attenuation);
+ float omni_attenuation = get_omni_spot_attenuation(light_length, omni_lights[idx].inv_radius, omni_lights[idx].attenuation);
vec3 color = omni_lights[idx].color;
float size_A = 0.0;
@@ -811,7 +816,9 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 f
diffuse_light,
specular_light);
}
+#endif // !DISABLE_LIGHT_OMNI
+#ifndef DISABLE_LIGHT_SPOT
void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 f0, float roughness, float metallic, float shadow, vec3 albedo, inout float alpha,
#ifdef LIGHT_BACKLIGHT_USED
vec3 backlight,
@@ -830,7 +837,7 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 f
vec3 light_rel_vec = spot_lights[idx].position - vertex;
float light_length = length(light_rel_vec);
- float spot_attenuation = get_omni_attenuation(light_length, spot_lights[idx].inv_radius, spot_lights[idx].attenuation);
+ float spot_attenuation = get_omni_spot_attenuation(light_length, spot_lights[idx].inv_radius, spot_lights[idx].attenuation);
vec3 spot_dir = spot_lights[idx].direction;
float scos = max(dot(-normalize(light_rel_vec), spot_dir), spot_lights[idx].cone_angle);
float spot_rim = max(0.0001, (1.0 - scos) / (1.0 - spot_lights[idx].cone_angle));
@@ -859,7 +866,9 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 f
#endif
diffuse_light, specular_light);
}
-#endif // !defined(DISABLE_LIGHT_DIRECTIONAL) || !defined(DISABLE_LIGHT_OMNI) && !defined(DISABLE_LIGHT_SPOT)
+#endif // !DISABLE_LIGHT_SPOT
+
+#endif // !defined(DISABLE_LIGHT_DIRECTIONAL) || !defined(DISABLE_LIGHT_OMNI) || !defined(DISABLE_LIGHT_SPOT)
#ifndef MODE_RENDER_DEPTH
vec4 fog_process(vec3 vertex) {
@@ -918,6 +927,7 @@ void main() {
#else
vec3 view = -normalize(vertex_interp);
#endif
+ highp mat4 model_matrix = world_transform;
vec3 albedo = vec3(1.0);
vec3 backlight = vec3(0.0);
vec4 transmittance_color = vec4(0.0, 0.0, 0.0, 1.0);
@@ -1056,15 +1066,11 @@ void main() {
fog = fog_process(vertex);
}
#endif // !DISABLE_FOG
-#endif //!CUSTOM_FOG_USED
+#endif // !CUSTOM_FOG_USED
uint fog_rg = packHalf2x16(fog.rg);
uint fog_ba = packHalf2x16(fog.ba);
-#endif //!MODE_RENDER_DEPTH
-
-#ifndef MODE_RENDER_DEPTH
-
// Convert colors to linear
albedo = srgb_to_linear(albedo);
emission = srgb_to_linear(emission);
@@ -1097,7 +1103,7 @@ void main() {
ref_vec = mix(ref_vec, normal, roughness * roughness);
float horizon = min(1.0 + dot(ref_vec, normal), 1.0);
ref_vec = scene_data.radiance_inverse_xform * ref_vec;
- specular_light = textureLod(radiance_map, ref_vec, roughness * RADIANCE_MAX_LOD).rgb;
+ specular_light = textureLod(radiance_map, ref_vec, sqrt(roughness) * RADIANCE_MAX_LOD).rgb;
specular_light = srgb_to_linear(specular_light);
specular_light *= horizon * horizon;
specular_light *= scene_data.ambient_light_color_energy.a;
@@ -1159,7 +1165,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 * clamp(50.0 * f0.g, 0.0, 1.0);
+ specular_light *= env.x * f0 + env.y * clamp(50.0 * f0.g, metallic, 1.0);
#endif
}
@@ -1185,10 +1191,10 @@ void main() {
diffuse_light,
specular_light);
}
-#endif //!DISABLE_LIGHT_DIRECTIONAL
+#endif // !DISABLE_LIGHT_DIRECTIONAL
#ifndef DISABLE_LIGHT_OMNI
- for (int i = 0; i < MAX_FORWARD_LIGHTS; i++) {
+ for (uint i = 0u; i < MAX_FORWARD_LIGHTS; i++) {
if (i >= omni_light_count) {
break;
}
@@ -1211,7 +1217,7 @@ void main() {
#endif // !DISABLE_LIGHT_OMNI
#ifndef DISABLE_LIGHT_SPOT
- for (int i = 0; i < MAX_FORWARD_LIGHTS; i++) {
+ for (uint i = 0u; i < MAX_FORWARD_LIGHTS; i++) {
if (i >= spot_light_count) {
break;
}
@@ -1232,9 +1238,10 @@ void main() {
#endif
diffuse_light, specular_light);
}
-
#endif // !DISABLE_LIGHT_SPOT
+
#endif // !MODE_UNSHADED
+
#endif // !MODE_RENDER_DEPTH
#if defined(USE_SHADOW_TO_OPACITY)
diff --git a/drivers/gles3/shaders/skeleton.glsl b/drivers/gles3/shaders/skeleton.glsl
new file mode 100644
index 0000000000..a1e3c098f4
--- /dev/null
+++ b/drivers/gles3/shaders/skeleton.glsl
@@ -0,0 +1,269 @@
+/* clang-format off */
+#[modes]
+
+mode_base_pass =
+mode_blend_pass = #define MODE_BLEND_PASS
+
+#[specializations]
+
+MODE_2D = true
+USE_BLEND_SHAPES = false
+USE_SKELETON = false
+USE_NORMAL = false
+USE_TANGENT = false
+FINAL_PASS = false
+USE_EIGHT_WEIGHTS = false
+
+#[vertex]
+
+#include "stdlib_inc.glsl"
+
+#ifdef MODE_2D
+#define VFORMAT vec2
+#else
+#define VFORMAT vec3
+#endif
+
+#ifdef FINAL_PASS
+#define OFORMAT vec2
+#else
+#define OFORMAT uvec2
+#endif
+
+// These come from the source mesh and the output from previous passes.
+layout(location = 0) in highp VFORMAT in_vertex;
+#ifdef MODE_BLEND_PASS
+#ifdef USE_NORMAL
+layout(location = 1) in highp uvec2 in_normal;
+#endif
+#ifdef USE_TANGENT
+layout(location = 2) in highp uvec2 in_tangent;
+#endif
+#else // MODE_BLEND_PASS
+#ifdef USE_NORMAL
+layout(location = 1) in highp vec2 in_normal;
+#endif
+#ifdef USE_TANGENT
+layout(location = 2) in highp vec2 in_tangent;
+#endif
+#endif // MODE_BLEND_PASS
+
+#ifdef USE_SKELETON
+#ifdef USE_EIGHT_WEIGHTS
+layout(location = 10) in highp uvec4 in_bone_attrib;
+layout(location = 11) in highp uvec4 in_bone_attrib2;
+layout(location = 12) in mediump vec4 in_weight_attrib;
+layout(location = 13) in mediump vec4 in_weight_attrib2;
+#else
+layout(location = 10) in highp uvec4 in_bone_attrib;
+layout(location = 11) in mediump vec4 in_weight_attrib;
+#endif
+
+uniform mediump sampler2D skeleton_texture; // texunit:0
+#endif
+
+/* clang-format on */
+#ifdef MODE_BLEND_PASS
+layout(location = 3) in highp VFORMAT blend_vertex;
+#ifdef USE_NORMAL
+layout(location = 4) in highp vec2 blend_normal;
+#endif
+#ifdef USE_TANGENT
+layout(location = 5) in highp vec2 blend_tangent;
+#endif
+#endif // MODE_BLEND_PASS
+
+out highp VFORMAT out_vertex; //tfb:
+
+#ifdef USE_NORMAL
+flat out highp OFORMAT out_normal; //tfb:USE_NORMAL
+#endif
+#ifdef USE_TANGENT
+flat out highp OFORMAT out_tangent; //tfb:USE_TANGENT
+#endif
+
+#ifdef USE_BLEND_SHAPES
+uniform highp float blend_weight;
+uniform lowp float blend_shape_count;
+#endif
+
+vec2 signNotZero(vec2 v) {
+ return mix(vec2(-1.0), vec2(1.0), greaterThanEqual(v.xy, vec2(0.0)));
+}
+
+vec3 oct_to_vec3(vec2 oct) {
+ oct = oct * 2.0 - 1.0;
+ vec3 v = vec3(oct.xy, 1.0 - abs(oct.x) - abs(oct.y));
+ if (v.z < 0.0) {
+ v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);
+ }
+ return normalize(v);
+}
+
+vec2 vec3_to_oct(vec3 e) {
+ e /= abs(e.x) + abs(e.y) + abs(e.z);
+ vec2 oct = e.z >= 0.0f ? e.xy : (vec2(1.0f) - abs(e.yx)) * signNotZero(e.xy);
+ return oct * 0.5f + 0.5f;
+}
+
+vec4 oct_to_tang(vec2 oct_sign_encoded) {
+ // Binormal sign encoded in y component
+ vec2 oct = vec2(oct_sign_encoded.x, abs(oct_sign_encoded.y) * 2.0 - 1.0);
+ return vec4(oct_to_vec3(oct), sign(oct_sign_encoded.y));
+}
+
+vec2 tang_to_oct(vec4 base) {
+ vec2 oct = vec3_to_oct(base.xyz);
+ // Encode binormal sign in y component
+ oct.y = oct.y * 0.5f + 0.5f;
+ oct.y = base.w >= 0.0f ? oct.y : 1.0 - oct.y;
+ return oct;
+}
+
+// Our original input for normals and tangents is 2 16-bit floats.
+// Transform Feedback has to write out 32-bits per channel.
+// Octahedral compression requires normalized vectors, but we need to store
+// non-normalized vectors until the very end.
+// Therefore, we will compress our normals into 16 bits using signed-normalized
+// fixed point precision. This works well, because we know that each normal
+// is no larger than |1| so we can normalize by dividing by the number of blend
+// shapes.
+uvec2 vec4_to_vec2(vec4 p_vec) {
+ return uvec2(packSnorm2x16(p_vec.xy), packSnorm2x16(p_vec.zw));
+}
+
+vec4 vec2_to_vec4(uvec2 p_vec) {
+ return vec4(unpackSnorm2x16(p_vec.x), unpackSnorm2x16(p_vec.y));
+}
+
+void main() {
+#ifdef MODE_2D
+ out_vertex = in_vertex;
+
+#ifdef USE_BLEND_SHAPES
+#ifdef MODE_BLEND_PASS
+ out_vertex = in_vertex + blend_vertex * blend_weight;
+#else
+ out_vertex = in_vertex * blend_weight;
+#endif
+#ifdef FINAL_PASS
+ out_vertex = normalize(out_vertex);
+#endif
+#endif // USE_BLEND_SHAPES
+
+#ifdef USE_SKELETON
+
+#define TEX(m) texelFetch(skeleton_texture, ivec2(m % 256u, m / 256u), 0)
+#define GET_BONE_MATRIX(a, b, w) mat2x4(TEX(a), TEX(b)) * w
+
+ uvec4 bones = in_bone_attrib * uvec4(2u);
+ uvec4 bones_a = bones + uvec4(1u);
+
+ highp mat2x4 m = GET_BONE_MATRIX(bones.x, bones_a.x, in_weight_attrib.x);
+ m += GET_BONE_MATRIX(bones.y, bones_a.y, in_weight_attrib.y);
+ m += GET_BONE_MATRIX(bones.z, bones_a.z, in_weight_attrib.z);
+ m += GET_BONE_MATRIX(bones.w, bones_a.w, in_weight_attrib.w);
+
+ mat4 bone_matrix = mat4(m[0], m[1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0));
+
+ //reverse order because its transposed
+ out_vertex = (vec4(out_vertex, 0.0, 1.0) * bone_matrix).xy;
+#endif // USE_SKELETON
+
+#else // MODE_2D
+
+#ifdef USE_BLEND_SHAPES
+#ifdef MODE_BLEND_PASS
+ out_vertex = in_vertex + blend_vertex * blend_weight;
+
+#ifdef USE_NORMAL
+ vec3 normal = vec2_to_vec4(in_normal).xyz * blend_shape_count;
+ vec3 normal_blend = oct_to_vec3(blend_normal) * blend_weight;
+#ifdef FINAL_PASS
+ out_normal = vec3_to_oct(normalize(normal + normal_blend));
+#else
+ out_normal = vec4_to_vec2(vec4(normal + normal_blend, 0.0) / blend_shape_count);
+#endif
+#endif // USE_NORMAL
+
+#ifdef USE_TANGENT
+ vec4 tangent = vec2_to_vec4(in_tangent) * blend_shape_count;
+ vec4 tangent_blend = oct_to_tang(blend_tangent) * blend_weight;
+#ifdef FINAL_PASS
+ out_tangent = tang_to_oct(vec4(normalize(tangent.xyz + tangent_blend.xyz), tangent.w));
+#else
+ out_tangent = vec4_to_vec2(vec4((tangent.xyz + tangent_blend.xyz) / blend_shape_count, tangent.w));
+#endif
+#endif // USE_TANGENT
+
+#else // MODE_BLEND_PASS
+ out_vertex = in_vertex * blend_weight;
+
+#ifdef USE_NORMAL
+ vec3 normal = oct_to_vec3(in_normal);
+ out_normal = vec4_to_vec2(vec4(normal * blend_weight / blend_shape_count, 0.0));
+#endif
+#ifdef USE_TANGENT
+ vec4 tangent = oct_to_tang(in_tangent);
+ out_tangent = vec4_to_vec2(vec4(tangent.rgb * blend_weight / blend_shape_count, tangent.w));
+#endif
+#endif // MODE_BLEND_PASS
+#else // USE_BLEND_SHAPES
+
+ // Make attributes available to the skeleton shader if not written by blend shapes.
+ out_vertex = in_vertex;
+#ifdef USE_NORMAL
+ out_normal = in_normal;
+#endif
+#ifdef USE_TANGENT
+ out_tangent = in_tangent;
+#endif
+#endif // USE_BLEND_SHAPES
+
+#ifdef USE_SKELETON
+
+#define TEX(m) texelFetch(skeleton_texture, ivec2(m % 256u, m / 256u), 0)
+#define GET_BONE_MATRIX(a, b, c, w) mat4(TEX(a), TEX(b), TEX(c), vec4(0.0, 0.0, 0.0, 1.0)) * w
+
+ uvec4 bones = in_bone_attrib * uvec4(3);
+ uvec4 bones_a = bones + uvec4(1);
+ uvec4 bones_b = bones + uvec4(2);
+
+ highp mat4 m;
+ m = GET_BONE_MATRIX(bones.x, bones_a.x, bones_b.x, in_weight_attrib.x);
+ m += GET_BONE_MATRIX(bones.y, bones_a.y, bones_b.y, in_weight_attrib.y);
+ m += GET_BONE_MATRIX(bones.z, bones_a.z, bones_b.z, in_weight_attrib.z);
+ m += GET_BONE_MATRIX(bones.w, bones_a.w, bones_b.w, in_weight_attrib.w);
+
+#ifdef USE_EIGHT_WEIGHTS
+ bones = in_bone_attrib2 * uvec4(3);
+ bones_a = bones + uvec4(1);
+ bones_b = bones + uvec4(2);
+
+ m += GET_BONE_MATRIX(bones.x, bones_a.x, bones_b.x, in_weight_attrib2.x);
+ m += GET_BONE_MATRIX(bones.y, bones_a.y, bones_b.y, in_weight_attrib2.y);
+ m += GET_BONE_MATRIX(bones.z, bones_a.z, bones_b.z, in_weight_attrib2.z);
+ m += GET_BONE_MATRIX(bones.w, bones_a.w, bones_b.w, in_weight_attrib2.w);
+#endif
+
+ // Reverse order because its transposed.
+ out_vertex = (vec4(out_vertex, 1.0) * m).xyz;
+#ifdef USE_NORMAL
+ vec3 vertex_normal = oct_to_vec3(out_normal);
+ out_normal = vec3_to_oct(normalize((vec4(vertex_normal, 0.0) * m).xyz));
+#endif // USE_NORMAL
+#ifdef USE_TANGENT
+ vec4 vertex_tangent = oct_to_tang(out_tangent);
+ out_tangent = tang_to_oct(vec4(normalize((vec4(vertex_tangent.xyz, 0.0) * m).xyz), vertex_tangent.w));
+#endif // USE_TANGENT
+#endif // USE_SKELETON
+#endif // MODE_2D
+}
+
+/* clang-format off */
+#[fragment]
+
+void main() {
+
+}
+/* clang-format on */
diff --git a/drivers/gles3/shaders/stdlib_inc.glsl b/drivers/gles3/shaders/stdlib_inc.glsl
index d5051760d7..8d4a24cc1f 100644
--- a/drivers/gles3/shaders/stdlib_inc.glsl
+++ b/drivers/gles3/shaders/stdlib_inc.glsl
@@ -38,23 +38,33 @@ vec2 unpackSnorm2x16(uint p) {
vec2 v = vec2(float(p & uint(0xffff)), float(p >> uint(16)));
return clamp((v - 32767.0) * vec2(0.00003051851), vec2(-1.0), vec2(1.0));
}
+
#endif
-uint packUnorm4x8(vec4 v) {
+// Compatibility renames. These are exposed with the "godot_" prefix
+// to work around an Adreno bug which was exposing these ES310 functions
+// in ES300 shaders. Internally, we must use the "godot_" prefix, but user shaders
+// will be mapped automatically.
+uint godot_packUnorm4x8(vec4 v) {
uvec4 uv = uvec4(round(clamp(v, vec4(0.0), vec4(1.0)) * 255.0));
return uv.x | (uv.y << uint(8)) | (uv.z << uint(16)) | (uv.w << uint(24));
}
-vec4 unpackUnorm4x8(uint p) {
+vec4 godot_unpackUnorm4x8(uint p) {
return vec4(float(p & uint(0xff)), float((p >> uint(8)) & uint(0xff)), float((p >> uint(16)) & uint(0xff)), float(p >> uint(24))) * 0.00392156862; // 1.0 / 255.0
}
-uint packSnorm4x8(vec4 v) {
+uint godot_packSnorm4x8(vec4 v) {
uvec4 uv = uvec4(round(clamp(v, vec4(-1.0), vec4(1.0)) * 127.0) + 127.0);
return uv.x | uv.y << uint(8) | uv.z << uint(16) | uv.w << uint(24);
}
-vec4 unpackSnorm4x8(uint p) {
+vec4 godot_unpackSnorm4x8(uint p) {
vec4 v = vec4(float(p & uint(0xff)), float((p >> uint(8)) & uint(0xff)), float((p >> uint(16)) & uint(0xff)), float(p >> uint(24)));
return clamp((v - vec4(127.0)) * vec4(0.00787401574), vec4(-1.0), vec4(1.0));
}
+
+#define packUnorm4x8 godot_packUnorm4x8
+#define unpackUnorm4x8 godot_unpackUnorm4x8
+#define packSnorm4x8 godot_packSnorm4x8
+#define unpackSnorm4x8 godot_unpackSnorm4x8
diff --git a/drivers/gles3/storage/config.cpp b/drivers/gles3/storage/config.cpp
index 9b496c0999..46dc2b806e 100644
--- a/drivers/gles3/storage/config.cpp
+++ b/drivers/gles3/storage/config.cpp
@@ -90,8 +90,6 @@ Config::Config() {
glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &max_uniform_buffer_size);
glGetIntegerv(GL_MAX_VIEWPORT_DIMS, max_viewport_size);
- glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &uniform_buffer_offset_alignment);
-
support_anisotropic_filter = extensions.has("GL_EXT_texture_filter_anisotropic");
if (support_anisotropic_filter) {
glGetFloatv(_GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &anisotropic_level);
diff --git a/drivers/gles3/storage/config.h b/drivers/gles3/storage/config.h
index 87202fde84..1a93b4b8ef 100644
--- a/drivers/gles3/storage/config.h
+++ b/drivers/gles3/storage/config.h
@@ -67,8 +67,6 @@ public:
int max_renderable_lights = 0;
int max_lights_per_object = 0;
- int uniform_buffer_offset_alignment = 0;
-
// TODO implement wireframe in OpenGL
// bool generate_wireframes;
diff --git a/drivers/gles3/storage/light_storage.cpp b/drivers/gles3/storage/light_storage.cpp
index b6bd4a2760..710112bff4 100644
--- a/drivers/gles3/storage/light_storage.cpp
+++ b/drivers/gles3/storage/light_storage.cpp
@@ -502,6 +502,10 @@ bool LightStorage::reflection_probe_instance_begin_render(RID p_instance, RID p_
return false;
}
+Ref<RenderSceneBuffers> LightStorage::reflection_probe_atlas_get_render_buffers(RID p_reflection_atlas) {
+ return Ref<RenderSceneBuffers>();
+}
+
bool LightStorage::reflection_probe_instance_postprocess_step(RID p_instance) {
return true;
}
diff --git a/drivers/gles3/storage/light_storage.h b/drivers/gles3/storage/light_storage.h
index 12cb2c4393..f41dafa5b0 100644
--- a/drivers/gles3/storage/light_storage.h
+++ b/drivers/gles3/storage/light_storage.h
@@ -366,6 +366,7 @@ public:
virtual bool reflection_probe_instance_needs_redraw(RID p_instance) override;
virtual bool reflection_probe_instance_has_reflection(RID p_instance) override;
virtual bool reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas) override;
+ virtual Ref<RenderSceneBuffers> reflection_probe_atlas_get_render_buffers(RID p_reflection_atlas) override;
virtual bool reflection_probe_instance_postprocess_step(RID p_instance) override;
/* LIGHTMAP CAPTURE */
diff --git a/drivers/gles3/storage/material_storage.cpp b/drivers/gles3/storage/material_storage.cpp
index 6748eb3676..ebafdc88d8 100644
--- a/drivers/gles3/storage/material_storage.cpp
+++ b/drivers/gles3/storage/material_storage.cpp
@@ -34,6 +34,7 @@
#include "config.h"
#include "material_storage.h"
+#include "particles_storage.h"
#include "texture_storage.h"
#include "drivers/gles3/rasterizer_canvas_gles3.h"
@@ -922,6 +923,104 @@ _FORCE_INLINE_ static void _fill_std140_ubo_empty(ShaderLanguage::DataType type,
}
///////////////////////////////////////////////////////////////////////////
+// ShaderData
+
+void ShaderData::set_path_hint(const String &p_hint) {
+ path = p_hint;
+}
+
+void ShaderData::set_default_texture_parameter(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;
+ }
+}
+
+Variant ShaderData::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();
+}
+
+void ShaderData::get_shader_uniform_list(List<PropertyInfo> *p_param_list) const {
+ SortArray<Pair<StringName, int>, ShaderLanguage::UniformOrderComparator> sorter;
+ LocalVector<Pair<StringName, int>> filtered_uniforms;
+
+ for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
+ if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_LOCAL) {
+ continue;
+ }
+ if (E.value.texture_order >= 0) {
+ filtered_uniforms.push_back(Pair<StringName, int>(E.key, E.value.texture_order + 100000));
+ } else {
+ filtered_uniforms.push_back(Pair<StringName, int>(E.key, E.value.order));
+ }
+ }
+ int uniform_count = filtered_uniforms.size();
+ sorter.sort(filtered_uniforms.ptr(), uniform_count);
+
+ String last_group;
+ for (int i = 0; i < uniform_count; i++) {
+ const StringName &uniform_name = filtered_uniforms[i].first;
+ const ShaderLanguage::ShaderNode::Uniform &uniform = uniforms[uniform_name];
+
+ String group = uniform.group;
+ if (!uniform.subgroup.is_empty()) {
+ group += "::" + uniform.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(uniform);
+ pi.name = uniform_name;
+ p_param_list->push_back(pi);
+ }
+}
+
+void ShaderData::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 ShaderData::is_parameter_texture(const StringName &p_param) const {
+ if (!uniforms.has(p_param)) {
+ return false;
+ }
+
+ return uniforms[p_param].texture_order >= 0;
+}
+
+///////////////////////////////////////////////////////////////////////////
// MaterialData
// Look up table to translate ShaderLanguage::DataType to GL_TEXTURE_*
@@ -1342,13 +1441,13 @@ MaterialStorage::MaterialStorage() {
shader_data_request_func[RS::SHADER_SPATIAL] = _create_scene_shader_func;
shader_data_request_func[RS::SHADER_CANVAS_ITEM] = _create_canvas_shader_func;
- shader_data_request_func[RS::SHADER_PARTICLES] = nullptr;
+ shader_data_request_func[RS::SHADER_PARTICLES] = _create_particles_shader_func;
shader_data_request_func[RS::SHADER_SKY] = _create_sky_shader_func;
shader_data_request_func[RS::SHADER_FOG] = nullptr;
material_data_request_func[RS::SHADER_SPATIAL] = _create_scene_material_func;
material_data_request_func[RS::SHADER_CANVAS_ITEM] = _create_canvas_material_func;
- material_data_request_func[RS::SHADER_PARTICLES] = nullptr;
+ material_data_request_func[RS::SHADER_PARTICLES] = _create_particles_material_func;
material_data_request_func[RS::SHADER_SKY] = _create_sky_material_func;
material_data_request_func[RS::SHADER_FOG] = nullptr;
@@ -1521,6 +1620,7 @@ MaterialStorage::MaterialStorage() {
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["CAMERA_VISIBLE_LAYERS"] = "scene_data.camera_visible_layers";
actions.renames["NODE_POSITION_VIEW"] = "(model_matrix * scene_data.view_matrix)[3].xyz";
actions.renames["VIEW_INDEX"] = "ViewIndex";
@@ -1613,32 +1713,32 @@ MaterialStorage::MaterialStorage() {
{
// Setup Particles compiler
- /*
-ShaderCompiler::DefaultIdentifierActions actions;
- actions.renames["COLOR"] = "PARTICLE.color";
- actions.renames["VELOCITY"] = "PARTICLE.velocity";
+ ShaderCompiler::DefaultIdentifierActions actions;
+
+ actions.renames["COLOR"] = "out_color";
+ actions.renames["VELOCITY"] = "out_velocity_flags.xyz";
//actions.renames["MASS"] = "mass"; ?
actions.renames["ACTIVE"] = "particle_active";
actions.renames["RESTART"] = "restart";
- actions.renames["CUSTOM"] = "PARTICLE.custom";
- for (int i = 0; i < ParticlesShader::MAX_USERDATAS; i++) {
+ actions.renames["CUSTOM"] = "out_custom";
+ for (int i = 0; i < PARTICLES_MAX_USERDATAS; i++) {
String udname = "USERDATA" + itos(i + 1);
- actions.renames[udname] = "PARTICLE.userdata" + itos(i + 1);
+ actions.renames[udname] = "out_userdata" + itos(i + 1);
actions.usage_defines[udname] = "#define USERDATA" + itos(i + 1) + "_USED\n";
}
- actions.renames["TRANSFORM"] = "PARTICLE.xform";
- actions.renames["TIME"] = "frame_history.data[0].time";
+ actions.renames["TRANSFORM"] = "xform";
+ actions.renames["TIME"] = "time";
actions.renames["PI"] = _MKSTR(Math_PI);
actions.renames["TAU"] = _MKSTR(Math_TAU);
actions.renames["E"] = _MKSTR(Math_E);
- actions.renames["LIFETIME"] = "params.lifetime";
+ actions.renames["LIFETIME"] = "lifetime";
actions.renames["DELTA"] = "local_delta";
actions.renames["NUMBER"] = "particle_number";
actions.renames["INDEX"] = "index";
//actions.renames["GRAVITY"] = "current_gravity";
- actions.renames["EMISSION_TRANSFORM"] = "FRAME.emission_transform";
- actions.renames["RANDOM_SEED"] = "FRAME.random_seed";
+ actions.renames["EMISSION_TRANSFORM"] = "emission_transform";
+ actions.renames["RANDOM_SEED"] = "random_seed";
actions.renames["FLAG_EMIT_POSITION"] = "EMISSION_FLAG_HAS_POSITION";
actions.renames["FLAG_EMIT_ROT_SCALE"] = "EMISSION_FLAG_HAS_ROTATION_SCALE";
actions.renames["FLAG_EMIT_VELOCITY"] = "EMISSION_FLAG_HAS_VELOCITY";
@@ -1660,18 +1760,10 @@ ShaderCompiler::DefaultIdentifierActions actions;
actions.render_mode_defines["keep_data"] = "#define ENABLE_KEEP_DATA\n";
actions.render_mode_defines["collision_use_scale"] = "#define USE_COLLISION_SCALE\n";
- actions.sampler_array_name = "material_samplers";
- actions.base_texture_binding_index = 1;
- actions.texture_layout_set = 3;
- actions.base_uniform_string = "material.";
- actions.base_varying_index = 10;
-
actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP;
actions.default_repeat = ShaderLanguage::REPEAT_ENABLE;
- actions.global_buffer_array_variable = "global_shader_uniforms.data";
- particles_shader.compiler.initialize(actions);
- */
+ shaders.compiler_particles.initialize(actions);
}
{
@@ -2470,8 +2562,8 @@ void MaterialStorage::shader_set_code(RID p_shader, const String &p_code) {
RS::ShaderMode new_mode;
if (mode_string == "canvas_item") {
new_mode = RS::SHADER_CANVAS_ITEM;
- //} else if (mode_string == "particles") {
- // new_mode = RS::SHADER_PARTICLES;
+ } else if (mode_string == "particles") {
+ new_mode = RS::SHADER_PARTICLES;
} else if (mode_string == "spatial") {
new_mode = RS::SHADER_SPATIAL;
} else if (mode_string == "sky") {
@@ -2542,6 +2634,9 @@ void MaterialStorage::shader_set_path_hint(RID p_shader, const String &p_path) {
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 {
@@ -2889,85 +2984,6 @@ void CanvasShaderData::set_code(const String &p_code) {
valid = true;
}
-void CanvasShaderData::set_default_texture_parameter(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 CanvasShaderData::get_shader_uniform_list(List<PropertyInfo> *p_param_list) const {
- HashMap<int, StringName> order;
-
- for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
- if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_LOCAL ||
- E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_SCREEN_TEXTURE ||
- E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE ||
- E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_DEPTH_TEXTURE) {
- 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 CanvasShaderData::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 CanvasShaderData::is_parameter_texture(const StringName &p_param) const {
- if (!uniforms.has(p_param)) {
- return false;
- }
-
- return uniforms[p_param].texture_order >= 0;
-}
-
bool CanvasShaderData::is_animated() const {
return false;
}
@@ -2976,15 +2992,6 @@ bool CanvasShaderData::casts_shadows() const {
return false;
}
-Variant CanvasShaderData::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 CanvasShaderData::get_native_source_code() const {
return MaterialStorage::get_singleton()->shaders.canvas_shader.version_get_native_source_code(version);
}
@@ -3007,7 +3014,7 @@ GLES3::ShaderData *GLES3::_create_canvas_shader_func() {
}
void CanvasMaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
- return update_parameters_internal(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);
+ update_parameters_internal(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);
}
void CanvasMaterialData::bind_uniforms() {
@@ -3020,6 +3027,9 @@ void CanvasMaterialData::bind_uniforms() {
Texture *texture = TextureStorage::get_singleton()->get_texture(textures[ti]);
glActiveTexture(GL_TEXTURE1 + ti); // Start at GL_TEXTURE1 because texture slot 0 is used by the base texture
glBindTexture(target_from_type[texture_uniforms[ti].type], texture->tex_id);
+ if (texture->render_target) {
+ texture->render_target->used_in_frame = true;
+ }
// Set sampler state here as the same texture can be used in multiple places with different flags
// Need to convert sampler state from ShaderLanguage::Texture* to RS::CanvasItemTexture*
@@ -3133,83 +3143,6 @@ void SkyShaderData::set_code(const String &p_code) {
valid = true;
}
-void SkyShaderData::set_default_texture_parameter(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 SkyShaderData::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 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;
- }
-
- 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 SkyShaderData::is_parameter_texture(const StringName &p_param) const {
- if (!uniforms.has(p_param)) {
- return false;
- }
-
- return uniforms[p_param].texture_order >= 0;
-}
-
bool SkyShaderData::is_animated() const {
return false;
}
@@ -3218,15 +3151,6 @@ bool SkyShaderData::casts_shadows() const {
return false;
}
-Variant 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;
- return ShaderLanguage::constant_value_to_variant(default_value, uniform.type, uniform.array_size, uniform.hint);
- }
- return Variant();
-}
-
RS::ShaderNativeSourceCode SkyShaderData::get_native_source_code() const {
return MaterialStorage::get_singleton()->shaders.sky_shader.version_get_native_source_code(version);
}
@@ -3251,7 +3175,7 @@ GLES3::ShaderData *GLES3::_create_sky_shader_func() {
void SkyMaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
uniform_set_updated = true;
- return update_parameters_internal(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);
+ update_parameters_internal(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);
}
SkyMaterialData::~SkyMaterialData() {
@@ -3273,6 +3197,9 @@ void SkyMaterialData::bind_uniforms() {
Texture *texture = TextureStorage::get_singleton()->get_texture(textures[ti]);
glActiveTexture(GL_TEXTURE0 + ti);
glBindTexture(target_from_type[texture_uniforms[ti].type], texture->tex_id);
+ if (texture->render_target) {
+ texture->render_target->used_in_frame = true;
+ }
// Set sampler state here as the same texture can be used in multiple places with different flags
// Need to convert sampler state from ShaderLanguage::Texture* to RS::CanvasItemTexture*
@@ -3358,6 +3285,9 @@ void SceneShaderData::set_code(const String &p_code) {
actions.usage_flag_pointers["ALPHA"] = &uses_alpha;
actions.usage_flag_pointers["ALPHA_SCISSOR_THRESHOLD"] = &uses_alpha_clip;
+ // Use alpha clip pipeline for alpha hash/dither.
+ // This prevents sorting issues inherent to alpha blending and allows such materials to cast shadows.
+ actions.usage_flag_pointers["ALPHA_HASH_SCALE"] = &uses_alpha_clip;
actions.render_mode_flags["depth_prepass_alpha"] = &uses_depth_pre_pass;
actions.usage_flag_pointers["SSS_STRENGTH"] = &uses_sss;
@@ -3418,6 +3348,8 @@ void SceneShaderData::set_code(const String &p_code) {
vertex_input_mask |= uses_bones << 9;
vertex_input_mask |= uses_weights << 10;
uses_screen_texture_mipmaps = gen_code.uses_screen_texture_mipmaps;
+ uses_vertex_time = gen_code.uses_vertex_time;
+ uses_fragment_time = gen_code.uses_fragment_time;
#if 0
print_line("**compiling shader:");
@@ -3457,101 +3389,16 @@ void SceneShaderData::set_code(const String &p_code) {
valid = true;
}
-void SceneShaderData::set_default_texture_parameter(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 SceneShaderData::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_LOCAL ||
- E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_SCREEN_TEXTURE ||
- E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE ||
- E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_DEPTH_TEXTURE) {
- 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 SceneShaderData::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 SceneShaderData::is_parameter_texture(const StringName &p_param) const {
- if (!uniforms.has(p_param)) {
- return false;
- }
-
- return uniforms[p_param].texture_order >= 0;
-}
-
bool SceneShaderData::is_animated() const {
- return false;
+ return (uses_fragment_time && uses_discard) || (uses_vertex_time && uses_vertex);
}
bool SceneShaderData::casts_shadows() const {
- return false;
-}
+ bool has_read_screen_alpha = uses_screen_texture || uses_depth_texture || uses_normal_texture;
+ bool has_base_alpha = (uses_alpha && !uses_alpha_clip) || has_read_screen_alpha;
+ bool has_alpha = has_base_alpha || uses_blend_alpha;
-Variant SceneShaderData::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();
+ return !has_alpha || (uses_depth_pre_pass && !(depth_draw == DEPTH_DRAW_DISABLED || depth_test == DEPTH_TEST_DISABLED));
}
RS::ShaderNativeSourceCode SceneShaderData::get_native_source_code() const {
@@ -3583,7 +3430,7 @@ void SceneMaterialData::set_next_pass(RID p_pass) {
}
void SceneMaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
- return update_parameters_internal(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);
+ update_parameters_internal(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);
}
SceneMaterialData::~SceneMaterialData() {
@@ -3606,6 +3453,127 @@ void SceneMaterialData::bind_uniforms() {
Texture *texture = TextureStorage::get_singleton()->get_texture(textures[ti]);
glActiveTexture(GL_TEXTURE0 + ti);
glBindTexture(target_from_type[texture_uniforms[ti].type], texture->tex_id);
+ if (texture->render_target) {
+ texture->render_target->used_in_frame = true;
+ }
+
+ // Set sampler state here as the same texture can be used in multiple places with different flags
+ // Need to convert sampler state from ShaderLanguage::Texture* to RS::CanvasItemTexture*
+ RS::CanvasItemTextureFilter filter = RS::CanvasItemTextureFilter((int(texture_uniforms[ti].filter) + 1) % RS::CANVAS_ITEM_TEXTURE_FILTER_MAX);
+ RS::CanvasItemTextureRepeat repeat = RS::CanvasItemTextureRepeat((int(texture_uniforms[ti].repeat) + 1) % RS::CANVAS_ITEM_TEXTURE_REPEAT_MIRROR);
+ texture->gl_set_filter(filter);
+ texture->gl_set_repeat(repeat);
+ }
+}
+
+/* Particles SHADER */
+
+void ParticlesShaderData::set_code(const String &p_code) {
+ //compile
+
+ code = p_code;
+ valid = false;
+ ubo_size = 0;
+ uniforms.clear();
+ uses_collision = false;
+
+ if (code.is_empty()) {
+ return; //just invalid, but no error
+ }
+
+ ShaderCompiler::GeneratedCode gen_code;
+ ShaderCompiler::IdentifierActions actions;
+ actions.entry_point_stages["start"] = ShaderCompiler::STAGE_VERTEX;
+ actions.entry_point_stages["process"] = ShaderCompiler::STAGE_VERTEX;
+
+ actions.usage_flag_pointers["COLLIDED"] = &uses_collision;
+
+ userdata_count = 0;
+ for (uint32_t i = 0; i < PARTICLES_MAX_USERDATAS; i++) {
+ userdatas_used[i] = false;
+ actions.usage_flag_pointers["USERDATA" + itos(i + 1)] = &userdatas_used[i];
+ }
+
+ actions.uniforms = &uniforms;
+
+ Error err = MaterialStorage::get_singleton()->shaders.compiler_particles.compile(RS::SHADER_PARTICLES, code, &actions, path, gen_code);
+ ERR_FAIL_COND_MSG(err != OK, "Shader compilation failed.");
+
+ if (version.is_null()) {
+ version = MaterialStorage::get_singleton()->shaders.particles_process_shader.version_create();
+ }
+
+ for (uint32_t i = 0; i < PARTICLES_MAX_USERDATAS; i++) {
+ if (userdatas_used[i]) {
+ userdata_count++;
+ }
+ }
+
+ Vector<StringName> texture_uniform_names;
+ for (int i = 0; i < gen_code.texture_uniforms.size(); i++) {
+ texture_uniform_names.push_back(gen_code.texture_uniforms[i].name);
+ }
+
+ MaterialStorage::get_singleton()->shaders.particles_process_shader.version_set_code(version, gen_code.code, gen_code.uniforms, gen_code.stage_globals[ShaderCompiler::STAGE_VERTEX], gen_code.stage_globals[ShaderCompiler::STAGE_FRAGMENT], gen_code.defines, texture_uniform_names);
+ ERR_FAIL_COND(!MaterialStorage::get_singleton()->shaders.particles_process_shader.version_is_valid(version));
+
+ ubo_size = gen_code.uniform_total_size;
+ ubo_offsets = gen_code.uniform_offsets;
+ texture_uniforms = gen_code.texture_uniforms;
+
+ valid = true;
+}
+
+bool ParticlesShaderData::is_animated() const {
+ return false;
+}
+
+bool ParticlesShaderData::casts_shadows() const {
+ return false;
+}
+
+RS::ShaderNativeSourceCode ParticlesShaderData::get_native_source_code() const {
+ return MaterialStorage::get_singleton()->shaders.particles_process_shader.version_get_native_source_code(version);
+}
+
+ParticlesShaderData::~ParticlesShaderData() {
+ if (version.is_valid()) {
+ MaterialStorage::get_singleton()->shaders.particles_process_shader.version_free(version);
+ }
+}
+
+GLES3::ShaderData *GLES3::_create_particles_shader_func() {
+ ParticlesShaderData *shader_data = memnew(ParticlesShaderData);
+ return shader_data;
+}
+
+void ParticleProcessMaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
+ update_parameters_internal(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);
+}
+
+ParticleProcessMaterialData::~ParticleProcessMaterialData() {
+}
+
+GLES3::MaterialData *GLES3::_create_particles_material_func(ShaderData *p_shader) {
+ ParticleProcessMaterialData *material_data = memnew(ParticleProcessMaterialData);
+ material_data->shader_data = static_cast<ParticlesShaderData *>(p_shader);
+ //update will happen later anyway so do nothing.
+ return material_data;
+}
+
+void ParticleProcessMaterialData::bind_uniforms() {
+ // Bind Material Uniforms
+ glBindBufferBase(GL_UNIFORM_BUFFER, GLES3::PARTICLES_MATERIAL_UNIFORM_LOCATION, uniform_buffer);
+
+ RID *textures = texture_cache.ptrw();
+ ShaderCompiler::GeneratedCode::Texture *texture_uniforms = shader_data->texture_uniforms.ptrw();
+ for (int ti = 0; ti < texture_cache.size(); ti++) {
+ Texture *texture = TextureStorage::get_singleton()->get_texture(textures[ti]);
+ glActiveTexture(GL_TEXTURE1 + ti); // Start at GL_TEXTURE1 because texture slot 0 is reserved for the heightmap texture.
+ glBindTexture(target_from_type[texture_uniforms[ti].type], texture->tex_id);
+ if (texture->render_target) {
+ texture->render_target->used_in_frame = true;
+ }
// Set sampler state here as the same texture can be used in multiple places with different flags
// Need to convert sampler state from ShaderLanguage::Texture* to RS::CanvasItemTexture*
diff --git a/drivers/gles3/storage/material_storage.h b/drivers/gles3/storage/material_storage.h
index 24d9a0fee1..9965d23070 100644
--- a/drivers/gles3/storage/material_storage.h
+++ b/drivers/gles3/storage/material_storage.h
@@ -44,6 +44,7 @@
#include "../shaders/canvas.glsl.gen.h"
#include "../shaders/cubemap_filter.glsl.gen.h"
+#include "../shaders/particles.glsl.gen.h"
#include "../shaders/scene.glsl.gen.h"
#include "../shaders/sky.glsl.gen.h"
@@ -52,15 +53,20 @@ namespace GLES3 {
/* Shader Structs */
struct ShaderData {
- virtual void set_code(const String &p_Code) = 0;
- virtual void set_default_texture_parameter(const StringName &p_name, RID p_texture, int p_index) = 0;
- virtual void get_shader_uniform_list(List<PropertyInfo> *p_param_list) const = 0;
+ String path;
+ HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms;
+ HashMap<StringName, HashMap<int, RID>> default_texture_params;
- virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const = 0;
- virtual bool is_parameter_texture(const StringName &p_param) const = 0;
+ virtual void set_path_hint(const String &p_hint);
+ virtual void set_default_texture_parameter(const StringName &p_name, RID p_texture, int p_index);
+ virtual Variant get_default_parameter(const StringName &p_parameter) 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_parameter_texture(const StringName &p_param) const;
+
+ virtual void set_code(const String &p_Code) = 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() {}
@@ -147,17 +153,14 @@ struct CanvasShaderData : public ShaderData {
bool valid;
RID version;
- String path;
BlendMode blend_mode = BLEND_MODE_MIX;
- HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms;
Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms;
Vector<uint32_t> ubo_offsets;
uint32_t ubo_size;
String code;
- HashMap<StringName, HashMap<int, RID>> default_texture_params;
bool uses_screen_texture = false;
bool uses_screen_texture_mipmaps = false;
@@ -165,14 +168,8 @@ struct CanvasShaderData : public ShaderData {
bool uses_time = false;
virtual void set_code(const String &p_Code);
- virtual void set_default_texture_parameter(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_parameter_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;
CanvasShaderData();
@@ -199,15 +196,12 @@ struct SkyShaderData : public ShaderData {
bool valid;
RID version;
- HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms;
Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms;
Vector<uint32_t> ubo_offsets;
uint32_t ubo_size;
- String path;
String code;
- HashMap<StringName, HashMap<int, RID>> default_texture_params;
bool uses_time;
bool uses_position;
@@ -216,13 +210,8 @@ struct SkyShaderData : public ShaderData {
bool uses_light;
virtual void set_code(const String &p_Code);
- virtual void set_default_texture_parameter(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_parameter_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;
SkyShaderData();
virtual ~SkyShaderData();
@@ -280,16 +269,12 @@ struct SceneShaderData : public ShaderData {
bool valid;
RID version;
- String path;
-
- HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms;
Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms;
Vector<uint32_t> ubo_offsets;
uint32_t ubo_size;
String code;
- HashMap<StringName, HashMap<int, RID>> default_texture_params;
BlendMode blend_mode;
AlphaAntiAliasing alpha_antialiasing_mode;
@@ -318,6 +303,8 @@ struct SceneShaderData : public ShaderData {
bool uses_depth_texture;
bool uses_normal_texture;
bool uses_time;
+ bool uses_vertex_time;
+ bool uses_fragment_time;
bool writes_modelview_or_projection;
bool uses_world_coordinates;
bool uses_tangent;
@@ -337,14 +324,8 @@ struct SceneShaderData : public ShaderData {
uint32_t index = 0;
virtual void set_code(const String &p_Code);
- virtual void set_default_texture_parameter(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_parameter_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;
SceneShaderData();
@@ -368,6 +349,53 @@ struct SceneMaterialData : public MaterialData {
MaterialData *_create_scene_material_func(ShaderData *p_shader);
+/* Particle Shader */
+
+enum {
+ PARTICLES_MAX_USERDATAS = 6
+};
+
+struct ParticlesShaderData : public ShaderData {
+ bool valid = false;
+ RID version;
+ bool uses_collision = false;
+
+ Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms;
+
+ Vector<uint32_t> ubo_offsets;
+ uint32_t ubo_size = 0;
+
+ String code;
+
+ bool uses_time = false;
+
+ bool userdatas_used[PARTICLES_MAX_USERDATAS] = {};
+ uint32_t userdata_count = 0;
+
+ virtual void set_code(const String &p_Code);
+ virtual bool is_animated() const;
+ virtual bool casts_shadows() const;
+ virtual RS::ShaderNativeSourceCode get_native_source_code() const;
+
+ ParticlesShaderData() {}
+ virtual ~ParticlesShaderData();
+};
+
+ShaderData *_create_particles_shader_func();
+
+struct ParticleProcessMaterialData : public MaterialData {
+ ParticlesShaderData *shader_data = nullptr;
+ RID uniform_set;
+
+ virtual void set_render_priority(int p_priority) {}
+ virtual void set_next_pass(RID p_pass) {}
+ virtual void update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty);
+ virtual void bind_uniforms();
+ virtual ~ParticleProcessMaterialData();
+};
+
+MaterialData *_create_particles_material_func(ShaderData *p_shader);
+
/* Global shader uniform structs */
struct GlobalShaderUniforms {
enum {
@@ -504,6 +532,7 @@ public:
SkyShaderGLES3 sky_shader;
SceneShaderGLES3 scene_shader;
CubemapFilterShaderGLES3 cubemap_filter_shader;
+ ParticlesShaderGLES3 particles_process_shader;
ShaderCompiler compiler_canvas;
ShaderCompiler compiler_scene;
diff --git a/drivers/gles3/storage/mesh_storage.cpp b/drivers/gles3/storage/mesh_storage.cpp
index 9ec0fc0286..d31ac4d413 100644
--- a/drivers/gles3/storage/mesh_storage.cpp
+++ b/drivers/gles3/storage/mesh_storage.cpp
@@ -44,10 +44,16 @@ MeshStorage *MeshStorage::get_singleton() {
MeshStorage::MeshStorage() {
singleton = this;
+
+ {
+ skeleton_shader.shader.initialize();
+ skeleton_shader.shader_version = skeleton_shader.shader.version_create();
+ }
}
MeshStorage::~MeshStorage() {
singleton = nullptr;
+ skeleton_shader.shader.version_free(skeleton_shader.shader_version);
}
/* MESH API */
@@ -87,7 +93,6 @@ void MeshStorage::mesh_set_blend_shape_count(RID p_mesh, int p_blend_shape_count
ERR_FAIL_COND(!mesh);
ERR_FAIL_COND(mesh->surface_count > 0); //surfaces already exist
- WARN_PRINT_ONCE("blend shapes not supported by GLES3 renderer yet");
mesh->blend_shape_count = p_blend_shape_count;
}
@@ -111,7 +116,6 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface)
uint32_t attrib_stride = 0;
uint32_t skin_stride = 0;
- // TODO: I think this should be <=, but it is copied from RendererRD, will have to verify later
for (int i = 0; i < RS::ARRAY_WEIGHTS; i++) {
if ((p_surface.format & (1 << i))) {
switch (i) {
@@ -245,25 +249,82 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface)
s->aabb = p_surface.aabb;
s->bone_aabbs = p_surface.bone_aabbs; //only really useful for returning them.
- if (mesh->blend_shape_count > 0) {
- //s->blend_shape_buffer = RD::get_singleton()->storage_buffer_create(p_surface.blend_shape_data.size(), p_surface.blend_shape_data);
+ if (p_surface.skin_data.size() || mesh->blend_shape_count > 0) {
+ // Size must match the size of the vertex array.
+ int size = p_surface.vertex_data.size();
+ int vertex_size = 0;
+ int stride = 0;
+ int normal_offset = 0;
+ int tangent_offset = 0;
+ if ((p_surface.format & (1 << RS::ARRAY_VERTEX))) {
+ if (p_surface.format & RS::ARRAY_FLAG_USE_2D_VERTICES) {
+ vertex_size = 2;
+ } else {
+ vertex_size = 3;
+ }
+ stride = sizeof(float) * vertex_size;
+ }
+ if ((p_surface.format & (1 << RS::ARRAY_NORMAL))) {
+ normal_offset = stride;
+ stride += sizeof(uint16_t) * 2;
+ }
+ if ((p_surface.format & (1 << RS::ARRAY_TANGENT))) {
+ tangent_offset = stride;
+ stride += sizeof(uint16_t) * 2;
+ }
+
+ if (mesh->blend_shape_count > 0) {
+ // Blend shapes are passed as one large array, for OpenGL, we need to split each of them into their own buffer
+ s->blend_shapes = memnew_arr(Mesh::Surface::BlendShape, mesh->blend_shape_count);
+
+ for (uint32_t i = 0; i < mesh->blend_shape_count; i++) {
+ glGenVertexArrays(1, &s->blend_shapes[i].vertex_array);
+ glBindVertexArray(s->blend_shapes[i].vertex_array);
+ glGenBuffers(1, &s->blend_shapes[i].vertex_buffer);
+ glBindBuffer(GL_ARRAY_BUFFER, s->blend_shapes[i].vertex_buffer);
+ glBufferData(GL_ARRAY_BUFFER, size, p_surface.blend_shape_data.ptr() + i * size, (s->format & RS::ARRAY_FLAG_USE_DYNAMIC_UPDATE) ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW);
+
+ if ((p_surface.format & (1 << RS::ARRAY_VERTEX))) {
+ glEnableVertexAttribArray(RS::ARRAY_VERTEX + 3);
+ glVertexAttribPointer(RS::ARRAY_VERTEX + 3, vertex_size, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(0));
+ }
+ if ((p_surface.format & (1 << RS::ARRAY_NORMAL))) {
+ glEnableVertexAttribArray(RS::ARRAY_NORMAL + 3);
+ glVertexAttribPointer(RS::ARRAY_NORMAL + 3, 2, GL_UNSIGNED_SHORT, GL_TRUE, stride, CAST_INT_TO_UCHAR_PTR(normal_offset));
+ }
+ if ((p_surface.format & (1 << RS::ARRAY_TANGENT))) {
+ glEnableVertexAttribArray(RS::ARRAY_TANGENT + 3);
+ glVertexAttribPointer(RS::ARRAY_TANGENT + 3, 2, GL_UNSIGNED_SHORT, GL_TRUE, stride, CAST_INT_TO_UCHAR_PTR(tangent_offset));
+ }
+ }
+ glBindVertexArray(0);
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ }
+
+ // Create a vertex array to use for skeleton/blend shapes.
+ glGenVertexArrays(1, &s->skeleton_vertex_array);
+ glBindVertexArray(s->skeleton_vertex_array);
+ glBindBuffer(GL_ARRAY_BUFFER, s->vertex_buffer);
+
+ if ((p_surface.format & (1 << RS::ARRAY_VERTEX))) {
+ glEnableVertexAttribArray(RS::ARRAY_VERTEX);
+ glVertexAttribPointer(RS::ARRAY_VERTEX, vertex_size, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(0));
+ }
+ if ((p_surface.format & (1 << RS::ARRAY_NORMAL))) {
+ glEnableVertexAttribArray(RS::ARRAY_NORMAL);
+ glVertexAttribPointer(RS::ARRAY_NORMAL, 2, GL_UNSIGNED_SHORT, GL_TRUE, stride, CAST_INT_TO_UCHAR_PTR(normal_offset));
+ }
+ if ((p_surface.format & (1 << RS::ARRAY_TANGENT))) {
+ glEnableVertexAttribArray(RS::ARRAY_TANGENT);
+ glVertexAttribPointer(RS::ARRAY_TANGENT, 2, GL_UNSIGNED_SHORT, GL_TRUE, stride, CAST_INT_TO_UCHAR_PTR(tangent_offset));
+ }
+ glBindVertexArray(0);
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
}
if (mesh->surface_count == 0) {
- mesh->bone_aabbs = p_surface.bone_aabbs;
mesh->aabb = p_surface.aabb;
} else {
- if (mesh->bone_aabbs.size() < p_surface.bone_aabbs.size()) {
- // ArrayMesh::_surface_set_data only allocates bone_aabbs up to max_bone
- // Each surface may affect different numbers of bones.
- mesh->bone_aabbs.resize(p_surface.bone_aabbs.size());
- }
- for (int i = 0; i < p_surface.bone_aabbs.size(); i++) {
- const AABB &bone = p_surface.bone_aabbs[i];
- if (bone.has_volume()) {
- mesh->bone_aabbs.write[i].merge_with(bone);
- }
- }
mesh->aabb.merge_with(p_surface.aabb);
}
@@ -409,7 +470,13 @@ RS::SurfaceData MeshStorage::mesh_get_surface(RID p_mesh, int p_surface) const {
}
sd.bone_aabbs = s.bone_aabbs;
- glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+ if (mesh->blend_shape_count) {
+ sd.blend_shape_data = Vector<uint8_t>();
+ for (uint32_t i = 0; i < mesh->blend_shape_count; i++) {
+ sd.blend_shape_data.append_array(Utilities::buffer_get_data(GL_ARRAY_BUFFER, s.blend_shapes[i].vertex_buffer, s.vertex_buffer_size));
+ }
+ }
return sd;
}
@@ -442,7 +509,7 @@ AABB MeshStorage::mesh_get_aabb(RID p_mesh, RID p_skeleton) {
Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton);
- if (!skeleton || skeleton->size == 0) {
+ if (!skeleton || skeleton->size == 0 || mesh->skeleton_aabb_version == skeleton->version) {
return mesh->aabb;
}
@@ -536,6 +603,8 @@ AABB MeshStorage::mesh_get_aabb(RID p_mesh, RID p_skeleton) {
}
}
+ mesh->aabb = aabb;
+ mesh->skeleton_aabb_version = skeleton->version;
return aabb;
}
@@ -605,6 +674,24 @@ void MeshStorage::mesh_clear(RID p_mesh) {
memdelete_arr(s.lods);
}
+ if (mesh->blend_shape_count) {
+ for (uint32_t j = 0; j < mesh->blend_shape_count; j++) {
+ if (s.blend_shapes[j].vertex_buffer != 0) {
+ glDeleteBuffers(1, &s.blend_shapes[j].vertex_buffer);
+ s.blend_shapes[j].vertex_buffer = 0;
+ }
+ if (s.blend_shapes[j].vertex_array != 0) {
+ glDeleteVertexArrays(1, &s.blend_shapes[j].vertex_array);
+ s.blend_shapes[j].vertex_array = 0;
+ }
+ }
+ memdelete_arr(s.blend_shapes);
+ }
+ if (s.skeleton_vertex_array != 0) {
+ glDeleteVertexArrays(1, &s.skeleton_vertex_array);
+ s.skeleton_vertex_array = 0;
+ }
+
memdelete(mesh->surfaces[i]);
}
if (mesh->surfaces) {
@@ -660,15 +747,15 @@ void MeshStorage::_mesh_surface_generate_version_for_input_mask(Mesh::Surface::V
case RS::ARRAY_NORMAL: {
attribs[i].offset = vertex_stride;
attribs[i].size = 2;
- attribs[i].type = GL_UNSIGNED_SHORT;
- vertex_stride += sizeof(uint16_t) * 2;
+ attribs[i].type = (mis ? GL_FLOAT : GL_UNSIGNED_SHORT);
+ vertex_stride += sizeof(uint16_t) * 2 * (mis ? 2 : 1);
attribs[i].normalized = GL_TRUE;
} break;
case RS::ARRAY_TANGENT: {
attribs[i].offset = vertex_stride;
attribs[i].size = 2;
- attribs[i].type = GL_UNSIGNED_SHORT;
- vertex_stride += sizeof(uint16_t) * 2;
+ attribs[i].type = (mis ? GL_FLOAT : GL_UNSIGNED_SHORT);
+ vertex_stride += sizeof(uint16_t) * 2 * (mis ? 2 : 1);
attribs[i].normalized = GL_TRUE;
} break;
case RS::ARRAY_COLOR: {
@@ -713,7 +800,7 @@ void MeshStorage::_mesh_surface_generate_version_for_input_mask(Mesh::Surface::V
attribs[i].offset = skin_stride;
attribs[i].size = 4;
attribs[i].type = GL_UNSIGNED_SHORT;
- attributes_stride += 4 * sizeof(uint16_t);
+ skin_stride += 4 * sizeof(uint16_t);
attribs[i].normalized = GL_FALSE;
attribs[i].integer = true;
} break;
@@ -721,7 +808,7 @@ void MeshStorage::_mesh_surface_generate_version_for_input_mask(Mesh::Surface::V
attribs[i].offset = skin_stride;
attribs[i].size = 4;
attribs[i].type = GL_UNSIGNED_SHORT;
- attributes_stride += 4 * sizeof(uint16_t);
+ skin_stride += 4 * sizeof(uint16_t);
attribs[i].normalized = GL_TRUE;
} break;
}
@@ -812,7 +899,7 @@ void MeshStorage::mesh_instance_set_blend_shape_weight(RID p_mesh_instance, int
ERR_FAIL_COND(!mi);
ERR_FAIL_INDEX(p_shape, (int)mi->blend_weights.size());
mi->blend_weights[p_shape] = p_weight;
- mi->weights_dirty = true;
+ mi->dirty = true;
}
void MeshStorage::_mesh_instance_clear(MeshInstance *mi) {
@@ -824,38 +911,65 @@ void MeshStorage::_mesh_instance_clear(MeshInstance *mi) {
}
memfree(mi->surfaces[i].versions);
}
+
+ if (mi->surfaces[i].vertex_buffers[0] != 0) {
+ glDeleteBuffers(2, mi->surfaces[i].vertex_buffers);
+ mi->surfaces[i].vertex_buffers[0] = 0;
+ mi->surfaces[i].vertex_buffers[1] = 0;
+ }
+
if (mi->surfaces[i].vertex_buffer != 0) {
glDeleteBuffers(1, &mi->surfaces[i].vertex_buffer);
mi->surfaces[i].vertex_buffer = 0;
}
}
mi->surfaces.clear();
-
- if (mi->blend_weights_buffer != 0) {
- glDeleteBuffers(1, &mi->blend_weights_buffer);
- mi->blend_weights_buffer = 0;
- }
mi->blend_weights.clear();
- mi->weights_dirty = false;
mi->skeleton_version = 0;
}
void MeshStorage::_mesh_instance_add_surface(MeshInstance *mi, Mesh *mesh, uint32_t p_surface) {
- if (mesh->blend_shape_count > 0 && mi->blend_weights_buffer == 0) {
+ if (mesh->blend_shape_count > 0) {
mi->blend_weights.resize(mesh->blend_shape_count);
for (uint32_t i = 0; i < mi->blend_weights.size(); i++) {
- mi->blend_weights[i] = 0;
+ mi->blend_weights[i] = 0.0;
}
- // Todo allocate buffer for blend_weights and copy data to it
- //mi->blend_weights_buffer = RD::get_singleton()->storage_buffer_create(sizeof(float) * mi->blend_weights.size(), mi->blend_weights.to_byte_array());
-
- mi->weights_dirty = true;
}
MeshInstance::Surface s;
- if (mesh->blend_shape_count > 0 || (mesh->surfaces[p_surface]->format & RS::ARRAY_FORMAT_BONES)) {
- //surface warrants transform
- //s.vertex_buffer = RD::get_singleton()->vertex_buffer_create(mesh->surfaces[p_surface]->vertex_buffer_size, Vector<uint8_t>(), true);
+ if ((mesh->blend_shape_count > 0 || (mesh->surfaces[p_surface]->format & RS::ARRAY_FORMAT_BONES)) && mesh->surfaces[p_surface]->vertex_buffer_size > 0) {
+ // Cache surface properties
+ s.format_cache = mesh->surfaces[p_surface]->format;
+ if ((s.format_cache & (1 << RS::ARRAY_VERTEX))) {
+ if (s.format_cache & RS::ARRAY_FLAG_USE_2D_VERTICES) {
+ s.vertex_size_cache = 2;
+ } else {
+ s.vertex_size_cache = 3;
+ }
+ s.vertex_stride_cache = sizeof(float) * s.vertex_size_cache;
+ }
+ if ((s.format_cache & (1 << RS::ARRAY_NORMAL))) {
+ s.vertex_normal_offset_cache = s.vertex_stride_cache;
+ s.vertex_stride_cache += sizeof(uint32_t) * 2;
+ }
+ if ((s.format_cache & (1 << RS::ARRAY_TANGENT))) {
+ s.vertex_tangent_offset_cache = s.vertex_stride_cache;
+ s.vertex_stride_cache += sizeof(uint32_t) * 2;
+ }
+
+ // Buffer to be used for rendering. Final output of skeleton and blend shapes.
+ glGenBuffers(1, &s.vertex_buffer);
+ glBindBuffer(GL_ARRAY_BUFFER, s.vertex_buffer);
+ glBufferData(GL_ARRAY_BUFFER, s.vertex_stride_cache * mesh->surfaces[p_surface]->vertex_count, nullptr, GL_DYNAMIC_DRAW);
+ if (mesh->blend_shape_count > 0) {
+ // Ping-Pong buffers for processing blendshapes.
+ glGenBuffers(2, s.vertex_buffers);
+ for (uint32_t i = 0; i < 2; i++) {
+ glBindBuffer(GL_ARRAY_BUFFER, s.vertex_buffers[i]);
+ glBufferData(GL_ARRAY_BUFFER, s.vertex_stride_cache * mesh->surfaces[p_surface]->vertex_count, nullptr, GL_DYNAMIC_DRAW);
+ }
+ }
+ glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind
}
mi->surfaces.push_back(s);
@@ -867,11 +981,6 @@ void MeshStorage::mesh_instance_check_for_update(RID p_mesh_instance) {
bool needs_update = mi->dirty;
- if (mi->weights_dirty && !mi->weight_update_list.in_list()) {
- dirty_mesh_instance_weights.add(&mi->weight_update_list);
- needs_update = true;
- }
-
if (mi->array_update_list.in_list()) {
return;
}
@@ -888,22 +997,223 @@ void MeshStorage::mesh_instance_check_for_update(RID p_mesh_instance) {
}
}
-void MeshStorage::update_mesh_instances() {
- while (dirty_mesh_instance_weights.first()) {
- MeshInstance *mi = dirty_mesh_instance_weights.first()->self();
+void MeshStorage::_blend_shape_bind_mesh_instance_buffer(MeshInstance *p_mi, uint32_t p_surface) {
+ glBindBuffer(GL_ARRAY_BUFFER, p_mi->surfaces[p_surface].vertex_buffers[0]);
- if (mi->blend_weights_buffer != 0) {
- //RD::get_singleton()->buffer_update(mi->blend_weights_buffer, 0, mi->blend_weights.size() * sizeof(float), mi->blend_weights.ptr());
- }
- dirty_mesh_instance_weights.remove(&mi->weight_update_list);
- mi->weights_dirty = false;
+ if ((p_mi->surfaces[p_surface].format_cache & (1 << RS::ARRAY_VERTEX))) {
+ glEnableVertexAttribArray(RS::ARRAY_VERTEX);
+ glVertexAttribPointer(RS::ARRAY_VERTEX, p_mi->surfaces[p_surface].vertex_size_cache, GL_FLOAT, GL_FALSE, p_mi->surfaces[p_surface].vertex_stride_cache, CAST_INT_TO_UCHAR_PTR(0));
+ } else {
+ glDisableVertexAttribArray(RS::ARRAY_VERTEX);
+ }
+ if ((p_mi->surfaces[p_surface].format_cache & (1 << RS::ARRAY_NORMAL))) {
+ glEnableVertexAttribArray(RS::ARRAY_NORMAL);
+ glVertexAttribIPointer(RS::ARRAY_NORMAL, 2, GL_UNSIGNED_INT, p_mi->surfaces[p_surface].vertex_stride_cache, CAST_INT_TO_UCHAR_PTR(p_mi->surfaces[p_surface].vertex_normal_offset_cache));
+ } else {
+ glDisableVertexAttribArray(RS::ARRAY_NORMAL);
}
+ if ((p_mi->surfaces[p_surface].format_cache & (1 << RS::ARRAY_TANGENT))) {
+ glEnableVertexAttribArray(RS::ARRAY_TANGENT);
+ glVertexAttribIPointer(RS::ARRAY_TANGENT, 2, GL_UNSIGNED_INT, p_mi->surfaces[p_surface].vertex_stride_cache, CAST_INT_TO_UCHAR_PTR(p_mi->surfaces[p_surface].vertex_tangent_offset_cache));
+ } else {
+ glDisableVertexAttribArray(RS::ARRAY_TANGENT);
+ }
+}
+
+void MeshStorage::_compute_skeleton(MeshInstance *p_mi, Skeleton *p_sk, uint32_t p_surface) {
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+ // Add in the bones and weights.
+ glBindBuffer(GL_ARRAY_BUFFER, p_mi->mesh->surfaces[p_surface]->skin_buffer);
+
+ bool use_8_weights = p_mi->surfaces[p_surface].format_cache & RS::ARRAY_FLAG_USE_8_BONE_WEIGHTS;
+ int skin_stride = sizeof(int16_t) * (use_8_weights ? 16 : 8);
+ glEnableVertexAttribArray(RS::ARRAY_BONES);
+ glVertexAttribIPointer(RS::ARRAY_BONES, 4, GL_UNSIGNED_SHORT, skin_stride, CAST_INT_TO_UCHAR_PTR(0));
+ if (use_8_weights) {
+ glEnableVertexAttribArray(11);
+ glVertexAttribIPointer(11, 4, GL_UNSIGNED_SHORT, skin_stride, CAST_INT_TO_UCHAR_PTR(4 * sizeof(uint16_t)));
+ glEnableVertexAttribArray(12);
+ glVertexAttribPointer(12, 4, GL_UNSIGNED_SHORT, GL_TRUE, skin_stride, CAST_INT_TO_UCHAR_PTR(8 * sizeof(uint16_t)));
+ glEnableVertexAttribArray(13);
+ glVertexAttribPointer(13, 4, GL_UNSIGNED_SHORT, GL_TRUE, skin_stride, CAST_INT_TO_UCHAR_PTR(12 * sizeof(uint16_t)));
+ } else {
+ glEnableVertexAttribArray(RS::ARRAY_WEIGHTS);
+ glVertexAttribPointer(RS::ARRAY_WEIGHTS, 4, GL_UNSIGNED_SHORT, GL_TRUE, skin_stride, CAST_INT_TO_UCHAR_PTR(4 * sizeof(uint16_t)));
+ }
+
+ glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, p_mi->surfaces[p_surface].vertex_buffer);
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, p_sk->transforms_texture);
+
+ glBeginTransformFeedback(GL_POINTS);
+ glDrawArrays(GL_POINTS, 0, p_mi->mesh->surfaces[p_surface]->vertex_count);
+ glEndTransformFeedback();
+
+ glDisableVertexAttribArray(RS::ARRAY_BONES);
+ glDisableVertexAttribArray(RS::ARRAY_WEIGHTS);
+ glDisableVertexAttribArray(RS::ARRAY_BONES + 2);
+ glDisableVertexAttribArray(RS::ARRAY_WEIGHTS + 2);
+ glBindVertexArray(0);
+ glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
+}
+
+void MeshStorage::update_mesh_instances() {
if (dirty_mesh_instance_arrays.first() == nullptr) {
return; //nothing to do
}
+ glEnable(GL_RASTERIZER_DISCARD);
// Process skeletons and blend shapes using transform feedback
- // TODO: Implement when working on skeletons and blend shapes
+ while (dirty_mesh_instance_arrays.first()) {
+ MeshInstance *mi = dirty_mesh_instance_arrays.first()->self();
+
+ Skeleton *sk = skeleton_owner.get_or_null(mi->skeleton);
+
+ // Precompute base weight if using blend shapes.
+ float base_weight = 1.0;
+ if (mi->mesh->blend_shape_count && mi->mesh->blend_shape_mode == RS::BLEND_SHAPE_MODE_NORMALIZED) {
+ for (uint32_t i = 0; i < mi->mesh->blend_shape_count; i++) {
+ base_weight -= mi->blend_weights[i];
+ }
+ }
+
+ for (uint32_t i = 0; i < mi->surfaces.size(); i++) {
+ if (mi->surfaces[i].vertex_buffer == 0 || mi->mesh->surfaces[i]->skeleton_vertex_array == 0) {
+ continue;
+ }
+
+ bool array_is_2d = mi->surfaces[i].format_cache & RS::ARRAY_FLAG_USE_2D_VERTICES;
+ bool can_use_skeleton = sk != nullptr && sk->use_2d == array_is_2d && (mi->surfaces[i].format_cache & RS::ARRAY_FORMAT_BONES);
+ bool use_8_weights = mi->surfaces[i].format_cache & RS::ARRAY_FLAG_USE_8_BONE_WEIGHTS;
+
+ // Always process blend shapes first.
+ if (mi->mesh->blend_shape_count) {
+ SkeletonShaderGLES3::ShaderVariant variant = SkeletonShaderGLES3::MODE_BASE_PASS;
+ uint64_t specialization = 0;
+ specialization |= array_is_2d ? SkeletonShaderGLES3::MODE_2D : 0;
+ specialization |= SkeletonShaderGLES3::USE_BLEND_SHAPES;
+ if (!array_is_2d) {
+ if ((mi->surfaces[i].format_cache & (1 << RS::ARRAY_NORMAL))) {
+ specialization |= SkeletonShaderGLES3::USE_NORMAL;
+ }
+ if ((mi->surfaces[i].format_cache & (1 << RS::ARRAY_TANGENT))) {
+ specialization |= SkeletonShaderGLES3::USE_TANGENT;
+ }
+ }
+
+ bool success = skeleton_shader.shader.version_bind_shader(skeleton_shader.shader_version, variant, specialization);
+ if (!success) {
+ continue;
+ }
+
+ skeleton_shader.shader.version_set_uniform(SkeletonShaderGLES3::BLEND_WEIGHT, base_weight, skeleton_shader.shader_version, variant, specialization);
+ skeleton_shader.shader.version_set_uniform(SkeletonShaderGLES3::BLEND_SHAPE_COUNT, float(mi->mesh->blend_shape_count), skeleton_shader.shader_version, variant, specialization);
+
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ glBindVertexArray(mi->mesh->surfaces[i]->skeleton_vertex_array);
+ glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, mi->surfaces[i].vertex_buffers[0]);
+ glBeginTransformFeedback(GL_POINTS);
+ glDrawArrays(GL_POINTS, 0, mi->mesh->surfaces[i]->vertex_count);
+ glEndTransformFeedback();
+
+ variant = SkeletonShaderGLES3::MODE_BLEND_PASS;
+ success = skeleton_shader.shader.version_bind_shader(skeleton_shader.shader_version, variant, specialization);
+ if (!success) {
+ continue;
+ }
+
+ //Do the last blend shape separately, as it can be combined with the skeleton pass.
+ for (uint32_t bs = 0; bs < mi->mesh->blend_shape_count - 1; bs++) {
+ float weight = mi->blend_weights[bs];
+
+ if (Math::is_zero_approx(weight)) {
+ //not bother with this one
+ continue;
+ }
+ skeleton_shader.shader.version_set_uniform(SkeletonShaderGLES3::BLEND_WEIGHT, weight, skeleton_shader.shader_version, variant, specialization);
+ skeleton_shader.shader.version_set_uniform(SkeletonShaderGLES3::BLEND_SHAPE_COUNT, float(mi->mesh->blend_shape_count), skeleton_shader.shader_version, variant, specialization);
+
+ glBindVertexArray(mi->mesh->surfaces[i]->blend_shapes[bs].vertex_array);
+ _blend_shape_bind_mesh_instance_buffer(mi, i);
+ glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, mi->surfaces[i].vertex_buffers[1]);
+
+ glBeginTransformFeedback(GL_POINTS);
+ glDrawArrays(GL_POINTS, 0, mi->mesh->surfaces[i]->vertex_count);
+ glEndTransformFeedback();
+
+ SWAP(mi->surfaces[i].vertex_buffers[0], mi->surfaces[i].vertex_buffers[1]);
+ }
+ uint32_t bs = mi->mesh->blend_shape_count - 1;
+
+ float weight = mi->blend_weights[bs];
+
+ glBindVertexArray(mi->mesh->surfaces[i]->blend_shapes[bs].vertex_array);
+ _blend_shape_bind_mesh_instance_buffer(mi, i);
+
+ specialization |= can_use_skeleton ? SkeletonShaderGLES3::USE_SKELETON : 0;
+ specialization |= (can_use_skeleton && use_8_weights) ? SkeletonShaderGLES3::USE_EIGHT_WEIGHTS : 0;
+ specialization |= SkeletonShaderGLES3::FINAL_PASS;
+ success = skeleton_shader.shader.version_bind_shader(skeleton_shader.shader_version, variant, specialization);
+ if (!success) {
+ continue;
+ }
+
+ skeleton_shader.shader.version_set_uniform(SkeletonShaderGLES3::BLEND_WEIGHT, weight, skeleton_shader.shader_version, variant, specialization);
+ skeleton_shader.shader.version_set_uniform(SkeletonShaderGLES3::BLEND_SHAPE_COUNT, float(mi->mesh->blend_shape_count), skeleton_shader.shader_version, variant, specialization);
+
+ if (can_use_skeleton) {
+ // Do last blendshape in the same pass as the Skeleton.
+ _compute_skeleton(mi, sk, i);
+ can_use_skeleton = false;
+ } else {
+ // Do last blendshape by itself and prepare vertex data for use by the renderer.
+ glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, mi->surfaces[i].vertex_buffer);
+
+ glBeginTransformFeedback(GL_POINTS);
+ glDrawArrays(GL_POINTS, 0, mi->mesh->surfaces[i]->vertex_count);
+ glEndTransformFeedback();
+ }
+
+ glBindVertexArray(0);
+ glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
+ }
+
+ // This branch should only execute when Skeleton is run by itself.
+ if (can_use_skeleton) {
+ SkeletonShaderGLES3::ShaderVariant variant = SkeletonShaderGLES3::MODE_BASE_PASS;
+ uint64_t specialization = 0;
+ specialization |= array_is_2d ? SkeletonShaderGLES3::MODE_2D : 0;
+ specialization |= SkeletonShaderGLES3::USE_SKELETON;
+ specialization |= SkeletonShaderGLES3::FINAL_PASS;
+ specialization |= use_8_weights ? SkeletonShaderGLES3::USE_EIGHT_WEIGHTS : 0;
+ if (!array_is_2d) {
+ if ((mi->surfaces[i].format_cache & (1 << RS::ARRAY_NORMAL))) {
+ specialization |= SkeletonShaderGLES3::USE_NORMAL;
+ }
+ if ((mi->surfaces[i].format_cache & (1 << RS::ARRAY_TANGENT))) {
+ specialization |= SkeletonShaderGLES3::USE_TANGENT;
+ }
+ }
+
+ bool success = skeleton_shader.shader.version_bind_shader(skeleton_shader.shader_version, variant, specialization);
+ if (!success) {
+ continue;
+ }
+
+ glBindVertexArray(mi->mesh->surfaces[i]->skeleton_vertex_array);
+ _compute_skeleton(mi, sk, i);
+ }
+ }
+ mi->dirty = false;
+ if (sk) {
+ mi->skeleton_version = sk->version;
+ }
+ dirty_mesh_instance_arrays.remove(&mi->array_update_list);
+ }
+ glDisable(GL_RASTERIZER_DISCARD);
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0);
}
/* MULTIMESH API */
@@ -1574,45 +1884,207 @@ void MeshStorage::_update_dirty_multimeshes() {
/* SKELETON API */
RID MeshStorage::skeleton_allocate() {
- return RID();
+ return skeleton_owner.allocate_rid();
}
void MeshStorage::skeleton_initialize(RID p_rid) {
+ skeleton_owner.initialize_rid(p_rid, Skeleton());
}
void MeshStorage::skeleton_free(RID p_rid) {
+ _update_dirty_skeletons();
+ skeleton_allocate_data(p_rid, 0);
+ Skeleton *skeleton = skeleton_owner.get_or_null(p_rid);
+ skeleton->dependency.deleted_notify(p_rid);
+ skeleton_owner.free(p_rid);
+}
+
+void MeshStorage::_skeleton_make_dirty(Skeleton *skeleton) {
+ if (!skeleton->dirty) {
+ skeleton->dirty = true;
+ skeleton->dirty_list = skeleton_dirty_list;
+ skeleton_dirty_list = skeleton;
+ }
}
void MeshStorage::skeleton_allocate_data(RID p_skeleton, int p_bones, bool p_2d_skeleton) {
+ Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton);
+ ERR_FAIL_COND(!skeleton);
+ ERR_FAIL_COND(p_bones < 0);
+
+ if (skeleton->size == p_bones && skeleton->use_2d == p_2d_skeleton) {
+ return;
+ }
+
+ skeleton->size = p_bones;
+ skeleton->use_2d = p_2d_skeleton;
+ skeleton->height = (p_bones * (p_2d_skeleton ? 2 : 3)) / 256;
+ if ((p_bones * (p_2d_skeleton ? 2 : 3)) % 256) {
+ skeleton->height++;
+ }
+
+ if (skeleton->transforms_texture != 0) {
+ glDeleteTextures(1, &skeleton->transforms_texture);
+ skeleton->transforms_texture = 0;
+ skeleton->data.clear();
+ }
+
+ if (skeleton->size) {
+ skeleton->data.resize(256 * skeleton->height * 4);
+ glGenTextures(1, &skeleton->transforms_texture);
+ glBindTexture(GL_TEXTURE_2D, skeleton->transforms_texture);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 256, skeleton->height, 0, GL_RGBA, GL_FLOAT, nullptr);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ memset(skeleton->data.ptrw(), 0, skeleton->data.size() * sizeof(float));
+
+ _skeleton_make_dirty(skeleton);
+ }
+
+ skeleton->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_SKELETON_DATA);
}
void MeshStorage::skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform) {
+ Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton);
+
+ ERR_FAIL_NULL(skeleton);
+ ERR_FAIL_COND(!skeleton->use_2d);
+
+ skeleton->base_transform_2d = p_base_transform;
}
int MeshStorage::skeleton_get_bone_count(RID p_skeleton) const {
- return 0;
+ Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton);
+ ERR_FAIL_COND_V(!skeleton, 0);
+
+ return skeleton->size;
}
void MeshStorage::skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform3D &p_transform) {
+ Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton);
+
+ ERR_FAIL_COND(!skeleton);
+ ERR_FAIL_INDEX(p_bone, skeleton->size);
+ ERR_FAIL_COND(skeleton->use_2d);
+
+ float *dataptr = skeleton->data.ptrw() + p_bone * 12;
+
+ dataptr[0] = p_transform.basis.rows[0][0];
+ dataptr[1] = p_transform.basis.rows[0][1];
+ dataptr[2] = p_transform.basis.rows[0][2];
+ dataptr[3] = p_transform.origin.x;
+ dataptr[4] = p_transform.basis.rows[1][0];
+ dataptr[5] = p_transform.basis.rows[1][1];
+ dataptr[6] = p_transform.basis.rows[1][2];
+ dataptr[7] = p_transform.origin.y;
+ dataptr[8] = p_transform.basis.rows[2][0];
+ dataptr[9] = p_transform.basis.rows[2][1];
+ dataptr[10] = p_transform.basis.rows[2][2];
+ dataptr[11] = p_transform.origin.z;
+
+ _skeleton_make_dirty(skeleton);
}
Transform3D MeshStorage::skeleton_bone_get_transform(RID p_skeleton, int p_bone) const {
- return Transform3D();
+ Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton);
+
+ ERR_FAIL_COND_V(!skeleton, Transform3D());
+ ERR_FAIL_INDEX_V(p_bone, skeleton->size, Transform3D());
+ ERR_FAIL_COND_V(skeleton->use_2d, Transform3D());
+
+ const float *dataptr = skeleton->data.ptr() + p_bone * 12;
+
+ Transform3D t;
+
+ t.basis.rows[0][0] = dataptr[0];
+ t.basis.rows[0][1] = dataptr[1];
+ t.basis.rows[0][2] = dataptr[2];
+ t.origin.x = dataptr[3];
+ t.basis.rows[1][0] = dataptr[4];
+ t.basis.rows[1][1] = dataptr[5];
+ t.basis.rows[1][2] = dataptr[6];
+ t.origin.y = dataptr[7];
+ t.basis.rows[2][0] = dataptr[8];
+ t.basis.rows[2][1] = dataptr[9];
+ t.basis.rows[2][2] = dataptr[10];
+ t.origin.z = dataptr[11];
+
+ return t;
}
void MeshStorage::skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform) {
+ Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton);
+
+ ERR_FAIL_COND(!skeleton);
+ ERR_FAIL_INDEX(p_bone, skeleton->size);
+ ERR_FAIL_COND(!skeleton->use_2d);
+
+ float *dataptr = skeleton->data.ptrw() + p_bone * 8;
+
+ dataptr[0] = p_transform.columns[0][0];
+ dataptr[1] = p_transform.columns[1][0];
+ dataptr[2] = 0;
+ dataptr[3] = p_transform.columns[2][0];
+ dataptr[4] = p_transform.columns[0][1];
+ dataptr[5] = p_transform.columns[1][1];
+ dataptr[6] = 0;
+ dataptr[7] = p_transform.columns[2][1];
+
+ _skeleton_make_dirty(skeleton);
}
Transform2D MeshStorage::skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const {
- return Transform2D();
+ Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton);
+
+ ERR_FAIL_COND_V(!skeleton, Transform2D());
+ ERR_FAIL_INDEX_V(p_bone, skeleton->size, Transform2D());
+ ERR_FAIL_COND_V(!skeleton->use_2d, Transform2D());
+
+ const float *dataptr = skeleton->data.ptr() + p_bone * 8;
+
+ Transform2D t;
+ t.columns[0][0] = dataptr[0];
+ t.columns[1][0] = dataptr[1];
+ t.columns[2][0] = dataptr[3];
+ t.columns[0][1] = dataptr[4];
+ t.columns[1][1] = dataptr[5];
+ t.columns[2][1] = dataptr[7];
+
+ return t;
}
-void MeshStorage::skeleton_update_dependency(RID p_base, DependencyTracker *p_instance) {
+void MeshStorage::_update_dirty_skeletons() {
+ while (skeleton_dirty_list) {
+ Skeleton *skeleton = skeleton_dirty_list;
+
+ if (skeleton->size) {
+ glBindTexture(GL_TEXTURE_2D, skeleton->transforms_texture);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 256, skeleton->height, 0, GL_RGBA, GL_FLOAT, skeleton->data.ptr());
+ glBindTexture(GL_TEXTURE_2D, 0);
+ }
+
+ skeleton_dirty_list = skeleton->dirty_list;
+
+ skeleton->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_SKELETON_BONES);
+
+ skeleton->version++;
+
+ skeleton->dirty = false;
+ skeleton->dirty_list = nullptr;
+ }
+
+ skeleton_dirty_list = nullptr;
}
-/* OCCLUDER */
+void MeshStorage::skeleton_update_dependency(RID p_skeleton, DependencyTracker *p_instance) {
+ Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton);
+ ERR_FAIL_COND(!skeleton);
-void MeshStorage::occluder_set_mesh(RID p_occluder, const PackedVector3Array &p_vertices, const PackedInt32Array &p_indices) {
+ p_instance->update_dependency(&skeleton->dependency);
}
#endif // GLES3_ENABLED
diff --git a/drivers/gles3/storage/mesh_storage.h b/drivers/gles3/storage/mesh_storage.h
index a31db24f2d..cbbba0d03e 100644
--- a/drivers/gles3/storage/mesh_storage.h
+++ b/drivers/gles3/storage/mesh_storage.h
@@ -33,6 +33,7 @@
#ifdef GLES3_ENABLED
+#include "../shaders/skeleton.glsl.gen.h"
#include "core/templates/local_vector.h"
#include "core/templates/rid_owner.h"
#include "core/templates/self_list.h"
@@ -102,7 +103,13 @@ struct Mesh {
Vector<AABB> bone_aabbs;
- GLuint blend_shape_buffer = 0;
+ struct BlendShape {
+ GLuint vertex_buffer = 0;
+ GLuint vertex_array = 0;
+ };
+
+ BlendShape *blend_shapes = nullptr;
+ GLuint skeleton_vertex_array = 0;
RID material;
};
@@ -113,12 +120,11 @@ struct Mesh {
Surface **surfaces = nullptr;
uint32_t surface_count = 0;
- Vector<AABB> bone_aabbs;
-
bool has_bone_weights = false;
AABB aabb;
AABB custom_aabb;
+ uint64_t skeleton_aabb_version = 0;
Vector<RID> material_cache;
@@ -136,7 +142,14 @@ struct MeshInstance {
Mesh *mesh = nullptr;
RID skeleton;
struct Surface {
+ GLuint vertex_buffers[2] = { 0, 0 };
+ GLuint vertex_arrays[2] = { 0, 0 };
GLuint vertex_buffer = 0;
+ int vertex_stride_cache = 0;
+ int vertex_size_cache = 0;
+ int vertex_normal_offset_cache = 0;
+ int vertex_tangent_offset_cache = 0;
+ uint32_t format_cache = 0;
Mesh::Surface::Version *versions = nullptr; //allocated on demand
uint32_t version_count = 0;
@@ -144,7 +157,6 @@ struct MeshInstance {
LocalVector<Surface> surfaces;
LocalVector<float> blend_weights;
- GLuint blend_weights_buffer = 0;
List<MeshInstance *>::Element *I = nullptr; //used to erase itself
uint64_t skeleton_version = 0;
bool dirty = false;
@@ -186,13 +198,15 @@ struct MultiMesh {
struct Skeleton {
bool use_2d = false;
int size = 0;
+ int height = 0;
Vector<float> data;
- GLuint buffer = 0;
bool dirty = false;
Skeleton *dirty_list = nullptr;
Transform2D base_transform_2d;
+ GLuint transforms_texture = 0;
+
uint64_t version = 1;
Dependency dependency;
@@ -202,6 +216,11 @@ class MeshStorage : public RendererMeshStorage {
private:
static MeshStorage *singleton;
+ struct {
+ SkeletonShaderGLES3 shader;
+ RID shader_version;
+ } skeleton_shader;
+
/* Mesh */
mutable RID_Owner<Mesh, true> mesh_owner;
@@ -214,6 +233,7 @@ private:
void _mesh_instance_clear(MeshInstance *mi);
void _mesh_instance_add_surface(MeshInstance *mi, Mesh *mesh, uint32_t p_surface);
+ void _blend_shape_bind_mesh_instance_buffer(MeshInstance *p_mi, uint32_t p_surface);
SelfList<MeshInstance>::List dirty_mesh_instance_weights;
SelfList<MeshInstance>::List dirty_mesh_instance_arrays;
@@ -232,9 +252,10 @@ private:
mutable RID_Owner<Skeleton, true> skeleton_owner;
- Skeleton *skeleton_dirty_list = nullptr;
-
_FORCE_INLINE_ void _skeleton_make_dirty(Skeleton *skeleton);
+ void _compute_skeleton(MeshInstance *p_mi, Skeleton *p_sk, uint32_t p_surface);
+
+ Skeleton *skeleton_dirty_list = nullptr;
public:
static MeshStorage *get_singleton();
@@ -327,6 +348,7 @@ public:
_FORCE_INLINE_ uint32_t mesh_surface_get_lod(void *p_surface, float p_model_scale, float p_distance_threshold, float p_mesh_lod_threshold, uint32_t &r_index_count) const {
Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface);
+ ERR_FAIL_COND_V(!s, 0);
int32_t current_lod = -1;
r_index_count = s->index_count;
@@ -403,6 +425,8 @@ public:
virtual void mesh_instance_check_for_update(RID p_mesh_instance) override;
virtual void update_mesh_instances() override;
+ // TODO: considering hashing versions with multimesh buffer RID.
+ // Doing so would allow us to avoid specifying multimesh buffer pointers every frame and may improve performance.
_FORCE_INLINE_ void mesh_instance_surface_get_vertex_arrays_and_format(RID p_mesh_instance, uint32_t p_surface_index, uint32_t p_input_mask, GLuint &r_vertex_array_gl) {
MeshInstance *mi = mesh_instance_owner.get_or_null(p_mesh_instance);
ERR_FAIL_COND(!mi);
@@ -531,9 +555,11 @@ public:
virtual void skeleton_update_dependency(RID p_base, DependencyTracker *p_instance) override;
- /* OCCLUDER */
+ void _update_dirty_skeletons();
- void occluder_set_mesh(RID p_occluder, const PackedVector3Array &p_vertices, const PackedInt32Array &p_indices);
+ _FORCE_INLINE_ bool skeleton_is_valid(RID p_skeleton) {
+ return skeleton_owner.get_or_null(p_skeleton) != nullptr;
+ }
};
} // namespace GLES3
diff --git a/drivers/gles3/storage/particles_storage.cpp b/drivers/gles3/storage/particles_storage.cpp
index 9ed9fedd5a..e158a3e90c 100644
--- a/drivers/gles3/storage/particles_storage.cpp
+++ b/drivers/gles3/storage/particles_storage.cpp
@@ -31,6 +31,12 @@
#ifdef GLES3_ENABLED
#include "particles_storage.h"
+#include "material_storage.h"
+#include "mesh_storage.h"
+#include "texture_storage.h"
+#include "utilities.h"
+
+#include "servers/rendering/rendering_server_default.h"
using namespace GLES3;
@@ -42,213 +48,1347 @@ ParticlesStorage *ParticlesStorage::get_singleton() {
ParticlesStorage::ParticlesStorage() {
singleton = this;
+ GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton();
+
+ {
+ String global_defines;
+ global_defines += "#define MAX_GLOBAL_SHADER_UNIFORMS 256\n"; // TODO: this is arbitrary for now
+ material_storage->shaders.particles_process_shader.initialize(global_defines, 1);
+ }
+ {
+ // default material and shader for particles shader
+ particles_shader.default_shader = material_storage->shader_allocate();
+ material_storage->shader_initialize(particles_shader.default_shader);
+ material_storage->shader_set_code(particles_shader.default_shader, R"(
+// Default particles shader.
+
+shader_type particles;
+
+void process() {
+ COLOR = vec4(1.0);
+}
+)");
+ particles_shader.default_material = material_storage->material_allocate();
+ material_storage->material_initialize(particles_shader.default_material);
+ material_storage->material_set_shader(particles_shader.default_material, particles_shader.default_shader);
+ }
+ {
+ particles_shader.copy_shader.initialize();
+ particles_shader.copy_shader_version = particles_shader.copy_shader.version_create();
+ }
}
ParticlesStorage::~ParticlesStorage() {
singleton = nullptr;
+ GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton();
+
+ material_storage->material_free(particles_shader.default_material);
+ material_storage->shader_free(particles_shader.default_shader);
+ particles_shader.copy_shader.version_free(particles_shader.copy_shader_version);
}
/* PARTICLES */
RID ParticlesStorage::particles_allocate() {
- return RID();
+ return particles_owner.allocate_rid();
}
void ParticlesStorage::particles_initialize(RID p_rid) {
+ particles_owner.initialize_rid(p_rid, Particles());
}
void ParticlesStorage::particles_free(RID p_rid) {
+ update_particles();
+ Particles *particles = particles_owner.get_or_null(p_rid);
+ particles->dependency.deleted_notify(p_rid);
+ _particles_free_data(particles);
+ particles_owner.free(p_rid);
}
void ParticlesStorage::particles_set_mode(RID p_particles, RS::ParticlesMode p_mode) {
-}
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+ if (particles->mode == p_mode) {
+ return;
+ }
-void ParticlesStorage::particles_emit(RID p_particles, const Transform3D &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags) {
+ _particles_free_data(particles);
+
+ particles->mode = p_mode;
}
void ParticlesStorage::particles_set_emitting(RID p_particles, bool p_emitting) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+
+ particles->emitting = p_emitting;
+}
+
+bool ParticlesStorage::particles_get_emitting(RID p_particles) {
+ ERR_FAIL_COND_V_MSG(RSG::threaded, false, "This function should never be used with threaded rendering, as it stalls the renderer.");
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND_V(!particles, false);
+
+ return particles->emitting;
+}
+
+void ParticlesStorage::_particles_free_data(Particles *particles) {
+ particles->userdata_count = 0;
+ particles->instance_buffer_size_cache = 0;
+ particles->instance_buffer_stride_cache = 0;
+ particles->num_attrib_arrays_cache = 0;
+ particles->process_buffer_stride_cache = 0;
+
+ if (particles->front_process_buffer != 0) {
+ glDeleteVertexArrays(1, &particles->front_vertex_array);
+ glDeleteBuffers(1, &particles->front_process_buffer);
+ glDeleteBuffers(1, &particles->front_instance_buffer);
+ particles->front_vertex_array = 0;
+ particles->front_process_buffer = 0;
+ particles->front_instance_buffer = 0;
+
+ glDeleteVertexArrays(1, &particles->back_vertex_array);
+ glDeleteBuffers(1, &particles->back_process_buffer);
+ glDeleteBuffers(1, &particles->back_instance_buffer);
+ particles->back_vertex_array = 0;
+ particles->back_process_buffer = 0;
+ particles->back_instance_buffer = 0;
+ }
+
+ if (particles->sort_buffer != 0) {
+ glDeleteBuffers(1, &particles->last_frame_buffer);
+ glDeleteBuffers(1, &particles->sort_buffer);
+ particles->last_frame_buffer = 0;
+ particles->sort_buffer = 0;
+ particles->sort_buffer_filled = false;
+ particles->last_frame_buffer_filled = false;
+ }
+
+ if (particles->frame_params_ubo != 0) {
+ glDeleteBuffers(1, &particles->frame_params_ubo);
+ particles->frame_params_ubo = 0;
+ }
}
void ParticlesStorage::particles_set_amount(RID p_particles, int p_amount) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+
+ if (particles->amount == p_amount) {
+ return;
+ }
+
+ _particles_free_data(particles);
+
+ particles->amount = p_amount;
+
+ particles->prev_ticks = 0;
+ particles->phase = 0;
+ particles->prev_phase = 0;
+ particles->clear = true;
+
+ particles->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_PARTICLES);
}
void ParticlesStorage::particles_set_lifetime(RID p_particles, double p_lifetime) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+ particles->lifetime = p_lifetime;
}
void ParticlesStorage::particles_set_one_shot(RID p_particles, bool p_one_shot) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+ particles->one_shot = p_one_shot;
}
void ParticlesStorage::particles_set_pre_process_time(RID p_particles, double p_time) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+ particles->pre_process_time = p_time;
}
-
void ParticlesStorage::particles_set_explosiveness_ratio(RID p_particles, real_t p_ratio) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+ particles->explosiveness = p_ratio;
}
-
void ParticlesStorage::particles_set_randomness_ratio(RID p_particles, real_t p_ratio) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+ particles->randomness = p_ratio;
}
void ParticlesStorage::particles_set_custom_aabb(RID p_particles, const AABB &p_aabb) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+ particles->custom_aabb = p_aabb;
+ particles->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB);
}
void ParticlesStorage::particles_set_speed_scale(RID p_particles, double p_scale) {
-}
-
-void ParticlesStorage::particles_set_use_local_coordinates(RID p_particles, bool p_enable) {
-}
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
-void ParticlesStorage::particles_set_process_material(RID p_particles, RID p_material) {
+ particles->speed_scale = p_scale;
}
+void ParticlesStorage::particles_set_use_local_coordinates(RID p_particles, bool p_enable) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
-RID ParticlesStorage::particles_get_process_material(RID p_particles) const {
- return RID();
+ particles->use_local_coords = p_enable;
+ particles->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_PARTICLES);
}
void ParticlesStorage::particles_set_fixed_fps(RID p_particles, int p_fps) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+
+ particles->fixed_fps = p_fps;
+
+ _particles_free_data(particles);
+
+ particles->prev_ticks = 0;
+ particles->phase = 0;
+ particles->prev_phase = 0;
+ particles->clear = true;
+
+ particles->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_PARTICLES);
}
void ParticlesStorage::particles_set_interpolate(RID p_particles, bool p_enable) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+
+ particles->interpolate = p_enable;
}
void ParticlesStorage::particles_set_fractional_delta(RID p_particles, bool p_enable) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+
+ particles->fractional_delta = p_enable;
}
-void ParticlesStorage::particles_set_subemitter(RID p_particles, RID p_subemitter_particles) {
+void ParticlesStorage::particles_set_trails(RID p_particles, bool p_enable, double p_length) {
+ if (p_enable) {
+ WARN_PRINT_ONCE("The OpenGL 3 renderer does not support particle trails");
+ }
}
-void ParticlesStorage::particles_set_view_axis(RID p_particles, const Vector3 &p_axis, const Vector3 &p_up_axis) {
+void ParticlesStorage::particles_set_trail_bind_poses(RID p_particles, const Vector<Transform3D> &p_bind_poses) {
+ if (p_bind_poses.size() != 0) {
+ WARN_PRINT_ONCE("The OpenGL 3 renderer does not support particle trails");
+ }
}
void ParticlesStorage::particles_set_collision_base_size(RID p_particles, real_t p_size) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+
+ particles->collision_base_size = p_size;
}
void ParticlesStorage::particles_set_transform_align(RID p_particles, RS::ParticlesTransformAlign p_transform_align) {
-}
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
-void ParticlesStorage::particles_set_trails(RID p_particles, bool p_enable, double p_length) {
+ particles->transform_align = p_transform_align;
}
-void ParticlesStorage::particles_set_trail_bind_poses(RID p_particles, const Vector<Transform3D> &p_bind_poses) {
+void ParticlesStorage::particles_set_process_material(RID p_particles, RID p_material) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+
+ particles->process_material = p_material;
+ particles->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_PARTICLES); //the instance buffer may have changed
}
-void ParticlesStorage::particles_restart(RID p_particles) {
+RID ParticlesStorage::particles_get_process_material(RID p_particles) const {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND_V(!particles, RID());
+
+ return particles->process_material;
}
void ParticlesStorage::particles_set_draw_order(RID p_particles, RS::ParticlesDrawOrder p_order) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+
+ particles->draw_order = p_order;
}
-void ParticlesStorage::particles_set_draw_passes(RID p_particles, int p_count) {
+void ParticlesStorage::particles_set_draw_passes(RID p_particles, int p_passes) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+
+ particles->draw_passes.resize(p_passes);
}
void ParticlesStorage::particles_set_draw_pass_mesh(RID p_particles, int p_pass, RID p_mesh) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+ ERR_FAIL_INDEX(p_pass, particles->draw_passes.size());
+ particles->draw_passes.write[p_pass] = p_mesh;
+ particles->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_PARTICLES);
+}
+
+void ParticlesStorage::particles_restart(RID p_particles) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+
+ particles->restart_request = true;
+}
+
+void ParticlesStorage::particles_set_subemitter(RID p_particles, RID p_subemitter_particles) {
+ if (p_subemitter_particles.is_valid()) {
+ WARN_PRINT_ONCE("The OpenGL 3 renderer does not support particle sub emitters");
+ }
+}
+
+void ParticlesStorage::particles_emit(RID p_particles, const Transform3D &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags) {
+ WARN_PRINT_ONCE("The OpenGL 3 renderer does not support manually emitting particles");
}
void ParticlesStorage::particles_request_process(RID p_particles) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+
+ if (!particles->dirty) {
+ particles->dirty = true;
+ particles->update_list = particle_update_list;
+ particle_update_list = particles;
+ }
}
AABB ParticlesStorage::particles_get_current_aabb(RID p_particles) {
- return AABB();
+ if (RSG::threaded) {
+ WARN_PRINT_ONCE("Calling this function with threaded rendering enabled stalls the renderer, use with care.");
+ }
+
+ const Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND_V(!particles, AABB());
+
+ int total_amount = particles->amount;
+
+ // If available, read from the sort buffer which should be 2 frames out of date.
+ // This will help alleviate GPU stalls.
+ GLuint read_buffer = particles->sort_buffer_filled ? particles->sort_buffer : particles->back_instance_buffer;
+
+ Vector<uint8_t> buffer = Utilities::buffer_get_data(GL_ARRAY_BUFFER, read_buffer, total_amount * sizeof(ParticleInstanceData3D));
+ ERR_FAIL_COND_V(buffer.size() != (int)(total_amount * sizeof(ParticleInstanceData3D)), AABB());
+
+ Transform3D inv = particles->emission_transform.affine_inverse();
+
+ AABB aabb;
+ if (buffer.size()) {
+ bool first = true;
+
+ const uint8_t *data_ptr = (const uint8_t *)buffer.ptr();
+ uint32_t particle_data_size = sizeof(ParticleInstanceData3D) + sizeof(float) * particles->userdata_count;
+
+ for (int i = 0; i < total_amount; i++) {
+ const ParticleInstanceData3D &particle_data = *(const ParticleInstanceData3D *)&data_ptr[particle_data_size * i];
+ // If scale is 0.0, we assume the particle is inactive.
+ if (particle_data.xform[0] > 0.0) {
+ Vector3 pos = Vector3(particle_data.xform[3], particle_data.xform[7], particle_data.xform[11]);
+ if (!particles->use_local_coords) {
+ pos = inv.xform(pos);
+ }
+ if (first) {
+ aabb.position = pos;
+ first = false;
+ } else {
+ aabb.expand_to(pos);
+ }
+ }
+ }
+ }
+
+ float longest_axis_size = 0;
+ for (int i = 0; i < particles->draw_passes.size(); i++) {
+ if (particles->draw_passes[i].is_valid()) {
+ AABB maabb = MeshStorage::get_singleton()->mesh_get_aabb(particles->draw_passes[i], RID());
+ longest_axis_size = MAX(maabb.get_longest_axis_size(), longest_axis_size);
+ }
+ }
+
+ aabb.grow_by(longest_axis_size);
+
+ return aabb;
}
AABB ParticlesStorage::particles_get_aabb(RID p_particles) const {
- return AABB();
+ const Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND_V(!particles, AABB());
+
+ return particles->custom_aabb;
}
void ParticlesStorage::particles_set_emission_transform(RID p_particles, const Transform3D &p_transform) {
-}
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
-bool ParticlesStorage::particles_get_emitting(RID p_particles) {
- return false;
+ particles->emission_transform = p_transform;
}
int ParticlesStorage::particles_get_draw_passes(RID p_particles) const {
- return 0;
-}
+ const Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND_V(!particles, 0);
-RID ParticlesStorage::particles_get_draw_pass_mesh(RID p_particles, int p_pass) const {
- return RID();
+ return particles->draw_passes.size();
}
-void ParticlesStorage::particles_add_collision(RID p_particles, RID p_instance) {
+RID ParticlesStorage::particles_get_draw_pass_mesh(RID p_particles, int p_pass) const {
+ const Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND_V(!particles, RID());
+ ERR_FAIL_INDEX_V(p_pass, particles->draw_passes.size(), RID());
+
+ return particles->draw_passes[p_pass];
}
-void ParticlesStorage::particles_remove_collision(RID p_particles, RID p_instance) {
+void ParticlesStorage::particles_add_collision(RID p_particles, RID p_particles_collision_instance) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+ particles->collisions.insert(p_particles_collision_instance);
+}
+
+void ParticlesStorage::particles_remove_collision(RID p_particles, RID p_particles_collision_instance) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+ particles->collisions.erase(p_particles_collision_instance);
+}
+
+void ParticlesStorage::particles_set_canvas_sdf_collision(RID p_particles, bool p_enable, const Transform2D &p_xform, const Rect2 &p_to_screen, GLuint p_texture) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+ particles->has_sdf_collision = p_enable;
+ particles->sdf_collision_transform = p_xform;
+ particles->sdf_collision_to_screen = p_to_screen;
+ particles->sdf_collision_texture = p_texture;
+}
+
+// Does one step of processing particles by reading from back_process_buffer and writing to front_process_buffer.
+void ParticlesStorage::_particles_process(Particles *p_particles, double p_delta) {
+ GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
+ GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton();
+
+ double new_phase = Math::fmod(p_particles->phase + (p_delta / p_particles->lifetime) * p_particles->speed_scale, 1.0);
+
+ //update current frame
+ ParticlesFrameParams frame_params;
+
+ if (p_particles->clear) {
+ p_particles->cycle_number = 0;
+ p_particles->random_seed = Math::rand();
+ } else if (new_phase < p_particles->phase) {
+ if (p_particles->one_shot) {
+ p_particles->emitting = false;
+ }
+ p_particles->cycle_number++;
+ }
+
+ frame_params.emitting = p_particles->emitting;
+ frame_params.system_phase = new_phase;
+ frame_params.prev_system_phase = p_particles->phase;
+
+ p_particles->phase = new_phase;
+
+ frame_params.time = RSG::rasterizer->get_total_time();
+ frame_params.delta = p_delta * p_particles->speed_scale;
+ frame_params.random_seed = p_particles->random_seed;
+ frame_params.explosiveness = p_particles->explosiveness;
+ frame_params.randomness = p_particles->randomness;
+
+ if (p_particles->use_local_coords) {
+ GLES3::MaterialStorage::store_transform(Transform3D(), frame_params.emission_transform);
+ } else {
+ GLES3::MaterialStorage::store_transform(p_particles->emission_transform, frame_params.emission_transform);
+ }
+
+ frame_params.cycle = p_particles->cycle_number;
+ frame_params.frame = p_particles->frame_counter++;
+ frame_params.pad0 = 0;
+ frame_params.pad1 = 0;
+ frame_params.pad2 = 0;
+
+ { //collision and attractors
+
+ frame_params.collider_count = 0;
+ frame_params.attractor_count = 0;
+ frame_params.particle_size = p_particles->collision_base_size;
+
+ GLuint collision_heightmap_texture = 0;
+
+ Transform3D to_particles;
+ if (p_particles->use_local_coords) {
+ to_particles = p_particles->emission_transform.affine_inverse();
+ }
+
+ if (p_particles->has_sdf_collision && p_particles->sdf_collision_texture != 0) {
+ //2D collision
+
+ Transform2D xform = p_particles->sdf_collision_transform; //will use dotproduct manually so invert beforehand
+
+ if (!p_particles->use_local_coords) {
+ Transform2D emission;
+ emission.columns[0] = Vector2(p_particles->emission_transform.basis.get_column(0).x, p_particles->emission_transform.basis.get_column(0).y);
+ emission.columns[1] = Vector2(p_particles->emission_transform.basis.get_column(1).x, p_particles->emission_transform.basis.get_column(1).y);
+ emission.set_origin(Vector2(p_particles->emission_transform.origin.x, p_particles->emission_transform.origin.y));
+ xform = xform * emission.affine_inverse();
+ }
+
+ Transform2D revert = xform.affine_inverse();
+ frame_params.collider_count = 1;
+ frame_params.colliders[0].transform[0] = xform.columns[0][0];
+ frame_params.colliders[0].transform[1] = xform.columns[0][1];
+ frame_params.colliders[0].transform[2] = 0;
+ frame_params.colliders[0].transform[3] = xform.columns[2][0];
+
+ frame_params.colliders[0].transform[4] = xform.columns[1][0];
+ frame_params.colliders[0].transform[5] = xform.columns[1][1];
+ frame_params.colliders[0].transform[6] = 0;
+ frame_params.colliders[0].transform[7] = xform.columns[2][1];
+
+ frame_params.colliders[0].transform[8] = revert.columns[0][0];
+ frame_params.colliders[0].transform[9] = revert.columns[0][1];
+ frame_params.colliders[0].transform[10] = 0;
+ frame_params.colliders[0].transform[11] = revert.columns[2][0];
+
+ frame_params.colliders[0].transform[12] = revert.columns[1][0];
+ frame_params.colliders[0].transform[13] = revert.columns[1][1];
+ frame_params.colliders[0].transform[14] = 0;
+ frame_params.colliders[0].transform[15] = revert.columns[2][1];
+
+ frame_params.colliders[0].extents[0] = p_particles->sdf_collision_to_screen.size.x;
+ frame_params.colliders[0].extents[1] = p_particles->sdf_collision_to_screen.size.y;
+ frame_params.colliders[0].extents[2] = p_particles->sdf_collision_to_screen.position.x;
+ frame_params.colliders[0].scale = p_particles->sdf_collision_to_screen.position.y;
+ frame_params.colliders[0].type = ParticlesFrameParams::COLLISION_TYPE_2D_SDF;
+
+ collision_heightmap_texture = p_particles->sdf_collision_texture;
+ }
+
+ for (const RID &E : p_particles->collisions) {
+ ParticlesCollisionInstance *pci = particles_collision_instance_owner.get_or_null(E);
+ if (!pci || !pci->active) {
+ continue;
+ }
+ ParticlesCollision *pc = particles_collision_owner.get_or_null(pci->collision);
+ ERR_CONTINUE(!pc);
+
+ Transform3D to_collider = pci->transform;
+ if (p_particles->use_local_coords) {
+ to_collider = to_particles * to_collider;
+ }
+ Vector3 scale = to_collider.basis.get_scale();
+ to_collider.basis.orthonormalize();
+
+ if (pc->type <= RS::PARTICLES_COLLISION_TYPE_VECTOR_FIELD_ATTRACT) {
+ //attractor
+ if (frame_params.attractor_count >= ParticlesFrameParams::MAX_ATTRACTORS) {
+ continue;
+ }
+
+ ParticlesFrameParams::Attractor &attr = frame_params.attractors[frame_params.attractor_count];
+
+ GLES3::MaterialStorage::store_transform(to_collider, attr.transform);
+ attr.strength = pc->attractor_strength;
+ attr.attenuation = pc->attractor_attenuation;
+ attr.directionality = pc->attractor_directionality;
+
+ switch (pc->type) {
+ case RS::PARTICLES_COLLISION_TYPE_SPHERE_ATTRACT: {
+ attr.type = ParticlesFrameParams::ATTRACTOR_TYPE_SPHERE;
+ float radius = pc->radius;
+ radius *= (scale.x + scale.y + scale.z) / 3.0;
+ attr.extents[0] = radius;
+ attr.extents[1] = radius;
+ attr.extents[2] = radius;
+ } break;
+ case RS::PARTICLES_COLLISION_TYPE_BOX_ATTRACT: {
+ attr.type = ParticlesFrameParams::ATTRACTOR_TYPE_BOX;
+ Vector3 extents = pc->extents * scale;
+ attr.extents[0] = extents.x;
+ attr.extents[1] = extents.y;
+ attr.extents[2] = extents.z;
+ } break;
+ case RS::PARTICLES_COLLISION_TYPE_VECTOR_FIELD_ATTRACT: {
+ WARN_PRINT_ONCE("Vector field particle attractors are not available in the OpenGL2 renderer.");
+ } break;
+ default: {
+ }
+ }
+
+ frame_params.attractor_count++;
+ } else {
+ //collider
+ if (frame_params.collider_count >= ParticlesFrameParams::MAX_COLLIDERS) {
+ continue;
+ }
+
+ ParticlesFrameParams::Collider &col = frame_params.colliders[frame_params.collider_count];
+
+ GLES3::MaterialStorage::store_transform(to_collider, col.transform);
+ switch (pc->type) {
+ case RS::PARTICLES_COLLISION_TYPE_SPHERE_COLLIDE: {
+ col.type = ParticlesFrameParams::COLLISION_TYPE_SPHERE;
+ float radius = pc->radius;
+ radius *= (scale.x + scale.y + scale.z) / 3.0;
+ col.extents[0] = radius;
+ col.extents[1] = radius;
+ col.extents[2] = radius;
+ } break;
+ case RS::PARTICLES_COLLISION_TYPE_BOX_COLLIDE: {
+ col.type = ParticlesFrameParams::COLLISION_TYPE_BOX;
+ Vector3 extents = pc->extents * scale;
+ col.extents[0] = extents.x;
+ col.extents[1] = extents.y;
+ col.extents[2] = extents.z;
+ } break;
+ case RS::PARTICLES_COLLISION_TYPE_SDF_COLLIDE: {
+ WARN_PRINT_ONCE("SDF Particle Colliders are not available in the OpenGL 3 renderer.");
+ } break;
+ case RS::PARTICLES_COLLISION_TYPE_HEIGHTFIELD_COLLIDE: {
+ if (collision_heightmap_texture != 0) { //already taken
+ continue;
+ }
+
+ col.type = ParticlesFrameParams::COLLISION_TYPE_HEIGHT_FIELD;
+ Vector3 extents = pc->extents * scale;
+ col.extents[0] = extents.x;
+ col.extents[1] = extents.y;
+ col.extents[2] = extents.z;
+ collision_heightmap_texture = pc->heightfield_texture;
+ } break;
+ default: {
+ }
+ }
+
+ frame_params.collider_count++;
+ }
+ }
+
+ // Bind heightmap or SDF texture.
+ GLuint heightmap = collision_heightmap_texture;
+ if (heightmap == 0) {
+ GLES3::Texture *tex = texture_storage->get_texture(texture_storage->texture_gl_get_default(GLES3::DEFAULT_GL_TEXTURE_BLACK));
+ heightmap = tex->tex_id;
+ }
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, heightmap);
+ }
+
+ if (p_particles->frame_params_ubo == 0) {
+ glGenBuffers(1, &p_particles->frame_params_ubo);
+ }
+ // Update per-frame UBO.
+ glBindBufferBase(GL_UNIFORM_BUFFER, PARTICLES_FRAME_UNIFORM_LOCATION, p_particles->frame_params_ubo);
+ glBufferData(GL_UNIFORM_BUFFER, sizeof(ParticlesFrameParams), &frame_params, GL_STREAM_DRAW);
+
+ // Get shader and set shader uniforms;
+ ParticleProcessMaterialData *m = static_cast<ParticleProcessMaterialData *>(material_storage->material_get_data(p_particles->process_material, RS::SHADER_PARTICLES));
+ if (!m) {
+ m = static_cast<ParticleProcessMaterialData *>(material_storage->material_get_data(particles_shader.default_material, RS::SHADER_PARTICLES));
+ }
+
+ ERR_FAIL_COND(!m);
+
+ ParticlesShaderGLES3::ShaderVariant variant = ParticlesShaderGLES3::MODE_DEFAULT;
+
+ uint32_t specialization = 0;
+ for (uint32_t i = 0; i < p_particles->userdata_count; i++) {
+ specialization |= (1 << i);
+ }
+
+ if (p_particles->mode == RS::ParticlesMode::PARTICLES_MODE_3D) {
+ specialization |= ParticlesShaderGLES3::MODE_3D;
+ }
+
+ RID version = particles_shader.default_shader_version;
+ if (m->shader_data->version.is_valid() && m->shader_data->valid) {
+ // Bind material uniform buffer and textures.
+ m->bind_uniforms();
+ version = m->shader_data->version;
+ }
+
+ bool success = material_storage->shaders.particles_process_shader.version_bind_shader(version, variant, specialization);
+ if (!success) {
+ return;
+ }
+
+ material_storage->shaders.particles_process_shader.version_set_uniform(ParticlesShaderGLES3::LIFETIME, p_particles->lifetime, version, variant, specialization);
+ material_storage->shaders.particles_process_shader.version_set_uniform(ParticlesShaderGLES3::CLEAR, p_particles->clear, version, variant, specialization);
+ material_storage->shaders.particles_process_shader.version_set_uniform(ParticlesShaderGLES3::TOTAL_PARTICLES, uint32_t(p_particles->amount), version, variant, specialization);
+ material_storage->shaders.particles_process_shader.version_set_uniform(ParticlesShaderGLES3::USE_FRACTIONAL_DELTA, p_particles->fractional_delta, version, variant, specialization);
+
+ p_particles->clear = false;
+
+ p_particles->has_collision_cache = m->shader_data->uses_collision;
+
+ glBindVertexArray(p_particles->back_vertex_array);
+
+ glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, p_particles->front_process_buffer);
+
+ glBeginTransformFeedback(GL_POINTS);
+ glDrawArrays(GL_POINTS, 0, p_particles->amount);
+ glEndTransformFeedback();
+
+ glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0);
+ glBindVertexArray(0);
+
+ SWAP(p_particles->front_process_buffer, p_particles->back_process_buffer);
+ SWAP(p_particles->front_vertex_array, p_particles->back_vertex_array);
}
-void ParticlesStorage::particles_set_canvas_sdf_collision(RID p_particles, bool p_enable, const Transform2D &p_xform, const Rect2 &p_to_screen, RID p_texture) {
+void ParticlesStorage::particles_set_view_axis(RID p_particles, const Vector3 &p_axis, const Vector3 &p_up_axis) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+
+ if (particles->draw_order != RS::PARTICLES_DRAW_ORDER_VIEW_DEPTH && particles->transform_align != RS::PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD && particles->transform_align != RS::PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD_Y_TO_VELOCITY) {
+ return;
+ }
+
+ if (particles->front_process_buffer == 0) {
+ return; //particles have not processed yet
+ }
+
+ Vector3 axis = -p_axis; // cameras look to z negative
+
+ if (particles->use_local_coords) {
+ axis = particles->emission_transform.basis.xform_inv(axis).normalized();
+ }
+
+ // Sort will be done on CPU since we don't have compute shaders.
+ // If the sort_buffer has valid data
+ // Use a buffer that is 2 frames out of date to avoid stalls.
+ if (particles->draw_order == RS::PARTICLES_DRAW_ORDER_VIEW_DEPTH && particles->sort_buffer_filled) {
+ glBindBuffer(GL_ARRAY_BUFFER, particles->sort_buffer);
+
+ ParticleInstanceData3D *particle_array;
+#ifndef __EMSCRIPTEN__
+ particle_array = static_cast<ParticleInstanceData3D *>(glMapBufferRange(GL_ARRAY_BUFFER, 0, particles->amount * sizeof(ParticleInstanceData3D), GL_MAP_READ_BIT | GL_MAP_WRITE_BIT));
+ ERR_FAIL_NULL(particle_array);
+#else
+ LocalVector<ParticleInstanceData3D> particle_vector;
+ particle_vector.resize(particles->amount);
+ particle_array = particle_vector.ptr();
+ glGetBufferSubData(GL_ARRAY_BUFFER, 0, particles->amount * sizeof(ParticleInstanceData3D), particle_array);
+#endif
+ SortArray<ParticleInstanceData3D, ParticlesViewSort> sorter;
+ sorter.compare.z_dir = axis;
+ sorter.sort(particle_array, particles->amount);
+
+#ifndef __EMSCRIPTEN__
+ glUnmapBuffer(GL_ARRAY_BUFFER);
+#else
+ glBufferSubData(GL_ARRAY_BUFFER, 0, particles->amount * sizeof(ParticleInstanceData3D), particle_vector.ptr());
+#endif
+ }
+
+ glEnable(GL_RASTERIZER_DISCARD);
+ _particles_update_instance_buffer(particles, axis, p_up_axis);
+ glDisable(GL_RASTERIZER_DISCARD);
+}
+
+void ParticlesStorage::_particles_update_buffers(Particles *particles) {
+ GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton();
+ uint32_t userdata_count = 0;
+
+ if (particles->process_material.is_valid()) {
+ GLES3::ParticleProcessMaterialData *material_data = static_cast<GLES3::ParticleProcessMaterialData *>(material_storage->material_get_data(particles->process_material, RS::SHADER_PARTICLES));
+ if (material_data && material_data->shader_data->version.is_valid() && material_data->shader_data->valid) {
+ userdata_count = material_data->shader_data->userdata_count;
+ }
+ }
+
+ if (userdata_count != particles->userdata_count) {
+ // Mismatch userdata, re-create buffers.
+ _particles_free_data(particles);
+ }
+
+ if (particles->amount > 0 && particles->front_process_buffer == 0) {
+ int total_amount = particles->amount;
+
+ particles->userdata_count = userdata_count;
+
+ uint32_t xform_size = particles->mode == RS::PARTICLES_MODE_2D ? 2 : 3;
+ particles->instance_buffer_stride_cache = sizeof(float) * 4 * (xform_size + 1);
+ particles->instance_buffer_size_cache = particles->instance_buffer_stride_cache * total_amount;
+ particles->num_attrib_arrays_cache = 5 + userdata_count + (xform_size - 2);
+ particles->process_buffer_stride_cache = sizeof(float) * 4 * particles->num_attrib_arrays_cache;
+
+ int process_data_amount = 4 * particles->num_attrib_arrays_cache * total_amount;
+ float *data = memnew_arr(float, process_data_amount);
+
+ for (int i = 0; i < process_data_amount; i++) {
+ data[i] = 0;
+ }
+
+ {
+ glGenVertexArrays(1, &particles->front_vertex_array);
+ glBindVertexArray(particles->front_vertex_array);
+ glGenBuffers(1, &particles->front_process_buffer);
+ glGenBuffers(1, &particles->front_instance_buffer);
+
+ glBindBuffer(GL_ARRAY_BUFFER, particles->front_process_buffer);
+ glBufferData(GL_ARRAY_BUFFER, particles->process_buffer_stride_cache * total_amount, data, GL_DYNAMIC_COPY);
+
+ for (uint32_t j = 0; j < particles->num_attrib_arrays_cache; j++) {
+ glEnableVertexAttribArray(j);
+ glVertexAttribPointer(j, 4, GL_FLOAT, GL_FALSE, particles->process_buffer_stride_cache, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * j));
+ }
+ glBindVertexArray(0);
+
+ glBindBuffer(GL_ARRAY_BUFFER, particles->front_instance_buffer);
+ glBufferData(GL_ARRAY_BUFFER, particles->instance_buffer_size_cache, nullptr, GL_DYNAMIC_COPY);
+ }
+
+ {
+ glGenVertexArrays(1, &particles->back_vertex_array);
+ glBindVertexArray(particles->back_vertex_array);
+ glGenBuffers(1, &particles->back_process_buffer);
+ glGenBuffers(1, &particles->back_instance_buffer);
+
+ glBindBuffer(GL_ARRAY_BUFFER, particles->back_process_buffer);
+ glBufferData(GL_ARRAY_BUFFER, particles->process_buffer_stride_cache * total_amount, data, GL_DYNAMIC_COPY);
+
+ for (uint32_t j = 0; j < particles->num_attrib_arrays_cache; j++) {
+ glEnableVertexAttribArray(j);
+ glVertexAttribPointer(j, 4, GL_FLOAT, GL_FALSE, particles->process_buffer_stride_cache, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * j));
+ }
+ glBindVertexArray(0);
+
+ glBindBuffer(GL_ARRAY_BUFFER, particles->back_instance_buffer);
+ glBufferData(GL_ARRAY_BUFFER, particles->instance_buffer_size_cache, nullptr, GL_DYNAMIC_COPY);
+ }
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+ memdelete_arr(data);
+ }
+}
+
+void ParticlesStorage::_particles_allocate_history_buffers(Particles *particles) {
+ if (particles->sort_buffer == 0) {
+ glGenBuffers(1, &particles->last_frame_buffer);
+ glBindBuffer(GL_ARRAY_BUFFER, particles->last_frame_buffer);
+ glBufferData(GL_ARRAY_BUFFER, particles->instance_buffer_size_cache, nullptr, GL_DYNAMIC_READ);
+
+ glGenBuffers(1, &particles->sort_buffer);
+ glBindBuffer(GL_ARRAY_BUFFER, particles->sort_buffer);
+ glBufferData(GL_ARRAY_BUFFER, particles->instance_buffer_size_cache, nullptr, GL_DYNAMIC_READ);
+ particles->sort_buffer_filled = false;
+ particles->last_frame_buffer_filled = false;
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ }
+}
+void ParticlesStorage::_particles_update_instance_buffer(Particles *particles, const Vector3 &p_axis, const Vector3 &p_up_axis) {
+ ParticlesCopyShaderGLES3::ShaderVariant variant = ParticlesCopyShaderGLES3::MODE_DEFAULT;
+
+ uint64_t specialization = 0;
+ if (particles->mode == RS::ParticlesMode::PARTICLES_MODE_3D) {
+ specialization |= ParticlesCopyShaderGLES3::MODE_3D;
+ }
+
+ bool success = particles_shader.copy_shader.version_bind_shader(particles_shader.copy_shader_version, variant, specialization);
+ if (!success) {
+ return;
+ }
+
+ // Affect 2D only.
+ if (particles->use_local_coords) {
+ // 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.
+ particles_shader.copy_shader.version_set_uniform(ParticlesCopyShaderGLES3::INV_EMISSION_TRANSFORM, Transform3D(), particles_shader.copy_shader_version, variant, specialization);
+ } 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();
+ particles_shader.copy_shader.version_set_uniform(ParticlesCopyShaderGLES3::INV_EMISSION_TRANSFORM, inv, particles_shader.copy_shader_version, variant, specialization);
+ }
+
+ particles_shader.copy_shader.version_set_uniform(ParticlesCopyShaderGLES3::FRAME_REMAINDER, particles->interpolate ? particles->frame_remainder : 0.0, particles_shader.copy_shader_version, variant, specialization);
+ particles_shader.copy_shader.version_set_uniform(ParticlesCopyShaderGLES3::ALIGN_MODE, uint32_t(particles->transform_align), particles_shader.copy_shader_version, variant, specialization);
+ particles_shader.copy_shader.version_set_uniform(ParticlesCopyShaderGLES3::ALIGN_UP, p_up_axis, particles_shader.copy_shader_version, variant, specialization);
+ particles_shader.copy_shader.version_set_uniform(ParticlesCopyShaderGLES3::SORT_DIRECTION, p_axis, particles_shader.copy_shader_version, variant, specialization);
+
+ glBindVertexArray(particles->back_vertex_array);
+ glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, particles->front_instance_buffer, 0, particles->instance_buffer_size_cache);
+ glBeginTransformFeedback(GL_POINTS);
+
+ if (particles->draw_order == RS::PARTICLES_DRAW_ORDER_LIFETIME) {
+ uint32_t lifetime_split = MIN(particles->amount * particles->phase, particles->amount - 1);
+ uint32_t stride = particles->process_buffer_stride_cache;
+
+ glBindBuffer(GL_ARRAY_BUFFER, particles->back_process_buffer);
+
+ // Offset VBO so you render starting at the newest particle.
+ if (particles->amount - lifetime_split > 0) {
+ glEnableVertexAttribArray(0); // Color.
+ glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(stride * lifetime_split + sizeof(float) * 4 * 0));
+ glEnableVertexAttribArray(1); // .xyz: velocity. .z: flags.
+ glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(stride * lifetime_split + sizeof(float) * 4 * 1));
+ glEnableVertexAttribArray(2); // Custom.
+ glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(stride * lifetime_split + sizeof(float) * 4 * 2));
+ glEnableVertexAttribArray(3); // Xform1.
+ glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(stride * lifetime_split + sizeof(float) * 4 * 3));
+ glEnableVertexAttribArray(4); // Xform2.
+ glVertexAttribPointer(4, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(stride * lifetime_split + sizeof(float) * 4 * 4));
+ if (particles->mode == RS::PARTICLES_MODE_3D) {
+ glEnableVertexAttribArray(5); // Xform3.
+ glVertexAttribPointer(5, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(stride * lifetime_split + sizeof(float) * 4 * 5));
+ }
+
+ uint32_t to_draw = particles->amount - lifetime_split;
+ glDrawArrays(GL_POINTS, 0, to_draw);
+ }
+
+ // Then render from index 0 up intil the newest particle.
+ if (lifetime_split > 0) {
+ glEndTransformFeedback();
+ // Now output to the second portion of the instance buffer.
+ glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, particles->front_instance_buffer, particles->instance_buffer_stride_cache * (particles->amount - lifetime_split), particles->instance_buffer_stride_cache * (lifetime_split));
+ glBeginTransformFeedback(GL_POINTS);
+ // Reset back to normal.
+ for (uint32_t j = 0; j < particles->num_attrib_arrays_cache; j++) {
+ glEnableVertexAttribArray(j);
+ glVertexAttribPointer(j, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * j));
+ }
+
+ glDrawArrays(GL_POINTS, 0, lifetime_split);
+ }
+ } else {
+ glDrawArrays(GL_POINTS, 0, particles->amount);
+ }
+
+ glEndTransformFeedback();
+ glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0, 0, 0);
+ glBindVertexArray(0);
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
}
void ParticlesStorage::update_particles() {
+ glEnable(GL_RASTERIZER_DISCARD);
+
+ GLuint global_buffer = GLES3::MaterialStorage::get_singleton()->global_shader_parameters_get_uniform_buffer();
+
+ glBindBufferBase(GL_UNIFORM_BUFFER, PARTICLES_GLOBALS_UNIFORM_LOCATION, global_buffer);
+ glBindBuffer(GL_UNIFORM_BUFFER, 0);
+
+ while (particle_update_list) {
+ // Use transform feedback to process particles.
+
+ Particles *particles = particle_update_list;
+
+ particle_update_list = particles->update_list;
+ particles->update_list = nullptr;
+ particles->dirty = false;
+
+ _particles_update_buffers(particles);
+
+ if (particles->restart_request) {
+ particles->prev_ticks = 0;
+ particles->phase = 0;
+ particles->prev_phase = 0;
+ particles->clear = true;
+ particles->restart_request = false;
+ }
+
+ if (particles->inactive && !particles->emitting) {
+ //go next
+ continue;
+ }
+
+ if (particles->emitting) {
+ if (particles->inactive) {
+ //restart system from scratch
+ particles->prev_ticks = 0;
+ particles->phase = 0;
+ particles->prev_phase = 0;
+ particles->clear = true;
+ }
+ particles->inactive = false;
+ particles->inactive_time = 0;
+ } else {
+ particles->inactive_time += particles->speed_scale * RSG::rasterizer->get_frame_delta_time();
+ if (particles->inactive_time > particles->lifetime * 1.2) {
+ particles->inactive = true;
+ continue;
+ }
+ }
+
+ // Copy the instance buffer that was last used into the last_frame buffer.
+ // sort_buffer should now be 2 frames out of date.
+ if (particles->draw_order == RS::PARTICLES_DRAW_ORDER_VIEW_DEPTH || particles->draw_order == RS::PARTICLES_DRAW_ORDER_REVERSE_LIFETIME) {
+ _particles_allocate_history_buffers(particles);
+ SWAP(particles->last_frame_buffer, particles->sort_buffer);
+
+ glBindBuffer(GL_COPY_READ_BUFFER, particles->back_instance_buffer);
+ glBindBuffer(GL_COPY_WRITE_BUFFER, particles->last_frame_buffer);
+ glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, 0, 0, particles->instance_buffer_size_cache);
+
+ // Last frame's last_frame turned into this frame's sort buffer.
+ particles->sort_buffer_filled = particles->last_frame_buffer_filled;
+ particles->sort_buffer_phase = particles->last_frame_phase;
+ particles->last_frame_buffer_filled = true;
+ particles->last_frame_phase = particles->phase;
+ glBindBuffer(GL_COPY_READ_BUFFER, 0);
+ glBindBuffer(GL_COPY_WRITE_BUFFER, 0);
+ }
+
+ int fixed_fps = 0;
+ if (particles->fixed_fps > 0) {
+ fixed_fps = particles->fixed_fps;
+ }
+
+ bool zero_time_scale = Engine::get_singleton()->get_time_scale() <= 0.0;
+
+ if (particles->clear && particles->pre_process_time > 0.0) {
+ double frame_time;
+ if (fixed_fps > 0) {
+ frame_time = 1.0 / fixed_fps;
+ } else {
+ frame_time = 1.0 / 30.0;
+ }
+
+ double todo = particles->pre_process_time;
+
+ while (todo >= 0) {
+ _particles_process(particles, frame_time);
+ todo -= frame_time;
+ }
+ }
+
+ if (fixed_fps > 0) {
+ double frame_time;
+ double decr;
+ if (zero_time_scale) {
+ frame_time = 0.0;
+ decr = 1.0 / fixed_fps;
+ } else {
+ frame_time = 1.0 / fixed_fps;
+ decr = frame_time;
+ }
+ double delta = RSG::rasterizer->get_frame_delta_time();
+ if (delta > 0.1) { //avoid recursive stalls if fps goes below 10
+ delta = 0.1;
+ } else if (delta <= 0.0) { //unlikely but..
+ delta = 0.001;
+ }
+ double todo = particles->frame_remainder + delta;
+
+ while (todo >= frame_time) {
+ _particles_process(particles, frame_time);
+ todo -= decr;
+ }
+
+ particles->frame_remainder = todo;
+
+ } else {
+ if (zero_time_scale) {
+ _particles_process(particles, 0.0);
+ } else {
+ _particles_process(particles, RSG::rasterizer->get_frame_delta_time());
+ }
+ }
+
+ // Copy particles to instance buffer and pack Color/Custom.
+ // We don't have camera information here, so don't copy here if we need camera information for view depth or align mode.
+ if (particles->draw_order != RS::PARTICLES_DRAW_ORDER_VIEW_DEPTH && particles->transform_align != RS::PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD && particles->transform_align != RS::PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD_Y_TO_VELOCITY) {
+ _particles_update_instance_buffer(particles, Vector3(0.0, 0.0, 0.0), Vector3(0.0, 0.0, 0.0));
+
+ if (particles->draw_order == RS::PARTICLES_DRAW_ORDER_REVERSE_LIFETIME && particles->sort_buffer_filled) {
+ if (particles->mode == RS::ParticlesMode::PARTICLES_MODE_2D) {
+ _particles_reverse_lifetime_sort<ParticleInstanceData2D>(particles);
+ } else {
+ _particles_reverse_lifetime_sort<ParticleInstanceData3D>(particles);
+ }
+ }
+ }
+
+ SWAP(particles->front_instance_buffer, particles->back_instance_buffer);
+
+ // At the end of update, the back_buffer contains the most up-to-date-information to read from.
+
+ particles->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB);
+ }
+
+ glDisable(GL_RASTERIZER_DISCARD);
+}
+
+template <typename ParticleInstanceData>
+void ParticlesStorage::_particles_reverse_lifetime_sort(Particles *particles) {
+ glBindBuffer(GL_ARRAY_BUFFER, particles->sort_buffer);
+
+ ParticleInstanceData *particle_array;
+ uint32_t buffer_size = particles->amount * sizeof(ParticleInstanceData);
+#ifndef __EMSCRIPTEN__
+ particle_array = static_cast<ParticleInstanceData *>(glMapBufferRange(GL_ARRAY_BUFFER, 0, buffer_size, GL_MAP_READ_BIT | GL_MAP_WRITE_BIT));
+
+ ERR_FAIL_NULL(particle_array);
+#else
+ LocalVector<ParticleInstanceData> particle_vector;
+ particle_vector.resize(particles->amount);
+ particle_array = particle_vector.ptr();
+ glGetBufferSubData(GL_ARRAY_BUFFER, 0, buffer_size, particle_array);
+#endif
+
+ uint32_t lifetime_split = MIN(particles->amount * particles->sort_buffer_phase, particles->amount - 1);
+
+ for (uint32_t i = 0; i < lifetime_split / 2; i++) {
+ SWAP(particle_array[i], particle_array[lifetime_split - i]);
+ }
+
+ for (uint32_t i = 0; i < (particles->amount - lifetime_split) / 2; i++) {
+ SWAP(particle_array[lifetime_split + i + 1], particle_array[particles->amount - 1 - i]);
+ }
+
+#ifndef __EMSCRIPTEN__
+ glUnmapBuffer(GL_ARRAY_BUFFER);
+#else
+ glBufferSubData(GL_ARRAY_BUFFER, 0, buffer_size, particle_vector.ptr());
+#endif
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+}
+
+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 {
- return false;
+ 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);
+ ERR_FAIL_COND_V(!particles, false);
+ return !particles->emitting && particles->inactive;
}
-/* PARTICLES COLLISION */
+/* PARTICLES COLLISION API */
RID ParticlesStorage::particles_collision_allocate() {
- return RID();
+ return particles_collision_owner.allocate_rid();
}
-
void ParticlesStorage::particles_collision_initialize(RID p_rid) {
+ particles_collision_owner.initialize_rid(p_rid, ParticlesCollision());
}
void ParticlesStorage::particles_collision_free(RID p_rid) {
+ ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_rid);
+
+ if (particles_collision->heightfield_texture != 0) {
+ glDeleteTextures(1, &particles_collision->heightfield_texture);
+ particles_collision->heightfield_texture = 0;
+ glDeleteFramebuffers(1, &particles_collision->heightfield_fb);
+ particles_collision->heightfield_fb = 0;
+ }
+ particles_collision->dependency.deleted_notify(p_rid);
+ particles_collision_owner.free(p_rid);
+}
+
+GLuint ParticlesStorage::particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const {
+ ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
+ ERR_FAIL_COND_V(!particles_collision, 0);
+ ERR_FAIL_COND_V(particles_collision->type != RS::PARTICLES_COLLISION_TYPE_HEIGHTFIELD_COLLIDE, 0);
+
+ if (particles_collision->heightfield_texture == 0) {
+ //create
+ const int resolutions[RS::PARTICLES_COLLISION_HEIGHTFIELD_RESOLUTION_MAX] = { 256, 512, 1024, 2048, 4096, 8192 };
+ Size2i size;
+ if (particles_collision->extents.x > particles_collision->extents.z) {
+ size.x = resolutions[particles_collision->heightfield_resolution];
+ size.y = int32_t(particles_collision->extents.z / particles_collision->extents.x * size.x);
+ } else {
+ size.y = resolutions[particles_collision->heightfield_resolution];
+ size.x = int32_t(particles_collision->extents.x / particles_collision->extents.z * size.y);
+ }
+
+ glGenTextures(1, &particles_collision->heightfield_texture);
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, particles_collision->heightfield_texture);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, size.x, size.y, 0, GL_DEPTH_COMPONENT, GL_FLOAT, nullptr);
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+
+ glGenFramebuffers(1, &particles_collision->heightfield_fb);
+ glBindFramebuffer(GL_FRAMEBUFFER, particles_collision->heightfield_fb);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, particles_collision->heightfield_texture, 0);
+#ifdef DEBUG_ENABLED
+ GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+ if (status != GL_FRAMEBUFFER_COMPLETE) {
+ WARN_PRINT("Could create heightmap texture status: " + GLES3::TextureStorage::get_singleton()->get_framebuffer_error(status));
+ }
+#endif
+ particles_collision->heightfield_fb_size = size;
+
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ }
+
+ return particles_collision->heightfield_fb;
}
void ParticlesStorage::particles_collision_set_collision_type(RID p_particles_collision, RS::ParticlesCollisionType p_type) {
+ ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
+ ERR_FAIL_COND(!particles_collision);
+
+ if (p_type == particles_collision->type) {
+ return;
+ }
+
+ if (particles_collision->heightfield_texture != 0) {
+ glDeleteTextures(1, &particles_collision->heightfield_texture);
+ particles_collision->heightfield_texture = 0;
+ glDeleteFramebuffers(1, &particles_collision->heightfield_fb);
+ particles_collision->heightfield_fb = 0;
+ }
+
+ particles_collision->type = p_type;
+ 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) {
+ ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
+ ERR_FAIL_COND(!particles_collision);
+ particles_collision->cull_mask = p_cull_mask;
}
void ParticlesStorage::particles_collision_set_sphere_radius(RID p_particles_collision, real_t p_radius) {
+ ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
+ ERR_FAIL_COND(!particles_collision);
+
+ particles_collision->radius = p_radius;
+ particles_collision->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB);
}
void ParticlesStorage::particles_collision_set_box_extents(RID p_particles_collision, const Vector3 &p_extents) {
+ ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
+ ERR_FAIL_COND(!particles_collision);
+
+ particles_collision->extents = p_extents;
+ particles_collision->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB);
}
void ParticlesStorage::particles_collision_set_attractor_strength(RID p_particles_collision, real_t p_strength) {
+ ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
+ ERR_FAIL_COND(!particles_collision);
+
+ particles_collision->attractor_strength = p_strength;
}
void ParticlesStorage::particles_collision_set_attractor_directionality(RID p_particles_collision, real_t p_directionality) {
+ ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
+ ERR_FAIL_COND(!particles_collision);
+
+ particles_collision->attractor_directionality = p_directionality;
}
void ParticlesStorage::particles_collision_set_attractor_attenuation(RID p_particles_collision, real_t p_curve) {
+ ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
+ ERR_FAIL_COND(!particles_collision);
+
+ particles_collision->attractor_attenuation = p_curve;
}
void ParticlesStorage::particles_collision_set_field_texture(RID p_particles_collision, RID p_texture) {
+ WARN_PRINT_ONCE("The OpenGL 3 renderer does not support SDF collisions in 3D particle shaders");
}
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(Dependency::DEPENDENCY_CHANGED_AABB);
}
void ParticlesStorage::particles_collision_set_height_field_resolution(RID p_particles_collision, RS::ParticlesCollisionHeightfieldResolution p_resolution) {
+ ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
+ ERR_FAIL_COND(!particles_collision);
+ ERR_FAIL_INDEX(p_resolution, RS::PARTICLES_COLLISION_HEIGHTFIELD_RESOLUTION_MAX);
+
+ if (particles_collision->heightfield_resolution == p_resolution) {
+ return;
+ }
+
+ particles_collision->heightfield_resolution = p_resolution;
+
+ if (particles_collision->heightfield_texture != 0) {
+ glDeleteTextures(1, &particles_collision->heightfield_texture);
+ particles_collision->heightfield_texture = 0;
+ glDeleteFramebuffers(1, &particles_collision->heightfield_fb);
+ particles_collision->heightfield_fb = 0;
+ }
}
AABB ParticlesStorage::particles_collision_get_aabb(RID p_particles_collision) const {
- return AABB();
+ ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
+ ERR_FAIL_COND_V(!particles_collision, AABB());
+
+ switch (particles_collision->type) {
+ case RS::PARTICLES_COLLISION_TYPE_SPHERE_ATTRACT:
+ case RS::PARTICLES_COLLISION_TYPE_SPHERE_COLLIDE: {
+ AABB aabb;
+ aabb.position = -Vector3(1, 1, 1) * particles_collision->radius;
+ aabb.size = Vector3(2, 2, 2) * particles_collision->radius;
+ return aabb;
+ }
+ default: {
+ AABB aabb;
+ aabb.position = -particles_collision->extents;
+ aabb.size = particles_collision->extents * 2;
+ return aabb;
+ }
+ }
+}
+
+Vector3 ParticlesStorage::particles_collision_get_extents(RID p_particles_collision) const {
+ const ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
+ ERR_FAIL_COND_V(!particles_collision, Vector3());
+ return particles_collision->extents;
}
bool ParticlesStorage::particles_collision_is_heightfield(RID p_particles_collision) const {
- return false;
+ const ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
+ ERR_FAIL_COND_V(!particles_collision, false);
+ return particles_collision->type == RS::PARTICLES_COLLISION_TYPE_HEIGHTFIELD_COLLIDE;
}
-RID ParticlesStorage::particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const {
- return RID();
+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) {
- return RID();
+ ParticlesCollisionInstance pci;
+ pci.collision = p_collision;
+ return particles_collision_instance_owner.make_rid(pci);
}
void ParticlesStorage::particles_collision_instance_free(RID p_rid) {
+ particles_collision_instance_owner.free(p_rid);
}
void ParticlesStorage::particles_collision_instance_set_transform(RID p_collision_instance, const Transform3D &p_transform) {
+ ParticlesCollisionInstance *pci = particles_collision_instance_owner.get_or_null(p_collision_instance);
+ ERR_FAIL_COND(!pci);
+ pci->transform = p_transform;
}
void ParticlesStorage::particles_collision_instance_set_active(RID p_collision_instance, bool p_active) {
+ ParticlesCollisionInstance *pci = particles_collision_instance_owner.get_or_null(p_collision_instance);
+ ERR_FAIL_COND(!pci);
+ pci->active = p_active;
}
#endif // GLES3_ENABLED
diff --git a/drivers/gles3/storage/particles_storage.h b/drivers/gles3/storage/particles_storage.h
index 84d1f94d8c..434718006e 100644
--- a/drivers/gles3/storage/particles_storage.h
+++ b/drivers/gles3/storage/particles_storage.h
@@ -33,25 +33,283 @@
#ifdef GLES3_ENABLED
+#include "../shaders/particles_copy.glsl.gen.h"
#include "core/templates/local_vector.h"
#include "core/templates/rid_owner.h"
#include "core/templates/self_list.h"
#include "servers/rendering/storage/particles_storage.h"
+#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 {
+enum ParticlesUniformLocation {
+ PARTICLES_FRAME_UNIFORM_LOCATION,
+ PARTICLES_GLOBALS_UNIFORM_LOCATION,
+ PARTICLES_MATERIAL_UNIFORM_LOCATION,
+};
+
class ParticlesStorage : public RendererParticlesStorage {
private:
static ParticlesStorage *singleton;
+ /* PARTICLES */
+
+ struct ParticleInstanceData3D {
+ float xform[12];
+ float color[2]; // Color and custom are packed together into one vec4;
+ float custom[2];
+ };
+
+ struct ParticleInstanceData2D {
+ float xform[8];
+ float color[2]; // Color and custom are packed together into one vec4;
+ float custom[2];
+ };
+
+ struct ParticlesViewSort {
+ Vector3 z_dir;
+ bool operator()(const ParticleInstanceData3D &p_a, const ParticleInstanceData3D &p_b) const {
+ return z_dir.dot(Vector3(p_a.xform[3], p_a.xform[7], p_a.xform[11])) < z_dir.dot(Vector3(p_b.xform[3], p_b.xform[7], p_b.xform[11]));
+ }
+ };
+
+ struct ParticlesFrameParams {
+ enum {
+ MAX_ATTRACTORS = 32,
+ MAX_COLLIDERS = 32,
+ MAX_3D_TEXTURES = 0 // GLES3 renderer doesn't support using 3D textures for flow field or collisions.
+ };
+
+ enum AttractorType {
+ ATTRACTOR_TYPE_SPHERE,
+ ATTRACTOR_TYPE_BOX,
+ ATTRACTOR_TYPE_VECTOR_FIELD,
+ };
+
+ struct Attractor {
+ float transform[16];
+ float extents[4]; // Extents or radius. w-channel is padding.
+
+ uint32_t type;
+ float strength;
+ float attenuation;
+ float directionality;
+ };
+
+ enum CollisionType {
+ COLLISION_TYPE_SPHERE,
+ COLLISION_TYPE_BOX,
+ COLLISION_TYPE_SDF,
+ COLLISION_TYPE_HEIGHT_FIELD,
+ COLLISION_TYPE_2D_SDF,
+
+ };
+
+ struct Collider {
+ float transform[16];
+ float extents[4]; // Extents or radius. w-channel is padding.
+
+ uint32_t type;
+ float scale;
+ float pad0;
+ float pad1;
+ };
+
+ uint32_t emitting;
+ uint32_t cycle;
+ float system_phase;
+ float prev_system_phase;
+
+ float explosiveness;
+ float randomness;
+ float time;
+ float delta;
+
+ float particle_size;
+ float pad0;
+ float pad1;
+ float pad2;
+
+ uint32_t random_seed;
+ uint32_t attractor_count;
+ uint32_t collider_count;
+ uint32_t frame;
+
+ float emission_transform[16];
+
+ Attractor attractors[MAX_ATTRACTORS];
+ Collider colliders[MAX_COLLIDERS];
+ };
+
+ 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;
+ GLuint sdf_collision_texture = 0;
+
+ 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;
+
+ GLuint frame_params_ubo = 0;
+
+ // We may process particles multiple times each frame (if they have a fixed FPS higher than the game FPS).
+ // Unfortunately, this means we can't just use a round-robin system of 3 buffers.
+ // To ensure the sort buffer is accurate, we copy the last frame instance buffer just before processing.
+
+ // Transform Feedback buffer and VAO for rendering.
+ // Each frame we render to this one.
+ GLuint front_vertex_array = 0; // Binds process buffer. Used for processing.
+ GLuint front_process_buffer = 0; // Transform + color + custom data + userdata + velocity + flags. Only needed for processing.
+ GLuint front_instance_buffer = 0; // Transform + color + custom data. In packed format needed for rendering.
+
+ // VAO for transform feedback, contains last frame's data.
+ // Read from this one for particles process and then copy to last frame buffer.
+ GLuint back_vertex_array = 0; // Binds process buffer. Used for processing.
+ GLuint back_process_buffer = 0; // Transform + color + custom data + userdata + velocity + flags. Only needed for processing.
+ GLuint back_instance_buffer = 0; // Transform + color + custom data. In packed format needed for rendering.
+
+ uint32_t instance_buffer_size_cache = 0;
+ uint32_t instance_buffer_stride_cache = 0;
+ uint32_t num_attrib_arrays_cache = 0;
+ uint32_t process_buffer_stride_cache = 0;
+
+ // Only ever copied to, holds last frame's instance data, then swaps with sort_buffer.
+ GLuint last_frame_buffer = 0;
+ bool last_frame_buffer_filled = false;
+ float last_frame_phase = 0.0;
+
+ // The frame-before-last's instance buffer.
+ // Use this to copy data back for sorting or computing AABB.
+ GLuint sort_buffer = 0;
+ bool sort_buffer_filled = false;
+ float sort_buffer_phase = 0.0;
+
+ uint32_t userdata_count = 0;
+
+ bool dirty = false;
+ Particles *update_list = nullptr;
+
+ double phase = 0.0;
+ double prev_phase = 0.0;
+ uint64_t prev_ticks = 0;
+ uint32_t random_seed = 0;
+
+ uint32_t cycle_number = 0;
+
+ double speed_scale = 1.0;
+
+ int fixed_fps = 30;
+ bool interpolate = true;
+ bool fractional_delta = false;
+ double frame_remainder = 0;
+ real_t collision_base_size = 0.01;
+
+ bool clear = true;
+
+ Transform3D emission_transform;
+
+ HashSet<RID> collisions;
+
+ Dependency dependency;
+
+ double trail_length = 1.0;
+ bool trails_enabled = false;
+
+ Particles() {
+ }
+ };
+
+ void _particles_process(Particles *p_particles, double p_delta);
+ void _particles_free_data(Particles *particles);
+ void _particles_update_buffers(Particles *particles);
+ void _particles_allocate_history_buffers(Particles *particles);
+ void _particles_update_instance_buffer(Particles *particles, const Vector3 &p_axis, const Vector3 &p_up_axis);
+
+ template <typename T>
+ void _particles_reverse_lifetime_sort(Particles *particles);
+
+ struct ParticlesShader {
+ RID default_shader;
+ RID default_material;
+ RID default_shader_version;
+
+ ParticlesCopyShaderGLES3 copy_shader;
+ RID copy_shader_version;
+ } particles_shader;
+
+ Particles *particle_update_list = nullptr;
+
+ mutable RID_Owner<Particles, true> particles_owner;
+
+ /* 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;
+ GLuint field_texture = 0;
+ GLuint heightfield_texture = 0;
+ GLuint heightfield_fb = 0;
+ 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;
+
public:
static ParticlesStorage *get_singleton();
ParticlesStorage();
virtual ~ParticlesStorage();
+ bool free(RID p_rid);
+
/* PARTICLES */
+ bool owns_particles(RID p_rid) { return particles_owner.owns(p_rid); }
+
virtual RID particles_allocate() override;
virtual void particles_initialize(RID p_rid) override;
virtual void particles_free(RID p_rid) override;
@@ -102,12 +360,51 @@ public:
virtual void particles_add_collision(RID p_particles, RID p_instance) override;
virtual void particles_remove_collision(RID p_particles, RID p_instance) override;
- virtual void particles_set_canvas_sdf_collision(RID p_particles, bool p_enable, const Transform2D &p_xform, const Rect2 &p_to_screen, RID p_texture) override;
+ void particles_set_canvas_sdf_collision(RID p_particles, bool p_enable, const Transform2D &p_xform, const Rect2 &p_to_screen, GLuint p_texture);
virtual void update_particles() override;
virtual bool particles_is_inactive(RID p_particles) const override;
+ _FORCE_INLINE_ RS::ParticlesMode particles_get_mode(RID p_particles) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND_V(!particles, RS::PARTICLES_MODE_2D);
+ return particles->mode;
+ }
+
+ _FORCE_INLINE_ uint32_t particles_get_amount(RID p_particles) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND_V(!particles, 0);
+
+ return particles->amount;
+ }
+
+ _FORCE_INLINE_ GLuint particles_get_gl_buffer(RID p_particles) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+
+ if ((particles->draw_order == RS::PARTICLES_DRAW_ORDER_VIEW_DEPTH || particles->draw_order == RS::PARTICLES_DRAW_ORDER_REVERSE_LIFETIME) && particles->sort_buffer_filled) {
+ return particles->sort_buffer;
+ }
+ return particles->back_instance_buffer;
+ }
+
+ _FORCE_INLINE_ bool particles_has_collision(RID p_particles) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND_V(!particles, 0);
+
+ return particles->has_collision_cache;
+ }
+
+ _FORCE_INLINE_ uint32_t particles_is_using_local_coords(RID p_particles) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND_V(!particles, false);
+
+ return particles->use_local_coords;
+ }
+
+ Dependency *particles_get_dependency(RID p_particles) const;
+
/* PARTICLES COLLISION */
+ bool owns_particles_collision(RID p_rid) { return particles_collision_owner.owns(p_rid); }
virtual RID particles_collision_allocate() override;
virtual void particles_collision_initialize(RID p_rid) override;
@@ -124,8 +421,22 @@ public:
virtual void particles_collision_height_field_update(RID p_particles_collision) override;
virtual void particles_collision_set_height_field_resolution(RID p_particles_collision, RS::ParticlesCollisionHeightfieldResolution p_resolution) override;
virtual AABB particles_collision_get_aabb(RID p_particles_collision) const override;
+ Vector3 particles_collision_get_extents(RID p_particles_collision) const;
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;
+ GLuint particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const;
+
+ _FORCE_INLINE_ Size2i particles_collision_get_heightfield_size(RID p_particles_collision) const {
+ ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
+ ERR_FAIL_COND_V(!particles_collision, Size2i());
+ ERR_FAIL_COND_V(particles_collision->type != RS::PARTICLES_COLLISION_TYPE_HEIGHTFIELD_COLLIDE, Size2i());
+
+ return particles_collision->heightfield_fb_size;
+ }
+
+ Dependency *particles_collision_get_dependency(RID p_particles) const;
+
+ /* PARTICLES COLLISION INSTANCE*/
+ 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;
virtual void particles_collision_instance_free(RID p_rid) override;
diff --git a/drivers/gles3/storage/texture_storage.cpp b/drivers/gles3/storage/texture_storage.cpp
index 51e22fe779..e6aa6a39c1 100644
--- a/drivers/gles3/storage/texture_storage.cpp
+++ b/drivers/gles3/storage/texture_storage.cpp
@@ -251,6 +251,8 @@ void TextureStorage::canvas_texture_free(RID p_rid) {
void TextureStorage::canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) {
CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture);
+ ERR_FAIL_NULL(ct);
+
switch (p_channel) {
case RS::CANVAS_TEXTURE_CHANNEL_DIFFUSE: {
ct->diffuse = p_texture;
@@ -266,6 +268,8 @@ void TextureStorage::canvas_texture_set_channel(RID p_canvas_texture, RS::Canvas
void TextureStorage::canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_specular_color, float p_shininess) {
CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture);
+ ERR_FAIL_NULL(ct);
+
ct->specular_color.r = p_specular_color.r;
ct->specular_color.g = p_specular_color.g;
ct->specular_color.b = p_specular_color.b;
@@ -274,11 +278,15 @@ void TextureStorage::canvas_texture_set_shading_parameters(RID p_canvas_texture,
void TextureStorage::canvas_texture_set_texture_filter(RID p_canvas_texture, RS::CanvasItemTextureFilter p_filter) {
CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture);
+ ERR_FAIL_NULL(ct);
+
ct->texture_filter = p_filter;
}
void TextureStorage::canvas_texture_set_texture_repeat(RID p_canvas_texture, RS::CanvasItemTextureRepeat p_repeat) {
CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture);
+ ERR_FAIL_NULL(ct);
+
ct->texture_repeat = p_repeat;
}
@@ -647,7 +655,7 @@ void TextureStorage::texture_2d_initialize(RID p_texture, const Ref<Image> &p_im
texture.height = p_image->get_height();
texture.alloc_width = texture.width;
texture.alloc_height = texture.height;
- texture.mipmaps = p_image->get_mipmap_count();
+ texture.mipmaps = p_image->get_mipmap_count() + 1;
texture.format = p_image->get_format();
texture.type = Texture::TYPE_2D;
texture.target = GL_TEXTURE_2D;
@@ -1598,9 +1606,9 @@ void TextureStorage::_update_render_target(RenderTarget *rt) {
return;
}
- if (rt->overridden.color.is_valid()) {
- texture->is_render_target = true;
- } else {
+ texture->is_render_target = true;
+ texture->render_target = rt;
+ if (rt->overridden.color.is_null()) {
texture->format = rt->image_format;
texture->real_format = rt->image_format;
texture->target = texture_target;
@@ -1686,34 +1694,54 @@ void TextureStorage::_clear_render_target(RenderTarget *rt) {
return;
}
+ // Dispose of the cached fbo's and the allocated textures
+ for (KeyValue<uint32_t, RenderTarget::RTOverridden::FBOCacheEntry> &E : rt->overridden.fbo_cache) {
+ glDeleteTextures(E.value.allocated_textures.size(), E.value.allocated_textures.ptr());
+ // Don't delete the current FBO, we'll do that a couple lines down.
+ if (E.value.fbo != rt->fbo) {
+ glDeleteFramebuffers(1, &E.value.fbo);
+ }
+ }
+ rt->overridden.fbo_cache.clear();
+
if (rt->fbo) {
glDeleteFramebuffers(1, &rt->fbo);
rt->fbo = 0;
}
if (rt->overridden.color.is_null()) {
- glDeleteTextures(1, &rt->color);
- rt->color = 0;
+ if (rt->texture.is_valid()) {
+ Texture *tex = get_texture(rt->texture);
+ tex->alloc_height = 0;
+ tex->alloc_width = 0;
+ tex->width = 0;
+ tex->height = 0;
+ tex->active = false;
+ tex->render_target = nullptr;
+ tex->is_render_target = false;
+ }
+ } else {
+ Texture *tex = get_texture(rt->overridden.color);
+ tex->render_target = nullptr;
+ tex->is_render_target = false;
}
- if (rt->overridden.depth.is_null()) {
- glDeleteTextures(1, &rt->depth);
- rt->depth = 0;
+ if (rt->overridden.color.is_valid()) {
+ rt->overridden.color = RID();
+ } else if (rt->color) {
+ glDeleteTextures(1, &rt->color);
}
+ rt->color = 0;
- if (rt->texture.is_valid()) {
- Texture *tex = get_texture(rt->texture);
- tex->alloc_height = 0;
- tex->alloc_width = 0;
- tex->width = 0;
- tex->height = 0;
- tex->active = false;
+ if (rt->overridden.depth.is_valid()) {
+ rt->overridden.depth = RID();
+ } else if (rt->depth) {
+ glDeleteTextures(1, &rt->depth);
}
+ rt->depth = 0;
- if (rt->overridden.color.is_valid()) {
- Texture *tex = get_texture(rt->overridden.color);
- tex->is_render_target = false;
- }
+ rt->overridden.velocity = RID();
+ rt->overridden.is_overridden = false;
if (rt->backbuffer_fbo != 0) {
glDeleteFramebuffers(1, &rt->backbuffer_fbo);
@@ -1724,18 +1752,9 @@ void TextureStorage::_clear_render_target(RenderTarget *rt) {
_render_target_clear_sdf(rt);
}
-void TextureStorage::_clear_render_target_overridden_fbo_cache(RenderTarget *rt) {
- // Dispose of the cached fbo's and the allocated textures
- for (KeyValue<uint32_t, RenderTarget::RTOverridden::FBOCacheEntry> &E : rt->overridden.fbo_cache) {
- glDeleteTextures(E.value.allocated_textures.size(), E.value.allocated_textures.ptr());
- glDeleteFramebuffers(1, &E.value.fbo);
- }
- rt->overridden.fbo_cache.clear();
-}
-
RID TextureStorage::render_target_create() {
RenderTarget render_target;
- //render_target.was_used = false;
+ render_target.used_in_frame = false;
render_target.clear_requested = false;
Texture t;
@@ -1751,7 +1770,6 @@ RID TextureStorage::render_target_create() {
void TextureStorage::render_target_free(RID p_rid) {
RenderTarget *rt = render_target_owner.get_or_null(p_rid);
_clear_render_target(rt);
- _clear_render_target_overridden_fbo_cache(rt);
Texture *t = get_texture(rt->texture);
if (t) {
@@ -1818,11 +1836,7 @@ void TextureStorage::render_target_set_override(RID p_render_target, RID p_color
if (p_color_texture.is_null() && p_depth_texture.is_null()) {
_clear_render_target(rt);
- rt->overridden.is_overridden = false;
- rt->overridden.color = RID();
- rt->overridden.depth = RID();
- rt->size = Size2i();
- _clear_render_target_overridden_fbo_cache(rt);
+ _update_render_target(rt);
return;
}
@@ -1841,6 +1855,8 @@ void TextureStorage::render_target_set_override(RID p_render_target, RID p_color
RBMap<uint32_t, RenderTarget::RTOverridden::FBOCacheEntry>::Element *cache;
if ((cache = rt->overridden.fbo_cache.find(hash_key)) != nullptr) {
rt->fbo = cache->get().fbo;
+ rt->color = cache->get().color;
+ rt->depth = cache->get().depth;
rt->size = cache->get().size;
rt->texture = p_color_texture;
return;
@@ -1850,6 +1866,8 @@ void TextureStorage::render_target_set_override(RID p_render_target, RID p_color
RenderTarget::RTOverridden::FBOCacheEntry new_entry;
new_entry.fbo = rt->fbo;
+ new_entry.color = rt->color;
+ new_entry.depth = rt->depth;
new_entry.size = rt->size;
// Keep track of any textures we had to allocate because they weren't overridden.
if (p_color_texture.is_null()) {
@@ -2215,7 +2233,11 @@ void TextureStorage::render_target_sdf_process(RID p_render_target) {
// Load
CanvasSdfShaderGLES3::ShaderVariant variant = shrink ? CanvasSdfShaderGLES3::MODE_LOAD_SHRINK : CanvasSdfShaderGLES3::MODE_LOAD;
- sdf_shader.shader.version_bind_shader(sdf_shader.shader_version, variant);
+ bool success = sdf_shader.shader.version_bind_shader(sdf_shader.shader_version, variant);
+ if (!success) {
+ return;
+ }
+
sdf_shader.shader.version_set_uniform(CanvasSdfShaderGLES3::BASE_SIZE, r.size, sdf_shader.shader_version, variant);
sdf_shader.shader.version_set_uniform(CanvasSdfShaderGLES3::SIZE, size, sdf_shader.shader_version, variant);
sdf_shader.shader.version_set_uniform(CanvasSdfShaderGLES3::STRIDE, 0, sdf_shader.shader_version, variant);
@@ -2236,7 +2258,11 @@ void TextureStorage::render_target_sdf_process(RID p_render_target) {
int stride = nearest_power_of_2_templated(MAX(size.width, size.height) / 2);
variant = CanvasSdfShaderGLES3::MODE_PROCESS;
- sdf_shader.shader.version_bind_shader(sdf_shader.shader_version, variant);
+ success = sdf_shader.shader.version_bind_shader(sdf_shader.shader_version, variant);
+ if (!success) {
+ return;
+ }
+
sdf_shader.shader.version_set_uniform(CanvasSdfShaderGLES3::BASE_SIZE, r.size, sdf_shader.shader_version, variant);
sdf_shader.shader.version_set_uniform(CanvasSdfShaderGLES3::SIZE, size, sdf_shader.shader_version, variant);
sdf_shader.shader.version_set_uniform(CanvasSdfShaderGLES3::STRIDE, stride, sdf_shader.shader_version, variant);
@@ -2260,7 +2286,11 @@ void TextureStorage::render_target_sdf_process(RID p_render_target) {
// Store
variant = shrink ? CanvasSdfShaderGLES3::MODE_STORE_SHRINK : CanvasSdfShaderGLES3::MODE_STORE;
- sdf_shader.shader.version_bind_shader(sdf_shader.shader_version, variant);
+ success = sdf_shader.shader.version_bind_shader(sdf_shader.shader_version, variant);
+ if (!success) {
+ return;
+ }
+
sdf_shader.shader.version_set_uniform(CanvasSdfShaderGLES3::BASE_SIZE, r.size, sdf_shader.shader_version, variant);
sdf_shader.shader.version_set_uniform(CanvasSdfShaderGLES3::SIZE, size, sdf_shader.shader_version, variant);
sdf_shader.shader.version_set_uniform(CanvasSdfShaderGLES3::STRIDE, stride, sdf_shader.shader_version, variant);
diff --git a/drivers/gles3/storage/texture_storage.h b/drivers/gles3/storage/texture_storage.h
index 7714e72f62..169c50638d 100644
--- a/drivers/gles3/storage/texture_storage.h
+++ b/drivers/gles3/storage/texture_storage.h
@@ -129,7 +129,7 @@ struct Texture {
bool is_external = false;
bool is_render_target = false;
- RID proxy_to = RID();
+ RID proxy_to;
Vector<RID> proxies;
String path;
@@ -344,6 +344,8 @@ struct RenderTarget {
struct FBOCacheEntry {
GLuint fbo;
+ GLuint color;
+ GLuint depth;
Size2i size;
Vector<GLuint> allocated_textures;
};
@@ -412,7 +414,6 @@ private:
mutable RID_Owner<RenderTarget> render_target_owner;
void _clear_render_target(RenderTarget *rt);
- void _clear_render_target_overridden_fbo_cache(RenderTarget *rt);
void _update_render_target(RenderTarget *rt);
void _create_render_target_backbuffer(RenderTarget *rt);
void _render_target_allocate_sdf(RenderTarget *rt);
diff --git a/drivers/gles3/storage/utilities.cpp b/drivers/gles3/storage/utilities.cpp
index 8e7e218bb9..02a110e3e5 100644
--- a/drivers/gles3/storage/utilities.cpp
+++ b/drivers/gles3/storage/utilities.cpp
@@ -108,6 +108,10 @@ RS::InstanceType Utilities::get_base_type(RID p_rid) const {
return RS::INSTANCE_LIGHT;
} else if (GLES3::LightStorage::get_singleton()->owns_lightmap(p_rid)) {
return RS::INSTANCE_LIGHTMAP;
+ } else if (GLES3::ParticlesStorage::get_singleton()->owns_particles(p_rid)) {
+ return RS::INSTANCE_PARTICLES;
+ } else if (GLES3::ParticlesStorage::get_singleton()->owns_particles_collision(p_rid)) {
+ return RS::INSTANCE_PARTICLES_COLLISION;
}
return RS::INSTANCE_NONE;
}
@@ -143,53 +147,21 @@ bool Utilities::free(RID p_rid) {
} else if (GLES3::LightStorage::get_singleton()->owns_lightmap(p_rid)) {
GLES3::LightStorage::get_singleton()->lightmap_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);
-
+ } else if (GLES3::ParticlesStorage::get_singleton()->owns_particles(p_rid)) {
+ GLES3::ParticlesStorage::get_singleton()->particles_free(p_rid);
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);
+ } else if (GLES3::ParticlesStorage::get_singleton()->owns_particles_collision(p_rid)) {
+ GLES3::ParticlesStorage::get_singleton()->particles_collision_free(p_rid);
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);
-
+ } else if (GLES3::ParticlesStorage::get_singleton()->owns_particles_collision_instance(p_rid)) {
+ GLES3::ParticlesStorage::get_singleton()->particles_collision_instance_free(p_rid);
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);
-
+ } else if (GLES3::MeshStorage::get_singleton()->owns_skeleton(p_rid)) {
+ GLES3::MeshStorage::get_singleton()->skeleton_free(p_rid);
return true;
+ } else {
+ return false;
}
- */
}
/* DEPENDENCIES */
@@ -207,6 +179,12 @@ void Utilities::base_update_dependency(RID p_base, DependencyTracker *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);
+ } 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);
}
}
@@ -306,7 +284,7 @@ String Utilities::get_captured_timestamp_name(uint32_t p_index) const {
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_skeletons();
MeshStorage::get_singleton()->_update_dirty_multimeshes();
TextureStorage::get_singleton()->update_texture_atlas();
}
diff --git a/drivers/register_driver_types.cpp b/drivers/register_driver_types.cpp
index 53a7f7aa4f..8362abefc9 100644
--- a/drivers/register_driver_types.cpp
+++ b/drivers/register_driver_types.cpp
@@ -30,7 +30,7 @@
#include "register_driver_types.h"
-#include "core/extension/native_extension_manager.h"
+#include "core/extension/gdextension_manager.h"
#include "drivers/png/image_loader_png.h"
#include "drivers/png/resource_saver_png.h"
diff --git a/drivers/unix/os_unix.cpp b/drivers/unix/os_unix.cpp
index 161706489f..711fd7b962 100644
--- a/drivers/unix/os_unix.cpp
+++ b/drivers/unix/os_unix.cpp
@@ -152,12 +152,10 @@ Vector<String> OS_Unix::get_video_adapter_driver_info() const {
String OS_Unix::get_stdin_string(bool p_block) {
if (p_block) {
char buff[1024];
- String ret = stdin_buf + fgets(buff, 1024, stdin);
- stdin_buf = "";
- return ret;
+ return String::utf8(fgets(buff, 1024, stdin));
}
- return "";
+ return String();
}
Error OS_Unix::get_entropy(uint8_t *r_buffer, int p_bytes) {
@@ -565,7 +563,7 @@ String OS_Unix::get_executable_path() const {
WARN_PRINT("MAXPATHLEN is too small");
}
- String path(resolved_path);
+ String path = String::utf8(resolved_path);
delete[] resolved_path;
return path;
diff --git a/drivers/unix/os_unix.h b/drivers/unix/os_unix.h
index ce06a52a95..68d2dd0042 100644
--- a/drivers/unix/os_unix.h
+++ b/drivers/unix/os_unix.h
@@ -46,8 +46,6 @@ protected:
virtual void finalize_core() override;
- String stdin_buf;
-
public:
OS_Unix();
diff --git a/drivers/vulkan/rendering_device_vulkan.cpp b/drivers/vulkan/rendering_device_vulkan.cpp
index 0ff4ca31e6..b982ab3e40 100644
--- a/drivers/vulkan/rendering_device_vulkan.cpp
+++ b/drivers/vulkan/rendering_device_vulkan.cpp
@@ -40,14 +40,13 @@
#include "drivers/vulkan/vulkan_context.h"
#include "thirdparty/misc/smolv.h"
-#include "thirdparty/spirv-reflect/spirv_reflect.h"
//#define FORCE_FULL_BARRIER
static const uint32_t SMALL_ALLOCATION_MAX_SIZE = 4096;
// Get the Vulkan object information and possible stage access types (bitwise OR'd with incoming values).
-RenderingDeviceVulkan::Buffer *RenderingDeviceVulkan::_get_buffer_from_owner(RID p_buffer, VkPipelineStageFlags &r_stage_mask, VkAccessFlags &r_access_mask, uint32_t p_post_barrier) {
+RenderingDeviceVulkan::Buffer *RenderingDeviceVulkan::_get_buffer_from_owner(RID p_buffer, VkPipelineStageFlags &r_stage_mask, VkAccessFlags &r_access_mask, BitField<BarrierMask> p_post_barrier) {
Buffer *buffer = nullptr;
if (vertex_buffer_owner.owns(p_buffer)) {
buffer = vertex_buffer_owner.get_or_null(p_buffer);
@@ -55,11 +54,11 @@ RenderingDeviceVulkan::Buffer *RenderingDeviceVulkan::_get_buffer_from_owner(RID
r_stage_mask |= VK_PIPELINE_STAGE_VERTEX_INPUT_BIT;
r_access_mask |= VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT;
if (buffer->usage & VK_BUFFER_USAGE_STORAGE_BUFFER_BIT) {
- if (p_post_barrier & BARRIER_MASK_RASTER) {
+ if (p_post_barrier.has_flag(BARRIER_MASK_RASTER)) {
r_access_mask |= VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
r_stage_mask |= VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
}
- if (p_post_barrier & BARRIER_MASK_COMPUTE) {
+ if (p_post_barrier.has_flag(BARRIER_MASK_COMPUTE)) {
r_access_mask |= VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
r_stage_mask |= VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
}
@@ -69,20 +68,20 @@ RenderingDeviceVulkan::Buffer *RenderingDeviceVulkan::_get_buffer_from_owner(RID
r_access_mask |= VK_ACCESS_INDEX_READ_BIT;
buffer = index_buffer_owner.get_or_null(p_buffer);
} else if (uniform_buffer_owner.owns(p_buffer)) {
- if (p_post_barrier & BARRIER_MASK_RASTER) {
+ if (p_post_barrier.has_flag(BARRIER_MASK_RASTER)) {
r_stage_mask |= VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
}
- if (p_post_barrier & BARRIER_MASK_COMPUTE) {
+ if (p_post_barrier.has_flag(BARRIER_MASK_COMPUTE)) {
r_stage_mask |= VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
}
r_access_mask |= VK_ACCESS_UNIFORM_READ_BIT;
buffer = uniform_buffer_owner.get_or_null(p_buffer);
} else if (texture_buffer_owner.owns(p_buffer)) {
- if (p_post_barrier & BARRIER_MASK_RASTER) {
+ if (p_post_barrier.has_flag(BARRIER_MASK_RASTER)) {
r_stage_mask |= VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
r_access_mask |= VK_ACCESS_SHADER_READ_BIT;
}
- if (p_post_barrier & BARRIER_MASK_COMPUTE) {
+ if (p_post_barrier.has_flag(BARRIER_MASK_COMPUTE)) {
r_stage_mask |= VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
r_access_mask |= VK_ACCESS_SHADER_READ_BIT;
}
@@ -90,11 +89,11 @@ RenderingDeviceVulkan::Buffer *RenderingDeviceVulkan::_get_buffer_from_owner(RID
buffer = &texture_buffer_owner.get_or_null(p_buffer)->buffer;
} else if (storage_buffer_owner.owns(p_buffer)) {
buffer = storage_buffer_owner.get_or_null(p_buffer);
- if (p_post_barrier & BARRIER_MASK_RASTER) {
+ if (p_post_barrier.has_flag(BARRIER_MASK_RASTER)) {
r_stage_mask |= VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
r_access_mask |= VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
}
- if (p_post_barrier & BARRIER_MASK_COMPUTE) {
+ if (p_post_barrier.has_flag(BARRIER_MASK_COMPUTE)) {
r_stage_mask |= VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
r_access_mask |= VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
}
@@ -996,8 +995,11 @@ void RenderingDeviceVulkan::get_compressed_image_format_block_dimensions(DataFor
case DATA_FORMAT_EAC_R11G11_UNORM_BLOCK:
case DATA_FORMAT_EAC_R11G11_SNORM_BLOCK:
case DATA_FORMAT_ASTC_4x4_UNORM_BLOCK: // Again, not sure about astc.
- case DATA_FORMAT_ASTC_4x4_SRGB_BLOCK:
- case DATA_FORMAT_ASTC_5x4_UNORM_BLOCK:
+ case DATA_FORMAT_ASTC_4x4_SRGB_BLOCK: {
+ r_w = 4;
+ r_h = 4;
+ } break;
+ case DATA_FORMAT_ASTC_5x4_UNORM_BLOCK: // Unsupported
case DATA_FORMAT_ASTC_5x4_SRGB_BLOCK:
case DATA_FORMAT_ASTC_5x5_UNORM_BLOCK:
case DATA_FORMAT_ASTC_5x5_SRGB_BLOCK:
@@ -1008,10 +1010,16 @@ void RenderingDeviceVulkan::get_compressed_image_format_block_dimensions(DataFor
case DATA_FORMAT_ASTC_8x5_UNORM_BLOCK:
case DATA_FORMAT_ASTC_8x5_SRGB_BLOCK:
case DATA_FORMAT_ASTC_8x6_UNORM_BLOCK:
- case DATA_FORMAT_ASTC_8x6_SRGB_BLOCK:
+ case DATA_FORMAT_ASTC_8x6_SRGB_BLOCK: {
+ r_w = 4;
+ r_h = 4;
+ } break;
case DATA_FORMAT_ASTC_8x8_UNORM_BLOCK:
- case DATA_FORMAT_ASTC_8x8_SRGB_BLOCK:
- case DATA_FORMAT_ASTC_10x5_UNORM_BLOCK:
+ case DATA_FORMAT_ASTC_8x8_SRGB_BLOCK: {
+ r_w = 8;
+ r_h = 8;
+ } break;
+ case DATA_FORMAT_ASTC_10x5_UNORM_BLOCK: // Unsupported
case DATA_FORMAT_ASTC_10x5_SRGB_BLOCK:
case DATA_FORMAT_ASTC_10x6_UNORM_BLOCK:
case DATA_FORMAT_ASTC_10x6_SRGB_BLOCK:
@@ -1101,7 +1109,7 @@ uint32_t RenderingDeviceVulkan::get_compressed_image_format_block_byte_size(Data
case DATA_FORMAT_ASTC_12x10_SRGB_BLOCK:
case DATA_FORMAT_ASTC_12x12_UNORM_BLOCK:
case DATA_FORMAT_ASTC_12x12_SRGB_BLOCK:
- return 8; // Wrong.
+ return 16;
default: {
}
}
@@ -1123,6 +1131,10 @@ uint32_t RenderingDeviceVulkan::get_compressed_image_format_pixel_rshift(DataFor
case DATA_FORMAT_EAC_R11_UNORM_BLOCK:
case DATA_FORMAT_EAC_R11_SNORM_BLOCK:
return 1;
+ case DATA_FORMAT_ASTC_8x8_SRGB_BLOCK:
+ case DATA_FORMAT_ASTC_8x8_UNORM_BLOCK: {
+ return 2;
+ }
default: {
}
}
@@ -1579,12 +1591,12 @@ Error RenderingDeviceVulkan::_buffer_update(Buffer *p_buffer, size_t p_offset, c
return OK;
}
-void RenderingDeviceVulkan::_memory_barrier(VkPipelineStageFlags p_src_stage_mask, VkPipelineStageFlags p_dst_stage_mask, VkAccessFlags p_src_access, VkAccessFlags p_dst_sccess, bool p_sync_with_draw) {
+void RenderingDeviceVulkan::_memory_barrier(VkPipelineStageFlags p_src_stage_mask, VkPipelineStageFlags p_dst_stage_mask, VkAccessFlags p_src_access, VkAccessFlags p_dst_access, bool p_sync_with_draw) {
VkMemoryBarrier mem_barrier;
mem_barrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
mem_barrier.pNext = nullptr;
mem_barrier.srcAccessMask = p_src_access;
- mem_barrier.dstAccessMask = p_dst_sccess;
+ mem_barrier.dstAccessMask = p_dst_access;
if (p_src_stage_mask == 0 || p_dst_stage_mask == 0) {
return; // No barrier, since this is invalid.
@@ -1628,14 +1640,14 @@ void RenderingDeviceVulkan::_full_barrier(bool p_sync_with_draw) {
p_sync_with_draw);
}
-void RenderingDeviceVulkan::_buffer_memory_barrier(VkBuffer buffer, uint64_t p_from, uint64_t p_size, VkPipelineStageFlags p_src_stage_mask, VkPipelineStageFlags p_dst_stage_mask, VkAccessFlags p_src_access, VkAccessFlags p_dst_sccess, bool p_sync_with_draw) {
+void RenderingDeviceVulkan::_buffer_memory_barrier(VkBuffer buffer, uint64_t p_from, uint64_t p_size, VkPipelineStageFlags p_src_stage_mask, VkPipelineStageFlags p_dst_stage_mask, VkAccessFlags p_src_access, VkAccessFlags p_dst_access, bool p_sync_with_draw) {
VkBufferMemoryBarrier buffer_mem_barrier;
buffer_mem_barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
buffer_mem_barrier.pNext = nullptr;
buffer_mem_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
buffer_mem_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
buffer_mem_barrier.srcAccessMask = p_src_access;
- buffer_mem_barrier.dstAccessMask = p_dst_sccess;
+ buffer_mem_barrier.dstAccessMask = p_dst_access;
buffer_mem_barrier.buffer = buffer;
buffer_mem_barrier.offset = p_from;
buffer_mem_barrier.size = p_size;
@@ -2009,7 +2021,7 @@ RID RenderingDeviceVulkan::texture_create(const TextureFormat &p_format, const T
if (p_data.size()) {
for (uint32_t i = 0; i < image_create_info.arrayLayers; i++) {
- _texture_update(id, i, p_data[i], RD::BARRIER_MASK_ALL, true);
+ _texture_update(id, i, p_data[i], RD::BARRIER_MASK_ALL_BARRIERS, true);
}
}
return id;
@@ -2414,7 +2426,7 @@ RID RenderingDeviceVulkan::texture_create_shared_from_slice(const TextureView &p
return id;
}
-Error RenderingDeviceVulkan::texture_update(RID p_texture, uint32_t p_layer, const Vector<uint8_t> &p_data, uint32_t p_post_barrier) {
+Error RenderingDeviceVulkan::texture_update(RID p_texture, uint32_t p_layer, const Vector<uint8_t> &p_data, BitField<BarrierMask> p_post_barrier) {
return _texture_update(p_texture, p_layer, p_data, p_post_barrier, false);
}
@@ -2434,7 +2446,7 @@ static _ALWAYS_INLINE_ void _copy_region(uint8_t const *__restrict p_src, uint8_
}
}
-Error RenderingDeviceVulkan::_texture_update(RID p_texture, uint32_t p_layer, const Vector<uint8_t> &p_data, uint32_t p_post_barrier, bool p_use_setup_queue) {
+Error RenderingDeviceVulkan::_texture_update(RID p_texture, uint32_t p_layer, const Vector<uint8_t> &p_data, BitField<BarrierMask> p_post_barrier, bool p_use_setup_queue) {
_THREAD_SAFE_METHOD_
ERR_FAIL_COND_V_MSG((draw_list || compute_list) && !p_use_setup_queue, ERR_INVALID_PARAMETER,
@@ -2608,15 +2620,15 @@ Error RenderingDeviceVulkan::_texture_update(RID p_texture, uint32_t p_layer, co
{
uint32_t barrier_flags = 0;
uint32_t access_flags = 0;
- if (p_post_barrier & BARRIER_MASK_COMPUTE) {
+ if (p_post_barrier.has_flag(BARRIER_MASK_COMPUTE)) {
barrier_flags |= VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
access_flags |= VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
}
- if (p_post_barrier & BARRIER_MASK_RASTER) {
+ if (p_post_barrier.has_flag(BARRIER_MASK_RASTER)) {
barrier_flags |= VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
access_flags |= VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
}
- if (p_post_barrier & BARRIER_MASK_TRANSFER) {
+ if (p_post_barrier.has_flag(BARRIER_MASK_TRANSFER)) {
barrier_flags |= VK_PIPELINE_STAGE_TRANSFER_BIT;
access_flags |= VK_ACCESS_TRANSFER_WRITE_BIT;
}
@@ -2869,7 +2881,7 @@ Size2i RenderingDeviceVulkan::texture_size(RID p_texture) {
return Size2i(tex->width, tex->height);
}
-Error RenderingDeviceVulkan::texture_copy(RID p_from_texture, RID p_to_texture, const Vector3 &p_from, const Vector3 &p_to, const Vector3 &p_size, uint32_t p_src_mipmap, uint32_t p_dst_mipmap, uint32_t p_src_layer, uint32_t p_dst_layer, uint32_t p_post_barrier) {
+Error RenderingDeviceVulkan::texture_copy(RID p_from_texture, RID p_to_texture, const Vector3 &p_from, const Vector3 &p_to, const Vector3 &p_size, uint32_t p_src_mipmap, uint32_t p_dst_mipmap, uint32_t p_src_layer, uint32_t p_dst_layer, BitField<BarrierMask> p_post_barrier) {
_THREAD_SAFE_METHOD_
Texture *src_tex = texture_owner.get_or_null(p_from_texture);
@@ -2994,15 +3006,15 @@ Error RenderingDeviceVulkan::texture_copy(RID p_from_texture, RID p_to_texture,
uint32_t barrier_flags = 0;
uint32_t access_flags = 0;
- if (p_post_barrier & BARRIER_MASK_COMPUTE) {
+ if (p_post_barrier.has_flag(BARRIER_MASK_COMPUTE)) {
barrier_flags |= VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
access_flags |= VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
}
- if (p_post_barrier & BARRIER_MASK_RASTER) {
+ if (p_post_barrier.has_flag(BARRIER_MASK_RASTER)) {
barrier_flags |= VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
access_flags |= VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
}
- if (p_post_barrier & BARRIER_MASK_TRANSFER) {
+ if (p_post_barrier.has_flag(BARRIER_MASK_TRANSFER)) {
barrier_flags |= VK_PIPELINE_STAGE_TRANSFER_BIT;
access_flags |= VK_ACCESS_TRANSFER_WRITE_BIT;
}
@@ -3064,7 +3076,7 @@ Error RenderingDeviceVulkan::texture_copy(RID p_from_texture, RID p_to_texture,
return OK;
}
-Error RenderingDeviceVulkan::texture_resolve_multisample(RID p_from_texture, RID p_to_texture, uint32_t p_post_barrier) {
+Error RenderingDeviceVulkan::texture_resolve_multisample(RID p_from_texture, RID p_to_texture, BitField<BarrierMask> p_post_barrier) {
_THREAD_SAFE_METHOD_
Texture *src_tex = texture_owner.get_or_null(p_from_texture);
@@ -3172,15 +3184,15 @@ Error RenderingDeviceVulkan::texture_resolve_multisample(RID p_from_texture, RID
uint32_t barrier_flags = 0;
uint32_t access_flags = 0;
- if (p_post_barrier & BARRIER_MASK_COMPUTE) {
+ if (p_post_barrier.has_flag(BARRIER_MASK_COMPUTE)) {
barrier_flags |= VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
access_flags |= VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
}
- if (p_post_barrier & BARRIER_MASK_RASTER) {
+ if (p_post_barrier.has_flag(BARRIER_MASK_RASTER)) {
barrier_flags |= VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
access_flags |= VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
}
- if (p_post_barrier & BARRIER_MASK_TRANSFER) {
+ if (p_post_barrier.has_flag(BARRIER_MASK_TRANSFER)) {
barrier_flags |= VK_PIPELINE_STAGE_TRANSFER_BIT;
access_flags |= VK_ACCESS_TRANSFER_WRITE_BIT;
}
@@ -3235,7 +3247,7 @@ Error RenderingDeviceVulkan::texture_resolve_multisample(RID p_from_texture, RID
return OK;
}
-Error RenderingDeviceVulkan::texture_clear(RID p_texture, const Color &p_color, uint32_t p_base_mipmap, uint32_t p_mipmaps, uint32_t p_base_layer, uint32_t p_layers, uint32_t p_post_barrier) {
+Error RenderingDeviceVulkan::texture_clear(RID p_texture, const Color &p_color, uint32_t p_base_mipmap, uint32_t p_mipmaps, uint32_t p_base_layer, uint32_t p_layers, BitField<BarrierMask> p_post_barrier) {
_THREAD_SAFE_METHOD_
Texture *src_tex = texture_owner.get_or_null(p_texture);
@@ -3308,15 +3320,15 @@ Error RenderingDeviceVulkan::texture_clear(RID p_texture, const Color &p_color,
uint32_t barrier_flags = 0;
uint32_t access_flags = 0;
- if (p_post_barrier & BARRIER_MASK_COMPUTE) {
+ if (p_post_barrier.has_flag(BARRIER_MASK_COMPUTE)) {
barrier_flags |= VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
access_flags |= VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
}
- if (p_post_barrier & BARRIER_MASK_RASTER) {
+ if (p_post_barrier.has_flag(BARRIER_MASK_RASTER)) {
barrier_flags |= VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
access_flags |= VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
}
- if (p_post_barrier & BARRIER_MASK_TRANSFER) {
+ if (p_post_barrier.has_flag(BARRIER_MASK_TRANSFER)) {
barrier_flags |= VK_PIPELINE_STAGE_TRANSFER_BIT;
access_flags |= VK_ACCESS_TRANSFER_WRITE_BIT;
}
@@ -3355,7 +3367,7 @@ Error RenderingDeviceVulkan::texture_clear(RID p_texture, const Color &p_color,
return OK;
}
-bool RenderingDeviceVulkan::texture_is_format_supported_for_usage(DataFormat p_format, uint32_t p_usage) const {
+bool RenderingDeviceVulkan::texture_is_format_supported_for_usage(DataFormat p_format, BitField<RenderingDevice::TextureUsageBits> p_usage) const {
ERR_FAIL_INDEX_V(p_format, DATA_FORMAT_MAX, false);
_THREAD_SAFE_METHOD_
@@ -3365,34 +3377,34 @@ bool RenderingDeviceVulkan::texture_is_format_supported_for_usage(DataFormat p_f
vkGetPhysicalDeviceFormatProperties(context->get_physical_device(), vulkan_formats[p_format], &properties);
VkFormatFeatureFlags flags;
- if (p_usage & TEXTURE_USAGE_CPU_READ_BIT) {
+ if (p_usage.has_flag(TEXTURE_USAGE_CPU_READ_BIT)) {
flags = properties.linearTilingFeatures;
} else {
flags = properties.optimalTilingFeatures;
}
- if (p_usage & TEXTURE_USAGE_SAMPLING_BIT && !(flags & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT)) {
+ if (p_usage.has_flag(TEXTURE_USAGE_SAMPLING_BIT) && !(flags & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT)) {
return false;
}
- if (p_usage & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT && !(flags & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT)) {
+ if (p_usage.has_flag(TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) && !(flags & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT)) {
return false;
}
- if (p_usage & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT && !(flags & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)) {
+ if (p_usage.has_flag(TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) && !(flags & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)) {
return false;
}
- if (p_usage & TEXTURE_USAGE_STORAGE_BIT && !(flags & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT)) {
+ if (p_usage.has_flag(TEXTURE_USAGE_STORAGE_BIT) && !(flags & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT)) {
return false;
}
- if (p_usage & TEXTURE_USAGE_STORAGE_ATOMIC_BIT && !(flags & VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT)) {
+ if (p_usage.has_flag(TEXTURE_USAGE_STORAGE_ATOMIC_BIT) && !(flags & VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT)) {
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) {
+ if (p_usage.has_flag(TEXTURE_USAGE_VRS_ATTACHMENT_BIT) && p_format != DATA_FORMAT_R8_UINT) {
return false;
}
@@ -3826,7 +3838,7 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
vrs_reference.layout = VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR;
vrs_reference.aspectMask = VK_IMAGE_ASPECT_NONE;
- Size2i texel_size = context->get_vrs_capabilities().max_texel_size;
+ Size2i texel_size = context->get_vrs_capabilities().texel_size;
VkFragmentShadingRateAttachmentInfoKHR &vrs_attachment_info = vrs_attachment_info_array[i];
vrs_attachment_info.sType = VK_STRUCTURE_TYPE_FRAGMENT_SHADING_RATE_ATTACHMENT_INFO_KHR;
@@ -4378,7 +4390,7 @@ RenderingDevice::VertexFormatID RenderingDeviceVulkan::vertex_format_create(cons
return id;
}
-RID RenderingDeviceVulkan::vertex_array_create(uint32_t p_vertex_count, VertexFormatID p_vertex_format, const Vector<RID> &p_src_buffers) {
+RID RenderingDeviceVulkan::vertex_array_create(uint32_t p_vertex_count, VertexFormatID p_vertex_format, const Vector<RID> &p_src_buffers, const Vector<uint64_t> &p_offsets) {
_THREAD_SAFE_METHOD_
ERR_FAIL_COND_V(!vertex_formats.has(p_vertex_format), RID());
@@ -4392,6 +4404,13 @@ RID RenderingDeviceVulkan::vertex_array_create(uint32_t p_vertex_count, VertexFo
VertexArray vertex_array;
+ if (p_offsets.is_empty()) {
+ vertex_array.offsets.resize_zeroed(p_src_buffers.size());
+ } else {
+ ERR_FAIL_COND_V(p_offsets.size() != p_src_buffers.size(), RID());
+ vertex_array.offsets = p_offsets;
+ }
+
vertex_array.vertex_count = p_vertex_count;
vertex_array.description = p_vertex_format;
vertex_array.max_instances_allowed = 0xFFFFFFFF; // By default as many as you want.
@@ -4423,7 +4442,6 @@ RID RenderingDeviceVulkan::vertex_array_create(uint32_t p_vertex_count, VertexFo
}
vertex_array.buffers.push_back(buffer->buffer);
- vertex_array.offsets.push_back(0); // Offset unused, but passing anyway.
}
RID id = vertex_array_owner.make_rid(vertex_array);
@@ -4518,14 +4536,6 @@ RID RenderingDeviceVulkan::index_array_create(RID p_index_buffer, uint32_t p_ind
/**** SHADER ****/
/****************/
-static const char *shader_stage_names[RenderingDevice::SHADER_STAGE_MAX] = {
- "Vertex",
- "Fragment",
- "TesselationControl",
- "TesselationEvaluation",
- "Compute"
-};
-
static const char *shader_uniform_names[RenderingDevice::UNIFORM_TYPE_MAX] = {
"Sampler", "CombinedSampler", "Texture", "Image", "TextureBuffer", "SamplerTextureBuffer", "ImageBuffer", "UniformBuffer", "StorageBuffer", "InputAttachment"
};
@@ -4556,198 +4566,6 @@ String RenderingDeviceVulkan::_shader_uniform_debug(RID p_shader, int p_set) {
}
return ret;
}
-#if 0
-bool RenderingDeviceVulkan::_uniform_add_binding(Vector<Vector<VkDescriptorSetLayoutBinding> > &bindings, Vector<Vector<UniformInfo> > &uniform_infos, const glslang::TObjectReflection &reflection, RenderingDevice::ShaderStage p_stage, Shader::PushConstant &push_constant, String *r_error) {
- VkDescriptorSetLayoutBinding layout_binding;
- UniformInfo info;
-
- switch (reflection.getType()->getBasicType()) {
- case glslang::EbtSampler: {
- //print_line("DEBUG: IsSampler");
- if (reflection.getType()->getSampler().dim == glslang::EsdBuffer) {
- // Texture buffers.
- if (reflection.getType()->getSampler().isCombined()) {
- layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
- info.type = UNIFORM_TYPE_SAMPLER_WITH_TEXTURE_BUFFER;
- //print_line("DEBUG: SAMPLER: texel combined");
- } else if (reflection.getType()->getSampler().isTexture()) {
- layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
- info.type = UNIFORM_TYPE_TEXTURE_BUFFER;
- //print_line("DEBUG: SAMPLER: texel alone");
- } else if (reflection.getType()->getSampler().isImage()) {
- layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
- info.type = UNIFORM_TYPE_IMAGE_BUFFER;
- //print_line("DEBUG: SAMPLER: texel buffer");
- } else {
- if (r_error) {
- *r_error = "On shader stage '" + String(shader_stage_names[p_stage]) + "', uniform '" + reflection.name + "' is of unsupported buffer type.";
- }
- return false;
- }
- } else if (reflection.getType()->getSampler().isCombined()) {
- layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
- info.type = UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
- //print_line("DEBUG: SAMPLER: combined");
- } else if (reflection.getType()->getSampler().isPureSampler()) {
- layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER;
- info.type = UNIFORM_TYPE_SAMPLER;
- //print_line("DEBUG: SAMPLER: sampler");
- } else if (reflection.getType()->getSampler().isTexture()) {
- layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
- info.type = UNIFORM_TYPE_TEXTURE;
- //print_line("DEBUG: SAMPLER: image");
- } else if (reflection.getType()->getSampler().isImage()) {
- layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
- info.type = UNIFORM_TYPE_IMAGE;
- //print_line("DEBUG: SAMPLER: storage image");
- } else {
- //print_line("DEBUG: sampler unknown");
- if (r_error) {
- *r_error = "On shader stage '" + String(shader_stage_names[p_stage]) + "', uniform '" + reflection.name + "' is of unsupported sampler type.";
- }
- return false;
- }
-
- if (reflection.getType()->isArray()) {
- layout_binding.descriptorCount = reflection.getType()->getArraySizes()->getCumulativeSize();
- //print_line("DEBUG: array of size: " + itos(layout_binding.descriptorCount));
- } else {
- layout_binding.descriptorCount = 1;
- }
-
- info.length = layout_binding.descriptorCount;
-
- } break;
- /*case glslang::EbtStruct: {
- print_line("DEBUG: Struct");
-
- } break;*/
- case glslang::EbtBlock: {
- //print_line("DEBUG: Block");
- if (reflection.getType()->getQualifier().storage == glslang::EvqUniform) {
- if (reflection.getType()->getQualifier().layoutPushConstant) {
- uint32_t len = reflection.size;
- if (push_constant.push_constant_size != 0 && push_constant.push_constant_size != len) {
- *r_error = "On shader stage '" + String(shader_stage_names[p_stage]) + "', uniform '" + reflection.name + "' push constants for different stages should all be the same size.";
- return false;
- }
- push_constant.push_constant_size = len;
- push_constant.push_constants_vk_stage |= shader_stage_masks[p_stage];
- return true;
- }
- //print_line("DEBUG: Uniform buffer");
- layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
- info.type = UNIFORM_TYPE_UNIFORM_BUFFER;
- } else if (reflection.getType()->getQualifier().storage == glslang::EvqBuffer) {
- layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
- info.type = UNIFORM_TYPE_STORAGE_BUFFER;
- //print_line("DEBUG: Storage buffer");
- } else {
- if (r_error) {
- *r_error = "On shader stage '" + String(shader_stage_names[p_stage]) + "', uniform '" + reflection.name + "' is of unsupported block type: (" + itos(reflection.getType()->getQualifier().storage) + ").";
- }
- return false;
- }
-
- if (reflection.getType()->isArray()) {
- layout_binding.descriptorCount = reflection.getType()->getArraySizes()->getCumulativeSize();
- //print_line("DEBUG: array of size: " + itos(layout_binding.descriptorCount));
- } else {
- layout_binding.descriptorCount = 1;
- }
-
- info.length = reflection.size;
-
- } break;
- /*case glslang::EbtReference: {
- } break;*/
- /*case glslang::EbtAtomicUint: {
- } break;*/
- default: {
- if (reflection.getType()->getQualifier().hasOffset() || reflection.name.find(".") != std::string::npos) {
- // Member of uniform block?
- return true;
- }
-
- if (r_error) {
- *r_error = "On shader stage '" + String(shader_stage_names[p_stage]) + "', uniform '" + reflection.name + "' unsupported uniform type.";
- }
- return false;
- }
- }
-
- if (!reflection.getType()->getQualifier().hasBinding()) {
- if (r_error) {
- *r_error = "On shader stage '" + String(shader_stage_names[p_stage]) + "', uniform '" + reflection.name + "' lacks a binding number.";
- }
- return false;
- }
-
- uint32_t set = reflection.getType()->getQualifier().hasSet() ? reflection.getType()->getQualifier().layoutSet : 0;
-
- if (set >= MAX_UNIFORM_SETS) {
- if (r_error) {
- *r_error = "On shader stage '" + String(shader_stage_names[p_stage]) + "', uniform '" + reflection.name + "' uses a set (" + itos(set) + ") index larger than what is supported (" + itos(MAX_UNIFORM_SETS) + ").";
- }
- return false;
- }
-
- if (set >= limits.maxBoundDescriptorSets) {
- if (r_error) {
- *r_error = "On shader stage '" + String(shader_stage_names[p_stage]) + "', uniform '" + reflection.name + "' uses a set (" + itos(set) + ") index larger than what is supported by the hardware (" + itos(limits.maxBoundDescriptorSets) + ").";
- }
- return false;
- }
-
- uint32_t binding = reflection.getType()->getQualifier().layoutBinding;
-
- if (set < (uint32_t)bindings.size()) {
- // Check if this already exists.
- for (int i = 0; i < bindings[set].size(); i++) {
- if (bindings[set][i].binding == binding) {
- // Already exists, verify that it's the same type.
- if (bindings[set][i].descriptorType != layout_binding.descriptorType) {
- if (r_error) {
- *r_error = "On shader stage '" + String(shader_stage_names[p_stage]) + "', uniform '" + reflection.name + "' trying to re-use location for set=" + itos(set) + ", binding=" + itos(binding) + " with different uniform type.";
- }
- return false;
- }
-
- // Also, verify that it's the same size.
- if (bindings[set][i].descriptorCount != layout_binding.descriptorCount || uniform_infos[set][i].length != info.length) {
- if (r_error) {
- *r_error = "On shader stage '" + String(shader_stage_names[p_stage]) + "', uniform '" + reflection.name + "' trying to re-use location for set=" + itos(set) + ", binding=" + itos(binding) + " with different uniform size.";
- }
- return false;
- }
-
- // Just append stage mask and return.
- bindings.write[set].write[i].stageFlags |= shader_stage_masks[p_stage];
- uniform_infos.write[set].write[i].stages |= 1 << p_stage;
- return true;
- }
- }
- }
- layout_binding.binding = binding;
- layout_binding.stageFlags = shader_stage_masks[p_stage];
- layout_binding.pImmutableSamplers = nullptr; // No support for this yet.
-
- info.stages = 1 << p_stage;
- info.binding = binding;
-
- if (set >= (uint32_t)bindings.size()) {
- bindings.resize(set + 1);
- uniform_infos.resize(set + 1);
- }
-#if 0
- print_line("stage: " + String(shader_stage_names[p_stage]) + " set: " + itos(set) + " binding: " + itos(info.binding) + " type:" + shader_uniform_names[info.type] + " length: " + itos(info.length));
-#endif
- bindings.write[set].push_back(layout_binding);
- uniform_infos.write[set].push_back(info);
-
- return true;
-}
-#endif
// Version 1: initial.
// Version 2: Added shader name.
@@ -4780,346 +4598,68 @@ struct RenderingDeviceVulkanShaderBinarySpecializationConstant {
struct RenderingDeviceVulkanShaderBinaryData {
uint32_t vertex_input_mask;
- uint32_t fragment_outputs;
- uint32_t specialization_constant_count;
+ uint32_t fragment_output_mask;
+ uint32_t specialization_constants_count;
uint32_t is_compute;
uint32_t compute_local_size[3];
uint32_t set_count;
uint32_t push_constant_size;
- uint32_t push_constants_vk_stage;
+ uint32_t push_constant_vk_stages_mask;
uint32_t stage_count;
uint32_t shader_name_len;
};
Vector<uint8_t> RenderingDeviceVulkan::shader_compile_binary_from_spirv(const Vector<ShaderStageSPIRVData> &p_spirv, const String &p_shader_name) {
- RenderingDeviceVulkanShaderBinaryData binary_data;
- binary_data.vertex_input_mask = 0;
- binary_data.fragment_outputs = 0;
- binary_data.specialization_constant_count = 0;
- binary_data.is_compute = 0;
- binary_data.compute_local_size[0] = 0;
- binary_data.compute_local_size[1] = 0;
- binary_data.compute_local_size[2] = 0;
- binary_data.set_count = 0;
- binary_data.push_constant_size = 0;
- binary_data.push_constants_vk_stage = 0;
+ SpirvReflectionData spirv_data;
+ if (_reflect_spirv(p_spirv, spirv_data) != OK) {
+ return Vector<uint8_t>();
+ }
+ ERR_FAIL_COND_V_MSG((uint32_t)spirv_data.uniforms.size() > limits.maxBoundDescriptorSets, Vector<uint8_t>(),
+ "Number of uniform sets is larger than what is supported by the hardware (" + itos(limits.maxBoundDescriptorSets) + ").");
+
+ // Collect reflection data into binary data.
+ RenderingDeviceVulkanShaderBinaryData binary_data;
Vector<Vector<RenderingDeviceVulkanShaderBinaryDataBinding>> uniform_info; // Set bindings.
Vector<RenderingDeviceVulkanShaderBinarySpecializationConstant> specialization_constants;
-
- uint32_t stages_processed = 0;
-
- for (int i = 0; i < p_spirv.size(); i++) {
- if (p_spirv[i].shader_stage == SHADER_STAGE_COMPUTE) {
- binary_data.is_compute = true;
- ERR_FAIL_COND_V_MSG(p_spirv.size() != 1, Vector<uint8_t>(),
- "Compute shaders can only receive one stage, dedicated to compute.");
- }
- ERR_FAIL_COND_V_MSG(stages_processed & (1 << p_spirv[i].shader_stage), Vector<uint8_t>(),
- "Stage " + String(shader_stage_names[p_spirv[i].shader_stage]) + " submitted more than once.");
-
- {
- SpvReflectShaderModule module;
- const uint8_t *spirv = p_spirv[i].spir_v.ptr();
- SpvReflectResult result = spvReflectCreateShaderModule(p_spirv[i].spir_v.size(), spirv, &module);
- 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 parsing shader.");
-
- if (binary_data.is_compute) {
- binary_data.compute_local_size[0] = module.entry_points->local_size.x;
- binary_data.compute_local_size[1] = module.entry_points->local_size.y;
- binary_data.compute_local_size[2] = module.entry_points->local_size.z;
- }
- uint32_t binding_count = 0;
- result = spvReflectEnumerateDescriptorBindings(&module, &binding_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 descriptor bindings.");
-
- uint32_t stage = p_spirv[i].shader_stage;
-
- if (binding_count > 0) {
- // Parse bindings.
-
- Vector<SpvReflectDescriptorBinding *> bindings;
- bindings.resize(binding_count);
- result = spvReflectEnumerateDescriptorBindings(&module, &binding_count, bindings.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 descriptor bindings.");
-
- for (uint32_t j = 0; j < binding_count; j++) {
- const SpvReflectDescriptorBinding &binding = *bindings[j];
-
- RenderingDeviceVulkanShaderBinaryDataBinding info{};
-
- 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: {
- info.type = UNIFORM_TYPE_SAMPLER;
- need_array_dimensions = true;
- } break;
- case SPV_REFLECT_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: {
- info.type = UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
- need_array_dimensions = true;
- } break;
- case SPV_REFLECT_DESCRIPTOR_TYPE_SAMPLED_IMAGE: {
- info.type = UNIFORM_TYPE_TEXTURE;
- need_array_dimensions = true;
- } break;
- 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;
- need_array_dimensions = true;
- } break;
- 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;
- need_block_size = true;
- } break;
- 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.");
- continue;
- } break;
- case SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: {
- ERR_PRINT("Dynamic storage buffer not supported.");
- continue;
- } break;
- case SPV_REFLECT_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: {
- info.type = UNIFORM_TYPE_INPUT_ATTACHMENT;
- need_array_dimensions = true;
- } break;
- case SPV_REFLECT_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR: {
- ERR_PRINT("Acceleration structure not supported.");
- continue;
- } break;
- }
-
- if (need_array_dimensions) {
- if (binding.array.dims_count == 0) {
- info.length = 1;
- } else {
- for (uint32_t k = 0; k < binding.array.dims_count; k++) {
- if (k == 0) {
- info.length = binding.array.dims[0];
- } else {
- info.length *= binding.array.dims[k];
- }
- }
- }
-
- } else if (need_block_size) {
- info.length = binding.block.size;
- } else {
- info.length = 0;
- }
-
- 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;
- }
-
- info.binding = binding.binding;
- uint32_t set = binding.set;
-
- ERR_FAIL_COND_V_MSG(set >= MAX_UNIFORM_SETS, Vector<uint8_t>(),
- "On shader stage '" + String(shader_stage_names[stage]) + "', uniform '" + binding.name + "' uses a set (" + itos(set) + ") index larger than what is supported (" + itos(MAX_UNIFORM_SETS) + ").");
-
- ERR_FAIL_COND_V_MSG(set >= limits.maxBoundDescriptorSets, Vector<uint8_t>(),
- "On shader stage '" + String(shader_stage_names[stage]) + "', uniform '" + binding.name + "' uses a set (" + itos(set) + ") index larger than what is supported by the hardware (" + itos(limits.maxBoundDescriptorSets) + ").");
-
- if (set < (uint32_t)uniform_info.size()) {
- // Check if this already exists.
- bool exists = false;
- for (int k = 0; k < uniform_info[set].size(); k++) {
- if (uniform_info[set][k].binding == (uint32_t)info.binding) {
- // Already exists, verify that it's the same type.
- ERR_FAIL_COND_V_MSG(uniform_info[set][k].type != info.type, 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 type.");
-
- // Also, verify that it's the same size.
- 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;
- break;
- }
- }
-
- if (exists) {
- continue; // Merged.
- }
- }
-
- info.stages = 1 << stage;
-
- if (set >= (uint32_t)uniform_info.size()) {
- uniform_info.resize(set + 1);
- }
-
- uniform_info.write[set].push_back(info);
- }
- }
-
- {
- // Specialization constants.
-
- uint32_t sc_count = 0;
- result = spvReflectEnumerateSpecializationConstants(&module, &sc_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 specialization constants.");
-
- if (sc_count) {
- Vector<SpvReflectSpecializationConstant *> spec_constants;
- spec_constants.resize(sc_count);
-
- result = spvReflectEnumerateSpecializationConstants(&module, &sc_count, spec_constants.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 obtaining specialization constants.");
-
- for (uint32_t j = 0; j < sc_count; j++) {
- int32_t existing = -1;
- RenderingDeviceVulkanShaderBinarySpecializationConstant sconst{};
- SpvReflectSpecializationConstant *spc = spec_constants[j];
-
- sconst.constant_id = spc->constant_id;
- sconst.int_value = 0.0; // Clear previous value JIC.
- switch (spc->constant_type) {
- case SPV_REFLECT_SPECIALIZATION_CONSTANT_BOOL: {
- sconst.type = PIPELINE_SPECIALIZATION_CONSTANT_TYPE_BOOL;
- sconst.bool_value = spc->default_value.int_bool_value != 0;
- } break;
- case SPV_REFLECT_SPECIALIZATION_CONSTANT_INT: {
- sconst.type = PIPELINE_SPECIALIZATION_CONSTANT_TYPE_INT;
- sconst.int_value = spc->default_value.int_bool_value;
- } break;
- case SPV_REFLECT_SPECIALIZATION_CONSTANT_FLOAT: {
- sconst.type = PIPELINE_SPECIALIZATION_CONSTANT_TYPE_FLOAT;
- sconst.float_value = spc->default_value.float_value;
- } break;
- }
- sconst.stage_flags = 1 << p_spirv[i].shader_stage;
-
- for (int k = 0; k < specialization_constants.size(); k++) {
- if (specialization_constants[k].constant_id == sconst.constant_id) {
- ERR_FAIL_COND_V_MSG(specialization_constants[k].type != sconst.type, Vector<uint8_t>(), "More than one specialization constant used for id (" + itos(sconst.constant_id) + "), but their types differ.");
- ERR_FAIL_COND_V_MSG(specialization_constants[k].int_value != sconst.int_value, Vector<uint8_t>(), "More than one specialization constant used for id (" + itos(sconst.constant_id) + "), but their default values differ.");
- existing = k;
- break;
- }
- }
-
- if (existing > 0) {
- specialization_constants.write[existing].stage_flags |= sconst.stage_flags;
- } else {
- specialization_constants.push_back(sconst);
- }
- }
- }
- }
-
- if (stage == SHADER_STAGE_VERTEX) {
- uint32_t iv_count = 0;
- result = spvReflectEnumerateInputVariables(&module, &iv_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 input variables.");
-
- if (iv_count) {
- Vector<SpvReflectInterfaceVariable *> input_vars;
- input_vars.resize(iv_count);
-
- result = spvReflectEnumerateInputVariables(&module, &iv_count, input_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 obtaining input variables.");
-
- for (uint32_t j = 0; j < iv_count; j++) {
- if (input_vars[j] && input_vars[j]->decoration_flags == 0) { // Regular input.
- binary_data.vertex_input_mask |= (1 << uint32_t(input_vars[j]->location));
- }
- }
- }
- }
-
- if (stage == SHADER_STAGE_FRAGMENT) {
- uint32_t ov_count = 0;
- result = spvReflectEnumerateOutputVariables(&module, &ov_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 output variables.");
-
- if (ov_count) {
- Vector<SpvReflectInterfaceVariable *> output_vars;
- output_vars.resize(ov_count);
-
- result = spvReflectEnumerateOutputVariables(&module, &ov_count, output_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 obtaining output variables.");
-
- for (uint32_t j = 0; j < ov_count; j++) {
- const SpvReflectInterfaceVariable *refvar = output_vars[j];
- if (refvar != nullptr && refvar->built_in != SpvBuiltInFragDepth) {
- binary_data.fragment_outputs |= 1 << refvar->location;
- }
- }
- }
+ {
+ binary_data.vertex_input_mask = spirv_data.vertex_input_mask;
+ binary_data.fragment_output_mask = spirv_data.fragment_output_mask;
+ binary_data.specialization_constants_count = spirv_data.specialization_constants.size();
+ binary_data.is_compute = spirv_data.is_compute;
+ binary_data.compute_local_size[0] = spirv_data.compute_local_size[0];
+ binary_data.compute_local_size[1] = spirv_data.compute_local_size[1];
+ binary_data.compute_local_size[2] = spirv_data.compute_local_size[2];
+ binary_data.set_count = spirv_data.uniforms.size();
+ binary_data.push_constant_size = spirv_data.push_constant_size;
+ for (uint32_t i = 0; i < SHADER_STAGE_MAX; i++) {
+ if (spirv_data.push_constant_stages_mask.has_flag((ShaderStage)(1 << i))) {
+ binary_data.push_constant_vk_stages_mask |= shader_stage_masks[i];
}
+ }
- uint32_t pc_count = 0;
- result = spvReflectEnumeratePushConstantBlocks(&module, &pc_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 push constants.");
-
- if (pc_count) {
- ERR_FAIL_COND_V_MSG(pc_count > 1, Vector<uint8_t>(),
- "Reflection of SPIR-V shader stage '" + String(shader_stage_names[p_spirv[i].shader_stage]) + "': Only one push constant is supported, which should be the same across shader stages.");
-
- Vector<SpvReflectBlockVariable *> pconstants;
- pconstants.resize(pc_count);
- result = spvReflectEnumeratePushConstantBlocks(&module, &pc_count, pconstants.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 obtaining push constants.");
-#if 0
- if (pconstants[0] == nullptr) {
- Ref<FileAccess> f = FileAccess::open("res://popo.spv", FileAccess::WRITE);
- f->store_buffer((const uint8_t *)&SpirV[0], SpirV.size() * sizeof(uint32_t));
- }
-#endif
-
- ERR_FAIL_COND_V_MSG(binary_data.push_constant_size && binary_data.push_constant_size != pconstants[0]->size, Vector<uint8_t>(),
- "Reflection of SPIR-V shader stage '" + String(shader_stage_names[p_spirv[i].shader_stage]) + "': Push constant block must be the same across shader stages.");
-
- binary_data.push_constant_size = pconstants[0]->size;
- binary_data.push_constants_vk_stage |= shader_stage_masks[stage];
-
- //print_line("Stage: " + String(shader_stage_names[stage]) + " push constant of size=" + itos(push_constant.push_constant_size));
+ for (const Vector<SpirvReflectionData::Uniform> &spirv_set : spirv_data.uniforms) {
+ Vector<RenderingDeviceVulkanShaderBinaryDataBinding> set_bindings;
+ for (const SpirvReflectionData::Uniform &spirv_uniform : spirv_set) {
+ RenderingDeviceVulkanShaderBinaryDataBinding binding{};
+ binding.type = (uint32_t)spirv_uniform.type;
+ binding.binding = spirv_uniform.binding;
+ binding.stages = (uint32_t)spirv_uniform.stages_mask;
+ binding.length = spirv_uniform.length;
+ binding.writable = (uint32_t)spirv_uniform.writable;
+ set_bindings.push_back(binding);
}
-
- // Destroy the reflection data when no longer required.
- spvReflectDestroyShaderModule(&module);
+ uniform_info.push_back(set_bindings);
}
- stages_processed |= (1 << p_spirv[i].shader_stage);
+ for (const SpirvReflectionData::SpecializationConstant &spirv_sc : spirv_data.specialization_constants) {
+ RenderingDeviceVulkanShaderBinarySpecializationConstant spec_constant{};
+ spec_constant.type = (uint32_t)spirv_sc.type;
+ spec_constant.constant_id = spirv_sc.constant_id;
+ spec_constant.int_value = spirv_sc.int_value;
+ spec_constant.stage_flags = (uint32_t)spirv_sc.stages_mask;
+ specialization_constants.push_back(spec_constant);
+ }
}
Vector<Vector<uint8_t>> compressed_stages;
@@ -5161,7 +4701,7 @@ Vector<uint8_t> RenderingDeviceVulkan::shader_compile_binary_from_spirv(const Ve
stages_binary_size += s;
}
- binary_data.specialization_constant_count = specialization_constants.size();
+ binary_data.specialization_constants_count = specialization_constants.size();
binary_data.set_count = uniform_info.size();
binary_data.stage_count = p_spirv.size();
@@ -5267,12 +4807,12 @@ RID RenderingDeviceVulkan::shader_create_from_bytecode(const Vector<uint8_t> &p_
const RenderingDeviceVulkanShaderBinaryData &binary_data = *(reinterpret_cast<const RenderingDeviceVulkanShaderBinaryData *>(binptr + 12));
Shader::PushConstant push_constant;
- push_constant.push_constant_size = binary_data.push_constant_size;
- push_constant.push_constants_vk_stage = binary_data.push_constants_vk_stage;
+ push_constant.size = binary_data.push_constant_size;
+ push_constant.vk_stages_mask = binary_data.push_constant_vk_stages_mask;
uint32_t vertex_input_mask = binary_data.vertex_input_mask;
- uint32_t fragment_outputs = binary_data.fragment_outputs;
+ uint32_t fragment_output_mask = binary_data.fragment_output_mask;
bool is_compute = binary_data.is_compute;
@@ -5368,11 +4908,11 @@ RID RenderingDeviceVulkan::shader_create_from_bytecode(const Vector<uint8_t> &p_
read_offset += set_size;
}
- ERR_FAIL_COND_V(read_offset + binary_data.specialization_constant_count * sizeof(RenderingDeviceVulkanShaderBinarySpecializationConstant) >= binsize, RID());
+ ERR_FAIL_COND_V(read_offset + binary_data.specialization_constants_count * sizeof(RenderingDeviceVulkanShaderBinarySpecializationConstant) >= binsize, RID());
Vector<Shader::SpecializationConstant> specialization_constants;
- for (uint32_t i = 0; i < binary_data.specialization_constant_count; i++) {
+ for (uint32_t i = 0; i < binary_data.specialization_constants_count; i++) {
const RenderingDeviceVulkanShaderBinarySpecializationConstant &src_sc = *(reinterpret_cast<const RenderingDeviceVulkanShaderBinarySpecializationConstant *>(binptr + read_offset));
Shader::SpecializationConstant sc;
sc.constant.int_value = src_sc.int_value;
@@ -5438,7 +4978,7 @@ RID RenderingDeviceVulkan::shader_create_from_bytecode(const Vector<uint8_t> &p_
Shader shader;
shader.vertex_input_mask = vertex_input_mask;
- shader.fragment_output_mask = fragment_outputs;
+ shader.fragment_output_mask = fragment_output_mask;
shader.push_constant = push_constant;
shader.is_compute = is_compute;
shader.compute_local_size[0] = compute_local_size[0];
@@ -5468,19 +5008,11 @@ RID RenderingDeviceVulkan::shader_create_from_bytecode(const Vector<uint8_t> &p_
break;
}
- const VkShaderStageFlagBits shader_stage_bits[SHADER_STAGE_MAX] = {
- VK_SHADER_STAGE_VERTEX_BIT,
- VK_SHADER_STAGE_FRAGMENT_BIT,
- VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
- VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
- VK_SHADER_STAGE_COMPUTE_BIT,
- };
-
VkPipelineShaderStageCreateInfo shader_stage;
shader_stage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
shader_stage.pNext = nullptr;
shader_stage.flags = 0;
- shader_stage.stage = shader_stage_bits[stage_type[i]];
+ shader_stage.stage = shader_stage_masks[stage_type[i]];
shader_stage.module = module;
shader_stage.pName = "main";
shader_stage.pSpecializationInfo = nullptr;
@@ -5552,10 +5084,10 @@ RID RenderingDeviceVulkan::shader_create_from_bytecode(const Vector<uint8_t> &p_
// Needs to be declared in this outer scope, otherwise it may not outlive its assignment
// to pipeline_layout_create_info.
VkPushConstantRange push_constant_range;
- if (push_constant.push_constant_size) {
- push_constant_range.stageFlags = push_constant.push_constants_vk_stage;
+ if (push_constant.size) {
+ push_constant_range.stageFlags = push_constant.vk_stages_mask;
push_constant_range.offset = 0;
- push_constant_range.size = push_constant.push_constant_size;
+ push_constant_range.size = push_constant.size;
pipeline_layout_create_info.pushConstantRangeCount = 1;
pipeline_layout_create_info.pPushConstantRanges = &push_constant_range;
@@ -5629,7 +5161,7 @@ RID RenderingDeviceVulkan::uniform_buffer_create(uint32_t p_size_bytes, const Ve
return id;
}
-RID RenderingDeviceVulkan::storage_buffer_create(uint32_t p_size_bytes, const Vector<uint8_t> &p_data, uint32_t p_usage) {
+RID RenderingDeviceVulkan::storage_buffer_create(uint32_t p_size_bytes, const Vector<uint8_t> &p_data, BitField<StorageBufferUsage> p_usage) {
_THREAD_SAFE_METHOD_
ERR_FAIL_COND_V_MSG(draw_list != nullptr && p_data.size(), RID(),
"Creating buffers with data is forbidden during creation of a draw list");
@@ -5640,7 +5172,7 @@ RID RenderingDeviceVulkan::storage_buffer_create(uint32_t p_size_bytes, const Ve
Buffer buffer;
uint32_t flags = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
- if (p_usage & STORAGE_BUFFER_USAGE_DISPATCH_INDIRECT) {
+ if (p_usage.has_flag(STORAGE_BUFFER_USAGE_DISPATCH_INDIRECT)) {
flags |= VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT;
}
Error err = _buffer_allocate(&buffer, p_size_bytes, flags, VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE, 0);
@@ -5950,10 +5482,8 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms,
// Can also be used as storage, add to mutable sampled.
mutable_sampled_textures.push_back(texture);
}
- if (texture->owner.is_valid()) {
- texture = texture_owner.get_or_null(texture->owner);
- ERR_FAIL_COND_V(!texture, RID()); // Bug, should never happen.
- }
+
+ DEV_ASSERT(!texture->owner.is_valid() || texture_owner.get_or_null(texture->owner));
img_info.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
@@ -6004,10 +5534,7 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms,
mutable_sampled_textures.push_back(texture);
}
- if (texture->owner.is_valid()) {
- texture = texture_owner.get_or_null(texture->owner);
- ERR_FAIL_COND_V(!texture, RID()); // Bug, should never happen.
- }
+ DEV_ASSERT(!texture->owner.is_valid() || texture_owner.get_or_null(texture->owner));
img_info.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
@@ -6052,10 +5579,7 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms,
mutable_storage_textures.push_back(texture);
}
- if (texture->owner.is_valid()) {
- texture = texture_owner.get_or_null(texture->owner);
- ERR_FAIL_COND_V(!texture, RID()); // Bug, should never happen.
- }
+ DEV_ASSERT(!texture->owner.is_valid() || texture_owner.get_or_null(texture->owner));
img_info.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
@@ -6217,10 +5741,7 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms,
img_info.sampler = VK_NULL_HANDLE;
img_info.imageView = texture->view;
- if (texture->owner.is_valid()) {
- texture = texture_owner.get_or_null(texture->owner);
- ERR_FAIL_COND_V(!texture, RID()); // Bug, should never happen.
- }
+ DEV_ASSERT(!texture->owner.is_valid() || texture_owner.get_or_null(texture->owner));
img_info.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
@@ -6315,7 +5836,7 @@ void RenderingDeviceVulkan::uniform_set_set_invalidation_callback(RID p_uniform_
us->invalidated_callback_userdata = p_userdata;
}
-Error RenderingDeviceVulkan::buffer_update(RID p_buffer, uint32_t p_offset, uint32_t p_size, const void *p_data, uint32_t p_post_barrier) {
+Error RenderingDeviceVulkan::buffer_update(RID p_buffer, uint32_t p_offset, uint32_t p_size, const void *p_data, BitField<BarrierMask> p_post_barrier) {
_THREAD_SAFE_METHOD_
ERR_FAIL_COND_V_MSG(draw_list, ERR_INVALID_PARAMETER,
@@ -6325,7 +5846,7 @@ Error RenderingDeviceVulkan::buffer_update(RID p_buffer, uint32_t p_offset, uint
VkPipelineStageFlags dst_stage_mask = 0;
VkAccessFlags dst_access = 0;
- if (p_post_barrier & BARRIER_MASK_TRANSFER) {
+ if (p_post_barrier.has_flag(BARRIER_MASK_TRANSFER)) {
// Protect subsequent updates.
dst_stage_mask = VK_PIPELINE_STAGE_TRANSFER_BIT;
dst_access = VK_ACCESS_TRANSFER_WRITE_BIT;
@@ -6361,7 +5882,7 @@ Error RenderingDeviceVulkan::buffer_update(RID p_buffer, uint32_t p_offset, uint
return err;
}
-Error RenderingDeviceVulkan::buffer_clear(RID p_buffer, uint32_t p_offset, uint32_t p_size, uint32_t p_post_barrier) {
+Error RenderingDeviceVulkan::buffer_clear(RID p_buffer, uint32_t p_offset, uint32_t p_size, BitField<BarrierMask> p_post_barrier) {
_THREAD_SAFE_METHOD_
ERR_FAIL_COND_V_MSG((p_size % 4) != 0, ERR_INVALID_PARAMETER,
@@ -6373,7 +5894,7 @@ Error RenderingDeviceVulkan::buffer_clear(RID p_buffer, uint32_t p_offset, uint3
VkPipelineStageFlags dst_stage_mask = 0;
VkAccessFlags dst_access = 0;
- if (p_post_barrier & BARRIER_MASK_TRANSFER) {
+ if (p_post_barrier.has_flag(BARRIER_MASK_TRANSFER)) {
// Protect subsequent updates.
dst_stage_mask = VK_PIPELINE_STAGE_TRANSFER_BIT;
dst_access = VK_ACCESS_TRANSFER_WRITE_BIT;
@@ -6412,13 +5933,13 @@ Vector<uint8_t> RenderingDeviceVulkan::buffer_get_data(RID p_buffer) {
VkPipelineShaderStageCreateFlags src_stage_mask = VK_PIPELINE_STAGE_TRANSFER_BIT;
VkAccessFlags src_access_mask = VK_ACCESS_TRANSFER_WRITE_BIT;
// Get the vulkan buffer and the potential stage/access possible.
- Buffer *buffer = _get_buffer_from_owner(p_buffer, src_stage_mask, src_access_mask, BARRIER_MASK_ALL);
+ Buffer *buffer = _get_buffer_from_owner(p_buffer, src_stage_mask, src_access_mask, BARRIER_MASK_ALL_BARRIERS);
if (!buffer) {
ERR_FAIL_V_MSG(Vector<uint8_t>(), "Buffer is either invalid or this type of buffer can't be retrieved. Only Index and Vertex buffers allow retrieving.");
}
// Make sure no one is using the buffer -- the "false" gets us to the same command buffer as below.
- _buffer_memory_barrier(buffer->buffer, 0, buffer->size, src_stage_mask, src_access_mask, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_ACCESS_TRANSFER_READ_BIT, false);
+ _buffer_memory_barrier(buffer->buffer, 0, buffer->size, src_stage_mask, VK_PIPELINE_STAGE_TRANSFER_BIT, src_access_mask, VK_ACCESS_TRANSFER_READ_BIT, false);
VkCommandBuffer command_buffer = frames[frame].setup_command_buffer;
@@ -6454,7 +5975,7 @@ Vector<uint8_t> RenderingDeviceVulkan::buffer_get_data(RID p_buffer) {
/**** RENDER PIPELINE ****/
/*************************/
-RID RenderingDeviceVulkan::render_pipeline_create(RID p_shader, FramebufferFormatID p_framebuffer_format, VertexFormatID p_vertex_format, RenderPrimitive p_render_primitive, const PipelineRasterizationState &p_rasterization_state, const PipelineMultisampleState &p_multisample_state, const PipelineDepthStencilState &p_depth_stencil_state, const PipelineColorBlendState &p_blend_state, int p_dynamic_state_flags, uint32_t p_for_render_pass, const Vector<PipelineSpecializationConstant> &p_specialization_constants) {
+RID RenderingDeviceVulkan::render_pipeline_create(RID p_shader, FramebufferFormatID p_framebuffer_format, VertexFormatID p_vertex_format, RenderPrimitive p_render_primitive, const PipelineRasterizationState &p_rasterization_state, const PipelineMultisampleState &p_multisample_state, const PipelineDepthStencilState &p_depth_stencil_state, const PipelineColorBlendState &p_blend_state, BitField<PipelineDynamicStateFlags> p_dynamic_state_flags, uint32_t p_for_render_pass, const Vector<PipelineSpecializationConstant> &p_specialization_constants) {
_THREAD_SAFE_METHOD_
// Needs a shader.
@@ -6740,31 +6261,31 @@ RID RenderingDeviceVulkan::render_pipeline_create(RID p_shader, FramebufferForma
dynamic_states.push_back(VK_DYNAMIC_STATE_VIEWPORT); // Viewport and scissor are always dynamic.
dynamic_states.push_back(VK_DYNAMIC_STATE_SCISSOR);
- if (p_dynamic_state_flags & DYNAMIC_STATE_LINE_WIDTH) {
+ if (p_dynamic_state_flags.has_flag(DYNAMIC_STATE_LINE_WIDTH)) {
dynamic_states.push_back(VK_DYNAMIC_STATE_LINE_WIDTH);
}
- if (p_dynamic_state_flags & DYNAMIC_STATE_DEPTH_BIAS) {
+ if (p_dynamic_state_flags.has_flag(DYNAMIC_STATE_DEPTH_BIAS)) {
dynamic_states.push_back(VK_DYNAMIC_STATE_DEPTH_BIAS);
}
- if (p_dynamic_state_flags & DYNAMIC_STATE_BLEND_CONSTANTS) {
+ if (p_dynamic_state_flags.has_flag(DYNAMIC_STATE_BLEND_CONSTANTS)) {
dynamic_states.push_back(VK_DYNAMIC_STATE_BLEND_CONSTANTS);
}
- if (p_dynamic_state_flags & DYNAMIC_STATE_DEPTH_BOUNDS) {
+ if (p_dynamic_state_flags.has_flag(DYNAMIC_STATE_DEPTH_BOUNDS)) {
dynamic_states.push_back(VK_DYNAMIC_STATE_DEPTH_BOUNDS);
}
- if (p_dynamic_state_flags & DYNAMIC_STATE_STENCIL_COMPARE_MASK) {
+ if (p_dynamic_state_flags.has_flag(DYNAMIC_STATE_STENCIL_COMPARE_MASK)) {
dynamic_states.push_back(VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK);
}
- if (p_dynamic_state_flags & DYNAMIC_STATE_STENCIL_WRITE_MASK) {
+ if (p_dynamic_state_flags.has_flag(DYNAMIC_STATE_STENCIL_WRITE_MASK)) {
dynamic_states.push_back(VK_DYNAMIC_STATE_STENCIL_WRITE_MASK);
}
- if (p_dynamic_state_flags & DYNAMIC_STATE_STENCIL_REFERENCE) {
+ if (p_dynamic_state_flags.has_flag(DYNAMIC_STATE_STENCIL_REFERENCE)) {
dynamic_states.push_back(VK_DYNAMIC_STATE_STENCIL_REFERENCE);
}
@@ -6872,10 +6393,10 @@ RID RenderingDeviceVulkan::render_pipeline_create(RID p_shader, FramebufferForma
ERR_FAIL_COND_V_MSG(err, RID(), "vkCreateGraphicsPipelines failed with error " + itos(err) + " for shader '" + shader->name + "'.");
pipeline.set_formats = shader->set_formats;
- pipeline.push_constant_stages = shader->push_constant.push_constants_vk_stage;
+ pipeline.push_constant_stages_mask = shader->push_constant.vk_stages_mask;
pipeline.pipeline_layout = shader->pipeline_layout;
pipeline.shader = p_shader;
- pipeline.push_constant_size = shader->push_constant.push_constant_size;
+ pipeline.push_constant_size = shader->push_constant.size;
#ifdef DEBUG_ENABLED
pipeline.validation.dynamic_state = p_dynamic_state_flags;
@@ -6987,10 +6508,10 @@ RID RenderingDeviceVulkan::compute_pipeline_create(RID p_shader, const Vector<Pi
ERR_FAIL_COND_V_MSG(err, RID(), "vkCreateComputePipelines failed with error " + itos(err) + ".");
pipeline.set_formats = shader->set_formats;
- pipeline.push_constant_stages = shader->push_constant.push_constants_vk_stage;
+ pipeline.push_constant_stages_mask = shader->push_constant.vk_stages_mask;
pipeline.pipeline_layout = shader->pipeline_layout;
pipeline.shader = p_shader;
- pipeline.push_constant_size = shader->push_constant.push_constant_size;
+ pipeline.push_constant_size = shader->push_constant.size;
pipeline.local_group_size[0] = shader->compute_local_size[0];
pipeline.local_group_size[1] = shader->compute_local_size[1];
pipeline.local_group_size[2] = shader->compute_local_size[2];
@@ -7632,7 +7153,7 @@ void RenderingDeviceVulkan::draw_list_bind_render_pipeline(DrawListID p_list, RI
dl->state.set_count = pcount; // Update set count.
if (pipeline->push_constant_size) {
- dl->state.pipeline_push_constant_stages = pipeline->push_constant_stages;
+ dl->state.pipeline_push_constant_stages = pipeline->push_constant_stages_mask;
#ifdef DEBUG_ENABLED
dl->validation.pipeline_push_constant_supplied = false;
#endif
@@ -8084,7 +7605,7 @@ void RenderingDeviceVulkan::_draw_list_free(Rect2i *r_last_viewport) {
_THREAD_SAFE_UNLOCK_
}
-void RenderingDeviceVulkan::draw_list_end(uint32_t p_post_barrier) {
+void RenderingDeviceVulkan::draw_list_end(BitField<BarrierMask> p_post_barrier) {
_THREAD_SAFE_METHOD_
ERR_FAIL_COND_MSG(!draw_list, "Immediate draw list is already inactive.");
@@ -8106,15 +7627,15 @@ void RenderingDeviceVulkan::draw_list_end(uint32_t p_post_barrier) {
uint32_t barrier_flags = 0;
uint32_t access_flags = 0;
- if (p_post_barrier & BARRIER_MASK_COMPUTE) {
+ if (p_post_barrier.has_flag(BARRIER_MASK_COMPUTE)) {
barrier_flags |= VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
access_flags |= VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
}
- if (p_post_barrier & BARRIER_MASK_RASTER) {
+ if (p_post_barrier.has_flag(BARRIER_MASK_RASTER)) {
barrier_flags |= VK_PIPELINE_STAGE_VERTEX_INPUT_BIT | VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT /*| VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT*/;
access_flags |= VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_INDEX_READ_BIT | VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT /*| VK_ACCESS_INDIRECT_COMMAND_READ_BIT*/;
}
- if (p_post_barrier & BARRIER_MASK_TRANSFER) {
+ if (p_post_barrier.has_flag(BARRIER_MASK_TRANSFER)) {
barrier_flags |= VK_PIPELINE_STAGE_TRANSFER_BIT;
access_flags |= VK_ACCESS_TRANSFER_WRITE_BIT | VK_ACCESS_TRANSFER_READ_BIT;
}
@@ -8248,7 +7769,7 @@ void RenderingDeviceVulkan::compute_list_bind_compute_pipeline(ComputeListID p_l
cl->state.set_count = pcount; // Update set count.
if (pipeline->push_constant_size) {
- cl->state.pipeline_push_constant_stages = pipeline->push_constant_stages;
+ cl->state.pipeline_push_constant_stages = pipeline->push_constant_stages_mask;
#ifdef DEBUG_ENABLED
cl->validation.pipeline_push_constant_supplied = false;
#endif
@@ -8592,20 +8113,20 @@ void RenderingDeviceVulkan::compute_list_add_barrier(ComputeListID p_list) {
#endif
}
-void RenderingDeviceVulkan::compute_list_end(uint32_t p_post_barrier) {
+void RenderingDeviceVulkan::compute_list_end(BitField<BarrierMask> p_post_barrier) {
ERR_FAIL_COND(!compute_list);
uint32_t barrier_flags = 0;
uint32_t access_flags = 0;
- if (p_post_barrier & BARRIER_MASK_COMPUTE) {
+ if (p_post_barrier.has_flag(BARRIER_MASK_COMPUTE)) {
barrier_flags |= VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
access_flags |= VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
}
- if (p_post_barrier & BARRIER_MASK_RASTER) {
+ if (p_post_barrier.has_flag(BARRIER_MASK_RASTER)) {
barrier_flags |= VK_PIPELINE_STAGE_VERTEX_INPUT_BIT | VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT;
access_flags |= VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_INDEX_READ_BIT | VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT | VK_ACCESS_INDIRECT_COMMAND_READ_BIT;
}
- if (p_post_barrier & BARRIER_MASK_TRANSFER) {
+ if (p_post_barrier.has_flag(BARRIER_MASK_TRANSFER)) {
barrier_flags |= VK_PIPELINE_STAGE_TRANSFER_BIT;
access_flags |= VK_ACCESS_TRANSFER_WRITE_BIT | VK_ACCESS_TRANSFER_READ_BIT;
}
@@ -8673,43 +8194,45 @@ void RenderingDeviceVulkan::compute_list_end(uint32_t p_post_barrier) {
_THREAD_SAFE_UNLOCK_
}
-void RenderingDeviceVulkan::barrier(uint32_t p_from, uint32_t p_to) {
+void RenderingDeviceVulkan::barrier(BitField<BarrierMask> p_from, BitField<BarrierMask> p_to) {
uint32_t src_barrier_flags = 0;
uint32_t src_access_flags = 0;
- if (p_from & BARRIER_MASK_COMPUTE) {
- src_barrier_flags |= VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
- src_access_flags |= VK_ACCESS_SHADER_WRITE_BIT;
- }
- if (p_from & BARRIER_MASK_RASTER) {
- src_barrier_flags |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
- src_access_flags |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
- }
- if (p_from & BARRIER_MASK_TRANSFER) {
- src_barrier_flags |= VK_PIPELINE_STAGE_TRANSFER_BIT;
- src_access_flags |= VK_ACCESS_TRANSFER_WRITE_BIT;
- }
if (p_from == 0) {
src_barrier_flags = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
+ } else {
+ if (p_from.has_flag(BARRIER_MASK_COMPUTE)) {
+ src_barrier_flags |= VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
+ src_access_flags |= VK_ACCESS_SHADER_WRITE_BIT;
+ }
+ if (p_from.has_flag(BARRIER_MASK_RASTER)) {
+ src_barrier_flags |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
+ src_access_flags |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
+ }
+ if (p_from.has_flag(BARRIER_MASK_TRANSFER)) {
+ src_barrier_flags |= VK_PIPELINE_STAGE_TRANSFER_BIT;
+ src_access_flags |= VK_ACCESS_TRANSFER_WRITE_BIT;
+ }
}
uint32_t dst_barrier_flags = 0;
uint32_t dst_access_flags = 0;
- if (p_to & BARRIER_MASK_COMPUTE) {
- dst_barrier_flags |= VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
- dst_access_flags |= VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
- }
- if (p_to & BARRIER_MASK_RASTER) {
- dst_barrier_flags |= VK_PIPELINE_STAGE_VERTEX_INPUT_BIT | VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT;
- dst_access_flags |= VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_INDEX_READ_BIT | VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT | VK_ACCESS_INDIRECT_COMMAND_READ_BIT;
- }
- if (p_to & BARRIER_MASK_TRANSFER) {
- dst_barrier_flags |= VK_PIPELINE_STAGE_TRANSFER_BIT;
- dst_access_flags |= VK_ACCESS_TRANSFER_WRITE_BIT | VK_ACCESS_TRANSFER_READ_BIT;
- }
if (p_to == 0) {
dst_barrier_flags = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
+ } else {
+ if (p_to.has_flag(BARRIER_MASK_COMPUTE)) {
+ dst_barrier_flags |= VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
+ dst_access_flags |= VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
+ }
+ if (p_to.has_flag(BARRIER_MASK_RASTER)) {
+ dst_barrier_flags |= VK_PIPELINE_STAGE_VERTEX_INPUT_BIT | VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT;
+ dst_access_flags |= VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_INDEX_READ_BIT | VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT | VK_ACCESS_INDIRECT_COMMAND_READ_BIT;
+ }
+ if (p_to.has_flag(BARRIER_MASK_TRANSFER)) {
+ dst_barrier_flags |= VK_PIPELINE_STAGE_TRANSFER_BIT;
+ dst_access_flags |= VK_ACCESS_TRANSFER_WRITE_BIT | VK_ACCESS_TRANSFER_READ_BIT;
+ }
}
_memory_barrier(src_barrier_flags, dst_barrier_flags, src_access_flags, dst_access_flags, true);
@@ -9186,7 +8709,7 @@ void RenderingDeviceVulkan::_free_pending_resources(int p_frame) {
Texture *texture = &frames[p_frame].textures_to_dispose_of.front()->get();
if (texture->bound) {
- WARN_PRINT("Deleted a texture while it was bound..");
+ WARN_PRINT("Deleted a texture while it was bound.");
}
vkDestroyImageView(device, texture->view, nullptr);
if (texture->owner.is_null()) {
@@ -9724,6 +9247,12 @@ uint64_t RenderingDeviceVulkan::limit_get(Limit p_limit) const {
VulkanContext::SubgroupCapabilities subgroup_capabilities = context->get_subgroup_capabilities();
return subgroup_capabilities.supported_operations_flags_rd();
}
+ case LIMIT_VRS_TEXEL_WIDTH: {
+ return context->get_vrs_capabilities().texel_size.x;
+ }
+ case LIMIT_VRS_TEXEL_HEIGHT: {
+ return context->get_vrs_capabilities().texel_size.y;
+ }
default:
ERR_FAIL_V(0);
}
diff --git a/drivers/vulkan/rendering_device_vulkan.h b/drivers/vulkan/rendering_device_vulkan.h
index 7c75e9bb2e..3ccd7bb1d9 100644
--- a/drivers/vulkan/rendering_device_vulkan.h
+++ b/drivers/vulkan/rendering_device_vulkan.h
@@ -162,7 +162,7 @@ class RenderingDeviceVulkan : public RenderingDevice {
uint32_t texture_upload_region_size_px = 0;
Vector<uint8_t> _texture_get_data_from_image(Texture *tex, VkImage p_image, VmaAllocation p_allocation, uint32_t p_layer, bool p_2d = false);
- Error _texture_update(RID p_texture, uint32_t p_layer, const Vector<uint8_t> &p_data, uint32_t p_post_barrier, bool p_use_setup_queue);
+ Error _texture_update(RID p_texture, uint32_t p_layer, const Vector<uint8_t> &p_data, BitField<BarrierMask> p_post_barrier, bool p_use_setup_queue);
/*****************/
/**** SAMPLER ****/
@@ -226,8 +226,8 @@ class RenderingDeviceVulkan : public RenderingDevice {
Error _buffer_update(Buffer *p_buffer, size_t p_offset, const uint8_t *p_data, size_t p_data_size, bool p_use_draw_command_buffer = false, uint32_t p_required_align = 32);
void _full_barrier(bool p_sync_with_draw);
- void _memory_barrier(VkPipelineStageFlags p_src_stage_mask, VkPipelineStageFlags p_dst_stage_mask, VkAccessFlags p_src_access, VkAccessFlags p_dst_sccess, bool p_sync_with_draw);
- void _buffer_memory_barrier(VkBuffer buffer, uint64_t p_from, uint64_t p_size, VkPipelineStageFlags p_src_stage_mask, VkPipelineStageFlags p_dst_stage_mask, VkAccessFlags p_src_access, VkAccessFlags p_dst_sccess, bool p_sync_with_draw);
+ void _memory_barrier(VkPipelineStageFlags p_src_stage_mask, VkPipelineStageFlags p_dst_stage_mask, VkAccessFlags p_src_access, VkAccessFlags p_dst_access, bool p_sync_with_draw);
+ void _buffer_memory_barrier(VkBuffer buffer, uint64_t p_from, uint64_t p_size, VkPipelineStageFlags p_src_stage_mask, VkPipelineStageFlags p_dst_stage_mask, VkAccessFlags p_src_access, VkAccessFlags p_dst_access, bool p_sync_with_draw);
/*********************/
/**** FRAMEBUFFER ****/
@@ -543,10 +543,6 @@ class RenderingDeviceVulkan : public RenderingDevice {
// As a result, we need to figure out quickly when something is no longer "compatible".
// in order to avoid costly rebinds.
- enum {
- MAX_UNIFORM_SETS = 16
- };
-
struct UniformInfo {
UniformType type = UniformType::UNIFORM_TYPE_MAX;
bool writable = false;
@@ -628,8 +624,8 @@ class RenderingDeviceVulkan : public RenderingDevice {
uint32_t fragment_output_mask = 0;
struct PushConstant {
- uint32_t push_constant_size = 0;
- uint32_t push_constants_vk_stage = 0;
+ uint32_t size = 0;
+ uint32_t vk_stages_mask = 0;
};
PushConstant push_constant;
@@ -791,7 +787,7 @@ class RenderingDeviceVulkan : public RenderingDevice {
VkPipelineLayout pipeline_layout = VK_NULL_HANDLE; // Not owned, needed for push constants.
VkPipeline pipeline = VK_NULL_HANDLE;
uint32_t push_constant_size = 0;
- uint32_t push_constant_stages = 0;
+ uint32_t push_constant_stages_mask = 0;
};
RID_Owner<RenderPipeline, true> render_pipeline_owner;
@@ -802,7 +798,7 @@ class RenderingDeviceVulkan : public RenderingDevice {
VkPipelineLayout pipeline_layout = VK_NULL_HANDLE; // Not owned, needed for push constants.
VkPipeline pipeline = VK_NULL_HANDLE;
uint32_t push_constant_size = 0;
- uint32_t push_constant_stages = 0;
+ uint32_t push_constant_stages_mask = 0;
uint32_t local_group_size[3] = { 0, 0, 0 };
};
@@ -909,7 +905,7 @@ class RenderingDeviceVulkan : public RenderingDevice {
Error _draw_list_setup_framebuffer(Framebuffer *p_framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, VkFramebuffer *r_framebuffer, VkRenderPass *r_render_pass, uint32_t *r_subpass_count);
Error _draw_list_render_pass_begin(Framebuffer *framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_colors, float p_clear_depth, uint32_t p_clear_stencil, Point2i viewport_offset, Point2i viewport_size, VkFramebuffer vkframebuffer, VkRenderPass render_pass, VkCommandBuffer command_buffer, VkSubpassContents subpass_contents, const Vector<RID> &p_storage_textures);
_FORCE_INLINE_ DrawList *_get_draw_list_ptr(DrawListID p_id);
- Buffer *_get_buffer_from_owner(RID p_buffer, VkPipelineStageFlags &dst_stage_mask, VkAccessFlags &dst_access, uint32_t p_post_barrier);
+ Buffer *_get_buffer_from_owner(RID p_buffer, VkPipelineStageFlags &dst_stage_mask, VkAccessFlags &dst_access, BitField<BarrierMask> p_post_barrier);
Error _draw_list_allocate(const Rect2i &p_viewport, uint32_t p_splits, uint32_t p_subpass);
void _draw_list_free(Rect2i *r_last_viewport = nullptr);
@@ -1052,17 +1048,17 @@ public:
virtual RID texture_create_from_extension(TextureType p_type, DataFormat p_format, TextureSamples p_samples, uint64_t p_flags, uint64_t p_image, uint64_t p_width, uint64_t p_height, uint64_t p_depth, uint64_t p_layers);
virtual RID texture_create_shared_from_slice(const TextureView &p_view, RID p_with_texture, uint32_t p_layer, uint32_t p_mipmap, uint32_t p_mipmaps = 1, TextureSliceType p_slice_type = TEXTURE_SLICE_2D);
- virtual Error texture_update(RID p_texture, uint32_t p_layer, const Vector<uint8_t> &p_data, uint32_t p_post_barrier = BARRIER_MASK_ALL);
+ virtual Error texture_update(RID p_texture, uint32_t p_layer, const Vector<uint8_t> &p_data, BitField<BarrierMask> p_post_barrier = BARRIER_MASK_ALL_BARRIERS);
virtual Vector<uint8_t> texture_get_data(RID p_texture, uint32_t p_layer);
- virtual bool texture_is_format_supported_for_usage(DataFormat p_format, uint32_t p_usage) const;
+ virtual bool texture_is_format_supported_for_usage(DataFormat p_format, BitField<RenderingDevice::TextureUsageBits> p_usage) const;
virtual bool texture_is_shared(RID p_texture);
virtual bool texture_is_valid(RID p_texture);
virtual Size2i texture_size(RID p_texture);
- virtual Error texture_copy(RID p_from_texture, RID p_to_texture, const Vector3 &p_from, const Vector3 &p_to, const Vector3 &p_size, uint32_t p_src_mipmap, uint32_t p_dst_mipmap, uint32_t p_src_layer, uint32_t p_dst_layer, uint32_t p_post_barrier = BARRIER_MASK_ALL);
- virtual Error texture_clear(RID p_texture, const Color &p_color, uint32_t p_base_mipmap, uint32_t p_mipmaps, uint32_t p_base_layer, uint32_t p_layers, uint32_t p_post_barrier = BARRIER_MASK_ALL);
- virtual Error texture_resolve_multisample(RID p_from_texture, RID p_to_texture, uint32_t p_post_barrier = BARRIER_MASK_ALL);
+ virtual Error texture_copy(RID p_from_texture, RID p_to_texture, const Vector3 &p_from, const Vector3 &p_to, const Vector3 &p_size, uint32_t p_src_mipmap, uint32_t p_dst_mipmap, uint32_t p_src_layer, uint32_t p_dst_layer, BitField<BarrierMask> p_post_barrier = BARRIER_MASK_ALL_BARRIERS);
+ virtual Error texture_clear(RID p_texture, const Color &p_color, uint32_t p_base_mipmap, uint32_t p_mipmaps, uint32_t p_base_layer, uint32_t p_layers, BitField<BarrierMask> p_post_barrier = BARRIER_MASK_ALL_BARRIERS);
+ virtual Error texture_resolve_multisample(RID p_from_texture, RID p_to_texture, BitField<BarrierMask> p_post_barrier = BARRIER_MASK_ALL_BARRIERS);
/*********************/
/**** FRAMEBUFFER ****/
@@ -1095,7 +1091,7 @@ public:
// 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.
virtual VertexFormatID vertex_format_create(const Vector<VertexAttribute> &p_vertex_formats);
- virtual RID vertex_array_create(uint32_t p_vertex_count, VertexFormatID p_vertex_format, const Vector<RID> &p_src_buffers);
+ virtual RID vertex_array_create(uint32_t p_vertex_count, VertexFormatID p_vertex_format, const Vector<RID> &p_src_buffers, const Vector<uint64_t> &p_offsets = Vector<uint64_t>());
virtual RID index_buffer_create(uint32_t p_size_indices, IndexBufferFormat p_format, const Vector<uint8_t> &p_data = Vector<uint8_t>(), bool p_use_restart_indices = false);
@@ -1117,22 +1113,22 @@ public:
/*****************/
virtual RID uniform_buffer_create(uint32_t p_size_bytes, const Vector<uint8_t> &p_data = Vector<uint8_t>());
- virtual RID storage_buffer_create(uint32_t p_size_bytes, const Vector<uint8_t> &p_data = Vector<uint8_t>(), uint32_t p_usage = 0);
+ virtual RID storage_buffer_create(uint32_t p_size_bytes, const Vector<uint8_t> &p_data = Vector<uint8_t>(), BitField<StorageBufferUsage> p_usage = 0);
virtual RID texture_buffer_create(uint32_t p_size_elements, DataFormat p_format, const Vector<uint8_t> &p_data = Vector<uint8_t>());
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, 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);
+ virtual Error buffer_update(RID p_buffer, uint32_t p_offset, uint32_t p_size, const void *p_data, BitField<BarrierMask> p_post_barrier = BARRIER_MASK_ALL_BARRIERS); // Works for any buffer.
+ virtual Error buffer_clear(RID p_buffer, uint32_t p_offset, uint32_t p_size, BitField<BarrierMask> p_post_barrier = BARRIER_MASK_ALL_BARRIERS);
virtual Vector<uint8_t> buffer_get_data(RID p_buffer);
/*************************/
/**** RENDER PIPELINE ****/
/*************************/
- virtual RID render_pipeline_create(RID p_shader, FramebufferFormatID p_framebuffer_format, VertexFormatID p_vertex_format, RenderPrimitive p_render_primitive, const PipelineRasterizationState &p_rasterization_state, const PipelineMultisampleState &p_multisample_state, const PipelineDepthStencilState &p_depth_stencil_state, const PipelineColorBlendState &p_blend_state, int p_dynamic_state_flags = 0, uint32_t p_for_render_pass = 0, const Vector<PipelineSpecializationConstant> &p_specialization_constants = Vector<PipelineSpecializationConstant>());
+ virtual RID render_pipeline_create(RID p_shader, FramebufferFormatID p_framebuffer_format, VertexFormatID p_vertex_format, RenderPrimitive p_render_primitive, const PipelineRasterizationState &p_rasterization_state, const PipelineMultisampleState &p_multisample_state, const PipelineDepthStencilState &p_depth_stencil_state, const PipelineColorBlendState &p_blend_state, BitField<PipelineDynamicStateFlags> p_dynamic_state_flags = 0, uint32_t p_for_render_pass = 0, const Vector<PipelineSpecializationConstant> &p_specialization_constants = Vector<PipelineSpecializationConstant>());
virtual bool render_pipeline_is_valid(RID p_pipeline);
/**************************/
@@ -1176,7 +1172,7 @@ public:
virtual DrawListID draw_list_switch_to_next_pass();
virtual Error draw_list_switch_to_next_pass_split(uint32_t p_splits, DrawListID *r_split_ids);
- virtual void draw_list_end(uint32_t p_post_barrier = BARRIER_MASK_ALL);
+ virtual void draw_list_end(BitField<BarrierMask> p_post_barrier = BARRIER_MASK_ALL_BARRIERS);
/***********************/
/**** COMPUTE LISTS ****/
@@ -1191,9 +1187,9 @@ public:
virtual void compute_list_dispatch(ComputeListID p_list, uint32_t p_x_groups, uint32_t p_y_groups, uint32_t p_z_groups);
virtual void compute_list_dispatch_threads(ComputeListID p_list, uint32_t p_x_threads, uint32_t p_y_threads, uint32_t p_z_threads);
virtual void compute_list_dispatch_indirect(ComputeListID p_list, RID p_buffer, uint32_t p_offset);
- virtual void compute_list_end(uint32_t p_post_barrier = BARRIER_MASK_ALL);
+ virtual void compute_list_end(BitField<BarrierMask> p_post_barrier = BARRIER_MASK_ALL_BARRIERS);
- virtual void barrier(uint32_t p_from = BARRIER_MASK_ALL, uint32_t p_to = BARRIER_MASK_ALL);
+ virtual void barrier(BitField<BarrierMask> p_from = BARRIER_MASK_ALL_BARRIERS, BitField<BarrierMask> p_to = BARRIER_MASK_ALL_BARRIERS);
virtual void full_barrier();
/**************/
diff --git a/drivers/vulkan/vulkan_context.cpp b/drivers/vulkan/vulkan_context.cpp
index 464ab474e1..ee251e7acf 100644
--- a/drivers/vulkan/vulkan_context.cpp
+++ b/drivers/vulkan/vulkan_context.cpp
@@ -68,7 +68,7 @@ Vector<VkAttachmentReference> VulkanContext::_convert_VkAttachmentReference2(uin
}
VkResult VulkanContext::vkCreateRenderPass2KHR(VkDevice p_device, const VkRenderPassCreateInfo2 *p_create_info, const VkAllocationCallbacks *p_allocator, VkRenderPass *p_render_pass) {
- if (has_renderpass2_ext) {
+ if (is_device_extension_enabled(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME)) {
if (fpCreateRenderPass2KHR == nullptr) {
fpCreateRenderPass2KHR = (PFN_vkCreateRenderPass2KHR)vkGetDeviceProcAddr(p_device, "vkCreateRenderPass2KHR");
}
@@ -378,9 +378,7 @@ Error VulkanContext::_obtain_vulkan_version() {
uint32_t api_version;
VkResult res = func(&api_version);
if (res == VK_SUCCESS) {
- vulkan_major = VK_API_VERSION_MAJOR(api_version);
- vulkan_minor = VK_API_VERSION_MINOR(api_version);
- vulkan_patch = VK_API_VERSION_PATCH(api_version);
+ instance_api_version = 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.
@@ -388,28 +386,34 @@ Error VulkanContext::_obtain_vulkan_version() {
}
} else {
print_line("vkEnumerateInstanceVersion not available, assuming Vulkan 1.0.");
- }
-
- // We don't go above 1.2.
- if ((vulkan_major > 1) || (vulkan_major == 1 && vulkan_minor > 2)) {
- vulkan_major = 1;
- vulkan_minor = 2;
- vulkan_patch = 0;
+ instance_api_version = VK_API_VERSION_1_0;
}
return OK;
}
-Error VulkanContext::_initialize_extensions() {
- uint32_t instance_extension_count = 0;
+bool VulkanContext::instance_extensions_initialized = false;
+HashMap<CharString, bool> VulkanContext::requested_instance_extensions;
+
+void VulkanContext::register_requested_instance_extension(const CharString &extension_name, bool p_required) {
+ ERR_FAIL_COND_MSG(instance_extensions_initialized, "You can only registered extensions before the Vulkan instance is created");
+ ERR_FAIL_COND(requested_instance_extensions.has(extension_name));
+
+ requested_instance_extensions[extension_name] = p_required;
+}
+
+Error VulkanContext::_initialize_instance_extensions() {
+ enabled_instance_extension_names.clear();
+
+ // Make sure our core extensions are here
+ register_requested_instance_extension(VK_KHR_SURFACE_EXTENSION_NAME, true);
+ register_requested_instance_extension(_get_platform_surface_extension(), true);
+
+ if (_use_validation_layers()) {
+ register_requested_instance_extension(VK_EXT_DEBUG_REPORT_EXTENSION_NAME, false);
+ }
- enabled_extension_count = 0;
- enabled_debug_utils = false;
- enabled_debug_report = false;
- // Look for instance extensions.
- VkBool32 surfaceExtFound = 0;
- VkBool32 platformSurfaceExtFound = 0;
- memset(extension_names, 0, sizeof(extension_names));
+ register_requested_instance_extension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, false);
// Only enable debug utils in verbose mode or DEV_ENABLED.
// End users would get spammed with messages of varying verbosity due to the
@@ -420,54 +424,141 @@ Error VulkanContext::_initialize_extensions() {
#else
bool want_debug_utils = OS::get_singleton()->is_stdout_verbose();
#endif
+ if (want_debug_utils) {
+ register_requested_instance_extension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME, false);
+ }
+ // Load instance extensions that are available...
+ uint32_t instance_extension_count = 0;
VkResult err = vkEnumerateInstanceExtensionProperties(nullptr, &instance_extension_count, nullptr);
ERR_FAIL_COND_V(err != VK_SUCCESS && err != VK_INCOMPLETE, ERR_CANT_CREATE);
+ ERR_FAIL_COND_V_MSG(instance_extension_count == 0, ERR_CANT_CREATE, "No instance extensions found, is a driver installed?");
- if (instance_extension_count > 0) {
- VkExtensionProperties *instance_extensions = (VkExtensionProperties *)malloc(sizeof(VkExtensionProperties) * instance_extension_count);
- err = vkEnumerateInstanceExtensionProperties(nullptr, &instance_extension_count, instance_extensions);
- if (err != VK_SUCCESS && err != VK_INCOMPLETE) {
- free(instance_extensions);
- ERR_FAIL_V(ERR_CANT_CREATE);
+ VkExtensionProperties *instance_extensions = (VkExtensionProperties *)malloc(sizeof(VkExtensionProperties) * instance_extension_count);
+ err = vkEnumerateInstanceExtensionProperties(nullptr, &instance_extension_count, instance_extensions);
+ if (err != VK_SUCCESS && err != VK_INCOMPLETE) {
+ free(instance_extensions);
+ ERR_FAIL_V(ERR_CANT_CREATE);
+ }
+#ifdef DEV_ENABLED
+ for (uint32_t i = 0; i < instance_extension_count; i++) {
+ print_verbose(String("VULKAN: Found instance extension ") + String(instance_extensions[i].extensionName));
+ }
+#endif
+
+ // Enable all extensions that are supported and requested
+ for (uint32_t i = 0; i < instance_extension_count; i++) {
+ CharString extension_name(instance_extensions[i].extensionName);
+ if (requested_instance_extensions.has(extension_name)) {
+ enabled_instance_extension_names.insert(extension_name);
}
- for (uint32_t i = 0; i < instance_extension_count; i++) {
- if (!strcmp(VK_KHR_SURFACE_EXTENSION_NAME, instance_extensions[i].extensionName)) {
- surfaceExtFound = 1;
- extension_names[enabled_extension_count++] = VK_KHR_SURFACE_EXTENSION_NAME;
- }
+ }
- if (!strcmp(_get_platform_surface_extension(), instance_extensions[i].extensionName)) {
- platformSurfaceExtFound = 1;
- extension_names[enabled_extension_count++] = _get_platform_surface_extension();
- }
- if (!strcmp(VK_EXT_DEBUG_REPORT_EXTENSION_NAME, instance_extensions[i].extensionName)) {
- if (_use_validation_layers()) {
- extension_names[enabled_extension_count++] = VK_EXT_DEBUG_REPORT_EXTENSION_NAME;
- enabled_debug_report = true;
- }
- }
- if (!strcmp(VK_EXT_DEBUG_UTILS_EXTENSION_NAME, instance_extensions[i].extensionName)) {
- if (want_debug_utils) {
- extension_names[enabled_extension_count++] = VK_EXT_DEBUG_UTILS_EXTENSION_NAME;
- enabled_debug_utils = true;
- }
- }
- if (!strcmp(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, instance_extensions[i].extensionName)) {
- extension_names[enabled_extension_count++] = VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME;
- }
- if (enabled_extension_count >= MAX_EXTENSIONS) {
+ // Now check our requested extensions
+ for (KeyValue<CharString, bool> &requested_extension : requested_instance_extensions) {
+ if (!enabled_instance_extension_names.has(requested_extension.key)) {
+ if (requested_extension.value) {
free(instance_extensions);
- ERR_FAIL_V_MSG(ERR_BUG, "Enabled extension count reaches MAX_EXTENSIONS, BUG");
+ ERR_FAIL_V_MSG(ERR_BUG, String("Required extension ") + String(requested_extension.key) + String(" not found, is a driver installed?"));
+ } else {
+ print_verbose(String("Optional extension ") + String(requested_extension.key) + String(" not found"));
}
}
+ }
- free(instance_extensions);
+ free(instance_extensions);
+
+ instance_extensions_initialized = true;
+ return OK;
+}
+
+bool VulkanContext::device_extensions_initialized = false;
+HashMap<CharString, bool> VulkanContext::requested_device_extensions;
+
+void VulkanContext::register_requested_device_extension(const CharString &extension_name, bool p_required) {
+ ERR_FAIL_COND_MSG(device_extensions_initialized, "You can only registered extensions before the Vulkan instance is created");
+ ERR_FAIL_COND(requested_device_extensions.has(extension_name));
+
+ requested_device_extensions[extension_name] = p_required;
+}
+
+Error VulkanContext::_initialize_device_extensions() {
+ // Look for device extensions.
+ enabled_device_extension_names.clear();
+
+ // Make sure our core extensions are here
+ register_requested_device_extension(VK_KHR_SWAPCHAIN_EXTENSION_NAME, true);
+
+ register_requested_device_extension(VK_KHR_MULTIVIEW_EXTENSION_NAME, false);
+ register_requested_device_extension(VK_KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME, false);
+ register_requested_device_extension(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME, false);
+ register_requested_device_extension(VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME, false);
+ register_requested_device_extension(VK_KHR_16BIT_STORAGE_EXTENSION_NAME, false);
+
+ // TODO consider the following extensions:
+ // - VK_KHR_spirv_1_4
+ // - VK_KHR_swapchain_mutable_format
+ // - VK_EXT_full_screen_exclusive
+ // - VK_EXT_hdr_metadata
+ // - VK_KHR_depth_stencil_resolve
+
+ // Even though the user "enabled" the extension via the command
+ // line, we must make sure that it's enumerated for use with the
+ // device. Therefore, disable it here, and re-enable it again if
+ // enumerated.
+ if (VK_KHR_incremental_present_enabled) {
+ register_requested_device_extension(VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME, false);
+ }
+ if (VK_GOOGLE_display_timing_enabled) {
+ register_requested_device_extension(VK_GOOGLE_DISPLAY_TIMING_EXTENSION_NAME, false);
+ }
+
+ // obtain available device extensions
+ uint32_t device_extension_count = 0;
+ VkResult err = vkEnumerateDeviceExtensionProperties(gpu, nullptr, &device_extension_count, nullptr);
+ ERR_FAIL_COND_V(err, ERR_CANT_CREATE);
+ ERR_FAIL_COND_V_MSG(device_extension_count == 0, ERR_CANT_CREATE,
+ "vkEnumerateDeviceExtensionProperties failed to find any extensions\n\n"
+ "Do you have a compatible Vulkan installable client driver (ICD) installed?\n"
+ "vkCreateInstance Failure");
+
+ VkExtensionProperties *device_extensions = (VkExtensionProperties *)malloc(sizeof(VkExtensionProperties) * device_extension_count);
+ err = vkEnumerateDeviceExtensionProperties(gpu, nullptr, &device_extension_count, device_extensions);
+ if (err) {
+ free(device_extensions);
+ ERR_FAIL_V(ERR_CANT_CREATE);
+ }
+
+#ifdef DEV_ENABLED
+ for (uint32_t i = 0; i < device_extension_count; i++) {
+ print_verbose(String("VULKAN: Found device extension ") + String(device_extensions[i].extensionName));
+ }
+#endif
+
+ // Enable all extensions that are supported and requested
+ for (uint32_t i = 0; i < device_extension_count; i++) {
+ CharString extension_name(device_extensions[i].extensionName);
+ if (requested_device_extensions.has(extension_name)) {
+ enabled_device_extension_names.insert(extension_name);
+ }
+ }
+
+ // Now check our requested extensions
+ for (KeyValue<CharString, bool> &requested_extension : requested_device_extensions) {
+ if (!enabled_device_extension_names.has(requested_extension.key)) {
+ if (requested_extension.value) {
+ free(device_extensions);
+ ERR_FAIL_V_MSG(ERR_BUG,
+ String("vkEnumerateDeviceExtensionProperties failed to find the ") + String(requested_extension.key) + String(" extension.\n\nDo you have a compatible Vulkan installable client driver (ICD) installed?\nvkCreateInstance Failure"));
+ } else {
+ print_verbose(String("Optional extension ") + String(requested_extension.key) + String(" not found"));
+ }
+ }
}
- ERR_FAIL_COND_V_MSG(!surfaceExtFound, ERR_CANT_CREATE, "No surface extension found, is a driver installed?");
- ERR_FAIL_COND_V_MSG(!platformSurfaceExtFound, ERR_CANT_CREATE, "No platform surface extension found, is a driver installed?");
+ free(device_extensions);
+ device_extensions_initialized = true;
return OK;
}
@@ -625,6 +716,9 @@ Error VulkanContext::_check_capabilities() {
vrs_capabilities.pipeline_vrs_supported = false;
vrs_capabilities.primitive_vrs_supported = false;
vrs_capabilities.attachment_vrs_supported = false;
+ vrs_capabilities.min_texel_size = Size2i();
+ vrs_capabilities.max_texel_size = Size2i();
+ vrs_capabilities.texel_size = Size2i();
multiview_capabilities.is_supported = false;
multiview_capabilities.geometry_shader_is_supported = false;
multiview_capabilities.tessellation_shader_is_supported = false;
@@ -641,180 +735,176 @@ 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.
- 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.
- vkGetPhysicalDeviceFeatures2_func = (PFN_vkGetPhysicalDeviceFeatures2)vkGetInstanceProcAddr(inst, "vkGetPhysicalDeviceFeatures2KHR");
- }
- if (vkGetPhysicalDeviceFeatures2_func != nullptr) {
- // 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,
- };
+ if (is_instance_extension_enabled(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) {
+ // 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.
+ vkGetPhysicalDeviceFeatures2_func = (PFN_vkGetPhysicalDeviceFeatures2)vkGetInstanceProcAddr(inst, "vkGetPhysicalDeviceFeatures2KHR");
+ }
+ if (vkGetPhysicalDeviceFeatures2_func != nullptr) {
+ // 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*/ &vrs_features,
- /*shaderFloat16*/ false,
- /*shaderInt8*/ false,
- };
+ VkPhysicalDeviceShaderFloat16Int8FeaturesKHR shader_features = {
+ /*sType*/ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES_KHR,
+ /*pNext*/ &vrs_features,
+ /*shaderFloat16*/ false,
+ /*shaderInt8*/ false,
+ };
- VkPhysicalDevice16BitStorageFeaturesKHR storage_feature = {
- /*sType*/ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES_KHR,
- /*pNext*/ &shader_features,
- /*storageBuffer16BitAccess*/ false,
- /*uniformAndStorageBuffer16BitAccess*/ false,
- /*storagePushConstant16*/ false,
- /*storageInputOutput16*/ false,
- };
+ VkPhysicalDevice16BitStorageFeaturesKHR storage_feature = {
+ /*sType*/ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES_KHR,
+ /*pNext*/ &shader_features,
+ /*storageBuffer16BitAccess*/ false,
+ /*uniformAndStorageBuffer16BitAccess*/ false,
+ /*storagePushConstant16*/ false,
+ /*storageInputOutput16*/ false,
+ };
- VkPhysicalDeviceMultiviewFeatures multiview_features = {
- /*sType*/ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES,
- /*pNext*/ &storage_feature,
- /*multiview*/ false,
- /*multiviewGeometryShader*/ false,
- /*multiviewTessellationShader*/ false,
- };
+ VkPhysicalDeviceMultiviewFeatures multiview_features = {
+ /*sType*/ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES,
+ /*pNext*/ &storage_feature,
+ /*multiview*/ false,
+ /*multiviewGeometryShader*/ false,
+ /*multiviewTessellationShader*/ false,
+ };
- VkPhysicalDeviceFeatures2 device_features;
- device_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
- device_features.pNext = &multiview_features;
+ VkPhysicalDeviceFeatures2 device_features;
+ device_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
+ device_features.pNext = &multiview_features;
- vkGetPhysicalDeviceFeatures2_func(gpu, &device_features);
+ vkGetPhysicalDeviceFeatures2_func(gpu, &device_features);
- // We must check that the relative extension is present before assuming a
- // feature as enabled. Actually, according to the spec we shouldn't add the
- // structs in pNext at all, but this works fine.
- // See also: https://github.com/godotengine/godot/issues/65409
- for (uint32_t i = 0; i < enabled_extension_count; ++i) {
- if (!strcmp(VK_KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME, extension_names[i])) {
+ // We must check that the relative extension is present before assuming a
+ // feature as enabled. Actually, according to the spec we shouldn't add the
+ // structs in pNext at all, but this works fine.
+ // See also: https://github.com/godotengine/godot/issues/65409
+ if (is_device_extension_enabled(VK_KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME)) {
vrs_capabilities.pipeline_vrs_supported = vrs_features.pipelineFragmentShadingRate;
vrs_capabilities.primitive_vrs_supported = vrs_features.primitiveFragmentShadingRate;
vrs_capabilities.attachment_vrs_supported = vrs_features.attachmentFragmentShadingRate;
-
- continue;
}
- if (!strcmp(VK_KHR_MULTIVIEW_EXTENSION_NAME, extension_names[i])) {
+ if (is_device_extension_enabled(VK_KHR_MULTIVIEW_EXTENSION_NAME)) {
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;
-
- continue;
}
- if (!strcmp(VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME, extension_names[i])) {
+ if (is_device_extension_enabled(VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME)) {
shader_capabilities.shader_float16_is_supported = shader_features.shaderFloat16;
shader_capabilities.shader_int8_is_supported = shader_features.shaderInt8;
-
- continue;
}
- if (!strcmp(VK_KHR_16BIT_STORAGE_EXTENSION_NAME, extension_names[i])) {
+ if (is_device_extension_enabled(VK_KHR_16BIT_STORAGE_EXTENSION_NAME)) {
storage_buffer_capabilities.storage_buffer_16_bit_access_is_supported = storage_feature.storageBuffer16BitAccess;
storage_buffer_capabilities.uniform_and_storage_buffer_16_bit_access_is_supported = storage_feature.uniformAndStorageBuffer16BitAccess;
storage_buffer_capabilities.storage_push_constant_16_is_supported = storage_feature.storagePushConstant16;
storage_buffer_capabilities.storage_input_output_16 = storage_feature.storageInputOutput16;
-
- continue;
}
}
- }
-
- // 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.
- device_properties_func = (PFN_vkGetPhysicalDeviceProperties2)vkGetInstanceProcAddr(inst, "vkGetPhysicalDeviceProperties2KHR");
- }
- if (device_properties_func != nullptr) {
- VkPhysicalDeviceFragmentShadingRatePropertiesKHR vrsProperties{};
- VkPhysicalDeviceMultiviewProperties multiviewProperties{};
- VkPhysicalDeviceSubgroupProperties subgroupProperties{};
- VkPhysicalDeviceProperties2 physicalDeviceProperties{};
- void *nextptr = nullptr;
- if (!(vulkan_major == 1 && vulkan_minor == 0)) {
- subgroupProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES;
- subgroupProperties.pNext = nextptr;
-
- nextptr = &subgroupProperties;
+ // 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.
+ device_properties_func = (PFN_vkGetPhysicalDeviceProperties2)vkGetInstanceProcAddr(inst, "vkGetPhysicalDeviceProperties2KHR");
}
+ if (device_properties_func != nullptr) {
+ VkPhysicalDeviceFragmentShadingRatePropertiesKHR vrsProperties{};
+ VkPhysicalDeviceMultiviewProperties multiviewProperties{};
+ VkPhysicalDeviceSubgroupProperties subgroupProperties{};
+ VkPhysicalDeviceProperties2 physicalDeviceProperties{};
+ void *nextptr = nullptr;
+
+ if (device_api_version >= VK_API_VERSION_1_1) { // Vulkan 1.1 or higher
+ subgroupProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES;
+ subgroupProperties.pNext = nextptr;
+
+ nextptr = &subgroupProperties;
+ }
- if (multiview_capabilities.is_supported) {
- multiviewProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES;
- multiviewProperties.pNext = nextptr;
+ if (multiview_capabilities.is_supported) {
+ multiviewProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES;
+ multiviewProperties.pNext = nextptr;
- nextptr = &multiviewProperties;
- }
+ nextptr = &multiviewProperties;
+ }
- if (vrs_capabilities.attachment_vrs_supported) {
- vrsProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_PROPERTIES_KHR;
- vrsProperties.pNext = nextptr;
+ if (vrs_capabilities.attachment_vrs_supported) {
+ vrsProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_PROPERTIES_KHR;
+ vrsProperties.pNext = nextptr;
- nextptr = &vrsProperties;
- }
+ nextptr = &vrsProperties;
+ }
- physicalDeviceProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
- physicalDeviceProperties.pNext = nextptr;
+ physicalDeviceProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
+ physicalDeviceProperties.pNext = nextptr;
- device_properties_func(gpu, &physicalDeviceProperties);
+ device_properties_func(gpu, &physicalDeviceProperties);
- subgroup_capabilities.size = subgroupProperties.subgroupSize;
- subgroup_capabilities.supportedStages = subgroupProperties.supportedStages;
- subgroup_capabilities.supportedOperations = subgroupProperties.supportedOperations;
- // Note: quadOperationsInAllStages will be true if:
- // - supportedStages has VK_SHADER_STAGE_ALL_GRAPHICS + VK_SHADER_STAGE_COMPUTE_BIT.
- // - supportedOperations has VK_SUBGROUP_FEATURE_QUAD_BIT.
- subgroup_capabilities.quadOperationsInAllStages = subgroupProperties.quadOperationsInAllStages;
+ subgroup_capabilities.size = subgroupProperties.subgroupSize;
+ subgroup_capabilities.supportedStages = subgroupProperties.supportedStages;
+ subgroup_capabilities.supportedOperations = subgroupProperties.supportedOperations;
+ // Note: quadOperationsInAllStages will be true if:
+ // - supportedStages has VK_SHADER_STAGE_ALL_GRAPHICS + VK_SHADER_STAGE_COMPUTE_BIT.
+ // - 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;
+ 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;
+
+ // We'll attempt to default to a texel size of 16x16
+ vrs_capabilities.texel_size.x = CLAMP(16, vrs_capabilities.min_texel_size.x, vrs_capabilities.max_texel_size.x);
+ vrs_capabilities.texel_size.y = CLAMP(16, vrs_capabilities.min_texel_size.y, vrs_capabilities.max_texel_size.y);
+
+ 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(")"));
+ }
- 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");
}
- } 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;
- if (multiview_capabilities.is_supported) {
- multiview_capabilities.max_view_count = multiviewProperties.maxMultiviewViewCount;
- multiview_capabilities.max_instance_count = multiviewProperties.maxMultiviewInstanceIndex;
+ print_verbose("- Vulkan multiview supported:");
+ print_verbose(" max view count: " + itos(multiview_capabilities.max_view_count));
+ print_verbose(" max instances: " + itos(multiview_capabilities.max_instance_count));
+ } else {
+ print_verbose("- Vulkan multiview not supported");
+ }
- print_verbose("- Vulkan multiview supported:");
- print_verbose(" max view count: " + itos(multiview_capabilities.max_view_count));
- print_verbose(" max instances: " + itos(multiview_capabilities.max_instance_count));
+ print_verbose("- Vulkan subgroup:");
+ print_verbose(" size: " + itos(subgroup_capabilities.size));
+ print_verbose(" stages: " + subgroup_capabilities.supported_stages_desc());
+ print_verbose(" supported ops: " + subgroup_capabilities.supported_operations_desc());
+ if (subgroup_capabilities.quadOperationsInAllStages) {
+ print_verbose(" quad operations in all stages");
+ }
} else {
- print_verbose("- Vulkan multiview not supported");
- }
-
- print_verbose("- Vulkan subgroup:");
- print_verbose(" size: " + itos(subgroup_capabilities.size));
- print_verbose(" stages: " + subgroup_capabilities.supported_stages_desc());
- print_verbose(" supported ops: " + subgroup_capabilities.supported_operations_desc());
- if (subgroup_capabilities.quadOperationsInAllStages) {
- print_verbose(" quad operations in all stages");
+ print_verbose("- Couldn't call vkGetPhysicalDeviceProperties2");
}
- } else {
- print_verbose("- Couldn't call vkGetPhysicalDeviceProperties2");
}
return OK;
@@ -826,27 +916,40 @@ Error VulkanContext::_create_instance() {
// Initialize extensions.
{
- Error err = _initialize_extensions();
+ Error err = _initialize_instance_extensions();
if (err != OK) {
return err;
}
}
+ int enabled_extension_count = 0;
+ const char *enabled_extension_names[MAX_EXTENSIONS];
+ ERR_FAIL_COND_V(enabled_instance_extension_names.size() > MAX_EXTENSIONS, ERR_CANT_CREATE);
+ for (const CharString &extension_name : enabled_instance_extension_names) {
+ enabled_extension_names[enabled_extension_count++] = extension_name.ptr();
+ }
+
+ // We'll set application version to the Vulkan version we're developing against, even if our instance is based on
+ // an older Vulkan version, devices can still support newer versions of Vulkan.
+ // The exception is when we're on Vulkan 1.0, we should not set this to anything but 1.0.
+ // Note that this value is only used by validation layers to warn us about version issues.
+ uint32_t application_api_version = instance_api_version == VK_API_VERSION_1_0 ? VK_API_VERSION_1_0 : VK_API_VERSION_1_2;
+
CharString cs = GLOBAL_GET("application/config/name").operator String().utf8();
const VkApplicationInfo app = {
/*sType*/ VK_STRUCTURE_TYPE_APPLICATION_INFO,
/*pNext*/ nullptr,
/*pApplicationName*/ cs.get_data(),
- /*applicationVersion*/ 0,
+ /*applicationVersion*/ 0, // It would be really nice if we store a version number in project settings, say "application/config/version"
/*pEngineName*/ VERSION_NAME,
/*engineVersion*/ VK_MAKE_VERSION(VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH),
- /*apiVersion*/ VK_MAKE_VERSION(vulkan_major, vulkan_minor, 0)
+ /*apiVersion*/ application_api_version
};
VkInstanceCreateInfo inst_info{};
inst_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
inst_info.pApplicationInfo = &app;
inst_info.enabledExtensionCount = enabled_extension_count;
- inst_info.ppEnabledExtensionNames = (const char *const *)extension_names;
+ inst_info.ppEnabledExtensionNames = (const char *const *)enabled_extension_names;
if (_use_validation_layers()) {
_get_preferred_validation_layers(&inst_info.enabledLayerCount, &inst_info.ppEnabledLayerNames);
}
@@ -856,9 +959,9 @@ Error VulkanContext::_create_instance() {
* After the instance is created, we use the instance-based
* function to register the final callback.
*/
- VkDebugUtilsMessengerCreateInfoEXT dbg_messenger_create_info;
- VkDebugReportCallbackCreateInfoEXT dbg_report_callback_create_info{};
- if (enabled_debug_utils) {
+ VkDebugUtilsMessengerCreateInfoEXT dbg_messenger_create_info = {};
+ VkDebugReportCallbackCreateInfoEXT dbg_report_callback_create_info = {};
+ if (is_instance_extension_enabled(VK_EXT_DEBUG_UTILS_EXTENSION_NAME)) {
// VK_EXT_debug_utils style.
dbg_messenger_create_info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
dbg_messenger_create_info.pNext = nullptr;
@@ -871,7 +974,7 @@ Error VulkanContext::_create_instance() {
dbg_messenger_create_info.pfnUserCallback = _debug_messenger_callback;
dbg_messenger_create_info.pUserData = this;
inst_info.pNext = &dbg_messenger_create_info;
- } else if (enabled_debug_report) {
+ } else if (is_instance_extension_enabled(VK_EXT_DEBUG_REPORT_EXTENSION_NAME)) {
dbg_report_callback_create_info.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT;
dbg_report_callback_create_info.flags = VK_DEBUG_REPORT_INFORMATION_BIT_EXT |
VK_DEBUG_REPORT_WARNING_BIT_EXT |
@@ -911,7 +1014,7 @@ Error VulkanContext::_create_instance() {
volkLoadInstance(inst);
#endif
- if (enabled_debug_utils) {
+ if (is_instance_extension_enabled(VK_EXT_DEBUG_UTILS_EXTENSION_NAME)) {
// Setup VK_EXT_debug_utils function pointers always (we use them for debug labels and names).
CreateDebugUtilsMessengerEXT =
(PFN_vkCreateDebugUtilsMessengerEXT)vkGetInstanceProcAddr(inst, "vkCreateDebugUtilsMessengerEXT");
@@ -952,7 +1055,7 @@ Error VulkanContext::_create_instance() {
ERR_FAIL_V(ERR_CANT_CREATE);
break;
}
- } else if (enabled_debug_report) {
+ } else if (is_instance_extension_enabled(VK_EXT_DEBUG_REPORT_EXTENSION_NAME)) {
CreateDebugReportCallbackEXT = (PFN_vkCreateDebugReportCallbackEXT)vkGetInstanceProcAddr(inst, "vkCreateDebugReportCallbackEXT");
DebugReportMessageEXT = (PFN_vkDebugReportMessageEXT)vkGetInstanceProcAddr(inst, "vkDebugReportMessageEXT");
DestroyDebugReportCallbackEXT = (PFN_vkDestroyDebugReportCallbackEXT)vkGetInstanceProcAddr(inst, "vkDestroyDebugReportCallbackEXT");
@@ -1133,12 +1236,6 @@ Error VulkanContext::_create_physical_device(VkSurfaceKHR p_surface) {
free(physical_devices);
- // 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.
vkGetPhysicalDeviceProperties(gpu, &gpu_props);
@@ -1158,90 +1255,19 @@ Error VulkanContext::_create_physical_device(VkSurfaceKHR p_surface) {
}
}
- print_line(
- "Vulkan API " + itos(vulkan_major) + "." + itos(vulkan_minor) + "." + itos(vulkan_patch) +
- " - " + "Using Vulkan Device #" + itos(device_index) + ": " + device_vendor + " - " + device_name);
-
+ // Get device version
device_api_version = gpu_props.apiVersion;
- err = vkEnumerateDeviceExtensionProperties(gpu, nullptr, &device_extension_count, nullptr);
- ERR_FAIL_COND_V(err, ERR_CANT_CREATE);
-
- if (device_extension_count > 0) {
- VkExtensionProperties *device_extensions = (VkExtensionProperties *)malloc(sizeof(VkExtensionProperties) * device_extension_count);
- err = vkEnumerateDeviceExtensionProperties(gpu, nullptr, &device_extension_count, device_extensions);
- if (err) {
- free(device_extensions);
- ERR_FAIL_V(ERR_CANT_CREATE);
- }
-
- for (uint32_t i = 0; i < device_extension_count; i++) {
- if (!strcmp(VK_KHR_SWAPCHAIN_EXTENSION_NAME, device_extensions[i].extensionName)) {
- swapchainExtFound = 1;
- 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.
- 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)) {
- has_renderpass2_ext = true;
- 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");
- }
- }
-
- if (VK_KHR_incremental_present_enabled) {
- // Even though the user "enabled" the extension via the command
- // line, we must make sure that it's enumerated for use with the
- // device. Therefore, disable it here, and re-enable it again if
- // enumerated.
- VK_KHR_incremental_present_enabled = false;
- for (uint32_t i = 0; i < device_extension_count; i++) {
- if (!strcmp(VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME, device_extensions[i].extensionName)) {
- extension_names[enabled_extension_count++] = VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME;
- VK_KHR_incremental_present_enabled = true;
- }
- if (enabled_extension_count >= MAX_EXTENSIONS) {
- free(device_extensions);
- ERR_FAIL_V_MSG(ERR_BUG, "Enabled extension count reaches MAX_EXTENSIONS, BUG");
- }
- }
- }
+ // Output our device version
+ print_line("Vulkan API " + get_device_api_version() + " - " + "Using Vulkan Device #" + itos(device_index) + ": " + device_vendor + " - " + device_name);
- if (VK_GOOGLE_display_timing_enabled) {
- // Even though the user "enabled" the extension via the command
- // line, we must make sure that it's enumerated for use with the
- // device. Therefore, disable it here, and re-enable it again if
- // enumerated.
- VK_GOOGLE_display_timing_enabled = false;
- for (uint32_t i = 0; i < device_extension_count; i++) {
- if (!strcmp(VK_GOOGLE_DISPLAY_TIMING_EXTENSION_NAME, device_extensions[i].extensionName)) {
- extension_names[enabled_extension_count++] = VK_GOOGLE_DISPLAY_TIMING_EXTENSION_NAME;
- VK_GOOGLE_display_timing_enabled = true;
- }
- if (enabled_extension_count >= MAX_EXTENSIONS) {
- free(device_extensions);
- ERR_FAIL_V_MSG(ERR_BUG, "Enabled extension count reaches MAX_EXTENSIONS, BUG");
- }
- }
+ {
+ Error _err = _initialize_device_extensions();
+ if (_err != OK) {
+ return _err;
}
-
- free(device_extensions);
}
- ERR_FAIL_COND_V_MSG(!swapchainExtFound, ERR_CANT_CREATE,
- "vkEnumerateDeviceExtensionProperties failed to find the " VK_KHR_SWAPCHAIN_EXTENSION_NAME
- " extension.\n\nDo you have a compatible Vulkan installable client driver (ICD) installed?\n"
- "vkCreateInstance Failure");
-
// Call with nullptr data to get count.
vkGetPhysicalDeviceQueueFamilyProperties(gpu, &queue_family_count, nullptr);
ERR_FAIL_COND_V(queue_family_count == 0, ERR_CANT_CREATE);
@@ -1302,7 +1328,7 @@ Error VulkanContext::_create_device() {
};
nextptr = &shader_features;
- VkPhysicalDeviceFragmentShadingRateFeaturesKHR vrs_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;
@@ -1314,10 +1340,10 @@ Error VulkanContext::_create_device() {
nextptr = &vrs_features;
}
- VkPhysicalDeviceVulkan11Features vulkan11features;
- VkPhysicalDevice16BitStorageFeaturesKHR storage_feature;
- VkPhysicalDeviceMultiviewFeatures multiview_features;
- if (vulkan_major > 1 || vulkan_minor >= 2) {
+ VkPhysicalDeviceVulkan11Features vulkan11features = {};
+ VkPhysicalDevice16BitStorageFeaturesKHR storage_feature = {};
+ VkPhysicalDeviceMultiviewFeatures multiview_features = {};
+ if (device_api_version >= VK_API_VERSION_1_2) {
// 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;
@@ -1345,7 +1371,7 @@ Error VulkanContext::_create_device() {
storage_feature.storageInputOutput16 = storage_buffer_capabilities.storage_input_output_16;
nextptr = &storage_feature;
- if (vulkan_major == 1 && vulkan_minor == 1) {
+ if (device_api_version >= VK_API_VERSION_1_1) { // any Vulkan 1.1.x version
multiview_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES;
multiview_features.pNext = nextptr;
multiview_features.multiview = multiview_capabilities.is_supported;
@@ -1355,6 +1381,13 @@ Error VulkanContext::_create_device() {
}
}
+ uint32_t enabled_extension_count = 0;
+ const char *enabled_extension_names[MAX_EXTENSIONS];
+ ERR_FAIL_COND_V(enabled_device_extension_names.size() > MAX_EXTENSIONS, ERR_CANT_CREATE);
+ for (const CharString &extension_name : enabled_device_extension_names) {
+ enabled_extension_names[enabled_extension_count++] = extension_name.ptr();
+ }
+
VkDeviceCreateInfo sdevice = {
/*sType*/ VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
/*pNext*/ nextptr,
@@ -1364,7 +1397,7 @@ Error VulkanContext::_create_device() {
/*enabledLayerCount*/ 0,
/*ppEnabledLayerNames*/ nullptr,
/*enabledExtensionCount*/ enabled_extension_count,
- /*ppEnabledExtensionNames*/ (const char *const *)extension_names,
+ /*ppEnabledExtensionNames*/ (const char *const *)enabled_extension_names,
/*pEnabledFeatures*/ &physical_device_features, // If specific features are required, pass them in here.
};
if (separate_present_queue) {
@@ -1452,7 +1485,7 @@ Error VulkanContext::_initialize_queues(VkSurfaceKHR p_surface) {
GET_DEVICE_PROC_ADDR(device, GetSwapchainImagesKHR);
GET_DEVICE_PROC_ADDR(device, AcquireNextImageKHR);
GET_DEVICE_PROC_ADDR(device, QueuePresentKHR);
- if (VK_GOOGLE_display_timing_enabled) {
+ if (is_device_extension_enabled(VK_GOOGLE_DISPLAY_TIMING_EXTENSION_NAME)) {
GET_DEVICE_PROC_ADDR(device, GetRefreshCycleDurationGOOGLE);
GET_DEVICE_PROC_ADDR(device, GetPastPresentationTimingGOOGLE);
}
@@ -2207,7 +2240,7 @@ Error VulkanContext::swap_buffers() {
VkResult err;
#if 0
- if (VK_GOOGLE_display_timing_enabled) {
+ if (is_device_extension_enabled(VK_GOOGLE_DISPLAY_TIMING_EXTENSION_NAME)) {
// Look at what happened to previous presents, and make appropriate
// adjustments in timing.
DemoUpdateTargetIPD(demo);
@@ -2328,7 +2361,7 @@ Error VulkanContext::swap_buffers() {
}
#if 0
- if (VK_KHR_incremental_present_enabled) {
+ if (is_device_extension_enabled(VK_KHR_incremental_present_enabled)) {
// If using VK_KHR_incremental_present, we provide a hint of the region
// that contains changed content relative to the previously-presented
// image. The implementation can use this hint in order to save
@@ -2359,7 +2392,7 @@ Error VulkanContext::swap_buffers() {
#endif
#if 0
- if (VK_GOOGLE_display_timing_enabled) {
+ if (is_device_extension_enabled(VK_GOOGLE_DISPLAY_TIMING_EXTENSION_NAME)) {
VkPresentTimeGOOGLE ptime;
if (prev_desired_present_time == 0) {
// This must be the first present for this swapchain.
@@ -2389,7 +2422,7 @@ Error VulkanContext::swap_buffers() {
/*swapchainCount*/ present.swapchainCount,
/*pTimes*/ &ptime,
};
- if (VK_GOOGLE_display_timing_enabled) {
+ if (is_device_extension_enabled(VK_GOOGLE_DISPLAY_TIMING_EXTENSION_NAME)) {
present.pNext = &present_time;
}
}
@@ -2462,6 +2495,13 @@ RID VulkanContext::local_device_create() {
queues[0].pQueuePriorities = queue_priorities;
queues[0].flags = 0;
+ uint32_t enabled_extension_count = 0;
+ const char *enabled_extension_names[MAX_EXTENSIONS];
+ ERR_FAIL_COND_V(enabled_device_extension_names.size() > MAX_EXTENSIONS, RID());
+ for (const CharString &extension_name : enabled_device_extension_names) {
+ enabled_extension_names[enabled_extension_count++] = extension_name.ptr();
+ }
+
VkDeviceCreateInfo sdevice = {
/*sType =*/VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
/*pNext */ nullptr,
@@ -2471,7 +2511,7 @@ RID VulkanContext::local_device_create() {
/*enabledLayerCount */ 0,
/*ppEnabledLayerNames */ nullptr,
/*enabledExtensionCount */ enabled_extension_count,
- /*ppEnabledExtensionNames */ (const char *const *)extension_names,
+ /*ppEnabledExtensionNames */ (const char *const *)enabled_extension_names,
/*pEnabledFeatures */ &physical_device_features, // If specific features are required, pass them in here.
};
err = vkCreateDevice(gpu, &sdevice, nullptr, &ld.device);
@@ -2536,7 +2576,7 @@ void VulkanContext::local_device_free(RID p_local_device) {
}
void VulkanContext::command_begin_label(VkCommandBuffer p_command_buffer, String p_label_name, const Color p_color) {
- if (!enabled_debug_utils) {
+ if (!is_instance_extension_enabled(VK_EXT_DEBUG_UTILS_EXTENSION_NAME)) {
return;
}
@@ -2553,7 +2593,7 @@ void VulkanContext::command_begin_label(VkCommandBuffer p_command_buffer, String
}
void VulkanContext::command_insert_label(VkCommandBuffer p_command_buffer, String p_label_name, const Color p_color) {
- if (!enabled_debug_utils) {
+ if (!is_instance_extension_enabled(VK_EXT_DEBUG_UTILS_EXTENSION_NAME)) {
return;
}
CharString cs = p_label_name.utf8();
@@ -2569,14 +2609,14 @@ void VulkanContext::command_insert_label(VkCommandBuffer p_command_buffer, Strin
}
void VulkanContext::command_end_label(VkCommandBuffer p_command_buffer) {
- if (!enabled_debug_utils) {
+ if (!is_instance_extension_enabled(VK_EXT_DEBUG_UTILS_EXTENSION_NAME)) {
return;
}
CmdEndDebugUtilsLabelEXT(p_command_buffer);
}
void VulkanContext::set_object_name(VkObjectType p_object_type, uint64_t p_object_handle, String p_object_name) {
- if (!enabled_debug_utils) {
+ if (!is_instance_extension_enabled(VK_EXT_DEBUG_UTILS_EXTENSION_NAME)) {
return;
}
CharString obj_data = p_object_name.utf8();
@@ -2602,7 +2642,7 @@ RenderingDevice::DeviceType VulkanContext::get_device_type() const {
}
String VulkanContext::get_device_api_version() const {
- return vformat("%d.%d.%d", vulkan_major, vulkan_minor, vulkan_patch);
+ return vformat("%d.%d.%d", VK_API_VERSION_MAJOR(device_api_version), VK_API_VERSION_MINOR(device_api_version), VK_API_VERSION_PATCH(device_api_version));
}
String VulkanContext::get_device_pipeline_cache_uuid() const {
@@ -2637,7 +2677,7 @@ VulkanContext::~VulkanContext() {
vkDestroySemaphore(device, image_ownership_semaphores[i], nullptr);
}
}
- if (inst_initialized && enabled_debug_utils) {
+ if (inst_initialized && is_instance_extension_enabled(VK_EXT_DEBUG_UTILS_EXTENSION_NAME)) {
DestroyDebugUtilsMessengerEXT(inst, dbg_messenger, nullptr);
}
if (inst_initialized && dbg_debug_report != VK_NULL_HANDLE) {
diff --git a/drivers/vulkan/vulkan_context.h b/drivers/vulkan/vulkan_context.h
index d6a25c5cd7..f37bee72eb 100644
--- a/drivers/vulkan/vulkan_context.h
+++ b/drivers/vulkan/vulkan_context.h
@@ -34,6 +34,7 @@
#include "core/error/error_list.h"
#include "core/os/mutex.h"
#include "core/string/ustring.h"
+#include "core/templates/hash_map.h"
#include "core/templates/rb_map.h"
#include "core/templates/rid_owner.h"
#include "servers/display_server.h"
@@ -76,6 +77,8 @@ public:
Size2i min_texel_size;
Size2i max_texel_size;
+
+ Size2i texel_size; // The texel size we'll use
};
struct ShaderCapabilities {
@@ -107,10 +110,7 @@ private:
bool device_initialized = false;
bool inst_initialized = false;
- // Vulkan 1.0 doesn't return version info so we assume this by default until we know otherwise.
- uint32_t vulkan_major = 1;
- uint32_t vulkan_minor = 0;
- uint32_t vulkan_patch = 0;
+ uint32_t instance_api_version = VK_API_VERSION_1_0;
SubgroupCapabilities subgroup_capabilities;
MultiviewCapabilities multiview_capabilities;
VRSCapabilities vrs_capabilities;
@@ -182,19 +182,15 @@ private:
int command_buffer_count = 1;
// Extensions.
+ static bool instance_extensions_initialized;
+ static HashMap<CharString, bool> requested_instance_extensions;
+ HashSet<CharString> enabled_instance_extension_names;
+ static bool device_extensions_initialized;
+ static HashMap<CharString, bool> requested_device_extensions;
+ HashSet<CharString> enabled_device_extension_names;
bool VK_KHR_incremental_present_enabled = true;
bool VK_GOOGLE_display_timing_enabled = true;
- uint32_t enabled_extension_count = 0;
- const char *extension_names[MAX_EXTENSIONS];
- bool enabled_debug_utils = false;
- bool has_renderpass2_ext = false;
-
- /**
- * True if VK_EXT_debug_report extension is used. VK_EXT_debug_report is deprecated but it is
- * still used if VK_EXT_debug_utils is not available.
- */
- bool enabled_debug_report = false;
PFN_vkCreateDebugUtilsMessengerEXT CreateDebugUtilsMessengerEXT = nullptr;
PFN_vkDestroyDebugUtilsMessengerEXT DestroyDebugUtilsMessengerEXT = nullptr;
@@ -223,7 +219,8 @@ private:
VkDebugReportCallbackEXT dbg_debug_report = VK_NULL_HANDLE;
Error _obtain_vulkan_version();
- Error _initialize_extensions();
+ Error _initialize_instance_extensions();
+ Error _initialize_device_extensions();
Error _check_capabilities();
VkBool32 _check_layers(uint32_t check_count, const char *const *check_names, uint32_t layer_count, VkLayerProperties *layers);
@@ -273,11 +270,11 @@ protected:
public:
// Extension calls.
- bool supports_renderpass2() const { return has_renderpass2_ext; }
+ bool supports_renderpass2() const { return is_device_extension_enabled(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME); }
VkResult vkCreateRenderPass2KHR(VkDevice p_device, const VkRenderPassCreateInfo2 *p_create_info, const VkAllocationCallbacks *p_allocator, VkRenderPass *p_render_pass);
- uint32_t get_vulkan_major() const { return vulkan_major; };
- uint32_t get_vulkan_minor() const { return vulkan_minor; };
+ uint32_t get_vulkan_major() const { return VK_API_VERSION_MAJOR(device_api_version); };
+ uint32_t get_vulkan_minor() const { return VK_API_VERSION_MINOR(device_api_version); };
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; };
@@ -293,6 +290,16 @@ public:
static void set_vulkan_hooks(VulkanHooks *p_vulkan_hooks) { vulkan_hooks = p_vulkan_hooks; };
+ static void register_requested_instance_extension(const CharString &extension_name, bool p_required);
+ bool is_instance_extension_enabled(const CharString &extension_name) const {
+ return enabled_instance_extension_names.has(extension_name);
+ }
+
+ static void register_requested_device_extension(const CharString &extension_name, bool p_required);
+ bool is_device_extension_enabled(const CharString &extension_name) const {
+ return enabled_device_extension_names.has(extension_name);
+ }
+
void window_resize(DisplayServer::WindowID p_window_id, int p_width, int p_height);
int window_get_width(DisplayServer::WindowID p_window = 0);
int window_get_height(DisplayServer::WindowID p_window = 0);
diff --git a/editor/action_map_editor.cpp b/editor/action_map_editor.cpp
index 3b9d6c18eb..a1e4b5fde4 100644
--- a/editor/action_map_editor.cpp
+++ b/editor/action_map_editor.cpp
@@ -35,6 +35,7 @@
#include "editor/input_event_configuration_dialog.h"
#include "scene/gui/check_button.h"
#include "scene/gui/tree.h"
+#include "scene/scene_string_names.h"
static bool _is_action_name_valid(const String &p_name) {
const char32_t *cstr = p_name.get_data();
@@ -362,6 +363,8 @@ void ActionMapEditor::_bind_methods() {
ADD_SIGNAL(MethodInfo("action_removed", PropertyInfo(Variant::STRING, "name")));
ADD_SIGNAL(MethodInfo("action_renamed", PropertyInfo(Variant::STRING, "old_name"), PropertyInfo(Variant::STRING, "new_name")));
ADD_SIGNAL(MethodInfo("action_reordered", PropertyInfo(Variant::STRING, "action_name"), PropertyInfo(Variant::STRING, "relative_to"), PropertyInfo(Variant::BOOL, "before")));
+ ADD_SIGNAL(MethodInfo(SNAME("filter_focused")));
+ ADD_SIGNAL(MethodInfo(SNAME("filter_unfocused")));
}
LineEdit *ActionMapEditor::get_search_box() const {
@@ -443,7 +446,7 @@ void ActionMapEditor::update_action_list(const Vector<ActionInfo> &p_action_info
TreeItem *event_item = action_tree->create_item(action_item);
// First Column - Text
- event_item->set_text(0, event_config_dialog->get_event_text(event, true));
+ event_item->set_text(0, EventListenerLineEdit::get_event_text(event, true));
event_item->set_meta("__event", event);
event_item->set_meta("__index", evnt_idx);
@@ -492,6 +495,14 @@ void ActionMapEditor::use_external_search_box(LineEdit *p_searchbox) {
action_list_search->connect("text_changed", callable_mp(this, &ActionMapEditor::_search_term_updated));
}
+void ActionMapEditor::_on_filter_focused() {
+ emit_signal(SNAME("filter_focused"));
+}
+
+void ActionMapEditor::_on_filter_unfocused() {
+ emit_signal(SNAME("filter_unfocused"));
+}
+
ActionMapEditor::ActionMapEditor() {
// Main Vbox Container
VBoxContainer *main_vbox = memnew(VBoxContainer);
@@ -512,6 +523,8 @@ ActionMapEditor::ActionMapEditor() {
action_list_search_by_event->set_h_size_flags(Control::SIZE_EXPAND_FILL);
action_list_search_by_event->set_stretch_ratio(0.75);
action_list_search_by_event->connect("event_changed", callable_mp(this, &ActionMapEditor::_search_by_event));
+ action_list_search_by_event->connect(SceneStringNames::get_singleton()->focus_entered, callable_mp(this, &ActionMapEditor::_on_filter_focused));
+ action_list_search_by_event->connect(SceneStringNames::get_singleton()->focus_exited, callable_mp(this, &ActionMapEditor::_on_filter_unfocused));
top_hbox->add_child(action_list_search_by_event);
Button *clear_all_search = memnew(Button);
diff --git a/editor/action_map_editor.h b/editor/action_map_editor.h
index d56ee6f9eb..1908805b17 100644
--- a/editor/action_map_editor.h
+++ b/editor/action_map_editor.h
@@ -47,8 +47,8 @@ class ActionMapEditor : public Control {
public:
struct ActionInfo {
- String name = String();
- Dictionary action = Dictionary();
+ String name;
+ Dictionary action;
Ref<Texture2D> icon = Ref<Texture2D>();
bool editable = true;
@@ -67,8 +67,8 @@ private:
// Storing which action/event is currently being edited in the InputEventConfigurationDialog.
- Dictionary current_action = Dictionary();
- String current_action_name = String();
+ Dictionary current_action;
+ String current_action_name;
int current_action_event_index = -1;
// Popups
@@ -106,6 +106,9 @@ private:
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 _on_filter_focused();
+ void _on_filter_unfocused();
+
protected:
void _notification(int p_what);
static void _bind_methods();
diff --git a/editor/animation_bezier_editor.cpp b/editor/animation_bezier_editor.cpp
index 4c7ebca299..7b5a7b7046 100644
--- a/editor/animation_bezier_editor.cpp
+++ b/editor/animation_bezier_editor.cpp
@@ -32,6 +32,7 @@
#include "editor/editor_node.h"
#include "editor/editor_scale.h"
+#include "editor/editor_settings.h"
#include "editor/editor_undo_redo_manager.h"
#include "scene/gui/view_panner.h"
#include "scene/resources/text_line.h"
@@ -574,7 +575,7 @@ void AnimationBezierTrackEdit::_notification(int p_what) {
ep.point_rect.size = bezier_icon->get_size();
if (selection.has(IntPair(i, j))) {
draw_texture(selected_icon, ep.point_rect.position);
- draw_string(font, ep.point_rect.position + Vector2(8, -font->get_height(font_size) - 8), TTR("Time:") + " " + TS->format_number(rtos(Math::snapped(offset, 0.001))), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, accent);
+ draw_string(font, ep.point_rect.position + Vector2(8, -font->get_height(font_size) - 8), TTR("Time:") + " " + TS->format_number(rtos(Math::snapped(offset, 0.0001))), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, accent);
draw_string(font, ep.point_rect.position + Vector2(8, -8), TTR("Value:") + " " + TS->format_number(rtos(Math::snapped(value, 0.001))), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, accent);
} else {
Color track_color = Color(1, 1, 1, 1);
@@ -655,10 +656,6 @@ Size2 AnimationBezierTrackEdit::get_minimum_size() const {
return Vector2(1, 1);
}
-void AnimationBezierTrackEdit::set_undo_redo(Ref<EditorUndoRedoManager> p_undo_redo) {
- undo_redo = p_undo_redo;
-}
-
void AnimationBezierTrackEdit::set_timeline(AnimationTimelineEdit *p_timeline) {
timeline = p_timeline;
timeline->connect("zoom_changed", callable_mp(this, &AnimationBezierTrackEdit::_zoom_changed));
@@ -791,6 +788,7 @@ void AnimationBezierTrackEdit::_clear_selection() {
}
void AnimationBezierTrackEdit::_change_selected_keys_handle_mode(Animation::HandleMode p_mode, bool p_auto) {
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Update Selected Key Handles"));
for (SelectionSet::Element *E = selection.back(); E; E = E->prev()) {
const IntPair track_key_pair = E->get();
@@ -814,7 +812,7 @@ void AnimationBezierTrackEdit::_select_at_anim(const Ref<Animation> &p_anim, int
return;
}
- int idx = animation->track_find_key(p_track, p_pos, true);
+ int idx = animation->track_find_key(p_track, p_pos, Animation::FIND_MODE_APPROX);
ERR_FAIL_COND(idx < 0);
selection.insert(IntPair(p_track, idx));
@@ -903,11 +901,17 @@ void AnimationBezierTrackEdit::gui_input(const Ref<InputEvent> &p_event) {
}
float zoom_value = timeline->get_zoom()->get_max() - zv;
- timeline->get_zoom()->set_value(zoom_value);
- timeline->call_deferred("set_value", minimum_time);
+ if (Math::is_finite(minimum_time) && Math::is_finite(maximum_time) && maximum_time - minimum_time > CMP_EPSILON) {
+ timeline->get_zoom()->set_value(zoom_value);
+ timeline->call_deferred("set_value", minimum_time);
+ }
- v_scroll = (maximum_value + minimum_value) / 2.0;
- v_zoom = (maximum_value - minimum_value) / ((get_size().height - timeline->get_size().height) * 0.9);
+ if (Math::is_finite(minimum_value) && Math::is_finite(maximum_value)) {
+ v_scroll = (maximum_value + minimum_value) / 2.0;
+ if (maximum_value - minimum_value > CMP_EPSILON) {
+ v_zoom = (maximum_value - minimum_value) / ((get_size().height - timeline->get_size().height) * 0.9);
+ }
+ }
queue_redraw();
accept_event();
@@ -938,9 +942,7 @@ void AnimationBezierTrackEdit::gui_input(const Ref<InputEvent> &p_event) {
Vector2 popup_pos = get_screen_position() + mb->get_position();
menu->clear();
- if (!locked_tracks.has(selected_track) || locked_tracks.has(selected_track)) {
- menu->add_icon_item(bezier_icon, TTR("Insert Key Here"), MENU_KEY_INSERT);
- }
+ menu->add_icon_item(bezier_icon, TTR("Insert Key Here"), MENU_KEY_INSERT);
if (selection.size()) {
menu->add_separator();
menu->add_icon_item(get_theme_icon(SNAME("Duplicate"), SNAME("EditorIcons")), TTR("Duplicate Selected Key(s)"), MENU_KEY_DUPLICATE);
@@ -983,6 +985,7 @@ void AnimationBezierTrackEdit::gui_input(const Ref<InputEvent> &p_event) {
if (I.value.has_point(mb->get_position())) {
if (I.key == REMOVE_ICON) {
if (!read_only) {
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action("Remove Bezier Track");
undo_redo->add_do_method(this, "_update_locked_tracks_after", track);
@@ -1165,17 +1168,18 @@ void AnimationBezierTrackEdit::gui_input(const Ref<InputEvent> &p_event) {
new_point[4] = 0;
real_t time = ((mb->get_position().x - limit) / timeline->get_zoom_scale()) + timeline->get_value();
- while (animation->track_find_key(selected_track, time, true) != -1) {
- time += 0.001;
+ while (animation->track_find_key(selected_track, time, Animation::FIND_MODE_APPROX) != -1) {
+ time += 0.0001;
}
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Add Bezier Point"));
undo_redo->add_do_method(animation.ptr(), "bezier_track_insert_key", selected_track, time, new_point);
undo_redo->add_undo_method(animation.ptr(), "track_remove_key_at_time", selected_track, time);
undo_redo->commit_action();
//then attempt to move
- int index = animation->track_find_key(selected_track, time, true);
+ int index = animation->track_find_key(selected_track, time, Animation::FIND_MODE_APPROX);
ERR_FAIL_COND(index == -1);
_clear_selection();
selection.insert(IntPair(selected_track, index));
@@ -1266,6 +1270,7 @@ void AnimationBezierTrackEdit::gui_input(const Ref<InputEvent> &p_event) {
if (moving_selection) {
//combit it
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Move Bezier Points"));
List<AnimMoveRestore> to_restore;
@@ -1278,7 +1283,7 @@ void AnimationBezierTrackEdit::gui_input(const Ref<InputEvent> &p_event) {
for (SelectionSet::Element *E = selection.back(); E; E = E->prev()) {
real_t newtime = editor->snap_time(animation->track_get_key_time(E->get().first, E->get().second) + moving_selection_offset.x);
- int idx = animation->track_find_key(E->get().first, newtime, true);
+ int idx = animation->track_find_key(E->get().first, newtime, Animation::FIND_MODE_APPROX);
if (idx == -1) {
continue;
}
@@ -1466,6 +1471,7 @@ void AnimationBezierTrackEdit::gui_input(const Ref<InputEvent> &p_event) {
if ((moving_handle == -1 || moving_handle == 1) && mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == MouseButton::LEFT) {
if (!read_only) {
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Move Bezier Points"));
if (moving_handle == -1) {
real_t ratio = timeline->get_zoom_scale() * v_zoom;
@@ -1533,10 +1539,11 @@ void AnimationBezierTrackEdit::_menu_selected(int p_index) {
real_t time = ((menu_insert_key.x - limit) / timeline->get_zoom_scale()) + timeline->get_value();
- while (animation->track_find_key(selected_track, time, true) != -1) {
+ while (animation->track_find_key(selected_track, time, Animation::FIND_MODE_APPROX) != -1) {
time += 0.001;
}
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Add Bezier Point"));
undo_redo->add_do_method(animation.ptr(), "track_insert_key", selected_track, time, new_point);
undo_redo->add_undo_method(animation.ptr(), "track_remove_key_at_time", selected_track, time);
@@ -1584,14 +1591,15 @@ void AnimationBezierTrackEdit::duplicate_selection() {
}
}
- undo_redo->create_action(TTR("Anim Duplicate Keys"));
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
+ undo_redo->create_action(TTR("Animation Duplicate Keys"));
List<Pair<int, real_t>> new_selection_values;
for (SelectionSet::Element *E = selection.back(); E; E = E->prev()) {
real_t t = animation->track_get_key_time(E->get().first, E->get().second);
real_t dst_time = t + (timeline->get_play_position() - top_time);
- int existing_idx = animation->track_find_key(E->get().first, dst_time, true);
+ int existing_idx = animation->track_find_key(E->get().first, dst_time, Animation::FIND_MODE_APPROX);
undo_redo->add_do_method(animation.ptr(), "track_insert_key", E->get().first, dst_time, animation->track_get_key_value(E->get().first, E->get().second), animation->track_get_key_transition(E->get().first, E->get().second));
undo_redo->add_undo_method(animation.ptr(), "track_remove_key_at_time", E->get().first, dst_time);
@@ -1615,7 +1623,7 @@ void AnimationBezierTrackEdit::duplicate_selection() {
int track = E.first;
real_t time = E.second;
- int existing_idx = animation->track_find_key(track, time, true);
+ int existing_idx = animation->track_find_key(track, time, Animation::FIND_MODE_APPROX);
if (existing_idx == -1) {
continue;
@@ -1629,7 +1637,8 @@ void AnimationBezierTrackEdit::duplicate_selection() {
void AnimationBezierTrackEdit::delete_selection() {
if (selection.size()) {
- undo_redo->create_action(TTR("Anim Delete Keys"));
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
+ undo_redo->create_action(TTR("Animation Delete Keys"));
for (SelectionSet::Element *E = selection.back(); E; E = E->prev()) {
undo_redo->add_do_method(animation.ptr(), "track_remove_key", E->get().first, E->get().second);
diff --git a/editor/animation_bezier_editor.h b/editor/animation_bezier_editor.h
index beb7a5e9c6..8f03787429 100644
--- a/editor/animation_bezier_editor.h
+++ b/editor/animation_bezier_editor.h
@@ -34,7 +34,6 @@
#include "animation_track_editor.h"
#include "core/templates/hashfuncs.h"
-class EditorUndoRedoManager;
class ViewPanner;
class AnimationBezierTrackEdit : public Control {
@@ -53,7 +52,6 @@ class AnimationBezierTrackEdit : public Control {
};
AnimationTimelineEdit *timeline = nullptr;
- Ref<EditorUndoRedoManager> undo_redo;
Node *root = nullptr;
Control *play_position = nullptr; //separate control used to draw so updates for only position changed are much faster
real_t play_position_pos = 0;
@@ -197,7 +195,6 @@ public:
void set_animation_and_track(const Ref<Animation> &p_animation, int p_track, bool p_read_only);
virtual Size2 get_minimum_size() const override;
- void set_undo_redo(Ref<EditorUndoRedoManager> p_undo_redo);
void set_timeline(AnimationTimelineEdit *p_timeline);
void set_editor(AnimationTrackEditor *p_editor);
void set_root(Node *p_root);
diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp
index 44ecda103e..74e0db967d 100644
--- a/editor/animation_track_editor.cpp
+++ b/editor/animation_track_editor.cpp
@@ -35,1362 +35,1195 @@
#include "editor/animation_bezier_editor.h"
#include "editor/editor_node.h"
#include "editor/editor_scale.h"
+#include "editor/editor_settings.h"
#include "editor/editor_undo_redo_manager.h"
+#include "editor/inspector_dock.h"
#include "editor/plugins/animation_player_editor_plugin.h"
#include "scene/animation/animation_player.h"
#include "scene/animation/tween.h"
+#include "scene/gui/grid_container.h"
#include "scene/gui/separator.h"
#include "scene/gui/view_panner.h"
#include "scene/main/window.h"
#include "scene/scene_string_names.h"
#include "servers/audio/audio_stream.h"
-class AnimationTrackKeyEdit : public Object {
- GDCLASS(AnimationTrackKeyEdit, Object);
-
-public:
- bool setting = false;
- bool animation_read_only = false;
+void AnimationTrackKeyEdit::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("_update_obj"), &AnimationTrackKeyEdit::_update_obj);
+ ClassDB::bind_method(D_METHOD("_key_ofs_changed"), &AnimationTrackKeyEdit::_key_ofs_changed);
+ ClassDB::bind_method(D_METHOD("_hide_script_from_inspector"), &AnimationTrackKeyEdit::_hide_script_from_inspector);
+ ClassDB::bind_method(D_METHOD("_hide_metadata_from_inspector"), &AnimationTrackKeyEdit::_hide_metadata_from_inspector);
+ ClassDB::bind_method(D_METHOD("get_root_path"), &AnimationTrackKeyEdit::get_root_path);
+ ClassDB::bind_method(D_METHOD("_dont_undo_redo"), &AnimationTrackKeyEdit::_dont_undo_redo);
+ ClassDB::bind_method(D_METHOD("_is_read_only"), &AnimationTrackKeyEdit::_is_read_only);
+}
- bool _hide_script_from_inspector() { return true; }
- bool _hide_metadata_from_inspector() { return true; }
- bool _dont_undo_redo() { return true; }
+void AnimationTrackKeyEdit::_fix_node_path(Variant &value) {
+ NodePath np = value;
- bool _is_read_only() {
- return animation_read_only;
+ if (np == NodePath()) {
+ return;
}
- static void _bind_methods() {
- ClassDB::bind_method(D_METHOD("_update_obj"), &AnimationTrackKeyEdit::_update_obj);
- ClassDB::bind_method(D_METHOD("_key_ofs_changed"), &AnimationTrackKeyEdit::_key_ofs_changed);
- ClassDB::bind_method(D_METHOD("_hide_script_from_inspector"), &AnimationTrackKeyEdit::_hide_script_from_inspector);
- ClassDB::bind_method(D_METHOD("_hide_metadata_from_inspector"), &AnimationTrackKeyEdit::_hide_metadata_from_inspector);
- ClassDB::bind_method(D_METHOD("get_root_path"), &AnimationTrackKeyEdit::get_root_path);
- ClassDB::bind_method(D_METHOD("_dont_undo_redo"), &AnimationTrackKeyEdit::_dont_undo_redo);
- ClassDB::bind_method(D_METHOD("_is_read_only"), &AnimationTrackKeyEdit::_is_read_only);
- }
+ Node *root = EditorNode::get_singleton()->get_tree()->get_root();
- void _fix_node_path(Variant &value) {
- NodePath np = value;
+ Node *np_node = root->get_node(np);
+ ERR_FAIL_COND(!np_node);
- if (np == NodePath()) {
- return;
- }
+ Node *edited_node = root->get_node(base);
+ ERR_FAIL_COND(!edited_node);
- Node *root = EditorNode::get_singleton()->get_tree()->get_root();
+ value = edited_node->get_path_to(np_node);
+}
- Node *np_node = root->get_node(np);
- ERR_FAIL_COND(!np_node);
+void AnimationTrackKeyEdit::_update_obj(const Ref<Animation> &p_anim) {
+ if (setting || animation != p_anim) {
+ return;
+ }
- Node *edited_node = root->get_node(base);
- ERR_FAIL_COND(!edited_node);
+ notify_change();
+}
- value = edited_node->get_path_to(np_node);
+void AnimationTrackKeyEdit::_key_ofs_changed(const Ref<Animation> &p_anim, float from, float to) {
+ if (animation != p_anim || from != key_ofs) {
+ return;
}
- void _update_obj(const Ref<Animation> &p_anim) {
- if (setting || animation != p_anim) {
- return;
- }
+ key_ofs = to;
- notify_change();
+ if (setting) {
+ return;
}
- void _key_ofs_changed(const Ref<Animation> &p_anim, float from, float to) {
- if (animation != p_anim || from != key_ofs) {
- return;
- }
+ notify_change();
+}
- key_ofs = to;
+bool AnimationTrackKeyEdit::_set(const StringName &p_name, const Variant &p_value) {
+ int key = animation->track_find_key(track, key_ofs, Animation::FIND_MODE_APPROX);
+ ERR_FAIL_COND_V(key == -1, false);
- if (setting) {
- return;
- }
+ String name = p_name;
+ if (name == "easing") {
+ float val = p_value;
+ float prev_val = animation->track_get_key_transition(track, key);
+ setting = true;
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
+ undo_redo->create_action(TTR("Animation Change Transition"), UndoRedo::MERGE_ENDS);
+ undo_redo->add_do_method(animation.ptr(), "track_set_key_transition", track, key, val);
+ undo_redo->add_undo_method(animation.ptr(), "track_set_key_transition", track, key, prev_val);
+ undo_redo->add_do_method(this, "_update_obj", animation);
+ undo_redo->add_undo_method(this, "_update_obj", animation);
+ undo_redo->commit_action();
- notify_change();
+ setting = false;
+ return true;
}
- bool _set(const StringName &p_name, const Variant &p_value) {
- int key = animation->track_find_key(track, key_ofs, true);
- ERR_FAIL_COND_V(key == -1, false);
-
- String name = p_name;
- if (name == "time" || name == "frame") {
- float new_time = p_value;
-
- if (name == "frame") {
- float fps = animation->get_step();
- if (fps > 0) {
- fps = 1.0 / fps;
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
+ switch (animation->track_get_type(track)) {
+ case Animation::TYPE_POSITION_3D:
+ case Animation::TYPE_ROTATION_3D:
+ case Animation::TYPE_SCALE_3D: {
+ if (name == "position" || name == "rotation" || name == "scale") {
+ Variant old = animation->track_get_key_value(track, key);
+ setting = true;
+ String chan;
+ switch (animation->track_get_type(track)) {
+ case Animation::TYPE_POSITION_3D:
+ chan = "Position3D";
+ break;
+ case Animation::TYPE_ROTATION_3D:
+ chan = "Rotation3D";
+ break;
+ case Animation::TYPE_SCALE_3D:
+ chan = "Scale3D";
+ break;
+ default: {
+ }
}
- new_time /= fps;
- }
- if (new_time == key_ofs) {
+ undo_redo->create_action(vformat(TTR("Animation Change %s"), chan));
+ undo_redo->add_do_method(animation.ptr(), "track_set_key_value", track, key, p_value);
+ undo_redo->add_undo_method(animation.ptr(), "track_set_key_value", track, key, old);
+ undo_redo->add_do_method(this, "_update_obj", animation);
+ undo_redo->add_undo_method(this, "_update_obj", animation);
+ undo_redo->commit_action();
+
+ setting = false;
return true;
}
- int existing = animation->track_find_key(track, new_time, true);
+ } break;
+ case Animation::TYPE_BLEND_SHAPE:
+ case Animation::TYPE_VALUE: {
+ if (name == "value") {
+ Variant value = p_value;
- setting = true;
- undo_redo->create_action(TTR("Anim Change Keyframe Time"), UndoRedo::MERGE_ENDS);
+ if (value.get_type() == Variant::NODE_PATH) {
+ _fix_node_path(value);
+ }
- Variant val = animation->track_get_key_value(track, key);
- float trans = animation->track_get_key_transition(track, key);
+ setting = true;
+ undo_redo->create_action(TTR("Animation Change Keyframe Value"), UndoRedo::MERGE_ENDS);
+ Variant prev = animation->track_get_key_value(track, key);
+ undo_redo->add_do_method(animation.ptr(), "track_set_key_value", track, key, value);
+ undo_redo->add_undo_method(animation.ptr(), "track_set_key_value", track, key, prev);
+ undo_redo->add_do_method(this, "_update_obj", animation);
+ undo_redo->add_undo_method(this, "_update_obj", animation);
+ undo_redo->commit_action();
- undo_redo->add_do_method(animation.ptr(), "track_remove_key", track, key);
- undo_redo->add_do_method(animation.ptr(), "track_insert_key", track, new_time, val, trans);
- undo_redo->add_do_method(this, "_key_ofs_changed", animation, key_ofs, new_time);
- undo_redo->add_undo_method(animation.ptr(), "track_remove_key_at_time", track, new_time);
- undo_redo->add_undo_method(animation.ptr(), "track_insert_key", track, key_ofs, val, trans);
- undo_redo->add_undo_method(this, "_key_ofs_changed", animation, new_time, key_ofs);
+ setting = false;
+ return true;
+ }
+ } break;
+ case Animation::TYPE_METHOD: {
+ Dictionary d_old = animation->track_get_key_value(track, key);
+ Dictionary d_new = d_old.duplicate();
+
+ bool change_notify_deserved = false;
+ bool mergeable = false;
+
+ if (name == "name") {
+ d_new["method"] = p_value;
+ } else if (name == "arg_count") {
+ Vector<Variant> args = d_old["args"];
+ args.resize(p_value);
+ d_new["args"] = args;
+ change_notify_deserved = true;
+ } else if (name.begins_with("args/")) {
+ Vector<Variant> args = d_old["args"];
+ int idx = name.get_slice("/", 1).to_int();
+ ERR_FAIL_INDEX_V(idx, args.size(), false);
+
+ String what = name.get_slice("/", 2);
+ if (what == "type") {
+ Variant::Type t = Variant::Type(int(p_value));
+
+ if (t != args[idx].get_type()) {
+ Callable::CallError err;
+ if (Variant::can_convert(args[idx].get_type(), t)) {
+ Variant old = args[idx];
+ Variant *ptrs[1] = { &old };
+ Variant::construct(t, args.write[idx], (const Variant **)ptrs, 1, err);
+ } else {
+ Variant::construct(t, args.write[idx], nullptr, 0, err);
+ }
+ change_notify_deserved = true;
+ d_new["args"] = args;
+ }
+ } else if (what == "value") {
+ Variant value = p_value;
+ if (value.get_type() == Variant::NODE_PATH) {
+ _fix_node_path(value);
+ }
- if (existing != -1) {
- Variant v = animation->track_get_key_value(track, existing);
- trans = animation->track_get_key_transition(track, existing);
- undo_redo->add_undo_method(animation.ptr(), "track_insert_key", track, new_time, v, trans);
+ args.write[idx] = value;
+ d_new["args"] = args;
+ mergeable = true;
+ }
}
- undo_redo->commit_action();
- setting = false;
- return true;
- }
+ if (mergeable) {
+ undo_redo->create_action(TTR("Animation Change Call"), UndoRedo::MERGE_ENDS);
+ } else {
+ undo_redo->create_action(TTR("Animation Change Call"));
+ }
- if (name == "easing") {
- float val = p_value;
- float prev_val = animation->track_get_key_transition(track, key);
setting = true;
- undo_redo->create_action(TTR("Anim Change Transition"), UndoRedo::MERGE_ENDS);
- undo_redo->add_do_method(animation.ptr(), "track_set_key_transition", track, key, val);
- undo_redo->add_undo_method(animation.ptr(), "track_set_key_transition", track, key, prev_val);
+ undo_redo->add_do_method(animation.ptr(), "track_set_key_value", track, key, d_new);
+ undo_redo->add_undo_method(animation.ptr(), "track_set_key_value", track, key, d_old);
undo_redo->add_do_method(this, "_update_obj", animation);
undo_redo->add_undo_method(this, "_update_obj", animation);
undo_redo->commit_action();
setting = false;
+ if (change_notify_deserved) {
+ notify_change();
+ }
return true;
- }
-
- switch (animation->track_get_type(track)) {
- case Animation::TYPE_POSITION_3D:
- case Animation::TYPE_ROTATION_3D:
- case Animation::TYPE_SCALE_3D: {
- if (name == "position" || name == "rotation" || name == "scale") {
- Variant old = animation->track_get_key_value(track, key);
- setting = true;
- String chan;
- switch (animation->track_get_type(track)) {
- case Animation::TYPE_POSITION_3D:
- chan = "Position3D";
- break;
- case Animation::TYPE_ROTATION_3D:
- chan = "Rotation3D";
- break;
- case Animation::TYPE_SCALE_3D:
- chan = "Scale3D";
- break;
- default: {
- }
- }
-
- undo_redo->create_action(vformat(TTR("Anim Change %s"), chan));
- undo_redo->add_do_method(animation.ptr(), "track_set_key_value", track, key, p_value);
- undo_redo->add_undo_method(animation.ptr(), "track_set_key_value", track, key, old);
- undo_redo->add_do_method(this, "_update_obj", animation);
- undo_redo->add_undo_method(this, "_update_obj", animation);
- undo_redo->commit_action();
+ } break;
+ case Animation::TYPE_BEZIER: {
+ if (name == "value") {
+ const Variant &value = p_value;
- setting = false;
- return true;
- }
+ setting = true;
+ undo_redo->create_action(TTR("Animation Change Keyframe Value"), UndoRedo::MERGE_ENDS);
+ float prev = animation->bezier_track_get_key_value(track, key);
+ undo_redo->add_do_method(animation.ptr(), "bezier_track_set_key_value", track, key, value);
+ undo_redo->add_undo_method(animation.ptr(), "bezier_track_set_key_value", track, key, prev);
+ undo_redo->add_do_method(this, "_update_obj", animation);
+ undo_redo->add_undo_method(this, "_update_obj", animation);
+ undo_redo->commit_action();
- } break;
- case Animation::TYPE_BLEND_SHAPE:
- case Animation::TYPE_VALUE: {
- if (name == "value") {
- Variant value = p_value;
+ setting = false;
+ return true;
+ }
- if (value.get_type() == Variant::NODE_PATH) {
- _fix_node_path(value);
- }
+ if (name == "in_handle") {
+ const Variant &value = p_value;
- setting = true;
- undo_redo->create_action(TTR("Anim Change Keyframe Value"), UndoRedo::MERGE_ENDS);
- Variant prev = animation->track_get_key_value(track, key);
- undo_redo->add_do_method(animation.ptr(), "track_set_key_value", track, key, value);
- undo_redo->add_undo_method(animation.ptr(), "track_set_key_value", track, key, prev);
- undo_redo->add_do_method(this, "_update_obj", animation);
- undo_redo->add_undo_method(this, "_update_obj", animation);
- undo_redo->commit_action();
+ setting = true;
+ undo_redo->create_action(TTR("Animation Change Keyframe Value"), UndoRedo::MERGE_ENDS);
+ Vector2 prev = animation->bezier_track_get_key_in_handle(track, key);
+ undo_redo->add_do_method(animation.ptr(), "bezier_track_set_key_in_handle", track, key, value);
+ undo_redo->add_undo_method(animation.ptr(), "bezier_track_set_key_in_handle", track, key, prev);
+ undo_redo->add_do_method(this, "_update_obj", animation);
+ undo_redo->add_undo_method(this, "_update_obj", animation);
+ undo_redo->commit_action();
- setting = false;
- return true;
- }
- } break;
- case Animation::TYPE_METHOD: {
- Dictionary d_old = animation->track_get_key_value(track, key);
- Dictionary d_new = d_old.duplicate();
+ setting = false;
+ return true;
+ }
- bool change_notify_deserved = false;
- bool mergeable = false;
+ if (name == "out_handle") {
+ const Variant &value = p_value;
- if (name == "name") {
- d_new["method"] = p_value;
- } else if (name == "arg_count") {
- Vector<Variant> args = d_old["args"];
- args.resize(p_value);
- d_new["args"] = args;
- change_notify_deserved = true;
- } else if (name.begins_with("args/")) {
- Vector<Variant> args = d_old["args"];
- int idx = name.get_slice("/", 1).to_int();
- ERR_FAIL_INDEX_V(idx, args.size(), false);
-
- String what = name.get_slice("/", 2);
- if (what == "type") {
- Variant::Type t = Variant::Type(int(p_value));
-
- if (t != args[idx].get_type()) {
- Callable::CallError err;
- if (Variant::can_convert(args[idx].get_type(), t)) {
- Variant old = args[idx];
- Variant *ptrs[1] = { &old };
- Variant::construct(t, args.write[idx], (const Variant **)ptrs, 1, err);
- } else {
- Variant::construct(t, args.write[idx], nullptr, 0, err);
- }
- change_notify_deserved = true;
- d_new["args"] = args;
- }
- } else if (what == "value") {
- Variant value = p_value;
- if (value.get_type() == Variant::NODE_PATH) {
- _fix_node_path(value);
- }
+ setting = true;
+ undo_redo->create_action(TTR("Animation Change Keyframe Value"), UndoRedo::MERGE_ENDS);
+ Vector2 prev = animation->bezier_track_get_key_out_handle(track, key);
+ undo_redo->add_do_method(animation.ptr(), "bezier_track_set_key_out_handle", track, key, value);
+ undo_redo->add_undo_method(animation.ptr(), "bezier_track_set_key_out_handle", track, key, prev);
+ undo_redo->add_do_method(this, "_update_obj", animation);
+ undo_redo->add_undo_method(this, "_update_obj", animation);
+ undo_redo->commit_action();
- args.write[idx] = value;
- d_new["args"] = args;
- mergeable = true;
- }
- }
+ setting = false;
+ return true;
+ }
- if (mergeable) {
- undo_redo->create_action(TTR("Anim Change Call"), UndoRedo::MERGE_ENDS);
- } else {
- undo_redo->create_action(TTR("Anim Change Call"));
- }
+ if (name == "handle_mode") {
+ const Variant &value = p_value;
setting = true;
- undo_redo->add_do_method(animation.ptr(), "track_set_key_value", track, key, d_new);
- undo_redo->add_undo_method(animation.ptr(), "track_set_key_value", track, key, d_old);
+ undo_redo->create_action(TTR("Animation Change Keyframe Value"), UndoRedo::MERGE_ENDS);
+ int prev = animation->bezier_track_get_key_handle_mode(track, key);
+ undo_redo->add_do_method(this, "_bezier_track_set_key_handle_mode", animation.ptr(), track, key, value);
+ undo_redo->add_undo_method(this, "_bezier_track_set_key_handle_mode", animation.ptr(), track, key, prev);
undo_redo->add_do_method(this, "_update_obj", animation);
undo_redo->add_undo_method(this, "_update_obj", animation);
undo_redo->commit_action();
setting = false;
- if (change_notify_deserved) {
- notify_change();
- }
return true;
- } break;
- case Animation::TYPE_BEZIER: {
- if (name == "value") {
- const Variant &value = p_value;
-
- setting = true;
- undo_redo->create_action(TTR("Anim Change Keyframe Value"), UndoRedo::MERGE_ENDS);
- float prev = animation->bezier_track_get_key_value(track, key);
- undo_redo->add_do_method(animation.ptr(), "bezier_track_set_key_value", track, key, value);
- undo_redo->add_undo_method(animation.ptr(), "bezier_track_set_key_value", track, key, prev);
- undo_redo->add_do_method(this, "_update_obj", animation);
- undo_redo->add_undo_method(this, "_update_obj", animation);
- undo_redo->commit_action();
-
- setting = false;
- return true;
- }
+ }
+ } break;
+ case Animation::TYPE_AUDIO: {
+ if (name == "stream") {
+ Ref<AudioStream> stream = p_value;
- if (name == "in_handle") {
- const Variant &value = p_value;
+ setting = true;
+ undo_redo->create_action(TTR("Animation Change Keyframe Value"), UndoRedo::MERGE_ENDS);
+ Ref<Resource> prev = animation->audio_track_get_key_stream(track, key);
+ undo_redo->add_do_method(animation.ptr(), "audio_track_set_key_stream", track, key, stream);
+ undo_redo->add_undo_method(animation.ptr(), "audio_track_set_key_stream", track, key, prev);
+ undo_redo->add_do_method(this, "_update_obj", animation);
+ undo_redo->add_undo_method(this, "_update_obj", animation);
+ undo_redo->commit_action();
- setting = true;
- undo_redo->create_action(TTR("Anim Change Keyframe Value"), UndoRedo::MERGE_ENDS);
- Vector2 prev = animation->bezier_track_get_key_in_handle(track, key);
- undo_redo->add_do_method(animation.ptr(), "bezier_track_set_key_in_handle", track, key, value);
- undo_redo->add_undo_method(animation.ptr(), "bezier_track_set_key_in_handle", track, key, prev);
- undo_redo->add_do_method(this, "_update_obj", animation);
- undo_redo->add_undo_method(this, "_update_obj", animation);
- undo_redo->commit_action();
-
- setting = false;
- return true;
- }
+ setting = false;
+ return true;
+ }
- if (name == "out_handle") {
- const Variant &value = p_value;
+ if (name == "start_offset") {
+ float value = p_value;
- setting = true;
- undo_redo->create_action(TTR("Anim Change Keyframe Value"), UndoRedo::MERGE_ENDS);
- Vector2 prev = animation->bezier_track_get_key_out_handle(track, key);
- undo_redo->add_do_method(animation.ptr(), "bezier_track_set_key_out_handle", track, key, value);
- undo_redo->add_undo_method(animation.ptr(), "bezier_track_set_key_out_handle", track, key, prev);
- undo_redo->add_do_method(this, "_update_obj", animation);
- undo_redo->add_undo_method(this, "_update_obj", animation);
- undo_redo->commit_action();
-
- setting = false;
- return true;
- }
+ setting = true;
+ undo_redo->create_action(TTR("Animation Change Keyframe Value"), UndoRedo::MERGE_ENDS);
+ float prev = animation->audio_track_get_key_start_offset(track, key);
+ undo_redo->add_do_method(animation.ptr(), "audio_track_set_key_start_offset", track, key, value);
+ undo_redo->add_undo_method(animation.ptr(), "audio_track_set_key_start_offset", track, key, prev);
+ undo_redo->add_do_method(this, "_update_obj", animation);
+ undo_redo->add_undo_method(this, "_update_obj", animation);
+ undo_redo->commit_action();
- if (name == "handle_mode") {
- const Variant &value = p_value;
+ setting = false;
+ return true;
+ }
- setting = true;
- undo_redo->create_action(TTR("Anim Change Keyframe Value"), UndoRedo::MERGE_ENDS);
- int prev = animation->bezier_track_get_key_handle_mode(track, key);
- undo_redo->add_do_method(this, "_bezier_track_set_key_handle_mode", animation.ptr(), track, key, value);
- undo_redo->add_undo_method(this, "_bezier_track_set_key_handle_mode", animation.ptr(), track, key, prev);
- undo_redo->add_do_method(this, "_update_obj", animation);
- undo_redo->add_undo_method(this, "_update_obj", animation);
- undo_redo->commit_action();
-
- setting = false;
- return true;
- }
- } break;
- case Animation::TYPE_AUDIO: {
- if (name == "stream") {
- Ref<AudioStream> stream = p_value;
+ if (name == "end_offset") {
+ float value = p_value;
- setting = true;
- undo_redo->create_action(TTR("Anim Change Keyframe Value"), UndoRedo::MERGE_ENDS);
- Ref<Resource> prev = animation->audio_track_get_key_stream(track, key);
- undo_redo->add_do_method(animation.ptr(), "audio_track_set_key_stream", track, key, stream);
- undo_redo->add_undo_method(animation.ptr(), "audio_track_set_key_stream", track, key, prev);
- undo_redo->add_do_method(this, "_update_obj", animation);
- undo_redo->add_undo_method(this, "_update_obj", animation);
- undo_redo->commit_action();
-
- setting = false;
- return true;
- }
+ setting = true;
+ undo_redo->create_action(TTR("Animation Change Keyframe Value"), UndoRedo::MERGE_ENDS);
+ float prev = animation->audio_track_get_key_end_offset(track, key);
+ undo_redo->add_do_method(animation.ptr(), "audio_track_set_key_end_offset", track, key, value);
+ undo_redo->add_undo_method(animation.ptr(), "audio_track_set_key_end_offset", track, key, prev);
+ undo_redo->add_do_method(this, "_update_obj", animation);
+ undo_redo->add_undo_method(this, "_update_obj", animation);
+ undo_redo->commit_action();
- if (name == "start_offset") {
- float value = p_value;
+ setting = false;
+ return true;
+ }
+ } break;
+ case Animation::TYPE_ANIMATION: {
+ if (name == "animation") {
+ StringName anim_name = p_value;
- setting = true;
- undo_redo->create_action(TTR("Anim Change Keyframe Value"), UndoRedo::MERGE_ENDS);
- float prev = animation->audio_track_get_key_start_offset(track, key);
- undo_redo->add_do_method(animation.ptr(), "audio_track_set_key_start_offset", track, key, value);
- undo_redo->add_undo_method(animation.ptr(), "audio_track_set_key_start_offset", track, key, prev);
- undo_redo->add_do_method(this, "_update_obj", animation);
- undo_redo->add_undo_method(this, "_update_obj", animation);
- undo_redo->commit_action();
-
- setting = false;
- return true;
- }
+ setting = true;
+ undo_redo->create_action(TTR("Animation Change Keyframe Value"), UndoRedo::MERGE_ENDS);
+ StringName prev = animation->animation_track_get_key_animation(track, key);
+ undo_redo->add_do_method(animation.ptr(), "animation_track_set_key_animation", track, key, anim_name);
+ undo_redo->add_undo_method(animation.ptr(), "animation_track_set_key_animation", track, key, prev);
+ undo_redo->add_do_method(this, "_update_obj", animation);
+ undo_redo->add_undo_method(this, "_update_obj", animation);
+ undo_redo->commit_action();
- if (name == "end_offset") {
- float value = p_value;
+ setting = false;
+ return true;
+ }
+ } break;
+ }
- setting = true;
- undo_redo->create_action(TTR("Anim Change Keyframe Value"), UndoRedo::MERGE_ENDS);
- float prev = animation->audio_track_get_key_end_offset(track, key);
- undo_redo->add_do_method(animation.ptr(), "audio_track_set_key_end_offset", track, key, value);
- undo_redo->add_undo_method(animation.ptr(), "audio_track_set_key_end_offset", track, key, prev);
- undo_redo->add_do_method(this, "_update_obj", animation);
- undo_redo->add_undo_method(this, "_update_obj", animation);
- undo_redo->commit_action();
-
- setting = false;
- return true;
- }
- } break;
- case Animation::TYPE_ANIMATION: {
- if (name == "animation") {
- StringName anim_name = p_value;
+ return false;
+}
- setting = true;
- undo_redo->create_action(TTR("Anim Change Keyframe Value"), UndoRedo::MERGE_ENDS);
- StringName prev = animation->animation_track_get_key_animation(track, key);
- undo_redo->add_do_method(animation.ptr(), "animation_track_set_key_animation", track, key, anim_name);
- undo_redo->add_undo_method(animation.ptr(), "animation_track_set_key_animation", track, key, prev);
- undo_redo->add_do_method(this, "_update_obj", animation);
- undo_redo->add_undo_method(this, "_update_obj", animation);
- undo_redo->commit_action();
-
- setting = false;
- return true;
- }
- } break;
- }
+bool AnimationTrackKeyEdit::_get(const StringName &p_name, Variant &r_ret) const {
+ int key = animation->track_find_key(track, key_ofs, Animation::FIND_MODE_APPROX);
+ ERR_FAIL_COND_V(key == -1, false);
- return false;
+ String name = p_name;
+ if (name == "easing") {
+ r_ret = animation->track_get_key_transition(track, key);
+ return true;
}
- bool _get(const StringName &p_name, Variant &r_ret) const {
- int key = animation->track_find_key(track, key_ofs, true);
- ERR_FAIL_COND_V(key == -1, false);
-
- String name = p_name;
- if (name == "time") {
- r_ret = key_ofs;
- return true;
- }
-
- if (name == "frame") {
- float fps = animation->get_step();
- if (fps > 0) {
- fps = 1.0 / fps;
+ switch (animation->track_get_type(track)) {
+ case Animation::TYPE_POSITION_3D:
+ case Animation::TYPE_ROTATION_3D:
+ case Animation::TYPE_SCALE_3D: {
+ if (name == "position" || name == "rotation" || name == "scale") {
+ r_ret = animation->track_get_key_value(track, key);
+ return true;
+ }
+ } break;
+ case Animation::TYPE_BLEND_SHAPE:
+ case Animation::TYPE_VALUE: {
+ if (name == "value") {
+ r_ret = animation->track_get_key_value(track, key);
+ return true;
}
- r_ret = key_ofs * fps;
- return true;
- }
- if (name == "easing") {
- r_ret = animation->track_get_key_transition(track, key);
- return true;
- }
+ } break;
+ case Animation::TYPE_METHOD: {
+ Dictionary d = animation->track_get_key_value(track, key);
- switch (animation->track_get_type(track)) {
- case Animation::TYPE_POSITION_3D:
- case Animation::TYPE_ROTATION_3D:
- case Animation::TYPE_SCALE_3D: {
- if (name == "position" || name == "rotation" || name == "scale") {
- r_ret = animation->track_get_key_value(track, key);
- return true;
- }
- } break;
- case Animation::TYPE_BLEND_SHAPE:
- case Animation::TYPE_VALUE: {
- if (name == "value") {
- r_ret = animation->track_get_key_value(track, key);
- return true;
- }
+ if (name == "name") {
+ ERR_FAIL_COND_V(!d.has("method"), false);
+ r_ret = d["method"];
+ return true;
+ }
- } break;
- case Animation::TYPE_METHOD: {
- Dictionary d = animation->track_get_key_value(track, key);
+ ERR_FAIL_COND_V(!d.has("args"), false);
- if (name == "name") {
- ERR_FAIL_COND_V(!d.has("method"), false);
- r_ret = d["method"];
- return true;
- }
+ Vector<Variant> args = d["args"];
- ERR_FAIL_COND_V(!d.has("args"), false);
+ if (name == "arg_count") {
+ r_ret = args.size();
+ return true;
+ }
- Vector<Variant> args = d["args"];
+ if (name.begins_with("args/")) {
+ int idx = name.get_slice("/", 1).to_int();
+ ERR_FAIL_INDEX_V(idx, args.size(), false);
- if (name == "arg_count") {
- r_ret = args.size();
+ String what = name.get_slice("/", 2);
+ if (what == "type") {
+ r_ret = args[idx].get_type();
return true;
}
- if (name.begins_with("args/")) {
- int idx = name.get_slice("/", 1).to_int();
- ERR_FAIL_INDEX_V(idx, args.size(), false);
-
- String what = name.get_slice("/", 2);
- if (what == "type") {
- r_ret = args[idx].get_type();
- return true;
- }
-
- if (what == "value") {
- r_ret = args[idx];
- return true;
- }
- }
-
- } break;
- case Animation::TYPE_BEZIER: {
- if (name == "value") {
- r_ret = animation->bezier_track_get_key_value(track, key);
+ if (what == "value") {
+ r_ret = args[idx];
return true;
}
+ }
- if (name == "in_handle") {
- r_ret = animation->bezier_track_get_key_in_handle(track, key);
- return true;
- }
+ } break;
+ case Animation::TYPE_BEZIER: {
+ if (name == "value") {
+ r_ret = animation->bezier_track_get_key_value(track, key);
+ return true;
+ }
- if (name == "out_handle") {
- r_ret = animation->bezier_track_get_key_out_handle(track, key);
- return true;
- }
+ if (name == "in_handle") {
+ r_ret = animation->bezier_track_get_key_in_handle(track, key);
+ return true;
+ }
- if (name == "handle_mode") {
- r_ret = animation->bezier_track_get_key_handle_mode(track, key);
- return true;
- }
+ if (name == "out_handle") {
+ r_ret = animation->bezier_track_get_key_out_handle(track, key);
+ return true;
+ }
- } break;
- case Animation::TYPE_AUDIO: {
- if (name == "stream") {
- r_ret = animation->audio_track_get_key_stream(track, key);
- return true;
- }
+ if (name == "handle_mode") {
+ r_ret = animation->bezier_track_get_key_handle_mode(track, key);
+ return true;
+ }
- if (name == "start_offset") {
- r_ret = animation->audio_track_get_key_start_offset(track, key);
- return true;
- }
+ } break;
+ case Animation::TYPE_AUDIO: {
+ if (name == "stream") {
+ r_ret = animation->audio_track_get_key_stream(track, key);
+ return true;
+ }
- if (name == "end_offset") {
- r_ret = animation->audio_track_get_key_end_offset(track, key);
- return true;
- }
+ if (name == "start_offset") {
+ r_ret = animation->audio_track_get_key_start_offset(track, key);
+ return true;
+ }
- } break;
- case Animation::TYPE_ANIMATION: {
- if (name == "animation") {
- r_ret = animation->animation_track_get_key_animation(track, key);
- return true;
- }
+ if (name == "end_offset") {
+ r_ret = animation->audio_track_get_key_end_offset(track, key);
+ return true;
+ }
- } break;
- }
+ } break;
+ case Animation::TYPE_ANIMATION: {
+ if (name == "animation") {
+ r_ret = animation->animation_track_get_key_animation(track, key);
+ return true;
+ }
- return false;
+ } break;
}
- void _get_property_list(List<PropertyInfo> *p_list) const {
- if (animation.is_null()) {
- return;
- }
- ERR_FAIL_INDEX(track, animation->get_track_count());
- int key = animation->track_find_key(track, key_ofs, true);
- ERR_FAIL_COND(key == -1);
+ return false;
+}
- if (use_fps && animation->get_step() > 0) {
- float max_frame = animation->get_length() / animation->get_step();
- p_list->push_back(PropertyInfo(Variant::FLOAT, PNAME("frame"), PROPERTY_HINT_RANGE, "0," + rtos(max_frame) + ",1"));
- } else {
- p_list->push_back(PropertyInfo(Variant::FLOAT, PNAME("time"), PROPERTY_HINT_RANGE, "0," + rtos(animation->get_length()) + ",0.01"));
- }
+void AnimationTrackKeyEdit::_get_property_list(List<PropertyInfo> *p_list) const {
+ if (animation.is_null()) {
+ return;
+ }
- switch (animation->track_get_type(track)) {
- case Animation::TYPE_POSITION_3D: {
- p_list->push_back(PropertyInfo(Variant::VECTOR3, PNAME("position")));
- } break;
- case Animation::TYPE_ROTATION_3D: {
- p_list->push_back(PropertyInfo(Variant::QUATERNION, PNAME("rotation")));
- } break;
- case Animation::TYPE_SCALE_3D: {
- p_list->push_back(PropertyInfo(Variant::VECTOR3, PNAME("scale")));
- } break;
- case Animation::TYPE_BLEND_SHAPE: {
- p_list->push_back(PropertyInfo(Variant::FLOAT, PNAME("value")));
- } break;
- case Animation::TYPE_VALUE: {
- Variant v = animation->track_get_key_value(track, key);
+ ERR_FAIL_INDEX(track, animation->get_track_count());
+ int key = animation->track_find_key(track, key_ofs, Animation::FIND_MODE_APPROX);
+ ERR_FAIL_COND(key == -1);
- if (hint.type != Variant::NIL) {
- PropertyInfo pi = hint;
- pi.name = PNAME("value");
- p_list->push_back(pi);
- } else {
- PropertyHint val_hint = PROPERTY_HINT_NONE;
- String val_hint_string;
-
- if (v.get_type() == Variant::OBJECT) {
- // Could actually check the object property if exists..? Yes I will!
- Ref<Resource> res = v;
- if (res.is_valid()) {
- val_hint = PROPERTY_HINT_RESOURCE_TYPE;
- val_hint_string = res->get_class();
- }
- }
+ switch (animation->track_get_type(track)) {
+ case Animation::TYPE_POSITION_3D: {
+ p_list->push_back(PropertyInfo(Variant::VECTOR3, PNAME("position")));
+ } break;
+ case Animation::TYPE_ROTATION_3D: {
+ p_list->push_back(PropertyInfo(Variant::QUATERNION, PNAME("rotation")));
+ } break;
+ case Animation::TYPE_SCALE_3D: {
+ p_list->push_back(PropertyInfo(Variant::VECTOR3, PNAME("scale")));
+ } break;
+ case Animation::TYPE_BLEND_SHAPE: {
+ p_list->push_back(PropertyInfo(Variant::FLOAT, PNAME("value")));
+ } break;
+ case Animation::TYPE_VALUE: {
+ Variant v = animation->track_get_key_value(track, key);
- if (v.get_type() != Variant::NIL) {
- p_list->push_back(PropertyInfo(v.get_type(), PNAME("value"), val_hint, val_hint_string));
+ if (hint.type != Variant::NIL) {
+ PropertyInfo pi = hint;
+ pi.name = PNAME("value");
+ p_list->push_back(pi);
+ } else {
+ PropertyHint val_hint = PROPERTY_HINT_NONE;
+ String val_hint_string;
+
+ if (v.get_type() == Variant::OBJECT) {
+ // Could actually check the object property if exists..? Yes I will!
+ Ref<Resource> res = v;
+ if (res.is_valid()) {
+ val_hint = PROPERTY_HINT_RESOURCE_TYPE;
+ val_hint_string = res->get_class();
}
}
- } break;
- case Animation::TYPE_METHOD: {
- p_list->push_back(PropertyInfo(Variant::STRING_NAME, PNAME("name")));
- p_list->push_back(PropertyInfo(Variant::INT, PNAME("arg_count"), PROPERTY_HINT_RANGE, "0,32,1,or_greater"));
-
- Dictionary d = animation->track_get_key_value(track, key);
- ERR_FAIL_COND(!d.has("args"));
- Vector<Variant> args = d["args"];
- String vtypes;
- for (int i = 0; i < Variant::VARIANT_MAX; i++) {
- if (i > 0) {
- vtypes += ",";
- }
- vtypes += Variant::get_type_name(Variant::Type(i));
+ if (v.get_type() != Variant::NIL) {
+ p_list->push_back(PropertyInfo(v.get_type(), PNAME("value"), val_hint, val_hint_string));
}
+ }
- for (int i = 0; i < args.size(); i++) {
- p_list->push_back(PropertyInfo(Variant::INT, vformat("%s/%d/%s", PNAME("args"), i, PNAME("type")), PROPERTY_HINT_ENUM, vtypes));
- if (args[i].get_type() != Variant::NIL) {
- p_list->push_back(PropertyInfo(args[i].get_type(), vformat("%s/%d/%s", PNAME("args"), i, PNAME("value"))));
- }
+ } break;
+ case Animation::TYPE_METHOD: {
+ p_list->push_back(PropertyInfo(Variant::STRING_NAME, PNAME("name")));
+ p_list->push_back(PropertyInfo(Variant::INT, PNAME("arg_count"), PROPERTY_HINT_RANGE, "0,32,1,or_greater"));
+
+ Dictionary d = animation->track_get_key_value(track, key);
+ ERR_FAIL_COND(!d.has("args"));
+ Vector<Variant> args = d["args"];
+ String vtypes;
+ for (int i = 0; i < Variant::VARIANT_MAX; i++) {
+ if (i > 0) {
+ vtypes += ",";
}
+ vtypes += Variant::get_type_name(Variant::Type(i));
+ }
- } break;
- case Animation::TYPE_BEZIER: {
- Animation::HandleMode hm = animation->bezier_track_get_key_handle_mode(track, key);
- p_list->push_back(PropertyInfo(Variant::FLOAT, PNAME("value")));
- if (hm == Animation::HANDLE_MODE_LINEAR) {
- p_list->push_back(PropertyInfo(Variant::VECTOR2, PNAME("in_handle"), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_READ_ONLY));
- p_list->push_back(PropertyInfo(Variant::VECTOR2, PNAME("out_handle"), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_READ_ONLY));
- } else {
- p_list->push_back(PropertyInfo(Variant::VECTOR2, PNAME("in_handle")));
- p_list->push_back(PropertyInfo(Variant::VECTOR2, PNAME("out_handle")));
+ for (int i = 0; i < args.size(); i++) {
+ p_list->push_back(PropertyInfo(Variant::INT, vformat("%s/%d/%s", PNAME("args"), i, PNAME("type")), PROPERTY_HINT_ENUM, vtypes));
+ if (args[i].get_type() != Variant::NIL) {
+ p_list->push_back(PropertyInfo(args[i].get_type(), vformat("%s/%d/%s", PNAME("args"), i, PNAME("value"))));
}
- p_list->push_back(PropertyInfo(Variant::INT, PNAME("handle_mode"), PROPERTY_HINT_ENUM, "Free,Linear,Balanced,Mirrored"));
-
- } break;
- case Animation::TYPE_AUDIO: {
- p_list->push_back(PropertyInfo(Variant::OBJECT, PNAME("stream"), PROPERTY_HINT_RESOURCE_TYPE, "AudioStream"));
- p_list->push_back(PropertyInfo(Variant::FLOAT, PNAME("start_offset"), PROPERTY_HINT_RANGE, "0,3600,0.01,or_greater"));
- p_list->push_back(PropertyInfo(Variant::FLOAT, PNAME("end_offset"), PROPERTY_HINT_RANGE, "0,3600,0.01,or_greater"));
+ }
- } break;
- case Animation::TYPE_ANIMATION: {
- String animations;
+ } break;
+ case Animation::TYPE_BEZIER: {
+ Animation::HandleMode hm = animation->bezier_track_get_key_handle_mode(track, key);
+ p_list->push_back(PropertyInfo(Variant::FLOAT, PNAME("value")));
+ if (hm == Animation::HANDLE_MODE_LINEAR) {
+ p_list->push_back(PropertyInfo(Variant::VECTOR2, PNAME("in_handle"), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_READ_ONLY));
+ p_list->push_back(PropertyInfo(Variant::VECTOR2, PNAME("out_handle"), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_READ_ONLY));
+ } else {
+ p_list->push_back(PropertyInfo(Variant::VECTOR2, PNAME("in_handle")));
+ p_list->push_back(PropertyInfo(Variant::VECTOR2, PNAME("out_handle")));
+ }
+ p_list->push_back(PropertyInfo(Variant::INT, PNAME("handle_mode"), PROPERTY_HINT_ENUM, "Free,Linear,Balanced,Mirrored"));
- if (root_path && root_path->has_node(animation->track_get_path(track))) {
- AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(root_path->get_node(animation->track_get_path(track)));
- if (ap) {
- List<StringName> anims;
- ap->get_animation_list(&anims);
- for (const StringName &E : anims) {
- if (!animations.is_empty()) {
- animations += ",";
- }
+ } break;
+ case Animation::TYPE_AUDIO: {
+ p_list->push_back(PropertyInfo(Variant::OBJECT, PNAME("stream"), PROPERTY_HINT_RESOURCE_TYPE, "AudioStream"));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, PNAME("start_offset"), PROPERTY_HINT_RANGE, "0,3600,0.0001,or_greater"));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, PNAME("end_offset"), PROPERTY_HINT_RANGE, "0,3600,0.0001,or_greater"));
- animations += String(E);
+ } break;
+ case Animation::TYPE_ANIMATION: {
+ String animations;
+
+ if (root_path && root_path->has_node(animation->track_get_path(track))) {
+ AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(root_path->get_node(animation->track_get_path(track)));
+ if (ap) {
+ List<StringName> anims;
+ ap->get_animation_list(&anims);
+ for (const StringName &E : anims) {
+ if (!animations.is_empty()) {
+ animations += ",";
}
+
+ animations += String(E);
}
}
+ }
- if (!animations.is_empty()) {
- animations += ",";
- }
- animations += "[stop]";
+ if (!animations.is_empty()) {
+ animations += ",";
+ }
+ animations += "[stop]";
- p_list->push_back(PropertyInfo(Variant::STRING_NAME, PNAME("animation"), PROPERTY_HINT_ENUM, animations));
+ p_list->push_back(PropertyInfo(Variant::STRING_NAME, PNAME("animation"), PROPERTY_HINT_ENUM, animations));
- } break;
- }
+ } break;
+ }
- if (animation->track_get_type(track) == Animation::TYPE_VALUE) {
- p_list->push_back(PropertyInfo(Variant::FLOAT, PNAME("easing"), PROPERTY_HINT_EXP_EASING));
- }
+ if (animation->track_get_type(track) == Animation::TYPE_VALUE) {
+ p_list->push_back(PropertyInfo(Variant::FLOAT, PNAME("easing"), PROPERTY_HINT_EXP_EASING));
}
+}
- Ref<EditorUndoRedoManager> undo_redo;
- Ref<Animation> animation;
- int track = -1;
- float key_ofs = 0;
- Node *root_path = nullptr;
+void AnimationTrackKeyEdit::notify_change() {
+ notify_property_list_changed();
+}
- PropertyInfo hint;
- NodePath base;
- bool use_fps = false;
+Node *AnimationTrackKeyEdit::get_root_path() {
+ return root_path;
+}
- void notify_change() {
- notify_property_list_changed();
- }
+void AnimationTrackKeyEdit::set_use_fps(bool p_enable) {
+ use_fps = p_enable;
+ notify_property_list_changed();
+}
- Node *get_root_path() {
- return root_path;
- }
+void AnimationMultiTrackKeyEdit::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("_update_obj"), &AnimationMultiTrackKeyEdit::_update_obj);
+ ClassDB::bind_method(D_METHOD("_key_ofs_changed"), &AnimationMultiTrackKeyEdit::_key_ofs_changed);
+ ClassDB::bind_method(D_METHOD("_hide_script_from_inspector"), &AnimationMultiTrackKeyEdit::_hide_script_from_inspector);
+ ClassDB::bind_method(D_METHOD("_hide_metadata_from_inspector"), &AnimationMultiTrackKeyEdit::_hide_metadata_from_inspector);
+ ClassDB::bind_method(D_METHOD("get_root_path"), &AnimationMultiTrackKeyEdit::get_root_path);
+ ClassDB::bind_method(D_METHOD("_dont_undo_redo"), &AnimationMultiTrackKeyEdit::_dont_undo_redo);
+ ClassDB::bind_method(D_METHOD("_is_read_only"), &AnimationMultiTrackKeyEdit::_is_read_only);
+}
+
+void AnimationMultiTrackKeyEdit::_fix_node_path(Variant &value, NodePath &base) {
+ NodePath np = value;
- void set_use_fps(bool p_enable) {
- use_fps = p_enable;
- notify_property_list_changed();
+ if (np == NodePath()) {
+ return;
}
-};
-class AnimationMultiTrackKeyEdit : public Object {
- GDCLASS(AnimationMultiTrackKeyEdit, Object);
+ Node *root = EditorNode::get_singleton()->get_tree()->get_root();
-public:
- bool setting = false;
- bool animation_read_only = false;
+ Node *np_node = root->get_node(np);
+ ERR_FAIL_COND(!np_node);
- bool _hide_script_from_inspector() { return true; }
- bool _hide_metadata_from_inspector() { return true; }
- bool _dont_undo_redo() { return true; }
+ Node *edited_node = root->get_node(base);
+ ERR_FAIL_COND(!edited_node);
- bool _is_read_only() {
- return animation_read_only;
- }
+ value = edited_node->get_path_to(np_node);
+}
- static void _bind_methods() {
- ClassDB::bind_method(D_METHOD("_update_obj"), &AnimationMultiTrackKeyEdit::_update_obj);
- ClassDB::bind_method(D_METHOD("_key_ofs_changed"), &AnimationMultiTrackKeyEdit::_key_ofs_changed);
- ClassDB::bind_method(D_METHOD("_hide_script_from_inspector"), &AnimationMultiTrackKeyEdit::_hide_script_from_inspector);
- ClassDB::bind_method(D_METHOD("_hide_metadata_from_inspector"), &AnimationMultiTrackKeyEdit::_hide_metadata_from_inspector);
- ClassDB::bind_method(D_METHOD("get_root_path"), &AnimationMultiTrackKeyEdit::get_root_path);
- ClassDB::bind_method(D_METHOD("_dont_undo_redo"), &AnimationMultiTrackKeyEdit::_dont_undo_redo);
- ClassDB::bind_method(D_METHOD("_is_read_only"), &AnimationMultiTrackKeyEdit::_is_read_only);
+void AnimationMultiTrackKeyEdit::_update_obj(const Ref<Animation> &p_anim) {
+ if (setting || animation != p_anim) {
+ return;
}
- void _fix_node_path(Variant &value, NodePath &base) {
- NodePath np = value;
+ notify_change();
+}
- if (np == NodePath()) {
- return;
- }
+void AnimationMultiTrackKeyEdit::_key_ofs_changed(const Ref<Animation> &p_anim, float from, float to) {
+ if (animation != p_anim) {
+ return;
+ }
- Node *root = EditorNode::get_singleton()->get_tree()->get_root();
+ for (const KeyValue<int, List<float>> &E : key_ofs_map) {
+ int key = 0;
+ for (const float &key_ofs : E.value) {
+ if (from != key_ofs) {
+ key++;
+ continue;
+ }
- Node *np_node = root->get_node(np);
- ERR_FAIL_COND(!np_node);
+ int track = E.key;
+ key_ofs_map[track][key] = to;
- Node *edited_node = root->get_node(base);
- ERR_FAIL_COND(!edited_node);
+ if (setting) {
+ return;
+ }
- value = edited_node->get_path_to(np_node);
- }
+ notify_change();
- void _update_obj(const Ref<Animation> &p_anim) {
- if (setting || animation != p_anim) {
return;
}
-
- notify_change();
}
+}
- void _key_ofs_changed(const Ref<Animation> &p_anim, float from, float to) {
- if (animation != p_anim) {
- return;
- }
-
- for (const KeyValue<int, List<float>> &E : key_ofs_map) {
- int key = 0;
- for (const float &key_ofs : E.value) {
- if (from != key_ofs) {
- key++;
- continue;
- }
+bool AnimationMultiTrackKeyEdit::_set(const StringName &p_name, const Variant &p_value) {
+ bool update_obj = false;
+ bool change_notify_deserved = false;
+ for (const KeyValue<int, List<float>> &E : key_ofs_map) {
+ int track = E.key;
+ for (const float &key_ofs : E.value) {
+ int key = animation->track_find_key(track, key_ofs, Animation::FIND_MODE_APPROX);
+ ERR_FAIL_COND_V(key == -1, false);
- int track = E.key;
- key_ofs_map[track][key] = to;
+ String name = p_name;
+ if (name == "easing") {
+ float val = p_value;
+ float prev_val = animation->track_get_key_transition(track, key);
- if (setting) {
- return;
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
+ if (!setting) {
+ setting = true;
+ undo_redo->create_action(TTR("Animation Multi Change Transition"), UndoRedo::MERGE_ENDS);
}
-
- notify_change();
-
- return;
+ undo_redo->add_do_method(animation.ptr(), "track_set_key_transition", track, key, val);
+ undo_redo->add_undo_method(animation.ptr(), "track_set_key_transition", track, key, prev_val);
+ update_obj = true;
}
- }
- }
- bool _set(const StringName &p_name, const Variant &p_value) {
- bool update_obj = false;
- bool change_notify_deserved = false;
- for (const KeyValue<int, List<float>> &E : key_ofs_map) {
- int track = E.key;
- for (const float &key_ofs : E.value) {
- int key = animation->track_find_key(track, key_ofs, true);
- ERR_FAIL_COND_V(key == -1, false);
-
- String name = p_name;
- if (name == "time" || name == "frame") {
- float new_time = p_value;
-
- if (name == "frame") {
- float fps = animation->get_step();
- if (fps > 0) {
- fps = 1.0 / fps;
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
+ switch (animation->track_get_type(track)) {
+ case Animation::TYPE_POSITION_3D:
+ case Animation::TYPE_ROTATION_3D:
+ case Animation::TYPE_SCALE_3D: {
+ Variant old = animation->track_get_key_value(track, key);
+ if (!setting) {
+ String chan;
+ switch (animation->track_get_type(track)) {
+ case Animation::TYPE_POSITION_3D:
+ chan = "Position3D";
+ break;
+ case Animation::TYPE_ROTATION_3D:
+ chan = "Rotation3D";
+ break;
+ case Animation::TYPE_SCALE_3D:
+ chan = "Scale3D";
+ break;
+ default: {
+ }
}
- new_time /= fps;
- }
- int existing = animation->track_find_key(track, new_time, true);
-
- if (!setting) {
setting = true;
- undo_redo->create_action(TTR("Anim Multi Change Keyframe Time"), UndoRedo::MERGE_ENDS);
+ undo_redo->create_action(vformat(TTR("Animation Multi Change %s"), chan));
}
+ undo_redo->add_do_method(animation.ptr(), "track_set_key_value", track, key, p_value);
+ undo_redo->add_undo_method(animation.ptr(), "track_set_key_value", track, key, old);
+ update_obj = true;
+ } break;
+ case Animation::TYPE_BLEND_SHAPE:
+ case Animation::TYPE_VALUE: {
+ if (name == "value") {
+ Variant value = p_value;
- Variant val = animation->track_get_key_value(track, key);
- float trans = animation->track_get_key_transition(track, key);
-
- undo_redo->add_do_method(animation.ptr(), "track_remove_key", track, key);
- undo_redo->add_do_method(animation.ptr(), "track_insert_key", track, new_time, val, trans);
- undo_redo->add_do_method(this, "_key_ofs_changed", animation, key_ofs, new_time);
- undo_redo->add_undo_method(animation.ptr(), "track_remove_key_at_time", track, new_time);
- undo_redo->add_undo_method(animation.ptr(), "track_insert_key", track, key_ofs, val, trans);
- undo_redo->add_undo_method(this, "_key_ofs_changed", animation, new_time, key_ofs);
+ if (value.get_type() == Variant::NODE_PATH) {
+ _fix_node_path(value, base_map[track]);
+ }
- if (existing != -1) {
- Variant v = animation->track_get_key_value(track, existing);
- trans = animation->track_get_key_transition(track, existing);
- undo_redo->add_undo_method(animation.ptr(), "track_insert_key", track, new_time, v, trans);
+ if (!setting) {
+ setting = true;
+ undo_redo->create_action(TTR("Animation Multi Change Keyframe Value"), UndoRedo::MERGE_ENDS);
+ }
+ Variant prev = animation->track_get_key_value(track, key);
+ undo_redo->add_do_method(animation.ptr(), "track_set_key_value", track, key, value);
+ undo_redo->add_undo_method(animation.ptr(), "track_set_key_value", track, key, prev);
+ update_obj = true;
}
- } else if (name == "easing") {
- float val = p_value;
- float prev_val = animation->track_get_key_transition(track, key);
+ } break;
+ case Animation::TYPE_METHOD: {
+ Dictionary d_old = animation->track_get_key_value(track, key);
+ Dictionary d_new = d_old.duplicate();
- if (!setting) {
- setting = true;
- undo_redo->create_action(TTR("Anim Multi Change Transition"), UndoRedo::MERGE_ENDS);
- }
- undo_redo->add_do_method(animation.ptr(), "track_set_key_transition", track, key, val);
- undo_redo->add_undo_method(animation.ptr(), "track_set_key_transition", track, key, prev_val);
- update_obj = true;
- }
+ bool mergeable = false;
- switch (animation->track_get_type(track)) {
- case Animation::TYPE_POSITION_3D:
- case Animation::TYPE_ROTATION_3D:
- case Animation::TYPE_SCALE_3D: {
- Variant old = animation->track_get_key_value(track, key);
- if (!setting) {
- String chan;
- switch (animation->track_get_type(track)) {
- case Animation::TYPE_POSITION_3D:
- chan = "Position3D";
- break;
- case Animation::TYPE_ROTATION_3D:
- chan = "Rotation3D";
- break;
- case Animation::TYPE_SCALE_3D:
- chan = "Scale3D";
- break;
- default: {
+ if (name == "name") {
+ d_new["method"] = p_value;
+ } else if (name == "arg_count") {
+ Vector<Variant> args = d_old["args"];
+ args.resize(p_value);
+ d_new["args"] = args;
+ change_notify_deserved = true;
+ } else if (name.begins_with("args/")) {
+ Vector<Variant> args = d_old["args"];
+ int idx = name.get_slice("/", 1).to_int();
+ ERR_FAIL_INDEX_V(idx, args.size(), false);
+
+ String what = name.get_slice("/", 2);
+ if (what == "type") {
+ Variant::Type t = Variant::Type(int(p_value));
+
+ if (t != args[idx].get_type()) {
+ Callable::CallError err;
+ if (Variant::can_convert(args[idx].get_type(), t)) {
+ Variant old = args[idx];
+ Variant *ptrs[1] = { &old };
+ Variant::construct(t, args.write[idx], (const Variant **)ptrs, 1, err);
+ } else {
+ Variant::construct(t, args.write[idx], nullptr, 0, err);
}
+ change_notify_deserved = true;
+ d_new["args"] = args;
}
-
- setting = true;
- undo_redo->create_action(vformat(TTR("Anim Multi Change %s"), chan));
- }
- undo_redo->add_do_method(animation.ptr(), "track_set_key_value", track, key, p_value);
- undo_redo->add_undo_method(animation.ptr(), "track_set_key_value", track, key, old);
- update_obj = true;
- } break;
- case Animation::TYPE_BLEND_SHAPE:
- case Animation::TYPE_VALUE: {
- if (name == "value") {
+ } else if (what == "value") {
Variant value = p_value;
-
if (value.get_type() == Variant::NODE_PATH) {
_fix_node_path(value, base_map[track]);
}
- if (!setting) {
- setting = true;
- undo_redo->create_action(TTR("Anim Multi Change Keyframe Value"), UndoRedo::MERGE_ENDS);
- }
- Variant prev = animation->track_get_key_value(track, key);
- undo_redo->add_do_method(animation.ptr(), "track_set_key_value", track, key, value);
- undo_redo->add_undo_method(animation.ptr(), "track_set_key_value", track, key, prev);
- update_obj = true;
+ args.write[idx] = value;
+ d_new["args"] = args;
+ mergeable = true;
}
- } break;
- case Animation::TYPE_METHOD: {
- Dictionary d_old = animation->track_get_key_value(track, key);
- Dictionary d_new = d_old.duplicate();
+ }
- bool mergeable = false;
+ Variant prev = animation->track_get_key_value(track, key);
- if (name == "name") {
- d_new["method"] = p_value;
- } else if (name == "arg_count") {
- Vector<Variant> args = d_old["args"];
- args.resize(p_value);
- d_new["args"] = args;
- change_notify_deserved = true;
- } else if (name.begins_with("args/")) {
- Vector<Variant> args = d_old["args"];
- int idx = name.get_slice("/", 1).to_int();
- ERR_FAIL_INDEX_V(idx, args.size(), false);
-
- String what = name.get_slice("/", 2);
- if (what == "type") {
- Variant::Type t = Variant::Type(int(p_value));
-
- if (t != args[idx].get_type()) {
- Callable::CallError err;
- if (Variant::can_convert(args[idx].get_type(), t)) {
- Variant old = args[idx];
- Variant *ptrs[1] = { &old };
- Variant::construct(t, args.write[idx], (const Variant **)ptrs, 1, err);
- } else {
- Variant::construct(t, args.write[idx], nullptr, 0, err);
- }
- change_notify_deserved = true;
- d_new["args"] = args;
- }
- } else if (what == "value") {
- Variant value = p_value;
- if (value.get_type() == Variant::NODE_PATH) {
- _fix_node_path(value, base_map[track]);
- }
+ if (!setting) {
+ if (mergeable) {
+ undo_redo->create_action(TTR("Animation Multi Change Call"), UndoRedo::MERGE_ENDS);
+ } else {
+ undo_redo->create_action(TTR("Animation Multi Change Call"));
+ }
- args.write[idx] = value;
- d_new["args"] = args;
- mergeable = true;
- }
+ setting = true;
+ }
+
+ undo_redo->add_do_method(animation.ptr(), "track_set_key_value", track, key, d_new);
+ undo_redo->add_undo_method(animation.ptr(), "track_set_key_value", track, key, d_old);
+ update_obj = true;
+ } break;
+ case Animation::TYPE_BEZIER: {
+ if (name == "value") {
+ const Variant &value = p_value;
+
+ if (!setting) {
+ setting = true;
+ undo_redo->create_action(TTR("Animation Multi Change Keyframe Value"), UndoRedo::MERGE_ENDS);
}
+ float prev = animation->bezier_track_get_key_value(track, key);
+ undo_redo->add_do_method(animation.ptr(), "bezier_track_set_key_value", track, key, value);
+ undo_redo->add_undo_method(animation.ptr(), "bezier_track_set_key_value", track, key, prev);
+ update_obj = true;
+ } else if (name == "in_handle") {
+ const Variant &value = p_value;
- Variant prev = animation->track_get_key_value(track, key);
+ if (!setting) {
+ setting = true;
+ undo_redo->create_action(TTR("Animation Multi Change Keyframe Value"), UndoRedo::MERGE_ENDS);
+ }
+ Vector2 prev = animation->bezier_track_get_key_in_handle(track, key);
+ undo_redo->add_do_method(this, "_bezier_track_set_key_in_handle", track, key, value);
+ undo_redo->add_undo_method(this, "_bezier_track_set_key_in_handle", track, key, prev);
+ update_obj = true;
+ } else if (name == "out_handle") {
+ const Variant &value = p_value;
if (!setting) {
- if (mergeable) {
- undo_redo->create_action(TTR("Anim Multi Change Call"), UndoRedo::MERGE_ENDS);
- } else {
- undo_redo->create_action(TTR("Anim Multi Change Call"));
- }
+ setting = true;
+ undo_redo->create_action(TTR("Animation Multi Change Keyframe Value"), UndoRedo::MERGE_ENDS);
+ }
+ Vector2 prev = animation->bezier_track_get_key_out_handle(track, key);
+ undo_redo->add_do_method(this, "_bezier_track_set_key_out_handle", track, key, value);
+ undo_redo->add_undo_method(this, "_bezier_track_set_key_out_handle", track, key, prev);
+ update_obj = true;
+ } else if (name == "handle_mode") {
+ const Variant &value = p_value;
+ if (!setting) {
setting = true;
+ undo_redo->create_action(TTR("Animation Multi Change Keyframe Value"), UndoRedo::MERGE_ENDS);
}
+ int prev = animation->bezier_track_get_key_handle_mode(track, key);
+ undo_redo->add_do_method(this, "_bezier_track_set_key_handle_mode", animation.ptr(), track, key, value);
+ undo_redo->add_undo_method(this, "_bezier_track_set_key_handle_mode", animation.ptr(), track, key, prev);
+ update_obj = true;
+ }
+ } break;
+ case Animation::TYPE_AUDIO: {
+ if (name == "stream") {
+ Ref<AudioStream> stream = p_value;
- undo_redo->add_do_method(animation.ptr(), "track_set_key_value", track, key, d_new);
- undo_redo->add_undo_method(animation.ptr(), "track_set_key_value", track, key, d_old);
+ if (!setting) {
+ setting = true;
+ undo_redo->create_action(TTR("Animation Multi Change Keyframe Value"), UndoRedo::MERGE_ENDS);
+ }
+ Ref<Resource> prev = animation->audio_track_get_key_stream(track, key);
+ undo_redo->add_do_method(animation.ptr(), "audio_track_set_key_stream", track, key, stream);
+ undo_redo->add_undo_method(animation.ptr(), "audio_track_set_key_stream", track, key, prev);
update_obj = true;
- } break;
- case Animation::TYPE_BEZIER: {
- if (name == "value") {
- const Variant &value = p_value;
+ } else if (name == "start_offset") {
+ float value = p_value;
- if (!setting) {
- setting = true;
- undo_redo->create_action(TTR("Anim Multi Change Keyframe Value"), UndoRedo::MERGE_ENDS);
- }
- float prev = animation->bezier_track_get_key_value(track, key);
- undo_redo->add_do_method(animation.ptr(), "bezier_track_set_key_value", track, key, value);
- undo_redo->add_undo_method(animation.ptr(), "bezier_track_set_key_value", track, key, prev);
- update_obj = true;
- } else if (name == "in_handle") {
- const Variant &value = p_value;
-
- if (!setting) {
- setting = true;
- undo_redo->create_action(TTR("Anim Multi Change Keyframe Value"), UndoRedo::MERGE_ENDS);
- }
- Vector2 prev = animation->bezier_track_get_key_in_handle(track, key);
- undo_redo->add_do_method(this, "_bezier_track_set_key_in_handle", track, key, value);
- undo_redo->add_undo_method(this, "_bezier_track_set_key_in_handle", track, key, prev);
- update_obj = true;
- } else if (name == "out_handle") {
- const Variant &value = p_value;
-
- if (!setting) {
- setting = true;
- undo_redo->create_action(TTR("Anim Multi Change Keyframe Value"), UndoRedo::MERGE_ENDS);
- }
- Vector2 prev = animation->bezier_track_get_key_out_handle(track, key);
- undo_redo->add_do_method(this, "_bezier_track_set_key_out_handle", track, key, value);
- undo_redo->add_undo_method(this, "_bezier_track_set_key_out_handle", track, key, prev);
- update_obj = true;
- } else if (name == "handle_mode") {
- const Variant &value = p_value;
-
- if (!setting) {
- setting = true;
- undo_redo->create_action(TTR("Anim Multi Change Keyframe Value"), UndoRedo::MERGE_ENDS);
- }
- int prev = animation->bezier_track_get_key_handle_mode(track, key);
- undo_redo->add_do_method(this, "_bezier_track_set_key_handle_mode", animation.ptr(), track, key, value);
- undo_redo->add_undo_method(this, "_bezier_track_set_key_handle_mode", animation.ptr(), track, key, prev);
- update_obj = true;
+ if (!setting) {
+ setting = true;
+ undo_redo->create_action(TTR("Animation Multi Change Keyframe Value"), UndoRedo::MERGE_ENDS);
}
- } break;
- case Animation::TYPE_AUDIO: {
- if (name == "stream") {
- Ref<AudioStream> stream = p_value;
+ float prev = animation->audio_track_get_key_start_offset(track, key);
+ undo_redo->add_do_method(animation.ptr(), "audio_track_set_key_start_offset", track, key, value);
+ undo_redo->add_undo_method(animation.ptr(), "audio_track_set_key_start_offset", track, key, prev);
+ update_obj = true;
+ } else if (name == "end_offset") {
+ float value = p_value;
- if (!setting) {
- setting = true;
- undo_redo->create_action(TTR("Anim Multi Change Keyframe Value"), UndoRedo::MERGE_ENDS);
- }
- Ref<Resource> prev = animation->audio_track_get_key_stream(track, key);
- undo_redo->add_do_method(animation.ptr(), "audio_track_set_key_stream", track, key, stream);
- undo_redo->add_undo_method(animation.ptr(), "audio_track_set_key_stream", track, key, prev);
- update_obj = true;
- } else if (name == "start_offset") {
- float value = p_value;
-
- if (!setting) {
- setting = true;
- undo_redo->create_action(TTR("Anim Multi Change Keyframe Value"), UndoRedo::MERGE_ENDS);
- }
- float prev = animation->audio_track_get_key_start_offset(track, key);
- undo_redo->add_do_method(animation.ptr(), "audio_track_set_key_start_offset", track, key, value);
- undo_redo->add_undo_method(animation.ptr(), "audio_track_set_key_start_offset", track, key, prev);
- update_obj = true;
- } else if (name == "end_offset") {
- float value = p_value;
-
- if (!setting) {
- setting = true;
- undo_redo->create_action(TTR("Anim Multi Change Keyframe Value"), UndoRedo::MERGE_ENDS);
- }
- float prev = animation->audio_track_get_key_end_offset(track, key);
- undo_redo->add_do_method(animation.ptr(), "audio_track_set_key_end_offset", track, key, value);
- undo_redo->add_undo_method(animation.ptr(), "audio_track_set_key_end_offset", track, key, prev);
- update_obj = true;
+ if (!setting) {
+ setting = true;
+ undo_redo->create_action(TTR("Animation Multi Change Keyframe Value"), UndoRedo::MERGE_ENDS);
}
- } break;
- case Animation::TYPE_ANIMATION: {
- if (name == "animation") {
- StringName anim_name = p_value;
+ float prev = animation->audio_track_get_key_end_offset(track, key);
+ undo_redo->add_do_method(animation.ptr(), "audio_track_set_key_end_offset", track, key, value);
+ undo_redo->add_undo_method(animation.ptr(), "audio_track_set_key_end_offset", track, key, prev);
+ update_obj = true;
+ }
+ } break;
+ case Animation::TYPE_ANIMATION: {
+ if (name == "animation") {
+ StringName anim_name = p_value;
- if (!setting) {
- setting = true;
- undo_redo->create_action(TTR("Anim Multi Change Keyframe Value"), UndoRedo::MERGE_ENDS);
- }
- StringName prev = animation->animation_track_get_key_animation(track, key);
- undo_redo->add_do_method(animation.ptr(), "animation_track_set_key_animation", track, key, anim_name);
- undo_redo->add_undo_method(animation.ptr(), "animation_track_set_key_animation", track, key, prev);
- update_obj = true;
+ if (!setting) {
+ setting = true;
+ undo_redo->create_action(TTR("Animation Multi Change Keyframe Value"), UndoRedo::MERGE_ENDS);
}
- } break;
- }
+ StringName prev = animation->animation_track_get_key_animation(track, key);
+ undo_redo->add_do_method(animation.ptr(), "animation_track_set_key_animation", track, key, anim_name);
+ undo_redo->add_undo_method(animation.ptr(), "animation_track_set_key_animation", track, key, prev);
+ update_obj = true;
+ }
+ } break;
}
}
+ }
- if (setting) {
- if (update_obj) {
- undo_redo->add_do_method(this, "_update_obj", animation);
- undo_redo->add_undo_method(this, "_update_obj", animation);
- }
-
- undo_redo->commit_action();
- setting = false;
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
+ if (setting) {
+ if (update_obj) {
+ undo_redo->add_do_method(this, "_update_obj", animation);
+ undo_redo->add_undo_method(this, "_update_obj", animation);
+ }
- if (change_notify_deserved) {
- notify_change();
- }
+ undo_redo->commit_action();
+ setting = false;
- return true;
+ if (change_notify_deserved) {
+ notify_change();
}
- return false;
+ return true;
}
- bool _get(const StringName &p_name, Variant &r_ret) const {
- for (const KeyValue<int, List<float>> &E : key_ofs_map) {
- int track = E.key;
- for (const float &key_ofs : E.value) {
- int key = animation->track_find_key(track, key_ofs, true);
- ERR_CONTINUE(key == -1);
+ return false;
+}
- String name = p_name;
- if (name == "time") {
- r_ret = key_ofs;
- return true;
- }
+bool AnimationMultiTrackKeyEdit::_get(const StringName &p_name, Variant &r_ret) const {
+ for (const KeyValue<int, List<float>> &E : key_ofs_map) {
+ int track = E.key;
+ for (const float &key_ofs : E.value) {
+ int key = animation->track_find_key(track, key_ofs, Animation::FIND_MODE_APPROX);
+ ERR_CONTINUE(key == -1);
- if (name == "frame") {
- float fps = animation->get_step();
- if (fps > 0) {
- fps = 1.0 / fps;
+ String name = p_name;
+ if (name == "easing") {
+ r_ret = animation->track_get_key_transition(track, key);
+ return true;
+ }
+
+ switch (animation->track_get_type(track)) {
+ case Animation::TYPE_POSITION_3D:
+ case Animation::TYPE_ROTATION_3D:
+ case Animation::TYPE_SCALE_3D: {
+ if (name == "position" || name == "rotation" || name == "scale") {
+ r_ret = animation->track_get_key_value(track, key);
+ return true;
}
- r_ret = key_ofs * fps;
- return true;
- }
- if (name == "easing") {
- r_ret = animation->track_get_key_transition(track, key);
- return true;
- }
+ } break;
+ case Animation::TYPE_BLEND_SHAPE:
+ case Animation::TYPE_VALUE: {
+ if (name == "value") {
+ r_ret = animation->track_get_key_value(track, key);
+ return true;
+ }
- switch (animation->track_get_type(track)) {
- case Animation::TYPE_POSITION_3D:
- case Animation::TYPE_ROTATION_3D:
- case Animation::TYPE_SCALE_3D: {
- if (name == "position" || name == "rotation" || name == "scale") {
- r_ret = animation->track_get_key_value(track, key);
- return true;
- }
+ } break;
+ case Animation::TYPE_METHOD: {
+ Dictionary d = animation->track_get_key_value(track, key);
- } break;
- case Animation::TYPE_BLEND_SHAPE:
- case Animation::TYPE_VALUE: {
- if (name == "value") {
- r_ret = animation->track_get_key_value(track, key);
- return true;
- }
+ if (name == "name") {
+ ERR_FAIL_COND_V(!d.has("method"), false);
+ r_ret = d["method"];
+ return true;
+ }
- } break;
- case Animation::TYPE_METHOD: {
- Dictionary d = animation->track_get_key_value(track, key);
+ ERR_FAIL_COND_V(!d.has("args"), false);
- if (name == "name") {
- ERR_FAIL_COND_V(!d.has("method"), false);
- r_ret = d["method"];
- return true;
- }
+ Vector<Variant> args = d["args"];
- ERR_FAIL_COND_V(!d.has("args"), false);
+ if (name == "arg_count") {
+ r_ret = args.size();
+ return true;
+ }
- Vector<Variant> args = d["args"];
+ if (name.begins_with("args/")) {
+ int idx = name.get_slice("/", 1).to_int();
+ ERR_FAIL_INDEX_V(idx, args.size(), false);
- if (name == "arg_count") {
- r_ret = args.size();
+ String what = name.get_slice("/", 2);
+ if (what == "type") {
+ r_ret = args[idx].get_type();
return true;
}
- if (name.begins_with("args/")) {
- int idx = name.get_slice("/", 1).to_int();
- ERR_FAIL_INDEX_V(idx, args.size(), false);
-
- String what = name.get_slice("/", 2);
- if (what == "type") {
- r_ret = args[idx].get_type();
- return true;
- }
-
- if (what == "value") {
- r_ret = args[idx];
- return true;
- }
- }
-
- } break;
- case Animation::TYPE_BEZIER: {
- if (name == "value") {
- r_ret = animation->bezier_track_get_key_value(track, key);
+ if (what == "value") {
+ r_ret = args[idx];
return true;
}
+ }
- if (name == "in_handle") {
- r_ret = animation->bezier_track_get_key_in_handle(track, key);
- return true;
- }
+ } break;
+ case Animation::TYPE_BEZIER: {
+ if (name == "value") {
+ r_ret = animation->bezier_track_get_key_value(track, key);
+ return true;
+ }
- if (name == "out_handle") {
- r_ret = animation->bezier_track_get_key_out_handle(track, key);
- return true;
- }
+ if (name == "in_handle") {
+ r_ret = animation->bezier_track_get_key_in_handle(track, key);
+ return true;
+ }
- if (name == "handle_mode") {
- r_ret = animation->bezier_track_get_key_handle_mode(track, key);
- return true;
- }
+ if (name == "out_handle") {
+ r_ret = animation->bezier_track_get_key_out_handle(track, key);
+ return true;
+ }
- } break;
- case Animation::TYPE_AUDIO: {
- if (name == "stream") {
- r_ret = animation->audio_track_get_key_stream(track, key);
- return true;
- }
+ if (name == "handle_mode") {
+ r_ret = animation->bezier_track_get_key_handle_mode(track, key);
+ return true;
+ }
- if (name == "start_offset") {
- r_ret = animation->audio_track_get_key_start_offset(track, key);
- return true;
- }
+ } break;
+ case Animation::TYPE_AUDIO: {
+ if (name == "stream") {
+ r_ret = animation->audio_track_get_key_stream(track, key);
+ return true;
+ }
- if (name == "end_offset") {
- r_ret = animation->audio_track_get_key_end_offset(track, key);
- return true;
- }
+ if (name == "start_offset") {
+ r_ret = animation->audio_track_get_key_start_offset(track, key);
+ return true;
+ }
- } break;
- case Animation::TYPE_ANIMATION: {
- if (name == "animation") {
- r_ret = animation->animation_track_get_key_animation(track, key);
- return true;
- }
+ if (name == "end_offset") {
+ r_ret = animation->audio_track_get_key_end_offset(track, key);
+ return true;
+ }
- } break;
- }
+ } break;
+ case Animation::TYPE_ANIMATION: {
+ if (name == "animation") {
+ r_ret = animation->animation_track_get_key_animation(track, key);
+ return true;
+ }
+
+ } break;
}
}
+ }
- return false;
+ return false;
+}
+
+void AnimationMultiTrackKeyEdit::_get_property_list(List<PropertyInfo> *p_list) const {
+ if (animation.is_null()) {
+ return;
}
- void _get_property_list(List<PropertyInfo> *p_list) const {
- if (animation.is_null()) {
- return;
- }
- int first_track = -1;
- float first_key = -1.0;
+ int first_track = -1;
+ float first_key = -1.0;
- bool show_time = true;
- bool same_track_type = true;
- bool same_key_type = true;
- for (const KeyValue<int, List<float>> &E : key_ofs_map) {
- int track = E.key;
- ERR_FAIL_INDEX(track, animation->get_track_count());
+ bool same_track_type = true;
+ bool same_key_type = true;
+ for (const KeyValue<int, List<float>> &E : key_ofs_map) {
+ int track = E.key;
+ ERR_FAIL_INDEX(track, animation->get_track_count());
- if (first_track < 0) {
- first_track = track;
- }
+ if (first_track < 0) {
+ first_track = track;
+ }
- if (show_time && E.value.size() > 1) {
- show_time = false;
+ if (same_track_type) {
+ if (animation->track_get_type(first_track) != animation->track_get_type(track)) {
+ same_track_type = false;
+ same_key_type = false;
}
- if (same_track_type) {
- if (animation->track_get_type(first_track) != animation->track_get_type(track)) {
- same_track_type = false;
- same_key_type = false;
+ for (const float &F : E.value) {
+ int key = animation->track_find_key(track, F, Animation::FIND_MODE_APPROX);
+ ERR_FAIL_COND(key == -1);
+ if (first_key < 0) {
+ first_key = key;
}
- for (const float &F : E.value) {
- int key = animation->track_find_key(track, F, true);
- ERR_FAIL_COND(key == -1);
- if (first_key < 0) {
- first_key = key;
- }
-
- if (animation->track_get_key_value(first_track, first_key).get_type() != animation->track_get_key_value(track, key).get_type()) {
- same_key_type = false;
- }
+ if (animation->track_get_key_value(first_track, first_key).get_type() != animation->track_get_key_value(track, key).get_type()) {
+ same_key_type = false;
}
}
}
+ }
- if (show_time) {
- if (use_fps && animation->get_step() > 0) {
- float max_frame = animation->get_length() / animation->get_step();
- p_list->push_back(PropertyInfo(Variant::FLOAT, "frame", PROPERTY_HINT_RANGE, "0," + rtos(max_frame) + ",1"));
- } else {
- p_list->push_back(PropertyInfo(Variant::FLOAT, "time", PROPERTY_HINT_RANGE, "0," + rtos(animation->get_length()) + ",0.01"));
- }
- }
-
- if (same_track_type) {
- switch (animation->track_get_type(first_track)) {
- case Animation::TYPE_POSITION_3D: {
- p_list->push_back(PropertyInfo(Variant::VECTOR3, "position"));
- } break;
- case Animation::TYPE_ROTATION_3D: {
- p_list->push_back(PropertyInfo(Variant::QUATERNION, "scale"));
- } break;
- case Animation::TYPE_SCALE_3D: {
- p_list->push_back(PropertyInfo(Variant::VECTOR3, "scale"));
- } break;
- case Animation::TYPE_BLEND_SHAPE: {
- p_list->push_back(PropertyInfo(Variant::FLOAT, "value"));
- } break;
- case Animation::TYPE_VALUE: {
- if (same_key_type) {
- Variant v = animation->track_get_key_value(first_track, first_key);
+ if (same_track_type) {
+ switch (animation->track_get_type(first_track)) {
+ case Animation::TYPE_POSITION_3D: {
+ p_list->push_back(PropertyInfo(Variant::VECTOR3, "position"));
+ } break;
+ case Animation::TYPE_ROTATION_3D: {
+ p_list->push_back(PropertyInfo(Variant::QUATERNION, "scale"));
+ } break;
+ case Animation::TYPE_SCALE_3D: {
+ p_list->push_back(PropertyInfo(Variant::VECTOR3, "scale"));
+ } break;
+ case Animation::TYPE_BLEND_SHAPE: {
+ p_list->push_back(PropertyInfo(Variant::FLOAT, "value"));
+ } break;
+ case Animation::TYPE_VALUE: {
+ if (same_key_type) {
+ Variant v = animation->track_get_key_value(first_track, first_key);
- if (hint.type != Variant::NIL) {
- PropertyInfo pi = hint;
- pi.name = "value";
- p_list->push_back(pi);
- } else {
- PropertyHint val_hint = PROPERTY_HINT_NONE;
- String val_hint_string;
-
- if (v.get_type() == Variant::OBJECT) {
- // Could actually check the object property if exists..? Yes I will!
- Ref<Resource> res = v;
- if (res.is_valid()) {
- val_hint = PROPERTY_HINT_RESOURCE_TYPE;
- val_hint_string = res->get_class();
- }
+ if (hint.type != Variant::NIL) {
+ PropertyInfo pi = hint;
+ pi.name = "value";
+ p_list->push_back(pi);
+ } else {
+ PropertyHint val_hint = PROPERTY_HINT_NONE;
+ String val_hint_string;
+
+ if (v.get_type() == Variant::OBJECT) {
+ // Could actually check the object property if exists..? Yes I will!
+ Ref<Resource> res = v;
+ if (res.is_valid()) {
+ val_hint = PROPERTY_HINT_RESOURCE_TYPE;
+ val_hint_string = res->get_class();
}
+ }
- if (v.get_type() != Variant::NIL) {
- p_list->push_back(PropertyInfo(v.get_type(), "value", val_hint, val_hint_string));
- }
+ if (v.get_type() != Variant::NIL) {
+ p_list->push_back(PropertyInfo(v.get_type(), "value", val_hint, val_hint_string));
}
}
+ }
- p_list->push_back(PropertyInfo(Variant::FLOAT, "easing", PROPERTY_HINT_EXP_EASING));
- } break;
- case Animation::TYPE_METHOD: {
- p_list->push_back(PropertyInfo(Variant::STRING_NAME, "name"));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, "easing", PROPERTY_HINT_EXP_EASING));
+ } break;
+ case Animation::TYPE_METHOD: {
+ p_list->push_back(PropertyInfo(Variant::STRING_NAME, "name"));
- p_list->push_back(PropertyInfo(Variant::INT, "arg_count", PROPERTY_HINT_RANGE, "0,32,1,or_greater"));
+ p_list->push_back(PropertyInfo(Variant::INT, "arg_count", PROPERTY_HINT_RANGE, "0,32,1,or_greater"));
- Dictionary d = animation->track_get_key_value(first_track, first_key);
- ERR_FAIL_COND(!d.has("args"));
- Vector<Variant> args = d["args"];
- String vtypes;
- for (int i = 0; i < Variant::VARIANT_MAX; i++) {
- if (i > 0) {
- vtypes += ",";
- }
- vtypes += Variant::get_type_name(Variant::Type(i));
+ Dictionary d = animation->track_get_key_value(first_track, first_key);
+ ERR_FAIL_COND(!d.has("args"));
+ Vector<Variant> args = d["args"];
+ String vtypes;
+ for (int i = 0; i < Variant::VARIANT_MAX; i++) {
+ if (i > 0) {
+ vtypes += ",";
}
+ vtypes += Variant::get_type_name(Variant::Type(i));
+ }
- for (int i = 0; i < args.size(); i++) {
- p_list->push_back(PropertyInfo(Variant::INT, "args/" + itos(i) + "/type", PROPERTY_HINT_ENUM, vtypes));
- if (args[i].get_type() != Variant::NIL) {
- p_list->push_back(PropertyInfo(args[i].get_type(), "args/" + itos(i) + "/value"));
- }
- }
- } break;
- case Animation::TYPE_BEZIER: {
- p_list->push_back(PropertyInfo(Variant::FLOAT, "value"));
- p_list->push_back(PropertyInfo(Variant::VECTOR2, "in_handle"));
- p_list->push_back(PropertyInfo(Variant::VECTOR2, "out_handle"));
- p_list->push_back(PropertyInfo(Variant::INT, "handle_mode", PROPERTY_HINT_ENUM, "Free,Linear,Balanced,Mirrored"));
- } break;
- case Animation::TYPE_AUDIO: {
- p_list->push_back(PropertyInfo(Variant::OBJECT, "stream", PROPERTY_HINT_RESOURCE_TYPE, "AudioStream"));
- p_list->push_back(PropertyInfo(Variant::FLOAT, "start_offset", PROPERTY_HINT_RANGE, "0,3600,0.01,or_greater"));
- p_list->push_back(PropertyInfo(Variant::FLOAT, "end_offset", PROPERTY_HINT_RANGE, "0,3600,0.01,or_greater"));
- } break;
- case Animation::TYPE_ANIMATION: {
- if (key_ofs_map.size() > 1) {
- break;
+ for (int i = 0; i < args.size(); i++) {
+ p_list->push_back(PropertyInfo(Variant::INT, "args/" + itos(i) + "/type", PROPERTY_HINT_ENUM, vtypes));
+ if (args[i].get_type() != Variant::NIL) {
+ p_list->push_back(PropertyInfo(args[i].get_type(), "args/" + itos(i) + "/value"));
}
+ }
+ } break;
+ case Animation::TYPE_BEZIER: {
+ p_list->push_back(PropertyInfo(Variant::FLOAT, "value"));
+ p_list->push_back(PropertyInfo(Variant::VECTOR2, "in_handle"));
+ p_list->push_back(PropertyInfo(Variant::VECTOR2, "out_handle"));
+ p_list->push_back(PropertyInfo(Variant::INT, "handle_mode", PROPERTY_HINT_ENUM, "Free,Linear,Balanced,Mirrored"));
+ } break;
+ case Animation::TYPE_AUDIO: {
+ p_list->push_back(PropertyInfo(Variant::OBJECT, "stream", PROPERTY_HINT_RESOURCE_TYPE, "AudioStream"));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, "start_offset", PROPERTY_HINT_RANGE, "0,3600,0.0001,or_greater"));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, "end_offset", PROPERTY_HINT_RANGE, "0,3600,0.0001,or_greater"));
+ } break;
+ case Animation::TYPE_ANIMATION: {
+ if (key_ofs_map.size() > 1) {
+ break;
+ }
- String animations;
-
- if (root_path && root_path->has_node(animation->track_get_path(first_track))) {
- AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(root_path->get_node(animation->track_get_path(first_track)));
- if (ap) {
- List<StringName> anims;
- ap->get_animation_list(&anims);
- for (List<StringName>::Element *G = anims.front(); G; G = G->next()) {
- if (!animations.is_empty()) {
- animations += ",";
- }
+ String animations;
- animations += String(G->get());
+ if (root_path && root_path->has_node(animation->track_get_path(first_track))) {
+ AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(root_path->get_node(animation->track_get_path(first_track)));
+ if (ap) {
+ List<StringName> anims;
+ ap->get_animation_list(&anims);
+ for (List<StringName>::Element *G = anims.front(); G; G = G->next()) {
+ if (!animations.is_empty()) {
+ animations += ",";
}
+
+ animations += String(G->get());
}
}
+ }
- if (!animations.is_empty()) {
- animations += ",";
- }
- animations += "[stop]";
+ if (!animations.is_empty()) {
+ animations += ",";
+ }
+ animations += "[stop]";
- p_list->push_back(PropertyInfo(Variant::STRING_NAME, "animation", PROPERTY_HINT_ENUM, animations));
- } break;
- }
+ p_list->push_back(PropertyInfo(Variant::STRING_NAME, "animation", PROPERTY_HINT_ENUM, animations));
+ } break;
}
}
+}
- Ref<Animation> animation;
-
- RBMap<int, List<float>> key_ofs_map;
- RBMap<int, NodePath> base_map;
- PropertyInfo hint;
-
- Node *root_path = nullptr;
-
- bool use_fps = false;
-
- Ref<EditorUndoRedoManager> undo_redo;
-
- void notify_change() {
- notify_property_list_changed();
- }
+void AnimationMultiTrackKeyEdit::notify_change() {
+ notify_property_list_changed();
+}
- Node *get_root_path() {
- return root_path;
- }
+Node *AnimationMultiTrackKeyEdit::get_root_path() {
+ return root_path;
+}
- void set_use_fps(bool p_enable) {
- use_fps = p_enable;
- notify_property_list_changed();
- }
-};
+void AnimationMultiTrackKeyEdit::set_use_fps(bool p_enable) {
+ use_fps = p_enable;
+ notify_property_list_changed();
+}
void AnimationTimelineEdit::_zoom_changed(double) {
queue_redraw();
@@ -1413,12 +1246,13 @@ void AnimationTimelineEdit::_anim_length_changed(double p_new_len) {
return;
}
- p_new_len = MAX(0.001, p_new_len);
+ p_new_len = MAX(0.0001, p_new_len);
if (use_fps && animation->get_step() > 0) {
p_new_len *= animation->get_step();
}
editing = true;
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Change Animation Length"));
undo_redo->add_do_method(animation.ptr(), "set_length", p_new_len);
undo_redo->add_undo_method(animation.ptr(), "set_length", animation->get_length());
@@ -1431,6 +1265,7 @@ void AnimationTimelineEdit::_anim_length_changed(double p_new_len) {
void AnimationTimelineEdit::_anim_loop_pressed() {
if (!read_only) {
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Change Animation Loop"));
switch (animation->get_loop_mode()) {
case Animation::LOOP_NONE: {
@@ -1530,7 +1365,7 @@ void AnimationTimelineEdit::_notification(int p_what) {
float l = animation->get_length();
if (l <= 0) {
- l = 0.001; // Avoid crashor.
+ l = 0.0001; // Avoid crashor.
}
Ref<Texture2D> hsize_icon = get_theme_icon(SNAME("Hsize"), SNAME("EditorIcons"));
@@ -1591,7 +1426,7 @@ void AnimationTimelineEdit::_notification(int p_what) {
end_px = zoomw;
}
- draw_rect(Rect2(Point2(get_name_limit() + begin_px, 0), Point2(end_px - begin_px - 1, h)), timecolor);
+ draw_rect(Rect2(Point2(get_name_limit() + begin_px, 0), Point2(end_px - begin_px, h)), timecolor);
}
}
@@ -1678,6 +1513,7 @@ void AnimationTimelineEdit::_notification(int p_what) {
}
draw_line(Vector2(0, get_size().height), get_size(), linecolor, Math::round(EDSCALE));
+ update_values();
} break;
}
}
@@ -1700,7 +1536,6 @@ void AnimationTimelineEdit::set_animation(const Ref<Animation> &p_animation, boo
play_position->hide();
}
queue_redraw();
- update_values();
}
Size2 AnimationTimelineEdit::get_minimum_size() const {
@@ -1712,10 +1547,6 @@ Size2 AnimationTimelineEdit::get_minimum_size() const {
return ms;
}
-void AnimationTimelineEdit::set_undo_redo(Ref<EditorUndoRedoManager> p_undo_redo) {
- undo_redo = p_undo_redo;
-}
-
void AnimationTimelineEdit::set_zoom(Range *p_zoom) {
zoom = p_zoom;
zoom->connect("value_changed", callable_mp(this, &AnimationTimelineEdit::_zoom_changed));
@@ -1749,9 +1580,12 @@ void AnimationTimelineEdit::update_values() {
length->set_step(1);
length->set_tooltip_text(TTR("Animation length (frames)"));
time_icon->set_tooltip_text(TTR("Animation length (frames)"));
+ if (track_edit) {
+ track_edit->editor->_update_key_edit();
+ }
} else {
length->set_value(animation->get_length());
- length->set_step(0.001);
+ length->set_step(0.0001);
length->set_tooltip_text(TTR("Animation length (seconds)"));
time_icon->set_tooltip_text(TTR("Animation length (seconds)"));
}
@@ -1893,7 +1727,6 @@ void AnimationTimelineEdit::_zoom_callback(Vector2 p_scroll_vec, Vector2 p_origi
void AnimationTimelineEdit::set_use_fps(bool p_use_fps) {
use_fps = p_use_fps;
- update_values();
queue_redraw();
}
@@ -1943,9 +1776,9 @@ AnimationTimelineEdit::AnimationTimelineEdit() {
time_icon->set_tooltip_text(TTR("Animation length (seconds)"));
len_hb->add_child(time_icon);
length = memnew(EditorSpinSlider);
- length->set_min(0.001);
+ length->set_min(0.0001);
length->set_max(36000);
- length->set_step(0.001);
+ length->set_step(0.0001);
length->set_allow_greater(true);
length->set_custom_minimum_size(Vector2(70 * EDSCALE, 0));
length->set_hide_slider(true);
@@ -2051,7 +1884,7 @@ void AnimationTrackEdit::_notification(int p_what) {
} else if (animation->track_get_type(track) == Animation::TYPE_AUDIO) {
text = TTR("Audio Clips:");
} else if (animation->track_get_type(track) == Animation::TYPE_ANIMATION) {
- text = TTR("Anim Clips:");
+ text = TTR("Animation Clips:");
} else {
text += anim_path.get_concatenated_subnames();
}
@@ -2127,10 +1960,9 @@ void AnimationTrackEdit::_notification(int p_what) {
get_theme_icon(SNAME("InterpLinearAngle"), SNAME("EditorIcons")),
get_theme_icon(SNAME("InterpCubicAngle"), SNAME("EditorIcons")),
};
- Ref<Texture2D> cont_icon[4] = {
+ Ref<Texture2D> cont_icon[3] = {
get_theme_icon(SNAME("TrackContinuous"), SNAME("EditorIcons")),
get_theme_icon(SNAME("TrackDiscrete"), SNAME("EditorIcons")),
- get_theme_icon(SNAME("TrackTrigger"), SNAME("EditorIcons")),
get_theme_icon(SNAME("TrackCapture"), SNAME("EditorIcons"))
};
@@ -2514,14 +2346,6 @@ Size2 AnimationTrackEdit::get_minimum_size() const {
return Vector2(1, max_h + separation);
}
-void AnimationTrackEdit::set_undo_redo(Ref<EditorUndoRedoManager> p_undo_redo) {
- undo_redo = p_undo_redo;
-}
-
-Ref<EditorUndoRedoManager> AnimationTrackEdit::get_undo_redo() const {
- return undo_redo;
-}
-
void AnimationTrackEdit::set_timeline(AnimationTimelineEdit *p_timeline) {
timeline = p_timeline;
timeline->set_track_edit(this);
@@ -2568,6 +2392,7 @@ void AnimationTrackEdit::_zoom_changed() {
}
void AnimationTrackEdit::_path_submitted(const String &p_text) {
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Change Track Path"));
undo_redo->add_do_method(animation.ptr(), "track_set_path", track, p_text);
undo_redo->add_undo_method(animation.ptr(), "track_set_path", track, animation->track_get_path(track));
@@ -2671,7 +2496,7 @@ String AnimationTrackEdit::get_tooltip(const Point2 &p_pos) const {
}
if (key_idx != -1) {
- String text = TTR("Time (s):") + " " + rtos(animation->track_get_key_time(track, key_idx)) + "\n";
+ String text = TTR("Time (s):") + " " + TS->format_number(rtos(Math::snapped(animation->track_get_key_time(track, key_idx), 0.0001))) + "\n";
switch (animation->track_get_type(track)) {
case Animation::TYPE_POSITION_3D: {
Vector3 t = animation->track_get_key_value(track, key_idx);
@@ -2805,6 +2630,7 @@ void AnimationTrackEdit::gui_input(const Ref<InputEvent> &p_event) {
if (!read_only) {
if (check_rect.has_point(pos)) {
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Toggle Track Enabled"));
undo_redo->add_do_method(animation.ptr(), "track_set_enabled", track, !animation->track_is_enabled(track));
undo_redo->add_undo_method(animation.ptr(), "track_set_enabled", track, animation->track_is_enabled(track));
@@ -2828,7 +2654,6 @@ void AnimationTrackEdit::gui_input(const Ref<InputEvent> &p_event) {
menu->clear();
menu->add_icon_item(get_theme_icon(SNAME("TrackContinuous"), SNAME("EditorIcons")), TTR("Continuous"), MENU_CALL_MODE_CONTINUOUS);
menu->add_icon_item(get_theme_icon(SNAME("TrackDiscrete"), SNAME("EditorIcons")), TTR("Discrete"), MENU_CALL_MODE_DISCRETE);
- menu->add_icon_item(get_theme_icon(SNAME("TrackTrigger"), SNAME("EditorIcons")), TTR("Trigger"), MENU_CALL_MODE_TRIGGER);
menu->add_icon_item(get_theme_icon(SNAME("TrackCapture"), SNAME("EditorIcons")), TTR("Capture"), MENU_CALL_MODE_CAPTURE);
menu->reset_size();
@@ -3193,9 +3018,9 @@ void AnimationTrackEdit::_menu_selected(int p_index) {
switch (p_index) {
case MENU_CALL_MODE_CONTINUOUS:
case MENU_CALL_MODE_DISCRETE:
- case MENU_CALL_MODE_TRIGGER:
case MENU_CALL_MODE_CAPTURE: {
Animation::UpdateMode update_mode = Animation::UpdateMode(p_index);
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Change Animation Update Mode"));
undo_redo->add_do_method(animation.ptr(), "value_track_set_update_mode", track, update_mode);
undo_redo->add_undo_method(animation.ptr(), "value_track_set_update_mode", track, animation->value_track_get_update_mode(track));
@@ -3209,6 +3034,7 @@ void AnimationTrackEdit::_menu_selected(int p_index) {
case MENU_INTERPOLATION_LINEAR_ANGLE:
case MENU_INTERPOLATION_CUBIC_ANGLE: {
Animation::InterpolationType interp_mode = Animation::InterpolationType(p_index - MENU_INTERPOLATION_NEAREST);
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Change Animation Interpolation Mode"));
undo_redo->add_do_method(animation.ptr(), "track_set_interpolation_type", track, interp_mode);
undo_redo->add_undo_method(animation.ptr(), "track_set_interpolation_type", track, animation->track_get_interpolation_type(track));
@@ -3218,6 +3044,7 @@ void AnimationTrackEdit::_menu_selected(int p_index) {
case MENU_LOOP_WRAP:
case MENU_LOOP_CLAMP: {
bool loop_wrap = p_index == MENU_LOOP_WRAP;
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Change Animation Loop Mode"));
undo_redo->add_do_method(animation.ptr(), "track_set_interpolation_loop_wrap", track, loop_wrap);
undo_redo->add_undo_method(animation.ptr(), "track_set_interpolation_loop_wrap", track, animation->track_get_interpolation_loop_wrap(track));
@@ -3446,8 +3273,7 @@ void AnimationTrackEditor::set_animation(const Ref<Animation> &p_anim, bool p_re
track_edits[_get_track_selected()]->release_focus();
}
if (animation.is_valid()) {
- animation->disconnect("tracks_changed", callable_mp(this, &AnimationTrackEditor::_animation_changed));
- animation->disconnect("changed", callable_mp(this, &AnimationTrackEditor::_sync_animation_change));
+ animation->disconnect("changed", callable_mp(this, &AnimationTrackEditor::_animation_changed));
_clear_selection();
}
animation = p_anim;
@@ -3458,8 +3284,7 @@ void AnimationTrackEditor::set_animation(const Ref<Animation> &p_anim, bool p_re
_update_tracks();
if (animation.is_valid()) {
- animation->connect("tracks_changed", callable_mp(this, &AnimationTrackEditor::_animation_changed), CONNECT_DEFERRED);
- animation->connect("changed", callable_mp(this, &AnimationTrackEditor::_sync_animation_change), CONNECT_DEFERRED);
+ animation->connect("changed", callable_mp(this, &AnimationTrackEditor::_animation_changed));
hscroll->show();
edit->set_disabled(read_only);
@@ -3613,7 +3438,8 @@ void AnimationTrackEditor::_animation_track_remove_request(int p_track, Ref<Anim
}
int idx = p_track;
if (idx >= 0 && idx < p_from_animation->get_track_count()) {
- undo_redo->create_action(TTR("Remove Anim Track"));
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
+ undo_redo->create_action(TTR("Remove Anim Track"), UndoRedo::MERGE_DISABLE, p_from_animation.ptr());
// Remove corresponding reset tracks if they are no longer needed.
AnimationPlayer *player = AnimationPlayerEditor::get_singleton()->get_player();
@@ -3813,7 +3639,8 @@ void AnimationTrackEditor::_query_insert(const InsertData &p_id) {
}
void AnimationTrackEditor::_insert_track(bool p_reset_wanted, bool p_create_beziers) {
- undo_redo->create_action(TTR("Anim Insert"));
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
+ undo_redo->create_action(TTR("Animation Insert Key"));
Ref<Animation> reset_anim;
if (p_reset_wanted) {
@@ -3850,7 +3677,7 @@ void AnimationTrackEditor::insert_transform_key(Node3D *p_node, const String &p_
}
// Let's build a node path.
- String path = root->get_path_to(p_node);
+ String path = root->get_path_to(p_node, true);
if (!p_sub.is_empty()) {
path += ":" + p_sub;
}
@@ -3890,7 +3717,7 @@ bool AnimationTrackEditor::has_track(Node3D *p_node, const String &p_sub, const
}
// Let's build a node path.
- String path = root->get_path_to(p_node);
+ String path = root->get_path_to(p_node, true);
if (!p_sub.is_empty()) {
path += ":" + p_sub;
}
@@ -3938,11 +3765,10 @@ void AnimationTrackEditor::_insert_animation_key(NodePath p_path, const Variant
void AnimationTrackEditor::insert_node_value_key(Node *p_node, const String &p_property, const Variant &p_value, bool p_only_if_exists) {
ERR_FAIL_COND(!root);
- // Let's build a node path.
+ // Let's build a node path.
Node *node = p_node;
-
- String path = root->get_path_to(node);
+ String path = root->get_path_to(node, true);
if (Object::cast_to<AnimationPlayer>(node) && p_property == "current_animation") {
if (node == AnimationPlayerEditor::get_singleton()->get_player()) {
@@ -4036,14 +3862,13 @@ void AnimationTrackEditor::insert_value_key(const String &p_property, const Vari
EditorSelectionHistory *history = EditorNode::get_singleton()->get_editor_selection_history();
ERR_FAIL_COND(!root);
- // Let's build a node path.
ERR_FAIL_COND(history->get_path_size() == 0);
Object *obj = ObjectDB::get_instance(history->get_path_object(0));
ERR_FAIL_COND(!Object::cast_to<Node>(obj));
+ // Let's build a node path.
Node *node = Object::cast_to<Node>(obj);
-
- String path = root->get_path_to(node);
+ String path = root->get_path_to(node, true);
if (Object::cast_to<AnimationPlayer>(node) && p_property == "current_animation") {
if (node == AnimationPlayerEditor::get_singleton()->get_player()) {
@@ -4143,6 +3968,7 @@ Ref<Animation> AnimationTrackEditor::_create_and_get_reset_animation() {
Ref<Animation> reset_anim;
reset_anim.instantiate();
reset_anim->set_length(ANIM_MIN_LENGTH);
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->add_do_method(al.ptr(), "add_animation", SceneStringNames::get_singleton()->RESET, reset_anim);
undo_redo->add_do_method(AnimationPlayerEditor::get_singleton(), "_animation_player_changed", player);
undo_redo->add_undo_method(al.ptr(), "remove_animation", SceneStringNames::get_singleton()->RESET);
@@ -4152,7 +3978,8 @@ Ref<Animation> AnimationTrackEditor::_create_and_get_reset_animation() {
}
void AnimationTrackEditor::_confirm_insert_list() {
- undo_redo->create_action(TTR("Anim Create & Insert"));
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
+ undo_redo->create_action(TTR("Animation Insert Key"));
bool create_reset = insert_confirm_reset->is_visible() && insert_confirm_reset->is_pressed();
Ref<Animation> reset_anim;
@@ -4318,13 +4145,10 @@ AnimationTrackEditor::TrackIndices AnimationTrackEditor::_confirm_insert(InsertD
h.type == Variant::TRANSFORM3D) {
update_mode = Animation::UPDATE_CONTINUOUS;
}
-
- if (h.usage & PROPERTY_USAGE_ANIMATE_AS_TRIGGER) {
- update_mode = Animation::UPDATE_TRIGGER;
- }
}
}
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
if (create_normal_track) {
if (p_create_beziers) {
bool valid;
@@ -4342,7 +4166,6 @@ AnimationTrackEditor::TrackIndices AnimationTrackEditor::_confirm_insert(InsertD
}
}
created = true;
- undo_redo->create_action(TTR("Anim Insert Track & Key"));
p_id.track_idx = p_next_tracks.normal;
@@ -4351,9 +4174,6 @@ AnimationTrackEditor::TrackIndices AnimationTrackEditor::_confirm_insert(InsertD
if (p_id.type == Animation::TYPE_VALUE) {
undo_redo->add_do_method(animation.ptr(), "value_track_set_update_mode", p_id.track_idx, update_mode);
}
-
- } else {
- undo_redo->create_action(TTR("Anim Insert Key"));
}
float time = timeline->get_play_position();
@@ -4396,7 +4216,7 @@ AnimationTrackEditor::TrackIndices AnimationTrackEditor::_confirm_insert(InsertD
p_next_tracks.normal++;
} else {
undo_redo->add_undo_method(animation.ptr(), "track_remove_key_at_time", p_id.track_idx, time);
- int existing = animation->track_find_key(p_id.track_idx, time, true);
+ int existing = animation->track_find_key(p_id.track_idx, time, Animation::FIND_MODE_APPROX);
if (existing != -1) {
Variant v = animation->track_get_key_value(p_id.track_idx, existing);
float trans = animation->track_get_key_transition(p_id.track_idx, existing);
@@ -4424,8 +4244,6 @@ AnimationTrackEditor::TrackIndices AnimationTrackEditor::_confirm_insert(InsertD
}
}
- undo_redo->commit_action();
-
return p_next_tracks;
}
@@ -4609,7 +4427,6 @@ void AnimationTrackEditor::_update_tracks() {
track_vbox->add_child(track_edit);
}
- track_edit->set_undo_redo(undo_redo);
track_edit->set_timeline(timeline);
track_edit->set_root(root);
track_edit->set_animation_and_track(animation, i, file_read_only);
@@ -4650,29 +4467,25 @@ void AnimationTrackEditor::_redraw_groups() {
}
}
-void AnimationTrackEditor::_sync_animation_change() {
- bezier_edit->queue_redraw();
-}
-
void AnimationTrackEditor::_animation_changed() {
if (animation_changing_awaiting_update) {
return; // All will be updated, don't bother with anything.
}
if (key_edit) {
- _update_key_edit();
- }
-
- if (key_edit && key_edit->setting) {
- // If editing a key, just redraw the edited track, makes refresh less costly.
- if (key_edit->track < track_edits.size()) {
- if (animation->track_get_type(key_edit->track) == Animation::TYPE_BEZIER) {
- bezier_edit->queue_redraw();
- } else {
- track_edits[key_edit->track]->queue_redraw();
+ if (key_edit->setting) {
+ // If editing a key, just redraw the edited track, makes refresh less costly.
+ if (key_edit->track < track_edits.size()) {
+ if (animation->track_get_type(key_edit->track) == Animation::TYPE_BEZIER) {
+ bezier_edit->queue_redraw();
+ } else {
+ track_edits[key_edit->track]->queue_redraw();
+ }
}
+ return;
+ } else {
+ _update_key_edit();
}
- return;
}
animation_changing_awaiting_update = true;
@@ -4787,12 +4600,14 @@ void AnimationTrackEditor::_update_scroll(double) {
}
void AnimationTrackEditor::_update_step(double p_new_step) {
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Change Animation Step"));
float step_value = p_new_step;
if (timeline->is_using_fps()) {
if (step_value != 0.0) {
step_value = 1.0 / step_value;
}
+ timeline->queue_redraw();
}
undo_redo->add_do_method(animation.ptr(), "set_step", step_value);
undo_redo->add_undo_method(animation.ptr(), "set_step", animation->get_step());
@@ -4812,6 +4627,7 @@ void AnimationTrackEditor::_dropped_track(int p_from_track, int p_to_track) {
}
_clear_selection(true);
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Rearrange Tracks"));
undo_redo->add_do_method(animation.ptr(), "track_move_to", p_from_track, p_to_track);
// Take into account that the position of the tracks that come after the one removed will change.
@@ -4826,7 +4642,7 @@ void AnimationTrackEditor::_new_track_node_selected(NodePath p_path) {
ERR_FAIL_COND(!root);
Node *node = get_node(p_path);
ERR_FAIL_COND(!node);
- NodePath path_to = root->get_path_to(node);
+ NodePath path_to = root->get_path_to(node, true);
if (adding_track_type == Animation::TYPE_BLEND_SHAPE && !node->is_class("MeshInstance3D")) {
EditorNode::get_singleton()->show_warning(TTR("Blend Shape tracks only apply to MeshInstance3D nodes."));
@@ -4855,6 +4671,7 @@ void AnimationTrackEditor::_new_track_node_selected(NodePath p_path) {
case Animation::TYPE_ROTATION_3D:
case Animation::TYPE_SCALE_3D:
case Animation::TYPE_METHOD: {
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Add Track"));
undo_redo->add_do_method(animation.ptr(), "add_track", adding_track_type);
undo_redo->add_do_method(animation.ptr(), "track_set_path", animation->get_track_count(), path_to);
@@ -4883,6 +4700,7 @@ void AnimationTrackEditor::_new_track_node_selected(NodePath p_path) {
return;
}
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Add Track"));
undo_redo->add_do_method(animation.ptr(), "add_track", adding_track_type);
undo_redo->add_do_method(animation.ptr(), "track_set_path", animation->get_track_count(), path_to);
@@ -4901,6 +4719,7 @@ void AnimationTrackEditor::_new_track_node_selected(NodePath p_path) {
return;
}
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Add Track"));
undo_redo->add_do_method(animation.ptr(), "add_track", adding_track_type);
undo_redo->add_do_method(animation.ptr(), "track_set_path", animation->get_track_count(), path_to);
@@ -4925,6 +4744,7 @@ void AnimationTrackEditor::_add_track(int p_type) {
void AnimationTrackEditor::_new_track_property_selected(String p_name) {
String full_path = String(adding_track_path) + ":" + p_name;
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
if (adding_track_type == Animation::TYPE_VALUE) {
Animation::UpdateMode update_mode = Animation::UPDATE_DISCRETE;
{
@@ -4946,10 +4766,6 @@ void AnimationTrackEditor::_new_track_property_selected(String p_name) {
h.type == Variant::TRANSFORM3D) {
update_mode = Animation::UPDATE_CONTINUOUS;
}
-
- if (h.usage & PROPERTY_USAGE_ANIMATE_AS_TRIGGER) {
- update_mode = Animation::UPDATE_TRIGGER;
- }
}
undo_redo->create_action(TTR("Add Track"));
@@ -5015,10 +4831,11 @@ void AnimationTrackEditor::_insert_key_from_track(float p_ofs, int p_track) {
if (snap->is_pressed() && step->get_value() != 0) {
p_ofs = snap_time(p_ofs);
}
- while (animation->track_find_key(p_track, p_ofs, true) != -1) { // Make sure insertion point is valid.
- p_ofs += 0.001;
+ while (animation->track_find_key(p_track, p_ofs, Animation::FIND_MODE_APPROX) != -1) { // Make sure insertion point is valid.
+ p_ofs += 0.0001;
}
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
switch (animation->track_get_type(p_track)) {
case Animation::TYPE_POSITION_3D: {
if (!root->has_node(animation->track_get_path(p_track))) {
@@ -5174,6 +4991,7 @@ void AnimationTrackEditor::_add_method_key(const String &p_method) {
}
d["args"] = params;
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Add Method Track Key"));
undo_redo->add_do_method(animation.ptr(), "track_insert_key", insert_key_from_track_call_track, insert_key_from_track_call_ofs, d);
undo_redo->add_undo_method(animation.ptr(), "track_remove_key_at_time", insert_key_from_track_call_track, insert_key_from_track_call_ofs);
@@ -5283,13 +5101,17 @@ void AnimationTrackEditor::_update_key_edit() {
key_edit->track = selection.front()->key().track;
key_edit->use_fps = timeline->is_using_fps();
- float ofs = animation->track_get_key_time(key_edit->track, selection.front()->key().key);
+ int key_id = selection.front()->key().key;
+ if (key_id >= animation->track_get_key_count(key_edit->track)) {
+ _clear_key_edit();
+ return; // Probably in the process of rearranging the keys.
+ }
+ float ofs = animation->track_get_key_time(key_edit->track, key_id);
key_edit->key_ofs = ofs;
key_edit->root_path = root;
NodePath np;
key_edit->hint = _find_hint_for_track(key_edit->track, np);
- key_edit->undo_redo = undo_redo;
key_edit->base = np;
EditorNode::get_singleton()->push_item(key_edit);
@@ -5312,18 +5134,19 @@ void AnimationTrackEditor::_update_key_edit() {
base_map[track] = NodePath();
}
+ int key_id = E.key.key;
+ if (key_id >= animation->track_get_key_count(track)) {
+ _clear_key_edit();
+ return; // Probably in the process of rearranging the keys.
+ }
key_ofs_map[track].push_back(animation->track_get_key_time(track, E.key.key));
}
multi_key_edit->key_ofs_map = key_ofs_map;
multi_key_edit->base_map = base_map;
multi_key_edit->hint = _find_hint_for_track(first_track, base_map[first_track]);
-
multi_key_edit->use_fps = timeline->is_using_fps();
-
multi_key_edit->root_path = root;
- multi_key_edit->undo_redo = undo_redo;
-
EditorNode::get_singleton()->push_item(multi_key_edit);
}
}
@@ -5341,7 +5164,7 @@ void AnimationTrackEditor::_select_at_anim(const Ref<Animation> &p_anim, int p_t
return;
}
- int idx = animation->track_find_key(p_track, p_pos, true);
+ int idx = animation->track_find_key(p_track, p_pos, Animation::FIND_MODE_APPROX);
ERR_FAIL_COND(idx < 0);
SelectedKey sk;
@@ -5351,10 +5174,12 @@ void AnimationTrackEditor::_select_at_anim(const Ref<Animation> &p_anim, int p_t
ki.pos = p_pos;
selection.insert(sk, ki);
+ _update_key_edit();
}
void AnimationTrackEditor::_move_selection_commit() {
- undo_redo->create_action(TTR("Anim Move Keys"));
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
+ undo_redo->create_action(TTR("Animation Move Keys"));
List<_AnimMoveRestore> to_restore;
@@ -5366,7 +5191,7 @@ void AnimationTrackEditor::_move_selection_commit() {
// 2 - Remove overlapped keys.
for (RBMap<SelectedKey, KeyInfo>::Element *E = selection.back(); E; E = E->prev()) {
float newtime = snap_time(E->get().pos + motion);
- int idx = animation->track_find_key(E->key().track, newtime, true);
+ int idx = animation->track_find_key(E->key().track, newtime, Animation::FIND_MODE_APPROX);
if (idx == -1) {
continue;
}
@@ -5426,7 +5251,6 @@ void AnimationTrackEditor::_move_selection_commit() {
undo_redo->add_do_method(this, "_redraw_tracks");
undo_redo->add_undo_method(this, "_redraw_tracks");
undo_redo->commit_action();
- _update_key_edit();
}
void AnimationTrackEditor::_move_selection_cancel() {
@@ -5606,7 +5430,8 @@ void AnimationTrackEditor::_anim_duplicate_keys(bool transpose) {
int start_track = transpose ? _get_track_selected() : top_track;
- undo_redo->create_action(TTR("Anim Duplicate Keys"));
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
+ undo_redo->create_action(TTR("Animation Duplicate Keys"));
List<Pair<int, float>> new_selection_values;
@@ -5626,7 +5451,7 @@ void AnimationTrackEditor::_anim_duplicate_keys(bool transpose) {
continue;
}
- int existing_idx = animation->track_find_key(dst_track, dst_time, true);
+ int existing_idx = animation->track_find_key(dst_track, dst_time, Animation::FIND_MODE_APPROX);
undo_redo->add_do_method(animation.ptr(), "track_insert_key", dst_track, dst_time, animation->track_get_key_value(E->key().track, E->key().key), animation->track_get_key_transition(E->key().track, E->key().key));
undo_redo->add_undo_method(animation.ptr(), "track_remove_key_at_time", dst_track, dst_time);
@@ -5656,7 +5481,6 @@ void AnimationTrackEditor::_anim_duplicate_keys(bool transpose) {
undo_redo->add_do_method(this, "_redraw_tracks");
undo_redo->add_undo_method(this, "_redraw_tracks");
undo_redo->commit_action();
- _update_key_edit();
}
}
@@ -5836,6 +5660,7 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) {
}
int base_track = animation->get_track_count();
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Paste Tracks"));
for (int i = 0; i < track_clipboard.size(); i++) {
undo_redo->add_do_method(animation.ptr(), "add_track", track_clipboard[i].track_type);
@@ -5903,11 +5728,10 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) {
}
float s = scale->get_value();
- if (s == 0) {
- ERR_PRINT("Can't scale to 0");
- }
+ ERR_FAIL_COND_MSG(s == 0, "Can't scale to 0.");
- undo_redo->create_action(TTR("Anim Scale Keys"));
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
+ undo_redo->create_action(TTR("Animation Scale Keys"));
List<_AnimMoveRestore> to_restore;
@@ -5918,7 +5742,7 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) {
// 2 - Remove overlapped keys.
for (RBMap<SelectedKey, KeyInfo>::Element *E = selection.back(); E; E = E->prev()) {
float newtime = (E->get().pos - from_t) * s + from_t;
- int idx = animation->track_find_key(E->key().track, newtime, true);
+ int idx = animation->track_find_key(E->key().track, newtime, Animation::FIND_MODE_APPROX);
if (idx == -1) {
continue;
}
@@ -5980,14 +5804,13 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) {
undo_redo->add_do_method(this, "_redraw_tracks");
undo_redo->add_undo_method(this, "_redraw_tracks");
undo_redo->commit_action();
- _update_key_edit();
-
} break;
case EDIT_EASE_SELECTION: {
ease_dialog->popup_centered(Size2(200, 100) * EDSCALE);
} break;
case EDIT_EASE_CONFIRM: {
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Make Easing Keys"));
Tween::TransitionType transition_type = static_cast<Tween::TransitionType>(transition_selection->get_selected_id());
@@ -6094,7 +5917,8 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) {
_anim_duplicate_keys(true);
} break;
case EDIT_ADD_RESET_KEY: {
- undo_redo->create_action(TTR("Anim Add RESET Keys"));
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
+ undo_redo->create_action(TTR("Animation Add RESET Keys"));
Ref<Animation> reset = _create_and_get_reset_animation();
int reset_tracks = reset->get_track_count();
@@ -6129,7 +5953,7 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) {
undo_redo->add_do_method(reset.ptr(), "track_set_path", dst_track, path);
undo_redo->add_undo_method(reset.ptr(), "remove_track", dst_track);
} else {
- existing_idx = reset->track_find_key(dst_track, 0, true);
+ existing_idx = reset->track_find_key(dst_track, 0, Animation::FIND_MODE_APPROX);
}
undo_redo->add_do_method(reset.ptr(), "track_insert_key", dst_track, 0, animation->track_get_key_value(sk.track, sk.key), animation->track_get_key_transition(sk.track, sk.key));
@@ -6154,7 +5978,8 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) {
}
if (selection.size()) {
- undo_redo->create_action(TTR("Anim Delete Keys"));
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
+ undo_redo->create_action(TTR("Animation Delete Keys"));
for (RBMap<SelectedKey, KeyInfo>::Element *E = selection.back(); E; E = E->prev()) {
undo_redo->add_do_method(animation.ptr(), "track_remove_key", E->key().track, E->key().key);
@@ -6184,6 +6009,7 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) {
bake_dialog->popup_centered(Size2(200, 100) * EDSCALE);
} break;
case EDIT_BAKE_ANIMATION_CONFIRM: {
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Bake Animation as Linear keys."));
int track_len = animation->get_track_count();
@@ -6304,6 +6130,7 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) {
animation->optimize(optimize_velocity_error->get_value(), optimize_angular_error->get_value(), optimize_precision_error->get_value());
_redraw_tracks();
_update_key_edit();
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->clear_history(true, undo_redo->get_history_id_for_object(animation.ptr()));
undo_redo->clear_history(true, undo_redo->get_history_id_for_object(this));
@@ -6373,6 +6200,7 @@ void AnimationTrackEditor::_cleanup_animation(Ref<Animation> p_animation) {
}
}
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->clear_history(true, undo_redo->get_history_id_for_object(animation.ptr()));
undo_redo->clear_history(true, undo_redo->get_history_id_for_object(this));
_update_tracks();
@@ -6538,8 +6366,6 @@ void AnimationTrackEditor::_pick_track_filter_input(const Ref<InputEvent> &p_ie)
}
AnimationTrackEditor::AnimationTrackEditor() {
- undo_redo = EditorNode::get_undo_redo();
-
main_panel = memnew(PanelContainer);
main_panel->set_focus_mode(FOCUS_ALL); // Allow panel to have focus so that shortcuts work as expected.
add_child(main_panel);
@@ -6564,7 +6390,6 @@ AnimationTrackEditor::AnimationTrackEditor() {
main_panel->add_child(info_message);
timeline = memnew(AnimationTimelineEdit);
- timeline->set_undo_redo(undo_redo);
timeline_vbox->add_child(timeline);
timeline->connect("timeline_changed", callable_mp(this, &AnimationTrackEditor::_timeline_changed));
timeline->connect("name_limit_changed", callable_mp(this, &AnimationTrackEditor::_name_limit_changed));
@@ -6587,7 +6412,6 @@ AnimationTrackEditor::AnimationTrackEditor() {
bezier_edit = memnew(AnimationBezierTrackEdit);
timeline_vbox->add_child(bezier_edit);
- bezier_edit->set_undo_redo(undo_redo);
bezier_edit->set_editor(this);
bezier_edit->set_timeline(timeline);
bezier_edit->hide();
@@ -6658,7 +6482,7 @@ AnimationTrackEditor::AnimationTrackEditor() {
step = memnew(EditorSpinSlider);
step->set_min(0);
step->set_max(1000000);
- step->set_step(0.001);
+ step->set_step(0.0001);
step->set_hide_slider(true);
step->set_custom_minimum_size(Size2(100, 0) * EDSCALE);
step->set_tooltip_text(TTR("Animation step value."));
@@ -6948,3 +6772,103 @@ AnimationTrackEditor::~AnimationTrackEditor() {
memdelete(multi_key_edit);
}
}
+
+// AnimationTrackKeyEditEditorPlugin
+
+void AnimationTrackKeyEditEditor::_time_edit_entered() {
+ int key = animation->track_find_key(track, key_ofs, Animation::FIND_MODE_APPROX);
+ if (key == -1) {
+ return;
+ }
+ key_data_cache.time = animation->track_get_key_time(track, key);
+ key_data_cache.transition = animation->track_get_key_transition(track, key);
+ key_data_cache.value = animation->track_get_key_value(track, key);
+}
+
+void AnimationTrackKeyEditEditor::_time_edit_exited() {
+ real_t new_time = spinner->get_value();
+
+ if (use_fps) {
+ real_t fps = animation->get_step();
+ if (fps > 0) {
+ fps = 1.0 / fps;
+ }
+ new_time /= fps;
+ }
+
+ if (Math::is_equal_approx(new_time, key_data_cache.time)) {
+ return; // No change.
+ }
+
+ int existing = animation->track_find_key(track, new_time, Animation::FIND_MODE_APPROX);
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
+ undo_redo->create_action(TTR("Animation Change Keyframe Time"), UndoRedo::MERGE_ENDS);
+
+ if (existing != -1) {
+ undo_redo->add_do_method(animation.ptr(), "track_remove_key_at_time", track, animation->track_get_key_time(track, existing));
+ }
+ undo_redo->add_do_method(animation.ptr(), "track_remove_key_at_time", track, key_data_cache.time);
+ undo_redo->add_do_method(animation.ptr(), "track_insert_key", track, new_time, key_data_cache.value, key_data_cache.transition);
+ undo_redo->add_undo_method(animation.ptr(), "track_remove_key_at_time", track, new_time);
+ undo_redo->add_undo_method(animation.ptr(), "track_insert_key", track, key_data_cache.time, key_data_cache.value, key_data_cache.transition);
+ if (existing != -1) {
+ undo_redo->add_undo_method(animation.ptr(), "track_insert_key", track, animation->track_get_key_time(track, existing), animation->track_get_key_value(track, existing), animation->track_get_key_transition(track, existing));
+ }
+
+ // Reselect key.
+ AnimationPlayerEditor *ape = AnimationPlayerEditor::get_singleton();
+ if (ape) {
+ AnimationTrackEditor *ate = ape->get_track_editor();
+ if (ate) {
+ undo_redo->add_do_method(ate, "_clear_selection_for_anim", animation);
+ undo_redo->add_undo_method(ate, "_clear_selection_for_anim", animation);
+ undo_redo->add_do_method(ate, "_select_at_anim", animation, track, new_time);
+ undo_redo->add_undo_method(ate, "_select_at_anim", animation, track, key_data_cache.time);
+ }
+ }
+
+ undo_redo->commit_action();
+}
+
+AnimationTrackKeyEditEditor::AnimationTrackKeyEditEditor(Ref<Animation> p_animation, int p_track, real_t p_key_ofs, bool p_use_fps) {
+ if (!p_animation.is_valid()) {
+ return;
+ }
+
+ animation = p_animation;
+ track = p_track;
+ key_ofs = p_key_ofs;
+ use_fps = p_use_fps;
+
+ set_label("Time");
+
+ spinner = memnew(EditorSpinSlider);
+ spinner->set_focus_mode(Control::FOCUS_CLICK);
+ spinner->set_min(0);
+ spinner->set_allow_greater(true);
+ spinner->set_allow_lesser(true);
+
+ if (use_fps) {
+ spinner->set_step(1);
+ spinner->set_hide_slider(true);
+ real_t fps = animation->get_step();
+ if (fps > 0) {
+ fps = 1.0 / fps;
+ }
+ spinner->set_value(key_ofs * fps);
+ } else {
+ spinner->set_step(0.0001);
+ spinner->set_value(key_ofs);
+ spinner->set_max(animation->get_length());
+ }
+
+ add_child(spinner);
+
+ spinner->connect("grabbed", callable_mp(this, &AnimationTrackKeyEditEditor::_time_edit_entered), CONNECT_DEFERRED);
+ spinner->connect("ungrabbed", callable_mp(this, &AnimationTrackKeyEditEditor::_time_edit_exited), CONNECT_DEFERRED);
+ spinner->connect("value_focus_entered", callable_mp(this, &AnimationTrackKeyEditEditor::_time_edit_entered), CONNECT_DEFERRED);
+ spinner->connect("value_focus_exited", callable_mp(this, &AnimationTrackKeyEditEditor::_time_edit_exited), CONNECT_DEFERRED);
+}
+
+AnimationTrackKeyEditEditor::~AnimationTrackKeyEditEditor() {
+}
diff --git a/editor/animation_track_editor.h b/editor/animation_track_editor.h
index 5c51921d93..5ae826bd5c 100644
--- a/editor/animation_track_editor.h
+++ b/editor/animation_track_editor.h
@@ -50,9 +50,83 @@
#include "scene/resources/animation.h"
#include "scene_tree_editor.h"
+class AnimationTrackEditor;
class AnimationTrackEdit;
class ViewPanner;
+class AnimationTrackKeyEdit : public Object {
+ GDCLASS(AnimationTrackKeyEdit, Object);
+
+public:
+ bool setting = false;
+ bool animation_read_only = false;
+
+ Ref<Animation> animation;
+ int track = -1;
+ float key_ofs = 0;
+ Node *root_path = nullptr;
+
+ PropertyInfo hint;
+ NodePath base;
+ bool use_fps = false;
+
+ bool _hide_script_from_inspector() { return true; }
+ bool _hide_metadata_from_inspector() { return true; }
+ bool _dont_undo_redo() { return true; }
+
+ bool _is_read_only() { return animation_read_only; }
+
+ void notify_change();
+ Node *get_root_path();
+ void set_use_fps(bool p_enable);
+
+protected:
+ static void _bind_methods();
+ void _fix_node_path(Variant &value);
+ void _update_obj(const Ref<Animation> &p_anim);
+ void _key_ofs_changed(const Ref<Animation> &p_anim, float from, float to);
+ 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;
+};
+
+class AnimationMultiTrackKeyEdit : public Object {
+ GDCLASS(AnimationMultiTrackKeyEdit, Object);
+
+public:
+ bool setting = false;
+ bool animation_read_only = false;
+
+ Ref<Animation> animation;
+
+ RBMap<int, List<float>> key_ofs_map;
+ RBMap<int, NodePath> base_map;
+ PropertyInfo hint;
+
+ Node *root_path = nullptr;
+
+ bool use_fps = false;
+
+ bool _hide_script_from_inspector() { return true; }
+ bool _hide_metadata_from_inspector() { return true; }
+ bool _dont_undo_redo() { return true; }
+
+ bool _is_read_only() { return animation_read_only; }
+
+ void notify_change();
+ Node *get_root_path();
+ void set_use_fps(bool p_enable);
+
+protected:
+ static void _bind_methods();
+ void _fix_node_path(Variant &value, NodePath &base);
+ void _update_obj(const Ref<Animation> &p_anim);
+ void _key_ofs_changed(const Ref<Animation> &p_anim, float from, float to);
+ 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;
+};
+
class AnimationTimelineEdit : public Range {
GDCLASS(AnimationTimelineEdit, Range);
@@ -79,7 +153,6 @@ class AnimationTimelineEdit : public Range {
void _anim_loop_pressed();
void _play_position_draw();
- Ref<EditorUndoRedoManager> undo_redo;
Rect2 hsize_rect;
bool editing = false;
@@ -113,7 +186,6 @@ public:
void set_track_edit(AnimationTrackEdit *p_track_edit);
void set_zoom(Range *p_zoom);
Range *get_zoom() const { return zoom; }
- void set_undo_redo(Ref<EditorUndoRedoManager> p_undo_redo);
void set_play_position(float p_pos);
float get_play_position() const;
@@ -131,15 +203,13 @@ public:
AnimationTimelineEdit();
};
-class AnimationTrackEditor;
-
class AnimationTrackEdit : public Control {
GDCLASS(AnimationTrackEdit, Control);
+ friend class AnimationTimelineEdit;
enum {
MENU_CALL_MODE_CONTINUOUS,
MENU_CALL_MODE_DISCRETE,
- MENU_CALL_MODE_TRIGGER,
MENU_CALL_MODE_CAPTURE,
MENU_INTERPOLATION_NEAREST,
MENU_INTERPOLATION_LINEAR,
@@ -155,7 +225,6 @@ class AnimationTrackEdit : public Control {
};
AnimationTimelineEdit *timeline = nullptr;
- Ref<EditorUndoRedoManager> undo_redo;
Popup *path_popup = nullptr;
LineEdit *path = nullptr;
Node *root = nullptr;
@@ -236,12 +305,10 @@ public:
Ref<Animation> get_animation() const;
AnimationTimelineEdit *get_timeline() const { return timeline; }
AnimationTrackEditor *get_editor() const { return editor; }
- Ref<EditorUndoRedoManager> get_undo_redo() const;
NodePath get_path() const;
void set_animation_and_track(const Ref<Animation> &p_animation, int p_track, bool p_read_only);
virtual Size2 get_minimum_size() const override;
- void set_undo_redo(Ref<EditorUndoRedoManager> p_undo_redo);
void set_timeline(AnimationTimelineEdit *p_timeline);
void set_editor(AnimationTrackEditor *p_editor);
void set_root(Node *p_root);
@@ -293,6 +360,7 @@ public:
class AnimationTrackEditor : public VBoxContainer {
GDCLASS(AnimationTrackEditor, VBoxContainer);
+ friend class AnimationTimelineEdit;
Ref<Animation> animation;
bool read_only = false;
@@ -326,7 +394,6 @@ class AnimationTrackEditor : public VBoxContainer {
bool animation_changing_awaiting_update = false;
void _animation_update(); // Updated by AnimationTrackEditor(this)
int _get_track_selected();
- void _sync_animation_change();
void _animation_changed();
void _update_tracks();
void _redraw_tracks();
@@ -338,8 +405,6 @@ class AnimationTrackEditor : public VBoxContainer {
void _animation_track_remove_request(int p_track, Ref<Animation> p_from_animation);
void _track_grab_focus(int p_track);
- Ref<EditorUndoRedoManager> undo_redo;
-
void _update_scroll(double);
void _update_step(double p_new_step);
void _update_length(double p_new_len);
@@ -433,7 +498,6 @@ class AnimationTrackEditor : public VBoxContainer {
AnimationTrackKeyEdit *key_edit = nullptr;
AnimationMultiTrackKeyEdit *multi_key_edit = nullptr;
void _update_key_edit();
-
void _clear_key_edit();
Control *box_selection = nullptr;
@@ -600,4 +664,30 @@ public:
~AnimationTrackEditor();
};
+// AnimationTrackKeyEditEditorPlugin
+
+class AnimationTrackKeyEditEditor : public EditorProperty {
+ GDCLASS(AnimationTrackKeyEditEditor, EditorProperty);
+
+ Ref<Animation> animation;
+ int track = -1;
+ real_t key_ofs = 0.0;
+ bool use_fps = false;
+
+ EditorSpinSlider *spinner = nullptr;
+
+ struct KeyDataCache {
+ real_t time = 0.0;
+ float transition = 0.0;
+ Variant value;
+ } key_data_cache;
+
+ void _time_edit_entered();
+ void _time_edit_exited();
+
+public:
+ AnimationTrackKeyEditEditor(Ref<Animation> p_animation, int p_track, real_t p_key_ofs, bool p_use_fps);
+ ~AnimationTrackKeyEditEditor();
+};
+
#endif // ANIMATION_TRACK_EDITOR_H
diff --git a/editor/animation_track_editor_plugins.cpp b/editor/animation_track_editor_plugins.cpp
index 971b671a0c..0ad62710eb 100644
--- a/editor/animation_track_editor_plugins.cpp
+++ b/editor/animation_track_editor_plugins.cpp
@@ -31,6 +31,7 @@
#include "animation_track_editor_plugins.h"
#include "editor/audio_stream_preview.h"
+#include "editor/editor_node.h"
#include "editor/editor_resource_preview.h"
#include "editor/editor_scale.h"
#include "editor/editor_undo_redo_manager.h"
@@ -830,8 +831,8 @@ Rect2 AnimationTrackEditTypeAudio::get_key_rect(int p_index, float p_pixels_sec)
len -= end_ofs;
len -= start_ofs;
- if (len <= 0.001) {
- len = 0.001;
+ if (len <= 0.0001) {
+ len = 0.0001;
}
if (get_animation()->track_get_key_count(get_track()) > p_index + 1) {
@@ -856,18 +857,14 @@ void AnimationTrackEditTypeAudio::draw_key(int p_index, float p_pixels_sec, int
float start_ofs = get_animation()->audio_track_get_key_start_offset(get_track(), p_index);
float end_ofs = get_animation()->audio_track_get_key_end_offset(get_track(), p_index);
+ int px_offset = 0;
if (len_resizing && p_index == len_resizing_index) {
- float ofs_local = -len_resizing_rel / get_timeline()->get_zoom_scale();
+ float ofs_local = len_resizing_rel / get_timeline()->get_zoom_scale();
if (len_resizing_start) {
start_ofs += ofs_local;
- if (start_ofs < 0) {
- start_ofs = 0;
- }
+ px_offset = ofs_local * p_pixels_sec;
} else {
- end_ofs += ofs_local;
- if (end_ofs < 0) {
- end_ofs = 0;
- }
+ end_ofs -= ofs_local;
}
}
@@ -890,14 +887,14 @@ void AnimationTrackEditTypeAudio::draw_key(int p_index, float p_pixels_sec, int
len -= end_ofs;
len -= start_ofs;
- if (len <= 0.001) {
- len = 0.001;
+ if (len <= 0.0001) {
+ len = 0.0001;
}
int pixel_len = len * p_pixels_sec;
- int pixel_begin = p_x;
- int pixel_end = p_x + pixel_len;
+ int pixel_begin = px_offset + p_x;
+ int pixel_end = px_offset + p_x + pixel_len;
if (pixel_end < p_clip_left) {
return;
@@ -1017,14 +1014,15 @@ void AnimationTrackEditTypeAudio::drop_data(const Point2 &p_point, const Variant
ofs = get_editor()->snap_time(ofs);
- while (get_animation()->track_find_key(get_track(), ofs, true) != -1) { //make sure insertion point is valid
- ofs += 0.001;
+ while (get_animation()->track_find_key(get_track(), ofs, Animation::FIND_MODE_APPROX) != -1) { //make sure insertion point is valid
+ ofs += 0.0001;
}
- get_undo_redo()->create_action(TTR("Add Audio Track Clip"));
- get_undo_redo()->add_do_method(get_animation().ptr(), "audio_track_insert_key", get_track(), ofs, stream);
- get_undo_redo()->add_undo_method(get_animation().ptr(), "track_remove_key_at_time", get_track(), ofs);
- get_undo_redo()->commit_action();
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
+ undo_redo->create_action(TTR("Add Audio Track Clip"));
+ undo_redo->add_do_method(get_animation().ptr(), "audio_track_insert_key", get_track(), ofs, stream);
+ undo_redo->add_undo_method(get_animation().ptr(), "track_remove_key_at_time", get_track(), ofs);
+ undo_redo->commit_action();
queue_redraw();
return;
@@ -1059,9 +1057,6 @@ void AnimationTrackEditTypeAudio::gui_input(const Ref<InputEvent> &p_event) {
len -= end_ofs;
len -= start_ofs;
- if (len <= 0.001) {
- len = 0.001;
- }
if (get_animation()->track_get_key_count(get_track()) > i + 1) {
len = MIN(len, get_animation()->track_get_key_time(get_track(), i + 1) - get_animation()->track_get_key_time(get_track(), i));
@@ -1076,6 +1071,13 @@ void AnimationTrackEditTypeAudio::gui_input(const Ref<InputEvent> &p_event) {
int end = ofs + len * get_timeline()->get_zoom_scale();
if (end >= get_timeline()->get_name_limit() && end <= get_size().width - get_timeline()->get_buttons_width() && ABS(mm->get_position().x - end) < 5 * EDSCALE) {
+ len_resizing_start = false;
+ use_hsize_cursor = true;
+ len_resizing_index = i;
+ }
+
+ if (ofs >= get_timeline()->get_name_limit() && ofs <= get_size().width - get_timeline()->get_buttons_width() && ABS(mm->get_position().x - ofs) < 5 * EDSCALE) {
+ len_resizing_start = true;
use_hsize_cursor = true;
len_resizing_index = i;
}
@@ -1084,8 +1086,25 @@ void AnimationTrackEditTypeAudio::gui_input(const Ref<InputEvent> &p_event) {
}
if (len_resizing && mm.is_valid()) {
+ // Rezising index is some.
len_resizing_rel += mm->get_relative().x;
- len_resizing_start = mm->is_shift_pressed();
+ float ofs_local = len_resizing_rel / get_timeline()->get_zoom_scale();
+ float prev_ofs_start = get_animation()->audio_track_get_key_start_offset(get_track(), len_resizing_index);
+ float prev_ofs_end = get_animation()->audio_track_get_key_end_offset(get_track(), len_resizing_index);
+ Ref<AudioStream> stream = get_animation()->audio_track_get_key_stream(get_track(), len_resizing_index);
+ float len = stream->get_length();
+ if (len == 0) {
+ Ref<AudioStreamPreview> preview = AudioStreamPreviewGenerator::get_singleton()->generate_preview(stream);
+ float preview_len = preview->get_length();
+ len = preview_len;
+ }
+
+ if (len_resizing_start) {
+ len_resizing_rel = CLAMP(ofs_local, -prev_ofs_start, len - prev_ofs_end - prev_ofs_start) * get_timeline()->get_zoom_scale();
+ } else {
+ len_resizing_rel = CLAMP(ofs_local, -(len - prev_ofs_end - prev_ofs_start), prev_ofs_end) * get_timeline()->get_zoom_scale();
+ }
+
queue_redraw();
accept_event();
return;
@@ -1094,7 +1113,11 @@ void AnimationTrackEditTypeAudio::gui_input(const Ref<InputEvent> &p_event) {
Ref<InputEventMouseButton> mb = p_event;
if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MouseButton::LEFT && over_drag_position) {
len_resizing = true;
- len_resizing_start = mb->is_shift_pressed();
+ // In case if resizing index is not set yet reset the flag.
+ if (len_resizing_index < 0) {
+ len_resizing = false;
+ return;
+ }
len_resizing_from_px = mb->get_position().x;
len_resizing_rel = 0;
queue_redraw();
@@ -1102,24 +1125,44 @@ void AnimationTrackEditTypeAudio::gui_input(const Ref<InputEvent> &p_event) {
return;
}
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
if (len_resizing && mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == MouseButton::LEFT) {
- float ofs_local = -len_resizing_rel / get_timeline()->get_zoom_scale();
+ if (len_resizing_rel == 0 || len_resizing_index < 0) {
+ len_resizing = false;
+ return;
+ }
+
if (len_resizing_start) {
+ float ofs_local = len_resizing_rel / get_timeline()->get_zoom_scale();
float prev_ofs = get_animation()->audio_track_get_key_start_offset(get_track(), len_resizing_index);
- get_undo_redo()->create_action(TTR("Change Audio Track Clip Start Offset"));
- get_undo_redo()->add_do_method(get_animation().ptr(), "audio_track_set_key_start_offset", get_track(), len_resizing_index, prev_ofs + ofs_local);
- get_undo_redo()->add_undo_method(get_animation().ptr(), "audio_track_set_key_start_offset", get_track(), len_resizing_index, prev_ofs);
- get_undo_redo()->commit_action();
+ float prev_time = get_animation()->track_get_key_time(get_track(), len_resizing_index);
+ float new_ofs = prev_ofs + ofs_local;
+ float new_time = prev_time + ofs_local;
+ if (prev_time != new_time) {
+ undo_redo->create_action(TTR("Change Audio Track Clip Start Offset"));
+
+ undo_redo->add_do_method(get_animation().ptr(), "track_set_key_time", get_track(), len_resizing_index, new_time);
+ undo_redo->add_undo_method(get_animation().ptr(), "track_set_key_time", get_track(), len_resizing_index, prev_time);
+ undo_redo->add_do_method(get_animation().ptr(), "audio_track_set_key_start_offset", get_track(), len_resizing_index, new_ofs);
+ undo_redo->add_undo_method(get_animation().ptr(), "audio_track_set_key_start_offset", get_track(), len_resizing_index, prev_ofs);
+
+ undo_redo->commit_action();
+ }
} else {
+ float ofs_local = -len_resizing_rel / get_timeline()->get_zoom_scale();
float prev_ofs = get_animation()->audio_track_get_key_end_offset(get_track(), len_resizing_index);
- get_undo_redo()->create_action(TTR("Change Audio Track Clip End Offset"));
- get_undo_redo()->add_do_method(get_animation().ptr(), "audio_track_set_key_end_offset", get_track(), len_resizing_index, prev_ofs + ofs_local);
- get_undo_redo()->add_undo_method(get_animation().ptr(), "audio_track_set_key_end_offset", get_track(), len_resizing_index, prev_ofs);
- get_undo_redo()->commit_action();
+ float new_ofs = prev_ofs + ofs_local;
+ if (prev_ofs != new_ofs) {
+ undo_redo->create_action(TTR("Change Audio Track Clip End Offset"));
+ undo_redo->add_do_method(get_animation().ptr(), "audio_track_set_key_end_offset", get_track(), len_resizing_index, new_ofs);
+ undo_redo->add_undo_method(get_animation().ptr(), "audio_track_set_key_end_offset", get_track(), len_resizing_index, prev_ofs);
+ undo_redo->commit_action();
+ }
}
len_resizing_index = -1;
+ len_resizing = false;
queue_redraw();
accept_event();
return;
diff --git a/editor/audio_stream_preview.cpp b/editor/audio_stream_preview.cpp
index b9e52ad7ad..b84e58125e 100644
--- a/editor/audio_stream_preview.cpp
+++ b/editor/audio_stream_preview.cpp
@@ -42,6 +42,10 @@ float AudioStreamPreview::get_max(float p_time, float p_time_next) const {
}
int max = preview.size() / 2;
+ if (max == 0) {
+ return 0;
+ }
+
int time_from = p_time / length * max;
int time_to = p_time_next / length * max;
time_from = CLAMP(time_from, 0, max - 1);
@@ -69,6 +73,10 @@ float AudioStreamPreview::get_min(float p_time, float p_time_next) const {
}
int max = preview.size() / 2;
+ if (max == 0) {
+ return 0;
+ }
+
int time_from = p_time / length * max;
int time_to = p_time_next / length * max;
time_from = CLAMP(time_from, 0, max - 1);
diff --git a/editor/code_editor.cpp b/editor/code_editor.cpp
index 212a46cb62..7ae0db7b48 100644
--- a/editor/code_editor.cpp
+++ b/editor/code_editor.cpp
@@ -33,6 +33,7 @@
#include "core/input/input.h"
#include "core/os/keyboard.h"
#include "core/string/string_builder.h"
+#include "core/templates/pair.h"
#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/plugins/script_editor_plugin.h"
@@ -91,10 +92,10 @@ void FindReplaceBar::_notification(int p_what) {
case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
find_prev->set_icon(get_theme_icon(SNAME("MoveUp"), SNAME("EditorIcons")));
find_next->set_icon(get_theme_icon(SNAME("MoveDown"), SNAME("EditorIcons")));
- hide_button->set_normal_texture(get_theme_icon(SNAME("Close"), SNAME("EditorIcons")));
- hide_button->set_hover_texture(get_theme_icon(SNAME("Close"), SNAME("EditorIcons")));
- hide_button->set_pressed_texture(get_theme_icon(SNAME("Close"), SNAME("EditorIcons")));
- hide_button->set_custom_minimum_size(hide_button->get_normal_texture()->get_size());
+ hide_button->set_texture_normal(get_theme_icon(SNAME("Close"), SNAME("EditorIcons")));
+ hide_button->set_texture_hover(get_theme_icon(SNAME("Close"), SNAME("EditorIcons")));
+ hide_button->set_texture_pressed(get_theme_icon(SNAME("Close"), SNAME("EditorIcons")));
+ hide_button->set_custom_minimum_size(hide_button->get_texture_normal()->get_size());
} break;
case NOTIFICATION_VISIBILITY_CHANGED: {
@@ -377,10 +378,12 @@ void FindReplaceBar::_update_results_count() {
if (is_whole_words()) {
if (col_pos > 0 && !is_symbol(line_text[col_pos - 1])) {
- break;
+ col_pos += searched.length();
+ continue;
}
- if (col_pos + line_text.length() < line_text.length() && !is_symbol(line_text[col_pos + searched.length()])) {
- break;
+ if (col_pos + searched.length() < line_text.length() && !is_symbol(line_text[col_pos + searched.length()])) {
+ col_pos += searched.length();
+ continue;
}
}
@@ -870,6 +873,10 @@ void CodeTextEditor::_reset_zoom() {
}
void CodeTextEditor::_line_col_changed() {
+ if (!code_complete_timer->is_stopped() && code_complete_timer_line != text_editor->get_caret_line()) {
+ code_complete_timer->stop();
+ }
+
String line = text_editor->get_line(text_editor->get_caret_line());
int positional_column = 0;
@@ -899,6 +906,7 @@ void CodeTextEditor::_line_col_changed() {
void CodeTextEditor::_text_changed() {
if (text_editor->is_insert_text_operation()) {
+ code_complete_timer_line = text_editor->get_caret_line();
code_complete_timer->start();
}
@@ -1288,90 +1296,98 @@ void CodeTextEditor::convert_case(CaseStyle p_case) {
void CodeTextEditor::move_lines_up() {
text_editor->begin_complex_operation();
- Vector<int> carets_to_remove;
-
Vector<int> caret_edit_order = text_editor->get_caret_index_edit_order();
+
+ // Lists of carets representing each group
+ Vector<Vector<int>> caret_groups;
+ Vector<Pair<int, int>> group_borders;
+
+ // Search for groups of carets and their selections residing on the same lines
for (int i = 0; i < caret_edit_order.size(); i++) {
int c = caret_edit_order[i];
- int cl = text_editor->get_caret_line(c);
- bool swaped_caret = false;
- for (int j = i + 1; j < caret_edit_order.size(); j++) {
- if (text_editor->has_selection(caret_edit_order[j])) {
- if (text_editor->get_selection_from_line() == cl) {
- carets_to_remove.push_back(caret_edit_order[j]);
- continue;
- }
+ Vector<int> new_group{ c };
+ Pair<int, int> group_border;
+ if (text_editor->has_selection(c)) {
+ group_border.first = text_editor->get_selection_from_line(c);
+ group_border.second = text_editor->get_selection_to_line(c);
+ } else {
+ group_border.first = text_editor->get_caret_line(c);
+ group_border.second = text_editor->get_caret_line(c);
+ }
- if (text_editor->get_selection_to_line() == cl) {
- if (text_editor->has_selection(c)) {
- if (text_editor->get_selection_to_line(c) != cl) {
- text_editor->select(cl + 1, 0, text_editor->get_selection_to_line(c), text_editor->get_selection_to_column(c), c);
- break;
- }
- }
+ for (int j = i; j < caret_edit_order.size() - 1; j++) {
+ int c_current = caret_edit_order[j];
+ int c_next = caret_edit_order[j + 1];
- carets_to_remove.push_back(c);
- i = j - 1;
- swaped_caret = true;
- break;
- }
+ int next_start_pos = text_editor->has_selection(c_next) ? text_editor->get_selection_from_line(c_next) : text_editor->get_caret_line(c_next);
+ int next_end_pos = text_editor->has_selection(c_next) ? text_editor->get_selection_to_line(c_next) : text_editor->get_caret_line(c_next);
+
+ int current_start_pos = text_editor->has_selection(c_current) ? text_editor->get_selection_from_line(c_current) : text_editor->get_caret_line(c_current);
+
+ i = j;
+ if (next_end_pos != current_start_pos && next_end_pos + 1 != current_start_pos) {
break;
}
-
- if (text_editor->get_caret_line(caret_edit_order[j]) == cl) {
- carets_to_remove.push_back(caret_edit_order[j]);
- i = j;
- continue;
+ group_border.first = next_start_pos;
+ new_group.push_back(c_next);
+ // If the last caret is added to the current group there is no need to process it again
+ if (j + 1 == caret_edit_order.size() - 1) {
+ i++;
}
- break;
}
+ group_borders.push_back(group_border);
+ caret_groups.push_back(new_group);
+ }
- if (swaped_caret) {
+ for (int i = group_borders.size() - 1; i >= 0; i--) {
+ if (group_borders[i].first - 1 < 0) {
continue;
}
- if (text_editor->has_selection(c)) {
+ // If the group starts overlapping with the upper group don't move it
+ if (i < group_borders.size() - 1 && group_borders[i].first - 1 <= group_borders[i + 1].second) {
+ continue;
+ }
+
+ // We have to remember caret positions and selections prior to line swapping
+ Vector<Vector<int>> caret_group_parameters;
+
+ for (int j = 0; j < caret_groups[i].size(); j++) {
+ int c = caret_groups[i][j];
+ int cursor_line = text_editor->get_caret_line(c);
+ int cursor_column = text_editor->get_caret_column(c);
+
+ if (!text_editor->has_selection(c)) {
+ caret_group_parameters.push_back(Vector<int>{ -1, -1, -1, -1, cursor_line, cursor_column });
+ continue;
+ }
int from_line = text_editor->get_selection_from_line(c);
int from_col = text_editor->get_selection_from_column(c);
int to_line = text_editor->get_selection_to_line(c);
int to_column = text_editor->get_selection_to_column(c);
- int cursor_line = text_editor->get_caret_line(c);
+ caret_group_parameters.push_back(Vector<int>{ from_line, from_col, to_line, to_column, cursor_line, cursor_column });
+ }
- for (int j = from_line; j <= to_line; j++) {
- int line_id = j;
- int next_id = j - 1;
+ for (int line_id = group_borders[i].first; line_id <= group_borders[i].second; line_id++) {
+ text_editor->unfold_line(line_id);
+ text_editor->unfold_line(line_id - 1);
- if (line_id == 0 || next_id < 0) {
- return;
- }
+ text_editor->swap_lines(line_id - 1, line_id);
+ }
- text_editor->unfold_line(line_id);
- text_editor->unfold_line(next_id);
+ for (int j = 0; j < caret_groups[i].size(); j++) {
+ int c = caret_groups[i][j];
+ Vector<int> caret_parameters = caret_group_parameters[j];
+ text_editor->set_caret_line(caret_parameters[4] - 1, c == 0, true, 0, c);
+ text_editor->set_caret_column(caret_parameters[5], c == 0, c);
- text_editor->swap_lines(line_id, next_id);
- text_editor->set_caret_line(next_id, c == 0, true, 0, c);
+ if (caret_parameters[0] >= 0) {
+ text_editor->select(caret_parameters[0] - 1, caret_parameters[1], caret_parameters[2] - 1, caret_parameters[3], c);
}
- int from_line_up = from_line > 0 ? from_line - 1 : from_line;
- int to_line_up = to_line > 0 ? to_line - 1 : to_line;
- int cursor_line_up = cursor_line > 0 ? cursor_line - 1 : cursor_line;
- text_editor->select(from_line_up, from_col, to_line_up, to_column, c);
- text_editor->set_caret_line(cursor_line_up, c == 0, true, 0, c);
- } else {
- int line_id = text_editor->get_caret_line(c);
- int next_id = line_id - 1;
-
- if (line_id == 0 || next_id < 0) {
- return;
- }
-
- text_editor->unfold_line(line_id);
- text_editor->unfold_line(next_id);
-
- text_editor->swap_lines(line_id, next_id);
- text_editor->set_caret_line(next_id, c == 0, true, 0, c);
}
}
+
text_editor->end_complex_operation();
text_editor->merge_overlapping_carets();
text_editor->queue_redraw();
@@ -1380,95 +1396,97 @@ void CodeTextEditor::move_lines_up() {
void CodeTextEditor::move_lines_down() {
text_editor->begin_complex_operation();
- Vector<int> carets_to_remove;
-
Vector<int> caret_edit_order = text_editor->get_caret_index_edit_order();
+
+ // Lists of carets representing each group
+ Vector<Vector<int>> caret_groups;
+ Vector<Pair<int, int>> group_borders;
+
+ // Search for groups of carets and their selections residing on the same lines
for (int i = 0; i < caret_edit_order.size(); i++) {
int c = caret_edit_order[i];
- int cl = text_editor->get_caret_line(c);
- bool swaped_caret = false;
- for (int j = i + 1; j < caret_edit_order.size(); j++) {
- if (text_editor->has_selection(caret_edit_order[j])) {
- if (text_editor->get_selection_from_line() == cl) {
- carets_to_remove.push_back(caret_edit_order[j]);
- continue;
- }
+ Vector<int> new_group{ c };
+ Pair<int, int> group_border;
+ if (text_editor->has_selection(c)) {
+ group_border.first = text_editor->get_selection_from_line(c);
+ group_border.second = text_editor->get_selection_to_line(c);
+ } else {
+ group_border.first = text_editor->get_caret_line(c);
+ group_border.second = text_editor->get_caret_line(c);
+ }
- if (text_editor->get_selection_to_line() == cl) {
- if (text_editor->has_selection(c)) {
- if (text_editor->get_selection_to_line(c) != cl) {
- text_editor->select(cl + 1, 0, text_editor->get_selection_to_line(c), text_editor->get_selection_to_column(c), c);
- break;
- }
- }
+ for (int j = i; j < caret_edit_order.size() - 1; j++) {
+ int c_current = caret_edit_order[j];
+ int c_next = caret_edit_order[j + 1];
- carets_to_remove.push_back(c);
- i = j - 1;
- swaped_caret = true;
- break;
+ int next_start_pos = text_editor->has_selection(c_next) ? text_editor->get_selection_from_line(c_next) : text_editor->get_caret_line(c_next);
+ int next_end_pos = text_editor->has_selection(c_next) ? text_editor->get_selection_to_line(c_next) : text_editor->get_caret_line(c_next);
+
+ int current_start_pos = text_editor->has_selection(c_current) ? text_editor->get_selection_from_line(c_current) : text_editor->get_caret_line(c_current);
+
+ i = j;
+ if (next_end_pos == current_start_pos || next_end_pos + 1 == current_start_pos) {
+ group_border.first = next_start_pos;
+ new_group.push_back(c_next);
+ // If the last caret is added to the current group there is no need to process it again
+ if (j + 1 == caret_edit_order.size() - 1) {
+ i++;
}
+ } else {
break;
}
-
- if (text_editor->get_caret_line(caret_edit_order[j]) == cl) {
- carets_to_remove.push_back(caret_edit_order[j]);
- i = j;
- continue;
- }
- break;
}
+ group_borders.push_back(group_border);
+ caret_groups.push_back(new_group);
+ }
- if (swaped_caret) {
+ for (int i = 0; i < group_borders.size(); i++) {
+ if (group_borders[i].second + 1 > text_editor->get_line_count() - 1) {
continue;
}
- if (text_editor->has_selection(c)) {
- int from_line = text_editor->get_selection_from_line(c);
- int from_col = text_editor->get_selection_from_column(c);
- int to_line = text_editor->get_selection_to_line(c);
- int to_column = text_editor->get_selection_to_column(c);
- int cursor_line = text_editor->get_caret_line(c);
-
- for (int l = to_line; l >= from_line; l--) {
- int line_id = l;
- int next_id = l + 1;
-
- if (line_id == text_editor->get_line_count() - 1 || next_id > text_editor->get_line_count()) {
- continue;
- }
-
- text_editor->unfold_line(line_id);
- text_editor->unfold_line(next_id);
+ // If the group starts overlapping with the upper group don't move it
+ if (i > 0 && group_borders[i].second + 1 >= group_borders[i - 1].first) {
+ continue;
+ }
- text_editor->swap_lines(line_id, next_id);
- text_editor->set_caret_line(next_id, c == 0, true, 0, c);
- }
- int from_line_down = from_line < text_editor->get_line_count() ? from_line + 1 : from_line;
- int to_line_down = to_line < text_editor->get_line_count() ? to_line + 1 : to_line;
- int cursor_line_down = cursor_line < text_editor->get_line_count() ? cursor_line + 1 : cursor_line;
- text_editor->select(from_line_down, from_col, to_line_down, to_column, c);
- text_editor->set_caret_line(cursor_line_down, c == 0, true, 0, c);
- } else {
- int line_id = text_editor->get_caret_line(c);
- int next_id = line_id + 1;
+ // We have to remember caret positions and selections prior to line swapping
+ Vector<Vector<int>> caret_group_parameters;
- if (line_id == text_editor->get_line_count() - 1 || next_id > text_editor->get_line_count()) {
- continue;
+ for (int j = 0; j < caret_groups[i].size(); j++) {
+ int c = caret_groups[i][j];
+ int cursor_line = text_editor->get_caret_line(c);
+ int cursor_column = text_editor->get_caret_column(c);
+
+ if (text_editor->has_selection(c)) {
+ int from_line = text_editor->get_selection_from_line(c);
+ int from_col = text_editor->get_selection_from_column(c);
+ int to_line = text_editor->get_selection_to_line(c);
+ int to_column = text_editor->get_selection_to_column(c);
+ caret_group_parameters.push_back(Vector<int>{ from_line, from_col, to_line, to_column, cursor_line, cursor_column });
+ } else {
+ caret_group_parameters.push_back(Vector<int>{ -1, -1, -1, -1, cursor_line, cursor_column });
}
+ }
+ for (int line_id = group_borders[i].second; line_id >= group_borders[i].first; line_id--) {
text_editor->unfold_line(line_id);
- text_editor->unfold_line(next_id);
+ text_editor->unfold_line(line_id + 1);
- text_editor->swap_lines(line_id, next_id);
- text_editor->set_caret_line(next_id, c == 0, true, 0, c);
+ text_editor->swap_lines(line_id + 1, line_id);
}
- }
- // Sort and remove backwards to preserve indexes.
- carets_to_remove.sort();
- for (int i = carets_to_remove.size() - 1; i >= 0; i--) {
- text_editor->remove_caret(carets_to_remove[i]);
+ for (int j = 0; j < caret_groups[i].size(); j++) {
+ int c = caret_groups[i][j];
+ Vector<int> caret_parameters = caret_group_parameters[j];
+ text_editor->set_caret_line(caret_parameters[4] + 1, c == 0, true, 0, c);
+ text_editor->set_caret_column(caret_parameters[5], c == 0, c);
+
+ if (caret_parameters[0] >= 0) {
+ text_editor->select(caret_parameters[0] + 1, caret_parameters[1], caret_parameters[2] + 1, caret_parameters[3], c);
+ }
+ }
}
text_editor->merge_overlapping_carets();
@@ -1872,7 +1890,7 @@ void CodeTextEditor::_apply_settings_change() {
}
fc->set_opentype_features(ftrs);
} break;
- default: { // Default.
+ default: { // Enabled.
Dictionary ftrs;
ftrs[TS->name_to_tag("calt")] = 1;
fc->set_opentype_features(ftrs);
@@ -2000,23 +2018,14 @@ void CodeTextEditor::goto_next_bookmark() {
return;
}
- text_editor->remove_secondary_carets();
- int line = text_editor->get_caret_line();
- if (line >= (int)bmarks[bmarks.size() - 1]) {
- text_editor->unfold_line(bmarks[0]);
- text_editor->set_caret_line(bmarks[0]);
- text_editor->center_viewport_to_caret();
- } else {
- for (int i = 0; i < bmarks.size(); i++) {
- int bmark_line = bmarks[i];
- if (bmark_line > line) {
- text_editor->unfold_line(bmark_line);
- text_editor->set_caret_line(bmark_line);
- text_editor->center_viewport_to_caret();
- return;
- }
+ int current_line = text_editor->get_caret_line();
+ int bmark_idx = 0;
+ if (current_line < (int)bmarks[bmarks.size() - 1]) {
+ while (bmark_idx < bmarks.size() && bmarks[bmark_idx] <= current_line) {
+ bmark_idx++;
}
}
+ goto_line_centered(bmarks[bmark_idx]);
}
void CodeTextEditor::goto_prev_bookmark() {
@@ -2025,23 +2034,14 @@ void CodeTextEditor::goto_prev_bookmark() {
return;
}
- text_editor->remove_secondary_carets();
- int line = text_editor->get_caret_line();
- if (line <= (int)bmarks[0]) {
- text_editor->unfold_line(bmarks[bmarks.size() - 1]);
- text_editor->set_caret_line(bmarks[bmarks.size() - 1]);
- text_editor->center_viewport_to_caret();
- } else {
- for (int i = bmarks.size() - 1; i >= 0; i--) {
- int bmark_line = bmarks[i];
- if (bmark_line < line) {
- text_editor->unfold_line(bmark_line);
- text_editor->set_caret_line(bmark_line);
- text_editor->center_viewport_to_caret();
- return;
- }
+ int current_line = text_editor->get_caret_line();
+ int bmark_idx = bmarks.size() - 1;
+ if (current_line > (int)bmarks[0]) {
+ while (bmark_idx >= 0 && bmarks[bmark_idx] >= current_line) {
+ bmark_idx--;
}
}
+ goto_line_centered(bmarks[bmark_idx]);
}
void CodeTextEditor::remove_all_bookmarks() {
@@ -2106,7 +2106,7 @@ CodeTextEditor::CodeTextEditor() {
}
fc->set_opentype_features(ftrs);
} break;
- default: { // Default.
+ default: { // Enabled.
Dictionary ftrs;
ftrs[TS->name_to_tag("calt")] = 1;
fc->set_opentype_features(ftrs);
diff --git a/editor/code_editor.h b/editor/code_editor.h
index ded7518287..4d7034fbd0 100644
--- a/editor/code_editor.h
+++ b/editor/code_editor.h
@@ -158,6 +158,7 @@ class CodeTextEditor : public VBoxContainer {
Label *info = nullptr;
Timer *idle = nullptr;
Timer *code_complete_timer = nullptr;
+ int code_complete_timer_line = 0;
Timer *font_resize_timer = nullptr;
int font_resize_val;
diff --git a/editor/connections_dialog.cpp b/editor/connections_dialog.cpp
index ed2044c117..1f0cc1dc77 100644
--- a/editor/connections_dialog.cpp
+++ b/editor/connections_dialog.cpp
@@ -31,6 +31,7 @@
#include "connections_dialog.h"
#include "editor/doc_tools.h"
+#include "editor/editor_help.h"
#include "editor/editor_node.h"
#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
@@ -787,23 +788,7 @@ bool ConnectionsDock::_is_item_signal(TreeItem &p_item) {
}
bool ConnectionsDock::_is_connection_inherited(Connection &p_connection) {
- Node *scene_root = EditorNode::get_singleton()->get_edited_scene();
- Ref<PackedScene> scn = ResourceLoader::load(scene_root->get_scene_file_path());
- ERR_FAIL_NULL_V(scn, false);
-
- Ref<SceneState> state = scn->get_state();
- ERR_FAIL_NULL_V(state, false);
-
- Node *source = Object::cast_to<Node>(p_connection.signal.get_object());
- Node *target = Object::cast_to<Node>(p_connection.callable.get_object());
-
- const NodePath source_path = scene_root->get_path_to(source);
- const NodePath target_path = scene_root->get_path_to(target);
- const StringName signal_name = p_connection.signal.get_name();
- const StringName method_name = p_connection.callable.get_method();
-
- // If it cannot be found in PackedScene, this connection was inherited.
- return !state->has_connection(source_path, signal_name, target_path, method_name, true);
+ return bool(p_connection.flags & CONNECT_INHERITED);
}
/*
diff --git a/editor/create_dialog.cpp b/editor/create_dialog.cpp
index 545b0895b0..5292b51032 100644
--- a/editor/create_dialog.cpp
+++ b/editor/create_dialog.cpp
@@ -275,7 +275,8 @@ void CreateDialog::_configure_search_option_item(TreeItem *r_item, const String
r_item->set_text(0, "\"" + p_type + "\"");
} else if (script_type) {
r_item->set_metadata(0, p_type);
- r_item->set_text(0, p_type + " (" + ScriptServer::get_global_class_path(p_type).get_file() + ")");
+ r_item->set_text(0, p_type);
+ r_item->set_suffix(0, "(" + ScriptServer::get_global_class_path(p_type).get_file() + ")");
} else {
r_item->set_metadata(0, custom_type_parents[p_type]);
r_item->set_text(0, p_type);
@@ -283,8 +284,9 @@ void CreateDialog::_configure_search_option_item(TreeItem *r_item, const String
bool can_instantiate = (p_type_category == TypeCategory::CPP_TYPE && ClassDB::can_instantiate(p_type)) ||
p_type_category == TypeCategory::OTHER_TYPE;
+ bool is_virtual = ClassDB::class_exists(p_type) && ClassDB::is_virtual(p_type);
- if (can_instantiate && !ClassDB::is_virtual(p_type)) {
+ if (can_instantiate && !is_virtual) {
r_item->set_icon(0, EditorNode::get_singleton()->get_class_icon(p_type, icon_fallback));
} else {
r_item->set_icon(0, EditorNode::get_singleton()->get_class_icon(p_type, "NodeDisabled"));
@@ -501,7 +503,7 @@ String CreateDialog::get_selected_type() {
return selected->get_text(0);
}
-Variant CreateDialog::instance_selected() {
+Variant CreateDialog::instantiate_selected() {
TreeItem *selected = search_options->get_selected();
if (!selected) {
@@ -519,7 +521,7 @@ Variant CreateDialog::instance_selected() {
n->set_name(custom);
}
} else {
- obj = EditorNode::get_editor_data().instance_custom_type(selected->get_text(0), custom);
+ obj = EditorNode::get_editor_data().instantiate_custom_type(selected->get_text(0), custom);
}
} else {
obj = ClassDB::instantiate(selected->get_text(0));
@@ -752,8 +754,7 @@ CreateDialog::CreateDialog() {
favorites->connect("cell_selected", callable_mp(this, &CreateDialog::_favorite_selected));
favorites->connect("item_activated", callable_mp(this, &CreateDialog::_favorite_activated));
favorites->add_theme_constant_override("draw_guides", 1);
- // Cannot forward drag data to a non control, must be fixed.
- //favorites->set_drag_forwarding(this);
+ favorites->set_drag_forwarding(this);
fav_vb->add_margin_child(TTR("Favorites:"), favorites, true);
VBoxContainer *rec_vb = memnew(VBoxContainer);
diff --git a/editor/create_dialog.h b/editor/create_dialog.h
index f2e741624f..961538d8b7 100644
--- a/editor/create_dialog.h
+++ b/editor/create_dialog.h
@@ -110,7 +110,7 @@ protected:
void _save_and_update_favorite_list();
public:
- Variant instance_selected();
+ Variant instantiate_selected();
String get_selected_type();
void set_base_type(const String &p_base) { base_type = p_base; }
diff --git a/editor/debugger/editor_debugger_inspector.cpp b/editor/debugger/editor_debugger_inspector.cpp
index 371aaf8617..c64f23aba0 100644
--- a/editor/debugger/editor_debugger_inspector.cpp
+++ b/editor/debugger/editor_debugger_inspector.cpp
@@ -230,7 +230,7 @@ void EditorDebuggerInspector::add_stack_variable(const Array &p_array) {
Variant v = var.value;
PropertyHint h = PROPERTY_HINT_NONE;
- String hs = String();
+ String hs;
if (v.get_type() == Variant::OBJECT) {
v = Object::cast_to<EncodedObjectAsID>(v)->get_object_id();
diff --git a/editor/debugger/editor_debugger_node.cpp b/editor/debugger/editor_debugger_node.cpp
index 68aff328ed..0a0f0cf90a 100644
--- a/editor/debugger/editor_debugger_node.cpp
+++ b/editor/debugger/editor_debugger_node.cpp
@@ -35,6 +35,9 @@
#include "editor/debugger/script_editor_debugger.h"
#include "editor/editor_log.h"
#include "editor/editor_node.h"
+#include "editor/editor_settings.h"
+#include "editor/editor_undo_redo_manager.h"
+#include "editor/inspector_dock.h"
#include "editor/plugins/editor_debugger_plugin.h"
#include "editor/plugins/script_editor_plugin.h"
#include "editor/scene_tree_dock.h"
@@ -119,8 +122,8 @@ ScriptEditorDebugger *EditorDebuggerNode::_add_debugger() {
}
if (!debugger_plugins.is_empty()) {
- for (const Ref<Script> &i : debugger_plugins) {
- node->add_debugger_plugin(i);
+ for (Ref<EditorDebuggerPlugin> plugin : debugger_plugins) {
+ plugin->create_session(node);
}
}
@@ -167,7 +170,7 @@ void EditorDebuggerNode::_text_editor_stack_goto(const ScriptEditorDebugger *p_d
void EditorDebuggerNode::_bind_methods() {
// LiveDebug.
ClassDB::bind_method("live_debug_create_node", &EditorDebuggerNode::live_debug_create_node);
- ClassDB::bind_method("live_debug_instance_node", &EditorDebuggerNode::live_debug_instance_node);
+ ClassDB::bind_method("live_debug_instantiate_node", &EditorDebuggerNode::live_debug_instantiate_node);
ClassDB::bind_method("live_debug_remove_node", &EditorDebuggerNode::live_debug_remove_node);
ClassDB::bind_method("live_debug_remove_and_keep_node", &EditorDebuggerNode::live_debug_remove_and_keep_node);
ClassDB::bind_method("live_debug_restore_node", &EditorDebuggerNode::live_debug_restore_node);
@@ -207,9 +210,32 @@ String EditorDebuggerNode::get_server_uri() const {
return server->get_uri();
}
+void EditorDebuggerNode::set_keep_open(bool p_keep_open) {
+ keep_open = p_keep_open;
+ if (keep_open) {
+ if (server.is_null() || !server->is_active()) {
+ start();
+ }
+ } else {
+ bool found = false;
+ _for_all(tabs, [&](ScriptEditorDebugger *p_debugger) {
+ if (p_debugger->is_session_active()) {
+ found = true;
+ }
+ });
+ if (!found) {
+ stop();
+ }
+ }
+}
+
Error EditorDebuggerNode::start(const String &p_uri) {
- stop();
ERR_FAIL_COND_V(p_uri.find("://") < 0, ERR_INVALID_PARAMETER);
+ if (keep_open && current_uri == p_uri && server.is_valid()) {
+ return OK;
+ }
+ stop(true);
+ current_uri = p_uri;
if (EDITOR_GET("run/output/always_open_output_on_play")) {
EditorNode::get_singleton()->make_bottom_panel_item_visible(EditorNode::get_log());
} else {
@@ -225,7 +251,11 @@ Error EditorDebuggerNode::start(const String &p_uri) {
return OK;
}
-void EditorDebuggerNode::stop() {
+void EditorDebuggerNode::stop(bool p_force) {
+ if (keep_open && !p_force) {
+ return;
+ }
+ current_uri.clear();
if (server.is_valid()) {
server->stop();
EditorNode::get_log()->add_message("--- Debugging process stopped ---", EditorLog::MSG_TYPE_EDITOR);
@@ -244,12 +274,8 @@ void EditorDebuggerNode::stop() {
}
});
_break_state_changed();
- if (hide_on_stop) {
- if (is_visible_in_tree()) {
- EditorNode::get_singleton()->hide_bottom_panel();
- }
- }
breakpoints.clear();
+ EditorNode::get_undo_redo()->clear_history(false, EditorUndoRedoManager::REMOTE_HISTORY);
set_process(false);
}
@@ -428,7 +454,6 @@ void EditorDebuggerNode::set_script_debug_button(MenuButton *p_button) {
p->add_shortcut(ED_GET_SHORTCUT("debugger/break"), DEBUG_BREAK);
p->add_shortcut(ED_GET_SHORTCUT("debugger/continue"), DEBUG_CONTINUE);
p->add_separator();
- p->add_check_shortcut(ED_GET_SHORTCUT("debugger/keep_debugger_open"), DEBUG_KEEP_DEBUGGER_OPEN);
p->add_check_shortcut(ED_GET_SHORTCUT("debugger/debug_with_external_editor"), DEBUG_WITH_EXTERNAL_EDITOR);
p->connect("id_pressed", callable_mp(this, &EditorDebuggerNode::_menu_option));
@@ -468,12 +493,6 @@ void EditorDebuggerNode::_menu_option(int p_id) {
case DEBUG_CONTINUE: {
debug_continue();
} break;
- case DEBUG_KEEP_DEBUGGER_OPEN: {
- bool ischecked = script_menu->get_popup()->is_item_checked(script_menu->get_popup()->get_item_index(DEBUG_KEEP_DEBUGGER_OPEN));
- hide_on_stop = ischecked;
- script_menu->get_popup()->set_item_checked(script_menu->get_popup()->get_item_index(DEBUG_KEEP_DEBUGGER_OPEN), !ischecked);
- EditorSettings::get_singleton()->set_project_metadata("debug_options", "keep_debugger_open", !ischecked);
- } break;
case DEBUG_WITH_EXTERNAL_EDITOR: {
bool ischecked = script_menu->get_popup()->is_item_checked(script_menu->get_popup()->get_item_index(DEBUG_WITH_EXTERNAL_EDITOR));
debug_with_external_editor = !ischecked;
@@ -484,9 +503,6 @@ void EditorDebuggerNode::_menu_option(int p_id) {
}
void EditorDebuggerNode::_update_debug_options() {
- if (EditorSettings::get_singleton()->get_project_metadata("debug_options", "keep_debugger_open", false).operator bool()) {
- _menu_option(DEBUG_KEEP_DEBUGGER_OPEN);
- }
if (EditorSettings::get_singleton()->get_project_metadata("debug_options", "debug_with_external_editor", false).operator bool()) {
_menu_option(DEBUG_WITH_EXTERNAL_EDITOR);
}
@@ -676,9 +692,9 @@ void EditorDebuggerNode::live_debug_create_node(const NodePath &p_parent, const
});
}
-void EditorDebuggerNode::live_debug_instance_node(const NodePath &p_parent, const String &p_path, const String &p_name) {
+void EditorDebuggerNode::live_debug_instantiate_node(const NodePath &p_parent, const String &p_path, const String &p_name) {
_for_all(tabs, [&](ScriptEditorDebugger *dbg) {
- dbg->live_debug_instance_node(p_parent, p_path, p_name);
+ dbg->live_debug_instantiate_node(p_parent, p_path, p_name);
});
}
@@ -723,22 +739,36 @@ EditorDebuggerNode::CameraOverride EditorDebuggerNode::get_camera_override() {
return camera_override;
}
-void EditorDebuggerNode::add_debugger_plugin(const Ref<Script> &p_script) {
- ERR_FAIL_COND_MSG(debugger_plugins.has(p_script), "Debugger plugin already exists.");
- ERR_FAIL_COND_MSG(p_script.is_null(), "Debugger plugin script is null");
- ERR_FAIL_COND_MSG(p_script->get_instance_base_type() == StringName(), "Debugger plugin script has error.");
- ERR_FAIL_COND_MSG(String(p_script->get_instance_base_type()) != "EditorDebuggerPlugin", "Base type of debugger plugin is not 'EditorDebuggerPlugin'.");
- ERR_FAIL_COND_MSG(!p_script->is_tool(), "Debugger plugin script is not in tool mode.");
- debugger_plugins.insert(p_script);
+void EditorDebuggerNode::add_debugger_plugin(const Ref<EditorDebuggerPlugin> &p_plugin) {
+ ERR_FAIL_COND_MSG(p_plugin.is_null(), "Debugger plugin is null.");
+ ERR_FAIL_COND_MSG(debugger_plugins.has(p_plugin), "Debugger plugin already exists.");
+ debugger_plugins.insert(p_plugin);
+
+ Ref<EditorDebuggerPlugin> plugin = p_plugin;
for (int i = 0; get_debugger(i); i++) {
- get_debugger(i)->add_debugger_plugin(p_script);
+ plugin->create_session(get_debugger(i));
}
}
-void EditorDebuggerNode::remove_debugger_plugin(const Ref<Script> &p_script) {
- ERR_FAIL_COND_MSG(!debugger_plugins.has(p_script), "Debugger plugin doesn't exists.");
- debugger_plugins.erase(p_script);
- for (int i = 0; get_debugger(i); i++) {
- get_debugger(i)->remove_debugger_plugin(p_script);
+void EditorDebuggerNode::remove_debugger_plugin(const Ref<EditorDebuggerPlugin> &p_plugin) {
+ ERR_FAIL_COND_MSG(p_plugin.is_null(), "Debugger plugin is null.");
+ ERR_FAIL_COND_MSG(!debugger_plugins.has(p_plugin), "Debugger plugin doesn't exists.");
+ debugger_plugins.erase(p_plugin);
+ Ref<EditorDebuggerPlugin>(p_plugin)->clear();
+}
+
+bool EditorDebuggerNode::plugins_capture(ScriptEditorDebugger *p_debugger, const String &p_message, const Array &p_data) {
+ int session_index = tabs->get_tab_idx_from_control(p_debugger);
+ ERR_FAIL_COND_V(session_index < 0, false);
+ int colon_index = p_message.find_char(':');
+ ERR_FAIL_COND_V_MSG(colon_index < 1, false, "Invalid message received.");
+
+ const String cap = p_message.substr(0, colon_index);
+ bool parsed = false;
+ for (Ref<EditorDebuggerPlugin> plugin : debugger_plugins) {
+ if (plugin->has_capture(cap)) {
+ parsed |= plugin->capture(p_message, p_data, session_index);
+ }
}
+ return parsed;
}
diff --git a/editor/debugger/editor_debugger_node.h b/editor/debugger/editor_debugger_node.h
index 305f18a652..030f4c7d12 100644
--- a/editor/debugger/editor_debugger_node.h
+++ b/editor/debugger/editor_debugger_node.h
@@ -36,6 +36,7 @@
class Button;
class DebugAdapterParser;
+class EditorDebuggerPlugin;
class EditorDebuggerTree;
class EditorDebuggerRemoteObject;
class MenuButton;
@@ -62,7 +63,6 @@ private:
DEBUG_STEP,
DEBUG_BREAK,
DEBUG_CONTINUE,
- DEBUG_KEEP_DEBUGGER_OPEN,
DEBUG_WITH_EXTERNAL_EDITOR,
};
@@ -109,11 +109,13 @@ private:
float remote_scene_tree_timeout = 0.0;
bool auto_switch_remote_scene_tree = false;
bool debug_with_external_editor = false;
- bool hide_on_stop = true;
+ bool keep_open = false;
+ String current_uri;
+
CameraOverride camera_override = OVERRIDE_NONE;
HashMap<Breakpoint, bool, Breakpoint> breakpoints;
- HashSet<Ref<Script>> debugger_plugins;
+ HashSet<Ref<EditorDebuggerPlugin>> debugger_plugins;
ScriptEditorDebugger *_add_debugger();
EditorDebuggerRemoteObject *get_inspected_remote_object();
@@ -190,7 +192,7 @@ public:
void set_live_debugging(bool p_enabled);
void update_live_edit_root();
void live_debug_create_node(const NodePath &p_parent, const String &p_type, const String &p_name);
- void live_debug_instance_node(const NodePath &p_parent, const String &p_path, const String &p_name);
+ void live_debug_instantiate_node(const NodePath &p_parent, const String &p_path, const String &p_name);
void live_debug_remove_node(const NodePath &p_at);
void live_debug_remove_and_keep_node(const NodePath &p_at, ObjectID p_keep_id);
void live_debug_restore_node(ObjectID p_id, const NodePath &p_at, int p_at_pos);
@@ -202,11 +204,13 @@ public:
String get_server_uri() const;
+ void set_keep_open(bool p_keep_open);
Error start(const String &p_uri = "tcp://");
- void stop();
+ void stop(bool p_force = false);
- void add_debugger_plugin(const Ref<Script> &p_script);
- void remove_debugger_plugin(const Ref<Script> &p_script);
+ bool plugins_capture(ScriptEditorDebugger *p_debugger, const String &p_message, const Array &p_data);
+ void add_debugger_plugin(const Ref<EditorDebuggerPlugin> &p_plugin);
+ void remove_debugger_plugin(const Ref<EditorDebuggerPlugin> &p_plugin);
};
#endif // EDITOR_DEBUGGER_NODE_H
diff --git a/editor/debugger/editor_debugger_tree.cpp b/editor/debugger/editor_debugger_tree.cpp
index 4168efda26..8b31781c5e 100644
--- a/editor/debugger/editor_debugger_tree.cpp
+++ b/editor/debugger/editor_debugger_tree.cpp
@@ -34,6 +34,7 @@
#include "editor/editor_node.h"
#include "editor/scene_tree_dock.h"
#include "scene/debugger/scene_debugger.h"
+#include "scene/gui/texture_rect.h"
#include "scene/resources/packed_scene.h"
#include "servers/display_server.h"
diff --git a/editor/debugger/editor_profiler.cpp b/editor/debugger/editor_profiler.cpp
index 35666a5566..0f8b2f36be 100644
--- a/editor/debugger/editor_profiler.cpp
+++ b/editor/debugger/editor_profiler.cpp
@@ -106,7 +106,7 @@ void EditorProfiler::clear() {
seeking = false;
// Ensure button text (start, stop) is correct
- _set_button_text();
+ _update_button_text();
emit_signal(SNAME("enable_profiling"), activate->is_pressed());
}
@@ -376,7 +376,7 @@ void EditorProfiler::_update_frame() {
updating_frame = false;
}
-void EditorProfiler::_set_button_text() {
+void EditorProfiler::_update_button_text() {
if (activate->is_pressed()) {
activate->set_icon(get_theme_icon(SNAME("Stop"), SNAME("EditorIcons")));
activate->set_text(TTR("Stop"));
@@ -387,7 +387,7 @@ void EditorProfiler::_set_button_text() {
}
void EditorProfiler::_activate_pressed() {
- _set_button_text();
+ _update_button_text();
if (activate->is_pressed()) {
_clear_pressed();
@@ -510,13 +510,17 @@ void EditorProfiler::_bind_methods() {
}
void EditorProfiler::set_enabled(bool p_enable, bool p_clear) {
- activate->set_pressed(false);
activate->set_disabled(!p_enable);
if (p_clear) {
clear();
}
}
+void EditorProfiler::set_pressed(bool p_pressed) {
+ activate->set_pressed(p_pressed);
+ _update_button_text();
+}
+
bool EditorProfiler::is_profiling() {
return activate->is_pressed();
}
@@ -595,6 +599,7 @@ EditorProfiler::EditorProfiler() {
add_child(hb);
activate = memnew(Button);
activate->set_toggle_mode(true);
+ activate->set_disabled(true);
activate->set_text(TTR("Start"));
activate->connect("pressed", callable_mp(this, &EditorProfiler::_activate_pressed));
hb->add_child(activate);
diff --git a/editor/debugger/editor_profiler.h b/editor/debugger/editor_profiler.h
index e9ecc285ed..d0dd67688b 100644
--- a/editor/debugger/editor_profiler.h
+++ b/editor/debugger/editor_profiler.h
@@ -122,7 +122,7 @@ private:
Timer *frame_delay = nullptr;
Timer *plot_delay = nullptr;
- void _set_button_text();
+ void _update_button_text();
void _update_frame();
void _activate_pressed();
@@ -155,6 +155,7 @@ protected:
public:
void add_frame_metric(const Metric &p_metric, bool p_final = false);
void set_enabled(bool p_enable, bool p_clear = true);
+ void set_pressed(bool p_pressed);
bool is_profiling();
bool is_seeking() { return seeking; }
void disable_seeking();
diff --git a/editor/debugger/editor_visual_profiler.cpp b/editor/debugger/editor_visual_profiler.cpp
index b8bc712ba6..fe425220c9 100644
--- a/editor/debugger/editor_visual_profiler.cpp
+++ b/editor/debugger/editor_visual_profiler.cpp
@@ -66,6 +66,7 @@ void EditorVisualProfiler::add_frame_metric(const Metric &p_metric) {
}
updating_frame = true;
+ clear_button->set_disabled(false);
cursor_metric_edit->set_max(frame_metrics[last_metric].frame_number);
cursor_metric_edit->set_min(MAX(frame_metrics[last_metric].frame_number - frame_metrics.size(), 0u));
@@ -408,6 +409,7 @@ void EditorVisualProfiler::_activate_pressed() {
activate->set_icon(get_theme_icon(SNAME("Stop"), SNAME("EditorIcons")));
activate->set_text(TTR("Stop"));
_clear_pressed(); //always clear on start
+ clear_button->set_disabled(false);
} else {
activate->set_icon(get_theme_icon(SNAME("Play"), SNAME("EditorIcons")));
activate->set_text(TTR("Start"));
@@ -416,6 +418,7 @@ void EditorVisualProfiler::_activate_pressed() {
}
void EditorVisualProfiler::_clear_pressed() {
+ clear_button->set_disabled(true);
clear();
_update_plot();
}
@@ -647,10 +650,25 @@ void EditorVisualProfiler::_bind_methods() {
ADD_SIGNAL(MethodInfo("enable_profiling", PropertyInfo(Variant::BOOL, "enable")));
}
+void EditorVisualProfiler::_update_button_text() {
+ if (activate->is_pressed()) {
+ activate->set_icon(get_theme_icon(SNAME("Stop"), SNAME("EditorIcons")));
+ activate->set_text(TTR("Stop"));
+ } else {
+ activate->set_icon(get_theme_icon(SNAME("Play"), SNAME("EditorIcons")));
+ activate->set_text(TTR("Start"));
+ }
+}
+
void EditorVisualProfiler::set_enabled(bool p_enable) {
activate->set_disabled(!p_enable);
}
+void EditorVisualProfiler::set_pressed(bool p_pressed) {
+ activate->set_pressed(p_pressed);
+ _update_button_text();
+}
+
bool EditorVisualProfiler::is_profiling() {
return activate->is_pressed();
}
@@ -714,12 +732,14 @@ EditorVisualProfiler::EditorVisualProfiler() {
add_child(hb);
activate = memnew(Button);
activate->set_toggle_mode(true);
+ activate->set_disabled(true);
activate->set_text(TTR("Start"));
activate->connect("pressed", callable_mp(this, &EditorVisualProfiler::_activate_pressed));
hb->add_child(activate);
clear_button = memnew(Button);
clear_button->set_text(TTR("Clear"));
+ clear_button->set_disabled(true);
clear_button->connect("pressed", callable_mp(this, &EditorVisualProfiler::_clear_pressed));
hb->add_child(clear_button);
diff --git a/editor/debugger/editor_visual_profiler.h b/editor/debugger/editor_visual_profiler.h
index 8aa9e7b308..8180d354e8 100644
--- a/editor/debugger/editor_visual_profiler.h
+++ b/editor/debugger/editor_visual_profiler.h
@@ -101,6 +101,8 @@ private:
Timer *frame_delay = nullptr;
Timer *plot_delay = nullptr;
+ void _update_button_text();
+
void _update_frame(bool p_focus_selected = false);
void _activate_pressed();
@@ -133,6 +135,7 @@ protected:
public:
void add_frame_metric(const Metric &p_metric);
void set_enabled(bool p_enable);
+ void set_pressed(bool p_pressed);
bool is_profiling();
bool is_seeking() { return seeking; }
void disable_seeking();
diff --git a/editor/debugger/script_editor_debugger.cpp b/editor/debugger/script_editor_debugger.cpp
index f1f34b8ebb..f6b00b83b0 100644
--- a/editor/debugger/script_editor_debugger.cpp
+++ b/editor/debugger/script_editor_debugger.cpp
@@ -37,7 +37,6 @@
#include "core/string/ustring.h"
#include "core/version.h"
#include "editor/debugger/debug_adapter/debug_adapter_protocol.h"
-#include "editor/debugger/editor_network_profiler.h"
#include "editor/debugger/editor_performance_profiler.h"
#include "editor/debugger/editor_profiler.h"
#include "editor/debugger/editor_visual_profiler.h"
@@ -47,12 +46,15 @@
#include "editor/editor_property_name_processor.h"
#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
+#include "editor/inspector_dock.h"
#include "editor/plugins/canvas_item_editor_plugin.h"
#include "editor/plugins/editor_debugger_plugin.h"
#include "editor/plugins/node_3d_editor_plugin.h"
#include "main/performance.h"
#include "scene/3d/camera_3d.h"
+#include "scene/debugger/scene_debugger.h"
#include "scene/gui/dialogs.h"
+#include "scene/gui/grid_container.h"
#include "scene/gui/label.h"
#include "scene/gui/line_edit.h"
#include "scene/gui/margin_container.h"
@@ -317,6 +319,7 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da
tabs->set_current_tab(0);
}
profiler->set_enabled(false, false);
+ visual_profiler->set_enabled(false);
inspector->clear_cache(); // Take a chance to force remote objects update.
} else if (p_msg == "debug_exit") {
@@ -326,8 +329,12 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da
_update_buttons_state();
_set_reason_text(TTR("Execution resumed."), MESSAGE_SUCCESS);
emit_signal(SNAME("breaked"), false, false, "", false);
+
profiler->set_enabled(true, false);
profiler->disable_seeking();
+
+ visual_profiler->set_enabled(true);
+
} else if (p_msg == "set_pid") {
ERR_FAIL_COND(p_data.size() < 1);
remote_pid = p_data[0];
@@ -713,17 +720,6 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da
profiler->add_frame_metric(metric, true);
}
- } else if (p_msg == "multiplayer:rpc") {
- SceneDebugger::RPCProfilerFrame frame;
- frame.deserialize(p_data);
- for (int i = 0; i < frame.infos.size(); i++) {
- network_profiler->add_node_frame_data(frame.infos[i]);
- }
-
- } else if (p_msg == "multiplayer:bandwidth") {
- ERR_FAIL_COND(p_data.size() < 2);
- network_profiler->set_bandwidth(p_data[0], p_data[1]);
-
} else if (p_msg == "request_quit") {
emit_signal(SNAME("stop_requested"));
_stop_and_notify();
@@ -741,22 +737,7 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da
int colon_index = p_msg.find_char(':');
ERR_FAIL_COND_MSG(colon_index < 1, "Invalid message received");
- bool parsed = false;
- const String cap = p_msg.substr(0, colon_index);
- HashMap<StringName, Callable>::Iterator element = captures.find(cap);
- if (element) {
- Callable &c = element->value;
- ERR_FAIL_COND_MSG(c.is_null(), "Invalid callable registered: " + cap);
- Variant cmd = p_msg.substr(colon_index + 1), cmd_data = p_data;
- const Variant *args[2] = { &cmd, &cmd_data };
- Variant retval;
- Callable::CallError 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;
- }
-
+ bool parsed = EditorDebuggerNode::get_singleton()->plugins_capture(this, p_msg, p_data);
if (!parsed) {
WARN_PRINT("unknown message " + p_msg);
}
@@ -775,7 +756,16 @@ void ScriptEditorDebugger::_set_reason_text(const String &p_reason, MessageType
reason->add_theme_color_override("font_color", get_theme_color(SNAME("success_color"), SNAME("Editor")));
}
reason->set_text(p_reason);
- reason->set_tooltip_text(p_reason.word_wrap(80));
+
+ const PackedInt32Array boundaries = TS->string_get_word_breaks(p_reason, "", 80);
+ PackedStringArray lines;
+ for (int i = 0; i < boundaries.size(); i += 2) {
+ const int start = boundaries[i];
+ const int end = boundaries[i + 1];
+ lines.append(p_reason.substr(start, end - start + 1));
+ }
+
+ reason->set_tooltip_text(String("\n").join(lines));
}
void ScriptEditorDebugger::_notification(int p_what) {
@@ -916,6 +906,7 @@ void ScriptEditorDebugger::start(Ref<RemoteDebuggerPeer> p_peer) {
stop();
profiler->set_enabled(true, true);
+ visual_profiler->set_enabled(true);
peer = p_peer;
ERR_FAIL_COND(p_peer.is_null());
@@ -972,7 +963,11 @@ void ScriptEditorDebugger::stop() {
res_path_cache.clear();
profiler_signature.clear();
- profiler->set_enabled(true, false);
+ profiler->set_enabled(false, false);
+ profiler->set_pressed(false);
+
+ visual_profiler->set_enabled(false);
+ visual_profiler->set_pressed(false);
inspector->edit(nullptr);
_update_buttons_state();
@@ -982,10 +977,6 @@ void ScriptEditorDebugger::_profiler_activate(bool p_enable, int p_type) {
Array msg_data;
msg_data.push_back(p_enable);
switch (p_type) {
- case PROFILER_NETWORK:
- _put_msg("profiler:multiplayer", msg_data);
- _put_msg("profiler:rpc", msg_data);
- break;
case PROFILER_VISUAL:
_put_msg("profiler:visual", msg_data);
break;
@@ -1283,13 +1274,13 @@ void ScriptEditorDebugger::live_debug_create_node(const NodePath &p_parent, cons
}
}
-void ScriptEditorDebugger::live_debug_instance_node(const NodePath &p_parent, const String &p_path, const String &p_name) {
+void ScriptEditorDebugger::live_debug_instantiate_node(const NodePath &p_parent, const String &p_path, const String &p_name) {
if (live_debug) {
Array msg;
msg.push_back(p_parent);
msg.push_back(p_path);
msg.push_back(p_name);
- _put_msg("scene:live_instance_node", msg);
+ _put_msg("scene:live_instantiate_node", msg);
}
}
@@ -1626,7 +1617,7 @@ void ScriptEditorDebugger::_tab_changed(int p_tab) {
void ScriptEditorDebugger::_bind_methods() {
ClassDB::bind_method(D_METHOD("live_debug_create_node"), &ScriptEditorDebugger::live_debug_create_node);
- ClassDB::bind_method(D_METHOD("live_debug_instance_node"), &ScriptEditorDebugger::live_debug_instance_node);
+ ClassDB::bind_method(D_METHOD("live_debug_instantiate_node"), &ScriptEditorDebugger::live_debug_instantiate_node);
ClassDB::bind_method(D_METHOD("live_debug_remove_node"), &ScriptEditorDebugger::live_debug_remove_node);
ClassDB::bind_method(D_METHOD("live_debug_remove_and_keep_node"), &ScriptEditorDebugger::live_debug_remove_and_keep_node);
ClassDB::bind_method(D_METHOD("live_debug_restore_node"), &ScriptEditorDebugger::live_debug_restore_node);
@@ -1658,41 +1649,25 @@ void ScriptEditorDebugger::_bind_methods() {
ADD_SIGNAL(MethodInfo("errors_cleared"));
}
-void ScriptEditorDebugger::add_debugger_plugin(const Ref<Script> &p_script) {
- if (!debugger_plugins.has(p_script)) {
- EditorDebuggerPlugin *plugin = memnew(EditorDebuggerPlugin());
- plugin->attach_debugger(this);
- plugin->set_script(p_script);
- tabs->add_child(plugin);
- debugger_plugins.insert(p_script, plugin);
- }
+void ScriptEditorDebugger::add_debugger_tab(Control *p_control) {
+ tabs->add_child(p_control);
}
-void ScriptEditorDebugger::remove_debugger_plugin(const Ref<Script> &p_script) {
- if (debugger_plugins.has(p_script)) {
- tabs->remove_child(debugger_plugins[p_script]);
- debugger_plugins[p_script]->detach_debugger(false);
- memdelete(debugger_plugins[p_script]);
- debugger_plugins.erase(p_script);
- }
+void ScriptEditorDebugger::remove_debugger_tab(Control *p_control) {
+ int idx = tabs->get_tab_idx_from_control(p_control);
+ ERR_FAIL_COND(idx < 0);
+ p_control->queue_free();
}
void ScriptEditorDebugger::send_message(const String &p_message, const Array &p_args) {
_put_msg(p_message, p_args);
}
-void ScriptEditorDebugger::register_message_capture(const StringName &p_name, const Callable &p_callable) {
- ERR_FAIL_COND_MSG(has_capture(p_name), "Capture already registered: " + p_name);
- captures.insert(p_name, p_callable);
-}
-
-void ScriptEditorDebugger::unregister_message_capture(const StringName &p_name) {
- ERR_FAIL_COND_MSG(!has_capture(p_name), "Capture not registered: " + p_name);
- captures.erase(p_name);
-}
-
-bool ScriptEditorDebugger::has_capture(const StringName &p_name) {
- return captures.has(p_name);
+void ScriptEditorDebugger::toggle_profiler(const String &p_profiler, bool p_enable, const Array &p_data) {
+ Array msg_data;
+ msg_data.push_back(p_enable);
+ msg_data.append_array(p_data);
+ _put_msg("profiler:" + p_profiler, msg_data);
}
ScriptEditorDebugger::ScriptEditorDebugger() {
@@ -1702,6 +1677,8 @@ ScriptEditorDebugger::ScriptEditorDebugger() {
add_child(tabs);
+ InspectorDock::get_inspector_singleton()->connect("object_id_selected", callable_mp(this, &ScriptEditorDebugger::_remote_object_selected));
+
{ //debugger
VBoxContainer *vbc = memnew(VBoxContainer);
vbc->set_name(TTR("Debugger"));
@@ -1904,13 +1881,6 @@ ScriptEditorDebugger::ScriptEditorDebugger() {
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).bind(PROFILER_NETWORK));
- }
-
{ //monitors
performance_profiler = memnew(EditorPerformanceProfiler);
tabs->add_child(performance_profiler);
diff --git a/editor/debugger/script_editor_debugger.h b/editor/debugger/script_editor_debugger.h
index aa0a50ff03..06bff39053 100644
--- a/editor/debugger/script_editor_debugger.h
+++ b/editor/debugger/script_editor_debugger.h
@@ -50,7 +50,6 @@ class ItemList;
class EditorProfiler;
class EditorFileDialog;
class EditorVisualProfiler;
-class EditorNetworkProfiler;
class EditorPerformanceProfiler;
class SceneDebuggerTree;
class EditorDebuggerPlugin;
@@ -72,7 +71,6 @@ private:
};
enum ProfilerType {
- PROFILER_NETWORK,
PROFILER_VISUAL,
PROFILER_SCRIPTS_SERVERS
};
@@ -151,7 +149,6 @@ private:
EditorProfiler *profiler = nullptr;
EditorVisualProfiler *visual_profiler = nullptr;
- EditorNetworkProfiler *network_profiler = nullptr;
EditorPerformanceProfiler *performance_profiler = nullptr;
OS::ProcessID remote_pid = 0;
@@ -163,10 +160,6 @@ private:
EditorDebuggerNode::CameraOverride camera_override;
- HashMap<Ref<Script>, EditorDebuggerPlugin *> debugger_plugins;
-
- HashMap<StringName, Callable> captures;
-
void _stack_dump_frame_selected();
void _file_selected(const String &p_file);
@@ -266,7 +259,7 @@ public:
void set_live_debugging(bool p_enable);
void live_debug_create_node(const NodePath &p_parent, const String &p_type, const String &p_name);
- void live_debug_instance_node(const NodePath &p_parent, const String &p_path, const String &p_name);
+ void live_debug_instantiate_node(const NodePath &p_parent, const String &p_path, const String &p_name);
void live_debug_remove_node(const NodePath &p_at);
void live_debug_remove_and_keep_node(const NodePath &p_at, ObjectID p_keep_id);
void live_debug_restore_node(ObjectID p_id, const NodePath &p_at, int p_at_pos);
@@ -286,14 +279,11 @@ public:
virtual Size2 get_minimum_size() const override;
- void add_debugger_plugin(const Ref<Script> &p_script);
- void remove_debugger_plugin(const Ref<Script> &p_script);
+ void add_debugger_tab(Control *p_control);
+ void remove_debugger_tab(Control *p_control);
void send_message(const String &p_message, const Array &p_args);
-
- void register_message_capture(const StringName &p_name, const Callable &p_callable);
- void unregister_message_capture(const StringName &p_name);
- bool has_capture(const StringName &p_name);
+ void toggle_profiler(const String &p_profiler, bool p_enable, const Array &p_data);
ScriptEditorDebugger();
~ScriptEditorDebugger();
diff --git a/editor/doc_tools.cpp b/editor/doc_tools.cpp
index 14a2640e63..65e73d8df4 100644
--- a/editor/doc_tools.cpp
+++ b/editor/doc_tools.cpp
@@ -701,7 +701,7 @@ void DocTools::generate(bool p_basic_types) {
if (rt != Variant::NIL) { // Has operator.
// Skip String % operator as it's registered separately for each Variant arg type,
// we'll add it manually below.
- if (i == Variant::STRING && Variant::Operator(j) == Variant::OP_MODULE) {
+ if ((i == Variant::STRING || i == Variant::STRING_NAME) && Variant::Operator(j) == Variant::OP_MODULE) {
continue;
}
MethodInfo mi;
@@ -718,7 +718,7 @@ void DocTools::generate(bool p_basic_types) {
}
}
- if (i == Variant::STRING) {
+ if (i == Variant::STRING || i == Variant::STRING_NAME) {
// We skipped % operator above, and we register it manually once for Variant arg type here.
MethodInfo mi;
mi.name = "operator %";
diff --git a/editor/editor_audio_buses.cpp b/editor/editor_audio_buses.cpp
index 24116a8053..a040d918df 100644
--- a/editor/editor_audio_buses.cpp
+++ b/editor/editor_audio_buses.cpp
@@ -40,6 +40,7 @@
#include "editor/editor_settings.h"
#include "editor/editor_undo_redo_manager.h"
#include "filesystem_dock.h"
+#include "scene/gui/separator.h"
#include "scene/resources/font.h"
#include "servers/audio_server.h"
diff --git a/editor/editor_audio_buses.h b/editor/editor_audio_buses.h
index 436b391ccd..97e94089cc 100644
--- a/editor/editor_audio_buses.h
+++ b/editor/editor_audio_buses.h
@@ -47,6 +47,7 @@
#include "scene/gui/tree.h"
class EditorAudioBuses;
+class EditorFileDialog;
class EditorAudioBus : public PanelContainer {
GDCLASS(EditorAudioBus, PanelContainer);
diff --git a/editor/editor_autoload_settings.cpp b/editor/editor_autoload_settings.cpp
index 598bcdc639..41b3d45a1f 100644
--- a/editor/editor_autoload_settings.cpp
+++ b/editor/editor_autoload_settings.cpp
@@ -400,27 +400,38 @@ void EditorAutoloadSettings::_autoload_text_changed(const String p_name) {
}
Node *EditorAutoloadSettings::_create_autoload(const String &p_path) {
- Ref<Resource> res = ResourceLoader::load(p_path);
- ERR_FAIL_COND_V_MSG(res.is_null(), nullptr, "Can't autoload: " + p_path + ".");
Node *n = nullptr;
- Ref<PackedScene> scn = res;
- Ref<Script> scr = res;
- if (scn.is_valid()) {
- n = scn->instantiate();
- } else if (scr.is_valid()) {
- StringName ibt = scr->get_instance_base_type();
- bool valid_type = ClassDB::is_parent_class(ibt, "Node");
- ERR_FAIL_COND_V_MSG(!valid_type, nullptr, "Script does not inherit from Node: " + p_path + ".");
+ if (ResourceLoader::get_resource_type(p_path) == "PackedScene") {
+ // Cache the scene reference before loading it (for cyclic references)
+ Ref<PackedScene> scn;
+ scn.instantiate();
+ scn->set_path(p_path);
+ scn->reload_from_file();
+ ERR_FAIL_COND_V_MSG(!scn.is_valid(), nullptr, vformat("Can't autoload: %s.", p_path));
- Object *obj = ClassDB::instantiate(ibt);
+ if (scn.is_valid()) {
+ n = scn->instantiate();
+ }
+ } else {
+ Ref<Resource> res = ResourceLoader::load(p_path);
+ ERR_FAIL_COND_V_MSG(res.is_null(), nullptr, vformat("Can't autoload: %s.", p_path));
+
+ Ref<Script> scr = res;
+ if (scr.is_valid()) {
+ StringName ibt = scr->get_instance_base_type();
+ bool valid_type = ClassDB::is_parent_class(ibt, "Node");
+ ERR_FAIL_COND_V_MSG(!valid_type, nullptr, vformat("Script does not inherit from Node: %s.", p_path));
+
+ Object *obj = ClassDB::instantiate(ibt);
- ERR_FAIL_COND_V_MSG(!obj, nullptr, "Cannot instance script for Autoload, expected 'Node' inheritance, got: " + String(ibt) + ".");
+ ERR_FAIL_COND_V_MSG(!obj, nullptr, vformat("Cannot instance script for Autoload, expected 'Node' inheritance, got: %s.", ibt));
- n = Object::cast_to<Node>(obj);
- n->set_script(scr);
+ n = Object::cast_to<Node>(obj);
+ n->set_script(scr);
+ }
}
- ERR_FAIL_COND_V_MSG(!n, nullptr, "Path in Autoload not a node or script: " + p_path + ".");
+ ERR_FAIL_COND_V_MSG(!n, nullptr, vformat("Path in Autoload not a node or script: %s.", p_path));
return n;
}
@@ -530,8 +541,6 @@ void EditorAutoloadSettings::update_autoload() {
info.node->queue_free();
info.node = nullptr;
}
-
- ProjectSettings::get_singleton()->remove_autoload(info.name);
}
// Load new/changed autoloads
@@ -556,12 +565,6 @@ void EditorAutoloadSettings::update_autoload() {
}
}
- ProjectSettings::AutoloadInfo prop_info;
- prop_info.name = info->name;
- prop_info.path = info->path;
- prop_info.is_singleton = info->is_singleton;
- ProjectSettings::get_singleton()->add_autoload(prop_info);
-
if (!info->in_editor && !info->is_singleton) {
// No reason to keep this node
memdelete(info->node);
diff --git a/editor/editor_build_profile.h b/editor/editor_build_profile.h
index 606c415429..9624f7e44b 100644
--- a/editor/editor_build_profile.h
+++ b/editor/editor_build_profile.h
@@ -117,6 +117,7 @@ public:
VARIANT_ENUM_CAST(EditorBuildProfile::BuildOption)
VARIANT_ENUM_CAST(EditorBuildProfile::BuildOptionCategory)
+class EditorFileDialog;
class EditorFileSystemDirectory;
class EditorBuildProfileManager : public AcceptDialog {
diff --git a/editor/editor_command_palette.cpp b/editor/editor_command_palette.cpp
index 3f93fa1f41..609afeb40a 100644
--- a/editor/editor_command_palette.cpp
+++ b/editor/editor_command_palette.cpp
@@ -38,6 +38,9 @@
EditorCommandPalette *EditorCommandPalette::singleton = nullptr;
+static Rect2i prev_rect = Rect2i();
+static bool was_showed = false;
+
float EditorCommandPalette::_score_path(const String &p_search, const String &p_path) {
float score = 0.9f + .1f * (p_search.length() / (float)p_path.length());
@@ -145,6 +148,17 @@ void EditorCommandPalette::_bind_methods() {
ClassDB::bind_method(D_METHOD("remove_command", "key_name"), &EditorCommandPalette::remove_command);
}
+void EditorCommandPalette::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_VISIBILITY_CHANGED: {
+ if (!is_visible()) {
+ prev_rect = Rect2i(get_position(), get_size());
+ was_showed = true;
+ }
+ } break;
+ }
+}
+
void EditorCommandPalette::_sbox_input(const Ref<InputEvent> &p_ie) {
Ref<InputEventKey> k = p_ie;
if (k.is_valid()) {
@@ -171,7 +185,11 @@ void EditorCommandPalette::_confirmed() {
}
void EditorCommandPalette::open_popup() {
- popup_centered_clamped(Size2i(600, 440), 0.8f);
+ if (was_showed) {
+ popup(prev_rect);
+ } else {
+ popup_centered_clamped(Size2(600, 440) * EDSCALE, 0.8f);
+ }
command_search_box->clear();
command_search_box->grab_focus();
diff --git a/editor/editor_command_palette.h b/editor/editor_command_palette.h
index 15200552b4..81cf401851 100644
--- a/editor/editor_command_palette.h
+++ b/editor/editor_command_palette.h
@@ -91,6 +91,7 @@ class EditorCommandPalette : public ConfirmationDialog {
protected:
static void _bind_methods();
+ void _notification(int p_what);
public:
void open_popup();
diff --git a/editor/editor_data.cpp b/editor/editor_data.cpp
index a3dd19bb67..e593d652ad 100644
--- a/editor/editor_data.cpp
+++ b/editor/editor_data.cpp
@@ -486,7 +486,7 @@ void EditorData::add_custom_type(const String &p_type, const String &p_inherits,
custom_types[p_inherits].push_back(ct);
}
-Variant EditorData::instance_custom_type(const String &p_type, const String &p_inherits) {
+Variant EditorData::instantiate_custom_type(const String &p_type, const String &p_inherits) {
if (get_custom_types().has(p_inherits)) {
for (int i = 0; i < get_custom_types()[p_inherits].size(); i++) {
if (get_custom_types()[p_inherits][i].name == p_type) {
@@ -945,11 +945,12 @@ StringName EditorData::script_class_get_base(const String &p_class) const {
Variant EditorData::script_class_instance(const String &p_class) {
if (ScriptServer::is_global_class(p_class)) {
- Variant obj = ClassDB::instantiate(ScriptServer::get_global_class_native_base(p_class));
- if (obj) {
- Ref<Script> script = script_class_load_script(p_class);
- if (script.is_valid()) {
- ((Object *)obj)->set_script(script);
+ Ref<Script> script = script_class_load_script(p_class);
+ if (script.is_valid()) {
+ // Store in a variant to initialize the refcount if needed.
+ Variant obj = ClassDB::instantiate(script->get_instance_base_type());
+ if (obj) {
+ obj.operator Object *()->set_script(script);
}
return obj;
}
diff --git a/editor/editor_data.h b/editor/editor_data.h
index 4f1740d4f0..aad00f3ff8 100644
--- a/editor/editor_data.h
+++ b/editor/editor_data.h
@@ -181,7 +181,7 @@ public:
void restore_editor_global_states();
void add_custom_type(const String &p_type, const String &p_inherits, const Ref<Script> &p_script, const Ref<Texture2D> &p_icon);
- Variant instance_custom_type(const String &p_type, const String &p_inherits);
+ Variant instantiate_custom_type(const String &p_type, const String &p_inherits);
void remove_custom_type(const String &p_type);
const HashMap<String, Vector<CustomType>> &get_custom_types() const { return custom_types; }
const CustomType *get_custom_type_by_name(const String &p_name) const;
diff --git a/editor/editor_feature_profile.cpp b/editor/editor_feature_profile.cpp
index 49fb16a095..7080cdbdd5 100644
--- a/editor/editor_feature_profile.cpp
+++ b/editor/editor_feature_profile.cpp
@@ -309,7 +309,11 @@ void EditorFeatureProfile::_bind_methods() {
BIND_ENUM_CONSTANT(FEATURE_MAX);
}
-EditorFeatureProfile::EditorFeatureProfile() {}
+EditorFeatureProfile::EditorFeatureProfile() {
+ for (int i = 0; i < FEATURE_MAX; i++) {
+ features_disabled[i] = false;
+ }
+}
//////////////////////////
@@ -746,6 +750,8 @@ void EditorFeatureProfileManager::_update_selected_profile() {
class_list->clear();
String profile = _get_selected_profile();
+ profile_actions[PROFILE_SET]->set_disabled(profile == current_profile);
+
if (profile.is_empty()) { //nothing selected, nothing edited
property_list->clear();
edited.unref();
diff --git a/editor/editor_feature_profile.h b/editor/editor_feature_profile.h
index 6868c54146..1d79844913 100644
--- a/editor/editor_feature_profile.h
+++ b/editor/editor_feature_profile.h
@@ -40,6 +40,8 @@
#include "scene/gui/split_container.h"
#include "scene/gui/tree.h"
+class EditorFileDialog;
+
class EditorFeatureProfile : public RefCounted {
GDCLASS(EditorFeatureProfile, RefCounted);
diff --git a/editor/editor_file_dialog.cpp b/editor/editor_file_dialog.cpp
index ee02916a5f..55c512f77d 100644
--- a/editor/editor_file_dialog.cpp
+++ b/editor/editor_file_dialog.cpp
@@ -34,7 +34,6 @@
#include "core/io/file_access.h"
#include "core/os/keyboard.h"
#include "core/os/os.h"
-#include "core/string/print_string.h"
#include "dependency_editor.h"
#include "editor/editor_file_system.h"
#include "editor/editor_node.h"
@@ -44,6 +43,10 @@
#include "scene/gui/center_container.h"
#include "scene/gui/label.h"
#include "scene/gui/margin_container.h"
+#include "scene/gui/option_button.h"
+#include "scene/gui/separator.h"
+#include "scene/gui/split_container.h"
+#include "scene/gui/texture_rect.h"
#include "servers/display_server.h"
EditorFileDialog::GetIconFunc EditorFileDialog::get_icon_func = nullptr;
diff --git a/editor/editor_file_dialog.h b/editor/editor_file_dialog.h
index 2e7302aaf9..40073326a1 100644
--- a/editor/editor_file_dialog.h
+++ b/editor/editor_file_dialog.h
@@ -32,17 +32,14 @@
#define EDITOR_FILE_DIALOG_H
#include "core/io/dir_access.h"
-#include "editor/plugins/editor_preview_plugins.h"
-#include "scene/gui/box_container.h"
#include "scene/gui/dialogs.h"
-#include "scene/gui/item_list.h"
-#include "scene/gui/line_edit.h"
-#include "scene/gui/option_button.h"
-#include "scene/gui/separator.h"
-#include "scene/gui/split_container.h"
-#include "scene/gui/texture_rect.h"
class DependencyRemoveDialog;
+class HSplitContainer;
+class ItemList;
+class OptionButton;
+class PopupMenu;
+class TextureRect;
class EditorFileDialog : public ConfirmationDialog {
GDCLASS(EditorFileDialog, ConfirmationDialog);
diff --git a/editor/editor_file_system.cpp b/editor/editor_file_system.cpp
index ce06631fdd..b98480b594 100644
--- a/editor/editor_file_system.cpp
+++ b/editor/editor_file_system.cpp
@@ -31,7 +31,7 @@
#include "editor_file_system.h"
#include "core/config/project_settings.h"
-#include "core/extension/native_extension_manager.h"
+#include "core/extension/gdextension_manager.h"
#include "core/io/file_access.h"
#include "core/io/resource_importer.h"
#include "core/io/resource_loader.h"
@@ -39,6 +39,7 @@
#include "core/object/worker_thread_pool.h"
#include "core/os/os.h"
#include "core/variant/variant_parser.h"
+#include "editor/editor_help.h"
#include "editor/editor_node.h"
#include "editor/editor_paths.h"
#include "editor/editor_resource_preview.h"
@@ -619,7 +620,12 @@ bool EditorFileSystem::_update_scan_actions() {
if (_test_for_reimport(full_path, false)) {
//must reimport
reimports.push_back(full_path);
- reimports.append_array(_get_dependencies(full_path));
+ Vector<String> dependencies = _get_dependencies(full_path);
+ for (const String &dependency_path : dependencies) {
+ if (import_extensions.has(dependency_path.get_extension())) {
+ reimports.push_back(dependency_path);
+ }
+ }
} else {
//must not reimport, all was good
//update modified times, to avoid reimport
@@ -1636,6 +1642,7 @@ Error EditorFileSystem::_reimport_group(const String &p_group_file, const Vector
String importer_name;
HashMap<String, HashMap<StringName, Variant>> source_file_options;
+ HashMap<String, ResourceUID::ID> uids;
HashMap<String, String> base_paths;
for (int i = 0; i < p_files.size(); i++) {
Ref<ConfigFile> config;
@@ -1651,6 +1658,15 @@ Error EditorFileSystem::_reimport_group(const String &p_group_file, const Vector
ERR_FAIL_V(ERR_FILE_CORRUPT);
}
+ ResourceUID::ID uid = ResourceUID::INVALID_ID;
+
+ if (config->has_section_key("remap", "uid")) {
+ String uidt = config->get_value("remap", "uid");
+ uid = ResourceUID::get_singleton()->text_to_id(uidt);
+ }
+
+ uids[p_files[i]] = uid;
+
source_file_options[p_files[i]] = HashMap<StringName, Variant>();
importer_name = file_importer_name;
@@ -1695,6 +1711,7 @@ Error EditorFileSystem::_reimport_group(const String &p_group_file, const Vector
const String &file = E.key;
String base_path = ResourceFormatImporter::get_singleton()->get_import_base_path(file);
Vector<String> dest_paths;
+ ResourceUID::ID uid = uids[file];
{
Ref<FileAccess> f = FileAccess::open(file + ".import", FileAccess::WRITE);
ERR_FAIL_COND_V_MSG(f.is_null(), ERR_FILE_CANT_OPEN, "Cannot open import file '" + file + ".import'.");
@@ -1711,6 +1728,12 @@ Error EditorFileSystem::_reimport_group(const String &p_group_file, const Vector
f->store_line("type=\"" + importer->get_resource_type() + "\"");
}
+ if (uid == ResourceUID::INVALID_ID) {
+ uid = ResourceUID::get_singleton()->create_id();
+ }
+
+ f->store_line("uid=\"" + ResourceUID::get_singleton()->id_to_text(uid) + "\""); // Store in readable format.
+
if (err == OK) {
String path = base_path + "." + importer->get_save_extension();
f->store_line("path=\"" + path + "\"");
@@ -1776,12 +1799,19 @@ Error EditorFileSystem::_reimport_group(const String &p_group_file, const Vector
fs->files[cpos]->modified_time = FileAccess::get_modified_time(file);
fs->files[cpos]->import_modified_time = FileAccess::get_modified_time(file + ".import");
fs->files[cpos]->deps = _get_dependencies(file);
+ fs->files[cpos]->uid = uid;
fs->files[cpos]->type = importer->get_resource_type();
if (fs->files[cpos]->type == "" && textfile_extensions.has(file.get_extension())) {
fs->files[cpos]->type = "TextFile";
}
fs->files[cpos]->import_valid = err == OK;
+ if (ResourceUID::get_singleton()->has_id(uid)) {
+ ResourceUID::get_singleton()->set_id(uid, file);
+ } else {
+ ResourceUID::get_singleton()->add_id(uid, file);
+ }
+
//if file is currently up, maybe the source it was loaded from changed, so import math must be updated for it
//to reload properly
Ref<Resource> r = ResourceCache::get_ref(file);
@@ -2068,6 +2098,8 @@ void EditorFileSystem::reimport_files(const Vector<String> &p_files) {
importing = true;
EditorProgress pr("reimport", TTR("(Re)Importing Assets"), p_files.size());
+ Vector<String> reloads;
+
Vector<ImportFile> reimport_files;
HashSet<String> groups_to_reimport;
@@ -2083,22 +2115,26 @@ void EditorFileSystem::reimport_files(const Vector<String> &p_files) {
String group_file = ResourceFormatImporter::get_singleton()->get_import_group_file(file);
if (group_file_cache.has(file)) {
- //maybe the file itself is a group!
+ // Maybe the file itself is a group!
groups_to_reimport.insert(file);
- //groups do not belong to groups
+ // Groups do not belong to groups.
+ group_file = String();
+ } else if (groups_to_reimport.has(file)) {
+ // Groups do not belong to groups.
group_file = String();
} else if (!group_file.is_empty()) {
- //it's a group file, add group to import and skip this file
+ // It's a group file, add group to import and skip this file.
groups_to_reimport.insert(group_file);
} else {
- //it's a regular file
+ // It's a regular file.
ImportFile ifile;
ifile.path = file;
ResourceFormatImporter::get_singleton()->get_import_order_threads_and_importer(file, ifile.order, ifile.threaded, ifile.importer);
+ reloads.push_back(file);
reimport_files.push_back(ifile);
}
- //group may have changed, so also update group reference
+ // Group may have changed, so also update group reference.
EditorFileSystemDirectory *fs = nullptr;
int cpos = -1;
if (_find_file(file, &fs, cpos)) {
@@ -2112,10 +2148,14 @@ void EditorFileSystem::reimport_files(const Vector<String> &p_files) {
int from = 0;
for (int i = 0; i < reimport_files.size(); i++) {
+ if (groups_to_reimport.has(reimport_files[i].path)) {
+ continue;
+ }
+
if (use_multiple_threads && reimport_files[i].threaded) {
if (i + 1 == reimport_files.size() || reimport_files[i + 1].importer != reimport_files[from].importer) {
if (from - i == 0) {
- //single file, do not use threads
+ // Single file, do not use threads.
pr.step(reimport_files[i].path.get_file(), i);
_reimport_file(reimport_files[i].path);
} else {
@@ -2153,20 +2193,25 @@ void EditorFileSystem::reimport_files(const Vector<String> &p_files) {
}
}
- //reimport groups
+ // Reimport groups.
+
+ from = reimport_files.size();
if (groups_to_reimport.size()) {
HashMap<String, Vector<String>> group_files;
_find_group_files(filesystem, group_files, groups_to_reimport);
for (const KeyValue<String, Vector<String>> &E : group_files) {
+ pr.step(E.key.get_file(), from++);
Error err = _reimport_group(E.key, E.value);
+ reloads.push_back(E.key);
+ reloads.append_array(E.value);
if (err == OK) {
_reimport_file(E.key);
}
}
}
- ResourceUID::get_singleton()->update_cache(); //after reimporting, update the cache
+ ResourceUID::get_singleton()->update_cache(); // After reimporting, update the cache.
_save_filesystem_cache();
importing = false;
@@ -2174,7 +2219,7 @@ void EditorFileSystem::reimport_files(const Vector<String> &p_files) {
emit_signal(SNAME("filesystem_changed"));
}
- emit_signal(SNAME("resources_reimported"), p_files);
+ emit_signal(SNAME("resources_reimported"), reloads);
}
Error EditorFileSystem::_resource_import(const String &p_path) {
@@ -2290,7 +2335,7 @@ ResourceUID::ID EditorFileSystem::_resource_saver_get_resource_id_for_path(const
static void _scan_extensions_dir(EditorFileSystemDirectory *d, HashSet<String> &extensions) {
int fc = d->get_file_count();
for (int i = 0; i < fc; i++) {
- if (d->get_file_type(i) == SNAME("NativeExtension")) {
+ if (d->get_file_type(i) == SNAME("GDExtension")) {
extensions.insert(d->get_file_path(i));
}
}
@@ -2311,19 +2356,19 @@ bool EditorFileSystem::_scan_extensions() {
Vector<String> extensions_removed;
for (const String &E : extensions) {
- if (!NativeExtensionManager::get_singleton()->is_extension_loaded(E)) {
+ if (!GDExtensionManager::get_singleton()->is_extension_loaded(E)) {
extensions_added.push_back(E);
}
}
- Vector<String> loaded_extensions = NativeExtensionManager::get_singleton()->get_loaded_extensions();
+ Vector<String> loaded_extensions = GDExtensionManager::get_singleton()->get_loaded_extensions();
for (int i = 0; i < loaded_extensions.size(); i++) {
if (!extensions.has(loaded_extensions[i])) {
extensions_removed.push_back(loaded_extensions[i]);
}
}
- String extension_list_config_file = NativeExtension::get_extension_list_config_file();
+ String extension_list_config_file = GDExtension::get_extension_list_config_file();
if (extensions.size()) {
if (extensions_added.size() || extensions_removed.size()) { //extensions were added or removed
Ref<FileAccess> f = FileAccess::open(extension_list_config_file, FileAccess::WRITE);
@@ -2340,18 +2385,18 @@ bool EditorFileSystem::_scan_extensions() {
bool needs_restart = false;
for (int i = 0; i < extensions_added.size(); i++) {
- NativeExtensionManager::LoadStatus st = NativeExtensionManager::get_singleton()->load_extension(extensions_added[i]);
- if (st == NativeExtensionManager::LOAD_STATUS_FAILED) {
+ GDExtensionManager::LoadStatus st = GDExtensionManager::get_singleton()->load_extension(extensions_added[i]);
+ if (st == GDExtensionManager::LOAD_STATUS_FAILED) {
EditorNode::get_singleton()->add_io_error("Error loading extension: " + extensions_added[i]);
- } else if (st == NativeExtensionManager::LOAD_STATUS_NEEDS_RESTART) {
+ } else if (st == GDExtensionManager::LOAD_STATUS_NEEDS_RESTART) {
needs_restart = true;
}
}
for (int i = 0; i < extensions_removed.size(); i++) {
- NativeExtensionManager::LoadStatus st = NativeExtensionManager::get_singleton()->unload_extension(extensions_removed[i]);
- if (st == NativeExtensionManager::LOAD_STATUS_FAILED) {
+ GDExtensionManager::LoadStatus st = GDExtensionManager::get_singleton()->unload_extension(extensions_removed[i]);
+ if (st == GDExtensionManager::LOAD_STATUS_FAILED) {
EditorNode::get_singleton()->add_io_error("Error removing extension: " + extensions_added[i]);
- } else if (st == NativeExtensionManager::LOAD_STATUS_NEEDS_RESTART) {
+ } else if (st == GDExtensionManager::LOAD_STATUS_NEEDS_RESTART) {
needs_restart = true;
}
}
diff --git a/editor/editor_fonts.cpp b/editor/editor_fonts.cpp
index 51ebc31df3..cf413133aa 100644
--- a/editor/editor_fonts.cpp
+++ b/editor/editor_fonts.cpp
@@ -41,7 +41,7 @@ Ref<FontFile> load_external_font(const String &p_path, TextServer::Hinting p_hin
Ref<FontFile> font;
font.instantiate();
- Vector<uint8_t> data = FileAccess::get_file_as_array(p_path);
+ Vector<uint8_t> data = FileAccess::get_file_as_bytes(p_path);
font->set_data(data);
font->set_multichannel_signed_distance_field(p_msdf);
@@ -335,7 +335,7 @@ void editor_register_fonts(Ref<Theme> p_theme) {
}
mono_fc->set_opentype_features(ftrs);
} break;
- default: { // Default.
+ default: { // Enabled.
Dictionary ftrs;
ftrs[TS->name_to_tag("calt")] = 1;
mono_fc->set_opentype_features(ftrs);
diff --git a/editor/editor_help.cpp b/editor/editor_help.cpp
index 89398409a2..21119048cb 100644
--- a/editor/editor_help.cpp
+++ b/editor/editor_help.cpp
@@ -39,6 +39,7 @@
#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/plugins/script_editor_plugin.h"
+#include "scene/gui/line_edit.h"
#define CONTRIBUTE_URL vformat("%s/community/contributing/updating_the_class_reference.html", VERSION_DOCS_URL)
@@ -58,6 +59,8 @@ void EditorHelp::_update_theme() {
class_desc->add_theme_constant_override("line_separation", get_theme_constant(SNAME("line_separation"), SNAME("EditorHelp")));
class_desc->add_theme_constant_override("table_h_separation", get_theme_constant(SNAME("table_h_separation"), SNAME("EditorHelp")));
class_desc->add_theme_constant_override("table_v_separation", get_theme_constant(SNAME("table_v_separation"), SNAME("EditorHelp")));
+ class_desc->add_theme_constant_override("text_highlight_h_padding", get_theme_constant(SNAME("text_highlight_h_padding"), SNAME("EditorHelp")));
+ class_desc->add_theme_constant_override("text_highlight_v_padding", get_theme_constant(SNAME("text_highlight_v_padding"), SNAME("EditorHelp")));
doc_font = get_theme_font(SNAME("doc"), SNAME("EditorFonts"));
doc_bold_font = get_theme_font(SNAME("doc_bold"), SNAME("EditorFonts"));
@@ -191,21 +194,29 @@ void EditorHelp::_class_desc_resized(bool p_force_update_theme) {
if (display_margin != new_display_margin || p_force_update_theme) {
display_margin = new_display_margin;
- Ref<StyleBox> class_desc_stylebox = EditorNode::get_singleton()->get_theme_base()->get_theme_stylebox(SNAME("normal"), SNAME("RichTextLabel"))->duplicate();
+ Ref<StyleBox> class_desc_stylebox = EditorNode::get_singleton()->get_theme_base()->get_theme_stylebox(SNAME("background"), SNAME("EditorHelp"))->duplicate();
class_desc_stylebox->set_default_margin(SIDE_LEFT, display_margin);
class_desc_stylebox->set_default_margin(SIDE_RIGHT, display_margin);
class_desc->add_theme_style_override("normal", class_desc_stylebox);
+ class_desc->add_theme_style_override("focused", class_desc_stylebox);
}
}
void EditorHelp::_add_type(const String &p_type, const String &p_enum) {
- String t = p_type;
- if (t.is_empty()) {
- t = "void";
+ if (p_type.is_empty() || p_type == "void") {
+ class_desc->push_color(Color(type_color, 0.5));
+ class_desc->push_hint(TTR("No return value."));
+ class_desc->add_text("void");
+ class_desc->pop();
+ class_desc->pop();
+ return;
}
- bool can_ref = (t != "void" && !t.contains("*")) || !p_enum.is_empty();
- if (!p_enum.is_empty()) {
+ bool is_enum_type = !p_enum.is_empty();
+ bool can_ref = !p_type.contains("*") || is_enum_type;
+
+ String t = p_type;
+ if (is_enum_type) {
if (p_enum.get_slice_count(".") > 1) {
t = p_enum.get_slice(".", 1);
} else {
@@ -219,21 +230,24 @@ void EditorHelp::_add_type(const String &p_type, const String &p_enum) {
if (t.ends_with("[]")) {
add_array = true;
t = t.replace("[]", "");
+
+ class_desc->push_meta("#Array"); //class
+ class_desc->add_text("Array");
+ class_desc->pop();
+ class_desc->add_text("[");
}
- if (p_enum.is_empty()) {
- class_desc->push_meta("#" + t); //class
- } else {
+
+ if (is_enum_type) {
class_desc->push_meta("$" + p_enum); //class
+ } else {
+ class_desc->push_meta("#" + t); //class
}
}
class_desc->add_text(t);
if (can_ref) {
- class_desc->pop();
+ class_desc->pop(); // Pushed meta above.
if (add_array) {
- class_desc->add_text(" ");
- class_desc->push_meta("#Array"); //class
- class_desc->add_text("[]");
- class_desc->pop();
+ class_desc->add_text("]");
}
}
class_desc->pop();
@@ -432,7 +446,7 @@ Error EditorHelp::_goto_desc(const String &p_class, int p_vscr) {
return OK;
}
-void EditorHelp::_update_method_list(const Vector<DocData::MethodDoc> p_methods, bool &r_method_descrpitons) {
+void EditorHelp::_update_method_list(const Vector<DocData::MethodDoc> p_methods) {
Ref<Font> font = get_theme_font(SNAME("doc_source"), SNAME("EditorFonts"));
class_desc->pop(); // title font size
class_desc->pop(); // title font
@@ -482,10 +496,6 @@ void EditorHelp::_update_method_list(const Vector<DocData::MethodDoc> p_methods,
class_desc->pop(); //cell
}
- if (!m[i].description.strip_edges().is_empty() || m[i].errors_returned.size() > 0) {
- r_method_descrpitons = true;
- }
-
_add_method(m[i], true);
}
@@ -703,11 +713,15 @@ void EditorHelp::_update_doc() {
class_desc->add_newline();
}
+ bool has_description = false;
+
class_desc->add_newline();
class_desc->add_newline();
// Brief description
if (!cd.brief_description.strip_edges().is_empty()) {
+ has_description = true;
+
class_desc->push_color(text_color);
class_desc->push_font(doc_bold_font);
class_desc->push_indent(1);
@@ -722,6 +736,8 @@ void EditorHelp::_update_doc() {
// Class description
if (!cd.description.strip_edges().is_empty()) {
+ has_description = true;
+
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);
@@ -746,6 +762,22 @@ void EditorHelp::_update_doc() {
class_desc->add_newline();
}
+ if (!has_description) {
+ 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 class."));
+ } else {
+ class_desc->append_text(TTR("There is currently no description for this class. 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->add_newline();
+ class_desc->add_newline();
+ }
+
// Online tutorials
if (cd.tutorials.size()) {
class_desc->push_color(title_color);
@@ -782,7 +814,6 @@ void EditorHelp::_update_doc() {
// Properties overview
HashSet<String> skip_methods;
- bool property_descr = false;
bool has_properties = cd.properties.size() != 0;
if (cd.is_script_doc) {
@@ -860,7 +891,6 @@ void EditorHelp::_update_doc() {
if (describe) {
class_desc->pop();
- property_descr = true;
}
class_desc->pop();
@@ -945,9 +975,6 @@ void EditorHelp::_update_doc() {
}
// Methods overview
- bool constructor_descriptions = false;
- bool method_descriptions = false;
- bool operator_descriptions = false;
bool sort_methods = EDITOR_GET("text_editor/help/sort_functions_alphabetically");
Vector<DocData::MethodDoc> methods;
@@ -975,19 +1002,20 @@ void EditorHelp::_update_doc() {
class_desc->push_font(doc_title_font);
class_desc->push_font_size(doc_title_font_size);
class_desc->add_text(TTR("Constructors"));
- _update_method_list(cd.constructors, constructor_descriptions);
+ _update_method_list(cd.constructors);
}
if (!methods.is_empty()) {
if (sort_methods) {
methods.sort();
}
+
section_line.push_back(Pair<String, int>(TTR("Methods"), 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("Methods"));
- _update_method_list(methods, method_descriptions);
+ _update_method_list(methods);
}
if (!cd.operators.is_empty()) {
@@ -1000,7 +1028,7 @@ void EditorHelp::_update_doc() {
class_desc->push_font(doc_title_font);
class_desc->push_font_size(doc_title_font_size);
class_desc->add_text(TTR("Operators"));
- _update_method_list(cd.operators, operator_descriptions);
+ _update_method_list(cd.operators);
}
// Theme properties
@@ -1335,7 +1363,7 @@ void EditorHelp::_update_doc() {
if (constants[i].value.begins_with("Color(") && constants[i].value.ends_with(")")) {
String stripped = constants[i].value.replace(" ", "").replace("Color(", "").replace(")", "");
- Vector<float> color = stripped.split_floats(",");
+ PackedFloat64Array color = stripped.split_floats(",");
if (color.size() >= 3) {
class_desc->push_color(Color(color[0], color[1], color[2]));
_add_bulletpoint();
@@ -1493,7 +1521,7 @@ void EditorHelp::_update_doc() {
}
// Property descriptions
- if (property_descr) {
+ if (has_properties) {
section_line.push_back(Pair<String, int>(TTR("Property Descriptions"), class_desc->get_paragraph_count() - 2));
class_desc->push_color(title_color);
class_desc->push_font(doc_title_font);
@@ -1668,7 +1696,7 @@ void EditorHelp::_update_doc() {
}
// Constructor descriptions
- if (constructor_descriptions) {
+ if (!cd.constructors.is_empty()) {
section_line.push_back(Pair<String, int>(TTR("Constructor Descriptions"), class_desc->get_paragraph_count() - 2));
class_desc->push_color(title_color);
class_desc->push_font(doc_title_font);
@@ -1678,7 +1706,7 @@ void EditorHelp::_update_doc() {
}
// Method descriptions
- if (method_descriptions) {
+ if (!methods.is_empty()) {
section_line.push_back(Pair<String, int>(TTR("Method Descriptions"), class_desc->get_paragraph_count() - 2));
class_desc->push_color(title_color);
class_desc->push_font(doc_title_font);
@@ -1688,7 +1716,7 @@ void EditorHelp::_update_doc() {
}
// Operator descriptions
- if (operator_descriptions) {
+ if (!cd.operators.is_empty()) {
section_line.push_back(Pair<String, int>(TTR("Operator Descriptions"), class_desc->get_paragraph_count() - 2));
class_desc->push_color(title_color);
class_desc->push_font(doc_title_font);
@@ -1696,6 +1724,8 @@ void EditorHelp::_update_doc() {
class_desc->add_text(TTR("Operator Descriptions"));
_update_method_descriptions(cd, cd.operators, "operator");
}
+
+ // Free the scroll.
scroll_locked = false;
}
@@ -1786,9 +1816,19 @@ static void _add_text_to_rt(const String &p_bbcode, RichTextLabel *p_rt, Control
Ref<Font> doc_code_font = p_owner_node->get_theme_font(SNAME("doc_source"), SNAME("EditorFonts"));
Ref<Font> doc_kbd_font = p_owner_node->get_theme_font(SNAME("doc_keyboard"), SNAME("EditorFonts"));
- Color link_color = p_owner_node->get_theme_color(SNAME("link_color"), SNAME("EditorHelp"));
- Color code_color = p_owner_node->get_theme_color(SNAME("code_color"), SNAME("EditorHelp"));
- Color kbd_color = p_owner_node->get_theme_color(SNAME("kbd_color"), SNAME("EditorHelp"));
+ const Color type_color = p_owner_node->get_theme_color(SNAME("type_color"), SNAME("EditorHelp"));
+ const Color code_color = p_owner_node->get_theme_color(SNAME("code_color"), SNAME("EditorHelp"));
+ const Color kbd_color = p_owner_node->get_theme_color(SNAME("kbd_color"), SNAME("EditorHelp"));
+ const Color code_dark_color = Color(code_color, 0.8);
+
+ const Color link_color = p_owner_node->get_theme_color(SNAME("link_color"), SNAME("EditorHelp"));
+ const Color link_method_color = p_owner_node->get_theme_color(SNAME("accent_color"), SNAME("Editor"));
+ const Color link_property_color = link_color.lerp(p_owner_node->get_theme_color(SNAME("accent_color"), SNAME("Editor")), 0.25);
+ const Color link_annotation_color = link_color.lerp(p_owner_node->get_theme_color(SNAME("accent_color"), SNAME("Editor")), 0.5);
+
+ const Color code_bg_color = p_owner_node->get_theme_color(SNAME("code_bg_color"), SNAME("EditorHelp"));
+ const Color kbd_bg_color = p_owner_node->get_theme_color(SNAME("kbd_bg_color"), SNAME("EditorHelp"));
+ const Color param_bg_color = p_owner_node->get_theme_color(SNAME("param_bg_color"), SNAME("EditorHelp"));
String bbcode = p_bbcode.dedent().replace("\t", "").replace("\r", "").strip_edges();
@@ -1921,14 +1961,21 @@ static void _add_text_to_rt(const String &p_bbcode, RichTextLabel *p_rt, Control
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
+ // Use monospace font 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));
+
+ Color target_color = link_color;
+ if (link_tag == "method") {
+ target_color = link_method_color;
+ } else if (link_tag == "member" || link_tag == "signal" || link_tag == "theme property") {
+ target_color = link_property_color;
+ } else if (link_tag == "annotation") {
+ target_color = link_annotation_color;
+ }
+ p_rt->push_color(target_color);
p_rt->push_meta("@" + link_tag + " " + link_target);
- p_rt->add_text(link_target + (tag.begins_with("method ") ? "()" : ""));
- p_rt->pop();
+ p_rt->add_text(link_target + (link_tag == "method" ? "()" : ""));
p_rt->pop();
p_rt->pop();
p_rt->pop();
@@ -1940,7 +1987,7 @@ static void _add_text_to_rt(const String &p_bbcode, RichTextLabel *p_rt, Control
// 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_bgcolor(param_bg_color);
p_rt->push_color(code_color);
p_rt->add_text(param_name);
p_rt->pop();
@@ -1951,17 +1998,15 @@ static void _add_text_to_rt(const String &p_bbcode, RichTextLabel *p_rt, Control
} 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
+ // Use monospace font 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_color(type_color);
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") {
@@ -1975,30 +2020,30 @@ static void _add_text_to_rt(const String &p_bbcode, RichTextLabel *p_rt, Control
pos = brk_end + 1;
tag_stack.push_front(tag);
} else if (tag == "code") {
- // Use monospace font with translucent background color to make code easier to distinguish from other text.
+ // Use monospace font with darkened 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);
+ p_rt->push_bgcolor(code_bg_color);
+ p_rt->push_color(code_color.lerp(p_owner_node->get_theme_color(SNAME("error_color"), SNAME("Editor")), 0.6));
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 monospace font with darkened 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_row_background_color(code_bg_color, Color(code_bg_color, 0.99));
p_rt->set_cell_padding(Rect2(10 * EDSCALE, 10 * EDSCALE, 10 * EDSCALE, 10 * EDSCALE));
- p_rt->push_color(code_color);
+ p_rt->push_color(code_dark_color);
codeblock_tag = true;
pos = brk_end + 1;
tag_stack.push_front(tag);
} else if (tag == "kbd") {
// 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_bgcolor(kbd_bg_color);
p_rt->push_color(kbd_color);
code_tag = true; // Though not strictly a code tag, logic is similar.
pos = brk_end + 1;
@@ -2390,10 +2435,10 @@ void FindBar::_notification(int p_what) {
case NOTIFICATION_THEME_CHANGED: {
find_prev->set_icon(get_theme_icon(SNAME("MoveUp"), SNAME("EditorIcons")));
find_next->set_icon(get_theme_icon(SNAME("MoveDown"), SNAME("EditorIcons")));
- hide_button->set_normal_texture(get_theme_icon(SNAME("Close"), SNAME("EditorIcons")));
- hide_button->set_hover_texture(get_theme_icon(SNAME("Close"), SNAME("EditorIcons")));
- hide_button->set_pressed_texture(get_theme_icon(SNAME("Close"), SNAME("EditorIcons")));
- hide_button->set_custom_minimum_size(hide_button->get_normal_texture()->get_size());
+ hide_button->set_texture_normal(get_theme_icon(SNAME("Close"), SNAME("EditorIcons")));
+ hide_button->set_texture_hover(get_theme_icon(SNAME("Close"), SNAME("EditorIcons")));
+ hide_button->set_texture_pressed(get_theme_icon(SNAME("Close"), SNAME("EditorIcons")));
+ hide_button->set_custom_minimum_size(hide_button->get_texture_normal()->get_size());
matches_label->add_theme_color_override("font_color", results_count > 0 ? get_theme_color(SNAME("font_color"), SNAME("Label")) : get_theme_color(SNAME("error_color"), SNAME("Editor")));
} break;
diff --git a/editor/editor_help.h b/editor/editor_help.h
index c9c1afb51b..15bfdc7c91 100644
--- a/editor/editor_help.h
+++ b/editor/editor_help.h
@@ -167,7 +167,7 @@ class EditorHelp : public VBoxContainer {
Error _goto_desc(const String &p_class, int p_vscr = -1);
//void _update_history_buttons();
- void _update_method_list(const Vector<DocData::MethodDoc> p_methods, bool &r_method_descrpitons);
+ void _update_method_list(const Vector<DocData::MethodDoc> p_methods);
void _update_method_descriptions(const DocData::ClassDoc p_classdoc, const Vector<DocData::MethodDoc> p_methods, const String &p_method_type);
void _update_doc();
diff --git a/editor/editor_help_search.cpp b/editor/editor_help_search.cpp
index 286dcf4b8e..b48fbb805a 100644
--- a/editor/editor_help_search.cpp
+++ b/editor/editor_help_search.cpp
@@ -443,6 +443,10 @@ bool EditorHelpSearch::Runner::_phase_member_items_init() {
}
bool EditorHelpSearch::Runner::_phase_member_items() {
+ if (!iterator_match) {
+ return true;
+ }
+
ClassMatch &match = iterator_match->value;
if (!match.doc || match.doc->name.is_empty()) {
diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp
index 6e18bde303..88a1bbb4a9 100644
--- a/editor/editor_inspector.cpp
+++ b/editor/editor_inspector.cpp
@@ -30,9 +30,7 @@
#include "editor_inspector.h"
-#include "array_property_edit.h"
#include "core/os/keyboard.h"
-#include "dictionary_property_edit.h"
#include "editor/doc_tools.h"
#include "editor/editor_feature_profile.h"
#include "editor/editor_node.h"
@@ -40,9 +38,11 @@
#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_undo_redo_manager.h"
+#include "editor/inspector_dock.h"
#include "editor/plugins/script_editor_plugin.h"
#include "multi_node_edit.h"
-#include "scene/gui/center_container.h"
+#include "scene/gui/spin_box.h"
+#include "scene/gui/texture_rect.h"
#include "scene/property_utils.h"
#include "scene/resources/packed_scene.h"
@@ -660,6 +660,7 @@ void EditorProperty::gui_input(const Ref<InputEvent> &p_event) {
}
if (keying_rect.has_point(mpos)) {
+ accept_event();
emit_signal(SNAME("property_keyed"), property, use_keying_next());
if (use_keying_next()) {
@@ -683,10 +684,12 @@ void EditorProperty::gui_input(const Ref<InputEvent> &p_event) {
}
}
if (delete_rect.has_point(mpos)) {
+ accept_event();
emit_signal(SNAME("property_deleted"), property);
}
if (revert_rect.has_point(mpos)) {
+ accept_event();
bool is_valid_revert = false;
Variant revert_value = EditorPropertyRevert::get_property_revert_value(object, property, &is_valid_revert);
ERR_FAIL_COND(!is_valid_revert);
@@ -695,11 +698,13 @@ void EditorProperty::gui_input(const Ref<InputEvent> &p_event) {
}
if (check_rect.has_point(mpos)) {
+ accept_event();
checked = !checked;
queue_redraw();
emit_signal(SNAME("property_checked"), property, checked);
}
} else if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MouseButton::RIGHT) {
+ accept_event();
_update_popup();
menu->set_position(get_screen_position() + get_local_mouse_position());
menu->reset_size();
@@ -1167,6 +1172,36 @@ void EditorInspectorSection::_test_unfold() {
}
}
+Ref<Texture2D> EditorInspectorSection::_get_arrow() {
+ Ref<Texture2D> arrow;
+ if (foldable) {
+ if (object->editor_is_section_unfolded(section)) {
+ arrow = get_theme_icon(SNAME("arrow"), SNAME("Tree"));
+ } else {
+ if (is_layout_rtl()) {
+ arrow = get_theme_icon(SNAME("arrow_collapsed_mirrored"), SNAME("Tree"));
+ } else {
+ arrow = get_theme_icon(SNAME("arrow_collapsed"), SNAME("Tree"));
+ }
+ }
+ }
+ return arrow;
+}
+
+int EditorInspectorSection::_get_header_height() {
+ Ref<Font> font = get_theme_font(SNAME("bold"), SNAME("EditorFonts"));
+ int font_size = get_theme_font_size(SNAME("bold_size"), SNAME("EditorFonts"));
+
+ int header_height = font->get_height(font_size);
+ Ref<Texture2D> arrow = _get_arrow();
+ if (arrow.is_valid()) {
+ header_height = MAX(header_height, arrow->get_height());
+ }
+ header_height += get_theme_constant(SNAME("v_separation"), SNAME("Tree"));
+
+ return header_height;
+}
+
void EditorInspectorSection::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_THEME_CHANGED: {
@@ -1177,30 +1212,6 @@ void EditorInspectorSection::_notification(int p_what) {
if (!vbox_added) {
return;
}
- // 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"));
-
- // Get the right direction arrow texture, if the section is foldable.
- Ref<Texture2D> arrow;
- if (foldable) {
- if (object->editor_is_section_unfolded(section)) {
- arrow = get_theme_icon(SNAME("arrow"), SNAME("Tree"));
- } else {
- if (is_layout_rtl()) {
- arrow = get_theme_icon(SNAME("arrow_collapsed_mirrored"), SNAME("Tree"));
- } else {
- arrow = get_theme_icon(SNAME("arrow_collapsed"), SNAME("Tree"));
- }
- }
- }
-
- // Compute the height of the section header.
- int header_height = font->get_height(font_size);
- if (arrow.is_valid()) {
- header_height = MAX(header_height, arrow->get_height());
- }
- header_height += get_theme_constant(SNAME("v_separation"), SNAME("Tree"));
int inspector_margin = get_theme_constant(SNAME("inspector_margin"), SNAME("Editor"));
int section_indent_size = get_theme_constant(SNAME("indent_size"), SNAME("EditorInspectorSection"));
@@ -1213,6 +1224,7 @@ void EditorInspectorSection::_notification(int p_what) {
}
Size2 size = get_size() - Vector2(inspector_margin, 0);
+ int header_height = _get_header_height();
Vector2 offset = Vector2(is_layout_rtl() ? 0 : inspector_margin, header_height);
for (int i = 0; i < get_child_count(); i++) {
Control *c = Object::cast_to<Control>(get_child(i));
@@ -1228,36 +1240,6 @@ void EditorInspectorSection::_notification(int p_what) {
} break;
case NOTIFICATION_DRAW: {
- // 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"));
- } else {
- arrow = get_theme_icon(SNAME("arrow_collapsed"), SNAME("Tree"));
- }
- }
- }
-
- bool rtl = is_layout_rtl();
-
- // Compute the height and width of the section header.
- int header_height = font->get_height(font_size);
- if (arrow.is_valid()) {
- header_height = MAX(header_height, arrow->get_height());
- }
- header_height += get_theme_constant(SNAME("v_separation"), SNAME("Tree"));
-
int section_indent = 0;
int section_indent_size = get_theme_constant(SNAME("indent_size"), SNAME("EditorInspectorSection"));
if (indent_depth > 0 && section_indent_size > 0) {
@@ -1270,11 +1252,13 @@ void EditorInspectorSection::_notification(int p_what) {
int header_width = get_size().width - section_indent;
int header_offset_x = 0.0;
+ bool rtl = is_layout_rtl();
if (!rtl) {
header_offset_x += section_indent;
}
// Draw header area.
+ int header_height = _get_header_height();
Rect2 header_rect = Rect2(Vector2(header_offset_x, 0.0), Vector2(header_width, header_height));
Color c = bg_color;
c.a *= 0.4;
@@ -1283,7 +1267,7 @@ void EditorInspectorSection::_notification(int p_what) {
}
draw_rect(header_rect, c);
- // Draw header title, folding arrow and coutn of revertable properties.
+ // Draw header title, folding arrow and count of revertable properties.
{
int separation = Math::round(2 * EDSCALE);
@@ -1291,6 +1275,7 @@ void EditorInspectorSection::_notification(int p_what) {
int margin_end = separation;
// - Arrow.
+ Ref<Texture2D> arrow = _get_arrow();
if (arrow.is_valid()) {
Point2 arrow_position;
if (rtl) {
@@ -1308,6 +1293,13 @@ void EditorInspectorSection::_notification(int p_what) {
// - Count of revertable properties.
String num_revertable_str;
int num_revertable_width = 0;
+
+ bool folded = foldable && !object->editor_is_section_unfolded(section);
+
+ 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"));
+
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;
@@ -1476,12 +1468,16 @@ void EditorInspectorSection::gui_input(const Ref<InputEvent> &p_event) {
Ref<InputEventMouseButton> mb = p_event;
if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MouseButton::LEFT) {
- Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Tree"));
- int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Tree"));
- if (mb->get_position().y > font->get_height(font_size)) { //clicked outside
- return;
+ if (object->editor_is_section_unfolded(section)) {
+ int header_height = _get_header_height();
+
+ if (mb->get_position().y >= header_height) {
+ return;
+ }
}
+ accept_event();
+
bool should_unfold = !object->editor_is_section_unfolded(section);
if (should_unfold) {
unfold();
@@ -1680,6 +1676,7 @@ void EditorInspectorArray::_panel_gui_input(Ref<InputEvent> p_event, int p_index
Ref<InputEventMouseButton> mb = p_event;
if (mb.is_valid()) {
if (movable && mb->get_button_index() == MouseButton::RIGHT) {
+ array_elements[p_index].panel->accept_event();
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);
@@ -2589,7 +2586,7 @@ bool EditorInspector::_is_property_disabled_by_feature_profile(const StringName
return false;
}
-void EditorInspector::update_tree() {
+void EditorInspector::_update_tree() {
//to update properly if all is refreshed
StringName current_selected = property_selected;
int current_focusable = -1;
@@ -3114,11 +3111,24 @@ void EditorInspector::update_tree() {
// Build the doc hint, to use as tooltip.
// Get the class name.
- StringName classname = doc_name == "" ? object->get_class_name() : doc_name;
+ StringName classname = doc_name;
if (!object_class.is_empty()) {
classname = object_class;
} else if (Object::cast_to<MultiNodeEdit>(object)) {
classname = Object::cast_to<MultiNodeEdit>(object)->get_edited_class_name();
+ } else if (classname == "") {
+ classname = object->get_class_name();
+ Resource *res = Object::cast_to<Resource>(object);
+ if (res && !res->get_script().is_null()) {
+ // Grab the script of this resource to get the evaluated script class.
+ Ref<Script> scr = res->get_script();
+ if (scr.is_valid()) {
+ Vector<DocData::ClassDoc> docs = scr->get_documentation();
+ if (!docs.is_empty()) {
+ classname = docs[0].name;
+ }
+ }
+ }
}
StringName propname = property_prefix + p.name;
@@ -3295,6 +3305,10 @@ void EditorInspector::update_tree() {
}
}
+void EditorInspector::update_tree() {
+ update_tree_pending = true;
+}
+
void EditorInspector::update_property(const String &p_prop) {
if (!editor_property_map.has(p_prop)) {
return;
@@ -3889,10 +3903,9 @@ void EditorInspector::_notification(int p_what) {
changing++;
if (update_tree_pending) {
- update_tree();
update_tree_pending = false;
pending.clear();
-
+ _update_tree();
} else {
while (pending.size()) {
StringName prop = *pending.begin();
diff --git a/editor/editor_inspector.h b/editor/editor_inspector.h
index 1b93b19845..53490f0880 100644
--- a/editor/editor_inspector.h
+++ b/editor/editor_inspector.h
@@ -33,14 +33,17 @@
#include "editor_property_name_processor.h"
#include "scene/gui/box_container.h"
-#include "scene/gui/button.h"
-#include "scene/gui/dialogs.h"
-#include "scene/gui/line_edit.h"
-#include "scene/gui/option_button.h"
-#include "scene/gui/panel_container.h"
#include "scene/gui/scroll_container.h"
-#include "scene/gui/spin_box.h"
-#include "scene/gui/texture_rect.h"
+
+class AcceptDialog;
+class Button;
+class ConfirmationDialog;
+class LineEdit;
+class OptionButton;
+class PanelContainer;
+class PopupMenu;
+class SpinBox;
+class TextureRect;
class EditorPropertyRevert {
public:
@@ -277,6 +280,8 @@ class EditorInspectorSection : public Container {
HashSet<StringName> revertable_properties;
void _test_unfold();
+ int _get_header_height();
+ Ref<Texture2D> _get_arrow();
protected:
Object *object = nullptr;
@@ -537,6 +542,8 @@ class EditorInspector : public ScrollContainer {
void _show_add_meta_dialog();
void _check_meta_name(const String &p_name);
+ void _update_tree();
+
protected:
static void _bind_methods();
void _notification(int p_what);
diff --git a/editor/editor_layouts_dialog.cpp b/editor/editor_layouts_dialog.cpp
index 886e29a504..19b137c7fd 100644
--- a/editor/editor_layouts_dialog.cpp
+++ b/editor/editor_layouts_dialog.cpp
@@ -33,6 +33,7 @@
#include "core/io/config_file.h"
#include "core/object/class_db.h"
#include "core/os/keyboard.h"
+#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "scene/gui/item_list.h"
#include "scene/gui/line_edit.h"
@@ -97,6 +98,11 @@ void EditorLayoutsDialog::_post_popup() {
for (const String &E : layouts) {
layout_names->add_item(E);
}
+ if (name->is_visible()) {
+ name->grab_focus();
+ } else {
+ layout_names->grab_focus();
+ }
}
EditorLayoutsDialog::EditorLayoutsDialog() {
@@ -106,7 +112,9 @@ EditorLayoutsDialog::EditorLayoutsDialog() {
makevb->set_anchor_and_offset(SIDE_RIGHT, Control::ANCHOR_END, -5);
layout_names = memnew(ItemList);
- makevb->add_child(layout_names);
+ layout_names->set_auto_height(true);
+ makevb->add_margin_child(TTR("Select existing layout:"), layout_names);
+ layout_names->set_custom_minimum_size(Size2(300 * EDSCALE, 1));
layout_names->set_visible(true);
layout_names->set_offset(SIDE_TOP, 5);
layout_names->set_anchor_and_offset(SIDE_LEFT, Control::ANCHOR_BEGIN, 5);
@@ -116,8 +124,10 @@ EditorLayoutsDialog::EditorLayoutsDialog() {
layout_names->set_allow_rmb_select(true);
name = memnew(LineEdit);
+ name->set_placeholder("Or enter new layout name");
makevb->add_child(name);
name->set_offset(SIDE_TOP, 5);
+ name->set_custom_minimum_size(Size2(300 * EDSCALE, 1));
name->set_anchor_and_offset(SIDE_LEFT, Control::ANCHOR_BEGIN, 5);
name->set_anchor_and_offset(SIDE_RIGHT, Control::ANCHOR_END, -5);
name->connect("gui_input", callable_mp(this, &EditorLayoutsDialog::_line_gui_input));
diff --git a/editor/editor_log.cpp b/editor/editor_log.cpp
index 84284a7f31..a232c83783 100644
--- a/editor/editor_log.cpp
+++ b/editor/editor_log.cpp
@@ -286,7 +286,7 @@ void EditorLog::_add_log_line(LogMessage &p_message, bool p_replace_previous) {
// Remove last line if replacing, as it will be replace by the next added line.
// Why "- 2"? RichTextLabel is weird. When you add a line with add_newline(), it also adds an element to the list of lines which is null/blank,
// but it still counts as a line. So if you remove the last line (count - 1) you are actually removing nothing...
- log->remove_line(log->get_paragraph_count() - 2);
+ log->remove_paragraph(log->get_paragraph_count() - 2);
}
switch (p_message.type) {
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index 1bca1b3c87..01e605880c 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -37,7 +37,6 @@
#include "core/io/image_loader.h"
#include "core/io/resource_loader.h"
#include "core/io/resource_saver.h"
-#include "core/io/stream_peer_tls.h"
#include "core/object/class_db.h"
#include "core/object/message_queue.h"
#include "core/os/keyboard.h"
@@ -47,10 +46,7 @@
#include "core/string/translation.h"
#include "core/version.h"
#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"
#include "scene/gui/link_button.h"
@@ -61,18 +57,13 @@
#include "scene/gui/split_container.h"
#include "scene/gui/tab_bar.h"
#include "scene/gui/tab_container.h"
-#include "scene/gui/texture_progress_bar.h"
#include "scene/main/window.h"
#include "scene/resources/packed_scene.h"
#include "servers/display_server.h"
-#include "servers/navigation_server_2d.h"
#include "servers/navigation_server_3d.h"
#include "servers/physics_server_2d.h"
-#include "servers/rendering/rendering_device.h"
-#include "editor/animation_track_editor.h"
#include "editor/audio_stream_preview.h"
-#include "editor/debugger/debug_adapter/debug_adapter_server.h"
#include "editor/debugger/editor_debugger_node.h"
#include "editor/dependency_editor.h"
#include "editor/editor_about.h"
@@ -82,7 +73,6 @@
#include "editor/editor_data.h"
#include "editor/editor_feature_profile.h"
#include "editor/editor_file_dialog.h"
-#include "editor/editor_file_system.h"
#include "editor/editor_folding.h"
#include "editor/editor_help.h"
#include "editor/editor_inspector.h"
@@ -93,15 +83,12 @@
#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"
#include "editor/editor_run_native.h"
-#include "editor/editor_run_script.h"
#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_settings_dialog.h"
-#include "editor/editor_spin_slider.h"
#include "editor/editor_themes.h"
#include "editor/editor_toaster.h"
#include "editor/editor_translation_parser.h"
@@ -109,6 +96,7 @@
#include "editor/export/editor_export.h"
#include "editor/export/export_template_manager.h"
#include "editor/export/project_export.h"
+#include "editor/fbx_importer_manager.h"
#include "editor/filesystem_dock.h"
#include "editor/history_dock.h"
#include "editor/import/audio_stream_import_settings.h"
@@ -122,88 +110,32 @@
#include "editor/import/resource_importer_imagefont.h"
#include "editor/import/resource_importer_layered_texture.h"
#include "editor/import/resource_importer_obj.h"
-#include "editor/import/resource_importer_scene.h"
#include "editor/import/resource_importer_shader_file.h"
#include "editor/import/resource_importer_texture.h"
#include "editor/import/resource_importer_texture_atlas.h"
#include "editor/import/resource_importer_wav.h"
#include "editor/import/scene_import_settings.h"
#include "editor/import_dock.h"
+#include "editor/inspector_dock.h"
#include "editor/multi_node_edit.h"
#include "editor/node_dock.h"
#include "editor/plugin_config_dialog.h"
-#include "editor/plugins/animation_blend_space_1d_editor.h"
-#include "editor/plugins/animation_blend_space_2d_editor.h"
-#include "editor/plugins/animation_blend_tree_editor_plugin.h"
#include "editor/plugins/animation_player_editor_plugin.h"
-#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_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"
-#include "editor/plugins/cpu_particles_2d_editor_plugin.h"
-#include "editor/plugins/cpu_particles_3d_editor_plugin.h"
-#include "editor/plugins/curve_editor_plugin.h"
#include "editor/plugins/debugger_editor_plugin.h"
-#include "editor/plugins/editor_debugger_plugin.h"
#include "editor/plugins/editor_preview_plugins.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"
-#include "editor/plugins/gpu_particles_collision_sdf_editor_plugin.h"
-#include "editor/plugins/gradient_editor_plugin.h"
-#include "editor/plugins/gradient_texture_2d_editor_plugin.h"
-#include "editor/plugins/input_event_editor_plugin.h"
-#include "editor/plugins/light_occluder_2d_editor_plugin.h"
-#include "editor/plugins/lightmap_gi_editor_plugin.h"
-#include "editor/plugins/line_2d_editor_plugin.h"
#include "editor/plugins/material_editor_plugin.h"
-#include "editor/plugins/mesh_editor_plugin.h"
-#include "editor/plugins/mesh_instance_3d_editor_plugin.h"
#include "editor/plugins/mesh_library_editor_plugin.h"
-#include "editor/plugins/multimesh_editor_plugin.h"
-#include "editor/plugins/navigation_link_2d_editor_plugin.h"
-#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/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/resource_preloader_editor_plugin.h"
#include "editor/plugins/root_motion_editor_plugin.h"
-#include "editor/plugins/script_editor_plugin.h"
#include "editor/plugins/script_text_editor.h"
-#include "editor/plugins/shader_editor_plugin.h"
-#include "editor/plugins/shader_file_editor_plugin.h"
-#include "editor/plugins/skeleton_2d_editor_plugin.h"
-#include "editor/plugins/skeleton_3d_editor_plugin.h"
-#include "editor/plugins/skeleton_ik_3d_editor_plugin.h"
-#include "editor/plugins/sprite_2d_editor_plugin.h"
-#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_editor.h"
-#include "editor/plugins/texture_3d_editor_plugin.h"
-#include "editor/plugins/texture_editor_plugin.h"
-#include "editor/plugins/texture_layered_editor_plugin.h"
-#include "editor/plugins/texture_region_editor_plugin.h"
-#include "editor/plugins/theme_editor_plugin.h"
-#include "editor/plugins/tiles/tiles_editor_plugin.h"
#include "editor/plugins/version_control_editor_plugin.h"
#include "editor/plugins/visual_shader_editor_plugin.h"
-#include "editor/plugins/voxel_gi_editor_plugin.h"
#include "editor/progress_dialog.h"
#include "editor/project_settings_editor.h"
#include "editor/register_exporters.h"
@@ -506,8 +438,6 @@ void EditorNode::_update_from_settings() {
bool glow_bicubic = int(GLOBAL_GET("rendering/environment/glow/upscale_mode")) > 0;
RS::get_singleton()->environment_set_ssil_quality(RS::EnvironmentSSILQuality(int(GLOBAL_GET("rendering/environment/ssil/quality"))), GLOBAL_GET("rendering/environment/ssil/half_size"), GLOBAL_GET("rendering/environment/ssil/adaptive_target"), GLOBAL_GET("rendering/environment/ssil/blur_passes"), GLOBAL_GET("rendering/environment/ssil/fadeout_from"), GLOBAL_GET("rendering/environment/ssil/fadeout_to"));
RS::get_singleton()->environment_glow_set_use_bicubic_upscale(glow_bicubic);
- bool glow_high_quality = GLOBAL_GET("rendering/environment/glow/use_high_quality");
- RS::get_singleton()->environment_glow_set_use_high_quality(glow_high_quality);
RS::EnvironmentSSRRoughnessQuality ssr_roughness_quality = RS::EnvironmentSSRRoughnessQuality(int(GLOBAL_GET("rendering/environment/screen_space_reflection/roughness_quality")));
RS::get_singleton()->environment_set_ssr_roughness_quality(ssr_roughness_quality);
RS::SubSurfaceScatteringQuality sss_quality = RS::SubSurfaceScatteringQuality(int(GLOBAL_GET("rendering/environment/subsurface_scattering/subsurface_scattering_quality")));
@@ -1263,6 +1193,10 @@ void EditorNode::edit_node(Node *p_node) {
push_item(p_node);
}
+void EditorNode::edit_resource(const Ref<Resource> &p_resource) {
+ InspectorDock::get_singleton()->edit_resource(p_resource);
+}
+
void EditorNode::save_resource_in_path(const Ref<Resource> &p_resource, const String &p_path) {
editor_data.apply_changes_in_editors();
int flg = 0;
@@ -1763,7 +1697,7 @@ void EditorNode::_save_scene(String p_file, int idx) {
}
if (!scene->get_scene_file_path().is_empty() && _validate_scene_recursive(scene->get_scene_file_path(), scene)) {
- show_accept(TTR("This scene can't be saved because there is a cyclic instancing inclusion.\nPlease resolve it and then attempt to save again."), TTR("OK"));
+ show_accept(TTR("This scene can't be saved because there is a cyclic instance inclusion.\nPlease resolve it and then attempt to save again."), TTR("OK"));
return;
}
@@ -2331,7 +2265,7 @@ void EditorNode::_edit_current(bool p_skip_foreign) {
if (get_edited_scene() && !get_edited_scene()->get_scene_file_path().is_empty()) {
String source_scene = get_edited_scene()->get_scene_file_path();
if (FileAccess::exists(source_scene + ".import")) {
- editable_info = TTR("This scene was imported, so changes to it won't be kept.\nInstancing it or inheriting will allow making changes to it.\nPlease read the documentation relevant to importing scenes to better understand this workflow.");
+ editable_info = TTR("This scene was imported, so changes to it won't be kept.\nInstantiating or inheriting it will allow you to make changes to it.\nPlease read the documentation relevant to importing scenes to better understand this workflow.");
info_is_warning = true;
}
}
@@ -2339,7 +2273,9 @@ void EditorNode::_edit_current(bool p_skip_foreign) {
} else {
Node *selected_node = nullptr;
- if (current_obj->is_class("MultiNodeEdit")) {
+ if (current_obj->is_class("EditorDebuggerRemoteObject")) {
+ disable_folding = true;
+ } else if (current_obj->is_class("MultiNodeEdit")) {
Node *scene = get_edited_scene();
if (scene) {
MultiNodeEdit *multi_node_edit = Object::cast_to<MultiNodeEdit>(current_obj);
@@ -2819,11 +2755,20 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
log->add_message(TTR("Can't undo while mouse buttons are pressed."), EditorLog::MSG_TYPE_EDITOR);
} else {
String action = editor_data.get_undo_redo()->get_current_action_name();
-
+ int id = editor_data.get_undo_redo()->get_current_action_history_id();
if (!editor_data.get_undo_redo()->undo()) {
log->add_message(TTR("Nothing to undo."), EditorLog::MSG_TYPE_EDITOR);
} else if (!action.is_empty()) {
- log->add_message(vformat(TTR("Undo: %s"), action), EditorLog::MSG_TYPE_EDITOR);
+ switch (id) {
+ case EditorUndoRedoManager::GLOBAL_HISTORY:
+ log->add_message(vformat(TTR("Global Undo: %s"), action), EditorLog::MSG_TYPE_EDITOR);
+ break;
+ case EditorUndoRedoManager::REMOTE_HISTORY:
+ log->add_message(vformat(TTR("Remote Undo: %s"), action), EditorLog::MSG_TYPE_EDITOR);
+ break;
+ default:
+ log->add_message(vformat(TTR("Scene Undo: %s"), action), EditorLog::MSG_TYPE_EDITOR);
+ }
}
}
} break;
@@ -2835,7 +2780,20 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
log->add_message(TTR("Nothing to redo."), EditorLog::MSG_TYPE_EDITOR);
} else {
String action = editor_data.get_undo_redo()->get_current_action_name();
- log->add_message(vformat(TTR("Redo: %s"), action), EditorLog::MSG_TYPE_EDITOR);
+ if (action.is_empty()) {
+ break;
+ }
+
+ switch (editor_data.get_undo_redo()->get_current_action_history_id()) {
+ case EditorUndoRedoManager::GLOBAL_HISTORY:
+ log->add_message(vformat(TTR("Global Redo: %s"), action), EditorLog::MSG_TYPE_EDITOR);
+ break;
+ case EditorUndoRedoManager::REMOTE_HISTORY:
+ log->add_message(vformat(TTR("Remote Redo: %s"), action), EditorLog::MSG_TYPE_EDITOR);
+ break;
+ default:
+ log->add_message(vformat(TTR("Scene Redo: %s"), action), EditorLog::MSG_TYPE_EDITOR);
+ }
}
}
} break;
@@ -3024,7 +2982,11 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
} break;
case SETTINGS_MANAGE_EXPORT_TEMPLATES: {
export_template_manager->popup_manager();
-
+ } break;
+ case SETTINGS_MANAGE_FBX_IMPORTER: {
+#if !defined(ANDROID_ENABLED) && !defined(WEB_ENABLED)
+ fbx_importer_manager->show_dialog();
+#endif
} break;
case SETTINGS_INSTALL_ANDROID_BUILD_TEMPLATE: {
custom_build_manage_templates->hide();
@@ -3421,7 +3383,9 @@ void EditorNode::add_editor_plugin(EditorPlugin *p_editor, bool p_config_changed
void EditorNode::remove_editor_plugin(EditorPlugin *p_editor, bool p_config_changed) {
if (p_editor->has_main_screen()) {
- for (int i = 0; i < singleton->main_editor_buttons.size(); i++) {
+ // Remove the main editor button and update the bindings of
+ // all buttons behind it to point to the correct main window.
+ for (int i = singleton->main_editor_buttons.size() - 1; i >= 0; i--) {
if (p_editor->get_name() == singleton->main_editor_buttons[i]->get_text()) {
if (singleton->main_editor_buttons[i]->is_pressed()) {
singleton->editor_select(EDITOR_SCRIPT);
@@ -3431,6 +3395,9 @@ void EditorNode::remove_editor_plugin(EditorPlugin *p_editor, bool p_config_chan
singleton->main_editor_buttons.remove_at(i);
break;
+ } else {
+ singleton->main_editor_buttons[i]->disconnect("pressed", callable_mp(singleton, &EditorNode::editor_select));
+ singleton->main_editor_buttons[i]->connect("pressed", callable_mp(singleton, &EditorNode::editor_select).bind(i - 1));
}
}
@@ -3992,7 +3959,7 @@ bool EditorNode::is_resource_read_only(Ref<Resource> p_resource, bool p_foreign_
return false;
}
-void EditorNode::request_instance_scene(const String &p_path) {
+void EditorNode::request_instantiate_scene(const String &p_path) {
SceneTreeDock::get_singleton()->instantiate(p_path);
}
@@ -4128,62 +4095,6 @@ bool EditorNode::is_scene_in_use(const String &p_path) {
return false;
}
-void EditorNode::register_editor_types() {
- ResourceLoader::set_timestamp_on_load(true);
- ResourceSaver::set_timestamp_on_save(true);
-
- GDREGISTER_CLASS(EditorPaths);
- GDREGISTER_CLASS(EditorPlugin);
- GDREGISTER_CLASS(EditorTranslationParserPlugin);
- GDREGISTER_CLASS(EditorImportPlugin);
- GDREGISTER_CLASS(EditorScript);
- GDREGISTER_CLASS(EditorSelection);
- GDREGISTER_CLASS(EditorFileDialog);
- GDREGISTER_ABSTRACT_CLASS(EditorSettings);
- GDREGISTER_CLASS(EditorNode3DGizmo);
- GDREGISTER_CLASS(EditorNode3DGizmoPlugin);
- GDREGISTER_ABSTRACT_CLASS(EditorResourcePreview);
- GDREGISTER_CLASS(EditorResourcePreviewGenerator);
- GDREGISTER_ABSTRACT_CLASS(EditorFileSystem);
- GDREGISTER_CLASS(EditorFileSystemDirectory);
- GDREGISTER_CLASS(EditorVCSInterface);
- GDREGISTER_ABSTRACT_CLASS(ScriptEditor);
- GDREGISTER_ABSTRACT_CLASS(ScriptEditorBase);
- GDREGISTER_CLASS(EditorSyntaxHighlighter);
- GDREGISTER_ABSTRACT_CLASS(EditorInterface);
- GDREGISTER_CLASS(EditorExportPlugin);
- GDREGISTER_ABSTRACT_CLASS(EditorExportPlatform);
- GDREGISTER_CLASS(EditorResourceConversionPlugin);
- GDREGISTER_CLASS(EditorSceneFormatImporter);
- GDREGISTER_CLASS(EditorScenePostImportPlugin);
- GDREGISTER_CLASS(EditorInspector);
- GDREGISTER_CLASS(EditorInspectorPlugin);
- GDREGISTER_CLASS(EditorProperty);
- GDREGISTER_CLASS(AnimationTrackEditPlugin);
- GDREGISTER_CLASS(ScriptCreateDialog);
- GDREGISTER_CLASS(EditorFeatureProfile);
- GDREGISTER_CLASS(EditorSpinSlider);
- GDREGISTER_CLASS(EditorResourcePicker);
- GDREGISTER_CLASS(EditorScriptPicker);
- GDREGISTER_ABSTRACT_CLASS(EditorUndoRedoManager);
-
- GDREGISTER_ABSTRACT_CLASS(FileSystemDock);
- GDREGISTER_VIRTUAL_CLASS(EditorFileSystemImportFormatSupportQuery);
-
- GDREGISTER_CLASS(EditorScenePostImport);
- GDREGISTER_CLASS(EditorCommandPalette);
- GDREGISTER_CLASS(EditorDebuggerPlugin);
-}
-
-void EditorNode::unregister_editor_types() {
- _init_callbacks.clear();
- if (EditorPaths::get_singleton()) {
- EditorPaths::free();
- }
-
- EditorResourcePicker::clear_caches();
-}
-
void EditorNode::stop_child_process(OS::ProcessID p_pid) {
if (has_child_process(p_pid)) {
editor_run.stop_child_process(p_pid);
@@ -4556,6 +4467,7 @@ void EditorNode::_dock_floating_close_request(Control *p_control) {
dock_slot[window_slot]->add_child(p_control);
dock_slot[window_slot]->move_child(p_control, MIN((int)window->get_meta("dock_index"), dock_slot[window_slot]->get_tab_count()));
dock_slot[window_slot]->set_current_tab(window->get_meta("dock_index"));
+ dock_slot[window_slot]->set_tab_title(dock_slot[window_slot]->get_tab_idx_from_control(p_control), TTRGET(p_control->get_name()));
window->queue_free();
@@ -4579,7 +4491,7 @@ void EditorNode::_dock_make_float() {
dock_slot[dock_popup_selected_idx]->remove_child(dock);
Window *window = memnew(Window);
- window->set_title(dock->get_name());
+ window->set_title(TTRGET(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_FULL_RECT);
@@ -5001,7 +4913,7 @@ void EditorNode::_load_docks_from_config(Ref<ConfigFile> p_layout, const String
Vector<String> names = String(p_layout->get_value(p_section, "dock_" + itos(i + 1))).split(",");
- for (int j = 0; j < names.size(); j++) {
+ for (int j = names.size() - 1; j >= 0; j--) {
String name = names[j];
// FIXME: Find it, in a horribly inefficient way.
int atidx = -1;
@@ -5022,7 +4934,7 @@ void EditorNode::_load_docks_from_config(Ref<ConfigFile> p_layout, const String
}
if (atidx == i) {
- node->move_to_front();
+ dock_slot[i]->move_child(node, 0);
continue;
}
@@ -5032,6 +4944,7 @@ void EditorNode::_load_docks_from_config(Ref<ConfigFile> p_layout, const String
dock_slot[atidx]->hide();
}
dock_slot[i]->add_child(node);
+ dock_slot[i]->move_child(node, 0);
dock_slot[i]->show();
}
}
@@ -5233,6 +5146,10 @@ bool EditorNode::immediate_confirmation_dialog(const String &p_text, const Strin
return singleton->immediate_dialog_confirmed;
}
+void EditorNode::cleanup() {
+ _init_callbacks.clear();
+}
+
int EditorNode::get_current_tab() {
return scene_tabs->get_current_tab();
}
@@ -5277,15 +5194,15 @@ void EditorNode::_layout_menu_option(int p_id) {
current_menu_option = p_id;
layout_dialog->set_title(TTR("Save Layout"));
layout_dialog->set_ok_button_text(TTR("Save"));
- layout_dialog->popup_centered();
layout_dialog->set_name_line_enabled(true);
+ layout_dialog->popup_centered();
} break;
case SETTINGS_LAYOUT_DELETE: {
current_menu_option = p_id;
layout_dialog->set_title(TTR("Delete Layout"));
layout_dialog->set_ok_button_text(TTR("Delete"));
- layout_dialog->popup_centered();
layout_dialog->set_name_line_enabled(false);
+ layout_dialog->popup_centered();
} break;
case SETTINGS_LAYOUT_DEFAULT: {
_load_docks_from_config(default_layout, "docks");
@@ -5761,7 +5678,7 @@ void EditorNode::_global_menu_new_window(const Variant &p_tag) {
}
void EditorNode::_dropped_files(const Vector<String> &p_files) {
- String to_path = ProjectSettings::get_singleton()->globalize_path(FileSystemDock::get_singleton()->get_selected_path());
+ String to_path = ProjectSettings::get_singleton()->globalize_path(FileSystemDock::get_singleton()->get_current_directory());
_add_dropped_files_recursive(p_files, to_path);
@@ -5992,10 +5909,6 @@ void EditorNode::_feature_profile_changed() {
node_tabs->set_tab_hidden(node_tabs->get_tab_idx_from_control(NodeDock::get_singleton()), false);
fs_tabs->set_tab_hidden(fs_tabs->get_tab_idx_from_control(FileSystemDock::get_singleton()), false);
history_tabs->set_tab_hidden(history_tabs->get_tab_idx_from_control(history_dock), false);
- history_dock->set_visible(true);
- ImportDock::get_singleton()->set_visible(true);
- NodeDock::get_singleton()->set_visible(true);
- FileSystemDock::get_singleton()->set_visible(true);
main_editor_buttons[EDITOR_3D]->set_visible(true);
main_editor_buttons[EDITOR_SCRIPT]->set_visible(true);
if (AssetLibraryEditorPlugin::is_available()) {
@@ -6150,14 +6063,7 @@ EditorNode::EditorNode() {
Input *id = Input::get_singleton();
if (id) {
- bool found_touchscreen = false;
- for (int i = 0; i < DisplayServer::get_singleton()->get_screen_count(); i++) {
- if (DisplayServer::get_singleton()->screen_is_touchscreen(i)) {
- found_touchscreen = true;
- }
- }
-
- if (!found_touchscreen && Input::get_singleton()) {
+ if (!DisplayServer::get_singleton()->is_touchscreen_available() && Input::get_singleton()) {
// Only if no touchscreen ui hint, disable emulation just in case.
id->set_emulate_touch_from_mouse(false);
}
@@ -6723,6 +6629,11 @@ EditorNode::EditorNode() {
gui_base->add_child(about);
feature_profile_manager->connect("current_feature_profile_changed", callable_mp(this, &EditorNode::_feature_profile_changed));
+#if !defined(ANDROID_ENABLED) && !defined(WEB_ENABLED)
+ fbx_importer_manager = memnew(FBXImporterManager);
+ gui_base->add_child(fbx_importer_manager);
+#endif
+
warning = memnew(AcceptDialog);
warning->add_button(TTR("Copy Text"), true, "copy");
gui_base->add_child(warning);
@@ -6895,6 +6806,9 @@ EditorNode::EditorNode() {
#ifndef ANDROID_ENABLED
settings_menu->add_item(TTR("Manage Export Templates..."), SETTINGS_MANAGE_EXPORT_TEMPLATES);
#endif
+#if !defined(ANDROID_ENABLED) && !defined(WEB_ENABLED)
+ settings_menu->add_item(TTR("Configure FBX Importer..."), SETTINGS_MANAGE_FBX_IMPORTER);
+#endif
help_menu = memnew(PopupMenu);
help_menu->set_name(TTR("Help"));
@@ -7100,7 +7014,7 @@ EditorNode::EditorNode() {
FileSystemDock *filesystem_dock = memnew(FileSystemDock);
filesystem_dock->connect("inherit", callable_mp(this, &EditorNode::_inherit_request));
- filesystem_dock->connect("instance", callable_mp(this, &EditorNode::_instantiate_request));
+ filesystem_dock->connect("instantiate", 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);
@@ -7150,7 +7064,7 @@ EditorNode::EditorNode() {
// Dock numbers are based on DockSlot enum value + 1.
default_layout->set_value(docks_section, "dock_3", "Scene,Import");
default_layout->set_value(docks_section, "dock_4", "FileSystem");
- default_layout->set_value(docks_section, "dock_5", "Inspector,Node");
+ default_layout->set_value(docks_section, "dock_5", "Inspector,Node,History");
for (int i = 0; i < vsplits.size(); i++) {
default_layout->set_value(docks_section, "dock_split_" + itos(i + 1), 0);
@@ -7323,7 +7237,6 @@ EditorNode::EditorNode() {
add_child(audio_preview_gen);
add_editor_plugin(memnew(DebuggerEditorPlugin(debug_menu)));
- add_editor_plugin(memnew(DebugAdapterServer()));
disk_changed = memnew(ConfirmationDialog);
{
@@ -7349,6 +7262,7 @@ EditorNode::EditorNode() {
gui_base->add_child(disk_changed);
add_editor_plugin(memnew(AnimationPlayerEditorPlugin));
+ add_editor_plugin(memnew(AnimationTrackKeyEditEditorPlugin));
add_editor_plugin(memnew(CanvasItemEditorPlugin));
add_editor_plugin(memnew(Node3DEditorPlugin));
add_editor_plugin(memnew(ScriptEditorPlugin));
@@ -7373,63 +7287,7 @@ EditorNode::EditorNode() {
raise_bottom_panel_item(AnimationPlayerEditor::get_singleton());
add_editor_plugin(VersionControlEditorPlugin::get_singleton());
-
- // 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(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(MeshLibraryEditorPlugin));
- 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(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));
-
- // 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(NavigationLink2DEditorPlugin));
- add_editor_plugin(memnew(NavigationPolygonEditorPlugin));
- 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));
diff --git a/editor/editor_node.h b/editor/editor_node.h
index f27fe429b9..950970379d 100644
--- a/editor/editor_node.h
+++ b/editor/editor_node.h
@@ -32,12 +32,13 @@
#define EDITOR_NODE_H
#include "core/templates/safe_refcount.h"
+#include "editor/editor_data.h"
#include "editor/editor_folding.h"
#include "editor/editor_native_shader_source_visualizer.h"
+#include "editor/editor_plugin.h"
#include "editor/editor_run.h"
#include "editor/editor_title_bar.h"
#include "editor/export/editor_export.h"
-#include "editor/inspector_dock.h"
typedef void (*EditorNodeInitCallback)();
typedef void (*EditorPluginInitializeCallback)();
@@ -46,8 +47,8 @@ typedef bool (*EditorBuildCallback)();
class AcceptDialog;
class AudioStreamPreviewGenerator;
class BackgroundProgress;
-class Button;
class CenterContainer;
+class CheckBox;
class ColorPicker;
class ConfirmationDialog;
class Control;
@@ -59,22 +60,24 @@ class EditorCommandPalette;
class EditorExport;
class EditorExtensionManager;
class EditorFeatureProfileManager;
+class EditorFileDialog;
class EditorFileServer;
class EditorFolding;
class EditorInspector;
class EditorLayoutsDialog;
class EditorLog;
-class EditorPlugin;
class EditorPluginList;
class EditorQuickOpen;
class EditorResourcePreview;
class EditorResourceConversionPlugin;
class EditorRun;
class EditorRunNative;
+class EditorSelectionHistory;
class EditorSettingsDialog;
class EditorToaster;
class EditorUndoRedoManager;
class ExportTemplateManager;
+class FBXImporterManager;
class FileDialog;
class FileSystemDock;
class HistoryDock;
@@ -84,6 +87,7 @@ class LinkButton;
class MenuBar;
class MenuButton;
class NodeDock;
+class OptionButton;
class OrphanResourcesDialog;
class Panel;
class PanelContainer;
@@ -98,7 +102,9 @@ class ScriptCreateDialog;
class SubViewport;
class TabBar;
class TabContainer;
+class TextureRect;
class TextureProgressBar;
+class Tree;
class VSplitContainer;
class Window;
class EditorBuildProfileManager;
@@ -204,6 +210,7 @@ private:
SETTINGS_EDITOR_DATA_FOLDER,
SETTINGS_EDITOR_CONFIG_FOLDER,
SETTINGS_MANAGE_EXPORT_TEMPLATES,
+ SETTINGS_MANAGE_FBX_IMPORTER,
SETTINGS_MANAGE_FEATURE_PROFILES,
SETTINGS_INSTALL_ANDROID_BUILD_TEMPLATE,
SETTINGS_PICK_MAIN_SCENE,
@@ -280,6 +287,8 @@ private:
ProjectExportDialog *project_export = nullptr;
ProjectSettingsEditor *project_settings_editor = nullptr;
+ FBXImporterManager *fbx_importer_manager = nullptr;
+
Vector<EditorPlugin *> editor_plugins;
bool _initializing_plugins = false;
HashMap<String, EditorPlugin *> addon_name_to_plugin;
@@ -713,9 +722,6 @@ public:
bool call_build();
- static void register_editor_types();
- static void unregister_editor_types();
-
static EditorNode *get_singleton() { return singleton; }
static EditorLog *get_log() { return singleton->log; }
@@ -749,6 +755,8 @@ public:
static bool immediate_confirmation_dialog(const String &p_text, const String &p_ok_text = TTR("Ok"), const String &p_cancel_text = TTR("Cancel"));
+ static void cleanup();
+
EditorPlugin *get_editor_plugin_screen() { return editor_plugin_screen; }
EditorPluginList *get_editor_plugins_force_input_forwarding() { return editor_plugins_force_input_forwarding; }
EditorPluginList *get_editor_plugins_force_over() { return editor_plugins_force_over; }
@@ -776,7 +784,7 @@ public:
bool is_movie_maker_enabled() const;
void edit_node(Node *p_node);
- void edit_resource(const Ref<Resource> &p_resource) { InspectorDock::get_singleton()->edit_resource(p_resource); };
+ void edit_resource(const Ref<Resource> &p_resource);
void save_resource_in_path(const Ref<Resource> &p_resource, const String &p_path);
void save_resource(const Ref<Resource> &p_resource);
@@ -816,7 +824,7 @@ public:
void setup_color_picker(ColorPicker *picker);
- void request_instance_scene(const String &p_path);
+ void request_instantiate_scene(const String &p_path);
void request_instantiate_scenes(const Vector<String> &p_files);
void set_convert_old_scene(bool p_old) { convert_old = p_old; }
diff --git a/editor/editor_plugin.cpp b/editor/editor_plugin.cpp
index 8fca21ae7b..f9c8b722c4 100644
--- a/editor/editor_plugin.cpp
+++ b/editor/editor_plugin.cpp
@@ -30,15 +30,21 @@
#include "editor_plugin.h"
+#include "editor/debugger/editor_debugger_node.h"
#include "editor/editor_command_palette.h"
#include "editor/editor_node.h"
#include "editor/editor_paths.h"
#include "editor/editor_resource_preview.h"
#include "editor/editor_settings.h"
+#include "editor/editor_translation_parser.h"
#include "editor/editor_undo_redo_manager.h"
#include "editor/export/editor_export.h"
#include "editor/filesystem_dock.h"
+#include "editor/import/editor_import_plugin.h"
+#include "editor/import/resource_importer_scene.h"
+#include "editor/inspector_dock.h"
#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/plugins/script_editor_plugin.h"
#include "editor/project_settings_editor.h"
@@ -238,14 +244,18 @@ void EditorInterface::select_file(const String &p_file) {
FileSystemDock::get_singleton()->select_file(p_file);
}
-String EditorInterface::get_selected_path() const {
- return FileSystemDock::get_singleton()->get_selected_path();
+Vector<String> EditorInterface::get_selected_paths() const {
+ return FileSystemDock::get_singleton()->get_selected_paths();
}
String EditorInterface::get_current_path() const {
return FileSystemDock::get_singleton()->get_current_path();
}
+String EditorInterface::get_current_directory() const {
+ return FileSystemDock::get_singleton()->get_current_directory();
+}
+
void EditorInterface::inspect_object(Object *p_obj, const String &p_for_property, bool p_inspector_only) {
EditorNode::get_singleton()->push_item(p_obj, p_for_property, p_inspector_only);
}
@@ -363,8 +373,9 @@ void EditorInterface::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_editor_main_screen"), &EditorInterface::get_editor_main_screen);
ClassDB::bind_method(D_METHOD("make_mesh_previews", "meshes", "preview_size"), &EditorInterface::_make_mesh_previews);
ClassDB::bind_method(D_METHOD("select_file", "file"), &EditorInterface::select_file);
- ClassDB::bind_method(D_METHOD("get_selected_path"), &EditorInterface::get_selected_path);
+ ClassDB::bind_method(D_METHOD("get_selected_paths"), &EditorInterface::get_selected_paths);
ClassDB::bind_method(D_METHOD("get_current_path"), &EditorInterface::get_current_path);
+ ClassDB::bind_method(D_METHOD("get_current_directory"), &EditorInterface::get_current_directory);
ClassDB::bind_method(D_METHOD("get_file_system_dock"), &EditorInterface::get_file_system_dock);
ClassDB::bind_method(D_METHOD("get_editor_paths"), &EditorInterface::get_editor_paths);
ClassDB::bind_method(D_METHOD("get_command_palette"), &EditorInterface::get_command_palette);
@@ -837,12 +848,12 @@ ScriptCreateDialog *EditorPlugin::get_script_create_dialog() {
return SceneTreeDock::get_singleton()->get_script_create_dialog();
}
-void EditorPlugin::add_debugger_plugin(const Ref<Script> &p_script) {
- EditorDebuggerNode::get_singleton()->add_debugger_plugin(p_script);
+void EditorPlugin::add_debugger_plugin(const Ref<EditorDebuggerPlugin> &p_plugin) {
+ EditorDebuggerNode::get_singleton()->add_debugger_plugin(p_plugin);
}
-void EditorPlugin::remove_debugger_plugin(const Ref<Script> &p_script) {
- EditorDebuggerNode::get_singleton()->remove_debugger_plugin(p_script);
+void EditorPlugin::remove_debugger_plugin(const Ref<EditorDebuggerPlugin> &p_plugin) {
+ EditorDebuggerNode::get_singleton()->remove_debugger_plugin(p_plugin);
}
void EditorPlugin::_editor_project_settings_changed() {
diff --git a/editor/editor_plugin.h b/editor/editor_plugin.h
index 753ccedf70..d736675faf 100644
--- a/editor/editor_plugin.h
+++ b/editor/editor_plugin.h
@@ -32,32 +32,34 @@
#define EDITOR_PLUGIN_H
#include "core/io/config_file.h"
-#include "editor/debugger/editor_debugger_node.h"
-#include "editor/editor_inspector.h"
-#include "editor/editor_translation_parser.h"
-#include "editor/import/editor_import_plugin.h"
-#include "editor/import/resource_importer_scene.h"
-#include "editor/script_create_dialog.h"
#include "scene/3d/camera_3d.h"
-#include "scene/main/node.h"
-#include "scene/resources/texture.h"
+#include "scene/gui/control.h"
class Node3D;
-class Camera3D;
+class Button;
+class PopupMenu;
class EditorCommandPalette;
-class EditorSelection;
+class EditorDebuggerPlugin;
class EditorExport;
-class EditorSettings;
-class EditorImportPlugin;
class EditorExportPlugin;
+class EditorFileSystem;
+class EditorImportPlugin;
+class EditorInspector;
+class EditorInspectorPlugin;
class EditorNode3DGizmoPlugin;
+class EditorPaths;
class EditorResourcePreview;
-class EditorUndoRedoManager;
-class EditorFileSystem;
+class EditorSceneFormatImporter;
+class EditorScenePostImportPlugin;
+class EditorSelection;
+class EditorSettings;
class EditorToolAddons;
-class EditorPaths;
+class EditorTranslationParserPlugin;
+class EditorUndoRedoManager;
class FileSystemDock;
+class ScriptCreateDialog;
class ScriptEditor;
+class VBoxContainer;
class EditorInterface : public Node {
GDCLASS(EditorInterface, Node);
@@ -92,8 +94,9 @@ public:
EditorCommandPalette *get_command_palette() const;
void select_file(const String &p_file);
- String get_selected_path() const;
+ Vector<String> get_selected_paths() const;
String get_current_path() const;
+ String get_current_directory() const;
void inspect_object(Object *p_obj, const String &p_for_property = String(), bool p_inspector_only = false);
@@ -301,8 +304,8 @@ public:
void add_autoload_singleton(const String &p_name, const String &p_path);
void remove_autoload_singleton(const String &p_name);
- void add_debugger_plugin(const Ref<Script> &p_script);
- void remove_debugger_plugin(const Ref<Script> &p_script);
+ void add_debugger_plugin(const Ref<EditorDebuggerPlugin> &p_plugin);
+ void remove_debugger_plugin(const Ref<EditorDebuggerPlugin> &p_plugin);
void enable_plugin();
void disable_plugin();
@@ -319,7 +322,7 @@ typedef EditorPlugin *(*EditorPluginCreateFunc)();
class EditorPlugins {
enum {
- MAX_CREATE_FUNCS = 64
+ MAX_CREATE_FUNCS = 128
};
static EditorPluginCreateFunc creation_funcs[MAX_CREATE_FUNCS];
diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp
index d71976a1af..4c9b18efe7 100644
--- a/editor/editor_properties.cpp
+++ b/editor/editor_properties.cpp
@@ -31,16 +31,23 @@
#include "editor_properties.h"
#include "core/config/project_settings.h"
+#include "core/core_string_names.h"
+#include "editor/create_dialog.h"
#include "editor/editor_file_dialog.h"
#include "editor/editor_node.h"
#include "editor/editor_properties_array_dict.h"
-#include "editor/editor_resource_preview.h"
+#include "editor/editor_resource_picker.h"
#include "editor/editor_scale.h"
-#include "editor/filesystem_dock.h"
+#include "editor/editor_settings.h"
+#include "editor/inspector_dock.h"
+#include "editor/plugins/script_editor_plugin.h"
#include "editor/project_settings_editor.h"
+#include "editor/property_selector.h"
+#include "editor/scene_tree_editor.h"
#include "scene/2d/gpu_particles_2d.h"
#include "scene/3d/fog_volume.h"
#include "scene/3d/gpu_particles_3d.h"
+#include "scene/gui/color_picker.h"
#include "scene/main/window.h"
#include "scene/resources/font.h"
#include "scene/resources/mesh.h"
@@ -1169,9 +1176,9 @@ void EditorPropertyLayers::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE:
case NOTIFICATION_THEME_CHANGED: {
- button->set_normal_texture(get_theme_icon(SNAME("GuiTabMenuHl"), SNAME("EditorIcons")));
- button->set_pressed_texture(get_theme_icon(SNAME("GuiTabMenuHl"), SNAME("EditorIcons")));
- button->set_disabled_texture(get_theme_icon(SNAME("GuiTabMenu"), SNAME("EditorIcons")));
+ button->set_texture_normal(get_theme_icon(SNAME("GuiTabMenuHl"), SNAME("EditorIcons")));
+ button->set_texture_pressed(get_theme_icon(SNAME("GuiTabMenuHl"), SNAME("EditorIcons")));
+ button->set_texture_disabled(get_theme_icon(SNAME("GuiTabMenu"), SNAME("EditorIcons")));
} break;
}
}
@@ -1377,10 +1384,11 @@ void EditorPropertyInteger::update_property() {
void EditorPropertyInteger::_bind_methods() {
}
-void EditorPropertyInteger::setup(int64_t p_min, int64_t p_max, int64_t p_step, bool p_allow_greater, bool p_allow_lesser, const String &p_suffix) {
+void EditorPropertyInteger::setup(int64_t p_min, int64_t p_max, int64_t p_step, bool p_hide_slider, bool p_allow_greater, bool p_allow_lesser, const String &p_suffix) {
spin->set_min(p_min);
spin->set_max(p_max);
spin->set_step(p_step);
+ spin->set_hide_slider(p_hide_slider);
spin->set_allow_greater(p_allow_greater);
spin->set_allow_lesser(p_allow_lesser);
spin->set_suffix(p_suffix);
@@ -1811,8 +1819,8 @@ void EditorPropertyVector2::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE:
case NOTIFICATION_THEME_CHANGED: {
- linked->set_normal_texture(get_theme_icon(SNAME("Unlinked"), SNAME("EditorIcons")));
- linked->set_pressed_texture(get_theme_icon(SNAME("Instance"), SNAME("EditorIcons")));
+ linked->set_texture_normal(get_theme_icon(SNAME("Unlinked"), SNAME("EditorIcons")));
+ linked->set_texture_pressed(get_theme_icon(SNAME("Instance"), SNAME("EditorIcons")));
const Color *colors = _get_property_colors();
for (int i = 0; i < 2; i++) {
@@ -2089,8 +2097,8 @@ void EditorPropertyVector3::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE:
case NOTIFICATION_THEME_CHANGED: {
- linked->set_normal_texture(get_theme_icon(SNAME("Unlinked"), SNAME("EditorIcons")));
- linked->set_pressed_texture(get_theme_icon(SNAME("Instance"), SNAME("EditorIcons")));
+ linked->set_texture_normal(get_theme_icon(SNAME("Unlinked"), SNAME("EditorIcons")));
+ linked->set_texture_pressed(get_theme_icon(SNAME("Instance"), SNAME("EditorIcons")));
const Color *colors = _get_property_colors();
for (int i = 0; i < 3; i++) {
@@ -2224,8 +2232,8 @@ void EditorPropertyVector2i::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE:
case NOTIFICATION_THEME_CHANGED: {
- linked->set_normal_texture(get_theme_icon(SNAME("Unlinked"), SNAME("EditorIcons")));
- linked->set_pressed_texture(get_theme_icon(SNAME("Instance"), SNAME("EditorIcons")));
+ linked->set_texture_normal(get_theme_icon(SNAME("Unlinked"), SNAME("EditorIcons")));
+ linked->set_texture_pressed(get_theme_icon(SNAME("Instance"), SNAME("EditorIcons")));
const Color *colors = _get_property_colors();
for (int i = 0; i < 2; i++) {
@@ -2235,12 +2243,11 @@ void EditorPropertyVector2i::_notification(int p_what) {
}
}
-void EditorPropertyVector2i::setup(int p_min, int p_max, bool p_hide_slider, bool p_link, const String &p_suffix) {
+void EditorPropertyVector2i::setup(int p_min, int p_max, bool p_link, const String &p_suffix) {
for (int i = 0; i < 2; i++) {
spin[i]->set_min(p_min);
spin[i]->set_max(p_max);
spin[i]->set_step(1);
- spin[i]->set_hide_slider(p_hide_slider);
spin[i]->set_allow_greater(true);
spin[i]->set_allow_lesser(true);
spin[i]->set_suffix(p_suffix);
@@ -2345,12 +2352,11 @@ void EditorPropertyRect2i::_notification(int p_what) {
void EditorPropertyRect2i::_bind_methods() {
}
-void EditorPropertyRect2i::setup(int p_min, int p_max, bool p_hide_slider, const String &p_suffix) {
+void EditorPropertyRect2i::setup(int p_min, int p_max, 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(1);
- spin[i]->set_hide_slider(p_hide_slider);
spin[i]->set_allow_greater(true);
spin[i]->set_allow_lesser(true);
spin[i]->set_suffix(p_suffix);
@@ -2475,8 +2481,8 @@ void EditorPropertyVector3i::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE:
case NOTIFICATION_THEME_CHANGED: {
- linked->set_normal_texture(get_theme_icon(SNAME("Unlinked"), SNAME("EditorIcons")));
- linked->set_pressed_texture(get_theme_icon(SNAME("Instance"), SNAME("EditorIcons")));
+ linked->set_texture_normal(get_theme_icon(SNAME("Unlinked"), SNAME("EditorIcons")));
+ linked->set_texture_pressed(get_theme_icon(SNAME("Instance"), SNAME("EditorIcons")));
const Color *colors = _get_property_colors();
for (int i = 0; i < 3; i++) {
@@ -2489,12 +2495,12 @@ void EditorPropertyVector3i::_notification(int p_what) {
void EditorPropertyVector3i::_bind_methods() {
}
-void EditorPropertyVector3i::setup(int p_min, int p_max, bool p_hide_slider, bool p_link, const String &p_suffix) {
+void EditorPropertyVector3i::setup(int p_min, int p_max, bool p_link, const String &p_suffix) {
for (int i = 0; i < 3; i++) {
spin[i]->set_min(p_min);
spin[i]->set_max(p_max);
spin[i]->set_step(1);
- spin[i]->set_hide_slider(p_hide_slider);
+ spin[i]->set_hide_slider(false);
spin[i]->set_allow_greater(true);
spin[i]->set_allow_lesser(true);
spin[i]->set_suffix(p_suffix);
@@ -2997,11 +3003,11 @@ void EditorPropertyVector4i::_notification(int p_what) {
void EditorPropertyVector4i::_bind_methods() {
}
-void EditorPropertyVector4i::setup(double p_min, double p_max, bool p_hide_slider, const String &p_suffix) {
+void EditorPropertyVector4i::setup(double p_min, double p_max, 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_hide_slider);
+ spin[i]->set_step(1);
spin[i]->set_allow_greater(true);
spin[i]->set_allow_lesser(true);
spin[i]->set_suffix(p_suffix);
@@ -3844,8 +3850,11 @@ 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;
+
+ // The bool is_script applies only to an object's main script.
+ // Changing the value of Script-type exported variables of the main script should not trigger saving/reloading properties.
bool is_script = false;
- if (get_edited_object() && s.is_valid()) {
+ if (get_edited_object() && s.is_valid() && get_edited_property() == CoreStringNames::get_singleton()->_script) {
is_script = true;
InspectorDock::get_singleton()->store_script_properties(get_edited_object());
s->call("set_instance_base_type", get_edited_object()->get_class());
@@ -4337,7 +4346,7 @@ EditorProperty *EditorInspectorDefaultPlugin::get_editor_for_property(Object *p_
EditorPropertyInteger *editor = memnew(EditorPropertyInteger);
EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, 1);
- editor->setup(hint.min, hint.max, hint.step, hint.or_greater, hint.or_less, hint.suffix);
+ editor->setup(hint.min, hint.max, hint.step, hint.hide_slider, hint.or_greater, hint.or_less, hint.suffix);
return editor;
}
@@ -4465,7 +4474,7 @@ EditorProperty *EditorInspectorDefaultPlugin::get_editor_for_property(Object *p_
case Variant::VECTOR2I: {
EditorPropertyVector2i *editor = memnew(EditorPropertyVector2i(p_wide));
EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, 1);
- editor->setup(hint.min, hint.max, hint.hide_slider, p_hint == PROPERTY_HINT_LINK, hint.suffix);
+ editor->setup(hint.min, hint.max, p_hint == PROPERTY_HINT_LINK, hint.suffix);
return editor;
} break;
@@ -4478,7 +4487,7 @@ EditorProperty *EditorInspectorDefaultPlugin::get_editor_for_property(Object *p_
case Variant::RECT2I: {
EditorPropertyRect2i *editor = memnew(EditorPropertyRect2i(p_wide));
EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, 1);
- editor->setup(hint.min, hint.max, hint.hide_slider, hint.suffix);
+ editor->setup(hint.min, hint.max, hint.suffix);
return editor;
} break;
@@ -4492,7 +4501,7 @@ EditorProperty *EditorInspectorDefaultPlugin::get_editor_for_property(Object *p_
case Variant::VECTOR3I: {
EditorPropertyVector3i *editor = memnew(EditorPropertyVector3i(p_wide));
EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, 1);
- editor->setup(hint.min, hint.max, hint.hide_slider, p_hint == PROPERTY_HINT_LINK, hint.suffix);
+ editor->setup(hint.min, hint.max, p_hint == PROPERTY_HINT_LINK, hint.suffix);
return editor;
} break;
@@ -4506,7 +4515,7 @@ EditorProperty *EditorInspectorDefaultPlugin::get_editor_for_property(Object *p_
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);
+ editor->setup(hint.min, hint.max, hint.suffix);
return editor;
} break;
diff --git a/editor/editor_properties.h b/editor/editor_properties.h
index 20b130f57f..042b94130b 100644
--- a/editor/editor_properties.h
+++ b/editor/editor_properties.h
@@ -31,15 +31,19 @@
#ifndef EDITOR_PROPERTIES_H
#define EDITOR_PROPERTIES_H
-#include "editor/create_dialog.h"
#include "editor/editor_inspector.h"
-#include "editor/editor_locale_dialog.h"
-#include "editor/editor_resource_picker.h"
-#include "editor/editor_spin_slider.h"
-#include "editor/property_selector.h"
-#include "editor/scene_tree_editor.h"
-#include "scene/gui/color_picker.h"
-#include "scene/gui/line_edit.h"
+
+class CheckBox;
+class ColorPickerButton;
+class CreateDialog;
+class EditorFileDialog;
+class EditorLocaleDialog;
+class EditorResourcePicker;
+class EditorSpinSlider;
+class PropertySelector;
+class SceneTreeDialog;
+class TextEdit;
+class TextureButton;
class EditorPropertyNil : public EditorProperty {
GDCLASS(EditorPropertyNil, EditorProperty);
@@ -374,7 +378,7 @@ protected:
public:
virtual void update_property() override;
- void setup(int64_t p_min, int64_t p_max, int64_t p_step, bool p_allow_greater, bool p_allow_lesser, const String &p_suffix = String());
+ void setup(int64_t p_min, int64_t p_max, int64_t p_step, bool p_hide_slider, bool p_allow_greater, bool p_allow_lesser, const String &p_suffix = String());
EditorPropertyInteger();
};
@@ -562,7 +566,7 @@ protected:
public:
virtual void update_property() override;
- void setup(int p_min, int p_max, bool p_hide_slider, bool p_link = false, const String &p_suffix = String());
+ void setup(int p_min, int p_max, bool p_link = false, const String &p_suffix = String());
EditorPropertyVector2i(bool p_force_wide = false);
};
@@ -579,7 +583,7 @@ protected:
public:
virtual void update_property() override;
- void setup(int p_min, int p_max, bool p_hide_slider, const String &p_suffix = String());
+ void setup(int p_min, int p_max, const String &p_suffix = String());
EditorPropertyRect2i(bool p_force_wide = false);
};
@@ -604,7 +608,7 @@ protected:
public:
virtual void update_property() override;
- void setup(int p_min, int p_max, bool p_hide_slider, bool p_link = false, const String &p_suffix = String());
+ void setup(int p_min, int p_max, bool p_link = false, const String &p_suffix = String());
EditorPropertyVector3i(bool p_force_wide = false);
};
@@ -639,7 +643,7 @@ class EditorPropertyQuaternion : public EditorProperty {
EditorSpinSlider *euler[3];
Button *edit_button = nullptr;
- Vector3 edit_euler = Vector3();
+ Vector3 edit_euler;
void _value_changed(double p_val, const String &p_name);
void _edit_custom_value();
@@ -689,7 +693,7 @@ protected:
public:
virtual void update_property() override;
- void setup(double p_min, double p_max, bool p_hide_slider, const String &p_suffix = String());
+ void setup(double p_min, double p_max, const String &p_suffix = String());
EditorPropertyVector4i();
};
diff --git a/editor/editor_properties_array_dict.cpp b/editor/editor_properties_array_dict.cpp
index 659221ee0b..451cb7cfee 100644
--- a/editor/editor_properties_array_dict.cpp
+++ b/editor/editor_properties_array_dict.cpp
@@ -34,6 +34,7 @@
#include "core/io/marshalls.h"
#include "editor/editor_properties.h"
#include "editor/editor_scale.h"
+#include "editor/editor_settings.h"
#include "editor/inspector_dock.h"
bool EditorPropertyArrayObject::_set(const StringName &p_name, const Variant &p_value) {
@@ -692,6 +693,8 @@ void EditorPropertyArray::_reorder_button_up() {
reorder_mouse_y_delta = 0.0f;
Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_VISIBLE);
+
+ ERR_FAIL_NULL(reorder_selected_button);
reorder_selected_button->warp_mouse(reorder_selected_button->get_size() / 2.0f);
reorder_selected_element_hbox = nullptr;
@@ -916,7 +919,7 @@ void EditorPropertyDictionary::update_property() {
} break;
case Variant::INT: {
EditorPropertyInteger *editor = memnew(EditorPropertyInteger);
- editor->setup(-100000, 100000, 1, true, true);
+ editor->setup(-100000, 100000, 1, false, true, true);
prop = editor;
} break;
@@ -939,7 +942,7 @@ void EditorPropertyDictionary::update_property() {
} break;
case Variant::VECTOR2I: {
EditorPropertyVector2i *editor = memnew(EditorPropertyVector2i);
- editor->setup(-100000, 100000, true);
+ editor->setup(-100000, 100000);
prop = editor;
} break;
@@ -951,7 +954,7 @@ void EditorPropertyDictionary::update_property() {
} break;
case Variant::RECT2I: {
EditorPropertyRect2i *editor = memnew(EditorPropertyRect2i);
- editor->setup(-100000, 100000, true);
+ editor->setup(-100000, 100000);
prop = editor;
} break;
@@ -963,7 +966,7 @@ void EditorPropertyDictionary::update_property() {
} break;
case Variant::VECTOR3I: {
EditorPropertyVector3i *editor = memnew(EditorPropertyVector3i);
- editor->setup(-100000, 100000, true);
+ editor->setup(-100000, 100000);
prop = editor;
} break;
@@ -975,7 +978,7 @@ void EditorPropertyDictionary::update_property() {
} break;
case Variant::VECTOR4I: {
EditorPropertyVector4i *editor = memnew(EditorPropertyVector4i);
- editor->setup(-100000, 100000, true);
+ editor->setup(-100000, 100000);
prop = editor;
} break;
diff --git a/editor/editor_property_name_processor.cpp b/editor/editor_property_name_processor.cpp
index a2dfa4f80e..e8a0912d66 100644
--- a/editor/editor_property_name_processor.cpp
+++ b/editor/editor_property_name_processor.cpp
@@ -64,6 +64,10 @@ String EditorPropertyNameProcessor::_capitalize_name(const String &p_name) const
Vector<String> parts = p_name.split("_", false);
for (int i = 0; i < parts.size(); i++) {
+ // Articles/conjunctions/prepositions which should only be capitalized when not at beginning and end.
+ if (i > 0 && i + 1 < parts.size() && stop_words.find(parts[i]) != -1) {
+ continue;
+ }
HashMap<String, String>::ConstIterator remap = capitalize_string_remaps.find(parts[i]);
if (remap) {
parts.write[i] = remap->value;
@@ -143,6 +147,7 @@ EditorPropertyNameProcessor::EditorPropertyNameProcessor() {
capitalize_string_remaps["gdscript"] = "GDScript";
capitalize_string_remaps["ggx"] = "GGX";
capitalize_string_remaps["gi"] = "GI";
+ capitalize_string_remaps["gl"] = "GL";
capitalize_string_remaps["glb"] = "GLB";
capitalize_string_remaps["gles2"] = "GLES2";
capitalize_string_remaps["gles3"] = "GLES3";
@@ -157,6 +162,7 @@ EditorPropertyNameProcessor::EditorPropertyNameProcessor() {
capitalize_string_remaps["html"] = "HTML";
capitalize_string_remaps["http"] = "HTTP";
capitalize_string_remaps["id"] = "ID";
+ capitalize_string_remaps["ids"] = "IDs";
capitalize_string_remaps["igd"] = "IGD";
capitalize_string_remaps["ik"] = "IK";
capitalize_string_remaps["image@2x"] = "Image @2x";
@@ -223,7 +229,9 @@ EditorPropertyNameProcessor::EditorPropertyNameProcessor() {
capitalize_string_remaps["svg"] = "SVG";
capitalize_string_remaps["taa"] = "TAA";
capitalize_string_remaps["tcp"] = "TCP";
+ capitalize_string_remaps["tls"] = "TLS";
capitalize_string_remaps["ui"] = "UI";
+ capitalize_string_remaps["uri"] = "URI";
capitalize_string_remaps["url"] = "URL";
capitalize_string_remaps["urls"] = "URLs";
capitalize_string_remaps["us"] = String::utf8("(µs)"); // Unit.
@@ -237,6 +245,7 @@ EditorPropertyNameProcessor::EditorPropertyNameProcessor() {
capitalize_string_remaps["vector2"] = "Vector2";
capitalize_string_remaps["vpn"] = "VPN";
capitalize_string_remaps["vram"] = "VRAM";
+ capitalize_string_remaps["vrs"] = "VRS";
capitalize_string_remaps["vsync"] = "V-Sync";
capitalize_string_remaps["wap"] = "WAP";
capitalize_string_remaps["webp"] = "WebP";
@@ -246,9 +255,33 @@ EditorPropertyNameProcessor::EditorPropertyNameProcessor() {
capitalize_string_remaps["wifi"] = "Wi-Fi";
capitalize_string_remaps["x86"] = "x86";
capitalize_string_remaps["xr"] = "XR";
+ capitalize_string_remaps["xray"] = "X-Ray";
capitalize_string_remaps["xy"] = "XY";
capitalize_string_remaps["xz"] = "XZ";
capitalize_string_remaps["yz"] = "YZ";
+
+ // Articles, conjunctions, prepositions.
+ // The following initialization is parsed in `editor/translations/extract.py` with a regex.
+ // The word definition format should be kept synced with the regex.
+ stop_words = LocalVector<String>({
+ "a",
+ "an",
+ "and",
+ "as",
+ "at",
+ "by",
+ "for",
+ "in",
+ "not",
+ "of",
+ "on",
+ "or",
+ "over",
+ "per",
+ "the",
+ "then",
+ "to",
+ });
}
EditorPropertyNameProcessor::~EditorPropertyNameProcessor() {
diff --git a/editor/editor_property_name_processor.h b/editor/editor_property_name_processor.h
index 37d905c806..fcabbfd9d3 100644
--- a/editor/editor_property_name_processor.h
+++ b/editor/editor_property_name_processor.h
@@ -40,6 +40,7 @@ class EditorPropertyNameProcessor : public Node {
mutable HashMap<String, String> capitalize_string_cache;
HashMap<String, String> capitalize_string_remaps;
+ LocalVector<String> stop_words; // Exceptions that shouldn't be capitalized.
// Capitalizes property path segments.
String _capitalize_name(const String &p_name) const;
diff --git a/editor/editor_quick_open.cpp b/editor/editor_quick_open.cpp
index b4ec3bca15..6ddccba0e2 100644
--- a/editor/editor_quick_open.cpp
+++ b/editor/editor_quick_open.cpp
@@ -32,17 +32,26 @@
#include "core/os/keyboard.h"
#include "editor/editor_node.h"
+#include "editor/editor_scale.h"
-void EditorQuickOpen::popup_dialog(const StringName &p_base, bool p_enable_multi, bool p_dontclear) {
+static Rect2i prev_rect = Rect2i();
+static bool was_showed = false;
+
+void EditorQuickOpen::popup_dialog(const String &p_base, bool p_enable_multi, bool p_dont_clear) {
base_type = p_base;
allow_multi_select = p_enable_multi;
search_options->set_select_mode(allow_multi_select ? Tree::SELECT_MULTI : Tree::SELECT_SINGLE);
- popup_centered_clamped(Size2i(600, 440), 0.8f);
+
+ if (was_showed) {
+ popup(prev_rect);
+ } else {
+ popup_centered_clamped(Size2(600, 440) * EDSCALE, 0.8f);
+ }
EditorFileSystemDirectory *efsd = EditorFileSystem::get_singleton()->get_filesystem();
_build_search_cache(efsd);
- if (p_dontclear) {
+ if (p_dont_clear) {
search_box->select_all();
_update_search();
} else {
@@ -56,7 +65,7 @@ void EditorQuickOpen::_build_search_cache(EditorFileSystemDirectory *p_efsd) {
_build_search_cache(p_efsd->get_subdir(i));
}
- Vector<String> base_types = String(base_type).split(String(","));
+ Vector<String> base_types = base_type.split(",");
for (int i = 0; i < p_efsd->get_file_count(); i++) {
String file = p_efsd->get_file_path(i);
String engine_type = p_efsd->get_file_type(i);
@@ -80,7 +89,7 @@ void EditorQuickOpen::_build_search_cache(EditorFileSystemDirectory *p_efsd) {
// Store refs to used icons.
String ext = file.get_extension();
if (!icons.has(ext)) {
- icons.insert(ext, get_theme_icon((has_theme_icon(actual_type, SNAME("EditorIcons")) ? actual_type : String("Object")), SNAME("EditorIcons")));
+ icons.insert(ext, get_theme_icon((has_theme_icon(actual_type, SNAME("EditorIcons")) ? actual_type : "Object"), SNAME("EditorIcons")));
}
// Stop testing base types as soon as we got a match.
@@ -231,7 +240,7 @@ Vector<String> EditorQuickOpen::get_selected_files() const {
return selected_files;
}
-StringName EditorQuickOpen::get_base_type() const {
+String EditorQuickOpen::get_base_type() const {
return base_type;
}
@@ -243,6 +252,13 @@ void EditorQuickOpen::_notification(int p_what) {
search_box->set_clear_button_enabled(true);
} break;
+ case NOTIFICATION_VISIBILITY_CHANGED: {
+ if (!is_visible()) {
+ prev_rect = Rect2i(get_position(), get_size());
+ was_showed = true;
+ }
+ } break;
+
case NOTIFICATION_EXIT_TREE: {
disconnect("confirmed", callable_mp(this, &EditorQuickOpen::_confirmed));
} break;
diff --git a/editor/editor_quick_open.h b/editor/editor_quick_open.h
index 83cbbd7cac..3b7e8136ef 100644
--- a/editor/editor_quick_open.h
+++ b/editor/editor_quick_open.h
@@ -41,7 +41,7 @@ class EditorQuickOpen : public ConfirmationDialog {
LineEdit *search_box = nullptr;
Tree *search_options = nullptr;
- StringName base_type;
+ String base_type;
bool allow_multi_select = false;
bool _load_resources = false; // Prohibitively slow for now.
@@ -77,12 +77,12 @@ protected:
static void _bind_methods();
public:
- StringName get_base_type() const;
+ String get_base_type() const;
String get_selected() const;
Vector<String> get_selected_files() const;
- void popup_dialog(const StringName &p_base, bool p_enable_multi = false, bool p_dontclear = false);
+ void popup_dialog(const String &p_base, bool p_enable_multi = false, bool p_dontclear = false);
EditorQuickOpen();
};
diff --git a/editor/editor_resource_picker.cpp b/editor/editor_resource_picker.cpp
index 0b38996b2d..acc8b3b6a2 100644
--- a/editor/editor_resource_picker.cpp
+++ b/editor/editor_resource_picker.cpp
@@ -256,7 +256,7 @@ void EditorResourcePicker::_update_menu_items() {
paste_valid = ClassDB::is_parent_class(res_type, base) || EditorNode::get_editor_data().script_class_is_parent(res_type, base);
- if (!paste_valid) {
+ if (paste_valid) {
break;
}
}
@@ -438,7 +438,7 @@ void EditorResourcePicker::_edit_menu_cbk(int p_which) {
}
if (!obj) {
- obj = EditorNode::get_editor_data().instance_custom_type(intype, "Resource");
+ obj = EditorNode::get_editor_data().instantiate_custom_type(intype, "Resource");
}
Resource *resp = Object::cast_to<Resource>(obj);
diff --git a/editor/editor_run.cpp b/editor/editor_run.cpp
index 41d5d1b0d2..913a0ba104 100644
--- a/editor/editor_run.cpp
+++ b/editor/editor_run.cpp
@@ -31,6 +31,7 @@
#include "editor_run.h"
#include "core/config/project_settings.h"
+#include "editor/debugger/editor_debugger_node.h"
#include "editor/editor_node.h"
#include "editor/editor_settings.h"
#include "main/main.h"
diff --git a/editor/editor_run.h b/editor/editor_run.h
index 4cbc6838e4..935e32ee2a 100644
--- a/editor/editor_run.h
+++ b/editor/editor_run.h
@@ -32,7 +32,7 @@
#define EDITOR_RUN_H
#include "core/os/os.h"
-#include "scene/main/node.h"
+
class EditorRun {
public:
enum Status {
diff --git a/editor/editor_sectioned_inspector.cpp b/editor/editor_sectioned_inspector.cpp
index ae47bbe864..5c8ef89ac9 100644
--- a/editor/editor_sectioned_inspector.cpp
+++ b/editor/editor_sectioned_inspector.cpp
@@ -312,7 +312,9 @@ void SectionedInspector::_search_changed(const String &p_what) {
void SectionedInspector::_notification(int p_what) {
switch (p_what) {
case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
- inspector->set_property_name_style(EditorPropertyNameProcessor::get_settings_style());
+ if (EditorSettings::get_singleton()->check_changed_settings_in_group("interface/editor/localize_settings")) {
+ inspector->set_property_name_style(EditorPropertyNameProcessor::get_settings_style());
+ }
} break;
}
}
diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp
index a4e907b46f..79b03febdc 100644
--- a/editor/editor_settings.cpp
+++ b/editor/editor_settings.cpp
@@ -412,7 +412,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
EDITOR_SETTING_USAGE(Variant::FLOAT, PROPERTY_HINT_RANGE, "interface/editor/custom_display_scale", 1.0, "0.5,3,0.01", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED)
EDITOR_SETTING(Variant::INT, PROPERTY_HINT_RANGE, "interface/editor/main_font_size", 14, "8,48,1")
EDITOR_SETTING(Variant::INT, PROPERTY_HINT_RANGE, "interface/editor/code_font_size", 14, "8,48,1")
- EDITOR_SETTING(Variant::INT, PROPERTY_HINT_ENUM, "interface/editor/code_font_contextual_ligatures", 0, "Default,Disable Contextual Alternates (Coding Ligatures),Use Custom OpenType Feature Set")
+ EDITOR_SETTING(Variant::INT, PROPERTY_HINT_ENUM, "interface/editor/code_font_contextual_ligatures", 1, "Enabled,Disable Contextual Alternates (Coding Ligatures),Use Custom OpenType Feature Set")
_initial_set("interface/editor/code_font_custom_opentype_features", "");
_initial_set("interface/editor/code_font_custom_variations", "");
EDITOR_SETTING(Variant::INT, PROPERTY_HINT_ENUM, "interface/editor/font_antialiasing", 1, "None,Grayscale,LCD Subpixel")
@@ -452,11 +452,12 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
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")
+ EDITOR_SETTING(Variant::STRING, PROPERTY_HINT_ENUM, "interface/theme/preset", "Default", "Default,Breeze Dark,Godot 2,Gray,Light,Solarized (Dark),Solarized (Light),Black (OLED),Custom")
EDITOR_SETTING(Variant::INT, PROPERTY_HINT_ENUM, "interface/theme/icon_and_font_color", 0, "Auto,Dark,Light")
EDITOR_SETTING(Variant::COLOR, PROPERTY_HINT_NONE, "interface/theme/base_color", Color(0.2, 0.23, 0.31), "")
EDITOR_SETTING(Variant::COLOR, PROPERTY_HINT_NONE, "interface/theme/accent_color", Color(0.41, 0.61, 0.91), "")
EDITOR_SETTING(Variant::FLOAT, PROPERTY_HINT_RANGE, "interface/theme/contrast", 0.3, "-1,1,0.01")
+ EDITOR_SETTING(Variant::BOOL, PROPERTY_HINT_NONE, "interface/theme/draw_extra_borders", false, "")
EDITOR_SETTING(Variant::FLOAT, PROPERTY_HINT_RANGE, "interface/theme/icon_saturation", 1.0, "0,2,0.01")
EDITOR_SETTING(Variant::FLOAT, PROPERTY_HINT_RANGE, "interface/theme/relationship_line_opacity", 0.1, "0.00,1,0.01")
EDITOR_SETTING(Variant::INT, PROPERTY_HINT_RANGE, "interface/theme/border_size", 0, "0,2,1")
@@ -733,6 +734,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
// TRANSLATORS: Project Manager here refers to the tool used to create/manage Godot projects.
EDITOR_SETTING(Variant::INT, PROPERTY_HINT_ENUM, "project_manager/sorting_order", 0, "Last Edited,Name,Path")
+ EDITOR_SETTING(Variant::STRING, PROPERTY_HINT_NONE, "project_manager/default_renderer", "forward_plus", "forward_plus,mobile,gl_compatibility")
if (p_extra_config.is_valid()) {
if (p_extra_config->has_section("init_projects") && p_extra_config->has_section_key("init_projects", "list")) {
diff --git a/editor/editor_settings_dialog.cpp b/editor/editor_settings_dialog.cpp
index 77a0d9f85c..6c11572d10 100644
--- a/editor/editor_settings_dialog.cpp
+++ b/editor/editor_settings_dialog.cpp
@@ -61,7 +61,7 @@ void EditorSettingsDialog::_settings_changed() {
void EditorSettingsDialog::_settings_property_edited(const String &p_name) {
String full_name = inspector->get_full_item_path(p_name);
- if (full_name == "interface/theme/accent_color" || full_name == "interface/theme/base_color" || full_name == "interface/theme/contrast") {
+ if (full_name == "interface/theme/accent_color" || full_name == "interface/theme/base_color" || full_name == "interface/theme/contrast" || full_name == "interface/theme/draw_extra_borders") {
EditorSettings::get_singleton()->set_manually("interface/theme/preset", "Custom"); // set preset to Custom
} else if (full_name.begins_with("text_editor/theme/highlighting")) {
EditorSettings::get_singleton()->set_manually("text_editor/theme/color_theme", "Custom");
@@ -152,7 +152,9 @@ void EditorSettingsDialog::_notification(int p_what) {
_update_shortcuts();
}
- inspector->update_category_list();
+ if (EditorSettings::get_singleton()->check_changed_settings_in_group("interface/editor/localize_settings")) {
+ inspector->update_category_list();
+ }
} break;
}
}
diff --git a/editor/editor_spin_slider.cpp b/editor/editor_spin_slider.cpp
index 1cdfceebc8..60c46835fe 100644
--- a/editor/editor_spin_slider.cpp
+++ b/editor/editor_spin_slider.cpp
@@ -76,6 +76,7 @@ void EditorSpinSlider::gui_input(const Ref<InputEvent> &p_event) {
pre_grab_value = get_value();
grabbing_spinner = false;
grabbing_spinner_mouse_pos = get_global_mouse_position();
+ emit_signal("grabbed");
}
} else {
if (grabbing_spinner_attempt) {
@@ -83,6 +84,7 @@ void EditorSpinSlider::gui_input(const Ref<InputEvent> &p_event) {
Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_VISIBLE);
Input::get_singleton()->warp_mouse(grabbing_spinner_mouse_pos);
queue_redraw();
+ emit_signal("ungrabbed");
} else {
_focus_entered();
}
@@ -178,9 +180,11 @@ void EditorSpinSlider::_grabber_gui_input(const Ref<InputEvent> &p_event) {
grabbing_ratio = get_as_ratio();
grabbing_from = grabber->get_transform().xform(mb->get_position()).x;
}
+ emit_signal("grabbed");
} else {
grabbing_grabber = false;
mousewheel_over_grabber = false;
+ emit_signal("ungrabbed");
}
}
@@ -299,10 +303,6 @@ void EditorSpinSlider::_draw_spin_slider() {
Ref<Texture2D> updown = get_theme_icon(is_read_only() ? SNAME("updown_disabled") : SNAME("updown"), SNAME("SpinBox"));
- if (get_step() == 1) {
- number_width -= updown->get_width();
- }
-
String numstr = get_text_value();
int vofs = (size.height - font->get_height(font_size)) / 2 + font->get_ascent(font_size);
@@ -359,76 +359,79 @@ void EditorSpinSlider::_draw_spin_slider() {
}
TS->free_rid(num_rid);
- if (get_step() == 1) {
- Ref<Texture2D> updown2 = get_theme_icon(is_read_only() ? SNAME("updown_disabled") : SNAME("updown"), SNAME("SpinBox"));
- int updown_vofs = (size.height - updown2->get_height()) / 2;
- if (rtl) {
- updown_offset = sb->get_margin(SIDE_LEFT);
- } else {
- updown_offset = size.width - sb->get_margin(SIDE_RIGHT) - updown2->get_width();
- }
- Color c(1, 1, 1);
- if (hover_updown) {
- c *= Color(1.2, 1.2, 1.2);
- }
- draw_texture(updown2, Vector2(updown_offset, updown_vofs), c);
- if (grabber->is_visible()) {
- grabber->hide();
- }
- } else if (!hide_slider) {
- const int grabber_w = 4 * EDSCALE;
- const int width = size.width - sb->get_minimum_size().width - grabber_w;
- const int ofs = sb->get_offset().x;
- const int svofs = (size.height + vofs) / 2 - 1;
- Color c = fc;
-
- // Draw the horizontal slider's background.
- c.a = 0.2;
- draw_rect(Rect2(ofs, svofs + 1, width, 2 * EDSCALE), c);
-
- // Draw the horizontal slider's filled part on the left.
- const int gofs = get_as_ratio() * width;
- c.a = 0.45;
- draw_rect(Rect2(ofs, svofs + 1, gofs, 2 * EDSCALE), c);
-
- // Draw the horizontal slider's grabber.
- c.a = 0.9;
- const Rect2 grabber_rect = Rect2(ofs + gofs, svofs, grabber_w, 4 * EDSCALE);
- draw_rect(grabber_rect, c);
-
- grabbing_spinner_mouse_pos = get_global_position() + grabber_rect.get_center();
-
- bool display_grabber = (grabbing_grabber || mouse_over_spin || mouse_over_grabber) && !grabbing_spinner && !(value_input_popup && value_input_popup->is_visible());
- if (grabber->is_visible() != display_grabber) {
- if (display_grabber) {
- grabber->show();
+ if (!hide_slider) {
+ if (get_step() == 1) {
+ number_width -= updown->get_width();
+ Ref<Texture2D> updown2 = get_theme_icon(is_read_only() ? SNAME("updown_disabled") : SNAME("updown"), SNAME("SpinBox"));
+ int updown_vofs = (size.height - updown2->get_height()) / 2;
+ if (rtl) {
+ updown_offset = sb->get_margin(SIDE_LEFT);
} else {
+ updown_offset = size.width - sb->get_margin(SIDE_RIGHT) - updown2->get_width();
+ }
+ Color c(1, 1, 1);
+ if (hover_updown) {
+ c *= Color(1.2, 1.2, 1.2);
+ }
+ draw_texture(updown2, Vector2(updown_offset, updown_vofs), c);
+ if (grabber->is_visible()) {
grabber->hide();
}
- }
-
- if (display_grabber) {
- Ref<Texture2D> grabber_tex;
- if (mouse_over_grabber) {
- grabber_tex = get_theme_icon(SNAME("grabber_highlight"), SNAME("HSlider"));
- } else {
- grabber_tex = get_theme_icon(SNAME("grabber"), SNAME("HSlider"));
+ } else {
+ const int grabber_w = 4 * EDSCALE;
+ const int width = size.width - sb->get_minimum_size().width - grabber_w;
+ const int ofs = sb->get_offset().x;
+ const int svofs = (size.height + vofs) / 2 - 1;
+ Color c = fc;
+
+ // Draw the horizontal slider's background.
+ c.a = 0.2;
+ draw_rect(Rect2(ofs, svofs + 1, width, 2 * EDSCALE), c);
+
+ // Draw the horizontal slider's filled part on the left.
+ const int gofs = get_as_ratio() * width;
+ c.a = 0.45;
+ draw_rect(Rect2(ofs, svofs + 1, gofs, 2 * EDSCALE), c);
+
+ // Draw the horizontal slider's grabber.
+ c.a = 0.9;
+ const Rect2 grabber_rect = Rect2(ofs + gofs, svofs, grabber_w, 4 * EDSCALE);
+ draw_rect(grabber_rect, c);
+
+ grabbing_spinner_mouse_pos = get_global_position() + grabber_rect.get_center();
+
+ bool display_grabber = (grabbing_grabber || mouse_over_spin || mouse_over_grabber) && !grabbing_spinner && !(value_input_popup && value_input_popup->is_visible());
+ if (grabber->is_visible() != display_grabber) {
+ if (display_grabber) {
+ grabber->show();
+ } else {
+ grabber->hide();
+ }
}
- if (grabber->get_texture() != grabber_tex) {
- grabber->set_texture(grabber_tex);
- }
+ if (display_grabber) {
+ Ref<Texture2D> grabber_tex;
+ if (mouse_over_grabber) {
+ grabber_tex = get_theme_icon(SNAME("grabber_highlight"), SNAME("HSlider"));
+ } else {
+ grabber_tex = get_theme_icon(SNAME("grabber"), SNAME("HSlider"));
+ }
- Vector2 scale = get_global_transform_with_canvas().get_scale();
- grabber->set_scale(scale);
- grabber->reset_size();
- grabber->set_position(get_global_position() + (grabber_rect.get_center() - grabber->get_size() * 0.5) * scale);
+ if (grabber->get_texture() != grabber_tex) {
+ grabber->set_texture(grabber_tex);
+ }
- if (mousewheel_over_grabber) {
- Input::get_singleton()->warp_mouse(grabber->get_position() + grabber_rect.size);
- }
+ Vector2 scale = get_global_transform_with_canvas().get_scale();
+ grabber->set_scale(scale);
+ grabber->reset_size();
+ grabber->set_position(get_global_position() + (grabber_rect.get_center() - grabber->get_size() * 0.5) * scale);
+
+ if (mousewheel_over_grabber) {
+ Input::get_singleton()->warp_mouse(grabber->get_position() + grabber_rect.size);
+ }
- grabber_range = width;
+ grabber_range = width;
+ }
}
}
}
@@ -582,7 +585,10 @@ void EditorSpinSlider::_value_focus_exited() {
//tab was pressed
} else {
//enter, click, esc
+ grab_focus();
}
+
+ emit_signal("value_focus_exited");
}
void EditorSpinSlider::_grabber_mouse_entered() {
@@ -619,15 +625,14 @@ bool EditorSpinSlider::is_grabbing() const {
void EditorSpinSlider::_focus_entered() {
_ensure_input_popup();
- Rect2 gr = get_screen_rect();
value_input->set_text(get_text_value());
- value_input_popup->set_position(gr.position);
- value_input_popup->set_size(gr.size);
- value_input_popup->call_deferred(SNAME("popup"));
+ value_input_popup->set_size(get_size());
+ value_input_popup->call_deferred(SNAME("show"));
value_input->call_deferred(SNAME("grab_focus"));
value_input->call_deferred(SNAME("select_all"));
value_input->set_focus_next(find_next_valid_focus()->get_path());
value_input->set_focus_previous(find_prev_valid_focus()->get_path());
+ emit_signal("value_focus_entered");
}
void EditorSpinSlider::_bind_methods() {
@@ -651,6 +656,11 @@ void EditorSpinSlider::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "read_only"), "set_read_only", "is_read_only");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "flat"), "set_flat", "is_flat");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hide_slider"), "set_hide_slider", "is_hiding_slider");
+
+ ADD_SIGNAL(MethodInfo("grabbed"));
+ ADD_SIGNAL(MethodInfo("ungrabbed"));
+ ADD_SIGNAL(MethodInfo("value_focus_entered"));
+ ADD_SIGNAL(MethodInfo("value_focus_exited"));
}
void EditorSpinSlider::_ensure_input_popup() {
@@ -658,14 +668,13 @@ void EditorSpinSlider::_ensure_input_popup() {
return;
}
- value_input_popup = memnew(Popup);
+ value_input_popup = memnew(Control);
add_child(value_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_FULL_RECT);
- value_input_popup->connect("popup_hide", callable_mp(this, &EditorSpinSlider::_value_input_closed));
+ value_input_popup->connect("hidden", 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));
value_input->connect("gui_input", callable_mp(this, &EditorSpinSlider::_value_input_gui_input));
diff --git a/editor/editor_spin_slider.h b/editor/editor_spin_slider.h
index afcaa3e4b6..fd5c3dc5df 100644
--- a/editor/editor_spin_slider.h
+++ b/editor/editor_spin_slider.h
@@ -63,7 +63,7 @@ class EditorSpinSlider : public Range {
Vector2 grabbing_spinner_mouse_pos;
double pre_grab_value = 0.0;
- Popup *value_input_popup = nullptr;
+ Control *value_input_popup = nullptr;
LineEdit *value_input = nullptr;
bool value_input_just_closed = false;
bool value_input_dirty = false;
diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp
index 17b5eb3314..96834f4a6c 100644
--- a/editor/editor_themes.cpp
+++ b/editor/editor_themes.cpp
@@ -240,7 +240,8 @@ static Ref<ImageTexture> editor_generate_icon(int p_index, float p_scale, float
// with integer editor scales.
const bool upsample = !Math::is_equal_approx(Math::round(p_scale), p_scale);
ImageLoaderSVG img_loader;
- img_loader.create_image_from_string(img, editor_icons_sources[p_index], p_scale, upsample, p_convert_colors);
+ Error err = img_loader.create_image_from_string(img, editor_icons_sources[p_index], p_scale, upsample, p_convert_colors);
+ ERR_FAIL_COND_V_MSG(err != OK, Ref<ImageTexture>(), "Failed generating icon, unsupported or invalid SVG data in editor theme.");
if (p_saturation != 1.0) {
img->adjust_bcs(1.0, 1.0, p_saturation);
}
@@ -392,6 +393,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
Color accent_color = EDITOR_GET("interface/theme/accent_color");
Color base_color = EDITOR_GET("interface/theme/base_color");
float contrast = EDITOR_GET("interface/theme/contrast");
+ bool draw_extra_borders = EDITOR_GET("interface/theme/draw_extra_borders");
float icon_saturation = EDITOR_GET("interface/theme/icon_saturation");
float relationship_line_opacity = EDITOR_GET("interface/theme/relationship_line_opacity");
@@ -403,6 +405,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
Color preset_accent_color;
Color preset_base_color;
float preset_contrast = 0;
+ bool preset_draw_extra_borders = false;
const float default_contrast = 0.3;
@@ -439,6 +442,12 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
preset_base_color = Color(0.89, 0.86, 0.79);
// A negative contrast rate looks better for light themes, since it better follows the natural order of UI "elevation".
preset_contrast = -0.08;
+ } else if (preset == "Black (OLED)") {
+ preset_accent_color = Color(0.45, 0.75, 1.0);
+ preset_base_color = Color(0, 0, 0);
+ // The contrast rate value is irrelevant on a fully black theme.
+ preset_contrast = 0.0;
+ preset_draw_extra_borders = true;
} else { // Default
preset_accent_color = Color(0.44, 0.73, 0.98);
preset_base_color = Color(0.21, 0.24, 0.29);
@@ -449,15 +458,18 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
accent_color = preset_accent_color;
base_color = preset_base_color;
contrast = preset_contrast;
+ draw_extra_borders = preset_draw_extra_borders;
EditorSettings::get_singleton()->set_initial_value("interface/theme/accent_color", accent_color);
EditorSettings::get_singleton()->set_initial_value("interface/theme/base_color", base_color);
EditorSettings::get_singleton()->set_initial_value("interface/theme/contrast", contrast);
+ EditorSettings::get_singleton()->set_initial_value("interface/theme/draw_extra_borders", draw_extra_borders);
}
EditorSettings::get_singleton()->set_manually("interface/theme/preset", preset);
EditorSettings::get_singleton()->set_manually("interface/theme/accent_color", accent_color);
EditorSettings::get_singleton()->set_manually("interface/theme/base_color", base_color);
EditorSettings::get_singleton()->set_manually("interface/theme/contrast", contrast);
+ EditorSettings::get_singleton()->set_manually("interface/theme/draw_extra_borders", draw_extra_borders);
// Colors
bool dark_theme = EditorSettings::get_singleton()->is_dark_theme();
@@ -476,6 +488,10 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
const Color dark_color_2 = base_color.lerp(Color(0, 0, 0, 1), contrast * 1.5).clamp();
const Color dark_color_3 = base_color.lerp(Color(0, 0, 0, 1), contrast * 2).clamp();
+ // Only used when the Draw Extra Borders editor setting is enabled.
+ const Color extra_border_color_1 = Color(0.5, 0.5, 0.5);
+ const Color extra_border_color_2 = dark_theme ? Color(0.3, 0.3, 0.3) : Color(0.7, 0.7, 0.7);
+
const Color background_color = dark_color_2;
// White (dark theme) or black (light theme), will be used to generate the rest of the colors
@@ -488,7 +504,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
const Color font_hover_color = mono_color.lerp(base_color, 0.125);
const Color font_focus_color = mono_color.lerp(base_color, 0.125);
const Color font_hover_pressed_color = font_hover_color.lerp(accent_color, 0.74);
- const Color font_disabled_color = Color(mono_color.r, mono_color.g, mono_color.b, 0.3);
+ const Color font_disabled_color = Color(mono_color.r, mono_color.g, mono_color.b, 0.35);
const Color font_readonly_color = Color(mono_color.r, mono_color.g, mono_color.b, 0.65);
const Color font_placeholder_color = Color(mono_color.r, mono_color.g, mono_color.b, 0.6);
const Color selection_color = accent_color * Color(1, 1, 1, 0.4);
@@ -633,10 +649,19 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
Ref<StyleBoxFlat> style_widget = style_default->duplicate();
style_widget->set_default_margin_individual(widget_default_margin.x, widget_default_margin.y, widget_default_margin.x, widget_default_margin.y);
style_widget->set_bg_color(dark_color_1);
- style_widget->set_border_color(dark_color_2);
+ if (draw_extra_borders) {
+ style_widget->set_border_width_all(Math::round(EDSCALE));
+ style_widget->set_border_color(extra_border_color_1);
+ } else {
+ style_widget->set_border_color(dark_color_2);
+ }
Ref<StyleBoxFlat> style_widget_disabled = style_widget->duplicate();
- style_widget_disabled->set_border_color(disabled_color);
+ if (draw_extra_borders) {
+ style_widget_disabled->set_border_color(extra_border_color_2);
+ } else {
+ style_widget_disabled->set_border_color(disabled_color);
+ }
style_widget_disabled->set_bg_color(disabled_bg_color);
Ref<StyleBoxFlat> style_widget_focus = style_widget->duplicate();
@@ -649,7 +674,11 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
Ref<StyleBoxFlat> style_widget_hover = style_widget->duplicate();
style_widget_hover->set_bg_color(mono_color * Color(1, 1, 1, 0.11));
- style_widget_hover->set_border_color(mono_color * Color(1, 1, 1, 0.05));
+ if (draw_extra_borders) {
+ style_widget_hover->set_border_color(extra_border_color_1);
+ } else {
+ style_widget_hover->set_border_color(mono_color * Color(1, 1, 1, 0.05));
+ }
// Style for windows, popups, etc..
Ref<StyleBoxFlat> style_popup = style_default->duplicate();
@@ -990,7 +1019,11 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
style_popup_menu->set_default_margin_individual(EDSCALE, 2 * EDSCALE, EDSCALE, 2 * EDSCALE);
// Always display a border for PopupMenus so they can be distinguished from their background.
style_popup_menu->set_border_width_all(EDSCALE);
- style_popup_menu->set_border_color(dark_color_2);
+ if (draw_extra_borders) {
+ style_popup_menu->set_border_color(extra_border_color_2);
+ } else {
+ style_popup_menu->set_border_color(dark_color_2);
+ }
theme->set_stylebox("panel", "PopupMenu", style_popup_menu);
Ref<StyleBoxFlat> style_menu_hover = style_widget_hover->duplicate();
@@ -1110,7 +1143,13 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
Ref<StyleBoxFlat> style_tree_bg = style_default->duplicate();
// Make Trees easier to distinguish from other controls by using a darker background color.
style_tree_bg->set_bg_color(dark_color_1.lerp(dark_color_2, 0.5));
- style_tree_bg->set_border_color(dark_color_3);
+ if (draw_extra_borders) {
+ style_tree_bg->set_border_width_all(Math::round(EDSCALE));
+ style_tree_bg->set_border_color(extra_border_color_2);
+ } else {
+ style_tree_bg->set_border_color(dark_color_3);
+ }
+
theme->set_stylebox("panel", "Tree", style_tree_bg);
// Tree
@@ -1206,8 +1245,14 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
// ItemList
Ref<StyleBoxFlat> style_itemlist_bg = style_default->duplicate();
style_itemlist_bg->set_bg_color(dark_color_1);
- style_itemlist_bg->set_border_width_all(border_width);
- style_itemlist_bg->set_border_color(dark_color_3);
+
+ if (draw_extra_borders) {
+ style_itemlist_bg->set_border_width_all(Math::round(EDSCALE));
+ style_itemlist_bg->set_border_color(extra_border_color_2);
+ } else {
+ style_itemlist_bg->set_border_width_all(border_width);
+ style_itemlist_bg->set_border_color(dark_color_3);
+ }
Ref<StyleBoxFlat> style_itemlist_cursor = style_default->duplicate();
style_itemlist_cursor->set_draw_center(false);
@@ -1325,14 +1370,21 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
// The original style_widget style has an extra 1 pixel offset that makes LineEdits not align with Buttons,
// so this compensates for that.
style_line_edit->set_default_margin(SIDE_TOP, style_line_edit->get_default_margin(SIDE_TOP) - 1 * EDSCALE);
- // Add a bottom line to make LineEdits more visible, especially in sectioned inspectors
- // such as the Project Settings.
- style_line_edit->set_border_width(SIDE_BOTTOM, Math::round(2 * EDSCALE));
- style_line_edit->set_border_color(dark_color_2);
+
// Don't round the bottom corner to make the line look sharper.
style_tab_selected->set_corner_radius(CORNER_BOTTOM_LEFT, 0);
style_tab_selected->set_corner_radius(CORNER_BOTTOM_RIGHT, 0);
+ if (draw_extra_borders) {
+ style_line_edit->set_border_width_all(Math::round(EDSCALE));
+ style_line_edit->set_border_color(extra_border_color_1);
+ } else {
+ // Add a bottom line to make LineEdits more visible, especially in sectioned inspectors
+ // such as the Project Settings.
+ style_line_edit->set_border_width(SIDE_BOTTOM, Math::round(2 * EDSCALE));
+ style_line_edit->set_border_color(dark_color_2);
+ }
+
Ref<StyleBoxFlat> style_line_edit_disabled = style_line_edit->duplicate();
style_line_edit_disabled->set_border_color(disabled_color);
style_line_edit_disabled->set_bg_color(disabled_bg_color);
@@ -1491,6 +1543,11 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_stylebox("normal", "RichTextLabel", style_tree_bg);
// Editor help.
+ Ref<StyleBoxFlat> style_editor_help = style_default->duplicate();
+ style_editor_help->set_bg_color(dark_color_2);
+ style_editor_help->set_border_color(dark_color_3);
+ theme->set_stylebox("background", "EditorHelp", style_editor_help);
+
theme->set_color("title_color", "EditorHelp", accent_color);
theme->set_color("headline_color", "EditorHelp", mono_color);
theme->set_color("text_color", "EditorHelp", font_color);
@@ -1503,9 +1560,14 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_color("link_color", "EditorHelp", accent_color.lerp(mono_color, 0.8));
theme->set_color("code_color", "EditorHelp", accent_color.lerp(mono_color, 0.6));
theme->set_color("kbd_color", "EditorHelp", accent_color.lerp(property_color, 0.6));
+ theme->set_color("code_bg_color", "EditorHelp", dark_color_3);
+ theme->set_color("kbd_bg_color", "EditorHelp", dark_color_1);
+ theme->set_color("param_bg_color", "EditorHelp", dark_color_1);
theme->set_constant("line_separation", "EditorHelp", Math::round(6 * EDSCALE));
theme->set_constant("table_h_separation", "EditorHelp", 16 * EDSCALE);
theme->set_constant("table_v_separation", "EditorHelp", 6 * EDSCALE);
+ theme->set_constant("text_highlight_h_padding", "EditorHelp", 1 * EDSCALE);
+ theme->set_constant("text_highlight_v_padding", "EditorHelp", 2 * EDSCALE);
// Panel
theme->set_stylebox("panel", "Panel", make_flat_stylebox(dark_color_1, 6, 4, 6, 4, corner_width));
diff --git a/editor/editor_undo_redo_manager.cpp b/editor/editor_undo_redo_manager.cpp
index 09b567fc68..780ea2fd23 100644
--- a/editor/editor_undo_redo_manager.cpp
+++ b/editor/editor_undo_redo_manager.cpp
@@ -33,6 +33,8 @@
#include "core/io/resource.h"
#include "core/os/os.h"
#include "core/templates/local_vector.h"
+#include "editor/debugger/editor_debugger_inspector.h"
+#include "editor/debugger/editor_debugger_node.h"
#include "editor/editor_log.h"
#include "editor/editor_node.h"
#include "scene/main/node.h"
@@ -58,6 +60,10 @@ UndoRedo *EditorUndoRedoManager::get_history_undo_redo(int p_idx) const {
int EditorUndoRedoManager::get_history_id_for_object(Object *p_object) const {
int history_id = INVALID_HISTORY;
+ if (Object::cast_to<EditorDebuggerRemoteObject>(p_object)) {
+ return REMOTE_HISTORY;
+ }
+
if (Node *node = Object::cast_to<Node>(p_object)) {
Node *edited_scene = EditorNode::get_singleton()->get_edited_scene();
@@ -109,9 +115,14 @@ EditorUndoRedoManager::History &EditorUndoRedoManager::get_history_for_object(Ob
}
void EditorUndoRedoManager::create_action_for_history(const String &p_name, int p_history_id, UndoRedo::MergeMode p_mode) {
- pending_action.action_name = p_name;
- pending_action.timestamp = OS::get_singleton()->get_unix_time();
- pending_action.merge_mode = p_mode;
+ if (pending_action.history_id != INVALID_HISTORY) {
+ // Nested action.
+ p_history_id = pending_action.history_id;
+ } else {
+ pending_action.action_name = p_name;
+ pending_action.timestamp = OS::get_singleton()->get_unix_time();
+ pending_action.merge_mode = p_mode;
+ }
if (p_history_id != INVALID_HISTORY) {
pending_action.history_id = p_history_id;
@@ -228,6 +239,12 @@ void EditorUndoRedoManager::commit_action(bool p_execute) {
history.undo_redo->commit_action(p_execute);
history.redo_stack.clear();
+ if (history.undo_redo->get_action_level() > 0) {
+ // Nested action.
+ is_committing = false;
+ return;
+ }
+
if (!history.undo_stack.is_empty()) {
const Action &prev_action = history.undo_stack.back()->get();
if (pending_action.merge_mode != UndoRedo::MERGE_DISABLE && pending_action.merge_mode == prev_action.merge_mode && pending_action.action_name == prev_action.action_name) {
@@ -253,27 +270,9 @@ bool EditorUndoRedoManager::undo() {
return false;
}
- int selected_history = INVALID_HISTORY;
- double global_timestamp = 0;
-
- // Pick the history with greatest last action timestamp (either global or current scene).
- {
- History &history = get_or_create_history(GLOBAL_HISTORY);
- if (!history.undo_stack.is_empty()) {
- selected_history = history.id;
- global_timestamp = history.undo_stack.back()->get().timestamp;
- }
- }
-
- {
- History &history = get_or_create_history(EditorNode::get_editor_data().get_current_edited_scene_history_id());
- if (!history.undo_stack.is_empty() && history.undo_stack.back()->get().timestamp > global_timestamp) {
- selected_history = history.id;
- }
- }
-
- if (selected_history != INVALID_HISTORY) {
- return undo_history(selected_history);
+ History *selected_history = _get_newest_undo();
+ if (selected_history) {
+ return undo_history(selected_history->id);
}
return false;
}
@@ -311,6 +310,14 @@ bool EditorUndoRedoManager::redo() {
}
{
+ History &history = get_or_create_history(REMOTE_HISTORY);
+ if (!history.redo_stack.is_empty() && history.redo_stack.back()->get().timestamp < global_timestamp) {
+ selected_history = history.id;
+ global_timestamp = history.redo_stack.back()->get().timestamp;
+ }
+ }
+
+ {
History &history = get_or_create_history(EditorNode::get_editor_data().get_current_edited_scene_history_id());
if (!history.redo_stack.is_empty() && history.redo_stack.back()->get().timestamp < global_timestamp) {
selected_history = history.id;
@@ -355,7 +362,7 @@ bool EditorUndoRedoManager::is_history_unsaved(int p_id) {
bool EditorUndoRedoManager::has_undo() {
for (const KeyValue<int, History> &E : history_map) {
- if ((E.key == GLOBAL_HISTORY || E.key == EditorNode::get_editor_data().get_current_edited_scene_history_id()) && !E.value.undo_stack.is_empty()) {
+ if ((E.key == GLOBAL_HISTORY || E.key == REMOTE_HISTORY || E.key == EditorNode::get_editor_data().get_current_edited_scene_history_id()) && !E.value.undo_stack.is_empty()) {
return true;
}
}
@@ -364,7 +371,7 @@ bool EditorUndoRedoManager::has_undo() {
bool EditorUndoRedoManager::has_redo() {
for (const KeyValue<int, History> &E : history_map) {
- if ((E.key == GLOBAL_HISTORY || E.key == EditorNode::get_editor_data().get_current_edited_scene_history_id()) && !E.value.redo_stack.is_empty()) {
+ if ((E.key == GLOBAL_HISTORY || E.key == REMOTE_HISTORY || E.key == EditorNode::get_editor_data().get_current_edited_scene_history_id()) && !E.value.redo_stack.is_empty()) {
return true;
}
}
@@ -373,7 +380,11 @@ bool EditorUndoRedoManager::has_redo() {
void EditorUndoRedoManager::clear_history(bool p_increase_version, int p_idx) {
if (p_idx != INVALID_HISTORY) {
- get_or_create_history(p_idx).undo_redo->clear_history(p_increase_version);
+ History &history = get_or_create_history(p_idx);
+ history.undo_redo->clear_history(p_increase_version);
+ history.undo_stack.clear();
+ history.redo_stack.clear();
+
if (!p_increase_version) {
set_history_as_saved(p_idx);
}
@@ -390,25 +401,7 @@ void EditorUndoRedoManager::clear_history(bool p_increase_version, int p_idx) {
String EditorUndoRedoManager::get_current_action_name() {
if (has_undo()) {
- History *selected_history = nullptr;
- double global_timestamp = 0;
-
- // Pick the history with greatest last action timestamp (either global or current scene).
- {
- History &history = get_or_create_history(GLOBAL_HISTORY);
- if (!history.undo_stack.is_empty()) {
- selected_history = &history;
- global_timestamp = history.undo_stack.back()->get().timestamp;
- }
- }
-
- {
- History &history = get_or_create_history(EditorNode::get_editor_data().get_current_edited_scene_history_id());
- if (!history.undo_stack.is_empty() && history.undo_stack.back()->get().timestamp > global_timestamp) {
- selected_history = &history;
- }
- }
-
+ History *selected_history = _get_newest_undo();
if (selected_history) {
return selected_history->undo_redo->get_current_action_name();
}
@@ -416,6 +409,16 @@ String EditorUndoRedoManager::get_current_action_name() {
return "";
}
+int EditorUndoRedoManager::get_current_action_history_id() {
+ if (has_undo()) {
+ History *selected_history = _get_newest_undo();
+ if (selected_history) {
+ return selected_history->id;
+ }
+ }
+ return INVALID_HISTORY;
+}
+
void EditorUndoRedoManager::discard_history(int p_idx, bool p_erase_from_map) {
ERR_FAIL_COND(!history_map.has(p_idx));
History &history = history_map[p_idx];
@@ -430,6 +433,37 @@ void EditorUndoRedoManager::discard_history(int p_idx, bool p_erase_from_map) {
}
}
+EditorUndoRedoManager::History *EditorUndoRedoManager::_get_newest_undo() {
+ History *selected_history = nullptr;
+ double global_timestamp = 0;
+
+ // Pick the history with greatest last action timestamp (either global or current scene).
+ {
+ History &history = get_or_create_history(GLOBAL_HISTORY);
+ if (!history.undo_stack.is_empty()) {
+ selected_history = &history;
+ global_timestamp = history.undo_stack.back()->get().timestamp;
+ }
+ }
+
+ {
+ History &history = get_or_create_history(REMOTE_HISTORY);
+ if (!history.undo_stack.is_empty() && history.undo_stack.back()->get().timestamp > global_timestamp) {
+ selected_history = &history;
+ global_timestamp = history.undo_stack.back()->get().timestamp;
+ }
+ }
+
+ {
+ History &history = get_or_create_history(EditorNode::get_editor_data().get_current_edited_scene_history_id());
+ if (!history.undo_stack.is_empty() && history.undo_stack.back()->get().timestamp > global_timestamp) {
+ selected_history = &history;
+ }
+ }
+
+ return selected_history;
+}
+
void EditorUndoRedoManager::_bind_methods() {
ClassDB::bind_method(D_METHOD("create_action", "name", "merge_mode", "custom_context"), &EditorUndoRedoManager::create_action, DEFVAL(UndoRedo::MERGE_DISABLE), DEFVAL((Object *)nullptr));
ClassDB::bind_method(D_METHOD("commit_action", "execute"), &EditorUndoRedoManager::commit_action, DEFVAL(true));
@@ -465,6 +499,7 @@ void EditorUndoRedoManager::_bind_methods() {
ADD_SIGNAL(MethodInfo("version_changed"));
BIND_ENUM_CONSTANT(GLOBAL_HISTORY);
+ BIND_ENUM_CONSTANT(REMOTE_HISTORY);
BIND_ENUM_CONSTANT(INVALID_HISTORY);
}
diff --git a/editor/editor_undo_redo_manager.h b/editor/editor_undo_redo_manager.h
index 60bcd059df..74911180f0 100644
--- a/editor/editor_undo_redo_manager.h
+++ b/editor/editor_undo_redo_manager.h
@@ -41,6 +41,7 @@ class EditorUndoRedoManager : public RefCounted {
public:
enum SpecialHistory {
GLOBAL_HISTORY = 0,
+ REMOTE_HISTORY = -9,
INVALID_HISTORY = -99,
};
@@ -65,6 +66,8 @@ private:
bool is_committing = false;
+ History *_get_newest_undo();
+
protected:
static void _bind_methods();
@@ -126,6 +129,7 @@ public:
bool has_redo();
String get_current_action_name();
+ int get_current_action_history_id();
void discard_history(int p_idx, bool p_erase_from_map = true);
~EditorUndoRedoManager();
diff --git a/editor/editor_vcs_interface.cpp b/editor/editor_vcs_interface.cpp
index d22c7bd149..3a6516fbfa 100644
--- a/editor/editor_vcs_interface.cpp
+++ b/editor/editor_vcs_interface.cpp
@@ -57,7 +57,7 @@ void EditorVCSInterface::set_credentials(String p_username, String p_password, S
}
List<String> EditorVCSInterface::get_remotes() {
- TypedArray<Dictionary> result;
+ TypedArray<String> result;
if (!GDVIRTUAL_CALL(_get_remotes, result)) {
UNIMPLEMENTED();
return {};
@@ -137,7 +137,7 @@ List<EditorVCSInterface::Commit> EditorVCSInterface::get_previous_commits(int p_
}
List<String> EditorVCSInterface::get_branch_list() {
- TypedArray<Dictionary> result;
+ TypedArray<String> result;
if (!GDVIRTUAL_CALL(_get_branch_list, result)) {
UNIMPLEMENTED();
return {};
diff --git a/editor/editor_vcs_interface.h b/editor/editor_vcs_interface.h
index 5d4901cefa..c93fe4a672 100644
--- a/editor/editor_vcs_interface.h
+++ b/editor/editor_vcs_interface.h
@@ -117,8 +117,8 @@ protected:
GDVIRTUAL0R(bool, _shut_down);
GDVIRTUAL0R(String, _get_vcs_name);
GDVIRTUAL1R(TypedArray<Dictionary>, _get_previous_commits, int);
- GDVIRTUAL0R(TypedArray<Dictionary>, _get_branch_list);
- GDVIRTUAL0R(TypedArray<Dictionary>, _get_remotes);
+ GDVIRTUAL0R(TypedArray<String>, _get_branch_list);
+ GDVIRTUAL0R(TypedArray<String>, _get_remotes);
GDVIRTUAL1(_create_branch, String);
GDVIRTUAL1(_remove_branch, String);
GDVIRTUAL2(_create_remote, String, String);
diff --git a/editor/event_listener_line_edit.cpp b/editor/event_listener_line_edit.cpp
index e4c35a5b81..1b081f9091 100644
--- a/editor/event_listener_line_edit.cpp
+++ b/editor/event_listener_line_edit.cpp
@@ -30,6 +30,72 @@
#include "editor/event_listener_line_edit.h"
+#include "core/input/input_map.h"
+
+// Maps to 2*axis if value is neg, or 2*axis+1 if value is pos.
+static const char *_joy_axis_descriptions[(size_t)JoyAxis::MAX * 2] = {
+ TTRC("Left Stick Left, Joystick 0 Left"),
+ TTRC("Left Stick Right, Joystick 0 Right"),
+ TTRC("Left Stick Up, Joystick 0 Up"),
+ TTRC("Left Stick Down, Joystick 0 Down"),
+ TTRC("Right Stick Left, Joystick 1 Left"),
+ TTRC("Right Stick Right, Joystick 1 Right"),
+ TTRC("Right Stick Up, Joystick 1 Up"),
+ TTRC("Right Stick Down, Joystick 1 Down"),
+ TTRC("Joystick 2 Left"),
+ TTRC("Left Trigger, Sony L2, Xbox LT, Joystick 2 Right"),
+ TTRC("Joystick 2 Up"),
+ TTRC("Right Trigger, Sony R2, Xbox RT, Joystick 2 Down"),
+ TTRC("Joystick 3 Left"),
+ TTRC("Joystick 3 Right"),
+ TTRC("Joystick 3 Up"),
+ TTRC("Joystick 3 Down"),
+ TTRC("Joystick 4 Left"),
+ TTRC("Joystick 4 Right"),
+ TTRC("Joystick 4 Up"),
+ TTRC("Joystick 4 Down"),
+};
+
+String EventListenerLineEdit::get_event_text(const Ref<InputEvent> &p_event, bool p_include_device) {
+ ERR_FAIL_COND_V_MSG(p_event.is_null(), String(), "Provided event is not a valid instance of InputEvent");
+
+ String text = p_event->as_text();
+
+ Ref<InputEventKey> key = p_event;
+ if (key.is_valid() && key->is_command_or_control_autoremap()) {
+#ifdef MACOS_ENABLED
+ text = text.replace("Command", "Command/Ctrl");
+#else
+ text = text.replace("Ctrl", "Command/Ctrl");
+#endif
+ }
+ Ref<InputEventMouse> mouse = p_event;
+ Ref<InputEventJoypadMotion> jp_motion = p_event;
+ Ref<InputEventJoypadButton> jp_button = p_event;
+ if (jp_motion.is_valid()) {
+ // Joypad motion events will display slightly differently than what the event->as_text() provides. See #43660.
+ String desc = TTR("Unknown Joypad Axis");
+ if (jp_motion->get_axis() < JoyAxis::MAX) {
+ desc = RTR(_joy_axis_descriptions[2 * (size_t)jp_motion->get_axis() + (jp_motion->get_axis_value() < 0 ? 0 : 1)]);
+ }
+
+ text = vformat("Joypad Axis %s %s (%s)", itos((int64_t)jp_motion->get_axis()), jp_motion->get_axis_value() < 0 ? "-" : "+", desc);
+ }
+ if (p_include_device && (mouse.is_valid() || jp_button.is_valid() || jp_motion.is_valid())) {
+ String device_string = get_device_string(p_event->get_device());
+ text += vformat(" - %s", device_string);
+ }
+
+ return text;
+}
+
+String EventListenerLineEdit::get_device_string(int p_device) {
+ if (p_device == InputMap::ALL_DEVICES) {
+ return TTR("All Devices");
+ }
+ return TTR("Device") + " " + itos(p_device);
+}
+
bool EventListenerLineEdit::_is_event_allowed(const Ref<InputEvent> &p_event) const {
const Ref<InputEventMouseButton> mb = p_event;
const Ref<InputEventKey> k = p_event;
@@ -71,7 +137,7 @@ void EventListenerLineEdit::gui_input(const Ref<InputEvent> &p_event) {
}
event = p_event;
- set_text(event->as_text());
+ set_text(get_event_text(event, false));
emit_signal("event_changed", event);
}
diff --git a/editor/event_listener_line_edit.h b/editor/event_listener_line_edit.h
index c4cd5e4511..487efbc368 100644
--- a/editor/event_listener_line_edit.h
+++ b/editor/event_listener_line_edit.h
@@ -61,6 +61,9 @@ protected:
static void _bind_methods();
public:
+ static String get_event_text(const Ref<InputEvent> &p_event, bool p_include_device);
+ static String get_device_string(int p_device);
+
Ref<InputEvent> get_event() const;
void clear_event();
diff --git a/editor/export/editor_export_platform.cpp b/editor/export/editor_export_platform.cpp
index 7c5c7da2ef..d0dcbc3bfd 100644
--- a/editor/export/editor_export_platform.cpp
+++ b/editor/export/editor_export_platform.cpp
@@ -32,7 +32,7 @@
#include "core/config/project_settings.h"
#include "core/crypto/crypto_core.h"
-#include "core/extension/native_extension.h"
+#include "core/extension/gdextension.h"
#include "core/io/file_access_encrypted.h"
#include "core/io/file_access_pack.h" // PACK_HEADER_MAGIC, PACK_FORMAT_VERSION
#include "core/io/zip_io.h"
@@ -442,10 +442,11 @@ HashSet<String> EditorExportPlatform::get_features(const Ref<EditorExportPreset>
result.insert(E);
}
+ result.insert("template");
if (p_debug) {
- result.insert("debug");
+ result.insert("template_debug");
} else {
- result.insert("release");
+ result.insert("template_release");
}
if (!p_preset->get_custom_features().is_empty()) {
@@ -1034,7 +1035,7 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> &
return err;
}
// Now actual remapped file:
- sarr = FileAccess::get_file_as_array(export_path);
+ sarr = FileAccess::get_file_as_bytes(export_path);
err = p_func(p_udata, export_path, sarr, idx, total, enc_in_filters, enc_ex_filters, key);
if (err != OK) {
return err;
@@ -1053,7 +1054,7 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> &
if (importer_type == "keep") {
//just keep file as-is
- Vector<uint8_t> array = FileAccess::get_file_as_array(path);
+ Vector<uint8_t> array = FileAccess::get_file_as_bytes(path);
err = p_func(p_udata, path, array, idx, total, enc_in_filters, enc_ex_filters, key);
if (err != OK) {
@@ -1086,14 +1087,14 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> &
String remap = F;
if (remap == "path") {
String remapped_path = config->get_value("remap", remap);
- Vector<uint8_t> array = FileAccess::get_file_as_array(remapped_path);
+ Vector<uint8_t> array = FileAccess::get_file_as_bytes(remapped_path);
err = p_func(p_udata, remapped_path, array, idx, total, enc_in_filters, enc_ex_filters, key);
} else if (remap.begins_with("path.")) {
String feature = remap.get_slice(".", 1);
if (remap_features.has(feature)) {
String remapped_path = config->get_value("remap", remap);
- Vector<uint8_t> array = FileAccess::get_file_as_array(remapped_path);
+ Vector<uint8_t> array = FileAccess::get_file_as_bytes(remapped_path);
err = p_func(p_udata, remapped_path, array, idx, total, enc_in_filters, enc_ex_filters, key);
}
}
@@ -1104,7 +1105,7 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> &
}
//also save the .import file
- Vector<uint8_t> array = FileAccess::get_file_as_array(path + ".import");
+ Vector<uint8_t> array = FileAccess::get_file_as_bytes(path + ".import");
err = p_func(p_udata, path + ".import", array, idx, total, enc_in_filters, enc_ex_filters, key);
if (err != OK) {
@@ -1164,7 +1165,7 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> &
path_remaps.push_back(export_path);
}
- Vector<uint8_t> array = FileAccess::get_file_as_array(export_path);
+ Vector<uint8_t> array = FileAccess::get_file_as_bytes(export_path);
err = p_func(p_udata, export_path, array, idx, total, enc_in_filters, enc_ex_filters, key);
if (err != OK) {
return err;
@@ -1244,14 +1245,14 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> &
String icon = GLOBAL_GET("application/config/icon");
String splash = GLOBAL_GET("application/boot_splash/image");
if (!icon.is_empty() && FileAccess::exists(icon)) {
- Vector<uint8_t> array = FileAccess::get_file_as_array(icon);
+ Vector<uint8_t> array = FileAccess::get_file_as_bytes(icon);
err = p_func(p_udata, icon, array, idx, total, enc_in_filters, enc_ex_filters, key);
if (err != OK) {
return err;
}
}
if (!splash.is_empty() && FileAccess::exists(splash) && icon != splash) {
- Vector<uint8_t> array = FileAccess::get_file_as_array(splash);
+ Vector<uint8_t> array = FileAccess::get_file_as_bytes(splash);
err = p_func(p_udata, splash, array, idx, total, enc_in_filters, enc_ex_filters, key);
if (err != OK) {
return err;
@@ -1259,16 +1260,16 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> &
}
String resource_cache_file = ResourceUID::get_cache_file();
if (FileAccess::exists(resource_cache_file)) {
- Vector<uint8_t> array = FileAccess::get_file_as_array(resource_cache_file);
+ Vector<uint8_t> array = FileAccess::get_file_as_bytes(resource_cache_file);
err = p_func(p_udata, resource_cache_file, array, idx, total, enc_in_filters, enc_ex_filters, key);
if (err != OK) {
return err;
}
}
- String extension_list_config_file = NativeExtension::get_extension_list_config_file();
+ String extension_list_config_file = GDExtension::get_extension_list_config_file();
if (FileAccess::exists(extension_list_config_file)) {
- Vector<uint8_t> array = FileAccess::get_file_as_array(extension_list_config_file);
+ Vector<uint8_t> array = FileAccess::get_file_as_bytes(extension_list_config_file);
err = p_func(p_udata, extension_list_config_file, array, idx, total, enc_in_filters, enc_ex_filters, key);
if (err != OK) {
return err;
@@ -1282,7 +1283,7 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> &
// Try using user provided data file.
String ts_data = "res://" + TS->get_support_data_filename();
if (FileAccess::exists(ts_data)) {
- Vector<uint8_t> array = FileAccess::get_file_as_array(ts_data);
+ Vector<uint8_t> array = FileAccess::get_file_as_bytes(ts_data);
err = p_func(p_udata, ts_data, array, idx, total, enc_in_filters, enc_ex_filters, key);
if (err != OK) {
return err;
@@ -1291,7 +1292,7 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> &
// Use default text server data.
String icu_data_file = EditorPaths::get_singleton()->get_cache_dir().path_join("tmp_icu_data");
TS->save_support_data(icu_data_file);
- Vector<uint8_t> array = FileAccess::get_file_as_array(icu_data_file);
+ Vector<uint8_t> array = FileAccess::get_file_as_bytes(icu_data_file);
err = p_func(p_udata, ts_data, array, idx, total, enc_in_filters, enc_ex_filters, key);
DirAccess::remove_file_or_error(icu_data_file);
if (err != OK) {
@@ -1304,7 +1305,7 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> &
String config_file = "project.binary";
String engine_cfb = EditorPaths::get_singleton()->get_cache_dir().path_join("tmp" + config_file);
ProjectSettings::get_singleton()->save_custom(engine_cfb, custom_map, custom_list);
- Vector<uint8_t> data = FileAccess::get_file_as_array(engine_cfb);
+ Vector<uint8_t> data = FileAccess::get_file_as_bytes(engine_cfb);
DirAccess::remove_file_or_error(engine_cfb);
return p_func(p_udata, "res://" + config_file, data, idx, total, enc_in_filters, enc_ex_filters, key);
diff --git a/editor/export/editor_export_plugin.cpp b/editor/export/editor_export_plugin.cpp
index 78d4f93dfe..f0e841f307 100644
--- a/editor/export/editor_export_plugin.cpp
+++ b/editor/export/editor_export_plugin.cpp
@@ -148,10 +148,8 @@ bool EditorExportPlugin::_begin_customize_resources(const Ref<EditorExportPlatfo
Ref<Resource> EditorExportPlugin::_customize_resource(const Ref<Resource> &p_resource, const String &p_path) {
Ref<Resource> ret;
- if (GDVIRTUAL_REQUIRED_CALL(_customize_resource, p_resource, p_path, ret)) {
- return ret;
- }
- return Ref<Resource>();
+ GDVIRTUAL_REQUIRED_CALL(_customize_resource, p_resource, p_path, ret);
+ return ret;
}
bool EditorExportPlugin::_begin_customize_scenes(const Ref<EditorExportPlatform> &p_platform, const Vector<String> &p_features) const {
@@ -162,18 +160,14 @@ bool EditorExportPlugin::_begin_customize_scenes(const Ref<EditorExportPlatform>
Node *EditorExportPlugin::_customize_scene(Node *p_root, const String &p_path) {
Node *ret = nullptr;
- if (GDVIRTUAL_REQUIRED_CALL(_customize_scene, p_root, p_path, ret)) {
- return ret;
- }
- return nullptr;
+ GDVIRTUAL_REQUIRED_CALL(_customize_scene, p_root, p_path, ret);
+ return ret;
}
uint64_t EditorExportPlugin::_get_customization_configuration_hash() const {
uint64_t ret = 0;
- if (GDVIRTUAL_REQUIRED_CALL(_get_customization_configuration_hash, ret)) {
- return ret;
- }
- return 0;
+ GDVIRTUAL_REQUIRED_CALL(_get_customization_configuration_hash, ret);
+ return ret;
}
void EditorExportPlugin::_end_customize_scenes() {
@@ -186,10 +180,8 @@ void EditorExportPlugin::_end_customize_resources() {
String EditorExportPlugin::_get_name() const {
String ret;
- if (GDVIRTUAL_REQUIRED_CALL(_get_name, ret)) {
- return ret;
- }
- return "";
+ GDVIRTUAL_REQUIRED_CALL(_get_name, ret);
+ return ret;
}
void EditorExportPlugin::_export_file(const String &p_path, const String &p_type, const HashSet<String> &p_features) {
diff --git a/editor/export/editor_export_plugin.h b/editor/export/editor_export_plugin.h
index 3f37ed40be..88eeaf821d 100644
--- a/editor/export/editor_export_plugin.h
+++ b/editor/export/editor_export_plugin.h
@@ -31,7 +31,7 @@
#ifndef EDITOR_EXPORT_PLUGIN_H
#define EDITOR_EXPORT_PLUGIN_H
-#include "core/extension/native_extension.h"
+#include "core/extension/gdextension.h"
#include "editor_export_preset.h"
#include "editor_export_shared_object.h"
#include "scene/main/node.h"
diff --git a/editor/export/export_template_manager.cpp b/editor/export/export_template_manager.cpp
index 9ebf4d795a..84766a5bef 100644
--- a/editor/export/export_template_manager.cpp
+++ b/editor/export/export_template_manager.cpp
@@ -40,6 +40,7 @@
#include "editor/editor_settings.h"
#include "editor/progress_dialog.h"
#include "scene/gui/file_dialog.h"
+#include "scene/gui/menu_button.h"
#include "scene/gui/separator.h"
#include "scene/gui/tree.h"
#include "scene/main/http_request.h"
diff --git a/editor/export/project_export.cpp b/editor/export/project_export.cpp
index 6ff3539708..f5c5aafb5d 100644
--- a/editor/export/project_export.cpp
+++ b/editor/export/project_export.cpp
@@ -37,9 +37,16 @@
#include "editor/editor_node.h"
#include "editor/editor_properties.h"
#include "editor/editor_scale.h"
+#include "editor/editor_settings.h"
#include "editor/export/editor_export.h"
+#include "scene/gui/check_box.h"
#include "scene/gui/check_button.h"
+#include "scene/gui/item_list.h"
#include "scene/gui/link_button.h"
+#include "scene/gui/menu_button.h"
+#include "scene/gui/option_button.h"
+#include "scene/gui/split_container.h"
+#include "scene/gui/texture_rect.h"
#include "scene/gui/tree.h"
void ProjectExportDialog::_theme_changed() {
diff --git a/editor/fbx_importer_manager.cpp b/editor/fbx_importer_manager.cpp
new file mode 100644
index 0000000000..b258fe7e09
--- /dev/null
+++ b/editor/fbx_importer_manager.cpp
@@ -0,0 +1,158 @@
+/*************************************************************************/
+/* fbx_importer_manager.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 "fbx_importer_manager.h"
+
+#include "editor/editor_scale.h"
+#include "editor/editor_settings.h"
+#include "scene/gui/link_button.h"
+
+void FBXImporterManager::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_READY: {
+ connect("confirmed", callable_mp(this, &FBXImporterManager::_path_confirmed));
+ } break;
+ }
+}
+
+void FBXImporterManager::show_dialog(bool p_exclusive) {
+ String fbx2gltf_path = EDITOR_GET("filesystem/import/fbx/fbx2gltf_path");
+ fbx_path->set_text(fbx2gltf_path);
+ _validate_path(fbx2gltf_path);
+
+ set_flag(Window::FLAG_BORDERLESS, p_exclusive); // Avoid closing accidentally .
+ set_close_on_escape(!p_exclusive);
+
+ popup_centered();
+}
+
+void FBXImporterManager::_validate_path(const String &p_path) {
+ String error;
+ bool success = false;
+
+ if (p_path == "") {
+ error = TTR("Path to FBX2glTF executable is empty.");
+ } else if (!FileAccess::exists(p_path)) {
+ error = TTR("Path to FBX2glTF executable is invalid.");
+ } else {
+ List<String> args;
+ args.push_back("--version");
+ int exitcode;
+ Error err = OS::get_singleton()->execute(p_path, args, nullptr, &exitcode);
+
+ if (err == OK && exitcode == 0) {
+ success = true;
+ } else {
+ error = TTR("Error executing this file (wrong version or architecture).");
+ }
+ }
+
+ if (success) {
+ path_status->set_text(TTR("FBX2glTF executable is valid."));
+ path_status->add_theme_color_override("font_color", path_status->get_theme_color(SNAME("success_color"), SNAME("Editor")));
+ get_ok_button()->set_disabled(false);
+ } else {
+ path_status->set_text(error);
+ path_status->add_theme_color_override("font_color", path_status->get_theme_color(SNAME("error_color"), SNAME("Editor")));
+ get_ok_button()->set_disabled(true);
+ }
+}
+
+void FBXImporterManager::_select_file(const String &p_path) {
+ fbx_path->set_text(p_path);
+ _validate_path(p_path);
+}
+
+void FBXImporterManager::_path_confirmed() {
+ String path = fbx_path->get_text();
+ EditorSettings::get_singleton()->set("filesystem/import/fbx/fbx2gltf_path", path);
+ EditorSettings::get_singleton()->save();
+}
+
+void FBXImporterManager::_browse_install() {
+ if (fbx_path->get_text() != String()) {
+ browse_dialog->set_current_file(fbx_path->get_text());
+ }
+
+ browse_dialog->popup_centered_ratio();
+}
+
+FBXImporterManager *FBXImporterManager::singleton = nullptr;
+
+FBXImporterManager::FBXImporterManager() {
+ singleton = this;
+
+ set_title(TTR("Configure FBX Importer"));
+
+ VBoxContainer *vb = memnew(VBoxContainer);
+ vb->add_child(memnew(Label(TTR("FBX2glTF is required for importing FBX files.\nPlease download it and provide a valid path to the binary:"))));
+ LinkButton *lb = memnew(LinkButton);
+ lb->set_text(TTR("Click this link to download FBX2glTF"));
+ lb->set_uri("https://godotengine.org/fbx-import");
+ vb->add_child(lb);
+
+ HBoxContainer *hb = memnew(HBoxContainer);
+
+ fbx_path = memnew(LineEdit);
+ fbx_path->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ hb->add_child(fbx_path);
+ fbx_path_browse = memnew(Button);
+ hb->add_child(fbx_path_browse);
+ fbx_path_browse->set_text(TTR("Browse"));
+ fbx_path_browse->connect("pressed", callable_mp(this, &FBXImporterManager::_browse_install));
+ hb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ hb->set_custom_minimum_size(Size2(400 * EDSCALE, 0));
+
+ vb->add_child(hb);
+
+ path_status = memnew(Label);
+ vb->add_child(path_status);
+
+ add_child(vb);
+
+ fbx_path->connect("text_changed", callable_mp(this, &FBXImporterManager::_validate_path));
+
+ get_ok_button()->set_text(TTR("Confirm Path"));
+
+ browse_dialog = memnew(EditorFileDialog);
+ browse_dialog->set_access(EditorFileDialog::ACCESS_FILESYSTEM);
+ browse_dialog->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE);
+#if defined(X11_ENABLED)
+ browse_dialog->add_filter("FBX2glTF-linux-x86_64");
+#elif defined(OSX_ENABLED)
+ browse_dialog->add_filter("FBX2glTF-macos-x86_64");
+#elif defined(WINDOWS_ENABLED)
+ browse_dialog->add_filter("FBX2glTF-windows-x86_64");
+#endif
+
+ browse_dialog->connect("file_selected", callable_mp(this, &FBXImporterManager::_select_file));
+
+ add_child(browse_dialog);
+}
diff --git a/editor/fbx_importer_manager.h b/editor/fbx_importer_manager.h
new file mode 100644
index 0000000000..28de761519
--- /dev/null
+++ b/editor/fbx_importer_manager.h
@@ -0,0 +1,66 @@
+/*************************************************************************/
+/* fbx_importer_manager.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 FBX_IMPORTER_MANAGER_H
+#define FBX_IMPORTER_MANAGER_H
+
+#include "editor/editor_file_dialog.h"
+#include "scene/gui/dialogs.h"
+#include "scene/gui/line_edit.h"
+
+class FBXImporterManager : public ConfirmationDialog {
+ GDCLASS(FBXImporterManager, ConfirmationDialog)
+
+ Label *message = nullptr;
+ LineEdit *fbx_path = nullptr;
+ Button *fbx_path_browse = nullptr;
+ EditorFileDialog *browse_dialog = nullptr;
+ Label *path_status = nullptr;
+
+ void _validate_path(const String &p_path);
+ void _select_file(const String &p_path);
+ void _path_confirmed();
+ void _browse_install();
+ void _link_clicked();
+
+ static FBXImporterManager *singleton;
+
+protected:
+ void _notification(int p_what);
+
+public:
+ static FBXImporterManager *get_singleton() { return singleton; }
+
+ void show_dialog(bool p_exclusive = false);
+
+ FBXImporterManager();
+};
+
+#endif // FBX_IMPORTER_MANAGER_H
diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp
index 62bcf0b193..6316a7f545 100644
--- a/editor/filesystem_dock.cpp
+++ b/editor/filesystem_dock.cpp
@@ -42,6 +42,7 @@
#include "editor/editor_resource_preview.h"
#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
+#include "editor/import/resource_importer_scene.h"
#include "editor/import_dock.h"
#include "editor/scene_create_dialog.h"
#include "editor/scene_tree_dock.h"
@@ -511,7 +512,15 @@ void FileSystemDock::_tree_multi_selected(Object *p_item, int p_column, bool p_s
}
}
-String FileSystemDock::get_selected_path() const {
+Vector<String> FileSystemDock::get_selected_paths() const {
+ return _tree_get_selected(false);
+}
+
+String FileSystemDock::get_current_path() const {
+ return path;
+}
+
+String FileSystemDock::get_current_directory() const {
if (path.ends_with("/")) {
return path;
} else {
@@ -519,10 +528,6 @@ String FileSystemDock::get_selected_path() const {
}
}
-String FileSystemDock::get_current_path() const {
- return path;
-}
-
void FileSystemDock::_set_current_path_text(const String &p_path) {
if (p_path == "Favorites") {
current_path->set_text(TTR("Favorites"));
@@ -1409,7 +1414,7 @@ void FileSystemDock::_update_dependencies_after_move(const HashMap<String, Strin
Error err = ResourceLoader::rename_dependencies(file, p_renames);
if (err == OK) {
if (ResourceLoader::get_resource_type(file) == "PackedScene") {
- EditorNode::get_singleton()->reload_scene(file);
+ callable_mp(EditorNode::get_singleton(), &EditorNode::reload_scene).bind(file).call_deferred();
}
} else {
EditorNode::get_singleton()->add_io_error(TTR("Unable to update dependencies:") + "\n" + remaps[i] + "\n");
@@ -1726,7 +1731,7 @@ void FileSystemDock::_move_operation_confirm(const String &p_to_path, bool p_ove
}
}
-Vector<String> FileSystemDock::_tree_get_selected(bool remove_self_inclusion) {
+Vector<String> FileSystemDock::_tree_get_selected(bool remove_self_inclusion) const {
// Build a list of selected items with the active one at the first position.
Vector<String> selected_strings;
@@ -1847,8 +1852,8 @@ void FileSystemDock::_file_option(int p_option, const Vector<String> &p_selected
}
} break;
- case FILE_INSTANCE: {
- // Instance all selected scenes.
+ case FILE_INSTANTIATE: {
+ // Instantiate all selected scenes.
Vector<String> paths;
for (int i = 0; i < p_selected.size(); i++) {
String fpath = p_selected[i];
@@ -1857,7 +1862,7 @@ void FileSystemDock::_file_option(int p_option, const Vector<String> &p_selected
}
}
if (!paths.is_empty()) {
- emit_signal(SNAME("instance"), paths);
+ emit_signal(SNAME("instantiate"), paths);
}
} break;
@@ -2072,7 +2077,7 @@ void FileSystemDock::_resource_created() {
return;
}
- Variant c = new_resource_dialog->instance_selected();
+ Variant c = new_resource_dialog->instantiate_selected();
ERR_FAIL_COND(!c);
Resource *r = Object::cast_to<Resource>(c);
@@ -2535,7 +2540,7 @@ void FileSystemDock::_file_and_folders_fill_popup(PopupMenu *p_popup, Vector<Str
} else {
p_popup->add_icon_item(get_theme_icon(SNAME("Load"), SNAME("EditorIcons")), TTR("Open Scenes"), FILE_OPEN);
}
- p_popup->add_icon_item(get_theme_icon(SNAME("Instance"), SNAME("EditorIcons")), TTR("Instance"), FILE_INSTANCE);
+ p_popup->add_icon_item(get_theme_icon(SNAME("Instance"), SNAME("EditorIcons")), TTR("Instantiate"), FILE_INSTANTIATE);
p_popup->add_separator();
} else if (filenames.size() == 1) {
p_popup->add_icon_item(get_theme_icon(SNAME("Load"), SNAME("EditorIcons")), TTR("Open"), FILE_OPEN);
@@ -2989,7 +2994,7 @@ void FileSystemDock::_file_sort_popup(int p_id) {
MenuButton *FileSystemDock::_create_file_menu_button() {
MenuButton *button = memnew(MenuButton);
button->set_flat(true);
- button->set_tooltip_text(TTR("Sort files"));
+ button->set_tooltip_text(TTR("Sort Files"));
PopupMenu *p = button->get_popup();
p->connect("id_pressed", callable_mp(this, &FileSystemDock::_file_sort_popup));
@@ -3018,7 +3023,7 @@ void FileSystemDock::_bind_methods() {
ClassDB::bind_method(D_METHOD("_update_import_dock"), &FileSystemDock::_update_import_dock);
ADD_SIGNAL(MethodInfo("inherit", PropertyInfo(Variant::STRING, "file")));
- ADD_SIGNAL(MethodInfo("instance", PropertyInfo(Variant::PACKED_STRING_ARRAY, "files")));
+ ADD_SIGNAL(MethodInfo("instantiate", PropertyInfo(Variant::PACKED_STRING_ARRAY, "files")));
ADD_SIGNAL(MethodInfo("file_removed", PropertyInfo(Variant::STRING, "file")));
ADD_SIGNAL(MethodInfo("folder_removed", PropertyInfo(Variant::STRING, "folder")));
@@ -3052,14 +3057,14 @@ FileSystemDock::FileSystemDock() {
button_hist_prev->set_flat(true);
button_hist_prev->set_disabled(true);
button_hist_prev->set_focus_mode(FOCUS_NONE);
- button_hist_prev->set_tooltip_text(TTR("Previous Folder/File"));
+ button_hist_prev->set_tooltip_text(TTR("Go to previous selected folder/file."));
toolbar_hbc->add_child(button_hist_prev);
button_hist_next = memnew(Button);
button_hist_next->set_flat(true);
button_hist_next->set_disabled(true);
button_hist_next->set_focus_mode(FOCUS_NONE);
- button_hist_next->set_tooltip_text(TTR("Next Folder/File"));
+ button_hist_next->set_tooltip_text(TTR("Go to next selected folder/file."));
toolbar_hbc->add_child(button_hist_next);
current_path = memnew(LineEdit);
diff --git a/editor/filesystem_dock.h b/editor/filesystem_dock.h
index f39ca9e74d..c4ce500c1e 100644
--- a/editor/filesystem_dock.h
+++ b/editor/filesystem_dock.h
@@ -79,7 +79,7 @@ private:
FILE_OPEN,
FILE_INHERIT,
FILE_MAIN_SCENE,
- FILE_INSTANCE,
+ FILE_INSTANTIATE,
FILE_ADD_FAVORITE,
FILE_REMOVE_FAVORITE,
FILE_DEPENDENCIES,
@@ -297,12 +297,12 @@ private:
void _update_display_mode(bool p_force = false);
- Vector<String> _tree_get_selected(bool remove_self_inclusion = true);
+ Vector<String> _tree_get_selected(bool remove_self_inclusion = true) const;
bool _is_file_type_disabled_by_feature_profile(const StringName &p_class);
void _feature_profile_changed();
- Vector<String> _remove_self_included_paths(Vector<String> selected_strings);
+ static Vector<String> _remove_self_included_paths(Vector<String> selected_strings);
private:
static FileSystemDock *singleton;
@@ -315,9 +315,11 @@ protected:
static void _bind_methods();
public:
- String get_selected_path() const;
+ Vector<String> get_selected_paths() const;
String get_current_path() const;
+ String get_current_directory() const;
+
void navigate_to_path(const String &p_path);
void focus_on_filter();
diff --git a/editor/find_in_files.cpp b/editor/find_in_files.cpp
index b7605d8e2b..3a6c891142 100644
--- a/editor/find_in_files.cpp
+++ b/editor/find_in_files.cpp
@@ -569,8 +569,6 @@ FindInFilesPanel::FindInFilesPanel() {
hbc->add_child(find_label);
_search_text_label = memnew(Label);
- _search_text_label->add_theme_font_override("font", EditorNode::get_singleton()->get_gui_base()->get_theme_font(SNAME("source"), SNAME("EditorFonts")));
- _search_text_label->add_theme_font_size_override("font_size", EditorNode::get_singleton()->get_gui_base()->get_theme_font_size(SNAME("source_size"), SNAME("EditorFonts")));
hbc->add_child(_search_text_label);
_progress_bar = memnew(ProgressBar);
@@ -598,14 +596,13 @@ FindInFilesPanel::FindInFilesPanel() {
}
_results_display = memnew(Tree);
- _results_display->add_theme_font_override("font", EditorNode::get_singleton()->get_gui_base()->get_theme_font(SNAME("source"), SNAME("EditorFonts")));
- _results_display->add_theme_font_size_override("font_size", EditorNode::get_singleton()->get_gui_base()->get_theme_font_size(SNAME("source_size"), SNAME("EditorFonts")));
_results_display->set_v_size_flags(SIZE_EXPAND_FILL);
_results_display->connect("item_selected", callable_mp(this, &FindInFilesPanel::_on_result_selected));
_results_display->connect("item_edited", callable_mp(this, &FindInFilesPanel::_on_item_edited));
_results_display->set_hide_root(true);
_results_display->set_select_mode(Tree::SELECT_ROW);
_results_display->set_allow_rmb_select(true);
+ _results_display->set_allow_reselect(true);
_results_display->create_item(); // Root
vbc->add_child(_results_display);
@@ -687,13 +684,20 @@ void FindInFilesPanel::stop_search() {
void FindInFilesPanel::_notification(int p_what) {
switch (p_what) {
- case NOTIFICATION_PROCESS: {
- _progress_bar->set_as_ratio(_finder->get_progress());
- } break;
-
case NOTIFICATION_THEME_CHANGED: {
_search_text_label->add_theme_font_override("font", get_theme_font(SNAME("source"), SNAME("EditorFonts")));
+ _search_text_label->add_theme_font_size_override("font_size", get_theme_font_size(SNAME("source_size"), SNAME("EditorFonts")));
_results_display->add_theme_font_override("font", get_theme_font(SNAME("source"), SNAME("EditorFonts")));
+ _results_display->add_theme_font_size_override("font_size", get_theme_font_size(SNAME("source_size"), SNAME("EditorFonts")));
+
+ // Rebuild search tree.
+ if (!_finder->get_search_text().is_empty()) {
+ start_search();
+ }
+ } break;
+
+ case NOTIFICATION_PROCESS: {
+ _progress_bar->set_as_ratio(_finder->get_progress());
} break;
}
}
@@ -717,6 +721,10 @@ void FindInFilesPanel::_on_result_found(String fpath, int line_number, int begin
file_item = E->value;
}
+ Color file_item_color = _results_display->get_theme_color(SNAME("font_color")) * Color(1, 1, 1, 0.67);
+ file_item->set_custom_color(0, file_item_color);
+ file_item->set_selectable(0, false);
+
int text_index = _with_replace ? 1 : 0;
TreeItem *item = _results_display->create_item(file_item);
@@ -763,13 +771,13 @@ 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), 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.x += font->get_string_size(item_text.left(r.begin_trimmed), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size).x - 1;
+ match_rect.size.x = font->get_string_size(_search_text_label->get_text(), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size).x + 1;
match_rect.position.y += 1 * EDSCALE;
match_rect.size.y -= 2 * EDSCALE;
- // Use the inverted accent color to help match rectangles stand out even on the currently selected line.
- _results_display->draw_rect(match_rect, get_theme_color(SNAME("accent_color"), SNAME("Editor")).inverted() * Color(1, 1, 1, 0.5));
+ _results_display->draw_rect(match_rect, get_theme_color(SNAME("accent_color"), SNAME("Editor")) * Color(1, 1, 1, 0.33), false, 2.0);
+ _results_display->draw_rect(match_rect, get_theme_color(SNAME("accent_color"), SNAME("Editor")) * Color(1, 1, 1, 0.17), true);
// Text is drawn by Tree already.
}
@@ -777,14 +785,12 @@ void FindInFilesPanel::draw_result_text(Object *item_obj, Rect2 rect) {
void FindInFilesPanel::_on_item_edited() {
TreeItem *item = _results_display->get_selected();
- if (item->is_checked(0)) {
- item->set_custom_color(1, _results_display->get_theme_color(SNAME("font_color")));
- } else {
- // Grey out.
- Color color = _results_display->get_theme_color(SNAME("font_color"));
- color.a /= 2.0;
- item->set_custom_color(1, color);
+ // Change opacity to half if checkbox is checked, otherwise full.
+ Color use_color = _results_display->get_theme_color(SNAME("font_color"));
+ if (!item->is_checked(0)) {
+ use_color.a *= 0.5;
}
+ item->set_custom_color(1, use_color);
}
void FindInFilesPanel::_on_finished() {
@@ -793,11 +799,11 @@ void FindInFilesPanel::_on_finished() {
int file_count = _file_items.size();
if (result_count == 1 && file_count == 1) {
- results_text = vformat(TTR("%d match in %d file."), result_count, file_count);
+ results_text = vformat(TTR("%d match in %d file"), result_count, file_count);
} else if (result_count != 1 && file_count == 1) {
- results_text = vformat(TTR("%d matches in %d file."), result_count, file_count);
+ results_text = vformat(TTR("%d matches in %d file"), result_count, file_count);
} else {
- results_text = vformat(TTR("%d matches in %d files."), result_count, file_count);
+ results_text = vformat(TTR("%d matches in %d files"), result_count, file_count);
}
_status_label->set_text(results_text);
diff --git a/editor/history_dock.cpp b/editor/history_dock.cpp
index 57088a76cb..93599eff56 100644
--- a/editor/history_dock.cpp
+++ b/editor/history_dock.cpp
@@ -206,7 +206,7 @@ void HistoryDock::seek_history(int p_index) {
void HistoryDock::_notification(int p_notification) {
switch (p_notification) {
- case NOTIFICATION_ENTER_TREE: {
+ case NOTIFICATION_READY: {
EditorNode::get_singleton()->connect("scene_changed", callable_mp(this, &HistoryDock::on_history_changed));
} break;
@@ -219,6 +219,8 @@ void HistoryDock::_notification(int p_notification) {
}
HistoryDock::HistoryDock() {
+ set_name("History");
+
ur_manager = EditorNode::get_undo_redo();
ur_manager->connect("history_changed", callable_mp(this, &HistoryDock::on_history_changed));
ur_manager->connect("version_changed", callable_mp(this, &HistoryDock::on_version_changed));
diff --git a/editor/icons/ArrowDown.svg b/editor/icons/ArrowDown.svg
index d24357d2c5..f17c1bede7 100644
--- a/editor/icons/ArrowDown.svg
+++ b/editor/icons/ArrowDown.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 3.002a1 1 0 0 0 -.69336.29102 1 1 0 0 0 0 1.4141l2.293 2.293h-4.5859c-.55228 0-1 .4477-1 1s.44772 1 1 1h4.5859l-2.293 2.293a1 1 0 0 0 0 1.4141 1 1 0 0 0 1.4141 0l4-4a1.0001 1.0001 0 0 0 0-1.4141l-4-4a1 1 0 0 0 -.7207-.29102z" fill="#e0e0e0" fill-opacity=".99608" transform="matrix(0 1 -1 0 16.0021 -.00004)"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 3.002a1 1 0 0 0 -.69336.29102 1 1 0 0 0 0 1.4141l2.293 2.293h-4.5859c-.55228 0-1 .4477-1 1s.44772 1 1 1h4.5859l-2.293 2.293a1 1 0 0 0 0 1.4141 1 1 0 0 0 1.4141 0l4-4a1.0001 1.0001 0 0 0 0-1.4141l-4-4a1 1 0 0 0 -.7207-.29102z" fill="#e0e0e0" transform="matrix(0 1 -1 0 16.0021 -.00004)"/></svg>
diff --git a/editor/icons/ArrowLeft.svg b/editor/icons/ArrowLeft.svg
index ddd2f4e353..1a923cb6db 100644
--- a/editor/icons/ArrowLeft.svg
+++ b/editor/icons/ArrowLeft.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m7.9863 3.002a1 1 0 0 0 -.69336.29102l-4 4a1.0001 1.0001 0 0 0 0 1.4141l4 4a1 1 0 0 0 1.4141 0 1 1 0 0 0 0-1.4141l-2.293-2.293h4.5859a1 1 0 0 0 1-1 1 1 0 0 0 -1-1h-4.5859l2.293-2.293a1 1 0 0 0 0-1.4141 1 1 0 0 0 -.7207-.29102z" fill="#e0e0e0" fill-opacity=".99608"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m7.9863 3.002a1 1 0 0 0 -.69336.29102l-4 4a1.0001 1.0001 0 0 0 0 1.4141l4 4a1 1 0 0 0 1.4141 0 1 1 0 0 0 0-1.4141l-2.293-2.293h4.5859a1 1 0 0 0 1-1 1 1 0 0 0 -1-1h-4.5859l2.293-2.293a1 1 0 0 0 0-1.4141 1 1 0 0 0 -.7207-.29102z" fill="#e0e0e0"/></svg>
diff --git a/editor/icons/ArrowRight.svg b/editor/icons/ArrowRight.svg
index a0c78dc1eb..da706c17ba 100644
--- a/editor/icons/ArrowRight.svg
+++ b/editor/icons/ArrowRight.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 3.002a1 1 0 0 0 -.69336.29102 1 1 0 0 0 0 1.4141l2.293 2.293h-4.5859c-.55228 0-1 .4477-1 1s.44772 1 1 1h4.5859l-2.293 2.293a1 1 0 0 0 0 1.4141 1 1 0 0 0 1.4141 0l4-4a1.0001 1.0001 0 0 0 0-1.4141l-4-4a1 1 0 0 0 -.7207-.29102z" fill="#e0e0e0" fill-opacity=".99608"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 3.002a1 1 0 0 0 -.69336.29102 1 1 0 0 0 0 1.4141l2.293 2.293h-4.5859c-.55228 0-1 .4477-1 1s.44772 1 1 1h4.5859l-2.293 2.293a1 1 0 0 0 0 1.4141 1 1 0 0 0 1.4141 0l4-4a1.0001 1.0001 0 0 0 0-1.4141l-4-4a1 1 0 0 0 -.7207-.29102z" fill="#e0e0e0"/></svg>
diff --git a/editor/icons/ArrowUp.svg b/editor/icons/ArrowUp.svg
index f71f95c7b1..1381fea1b4 100644
--- a/editor/icons/ArrowUp.svg
+++ b/editor/icons/ArrowUp.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8.00008 1049.4022a1 1 0 0 0 .69336-.291 1 1 0 0 0 0-1.4141l-2.293-2.293h4.5859c.55228 0 1-.4477 1-1s-.44772-1-1-1h-4.5859l2.293-2.293a1 1 0 0 0 0-1.4141 1 1 0 0 0 -1.4141 0l-4 4a1.0001 1.0001 0 0 0 0 1.4141l4 4a1 1 0 0 0 .7207.291z" fill="#e0e0e0" fill-opacity=".99608" transform="matrix(0 1 -1 0 1052.4021 -.00004)"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8.00008 1049.4022a1 1 0 0 0 .69336-.291 1 1 0 0 0 0-1.4141l-2.293-2.293h4.5859c.55228 0 1-.4477 1-1s-.44772-1-1-1h-4.5859l2.293-2.293a1 1 0 0 0 0-1.4141 1 1 0 0 0 -1.4141 0l-4 4a1.0001 1.0001 0 0 0 0 1.4141l4 4a1 1 0 0 0 .7207.291z" fill="#e0e0e0" transform="matrix(0 1 -1 0 1052.4021 -.00004)"/></svg>
diff --git a/editor/icons/AutoKey.svg b/editor/icons/AutoKey.svg
index acc6665baf..877b00722f 100644
--- a/editor/icons/AutoKey.svg
+++ b/editor/icons/AutoKey.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0"><circle cx="8" cy="5" r="4"/><path d="m11 13c0 1.6569 1.3431 3 3 3h1v-2h-1c-.55228-.00001-.99999-.44772-1-1 .00001-.55228.44772-.99999 1-1h1v-2h-1c-1.6569 0-3 1.3431-3 3z" fill-opacity=".99608"/><path d="m4 10c-1.6569 0-3 1.3431-3 3v3h2v-3c.0000096-.5523.44772-1 1-1h1v-2z" fill-opacity=".99608"/><path d="m8 10c-3 0-3 3-3 3s0 3 3 3h1v-2h-1s-1 0-1-1h3 1s0-3-3-3zm-1 1h2v1h-2z"/></g></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0"><circle cx="8" cy="5" r="4"/><path d="m11 13c0 1.6569 1.3431 3 3 3h1v-2h-1c-.55228-.00001-.99999-.44772-1-1 .00001-.55228.44772-.99999 1-1h1v-2h-1c-1.6569 0-3 1.3431-3 3z"/><path d="m4 10c-1.6569 0-3 1.3431-3 3v3h2v-3c.0000096-.5523.44772-1 1-1h1v-2z"/><path d="m8 10c-3 0-3 3-3 3s0 3 3 3h1v-2h-1s-1 0-1-1h3 1s0-3-3-3zm-1 1h2v1h-2z"/></g></svg>
diff --git a/editor/icons/Blend.svg b/editor/icons/Blend.svg
index 4de2fa5a43..e692fc1c30 100644
--- a/editor/icons/Blend.svg
+++ b/editor/icons/Blend.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m9 1v2h2.5859l-3.5859 3.5859-4.293-4.293-1.4141 1.4141 4.293 4.293-4.293 4.293 1.4141 1.4141 4.293-4.293 3.5859 3.5859h-2.5859v2h5a1.0001 1.0001 0 0 0 1-1v-5h-2v2.5859l-3.5859-3.5859 3.5859-3.5859v2.5859h2v-5a1.0001 1.0001 0 0 0 -1-1h-5z" fill="#e0e0e0" fill-opacity=".99608"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m9 1v2h2.5859l-3.5859 3.5859-4.293-4.293-1.4141 1.4141 4.293 4.293-4.293 4.293 1.4141 1.4141 4.293-4.293 3.5859 3.5859h-2.5859v2h5a1.0001 1.0001 0 0 0 1-1v-5h-2v2.5859l-3.5859-3.5859 3.5859-3.5859v2.5859h2v-5a1.0001 1.0001 0 0 0 -1-1h-5z" fill="#e0e0e0"/></svg>
diff --git a/editor/icons/Bone.svg b/editor/icons/Bone.svg
index cbfa4794ed..f86b981619 100644
--- a/editor/icons/Bone.svg
+++ b/editor/icons/Bone.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m10.478 1037.4a2.4664 2.4663 0 0 0 -1.7804.7205 2.4664 2.4663 0 0 0 -.31408 3.1041l-3.559 3.5608a2.4664 2.4663 0 0 0 -3.1023.3121 2.4664 2.4663 0 0 0 0 3.4876 2.4664 2.4663 0 0 0 1.397.6955 2.4664 2.4663 0 0 0 .69561 1.397 2.4664 2.4663 0 0 0 3.4877 0 2.4664 2.4663 0 0 0 .31408-3.1041l3.5609-3.5608a2.4664 2.4663 0 0 0 3.1004-.3102 2.4664 2.4663 0 0 0 0-3.4875 2.4664 2.4663 0 0 0 -1.397-.6974 2.4664 2.4663 0 0 0 -.69561-1.3971 2.4664 2.4663 0 0 0 -1.7072-.7205z" fill="#e0e0e0" fill-opacity=".99608" transform="translate(0 -1036.4)"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m10.478 1037.4a2.4664 2.4663 0 0 0 -1.7804.7205 2.4664 2.4663 0 0 0 -.31408 3.1041l-3.559 3.5608a2.4664 2.4663 0 0 0 -3.1023.3121 2.4664 2.4663 0 0 0 0 3.4876 2.4664 2.4663 0 0 0 1.397.6955 2.4664 2.4663 0 0 0 .69561 1.397 2.4664 2.4663 0 0 0 3.4877 0 2.4664 2.4663 0 0 0 .31408-3.1041l3.5609-3.5608a2.4664 2.4663 0 0 0 3.1004-.3102 2.4664 2.4663 0 0 0 0-3.4875 2.4664 2.4663 0 0 0 -1.397-.6974 2.4664 2.4663 0 0 0 -.69561-1.3971 2.4664 2.4663 0 0 0 -1.7072-.7205z" fill="#e0e0e0" transform="translate(0 -1036.4)"/></svg>
diff --git a/editor/icons/CPUParticles3D.svg b/editor/icons/CPUParticles3D.svg
index d7ced5fc6b..5001375f80 100644
--- a/editor/icons/CPUParticles3D.svg
+++ b/editor/icons/CPUParticles3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m4.5587261.60940813c-.4226244 0-.7617187.3410473-.7617187.76367177v.5078126c0 .1028478.020058.199689.056641.2890624h-1.1933597c-.4226245 0-.7617188.3390944-.7617188.7617188v.921875c-.040428-.00657-.0767989-.0234375-.1191406-.0234375h-.5078125c-.42262448 0-.76367188.3410475-.76367188.7636719v.3730468c0 .4226245.3410474.7617188.76367188.7617188h.5078125c.042396 0 .078663-.016851.1191406-.023437v4.4531248c-.040428-.0066-.076799-.02344-.1191406-.02344h-.5078125c-.42262448 0-.76367188.341047-.76367188.763672v.373047c0 .422625.3410474.761718.76367188.761718h.5078125c.042396 0 .078663-.01685.1191406-.02344v1.125c0 .422624.3390944.763672.7617188.763672h1.1367187v.457031c0 .422624.3390943.763672.7617187.763672h.3730469c.4226244 0 .7636719-.341048.7636719-.763672v-.457031h4.4062501v.457031c0 .422624.339094.763672.761719.763672h.373047c.422624 0 .763671-.341048.763671-.763672v-.457031h1.269532c.422625 0 .763672-.341048.763672-.763672v-1.111328c.01774.0012.03272.0098.05078.0098h.507812c.422624 0 .763672-.339093.763672-.761718v-.373047c0-.422624-.341048-.763672-.763672-.763672h-.507812c-.01803 0-.03307.0085-.05078.0098v-4.4258454c.01774.00122.03272.00977.05078.00977h.507812c.422624 0 .763672-.3390943.763672-.7617188v-.3730512c0-.4226244-.341048-.7636719-.763672-.7636719h-.507812c-.01803 0-.03307.00855-.05078.00977v-.9082075c0-.4226244-.341047-.7617187-.763672-.7617188h-1.328125c.03658-.089375.05859-.1862118.05859-.2890624v-.5078126c0-.42262437-.341047-.76367177-.763671-.76367177h-.373047c-.422625 0-.761719.3410474-.761719.76367177v.5078126c0 .1028478.02006.1996891.05664.2890624h-4.5214809c.036585-.0893749.0585938-.1862118.0585938-.2890624v-.5078126c0-.42262437-.3410475-.76367177-.7636719-.76367177zm3.2382813 2.35742177a3.279661 3.6440678 0 0 1 3.2128906 2.9394532 2.1864407 2.1864407 0 0 1 1.888672 2.1621094 2.1864407 2.1864407 0 0 1 -2.1875 2.1855475h-5.8300782a2.1864407 2.1864407 0 0 1 -2.1855469-2.1855475 2.1864407 2.1864407 0 0 1 1.8847656-2.1640626 3.279661 3.6440678 0 0 1 3.2167969-2.9375zm-2.9160156 8.0156251a.72881355.72881355 0 0 1 .7285156.728516.72881355.72881355 0 0 1 -.7285156.730469.72881355.72881355 0 0 1 -.7285157-.730469.72881355.72881355 0 0 1 .7285157-.728516zm5.8300782 0a.72881355.72881355 0 0 1 .730469.728516.72881355.72881355 0 0 1 -.730469.730469.72881355.72881355 0 0 1 -.7285157-.730469.72881355.72881355 0 0 1 .7285157-.728516zm-2.9140626.728516a.72881355.72881355 0 0 1 .7285156.730469.72881355.72881355 0 0 1 -.7285156.728515.72881355.72881355 0 0 1 -.7285156-.728515.72881355.72881355 0 0 1 .7285156-.730469z" fill="#fc7f7f" fill-opacity=".996078"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m4.5587261.60940813c-.4226244 0-.7617187.3410473-.7617187.76367177v.5078126c0 .1028478.020058.199689.056641.2890624h-1.1933597c-.4226245 0-.7617188.3390944-.7617188.7617188v.921875c-.040428-.00657-.0767989-.0234375-.1191406-.0234375h-.5078125c-.42262448 0-.76367188.3410475-.76367188.7636719v.3730468c0 .4226245.3410474.7617188.76367188.7617188h.5078125c.042396 0 .078663-.016851.1191406-.023437v4.4531248c-.040428-.0066-.076799-.02344-.1191406-.02344h-.5078125c-.42262448 0-.76367188.341047-.76367188.763672v.373047c0 .422625.3410474.761718.76367188.761718h.5078125c.042396 0 .078663-.01685.1191406-.02344v1.125c0 .422624.3390944.763672.7617188.763672h1.1367187v.457031c0 .422624.3390943.763672.7617187.763672h.3730469c.4226244 0 .7636719-.341048.7636719-.763672v-.457031h4.4062501v.457031c0 .422624.339094.763672.761719.763672h.373047c.422624 0 .763671-.341048.763671-.763672v-.457031h1.269532c.422625 0 .763672-.341048.763672-.763672v-1.111328c.01774.0012.03272.0098.05078.0098h.507812c.422624 0 .763672-.339093.763672-.761718v-.373047c0-.422624-.341048-.763672-.763672-.763672h-.507812c-.01803 0-.03307.0085-.05078.0098v-4.4258454c.01774.00122.03272.00977.05078.00977h.507812c.422624 0 .763672-.3390943.763672-.7617188v-.3730512c0-.4226244-.341048-.7636719-.763672-.7636719h-.507812c-.01803 0-.03307.00855-.05078.00977v-.9082075c0-.4226244-.341047-.7617187-.763672-.7617188h-1.328125c.03658-.089375.05859-.1862118.05859-.2890624v-.5078126c0-.42262437-.341047-.76367177-.763671-.76367177h-.373047c-.422625 0-.761719.3410474-.761719.76367177v.5078126c0 .1028478.02006.1996891.05664.2890624h-4.5214809c.036585-.0893749.0585938-.1862118.0585938-.2890624v-.5078126c0-.42262437-.3410475-.76367177-.7636719-.76367177zm3.2382813 2.35742177a3.279661 3.6440678 0 0 1 3.2128906 2.9394532 2.1864407 2.1864407 0 0 1 1.888672 2.1621094 2.1864407 2.1864407 0 0 1 -2.1875 2.1855475h-5.8300782a2.1864407 2.1864407 0 0 1 -2.1855469-2.1855475 2.1864407 2.1864407 0 0 1 1.8847656-2.1640626 3.279661 3.6440678 0 0 1 3.2167969-2.9375zm-2.9160156 8.0156251a.72881355.72881355 0 0 1 .7285156.728516.72881355.72881355 0 0 1 -.7285156.730469.72881355.72881355 0 0 1 -.7285157-.730469.72881355.72881355 0 0 1 .7285157-.728516zm5.8300782 0a.72881355.72881355 0 0 1 .730469.728516.72881355.72881355 0 0 1 -.730469.730469.72881355.72881355 0 0 1 -.7285157-.730469.72881355.72881355 0 0 1 .7285157-.728516zm-2.9140626.728516a.72881355.72881355 0 0 1 .7285156.730469.72881355.72881355 0 0 1 -.7285156.728515.72881355.72881355 0 0 1 -.7285156-.728515.72881355.72881355 0 0 1 .7285156-.730469z" fill="#fc7f7f"/></svg>
diff --git a/editor/icons/CameraTexture.svg b/editor/icons/CameraTexture.svg
index adb4762082..91e3fe9b41 100644
--- a/editor/icons/CameraTexture.svg
+++ b/editor/icons/CameraTexture.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m2 1c-.55228 0-1 .44772-1 1v12c0 .55228.44772 1 1 1h12c.55228 0 1-.44772 1-1v-12c0-.55228-.44772-1-1-1zm1 2h10v8h-10zm5.8184 1.0039c-.85534.0009758-1.5654.66069-1.6289 1.5137-.30036-.27229-.69029-.4234-1.0957-.42383-.90315 0-1.6367.73162-1.6367 1.6348.0009732.69217.43922 1.3103 1.0918 1.541v1.1855c0 .30198.24293.54492.54492.54492h3.2695c.30199 0 .54492-.24294.54492-.54492v-.54492l1.6367 1.0898v-3.2715l-1.6367 1.0918v-.96484c.34606-.30952.54406-.75251.54492-1.2168 0-.90315-.73162-1.6348-1.6348-1.6348z" fill="#e0e0e0" fill-opacity=".99608"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m2 1c-.55228 0-1 .44772-1 1v12c0 .55228.44772 1 1 1h12c.55228 0 1-.44772 1-1v-12c0-.55228-.44772-1-1-1zm1 2h10v8h-10zm5.8184 1.0039c-.85534.0009758-1.5654.66069-1.6289 1.5137-.30036-.27229-.69029-.4234-1.0957-.42383-.90315 0-1.6367.73162-1.6367 1.6348.0009732.69217.43922 1.3103 1.0918 1.541v1.1855c0 .30198.24293.54492.54492.54492h3.2695c.30199 0 .54492-.24294.54492-.54492v-.54492l1.6367 1.0898v-3.2715l-1.6367 1.0918v-.96484c.34606-.30952.54406-.75251.54492-1.2168 0-.90315-.73162-1.6348-1.6348-1.6348z" fill="#e0e0e0"/></svg>
diff --git a/editor/icons/CanvasItem.svg b/editor/icons/CanvasItem.svg
index f396290436..0d9b47613a 100644
--- a/editor/icons/CanvasItem.svg
+++ b/editor/icons/CanvasItem.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m2.9208 1046.4c-.26373.3-.4204.7296-.4204 1.2383 0 1.6277-3.1381-.1781-.33757 2.6703.88382.899 2.6544.6701 3.5382-.2288.88384-.899.88382-2.3565 0-3.2554-1.1002-1.1191-2.2001-1.0845-2.7803-.4244zm2.3802-1.6103 2.4005 2.4416 6.8014-6.9177c.66286-.6742.66286-1.7673 0-2.4415-.66288-.6741-1.7376-.6741-2.4005 0z" fill="#e0e0e0" fill-opacity=".99608" transform="translate(0 -1036.4)"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m2.9208 1046.4c-.26373.3-.4204.7296-.4204 1.2383 0 1.6277-3.1381-.1781-.33757 2.6703.88382.899 2.6544.6701 3.5382-.2288.88384-.899.88382-2.3565 0-3.2554-1.1002-1.1191-2.2001-1.0845-2.7803-.4244zm2.3802-1.6103 2.4005 2.4416 6.8014-6.9177c.66286-.6742.66286-1.7673 0-2.4415-.66288-.6741-1.7376-.6741-2.4005 0z" fill="#e0e0e0" transform="translate(0 -1036.4)"/></svg>
diff --git a/editor/icons/CanvasLayer.svg b/editor/icons/CanvasLayer.svg
index 6e98fd1ba9..87295e6099 100644
--- a/editor/icons/CanvasLayer.svg
+++ b/editor/icons/CanvasLayer.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 1a2 2 0 0 0 -2 2v6h1v-6a1 1 0 0 1 1-1h6v-1zm10.303 0c-.4344 0-.86973.16881-1.2012.50586l-6.8008 6.918 2.4004 2.4414 6.8008-6.918c.66286-.6742.66286-1.7672 0-2.4414-.33144-.33705-.76482-.50586-1.1992-.50586zm.69727 6v6a1 1 0 0 1 -1 1h-6v1h6a2 2 0 0 0 2-2v-6zm-9.8848 2.5781c-.48501-.048725-.90521.12503-1.1953.45508-.26373.3-.41992.72958-.41992 1.2383 0 1.6277-3.1385-.17848-.33789 2.6699.88382.899 2.6552.67038 3.5391-.22852.88384-.899.88382-2.357 0-3.2559-.55011-.55955-1.1009-.83018-1.5859-.87891z" fill="#e0e0e0" fill-opacity=".99608"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 1a2 2 0 0 0 -2 2v6h1v-6a1 1 0 0 1 1-1h6v-1zm10.303 0c-.4344 0-.86973.16881-1.2012.50586l-6.8008 6.918 2.4004 2.4414 6.8008-6.918c.66286-.6742.66286-1.7672 0-2.4414-.33144-.33705-.76482-.50586-1.1992-.50586zm.69727 6v6a1 1 0 0 1 -1 1h-6v1h6a2 2 0 0 0 2-2v-6zm-9.8848 2.5781c-.48501-.048725-.90521.12503-1.1953.45508-.26373.3-.41992.72958-.41992 1.2383 0 1.6277-3.1385-.17848-.33789 2.6699.88382.899 2.6552.67038 3.5391-.22852.88384-.899.88382-2.357 0-3.2559-.55011-.55955-1.1009-.83018-1.5859-.87891z" fill="#e0e0e0"/></svg>
diff --git a/editor/icons/CharacterBody3D.svg b/editor/icons/CharacterBody3D.svg
index d0def4f14a..21a642cacb 100644
--- a/editor/icons/CharacterBody3D.svg
+++ b/editor/icons/CharacterBody3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m6 1c-.55401 0-1 .44599-1 1v3c0 .55401.44599 1 1 1h1v.99023a1.0001 1.0001 0 0 0 -.31641.0625l-2.0508.68359-.68359-2.0508a1.0001 1.0001 0 0 0 -.99023-.69727 1.0001 1.0001 0 0 0 -.9082 1.3281l1 3a1.0001 1.0001 0 0 0 1.2656.63281l1.6836-.56055v.61133c0 .04088.018715.07566.023437.11523l-4.5781 3.0527a1.0001 1.0001 0 1 0 1.1094 1.6641l5.0566-3.3711 1.4941 2.9863a1.0001 1.0001 0 0 0 1.2109.50195l3-1a1.0001 1.0001 0 1 0 -.63281-1.8965l-2.1777.72461-.97461-1.9512c.2759-.17764.46875-.47227.46875-.82617v-1h1.3828l.72266 1.4473a1.0001 1.0001 0 1 0 1.7891-.89453l-1-2a1.0001 1.0001 0 0 0 -.89453-.55273h-3v-1h1c.55401 0 1-.44599 1-1v-3c0-.55401-.44599-1-1-1zm0 2h1v2h-1z" fill="#fc7f7f" fill-opacity=".99608"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m6 1c-.55401 0-1 .44599-1 1v3c0 .55401.44599 1 1 1h1v.99023a1.0001 1.0001 0 0 0 -.31641.0625l-2.0508.68359-.68359-2.0508a1.0001 1.0001 0 0 0 -.99023-.69727 1.0001 1.0001 0 0 0 -.9082 1.3281l1 3a1.0001 1.0001 0 0 0 1.2656.63281l1.6836-.56055v.61133c0 .04088.018715.07566.023437.11523l-4.5781 3.0527a1.0001 1.0001 0 1 0 1.1094 1.6641l5.0566-3.3711 1.4941 2.9863a1.0001 1.0001 0 0 0 1.2109.50195l3-1a1.0001 1.0001 0 1 0 -.63281-1.8965l-2.1777.72461-.97461-1.9512c.2759-.17764.46875-.47227.46875-.82617v-1h1.3828l.72266 1.4473a1.0001 1.0001 0 1 0 1.7891-.89453l-1-2a1.0001 1.0001 0 0 0 -.89453-.55273h-3v-1h1c.55401 0 1-.44599 1-1v-3c0-.55401-.44599-1-1-1zm0 2h1v2h-1z" fill="#fc7f7f"/></svg>
diff --git a/editor/icons/Clear.svg b/editor/icons/Clear.svg
index 43c00311bc..577cacba22 100644
--- a/editor/icons/Clear.svg
+++ b/editor/icons/Clear.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1a1 1 0 0 0 -1 1v5h-2c-1.108 0-2 .892-2 2v1h10v-1c0-1.108-.892-2-2-2h-2v-5a1 1 0 0 0 -1-1zm-5 10v4l10-1v-3z" fill="#e0e0e0" fill-opacity=".99608"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1a1 1 0 0 0 -1 1v5h-2c-1.108 0-2 .892-2 2v1h10v-1c0-1.108-.892-2-2-2h-2v-5a1 1 0 0 0 -1-1zm-5 10v4l10-1v-3z" fill="#e0e0e0"/></svg>
diff --git a/editor/icons/CollisionPolygon3D.svg b/editor/icons/CollisionPolygon3D.svg
index 57531fa9f4..121bd82685 100644
--- a/editor/icons/CollisionPolygon3D.svg
+++ b/editor/icons/CollisionPolygon3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m14 1050.4h-12v-12h12l-6 6z" fill="none" stroke="#fc7f7f" stroke-linejoin="round" stroke-opacity=".99608" stroke-width="2" transform="translate(0 -1036.4)"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m14 1050.4h-12v-12h12l-6 6z" fill="none" stroke="#fc7f7f" stroke-linejoin="round" stroke-width="2" transform="translate(0 -1036.4)"/></svg>
diff --git a/editor/icons/CollisionShape3D.svg b/editor/icons/CollisionShape3D.svg
index 7a8bbf8050..d7f8a308e6 100644
--- a/editor/icons/CollisionShape3D.svg
+++ b/editor/icons/CollisionShape3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1050.4-6-3v-6l6-3 6 3v6z" fill="none" stroke="#fc7f7f" stroke-linejoin="round" stroke-opacity=".99608" stroke-width="2" transform="translate(0 -1036.399988)"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1050.4-6-3v-6l6-3 6 3v6z" fill="none" stroke="#fc7f7f" stroke-linejoin="round" stroke-width="2" transform="translate(0 -1036.399988)"/></svg>
diff --git a/editor/icons/CompressedTexture2D.svg b/editor/icons/CompressedTexture2D.svg
index 068f65dead..54ff10b3c1 100644
--- a/editor/icons/CompressedTexture2D.svg
+++ b/editor/icons/CompressedTexture2D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m2 1a1 1 0 0 0 -1 1v12a1 1 0 0 0 1 1h6v-2h2v-2h-2-5v-8h5v-2zm6 2v2h2v-2zm2 0h2v-2h-2zm2 0v2h2v-2zm0 2h-2v2h2zm0 2v2h2v-2zm0 2h-2v2h2zm0 2v2h2v-2zm0 2h-2v2h2zm-2-4v-2h-2v-1h-1v1h-1v1h-1v1h-1v1h2 2v-1z" fill="#e0e0e0" fill-opacity=".99608"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m2 1a1 1 0 0 0 -1 1v12a1 1 0 0 0 1 1h6v-2h2v-2h-2-5v-8h5v-2zm6 2v2h2v-2zm2 0h2v-2h-2zm2 0v2h2v-2zm0 2h-2v2h2zm0 2v2h2v-2zm0 2h-2v2h2zm0 2v2h2v-2zm0 2h-2v2h2zm-2-4v-2h-2v-1h-1v1h-1v1h-1v1h-1v1h2 2v-1z" fill="#e0e0e0"/></svg>
diff --git a/editor/icons/CurveTexture.svg b/editor/icons/CurveTexture.svg
index 761fb9a45b..f5a2eec195 100644
--- a/editor/icons/CurveTexture.svg
+++ b/editor/icons/CurveTexture.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m2 1c-.55228 0-1 .44772-1 1v9.1602c.32185-.10966.66-.16382 1-.16016.33117 0 .66575-.007902 1-.013672v-7.9863h10v1.1348c.29007-.10393.59442-.16256.90234-.17383.37315-.012796.74541.044169 1.0977.16797v-2.1289c0-.55228-.44772-1-1-1h-12zm7 4v1h-1v1h-2v1h-1v1h-1v1h2 2 .39062c1.1119-.56677 1.9678-1.4538 2.6094-3.4727v-.52734h-1v-1h-1zm4.9668.98828a1.0001 1.0001 0 0 0 -.92774.73828c-.92743 3.246-2.6356 4.6825-4.6523 5.4668-2.0168.7843-4.3867.80664-6.3867.80664a1.0001 1.0001 0 1 0 0 2c2 0 4.6301.023994 7.1133-.94141 2.4832-.9657 4.7751-3.0292 5.8477-6.7832a1.0001 1.0001 0 0 0 -.99414-1.2871z" fill="#e0e0e0" fill-opacity=".99608"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m2 1c-.55228 0-1 .44772-1 1v9.1602c.32185-.10966.66-.16382 1-.16016.33117 0 .66575-.007902 1-.013672v-7.9863h10v1.1348c.29007-.10393.59442-.16256.90234-.17383.37315-.012796.74541.044169 1.0977.16797v-2.1289c0-.55228-.44772-1-1-1h-12zm7 4v1h-1v1h-2v1h-1v1h-1v1h2 2 .39062c1.1119-.56677 1.9678-1.4538 2.6094-3.4727v-.52734h-1v-1h-1zm4.9668.98828a1.0001 1.0001 0 0 0 -.92774.73828c-.92743 3.246-2.6356 4.6825-4.6523 5.4668-2.0168.7843-4.3867.80664-6.3867.80664a1.0001 1.0001 0 1 0 0 2c2 0 4.6301.023994 7.1133-.94141 2.4832-.9657 4.7751-3.0292 5.8477-6.7832a1.0001 1.0001 0 0 0 -.99414-1.2871z" fill="#e0e0e0"/></svg>
diff --git a/editor/icons/DebugSkipBreakpointsOff.svg b/editor/icons/DebugSkipBreakpointsOff.svg
index aef0d45a05..c0b6e8d188 100644
--- a/editor/icons/DebugSkipBreakpointsOff.svg
+++ b/editor/icons/DebugSkipBreakpointsOff.svg
@@ -1 +1,2 @@
-<svg height="17" viewBox="0 0 17 17" width="17" xmlns="http://www.w3.org/2000/svg"><path d="m4.8983252 3.006855a1.6192284 1.3289529 0 0 1 -.0000431.0097" stroke-width=".626319"/><path d="m8.796752 5.0553513a2.563139 3.6270869 0 0 1 -.0000683.02648" stroke-width=".626319"/><path d="m13.121337 4.512148a6.1594577 6.0545759 0 0 1 -.248787 8.20109 6.1594577 6.0545759 0 0 1 -8.3355404.427215 6.1594577 6.0545759 0 0 1 -1.1151058-8.1311866 6.1594577 6.0545759 0 0 1 8.1530832-1.7576713" fill="#fc7f7f" fill-opacity=".996078" stroke-width="1.019123"/></svg>
+<svg height="17" width="17" xmlns="http://www.w3.org/2000/svg"><circle cx="8.5" cy="8.5" r="6" fill="#fc7f7f" stroke-width="1"/></svg>
+
diff --git a/editor/icons/DebugSkipBreakpointsOn.svg b/editor/icons/DebugSkipBreakpointsOn.svg
index d8fbc6e43a..abea9579cf 100644
--- a/editor/icons/DebugSkipBreakpointsOn.svg
+++ b/editor/icons/DebugSkipBreakpointsOn.svg
@@ -1 +1,2 @@
-<svg height="17" viewBox="0 0 17 17" width="17" xmlns="http://www.w3.org/2000/svg"><path d="m4.8983252 3.006855a1.6192284 1.3289529 0 0 1 -.0000431.0097" stroke-width=".626319"/><path d="m8.796752 5.0553513a2.563139 3.6270869 0 0 1 -.0000683.02648" stroke-width=".626319"/><path d="m13.121337 4.512148a6.1594577 6.0545759 0 0 1 -.248787 8.20109 6.1594577 6.0545759 0 0 1 -8.3355404.427215 6.1594577 6.0545759 0 0 1 -1.1151058-8.1311866 6.1594577 6.0545759 0 0 1 8.1530832-1.7576713" fill="#fc7f7f" fill-opacity=".996078" stroke-width="1.019123"/><path d="m-9.290675 10.816157h18.575495v2.518711h-18.575495z" fill="#e0e0e0" stroke-width="1.187332" transform="matrix(.70605846 -.70815355 .70605846 .70815355 0 0)"/></svg>
+<svg height="17" width="17" xmlns="http://www.w3.org/2000/svg"><circle cx="8.5" cy="8.5" r="6" fill="#fc7f7f" stroke-width="1"/><path d="M1.077 14.239 14.192 1.084l1.779 1.784L2.855 16.022z" fill="#e0e0e0"/></svg>
+
diff --git a/editor/icons/DirectionalLight3D.svg b/editor/icons/DirectionalLight3D.svg
index ef25fd473a..a7c05452de 100644
--- a/editor/icons/DirectionalLight3D.svg
+++ b/editor/icons/DirectionalLight3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m7 1v3h2v-3zm-2.5352 2.0508-1.4141 1.4141 1.4141 1.4141 1.4141-1.4141zm7.0703 0-1.4141 1.4141 1.4141 1.4141 1.4141-1.4141zm-3.5352 1.9492c-1.6569 0-3 1.3432-3 3s1.3431 3 3 3 3-1.3432 3-3-1.3431-3-3-3zm-7 2v2h3v-2zm11 0v2h3v-2zm-7.5352 3.1211-1.4141 1.4141 1.4141 1.4141 1.4141-1.4141zm7.0703 0-1.4141 1.4141 1.4141 1.4141 1.4141-1.4141zm-4.5352 1.8789v3h2v-3z" fill="#fc7f7f" fill-opacity=".99608"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m7 1v3h2v-3zm-2.5352 2.0508-1.4141 1.4141 1.4141 1.4141 1.4141-1.4141zm7.0703 0-1.4141 1.4141 1.4141 1.4141 1.4141-1.4141zm-3.5352 1.9492c-1.6569 0-3 1.3432-3 3s1.3431 3 3 3 3-1.3432 3-3-1.3431-3-3-3zm-7 2v2h3v-2zm11 0v2h3v-2zm-7.5352 3.1211-1.4141 1.4141 1.4141 1.4141 1.4141-1.4141zm7.0703 0-1.4141 1.4141 1.4141 1.4141 1.4141-1.4141zm-4.5352 1.8789v3h2v-3z" fill="#fc7f7f"/></svg>
diff --git a/editor/icons/EditorPlugin.svg b/editor/icons/EditorPlugin.svg
index 7008762fa8..8fab923c6d 100644
--- a/editor/icons/EditorPlugin.svg
+++ b/editor/icons/EditorPlugin.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m2 1c-.55226.0001-.99994.4477-1 1v8c.0000552.5523.44774.9999 1 1h3v.27148a2 2 0 0 0 -1 1.7285 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -1-1.7305v-.26953h3c.55226-.0001.99994-.4477 1-1v-3h.27148a2 2 0 0 0 1.7285 1 2 2 0 0 0 2-2 2 2 0 0 0 -2-2 2 2 0 0 0 -1.7305 1h-.26953v-3c-.000055-.5523-.44774-.9999-1-1h-8z" fill="#e0e0e0" fill-opacity=".99608" fill-rule="evenodd"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m2 1c-.55226.0001-.99994.4477-1 1v8c.0000552.5523.44774.9999 1 1h3v.27148a2 2 0 0 0 -1 1.7285 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -1-1.7305v-.26953h3c.55226-.0001.99994-.4477 1-1v-3h.27148a2 2 0 0 0 1.7285 1 2 2 0 0 0 2-2 2 2 0 0 0 -2-2 2 2 0 0 0 -1.7305 1h-.26953v-3c-.000055-.5523-.44774-.9999-1-1h-8z" fill="#e0e0e0" fill-rule="evenodd"/></svg>
diff --git a/editor/icons/Eraser.svg b/editor/icons/Eraser.svg
index 4995fa863c..c9be2569ef 100644
--- a/editor/icons/Eraser.svg
+++ b/editor/icons/Eraser.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m10.228155 1.5447161-9.60250173 9.6107429 1.41421353 1.414213 1.6134635 1.885612.00693-.0069 4.2288056.000024 7.4852811-7.4852817zm-4.4456043 7.2823178 2.3136653 2.5858141-1.0357479 1.035746h-2.5853592l-1.0209853-1.293133z" fill="#e0e0e0" fill-opacity=".996078" stroke-width="1.02405"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m10.228155 1.5447161-9.60250173 9.6107429 1.41421353 1.414213 1.6134635 1.885612.00693-.0069 4.2288056.000024 7.4852811-7.4852817zm-4.4456043 7.2823178 2.3136653 2.5858141-1.0357479 1.035746h-2.5853592l-1.0209853-1.293133z" fill="#e0e0e0" stroke-width="1.02405"/></svg>
diff --git a/editor/icons/FogVolume.svg b/editor/icons/FogVolume.svg
index b0a18eb29d..89ee466db4 100644
--- a/editor/icons/FogVolume.svg
+++ b/editor/icons/FogVolume.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#fc7f7f"><g fill-opacity=".996078"><path d="m4.5 9.0000002c-.2761429-.0000014-.5000014.2238571-.5.5-.0000014.2761429.2238571.5000008.5.4999998l8-.0000002c.276143.0000012.500001-.2238569.5-.4999998.000001-.2761429-.223857-.5000014-.5-.5z"/><path d="m3.5 11c-.2761429-.000001-.5000014.223857-.5.5-.0000014.276143.2238571.500001.5.5h5c.2761429.000001.500001-.223857.5-.5.000001-.276143-.2238571-.500001-.5-.5z"/><path d="m5.5 13c-.2761424 0-.5.223858-.5.5s.2238576.5.5.5h5c.276142 0 .5-.223858.5-.5s-.223858-.5-.5-.5z"/></g><path d="m2.5 8s-1.5 0-1.5-1.5 2-1.5 2-1.5 0-4 3.5-4 3.5 3 3.5 3 1.260711-2 3-1 .5 3 .5 3 1.5 0 1.5 1-1 1-1 1z" fill-opacity=".99608"/><path d="m10.5 11c-.276143-.000001-.500001.223857-.5.5-.000001.276143.223857.500001.5.5h2.5c.276143.000001.500001-.223857.5-.5.000001-.276143-.223857-.500001-.5-.5z" fill-opacity=".996078"/></g></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#fc7f7f"><g><path d="m4.5 9.0000002c-.2761429-.0000014-.5000014.2238571-.5.5-.0000014.2761429.2238571.5000008.5.4999998l8-.0000002c.276143.0000012.500001-.2238569.5-.4999998.000001-.2761429-.223857-.5000014-.5-.5z"/><path d="m3.5 11c-.2761429-.000001-.5000014.223857-.5.5-.0000014.276143.2238571.500001.5.5h5c.2761429.000001.500001-.223857.5-.5.000001-.276143-.2238571-.500001-.5-.5z"/><path d="m5.5 13c-.2761424 0-.5.223858-.5.5s.2238576.5.5.5h5c.276142 0 .5-.223858.5-.5s-.223858-.5-.5-.5z"/></g><path d="m2.5 8s-1.5 0-1.5-1.5 2-1.5 2-1.5 0-4 3.5-4 3.5 3 3.5 3 1.260711-2 3-1 .5 3 .5 3 1.5 0 1.5 1-1 1-1 1z"/><path d="m10.5 11c-.276143-.000001-.500001.223857-.5.5-.000001.276143.223857.500001.5.5h2.5c.276143.000001.500001-.223857.5-.5.000001-.276143-.223857-.500001-.5-.5z"/></g></svg>
diff --git a/editor/icons/GPUParticles3D.svg b/editor/icons/GPUParticles3D.svg
index bbc90ec35f..521a93efc6 100644
--- a/editor/icons/GPUParticles3D.svg
+++ b/editor/icons/GPUParticles3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1a4.5 5 0 0 0 -4.4141 4.0312 3 3 0 0 0 -2.5859 2.9688 3 3 0 0 0 3 3h8a3 3 0 0 0 3-3 3 3 0 0 0 -2.5898-2.9668 4.5 5 0 0 0 -4.4102-4.0332zm-4 11a1 1 0 0 0 -1 1 1 1 0 0 0 1 1 1 1 0 0 0 1-1 1 1 0 0 0 -1-1zm8 0a1 1 0 0 0 -1 1 1 1 0 0 0 1 1 1 1 0 0 0 1-1 1 1 0 0 0 -1-1zm-4 1a1 1 0 0 0 -1 1 1 1 0 0 0 1 1 1 1 0 0 0 1-1 1 1 0 0 0 -1-1z" fill="#fc7f7f" fill-opacity=".99608"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1a4.5 5 0 0 0 -4.4141 4.0312 3 3 0 0 0 -2.5859 2.9688 3 3 0 0 0 3 3h8a3 3 0 0 0 3-3 3 3 0 0 0 -2.5898-2.9668 4.5 5 0 0 0 -4.4102-4.0332zm-4 11a1 1 0 0 0 -1 1 1 1 0 0 0 1 1 1 1 0 0 0 1-1 1 1 0 0 0 -1-1zm8 0a1 1 0 0 0 -1 1 1 1 0 0 0 1 1 1 1 0 0 0 1-1 1 1 0 0 0 -1-1zm-4 1a1 1 0 0 0 -1 1 1 1 0 0 0 1 1 1 1 0 0 0 1-1 1 1 0 0 0 -1-1z" fill="#fc7f7f"/></svg>
diff --git a/editor/icons/GPUParticlesAttractorBox3D.svg b/editor/icons/GPUParticlesAttractorBox3D.svg
index 7a2ee7a6b9..fdf65d11cb 100644
--- a/editor/icons/GPUParticlesAttractorBox3D.svg
+++ b/editor/icons/GPUParticlesAttractorBox3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><circle cx="8" cy="8" fill="#fc7f7f" fill-opacity=".996078" r="1"/><g fill="none" stroke="#fc7f7f" stroke-opacity=".996078"><ellipse cx="8" cy="-8" rx="2.339226" ry="4.949748" transform="rotate(90)"/><ellipse cx="8" cy="8" rx="2.339226" ry="4.949748"/><path d="m1.498906 1.498906h13.002189v13.002188h-13.002189z" stroke-width=".997813"/></g></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><circle cx="8" cy="8" fill="#fc7f7f" r="1"/><g fill="none" stroke="#fc7f7f"><ellipse cx="8" cy="-8" rx="2.339226" ry="4.949748" transform="rotate(90)"/><ellipse cx="8" cy="8" rx="2.339226" ry="4.949748"/><path d="m1.498906 1.498906h13.002189v13.002188h-13.002189z" stroke-width=".997813"/></g></svg>
diff --git a/editor/icons/GPUParticlesAttractorSphere3D.svg b/editor/icons/GPUParticlesAttractorSphere3D.svg
index 2215331a18..15a8016827 100644
--- a/editor/icons/GPUParticlesAttractorSphere3D.svg
+++ b/editor/icons/GPUParticlesAttractorSphere3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><ellipse cx="-8" cy="-7.999999" fill="none" rx="6.499003" ry="6.499001" stroke="#fc7f7f" stroke-opacity=".996078" stroke-width="1.002" transform="scale(-1)"/><circle cx="8" cy="8" fill="#fc7f7f" fill-opacity=".996078" r="1"/><g fill="none" stroke="#fc7f7f" stroke-opacity=".996078"><ellipse cx="11.313708" rx="2.339226" ry="4.949748" transform="matrix(.70710678 .70710678 -.70710678 .70710678 0 0)"/><ellipse cy="11.313708" rx="2.339226" ry="4.949748" transform="matrix(.70710678 -.70710678 .70710678 .70710678 0 0)"/></g></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><ellipse cx="-8" cy="-7.999999" fill="none" rx="6.499003" ry="6.499001" stroke="#fc7f7f" stroke-width="1.002" transform="scale(-1)"/><circle cx="8" cy="8" fill="#fc7f7f" r="1"/><g fill="none" stroke="#fc7f7f"><ellipse cx="11.313708" rx="2.339226" ry="4.949748" transform="matrix(.70710678 .70710678 -.70710678 .70710678 0 0)"/><ellipse cy="11.313708" rx="2.339226" ry="4.949748" transform="matrix(.70710678 -.70710678 .70710678 .70710678 0 0)"/></g></svg>
diff --git a/editor/icons/GPUParticlesAttractorVectorField3D.svg b/editor/icons/GPUParticlesAttractorVectorField3D.svg
index 87b2b21804..c9e0b4fae3 100644
--- a/editor/icons/GPUParticlesAttractorVectorField3D.svg
+++ b/editor/icons/GPUParticlesAttractorVectorField3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><ellipse cx="6.663637" cy="9.245457" fill="#fc7f7f" fill-opacity=".996078" rx="1.030661" ry=".998146"/><ellipse cx="-6.672815" cy="-9.387111" fill="none" rx="2.408711" ry="5.096776" stroke="#fc7f7f" stroke-opacity=".996078" stroke-width="1.0297" transform="matrix(-.99999945 .00104887 .00104887 -.99999945 0 0)"/><ellipse cx="9.387111" cy="-6.672815" fill="none" rx="2.408711" ry="5.096776" stroke="#fc7f7f" stroke-opacity=".996078" stroke-width="1.0297" transform="matrix(-.00104887 .99999945 -.99999945 .00104887 0 0)"/><g fill="#fc7f7f" fill-opacity=".996078"><path d="m11.8 15 2.4-2.4.8.8v-2.4h-2.4l.8.8-2.4 2.4z"/><path d="m11 6 3-3 1 1v-3h-3l1 1-3 3z"/><path d="m1.8 5 2.4-2.4.8.8v-2.4h-2.4l.8.8-2.4 2.4z"/></g></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><ellipse cx="6.663637" cy="9.245457" fill="#fc7f7f" rx="1.030661" ry=".998146"/><ellipse cx="-6.672815" cy="-9.387111" fill="none" rx="2.408711" ry="5.096776" stroke="#fc7f7f" stroke-width="1.0297" transform="matrix(-.99999945 .00104887 .00104887 -.99999945 0 0)"/><ellipse cx="9.387111" cy="-6.672815" fill="none" rx="2.408711" ry="5.096776" stroke="#fc7f7f" stroke-width="1.0297" transform="matrix(-.00104887 .99999945 -.99999945 .00104887 0 0)"/><g fill="#fc7f7f"><path d="m11.8 15 2.4-2.4.8.8v-2.4h-2.4l.8.8-2.4 2.4z"/><path d="m11 6 3-3 1 1v-3h-3l1 1-3 3z"/><path d="m1.8 5 2.4-2.4.8.8v-2.4h-2.4l.8.8-2.4 2.4z"/></g></svg>
diff --git a/editor/icons/GPUParticlesCollisionBox3D.svg b/editor/icons/GPUParticlesCollisionBox3D.svg
index 4f7325d086..ca595f16eb 100644
--- a/editor/icons/GPUParticlesCollisionBox3D.svg
+++ b/editor/icons/GPUParticlesCollisionBox3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 14.999999 14.999999" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#fc7f7f" fill-opacity=".996078"><path d="m7.5 2.8124998-5.5883107 2.7941554v5.7660988l5.5883107 2.794155 5.588311-2.794155v-5.7660988zm0 1.6886278 3.145021 1.5732692-3.145021 1.5717523-3.1450214-1.5717523zm-3.9916505 2.8362274 3.1933204 1.5966602v3.1465378l-3.1933204-1.598256zm7.9833015 0v3.145021l-3.1933209 1.598257v-3.146538z" stroke-width=".851579"/><circle cx="1.875" cy="3.75" r=".9375"/><circle cx="13.124999" cy="3.75" r=".9375"/><circle cx="9.374999" cy="1.875" r=".9375"/><circle cx="5.625" cy="1.875" r=".9375"/></g></svg>
+<svg height="16" viewBox="0 0 14.999999 14.999999" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#fc7f7f"><path d="m7.5 2.8124998-5.5883107 2.7941554v5.7660988l5.5883107 2.794155 5.588311-2.794155v-5.7660988zm0 1.6886278 3.145021 1.5732692-3.145021 1.5717523-3.1450214-1.5717523zm-3.9916505 2.8362274 3.1933204 1.5966602v3.1465378l-3.1933204-1.598256zm7.9833015 0v3.145021l-3.1933209 1.598257v-3.146538z" stroke-width=".851579"/><circle cx="1.875" cy="3.75" r=".9375"/><circle cx="13.124999" cy="3.75" r=".9375"/><circle cx="9.374999" cy="1.875" r=".9375"/><circle cx="5.625" cy="1.875" r=".9375"/></g></svg>
diff --git a/editor/icons/GPUParticlesCollisionSDF3D.svg b/editor/icons/GPUParticlesCollisionSDF3D.svg
index 00eca8295d..38fe6c49f8 100644
--- a/editor/icons/GPUParticlesCollisionSDF3D.svg
+++ b/editor/icons/GPUParticlesCollisionSDF3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m14 14h-12v-9s3 4 5.9999999 3.9999999c3.0000001-.0000001 6.0000001-3.9999999 6.0000001-3.9999999z" fill="none" stroke="#fc7f7f" stroke-linejoin="round" stroke-opacity=".996078" stroke-width="2"/><g fill="#fc7f7f" fill-opacity=".996078"><circle cx="2" cy="2" r="1"/><circle cx="14" cy="2" r="1"/><circle cx="10" cy="5" r="1"/><circle cx="6" cy="5" r="1"/></g></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m14 14h-12v-9s3 4 5.9999999 3.9999999c3.0000001-.0000001 6.0000001-3.9999999 6.0000001-3.9999999z" fill="none" stroke="#fc7f7f" stroke-linejoin="round" stroke-width="2"/><g fill="#fc7f7f"><circle cx="2" cy="2" r="1"/><circle cx="14" cy="2" r="1"/><circle cx="10" cy="5" r="1"/><circle cx="6" cy="5" r="1"/></g></svg>
diff --git a/editor/icons/GPUParticlesCollisionSphere3D.svg b/editor/icons/GPUParticlesCollisionSphere3D.svg
index cd188ddacc..4aa3f7c5bf 100644
--- a/editor/icons/GPUParticlesCollisionSphere3D.svg
+++ b/editor/icons/GPUParticlesCollisionSphere3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#fc7f7f" fill-opacity=".996078"><path d="m8 3.0532484c-3.2888554 0-5.9733758 2.6845204-5.9733758 5.9733758 0 3.2889408 2.6845204 5.9733758 5.9733758 5.9733758 3.288855 0 5.973376-2.684435 5.973376-5.9733758 0-3.2888554-2.684521-5.9733758-5.973376-5.9733758zm-.8533394 1.79005v4.1567016c-1.1034532-.0608789-2.2238878-.2544573-3.3650586-.5900074.256693-1.7901354 1.6087154-3.2141029 3.3650586-3.5667027zm1.7066788 0c1.7535276.3520281 3.1035956 1.77213 3.3633516 3.55834-1.113266.3129793-2.2321649.5142138-3.3633516.5866709zm3.2300606 5.3599956c-.434043 1.51792-1.663927 2.690664-3.2300606 3.005035v-2.518376c1.0915918-.0617 2.1691036-.227875 3.2300606-.486668zm-8.161765.015c1.0865571.272147 2.162106.428504 3.2250256.480003v2.510013c-1.5608431-.313338-2.7870065-1.479605-3.2250256-2.990016z" stroke-width=".853339"/><circle cx="2" cy="5" r="1"/><circle cx="14" cy="5" r="1"/><circle cx="10" cy="2" r="1"/><circle cx="6" cy="2" r="1"/></g></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#fc7f7f"><path d="m8 3.0532484c-3.2888554 0-5.9733758 2.6845204-5.9733758 5.9733758 0 3.2889408 2.6845204 5.9733758 5.9733758 5.9733758 3.288855 0 5.973376-2.684435 5.973376-5.9733758 0-3.2888554-2.684521-5.9733758-5.973376-5.9733758zm-.8533394 1.79005v4.1567016c-1.1034532-.0608789-2.2238878-.2544573-3.3650586-.5900074.256693-1.7901354 1.6087154-3.2141029 3.3650586-3.5667027zm1.7066788 0c1.7535276.3520281 3.1035956 1.77213 3.3633516 3.55834-1.113266.3129793-2.2321649.5142138-3.3633516.5866709zm3.2300606 5.3599956c-.434043 1.51792-1.663927 2.690664-3.2300606 3.005035v-2.518376c1.0915918-.0617 2.1691036-.227875 3.2300606-.486668zm-8.161765.015c1.0865571.272147 2.162106.428504 3.2250256.480003v2.510013c-1.5608431-.313338-2.7870065-1.479605-3.2250256-2.990016z" stroke-width=".853339"/><circle cx="2" cy="5" r="1"/><circle cx="14" cy="5" r="1"/><circle cx="10" cy="2" r="1"/><circle cx="6" cy="2" r="1"/></g></svg>
diff --git a/editor/icons/GradientTexture1D.svg b/editor/icons/GradientTexture1D.svg
index fa03e69805..9be4b00329 100644
--- a/editor/icons/GradientTexture1D.svg
+++ b/editor/icons/GradientTexture1D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0"><path d="m12.5 10.5v-7h-3v1h-1v1h1v1h-1v1h1v1h-1v1h1v1zm-4-1h-1v1h1zm-1 0v-1h-1v1zm0-1h1v-1h-1zm0-1v-1h-1v1zm0-1h1v-1h-1zm0-1v-1h-1v1zm0-1h1v-1h-1z" stroke-width=".787342"/><path d="m2 1c-.552285 0-1 .4477153-1 1v12.000001c0 .552285.447715 1 1 1h11.999999c.552285 0 1-.447715 1-1v-12.000001c0-.5522847-.447715-1-1-1zm1 2.0000001h9.999999v8.0000009h-9.999999z" fill-opacity=".99608"/></g></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0"><path d="m12.5 10.5v-7h-3v1h-1v1h1v1h-1v1h1v1h-1v1h1v1zm-4-1h-1v1h1zm-1 0v-1h-1v1zm0-1h1v-1h-1zm0-1v-1h-1v1zm0-1h1v-1h-1zm0-1v-1h-1v1zm0-1h1v-1h-1z" stroke-width=".787342"/><path d="m2 1c-.552285 0-1 .4477153-1 1v12.000001c0 .552285.447715 1 1 1h11.999999c.552285 0 1-.447715 1-1v-12.000001c0-.5522847-.447715-1-1-1zm1 2.0000001h9.999999v8.0000009h-9.999999z"/></g></svg>
diff --git a/editor/icons/GuiVisibilityHidden.svg b/editor/icons/GuiVisibilityHidden.svg
index 6152fe8acf..1052d6dfcb 100644
--- a/editor/icons/GuiVisibilityHidden.svg
+++ b/editor/icons/GuiVisibilityHidden.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m2.9609 7.7266-1.9219.54883c.31999 1.12.8236 2.0593 1.4316 2.8398l-.83398.83398 1.4141 1.4141.84375-.84375c.98585.74762 2.0766 1.2067 3.1055 1.3867v1.0938h2v-1.0938c1.0288-.17998 2.1196-.6391 3.1055-1.3867l.84375.84375 1.4141-1.4141-.83398-.83398c.60804-.78055 1.1117-1.7199 1.4316-2.8398l-1.9219-.54883c-.8756 3.0646-3.5391 4.2734-5.0391 4.2734s-4.1635-1.2088-5.0391-4.2734z" fill="#e0e0e0" fill-opacity=".99608" fill-rule="evenodd"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m2.9609 7.7266-1.9219.54883c.31999 1.12.8236 2.0593 1.4316 2.8398l-.83398.83398 1.4141 1.4141.84375-.84375c.98585.74762 2.0766 1.2067 3.1055 1.3867v1.0938h2v-1.0938c1.0288-.17998 2.1196-.6391 3.1055-1.3867l.84375.84375 1.4141-1.4141-.83398-.83398c.60804-.78055 1.1117-1.7199 1.4316-2.8398l-1.9219-.54883c-.8756 3.0646-3.5391 4.2734-5.0391 4.2734s-4.1635-1.2088-5.0391-4.2734z" fill="#e0e0e0" fill-rule="evenodd"/></svg>
diff --git a/editor/icons/GuiVisibilityVisible.svg b/editor/icons/GuiVisibilityVisible.svg
index 32eaea633b..96659eb655 100644
--- a/editor/icons/GuiVisibilityVisible.svg
+++ b/editor/icons/GuiVisibilityVisible.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 2c-2.5567 0-5.7907 1.9477-6.9551 5.7051a1.0001 1.0001 0 0 0 -.00586.57031c1.1244 3.9354 4.4609 5.7246 6.9609 5.7246s5.8365-1.7892 6.9609-5.7246a1.0001 1.0001 0 0 0 0-.55273c-1.1003-3.7876-4.4066-5.7227-6.9609-5.7227zm0 2a4 4 0 0 1 4 4 4 4 0 0 1 -4 4 4 4 0 0 1 -4-4 4 4 0 0 1 4-4zm0 2a2 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" fill="#e0e0e0" fill-opacity=".99608" fill-rule="evenodd"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 2c-2.5567 0-5.7907 1.9477-6.9551 5.7051a1.0001 1.0001 0 0 0 -.00586.57031c1.1244 3.9354 4.4609 5.7246 6.9609 5.7246s5.8365-1.7892 6.9609-5.7246a1.0001 1.0001 0 0 0 0-.55273c-1.1003-3.7876-4.4066-5.7227-6.9609-5.7227zm0 2a4 4 0 0 1 4 4 4 4 0 0 1 -4 4 4 4 0 0 1 -4-4 4 4 0 0 1 4-4zm0 2a2 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" fill="#e0e0e0" fill-rule="evenodd"/></svg>
diff --git a/editor/icons/GuiVisibilityXray.svg b/editor/icons/GuiVisibilityXray.svg
index 109911df45..29ca9d0810 100644
--- a/editor/icons/GuiVisibilityXray.svg
+++ b/editor/icons/GuiVisibilityXray.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0" fill-rule="evenodd"><path d="m7.9998 2c-2.5567 0-5.7907 1.9477-6.9551 5.7051a1.0001 1.0001 0 0 0 -.00586.5703c1.1244 3.9354 4.4609 5.7246 6.9609 5.7246s5.8365-1.7892 6.9609-5.7246a1.0001 1.0001 0 0 0 0-.5527c-1.1003-3.7876-4.4066-5.7227-6.9609-5.7227zm0 2a4 4 0 0 1 4 4 4 4 0 0 1 -4 4 4 4 0 0 1 -4-4 4 4 0 0 1 4-4zm0 2a2 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" fill-opacity=".39216"/><path d="m8 2c-2.5567 0-5.7907 1.9477-6.9551 5.7051a1.0001 1.0001 0 0 0 -.00586.57031c1.1244 3.9354 4.4609 5.7246 6.9609 5.7246v-2a4 4 0 0 1 -4-4 4 4 0 0 1 4-4zm0 4a2 2 0 0 0 -2 2 2 2 0 0 0 2 2z" fill-opacity=".99608"/></g></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0" fill-rule="evenodd"><path d="m7.9998 2c-2.5567 0-5.7907 1.9477-6.9551 5.7051a1.0001 1.0001 0 0 0 -.00586.5703c1.1244 3.9354 4.4609 5.7246 6.9609 5.7246s5.8365-1.7892 6.9609-5.7246a1.0001 1.0001 0 0 0 0-.5527c-1.1003-3.7876-4.4066-5.7227-6.9609-5.7227zm0 2a4 4 0 0 1 4 4 4 4 0 0 1 -4 4 4 4 0 0 1 -4-4 4 4 0 0 1 4-4zm0 2a2 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" fill-opacity=".39216"/><path d="m8 2c-2.5567 0-5.7907 1.9477-6.9551 5.7051a1.0001 1.0001 0 0 0 -.00586.57031c1.1244 3.9354 4.4609 5.7246 6.9609 5.7246v-2a4 4 0 0 1 -4-4 4 4 0 0 1 4-4zm0 4a2 2 0 0 0 -2 2 2 2 0 0 0 2 2z"/></g></svg>
diff --git a/editor/icons/HTTPRequest.svg b/editor/icons/HTTPRequest.svg
index 1a2187fe15..34912dcd2b 100644
--- a/editor/icons/HTTPRequest.svg
+++ b/editor/icons/HTTPRequest.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m4 1-3 4h2v3h2v-3h2zm7 0v3h-2l3 4 3-4h-2v-3zm-10 9v2 1 2h1v-2h1v2h1v-5h-1v2h-1v-2zm4 0v1h1v4h1v-4h1v-1zm4 0v1h1v4h1v-4h1v-1zm4 0v2 1 2h1v-2h1 1v-1-2h-2zm1 1h1v1h-1z" fill="#e0e0e0" fill-opacity=".99608"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m4 1-3 4h2v3h2v-3h2zm7 0v3h-2l3 4 3-4h-2v-3zm-10 9v2 1 2h1v-2h1v2h1v-5h-1v2h-1v-2zm4 0v1h1v4h1v-4h1v-1zm4 0v1h1v4h1v-4h1v-1zm4 0v2 1 2h1v-2h1 1v-1-2h-2zm1 1h1v1h-1z" fill="#e0e0e0"/></svg>
diff --git a/editor/icons/History.svg b/editor/icons/History.svg
index 45bc565088..cb1bb4178f 100644
--- a/editor/icons/History.svg
+++ b/editor/icons/History.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0" fill-opacity=".99608" transform="translate(0 -1036.4)"><path d="m9 2a6 6 0 0 0 -6 6h2a4 4 0 0 1 4-4 4 4 0 0 1 4 4 4 4 0 0 1 -4 4v2a6 6 0 0 0 6-6 6 6 0 0 0 -6-6z" transform="translate(0 1036.4)"/><path d="m4.118 1048.3-1.6771-.9683-1.6771-.9682 1.6771-.9683 1.6771-.9682-.0000001 1.9365z" transform="matrix(0 -1.1926 1.5492 0 -1617 1049.3)"/><path d="m8 1041.4h2v4h-2z"/><path d="m8 1043.4h4v2h-4z"/></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)"><path d="m9 2a6 6 0 0 0 -6 6h2a4 4 0 0 1 4-4 4 4 0 0 1 4 4 4 4 0 0 1 -4 4v2a6 6 0 0 0 6-6 6 6 0 0 0 -6-6z" transform="translate(0 1036.4)"/><path d="m4.118 1048.3-1.6771-.9683-1.6771-.9682 1.6771-.9683 1.6771-.9682-.0000001 1.9365z" transform="matrix(0 -1.1926 1.5492 0 -1617 1049.3)"/><path d="m8 1041.4h2v4h-2z"/><path d="m8 1043.4h4v2h-4z"/></g></svg>
diff --git a/editor/icons/Hsize.svg b/editor/icons/Hsize.svg
index c7b62e58c8..cf805fce50 100644
--- a/editor/icons/Hsize.svg
+++ b/editor/icons/Hsize.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m4 7v-2l-3 3 3 3v-2h8v2l3-3-3-3v2z" fill="#e0e0e0" fill-opacity=".99608"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m4 7v-2l-3 3 3 3v-2h8v2l3-3-3-3v2z" fill="#e0e0e0"/></svg>
diff --git a/editor/icons/Image.svg b/editor/icons/Image.svg
index ddf97ec59e..a990974a4f 100644
--- a/editor/icons/Image.svg
+++ b/editor/icons/Image.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m2 1a1 1 0 0 0 -1 1v12a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-12a1 1 0 0 0 -1-1zm1 2h10v8h-10zm6 2-1.5 2.5-.70117 1.168-.099609-.16797-.89844-1.5-.90039 1.5-.90039 1.5h1.8008.19922 1.5996 1.4004 3l-1.5-2.5-1.5-2.5z" fill="#e0e0e0" fill-opacity=".99608"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m2 1a1 1 0 0 0 -1 1v12a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-12a1 1 0 0 0 -1-1zm1 2h10v8h-10zm6 2-1.5 2.5-.70117 1.168-.099609-.16797-.89844-1.5-.90039 1.5-.90039 1.5h1.8008.19922 1.5996 1.4004 3l-1.5-2.5-1.5-2.5z" fill="#e0e0e0"/></svg>
diff --git a/editor/icons/ImageTexture.svg b/editor/icons/ImageTexture.svg
index 013e847db3..25d4b53d00 100644
--- a/editor/icons/ImageTexture.svg
+++ b/editor/icons/ImageTexture.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m2 1a1 1 0 0 0 -1 1v12a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-12a1 1 0 0 0 -1-1zm1 2h10v8h-10zm6 2v1h-1v1h-2v1h-1v1h-1v1h2 2 2 2v-2h-1v-2h-1v-1z" fill="#e0e0e0" fill-opacity=".99608"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m2 1a1 1 0 0 0 -1 1v12a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-12a1 1 0 0 0 -1-1zm1 2h10v8h-10zm6 2v1h-1v1h-2v1h-1v1h-1v1h2 2 2 2v-2h-1v-2h-1v-1z" fill="#e0e0e0"/></svg>
diff --git a/editor/icons/JoyAxis.svg b/editor/icons/JoyAxis.svg
index 1ab65f0af0..11c694aede 100644
--- a/editor/icons/JoyAxis.svg
+++ b/editor/icons/JoyAxis.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g transform="translate(0 -1036.4)"><path d="m27 1038.4h7v14h-7z" fill="#fff" fill-opacity=".99608"/><g fill="#e0e0e0"><path d="m3 1a2 2 0 0 0 -2 2v10a2 2 0 0 0 2 2h12v-14zm4 2h2a1 1 0 0 1 1 1v2h2a1 1 0 0 1 1 1v2a1 1 0 0 1 -1 1h-2v2a1 1 0 0 1 -1 1h-2a1 1 0 0 1 -1-1v-2h-2a1 1 0 0 1 -1-1v-2a1 1 0 0 1 1-1h2v-2a1 1 0 0 1 1-1z" fill-opacity=".99608" transform="translate(0 1036.4)"/><circle cx="8" cy="1044.4" r="1"/></g></g></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g transform="translate(0 -1036.4)"><path d="m27 1038.4h7v14h-7z" fill="#fff"/><g fill="#e0e0e0"><path d="m3 1a2 2 0 0 0 -2 2v10a2 2 0 0 0 2 2h12v-14zm4 2h2a1 1 0 0 1 1 1v2h2a1 1 0 0 1 1 1v2a1 1 0 0 1 -1 1h-2v2a1 1 0 0 1 -1 1h-2a1 1 0 0 1 -1-1v-2h-2a1 1 0 0 1 -1-1v-2a1 1 0 0 1 1-1h2v-2a1 1 0 0 1 1-1z" transform="translate(0 1036.4)"/><circle cx="8" cy="1044.4" r="1"/></g></g></svg>
diff --git a/editor/icons/JoyButton.svg b/editor/icons/JoyButton.svg
index 080d91ad53..d3d6e22929 100644
--- a/editor/icons/JoyButton.svg
+++ b/editor/icons/JoyButton.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill-opacity=".99608" transform="translate(0 -1036.4)"><path d="m27 1038.4h7v14h-7z" fill="#fff"/><path d="m1 1v14h12c1.1046 0 2-.8954 2-2v-10c0-1.1046-.89543-2-2-2zm7 1a2 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-2zm-4 4a2 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-2zm8 0a2 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-2zm-4 4a2 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="#e0e0e0" 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 transform="translate(0 -1036.4)"><path d="m27 1038.4h7v14h-7z" fill="#fff"/><path d="m1 1v14h12c1.1046 0 2-.8954 2-2v-10c0-1.1046-.89543-2-2-2zm7 1a2 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-2zm-4 4a2 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-2zm8 0a2 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-2zm-4 4a2 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="#e0e0e0" transform="translate(0 1036.4)"/></g></svg>
diff --git a/editor/icons/Joypad.svg b/editor/icons/Joypad.svg
index 3c6bbf2980..ead745379b 100644
--- a/editor/icons/Joypad.svg
+++ b/editor/icons/Joypad.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 3c-.55226.0000552-.99994.44774-1 1v8c.0000552.55226.44774.99994 1 1h14c.55226-.000055.99994-.44774 1-1v-8c-.000055-.55226-.44774-.99994-1-1zm2 2h2v2h2v2h-2v2h-2v-2h-2v-2h2zm10.5 0a1.5 1.5 0 0 1 1.5 1.5 1.5 1.5 0 0 1 -1.5 1.5 1.5 1.5 0 0 1 -1.5-1.5 1.5 1.5 0 0 1 1.5-1.5zm-3 3a1.5 1.5 0 0 1 1.5 1.5 1.5 1.5 0 0 1 -1.5 1.5 1.5 1.5 0 0 1 -1.5-1.5 1.5 1.5 0 0 1 1.5-1.5z" fill="#e0e0e0" fill-opacity=".99608" fill-rule="evenodd"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 3c-.55226.0000552-.99994.44774-1 1v8c.0000552.55226.44774.99994 1 1h14c.55226-.000055.99994-.44774 1-1v-8c-.000055-.55226-.44774-.99994-1-1zm2 2h2v2h2v2h-2v2h-2v-2h-2v-2h2zm10.5 0a1.5 1.5 0 0 1 1.5 1.5 1.5 1.5 0 0 1 -1.5 1.5 1.5 1.5 0 0 1 -1.5-1.5 1.5 1.5 0 0 1 1.5-1.5zm-3 3a1.5 1.5 0 0 1 1.5 1.5 1.5 1.5 0 0 1 -1.5 1.5 1.5 1.5 0 0 1 -1.5-1.5 1.5 1.5 0 0 1 1.5-1.5z" fill="#e0e0e0" fill-rule="evenodd"/></svg>
diff --git a/editor/icons/Key.svg b/editor/icons/Key.svg
index 544ebe5a47..01bf51dbd8 100644
--- a/editor/icons/Key.svg
+++ b/editor/icons/Key.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m11 4a4 4 0 0 0 -3.8691 3h-6.1309v2h1v2h3v-2h2.1328a4 4 0 0 0 3.8672 3 4 4 0 0 0 4-4 4 4 0 0 0 -4-4zm0 2a2 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="#e0e0e0" fill-opacity=".99608"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m11 4a4 4 0 0 0 -3.8691 3h-6.1309v2h1v2h3v-2h2.1328a4 4 0 0 0 3.8672 3 4 4 0 0 0 4-4 4 4 0 0 0 -4-4zm0 2a2 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="#e0e0e0"/></svg>
diff --git a/editor/icons/KeyNext.svg b/editor/icons/KeyNext.svg
index 83a8329494..47387c875a 100644
--- a/editor/icons/KeyNext.svg
+++ b/editor/icons/KeyNext.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m11 9v2h-2v2h2v2h2v-2h2v-2h-2v-2z" fill="#5fff97"/><path d="m11 1a4 4 0 0 0 -3.8691 3h-6.1309v2h1v2h3v-2h2.1328a4 4 0 0 0 2.8672 2.8691v-.86914h3.6387a4 4 0 0 0 1.3613-3 4 4 0 0 0 -4-4zm0 2a2 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="#e0e0e0" fill-opacity=".99608"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m11 9v2h-2v2h2v2h2v-2h2v-2h-2v-2z" fill="#5fff97"/><path d="m11 1a4 4 0 0 0 -3.8691 3h-6.1309v2h1v2h3v-2h2.1328a4 4 0 0 0 2.8672 2.8691v-.86914h3.6387a4 4 0 0 0 1.3613-3 4 4 0 0 0 -4-4zm0 2a2 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="#e0e0e0"/></svg>
diff --git a/editor/icons/KeyPosition.svg b/editor/icons/KeyPosition.svg
index 260a6f582f..c0fa703462 100644
--- a/editor/icons/KeyPosition.svg
+++ b/editor/icons/KeyPosition.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1c-.195 0-.38964.07519-.53906.22461l-3.2363 3.2363c-.29884.29884-.29884.77929 0 1.0781l3.2363 3.2363c.29884.29884.77929.29884 1.0781 0l3.2363-3.2363c.29884-.29884.29884-.77929 0-1.0781l-3.2363-3.2363c-.14942-.14942-.34406-.22461-.53906-.22461zm-7 7v5c0 1.6569 1.3471 3.114 3 3h1v-2h-1c-.55228-.00001-.99999-.44772-1-1v-5zm7 2c-1.645 0-3 1.355-3 3s1.355 3 3 3 3-1.355 3-3-1.355-3-3-3zm3 3c0 1.6569 1.3431 3 3 3h1v-2h-1c-.55228-.00001-.99999-.44772-1-1 .00001-.55228.44772-.99999 1-1h1v-2h-1c-1.6569 0-3 1.3431-3 3zm-3-1c.56413 0 1 .4359 1 1 0 .5642-.43587 1-1 1s-1-.4358-1-1c0-.5641.43587-1 1-1z" fill="#e0e0e0" fill-opacity=".99608"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1c-.195 0-.38964.07519-.53906.22461l-3.2363 3.2363c-.29884.29884-.29884.77929 0 1.0781l3.2363 3.2363c.29884.29884.77929.29884 1.0781 0l3.2363-3.2363c.29884-.29884.29884-.77929 0-1.0781l-3.2363-3.2363c-.14942-.14942-.34406-.22461-.53906-.22461zm-7 7v5c0 1.6569 1.3471 3.114 3 3h1v-2h-1c-.55228-.00001-.99999-.44772-1-1v-5zm7 2c-1.645 0-3 1.355-3 3s1.355 3 3 3 3-1.355 3-3-1.355-3-3-3zm3 3c0 1.6569 1.3431 3 3 3h1v-2h-1c-.55228-.00001-.99999-.44772-1-1 .00001-.55228.44772-.99999 1-1h1v-2h-1c-1.6569 0-3 1.3431-3 3zm-3-1c.56413 0 1 .4359 1 1 0 .5642-.43587 1-1 1s-1-.4358-1-1c0-.5641.43587-1 1-1z" fill="#e0e0e0"/></svg>
diff --git a/editor/icons/KeyRotation.svg b/editor/icons/KeyRotation.svg
index 284a835467..391511df7c 100644
--- a/editor/icons/KeyRotation.svg
+++ b/editor/icons/KeyRotation.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1c-.195 0-.38964.07519-.53906.22461l-3.2363 3.2363c-.29884.29884-.29884.77929 0 1.0781l3.2363 3.2363c.29884.29884.77929.29884 1.0781 0l3.2363-3.2363c.29884-.29884.29884-.77929 0-1.0781l-3.2363-3.2363c-.14942-.14942-.34406-.22461-.53906-.22461zm3 7v5c0 1.6569 1.3431 3 3 3h1v-2h-1c-.55228 0-.99999-.4477-1-1v-1h2v-2h-2v-2zm0 5c0-1.645-1.355-3-3-3s-3 1.355-3 3 1.355 3 3 3 3-1.355 3-3zm-7-3c-1.6569 0-3 1.3431-3 3v3h2v-3c.0000096-.5523.44772-1 1-1h1v-2zm4 2c.56413 0 1 .4359 1 1 0 .5642-.43587 1-1 1s-1-.4358-1-1c0-.5641.43587-1 1-1z" fill="#e0e0e0" fill-opacity=".99608"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1c-.195 0-.38964.07519-.53906.22461l-3.2363 3.2363c-.29884.29884-.29884.77929 0 1.0781l3.2363 3.2363c.29884.29884.77929.29884 1.0781 0l3.2363-3.2363c.29884-.29884.29884-.77929 0-1.0781l-3.2363-3.2363c-.14942-.14942-.34406-.22461-.53906-.22461zm3 7v5c0 1.6569 1.3431 3 3 3h1v-2h-1c-.55228 0-.99999-.4477-1-1v-1h2v-2h-2v-2zm0 5c0-1.645-1.355-3-3-3s-3 1.355-3 3 1.355 3 3 3 3-1.355 3-3zm-7-3c-1.6569 0-3 1.3431-3 3v3h2v-3c.0000096-.5523.44772-1 1-1h1v-2zm4 2c.56413 0 1 .4359 1 1 0 .5642-.43587 1-1 1s-1-.4358-1-1c0-.5641.43587-1 1-1z" fill="#e0e0e0"/></svg>
diff --git a/editor/icons/KeyScale.svg b/editor/icons/KeyScale.svg
index 84805191f2..5caf80e68e 100644
--- a/editor/icons/KeyScale.svg
+++ b/editor/icons/KeyScale.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1c-.195 0-.38964.07519-.53906.22461l-3.2363 3.2363c-.29884.29884-.29884.77929 0 1.0781l3.2363 3.2363c.29884.29884.77929.29884 1.0781 0l3.2363-3.2363c.29884-.29884.29884-.77929 0-1.0781l-3.2363-3.2363c-.14942-.14942-.34406-.22461-.53906-.22461zm3 7v5c0 1.6569 1.3431 3 3 3h1v-2h-1c-.55228-.00001-.99999-.44772-1-1v-5zm-8 2c-.71466-.0001-1.3751.3811-1.7324 1-.35727.6188-.35727 1.3812 0 2 .35733.6189 1.0178 1.0001 1.7324 1h-2v2h2c.71466.0001 1.3751-.3811 1.7324-1 .35727-.6188.35727-1.3812 0-2-.35733-.6189-1.0178-1.0001-1.7324-1h2v-2zm6 0c-1.6569 0-3 1.3431-3 3s1.3431 3 3 3h1v-2h-1c-.55228-.00001-.99999-.44772-1-1 .0000096-.55228.44772-.99999 1-1h1v-2z" fill="#e0e0e0" fill-opacity=".99608"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1c-.195 0-.38964.07519-.53906.22461l-3.2363 3.2363c-.29884.29884-.29884.77929 0 1.0781l3.2363 3.2363c.29884.29884.77929.29884 1.0781 0l3.2363-3.2363c.29884-.29884.29884-.77929 0-1.0781l-3.2363-3.2363c-.14942-.14942-.34406-.22461-.53906-.22461zm3 7v5c0 1.6569 1.3431 3 3 3h1v-2h-1c-.55228-.00001-.99999-.44772-1-1v-5zm-8 2c-.71466-.0001-1.3751.3811-1.7324 1-.35727.6188-.35727 1.3812 0 2 .35733.6189 1.0178 1.0001 1.7324 1h-2v2h2c.71466.0001 1.3751-.3811 1.7324-1 .35727-.6188.35727-1.3812 0-2-.35733-.6189-1.0178-1.0001-1.7324-1h2v-2zm6 0c-1.6569 0-3 1.3431-3 3s1.3431 3 3 3h1v-2h-1c-.55228-.00001-.99999-.44772-1-1 .0000096-.55228.44772-.99999 1-1h1v-2z" fill="#e0e0e0"/></svg>
diff --git a/editor/icons/LightmapProbe.svg b/editor/icons/LightmapProbe.svg
index 07f2b41a7c..dc5d8321e7 100644
--- a/editor/icons/LightmapProbe.svg
+++ b/editor/icons/LightmapProbe.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 9h3v-2h-3zm2.050781 2.535156 1.414063 1.414063 1.414062-1.414063-1.414062-1.414062zm0-7.070312 1.414063 1.414062 1.414062-1.414062-1.414062-1.414063zm1.949219 3.535156c0 1.6569 1.3432 3 3 3s3-1.3431 3-3-1.3432-3-3-3-3 1.3431-3 3zm3 7c3.865993 0 7-3.134007 7-7s-3.134007-7-7-7v2.333984c2.577329 0 4.666016 2.088687 4.666016 4.666016s-2.088687 4.666016-4.666016 4.666016z" fill="#fc7f7f" fill-opacity=".996078" stroke-width="1.16667"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 9h3v-2h-3zm2.050781 2.535156 1.414063 1.414063 1.414062-1.414063-1.414062-1.414062zm0-7.070312 1.414063 1.414062 1.414062-1.414062-1.414062-1.414063zm1.949219 3.535156c0 1.6569 1.3432 3 3 3s3-1.3431 3-3-1.3432-3-3-3-3 1.3431-3 3zm3 7c3.865993 0 7-3.134007 7-7s-3.134007-7-7-7v2.333984c2.577329 0 4.666016 2.088687 4.666016 4.666016s-2.088687 4.666016-4.666016 4.666016z" fill="#fc7f7f" stroke-width="1.16667"/></svg>
diff --git a/editor/icons/ListSelect.svg b/editor/icons/ListSelect.svg
index 9e2bf381d3..f1dac744d4 100644
--- a/editor/icons/ListSelect.svg
+++ b/editor/icons/ListSelect.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 1v14h8.2578l-.82227-2h-5.4355v-2h4.6113l-.82227-2h-3.7891v-2h3.8867a1.5002 1.5002 0 0 1 1.0977-.49805v-.0019531a1.5002 1.5002 0 0 1 .58594.11133l.94531.38867h.48438v.19922l2 .82227v-7.0215h-11zm2 2h7v2h-7zm5 5 3.291 8 .94726-2.8203 1.8828 1.8828.94336-.94141-1.8848-1.8828 2.8203-.94726-8-3.291z" fill="#e0e0e0" fill-opacity=".99608"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 1v14h8.2578l-.82227-2h-5.4355v-2h4.6113l-.82227-2h-3.7891v-2h3.8867a1.5002 1.5002 0 0 1 1.0977-.49805v-.0019531a1.5002 1.5002 0 0 1 .58594.11133l.94531.38867h.48438v.19922l2 .82227v-7.0215h-11zm2 2h7v2h-7zm5 5 3.291 8 .94726-2.8203 1.8828 1.8828.94336-.94141-1.8848-1.8828 2.8203-.94726-8-3.291z" fill="#e0e0e0"/></svg>
diff --git a/editor/icons/Loop.svg b/editor/icons/Loop.svg
index 7fd8561bc4..9bbf168189 100644
--- a/editor/icons/Loop.svg
+++ b/editor/icons/Loop.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1v2h-2a5 5 0 0 0 -5 5 5 5 0 0 0 1.0039 2.9961l1.4355-1.4355a3 3 0 0 1 -.43945-1.5605 3 3 0 0 1 3-3h2v2l2-1.5 2-1.5-2-1.5-2-1.5zm5.9961 4.0039-1.4355 1.4355a3 3 0 0 1 .43945 1.5605 3 3 0 0 1 -3 3h-2v-2l-2 1.5-2 1.5 2 1.5 2 1.5v-2h2a5 5 0 0 0 5-5 5 5 0 0 0 -1.0039-2.9961z" fill="#e0e0e0" fill-opacity=".99608"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1v2h-2a5 5 0 0 0 -5 5 5 5 0 0 0 1.0039 2.9961l1.4355-1.4355a3 3 0 0 1 -.43945-1.5605 3 3 0 0 1 3-3h2v2l2-1.5 2-1.5-2-1.5-2-1.5zm5.9961 4.0039-1.4355 1.4355a3 3 0 0 1 .43945 1.5605 3 3 0 0 1 -3 3h-2v-2l-2 1.5-2 1.5 2 1.5 2 1.5v-2h2a5 5 0 0 0 5-5 5 5 0 0 0 -1.0039-2.9961z" fill="#e0e0e0"/></svg>
diff --git a/editor/icons/Marker3D.svg b/editor/icons/Marker3D.svg
index 894b195589..bbc531cc3e 100644
--- a/editor/icons/Marker3D.svg
+++ b/editor/icons/Marker3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m7 1v4h2v-4zm-6 6v2h4v-2zm10 0v2h4v-2zm-4 4v4h2v-4z" fill="#fc7f7f" fill-opacity=".99608"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m7 1v4h2v-4zm-6 6v2h4v-2zm10 0v2h4v-2zm-4 4v4h2v-4z" fill="#fc7f7f"/></svg>
diff --git a/editor/icons/MeshInstance3D.svg b/editor/icons/MeshInstance3D.svg
index a9258505f8..67757dafd2 100644
--- a/editor/icons/MeshInstance3D.svg
+++ b/editor/icons/MeshInstance3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 1a2 2 0 0 0 -2 2 2 2 0 0 0 1 1.7305v6.541a2 2 0 0 0 -1 1.7285 2 2 0 0 0 2 2 2 2 0 0 0 1.7305-1h6.541a2 2 0 0 0 1.7285 1 2 2 0 0 0 2-2 2 2 0 0 0 -1.0312-1.75h.03125v-6.5215a2 2 0 0 0 1-1.7285 2 2 0 0 0 -2-2 2 2 0 0 0 -1.7305 1h-6.541a2 2 0 0 0 -1.7285-1zm2.4141 3h5.8574a2 2 0 0 0 .72852.73047v5.8555l-6.5859-6.5859zm-1.4141 1.4141 6.5859 6.5859h-5.8574a2 2 0 0 0 -.72852-.73047v-5.8555z" fill="#fc7f7f" fill-opacity=".99608"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 1a2 2 0 0 0 -2 2 2 2 0 0 0 1 1.7305v6.541a2 2 0 0 0 -1 1.7285 2 2 0 0 0 2 2 2 2 0 0 0 1.7305-1h6.541a2 2 0 0 0 1.7285 1 2 2 0 0 0 2-2 2 2 0 0 0 -1.0312-1.75h.03125v-6.5215a2 2 0 0 0 1-1.7285 2 2 0 0 0 -2-2 2 2 0 0 0 -1.7305 1h-6.541a2 2 0 0 0 -1.7285-1zm2.4141 3h5.8574a2 2 0 0 0 .72852.73047v5.8555l-6.5859-6.5859zm-1.4141 1.4141 6.5859 6.5859h-5.8574a2 2 0 0 0 -.72852-.73047v-5.8555z" fill="#fc7f7f"/></svg>
diff --git a/editor/icons/MeshTexture.svg b/editor/icons/MeshTexture.svg
index 988882c960..ccf16b828b 100644
--- a/editor/icons/MeshTexture.svg
+++ b/editor/icons/MeshTexture.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 1c-1.1046 0-2 .89543-2 2 .0005649.71397.38169 1.3735 1 1.7305v6.541c-.61771.35663-.99874 1.0152-1 1.7285 0 1.1046.89543 2 2 2 .71397-.000565 1.3735-.38169 1.7305-1h6.541c.35663.61771 1.0152.99874 1.7285 1 1.1046 0 2-.89543 2-2 .000101-.72747-.39481-1.3976-1.0312-1.75h.03125v-6.5215c.61771-.35663.99874-1.0152 1-1.7285 0-1.1046-.89543-2-2-2-.71397.0005648-1.3735.38169-1.7305 1h-6.541c-.35663-.61771-1.0152-.99874-1.7285-1zm1.7266 3h.6875 5.168.68945c.17478.30301.42598.55488.72852.73047v.68359 5.1719.68555c-.30301.17478-.55488.42598-.73047.72852h-.68359-5.1719-.68555c-.17478-.30301-.42598-.55488-.72852-.73047v-.6875l-.0039062.003907v-5.8574c.30302-.17478.55488-.42598.73047-.72852zm4.0859 2.25v.70117h-.8125v.69922h-1.625v.69922h-.8125v.69922h-.8125v.70117h1.625 1.625 1.625 1.625v-1.4004h-.8125v-1.3984h-.8125v-.70117h-.8125z" fill="#e0e0e0" fill-opacity=".99608"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 1c-1.1046 0-2 .89543-2 2 .0005649.71397.38169 1.3735 1 1.7305v6.541c-.61771.35663-.99874 1.0152-1 1.7285 0 1.1046.89543 2 2 2 .71397-.000565 1.3735-.38169 1.7305-1h6.541c.35663.61771 1.0152.99874 1.7285 1 1.1046 0 2-.89543 2-2 .000101-.72747-.39481-1.3976-1.0312-1.75h.03125v-6.5215c.61771-.35663.99874-1.0152 1-1.7285 0-1.1046-.89543-2-2-2-.71397.0005648-1.3735.38169-1.7305 1h-6.541c-.35663-.61771-1.0152-.99874-1.7285-1zm1.7266 3h.6875 5.168.68945c.17478.30301.42598.55488.72852.73047v.68359 5.1719.68555c-.30301.17478-.55488.42598-.73047.72852h-.68359-5.1719-.68555c-.17478-.30301-.42598-.55488-.72852-.73047v-.6875l-.0039062.003907v-5.8574c.30302-.17478.55488-.42598.73047-.72852zm4.0859 2.25v.70117h-.8125v.69922h-1.625v.69922h-.8125v.69922h-.8125v.70117h1.625 1.625 1.625 1.625v-1.4004h-.8125v-1.3984h-.8125v-.70117h-.8125z" fill="#e0e0e0"/></svg>
diff --git a/editor/icons/MirrorX.svg b/editor/icons/MirrorX.svg
index fa668986ac..84c1da1b66 100644
--- a/editor/icons/MirrorX.svg
+++ b/editor/icons/MirrorX.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="none" stroke="#e0e0e0" stroke-opacity=".99608" stroke-width="2" transform="translate(0 -1036.4)"><path d="m4 1042.4-2 2 2 2" stroke-linecap="round" stroke-linejoin="round"/><path d="m2 1044.4h11"/><path d="m12 1042.4 2 2-2 2" stroke-linecap="round" stroke-linejoin="round"/></g></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="none" stroke="#e0e0e0" stroke-width="2" transform="translate(0 -1036.4)"><path d="m4 1042.4-2 2 2 2" stroke-linecap="round" stroke-linejoin="round"/><path d="m2 1044.4h11"/><path d="m12 1042.4 2 2-2 2" stroke-linecap="round" stroke-linejoin="round"/></g></svg>
diff --git a/editor/icons/MirrorY.svg b/editor/icons/MirrorY.svg
index bb4e4d3543..beaf8b0536 100644
--- a/editor/icons/MirrorY.svg
+++ b/editor/icons/MirrorY.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m11.012 1048.4a1.0001 1.0001 0 0 0 -1.7168-.6973l-.29297.293v-7.1719l.29297.293a1.0001 1.0001 0 0 0 1.7148-.7266 1.0001 1.0001 0 0 0 -.30078-.6875l-2-2a1.0001 1.0001 0 0 0 -1.4141 0l-2 2a1.0001 1.0001 0 1 0 1.4141 1.4141l.29297-.293v7.1719l-.29297-.293a1.0001 1.0001 0 1 0 -1.4141 1.4141l2 2a1.0001 1.0001 0 0 0 1.4141 0l2-2a1.0001 1.0001 0 0 0 .30273-.7168z" fill="#e0e0e0" fill-opacity=".99608" transform="translate(0 -1036.4)"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m11.012 1048.4a1.0001 1.0001 0 0 0 -1.7168-.6973l-.29297.293v-7.1719l.29297.293a1.0001 1.0001 0 0 0 1.7148-.7266 1.0001 1.0001 0 0 0 -.30078-.6875l-2-2a1.0001 1.0001 0 0 0 -1.4141 0l-2 2a1.0001 1.0001 0 1 0 1.4141 1.4141l.29297-.293v7.1719l-.29297-.293a1.0001 1.0001 0 1 0 -1.4141 1.4141l2 2a1.0001 1.0001 0 0 0 1.4141 0l2-2a1.0001 1.0001 0 0 0 .30273-.7168z" fill="#e0e0e0" transform="translate(0 -1036.4)"/></svg>
diff --git a/editor/icons/MoveDown.svg b/editor/icons/MoveDown.svg
index 3c2d771cd5..85301f7f22 100644
--- a/editor/icons/MoveDown.svg
+++ b/editor/icons/MoveDown.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m6 1a1.0001 1.0001 0 1 0 0 2h4a1.0001 1.0001 0 1 0 0-2zm2 4c-.55231 0-1 .4477-1 1v5.1484l-2.2188-2.7734c-.34504-.4317-.97482-.50165-1.4062-.15625-.4305.3449-.5004.9732-.15625 1.4043l4 5c.18868.2369.4745.37695.77734.37695.30559.0009.59477-.13795.78516-.37695l4-5c.34415-.4311.27424-1.0594-.15625-1.4043-.43143-.3454-1.0612-.27545-1.4062.15625l-2.2188 2.7734v-5.1484c0-.5523-.44769-1-1-1z" fill="#e0e0e0" fill-opacity=".99608"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m6 1a1.0001 1.0001 0 1 0 0 2h4a1.0001 1.0001 0 1 0 0-2zm2 4c-.55231 0-1 .4477-1 1v5.1484l-2.2188-2.7734c-.34504-.4317-.97482-.50165-1.4062-.15625-.4305.3449-.5004.9732-.15625 1.4043l4 5c.18868.2369.4745.37695.77734.37695.30559.0009.59477-.13795.78516-.37695l4-5c.34415-.4311.27424-1.0594-.15625-1.4043-.43143-.3454-1.0612-.27545-1.4062.15625l-2.2188 2.7734v-5.1484c0-.5523-.44769-1-1-1z" fill="#e0e0e0"/></svg>
diff --git a/editor/icons/MoveLeft.svg b/editor/icons/MoveLeft.svg
index 8f96ee0060..eedae80a81 100644
--- a/editor/icons/MoveLeft.svg
+++ b/editor/icons/MoveLeft.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m15 10a1.0001 1.0001 0 1 1 -2 0v-4a1.0001 1.0001 0 1 1 2 0zm-4-2c0 .55231-.4477 1-1 1h-5.1484l2.7734 2.2188c.4317.34504.50165.97482.15625 1.4062-.3449.4305-.9732.5004-1.4043.15625l-5-4c-.2369-.18868-.37695-.4745-.37695-.77734-.0009-.30559.13795-.59477.37695-.78516l5-4c.4311-.34415 1.0594-.27424 1.4043.15625.3454.43143.27545 1.0612-.15625 1.4062l-2.7734 2.2188h5.1484c.5523 0 1 .44769 1 1z" fill="#e0e0e0" fill-opacity=".99608"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m15 10a1.0001 1.0001 0 1 1 -2 0v-4a1.0001 1.0001 0 1 1 2 0zm-4-2c0 .55231-.4477 1-1 1h-5.1484l2.7734 2.2188c.4317.34504.50165.97482.15625 1.4062-.3449.4305-.9732.5004-1.4043.15625l-5-4c-.2369-.18868-.37695-.4745-.37695-.77734-.0009-.30559.13795-.59477.37695-.78516l5-4c.4311-.34415 1.0594-.27424 1.4043.15625.3454.43143.27545 1.0612-.15625 1.4062l-2.7734 2.2188h5.1484c.5523 0 1 .44769 1 1z" fill="#e0e0e0"/></svg>
diff --git a/editor/icons/MoveRight.svg b/editor/icons/MoveRight.svg
index ee8d1b45a4..951755fabe 100644
--- a/editor/icons/MoveRight.svg
+++ b/editor/icons/MoveRight.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 10a1.0001 1.0001 0 1 0 2 0v-4a1.0001 1.0001 0 1 0 -2 0zm4-2c0 .55231.4477 1 1 1h5.1484l-2.7734 2.2188c-.4317.34504-.50165.97482-.15625 1.4062.3449.4305.9732.5004 1.4043.15625l5-4c.2369-.18868.37695-.4745.37695-.77734.0009-.30559-.13795-.59477-.37695-.78516l-5-4c-.4311-.34415-1.0594-.27424-1.4043.15625-.3454.43143-.27545 1.0612.15625 1.4062l2.7734 2.2188h-5.1484c-.5523 0-1 .44769-1 1z" fill="#e0e0e0" fill-opacity=".99608"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 10a1.0001 1.0001 0 1 0 2 0v-4a1.0001 1.0001 0 1 0 -2 0zm4-2c0 .55231.4477 1 1 1h5.1484l-2.7734 2.2188c-.4317.34504-.50165.97482-.15625 1.4062.3449.4305.9732.5004 1.4043.15625l5-4c.2369-.18868.37695-.4745.37695-.77734.0009-.30559-.13795-.59477-.37695-.78516l-5-4c-.4311-.34415-1.0594-.27424-1.4043.15625-.3454.43143-.27545 1.0612.15625 1.4062l2.7734 2.2188h-5.1484c-.5523 0-1 .44769-1 1z" fill="#e0e0e0"/></svg>
diff --git a/editor/icons/MoveUp.svg b/editor/icons/MoveUp.svg
index f1302b2984..6cdc984ebc 100644
--- a/editor/icons/MoveUp.svg
+++ b/editor/icons/MoveUp.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m6 15a1.0001 1.0001 0 1 1 0-2h4a1.0001 1.0001 0 1 1 0 2zm2-4c-.55231 0-1-.4477-1-1v-5.1484l-2.2188 2.7734c-.34504.4317-.97482.50165-1.4062.15625-.4305-.3449-.5004-.9732-.15625-1.4043l4-5c.18868-.2369.4745-.37695.77734-.37695.30559-.0009.59477.13795.78516.37695l4 5c.34415.4311.27424 1.0594-.15625 1.4043-.43143.3454-1.0612.27545-1.4062-.15625l-2.2188-2.7734v5.1484c0 .5523-.44769 1-1 1z" fill="#e0e0e0" fill-opacity=".99608"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m6 15a1.0001 1.0001 0 1 1 0-2h4a1.0001 1.0001 0 1 1 0 2zm2-4c-.55231 0-1-.4477-1-1v-5.1484l-2.2188 2.7734c-.34504.4317-.97482.50165-1.4062.15625-.4305-.3449-.5004-.9732-.15625-1.4043l4-5c.18868-.2369.4745-.37695.77734-.37695.30559-.0009.59477.13795.78516.37695l4 5c.34415.4311.27424 1.0594-.15625 1.4043-.43143.3454-1.0612.27545-1.4062-.15625l-2.2188-2.7734v5.1484c0 .5523-.44769 1-1 1z" fill="#e0e0e0"/></svg>
diff --git a/editor/icons/MultiMeshInstance3D.svg b/editor/icons/MultiMeshInstance3D.svg
index 3ccd2c9cbe..eb82d4928b 100644
--- a/editor/icons/MultiMeshInstance3D.svg
+++ b/editor/icons/MultiMeshInstance3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 1c-1.1046 0-2 .89543-2 2 .0005649.71397.38169 1.3735 1 1.7305v6.541c-.61771.35663-.99874 1.0152-1 1.7285 0 1.1046.89543 2 2 2 .71397-.000565 1.3735-.38169 1.7305-1h1.2695v-2h-1.2715c-.17478-.30301-.42598-.55488-.72852-.73047v-5.8555l3.5859 3.5859h1.4141v-1.4141l-3.5859-3.5859h5.8574c.17532.30158.42647.55205.72852.72656v1.2734h2v-1.2695c.61831-.35698.99944-1.0165 1-1.7305 0-1.1046-.89543-2-2-2-.71397.0005648-1.3735.38169-1.7305 1h-6.541c-.35663-.61771-1.0152-.99874-1.7285-1zm8 7v3h-3v2h3v3h2v-3h3v-2h-3v-3z" fill="#fc7f7f" fill-opacity=".99608"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 1c-1.1046 0-2 .89543-2 2 .0005649.71397.38169 1.3735 1 1.7305v6.541c-.61771.35663-.99874 1.0152-1 1.7285 0 1.1046.89543 2 2 2 .71397-.000565 1.3735-.38169 1.7305-1h1.2695v-2h-1.2715c-.17478-.30301-.42598-.55488-.72852-.73047v-5.8555l3.5859 3.5859h1.4141v-1.4141l-3.5859-3.5859h5.8574c.17532.30158.42647.55205.72852.72656v1.2734h2v-1.2695c.61831-.35698.99944-1.0165 1-1.7305 0-1.1046-.89543-2-2-2-.71397.0005648-1.3735.38169-1.7305 1h-6.541c-.35663-.61771-1.0152-.99874-1.7285-1zm8 7v3h-3v2h3v3h2v-3h3v-2h-3v-3z" fill="#fc7f7f"/></svg>
diff --git a/editor/icons/Navigation3D.svg b/editor/icons/Navigation3D.svg
index 646500d9ed..79cca958f8 100644
--- a/editor/icons/Navigation3D.svg
+++ b/editor/icons/Navigation3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 1050.4 5-2 5 2-5-12z" fill="#fc7f7f" fill-opacity=".99608" fill-rule="evenodd" transform="translate(0 -1036.4)"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 1050.4 5-2 5 2-5-12z" fill="#fc7f7f" fill-rule="evenodd" transform="translate(0 -1036.4)"/></svg>
diff --git a/editor/icons/NavigationLink2D.svg b/editor/icons/NavigationLink2D.svg
index 6c5f17e256..df470ece57 100644
--- a/editor/icons/NavigationLink2D.svg
+++ b/editor/icons/NavigationLink2D.svg
@@ -1,4 +1,4 @@
<svg version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<path d="m12.386 5.3097c-0.69157-0.021112-1.3071 0.36382-1.7492 0.86685-0.58 0.58-1.16 1.16-1.74 1.74 0.4588-0.28502 1.0599-0.064948 1.4771-0.037996 0.45549-0.44357 0.89024-0.91006 1.3596-1.3383 0.56256-0.44564 1.4906-0.15731 1.7028 0.52802 0.18967 0.4871-0.049221 1.0098-0.43284 1.3208-0.70048 0.68896-1.3789 1.4022-2.0935 2.0755-0.47999 0.3725-1.2044 0.226-1.5679-0.24034-0.38763-0.38194-1.0641 0.16031-0.78317 0.6241 0.6767 0.94379 2.1573 1.1282 3.0411 0.36751 0.80287-0.7704 1.5793-1.5696 2.3665-2.3564 0.79925-0.83719 0.70104-2.3112-0.19552-3.0393-0.38108-0.32877-0.8822-0.5119-1.385-0.51049zm-3.051 3.051c-0.69157-0.021106-1.3071 0.36382-1.7492 0.86685-0.67513 0.68452-1.37 1.3506-2.0319 2.0474-0.75433 0.87744-0.58087 2.3428 0.34933 3.0252 0.84748 0.68613 2.192 0.54839 2.8998-0.27341 0.63032-0.63031 1.2606-1.2606 1.8909-1.8909-0.4587 0.28554-1.0602 0.0659-1.477 0.038069-0.45445 0.44348-0.88773 0.91034-1.3564 1.3383-0.56256 0.44565-1.4906 0.15731-1.7028-0.52802-0.18967-0.4871 0.049229-1.0098 0.43284-1.3208 0.70048-0.68896 1.3789-1.4022 2.0935-2.0755 0.48-0.3725 1.2044-0.22601 1.5679 0.24036 0.38733 0.38325 1.064-0.16067 0.78313-0.6241-0.39353-0.52481-1.0429-0.84871-1.7002-0.8434z" fill="#8ea6f4" fill-opacity=".99608" stroke-linecap="round" stroke-linejoin="round" stroke-width=".013911"/>
-<path d="m2 1c-0.61942-0.0066969-1.0877 0.60314-1 1.198 0.00345 3.968-0.006897 7.9364 0.00517 11.904 0.043388 0.62851 0.69346 0.98513 1.272 0.89776h2.5896c-0.77174-0.5015-1.2078-1.2613-1.3143-2.3356-0.11601-1.1701 0.63729-2.024 1.6748-3.1566 0.65335-0.71326 1.4757-1.5822 2.3587-2.3316 0.76308-0.64765 1.7509-1.679 2.9376-2.578 0.91259-0.69136 2.2893-0.74691 3.1014-0.33143 0.91184 0.46649 1.2635 1.1209 1.4067 1.3826-0.0052-2.335-0.02135-1.3526-0.03955-3.6863 5e-3 -0.64349-0.67497-1.0568-1.2694-0.96289z" fill="#8ea6f4" fill-opacity=".99608"/>
+<path d="m12.386 5.3097c-0.69157-0.021112-1.3071 0.36382-1.7492 0.86685-0.58 0.58-1.16 1.16-1.74 1.74 0.4588-0.28502 1.0599-0.064948 1.4771-0.037996 0.45549-0.44357 0.89024-0.91006 1.3596-1.3383 0.56256-0.44564 1.4906-0.15731 1.7028 0.52802 0.18967 0.4871-0.049221 1.0098-0.43284 1.3208-0.70048 0.68896-1.3789 1.4022-2.0935 2.0755-0.47999 0.3725-1.2044 0.226-1.5679-0.24034-0.38763-0.38194-1.0641 0.16031-0.78317 0.6241 0.6767 0.94379 2.1573 1.1282 3.0411 0.36751 0.80287-0.7704 1.5793-1.5696 2.3665-2.3564 0.79925-0.83719 0.70104-2.3112-0.19552-3.0393-0.38108-0.32877-0.8822-0.5119-1.385-0.51049zm-3.051 3.051c-0.69157-0.021106-1.3071 0.36382-1.7492 0.86685-0.67513 0.68452-1.37 1.3506-2.0319 2.0474-0.75433 0.87744-0.58087 2.3428 0.34933 3.0252 0.84748 0.68613 2.192 0.54839 2.8998-0.27341 0.63032-0.63031 1.2606-1.2606 1.8909-1.8909-0.4587 0.28554-1.0602 0.0659-1.477 0.038069-0.45445 0.44348-0.88773 0.91034-1.3564 1.3383-0.56256 0.44565-1.4906 0.15731-1.7028-0.52802-0.18967-0.4871 0.049229-1.0098 0.43284-1.3208 0.70048-0.68896 1.3789-1.4022 2.0935-2.0755 0.48-0.3725 1.2044-0.22601 1.5679 0.24036 0.38733 0.38325 1.064-0.16067 0.78313-0.6241-0.39353-0.52481-1.0429-0.84871-1.7002-0.8434z" fill="#8ea6f4" stroke-linecap="round" stroke-linejoin="round" stroke-width=".013911"/>
+<path d="m2 1c-0.61942-0.0066969-1.0877 0.60314-1 1.198 0.00345 3.968-0.006897 7.9364 0.00517 11.904 0.043388 0.62851 0.69346 0.98513 1.272 0.89776h2.5896c-0.77174-0.5015-1.2078-1.2613-1.3143-2.3356-0.11601-1.1701 0.63729-2.024 1.6748-3.1566 0.65335-0.71326 1.4757-1.5822 2.3587-2.3316 0.76308-0.64765 1.7509-1.679 2.9376-2.578 0.91259-0.69136 2.2893-0.74691 3.1014-0.33143 0.91184 0.46649 1.2635 1.1209 1.4067 1.3826-0.0052-2.335-0.02135-1.3526-0.03955-3.6863 5e-3 -0.64349-0.67497-1.0568-1.2694-0.96289z" fill="#8ea6f4"/>
</svg>
diff --git a/editor/icons/NavigationLink3D.svg b/editor/icons/NavigationLink3D.svg
index ea4092c2c7..05f36da2b2 100644
--- a/editor/icons/NavigationLink3D.svg
+++ b/editor/icons/NavigationLink3D.svg
@@ -1,4 +1,4 @@
<svg version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<path d="m12.386 5.3097c-0.69157-0.021112-1.3071 0.36382-1.7492 0.86685-0.58 0.58-1.16 1.16-1.74 1.74 0.4588-0.28502 1.0599-0.064948 1.4771-0.037996 0.45549-0.44357 0.89024-0.91006 1.3596-1.3383 0.56256-0.44564 1.4906-0.15731 1.7028 0.52802 0.18967 0.4871-0.049221 1.0098-0.43284 1.3208-0.70048 0.68896-1.3789 1.4022-2.0935 2.0755-0.47999 0.3725-1.2044 0.226-1.5679-0.24034-0.38763-0.38194-1.0641 0.16031-0.78317 0.6241 0.6767 0.94379 2.1573 1.1282 3.0411 0.36751 0.80287-0.7704 1.5793-1.5696 2.3665-2.3564 0.79925-0.83719 0.70104-2.3112-0.19552-3.0393-0.38108-0.32877-0.8822-0.5119-1.385-0.51049zm-3.051 3.051c-0.69157-0.021106-1.3071 0.36382-1.7492 0.86685-0.67513 0.68452-1.37 1.3506-2.0319 2.0474-0.75433 0.87744-0.58087 2.3428 0.34933 3.0252 0.84748 0.68613 2.192 0.54839 2.8998-0.27341 0.63032-0.63031 1.2606-1.2606 1.8909-1.8909-0.4587 0.28554-1.0602 0.0659-1.477 0.038069-0.45445 0.44348-0.88773 0.91034-1.3564 1.3383-0.56256 0.44565-1.4906 0.15731-1.7028-0.52802-0.18967-0.4871 0.049229-1.0098 0.43284-1.3208 0.70048-0.68896 1.3789-1.4022 2.0935-2.0755 0.48-0.3725 1.2044-0.22601 1.5679 0.24036 0.38733 0.38325 1.064-0.16067 0.78313-0.6241-0.39353-0.52481-1.0429-0.84871-1.7002-0.8434z" fill="#fc7e7e" fill-opacity=".99608" stroke-linecap="round" stroke-linejoin="round" stroke-width=".013911"/>
-<path d="m2 1c-0.61942-0.0066969-1.0877 0.60314-1 1.198 0.00345 3.968-0.006897 7.9364 0.00517 11.904 0.043388 0.62851 0.69346 0.98513 1.272 0.89776h2.5896c-0.77174-0.5015-1.2078-1.2613-1.3143-2.3356-0.11601-1.1701 0.63729-2.024 1.6748-3.1566 0.65335-0.71326 1.4757-1.5822 2.3587-2.3316 0.76308-0.64765 1.7509-1.679 2.9376-2.578 0.91259-0.69136 2.2893-0.74691 3.1014-0.33143 0.91184 0.46649 1.2635 1.1209 1.4067 1.3826-0.0052-2.335-0.02135-1.3526-0.03955-3.6863 5e-3 -0.64349-0.67497-1.0568-1.2694-0.96289z" fill="#fc7d7d" fill-opacity=".99608"/>
+<path d="m12.386 5.3097c-0.69157-0.021112-1.3071 0.36382-1.7492 0.86685-0.58 0.58-1.16 1.16-1.74 1.74 0.4588-0.28502 1.0599-0.064948 1.4771-0.037996 0.45549-0.44357 0.89024-0.91006 1.3596-1.3383 0.56256-0.44564 1.4906-0.15731 1.7028 0.52802 0.18967 0.4871-0.049221 1.0098-0.43284 1.3208-0.70048 0.68896-1.3789 1.4022-2.0935 2.0755-0.47999 0.3725-1.2044 0.226-1.5679-0.24034-0.38763-0.38194-1.0641 0.16031-0.78317 0.6241 0.6767 0.94379 2.1573 1.1282 3.0411 0.36751 0.80287-0.7704 1.5793-1.5696 2.3665-2.3564 0.79925-0.83719 0.70104-2.3112-0.19552-3.0393-0.38108-0.32877-0.8822-0.5119-1.385-0.51049zm-3.051 3.051c-0.69157-0.021106-1.3071 0.36382-1.7492 0.86685-0.67513 0.68452-1.37 1.3506-2.0319 2.0474-0.75433 0.87744-0.58087 2.3428 0.34933 3.0252 0.84748 0.68613 2.192 0.54839 2.8998-0.27341 0.63032-0.63031 1.2606-1.2606 1.8909-1.8909-0.4587 0.28554-1.0602 0.0659-1.477 0.038069-0.45445 0.44348-0.88773 0.91034-1.3564 1.3383-0.56256 0.44565-1.4906 0.15731-1.7028-0.52802-0.18967-0.4871 0.049229-1.0098 0.43284-1.3208 0.70048-0.68896 1.3789-1.4022 2.0935-2.0755 0.48-0.3725 1.2044-0.22601 1.5679 0.24036 0.38733 0.38325 1.064-0.16067 0.78313-0.6241-0.39353-0.52481-1.0429-0.84871-1.7002-0.8434z" fill="#fc7e7e" stroke-linecap="round" stroke-linejoin="round" stroke-width=".013911"/>
+<path d="m2 1c-0.61942-0.0066969-1.0877 0.60314-1 1.198 0.00345 3.968-0.006897 7.9364 0.00517 11.904 0.043388 0.62851 0.69346 0.98513 1.272 0.89776h2.5896c-0.77174-0.5015-1.2078-1.2613-1.3143-2.3356-0.11601-1.1701 0.63729-2.024 1.6748-3.1566 0.65335-0.71326 1.4757-1.5822 2.3587-2.3316 0.76308-0.64765 1.7509-1.679 2.9376-2.578 0.91259-0.69136 2.2893-0.74691 3.1014-0.33143 0.91184 0.46649 1.2635 1.1209 1.4067 1.3826-0.0052-2.335-0.02135-1.3526-0.03955-3.6863 5e-3 -0.64349-0.67497-1.0568-1.2694-0.96289z" fill="#fc7d7d"/>
</svg>
diff --git a/editor/icons/NavigationRegion3D.svg b/editor/icons/NavigationRegion3D.svg
index 39b6d0ca13..523ae4d20d 100644
--- a/editor/icons/NavigationRegion3D.svg
+++ b/editor/icons/NavigationRegion3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m2 1c-.1339223.0000569-.2535666.030668-.3652344.074219-.022275.00881-.041042.020919-.0625.03125-.088962.042467-.1681009.095499-.2382812.1601562-.021532.01952-.042739.037285-.0625.058594-.074111.081092-.13722.1698052-.1816406.2695312-.00343.00765-.00847.013733-.011719.021484l-.00195.00195c-.0452281.1091913-.0629952.2269004-.0683623.3457062-.0005086.0130821-.0078112.023903-.0078125.0371094v12c.0000552.552262.4477381.999945 1 1h4.8847656a2.1184381 2.1184381 0 0 1 .1328125-.744141l2.9999999-7.9999996a2.1184381 2.1184381 0 0 1 2.007813-1.3730469 2.1184381 2.1184381 0 0 1 1.957031 1.3730469l1.017578 2.7128906v-6.96875c-.000001-.013206-.0073-.024027-.0078-.037109-.0054-.1188058-.02313-.2365149-.06836-.3457031l-.002-.00195c-.0032-.00756-.0084-.013999-.01172-.021484-.04442-.099726-.107529-.188439-.18164-.2695312-.01976-.021308-.04097-.039073-.0625-.058594-.07018-.064657-.149319-.1176895-.238282-.1601562-.02146-.010331-.04022-.022439-.0625-.03125-.111631-.0435548-.231276-.0741656-.365198-.0742225zm10 6-3 8 3-2 3 2z" fill="#fc7f7f" fill-opacity=".996078" fill-rule="evenodd"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m2 1c-.1339223.0000569-.2535666.030668-.3652344.074219-.022275.00881-.041042.020919-.0625.03125-.088962.042467-.1681009.095499-.2382812.1601562-.021532.01952-.042739.037285-.0625.058594-.074111.081092-.13722.1698052-.1816406.2695312-.00343.00765-.00847.013733-.011719.021484l-.00195.00195c-.0452281.1091913-.0629952.2269004-.0683623.3457062-.0005086.0130821-.0078112.023903-.0078125.0371094v12c.0000552.552262.4477381.999945 1 1h4.8847656a2.1184381 2.1184381 0 0 1 .1328125-.744141l2.9999999-7.9999996a2.1184381 2.1184381 0 0 1 2.007813-1.3730469 2.1184381 2.1184381 0 0 1 1.957031 1.3730469l1.017578 2.7128906v-6.96875c-.000001-.013206-.0073-.024027-.0078-.037109-.0054-.1188058-.02313-.2365149-.06836-.3457031l-.002-.00195c-.0032-.00756-.0084-.013999-.01172-.021484-.04442-.099726-.107529-.188439-.18164-.2695312-.01976-.021308-.04097-.039073-.0625-.058594-.07018-.064657-.149319-.1176895-.238282-.1601562-.02146-.010331-.04022-.022439-.0625-.03125-.111631-.0435548-.231276-.0741656-.365198-.0742225zm10 6-3 8 3-2 3 2z" fill="#fc7f7f" fill-rule="evenodd"/></svg>
diff --git a/editor/icons/Node3D.svg b/editor/icons/Node3D.svg
index c8a3163e51..620bc95229 100644
--- a/editor/icons/Node3D.svg
+++ b/editor/icons/Node3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 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 6-6 6 6 0 0 0 -6-6zm0 2a4 4 0 0 1 4 4 4 4 0 0 1 -4 4 4 4 0 0 1 -4-4 4 4 0 0 1 4-4z" fill="#fc7f7f" fill-opacity=".99608"/></svg>
+<svg height="16" viewBox="0 0 16 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 6-6 6 6 0 0 0 -6-6zm0 2a4 4 0 0 1 4 4 4 4 0 0 1 -4 4 4 4 0 0 1 -4-4 4 4 0 0 1 4-4z" fill="#fc7f7f"/></svg>
diff --git a/editor/icons/OccluderInstance3D.svg b/editor/icons/OccluderInstance3D.svg
index cc7ccc410f..18f6054873 100644
--- a/editor/icons/OccluderInstance3D.svg
+++ b/editor/icons/OccluderInstance3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m7.90625 1a7 7 0 0 0 -1.2988281.1386719 4.5 4.5 0 0 1 3.3925781 4.3613281 4.5 4.5 0 0 1 -4.5 4.5 4.5 4.5 0 0 1 -4.359375-3.3886719 7 7 0 0 0 -.140625 1.3886719 7 7 0 0 0 7 7 7 7 0 0 0 7-7 7 7 0 0 0 -7-7 7 7 0 0 0 -.09375 0z" fill="#fc7f7f" fill-opacity=".996078" stroke-width=".365215"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m7.90625 1a7 7 0 0 0 -1.2988281.1386719 4.5 4.5 0 0 1 3.3925781 4.3613281 4.5 4.5 0 0 1 -4.5 4.5 4.5 4.5 0 0 1 -4.359375-3.3886719 7 7 0 0 0 -.140625 1.3886719 7 7 0 0 0 7 7 7 7 0 0 0 7-7 7 7 0 0 0 -7-7 7 7 0 0 0 -.09375 0z" fill="#fc7f7f" stroke-width=".365215"/></svg>
diff --git a/editor/icons/OmniLight3D.svg b/editor/icons/OmniLight3D.svg
index 391e9104a1..9d874b359c 100644
--- a/editor/icons/OmniLight3D.svg
+++ b/editor/icons/OmniLight3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1a5 5 0 0 0 -5 5 5 5 0 0 0 3 4.5762v2.4238h4v-2.4199a5 5 0 0 0 3-4.5801 5 5 0 0 0 -5-5zm0 2a3 3 0 0 1 3 3 3 3 0 0 1 -3 3 3 3 0 0 1 -3-3 3 3 0 0 1 3-3zm-1 11v1h2v-1z" fill="#fc7f7f" fill-opacity=".99608"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1a5 5 0 0 0 -5 5 5 5 0 0 0 3 4.5762v2.4238h4v-2.4199a5 5 0 0 0 3-4.5801 5 5 0 0 0 -5-5zm0 2a3 3 0 0 1 3 3 3 3 0 0 1 -3 3 3 3 0 0 1 -3-3 3 3 0 0 1 3-3zm-1 11v1h2v-1z" fill="#fc7f7f"/></svg>
diff --git a/editor/icons/OneWayTile.svg b/editor/icons/OneWayTile.svg
new file mode 100644
index 0000000000..273b1a183b
--- /dev/null
+++ b/editor/icons/OneWayTile.svg
@@ -0,0 +1 @@
+<svg clip-rule="evenodd" fill-rule="evenodd" height="16" stroke-linecap="round" stroke-linejoin="round" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m10.958984 1.5-1.4785152 1.4667969-1.4785157 1.46875-1.4804687-1.4667969-1.4785156-1.4667969-.5214844.5136719-.5214844.5136719 2 1.9863281 2 1.984375 2-1.984375 2-1.9824219-.519531-.5175781zm0 8-1.4785152 1.466797-1.4785157 1.46875-1.4804687-1.466797-1.4785156-1.4667969-.5214844.5136719-.5214844.513672 2 1.986328 2 1.984375 2-1.984375 2-1.982422-.519531-.517578z" fill="#fff"/></svg>
diff --git a/editor/icons/ParallaxBackground.svg b/editor/icons/ParallaxBackground.svg
index f188230fcc..71a586eff4 100644
--- a/editor/icons/ParallaxBackground.svg
+++ b/editor/icons/ParallaxBackground.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g transform="translate(0 -1036.4)"><path d="m2 2a1 1 0 0 0 -1 1v10a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-10a1 1 0 0 0 -1-1zm0 1h12v10h-12zm5 2-3 3 3 3zm2 0v6l3-3z" fill="#e0e0e0" fill-opacity=".99608" 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 transform="translate(0 -1036.4)"><path d="m2 2a1 1 0 0 0 -1 1v10a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-10a1 1 0 0 0 -1-1zm0 1h12v10h-12zm5 2-3 3 3 3zm2 0v6l3-3z" fill="#e0e0e0" transform="translate(0 1036.4)"/></g></svg>
diff --git a/editor/icons/Path3D.svg b/editor/icons/Path3D.svg
index 076ce9acd2..4e84cf9789 100644
--- a/editor/icons/Path3D.svg
+++ b/editor/icons/Path3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m13 1a2 2 0 0 0 -2 2 2 2 0 0 0 .84961 1.6328c-.19239.88508-.55317 1.3394-.98633 1.6426-.64426.451-1.7129.60547-2.9629.73047s-2.6814.22053-3.9121 1.082c-.89278.62493-1.5321 1.6522-1.8184 3.0957a2 2 0 0 0 -1.1699 1.8164 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -.84961-1.6328c.19235-.88496.55306-1.3373.98633-1.6406.64426-.451 1.7129-.60547 2.9629-.73047s2.6814-.22053 3.9121-1.082c.8927-.62488 1.5321-1.6538 1.8184-3.0977a2 2 0 0 0 1.1699-1.8164 2 2 0 0 0 -2-2z" fill="#fc7f7f" fill-opacity=".99608"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m13 1a2 2 0 0 0 -2 2 2 2 0 0 0 .84961 1.6328c-.19239.88508-.55317 1.3394-.98633 1.6426-.64426.451-1.7129.60547-2.9629.73047s-2.6814.22053-3.9121 1.082c-.89278.62493-1.5321 1.6522-1.8184 3.0957a2 2 0 0 0 -1.1699 1.8164 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -.84961-1.6328c.19235-.88496.55306-1.3373.98633-1.6406.64426-.451 1.7129-.60547 2.9629-.73047s2.6814-.22053 3.9121-1.082c.8927-.62488 1.5321-1.6538 1.8184-3.0977a2 2 0 0 0 1.1699-1.8164 2 2 0 0 0 -2-2z" fill="#fc7f7f"/></svg>
diff --git a/editor/icons/PathFollow3D.svg b/editor/icons/PathFollow3D.svg
index f9bb38939e..01da0b0114 100644
--- a/editor/icons/PathFollow3D.svg
+++ b/editor/icons/PathFollow3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m13 0-3 4h1.9473c-.1385 1.3203-.5583 1.9074-1.084 2.2754-.64426.451-1.7129.60547-2.9629.73047s-2.6814.22053-3.9121 1.082c-.89278.62493-1.5321 1.6522-1.8184 3.0957a2 2 0 0 0 -1.1699 1.8164 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -.84961-1.6328c.19235-.88496.55306-1.3373.98633-1.6406.64426-.451 1.7129-.60547 2.9629-.73047s2.6814-.22053 3.9121-1.082c1.0528-.73697 1.7552-2.032 1.9375-3.9141h2.0508l-3-4z" fill="#fc7f7f" fill-opacity=".99608"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m13 0-3 4h1.9473c-.1385 1.3203-.5583 1.9074-1.084 2.2754-.64426.451-1.7129.60547-2.9629.73047s-2.6814.22053-3.9121 1.082c-.89278.62493-1.5321 1.6522-1.8184 3.0957a2 2 0 0 0 -1.1699 1.8164 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -.84961-1.6328c.19235-.88496.55306-1.3373.98633-1.6406.64426-.451 1.7129-.60547 2.9629-.73047s2.6814-.22053 3.9121-1.082c1.0528-.73697 1.7552-2.032 1.9375-3.9141h2.0508l-3-4z" fill="#fc7f7f"/></svg>
diff --git a/editor/icons/Progress1.svg b/editor/icons/Progress1.svg
index 07505ddd67..d9a58d837e 100644
--- a/editor/icons/Progress1.svg
+++ b/editor/icons/Progress1.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="m9 1037.4v3.0547a4 4 0 0 1 1.0273.4258l2.1582-2.1582a7 7 0 0 0 -3.1855-1.3223z" fill-opacity=".99608"/><path d="m7 1.0801a7 7 0 0 0 -3.1855 1.3203l2.1582 2.1582a4 4 0 0 1 1.0273-.42773v-3.0508zm-4.5996 2.7344a7 7 0 0 0 -1.3223 3.1855h3.0547a4 4 0 0 1 .42578-1.0273l-2.1582-2.1582zm11.199 0-2.1582 2.1582a4 4 0 0 1 .42774 1.0273h3.0508a7 7 0 0 0 -1.3203-3.1855zm-12.52 5.1855a7 7 0 0 0 1.3203 3.1855l2.1582-2.1582a4 4 0 0 1 -.42773-1.0273h-3.0508zm10.787 0a4 4 0 0 1 -.42578 1.0273l2.1582 2.1582a7 7 0 0 0 1.3223-3.1855h-3.0547zm-5.8945 2.4414-2.1582 2.1582a7 7 0 0 0 3.1855 1.3223v-3.0547a4 4 0 0 1 -1.0273-.42578zm4.0547 0a4 4 0 0 1 -1.0273.42774v3.0508a7 7 0 0 0 3.1855-1.3203l-2.1582-2.1582z" fill-opacity=".19608" 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)"><path d="m9 1037.4v3.0547a4 4 0 0 1 1.0273.4258l2.1582-2.1582a7 7 0 0 0 -3.1855-1.3223z"/><path d="m7 1.0801a7 7 0 0 0 -3.1855 1.3203l2.1582 2.1582a4 4 0 0 1 1.0273-.42773v-3.0508zm-4.5996 2.7344a7 7 0 0 0 -1.3223 3.1855h3.0547a4 4 0 0 1 .42578-1.0273l-2.1582-2.1582zm11.199 0-2.1582 2.1582a4 4 0 0 1 .42774 1.0273h3.0508a7 7 0 0 0 -1.3203-3.1855zm-12.52 5.1855a7 7 0 0 0 1.3203 3.1855l2.1582-2.1582a4 4 0 0 1 -.42773-1.0273h-3.0508zm10.787 0a4 4 0 0 1 -.42578 1.0273l2.1582 2.1582a7 7 0 0 0 1.3223-3.1855h-3.0547zm-5.8945 2.4414-2.1582 2.1582a7 7 0 0 0 3.1855 1.3223v-3.0547a4 4 0 0 1 -1.0273-.42578zm4.0547 0a4 4 0 0 1 -1.0273.42774v3.0508a7 7 0 0 0 3.1855-1.3203l-2.1582-2.1582z" fill-opacity=".19608" transform="translate(0 1036.4)"/></g></svg>
diff --git a/editor/icons/Progress2.svg b/editor/icons/Progress2.svg
index 0a48f7d3f5..d98de2e78b 100644
--- a/editor/icons/Progress2.svg
+++ b/editor/icons/Progress2.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="m9 1.0781v3.0547a4 4 0 0 1 1.0273.42578l2.1582-2.1582a7 7 0 0 0 -3.1855-1.3223zm-2 .0019531a7 7 0 0 0 -3.1855 1.3203l2.1582 2.1582a4 4 0 0 1 1.0273-.42773v-3.0508zm-4.5996 2.7344a7 7 0 0 0 -1.3223 3.1855h3.0547a4 4 0 0 1 .42578-1.0273l-2.1582-2.1582zm-1.3203 5.1855a7 7 0 0 0 1.3203 3.1855l2.1582-2.1582a4 4 0 0 1 -.42773-1.0273h-3.0508zm10.787 0a4 4 0 0 1 -.42578 1.0273l2.1582 2.1582a7 7 0 0 0 1.3223-3.1855h-3.0547zm-5.8945 2.4414-2.1582 2.1582a7 7 0 0 0 3.1855 1.3223v-3.0547a4 4 0 0 1 -1.0273-.42578zm4.0547 0a4 4 0 0 1 -1.0273.42774v3.0508a7 7 0 0 0 3.1855-1.3203l-2.1582-2.1582z" fill-opacity=".19608" transform="translate(0 1036.4)"/><path d="m13.6 1040.2-2.1582 2.1582a4 4 0 0 1 .42774 1.0273h3.0508a7 7 0 0 0 -1.3203-3.1855z" fill-opacity=".99608"/></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)"><path d="m9 1.0781v3.0547a4 4 0 0 1 1.0273.42578l2.1582-2.1582a7 7 0 0 0 -3.1855-1.3223zm-2 .0019531a7 7 0 0 0 -3.1855 1.3203l2.1582 2.1582a4 4 0 0 1 1.0273-.42773v-3.0508zm-4.5996 2.7344a7 7 0 0 0 -1.3223 3.1855h3.0547a4 4 0 0 1 .42578-1.0273l-2.1582-2.1582zm-1.3203 5.1855a7 7 0 0 0 1.3203 3.1855l2.1582-2.1582a4 4 0 0 1 -.42773-1.0273h-3.0508zm10.787 0a4 4 0 0 1 -.42578 1.0273l2.1582 2.1582a7 7 0 0 0 1.3223-3.1855h-3.0547zm-5.8945 2.4414-2.1582 2.1582a7 7 0 0 0 3.1855 1.3223v-3.0547a4 4 0 0 1 -1.0273-.42578zm4.0547 0a4 4 0 0 1 -1.0273.42774v3.0508a7 7 0 0 0 3.1855-1.3203l-2.1582-2.1582z" fill-opacity=".19608" transform="translate(0 1036.4)"/><path d="m13.6 1040.2-2.1582 2.1582a4 4 0 0 1 .42774 1.0273h3.0508a7 7 0 0 0 -1.3203-3.1855z"/></g></svg>
diff --git a/editor/icons/Progress3.svg b/editor/icons/Progress3.svg
index a7f0f9c973..a1e84fa7cf 100644
--- a/editor/icons/Progress3.svg
+++ b/editor/icons/Progress3.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="m9 1.0781v3.0547a4 4 0 0 1 1.0273.42578l2.1582-2.1582a7 7 0 0 0 -3.1855-1.3223zm-2 .0019531a7 7 0 0 0 -3.1855 1.3203l2.1582 2.1582a4 4 0 0 1 1.0273-.42773v-3.0508zm-4.5996 2.7344a7 7 0 0 0 -1.3223 3.1855h3.0547a4 4 0 0 1 .42578-1.0273l-2.1582-2.1582zm11.199 0-2.1582 2.1582a4 4 0 0 1 .42774 1.0273h3.0508a7 7 0 0 0 -1.3203-3.1855zm-12.52 5.1855a7 7 0 0 0 1.3203 3.1855l2.1582-2.1582a4 4 0 0 1 -.42773-1.0273h-3.0508zm4.8926 2.4414-2.1582 2.1582a7 7 0 0 0 3.1855 1.3223v-3.0547a4 4 0 0 1 -1.0273-.42578zm4.0547 0a4 4 0 0 1 -1.0273.42774v3.0508a7 7 0 0 0 3.1855-1.3203l-2.1582-2.1582z" fill-opacity=".19608" transform="translate(0 1036.4)"/><path d="m11.867 1045.4a4 4 0 0 1 -.42578 1.0273l2.1582 2.1582a7 7 0 0 0 1.3223-3.1855h-3.0547z" fill-opacity=".99608"/></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)"><path d="m9 1.0781v3.0547a4 4 0 0 1 1.0273.42578l2.1582-2.1582a7 7 0 0 0 -3.1855-1.3223zm-2 .0019531a7 7 0 0 0 -3.1855 1.3203l2.1582 2.1582a4 4 0 0 1 1.0273-.42773v-3.0508zm-4.5996 2.7344a7 7 0 0 0 -1.3223 3.1855h3.0547a4 4 0 0 1 .42578-1.0273l-2.1582-2.1582zm11.199 0-2.1582 2.1582a4 4 0 0 1 .42774 1.0273h3.0508a7 7 0 0 0 -1.3203-3.1855zm-12.52 5.1855a7 7 0 0 0 1.3203 3.1855l2.1582-2.1582a4 4 0 0 1 -.42773-1.0273h-3.0508zm4.8926 2.4414-2.1582 2.1582a7 7 0 0 0 3.1855 1.3223v-3.0547a4 4 0 0 1 -1.0273-.42578zm4.0547 0a4 4 0 0 1 -1.0273.42774v3.0508a7 7 0 0 0 3.1855-1.3203l-2.1582-2.1582z" fill-opacity=".19608" transform="translate(0 1036.4)"/><path d="m11.867 1045.4a4 4 0 0 1 -.42578 1.0273l2.1582 2.1582a7 7 0 0 0 1.3223-3.1855h-3.0547z"/></g></svg>
diff --git a/editor/icons/Progress4.svg b/editor/icons/Progress4.svg
index 171920915e..04a556fd93 100644
--- a/editor/icons/Progress4.svg
+++ b/editor/icons/Progress4.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="m9 1.0781v3.0547a4 4 0 0 1 1.0273.42578l2.1582-2.1582a7 7 0 0 0 -3.1855-1.3223zm-2 .0019531a7 7 0 0 0 -3.1855 1.3203l2.1582 2.1582a4 4 0 0 1 1.0273-.42773v-3.0508zm-4.5996 2.7344a7 7 0 0 0 -1.3223 3.1855h3.0547a4 4 0 0 1 .42578-1.0273l-2.1582-2.1582zm11.199 0-2.1582 2.1582a4 4 0 0 1 .42774 1.0273h3.0508a7 7 0 0 0 -1.3203-3.1855zm-12.52 5.1855a7 7 0 0 0 1.3203 3.1855l2.1582-2.1582a4 4 0 0 1 -.42773-1.0273h-3.0508zm10.787 0a4 4 0 0 1 -.42578 1.0273l2.1582 2.1582a7 7 0 0 0 1.3223-3.1855h-3.0547zm-5.8945 2.4414-2.1582 2.1582a7 7 0 0 0 3.1855 1.3223v-3.0547a4 4 0 0 1 -1.0273-.42578z" fill-opacity=".19608" transform="translate(0 1036.4)"/><path d="m10.027 1047.8a4 4 0 0 1 -1.0273.4277v3.0508a7 7 0 0 0 3.1855-1.3203z" fill-opacity=".99608"/></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)"><path d="m9 1.0781v3.0547a4 4 0 0 1 1.0273.42578l2.1582-2.1582a7 7 0 0 0 -3.1855-1.3223zm-2 .0019531a7 7 0 0 0 -3.1855 1.3203l2.1582 2.1582a4 4 0 0 1 1.0273-.42773v-3.0508zm-4.5996 2.7344a7 7 0 0 0 -1.3223 3.1855h3.0547a4 4 0 0 1 .42578-1.0273l-2.1582-2.1582zm11.199 0-2.1582 2.1582a4 4 0 0 1 .42774 1.0273h3.0508a7 7 0 0 0 -1.3203-3.1855zm-12.52 5.1855a7 7 0 0 0 1.3203 3.1855l2.1582-2.1582a4 4 0 0 1 -.42773-1.0273h-3.0508zm10.787 0a4 4 0 0 1 -.42578 1.0273l2.1582 2.1582a7 7 0 0 0 1.3223-3.1855h-3.0547zm-5.8945 2.4414-2.1582 2.1582a7 7 0 0 0 3.1855 1.3223v-3.0547a4 4 0 0 1 -1.0273-.42578z" fill-opacity=".19608" transform="translate(0 1036.4)"/><path d="m10.027 1047.8a4 4 0 0 1 -1.0273.4277v3.0508a7 7 0 0 0 3.1855-1.3203z"/></g></svg>
diff --git a/editor/icons/Progress5.svg b/editor/icons/Progress5.svg
index 7289b7b8fe..d5a5432781 100644
--- a/editor/icons/Progress5.svg
+++ b/editor/icons/Progress5.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="m9 1.0781v3.0547a4 4 0 0 1 1.0273.42578l2.1582-2.1582a7 7 0 0 0 -3.1855-1.3223zm-2 .0019531a7 7 0 0 0 -3.1855 1.3203l2.1582 2.1582a4 4 0 0 1 1.0273-.42773v-3.0508zm-4.5996 2.7344a7 7 0 0 0 -1.3223 3.1855h3.0547a4 4 0 0 1 .42578-1.0273l-2.1582-2.1582zm11.199 0-2.1582 2.1582a4 4 0 0 1 .42774 1.0273h3.0508a7 7 0 0 0 -1.3203-3.1855zm-12.52 5.1855a7 7 0 0 0 1.3203 3.1855l2.1582-2.1582a4 4 0 0 1 -.42773-1.0273h-3.0508zm10.787 0a4 4 0 0 1 -.42578 1.0273l2.1582 2.1582a7 7 0 0 0 1.3223-3.1855h-3.0547zm-1.8398 2.4414a4 4 0 0 1 -1.0273.42774v3.0508a7 7 0 0 0 3.1855-1.3203l-2.1582-2.1582z" fill-opacity=".19608" transform="translate(0 1036.4)"/><path d="m5.9727 1047.8-2.1582 2.1582a7 7 0 0 0 3.1855 1.3223v-3.0547a4 4 0 0 1 -1.0273-.4258z" fill-opacity=".99608"/></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)"><path d="m9 1.0781v3.0547a4 4 0 0 1 1.0273.42578l2.1582-2.1582a7 7 0 0 0 -3.1855-1.3223zm-2 .0019531a7 7 0 0 0 -3.1855 1.3203l2.1582 2.1582a4 4 0 0 1 1.0273-.42773v-3.0508zm-4.5996 2.7344a7 7 0 0 0 -1.3223 3.1855h3.0547a4 4 0 0 1 .42578-1.0273l-2.1582-2.1582zm11.199 0-2.1582 2.1582a4 4 0 0 1 .42774 1.0273h3.0508a7 7 0 0 0 -1.3203-3.1855zm-12.52 5.1855a7 7 0 0 0 1.3203 3.1855l2.1582-2.1582a4 4 0 0 1 -.42773-1.0273h-3.0508zm10.787 0a4 4 0 0 1 -.42578 1.0273l2.1582 2.1582a7 7 0 0 0 1.3223-3.1855h-3.0547zm-1.8398 2.4414a4 4 0 0 1 -1.0273.42774v3.0508a7 7 0 0 0 3.1855-1.3203l-2.1582-2.1582z" fill-opacity=".19608" transform="translate(0 1036.4)"/><path d="m5.9727 1047.8-2.1582 2.1582a7 7 0 0 0 3.1855 1.3223v-3.0547a4 4 0 0 1 -1.0273-.4258z"/></g></svg>
diff --git a/editor/icons/Progress6.svg b/editor/icons/Progress6.svg
index 3deba6d48c..95aebb3cf5 100644
--- a/editor/icons/Progress6.svg
+++ b/editor/icons/Progress6.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="m9 1.0781v3.0547a4 4 0 0 1 1.0273.42578l2.1582-2.1582a7 7 0 0 0 -3.1855-1.3223zm-2 .0019531a7 7 0 0 0 -3.1855 1.3203l2.1582 2.1582a4 4 0 0 1 1.0273-.42773v-3.0508zm-4.5996 2.7344a7 7 0 0 0 -1.3223 3.1855h3.0547a4 4 0 0 1 .42578-1.0273l-2.1582-2.1582zm11.199 0-2.1582 2.1582a4 4 0 0 1 .42774 1.0273h3.0508a7 7 0 0 0 -1.3203-3.1855zm-1.7324 5.1855a4 4 0 0 1 -.42578 1.0273l2.1582 2.1582a7 7 0 0 0 1.3223-3.1855h-3.0547zm-5.8945 2.4414-2.1582 2.1582a7 7 0 0 0 3.1855 1.3223v-3.0547a4 4 0 0 1 -1.0273-.42578zm4.0547 0a4 4 0 0 1 -1.0273.42774v3.0508a7 7 0 0 0 3.1855-1.3203l-2.1582-2.1582z" fill-opacity=".19608" transform="translate(0 1036.4)"/><path d="m1.0801 1045.4a7 7 0 0 0 1.3203 3.1855l2.1582-2.1582a4 4 0 0 1 -.42773-1.0273h-3.0508z" fill-opacity=".99608"/></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)"><path d="m9 1.0781v3.0547a4 4 0 0 1 1.0273.42578l2.1582-2.1582a7 7 0 0 0 -3.1855-1.3223zm-2 .0019531a7 7 0 0 0 -3.1855 1.3203l2.1582 2.1582a4 4 0 0 1 1.0273-.42773v-3.0508zm-4.5996 2.7344a7 7 0 0 0 -1.3223 3.1855h3.0547a4 4 0 0 1 .42578-1.0273l-2.1582-2.1582zm11.199 0-2.1582 2.1582a4 4 0 0 1 .42774 1.0273h3.0508a7 7 0 0 0 -1.3203-3.1855zm-1.7324 5.1855a4 4 0 0 1 -.42578 1.0273l2.1582 2.1582a7 7 0 0 0 1.3223-3.1855h-3.0547zm-5.8945 2.4414-2.1582 2.1582a7 7 0 0 0 3.1855 1.3223v-3.0547a4 4 0 0 1 -1.0273-.42578zm4.0547 0a4 4 0 0 1 -1.0273.42774v3.0508a7 7 0 0 0 3.1855-1.3203l-2.1582-2.1582z" fill-opacity=".19608" transform="translate(0 1036.4)"/><path d="m1.0801 1045.4a7 7 0 0 0 1.3203 3.1855l2.1582-2.1582a4 4 0 0 1 -.42773-1.0273h-3.0508z"/></g></svg>
diff --git a/editor/icons/Progress7.svg b/editor/icons/Progress7.svg
index 546155dc59..cbcd7df35f 100644
--- a/editor/icons/Progress7.svg
+++ b/editor/icons/Progress7.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="m9 1.0781v3.0547a4 4 0 0 1 1.0273.42578l2.1582-2.1582a7 7 0 0 0 -3.1855-1.3223zm-2 .0019531a7 7 0 0 0 -3.1855 1.3203l2.1582 2.1582a4 4 0 0 1 1.0273-.42773v-3.0508zm6.5996 2.7344-2.1582 2.1582a4 4 0 0 1 .42774 1.0273h3.0508a7 7 0 0 0 -1.3203-3.1855zm-12.52 5.1855a7 7 0 0 0 1.3203 3.1855l2.1582-2.1582a4 4 0 0 1 -.42773-1.0273h-3.0508zm10.787 0a4 4 0 0 1 -.42578 1.0273l2.1582 2.1582a7 7 0 0 0 1.3223-3.1855h-3.0547zm-5.8945 2.4414-2.1582 2.1582a7 7 0 0 0 3.1855 1.3223v-3.0547a4 4 0 0 1 -1.0273-.42578zm4.0547 0a4 4 0 0 1 -1.0273.42774v3.0508a7 7 0 0 0 3.1855-1.3203l-2.1582-2.1582z" fill-opacity=".19608" transform="translate(0 1036.4)"/><path d="m2.4004 1040.2a7 7 0 0 0 -1.3223 3.1855h3.0547a4 4 0 0 1 .42578-1.0273l-2.1582-2.1582z" fill-opacity=".99608"/></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)"><path d="m9 1.0781v3.0547a4 4 0 0 1 1.0273.42578l2.1582-2.1582a7 7 0 0 0 -3.1855-1.3223zm-2 .0019531a7 7 0 0 0 -3.1855 1.3203l2.1582 2.1582a4 4 0 0 1 1.0273-.42773v-3.0508zm6.5996 2.7344-2.1582 2.1582a4 4 0 0 1 .42774 1.0273h3.0508a7 7 0 0 0 -1.3203-3.1855zm-12.52 5.1855a7 7 0 0 0 1.3203 3.1855l2.1582-2.1582a4 4 0 0 1 -.42773-1.0273h-3.0508zm10.787 0a4 4 0 0 1 -.42578 1.0273l2.1582 2.1582a7 7 0 0 0 1.3223-3.1855h-3.0547zm-5.8945 2.4414-2.1582 2.1582a7 7 0 0 0 3.1855 1.3223v-3.0547a4 4 0 0 1 -1.0273-.42578zm4.0547 0a4 4 0 0 1 -1.0273.42774v3.0508a7 7 0 0 0 3.1855-1.3203l-2.1582-2.1582z" fill-opacity=".19608" transform="translate(0 1036.4)"/><path d="m2.4004 1040.2a7 7 0 0 0 -1.3223 3.1855h3.0547a4 4 0 0 1 .42578-1.0273l-2.1582-2.1582z"/></g></svg>
diff --git a/editor/icons/Progress8.svg b/editor/icons/Progress8.svg
index b56ffcb727..900b681c69 100644
--- a/editor/icons/Progress8.svg
+++ b/editor/icons/Progress8.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="m9 1.0781v3.0547a4 4 0 0 1 1.0273.42578l2.1582-2.1582a7 7 0 0 0 -3.1855-1.3223zm-6.5996 2.7363a7 7 0 0 0 -1.3223 3.1855h3.0547a4 4 0 0 1 .42578-1.0273l-2.1582-2.1582zm11.199 0-2.1582 2.1582a4 4 0 0 1 .42774 1.0273h3.0508a7 7 0 0 0 -1.3203-3.1855zm-12.52 5.1855a7 7 0 0 0 1.3203 3.1855l2.1582-2.1582a4 4 0 0 1 -.42773-1.0273h-3.0508zm10.787 0a4 4 0 0 1 -.42578 1.0273l2.1582 2.1582a7 7 0 0 0 1.3223-3.1855h-3.0547zm-5.8945 2.4414-2.1582 2.1582a7 7 0 0 0 3.1855 1.3223v-3.0547a4 4 0 0 1 -1.0273-.42578zm4.0547 0a4 4 0 0 1 -1.0273.42774v3.0508a7 7 0 0 0 3.1855-1.3203l-2.1582-2.1582z" fill-opacity=".19608" transform="translate(0 1036.4)"/><path d="m7 1037.4a7 7 0 0 0 -3.1855 1.3203l2.1582 2.1582a4 4 0 0 1 1.0273-.4277z" fill-opacity=".99608"/></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)"><path d="m9 1.0781v3.0547a4 4 0 0 1 1.0273.42578l2.1582-2.1582a7 7 0 0 0 -3.1855-1.3223zm-6.5996 2.7363a7 7 0 0 0 -1.3223 3.1855h3.0547a4 4 0 0 1 .42578-1.0273l-2.1582-2.1582zm11.199 0-2.1582 2.1582a4 4 0 0 1 .42774 1.0273h3.0508a7 7 0 0 0 -1.3203-3.1855zm-12.52 5.1855a7 7 0 0 0 1.3203 3.1855l2.1582-2.1582a4 4 0 0 1 -.42773-1.0273h-3.0508zm10.787 0a4 4 0 0 1 -.42578 1.0273l2.1582 2.1582a7 7 0 0 0 1.3223-3.1855h-3.0547zm-5.8945 2.4414-2.1582 2.1582a7 7 0 0 0 3.1855 1.3223v-3.0547a4 4 0 0 1 -1.0273-.42578zm4.0547 0a4 4 0 0 1 -1.0273.42774v3.0508a7 7 0 0 0 3.1855-1.3203l-2.1582-2.1582z" fill-opacity=".19608" transform="translate(0 1036.4)"/><path d="m7 1037.4a7 7 0 0 0 -3.1855 1.3203l2.1582 2.1582a4 4 0 0 1 1.0273-.4277z"/></g></svg>
diff --git a/editor/icons/ProxyTexture.svg b/editor/icons/ProxyTexture.svg
index 526f21c379..5435e72a1b 100644
--- a/editor/icons/ProxyTexture.svg
+++ b/editor/icons/ProxyTexture.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 1v4h4v-4zm6 0v2h6v8h-6v4h7a1 1 0 0 0 1-1v-12a1 1 0 0 0 -1-1zm2 4v1h-1v1h-1v3h1 2 2v-2h-1v-2h-1v-1zm-8 1v4h4v-4zm0 5v4h4v-4z" fill="#e0e0e0" fill-opacity=".99608"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 1v4h4v-4zm6 0v2h6v8h-6v4h7a1 1 0 0 0 1-1v-12a1 1 0 0 0 -1-1zm2 4v1h-1v1h-1v3h1 2 2v-2h-1v-2h-1v-1zm-8 1v4h4v-4zm0 5v4h4v-4z" fill="#e0e0e0"/></svg>
diff --git a/editor/icons/Quad.svg b/editor/icons/Quad.svg
index 70ef6b7227..5627876bfb 100644
--- a/editor/icons/Quad.svg
+++ b/editor/icons/Quad.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 1v2 10 2h2 12v-2-12h-12zm3.4141 2h8.5859v8.5859zm-1.4141 1.4141 8.5859 8.5859h-8.5859z" fill="#fc7f7f" fill-opacity=".99608"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 1v2 10 2h2 12v-2-12h-12zm3.4141 2h8.5859v8.5859zm-1.4141 1.4141 8.5859 8.5859h-8.5859z" fill="#fc7f7f"/></svg>
diff --git a/editor/icons/RayCast3D.svg b/editor/icons/RayCast3D.svg
index 9670e63022..59a5e181d6 100644
--- a/editor/icons/RayCast3D.svg
+++ b/editor/icons/RayCast3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m7 1v9h-3l4 5 4-5h-3v-9z" fill="#fc7f7f" fill-opacity=".99608"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m7 1v9h-3l4 5 4-5h-3v-9z" fill="#fc7f7f"/></svg>
diff --git a/editor/icons/ReflectionProbe.svg b/editor/icons/ReflectionProbe.svg
index a88a3524be..dee37be8be 100644
--- a/editor/icons/ReflectionProbe.svg
+++ b/editor/icons/ReflectionProbe.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m10 2a1.0001 1.0001 0 1 0 0 2h1.5859l-4.5195 4.5195-4.2988-5.1582-1.5352 1.2793 5 6a1.0001 1.0001 0 0 0 1.4746.064453l5.293-5.293v1.5879a1.0001 1.0001 0 1 0 2 0v-4a1.0001 1.0001 0 0 0 -1-1h-4zm-9 7v5a1.0001 1.0001 0 0 0 1 1h12a1.0001 1.0001 0 0 0 1-1v-4h-2v3h-10v-4z" fill="#fc7f7f" fill-opacity=".99608"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m10 2a1.0001 1.0001 0 1 0 0 2h1.5859l-4.5195 4.5195-4.2988-5.1582-1.5352 1.2793 5 6a1.0001 1.0001 0 0 0 1.4746.064453l5.293-5.293v1.5879a1.0001 1.0001 0 1 0 2 0v-4a1.0001 1.0001 0 0 0 -1-1h-4zm-9 7v5a1.0001 1.0001 0 0 0 1 1h12a1.0001 1.0001 0 0 0 1-1v-4h-2v3h-10v-4z" fill="#fc7f7f"/></svg>
diff --git a/editor/icons/Reload.svg b/editor/icons/Reload.svg
index 1200df1dde..4891455cea 100644
--- a/editor/icons/Reload.svg
+++ b/editor/icons/Reload.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0" fill-opacity=".99608" transform="translate(0 -1036.4)"><path d="m9 2a6 6 0 0 0 -6 6h2a4 4 0 0 1 4-4 4 4 0 0 1 4 4 4 4 0 0 1 -4 4v2a6 6 0 0 0 6-6 6 6 0 0 0 -6-6z" transform="translate(0 1036.4)"/><path d="m4.118 1048.3-1.6771-.9683-1.6771-.9682 1.6771-.9683 1.6771-.9682-.0000001 1.9365z" transform="matrix(0 -1.1926 1.5492 0 -1617 1049.3)"/></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)"><path d="m9 2a6 6 0 0 0 -6 6h2a4 4 0 0 1 4-4 4 4 0 0 1 4 4 4 4 0 0 1 -4 4v2a6 6 0 0 0 6-6 6 6 0 0 0 -6-6z" transform="translate(0 1036.4)"/><path d="m4.118 1048.3-1.6771-.9683-1.6771-.9682 1.6771-.9683 1.6771-.9682-.0000001 1.9365z" transform="matrix(0 -1.1926 1.5492 0 -1617 1049.3)"/></g></svg>
diff --git a/editor/icons/ReloadSmall.svg b/editor/icons/ReloadSmall.svg
index 9418a57ab1..ca13da056d 100644
--- a/editor/icons/ReloadSmall.svg
+++ b/editor/icons/ReloadSmall.svg
@@ -1 +1 @@
-<svg height="14" viewBox="0 0 14 14" width="14" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0" fill-opacity=".99608" transform="translate(0 -1038.4)"><path d="m8 1039.4a6 6 0 0 0 -6 6h2a4 4 0 0 1 4-4 4 4 0 0 1 4 4 4 4 0 0 1 -4 4v2a6 6 0 0 0 6-6 6 6 0 0 0 -6-6z"/><path d="m4.118 1048.3-1.6771-.9683-1.6771-.9682 1.6771-.9683 1.6771-.9682-.0000001 1.9365z" transform="matrix(0 -1.1926 1.5492 0 -1618 1050.3)"/></g></svg>
+<svg height="14" viewBox="0 0 14 14" width="14" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0" transform="translate(0 -1038.4)"><path d="m8 1039.4a6 6 0 0 0 -6 6h2a4 4 0 0 1 4-4 4 4 0 0 1 4 4 4 4 0 0 1 -4 4v2a6 6 0 0 0 6-6 6 6 0 0 0 -6-6z"/><path d="m4.118 1048.3-1.6771-.9683-1.6771-.9682 1.6771-.9683 1.6771-.9682-.0000001 1.9365z" transform="matrix(0 -1.1926 1.5492 0 -1618 1050.3)"/></g></svg>
diff --git a/editor/icons/Remove.svg b/editor/icons/Remove.svg
index 5bcdf8e569..eb8e244d9a 100644
--- a/editor/icons/Remove.svg
+++ b/editor/icons/Remove.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m5 1v1h-4v2h14v-2h-4v-1zm-3 4v8a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2v-8zm1 2h2v6h-2zm4 0h2v6h-2zm4 0h2v6h-2z" fill="#e0e0e0" fill-opacity=".99608"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m5 1v1h-4v2h14v-2h-4v-1zm-3 4v8a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2v-8zm1 2h2v6h-2zm4 0h2v6h-2zm4 0h2v6h-2z" fill="#e0e0e0"/></svg>
diff --git a/editor/icons/RigidBody3D.svg b/editor/icons/RigidBody3D.svg
index 7f5db4ce88..593f6e1f57 100644
--- a/editor/icons/RigidBody3D.svg
+++ b/editor/icons/RigidBody3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1a7 7 0 0 0 -7 7 7 7 0 0 0 .035156.69922 7 7 0 0 0 .27734 1.3691 7 7 0 0 0 .91016 1.8848 7 7 0 0 0 .30273.4082c.000785-.00256.0011667-.005252.0019532-.007812a7 7 0 0 0 5.4727 2.6465 7 7 0 0 0 3.2422-.80273c.001374.000393.002531.00156.003906.001953a7 7 0 0 0 .035156-.021485 7 7 0 0 0 .42578-.25 7 7 0 0 0 .16992-.10352 7 7 0 0 0 .36914-.26953 7 7 0 0 0 .20508-.15625 7 7 0 0 0 .3418-.30859 7 7 0 0 0 .16406-.1543 7 7 0 0 0 .33008-.36133 7 7 0 0 0 .14062-.16016 7 7 0 0 0 .27734-.37305 7 7 0 0 0 .13867-.19531 7 7 0 0 0 .21875-.36133 7 7 0 0 0 .14258-.25 7 7 0 0 0 .15625-.33398 7 7 0 0 0 .13867-.31055 7 7 0 0 0 .10742-.30859 7 7 0 0 0 .11914-.35352 7 7 0 0 0 .087891-.36914 7 7 0 0 0 .066406-.29297 7 7 0 0 0 .056641-.40039 7 7 0 0 0 .037109-.3125 7 7 0 0 0 .025391-.55273 7 7 0 0 0 -4.3848-6.4883 7 7 0 0 0 -.007812-.0039063 7 7 0 0 0 -.001953 0 7 7 0 0 0 -.61523-.21289 7 7 0 0 0 -.044922-.015625 7 7 0 0 0 -.0058594-.0019531 7 7 0 0 0 -.55078-.13086 7 7 0 0 0 -.14062-.03125 7 7 0 0 0 -.55078-.072266 7 7 0 0 0 -.14258-.017578 7 7 0 0 0 -.55469-.025391zm1.9512 1.334a6 6 0 0 1 4.0488 5.666h-7a2 2 0 0 0 -.94922-1.6992c1.3464-2.0289 2.6038-3.2631 3.9004-3.9668zm-6.8281 2.1797c.14632.65093.35776 1.2833.68359 1.8848a2 2 0 0 0 -.80664 1.6016h-1a6 6 0 0 1 1.123-3.4863zm1.877 1.4863a2 2 0 0 0 -.10938.0039062 2 2 0 0 1 .10938-.0039062zm-.18945.011719a2 2 0 0 0 -.12109.013672 2 2 0 0 1 .12109-.013672zm-.44141.09375a2 2 0 0 0 -.056641.019531 2 2 0 0 1 .056641-.019531zm-1.3594 2.0605a2 2 0 0 0 .013672.11914 2 2 0 0 1 -.013672-.11914zm.027344.20898a2 2 0 0 0 .017578.080078 2 2 0 0 1 -.017578-.080078zm.73438 1.1992a2 2 0 0 0 1.2285.42578 2 2 0 0 0 1.0508-.30078c1.345 2.0268 2.6013 3.2645 3.8965 3.9688a6 6 0 0 1 -1.9473.33203 6 6 0 0 1 -5.0547-2.7695c.23771-.5785.50336-1.1403.82617-1.6563z" fill="#fc7f7f" fill-opacity=".99608"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1a7 7 0 0 0 -7 7 7 7 0 0 0 .035156.69922 7 7 0 0 0 .27734 1.3691 7 7 0 0 0 .91016 1.8848 7 7 0 0 0 .30273.4082c.000785-.00256.0011667-.005252.0019532-.007812a7 7 0 0 0 5.4727 2.6465 7 7 0 0 0 3.2422-.80273c.001374.000393.002531.00156.003906.001953a7 7 0 0 0 .035156-.021485 7 7 0 0 0 .42578-.25 7 7 0 0 0 .16992-.10352 7 7 0 0 0 .36914-.26953 7 7 0 0 0 .20508-.15625 7 7 0 0 0 .3418-.30859 7 7 0 0 0 .16406-.1543 7 7 0 0 0 .33008-.36133 7 7 0 0 0 .14062-.16016 7 7 0 0 0 .27734-.37305 7 7 0 0 0 .13867-.19531 7 7 0 0 0 .21875-.36133 7 7 0 0 0 .14258-.25 7 7 0 0 0 .15625-.33398 7 7 0 0 0 .13867-.31055 7 7 0 0 0 .10742-.30859 7 7 0 0 0 .11914-.35352 7 7 0 0 0 .087891-.36914 7 7 0 0 0 .066406-.29297 7 7 0 0 0 .056641-.40039 7 7 0 0 0 .037109-.3125 7 7 0 0 0 .025391-.55273 7 7 0 0 0 -4.3848-6.4883 7 7 0 0 0 -.007812-.0039063 7 7 0 0 0 -.001953 0 7 7 0 0 0 -.61523-.21289 7 7 0 0 0 -.044922-.015625 7 7 0 0 0 -.0058594-.0019531 7 7 0 0 0 -.55078-.13086 7 7 0 0 0 -.14062-.03125 7 7 0 0 0 -.55078-.072266 7 7 0 0 0 -.14258-.017578 7 7 0 0 0 -.55469-.025391zm1.9512 1.334a6 6 0 0 1 4.0488 5.666h-7a2 2 0 0 0 -.94922-1.6992c1.3464-2.0289 2.6038-3.2631 3.9004-3.9668zm-6.8281 2.1797c.14632.65093.35776 1.2833.68359 1.8848a2 2 0 0 0 -.80664 1.6016h-1a6 6 0 0 1 1.123-3.4863zm1.877 1.4863a2 2 0 0 0 -.10938.0039062 2 2 0 0 1 .10938-.0039062zm-.18945.011719a2 2 0 0 0 -.12109.013672 2 2 0 0 1 .12109-.013672zm-.44141.09375a2 2 0 0 0 -.056641.019531 2 2 0 0 1 .056641-.019531zm-1.3594 2.0605a2 2 0 0 0 .013672.11914 2 2 0 0 1 -.013672-.11914zm.027344.20898a2 2 0 0 0 .017578.080078 2 2 0 0 1 -.017578-.080078zm.73438 1.1992a2 2 0 0 0 1.2285.42578 2 2 0 0 0 1.0508-.30078c1.345 2.0268 2.6013 3.2645 3.8965 3.9688a6 6 0 0 1 -1.9473.33203 6 6 0 0 1 -5.0547-2.7695c.23771-.5785.50336-1.1403.82617-1.6563z" fill="#fc7f7f"/></svg>
diff --git a/editor/icons/RotateLeft.svg b/editor/icons/RotateLeft.svg
index 1200df1dde..4891455cea 100644
--- a/editor/icons/RotateLeft.svg
+++ b/editor/icons/RotateLeft.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0" fill-opacity=".99608" transform="translate(0 -1036.4)"><path d="m9 2a6 6 0 0 0 -6 6h2a4 4 0 0 1 4-4 4 4 0 0 1 4 4 4 4 0 0 1 -4 4v2a6 6 0 0 0 6-6 6 6 0 0 0 -6-6z" transform="translate(0 1036.4)"/><path d="m4.118 1048.3-1.6771-.9683-1.6771-.9682 1.6771-.9683 1.6771-.9682-.0000001 1.9365z" transform="matrix(0 -1.1926 1.5492 0 -1617 1049.3)"/></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)"><path d="m9 2a6 6 0 0 0 -6 6h2a4 4 0 0 1 4-4 4 4 0 0 1 4 4 4 4 0 0 1 -4 4v2a6 6 0 0 0 6-6 6 6 0 0 0 -6-6z" transform="translate(0 1036.4)"/><path d="m4.118 1048.3-1.6771-.9683-1.6771-.9682 1.6771-.9683 1.6771-.9682-.0000001 1.9365z" transform="matrix(0 -1.1926 1.5492 0 -1617 1049.3)"/></g></svg>
diff --git a/editor/icons/RotateRight.svg b/editor/icons/RotateRight.svg
index d69e6a7705..7c9da781dc 100644
--- a/editor/icons/RotateRight.svg
+++ b/editor/icons/RotateRight.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0" fill-opacity=".99608" transform="matrix(-1 0 0 1 16.026308 -1036.4)"><path d="m9 2a6 6 0 0 0 -6 6h2a4 4 0 0 1 4-4 4 4 0 0 1 4 4 4 4 0 0 1 -4 4v2a6 6 0 0 0 6-6 6 6 0 0 0 -6-6z" transform="translate(0 1036.4)"/><path d="m4.118 1048.3-1.6771-.9683-1.6771-.9682 1.6771-.9683 1.6771-.9682-.0000001 1.9365z" transform="matrix(0 -1.1926 1.5492 0 -1617 1049.3)"/></g></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0" transform="matrix(-1 0 0 1 16.026308 -1036.4)"><path d="m9 2a6 6 0 0 0 -6 6h2a4 4 0 0 1 4-4 4 4 0 0 1 4 4 4 4 0 0 1 -4 4v2a6 6 0 0 0 6-6 6 6 0 0 0 -6-6z" transform="translate(0 1036.4)"/><path d="m4.118 1048.3-1.6771-.9683-1.6771-.9682 1.6771-.9683 1.6771-.9682-.0000001 1.9365z" transform="matrix(0 -1.1926 1.5492 0 -1617 1049.3)"/></g></svg>
diff --git a/editor/icons/Search.svg b/editor/icons/Search.svg
index fff4a3cb19..847163d766 100644
--- a/editor/icons/Search.svg
+++ b/editor/icons/Search.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m6 1a5 5 0 0 0 -5 5 5 5 0 0 0 5 5 5 5 0 0 0 2.7539-.83203l4.3164 4.3164 1.4141-1.4141-4.3164-4.3164a5 5 0 0 0 .83203-2.7539 5 5 0 0 0 -5-5zm0 2a3 3 0 0 1 3 3 3 3 0 0 1 -3 3 3 3 0 0 1 -3-3 3 3 0 0 1 3-3z" fill="#e0e0e0" fill-opacity=".99608"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m6 1a5 5 0 0 0 -5 5 5 5 0 0 0 5 5 5 5 0 0 0 2.7539-.83203l4.3164 4.3164 1.4141-1.4141-4.3164-4.3164a5 5 0 0 0 .83203-2.7539 5 5 0 0 0 -5-5zm0 2a3 3 0 0 1 3 3 3 3 0 0 1 -3 3 3 3 0 0 1 -3-3 3 3 0 0 1 3-3z" fill="#e0e0e0"/></svg>
diff --git a/editor/icons/Shortcut.svg b/editor/icons/Shortcut.svg
index 4ef16f0401..2e9a69d8b6 100644
--- a/editor/icons/Shortcut.svg
+++ b/editor/icons/Shortcut.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m4 2c-.55228 0-1 .4477-1 1v9.084c.0004015.506.448.91602 1 .91602h8c.552 0 .9996-.41002 1-.91602v-9.084c0-.5523-.44772-1-1-1zm-3 2v9a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2v-9h-1v9a.99998.99998 0 0 1 -1 1h-10a1 1 0 0 1 -1-1v-9zm6 0h3l-1 3h2l-4 4 1-3h-2z" fill="#e0e0e0" fill-opacity=".99608"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m4 2c-.55228 0-1 .4477-1 1v9.084c.0004015.506.448.91602 1 .91602h8c.552 0 .9996-.41002 1-.91602v-9.084c0-.5523-.44772-1-1-1zm-3 2v9a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2v-9h-1v9a.99998.99998 0 0 1 -1 1h-10a1 1 0 0 1 -1-1v-9zm6 0h3l-1 3h2l-4 4 1-3h-2z" fill="#e0e0e0"/></svg>
diff --git a/editor/icons/Skeleton3D.svg b/editor/icons/Skeleton3D.svg
index f1a1db86a9..19a796c4f1 100644
--- a/editor/icons/Skeleton3D.svg
+++ b/editor/icons/Skeleton3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m6 2a4 4 0 0 0 -4 4 4 4 0 0 0 2 3.4531v3.5469a2 2 0 0 0 1 1.7324 2 2 0 0 0 1 .26562v.001953h4v-.001953a2 2 0 0 0 1-.26562 2 2 0 0 0 1-1.7324v-3.5469a4 4 0 0 0 2-3.4531 4 4 0 0 0 -4-4zm-1 3a1 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-1zm6 0a1 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-1zm-4 2h2v1h-2zm-2 2h1v1h1v-1h1 1v1h1v-1h1v.86719 3.1328h-1v-1h-1v1h-1-1v-1h-1v1h-1v-3.1309-.86914z" fill="#fc7f7f" fill-opacity=".99608"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m6 2a4 4 0 0 0 -4 4 4 4 0 0 0 2 3.4531v3.5469a2 2 0 0 0 1 1.7324 2 2 0 0 0 1 .26562v.001953h4v-.001953a2 2 0 0 0 1-.26562 2 2 0 0 0 1-1.7324v-3.5469a4 4 0 0 0 2-3.4531 4 4 0 0 0 -4-4zm-1 3a1 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-1zm6 0a1 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-1zm-4 2h2v1h-2zm-2 2h1v1h1v-1h1 1v1h1v-1h1v.86719 3.1328h-1v-1h-1v1h-1-1v-1h-1v1h-1v-3.1309-.86914z" fill="#fc7f7f"/></svg>
diff --git a/editor/icons/SoftBody3D.svg b/editor/icons/SoftBody3D.svg
index 7bc9a22c22..1bd2531ce9 100644
--- a/editor/icons/SoftBody3D.svg
+++ b/editor/icons/SoftBody3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m2 1s-3 5 0 7-1 7-1 7h13s3-6 0-8 1-6 1-6zm2 2h7s-2 3 1 5 0 5 0 5h-7s2-4-1-6 0-4 0-4z" fill="#fc7f7f" fill-opacity=".996078"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m2 1s-3 5 0 7-1 7-1 7h13s3-6 0-8 1-6 1-6zm2 2h7s-2 3 1 5 0 5 0 5h-7s2-4-1-6 0-4 0-4z" fill="#fc7f7f"/></svg>
diff --git a/editor/icons/SpotLight3D.svg b/editor/icons/SpotLight3D.svg
index 73b738efcf..27c318257a 100644
--- a/editor/icons/SpotLight3D.svg
+++ b/editor/icons/SpotLight3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m6 1a1 1 0 0 0 -1 1v3.6934c-1.7861.86608-3 2.4605-3 4.3066h4a2 2 0 0 0 2 2 2 2 0 0 0 2-2h4c0-1.8462-1.2139-3.4406-3-4.3066v-3.6934a1 1 0 0 0 -1-1zm-1.0977 9.6348-1.7324 1 1 1.7305 1.7324-1zm6.1953 0-1 1.7305 1.7324 1 1-1.7305zm-4.0977 2.3652v2h2v-2z" fill="#fc7f7f" fill-opacity=".99608"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m6 1a1 1 0 0 0 -1 1v3.6934c-1.7861.86608-3 2.4605-3 4.3066h4a2 2 0 0 0 2 2 2 2 0 0 0 2-2h4c0-1.8462-1.2139-3.4406-3-4.3066v-3.6934a1 1 0 0 0 -1-1zm-1.0977 9.6348-1.7324 1 1 1.7305 1.7324-1zm6.1953 0-1 1.7305 1.7324 1 1-1.7305zm-4.0977 2.3652v2h2v-2z" fill="#fc7f7f"/></svg>
diff --git a/editor/icons/StaticBody3D.svg b/editor/icons/StaticBody3D.svg
index 55b061571f..1172fb0821 100644
--- a/editor/icons/StaticBody3D.svg
+++ b/editor/icons/StaticBody3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 1a2 2 0 0 0 -1.4141.58594 2 2 0 0 0 -.58594 1.4141v10a2 2 0 0 0 .58594 1.4141 2 2 0 0 0 1.4141.58594h10a2 2 0 0 0 2-2v-10a2 2 0 0 0 -2-2h-10zm0 1h10a1 1 0 0 1 1 1v10a1 1 0 0 1 -1 1h-10a1 1 0 0 1 -1-1v-10a1 1 0 0 1 1-1zm0 1v2h2v-2zm8 0v2h2v-2zm-8 8v2h2v-2zm8 0v2h2v-2z" fill="#fc7f7f" fill-opacity=".99608"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 1a2 2 0 0 0 -1.4141.58594 2 2 0 0 0 -.58594 1.4141v10a2 2 0 0 0 .58594 1.4141 2 2 0 0 0 1.4141.58594h10a2 2 0 0 0 2-2v-10a2 2 0 0 0 -2-2h-10zm0 1h10a1 1 0 0 1 1 1v10a1 1 0 0 1 -1 1h-10a1 1 0 0 1 -1-1v-10a1 1 0 0 1 1-1zm0 1v2h2v-2zm8 0v2h2v-2zm-8 8v2h2v-2zm8 0v2h2v-2z" fill="#fc7f7f"/></svg>
diff --git a/editor/icons/SubViewport.svg b/editor/icons/SubViewport.svg
index 1e17ae234f..d5da67ee53 100644
--- a/editor/icons/SubViewport.svg
+++ b/editor/icons/SubViewport.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 2c-.5304.0000801-1.0390625.2108475-1.4140625.5859375-.37509.37501-.5858575.8836225-.5859375 1.4140625v8c.0000803.5304.2108475 1.039063.5859375 1.414062.37501.375091.8836225.585858 1.4140625.585938h10c1.1046 0 2-.89543 2-2v-8c0-1.1046-.89543-2-2-2zm0 1h10c.55228.0000096.99999.44772 1 1v8c-.00001.55228-.44772.99999-1 1h-10c-.55228-.00001-.99999-.44772-1-1v-8c.0000096-.55228.44772-.99999 1-1zm3 1c-.5304.0001-1.0390625.2108375-1.4140625.5859375-.37509.375-.5858575.8836225-.5859375 1.4140625v4c.00008.5304.2108475 1.039062.5859375 1.414062.37501.3751.8836225.585838 1.4140625.585938h4c1.1046 0 2-.8954 2-2v-4c0-1.1046-.89543-2-2-2zm0 1h4c.55228 0 .99999.4477 1 1v4c-.00001.5523-.44772 1-1 1h-4c-.55228 0-.99999-.4477-1-1v-4c.00001-.5523.44772-1 1-1z" fill="#e0e0e0" fill-opacity=".996078"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 2c-.5304.0000801-1.0390625.2108475-1.4140625.5859375-.37509.37501-.5858575.8836225-.5859375 1.4140625v8c.0000803.5304.2108475 1.039063.5859375 1.414062.37501.375091.8836225.585858 1.4140625.585938h10c1.1046 0 2-.89543 2-2v-8c0-1.1046-.89543-2-2-2zm0 1h10c.55228.0000096.99999.44772 1 1v8c-.00001.55228-.44772.99999-1 1h-10c-.55228-.00001-.99999-.44772-1-1v-8c.0000096-.55228.44772-.99999 1-1zm3 1c-.5304.0001-1.0390625.2108375-1.4140625.5859375-.37509.375-.5858575.8836225-.5859375 1.4140625v4c.00008.5304.2108475 1.039062.5859375 1.414062.37501.3751.8836225.585838 1.4140625.585938h4c1.1046 0 2-.8954 2-2v-4c0-1.1046-.89543-2-2-2zm0 1h4c.55228 0 .99999.4477 1 1v4c-.00001.5523-.44772 1-1 1h-4c-.55228 0-.99999-.4477-1-1v-4c.00001-.5523.44772-1 1-1z" fill="#e0e0e0"/></svg>
diff --git a/editor/icons/Texture2DArray.svg b/editor/icons/Texture2DArray.svg
index a71860023b..6d5bf0deb8 100644
--- a/editor/icons/Texture2DArray.svg
+++ b/editor/icons/Texture2DArray.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(-.359546 .287637)"><path d="m2 1c-.5522847 0-1 .4477153-1 1v12c0 .552285.4477153 1 1 1h12c.552285 0 1-.447715 1-1v-12c0-.5522847-.447715-1-1-1zm1 2h10v8h-10z" fill-opacity=".99608" transform="translate(.359546 -.287637)"/><g fill-opacity=".996078" stroke-width=".207395" transform="matrix(1.6197742 0 0 .750929 -3.723153 1.832957)"><path d="m4.9900159 2.5027746h1.85211v1.3316838h-.926055v5.3267353h.926055v1.3316833h-1.85211z"/><path d="m9.9289759 10.492877h-1.85211v-1.3316833h.926055v-5.3267353h-.926055v-1.3316838h1.85211z"/></g></g></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0" transform="translate(-.359546 .287637)"><path d="m2 1c-.5522847 0-1 .4477153-1 1v12c0 .552285.4477153 1 1 1h12c.552285 0 1-.447715 1-1v-12c0-.5522847-.447715-1-1-1zm1 2h10v8h-10z" transform="translate(.359546 -.287637)"/><g stroke-width=".207395" transform="matrix(1.6197742 0 0 .750929 -3.723153 1.832957)"><path d="m4.9900159 2.5027746h1.85211v1.3316838h-.926055v5.3267353h.926055v1.3316833h-1.85211z"/><path d="m9.9289759 10.492877h-1.85211v-1.3316833h.926055v-5.3267353h-.926055v-1.3316838h1.85211z"/></g></g></svg>
diff --git a/editor/icons/TileSelection.svg b/editor/icons/TileSelection.svg
new file mode 100644
index 0000000000..418382aa1c
--- /dev/null
+++ b/editor/icons/TileSelection.svg
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ height="5"
+ viewBox="0 0 5 5"
+ width="5"
+ version="1.1"
+ id="svg10"
+ sodipodi:docname="TileSelection.svg"
+ inkscape:version="1.1 (c68e22c387, 2021-05-23)"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg">
+ <defs
+ id="defs14">
+ <linearGradient
+ id="linearGradient1060"
+ inkscape:swatch="solid">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop1058" />
+ </linearGradient>
+ </defs>
+ <sodipodi:namedview
+ id="namedview12"
+ pagecolor="#505050"
+ bordercolor="#ffffff"
+ borderopacity="1"
+ inkscape:pageshadow="0"
+ inkscape:pageopacity="0"
+ inkscape:pagecheckerboard="1"
+ showgrid="false"
+ inkscape:zoom="64"
+ inkscape:cx="4.3125"
+ inkscape:cy="1.984375"
+ inkscape:window-width="3840"
+ inkscape:window-height="2066"
+ inkscape:window-x="-11"
+ inkscape:window-y="-11"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg10" />
+ <rect
+ style="fill:none;stroke:#ffffff;stroke-width:1.00038;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect940"
+ width="3.9996195"
+ height="3.999619"
+ x="0.50019002"
+ y="0.50019002" />
+ <rect
+ style="fill:none;stroke:#000000;stroke-width:0.999543;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect3062"
+ width="2.000457"
+ height="2.000457"
+ x="1.4997715"
+ y="1.4997715" />
+</svg>
diff --git a/editor/icons/ToolMove.svg b/editor/icons/ToolMove.svg
index b83f62265f..8c14b76eba 100644
--- a/editor/icons/ToolMove.svg
+++ b/editor/icons/ToolMove.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m7.9844 1.002a1.0001 1.0001 0 0 0 -.69141.29102l-2 2 1.4141 1.4141 1.293-1.293 1.293 1.293 1.4141-1.4141-2-2a1.0001 1.0001 0 0 0 -.72266-.29102zm-4.6914 4.291-2 2a1.0001 1.0001 0 0 0 0 1.4141l2 2 1.4141-1.4141-1.293-1.293 1.293-1.293-1.4141-1.4141zm9.4141 0-1.4141 1.4141 1.293 1.293-1.293 1.293 1.4141 1.4141 2-2a1.0001 1.0001 0 0 0 0-1.4141l-2-2zm-4.707.70703a2 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-2zm-1.293 5.293-1.4141 1.4141 2 2a1.0001 1.0001 0 0 0 1.4141 0l2-2-1.4141-1.4141-1.293 1.293-1.293-1.293z" fill="#e0e0e0" fill-opacity=".99608"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m7.9844 1.002a1.0001 1.0001 0 0 0 -.69141.29102l-2 2 1.4141 1.4141 1.293-1.293 1.293 1.293 1.4141-1.4141-2-2a1.0001 1.0001 0 0 0 -.72266-.29102zm-4.6914 4.291-2 2a1.0001 1.0001 0 0 0 0 1.4141l2 2 1.4141-1.4141-1.293-1.293 1.293-1.293-1.4141-1.4141zm9.4141 0-1.4141 1.4141 1.293 1.293-1.293 1.293 1.4141 1.4141 2-2a1.0001 1.0001 0 0 0 0-1.4141l-2-2zm-4.707.70703a2 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-2zm-1.293 5.293-1.4141 1.4141 2 2a1.0001 1.0001 0 0 0 1.4141 0l2-2-1.4141-1.4141-1.293 1.293-1.293-1.293z" fill="#e0e0e0"/></svg>
diff --git a/editor/icons/ToolPan.svg b/editor/icons/ToolPan.svg
index 28ffe6336a..51db68ae74 100644
--- a/editor/icons/ToolPan.svg
+++ b/editor/icons/ToolPan.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m10 1a1 1 0 0 0 -1 1v6h-1v-5a1 1 0 0 0 -1-1 1 1 0 0 0 -1 1v8 .033203l-2.4746-1.8086c-.52015-.3803-1.1948-.4556-1.6504 0-.45566.4556-.45561 1.1948 0 1.6504l4.125 4.125h6a2 2 0 0 0 2-2v-5-4a1 1 0 0 0 -1-1 1 1 0 0 0 -1 1v4h-1v-6a1 1 0 0 0 -1-1z" fill="#e0e0e0" fill-opacity=".99608"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m10 1a1 1 0 0 0 -1 1v6h-1v-5a1 1 0 0 0 -1-1 1 1 0 0 0 -1 1v8 .033203l-2.4746-1.8086c-.52015-.3803-1.1948-.4556-1.6504 0-.45566.4556-.45561 1.1948 0 1.6504l4.125 4.125h6a2 2 0 0 0 2-2v-5-4a1 1 0 0 0 -1-1 1 1 0 0 0 -1 1v4h-1v-6a1 1 0 0 0 -1-1z" fill="#e0e0e0"/></svg>
diff --git a/editor/icons/ToolRotate.svg b/editor/icons/ToolRotate.svg
index 41dd22584d..0fa1904937 100644
--- a/editor/icons/ToolRotate.svg
+++ b/editor/icons/ToolRotate.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8.0879 1.002a7 7 0 0 0 -.30469.0019531 7 7 0 0 0 -.69727.056641 7 7 0 0 0 -5.9512 5.5742 7 7 0 0 0 1.9707 6.3652h-1.1055v2h4a1.0001 1.0001 0 0 0 .9707-1.2422l-1-4-1.9414.48633.28125 1.1211a5 5 0 0 1 -1.3105-3.3652 5 5 0 0 1 5-5 5 5 0 0 1 5 5 5 5 0 0 1 -1.4668 3.5332l1.416 1.416a7 7 0 0 0 1.3281-8.0449 7 7 0 0 0 -6.1895-3.9023zm-.087891 4.998a2 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" fill="#e0e0e0" fill-opacity=".99608"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8.0879 1.002a7 7 0 0 0 -.30469.0019531 7 7 0 0 0 -.69727.056641 7 7 0 0 0 -5.9512 5.5742 7 7 0 0 0 1.9707 6.3652h-1.1055v2h4a1.0001 1.0001 0 0 0 .9707-1.2422l-1-4-1.9414.48633.28125 1.1211a5 5 0 0 1 -1.3105-3.3652 5 5 0 0 1 5-5 5 5 0 0 1 5 5 5 5 0 0 1 -1.4668 3.5332l1.416 1.416a7 7 0 0 0 1.3281-8.0449 7 7 0 0 0 -6.1895-3.9023zm-.087891 4.998a2 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" fill="#e0e0e0"/></svg>
diff --git a/editor/icons/ToolScale.svg b/editor/icons/ToolScale.svg
index 730143a474..9ebeaffeae 100644
--- a/editor/icons/ToolScale.svg
+++ b/editor/icons/ToolScale.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m9 1a1 1 0 0 0 -1 1 1 1 0 0 0 1 1h2.5859l-1.293 1.293 1.4141 1.4141 1.293-1.293v2.5859a1 1 0 0 0 1 1 1 1 0 0 0 1-1v-5a1.0001 1.0001 0 0 0 -1-1zm-1 5a2 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-2zm-6 2a1 1 0 0 0 -1 1v5a1.0001 1.0001 0 0 0 1 1h5a1 1 0 0 0 1-1 1 1 0 0 0 -1-1h-2.5859l1.293-1.293-1.4141-1.4141-1.293 1.293v-2.5859a1 1 0 0 0 -1-1z" fill="#e0e0e0" fill-opacity=".99608"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m9 1a1 1 0 0 0 -1 1 1 1 0 0 0 1 1h2.5859l-1.293 1.293 1.4141 1.4141 1.293-1.293v2.5859a1 1 0 0 0 1 1 1 1 0 0 0 1-1v-5a1.0001 1.0001 0 0 0 -1-1zm-1 5a2 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-2zm-6 2a1 1 0 0 0 -1 1v5a1.0001 1.0001 0 0 0 1 1h5a1 1 0 0 0 1-1 1 1 0 0 0 -1-1h-2.5859l1.293-1.293-1.4141-1.4141-1.293 1.293v-2.5859a1 1 0 0 0 -1-1z" fill="#e0e0e0"/></svg>
diff --git a/editor/icons/TrackTrigger.svg b/editor/icons/TrackTrigger.svg
deleted file mode 100644
index c403fba59a..0000000000
--- a/editor/icons/TrackTrigger.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg height="8" viewBox="0 0 16 8" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 1v2h2v4h2v-4h2v-2zm13 0a1 1 0 0 0 -1 1 1 1 0 0 0 1 1 1 1 0 0 0 1-1 1 1 0 0 0 -1-1zm-3 2a1 1 0 0 0 -1 1 1 1 0 0 0 1 1 1 1 0 0 0 1-1 1 1 0 0 0 -1-1zm-3 2a1 1 0 0 0 -1 1 1 1 0 0 0 1 1 1 1 0 0 0 1-1 1 1 0 0 0 -1-1z" fill="#f68f45"/></svg>
diff --git a/editor/icons/TripleBar.svg b/editor/icons/TripleBar.svg
index 2b521e6c15..6baea09478 100644
--- a/editor/icons/TripleBar.svg
+++ b/editor/icons/TripleBar.svg
@@ -1 +1 @@
-<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="m1.9375 4h12.062zm0 4h12.062zm0 4h12.062z" fill="none" stroke="#e0e0e0" stroke-opacity=".99608" stroke-width=".92823"/></svg>
+<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="m1.9375 4h12.062zm0 4h12.062zm0 4h12.062z" fill="none" stroke="#e0e0e0" stroke-width=".92823"/></svg>
diff --git a/editor/icons/VehicleBody3D.svg b/editor/icons/VehicleBody3D.svg
index 00e4696a17..5e21f40c85 100644
--- a/editor/icons/VehicleBody3D.svg
+++ b/editor/icons/VehicleBody3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m5 3a1 1 0 0 0 -1 1l-1 3h-2v4h1.0508c.23167-1.1411 1.2398-2 2.4492-2s2.2175.85893 2.4492 2h2.1016c.23167-1.1411 1.2398-2 2.4492-2s2.2175.85893 2.4492 2h1.0508v-4h-4v-4zm1 1h4v3h-4zm-1.5 6a1.5 1.5 0 0 0 -1.5 1.5 1.5 1.5 0 0 0 1.5 1.5 1.5 1.5 0 0 0 1.5-1.5 1.5 1.5 0 0 0 -1.5-1.5zm7 0a1.5 1.5 0 0 0 -1.5 1.5 1.5 1.5 0 0 0 1.5 1.5 1.5 1.5 0 0 0 1.5-1.5 1.5 1.5 0 0 0 -1.5-1.5z" fill="#fc7f7f" fill-opacity=".99608"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m5 3a1 1 0 0 0 -1 1l-1 3h-2v4h1.0508c.23167-1.1411 1.2398-2 2.4492-2s2.2175.85893 2.4492 2h2.1016c.23167-1.1411 1.2398-2 2.4492-2s2.2175.85893 2.4492 2h1.0508v-4h-4v-4zm1 1h4v3h-4zm-1.5 6a1.5 1.5 0 0 0 -1.5 1.5 1.5 1.5 0 0 0 1.5 1.5 1.5 1.5 0 0 0 1.5-1.5 1.5 1.5 0 0 0 -1.5-1.5zm7 0a1.5 1.5 0 0 0 -1.5 1.5 1.5 1.5 0 0 0 1.5 1.5 1.5 1.5 0 0 0 1.5-1.5 1.5 1.5 0 0 0 -1.5-1.5z" fill="#fc7f7f"/></svg>
diff --git a/editor/icons/VehicleWheel3D.svg b/editor/icons/VehicleWheel3D.svg
index 4c825d6e34..540bad8ab0 100644
--- a/editor/icons/VehicleWheel3D.svg
+++ b/editor/icons/VehicleWheel3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1a7 7 0 0 0 -7 7 7 7 0 0 0 7 7 7 7 0 0 0 7-7 7 7 0 0 0 -7-7zm0 2a5 5 0 0 1 5 5 5 5 0 0 1 -5 5 5 5 0 0 1 -5-5 5 5 0 0 1 5-5zm0 1a4 4 0 0 0 -4 4 4 4 0 0 0 4 4 4 4 0 0 0 4-4 4 4 0 0 0 -4-4zm0 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-1zm-2 2a1 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-1zm4 0a1 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-1zm-2 2a1 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="#fc7f7f" fill-opacity=".99608"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1a7 7 0 0 0 -7 7 7 7 0 0 0 7 7 7 7 0 0 0 7-7 7 7 0 0 0 -7-7zm0 2a5 5 0 0 1 5 5 5 5 0 0 1 -5 5 5 5 0 0 1 -5-5 5 5 0 0 1 5-5zm0 1a4 4 0 0 0 -4 4 4 4 0 0 0 4 4 4 4 0 0 0 4-4 4 4 0 0 0 -4-4zm0 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-1zm-2 2a1 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-1zm4 0a1 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-1zm-2 2a1 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="#fc7f7f"/></svg>
diff --git a/editor/icons/Viewport.svg b/editor/icons/Viewport.svg
index 7d388c1c6d..9de1e8b05a 100644
--- a/editor/icons/Viewport.svg
+++ b/editor/icons/Viewport.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 2c-.5304.0000801-1.0391.21085-1.4141.58594-.37509.37501-.58586.88366-.58594 1.4141v8c.0000803.5304.21085 1.0391.58594 1.4141.37501.37509.88366.58586 1.4141.58594h10c1.1046 0 2-.89543 2-2v-8c0-1.1046-.89543-2-2-2zm0 1h10c.55228.0000096.99999.44772 1 1v8c-.00001.55228-.44772.99999-1 1h-10c-.55228-.00001-.99999-.44772-1-1v-8c.0000096-.55228.44772-.99999 1-1z" fill="#e0e0e0" fill-opacity=".99608"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 2c-.5304.0000801-1.0391.21085-1.4141.58594-.37509.37501-.58586.88366-.58594 1.4141v8c.0000803.5304.21085 1.0391.58594 1.4141.37501.37509.88366.58586 1.4141.58594h10c1.1046 0 2-.89543 2-2v-8c0-1.1046-.89543-2-2-2zm0 1h10c.55228.0000096.99999.44772 1 1v8c-.00001.55228-.44772.99999-1 1h-10c-.55228-.00001-.99999-.44772-1-1v-8c.0000096-.55228.44772-.99999 1-1z" fill="#e0e0e0"/></svg>
diff --git a/editor/icons/ViewportSpeed.svg b/editor/icons/ViewportSpeed.svg
index 57292e2e91..caed3cb1de 100644
--- a/editor/icons/ViewportSpeed.svg
+++ b/editor/icons/ViewportSpeed.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g stroke-width="3.77953"><path d="m6.0285136 0c-1.0906961 0-2.0000127.90931655-2.0000127 2.0000126v2.3105008c-.3234859-.1927559-.6845858-.3367559-1.0781102-.3223937-1.3171276.048-2.24957487 1.4115024-1.8164032 2.6561764l.9960945 2.9883213c.183927.5526806.6039307.9375116 1.1054741 1.1581986l-2.30275287 1.537096c-.49591181.31937-.83535119.846198-.91211339 1.373102-.07676977.526904.06603212 1.019906.33007748 1.416.26404536.396095.66572598.719811 1.18163158.851603.5153008.131528 1.1318173.02268 1.6171842-.312566h.00195l4.1015433-2.734413.9863434 1.972611c.4415244.884069 1.4843716 1.316372 2.4218832 1.00388l3-.999987-.02929.01134c.570898-.17159 1.048139-.590173 1.265613-1.082078.217466-.491906.208418-1.011893.05664-1.466797-.119282-.357543-.41469-.637606-.728504-.892611.261162-.206362.546142-.39171.681638-.730394.195632-.489109.17105-1.1070991-.08984-1.6289007l-1.000027-2.0011107c-.337916-.6777827-1.033625-1.1077039-1.789039-1.1075905h-.419906c.196645-.3087874.419906-.6128126.419906-.9999874v-3.0000001c0-1.09069605-.909317-2.0000126-2.000012-2.0000126z"/><path d="m6.0285136.99998741c-.5540032 0-.9999874.44598429-.9999874 1.00002519v3.0000001c0 .5540031.4459842.9999874.9999874.9999874h.9999874v.9902362a1.0001008 1.0001008 0 0 0 -.316407.062362l-2.0507716.6835656-.6836032-2.0507717a1.0001008 1.0001008 0 0 0 -.9902362-.6972473 1.0001008 1.0001008 0 0 0 -.9082205 1.328126l.9999874 3.0000001a1.0001008 1.0001008 0 0 0 1.2656126.6328063l1.6835906-.5605418v.6113008c0 .040819.018709.075591.023433.1152757l-4.5781418 3.052762a1.0001008 1.0001008 0 1 0 1.1093669 1.664051l5.05663-3.371112 1.4941228 2.986356a1.0001008 1.0001008 0 0 0 1.210922.501921l3.000001-.999987a1.0001008 1.0001008 0 1 0 -.632807-1.896378l-2.177726.724611-.9746262-1.951182c.275898-.177637.4687372-.472252.4687372-.8261665v-.9999874h1.382815l.722646 1.4472569a1.0001246 1.0001246 0 1 0 1.789077-.8945388l-.999987-1.9999748a1.0001008 1.0001008 0 0 0 -.894539-.5527559h-2.9999995v-.9999874h.9999875c.554003 0 .999987-.4459843.999987-.9999874v-3.0000001c0-.5540409-.445984-1.00002519-.999987-1.00002519zm0 2.00001259h.9999874v2.0000127h-.9999874z" fill="#fff" fill-opacity=".99608"/></g></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g stroke-width="3.77953"><path d="m6.0285136 0c-1.0906961 0-2.0000127.90931655-2.0000127 2.0000126v2.3105008c-.3234859-.1927559-.6845858-.3367559-1.0781102-.3223937-1.3171276.048-2.24957487 1.4115024-1.8164032 2.6561764l.9960945 2.9883213c.183927.5526806.6039307.9375116 1.1054741 1.1581986l-2.30275287 1.537096c-.49591181.31937-.83535119.846198-.91211339 1.373102-.07676977.526904.06603212 1.019906.33007748 1.416.26404536.396095.66572598.719811 1.18163158.851603.5153008.131528 1.1318173.02268 1.6171842-.312566h.00195l4.1015433-2.734413.9863434 1.972611c.4415244.884069 1.4843716 1.316372 2.4218832 1.00388l3-.999987-.02929.01134c.570898-.17159 1.048139-.590173 1.265613-1.082078.217466-.491906.208418-1.011893.05664-1.466797-.119282-.357543-.41469-.637606-.728504-.892611.261162-.206362.546142-.39171.681638-.730394.195632-.489109.17105-1.1070991-.08984-1.6289007l-1.000027-2.0011107c-.337916-.6777827-1.033625-1.1077039-1.789039-1.1075905h-.419906c.196645-.3087874.419906-.6128126.419906-.9999874v-3.0000001c0-1.09069605-.909317-2.0000126-2.000012-2.0000126z"/><path d="m6.0285136.99998741c-.5540032 0-.9999874.44598429-.9999874 1.00002519v3.0000001c0 .5540031.4459842.9999874.9999874.9999874h.9999874v.9902362a1.0001008 1.0001008 0 0 0 -.316407.062362l-2.0507716.6835656-.6836032-2.0507717a1.0001008 1.0001008 0 0 0 -.9902362-.6972473 1.0001008 1.0001008 0 0 0 -.9082205 1.328126l.9999874 3.0000001a1.0001008 1.0001008 0 0 0 1.2656126.6328063l1.6835906-.5605418v.6113008c0 .040819.018709.075591.023433.1152757l-4.5781418 3.052762a1.0001008 1.0001008 0 1 0 1.1093669 1.664051l5.05663-3.371112 1.4941228 2.986356a1.0001008 1.0001008 0 0 0 1.210922.501921l3.000001-.999987a1.0001008 1.0001008 0 1 0 -.632807-1.896378l-2.177726.724611-.9746262-1.951182c.275898-.177637.4687372-.472252.4687372-.8261665v-.9999874h1.382815l.722646 1.4472569a1.0001246 1.0001246 0 1 0 1.789077-.8945388l-.999987-1.9999748a1.0001008 1.0001008 0 0 0 -.894539-.5527559h-2.9999995v-.9999874h.9999875c.554003 0 .999987-.4459843.999987-.9999874v-3.0000001c0-.5540409-.445984-1.00002519-.999987-1.00002519zm0 2.00001259h.9999874v2.0000127h-.9999874z" fill="#fff"/></g></svg>
diff --git a/editor/icons/ViewportTexture.svg b/editor/icons/ViewportTexture.svg
index 3dd448b1ac..a5b1e4ab07 100644
--- a/editor/icons/ViewportTexture.svg
+++ b/editor/icons/ViewportTexture.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 2c-.5304.0000801-1.0391.21085-1.4141.58594-.37509.37501-.58586.88366-.58594 1.4141v8c.0000803.5304.21085 1.0391.58594 1.4141.37501.37509.88366.58586 1.4141.58594h10c1.1046 0 2-.89543 2-2v-8c0-1.1046-.89543-2-2-2h-10zm0 1h10c.55228.0000096.99999.44772 1 1v8c-.00001.55228-.44772.99999-1 1h-10c-.55228-.00001-.99999-.44772-1-1v-8c.0000096-.55228.44772-.99999 1-1zm6 3v1h-1v1h-2v1h-1v1h-1v1h2 2 2 2v-2h-1v-1-1h-1v-1z" fill="#e0e0e0" fill-opacity=".99608"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 2c-.5304.0000801-1.0391.21085-1.4141.58594-.37509.37501-.58586.88366-.58594 1.4141v8c.0000803.5304.21085 1.0391.58594 1.4141.37501.37509.88366.58586 1.4141.58594h10c1.1046 0 2-.89543 2-2v-8c0-1.1046-.89543-2-2-2h-10zm0 1h10c.55228.0000096.99999.44772 1 1v8c-.00001.55228-.44772.99999-1 1h-10c-.55228-.00001-.99999-.44772-1-1v-8c.0000096-.55228.44772-.99999 1-1zm6 3v1h-1v1h-2v1h-1v1h-1v1h2 2 2 2v-2h-1v-1-1h-1v-1z" fill="#e0e0e0"/></svg>
diff --git a/editor/icons/VisibleOnScreenEnabler3D.svg b/editor/icons/VisibleOnScreenEnabler3D.svg
index 6923bcb46b..1c24a348a5 100644
--- a/editor/icons/VisibleOnScreenEnabler3D.svg
+++ b/editor/icons/VisibleOnScreenEnabler3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 1v3h1v-2h2v-1zm11 0v1h2v2h1v-3zm-4 1c-2.5567 0-5.7907 1.9477-6.9551 5.7051a1.0001 1.0001 0 0 0 -.0058594.57031c1.1244 3.9354 4.4609 5.7246 6.9609 5.7246s5.8365-1.7892 6.9609-5.7246a1.0001 1.0001 0 0 0 0-.55273c-1.1003-3.7876-4.4066-5.7227-6.9609-5.7227zm0 2a4 4 0 0 1 4 4 4 4 0 0 1 -4 4 4 4 0 0 1 -4-4 4 4 0 0 1 4-4zm0 2a2 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-2zm-7 6v3h3v-1h-2v-2zm13 0v2h-2v1h3v-3z" fill="#fc7f7f" fill-opacity=".99608" fill-rule="evenodd"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 1v3h1v-2h2v-1zm11 0v1h2v2h1v-3zm-4 1c-2.5567 0-5.7907 1.9477-6.9551 5.7051a1.0001 1.0001 0 0 0 -.0058594.57031c1.1244 3.9354 4.4609 5.7246 6.9609 5.7246s5.8365-1.7892 6.9609-5.7246a1.0001 1.0001 0 0 0 0-.55273c-1.1003-3.7876-4.4066-5.7227-6.9609-5.7227zm0 2a4 4 0 0 1 4 4 4 4 0 0 1 -4 4 4 4 0 0 1 -4-4 4 4 0 0 1 4-4zm0 2a2 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-2zm-7 6v3h3v-1h-2v-2zm13 0v2h-2v1h3v-3z" fill="#fc7f7f" fill-rule="evenodd"/></svg>
diff --git a/editor/icons/VisibleOnScreenNotifier3D.svg b/editor/icons/VisibleOnScreenNotifier3D.svg
index 2fdf784701..f731ae99a2 100644
--- a/editor/icons/VisibleOnScreenNotifier3D.svg
+++ b/editor/icons/VisibleOnScreenNotifier3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m12 1v6h2v-6zm-4 2c-2.5567 0-5.7907 1.9477-6.9551 5.7051a1.0001 1.0001 0 0 0 -.0058594.57031c1.1244 3.9354 4.4609 5.7246 6.9609 5.7246 1.4907 0 3.2717-.65207 4.7109-2h-.71094-2v-.54102a4 4 0 0 1 -2 .54102 4 4 0 0 1 -4-4 4 4 0 0 1 4-4 4 4 0 0 1 2 .54102v-2.1816c-.68312-.23834-1.3644-.35938-2-.35938zm0 4a2 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-2zm4 2v2h2v-2z" fill="#fc7f7f" fill-opacity=".99608" fill-rule="evenodd"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m12 1v6h2v-6zm-4 2c-2.5567 0-5.7907 1.9477-6.9551 5.7051a1.0001 1.0001 0 0 0 -.0058594.57031c1.1244 3.9354 4.4609 5.7246 6.9609 5.7246 1.4907 0 3.2717-.65207 4.7109-2h-.71094-2v-.54102a4 4 0 0 1 -2 .54102 4 4 0 0 1 -4-4 4 4 0 0 1 4-4 4 4 0 0 1 2 .54102v-2.1816c-.68312-.23834-1.3644-.35938-2-.35938zm0 4a2 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-2zm4 2v2h2v-2z" fill="#fc7f7f" fill-rule="evenodd"/></svg>
diff --git a/editor/icons/VoxelGI.svg b/editor/icons/VoxelGI.svg
index f5e1025260..58567569af 100644
--- a/editor/icons/VoxelGI.svg
+++ b/editor/icons/VoxelGI.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m2 1a1.0001 1.0001 0 0 0 -1 1v12a1.0001 1.0001 0 0 0 1 1h4v-2h-3v-10h9v-2zm9 3a4 4 0 0 0 -4 4 4 4 0 0 0 2 3.459v.54102c0 .55401.44599 1 1 1h2c.55401 0 1-.44599 1-1v-.54102a4 4 0 0 0 2-3.459 4 4 0 0 0 -4-4zm0 2a2 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-2zm-1 8v1h2v-1z" fill="#fc7f7f" fill-opacity=".99608"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m2 1a1.0001 1.0001 0 0 0 -1 1v12a1.0001 1.0001 0 0 0 1 1h4v-2h-3v-10h9v-2zm9 3a4 4 0 0 0 -4 4 4 4 0 0 0 2 3.459v.54102c0 .55401.44599 1 1 1h2c.55401 0 1-.44599 1-1v-.54102a4 4 0 0 0 2-3.459 4 4 0 0 0 -4-4zm0 2a2 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-2zm-1 8v1h2v-1z" fill="#fc7f7f"/></svg>
diff --git a/editor/icons/WorldEnvironment.svg b/editor/icons/WorldEnvironment.svg
index d26ec52034..6c7e34657f 100644
--- a/editor/icons/WorldEnvironment.svg
+++ b/editor/icons/WorldEnvironment.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g stroke-linecap="round" stroke-linejoin="round" stroke-width="2"><path d="m8 1a7 7 0 0 0 -7 7 7 7 0 0 0 7 7 7 7 0 0 0 7-7 7 7 0 0 0 -7-7zm-1.7305 2.3125c-.83125 1.5372-1.2685 3.1037-1.2695 4.6816-.64057-.11251-1.3005-.27158-1.9766-.47266a5 5 0 0 1 3.2461-4.209zm3.4629.0039062a5 5 0 0 1 3.2383 4.1875c-.65187.17448-1.3077.32867-1.9727.44922-.00845-1.5627-.44294-3.1141-1.2656-4.6367zm-1.7324.0078126c1.0126 1.593 1.5 3.1425 1.5 4.6758 0 .054042-.0066161.10803-.0078125.16211-.96392.096801-1.9566.1103-2.9844.027344-.0016335-.063192-.0078125-.12632-.0078125-.18945 0-1.5333.48744-3.0828 1.5-4.6758zm4.8789 5.7578a5 5 0 0 1 -3.1484 3.6055c.57106-1.0564.95277-2.1268 1.1367-3.2051.68204-.10905 1.3556-.23789 2.0117-.40039zm-9.7461.033203c.68377.18153 1.3555.33345 2.0098.43164.18781 1.0551.56647 2.1026 1.125 3.1367a5 5 0 0 1 -3.1348-3.5684zm6.168.55469c-.22615.98866-.65424 1.9884-1.3008 3.0059-.63811-1.0042-1.0645-1.9908-1.293-2.9668.89027.054126 1.7517.029377 2.5938-.039062z" fill="#fc7f7f" fill-opacity=".99608"/><path d="m8 1v2.3242c1.0126 1.593 1.5 3.1425 1.5 4.6758 0 .054042-.0066161.10803-.0078125.16211-.4894.049148-.98713.077552-1.4922.082031v1.4922c.43915-.0075968.87287-.031628 1.3008-.066406-.22615.98866-.65424 1.9884-1.3008 3.0059v2.3242a7 7 0 0 0 7-7 7 7 0 0 0 -7-7zm1.7324 2.3164a5 5 0 0 1 3.2383 4.1875c-.65187.17448-1.3077.32867-1.9727.44922-.00845-1.5627-.44294-3.1141-1.2656-4.6367zm3.1465 5.7656a5 5 0 0 1 -3.1484 3.6055c.57106-1.0564.95277-2.1268 1.1367-3.2051.68204-.10905 1.3556-.23789 2.0117-.40039z" fill="#8da5f3"/></g></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g stroke-linecap="round" stroke-linejoin="round" stroke-width="2"><path d="m8 1a7 7 0 0 0 -7 7 7 7 0 0 0 7 7 7 7 0 0 0 7-7 7 7 0 0 0 -7-7zm-1.7305 2.3125c-.83125 1.5372-1.2685 3.1037-1.2695 4.6816-.64057-.11251-1.3005-.27158-1.9766-.47266a5 5 0 0 1 3.2461-4.209zm3.4629.0039062a5 5 0 0 1 3.2383 4.1875c-.65187.17448-1.3077.32867-1.9727.44922-.00845-1.5627-.44294-3.1141-1.2656-4.6367zm-1.7324.0078126c1.0126 1.593 1.5 3.1425 1.5 4.6758 0 .054042-.0066161.10803-.0078125.16211-.96392.096801-1.9566.1103-2.9844.027344-.0016335-.063192-.0078125-.12632-.0078125-.18945 0-1.5333.48744-3.0828 1.5-4.6758zm4.8789 5.7578a5 5 0 0 1 -3.1484 3.6055c.57106-1.0564.95277-2.1268 1.1367-3.2051.68204-.10905 1.3556-.23789 2.0117-.40039zm-9.7461.033203c.68377.18153 1.3555.33345 2.0098.43164.18781 1.0551.56647 2.1026 1.125 3.1367a5 5 0 0 1 -3.1348-3.5684zm6.168.55469c-.22615.98866-.65424 1.9884-1.3008 3.0059-.63811-1.0042-1.0645-1.9908-1.293-2.9668.89027.054126 1.7517.029377 2.5938-.039062z" fill="#fc7f7f"/><path d="m8 1v2.3242c1.0126 1.593 1.5 3.1425 1.5 4.6758 0 .054042-.0066161.10803-.0078125.16211-.4894.049148-.98713.077552-1.4922.082031v1.4922c.43915-.0075968.87287-.031628 1.3008-.066406-.22615.98866-.65424 1.9884-1.3008 3.0059v2.3242a7 7 0 0 0 7-7 7 7 0 0 0 -7-7zm1.7324 2.3164a5 5 0 0 1 3.2383 4.1875c-.65187.17448-1.3077.32867-1.9727.44922-.00845-1.5627-.44294-3.1141-1.2656-4.6367zm3.1465 5.7656a5 5 0 0 1 -3.1484 3.6055c.57106-1.0564.95277-2.1268 1.1367-3.2051.68204-.10905 1.3556-.23789 2.0117-.40039z" fill="#8da5f3"/></g></svg>
diff --git a/editor/icons/Zoom.svg b/editor/icons/Zoom.svg
index fc0102f0e3..6e6462af35 100644
--- a/editor/icons/Zoom.svg
+++ b/editor/icons/Zoom.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m6 1a5 5 0 0 0 -5 5 5 5 0 0 0 5 5 5 5 0 0 0 2.752-.83398l4.3184 4.3184 1.4141-1.4141-4.3184-4.3184a5 5 0 0 0 .41016-.75195h-.57617v-2h-1a3 3 0 0 1 -3 3 3 3 0 0 1 -3-3 3 3 0 0 1 3-3 3 3 0 0 1 2 .76758v-1.7676h.99023a5 5 0 0 0 -2.9902-1zm5 0v2h-2v2h2v2h2v-2h2v-2h-2v-2z" fill="#e0e0e0" fill-opacity=".99608"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m6 1a5 5 0 0 0 -5 5 5 5 0 0 0 5 5 5 5 0 0 0 2.752-.83398l4.3184 4.3184 1.4141-1.4141-4.3184-4.3184a5 5 0 0 0 .41016-.75195h-.57617v-2h-1a3 3 0 0 1 -3 3 3 3 0 0 1 -3-3 3 3 0 0 1 3-3 3 3 0 0 1 2 .76758v-1.7676h.99023a5 5 0 0 0 -2.9902-1zm5 0v2h-2v2h2v2h2v-2h2v-2h-2v-2z" fill="#e0e0e0"/></svg>
diff --git a/editor/import/audio_stream_import_settings.cpp b/editor/import/audio_stream_import_settings.cpp
index d94b517003..92d4397c68 100644
--- a/editor/import/audio_stream_import_settings.cpp
+++ b/editor/import/audio_stream_import_settings.cpp
@@ -32,6 +32,7 @@
#include "editor/audio_stream_preview.h"
#include "editor/editor_file_system.h"
#include "editor/editor_scale.h"
+#include "scene/gui/check_box.h"
AudioStreamImportSettings *AudioStreamImportSettings::singleton = nullptr;
@@ -287,17 +288,15 @@ void AudioStreamImportSettings::_draw_indicator() {
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) {
+ if (i - text_w / 2 > 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;
@@ -466,12 +465,17 @@ void AudioStreamImportSettings::_settings_changed() {
updating_settings = true;
stream->call("set_loop", loop->is_pressed());
stream->call("set_loop_offset", loop_offset->get_value());
+ if (loop->is_pressed()) {
+ loop_offset->set_editable(true);
+ } else {
+ loop_offset->set_editable(false);
+ }
+
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();
+ beats_enabled->set_disabled(false);
+ beats_edit->set_editable(true);
+ bar_beats_edit->set_editable(true);
double bpm = bpm_edit->get_value();
if (bpm > 0) {
float beat_size = 60 / float(bpm);
@@ -487,10 +491,9 @@ void AudioStreamImportSettings::_settings_changed() {
} 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();
+ beats_enabled->set_disabled(true);
+ beats_edit->set_editable(false);
+ bar_beats_edit->set_editable(false);
}
if (bpm_enabled->is_pressed() && beats_enabled->is_pressed()) {
stream->call("set_beat_count", beats_edit->get_value());
@@ -553,17 +556,8 @@ AudioStreamImportSettings::AudioStreamImportSettings() {
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_text(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->set_text(TTR("Beat Count:"));
beats_enabled->connect("toggled", callable_mp(this, &AudioStreamImportSettings::_settings_changed).unbind(1));
interactive_hb->add_child(beats_enabled);
beats_edit = memnew(SpinBox);
@@ -571,6 +565,15 @@ AudioStreamImportSettings::AudioStreamImportSettings() {
beats_edit->set_max(99999);
beats_edit->connect("value_changed", callable_mp(this, &AudioStreamImportSettings::_settings_changed).unbind(1));
interactive_hb->add_child(beats_edit);
+ bar_beats_label = memnew(Label(TTR("Bar Beats:")));
+ interactive_hb->add_child(bar_beats_label);
+ bar_beats_edit = memnew(SpinBox);
+ bar_beats_edit->set_tooltip_text(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();
main_vbox->add_margin_child(TTR("Music Playback:"), interactive_hb);
color_rect = memnew(ColorRect);
diff --git a/editor/import/audio_stream_import_settings.h b/editor/import/audio_stream_import_settings.h
index 5e399237ca..fc756c6524 100644
--- a/editor/import/audio_stream_import_settings.h
+++ b/editor/import/audio_stream_import_settings.h
@@ -34,9 +34,12 @@
#include "editor/editor_plugin.h"
#include "scene/audio/audio_stream_player.h"
#include "scene/gui/color_rect.h"
+#include "scene/gui/dialogs.h"
#include "scene/gui/spin_box.h"
#include "scene/resources/texture.h"
+class CheckBox;
+
class AudioStreamImportSettings : public ConfirmationDialog {
GDCLASS(AudioStreamImportSettings, ConfirmationDialog);
diff --git a/editor/import/dynamic_font_import_settings.cpp b/editor/import/dynamic_font_import_settings.cpp
index f61ff5182d..afcfacdf75 100644
--- a/editor/import/dynamic_font_import_settings.cpp
+++ b/editor/import/dynamic_font_import_settings.cpp
@@ -30,6 +30,7 @@
#include "dynamic_font_import_settings.h"
+#include "core/config/project_settings.h"
#include "editor/editor_file_dialog.h"
#include "editor/editor_file_system.h"
#include "editor/editor_inspector.h"
@@ -468,6 +469,8 @@ void DynamicFontImportSettings::_main_prop_changed(const String &p_edited_proper
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 == "allow_system_fallback") {
+ font_preview->set_allow_system_fallback(import_settings_data->get("allow_system_fallback"));
} else if (p_edited_property == "force_autohinter") {
font_preview->set_force_autohinter(import_settings_data->get("force_autohinter"));
} else if (p_edited_property == "hinting") {
@@ -528,6 +531,12 @@ void DynamicFontImportSettings::_variation_selected() {
label_glyphs->set_text(TTR("Preloaded glyphs: ") + itos(import_variation_data->selected_glyphs.size()));
_range_selected();
_change_text_opts();
+
+ btn_fill->set_disabled(false);
+ btn_fill_locales->set_disabled(false);
+ } else {
+ btn_fill->set_disabled(true);
+ btn_fill_locales->set_disabled(true);
}
}
@@ -551,6 +560,15 @@ void DynamicFontImportSettings::_variation_remove(Object *p_item, int p_column,
}
_variations_validate();
+
+ vars_item = vars_list->get_selected();
+ if (vars_item) {
+ btn_fill->set_disabled(false);
+ btn_fill_locales->set_disabled(false);
+ } else {
+ btn_fill->set_disabled(true);
+ btn_fill_locales->set_disabled(true);
+ }
}
void DynamicFontImportSettings::_variation_changed(const String &p_edited_property) {
@@ -623,6 +641,27 @@ void DynamicFontImportSettings::_change_text_opts() {
text_edit->add_theme_font_override("font", font_main_text);
}
+void DynamicFontImportSettings::_glyph_update_lbl() {
+ 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;
+ }
+
+ int linked_glyphs = 0;
+ for (const char32_t &c : import_variation_data->selected_chars) {
+ if (import_variation_data->selected_glyphs.has(font_main->get_glyph_index(16, c))) {
+ linked_glyphs++;
+ }
+ }
+ int unlinked_glyphs = import_variation_data->selected_glyphs.size() - linked_glyphs;
+ label_glyphs->set_text(TTR("Preloaded glyphs:") + " " + itos(unlinked_glyphs + import_variation_data->selected_chars.size()));
+}
+
void DynamicFontImportSettings::_glyph_clear() {
Ref<DynamicFontImportSettingsData> import_variation_data;
@@ -635,7 +674,7 @@ void DynamicFontImportSettings::_glyph_clear() {
}
import_variation_data->selected_glyphs.clear();
- label_glyphs->set_text(TTR("Preloaded glyphs:") + " " + itos(import_variation_data->selected_glyphs.size()));
+ _glyph_update_lbl();
_range_selected();
}
@@ -662,7 +701,7 @@ void DynamicFontImportSettings::_glyph_text_selected() {
}
}
TS->free_rid(text_rid);
- label_glyphs->set_text(TTR("Preloaded glyphs:") + " " + itos(import_variation_data->selected_glyphs.size()));
+ _glyph_update_lbl();
}
_range_selected();
}
@@ -699,7 +738,7 @@ void DynamicFontImportSettings::_glyph_selected() {
item->clear_custom_bg_color(glyph_table->get_selected_column());
}
}
- label_glyphs->set_text(TTR("Preloaded glyphs:") + " " + itos(import_variation_data->selected_glyphs.size()));
+ _glyph_update_lbl();
item = glyph_tree->get_selected();
ERR_FAIL_NULL(item);
@@ -800,7 +839,7 @@ void DynamicFontImportSettings::_edit_range(int32_t p_start, int32_t p_end) {
col = 0;
}
}
- label_glyphs->set_text(TTR("Preloaded glyphs:") + " " + itos(import_variation_data->selected_glyphs.size()));
+ _glyph_update_lbl();
}
bool DynamicFontImportSettings::_char_update(int32_t p_char) {
@@ -899,6 +938,7 @@ void DynamicFontImportSettings::_re_import() {
main_settings["multichannel_signed_distance_field"] = import_settings_data->get("multichannel_signed_distance_field");
main_settings["msdf_pixel_range"] = import_settings_data->get("msdf_pixel_range");
main_settings["msdf_size"] = import_settings_data->get("msdf_size");
+ main_settings["allow_system_fallback"] = import_settings_data->get("allow_system_fallback");
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");
@@ -914,9 +954,18 @@ void DynamicFontImportSettings::_re_import() {
Dictionary preload_config;
preload_config["name"] = vars_item->get_text(0);
+ Size2i conf_size = Vector2i(16, 0);
for (const KeyValue<StringName, Variant> &E : import_variation_data->settings) {
- preload_config[E.key] = E.value;
+ if (E.key == "size") {
+ conf_size.x = E.value;
+ }
+ if (E.key == "outline_size") {
+ conf_size.y = E.value;
+ } else {
+ preload_config[E.key] = E.value;
+ }
}
+ preload_config["size"] = conf_size;
Array chars;
for (const char32_t &E : import_variation_data->selected_chars) {
@@ -947,9 +996,72 @@ void DynamicFontImportSettings::_re_import() {
EditorFileSystem::get_singleton()->reimport_file_with_custom_parameters(base_path, "font_data_dynamic", main_settings);
}
+void DynamicFontImportSettings::_locale_edited() {
+ TreeItem *item = locale_tree->get_selected();
+ ERR_FAIL_NULL(item);
+ item->set_checked(0, !item->is_checked(0));
+}
+
+void DynamicFontImportSettings::_process_locales() {
+ 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;
+ }
+
+ for (int i = 0; i < locale_root->get_child_count(); i++) {
+ TreeItem *item = locale_root->get_child(i);
+ if (item) {
+ if (item->is_checked(0)) {
+ String locale = item->get_text(0);
+ Ref<Translation> tr = ResourceLoader::load(locale);
+ if (tr.is_valid()) {
+ Vector<String> messages = tr->get_translated_message_list();
+ for (const String &E : messages) {
+ RID text_rid = TS->create_shaped_text();
+ if (text_rid.is_valid()) {
+ TS->shaped_text_add_string(text_rid, E, font_main->get_rids(), 16, Dictionary(), tr->get_locale());
+ 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 j = 0; j < gl_size; j++) {
+ if (gl[j].font_rid.is_valid() && gl[j].index != 0) {
+ import_variation_data->selected_glyphs.insert(gl[j].index);
+ }
+ }
+ TS->free_rid(text_rid);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ _glyph_update_lbl();
+ _range_selected();
+}
+
void DynamicFontImportSettings::open_settings(const String &p_path) {
// Load base font data.
- Vector<uint8_t> font_data = FileAccess::get_file_as_array(p_path);
+ Vector<uint8_t> font_data = FileAccess::get_file_as_bytes(p_path);
+
+ // Load project locale list.
+ locale_tree->clear();
+ locale_root = locale_tree->create_item();
+ ERR_FAIL_NULL(locale_root);
+
+ Vector<String> translations = GLOBAL_GET("internationalization/locale/translations");
+ for (const String &E : translations) {
+ TreeItem *item = locale_tree->create_item(locale_root);
+ ERR_FAIL_NULL(item);
+ item->set_cell_mode(0, TreeItem::CELL_MODE_CHECK);
+ item->set_text(0, E);
+ }
// Load font for preview.
font_preview.instantiate();
@@ -1003,10 +1115,11 @@ void DynamicFontImportSettings::open_settings(const String &p_path) {
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();
+ glyph_tree->set_selected(glyph_root->get_child(0));
+
vars_list_root = vars_list->create_item();
import_settings_data->settings.clear();
@@ -1080,6 +1193,10 @@ void DynamicFontImportSettings::open_settings(const String &p_path) {
import_variation_data_custom->selected_glyphs.insert(c);
}
}
+ if (preload_configurations.is_empty()) {
+ _variation_add(); // Add default variation.
+ }
+ vars_list->set_selected(vars_list_root->get_child(0));
} else {
Variant value = config->get_value("params", key);
import_settings_data->defaults[key] = value;
@@ -1097,6 +1214,7 @@ void DynamicFontImportSettings::open_settings(const String &p_path) {
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_allow_system_fallback(import_settings_data->get("allow_system_fallback"));
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());
@@ -1127,6 +1245,7 @@ DynamicFontImportSettings::DynamicFontImportSettings() {
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));
options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::INT, "msdf_pixel_range", PROPERTY_HINT_RANGE, "1,100,1"), 8));
options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::INT, "msdf_size", PROPERTY_HINT_RANGE, "1,250,1"), 48));
+ options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "allow_system_fallback"), true));
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));
@@ -1138,7 +1257,7 @@ DynamicFontImportSettings::DynamicFontImportSettings() {
options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::DICTIONARY, "opentype_features"), Dictionary()));
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()));
+ options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::ARRAY, "fallbacks", PROPERTY_HINT_ARRAY_TYPE, MAKE_RESOURCE_TYPE_HINT("Font")), Array()));
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));
@@ -1269,11 +1388,57 @@ DynamicFontImportSettings::DynamicFontImportSettings() {
inspector_vars->connect("property_edited", callable_mp(this, &DynamicFontImportSettings::_variation_changed));
page2_side_vb->add_child(inspector_vars);
+ VBoxContainer *preload_pages_vb = memnew(VBoxContainer);
+ page2_hb->add_child(preload_pages_vb);
+
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);
+ preload_pages_vb->add_child(preload_pages);
+
+ HBoxContainer *gl_hb = memnew(HBoxContainer);
+ preload_pages_vb->add_child(gl_hb);
+ gl_hb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+
+ label_glyphs = memnew(Label);
+ gl_hb->add_child(label_glyphs);
+ label_glyphs->set_text(TTR("Preloaded glyphs:") + " " + itos(0));
+ label_glyphs->set_custom_minimum_size(Size2(50 * EDSCALE, 0));
+
+ Button *btn_clear = memnew(Button);
+ gl_hb->add_child(btn_clear);
+ btn_clear->set_text(TTR("Clear Glyph List"));
+ btn_clear->connect("pressed", callable_mp(this, &DynamicFontImportSettings::_glyph_clear));
+
+ VBoxContainer *page2_0_vb = memnew(VBoxContainer);
+ page2_0_vb->set_name(TTR("Glyphs from the Translations"));
+ preload_pages->add_child(page2_0_vb);
+
+ page2_0_description = memnew(Label);
+ page2_0_description->set_text(TTR("Select translations to add all required glyphs to pre-render list:"));
+ page2_0_description->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ page2_0_description->set_autowrap_mode(TextServer::AUTOWRAP_WORD_SMART);
+ page2_0_vb->add_child(page2_0_description);
+
+ locale_tree = memnew(Tree);
+ page2_0_vb->add_child(locale_tree);
+ locale_tree->set_columns(1);
+ locale_tree->set_hide_root(true);
+ locale_tree->set_column_expand(0, true);
+ locale_tree->connect("item_activated", callable_mp(this, &DynamicFontImportSettings::_locale_edited));
+ locale_tree->set_column_custom_minimum_width(0, 120 * EDSCALE);
+ locale_tree->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+ locale_root = locale_tree->create_item();
+
+ HBoxContainer *locale_hb = memnew(HBoxContainer);
+ page2_0_vb->add_child(locale_hb);
+ locale_hb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+
+ btn_fill_locales = memnew(Button);
+ locale_hb->add_child(btn_fill_locales);
+ btn_fill_locales->set_text(TTR("Shape all Strings in the Translations and Add Glyphs"));
+ btn_fill_locales->connect("pressed", callable_mp(this, &DynamicFontImportSettings::_process_locales));
// Page 2.1 layout: Text to select glyphs
VBoxContainer *page2_1_vb = memnew(VBoxContainer);
@@ -1281,7 +1446,7 @@ DynamicFontImportSettings::DynamicFontImportSettings() {
preload_pages->add_child(page2_1_vb);
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_text(TTR("Enter a text and select OpenType features 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);
@@ -1307,21 +1472,11 @@ DynamicFontImportSettings::DynamicFontImportSettings() {
page2_1_vb->add_child(text_hb);
text_hb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- label_glyphs = memnew(Label);
- text_hb->add_child(label_glyphs);
- label_glyphs->set_text(TTR("Preloaded glyphs:") + " " + itos(0));
- label_glyphs->set_custom_minimum_size(Size2(50 * EDSCALE, 0));
-
- Button *btn_fill = memnew(Button);
+ btn_fill = memnew(Button);
text_hb->add_child(btn_fill);
btn_fill->set_text(TTR("Shape Text and Add Glyphs"));
btn_fill->connect("pressed", callable_mp(this, &DynamicFontImportSettings::_glyph_text_selected));
- Button *btn_clear = memnew(Button);
- text_hb->add_child(btn_clear);
- btn_clear->set_text(TTR("Clear Glyph List"));
- btn_clear->connect("pressed", callable_mp(this, &DynamicFontImportSettings::_glyph_clear));
-
// Page 2.2 layout: Character map
VBoxContainer *page2_2_vb = memnew(VBoxContainer);
page2_2_vb->set_name(TTR("Glyphs from the Character Map"));
diff --git a/editor/import/dynamic_font_import_settings.h b/editor/import/dynamic_font_import_settings.h
index a1f763b445..386e9896dc 100644
--- a/editor/import/dynamic_font_import_settings.h
+++ b/editor/import/dynamic_font_import_settings.h
@@ -118,18 +118,30 @@ class DynamicFontImportSettings : public ConfirmationDialog {
TabContainer *preload_pages = nullptr;
+ Label *label_glyphs = nullptr;
+ void _glyph_clear();
+ void _glyph_update_lbl();
+
+ // Page 2.0 layout: Translations
+ Label *page2_0_description = nullptr;
+ Tree *locale_tree = nullptr;
+ TreeItem *locale_root = nullptr;
+ Button *btn_fill_locales = nullptr;
+
+ void _locale_edited();
+ void _process_locales();
+
// Page 2.1 layout: Text to select glyphs
Label *page2_1_description = nullptr;
- Label *label_glyphs = nullptr;
TextEdit *text_edit = nullptr;
EditorInspector *inspector_text = nullptr;
+ Button *btn_fill = nullptr;
List<ResourceImporter::ImportOption> options_text;
Ref<DynamicFontImportSettingsData> text_settings_data;
void _change_text_opts();
void _glyph_text_selected();
- void _glyph_clear();
// Page 2.2 layout: Character map
Label *page2_2_description = nullptr;
diff --git a/editor/import/editor_import_collada.cpp b/editor/import/editor_import_collada.cpp
index 6890a46193..c335655d4e 100644
--- a/editor/import/editor_import_collada.cpp
+++ b/editor/import/editor_import_collada.cpp
@@ -65,7 +65,7 @@ struct ColladaImport {
bool force_make_tangents = false;
bool apply_mesh_xform_to_vertices = true;
bool use_mesh_builtin_materials = false;
- float bake_fps = 15;
+ float bake_fps = 30;
HashMap<String, NodeMap> node_map; //map from collada node to engine node
HashMap<String, String> node_name_map; //map from collada node to engine node
@@ -1760,7 +1760,7 @@ void EditorSceneFormatImporterCollada::get_extensions(List<String> *r_extensions
r_extensions->push_back("dae");
}
-Node *EditorSceneFormatImporterCollada::import_scene(const String &p_path, uint32_t p_flags, const HashMap<StringName, Variant> &p_options, int p_bake_fps, List<String> *r_missing_deps, Error *r_err) {
+Node *EditorSceneFormatImporterCollada::import_scene(const String &p_path, uint32_t p_flags, const HashMap<StringName, Variant> &p_options, List<String> *r_missing_deps, Error *r_err) {
if (r_err) {
*r_err = OK;
}
@@ -1771,7 +1771,7 @@ Node *EditorSceneFormatImporterCollada::import_scene(const String &p_path, uint3
}
state.use_mesh_builtin_materials = true;
- state.bake_fps = p_bake_fps;
+ state.bake_fps = (float)p_options["animation/fps"];
Error err = state.load(p_path, flags, p_flags & EditorSceneFormatImporter::IMPORT_GENERATE_TANGENT_ARRAYS, false);
diff --git a/editor/import/editor_import_collada.h b/editor/import/editor_import_collada.h
index a75b0a903f..ec30c91c1b 100644
--- a/editor/import/editor_import_collada.h
+++ b/editor/import/editor_import_collada.h
@@ -39,7 +39,7 @@ class EditorSceneFormatImporterCollada : public EditorSceneFormatImporter {
public:
virtual uint32_t get_import_flags() const override;
virtual void get_extensions(List<String> *r_extensions) const override;
- virtual Node *import_scene(const String &p_path, uint32_t p_flags, const HashMap<StringName, Variant> &p_options, int p_bake_fps, List<String> *r_missing_deps = nullptr, Error *r_err = nullptr) override;
+ virtual Node *import_scene(const String &p_path, uint32_t p_flags, const HashMap<StringName, Variant> &p_options, List<String> *r_missing_deps = nullptr, Error *r_err = nullptr) override;
EditorSceneFormatImporterCollada();
};
diff --git a/editor/import/post_import_plugin_skeleton_renamer.cpp b/editor/import/post_import_plugin_skeleton_renamer.cpp
index 72ccb832c7..c2694329c2 100644
--- a/editor/import/post_import_plugin_skeleton_renamer.cpp
+++ b/editor/import/post_import_plugin_skeleton_renamer.cpp
@@ -44,100 +44,164 @@ void PostImportPluginSkeletonRenamer::get_internal_import_options(InternalImport
}
}
-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);
+void PostImportPluginSkeletonRenamer::_internal_process(InternalImportCategory p_category, Node *p_base_scene, Node *p_node, Ref<Resource> p_resource, const Dictionary &p_options, HashMap<String, String> p_rename_map) {
+ // Prepare objects.
+ Object *map = p_options["retarget/bone_map"].get_validated_object();
+ if (!map || !bool(p_options["retarget/bone_renamer/rename_bones"])) {
+ return;
+ }
+ 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 Skeleton3D.
+ {
+ int len = skeleton->get_bone_count();
+ for (int i = 0; i < len; i++) {
+ StringName bn = p_rename_map[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 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 = p_rename_map[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 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 = p_rename_map[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);
+ Dictionary rename_map_dict;
+ for (HashMap<String, String>::Iterator E = p_rename_map.begin(); E; ++E) {
+ rename_map_dict[E->key] = E->value;
+ }
+ vargs.push_back(rename_map_dict);
+ 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);
+ }
+ }
+}
+
+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;
+ }
+ Skeleton3D *skeleton = Object::cast_to<Skeleton3D>(p_node);
+ BoneMap *bone_map = Object::cast_to<BoneMap>(map);
+ int len = skeleton->get_bone_count();
+
+ // First, prepare main rename map.
+ HashMap<String, String> main_rename_map;
+ for (int i = 0; i < len; i++) {
+ String bone_name = skeleton->get_bone_name(i);
+ String target_name = bone_map->find_profile_bone_name(bone_name);
+ if (target_name.is_empty()) {
+ continue;
+ }
+ main_rename_map.insert(bone_name, target_name);
+ }
- // Rename bones in all Nodes by calling method.
+ // Preprocess of renaming bones to avoid to conflict with original bone name.
+ HashMap<String, String> pre_rename_map; // HashMap<skeleton bone name, target(profile) bone name>
{
- 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];
+ Vector<String> solved_name_stack;
+ for (int i = 0; i < len; i++) {
+ String bone_name = skeleton->get_bone_name(i);
+ String target_name = bone_map->find_profile_bone_name(bone_name);
+ if (target_name.is_empty() || bone_name == target_name || skeleton->find_bone(target_name) == -1) {
+ continue; // No conflicting.
+ }
+
+ // Solve conflicting.
+ Ref<SkeletonProfile> profile = bone_map->get_profile();
+ String solved_name = target_name;
+ for (int j = 2; skeleton->find_bone(solved_name) >= 0 || profile->find_bone(solved_name) >= 0 || solved_name_stack.has(solved_name); j++) {
+ solved_name = target_name + itos(j);
+ }
+ solved_name_stack.push_back(solved_name);
+ pre_rename_map.insert(target_name, solved_name);
}
+ _internal_process(p_category, p_base_scene, p_node, p_resource, p_options, pre_rename_map);
+ }
- 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);
+ // Main process of renaming bones.
+ {
+ // Apply pre-renaming result to prepared main rename map.
+ Vector<String> remove_queue;
+ for (HashMap<String, String>::Iterator E = main_rename_map.begin(); E; ++E) {
+ if (pre_rename_map.has(E->key)) {
+ remove_queue.push_back(E->key);
+ }
+ }
+ for (int i = 0; i < remove_queue.size(); i++) {
+ main_rename_map.insert(pre_rename_map[remove_queue[i]], main_rename_map[remove_queue[i]]);
+ main_rename_map.erase(remove_queue[i]);
}
+ _internal_process(p_category, p_base_scene, p_node, p_resource, p_options, main_rename_map);
}
// Make unique skeleton.
diff --git a/editor/import/post_import_plugin_skeleton_renamer.h b/editor/import/post_import_plugin_skeleton_renamer.h
index 73cbabd1c5..b430f49ff4 100644
--- a/editor/import/post_import_plugin_skeleton_renamer.h
+++ b/editor/import/post_import_plugin_skeleton_renamer.h
@@ -40,6 +40,8 @@ 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;
+ void _internal_process(InternalImportCategory p_category, Node *p_base_scene, Node *p_node, Ref<Resource> p_resource, const Dictionary &p_options, HashMap<String, String> p_rename_map);
+
PostImportPluginSkeletonRenamer();
};
diff --git a/editor/import/resource_importer_bmfont.cpp b/editor/import/resource_importer_bmfont.cpp
index 14b5638755..357faf0022 100644
--- a/editor/import/resource_importer_bmfont.cpp
+++ b/editor/import/resource_importer_bmfont.cpp
@@ -60,7 +60,7 @@ 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::ARRAY, "fallbacks", PROPERTY_HINT_ARRAY_TYPE, MAKE_RESOURCE_TYPE_HINT("Font")), Array()));
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "compress"), true));
}
@@ -76,6 +76,7 @@ Error ResourceImporterBMFont::import(const String &p_source_file, const String &
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 + "\".");
+ font->set_allow_system_fallback(false);
font->set_fallbacks(fallbacks);
int flg = 0;
diff --git a/editor/import/resource_importer_dynamic_font.cpp b/editor/import/resource_importer_dynamic_font.cpp
index a6ae832479..2f1445af48 100644
--- a/editor/import/resource_importer_dynamic_font.cpp
+++ b/editor/import/resource_importer_dynamic_font.cpp
@@ -114,13 +114,14 @@ void ResourceImporterDynamicFont::get_import_options(const String &p_path, List<
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "msdf_pixel_range", PROPERTY_HINT_RANGE, "1,100,1"), 8));
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "msdf_size", PROPERTY_HINT_RANGE, "1,250,1"), 48));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "allow_system_fallback"), true));
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, "oversampling", PROPERTY_HINT_RANGE, "0,10,0.1"), 0.0));
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::ARRAY, "fallbacks", PROPERTY_HINT_ARRAY_TYPE, MAKE_RESOURCE_TYPE_HINT("Font")), Array()));
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));
@@ -150,13 +151,14 @@ Error ResourceImporterDynamicFont::import(const String &p_source_file, const Str
Dictionary ot_ov = p_options["opentype_features"];
bool autohinter = p_options["force_autohinter"];
+ bool allow_system_fallback = p_options["allow_system_fallback"];
int hinting = p_options["hinting"];
int subpixel_positioning = p_options["subpixel_positioning"];
real_t oversampling = p_options["oversampling"];
Array fallbacks = p_options["fallbacks"];
// Load base font data.
- Vector<uint8_t> data = FileAccess::get_file_as_array(p_source_file);
+ Vector<uint8_t> data = FileAccess::get_file_as_bytes(p_source_file);
// Create font.
Ref<FontFile> font;
@@ -170,6 +172,7 @@ Error ResourceImporterDynamicFont::import(const String &p_source_file, const Str
font->set_opentype_feature_overrides(ot_ov);
font->set_fixed_size(0);
font->set_force_autohinter(autohinter);
+ font->set_allow_system_fallback(allow_system_fallback);
font->set_subpixel_positioning((TextServer::SubpixelPositioning)subpixel_positioning);
font->set_hinting((TextServer::Hinting)hinting);
font->set_oversampling(oversampling);
diff --git a/editor/import/resource_importer_imagefont.cpp b/editor/import/resource_importer_imagefont.cpp
index 58c2061051..9c3304d946 100644
--- a/editor/import/resource_importer_imagefont.cpp
+++ b/editor/import/resource_importer_imagefont.cpp
@@ -63,9 +63,10 @@ void ResourceImporterImageFont::get_import_options(const String &p_path, List<Im
r_options->push_back(ImportOption(PropertyInfo(Variant::PACKED_STRING_ARRAY, "character_ranges"), Vector<String>()));
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::RECT2I, "image_margin"), Rect2i()));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::RECT2I, "character_margin"), Rect2i()));
- 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::ARRAY, "fallbacks", PROPERTY_HINT_ARRAY_TYPE, MAKE_RESOURCE_TYPE_HINT("Font")), Array()));
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "compress"), true));
}
@@ -93,33 +94,40 @@ Error ResourceImporterImageFont::import(const String &p_source_file, const Strin
int columns = p_options["columns"];
int rows = p_options["rows"];
- int base_size = p_options["font_size"];
Vector<String> ranges = p_options["character_ranges"];
Array fallbacks = p_options["fallbacks"];
+ Rect2i img_margin = p_options["image_margin"];
+ Rect2i char_margin = p_options["character_margin"];
+
+ Ref<Image> img;
+ img.instantiate();
+ Error err = ImageLoader::load_image(p_source_file, img);
+ ERR_FAIL_COND_V_MSG(err != OK, ERR_FILE_CANT_READ, TTR("Can't load font texture:") + " \"" + p_source_file + "\".");
+
+ int count = columns * rows;
+ int chr_cell_width = (img->get_width() - img_margin.position.x - img_margin.size.x) / columns;
+ int chr_cell_height = (img->get_height() - img_margin.position.y - img_margin.size.y) / rows;
+ ERR_FAIL_COND_V_MSG(chr_cell_width <= 0 || chr_cell_height <= 0, ERR_FILE_CANT_READ, TTR("Image margin too big."));
+
+ int chr_width = chr_cell_width - char_margin.position.x - char_margin.size.x;
+ int chr_height = chr_cell_height - char_margin.position.y - char_margin.size.y;
+ ERR_FAIL_COND_V_MSG(chr_width <= 0 || chr_height <= 0, ERR_FILE_CANT_READ, TTR("Character margin too bit."));
Ref<FontFile> font;
font.instantiate();
font->set_antialiasing(TextServer::FONT_ANTIALIASING_NONE);
font->set_generate_mipmaps(false);
font->set_multichannel_signed_distance_field(false);
- font->set_fixed_size(base_size);
+ font->set_fixed_size(chr_height);
font->set_subpixel_positioning(TextServer::SUBPIXEL_POSITIONING_DISABLED);
font->set_force_autohinter(false);
+ font->set_allow_system_fallback(false);
font->set_hinting(TextServer::HINTING_NONE);
font->set_oversampling(1.0f);
font->set_fallbacks(fallbacks);
+ font->set_texture_image(0, Vector2i(chr_height, 0), 0, img);
- Ref<Image> img;
- img.instantiate();
- Error err = ImageLoader::load_image(p_source_file, img);
- ERR_FAIL_COND_V_MSG(err != OK, ERR_FILE_CANT_READ, TTR("Can't load font texture:") + " \"" + p_source_file + "\".");
- font->set_texture_image(0, Vector2i(base_size, 0), 0, img);
-
- int count = columns * rows;
- int chr_width = img->get_width() / columns;
- int chr_height = img->get_height() / rows;
int pos = 0;
-
for (int i = 0; i < ranges.size(); i++) {
int32_t start, end;
Vector<String> tokens = ranges[i].split("-");
@@ -141,17 +149,17 @@ Error ResourceImporterImageFont::import(const String &p_source_file, const Strin
for (int32_t idx = start; idx <= end; idx++) {
int x = pos % columns;
int y = pos / columns;
- font->set_glyph_advance(0, base_size, idx, Vector2(chr_width, 0));
- font->set_glyph_offset(0, Vector2i(base_size, 0), idx, Vector2(0, -0.5 * chr_height));
- font->set_glyph_size(0, Vector2i(base_size, 0), idx, Vector2(chr_width, chr_height));
- font->set_glyph_uv_rect(0, Vector2i(base_size, 0), idx, Rect2(chr_width * x, chr_height * y, chr_width, chr_height));
- font->set_glyph_texture_idx(0, Vector2i(base_size, 0), idx, 0);
+ font->set_glyph_advance(0, chr_height, idx, Vector2(chr_width, 0));
+ font->set_glyph_offset(0, Vector2i(chr_height, 0), idx, Vector2(0, -0.5 * chr_height));
+ font->set_glyph_size(0, Vector2i(chr_height, 0), idx, Vector2(chr_width, chr_height));
+ font->set_glyph_uv_rect(0, Vector2i(chr_height, 0), idx, Rect2(img_margin.position.x + chr_cell_width * x + char_margin.position.x, img_margin.position.y + chr_cell_height * y + char_margin.position.y, chr_width, chr_height));
+ font->set_glyph_texture_idx(0, Vector2i(chr_height, 0), idx, 0);
pos++;
- ERR_FAIL_COND_V_MSG(pos >= count, ERR_CANT_CREATE, "Too many characters in range.");
+ ERR_FAIL_COND_V_MSG(pos >= count, ERR_CANT_CREATE, "Too many characters in range, should be " + itos(columns * rows));
}
}
- font->set_cache_ascent(0, base_size, 0.5 * chr_height);
- font->set_cache_descent(0, base_size, 0.5 * chr_height);
+ font->set_cache_ascent(0, chr_height, 0.5 * chr_height);
+ font->set_cache_descent(0, chr_height, 0.5 * chr_height);
int flg = 0;
if ((bool)p_options["compress"]) {
diff --git a/editor/import/resource_importer_obj.cpp b/editor/import/resource_importer_obj.cpp
index fe70fd58b5..f19b4dbe56 100644
--- a/editor/import/resource_importer_obj.cpp
+++ b/editor/import/resource_importer_obj.cpp
@@ -422,7 +422,7 @@ static Error _parse_obj(const String &p_path, List<Ref<Mesh>> &r_meshes, bool p_
return OK;
}
-Node *EditorOBJImporter::import_scene(const String &p_path, uint32_t p_flags, const HashMap<StringName, Variant> &p_options, int p_bake_fps, List<String> *r_missing_deps, Error *r_err) {
+Node *EditorOBJImporter::import_scene(const String &p_path, uint32_t p_flags, const HashMap<StringName, Variant> &p_options, List<String> *r_missing_deps, Error *r_err) {
List<Ref<Mesh>> meshes;
Error err = _parse_obj(p_path, meshes, false, p_flags & IMPORT_GENERATE_TANGENT_ARRAYS, false, Vector3(1, 1, 1), Vector3(0, 0, 0), r_missing_deps);
diff --git a/editor/import/resource_importer_obj.h b/editor/import/resource_importer_obj.h
index 4dfac90fa1..121d8e6d36 100644
--- a/editor/import/resource_importer_obj.h
+++ b/editor/import/resource_importer_obj.h
@@ -39,7 +39,7 @@ class EditorOBJImporter : public EditorSceneFormatImporter {
public:
virtual uint32_t get_import_flags() const override;
virtual void get_extensions(List<String> *r_extensions) const override;
- virtual Node *import_scene(const String &p_path, uint32_t p_flags, const HashMap<StringName, Variant> &p_options, int p_bake_fps, List<String> *r_missing_deps, Error *r_err = nullptr) override;
+ virtual Node *import_scene(const String &p_path, uint32_t p_flags, const HashMap<StringName, Variant> &p_options, List<String> *r_missing_deps, Error *r_err = nullptr) override;
EditorOBJImporter();
};
diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp
index a6a0eef11b..9566c1b23c 100644
--- a/editor/import/resource_importer_scene.cpp
+++ b/editor/import/resource_importer_scene.cpp
@@ -74,13 +74,13 @@ void EditorSceneFormatImporter::get_extensions(List<String> *r_extensions) const
ERR_FAIL();
}
-Node *EditorSceneFormatImporter::import_scene(const String &p_path, uint32_t p_flags, const HashMap<StringName, Variant> &p_options, int p_bake_fps, List<String> *r_missing_deps, Error *r_err) {
+Node *EditorSceneFormatImporter::import_scene(const String &p_path, uint32_t p_flags, const HashMap<StringName, Variant> &p_options, List<String> *r_missing_deps, Error *r_err) {
Dictionary options_dict;
for (const KeyValue<StringName, Variant> &elem : p_options) {
options_dict[elem.key] = elem.value;
}
Object *ret = nullptr;
- if (GDVIRTUAL_CALL(_import_scene, p_path, p_flags, options_dict, p_bake_fps, ret)) {
+ if (GDVIRTUAL_CALL(_import_scene, p_path, p_flags, options_dict, ret)) {
return Object::cast_to<Node>(ret);
}
@@ -100,7 +100,7 @@ Variant EditorSceneFormatImporter::get_option_visibility(const String &p_path, b
void EditorSceneFormatImporter::_bind_methods() {
GDVIRTUAL_BIND(_get_import_flags);
GDVIRTUAL_BIND(_get_extensions);
- GDVIRTUAL_BIND(_import_scene, "path", "flags", "options", "bake_fps");
+ GDVIRTUAL_BIND(_import_scene, "path", "flags", "options");
GDVIRTUAL_BIND(_get_import_options, "path");
GDVIRTUAL_BIND(_get_option_visibility, "path", "for_animation", "option");
@@ -355,7 +355,7 @@ static void _pre_gen_shape_list(Ref<ImporterMesh> &mesh, Vector<Ref<Shape3D>> &r
ERR_FAIL_NULL_MSG(mesh, "Cannot generate shape list with null mesh value");
ERR_FAIL_NULL_MSG(mesh->get_mesh(), "Cannot generate shape list with null mesh value");
if (!p_convex) {
- Ref<Shape3D> shape = mesh->create_trimesh_shape();
+ Ref<ConcavePolygonShape3D> shape = mesh->create_trimesh_shape();
r_shape_list.push_back(shape);
} else {
Vector<Ref<Shape3D>> cd;
@@ -402,7 +402,7 @@ void _rescale_importer_mesh(Vector3 p_scale, Ref<ImporterMesh> p_mesh, bool is_s
const int fmt_compress_flags = p_mesh->get_surface_format(surf_idx);
Array arr = p_mesh->get_surface_arrays(surf_idx);
String name = p_mesh->get_surface_name(surf_idx);
- Dictionary lods = Dictionary();
+ Dictionary lods;
Ref<Material> mat = p_mesh->get_surface_material(surf_idx);
{
Vector<Vector3> vertex_array = arr[ArrayMesh::ARRAY_VERTEX];
@@ -1864,6 +1864,7 @@ void ResourceImporterScene::get_import_options(const String &p_path, List<Import
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "skins/use_named_skins"), true));
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "animation/import"), true));
r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "animation/fps", PROPERTY_HINT_RANGE, "1,120,1"), 30));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "animation/trimming"), false));
r_options->push_back(ImportOption(PropertyInfo(Variant::STRING, "import_script/path", PROPERTY_HINT_FILE, script_ext_hint), ""));
r_options->push_back(ImportOption(PropertyInfo(Variant::DICTIONARY, "_subresources", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), Dictionary()));
@@ -2281,13 +2282,8 @@ Node *ResourceImporterScene::pre_import(const String &p_source_file, const HashM
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, p_options, bake_fps, nullptr, &err);
+ Node *scene = importer->import_scene(p_source_file, EditorSceneFormatImporter::IMPORT_ANIMATION | EditorSceneFormatImporter::IMPORT_GENERATE_TANGENT_ARRAYS, p_options, nullptr, &err);
if (!scene || err != OK) {
return nullptr;
}
@@ -2326,8 +2322,6 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p
ERR_FAIL_COND_V(!importer.is_valid(), ERR_FILE_UNRECOGNIZED);
- float fps = p_options["animation/fps"];
-
int import_flags = 0;
if (animation_importer) {
@@ -2350,7 +2344,7 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p
Error err = OK;
List<String> missing_deps; // for now, not much will be done with this
- Node *scene = importer->import_scene(src_path, import_flags, p_options, fps, &missing_deps, &err);
+ Node *scene = importer->import_scene(src_path, import_flags, p_options, &missing_deps, &err);
if (!scene || err != OK) {
return err;
}
@@ -2398,6 +2392,10 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p
post_importer_plugins.write[i]->pre_process(scene, p_options);
}
+ float fps = 30;
+ if (p_options.has(SNAME("animation/fps"))) {
+ fps = (float)p_options[SNAME("animation/fps")];
+ }
_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);
@@ -2450,7 +2448,7 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p
Vector<Vector<uint8_t>> mesh_lightmap_caches;
{
- src_lightmap_cache = FileAccess::get_file_as_array(p_source_file + ".unwrap_cache", &err);
+ src_lightmap_cache = FileAccess::get_file_as_bytes(p_source_file + ".unwrap_cache", &err);
if (err != OK) {
src_lightmap_cache.clear();
}
@@ -2612,7 +2610,7 @@ void EditorSceneFormatImporterESCN::get_extensions(List<String> *r_extensions) c
r_extensions->push_back("escn");
}
-Node *EditorSceneFormatImporterESCN::import_scene(const String &p_path, uint32_t p_flags, const HashMap<StringName, Variant> &p_options, int p_bake_fps, List<String> *r_missing_deps, Error *r_err) {
+Node *EditorSceneFormatImporterESCN::import_scene(const String &p_path, uint32_t p_flags, const HashMap<StringName, Variant> &p_options, List<String> *r_missing_deps, Error *r_err) {
Error error;
Ref<PackedScene> ps = ResourceFormatLoaderText::singleton->load(p_path, p_path, &error);
ERR_FAIL_COND_V_MSG(!ps.is_valid(), nullptr, "Cannot load scene as text resource from path '" + p_path + "'.");
diff --git a/editor/import/resource_importer_scene.h b/editor/import/resource_importer_scene.h
index 5f64330453..678251372b 100644
--- a/editor/import/resource_importer_scene.h
+++ b/editor/import/resource_importer_scene.h
@@ -53,12 +53,12 @@ class EditorSceneFormatImporter : public RefCounted {
protected:
static void _bind_methods();
- Node *import_scene_wrapper(const String &p_path, uint32_t p_flags, Dictionary p_options, int p_bake_fps);
- Ref<Animation> import_animation_wrapper(const String &p_path, uint32_t p_flags, Dictionary p_options, int p_bake_fps);
+ Node *import_scene_wrapper(const String &p_path, uint32_t p_flags, Dictionary p_options);
+ Ref<Animation> import_animation_wrapper(const String &p_path, uint32_t p_flags, Dictionary p_options);
GDVIRTUAL0RC(int, _get_import_flags)
GDVIRTUAL0RC(Vector<String>, _get_extensions)
- GDVIRTUAL4R(Object *, _import_scene, String, uint32_t, Dictionary, uint32_t)
+ GDVIRTUAL3R(Object *, _import_scene, String, uint32_t, Dictionary)
GDVIRTUAL1(_get_import_options, String)
GDVIRTUAL3RC(Variant, _get_option_visibility, String, bool, String)
@@ -74,7 +74,7 @@ public:
virtual uint32_t get_import_flags() const;
virtual void get_extensions(List<String> *r_extensions) const;
- virtual Node *import_scene(const String &p_path, uint32_t p_flags, const HashMap<StringName, Variant> &p_options, int p_bake_fps, List<String> *r_missing_deps, Error *r_err = nullptr);
+ virtual Node *import_scene(const String &p_path, uint32_t p_flags, const HashMap<StringName, Variant> &p_options, List<String> *r_missing_deps, Error *r_err = nullptr);
virtual void get_import_options(const String &p_path, List<ResourceImporter::ImportOption> *r_options);
virtual Variant get_option_visibility(const String &p_path, bool p_for_animation, const String &p_option, const HashMap<StringName, Variant> &p_options);
@@ -310,7 +310,7 @@ class EditorSceneFormatImporterESCN : public EditorSceneFormatImporter {
public:
virtual uint32_t get_import_flags() const override;
virtual void get_extensions(List<String> *r_extensions) const override;
- virtual Node *import_scene(const String &p_path, uint32_t p_flags, const HashMap<StringName, Variant> &p_options, int p_bake_fps, List<String> *r_missing_deps, Error *r_err = nullptr) override;
+ virtual Node *import_scene(const String &p_path, uint32_t p_flags, const HashMap<StringName, Variant> &p_options, List<String> *r_missing_deps, Error *r_err = nullptr) override;
};
template <class M>
diff --git a/editor/import/resource_importer_wav.cpp b/editor/import/resource_importer_wav.cpp
index 1dcae2841b..f5a0f0abcf 100644
--- a/editor/import/resource_importer_wav.cpp
+++ b/editor/import/resource_importer_wav.cpp
@@ -107,7 +107,7 @@ Error ResourceImporterWAV::import(const String &p_source_file, const String &p_s
file->get_buffer((uint8_t *)&riff, 4); //RIFF
if (riff[0] != 'R' || riff[1] != 'I' || riff[2] != 'F' || riff[3] != 'F') {
- ERR_FAIL_V(ERR_FILE_UNRECOGNIZED);
+ ERR_FAIL_V_MSG(ERR_FILE_UNRECOGNIZED, vformat("Not a WAV file. File should start with 'RIFF', but found '%s', in file of size %d bytes", riff, file->get_length()));
}
/* GET FILESIZE */
@@ -115,12 +115,12 @@ Error ResourceImporterWAV::import(const String &p_source_file, const String &p_s
/* CHECK WAVE */
- char wave[4];
-
- file->get_buffer((uint8_t *)&wave, 4); //RIFF
+ char wave[5];
+ wave[4] = 0;
+ file->get_buffer((uint8_t *)&wave, 4); //WAVE
if (wave[0] != 'W' || wave[1] != 'A' || wave[2] != 'V' || wave[3] != 'E') {
- ERR_FAIL_V_MSG(ERR_FILE_UNRECOGNIZED, "Not a WAV file (no WAVE RIFF header).");
+ ERR_FAIL_V_MSG(ERR_FILE_UNRECOGNIZED, vformat("Not a WAV file. Header should contain 'WAVE', but found '%s', in file of size %d bytes", wave, file->get_length()));
}
// Let users override potential loop points from the WAV.
diff --git a/editor/import/scene_import_settings.cpp b/editor/import/scene_import_settings.cpp
index 730aa3bd61..380a4e370c 100644
--- a/editor/import/scene_import_settings.cpp
+++ b/editor/import/scene_import_settings.cpp
@@ -555,6 +555,7 @@ void SceneImportSettings::open_settings(const String &p_path, bool p_for_animati
material_set.clear();
mesh_set.clear();
+ animation_map.clear();
material_map.clear();
mesh_map.clear();
node_map.clear();
@@ -957,15 +958,15 @@ void SceneImportSettings::_notification(int p_what) {
void SceneImportSettings::_menu_callback(int p_id) {
switch (p_id) {
case ACTION_EXTRACT_MATERIALS: {
- save_path->set_text(TTR("Select folder to extract material resources"));
+ save_path->set_title(TTR("Select folder to extract material resources"));
external_extension_type->select(0);
} break;
case ACTION_CHOOSE_MESH_SAVE_PATHS: {
- save_path->set_text(TTR("Select folder where mesh resources will save on import"));
+ save_path->set_title(TTR("Select folder where mesh resources will save on import"));
external_extension_type->select(1);
} break;
case ACTION_CHOOSE_ANIMATION_SAVE_PATHS: {
- save_path->set_text(TTR("Select folder where animations will save on import"));
+ save_path->set_title(TTR("Select folder where animations will save on import"));
external_extension_type->select(1);
} break;
}
diff --git a/editor/input_event_configuration_dialog.cpp b/editor/input_event_configuration_dialog.cpp
index c577c61db7..cb2a8205c2 100644
--- a/editor/input_event_configuration_dialog.cpp
+++ b/editor/input_event_configuration_dialog.cpp
@@ -38,63 +38,6 @@
#include "scene/gui/separator.h"
#include "scene/gui/tree.h"
-// Maps to 2*axis if value is neg, or 2*axis+1 if value is pos.
-static const char *_joy_axis_descriptions[(size_t)JoyAxis::MAX * 2] = {
- TTRC("Left Stick Left, Joystick 0 Left"),
- TTRC("Left Stick Right, Joystick 0 Right"),
- TTRC("Left Stick Up, Joystick 0 Up"),
- TTRC("Left Stick Down, Joystick 0 Down"),
- TTRC("Right Stick Left, Joystick 1 Left"),
- TTRC("Right Stick Right, Joystick 1 Right"),
- TTRC("Right Stick Up, Joystick 1 Up"),
- TTRC("Right Stick Down, Joystick 1 Down"),
- TTRC("Joystick 2 Left"),
- TTRC("Left Trigger, Sony L2, Xbox LT, Joystick 2 Right"),
- TTRC("Joystick 2 Up"),
- TTRC("Right Trigger, Sony R2, Xbox RT, Joystick 2 Down"),
- TTRC("Joystick 3 Left"),
- TTRC("Joystick 3 Right"),
- TTRC("Joystick 3 Up"),
- TTRC("Joystick 3 Down"),
- TTRC("Joystick 4 Left"),
- TTRC("Joystick 4 Right"),
- TTRC("Joystick 4 Up"),
- TTRC("Joystick 4 Down"),
-};
-
-String InputEventConfigurationDialog::get_event_text(const Ref<InputEvent> &p_event, bool p_include_device) const {
- ERR_FAIL_COND_V_MSG(p_event.is_null(), String(), "Provided event is not a valid instance of InputEvent");
-
- String text = p_event->as_text();
-
- Ref<InputEventKey> key = p_event;
- if (key.is_valid() && key->is_command_or_control_autoremap()) {
-#ifdef MACOS_ENABLED
- text = text.replace("Command", "Command/Ctrl");
-#else
- text = text.replace("Ctrl", "Command/Ctrl");
-#endif
- }
- Ref<InputEventMouse> mouse = p_event;
- Ref<InputEventJoypadMotion> jp_motion = p_event;
- Ref<InputEventJoypadButton> jp_button = p_event;
- if (jp_motion.is_valid()) {
- // Joypad motion events will display slightly differently than what the event->as_text() provides. See #43660.
- String desc = TTR("Unknown Joypad Axis");
- if (jp_motion->get_axis() < JoyAxis::MAX) {
- desc = RTR(_joy_axis_descriptions[2 * (size_t)jp_motion->get_axis() + (jp_motion->get_axis_value() < 0 ? 0 : 1)]);
- }
-
- text = vformat("Joypad Axis %s %s (%s)", itos((int64_t)jp_motion->get_axis()), jp_motion->get_axis_value() < 0 ? "-" : "+", desc);
- }
- if (p_include_device && (mouse.is_valid() || jp_button.is_valid() || jp_motion.is_valid())) {
- String device_string = _get_device_string(p_event->get_device());
- text += vformat(" - %s", device_string);
- }
-
- return text;
-}
-
void InputEventConfigurationDialog::_set_event(const Ref<InputEvent> &p_event, bool p_update_input_list_selection) {
if (p_event.is_valid()) {
event = p_event;
@@ -107,7 +50,7 @@ void InputEventConfigurationDialog::_set_event(const Ref<InputEvent> &p_event, b
}
// Update Label
- event_as_text->set_text(get_event_text(event, true));
+ event_as_text->set_text(EventListenerLineEdit::get_event_text(event, true));
Ref<InputEventKey> k = p_event;
Ref<InputEventMouseButton> mb = p_event;
@@ -222,14 +165,7 @@ void InputEventConfigurationDialog::_on_listen_input_changed(const Ref<InputEven
}
if (joym.is_valid()) {
- float axis_value = joym->get_axis_value();
- if (ABS(axis_value) < 0.9) {
- // Ignore motion below 0.9 magnitude to avoid accidental touches
- return;
- } else {
- // Always make the value 1 or -1 for display consistency
- joym->set_axis_value(SIGN(axis_value));
- }
+ joym->set_axis_value(SIGN(joym->get_axis_value()));
}
if (k.is_valid()) {
@@ -305,7 +241,7 @@ void InputEventConfigurationDialog::_update_input_list() {
Ref<InputEventMouseButton> mb;
mb.instantiate();
mb->set_button_index(mouse_buttons[i]);
- String desc = get_event_text(mb, false);
+ String desc = EventListenerLineEdit::get_event_text(mb, false);
if (!search_term.is_empty() && desc.findn(search_term) == -1) {
continue;
@@ -328,7 +264,7 @@ void InputEventConfigurationDialog::_update_input_list() {
Ref<InputEventJoypadButton> joyb;
joyb.instantiate();
joyb->set_button_index((JoyButton)i);
- String desc = get_event_text(joyb, false);
+ String desc = EventListenerLineEdit::get_event_text(joyb, false);
if (!search_term.is_empty() && desc.findn(search_term) == -1) {
continue;
@@ -354,7 +290,7 @@ void InputEventConfigurationDialog::_update_input_list() {
joym.instantiate();
joym->set_axis((JoyAxis)axis);
joym->set_axis_value(direction);
- String desc = get_event_text(joym, false);
+ String desc = EventListenerLineEdit::get_event_text(joym, false);
if (!search_term.is_empty() && desc.findn(search_term) == -1) {
continue;
@@ -513,7 +449,7 @@ void InputEventConfigurationDialog::_device_selection_changed(int p_option_butto
// Subtract 1 as option index 0 corresponds to "All Devices" (value of -1)
// and option index 1 corresponds to device 0, etc...
event->set_device(p_option_button_index - 1);
- event_as_text->set_text(get_event_text(event, true));
+ event_as_text->set_text(EventListenerLineEdit::get_event_text(event, true));
}
void InputEventConfigurationDialog::_set_current_device(int p_device) {
@@ -524,13 +460,6 @@ int InputEventConfigurationDialog::_get_current_device() const {
return device_id_option->get_selected() - 1;
}
-String InputEventConfigurationDialog::_get_device_string(int p_device) const {
- if (p_device == InputMap::ALL_DEVICES) {
- return TTR("All Devices");
- }
- return TTR("Device") + " " + itos(p_device);
-}
-
void InputEventConfigurationDialog::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_VISIBILITY_CHANGED: {
@@ -659,7 +588,7 @@ InputEventConfigurationDialog::InputEventConfigurationDialog() {
device_id_option = memnew(OptionButton);
device_id_option->set_h_size_flags(Control::SIZE_EXPAND_FILL);
for (int i = -1; i < 8; i++) {
- device_id_option->add_item(_get_device_string(i));
+ device_id_option->add_item(EventListenerLineEdit::get_device_string(i));
}
device_id_option->connect("item_selected", callable_mp(this, &InputEventConfigurationDialog::_device_selection_changed));
_set_current_device(InputMap::ALL_DEVICES);
diff --git a/editor/input_event_configuration_dialog.h b/editor/input_event_configuration_dialog.h
index fc590cba26..eb6eb485ea 100644
--- a/editor/input_event_configuration_dialog.h
+++ b/editor/input_event_configuration_dialog.h
@@ -105,7 +105,6 @@ private:
void _device_selection_changed(int p_option_button_index);
void _set_current_device(int p_device);
int _get_current_device() const;
- String _get_device_string(int p_device) const;
protected:
void _notification(int p_what);
@@ -114,7 +113,6 @@ public:
// Pass an existing event to configure it. Alternatively, pass no event to start with a blank configuration.
void popup_and_configure(const Ref<InputEvent> &p_event = Ref<InputEvent>());
Ref<InputEvent> get_event() const;
- String get_event_text(const Ref<InputEvent> &p_event, bool p_include_device) const;
void set_allowed_input_types(int p_type_masks);
diff --git a/editor/inspector_dock.cpp b/editor/inspector_dock.cpp
index bd2eb5fd9e..8cb0e4e8d7 100644
--- a/editor/inspector_dock.cpp
+++ b/editor/inspector_dock.cpp
@@ -365,7 +365,7 @@ void InspectorDock::_select_history(int p_idx) {
}
void InspectorDock::_resource_created() {
- Variant c = new_resource_dialog->instance_selected();
+ Variant c = new_resource_dialog->instantiate_selected();
ERR_FAIL_COND(!c);
Resource *r = Object::cast_to<Resource>(c);
@@ -670,14 +670,14 @@ InspectorDock::InspectorDock(EditorData &p_editor_data) {
backward_button = memnew(Button);
backward_button->set_flat(true);
general_options_hb->add_child(backward_button);
- backward_button->set_tooltip_text(TTR("Go to the previous edited object in history."));
+ backward_button->set_tooltip_text(TTR("Go to previous edited object in history."));
backward_button->set_disabled(true);
backward_button->connect("pressed", callable_mp(this, &InspectorDock::_edit_back));
forward_button = memnew(Button);
forward_button->set_flat(true);
general_options_hb->add_child(forward_button);
- forward_button->set_tooltip_text(TTR("Go to the next edited object in history."));
+ forward_button->set_tooltip_text(TTR("Go to next edited object in history."));
forward_button->set_disabled(true);
forward_button->connect("pressed", callable_mp(this, &InspectorDock::_edit_forward));
diff --git a/editor/plugin_config_dialog.cpp b/editor/plugin_config_dialog.cpp
index a7ebf21cd2..1f350f1199 100644
--- a/editor/plugin_config_dialog.cpp
+++ b/editor/plugin_config_dialog.cpp
@@ -36,6 +36,7 @@
#include "editor/editor_plugin.h"
#include "editor/editor_scale.h"
#include "editor/project_settings_editor.h"
+#include "scene/gui/grid_container.h"
void PluginConfigDialog::_clear_fields() {
name_edit->set_text("");
@@ -218,6 +219,7 @@ PluginConfigDialog::PluginConfigDialog() {
GridContainer *grid = memnew(GridContainer);
grid->set_columns(3);
+ grid->set_v_size_flags(Control::SIZE_EXPAND_FILL);
vbox->add_child(grid);
// Plugin Name
@@ -233,6 +235,7 @@ PluginConfigDialog::PluginConfigDialog() {
name_edit = memnew(LineEdit);
name_edit->connect("text_changed", callable_mp(this, &PluginConfigDialog::_on_required_text_changed));
name_edit->set_placeholder("MyPlugin");
+ name_edit->set_h_size_flags(Control::SIZE_EXPAND_FILL);
grid->add_child(name_edit);
// Subfolder
@@ -247,6 +250,7 @@ PluginConfigDialog::PluginConfigDialog() {
subfolder_edit = memnew(LineEdit);
subfolder_edit->set_placeholder("\"my_plugin\" -> res://addons/my_plugin");
+ subfolder_edit->set_h_size_flags(Control::SIZE_EXPAND_FILL);
subfolder_edit->connect("text_changed", callable_mp(this, &PluginConfigDialog::_on_required_text_changed));
grid->add_child(subfolder_edit);
@@ -262,6 +266,8 @@ PluginConfigDialog::PluginConfigDialog() {
desc_edit = memnew(TextEdit);
desc_edit->set_custom_minimum_size(Size2(400, 80) * EDSCALE);
desc_edit->set_line_wrapping_mode(TextEdit::LineWrappingMode::LINE_WRAPPING_BOUNDARY);
+ desc_edit->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ desc_edit->set_v_size_flags(Control::SIZE_EXPAND_FILL);
grid->add_child(desc_edit);
// Author
@@ -275,6 +281,7 @@ PluginConfigDialog::PluginConfigDialog() {
author_edit = memnew(LineEdit);
author_edit->set_placeholder("Godette");
+ author_edit->set_h_size_flags(Control::SIZE_EXPAND_FILL);
grid->add_child(author_edit);
// Version
@@ -288,6 +295,7 @@ PluginConfigDialog::PluginConfigDialog() {
version_edit = memnew(LineEdit);
version_edit->set_placeholder("1.0");
+ version_edit->set_h_size_flags(Control::SIZE_EXPAND_FILL);
grid->add_child(version_edit);
// Language dropdown
@@ -325,6 +333,7 @@ PluginConfigDialog::PluginConfigDialog() {
script_edit = memnew(LineEdit);
script_edit->connect("text_changed", callable_mp(this, &PluginConfigDialog::_on_required_text_changed));
script_edit->set_placeholder("\"plugin.gd\" -> res://addons/my_plugin/plugin.gd");
+ script_edit->set_h_size_flags(Control::SIZE_EXPAND_FILL);
grid->add_child(script_edit);
// Activate now checkbox
diff --git a/editor/plugins/abstract_polygon_2d_editor.h b/editor/plugins/abstract_polygon_2d_editor.h
index 8a3db9d837..8414945223 100644
--- a/editor/plugins/abstract_polygon_2d_editor.h
+++ b/editor/plugins/abstract_polygon_2d_editor.h
@@ -36,6 +36,7 @@
#include "scene/gui/box_container.h"
class CanvasItemEditor;
+class ConfirmationDialog;
class AbstractPolygon2DEditor : public HBoxContainer {
GDCLASS(AbstractPolygon2DEditor, HBoxContainer);
diff --git a/editor/plugins/animation_blend_space_1d_editor.cpp b/editor/plugins/animation_blend_space_1d_editor.cpp
index f16a6bfa88..7d64055cc3 100644
--- a/editor/plugins/animation_blend_space_1d_editor.cpp
+++ b/editor/plugins/animation_blend_space_1d_editor.cpp
@@ -37,6 +37,8 @@
#include "editor/editor_settings.h"
#include "editor/editor_undo_redo_manager.h"
#include "scene/animation/animation_blend_tree.h"
+#include "scene/gui/check_box.h"
+#include "scene/gui/panel_container.h"
StringName AnimationNodeBlendSpace1DEditor::get_blend_position_path() const {
StringName path = AnimationTreeEditor::get_singleton()->get_base_path() + "blend_position";
@@ -44,6 +46,11 @@ StringName AnimationNodeBlendSpace1DEditor::get_blend_position_path() const {
}
void AnimationNodeBlendSpace1DEditor::_blend_space_gui_input(const Ref<InputEvent> &p_event) {
+ AnimationTree *tree = AnimationTreeEditor::get_singleton()->get_animation_tree();
+ if (!tree) {
+ return;
+ }
+
Ref<InputEventKey> k = p_event;
if (tool_select->is_pressed() && k.is_valid() && k->is_pressed() && k->get_keycode() == Key::KEY_DELETE && !k->is_echo()) {
@@ -69,11 +76,8 @@ void AnimationNodeBlendSpace1DEditor::_blend_space_gui_input(const Ref<InputEven
menu->add_submenu_item(TTR("Add Animation"), "animations");
- AnimationTree *gp = AnimationTreeEditor::get_singleton()->get_tree();
- ERR_FAIL_COND(!gp);
-
- if (gp->has_node(gp->get_animation_player())) {
- AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(gp->get_node(gp->get_animation_player()));
+ if (tree->has_node(tree->get_animation_player())) {
+ AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(tree->get_node(tree->get_animation_player()));
if (ap) {
List<StringName> names;
@@ -153,6 +157,7 @@ void AnimationNodeBlendSpace1DEditor::_blend_space_gui_input(const Ref<InputEven
}
updating = true;
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Move Node Point"));
undo_redo->add_do_method(blend_space.ptr(), "set_blend_point_position", selected_point, point);
undo_redo->add_undo_method(blend_space.ptr(), "set_blend_point_position", selected_point, blend_space->get_blend_point_position(selected_point));
@@ -177,7 +182,7 @@ void AnimationNodeBlendSpace1DEditor::_blend_space_gui_input(const Ref<InputEven
blend_pos *= blend_space->get_max_space() - blend_space->get_min_space();
blend_pos += blend_space->get_min_space();
- AnimationTreeEditor::get_singleton()->get_tree()->set(get_blend_position_path(), blend_pos);
+ tree->set(get_blend_position_path(), blend_pos);
blend_space_draw->queue_redraw();
}
@@ -200,13 +205,18 @@ void AnimationNodeBlendSpace1DEditor::_blend_space_gui_input(const Ref<InputEven
blend_pos *= blend_space->get_max_space() - blend_space->get_min_space();
blend_pos += blend_space->get_min_space();
- AnimationTreeEditor::get_singleton()->get_tree()->set(get_blend_position_path(), blend_pos);
+ tree->set(get_blend_position_path(), blend_pos);
blend_space_draw->queue_redraw();
}
}
void AnimationNodeBlendSpace1DEditor::_blend_space_draw() {
+ AnimationTree *tree = AnimationTreeEditor::get_singleton()->get_animation_tree();
+ if (!tree) {
+ return;
+ }
+
Color linecolor = get_theme_color(SNAME("font_color"), SNAME("Label"));
Color linecolor_soft = linecolor;
linecolor_soft.a *= 0.5;
@@ -298,7 +308,7 @@ void AnimationNodeBlendSpace1DEditor::_blend_space_draw() {
color.a *= 0.5;
}
- float point = AnimationTreeEditor::get_singleton()->get_tree()->get(get_blend_position_path());
+ float point = tree->get(get_blend_position_path());
point = (point - blend_space->get_min_space()) / (blend_space->get_max_space() - blend_space->get_min_space());
point *= s.width;
@@ -341,6 +351,7 @@ void AnimationNodeBlendSpace1DEditor::_config_changed(double) {
}
updating = true;
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
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());
@@ -364,6 +375,7 @@ void AnimationNodeBlendSpace1DEditor::_labels_changed(String) {
}
updating = true;
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Change BlendSpace1D Labels"), UndoRedo::MERGE_ENDS);
undo_redo->add_do_method(blend_space.ptr(), "set_value_label", label_value->get_text());
undo_redo->add_undo_method(blend_space.ptr(), "set_value_label", blend_space->get_value_label());
@@ -419,6 +431,7 @@ void AnimationNodeBlendSpace1DEditor::_add_menu_type(int p_index) {
}
updating = true;
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Add Node Point"));
undo_redo->add_do_method(blend_space.ptr(), "add_blend_point", node, add_point_pos);
undo_redo->add_undo_method(blend_space.ptr(), "remove_blend_point", blend_space->get_blend_point_count());
@@ -437,6 +450,7 @@ void AnimationNodeBlendSpace1DEditor::_add_animation_type(int p_index) {
anim->set_animation(animations_to_add[p_index]);
updating = true;
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Add Animation Point"));
undo_redo->add_do_method(blend_space.ptr(), "add_blend_point", anim, add_point_pos);
undo_redo->add_undo_method(blend_space.ptr(), "remove_blend_point", blend_space->get_blend_point_count());
@@ -510,6 +524,7 @@ void AnimationNodeBlendSpace1DEditor::_erase_selected() {
if (selected_point != -1) {
updating = true;
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Remove BlendSpace1D Point"));
undo_redo->add_do_method(blend_space.ptr(), "remove_blend_point", selected_point);
undo_redo->add_undo_method(blend_space.ptr(), "add_blend_point", blend_space->get_blend_point_node(selected_point), blend_space->get_blend_point_position(selected_point), selected_point);
@@ -529,6 +544,7 @@ void AnimationNodeBlendSpace1DEditor::_edit_point_pos(double) {
}
updating = true;
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Move BlendSpace1D Node Point"));
undo_redo->add_do_method(blend_space.ptr(), "set_blend_point_position", selected_point, edit_value->get_value());
undo_redo->add_undo_method(blend_space.ptr(), "set_blend_point_position", selected_point, blend_space->get_blend_point_position(selected_point));
@@ -566,12 +582,17 @@ void AnimationNodeBlendSpace1DEditor::_notification(int p_what) {
} break;
case NOTIFICATION_PROCESS: {
+ AnimationTree *tree = AnimationTreeEditor::get_singleton()->get_animation_tree();
+ if (!tree) {
+ return;
+ }
+
String error;
- if (!AnimationTreeEditor::get_singleton()->get_tree()->is_active()) {
+ if (!tree->is_active()) {
error = TTR("AnimationTree is inactive.\nActivate to enable playback, check node warnings if activation fails.");
- } else if (AnimationTreeEditor::get_singleton()->get_tree()->is_state_invalid()) {
- error = AnimationTreeEditor::get_singleton()->get_tree()->get_invalid_state_reason();
+ } else if (tree->is_state_invalid()) {
+ error = tree->get_invalid_state_reason();
}
if (error != error_label->get_text()) {
@@ -762,8 +783,6 @@ AnimationNodeBlendSpace1DEditor::AnimationNodeBlendSpace1DEditor() {
error_panel->add_child(error_label);
error_label->set_text("hmmm");
- undo_redo = EditorNode::get_undo_redo();
-
menu = memnew(PopupMenu);
add_child(menu);
menu->connect("id_pressed", callable_mp(this, &AnimationNodeBlendSpace1DEditor::_add_menu_type));
@@ -778,7 +797,6 @@ AnimationNodeBlendSpace1DEditor::AnimationNodeBlendSpace1DEditor() {
open_file->set_title(TTR("Open Animation Node"));
open_file->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE);
open_file->connect("file_selected", callable_mp(this, &AnimationNodeBlendSpace1DEditor::_file_opened));
- undo_redo = EditorNode::get_undo_redo();
set_custom_minimum_size(Size2(0, 150 * EDSCALE));
}
diff --git a/editor/plugins/animation_blend_space_1d_editor.h b/editor/plugins/animation_blend_space_1d_editor.h
index c8b01cb54b..ec07678b27 100644
--- a/editor/plugins/animation_blend_space_1d_editor.h
+++ b/editor/plugins/animation_blend_space_1d_editor.h
@@ -40,7 +40,8 @@
#include "scene/gui/separator.h"
#include "scene/gui/tree.h"
-class EditorUndoRedoManager;
+class CheckBox;
+class PanelContainer;
class AnimationNodeBlendSpace1DEditor : public AnimationTreeNodeEditorPlugin {
GDCLASS(AnimationNodeBlendSpace1DEditor, AnimationTreeNodeEditorPlugin);
@@ -79,8 +80,6 @@ class AnimationNodeBlendSpace1DEditor : public AnimationTreeNodeEditorPlugin {
bool updating = false;
- Ref<EditorUndoRedoManager> undo_redo;
-
static AnimationNodeBlendSpace1DEditor *singleton;
void _blend_space_gui_input(const Ref<InputEvent> &p_event);
diff --git a/editor/plugins/animation_blend_space_2d_editor.cpp b/editor/plugins/animation_blend_space_2d_editor.cpp
index 6f206ff445..526f69732b 100644
--- a/editor/plugins/animation_blend_space_2d_editor.cpp
+++ b/editor/plugins/animation_blend_space_2d_editor.cpp
@@ -42,8 +42,12 @@
#include "editor/editor_undo_redo_manager.h"
#include "scene/animation/animation_blend_tree.h"
#include "scene/animation/animation_player.h"
+#include "scene/gui/check_box.h"
+#include "scene/gui/grid_container.h"
#include "scene/gui/menu_button.h"
+#include "scene/gui/option_button.h"
#include "scene/gui/panel.h"
+#include "scene/gui/panel_container.h"
#include "scene/main/window.h"
bool AnimationNodeBlendSpace2DEditor::can_edit(const Ref<AnimationNode> &p_node) {
@@ -91,6 +95,11 @@ StringName AnimationNodeBlendSpace2DEditor::get_blend_position_path() const {
}
void AnimationNodeBlendSpace2DEditor::_blend_space_gui_input(const Ref<InputEvent> &p_event) {
+ AnimationTree *tree = AnimationTreeEditor::get_singleton()->get_animation_tree();
+ if (!tree) {
+ return;
+ }
+
Ref<InputEventKey> k = p_event;
if (tool_select->is_pressed() && k.is_valid() && k->is_pressed() && k->get_keycode() == Key::KEY_DELETE && !k->is_echo()) {
if (selected_point != -1 || selected_triangle != -1) {
@@ -114,10 +123,8 @@ void AnimationNodeBlendSpace2DEditor::_blend_space_gui_input(const Ref<InputEven
ClassDB::get_inheriters_from_class("AnimationRootNode", &classes);
menu->add_submenu_item(TTR("Add Animation"), "animations");
- AnimationTree *gp = AnimationTreeEditor::get_singleton()->get_tree();
- ERR_FAIL_COND(!gp);
- if (gp && gp->has_node(gp->get_animation_player())) {
- AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(gp->get_node(gp->get_animation_player()));
+ if (tree->has_node(tree->get_animation_player())) {
+ AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(tree->get_node(tree->get_animation_player()));
if (ap) {
List<StringName> names;
ap->get_animation_list(&names);
@@ -221,6 +228,7 @@ void AnimationNodeBlendSpace2DEditor::_blend_space_gui_input(const Ref<InputEven
}
updating = true;
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Add Triangle"));
undo_redo->add_do_method(blend_space.ptr(), "add_triangle", making_triangle[0], making_triangle[1], making_triangle[2]);
undo_redo->add_undo_method(blend_space.ptr(), "remove_triangle", blend_space->get_triangle_count());
@@ -246,6 +254,7 @@ void AnimationNodeBlendSpace2DEditor::_blend_space_gui_input(const Ref<InputEven
if (!read_only) {
updating = true;
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Move Node Point"));
undo_redo->add_do_method(blend_space.ptr(), "set_blend_point_position", selected_point, point);
undo_redo->add_undo_method(blend_space.ptr(), "set_blend_point_position", selected_point, blend_space->get_blend_point_position(selected_point));
@@ -269,7 +278,7 @@ void AnimationNodeBlendSpace2DEditor::_blend_space_gui_input(const Ref<InputEven
blend_pos *= (blend_space->get_max_space() - blend_space->get_min_space());
blend_pos += blend_space->get_min_space();
- AnimationTreeEditor::get_singleton()->get_tree()->set(get_blend_position_path(), blend_pos);
+ tree->set(get_blend_position_path(), blend_pos);
blend_space_draw->queue_redraw();
}
@@ -305,7 +314,7 @@ void AnimationNodeBlendSpace2DEditor::_blend_space_gui_input(const Ref<InputEven
blend_pos *= (blend_space->get_max_space() - blend_space->get_min_space());
blend_pos += blend_space->get_min_space();
- AnimationTreeEditor::get_singleton()->get_tree()->set(get_blend_position_path(), blend_pos);
+ tree->set(get_blend_position_path(), blend_pos);
blend_space_draw->queue_redraw();
}
@@ -353,6 +362,7 @@ void AnimationNodeBlendSpace2DEditor::_add_menu_type(int p_index) {
}
updating = true;
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Add Node Point"));
undo_redo->add_do_method(blend_space.ptr(), "add_blend_point", node, add_point_pos);
undo_redo->add_undo_method(blend_space.ptr(), "remove_blend_point", blend_space->get_blend_point_count());
@@ -371,6 +381,7 @@ void AnimationNodeBlendSpace2DEditor::_add_animation_type(int p_index) {
anim->set_animation(animations_to_add[p_index]);
updating = true;
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Add Animation Point"));
undo_redo->add_do_method(blend_space.ptr(), "add_blend_point", anim, add_point_pos);
undo_redo->add_undo_method(blend_space.ptr(), "remove_blend_point", blend_space->get_blend_point_count());
@@ -430,6 +441,11 @@ void AnimationNodeBlendSpace2DEditor::_tool_switch(int p_tool) {
}
void AnimationNodeBlendSpace2DEditor::_blend_space_draw() {
+ AnimationTree *tree = AnimationTreeEditor::get_singleton()->get_animation_tree();
+ if (!tree) {
+ return;
+ }
+
Color linecolor = get_theme_color(SNAME("font_color"), SNAME("Label"));
Color linecolor_soft = linecolor;
linecolor_soft.a *= 0.5;
@@ -588,7 +604,7 @@ void AnimationNodeBlendSpace2DEditor::_blend_space_draw() {
color.a *= 0.5;
}
- Vector2 blend_pos = AnimationTreeEditor::get_singleton()->get_tree()->get(get_blend_position_path());
+ Vector2 blend_pos = tree->get(get_blend_position_path());
Vector2 point = blend_pos;
point = (point - blend_space->get_min_space()) / (blend_space->get_max_space() - blend_space->get_min_space());
@@ -660,6 +676,7 @@ void AnimationNodeBlendSpace2DEditor::_config_changed(double) {
}
updating = true;
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
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());
@@ -685,6 +702,7 @@ void AnimationNodeBlendSpace2DEditor::_labels_changed(String) {
}
updating = true;
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Change BlendSpace2D Labels"), UndoRedo::MERGE_ENDS);
undo_redo->add_do_method(blend_space.ptr(), "set_x_label", label_x->get_text());
undo_redo->add_undo_method(blend_space.ptr(), "set_x_label", blend_space->get_x_label());
@@ -697,6 +715,7 @@ void AnimationNodeBlendSpace2DEditor::_labels_changed(String) {
}
void AnimationNodeBlendSpace2DEditor::_erase_selected() {
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
if (selected_point != -1) {
updating = true;
undo_redo->create_action(TTR("Remove BlendSpace2D Point"));
@@ -759,6 +778,7 @@ void AnimationNodeBlendSpace2DEditor::_edit_point_pos(double) {
return;
}
updating = true;
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Move Node Point"));
undo_redo->add_do_method(blend_space.ptr(), "set_blend_point_position", selected_point, Vector2(edit_x->get_value(), edit_y->get_value()));
undo_redo->add_undo_method(blend_space.ptr(), "set_blend_point_position", selected_point, blend_space->get_blend_point_position(selected_point));
@@ -794,14 +814,19 @@ void AnimationNodeBlendSpace2DEditor::_notification(int p_what) {
} break;
case NOTIFICATION_PROCESS: {
+ AnimationTree *tree = AnimationTreeEditor::get_singleton()->get_animation_tree();
+ if (!tree) {
+ return;
+ }
+
String error;
- if (!AnimationTreeEditor::get_singleton()->get_tree()) {
+ if (!tree) {
error = TTR("BlendSpace2D does not belong to an AnimationTree node.");
- } else if (!AnimationTreeEditor::get_singleton()->get_tree()->is_active()) {
+ } else if (!tree->is_active()) {
error = TTR("AnimationTree is inactive.\nActivate to enable playback, check node warnings if activation fails.");
- } else if (AnimationTreeEditor::get_singleton()->get_tree()->is_state_invalid()) {
- error = AnimationTreeEditor::get_singleton()->get_tree()->get_invalid_state_reason();
+ } else if (tree->is_state_invalid()) {
+ error = tree->get_invalid_state_reason();
} else if (blend_space->get_triangle_count() == 0) {
error = TTR("No triangles exist, so no blending can take place.");
}
@@ -835,6 +860,7 @@ void AnimationNodeBlendSpace2DEditor::_removed_from_graph() {
}
void AnimationNodeBlendSpace2DEditor::_auto_triangles_toggled() {
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Toggle Auto Triangles"));
undo_redo->add_do_method(blend_space.ptr(), "set_auto_triangles", auto_triangles->is_pressed());
undo_redo->add_undo_method(blend_space.ptr(), "set_auto_triangles", blend_space->get_auto_triangles());
@@ -1058,8 +1084,6 @@ AnimationNodeBlendSpace2DEditor::AnimationNodeBlendSpace2DEditor() {
error_panel->add_child(error_label);
error_label->set_text("eh");
- undo_redo = EditorNode::get_undo_redo();
-
set_custom_minimum_size(Size2(0, 300 * EDSCALE));
menu = memnew(PopupMenu);
@@ -1076,7 +1100,6 @@ AnimationNodeBlendSpace2DEditor::AnimationNodeBlendSpace2DEditor() {
open_file->set_title(TTR("Open Animation Node"));
open_file->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE);
open_file->connect("file_selected", callable_mp(this, &AnimationNodeBlendSpace2DEditor::_file_opened));
- undo_redo = EditorNode::get_undo_redo();
selected_point = -1;
selected_triangle = -1;
diff --git a/editor/plugins/animation_blend_space_2d_editor.h b/editor/plugins/animation_blend_space_2d_editor.h
index 1f015a1804..60873e5473 100644
--- a/editor/plugins/animation_blend_space_2d_editor.h
+++ b/editor/plugins/animation_blend_space_2d_editor.h
@@ -40,7 +40,9 @@
#include "scene/gui/separator.h"
#include "scene/gui/tree.h"
-class EditorUndoRedoManager;
+class CheckBox;
+class OptionButton;
+class PanelContainer;
class AnimationNodeBlendSpace2DEditor : public AnimationTreeNodeEditorPlugin {
GDCLASS(AnimationNodeBlendSpace2DEditor, AnimationTreeNodeEditorPlugin);
@@ -85,8 +87,6 @@ class AnimationNodeBlendSpace2DEditor : public AnimationTreeNodeEditorPlugin {
bool updating;
- Ref<EditorUndoRedoManager> undo_redo;
-
static AnimationNodeBlendSpace2DEditor *singleton;
void _blend_space_gui_input(const Ref<InputEvent> &p_event);
diff --git a/editor/plugins/animation_blend_tree_editor_plugin.cpp b/editor/plugins/animation_blend_tree_editor_plugin.cpp
index 6d00e77a4b..509caa78ef 100644
--- a/editor/plugins/animation_blend_tree_editor_plugin.cpp
+++ b/editor/plugins/animation_blend_tree_editor_plugin.cpp
@@ -41,9 +41,11 @@
#include "editor/editor_settings.h"
#include "editor/editor_undo_redo_manager.h"
#include "scene/animation/animation_player.h"
+#include "scene/gui/check_box.h"
#include "scene/gui/menu_button.h"
#include "scene/gui/panel.h"
#include "scene/gui/progress_bar.h"
+#include "scene/gui/separator.h"
#include "scene/gui/view_panner.h"
#include "scene/main/window.h"
@@ -96,8 +98,12 @@ Size2 AnimationNodeBlendTreeEditor::get_minimum_size() const {
}
void AnimationNodeBlendTreeEditor::_property_changed(const StringName &p_property, const Variant &p_value, const String &p_field, bool p_changing) {
- AnimationTree *tree = AnimationTreeEditor::get_singleton()->get_tree();
+ AnimationTree *tree = AnimationTreeEditor::get_singleton()->get_animation_tree();
+ if (!tree) {
+ return;
+ }
updating = true;
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Parameter Changed:") + " " + String(p_property), UndoRedo::MERGE_ENDS);
undo_redo->add_do_property(tree, p_property, p_value);
undo_redo->add_undo_property(tree, p_property, tree->get(p_property));
@@ -112,6 +118,11 @@ void AnimationNodeBlendTreeEditor::update_graph() {
return;
}
+ AnimationTree *tree = AnimationTreeEditor::get_singleton()->get_animation_tree();
+ if (!tree) {
+ return;
+ }
+
visible_properties.clear();
graph->set_scroll_ofs(blend_tree->get_graph_offset() * EDSCALE);
@@ -174,10 +185,10 @@ void AnimationNodeBlendTreeEditor::update_graph() {
continue;
}
String base_path = AnimationTreeEditor::get_singleton()->get_base_path() + String(E) + "/" + F.name;
- EditorProperty *prop = EditorInspector::instantiate_property_editor(AnimationTreeEditor::get_singleton()->get_tree(), F.type, base_path, F.hint, F.hint_string, F.usage);
+ EditorProperty *prop = EditorInspector::instantiate_property_editor(tree, F.type, base_path, F.hint, F.hint_string, F.usage);
if (prop) {
prop->set_read_only(read_only);
- prop->set_object_and_property(AnimationTreeEditor::get_singleton()->get_tree(), base_path);
+ prop->set_object_and_property(tree, base_path);
prop->update_property();
prop->set_name_split_ratio(0);
prop->connect("property_changed", callable_mp(this, &AnimationNodeBlendTreeEditor::_property_changed));
@@ -225,9 +236,8 @@ void AnimationNodeBlendTreeEditor::update_graph() {
ProgressBar *pb = memnew(ProgressBar);
- AnimationTree *player = AnimationTreeEditor::get_singleton()->get_tree();
- if (player->has_node(player->get_animation_player())) {
- AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(player->get_node(player->get_animation_player()));
+ if (tree->has_node(tree->get_animation_player())) {
+ AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(tree->get_node(tree->get_animation_player()));
if (ap) {
List<StringName> anims;
ap->get_animation_list(&anims);
@@ -353,6 +363,7 @@ void AnimationNodeBlendTreeEditor::_add_node(int p_idx) {
name = base_name + " " + itos(base);
}
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Add Node to BlendTree"));
undo_redo->add_do_method(blend_tree.ptr(), "add_node", name, anode, instance_pos / EDSCALE);
undo_redo->add_undo_method(blend_tree.ptr(), "remove_node", name);
@@ -372,11 +383,11 @@ void AnimationNodeBlendTreeEditor::_add_node(int p_idx) {
undo_redo->commit_action();
}
-void AnimationNodeBlendTreeEditor::_popup(bool p_has_input_ports, const Vector2 &p_popup_position, const Vector2 &p_node_position) {
+void AnimationNodeBlendTreeEditor::_popup(bool p_has_input_ports, const Vector2 &p_node_position) {
_update_options_menu(p_has_input_ports);
use_position_from_popup_menu = true;
position_from_popup_menu = p_node_position;
- add_node->get_popup()->set_position(p_popup_position);
+ add_node->get_popup()->set_position(graph->get_screen_position() + graph->get_local_mouse_position());
add_node->get_popup()->reset_size();
add_node->get_popup()->popup();
}
@@ -386,7 +397,7 @@ void AnimationNodeBlendTreeEditor::_popup_request(const Vector2 &p_position) {
return;
}
- _popup(false, graph->get_screen_position() + graph->get_local_mouse_position(), p_position);
+ _popup(false, p_position);
}
void AnimationNodeBlendTreeEditor::_connection_to_empty(const String &p_from, int p_from_slot, const Vector2 &p_release_position) {
@@ -397,7 +408,7 @@ void AnimationNodeBlendTreeEditor::_connection_to_empty(const String &p_from, in
Ref<AnimationNode> node = blend_tree->get_node(p_from);
if (node.is_valid()) {
from_node = p_from;
- _popup(true, p_release_position, graph->get_global_mouse_position());
+ _popup(true, p_release_position);
}
}
@@ -410,12 +421,13 @@ void AnimationNodeBlendTreeEditor::_connection_from_empty(const String &p_to, in
if (node.is_valid()) {
to_node = p_to;
to_slot = p_to_slot;
- _popup(false, p_release_position, graph->get_global_mouse_position());
+ _popup(false, p_release_position);
}
}
void AnimationNodeBlendTreeEditor::_node_dragged(const Vector2 &p_from, const Vector2 &p_to, const StringName &p_which) {
updating = true;
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Node Moved"));
undo_redo->add_do_method(blend_tree.ptr(), "set_node_position", p_which, p_to / EDSCALE);
undo_redo->add_undo_method(blend_tree.ptr(), "set_node_position", p_which, p_from / EDSCALE);
@@ -437,6 +449,7 @@ void AnimationNodeBlendTreeEditor::_connection_request(const String &p_from, int
return;
}
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Nodes Connected"));
undo_redo->add_do_method(blend_tree.ptr(), "connect_node", p_to, p_to_index, p_from);
undo_redo->add_undo_method(blend_tree.ptr(), "disconnect_node", p_to, p_to_index);
@@ -453,6 +466,7 @@ void AnimationNodeBlendTreeEditor::_disconnection_request(const String &p_from,
graph->disconnect_node(p_from, p_from_index, p_to, p_to_index);
updating = true;
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Nodes Disconnected"));
undo_redo->add_do_method(blend_tree.ptr(), "disconnect_node", p_to, p_to_index);
undo_redo->add_undo_method(blend_tree.ptr(), "connect_node", p_to, p_to_index, p_from);
@@ -468,6 +482,7 @@ void AnimationNodeBlendTreeEditor::_anim_selected(int p_index, Array p_options,
Ref<AnimationNodeAnimation> anim = blend_tree->get_node(p_node);
ERR_FAIL_COND(!anim.is_valid());
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Set Animation"));
undo_redo->add_do_method(anim.ptr(), "set_animation", option);
undo_redo->add_undo_method(anim.ptr(), "set_animation", anim->get_animation());
@@ -481,6 +496,7 @@ void AnimationNodeBlendTreeEditor::_delete_request(const String &p_which) {
return;
}
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Delete Node"));
undo_redo->add_do_method(blend_tree.ptr(), "remove_node", p_which);
undo_redo->add_undo_method(blend_tree.ptr(), "add_node", p_which, blend_tree->get_node(p_which), blend_tree.ptr()->get_node_position(p_which));
@@ -525,6 +541,7 @@ void AnimationNodeBlendTreeEditor::_delete_nodes_request(const TypedArray<String
return;
}
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Delete Node(s)"));
for (const StringName &F : to_erase) {
@@ -558,6 +575,7 @@ void AnimationNodeBlendTreeEditor::_open_in_editor(const String &p_which) {
void AnimationNodeBlendTreeEditor::_filter_toggled() {
updating = true;
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Toggle Filter On/Off"));
undo_redo->add_do_method(_filter_edit.ptr(), "set_filter_enabled", filter_enabled->is_pressed());
undo_redo->add_undo_method(_filter_edit.ptr(), "set_filter_enabled", _filter_edit->is_filter_enabled());
@@ -575,6 +593,7 @@ void AnimationNodeBlendTreeEditor::_filter_edited() {
bool filtered = edited->is_checked(0);
updating = true;
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Change Filter"));
undo_redo->add_do_method(_filter_edit.ptr(), "set_filter_path", edited_path, filtered);
undo_redo->add_undo_method(_filter_edit.ptr(), "set_filter_path", edited_path, _filter_edit->is_path_filtered(edited_path));
@@ -589,14 +608,19 @@ bool AnimationNodeBlendTreeEditor::_update_filters(const Ref<AnimationNode> &ano
return false;
}
- NodePath player_path = AnimationTreeEditor::get_singleton()->get_tree()->get_animation_player();
+ AnimationTree *tree = AnimationTreeEditor::get_singleton()->get_animation_tree();
+ if (!tree) {
+ return false;
+ }
- if (!AnimationTreeEditor::get_singleton()->get_tree()->has_node(player_path)) {
+ NodePath player_path = tree->get_animation_player();
+
+ if (!tree->has_node(player_path)) {
EditorNode::get_singleton()->show_warning(TTR("No animation player set, so unable to retrieve track names."));
return false;
}
- AnimationPlayer *player = Object::cast_to<AnimationPlayer>(AnimationTreeEditor::get_singleton()->get_tree()->get_node(player_path));
+ AnimationPlayer *player = Object::cast_to<AnimationPlayer>(tree->get_node(player_path));
if (!player) {
EditorNode::get_singleton()->show_warning(TTR("Player path set is invalid, so unable to retrieve track names."));
return false;
@@ -827,12 +851,17 @@ void AnimationNodeBlendTreeEditor::_notification(int p_what) {
} break;
case NOTIFICATION_PROCESS: {
+ AnimationTree *tree = AnimationTreeEditor::get_singleton()->get_animation_tree();
+ if (!tree) {
+ return; // Node has been changed.
+ }
+
String error;
- if (!AnimationTreeEditor::get_singleton()->get_tree()->is_active()) {
+ if (!tree->is_active()) {
error = TTR("AnimationTree is inactive.\nActivate to enable playback, check node warnings if activation fails.");
- } else if (AnimationTreeEditor::get_singleton()->get_tree()->is_state_invalid()) {
- error = AnimationTreeEditor::get_singleton()->get_tree()->get_invalid_state_reason();
+ } else if (tree->is_state_invalid()) {
+ error = tree->get_invalid_state_reason();
}
if (error != error_label->get_text()) {
@@ -849,16 +878,15 @@ void AnimationNodeBlendTreeEditor::_notification(int p_what) {
for (const AnimationNodeBlendTree::NodeConnection &E : conns) {
float activity = 0;
StringName path = AnimationTreeEditor::get_singleton()->get_base_path() + E.input_node;
- if (AnimationTreeEditor::get_singleton()->get_tree() && !AnimationTreeEditor::get_singleton()->get_tree()->is_state_invalid()) {
- activity = AnimationTreeEditor::get_singleton()->get_tree()->get_connection_activity(path, E.input_index);
+ if (!tree->is_state_invalid()) {
+ activity = tree->get_connection_activity(path, E.input_index);
}
graph->set_connection_activity(E.output_node, 0, E.input_node, E.input_index, activity);
}
- AnimationTree *graph_player = AnimationTreeEditor::get_singleton()->get_tree();
AnimationPlayer *player = nullptr;
- if (graph_player->has_node(graph_player->get_animation_player())) {
- player = Object::cast_to<AnimationPlayer>(graph_player->get_node(graph_player->get_animation_player()));
+ if (tree->has_node(tree->get_animation_player())) {
+ player = Object::cast_to<AnimationPlayer>(tree->get_node(tree->get_animation_player()));
}
if (player) {
@@ -871,7 +899,7 @@ void AnimationNodeBlendTreeEditor::_notification(int p_what) {
E.value->set_max(anim->get_length());
//StringName path = AnimationTreeEditor::get_singleton()->get_base_path() + E.input_node;
StringName time_path = AnimationTreeEditor::get_singleton()->get_base_path() + String(E.key) + "/time";
- E.value->set_value(AnimationTreeEditor::get_singleton()->get_tree()->get(time_path));
+ E.value->set_value(tree->get(time_path));
}
}
}
@@ -925,6 +953,11 @@ void AnimationNodeBlendTreeEditor::_node_renamed(const String &p_text, Ref<Anima
return;
}
+ AnimationTree *tree = AnimationTreeEditor::get_singleton()->get_animation_tree();
+ if (!tree) {
+ return;
+ }
+
String prev_name = blend_tree->get_node_name(p_node);
ERR_FAIL_COND(prev_name.is_empty());
GraphNode *gn = Object::cast_to<GraphNode>(graph->get_node(prev_name));
@@ -949,11 +982,12 @@ void AnimationNodeBlendTreeEditor::_node_renamed(const String &p_text, Ref<Anima
String base_path = AnimationTreeEditor::get_singleton()->get_base_path();
updating = true;
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Node Renamed"));
undo_redo->add_do_method(blend_tree.ptr(), "rename_node", prev_name, name);
undo_redo->add_undo_method(blend_tree.ptr(), "rename_node", name, prev_name);
- undo_redo->add_do_method(AnimationTreeEditor::get_singleton()->get_tree(), "rename_parameter", base_path + prev_name, base_path + name);
- undo_redo->add_undo_method(AnimationTreeEditor::get_singleton()->get_tree(), "rename_parameter", base_path + name, base_path + prev_name);
+ undo_redo->add_do_method(tree, "rename_parameter", base_path + prev_name, base_path + name);
+ undo_redo->add_undo_method(tree, "rename_parameter", base_path + name, base_path + prev_name);
undo_redo->add_do_method(this, "update_graph");
undo_redo->add_undo_method(this, "update_graph");
undo_redo->commit_action();
@@ -1117,5 +1151,4 @@ AnimationNodeBlendTreeEditor::AnimationNodeBlendTreeEditor() {
open_file->set_title(TTR("Open Animation Node"));
open_file->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE);
open_file->connect("file_selected", callable_mp(this, &AnimationNodeBlendTreeEditor::_file_opened));
- undo_redo = EditorNode::get_undo_redo();
}
diff --git a/editor/plugins/animation_blend_tree_editor_plugin.h b/editor/plugins/animation_blend_tree_editor_plugin.h
index b55fc3b617..4b55aa9b3f 100644
--- a/editor/plugins/animation_blend_tree_editor_plugin.h
+++ b/editor/plugins/animation_blend_tree_editor_plugin.h
@@ -31,17 +31,21 @@
#ifndef ANIMATION_BLEND_TREE_EDITOR_PLUGIN_H
#define ANIMATION_BLEND_TREE_EDITOR_PLUGIN_H
-#include "editor/editor_plugin.h"
#include "editor/plugins/animation_tree_editor_plugin.h"
#include "scene/animation/animation_blend_tree.h"
#include "scene/gui/button.h"
#include "scene/gui/graph_edit.h"
+#include "scene/gui/panel_container.h"
#include "scene/gui/popup.h"
#include "scene/gui/tree.h"
+class AcceptDialog;
+class CheckBox;
class ProgressBar;
class EditorFileDialog;
-class EditorUndoRedoManager;
+class EditorProperty;
+class MenuButton;
+class PanelContainer;
class AnimationNodeBlendTreeEditor : public AnimationTreeNodeEditorPlugin {
GDCLASS(AnimationNodeBlendTreeEditor, AnimationTreeNodeEditorPlugin);
@@ -58,8 +62,6 @@ class AnimationNodeBlendTreeEditor : public AnimationTreeNodeEditorPlugin {
PanelContainer *error_panel = nullptr;
Label *error_label = nullptr;
- Ref<EditorUndoRedoManager> undo_redo;
-
AcceptDialog *filter_dialog = nullptr;
Tree *filters = nullptr;
CheckBox *filter_enabled = nullptr;
@@ -115,7 +117,7 @@ class AnimationNodeBlendTreeEditor : public AnimationTreeNodeEditorPlugin {
void _filter_toggled();
Ref<AnimationNode> _filter_edit;
- void _popup(bool p_has_input_ports, const Vector2 &p_popup_position, const Vector2 &p_node_position);
+ void _popup(bool p_has_input_ports, const Vector2 &p_node_position);
void _popup_request(const Vector2 &p_position);
void _connection_to_empty(const String &p_from, int p_from_slot, const Vector2 &p_release_position);
void _connection_from_empty(const String &p_to, int p_to_slot, const Vector2 &p_release_position);
diff --git a/editor/plugins/animation_library_editor.cpp b/editor/plugins/animation_library_editor.cpp
index 2d20c0cca7..10b5271fc8 100644
--- a/editor/plugins/animation_library_editor.cpp
+++ b/editor/plugins/animation_library_editor.cpp
@@ -32,6 +32,7 @@
#include "editor/editor_file_dialog.h"
#include "editor/editor_node.h"
#include "editor/editor_scale.h"
+#include "editor/editor_settings.h"
#include "editor/editor_undo_redo_manager.h"
void AnimationLibraryEditor::set_animation_player(Object *p_player) {
@@ -93,7 +94,7 @@ void AnimationLibraryEditor::_add_library_validate(const String &p_name) {
void AnimationLibraryEditor::_add_library_confirm() {
if (adding_animation) {
String anim_name = add_library_name->get_text();
- Ref<EditorUndoRedoManager> undo_redo = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_singleton()->get_undo_redo();
Ref<AnimationLibrary> al = player->call("get_animation_library", adding_animation_to_library);
ERR_FAIL_COND(!al.is_valid());
@@ -110,7 +111,7 @@ void AnimationLibraryEditor::_add_library_confirm() {
} else {
String lib_name = add_library_name->get_text();
- Ref<EditorUndoRedoManager> undo_redo = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_singleton()->get_undo_redo();
Ref<AnimationLibrary> al;
al.instantiate();
@@ -210,7 +211,7 @@ void AnimationLibraryEditor::_file_popup_selected(int p_id) {
ald->add_animation(animation_name, animation);
}
- Ref<EditorUndoRedoManager> undo_redo = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_singleton()->get_undo_redo();
undo_redo->create_action(vformat(TTR("Make Animation Library Unique: %s"), lib_name));
undo_redo->add_do_method(player, "remove_animation_library", lib_name);
undo_redo->add_do_method(player, "add_animation_library", lib_name, ald);
@@ -279,7 +280,7 @@ void AnimationLibraryEditor::_file_popup_selected(int p_id) {
Ref<Animation> animd = anim->duplicate();
- Ref<EditorUndoRedoManager> undo_redo = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_singleton()->get_undo_redo();
undo_redo->create_action(vformat(TTR("Make Animation Unique: %s"), anim_name));
undo_redo->add_do_method(al.ptr(), "remove_animation", anim_name);
undo_redo->add_do_method(al.ptr(), "add_animation", anim_name, animd);
@@ -327,7 +328,7 @@ void AnimationLibraryEditor::_load_file(String p_path) {
name = p_path.get_file().get_basename() + " " + itos(attempt);
}
- Ref<EditorUndoRedoManager> undo_redo = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_singleton()->get_undo_redo();
undo_redo->create_action(vformat(TTR("Add Animation Library: %s"), name));
undo_redo->add_do_method(player, "add_animation_library", name, al);
@@ -365,7 +366,7 @@ void AnimationLibraryEditor::_load_file(String p_path) {
name = p_path.get_file().get_basename() + " " + itos(attempt);
}
- Ref<EditorUndoRedoManager> undo_redo = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_singleton()->get_undo_redo();
undo_redo->create_action(vformat(TTR("Load Animation into Library: %s"), name));
undo_redo->add_do_method(al.ptr(), "add_animation", name, anim);
@@ -381,7 +382,7 @@ void AnimationLibraryEditor::_load_file(String p_path) {
EditorNode::get_singleton()->save_resource_in_path(al, p_path);
if (al->get_path() != prev_path) { // Save successful.
- Ref<EditorUndoRedoManager> undo_redo = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_singleton()->get_undo_redo();
undo_redo->create_action(vformat(TTR("Save Animation library to File: %s"), file_dialog_library));
undo_redo->add_do_method(al.ptr(), "set_path", al->get_path());
@@ -402,7 +403,7 @@ void AnimationLibraryEditor::_load_file(String p_path) {
String prev_path = anim->get_path();
EditorNode::get_singleton()->save_resource_in_path(anim, p_path);
if (anim->get_path() != prev_path) { // Save successful.
- Ref<EditorUndoRedoManager> undo_redo = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_singleton()->get_undo_redo();
undo_redo->create_action(vformat(TTR("Save Animation to File: %s"), file_dialog_animation));
undo_redo->add_do_method(anim.ptr(), "set_path", anim->get_path());
@@ -420,7 +421,7 @@ void AnimationLibraryEditor::_item_renamed() {
String text = ti->get_text(0);
String old_text = ti->get_metadata(0);
bool restore_text = false;
- Ref<EditorUndoRedoManager> undo_redo = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_singleton()->get_undo_redo();
if (String(text).contains("/") || String(text).contains(":") || String(text).contains(",") || String(text).contains("[")) {
restore_text = true;
@@ -534,7 +535,7 @@ void AnimationLibraryEditor::_button_pressed(TreeItem *p_item, int p_column, int
name = base_name + " (" + itos(attempt) + ")";
}
- Ref<EditorUndoRedoManager> undo_redo = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_singleton()->get_undo_redo();
undo_redo->create_action(vformat(TTR("Add Animation to Library: %s"), name));
undo_redo->add_do_method(al.ptr(), "add_animation", name, anim);
@@ -560,7 +561,7 @@ void AnimationLibraryEditor::_button_pressed(TreeItem *p_item, int p_column, int
file_dialog_library = lib_name;
} break;
case LIB_BUTTON_DELETE: {
- Ref<EditorUndoRedoManager> undo_redo = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_singleton()->get_undo_redo();
undo_redo->create_action(vformat(TTR("Remove Animation Library: %s"), lib_name));
undo_redo->add_do_method(player, "remove_animation_library", lib_name);
undo_redo->add_undo_method(player, "add_animation_library", lib_name, al);
@@ -601,7 +602,7 @@ void AnimationLibraryEditor::_button_pressed(TreeItem *p_item, int p_column, int
} break;
case ANIM_BUTTON_DELETE: {
- Ref<EditorUndoRedoManager> undo_redo = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_singleton()->get_undo_redo();
undo_redo->create_action(vformat(TTR("Remove Animation from Library: %s"), anim_name));
undo_redo->add_do_method(al.ptr(), "remove_animation", anim_name);
undo_redo->add_undo_method(al.ptr(), "add_animation", anim_name, anim);
diff --git a/editor/plugins/animation_player_editor_plugin.cpp b/editor/plugins/animation_player_editor_plugin.cpp
index 1ebe81c4b0..344a800241 100644
--- a/editor/plugins/animation_player_editor_plugin.cpp
+++ b/editor/plugins/animation_player_editor_plugin.cpp
@@ -40,9 +40,11 @@
#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_undo_redo_manager.h"
+#include "editor/inspector_dock.h"
#include "editor/plugins/canvas_item_editor_plugin.h" // For onion skinning.
#include "editor/plugins/node_3d_editor_plugin.h" // For onion skinning.
#include "editor/scene_tree_dock.h"
+#include "scene/gui/separator.h"
#include "scene/main/window.h"
#include "scene/resources/animation.h"
#include "scene/scene_string_names.h"
@@ -85,13 +87,13 @@ void AnimationPlayerEditor::_notification(int p_what) {
}
frame->set_value(player->get_current_animation_position());
track_editor->set_anim_pos(player->get_current_animation_position());
-
} else if (!player->is_valid()) {
// Reset timeline when the player has been stopped externally
frame->set_value(0);
} else if (last_active) {
// Need the last frame after it stopped.
frame->set_value(player->get_current_animation_position());
+ track_editor->set_anim_pos(player->get_current_animation_position());
}
last_active = player->is_playing();
@@ -197,6 +199,7 @@ void AnimationPlayerEditor::_play_pressed() {
if (current == player->get_assigned_animation()) {
player->stop(); //so it won't blend with itself
}
+ ERR_FAIL_COND_EDMSG(!_validate_tracks(player->get_animation(current)), "Animation tracks may have any invalid key, abort playing.");
player->play(current);
}
@@ -209,13 +212,12 @@ void AnimationPlayerEditor::_play_from_pressed() {
if (!current.is_empty()) {
float time = player->get_current_animation_position();
-
if (current == player->get_assigned_animation() && player->is_playing()) {
player->stop(); //so it won't blend with itself
}
-
- player->play(current);
+ ERR_FAIL_COND_EDMSG(!_validate_tracks(player->get_animation(current)), "Animation tracks may have any invalid key, abort playing.");
player->seek(time);
+ player->play(current);
}
//unstop
@@ -235,6 +237,7 @@ void AnimationPlayerEditor::_play_bw_pressed() {
if (current == player->get_assigned_animation()) {
player->stop(); //so it won't blend with itself
}
+ ERR_FAIL_COND_EDMSG(!_validate_tracks(player->get_animation(current)), "Animation tracks may have any invalid key, abort playing.");
player->play(current, -1, -1, true);
}
@@ -250,9 +253,9 @@ void AnimationPlayerEditor::_play_bw_from_pressed() {
if (current == player->get_assigned_animation()) {
player->stop(); //so it won't blend with itself
}
-
- player->play(current, -1, -1, true);
+ ERR_FAIL_COND_EDMSG(!_validate_tracks(player->get_animation(current)), "Animation tracks may have any invalid key, abort playing.");
player->seek(time);
+ player->play(current, -1, -1, true);
}
//unstop
@@ -420,7 +423,7 @@ void AnimationPlayerEditor::_select_anim_by_name(const String &p_anim) {
_animation_selected(idx);
}
-double AnimationPlayerEditor::_get_editor_step() const {
+float AnimationPlayerEditor::_get_editor_step() const {
// Returns the effective snapping value depending on snapping modifiers, or 0 if snapping is disabled.
if (track_editor->is_snap_enabled()) {
const String current = player->get_assigned_animation();
@@ -431,7 +434,7 @@ double AnimationPlayerEditor::_get_editor_step() const {
return Input::get_singleton()->is_key_pressed(Key::SHIFT) ? anim->get_step() * 0.25 : anim->get_step();
}
- return 0.0;
+ return 0.0f;
}
void AnimationPlayerEditor::_animation_name_edited() {
@@ -950,7 +953,7 @@ void AnimationPlayerEditor::_update_animation_list_icons() {
}
void AnimationPlayerEditor::_update_name_dialog_library_dropdown() {
- StringName current_library_name = StringName();
+ StringName current_library_name;
if (animation->has_selectable_items()) {
String current_animation_name = animation->get_item_text(animation->get_selected());
Ref<Animation> current_animation = player->get_animation(current_animation_name);
@@ -1562,6 +1565,53 @@ void AnimationPlayerEditor::_pin_pressed() {
SceneTreeDock::get_singleton()->get_tree_editor()->update_tree();
}
+bool AnimationPlayerEditor::_validate_tracks(const Ref<Animation> p_anim) {
+ bool is_valid = true;
+ if (!p_anim.is_valid()) {
+ return true; // There is a problem outside of the animation track.
+ }
+ int len = p_anim->get_track_count();
+ for (int i = 0; i < len; i++) {
+ Animation::TrackType ttype = p_anim->track_get_type(i);
+ if (ttype == Animation::TYPE_ROTATION_3D) {
+ int key_len = p_anim->track_get_key_count(i);
+ for (int j = 0; j < key_len; j++) {
+ Quaternion q;
+ p_anim->rotation_track_get_key(i, j, &q);
+ ERR_BREAK_EDMSG(!q.is_normalized(), "AnimationPlayer: '" + player->get_name() + "', Animation: '" + player->get_current_animation() + "', rotation track: '" + p_anim->track_get_path(i) + "' contains unnormalized Quaternion key.");
+ }
+ } else if (ttype == Animation::TYPE_VALUE) {
+ int key_len = p_anim->track_get_key_count(i);
+ if (key_len == 0) {
+ continue;
+ }
+ switch (p_anim->track_get_key_value(i, 0).get_type()) {
+ case Variant::QUATERNION: {
+ for (int j = 0; j < key_len; j++) {
+ Quaternion q = Quaternion(p_anim->track_get_key_value(i, j));
+ if (!q.is_normalized()) {
+ is_valid = false;
+ ERR_BREAK_EDMSG(true, "AnimationPlayer: '" + player->get_name() + "', Animation: '" + player->get_current_animation() + "', value track: '" + p_anim->track_get_path(i) + "' contains unnormalized Quaternion key.");
+ }
+ }
+ } break;
+ case Variant::TRANSFORM3D: {
+ for (int j = 0; j < key_len; j++) {
+ Transform3D t = Transform3D(p_anim->track_get_key_value(i, j));
+ if (!t.basis.orthonormalized().is_rotation()) {
+ is_valid = false;
+ ERR_BREAK_EDMSG(true, "AnimationPlayer: '" + player->get_name() + "', Animation: '" + player->get_current_animation() + "', value track: '" + p_anim->track_get_path(i) + "' contains corrupted basis (some axes are too close other axis or scaled by zero) Transform3D key.");
+ }
+ }
+ } break;
+ default: {
+ } break;
+ }
+ }
+ }
+ return is_valid;
+}
+
void AnimationPlayerEditor::_bind_methods() {
ClassDB::bind_method(D_METHOD("_animation_new"), &AnimationPlayerEditor::_animation_new);
ClassDB::bind_method(D_METHOD("_animation_rename"), &AnimationPlayerEditor::_animation_rename);
@@ -1872,10 +1922,12 @@ void AnimationPlayerEditorPlugin::_notification(int p_what) {
}
void AnimationPlayerEditorPlugin::_property_keyed(const String &p_keyed, const Variant &p_value, bool p_advance) {
- if (!anim_editor->get_track_editor()->has_keying()) {
+ AnimationTrackEditor *te = anim_editor->get_track_editor();
+ if (!te || !te->has_keying()) {
return;
}
- anim_editor->get_track_editor()->insert_value_key(p_keyed, p_value, p_advance);
+ te->_clear_selection();
+ te->insert_value_key(p_keyed, p_value, p_advance);
}
void AnimationPlayerEditorPlugin::_transform_key_request(Object *sp, const String &p_sub, const Transform3D &p_key) {
@@ -1921,3 +1973,26 @@ AnimationPlayerEditorPlugin::AnimationPlayerEditorPlugin() {
AnimationPlayerEditorPlugin::~AnimationPlayerEditorPlugin() {
}
+
+// AnimationTrackKeyEditEditorPlugin
+
+bool EditorInspectorPluginAnimationTrackKeyEdit::can_handle(Object *p_object) {
+ return Object::cast_to<AnimationTrackKeyEdit>(p_object) != nullptr;
+}
+
+void EditorInspectorPluginAnimationTrackKeyEdit::parse_begin(Object *p_object) {
+ AnimationTrackKeyEdit *atk = Object::cast_to<AnimationTrackKeyEdit>(p_object);
+ ERR_FAIL_COND(!atk);
+
+ atk_editor = memnew(AnimationTrackKeyEditEditor(atk->animation, atk->track, atk->key_ofs, atk->use_fps));
+ add_custom_control(atk_editor);
+}
+
+AnimationTrackKeyEditEditorPlugin::AnimationTrackKeyEditEditorPlugin() {
+ atk_plugin = memnew(EditorInspectorPluginAnimationTrackKeyEdit);
+ EditorInspector::add_inspector_plugin(atk_plugin);
+}
+
+bool AnimationTrackKeyEditEditorPlugin::handles(Object *p_object) const {
+ return p_object->is_class("AnimationTrackKeyEdit");
+}
diff --git a/editor/plugins/animation_player_editor_plugin.h b/editor/plugins/animation_player_editor_plugin.h
index 6370b00ea8..8539d450e6 100644
--- a/editor/plugins/animation_player_editor_plugin.h
+++ b/editor/plugins/animation_player_editor_plugin.h
@@ -162,7 +162,7 @@ class AnimationPlayerEditor : public VBoxContainer {
} onion;
void _select_anim_by_name(const String &p_anim);
- double _get_editor_step() const;
+ float _get_editor_step() const;
void _play_pressed();
void _play_from_pressed();
void _play_bw_pressed();
@@ -212,6 +212,8 @@ class AnimationPlayerEditor : public VBoxContainer {
void _start_onion_skinning();
void _stop_onion_skinning();
+ bool _validate_tracks(const Ref<Animation> p_anim);
+
void _pin_pressed();
String _get_current() const;
@@ -270,4 +272,30 @@ public:
~AnimationPlayerEditorPlugin();
};
+// AnimationTrackKeyEditEditorPlugin
+
+class EditorInspectorPluginAnimationTrackKeyEdit : public EditorInspectorPlugin {
+ GDCLASS(EditorInspectorPluginAnimationTrackKeyEdit, EditorInspectorPlugin);
+
+ AnimationTrackKeyEditEditor *atk_editor = nullptr;
+
+public:
+ virtual bool can_handle(Object *p_object) override;
+ virtual void parse_begin(Object *p_object) override;
+};
+
+class AnimationTrackKeyEditEditorPlugin : public EditorPlugin {
+ GDCLASS(AnimationTrackKeyEditEditorPlugin, EditorPlugin);
+
+ EditorInspectorPluginAnimationTrackKeyEdit *atk_plugin = nullptr;
+
+public:
+ bool has_main_screen() const override { return false; }
+ virtual bool handles(Object *p_object) const override;
+
+ virtual String get_name() const override { return "AnimationTrackKeyEdit"; }
+
+ AnimationTrackKeyEditEditorPlugin();
+};
+
#endif // ANIMATION_PLAYER_EDITOR_PLUGIN_H
diff --git a/editor/plugins/animation_state_machine_editor.cpp b/editor/plugins/animation_state_machine_editor.cpp
index c32f9b1775..7b8a5d06f8 100644
--- a/editor/plugins/animation_state_machine_editor.cpp
+++ b/editor/plugins/animation_state_machine_editor.cpp
@@ -43,7 +43,10 @@
#include "scene/animation/animation_blend_tree.h"
#include "scene/animation/animation_player.h"
#include "scene/gui/menu_button.h"
+#include "scene/gui/option_button.h"
#include "scene/gui/panel.h"
+#include "scene/gui/panel_container.h"
+#include "scene/gui/separator.h"
#include "scene/gui/tree.h"
#include "scene/main/viewport.h"
#include "scene/main/window.h"
@@ -76,7 +79,12 @@ void AnimationNodeStateMachineEditor::edit(const Ref<AnimationNode> &p_node) {
}
void AnimationNodeStateMachineEditor::_state_machine_gui_input(const Ref<InputEvent> &p_event) {
- Ref<AnimationNodeStateMachinePlayback> playback = AnimationTreeEditor::get_singleton()->get_tree()->get(AnimationTreeEditor::get_singleton()->get_base_path() + "playback");
+ AnimationTree *tree = AnimationTreeEditor::get_singleton()->get_animation_tree();
+ if (!tree) {
+ return;
+ }
+
+ Ref<AnimationNodeStateMachinePlayback> playback = tree->get(AnimationTreeEditor::get_singleton()->get_base_path() + "playback");
if (playback.is_null()) {
return;
}
@@ -238,6 +246,7 @@ void AnimationNodeStateMachineEditor::_state_machine_gui_input(const Ref<InputEv
Ref<AnimationNode> an = state_machine->get_node(selected_node);
updating = true;
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Move Node"));
for (int i = 0; i < node_rects.size(); i++) {
@@ -420,7 +429,7 @@ void AnimationNodeStateMachineEditor::_state_machine_gui_input(const Ref<InputEv
if (mm.is_valid()) {
state_machine_draw->grab_focus();
- String new_over_node = StringName();
+ String new_over_node;
int new_over_node_what = -1;
if (tool_select->is_pressed()) {
for (int i = node_rects.size() - 1; i >= 0; i--) { // Inverse to draw order.
@@ -534,6 +543,7 @@ void AnimationNodeStateMachineEditor::_group_selected_nodes() {
}
updating = true;
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action("Group");
// Move selected nodes to the new state machine
@@ -648,6 +658,7 @@ void AnimationNodeStateMachineEditor::_ungroup_selected_nodes() {
Vector<TransitionUR> transitions_ur;
updating = true;
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action("Ungroup");
// Move all child nodes to current state machine
@@ -730,6 +741,11 @@ void AnimationNodeStateMachineEditor::_ungroup_selected_nodes() {
}
void AnimationNodeStateMachineEditor::_open_menu(const Vector2 &p_position) {
+ AnimationTree *tree = AnimationTreeEditor::get_singleton()->get_animation_tree();
+ if (!tree) {
+ return;
+ }
+
menu->clear();
animations_menu->clear();
animations_to_add.clear();
@@ -739,10 +755,8 @@ void AnimationNodeStateMachineEditor::_open_menu(const Vector2 &p_position) {
ClassDB::get_inheriters_from_class("AnimationRootNode", &classes);
menu->add_submenu_item(TTR("Add Animation"), "animations");
- AnimationTree *gp = AnimationTreeEditor::get_singleton()->get_tree();
- ERR_FAIL_COND(!gp);
- if (gp && gp->has_node(gp->get_animation_player())) {
- AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(gp->get_node(gp->get_animation_player()));
+ if (tree->has_node(tree->get_animation_player())) {
+ AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(tree->get_node(tree->get_animation_player()));
if (ap) {
List<StringName> names;
ap->get_animation_list(&names);
@@ -921,6 +935,7 @@ void AnimationNodeStateMachineEditor::_stop_connecting() {
void AnimationNodeStateMachineEditor::_delete_selected() {
TreeItem *item = delete_tree->get_next_selected(nullptr);
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
while (item) {
if (!updating) {
updating = true;
@@ -948,6 +963,7 @@ void AnimationNodeStateMachineEditor::_delete_all() {
selected_multi_transition = TransitionLine();
updating = true;
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action("Transition(s) Removed");
_erase_selected(true);
for (int i = 0; i < multi_transitions.size(); i++) {
@@ -1027,6 +1043,7 @@ void AnimationNodeStateMachineEditor::_add_menu_type(int p_index) {
}
updating = true;
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Add Node and Transition"));
undo_redo->add_do_method(state_machine.ptr(), "add_node", name, node, add_node_pos);
undo_redo->add_undo_method(state_machine.ptr(), "remove_node", name);
@@ -1053,6 +1070,7 @@ void AnimationNodeStateMachineEditor::_add_animation_type(int p_index) {
}
updating = true;
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Add Node and Transition"));
undo_redo->add_do_method(state_machine.ptr(), "add_node", name, anim, add_node_pos);
undo_redo->add_undo_method(state_machine.ptr(), "remove_node", name);
@@ -1079,8 +1097,10 @@ void AnimationNodeStateMachineEditor::_add_transition(const bool p_nested_action
Ref<AnimationNodeStateMachineTransition> tr;
tr.instantiate();
- tr->set_switch_mode(AnimationNodeStateMachineTransition::SwitchMode(transition_mode->get_selected()));
+ tr->set_advance_mode(auto_advance->is_pressed() ? AnimationNodeStateMachineTransition::AdvanceMode::ADVANCE_MODE_AUTO : AnimationNodeStateMachineTransition::AdvanceMode::ADVANCE_MODE_ENABLED);
+ tr->set_switch_mode(AnimationNodeStateMachineTransition::SwitchMode(switch_mode->get_selected()));
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
if (!p_nested_action) {
updating = true;
undo_redo->create_action(TTR("Add Transition"));
@@ -1181,7 +1201,12 @@ void AnimationNodeStateMachineEditor::_clip_dst_line_to_rect(const Vector2 &p_fr
}
void AnimationNodeStateMachineEditor::_state_machine_draw() {
- Ref<AnimationNodeStateMachinePlayback> playback = AnimationTreeEditor::get_singleton()->get_tree()->get(AnimationTreeEditor::get_singleton()->get_base_path() + "playback");
+ AnimationTree *tree = AnimationTreeEditor::get_singleton()->get_animation_tree();
+ if (!tree) {
+ return;
+ }
+
+ Ref<AnimationNodeStateMachinePlayback> playback = tree->get(AnimationTreeEditor::get_singleton()->get_base_path() + "playback");
Ref<StyleBoxFlat> style = get_theme_stylebox(SNAME("state_machine_frame"), SNAME("GraphNode"));
Ref<StyleBoxFlat> style_selected = get_theme_stylebox(SNAME("state_machine_selected_frame"), SNAME("GraphNode"));
@@ -1302,7 +1327,7 @@ void AnimationNodeStateMachineEditor::_state_machine_draw() {
}
}
- _connection_draw(from, to, AnimationNodeStateMachineTransition::SwitchMode(transition_mode->get_selected()), true, false, false, false, false);
+ _connection_draw(from, to, AnimationNodeStateMachineTransition::SwitchMode(switch_mode->get_selected()), true, false, false, false, false);
}
Ref<Texture2D> tr_reference_icon = get_theme_icon(SNAME("TransitionImmediateBig"), SNAME("EditorIcons"));
@@ -1325,8 +1350,8 @@ void AnimationNodeStateMachineEditor::_state_machine_draw() {
tl.to = (state_machine->get_node_position(local_to) * EDSCALE) + ofs_to - state_machine->get_graph_offset() * EDSCALE;
Ref<AnimationNodeStateMachineTransition> tr = state_machine->get_transition(i);
- tl.disabled = tr->is_disabled();
- tl.auto_advance = tr->has_auto_advance();
+ tl.disabled = bool(tr->get_advance_mode() == AnimationNodeStateMachineTransition::ADVANCE_MODE_DISABLED);
+ tl.auto_advance = bool(tr->get_advance_mode() == AnimationNodeStateMachineTransition::ADVANCE_MODE_AUTO);
tl.advance_condition_name = tr->get_advance_condition_name();
tl.advance_condition_state = false;
tl.mode = tr->get_switch_mode();
@@ -1369,7 +1394,7 @@ void AnimationNodeStateMachineEditor::_state_machine_draw() {
}
StringName fullpath = AnimationTreeEditor::get_singleton()->get_base_path() + String(tl.advance_condition_name);
- if (tl.advance_condition_name != StringName() && bool(AnimationTreeEditor::get_singleton()->get_tree()->get(fullpath))) {
+ if (tl.advance_condition_name != StringName() && bool(tree->get(fullpath))) {
tl.advance_condition_state = true;
tl.auto_advance = true;
}
@@ -1484,7 +1509,12 @@ void AnimationNodeStateMachineEditor::_state_machine_draw() {
}
void AnimationNodeStateMachineEditor::_state_machine_pos_draw() {
- Ref<AnimationNodeStateMachinePlayback> playback = AnimationTreeEditor::get_singleton()->get_tree()->get(AnimationTreeEditor::get_singleton()->get_base_path() + "playback");
+ AnimationTree *tree = AnimationTreeEditor::get_singleton()->get_animation_tree();
+ if (!tree) {
+ return;
+ }
+
+ Ref<AnimationNodeStateMachinePlayback> playback = tree->get(AnimationTreeEditor::get_singleton()->get_base_path() + "playback");
if (!playback.is_valid() || !playback->is_playing()) {
return;
@@ -1561,10 +1591,12 @@ void AnimationNodeStateMachineEditor::_notification(int p_what) {
tool_create->set_icon(get_theme_icon(SNAME("ToolAddNode"), SNAME("EditorIcons")));
tool_connect->set_icon(get_theme_icon(SNAME("ToolConnect"), SNAME("EditorIcons")));
- transition_mode->clear();
- transition_mode->add_icon_item(get_theme_icon(SNAME("TransitionImmediate"), SNAME("EditorIcons")), TTR("Immediate"));
- transition_mode->add_icon_item(get_theme_icon(SNAME("TransitionSync"), SNAME("EditorIcons")), TTR("Sync"));
- transition_mode->add_icon_item(get_theme_icon(SNAME("TransitionEnd"), SNAME("EditorIcons")), TTR("At End"));
+ switch_mode->clear();
+ switch_mode->add_icon_item(get_theme_icon(SNAME("TransitionImmediate"), SNAME("EditorIcons")), TTR("Immediate"));
+ switch_mode->add_icon_item(get_theme_icon(SNAME("TransitionSync"), SNAME("EditorIcons")), TTR("Sync"));
+ switch_mode->add_icon_item(get_theme_icon(SNAME("TransitionEnd"), SNAME("EditorIcons")), TTR("At End"));
+
+ auto_advance->set_icon(get_theme_icon(SNAME("AutoPlay"), SNAME("EditorIcons")));
tool_erase->set_icon(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")));
tool_group->set_icon(get_theme_icon(SNAME("Group"), SNAME("EditorIcons")));
@@ -1576,17 +1608,22 @@ void AnimationNodeStateMachineEditor::_notification(int p_what) {
} break;
case NOTIFICATION_PROCESS: {
+ AnimationTree *tree = AnimationTreeEditor::get_singleton()->get_animation_tree();
+ if (!tree) {
+ return;
+ }
+
String error;
- Ref<AnimationNodeStateMachinePlayback> playback = AnimationTreeEditor::get_singleton()->get_tree()->get(AnimationTreeEditor::get_singleton()->get_base_path() + "playback");
+ Ref<AnimationNodeStateMachinePlayback> playback = tree->get(AnimationTreeEditor::get_singleton()->get_base_path() + "playback");
if (error_time > 0) {
error = error_text;
error_time -= get_process_delta_time();
- } else if (!AnimationTreeEditor::get_singleton()->get_tree()->is_active()) {
+ } else if (!tree->is_active()) {
error = TTR("AnimationTree is inactive.\nActivate to enable playback, check node warnings if activation fails.");
- } else if (AnimationTreeEditor::get_singleton()->get_tree()->is_state_invalid()) {
- error = AnimationTreeEditor::get_singleton()->get_tree()->get_invalid_state_reason();
+ } else if (tree->is_state_invalid()) {
+ error = tree->get_invalid_state_reason();
/*} else if (state_machine->get_parent().is_valid() && state_machine->get_parent()->is_class("AnimationNodeStateMachine")) {
if (state_machine->get_start_node() == StringName() || state_machine->get_end_node() == StringName()) {
error = TTR("Start and end nodes are needed for a sub-transition.");
@@ -1618,12 +1655,12 @@ void AnimationNodeStateMachineEditor::_notification(int p_what) {
break;
}
- if (transition_lines[i].disabled != state_machine->get_transition(tidx)->is_disabled()) {
+ if (transition_lines[i].disabled != bool(state_machine->get_transition(tidx)->get_advance_mode() == AnimationNodeStateMachineTransition::ADVANCE_MODE_DISABLED)) {
state_machine_draw->queue_redraw();
break;
}
- if (transition_lines[i].auto_advance != state_machine->get_transition(tidx)->has_auto_advance()) {
+ if (transition_lines[i].auto_advance != bool(state_machine->get_transition(tidx)->get_advance_mode() == AnimationNodeStateMachineTransition::ADVANCE_MODE_AUTO)) {
state_machine_draw->queue_redraw();
break;
}
@@ -1638,7 +1675,7 @@ void AnimationNodeStateMachineEditor::_notification(int p_what) {
break;
}
- bool acstate = transition_lines[i].advance_condition_name != StringName() && bool(AnimationTreeEditor::get_singleton()->get_tree()->get(AnimationTreeEditor::get_singleton()->get_base_path() + String(transition_lines[i].advance_condition_name)));
+ bool acstate = transition_lines[i].advance_condition_name != StringName() && bool(tree->get(AnimationTreeEditor::get_singleton()->get_base_path() + String(transition_lines[i].advance_condition_name)));
if (transition_lines[i].advance_condition_state != acstate) {
state_machine_draw->queue_redraw();
@@ -1693,7 +1730,7 @@ void AnimationNodeStateMachineEditor::_notification(int p_what) {
Ref<AnimationNodeStateMachinePlayback> current_node_playback;
while (anodesm.is_valid()) {
- current_node_playback = AnimationTreeEditor::get_singleton()->get_tree()->get(AnimationTreeEditor::get_singleton()->get_base_path() + next + "/playback");
+ current_node_playback = tree->get(AnimationTreeEditor::get_singleton()->get_base_path() + next + "/playback");
next += "/" + current_node_playback->get_current_node();
anodesm = anodesm->get_node(current_node_playback->get_current_node());
}
@@ -1745,6 +1782,7 @@ void AnimationNodeStateMachineEditor::_name_edited(const String &p_text) {
}
updating = true;
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Node Renamed"));
undo_redo->add_do_method(state_machine.ptr(), "rename_node", prev_name, name);
undo_redo->add_undo_method(state_machine.ptr(), "rename_node", name, prev_name);
@@ -1779,6 +1817,7 @@ void AnimationNodeStateMachineEditor::_erase_selected(const bool p_nested_action
if (!p_nested_action) {
updating = true;
}
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Node Removed"));
for (int i = 0; i < node_rects.size(); i++) {
@@ -1847,6 +1886,7 @@ void AnimationNodeStateMachineEditor::_erase_selected(const bool p_nested_action
if (!p_nested_action) {
updating = true;
}
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Transition Removed"));
undo_redo->add_do_method(state_machine.ptr(), "remove_transition", selected_transition_from, selected_transition_to);
undo_redo->add_undo_method(state_machine.ptr(), "add_transition", selected_transition_from, selected_transition_to, tr);
@@ -1867,7 +1907,7 @@ void AnimationNodeStateMachineEditor::_erase_selected(const bool p_nested_action
void AnimationNodeStateMachineEditor::_update_mode() {
if (tool_select->is_pressed()) {
- tool_erase_hb->show();
+ selection_tools_hb->show();
bool nothing_selected = selected_nodes.is_empty() && selected_transition_from == StringName() && selected_transition_to == StringName();
bool start_end_selected = selected_nodes.size() == 1 && (*selected_nodes.begin() == state_machine->start_node || *selected_nodes.begin() == state_machine->end_node);
tool_erase->set_disabled(nothing_selected || start_end_selected || read_only);
@@ -1890,7 +1930,13 @@ void AnimationNodeStateMachineEditor::_update_mode() {
}
}
} else {
- tool_erase_hb->hide();
+ selection_tools_hb->hide();
+ }
+
+ if (tool_connect->is_pressed()) {
+ transition_tools_hb->show();
+ } else {
+ transition_tools_hb->hide();
}
}
@@ -1941,35 +1987,48 @@ AnimationNodeStateMachineEditor::AnimationNodeStateMachineEditor() {
tool_connect->set_tooltip_text(TTR("Connect nodes."));
tool_connect->connect("pressed", callable_mp(this, &AnimationNodeStateMachineEditor::_update_mode), CONNECT_DEFERRED);
- tool_erase_hb = memnew(HBoxContainer);
- top_hb->add_child(tool_erase_hb);
- tool_erase_hb->add_child(memnew(VSeparator));
+ // Context-sensitive selection tools:
+ selection_tools_hb = memnew(HBoxContainer);
+ top_hb->add_child(selection_tools_hb);
+ selection_tools_hb->add_child(memnew(VSeparator));
tool_group = memnew(Button);
tool_group->set_flat(true);
tool_group->set_tooltip_text(TTR("Group Selected Node(s)") + " (Ctrl+G)");
tool_group->connect("pressed", callable_mp(this, &AnimationNodeStateMachineEditor::_group_selected_nodes));
tool_group->set_disabled(true);
- tool_erase_hb->add_child(tool_group);
+ selection_tools_hb->add_child(tool_group);
tool_ungroup = memnew(Button);
tool_ungroup->set_flat(true);
tool_ungroup->set_tooltip_text(TTR("Ungroup Selected Node") + " (Ctrl+Shift+G)");
tool_ungroup->connect("pressed", callable_mp(this, &AnimationNodeStateMachineEditor::_ungroup_selected_nodes));
tool_ungroup->set_visible(false);
- tool_erase_hb->add_child(tool_ungroup);
+ selection_tools_hb->add_child(tool_ungroup);
tool_erase = memnew(Button);
tool_erase->set_flat(true);
tool_erase->set_tooltip_text(TTR("Remove selected node or transition."));
tool_erase->connect("pressed", callable_mp(this, &AnimationNodeStateMachineEditor::_erase_selected).bind(false));
tool_erase->set_disabled(true);
- tool_erase_hb->add_child(tool_erase);
+ selection_tools_hb->add_child(tool_erase);
+
+ transition_tools_hb = memnew(HBoxContainer);
+ top_hb->add_child(transition_tools_hb);
+ transition_tools_hb->add_child(memnew(VSeparator));
+
+ transition_tools_hb->add_child(memnew(Label(TTR("Transition:"))));
+ switch_mode = memnew(OptionButton);
+ transition_tools_hb->add_child(switch_mode);
- top_hb->add_child(memnew(VSeparator));
- top_hb->add_child(memnew(Label(TTR("Transition:"))));
- transition_mode = memnew(OptionButton);
- top_hb->add_child(transition_mode);
+ auto_advance = memnew(Button);
+ auto_advance->set_flat(true);
+ auto_advance->set_tooltip_text(TTR("New Transitions Should Auto Advance"));
+ auto_advance->set_toggle_mode(true);
+ auto_advance->set_pressed(true);
+ transition_tools_hb->add_child(auto_advance);
+
+ //
top_hb->add_spacer();
@@ -2013,8 +2072,6 @@ AnimationNodeStateMachineEditor::AnimationNodeStateMachineEditor() {
error_panel->add_child(error_label);
error_panel->hide();
- undo_redo = EditorNode::get_undo_redo();
-
set_custom_minimum_size(Size2(0, 300 * EDSCALE));
menu = memnew(PopupMenu);
@@ -2055,7 +2112,6 @@ AnimationNodeStateMachineEditor::AnimationNodeStateMachineEditor() {
open_file->set_title(TTR("Open Animation Node"));
open_file->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE);
open_file->connect("file_selected", callable_mp(this, &AnimationNodeStateMachineEditor::_file_opened));
- undo_redo = EditorNode::get_undo_redo();
delete_window = memnew(ConfirmationDialog);
delete_window->set_flag(Window::FLAG_RESIZE_DISABLED, true);
diff --git a/editor/plugins/animation_state_machine_editor.h b/editor/plugins/animation_state_machine_editor.h
index d0828a5f52..28b5f0cbcc 100644
--- a/editor/plugins/animation_state_machine_editor.h
+++ b/editor/plugins/animation_state_machine_editor.h
@@ -31,16 +31,16 @@
#ifndef ANIMATION_STATE_MACHINE_EDITOR_H
#define ANIMATION_STATE_MACHINE_EDITOR_H
-#include "editor/editor_plugin.h"
#include "editor/plugins/animation_tree_editor_plugin.h"
#include "scene/animation/animation_node_state_machine.h"
-#include "scene/gui/button.h"
#include "scene/gui/graph_edit.h"
#include "scene/gui/popup.h"
#include "scene/gui/tree.h"
+class ConfirmationDialog;
class EditorFileDialog;
-class EditorUndoRedoManager;
+class OptionButton;
+class PanelContainer;
class AnimationNodeStateMachineEditor : public AnimationTreeNodeEditorPlugin {
GDCLASS(AnimationNodeStateMachineEditor, AnimationTreeNodeEditorPlugin);
@@ -52,15 +52,18 @@ class AnimationNodeStateMachineEditor : public AnimationTreeNodeEditorPlugin {
Button *tool_select = nullptr;
Button *tool_create = nullptr;
Button *tool_connect = nullptr;
- Button *tool_group = nullptr;
- Button *tool_ungroup = nullptr;
Popup *name_edit_popup = nullptr;
LineEdit *name_edit = nullptr;
- HBoxContainer *tool_erase_hb = nullptr;
+ HBoxContainer *selection_tools_hb = nullptr;
+ Button *tool_group = nullptr;
+ Button *tool_ungroup = nullptr;
Button *tool_erase = nullptr;
- OptionButton *transition_mode = nullptr;
+ HBoxContainer *transition_tools_hb = nullptr;
+ OptionButton *switch_mode = nullptr;
+ Button *auto_advance = nullptr;
+
OptionButton *play_mode = nullptr;
PanelContainer *panel = nullptr;
@@ -79,8 +82,6 @@ class AnimationNodeStateMachineEditor : public AnimationTreeNodeEditorPlugin {
bool updating = false;
- Ref<EditorUndoRedoManager> undo_redo;
-
static AnimationNodeStateMachineEditor *singleton;
void _state_machine_gui_input(const Ref<InputEvent> &p_event);
diff --git a/editor/plugins/animation_tree_editor_plugin.cpp b/editor/plugins/animation_tree_editor_plugin.cpp
index 1de4fbaabc..c31a2689ec 100644
--- a/editor/plugins/animation_tree_editor_plugin.cpp
+++ b/editor/plugins/animation_tree_editor_plugin.cpp
@@ -74,6 +74,13 @@ void AnimationTreeEditor::edit(AnimationTree *p_tree) {
edit_path(path);
}
+void AnimationTreeEditor::_node_removed(Node *p_node) {
+ if (p_node == tree) {
+ tree = nullptr;
+ _clear_editors();
+ }
+}
+
void AnimationTreeEditor::_path_button_pressed(int p_path) {
edited_path.clear();
for (int i = 0; i <= p_path; i++) {
@@ -145,7 +152,6 @@ void AnimationTreeEditor::edit_path(const Vector<String> &p_path) {
} else {
current_root = ObjectID();
edited_path = button_path;
-
for (int i = 0; i < editors.size(); i++) {
editors[i]->edit(Ref<AnimationNode>());
editors[i]->hide();
@@ -155,6 +161,17 @@ void AnimationTreeEditor::edit_path(const Vector<String> &p_path) {
_update_path();
}
+void AnimationTreeEditor::_clear_editors() {
+ button_path.clear();
+ current_root = ObjectID();
+ edited_path = button_path;
+ for (int i = 0; i < editors.size(); i++) {
+ editors[i]->edit(Ref<AnimationNode>());
+ editors[i]->hide();
+ }
+ _update_path();
+}
+
Vector<String> AnimationTreeEditor::get_edited_path() const {
return button_path;
}
@@ -167,6 +184,9 @@ void AnimationTreeEditor::enter_editor(const String &p_path) {
void AnimationTreeEditor::_notification(int p_what) {
switch (p_what) {
+ case NOTIFICATION_ENTER_TREE: {
+ get_tree()->connect("node_removed", callable_mp(this, &AnimationTreeEditor::_node_removed));
+ } break;
case NOTIFICATION_PROCESS: {
ObjectID root;
if (tree && tree->get_tree_root().is_valid()) {
@@ -181,6 +201,9 @@ void AnimationTreeEditor::_notification(int p_what) {
edit_path(edited_path);
}
} break;
+ case NOTIFICATION_EXIT_TREE: {
+ get_tree()->disconnect("node_removed", callable_mp(this, &AnimationTreeEditor::_node_removed));
+ } break;
}
}
diff --git a/editor/plugins/animation_tree_editor_plugin.h b/editor/plugins/animation_tree_editor_plugin.h
index 9ef9fff8cd..b933523057 100644
--- a/editor/plugins/animation_tree_editor_plugin.h
+++ b/editor/plugins/animation_tree_editor_plugin.h
@@ -35,8 +35,6 @@
#include "scene/animation/animation_tree.h"
#include "scene/gui/button.h"
#include "scene/gui/graph_edit.h"
-#include "scene/gui/popup.h"
-#include "scene/gui/tree.h"
class EditorFileDialog;
@@ -62,6 +60,7 @@ class AnimationTreeEditor : public VBoxContainer {
Vector<AnimationTreeNodeEditorPlugin *> editors;
void _update_path();
+ void _clear_editors();
ObjectID current_root;
void _path_button_pressed(int p_path);
@@ -71,12 +70,13 @@ class AnimationTreeEditor : public VBoxContainer {
protected:
void _notification(int p_what);
+ void _node_removed(Node *p_node);
static void _bind_methods();
static AnimationTreeEditor *singleton;
public:
- AnimationTree *get_tree() { return tree; }
+ AnimationTree *get_animation_tree() { return tree; }
void add_plugin(AnimationTreeNodeEditorPlugin *p_editor);
void remove_plugin(AnimationTreeNodeEditorPlugin *p_editor);
diff --git a/editor/plugins/asset_library_editor_plugin.cpp b/editor/plugins/asset_library_editor_plugin.cpp
index 51b65e8eb0..6483a18a4d 100644
--- a/editor/plugins/asset_library_editor_plugin.cpp
+++ b/editor/plugins/asset_library_editor_plugin.cpp
@@ -41,6 +41,12 @@
#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/project_settings_editor.h"
+#include "scene/gui/menu_button.h"
+
+#include "modules/modules_enabled.gen.h" // For svg.
+#ifdef MODULE_SVG_ENABLED
+#include "modules/svg/image_loader_svg.h"
+#endif
static inline void setup_http_request(HTTPRequest *request) {
request->set_use_threads(EDITOR_DEF("asset_library/use_threads", true));
@@ -65,13 +71,13 @@ void EditorAssetLibraryItem::set_image(int p_type, int p_index, const Ref<Textur
ERR_FAIL_COND(p_type != EditorAssetLibrary::IMAGE_QUEUE_ICON);
ERR_FAIL_COND(p_index != 0);
- icon->set_normal_texture(p_image);
+ icon->set_texture_normal(p_image);
}
void EditorAssetLibraryItem::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE: {
- icon->set_normal_texture(get_theme_icon(SNAME("ProjectIconLoading"), SNAME("EditorIcons")));
+ icon->set_texture_normal(get_theme_icon(SNAME("ProjectIconLoading"), SNAME("EditorIcons")));
category->add_theme_color_override("font_color", Color(0.5, 0.5, 0.5));
author->add_theme_color_override("font_color", Color(0.5, 0.5, 0.5));
price->add_theme_color_override("font_color", Color(0.5, 0.5, 0.5));
@@ -402,7 +408,7 @@ void EditorAssetLibraryItemDownload::_notification(int p_what) {
case NOTIFICATION_THEME_CHANGED: {
panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("panel"), SNAME("AssetLib")));
status->add_theme_color_override("font_color", get_theme_color(SNAME("status_color"), SNAME("AssetLib")));
- dismiss_button->set_normal_texture(get_theme_icon(SNAME("dismiss"), SNAME("AssetLib")));
+ dismiss_button->set_texture_normal(get_theme_icon(SNAME("dismiss"), SNAME("AssetLib")));
} break;
case NOTIFICATION_PROCESS: {
@@ -750,13 +756,30 @@ void EditorAssetLibrary::_image_update(bool use_cache, bool final, const PackedB
uint8_t png_signature[8] = { 137, 80, 78, 71, 13, 10, 26, 10 };
uint8_t jpg_signature[3] = { 255, 216, 255 };
+ uint8_t webp_signature[4] = { 82, 73, 70, 70 };
+ uint8_t bmp_signature[2] = { 66, 77 };
if (r) {
if ((memcmp(&r[0], &png_signature[0], 8) == 0) && Image::_png_mem_loader_func) {
image->copy_internals_from(Image::_png_mem_loader_func(r, len));
} else if ((memcmp(&r[0], &jpg_signature[0], 3) == 0) && Image::_jpg_mem_loader_func) {
image->copy_internals_from(Image::_jpg_mem_loader_func(r, len));
+ } else if ((memcmp(&r[0], &webp_signature[0], 4) == 0) && Image::_webp_mem_loader_func) {
+ image->copy_internals_from(Image::_webp_mem_loader_func(r, len));
+ } else if ((memcmp(&r[0], &bmp_signature[0], 2) == 0) && Image::_bmp_mem_loader_func) {
+ image->copy_internals_from(Image::_bmp_mem_loader_func(r, len));
}
+#ifdef MODULE_SVG_ENABLED
+ else {
+ ImageLoaderSVG svg_loader;
+ Ref<Image> img = Ref<Image>(memnew(Image));
+ Error err = svg_loader.create_image_from_utf8_buffer(img, image_data, 1.0, false);
+
+ if (err == OK) {
+ image->copy_internals_from(img);
+ }
+ }
+#endif
}
if (!image->is_empty()) {
diff --git a/editor/plugins/asset_library_editor_plugin.h b/editor/plugins/asset_library_editor_plugin.h
index 070d25e29f..2795892c2e 100644
--- a/editor/plugins/asset_library_editor_plugin.h
+++ b/editor/plugins/asset_library_editor_plugin.h
@@ -50,6 +50,9 @@
#include "scene/gui/texture_button.h"
#include "scene/main/http_request.h"
+class EditorFileDialog;
+class MenuButton;
+
class EditorAssetLibraryItem : public PanelContainer {
GDCLASS(EditorAssetLibraryItem, PanelContainer);
diff --git a/editor/plugins/audio_stream_editor_plugin.cpp b/editor/plugins/audio_stream_editor_plugin.cpp
new file mode 100644
index 0000000000..60d949cdf0
--- /dev/null
+++ b/editor/plugins/audio_stream_editor_plugin.cpp
@@ -0,0 +1,280 @@
+/*************************************************************************/
+/* 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/core_string_names.h"
+#include "editor/audio_stream_preview.h"
+#include "editor/editor_scale.h"
+#include "editor/editor_settings.h"
+#include "scene/resources/audio_stream_wav.h"
+
+// AudioStreamEditor
+
+void AudioStreamEditor::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_READY: {
+ AudioStreamPreviewGenerator::get_singleton()->connect(SNAME("preview_updated"), callable_mp(this, &AudioStreamEditor::_preview_changed));
+ } break;
+ case NOTIFICATION_THEME_CHANGED:
+ case NOTIFICATION_ENTER_TREE: {
+ Ref<Font> font = get_theme_font(SNAME("status_source"), SNAME("EditorFonts"));
+
+ _current_label->add_theme_font_override(SNAME("font"), font);
+ _duration_label->add_theme_font_override(SNAME("font"), font);
+
+ _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->queue_redraw();
+ _preview->queue_redraw();
+ } break;
+ case NOTIFICATION_PROCESS: {
+ _current = _player->get_playback_position();
+ _indicator->queue_redraw();
+ } break;
+ case NOTIFICATION_VISIBILITY_CHANGED: {
+ if (!is_visible_in_tree()) {
+ _stop();
+ }
+ } break;
+ default: {
+ } 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);
+ }
+
+ RS::get_singleton()->canvas_item_add_multiline(_preview->get_canvas_item(), lines, { get_theme_color(SNAME("contrast_color_2"), SNAME("Editor")) });
+}
+
+void AudioStreamEditor::_preview_changed(ObjectID p_which) {
+ if (stream.is_valid() && stream->get_instance_id() == p_which) {
+ _preview->queue_redraw();
+ }
+}
+
+void AudioStreamEditor::_stream_changed() {
+ if (!is_visible()) {
+ return;
+ }
+ queue_redraw();
+}
+
+void AudioStreamEditor::_play() {
+ if (_player->is_playing()) {
+ _pausing = true;
+ _player->stop();
+ _play_button->set_icon(get_theme_icon(SNAME("MainPlay"), SNAME("EditorIcons")));
+ set_process(false);
+ } else {
+ _pausing = false;
+ _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->queue_redraw();
+ set_process(false);
+}
+
+void AudioStreamEditor::_on_finished() {
+ _play_button->set_icon(get_theme_icon(SNAME("MainPlay"), SNAME("EditorIcons")));
+ if (!_pausing) {
+ _current = 0;
+ _indicator->queue_redraw();
+ } else {
+ _pausing = false;
+ }
+ set_process(false);
+}
+
+void AudioStreamEditor::_draw_indicator() {
+ if (stream.is_null()) {
+ return;
+ }
+
+ Rect2 rect = _preview->get_rect();
+ float len = stream->get_length();
+ float ofs_x = _current / len * rect.size.width;
+ const Color col = get_theme_color(SNAME("accent_color"), SNAME("Editor"));
+ Ref<Texture2D> icon = get_theme_icon(SNAME("TimelineIndicator"), SNAME("EditorIcons"));
+ _indicator->draw_line(Point2(ofs_x, 0), Point2(ofs_x, rect.size.height), col, Math::round(2 * EDSCALE));
+ _indicator->draw_texture(
+ icon,
+ Point2(ofs_x - icon->get_width() * 0.5, 0),
+ col);
+
+ _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->queue_redraw();
+}
+
+void AudioStreamEditor::set_stream(const Ref<AudioStream> &p_stream) {
+ if (stream.is_valid()) {
+ stream->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(this, &AudioStreamEditor::_stream_changed));
+ }
+
+ stream = p_stream;
+ if (stream.is_null()) {
+ hide();
+ return;
+ }
+ stream->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &AudioStreamEditor::_stream_changed));
+
+ _player->set_stream(stream);
+ _current = 0;
+
+ String text = String::num(stream->get_length(), 2).pad_decimals(2) + "s";
+ _duration_label->set_text(text);
+
+ queue_redraw();
+}
+
+AudioStreamEditor::AudioStreamEditor() {
+ set_custom_minimum_size(Size2(1, 100) * EDSCALE);
+
+ _player = memnew(AudioStreamPlayer);
+ _player->connect(SNAME("finished"), callable_mp(this, &AudioStreamEditor::_on_finished));
+ add_child(_player);
+
+ VBoxContainer *vbox = memnew(VBoxContainer);
+ vbox->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT);
+ add_child(vbox);
+
+ _preview = memnew(ColorRect);
+ _preview->set_v_size_flags(SIZE_EXPAND_FILL);
+ _preview->connect(SNAME("draw"), callable_mp(this, &AudioStreamEditor::_draw_preview));
+ vbox->add_child(_preview);
+
+ _indicator = memnew(Control);
+ _indicator->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT);
+ _indicator->connect(SNAME("draw"), callable_mp(this, &AudioStreamEditor::_draw_indicator));
+ _indicator->connect(SNAME("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);
+ hbox->add_child(_play_button);
+ _play_button->set_flat(true);
+ _play_button->set_focus_mode(Control::FOCUS_NONE);
+ _play_button->connect(SNAME("pressed"), callable_mp(this, &AudioStreamEditor::_play));
+ _play_button->set_shortcut(ED_SHORTCUT("audio_stream_editor/audio_preview_play_pause", TTR("Audio Preview Play/Pause"), Key::SPACE));
+
+ _stop_button = memnew(Button);
+ hbox->add_child(_stop_button);
+ _stop_button->set_flat(true);
+ _stop_button->set_focus_mode(Control::FOCUS_NONE);
+ _stop_button->connect(SNAME("pressed"), callable_mp(this, &AudioStreamEditor::_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);
+}
+
+// EditorInspectorPluginAudioStream
+
+bool EditorInspectorPluginAudioStream::can_handle(Object *p_object) {
+ return Object::cast_to<AudioStreamWAV>(p_object) != nullptr;
+}
+
+void EditorInspectorPluginAudioStream::parse_begin(Object *p_object) {
+ AudioStream *stream = Object::cast_to<AudioStream>(p_object);
+
+ editor = memnew(AudioStreamEditor);
+ editor->set_stream(Ref<AudioStream>(stream));
+
+ add_custom_control(editor);
+}
+
+// AudioStreamEditorPlugin
+
+AudioStreamEditorPlugin::AudioStreamEditorPlugin() {
+ Ref<EditorInspectorPluginAudioStream> plugin;
+ plugin.instantiate();
+ add_inspector_plugin(plugin);
+}
diff --git a/editor/plugins/audio_stream_editor_plugin.h b/editor/plugins/audio_stream_editor_plugin.h
new file mode 100644
index 0000000000..13e52929ee
--- /dev/null
+++ b/editor/plugins/audio_stream_editor_plugin.h
@@ -0,0 +1,93 @@
+/*************************************************************************/
+/* audio_stream_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 AUDIO_STREAM_EDITOR_PLUGIN_H
+#define AUDIO_STREAM_EDITOR_PLUGIN_H
+
+#include "editor/editor_inspector.h"
+#include "editor/editor_plugin.h"
+#include "scene/audio/audio_stream_player.h"
+#include "scene/gui/button.h"
+#include "scene/gui/color_rect.h"
+#include "scene/gui/label.h"
+
+class AudioStreamEditor : public ColorRect {
+ GDCLASS(AudioStreamEditor, ColorRect);
+
+ Ref<AudioStream> stream;
+
+ AudioStreamPlayer *_player = nullptr;
+ ColorRect *_preview = nullptr;
+ Control *_indicator = nullptr;
+ Label *_current_label = nullptr;
+ Label *_duration_label = nullptr;
+
+ Button *_play_button = nullptr;
+ Button *_stop_button = nullptr;
+
+ float _current = 0;
+ bool _dragging = false;
+ bool _pausing = false;
+
+protected:
+ void _notification(int p_what);
+ void _preview_changed(ObjectID p_which);
+ void _play();
+ void _stop();
+ void _on_finished();
+ void _draw_preview();
+ void _draw_indicator();
+ void _on_input_indicator(Ref<InputEvent> p_event);
+ void _seek_to(real_t p_x);
+ void _stream_changed();
+
+public:
+ void set_stream(const Ref<AudioStream> &p_stream);
+
+ AudioStreamEditor();
+};
+
+class EditorInspectorPluginAudioStream : public EditorInspectorPlugin {
+ GDCLASS(EditorInspectorPluginAudioStream, EditorInspectorPlugin);
+ AudioStreamEditor *editor = nullptr;
+
+public:
+ virtual bool can_handle(Object *p_object) override;
+ virtual void parse_begin(Object *p_object) override;
+};
+
+class AudioStreamEditorPlugin : public EditorPlugin {
+ GDCLASS(AudioStreamEditorPlugin, EditorPlugin);
+
+public:
+ AudioStreamEditorPlugin();
+};
+
+#endif // AUDIO_STREAM_EDITOR_PLUGIN_H
diff --git a/editor/plugins/audio_stream_randomizer_editor_plugin.cpp b/editor/plugins/audio_stream_randomizer_editor_plugin.cpp
index e21a50a434..61b7683a05 100644
--- a/editor/plugins/audio_stream_randomizer_editor_plugin.cpp
+++ b/editor/plugins/audio_stream_randomizer_editor_plugin.cpp
@@ -81,7 +81,7 @@ void AudioStreamRandomizerEditorPlugin::_move_stream_array_element(Object *p_und
if (p_from_index < 0) {
undo_redo_man->add_undo_method(randomizer, "remove_stream", p_to_pos < 0 ? randomizer->get_streams_count() : p_to_pos);
} else if (p_to_pos < 0) {
- undo_redo_man->add_undo_method(randomizer, "add_stream", p_from_index);
+ undo_redo_man->add_undo_method(randomizer, "add_stream", p_from_index, Ref<AudioStream>());
}
List<PropertyInfo> properties;
@@ -107,7 +107,7 @@ void AudioStreamRandomizerEditorPlugin::_move_stream_array_element(Object *p_und
#undef ADD_UNDO
if (p_from_index < 0) {
- undo_redo_man->add_do_method(randomizer, "add_stream", p_to_pos);
+ undo_redo_man->add_do_method(randomizer, "add_stream", p_to_pos, Ref<AudioStream>());
} else if (p_to_pos < 0) {
undo_redo_man->add_do_method(randomizer, "remove_stream", p_from_index);
} else {
diff --git a/editor/plugins/bit_map_editor_plugin.cpp b/editor/plugins/bit_map_editor_plugin.cpp
index 657c5a36b6..8d9b3147a9 100644
--- a/editor/plugins/bit_map_editor_plugin.cpp
+++ b/editor/plugins/bit_map_editor_plugin.cpp
@@ -31,6 +31,8 @@
#include "bit_map_editor_plugin.h"
#include "editor/editor_scale.h"
+#include "scene/gui/label.h"
+#include "scene/gui/texture_rect.h"
void BitMapEditor::setup(const Ref<BitMap> &p_bitmap) {
texture_rect->set_texture(ImageTexture::create_from_image(p_bitmap->convert_to_image()));
diff --git a/editor/plugins/bit_map_editor_plugin.h b/editor/plugins/bit_map_editor_plugin.h
index b045f8c751..8c65b1b6f1 100644
--- a/editor/plugins/bit_map_editor_plugin.h
+++ b/editor/plugins/bit_map_editor_plugin.h
@@ -31,9 +31,12 @@
#ifndef BIT_MAP_EDITOR_PLUGIN_H
#define BIT_MAP_EDITOR_PLUGIN_H
+#include "editor/editor_inspector.h"
#include "editor/editor_plugin.h"
#include "scene/resources/bit_map.h"
+class TextureRect;
+
class BitMapEditor : public VBoxContainer {
GDCLASS(BitMapEditor, VBoxContainer);
diff --git a/editor/plugins/bone_map_editor_plugin.cpp b/editor/plugins/bone_map_editor_plugin.cpp
index c834e0e93e..4bf11f0627 100644
--- a/editor/plugins/bone_map_editor_plugin.cpp
+++ b/editor/plugins/bone_map_editor_plugin.cpp
@@ -31,16 +31,20 @@
#include "bone_map_editor_plugin.h"
#include "editor/editor_scale.h"
+#include "editor/editor_settings.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"
+#include "scene/gui/aspect_ratio_container.h"
+#include "scene/gui/separator.h"
+#include "scene/gui/texture_rect.h"
void BoneMapperButton::fetch_textures() {
if (selected) {
- set_normal_texture(get_theme_icon(SNAME("BoneMapperHandleSelected"), SNAME("EditorIcons")));
+ set_texture_normal(get_theme_icon(SNAME("BoneMapperHandleSelected"), SNAME("EditorIcons")));
} else {
- set_normal_texture(get_theme_icon(SNAME("BoneMapperHandle"), SNAME("EditorIcons")));
+ set_texture_normal(get_theme_icon(SNAME("BoneMapperHandle"), SNAME("EditorIcons")));
}
set_offset(SIDE_LEFT, 0);
set_offset(SIDE_RIGHT, 0);
@@ -742,7 +746,6 @@ void BoneMapper::auto_mapping_process(Ref<BoneMap> &p_bone_map) {
} else {
p_bone_map->_set_skeleton_bone_name("LeftEye", skeleton->get_bone_name(bone_idx));
}
- bone_idx = -1;
bone_idx = search_bone_by_name(skeleton, picklist, BONE_SEGREGATION_RIGHT, neck_or_head);
if (bone_idx == -1) {
@@ -750,7 +753,6 @@ void BoneMapper::auto_mapping_process(Ref<BoneMap> &p_bone_map) {
} else {
p_bone_map->_set_skeleton_bone_name("RightEye", skeleton->get_bone_name(bone_idx));
}
- bone_idx = -1;
picklist.clear();
// 4-2. Guess Jaw
diff --git a/editor/plugins/bone_map_editor_plugin.h b/editor/plugins/bone_map_editor_plugin.h
index 16e5403978..e6a35d1120 100644
--- a/editor/plugins/bone_map_editor_plugin.h
+++ b/editor/plugins/bone_map_editor_plugin.h
@@ -41,11 +41,14 @@
#endif
#include "scene/3d/skeleton_3d.h"
+#include "scene/gui/box_container.h"
#include "scene/gui/color_rect.h"
#include "scene/gui/dialogs.h"
#include "scene/resources/bone_map.h"
#include "scene/resources/texture.h"
+class AspectRatioContainer;
+
class BoneMapperButton : public TextureButton {
GDCLASS(BoneMapperButton, TextureButton);
diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp
index baf335f5b4..aab64587ce 100644
--- a/editor/plugins/canvas_item_editor_plugin.cpp
+++ b/editor/plugins/canvas_item_editor_plugin.cpp
@@ -32,15 +32,14 @@
#include "core/config/project_settings.h"
#include "core/input/input.h"
-#include "core/math/geometry_2d.h"
#include "core/os/keyboard.h"
-#include "core/string/print_string.h"
#include "editor/debugger/editor_debugger_node.h"
#include "editor/editor_node.h"
#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_toaster.h"
#include "editor/editor_undo_redo_manager.h"
+#include "editor/editor_zoom_widget.h"
#include "editor/plugins/animation_player_editor_plugin.h"
#include "editor/plugins/script_editor_plugin.h"
#include "editor/scene_tree_dock.h"
@@ -55,6 +54,7 @@
#include "scene/gui/grid_container.h"
#include "scene/gui/nine_patch_rect.h"
#include "scene/gui/separator.h"
+#include "scene/gui/split_container.h"
#include "scene/gui/subviewport_container.h"
#include "scene/gui/view_panner.h"
#include "scene/main/canvas_layer.h"
@@ -412,7 +412,7 @@ Point2 CanvasItemEditor::snap_point(Point2 p_target, unsigned int p_modes, unsig
// Other nodes sides
if ((is_snap_active && snap_other_nodes && (p_modes & SNAP_OTHER_NODES)) || (p_forced_modes & SNAP_OTHER_NODES)) {
- Transform2D to_snap_transform = Transform2D();
+ Transform2D to_snap_transform;
List<const CanvasItem *> exceptions = List<const CanvasItem *>();
for (const CanvasItem *E : p_other_nodes_exceptions) {
exceptions.push_back(E);
@@ -813,7 +813,7 @@ Vector2 CanvasItemEditor::_position_to_anchor(const Control *p_control, Vector2
Rect2 parent_rect = p_control->get_parent_anchorable_rect();
- Vector2 output = Vector2();
+ Vector2 output;
if (p_control->is_layout_rtl()) {
output.x = (parent_rect.size.x == 0) ? 0.0 : (parent_rect.size.x - p_control->get_transform().xform(position).x - parent_rect.position.x) / parent_rect.size.x;
} else {
@@ -2268,7 +2268,7 @@ bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) {
}
}
- String suffix = String();
+ String suffix;
if (locked == 1) {
suffix = " (" + TTR("Locked") + ")";
} else if (locked == 2) {
@@ -2790,7 +2790,7 @@ void CanvasItemEditor::_draw_rulers() {
int font_size = get_theme_font_size(SNAME("rulers_size"), SNAME("EditorFonts"));
// The rule transform
- Transform2D ruler_transform = Transform2D();
+ Transform2D ruler_transform;
if (grid_snap_active || _is_grid_visible()) {
List<CanvasItem *> selection = _get_edited_canvas_items();
if (snap_relative && selection.size() > 0) {
@@ -2816,11 +2816,11 @@ void CanvasItemEditor::_draw_rulers() {
// Subdivisions
int major_subdivision = 2;
- Transform2D major_subdivide = Transform2D();
+ Transform2D major_subdivide;
major_subdivide.scale(Size2(1.0 / major_subdivision, 1.0 / major_subdivision));
int minor_subdivision = 5;
- Transform2D minor_subdivide = Transform2D();
+ Transform2D minor_subdivide;
minor_subdivide.scale(Size2(1.0 / minor_subdivision, 1.0 / minor_subdivision));
// First and last graduations to draw (in the ruler space)
@@ -3032,7 +3032,7 @@ void CanvasItemEditor::_draw_ruler_tool() {
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();
+ Point2 v_angle_text_pos;
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_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);
@@ -3043,7 +3043,7 @@ void CanvasItemEditor::_draw_ruler_tool() {
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();
+ Point2 h_angle_text_pos;
h_angle_text_pos.x = CLAMP(end.x - angle_text_width / 2, angle_text_width / 2, viewport->get_rect().size.x - angle_text_width);
if (begin.y < end.y) {
h_angle_text_pos.y = end.y + text_height * 1.5;
@@ -5504,6 +5504,11 @@ void CanvasItemEditorViewport::_create_preview(const Vector<String> &files) cons
Ref<Texture2D> texture = Ref<Texture2D>(Object::cast_to<Texture2D>(*res));
Ref<PackedScene> scene = Ref<PackedScene>(Object::cast_to<PackedScene>(*res));
if (texture != nullptr || scene != nullptr) {
+ bool root_node_selected = EditorNode::get_singleton()->get_editor_selection()->is_selected(EditorNode::get_singleton()->get_edited_scene());
+ String desc = TTR("Drag and drop to add as child of current scene's root node.") + "\n" + TTR("Hold Ctrl when dropping to add as child of selected node.");
+ if (!root_node_selected) {
+ desc += "\n" + TTR("Hold Shift when dropping to add as sibling of selected node.");
+ }
if (texture != nullptr) {
Sprite2D *sprite = memnew(Sprite2D);
sprite->set_texture(texture);
@@ -5511,14 +5516,15 @@ void CanvasItemEditorViewport::_create_preview(const Vector<String> &files) cons
preview_node->add_child(sprite);
label->show();
label_desc->show();
- label_desc->set_text(TTR("Drag and drop to add as child of current scene's root node.\nHold Ctrl when dropping to add as child of selected node.\nHold Shift when dropping to add as sibling of selected node.\nHold Alt when dropping to add as a different node type."));
+ desc += "\n" + TTR("Hold Alt when dropping to add as a different node type.");
+ label_desc->set_text(desc);
} else {
if (scene.is_valid()) {
Node *instance = scene->instantiate();
if (instance) {
preview_node->add_child(instance);
label_desc->show();
- label_desc->set_text(TTR("Drag and drop to add as child of current scene's root node.\nHold Ctrl when dropping to add as child of selected node.\nHold Shift when dropping to add as sibling of selected node."));
+ label_desc->set_text(desc);
}
}
}
@@ -5596,7 +5602,7 @@ void CanvasItemEditorViewport::_create_nodes(Node *parent, Node *child, String &
// make visible for certain node type
if (Object::cast_to<Control>(child)) {
Size2 texture_size = texture->get_size();
- undo_redo->add_do_property(child, "rect_size", texture_size);
+ undo_redo->add_do_property(child, "size", texture_size);
} else if (Object::cast_to<Polygon2D>(child)) {
Size2 texture_size = texture->get_size();
Vector<Vector2> list = {
@@ -5612,6 +5618,11 @@ void CanvasItemEditorViewport::_create_nodes(Node *parent, Node *child, String &
Transform2D xform = canvas_item_editor->get_canvas_transform();
Point2 target_position = xform.affine_inverse().xform(p_point);
+ // Adjust position for Control and TouchScreenButton
+ if (Object::cast_to<Control>(child) || Object::cast_to<TouchScreenButton>(child)) {
+ target_position -= texture->get_size() / 2;
+ }
+
// there's nothing to be used as source position so snapping will work as absolute if enabled
target_position = canvas_item_editor->snap_point(target_position);
undo_redo->add_do_method(child, "set_global_position", target_position);
@@ -5624,13 +5635,13 @@ bool CanvasItemEditorViewport::_create_instance(Node *parent, String &path, cons
}
Node *instantiated_scene = sdata->instantiate(PackedScene::GEN_EDIT_STATE_INSTANCE);
- if (!instantiated_scene) { // error on instancing
+ if (!instantiated_scene) { // Error on instantiation.
return false;
}
Node *edited_scene = EditorNode::get_singleton()->get_edited_scene();
- if (!edited_scene->get_scene_file_path().is_empty()) { // cyclical instancing
+ if (!edited_scene->get_scene_file_path().is_empty()) { // Cyclic instantiation.
if (_cyclical_dependency_exists(edited_scene->get_scene_file_path(), instantiated_scene)) {
memdelete(instantiated_scene);
return false;
@@ -5647,7 +5658,7 @@ bool CanvasItemEditorViewport::_create_instance(Node *parent, String &path, cons
String new_name = parent->validate_child_name(instantiated_scene);
EditorDebuggerNode *ed = EditorDebuggerNode::get_singleton();
- undo_redo->add_do_method(ed, "live_debug_instance_node", edited_scene->get_path_to(parent), path, new_name);
+ undo_redo->add_do_method(ed, "live_debug_instantiate_node", edited_scene->get_path_to(parent), path, new_name);
undo_redo->add_undo_method(ed, "live_debug_remove_node", NodePath(String(edited_scene->get_path_to(parent)) + "/" + new_name));
CanvasItem *instance_ci = Object::cast_to<CanvasItem>(instantiated_scene);
@@ -5720,7 +5731,7 @@ void CanvasItemEditorViewport::_perform_drop_data() {
files_str += error_files[i].get_file().get_basename() + ",";
}
files_str = files_str.substr(0, files_str.length() - 1);
- accept->set_text(vformat(TTR("Error instancing scene from %s"), files_str.get_data()));
+ accept->set_text(vformat(TTR("Error instantiating scene from %s"), files_str.get_data()));
accept->popup_centered();
}
}
diff --git a/editor/plugins/canvas_item_editor_plugin.h b/editor/plugins/canvas_item_editor_plugin.h
index ba193a67b8..9c7d0fbe6f 100644
--- a/editor/plugins/canvas_item_editor_plugin.h
+++ b/editor/plugins/canvas_item_editor_plugin.h
@@ -32,19 +32,21 @@
#define CANVAS_ITEM_EDITOR_PLUGIN_H
#include "editor/editor_plugin.h"
-#include "editor/editor_zoom_widget.h"
+#include "scene/gui/base_button.h"
#include "scene/gui/box_container.h"
-#include "scene/gui/check_box.h"
-#include "scene/gui/label.h"
-#include "scene/gui/panel_container.h"
-#include "scene/gui/spin_box.h"
-#include "scene/gui/split_container.h"
-#include "scene/gui/texture_rect.h"
-#include "scene/main/canvas_item.h"
-class EditorData;
+class AcceptDialog;
class CanvasItemEditorViewport;
+class ConfirmationDialog;
+class EditorData;
+class EditorZoomWidget;
+class HScrollBar;
+class HSplitContainer;
+class MenuButton;
+class PanelContainer;
class ViewPanner;
+class VScrollBar;
+class VSplitContainer;
class CanvasItemEditorSelectedItem : public Object {
GDCLASS(CanvasItemEditorSelectedItem, Object);
@@ -336,12 +338,12 @@ private:
Point2 drag_start_origin;
DragType drag_type = DRAG_NONE;
- Point2 drag_from = Vector2();
- Point2 drag_to = Vector2();
+ Point2 drag_from;
+ Point2 drag_to;
Point2 drag_rotation_center;
List<CanvasItem *> drag_selection;
int dragged_guide_index = -1;
- Point2 dragged_guide_pos = Point2();
+ Point2 dragged_guide_pos;
bool is_hovering_h_guide = false;
bool is_hovering_v_guide = false;
diff --git a/editor/plugins/cast_2d_editor_plugin.cpp b/editor/plugins/cast_2d_editor_plugin.cpp
index a8d255f997..d991cdf27f 100644
--- a/editor/plugins/cast_2d_editor_plugin.cpp
+++ b/editor/plugins/cast_2d_editor_plugin.cpp
@@ -77,6 +77,7 @@ bool Cast2DEditor::forward_canvas_gui_input(const Ref<InputEvent> &p_event) {
return false;
}
} else if (pressed) {
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Set target_position"));
undo_redo->add_do_property(node, "target_position", target_position);
undo_redo->add_do_method(canvas_item_editor, "update_viewport");
@@ -130,10 +131,6 @@ void Cast2DEditor::edit(Node2D *p_node) {
canvas_item_editor->update_viewport();
}
-Cast2DEditor::Cast2DEditor() {
- undo_redo = EditorNode::get_singleton()->get_undo_redo();
-}
-
///////////////////////
void Cast2DEditorPlugin::edit(Object *p_object) {
diff --git a/editor/plugins/cast_2d_editor_plugin.h b/editor/plugins/cast_2d_editor_plugin.h
index ceed9b9111..1165a301f6 100644
--- a/editor/plugins/cast_2d_editor_plugin.h
+++ b/editor/plugins/cast_2d_editor_plugin.h
@@ -35,12 +35,10 @@
#include "scene/2d/node_2d.h"
class CanvasItemEditor;
-class EditorUndoRedoManager;
class Cast2DEditor : public Control {
GDCLASS(Cast2DEditor, Control);
- Ref<EditorUndoRedoManager> undo_redo;
CanvasItemEditor *canvas_item_editor = nullptr;
Node2D *node = nullptr;
@@ -55,8 +53,6 @@ public:
bool forward_canvas_gui_input(const Ref<InputEvent> &p_event);
void forward_canvas_draw_over_viewport(Control *p_overlay);
void edit(Node2D *p_node);
-
- Cast2DEditor();
};
class Cast2DEditorPlugin : public EditorPlugin {
diff --git a/editor/plugins/collision_shape_2d_editor_plugin.cpp b/editor/plugins/collision_shape_2d_editor_plugin.cpp
index 11992ad10e..a7f842aa66 100644
--- a/editor/plugins/collision_shape_2d_editor_plugin.cpp
+++ b/editor/plugins/collision_shape_2d_editor_plugin.cpp
@@ -219,6 +219,7 @@ void CollisionShape2DEditor::set_handle(int idx, Point2 &p_point) {
}
void CollisionShape2DEditor::commit_handle(int idx, Variant &p_org) {
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Set Handle"));
switch (shape_type) {
@@ -588,8 +589,6 @@ CollisionShape2DEditor::CollisionShape2DEditor() {
node = nullptr;
canvas_item_editor = nullptr;
- undo_redo = EditorNode::get_singleton()->get_undo_redo();
-
edit_handle = -1;
pressed = false;
diff --git a/editor/plugins/collision_shape_2d_editor_plugin.h b/editor/plugins/collision_shape_2d_editor_plugin.h
index 49e0820ae9..51cdab7396 100644
--- a/editor/plugins/collision_shape_2d_editor_plugin.h
+++ b/editor/plugins/collision_shape_2d_editor_plugin.h
@@ -35,7 +35,6 @@
#include "scene/2d/collision_shape_2d.h"
class CanvasItemEditor;
-class EditorUndoRedoManager;
class CollisionShape2DEditor : public Control {
GDCLASS(CollisionShape2DEditor, Control);
@@ -62,7 +61,6 @@ class CollisionShape2DEditor : public Control {
Point2(1, -1),
};
- Ref<EditorUndoRedoManager> undo_redo;
CanvasItemEditor *canvas_item_editor = nullptr;
CollisionShape2D *node = nullptr;
diff --git a/editor/plugins/control_editor_plugin.cpp b/editor/plugins/control_editor_plugin.cpp
index 1791f7b420..c18876b9ef 100644
--- a/editor/plugins/control_editor_plugin.cpp
+++ b/editor/plugins/control_editor_plugin.cpp
@@ -35,6 +35,7 @@
#include "editor/editor_settings.h"
#include "editor/editor_undo_redo_manager.h"
#include "editor/plugins/canvas_item_editor_plugin.h"
+#include "scene/gui/grid_container.h"
#include "scene/gui/separator.h"
// Inspector controls.
@@ -720,6 +721,7 @@ void ControlEditorToolbar::_anchors_preset_selected(int p_preset) {
LayoutPreset preset = (LayoutPreset)p_preset;
List<Node *> selection = editor_selection->get_selected_node_list();
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Change Anchors, Offsets, Grow Direction"));
for (Node *E : selection) {
@@ -739,6 +741,7 @@ void ControlEditorToolbar::_anchors_preset_selected(int p_preset) {
void ControlEditorToolbar::_anchors_to_current_ratio() {
List<Node *> selection = editor_selection->get_selected_node_list();
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Change Anchors, Offsets (Keep Ratio)"));
for (Node *E : selection) {
@@ -789,6 +792,7 @@ void ControlEditorToolbar::_anchor_mode_toggled(bool p_status) {
void ControlEditorToolbar::_container_flags_selected(int p_flags, bool p_vertical) {
List<Node *> selection = editor_selection->get_selected_node_list();
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
if (p_vertical) {
undo_redo->create_action(TTR("Change Vertical Size Flags"));
} else {
@@ -815,7 +819,7 @@ Vector2 ControlEditorToolbar::_position_to_anchor(const Control *p_control, Vect
Rect2 parent_rect = p_control->get_parent_anchorable_rect();
- Vector2 output = Vector2();
+ Vector2 output;
if (p_control->is_layout_rtl()) {
output.x = (parent_rect.size.x == 0) ? 0.0 : (parent_rect.size.x - p_control->get_transform().xform(position).x - parent_rect.position.x) / parent_rect.size.x;
} else {
@@ -1024,7 +1028,6 @@ ControlEditorToolbar::ControlEditorToolbar() {
container_v_picker->connect("size_flags_selected", callable_mp(this, &ControlEditorToolbar::_container_flags_selected).bind(true));
// Editor connections.
- undo_redo = EditorNode::get_singleton()->get_undo_redo();
editor_selection = EditorNode::get_singleton()->get_editor_selection();
editor_selection->add_editor_plugin(this);
editor_selection->connect("selection_changed", callable_mp(this, &ControlEditorToolbar::_selection_changed));
diff --git a/editor/plugins/control_editor_plugin.h b/editor/plugins/control_editor_plugin.h
index d78773a509..cf2c6f4e20 100644
--- a/editor/plugins/control_editor_plugin.h
+++ b/editor/plugins/control_editor_plugin.h
@@ -31,6 +31,7 @@
#ifndef CONTROL_EDITOR_PLUGIN_H
#define CONTROL_EDITOR_PLUGIN_H
+#include "editor/editor_inspector.h"
#include "editor/editor_plugin.h"
#include "scene/gui/box_container.h"
#include "scene/gui/button.h"
@@ -44,7 +45,7 @@
#include "scene/gui/separator.h"
#include "scene/gui/texture_rect.h"
-class EditorUndoRedoManager;
+class GridContainer;
// Inspector controls.
class ControlPositioningWarning : public MarginContainer {
@@ -205,7 +206,6 @@ public:
class ControlEditorToolbar : public HBoxContainer {
GDCLASS(ControlEditorToolbar, HBoxContainer);
- Ref<EditorUndoRedoManager> undo_redo;
EditorSelection *editor_selection = nullptr;
ControlEditorPopupButton *anchors_button = nullptr;
diff --git a/editor/plugins/cpu_particles_2d_editor_plugin.cpp b/editor/plugins/cpu_particles_2d_editor_plugin.cpp
index a0e6771768..36b51e0e0c 100644
--- a/editor/plugins/cpu_particles_2d_editor_plugin.cpp
+++ b/editor/plugins/cpu_particles_2d_editor_plugin.cpp
@@ -34,9 +34,12 @@
#include "core/io/image_loader.h"
#include "editor/editor_file_dialog.h"
#include "editor/editor_node.h"
-#include "editor/editor_undo_redo_manager.h"
#include "scene/2d/cpu_particles_2d.h"
+#include "scene/gui/check_box.h"
+#include "scene/gui/menu_button.h"
+#include "scene/gui/option_button.h"
#include "scene/gui/separator.h"
+#include "scene/gui/spin_box.h"
#include "scene/resources/particle_process_material.h"
void CPUParticles2DEditorPlugin::edit(Object *p_object) {
@@ -239,7 +242,6 @@ void CPUParticles2DEditorPlugin::_bind_methods() {
CPUParticles2DEditorPlugin::CPUParticles2DEditorPlugin() {
particles = nullptr;
- undo_redo = EditorNode::get_singleton()->get_undo_redo();
toolbar = memnew(HBoxContainer);
add_control_to_container(CONTAINER_CANVAS_EDITOR_MENU, toolbar);
diff --git a/editor/plugins/cpu_particles_2d_editor_plugin.h b/editor/plugins/cpu_particles_2d_editor_plugin.h
index 06ca208463..1fc9ed763c 100644
--- a/editor/plugins/cpu_particles_2d_editor_plugin.h
+++ b/editor/plugins/cpu_particles_2d_editor_plugin.h
@@ -36,10 +36,12 @@
#include "scene/2d/cpu_particles_2d.h"
#include "scene/gui/box_container.h"
-class EditorPlugin;
+class CheckBox;
+class ConfirmationDialog;
class SpinBox;
class EditorFileDialog;
-class EditorUndoRedoManager;
+class MenuButton;
+class OptionButton;
class CPUParticles2DEditorPlugin : public EditorPlugin {
GDCLASS(CPUParticles2DEditorPlugin, EditorPlugin);
@@ -71,7 +73,6 @@ class CPUParticles2DEditorPlugin : public EditorPlugin {
String source_emission_file;
- Ref<EditorUndoRedoManager> undo_redo;
void _file_selected(const String &p_file);
void _menu_callback(int p_idx);
void _generate_emission_mask();
diff --git a/editor/plugins/curve_editor_plugin.h b/editor/plugins/curve_editor_plugin.h
index 5cf3b16a06..5503ce96ff 100644
--- a/editor/plugins/curve_editor_plugin.h
+++ b/editor/plugins/curve_editor_plugin.h
@@ -31,6 +31,7 @@
#ifndef CURVE_EDITOR_PLUGIN_H
#define CURVE_EDITOR_PLUGIN_H
+#include "editor/editor_inspector.h"
#include "editor/editor_plugin.h"
#include "editor/editor_resource_preview.h"
#include "scene/resources/curve.h"
diff --git a/editor/plugins/debugger_editor_plugin.cpp b/editor/plugins/debugger_editor_plugin.cpp
index dd6187c264..7d04880fb7 100644
--- a/editor/plugins/debugger_editor_plugin.cpp
+++ b/editor/plugins/debugger_editor_plugin.cpp
@@ -47,7 +47,6 @@ DebuggerEditorPlugin::DebuggerEditorPlugin(PopupMenu *p_debug_menu) {
ED_SHORTCUT("debugger/step_over", TTR("Step Over"), Key::F10);
ED_SHORTCUT("debugger/break", TTR("Break"));
ED_SHORTCUT("debugger/continue", TTR("Continue"), Key::F12);
- ED_SHORTCUT("debugger/keep_debugger_open", TTR("Keep Debugger Open"));
ED_SHORTCUT("debugger/debug_with_external_editor", TTR("Debug with External Editor"));
// File Server for deploy with remote filesystem.
@@ -85,6 +84,9 @@ DebuggerEditorPlugin::DebuggerEditorPlugin(PopupMenu *p_debug_menu) {
debug_menu->add_check_shortcut(ED_SHORTCUT("editor/sync_script_changes", TTR("Synchronize Script Changes")), RUN_RELOAD_SCRIPTS);
debug_menu->set_item_tooltip(-1,
TTR("When this option is enabled, any script that is saved will be reloaded in the running project.\nWhen used remotely on a device, this is more efficient when the network filesystem option is enabled."));
+ debug_menu->add_check_shortcut(ED_SHORTCUT("editor/keep_server_open", TTR("Keep Debug Server Open")), SERVER_KEEP_OPEN);
+ debug_menu->set_item_tooltip(-1,
+ TTR("When this option is enabled, the editor debug server will stay open and listen for new sessions started outside of the editor itself."));
// Multi-instance, start/stop
instances_menu = memnew(PopupMenu);
@@ -176,6 +178,14 @@ void DebuggerEditorPlugin::_menu_option(int p_option) {
EditorSettings::get_singleton()->set_project_metadata("debug_options", "run_reload_scripts", !ischecked);
} break;
+ case SERVER_KEEP_OPEN: {
+ bool ischecked = debug_menu->is_item_checked(debug_menu->get_item_index(SERVER_KEEP_OPEN));
+ debug_menu->set_item_checked(debug_menu->get_item_index(SERVER_KEEP_OPEN), !ischecked);
+
+ EditorDebuggerNode::get_singleton()->set_keep_open(!ischecked);
+ EditorSettings::get_singleton()->set_project_metadata("debug_options", "server_keep_open", !ischecked);
+
+ } break;
}
}
@@ -195,6 +205,7 @@ void DebuggerEditorPlugin::_update_debug_options() {
bool check_debug_navigation = EditorSettings::get_singleton()->get_project_metadata("debug_options", "run_debug_navigation", false);
bool check_live_debug = EditorSettings::get_singleton()->get_project_metadata("debug_options", "run_live_debug", true);
bool check_reload_scripts = EditorSettings::get_singleton()->get_project_metadata("debug_options", "run_reload_scripts", true);
+ bool check_server_keep_open = EditorSettings::get_singleton()->get_project_metadata("debug_options", "server_keep_open", false);
int instances = EditorSettings::get_singleton()->get_project_metadata("debug_options", "run_debug_instances", 1);
if (check_deploy_remote) {
@@ -218,6 +229,9 @@ void DebuggerEditorPlugin::_update_debug_options() {
if (check_reload_scripts) {
_menu_option(RUN_RELOAD_SCRIPTS);
}
+ if (check_server_keep_open) {
+ _menu_option(SERVER_KEEP_OPEN);
+ }
int len = instances_menu->get_item_count();
for (int idx = 0; idx < len; idx++) {
diff --git a/editor/plugins/debugger_editor_plugin.h b/editor/plugins/debugger_editor_plugin.h
index c706acdb5c..5f682ed5e0 100644
--- a/editor/plugins/debugger_editor_plugin.h
+++ b/editor/plugins/debugger_editor_plugin.h
@@ -53,6 +53,7 @@ private:
RUN_DEBUG_NAVIGATION,
RUN_DEPLOY_REMOTE_DEBUG,
RUN_RELOAD_SCRIPTS,
+ SERVER_KEEP_OPEN,
};
void _update_debug_options();
diff --git a/editor/plugins/editor_debugger_plugin.cpp b/editor/plugins/editor_debugger_plugin.cpp
index 4ce3d7cfd5..5dd3038c0e 100644
--- a/editor/plugins/editor_debugger_plugin.cpp
+++ b/editor/plugins/editor_debugger_plugin.cpp
@@ -32,7 +32,7 @@
#include "editor/debugger/script_editor_debugger.h"
-void EditorDebuggerPlugin::_breaked(bool p_really_did, bool p_can_debug, String p_message, bool p_has_stackdump) {
+void EditorDebuggerSession::_breaked(bool p_really_did, bool p_can_debug, String p_message, bool p_has_stackdump) {
if (p_really_did) {
emit_signal(SNAME("breaked"), p_can_debug);
} else {
@@ -40,22 +40,22 @@ void EditorDebuggerPlugin::_breaked(bool p_really_did, bool p_can_debug, String
}
}
-void EditorDebuggerPlugin::_started() {
+void EditorDebuggerSession::_started() {
emit_signal(SNAME("started"));
}
-void EditorDebuggerPlugin::_stopped() {
+void EditorDebuggerSession::_stopped() {
emit_signal(SNAME("stopped"));
}
-void EditorDebuggerPlugin::_bind_methods() {
- ClassDB::bind_method(D_METHOD("send_message", "message", "data"), &EditorDebuggerPlugin::send_message);
- ClassDB::bind_method(D_METHOD("register_message_capture", "name", "callable"), &EditorDebuggerPlugin::register_message_capture);
- ClassDB::bind_method(D_METHOD("unregister_message_capture", "name"), &EditorDebuggerPlugin::unregister_message_capture);
- ClassDB::bind_method(D_METHOD("has_capture", "name"), &EditorDebuggerPlugin::has_capture);
- ClassDB::bind_method(D_METHOD("is_breaked"), &EditorDebuggerPlugin::is_breaked);
- ClassDB::bind_method(D_METHOD("is_debuggable"), &EditorDebuggerPlugin::is_debuggable);
- ClassDB::bind_method(D_METHOD("is_session_active"), &EditorDebuggerPlugin::is_session_active);
+void EditorDebuggerSession::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("send_message", "message", "data"), &EditorDebuggerSession::send_message, DEFVAL(Array()));
+ ClassDB::bind_method(D_METHOD("toggle_profiler", "profiler", "enable", "data"), &EditorDebuggerSession::toggle_profiler, DEFVAL(Array()));
+ ClassDB::bind_method(D_METHOD("is_breaked"), &EditorDebuggerSession::is_breaked);
+ ClassDB::bind_method(D_METHOD("is_debuggable"), &EditorDebuggerSession::is_debuggable);
+ ClassDB::bind_method(D_METHOD("is_active"), &EditorDebuggerSession::is_active);
+ ClassDB::bind_method(D_METHOD("add_session_tab", "control"), &EditorDebuggerSession::add_session_tab);
+ ClassDB::bind_method(D_METHOD("remove_session_tab", "control"), &EditorDebuggerSession::remove_session_tab);
ADD_SIGNAL(MethodInfo("started"));
ADD_SIGNAL(MethodInfo("stopped"));
@@ -63,62 +63,131 @@ void EditorDebuggerPlugin::_bind_methods() {
ADD_SIGNAL(MethodInfo("continued"));
}
-void EditorDebuggerPlugin::attach_debugger(ScriptEditorDebugger *p_debugger) {
- debugger = p_debugger;
- if (debugger) {
- debugger->connect("started", callable_mp(this, &EditorDebuggerPlugin::_started));
- debugger->connect("stopped", callable_mp(this, &EditorDebuggerPlugin::_stopped));
- debugger->connect("breaked", callable_mp(this, &EditorDebuggerPlugin::_breaked));
- }
+void EditorDebuggerSession::add_session_tab(Control *p_tab) {
+ ERR_FAIL_COND(!p_tab || !debugger);
+ debugger->add_debugger_tab(p_tab);
+ tabs.insert(p_tab);
}
-void EditorDebuggerPlugin::detach_debugger(bool p_call_debugger) {
- if (debugger) {
- debugger->disconnect("started", callable_mp(this, &EditorDebuggerPlugin::_started));
- debugger->disconnect("stopped", callable_mp(this, &EditorDebuggerPlugin::_stopped));
- debugger->disconnect("breaked", callable_mp(this, &EditorDebuggerPlugin::_breaked));
- if (p_call_debugger && get_script_instance()) {
- debugger->remove_debugger_plugin(get_script_instance()->get_script());
- }
- debugger = nullptr;
- }
+void EditorDebuggerSession::remove_session_tab(Control *p_tab) {
+ ERR_FAIL_COND(!p_tab || !debugger);
+ debugger->remove_debugger_tab(p_tab);
+ tabs.erase(p_tab);
}
-void EditorDebuggerPlugin::send_message(const String &p_message, const Array &p_args) {
+void EditorDebuggerSession::send_message(const String &p_message, const Array &p_args) {
ERR_FAIL_COND_MSG(!debugger, "Plugin is not attached to debugger");
debugger->send_message(p_message, p_args);
}
-void EditorDebuggerPlugin::register_message_capture(const StringName &p_name, const Callable &p_callable) {
+void EditorDebuggerSession::toggle_profiler(const String &p_profiler, bool p_enable, const Array &p_data) {
ERR_FAIL_COND_MSG(!debugger, "Plugin is not attached to debugger");
- debugger->register_message_capture(p_name, p_callable);
+ debugger->toggle_profiler(p_profiler, p_enable, p_data);
}
-void EditorDebuggerPlugin::unregister_message_capture(const StringName &p_name) {
- ERR_FAIL_COND_MSG(!debugger, "Plugin is not attached to debugger");
- debugger->unregister_message_capture(p_name);
-}
-
-bool EditorDebuggerPlugin::has_capture(const StringName &p_name) {
- ERR_FAIL_COND_V_MSG(!debugger, false, "Plugin is not attached to debugger");
- return debugger->has_capture(p_name);
-}
-
-bool EditorDebuggerPlugin::is_breaked() {
+bool EditorDebuggerSession::is_breaked() {
ERR_FAIL_COND_V_MSG(!debugger, false, "Plugin is not attached to debugger");
return debugger->is_breaked();
}
-bool EditorDebuggerPlugin::is_debuggable() {
+bool EditorDebuggerSession::is_debuggable() {
ERR_FAIL_COND_V_MSG(!debugger, false, "Plugin is not attached to debugger");
return debugger->is_debuggable();
}
-bool EditorDebuggerPlugin::is_session_active() {
+bool EditorDebuggerSession::is_active() {
ERR_FAIL_COND_V_MSG(!debugger, false, "Plugin is not attached to debugger");
return debugger->is_session_active();
}
+void EditorDebuggerSession::detach_debugger() {
+ if (!debugger) {
+ return;
+ }
+ debugger->disconnect("started", callable_mp(this, &EditorDebuggerSession::_started));
+ debugger->disconnect("stopped", callable_mp(this, &EditorDebuggerSession::_stopped));
+ debugger->disconnect("breaked", callable_mp(this, &EditorDebuggerSession::_breaked));
+ debugger->disconnect("tree_exited", callable_mp(this, &EditorDebuggerSession::_debugger_gone_away));
+ for (Control *tab : tabs) {
+ debugger->remove_debugger_tab(tab);
+ }
+ tabs.clear();
+ debugger = nullptr;
+}
+
+void EditorDebuggerSession::_debugger_gone_away() {
+ debugger = nullptr;
+ tabs.clear();
+}
+
+EditorDebuggerSession::EditorDebuggerSession(ScriptEditorDebugger *p_debugger) {
+ ERR_FAIL_COND(!p_debugger);
+ debugger = p_debugger;
+ debugger->connect("started", callable_mp(this, &EditorDebuggerSession::_started));
+ debugger->connect("stopped", callable_mp(this, &EditorDebuggerSession::_stopped));
+ debugger->connect("breaked", callable_mp(this, &EditorDebuggerSession::_breaked));
+ debugger->connect("tree_exited", callable_mp(this, &EditorDebuggerSession::_debugger_gone_away), CONNECT_ONE_SHOT);
+}
+
+EditorDebuggerSession::~EditorDebuggerSession() {
+ detach_debugger();
+}
+
+/// EditorDebuggerPlugin
+
EditorDebuggerPlugin::~EditorDebuggerPlugin() {
- detach_debugger(true);
+ clear();
+}
+
+void EditorDebuggerPlugin::clear() {
+ for (int i = 0; i < sessions.size(); i++) {
+ sessions[i]->detach_debugger();
+ }
+ sessions.clear();
+}
+
+void EditorDebuggerPlugin::create_session(ScriptEditorDebugger *p_debugger) {
+ sessions.push_back(Ref<EditorDebuggerSession>(memnew(EditorDebuggerSession(p_debugger))));
+ setup_session(sessions.size() - 1);
+}
+
+void EditorDebuggerPlugin::setup_session(int p_idx) {
+ GDVIRTUAL_CALL(_setup_session, p_idx);
+}
+
+Ref<EditorDebuggerSession> EditorDebuggerPlugin::get_session(int p_idx) {
+ ERR_FAIL_INDEX_V(p_idx, sessions.size(), nullptr);
+ return sessions[p_idx];
+}
+
+Array EditorDebuggerPlugin::get_sessions() {
+ Array ret;
+ for (int i = 0; i < sessions.size(); i++) {
+ ret.push_back(sessions[i]);
+ }
+ return ret;
+}
+
+bool EditorDebuggerPlugin::has_capture(const String &p_message) const {
+ bool ret = false;
+ if (GDVIRTUAL_CALL(_has_capture, p_message, ret)) {
+ return ret;
+ }
+ return false;
+}
+
+bool EditorDebuggerPlugin::capture(const String &p_message, const Array &p_data, int p_session_id) {
+ bool ret = false;
+ if (GDVIRTUAL_CALL(_capture, p_message, p_data, p_session_id, ret)) {
+ return ret;
+ }
+ return false;
+}
+
+void EditorDebuggerPlugin::_bind_methods() {
+ GDVIRTUAL_BIND(_setup_session, "session_id");
+ GDVIRTUAL_BIND(_has_capture, "capture");
+ GDVIRTUAL_BIND(_capture, "message", "data", "session_id");
+ ClassDB::bind_method(D_METHOD("get_session", "id"), &EditorDebuggerPlugin::get_session);
+ ClassDB::bind_method(D_METHOD("get_sessions"), &EditorDebuggerPlugin::get_sessions);
}
diff --git a/editor/plugins/editor_debugger_plugin.h b/editor/plugins/editor_debugger_plugin.h
index b602c36912..46f8f17cc2 100644
--- a/editor/plugins/editor_debugger_plugin.h
+++ b/editor/plugins/editor_debugger_plugin.h
@@ -35,29 +35,62 @@
class ScriptEditorDebugger;
-class EditorDebuggerPlugin : public Control {
- GDCLASS(EditorDebuggerPlugin, Control);
+class EditorDebuggerSession : public RefCounted {
+ GDCLASS(EditorDebuggerSession, RefCounted);
private:
+ HashSet<Control *> tabs;
+
ScriptEditorDebugger *debugger = nullptr;
void _breaked(bool p_really_did, bool p_can_debug, String p_message, bool p_has_stackdump);
void _started();
void _stopped();
+ void _debugger_gone_away();
protected:
static void _bind_methods();
public:
- void attach_debugger(ScriptEditorDebugger *p_debugger);
- void detach_debugger(bool p_call_debugger);
- void send_message(const String &p_message, const Array &p_args);
- void register_message_capture(const StringName &p_name, const Callable &p_callable);
- void unregister_message_capture(const StringName &p_name);
- bool has_capture(const StringName &p_name);
+ void detach_debugger();
+
+ void add_session_tab(Control *p_tab);
+ void remove_session_tab(Control *p_tab);
+ void send_message(const String &p_message, const Array &p_args = Array());
+ void toggle_profiler(const String &p_profiler, bool p_enable, const Array &p_data = Array());
bool is_breaked();
bool is_debuggable();
- bool is_session_active();
+ bool is_active();
+
+ EditorDebuggerSession(ScriptEditorDebugger *p_debugger);
+ ~EditorDebuggerSession();
+};
+
+class EditorDebuggerPlugin : public RefCounted {
+ GDCLASS(EditorDebuggerPlugin, RefCounted);
+
+private:
+ List<Ref<EditorDebuggerSession>> sessions;
+
+protected:
+ static void _bind_methods();
+
+public:
+ void create_session(ScriptEditorDebugger *p_debugger);
+ void clear();
+
+ virtual void setup_session(int p_idx);
+ virtual bool capture(const String &p_message, const Array &p_data, int p_session);
+ virtual bool has_capture(const String &p_capture) const;
+
+ Ref<EditorDebuggerSession> get_session(int p_session_id);
+ Array get_sessions();
+
+ GDVIRTUAL3R(bool, _capture, const String &, const Array &, int);
+ GDVIRTUAL1RC(bool, _has_capture, const String &);
+ GDVIRTUAL1(_setup_session, int);
+
+ EditorDebuggerPlugin() {}
~EditorDebuggerPlugin();
};
diff --git a/editor/plugins/editor_preview_plugins.h b/editor/plugins/editor_preview_plugins.h
index efb2c80cfd..0f8ed1c857 100644
--- a/editor/plugins/editor_preview_plugins.h
+++ b/editor/plugins/editor_preview_plugins.h
@@ -70,10 +70,12 @@ public:
};
class EditorPackedScenePreviewPlugin : public EditorResourcePreviewGenerator {
+ GDCLASS(EditorPackedScenePreviewPlugin, EditorResourcePreviewGenerator);
+
public:
- virtual bool handles(const String &p_type) const;
- virtual Ref<Texture2D> generate(const Ref<Resource> &p_from, const Size2 &p_size) const;
- virtual Ref<Texture2D> generate_from_path(const String &p_path, const Size2 &p_size) const;
+ virtual bool handles(const String &p_type) const override;
+ virtual Ref<Texture2D> generate(const Ref<Resource> &p_from, const Size2 &p_size) const override;
+ virtual Ref<Texture2D> generate_from_path(const String &p_path, const Size2 &p_size) const override;
EditorPackedScenePreviewPlugin();
};
@@ -107,17 +109,21 @@ public:
};
class EditorScriptPreviewPlugin : public EditorResourcePreviewGenerator {
+ GDCLASS(EditorScriptPreviewPlugin, EditorResourcePreviewGenerator);
+
public:
- virtual bool handles(const String &p_type) const;
- virtual Ref<Texture2D> generate(const Ref<Resource> &p_from, const Size2 &p_size) const;
+ virtual bool handles(const String &p_type) const override;
+ virtual Ref<Texture2D> generate(const Ref<Resource> &p_from, const Size2 &p_size) const override;
EditorScriptPreviewPlugin();
};
class EditorAudioStreamPreviewPlugin : public EditorResourcePreviewGenerator {
+ GDCLASS(EditorAudioStreamPreviewPlugin, EditorResourcePreviewGenerator);
+
public:
- virtual bool handles(const String &p_type) const;
- virtual Ref<Texture2D> generate(const Ref<Resource> &p_from, const Size2 &p_size) const;
+ virtual bool handles(const String &p_type) const override;
+ virtual Ref<Texture2D> generate(const Ref<Resource> &p_from, const Size2 &p_size) const override;
EditorAudioStreamPreviewPlugin();
};
diff --git a/editor/plugins/font_config_plugin.cpp b/editor/plugins/font_config_plugin.cpp
index 33992314b0..6b3db095d4 100644
--- a/editor/plugins/font_config_plugin.cpp
+++ b/editor/plugins/font_config_plugin.cpp
@@ -31,6 +31,7 @@
#include "font_config_plugin.h"
#include "editor/editor_scale.h"
+#include "editor/editor_settings.h"
#include "editor/import/dynamic_font_import_settings.h"
/*************************************************************************/
@@ -482,7 +483,7 @@ void EditorPropertyOTVariation::update_property() {
Vector3i range = supported.get_value_at_index(i);
EditorPropertyInteger *prop = memnew(EditorPropertyInteger);
- prop->setup(range.x, range.y, 1, false, false);
+ prop->setup(range.x, range.y, false, 1, false, false);
prop->set_object_and_property(object.ptr(), "keys/" + itos(name_tag));
String name = TS->tag_to_name(name_tag);
@@ -761,7 +762,7 @@ void EditorPropertyOTFeatures::update_property() {
} break;
case Variant::INT: {
EditorPropertyInteger *editor = memnew(EditorPropertyInteger);
- editor->setup(0, 255, 1, false, false);
+ editor->setup(0, 255, 1, false, false, false);
prop = editor;
} break;
default: {
diff --git a/editor/plugins/gdextension_export_plugin.h b/editor/plugins/gdextension_export_plugin.h
index c5f7d2a047..41edf9ac75 100644
--- a/editor/plugins/gdextension_export_plugin.h
+++ b/editor/plugins/gdextension_export_plugin.h
@@ -40,7 +40,7 @@ protected:
};
void GDExtensionExportPlugin::_export_file(const String &p_path, const String &p_type, const HashSet<String> &p_features) {
- if (p_type != "NativeExtension") {
+ if (p_type != "GDExtension") {
return;
}
@@ -54,60 +54,38 @@ void GDExtensionExportPlugin::_export_file(const String &p_path, const String &p
String entry_symbol = config->get_value("configuration", "entry_symbol");
- List<String> libraries;
-
- config->get_section_keys("libraries", &libraries);
-
- bool could_export = false;
- for (const String &E : libraries) {
- Vector<String> tags = E.split(".");
- bool all_tags_met = true;
- for (int i = 0; i < tags.size(); i++) {
- String tag = tags[i].strip_edges();
- if (!p_features.has(tag)) {
- all_tags_met = false;
- break;
- }
- }
-
- if (all_tags_met) {
- String library_path = config->get_value("libraries", E);
- if (!library_path.begins_with("res://")) {
- print_line("Skipping export of out-of-project library " + library_path);
- continue;
- }
- add_shared_object(library_path, tags);
-
- if (p_features.has("iOS") && (library_path.ends_with(".a") || library_path.ends_with(".xcframework"))) {
- String additional_code = "extern void register_dynamic_symbol(char *name, void *address);\n"
- "extern void add_ios_init_callback(void (*cb)());\n"
- "\n"
- "extern \"C\" void $ENTRY();\n"
- "void $ENTRY_init() {\n"
- " if (&$ENTRY) register_dynamic_symbol((char *)\"$ENTRY\", (void *)$ENTRY);\n"
- "}\n"
- "struct $ENTRY_struct {\n"
- " $ENTRY_struct() {\n"
- " add_ios_init_callback($ENTRY_init);\n"
- " }\n"
- "};\n"
- "$ENTRY_struct $ENTRY_struct_instance;\n\n";
- additional_code = additional_code.replace("$ENTRY", entry_symbol);
- add_ios_cpp_code(additional_code);
-
- String linker_flags = "-Wl,-U,_" + entry_symbol;
- add_ios_linker_flags(linker_flags);
- }
- could_export = true;
- break;
+ PackedStringArray tags;
+ String library_path = GDExtension::find_extension_library(
+ p_path, config, [p_features](String p_feature) { return p_features.has(p_feature); }, &tags);
+ if (!library_path.is_empty()) {
+ add_shared_object(library_path, tags);
+
+ if (p_features.has("iOS") && (library_path.ends_with(".a") || library_path.ends_with(".xcframework"))) {
+ String additional_code = "extern void register_dynamic_symbol(char *name, void *address);\n"
+ "extern void add_ios_init_callback(void (*cb)());\n"
+ "\n"
+ "extern \"C\" void $ENTRY();\n"
+ "void $ENTRY_init() {\n"
+ " if (&$ENTRY) register_dynamic_symbol((char *)\"$ENTRY\", (void *)$ENTRY);\n"
+ "}\n"
+ "struct $ENTRY_struct {\n"
+ " $ENTRY_struct() {\n"
+ " add_ios_init_callback($ENTRY_init);\n"
+ " }\n"
+ "};\n"
+ "$ENTRY_struct $ENTRY_struct_instance;\n\n";
+ additional_code = additional_code.replace("$ENTRY", entry_symbol);
+ add_ios_cpp_code(additional_code);
+
+ String linker_flags = "-Wl,-U,_" + entry_symbol;
+ add_ios_linker_flags(linker_flags);
}
- }
- if (!could_export) {
- Vector<String> tags;
+ } else {
+ Vector<String> features_vector;
for (const String &E : p_features) {
- tags.append(E);
+ features_vector.append(E);
}
- ERR_FAIL_MSG(vformat("No suitable library found. The libraries' tags referred to an invalid feature flag. Possible feature flags for your platform: %s", p_path, String(", ").join(tags)));
+ ERR_FAIL_MSG(vformat("No suitable library found for GDExtension: %s. Possible feature flags for your platform: %s", p_path, String(", ").join(features_vector)));
}
List<String> dependencies;
@@ -115,11 +93,11 @@ void GDExtensionExportPlugin::_export_file(const String &p_path, const String &p
config->get_section_keys("dependencies", &dependencies);
}
- for (const String &E : libraries) {
- Vector<String> tags = E.split(".");
+ for (const String &E : dependencies) {
+ Vector<String> dependency_tags = E.split(".");
bool all_tags_met = true;
- for (int i = 0; i < tags.size(); i++) {
- String tag = tags[i].strip_edges();
+ for (int i = 0; i < dependency_tags.size(); i++) {
+ String tag = dependency_tags[i].strip_edges();
if (!p_features.has(tag)) {
all_tags_met = false;
break;
@@ -129,13 +107,12 @@ void GDExtensionExportPlugin::_export_file(const String &p_path, const String &p
if (all_tags_met) {
Dictionary dependency = config->get_value("dependencies", E);
for (const Variant *key = dependency.next(nullptr); key; key = dependency.next(key)) {
- String library_path = *key;
+ String dependency_path = *key;
String target_path = dependency[*key];
- if (!library_path.begins_with("res://")) {
- print_line("Skipping export of out-of-project library " + library_path);
- continue;
+ if (dependency_path.is_relative_path()) {
+ dependency_path = p_path.get_base_dir().path_join(dependency_path);
}
- add_shared_object(library_path, tags, target_path);
+ add_shared_object(dependency_path, dependency_tags, target_path);
}
break;
}
diff --git a/editor/plugins/gpu_particles_2d_editor_plugin.cpp b/editor/plugins/gpu_particles_2d_editor_plugin.cpp
index 891b9efa4f..0fa3efba9a 100644
--- a/editor/plugins/gpu_particles_2d_editor_plugin.cpp
+++ b/editor/plugins/gpu_particles_2d_editor_plugin.cpp
@@ -37,6 +37,7 @@
#include "editor/editor_undo_redo_manager.h"
#include "editor/scene_tree_dock.h"
#include "scene/2d/cpu_particles_2d.h"
+#include "scene/gui/menu_button.h"
#include "scene/gui/separator.h"
#include "scene/resources/particle_process_material.h"
@@ -160,6 +161,7 @@ void GPUParticles2DEditorPlugin::_generate_visibility_rect() {
particles->set_emitting(false);
}
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Generate Visibility Rect"));
undo_redo->add_do_method(particles, "set_visibility_rect", rect);
undo_redo->add_undo_method(particles, "set_visibility_rect", particles->get_visibility_rect());
@@ -359,7 +361,6 @@ void GPUParticles2DEditorPlugin::_bind_methods() {
GPUParticles2DEditorPlugin::GPUParticles2DEditorPlugin() {
particles = nullptr;
- undo_redo = EditorNode::get_singleton()->get_undo_redo();
toolbar = memnew(HBoxContainer);
add_control_to_container(CONTAINER_CANVAS_EDITOR_MENU, toolbar);
diff --git a/editor/plugins/gpu_particles_2d_editor_plugin.h b/editor/plugins/gpu_particles_2d_editor_plugin.h
index 0229b57c10..34cadaf7de 100644
--- a/editor/plugins/gpu_particles_2d_editor_plugin.h
+++ b/editor/plugins/gpu_particles_2d_editor_plugin.h
@@ -37,8 +37,11 @@
#include "scene/gui/box_container.h"
#include "scene/gui/spin_box.h"
+class CheckBox;
+class ConfirmationDialog;
class EditorFileDialog;
-class EditorUndoRedoManager;
+class MenuButton;
+class OptionButton;
class GPUParticles2DEditorPlugin : public EditorPlugin {
GDCLASS(GPUParticles2DEditorPlugin, EditorPlugin);
@@ -76,7 +79,6 @@ class GPUParticles2DEditorPlugin : public EditorPlugin {
String source_emission_file;
- Ref<EditorUndoRedoManager> undo_redo;
void _file_selected(const String &p_file);
void _menu_callback(int p_idx);
void _generate_visibility_rect();
diff --git a/editor/plugins/gpu_particles_3d_editor_plugin.cpp b/editor/plugins/gpu_particles_3d_editor_plugin.cpp
index db3a46d1f1..b2878244d0 100644
--- a/editor/plugins/gpu_particles_3d_editor_plugin.cpp
+++ b/editor/plugins/gpu_particles_3d_editor_plugin.cpp
@@ -36,6 +36,8 @@
#include "editor/plugins/node_3d_editor_plugin.h"
#include "editor/scene_tree_dock.h"
#include "scene/3d/cpu_particles_3d.h"
+#include "scene/3d/mesh_instance_3d.h"
+#include "scene/gui/menu_button.h"
#include "scene/resources/particle_process_material.h"
bool GPUParticles3DEditorBase::_generate(Vector<Vector3> &points, Vector<Vector3> &normals) {
diff --git a/editor/plugins/gpu_particles_3d_editor_plugin.h b/editor/plugins/gpu_particles_3d_editor_plugin.h
index 17bdfa6e3f..e5b264cfe4 100644
--- a/editor/plugins/gpu_particles_3d_editor_plugin.h
+++ b/editor/plugins/gpu_particles_3d_editor_plugin.h
@@ -35,6 +35,10 @@
#include "scene/3d/gpu_particles_3d.h"
#include "scene/gui/spin_box.h"
+class ConfirmationDialog;
+class HBoxContainer;
+class MenuButton;
+class OptionButton;
class SceneTreeDialog;
class GPUParticles3DEditorBase : public Control {
diff --git a/editor/plugins/gpu_particles_collision_sdf_editor_plugin.h b/editor/plugins/gpu_particles_collision_sdf_editor_plugin.h
index 684279039a..2c1f49df29 100644
--- a/editor/plugins/gpu_particles_collision_sdf_editor_plugin.h
+++ b/editor/plugins/gpu_particles_collision_sdf_editor_plugin.h
@@ -37,6 +37,7 @@
struct EditorProgress;
class EditorFileDialog;
+class HBoxContainer;
class GPUParticlesCollisionSDF3DEditorPlugin : public EditorPlugin {
GDCLASS(GPUParticlesCollisionSDF3DEditorPlugin, EditorPlugin);
diff --git a/editor/plugins/gradient_editor.cpp b/editor/plugins/gradient_editor.cpp
index 7039ada10a..c466a82f7d 100644
--- a/editor/plugins/gradient_editor.cpp
+++ b/editor/plugins/gradient_editor.cpp
@@ -57,7 +57,7 @@ int GradientEditor::_get_point_from_pos(int x) {
for (int i = 0; i < points.size(); i++) {
// Check if we clicked at point.
float distance = ABS(x - points[i].offset * total_w);
- float min = (draw_point_width / 2 * 1.7); //make it easier to grab
+ float min = (handle_width / 2 * 1.7); // Make it easier to grab.
if (distance <= min && distance < min_distance) {
result = i;
min_distance = distance;
@@ -203,6 +203,7 @@ void GradientEditor::gui_input(const Ref<InputEvent> &p_event) {
grabbed = _get_point_from_pos(mb->get_position().x);
_show_color_picker();
accept_event();
+ return;
}
// Delete point on right click.
@@ -396,7 +397,7 @@ void GradientEditor::_notification(int p_what) {
}
case NOTIFICATION_THEME_CHANGED: {
draw_spacing = BASE_SPACING * get_theme_default_base_scale();
- draw_point_width = BASE_POINT_WIDTH * get_theme_default_base_scale();
+ handle_width = BASE_HANDLE_WIDTH * get_theme_default_base_scale();
} break;
case NOTIFICATION_DRAW: {
@@ -407,32 +408,38 @@ void GradientEditor::_notification(int p_what) {
return; // Safety check. We have division by 'h'. And in any case there is nothing to draw with such size.
}
- int total_w = get_size().width - get_size().height - draw_spacing;
+ int total_w = get_size().width - get_size().height - draw_spacing - handle_width;
// Draw checker pattern for ramp.
- draw_texture_rect(get_theme_icon(SNAME("GuiMiniCheckerboard"), SNAME("EditorIcons")), Rect2(0, 0, total_w, h), true);
+ draw_texture_rect(get_theme_icon(SNAME("GuiMiniCheckerboard"), SNAME("EditorIcons")), Rect2(handle_width / 2, 0, total_w, h), true);
// Draw color ramp.
gradient_cache->set_points(points);
gradient_cache->set_interpolation_mode(interpolation_mode);
preview_texture->set_gradient(gradient_cache);
- draw_texture_rect(preview_texture, Rect2(0, 0, total_w, h));
+ draw_texture_rect(preview_texture, Rect2(handle_width / 2, 0, total_w, h));
+
+ // Draw borders around color ramp if in focus.
+ if (has_focus()) {
+ draw_rect(Rect2(handle_width / 2, 0, total_w, h), Color(1, 1, 1, 0.9), false);
+ }
// Draw point markers.
for (int i = 0; i < points.size(); i++) {
- Color col = points[i].color.inverted();
+ Color col = points[i].color.get_v() > 0.5 ? Color(0, 0, 0) : Color(1, 1, 1);
col.a = 0.9;
- draw_line(Vector2(points[i].offset * total_w, 0), Vector2(points[i].offset * total_w, h / 2), col);
- Rect2 rect = Rect2(points[i].offset * total_w - draw_point_width / 2, h / 2, draw_point_width, h / 2);
+ draw_line(Vector2(points[i].offset * total_w + handle_width / 2, 0), Vector2(points[i].offset * total_w + handle_width / 2, h / 2), col);
+ Rect2 rect = Rect2(points[i].offset * total_w, h / 2, handle_width, h / 2);
draw_rect(rect, points[i].color, true);
draw_rect(rect, col, false);
if (grabbed == i) {
+ const Color focus_color = get_theme_color(SNAME("accent_color"), SNAME("Editor"));
rect = rect.grow(-1);
if (has_focus()) {
- draw_rect(rect, Color(1, 0, 0, 0.9), false);
+ draw_rect(rect, focus_color, false);
} else {
- draw_rect(rect, Color(0.6, 0, 0, 0.9), false);
+ draw_rect(rect, focus_color.darkened(0.4), false);
}
rect = rect.grow(-1);
@@ -441,23 +448,16 @@ void GradientEditor::_notification(int p_what) {
}
// Draw "button" for color selector.
- draw_texture_rect(get_theme_icon(SNAME("GuiMiniCheckerboard"), SNAME("EditorIcons")), Rect2(total_w + draw_spacing, 0, h, h), true);
+ int button_offset = total_w + handle_width + draw_spacing;
+ draw_texture_rect(get_theme_icon(SNAME("GuiMiniCheckerboard"), SNAME("EditorIcons")), Rect2(button_offset, 0, h, h), true);
if (grabbed != -1) {
// Draw with selection color.
- draw_rect(Rect2(total_w + draw_spacing, 0, h, h), points[grabbed].color);
+ draw_rect(Rect2(button_offset, 0, h, h), points[grabbed].color);
} else {
// If no color selected draw grey color with 'X' on top.
- draw_rect(Rect2(total_w + draw_spacing, 0, h, h), Color(0.5, 0.5, 0.5, 1));
- draw_line(Vector2(total_w + draw_spacing, 0), Vector2(total_w + draw_spacing + h, h), Color(1, 1, 1, 0.6));
- draw_line(Vector2(total_w + draw_spacing, h), Vector2(total_w + draw_spacing + h, 0), Color(1, 1, 1, 0.6));
- }
-
- // Draw borders around color ramp if in focus.
- if (has_focus()) {
- draw_line(Vector2(-1, -1), Vector2(total_w + 1, -1), Color(1, 1, 1, 0.6));
- draw_line(Vector2(total_w + 1, -1), Vector2(total_w + 1, h + 1), Color(1, 1, 1, 0.6));
- draw_line(Vector2(total_w + 1, h + 1), Vector2(-1, h + 1), Color(1, 1, 1, 0.6));
- draw_line(Vector2(-1, -1), Vector2(-1, h + 1), Color(1, 1, 1, 0.6));
+ draw_rect(Rect2(button_offset, 0, h, h), Color(0.5, 0.5, 0.5, 1));
+ draw_line(Vector2(button_offset, 0), Vector2(button_offset + h, h), Color(1, 1, 1, 0.6));
+ draw_line(Vector2(button_offset, h), Vector2(button_offset + h, 0), Color(1, 1, 1, 0.6));
}
} break;
diff --git a/editor/plugins/gradient_editor.h b/editor/plugins/gradient_editor.h
index 816b539ba2..f27cd8a188 100644
--- a/editor/plugins/gradient_editor.h
+++ b/editor/plugins/gradient_editor.h
@@ -53,10 +53,10 @@ class GradientEditor : public Control {
// Make sure to use the scaled value below.
const int BASE_SPACING = 3;
- const int BASE_POINT_WIDTH = 8;
+ const int BASE_HANDLE_WIDTH = 8;
int draw_spacing = BASE_SPACING;
- int draw_point_width = BASE_POINT_WIDTH;
+ int handle_width = BASE_HANDLE_WIDTH;
void _gradient_changed();
void _ramp_changed();
diff --git a/editor/plugins/gradient_editor_plugin.h b/editor/plugins/gradient_editor_plugin.h
index ab191d83e2..f3859e74d3 100644
--- a/editor/plugins/gradient_editor_plugin.h
+++ b/editor/plugins/gradient_editor_plugin.h
@@ -31,6 +31,7 @@
#ifndef GRADIENT_EDITOR_PLUGIN_H
#define GRADIENT_EDITOR_PLUGIN_H
+#include "editor/editor_inspector.h"
#include "editor/editor_plugin.h"
#include "gradient_editor.h"
diff --git a/editor/plugins/gradient_texture_2d_editor_plugin.cpp b/editor/plugins/gradient_texture_2d_editor_plugin.cpp
index 561dca4fc6..0591288c6e 100644
--- a/editor/plugins/gradient_texture_2d_editor_plugin.cpp
+++ b/editor/plugins/gradient_texture_2d_editor_plugin.cpp
@@ -55,6 +55,7 @@ void GradientTexture2DEditorRect::_update_fill_position() {
String property_name = handle == HANDLE_FILL_FROM ? "fill_from" : "fill_to";
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(vformat(TTR("Set %s"), property_name), UndoRedo::MERGE_ENDS);
undo_redo->add_do_property(texture.ptr(), property_name, percent);
undo_redo->add_undo_property(texture.ptr(), property_name, handle == HANDLE_FILL_FROM ? texture->get_fill_from() : texture->get_fill_to());
@@ -175,8 +176,6 @@ void GradientTexture2DEditorRect::_notification(int p_what) {
}
GradientTexture2DEditorRect::GradientTexture2DEditorRect() {
- undo_redo = EditorNode::get_undo_redo();
-
checkerboard = memnew(TextureRect);
checkerboard->set_stretch_mode(TextureRect::STRETCH_TILE);
checkerboard->set_ignore_texture_size(true);
@@ -189,6 +188,7 @@ GradientTexture2DEditorRect::GradientTexture2DEditorRect() {
///////////////////////
void GradientTexture2DEditor::_reverse_button_pressed() {
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Swap GradientTexture2D Fill Points"));
undo_redo->add_do_property(texture.ptr(), "fill_from", texture->get_fill_to());
undo_redo->add_do_property(texture.ptr(), "fill_to", texture->get_fill_from());
@@ -223,8 +223,6 @@ void GradientTexture2DEditor::_notification(int p_what) {
}
GradientTexture2DEditor::GradientTexture2DEditor() {
- undo_redo = EditorNode::get_undo_redo();
-
HFlowContainer *toolbar = memnew(HFlowContainer);
add_child(toolbar);
diff --git a/editor/plugins/gradient_texture_2d_editor_plugin.h b/editor/plugins/gradient_texture_2d_editor_plugin.h
index 9faf33152a..3172944ea8 100644
--- a/editor/plugins/gradient_texture_2d_editor_plugin.h
+++ b/editor/plugins/gradient_texture_2d_editor_plugin.h
@@ -31,11 +31,10 @@
#ifndef GRADIENT_TEXTURE_2D_EDITOR_PLUGIN_H
#define GRADIENT_TEXTURE_2D_EDITOR_PLUGIN_H
+#include "editor/editor_inspector.h"
#include "editor/editor_plugin.h"
#include "editor/editor_spin_slider.h"
-class EditorUndoRedoManager;
-
class GradientTexture2DEditorRect : public Control {
GDCLASS(GradientTexture2DEditorRect, Control);
@@ -46,7 +45,6 @@ class GradientTexture2DEditorRect : public Control {
};
Ref<GradientTexture2D> texture;
- Ref<EditorUndoRedoManager> undo_redo;
bool snap_enabled = false;
float snap_size = 0;
@@ -76,7 +74,6 @@ class GradientTexture2DEditor : public VBoxContainer {
GDCLASS(GradientTexture2DEditor, VBoxContainer);
Ref<GradientTexture2D> texture;
- Ref<EditorUndoRedoManager> undo_redo;
Button *reverse_button = nullptr;
Button *snap_button = nullptr;
diff --git a/editor/plugins/material_editor_plugin.cpp b/editor/plugins/material_editor_plugin.cpp
index fe7713f175..759c1c967d 100644
--- a/editor/plugins/material_editor_plugin.cpp
+++ b/editor/plugins/material_editor_plugin.cpp
@@ -72,15 +72,15 @@ void MaterialEditor::_update_theme_item_cache() {
void MaterialEditor::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_THEME_CHANGED: {
- light_1_switch->set_normal_texture(theme_cache.light_1_on);
- light_1_switch->set_pressed_texture(theme_cache.light_1_off);
- light_2_switch->set_normal_texture(theme_cache.light_2_on);
- light_2_switch->set_pressed_texture(theme_cache.light_2_off);
-
- sphere_switch->set_normal_texture(theme_cache.sphere_off);
- sphere_switch->set_pressed_texture(theme_cache.sphere_on);
- box_switch->set_normal_texture(theme_cache.box_off);
- box_switch->set_pressed_texture(theme_cache.box_on);
+ light_1_switch->set_texture_normal(theme_cache.light_1_on);
+ light_1_switch->set_texture_pressed(theme_cache.light_1_off);
+ light_2_switch->set_texture_normal(theme_cache.light_2_on);
+ light_2_switch->set_texture_pressed(theme_cache.light_2_off);
+
+ sphere_switch->set_texture_normal(theme_cache.sphere_off);
+ sphere_switch->set_texture_pressed(theme_cache.sphere_on);
+ box_switch->set_texture_normal(theme_cache.box_off);
+ box_switch->set_texture_pressed(theme_cache.box_on);
} break;
case NOTIFICATION_DRAW: {
diff --git a/editor/plugins/material_editor_plugin.h b/editor/plugins/material_editor_plugin.h
index 8e64434d8b..7d7d41785b 100644
--- a/editor/plugins/material_editor_plugin.h
+++ b/editor/plugins/material_editor_plugin.h
@@ -31,6 +31,7 @@
#ifndef MATERIAL_EDITOR_PLUGIN_H
#define MATERIAL_EDITOR_PLUGIN_H
+#include "editor/editor_inspector.h"
#include "editor/editor_plugin.h"
#include "editor/plugins/editor_resource_conversion_plugin.h"
#include "scene/3d/camera_3d.h"
@@ -40,12 +41,14 @@
#include "scene/resources/material.h"
#include "scene/resources/primitive_meshes.h"
+class SubViewport;
class SubViewportContainer;
+class TextureButton;
class MaterialEditor : public Control {
GDCLASS(MaterialEditor, Control);
- Vector2 rot = Vector2();
+ Vector2 rot;
HBoxContainer *layout_2d = nullptr;
ColorRect *rect_instance = nullptr;
diff --git a/editor/plugins/mesh_editor_plugin.cpp b/editor/plugins/mesh_editor_plugin.cpp
index be26baaea5..79fbf19f89 100644
--- a/editor/plugins/mesh_editor_plugin.cpp
+++ b/editor/plugins/mesh_editor_plugin.cpp
@@ -32,6 +32,8 @@
#include "core/config/project_settings.h"
#include "editor/editor_scale.h"
+#include "scene/gui/texture_button.h"
+#include "scene/main/viewport.h"
void MeshEditor::gui_input(const Ref<InputEvent> &p_event) {
ERR_FAIL_COND(p_event.is_null());
@@ -61,10 +63,10 @@ void MeshEditor::_update_theme_item_cache() {
void MeshEditor::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_THEME_CHANGED: {
- light_1_switch->set_normal_texture(theme_cache.light_1_on);
- light_1_switch->set_pressed_texture(theme_cache.light_1_off);
- light_2_switch->set_normal_texture(theme_cache.light_2_on);
- light_2_switch->set_pressed_texture(theme_cache.light_2_off);
+ light_1_switch->set_texture_normal(theme_cache.light_1_on);
+ light_1_switch->set_texture_pressed(theme_cache.light_1_off);
+ light_2_switch->set_texture_normal(theme_cache.light_2_on);
+ light_2_switch->set_texture_pressed(theme_cache.light_2_off);
} break;
}
}
diff --git a/editor/plugins/mesh_editor_plugin.h b/editor/plugins/mesh_editor_plugin.h
index 6394cb1171..8eecc909b6 100644
--- a/editor/plugins/mesh_editor_plugin.h
+++ b/editor/plugins/mesh_editor_plugin.h
@@ -31,6 +31,7 @@
#ifndef MESH_EDITOR_PLUGIN_H
#define MESH_EDITOR_PLUGIN_H
+#include "editor/editor_inspector.h"
#include "editor/editor_plugin.h"
#include "scene/3d/camera_3d.h"
#include "scene/3d/light_3d.h"
@@ -39,6 +40,9 @@
#include "scene/resources/camera_attributes.h"
#include "scene/resources/material.h"
+class SubViewport;
+class TextureButton;
+
class MeshEditor : public SubViewportContainer {
GDCLASS(MeshEditor, SubViewportContainer);
diff --git a/editor/plugins/mesh_instance_3d_editor_plugin.cpp b/editor/plugins/mesh_instance_3d_editor_plugin.cpp
index d5cdb70ccf..aec43290f9 100644
--- a/editor/plugins/mesh_instance_3d_editor_plugin.cpp
+++ b/editor/plugins/mesh_instance_3d_editor_plugin.cpp
@@ -38,6 +38,10 @@
#include "scene/3d/navigation_region_3d.h"
#include "scene/3d/physics_body_3d.h"
#include "scene/gui/box_container.h"
+#include "scene/gui/menu_button.h"
+#include "scene/resources/concave_polygon_shape_3d.h"
+#include "scene/resources/convex_polygon_shape_3d.h"
+#include "scene/scene_string_names.h"
void MeshInstance3DEditor::_node_removed(Node *p_node) {
if (p_node == node) {
@@ -66,7 +70,7 @@ void MeshInstance3DEditor::_menu_option(int p_option) {
List<Node *> selection = editor_selection->get_selected_node_list();
if (selection.is_empty()) {
- Ref<Shape3D> shape = mesh->create_trimesh_shape();
+ Ref<ConcavePolygonShape3D> shape = mesh->create_trimesh_shape();
if (shape.is_null()) {
err_dialog->set_text(TTR("Couldn't create a Trimesh collision shape."));
err_dialog->popup_centered();
@@ -84,8 +88,8 @@ void MeshInstance3DEditor::_menu_option(int p_option) {
ur->add_do_method(node, "add_child", body, true);
ur->add_do_method(body, "set_owner", owner);
ur->add_do_method(cshape, "set_owner", owner);
- ur->add_do_method(Node3DEditor::get_singleton(), "_request_gizmo", body);
- ur->add_do_method(Node3DEditor::get_singleton(), "_request_gizmo", cshape);
+ ur->add_do_method(Node3DEditor::get_singleton(), SceneStringNames::get_singleton()->_request_gizmo, body);
+ ur->add_do_method(Node3DEditor::get_singleton(), SceneStringNames::get_singleton()->_request_gizmo, cshape);
ur->add_do_reference(body);
ur->add_undo_method(node, "remove_child", body);
ur->commit_action();
@@ -105,7 +109,7 @@ void MeshInstance3DEditor::_menu_option(int p_option) {
continue;
}
- Ref<Shape3D> shape = m->create_trimesh_shape();
+ Ref<ConcavePolygonShape3D> shape = m->create_trimesh_shape();
if (shape.is_null()) {
continue;
}
@@ -120,8 +124,8 @@ void MeshInstance3DEditor::_menu_option(int p_option) {
ur->add_do_method(instance, "add_child", body, true);
ur->add_do_method(body, "set_owner", owner);
ur->add_do_method(cshape, "set_owner", owner);
- ur->add_do_method(Node3DEditor::get_singleton(), "_request_gizmo", body);
- ur->add_do_method(Node3DEditor::get_singleton(), "_request_gizmo", cshape);
+ ur->add_do_method(Node3DEditor::get_singleton(), SceneStringNames::get_singleton()->_request_gizmo, body);
+ ur->add_do_method(Node3DEditor::get_singleton(), SceneStringNames::get_singleton()->_request_gizmo, cshape);
ur->add_do_reference(body);
ur->add_undo_method(instance, "remove_child", body);
}
@@ -137,7 +141,7 @@ void MeshInstance3DEditor::_menu_option(int p_option) {
return;
}
- Ref<Shape3D> shape = mesh->create_trimesh_shape();
+ Ref<ConcavePolygonShape3D> shape = mesh->create_trimesh_shape();
if (shape.is_null()) {
return;
}
@@ -155,7 +159,7 @@ void MeshInstance3DEditor::_menu_option(int p_option) {
ur->add_do_method(node->get_parent(), "add_child", cshape, true);
ur->add_do_method(node->get_parent(), "move_child", cshape, node->get_index() + 1);
ur->add_do_method(cshape, "set_owner", owner);
- ur->add_do_method(Node3DEditor::get_singleton(), "_request_gizmo", cshape);
+ ur->add_do_method(Node3DEditor::get_singleton(), SceneStringNames::get_singleton()->_request_gizmo, cshape);
ur->add_do_reference(cshape);
ur->add_undo_method(node->get_parent(), "remove_child", cshape);
ur->commit_action();
@@ -171,7 +175,7 @@ void MeshInstance3DEditor::_menu_option(int p_option) {
bool simplify = (p_option == MENU_OPTION_CREATE_SIMPLIFIED_CONVEX_COLLISION_SHAPE);
- Ref<Shape3D> shape = mesh->create_convex_shape(true, simplify);
+ Ref<ConvexPolygonShape3D> shape = mesh->create_convex_shape(true, simplify);
if (shape.is_null()) {
err_dialog->set_text(TTR("Couldn't create a single convex collision shape."));
@@ -195,7 +199,7 @@ void MeshInstance3DEditor::_menu_option(int p_option) {
ur->add_do_method(node->get_parent(), "add_child", cshape, true);
ur->add_do_method(node->get_parent(), "move_child", cshape, node->get_index() + 1);
ur->add_do_method(cshape, "set_owner", owner);
- ur->add_do_method(Node3DEditor::get_singleton(), "_request_gizmo", cshape);
+ ur->add_do_method(Node3DEditor::get_singleton(), SceneStringNames::get_singleton()->_request_gizmo, cshape);
ur->add_do_reference(cshape);
ur->add_undo_method(node->get_parent(), "remove_child", cshape);
@@ -234,7 +238,7 @@ void MeshInstance3DEditor::_menu_option(int p_option) {
ur->add_do_method(node->get_parent(), "add_child", cshape);
ur->add_do_method(node->get_parent(), "move_child", cshape, node->get_index() + 1);
ur->add_do_method(cshape, "set_owner", owner);
- ur->add_do_method(Node3DEditor::get_singleton(), "_request_gizmo", cshape);
+ ur->add_do_method(Node3DEditor::get_singleton(), SceneStringNames::get_singleton()->_request_gizmo, cshape);
ur->add_do_reference(cshape);
ur->add_undo_method(node->get_parent(), "remove_child", cshape);
}
@@ -260,7 +264,7 @@ void MeshInstance3DEditor::_menu_option(int p_option) {
ur->add_do_method(node, "add_child", nmi, true);
ur->add_do_method(nmi, "set_owner", owner);
- ur->add_do_method(Node3DEditor::get_singleton(), "_request_gizmo", nmi);
+ ur->add_do_method(Node3DEditor::get_singleton(), SceneStringNames::get_singleton()->_request_gizmo, nmi);
ur->add_do_reference(nmi);
ur->add_undo_method(node, "remove_child", nmi);
@@ -271,7 +275,7 @@ void MeshInstance3DEditor::_menu_option(int p_option) {
outline_dialog->popup_centered(Vector2(200, 90));
} break;
case MENU_OPTION_CREATE_DEBUG_TANGENTS: {
- Ref<EditorUndoRedoManager> ur = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &ur = EditorNode::get_singleton()->get_undo_redo();
ur->create_action(TTR("Create Debug Tangents"));
MeshInstance3D *tangents = node->create_debug_tangents_node();
@@ -495,7 +499,7 @@ void MeshInstance3DEditor::_create_outline_mesh() {
ur->add_do_method(node, "add_child", mi, true);
ur->add_do_method(mi, "set_owner", owner);
- ur->add_do_method(Node3DEditor::get_singleton(), "_request_gizmo", mi);
+ ur->add_do_method(Node3DEditor::get_singleton(), SceneStringNames::get_singleton()->_request_gizmo, mi);
ur->add_do_reference(mi);
ur->add_undo_method(node, "remove_child", mi);
diff --git a/editor/plugins/mesh_instance_3d_editor_plugin.h b/editor/plugins/mesh_instance_3d_editor_plugin.h
index 88800227d1..81ba263be0 100644
--- a/editor/plugins/mesh_instance_3d_editor_plugin.h
+++ b/editor/plugins/mesh_instance_3d_editor_plugin.h
@@ -35,6 +35,10 @@
#include "scene/3d/mesh_instance_3d.h"
#include "scene/gui/spin_box.h"
+class AcceptDialog;
+class ConfirmationDialog;
+class MenuButton;
+
class MeshInstance3DEditor : public Control {
GDCLASS(MeshInstance3DEditor, Control);
diff --git a/editor/plugins/mesh_library_editor_plugin.cpp b/editor/plugins/mesh_library_editor_plugin.cpp
index 6654b03a0d..4b31e99f0e 100644
--- a/editor/plugins/mesh_library_editor_plugin.cpp
+++ b/editor/plugins/mesh_library_editor_plugin.cpp
@@ -33,11 +33,13 @@
#include "editor/editor_file_dialog.h"
#include "editor/editor_node.h"
#include "editor/editor_settings.h"
+#include "editor/inspector_dock.h"
#include "main/main.h"
#include "node_3d_editor_plugin.h"
#include "scene/3d/mesh_instance_3d.h"
#include "scene/3d/navigation_region_3d.h"
#include "scene/3d/physics_body_3d.h"
+#include "scene/gui/menu_button.h"
#include "scene/main/window.h"
#include "scene/resources/packed_scene.h"
@@ -158,23 +160,23 @@ void MeshLibraryEditor::_import_scene(Node *p_scene, Ref<MeshLibrary> p_library,
p_library->set_item_shapes(id, collisions);
- Ref<NavigationMesh> navmesh;
- Transform3D navmesh_transform;
+ Ref<NavigationMesh> navigation_mesh;
+ Transform3D navigation_mesh_transform;
for (int j = 0; j < mi->get_child_count(); j++) {
Node *child2 = mi->get_child(j);
if (!Object::cast_to<NavigationRegion3D>(child2)) {
continue;
}
NavigationRegion3D *sb = Object::cast_to<NavigationRegion3D>(child2);
- navmesh = sb->get_navigation_mesh();
- navmesh_transform = sb->get_transform();
- if (!navmesh.is_null()) {
+ navigation_mesh = sb->get_navigation_mesh();
+ navigation_mesh_transform = sb->get_transform();
+ if (!navigation_mesh.is_null()) {
break;
}
}
- if (!navmesh.is_null()) {
- p_library->set_item_navmesh(id, navmesh);
- p_library->set_item_navmesh_transform(id, navmesh_transform);
+ if (!navigation_mesh.is_null()) {
+ p_library->set_item_navigation_mesh(id, navigation_mesh);
+ p_library->set_item_navigation_mesh_transform(id, navigation_mesh_transform);
}
}
diff --git a/editor/plugins/multimesh_editor_plugin.cpp b/editor/plugins/multimesh_editor_plugin.cpp
index b0e206b020..40fac060cd 100644
--- a/editor/plugins/multimesh_editor_plugin.cpp
+++ b/editor/plugins/multimesh_editor_plugin.cpp
@@ -35,6 +35,8 @@
#include "node_3d_editor_plugin.h"
#include "scene/3d/mesh_instance_3d.h"
#include "scene/gui/box_container.h"
+#include "scene/gui/menu_button.h"
+#include "scene/gui/option_button.h"
void MultiMeshEditor::_node_removed(Node *p_node) {
if (p_node == node) {
diff --git a/editor/plugins/multimesh_editor_plugin.h b/editor/plugins/multimesh_editor_plugin.h
index 5773989d0d..76f86cfa5d 100644
--- a/editor/plugins/multimesh_editor_plugin.h
+++ b/editor/plugins/multimesh_editor_plugin.h
@@ -36,6 +36,10 @@
#include "scene/gui/slider.h"
#include "scene/gui/spin_box.h"
+class AcceptDialog;
+class ConfirmationDialog;
+class MenuButton;
+class OptionButton;
class SceneTreeDialog;
class MultiMeshEditor : public Control {
diff --git a/editor/plugins/navigation_link_2d_editor_plugin.cpp b/editor/plugins/navigation_link_2d_editor_plugin.cpp
index b72f639fbf..560454e5d3 100644
--- a/editor/plugins/navigation_link_2d_editor_plugin.cpp
+++ b/editor/plugins/navigation_link_2d_editor_plugin.cpp
@@ -85,6 +85,7 @@ bool NavigationLink2DEditor::forward_canvas_gui_input(const Ref<InputEvent> &p_e
end_grabbed = false;
}
} else {
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
if (start_grabbed) {
undo_redo->create_action(TTR("Set start_location"));
undo_redo->add_do_method(node, "set_start_location", node->get_start_location());
@@ -165,10 +166,6 @@ void NavigationLink2DEditor::edit(NavigationLink2D *p_node) {
canvas_item_editor->update_viewport();
}
-NavigationLink2DEditor::NavigationLink2DEditor() {
- undo_redo = EditorNode::get_undo_redo();
-}
-
///////////////////////
void NavigationLink2DEditorPlugin::edit(Object *p_object) {
diff --git a/editor/plugins/navigation_link_2d_editor_plugin.h b/editor/plugins/navigation_link_2d_editor_plugin.h
index 0a3d9b8810..fea9f58a40 100644
--- a/editor/plugins/navigation_link_2d_editor_plugin.h
+++ b/editor/plugins/navigation_link_2d_editor_plugin.h
@@ -35,12 +35,10 @@
#include "scene/2d/navigation_link_2d.h"
class CanvasItemEditor;
-class EditorUndoRedoManager;
class NavigationLink2DEditor : public Control {
GDCLASS(NavigationLink2DEditor, Control);
- Ref<EditorUndoRedoManager> undo_redo;
CanvasItemEditor *canvas_item_editor = nullptr;
NavigationLink2D *node = nullptr;
@@ -58,8 +56,6 @@ public:
bool forward_canvas_gui_input(const Ref<InputEvent> &p_event);
void forward_canvas_draw_over_viewport(Control *p_overlay);
void edit(NavigationLink2D *p_node);
-
- NavigationLink2DEditor();
};
class NavigationLink2DEditorPlugin : public EditorPlugin {
diff --git a/editor/plugins/node_3d_editor_gizmos.cpp b/editor/plugins/node_3d_editor_gizmos.cpp
index 0af2a13df2..91c7fbc06a 100644
--- a/editor/plugins/node_3d_editor_gizmos.cpp
+++ b/editor/plugins/node_3d_editor_gizmos.cpp
@@ -30,6 +30,7 @@
#include "node_3d_editor_gizmos.h"
+#include "core/config/project_settings.h"
#include "core/math/convex_hull.h"
#include "core/math/geometry_2d.h"
#include "core/math/geometry_3d.h"
@@ -1015,8 +1016,9 @@ Ref<StandardMaterial3D> EditorNode3DGizmoPlugin::get_material(const String &p_na
}
String EditorNode3DGizmoPlugin::get_gizmo_name() const {
- if (get_script_instance() && get_script_instance()->has_method("_get_gizmo_name")) {
- return get_script_instance()->call("_get_gizmo_name");
+ String ret;
+ if (GDVIRTUAL_CALL(_get_gizmo_name, ret)) {
+ return ret;
}
WARN_PRINT_ONCE("A 3D editor gizmo has no name defined (it will appear as \"Unnamed Gizmo\" in the \"View > Gizmos\" menu). To resolve this, override the `_get_gizmo_name()` function to return a String in the script that extends EditorNode3DGizmoPlugin.");
@@ -1024,8 +1026,9 @@ String EditorNode3DGizmoPlugin::get_gizmo_name() const {
}
int EditorNode3DGizmoPlugin::get_priority() const {
- if (get_script_instance() && get_script_instance()->has_method("_get_priority")) {
- return get_script_instance()->call("_get_priority");
+ int ret;
+ if (GDVIRTUAL_CALL(_get_priority, ret)) {
+ return ret;
}
return 0;
}
@@ -1732,6 +1735,24 @@ Camera3DGizmoPlugin::Camera3DGizmoPlugin() {
create_handle_material("handles");
}
+Size2i Camera3DGizmoPlugin::_get_viewport_size(Camera3D *p_camera) {
+ Viewport *viewport = p_camera->get_viewport();
+
+ Window *window = Object::cast_to<Window>(viewport);
+ if (window) {
+ return window->get_size();
+ }
+
+ SubViewport *sub_viewport = Object::cast_to<SubViewport>(viewport);
+ ERR_FAIL_NULL_V(sub_viewport, Size2i());
+
+ if (sub_viewport == EditorNode::get_singleton()->get_scene_root()) {
+ return Size2(GLOBAL_GET("display/window/size/viewport_width"), GLOBAL_GET("display/window/size/viewport_height"));
+ }
+
+ return sub_viewport->get_size();
+}
+
bool Camera3DGizmoPlugin::has_gizmo(Node3D *p_spatial) {
return Object::cast_to<Camera3D>(p_spatial) != nullptr;
}
@@ -1830,6 +1851,10 @@ void Camera3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
Ref<Material> material = get_material("camera_material", p_gizmo);
+ const Size2i viewport_size = _get_viewport_size(camera);
+ const real_t viewport_aspect = viewport_size.x > 0 && viewport_size.y > 0 ? viewport_size.aspect() : 1.0;
+ const Size2 size_factor = viewport_aspect > 1.0 ? Size2(1.0, 1.0 / viewport_aspect) : Size2(viewport_aspect, 1.0);
+
#define ADD_TRIANGLE(m_a, m_b, m_c) \
{ \
lines.push_back(m_a); \
@@ -1857,10 +1882,11 @@ void Camera3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
// The real FOV is halved for accurate representation
float fov = camera->get_fov() / 2.0;
- Vector3 side = Vector3(Math::sin(Math::deg_to_rad(fov)), 0, -Math::cos(Math::deg_to_rad(fov)));
- Vector3 nside = side;
- nside.x = -nside.x;
- Vector3 up = Vector3(0, side.x, 0);
+ const float hsize = Math::sin(Math::deg_to_rad(fov));
+ const float depth = -Math::cos(Math::deg_to_rad(fov));
+ Vector3 side = Vector3(hsize * size_factor.x, 0, depth);
+ Vector3 nside = Vector3(-side.x, side.y, side.z);
+ Vector3 up = Vector3(0, hsize * size_factor.y, 0);
ADD_TRIANGLE(Vector3(), side + up, side - up);
ADD_TRIANGLE(Vector3(), nside + up, nside - up);
@@ -1868,18 +1894,18 @@ void Camera3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
ADD_TRIANGLE(Vector3(), side - up, nside - up);
handles.push_back(side);
- side.x *= 0.25;
- nside.x *= 0.25;
- Vector3 tup(0, up.y * 3 / 2, side.z);
+ side.x = MIN(side.x, hsize * 0.25);
+ nside.x = -side.x;
+ Vector3 tup(0, up.y + hsize / 2, side.z);
ADD_TRIANGLE(tup, side + up, nside + up);
-
} break;
+
case Camera3D::PROJECTION_ORTHOGONAL: {
float size = camera->get_size();
float hsize = size * 0.5;
- Vector3 right(hsize, 0, 0);
- Vector3 up(0, hsize, 0);
+ Vector3 right(hsize * size_factor.x, 0, 0);
+ Vector3 up(0, hsize * size_factor.y, 0);
Vector3 back(0, 0, -1.0);
Vector3 front(0, 0, 0);
@@ -1890,18 +1916,19 @@ void Camera3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
handles.push_back(right + back);
- right.x *= 0.25;
- Vector3 tup(0, up.y * 3 / 2, back.z);
+ right.x = MIN(right.x, hsize * 0.25);
+ Vector3 tup(0, up.y + hsize / 2, back.z);
ADD_TRIANGLE(tup, right + up + back, -right + up + back);
} break;
+
case Camera3D::PROJECTION_FRUSTUM: {
float hsize = camera->get_size() / 2.0;
Vector3 side = Vector3(hsize, 0, -camera->get_near()).normalized();
- Vector3 nside = side;
- nside.x = -nside.x;
- Vector3 up = Vector3(0, side.x, 0);
+ side.x *= size_factor.x;
+ Vector3 nside = Vector3(-side.x, side.y, side.z);
+ Vector3 up = Vector3(0, hsize * size_factor.y, 0);
Vector3 offset = Vector3(camera->get_frustum_offset().x, camera->get_frustum_offset().y, 0.0);
ADD_TRIANGLE(Vector3(), side + up + offset, side - up + offset);
@@ -1909,11 +1936,11 @@ void Camera3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
ADD_TRIANGLE(Vector3(), side + up + offset, nside + up + offset);
ADD_TRIANGLE(Vector3(), side - up + offset, nside - up + offset);
- side.x *= 0.25;
- nside.x *= 0.25;
- Vector3 tup(0, up.y * 3 / 2, side.z);
+ side.x = MIN(side.x, hsize * 0.25);
+ nside.x = -side.x;
+ Vector3 tup(0, up.y + hsize / 2, side.z);
ADD_TRIANGLE(tup + offset, side + up + offset, nside + up + offset);
- }
+ } break;
}
#undef ADD_TRIANGLE
@@ -1921,7 +1948,10 @@ void Camera3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
p_gizmo->add_lines(lines, material);
p_gizmo->add_collision_segments(lines);
- p_gizmo->add_handles(handles, get_material("handles"));
+
+ if (!handles.is_empty()) {
+ p_gizmo->add_handles(handles, get_material("handles"));
+ }
}
//////
diff --git a/editor/plugins/node_3d_editor_gizmos.h b/editor/plugins/node_3d_editor_gizmos.h
index d7e3e03f61..60d44ad787 100644
--- a/editor/plugins/node_3d_editor_gizmos.h
+++ b/editor/plugins/node_3d_editor_gizmos.h
@@ -264,6 +264,9 @@ public:
class Camera3DGizmoPlugin : public EditorNode3DGizmoPlugin {
GDCLASS(Camera3DGizmoPlugin, EditorNode3DGizmoPlugin);
+private:
+ static Size2i _get_viewport_size(Camera3D *p_camera);
+
public:
bool has_gizmo(Node3D *p_spatial) override;
String get_gizmo_name() const override;
diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp
index 7febb50f5c..4976c8c750 100644
--- a/editor/plugins/node_3d_editor_plugin.cpp
+++ b/editor/plugins/node_3d_editor_plugin.cpp
@@ -36,14 +36,12 @@
#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"
#include "editor/editor_node.h"
#include "editor/editor_settings.h"
#include "editor/editor_undo_redo_manager.h"
#include "editor/plugins/animation_player_editor_plugin.h"
#include "editor/plugins/node_3d_editor_gizmos.h"
-#include "editor/plugins/script_editor_plugin.h"
#include "editor/scene_tree_dock.h"
#include "scene/3d/camera_3d.h"
#include "scene/3d/collision_shape_3d.h"
@@ -54,9 +52,12 @@
#include "scene/3d/visual_instance_3d.h"
#include "scene/3d/world_environment.h"
#include "scene/gui/center_container.h"
+#include "scene/gui/color_picker.h"
#include "scene/gui/flow_container.h"
+#include "scene/gui/split_container.h"
#include "scene/gui/subviewport_container.h"
#include "scene/resources/packed_scene.h"
+#include "scene/resources/sky_material.h"
#include "scene/resources/surface_tool.h"
constexpr real_t DISTANCE_DEFAULT = 4;
@@ -85,6 +86,177 @@ constexpr real_t MAX_Z = 1000000.0;
constexpr real_t MIN_FOV = 0.01;
constexpr real_t MAX_FOV = 179;
+void ViewportNavigationControl::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_ENTER_TREE: {
+ if (!is_connected("mouse_exited", callable_mp(this, &ViewportNavigationControl::_on_mouse_exited))) {
+ connect("mouse_exited", callable_mp(this, &ViewportNavigationControl::_on_mouse_exited));
+ }
+ if (!is_connected("mouse_entered", callable_mp(this, &ViewportNavigationControl::_on_mouse_entered))) {
+ connect("mouse_entered", callable_mp(this, &ViewportNavigationControl::_on_mouse_entered));
+ }
+ } break;
+
+ case NOTIFICATION_DRAW: {
+ if (viewport != nullptr) {
+ _draw();
+ _update_navigation();
+ }
+ } break;
+ }
+}
+
+void ViewportNavigationControl::_draw() {
+ if (nav_mode == Node3DEditorViewport::NAVIGATION_NONE) {
+ return;
+ }
+
+ Vector2 center = get_size() / 2.0;
+ float radius = get_size().x / 2.0;
+
+ const bool focused = focused_index != -1;
+ draw_circle(center, radius, Color(0.5, 0.5, 0.5, focused || hovered ? 0.35 : 0.15));
+
+ const Color c = focused ? Color(0.9, 0.9, 0.9, 0.9) : Color(0.5, 0.5, 0.5, 0.25);
+
+ Vector2 circle_pos = focused ? center.move_toward(focused_pos, radius) : center;
+
+ draw_circle(circle_pos, AXIS_CIRCLE_RADIUS, c);
+ draw_circle(circle_pos, AXIS_CIRCLE_RADIUS * 0.8, c.darkened(0.4));
+}
+
+void ViewportNavigationControl::_process_click(int p_index, Vector2 p_position, bool p_pressed) {
+ hovered = false;
+ queue_redraw();
+
+ if (focused_index != -1 && focused_index != p_index) {
+ return;
+ }
+ if (p_pressed) {
+ if (p_position.distance_to(get_size() / 2.0) < get_size().x / 2.0) {
+ focused_pos = p_position;
+ focused_index = p_index;
+ queue_redraw();
+ }
+ } else {
+ focused_index = -1;
+ if (Input::get_singleton()->get_mouse_mode() == Input::MOUSE_MODE_CAPTURED) {
+ Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_VISIBLE);
+ Input::get_singleton()->warp_mouse(focused_mouse_start);
+ }
+ }
+}
+
+void ViewportNavigationControl::_process_drag(int p_index, Vector2 p_position, Vector2 p_relative_position) {
+ if (focused_index == p_index) {
+ if (Input::get_singleton()->get_mouse_mode() == Input::MOUSE_MODE_VISIBLE) {
+ Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_CAPTURED);
+ focused_mouse_start = p_position;
+ }
+ focused_pos += p_relative_position;
+ queue_redraw();
+ }
+}
+
+void ViewportNavigationControl::gui_input(const Ref<InputEvent> &p_event) {
+ // Mouse events
+ const Ref<InputEventMouseButton> mouse_button = p_event;
+ if (mouse_button.is_valid() && mouse_button->get_button_index() == MouseButton::LEFT) {
+ _process_click(100, mouse_button->get_position(), mouse_button->is_pressed());
+ }
+
+ const Ref<InputEventMouseMotion> mouse_motion = p_event;
+ if (mouse_motion.is_valid()) {
+ _process_drag(100, mouse_motion->get_global_position(), viewport->_get_warped_mouse_motion(mouse_motion));
+ }
+
+ // Touch events
+ const Ref<InputEventScreenTouch> screen_touch = p_event;
+ if (screen_touch.is_valid()) {
+ _process_click(screen_touch->get_index(), screen_touch->get_position(), screen_touch->is_pressed());
+ }
+
+ const Ref<InputEventScreenDrag> screen_drag = p_event;
+ if (screen_drag.is_valid()) {
+ _process_drag(screen_drag->get_index(), screen_drag->get_position(), screen_drag->get_relative());
+ }
+}
+
+void ViewportNavigationControl::_update_navigation() {
+ if (focused_index == -1) {
+ return;
+ }
+
+ Vector2 delta = focused_pos - (get_size() / 2.0);
+ Vector2 delta_normalized = delta.normalized();
+ switch (nav_mode) {
+ case Node3DEditorViewport::NavigationMode::NAVIGATION_MOVE: {
+ real_t speed_multiplier = MIN(delta.length() / (get_size().x * 100.0), 3.0);
+ real_t speed = viewport->freelook_speed * speed_multiplier;
+
+ const Node3DEditorViewport::FreelookNavigationScheme navigation_scheme = (Node3DEditorViewport::FreelookNavigationScheme)EditorSettings::get_singleton()->get("editors/3d/freelook/freelook_navigation_scheme").operator int();
+
+ Vector3 forward;
+ if (navigation_scheme == Node3DEditorViewport::FreelookNavigationScheme::FREELOOK_FULLY_AXIS_LOCKED) {
+ // Forward/backward keys will always go straight forward/backward, never moving on the Y axis.
+ forward = Vector3(0, 0, delta_normalized.y).rotated(Vector3(0, 1, 0), viewport->camera->get_rotation().y);
+ } else {
+ // Forward/backward keys will be relative to the camera pitch.
+ forward = viewport->camera->get_transform().basis.xform(Vector3(0, 0, delta_normalized.y));
+ }
+
+ const Vector3 right = viewport->camera->get_transform().basis.xform(Vector3(delta_normalized.x, 0, 0));
+
+ const Vector3 direction = forward + right;
+ const Vector3 motion = direction * speed;
+ viewport->cursor.pos += motion;
+ viewport->cursor.eye_pos += motion;
+ } break;
+
+ case Node3DEditorViewport::NavigationMode::NAVIGATION_LOOK: {
+ real_t speed_multiplier = MIN(delta.length() / (get_size().x * 2.5), 3.0);
+ real_t speed = viewport->freelook_speed * speed_multiplier;
+ viewport->_nav_look(nullptr, delta_normalized * speed);
+ } break;
+
+ case Node3DEditorViewport::NAVIGATION_PAN: {
+ real_t speed_multiplier = MIN(delta.length() / (get_size().x), 3.0);
+ real_t speed = viewport->freelook_speed * speed_multiplier;
+ viewport->_nav_pan(nullptr, -delta_normalized * speed);
+ } break;
+ case Node3DEditorViewport::NAVIGATION_ZOOM: {
+ real_t speed_multiplier = MIN(delta.length() / (get_size().x), 3.0);
+ real_t speed = viewport->freelook_speed * speed_multiplier;
+ viewport->_nav_zoom(nullptr, delta_normalized * speed);
+ } break;
+ case Node3DEditorViewport::NAVIGATION_ORBIT: {
+ real_t speed_multiplier = MIN(delta.length() / (get_size().x), 3.0);
+ real_t speed = viewport->freelook_speed * speed_multiplier;
+ viewport->_nav_orbit(nullptr, delta_normalized * speed);
+ } break;
+ case Node3DEditorViewport::NAVIGATION_NONE: {
+ } break;
+ }
+}
+
+void ViewportNavigationControl::_on_mouse_entered() {
+ hovered = true;
+ queue_redraw();
+}
+
+void ViewportNavigationControl::_on_mouse_exited() {
+ hovered = false;
+ queue_redraw();
+}
+
+void ViewportNavigationControl::set_navigation_mode(Node3DEditorViewport::NavigationMode p_nav_mode) {
+ nav_mode = p_nav_mode;
+}
+
+void ViewportNavigationControl::set_viewport(Node3DEditorViewport *p_viewport) {
+ viewport = p_viewport;
+}
+
void ViewportRotationControl::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE: {
@@ -119,7 +291,7 @@ void ViewportRotationControl::_draw() {
const Vector2i center = get_size() / 2.0;
const real_t radius = get_size().x / 2.0;
- if (focused_axis > -2 || orbiting) {
+ if (focused_axis > -2 || orbiting_index != -1) {
draw_circle(center, radius, Color(0.5, 0.5, 0.5, 0.25));
}
@@ -190,41 +362,63 @@ void ViewportRotationControl::_get_sorted_axis(Vector<Axis2D> &r_axis) {
r_axis.sort_custom<Axis2DCompare>();
}
+void ViewportRotationControl::_process_click(int p_index, Vector2 p_position, bool p_pressed) {
+ if (orbiting_index != -1 && orbiting_index != p_index) {
+ return;
+ }
+ if (p_pressed) {
+ if (p_position.distance_to(get_size() / 2.0) < get_size().x / 2.0) {
+ orbiting_index = p_index;
+ }
+ } else {
+ if (focused_axis > -1) {
+ viewport->_menu_option(axis_menu_options[focused_axis]);
+ _update_focus();
+ }
+ orbiting_index = -1;
+ if (Input::get_singleton()->get_mouse_mode() == Input::MOUSE_MODE_CAPTURED) {
+ Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_VISIBLE);
+ Input::get_singleton()->warp_mouse(orbiting_mouse_start);
+ }
+ }
+}
+
+void ViewportRotationControl::_process_drag(Ref<InputEventWithModifiers> p_event, int p_index, Vector2 p_position, Vector2 p_relative_position) {
+ if (orbiting_index == p_index) {
+ if (Input::get_singleton()->get_mouse_mode() == Input::MOUSE_MODE_VISIBLE) {
+ Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_CAPTURED);
+ orbiting_mouse_start = p_position;
+ }
+ viewport->_nav_orbit(p_event, p_relative_position);
+ focused_axis = -1;
+ } else {
+ _update_focus();
+ }
+}
+
void ViewportRotationControl::gui_input(const Ref<InputEvent> &p_event) {
ERR_FAIL_COND(p_event.is_null());
+ // Mouse events
const Ref<InputEventMouseButton> mb = p_event;
if (mb.is_valid() && mb->get_button_index() == MouseButton::LEFT) {
- Vector2 pos = mb->get_position();
- if (mb->is_pressed()) {
- if (pos.distance_to(get_size() / 2.0) < get_size().x / 2.0) {
- orbiting = true;
- }
- } else {
- if (focused_axis > -1) {
- viewport->_menu_option(axis_menu_options[focused_axis]);
- _update_focus();
- }
- orbiting = false;
- if (Input::get_singleton()->get_mouse_mode() == Input::MOUSE_MODE_CAPTURED) {
- Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_VISIBLE);
- Input::get_singleton()->warp_mouse(orbiting_mouse_start);
- }
- }
+ _process_click(100, mb->get_position(), mb->is_pressed());
}
const Ref<InputEventMouseMotion> mm = p_event;
if (mm.is_valid()) {
- if (orbiting) {
- if (Input::get_singleton()->get_mouse_mode() == Input::MOUSE_MODE_VISIBLE) {
- Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_CAPTURED);
- orbiting_mouse_start = mm->get_global_position();
- }
- viewport->_nav_orbit(mm, viewport->_get_warped_mouse_motion(mm));
- focused_axis = -1;
- } else {
- _update_focus();
- }
+ _process_drag(mm, 100, mm->get_global_position(), viewport->_get_warped_mouse_motion(mm));
+ }
+
+ // Touch events
+ const Ref<InputEventScreenTouch> screen_touch = p_event;
+ if (screen_touch.is_valid()) {
+ _process_click(screen_touch->get_index(), screen_touch->get_position(), screen_touch->is_pressed());
+ }
+
+ const Ref<InputEventScreenDrag> screen_drag = p_event;
+ if (screen_drag.is_valid()) {
+ _process_drag(screen_drag, screen_drag->get_index(), screen_drag->get_position(), screen_drag->get_relative());
}
}
@@ -269,6 +463,15 @@ void Node3DEditorViewport::_view_settings_confirmed(real_t p_interp_delta) {
_update_camera(p_interp_delta);
}
+void Node3DEditorViewport::_update_navigation_controls_visibility() {
+ bool show_viewport_rotation_gizmo = EDITOR_GET("editors/3d/navigation/show_viewport_rotation_gizmo") && (!previewing_cinema && !previewing_camera);
+ rotation_control->set_visible(show_viewport_rotation_gizmo);
+
+ bool show_viewport_navigation_gizmo = EDITOR_GET("editors/3d/navigation/show_viewport_navigation_gizmo") && (!previewing_cinema && !previewing_camera);
+ position_control->set_visible(show_viewport_navigation_gizmo);
+ look_control->set_visible(show_viewport_navigation_gizmo);
+}
+
void Node3DEditorViewport::_update_camera(real_t p_interp_delta) {
bool is_orthogonal = camera->get_projection() == Camera3D::PROJECTION_ORTHOGONAL;
@@ -352,6 +555,8 @@ void Node3DEditorViewport::_update_camera(real_t p_interp_delta) {
update_transform_gizmo_view();
rotation_control->queue_redraw();
+ position_control->queue_redraw();
+ look_control->queue_redraw();
spatial_editor->update_grid();
}
}
@@ -1329,7 +1534,7 @@ void Node3DEditorViewport::_list_select(Ref<InputEventMouseButton> b) {
}
}
- String suffix = String();
+ String suffix;
if (locked == 1) {
suffix = " (" + TTR("Locked") + ")";
} else if (locked == 2) {
@@ -2090,7 +2295,7 @@ void Node3DEditorViewport::_nav_pan(Ref<InputEventWithModifiers> p_event, const
const NavigationScheme nav_scheme = (NavigationScheme)EDITOR_GET("editors/3d/navigation/navigation_scheme").operator int();
real_t pan_speed = 1 / 150.0;
- if (nav_scheme == NAVIGATION_MAYA && p_event->is_shift_pressed()) {
+ if (p_event.is_valid() && nav_scheme == NAVIGATION_MAYA && p_event->is_shift_pressed()) {
pan_speed *= 10;
}
@@ -2114,7 +2319,7 @@ void Node3DEditorViewport::_nav_zoom(Ref<InputEventWithModifiers> p_event, const
const NavigationScheme nav_scheme = (NavigationScheme)EDITOR_GET("editors/3d/navigation/navigation_scheme").operator int();
real_t zoom_speed = 1 / 80.0;
- if (nav_scheme == NAVIGATION_MAYA && p_event->is_shift_pressed()) {
+ if (p_event.is_valid() && nav_scheme == NAVIGATION_MAYA && p_event->is_shift_pressed()) {
zoom_speed *= 10;
}
@@ -2401,7 +2606,7 @@ void Node3DEditorViewport::_project_settings_changed() {
const bool use_taa = GLOBAL_GET("rendering/anti_aliasing/quality/use_taa");
viewport->set_use_taa(use_taa);
- const bool transparent_background = GLOBAL_GET("rendering/transparent_background");
+ const bool transparent_background = GLOBAL_GET("rendering/viewport/transparent_background");
viewport->set_transparent_background(transparent_background);
const bool use_debanding = GLOBAL_GET("rendering/anti_aliasing/quality/use_debanding");
@@ -2446,7 +2651,6 @@ void Node3DEditorViewport::_notification(int p_what) {
set_freelook_active(false);
}
call_deferred(SNAME("update_transform_gizmo_view"));
- rotation_control->set_visible(EDITOR_GET("editors/3d/navigation/show_viewport_rotation_gizmo"));
} break;
case NOTIFICATION_RESIZED: {
@@ -2464,6 +2668,7 @@ void Node3DEditorViewport::_notification(int p_what) {
}
}
+ _update_navigation_controls_visibility();
_update_freelook(delta);
Node *scene_root = SceneTreeDock::get_singleton()->get_editor_data()->get_edited_scene_root();
@@ -3368,7 +3573,8 @@ void Node3DEditorViewport::_toggle_camera_preview(bool p_activate) {
ERR_FAIL_COND(p_activate && !preview);
ERR_FAIL_COND(!p_activate && !previewing);
- rotation_control->set_visible(!p_activate);
+ previewing_camera = p_activate;
+ _update_navigation_controls_visibility();
if (!p_activate) {
previewing->disconnect("tree_exiting", callable_mp(this, &Node3DEditorViewport::_preview_exited_scene));
@@ -3389,7 +3595,7 @@ void Node3DEditorViewport::_toggle_camera_preview(bool p_activate) {
void Node3DEditorViewport::_toggle_cinema_preview(bool p_activate) {
previewing_cinema = p_activate;
- rotation_control->set_visible(!p_activate);
+ _update_navigation_controls_visibility();
if (!previewing_cinema) {
if (previewing != nullptr) {
@@ -3492,7 +3698,7 @@ void Node3DEditorViewport::update_transform_gizmo_view() {
}
for (int i = 0; i < 3; i++) {
- Transform3D axis_angle = Transform3D();
+ Transform3D axis_angle;
if (xform.basis.get_column(i).normalized().dot(xform.basis.get_column((i + 1) % 3).normalized()) < 1.0) {
axis_angle = axis_angle.looking_at(xform.basis.get_column(i).normalized(), xform.basis.get_column((i + 1) % 3).normalized());
}
@@ -4039,7 +4245,7 @@ bool Node3DEditorViewport::_create_instance(Node *parent, String &path, const Po
return false;
}
- if (!EditorNode::get_singleton()->get_edited_scene()->get_scene_file_path().is_empty()) { // cyclical instancing
+ if (!EditorNode::get_singleton()->get_edited_scene()->get_scene_file_path().is_empty()) { // Cyclic instantiation.
if (_cyclical_dependency_exists(EditorNode::get_singleton()->get_edited_scene()->get_scene_file_path(), instantiated_scene)) {
memdelete(instantiated_scene);
return false;
@@ -4058,7 +4264,7 @@ bool Node3DEditorViewport::_create_instance(Node *parent, String &path, const Po
String new_name = parent->validate_child_name(instantiated_scene);
EditorDebuggerNode *ed = EditorDebuggerNode::get_singleton();
- undo_redo->add_do_method(ed, "live_debug_instance_node", EditorNode::get_singleton()->get_edited_scene()->get_path_to(parent), path, new_name);
+ undo_redo->add_do_method(ed, "live_debug_instantiate_node", EditorNode::get_singleton()->get_edited_scene()->get_path_to(parent), path, new_name);
undo_redo->add_undo_method(ed, "live_debug_remove_node", NodePath(String(EditorNode::get_singleton()->get_edited_scene()->get_path_to(parent)) + "/" + new_name));
Node3D *node3d = Object::cast_to<Node3D>(instantiated_scene);
@@ -4129,7 +4335,7 @@ void Node3DEditorViewport::_perform_drop_data() {
files_str += error_files[i].get_file().get_basename() + ",";
}
files_str = files_str.substr(0, files_str.length() - 1);
- accept->set_text(vformat(TTR("Error instancing scene from %s"), files_str.get_data()));
+ accept->set_text(vformat(TTR("Error instantiating scene from %s"), files_str.get_data()));
accept->popup_centered();
}
}
@@ -4873,6 +5079,14 @@ Node3DEditorViewport::Node3DEditorViewport(Node3DEditor *p_spatial_editor, int p
preview_node = nullptr;
+ bottom_center_vbox = memnew(VBoxContainer);
+ bottom_center_vbox->set_anchors_preset(LayoutPreset::PRESET_CENTER);
+ bottom_center_vbox->set_anchor_and_offset(SIDE_TOP, ANCHOR_END, -20 * EDSCALE);
+ bottom_center_vbox->set_anchor_and_offset(SIDE_BOTTOM, ANCHOR_END, -10 * EDSCALE);
+ bottom_center_vbox->set_h_grow_direction(GROW_DIRECTION_BOTH);
+ bottom_center_vbox->set_v_grow_direction(GROW_DIRECTION_BEGIN);
+ surface->add_child(bottom_center_vbox);
+
info_label = memnew(Label);
info_label->set_anchor_and_offset(SIDE_LEFT, ANCHOR_END, -90 * EDSCALE);
info_label->set_anchor_and_offset(SIDE_TOP, ANCHOR_END, -90 * EDSCALE);
@@ -4893,23 +5107,18 @@ Node3DEditorViewport::Node3DEditorViewport(Node3DEditor *p_spatial_editor, int p
previewing_cinema = false;
locked_label = memnew(Label);
- locked_label->set_anchor_and_offset(SIDE_TOP, ANCHOR_END, -20 * EDSCALE);
- locked_label->set_anchor_and_offset(SIDE_BOTTOM, ANCHOR_END, -10 * EDSCALE);
- locked_label->set_h_grow_direction(GROW_DIRECTION_END);
- locked_label->set_v_grow_direction(GROW_DIRECTION_BEGIN);
locked_label->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_CENTER);
- surface->add_child(locked_label);
+ locked_label->set_h_size_flags(SIZE_SHRINK_CENTER);
+ bottom_center_vbox->add_child(locked_label);
locked_label->set_text(TTR("View Rotation Locked"));
locked_label->hide();
zoom_limit_label = memnew(Label);
- zoom_limit_label->set_anchors_and_offsets_preset(LayoutPreset::PRESET_BOTTOM_LEFT);
- zoom_limit_label->set_offset(Side::SIDE_TOP, -28 * EDSCALE);
zoom_limit_label->set_text(TTR("To zoom further, change the camera's clipping planes (View -> Settings...)"));
zoom_limit_label->set_name("ZoomLimitMessageLabel");
zoom_limit_label->add_theme_color_override("font_color", Color(1, 1, 1, 1));
zoom_limit_label->hide();
- surface->add_child(zoom_limit_label);
+ bottom_center_vbox->add_child(zoom_limit_label);
preview_material_label = memnew(Label);
preview_material_label->set_anchors_and_offsets_preset(LayoutPreset::PRESET_BOTTOM_LEFT);
@@ -4940,6 +5149,30 @@ Node3DEditorViewport::Node3DEditorViewport(Node3DEditor *p_spatial_editor, int p
// Prevent visible spacing between frame time labels.
top_right_vbox->add_theme_constant_override("separation", 0);
+ const int navigation_control_size = 150;
+
+ position_control = memnew(ViewportNavigationControl);
+ position_control->set_navigation_mode(Node3DEditorViewport::NAVIGATION_MOVE);
+ position_control->set_custom_minimum_size(Size2(navigation_control_size, navigation_control_size) * EDSCALE);
+ position_control->set_h_size_flags(SIZE_SHRINK_END);
+ position_control->set_anchor_and_offset(SIDE_LEFT, ANCHOR_BEGIN, 0 * EDSCALE);
+ position_control->set_anchor_and_offset(SIDE_TOP, ANCHOR_END, -navigation_control_size * EDSCALE);
+ position_control->set_anchor_and_offset(SIDE_RIGHT, ANCHOR_BEGIN, navigation_control_size * EDSCALE);
+ position_control->set_anchor_and_offset(SIDE_BOTTOM, ANCHOR_END, 0 * EDSCALE);
+ position_control->set_viewport(this);
+ surface->add_child(position_control);
+
+ look_control = memnew(ViewportNavigationControl);
+ look_control->set_navigation_mode(Node3DEditorViewport::NAVIGATION_LOOK);
+ look_control->set_custom_minimum_size(Size2(navigation_control_size, navigation_control_size) * EDSCALE);
+ look_control->set_h_size_flags(SIZE_SHRINK_END);
+ look_control->set_anchor_and_offset(SIDE_LEFT, ANCHOR_END, -navigation_control_size * EDSCALE);
+ look_control->set_anchor_and_offset(SIDE_TOP, ANCHOR_END, -navigation_control_size * EDSCALE);
+ look_control->set_anchor_and_offset(SIDE_RIGHT, ANCHOR_END, 0 * EDSCALE);
+ look_control->set_anchor_and_offset(SIDE_BOTTOM, ANCHOR_END, 0 * EDSCALE);
+ look_control->set_viewport(this);
+ surface->add_child(look_control);
+
rotation_control = memnew(ViewportRotationControl);
rotation_control->set_custom_minimum_size(Size2(80, 80) * EDSCALE);
rotation_control->set_h_size_flags(SIZE_SHRINK_END);
@@ -6803,8 +7036,8 @@ void Node3DEditor::_init_grid() {
// Don't draw lines over the origin if it's enabled.
if (!(origin_enabled && Math::is_zero_approx(position_a))) {
- Vector3 line_bgn = Vector3();
- Vector3 line_end = Vector3();
+ Vector3 line_bgn;
+ Vector3 line_end;
line_bgn[a] = position_a;
line_end[a] = position_a;
line_bgn[b] = bgn_b;
@@ -6819,8 +7052,8 @@ void Node3DEditor::_init_grid() {
}
if (!(origin_enabled && Math::is_zero_approx(position_b))) {
- Vector3 line_bgn = Vector3();
- Vector3 line_end = Vector3();
+ Vector3 line_bgn;
+ Vector3 line_end;
line_bgn[b] = position_b;
line_end[b] = position_b;
line_bgn[a] = bgn_a;
@@ -6988,8 +7221,8 @@ void Node3DEditor::_snap_selected_nodes_to_floor() {
for (Node *E : selection) {
Node3D *sp = Object::cast_to<Node3D>(E);
if (sp) {
- Vector3 from = Vector3();
- Vector3 position_offset = Vector3();
+ Vector3 from;
+ Vector3 position_offset;
// Priorities for snapping to floor are CollisionShapes, VisualInstances and then origin
HashSet<VisualInstance3D *> vi = _get_child_nodes<VisualInstance3D>(sp);
@@ -7248,6 +7481,8 @@ void Node3DEditor::_notification(int p_what) {
sun_state->set_custom_minimum_size(sun_vb->get_combined_minimum_size());
environ_state->set_custom_minimum_size(environ_vb->get_combined_minimum_size());
+
+ EditorNode::get_singleton()->connect("project_settings_changed", callable_mp(this, &Node3DEditor::update_all_gizmos).bind(Variant()));
} break;
case NOTIFICATION_ENTER_TREE: {
@@ -7408,6 +7643,13 @@ void Node3DEditor::_request_gizmo(Object *p_obj) {
}
}
+void Node3DEditor::_request_gizmo_for_id(ObjectID p_id) {
+ Node3D *node = Object::cast_to<Node3D>(ObjectDB::get_instance(p_id));
+ if (node) {
+ _request_gizmo(node);
+ }
+}
+
void Node3DEditor::_set_subgizmo_selection(Object *p_obj, Ref<Node3DGizmo> p_gizmo, int p_id, Transform3D p_transform) {
if (p_id == -1) {
_clear_subgizmo_selection(p_obj);
@@ -7588,6 +7830,7 @@ void Node3DEditor::_register_all_gizmos() {
void Node3DEditor::_bind_methods() {
ClassDB::bind_method("_get_editor_data", &Node3DEditor::_get_editor_data);
ClassDB::bind_method("_request_gizmo", &Node3DEditor::_request_gizmo);
+ ClassDB::bind_method("_request_gizmo_for_id", &Node3DEditor::_request_gizmo_for_id);
ClassDB::bind_method("_set_subgizmo_selection", &Node3DEditor::_set_subgizmo_selection);
ClassDB::bind_method("_clear_subgizmo_selection", &Node3DEditor::_clear_subgizmo_selection);
ClassDB::bind_method("_refresh_menu_icons", &Node3DEditor::_refresh_menu_icons);
@@ -8191,6 +8434,7 @@ Node3DEditor::Node3DEditor() {
EDITOR_DEF("editors/3d/manipulator_gizmo_opacity", 0.9);
EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::FLOAT, "editors/3d/manipulator_gizmo_opacity", PROPERTY_HINT_RANGE, "0,1,0.01"));
EDITOR_DEF("editors/3d/navigation/show_viewport_rotation_gizmo", true);
+ EDITOR_DEF("editors/3d/navigation/show_viewport_navigation_gizmo", DisplayServer::get_singleton()->is_touchscreen_available());
current_hover_gizmo_handle = -1;
current_hover_gizmo_handle_secondary = false;
diff --git a/editor/plugins/node_3d_editor_plugin.h b/editor/plugins/node_3d_editor_plugin.h
index 5ea1bf6dc1..53e167ace6 100644
--- a/editor/plugins/node_3d_editor_plugin.h
+++ b/editor/plugins/node_3d_editor_plugin.h
@@ -33,26 +33,31 @@
#include "editor/editor_plugin.h"
#include "editor/editor_scale.h"
-#include "editor/editor_spin_slider.h"
#include "editor/plugins/node_3d_editor_gizmos.h"
-#include "scene/3d/camera_3d.h"
-#include "scene/3d/light_3d.h"
-#include "scene/3d/visual_instance_3d.h"
-#include "scene/3d/world_environment.h"
-#include "scene/gui/color_picker.h"
-#include "scene/gui/panel_container.h"
+#include "scene/gui/box_container.h"
+#include "scene/gui/button.h"
#include "scene/gui/spin_box.h"
-#include "scene/gui/split_container.h"
-#include "scene/resources/environment.h"
-#include "scene/resources/fog_material.h"
-#include "scene/resources/sky_material.h"
+class AcceptDialog;
+class CheckBox;
+class ColorPickerButton;
+class ConfirmationDialog;
+class DirectionalLight3D;
class EditorData;
+class EditorSpinSlider;
+class HSplitContainer;
+class LineEdit;
+class MenuButton;
class Node3DEditor;
class Node3DEditorViewport;
+class OptionButton;
+class PanelContainer;
+class ProceduralSkyMaterial;
+class SubViewport;
class SubViewportContainer;
-class DirectionalLight3D;
+class VSplitContainer;
class WorldEnvironment;
+class ViewportNavigationControl;
class ViewportRotationControl : public Control {
GDCLASS(ViewportRotationControl, Control);
@@ -73,7 +78,7 @@ class ViewportRotationControl : public Control {
Vector<Color> axis_colors;
Vector<int> axis_menu_options;
Vector2i orbiting_mouse_start;
- bool orbiting = false;
+ int orbiting_index = -1;
int focused_axis = -2;
const float AXIS_CIRCLE_RADIUS = 8.0f * EDSCALE;
@@ -86,6 +91,8 @@ protected:
void _get_sorted_axis(Vector<Axis2D> &r_axis);
void _update_focus();
void _on_mouse_exited();
+ void _process_click(int p_index, Vector2 p_position, bool p_pressed);
+ void _process_drag(Ref<InputEventWithModifiers> p_event, int p_index, Vector2 p_position, Vector2 p_relative_position);
public:
void set_viewport(Node3DEditorViewport *p_viewport);
@@ -94,6 +101,7 @@ public:
class Node3DEditorViewport : public Control {
GDCLASS(Node3DEditorViewport, Control);
friend class Node3DEditor;
+ friend class ViewportNavigationControl;
friend class ViewportRotationControl;
enum {
VIEW_TOP,
@@ -232,6 +240,9 @@ private:
Label *preview_material_label_desc = nullptr;
VBoxContainer *top_right_vbox = nullptr;
+ VBoxContainer *bottom_center_vbox = nullptr;
+ ViewportNavigationControl *position_control = nullptr;
+ ViewportNavigationControl *look_control = nullptr;
ViewportRotationControl *rotation_control = nullptr;
Gradient *frame_time_gradient = nullptr;
Label *cpu_time_label = nullptr;
@@ -293,7 +304,8 @@ private:
NAVIGATION_PAN,
NAVIGATION_ZOOM,
NAVIGATION_ORBIT,
- NAVIGATION_LOOK
+ NAVIGATION_LOOK,
+ NAVIGATION_MOVE
};
enum TransformMode {
TRANSFORM_NONE,
@@ -372,6 +384,7 @@ private:
void _view_settings_confirmed(real_t p_interp_delta);
void _update_camera(real_t p_interp_delta);
+ void _update_navigation_controls_visibility();
Transform3D to_camera_transform(const Cursor &p_cursor) const;
void _draw();
@@ -387,6 +400,7 @@ private:
Camera3D *previewing = nullptr;
Camera3D *preview = nullptr;
+ bool previewing_camera;
bool previewing_cinema;
bool _is_node_locked(const Node *p_node);
void _preview_exited_scene();
@@ -569,7 +583,7 @@ private:
bool grid_enabled = false;
bool grid_init_draw = false;
Camera3D::ProjectionType grid_camera_last_update_perspective = Camera3D::PROJECTION_PERSPECTIVE;
- Vector3 grid_camera_last_update_position = Vector3();
+ Vector3 grid_camera_last_update_position;
Ref<ArrayMesh> move_gizmo[3], move_plane_gizmo[3], rotate_gizmo[4], scale_gizmo[3], scale_plane_gizmo[3], axis_gizmo[3];
Ref<StandardMaterial3D> gizmo_color[3];
@@ -704,6 +718,7 @@ private:
Node3D *selected = nullptr;
void _request_gizmo(Object *p_obj);
+ void _request_gizmo_for_id(ObjectID p_id);
void _set_subgizmo_selection(Object *p_obj, Ref<Node3DGizmo> p_gizmo, int p_id, Transform3D p_transform = Transform3D());
void _clear_subgizmo_selection(Object *p_obj = nullptr);
@@ -912,4 +927,31 @@ public:
~Node3DEditorPlugin();
};
+class ViewportNavigationControl : public Control {
+ GDCLASS(ViewportNavigationControl, Control);
+
+ Node3DEditorViewport *viewport = nullptr;
+ Vector2i focused_mouse_start;
+ Vector2 focused_pos;
+ bool hovered = false;
+ int focused_index = -1;
+ Node3DEditorViewport::NavigationMode nav_mode = Node3DEditorViewport::NavigationMode::NAVIGATION_NONE;
+
+ const float AXIS_CIRCLE_RADIUS = 30.0f * EDSCALE;
+
+protected:
+ void _notification(int p_what);
+ virtual void gui_input(const Ref<InputEvent> &p_event) override;
+ void _draw();
+ void _on_mouse_entered();
+ void _on_mouse_exited();
+ void _process_click(int p_index, Vector2 p_position, bool p_pressed);
+ void _process_drag(int p_index, Vector2 p_position, Vector2 p_relative_position);
+ void _update_navigation();
+
+public:
+ void set_navigation_mode(Node3DEditorViewport::NavigationMode p_nav_mode);
+ void set_viewport(Node3DEditorViewport *p_viewport);
+};
+
#endif // NODE_3D_EDITOR_PLUGIN_H
diff --git a/editor/plugins/packed_scene_editor_plugin.cpp b/editor/plugins/packed_scene_editor_plugin.cpp
new file mode 100644
index 0000000000..0a1b96dccb
--- /dev/null
+++ b/editor/plugins/packed_scene_editor_plugin.cpp
@@ -0,0 +1,81 @@
+/*************************************************************************/
+/* packed_scene_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 "packed_scene_editor_plugin.h"
+
+#include "editor/editor_node.h"
+#include "scene/gui/button.h"
+#include "scene/resources/packed_scene.h"
+#include "scene/scene_string_names.h"
+
+void PackedSceneEditor::_on_open_scene_pressed() {
+ // Using deferred call because changing scene updates the Inspector and thus destroys this plugin.
+ callable_mp(EditorNode::get_singleton(), &EditorNode::open_request).call_deferred(packed_scene->get_path());
+}
+
+void PackedSceneEditor::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_ENTER_TREE:
+ case NOTIFICATION_THEME_CHANGED: {
+ open_scene_button->set_icon(get_theme_icon(SNAME("PackedScene"), SNAME("EditorIcons")));
+ } break;
+ }
+}
+
+PackedSceneEditor::PackedSceneEditor(Ref<PackedScene> &p_packed_scene) {
+ packed_scene = p_packed_scene;
+
+ open_scene_button = EditorInspector::create_inspector_action_button(TTR("Open Scene"));
+ open_scene_button->connect(SNAME("pressed"), callable_mp(this, &PackedSceneEditor::_on_open_scene_pressed));
+ open_scene_button->set_disabled(!packed_scene->get_path().get_file().is_valid_filename());
+ add_child(open_scene_button);
+
+ add_child(memnew(Control)); // Add padding before the regular properties.
+}
+
+///////////////////////
+
+bool EditorInspectorPluginPackedScene::can_handle(Object *p_object) {
+ return Object::cast_to<PackedScene>(p_object) != nullptr;
+}
+
+void EditorInspectorPluginPackedScene::parse_begin(Object *p_object) {
+ Ref<PackedScene> packed_scene(p_object);
+ PackedSceneEditor *editor = memnew(PackedSceneEditor(packed_scene));
+ add_custom_control(editor);
+}
+
+///////////////////////
+
+PackedSceneEditorPlugin::PackedSceneEditorPlugin() {
+ Ref<EditorInspectorPluginPackedScene> plugin;
+ plugin.instantiate();
+ add_inspector_plugin(plugin);
+}
diff --git a/editor/plugins/packed_scene_editor_plugin.h b/editor/plugins/packed_scene_editor_plugin.h
new file mode 100644
index 0000000000..0912030180
--- /dev/null
+++ b/editor/plugins/packed_scene_editor_plugin.h
@@ -0,0 +1,68 @@
+/*************************************************************************/
+/* packed_scene_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 PACKED_SCENE_EDITOR_PLUGIN_H
+#define PACKED_SCENE_EDITOR_PLUGIN_H
+
+#include "editor/editor_inspector.h"
+#include "editor/editor_plugin.h"
+#include "scene/gui/box_container.h"
+
+class PackedSceneEditor : public VBoxContainer {
+ GDCLASS(PackedSceneEditor, VBoxContainer);
+
+ Ref<PackedScene> packed_scene;
+ Button *open_scene_button;
+
+ void _on_open_scene_pressed();
+
+protected:
+ void _notification(int p_what);
+
+public:
+ PackedSceneEditor(Ref<PackedScene> &p_packed_scene);
+};
+
+class EditorInspectorPluginPackedScene : public EditorInspectorPlugin {
+ GDCLASS(EditorInspectorPluginPackedScene, EditorInspectorPlugin);
+
+public:
+ virtual bool can_handle(Object *p_object) override;
+ virtual void parse_begin(Object *p_object) override;
+};
+
+class PackedSceneEditorPlugin : public EditorPlugin {
+ GDCLASS(PackedSceneEditorPlugin, EditorPlugin);
+
+public:
+ PackedSceneEditorPlugin();
+};
+
+#endif // PACKED_SCENE_EDITOR_PLUGIN_H
diff --git a/editor/plugins/path_2d_editor_plugin.cpp b/editor/plugins/path_2d_editor_plugin.cpp
index c8bd4c1d05..3204cc8d0f 100644
--- a/editor/plugins/path_2d_editor_plugin.cpp
+++ b/editor/plugins/path_2d_editor_plugin.cpp
@@ -37,6 +37,7 @@
#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_undo_redo_manager.h"
+#include "scene/gui/menu_button.h"
void Path2DEditor::_notification(int p_what) {
switch (p_what) {
@@ -119,6 +120,7 @@ bool Path2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
}
// Check for point deletion.
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
if ((mb->get_button_index() == MouseButton::RIGHT && mode == MODE_EDIT) || (mb->get_button_index() == MouseButton::LEFT && mode == MODE_DELETE)) {
if (dist_to_p < grab_threshold) {
undo_redo->create_action(TTR("Remove Point from Curve"));
@@ -153,6 +155,7 @@ bool Path2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
if (mb->is_pressed() && mb->get_button_index() == MouseButton::LEFT && ((mb->is_command_or_control_pressed() && mode == MODE_EDIT) || mode == MODE_CREATE)) {
Ref<Curve2D> curve = node->get_curve();
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Add Point to Curve"));
undo_redo->add_do_method(curve.ptr(), "add_point", cpoint);
undo_redo->add_undo_method(curve.ptr(), "remove_point", curve->get_point_count());
@@ -188,6 +191,7 @@ bool Path2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
insertion_point = curve->get_point_count() - 2;
}
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Split Curve"));
undo_redo->add_do_method(curve.ptr(), "add_point", xform.affine_inverse().xform(gpoint2), Vector2(0, 0), Vector2(0, 0), insertion_point + 1);
undo_redo->add_undo_method(curve.ptr(), "remove_point", insertion_point + 1);
@@ -211,6 +215,7 @@ bool Path2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
if (!mb->is_pressed() && mb->get_button_index() == MouseButton::LEFT && action != ACTION_NONE) {
Ref<Curve2D> curve = node->get_curve();
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
Vector2 new_pos = moving_from + xform.affine_inverse().basis_xform(gpoint - moving_screen_from);
switch (action) {
case ACTION_NONE:
@@ -486,6 +491,7 @@ void Path2DEditor::_mode_selected(int p_mode) {
return;
}
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Remove Point from Curve"));
undo_redo->add_do_method(node->get_curve().ptr(), "add_point", begin);
undo_redo->add_undo_method(node->get_curve().ptr(), "remove_point", node->get_curve()->get_point_count());
@@ -519,7 +525,6 @@ void Path2DEditor::_handle_option_pressed(int p_option) {
Path2DEditor::Path2DEditor() {
canvas_item_editor = nullptr;
- undo_redo = EditorNode::get_singleton()->get_undo_redo();
mirror_handle_angle = true;
mirror_handle_length = true;
on_edge = false;
diff --git a/editor/plugins/path_2d_editor_plugin.h b/editor/plugins/path_2d_editor_plugin.h
index 13eca79010..c6ed257540 100644
--- a/editor/plugins/path_2d_editor_plugin.h
+++ b/editor/plugins/path_2d_editor_plugin.h
@@ -33,16 +33,15 @@
#include "editor/editor_plugin.h"
#include "scene/2d/path_2d.h"
+#include "scene/gui/box_container.h"
#include "scene/gui/separator.h"
class CanvasItemEditor;
-class EditorUndoRedoManager;
+class MenuButton;
class Path2DEditor : public HBoxContainer {
GDCLASS(Path2DEditor, HBoxContainer);
- Ref<EditorUndoRedoManager> undo_redo;
-
CanvasItemEditor *canvas_item_editor = nullptr;
Panel *panel = nullptr;
Path2D *node = nullptr;
diff --git a/editor/plugins/path_3d_editor_plugin.cpp b/editor/plugins/path_3d_editor_plugin.cpp
index d7953bf4e0..7a9e50e482 100644
--- a/editor/plugins/path_3d_editor_plugin.cpp
+++ b/editor/plugins/path_3d_editor_plugin.cpp
@@ -37,6 +37,7 @@
#include "editor/editor_settings.h"
#include "editor/editor_undo_redo_manager.h"
#include "node_3d_editor_plugin.h"
+#include "scene/gui/menu_button.h"
#include "scene/resources/curve.h"
static bool _is_in_handle(int p_id, int p_num_points) {
@@ -239,38 +240,60 @@ void Path3DGizmo::redraw() {
return;
}
- Vector<Vector3> v3a = c->tessellate();
- //Vector<Vector3> v3a=c->get_baked_points();
+ real_t interval = 0.1;
+ const real_t length = c->get_baked_length();
- int v3s = v3a.size();
- if (v3s == 0) {
- return;
- }
- Vector<Vector3> v3p;
- const Vector3 *r = v3a.ptr();
-
- // BUG: the following won't work when v3s, avoid drawing as a temporary workaround.
- for (int i = 0; i < v3s - 1; i++) {
- v3p.push_back(r[i]);
- v3p.push_back(r[i + 1]);
- //v3p.push_back(r[i]);
- //v3p.push_back(r[i]+Vector3(0,0.2,0));
- }
+ // 1. Draw curve and bones.
+ if (length > CMP_EPSILON) {
+ const int sample_count = int(length / interval) + 2;
+ interval = length / (sample_count - 1); // Recalculate real interval length.
+
+ Vector<Transform3D> frames;
+ frames.resize(sample_count);
+
+ {
+ Transform3D *w = frames.ptrw();
+
+ for (int i = 0; i < sample_count; i++) {
+ w[i] = c->sample_baked_with_rotation(i * interval, true, true);
+ }
+ }
+
+ const Transform3D *r = frames.ptr();
+ Vector<Vector3> v3p;
+ for (int i = 0; i < sample_count - 1; i++) {
+ const Vector3 p1 = r[i].origin;
+ const Vector3 p2 = r[i + 1].origin;
+ const Vector3 side = r[i].basis.get_column(0);
+ const Vector3 up = r[i].basis.get_column(1);
+ const Vector3 forward = r[i].basis.get_column(2);
+
+ // Curve segment.
+ v3p.push_back(p1);
+ v3p.push_back(p2);
+
+ // Fish Bone.
+ v3p.push_back(p1);
+ v3p.push_back(p1 + (side - forward + up * 0.3) * 0.06);
+
+ v3p.push_back(p1);
+ v3p.push_back(p1 + (-side - forward + up * 0.3) * 0.06);
+ }
- if (v3p.size() > 1) {
add_lines(v3p, path_material);
add_collision_segments(v3p);
}
+ // 2. Draw handles.
if (Path3DEditorPlugin::singleton->get_edited_path() == path) {
- v3p.clear();
+ Vector<Vector3> v3p;
Vector<Vector3> handle_points;
Vector<Vector3> sec_handle_points;
for (int i = 0; i < c->get_point_count(); i++) {
Vector3 p = c->get_point_position(i);
handle_points.push_back(p);
- // push Out points first so they get selected if the In and Out points are on top of each other.
+ // Push out points first so they get selected if the In and Out points are on top of each other.
if (i < c->get_point_count() - 1) {
v3p.push_back(p);
v3p.push_back(p + c->get_point_out(i));
diff --git a/editor/plugins/path_3d_editor_plugin.h b/editor/plugins/path_3d_editor_plugin.h
index 11a640b79f..a2816c89ae 100644
--- a/editor/plugins/path_3d_editor_plugin.h
+++ b/editor/plugins/path_3d_editor_plugin.h
@@ -37,6 +37,8 @@
#include "scene/3d/path_3d.h"
#include "scene/gui/separator.h"
+class MenuButton;
+
class Path3DGizmo : public EditorNode3DGizmo {
GDCLASS(Path3DGizmo, EditorNode3DGizmo);
diff --git a/editor/plugins/physical_bone_3d_editor_plugin.cpp b/editor/plugins/physical_bone_3d_editor_plugin.cpp
index 9dc89133c4..2b59e4cf08 100644
--- a/editor/plugins/physical_bone_3d_editor_plugin.cpp
+++ b/editor/plugins/physical_bone_3d_editor_plugin.cpp
@@ -31,6 +31,7 @@
#include "physical_bone_3d_editor_plugin.h"
#include "editor/plugins/node_3d_editor_plugin.h"
+#include "scene/gui/separator.h"
void PhysicalBone3DEditor::_bind_methods() {
}
diff --git a/editor/plugins/polygon_2d_editor_plugin.cpp b/editor/plugins/polygon_2d_editor_plugin.cpp
index 6218c887fb..a19a42f951 100644
--- a/editor/plugins/polygon_2d_editor_plugin.cpp
+++ b/editor/plugins/polygon_2d_editor_plugin.cpp
@@ -38,10 +38,14 @@
#include "editor/editor_undo_redo_manager.h"
#include "editor/plugins/canvas_item_editor_plugin.h"
#include "scene/2d/skeleton_2d.h"
+#include "scene/gui/check_box.h"
#include "scene/gui/menu_button.h"
#include "scene/gui/scroll_container.h"
#include "scene/gui/separator.h"
#include "scene/gui/slider.h"
+#include "scene/gui/spin_box.h"
+#include "scene/gui/split_container.h"
+#include "scene/gui/texture_rect.h"
#include "scene/gui/view_panner.h"
Node2D *Polygon2DEditor::_get_node() const {
diff --git a/editor/plugins/polygon_2d_editor_plugin.h b/editor/plugins/polygon_2d_editor_plugin.h
index d878d3f9af..6021401e4f 100644
--- a/editor/plugins/polygon_2d_editor_plugin.h
+++ b/editor/plugins/polygon_2d_editor_plugin.h
@@ -33,11 +33,17 @@
#include "editor/plugins/abstract_polygon_2d_editor.h"
+class AcceptDialog;
+class ButtonGroup;
+class HScrollBar;
class HSlider;
+class MenuButton;
class Panel;
class ScrollContainer;
class SpinBox;
+class TextureRect;
class ViewPanner;
+class VScrollBar;
class Polygon2DEditor : public AbstractPolygon2DEditor {
GDCLASS(Polygon2DEditor, AbstractPolygon2DEditor);
diff --git a/editor/plugins/polygon_3d_editor_plugin.cpp b/editor/plugins/polygon_3d_editor_plugin.cpp
index dc6ae6be96..dde44d31fa 100644
--- a/editor/plugins/polygon_3d_editor_plugin.cpp
+++ b/editor/plugins/polygon_3d_editor_plugin.cpp
@@ -41,6 +41,7 @@
#include "editor/editor_undo_redo_manager.h"
#include "node_3d_editor_plugin.h"
#include "scene/3d/camera_3d.h"
+#include "scene/gui/separator.h"
void Polygon3DEditor::_notification(int p_what) {
switch (p_what) {
@@ -95,6 +96,7 @@ void Polygon3DEditor::_menu_option(int p_option) {
void Polygon3DEditor::_wip_close() {
Object *obj = node_resource.is_valid() ? (Object *)node_resource.ptr() : node;
ERR_FAIL_COND_MSG(!obj, "Edited object is not valid.");
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Create Polygon3D"));
undo_redo->add_undo_method(obj, "set_polygon", obj->call("get_polygon"));
undo_redo->add_do_method(obj, "set_polygon", wip);
@@ -184,6 +186,7 @@ EditorPlugin::AfterGUIInput Polygon3DEditor::forward_3d_gui_input(Camera3D *p_ca
if (mb->is_pressed()) {
if (mb->is_ctrl_pressed()) {
if (poly.size() < 3) {
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Edit Poly"));
undo_redo->add_undo_method(obj, "set_polygon", poly);
poly.push_back(cpoint);
@@ -262,6 +265,7 @@ EditorPlugin::AfterGUIInput Polygon3DEditor::forward_3d_gui_input(Camera3D *p_ca
ERR_FAIL_INDEX_V(edited_point, poly.size(), EditorPlugin::AFTER_GUI_INPUT_PASS);
poly.write[edited_point] = edited_point_pos;
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Edit Poly"));
undo_redo->add_do_method(obj, "set_polygon", poly);
undo_redo->add_undo_method(obj, "set_polygon", pre_move_edit);
@@ -290,6 +294,7 @@ EditorPlugin::AfterGUIInput Polygon3DEditor::forward_3d_gui_input(Camera3D *p_ca
}
if (closest_idx >= 0) {
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Edit Poly (Remove Point)"));
undo_redo->add_undo_method(obj, "set_polygon", poly);
poly.remove_at(closest_idx);
@@ -527,7 +532,6 @@ void Polygon3DEditor::_bind_methods() {
Polygon3DEditor::Polygon3DEditor() {
node = nullptr;
- undo_redo = EditorNode::get_undo_redo();
add_child(memnew(VSeparator));
button_create = memnew(Button);
diff --git a/editor/plugins/polygon_3d_editor_plugin.h b/editor/plugins/polygon_3d_editor_plugin.h
index 918072b429..2fa9820aa6 100644
--- a/editor/plugins/polygon_3d_editor_plugin.h
+++ b/editor/plugins/polygon_3d_editor_plugin.h
@@ -34,15 +34,15 @@
#include "editor/editor_plugin.h"
#include "scene/3d/collision_polygon_3d.h"
#include "scene/3d/mesh_instance_3d.h"
+#include "scene/gui/box_container.h"
#include "scene/resources/immediate_mesh.h"
class CanvasItemEditor;
-class EditorUndoRedoManager;
+class MenuButton;
class Polygon3DEditor : public HBoxContainer {
GDCLASS(Polygon3DEditor, HBoxContainer);
- Ref<EditorUndoRedoManager> undo_redo;
enum Mode {
MODE_CREATE,
MODE_EDIT,
diff --git a/editor/plugins/resource_preloader_editor_plugin.cpp b/editor/plugins/resource_preloader_editor_plugin.cpp
index e35e794b24..2794b02ba6 100644
--- a/editor/plugins/resource_preloader_editor_plugin.cpp
+++ b/editor/plugins/resource_preloader_editor_plugin.cpp
@@ -71,6 +71,7 @@ void ResourcePreloaderEditor::_files_load_request(const Vector<String> &p_paths)
name = basename + " " + itos(counter);
}
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Add Resource"));
undo_redo->add_do_method(preloader, "add_resource", name, resource);
undo_redo->add_undo_method(preloader, "remove_resource", name);
@@ -115,6 +116,7 @@ void ResourcePreloaderEditor::_item_edited() {
}
Ref<Resource> samp = preloader->get_resource(old_name);
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Rename Resource"));
undo_redo->add_do_method(preloader, "remove_resource", old_name);
undo_redo->add_do_method(preloader, "add_resource", new_name, samp);
@@ -127,6 +129,7 @@ void ResourcePreloaderEditor::_item_edited() {
}
void ResourcePreloaderEditor::_remove_resource(const String &p_to_remove) {
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Delete Resource"));
undo_redo->add_do_method(preloader, "remove_resource", p_to_remove);
undo_redo->add_undo_method(preloader, "add_resource", p_to_remove, preloader->get_resource(p_to_remove));
@@ -160,6 +163,7 @@ void ResourcePreloaderEditor::_paste_pressed() {
name = basename + " " + itos(counter);
}
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Paste Resource"));
undo_redo->add_do_method(preloader, "add_resource", name, r);
undo_redo->add_undo_method(preloader, "remove_resource", name);
@@ -235,10 +239,6 @@ void ResourcePreloaderEditor::_cell_button_pressed(Object *p_item, int p_column,
}
}
-void ResourcePreloaderEditor::set_undo_redo(Ref<EditorUndoRedoManager> p_undo_redo) {
- undo_redo = p_undo_redo;
-}
-
void ResourcePreloaderEditor::edit(ResourcePreloader *p_preloader) {
preloader = p_preloader;
@@ -322,6 +322,7 @@ void ResourcePreloaderEditor::drop_data_fw(const Point2 &p_point, const Variant
name = basename + "_" + itos(counter);
}
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Add Resource"));
undo_redo->add_do_method(preloader, "add_resource", name, r);
undo_redo->add_undo_method(preloader, "remove_resource", name);
@@ -392,7 +393,6 @@ ResourcePreloaderEditor::ResourcePreloaderEditor() {
}
void ResourcePreloaderEditorPlugin::edit(Object *p_object) {
- preloader_editor->set_undo_redo(EditorNode::get_undo_redo());
ResourcePreloader *s = Object::cast_to<ResourcePreloader>(p_object);
if (!s) {
return;
diff --git a/editor/plugins/resource_preloader_editor_plugin.h b/editor/plugins/resource_preloader_editor_plugin.h
index ef80283dae..7c1be9114d 100644
--- a/editor/plugins/resource_preloader_editor_plugin.h
+++ b/editor/plugins/resource_preloader_editor_plugin.h
@@ -33,11 +33,11 @@
#include "editor/editor_plugin.h"
#include "scene/gui/dialogs.h"
+#include "scene/gui/panel_container.h"
#include "scene/gui/tree.h"
#include "scene/main/resource_preloader.h"
class EditorFileDialog;
-class EditorUndoRedoManager;
class ResourcePreloaderEditor : public PanelContainer {
GDCLASS(ResourcePreloaderEditor, PanelContainer);
@@ -67,8 +67,6 @@ class ResourcePreloaderEditor : public PanelContainer {
void _cell_button_pressed(Object *p_item, int p_column, int p_id, MouseButton p_button);
void _item_edited();
- Ref<EditorUndoRedoManager> undo_redo;
-
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);
@@ -79,8 +77,6 @@ protected:
static void _bind_methods();
public:
- void set_undo_redo(Ref<EditorUndoRedoManager> p_undo_redo);
-
void edit(ResourcePreloader *p_preloader);
ResourcePreloaderEditor();
};
diff --git a/editor/plugins/root_motion_editor_plugin.cpp b/editor/plugins/root_motion_editor_plugin.cpp
index de30c4100d..93a64a8f3d 100644
--- a/editor/plugins/root_motion_editor_plugin.cpp
+++ b/editor/plugins/root_motion_editor_plugin.cpp
@@ -30,6 +30,9 @@
#include "root_motion_editor_plugin.h"
#include "editor/editor_node.h"
+#include "scene/animation/animation_player.h"
+#include "scene/animation/animation_tree.h"
+#include "scene/gui/tree.h"
#include "scene/main/window.h"
void EditorPropertyRootMotion::_confirmed() {
@@ -45,8 +48,6 @@ void EditorPropertyRootMotion::_confirmed() {
}
void EditorPropertyRootMotion::_node_assign() {
- NodePath current = get_edited_object()->get(get_edited_property());
-
AnimationTree *atree = Object::cast_to<AnimationTree>(get_edited_object());
if (!atree->has_node(atree->get_animation_player())) {
EditorNode::get_singleton()->show_warning(TTR("AnimationTree has no path set to an AnimationPlayer"));
@@ -73,7 +74,10 @@ void EditorPropertyRootMotion::_node_assign() {
for (const StringName &E : animations) {
Ref<Animation> anim = player->get_animation(E);
for (int i = 0; i < anim->get_track_count(); i++) {
- paths.insert(anim->track_get_path(i));
+ String pathname = anim->track_get_path(i).get_concatenated_names();
+ if (!paths.has(pathname)) {
+ paths.insert(pathname);
+ }
}
}
}
@@ -122,66 +126,33 @@ void EditorPropertyRootMotion::_node_assign() {
continue; //no node, can't edit
}
- if (path.get_subname_count()) {
- String concat = path.get_concatenated_subnames();
-
- Skeleton3D *skeleton = Object::cast_to<Skeleton3D>(node);
- if (skeleton && skeleton->find_bone(concat) != -1) {
- //path in skeleton
- const String &bone = concat;
- int idx = skeleton->find_bone(bone);
- List<String> bone_path;
- while (idx != -1) {
- bone_path.push_front(skeleton->get_bone_name(idx));
- idx = skeleton->get_bone_parent(idx);
+ Skeleton3D *skeleton = Object::cast_to<Skeleton3D>(node);
+ if (skeleton) {
+ HashMap<int, TreeItem *> items;
+ items.insert(-1, ti);
+ Ref<Texture> bone_icon = get_theme_icon(SNAME("BoneAttachment3D"), SNAME("EditorIcons"));
+ Vector<int> bones_to_process = skeleton->get_parentless_bones();
+ while (bones_to_process.size() > 0) {
+ int current_bone_idx = bones_to_process[0];
+ bones_to_process.erase(current_bone_idx);
+
+ Vector<int> current_bone_child_bones = skeleton->get_bone_children(current_bone_idx);
+ int child_bone_size = current_bone_child_bones.size();
+ for (int i = 0; i < child_bone_size; i++) {
+ bones_to_process.push_back(current_bone_child_bones[i]);
}
- accum += ":";
- for (List<String>::Element *F = bone_path.front(); F; F = F->next()) {
- if (F != bone_path.front()) {
- accum += "/";
- }
-
- accum += F->get();
- if (!parenthood.has(accum)) {
- ti = filters->create_item(ti);
- parenthood[accum] = ti;
- ti->set_text(0, F->get());
- ti->set_selectable(0, true);
- ti->set_editable(0, false);
- ti->set_icon(0, get_theme_icon(SNAME("BoneAttachment3D"), SNAME("EditorIcons")));
- ti->set_metadata(0, accum);
- } else {
- ti = parenthood[accum];
- }
- }
+ const int parent_idx = skeleton->get_bone_parent(current_bone_idx);
+ TreeItem *parent_item = items.find(parent_idx)->value;
- ti->set_selectable(0, true);
- ti->set_text(0, concat);
- ti->set_icon(0, get_theme_icon(SNAME("BoneAttachment3D"), SNAME("EditorIcons")));
- ti->set_metadata(0, path);
- if (path == current) {
- ti->select(0);
- }
+ TreeItem *joint_item = filters->create_item(parent_item);
+ items.insert(current_bone_idx, joint_item);
- } else {
- //just a property
- ti = filters->create_item(ti);
- ti->set_text(0, concat);
- ti->set_selectable(0, true);
- ti->set_metadata(0, path);
- if (path == current) {
- ti->select(0);
- }
- }
- } else {
- if (ti) {
- //just a node, likely call or animation track
- ti->set_selectable(0, true);
- ti->set_metadata(0, path);
- if (path == current) {
- ti->select(0);
- }
+ joint_item->set_text(0, skeleton->get_bone_name(current_bone_idx));
+ joint_item->set_icon(0, bone_icon);
+ joint_item->set_selectable(0, true);
+ joint_item->set_metadata(0, accum + ":" + skeleton->get_bone_name(current_bone_idx));
+ joint_item->set_collapsed(true);
}
}
}
@@ -197,7 +168,6 @@ void EditorPropertyRootMotion::_node_clear() {
void EditorPropertyRootMotion::update_property() {
NodePath p = get_edited_object()->get(get_edited_property());
-
assign->set_tooltip_text(p);
if (p == NodePath()) {
assign->set_icon(Ref<Texture2D>());
@@ -206,26 +176,8 @@ void EditorPropertyRootMotion::update_property() {
return;
}
- Node *base_node = nullptr;
- if (base_hint != NodePath()) {
- if (get_tree()->get_root()->has_node(base_hint)) {
- base_node = get_tree()->get_root()->get_node(base_hint);
- }
- } else {
- base_node = Object::cast_to<Node>(get_edited_object());
- }
-
- if (!base_node || !base_node->has_node(p)) {
- assign->set_icon(Ref<Texture2D>());
- assign->set_text(p);
- return;
- }
-
- Node *target_node = base_node->get_node(p);
- ERR_FAIL_COND(!target_node);
-
- assign->set_text(target_node->get_name());
- assign->set_icon(EditorNode::get_singleton()->get_object_icon(target_node, "Node"));
+ assign->set_icon(Ref<Texture2D>());
+ assign->set_text(p);
}
void EditorPropertyRootMotion::setup(const NodePath &p_base_hint) {
@@ -280,9 +232,6 @@ bool EditorInspectorRootMotionPlugin::can_handle(Object *p_object) {
bool EditorInspectorRootMotionPlugin::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 == "root_motion_track" && p_object->is_class("AnimationTree") && p_type == Variant::NODE_PATH) {
EditorPropertyRootMotion *editor = memnew(EditorPropertyRootMotion);
- if (p_hint == PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE && !p_hint_text.is_empty()) {
- editor->setup(p_hint_text);
- }
add_property_editor(p_path, editor);
return true;
}
diff --git a/editor/plugins/root_motion_editor_plugin.h b/editor/plugins/root_motion_editor_plugin.h
index 5b8c1d77b3..7134b48c36 100644
--- a/editor/plugins/root_motion_editor_plugin.h
+++ b/editor/plugins/root_motion_editor_plugin.h
@@ -32,9 +32,8 @@
#define ROOT_MOTION_EDITOR_PLUGIN_H
#include "editor/editor_inspector.h"
-#include "editor/editor_spin_slider.h"
-#include "editor/property_selector.h"
-#include "scene/animation/animation_tree.h"
+
+class Tree;
class EditorPropertyRootMotion : public EditorProperty {
GDCLASS(EditorPropertyRootMotion, EditorProperty);
diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp
index 4ff3919e9b..bb5491fcb5 100644
--- a/editor/plugins/script_editor_plugin.cpp
+++ b/editor/plugins/script_editor_plugin.cpp
@@ -40,6 +40,7 @@
#include "editor/debugger/editor_debugger_node.h"
#include "editor/debugger/script_editor_debugger.h"
#include "editor/editor_file_dialog.h"
+#include "editor/editor_help_search.h"
#include "editor/editor_node.h"
#include "editor/editor_paths.h"
#include "editor/editor_run_script.h"
@@ -47,6 +48,7 @@
#include "editor/editor_settings.h"
#include "editor/filesystem_dock.h"
#include "editor/find_in_files.h"
+#include "editor/inspector_dock.h"
#include "editor/node_dock.h"
#include "editor/plugins/shader_editor_plugin.h"
#include "editor/plugins/text_shader_editor.h"
diff --git a/editor/plugins/script_editor_plugin.h b/editor/plugins/script_editor_plugin.h
index a45ce4cc22..213fbdc22a 100644
--- a/editor/plugins/script_editor_plugin.h
+++ b/editor/plugins/script_editor_plugin.h
@@ -31,23 +31,22 @@
#ifndef SCRIPT_EDITOR_PLUGIN_H
#define SCRIPT_EDITOR_PLUGIN_H
-#include "core/object/script_language.h"
-#include "editor/code_editor.h"
-#include "editor/editor_help.h"
-#include "editor/editor_help_search.h"
#include "editor/editor_plugin.h"
-#include "editor/script_create_dialog.h"
-#include "scene/gui/item_list.h"
-#include "scene/gui/line_edit.h"
-#include "scene/gui/menu_button.h"
-#include "scene/gui/split_container.h"
-#include "scene/gui/tab_container.h"
-#include "scene/gui/text_edit.h"
-#include "scene/gui/tree.h"
-#include "scene/main/timer.h"
+#include "scene/gui/dialogs.h"
+#include "scene/gui/panel_container.h"
+#include "scene/resources/syntax_highlighter.h"
#include "scene/resources/text_file.h"
class EditorFileDialog;
+class EditorHelpSearch;
+class FindReplaceBar;
+class HSplitContainer;
+class ItemList;
+class MenuButton;
+class TabContainer;
+class TextureRect;
+class Tree;
+class VSplitContainer;
class EditorSyntaxHighlighter : public SyntaxHighlighter {
GDCLASS(EditorSyntaxHighlighter, SyntaxHighlighter)
diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp
index 0d12d07aa7..38639ac811 100644
--- a/editor/plugins/script_text_editor.cpp
+++ b/editor/plugins/script_text_editor.cpp
@@ -38,6 +38,7 @@
#include "editor/editor_node.h"
#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
+#include "scene/gui/split_container.h"
void ConnectionInfoDialog::ok_pressed() {
}
@@ -1222,7 +1223,9 @@ void ScriptTextEditor::_edit_option(int p_op) {
code_editor->duplicate_selection();
} break;
case EDIT_TOGGLE_FOLD_LINE: {
- tx->toggle_foldable_line(tx->get_caret_line());
+ for (int caret_idx = 0; caret_idx < tx->get_caret_count(); caret_idx++) {
+ tx->toggle_foldable_line(tx->get_caret_line(caret_idx));
+ }
tx->queue_redraw();
} break;
case EDIT_FOLD_ALL_LINES: {
@@ -1290,28 +1293,28 @@ void ScriptTextEditor::_edit_option(int p_op) {
} break;
case EDIT_EVALUATE: {
Expression expression;
- Vector<String> lines = code_editor->get_text_editor()->get_selected_text().split("\n");
- PackedStringArray results;
-
- for (int i = 0; i < lines.size(); i++) {
- String line = lines[i];
- String whitespace = line.substr(0, line.size() - line.strip_edges(true, false).size()); //extract the whitespace at the beginning
-
- if (expression.parse(line) == OK) {
- Variant result = expression.execute(Array(), Variant(), false, true);
- if (expression.get_error_text().is_empty()) {
- results.push_back(whitespace + result.get_construct_string());
+ tx->begin_complex_operation();
+ for (int caret_idx = 0; caret_idx < tx->get_caret_count(); caret_idx++) {
+ Vector<String> lines = tx->get_selected_text(caret_idx).split("\n");
+ PackedStringArray results;
+
+ for (int i = 0; i < lines.size(); i++) {
+ String line = lines[i];
+ String whitespace = line.substr(0, line.size() - line.strip_edges(true, false).size()); // Extract the whitespace at the beginning.
+ if (expression.parse(line) == OK) {
+ Variant result = expression.execute(Array(), Variant(), false, true);
+ if (expression.get_error_text().is_empty()) {
+ results.push_back(whitespace + result.get_construct_string());
+ } else {
+ results.push_back(line);
+ }
} else {
results.push_back(line);
}
- } else {
- results.push_back(line);
}
+ tx->insert_text_at_caret(String("\n").join(results), caret_idx);
}
-
- code_editor->get_text_editor()->begin_complex_operation(); //prevents creating a two-step undo
- code_editor->get_text_editor()->insert_text_at_caret(String("\n").join(results));
- code_editor->get_text_editor()->end_complex_operation();
+ tx->end_complex_operation();
} break;
case SEARCH_FIND: {
code_editor->get_find_replace_bar()->popup_search();
@@ -1326,14 +1329,14 @@ void ScriptTextEditor::_edit_option(int p_op) {
code_editor->get_find_replace_bar()->popup_replace();
} break;
case SEARCH_IN_FILES: {
- String selected_text = code_editor->get_text_editor()->get_selected_text();
+ String selected_text = tx->get_selected_text();
// Yep, because it doesn't make sense to instance this dialog for every single script open...
// So this will be delegated to the ScriptEditor.
emit_signal(SNAME("search_in_files_requested"), selected_text);
} break;
case REPLACE_IN_FILES: {
- String selected_text = code_editor->get_text_editor()->get_selected_text();
+ String selected_text = tx->get_selected_text();
emit_signal(SNAME("replace_in_files_requested"), selected_text);
} break;
@@ -1357,10 +1360,12 @@ void ScriptTextEditor::_edit_option(int p_op) {
code_editor->remove_all_bookmarks();
} break;
case DEBUG_TOGGLE_BREAKPOINT: {
- int line = tx->get_caret_line();
- bool dobreak = !tx->is_line_breakpointed(line);
- tx->set_line_as_breakpoint(line, dobreak);
- EditorDebuggerNode::get_singleton()->set_breakpoint(script->get_path(), line + 1, dobreak);
+ for (int caret_idx = 0; caret_idx < tx->get_caret_count(); caret_idx++) {
+ int line = tx->get_caret_line(caret_idx);
+ bool dobreak = !tx->is_line_breakpointed(line);
+ tx->set_line_as_breakpoint(line, dobreak);
+ EditorDebuggerNode::get_singleton()->set_breakpoint(script->get_path(), line + 1, dobreak);
+ }
} break;
case DEBUG_REMOVE_ALL_BREAKPOINTS: {
PackedInt32Array bpoints = tx->get_breakpointed_lines();
@@ -1378,26 +1383,14 @@ void ScriptTextEditor::_edit_option(int p_op) {
return;
}
- tx->remove_secondary_carets();
- int line = tx->get_caret_line();
-
- // wrap around
- if (line >= (int)bpoints[bpoints.size() - 1]) {
- tx->unfold_line(bpoints[0]);
- tx->set_caret_line(bpoints[0]);
- tx->center_viewport_to_caret();
- } else {
- for (int i = 0; i < bpoints.size(); i++) {
- int bline = bpoints[i];
- if (bline > line) {
- tx->unfold_line(bline);
- tx->set_caret_line(bline);
- tx->center_viewport_to_caret();
- return;
- }
+ int current_line = tx->get_caret_line();
+ int bpoint_idx = 0;
+ if (current_line < (int)bpoints[bpoints.size() - 1]) {
+ while (bpoint_idx < bpoints.size() && bpoints[bpoint_idx] <= current_line) {
+ bpoint_idx++;
}
}
-
+ code_editor->goto_line_centered(bpoints[bpoint_idx]);
} break;
case DEBUG_GOTO_PREV_BREAKPOINT: {
PackedInt32Array bpoints = tx->get_breakpointed_lines();
@@ -1405,25 +1398,14 @@ void ScriptTextEditor::_edit_option(int p_op) {
return;
}
- tx->remove_secondary_carets();
- int line = tx->get_caret_line();
- // wrap around
- if (line <= (int)bpoints[0]) {
- tx->unfold_line(bpoints[bpoints.size() - 1]);
- tx->set_caret_line(bpoints[bpoints.size() - 1]);
- tx->center_viewport_to_caret();
- } else {
- for (int i = bpoints.size() - 1; i >= 0; i--) {
- int bline = bpoints[i];
- if (bline < line) {
- tx->unfold_line(bline);
- tx->set_caret_line(bline);
- tx->center_viewport_to_caret();
- return;
- }
+ int current_line = tx->get_caret_line();
+ int bpoint_idx = bpoints.size() - 1;
+ if (current_line > (int)bpoints[0]) {
+ while (bpoint_idx >= 0 && bpoints[bpoint_idx] >= current_line) {
+ bpoint_idx--;
}
}
-
+ code_editor->goto_line_centered(bpoints[bpoint_idx]);
} break;
case HELP_CONTEXTUAL: {
String text = tx->get_selected_text(0);
@@ -1834,7 +1816,7 @@ void ScriptTextEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) {
base = _find_node_for_script(base, base, script);
}
ScriptLanguage::LookupResult result;
- if (script->get_language()->lookup_code(code_editor->get_text_editor()->get_text_for_symbol_lookup(), word_at_pos, script->get_path(), base, result) == OK) {
+ if (script->get_language()->lookup_code(tx->get_text_for_symbol_lookup(), word_at_pos, script->get_path(), base, result) == OK) {
open_docs = true;
}
}
@@ -1860,7 +1842,7 @@ void ScriptTextEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) {
if (valid) {
color_args = line.substr(begin, end - begin);
String stripped = color_args.replace(" ", "").replace("(", "").replace(")", "");
- Vector<float> color = stripped.split_floats(",");
+ PackedFloat64Array color = stripped.split_floats(",");
if (color.size() > 2) {
float alpha = color.size() > 3 ? color[3] : 1.0f;
color_picker->set_pick_color(Color(color[0], color[1], color[2], alpha));
diff --git a/editor/plugins/script_text_editor.h b/editor/plugins/script_text_editor.h
index 5fd12674b3..cbc4153e12 100644
--- a/editor/plugins/script_text_editor.h
+++ b/editor/plugins/script_text_editor.h
@@ -31,10 +31,14 @@
#ifndef SCRIPT_TEXT_EDITOR_H
#define SCRIPT_TEXT_EDITOR_H
+#include "script_editor_plugin.h"
+
+#include "editor/code_editor.h"
#include "scene/gui/color_picker.h"
#include "scene/gui/dialogs.h"
#include "scene/gui/tree.h"
-#include "script_editor_plugin.h"
+
+class RichTextLabel;
class ConnectionInfoDialog : public AcceptDialog {
GDCLASS(ConnectionInfoDialog, AcceptDialog);
diff --git a/editor/plugins/shader_editor_plugin.cpp b/editor/plugins/shader_editor_plugin.cpp
index 2f80e41dd4..fbc94c70f8 100644
--- a/editor/plugins/shader_editor_plugin.cpp
+++ b/editor/plugins/shader_editor_plugin.cpp
@@ -34,9 +34,12 @@
#include "editor/editor_scale.h"
#include "editor/editor_undo_redo_manager.h"
#include "editor/filesystem_dock.h"
+#include "editor/inspector_dock.h"
#include "editor/plugins/text_shader_editor.h"
#include "editor/plugins/visual_shader_editor_plugin.h"
#include "editor/shader_create_dialog.h"
+#include "scene/gui/item_list.h"
+#include "scene/gui/texture_rect.h"
void ShaderEditorPlugin::_update_shader_list() {
shader_list->clear();
diff --git a/editor/plugins/shader_editor_plugin.h b/editor/plugins/shader_editor_plugin.h
index 7638778af7..4f0894a1a9 100644
--- a/editor/plugins/shader_editor_plugin.h
+++ b/editor/plugins/shader_editor_plugin.h
@@ -35,6 +35,7 @@
class HSplitContainer;
class ItemList;
+class MenuButton;
class ShaderCreateDialog;
class TabContainer;
class TextShaderEditor;
@@ -95,6 +96,7 @@ protected:
static void _bind_methods();
public:
+ virtual String get_name() const override { return "Shader"; }
virtual void edit(Object *p_object) override;
virtual bool handles(Object *p_object) const override;
virtual void make_visible(bool p_visible) override;
diff --git a/editor/plugins/shader_file_editor_plugin.cpp b/editor/plugins/shader_file_editor_plugin.cpp
index 4874944d33..4e33c421ae 100644
--- a/editor/plugins/shader_file_editor_plugin.cpp
+++ b/editor/plugins/shader_file_editor_plugin.cpp
@@ -37,6 +37,8 @@
#include "editor/editor_node.h"
#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
+#include "scene/gui/item_list.h"
+#include "scene/gui/split_container.h"
#include "servers/display_server.h"
#include "servers/rendering/shader_types.h"
@@ -286,6 +288,7 @@ ShaderFileEditor::ShaderFileEditor() {
error_text = memnew(RichTextLabel);
error_text->set_v_size_flags(SIZE_EXPAND_FILL);
+ error_text->set_selection_enabled(true);
main_vb->add_child(error_text);
}
diff --git a/editor/plugins/skeleton_2d_editor_plugin.cpp b/editor/plugins/skeleton_2d_editor_plugin.cpp
index dbad81d743..5ae21a430d 100644
--- a/editor/plugins/skeleton_2d_editor_plugin.cpp
+++ b/editor/plugins/skeleton_2d_editor_plugin.cpp
@@ -35,6 +35,7 @@
#include "editor/editor_undo_redo_manager.h"
#include "scene/2d/mesh_instance_2d.h"
#include "scene/gui/box_container.h"
+#include "scene/gui/menu_button.h"
#include "thirdparty/misc/clipper.hpp"
void Skeleton2DEditor::_node_removed(Node *p_node) {
diff --git a/editor/plugins/skeleton_2d_editor_plugin.h b/editor/plugins/skeleton_2d_editor_plugin.h
index 295725b751..6794f72955 100644
--- a/editor/plugins/skeleton_2d_editor_plugin.h
+++ b/editor/plugins/skeleton_2d_editor_plugin.h
@@ -35,6 +35,9 @@
#include "scene/2d/skeleton_2d.h"
#include "scene/gui/spin_box.h"
+class AcceptDialog;
+class MenuButton;
+
class Skeleton2DEditor : public Control {
GDCLASS(Skeleton2DEditor, Control);
diff --git a/editor/plugins/skeleton_3d_editor_plugin.cpp b/editor/plugins/skeleton_3d_editor_plugin.cpp
index 7922a768ec..d2dadd884b 100644
--- a/editor/plugins/skeleton_3d_editor_plugin.cpp
+++ b/editor/plugins/skeleton_3d_editor_plugin.cpp
@@ -34,6 +34,7 @@
#include "editor/editor_node.h"
#include "editor/editor_properties.h"
#include "editor/editor_scale.h"
+#include "editor/editor_settings.h"
#include "editor/editor_undo_redo_manager.h"
#include "editor/plugins/animation_player_editor_plugin.h"
#include "node_3d_editor_plugin.h"
@@ -41,10 +42,12 @@
#include "scene/3d/joint_3d.h"
#include "scene/3d/mesh_instance_3d.h"
#include "scene/3d/physics_body_3d.h"
+#include "scene/gui/separator.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"
+#include "scene/scene_string_names.h"
void BoneTransformEditor::create_editors() {
const Color section_color = get_theme_color(SNAME("prop_subsection"), SNAME("Editor"));
@@ -113,6 +116,7 @@ void BoneTransformEditor::_value_changed(const String &p_property, Variant p_val
return;
}
if (skeleton) {
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Set Bone Transform"), UndoRedo::MERGE_ENDS);
undo_redo->add_undo_property(skeleton, p_property, skeleton->get(p_property));
undo_redo->add_do_property(skeleton, p_property, p_value);
@@ -122,7 +126,6 @@ void BoneTransformEditor::_value_changed(const String &p_property, Variant p_val
BoneTransformEditor::BoneTransformEditor(Skeleton3D *p_skeleton) :
skeleton(p_skeleton) {
- undo_redo = EditorNode::get_undo_redo();
}
void BoneTransformEditor::set_keyable(const bool p_keyable) {
@@ -150,9 +153,10 @@ void BoneTransformEditor::set_target(const String &p_prop) {
void BoneTransformEditor::_property_keyed(const String &p_path, bool p_advance) {
AnimationTrackEditor *te = AnimationPlayerEditor::get_singleton()->get_track_editor();
- if (!te->has_keying()) {
+ if (!te || !te->has_keying()) {
return;
}
+ te->_clear_selection();
PackedStringArray split = p_path.split("/");
if (split.size() == 3 && split[0] == "bones") {
int bone_idx = split[1].to_int();
@@ -397,8 +401,8 @@ void Skeleton3DEditor::create_physical_skeleton() {
ur->add_do_method(physical_bone, "set_joint_type", PhysicalBone3D::JOINT_TYPE_PIN);
}
- ur->add_do_method(Node3DEditor::get_singleton(), "_request_gizmo", physical_bone);
- ur->add_do_method(Node3DEditor::get_singleton(), "_request_gizmo", collision_shape);
+ ur->add_do_method(Node3DEditor::get_singleton(), SceneStringNames::get_singleton()->_request_gizmo, physical_bone);
+ ur->add_do_method(Node3DEditor::get_singleton(), SceneStringNames::get_singleton()->_request_gizmo, collision_shape);
ur->add_do_reference(physical_bone);
ur->add_undo_method(skeleton, "remove_child", physical_bone);
@@ -714,12 +718,12 @@ void Skeleton3DEditor::create_editors() {
// Skeleton options.
PopupMenu *p = skeleton_options->get_popup();
- p->add_shortcut(ED_SHORTCUT("skeleton_3d_editor/reset_all_poses", TTR("Reset all bone Poses")), SKELETON_OPTION_RESET_ALL_POSES);
- p->add_shortcut(ED_SHORTCUT("skeleton_3d_editor/reset_selected_poses", TTR("Reset selected Poses")), SKELETON_OPTION_RESET_SELECTED_POSES);
- p->add_shortcut(ED_SHORTCUT("skeleton_3d_editor/all_poses_to_rests", TTR("Apply all poses to rests")), SKELETON_OPTION_ALL_POSES_TO_RESTS);
- p->add_shortcut(ED_SHORTCUT("skeleton_3d_editor/selected_poses_to_rests", TTR("Apply selected poses to rests")), SKELETON_OPTION_SELECTED_POSES_TO_RESTS);
- p->add_item(TTR("Create physical skeleton"), SKELETON_OPTION_CREATE_PHYSICAL_SKELETON);
- p->add_item(TTR("Export skeleton profile"), SKELETON_OPTION_EXPORT_SKELETON_PROFILE);
+ p->add_shortcut(ED_SHORTCUT("skeleton_3d_editor/reset_all_poses", TTR("Reset All Bone Poses")), SKELETON_OPTION_RESET_ALL_POSES);
+ p->add_shortcut(ED_SHORTCUT("skeleton_3d_editor/reset_selected_poses", TTR("Reset Selected Poses")), SKELETON_OPTION_RESET_SELECTED_POSES);
+ p->add_shortcut(ED_SHORTCUT("skeleton_3d_editor/all_poses_to_rests", TTR("Apply All Poses to Rests")), SKELETON_OPTION_ALL_POSES_TO_RESTS);
+ p->add_shortcut(ED_SHORTCUT("skeleton_3d_editor/selected_poses_to_rests", TTR("Apply Selected Poses to Rests")), SKELETON_OPTION_SELECTED_POSES_TO_RESTS);
+ p->add_item(TTR("Create Physical Skeleton"), SKELETON_OPTION_CREATE_PHYSICAL_SKELETON);
+ 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);
@@ -1239,7 +1243,7 @@ int Skeleton3DGizmoPlugin::subgizmos_intersect_ray(const EditorNode3DGizmo *p_gi
Skeleton3DEditor *se = Skeleton3DEditor::get_singleton();
- if (!se->is_edit_mode()) {
+ if (!se || !se->is_edit_mode()) {
return -1;
}
@@ -1288,7 +1292,7 @@ void Skeleton3DGizmoPlugin::set_subgizmo_transform(const EditorNode3DGizmo *p_gi
ERR_FAIL_COND(!skeleton);
// Prepare for global to local.
- Transform3D original_to_local = Transform3D();
+ Transform3D original_to_local;
int parent_idx = skeleton->get_bone_parent(p_id);
if (parent_idx >= 0) {
original_to_local = original_to_local * skeleton->get_bone_global_pose(parent_idx);
@@ -1296,7 +1300,7 @@ void Skeleton3DGizmoPlugin::set_subgizmo_transform(const EditorNode3DGizmo *p_gi
Basis to_local = original_to_local.get_basis().inverse();
// Prepare transform.
- Transform3D t = Transform3D();
+ Transform3D t;
// Basis.
t.basis = to_local * p_transform.get_basis();
diff --git a/editor/plugins/skeleton_3d_editor_plugin.h b/editor/plugins/skeleton_3d_editor_plugin.h
index 9f02d144ed..8ef61861d0 100644
--- a/editor/plugins/skeleton_3d_editor_plugin.h
+++ b/editor/plugins/skeleton_3d_editor_plugin.h
@@ -41,11 +41,13 @@
#include "scene/resources/immediate_mesh.h"
class EditorInspectorPluginSkeleton;
-class EditorUndoRedoManager;
class Joint;
class PhysicalBone3D;
class Skeleton3DEditorPlugin;
class Button;
+class Tree;
+class TreeItem;
+class VSeparator;
class BoneTransformEditor : public VBoxContainer {
GDCLASS(BoneTransformEditor, VBoxContainer);
@@ -65,8 +67,6 @@ class BoneTransformEditor : public VBoxContainer {
Skeleton3D *skeleton = nullptr;
// String property;
- Ref<EditorUndoRedoManager> undo_redo;
-
bool toggle_enabled = false;
bool updating = false;
diff --git a/editor/plugins/sprite_2d_editor_plugin.cpp b/editor/plugins/sprite_2d_editor_plugin.cpp
index b78b70cd5c..110ad7cac0 100644
--- a/editor/plugins/sprite_2d_editor_plugin.cpp
+++ b/editor/plugins/sprite_2d_editor_plugin.cpp
@@ -41,6 +41,7 @@
#include "scene/2d/mesh_instance_2d.h"
#include "scene/2d/polygon_2d.h"
#include "scene/gui/box_container.h"
+#include "scene/gui/menu_button.h"
#include "thirdparty/misc/clipper.hpp"
void Sprite2DEditor::_node_removed(Node *p_node) {
diff --git a/editor/plugins/sprite_2d_editor_plugin.h b/editor/plugins/sprite_2d_editor_plugin.h
index b87f108bd2..ae1083ed41 100644
--- a/editor/plugins/sprite_2d_editor_plugin.h
+++ b/editor/plugins/sprite_2d_editor_plugin.h
@@ -35,6 +35,10 @@
#include "scene/2d/sprite_2d.h"
#include "scene/gui/spin_box.h"
+class AcceptDialog;
+class ConfirmationDialog;
+class MenuButton;
+
class Sprite2DEditor : public Control {
GDCLASS(Sprite2DEditor, Control);
diff --git a/editor/plugins/sprite_frames_editor_plugin.cpp b/editor/plugins/sprite_frames_editor_plugin.cpp
index d3ab5b6f77..64e899b121 100644
--- a/editor/plugins/sprite_frames_editor_plugin.cpp
+++ b/editor/plugins/sprite_frames_editor_plugin.cpp
@@ -34,6 +34,7 @@
#include "core/io/resource_loader.h"
#include "core/os/keyboard.h"
#include "editor/editor_file_dialog.h"
+#include "editor/editor_file_system.h"
#include "editor/editor_node.h"
#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
@@ -43,6 +44,7 @@
#include "scene/gui/center_container.h"
#include "scene/gui/margin_container.h"
#include "scene/gui/panel_container.h"
+#include "scene/gui/separator.h"
static void _draw_shadowed_line(Control *p_control, const Point2 &p_from, const Size2 &p_size, const Size2 &p_shadow_offset, Color p_color, Color p_shadow_color) {
p_control->draw_line(p_from, p_from + p_size, p_color);
@@ -249,6 +251,7 @@ void SpriteFramesEditor::_sheet_add_frames() {
const Size2i offset = _get_offset();
const Size2i separation = _get_separation();
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Add Frame"));
int fc = frames->get_frame_count(edited_anim);
@@ -467,6 +470,7 @@ void SpriteFramesEditor::_file_load_request(const Vector<String> &p_path, int p_
return;
}
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Add Frame"));
int fc = frames->get_frame_count(edited_anim);
@@ -527,6 +531,7 @@ void SpriteFramesEditor::_paste_pressed() {
return; ///beh should show an error i guess
}
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Paste Frame"));
undo_redo->add_do_method(frames, "add_frame", edited_anim, r);
undo_redo->add_undo_method(frames, "remove_frame", edited_anim, frames->get_frame_count(edited_anim));
@@ -564,6 +569,7 @@ void SpriteFramesEditor::_empty_pressed() {
Ref<Texture2D> r;
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Add Empty"));
undo_redo->add_do_method(frames, "add_frame", edited_anim, r, from);
undo_redo->add_undo_method(frames, "remove_frame", edited_anim, from);
@@ -587,6 +593,7 @@ void SpriteFramesEditor::_empty2_pressed() {
Ref<Texture2D> r;
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Add Empty"));
undo_redo->add_do_method(frames, "add_frame", edited_anim, r, from + 1);
undo_redo->add_undo_method(frames, "remove_frame", edited_anim, from + 1);
@@ -610,6 +617,7 @@ void SpriteFramesEditor::_up_pressed() {
sel = to_move;
sel -= 1;
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Delete Resource"));
undo_redo->add_do_method(frames, "set_frame", edited_anim, to_move, frames->get_frame(edited_anim, to_move - 1));
undo_redo->add_do_method(frames, "set_frame", edited_anim, to_move - 1, frames->get_frame(edited_anim, to_move));
@@ -635,6 +643,7 @@ void SpriteFramesEditor::_down_pressed() {
sel = to_move;
sel += 1;
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Delete Resource"));
undo_redo->add_do_method(frames, "set_frame", edited_anim, to_move, frames->get_frame(edited_anim, to_move + 1));
undo_redo->add_do_method(frames, "set_frame", edited_anim, to_move + 1, frames->get_frame(edited_anim, to_move));
@@ -657,6 +666,7 @@ void SpriteFramesEditor::_delete_pressed() {
return;
}
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Delete Resource"));
undo_redo->add_do_method(frames, "remove_frame", edited_anim, to_delete);
undo_redo->add_undo_method(frames, "add_frame", edited_anim, frames->get_frame(edited_anim, to_delete), to_delete);
@@ -743,6 +753,7 @@ void SpriteFramesEditor::_animation_name_edited() {
List<Node *> nodes;
_find_anim_sprites(EditorNode::get_singleton()->get_edited_scene(), &nodes, Ref<SpriteFrames>(frames));
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Rename Animation"));
undo_redo->add_do_method(frames, "rename_animation", edited_anim, name);
undo_redo->add_undo_method(frames, "rename_animation", name, edited_anim);
@@ -772,6 +783,7 @@ void SpriteFramesEditor::_animation_add() {
List<Node *> nodes;
_find_anim_sprites(EditorNode::get_singleton()->get_edited_scene(), &nodes, Ref<SpriteFrames>(frames));
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Add Animation"));
undo_redo->add_do_method(frames, "add_animation", name);
undo_redo->add_undo_method(frames, "remove_animation", name);
@@ -804,6 +816,7 @@ void SpriteFramesEditor::_animation_remove() {
}
void SpriteFramesEditor::_animation_remove_confirmed() {
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Remove Animation"));
undo_redo->add_do_method(frames, "remove_animation", edited_anim);
undo_redo->add_undo_method(frames, "add_animation", edited_anim);
@@ -831,6 +844,7 @@ void SpriteFramesEditor::_animation_loop_changed() {
return;
}
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Change Animation Loop"));
undo_redo->add_do_method(frames, "set_animation_loop", edited_anim, anim_loop->is_pressed());
undo_redo->add_undo_method(frames, "set_animation_loop", edited_anim, frames->get_animation_loop(edited_anim));
@@ -844,6 +858,7 @@ void SpriteFramesEditor::_animation_fps_changed(double p_value) {
return;
}
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Change Animation FPS"), UndoRedo::MERGE_ENDS);
undo_redo->add_do_method(frames, "set_animation_speed", edited_anim, p_value);
undo_redo->add_undo_method(frames, "set_animation_speed", edited_anim, frames->get_animation_speed(edited_anim));
@@ -1035,10 +1050,6 @@ void SpriteFramesEditor::edit(SpriteFrames *p_frames) {
delete_frame->set_disabled(read_only);
}
-void SpriteFramesEditor::set_undo_redo(Ref<EditorUndoRedoManager> p_undo_redo) {
- undo_redo = p_undo_redo;
-}
-
Variant SpriteFramesEditor::get_drag_data_fw(const Point2 &p_point, Control *p_from) {
if (read_only) {
return false;
@@ -1136,6 +1147,7 @@ void SpriteFramesEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da
reorder = true;
}
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
if (reorder) { //drop is from reordering frames
int from_frame = -1;
if (d.has("frame")) {
@@ -1525,13 +1537,11 @@ SpriteFramesEditor::SpriteFramesEditor() {
_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.
+ // Not by setting its minimum size so it can still be shrunk if desired.
set_split_offset(56 * EDSCALE);
}
void SpriteFramesEditorPlugin::edit(Object *p_object) {
- frames_editor->set_undo_redo(get_undo_redo());
-
SpriteFrames *s;
AnimatedSprite2D *animated_sprite = Object::cast_to<AnimatedSprite2D>(p_object);
if (animated_sprite) {
diff --git a/editor/plugins/sprite_frames_editor_plugin.h b/editor/plugins/sprite_frames_editor_plugin.h
index 5fc3fe4481..64245ee1e0 100644
--- a/editor/plugins/sprite_frames_editor_plugin.h
+++ b/editor/plugins/sprite_frames_editor_plugin.h
@@ -45,7 +45,6 @@
#include "scene/gui/tree.h"
class EditorFileDialog;
-class EditorUndoRedoManager;
class SpriteFramesEditor : public HSplitContainer {
GDCLASS(SpriteFramesEditor, HSplitContainer);
@@ -154,8 +153,6 @@ class SpriteFramesEditor : public HSplitContainer {
bool updating;
bool updating_split_settings = false; // Skip SpinBox/Range callback when setting value by code.
- Ref<EditorUndoRedoManager> undo_redo;
-
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);
@@ -179,8 +176,6 @@ protected:
static void _bind_methods();
public:
- void set_undo_redo(Ref<EditorUndoRedoManager> p_undo_redo);
-
void edit(SpriteFrames *p_frames);
SpriteFramesEditor();
};
diff --git a/editor/plugins/style_box_editor_plugin.cpp b/editor/plugins/style_box_editor_plugin.cpp
index fffcce6d9a..afc54a2b83 100644
--- a/editor/plugins/style_box_editor_plugin.cpp
+++ b/editor/plugins/style_box_editor_plugin.cpp
@@ -31,6 +31,7 @@
#include "style_box_editor_plugin.h"
#include "editor/editor_scale.h"
+#include "scene/gui/texture_button.h"
bool StyleBoxPreview::grid_preview_enabled = true;
@@ -80,9 +81,9 @@ void StyleBoxPreview::_notification(int p_what) {
// See https://github.com/godotengine/godot/issues/50743.
break;
}
- grid_preview->set_normal_texture(get_theme_icon(SNAME("StyleBoxGridInvisible"), SNAME("EditorIcons")));
- grid_preview->set_pressed_texture(get_theme_icon(SNAME("StyleBoxGridVisible"), SNAME("EditorIcons")));
- grid_preview->set_hover_texture(get_theme_icon(SNAME("StyleBoxGridVisible"), SNAME("EditorIcons")));
+ grid_preview->set_texture_normal(get_theme_icon(SNAME("StyleBoxGridInvisible"), SNAME("EditorIcons")));
+ grid_preview->set_texture_pressed(get_theme_icon(SNAME("StyleBoxGridVisible"), SNAME("EditorIcons")));
+ grid_preview->set_texture_hover(get_theme_icon(SNAME("StyleBoxGridVisible"), SNAME("EditorIcons")));
checkerboard->set_texture(get_theme_icon(SNAME("Checkerboard"), SNAME("EditorIcons")));
} break;
}
diff --git a/editor/plugins/style_box_editor_plugin.h b/editor/plugins/style_box_editor_plugin.h
index a072745d8f..d5351d3f34 100644
--- a/editor/plugins/style_box_editor_plugin.h
+++ b/editor/plugins/style_box_editor_plugin.h
@@ -37,6 +37,8 @@
#include "scene/gui/texture_rect.h"
#include "scene/resources/style_box.h"
+class TextureButton;
+
class StyleBoxPreview : public VBoxContainer {
GDCLASS(StyleBoxPreview, VBoxContainer);
diff --git a/editor/plugins/text_editor.cpp b/editor/plugins/text_editor.cpp
index 03cff74bdb..d6079d6285 100644
--- a/editor/plugins/text_editor.cpp
+++ b/editor/plugins/text_editor.cpp
@@ -33,6 +33,7 @@
#include "core/os/keyboard.h"
#include "editor/editor_node.h"
#include "editor/editor_settings.h"
+#include "scene/gui/menu_button.h"
void TextEditor::add_syntax_highlighter(Ref<EditorSyntaxHighlighter> p_highlighter) {
ERR_FAIL_COND(p_highlighter.is_null());
@@ -352,7 +353,9 @@ void TextEditor::_edit_option(int p_op) {
code_editor->duplicate_selection();
} break;
case EDIT_TOGGLE_FOLD_LINE: {
- tx->toggle_foldable_line(tx->get_caret_line());
+ for (int caret_idx = 0; caret_idx < tx->get_caret_count(); caret_idx++) {
+ tx->toggle_foldable_line(tx->get_caret_line(caret_idx));
+ }
tx->queue_redraw();
} break;
case EDIT_FOLD_ALL_LINES: {
diff --git a/editor/plugins/text_editor.h b/editor/plugins/text_editor.h
index 486a0f2c23..9f2132bc0b 100644
--- a/editor/plugins/text_editor.h
+++ b/editor/plugins/text_editor.h
@@ -33,6 +33,8 @@
#include "script_editor_plugin.h"
+#include "editor/code_editor.h"
+
class TextEditor : public ScriptEditorBase {
GDCLASS(TextEditor, ScriptEditorBase);
diff --git a/editor/plugins/texture_3d_editor_plugin.cpp b/editor/plugins/texture_3d_editor_plugin.cpp
index 4b2f28658a..bdea12c2cb 100644
--- a/editor/plugins/texture_3d_editor_plugin.cpp
+++ b/editor/plugins/texture_3d_editor_plugin.cpp
@@ -30,6 +30,8 @@
#include "texture_3d_editor_plugin.h"
+#include "scene/gui/label.h"
+
void Texture3DEditor::_texture_rect_draw() {
texture_rect->draw_rect(Rect2(Point2(), texture_rect->get_size()), Color(1, 1, 1, 1));
}
diff --git a/editor/plugins/texture_3d_editor_plugin.h b/editor/plugins/texture_3d_editor_plugin.h
index 7795c83c8a..6790f6f2d5 100644
--- a/editor/plugins/texture_3d_editor_plugin.h
+++ b/editor/plugins/texture_3d_editor_plugin.h
@@ -31,6 +31,7 @@
#ifndef TEXTURE_3D_EDITOR_PLUGIN_H
#define TEXTURE_3D_EDITOR_PLUGIN_H
+#include "editor/editor_inspector.h"
#include "editor/editor_plugin.h"
#include "scene/gui/spin_box.h"
#include "scene/resources/shader.h"
diff --git a/editor/plugins/texture_editor_plugin.cpp b/editor/plugins/texture_editor_plugin.cpp
index 4aed7a92a2..5783912c96 100644
--- a/editor/plugins/texture_editor_plugin.cpp
+++ b/editor/plugins/texture_editor_plugin.cpp
@@ -30,6 +30,8 @@
#include "texture_editor_plugin.h"
#include "editor/editor_scale.h"
+#include "scene/gui/label.h"
+#include "scene/gui/texture_rect.h"
TextureRect *TexturePreview::get_texture_display() {
return texture_display;
diff --git a/editor/plugins/texture_editor_plugin.h b/editor/plugins/texture_editor_plugin.h
index 9beada556c..d7312bfcb4 100644
--- a/editor/plugins/texture_editor_plugin.h
+++ b/editor/plugins/texture_editor_plugin.h
@@ -31,9 +31,13 @@
#ifndef TEXTURE_EDITOR_PLUGIN_H
#define TEXTURE_EDITOR_PLUGIN_H
+#include "editor/editor_inspector.h"
#include "editor/editor_plugin.h"
+#include "scene/gui/margin_container.h"
#include "scene/resources/texture.h"
+class TextureRect;
+
class TexturePreview : public MarginContainer {
GDCLASS(TexturePreview, MarginContainer);
diff --git a/editor/plugins/texture_layered_editor_plugin.cpp b/editor/plugins/texture_layered_editor_plugin.cpp
index b0a174c1bc..479e84682b 100644
--- a/editor/plugins/texture_layered_editor_plugin.cpp
+++ b/editor/plugins/texture_layered_editor_plugin.cpp
@@ -30,6 +30,8 @@
#include "texture_layered_editor_plugin.h"
+#include "scene/gui/label.h"
+
void TextureLayeredEditor::gui_input(const Ref<InputEvent> &p_event) {
ERR_FAIL_COND(p_event.is_null());
diff --git a/editor/plugins/texture_layered_editor_plugin.h b/editor/plugins/texture_layered_editor_plugin.h
index f4dbc104c8..16a2f65386 100644
--- a/editor/plugins/texture_layered_editor_plugin.h
+++ b/editor/plugins/texture_layered_editor_plugin.h
@@ -31,6 +31,7 @@
#ifndef TEXTURE_LAYERED_EDITOR_PLUGIN_H
#define TEXTURE_LAYERED_EDITOR_PLUGIN_H
+#include "editor/editor_inspector.h"
#include "editor/editor_plugin.h"
#include "scene/gui/spin_box.h"
#include "scene/resources/shader.h"
diff --git a/editor/plugins/texture_region_editor_plugin.cpp b/editor/plugins/texture_region_editor_plugin.cpp
index b0c8597adf..fdfa3f8d0a 100644
--- a/editor/plugins/texture_region_editor_plugin.cpp
+++ b/editor/plugins/texture_region_editor_plugin.cpp
@@ -38,7 +38,9 @@
#include "editor/editor_settings.h"
#include "editor/editor_undo_redo_manager.h"
#include "scene/gui/check_box.h"
+#include "scene/gui/option_button.h"
#include "scene/gui/separator.h"
+#include "scene/gui/spin_box.h"
#include "scene/gui/view_panner.h"
#include "scene/resources/texture.h"
@@ -298,6 +300,7 @@ void TextureRegionEditor::_region_input(const Ref<InputEvent> &p_input) {
mtx.xform(rect.position + Vector2(0, rect.size.y / 2)) + Vector2(-handle_offset, 0)
};
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
Ref<InputEventMouseButton> mb = p_input;
if (mb.is_valid()) {
if (mb->get_button_index() == MouseButton::LEFT) {
@@ -1065,7 +1068,6 @@ TextureRegionEditor::TextureRegionEditor() {
node_ninepatch = nullptr;
obj_styleBox = Ref<StyleBoxTexture>(nullptr);
atlas_tex = Ref<AtlasTexture>(nullptr);
- undo_redo = EditorNode::get_singleton()->get_undo_redo();
preview_tex = Ref<CanvasTexture>(memnew(CanvasTexture));
diff --git a/editor/plugins/texture_region_editor_plugin.h b/editor/plugins/texture_region_editor_plugin.h
index 7eda4f469f..90a5b20e14 100644
--- a/editor/plugins/texture_region_editor_plugin.h
+++ b/editor/plugins/texture_region_editor_plugin.h
@@ -32,15 +32,17 @@
#define TEXTURE_REGION_EDITOR_PLUGIN_H
#include "canvas_item_editor_plugin.h"
+#include "editor/editor_inspector.h"
#include "editor/editor_plugin.h"
#include "scene/2d/sprite_2d.h"
#include "scene/3d/sprite_3d.h"
+#include "scene/gui/dialogs.h"
#include "scene/gui/nine_patch_rect.h"
#include "scene/resources/style_box.h"
#include "scene/resources/texture.h"
class ViewPanner;
-class EditorUndoRedoManager;
+class OptionButton;
class TextureRegionEditor : public AcceptDialog {
GDCLASS(TextureRegionEditor, AcceptDialog);
@@ -69,8 +71,6 @@ class TextureRegionEditor : public AcceptDialog {
VScrollBar *vscroll = nullptr;
HScrollBar *hscroll = nullptr;
- Ref<EditorUndoRedoManager> undo_redo;
-
Vector2 draw_ofs;
float draw_zoom = 0.0;
bool updating_scroll = false;
diff --git a/editor/plugins/theme_editor_plugin.cpp b/editor/plugins/theme_editor_plugin.cpp
index 5d02e4e437..135b218768 100644
--- a/editor/plugins/theme_editor_plugin.cpp
+++ b/editor/plugins/theme_editor_plugin.cpp
@@ -38,6 +38,8 @@
#include "editor/editor_undo_redo_manager.h"
#include "editor/progress_dialog.h"
#include "scene/gui/color_picker.h"
+#include "scene/gui/panel_container.h"
+#include "scene/gui/split_container.h"
#include "scene/theme/theme_db.h"
void ThemeItemImportTree::_update_items_tree() {
diff --git a/editor/plugins/theme_editor_plugin.h b/editor/plugins/theme_editor_plugin.h
index 9f89a047cb..b54aa5de6c 100644
--- a/editor/plugins/theme_editor_plugin.h
+++ b/editor/plugins/theme_editor_plugin.h
@@ -45,6 +45,8 @@
#include "scene/resources/theme.h"
class EditorFileDialog;
+class PanelContainer;
+class TabContainer;
class ThemeItemImportTree : public VBoxContainer {
GDCLASS(ThemeItemImportTree, VBoxContainer);
diff --git a/editor/plugins/theme_editor_preview.cpp b/editor/plugins/theme_editor_preview.cpp
index fdd8a80ad3..082b21bbe5 100644
--- a/editor/plugins/theme_editor_preview.cpp
+++ b/editor/plugins/theme_editor_preview.cpp
@@ -36,9 +36,12 @@
#include "editor/editor_node.h"
#include "editor/editor_scale.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/progress_bar.h"
+#include "scene/gui/text_edit.h"
+#include "scene/gui/tree.h"
#include "scene/resources/packed_scene.h"
#include "scene/theme/theme_db.h"
diff --git a/editor/plugins/tiles/atlas_merging_dialog.cpp b/editor/plugins/tiles/atlas_merging_dialog.cpp
index 167c6d169b..f892f3637d 100644
--- a/editor/plugins/tiles/atlas_merging_dialog.cpp
+++ b/editor/plugins/tiles/atlas_merging_dialog.cpp
@@ -154,6 +154,7 @@ void AtlasMergingDialog::_merge_confirmed(String p_path) {
Ref<Texture2D> new_texture_resource = ResourceLoader::load(p_path, "Texture2D");
merged->set_texture(new_texture_resource);
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Merge TileSetAtlasSource"));
int next_id = tile_set->get_next_source_id();
undo_redo->add_do_method(*tile_set, "add_source", merged, next_id);
@@ -193,6 +194,7 @@ void AtlasMergingDialog::ok_pressed() {
}
void AtlasMergingDialog::cancel_pressed() {
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
for (int i = 0; i < commited_actions_count; i++) {
undo_redo->undo();
}
@@ -234,7 +236,7 @@ void AtlasMergingDialog::update_tile_set(Ref<TileSet> p_tile_set) {
if (atlas_source.is_valid()) {
Ref<Texture2D> texture = atlas_source->get_texture();
if (texture.is_valid()) {
- String item_text = vformat("%s (id:%d)", texture->get_path().get_file(), source_id);
+ String item_text = vformat(TTR("%s (ID: %d)"), texture->get_path().get_file(), source_id);
atlas_merging_atlases_list->add_item(item_text, texture);
atlas_merging_atlases_list->set_item_metadata(-1, source_id);
}
@@ -248,8 +250,6 @@ void AtlasMergingDialog::update_tile_set(Ref<TileSet> p_tile_set) {
}
AtlasMergingDialog::AtlasMergingDialog() {
- undo_redo = EditorNode::get_singleton()->get_undo_redo();
-
// Atlas merging window.
set_title(TTR("Atlas Merging"));
set_hide_on_ok(false);
diff --git a/editor/plugins/tiles/atlas_merging_dialog.h b/editor/plugins/tiles/atlas_merging_dialog.h
index c7e4635d16..228c188817 100644
--- a/editor/plugins/tiles/atlas_merging_dialog.h
+++ b/editor/plugins/tiles/atlas_merging_dialog.h
@@ -38,7 +38,6 @@
#include "scene/resources/tile_set.h"
class EditorFileDialog;
-class EditorUndoRedoManager;
class AtlasMergingDialog : public ConfirmationDialog {
GDCLASS(AtlasMergingDialog, ConfirmationDialog);
@@ -50,8 +49,6 @@ private:
LocalVector<HashMap<Vector2i, Vector2i>> merged_mapping;
Ref<TileSet> tile_set;
- Ref<EditorUndoRedoManager> undo_redo;
-
// Settings.
int next_line_after_column = 30;
diff --git a/editor/plugins/tiles/tile_data_editors.cpp b/editor/plugins/tiles/tile_data_editors.cpp
index a7d90856ac..1fdf940a82 100644
--- a/editor/plugins/tiles/tile_data_editors.cpp
+++ b/editor/plugins/tiles/tile_data_editors.cpp
@@ -38,8 +38,13 @@
#include "editor/editor_node.h"
#include "editor/editor_properties.h"
#include "editor/editor_scale.h"
+#include "editor/editor_settings.h"
#include "editor/editor_undo_redo_manager.h"
+#include "scene/gui/menu_button.h"
+#include "scene/gui/option_button.h"
+#include "scene/gui/separator.h"
+
#ifdef DEBUG_ENABLED
#include "servers/navigation_server_3d.h"
#endif // DEBUG_ENABLED
@@ -153,7 +158,14 @@ void GenericTilePolygonEditor::_base_control_draw() {
// Draw the background.
if (background_texture.is_valid()) {
- base_control->draw_texture_rect_region(background_texture, Rect2(-background_region.size / 2 - background_offset, background_region.size), background_region, background_modulate, background_transpose);
+ Size2 region_size = background_region.size;
+ if (background_h_flip) {
+ region_size.x = -region_size.x;
+ }
+ if (background_v_flip) {
+ region_size.y = -region_size.y;
+ }
+ base_control->draw_texture_rect_region(background_texture, Rect2(-background_region.size / 2 - background_offset, region_size), background_region, background_modulate, background_transpose);
}
// Draw the polygons.
@@ -255,7 +267,7 @@ void GenericTilePolygonEditor::_zoom_changed() {
void GenericTilePolygonEditor::_advanced_menu_item_pressed(int p_item_pressed) {
Ref<EditorUndoRedoManager> undo_redo;
if (use_undo_redo) {
- undo_redo = editor_undo_redo;
+ undo_redo = EditorNode::get_undo_redo();
} else {
// This nice hack allows for discarding undo actions without making code too complex.
undo_redo.instantiate();
@@ -297,7 +309,22 @@ void GenericTilePolygonEditor::_advanced_menu_item_pressed(int p_item_pressed) {
case ROTATE_LEFT:
case FLIP_HORIZONTALLY:
case FLIP_VERTICALLY: {
- undo_redo->create_action(TTR("Rotate Polygons Left"));
+ switch (p_item_pressed) {
+ case ROTATE_RIGHT: {
+ undo_redo->create_action(TTR("Rotate Polygons Right"));
+ } break;
+ case ROTATE_LEFT: {
+ undo_redo->create_action(TTR("Rotate Polygons Left"));
+ } break;
+ case FLIP_HORIZONTALLY: {
+ undo_redo->create_action(TTR("Flip Polygons Horizontally"));
+ } break;
+ case FLIP_VERTICALLY: {
+ undo_redo->create_action(TTR("Flip Polygons Vertically"));
+ } break;
+ default:
+ break;
+ }
for (unsigned int i = 0; i < polygons.size(); i++) {
Vector<Point2> new_polygon;
for (int point_index = 0; point_index < polygons[i].size(); point_index++) {
@@ -420,7 +447,7 @@ void GenericTilePolygonEditor::_snap_to_half_pixel(Point2 &r_point) {
void GenericTilePolygonEditor::_base_control_gui_input(Ref<InputEvent> p_event) {
Ref<EditorUndoRedoManager> undo_redo;
if (use_undo_redo) {
- undo_redo = editor_undo_redo;
+ undo_redo = EditorNode::get_undo_redo();
} else {
// This nice hack allows for discarding undo actions without making code too complex.
undo_redo.instantiate();
@@ -756,8 +783,6 @@ void GenericTilePolygonEditor::_bind_methods() {
}
GenericTilePolygonEditor::GenericTilePolygonEditor() {
- editor_undo_redo = EditorNode::get_undo_redo();
-
toolbar = memnew(HBoxContainer);
add_child(toolbar);
@@ -846,6 +871,7 @@ GenericTilePolygonEditor::GenericTilePolygonEditor() {
void TileDataDefaultEditor::_property_value_changed(StringName p_property, Variant p_value, StringName p_field) {
ERR_FAIL_COND(!dummy_object);
dummy_object->set(p_property, p_value);
+ emit_signal(SNAME("needs_redraw"));
}
Variant TileDataDefaultEditor::_get_painted_value() {
@@ -876,6 +902,7 @@ Variant TileDataDefaultEditor::_get_value(TileSetAtlasSource *p_tile_set_atlas_s
}
void TileDataDefaultEditor::_setup_undo_redo_action(TileSetAtlasSource *p_tile_set_atlas_source, HashMap<TileMapCell, Variant, TileMapCell> p_previous_values, Variant p_new_value) {
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
for (const KeyValue<TileMapCell, Variant> &E : p_previous_values) {
Vector2i coords = E.key.get_atlas_coords();
undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/%s", coords.x, coords.y, E.key.alternative_tile, property), E.value);
@@ -944,6 +971,7 @@ void TileDataDefaultEditor::forward_painting_atlas_gui_input(TileAtlasView *p_ti
}
}
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
Ref<InputEventMouseButton> mb = p_event;
if (mb.is_valid()) {
if (mb->get_button_index() == MouseButton::LEFT) {
@@ -1067,6 +1095,7 @@ void TileDataDefaultEditor::forward_painting_alternatives_gui_input(TileAtlasVie
drag_last_pos = mb->get_position();
}
} else {
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Painting Tiles Property"));
_setup_undo_redo_action(p_tile_set_atlas_source, drag_modified, drag_painted_value);
undo_redo->commit_action(false);
@@ -1138,6 +1167,7 @@ void TileDataDefaultEditor::draw_over_tile(CanvasItem *p_canvas_item, Transform2
void TileDataDefaultEditor::setup_property_editor(Variant::Type p_type, String p_property, String p_label, Variant p_default_value) {
ERR_FAIL_COND_MSG(!property.is_empty(), "Cannot setup TileDataDefaultEditor twice");
property = p_property;
+ property_type = p_type;
// Update everything.
if (property_editor) {
@@ -1182,16 +1212,16 @@ void TileDataDefaultEditor::_notification(int p_what) {
}
}
-TileDataDefaultEditor::TileDataDefaultEditor() {
- undo_redo = EditorNode::get_undo_redo();
+Variant::Type TileDataDefaultEditor::get_property_type() {
+ return property_type;
+}
+TileDataDefaultEditor::TileDataDefaultEditor() {
label = memnew(Label);
label->set_text(TTR("Painting:"));
label->set_theme_type_variation("HeaderSmall");
add_child(label);
- toolbar->add_child(memnew(VSeparator));
-
picker_button = memnew(Button);
picker_button->set_flat(true);
picker_button->set_toggle_mode(true);
@@ -1315,6 +1345,7 @@ Variant TileDataOcclusionShapeEditor::_get_value(TileSetAtlasSource *p_tile_set_
}
void TileDataOcclusionShapeEditor::_setup_undo_redo_action(TileSetAtlasSource *p_tile_set_atlas_source, HashMap<TileMapCell, Variant, TileMapCell> p_previous_values, Variant p_new_value) {
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
for (const KeyValue<TileMapCell, Variant> &E : p_previous_values) {
Vector2i coords = E.key.get_atlas_coords();
undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/occlusion_layer_%d/polygon", coords.x, coords.y, E.key.alternative_tile, occlusion_layer), E.value);
@@ -1335,8 +1366,6 @@ void TileDataOcclusionShapeEditor::_notification(int p_what) {
}
TileDataOcclusionShapeEditor::TileDataOcclusionShapeEditor() {
- undo_redo = EditorNode::get_undo_redo();
-
polygon_editor = memnew(GenericTilePolygonEditor);
add_child(polygon_editor);
}
@@ -1496,6 +1525,7 @@ Variant TileDataCollisionEditor::_get_value(TileSetAtlasSource *p_tile_set_atlas
void TileDataCollisionEditor::_setup_undo_redo_action(TileSetAtlasSource *p_tile_set_atlas_source, HashMap<TileMapCell, Variant, TileMapCell> p_previous_values, Variant p_new_value) {
Array new_array = p_new_value;
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
for (KeyValue<TileMapCell, Variant> &E : p_previous_values) {
Array old_array = E.value;
@@ -1532,8 +1562,6 @@ void TileDataCollisionEditor::_notification(int p_what) {
}
TileDataCollisionEditor::TileDataCollisionEditor() {
- undo_redo = EditorNode::get_undo_redo();
-
polygon_editor = memnew(GenericTilePolygonEditor);
polygon_editor->set_multiple_polygon_mode(true);
polygon_editor->connect("polygons_changed", callable_mp(this, &TileDataCollisionEditor::_polygons_changed));
@@ -1588,12 +1616,31 @@ void TileDataCollisionEditor::draw_over_tile(CanvasItem *p_canvas_item, Transfor
}
RenderingServer::get_singleton()->canvas_item_add_set_transform(p_canvas_item->get_canvas_item(), p_transform);
+
+ Ref<Texture2D> one_way_icon = get_theme_icon(SNAME("OneWayTile"), SNAME("EditorIcons"));
for (int i = 0; i < tile_data->get_collision_polygons_count(physics_layer); i++) {
Vector<Vector2> polygon = tile_data->get_collision_polygon_points(physics_layer, i);
- if (polygon.size() >= 3) {
- p_canvas_item->draw_polygon(polygon, color);
+ if (polygon.size() < 3) {
+ continue;
+ }
+
+ p_canvas_item->draw_polygon(polygon, color);
+
+ if (tile_data->is_collision_polygon_one_way(physics_layer, i)) {
+ PackedVector2Array uvs;
+ uvs.resize(polygon.size());
+ Vector2 size_1 = Vector2(1, 1) / tile_set->get_tile_size();
+
+ for (int j = 0; j < polygon.size(); j++) {
+ uvs.write[j] = polygon[j] * size_1 + Vector2(0.5, 0.5);
+ }
+
+ Vector<Color> color2;
+ color2.push_back(Color(1, 1, 1, 0.4));
+ p_canvas_item->draw_polygon(polygon, color2, uvs, one_way_icon);
}
}
+
RenderingServer::get_singleton()->canvas_item_add_set_transform(p_canvas_item->get_canvas_item(), Transform2D());
}
@@ -2180,6 +2227,7 @@ void TileDataTerrainsEditor::forward_painting_atlas_gui_input(TileAtlasView *p_t
}
}
} else {
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
if (drag_type == DRAG_TYPE_PAINT_TERRAIN_SET_RECT) {
Rect2i rect;
rect.set_position(p_tile_atlas_view->get_atlas_tile_coords_at_pos(drag_start_pos));
@@ -2476,9 +2524,6 @@ void TileDataTerrainsEditor::forward_painting_alternatives_gui_input(TileAtlasVi
if (terrain_set == -1 || !tile_data || tile_data->get_terrain_set() != terrain_set) {
// Paint terrain sets.
- if (mb->get_button_index() == MouseButton::RIGHT) {
- terrain_set = -1;
- }
drag_type = DRAG_TYPE_PAINT_TERRAIN_SET;
drag_modified.clear();
drag_painted_value = int(dummy_object->get("terrain_set"));
@@ -2555,6 +2600,7 @@ void TileDataTerrainsEditor::forward_painting_alternatives_gui_input(TileAtlasVi
}
}
} else {
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
if (drag_type == DRAG_TYPE_PAINT_TERRAIN_SET) {
undo_redo->create_action(TTR("Painting Tiles Property"));
for (KeyValue<TileMapCell, Variant> &E : drag_modified) {
@@ -2620,16 +2666,12 @@ void TileDataTerrainsEditor::_notification(int p_what) {
}
TileDataTerrainsEditor::TileDataTerrainsEditor() {
- undo_redo = EditorNode::get_undo_redo();
-
label = memnew(Label);
label->set_text(TTR("Painting:"));
label->set_theme_type_variation("HeaderSmall");
add_child(label);
// Toolbar
- toolbar->add_child(memnew(VSeparator));
-
picker_button = memnew(Button);
picker_button->set_flat(true);
picker_button->set_toggle_mode(true);
@@ -2705,6 +2747,7 @@ Variant TileDataNavigationEditor::_get_value(TileSetAtlasSource *p_tile_set_atla
}
void TileDataNavigationEditor::_setup_undo_redo_action(TileSetAtlasSource *p_tile_set_atlas_source, HashMap<TileMapCell, Variant, TileMapCell> p_previous_values, Variant p_new_value) {
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
for (const KeyValue<TileMapCell, Variant> &E : p_previous_values) {
Vector2i coords = E.key.get_atlas_coords();
undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/navigation_layer_%d/polygon", coords.x, coords.y, E.key.alternative_tile, navigation_layer), E.value);
@@ -2727,8 +2770,6 @@ void TileDataNavigationEditor::_notification(int p_what) {
}
TileDataNavigationEditor::TileDataNavigationEditor() {
- undo_redo = EditorNode::get_undo_redo();
-
polygon_editor = memnew(GenericTilePolygonEditor);
polygon_editor->set_multiple_polygon_mode(true);
add_child(polygon_editor);
diff --git a/editor/plugins/tiles/tile_data_editors.h b/editor/plugins/tiles/tile_data_editors.h
index c1560138b2..e98e1d6701 100644
--- a/editor/plugins/tiles/tile_data_editors.h
+++ b/editor/plugins/tiles/tile_data_editors.h
@@ -39,6 +39,7 @@
#include "scene/gui/control.h"
#include "scene/gui/label.h"
+class MenuButton;
class EditorUndoRedoManager;
class TileDataEditor : public VBoxContainer {
@@ -95,7 +96,6 @@ private:
bool multiple_polygon_mode = false;
bool use_undo_redo = true;
- Ref<EditorUndoRedoManager> editor_undo_redo;
// UI
int hovered_polygon_index = -1;
@@ -216,10 +216,9 @@ private:
protected:
DummyObject *dummy_object = memnew(DummyObject);
- Ref<EditorUndoRedoManager> undo_redo;
-
StringName type;
String property;
+ Variant::Type property_type;
void _notification(int p_what);
virtual Variant _get_painted_value();
@@ -237,6 +236,7 @@ public:
virtual void draw_over_tile(CanvasItem *p_canvas_item, Transform2D p_transform, TileMapCell p_cell, bool p_selected = false) override;
void setup_property_editor(Variant::Type p_type, String p_property, String p_label = "", Variant p_default_value = Variant());
+ Variant::Type get_property_type();
TileDataDefaultEditor();
~TileDataDefaultEditor();
@@ -281,8 +281,6 @@ private:
virtual void _setup_undo_redo_action(TileSetAtlasSource *p_tile_set_atlas_source, HashMap<TileMapCell, Variant, TileMapCell> p_previous_values, Variant p_new_value) override;
protected:
- Ref<EditorUndoRedoManager> undo_redo;
-
virtual void _tile_set_changed() override;
void _notification(int p_what);
@@ -316,8 +314,6 @@ class TileDataCollisionEditor : public TileDataDefaultEditor {
virtual void _setup_undo_redo_action(TileSetAtlasSource *p_tile_set_atlas_source, HashMap<TileMapCell, Variant, TileMapCell> p_previous_values, Variant p_new_value) override;
protected:
- Ref<EditorUndoRedoManager> undo_redo;
-
virtual void _tile_set_changed() override;
void _notification(int p_what);
@@ -368,8 +364,6 @@ protected:
void _notification(int p_what);
- Ref<EditorUndoRedoManager> undo_redo;
-
public:
virtual Control *get_toolbar() override { return toolbar; };
virtual void forward_draw_over_atlas(TileAtlasView *p_tile_atlas_view, TileSetAtlasSource *p_tile_atlas_source, CanvasItem *p_canvas_item, Transform2D p_transform) override;
@@ -401,8 +395,6 @@ private:
virtual void _setup_undo_redo_action(TileSetAtlasSource *p_tile_set_atlas_source, HashMap<TileMapCell, Variant, TileMapCell> p_previous_values, Variant p_new_value) override;
protected:
- Ref<EditorUndoRedoManager> undo_redo;
-
virtual void _tile_set_changed() override;
void _notification(int p_what);
diff --git a/editor/plugins/tiles/tile_map_editor.cpp b/editor/plugins/tiles/tile_map_editor.cpp
index 57416ff55f..5a1f214933 100644
--- a/editor/plugins/tiles/tile_map_editor.cpp
+++ b/editor/plugins/tiles/tile_map_editor.cpp
@@ -35,6 +35,7 @@
#include "editor/editor_node.h"
#include "editor/editor_resource_preview.h"
#include "editor/editor_scale.h"
+#include "editor/editor_settings.h"
#include "editor/editor_undo_redo_manager.h"
#include "editor/plugins/canvas_item_editor_plugin.h"
@@ -54,7 +55,7 @@ void TileMapEditorTilesPlugin::tile_set_changed() {
}
void TileMapEditorTilesPlugin::_on_random_tile_checkbox_toggled(bool p_pressed) {
- scatter_spinbox->set_editable(p_pressed);
+ scatter_controls_container->set_visible(p_pressed);
}
void TileMapEditorTilesPlugin::_on_scattering_spinbox_changed(double p_value) {
@@ -155,7 +156,7 @@ void TileMapEditorTilesPlugin::_update_tile_set_sources_list() {
// Common to all type of sources.
if (!source->get_name().is_empty()) {
- item_text = vformat(TTR("%s (id:%d)"), source->get_name(), source_id);
+ item_text = vformat(TTR("%s (ID: %d)"), source->get_name(), source_id);
}
// Atlas source.
@@ -164,7 +165,7 @@ void TileMapEditorTilesPlugin::_update_tile_set_sources_list() {
texture = atlas_source->get_texture();
if (item_text.is_empty()) {
if (texture.is_valid()) {
- item_text = vformat("%s (ID: %d)", texture->get_path().get_file(), source_id);
+ item_text = vformat(TTR("%s (ID: %d)"), texture->get_path().get_file(), source_id);
} else {
item_text = vformat(TTR("No Texture Atlas Source (ID: %d)"), source_id);
}
@@ -272,6 +273,7 @@ void TileMapEditorTilesPlugin::_patterns_item_list_gui_input(const Ref<InputEven
if (ED_IS_SHORTCUT("tiles_editor/paste", p_event) && p_event->is_pressed() && !p_event->is_echo()) {
select_last_pattern = true;
int new_pattern_index = tile_set->get_patterns_count();
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Add TileSet pattern"));
undo_redo->add_do_method(*tile_set, "add_pattern", tile_map_clipboard, new_pattern_index);
undo_redo->add_undo_method(*tile_set, "remove_pattern", new_pattern_index);
@@ -281,6 +283,7 @@ void TileMapEditorTilesPlugin::_patterns_item_list_gui_input(const Ref<InputEven
if (ED_IS_SHORTCUT("tiles_editor/delete", p_event) && p_event->is_pressed() && !p_event->is_echo()) {
Vector<int> selected = patterns_item_list->get_selected_items();
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Remove TileSet patterns"));
for (int i = 0; i < selected.size(); i++) {
int pattern_index = selected[i];
@@ -469,6 +472,7 @@ void TileMapEditorTilesPlugin::_update_theme() {
random_tile_toggle->set_icon(tiles_bottom_panel->get_theme_icon(SNAME("RandomNumberGenerator"), SNAME("EditorIcons")));
missing_atlas_texture_icon = tiles_bottom_panel->get_theme_icon(SNAME("TileSet"), SNAME("EditorIcons"));
+ _update_tile_set_sources_list();
}
bool TileMapEditorTilesPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p_event) {
@@ -511,6 +515,7 @@ bool TileMapEditorTilesPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p
if (ED_IS_SHORTCUT("tiles_editor/cut", p_event)) {
// Delete selected tiles.
if (!tile_map_selection.is_empty()) {
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Delete tiles"));
for (const Vector2i &E : tile_map_selection) {
undo_redo->add_do_method(tile_map, "set_cell", tile_map_layer, E, TileSet::INVALID_SOURCE, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE);
@@ -542,6 +547,7 @@ bool TileMapEditorTilesPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p
if (ED_IS_SHORTCUT("tiles_editor/delete", p_event)) {
// Delete selected tiles.
if (!tile_map_selection.is_empty()) {
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Delete tiles"));
for (const Vector2i &E : tile_map_selection) {
undo_redo->add_do_method(tile_map, "set_cell", tile_map_layer, E, TileSet::INVALID_SOURCE, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE);
@@ -918,6 +924,7 @@ void TileMapEditorTilesPlugin::forward_canvas_draw_over_viewport(Control *p_over
Color modulate = tile_data->get_modulate();
Color self_modulate = tile_map->get_self_modulate();
modulate *= self_modulate;
+ modulate *= tile_map->get_layer_modulate(tile_map_layer);
// Draw the tile.
p_overlay->draw_texture_rect_region(atlas_source->get_texture(), dest_rect, source_rect, modulate * Color(1.0, 1.0, 1.0, 0.5), transpose, tile_set->is_uv_clipping());
@@ -1159,7 +1166,7 @@ HashMap<Vector2i, TileMapCell> TileMapEditorTilesPlugin::_draw_bucket_fill(Vecto
}
// Get surrounding tiles (handles different tile shapes).
- TypedArray<Vector2i> around = tile_map->get_surrounding_tiles(coords);
+ TypedArray<Vector2i> around = tile_map->get_surrounding_cells(coords);
for (int i = 0; i < around.size(); i++) {
to_check.push_back(around[i]);
}
@@ -1233,6 +1240,7 @@ void TileMapEditorTilesPlugin::_stop_dragging() {
Transform2D xform = CanvasItemEditor::get_singleton()->get_canvas_transform() * tile_map->get_global_transform();
Vector2 mpos = xform.affine_inverse().xform(CanvasItemEditor::get_singleton()->get_viewport_control()->get_local_mouse_position());
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
switch (drag_type) {
case DRAG_TYPE_SELECT: {
undo_redo->create_action(TTR("Change selection"));
@@ -1691,7 +1699,7 @@ void TileMapEditorTilesPlugin::_tile_atlas_control_draw() {
if (frame > 0) {
color.a *= 0.3;
}
- tile_atlas_control->draw_rect(atlas->get_tile_texture_region(E.get_atlas_coords(), frame), color, false);
+ TilesEditorPlugin::draw_selection_rect(tile_atlas_control, atlas->get_tile_texture_region(E.get_atlas_coords(), frame), color);
}
}
}
@@ -1699,11 +1707,8 @@ void TileMapEditorTilesPlugin::_tile_atlas_control_draw() {
// Draw the hovered tile.
if (hovered_tile.get_atlas_coords() != TileSetSource::INVALID_ATLAS_COORDS && hovered_tile.alternative_tile == 0 && !tile_set_dragging_selection) {
for (int frame = 0; frame < atlas->get_tile_animation_frames_count(hovered_tile.get_atlas_coords()); frame++) {
- Color color = Color(1.0, 1.0, 1.0);
- if (frame > 0) {
- color.a *= 0.3;
- }
- tile_atlas_control->draw_rect(atlas->get_tile_texture_region(hovered_tile.get_atlas_coords(), frame), color, false);
+ Color color = Color(1.0, 0.8, 0.0, frame == 0 ? 0.6 : 0.3);
+ TilesEditorPlugin::draw_selection_rect(tile_atlas_control, atlas->get_tile_texture_region(hovered_tile.get_atlas_coords(), frame), color);
}
}
@@ -1724,9 +1729,8 @@ void TileMapEditorTilesPlugin::_tile_atlas_control_draw() {
}
}
}
- Color selection_rect_color = selection_color.lightened(0.2);
for (const Vector2i &E : to_draw) {
- tile_atlas_control->draw_rect(atlas->get_tile_texture_region(E), selection_rect_color, false);
+ TilesEditorPlugin::draw_selection_rect(tile_atlas_control, atlas->get_tile_texture_region(E));
}
}
}
@@ -1875,7 +1879,7 @@ void TileMapEditorTilesPlugin::_tile_alternatives_control_draw() {
if (E.source_id == source_id && E.get_atlas_coords() != TileSetSource::INVALID_ATLAS_COORDS && E.alternative_tile > 0) {
Rect2i rect = tile_atlas_view->get_alternative_tile_rect(E.get_atlas_coords(), E.alternative_tile);
if (rect != Rect2i()) {
- alternative_tiles_control->draw_rect(rect, Color(0.2, 0.2, 1.0), false);
+ TilesEditorPlugin::draw_selection_rect(alternative_tiles_control, rect);
}
}
}
@@ -1884,7 +1888,7 @@ void TileMapEditorTilesPlugin::_tile_alternatives_control_draw() {
if (hovered_tile.get_atlas_coords() != TileSetSource::INVALID_ATLAS_COORDS && hovered_tile.alternative_tile > 0) {
Rect2i rect = tile_atlas_view->get_alternative_tile_rect(hovered_tile.get_atlas_coords(), hovered_tile.alternative_tile);
if (rect != Rect2i()) {
- alternative_tiles_control->draw_rect(rect, Color(1.0, 1.0, 1.0), false);
+ TilesEditorPlugin::draw_selection_rect(alternative_tiles_control, rect, Color(1.0, 0.8, 0.0, 0.5));
}
}
}
@@ -2012,8 +2016,6 @@ void TileMapEditorTilesPlugin::_bind_methods() {
}
TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() {
- undo_redo = EditorNode::get_undo_redo();
-
CanvasItemEditor::get_singleton()
->get_viewport_control()
->connect("mouse_exited", callable_mp(this, &TileMapEditorTilesPlugin::_mouse_exited_viewport));
@@ -2123,10 +2125,12 @@ TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() {
tools_settings->add_child(random_tile_toggle);
// Random tile scattering.
+ scatter_controls_container = memnew(HBoxContainer);
+
scatter_label = memnew(Label);
scatter_label->set_tooltip_text(TTR("Defines the probability of painting nothing instead of a randomly selected tile."));
scatter_label->set_text(TTR("Scattering:"));
- tools_settings->add_child(scatter_label);
+ scatter_controls_container->add_child(scatter_label);
scatter_spinbox = memnew(SpinBox);
scatter_spinbox->set_min(0.0);
@@ -2135,7 +2139,8 @@ TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() {
scatter_spinbox->set_tooltip_text(TTR("Defines the probability of painting nothing instead of a randomly selected tile."));
scatter_spinbox->get_line_edit()->add_theme_constant_override("minimum_character_width", 4);
scatter_spinbox->connect("value_changed", callable_mp(this, &TileMapEditorTilesPlugin::_on_scattering_spinbox_changed));
- tools_settings->add_child(scatter_spinbox);
+ scatter_controls_container->add_child(scatter_spinbox);
+ tools_settings->add_child(scatter_controls_container);
_on_random_tile_checkbox_toggled(false);
@@ -2267,6 +2272,7 @@ TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() {
patterns_help_label = memnew(Label);
patterns_help_label->set_text(TTR("Drag and drop or paste a TileMap selection here to store a pattern."));
+ patterns_help_label->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_CENTER);
patterns_help_label->set_anchors_and_offsets_preset(Control::PRESET_CENTER);
patterns_item_list->add_child(patterns_help_label);
@@ -2542,7 +2548,7 @@ RBSet<Vector2i> TileMapEditorTerrainsPlugin::_get_cells_for_bucket_fill(Vector2i
output.insert(coords);
// Get surrounding tiles (handles different tile shapes).
- TypedArray<Vector2i> around = tile_map->get_surrounding_tiles(coords);
+ TypedArray<Vector2i> around = tile_map->get_surrounding_cells(coords);
for (int i = 0; i < around.size(); i++) {
to_check.push_back(around[i]);
}
@@ -2633,6 +2639,7 @@ void TileMapEditorTerrainsPlugin::_stop_dragging() {
Transform2D xform = CanvasItemEditor::get_singleton()->get_canvas_transform() * tile_map->get_global_transform();
Vector2 mpos = xform.affine_inverse().xform(CanvasItemEditor::get_singleton()->get_viewport_control()->get_local_mouse_position());
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
switch (drag_type) {
case DRAG_TYPE_PICK: {
Vector2i coords = tile_map->local_to_map(mpos);
@@ -3303,8 +3310,6 @@ void TileMapEditorTerrainsPlugin::edit(ObjectID p_tile_map_id, int p_tile_map_la
}
TileMapEditorTerrainsPlugin::TileMapEditorTerrainsPlugin() {
- undo_redo = EditorNode::get_undo_redo();
-
main_vbox_container = memnew(VBoxContainer);
main_vbox_container->connect("tree_entered", callable_mp(this, &TileMapEditorTerrainsPlugin::_update_theme));
main_vbox_container->connect("theme_changed", callable_mp(this, &TileMapEditorTerrainsPlugin::_update_theme));
@@ -3478,6 +3483,7 @@ void TileMapEditor::_advanced_menu_button_id_pressed(int p_id) {
}
if (p_id == 0) { // Replace Tile Proxies
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Replace Tiles with Proxies"));
for (int layer_index = 0; layer_index < tile_map->get_layers_count(); layer_index++) {
TypedArray<Vector2i> used_cells = tile_map->get_used_cells(layer_index);
@@ -3951,8 +3957,6 @@ void TileMapEditor::edit(TileMap *p_tile_map) {
}
TileMapEditor::TileMapEditor() {
- undo_redo = EditorNode::get_undo_redo();
-
set_process_internal(true);
// Shortcuts.
diff --git a/editor/plugins/tiles/tile_map_editor.h b/editor/plugins/tiles/tile_map_editor.h
index 9a47d8bbc4..9700e26e01 100644
--- a/editor/plugins/tiles/tile_map_editor.h
+++ b/editor/plugins/tiles/tile_map_editor.h
@@ -47,8 +47,6 @@
#include "scene/gui/tab_bar.h"
#include "scene/gui/tree.h"
-class EditorUndoRedoManager;
-
class TileMapEditorPlugin : public Object {
public:
struct TabData {
@@ -70,7 +68,6 @@ class TileMapEditorTilesPlugin : public TileMapEditorPlugin {
GDCLASS(TileMapEditorTilesPlugin, TileMapEditorPlugin);
private:
- Ref<EditorUndoRedoManager> undo_redo;
ObjectID tile_map_id;
int tile_map_layer = -1;
virtual void edit(ObjectID p_tile_map_id, int p_tile_map_layer) override;
@@ -94,6 +91,8 @@ private:
VSeparator *tools_settings_vsep_2 = nullptr;
CheckBox *bucket_contiguous_checkbox = nullptr;
Button *random_tile_toggle = nullptr;
+
+ HBoxContainer *scatter_controls_container = nullptr;
float scattering = 0.0;
Label *scatter_label = nullptr;
SpinBox *scatter_spinbox = nullptr;
@@ -223,7 +222,6 @@ class TileMapEditorTerrainsPlugin : public TileMapEditorPlugin {
GDCLASS(TileMapEditorTerrainsPlugin, TileMapEditorPlugin);
private:
- Ref<EditorUndoRedoManager> undo_redo;
ObjectID tile_map_id;
int tile_map_layer = -1;
virtual void edit(ObjectID p_tile_map_id, int p_tile_map_layer) override;
@@ -317,7 +315,6 @@ class TileMapEditor : public VBoxContainer {
GDCLASS(TileMapEditor, VBoxContainer);
private:
- Ref<EditorUndoRedoManager> undo_redo;
bool tileset_changed_needs_update = false;
ObjectID tile_map_id;
int tile_map_layer = -1;
diff --git a/editor/plugins/tiles/tile_proxies_manager_dialog.cpp b/editor/plugins/tiles/tile_proxies_manager_dialog.cpp
index 9e4c29fa79..2868c14452 100644
--- a/editor/plugins/tiles/tile_proxies_manager_dialog.cpp
+++ b/editor/plugins/tiles/tile_proxies_manager_dialog.cpp
@@ -32,9 +32,11 @@
#include "editor/editor_node.h"
#include "editor/editor_scale.h"
+#include "editor/editor_settings.h"
#include "editor/editor_undo_redo_manager.h"
+#include "scene/gui/separator.h"
-void TileProxiesManagerDialog::_right_clicked(int p_item, Vector2 p_local_mouse_pos, Object *p_item_list, MouseButton p_mouse_button_index) {
+void TileProxiesManagerDialog::_right_clicked(int p_item, Vector2 p_local_mouse_pos, MouseButton p_mouse_button_index, Object *p_item_list) {
if (p_mouse_button_index != MouseButton::RIGHT) {
return;
}
@@ -53,6 +55,7 @@ void TileProxiesManagerDialog::_menu_id_pressed(int p_id) {
}
void TileProxiesManagerDialog::_delete_selected_bindings() {
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Remove Tile Proxies"));
Vector<int> source_level_selected = source_level_list->get_selected_items();
@@ -74,7 +77,7 @@ void TileProxiesManagerDialog::_delete_selected_bindings() {
Vector<int> alternative_level_selected = alternative_level_list->get_selected_items();
for (int i = 0; i < alternative_level_selected.size(); i++) {
Array key = alternative_level_list->get_item_metadata(alternative_level_selected[i]);
- Array val = tile_set->get_coords_level_tile_proxy(key[0], key[1]);
+ Array val = tile_set->get_alternative_level_tile_proxy(key[0], key[1], key[2]);
undo_redo->add_do_method(*tile_set, "remove_alternative_level_tile_proxy", key[0], key[1], key[2]);
undo_redo->add_undo_method(*tile_set, "set_alternative_level_tile_proxy", key[0], key[1], key[2], val[0], val[1], val[2]);
}
@@ -152,6 +155,7 @@ void TileProxiesManagerDialog::_property_changed(const String &p_path, const Var
}
void TileProxiesManagerDialog::_add_button_pressed() {
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
if (from.source_id != TileSet::INVALID_SOURCE && to.source_id != TileSet::INVALID_SOURCE) {
Vector2i from_coords = from.get_atlas_coords();
Vector2i to_coords = to.get_atlas_coords();
@@ -192,6 +196,7 @@ void TileProxiesManagerDialog::_add_button_pressed() {
}
void TileProxiesManagerDialog::_clear_invalid_button_pressed() {
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Delete All Invalid Tile Proxies"));
undo_redo->add_do_method(*tile_set, "cleanup_invalid_tile_proxies");
@@ -219,6 +224,7 @@ void TileProxiesManagerDialog::_clear_invalid_button_pressed() {
}
void TileProxiesManagerDialog::_clear_all_button_pressed() {
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Delete All Tile Proxies"));
undo_redo->add_do_method(*tile_set, "clear_tile_proxies");
@@ -299,6 +305,7 @@ void TileProxiesManagerDialog::_unhandled_key_input(Ref<InputEvent> p_event) {
}
void TileProxiesManagerDialog::cancel_pressed() {
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
for (int i = 0; i < commited_actions_count; i++) {
undo_redo->undo();
}
@@ -318,8 +325,6 @@ void TileProxiesManagerDialog::update_tile_set(Ref<TileSet> p_tile_set) {
}
TileProxiesManagerDialog::TileProxiesManagerDialog() {
- undo_redo = EditorNode::get_singleton()->get_undo_redo();
-
// Tile proxy management window.
set_title(TTR("Tile Proxies Management"));
set_process_unhandled_key_input(true);
@@ -393,7 +398,7 @@ TileProxiesManagerDialog::TileProxiesManagerDialog() {
source_from_property_editor->connect("property_changed", callable_mp(this, &TileProxiesManagerDialog::_property_changed));
source_from_property_editor->set_selectable(false);
source_from_property_editor->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- source_from_property_editor->setup(-1, 99999, 1, true, false);
+ source_from_property_editor->setup(-1, 99999, 1, false, true, false);
vboxcontainer_from->add_child(source_from_property_editor);
coords_from_property_editor = memnew(EditorPropertyVector2i);
@@ -412,7 +417,7 @@ TileProxiesManagerDialog::TileProxiesManagerDialog() {
alternative_from_property_editor->connect("property_changed", callable_mp(this, &TileProxiesManagerDialog::_property_changed));
alternative_from_property_editor->set_selectable(false);
alternative_from_property_editor->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- alternative_from_property_editor->setup(-1, 99999, 1, true, false);
+ alternative_from_property_editor->setup(-1, 99999, 1, false, true, false);
alternative_from_property_editor->hide();
vboxcontainer_from->add_child(alternative_from_property_editor);
@@ -427,7 +432,7 @@ TileProxiesManagerDialog::TileProxiesManagerDialog() {
source_to_property_editor->connect("property_changed", callable_mp(this, &TileProxiesManagerDialog::_property_changed));
source_to_property_editor->set_selectable(false);
source_to_property_editor->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- source_to_property_editor->setup(-1, 99999, 1, true, false);
+ source_to_property_editor->setup(-1, 99999, 1, false, true, false);
vboxcontainer_to->add_child(source_to_property_editor);
coords_to_property_editor = memnew(EditorPropertyVector2i);
@@ -446,7 +451,7 @@ TileProxiesManagerDialog::TileProxiesManagerDialog() {
alternative_to_property_editor->connect("property_changed", callable_mp(this, &TileProxiesManagerDialog::_property_changed));
alternative_to_property_editor->set_selectable(false);
alternative_to_property_editor->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- alternative_to_property_editor->setup(-1, 99999, 1, true, false);
+ alternative_to_property_editor->setup(-1, 99999, 1, false, true, false);
alternative_to_property_editor->hide();
vboxcontainer_to->add_child(alternative_to_property_editor);
diff --git a/editor/plugins/tiles/tile_proxies_manager_dialog.h b/editor/plugins/tiles/tile_proxies_manager_dialog.h
index 511e442a10..09c8068336 100644
--- a/editor/plugins/tiles/tile_proxies_manager_dialog.h
+++ b/editor/plugins/tiles/tile_proxies_manager_dialog.h
@@ -36,6 +36,8 @@
#include "scene/gui/dialogs.h"
#include "scene/gui/item_list.h"
+class EditorUndoRedoManager;
+
class TileProxiesManagerDialog : public ConfirmationDialog {
GDCLASS(TileProxiesManagerDialog, ConfirmationDialog);
@@ -43,8 +45,6 @@ private:
int commited_actions_count = 0;
Ref<TileSet> tile_set;
- Ref<EditorUndoRedoManager> undo_redo;
-
TileMapCell from;
TileMapCell to;
@@ -61,7 +61,7 @@ private:
EditorPropertyInteger *alternative_to_property_editor = nullptr;
PopupMenu *popup_menu = nullptr;
- void _right_clicked(int p_item, Vector2 p_local_mouse_pos, Object *p_item_list, MouseButton p_mouse_button_index);
+ void _right_clicked(int p_item, Vector2 p_local_mouse_pos, MouseButton p_mouse_button_index, Object *p_item_list);
void _menu_id_pressed(int p_id);
void _delete_selected_bindings();
void _update_lists();
diff --git a/editor/plugins/tiles/tile_set_atlas_source_editor.cpp b/editor/plugins/tiles/tile_set_atlas_source_editor.cpp
index ab54a093f2..34bbfa2c7e 100644
--- a/editor/plugins/tiles/tile_set_atlas_source_editor.cpp
+++ b/editor/plugins/tiles/tile_set_atlas_source_editor.cpp
@@ -35,10 +35,10 @@
#include "editor/editor_inspector.h"
#include "editor/editor_node.h"
#include "editor/editor_scale.h"
+#include "editor/editor_settings.h"
#include "editor/editor_undo_redo_manager.h"
#include "editor/progress_dialog.h"
-#include "editor/editor_node.h"
#include "scene/gui/box_container.h"
#include "scene/gui/button.h"
#include "scene/gui/control.h"
@@ -64,11 +64,15 @@ void TileSetAtlasSourceEditor::TileSetAtlasSourceProxyObject::set_id(int p_id) {
emit_signal(SNAME("changed"), "id");
}
-int TileSetAtlasSourceEditor::TileSetAtlasSourceProxyObject::get_id() {
+int TileSetAtlasSourceEditor::TileSetAtlasSourceProxyObject::get_id() const {
return source_id;
}
bool TileSetAtlasSourceEditor::TileSetAtlasSourceProxyObject::_set(const StringName &p_name, const Variant &p_value) {
+ if (p_name == "id") {
+ set_id(p_value);
+ return true;
+ }
String name = p_name;
if (name == "name") {
// Use the resource_name property to store the source's name.
@@ -86,6 +90,10 @@ bool TileSetAtlasSourceEditor::TileSetAtlasSourceProxyObject::_get(const StringN
if (!tile_set_atlas_source) {
return false;
}
+ if (p_name == "id") {
+ r_ret = get_id();
+ return true;
+ }
String name = p_name;
if (name == "name") {
// Use the resource_name property to store the source's name.
@@ -97,6 +105,8 @@ bool TileSetAtlasSourceEditor::TileSetAtlasSourceProxyObject::_get(const StringN
}
void TileSetAtlasSourceEditor::TileSetAtlasSourceProxyObject::_get_property_list(List<PropertyInfo> *p_list) const {
+ p_list->push_back(PropertyInfo(Variant::NIL, TTR("Atlas"), PROPERTY_HINT_NONE, String(), PROPERTY_USAGE_CATEGORY));
+ p_list->push_back(PropertyInfo(Variant::INT, "id", PROPERTY_HINT_RANGE, "0," + itos(INT_MAX) + ",1"));
p_list->push_back(PropertyInfo(Variant::STRING, "name", PROPERTY_HINT_NONE, ""));
p_list->push_back(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"));
p_list->push_back(PropertyInfo(Variant::VECTOR2I, "margins", PROPERTY_HINT_NONE, "suffix:px"));
@@ -106,12 +116,6 @@ void TileSetAtlasSourceEditor::TileSetAtlasSourceProxyObject::_get_property_list
}
void TileSetAtlasSourceEditor::TileSetAtlasSourceProxyObject::_bind_methods() {
- // -- Shape and layout --
- ClassDB::bind_method(D_METHOD("set_id", "id"), &TileSetAtlasSourceEditor::TileSetAtlasSourceProxyObject::set_id);
- ClassDB::bind_method(D_METHOD("get_id"), &TileSetAtlasSourceEditor::TileSetAtlasSourceProxyObject::get_id);
-
- ADD_PROPERTY(PropertyInfo(Variant::INT, "id", PROPERTY_HINT_RANGE, "0," + itos(INT_MAX) + ",1"), "set_id", "get_id");
-
ADD_SIGNAL(MethodInfo("changed", PropertyInfo(Variant::STRING, "what")));
}
@@ -152,7 +156,7 @@ bool TileSetAtlasSourceEditor::AtlasTileProxyObject::_set(const StringName &p_na
// ID and size related properties.
if (tiles.size() == 1) {
- const Vector2i &coords = tiles.front()->get().tile;
+ const Vector2i coords = tiles.front()->get().tile;
const int &alternative = tiles.front()->get().alternative;
if (alternative == 0) {
@@ -383,11 +387,15 @@ void TileSetAtlasSourceEditor::AtlasTileProxyObject::_get_property_list(List<Pro
// ID and size related properties.
if (tiles.size() == 1) {
if (tiles.front()->get().alternative == 0) {
- p_list->push_back(PropertyInfo(Variant::VECTOR2I, "atlas_coords", PROPERTY_HINT_NONE, ""));
- p_list->push_back(PropertyInfo(Variant::VECTOR2I, "size_in_atlas", PROPERTY_HINT_NONE, ""));
+ p_list->push_back(PropertyInfo(Variant::NIL, TTR("Base Tile"), PROPERTY_HINT_NONE, String(), PROPERTY_USAGE_CATEGORY));
+ p_list->push_back(PropertyInfo(Variant::VECTOR2I, "atlas_coords"));
+ p_list->push_back(PropertyInfo(Variant::VECTOR2I, "size_in_atlas"));
} else {
- p_list->push_back(PropertyInfo(Variant::INT, "alternative_id", PROPERTY_HINT_NONE, ""));
+ p_list->push_back(PropertyInfo(Variant::NIL, TTR("Alternative Tile"), PROPERTY_HINT_NONE, String(), PROPERTY_USAGE_CATEGORY));
+ p_list->push_back(PropertyInfo(Variant::INT, "alternative_id"));
}
+ } else {
+ p_list->push_back(PropertyInfo(Variant::NIL, TTR("Tiles"), PROPERTY_HINT_NONE, String(), PROPERTY_USAGE_CATEGORY));
}
// Animation.
@@ -443,6 +451,11 @@ void TileSetAtlasSourceEditor::AtlasTileProxyObject::_get_property_list(List<Pro
HashMap<String, int> counts; // Counts the number of time a property appears (useful for groups that may appear more than once)
for (List<PropertyInfo>::Element *E_property = list.front(); E_property; E_property = E_property->next()) {
+ // Don't show category for TileData.
+ if (E_property->get().usage & PROPERTY_USAGE_CATEGORY) {
+ continue;
+ }
+
const String &property_string = E_property->get().name;
if (!tile_data->is_allowing_transform() && (property_string == "flip_h" || property_string == "flip_v" || property_string == "transpose")) {
continue;
@@ -543,11 +556,13 @@ void TileSetAtlasSourceEditor::_update_source_inspector() {
void TileSetAtlasSourceEditor::_update_fix_selected_and_hovered_tiles() {
// Fix selected.
- for (RBSet<TileSelection>::Element *E = selection.front(); E; E = E->next()) {
+ for (RBSet<TileSelection>::Element *E = selection.front(); E;) {
+ RBSet<TileSelection>::Element *N = E->next();
TileSelection selected = E->get();
if (!tile_set_atlas_source->has_tile(selected.tile) || !tile_set_atlas_source->has_alternative_tile(selected.tile, selected.alternative)) {
selection.erase(E);
}
+ E = N;
}
// Fix hovered.
@@ -564,7 +579,6 @@ void TileSetAtlasSourceEditor::_update_fix_selected_and_hovered_tiles() {
void TileSetAtlasSourceEditor::_update_atlas_source_inspector() {
// Update visibility.
bool inspector_visible = tools_button_group->get_pressed_button() == tool_setup_atlas_source_button;
- atlas_source_inspector_label->set_visible(inspector_visible);
atlas_source_inspector->set_visible(inspector_visible);
}
@@ -574,11 +588,9 @@ void TileSetAtlasSourceEditor::_update_tile_inspector() {
if (!selection.is_empty()) {
tile_proxy_object->edit(tile_set_atlas_source, selection);
}
- tile_inspector_label->show();
tile_inspector->set_visible(!selection.is_empty());
tile_inspector_no_tile_selected_label->set_visible(selection.is_empty());
} else {
- tile_inspector_label->hide();
tile_inspector->hide();
tile_inspector_no_tile_selected_label->hide();
}
@@ -737,18 +749,29 @@ 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_layer_name(i).is_empty()) {
- ADD_TILE_DATA_EDITOR(group, vformat("Custom Data %d", i), vformat("custom_data_%d", i));
+ String editor_name = vformat("custom_data_%d", i);
+ String prop_name = tile_set->get_custom_data_layer_name(i);
+ Variant::Type prop_type = tile_set->get_custom_data_layer_type(i);
+
+ if (prop_name.is_empty()) {
+ ADD_TILE_DATA_EDITOR(group, vformat("Custom Data %d", i), editor_name);
} else {
- ADD_TILE_DATA_EDITOR(group, tile_set->get_custom_data_layer_name(i), vformat("custom_data_%d", i));
+ ADD_TILE_DATA_EDITOR(group, prop_name, editor_name);
+ }
+
+ // If the type of the edited property has been changed, delete the
+ // editor and create a new one.
+ if (tile_data_editors.has(editor_name) && ((TileDataDefaultEditor *)tile_data_editors[editor_name])->get_property_type() != prop_type) {
+ tile_data_editors[vformat("custom_data_%d", i)]->queue_free();
+ tile_data_editors.erase(vformat("custom_data_%d", i));
}
- if (!tile_data_editors.has(vformat("custom_data_%d", i))) {
+ if (!tile_data_editors.has(editor_name)) {
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_layer_type(i), vformat("custom_data_%d", i), tile_set->get_custom_data_layer_name(i));
+ tile_data_custom_data_editor->setup_property_editor(prop_type, editor_name, prop_name);
tile_data_custom_data_editor->connect("needs_redraw", callable_mp((CanvasItem *)tile_atlas_control_unscaled, &Control::queue_redraw));
tile_data_custom_data_editor->connect("needs_redraw", callable_mp((CanvasItem *)alternative_tiles_control_unscaled, &Control::queue_redraw));
- tile_data_editors[vformat("custom_data_%d", i)] = tile_data_custom_data_editor;
+ tile_data_editors[editor_name] = tile_data_custom_data_editor;
}
}
for (int i = tile_set->get_custom_data_layers_count(); tile_data_editors.has(vformat("custom_data_%d", i)); i++) {
@@ -784,7 +807,7 @@ void TileSetAtlasSourceEditor::_update_tile_data_editors() {
} else {
tile_data_editor_dropdown_button->set_text(TTR("Select a property editor"));
}
- tile_data_editors_label->set_visible(is_visible);
+ tile_data_editors_scroll->set_visible(is_visible);
}
void TileSetAtlasSourceEditor::_update_current_tile_data_editor() {
@@ -941,21 +964,18 @@ void TileSetAtlasSourceEditor::_update_toolbar() {
if (current_tile_data_editor_toolbar) {
current_tile_data_editor_toolbar->hide();
}
- tool_settings_vsep->show();
tools_settings_erase_button->show();
tool_advanced_menu_buttom->show();
} else if (tools_button_group->get_pressed_button() == tool_select_button) {
if (current_tile_data_editor_toolbar) {
current_tile_data_editor_toolbar->hide();
}
- tool_settings_vsep->hide();
tools_settings_erase_button->hide();
tool_advanced_menu_buttom->hide();
} else if (tools_button_group->get_pressed_button() == tool_paint_button) {
if (current_tile_data_editor_toolbar) {
current_tile_data_editor_toolbar->show();
}
- tool_settings_vsep->hide();
tools_settings_erase_button->hide();
tool_advanced_menu_buttom->hide();
}
@@ -1671,10 +1691,6 @@ Array TileSetAtlasSourceEditor::_get_selection_as_array() {
}
void TileSetAtlasSourceEditor::_tile_atlas_control_draw() {
- // Colors.
- Color grid_color = EDITOR_GET("editors/tiles_editor/grid_color");
- Color selection_color = Color().from_hsv(Math::fposmod(grid_color.get_h() + 0.5, 1.0), grid_color.get_s(), grid_color.get_v(), 1.0);
-
// Draw the selected tile.
if (tools_button_group->get_pressed_button() == tool_select_button) {
for (const TileSelection &E : selection) {
@@ -1682,12 +1698,9 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_draw() {
if (selected.alternative == 0) {
// Draw the rect.
for (int frame = 0; frame < tile_set_atlas_source->get_tile_animation_frames_count(selected.tile); frame++) {
- Color color = selection_color;
- if (frame > 0) {
- color.a *= 0.3;
- }
+ Color color = Color(0.0, 1.0, 0.0, frame == 0 ? 1.0 : 0.3);
Rect2 region = tile_set_atlas_source->get_tile_texture_region(selected.tile, frame);
- tile_atlas_control->draw_rect(region, color, false);
+ TilesEditorPlugin::draw_selection_rect(tile_atlas_control, region, color);
}
}
}
@@ -1729,7 +1742,7 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_draw() {
// Draw the tiles to be removed.
for (const Vector2i &E : drag_modified_tiles) {
for (int frame = 0; frame < tile_set_atlas_source->get_tile_animation_frames_count(E); frame++) {
- tile_atlas_control->draw_rect(tile_set_atlas_source->get_tile_texture_region(E, frame), Color(0.0, 0.0, 0.0), false);
+ TilesEditorPlugin::draw_selection_rect(tile_atlas_control, tile_set_atlas_source->get_tile_texture_region(E, frame), Color(0.0, 0.0, 0.0));
}
}
} else if (drag_type == DRAG_TYPE_RECT_SELECT || drag_type == DRAG_TYPE_REMOVE_TILES_USING_RECT) {
@@ -1741,7 +1754,7 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_draw() {
Color color = Color(0.0, 0.0, 0.0);
if (drag_type == DRAG_TYPE_RECT_SELECT) {
- color = selection_color.lightened(0.2);
+ color = Color(1.0, 1.0, 0.0);
}
RBSet<Vector2i> to_paint;
@@ -1756,7 +1769,7 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_draw() {
for (const Vector2i &E : to_paint) {
Vector2i coords = E;
- tile_atlas_control->draw_rect(tile_set_atlas_source->get_tile_texture_region(coords), color, false);
+ TilesEditorPlugin::draw_selection_rect(tile_atlas_control, tile_set_atlas_source->get_tile_texture_region(coords), color);
}
} else if (drag_type == DRAG_TYPE_CREATE_TILES_USING_RECT) {
// Draw tiles to be created.
@@ -1773,7 +1786,7 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_draw() {
Vector2i coords = Vector2i(x, y);
if (tile_set_atlas_source->get_tile_at_coords(coords) == TileSetSource::INVALID_ATLAS_COORDS) {
Vector2i origin = margins + (coords * (tile_size + separation));
- tile_atlas_control->draw_rect(Rect2i(origin, tile_size), Color(1.0, 1.0, 1.0), false);
+ TilesEditorPlugin::draw_selection_rect(tile_atlas_control, Rect2i(origin, tile_size));
}
}
}
@@ -1790,7 +1803,7 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_draw() {
Vector2i separation = tile_set_atlas_source->get_separation();
Vector2i tile_size = tile_set_atlas_source->get_texture_region_size();
Vector2i origin = margins + (area.position * (tile_size + separation));
- tile_atlas_control->draw_rect(Rect2i(origin, area.size * tile_size), Color(1.0, 1.0, 1.0), false);
+ TilesEditorPlugin::draw_selection_rect(tile_atlas_control, Rect2i(origin, area.size * tile_size));
} else {
Vector2i grid_size = tile_set_atlas_source->get_atlas_grid_size();
if (hovered_base_tile_coords.x >= 0 && hovered_base_tile_coords.y >= 0 && hovered_base_tile_coords.x < grid_size.x && hovered_base_tile_coords.y < grid_size.y) {
@@ -1798,11 +1811,8 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_draw() {
if (hovered_tile != TileSetSource::INVALID_ATLAS_COORDS) {
// Draw existing hovered tile.
for (int frame = 0; frame < tile_set_atlas_source->get_tile_animation_frames_count(hovered_tile); frame++) {
- Color color = Color(1.0, 1.0, 1.0);
- if (frame > 0) {
- color.a *= 0.3;
- }
- tile_atlas_control->draw_rect(tile_set_atlas_source->get_tile_texture_region(hovered_tile, frame), color, false);
+ Color color = Color(1.0, 0.8, 0.0, frame == 0 ? 0.6 : 0.3);
+ TilesEditorPlugin::draw_selection_rect(tile_atlas_control, tile_set_atlas_source->get_tile_texture_region(hovered_tile, frame), color);
}
} else {
// Draw empty tile, only in add/remove tiles mode.
@@ -1811,7 +1821,7 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_draw() {
Vector2i separation = tile_set_atlas_source->get_separation();
Vector2i tile_size = tile_set_atlas_source->get_texture_region_size();
Vector2i origin = margins + (hovered_base_tile_coords * (tile_size + separation));
- tile_atlas_control->draw_rect(Rect2i(origin, tile_size), Color(1.0, 1.0, 1.0), false);
+ TilesEditorPlugin::draw_selection_rect(tile_atlas_control, Rect2i(origin, tile_size));
}
}
}
@@ -1963,9 +1973,6 @@ void TileSetAtlasSourceEditor::_tile_alternatives_control_mouse_exited() {
}
void TileSetAtlasSourceEditor::_tile_alternatives_control_draw() {
- Color grid_color = EDITOR_GET("editors/tiles_editor/grid_color");
- Color selection_color = Color().from_hsv(Math::fposmod(grid_color.get_h() + 0.5, 1.0), grid_color.get_s(), grid_color.get_v(), 1.0);
-
// Update the hovered alternative tile.
if (tools_button_group->get_pressed_button() == tool_select_button) {
// Draw hovered tile.
@@ -1973,7 +1980,7 @@ void TileSetAtlasSourceEditor::_tile_alternatives_control_draw() {
if (coords != TileSetSource::INVALID_ATLAS_COORDS) {
Rect2i rect = tile_atlas_view->get_alternative_tile_rect(coords, hovered_alternative_tile_coords.z);
if (rect != Rect2i()) {
- alternative_tiles_control->draw_rect(rect, Color(1.0, 1.0, 1.0), false);
+ TilesEditorPlugin::draw_selection_rect(alternative_tiles_control, rect, Color(1.0, 0.8, 0.0, 0.5));
}
}
@@ -1983,7 +1990,7 @@ void TileSetAtlasSourceEditor::_tile_alternatives_control_draw() {
if (selected.alternative >= 1) {
Rect2i rect = tile_atlas_view->get_alternative_tile_rect(selected.tile, selected.alternative);
if (rect != Rect2i()) {
- alternative_tiles_control->draw_rect(rect, selection_color, false);
+ TilesEditorPlugin::draw_selection_rect(alternative_tiles_control, rect);
}
}
}
@@ -2332,6 +2339,15 @@ void TileSetAtlasSourceEditor::_notification(int p_what) {
tile_set_changed_needs_update = false;
}
} break;
+
+ case NOTIFICATION_EXIT_TREE: {
+ for (KeyValue<String, TileDataEditor *> &E : tile_data_editors) {
+ Control *toolbar = E.value->get_toolbar();
+ if (toolbar->get_parent() == tool_settings_tile_data_toolbar_container) {
+ tool_settings_tile_data_toolbar_container->remove_child(toolbar);
+ }
+ }
+ } break;
}
}
@@ -2346,54 +2362,90 @@ TileSetAtlasSourceEditor::TileSetAtlasSourceEditor() {
set_process_unhandled_key_input(true);
set_process_internal(true);
- // -- Right side --
- HSplitContainer *split_container_right_side = memnew(HSplitContainer);
- split_container_right_side->set_h_size_flags(SIZE_EXPAND_FILL);
- add_child(split_container_right_side);
-
// Middle panel.
- ScrollContainer *middle_panel = memnew(ScrollContainer);
- middle_panel->set_horizontal_scroll_mode(ScrollContainer::SCROLL_MODE_DISABLED);
- middle_panel->set_custom_minimum_size(Size2(200, 0) * EDSCALE);
- split_container_right_side->add_child(middle_panel);
-
VBoxContainer *middle_vbox_container = memnew(VBoxContainer);
- middle_vbox_container->set_h_size_flags(SIZE_EXPAND_FILL);
- middle_panel->add_child(middle_vbox_container);
+ middle_vbox_container->set_custom_minimum_size(Size2(200, 0) * EDSCALE);
+ add_child(middle_vbox_container);
- // Tile inspector.
- tile_inspector_label = memnew(Label);
- tile_inspector_label->set_text(TTR("Tile Properties:"));
- tile_inspector_label->set_theme_type_variation("HeaderSmall");
- middle_vbox_container->add_child(tile_inspector_label);
+ // -- Toolbox --
+ tools_button_group.instantiate();
+ tools_button_group->connect("pressed", callable_mp(this, &TileSetAtlasSourceEditor::_update_fix_selected_and_hovered_tiles).unbind(1));
+ tools_button_group->connect("pressed", callable_mp(this, &TileSetAtlasSourceEditor::_update_tile_id_label).unbind(1));
+ tools_button_group->connect("pressed", callable_mp(this, &TileSetAtlasSourceEditor::_update_atlas_source_inspector).unbind(1));
+ tools_button_group->connect("pressed", callable_mp(this, &TileSetAtlasSourceEditor::_update_tile_inspector).unbind(1));
+ tools_button_group->connect("pressed", callable_mp(this, &TileSetAtlasSourceEditor::_update_tile_data_editors).unbind(1));
+ tools_button_group->connect("pressed", callable_mp(this, &TileSetAtlasSourceEditor::_update_current_tile_data_editor).unbind(1));
+ tools_button_group->connect("pressed", callable_mp(this, &TileSetAtlasSourceEditor::_update_atlas_view).unbind(1));
+ tools_button_group->connect("pressed", callable_mp(this, &TileSetAtlasSourceEditor::_update_toolbar).unbind(1));
+
+ HBoxContainer *toolbox = memnew(HBoxContainer);
+ middle_vbox_container->add_child(toolbox);
+
+ tool_setup_atlas_source_button = memnew(Button);
+ tool_setup_atlas_source_button->set_text(TTR("Setup"));
+ tool_setup_atlas_source_button->set_flat(true);
+ tool_setup_atlas_source_button->set_toggle_mode(true);
+ tool_setup_atlas_source_button->set_pressed(true);
+ tool_setup_atlas_source_button->set_button_group(tools_button_group);
+ tool_setup_atlas_source_button->set_tooltip_text(TTR("Atlas setup. Add/Remove tiles tool (use the shift key to create big tiles, control for rectangle editing)."));
+ toolbox->add_child(tool_setup_atlas_source_button);
+
+ tool_select_button = memnew(Button);
+ tool_select_button->set_text(TTR("Select"));
+ tool_select_button->set_flat(true);
+ tool_select_button->set_toggle_mode(true);
+ tool_select_button->set_pressed(false);
+ tool_select_button->set_button_group(tools_button_group);
+ tool_select_button->set_tooltip_text(TTR("Select tiles."));
+ toolbox->add_child(tool_select_button);
+
+ tool_paint_button = memnew(Button);
+ tool_paint_button->set_text(TTR("Paint"));
+ tool_paint_button->set_flat(true);
+ tool_paint_button->set_toggle_mode(true);
+ tool_paint_button->set_button_group(tools_button_group);
+ tool_paint_button->set_tooltip_text(TTR("Paint properties."));
+ toolbox->add_child(tool_paint_button);
+ // Tile inspector.
tile_proxy_object = memnew(AtlasTileProxyObject(this));
tile_proxy_object->connect("changed", callable_mp(this, &TileSetAtlasSourceEditor::_tile_proxy_object_changed));
tile_inspector = memnew(EditorInspector);
- tile_inspector->set_vertical_scroll_mode(ScrollContainer::SCROLL_MODE_DISABLED);
+ tile_inspector->set_v_size_flags(SIZE_EXPAND_FILL);
+ tile_inspector->set_show_categories(true);
tile_inspector->edit(tile_proxy_object);
tile_inspector->set_use_folding(true);
tile_inspector->connect("property_selected", callable_mp(this, &TileSetAtlasSourceEditor::_inspector_property_selected));
middle_vbox_container->add_child(tile_inspector);
tile_inspector_no_tile_selected_label = memnew(Label);
+ tile_inspector_no_tile_selected_label->set_v_size_flags(SIZE_EXPAND | SIZE_SHRINK_CENTER);
tile_inspector_no_tile_selected_label->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_CENTER);
tile_inspector_no_tile_selected_label->set_text(TTR("No tiles selected."));
middle_vbox_container->add_child(tile_inspector_no_tile_selected_label);
// Property values palette.
+ tile_data_editors_scroll = memnew(ScrollContainer);
+ tile_data_editors_scroll->set_horizontal_scroll_mode(ScrollContainer::SCROLL_MODE_DISABLED);
+ tile_data_editors_scroll->set_v_size_flags(SIZE_EXPAND_FILL);
+ middle_vbox_container->add_child(tile_data_editors_scroll);
+
+ VBoxContainer *tile_data_editors_vbox = memnew(VBoxContainer);
+ tile_data_editors_vbox->set_h_size_flags(SIZE_EXPAND_FILL);
+ tile_data_editors_scroll->add_child(tile_data_editors_vbox);
+
tile_data_editors_popup = memnew(Popup);
tile_data_editors_label = memnew(Label);
tile_data_editors_label->set_text(TTR("Paint Properties:"));
tile_data_editors_label->set_theme_type_variation("HeaderSmall");
- middle_vbox_container->add_child(tile_data_editors_label);
+ tile_data_editors_vbox->add_child(tile_data_editors_label);
tile_data_editor_dropdown_button = memnew(Button);
tile_data_editor_dropdown_button->connect("draw", callable_mp(this, &TileSetAtlasSourceEditor::_tile_data_editor_dropdown_button_draw));
tile_data_editor_dropdown_button->connect("pressed", callable_mp(this, &TileSetAtlasSourceEditor::_tile_data_editor_dropdown_button_pressed));
- middle_vbox_container->add_child(tile_data_editor_dropdown_button);
+ tile_data_editors_vbox->add_child(tile_data_editor_dropdown_button);
tile_data_editor_dropdown_button->add_child(tile_data_editors_popup);
tile_data_editors_tree = memnew(Tree);
@@ -2406,80 +2458,25 @@ TileSetAtlasSourceEditor::TileSetAtlasSourceEditor() {
tile_data_painting_editor_container = memnew(VBoxContainer);
tile_data_painting_editor_container->set_h_size_flags(SIZE_EXPAND_FILL);
- middle_vbox_container->add_child(tile_data_painting_editor_container);
+ tile_data_editors_vbox->add_child(tile_data_painting_editor_container);
// Atlas source inspector.
- atlas_source_inspector_label = memnew(Label);
- atlas_source_inspector_label->set_text(TTR("Atlas Properties:"));
- atlas_source_inspector_label->set_theme_type_variation("HeaderSmall");
- middle_vbox_container->add_child(atlas_source_inspector_label);
-
atlas_source_proxy_object = memnew(TileSetAtlasSourceProxyObject());
atlas_source_proxy_object->connect("changed", callable_mp(this, &TileSetAtlasSourceEditor::_atlas_source_proxy_object_changed));
atlas_source_inspector = memnew(EditorInspector);
- atlas_source_inspector->set_vertical_scroll_mode(ScrollContainer::SCROLL_MODE_DISABLED);
+ atlas_source_inspector->set_v_size_flags(SIZE_EXPAND_FILL);
+ atlas_source_inspector->set_show_categories(true);
atlas_source_inspector->edit(atlas_source_proxy_object);
middle_vbox_container->add_child(atlas_source_inspector);
- // Right panel.
- VBoxContainer *right_panel = memnew(VBoxContainer);
- right_panel->set_h_size_flags(SIZE_EXPAND_FILL);
- right_panel->set_v_size_flags(SIZE_EXPAND_FILL);
- split_container_right_side->add_child(right_panel);
-
- // -- Dialogs --
- 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->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);
-
- // -- Toolbox --
- tools_button_group.instantiate();
- tools_button_group->connect("pressed", callable_mp(this, &TileSetAtlasSourceEditor::_update_fix_selected_and_hovered_tiles).unbind(1));
- tools_button_group->connect("pressed", callable_mp(this, &TileSetAtlasSourceEditor::_update_tile_id_label).unbind(1));
- tools_button_group->connect("pressed", callable_mp(this, &TileSetAtlasSourceEditor::_update_atlas_source_inspector).unbind(1));
- tools_button_group->connect("pressed", callable_mp(this, &TileSetAtlasSourceEditor::_update_tile_inspector).unbind(1));
- tools_button_group->connect("pressed", callable_mp(this, &TileSetAtlasSourceEditor::_update_tile_data_editors).unbind(1));
- tools_button_group->connect("pressed", callable_mp(this, &TileSetAtlasSourceEditor::_update_current_tile_data_editor).unbind(1));
- tools_button_group->connect("pressed", callable_mp(this, &TileSetAtlasSourceEditor::_update_atlas_view).unbind(1));
- tools_button_group->connect("pressed", callable_mp(this, &TileSetAtlasSourceEditor::_update_toolbar).unbind(1));
-
- toolbox = memnew(HBoxContainer);
- right_panel->add_child(toolbox);
-
- tool_setup_atlas_source_button = memnew(Button);
- tool_setup_atlas_source_button->set_flat(true);
- tool_setup_atlas_source_button->set_toggle_mode(true);
- tool_setup_atlas_source_button->set_pressed(true);
- tool_setup_atlas_source_button->set_button_group(tools_button_group);
- tool_setup_atlas_source_button->set_tooltip_text(TTR("Atlas setup. Add/Remove tiles tool (use the shift key to create big tiles, control for rectangle editing)."));
- toolbox->add_child(tool_setup_atlas_source_button);
-
- tool_select_button = memnew(Button);
- tool_select_button->set_flat(true);
- tool_select_button->set_toggle_mode(true);
- tool_select_button->set_pressed(false);
- tool_select_button->set_button_group(tools_button_group);
- tool_select_button->set_tooltip_text(TTR("Select tiles."));
- toolbox->add_child(tool_select_button);
-
- tool_paint_button = memnew(Button);
- tool_paint_button->set_flat(true);
- tool_paint_button->set_toggle_mode(true);
- tool_paint_button->set_button_group(tools_button_group);
- tool_paint_button->set_tooltip_text(TTR("Paint properties."));
- toolbox->add_child(tool_paint_button);
+ // -- Right side --
+ VBoxContainer *right_vbox_container = memnew(VBoxContainer);
+ add_child(right_vbox_container);
// Tool settings.
tool_settings = memnew(HBoxContainer);
- toolbox->add_child(tool_settings);
-
- tool_settings_vsep = memnew(VSeparator);
- tool_settings->add_child(tool_settings_vsep);
+ right_vbox_container->add_child(tool_settings);
tool_settings_tile_data_toolbar_container = memnew(HBoxContainer);
tool_settings->add_child(tool_settings_tile_data_toolbar_container);
@@ -2496,24 +2493,31 @@ TileSetAtlasSourceEditor::TileSetAtlasSourceEditor() {
tool_advanced_menu_buttom->get_popup()->add_item(TTR("Create Tiles in Non-Transparent Texture Regions"), ADVANCED_AUTO_CREATE_TILES);
tool_advanced_menu_buttom->get_popup()->add_item(TTR("Remove Tiles in Fully Transparent Texture Regions"), ADVANCED_AUTO_REMOVE_TILES);
tool_advanced_menu_buttom->get_popup()->connect("id_pressed", callable_mp(this, &TileSetAtlasSourceEditor::_menu_option));
- toolbox->add_child(tool_advanced_menu_buttom);
+ tool_settings->add_child(tool_advanced_menu_buttom);
_update_toolbar();
// Right side of toolbar.
Control *middle_space = memnew(Control);
middle_space->set_h_size_flags(SIZE_EXPAND_FILL);
- toolbox->add_child(middle_space);
+ tool_settings->add_child(middle_space);
tool_tile_id_label = memnew(Label);
tool_tile_id_label->set_mouse_filter(Control::MOUSE_FILTER_STOP);
- toolbox->add_child(tool_tile_id_label);
+ tool_settings->add_child(tool_tile_id_label);
_update_tile_id_label();
+ // Right panel.
+ VBoxContainer *right_panel = memnew(VBoxContainer);
+ right_panel->set_h_size_flags(SIZE_EXPAND_FILL);
+ right_panel->set_v_size_flags(SIZE_EXPAND_FILL);
+ right_vbox_container->add_child(right_panel);
+
// Tile atlas view.
tile_atlas_view = memnew(TileAtlasView);
tile_atlas_view->set_h_size_flags(SIZE_EXPAND_FILL);
tile_atlas_view->set_v_size_flags(SIZE_EXPAND_FILL);
+ tile_atlas_view->set_custom_minimum_size(Size2(200, 0) * EDSCALE);
tile_atlas_view->connect("transform_changed", callable_mp(TilesEditorPlugin::get_singleton(), &TilesEditorPlugin::set_atlas_view_transform));
tile_atlas_view->connect("transform_changed", callable_mp(this, &TileSetAtlasSourceEditor::_tile_atlas_view_transform_changed).unbind(2));
right_panel->add_child(tile_atlas_view);
@@ -2556,17 +2560,17 @@ TileSetAtlasSourceEditor::TileSetAtlasSourceEditor() {
tile_atlas_view->add_control_over_alternative_tiles(alternative_tiles_control_unscaled, false);
alternative_tiles_control_unscaled->set_mouse_filter(Control::MOUSE_FILTER_IGNORE);
- tile_atlas_view_missing_source_label = memnew(Label);
- tile_atlas_view_missing_source_label->set_text(TTR("Add or select an atlas texture to the left panel."));
- tile_atlas_view_missing_source_label->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_CENTER);
- tile_atlas_view_missing_source_label->set_vertical_alignment(VERTICAL_ALIGNMENT_CENTER);
- tile_atlas_view_missing_source_label->set_h_size_flags(SIZE_EXPAND_FILL);
- tile_atlas_view_missing_source_label->set_v_size_flags(SIZE_EXPAND_FILL);
- tile_atlas_view_missing_source_label->hide();
- right_panel->add_child(tile_atlas_view_missing_source_label);
-
EditorNode::get_singleton()->get_editor_data().add_undo_redo_inspector_hook_callback(callable_mp(this, &TileSetAtlasSourceEditor::_undo_redo_inspector_callback));
+ // -- Dialogs --
+ 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->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);
+
// Inspector plugin.
Ref<EditorInspectorPluginTileData> tile_data_inspector_plugin;
tile_data_inspector_plugin.instantiate();
diff --git a/editor/plugins/tiles/tile_set_atlas_source_editor.h b/editor/plugins/tiles/tile_set_atlas_source_editor.h
index 8e217e359f..eede2ec086 100644
--- a/editor/plugins/tiles/tile_set_atlas_source_editor.h
+++ b/editor/plugins/tiles/tile_set_atlas_source_editor.h
@@ -37,10 +37,13 @@
#include "scene/gui/split_container.h"
#include "scene/resources/tile_set.h"
+class Popup;
class TileSet;
+class Tree;
+class VSeparator;
-class TileSetAtlasSourceEditor : public HBoxContainer {
- GDCLASS(TileSetAtlasSourceEditor, HBoxContainer);
+class TileSetAtlasSourceEditor : public HSplitContainer {
+ GDCLASS(TileSetAtlasSourceEditor, HSplitContainer);
public:
// A class to store which tiles are selected.
@@ -74,7 +77,7 @@ public:
public:
void set_id(int p_id);
- int get_id();
+ int get_id() const;
void edit(Ref<TileSet> p_tile_set, TileSetAtlasSource *p_tile_set_atlas_source, int p_source_id);
TileSetAtlasSource *get_edited() { return tile_set_atlas_source; };
@@ -117,6 +120,7 @@ private:
bool tile_set_changed_needs_update = false;
// -- Properties painting --
+ ScrollContainer *tile_data_editors_scroll = nullptr;
VBoxContainer *tile_data_painting_editor_container = nullptr;
Label *tile_data_editors_label = nullptr;
Button *tile_data_editor_dropdown_button = nullptr;
@@ -134,19 +138,15 @@ private:
// -- Inspector --
AtlasTileProxyObject *tile_proxy_object = nullptr;
- Label *tile_inspector_label = nullptr;
EditorInspector *tile_inspector = nullptr;
Label *tile_inspector_no_tile_selected_label = nullptr;
String selected_property;
void _inspector_property_selected(String p_property);
TileSetAtlasSourceProxyObject *atlas_source_proxy_object = nullptr;
- Label *atlas_source_inspector_label = nullptr;
EditorInspector *atlas_source_inspector = nullptr;
// -- Atlas view --
- HBoxContainer *toolbox = nullptr;
- Label *tile_atlas_view_missing_source_label = nullptr;
TileAtlasView *tile_atlas_view = nullptr;
// Dragging
@@ -207,7 +207,6 @@ private:
// Tool settings.
HBoxContainer *tool_settings = nullptr;
- VSeparator *tool_settings_vsep = nullptr;
HBoxContainer *tool_settings_tile_data_toolbar_container = nullptr;
Button *tools_settings_erase_button = nullptr;
MenuButton *tool_advanced_menu_buttom = nullptr;
diff --git a/editor/plugins/tiles/tile_set_editor.cpp b/editor/plugins/tiles/tile_set_editor.cpp
index 5e25d343b0..e8ceacf8f8 100644
--- a/editor/plugins/tiles/tile_set_editor.cpp
+++ b/editor/plugins/tiles/tile_set_editor.cpp
@@ -36,6 +36,7 @@
#include "editor/editor_file_system.h"
#include "editor/editor_node.h"
#include "editor/editor_scale.h"
+#include "editor/editor_settings.h"
#include "editor/editor_undo_redo_manager.h"
#include "scene/gui/box_container.h"
@@ -66,6 +67,7 @@ void TileSetEditor::_drop_data_fw(const Point2 &p_point, const Variant &p_data,
// Actually create the new source.
Ref<TileSetAtlasSource> atlas_source = memnew(TileSetAtlasSource);
atlas_source->set_texture(resource);
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Add a new atlas source"));
undo_redo->add_do_method(*tile_set, "add_source", atlas_source, source_id);
undo_redo->add_do_method(*atlas_source, "set_texture_region_size", tile_set->get_tile_size());
@@ -118,7 +120,9 @@ bool TileSetEditor::_can_drop_data_fw(const Point2 &p_point, const Variant &p_da
}
void TileSetEditor::_update_sources_list(int force_selected_id) {
- ERR_FAIL_COND(!tile_set.is_valid());
+ if (tile_set.is_null()) {
+ return;
+ }
// Get the previously selected id.
int old_selected = TileSet::INVALID_SOURCE;
@@ -149,7 +153,7 @@ void TileSetEditor::_update_sources_list(int force_selected_id) {
// Common to all type of sources.
if (!source->get_name().is_empty()) {
- item_text = vformat(TTR("%s (id:%d)"), source->get_name(), source_id);
+ item_text = vformat(TTR("%s (ID: %d)"), source->get_name(), source_id);
}
// Atlas source.
@@ -158,7 +162,7 @@ void TileSetEditor::_update_sources_list(int force_selected_id) {
texture = atlas_source->get_texture();
if (item_text.is_empty()) {
if (texture.is_valid()) {
- item_text = vformat("%s (ID: %d)", texture->get_path().get_file(), source_id);
+ item_text = vformat(TTR("%s (ID: %d)"), texture->get_path().get_file(), source_id);
} else {
item_text = vformat(TTR("No Texture Atlas Source (ID: %d)"), source_id);
}
@@ -256,6 +260,7 @@ void TileSetEditor::_source_delete_pressed() {
Ref<TileSetSource> source = tile_set->get_source(to_delete);
// Remove the source.
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Remove source"));
undo_redo->add_do_method(*tile_set, "remove_source", to_delete);
undo_redo->add_undo_method(*tile_set, "add_source", source, to_delete);
@@ -274,6 +279,7 @@ void TileSetEditor::_source_add_id_pressed(int p_id_pressed) {
Ref<TileSetAtlasSource> atlas_source = memnew(TileSetAtlasSource);
// Add a new source.
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Add atlas source"));
undo_redo->add_do_method(*tile_set, "add_source", atlas_source, source_id);
undo_redo->add_do_method(*atlas_source, "set_texture_region_size", tile_set->get_tile_size());
@@ -288,6 +294,7 @@ void TileSetEditor::_source_add_id_pressed(int p_id_pressed) {
Ref<TileSetScenesCollectionSource> scene_collection_source = memnew(TileSetScenesCollectionSource);
// Add a new source.
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Add atlas source"));
undo_redo->add_do_method(*tile_set, "add_source", scene_collection_source, source_id);
undo_redo->add_undo_method(*tile_set, "remove_source", source_id);
@@ -341,6 +348,7 @@ void TileSetEditor::_notification(int p_what) {
source_sort_button->set_icon(get_theme_icon(SNAME("Sort"), SNAME("EditorIcons")));
sources_advanced_menu_button->set_icon(get_theme_icon(SNAME("GuiTabMenuHl"), SNAME("EditorIcons")));
missing_texture_texture = get_theme_icon(SNAME("TileSet"), SNAME("EditorIcons"));
+ _update_sources_list();
} break;
case NOTIFICATION_INTERNAL_PROCESS: {
@@ -361,6 +369,7 @@ void TileSetEditor::_patterns_item_list_gui_input(const Ref<InputEvent> &p_event
if (ED_IS_SHORTCUT("tiles_editor/delete", p_event) && p_event->is_pressed() && !p_event->is_echo()) {
Vector<int> selected = patterns_item_list->get_selected_items();
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Remove TileSet patterns"));
for (int i = 0; i < selected.size(); i++) {
int pattern_index = selected[i];
@@ -666,8 +675,6 @@ void TileSetEditor::edit(Ref<TileSet> p_tile_set) {
TileSetEditor::TileSetEditor() {
singleton = this;
- undo_redo = EditorNode::get_undo_redo();
-
set_process_internal(true);
// TabBar.
@@ -701,7 +708,7 @@ TileSetEditor::TileSetEditor() {
source_sort_button = memnew(MenuButton);
source_sort_button->set_flat(true);
- source_sort_button->set_tooltip_text(TTR("Sort sources"));
+ source_sort_button->set_tooltip_text(TTR("Sort Sources"));
PopupMenu *p = source_sort_button->get_popup();
p->connect("id_pressed", callable_mp(this, &TileSetEditor::_set_source_sort));
@@ -801,6 +808,7 @@ TileSetEditor::TileSetEditor() {
patterns_help_label = memnew(Label);
patterns_help_label->set_text(TTR("Add new patterns in the TileMap editing mode."));
+ patterns_help_label->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_CENTER);
patterns_help_label->set_anchors_and_offsets_preset(Control::PRESET_CENTER);
patterns_item_list->add_child(patterns_help_label);
diff --git a/editor/plugins/tiles/tile_set_editor.h b/editor/plugins/tiles/tile_set_editor.h
index 76a471db74..95697f7ecc 100644
--- a/editor/plugins/tiles/tile_set_editor.h
+++ b/editor/plugins/tiles/tile_set_editor.h
@@ -39,8 +39,6 @@
#include "tile_set_atlas_source_editor.h"
#include "tile_set_scenes_collection_source_editor.h"
-class EditorUndoRedoManager;
-
class TileSetEditor : public VBoxContainer {
GDCLASS(TileSetEditor, VBoxContainer);
@@ -60,8 +58,6 @@ private:
TileSetAtlasSourceEditor *tile_set_atlas_source_editor = nullptr;
TileSetScenesCollectionSourceEditor *tile_set_scenes_collection_source_editor = nullptr;
- Ref<EditorUndoRedoManager> undo_redo;
-
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;
diff --git a/editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp b/editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp
index 3b711a568e..a14aad6652 100644
--- a/editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp
+++ b/editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp
@@ -38,6 +38,7 @@
#include "editor/editor_undo_redo_manager.h"
#include "scene/gui/item_list.h"
+#include "scene/gui/split_container.h"
#include "core/core_string_names.h"
diff --git a/editor/plugins/tiles/tiles_editor_plugin.cpp b/editor/plugins/tiles/tiles_editor_plugin.cpp
index 5b54062632..ee29913334 100644
--- a/editor/plugins/tiles/tiles_editor_plugin.cpp
+++ b/editor/plugins/tiles/tiles_editor_plugin.cpp
@@ -30,10 +30,13 @@
#include "tiles_editor_plugin.h"
+#include "tile_set_editor.h"
+
#include "core/os/mutex.h"
#include "editor/editor_node.h"
#include "editor/editor_scale.h"
+#include "editor/editor_settings.h"
#include "editor/plugins/canvas_item_editor_plugin.h"
#include "scene/2d/tile_map.h"
@@ -43,8 +46,6 @@
#include "scene/gui/separator.h"
#include "scene/resources/tile_set.h"
-#include "tile_set_editor.h"
-
TilesEditorPlugin *TilesEditorPlugin::singleton = nullptr;
void TilesEditorPlugin::_preview_frame_started() {
@@ -92,7 +93,7 @@ void TilesEditorPlugin::_thread() {
TypedArray<Vector2i> used_cells = tile_map->get_used_cells(0);
- Rect2 encompassing_rect = Rect2();
+ Rect2 encompassing_rect;
encompassing_rect.set_position(tile_map->map_to_local(used_cells[0]));
for (int i = 0; i < used_cells.size(); i++) {
Vector2i cell = used_cells[i];
@@ -384,6 +385,15 @@ bool TilesEditorPlugin::handles(Object *p_object) const {
return p_object->is_class("TileMap") || p_object->is_class("TileSet");
}
+void TilesEditorPlugin::draw_selection_rect(CanvasItem *p_ci, const Rect2 &p_rect, const Color &p_color) {
+ real_t scale = p_ci->get_global_transform().get_scale().x * 0.5;
+ p_ci->draw_set_transform(p_rect.position, 0, Vector2(1, 1) / scale);
+ RS::get_singleton()->canvas_item_add_nine_patch(
+ p_ci->get_canvas_item(), Rect2(Vector2(), p_rect.size * scale), Rect2(), EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("TileSelection"), SNAME("EditorIcons"))->get_rid(),
+ Vector2(2, 2), Vector2(2, 2), RS::NINE_PATCH_STRETCH, RS::NINE_PATCH_STRETCH, false, p_color);
+ p_ci->draw_set_transform_matrix(Transform2D());
+}
+
TilesEditorPlugin::TilesEditorPlugin() {
set_process_internal(true);
diff --git a/editor/plugins/tiles/tiles_editor_plugin.h b/editor/plugins/tiles/tiles_editor_plugin.h
index bdada9ec90..825a10dac2 100644
--- a/editor/plugins/tiles/tiles_editor_plugin.h
+++ b/editor/plugins/tiles/tiles_editor_plugin.h
@@ -71,7 +71,7 @@ private:
// For synchronization.
int atlas_sources_lists_current = 0;
float atlas_view_zoom = 1.0;
- Vector2 atlas_view_scroll = Vector2();
+ Vector2 atlas_view_scroll;
void _tile_map_changed();
@@ -128,6 +128,8 @@ public:
virtual bool handles(Object *p_object) const override;
virtual void make_visible(bool p_visible) override;
+ static void draw_selection_rect(CanvasItem *p_ci, const Rect2 &p_rect, const Color &p_color = Color(1.0, 1.0, 1.0));
+
TilesEditorPlugin();
~TilesEditorPlugin();
};
diff --git a/editor/plugins/version_control_editor_plugin.cpp b/editor/plugins/version_control_editor_plugin.cpp
index 4fdfaed50e..e9c6184d73 100644
--- a/editor/plugins/version_control_editor_plugin.cpp
+++ b/editor/plugins/version_control_editor_plugin.cpp
@@ -38,6 +38,7 @@
#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/filesystem_dock.h"
+#include "editor/plugins/script_editor_plugin.h"
#include "scene/gui/separator.h"
#define CHECK_PLUGIN_INITIALIZED() \
@@ -46,43 +47,7 @@
VersionControlEditorPlugin *VersionControlEditorPlugin::singleton = nullptr;
void VersionControlEditorPlugin::_bind_methods() {
- ClassDB::bind_method(D_METHOD("_initialize_vcs"), &VersionControlEditorPlugin::_initialize_vcs);
- ClassDB::bind_method(D_METHOD("_set_credentials"), &VersionControlEditorPlugin::_set_credentials);
- ClassDB::bind_method(D_METHOD("_update_set_up_warning"), &VersionControlEditorPlugin::_update_set_up_warning);
- ClassDB::bind_method(D_METHOD("_commit"), &VersionControlEditorPlugin::_commit);
- ClassDB::bind_method(D_METHOD("_refresh_stage_area"), &VersionControlEditorPlugin::_refresh_stage_area);
- ClassDB::bind_method(D_METHOD("_move_all"), &VersionControlEditorPlugin::_move_all);
- ClassDB::bind_method(D_METHOD("_load_diff"), &VersionControlEditorPlugin::_load_diff);
- ClassDB::bind_method(D_METHOD("_display_diff"), &VersionControlEditorPlugin::_display_diff);
- ClassDB::bind_method(D_METHOD("_item_activated"), &VersionControlEditorPlugin::_item_activated);
- ClassDB::bind_method(D_METHOD("_update_branch_create_button"), &VersionControlEditorPlugin::_update_branch_create_button);
- ClassDB::bind_method(D_METHOD("_update_remote_create_button"), &VersionControlEditorPlugin::_update_remote_create_button);
- ClassDB::bind_method(D_METHOD("_update_commit_button"), &VersionControlEditorPlugin::_update_commit_button);
- ClassDB::bind_method(D_METHOD("_refresh_branch_list"), &VersionControlEditorPlugin::_refresh_branch_list);
- ClassDB::bind_method(D_METHOD("_set_commit_list_size"), &VersionControlEditorPlugin::_set_commit_list_size);
- ClassDB::bind_method(D_METHOD("_refresh_commit_list"), &VersionControlEditorPlugin::_refresh_commit_list);
- ClassDB::bind_method(D_METHOD("_refresh_remote_list"), &VersionControlEditorPlugin::_refresh_remote_list);
- ClassDB::bind_method(D_METHOD("_ssh_public_key_selected"), &VersionControlEditorPlugin::_ssh_public_key_selected);
- ClassDB::bind_method(D_METHOD("_ssh_private_key_selected"), &VersionControlEditorPlugin::_ssh_private_key_selected);
- ClassDB::bind_method(D_METHOD("_commit_message_gui_input"), &VersionControlEditorPlugin::_commit_message_gui_input);
- ClassDB::bind_method(D_METHOD("_cell_button_pressed"), &VersionControlEditorPlugin::_cell_button_pressed);
- ClassDB::bind_method(D_METHOD("_discard_all"), &VersionControlEditorPlugin::_discard_all);
- ClassDB::bind_method(D_METHOD("_create_branch"), &VersionControlEditorPlugin::_create_branch);
- ClassDB::bind_method(D_METHOD("_create_remote"), &VersionControlEditorPlugin::_create_remote);
- ClassDB::bind_method(D_METHOD("_remove_branch"), &VersionControlEditorPlugin::_remove_branch);
- ClassDB::bind_method(D_METHOD("_remove_remote"), &VersionControlEditorPlugin::_remove_remote);
- ClassDB::bind_method(D_METHOD("_branch_item_selected"), &VersionControlEditorPlugin::_branch_item_selected);
- ClassDB::bind_method(D_METHOD("_remote_selected"), &VersionControlEditorPlugin::_remote_selected);
- ClassDB::bind_method(D_METHOD("_fetch"), &VersionControlEditorPlugin::_fetch);
- ClassDB::bind_method(D_METHOD("_pull"), &VersionControlEditorPlugin::_pull);
- ClassDB::bind_method(D_METHOD("_push"), &VersionControlEditorPlugin::_push);
- ClassDB::bind_method(D_METHOD("_extra_option_selected"), &VersionControlEditorPlugin::_extra_option_selected);
- ClassDB::bind_method(D_METHOD("_update_extra_options"), &VersionControlEditorPlugin::_update_extra_options);
- ClassDB::bind_method(D_METHOD("_popup_branch_remove_confirm"), &VersionControlEditorPlugin::_popup_branch_remove_confirm);
- ClassDB::bind_method(D_METHOD("_popup_remote_remove_confirm"), &VersionControlEditorPlugin::_popup_remote_remove_confirm);
- ClassDB::bind_method(D_METHOD("_popup_file_dialog"), &VersionControlEditorPlugin::_popup_file_dialog);
-
- ClassDB::bind_method(D_METHOD("popup_vcs_set_up_dialog"), &VersionControlEditorPlugin::popup_vcs_set_up_dialog);
+ // No binds required so far.
}
void VersionControlEditorPlugin::_create_vcs_metadata_files() {
@@ -93,12 +58,10 @@ void VersionControlEditorPlugin::_create_vcs_metadata_files() {
void VersionControlEditorPlugin::_notification(int p_what) {
if (p_what == NOTIFICATION_READY) {
String installed_plugin = GLOBAL_DEF("editor/version_control/plugin_name", "");
- String project_path = GLOBAL_DEF("editor/version_control/project_path", OS::get_singleton()->get_resource_dir());
- project_path_input->set_text(project_path);
bool has_autoload_enable = GLOBAL_DEF("editor/version_control/autoload_on_startup", false);
if (installed_plugin != "" && has_autoload_enable) {
- if (_load_plugin(installed_plugin, project_path)) {
+ if (_load_plugin(installed_plugin)) {
_set_credentials();
}
}
@@ -143,18 +106,15 @@ void VersionControlEditorPlugin::_initialize_vcs() {
const int id = set_up_choice->get_selected_id();
String selected_plugin = set_up_choice->get_item_text(id);
- if (_load_plugin(selected_plugin, project_path_input->get_text())) {
+ if (_load_plugin(selected_plugin)) {
ProjectSettings::get_singleton()->set("editor/version_control/autoload_on_startup", true);
ProjectSettings::get_singleton()->set("editor/version_control/plugin_name", selected_plugin);
- ProjectSettings::get_singleton()->set("editor/version_control/project_path", project_path_input->get_text());
ProjectSettings::get_singleton()->save();
}
}
void VersionControlEditorPlugin::_set_vcs_ui_state(bool p_enabled) {
- select_project_path_button->set_disabled(p_enabled);
set_up_dialog->get_ok_button()->set_disabled(!p_enabled);
- project_path_input->set_editable(!p_enabled);
set_up_choice->set_disabled(p_enabled);
toggle_vcs_choice->set_pressed_no_signal(p_enabled);
}
@@ -180,14 +140,14 @@ void VersionControlEditorPlugin::_set_credentials() {
EditorSettings::get_singleton()->set_setting("version_control/ssh_private_key_path", ssh_private_key);
}
-bool VersionControlEditorPlugin::_load_plugin(String p_name, String p_project_path) {
+bool VersionControlEditorPlugin::_load_plugin(String p_name) {
Object *extension_instance = ClassDB::instantiate(p_name);
ERR_FAIL_NULL_V_MSG(extension_instance, false, "Received a nullptr VCS extension instance during construction.");
EditorVCSInterface *vcs_plugin = Object::cast_to<EditorVCSInterface>(extension_instance);
ERR_FAIL_NULL_V_MSG(vcs_plugin, false, vformat("Could not cast VCS extension instance to %s.", EditorVCSInterface::get_class_static()));
- String res_dir = project_path_input->get_text();
+ String res_dir = OS::get_singleton()->get_resource_dir();
ERR_FAIL_COND_V_MSG(!vcs_plugin->initialize(res_dir), false, "Could not initialize " + p_name);
@@ -434,6 +394,10 @@ void VersionControlEditorPlugin::_discard_file(String p_file_path, EditorVCSInte
EditorFileSystem::get_singleton()->update_file(p_file_path);
}
+void VersionControlEditorPlugin::_confirm_discard_all() {
+ discard_all_confirm->popup_centered();
+}
+
void VersionControlEditorPlugin::_discard_all() {
TreeItem *file_entry = unstaged_files->get_root()->get_first_child();
while (file_entry) {
@@ -630,7 +594,6 @@ void VersionControlEditorPlugin::_display_diff(int p_idx) {
diff->pop();
diff->pop();
- diff->add_newline();
diff->push_font(EditorNode::get_singleton()->get_gui_base()->get_theme_font(SNAME("status_source"), SNAME("EditorFonts")));
for (int j = 0; j < diff_file.diff_hunks.size(); j++) {
EditorVCSInterface::DiffHunk hunk = diff_file.diff_hunks[j];
@@ -640,6 +603,7 @@ void VersionControlEditorPlugin::_display_diff(int p_idx) {
String old_lines = String::num_int64(hunk.old_lines);
String new_lines = String::num_int64(hunk.new_lines);
+ diff->add_newline();
diff->append_text("[center]@@ " + old_start + "," + old_lines + " " + new_start + "," + new_lines + " @@[/center]");
diff->add_newline();
@@ -652,7 +616,6 @@ void VersionControlEditorPlugin::_display_diff(int p_idx) {
break;
}
diff->add_newline();
- diff->add_newline();
}
diff->pop();
@@ -720,12 +683,10 @@ void VersionControlEditorPlugin::_display_diff_split_view(List<EditorVCSInterfac
if (diff_line.old_line_no >= 0) {
diff->push_cell();
- diff->push_indent(1);
diff->push_color(has_change ? red : white);
diff->add_text(String::num_int64(diff_line.old_line_no));
diff->pop();
diff->pop();
- diff->pop();
diff->push_cell();
diff->push_color(has_change ? red : white);
@@ -752,12 +713,10 @@ void VersionControlEditorPlugin::_display_diff_split_view(List<EditorVCSInterfac
if (diff_line.new_line_no >= 0) {
diff->push_cell();
- diff->push_indent(1);
diff->push_color(has_change ? green : white);
diff->add_text(String::num_int64(diff_line.new_line_no));
diff->pop();
diff->pop();
- diff->pop();
diff->push_cell();
diff->push_color(has_change ? green : white);
@@ -942,10 +901,6 @@ void VersionControlEditorPlugin::_toggle_vcs_integration(bool p_toggled) {
}
}
-void VersionControlEditorPlugin::_project_path_selected(String p_project_path) {
- project_path_input->set_text(p_project_path);
-}
-
void VersionControlEditorPlugin::fetch_available_vcs_plugin_names() {
available_plugins.clear();
ClassDB::get_direct_inheriters_from_class(EditorVCSInterface::get_class_static(), &available_plugins);
@@ -987,7 +942,7 @@ VersionControlEditorPlugin::VersionControlEditorPlugin() {
metadata_dialog->set_title(TTR("Create Version Control Metadata"));
metadata_dialog->set_min_size(Size2(200, 40));
metadata_dialog->get_ok_button()->connect(SNAME("pressed"), callable_mp(this, &VersionControlEditorPlugin::_create_vcs_metadata_files));
- version_control_actions->add_child(metadata_dialog);
+ add_child(metadata_dialog);
VBoxContainer *metadata_vb = memnew(VBoxContainer);
metadata_dialog->add_child(metadata_vb);
@@ -1016,7 +971,7 @@ VersionControlEditorPlugin::VersionControlEditorPlugin() {
set_up_dialog->set_min_size(Size2(600, 100));
set_up_dialog->add_cancel_button("Cancel");
set_up_dialog->set_hide_on_ok(true);
- version_control_actions->add_child(set_up_dialog);
+ add_child(set_up_dialog);
Button *set_up_apply_button = set_up_dialog->get_ok_button();
set_up_apply_button->set_text(TTR("Apply"));
@@ -1039,34 +994,6 @@ VersionControlEditorPlugin::VersionControlEditorPlugin() {
set_up_choice->set_h_size_flags(Control::SIZE_EXPAND_FILL);
set_up_hbc->add_child(set_up_choice);
- HBoxContainer *project_path_hbc = memnew(HBoxContainer);
- project_path_hbc->set_h_size_flags(Control::SIZE_FILL);
- set_up_vbc->add_child(project_path_hbc);
-
- Label *project_path_label = memnew(Label);
- project_path_label->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- project_path_label->set_text(TTR("VCS Project Path"));
- project_path_hbc->add_child(project_path_label);
-
- project_path_input = memnew(LineEdit);
- project_path_input->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- project_path_input->set_text(OS::get_singleton()->get_resource_dir());
- project_path_hbc->add_child(project_path_input);
-
- FileDialog *select_project_path_file_dialog = memnew(FileDialog);
- select_project_path_file_dialog->set_access(FileDialog::ACCESS_FILESYSTEM);
- select_project_path_file_dialog->set_file_mode(FileDialog::FILE_MODE_OPEN_DIR);
- select_project_path_file_dialog->set_show_hidden_files(true);
- select_project_path_file_dialog->set_current_dir(OS::get_singleton()->get_resource_dir());
- select_project_path_file_dialog->connect(SNAME("dir_selected"), callable_mp(this, &VersionControlEditorPlugin::_project_path_selected));
- project_path_hbc->add_child(select_project_path_file_dialog);
-
- select_project_path_button = memnew(Button);
- select_project_path_button->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("Folder", "EditorIcons"));
- select_project_path_button->connect(SNAME("pressed"), callable_mp(this, &VersionControlEditorPlugin::_popup_file_dialog).bind(select_project_path_file_dialog));
- select_project_path_button->set_tooltip_text(TTR("Select VCS project path"));
- project_path_hbc->add_child(select_project_path_button);
-
HBoxContainer *toggle_vcs_hbc = memnew(HBoxContainer);
toggle_vcs_hbc->set_h_size_flags(Control::SIZE_EXPAND_FILL);
set_up_vbc->add_child(toggle_vcs_hbc);
@@ -1239,10 +1166,21 @@ VersionControlEditorPlugin::VersionControlEditorPlugin() {
refresh_button->connect(SNAME("pressed"), callable_mp(this, &VersionControlEditorPlugin::_refresh_remote_list));
unstage_title->add_child(refresh_button);
+ discard_all_confirm = memnew(AcceptDialog);
+ discard_all_confirm->set_title(TTR("Discard all changes"));
+ discard_all_confirm->set_min_size(Size2i(400, 50));
+ discard_all_confirm->set_text(TTR("This operation is IRREVERSIBLE. Your changes will be deleted FOREVER."));
+ discard_all_confirm->set_hide_on_ok(true);
+ discard_all_confirm->set_ok_button_text(TTR("Permanentally delete my changes"));
+ discard_all_confirm->add_cancel_button();
+ version_commit_dock->add_child(discard_all_confirm);
+
+ discard_all_confirm->get_ok_button()->connect(SNAME("pressed"), callable_mp(this, &VersionControlEditorPlugin::_discard_all));
+
discard_all_button = memnew(Button);
discard_all_button->set_tooltip_text(TTR("Discard all changes"));
discard_all_button->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Close"), SNAME("EditorIcons")));
- discard_all_button->connect(SNAME("pressed"), callable_mp(this, &VersionControlEditorPlugin::_discard_all));
+ discard_all_button->connect(SNAME("pressed"), callable_mp(this, &VersionControlEditorPlugin::_confirm_discard_all));
discard_all_button->set_flat(true);
unstage_title->add_child(discard_all_button);
diff --git a/editor/plugins/version_control_editor_plugin.h b/editor/plugins/version_control_editor_plugin.h
index 3340384a92..d73588a1bf 100644
--- a/editor/plugins/version_control_editor_plugin.h
+++ b/editor/plugins/version_control_editor_plugin.h
@@ -73,8 +73,6 @@ private:
AcceptDialog *set_up_dialog = nullptr;
CheckButton *toggle_vcs_choice = nullptr;
OptionButton *set_up_choice = nullptr;
- LineEdit *project_path_input = nullptr;
- Button *select_project_path_button = nullptr;
VBoxContainer *set_up_vbc = nullptr;
VBoxContainer *set_up_settings_vbc = nullptr;
LineEdit *set_up_username = nullptr;
@@ -86,6 +84,8 @@ private:
FileDialog *set_up_ssh_private_key_file_dialog = nullptr;
Label *set_up_warning_text = nullptr;
+ AcceptDialog *discard_all_confirm = nullptr;
+
OptionButton *commit_list_size_button = nullptr;
AcceptDialog *branch_create_confirm = nullptr;
@@ -150,13 +150,14 @@ private:
void _update_opened_tabs();
void _update_extra_options();
- bool _load_plugin(String p_name, String p_project_path);
+ bool _load_plugin(String p_name);
void _pull();
void _push();
void _force_push();
void _fetch();
void _commit();
+ void _confirm_discard_all();
void _discard_all();
void _refresh_stage_area();
void _refresh_branch_list();
@@ -193,7 +194,6 @@ private:
void _create_vcs_metadata_files();
void _popup_file_dialog(Variant p_file_dialog_variant);
void _toggle_vcs_integration(bool p_toggled);
- void _project_path_selected(String p_project_path);
friend class EditorVCSInterface;
diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp
index c8f6a2431d..c93b0019dc 100644
--- a/editor/plugins/visual_shader_editor_plugin.cpp
+++ b/editor/plugins/visual_shader_editor_plugin.cpp
@@ -32,31 +32,31 @@
#include "core/config/project_settings.h"
#include "core/core_string_names.h"
-#include "core/input/input.h"
#include "core/io/resource_loader.h"
#include "core/math/math_defs.h"
#include "core/os/keyboard.h"
-#include "editor/editor_log.h"
#include "editor/editor_node.h"
#include "editor/editor_properties.h"
#include "editor/editor_scale.h"
+#include "editor/editor_settings.h"
#include "editor/editor_undo_redo_manager.h"
+#include "editor/inspector_dock.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/check_box.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/option_button.h"
#include "scene/gui/popup.h"
#include "scene/gui/rich_text_label.h"
+#include "scene/gui/separator.h"
#include "scene/gui/tree.h"
#include "scene/gui/view_panner.h"
#include "scene/main/window.h"
#include "scene/resources/visual_shader_nodes.h"
#include "scene/resources/visual_shader_particle_nodes.h"
-#include "scene/resources/visual_shader_sdf_nodes.h"
#include "servers/display_server.h"
#include "servers/rendering/shader_types.h"
@@ -269,6 +269,19 @@ void VisualShaderGraphPlugin::set_expression(VisualShader::Type p_type, int p_no
links[p_node_id].expression_edit->set_text(p_expression);
}
+Ref<Script> VisualShaderGraphPlugin::get_node_script(int p_node_id) const {
+ if (!links.has(p_node_id)) {
+ return Ref<Script>();
+ }
+
+ Ref<VisualShaderNodeCustom> custom = Ref<VisualShaderNodeCustom>(links[p_node_id].visual_node);
+ if (custom.is_valid()) {
+ return custom->get_script();
+ }
+
+ return Ref<Script>();
+}
+
void VisualShaderGraphPlugin::update_node_size(int p_node_id) {
if (!links.has(p_node_id)) {
return;
@@ -816,8 +829,8 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) {
if (vsnode->is_output_port_expandable(i)) {
TextureButton *expand = memnew(TextureButton);
expand->set_toggle_mode(true);
- expand->set_normal_texture(editor->get_theme_icon(SNAME("GuiTreeArrowDown"), SNAME("EditorIcons")));
- expand->set_pressed_texture(editor->get_theme_icon(SNAME("GuiTreeArrowRight"), SNAME("EditorIcons")));
+ expand->set_texture_normal(editor->get_theme_icon(SNAME("GuiTreeArrowDown"), SNAME("EditorIcons")));
+ expand->set_texture_pressed(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).bind(p_id, i, !vsnode->_is_output_port_expanded(i)), CONNECT_DEFERRED);
@@ -826,8 +839,8 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) {
if (vsnode->has_output_port_preview(i) && port_right != VisualShaderNode::PORT_TYPE_TRANSFORM && port_right != VisualShaderNode::PORT_TYPE_SAMPLER) {
TextureButton *preview = memnew(TextureButton);
preview->set_toggle_mode(true);
- preview->set_normal_texture(editor->get_theme_icon(SNAME("GuiVisibilityHidden"), SNAME("EditorIcons")));
- preview->set_pressed_texture(editor->get_theme_icon(SNAME("GuiVisibilityVisible"), SNAME("EditorIcons")));
+ preview->set_texture_normal(editor->get_theme_icon(SNAME("GuiVisibilityHidden"), SNAME("EditorIcons")));
+ preview->set_texture_pressed(editor->get_theme_icon(SNAME("GuiVisibilityVisible"), SNAME("EditorIcons")));
preview->set_v_size_flags(Control::SIZE_SHRINK_CENTER);
register_output_port(p_id, j, preview);
@@ -1113,6 +1126,8 @@ void VisualShaderEditor::edit(VisualShader *p_visual_shader) {
}
visual_shader->set_graph_offset(graph->get_scroll_ofs() / EDSCALE);
_set_mode(visual_shader->get_mode());
+
+ _update_nodes();
} else {
if (visual_shader.is_valid()) {
Callable ce = callable_mp(this, &VisualShaderEditor::_update_preview);
@@ -1135,10 +1150,6 @@ void VisualShaderEditor::edit(VisualShader *p_visual_shader) {
}
}
-void VisualShaderEditor::update_nodes() {
- _update_nodes();
-}
-
void VisualShaderEditor::add_plugin(const Ref<VisualShaderNodePlugin> &p_plugin) {
if (plugins.has(p_plugin)) {
return;
@@ -1200,6 +1211,228 @@ void VisualShaderEditor::add_custom_type(const String &p_name, const Ref<Script>
add_options.push_back(ao);
}
+Dictionary VisualShaderEditor::get_custom_node_data(Ref<VisualShaderNodeCustom> &p_custom_node) {
+ Dictionary dict;
+ dict["script"] = p_custom_node->get_script();
+
+ String name;
+ if (p_custom_node->has_method("_get_name")) {
+ name = (String)p_custom_node->call("_get_name");
+ } else {
+ name = "Unnamed";
+ }
+ dict["name"] = name;
+
+ String description = "";
+ if (p_custom_node->has_method("_get_description")) {
+ description = (String)p_custom_node->call("_get_description");
+ }
+ dict["description"] = description;
+
+ int return_icon_type = -1;
+ if (p_custom_node->has_method("_get_return_icon_type")) {
+ return_icon_type = (int)p_custom_node->call("_get_return_icon_type");
+ }
+ dict["return_icon_type"] = return_icon_type;
+
+ String category = "";
+ if (p_custom_node->has_method("_get_category")) {
+ category = (String)p_custom_node->call("_get_category");
+ }
+ category = category.rstrip("/");
+ category = category.lstrip("/");
+ category = "Addons/" + category;
+
+ String subcategory = "";
+ if (p_custom_node->has_method("_get_subcategory")) {
+ subcategory = (String)p_custom_node->call("_get_subcategory");
+ }
+ if (!subcategory.is_empty()) {
+ category += "/" + subcategory;
+ }
+ dict["category"] = category;
+
+ bool highend = false;
+ if (p_custom_node->has_method("_is_highend")) {
+ highend = (bool)p_custom_node->call("_is_highend");
+ }
+ dict["highend"] = highend;
+
+ return dict;
+}
+
+void VisualShaderEditor::update_custom_type(const Ref<Resource> &p_resource) {
+ Ref<Script> scr = Ref<Script>(p_resource.ptr());
+ if (scr.is_null() || scr->get_instance_base_type() != "VisualShaderNodeCustom") {
+ return;
+ }
+
+ Ref<VisualShaderNodeCustom> ref;
+ ref.instantiate();
+ ref->set_script(scr);
+ if (!ref->is_available(visual_shader->get_mode(), visual_shader->get_shader_type())) {
+ for (int i = 0; i < add_options.size(); i++) {
+ if (add_options[i].is_custom && add_options[i].script == scr) {
+ add_options.remove_at(i);
+ _update_options_menu();
+ // TODO: Make indication for the existed custom nodes with that script on graph to be disabled.
+ break;
+ }
+ }
+ return;
+ }
+ Dictionary dict = get_custom_node_data(ref);
+
+ bool found_type = false;
+ bool need_rebuild = false;
+
+ for (int i = 0; i < add_options.size(); i++) {
+ if (add_options[i].is_custom && add_options[i].script == scr) {
+ found_type = true;
+
+ add_options.write[i].name = dict["name"];
+ add_options.write[i].return_type = dict["return_icon_type"];
+ add_options.write[i].description = dict["description"];
+ add_options.write[i].category = dict["category"];
+ add_options.write[i].highend = dict["highend"];
+
+ int max_type = 0;
+ int type_offset = 0;
+ switch (visual_shader->get_mode()) {
+ case Shader::MODE_CANVAS_ITEM:
+ case Shader::MODE_SPATIAL: {
+ max_type = 3;
+ } break;
+ case Shader::MODE_PARTICLES: {
+ max_type = 5;
+ type_offset = 3;
+ } break;
+ case Shader::MODE_SKY: {
+ max_type = 1;
+ type_offset = 8;
+ } break;
+ case Shader::MODE_FOG: {
+ max_type = 1;
+ type_offset = 9;
+ } break;
+ default: {
+ } break;
+ }
+ max_type = type_offset + max_type;
+
+ for (int t = type_offset; t < max_type; t++) {
+ VisualShader::Type type = (VisualShader::Type)t;
+ Vector<int> nodes = visual_shader->get_node_list(type);
+
+ List<VisualShader::Connection> node_connections;
+ visual_shader->get_node_connections(type, &node_connections);
+
+ List<VisualShader::Connection> custom_node_input_connections;
+ List<VisualShader::Connection> custom_node_output_connections;
+ for (const VisualShader::Connection &E : node_connections) {
+ int from = E.from_node;
+ int from_idx = E.from_port;
+ int to = E.to_node;
+ int to_idx = E.to_port;
+
+ if (graph_plugin->get_node_script(from) == scr) {
+ custom_node_output_connections.push_back({ from, from_idx, to, to_idx });
+ } else if (graph_plugin->get_node_script(to) == scr) {
+ custom_node_input_connections.push_back({ from, from_idx, to, to_idx });
+ }
+ }
+
+ for (int j = 0; j < nodes.size(); j++) {
+ int node_id = nodes[j];
+
+ Ref<VisualShaderNode> vsnode = visual_shader->get_node(type, node_id);
+ if (vsnode.is_null()) {
+ continue;
+ }
+ Ref<VisualShaderNodeCustom> custom_node = Ref<VisualShaderNodeCustom>(vsnode.ptr());
+ if (custom_node.is_null() || custom_node->get_script() != scr) {
+ continue;
+ }
+ need_rebuild = true;
+
+ // Removes invalid connections.
+ {
+ int prev_input_port_count = custom_node->get_input_port_count();
+ int prev_output_port_count = custom_node->get_output_port_count();
+
+ custom_node->update_ports();
+
+ int input_port_count = custom_node->get_input_port_count();
+ int output_port_count = custom_node->get_output_port_count();
+
+ if (output_port_count != prev_output_port_count) {
+ for (const VisualShader::Connection &E : custom_node_output_connections) {
+ int from = E.from_node;
+ int from_idx = E.from_port;
+ int to = E.to_node;
+ int to_idx = E.to_port;
+
+ if (from_idx >= output_port_count) {
+ visual_shader->disconnect_nodes(type, from, from_idx, to, to_idx);
+ graph_plugin->disconnect_nodes(type, from, from_idx, to, to_idx);
+ }
+ }
+ }
+ if (input_port_count != prev_input_port_count) {
+ for (const VisualShader::Connection &E : custom_node_input_connections) {
+ int from = E.from_node;
+ int from_idx = E.from_port;
+ int to = E.to_node;
+ int to_idx = E.to_port;
+
+ if (to_idx >= input_port_count) {
+ visual_shader->disconnect_nodes(type, from, from_idx, to, to_idx);
+ graph_plugin->disconnect_nodes(type, from, from_idx, to, to_idx);
+ }
+ }
+ }
+ }
+
+ graph_plugin->update_node(type, node_id);
+ }
+ }
+ break;
+ }
+ }
+
+ if (!found_type) {
+ add_custom_type(dict["name"], dict["script"], dict["description"], dict["return_icon_type"], dict["category"], dict["highend"]);
+ }
+
+ // To prevent updating options multiple times when multiple scripts are saved.
+ if (!_block_update_options_menu) {
+ _block_update_options_menu = true;
+
+ call_deferred(SNAME("_update_options_menu_deferred"));
+ }
+
+ // To prevent rebuilding the shader multiple times when multiple scripts are saved.
+ if (need_rebuild && !_block_rebuild_shader) {
+ _block_rebuild_shader = true;
+
+ call_deferred(SNAME("_rebuild_shader_deferred"));
+ }
+}
+
+void VisualShaderEditor::_update_options_menu_deferred() {
+ _update_options_menu();
+
+ _block_update_options_menu = false;
+}
+
+void VisualShaderEditor::_rebuild_shader_deferred() {
+ if (visual_shader.is_valid()) {
+ visual_shader->rebuild();
+ }
+
+ _block_rebuild_shader = false;
+}
+
bool VisualShaderEditor::_is_available(int p_mode) {
int current_mode = edit_type->get_selected();
@@ -1241,57 +1474,10 @@ void VisualShaderEditor::_update_nodes() {
if (!ref->is_available(visual_shader->get_mode(), visual_shader->get_shader_type())) {
continue;
}
-
- String name;
- if (ref->has_method("_get_name")) {
- name = (String)ref->call("_get_name");
- } else {
- name = "Unnamed";
- }
-
- String description = "";
- if (ref->has_method("_get_description")) {
- description = (String)ref->call("_get_description");
- }
-
- int return_icon_type = -1;
- if (ref->has_method("_get_return_icon_type")) {
- return_icon_type = (int)ref->call("_get_return_icon_type");
- }
-
- String category = "";
- if (ref->has_method("_get_category")) {
- category = (String)ref->call("_get_category");
- }
-
- String subcategory = "";
- if (ref->has_method("_get_subcategory")) {
- subcategory = (String)ref->call("_get_subcategory");
- }
-
- bool highend = false;
- if (ref->has_method("_is_highend")) {
- highend = (bool)ref->call("_is_highend");
- }
-
- Dictionary dict;
- dict["name"] = name;
- dict["script"] = scr;
- dict["description"] = description;
- dict["return_icon_type"] = return_icon_type;
-
- category = category.rstrip("/");
- category = category.lstrip("/");
- category = "Addons/" + category;
- if (!subcategory.is_empty()) {
- category += "/" + subcategory;
- }
-
- dict["category"] = category;
- dict["highend"] = highend;
+ Dictionary dict = get_custom_node_data(ref);
String key;
- key = category + "/" + name;
+ key = String(dict["category"]) + "/" + String(dict["name"]);
added[key] = dict;
}
@@ -1659,6 +1845,7 @@ void VisualShaderEditor::_update_parameters(bool p_update_refs) {
}
void VisualShaderEditor::_update_parameter_refs(HashSet<String> &p_deleted_names) {
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
for (int i = 0; i < VisualShader::TYPE_MAX; i++) {
VisualShader::Type type = VisualShader::Type(i);
@@ -1758,6 +1945,7 @@ void VisualShaderEditor::_add_input_port(int p_node, int p_port, int p_port_type
return;
}
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Add Input Port"));
undo_redo->add_do_method(node.ptr(), "add_input_port", p_port, p_port_type, p_name);
undo_redo->add_undo_method(node.ptr(), "remove_input_port", p_port);
@@ -1773,6 +1961,7 @@ void VisualShaderEditor::_add_output_port(int p_node, int p_port, int p_port_typ
return;
}
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Add Output Port"));
undo_redo->add_do_method(node.ptr(), "add_output_port", p_port, p_port_type, p_name);
undo_redo->add_undo_method(node.ptr(), "remove_output_port", p_port);
@@ -1788,6 +1977,7 @@ void VisualShaderEditor::_change_input_port_type(int p_type, int p_node, int p_p
return;
}
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Change Input Port Type"));
undo_redo->add_do_method(node.ptr(), "set_input_port_type", p_port, p_type);
undo_redo->add_undo_method(node.ptr(), "set_input_port_type", p_port, node->get_input_port_type(p_port));
@@ -1803,6 +1993,7 @@ void VisualShaderEditor::_change_output_port_type(int p_type, int p_node, int p_
return;
}
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Change Output Port Type"));
undo_redo->add_do_method(node.ptr(), "set_output_port_type", p_port, p_type);
undo_redo->add_undo_method(node.ptr(), "set_output_port_type", p_port, node->get_output_port_type(p_port));
@@ -1831,6 +2022,7 @@ void VisualShaderEditor::_change_input_port_name(const String &p_text, Object *p
return;
}
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Change Input Port Name"));
undo_redo->add_do_method(node.ptr(), "set_input_port_name", p_port_id, validated_name);
undo_redo->add_undo_method(node.ptr(), "set_input_port_name", p_port_id, node->get_input_port_name(p_port_id));
@@ -1857,6 +2049,7 @@ void VisualShaderEditor::_change_output_port_name(const String &p_text, Object *
return;
}
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Change Output Port Name"));
undo_redo->add_do_method(node.ptr(), "set_output_port_name", p_port_id, validated_name);
undo_redo->add_undo_method(node.ptr(), "set_output_port_name", p_port_id, prev_name);
@@ -1869,6 +2062,7 @@ void VisualShaderEditor::_expand_output_port(int p_node, int p_port, bool p_expa
Ref<VisualShaderNode> node = visual_shader->get_node(type, p_node);
ERR_FAIL_COND(!node.is_valid());
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
if (p_expand) {
undo_redo->create_action(TTR("Expand Output Port"));
} else {
@@ -1966,6 +2160,7 @@ void VisualShaderEditor::_remove_input_port(int p_node, int p_port) {
return;
}
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Remove Input Port"));
List<VisualShader::Connection> conns;
@@ -2015,6 +2210,7 @@ void VisualShaderEditor::_remove_output_port(int p_node, int p_port) {
return;
}
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Remove Output Port"));
List<VisualShader::Connection> conns;
@@ -2081,6 +2277,7 @@ void VisualShaderEditor::_expression_focus_out(Object *code_edit, int p_node) {
return;
}
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Set VisualShader Expression"));
undo_redo->add_do_method(node.ptr(), "set_expression", expression_box->get_text());
undo_redo->add_undo_method(node.ptr(), "set_expression", node->get_expression());
@@ -2144,6 +2341,7 @@ void VisualShaderEditor::_node_resized(const Vector2 &p_new_size, int p_type, in
return;
}
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Resize VisualShader Node"), UndoRedo::MERGE_ENDS);
undo_redo->add_do_method(this, "_set_node_size", p_type, p_node, p_new_size);
undo_redo->add_undo_method(this, "_set_node_size", p_type, p_node, node->get_size());
@@ -2160,6 +2358,7 @@ void VisualShaderEditor::_preview_select_port(int p_node, int p_port) {
if (node->get_output_port_for_preview() == p_port) {
p_port = -1; //toggle it
}
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(p_port == -1 ? TTR("Hide Port Preview") : TTR("Show Port Preview"));
undo_redo->add_do_method(node.ptr(), "set_output_port_for_preview", p_port);
undo_redo->add_undo_method(node.ptr(), "set_output_port_for_preview", prev_port);
@@ -2205,6 +2404,7 @@ void VisualShaderEditor::_comment_title_popup_hide() {
if (node->get_title() == comment_title_change_edit->get_text()) {
return; // nothing changed - ignored
}
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Set Comment Node Title"));
undo_redo->add_do_method(node.ptr(), "set_title", comment_title_change_edit->get_text());
undo_redo->add_undo_method(node.ptr(), "set_title", node->get_title());
@@ -2247,6 +2447,7 @@ void VisualShaderEditor::_comment_desc_popup_hide() {
if (node->get_description() == comment_desc_change_edit->get_text()) {
return; // nothing changed - ignored
}
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Set Comment Node Description"));
undo_redo->add_do_method(node.ptr(), "set_description", comment_desc_change_edit->get_text());
undo_redo->add_undo_method(node.ptr(), "set_description", node->get_title());
@@ -2267,6 +2468,7 @@ void VisualShaderEditor::_parameter_line_edit_changed(const String &p_text, int
return;
}
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Set Parameter Name"));
undo_redo->add_do_method(node.ptr(), "set_parameter_name", validated_name);
undo_redo->add_undo_method(node.ptr(), "set_parameter_name", node->get_parameter_name());
@@ -2302,6 +2504,7 @@ void VisualShaderEditor::_port_edited(const StringName &p_property, const Varian
Ref<VisualShaderNode> vsn = visual_shader->get_node(type, editing_node);
ERR_FAIL_COND(!vsn.is_valid());
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Set Input Default Port"));
Ref<VisualShaderNodeCustom> custom = Object::cast_to<VisualShaderNodeCustom>(vsn.ptr());
@@ -2725,6 +2928,7 @@ void VisualShaderEditor::_add_node(int p_idx, const Vector<Variant> &p_ops, Stri
int id_to_use = visual_shader->get_valid_node_id(type);
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
if (p_resource_path.is_empty()) {
undo_redo->create_action(TTR("Add Node to Visual Shader"));
} else {
@@ -2894,6 +3098,7 @@ void VisualShaderEditor::_add_node(int p_idx, const Vector<Variant> &p_ops, Stri
}
void VisualShaderEditor::_add_varying(const String &p_name, VisualShader::VaryingMode p_mode, VisualShader::VaryingType p_type) {
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(vformat(TTR("Add Varying to Visual Shader: %s"), p_name));
undo_redo->add_do_method(visual_shader.ptr(), "add_varying", p_name, p_mode, p_type);
@@ -2928,6 +3133,7 @@ void VisualShaderEditor::_add_varying(const String &p_name, VisualShader::Varyin
}
void VisualShaderEditor::_remove_varying(const String &p_name) {
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(vformat(TTR("Remove Varying from Visual Shader: %s"), p_name));
VisualShader::VaryingMode var_mode = visual_shader->get_varying_mode(p_name);
@@ -3015,6 +3221,7 @@ void VisualShaderEditor::_node_dragged(const Vector2 &p_from, const Vector2 &p_t
void VisualShaderEditor::_nodes_dragged() {
drag_dirty = false;
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Node(s) Moved"));
for (const DragOp &E : drag_buffer) {
@@ -3038,6 +3245,7 @@ void VisualShaderEditor::_connection_request(const String &p_from, int p_from_in
return;
}
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Nodes Connected"));
List<VisualShader::Connection> conns;
@@ -3069,6 +3277,7 @@ void VisualShaderEditor::_disconnection_request(const String &p_from, int p_from
int from = p_from.to_int();
int to = p_to.to_int();
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Nodes Disconnected"));
undo_redo->add_do_method(visual_shader.ptr(), "disconnect_nodes", type, from, p_from_index, to, p_to_index);
undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes", type, from, p_from_index, to, p_to_index);
@@ -3108,6 +3317,7 @@ void VisualShaderEditor::_delete_nodes(int p_type, const List<int> &p_nodes) {
List<VisualShader::Connection> conns;
visual_shader->get_node_connections(type, &conns);
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
for (const int &F : p_nodes) {
for (const VisualShader::Connection &E : conns) {
if (E.from_node == F || E.to_node == F) {
@@ -3180,6 +3390,7 @@ void VisualShaderEditor::_delete_nodes(int p_type, const List<int> &p_nodes) {
}
void VisualShaderEditor::_replace_node(VisualShader::Type p_type_id, int p_node_id, const StringName &p_from, const StringName &p_to) {
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->add_do_method(visual_shader.ptr(), "replace_node", p_type_id, p_node_id, p_to);
undo_redo->add_undo_method(visual_shader.ptr(), "replace_node", p_type_id, p_node_id, p_from);
}
@@ -3214,6 +3425,7 @@ void VisualShaderEditor::_update_parameter(VisualShader::Type p_type_id, int p_n
void VisualShaderEditor::_convert_constants_to_parameters(bool p_vice_versa) {
VisualShader::Type type_id = get_current_shader_type();
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
if (!p_vice_versa) {
undo_redo->create_action(TTR("Convert Constant Node(s) To Parameter(s)"));
} else {
@@ -3412,6 +3624,7 @@ void VisualShaderEditor::_delete_node_request(int p_type, int p_node) {
List<int> to_erase;
to_erase.push_back(p_node);
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Delete VisualShader Node"));
_delete_nodes(p_type, to_erase);
undo_redo->commit_action();
@@ -3440,6 +3653,7 @@ void VisualShaderEditor::_delete_nodes_request(const TypedArray<StringName> &p_n
return;
}
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Delete VisualShader Node(s)"));
_delete_nodes(get_current_shader_type(), to_erase);
undo_redo->commit_action();
@@ -3623,12 +3837,6 @@ void VisualShaderEditor::_show_members_dialog(bool at_mouse_pos, VisualShaderNod
node_filter->select_all();
}
-void VisualShaderEditor::_show_varying_menu() {
- varying_options->set_item_disabled(int(VaryingMenuOptions::REMOVE), visual_shader->get_varyings_count() == 0);
- varying_options->set_position(graph->get_screen_position() + varying_button->get_position() + Size2(0, varying_button->get_size().height));
- varying_options->popup();
-}
-
void VisualShaderEditor::_varying_menu_id_pressed(int p_idx) {
switch (VaryingMenuOptions(p_idx)) {
case VaryingMenuOptions::ADD: {
@@ -3858,6 +4066,7 @@ void VisualShaderEditor::_dup_copy_nodes(int p_type, List<CopyItem> &r_items, Li
}
void VisualShaderEditor::_dup_paste_nodes(int p_type, List<CopyItem> &r_items, const List<VisualShader::Connection> &p_connections, const Vector2 &p_offset, bool p_duplicate) {
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
if (p_duplicate) {
undo_redo->create_action(TTR("Duplicate VisualShader Node(s)"));
} else {
@@ -3976,6 +4185,7 @@ void VisualShaderEditor::_copy_nodes(bool p_cut) {
_dup_copy_nodes(get_current_shader_type(), copy_items_buffer, copy_connections_buffer);
if (p_cut) {
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Cut VisualShader Node(s)"));
List<int> ids;
@@ -4246,6 +4456,7 @@ void VisualShaderEditor::_float_constant_selected(int p_which) {
return; // same
}
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(vformat(TTR("Set Constant: %s"), float_constant_defs[p_which].name));
undo_redo->add_do_method(node.ptr(), "set_constant", float_constant_defs[p_which].value);
undo_redo->add_undo_method(node.ptr(), "set_constant", node->get_constant());
@@ -4334,7 +4545,7 @@ void VisualShaderEditor::_update_varying_tree() {
}
}
- varying_options->set_item_disabled(int(VaryingMenuOptions::REMOVE), count == 0);
+ varying_button->get_popup()->set_item_disabled(int(VaryingMenuOptions::REMOVE), count == 0);
}
void VisualShaderEditor::_varying_create() {
@@ -4506,6 +4717,7 @@ void VisualShaderEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da
saved_node_pos_dirty = true;
_add_node(idx, add_options[idx].ops);
} else if (d.has("files")) {
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Add Node(s) to Visual Shader"));
if (d["files"].get_type() == Variant::PACKED_STRING_ARRAY) {
@@ -4666,6 +4878,8 @@ void VisualShaderEditor::_bind_methods() {
ClassDB::bind_method("_update_constant", &VisualShaderEditor::_update_constant);
ClassDB::bind_method("_update_parameter", &VisualShaderEditor::_update_parameter);
ClassDB::bind_method("_expand_output_port", &VisualShaderEditor::_expand_output_port);
+ ClassDB::bind_method("_update_options_menu_deferred", &VisualShaderEditor::_update_options_menu_deferred);
+ ClassDB::bind_method("_rebuild_shader_deferred", &VisualShaderEditor::_rebuild_shader_deferred);
ClassDB::bind_method(D_METHOD("_get_drag_data_fw"), &VisualShaderEditor::get_drag_data_fw);
ClassDB::bind_method(D_METHOD("_can_drop_data_fw"), &VisualShaderEditor::can_drop_data_fw);
@@ -4676,6 +4890,7 @@ void VisualShaderEditor::_bind_methods() {
VisualShaderEditor::VisualShaderEditor() {
ShaderLanguage::get_keyword_list(&keyword_list);
+ EditorNode::get_singleton()->connect("resource_saved", callable_mp(this, &VisualShaderEditor::update_custom_type));
graph = memnew(GraphEdit);
graph->get_zoom_hbox()->set_h_size_flags(SIZE_EXPAND_FILL);
@@ -4809,17 +5024,15 @@ VisualShaderEditor::VisualShaderEditor() {
graph->get_zoom_hbox()->move_child(add_node, 0);
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);
+ varying_button = memnew(MenuButton);
varying_button->set_text(TTR("Manage Varyings"));
+ varying_button->set_switch_on_hover(true);
graph->get_zoom_hbox()->add_child(varying_button);
- varying_button->connect("pressed", callable_mp(this, &VisualShaderEditor::_show_varying_menu));
- varying_options = memnew(PopupMenu);
- add_child(varying_options);
- varying_options->add_item(TTR("Add Varying"), int(VaryingMenuOptions::ADD));
- varying_options->add_item(TTR("Remove Varying"), int(VaryingMenuOptions::REMOVE));
- varying_options->connect("id_pressed", callable_mp(this, &VisualShaderEditor::_varying_menu_id_pressed));
+ PopupMenu *varying_menu = varying_button->get_popup();
+ varying_menu->add_item(TTR("Add Varying"), int(VaryingMenuOptions::ADD));
+ varying_menu->add_item(TTR("Remove Varying"), int(VaryingMenuOptions::REMOVE));
+ varying_menu->connect("id_pressed", callable_mp(this, &VisualShaderEditor::_varying_menu_id_pressed));
preview_shader = memnew(Button);
preview_shader->set_flat(true);
@@ -5183,6 +5396,7 @@ VisualShaderEditor::VisualShaderEditor() {
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("CameraVisibleLayers", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "camera_visible_layers", "CAMERA_VISIBLE_LAYERS"), { "camera_visible_layers" }, VisualShaderNode::PORT_TYPE_SCALAR_INT, 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));
@@ -5202,6 +5416,7 @@ VisualShaderEditor::VisualShaderEditor() {
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("CameraVisibleLayers", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "camera_visible_layers", "CAMERA_VISIBLE_LAYERS"), { "camera_visible_layers" }, VisualShaderNode::PORT_TYPE_SCALAR_INT, 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));
@@ -5683,8 +5898,6 @@ VisualShaderEditor::VisualShaderEditor() {
_update_options_menu();
- undo_redo = EditorNode::get_undo_redo();
-
Ref<VisualShaderNodePluginDefault> default_plugin;
default_plugin.instantiate();
default_plugin->set_editor(this);
diff --git a/editor/plugins/visual_shader_editor_plugin.h b/editor/plugins/visual_shader_editor_plugin.h
index f7e033d753..d559237569 100644
--- a/editor/plugins/visual_shader_editor_plugin.h
+++ b/editor/plugins/visual_shader_editor_plugin.h
@@ -32,23 +32,21 @@
#define VISUAL_SHADER_EDITOR_PLUGIN_H
#include "editor/editor_plugin.h"
+#include "editor/editor_properties.h"
#include "editor/plugins/editor_resource_conversion_plugin.h"
+#include "scene/resources/syntax_highlighter.h"
#include "scene/resources/visual_shader.h"
-class Button;
class CodeEdit;
-class CodeHighlighter;
class CurveEditor;
class GraphEdit;
class GraphNode;
-class PopupMenu;
+class MenuButton;
class PopupPanel;
class RichTextLabel;
-class TextEdit;
class Tree;
class VisualShaderEditor;
-class EditorUndoRedoManager;
class VisualShaderNodePlugin : public RefCounted {
GDCLASS(VisualShaderNodePlugin, RefCounted);
@@ -135,6 +133,7 @@ public:
void update_curve_xyz(int p_node_id);
void set_expression(VisualShader::Type p_type, int p_node_id, const String &p_expression);
int get_constant_index(float p_constant) const;
+ Ref<Script> get_node_script(int p_node_id) const;
void update_node_size(int p_node_id);
void update_theme();
VisualShader::Type get_shader_type() const;
@@ -172,8 +171,7 @@ class VisualShaderEditor : public VBoxContainer {
Ref<VisualShader> visual_shader;
GraphEdit *graph = nullptr;
Button *add_node = nullptr;
- Button *varying_button = nullptr;
- PopupMenu *varying_options = nullptr;
+ MenuButton *varying_button = nullptr;
Button *preview_shader = nullptr;
OptionButton *edit_type = nullptr;
@@ -193,7 +191,9 @@ class VisualShaderEditor : public VBoxContainer {
PanelContainer *error_panel = nullptr;
Label *error_label = nullptr;
- Ref<EditorUndoRedoManager> undo_redo;
+ bool _block_update_options_menu = false;
+ bool _block_rebuild_shader = false;
+
Point2 saved_node_pos;
bool saved_node_pos_dirty = false;
@@ -290,7 +290,6 @@ class VisualShaderEditor : public VBoxContainer {
void _tools_menu_option(int p_idx);
void _show_members_dialog(bool at_mouse_pos, VisualShaderNode::PortType p_input_port_type = VisualShaderNode::PORT_TYPE_MAX, VisualShaderNode::PortType p_output_port_type = VisualShaderNode::PORT_TYPE_MAX);
- void _show_varying_menu();
void _varying_menu_id_pressed(int p_idx);
void _show_add_varying_dialog();
void _show_remove_varying_dialog();
@@ -502,6 +501,9 @@ class VisualShaderEditor : public VBoxContainer {
void _update_parameter_refs(HashSet<String> &p_names);
void _update_varyings();
+ void _update_options_menu_deferred();
+ void _rebuild_shader_deferred();
+
void _visibility_changed();
protected:
@@ -509,7 +511,6 @@ protected:
static void _bind_methods();
public:
- void update_nodes();
void add_plugin(const Ref<VisualShaderNodePlugin> &p_plugin);
void remove_plugin(const Ref<VisualShaderNodePlugin> &p_plugin);
@@ -518,6 +519,9 @@ public:
void clear_custom_types();
void add_custom_type(const String &p_name, const Ref<Script> &p_script, const String &p_description, int p_return_icon_type, const String &p_category, bool p_highend);
+ Dictionary get_custom_node_data(Ref<VisualShaderNodeCustom> &p_custom_node);
+ void update_custom_type(const Ref<Resource> &p_resource);
+
virtual Size2 get_minimum_size() const override;
void edit(VisualShader *p_visual_shader);
VisualShaderEditor();
diff --git a/editor/plugins/voxel_gi_editor_plugin.h b/editor/plugins/voxel_gi_editor_plugin.h
index 43d6f71e26..feff3b4f35 100644
--- a/editor/plugins/voxel_gi_editor_plugin.h
+++ b/editor/plugins/voxel_gi_editor_plugin.h
@@ -37,6 +37,7 @@
class EditorFileDialog;
struct EditorProgress;
+class HBoxContainer;
class VoxelGIEditorPlugin : public EditorPlugin {
GDCLASS(VoxelGIEditorPlugin, EditorPlugin);
diff --git a/editor/project_converter_3_to_4.cpp b/editor/project_converter_3_to_4.cpp
index 78f3b4de0e..e07c672f5c 100644
--- a/editor/project_converter_3_to_4.cpp
+++ b/editor/project_converter_3_to_4.cpp
@@ -366,6 +366,7 @@ static const char *gdscript_function_renames[][2] = {
{ "get_scancode", "get_keycode" }, // InputEventKey
{ "get_scancode_string", "get_keycode_string" }, // OS
{ "get_scancode_with_modifiers", "get_keycode_with_modifiers" }, // InputEventKey
+ { "get_selected_path", "get_current_directory" }, // EditorInterface
{ "get_shift", "is_shift_pressed" }, // InputEventWithModifiers
{ "get_size_override", "get_size_2d_override" }, // SubViewport
{ "get_slide_count", "get_slide_collision_count" }, // CharacterBody2D, CharacterBody3D
@@ -464,6 +465,7 @@ static const char *gdscript_function_renames[][2] = {
{ "post_import", "_post_import" }, // EditorScenePostImport
{ "print_stray_nodes", "print_orphan_nodes" }, // Node
{ "property_list_changed_notify", "notify_property_list_changed" }, // Object
+ { "raise", "move_to_front" }, // CanvasItem
{ "recognize", "_recognize" }, // ResourceFormatLoader
{ "regen_normalmaps", "regen_normal_maps" }, // ArrayMesh
{ "remove", "remove_at" }, // Array, broke Directory
@@ -591,6 +593,7 @@ static const char *gdscript_function_renames[][2] = {
{ "is_abs_path", "is_absolute_path" }, // String
{ "is_valid_integer", "is_valid_int" }, // String
{ "linear_interpolate", "lerp" }, // Color
+ { "find_last", "rfind" }, // Array, String
{ "to_ascii", "to_ascii_buffer" }, // String
{ "to_utf8", "to_utf8_buffer" }, // String
{ "to_wchar", "to_utf32_buffer" }, // String // TODO - utf32 or utf16?
@@ -1395,7 +1398,7 @@ static const char *class_renames[][2] = {
// { "Physics2DDirectBodyStateSW", "GodotPhysicsDirectBodyState2D" }, // Class is not visible in ClassDB
// { "Physics2DShapeQueryResult", "PhysicsShapeQueryResult2D" }, // Class is not visible in ClassDB
// { "PhysicsShapeQueryResult", "PhysicsShapeQueryResult3D" }, // Class is not visible in ClassDB
- // { "NativeScript","NativeExtension"}, ??
+ // { "NativeScript","GDExtension"}, ??
{ "ARVRAnchor", "XRAnchor3D" },
{ "ARVRCamera", "XRCamera3D" },
{ "ARVRController", "XRController3D" },
@@ -2170,7 +2173,7 @@ int ProjectConverter3To4::validate_conversion() {
lines.append(line);
}
}
- print_line(vformat("Checking for conversion - %d/%d file - \"%s\" with size - %d KB"), i + 1, collected_files.size(), file_name.trim_prefix("res://"), file_size / 1024);
+ print_line(vformat("Checking for conversion - %d/%d file - \"%s\" with size - %d KB", i + 1, collected_files.size(), file_name.trim_prefix("res://"), file_size / 1024));
Vector<String> changed_elements;
Vector<String> reason;
@@ -2442,10 +2445,10 @@ bool ProjectConverter3To4::test_conversion(RegExContainer &reg_container) {
valid = valid && test_conversion_with_regex("\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", reg_container);
valid = valid && test_conversion_with_regex("\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", reg_container);
- valid = valid && test_conversion_gdscript_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_gdscript_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_gdscript_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_gdscript_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_gdscript_builtin("var size : Vector2 = Vector2() setget set_function , get_function", "var size : Vector2 = Vector2() : get = get_function, set = set_function", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
+ valid = valid && test_conversion_gdscript_builtin("var size : Vector2 = Vector2() setget set_function , ", "var size : Vector2 = Vector2() : set = set_function", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
+ valid = valid && test_conversion_gdscript_builtin("var size : Vector2 = Vector2() setget set_function", "var size : Vector2 = Vector2() : set = set_function", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
+ valid = valid && test_conversion_gdscript_builtin("var size : Vector2 = Vector2() setget , get_function", "var size : Vector2 = Vector2() : get = get_function", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
valid = valid && test_conversion_gdscript_builtin("get_node(@", "get_node(", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
@@ -2677,7 +2680,7 @@ bool ProjectConverter3To4::test_array_names() {
// List of excluded functions from builtin types and global namespace, because currently it is not possible to get list of functions from them.
// This will be available when https://github.com/godotengine/godot/pull/49053 or similar will be included into Godot.
- static const char *builtin_types_excluded_functions[] = { "dict_to_inst", "inst_to_dict", "bytes_to_var", "bytes_to_var_with_objects", "db_to_linear", "deg_to_rad", "linear_to_db", "rad_to_deg", "randf_range", "snapped", "str_to_var", "var_to_str", "var_to_bytes", "var_to_bytes_with_objects", "move_toward", "uri_encode", "uri_decode", "remove_at", "get_rotation_quaternion", "clamp", "grow_side", "is_absolute_path", "is_valid_int", "lerp", "to_ascii_buffer", "to_utf8_buffer", "to_utf32_buffer", "snapped", "remap", nullptr };
+ static const char *builtin_types_excluded_functions[] = { "dict_to_inst", "inst_to_dict", "bytes_to_var", "bytes_to_var_with_objects", "db_to_linear", "deg_to_rad", "linear_to_db", "rad_to_deg", "randf_range", "snapped", "str_to_var", "var_to_str", "var_to_bytes", "var_to_bytes_with_objects", "move_toward", "uri_encode", "uri_decode", "remove_at", "get_rotation_quaternion", "clamp", "grow_side", "is_absolute_path", "is_valid_int", "lerp", "to_ascii_buffer", "to_utf8_buffer", "to_utf32_buffer", "snapped", "remap", "rfind", nullptr };
for (int current_index = 0; builtin_types_excluded_functions[current_index]; current_index++) {
all_functions.insert(builtin_types_excluded_functions[current_index]);
}
@@ -3141,17 +3144,17 @@ void ProjectConverter3To4::process_gdscript_line(String &line, const RegExContai
// Setget Setget
if (line.contains("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);
+ line = reg_container.reg_setget_setget.sub(line, "var $1$2: get = $4, set = $3", true);
}
// Setget set
if (line.contains("setget")) {
- 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);
+ line = reg_container.reg_setget_set.sub(line, "var $1$2: set = $3", true);
}
// Setget get
if (line.contains("setget")) {
- 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);
+ line = reg_container.reg_setget_get.sub(line, "var $1$2: get = $3", true);
}
// OS.window_fullscreen = a -> if a: DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_FULLSCREEN) else: DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_WINDOWED)
diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp
index b2a2566ad4..0d93c8a95e 100644
--- a/editor/project_manager.cpp
+++ b/editor/project_manager.cpp
@@ -49,6 +49,7 @@
#include "editor/editor_vcs_interface.h"
#include "main/main.h"
#include "scene/gui/center_container.h"
+#include "scene/gui/check_box.h"
#include "scene/gui/line_edit.h"
#include "scene/gui/margin_container.h"
#include "scene/gui/panel_container.h"
@@ -93,6 +94,7 @@ private:
Container *path_container;
Container *install_path_container;
Container *renderer_container;
+ Label *renderer_info;
HBoxContainer *default_files_container;
Ref<ButtonGroup> renderer_button_group;
Label *msg;
@@ -425,6 +427,35 @@ private:
ok_pressed();
}
+ void _renderer_selected() {
+ String renderer_type = renderer_button_group->get_pressed_button()->get_meta(SNAME("rendering_method"));
+
+ if (renderer_type == "forward_plus") {
+ renderer_info->set_text(
+ String::utf8("• ") + TTR("Supports desktop platforms only.") +
+ String::utf8("\n• ") + TTR("Advanced 3D graphics available.") +
+ String::utf8("\n• ") + TTR("Can scale to large complex scenes.") +
+ String::utf8("\n• ") + TTR("Uses RenderingDevice backend.") +
+ String::utf8("\n• ") + TTR("Slower rendering of simple scenes."));
+ } else if (renderer_type == "mobile") {
+ renderer_info->set_text(
+ String::utf8("• ") + TTR("Supports desktop + mobile platforms.") +
+ String::utf8("\n• ") + TTR("Less advanced 3D graphics.") +
+ String::utf8("\n• ") + TTR("Less scalable for complex scenes.") +
+ String::utf8("\n• ") + TTR("Uses RenderingDevice backend.") +
+ String::utf8("\n• ") + TTR("Fast rendering of simple scenes."));
+ } else if (renderer_type == "gl_compatibility") {
+ renderer_info->set_text(
+ String::utf8("• ") + TTR("Supports desktop, mobile + web platforms.") +
+ String::utf8("\n• ") + TTR("Least advanced 3D graphics (currently work-in-progress).") +
+ String::utf8("\n• ") + TTR("Intended for low-end/older devices.") +
+ String::utf8("\n• ") + TTR("Uses OpenGL 3 backend (OpenGL 3.3/ES 3.0/WebGL2).") +
+ String::utf8("\n• ") + TTR("Fastest rendering of simple scenes."));
+ } else {
+ WARN_PRINT("Unknown renderer type. Please report this as a bug on GitHub.");
+ }
+ }
+
void ok_pressed() override {
String dir = project_path->get_text();
@@ -435,17 +466,17 @@ private:
return;
}
- ProjectSettings *current = memnew(ProjectSettings);
-
- int err = current->setup(dir2, "");
+ // Load project.godot as ConfigFile to set the new name.
+ ConfigFile cfg;
+ String project_godot = dir2.path_join("project.godot");
+ Error err = cfg.load(project_godot);
if (err != OK) {
- set_message(vformat(TTR("Couldn't load project.godot in project path (error %d). It may be missing or corrupted."), err), MESSAGE_ERROR);
+ set_message(vformat(TTR("Couldn't load project at '%s' (error %d). It may be missing or corrupted."), project_godot, err), MESSAGE_ERROR);
} else {
- ProjectSettings::CustomMap edited_settings;
- edited_settings["application/config/name"] = project_name->get_text().strip_edges();
-
- if (current->save_custom(dir2.path_join("project.godot"), edited_settings, Vector<String>(), true) != OK) {
- set_message(TTR("Couldn't edit project.godot in project path."), MESSAGE_ERROR);
+ cfg.set_value("application", "config/name", project_name->get_text().strip_edges());
+ err = cfg.save(project_godot);
+ if (err != OK) {
+ set_message(vformat(TTR("Couldn't save project at '%s' (error %d)."), project_godot, err), MESSAGE_ERROR);
}
}
@@ -482,10 +513,15 @@ private:
String renderer_type = renderer_button_group->get_pressed_button()->get_meta(SNAME("rendering_method"));
initial_settings["rendering/renderer/rendering_method"] = renderer_type;
+ EditorSettings::get_singleton()->set("project_manager/default_renderer", renderer_type);
+ EditorSettings::get_singleton()->save();
+
if (renderer_type == "forward_plus") {
project_features.push_back("Forward Plus");
} else if (renderer_type == "mobile") {
project_features.push_back("Mobile");
+ } else if (renderer_type == "gl_compatibility") {
+ project_features.push_back("GL Compatibility");
} else {
WARN_PRINT("Unknown renderer type. Please report this as a bug on GitHub.");
}
@@ -693,18 +729,19 @@ public:
default_files_container->hide();
get_ok_button()->set_disabled(false);
- ProjectSettings *current = memnew(ProjectSettings);
-
- int err = current->setup(project_path->get_text(), "");
+ // Fetch current name from project.godot to prefill the text input.
+ ConfigFile cfg;
+ String project_godot = project_path->get_text().path_join("project.godot");
+ Error err = cfg.load(project_godot);
if (err != OK) {
- set_message(vformat(TTR("Couldn't load project.godot in project path (error %d). It may be missing or corrupted."), err), MESSAGE_ERROR);
+ set_message(vformat(TTR("Couldn't load project at '%s' (error %d). It may be missing or corrupted."), project_godot, err), MESSAGE_ERROR);
status_rect->show();
msg->show();
get_ok_button()->set_disabled(true);
- } else if (current->has_setting("application/config/name")) {
- String proj = current->get("application/config/name");
- project_name->set_text(proj);
- _text_changed(proj);
+ } else {
+ String cur_name = cfg.get_value("application", "config/name", "");
+ project_name->set_text(cur_name);
+ _text_changed(cur_name);
}
project_name->call_deferred(SNAME("grab_focus"));
@@ -858,42 +895,55 @@ public:
renderer_container->add_child(rshc);
renderer_button_group.instantiate();
+ // Left hand side, used for checkboxes to select renderer.
Container *rvb = memnew(VBoxContainer);
- rvb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
rshc->add_child(rvb);
+
+ String default_renderer_type = "forward_plus";
+ if (EditorSettings::get_singleton()->has_setting("project_manager/default_renderer")) {
+ default_renderer_type = EditorSettings::get_singleton()->get_setting("project_manager/default_renderer");
+ }
+
Button *rs_button = memnew(CheckBox);
rs_button->set_button_group(renderer_button_group);
rs_button->set_text(TTR("Forward+"));
rs_button->set_meta(SNAME("rendering_method"), "forward_plus");
- rs_button->set_pressed(true);
+ rs_button->connect("pressed", callable_mp(this, &ProjectDialog::_renderer_selected));
rvb->add_child(rs_button);
- l = memnew(Label);
- l->set_text(
- String::utf8("• ") + TTR("Supports desktop platforms only.") +
- String::utf8("\n• ") + TTR("Advanced 3D graphics available.") +
- String::utf8("\n• ") + TTR("Can scale to large complex scenes.") +
- String::utf8("\n• ") + TTR("Slower rendering of simple scenes."));
- l->set_modulate(Color(1, 1, 1, 0.7));
- rvb->add_child(l);
-
- rshc->add_child(memnew(VSeparator));
+ if (default_renderer_type == "forward_plus") {
+ rs_button->set_pressed(true);
+ }
- rvb = memnew(VBoxContainer);
- rvb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- rshc->add_child(rvb);
rs_button = memnew(CheckBox);
rs_button->set_button_group(renderer_button_group);
rs_button->set_text(TTR("Mobile"));
rs_button->set_meta(SNAME("rendering_method"), "mobile");
+ rs_button->connect("pressed", callable_mp(this, &ProjectDialog::_renderer_selected));
rvb->add_child(rs_button);
- l = memnew(Label);
- l->set_text(
- String::utf8("• ") + TTR("Supports desktop + mobile platforms.") +
- String::utf8("\n• ") + TTR("Less advanced 3D graphics.") +
- String::utf8("\n• ") + TTR("Less scalable for complex scenes.") +
- String::utf8("\n• ") + TTR("Faster rendering of simple scenes."));
- l->set_modulate(Color(1, 1, 1, 0.7));
- rvb->add_child(l);
+ if (default_renderer_type == "mobile") {
+ rs_button->set_pressed(true);
+ }
+
+ rs_button = memnew(CheckBox);
+ rs_button->set_button_group(renderer_button_group);
+ rs_button->set_text(TTR("Compatibility"));
+ rs_button->set_meta(SNAME("rendering_method"), "gl_compatibility");
+ rs_button->connect("pressed", callable_mp(this, &ProjectDialog::_renderer_selected));
+ rvb->add_child(rs_button);
+ if (default_renderer_type == "gl_compatibility") {
+ rs_button->set_pressed(true);
+ }
+
+ rshc->add_child(memnew(VSeparator));
+
+ // Right hand side, used for text explaining each choice.
+ rvb = memnew(VBoxContainer);
+ rvb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ rshc->add_child(rvb);
+ renderer_info = memnew(Label);
+ renderer_info->set_modulate(Color(1, 1, 1, 0.7));
+ rvb->add_child(renderer_info);
+ _renderer_selected();
l = memnew(Label);
l->set_text(TTR("The renderer can be changed later, but scenes may need to be adjusted."));
@@ -1251,7 +1301,6 @@ void ProjectList::migrate_config() {
if (FileAccess::exists(_config_path)) {
return;
}
- print_line("Migrating legacy project list");
List<PropertyInfo> properties;
EditorSettings::get_singleton()->get_property_list(&properties);
@@ -1264,6 +1313,8 @@ void ProjectList::migrate_config() {
}
String path = EDITOR_GET(property_key);
+ print_line("Migrating legacy project '" + path + "'.");
+
String favoriteKey = "favorite_projects/" + property_key.get_slice("/", 1);
bool favorite = EditorSettings::get_singleton()->has_setting(favoriteKey);
add_project(path, favorite);
@@ -1376,7 +1427,7 @@ void ProjectList::create_project_item_control(int p_index) {
favorite_box->set_name("FavoriteBox");
TextureButton *favorite = memnew(TextureButton);
favorite->set_name("FavoriteButton");
- favorite->set_normal_texture(favorite_icon);
+ favorite->set_texture_normal(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).bind(hb));
diff --git a/editor/project_manager.h b/editor/project_manager.h
index 7c05429dde..de4db2944f 100644
--- a/editor/project_manager.h
+++ b/editor/project_manager.h
@@ -38,6 +38,7 @@
#include "scene/gui/scroll_container.h"
#include "scene/gui/tree.h"
+class CheckBox;
class ProjectDialog;
class ProjectList;
diff --git a/editor/project_settings_editor.cpp b/editor/project_settings_editor.cpp
index 28111bed58..b99a83a546 100644
--- a/editor/project_settings_editor.cpp
+++ b/editor/project_settings_editor.cpp
@@ -274,10 +274,14 @@ void ProjectSettingsEditor::_add_feature_overrides() {
presets.insert("s3tc");
presets.insert("etc");
presets.insert("etc2");
+ presets.insert("editor");
+ presets.insert("template_debug");
+ presets.insert("template_release");
presets.insert("debug");
presets.insert("release");
- presets.insert("editor");
- presets.insert("standalone");
+ presets.insert("template");
+ presets.insert("double");
+ presets.insert("single");
presets.insert("32");
presets.insert("64");
presets.insert("movie");
@@ -549,6 +553,14 @@ void ProjectSettingsEditor::_update_theme() {
}
}
+void ProjectSettingsEditor::_input_filter_focused() {
+ set_close_on_escape(false);
+}
+
+void ProjectSettingsEditor::_input_filter_unfocused() {
+ set_close_on_escape(true);
+}
+
void ProjectSettingsEditor::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_VISIBILITY_CHANGED: {
@@ -679,6 +691,8 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) {
action_map_editor->connect("action_removed", callable_mp(this, &ProjectSettingsEditor::_action_removed));
action_map_editor->connect("action_renamed", callable_mp(this, &ProjectSettingsEditor::_action_renamed));
action_map_editor->connect("action_reordered", callable_mp(this, &ProjectSettingsEditor::_action_reordered));
+ action_map_editor->connect(SNAME("filter_focused"), callable_mp(this, &ProjectSettingsEditor::_input_filter_focused));
+ action_map_editor->connect(SNAME("filter_unfocused"), callable_mp(this, &ProjectSettingsEditor::_input_filter_unfocused));
tab_container->add_child(action_map_editor);
localization_editor = memnew(LocalizationEditor);
diff --git a/editor/project_settings_editor.h b/editor/project_settings_editor.h
index 7f6dd1b692..1687be47fb 100644
--- a/editor/project_settings_editor.h
+++ b/editor/project_settings_editor.h
@@ -107,6 +107,9 @@ class ProjectSettingsEditor : public AcceptDialog {
void _update_action_map_editor();
void _update_theme();
+ void _input_filter_focused();
+ void _input_filter_unfocused();
+
protected:
void _notification(int p_what);
static void _bind_methods();
diff --git a/editor/register_editor_types.cpp b/editor/register_editor_types.cpp
new file mode 100644
index 0000000000..8ac0aa6fe3
--- /dev/null
+++ b/editor/register_editor_types.cpp
@@ -0,0 +1,224 @@
+/*************************************************************************/
+/* register_editor_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_editor_types.h"
+
+#include "editor/animation_track_editor.h"
+#include "editor/debugger/debug_adapter/debug_adapter_server.h"
+#include "editor/editor_command_palette.h"
+#include "editor/editor_feature_profile.h"
+#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_resource_picker.h"
+#include "editor/editor_resource_preview.h"
+#include "editor/editor_run_script.h"
+#include "editor/editor_settings.h"
+#include "editor/editor_translation_parser.h"
+#include "editor/editor_undo_redo_manager.h"
+#include "editor/filesystem_dock.h"
+#include "editor/import/editor_import_plugin.h"
+#include "editor/import/resource_importer_scene.h"
+#include "editor/plugins/animation_tree_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/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"
+#include "editor/plugins/cpu_particles_2d_editor_plugin.h"
+#include "editor/plugins/cpu_particles_3d_editor_plugin.h"
+#include "editor/plugins/curve_editor_plugin.h"
+#include "editor/plugins/editor_debugger_plugin.h"
+#include "editor/plugins/font_config_plugin.h"
+#include "editor/plugins/gpu_particles_2d_editor_plugin.h"
+#include "editor/plugins/gpu_particles_3d_editor_plugin.h"
+#include "editor/plugins/gpu_particles_collision_sdf_editor_plugin.h"
+#include "editor/plugins/gradient_editor_plugin.h"
+#include "editor/plugins/gradient_texture_2d_editor_plugin.h"
+#include "editor/plugins/input_event_editor_plugin.h"
+#include "editor/plugins/light_occluder_2d_editor_plugin.h"
+#include "editor/plugins/lightmap_gi_editor_plugin.h"
+#include "editor/plugins/line_2d_editor_plugin.h"
+#include "editor/plugins/material_editor_plugin.h"
+#include "editor/plugins/mesh_editor_plugin.h"
+#include "editor/plugins/mesh_instance_3d_editor_plugin.h"
+#include "editor/plugins/mesh_library_editor_plugin.h"
+#include "editor/plugins/multimesh_editor_plugin.h"
+#include "editor/plugins/navigation_link_2d_editor_plugin.h"
+#include "editor/plugins/navigation_polygon_editor_plugin.h"
+#include "editor/plugins/node_3d_editor_gizmos.h"
+#include "editor/plugins/occluder_instance_3d_editor_plugin.h"
+#include "editor/plugins/packed_scene_editor_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/resource_preloader_editor_plugin.h"
+#include "editor/plugins/script_editor_plugin.h"
+#include "editor/plugins/shader_editor_plugin.h"
+#include "editor/plugins/shader_file_editor_plugin.h"
+#include "editor/plugins/skeleton_2d_editor_plugin.h"
+#include "editor/plugins/skeleton_3d_editor_plugin.h"
+#include "editor/plugins/skeleton_ik_3d_editor_plugin.h"
+#include "editor/plugins/sprite_2d_editor_plugin.h"
+#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/texture_3d_editor_plugin.h"
+#include "editor/plugins/texture_editor_plugin.h"
+#include "editor/plugins/texture_layered_editor_plugin.h"
+#include "editor/plugins/texture_region_editor_plugin.h"
+#include "editor/plugins/theme_editor_plugin.h"
+#include "editor/plugins/tiles/tiles_editor_plugin.h"
+#include "editor/plugins/version_control_editor_plugin.h"
+#include "editor/plugins/visual_shader_editor_plugin.h"
+#include "editor/plugins/voxel_gi_editor_plugin.h"
+
+void register_editor_types() {
+ ResourceLoader::set_timestamp_on_load(true);
+ ResourceSaver::set_timestamp_on_save(true);
+
+ GDREGISTER_CLASS(EditorPaths);
+ GDREGISTER_CLASS(EditorPlugin);
+ GDREGISTER_CLASS(EditorTranslationParserPlugin);
+ GDREGISTER_CLASS(EditorImportPlugin);
+ GDREGISTER_CLASS(EditorScript);
+ GDREGISTER_CLASS(EditorSelection);
+ GDREGISTER_CLASS(EditorFileDialog);
+ GDREGISTER_ABSTRACT_CLASS(EditorSettings);
+ GDREGISTER_CLASS(EditorNode3DGizmo);
+ GDREGISTER_CLASS(EditorNode3DGizmoPlugin);
+ GDREGISTER_ABSTRACT_CLASS(EditorResourcePreview);
+ GDREGISTER_CLASS(EditorResourcePreviewGenerator);
+ GDREGISTER_ABSTRACT_CLASS(EditorFileSystem);
+ GDREGISTER_CLASS(EditorFileSystemDirectory);
+ GDREGISTER_CLASS(EditorVCSInterface);
+ GDREGISTER_ABSTRACT_CLASS(ScriptEditor);
+ GDREGISTER_ABSTRACT_CLASS(ScriptEditorBase);
+ GDREGISTER_CLASS(EditorSyntaxHighlighter);
+ GDREGISTER_ABSTRACT_CLASS(EditorInterface);
+ GDREGISTER_CLASS(EditorExportPlugin);
+ GDREGISTER_ABSTRACT_CLASS(EditorExportPlatform);
+ GDREGISTER_CLASS(EditorResourceConversionPlugin);
+ GDREGISTER_CLASS(EditorSceneFormatImporter);
+ GDREGISTER_CLASS(EditorScenePostImportPlugin);
+ GDREGISTER_CLASS(EditorInspector);
+ GDREGISTER_CLASS(EditorInspectorPlugin);
+ GDREGISTER_CLASS(EditorProperty);
+ GDREGISTER_CLASS(AnimationTrackEditPlugin);
+ GDREGISTER_CLASS(ScriptCreateDialog);
+ GDREGISTER_CLASS(EditorFeatureProfile);
+ GDREGISTER_CLASS(EditorSpinSlider);
+ GDREGISTER_CLASS(EditorResourcePicker);
+ GDREGISTER_CLASS(EditorScriptPicker);
+ GDREGISTER_ABSTRACT_CLASS(EditorUndoRedoManager);
+
+ GDREGISTER_ABSTRACT_CLASS(FileSystemDock);
+ GDREGISTER_VIRTUAL_CLASS(EditorFileSystemImportFormatSupportQuery);
+
+ GDREGISTER_CLASS(EditorScenePostImport);
+ GDREGISTER_CLASS(EditorCommandPalette);
+ GDREGISTER_CLASS(EditorDebuggerPlugin);
+ GDREGISTER_ABSTRACT_CLASS(EditorDebuggerSession);
+
+ // This list is alphabetized, and plugins that depend on Node2D are in their own section below.
+ EditorPlugins::add_by_type<AnimationTreeEditorPlugin>();
+ EditorPlugins::add_by_type<AudioStreamEditorPlugin>();
+ EditorPlugins::add_by_type<AudioStreamRandomizerEditorPlugin>();
+ EditorPlugins::add_by_type<BitMapEditorPlugin>();
+ EditorPlugins::add_by_type<BoneMapEditorPlugin>();
+ EditorPlugins::add_by_type<Camera3DEditorPlugin>();
+ EditorPlugins::add_by_type<ControlEditorPlugin>();
+ EditorPlugins::add_by_type<CPUParticles3DEditorPlugin>();
+ EditorPlugins::add_by_type<CurveEditorPlugin>();
+ EditorPlugins::add_by_type<DebugAdapterServer>();
+ EditorPlugins::add_by_type<FontEditorPlugin>();
+ EditorPlugins::add_by_type<GPUParticles3DEditorPlugin>();
+ EditorPlugins::add_by_type<GPUParticlesCollisionSDF3DEditorPlugin>();
+ EditorPlugins::add_by_type<GradientEditorPlugin>();
+ EditorPlugins::add_by_type<GradientTexture2DEditorPlugin>();
+ EditorPlugins::add_by_type<InputEventEditorPlugin>();
+ EditorPlugins::add_by_type<LightmapGIEditorPlugin>();
+ EditorPlugins::add_by_type<MaterialEditorPlugin>();
+ EditorPlugins::add_by_type<MeshEditorPlugin>();
+ EditorPlugins::add_by_type<MeshInstance3DEditorPlugin>();
+ EditorPlugins::add_by_type<MeshLibraryEditorPlugin>();
+ EditorPlugins::add_by_type<MultiMeshEditorPlugin>();
+ EditorPlugins::add_by_type<OccluderInstance3DEditorPlugin>();
+ EditorPlugins::add_by_type<PackedSceneEditorPlugin>();
+ EditorPlugins::add_by_type<Path3DEditorPlugin>();
+ EditorPlugins::add_by_type<PhysicalBone3DEditorPlugin>();
+ EditorPlugins::add_by_type<Polygon3DEditorPlugin>();
+ EditorPlugins::add_by_type<ResourcePreloaderEditorPlugin>();
+ EditorPlugins::add_by_type<ShaderEditorPlugin>();
+ EditorPlugins::add_by_type<ShaderFileEditorPlugin>();
+ EditorPlugins::add_by_type<Skeleton3DEditorPlugin>();
+ EditorPlugins::add_by_type<SkeletonIK3DEditorPlugin>();
+ EditorPlugins::add_by_type<SpriteFramesEditorPlugin>();
+ EditorPlugins::add_by_type<StyleBoxEditorPlugin>();
+ EditorPlugins::add_by_type<SubViewportPreviewEditorPlugin>();
+ EditorPlugins::add_by_type<Texture3DEditorPlugin>();
+ EditorPlugins::add_by_type<TextureEditorPlugin>();
+ EditorPlugins::add_by_type<TextureLayeredEditorPlugin>();
+ EditorPlugins::add_by_type<TextureRegionEditorPlugin>();
+ EditorPlugins::add_by_type<ThemeEditorPlugin>();
+ EditorPlugins::add_by_type<VoxelGIEditorPlugin>();
+
+ // 2D
+ EditorPlugins::add_by_type<CollisionPolygon2DEditorPlugin>();
+ EditorPlugins::add_by_type<CollisionShape2DEditorPlugin>();
+ EditorPlugins::add_by_type<CPUParticles2DEditorPlugin>();
+ EditorPlugins::add_by_type<GPUParticles2DEditorPlugin>();
+ EditorPlugins::add_by_type<LightOccluder2DEditorPlugin>();
+ EditorPlugins::add_by_type<Line2DEditorPlugin>();
+ EditorPlugins::add_by_type<NavigationLink2DEditorPlugin>();
+ EditorPlugins::add_by_type<NavigationPolygonEditorPlugin>();
+ EditorPlugins::add_by_type<Path2DEditorPlugin>();
+ EditorPlugins::add_by_type<Polygon2DEditorPlugin>();
+ EditorPlugins::add_by_type<Cast2DEditorPlugin>();
+ EditorPlugins::add_by_type<Skeleton2DEditorPlugin>();
+ EditorPlugins::add_by_type<Sprite2DEditorPlugin>();
+ EditorPlugins::add_by_type<TilesEditorPlugin>();
+}
+
+void unregister_editor_types() {
+ EditorNode::cleanup();
+ if (EditorPaths::get_singleton()) {
+ EditorPaths::free();
+ }
+
+ EditorResourcePicker::clear_caches();
+}
diff --git a/editor/register_editor_types.h b/editor/register_editor_types.h
new file mode 100644
index 0000000000..f53e7e3649
--- /dev/null
+++ b/editor/register_editor_types.h
@@ -0,0 +1,37 @@
+/*************************************************************************/
+/* register_editor_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 REGISTER_EDITOR_TYPES_H
+#define REGISTER_EDITOR_TYPES_H
+
+void register_editor_types();
+void unregister_editor_types();
+
+#endif // REGISTER_EDITOR_TYPES_H
diff --git a/editor/rename_dialog.cpp b/editor/rename_dialog.cpp
index f918570c66..40683e2938 100644
--- a/editor/rename_dialog.cpp
+++ b/editor/rename_dialog.cpp
@@ -42,13 +42,13 @@
#include "modules/regex/regex.h"
#include "plugins/script_editor_plugin.h"
#include "scene/gui/control.h"
+#include "scene/gui/grid_container.h"
#include "scene/gui/label.h"
#include "scene/gui/separator.h"
#include "scene/gui/tab_container.h"
-RenameDialog::RenameDialog(SceneTreeEditor *p_scene_tree_editor, Ref<EditorUndoRedoManager> p_undo_redo) {
+RenameDialog::RenameDialog(SceneTreeEditor *p_scene_tree_editor) {
scene_tree_editor = p_scene_tree_editor;
- undo_redo = p_undo_redo;
preview_node = nullptr;
set_title(TTR("Batch Rename"));
@@ -582,7 +582,8 @@ void RenameDialog::rename() {
// Forward recursive as opposed to the actual renaming.
_iterate_scene(root_node, selected_node_list, &global_count);
- if (undo_redo.is_valid() && !to_rename.is_empty()) {
+ if (!to_rename.is_empty()) {
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Batch Rename"));
// Make sure to iterate reversed so that child nodes will find parents.
diff --git a/editor/rename_dialog.h b/editor/rename_dialog.h
index dac73b13b8..2a3fda59a4 100644
--- a/editor/rename_dialog.h
+++ b/editor/rename_dialog.h
@@ -42,8 +42,6 @@
#include "scene/gui/spin_box.h"
#include "scene/gui/tab_container.h"
-class EditorUndoRedoManager;
-
class RenameDialog : public ConfirmationDialog {
GDCLASS(RenameDialog, ConfirmationDialog);
@@ -64,7 +62,6 @@ class RenameDialog : public ConfirmationDialog {
static void _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);
SceneTreeEditor *scene_tree_editor = nullptr;
- Ref<EditorUndoRedoManager> undo_redo;
int global_count = 0;
LineEdit *lne_search = nullptr;
@@ -110,8 +107,7 @@ public:
void reset();
void rename();
- RenameDialog(SceneTreeEditor *p_scene_tree_editor, Ref<EditorUndoRedoManager> p_undo_redo = Ref<EditorUndoRedoManager>());
- ~RenameDialog() {}
+ RenameDialog(SceneTreeEditor *p_scene_tree_editor);
};
#endif // MODULE_REGEX_ENABLED
diff --git a/editor/reparent_dialog.cpp b/editor/reparent_dialog.cpp
index 75098b25b1..37712d4197 100644
--- a/editor/reparent_dialog.cpp
+++ b/editor/reparent_dialog.cpp
@@ -33,6 +33,7 @@
#include "core/string/print_string.h"
#include "scene/gui/box_container.h"
#include "scene/gui/label.h"
+#include "scene/gui/tree.h"
void ReparentDialog::_notification(int p_what) {
switch (p_what) {
diff --git a/editor/scene_create_dialog.cpp b/editor/scene_create_dialog.cpp
index 5b54a5a229..9f3ce26a59 100644
--- a/editor/scene_create_dialog.cpp
+++ b/editor/scene_create_dialog.cpp
@@ -175,7 +175,7 @@ Node *SceneCreateDialog::create_scene_root() {
root = gui_ctl;
} break;
case ROOT_OTHER:
- root = Object::cast_to<Node>(select_node_dialog->instance_selected());
+ root = Object::cast_to<Node>(select_node_dialog->instantiate_selected());
break;
}
diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp
index 64ac38aaa5..f91b571118 100644
--- a/editor/scene_tree_dock.cpp
+++ b/editor/scene_tree_dock.cpp
@@ -33,6 +33,7 @@
#include "core/config/project_settings.h"
#include "core/input/input.h"
#include "core/io/resource_saver.h"
+#include "core/object/class_db.h"
#include "core/object/message_queue.h"
#include "core/os/keyboard.h"
#include "editor/debugger/editor_debugger_node.h"
@@ -40,14 +41,17 @@
#include "editor/editor_file_dialog.h"
#include "editor/editor_node.h"
#include "editor/editor_paths.h"
+#include "editor/editor_quick_open.h"
#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_undo_redo_manager.h"
+#include "editor/inspector_dock.h"
#include "editor/multi_node_edit.h"
#include "editor/plugins/animation_player_editor_plugin.h"
#include "editor/plugins/canvas_item_editor_plugin.h"
#include "editor/plugins/node_3d_editor_plugin.h"
#include "editor/plugins/script_editor_plugin.h"
+#include "editor/reparent_dialog.h"
#include "editor/shader_create_dialog.h"
#include "scene/main/window.h"
#include "scene/property_utils.h"
@@ -106,7 +110,7 @@ void SceneTreeDock::shortcut_input(const Ref<InputEvent> &p_event) {
#endif // MODULE_REGEX_ENABLED
} else if (ED_IS_SHORTCUT("scene_tree/add_child_node", p_event)) {
_tool_selected(TOOL_NEW);
- } else if (ED_IS_SHORTCUT("scene_tree/instance_scene", p_event)) {
+ } else if (ED_IS_SHORTCUT("scene_tree/instantiate_scene", p_event)) {
_tool_selected(TOOL_INSTANTIATE);
} else if (ED_IS_SHORTCUT("scene_tree/expand_collapse_all", p_event)) {
_tool_selected(TOOL_EXPAND_COLLAPSE);
@@ -198,7 +202,7 @@ void SceneTreeDock::_perform_instantiate_scenes(const Vector<String> &p_files, N
Node *instantiated_scene = sdata->instantiate(PackedScene::GEN_EDIT_STATE_INSTANCE);
if (!instantiated_scene) {
current_option = -1;
- accept->set_text(vformat(TTR("Error instancing scene from %s"), p_files[i]));
+ accept->set_text(vformat(TTR("Error instantiating scene from %s"), p_files[i]));
accept->popup_centered();
error = true;
break;
@@ -206,7 +210,7 @@ void SceneTreeDock::_perform_instantiate_scenes(const Vector<String> &p_files, N
if (!edited_scene->get_scene_file_path().is_empty()) {
if (_cyclical_dependency_exists(edited_scene->get_scene_file_path(), instantiated_scene)) {
- accept->set_text(vformat(TTR("Cannot instance the scene '%s' because the current scene exists within one of its nodes."), p_files[i]));
+ accept->set_text(vformat(TTR("Cannot instantiate the scene '%s' because the current scene exists within one of its nodes."), p_files[i]));
accept->popup_centered();
error = true;
break;
@@ -225,28 +229,29 @@ void SceneTreeDock::_perform_instantiate_scenes(const Vector<String> &p_files, N
return;
}
- editor_data->get_undo_redo()->create_action(TTR("Instance Scene(s)"));
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
+ undo_redo->create_action(TTR("Instantiate Scene(s)"));
for (int i = 0; i < instances.size(); i++) {
Node *instantiated_scene = instances[i];
- editor_data->get_undo_redo()->add_do_method(parent, "add_child", instantiated_scene, true);
+ undo_redo->add_do_method(parent, "add_child", instantiated_scene, true);
if (p_pos >= 0) {
- editor_data->get_undo_redo()->add_do_method(parent, "move_child", instantiated_scene, p_pos + i);
+ undo_redo->add_do_method(parent, "move_child", instantiated_scene, p_pos + i);
}
- editor_data->get_undo_redo()->add_do_method(instantiated_scene, "set_owner", edited_scene);
- editor_data->get_undo_redo()->add_do_method(editor_selection, "clear");
- editor_data->get_undo_redo()->add_do_method(editor_selection, "add_node", instantiated_scene);
- editor_data->get_undo_redo()->add_do_reference(instantiated_scene);
- editor_data->get_undo_redo()->add_undo_method(parent, "remove_child", instantiated_scene);
+ undo_redo->add_do_method(instantiated_scene, "set_owner", edited_scene);
+ undo_redo->add_do_method(editor_selection, "clear");
+ undo_redo->add_do_method(editor_selection, "add_node", instantiated_scene);
+ undo_redo->add_do_reference(instantiated_scene);
+ undo_redo->add_undo_method(parent, "remove_child", instantiated_scene);
String new_name = parent->validate_child_name(instantiated_scene);
EditorDebuggerNode *ed = EditorDebuggerNode::get_singleton();
- editor_data->get_undo_redo()->add_do_method(ed, "live_debug_instance_node", edited_scene->get_path_to(parent), p_files[i], new_name);
- editor_data->get_undo_redo()->add_undo_method(ed, "live_debug_remove_node", NodePath(String(edited_scene->get_path_to(parent)).path_join(new_name)));
+ undo_redo->add_do_method(ed, "live_debug_instantiate_node", edited_scene->get_path_to(parent), p_files[i], new_name);
+ undo_redo->add_undo_method(ed, "live_debug_remove_node", NodePath(String(edited_scene->get_path_to(parent)).path_join(new_name)));
}
- editor_data->get_undo_redo()->commit_action();
+ undo_redo->commit_action();
_push_item(instances[instances.size() - 1]);
for (int i = 0; i < instances.size(); i++) {
emit_signal(SNAME("node_created"), instances[i]);
@@ -263,7 +268,7 @@ void SceneTreeDock::_replace_with_branch_scene(const String &p_file, Node *base)
Node *instantiated_scene = sdata->instantiate(PackedScene::GEN_EDIT_STATE_INSTANCE);
if (!instantiated_scene) {
- accept->set_text(vformat(TTR("Error instancing scene from %s"), p_file));
+ accept->set_text(vformat(TTR("Error instantiating scene from %s"), p_file));
accept->popup_centered();
return;
}
@@ -533,23 +538,24 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
return;
}
- editor_data->get_undo_redo()->create_action(TTR("Detach Script"), UndoRedo::MERGE_DISABLE, EditorNode::get_singleton()->get_edited_scene());
- editor_data->get_undo_redo()->add_do_method(EditorNode::get_singleton(), "push_item", (Script *)nullptr);
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
+ undo_redo->create_action(TTR("Detach Script"), UndoRedo::MERGE_DISABLE, EditorNode::get_singleton()->get_edited_scene());
+ undo_redo->add_do_method(EditorNode::get_singleton(), "push_item", (Script *)nullptr);
for (int i = 0; i < selection.size(); i++) {
Node *n = Object::cast_to<Node>(selection[i]);
Ref<Script> existing = n->get_script();
Ref<Script> empty = EditorNode::get_singleton()->get_object_custom_type_base(n);
if (existing != empty) {
- editor_data->get_undo_redo()->add_do_method(n, "set_script", empty);
- editor_data->get_undo_redo()->add_undo_method(n, "set_script", existing);
+ undo_redo->add_do_method(n, "set_script", empty);
+ undo_redo->add_undo_method(n, "set_script", existing);
}
}
- editor_data->get_undo_redo()->add_do_method(this, "_update_script_button");
- editor_data->get_undo_redo()->add_undo_method(this, "_update_script_button");
+ undo_redo->add_do_method(this, "_update_script_button");
+ undo_redo->add_undo_method(this, "_update_script_button");
- editor_data->get_undo_redo()->commit_action();
+ undo_redo->commit_action();
} break;
case TOOL_MOVE_UP:
case TOOL_MOVE_DOWN: {
@@ -603,11 +609,12 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
break; // one or more nodes can not be moved
}
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
if (selection.size() == 1) {
- editor_data->get_undo_redo()->create_action(TTR("Move Node In Parent"));
+ undo_redo->create_action(TTR("Move Node In Parent"));
}
if (selection.size() > 1) {
- editor_data->get_undo_redo()->create_action(TTR("Move Nodes In Parent"));
+ undo_redo->create_action(TTR("Move Nodes In Parent"));
}
for (int i = 0; i < selection.size(); i++) {
@@ -620,11 +627,11 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
int bottom_node_pos = bottom_node->get_index();
int top_node_pos_next = top_node->get_index() + (MOVING_DOWN ? 1 : -1);
- editor_data->get_undo_redo()->add_do_method(top_node->get_parent(), "move_child", top_node, top_node_pos_next);
- editor_data->get_undo_redo()->add_undo_method(bottom_node->get_parent(), "move_child", bottom_node, bottom_node_pos);
+ undo_redo->add_do_method(top_node->get_parent(), "move_child", top_node, top_node_pos_next);
+ undo_redo->add_undo_method(bottom_node->get_parent(), "move_child", bottom_node, bottom_node_pos);
}
- editor_data->get_undo_redo()->commit_action();
+ undo_redo->commit_action();
} break;
case TOOL_DUPLICATE: {
@@ -652,8 +659,9 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
break;
}
- editor_data->get_undo_redo()->create_action(TTR("Duplicate Node(s)"), UndoRedo::MERGE_DISABLE, selection.front()->get());
- editor_data->get_undo_redo()->add_do_method(editor_selection, "clear");
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
+ undo_redo->create_action(TTR("Duplicate Node(s)"), UndoRedo::MERGE_DISABLE, selection.front()->get());
+ undo_redo->add_do_method(editor_selection, "clear");
Node *dupsingle = nullptr;
@@ -678,28 +686,28 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
dup->set_name(parent->validate_child_name(dup));
- editor_data->get_undo_redo()->add_do_method(add_below_node, "add_sibling", dup, true);
+ undo_redo->add_do_method(add_below_node, "add_sibling", dup, true);
for (Node *F : owned) {
if (!duplimap.has(F)) {
continue;
}
Node *d = duplimap[F];
- editor_data->get_undo_redo()->add_do_method(d, "set_owner", node->get_owner());
+ undo_redo->add_do_method(d, "set_owner", node->get_owner());
}
- editor_data->get_undo_redo()->add_do_method(editor_selection, "add_node", dup);
- editor_data->get_undo_redo()->add_undo_method(parent, "remove_child", dup);
- editor_data->get_undo_redo()->add_do_reference(dup);
+ undo_redo->add_do_method(editor_selection, "add_node", dup);
+ undo_redo->add_undo_method(parent, "remove_child", dup);
+ undo_redo->add_do_reference(dup);
EditorDebuggerNode *ed = EditorDebuggerNode::get_singleton();
- editor_data->get_undo_redo()->add_do_method(ed, "live_debug_duplicate_node", edited_scene->get_path_to(node), dup->get_name());
- editor_data->get_undo_redo()->add_undo_method(ed, "live_debug_remove_node", NodePath(String(edited_scene->get_path_to(parent)).path_join(dup->get_name())));
+ undo_redo->add_do_method(ed, "live_debug_duplicate_node", edited_scene->get_path_to(node), dup->get_name());
+ undo_redo->add_undo_method(ed, "live_debug_remove_node", NodePath(String(edited_scene->get_path_to(parent)).path_join(dup->get_name())));
add_below_node = dup;
}
- editor_data->get_undo_redo()->commit_action();
+ undo_redo->commit_action();
if (dupsingle) {
_push_item(dupsingle);
@@ -768,29 +776,30 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
return;
}
- editor_data->get_undo_redo()->create_action(TTR("Make node as Root"));
- editor_data->get_undo_redo()->add_do_method(node->get_parent(), "remove_child", node);
- editor_data->get_undo_redo()->add_do_method(EditorNode::get_singleton(), "set_edited_scene", node);
- editor_data->get_undo_redo()->add_do_method(node, "add_child", root, true);
- editor_data->get_undo_redo()->add_do_method(node, "set_scene_file_path", root->get_scene_file_path());
- editor_data->get_undo_redo()->add_do_method(root, "set_scene_file_path", String());
- editor_data->get_undo_redo()->add_do_method(node, "set_owner", (Object *)nullptr);
- editor_data->get_undo_redo()->add_do_method(root, "set_owner", node);
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
+ undo_redo->create_action(TTR("Make node as Root"));
+ undo_redo->add_do_method(node->get_parent(), "remove_child", node);
+ undo_redo->add_do_method(EditorNode::get_singleton(), "set_edited_scene", node);
+ undo_redo->add_do_method(node, "add_child", root, true);
+ undo_redo->add_do_method(node, "set_scene_file_path", root->get_scene_file_path());
+ undo_redo->add_do_method(root, "set_scene_file_path", String());
+ undo_redo->add_do_method(node, "set_owner", (Object *)nullptr);
+ undo_redo->add_do_method(root, "set_owner", node);
_node_replace_owner(root, root, node, MODE_DO);
- editor_data->get_undo_redo()->add_undo_method(root, "set_scene_file_path", root->get_scene_file_path());
- editor_data->get_undo_redo()->add_undo_method(node, "set_scene_file_path", String());
- editor_data->get_undo_redo()->add_undo_method(node, "remove_child", root);
- editor_data->get_undo_redo()->add_undo_method(EditorNode::get_singleton(), "set_edited_scene", root);
- editor_data->get_undo_redo()->add_undo_method(node->get_parent(), "add_child", node, true);
- editor_data->get_undo_redo()->add_undo_method(node->get_parent(), "move_child", node, node->get_index());
- editor_data->get_undo_redo()->add_undo_method(root, "set_owner", (Object *)nullptr);
- editor_data->get_undo_redo()->add_undo_method(node, "set_owner", root);
+ undo_redo->add_undo_method(root, "set_scene_file_path", root->get_scene_file_path());
+ undo_redo->add_undo_method(node, "set_scene_file_path", String());
+ undo_redo->add_undo_method(node, "remove_child", root);
+ undo_redo->add_undo_method(EditorNode::get_singleton(), "set_edited_scene", root);
+ undo_redo->add_undo_method(node->get_parent(), "add_child", node, true);
+ undo_redo->add_undo_method(node->get_parent(), "move_child", node, node->get_index());
+ undo_redo->add_undo_method(root, "set_owner", (Object *)nullptr);
+ undo_redo->add_undo_method(node, "set_owner", root);
_node_replace_owner(root, root, root, MODE_UNDO);
- editor_data->get_undo_redo()->add_do_method(scene_tree, "update_tree");
- editor_data->get_undo_redo()->add_undo_method(scene_tree, "update_tree");
- editor_data->get_undo_redo()->commit_action();
+ undo_redo->add_do_method(scene_tree, "update_tree");
+ undo_redo->add_undo_method(scene_tree, "update_tree");
+ undo_redo->commit_action();
} break;
case TOOL_MULTI_EDIT: {
if (!profile_allow_editing) {
@@ -1012,7 +1021,7 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
Node *node = e->get();
if (node) {
Node *root = EditorNode::get_singleton()->get_edited_scene();
- Ref<EditorUndoRedoManager> undo_redo = editor_data->get_undo_redo();
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
if (!root) {
break;
}
@@ -1088,7 +1097,7 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
bool enabling = !first_selected->get()->is_unique_name_in_owner();
List<Node *> full_selection = editor_selection->get_full_selected_node_list();
- Ref<EditorUndoRedoManager> undo_redo = editor_data->get_undo_redo();
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
if (enabling) {
Vector<Node *> new_unique_nodes;
@@ -1147,11 +1156,13 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
if (TOOL_CREATE_FAVORITE == p_tool) {
String name = selected_favorite_root.get_slicec(' ', 0);
if (ScriptServer::is_global_class(name)) {
- new_node = Object::cast_to<Node>(ClassDB::instantiate(ScriptServer::get_global_class_native_base(name)));
Ref<Script> scr = ResourceLoader::load(ScriptServer::get_global_class_path(name), "Script");
- if (new_node && scr.is_valid()) {
- new_node->set_script(scr);
- new_node->set_name(name);
+ if (scr.is_valid()) {
+ new_node = Object::cast_to<Node>(ClassDB::instantiate(scr->get_instance_base_type()));
+ if (new_node) {
+ new_node->set_script(scr);
+ new_node->set_name(name);
+ }
}
} else {
new_node = Object::cast_to<Node>(ClassDB::instantiate(selected_favorite_root));
@@ -1211,19 +1222,21 @@ void SceneTreeDock::_property_selected(int p_idx) {
}
void SceneTreeDock::_perform_property_drop(Node *p_node, String p_property, Ref<Resource> p_res) {
- editor_data->get_undo_redo()->create_action(vformat(TTR("Set %s"), p_property));
- editor_data->get_undo_redo()->add_do_property(p_node, p_property, p_res);
- editor_data->get_undo_redo()->add_undo_property(p_node, p_property, p_node->get(p_property));
- editor_data->get_undo_redo()->commit_action();
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
+ undo_redo->create_action(vformat(TTR("Set %s"), p_property));
+ undo_redo->add_do_property(p_node, p_property, p_res);
+ undo_redo->add_undo_property(p_node, p_property, p_node->get(p_property));
+ undo_redo->commit_action();
}
void SceneTreeDock::add_root_node(Node *p_node) {
- editor_data->get_undo_redo()->create_action_for_history(TTR("New Scene Root"), editor_data->get_current_edited_scene_history_id());
- editor_data->get_undo_redo()->add_do_method(EditorNode::get_singleton(), "set_edited_scene", p_node);
- editor_data->get_undo_redo()->add_do_method(scene_tree, "update_tree");
- editor_data->get_undo_redo()->add_do_reference(p_node);
- editor_data->get_undo_redo()->add_undo_method(EditorNode::get_singleton(), "set_edited_scene", (Object *)nullptr);
- editor_data->get_undo_redo()->commit_action();
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
+ undo_redo->create_action_for_history(TTR("New Scene Root"), editor_data->get_current_edited_scene_history_id());
+ undo_redo->add_do_method(EditorNode::get_singleton(), "set_edited_scene", p_node);
+ undo_redo->add_do_method(scene_tree, "update_tree");
+ undo_redo->add_do_reference(p_node);
+ undo_redo->add_undo_method(EditorNode::get_singleton(), "set_edited_scene", (Object *)nullptr);
+ undo_redo->commit_action();
}
void SceneTreeDock::_notification(int p_what) {
@@ -1368,7 +1381,7 @@ void SceneTreeDock::_notification(int p_what) {
void SceneTreeDock::_node_replace_owner(Node *p_base, Node *p_node, Node *p_root, ReplaceOwnerMode p_mode) {
if (p_node->get_owner() == p_base && p_node != p_root) {
- Ref<EditorUndoRedoManager> undo_redo = editor_data->get_undo_redo();
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
switch (p_mode) {
case MODE_BIDI: {
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;
@@ -1602,8 +1615,9 @@ void SceneTreeDock::perform_node_renames(Node *p_base, HashMap<Node *, NodePath>
Variant old_variant = p_base->get(propertyname);
Variant updated_variant = old_variant;
if (_check_node_path_recursive(p_base, updated_variant, p_renames)) {
- editor_data->get_undo_redo()->add_do_property(p_base, propertyname, updated_variant);
- editor_data->get_undo_redo()->add_undo_property(p_base, propertyname, old_variant);
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
+ undo_redo->add_do_property(p_base, propertyname, updated_variant);
+ undo_redo->add_undo_property(p_base, propertyname, old_variant);
p_base->set(propertyname, updated_variant);
}
}
@@ -1648,6 +1662,7 @@ void SceneTreeDock::perform_node_renames(Node *p_base, HashMap<Node *, NodePath>
}
HashMap<Node *, NodePath>::Iterator found_path = p_renames->find(n);
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
if (found_path) {
if (found_path->value == NodePath()) {
//will be erased
@@ -1661,12 +1676,12 @@ void SceneTreeDock::perform_node_renames(Node *p_base, HashMap<Node *, NodePath>
ERR_FAIL_COND(!EI); //another bug
}
- editor_data->get_undo_redo()->add_do_method(anim.ptr(), "remove_track", idx);
- editor_data->get_undo_redo()->add_undo_method(anim.ptr(), "add_track", anim->track_get_type(i), idx);
- editor_data->get_undo_redo()->add_undo_method(anim.ptr(), "track_set_path", idx, track_np);
- editor_data->get_undo_redo()->add_undo_method(anim.ptr(), "track_set_interpolation_type", idx, anim->track_get_interpolation_type(i));
+ undo_redo->add_do_method(anim.ptr(), "remove_track", idx);
+ undo_redo->add_undo_method(anim.ptr(), "add_track", anim->track_get_type(i), idx);
+ undo_redo->add_undo_method(anim.ptr(), "track_set_path", idx, track_np);
+ undo_redo->add_undo_method(anim.ptr(), "track_set_interpolation_type", idx, anim->track_get_interpolation_type(i));
for (int j = 0; j < anim->track_get_key_count(i); j++) {
- editor_data->get_undo_redo()->add_undo_method(anim.ptr(), "track_insert_key", idx, anim->track_get_key_time(i, j), anim->track_get_key_value(i, j), anim->track_get_key_transition(i, j));
+ undo_redo->add_undo_method(anim.ptr(), "track_insert_key", idx, anim->track_get_key_time(i, j), anim->track_get_key_value(i, j), anim->track_get_key_transition(i, j));
}
ran.erase(i); //byebye channel
@@ -1679,8 +1694,8 @@ void SceneTreeDock::perform_node_renames(Node *p_base, HashMap<Node *, NodePath>
if (new_path == track_np) {
continue; //bleh
}
- editor_data->get_undo_redo()->add_do_method(anim.ptr(), "track_set_path", i, new_path);
- editor_data->get_undo_redo()->add_undo_method(anim.ptr(), "track_set_path", i, track_np);
+ undo_redo->add_do_method(anim.ptr(), "track_set_path", i, new_path);
+ undo_redo->add_undo_method(anim.ptr(), "track_set_path", i, track_np);
}
}
}
@@ -1814,7 +1829,8 @@ void SceneTreeDock::_do_reparent(Node *p_new_parent, int p_position_in_parent, V
// Sort by tree order, so re-adding is easy.
p_nodes.sort_custom<Node::Comparator>();
- editor_data->get_undo_redo()->create_action(TTR("Reparent Node"));
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
+ undo_redo->create_action(TTR("Reparent Node"), UndoRedo::MERGE_DISABLE, p_nodes[0]);
HashMap<Node *, NodePath> path_renames;
Vector<StringName> former_names;
@@ -1835,15 +1851,18 @@ void SceneTreeDock::_do_reparent(Node *p_new_parent, int p_position_in_parent, V
owners.push_back(E);
}
- if (new_parent == node->get_parent() && node->get_index() < p_position_in_parent + ni) {
+ bool same_parent = new_parent == node->get_parent();
+ if (same_parent && node->get_index() < p_position_in_parent + ni) {
inc--; // If the child will generate a gap when moved, adjust.
}
- editor_data->get_undo_redo()->add_do_method(node->get_parent(), "remove_child", node);
- editor_data->get_undo_redo()->add_do_method(new_parent, "add_child", node, true);
+ if (!same_parent) {
+ undo_redo->add_do_method(node->get_parent(), "remove_child", node);
+ undo_redo->add_do_method(new_parent, "add_child", node, true);
+ }
- if (p_position_in_parent >= 0) {
- editor_data->get_undo_redo()->add_do_method(new_parent, "move_child", node, p_position_in_parent + inc);
+ if (p_position_in_parent >= 0 || same_parent) {
+ undo_redo->add_do_method(new_parent, "move_child", node, p_position_in_parent + inc);
}
EditorDebuggerNode *ed = EditorDebuggerNode::get_singleton();
@@ -1873,29 +1892,29 @@ void SceneTreeDock::_do_reparent(Node *p_new_parent, int p_position_in_parent, V
}
}
- editor_data->get_undo_redo()->add_do_method(ed, "live_debug_reparent_node", edited_scene->get_path_to(node), edited_scene->get_path_to(new_parent), new_name, p_position_in_parent + inc);
- editor_data->get_undo_redo()->add_undo_method(ed, "live_debug_reparent_node", NodePath(String(edited_scene->get_path_to(new_parent)).path_join(new_name)), edited_scene->get_path_to(node->get_parent()), node->get_name(), node->get_index());
+ undo_redo->add_do_method(ed, "live_debug_reparent_node", edited_scene->get_path_to(node), edited_scene->get_path_to(new_parent), new_name, p_position_in_parent + inc);
+ undo_redo->add_undo_method(ed, "live_debug_reparent_node", NodePath(String(edited_scene->get_path_to(new_parent)).path_join(new_name)), edited_scene->get_path_to(node->get_parent()), node->get_name(), node->get_index());
if (p_keep_global_xform) {
if (Object::cast_to<Node2D>(node)) {
- editor_data->get_undo_redo()->add_do_method(node, "set_global_transform", Object::cast_to<Node2D>(node)->get_global_transform());
+ undo_redo->add_do_method(node, "set_global_transform", Object::cast_to<Node2D>(node)->get_global_transform());
}
if (Object::cast_to<Node3D>(node)) {
- editor_data->get_undo_redo()->add_do_method(node, "set_global_transform", Object::cast_to<Node3D>(node)->get_global_transform());
+ undo_redo->add_do_method(node, "set_global_transform", Object::cast_to<Node3D>(node)->get_global_transform());
}
if (Object::cast_to<Control>(node)) {
- editor_data->get_undo_redo()->add_do_method(node, "set_global_position", Object::cast_to<Control>(node)->get_global_position());
+ undo_redo->add_do_method(node, "set_global_position", Object::cast_to<Control>(node)->get_global_position());
}
}
- editor_data->get_undo_redo()->add_do_method(this, "_set_owners", edited_scene, owners);
+ undo_redo->add_do_method(this, "_set_owners", edited_scene, owners);
if (AnimationPlayerEditor::get_singleton()->get_track_editor()->get_root() == node) {
- editor_data->get_undo_redo()->add_do_method(AnimationPlayerEditor::get_singleton()->get_track_editor(), "set_root", node);
+ undo_redo->add_do_method(AnimationPlayerEditor::get_singleton()->get_track_editor(), "set_root", node);
}
- editor_data->get_undo_redo()->add_undo_method(new_parent, "remove_child", node);
- editor_data->get_undo_redo()->add_undo_method(node, "set_name", former_names[ni]);
+ undo_redo->add_undo_method(new_parent, "remove_child", node);
+ undo_redo->add_undo_method(node, "set_name", former_names[ni]);
inc++;
}
@@ -1913,29 +1932,29 @@ void SceneTreeDock::_do_reparent(Node *p_new_parent, int p_position_in_parent, V
int child_pos = node->get_index();
- editor_data->get_undo_redo()->add_undo_method(node->get_parent(), "add_child", node, true);
- editor_data->get_undo_redo()->add_undo_method(node->get_parent(), "move_child", node, child_pos);
- editor_data->get_undo_redo()->add_undo_method(this, "_set_owners", edited_scene, owners);
+ undo_redo->add_undo_method(node->get_parent(), "add_child", node, true);
+ undo_redo->add_undo_method(node->get_parent(), "move_child", node, child_pos);
+ undo_redo->add_undo_method(this, "_set_owners", edited_scene, owners);
if (AnimationPlayerEditor::get_singleton()->get_track_editor()->get_root() == node) {
- editor_data->get_undo_redo()->add_undo_method(AnimationPlayerEditor::get_singleton()->get_track_editor(), "set_root", node);
+ undo_redo->add_undo_method(AnimationPlayerEditor::get_singleton()->get_track_editor(), "set_root", node);
}
if (p_keep_global_xform) {
if (Object::cast_to<Node2D>(node)) {
- editor_data->get_undo_redo()->add_undo_method(node, "set_transform", Object::cast_to<Node2D>(node)->get_transform());
+ undo_redo->add_undo_method(node, "set_transform", Object::cast_to<Node2D>(node)->get_transform());
}
if (Object::cast_to<Node3D>(node)) {
- editor_data->get_undo_redo()->add_undo_method(node, "set_transform", Object::cast_to<Node3D>(node)->get_transform());
+ undo_redo->add_undo_method(node, "set_transform", Object::cast_to<Node3D>(node)->get_transform());
}
if (Object::cast_to<Control>(node)) {
- editor_data->get_undo_redo()->add_undo_method(node, "set_position", Object::cast_to<Control>(node)->get_position());
+ undo_redo->add_undo_method(node, "set_position", Object::cast_to<Control>(node)->get_position());
}
}
}
perform_node_renames(nullptr, &path_renames);
- editor_data->get_undo_redo()->commit_action();
+ undo_redo->commit_action();
}
void SceneTreeDock::_script_created(Ref<Script> p_script) {
@@ -1945,37 +1964,22 @@ void SceneTreeDock::_script_created(Ref<Script> p_script) {
return;
}
- 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"), UndoRedo::MERGE_DISABLE, node);
- 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"), UndoRedo::MERGE_DISABLE, selected.front()->get());
- for (Node *E : selected) {
- Ref<Script> existing = E->get_script();
- editor_data->get_undo_redo()->add_do_method(InspectorDock::get_singleton(), "store_script_properties", E);
- editor_data->get_undo_redo()->add_undo_method(InspectorDock::get_singleton(), "store_script_properties", E);
- 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);
- editor_data->get_undo_redo()->add_do_method(InspectorDock::get_singleton(), "apply_script_properties", E);
- editor_data->get_undo_redo()->add_undo_method(InspectorDock::get_singleton(), "apply_script_properties", E);
- 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();
- }
-
- _push_item(p_script.operator->());
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
+ undo_redo->create_action(TTR("Attach Script"), UndoRedo::MERGE_DISABLE, selected.front()->get());
+ for (Node *E : selected) {
+ Ref<Script> existing = E->get_script();
+ undo_redo->add_do_method(InspectorDock::get_singleton(), "store_script_properties", E);
+ undo_redo->add_undo_method(InspectorDock::get_singleton(), "store_script_properties", E);
+ undo_redo->add_do_method(E, "set_script", p_script);
+ undo_redo->add_undo_method(E, "set_script", existing);
+ undo_redo->add_do_method(InspectorDock::get_singleton(), "apply_script_properties", E);
+ undo_redo->add_undo_method(InspectorDock::get_singleton(), "apply_script_properties", E);
+ undo_redo->add_do_method(this, "_update_script_button");
+ undo_redo->add_undo_method(this, "_update_script_button");
+ }
+ undo_redo->commit_action();
+
+ _push_item(p_script.ptr());
_update_script_button();
}
@@ -1986,10 +1990,11 @@ void SceneTreeDock::_shader_created(Ref<Shader> p_shader) {
Ref<Shader> existing = selected_shader_material->get_shader();
- editor_data->get_undo_redo()->create_action(TTR("Set Shader"));
- editor_data->get_undo_redo()->add_do_method(selected_shader_material.ptr(), "set_shader", p_shader);
- editor_data->get_undo_redo()->add_undo_method(selected_shader_material.ptr(), "set_shader", existing);
- editor_data->get_undo_redo()->commit_action();
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
+ undo_redo->create_action(TTR("Set Shader"));
+ undo_redo->add_do_method(selected_shader_material.ptr(), "set_shader", p_shader);
+ undo_redo->add_undo_method(selected_shader_material.ptr(), "set_shader", existing);
+ undo_redo->commit_action();
}
void SceneTreeDock::_script_creation_closed() {
@@ -2054,11 +2059,8 @@ void SceneTreeDock::_delete_confirm(bool p_cut) {
EditorNode::get_singleton()->get_editor_plugins_over()->make_visible(false);
- if (p_cut) {
- editor_data->get_undo_redo()->create_action(TTR("Cut Node(s)"), UndoRedo::MERGE_DISABLE, remove_list.front()->get());
- } else {
- editor_data->get_undo_redo()->create_action(TTR("Remove Node(s)"), UndoRedo::MERGE_DISABLE, remove_list.front()->get());
- }
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
+ undo_redo->create_action(p_cut ? TTR("Cut Node(s)") : TTR("Remove Node(s)"), UndoRedo::MERGE_DISABLE, remove_list.front()->get());
bool entire_scene = false;
@@ -2070,11 +2072,11 @@ void SceneTreeDock::_delete_confirm(bool p_cut) {
}
if (entire_scene) {
- editor_data->get_undo_redo()->add_do_method(EditorNode::get_singleton(), "set_edited_scene", (Object *)nullptr);
- editor_data->get_undo_redo()->add_undo_method(EditorNode::get_singleton(), "set_edited_scene", edited_scene);
- editor_data->get_undo_redo()->add_undo_method(edited_scene, "set_owner", edited_scene->get_owner());
- editor_data->get_undo_redo()->add_undo_method(scene_tree, "update_tree");
- editor_data->get_undo_redo()->add_undo_reference(edited_scene);
+ undo_redo->add_do_method(EditorNode::get_singleton(), "set_edited_scene", (Object *)nullptr);
+ undo_redo->add_undo_method(EditorNode::get_singleton(), "set_edited_scene", edited_scene);
+ undo_redo->add_undo_method(edited_scene, "set_owner", edited_scene->get_owner());
+ undo_redo->add_undo_method(scene_tree, "update_tree");
+ undo_redo->add_undo_reference(edited_scene);
} else {
remove_list.sort_custom<Node::Comparator>(); //sort nodes to keep positions
@@ -2103,21 +2105,21 @@ void SceneTreeDock::_delete_confirm(bool p_cut) {
owners.push_back(F);
}
- editor_data->get_undo_redo()->add_do_method(n->get_parent(), "remove_child", n);
- editor_data->get_undo_redo()->add_undo_method(n->get_parent(), "add_child", n, true);
- editor_data->get_undo_redo()->add_undo_method(n->get_parent(), "move_child", n, n->get_index());
+ undo_redo->add_do_method(n->get_parent(), "remove_child", n);
+ undo_redo->add_undo_method(n->get_parent(), "add_child", n, true);
+ undo_redo->add_undo_method(n->get_parent(), "move_child", n, n->get_index());
if (AnimationPlayerEditor::get_singleton()->get_track_editor()->get_root() == n) {
- editor_data->get_undo_redo()->add_undo_method(AnimationPlayerEditor::get_singleton()->get_track_editor(), "set_root", n);
+ undo_redo->add_undo_method(AnimationPlayerEditor::get_singleton()->get_track_editor(), "set_root", n);
}
- editor_data->get_undo_redo()->add_undo_method(this, "_set_owners", edited_scene, owners);
- editor_data->get_undo_redo()->add_undo_reference(n);
+ undo_redo->add_undo_method(this, "_set_owners", edited_scene, owners);
+ undo_redo->add_undo_reference(n);
EditorDebuggerNode *ed = EditorDebuggerNode::get_singleton();
- editor_data->get_undo_redo()->add_do_method(ed, "live_debug_remove_and_keep_node", edited_scene->get_path_to(n), n->get_instance_id());
- editor_data->get_undo_redo()->add_undo_method(ed, "live_debug_restore_node", n->get_instance_id(), edited_scene->get_path_to(n->get_parent()), n->get_index());
+ undo_redo->add_do_method(ed, "live_debug_remove_and_keep_node", edited_scene->get_path_to(n), n->get_instance_id());
+ undo_redo->add_undo_method(ed, "live_debug_restore_node", n->get_instance_id(), edited_scene->get_path_to(n->get_parent()), n->get_index());
}
}
- editor_data->get_undo_redo()->commit_action();
+ undo_redo->commit_action();
// hack, force 2d editor viewport to refresh after deletion
if (CanvasItemEditor *editor = CanvasItemEditor::get_singleton()) {
@@ -2177,7 +2179,7 @@ void SceneTreeDock::_selection_changed() {
}
void SceneTreeDock::_do_create(Node *p_parent) {
- Variant c = create_dialog->instance_selected();
+ Variant c = create_dialog->instantiate_selected();
Node *child = Object::cast_to<Node>(c);
ERR_FAIL_COND(!child);
@@ -2187,28 +2189,29 @@ void SceneTreeDock::_do_create(Node *p_parent) {
}
child->set_name(new_name);
- editor_data->get_undo_redo()->create_action_for_history(TTR("Create Node"), editor_data->get_current_edited_scene_history_id());
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
+ undo_redo->create_action_for_history(TTR("Create Node"), editor_data->get_current_edited_scene_history_id());
if (edited_scene) {
- editor_data->get_undo_redo()->add_do_method(p_parent, "add_child", child, true);
- editor_data->get_undo_redo()->add_do_method(child, "set_owner", edited_scene);
- editor_data->get_undo_redo()->add_do_method(editor_selection, "clear");
- editor_data->get_undo_redo()->add_do_method(editor_selection, "add_node", child);
- editor_data->get_undo_redo()->add_do_reference(child);
- editor_data->get_undo_redo()->add_undo_method(p_parent, "remove_child", child);
+ undo_redo->add_do_method(p_parent, "add_child", child, true);
+ undo_redo->add_do_method(child, "set_owner", edited_scene);
+ undo_redo->add_do_method(editor_selection, "clear");
+ undo_redo->add_do_method(editor_selection, "add_node", child);
+ undo_redo->add_do_reference(child);
+ undo_redo->add_undo_method(p_parent, "remove_child", child);
EditorDebuggerNode *ed = EditorDebuggerNode::get_singleton();
- editor_data->get_undo_redo()->add_do_method(ed, "live_debug_create_node", edited_scene->get_path_to(p_parent), child->get_class(), new_name);
- editor_data->get_undo_redo()->add_undo_method(ed, "live_debug_remove_node", NodePath(String(edited_scene->get_path_to(p_parent)).path_join(new_name)));
+ undo_redo->add_do_method(ed, "live_debug_create_node", edited_scene->get_path_to(p_parent), child->get_class(), new_name);
+ undo_redo->add_undo_method(ed, "live_debug_remove_node", NodePath(String(edited_scene->get_path_to(p_parent)).path_join(new_name)));
} else {
- editor_data->get_undo_redo()->add_do_method(EditorNode::get_singleton(), "set_edited_scene", child);
- editor_data->get_undo_redo()->add_do_method(scene_tree, "update_tree");
- editor_data->get_undo_redo()->add_do_reference(child);
- editor_data->get_undo_redo()->add_undo_method(EditorNode::get_singleton(), "set_edited_scene", (Object *)nullptr);
+ undo_redo->add_do_method(EditorNode::get_singleton(), "set_edited_scene", child);
+ undo_redo->add_do_method(scene_tree, "update_tree");
+ undo_redo->add_do_reference(child);
+ undo_redo->add_undo_method(EditorNode::get_singleton(), "set_edited_scene", (Object *)nullptr);
}
- editor_data->get_undo_redo()->commit_action();
+ undo_redo->commit_action();
_push_item(c);
editor_selection->clear();
editor_selection->add_node(child);
@@ -2261,7 +2264,7 @@ void SceneTreeDock::_create() {
for (Node *n : selection) {
ERR_FAIL_COND(!n);
- Variant c = create_dialog->instance_selected();
+ Variant c = create_dialog->instantiate_selected();
ERR_FAIL_COND(!c);
Node *newnode = Object::cast_to<Node>(c);
@@ -2389,7 +2392,7 @@ void SceneTreeDock::replace_node(Node *p_node, Node *p_by_node, bool p_keep_prop
}
//p_remove_old was added to support undo
if (p_remove_old) {
- editor_data->get_undo_redo()->clear_history();
+ EditorNode::get_undo_redo()->clear_history();
}
newnode->set_name(newname);
@@ -2434,9 +2437,12 @@ void SceneTreeDock::_new_scene_from(String p_file) {
Node *copy = base->duplicate_from_editor(duplimap);
if (copy) {
+ // Handle Unique Nodes.
for (int i = 0; i < copy->get_child_count(false); i++) {
_set_node_owner_recursive(copy->get_child(i, false), copy);
}
+ // Root node cannot ever be unique name in its own Scene!
+ copy->set_unique_name_in_owner(false);
Ref<PackedScene> sdata = memnew(PackedScene);
Error err = sdata->pack(copy);
@@ -2602,17 +2608,50 @@ 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());
- if (Node *n = get_node(p_to)) {
- editor_data->get_undo_redo()->create_action(TTR("Attach Script"), UndoRedo::MERGE_DISABLE, n);
- 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();
+ Node *n = get_node(p_to);
+
+ if (!n) {
+ return;
+ }
+
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
+ if (Input::get_singleton()->is_key_pressed(Key::CTRL)) {
+ Object *obj = ClassDB::instantiate(scr->get_instance_base_type());
+ ERR_FAIL_NULL(obj);
+
+ Node *new_node = Object::cast_to<Node>(obj);
+ if (!new_node) {
+ if (!obj->is_ref_counted()) {
+ memdelete(obj);
+ }
+ ERR_FAIL_MSG("Script does not extend Node-derived type.");
+ }
+ new_node->set_name(Node::adjust_name_casing(p_file.get_file().get_basename()));
+ new_node->set_script(scr);
+
+ undo_redo->create_action(TTR("Instantiate Script"));
+ undo_redo->add_do_method(n, "add_child", new_node, true);
+ undo_redo->add_do_method(new_node, "set_owner", edited_scene);
+ undo_redo->add_do_method(editor_selection, "clear");
+ undo_redo->add_do_method(editor_selection, "add_node", new_node);
+ undo_redo->add_do_reference(new_node);
+ undo_redo->add_undo_method(n, "remove_child", new_node);
+
+ EditorDebuggerNode *ed = EditorDebuggerNode::get_singleton();
+ undo_redo->add_do_method(ed, "live_debug_create_node", edited_scene->get_path_to(n), new_node->get_class(), new_node->get_name());
+ undo_redo->add_undo_method(ed, "live_debug_remove_node", NodePath(String(edited_scene->get_path_to(n)).path_join(new_node->get_name())));
+ undo_redo->commit_action();
+ } else {
+ undo_redo->create_action(TTR("Attach Script"), UndoRedo::MERGE_DISABLE, n);
+ undo_redo->add_do_method(InspectorDock::get_singleton(), "store_script_properties", n);
+ undo_redo->add_undo_method(InspectorDock::get_singleton(), "store_script_properties", n);
+ undo_redo->add_do_method(n, "set_script", scr);
+ undo_redo->add_undo_method(n, "set_script", n->get_script());
+ undo_redo->add_do_method(InspectorDock::get_singleton(), "apply_script_properties", n);
+ undo_redo->add_undo_method(InspectorDock::get_singleton(), "apply_script_properties", n);
+ undo_redo->add_do_method(this, "_update_script_button");
+ undo_redo->add_undo_method(this, "_update_script_button");
+ undo_redo->commit_action();
}
}
@@ -2686,7 +2725,7 @@ void SceneTreeDock::_tree_rmb(const Vector2 &p_menu_pos) {
menu->clear();
if (profile_allow_editing) {
menu->add_icon_shortcut(get_theme_icon(SNAME("Add"), SNAME("EditorIcons")), ED_GET_SHORTCUT("scene_tree/add_child_node"), TOOL_NEW);
- menu->add_icon_shortcut(get_theme_icon(SNAME("Instance"), SNAME("EditorIcons")), ED_GET_SHORTCUT("scene_tree/instance_scene"), TOOL_INSTANTIATE);
+ menu->add_icon_shortcut(get_theme_icon(SNAME("Instance"), SNAME("EditorIcons")), ED_GET_SHORTCUT("scene_tree/instantiate_scene"), TOOL_INSTANTIATE);
}
menu->reset_size();
@@ -2719,7 +2758,7 @@ void SceneTreeDock::_tree_rmb(const Vector2 &p_menu_pos) {
}
menu->add_icon_shortcut(get_theme_icon(SNAME("Add"), SNAME("EditorIcons")), ED_GET_SHORTCUT("scene_tree/add_child_node"), TOOL_NEW);
- menu->add_icon_shortcut(get_theme_icon(SNAME("Instance"), SNAME("EditorIcons")), ED_GET_SHORTCUT("scene_tree/instance_scene"), TOOL_INSTANTIATE);
+ menu->add_icon_shortcut(get_theme_icon(SNAME("Instance"), SNAME("EditorIcons")), ED_GET_SHORTCUT("scene_tree/instantiate_scene"), TOOL_INSTANTIATE);
}
menu->add_icon_shortcut(get_theme_icon(SNAME("Collapse"), SNAME("EditorIcons")), ED_GET_SHORTCUT("scene_tree/expand_collapse_all"), TOOL_EXPAND_COLLAPSE);
menu->add_separator();
@@ -3147,7 +3186,7 @@ List<Node *> SceneTreeDock::paste_nodes() {
owner = paste_parent;
}
- Ref<EditorUndoRedoManager> &ur = editor_data->get_undo_redo();
+ Ref<EditorUndoRedoManager> &ur = EditorNode::get_undo_redo();
ur->create_action(TTR("Paste Node(s)"), UndoRedo::MERGE_DISABLE, EditorNode::get_singleton()->get_edited_scene());
ur->add_do_method(editor_selection, "clear");
@@ -3445,7 +3484,7 @@ SceneTreeDock::SceneTreeDock(Node *p_scene_root, EditorSelection *p_editor_selec
ED_SHORTCUT_OVERRIDE("scene_tree/batch_rename", "macos", KeyModifierMask::SHIFT | Key::ENTER);
ED_SHORTCUT("scene_tree/add_child_node", TTR("Add Child Node"), KeyModifierMask::CMD_OR_CTRL | Key::A);
- ED_SHORTCUT("scene_tree/instance_scene", TTR("Instantiate Child Scene"), KeyModifierMask::CMD_OR_CTRL | KeyModifierMask::SHIFT | Key::A);
+ ED_SHORTCUT("scene_tree/instantiate_scene", TTR("Instantiate Child Scene"), KeyModifierMask::CMD_OR_CTRL | KeyModifierMask::SHIFT | Key::A);
ED_SHORTCUT("scene_tree/expand_collapse_all", TTR("Expand/Collapse Branch"));
ED_SHORTCUT("scene_tree/cut_node", TTR("Cut"), KeyModifierMask::CMD_OR_CTRL | Key::X);
ED_SHORTCUT("scene_tree/copy_node", TTR("Copy"), KeyModifierMask::CMD_OR_CTRL | Key::C);
@@ -3477,7 +3516,7 @@ SceneTreeDock::SceneTreeDock(Node *p_scene_root, EditorSelection *p_editor_selec
button_instance->set_flat(true);
button_instance->connect("pressed", callable_mp(this, &SceneTreeDock::_tool_selected).bind(TOOL_INSTANTIATE, false));
button_instance->set_tooltip_text(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"));
+ button_instance->set_shortcut(ED_GET_SHORTCUT("scene_tree/instantiate_scene"));
filter_hbc->add_child(button_instance);
vbc->add_child(filter_hbc);
@@ -3514,6 +3553,7 @@ SceneTreeDock::SceneTreeDock(Node *p_scene_root, EditorSelection *p_editor_selec
button_tree_menu = memnew(MenuButton);
button_tree_menu->set_flat(true);
+ button_tree_menu->set_tooltip_text(TTR("Extra scene options."));
button_tree_menu->connect("about_to_popup", callable_mp(this, &SceneTreeDock::_update_tree_menu));
filter_hbc->add_child(button_tree_menu);
@@ -3579,7 +3619,7 @@ SceneTreeDock::SceneTreeDock(Node *p_scene_root, EditorSelection *p_editor_selec
create_dialog->connect("favorites_updated", callable_mp(this, &SceneTreeDock::_update_create_root_dialog));
#ifdef MODULE_REGEX_ENABLED
- rename_dialog = memnew(RenameDialog(scene_tree, editor_data->get_undo_redo()));
+ rename_dialog = memnew(RenameDialog(scene_tree));
add_child(rename_dialog);
#endif // MODULE_REGEX_ENABLED
diff --git a/editor/scene_tree_dock.h b/editor/scene_tree_dock.h
index 04bb4d93e7..ac368e1aab 100644
--- a/editor/scene_tree_dock.h
+++ b/editor/scene_tree_dock.h
@@ -31,28 +31,24 @@
#ifndef SCENE_TREE_DOCK_H
#define SCENE_TREE_DOCK_H
-#include "editor/create_dialog.h"
+#include "scene_tree_editor.h"
+
#include "editor/editor_data.h"
-#include "editor/editor_quick_open.h"
-#include "editor/groups_editor.h"
-#include "editor/reparent_dialog.h"
#include "editor/script_create_dialog.h"
-#include "scene/animation/animation_player.h"
#include "scene/gui/box_container.h"
-#include "scene/gui/button.h"
-#include "scene/gui/control.h"
-#include "scene/gui/label.h"
-#include "scene/gui/popup_menu.h"
-#include "scene/gui/tree.h"
-#include "scene_tree_editor.h"
+#include "scene/resources/animation.h"
+
+class EditorQuickOpen;
+class MenuButton;
+class ReparentDialog;
+class ShaderCreateDialog;
+class TextureRect;
#include "modules/modules_enabled.gen.h" // For regex.
#ifdef MODULE_REGEX_ENABLED
class RenameDialog;
#endif // MODULE_REGEX_ENABLED
-class ShaderCreateDialog;
-
class SceneTreeDock : public VBoxContainer {
GDCLASS(SceneTreeDock, VBoxContainer);
diff --git a/editor/scene_tree_editor.cpp b/editor/scene_tree_editor.cpp
index 46d3502a24..30a9dc5bbf 100644
--- a/editor/scene_tree_editor.cpp
+++ b/editor/scene_tree_editor.cpp
@@ -32,10 +32,10 @@
#include "core/config/project_settings.h"
#include "core/object/message_queue.h"
-#include "core/string/print_string.h"
#include "editor/editor_file_system.h"
#include "editor/editor_node.h"
#include "editor/editor_scale.h"
+#include "editor/editor_settings.h"
#include "editor/editor_undo_redo_manager.h"
#include "editor/node_dock.h"
#include "editor/plugins/animation_player_editor_plugin.h"
@@ -132,8 +132,16 @@ void SceneTreeEditor::_cell_button_pressed(Object *p_item, int p_column, int p_i
if (config_err.is_empty()) {
return;
}
- config_err = config_err.word_wrap(80);
- warning->set_text(config_err);
+
+ const PackedInt32Array boundaries = TS->string_get_word_breaks(config_err, "", 80);
+ PackedStringArray lines;
+ for (int i = 0; i < boundaries.size(); i += 2) {
+ const int start = boundaries[i];
+ const int end = boundaries[i + 1];
+ lines.append(config_err.substr(start, end - start + 1));
+ }
+
+ warning->set_text(String("\n").join(lines));
warning->popup_centered();
} else if (p_id == BUTTON_SIGNALS) {
diff --git a/editor/scene_tree_editor.h b/editor/scene_tree_editor.h
index 33ef5dbcb3..c1afcf0f45 100644
--- a/editor/scene_tree_editor.h
+++ b/editor/scene_tree_editor.h
@@ -32,8 +32,6 @@
#define SCENE_TREE_EDITOR_H
#include "editor/editor_data.h"
-#include "editor/editor_settings.h"
-#include "scene/gui/button.h"
#include "scene/gui/dialogs.h"
#include "scene/gui/tree.h"
diff --git a/editor/script_create_dialog.cpp b/editor/script_create_dialog.cpp
index 08c0f0f708..52f4ae553f 100644
--- a/editor/script_create_dialog.cpp
+++ b/editor/script_create_dialog.cpp
@@ -107,7 +107,15 @@ static Vector<String> _get_hierarchy(String p_class_name) {
void ScriptCreateDialog::_notification(int p_what) {
switch (p_what) {
- case NOTIFICATION_ENTER_TREE: {
+ case NOTIFICATION_ENTER_TREE:
+ case NOTIFICATION_THEME_CHANGED: {
+ for (int i = 0; i < ScriptServer::get_language_count(); i++) {
+ Ref<Texture2D> language_icon = get_theme_icon(ScriptServer::get_language(i)->get_type(), SNAME("EditorIcons"));
+ if (language_icon.is_valid()) {
+ language_menu->set_item_icon(i, language_icon);
+ }
+ }
+
String last_language = EditorSettings::get_singleton()->get_project_metadata("script_setup", "last_selected_language", "");
if (!last_language.is_empty()) {
for (int i = 0; i < language_menu->get_item_count(); i++) {
@@ -120,15 +128,9 @@ void ScriptCreateDialog::_notification(int p_what) {
} else {
language_menu->select(default_language);
}
-
- [[fallthrough]];
- }
- case NOTIFICATION_THEME_CHANGED: {
- for (int i = 0; i < ScriptServer::get_language_count(); i++) {
- Ref<Texture2D> language_icon = get_theme_icon(ScriptServer::get_language(i)->get_type(), SNAME("EditorIcons"));
- if (language_icon.is_valid()) {
- language_menu->set_item_icon(i, language_icon);
- }
+ if (EditorSettings::get_singleton()->has_meta("script_setup_use_script_templates")) {
+ is_using_templates = bool(EditorSettings::get_singleton()->get_meta("script_setup_use_script_templates"));
+ use_templates->set_pressed(is_using_templates);
}
path_button->set_icon(get_theme_icon(SNAME("Folder"), SNAME("EditorIcons")));
@@ -331,7 +333,12 @@ void ScriptCreateDialog::_template_changed(int p_template) {
EditorSettings::get_singleton()->set_project_metadata("script_setup", "templates_dictionary", dic_templates_project);
} else {
// Save template info to editor dictionary (not a project template).
- templates_dictionary[parent_name->get_text()] = sinfo.get_hash();
+ Dictionary dic_templates;
+ if (EditorSettings::get_singleton()->has_meta("script_setup_templates_dictionary")) {
+ dic_templates = (Dictionary)EditorSettings::get_singleton()->get_meta("script_setup_templates_dictionary");
+ }
+ dic_templates[parent_name->get_text()] = sinfo.get_hash();
+ EditorSettings::get_singleton()->set_meta("script_setup_templates_dictionary", dic_templates);
// Remove template from project dictionary as we last used an editor level template.
Dictionary dic_templates_project = EditorSettings::get_singleton()->get_project_metadata("script_setup", "templates_dictionary", Dictionary());
if (dic_templates_project.has(parent_name->get_text())) {
@@ -480,6 +487,7 @@ void ScriptCreateDialog::_built_in_pressed() {
void ScriptCreateDialog::_use_template_pressed() {
is_using_templates = use_templates->is_pressed();
+ EditorSettings::get_singleton()->set_meta("script_setup_use_script_templates", is_using_templates);
_update_dialog();
}
@@ -597,6 +605,10 @@ void ScriptCreateDialog::_update_template_menu() {
if (is_language_using_templates) {
// Get the latest templates used for each type of node from project settings then global settings.
Dictionary last_local_templates = EditorSettings::get_singleton()->get_project_metadata("script_setup", "templates_dictionary", Dictionary());
+ Dictionary last_global_templates;
+ if (EditorSettings::get_singleton()->has_meta("script_setup_templates_dictionary")) {
+ last_global_templates = (Dictionary)EditorSettings::get_singleton()->get_meta("script_setup_templates_dictionary");
+ }
String inherits_base_type = parent_name->get_text();
// If it inherits from a script, get its parent class first.
@@ -651,7 +663,7 @@ void ScriptCreateDialog::_update_template_menu() {
// Check for last used template for this node in project settings then in global settings.
if (last_local_templates.has(parent_name->get_text()) && t.get_hash() == String(last_local_templates[parent_name->get_text()])) {
last_used_template = id;
- } else if (last_used_template == -1 && templates_dictionary.has(parent_name->get_text()) && t.get_hash() == String(templates_dictionary[parent_name->get_text()])) {
+ } else if (last_used_template == -1 && last_global_templates.has(parent_name->get_text()) && t.get_hash() == String(last_global_templates[parent_name->get_text()])) {
last_used_template = id;
}
t.id = id;
@@ -853,7 +865,7 @@ ScriptLanguage::ScriptTemplate ScriptCreateDialog::_parse_template(const ScriptL
script_template.inherit = p_inherits;
String space_indent = " ";
// Get meta delimiter
- String meta_delimiter = String();
+ String meta_delimiter;
List<String> comment_delimiters;
p_language->get_comment_delimiters(&comment_delimiters);
for (const String &script_delimiter : comment_delimiters) {
diff --git a/editor/script_create_dialog.h b/editor/script_create_dialog.h
index fb1a49a1ca..25428508da 100644
--- a/editor/script_create_dialog.h
+++ b/editor/script_create_dialog.h
@@ -83,7 +83,6 @@ class ScriptCreateDialog : public ConfirmationDialog {
int current_language;
int default_language;
bool re_check_path = false;
- Dictionary templates_dictionary;
Control *path_controls[2];
Control *name_controls[2];
diff --git a/editor/shader_globals_editor.cpp b/editor/shader_globals_editor.cpp
index 596b3eefba..b778262fed 100644
--- a/editor/shader_globals_editor.cpp
+++ b/editor/shader_globals_editor.cpp
@@ -69,28 +69,12 @@ static const char *global_var_type_names[RS::GLOBAL_VAR_TYPE_MAX] = {
class ShaderGlobalsEditorInterface : public Object {
GDCLASS(ShaderGlobalsEditorInterface, Object)
- void _var_changed() {
- emit_signal(SNAME("var_changed"));
- }
-
-protected:
- static void _bind_methods() {
- ClassDB::bind_method("_var_changed", &ShaderGlobalsEditorInterface::_var_changed);
- ADD_SIGNAL(MethodInfo("var_changed"));
- }
-
- bool _set(const StringName &p_name, const Variant &p_value) {
- Variant existing = RS::get_singleton()->global_shader_parameter_get(p_name);
-
- if (existing.get_type() == Variant::NIL) {
- return false;
- }
-
+ void _set_var(const StringName &p_name, const Variant &p_value, const Variant &p_prev_value) {
Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Set Shader Global Variable"));
undo_redo->add_do_method(RS::get_singleton(), "global_shader_parameter_set", p_name, p_value);
- undo_redo->add_undo_method(RS::get_singleton(), "global_shader_parameter_set", p_name, existing);
+ undo_redo->add_undo_method(RS::get_singleton(), "global_shader_parameter_set", p_name, p_prev_value);
RS::GlobalShaderParameterType type = RS::get_singleton()->global_shader_parameter_get_type(p_name);
Dictionary gv;
gv["type"] = global_var_type_names[type];
@@ -113,6 +97,27 @@ protected:
block_update = true;
undo_redo->commit_action();
block_update = false;
+ }
+
+ void _var_changed() {
+ emit_signal(SNAME("var_changed"));
+ }
+
+protected:
+ static void _bind_methods() {
+ ClassDB::bind_method("_set_var", &ShaderGlobalsEditorInterface::_set_var);
+ ClassDB::bind_method("_var_changed", &ShaderGlobalsEditorInterface::_var_changed);
+ ADD_SIGNAL(MethodInfo("var_changed"));
+ }
+
+ bool _set(const StringName &p_name, const Variant &p_value) {
+ Variant existing = RS::get_singleton()->global_shader_parameter_get(p_name);
+
+ if (existing.get_type() == Variant::NIL) {
+ return false;
+ }
+
+ call_deferred("_set_var", p_name, p_value, existing);
return true;
}
@@ -394,7 +399,7 @@ void ShaderGlobalsEditor::_variable_added() {
return;
}
- Ref<EditorUndoRedoManager> undo_redo = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_singleton()->get_undo_redo();
Variant value = create_var(RS::GlobalShaderParameterType(variable_type->get_selected()));
@@ -413,7 +418,7 @@ void ShaderGlobalsEditor::_variable_added() {
}
void ShaderGlobalsEditor::_variable_deleted(const String &p_variable) {
- Ref<EditorUndoRedoManager> undo_redo = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_singleton()->get_undo_redo();
undo_redo->create_action(TTR("Add Shader Global Parameter"));
undo_redo->add_do_method(RS::get_singleton(), "global_shader_parameter_remove", p_variable);
diff --git a/editor/translations/af.po b/editor/translations/af.po
index 8ada9c3379..a705eb58fb 100644
--- a/editor/translations/af.po
+++ b/editor/translations/af.po
@@ -13115,9 +13115,10 @@ msgstr "EnkelHouer"
#: scene/2d/path_2d.cpp scene/2d/polygon_2d.cpp scene/2d/sprite.cpp
#: scene/3d/cpu_particles.cpp scene/3d/label_3d.cpp scene/3d/path.cpp
#: scene/3d/physics_body.cpp scene/3d/soft_body.cpp scene/3d/sprite_3d.cpp
-#: 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
+#: scene/3d/visual_instance.cpp 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
msgid "Offset"
msgstr ""
@@ -14517,13 +14518,13 @@ msgstr ""
#: editor/project_manager.cpp
msgid ""
-"Couldn't load project.godot in project path (error %d). It may be missing or "
-"corrupted."
+"Couldn't load project at '%s' (error %d). It may be missing or corrupted."
msgstr ""
#: editor/project_manager.cpp
-msgid "Couldn't edit project.godot in project path."
-msgstr ""
+#, fuzzy
+msgid "Couldn't save project at '%s' (error %d)."
+msgstr "Kan nie '%s' oopmaak nie."
#: editor/project_manager.cpp
msgid "Couldn't create project.godot in project path."
@@ -23582,6 +23583,15 @@ msgstr "Fout terwyl laai:"
msgid "AABB"
msgstr ""
+#: scene/3d/visual_instance.cpp
+#, fuzzy
+msgid "Sorting"
+msgstr "Skep Vouer"
+
+#: scene/3d/visual_instance.cpp
+msgid "Use AABB Center"
+msgstr ""
+
#: scene/3d/visual_instance.cpp scene/resources/navigation_mesh.cpp
msgid "Geometry"
msgstr ""
diff --git a/editor/translations/ar.po b/editor/translations/ar.po
index adaef249f8..204dd9a41b 100644
--- a/editor/translations/ar.po
+++ b/editor/translations/ar.po
@@ -69,13 +69,14 @@
# عبد الرحمن أبو سعدة ||Abd Alrahman abo saada <abdalrahmanabs2005@gmail.com>, 2022.
# xX-Void-Xx <arandomdude75@gmail.com>, 2022.
# أحمد النور <ahmed2699@gmail.com>, 2022.
+# Commander Gordon <gordoncommander@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-09-08 07:39+0000\n"
-"Last-Translator: أحمد النور <ahmed2699@gmail.com>\n"
+"PO-Revision-Date: 2022-10-29 23:55+0000\n"
+"Last-Translator: Commander Gordon <gordoncommander@gmail.com>\n"
"Language-Team: Arabic <https://hosted.weblate.org/projects/godot-engine/"
"godot/ar/>\n"
"Language: ar\n"
@@ -84,7 +85,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.14.1-dev\n"
+"X-Generator: Weblate 4.14.2-dev\n"
#: core/bind/core_bind.cpp main/main.cpp
msgid "Tablet Driver"
@@ -524,7 +525,7 @@ msgstr "السرعة"
#: core/os/input_event.cpp editor/project_settings_editor.cpp
#: scene/3d/sprite_3d.cpp
msgid "Axis"
-msgstr "محاور"
+msgstr "محور"
#: core/os/input_event.cpp
msgid "Axis Value"
@@ -714,9 +715,8 @@ msgid "Version Control Autoload On Startup"
msgstr "التحميل التلقائي للتحكم ÙÙŠ الإصدار عند بدء التشغيل"
#: core/project_settings.cpp
-#, fuzzy
msgid "Version Control Plugin Name"
-msgstr "إدارة الإصدارات (Version Control)"
+msgstr "اسم مدير اصدار Ø§Ù„Ø§Ø¶Ø§ÙØ©"
#: core/project_settings.cpp scene/2d/collision_object_2d.cpp
#: scene/3d/collision_object.cpp scene/gui/control.cpp
@@ -797,9 +797,8 @@ msgid "3D"
msgstr "ثلاثي الأبعاد 3D"
#: core/project_settings.cpp
-#, fuzzy
msgid "Smooth Trimesh Collision"
-msgstr "إنشاء متصادم تراميش قريب"
+msgstr "إنشاء متصادم ترام"
#: core/project_settings.cpp drivers/gles2/rasterizer_canvas_base_gles2.cpp
#: drivers/gles2/rasterizer_scene_gles2.cpp
@@ -1194,7 +1193,7 @@ msgstr "توطين"
#: 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
@@ -1204,7 +1203,7 @@ 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
@@ -1238,12 +1237,12 @@ msgstr "المجرى (Stream)"
#: 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
@@ -1373,7 +1372,7 @@ msgstr "الوقت(ثواني):"
#: editor/animation_track_editor.cpp
#, fuzzy
msgid "Position:"
-msgstr "مكان الرصيÙ"
+msgstr "مكان الرصيÙ:"
#: editor/animation_track_editor.cpp
#, fuzzy
@@ -1397,27 +1396,27 @@ msgstr "نوع:"
#: editor/animation_track_editor.cpp
#, fuzzy
msgid "(Invalid, expected type: %s)"
-msgstr "إدارة قوالب التصدير:"
+msgstr "إدارة قوالب التصدير"
#: 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
@@ -2613,7 +2612,7 @@ 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."
@@ -2821,7 +2820,7 @@ msgstr "تصدير المشروع لمنصة:"
#: editor/editor_export.cpp
#, fuzzy
msgid "Completed with warnings."
-msgstr "نسخ مسار العÙقدة"
+msgstr "نسخ مسار العÙقدة."
#: editor/editor_export.cpp
#, fuzzy
@@ -2831,7 +2830,7 @@ msgstr "اكتمل بنجاح."
#: editor/editor_export.cpp
#, fuzzy
msgid "Failed."
-msgstr "ÙØ´Ù„:"
+msgstr "ÙØ´Ù„."
#: editor/editor_export.cpp
msgid "Storing File:"
@@ -2858,12 +2857,12 @@ msgstr "لا يمكن إنشاء المجلد."
#: 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 "لا يمكن ÙØªØ­ المل٠للكتابة."
#: editor/editor_export.cpp
#, fuzzy
@@ -2998,17 +2997,17 @@ 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 "مل٠النموذج غير موجود: ."
#: 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
@@ -3304,7 +3303,7 @@ 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
@@ -3324,17 +3323,17 @@ 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
@@ -3661,7 +3660,7 @@ msgstr "عنصر Ù…ÙÙØ¹Ù„"
#: editor/editor_inspector.cpp
#, fuzzy
msgid "Draw Red"
-msgstr "استدعاءات الرسم:"
+msgstr "استدعاءات الرسم"
#: editor/editor_inspector.cpp
#, fuzzy
@@ -4429,7 +4428,7 @@ msgstr "Ù…ÙØªÙحص"
#: editor/editor_node.cpp
#, fuzzy
msgid "Default Property Name Style"
-msgstr "مسار المشروع:"
+msgstr "مسار المشروع"
#: editor/editor_node.cpp
msgid "Default Float Step"
@@ -5278,7 +5277,7 @@ msgstr "ÙØªØ­ الكود البرمجي"
#: editor/editor_resource_picker.cpp
#, fuzzy
msgid "Script Owner"
-msgstr "اسم النص البرمجي:"
+msgstr "اسم النص البرمجي"
#: editor/editor_run_native.cpp
msgid ""
@@ -5454,12 +5453,12 @@ 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
msgid "On Save"
@@ -5482,7 +5481,7 @@ msgstr "Ù†Ø§ÙØ°Ø© XForm"
#: editor/editor_settings.cpp
#, fuzzy
msgid "Thumbnail Size"
-msgstr "الصورة المصغرة..."
+msgstr "الصورة المصغرة"
#: editor/editor_settings.cpp
msgid "Docks"
@@ -5612,12 +5611,12 @@ msgstr "المظهر"
#: editor/editor_settings.cpp scene/gui/text_edit.cpp
msgid "Show Line Numbers"
-msgstr "اضهار رقم الخط"
+msgstr "اظهار رقم الخط"
#: editor/editor_settings.cpp
#, fuzzy
msgid "Line Numbers Zero Padded"
-msgstr "رقم الخط:"
+msgstr "رقم الخط"
#: editor/editor_settings.cpp
msgid "Show Bookmark Gutter"
@@ -5837,12 +5836,12 @@ 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"
@@ -6027,7 +6026,7 @@ msgstr "إعادة تسمية عنصر اللون"
#: editor/editor_settings.cpp
#, fuzzy
msgid "Bone Selected Color"
-msgstr "عدل على الحساب الحالي:"
+msgstr "عدل على الحساب الحالي"
#: editor/editor_settings.cpp
msgid "Bone IK Color"
@@ -6040,7 +6039,7 @@ msgstr "لون حدود العظام"
#: editor/editor_settings.cpp
#, fuzzy
msgid "Bone Outline Size"
-msgstr "حجم الخطوط:"
+msgstr "حجم الخطوط"
#: editor/editor_settings.cpp
msgid "Viewport Border Color"
@@ -6061,7 +6060,7 @@ msgstr "التمرير للتحريك"
#: editor/editor_settings.cpp
#, fuzzy
msgid "Pan Speed"
-msgstr "السرعة:"
+msgstr "السرعة"
#: editor/editor_settings.cpp editor/plugins/polygon_2d_editor_plugin.cpp
#, fuzzy
@@ -6136,7 +6135,7 @@ msgstr "الاقتطاع التلقائي"
#: editor/editor_settings.cpp
#, fuzzy
msgid "Save Before Running"
-msgstr "Ø§Ø­ÙØ¸ المشهد قبل التشغيل..."
+msgstr "Ø§Ø­ÙØ¸ المشهد قبل التشغيل"
#: editor/editor_settings.cpp
#, fuzzy
@@ -6182,7 +6181,7 @@ msgstr "مدير المشروع"
#: editor/editor_settings.cpp
#, fuzzy
msgid "Sorting Order"
-msgstr "إعادة تسمية مجلد:"
+msgstr "إعادة تسمية مجلد"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
msgid "Symbol Color"
@@ -6216,19 +6215,19 @@ 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
@@ -6255,12 +6254,12 @@ 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"
@@ -6269,7 +6268,7 @@ msgstr "لون علامة الإقحام"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
#, fuzzy
msgid "Caret Background Color"
-msgstr "لون خلÙية غير صالح."
+msgstr "لون خلÙية غير صالح"
#: editor/editor_settings.cpp
#, fuzzy
@@ -7047,7 +7046,7 @@ 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"
@@ -7072,7 +7071,7 @@ msgstr "كرر"
#: scene/gui/control.cpp
#, fuzzy
msgid "Filter"
-msgstr "مرشحات:"
+msgstr "مرشحات"
#: editor/import/resource_importer_layered_texture.cpp
#: editor/import/resource_importer_texture.cpp
@@ -7101,7 +7100,7 @@ msgstr "الاقتطاع التلقائي"
#: 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
@@ -7109,7 +7108,7 @@ msgstr "عَرضياً:"
#: scene/resources/style_box.cpp
#, fuzzy
msgid "Vertical"
-msgstr "شاقولياً:"
+msgstr "شاقولياً"
#: editor/import/resource_importer_obj.cpp
#, fuzzy
@@ -7124,7 +7123,7 @@ msgstr "وضع التحجيم"
#: editor/import/resource_importer_obj.cpp
#, fuzzy
msgid "Offset Mesh"
-msgstr "Ø§Ù„Ù…ÙØ¹Ø§Ø¯Ù„:"
+msgstr "Ø§Ù„Ù…ÙØ¹Ø§Ø¯Ù„"
#: editor/import/resource_importer_obj.cpp
#: editor/import/resource_importer_scene.cpp
@@ -7205,7 +7204,7 @@ 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"
@@ -7214,7 +7213,7 @@ msgstr "استخدم الأسماء القديمة"
#: editor/import/resource_importer_scene.cpp modules/gltf/gltf_state.cpp
#, fuzzy
msgid "Materials"
-msgstr "تغيرات المادة:"
+msgstr "تغيرات المادة"
#: editor/import/resource_importer_scene.cpp
#, fuzzy
@@ -7294,12 +7293,12 @@ 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
@@ -7321,7 +7320,7 @@ msgstr "مقاطع الرسوم المتحركة"
#: 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
@@ -7435,7 +7434,7 @@ msgstr "رأس"
#: editor/import/resource_importer_texture.cpp
#, fuzzy
msgid "Normal Map Invert Y"
-msgstr "حجم عشوائي:"
+msgstr "حجم عشوائي"
#: editor/import/resource_importer_texture.cpp
msgid "Size Limit"
@@ -7461,12 +7460,12 @@ msgstr ""
#: 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
@@ -7603,7 +7602,7 @@ msgstr "ÙØ´Ù„ تحميل المورد."
#: editor/inspector_dock.cpp
#, fuzzy
msgid "Property Name Style"
-msgstr "اسم المشروع:"
+msgstr "اسم المشروع"
#: editor/inspector_dock.cpp scene/gui/color_picker.cpp
msgid "Raw"
@@ -8627,7 +8626,7 @@ msgstr "خطأ ÙÙŠ التحميل"
#: editor/plugins/asset_library_editor_plugin.cpp
#, fuzzy
msgid "Available URLs"
-msgstr "Ø§Ù„Ù…Ù„ÙØ§Øª Ø§Ù„Ù…ØªÙˆØ§ÙØ±Ø©:"
+msgstr "Ø§Ù„Ù…Ù„ÙØ§Øª Ø§Ù„Ù…ØªÙˆØ§ÙØ±Ø©"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Download for this asset is already in progress!"
@@ -8763,7 +8762,9 @@ msgstr "لا يمكن انشاء خرائط الضوء, تاكد من ان الÙ
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid "Failed determining lightmap size. Maximum lightmap size too small?"
-msgstr "ÙØ´Ù„ تحديد حجم الخريطة الضوئية. الحجم الأقصى للخريطة المضيئة صغير جدًا؟"
+msgstr ""
+"ÙØ´Ù„ تحديد حجم الخريطة الضوئية (lightmap). هل الحجم الأقصى للخريطة الضوئية "
+"صغير جدًا؟"
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
@@ -9688,7 +9689,7 @@ msgstr "بطاقة تعريÙ"
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
msgid "Separator"
-msgstr "Ø§Ù„ØªØ¨Ø§Ø¹ÙØ¯Ø§Øª:"
+msgstr "Ø§Ù„ØªØ¨Ø§Ø¹ÙØ¯Ø§Øª"
#: editor/plugins/item_list_editor_plugin.cpp
msgid "Item %d"
@@ -10839,7 +10840,7 @@ msgstr ""
#: editor/plugins/script_editor_plugin.cpp
#, fuzzy
msgid "Current Script Background Color"
-msgstr "لون خلÙية غير صالح."
+msgstr "لون خلÙية غير صالح"
#: editor/plugins/script_editor_plugin.cpp
#, fuzzy
@@ -10854,7 +10855,7 @@ msgstr "إنشاء نص برمجي"
#: editor/plugins/script_editor_plugin.cpp
#, fuzzy
msgid "List Script Names As"
-msgstr "اسم النص البرمجي:"
+msgstr "اسم النص البرمجي"
#: editor/plugins/script_editor_plugin.cpp
msgid "Exec Flags"
@@ -13036,12 +13037,13 @@ msgstr "إعدادت المحاذاة"
#: scene/2d/path_2d.cpp scene/2d/polygon_2d.cpp scene/2d/sprite.cpp
#: scene/3d/cpu_particles.cpp scene/3d/label_3d.cpp scene/3d/path.cpp
#: scene/3d/physics_body.cpp scene/3d/soft_body.cpp scene/3d/sprite_3d.cpp
-#: 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
+#: scene/3d/visual_instance.cpp 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
@@ -13054,7 +13056,7 @@ msgstr "الخطوة"
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
msgid "Separation"
-msgstr "Ø§Ù„ØªØ¨Ø§Ø¹ÙØ¯Ø§Øª:"
+msgstr "Ø§Ù„ØªØ¨Ø§Ø¹ÙØ¯Ø§Øª"
#: editor/plugins/tile_set_editor_plugin.cpp
#, fuzzy
@@ -13075,14 +13077,14 @@ 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
@@ -13103,7 +13105,7 @@ msgstr "وضع قناع-Ø§Ù„Ø¨ÙØª"
#: editor/plugins/tile_set_editor_plugin.cpp
#, fuzzy
msgid "Subtile Size"
-msgstr "حجم الخطوط:"
+msgstr "حجم الخطوط"
#: editor/plugins/tile_set_editor_plugin.cpp
#, fuzzy
@@ -13123,7 +13125,7 @@ msgstr "وضع التنقل"
#: editor/plugins/tile_set_editor_plugin.cpp
#, fuzzy
msgid "Shape Offset"
-msgstr "Ø§Ù„Ù…ÙØ¹Ø§Ø¯Ù„:"
+msgstr "Ø§Ù„Ù…ÙØ¹Ø§Ø¯Ù„"
#: editor/plugins/tile_set_editor_plugin.cpp
#, fuzzy
@@ -13242,7 +13244,7 @@ msgstr "أختر مسار Ø§Ù„Ù…ÙØªØ§Ø­ الخاص Ù„SSH"
#: editor/plugins/version_control_editor_plugin.cpp
msgid "SSH Passphrase"
-msgstr "كلمة مرور SSH"
+msgstr "كلمة المرور ل(SSH)"
#: editor/plugins/version_control_editor_plugin.cpp
msgid "Detect new changes"
@@ -14395,12 +14397,12 @@ 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"
@@ -14409,12 +14411,12 @@ 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"
@@ -14497,15 +14499,16 @@ msgid "Invalid project path (changed anything?)."
msgstr "مسار مشروع غير صالح (أعدلت شيء؟)."
#: editor/project_manager.cpp
+#, fuzzy
msgid ""
-"Couldn't load project.godot in project path (error %d). It may be missing or "
-"corrupted."
+"Couldn't load project at '%s' (error %d). It may be missing or corrupted."
msgstr ""
"لم يتم تحميل project.godot من مسار المشروع (خطأ %d). قد يكون Ù…Ùقوداً أو ØªØ§Ù„ÙØ§Ù‹."
#: editor/project_manager.cpp
-msgid "Couldn't edit project.godot in project path."
-msgstr "لا قدرة على تحرير project.godot ÙÙŠ مسار المشروع."
+#, fuzzy
+msgid "Couldn't save project at '%s' (error %d)."
+msgstr "لا يمكن ÙØªØ­ المشروع ÙÙŠ '%s'."
#: editor/project_manager.cpp
msgid "Couldn't create project.godot in project path."
@@ -15541,7 +15544,7 @@ msgstr "اجعله محلياً"
#: editor/scene_tree_dock.cpp
#, fuzzy
msgid "Enable Scene Unique Name(s)"
-msgstr "إسم العقدة:"
+msgstr "إسم العقدة"
#: editor/scene_tree_dock.cpp
#, fuzzy
@@ -15551,7 +15554,7 @@ msgstr "لقد تم استخدام هذا الاسم ÙÙŠ ÙˆØ¸ÙŠÙØ© برمجيØ
#: editor/scene_tree_dock.cpp
#, fuzzy
msgid "Disable Scene Unique Name(s)"
-msgstr "إسم العقدة:"
+msgstr "إسم العقدة"
#: editor/scene_tree_dock.cpp
msgid "New Scene Root"
@@ -15752,7 +15755,7 @@ msgstr "مجموعة الأزرار"
#: editor/scene_tree_editor.cpp
#, fuzzy
msgid "Disable Scene Unique Name"
-msgstr "إسم العقدة:"
+msgstr "إسم العقدة"
#: editor/scene_tree_editor.cpp
msgid "(Connecting From)"
@@ -16634,7 +16637,7 @@ msgstr "الحجم الكامل"
#: main/main.cpp scene/resources/dynamic_font.cpp
#, fuzzy
msgid "Use Filter"
-msgstr "تصÙية:"
+msgstr "تصÙية"
#: main/main.cpp scene/resources/style_box.cpp
#, fuzzy
@@ -16683,7 +16686,7 @@ msgstr ""
#: main/main.cpp
#, fuzzy
msgid "Tooltip Position Offset"
-msgstr "مقدار إزاحة الدوران:"
+msgstr "مقدار إزاحة الدوران"
#: main/main.cpp modules/mono/mono_gd/gd_mono.cpp
#, fuzzy
@@ -16698,7 +16701,7 @@ msgstr "Ù…Ùنقح الأخطاء"
#: main/main.cpp modules/mono/mono_gd/gd_mono.cpp
#, fuzzy
msgid "Wait Timeout"
-msgstr "انتهت المهلة."
+msgstr "انتهت المهلة"
#: main/main.cpp
msgid "Runtime"
@@ -16808,12 +16811,12 @@ msgstr "اقلب الوجوه"
#: 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
msgid "Rings"
@@ -16878,7 +16881,7 @@ msgstr ""
#: modules/csg/csg_shape.cpp
#, fuzzy
msgid "Path Rotation"
-msgstr "دوران عشوائي:"
+msgstr "دوران عشوائي"
#: modules/csg/csg_shape.cpp
#, fuzzy
@@ -16897,7 +16900,7 @@ msgstr "المسار المحلي"
#: modules/csg/csg_shape.cpp
#, fuzzy
msgid "Path Joined"
-msgstr "دوران عشوائي:"
+msgstr "دوران عشوائي"
#: modules/enet/networked_multiplayer_enet.cpp
msgid "Compression Mode"
@@ -17020,12 +17023,12 @@ 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
msgid "Icon Path"
@@ -17134,7 +17137,7 @@ msgstr "الواجهة View الخلÙية"
#: modules/gltf/gltf_accessor.cpp modules/gltf/gltf_buffer_view.cpp
#, fuzzy
msgid "Byte Offset"
-msgstr "مقدار إزاحة الشبكة:"
+msgstr "مقدار إزاحة الشبكة"
#: modules/gltf/gltf_accessor.cpp
msgid "Component Type"
@@ -17147,7 +17150,7 @@ msgstr ""
#: modules/gltf/gltf_accessor.cpp
#, fuzzy
msgid "Count"
-msgstr "الكمية:"
+msgstr "الكمية"
#: modules/gltf/gltf_accessor.cpp scene/resources/visual_shader_nodes.cpp
msgid "Min"
@@ -17173,7 +17176,7 @@ msgstr ""
#: modules/gltf/gltf_accessor.cpp
#, fuzzy
msgid "Sparse Indices Component Type"
-msgstr "توزيع الأشكال الهندسية..."
+msgstr "توزيع الأشكال الهندسية"
#: modules/gltf/gltf_accessor.cpp
msgid "Sparse Values Buffer View"
@@ -17252,7 +17255,7 @@ msgstr "طبخ (إعداد) خرائط الضوء"
#: modules/gltf/gltf_mesh.cpp
#, fuzzy
msgid "Instance Materials"
-msgstr "تغيرات المادة:"
+msgstr "تغيرات المادة"
#: modules/gltf/gltf_node.cpp scene/3d/skeleton.cpp
msgid "Parent"
@@ -17808,7 +17811,7 @@ msgstr "ضوضاء"
#: modules/opensimplex/noise_texture.cpp
#, fuzzy
msgid "Noise Offset"
-msgstr "مقدار إزاحة الشبكة:"
+msgstr "مقدار إزاحة الشبكة"
#: modules/opensimplex/open_simplex_noise.cpp
msgid "Octaves"
@@ -18363,7 +18366,7 @@ msgstr "اعادة التعيين Ù„Ù„Ø¥ÙØªØ±Ø§Ø¶ÙŠØ§Øª"
#: modules/visual_script/visual_script_func_nodes.cpp
#, fuzzy
msgid "Validate"
-msgstr "الأحر٠الصالحة:"
+msgstr "الأحر٠الصالحة"
#: modules/visual_script/visual_script_func_nodes.cpp
#, fuzzy
@@ -18457,7 +18460,7 @@ msgstr "تغيير حجم المصÙÙˆÙØ©"
#: scene/resources/visual_shader_nodes.cpp
#, fuzzy
msgid "Operator"
-msgstr "Ù…ÙØ´ØºÙ„ التراكم."
+msgstr "Ù…ÙØ´ØºÙ„ التراكم"
#: modules/visual_script/visual_script_nodes.cpp
msgid "Invalid argument of type:"
@@ -18703,7 +18706,7 @@ msgstr "إخلاء سلسلة IK"
#: modules/websocket/websocket_server.cpp
#, fuzzy
msgid "Handshake Timeout"
-msgstr "انتهت المهلة."
+msgstr "انتهت المهلة"
#: modules/webxr/webxr_interface.cpp
#, fuzzy
@@ -18713,12 +18716,12 @@ 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"
@@ -18825,7 +18828,7 @@ msgstr "مسار التصدير"
#: platform/android/export/export_plugin.cpp
#, fuzzy
msgid "Min SDK"
-msgstr "حجم الخطوط:"
+msgstr "حجم الخطوط"
#: platform/android/export/export_plugin.cpp
#, fuzzy
@@ -18883,7 +18886,7 @@ 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
@@ -18893,7 +18896,7 @@ 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"
@@ -18907,7 +18910,7 @@ msgstr "حذ٠العÙقد"
#: platform/android/export/export_plugin.cpp
#, fuzzy
msgid "Graphics"
-msgstr "مقدار إزاحة الشبكة:"
+msgstr "مقدار إزاحة الشبكة"
#: platform/android/export/export_plugin.cpp
#, fuzzy
@@ -18979,7 +18982,7 @@ 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
@@ -19283,7 +19286,7 @@ msgstr ""
msgid ""
"Unable to overwrite res://android/build/res/*.xml files with project name."
msgstr ""
-"تعذرت كتابة overwrite Ù…Ù„ÙØ§Øª res://android/build/res/*.xml مع اسم المشروع"
+"تعذرت كتابة overwrite Ù…Ù„ÙØ§Øª res://android/build/res/*.xml مع اسم المشروع."
#: platform/android/export/export_plugin.cpp
msgid "Could not export project files to gradle project."
@@ -19318,7 +19321,7 @@ msgstr "تعذر نسخ وإعادة تسمية المل٠المصدر، تÙÙ‚
#: platform/android/export/export_plugin.cpp
#, fuzzy
msgid "Package not found: \"%s\"."
-msgstr "لم يتم إيجاد الرسم المتحرك: '%s'"
+msgstr "لم يتم إيجاد الرسم المتحرك: '%s'."
#: platform/android/export/export_plugin.cpp
#, fuzzy
@@ -19347,7 +19350,7 @@ 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..."
@@ -19445,7 +19448,7 @@ msgstr ""
#: platform/iphone/export/export.cpp
#, fuzzy
msgid "Export Method Release"
-msgstr "وضع التصدير:"
+msgstr "وضع التصدير"
#: platform/iphone/export/export.cpp
msgid "Targeted Device Family"
@@ -19458,7 +19461,7 @@ 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
@@ -19488,7 +19491,7 @@ msgstr "الوصول للواي-ÙØ§ÙŠ"
#: platform/iphone/export/export.cpp
#, fuzzy
msgid "Push Notifications"
-msgstr "دوران عشوائي:"
+msgstr "دوران عشوائي"
#: platform/iphone/export/export.cpp
#, fuzzy
@@ -19629,17 +19632,17 @@ msgstr "شغل مل٠HTML Ø§Ù„Ù…ÙØµØ¯Ø± ÙÙŠ Ø§Ù„Ù…ØªØµÙØ­ Ø§Ù„Ø¥ÙØªØ±Ø§Ø¶ÙŠ
#: platform/javascript/export/export.cpp
#, fuzzy
msgid "Could not open template for export: \"%s\"."
-msgstr "لا يمكن ÙØªØ­ القالب من أجل التصدير:"
+msgstr "لا يمكن ÙØªØ­ القالب من أجل التصدير: ."
#: platform/javascript/export/export.cpp
#, fuzzy
msgid "Invalid export template: \"%s\"."
-msgstr "إدارة قوالب التصدير:"
+msgstr "إدارة قوالب التصدير: ."
#: platform/javascript/export/export.cpp
#, fuzzy
msgid "Could not write file: \"%s\"."
-msgstr "لا يمكن كتابة الملÙ:"
+msgstr "لا يمكن كتابة الملÙ: ."
#: platform/javascript/export/export.cpp platform/osx/export/export.cpp
#, fuzzy
@@ -19649,7 +19652,7 @@ msgstr "تحديد الهامش"
#: platform/javascript/export/export.cpp
#, fuzzy
msgid "Could not read file: \"%s\"."
-msgstr "لا يمكن كتابة الملÙ:"
+msgstr "لا يمكن كتابة الملÙ: ."
#: platform/javascript/export/export.cpp
msgid "PWA"
@@ -19658,7 +19661,7 @@ msgstr ""
#: platform/javascript/export/export.cpp
#, fuzzy
msgid "Variant"
-msgstr "Ø§Ù„ØªØ¨Ø§Ø¹ÙØ¯Ø§Øª:"
+msgstr "Ø§Ù„ØªØ¨Ø§Ø¹ÙØ¯Ø§Øª"
#: platform/javascript/export/export.cpp
#, fuzzy
@@ -19732,17 +19735,17 @@ msgstr ""
#: platform/javascript/export/export.cpp
#, fuzzy
msgid "Could not read HTML shell: \"%s\"."
-msgstr "لا يمكن قراءة مل٠HTML مخصص:"
+msgstr "لا يمكن قراءة مل٠HTML مخصص: ."
#: platform/javascript/export/export.cpp
#, fuzzy
msgid "Could not create HTTP server directory: %s."
-msgstr "لا يمكن إنشاء مجلد خادم ال HTTP:"
+msgstr "لا يمكن إنشاء مجلد خادم ال HTTP: ."
#: platform/javascript/export/export.cpp
#, fuzzy
msgid "Error starting HTTP server: %d."
-msgstr "خطأ ÙÙŠ بدء تشغيل خادم HTTP:"
+msgstr "خطأ ÙÙŠ بدء تشغيل خادم HTTP: ."
#: platform/javascript/export/export.cpp
msgid "Web"
@@ -19848,7 +19851,7 @@ msgstr ""
#: platform/osx/export/export.cpp
#, fuzzy
msgid "App Category"
-msgstr "Ø§Ù„ÙØ¦Ø©:"
+msgstr "Ø§Ù„ÙØ¦Ø©"
#: platform/osx/export/export.cpp
msgid "High Res"
@@ -20044,7 +20047,7 @@ msgstr ""
#: platform/osx/export/export.cpp
#, fuzzy
msgid "Could not open icon file \"%s\"."
-msgstr "لم نتمكن من تصدير Ù…Ù„ÙØ§Øª المشروع"
+msgstr "لم نتمكن من تصدير Ù…Ù„ÙØ§Øª المشروع."
#: platform/osx/export/export.cpp
msgid "Could not start xcrun executable."
@@ -20053,7 +20056,7 @@ msgstr "تعذر بدء تشغيل xcrun."
#: platform/osx/export/export.cpp
#, fuzzy
msgid "Notarization failed."
-msgstr "توطين"
+msgstr "توطين."
#: platform/osx/export/export.cpp
msgid "Notarization request UUID: \"%s\""
@@ -20108,7 +20111,7 @@ 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!"
@@ -20139,12 +20142,12 @@ msgstr "ينشئ الصورة المصغرة"
#: platform/osx/export/export.cpp
#, fuzzy
msgid "Could not find template app to export: \"%s\"."
-msgstr "لم يتم إيجاد قالب التطبيق (Template app) للتصدير:"
+msgstr "لم يتم إيجاد قالب التطبيق (Template app) للتصدير: ."
#: platform/osx/export/export.cpp
#, fuzzy
msgid "Invalid export format."
-msgstr "إدارة قوالب التصدير:"
+msgstr "إدارة قوالب التصدير."
#: platform/osx/export/export.cpp
msgid ""
@@ -20331,7 +20334,7 @@ msgstr "إظهار الكل"
#: platform/uwp/export/export.cpp
#, fuzzy
msgid "Short Name"
-msgstr "اسم النص البرمجي:"
+msgstr "اسم النص البرمجي"
#: platform/uwp/export/export.cpp
msgid "Publisher"
@@ -20340,12 +20343,12 @@ 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
@@ -20360,7 +20363,7 @@ msgstr "الإشاراة"
#: platform/uwp/export/export.cpp
#, fuzzy
msgid "Certificate"
-msgstr "القمم:"
+msgstr "القمم"
#: platform/uwp/export/export.cpp
#, fuzzy
@@ -20387,7 +20390,7 @@ msgstr "تحديد التعبير"
#: platform/uwp/export/export.cpp
msgid "Landscape"
-msgstr ""
+msgstr "بشكل اÙقي (Landscape)"
#: platform/uwp/export/export.cpp
#, fuzzy
@@ -20430,7 +20433,7 @@ msgstr ""
#: platform/uwp/export/export.cpp
#, fuzzy
msgid "Splash Screen"
-msgstr "استدعاءات الرسم:"
+msgstr "استدعاءات الرسم"
#: platform/uwp/export/export.cpp
#, fuzzy
@@ -20528,7 +20531,7 @@ msgstr "Ù…Ùنقح الأخطاء"
#: platform/windows/export/export.cpp
#, fuzzy
msgid "Failed to rename temporary file \"%s\"."
-msgstr "لا يمكن حذ٠مل٠مؤقت:"
+msgstr "لا يمكن حذ٠مل٠مؤقت."
#: platform/windows/export/export.cpp
msgid "Identity Type"
@@ -20556,17 +20559,17 @@ msgstr "الإصدار"
#: platform/windows/export/export.cpp
#, fuzzy
msgid "Product Version"
-msgstr "Ù…ÙØ¹Ø±Ù GUID (Ø§Ù„Ù…ÙØ¹Ø±Ù‘Ù Ø§Ù„ÙØ±ÙŠØ¯ العالمي) للمنتج غير صالح:"
+msgstr "Ù…ÙØ¹Ø±Ù GUID (Ø§Ù„Ù…ÙØ¹Ø±Ù‘Ù Ø§Ù„ÙØ±ÙŠØ¯ العالمي) للمنتج غير صالح"
#: 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
@@ -20580,7 +20583,7 @@ msgstr ""
#: platform/windows/export/export.cpp
#, fuzzy
msgid "Resources Modification"
-msgstr "دوران عشوائي:"
+msgstr "دوران عشوائي"
#: platform/windows/export/export.cpp
#, fuzzy
@@ -20617,7 +20620,7 @@ msgstr "لا يمكن العثور على Ù…ÙØªØ§Ø­ المتجر، لا يمكÙ
#: platform/windows/export/export.cpp
#, fuzzy
msgid "Invalid identity type."
-msgstr "Ù…ÙØ­Ø¯Ø¯ غير صالح:"
+msgstr "Ù…ÙØ­Ø¯Ø¯ غير صالح."
#: platform/windows/export/export.cpp
#, fuzzy
@@ -20639,7 +20642,7 @@ msgstr "صيغة غير صالحة."
#: platform/windows/export/export.cpp
#, fuzzy
msgid "Failed to remove temporary file \"%s\"."
-msgstr "لا يمكن حذ٠مل٠مؤقت:"
+msgstr "لا يمكن حذ٠مل٠مؤقت."
#: platform/windows/export/export.cpp
msgid ""
@@ -20690,8 +20693,9 @@ msgid "Osslsigncode"
msgstr ""
#: platform/windows/export/export.cpp
+#, fuzzy
msgid "Wine"
-msgstr ""
+msgstr "طبقة المعالجة Wine"
#: platform/x11/export/export.cpp
msgid "32-bit executables cannot have embedded data >= 4 GiB."
@@ -20828,7 +20832,7 @@ msgstr ""
#: scene/resources/material.cpp
#, fuzzy
msgid "Max Distance"
-msgstr "اختر Ø§Ù„Ù…Ø³Ø§ÙØ©:"
+msgstr "اختر Ø§Ù„Ù…Ø³Ø§ÙØ©"
#: scene/2d/audio_stream_player_2d.cpp scene/3d/light.cpp
#, fuzzy
@@ -20858,13 +20862,13 @@ 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
@@ -20948,12 +20952,12 @@ 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
@@ -21150,7 +21154,7 @@ msgstr ""
#: 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
@@ -21178,7 +21182,7 @@ msgstr ""
#: 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
@@ -21351,7 +21355,7 @@ 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"
@@ -21377,25 +21381,25 @@ msgstr ""
#: 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
@@ -21413,7 +21417,7 @@ msgstr "تقسيم المنحنى"
#: 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
@@ -21612,12 +21616,12 @@ 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"
@@ -21646,7 +21650,7 @@ msgstr ""
#: scene/2d/navigation_2d.cpp scene/3d/navigation.cpp
#, fuzzy
msgid "Edge Connection Margin"
-msgstr "تعديل الإتصال:"
+msgstr "تعديل الإتصال"
#: scene/2d/navigation_2d.cpp
msgid ""
@@ -21663,7 +21667,7 @@ 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"
@@ -21672,7 +21676,7 @@ msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
#, fuzzy
msgid "Path Max Distance"
-msgstr "اختر Ø§Ù„Ù…Ø³Ø§ÙØ©:"
+msgstr "اختر Ø§Ù„Ù…Ø³Ø§ÙØ©"
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
#, fuzzy
@@ -21700,7 +21704,7 @@ msgstr "القلب Ø£Ùقياً"
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
#, fuzzy
msgid "Max Speed"
-msgstr "السرعة:"
+msgstr "السرعة"
#: scene/2d/navigation_agent_2d.cpp
msgid ""
@@ -21744,7 +21748,7 @@ msgstr "Ø§Ù„Ø³ÙØ±"
#: scene/main/canvas_layer.cpp
#, fuzzy
msgid "Rotation Degrees"
-msgstr "ÙŠÙØ¯ÙŠØ± %s من الدرجات."
+msgstr "ÙŠÙØ¯ÙŠØ± %s من الدرجات"
#: scene/2d/node_2d.cpp scene/3d/spatial.cpp
#, fuzzy
@@ -21754,12 +21758,12 @@ msgstr "ثابت"
#: scene/2d/node_2d.cpp
#, fuzzy
msgid "Global Rotation Degrees"
-msgstr "ÙŠÙØ¯ÙŠØ± %s من الدرجات."
+msgstr "ÙŠÙØ¯ÙŠØ± %s من الدرجات"
#: scene/2d/node_2d.cpp
#, fuzzy
msgid "Global Scale"
-msgstr "حجم عشوائي:"
+msgstr "حجم عشوائي"
#: scene/2d/node_2d.cpp scene/3d/spatial.cpp
#, fuzzy
@@ -21779,7 +21783,7 @@ msgstr ""
#: scene/2d/parallax_background.cpp
#, fuzzy
msgid "Base Offset"
-msgstr "Ø§Ù„Ù…ÙØ¹Ø§Ø¯Ù„:"
+msgstr "Ø§Ù„Ù…ÙØ¹Ø§Ø¯Ù„"
#: scene/2d/parallax_background.cpp
#, fuzzy
@@ -21878,17 +21882,17 @@ msgstr ""
#: 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 "Ø§Ù„Ù…ÙØ¹Ø§Ø¯Ù„"
#: scene/2d/path_2d.cpp scene/3d/camera.cpp scene/3d/path.cpp
#, fuzzy
msgid "V Offset"
-msgstr "Ø§Ù„Ù…ÙØ¹Ø§Ø¯Ù„:"
+msgstr "Ø§Ù„Ù…ÙØ¹Ø§Ø¯Ù„"
#: scene/2d/path_2d.cpp scene/3d/path.cpp
msgid "Cubic Interp"
@@ -21951,7 +21955,7 @@ msgstr ""
#: scene/2d/physics_body_2d.cpp
#, fuzzy
msgid "Inertia"
-msgstr "شاقولياً:"
+msgstr "شاقولياً"
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
#, fuzzy
@@ -21990,7 +21994,7 @@ 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"
@@ -22037,7 +22041,7 @@ 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
@@ -22239,7 +22243,7 @@ msgstr "وضع الأولية"
#: scene/2d/tile_map.cpp
#, fuzzy
msgid "Centered Textures"
-msgstr "المزايا الرئيسية:"
+msgstr "المزايا الرئيسية"
#: scene/2d/tile_map.cpp
msgid "Cell Clip UV"
@@ -22371,7 +22375,7 @@ msgstr ""
#: scene/3d/arvr_nodes.cpp servers/arvr_server.cpp
#, fuzzy
msgid "World Scale"
-msgstr "حجم عشوائي:"
+msgstr "حجم عشوائي"
#: scene/3d/audio_stream_player_3d.cpp
#, fuzzy
@@ -22402,7 +22406,7 @@ msgstr "الوان الإنبعاث"
#: scene/3d/audio_stream_player_3d.cpp
#, fuzzy
msgid "Degrees"
-msgstr "ÙŠÙØ¯ÙŠØ± %s من الدرجات."
+msgstr "ÙŠÙØ¯ÙŠØ± %s من الدرجات"
#: scene/3d/audio_stream_player_3d.cpp
#, fuzzy
@@ -22489,7 +22493,7 @@ msgstr ""
#: scene/3d/baked_lightmap.cpp
#, fuzzy
msgid "Use Denoiser"
-msgstr "تصÙية:"
+msgstr "تصÙية"
#: scene/3d/baked_lightmap.cpp scene/resources/texture.cpp
msgid "Use HDR"
@@ -22518,7 +22522,7 @@ msgstr "عام"
#: scene/3d/baked_lightmap.cpp
#, fuzzy
msgid "Max Size"
-msgstr "الحجم:"
+msgstr "الحجم"
#: scene/3d/baked_lightmap.cpp
#, fuzzy
@@ -22528,7 +22532,7 @@ msgstr "قص العÙقد"
#: scene/3d/baked_lightmap.cpp
#, fuzzy
msgid "Custom Sky Rotation Degrees"
-msgstr "ÙŠÙØ¯ÙŠØ± %s من الدرجات."
+msgstr "ÙŠÙØ¯ÙŠØ± %s من الدرجات"
#: scene/3d/baked_lightmap.cpp scene/3d/ray_cast.cpp
#, fuzzy
@@ -22562,7 +22566,7 @@ msgstr "مع البيانات"
#: scene/3d/bone_attachment.cpp scene/3d/physics_body.cpp
#, fuzzy
msgid "Bone Name"
-msgstr "إسم العقدة:"
+msgstr "إسم العقدة"
#: scene/3d/camera.cpp
msgid "Keep Aspect"
@@ -22589,7 +22593,7 @@ msgstr ""
#: scene/3d/camera.cpp
#, fuzzy
msgid "Frustum Offset"
-msgstr "مقدار إزاحة الشبكة:"
+msgstr "مقدار إزاحة الشبكة"
#: scene/3d/camera.cpp
#, fuzzy
@@ -22853,7 +22857,7 @@ msgstr "الخطوط"
#: scene/3d/label_3d.cpp scene/resources/primitive_meshes.cpp
#, fuzzy
msgid "Horizontal Alignment"
-msgstr "عَرضياً:"
+msgstr "عَرضياً"
#: scene/3d/label_3d.cpp
#, fuzzy
@@ -22919,7 +22923,7 @@ msgstr "ÙØµÙ„ المسار"
#: scene/3d/light.cpp
#, fuzzy
msgid "Blend Splits"
-msgstr "أوقات الدمج:"
+msgstr "أوقات الدمج"
#: scene/3d/light.cpp
#, fuzzy
@@ -22965,7 +22969,7 @@ msgstr ""
#: scene/3d/mesh_instance.cpp
#, fuzzy
msgid "Transform Normals"
-msgstr "أجهض التحول."
+msgstr "أجهض التحول"
#: scene/3d/navigation.cpp
msgid ""
@@ -23058,12 +23062,12 @@ msgstr "تشغيل/Ø¥Ø·ÙØ§Ø¡ الوضوحية Visibility"
#: 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."
@@ -23161,7 +23165,7 @@ msgstr ""
#: scene/3d/vehicle_body.cpp
#, fuzzy
msgid "Relaxation"
-msgstr "Ø§Ù„ØªØ¨Ø§Ø¹ÙØ¯Ø§Øª:"
+msgstr "Ø§Ù„ØªØ¨Ø§Ø¹ÙØ¯Ø§Øª"
#: scene/3d/physics_body.cpp
#, fuzzy
@@ -23176,7 +23180,7 @@ msgstr "خطي"
#: scene/3d/physics_body.cpp
#, fuzzy
msgid "Angular Limit Lower"
-msgstr "أقصي أخطاء زواية:"
+msgstr "أقصي أخطاء زواية"
#: scene/3d/physics_body.cpp
#, fuzzy
@@ -23309,7 +23313,7 @@ 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"
@@ -23342,7 +23346,7 @@ msgstr "استثناء العÙقد"
#: scene/3d/physics_joint.cpp
#, fuzzy
msgid "Params"
-msgstr "لقد تم تغيير المَعلم:"
+msgstr "لقد تم تغيير المَعلم"
#: scene/3d/physics_joint.cpp
msgid "Angular Limit"
@@ -23370,7 +23374,7 @@ msgstr "تحريك المسار لليمين"
#: scene/3d/physics_joint.cpp
#, fuzzy
msgid "Max Impulse"
-msgstr "السرعة:"
+msgstr "السرعة"
#: scene/3d/physics_joint.cpp
#, fuzzy
@@ -23380,12 +23384,12 @@ 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
@@ -23418,7 +23422,7 @@ msgstr "رسوم متحركة"
#: scene/3d/physics_joint.cpp
#, fuzzy
msgid "Angular Ortho"
-msgstr "أقصي أخطاء زواية:"
+msgstr "أقصي أخطاء زواية"
#: scene/3d/physics_joint.cpp
#, fuzzy
@@ -23433,7 +23437,7 @@ msgstr "الشروع"
#: scene/3d/physics_joint.cpp
#, fuzzy
msgid "Force Limit"
-msgstr "استدعاءات الرسم:"
+msgstr "استدعاءات الرسم"
#: scene/3d/physics_joint.cpp
#, fuzzy
@@ -23533,7 +23537,7 @@ msgstr ""
#: scene/3d/portal.cpp
#, fuzzy
msgid "Linked Room"
-msgstr "جذر التعديل المباشر:"
+msgstr "جذر التعديل المباشر"
#: scene/3d/portal.cpp
#, fuzzy
@@ -23552,7 +23556,7 @@ msgstr ""
#: scene/3d/proximity_group.cpp
#, fuzzy
msgid "Grid Radius"
-msgstr "نص٠القطر:"
+msgstr "نص٠القطر"
#: scene/3d/ray_cast.cpp
#, fuzzy
@@ -23570,7 +23574,7 @@ msgstr "وضع التحديث"
#: scene/3d/reflection_probe.cpp
#, fuzzy
msgid "Origin Offset"
-msgstr "مقدار إزاحة الشبكة:"
+msgstr "مقدار إزاحة الشبكة"
#: scene/3d/reflection_probe.cpp
#, fuzzy
@@ -23823,12 +23827,12 @@ 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"
@@ -23945,7 +23949,7 @@ msgstr ""
#: scene/3d/vehicle_body.cpp
#, fuzzy
msgid "Use As Traction"
-msgstr "Ø§Ù„ØªØ¨Ø§Ø¹ÙØ¯Ø§Øª:"
+msgstr "Ø§Ù„ØªØ¨Ø§Ø¹ÙØ¯Ø§Øª"
#: scene/3d/vehicle_body.cpp
msgid "Use As Steering"
@@ -23978,6 +23982,16 @@ msgstr "خطأ"
msgid "AABB"
msgstr ""
+#: scene/3d/visual_instance.cpp
+#, fuzzy
+msgid "Sorting"
+msgstr "ترتيب"
+
+#: scene/3d/visual_instance.cpp
+#, fuzzy
+msgid "Use AABB Center"
+msgstr "استخدم Ambient"
+
#: scene/3d/visual_instance.cpp scene/resources/navigation_mesh.cpp
#, fuzzy
msgid "Geometry"
@@ -23991,7 +24005,7 @@ msgstr "يتجاوز"
#: scene/3d/visual_instance.cpp
#, fuzzy
msgid "Material Overlay"
-msgstr "تغيرات المادة:"
+msgstr "تغيرات المادة"
#: scene/3d/visual_instance.cpp
#, fuzzy
@@ -24001,7 +24015,7 @@ msgstr "إنشاء عÙقدة تظليل"
#: scene/3d/visual_instance.cpp
#, fuzzy
msgid "Extra Cull Margin"
-msgstr "وسائط إستدعاء إضاÙية :"
+msgstr "وسائط إستدعاء إضاÙية"
#: scene/3d/visual_instance.cpp
#, fuzzy
@@ -24026,7 +24040,7 @@ msgstr ""
#: scene/resources/material.cpp
#, fuzzy
msgid "Min Distance"
-msgstr "اختر Ø§Ù„Ù…Ø³Ø§ÙØ©:"
+msgstr "اختر Ø§Ù„Ù…Ø³Ø§ÙØ©"
#: scene/3d/visual_instance.cpp
msgid "Min Hysteresis"
@@ -24075,12 +24089,12 @@ msgstr "عقدة الخلط"
#: scene/animation/animation_blend_tree.cpp
#, fuzzy
msgid "Fadein Time"
-msgstr "وقت التلاشي X (ثواني):"
+msgstr "وقت التلاشي X (ثواني)"
#: scene/animation/animation_blend_tree.cpp
#, fuzzy
msgid "Fadeout Time"
-msgstr "وقت التلاشي X (ثواني):"
+msgstr "وقت التلاشي X (ثواني)"
#: scene/animation/animation_blend_tree.cpp
msgid "Auto Restart"
@@ -24097,17 +24111,17 @@ msgstr ""
#: scene/animation/animation_blend_tree.cpp
#, fuzzy
msgid "Random Delay"
-msgstr "إمالة عشوائية:"
+msgstr "إمالة عشوائية"
#: scene/animation/animation_blend_tree.cpp
#, fuzzy
msgid "Add Amount"
-msgstr "الكمية:"
+msgstr "الكمية"
#: scene/animation/animation_blend_tree.cpp
#, fuzzy
msgid "Blend Amount"
-msgstr "الكمية:"
+msgstr "الكمية"
#: scene/animation/animation_blend_tree.cpp
#, fuzzy
@@ -24123,7 +24137,7 @@ msgstr "Ø£Ø¶Ù Ù…Ù†ÙØ° أدخال"
#: scene/animation/animation_node_state_machine.cpp
#, fuzzy
msgid "Xfade Time"
-msgstr "وقت التلاشي X (ثواني):"
+msgstr "وقت التلاشي X (ثواني)"
#: scene/animation/animation_node_state_machine.cpp
#, fuzzy
@@ -24171,7 +24185,7 @@ msgstr "Ø£Ø¶ÙØ© نقطة الرسوم المتحركة"
#: scene/animation/animation_player.cpp
#, fuzzy
msgid "Playback Options"
-msgstr "إعدادات الص٠(Class):"
+msgstr "إعدادات الص٠(Class)"
#: scene/animation/animation_player.cpp
#, fuzzy
@@ -24214,7 +24228,7 @@ msgstr "العÙقدة الرئيسة Ù„Ù…ÙØ´ØºÙ„ الرسومات المتحر
#: scene/animation/animation_tree.cpp
#, fuzzy
msgid "Tree Root"
-msgstr "إنشاء العÙقدة الرئيسة (الجذر):"
+msgstr "إنشاء العÙقدة الرئيسة (الجذر)"
#: scene/animation/animation_tree.cpp
#, fuzzy
@@ -24475,12 +24489,12 @@ msgstr "الاتجاهات"
#: scene/gui/control.cpp scene/resources/navigation_mesh.cpp
#, fuzzy
msgid "Min Size"
-msgstr "حجم الخطوط:"
+msgstr "حجم الخطوط"
#: scene/gui/control.cpp
#, fuzzy
msgid "Pivot Offset"
-msgstr "مقدار إزاحة الشبكة:"
+msgstr "مقدار إزاحة الشبكة"
#: scene/gui/control.cpp
#, fuzzy
@@ -24533,7 +24547,7 @@ msgstr ""
#: scene/gui/control.cpp
#, fuzzy
msgid "Default Cursor Shape"
-msgstr "تحميل نسق المسار Ø§Ù„Ø¥ÙØªØ±Ø§Ø¶ÙŠ."
+msgstr "تحميل نسق المسار Ø§Ù„Ø¥ÙØªØ±Ø§Ø¶ÙŠ"
#: scene/gui/control.cpp
msgid "Pass On Modal Close Click"
@@ -24591,12 +24605,12 @@ msgstr "قطع الاتصال"
#: scene/gui/graph_edit.cpp
#, fuzzy
msgid "Scroll Offset"
-msgstr "مقدار إزاحة الشبكة:"
+msgstr "مقدار إزاحة الشبكة"
#: scene/gui/graph_edit.cpp
#, fuzzy
msgid "Snap Distance"
-msgstr "اختر Ø§Ù„Ù…Ø³Ø§ÙØ©:"
+msgstr "اختر Ø§Ù„Ù…Ø³Ø§ÙØ©"
#: scene/gui/graph_edit.cpp
#, fuzzy
@@ -24696,7 +24710,7 @@ msgstr ""
#: scene/gui/item_list.cpp
#, fuzzy
msgid "Icon Scale"
-msgstr "حجم عشوائي:"
+msgstr "حجم عشوائي"
#: scene/gui/item_list.cpp
#, fuzzy
@@ -24711,7 +24725,7 @@ msgstr "ألحق"
#: scene/gui/label.cpp scene/gui/rich_text_label.cpp
#, fuzzy
msgid "Visible Characters"
-msgstr "الأحر٠الصالحة:"
+msgstr "الأحر٠الصالحة"
#: scene/gui/label.cpp scene/gui/rich_text_label.cpp
#, fuzzy
@@ -24737,7 +24751,7 @@ msgstr ""
#: scene/gui/line_edit.cpp
#, fuzzy
msgid "Secret Character"
-msgstr "الأحر٠الصالحة:"
+msgstr "الأحر٠الصالحة"
#: scene/gui/line_edit.cpp
msgid "Expand To Text Length"
@@ -24803,7 +24817,7 @@ msgstr ""
#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
#, fuzzy
msgid "Blink Speed"
-msgstr "السرعة:"
+msgstr "السرعة"
#: scene/gui/link_button.cpp
msgid "Underline"
@@ -24887,7 +24901,7 @@ msgstr "بحث"
#: scene/gui/progress_bar.cpp
#, fuzzy
msgid "Percent"
-msgstr "الحالي:"
+msgstr "الحالي"
#: scene/gui/range.cpp
msgid "If \"Exp Edit\" is enabled, \"Min Value\" must be greater than 0."
@@ -24948,7 +24962,7 @@ msgstr "Ù…Ø³Ø§ÙØ© بادئة تلقائية"
#: scene/gui/rich_text_effect.cpp
#, fuzzy
msgid "Elapsed Time"
-msgstr "أوقات الدمج:"
+msgstr "أوقات الدمج"
#: scene/gui/rich_text_effect.cpp
#, fuzzy
@@ -24958,7 +24972,7 @@ msgstr "النهاية"
#: scene/gui/rich_text_effect.cpp
#, fuzzy
msgid "Character"
-msgstr "الأحر٠الصالحة:"
+msgstr "الأحر٠الصالحة"
#: scene/gui/rich_text_label.cpp
msgid "BBCode"
@@ -24971,7 +24985,7 @@ msgstr ""
#: scene/gui/rich_text_label.cpp
#, fuzzy
msgid "Tab Size"
-msgstr "الحجم:"
+msgstr "الحجم"
#: scene/gui/rich_text_label.cpp
#, fuzzy
@@ -24994,7 +25008,7 @@ msgstr "المحدد Ùقط"
#: scene/gui/rich_text_label.cpp scene/gui/text_edit.cpp
#, fuzzy
msgid "Override Selected Font Color"
-msgstr "عدل على الحساب الحالي:"
+msgstr "عدل على الحساب الحالي"
#: scene/gui/rich_text_label.cpp
#, fuzzy
@@ -25024,7 +25038,7 @@ msgstr "تزويد السطح"
#: scene/gui/scroll_container.cpp
#, fuzzy
msgid "Horizontal Enabled"
-msgstr "عَرضياً:"
+msgstr "عَرضياً"
#: scene/gui/scroll_container.cpp
#, fuzzy
@@ -25047,22 +25061,22 @@ msgstr "اختر لوناً"
#: scene/gui/slider.cpp
#, fuzzy
msgid "Ticks On Borders"
-msgstr "إعادة تسمية مجلد:"
+msgstr "إعادة تسمية مجلد"
#: scene/gui/spin_box.cpp
#, fuzzy
msgid "Prefix"
-msgstr "بادئة:"
+msgstr "بادئة"
#: scene/gui/spin_box.cpp
#, fuzzy
msgid "Suffix"
-msgstr "لاحقة:"
+msgstr "لاحقة"
#: scene/gui/split_container.cpp
#, fuzzy
msgid "Split Offset"
-msgstr "مقدار إزاحة الشبكة:"
+msgstr "مقدار إزاحة الشبكة"
#: scene/gui/split_container.cpp scene/gui/tree.cpp
#, fuzzy
@@ -25081,7 +25095,7 @@ msgstr ""
#: scene/gui/tab_container.cpp scene/gui/tabs.cpp
#, fuzzy
msgid "Current Tab"
-msgstr "الحالي:"
+msgstr "الحالي"
#: scene/gui/tab_container.cpp
#, fuzzy
@@ -25095,7 +25109,7 @@ 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"
@@ -25126,7 +25140,7 @@ msgstr "تخطي نقاط التكسّر"
#: scene/gui/text_edit.cpp
#, fuzzy
msgid "Fold Gutter"
-msgstr "مجلد:"
+msgstr "مجلد"
#: scene/gui/text_edit.cpp
#, fuzzy
@@ -25146,17 +25160,17 @@ msgstr "ØªÙØ¹ÙŠÙ„"
#: scene/gui/text_edit.cpp
#, fuzzy
msgid "Scroll Vertical"
-msgstr "شاقولياً:"
+msgstr "شاقولياً"
#: scene/gui/text_edit.cpp
#, fuzzy
msgid "Scroll Horizontal"
-msgstr "عَرضياً:"
+msgstr "عَرضياً"
#: scene/gui/text_edit.cpp
#, fuzzy
msgid "Draw"
-msgstr "استدعاءات الرسم:"
+msgstr "استدعاءات الرسم"
#: scene/gui/text_edit.cpp
#, fuzzy
@@ -25216,7 +25230,7 @@ msgstr ""
#: scene/gui/texture_progress.cpp
#, fuzzy
msgid "Fill Mode"
-msgstr "وضع التشغيل:"
+msgstr "وضع التشغيل"
#: scene/gui/texture_progress.cpp scene/resources/material.cpp
msgid "Tint"
@@ -25234,7 +25248,7 @@ msgstr "الشروع"
#: scene/gui/texture_progress.cpp
#, fuzzy
msgid "Fill Degrees"
-msgstr "ÙŠÙØ¯ÙŠØ± %s من الدرجات."
+msgstr "ÙŠÙØ¯ÙŠØ± %s من الدرجات"
#: scene/gui/texture_progress.cpp scene/resources/primitive_meshes.cpp
#, fuzzy
@@ -25287,7 +25301,7 @@ msgstr "زر معطّل"
#: scene/gui/tree.cpp
#, fuzzy
msgid "Hide Root"
-msgstr "إنشاء العÙقدة الرئيسة (الجذر):"
+msgstr "إنشاء العÙقدة الرئيسة (الجذر)"
#: scene/gui/tree.cpp
msgid "Drop Mode Flags"
@@ -25342,7 +25356,7 @@ msgstr ""
#: scene/main/http_request.cpp
#, fuzzy
msgid "Timeout"
-msgstr "انتهت المهلة."
+msgstr "انتهت المهلة"
#: scene/main/node.cpp
msgid ""
@@ -25387,17 +25401,17 @@ msgstr "إعادة التسمية"
#: scene/main/node.cpp
#, fuzzy
msgid "Owner"
-msgstr "ملاك:"
+msgstr "ملاك"
#: scene/main/node.cpp scene/main/scene_tree.cpp
#, fuzzy
msgid "Multiplayer"
-msgstr "تحديد التكرار:"
+msgstr "تحديد التكرار"
#: scene/main/node.cpp
#, fuzzy
msgid "Custom Multiplayer"
-msgstr "تحديد التكرار:"
+msgstr "تحديد التكرار"
#: scene/main/node.cpp
msgid "Process Priority"
@@ -25434,7 +25448,7 @@ msgstr ""
#: scene/main/scene_tree.cpp
#, fuzzy
msgid "Multiplayer Poll"
-msgstr "تحديد التكرار:"
+msgstr "تحديد التكرار"
#: scene/main/scene_tree.cpp scene/resources/mesh_library.cpp
#: scene/resources/shape_2d.cpp
@@ -25470,12 +25484,12 @@ msgstr "أنشئ الحد"
#: scene/main/scene_tree.cpp servers/visual_server.cpp
msgid "Reflections"
-msgstr "الانعكاسات"
+msgstr "انعكاسات"
#: scene/main/scene_tree.cpp
#, fuzzy
msgid "Atlas Size"
-msgstr "حجم الخطوط:"
+msgstr "حجم الخطوط"
#: scene/main/scene_tree.cpp
msgid "Atlas Subdiv"
@@ -25530,7 +25544,7 @@ msgstr ""
#: scene/main/timer.cpp
#, fuzzy
msgid "Autostart"
-msgstr "إعادة تشغيل تلقائية:"
+msgstr "إعادة تشغيل تلقائية"
#: scene/main/viewport.cpp
#, fuzzy
@@ -25615,7 +25629,7 @@ msgstr "تصحيح الأخطاء"
#: scene/main/viewport.cpp
#, fuzzy
msgid "Render Target"
-msgstr "Ù…ÙØ­Ø±Ùƒ الإخراج البصري:"
+msgstr "Ù…ÙØ­Ø±Ùƒ الإخراج البصري"
#: scene/main/viewport.cpp
msgid "V Flip"
@@ -25736,7 +25750,7 @@ msgstr ""
#: scene/resources/concave_polygon_shape_2d.cpp
#, fuzzy
msgid "Segments"
-msgstr "معاملات المشهد الرئيس:"
+msgstr "معاملات المشهد الرئيس"
#: scene/resources/curve.cpp
#, fuzzy
@@ -25779,7 +25793,7 @@ msgstr "القص Clip Ù…ÙØ¹Ø·Ù‘Ù„"
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
msgid "H Separation"
-msgstr "Ø§Ù„ØªØ¨Ø§Ø¹ÙØ¯Ø§Øª:"
+msgstr "Ø§Ù„ØªØ¨Ø§Ø¹ÙØ¯Ø§Øª"
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
@@ -25849,7 +25863,7 @@ msgstr "عنصر معطّل"
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
msgid "Off"
-msgstr "Ø§Ù„Ù…ÙØ¹Ø§Ø¯Ù„:"
+msgstr "Ø§Ù„Ù…ÙØ¹Ø§Ø¯Ù„"
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
@@ -25869,12 +25883,12 @@ msgstr "الاجبار على التعديل الابيض"
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
msgid "Shadow Offset X"
-msgstr "معادل الشبكة على المحور الأÙقي X:"
+msgstr "معادل الشبكة على المحور الأÙقي X"
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
msgid "Shadow Offset Y"
-msgstr "معادل الشبكة على المحور Y:"
+msgstr "معادل الشبكة على المحور Y"
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
@@ -25934,12 +25948,12 @@ msgstr "المشهد الرئيس"
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
msgid "Folded"
-msgstr "مجلد:"
+msgstr "مجلد"
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
msgid "Fold"
-msgstr "مجلد:"
+msgstr "مجلد"
#: scene/resources/default_theme/default_theme.cpp
msgid "Font Color Readonly"
@@ -26060,12 +26074,12 @@ msgstr "الاتجاهات"
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
msgid "Close H Offset"
-msgstr "مقدار إزاحة الشبكة:"
+msgstr "مقدار إزاحة الشبكة"
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
msgid "Close V Offset"
-msgstr "مقدار إزاحة الشبكة:"
+msgstr "مقدار إزاحة الشبكة"
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
@@ -26095,7 +26109,7 @@ msgstr "ÙØ§ØµÙ„ Ù…ÙØ³Ù…ّى"
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
msgid "Font Separator"
-msgstr "Ù…ÙØ´ØºÙ‘Ù„ اللون."
+msgstr "Ù…ÙØ´ØºÙ‘Ù„ اللون"
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
@@ -26105,12 +26119,12 @@ msgstr "إعادة تسمية عنصر اللون"
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
msgid "Font Color Separator"
-msgstr "Ù…ÙØ´ØºÙ‘Ù„ اللون."
+msgstr "Ù…ÙØ´ØºÙ‘Ù„ اللون"
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
msgid "V Separation"
-msgstr "Ø§Ù„ØªØ¨Ø§Ø¹ÙØ¯Ø§Øª:"
+msgstr "Ø§Ù„ØªØ¨Ø§Ø¹ÙØ¯Ø§Øª"
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
@@ -26155,17 +26169,17 @@ msgstr "الألوان"
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
msgid "Title Offset"
-msgstr "مقدار إزاحة الشبكة:"
+msgstr "مقدار إزاحة الشبكة"
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
msgid "Close Offset"
-msgstr "مقدار إزاحة الشبكة:"
+msgstr "مقدار إزاحة الشبكة"
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
msgid "Port Offset"
-msgstr "مقدار إزاحة الشبكة:"
+msgstr "مقدار إزاحة الشبكة"
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
@@ -26277,12 +26291,12 @@ msgstr "أظهر الموجهات"
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
msgid "Scroll Border"
-msgstr "شاقولياً:"
+msgstr "شاقولياً"
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
msgid "Scroll Speed"
-msgstr "مقدار إزاحة الشبكة:"
+msgstr "مقدار إزاحة الشبكة"
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
@@ -26292,7 +26306,7 @@ msgstr "تحديد الهامش"
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
msgid "Line Separation"
-msgstr "Ø§Ù„ØªØ¨Ø§Ø¹ÙØ¯Ø§Øª:"
+msgstr "Ø§Ù„ØªØ¨Ø§Ø¹ÙØ¯Ø§Øª"
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
@@ -26354,7 +26368,7 @@ msgstr "الهدÙ"
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
msgid "Folder"
-msgstr "مجلد:"
+msgstr "مجلد"
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
@@ -26394,7 +26408,7 @@ msgstr "بالعرض يساراً"
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
msgid "Screen Picker"
-msgstr "Ù…ÙØ´ØºÙ„ الشاشة."
+msgstr "Ù…ÙØ´ØºÙ„ الشاشة"
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
@@ -26457,12 +26471,12 @@ msgstr "المشهد الرئيس"
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
msgid "Table H Separation"
-msgstr "Ø§Ù„ØªØ¨Ø§Ø¹ÙØ¯Ø§Øª:"
+msgstr "Ø§Ù„ØªØ¨Ø§Ø¹ÙØ¯Ø§Øª"
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
msgid "Table V Separation"
-msgstr "Ø§Ù„ØªØ¨Ø§Ø¹ÙØ¯Ø§Øª:"
+msgstr "Ø§Ù„ØªØ¨Ø§Ø¹ÙØ¯Ø§Øª"
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
@@ -26557,7 +26571,7 @@ msgstr "مسار التركيز"
#: scene/resources/dynamic_font.cpp
#, fuzzy
msgid "Outline Size"
-msgstr "حجم الخطوط:"
+msgstr "حجم الخطوط"
#: scene/resources/dynamic_font.cpp
#, fuzzy
@@ -26572,12 +26586,12 @@ msgstr "الإشارات"
#: scene/resources/dynamic_font.cpp
#, fuzzy
msgid "Extra Spacing"
-msgstr "خيارات إضاÙية:"
+msgstr "خيارات إضاÙية"
#: scene/resources/dynamic_font.cpp
#, fuzzy
msgid "Char"
-msgstr "الأحر٠الصالحة:"
+msgstr "الأحر٠الصالحة"
#: scene/resources/dynamic_font.cpp
#, fuzzy
@@ -26605,12 +26619,12 @@ msgstr "الوثائق الإلكترونية"
#: scene/resources/environment.cpp
#, fuzzy
msgid "Sky Rotation"
-msgstr "خطوة الدوران:"
+msgstr "خطوة الدوران"
#: scene/resources/environment.cpp
#, fuzzy
msgid "Sky Rotation Degrees"
-msgstr "ÙŠÙØ¯ÙŠØ± %s من الدرجات."
+msgstr "ÙŠÙØ¯ÙŠØ± %s من الدرجات"
#: scene/resources/environment.cpp
msgid "Canvas Max Layer"
@@ -26637,12 +26651,12 @@ msgstr ""
#: scene/resources/environment.cpp
#, fuzzy
msgid "Sun Color"
-msgstr "تخزين الملÙ:"
+msgstr "تخزين الملÙ"
#: scene/resources/environment.cpp
#, fuzzy
msgid "Sun Amount"
-msgstr "الكمية:"
+msgstr "الكمية"
#: scene/resources/environment.cpp
#, fuzzy
@@ -26733,12 +26747,12 @@ msgstr "الخطوة"
#: scene/resources/environment.cpp
#, fuzzy
msgid "Fade In"
-msgstr "تلاشي ÙÙŠ البداية (ثواني):"
+msgstr "تلاشي ÙÙŠ البداية (ثواني)"
#: scene/resources/environment.cpp
#, fuzzy
msgid "Fade Out"
-msgstr "تلاشي من النهاية (ثواني):"
+msgstr "تلاشي من النهاية (ثواني)"
#: scene/resources/environment.cpp
#, fuzzy
@@ -26756,7 +26770,7 @@ msgstr ""
#: scene/resources/environment.cpp
#, fuzzy
msgid "Radius 2"
-msgstr "نص٠القطر:"
+msgstr "نص٠القطر"
#: scene/resources/environment.cpp
msgid "Intensity 2"
@@ -26787,7 +26801,7 @@ msgstr ""
#: scene/resources/environment.cpp scene/resources/material.cpp
#, fuzzy
msgid "Distance"
-msgstr "اختر Ø§Ù„Ù…Ø³Ø§ÙØ©:"
+msgstr "اختر Ø§Ù„Ù…Ø³Ø§ÙØ©"
#: scene/resources/environment.cpp
msgid "Transition"
@@ -26871,17 +26885,17 @@ msgstr "ضوء"
#: scene/resources/environment.cpp
#, fuzzy
msgid "Saturation"
-msgstr "Ø§Ù„ØªØ¨Ø§Ø¹ÙØ¯Ø§Øª:"
+msgstr "Ø§Ù„ØªØ¨Ø§Ø¹ÙØ¯Ø§Øª"
#: scene/resources/environment.cpp
#, fuzzy
msgid "Color Correction"
-msgstr "Ø§Ù„ÙˆØ¸ÙŠÙØ© البرمجية للون."
+msgstr "Ø§Ù„ÙˆØ¸ÙŠÙØ© البرمجية للون"
#: scene/resources/font.cpp
#, fuzzy
msgid "Ascent"
-msgstr "الحالي:"
+msgstr "الحالي"
#: scene/resources/font.cpp
#, fuzzy
@@ -26896,7 +26910,7 @@ msgstr "العمق"
#: scene/resources/gradient.cpp
#, fuzzy
msgid "Offsets"
-msgstr "Ø§Ù„Ù…ÙØ¹Ø§Ø¯Ù„:"
+msgstr "Ø§Ù„Ù…ÙØ¹Ø§Ø¯Ù„"
#: scene/resources/height_map_shape.cpp
msgid "Map Width"
@@ -26960,7 +26974,7 @@ msgstr "Ø§Ù„Ù…Ø³Ø§ÙØ© البادئة يميناً"
#: scene/resources/material.cpp
#, fuzzy
msgid "Ensure Correct Normals"
-msgstr "أجهض التحول."
+msgstr "أجهض التحول"
#: scene/resources/material.cpp
msgid "Albedo Tex MSDF"
@@ -26982,7 +26996,7 @@ msgstr ""
#: scene/resources/material.cpp servers/visual_server.cpp
#, fuzzy
msgid "Parameters"
-msgstr "لقد تم تغيير المَعلم:"
+msgstr "لقد تم تغيير المَعلم"
#: scene/resources/material.cpp
#, fuzzy
@@ -27026,7 +27040,7 @@ msgstr ""
#: scene/resources/material.cpp
#, fuzzy
msgid "Grow Amount"
-msgstr "الكمية:"
+msgstr "الكمية"
#: scene/resources/material.cpp
msgid "Use Alpha Scissor"
@@ -27133,7 +27147,7 @@ msgstr "الإنتقال"
#: scene/resources/material.cpp
#, fuzzy
msgid "Refraction"
-msgstr "Ø§Ù„ØªØ¨Ø§Ø¹ÙØ¯Ø§Øª:"
+msgstr "Ø§Ù„ØªØ¨Ø§Ø¹ÙØ¯Ø§Øª"
#: scene/resources/material.cpp
msgid "Detail"
@@ -27198,12 +27212,12 @@ 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"
@@ -27221,7 +27235,7 @@ msgstr ""
#: scene/resources/navigation_mesh.cpp
#, fuzzy
msgid "Sampling"
-msgstr "تحجيم:"
+msgstr "تحجيم"
#: scene/resources/navigation_mesh.cpp
#, fuzzy
@@ -27231,7 +27245,7 @@ msgstr "حدد نوع المتغير"
#: scene/resources/navigation_mesh.cpp
#, fuzzy
msgid "Parsed Geometry Type"
-msgstr "توزيع الأشكال الهندسية..."
+msgstr "توزيع الأشكال الهندسية"
#: scene/resources/navigation_mesh.cpp
msgid "Source Geometry Mode"
@@ -27249,7 +27263,7 @@ msgstr ""
#: scene/resources/navigation_mesh.cpp
#, fuzzy
msgid "Agents"
-msgstr "معاملات المشهد الرئيس:"
+msgstr "معاملات المشهد الرئيس"
#: scene/resources/navigation_mesh.cpp
msgid "Max Climb"
@@ -27290,7 +27304,7 @@ msgstr "أظهر Ø§Ù„Ø¥ÙØªØ±Ø§Ø¶ÙŠ"
#: scene/resources/navigation_mesh.cpp
#, fuzzy
msgid "Sample Distance"
-msgstr "اختر Ø§Ù„Ù…Ø³Ø§ÙØ©:"
+msgstr "اختر Ø§Ù„Ù…Ø³Ø§ÙØ©"
#: scene/resources/navigation_mesh.cpp
#, fuzzy
@@ -27317,7 +27331,7 @@ msgstr "توليد AABB"
#: scene/resources/navigation_mesh.cpp
#, fuzzy
msgid "Baking AABB Offset"
-msgstr "Ø§Ù„Ù…ÙØ¹Ø§Ø¯Ù„:"
+msgstr "Ø§Ù„Ù…ÙØ¹Ø§Ø¯Ù„"
#: scene/resources/occluder_shape.cpp
msgid "Spheres"
@@ -27362,7 +27376,7 @@ msgstr "Ù…ÙØ¹Ø¯Ù‘Ù„ تباطؤ الرؤية Ø§Ù„Ø­ÙØ±Ø©"
#: scene/resources/particles_material.cpp
#, fuzzy
msgid "Point Texture"
-msgstr "نقاط الانبعاث:"
+msgstr "نقاط الانبعاث"
#: scene/resources/particles_material.cpp
msgid "Normal Texture"
@@ -27381,7 +27395,7 @@ msgstr "Ø£Ø¶Ù Ù…Ù†ÙØ° أدخال"
#: scene/resources/particles_material.cpp
#, fuzzy
msgid "Scale Random"
-msgstr "نسبة التكبير:"
+msgstr "نسبة التكبير"
#: scene/resources/particles_material.cpp
#, fuzzy
@@ -27399,7 +27413,7 @@ msgstr ""
#: scene/resources/plane_shape.cpp
#, fuzzy
msgid "Plane"
-msgstr "التبويت:"
+msgstr "التبويت"
#: scene/resources/primitive_meshes.cpp
#, fuzzy
@@ -27425,7 +27439,7 @@ msgstr ""
#: scene/resources/primitive_meshes.cpp
#, fuzzy
msgid "Top Radius"
-msgstr "نص٠القطر:"
+msgstr "نص٠القطر"
#: scene/resources/primitive_meshes.cpp
#, fuzzy
@@ -27476,7 +27490,7 @@ msgstr "العظام"
#: scene/resources/sky.cpp
#, fuzzy
msgid "Radiance Size"
-msgstr "حجم الخطوط:"
+msgstr "حجم الخطوط"
#: scene/resources/sky.cpp
msgid "Panorama"
@@ -27490,7 +27504,7 @@ msgstr "الطابق التالي"
#: scene/resources/sky.cpp
#, fuzzy
msgid "Horizon Color"
-msgstr "تخزين الملÙ:"
+msgstr "تخزين الملÙ"
#: scene/resources/sky.cpp
#, fuzzy
@@ -27601,7 +27615,7 @@ msgstr "التقاط"
#: scene/resources/texture.cpp
#, fuzzy
msgid "From"
-msgstr "وضع التشغيل:"
+msgstr "وضع التشغيل"
#: scene/resources/texture.cpp
#, fuzzy
@@ -27769,7 +27783,7 @@ msgstr "أختبار"
#: scene/resources/world.cpp scene/resources/world_2d.cpp
#, fuzzy
msgid "Default Edge Connection Margin"
-msgstr "تعديل الإتصال:"
+msgstr "تعديل الإتصال"
#: scene/resources/world_2d.cpp
msgid "Canvas"
@@ -27805,7 +27819,7 @@ msgstr "عنصر Ø®Ùيار"
#: servers/audio/audio_stream.cpp
#, fuzzy
msgid "Random Pitch"
-msgstr "إمالة عشوائية:"
+msgstr "إمالة عشوائية"
#: servers/audio/effects/audio_effect_capture.cpp
#: servers/audio/effects/audio_effect_spectrum_analyzer.cpp
@@ -27857,7 +27871,7 @@ msgstr ""
#: servers/audio/effects/audio_effect_panner.cpp
#, fuzzy
msgid "Pan"
-msgstr "التبويت:"
+msgstr "التبويت"
#: servers/audio/effects/audio_effect_compressor.cpp
#: servers/audio/effects/audio_effect_filter.cpp
@@ -27955,7 +27969,7 @@ msgstr ""
#: servers/audio/effects/audio_effect_spectrum_analyzer.cpp
#, fuzzy
msgid "FFT Size"
-msgstr "الحجم:"
+msgstr "الحجم"
#: servers/audio/effects/audio_effect_reverb.cpp
msgid "Predelay"
@@ -27985,7 +27999,7 @@ 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"
@@ -28053,7 +28067,7 @@ msgstr ""
#: servers/physics_2d/physics_2d_server_sw.cpp
#, fuzzy
msgid "BP Hash Table Size"
-msgstr "الحجم:"
+msgstr "الحجم"
#: servers/physics_2d/physics_2d_server_sw.cpp
msgid "Large Object Surface Threshold In Cells"
@@ -28179,7 +28193,7 @@ msgstr "لا يمكن تعديل الثوابت."
#: servers/visual/visual_server_scene.cpp
#, fuzzy
msgid "Spatial Partitioning"
-msgstr "تجزئة..."
+msgstr "تجزئة"
#: servers/visual_server.cpp
#, fuzzy
@@ -28369,7 +28383,7 @@ msgstr ""
#: servers/visual_server.cpp
#, fuzzy
msgid "Batching"
-msgstr "جاري البحث..."
+msgstr "جاري البحث"
#: servers/visual_server.cpp
msgid "Use Batching"
@@ -28399,7 +28413,7 @@ msgstr ""
#: servers/visual_server.cpp
#, fuzzy
msgid "Max Join Items"
-msgstr "إدارة العناصر..."
+msgstr "إدارة العناصر"
#: servers/visual_server.cpp
msgid "Batch Buffer Size"
diff --git a/editor/translations/az.po b/editor/translations/az.po
index d4ffe0665e..b6b36d99e5 100644
--- a/editor/translations/az.po
+++ b/editor/translations/az.po
@@ -12593,9 +12593,10 @@ msgstr "Yapışdır(Snap):"
#: scene/2d/path_2d.cpp scene/2d/polygon_2d.cpp scene/2d/sprite.cpp
#: scene/3d/cpu_particles.cpp scene/3d/label_3d.cpp scene/3d/path.cpp
#: scene/3d/physics_body.cpp scene/3d/soft_body.cpp scene/3d/sprite_3d.cpp
-#: 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
+#: scene/3d/visual_instance.cpp 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
msgid "Offset"
msgstr ""
@@ -13952,12 +13953,11 @@ msgstr ""
#: editor/project_manager.cpp
msgid ""
-"Couldn't load project.godot in project path (error %d). It may be missing or "
-"corrupted."
+"Couldn't load project at '%s' (error %d). It may be missing or corrupted."
msgstr ""
#: editor/project_manager.cpp
-msgid "Couldn't edit project.godot in project path."
+msgid "Couldn't save project at '%s' (error %d)."
msgstr ""
#: editor/project_manager.cpp
@@ -22688,6 +22688,15 @@ msgstr "Maks. Xətti Xəta:"
msgid "AABB"
msgstr ""
+#: scene/3d/visual_instance.cpp
+#, fuzzy
+msgid "Sorting"
+msgstr "İnterpolasiya rejimi"
+
+#: scene/3d/visual_instance.cpp
+msgid "Use AABB Center"
+msgstr ""
+
#: scene/3d/visual_instance.cpp scene/resources/navigation_mesh.cpp
msgid "Geometry"
msgstr ""
diff --git a/editor/translations/bg.po b/editor/translations/bg.po
index a6a8b72ea5..262a6825a6 100644
--- a/editor/translations/bg.po
+++ b/editor/translations/bg.po
@@ -17,13 +17,14 @@
# Ivan Gechev <ivan_banov@abv.bg>, 2022.
# BigHomieDripDrop <bartu.bali@gmail.com>, 2022.
# xaio <xaio666@gmail.com>, 2022.
+# Vosh <vosh4k@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-09-22 15:26+0000\n"
-"Last-Translator: xaio <xaio666@gmail.com>\n"
+"PO-Revision-Date: 2022-10-25 15:43+0000\n"
+"Last-Translator: Vosh <vosh4k@gmail.com>\n"
"Language-Team: Bulgarian <https://hosted.weblate.org/projects/godot-engine/"
"godot/bg/>\n"
"Language: bg\n"
@@ -31,7 +32,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.14.1\n"
+"X-Generator: Weblate 4.14.2-dev\n"
#: core/bind/core_bind.cpp main/main.cpp
msgid "Tablet Driver"
@@ -437,19 +438,16 @@ msgid "Button Mask"
msgstr "Бутон"
#: core/os/input_event.cpp scene/2d/node_2d.cpp scene/gui/control.cpp
-#, fuzzy
msgid "Global Position"
-msgstr "Глобална конÑтанта"
+msgstr "Глобална позициÑ"
#: core/os/input_event.cpp
-#, fuzzy
msgid "Factor"
-msgstr "Вектор"
+msgstr "Фактор"
#: core/os/input_event.cpp
-#, fuzzy
msgid "Button Index"
-msgstr "Бутон"
+msgstr "Ð˜Ð½Ð´ÐµÐºÑ Ð½Ð° бутона"
#: core/os/input_event.cpp
msgid "Doubleclick"
@@ -485,9 +483,8 @@ msgid "Axis"
msgstr "ОÑ"
#: core/os/input_event.cpp
-#, fuzzy
msgid "Axis Value"
-msgstr "Закачане на ÑтойноÑтта"
+msgstr "СтойноÑÑ‚ на оÑта"
#: core/os/input_event.cpp modules/visual_script/visual_script_func_nodes.cpp
#, fuzzy
@@ -510,14 +507,12 @@ msgid "Delta"
msgstr "Делта"
#: core/os/input_event.cpp
-#, fuzzy
msgid "Channel"
-msgstr "ПромÑна на филтъра"
+msgstr "Канал"
#: core/os/input_event.cpp main/main.cpp
-#, fuzzy
msgid "Message"
-msgstr "Съобщение за подаването"
+msgstr "Съобщение"
#: core/os/input_event.cpp
#, fuzzy
@@ -527,9 +522,8 @@ msgstr "Скалиране"
#: core/os/input_event.cpp scene/2d/cpu_particles_2d.cpp
#: scene/2d/physics_body_2d.cpp scene/3d/cpu_particles.cpp
#: scene/3d/physics_body.cpp scene/resources/particles_material.cpp
-#, fuzzy
msgid "Velocity"
-msgstr "Орбитален изглед отдÑÑно"
+msgstr "СкороÑÑ‚"
#: core/os/input_event.cpp
msgid "Instrument"
@@ -547,14 +541,12 @@ 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 "ДейÑтвие"
+msgstr "Приложение"
#: core/project_settings.cpp main/main.cpp
-#, fuzzy
msgid "Config"
-msgstr "ÐаÑтройване на прилепването"
+msgstr "КонфигурациÑ"
#: core/project_settings.cpp
#, fuzzy
@@ -617,9 +609,8 @@ 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
@@ -669,9 +660,8 @@ msgid "Main Run Args"
msgstr ""
#: core/project_settings.cpp
-#, fuzzy
msgid "Scene Naming"
-msgstr "Път на Ñцената:"
+msgstr "Ðаименование на Ñцена"
#: core/project_settings.cpp
msgid "Search In File Extensions"
@@ -682,9 +672,8 @@ msgid "Script Templates Search Path"
msgstr "Път за търÑене на Ñкриптови шаблони"
#: core/project_settings.cpp
-#, fuzzy
msgid "Version Control Autoload On Startup"
-msgstr "Контрол на верÑиите"
+msgstr "Стартирай контрол на верÑиите при Ñтартиране"
#: core/project_settings.cpp
#, fuzzy
@@ -1053,7 +1042,7 @@ msgstr "Скалиране"
#: drivers/gles3/rasterizer_scene_gles3.cpp
msgid "Follow Surface"
-msgstr ""
+msgstr "Следвай повърхноÑÑ‚"
#: drivers/gles3/rasterizer_scene_gles3.cpp
msgid "Weight Samples"
@@ -1143,9 +1132,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
@@ -1156,9 +1144,8 @@ 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
@@ -1339,19 +1326,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
@@ -1646,7 +1630,7 @@ msgstr ""
#: editor/animation_track_editor.cpp
#: modules/visual_script/visual_script_editor.cpp
msgid "Clipboard is empty!"
-msgstr ""
+msgstr "Клипбордът е празен!"
#: editor/animation_track_editor.cpp
msgid "Paste Tracks"
@@ -12795,9 +12779,10 @@ msgstr "ÐаÑтройки за прилепването"
#: scene/2d/path_2d.cpp scene/2d/polygon_2d.cpp scene/2d/sprite.cpp
#: scene/3d/cpu_particles.cpp scene/3d/label_3d.cpp scene/3d/path.cpp
#: scene/3d/physics_body.cpp scene/3d/soft_body.cpp scene/3d/sprite_3d.cpp
-#: 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
+#: scene/3d/visual_instance.cpp 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 "ОтмеÑтване:"
@@ -14158,16 +14143,17 @@ msgid "Invalid project path (changed anything?)."
msgstr "Ðеправилен път до проекта (ПроменÑли ли Ñте нещо?)."
#: editor/project_manager.cpp
+#, fuzzy
msgid ""
-"Couldn't load project.godot in project path (error %d). It may be missing or "
-"corrupted."
+"Couldn't load project at '%s' (error %d). It may be missing or corrupted."
msgstr ""
"Файлът „project.godot“ не може да бъде зареден от Ð¿ÑŠÑ‚Ñ Ð½Ð° проекта (грешка "
"%d). Възможно е той да липÑва или да е повреден."
#: editor/project_manager.cpp
-msgid "Couldn't edit project.godot in project path."
-msgstr ""
+#, fuzzy
+msgid "Couldn't save project at '%s' (error %d)."
+msgstr "Ðе може да бъде отворен проектът в „%s“."
#: editor/project_manager.cpp
msgid "Couldn't create project.godot in project path."
@@ -23350,6 +23336,15 @@ msgstr "Грешка от %s"
msgid "AABB"
msgstr ""
+#: scene/3d/visual_instance.cpp
+#, fuzzy
+msgid "Sorting"
+msgstr "Сортиране"
+
+#: scene/3d/visual_instance.cpp
+msgid "Use AABB Center"
+msgstr ""
+
#: scene/3d/visual_instance.cpp scene/resources/navigation_mesh.cpp
#, fuzzy
msgid "Geometry"
diff --git a/editor/translations/bn.po b/editor/translations/bn.po
index f32a090f27..df79cd5d84 100644
--- a/editor/translations/bn.po
+++ b/editor/translations/bn.po
@@ -13807,9 +13807,10 @@ msgstr "অà§à¦¯à¦¾à¦¨à¦¿à¦®à§‡à¦¶à¦¨à§‡à¦° সিদà§à¦§à¦¾à¦¨à§à¦¤à¦¸à¦®à§
#: scene/2d/path_2d.cpp scene/2d/polygon_2d.cpp scene/2d/sprite.cpp
#: scene/3d/cpu_particles.cpp scene/3d/label_3d.cpp scene/3d/path.cpp
#: scene/3d/physics_body.cpp scene/3d/soft_body.cpp scene/3d/sprite_3d.cpp
-#: 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
+#: scene/3d/visual_instance.cpp 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 "অফসেট/ভারসামà§à¦¯:"
@@ -15277,14 +15278,13 @@ msgstr "অকারà§à¦¯à¦•র পà§à¦°à¦•লà§à¦ªà§‡à¦° পথ (কোনà§
#: editor/project_manager.cpp
#, fuzzy
msgid ""
-"Couldn't load project.godot in project path (error %d). It may be missing or "
-"corrupted."
+"Couldn't load project at '%s' (error %d). It may be missing or corrupted."
msgstr "পà§à¦°à¦•লà§à¦ªà§‡à¦° পথে engine.cfg তৈরি করা সমà§à¦­à¦¬ হয়নি।"
#: editor/project_manager.cpp
#, fuzzy
-msgid "Couldn't edit project.godot in project path."
-msgstr "পà§à¦°à¦•লà§à¦ªà§‡à¦° পথে engine.cfg তৈরি করা সমà§à¦­à¦¬ হয়নি।"
+msgid "Couldn't save project at '%s' (error %d)."
+msgstr "সংযোগ..."
#: editor/project_manager.cpp
#, fuzzy
@@ -24888,6 +24888,15 @@ msgstr "সমসà§à¦¯à¦¾/ভà§à¦²"
msgid "AABB"
msgstr ""
+#: scene/3d/visual_instance.cpp
+#, fuzzy
+msgid "Sorting"
+msgstr "সাজান:"
+
+#: scene/3d/visual_instance.cpp
+msgid "Use AABB Center"
+msgstr ""
+
#: scene/3d/visual_instance.cpp scene/resources/navigation_mesh.cpp
#, fuzzy
msgid "Geometry"
diff --git a/editor/translations/br.po b/editor/translations/br.po
index 7b92059104..0cfc29b4d1 100644
--- a/editor/translations/br.po
+++ b/editor/translations/br.po
@@ -12459,9 +12459,10 @@ msgstr "Tro Fiñvskeudenn"
#: scene/2d/path_2d.cpp scene/2d/polygon_2d.cpp scene/2d/sprite.cpp
#: scene/3d/cpu_particles.cpp scene/3d/label_3d.cpp scene/3d/path.cpp
#: scene/3d/physics_body.cpp scene/3d/soft_body.cpp scene/3d/sprite_3d.cpp
-#: 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
+#: scene/3d/visual_instance.cpp 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
msgid "Offset"
msgstr ""
@@ -13803,12 +13804,11 @@ msgstr ""
#: editor/project_manager.cpp
msgid ""
-"Couldn't load project.godot in project path (error %d). It may be missing or "
-"corrupted."
+"Couldn't load project at '%s' (error %d). It may be missing or corrupted."
msgstr ""
#: editor/project_manager.cpp
-msgid "Couldn't edit project.godot in project path."
+msgid "Couldn't save project at '%s' (error %d)."
msgstr ""
#: editor/project_manager.cpp
@@ -22459,6 +22459,15 @@ msgstr "Melezour"
msgid "AABB"
msgstr ""
+#: scene/3d/visual_instance.cpp
+#, fuzzy
+msgid "Sorting"
+msgstr "Mod Interpoladur"
+
+#: scene/3d/visual_instance.cpp
+msgid "Use AABB Center"
+msgstr ""
+
#: scene/3d/visual_instance.cpp scene/resources/navigation_mesh.cpp
msgid "Geometry"
msgstr ""
diff --git a/editor/translations/ca.po b/editor/translations/ca.po
index b08b3be823..d3ced0a876 100644
--- a/editor/translations/ca.po
+++ b/editor/translations/ca.po
@@ -13232,9 +13232,10 @@ msgstr "Opcions d'Ajustament"
#: scene/2d/path_2d.cpp scene/2d/polygon_2d.cpp scene/2d/sprite.cpp
#: scene/3d/cpu_particles.cpp scene/3d/label_3d.cpp scene/3d/path.cpp
#: scene/3d/physics_body.cpp scene/3d/soft_body.cpp scene/3d/sprite_3d.cpp
-#: 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
+#: scene/3d/visual_instance.cpp 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 "òfset:"
@@ -14752,16 +14753,17 @@ msgid "Invalid project path (changed anything?)."
msgstr "El Camí del Projecte no és vàlid (S'ha produit algun canvi?)."
#: editor/project_manager.cpp
+#, fuzzy
msgid ""
-"Couldn't load project.godot in project path (error %d). It may be missing or "
-"corrupted."
+"Couldn't load project at '%s' (error %d). It may be missing or corrupted."
msgstr ""
"No es pot carregar el fitxer 'project.godot' en el camí del projecte (error "
"%d). Pot ser que falti o que estigui malmès."
#: editor/project_manager.cpp
-msgid "Couldn't edit project.godot in project path."
-msgstr "No es pot editar el fitxer 'project.godot' en el camí del projecte."
+#, fuzzy
+msgid "Couldn't save project at '%s' (error %d)."
+msgstr "No es pot obrir el projecte a '%s'."
#: editor/project_manager.cpp
msgid "Couldn't create project.godot in project path."
@@ -24377,6 +24379,15 @@ msgstr "Error"
msgid "AABB"
msgstr ""
+#: scene/3d/visual_instance.cpp
+#, fuzzy
+msgid "Sorting"
+msgstr "Ordena"
+
+#: scene/3d/visual_instance.cpp
+msgid "Use AABB Center"
+msgstr ""
+
#: scene/3d/visual_instance.cpp scene/resources/navigation_mesh.cpp
#, fuzzy
msgid "Geometry"
diff --git a/editor/translations/cs.po b/editor/translations/cs.po
index 01c28b207e..173d38c85c 100644
--- a/editor/translations/cs.po
+++ b/editor/translations/cs.po
@@ -32,13 +32,14 @@
# JoeMoos <josephmoose13@gmail.com>, 2022.
# Mirinek <mirek.nozicka77@gmail.com>, 2022.
# Lubomír Baloun <lubosbaloun@gmail.com>, 2022.
+# Ondřej Pavelka <flamekick97@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-09-19 05:22+0000\n"
-"Last-Translator: Lubomír Baloun <lubosbaloun@gmail.com>\n"
+"PO-Revision-Date: 2022-12-12 09:46+0000\n"
+"Last-Translator: Ondřej Pavelka <flamekick97@gmail.com>\n"
"Language-Team: Czech <https://hosted.weblate.org/projects/godot-engine/godot/"
"cs/>\n"
"Language: cs\n"
@@ -46,11 +47,11 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
-"X-Generator: Weblate 4.14.1\n"
+"X-Generator: Weblate 4.15-dev\n"
#: core/bind/core_bind.cpp main/main.cpp
msgid "Tablet Driver"
-msgstr "OvladaÄ Grafického Tabletu"
+msgstr "OvladaÄe grafického tabletu"
#: core/bind/core_bind.cpp
msgid "Clipboard"
@@ -65,9 +66,8 @@ msgid "Exit Code"
msgstr "Kód pro ukonÄení (exit code)"
#: core/bind/core_bind.cpp
-#, fuzzy
msgid "V-Sync Enabled"
-msgstr "V-Sync Zapnutý"
+msgstr "V-Sync zapnutý"
#: core/bind/core_bind.cpp main/main.cpp
msgid "V-Sync Via Compositor"
@@ -93,22 +93,20 @@ msgstr "Nechat ladící program otevřený"
#: core/bind/core_bind.cpp
msgid "Min Window Size"
-msgstr "Minimální Velikost Okna"
+msgstr "Minimální velikost okna"
#: core/bind/core_bind.cpp
msgid "Max Window Size"
-msgstr "Maximální Velikost Okna"
+msgstr "Maximální velikost okna"
#: core/bind/core_bind.cpp
-#, fuzzy
msgid "Screen Orientation"
-msgstr "Operátor screen."
+msgstr "Orientace obrazovky"
#: core/bind/core_bind.cpp core/project_settings.cpp main/main.cpp
#: platform/uwp/os_uwp.cpp
-#, fuzzy
msgid "Window"
-msgstr "Nové okno"
+msgstr "Okno"
#: core/bind/core_bind.cpp core/project_settings.cpp
#, fuzzy
@@ -127,7 +125,7 @@ msgstr "Přepnout celou obrazovku"
#: core/bind/core_bind.cpp
msgid "Maximized"
-msgstr ""
+msgstr "Maximalizováno"
#: core/bind/core_bind.cpp
#, fuzzy
@@ -224,7 +222,7 @@ msgstr "Paměť"
#: modules/webrtc/webrtc_data_channel.h modules/websocket/websocket_macros.h
#: servers/visual_server.cpp
msgid "Limits"
-msgstr ""
+msgstr "Limity"
#: core/command_queue_mt.cpp
#, fuzzy
@@ -284,9 +282,8 @@ msgid "Read Chunk Size"
msgstr ""
#: core/io/marshalls.cpp
-#, fuzzy
msgid "Object ID"
-msgstr "Kreslené objekty:"
+msgstr "ID Objektu"
#: core/io/multiplayer_api.cpp core/io/packet_peer.cpp
#, fuzzy
@@ -407,7 +404,7 @@ msgstr "Status"
#: core/message_queue.cpp
msgid "Message Queue"
-msgstr ""
+msgstr "Fronta zpráv"
#: core/message_queue.cpp
msgid "Max Size (KB)"
@@ -445,7 +442,7 @@ msgstr "Správa verzí"
#: core/os/input_event.cpp
msgid "Meta"
-msgstr ""
+msgstr "Meta"
#: core/os/input_event.cpp
#, fuzzy
@@ -519,7 +516,7 @@ msgstr "Profil"
#: core/os/input_event.cpp
msgid "Pen Inverted"
-msgstr ""
+msgstr "Tužka invertována"
#: core/os/input_event.cpp
#, fuzzy
@@ -589,7 +586,7 @@ msgstr "Inicializovat"
#: core/os/input_event.cpp
msgid "Instrument"
-msgstr ""
+msgstr "Nástroj"
#: core/os/input_event.cpp
#, fuzzy
@@ -663,8 +660,9 @@ msgid "Use Hidden Project Data Directory"
msgstr ""
#: core/project_settings.cpp
+#, fuzzy
msgid "Use Custom User Dir"
-msgstr ""
+msgstr "Použít vlastní uživatelské dir"
#: core/project_settings.cpp
msgid "Custom User Dir Name"
@@ -1054,8 +1052,9 @@ msgstr "Vyrovnávací Paměti"
#: drivers/gles2/rasterizer_canvas_base_gles2.cpp
#: drivers/gles3/rasterizer_canvas_base_gles3.cpp
+#, fuzzy
msgid "Canvas Polygon Buffer Size (KB)"
-msgstr ""
+msgstr "Velikost zásobníku polygonového plátna (v KB)"
#: drivers/gles2/rasterizer_canvas_base_gles2.cpp
#: drivers/gles3/rasterizer_canvas_base_gles3.cpp
@@ -1108,7 +1107,7 @@ msgstr ""
#: drivers/gles3/rasterizer_scene_gles3.cpp
msgid "Max Renderable Lights"
-msgstr ""
+msgstr "Maximální poÄet renderovatelných svÄ›tel"
#: drivers/gles3/rasterizer_scene_gles3.cpp
#, fuzzy
@@ -1116,8 +1115,9 @@ msgid "Max Renderable Reflections"
msgstr "Vycentrovat výběr"
#: drivers/gles3/rasterizer_scene_gles3.cpp
+#, fuzzy
msgid "Max Lights Per Object"
-msgstr ""
+msgstr "Maximální poÄet svÄ›tel na objekt"
#: drivers/gles3/rasterizer_scene_gles3.cpp
msgid "Subsurface Scattering"
@@ -1266,7 +1266,7 @@ msgstr "Množství:"
#: 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
@@ -1289,8 +1289,9 @@ msgstr "Nastavit úchyt"
#: 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 "Stream"
#: editor/animation_track_editor.cpp
#, fuzzy
@@ -1577,9 +1578,8 @@ msgstr "Odstranit stopu animace"
#: 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"
+msgstr "Editory"
#: editor/animation_track_editor.cpp editor/editor_settings.cpp
#, fuzzy
@@ -2323,7 +2323,7 @@ msgstr "Otevřít"
#: editor/dependency_editor.cpp
msgid "Owners of: %s (Total: %d)"
-msgstr ""
+msgstr "Vlastníci: %s (Dohromady: %d)"
#: editor/dependency_editor.cpp
msgid ""
@@ -2884,8 +2884,9 @@ msgid "Choose"
msgstr "Vyberte"
#: editor/editor_export.cpp
+#, fuzzy
msgid "Project export for platform:"
-msgstr ""
+msgstr "Exportovat projekt pro platformu:"
#: editor/editor_export.cpp
#, fuzzy
@@ -3015,8 +3016,9 @@ msgid "Binary Format"
msgstr "Operátor barvy."
#: editor/editor_export.cpp
+#, fuzzy
msgid "64 Bits"
-msgstr ""
+msgstr "64 Bitů"
#: editor/editor_export.cpp
msgid "Embed PCK"
@@ -3029,19 +3031,19 @@ msgstr "Oblast textury"
#: 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"
@@ -3090,8 +3092,9 @@ msgid "On 32-bit exports the embedded PCK cannot be bigger than 4 GiB."
msgstr "Při 32-bitovým exportu vestavěné PCK nemůže být větší než 4 GiB."
#: editor/editor_export.cpp
+#, fuzzy
msgid "Convert Text Resources To Binary On Export"
-msgstr ""
+msgstr "Konvertovat textové zdroje do binárky při exportu"
#: editor/editor_feature_profile.cpp
msgid "3D Editor"
@@ -3414,8 +3417,9 @@ msgid "Show Hidden Files"
msgstr "Zobrazit skryté soubory"
#: editor/editor_file_dialog.cpp
+#, fuzzy
msgid "Disable Overwrite Warning"
-msgstr ""
+msgstr "Vypnout varování při přepsání"
#: editor/editor_file_dialog.cpp
msgid "Go Back"
@@ -3517,8 +3521,9 @@ msgid "(Re)Importing Assets"
msgstr "(Re)Importování assetů"
#: editor/editor_file_system.cpp
+#, fuzzy
msgid "Reimport Missing Imported Files"
-msgstr ""
+msgstr "Znovu importovat chybějící importované soubory"
#: editor/editor_help.cpp scene/2d/camera_2d.cpp scene/gui/control.cpp
#: scene/gui/nine_patch_rect.cpp scene/resources/dynamic_font.cpp
@@ -3620,9 +3625,8 @@ msgstr ""
#: editor/plugins/script_text_editor.cpp
#: modules/gdscript/editor/gdscript_highlighter.cpp
#: modules/gdscript/gdscript_editor.cpp
-#, fuzzy
msgid "Text Editor"
-msgstr "Otevřít editor"
+msgstr "Editor textu"
#: editor/editor_help.cpp editor/editor_node.cpp editor/editor_settings.cpp
#: editor/plugins/shader_editor_plugin.cpp
@@ -3631,7 +3635,7 @@ msgstr "Nápověda"
#: editor/editor_help.cpp
msgid "Sort Functions Alphabetically"
-msgstr ""
+msgstr "Třídit funkce abecedně"
#: editor/editor_help_search.cpp editor/editor_node.cpp
#: editor/plugins/script_editor_plugin.cpp
@@ -3751,10 +3755,12 @@ msgstr "(hodnota)"
msgid ""
"Pinning a value forces it to be saved even if it's equal to the default."
msgstr ""
+"Připnutí hodnoty vynutí její uložení, i když bude shodná s výchozí hodnotou."
#: editor/editor_inspector.cpp
+#, fuzzy
msgid "Pin value [Disabled because '%s' is editor-only]"
-msgstr ""
+msgstr "Připnout hodnotu [vypnuto jelikož '%s' je pouze v editoru]"
#: editor/editor_inspector.cpp
#: editor/plugins/gradient_texture_2d_editor_plugin.cpp
@@ -3771,11 +3777,11 @@ msgstr "Nastavit více:"
#: editor/editor_inspector.cpp
msgid "Pinned %s"
-msgstr ""
+msgstr "Připnuté %s"
#: editor/editor_inspector.cpp
msgid "Unpinned %s"
-msgstr ""
+msgstr "Nepřipnuté %s"
#: editor/editor_inspector.cpp
#, fuzzy
@@ -4415,80 +4421,73 @@ msgstr "%d více souborů"
msgid ""
"Unable to write to file '%s', file in use, locked or lacking permissions."
msgstr ""
+"Není možné zapisovat do souboru '%s', soubour je používán, uzamÄen nebo "
+"chybí oprávnění."
#: editor/editor_node.cpp editor/editor_settings.cpp editor/scene_tree_dock.cpp
#: servers/arvr/arvr_interface.cpp
-#, fuzzy
msgid "Interface"
-msgstr "Uživatelské rozhraní"
+msgstr "Rozhraní"
#: editor/editor_node.cpp editor/editor_settings.cpp
-#, fuzzy
msgid "Scene Tabs"
-msgstr "Přepnout záložku scény"
+msgstr "Karty scén"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Always Show Close Button"
-msgstr "Vždy zobrazit mřížku"
+msgstr "Vždy zobrazit tlaÄítko zavÅ™ení"
#: editor/editor_node.cpp editor/editor_settings.cpp
msgid "Resize If Many Tabs"
-msgstr ""
+msgstr "ZmÄ›nit velikost pÅ™i velkém poÄtu záložek"
#: editor/editor_node.cpp editor/editor_settings.cpp
msgid "Minimum Width"
-msgstr ""
+msgstr "Minimální šířka"
#: editor/editor_node.cpp editor/editor_settings.cpp
msgid "Output"
msgstr "Výstup"
#: editor/editor_node.cpp editor/editor_settings.cpp
-#, fuzzy
msgid "Always Clear Output On Play"
-msgstr "Vymazat výstup"
+msgstr "Vždy vymazat výstup při spuštění"
#: editor/editor_node.cpp editor/editor_settings.cpp
msgid "Always Open Output On Play"
-msgstr ""
+msgstr "Vždy otevřít výstup při spuštění"
#: editor/editor_node.cpp editor/editor_settings.cpp
msgid "Always Close Output On Stop"
-msgstr ""
+msgstr "Vždy zavřít výstup pÅ™i ukonÄení"
#: editor/editor_node.cpp
msgid "Save On Focus Loss"
msgstr ""
#: editor/editor_node.cpp editor/editor_settings.cpp
-#, fuzzy
msgid "Save Each Scene On Quit"
-msgstr "Uložit větev jako scénu"
+msgstr "Uložit všechny scény při vypnutí"
#: editor/editor_node.cpp editor/editor_settings.cpp
-#, fuzzy
msgid "Quit Confirmation"
-msgstr "Zobrazit informace"
+msgstr "Potvrzení při vypnutí"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Show Update Spinner"
-msgstr "Schovat aktualizaÄní koleÄko"
+msgstr "Zobrazit aktualizaÄní koleÄko"
#: editor/editor_node.cpp
msgid "Update Continuously"
msgstr "Aktualizovat průběžně"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Update Vital Only"
-msgstr "Změny materiálu:"
+msgstr "Aktualizovat pouze důležité"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Localize Settings"
-msgstr "Lokalizace"
+msgstr "LokalizaÄní nastavení"
#: editor/editor_node.cpp
#, fuzzy
@@ -4497,7 +4496,7 @@ msgstr "Uzel TimeSeek"
#: editor/editor_node.cpp editor/editor_settings.cpp
msgid "Show Thumbnail On Hover"
-msgstr ""
+msgstr "Zobrazit náhled při překrytí"
#: editor/editor_node.cpp editor/editor_settings.cpp
msgid "Inspector"
@@ -5399,69 +5398,64 @@ msgid "Did you forget the '_run' method?"
msgstr "Nezapoměl jste metodu '_run'?"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Editor Language"
-msgstr "Rozložení editoru"
+msgstr "Jazyk editoru"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Display Scale"
-msgstr "Zobrazit všechny"
+msgstr "Škálování zobrazení"
#: editor/editor_settings.cpp
msgid "Custom Display Scale"
-msgstr ""
+msgstr "Vlastní škálování zobrazení"
#: editor/editor_settings.cpp
msgid "Main Font Size"
-msgstr ""
+msgstr "Velikost písma editoru"
#: editor/editor_settings.cpp
msgid "Code Font Size"
-msgstr ""
+msgstr "Velikost písma kódu"
#: editor/editor_settings.cpp
msgid "Font Antialiased"
-msgstr ""
+msgstr "Vyhlazování písma"
#: editor/editor_settings.cpp
msgid "Font Hinting"
-msgstr ""
+msgstr "Hinting písma"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Main Font"
-msgstr "Hlavní scéna"
+msgstr "Font editoru"
#: editor/editor_settings.cpp
msgid "Main Font Bold"
-msgstr ""
+msgstr "TuÄný font editoru"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Code Font"
-msgstr "Přidat bod uzlu"
+msgstr "Font kódu"
#: editor/editor_settings.cpp
msgid "Dim Editor On Dialog Popup"
-msgstr ""
+msgstr "Ztmavit editor při zobrazení dialogového okna"
#: editor/editor_settings.cpp main/main.cpp
msgid "Low Processor Mode Sleep (µsec)"
-msgstr ""
+msgstr "Režim spánku s nízkým využitím procesoru (µs)"
#: editor/editor_settings.cpp
msgid "Unfocused Low Processor Mode Sleep (µsec)"
-msgstr ""
+msgstr "Nezaměřený režim spánku s nízkým využitím procesoru (µs)"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Separate Distraction Mode"
-msgstr "Nerozptylující režitm"
+msgstr "Oddělit nerozptylující režim"
#: editor/editor_settings.cpp
msgid "Automatically Open Screenshots"
-msgstr ""
+msgstr "Automaticky otevřít snímky obrazovky"
#: editor/editor_settings.cpp
msgid "Max Array Dictionary Items Per Page"
@@ -5475,58 +5469,54 @@ msgstr "Téma"
#: editor/editor_settings.cpp editor/import_dock.cpp
msgid "Preset"
-msgstr "Profil"
+msgstr "Předvolba"
#: editor/editor_settings.cpp
msgid "Icon And Font Color"
-msgstr ""
+msgstr "Barva ikon a písma"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Base Color"
-msgstr "Barvy"
+msgstr "Základní barva"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Accent Color"
-msgstr "Vyberte barvu"
+msgstr "Barva zvýraznění"
#: editor/editor_settings.cpp scene/resources/environment.cpp
msgid "Contrast"
-msgstr ""
+msgstr "Kontrast"
#: editor/editor_settings.cpp
+#, fuzzy
msgid "Relationship Line Opacity"
-msgstr ""
+msgstr "Průhlednost linky relace"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Highlight Tabs"
-msgstr "Ukládám světelné mapy"
+msgstr "Zvýraznit karty"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Border Size"
-msgstr "HraniÄní pixely"
+msgstr "Velikost okrajů"
#: editor/editor_settings.cpp
+#, fuzzy
msgid "Use Graph Node Headers"
-msgstr ""
+msgstr "Použít uzly záhlaví grafů"
#: editor/editor_settings.cpp
#, fuzzy
msgid "Additional Spacing"
-msgstr "Opakování animace"
+msgstr "Přídavné mezerování"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Custom Theme"
-msgstr "Motiv editoru"
+msgstr "Vlastní téma"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Show Script Button"
-msgstr "Pravé tlaÄítko koleÄka"
+msgstr "Ukázat tlaÄítko skriptu"
#: editor/editor_settings.cpp
#, fuzzy
@@ -5539,9 +5529,8 @@ msgid "Autoscan Project Path"
msgstr "Cesta k projektu:"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Default Project Path"
-msgstr "Cesta k projektu:"
+msgstr "Výchozí cesta k projektu"
#: editor/editor_settings.cpp
#, fuzzy
@@ -5563,9 +5552,8 @@ msgid "File Dialog"
msgstr "XForm dialog"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Thumbnail Size"
-msgstr "Náhled..."
+msgstr "Velikost náhledu"
#: editor/editor_settings.cpp
msgid "Docks"
@@ -5578,83 +5566,73 @@ msgstr "Úpravy stromu scény"
#: editor/editor_settings.cpp
msgid "Start Create Dialog Fully Expanded"
-msgstr ""
+msgstr "Plně rozbalit dialog vytvoření při spuštění"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Always Show Folders"
-msgstr "Vždy zobrazit mřížku"
+msgstr "Vždy zobrazit složky"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Property Editor"
-msgstr "Editor skupin"
+msgstr "Editor oblasti"
#: editor/editor_settings.cpp
msgid "Auto Refresh Interval"
-msgstr ""
+msgstr "Automatický interval obnovení"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Subresource Hue Tint"
-msgstr "DílÄí zdroje"
+msgstr "Podzdroj odstínu"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Color Theme"
-msgstr "Motiv editoru"
+msgstr "Barevné téma"
#: editor/editor_settings.cpp scene/3d/label_3d.cpp
#: scene/resources/default_theme/default_theme.cpp
msgid "Line Spacing"
-msgstr ""
+msgstr "Řádkování"
#: editor/editor_settings.cpp editor/plugins/script_text_editor.cpp
#: modules/gdscript/editor/gdscript_highlighter.cpp
-#, fuzzy
msgid "Highlighting"
-msgstr "Přímé osvětlení"
+msgstr "Zvýrazňování"
#: editor/editor_settings.cpp scene/gui/text_edit.cpp
-#, fuzzy
msgid "Syntax Highlighting"
-msgstr "ZvýrazňovaÄ syntaxe"
+msgstr "Zvýrazňování syntaxe"
#: editor/editor_settings.cpp scene/gui/text_edit.cpp
msgid "Highlight All Occurrences"
-msgstr ""
+msgstr "Zvýraznit všechny výskyty"
#: editor/editor_settings.cpp scene/gui/text_edit.cpp
msgid "Highlight Current Line"
-msgstr ""
+msgstr "Zvýraznit aktuální řádek"
#: editor/editor_settings.cpp editor/plugins/script_text_editor.cpp
msgid "Highlight Type Safe Lines"
msgstr ""
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Indent"
-msgstr "Odsadit zleva"
+msgstr "Odsazení"
#: editor/editor_settings.cpp editor/plugins/script_text_editor.cpp
msgid "Auto Indent"
msgstr "Automatické odsazení"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Convert Indent On Save"
-msgstr "Převést odsazení na mezery"
+msgstr "Konvertovat odsazení při uložení"
#: editor/editor_settings.cpp scene/gui/text_edit.cpp
-#, fuzzy
msgid "Draw Tabs"
-msgstr "Vykreslovací volání:"
+msgstr "Vykreslit taby"
#: editor/editor_settings.cpp scene/gui/text_edit.cpp
-#, fuzzy
msgid "Draw Spaces"
-msgstr "Vykreslovací volání:"
+msgstr "Vykreslit mezery"
#: editor/editor_settings.cpp editor/plugins/spatial_editor_plugin.cpp
#: editor/plugins/tile_set_editor_plugin.cpp scene/2d/tile_map.cpp
@@ -5665,47 +5643,43 @@ msgstr "Navigace"
#: editor/editor_settings.cpp scene/gui/text_edit.cpp
msgid "Smooth Scrolling"
-msgstr ""
+msgstr "Plynulé posouvání"
#: editor/editor_settings.cpp scene/gui/text_edit.cpp
msgid "V Scroll Speed"
-msgstr ""
+msgstr "Vertikální rychlost posouvání"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Show Minimap"
-msgstr "Zobrazit poÄátek"
+msgstr "Zobrazit minimapu"
#: editor/editor_settings.cpp
msgid "Minimap Width"
-msgstr ""
+msgstr "Šířka minimapy"
#: editor/editor_settings.cpp
msgid "Mouse Extra Buttons Navigate History"
-msgstr ""
+msgstr "NavigaÄní historie extra tlaÄítek myÅ¡i"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Drag And Drop Selection"
-msgstr "GridMap Vyplnit výběr"
+msgstr "Výběr přetažením"
#: editor/editor_settings.cpp
msgid "Stay In Script Editor On Node Selected"
-msgstr ""
+msgstr "Zůstat v editoru skriptu při výběru uzlu"
#: editor/editor_settings.cpp
msgid "Appearance"
-msgstr ""
+msgstr "Vzhled"
#: editor/editor_settings.cpp scene/gui/text_edit.cpp
-#, fuzzy
msgid "Show Line Numbers"
-msgstr "Číslo řádku:"
+msgstr "Zobrazit Äísla řádků"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Line Numbers Zero Padded"
-msgstr "Číslo řádku:"
+msgstr "Vyplnit Äísla řádků nulami"
#: editor/editor_settings.cpp
msgid "Show Bookmark Gutter"
@@ -5722,32 +5696,31 @@ msgstr ""
#: editor/editor_settings.cpp
msgid "Code Folding"
-msgstr ""
+msgstr "Složení kódu"
#: editor/editor_settings.cpp
msgid "Word Wrap"
-msgstr ""
+msgstr "Zalamování"
#: editor/editor_settings.cpp
msgid "Show Line Length Guidelines"
-msgstr ""
+msgstr "Zobrazit vodící Äáry délky řádků"
#: editor/editor_settings.cpp
msgid "Line Length Guideline Soft Column"
-msgstr ""
+msgstr "MÄ›kký sloupec Äáry délky řádku"
#: editor/editor_settings.cpp
msgid "Line Length Guideline Hard Column"
-msgstr ""
+msgstr "Tvrdý sloupec Äáry délky řádku"
#: editor/editor_settings.cpp editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Script List"
-msgstr "Editor skriptů"
+msgstr "Seznam skriptů"
#: editor/editor_settings.cpp
msgid "Show Members Overview"
-msgstr ""
+msgstr "Zobrazit pÅ™ehled Älenů"
#: editor/editor_settings.cpp editor/plugins/script_editor_plugin.cpp
#, fuzzy
@@ -5932,9 +5905,8 @@ msgid "Primary Grid Steps"
msgstr "Krok mřížky:"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Grid Size"
-msgstr "Krok mřížky:"
+msgstr "Velikost mřížky"
#: editor/editor_settings.cpp
msgid "Grid Division Level Max"
@@ -6192,9 +6164,8 @@ msgid "Onion Layers Future Color"
msgstr ""
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Visual Editors"
-msgstr "Editor skupin"
+msgstr "Vizuální editory"
#: editor/editor_settings.cpp
msgid "Minimap Opacity"
@@ -6279,76 +6250,70 @@ msgstr "Přejmenování složky:"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
msgid "Symbol Color"
-msgstr ""
+msgstr "Barva znaků"
#: editor/editor_settings.cpp
msgid "Keyword Color"
-msgstr ""
+msgstr "Barva klíÄových slov"
#: editor/editor_settings.cpp
msgid "Control Flow Keyword Color"
msgstr ""
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Base Type Color"
-msgstr "Změnit základní typ"
+msgstr "Barva základního typu"
#: editor/editor_settings.cpp
msgid "Engine Type Color"
-msgstr ""
+msgstr "Barva typu enginu"
#: editor/editor_settings.cpp
msgid "User Type Color"
-msgstr ""
+msgstr "Barva typu uživatele"
#: editor/editor_settings.cpp
msgid "Comment Color"
-msgstr ""
+msgstr "Barva komentářů"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "String Color"
-msgstr "Ukládám soubor:"
+msgstr "Barva řetězců"
#: 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 "Neplatná barva pozadí."
+msgstr "Barva pozadí"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Completion Background Color"
-msgstr "Neplatná barva pozadí."
+msgstr "Barva výplně pozadí"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Completion Selected Color"
-msgstr "Importovat vybrané"
+msgstr "Barva výplně výběru"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
+#, fuzzy
msgid "Completion Existing Color"
-msgstr ""
+msgstr "Barva výběru existence"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
msgid "Completion Scroll Color"
-msgstr ""
+msgstr "Barva výplně scrollu"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
msgid "Completion Font Color"
-msgstr ""
+msgstr "Barva výplně fontu"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Text Color"
-msgstr "Další patro"
+msgstr "Barva textu"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Line Number Color"
-msgstr "Číslo řádku:"
+msgstr "Barva Äísla řádku"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
#, fuzzy
@@ -6357,82 +6322,73 @@ msgstr "Číslo řádku:"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
msgid "Caret Color"
-msgstr ""
+msgstr "Barva vynechávky"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Caret Background Color"
-msgstr "Neplatná barva pozadí."
+msgstr "Barva pozadí vynechávky"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Text Selected Color"
-msgstr "Smazat vybraný"
+msgstr "Barva vybraného textu"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Selection Color"
-msgstr "Pouze výběr"
+msgstr "Barva výběru"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
msgid "Brace Mismatch Color"
-msgstr ""
+msgstr "Barva neshody závorek"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Current Line Color"
-msgstr "Aktuální scéna"
+msgstr "Barva aktuálního řádku"
#: editor/editor_settings.cpp
msgid "Line Length Guideline Color"
-msgstr ""
+msgstr "Barva Äáry délky řádku"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Word Highlighted Color"
-msgstr "ZvýrazňovaÄ syntaxe"
+msgstr "Barva zvýrazněného slova"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
msgid "Number Color"
-msgstr ""
+msgstr "Barva Äísel"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Function Color"
-msgstr "Funkce"
+msgstr "Barva funkcí"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
#, fuzzy
msgid "Member Variable Color"
-msgstr "Přejmenovat proměnnou"
+msgstr "Barva promÄ›nného Älena"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Mark Color"
-msgstr "Vyberte barvu"
+msgstr "Barva oznaÄení"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Bookmark Color"
-msgstr "Záložky"
+msgstr "Barva záložky"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Breakpoint Color"
-msgstr "Breakpointy"
+msgstr "Barva bodu přerušení (Breakpointu)"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
+#, fuzzy
msgid "Executing Line Color"
-msgstr ""
+msgstr "Barva provádějící se linky"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
msgid "Code Folding Color"
-msgstr ""
+msgstr "Barva složení kódu"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Search Result Color"
-msgstr "Výsledky hledání"
+msgstr "Barva výsledků hledání"
#: editor/editor_settings.cpp
#, fuzzy
@@ -6749,7 +6705,7 @@ msgstr ""
#: editor/plugins/version_control_editor_plugin.cpp
#: platform/uwp/export/export.cpp platform/windows/export/export.cpp
msgid "Password"
-msgstr ""
+msgstr "Heslo"
#: editor/filesystem_dock.cpp
msgid "Favorites"
@@ -7489,7 +7445,7 @@ msgstr "Pevné pixely"
#: editor/import/resource_importer_texture.cpp scene/resources/texture.cpp
msgid "Lossy Quality"
-msgstr ""
+msgstr "Ztrátová kvalita"
#: editor/import/resource_importer_texture.cpp
#, fuzzy
@@ -7498,14 +7454,14 @@ msgstr "Režim výběru"
#: 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 "Normálová mapa"
#: editor/import/resource_importer_texture.cpp
#, fuzzy
@@ -7542,7 +7498,7 @@ msgstr "Velikost: "
#: editor/import/resource_importer_texture.cpp
msgid "Detect 3D"
-msgstr ""
+msgstr "Detekovat 3D"
#: editor/import/resource_importer_texture.cpp
#, fuzzy
@@ -7554,6 +7510,8 @@ msgid ""
"Warning, no suitable PC VRAM compression enabled in Project Settings. This "
"texture will not display correctly on PC."
msgstr ""
+"Upozornění, žádná vhodná PC VRAM komprese není povolena v nastavení "
+"projektu. Tato textura se na PC nebude zobrazovat správně."
#: editor/import/resource_importer_texture_atlas.cpp
#, fuzzy
@@ -7571,8 +7529,9 @@ msgid "Crop To Region"
msgstr "Nastavit oblast textury"
#: editor/import/resource_importer_texture_atlas.cpp
+#, fuzzy
msgid "Trim Alpha Border From Region"
-msgstr ""
+msgstr "Oříznout ohraniÄení alfa z oblasti"
#: editor/import/resource_importer_wav.cpp scene/2d/physics_body_2d.cpp
#, fuzzy
@@ -7580,8 +7539,9 @@ msgid "Force"
msgstr "Vnutit nahrátí"
#: editor/import/resource_importer_wav.cpp
+#, fuzzy
msgid "8 Bit"
-msgstr ""
+msgstr "8 Bit"
#: editor/import/resource_importer_wav.cpp main/main.cpp
#: modules/mono/editor/csharp_project.cpp modules/mono/godotsharp_dirs.cpp
@@ -7601,7 +7561,7 @@ msgstr "Uzel Mix"
#: editor/import/resource_importer_wav.cpp
msgid "Trim"
-msgstr ""
+msgstr "Oříznout"
#: editor/import/resource_importer_wav.cpp
#, fuzzy
@@ -7694,6 +7654,8 @@ msgid ""
"Select a resource file in the filesystem or in the inspector to adjust "
"import settings."
msgstr ""
+"Vyberte zdrojový soubor v prohlížeÄi souboru nebo v inspektoru k úpravÄ› "
+"nastavení importu."
#: editor/inspector_dock.cpp
msgid "Failed to load resource."
@@ -7720,7 +7682,7 @@ msgstr "Jazyky"
#: editor/inspector_dock.cpp
msgid "Localization not available for current language."
-msgstr ""
+msgstr "Lokalizace není dostupná pro aktuální jazyk."
#: editor/inspector_dock.cpp
msgid "Copy Properties"
@@ -8592,7 +8554,7 @@ msgstr "Filtry..."
#: editor/plugins/asset_library_editor_plugin.cpp scene/main/http_request.cpp
msgid "Use Threads"
-msgstr ""
+msgstr "Použít vlákna"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Contents:"
@@ -8825,7 +8787,7 @@ msgstr "Testované"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Failed to get repository configuration."
-msgstr ""
+msgstr "Nepodařilo se získat konfiguraci repozitáře."
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Assets ZIP File"
@@ -8883,7 +8845,7 @@ msgstr "Zapéct lightmapy"
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid "LightMap Bake"
-msgstr ""
+msgstr "Zapéct lightmapu"
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid "Select lightmap bake file:"
@@ -9234,7 +9196,7 @@ msgstr "Režim škálování"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Shift: Scale proportionally."
-msgstr ""
+msgstr "Shift: ZvÄ›tÅ¡ovat proporÄnÄ›."
#: editor/plugins/canvas_item_editor_plugin.cpp
#: editor/plugins/spatial_editor_plugin.cpp
@@ -9400,11 +9362,11 @@ msgstr "Zobrazit mřížku"
#: editor/plugins/canvas_item_editor_plugin.cpp
#, fuzzy
msgid "Show When Snapping"
-msgstr "Chytré přichcování"
+msgstr "Zobrazit při skoku"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Hide"
-msgstr ""
+msgstr "Schovat"
#: editor/plugins/canvas_item_editor_plugin.cpp
#, fuzzy
@@ -9789,7 +9751,7 @@ msgstr "Ikona"
#: 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
@@ -10916,11 +10878,11 @@ msgstr "Výsledky hledání"
#: editor/plugins/script_editor_plugin.cpp
msgid "Open Dominant Script On Scene Change"
-msgstr ""
+msgstr "Otevřít dominantní skript při změně scény"
#: editor/plugins/script_editor_plugin.cpp
msgid "External"
-msgstr ""
+msgstr "Externí"
#: editor/plugins/script_editor_plugin.cpp
#, fuzzy
@@ -10933,37 +10895,32 @@ msgid "Exec Path"
msgstr "Exportovat cestu"
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Script Temperature Enabled"
-msgstr "Vybrat soubor šablony"
+msgstr "Povolit teplotu skriptu"
#: editor/plugins/script_editor_plugin.cpp
msgid "Highlight Current Script"
-msgstr ""
+msgstr "Zvýraznit aktuální skript"
#: editor/plugins/script_editor_plugin.cpp
msgid "Script Temperature History Size"
-msgstr ""
+msgstr "Velikost historie teploty skriptu"
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Current Script Background Color"
-msgstr "Neplatná barva pozadí."
+msgstr "Barva pozadí momentálního skriptu"
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Group Help Pages"
-msgstr "Seskupit vybrané"
+msgstr "Seskupit stránky s nápovědou"
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Sort Scripts By"
-msgstr "Vytvořit skript"
+msgstr "Seřadit skripty podle"
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "List Script Names As"
-msgstr "Název skriptu:"
+msgstr "Zobrazit názvy seznamu skriptů jako"
#: editor/plugins/script_editor_plugin.cpp
msgid "Exec Flags"
@@ -11667,11 +11624,11 @@ msgstr "Přepnout volný pohled"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Decrease Field of View"
-msgstr ""
+msgstr "Zmenšit zorné pole"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Increase Field of View"
-msgstr ""
+msgstr "Zvětšit zorné pole"
#: editor/plugins/spatial_editor_plugin.cpp
#, fuzzy
@@ -12255,9 +12212,8 @@ msgid "Select all Theme items with item data."
msgstr ""
#: editor/plugins/theme_editor_plugin.cpp
-#, fuzzy
msgid "Deselect All"
-msgstr "Vybrat vše"
+msgstr "Zrušit všechen výběr"
#: editor/plugins/theme_editor_plugin.cpp
msgid "Deselect all Theme items."
@@ -13188,9 +13144,10 @@ msgstr "Možnosti přichycení"
#: scene/2d/path_2d.cpp scene/2d/polygon_2d.cpp scene/2d/sprite.cpp
#: scene/3d/cpu_particles.cpp scene/3d/label_3d.cpp scene/3d/path.cpp
#: scene/3d/physics_body.cpp scene/3d/soft_body.cpp scene/3d/sprite_3d.cpp
-#: 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
+#: scene/3d/visual_instance.cpp 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 "Offset(Posun):"
@@ -14639,16 +14596,17 @@ msgid "Invalid project path (changed anything?)."
msgstr "Neplatná cesta k projektu (něco se změnilo?)."
#: editor/project_manager.cpp
+#, fuzzy
msgid ""
-"Couldn't load project.godot in project path (error %d). It may be missing or "
-"corrupted."
+"Couldn't load project at '%s' (error %d). It may be missing or corrupted."
msgstr ""
"Nelze naÄíst project.godot v umístÄ›ní projektu (chyba %d). Může chybÄ›t nebo "
"být poškozený."
#: editor/project_manager.cpp
-msgid "Couldn't edit project.godot in project path."
-msgstr "Nelze upravit project.godot v umístění projektu."
+#, fuzzy
+msgid "Couldn't save project at '%s' (error %d)."
+msgstr "Nelze otevřít projekt v '%s'."
#: editor/project_manager.cpp
msgid "Couldn't create project.godot in project path."
@@ -15852,13 +15810,12 @@ msgid "Clear Inheritance? (No Undo!)"
msgstr "Vymazat dÄ›diÄnost? (Nelze vrátit zpÄ›t!)"
#: editor/scene_tree_dock.cpp
-#, fuzzy
msgid "Show Scene Tree Root Selection"
-msgstr "Vycentrovat výběr"
+msgstr "Zobrazit výběr Tree Root ze scény"
#: editor/scene_tree_dock.cpp
msgid "Derive Script Globals By Name"
-msgstr ""
+msgstr "NaÄítat globální promÄ›nné skritpu podle názvu"
#: editor/scene_tree_dock.cpp
#, fuzzy
@@ -16767,7 +16724,7 @@ msgstr ""
#: main/main.cpp
msgid "Fullsize"
-msgstr ""
+msgstr "Plná velikost"
#: main/main.cpp scene/resources/dynamic_font.cpp
#, fuzzy
@@ -16805,9 +16762,8 @@ msgid "Emulate Mouse From Touch"
msgstr ""
#: main/main.cpp
-#, fuzzy
msgid "Mouse Cursor"
-msgstr "TlaÄítko myÅ¡i"
+msgstr "Kurzor myši"
#: main/main.cpp
#, fuzzy
@@ -16881,7 +16837,7 @@ msgstr "Přichytit ke stranám uzlu"
#: main/main.cpp
msgid "Dynamic Fonts"
-msgstr ""
+msgstr "Dynamické fonty"
#: main/main.cpp
msgid "Use Oversampling"
@@ -16921,21 +16877,18 @@ msgid "Calculate Tangents"
msgstr ""
#: modules/csg/csg_shape.cpp
-#, fuzzy
msgid "Use Collision"
-msgstr "Kolize"
+msgstr "Použít kolize"
#: modules/csg/csg_shape.cpp servers/physics_2d_server.cpp
-#, fuzzy
msgid "Collision Layer"
-msgstr "Kolizní režim"
+msgstr "Kolizní vrstva"
#: 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 "Kolizní režim"
+msgstr "Kolizní maska"
#: modules/csg/csg_shape.cpp
#, fuzzy
@@ -16950,9 +16903,8 @@ msgstr "Změnit velikost písmen"
#: 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 "Poloměr:"
+msgstr "Poloměr"
#: modules/csg/csg_shape.cpp scene/resources/primitive_meshes.cpp
#, fuzzy
@@ -17278,7 +17230,7 @@ msgstr ""
#: modules/gdscript/language_server/gdscript_language_server.cpp
msgid "Use Thread"
-msgstr ""
+msgstr "Použít vlákno"
#: modules/gltf/editor_scene_exporter_gltf_plugin.cpp
#, fuzzy
@@ -17310,9 +17262,8 @@ msgid "Normalized"
msgstr "Formát"
#: modules/gltf/gltf_accessor.cpp
-#, fuzzy
msgid "Count"
-msgstr "Množství:"
+msgstr "Množství"
#: modules/gltf/gltf_accessor.cpp scene/resources/visual_shader_nodes.cpp
#, fuzzy
@@ -17370,9 +17321,8 @@ msgid "Indices"
msgstr "Všechna zařízení"
#: modules/gltf/gltf_camera.cpp
-#, fuzzy
msgid "FOV Size"
-msgstr "Velikost:"
+msgstr "Velikost pohledu"
#: modules/gltf/gltf_camera.cpp
msgid "Zfar"
@@ -19442,9 +19392,8 @@ msgid "Invalid filename! Android APK requires the *.apk extension."
msgstr "Neplatné jméno souboru! Android APK vyžaduje příponu *.apk."
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Unsupported export format!"
-msgstr "Nepodporovaný formát exportu!\n"
+msgstr "Nepodporovaný formát exportu!"
#: platform/android/export/export_plugin.cpp
msgid ""
@@ -19455,15 +19404,12 @@ msgstr ""
"verzi. Přeinstalujte jej z nabídky \"Projekt\"."
#: 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 ""
-"Neshoda verzí Android buildu:\n"
-" Šablona nainstalována: %s\n"
-" Verze Godot: %s\n"
-"Přeinstalujte šablonu pro sestavení systému Android z nabídky \"Projekt\"."
+"Neshoda verzí Android buildu: Šablona nainstalována: %s, Verze Godotu: %s. "
+"Prosím, přeinstalujte Android build šablonu z nabídky \"Projekt\"."
#: platform/android/export/export_plugin.cpp
msgid ""
@@ -19471,9 +19417,8 @@ msgid ""
msgstr ""
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Could not export project files to gradle project."
-msgstr "Nelze exportovat soubory projektu do projektu gradle\n"
+msgstr "Nelze exportovat soubory projektu do projektu gradle."
#: platform/android/export/export_plugin.cpp
msgid "Could not write expansion package file!"
@@ -19484,12 +19429,11 @@ msgid "Building Android Project (gradle)"
msgstr "Buildování projektu pro 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 ""
-"Buildování projektu pro Android se nezdařilo, zkontrolujte chybový výstup.\n"
+"Buildování projektu pro Android se nezdařilo, zkontrolujte chybový výstup. "
"Případně navštivte dokumentaci o build pro Android na docs.godotengine.org."
#: platform/android/export/export_plugin.cpp
@@ -19514,11 +19458,8 @@ msgid "Creating APK..."
msgstr "Vytvářím APK..."
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Could not find template APK to export: \"%s\"."
-msgstr ""
-"Nepodařilo se najít šablonu APK pro export:\n"
-"%s"
+msgstr "Nepodařilo se najít šablonu APK pro export: \"%s\""
#: platform/android/export/export_plugin.cpp
msgid ""
@@ -19640,7 +19581,7 @@ msgstr ""
#: 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
#, fuzzy
@@ -21384,7 +21325,7 @@ msgstr "Místní projekty"
#: 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 "Pořadí vykreslování"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
@@ -21424,7 +21365,7 @@ msgstr "Směry"
#: scene/resources/particles_material.cpp
#: servers/audio/effects/audio_effect_reverb.cpp
msgid "Spread"
-msgstr ""
+msgstr "Rozšířit"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
@@ -21442,7 +21383,7 @@ msgstr "Inicializovat"
#: scene/resources/particles_material.cpp servers/physics_2d_server.cpp
#: servers/physics_server.cpp
msgid "Angular Velocity"
-msgstr ""
+msgstr "Úhlová rychlost"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
@@ -21494,12 +21435,12 @@ msgstr ""
#: scene/resources/particles_material.cpp
#: servers/audio/effects/audio_effect_reverb.cpp
msgid "Damping"
-msgstr ""
+msgstr "Tlumení"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
msgid "Damping Random"
-msgstr ""
+msgstr "Náhodné tlumení"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
@@ -21510,12 +21451,12 @@ msgstr "Rozdělit křivku"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp scene/3d/light.cpp
#: scene/resources/particles_material.cpp
msgid "Angle"
-msgstr ""
+msgstr "Úhel"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
msgid "Angle Random"
-msgstr ""
+msgstr "Náhodný úhel"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
@@ -21529,8 +21470,9 @@ msgid "Scale Amount"
msgstr "Množství:"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
+#, fuzzy
msgid "Scale Amount Random"
-msgstr ""
+msgstr "Škálovat náhodnou hodnotu"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#, fuzzy
@@ -21639,12 +21581,12 @@ msgstr "Deaktivované tlaÄítko"
#: scene/2d/joints_2d.cpp scene/3d/physics_body.cpp scene/3d/physics_joint.cpp
msgid "Softness"
-msgstr ""
+msgstr "Měkkost"
#: scene/2d/joints_2d.cpp scene/resources/animation.cpp
#: scene/resources/ray_shape.cpp scene/resources/segment_shape_2d.cpp
msgid "Length"
-msgstr ""
+msgstr "Délka"
#: scene/2d/joints_2d.cpp
#, fuzzy
@@ -21657,7 +21599,7 @@ msgstr ""
#: scene/2d/joints_2d.cpp scene/3d/physics_joint.cpp scene/3d/vehicle_body.cpp
msgid "Stiffness"
-msgstr ""
+msgstr "Tuhost"
#: scene/2d/light_2d.cpp
msgid ""
@@ -21679,15 +21621,15 @@ msgstr "Oblast textury"
#: scene/3d/light.cpp scene/resources/environment.cpp
#: scene/resources/material.cpp scene/resources/sky.cpp
msgid "Energy"
-msgstr ""
+msgstr "Energie"
#: scene/2d/light_2d.cpp
msgid "Z Min"
-msgstr ""
+msgstr "Z Min"
#: scene/2d/light_2d.cpp
msgid "Z Max"
-msgstr ""
+msgstr "Z Max"
#: scene/2d/light_2d.cpp
#, fuzzy
@@ -21754,8 +21696,9 @@ msgid "Default Color"
msgstr "Výchozí"
#: scene/2d/line_2d.cpp scene/resources/texture.cpp
+#, fuzzy
msgid "Fill"
-msgstr ""
+msgstr "Výplň"
#: scene/2d/line_2d.cpp scene/resources/texture.cpp
#, fuzzy
@@ -23678,9 +23621,8 @@ msgid "A RoomGroup should not be a child or grandchild of a Portal."
msgstr ""
#: scene/3d/portal.cpp
-#, fuzzy
msgid "Portal Active"
-msgstr " [aktivní portály]"
+msgstr "Aktivní portál"
#: scene/3d/portal.cpp scene/resources/occluder_shape_polygon.cpp
msgid "Two Way"
@@ -23820,8 +23762,9 @@ msgid "There should only be one RoomManager in the SceneTree."
msgstr ""
#: scene/3d/room_manager.cpp
+#, fuzzy
msgid "Main"
-msgstr ""
+msgstr "Hlavní"
#: scene/3d/room_manager.cpp scene/animation/animation_blend_tree.cpp
#: scene/animation/animation_player.cpp scene/animation/animation_tree.cpp
@@ -23833,7 +23776,7 @@ msgstr "Akce"
#: scene/3d/room_manager.cpp
msgid "Roomlist"
-msgstr ""
+msgstr "Seznam místností"
#: scene/3d/room_manager.cpp servers/visual_server.cpp
#, fuzzy
@@ -23852,7 +23795,7 @@ msgstr "Soubor ZIP"
#: scene/3d/room_manager.cpp servers/visual_server.cpp
msgid "Gameplay"
-msgstr ""
+msgstr "Hratelnost"
#: scene/3d/room_manager.cpp
#, fuzzy
@@ -23909,8 +23852,9 @@ msgid ""
msgstr ""
#: scene/3d/room_manager.cpp
+#, fuzzy
msgid "RoomList contains no Rooms, aborting."
-msgstr ""
+msgstr "Seznam místností neobsahuje žádné místnosti, přerušování."
#: scene/3d/room_manager.cpp
msgid "Misnamed nodes detected, check output log for details. Aborting."
@@ -24135,6 +24079,15 @@ msgstr "Chyba"
msgid "AABB"
msgstr ""
+#: scene/3d/visual_instance.cpp
+#, fuzzy
+msgid "Sorting"
+msgstr "Seřadit"
+
+#: scene/3d/visual_instance.cpp
+msgid "Use AABB Center"
+msgstr ""
+
#: scene/3d/visual_instance.cpp scene/resources/navigation_mesh.cpp
#, fuzzy
msgid "Geometry"
@@ -24711,7 +24664,7 @@ msgstr "Vlastnosti motivu"
#: scene/gui/dialogs.cpp
msgid "Window Title"
-msgstr ""
+msgstr "Název okna"
#: scene/gui/dialogs.cpp
#, fuzzy
@@ -24777,7 +24730,7 @@ msgstr "Zobrazit kosti"
#: scene/gui/graph_edit.cpp scene/gui/text_edit.cpp
#: scene/resources/default_theme/default_theme.cpp
msgid "Minimap"
-msgstr ""
+msgstr "Minimapa"
#: scene/gui/graph_edit.cpp
msgid "Enable grid minimap."
@@ -24830,7 +24783,7 @@ msgstr "Vyplnit výběr"
#: scene/gui/item_list.cpp
msgid "Max Text Lines"
-msgstr ""
+msgstr "Maximální poÄet řádků textu"
#: scene/gui/item_list.cpp
#, fuzzy
@@ -24839,15 +24792,15 @@ msgstr "Testované"
#: scene/gui/item_list.cpp
msgid "Max Columns"
-msgstr ""
+msgstr "Maximální poÄet sloupců"
#: scene/gui/item_list.cpp
msgid "Same Column Width"
-msgstr ""
+msgstr "Stejná šířka sloupce"
#: scene/gui/item_list.cpp
msgid "Fixed Column Width"
-msgstr ""
+msgstr "Pevná šířka sloupce"
#: scene/gui/item_list.cpp
#, fuzzy
@@ -24876,15 +24829,16 @@ msgstr "Přepnout viditelnost"
#: scene/gui/label.cpp
msgid "Lines Skipped"
-msgstr ""
+msgstr "PÅ™eskoÄené řádky"
#: scene/gui/label.cpp
+#, fuzzy
msgid "Max Lines Visible"
-msgstr ""
+msgstr "Maximální poÄet viditelných řádků"
#: scene/gui/line_edit.cpp scene/resources/navigation_mesh.cpp
msgid "Max Length"
-msgstr ""
+msgstr "Maximální délka"
#: scene/gui/line_edit.cpp
msgid "Secret"
@@ -25290,7 +25244,7 @@ msgstr "Složka:"
#: scene/gui/text_edit.cpp
#, fuzzy
msgid "Drag And Drop Selection Enabled"
-msgstr "Pouze výběr"
+msgstr "Výběr přetažením povolen"
#: scene/gui/text_edit.cpp
#, fuzzy
@@ -25956,9 +25910,8 @@ msgid "H Separation"
msgstr "Oddělení:"
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Underline Spacing"
-msgstr "Opakování animace"
+msgstr "Mezera podtržení"
#: scene/resources/default_theme/default_theme.cpp
msgid "Arrow"
diff --git a/editor/translations/da.po b/editor/translations/da.po
index e83ef150e4..bb158fcada 100644
--- a/editor/translations/da.po
+++ b/editor/translations/da.po
@@ -18,13 +18,14 @@
# Autowinto <happymansi@hotmail.com>, 2020, 2021.
# Mikkel Mouridsen <mikkelmouridsen@me.com>, 2020, 2021, 2022.
# snakatk <snaqii@live.dk>, 2021.
+# Mattis Møl Kristensen <mattismoel@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-04-08 07:29+0000\n"
-"Last-Translator: Mikkel Mouridsen <mikkelmouridsen@me.com>\n"
+"PO-Revision-Date: 2022-11-02 18:47+0000\n"
+"Last-Translator: Mattis Møl Kristensen <mattismoel@gmail.com>\n"
"Language-Team: Danish <https://hosted.weblate.org/projects/godot-engine/"
"godot/da/>\n"
"Language: da\n"
@@ -32,7 +33,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.12-dev\n"
+"X-Generator: Weblate 4.14.2-dev\n"
#: core/bind/core_bind.cpp main/main.cpp
msgid "Tablet Driver"
@@ -147,7 +148,7 @@ msgstr "Redaktør"
#: core/bind/core_bind.cpp
msgid "Print Error Messages"
-msgstr ""
+msgstr "Udskriv fejlmeddelelser"
#: core/bind/core_bind.cpp
#, fuzzy
@@ -13427,9 +13428,10 @@ msgstr "Singleton"
#: scene/2d/path_2d.cpp scene/2d/polygon_2d.cpp scene/2d/sprite.cpp
#: scene/3d/cpu_particles.cpp scene/3d/label_3d.cpp scene/3d/path.cpp
#: scene/3d/physics_body.cpp scene/3d/soft_body.cpp scene/3d/sprite_3d.cpp
-#: 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
+#: scene/3d/visual_instance.cpp 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
msgid "Offset"
msgstr ""
@@ -14855,13 +14857,13 @@ msgstr ""
#: editor/project_manager.cpp
msgid ""
-"Couldn't load project.godot in project path (error %d). It may be missing or "
-"corrupted."
+"Couldn't load project at '%s' (error %d). It may be missing or corrupted."
msgstr ""
#: editor/project_manager.cpp
-msgid "Couldn't edit project.godot in project path."
-msgstr ""
+#, fuzzy
+msgid "Couldn't save project at '%s' (error %d)."
+msgstr "Kan ikke åbne projekt"
#: editor/project_manager.cpp
msgid "Couldn't create project.godot in project path."
@@ -24174,6 +24176,15 @@ msgstr "Fejl!"
msgid "AABB"
msgstr ""
+#: scene/3d/visual_instance.cpp
+#, fuzzy
+msgid "Sorting"
+msgstr "Sorter"
+
+#: scene/3d/visual_instance.cpp
+msgid "Use AABB Center"
+msgstr ""
+
#: scene/3d/visual_instance.cpp scene/resources/navigation_mesh.cpp
#, fuzzy
msgid "Geometry"
diff --git a/editor/translations/de.po b/editor/translations/de.po
index 7244c02cc1..61a5a51b9c 100644
--- a/editor/translations/de.po
+++ b/editor/translations/de.po
@@ -86,13 +86,14 @@
# Tim <sakul8826@gmail.com>, 2022.
# Anonynonymouse <tom.spaine60388@gmail.com>, 2022.
# Felix Bitsch <felix.a.bitsch@gmail.com>, 2022.
+# miguel <miguel-gonzalez@gmx.de>, 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-09-11 22:22+0000\n"
-"Last-Translator: So Wieso <sowieso@dukun.de>\n"
+"PO-Revision-Date: 2022-12-13 13:21+0000\n"
+"Last-Translator: ‎ <artism90@googlemail.com>\n"
"Language-Team: German <https://hosted.weblate.org/projects/godot-engine/"
"godot/de/>\n"
"Language: de\n"
@@ -100,7 +101,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.14.1-dev\n"
+"X-Generator: Weblate 4.15-dev\n"
#: core/bind/core_bind.cpp main/main.cpp
msgid "Tablet Driver"
@@ -12889,9 +12890,10 @@ msgstr "Einrasteinstellungen"
#: scene/2d/path_2d.cpp scene/2d/polygon_2d.cpp scene/2d/sprite.cpp
#: scene/3d/cpu_particles.cpp scene/3d/label_3d.cpp scene/3d/path.cpp
#: scene/3d/physics_body.cpp scene/3d/soft_body.cpp scene/3d/sprite_3d.cpp
-#: 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
+#: scene/3d/visual_instance.cpp 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
msgid "Offset"
msgstr "Versatz"
@@ -13069,7 +13071,7 @@ msgstr "Pfad des privaten SSH-Schlüssels auswählen"
#: editor/plugins/version_control_editor_plugin.cpp
msgid "SSH Passphrase"
-msgstr "SSH-Passphrase"
+msgstr "SSH Schlüsseltext"
#: editor/plugins/version_control_editor_plugin.cpp
msgid "Detect new changes"
@@ -14306,16 +14308,17 @@ msgid "Invalid project path (changed anything?)."
msgstr "Ungültiger Projektpfad (etwas geändert?)."
#: editor/project_manager.cpp
+#, fuzzy
msgid ""
-"Couldn't load project.godot in project path (error %d). It may be missing or "
-"corrupted."
+"Couldn't load project at '%s' (error %d). It may be missing or corrupted."
msgstr ""
"Die Datei project.godot im Projektpfad konnte nicht geladen werden (Fehler "
"%d). Sie könnte fehlen oder beschädigt sein."
#: editor/project_manager.cpp
-msgid "Couldn't edit project.godot in project path."
-msgstr "project.godot des Projektpfads konnte nicht bearbeitet werden."
+#, fuzzy
+msgid "Couldn't save project at '%s' (error %d)."
+msgstr "Projekt in ‚%s‘ kann nicht geöffnet werden."
#: editor/project_manager.cpp
msgid "Couldn't create project.godot in project path."
@@ -16312,7 +16315,7 @@ msgstr "Ausrichtung"
#: main/main.cpp scene/gui/scroll_container.cpp scene/gui/text_edit.cpp
#: scene/main/scene_tree.cpp scene/register_scene_types.cpp
msgid "Common"
-msgstr "Gewöhnlich"
+msgstr "Allgemein"
#: main/main.cpp
msgid "Physics FPS"
@@ -23251,6 +23254,16 @@ msgstr "Max Kraft"
msgid "AABB"
msgstr "AABB"
+#: scene/3d/visual_instance.cpp
+#, fuzzy
+msgid "Sorting"
+msgstr "Sortiere"
+
+#: scene/3d/visual_instance.cpp
+#, fuzzy
+msgid "Use AABB Center"
+msgstr "Ambient verwenden"
+
#: scene/3d/visual_instance.cpp scene/resources/navigation_mesh.cpp
msgid "Geometry"
msgstr "Geometrie"
diff --git a/editor/translations/editor.pot b/editor/translations/editor.pot
index fb76a2c2c7..7b7bfd71cc 100644
--- a/editor/translations/editor.pot
+++ b/editor/translations/editor.pot
@@ -12352,9 +12352,10 @@ msgstr ""
#: scene/2d/path_2d.cpp scene/2d/polygon_2d.cpp scene/2d/sprite.cpp
#: scene/3d/cpu_particles.cpp scene/3d/label_3d.cpp scene/3d/path.cpp
#: scene/3d/physics_body.cpp scene/3d/soft_body.cpp scene/3d/sprite_3d.cpp
-#: 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
+#: scene/3d/visual_instance.cpp 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
msgid "Offset"
msgstr ""
@@ -13683,12 +13684,11 @@ msgstr ""
#: editor/project_manager.cpp
msgid ""
-"Couldn't load project.godot in project path (error %d). It may be missing or "
-"corrupted."
+"Couldn't load project at '%s' (error %d). It may be missing or corrupted."
msgstr ""
#: editor/project_manager.cpp
-msgid "Couldn't edit project.godot in project path."
+msgid "Couldn't save project at '%s' (error %d)."
msgstr ""
#: editor/project_manager.cpp
@@ -22180,6 +22180,14 @@ msgstr ""
msgid "AABB"
msgstr ""
+#: scene/3d/visual_instance.cpp
+msgid "Sorting"
+msgstr ""
+
+#: scene/3d/visual_instance.cpp
+msgid "Use AABB Center"
+msgstr ""
+
#: scene/3d/visual_instance.cpp scene/resources/navigation_mesh.cpp
msgid "Geometry"
msgstr ""
diff --git a/editor/translations/el.po b/editor/translations/el.po
index 3ab08f3dbd..98873c7d40 100644
--- a/editor/translations/el.po
+++ b/editor/translations/el.po
@@ -13281,9 +13281,10 @@ msgstr "Επιλογές ΠÏοσκόλλησης"
#: scene/2d/path_2d.cpp scene/2d/polygon_2d.cpp scene/2d/sprite.cpp
#: scene/3d/cpu_particles.cpp scene/3d/label_3d.cpp scene/3d/path.cpp
#: scene/3d/physics_body.cpp scene/3d/soft_body.cpp scene/3d/sprite_3d.cpp
-#: 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
+#: scene/3d/visual_instance.cpp 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 "Μετατόπιση:"
@@ -14747,17 +14748,17 @@ msgid "Invalid project path (changed anything?)."
msgstr "Μη έγκυÏη διαδÏομή έÏγου (Αλλάξατε τίποτα;)."
#: editor/project_manager.cpp
+#, fuzzy
msgid ""
-"Couldn't load project.godot in project path (error %d). It may be missing or "
-"corrupted."
+"Couldn't load project at '%s' (error %d). It may be missing or corrupted."
msgstr ""
"ΑδÏνατη η φόÏτωση του project.godot (σφάλμα %d). ΜποÏεί να λείπει ή να είναι "
"κατεστÏαμένο."
#: editor/project_manager.cpp
-msgid "Couldn't edit project.godot in project path."
-msgstr ""
-"Δεν ήταν δυνατή η επεξεÏγασία του project.godot στη διαδÏομή του έÏγου."
+#, fuzzy
+msgid "Couldn't save project at '%s' (error %d)."
+msgstr "Αδυνατό το άνοιγμα του έÏγου στο «%s»."
#: editor/project_manager.cpp
msgid "Couldn't create project.godot in project path."
@@ -24321,6 +24322,15 @@ msgstr "Σφάλμα"
msgid "AABB"
msgstr ""
+#: scene/3d/visual_instance.cpp
+#, fuzzy
+msgid "Sorting"
+msgstr "Ταξινόμηση"
+
+#: scene/3d/visual_instance.cpp
+msgid "Use AABB Center"
+msgstr ""
+
#: scene/3d/visual_instance.cpp scene/resources/navigation_mesh.cpp
#, fuzzy
msgid "Geometry"
diff --git a/editor/translations/en_Shaw.po b/editor/translations/en_Shaw.po
index 63ce9ca3d5..60caed0d9d 100644
--- a/editor/translations/en_Shaw.po
+++ b/editor/translations/en_Shaw.po
@@ -12406,9 +12406,10 @@ msgstr "ð‘¨ð‘¯ð‘¦ð‘¥ð‘±ð‘–ð‘©ð‘¯ ð‘¤ð‘µð‘ð‘¦ð‘™"
#: scene/2d/path_2d.cpp scene/2d/polygon_2d.cpp scene/2d/sprite.cpp
#: scene/3d/cpu_particles.cpp scene/3d/label_3d.cpp scene/3d/path.cpp
#: scene/3d/physics_body.cpp scene/3d/soft_body.cpp scene/3d/sprite_3d.cpp
-#: 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
+#: scene/3d/visual_instance.cpp 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
msgid "Offset"
msgstr ""
@@ -13745,12 +13746,11 @@ msgstr ""
#: editor/project_manager.cpp
msgid ""
-"Couldn't load project.godot in project path (error %d). It may be missing or "
-"corrupted."
+"Couldn't load project at '%s' (error %d). It may be missing or corrupted."
msgstr ""
#: editor/project_manager.cpp
-msgid "Couldn't edit project.godot in project path."
+msgid "Couldn't save project at '%s' (error %d)."
msgstr ""
#: editor/project_manager.cpp
@@ -22359,6 +22359,15 @@ msgstr "ð‘¥ð‘¦ð‘®ð‘¼"
msgid "AABB"
msgstr ""
+#: scene/3d/visual_instance.cpp
+#, fuzzy
+msgid "Sorting"
+msgstr "ð‘¦ð‘¯ð‘‘ð‘»ð‘ð‘©ð‘¤ð‘±ð‘–ð‘©ð‘¯ ð‘¥ð‘´ð‘›"
+
+#: scene/3d/visual_instance.cpp
+msgid "Use AABB Center"
+msgstr ""
+
#: scene/3d/visual_instance.cpp scene/resources/navigation_mesh.cpp
msgid "Geometry"
msgstr ""
diff --git a/editor/translations/eo.po b/editor/translations/eo.po
index 2bcbc62274..04205e10d6 100644
--- a/editor/translations/eo.po
+++ b/editor/translations/eo.po
@@ -13088,9 +13088,10 @@ msgstr "Opcioj de kaptado"
#: scene/2d/path_2d.cpp scene/2d/polygon_2d.cpp scene/2d/sprite.cpp
#: scene/3d/cpu_particles.cpp scene/3d/label_3d.cpp scene/3d/path.cpp
#: scene/3d/physics_body.cpp scene/3d/soft_body.cpp scene/3d/sprite_3d.cpp
-#: 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
+#: scene/3d/visual_instance.cpp 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 "Krada deÅovo:"
@@ -14472,16 +14473,17 @@ msgid "Invalid project path (changed anything?)."
msgstr "Nevalida dosierindiko de projekto (ÅanÄis ion ajn?)."
#: editor/project_manager.cpp
+#, fuzzy
msgid ""
-"Couldn't load project.godot in project path (error %d). It may be missing or "
-"corrupted."
+"Couldn't load project at '%s' (error %d). It may be missing or corrupted."
msgstr ""
"Ne eblas Åargi project.godot en projekta dosierindiko (eraro %d). Äœi eble "
"estas manka aÅ­ difektita."
#: editor/project_manager.cpp
-msgid "Couldn't edit project.godot in project path."
-msgstr "Ne eblas redakti project.godot en projekta dosierindiko."
+#, fuzzy
+msgid "Couldn't save project at '%s' (error %d)."
+msgstr "Ne eblas malfermi projekton ĉe '%s'."
#: editor/project_manager.cpp
msgid "Couldn't create project.godot in project path."
@@ -23733,6 +23735,15 @@ msgstr "Eraro!"
msgid "AABB"
msgstr ""
+#: scene/3d/visual_instance.cpp
+#, fuzzy
+msgid "Sorting"
+msgstr "Enportas:"
+
+#: scene/3d/visual_instance.cpp
+msgid "Use AABB Center"
+msgstr ""
+
#: scene/3d/visual_instance.cpp scene/resources/navigation_mesh.cpp
#, fuzzy
msgid "Geometry"
diff --git a/editor/translations/es.po b/editor/translations/es.po
index 629b36eea7..5d683058c3 100644
--- a/editor/translations/es.po
+++ b/editor/translations/es.po
@@ -43,7 +43,7 @@
# Dario <darlex259@gmail.com>, 2019.
# Adolfo Jayme Barrientos <fitojb@ubuntu.com>, 2019.
# Julián Luini <jluini@gmail.com>, 2020.
-# Victor S. <victorstancioiu@gmail.com>, 2020, 2021.
+# Victor S. <victorstancioiu@gmail.com>, 2020, 2021, 2022.
# henry rujano herrera <rujhen@gmail.com>, 2020.
# Megamega53 <Christopher.Morales21@myhunter.cuny.edu>, 2020.
# Serk Lintur <serk.lintur@gmail.com>, 2020.
@@ -60,7 +60,7 @@
# Lucasdelpiero <lucasdelpiero98@gmail.com>, 2021.
# SteamGoblin <SteamGoblin860@gmail.com>, 2021.
# Francisco C <pruebasfrancisco17@gmail.com>, 2021.
-# Cam <cameron.toms@gmail.com>, 2021.
+# Cam <cameron.toms@gmail.com>, 2021, 2022.
# Juan camilo <jugarciago01@gmail.com>, 2021.
# Manuel González <mgoopazo@gmail.com>, 2021.
# softonicblip <blazeawardspace@gmail.com>, 2021.
@@ -89,12 +89,14 @@
# Fernando Joaquin Manzano Lopez <ticantin12@gmail.com>, 2022.
# M3CG <cgmario1999@gmail.com>, 2022.
# Chalan <Valentin06ch@outlook.com>, 2022.
+# Luis Miguel Soto Sánchez <luismiguelsoto@jerez.es>, 2022.
+# Victor Stancioiu <victorstancioiu@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-09-27 21:37+0000\n"
+"PO-Revision-Date: 2022-11-16 22:47+0000\n"
"Last-Translator: Javier Ocampos <xavier.ocampos@gmail.com>\n"
"Language-Team: Spanish <https://hosted.weblate.org/projects/godot-engine/"
"godot/es/>\n"
@@ -103,7 +105,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.14.1\n"
+"X-Generator: Weblate 4.15-dev\n"
#: core/bind/core_bind.cpp main/main.cpp
msgid "Tablet Driver"
@@ -9706,7 +9708,7 @@ msgstr ""
#: editor/plugins/mesh_instance_editor_plugin.cpp
msgid "Create Simplified Convex Collision Sibling"
-msgstr "Crear Forma de Colisión Conexa Hermana"
+msgstr "Crear Collider Conexo Hermano"
#: editor/plugins/mesh_instance_editor_plugin.cpp
msgid ""
@@ -12886,9 +12888,10 @@ msgstr "Opciones de Ajuste"
#: scene/2d/path_2d.cpp scene/2d/polygon_2d.cpp scene/2d/sprite.cpp
#: scene/3d/cpu_particles.cpp scene/3d/label_3d.cpp scene/3d/path.cpp
#: scene/3d/physics_body.cpp scene/3d/soft_body.cpp scene/3d/sprite_3d.cpp
-#: 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
+#: scene/3d/visual_instance.cpp 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
msgid "Offset"
msgstr "Offset"
@@ -14305,16 +14308,17 @@ msgid "Invalid project path (changed anything?)."
msgstr "La ruta del proyecto no es correcta (¿has cambiado algo?)."
#: editor/project_manager.cpp
+#, fuzzy
msgid ""
-"Couldn't load project.godot in project path (error %d). It may be missing or "
-"corrupted."
+"Couldn't load project at '%s' (error %d). It may be missing or corrupted."
msgstr ""
"No se pudo cargar project.godot desde la ruta de proyecto (error %d). La "
"ruta no existe o está corrupta."
#: editor/project_manager.cpp
-msgid "Couldn't edit project.godot in project path."
-msgstr "No se pudo editar project.godot en la ruta del proyecto."
+#, fuzzy
+msgid "Couldn't save project at '%s' (error %d)."
+msgstr "No se puede abrir el proyecto en '%s'."
#: editor/project_manager.cpp
msgid "Couldn't create project.godot in project path."
@@ -16336,7 +16340,7 @@ msgstr "Imprimir FPS"
#: main/main.cpp
msgid "Verbose stdout"
-msgstr ""
+msgstr "Stdout Extendido"
#: main/main.cpp scene/main/scene_tree.cpp scene/resources/multimesh.cpp
msgid "Physics Interpolation"
@@ -16507,7 +16511,7 @@ msgstr "Aceptar Cierre Del Programa Automáticamente"
#: main/main.cpp scene/main/scene_tree.cpp
msgid "Quit On Go Back"
-msgstr "Salir y Regresar"
+msgstr "Salir al Ir Atrás"
#: main/main.cpp scene/main/viewport.cpp
msgid "Snap Controls To Pixels"
@@ -19557,7 +19561,7 @@ msgstr "Depuración"
#: platform/osx/export/export.cpp
msgid "App Sandbox"
-msgstr "App Sandbox"
+msgstr "Sandbox de App"
#: platform/osx/export/export.cpp
msgid "Network Server"
@@ -19675,6 +19679,8 @@ msgid ""
"Could not start codesign executable, make sure Xcode command line tools are "
"installed."
msgstr ""
+"No se ha podido iniciar el ejecutable de codificación, asegúrate de que las "
+"herramientas de línea de comandos de Xcode están instaladas."
#: platform/osx/export/export.cpp platform/windows/export/export.cpp
msgid "No identity found."
@@ -19700,11 +19706,11 @@ msgstr "No se ha podido iniciar el ejecutable hdiutil."
#: platform/osx/export/export.cpp
msgid "`hdiutil create` failed - file exists."
-msgstr ""
+msgstr "`hdiutil create` falló - el archivo ya existe."
#: platform/osx/export/export.cpp
msgid "`hdiutil create` failed."
-msgstr ""
+msgstr "`hdiutil create` falló."
#: platform/osx/export/export.cpp
msgid "Creating app bundle"
@@ -19918,11 +19924,11 @@ msgstr ""
#: platform/osx/export/export.cpp
msgid "macOS"
-msgstr ""
+msgstr "macOS"
#: platform/osx/export/export.cpp
msgid "Force Builtin Codesign"
-msgstr ""
+msgstr "Forzar Codificación Integrada"
#: platform/uwp/export/export.cpp
msgid "Architecture"
@@ -19938,7 +19944,7 @@ msgstr "Nombre Corto"
#: platform/uwp/export/export.cpp
msgid "Publisher"
-msgstr ""
+msgstr "Editor"
#: platform/uwp/export/export.cpp
msgid "Publisher Display Name"
@@ -19966,11 +19972,11 @@ msgstr "Algoritmo"
#: platform/uwp/export/export.cpp
msgid "Major"
-msgstr ""
+msgstr "Mayor"
#: platform/uwp/export/export.cpp
msgid "Minor"
-msgstr ""
+msgstr "Menor"
#: platform/uwp/export/export.cpp
msgid "Build"
@@ -19982,7 +19988,7 @@ msgstr "Revisión"
#: platform/uwp/export/export.cpp
msgid "Landscape"
-msgstr ""
+msgstr "Landscape"
#: platform/uwp/export/export.cpp
msgid "Portrait"
@@ -19990,11 +19996,11 @@ msgstr "Retrato"
#: platform/uwp/export/export.cpp
msgid "Landscape Flipped"
-msgstr ""
+msgstr "Landscape Volteado"
#: platform/uwp/export/export.cpp
msgid "Portrait Flipped"
-msgstr ""
+msgstr "Retrato Invertido"
#: platform/uwp/export/export.cpp
msgid "Store Logo"
@@ -20002,23 +20008,23 @@ msgstr "Logo de Tienda"
#: platform/uwp/export/export.cpp
msgid "Square 44 X 44 Logo"
-msgstr ""
+msgstr "Logo Cuadrado 44 X 44"
#: platform/uwp/export/export.cpp
msgid "Square 71 X 71 Logo"
-msgstr ""
+msgstr "Logo Cuadrado 71 X 71"
#: platform/uwp/export/export.cpp
msgid "Square 150 X 150 Logo"
-msgstr ""
+msgstr "Logo Cuadrado 150 X 150"
#: platform/uwp/export/export.cpp
msgid "Square 310 X 310 Logo"
-msgstr ""
+msgstr "Logo Cuadrado 310x310"
#: platform/uwp/export/export.cpp
msgid "Wide 310 X 150 Logo"
-msgstr ""
+msgstr "Logotipo Panorámico 310 X 150"
#: platform/uwp/export/export.cpp
msgid "Splash Screen"
@@ -20030,15 +20036,15 @@ msgstr "Tiles"
#: platform/uwp/export/export.cpp
msgid "Show Name On Square 150 X 150"
-msgstr ""
+msgstr "Mostrar Nombre en Cuadrado 150 X 150"
#: platform/uwp/export/export.cpp
msgid "Show Name On Wide 310 X 150"
-msgstr ""
+msgstr "Mostrar Nombre en Panorámico 310 X 150"
#: platform/uwp/export/export.cpp
msgid "Show Name On Square 310 X 310"
-msgstr ""
+msgstr "Mostrar Nombre en Cuadrado 310 X 310"
#: platform/uwp/export/export.cpp
msgid ""
@@ -20113,7 +20119,7 @@ msgstr ""
#: platform/uwp/export/export.cpp
msgid "UWP"
-msgstr ""
+msgstr "UWP"
#: platform/uwp/export/export.cpp platform/windows/export/export.cpp
msgid "Signtool"
@@ -20121,7 +20127,7 @@ msgstr "Signtool"
#: platform/uwp/export/export.cpp
msgid "Debug Certificate"
-msgstr ""
+msgstr "Certificado de Depuración"
#: platform/uwp/export/export.cpp
msgid "Debug Algorithm"
@@ -20133,11 +20139,11 @@ msgstr "Fallo al renombrar el archivo temporal \"%s\"."
#: platform/windows/export/export.cpp
msgid "Identity Type"
-msgstr ""
+msgstr "Tipo de Identidad"
#: platform/windows/export/export.cpp
msgid "Timestamp Server URL"
-msgstr ""
+msgstr "URL del Servidor de Marcas de Tiempo"
#: platform/windows/export/export.cpp
msgid "Digest Algorithm"
@@ -20169,7 +20175,7 @@ msgstr "Descripción del Archivo"
#: platform/windows/export/export.cpp
msgid "Trademarks"
-msgstr ""
+msgstr "Marcas comerciales"
#: platform/windows/export/export.cpp
msgid "Resources Modification"
@@ -20254,7 +20260,7 @@ msgstr "Versión de producto no válida:"
#: platform/windows/export/export.cpp
msgid "Windows executables cannot be >= 4 GiB."
-msgstr ""
+msgstr "Los ejecutables de Windows no pueden ser >= 4 GiB."
#: platform/windows/export/export.cpp platform/x11/export/export.cpp
msgid "Failed to open executable file \"%s\"."
@@ -20262,11 +20268,11 @@ msgstr "Fallo al abrir el archivo ejecutable \"%s\"."
#: platform/windows/export/export.cpp platform/x11/export/export.cpp
msgid "Executable file header corrupted."
-msgstr ""
+msgstr "La cabecera del archivo ejecutable está corrupta."
#: platform/windows/export/export.cpp platform/x11/export/export.cpp
msgid "Executable \"pck\" section not found."
-msgstr ""
+msgstr "No se encuentra la sección ejecutable \"pck\"."
#: platform/windows/export/export.cpp
msgid "Windows"
@@ -20274,19 +20280,19 @@ 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 ""
+msgstr "Los ejecutables de 32 bits no pueden tener datos embebidos >= 4 GiB."
#: scene/2d/animated_sprite.cpp scene/3d/sprite_3d.cpp
#: scene/resources/texture.cpp
@@ -20319,12 +20325,12 @@ 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
msgid "Flip H"
-msgstr ""
+msgstr "Voltear 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 "Voltear V"
#: scene/2d/area_2d.cpp scene/3d/area.cpp
msgid "Monitoring"
@@ -20357,7 +20363,7 @@ 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
msgid "Gravity"
-msgstr ""
+msgstr "Gravedad"
#: scene/2d/area_2d.cpp scene/3d/area.cpp
msgid "Linear Damp"
@@ -20365,7 +20371,7 @@ msgstr "Amortiguación Lineal"
#: scene/2d/area_2d.cpp scene/3d/area.cpp
msgid "Angular Damp"
-msgstr ""
+msgstr "Amortiguación Angular"
#: scene/2d/area_2d.cpp scene/3d/area.cpp
msgid "Audio Bus"
@@ -20394,7 +20400,7 @@ 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
msgid "Stream Paused"
-msgstr ""
+msgstr "Stream Pausado"
#: scene/2d/audio_stream_player_2d.cpp scene/3d/audio_stream_player_3d.cpp
#: scene/3d/light.cpp scene/3d/reflection_probe.cpp
@@ -20414,7 +20420,7 @@ msgstr "Bus"
#: scene/2d/audio_stream_player_2d.cpp scene/3d/audio_stream_player_3d.cpp
msgid "Area Mask"
-msgstr ""
+msgstr "Máscara de Ãrea"
#: scene/2d/back_buffer_copy.cpp
msgid "Copy Mode"
@@ -20489,7 +20495,7 @@ msgstr "Suavizar"
#: scene/2d/camera_2d.cpp
msgid "H"
-msgstr ""
+msgstr "H"
#: scene/2d/camera_2d.cpp
msgid "V"
@@ -20526,11 +20532,11 @@ msgstr "Animación de Partículas"
#: scene/2d/canvas_item.cpp
msgid "Particles Anim H Frames"
-msgstr ""
+msgstr "Animación de partículas Fotogramas H"
#: scene/2d/canvas_item.cpp
msgid "Particles Anim V Frames"
-msgstr ""
+msgstr "Animación de partículas Fotogramas V"
#: scene/2d/canvas_item.cpp
msgid "Particles Anim Loop"
@@ -20551,7 +20557,7 @@ msgstr "Modulación Automática"
#: scene/2d/canvas_item.cpp
msgid "Show Behind Parent"
-msgstr ""
+msgstr "Mostrar detrás del padre"
#: scene/2d/canvas_item.cpp
msgid "Show On Top"
@@ -20564,7 +20570,7 @@ msgstr "Máscara de Luz"
#: scene/2d/canvas_item.cpp
msgid "Use Parent Material"
-msgstr ""
+msgstr "Usar el material del padre"
#: scene/2d/canvas_modulate.cpp
msgid ""
@@ -20686,7 +20692,7 @@ msgstr "Emitiendo"
#: scene/2d/cpu_particles_2d.cpp scene/2d/particles_2d.cpp
#: scene/3d/cpu_particles.cpp scene/3d/particles.cpp
msgid "Lifetime"
-msgstr ""
+msgstr "Tiempo de vida"
#: scene/2d/cpu_particles_2d.cpp scene/2d/particles_2d.cpp
#: scene/3d/cpu_particles.cpp scene/3d/particles.cpp scene/main/timer.cpp
@@ -20701,7 +20707,7 @@ msgstr "Preproceso"
#: scene/2d/cpu_particles_2d.cpp scene/2d/particles_2d.cpp
#: scene/3d/cpu_particles.cpp scene/3d/particles.cpp
msgid "Explosiveness"
-msgstr ""
+msgstr "Explosividad"
#: scene/2d/cpu_particles_2d.cpp scene/2d/particles_2d.cpp
#: scene/3d/cpu_particles.cpp scene/3d/particles.cpp
@@ -20711,7 +20717,7 @@ msgstr "Aleatoriedad"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
msgid "Lifetime Randomness"
-msgstr ""
+msgstr "Aleatoriedad para siempre"
#: scene/2d/cpu_particles_2d.cpp scene/2d/particles_2d.cpp
#: scene/3d/cpu_particles.cpp scene/3d/particles.cpp
@@ -20721,12 +20727,12 @@ msgstr "FPS Fijos"
#: scene/2d/cpu_particles_2d.cpp scene/2d/particles_2d.cpp
#: scene/3d/cpu_particles.cpp scene/3d/particles.cpp
msgid "Fract Delta"
-msgstr ""
+msgstr "Fracción Delta"
#: scene/2d/cpu_particles_2d.cpp scene/2d/particles_2d.cpp
#: scene/3d/cpu_particles.cpp scene/3d/particles.cpp
msgid "Drawing"
-msgstr ""
+msgstr "Dibujo"
#: scene/2d/cpu_particles_2d.cpp scene/2d/particles_2d.cpp
#: scene/3d/cpu_particles.cpp scene/3d/particles.cpp
@@ -20736,7 +20742,7 @@ msgstr "Coordenadas 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 "Orden de dibujo"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
@@ -20770,7 +20776,7 @@ msgstr "Dirección"
#: scene/resources/particles_material.cpp
#: servers/audio/effects/audio_effect_reverb.cpp
msgid "Spread"
-msgstr ""
+msgstr "Propagación"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
@@ -20786,7 +20792,7 @@ msgstr "Velocidad Aleatoria"
#: scene/resources/particles_material.cpp servers/physics_2d_server.cpp
#: servers/physics_server.cpp
msgid "Angular Velocity"
-msgstr ""
+msgstr "Velocidad angular"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
@@ -20811,7 +20817,7 @@ msgstr "Aceleración"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
msgid "Accel Random"
-msgstr ""
+msgstr "Aceleración aleatoria"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
@@ -20821,12 +20827,12 @@ msgstr "Curva de Aceleración"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
msgid "Radial Accel"
-msgstr ""
+msgstr "Aceleración radial"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
msgid "Tangential Accel"
-msgstr ""
+msgstr "Aceleración tangencial"
#: scene/2d/cpu_particles_2d.cpp scene/2d/joints_2d.cpp
#: scene/3d/cpu_particles.cpp scene/3d/physics_body.cpp
@@ -20834,12 +20840,12 @@ msgstr ""
#: scene/resources/particles_material.cpp
#: servers/audio/effects/audio_effect_reverb.cpp
msgid "Damping"
-msgstr ""
+msgstr "Amortiguación"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
msgid "Damping Random"
-msgstr ""
+msgstr "Amortiguación Aleatoria"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
@@ -20849,12 +20855,12 @@ 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
msgid "Angle"
-msgstr ""
+msgstr "Ãngulo"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
msgid "Angle Random"
-msgstr ""
+msgstr "Ãngulo aleatorio"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
@@ -20867,7 +20873,7 @@ msgstr "Cantidad de Escala"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
msgid "Scale Amount Random"
-msgstr ""
+msgstr "Cantidad de escalado aleatoria"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
msgid "Scale Amount Curve"
@@ -20881,7 +20887,7 @@ msgstr "Rampa de Color"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
msgid "Color Initial Ramp"
-msgstr ""
+msgstr "Color Rampa Inicial"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
@@ -20955,7 +20961,7 @@ msgstr "Nodo B"
#: scene/3d/light.cpp scene/3d/physics_body.cpp scene/3d/physics_joint.cpp
#: scene/resources/environment.cpp
msgid "Bias"
-msgstr ""
+msgstr "Tendencia"
#: scene/2d/joints_2d.cpp
msgid "Disable Collision"
@@ -20963,12 +20969,12 @@ msgstr "Desactivar Colisión"
#: scene/2d/joints_2d.cpp scene/3d/physics_body.cpp scene/3d/physics_joint.cpp
msgid "Softness"
-msgstr ""
+msgstr "Suavidad"
#: scene/2d/joints_2d.cpp scene/resources/animation.cpp
#: scene/resources/ray_shape.cpp scene/resources/segment_shape_2d.cpp
msgid "Length"
-msgstr ""
+msgstr "Longitud"
#: scene/2d/joints_2d.cpp
msgid "Initial Offset"
@@ -20976,11 +20982,11 @@ msgstr "Offset Inicial"
#: scene/2d/joints_2d.cpp scene/3d/vehicle_body.cpp
msgid "Rest Length"
-msgstr ""
+msgstr "Duración de Reposo"
#: scene/2d/joints_2d.cpp scene/3d/physics_joint.cpp scene/3d/vehicle_body.cpp
msgid "Stiffness"
-msgstr ""
+msgstr "Rigidez"
#: scene/2d/light_2d.cpp
msgid ""
@@ -21002,15 +21008,15 @@ msgstr "Escala de Textura"
#: scene/3d/light.cpp scene/resources/environment.cpp
#: scene/resources/material.cpp scene/resources/sky.cpp
msgid "Energy"
-msgstr ""
+msgstr "Energía"
#: scene/2d/light_2d.cpp
msgid "Z Min"
-msgstr ""
+msgstr "Z Mín"
#: scene/2d/light_2d.cpp
msgid "Z Max"
-msgstr ""
+msgstr "Z Máx"
#: scene/2d/light_2d.cpp
msgid "Layer Min"
@@ -21022,7 +21028,7 @@ msgstr "Capa Máxima"
#: scene/2d/light_2d.cpp
msgid "Item Cull Mask"
-msgstr ""
+msgstr "Ãtem Cull Mask"
#: scene/2d/light_2d.cpp scene/3d/light.cpp scene/resources/style_box.cpp
msgid "Shadow"
@@ -21103,11 +21109,11 @@ msgstr "Borde"
#: scene/2d/line_2d.cpp
msgid "Sharp Limit"
-msgstr ""
+msgstr "Límite de nitidez"
#: scene/2d/line_2d.cpp
msgid "Round Precision"
-msgstr ""
+msgstr "Precisión redondeada"
#: scene/2d/line_2d.cpp scene/2d/polygon_2d.cpp
#: scene/resources/dynamic_font.cpp
@@ -21122,7 +21128,7 @@ msgstr "Multimesh"
#: 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 "Tamaño de la casilla"
#: scene/2d/navigation_2d.cpp scene/3d/navigation.cpp
msgid "Edge Connection Margin"
@@ -21134,6 +21140,9 @@ msgid ""
"will be removed in a future version. Use 'Navigation2DServer.map_get_path()' "
"instead."
msgstr ""
+"El nodo 'Navigation2D' y 'Navigation2D.get_simple_path()' están deprecados y "
+"serán eliminados en una versión future. En su lugar, usa 'Navigation2DServer."
+"map_get_path()'."
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
msgid "Pathfinding"
@@ -21328,7 +21337,7 @@ msgstr "Visibilidad Rect"
#: scene/2d/particles_2d.cpp scene/3d/particles.cpp
msgid "Process Material"
-msgstr ""
+msgstr "Material de Proceso"
#: scene/2d/path_2d.cpp scene/3d/path.cpp scene/resources/sky.cpp
#: scene/resources/texture.cpp
@@ -21354,11 +21363,11 @@ msgstr "Offset V"
#: scene/2d/path_2d.cpp scene/3d/path.cpp
msgid "Cubic Interp"
-msgstr ""
+msgstr "Interp. Cúbica"
#: scene/2d/path_2d.cpp
msgid "Lookahead"
-msgstr ""
+msgstr "Preveer"
#: scene/2d/physics_body_2d.cpp scene/3d/visual_instance.cpp
msgid "Layers"
@@ -21380,11 +21389,11 @@ msgstr "Fricción"
#: 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 "Rebotar"
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
msgid "Physics Material Override"
-msgstr ""
+msgstr "Reemplazar el material de físicas"
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
#: scene/resources/world.cpp scene/resources/world_2d.cpp
@@ -21403,7 +21412,7 @@ msgstr ""
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
msgid "Mass"
-msgstr ""
+msgstr "Masa"
#: scene/2d/physics_body_2d.cpp
msgid "Inertia"
@@ -21415,7 +21424,7 @@ msgstr "Peso"
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
msgid "Gravity Scale"
-msgstr ""
+msgstr "Escala de gravedad"
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
msgid "Custom Integrator"
@@ -21427,7 +21436,7 @@ msgstr "CD Continuo"
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
msgid "Contacts Reported"
-msgstr ""
+msgstr "Contactos reportados"
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
msgid "Contact Monitor"
@@ -21444,19 +21453,19 @@ msgstr "Puede Dormir"
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
msgid "Damp"
-msgstr ""
+msgstr "Humedad"
#: 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"
-msgstr ""
+msgstr "Fuerzas aplicadas"
#: scene/2d/physics_body_2d.cpp
msgid "Torque"
-msgstr ""
+msgstr "Torsión"
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
msgid "Safe Margin"
@@ -21472,7 +21481,7 @@ msgstr "Plataforma Móvil"
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
msgid "Apply Velocity On Leave"
-msgstr ""
+msgstr "Aplicar velocidad al salir"
#: scene/2d/physics_body_2d.cpp scene/2d/touch_screen_button.cpp
#: scene/3d/physics_body.cpp scene/gui/texture_button.cpp
@@ -21497,7 +21506,7 @@ msgstr "Colisionador"
#: 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 de colisionador"
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
#: servers/physics_2d_server.cpp servers/physics_server.cpp
@@ -21520,11 +21529,11 @@ msgstr "Velocidad del Colisionador"
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
msgid "Collider Metadata"
-msgstr ""
+msgstr "Metadatos del colisionador"
#: scene/2d/polygon_2d.cpp
msgid "Invert"
-msgstr ""
+msgstr "Invertir"
#: scene/2d/polygon_2d.cpp
msgid "Vertex Colors"
@@ -21540,7 +21549,7 @@ msgstr "Extensión de Gizmos"
#: scene/2d/ray_cast_2d.cpp scene/3d/ray_cast.cpp
msgid "Exclude Parent"
-msgstr ""
+msgstr "Excluir Padre"
#: scene/2d/ray_cast_2d.cpp scene/3d/ray_cast.cpp
msgid "Cast To"
@@ -21548,15 +21557,15 @@ msgstr "Lanzar A"
#: scene/2d/ray_cast_2d.cpp scene/3d/ray_cast.cpp
msgid "Collide With"
-msgstr ""
+msgstr "Colisionar con"
#: 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 "Cuerpos"
#: scene/2d/remote_transform_2d.cpp
msgid "Path property must point to a valid Node2D node to work."
@@ -21596,11 +21605,11 @@ msgstr ""
#: scene/2d/sprite.cpp scene/3d/sprite_3d.cpp
msgid "Hframes"
-msgstr ""
+msgstr "Fotogramas H"
#: scene/2d/sprite.cpp scene/3d/sprite_3d.cpp
msgid "Vframes"
-msgstr ""
+msgstr "Fotogramas V"
#: scene/2d/sprite.cpp scene/3d/sprite_3d.cpp
msgid "Frame Coords"
@@ -21658,7 +21667,7 @@ msgstr "Texturas Centradas"
#: scene/2d/tile_map.cpp
msgid "Cell Clip UV"
-msgstr ""
+msgstr "Clip de Celda UV"
#: scene/2d/tile_map.cpp
msgid "Use Parent"
@@ -21666,7 +21675,7 @@ msgstr "Usar Padres"
#: scene/2d/tile_map.cpp
msgid "Use Kinematic"
-msgstr ""
+msgstr "Usar cinemática"
#: scene/2d/touch_screen_button.cpp
msgid "Shape Centered"
@@ -21678,7 +21687,7 @@ msgstr "Forma Visible"
#: scene/2d/touch_screen_button.cpp
msgid "Passby Press"
-msgstr ""
+msgstr "Prensa de paso"
#: scene/2d/touch_screen_button.cpp
msgid "Visibility Mode"
@@ -21698,7 +21707,7 @@ msgstr "Pausar Animaciones"
#: scene/2d/visibility_notifier_2d.cpp scene/3d/visibility_notifier.cpp
msgid "Freeze Bodies"
-msgstr ""
+msgstr "Congelar cuerpos"
#: scene/2d/visibility_notifier_2d.cpp
msgid "Pause Particles"
@@ -21714,11 +21723,11 @@ msgstr "Procesamiento de los Padres"
#: scene/2d/visibility_notifier_2d.cpp
msgid "Physics Process Parent"
-msgstr ""
+msgstr "Procesado de Físicas Padre"
#: scene/3d/area.cpp
msgid "Reverb Bus"
-msgstr ""
+msgstr "Bus de reverberación"
#: scene/3d/area.cpp
msgid "Uniformity"
@@ -21730,11 +21739,11 @@ msgstr "ARVRCamera tiene que tener un nodo ARVROrigin como padre."
#: scene/3d/arvr_nodes.cpp
msgid "Controller ID"
-msgstr ""
+msgstr "ID del controlador"
#: scene/3d/arvr_nodes.cpp servers/arvr/arvr_positional_tracker.cpp
msgid "Rumble"
-msgstr ""
+msgstr "Retumbar"
#: scene/3d/arvr_nodes.cpp
msgid "ARVRController must have an ARVROrigin node as its parent."
@@ -21778,19 +21787,19 @@ msgstr "Modelo de Atenuación"
#: scene/3d/audio_stream_player_3d.cpp
msgid "Unit dB"
-msgstr ""
+msgstr "dB de la unidad"
#: scene/3d/audio_stream_player_3d.cpp
msgid "Unit Size"
-msgstr ""
+msgstr "Tamaño de la unidad"
#: scene/3d/audio_stream_player_3d.cpp
msgid "Max dB"
-msgstr ""
+msgstr "dB Máx"
#: scene/3d/audio_stream_player_3d.cpp
msgid "Out Of Range Mode"
-msgstr ""
+msgstr "Modo fuera de rango"
#: scene/3d/audio_stream_player_3d.cpp
msgid "Emission Angle"
@@ -21806,13 +21815,13 @@ msgstr "Filtro de Atenuación dB"
#: scene/3d/audio_stream_player_3d.cpp
msgid "Attenuation Filter"
-msgstr ""
+msgstr "Filtro de atenuación"
#: scene/3d/audio_stream_player_3d.cpp
#: servers/audio/effects/audio_effect_chorus.cpp
#: servers/audio/effects/audio_effect_filter.cpp
msgid "Cutoff Hz"
-msgstr ""
+msgstr "Hz de cierre"
#: scene/3d/audio_stream_player_3d.cpp
#: servers/audio/effects/audio_effect_filter.cpp
@@ -21830,7 +21839,7 @@ msgstr "Seguimiento"
#: 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"
@@ -21864,15 +21873,15 @@ msgstr "Extensiones"
#: scene/3d/baked_lightmap.cpp
msgid "Tweaks"
-msgstr ""
+msgstr "Retoques"
#: scene/3d/baked_lightmap.cpp
msgid "Bounces"
-msgstr ""
+msgstr "Rebotes"
#: scene/3d/baked_lightmap.cpp
msgid "Bounce Indirect Energy"
-msgstr ""
+msgstr "Energía indirecta del rebote"
#: scene/3d/baked_lightmap.cpp
msgid "Use Denoiser"
@@ -21880,7 +21889,7 @@ msgstr "Usar Eliminador de Ruido"
#: scene/3d/baked_lightmap.cpp scene/resources/texture.cpp
msgid "Use HDR"
-msgstr ""
+msgstr "Usar HDR"
#: scene/3d/baked_lightmap.cpp
msgid "Use Color"
@@ -21940,11 +21949,11 @@ msgstr "Nombre del Hueso"
#: scene/3d/camera.cpp
msgid "Keep Aspect"
-msgstr ""
+msgstr "Mantener aspecto"
#: scene/3d/camera.cpp scene/3d/light.cpp scene/3d/reflection_probe.cpp
msgid "Cull Mask"
-msgstr ""
+msgstr "Cull Mask"
#: scene/3d/camera.cpp
msgid "Doppler Tracking"
@@ -21956,7 +21965,7 @@ msgstr "Proyección"
#: scene/3d/camera.cpp
msgid "FOV"
-msgstr ""
+msgstr "FOV"
#: scene/3d/camera.cpp
msgid "Frustum Offset"
@@ -21968,7 +21977,7 @@ msgstr "Cercano"
#: scene/3d/camera.cpp
msgid "Far"
-msgstr ""
+msgstr "Lejos"
#: 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
@@ -21984,7 +21993,7 @@ msgstr "Recortar A"
#: scene/3d/collision_object.cpp scene/3d/soft_body.cpp
msgid "Ray Pickable"
-msgstr ""
+msgstr "Seleccionable por Rayo"
#: scene/3d/collision_object.cpp
msgid "Capture On Drag"
@@ -22089,7 +22098,7 @@ msgstr "Desactivar Z"
#: scene/3d/cpu_particles.cpp scene/resources/particles_material.cpp
msgid "Flatness"
-msgstr ""
+msgstr "Llanura"
#: scene/3d/cull_instance.cpp servers/visual_server.cpp
msgid "Portals"
@@ -22101,11 +22110,11 @@ msgstr "Modo Portal"
#: scene/3d/cull_instance.cpp
msgid "Include In Bound"
-msgstr ""
+msgstr "Incluir en límite"
#: scene/3d/cull_instance.cpp
msgid "Allow Merging"
-msgstr ""
+msgstr "Permitir fusión"
#: scene/3d/cull_instance.cpp
msgid "Autoplace Priority"
@@ -22139,7 +22148,7 @@ msgstr ""
#: scene/3d/gi_probe.cpp
msgid "Subdiv"
-msgstr ""
+msgstr "Subdividir"
#: scene/3d/gi_probe.cpp
msgid "Dynamic Range"
@@ -22147,7 +22156,7 @@ msgstr "Rango Dinámico"
#: scene/3d/gi_probe.cpp scene/3d/light.cpp
msgid "Normal Bias"
-msgstr ""
+msgstr "Tendencia normal"
#: scene/3d/label_3d.cpp scene/3d/sprite_3d.cpp
#: scene/resources/primitive_meshes.cpp
@@ -22156,7 +22165,7 @@ msgstr "Tamaño de Píxeles"
#: scene/3d/label_3d.cpp scene/3d/sprite_3d.cpp
msgid "Billboard"
-msgstr ""
+msgstr "Billboard"
#: scene/3d/label_3d.cpp scene/3d/sprite_3d.cpp
msgid "Shaded"
@@ -22164,11 +22173,11 @@ msgstr "Sombreado"
#: scene/3d/label_3d.cpp scene/3d/sprite_3d.cpp
msgid "Double Sided"
-msgstr ""
+msgstr "Doble cara"
#: scene/3d/label_3d.cpp scene/3d/sprite_3d.cpp scene/resources/material.cpp
msgid "No Depth Test"
-msgstr ""
+msgstr "Sin test de profundidad"
#: scene/3d/label_3d.cpp scene/3d/sprite_3d.cpp scene/resources/material.cpp
msgid "Fixed Size"
@@ -22176,11 +22185,11 @@ msgstr "Tamaño Fijo"
#: scene/3d/label_3d.cpp scene/3d/sprite_3d.cpp
msgid "Alpha Cut"
-msgstr ""
+msgstr "Corte alfa"
#: scene/3d/label_3d.cpp scene/resources/material.cpp
msgid "Alpha Scissor Threshold"
-msgstr ""
+msgstr "Umbral de recorte alfa"
#: scene/3d/label_3d.cpp scene/3d/sprite_3d.cpp scene/resources/material.cpp
msgid "Render Priority"
@@ -22266,7 +22275,7 @@ msgstr "Rango de Profundidad"
#: scene/3d/light.cpp
msgid "Omni"
-msgstr ""
+msgstr "Omni"
#: scene/3d/light.cpp
msgid "Shadow Mode"
@@ -22283,7 +22292,7 @@ msgstr ""
#: scene/3d/light.cpp
msgid "Spot"
-msgstr ""
+msgstr "Ubicar"
#: scene/3d/light.cpp
msgid "Angle Attenuation"
@@ -22303,6 +22312,9 @@ msgid ""
"be removed in a future version. Use 'NavigationServer.map_get_path()' "
"instead."
msgstr ""
+"El nodo 'Navigation' y 'Navigation.get_simple_path()' están obsoletos y "
+"serán eliminados en una futura versión. Utiliza en su lugar "
+"'NavigationServer.map_get_path()'."
#: scene/3d/navigation.cpp scene/resources/curve.cpp
msgid "Up Vector"
@@ -22471,7 +22483,7 @@ msgstr "Restringir Articulaciones"
#: scene/3d/physics_body.cpp scene/3d/physics_joint.cpp
msgid "Impulse Clamp"
-msgstr ""
+msgstr "Restricción de Impulso"
#: scene/3d/physics_body.cpp scene/3d/physics_joint.cpp
msgid "Swing Span"
@@ -22479,7 +22491,7 @@ msgstr "Expansión de Swing"
#: scene/3d/physics_body.cpp scene/3d/physics_joint.cpp
msgid "Twist Span"
-msgstr ""
+msgstr "Extensión de Torsión"
#: scene/3d/physics_body.cpp scene/3d/physics_joint.cpp
#: scene/3d/vehicle_body.cpp
@@ -22632,7 +22644,7 @@ msgstr "El nodo A y el nodo B deben ser diferentes PhysicsBody"
#: scene/3d/physics_joint.cpp
msgid "Solver"
-msgstr ""
+msgstr "Resolver"
#: scene/3d/physics_joint.cpp
msgid "Exclude Nodes"
@@ -22644,7 +22656,7 @@ msgstr "Parámetros"
#: scene/3d/physics_joint.cpp
msgid "Angular Limit"
-msgstr ""
+msgstr "Límite Angular"
#: scene/3d/physics_joint.cpp
msgid "Upper"
@@ -22724,15 +22736,15 @@ msgstr "Amortiguación Lineal X"
#: scene/3d/physics_joint.cpp
msgid "Equilibrium Point"
-msgstr ""
+msgstr "Punto de Equilibrio"
#: scene/3d/physics_joint.cpp
msgid "Angular Limit X"
-msgstr ""
+msgstr "Límite Angular X"
#: scene/3d/physics_joint.cpp
msgid "Angular Motor X"
-msgstr ""
+msgstr "Motor Angular X"
#: scene/3d/physics_joint.cpp
msgid "Angular Spring X"
@@ -22752,11 +22764,11 @@ msgstr "Amortiguación Lineal Y"
#: scene/3d/physics_joint.cpp
msgid "Angular Limit Y"
-msgstr ""
+msgstr "Límite Angular Y"
#: scene/3d/physics_joint.cpp
msgid "Angular Motor Y"
-msgstr ""
+msgstr "Motor Angular Y"
#: scene/3d/physics_joint.cpp
msgid "Angular Spring Y"
@@ -22776,11 +22788,11 @@ msgstr "Amortiguación Lineal Z"
#: scene/3d/physics_joint.cpp
msgid "Angular Limit Z"
-msgstr ""
+msgstr "Límite Angular Z"
#: scene/3d/physics_joint.cpp
msgid "Angular Motor Z"
-msgstr ""
+msgstr "Motor Angular Z"
#: scene/3d/physics_joint.cpp
msgid "Angular Spring Z"
@@ -22804,7 +22816,7 @@ msgstr "Portal Activo"
#: scene/3d/portal.cpp scene/resources/occluder_shape_polygon.cpp
msgid "Two Way"
-msgstr ""
+msgstr "Doble Vía"
#: scene/3d/portal.cpp
msgid "Linked Room"
@@ -22820,7 +22832,7 @@ msgstr "Nombre del Grupo"
#: scene/3d/proximity_group.cpp
msgid "Dispatch Mode"
-msgstr ""
+msgstr "Modo de Entrega"
#: scene/3d/proximity_group.cpp
msgid "Grid Radius"
@@ -22832,7 +22844,7 @@ msgstr "Depurar Shape"
#: scene/3d/ray_cast.cpp scene/resources/style_box.cpp
msgid "Thickness"
-msgstr ""
+msgstr "Espesor"
#: scene/3d/reflection_probe.cpp scene/main/viewport.cpp
msgid "Update Mode"
@@ -22897,11 +22909,11 @@ msgstr "Usar Simplificación Predeterminada"
#: scene/3d/room.cpp scene/3d/room_manager.cpp
msgid "Room Simplify"
-msgstr ""
+msgstr "Simplificar Room"
#: scene/3d/room.cpp
msgid "Bound"
-msgstr ""
+msgstr "Conectado"
#: scene/3d/room_group.cpp
msgid "Roomgroup Priority"
@@ -22933,7 +22945,7 @@ msgstr "Sólo debe haber un RoomManager en el 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
@@ -22960,7 +22972,7 @@ msgstr "Nombre del Archivo PVS"
#: scene/3d/room_manager.cpp servers/visual_server.cpp
msgid "Gameplay"
-msgstr ""
+msgstr "Gameplay"
#: scene/3d/room_manager.cpp
msgid "Gameplay Monitor"
@@ -22984,7 +22996,7 @@ msgstr "Depurar Extensión"
#: scene/3d/room_manager.cpp
msgid "Overlap Warning Threshold"
-msgstr ""
+msgstr "Umbral de Advertencia de Solapamiento"
#: scene/3d/room_manager.cpp
msgid "Preview Camera"
@@ -22992,7 +23004,7 @@ msgstr "Vista previa de la Cámara"
#: scene/3d/room_manager.cpp
msgid "Portal Depth Limit"
-msgstr ""
+msgstr "Límite de Profundidad del Portal"
#: scene/3d/room_manager.cpp
msgid "Default Portal Margin"
@@ -23074,7 +23086,7 @@ msgstr "Ãndice de Puntos"
#: scene/3d/soft_body.cpp
msgid "Spatial Attachment Path"
-msgstr ""
+msgstr "Ruta del Adjunto Espacial"
#: scene/3d/soft_body.cpp
msgid "Physics Enabled"
@@ -23094,31 +23106,31 @@ msgstr "Masa Total"
#: scene/3d/soft_body.cpp
msgid "Linear Stiffness"
-msgstr ""
+msgstr "Rigidez Lineal"
#: scene/3d/soft_body.cpp
msgid "Areaangular Stiffness"
-msgstr ""
+msgstr "Rigidez Ãrea-angular"
#: scene/3d/soft_body.cpp
msgid "Volume Stiffness"
-msgstr ""
+msgstr "Rigidez de volumen"
#: scene/3d/soft_body.cpp
msgid "Pressure Coefficient"
-msgstr ""
+msgstr "Coeficiente de presión"
#: scene/3d/soft_body.cpp
msgid "Damping Coefficient"
-msgstr ""
+msgstr "Coeficiente de amortización"
#: scene/3d/soft_body.cpp
msgid "Drag Coefficient"
-msgstr ""
+msgstr "Coeficiente de resistencia"
#: scene/3d/soft_body.cpp
msgid "Pose Matching Coefficient"
-msgstr ""
+msgstr "Coeficiente de Adaptación de la Pose"
#: scene/3d/soft_body.cpp
msgid "This body will be ignored until you set a mesh."
@@ -23156,7 +23168,7 @@ msgstr "Cantidad de Amortiguación"
#: scene/3d/sprite_3d.cpp scene/gui/graph_edit.cpp
msgid "Opacity"
-msgstr ""
+msgstr "Opacidad"
#: scene/3d/sprite_3d.cpp scene/resources/material.cpp
msgid "Transparent"
@@ -23188,15 +23200,15 @@ msgstr "Fuerza del Motor"
#: scene/3d/vehicle_body.cpp
msgid "Brake"
-msgstr ""
+msgstr "Freno"
#: scene/3d/vehicle_body.cpp
msgid "Steering"
-msgstr ""
+msgstr "Dirección"
#: scene/3d/vehicle_body.cpp
msgid "VehicleBody Motion"
-msgstr ""
+msgstr "Movimiento del VehicleBody"
#: scene/3d/vehicle_body.cpp
msgid "Use As Traction"
@@ -23204,7 +23216,7 @@ msgstr "Usar Como Tracción"
#: scene/3d/vehicle_body.cpp
msgid "Use As Steering"
-msgstr ""
+msgstr "Usar Como Dirección"
#: scene/3d/vehicle_body.cpp
msgid "Wheel"
@@ -23212,7 +23224,7 @@ msgstr "Rueda"
#: scene/3d/vehicle_body.cpp
msgid "Roll Influence"
-msgstr ""
+msgstr "Influencia del Rodaje"
#: scene/3d/vehicle_body.cpp
msgid "Friction Slip"
@@ -23230,6 +23242,16 @@ msgstr "Fuerza Máxima"
msgid "AABB"
msgstr "AABB"
+#: scene/3d/visual_instance.cpp
+#, fuzzy
+msgid "Sorting"
+msgstr "Ordenar"
+
+#: scene/3d/visual_instance.cpp
+#, fuzzy
+msgid "Use AABB Center"
+msgstr "Usar Ambiente"
+
#: scene/3d/visual_instance.cpp scene/resources/navigation_mesh.cpp
msgid "Geometry"
msgstr "Geometría"
@@ -23260,7 +23282,7 @@ msgstr "Generar Lightmap"
#: scene/3d/visual_instance.cpp
msgid "Lightmap Scale"
-msgstr ""
+msgstr "Escala de Lightmap"
#: scene/3d/visual_instance.cpp
msgid "LOD"
@@ -23273,11 +23295,11 @@ msgstr "Distancia Mínima"
#: scene/3d/visual_instance.cpp
msgid "Min Hysteresis"
-msgstr ""
+msgstr "Histéresis Mínima"
#: scene/3d/visual_instance.cpp
msgid "Max Hysteresis"
-msgstr ""
+msgstr "Histéresis Máxima"
#: scene/3d/world_environment.cpp
msgid ""
@@ -23333,7 +23355,7 @@ msgstr "Reinicio Automático"
#: scene/animation/animation_blend_tree.cpp
msgid "Delay"
-msgstr ""
+msgstr "Retraso"
#: scene/animation/animation_blend_tree.cpp
msgid "Random Delay"
@@ -23386,7 +23408,7 @@ msgstr "Animación Asignada"
#: scene/animation/animation_player.cpp
msgid "Reset On Save"
-msgstr ""
+msgstr "Restablecer Al Guardar"
#: scene/animation/animation_player.cpp
msgid "Current Animation Length"
@@ -23406,7 +23428,7 @@ msgstr "Tiempo de Mezcla Predeterminado"
#: scene/animation/animation_player.cpp
msgid "Method Call Mode"
-msgstr ""
+msgstr "Modo de Llamada de Método"
#: scene/animation/animation_tree.cpp
msgid "In node '%s', invalid animation: '%s'."
@@ -23448,7 +23470,7 @@ msgstr "Reproductor de Animación"
#: scene/animation/animation_tree.cpp
msgid "Root Motion"
-msgstr ""
+msgstr "Movimiento de la Raíz"
#: scene/animation/animation_tree.cpp
msgid "Track"
@@ -23496,11 +23518,11 @@ msgstr "Anular Base de la Punta"
#: scene/animation/skeleton_ik.cpp
msgid "Use Magnet"
-msgstr ""
+msgstr "Usar Imán"
#: scene/animation/skeleton_ik.cpp
msgid "Magnet"
-msgstr ""
+msgstr "Imán"
#: scene/animation/skeleton_ik.cpp
msgid "Target Node"
@@ -23512,7 +23534,7 @@ msgstr "Iteraciones Máximas"
#: scene/animation/tween.cpp
msgid "Playback Process Mode"
-msgstr ""
+msgstr "Modo de Proceso de Reproducción"
#: scene/animation/tween.cpp
msgid "Playback Speed"
@@ -23534,7 +23556,7 @@ msgstr "Modo de Estiramiento"
#: scene/gui/aspect_ratio_container.cpp scene/gui/box_container.cpp
msgid "Alignment"
-msgstr ""
+msgstr "Alineamiento"
#: scene/gui/base_button.cpp
msgid "Shortcut In Tooltip"
@@ -23546,11 +23568,11 @@ msgstr "Modo de Acción"
#: scene/gui/base_button.cpp
msgid "Enabled Focus Mode"
-msgstr ""
+msgstr "Modo de Concentración Activado"
#: scene/gui/base_button.cpp
msgid "Keep Pressed Outside"
-msgstr ""
+msgstr "Mantener presionado al exterior"
#: scene/gui/base_button.cpp scene/gui/shortcut.cpp
msgid "Shortcut"
@@ -23677,7 +23699,7 @@ msgstr "Contenido del Clip"
#: scene/gui/control.cpp scene/resources/visual_shader_nodes.cpp
msgid "Hint"
-msgstr ""
+msgstr "Indicio"
#: scene/gui/control.cpp
msgid "Tooltip"
@@ -23713,7 +23735,7 @@ msgstr "Anterior"
#: scene/gui/control.cpp
msgid "Mouse"
-msgstr ""
+msgstr "Ratón"
#: scene/gui/control.cpp
msgid "Default Cursor Shape"
@@ -23721,7 +23743,7 @@ msgstr "Forma del Cursor Predeterminado"
#: scene/gui/control.cpp
msgid "Pass On Modal Close Click"
-msgstr ""
+msgstr "Pasar Clic Al Cerrar Modal"
#: scene/gui/control.cpp
msgid "Size Flags"
@@ -23737,7 +23759,7 @@ msgstr "Propiedades del Tema"
#: scene/gui/dialogs.cpp
msgid "Window Title"
-msgstr ""
+msgstr "Título de Ventana"
#: scene/gui/dialogs.cpp
msgid "Dialog"
@@ -23745,7 +23767,7 @@ msgstr "Diálogo"
#: scene/gui/dialogs.cpp
msgid "Hide On OK"
-msgstr ""
+msgstr "Ocultar Al Aceptar"
#: scene/gui/dialogs.cpp
msgid "Alert!"
@@ -23794,7 +23816,7 @@ msgstr "Mostrar Etiqueta Zoom"
#: scene/gui/graph_edit.cpp scene/gui/text_edit.cpp
#: scene/resources/default_theme/default_theme.cpp
msgid "Minimap"
-msgstr ""
+msgstr "Minimapa"
#: scene/gui/graph_edit.cpp
msgid "Enable grid minimap."
@@ -23815,7 +23837,7 @@ msgstr "Comentario"
#: scene/gui/graph_node.cpp
msgid "Overlay"
-msgstr ""
+msgstr "Overlay"
#: scene/gui/grid_container.cpp scene/gui/item_list.cpp scene/gui/tree.cpp
msgid "Columns"
@@ -23828,19 +23850,19 @@ msgstr "Temporizadores"
#: scene/gui/item_list.cpp scene/gui/popup_menu.cpp scene/gui/tree.cpp
msgid "Incremental Search Max Interval Msec"
-msgstr ""
+msgstr "Intervalo Máx. de Búsqueda Incremental Msec"
#: scene/gui/item_list.cpp scene/gui/tree.cpp
msgid "Allow Reselect"
-msgstr "Permitir Volver A Seleccionar"
+msgstr "Permitir Reselección"
#: scene/gui/item_list.cpp scene/gui/tree.cpp
msgid "Allow RMB Select"
-msgstr "Permitir Selección Con Botón Derecho Del Ratón"
+msgstr "Permitir Selección Con Botón Derecho Del Mouse"
#: scene/gui/item_list.cpp
msgid "Max Text Lines"
-msgstr ""
+msgstr "Líneas de Texto Máximas"
#: scene/gui/item_list.cpp
msgid "Auto Height"
@@ -23848,15 +23870,15 @@ msgstr "Altura Automática"
#: scene/gui/item_list.cpp
msgid "Max Columns"
-msgstr ""
+msgstr "Columnas Máximas"
#: scene/gui/item_list.cpp
msgid "Same Column Width"
-msgstr ""
+msgstr "Misma Anchura de Columna"
#: scene/gui/item_list.cpp
msgid "Fixed Column Width"
-msgstr ""
+msgstr "Anchura de Columna Fija"
#: scene/gui/item_list.cpp
msgid "Icon Scale"
@@ -23880,19 +23902,19 @@ msgstr "Porcentaje Visible"
#: scene/gui/label.cpp
msgid "Lines Skipped"
-msgstr ""
+msgstr "Líneas Omitidas"
#: scene/gui/label.cpp
msgid "Max Lines Visible"
-msgstr ""
+msgstr "Máximo de Líneas Visibles"
#: scene/gui/line_edit.cpp scene/resources/navigation_mesh.cpp
msgid "Max Length"
-msgstr ""
+msgstr "Máxima Longitud"
#: scene/gui/line_edit.cpp
msgid "Secret"
-msgstr ""
+msgstr "Secreto"
#: scene/gui/line_edit.cpp
msgid "Secret Character"
@@ -23900,7 +23922,7 @@ msgstr "Caracter Secreto"
#: scene/gui/line_edit.cpp
msgid "Expand To Text Length"
-msgstr ""
+msgstr "Expandir a la Longitud del Texto"
#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Context Menu Enabled"
@@ -23929,7 +23951,7 @@ msgstr "Selección Activada"
#: scene/gui/line_edit.cpp scene/gui/rich_text_label.cpp
#: scene/gui/text_edit.cpp
msgid "Deselect On Focus Loss Enabled"
-msgstr ""
+msgstr "Deselección al perder el focus activada"
#: scene/gui/line_edit.cpp
msgid "Right Icon"
@@ -23941,15 +23963,15 @@ msgstr "Marcador"
#: scene/gui/line_edit.cpp
msgid "Alpha"
-msgstr ""
+msgstr "Alpha"
#: 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"
-msgstr ""
+msgstr "Parpardeo"
#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Blink Speed"
@@ -23957,7 +23979,7 @@ msgstr "Velocidad de Parpadeo"
#: scene/gui/link_button.cpp
msgid "Underline"
-msgstr ""
+msgstr "Subrayar"
#: scene/gui/menu_button.cpp
msgid "Switch On Hover"
@@ -23977,7 +23999,7 @@ msgstr "Parche de Margen"
#: scene/gui/nine_patch_rect.cpp scene/resources/style_box.cpp
msgid "Axis Stretch"
-msgstr ""
+msgstr "Estiramiento de Eje"
#: scene/gui/nine_patch_rect.cpp
msgid ""
@@ -24023,7 +24045,7 @@ msgstr "Ocultar Al Seleccionar Elemento de Estado"
#: scene/gui/popup_menu.cpp
msgid "Submenu Popup Delay"
-msgstr ""
+msgstr "Retraso en la Aparición del Submenú"
#: scene/gui/popup_menu.cpp
msgid "Allow Search"
@@ -24059,11 +24081,11 @@ msgstr "Redondeado"
#: scene/gui/range.cpp
msgid "Allow Greater"
-msgstr ""
+msgstr "Permitir Más"
#: scene/gui/range.cpp
msgid "Allow Lesser"
-msgstr ""
+msgstr "Permitir Menos"
#: scene/gui/reference_rect.cpp
msgid "Border Color"
@@ -24095,11 +24117,11 @@ msgstr "Carácter"
#: scene/gui/rich_text_label.cpp
msgid "BBCode"
-msgstr ""
+msgstr "BBCode"
#: scene/gui/rich_text_label.cpp
msgid "Meta Underlined"
-msgstr ""
+msgstr "Meta Subrayados"
#: scene/gui/rich_text_label.cpp
msgid "Tab Size"
@@ -24111,11 +24133,11 @@ msgstr "Ajustar Altura Del Contenido"
#: scene/gui/rich_text_label.cpp
msgid "Scroll Active"
-msgstr ""
+msgstr "Scroll Activo"
#: scene/gui/rich_text_label.cpp
msgid "Scroll Following"
-msgstr ""
+msgstr "Seguir el Scroll"
#: scene/gui/rich_text_label.cpp
msgid "Selection Enabled"
@@ -24161,15 +24183,15 @@ msgstr "Zona Muerta Predeterminada del Scroll"
#: scene/gui/slider.cpp
msgid "Scrollable"
-msgstr ""
+msgstr "Desplazable"
#: scene/gui/slider.cpp
msgid "Tick Count"
-msgstr "Cantidad De Marcas"
+msgstr "Contador de Marcas"
#: scene/gui/slider.cpp
msgid "Ticks On Borders"
-msgstr "Ticks En Bordes"
+msgstr "Marcas En Los Bordes"
#: scene/gui/spin_box.cpp
msgid "Prefix"
@@ -24193,7 +24215,7 @@ msgstr "Visibilidad de los Arrastradores"
#: scene/gui/tab_container.cpp scene/gui/tabs.cpp
msgid "Tab Align"
-msgstr ""
+msgstr "Alineamiento de Pestaña"
#: scene/gui/tab_container.cpp scene/gui/tabs.cpp
msgid "Current Tab"
@@ -24205,7 +24227,7 @@ msgstr "Pestañas Visibles"
#: scene/gui/tab_container.cpp
msgid "All Tabs In Front"
-msgstr ""
+msgstr "Todas las Pestañas al Frente"
#: scene/gui/tab_container.cpp scene/gui/tabs.cpp
msgid "Drag To Rearrange Enabled"
@@ -24213,31 +24235,31 @@ msgstr "Arrastrar Para Reordenar Habilitado"
#: scene/gui/tab_container.cpp
msgid "Use Hidden Tabs For Min Size"
-msgstr ""
+msgstr "Usar Pestañas Ocultas Para Tamaño Mínimo"
#: scene/gui/tabs.cpp
msgid "Tab Close Display Policy"
-msgstr ""
+msgstr "Política de Botón de Cerrar Pestaña"
#: scene/gui/tabs.cpp
msgid "Scrolling Enabled"
-msgstr ""
+msgstr "Desplazamiento Activado"
#: scene/gui/text_edit.cpp
msgid "Readonly"
-msgstr ""
+msgstr "Solo Lectura"
#: scene/gui/text_edit.cpp
msgid "Bookmark Gutter"
-msgstr "Canalón de Marcadores"
+msgstr "Marca del Umbral"
#: scene/gui/text_edit.cpp
msgid "Breakpoint Gutter"
-msgstr "Canalón de Puntos de Ruptura"
+msgstr "Umbral de Ruptura"
#: scene/gui/text_edit.cpp
msgid "Fold Gutter"
-msgstr "Canalón Plegable"
+msgstr "Pliegue del Umbral"
#: scene/gui/text_edit.cpp
msgid "Drag And Drop Selection Enabled"
@@ -24269,19 +24291,19 @@ msgstr "Modo Bloque"
#: scene/gui/text_edit.cpp
msgid "Moving By Right Click"
-msgstr ""
+msgstr "Mover Con Clic Derecho"
#: scene/gui/text_edit.cpp
msgid "Text Edit Idle Detect (sec)"
-msgstr ""
+msgstr "Detección de Inactividad en la Edición de Texto (seg.)"
#: scene/gui/text_edit.cpp
msgid "Text Edit Undo Stack Max Size"
-msgstr ""
+msgstr "Número máximo de acciones recordados para deshacer"
#: scene/gui/texture_button.cpp scene/resources/default_theme/default_theme.cpp
msgid "Hover"
-msgstr ""
+msgstr "Hover"
#: scene/gui/texture_button.cpp
msgid "Focused"
@@ -24298,7 +24320,7 @@ msgstr "Expandir"
#: scene/gui/texture_progress.cpp
msgid "Under"
-msgstr ""
+msgstr "Debajo"
#: scene/gui/texture_progress.cpp
msgid "Over"
@@ -24318,11 +24340,11 @@ msgstr "Modo de Relleno"
#: scene/gui/texture_progress.cpp scene/resources/material.cpp
msgid "Tint"
-msgstr ""
+msgstr "Tinte"
#: scene/gui/texture_progress.cpp
msgid "Radial Fill"
-msgstr ""
+msgstr "Relleno Radial"
#: scene/gui/texture_progress.cpp
msgid "Initial Angle"
@@ -24358,7 +24380,7 @@ msgstr "Estiramiento de Margen Inferior"
#: scene/gui/tree.cpp
msgid "Custom Minimum Height"
-msgstr ""
+msgstr "Altura Mínima Personalizada"
#: scene/gui/tree.cpp
msgid "(Other)"
@@ -24378,7 +24400,7 @@ msgstr "Ocultar Raíz"
#: scene/gui/tree.cpp
msgid "Drop Mode Flags"
-msgstr ""
+msgstr "Indicadores del Modo de Caída"
#: scene/gui/video_player.cpp
msgid "Audio Track"
@@ -24414,11 +24436,11 @@ msgstr "Descargar Tamaño del Fragmento"
#: scene/main/http_request.cpp
msgid "Body Size Limit"
-msgstr ""
+msgstr "Límite del Tamaño del Cuerpo"
#: scene/main/http_request.cpp
msgid "Max Redirects"
-msgstr ""
+msgstr "Redireccionamientos Máximos"
#: scene/main/http_request.cpp
msgid "Timeout"
@@ -24429,6 +24451,8 @@ msgid ""
"Setting node name '%s' to be unique within scene for '%s', but it's already "
"claimed by '%s'. This node is no longer set unique."
msgstr ""
+"El nombre de nodo '%s' fue establecido como único en la escena de '%s', pero "
+"ya está en uso por '%s'. Éste nodo ya no está como único."
#: scene/main/node.cpp
msgid "Name Num Separator"
@@ -24436,7 +24460,7 @@ msgstr "Separador Numérico del Nombre"
#: scene/main/node.cpp
msgid "Name Casing"
-msgstr ""
+msgstr "Capitalización de Nombre"
#: scene/main/node.cpp
msgid "Editor Description"
@@ -24488,7 +24512,7 @@ msgstr "Sugerencia de Depuración de Navegación"
#: scene/main/scene_tree.cpp
msgid "Use Font Oversampling"
-msgstr ""
+msgstr "Usar Sobremuestreo de Fuente"
#: scene/main/scene_tree.cpp
msgid "Edited Scene Root"
@@ -24496,7 +24520,7 @@ msgstr "Escena Raíz Editada"
#: scene/main/scene_tree.cpp
msgid "Root"
-msgstr ""
+msgstr "Raíz"
#: scene/main/scene_tree.cpp
msgid "Multiplayer Poll"
@@ -24505,11 +24529,11 @@ msgstr "Encuesta Multijugador"
#: 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"
-msgstr ""
+msgstr "Color de la Forma"
#: scene/main/scene_tree.cpp
msgid "Contact Color"
@@ -24517,7 +24541,7 @@ msgstr "Color de Contacto"
#: scene/main/scene_tree.cpp
msgid "Geometry Color"
-msgstr ""
+msgstr "Color de la Geometría"
#: scene/main/scene_tree.cpp
msgid "Disabled Geometry Color"
@@ -24525,7 +24549,7 @@ msgstr "Color de la Geometría Desactivada"
#: scene/main/scene_tree.cpp
msgid "Max Contacts Displayed"
-msgstr ""
+msgstr "Núm. Máx. de Contactos Mostrados"
#: scene/main/scene_tree.cpp scene/resources/shape_2d.cpp
msgid "Draw 2D Outlines"
@@ -24541,27 +24565,27 @@ msgstr "Tamaño de Atlas"
#: scene/main/scene_tree.cpp
msgid "Atlas Subdiv"
-msgstr ""
+msgstr "Subdivisión del Atlas"
#: scene/main/scene_tree.cpp scene/main/viewport.cpp
msgid "MSAA"
-msgstr ""
+msgstr "MSAA"
#: scene/main/scene_tree.cpp
msgid "Use FXAA"
-msgstr ""
+msgstr "Usar FXAA"
#: scene/main/scene_tree.cpp
msgid "Use Debanding"
-msgstr ""
+msgstr "Usar Debanding"
#: 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"
-msgstr ""
+msgstr "Usar Profundidad de 32 BPC"
#: scene/main/scene_tree.cpp
msgid "Default Environment"
@@ -24681,7 +24705,7 @@ msgstr "Objetivo de Renderizado"
#: scene/main/viewport.cpp
msgid "V Flip"
-msgstr ""
+msgstr "Reflejo V"
#: scene/main/viewport.cpp
msgid "Clear Mode"
@@ -24709,19 +24733,19 @@ msgstr "Sombra del Atlas"
#: scene/main/viewport.cpp
msgid "Quad 0"
-msgstr ""
+msgstr "Cuadrángulo 0"
#: scene/main/viewport.cpp
msgid "Quad 1"
-msgstr ""
+msgstr "Cuadrángulo 1"
#: scene/main/viewport.cpp
msgid "Quad 2"
-msgstr ""
+msgstr "Cuadrángulo 2"
#: scene/main/viewport.cpp
msgid "Quad 3"
-msgstr ""
+msgstr "Cuadrángulo 3"
#: scene/main/viewport.cpp
msgid "Canvas Transform"
@@ -24737,7 +24761,7 @@ msgstr "Retraso del Tooltip (sec)"
#: scene/register_scene_types.cpp
msgid "Swap OK Cancel"
-msgstr "Cancelar"
+msgstr "Intercambiar Aceptar con Cancelar"
#: scene/register_scene_types.cpp
msgid "Layer Names"
@@ -24769,7 +24793,7 @@ msgstr "Navegación 3D"
#: scene/register_scene_types.cpp
msgid "Use hiDPI"
-msgstr ""
+msgstr "Usar hiDPI"
#: scene/register_scene_types.cpp
msgid "Custom"
@@ -24786,7 +24810,7 @@ msgstr "Tasa de Mezcla"
#: scene/resources/audio_stream_sample.cpp
msgid "Stereo"
-msgstr ""
+msgstr "Estéreo"
#: scene/resources/concave_polygon_shape_2d.cpp
msgid "Segments"
@@ -24798,11 +24822,11 @@ msgstr "Bakear Resolución"
#: scene/resources/curve.cpp
msgid "Bake Interval"
-msgstr ""
+msgstr "Intervalo de Bakeado"
#: scene/resources/default_theme/default_theme.cpp
msgid "Panel"
-msgstr ""
+msgstr "Panel"
#: scene/resources/default_theme/default_theme.cpp
msgid "Font Color"
@@ -24834,7 +24858,7 @@ msgstr "Espaciado del Subrayado"
#: scene/resources/default_theme/default_theme.cpp
msgid "Arrow"
-msgstr ""
+msgstr "Flecha"
#: scene/resources/default_theme/default_theme.cpp
msgid "Arrow Margin"
@@ -24866,19 +24890,19 @@ msgstr "Radio Marcado Desactivado"
#: scene/resources/default_theme/default_theme.cpp
msgid "Radio Unchecked"
-msgstr ""
+msgstr "Radio Desmarcado"
#: scene/resources/default_theme/default_theme.cpp
msgid "Radio Unchecked Disabled"
-msgstr ""
+msgstr "Radio Desmarcado Desactivado"
#: scene/resources/default_theme/default_theme.cpp
msgid "Font Color Hover Pressed"
-msgstr ""
+msgstr "Color de Fuente Hover Pulsado"
#: scene/resources/default_theme/default_theme.cpp
msgid "Check V Adjust"
-msgstr ""
+msgstr "Comprobar Ajuste V"
#: scene/resources/default_theme/default_theme.cpp
msgid "On Disabled"
@@ -24918,7 +24942,7 @@ msgstr "Color de Fuente Seleccionada"
#: scene/resources/default_theme/default_theme.cpp
msgid "Font Color Uneditable"
-msgstr ""
+msgstr "Color de Fuente No Editable"
#: scene/resources/default_theme/default_theme.cpp
msgid "Cursor Color"
@@ -24942,7 +24966,7 @@ msgstr "BG"
#: scene/resources/default_theme/default_theme.cpp
msgid "FG"
-msgstr ""
+msgstr "FG"
#: scene/resources/default_theme/default_theme.cpp
msgid "Tab"
@@ -24964,7 +24988,7 @@ msgstr "Plegar"
#: scene/resources/default_theme/default_theme.cpp
msgid "Font Color Readonly"
-msgstr ""
+msgstr "Color de Fuente de Sólo Leída"
#: scene/resources/default_theme/default_theme.cpp
msgid "Completion Lines"
@@ -24984,7 +25008,7 @@ msgstr "Enfoque de Scroll"
#: scene/resources/default_theme/default_theme.cpp
msgid "Grabber"
-msgstr ""
+msgstr "Grabber"
#: scene/resources/default_theme/default_theme.cpp
msgid "Grabber Highlight"
@@ -25004,11 +25028,11 @@ msgstr "Incremento Resaltado"
#: scene/resources/default_theme/default_theme.cpp
msgid "Increment Pressed"
-msgstr ""
+msgstr "Incremento Pulsado"
#: scene/resources/default_theme/default_theme.cpp
msgid "Decrement"
-msgstr ""
+msgstr "Decremento"
#: scene/resources/default_theme/default_theme.cpp
msgid "Decrement Highlight"
@@ -25016,7 +25040,7 @@ msgstr "Decremento Resaltado"
#: scene/resources/default_theme/default_theme.cpp
msgid "Decrement Pressed"
-msgstr ""
+msgstr "Decremento Pulsado"
#: scene/resources/default_theme/default_theme.cpp
msgid "Slider"
@@ -25024,11 +25048,11 @@ msgstr "Deslizador"
#: scene/resources/default_theme/default_theme.cpp
msgid "Grabber Area"
-msgstr ""
+msgstr "Ãrea de Grabber"
#: scene/resources/default_theme/default_theme.cpp
msgid "Grabber Area Highlight"
-msgstr ""
+msgstr "Resaltado del Ãrea de Grabber"
#: scene/resources/default_theme/default_theme.cpp
msgid "Grabber Disabled"
@@ -25036,7 +25060,7 @@ msgstr "Agarre Desactivado"
#: scene/resources/default_theme/default_theme.cpp
msgid "Tick"
-msgstr ""
+msgstr "Marcar"
#: scene/resources/default_theme/default_theme.cpp
msgid "Updown"
@@ -25160,7 +25184,7 @@ msgstr "Enfoque Seleccionado"
#: scene/resources/default_theme/default_theme.cpp
msgid "Cursor Unfocused"
-msgstr ""
+msgstr "Cursor Desenfocado"
#: scene/resources/default_theme/default_theme.cpp
msgid "Button Pressed"
@@ -25220,7 +25244,7 @@ msgstr "Color de la Línea de Relación"
#: scene/resources/default_theme/default_theme.cpp
msgid "Custom Button Font Highlight"
-msgstr ""
+msgstr "Fuente Personalizada de Botón Resaltado"
#: scene/resources/default_theme/default_theme.cpp
msgid "Item Margin"
@@ -25268,7 +25292,7 @@ msgstr "Pestaña Desactivada"
#: scene/resources/default_theme/default_theme.cpp
msgid "Menu"
-msgstr ""
+msgstr "Menú"
#: scene/resources/default_theme/default_theme.cpp
msgid "Menu Highlight"
@@ -25292,15 +25316,15 @@ msgstr "Margen Superior"
#: scene/resources/default_theme/default_theme.cpp
msgid "Label V Align FG"
-msgstr ""
+msgstr "Etiqueta V Alinear FG"
#: scene/resources/default_theme/default_theme.cpp
msgid "Label V Align BG"
-msgstr ""
+msgstr "Etiqueta V Alinear BG"
#: scene/resources/default_theme/default_theme.cpp
msgid "Large"
-msgstr "Largo"
+msgstr "Grande"
#: scene/resources/default_theme/default_theme.cpp
msgid "Folder"
@@ -25356,11 +25380,11 @@ msgstr "Preset BG"
#: scene/resources/default_theme/default_theme.cpp
msgid "Overbright Indicator"
-msgstr ""
+msgstr "Indicador de Exceso de Brillo"
#: scene/resources/default_theme/default_theme.cpp
msgid "Preset FG"
-msgstr "Preset FG"
+msgstr "FG Preestablecido"
#: scene/resources/default_theme/default_theme.cpp
msgid "Preset BG Icon"
@@ -25416,11 +25440,11 @@ msgstr "Ocultar Automáticamente"
#: scene/resources/default_theme/default_theme.cpp
msgid "Minus"
-msgstr ""
+msgstr "Menos"
#: scene/resources/default_theme/default_theme.cpp
msgid "More"
-msgstr ""
+msgstr "Más"
#: scene/resources/default_theme/default_theme.cpp
msgid "Grid Minor"
@@ -25452,7 +25476,7 @@ msgstr "Bezier Len Neg"
#: scene/resources/default_theme/default_theme.cpp
msgid "Port Grab Distance Horizontal"
-msgstr ""
+msgstr "Distancia de Agarre Horizontal del Puerto"
#: scene/resources/default_theme/default_theme.cpp
msgid "Port Grab Distance Vertical"
@@ -25460,7 +25484,7 @@ msgstr "Distancia Vertical del Puerto de Agarre"
#: scene/resources/dynamic_font.cpp
msgid "Hinting"
-msgstr ""
+msgstr "Hinting"
#: scene/resources/dynamic_font.cpp
msgid "Override Oversampling"
@@ -25496,11 +25520,11 @@ msgstr "Datos de la Fuente"
#: scene/resources/environment.cpp
msgid "Background"
-msgstr ""
+msgstr "Fondo"
#: scene/resources/environment.cpp scene/resources/sky.cpp
msgid "Sky"
-msgstr ""
+msgstr "Cielo"
#: scene/resources/environment.cpp
msgid "Sky Custom FOV"
@@ -25536,7 +25560,7 @@ msgstr "Contribución del Cielo"
#: scene/resources/environment.cpp
msgid "Fog"
-msgstr ""
+msgstr "Niebla"
#: scene/resources/environment.cpp
msgid "Sun Color"
@@ -25596,19 +25620,19 @@ msgstr "Exposición"
#: scene/resources/environment.cpp
msgid "White"
-msgstr ""
+msgstr "Blanco"
#: scene/resources/environment.cpp
msgid "Auto Exposure"
-msgstr ""
+msgstr "Exposición Auto"
#: scene/resources/environment.cpp
msgid "Min Luma"
-msgstr ""
+msgstr "Luma Mínimo"
#: scene/resources/environment.cpp
msgid "Max Luma"
-msgstr ""
+msgstr "Luma Máximo"
#: scene/resources/environment.cpp
msgid "SS Reflections"
@@ -25632,11 +25656,11 @@ msgstr "Tolerancia de Profundidad"
#: scene/resources/environment.cpp scene/resources/material.cpp
msgid "Roughness"
-msgstr ""
+msgstr "Aspereza"
#: scene/resources/environment.cpp
msgid "SSAO"
-msgstr ""
+msgstr "SSAO"
#: scene/resources/environment.cpp
msgid "Radius 2"
@@ -25644,7 +25668,7 @@ msgstr "Radio 2"
#: scene/resources/environment.cpp
msgid "Intensity 2"
-msgstr ""
+msgstr "Intensidad 2"
#: scene/resources/environment.cpp scene/resources/material.cpp
msgid "Light Affect"
@@ -25656,11 +25680,11 @@ msgstr "Influencia del Canal AO"
#: scene/resources/environment.cpp
msgid "Blur"
-msgstr ""
+msgstr "Blur"
#: scene/resources/environment.cpp
msgid "Edge Sharpness"
-msgstr ""
+msgstr "Nitidez de Borde"
#: scene/resources/environment.cpp
msgid "DOF Far Blur"
@@ -25680,7 +25704,7 @@ msgstr ""
#: scene/resources/environment.cpp
msgid "Glow"
-msgstr ""
+msgstr "Brillo"
#: scene/resources/environment.cpp
msgid "Levels"
@@ -25720,15 +25744,15 @@ msgstr "7"
#: scene/resources/environment.cpp
msgid "Bloom"
-msgstr ""
+msgstr "Resplandor"
#: scene/resources/environment.cpp
msgid "HDR Threshold"
-msgstr ""
+msgstr "Umbral de HDR"
#: scene/resources/environment.cpp
msgid "HDR Luminance Cap"
-msgstr ""
+msgstr "Luminancia de HDR Máxima"
#: scene/resources/environment.cpp
msgid "HDR Scale"
@@ -25740,7 +25764,7 @@ msgstr ""
#: scene/resources/environment.cpp
msgid "Adjustments"
-msgstr ""
+msgstr "Ajustes"
#: scene/resources/environment.cpp
msgid "Brightness"
@@ -25772,7 +25796,7 @@ msgstr "Offsets"
#: scene/resources/height_map_shape.cpp
msgid "Map Width"
-msgstr ""
+msgstr "Anchura del Mapa"
#: scene/resources/height_map_shape.cpp
msgid "Map Depth"
@@ -25784,7 +25808,7 @@ msgstr "Datos del Mapa"
#: scene/resources/line_shape_2d.cpp
msgid "D"
-msgstr ""
+msgstr "D"
#: scene/resources/material.cpp
msgid "Next Pass"
@@ -25812,11 +25836,11 @@ msgstr ""
#: scene/resources/material.cpp
msgid "Albedo Tex Force sRGB"
-msgstr ""
+msgstr "Forzar sRGB en Textura Albedo"
#: scene/resources/material.cpp
msgid "Do Not Receive Shadows"
-msgstr ""
+msgstr "No Recibir Sombras"
#: scene/resources/material.cpp
msgid "Disable Ambient Light"
@@ -25828,7 +25852,7 @@ msgstr "Asegurar Normales Correctas"
#: scene/resources/material.cpp
msgid "Albedo Tex MSDF"
-msgstr ""
+msgstr "MSDF en Textura Albedo"
#: scene/resources/material.cpp
msgid "Vertex Color"
@@ -25836,11 +25860,11 @@ msgstr "Color del Vértice"
#: scene/resources/material.cpp
msgid "Use As Albedo"
-msgstr ""
+msgstr "Usar Como Albedo"
#: scene/resources/material.cpp
msgid "Is sRGB"
-msgstr ""
+msgstr "Es sRGB"
#: scene/resources/material.cpp servers/visual_server.cpp
msgid "Parameters"
@@ -25876,15 +25900,15 @@ msgstr "Mantener Escala del Billboard"
#: scene/resources/material.cpp
msgid "Grow"
-msgstr ""
+msgstr "Expandir"
#: scene/resources/material.cpp
msgid "Grow Amount"
-msgstr "Cantidad de Crecimiento"
+msgstr "Cantidad de Expansión"
#: scene/resources/material.cpp
msgid "Use Alpha Scissor"
-msgstr ""
+msgstr "Usar Corte Alpha"
#: scene/resources/material.cpp
msgid "Particles Anim"
@@ -25900,11 +25924,11 @@ msgstr "Cuadros V"
#: scene/resources/material.cpp
msgid "Albedo"
-msgstr ""
+msgstr "Albedo"
#: scene/resources/material.cpp
msgid "Metallic"
-msgstr ""
+msgstr "Metálico"
#: scene/resources/material.cpp
msgid "Texture Channel"
@@ -25916,15 +25940,15 @@ msgstr "Emisión"
#: scene/resources/material.cpp
msgid "On UV2"
-msgstr ""
+msgstr "En UV2"
#: scene/resources/material.cpp
msgid "NormalMap"
-msgstr ""
+msgstr "Mapa Normal"
#: scene/resources/material.cpp
msgid "Rim"
-msgstr ""
+msgstr "Borde"
#: scene/resources/material.cpp
msgid "Clearcoat"
@@ -25932,15 +25956,15 @@ msgstr "Transparencia"
#: scene/resources/material.cpp
msgid "Gloss"
-msgstr ""
+msgstr "Brillo"
#: scene/resources/material.cpp
msgid "Anisotropy"
-msgstr ""
+msgstr "Anisotropía"
#: scene/resources/material.cpp
msgid "Flowmap"
-msgstr ""
+msgstr "Flowmap"
#: scene/resources/material.cpp
msgid "Ambient Occlusion"
@@ -25948,7 +25972,7 @@ msgstr "Oclusión Ambiental"
#: scene/resources/material.cpp
msgid "Deep Parallax"
-msgstr ""
+msgstr "Paralaje Profundo"
#: scene/resources/material.cpp
msgid "Min Layers"
@@ -25960,7 +25984,7 @@ msgstr "Capas Máximas"
#: scene/resources/material.cpp
msgid "Flip Tangent"
-msgstr ""
+msgstr "Voltear Tangente"
#: scene/resources/material.cpp
msgid "Flip Binormal"
@@ -25980,7 +26004,7 @@ msgstr "Refracción"
#: scene/resources/material.cpp
msgid "Detail"
-msgstr ""
+msgstr "Detalle"
#: scene/resources/material.cpp
msgid "UV Layer"
@@ -25992,11 +26016,11 @@ msgstr "UV1"
#: scene/resources/material.cpp
msgid "Triplanar"
-msgstr ""
+msgstr "Triplanar"
#: scene/resources/material.cpp
msgid "Triplanar Sharpness"
-msgstr ""
+msgstr "Nitidez Triplanar"
#: scene/resources/material.cpp
msgid "UV2"
@@ -26008,7 +26032,7 @@ msgstr "Desvanecimiento de Proximidad"
#: scene/resources/material.cpp
msgid "Distance Fade"
-msgstr ""
+msgstr "Fade al Distanciarse"
#: scene/resources/material.cpp
msgid "Async Mode"
@@ -26020,7 +26044,7 @@ msgstr "Sugerencia de Tamaño del Lightmap"
#: scene/resources/mesh.cpp scene/resources/primitive_meshes.cpp
msgid "Custom AABB"
-msgstr ""
+msgstr "AABB Personalizado"
#: scene/resources/mesh_library.cpp
msgid "Mesh Transform"
@@ -26040,7 +26064,7 @@ msgstr "Formato de Transformación"
#: scene/resources/multimesh.cpp
msgid "Custom Data Format"
-msgstr ""
+msgstr "Formato de Datos Personalizado"
#: scene/resources/multimesh.cpp
msgid "Instance Count"
@@ -26048,7 +26072,7 @@ msgstr "Conteo de Instancias"
#: scene/resources/multimesh.cpp
msgid "Visible Instance Count"
-msgstr ""
+msgstr "Número de Instancias Visible"
#: scene/resources/navigation_mesh.cpp
msgid "Sampling"
@@ -26064,7 +26088,7 @@ msgstr "Tipo de Geometría Parseada"
#: scene/resources/navigation_mesh.cpp
msgid "Source Geometry Mode"
-msgstr ""
+msgstr "Modo de Geometría de Origen"
#: scene/resources/navigation_mesh.cpp
msgid "Source Group Name"
@@ -26072,7 +26096,7 @@ msgstr "Nombre del Grupo de Origen"
#: scene/resources/navigation_mesh.cpp
msgid "Cells"
-msgstr ""
+msgstr "Celdas"
#: scene/resources/navigation_mesh.cpp
msgid "Agents"
@@ -26080,11 +26104,11 @@ msgstr "Agentes"
#: scene/resources/navigation_mesh.cpp
msgid "Max Climb"
-msgstr ""
+msgstr "Escalada Máxima"
#: scene/resources/navigation_mesh.cpp
msgid "Max Slope"
-msgstr ""
+msgstr "Pendiente Máxima"
#: scene/resources/navigation_mesh.cpp
msgid "Regions"
@@ -26096,7 +26120,7 @@ msgstr "Tamaño de Unión"
#: scene/resources/navigation_mesh.cpp
msgid "Edges"
-msgstr ""
+msgstr "Aristas"
#: scene/resources/navigation_mesh.cpp
msgid "Max Error"
@@ -26104,7 +26128,7 @@ msgstr "Error Máximo"
#: scene/resources/navigation_mesh.cpp
msgid "Verts Per Poly"
-msgstr ""
+msgstr "Vértices por Poly"
#: scene/resources/navigation_mesh.cpp
msgid "Details"
@@ -26120,7 +26144,7 @@ msgstr "Error Máximo de Muestra"
#: scene/resources/navigation_mesh.cpp
msgid "Low Hanging Obstacles"
-msgstr ""
+msgstr "Obstáculos Colgando Bajo"
#: scene/resources/navigation_mesh.cpp
msgid "Ledge Spans"
@@ -26140,7 +26164,7 @@ msgstr "Bakear Offset AABB"
#: scene/resources/occluder_shape.cpp
msgid "Spheres"
-msgstr ""
+msgstr "Esferas"
#: scene/resources/occluder_shape.cpp
msgid "OccluderShapeSphere Set Spheres"
@@ -26156,11 +26180,11 @@ msgstr "Puntos de Rotura"
#: scene/resources/packed_scene.cpp
msgid "Bundled"
-msgstr ""
+msgstr "Empaquetado"
#: scene/resources/particles_material.cpp
msgid "Trail"
-msgstr ""
+msgstr "Rastro"
#: scene/resources/particles_material.cpp
msgid "Divisor"
@@ -26200,11 +26224,11 @@ msgstr "Curva de Escala"
#: scene/resources/physics_material.cpp
msgid "Rough"
-msgstr ""
+msgstr "Ãspero"
#: scene/resources/physics_material.cpp
msgid "Absorbent"
-msgstr ""
+msgstr "Absorbente"
#: scene/resources/plane_shape.cpp
msgid "Plane"
@@ -26216,19 +26240,19 @@ msgstr "Voltear Caras"
#: scene/resources/primitive_meshes.cpp
msgid "Mid Height"
-msgstr ""
+msgstr "Altura Mediana"
#: scene/resources/primitive_meshes.cpp
msgid "Subdivide Width"
-msgstr ""
+msgstr "Anchura de Subdivisión"
#: scene/resources/primitive_meshes.cpp
msgid "Subdivide Height"
-msgstr ""
+msgstr "Altura de Subdivisión"
#: scene/resources/primitive_meshes.cpp
msgid "Subdivide Depth"
-msgstr ""
+msgstr "Profundidad de Subdivisión"
#: scene/resources/primitive_meshes.cpp
msgid "Top Radius"
@@ -26244,7 +26268,7 @@ msgstr "De Izquierda a Derecha"
#: scene/resources/primitive_meshes.cpp
msgid "Is Hemisphere"
-msgstr ""
+msgstr "Es Hemisfera"
#: scene/resources/primitive_meshes.cpp
msgid "Curve Step"
@@ -26252,15 +26276,15 @@ msgstr "Paso de Curva"
#: scene/resources/ray_shape.cpp scene/resources/segment_shape_2d.cpp
msgid "Slips On Slope"
-msgstr ""
+msgstr "Resbala en Pendiente"
#: scene/resources/segment_shape_2d.cpp
msgid "A"
-msgstr ""
+msgstr "A"
#: scene/resources/shape_2d.cpp
msgid "Custom Solver Bias"
-msgstr ""
+msgstr "Bias de Solución Personalizado"
#: scene/resources/skin.cpp
msgid "Bind Count"
@@ -26280,7 +26304,7 @@ msgstr "Tamaño de Resplandor"
#: scene/resources/sky.cpp
msgid "Panorama"
-msgstr ""
+msgstr "Panorama"
#: scene/resources/sky.cpp
msgid "Top Color"
@@ -26308,15 +26332,15 @@ msgstr "Latitud"
#: scene/resources/sky.cpp
msgid "Longitude"
-msgstr ""
+msgstr "Longitud"
#: scene/resources/sky.cpp
msgid "Angle Min"
-msgstr ""
+msgstr "Ãngulo Mínimo"
#: scene/resources/sky.cpp
msgid "Angle Max"
-msgstr ""
+msgstr "Ãngulo Máximo"
#: scene/resources/style_box.cpp
msgid "Content Margin"
@@ -26328,7 +26352,7 @@ msgstr "Expandir Margen"
#: scene/resources/style_box.cpp
msgid "Skew"
-msgstr ""
+msgstr "Sesgo"
#: scene/resources/style_box.cpp
msgid "Corner Radius"
@@ -26336,19 +26360,19 @@ msgstr "Radio de Esquina"
#: scene/resources/style_box.cpp
msgid "Corner Detail"
-msgstr ""
+msgstr "Detalle de Esquina"
#: scene/resources/style_box.cpp
msgid "Anti Aliasing"
-msgstr ""
+msgstr "Antialias"
#: scene/resources/style_box.cpp
msgid "Grow Begin"
-msgstr ""
+msgstr "Inicio de Expansión"
#: scene/resources/style_box.cpp
msgid "Grow End"
-msgstr ""
+msgstr "Fin de Expansión"
#: scene/resources/texture.cpp
msgid "Load Path"
@@ -26404,7 +26428,7 @@ msgstr "Pausa"
#: scene/resources/texture.cpp
msgid "Which Feed"
-msgstr ""
+msgstr "Cuál Feed"
#: scene/resources/texture.cpp
msgid "Camera Is Active"
@@ -26416,7 +26440,7 @@ msgstr "Fuente Predeterminada"
#: scene/resources/visual_shader.cpp
msgid "Output Port For Preview"
-msgstr ""
+msgstr "Puerto de Salida para Previsualización"
#: scene/resources/visual_shader.cpp
msgid "Depth Draw"
@@ -26468,7 +26492,7 @@ msgstr "Tipo de Textura"
#: scene/resources/visual_shader_nodes.cpp
msgid "Cube Map"
-msgstr ""
+msgstr "Mapa de Cubo"
#: scene/resources/visual_shader_nodes.cpp
msgid "Default Value Enabled"
@@ -26500,7 +26524,7 @@ msgstr "Mapa de Navegación"
#: scene/resources/world.cpp scene/resources/world_2d.cpp
msgid "Direct Space State"
-msgstr ""
+msgstr "Estado de Espacio Directo"
#: scene/resources/world.cpp scene/resources/world_2d.cpp
msgid "Default Gravity Vector"
@@ -26536,7 +26560,7 @@ msgstr "Lienzo"
#: servers/arvr/arvr_interface.cpp
msgid "Is Primary"
-msgstr ""
+msgstr "Es Primario"
#: servers/arvr/arvr_interface.cpp
msgid "Is Initialized"
@@ -26544,11 +26568,11 @@ msgstr "Inicializado"
#: servers/arvr/arvr_interface.cpp
msgid "AR"
-msgstr ""
+msgstr "AR"
#: servers/arvr/arvr_interface.cpp
msgid "Is Anchor Detection Enabled"
-msgstr ""
+msgstr "Detección de Anclaje Está Activada"
#: servers/arvr_server.cpp
msgid "Primary Interface"
@@ -26566,36 +26590,36 @@ msgstr "Tono Aleatorio"
#: servers/audio/effects/audio_effect_spectrum_analyzer.cpp
#: servers/audio/effects/audio_stream_generator.cpp
msgid "Buffer Length"
-msgstr ""
+msgstr "Longitud de Buffer"
#: servers/audio/effects/audio_effect_chorus.cpp
msgid "Voice Count"
-msgstr ""
+msgstr "Número de Voces"
#: servers/audio/effects/audio_effect_chorus.cpp
#: 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 "Mojado"
#: 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 "Retraso (ms)"
#: servers/audio/effects/audio_effect_chorus.cpp
#: servers/audio/effects/audio_effect_phaser.cpp
msgid "Rate Hz"
-msgstr ""
+msgstr "Velocidad en Hz"
#: servers/audio/effects/audio_effect_chorus.cpp
msgid "Depth (ms)"
@@ -26604,7 +26628,7 @@ msgstr "Profundidad (ms)"
#: servers/audio/effects/audio_effect_chorus.cpp
#: servers/audio/effects/audio_effect_delay.cpp
msgid "Level dB"
-msgstr ""
+msgstr "Nivel en dB"
#: servers/audio/effects/audio_effect_chorus.cpp
#: servers/audio/effects/audio_effect_delay.cpp
@@ -26615,11 +26639,11 @@ msgstr "Pan"
#: servers/audio/effects/audio_effect_compressor.cpp
#: servers/audio/effects/audio_effect_filter.cpp
msgid "Gain"
-msgstr ""
+msgstr "Ganancia"
#: servers/audio/effects/audio_effect_compressor.cpp
msgid "Attack (µs)"
-msgstr ""
+msgstr "Ataque (µs)"
#: servers/audio/effects/audio_effect_compressor.cpp
msgid "Release (ms)"
@@ -26635,11 +26659,11 @@ msgstr ""
#: servers/audio/effects/audio_effect_delay.cpp
msgid "Tap 1"
-msgstr ""
+msgstr "Toque 1"
#: servers/audio/effects/audio_effect_delay.cpp
msgid "Tap 2"
-msgstr ""
+msgstr "Toque 2"
#: servers/audio/effects/audio_effect_delay.cpp
#: servers/audio/effects/audio_effect_phaser.cpp
@@ -26653,15 +26677,15 @@ msgstr "Paso Bajo"
#: servers/audio/effects/audio_effect_distortion.cpp
msgid "Pre Gain"
-msgstr ""
+msgstr "Pre-Ganancia"
#: servers/audio/effects/audio_effect_distortion.cpp
msgid "Keep Hf Hz"
-msgstr ""
+msgstr "Mantener Hz Altas"
#: servers/audio/effects/audio_effect_distortion.cpp
msgid "Drive"
-msgstr ""
+msgstr "Drive"
#: servers/audio/effects/audio_effect_distortion.cpp
msgid "Post Gain"
@@ -26673,11 +26697,11 @@ msgstr "Resonancia"
#: servers/audio/effects/audio_effect_limiter.cpp
msgid "Ceiling dB"
-msgstr ""
+msgstr "dB Tope"
#: servers/audio/effects/audio_effect_limiter.cpp
msgid "Threshold dB"
-msgstr ""
+msgstr "Umbral dB"
#: servers/audio/effects/audio_effect_limiter.cpp
msgid "Soft Clip dB"
@@ -26689,15 +26713,15 @@ msgstr ""
#: servers/audio/effects/audio_effect_phaser.cpp
msgid "Range Min Hz"
-msgstr ""
+msgstr "Rango Hz Mínimo"
#: servers/audio/effects/audio_effect_phaser.cpp
msgid "Range Max Hz"
-msgstr ""
+msgstr "Rango Hz Máximo"
#: servers/audio/effects/audio_effect_pitch_shift.cpp
msgid "Oversampling"
-msgstr ""
+msgstr "Sobremuestreo"
#: servers/audio/effects/audio_effect_pitch_shift.cpp
#: servers/audio/effects/audio_effect_spectrum_analyzer.cpp
@@ -26710,11 +26734,11 @@ msgstr ""
#: servers/audio/effects/audio_effect_reverb.cpp
msgid "Msec"
-msgstr ""
+msgstr "Mseg"
#: servers/audio/effects/audio_effect_reverb.cpp
msgid "Room Size"
-msgstr ""
+msgstr "Tamaño de Habitación"
#: servers/audio/effects/audio_effect_reverb.cpp
msgid "High-pass"
@@ -26734,7 +26758,7 @@ msgstr "Tiempo de Extracción (ms)"
#: servers/audio/effects/audio_effect_stereo_enhance.cpp
msgid "Surround"
-msgstr ""
+msgstr "Envolvente"
#: servers/audio_server.cpp
msgid "Enable Audio Input"
@@ -26746,7 +26770,7 @@ msgstr "Latencia de Salida"
#: servers/audio_server.cpp
msgid "Channel Disable Threshold dB"
-msgstr ""
+msgstr "Umbral dB de Deactivación de Canal"
#: servers/audio_server.cpp
msgid "Channel Disable Time"
@@ -26754,7 +26778,7 @@ msgstr "Tiempo de Desconexión del Canal"
#: servers/audio_server.cpp
msgid "Video Delay Compensation (ms)"
-msgstr ""
+msgstr "Compensación de Retraso de Vídeo (ms)"
#: servers/audio_server.cpp
msgid "Bus Count"
@@ -26770,7 +26794,7 @@ msgstr "Escala Global de Porcentajes"
#: servers/camera/camera_feed.cpp
msgid "Feed"
-msgstr ""
+msgstr "Feed"
#: servers/camera/camera_feed.cpp
msgid "Is Active"
@@ -26778,15 +26802,15 @@ msgstr "Activo"
#: servers/physics/space_sw.cpp servers/physics_2d/space_2d_sw.cpp
msgid "Sleep Threshold Linear"
-msgstr ""
+msgstr "Umbral de Sueño Lineal"
#: servers/physics/space_sw.cpp servers/physics_2d/space_2d_sw.cpp
msgid "Sleep Threshold Angular"
-msgstr ""
+msgstr "Umbral de Sueño Angular"
#: servers/physics/space_sw.cpp servers/physics_2d/space_2d_sw.cpp
msgid "Time Before Sleep"
-msgstr ""
+msgstr "Tiempo Antes de Sueño"
#: servers/physics_2d/physics_2d_server_sw.cpp
msgid "BP Hash Table Size"
@@ -26794,11 +26818,11 @@ msgstr "Tamaño de Tabla Hash BP"
#: servers/physics_2d/physics_2d_server_sw.cpp
msgid "Large Object Surface Threshold In Cells"
-msgstr ""
+msgstr "Umbral de Superficie de Objeto Grande en Celdas"
#: servers/physics_2d_server.cpp servers/physics_server.cpp
msgid "Inverse Mass"
-msgstr ""
+msgstr "Masa Inversa"
#: servers/physics_2d_server.cpp servers/physics_server.cpp
msgid "Inverse Inertia"
@@ -26822,11 +26846,11 @@ msgstr "Velocidad Lineal"
#: servers/physics_2d_server.cpp servers/physics_server.cpp
msgid "Exclude"
-msgstr ""
+msgstr "Excluir"
#: servers/physics_2d_server.cpp servers/physics_server.cpp
msgid "Shape RID"
-msgstr ""
+msgstr "RID de Forma"
#: servers/physics_2d_server.cpp servers/physics_server.cpp
msgid "Collide With Bodies"
@@ -26834,7 +26858,7 @@ msgstr "Colisión de Cuerpos"
#: servers/physics_2d_server.cpp servers/physics_server.cpp
msgid "Collide With Areas"
-msgstr ""
+msgstr "Colisionar Con Ãreas"
#: servers/physics_2d_server.cpp servers/physics_server.cpp
msgid "Motion Remainder"
@@ -26870,7 +26894,7 @@ msgstr "Centro de la Masa"
#: servers/physics_server.cpp
msgid "Principal Inertia Axes"
-msgstr ""
+msgstr "Ejes de Inercia Principal"
#: servers/visual/shader_language.cpp
msgid "Varying may not be assigned in the '%s' function."
@@ -26938,7 +26962,7 @@ msgstr "Importar PVRTC"
#: servers/visual_server.cpp
msgid "Lossless Compression"
-msgstr ""
+msgstr "Compresión Sin Pérdidas"
#: servers/visual_server.cpp
msgid "Force PNG"
@@ -26946,7 +26970,7 @@ msgstr "Forzar PNG"
#: servers/visual_server.cpp
msgid "WebP Compression Level"
-msgstr ""
+msgstr "Nivel de Compresión WebP"
#: servers/visual_server.cpp
msgid "Time Rollover Secs"
@@ -26958,19 +26982,19 @@ msgstr "Tamaño del Cubemap"
#: servers/visual_server.cpp
msgid "Quadrant 0 Subdiv"
-msgstr ""
+msgstr "Subdivisión del Cuadrante 0"
#: servers/visual_server.cpp
msgid "Quadrant 1 Subdiv"
-msgstr ""
+msgstr "Subdivisión del Cuadrante 1"
#: servers/visual_server.cpp
msgid "Quadrant 2 Subdiv"
-msgstr ""
+msgstr "Subdivisión del Cuadrante 2"
#: servers/visual_server.cpp
msgid "Quadrant 3 Subdiv"
-msgstr ""
+msgstr "Subdivisión del Cuadrante 3"
#: servers/visual_server.cpp
msgid "Shadows"
@@ -26986,11 +27010,11 @@ msgstr "Reflejos del Array de Texturas"
#: servers/visual_server.cpp
msgid "High Quality GGX"
-msgstr ""
+msgstr "GGX de Alta Calidad"
#: servers/visual_server.cpp
msgid "Irradiance Max Size"
-msgstr ""
+msgstr "Tamaño Máximo de Irradiancia"
#: servers/visual_server.cpp
msgid "Shading"
@@ -26998,19 +27022,19 @@ msgstr "Sombreado"
#: servers/visual_server.cpp
msgid "Force Vertex Shading"
-msgstr ""
+msgstr "Forzar Sombreado de Vértice"
#: servers/visual_server.cpp
msgid "Force Lambert Over Burley"
-msgstr ""
+msgstr "Forzar Lambert en Lugar de Burley"
#: servers/visual_server.cpp
msgid "Force Blinn Over GGX"
-msgstr ""
+msgstr "Forzar Blinn en Lugar de GGX"
#: servers/visual_server.cpp
msgid "Mesh Storage"
-msgstr ""
+msgstr "Almacenamiento de Malla"
#: servers/visual_server.cpp
msgid "Split Stream"
@@ -27018,7 +27042,7 @@ msgstr "Stream Dividido"
#: servers/visual_server.cpp
msgid "Use Physical Light Attenuation"
-msgstr ""
+msgstr "Usar Atenuación de Luz Física"
#: servers/visual_server.cpp
msgid "Depth Prepass"
@@ -27030,11 +27054,11 @@ msgstr ""
#: servers/visual_server.cpp
msgid "Anisotropic Filter Level"
-msgstr ""
+msgstr "Nivel de Filtro Anisotrópico"
#: servers/visual_server.cpp
msgid "Use Nearest Mipmap Filter"
-msgstr ""
+msgstr "Usar Filtro de Mapa MIP más Cercano"
#: servers/visual_server.cpp
msgid "Skinning"
@@ -27090,7 +27114,7 @@ msgstr "Usar División en Lotes en el Editor"
#: servers/visual_server.cpp
msgid "Single Rect Fallback"
-msgstr ""
+msgstr "Alternativa de Rect Único"
#: servers/visual_server.cpp
msgid "Max Join Item Commands"
@@ -27098,11 +27122,11 @@ msgstr ""
#: servers/visual_server.cpp
msgid "Colored Vertex Format Threshold"
-msgstr ""
+msgstr "Umbral de Formato de Vértice Coloreado"
#: servers/visual_server.cpp
msgid "Scissor Area Threshold"
-msgstr ""
+msgstr "Umbral de Ãrea de Corte"
#: servers/visual_server.cpp
msgid "Max Join Items"
@@ -27110,7 +27134,7 @@ msgstr "Elementos de Unión Máximos"
#: servers/visual_server.cpp
msgid "Batch Buffer Size"
-msgstr ""
+msgstr "Tamaño de Lote de Buffer"
#: servers/visual_server.cpp
msgid "Item Reordering Lookahead"
@@ -27126,7 +27150,7 @@ msgstr "Diagnosticar Cuadro"
#: servers/visual_server.cpp
msgid "GLES2"
-msgstr ""
+msgstr "GLES2"
#: servers/visual_server.cpp
msgid "Compatibility"
@@ -27134,7 +27158,7 @@ msgstr "Compatibilidad"
#: servers/visual_server.cpp
msgid "Disable Half Float"
-msgstr ""
+msgstr "Desactivar Float Medio"
#: servers/visual_server.cpp
msgid "Enable High Float"
@@ -27146,11 +27170,11 @@ msgstr "Precisión"
#: servers/visual_server.cpp
msgid "UV Contract"
-msgstr ""
+msgstr "Contracción UV"
#: servers/visual_server.cpp
msgid "UV Contract Amount"
-msgstr ""
+msgstr "Cantidad de Contracción UV"
#: servers/visual_server.cpp
msgid "Use Simple PVS"
@@ -27194,7 +27218,7 @@ msgstr "Compilaciones Simultáneas Máximas"
#: servers/visual_server.cpp
msgid "Log Active Async Compiles Count"
-msgstr ""
+msgstr "Anotar Número de Compilaciones Asíncronas Activas"
#: servers/visual_server.cpp
msgid "Shader Cache Size (MB)"
diff --git a/editor/translations/es_AR.po b/editor/translations/es_AR.po
index 5babe4ff23..fdb6b4f00d 100644
--- a/editor/translations/es_AR.po
+++ b/editor/translations/es_AR.po
@@ -21,13 +21,14 @@
# Manuel González <mgoopazo@gmail.com>, 2021.
# emnrx <emanuelermancia@gmail.com>, 2022.
# Mau_Restor <restor@gmail.com>, 2022.
+# Leonardo Martínez <leonardomartinez85@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-07-23 03:57+0000\n"
-"Last-Translator: Mau_Restor <restor@gmail.com>\n"
+"PO-Revision-Date: 2022-11-26 14:36+0000\n"
+"Last-Translator: emnrx <emanuelermancia@gmail.com>\n"
"Language-Team: Spanish (Argentina) <https://hosted.weblate.org/projects/"
"godot-engine/godot/es_AR/>\n"
"Language: es_AR\n"
@@ -35,7 +36,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.14-dev\n"
+"X-Generator: Weblate 4.15-dev\n"
#: core/bind/core_bind.cpp main/main.cpp
msgid "Tablet Driver"
@@ -71,7 +72,7 @@ msgstr "Modo de Bajo Uso del Procesador"
#: core/bind/core_bind.cpp
msgid "Low Processor Usage Mode Sleep (µsec)"
-msgstr ""
+msgstr "Modo de Baja Utilización del Procesador en Reposo (µseg)"
#: core/bind/core_bind.cpp main/main.cpp platform/uwp/os_uwp.cpp
msgid "Keep Screen On"
@@ -141,7 +142,7 @@ msgstr "Tamaño"
#: core/bind/core_bind.cpp
msgid "Endian Swap"
-msgstr ""
+msgstr "Intercambio Endiano"
#: core/bind/core_bind.cpp
msgid "Editor Hint"
@@ -248,20 +249,19 @@ msgstr "Conección"
#: core/io/http_client.cpp
msgid "Read Chunk Size"
-msgstr ""
+msgstr "Tamaño de fragmento de lectura"
#: core/io/marshalls.cpp
msgid "Object ID"
msgstr "ID de Objeto"
#: core/io/multiplayer_api.cpp core/io/packet_peer.cpp
-#, fuzzy
msgid "Allow Object Decoding"
-msgstr "Activar Onion Skinning"
+msgstr "Permitir decodificación de objetos"
#: core/io/multiplayer_api.cpp scene/main/scene_tree.cpp
msgid "Refuse New Network Connections"
-msgstr ""
+msgstr "Rechazar Nuevas Conexiones de Red"
#: core/io/multiplayer_api.cpp scene/main/scene_tree.cpp
#, fuzzy
@@ -309,9 +309,8 @@ msgid "Blocking Handshake"
msgstr ""
#: core/io/udp_server.cpp
-#, fuzzy
msgid "Max Pending Connections"
-msgstr "Editar Conexión:"
+msgstr "Máximo de Conexiones Pendientes"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
@@ -364,7 +363,6 @@ msgid "Seed"
msgstr "Semilla"
#: core/math/random_number_generator.cpp
-#, fuzzy
msgid "State"
msgstr "Estado"
@@ -381,9 +379,8 @@ msgid "Mouse Mode"
msgstr "Modo Mouse"
#: core/os/input.cpp
-#, fuzzy
msgid "Use Accumulated Input"
-msgstr "Eliminar Entrada"
+msgstr "Usar entrada acumulada"
#: core/os/input_event.cpp editor/project_settings_editor.cpp
#: servers/audio_server.cpp
@@ -411,9 +408,8 @@ msgid "Command"
msgstr "Comando"
#: core/os/input_event.cpp
-#, fuzzy
msgid "Physical"
-msgstr " (Física)"
+msgstr "Física"
#: core/os/input_event.cpp scene/2d/touch_screen_button.cpp
#: scene/gui/base_button.cpp scene/gui/texture_button.cpp
@@ -757,9 +753,8 @@ msgstr "Al Final de la interfaz de usuario"
#: servers/physics_2d/physics_2d_server_wrap_mt.h
#: servers/physics_2d/space_2d_sw.cpp servers/physics_2d_server.cpp
#: servers/physics_server.cpp
-#, fuzzy
msgid "Physics"
-msgstr " (Física)"
+msgstr "(Física)"
#: core/project_settings.cpp editor/editor_settings.cpp
#: editor/import/resource_importer_layered_texture.cpp
@@ -1073,7 +1068,7 @@ msgstr ""
#. TRANSLATORS: Adjective, refers to the mode for Bezier handles (Free, Balanced, Mirror).
#: editor/animation_bezier_editor.cpp
msgid "Free"
-msgstr "Gratis"
+msgstr "Libre"
#: editor/animation_bezier_editor.cpp
msgid "Balanced"
@@ -13119,9 +13114,10 @@ msgstr "Opciones de Ajuste"
#: scene/2d/path_2d.cpp scene/2d/polygon_2d.cpp scene/2d/sprite.cpp
#: scene/3d/cpu_particles.cpp scene/3d/label_3d.cpp scene/3d/path.cpp
#: scene/3d/physics_body.cpp scene/3d/soft_body.cpp scene/3d/sprite_3d.cpp
-#: 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
+#: scene/3d/visual_instance.cpp 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 "Offset:"
@@ -14563,16 +14559,17 @@ msgid "Invalid project path (changed anything?)."
msgstr "Ruta de proyecto inválida (cambiaste algo?)."
#: editor/project_manager.cpp
+#, fuzzy
msgid ""
-"Couldn't load project.godot in project path (error %d). It may be missing or "
-"corrupted."
+"Couldn't load project at '%s' (error %d). It may be missing or corrupted."
msgstr ""
"No se pudo cargar project.godot desde la ruta de proyecto (error %d). La "
"ruta no existe o está corrupta."
#: editor/project_manager.cpp
-msgid "Couldn't edit project.godot in project path."
-msgstr "No se pudo editar project.godot en la ruta de proyecto."
+#, fuzzy
+msgid "Couldn't save project at '%s' (error %d)."
+msgstr "No se puede abrir el proyecto en '%s'."
#: editor/project_manager.cpp
msgid "Couldn't create project.godot in project path."
@@ -19323,15 +19320,13 @@ msgid "Code Signing"
msgstr "Firmando código de 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 ""
-"No se ha encontrado 'apksigner'.\n"
-"Por favor, comprobá que el comando esté disponible en el directorio Android "
-"SDK build-tools.\n"
-"El %s resultante está sin firmar."
+"No se ha encontrado 'apksigner'. Por favor, comprobá que el comando esté "
+"disponible en el directorio Android SDK build-tools. El %s resultante está "
+"sin firmar."
#: platform/android/export/export_plugin.cpp
msgid "Signing debug %s..."
@@ -19380,9 +19375,8 @@ msgid "Invalid filename! Android APK requires the *.apk extension."
msgstr "¡Nombre de archivo inválido! Android APK requiere la extensión *.apk."
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Unsupported export format!"
-msgstr "¡Formato de exportación no soportado!\n"
+msgstr "¡Formato de exportación no soportado!"
#: platform/android/export/export_plugin.cpp
msgid ""
@@ -19394,16 +19388,13 @@ msgstr ""
"'Proyecto'."
#: 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 versión de compilación de Android no coincide:\n"
-" Plantilla instalada: %s\n"
-" Versión de Godot: %s\n"
-"Por favor, reinstalá la plantilla de compilación de Android desde el menú "
-"'Proyecto'."
+"La versión de compilación de Android no coincide: Plantilla instalada: %s, "
+"Versión de Godot: %s. Por favor, reinstalá la plantilla de compilación de "
+"Android desde el menú 'Proyecto'."
#: platform/android/export/export_plugin.cpp
#, fuzzy
@@ -19414,10 +19405,9 @@ msgstr ""
"el nombre del proyecto"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Could not export project files to gradle project."
msgstr ""
-"No se pudieron exportar los archivos del proyecto a un proyecto gradle\n"
+"No se pudieron exportar los archivos del proyecto a un proyecto gradle."
#: platform/android/export/export_plugin.cpp
msgid "Could not write expansion package file!"
@@ -19428,12 +19418,11 @@ msgid "Building Android Project (gradle)"
msgstr "Construir Proyecto 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 construcción del proyecto Android falló, comprueba la salida del error.\n"
+"La construcción del proyecto Android falló, comprueba la salida del error. "
"También podés visitar docs.godotengine.org para consultar la documentación "
"de compilación de Android."
@@ -19459,23 +19448,19 @@ msgid "Creating APK..."
msgstr "Creando APK..."
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Could not find template APK to export: \"%s\"."
-msgstr ""
-"No se pudo encontrar la plantilla APK para exportar:\n"
-"%s"
+msgstr "No se pudo encontrar la plantilla APK para exportar: %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 ""
"Bibliotecas faltantes en la plantilla de exportación para las arquitecturas "
-"seleccionadas: %s.\n"
-"Por favor, construya una plantilla con todas las bibliotecas necesarias, o "
-"desmarque las arquitecturas faltantes en el preset de exportación."
+"seleccionadas: %s. Por favor, construya una plantilla con todas las "
+"bibliotecas necesarias, o desmarque las arquitecturas faltantes en el preset "
+"de exportación."
#: platform/android/export/export_plugin.cpp
msgid "Adding files..."
@@ -20350,10 +20335,8 @@ msgid "ZIP Creation"
msgstr "Proyección"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Could not open file to read from path \"%s\"."
-msgstr ""
-"No se pudieron exportar los archivos del proyecto a un proyecto gradle\n"
+msgstr "No se pudieron exportar los archivos del proyecto a un proyecto gradle"
#: platform/osx/export/export.cpp
msgid "Invalid bundle identifier:"
@@ -22186,9 +22169,8 @@ msgid "Safe Margin"
msgstr "Margen Seguro"
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
-#, fuzzy
msgid "Sync To Physics"
-msgstr " (Física)"
+msgstr "(Física)"
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
#, fuzzy
@@ -23667,9 +23649,8 @@ msgid "A RoomGroup should not be a child or grandchild of a Portal."
msgstr "Un RoomGroup no debe ser hijo o nieto de un Portal."
#: scene/3d/portal.cpp
-#, fuzzy
msgid "Portal Active"
-msgstr " [portales activos]"
+msgstr "[portales activos]"
#: scene/3d/portal.cpp scene/resources/occluder_shape_polygon.cpp
msgid "Two Way"
@@ -24135,6 +24116,15 @@ msgstr "Error"
msgid "AABB"
msgstr ""
+#: scene/3d/visual_instance.cpp
+#, fuzzy
+msgid "Sorting"
+msgstr "Ordenar"
+
+#: scene/3d/visual_instance.cpp
+msgid "Use AABB Center"
+msgstr ""
+
#: scene/3d/visual_instance.cpp scene/resources/navigation_mesh.cpp
msgid "Geometry"
msgstr "Geometría"
@@ -25863,14 +25853,12 @@ msgid "3D Render"
msgstr "Renderizador:"
#: scene/register_scene_types.cpp
-#, fuzzy
msgid "2D Physics"
-msgstr " (Física)"
+msgstr "(Física)"
#: scene/register_scene_types.cpp
-#, fuzzy
msgid "3D Physics"
-msgstr " (Física)"
+msgstr "(Física)"
#: scene/register_scene_types.cpp
#, fuzzy
diff --git a/editor/translations/et.po b/editor/translations/et.po
index 0a4ab2fe0b..dc36ae0b94 100644
--- a/editor/translations/et.po
+++ b/editor/translations/et.po
@@ -12713,9 +12713,10 @@ msgstr "Intervall:"
#: scene/2d/path_2d.cpp scene/2d/polygon_2d.cpp scene/2d/sprite.cpp
#: scene/3d/cpu_particles.cpp scene/3d/label_3d.cpp scene/3d/path.cpp
#: scene/3d/physics_body.cpp scene/3d/soft_body.cpp scene/3d/sprite_3d.cpp
-#: 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
+#: scene/3d/visual_instance.cpp 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
msgid "Offset"
msgstr ""
@@ -14086,12 +14087,11 @@ msgstr ""
#: editor/project_manager.cpp
msgid ""
-"Couldn't load project.godot in project path (error %d). It may be missing or "
-"corrupted."
+"Couldn't load project at '%s' (error %d). It may be missing or corrupted."
msgstr ""
#: editor/project_manager.cpp
-msgid "Couldn't edit project.godot in project path."
+msgid "Couldn't save project at '%s' (error %d)."
msgstr ""
#: editor/project_manager.cpp
@@ -23119,6 +23119,15 @@ msgstr "Viga:"
msgid "AABB"
msgstr ""
+#: scene/3d/visual_instance.cpp
+#, fuzzy
+msgid "Sorting"
+msgstr "Salvestan faili:"
+
+#: scene/3d/visual_instance.cpp
+msgid "Use AABB Center"
+msgstr ""
+
#: scene/3d/visual_instance.cpp scene/resources/navigation_mesh.cpp
msgid "Geometry"
msgstr ""
diff --git a/editor/translations/eu.po b/editor/translations/eu.po
index c0f1953269..79da3d56fb 100644
--- a/editor/translations/eu.po
+++ b/editor/translations/eu.po
@@ -2,7 +2,7 @@
# Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur.
# Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md).
# This file is distributed under the same license as the Godot source code.
-# Julen Irazoki <rktzbkr.julen@gmail.com>, 2019.
+# Julen Irazoki <rktzbkr.julen@gmail.com>, 2019, 2022.
# Osoitz <oelkoro@gmail.com>, 2019, 2020.
# Erik Zubiria <erik@ezsd.net>, 2021.
# Sergio Varela <sergitroll9@gmail.com>, 2021.
@@ -11,15 +11,15 @@ msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"Report-Msgid-Bugs-To: https://github.com/godotengine/godot\n"
-"PO-Revision-Date: 2022-05-23 21:52+0000\n"
-"Last-Translator: Gorka Egino <gorkainventor@gmail.com>\n"
+"PO-Revision-Date: 2022-11-06 03:12+0000\n"
+"Last-Translator: Julen Irazoki <rktzbkr.julen@gmail.com>\n"
"Language-Team: Basque <https://hosted.weblate.org/projects/godot-engine/"
"godot/eu/>\n"
"Language: eu\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.13-dev\n"
+"X-Generator: Weblate 4.14.2\n"
#: core/bind/core_bind.cpp main/main.cpp
msgid "Tablet Driver"
@@ -2064,7 +2064,7 @@ msgstr ""
#: editor/connections_dialog.cpp editor/editor_help.cpp editor/node_dock.cpp
msgid "Signals"
-msgstr ""
+msgstr "Seinaleak"
#: editor/connections_dialog.cpp
msgid "Filter signals"
@@ -3676,7 +3676,7 @@ msgstr ""
#: editor/editor_network_profiler.cpp editor/editor_node.cpp
#: scene/main/node.cpp scene/resources/default_theme/default_theme.cpp
msgid "Node"
-msgstr ""
+msgstr "Nodoa"
#: editor/editor_network_profiler.cpp
msgid "Incoming RPC"
@@ -12662,9 +12662,10 @@ msgstr "Atxikitze aukerak"
#: scene/2d/path_2d.cpp scene/2d/polygon_2d.cpp scene/2d/sprite.cpp
#: scene/3d/cpu_particles.cpp scene/3d/label_3d.cpp scene/3d/path.cpp
#: scene/3d/physics_body.cpp scene/3d/soft_body.cpp scene/3d/sprite_3d.cpp
-#: 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
+#: scene/3d/visual_instance.cpp 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
msgid "Offset"
msgstr ""
@@ -14022,12 +14023,11 @@ msgstr ""
#: editor/project_manager.cpp
msgid ""
-"Couldn't load project.godot in project path (error %d). It may be missing or "
-"corrupted."
+"Couldn't load project at '%s' (error %d). It may be missing or corrupted."
msgstr ""
#: editor/project_manager.cpp
-msgid "Couldn't edit project.godot in project path."
+msgid "Couldn't save project at '%s' (error %d)."
msgstr ""
#: editor/project_manager.cpp
@@ -22940,6 +22940,15 @@ msgstr "Ispilua"
msgid "AABB"
msgstr ""
+#: scene/3d/visual_instance.cpp
+#, fuzzy
+msgid "Sorting"
+msgstr "Atxikitze ezarpenak"
+
+#: scene/3d/visual_instance.cpp
+msgid "Use AABB Center"
+msgstr ""
+
#: scene/3d/visual_instance.cpp scene/resources/navigation_mesh.cpp
msgid "Geometry"
msgstr ""
diff --git a/editor/translations/extract.py b/editor/translations/extract.py
index cecdb3939d..04661abcbd 100755
--- a/editor/translations/extract.py
+++ b/editor/translations/extract.py
@@ -71,11 +71,24 @@ matches.sort()
remaps = {}
remap_re = re.compile(r'^\t*capitalize_string_remaps\["(?P<from>.+)"\] = (String::utf8\()?"(?P<to>.+)"')
+stop_words = set()
+stop_words_re = re.compile(r'^\t*"(?P<word>.+)",')
+is_inside_stop_words = False
with open("editor/editor_property_name_processor.cpp") as f:
for line in f:
- m = remap_re.search(line)
- if m:
- remaps[m.group("from")] = m.group("to")
+ if is_inside_stop_words:
+ m = stop_words_re.search(line)
+ if m:
+ stop_words.add(m.group("word"))
+ else:
+ is_inside_stop_words = False
+ else:
+ m = remap_re.search(line)
+ if m:
+ remaps[m.group("from")] = m.group("to")
+
+ if not is_inside_stop_words and not stop_words:
+ is_inside_stop_words = "stop_words = " in line
main_po = """
@@ -147,9 +160,12 @@ capitalize_re = re.compile(r"(?<=\D)(?=\d)|(?<=\d)(?=\D([a-z]|\d))")
def _process_editor_string(name):
# See EditorPropertyNameProcessor::process_string().
capitalized_parts = []
- for segment in name.split("_"):
- if not segment:
+ parts = list(filter(bool, name.split("_"))) # Non-empty only.
+ for i, segment in enumerate(parts):
+ if i > 0 and i + 1 < len(parts) and segment in stop_words:
+ capitalized_parts.append(segment)
continue
+
remapped = remaps.get(segment)
if remapped:
capitalized_parts.append(remapped)
diff --git a/editor/translations/fa.po b/editor/translations/fa.po
index 28371fdd50..ad2a56e408 100644
--- a/editor/translations/fa.po
+++ b/editor/translations/fa.po
@@ -32,13 +32,14 @@
# John Smith <pkafsharix@gmail.com>, 2022.
# Ali Jafari <ali.jafari.sn@gmail.com>, 2022.
# Ali Almasi <A710almasi@gmail.com>, 2022.
+# 2g.2d.2t <2g.2d.2t@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-09-19 05:22+0000\n"
-"Last-Translator: Ali Jafari <ali.jafari.sn@gmail.com>\n"
+"PO-Revision-Date: 2022-11-16 22:47+0000\n"
+"Last-Translator: 2g.2d.2t <2g.2d.2t@gmail.com>\n"
"Language-Team: Persian <https://hosted.weblate.org/projects/godot-engine/"
"godot/fa/>\n"
"Language: fa\n"
@@ -46,7 +47,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.14.1\n"
+"X-Generator: Weblate 4.15-dev\n"
#: core/bind/core_bind.cpp main/main.cpp
msgid "Tablet Driver"
@@ -314,9 +315,8 @@ msgid "Data Array"
msgstr "آرایه داده"
#: core/io/stream_peer_ssl.cpp
-#, fuzzy
msgid "Blocking Handshake"
-msgstr "مسدود کردن دست دادن"
+msgstr "مسدود کردن تکان دادن دست"
#: core/io/udp_server.cpp
msgid "Max Pending Connections"
@@ -533,7 +533,6 @@ msgid "Velocity"
msgstr "سرعت"
#: core/os/input_event.cpp
-#, fuzzy
msgid "Instrument"
msgstr "ابزار"
@@ -699,9 +698,8 @@ msgid "UI Select"
msgstr "انتخاب رابط کاربری"
#: core/project_settings.cpp
-#, fuzzy
msgid "UI Cancel"
-msgstr "لغو"
+msgstr "لغو رابط کاربری"
#: core/project_settings.cpp
#, fuzzy
@@ -13185,9 +13183,10 @@ msgstr "تنها در قسمت انتخاب شده"
#: scene/2d/path_2d.cpp scene/2d/polygon_2d.cpp scene/2d/sprite.cpp
#: scene/3d/cpu_particles.cpp scene/3d/label_3d.cpp scene/3d/path.cpp
#: scene/3d/physics_body.cpp scene/3d/soft_body.cpp scene/3d/sprite_3d.cpp
-#: 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
+#: scene/3d/visual_instance.cpp 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
msgid "Offset"
msgstr ""
@@ -14613,13 +14612,13 @@ msgstr ""
#: editor/project_manager.cpp
msgid ""
-"Couldn't load project.godot in project path (error %d). It may be missing or "
-"corrupted."
+"Couldn't load project at '%s' (error %d). It may be missing or corrupted."
msgstr ""
#: editor/project_manager.cpp
-msgid "Couldn't edit project.godot in project path."
-msgstr ""
+#, fuzzy
+msgid "Couldn't save project at '%s' (error %d)."
+msgstr "ناتوان در گشودن پروژه"
#: editor/project_manager.cpp
msgid "Couldn't create project.godot in project path."
@@ -23946,6 +23945,15 @@ msgstr "بازتاب"
msgid "AABB"
msgstr ""
+#: scene/3d/visual_instance.cpp
+#, fuzzy
+msgid "Sorting"
+msgstr "مرتب‌سازی:"
+
+#: scene/3d/visual_instance.cpp
+msgid "Use AABB Center"
+msgstr ""
+
#: scene/3d/visual_instance.cpp scene/resources/navigation_mesh.cpp
msgid "Geometry"
msgstr ""
diff --git a/editor/translations/fi.po b/editor/translations/fi.po
index bb73facb22..8aeba71bff 100644
--- a/editor/translations/fi.po
+++ b/editor/translations/fi.po
@@ -13,13 +13,14 @@
# Matti Niskanen <matti.t.niskanen@gmail.com>, 2020.
# Severi Vidnäs <severi.vidnas@gmail.com>, 2021.
# Akseli Pihlajamaa <akselijuhanipihlajamaa@gmail.com>, 2022.
+# Hannu Lammi <hpl@kapsi.fi>, 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-09-11 22:22+0000\n"
-"Last-Translator: Akseli Pihlajamaa <akselijuhanipihlajamaa@gmail.com>\n"
+"PO-Revision-Date: 2022-10-27 01:11+0000\n"
+"Last-Translator: Hannu Lammi <hpl@kapsi.fi>\n"
"Language-Team: Finnish <https://hosted.weblate.org/projects/godot-engine/"
"godot/fi/>\n"
"Language: fi\n"
@@ -27,7 +28,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.14.1-dev\n"
+"X-Generator: Weblate 4.14.2-dev\n"
#: core/bind/core_bind.cpp main/main.cpp
msgid "Tablet Driver"
@@ -137,9 +138,8 @@ msgstr "Telakan sijainti"
#: 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 "Koko:"
+msgstr "Koko"
#: core/bind/core_bind.cpp
msgid "Endian Swap"
@@ -152,7 +152,7 @@ msgstr "Editori"
#: core/bind/core_bind.cpp
msgid "Print Error Messages"
-msgstr ""
+msgstr "Tulosta virheilmoitukset"
#: core/bind/core_bind.cpp
#, fuzzy
@@ -195,7 +195,7 @@ msgstr "Haun tulokset"
#: core/command_queue_mt.cpp core/message_queue.cpp main/main.cpp
msgid "Memory"
-msgstr ""
+msgstr "Muisti"
#: core/command_queue_mt.cpp core/message_queue.cpp
#: core/register_core_types.cpp drivers/gles2/rasterizer_canvas_base_gles2.cpp
@@ -458,7 +458,7 @@ msgstr "Fyysinen avain"
#: core/os/input_event.cpp
msgid "Unicode"
-msgstr ""
+msgstr "Unicode"
#: core/os/input_event.cpp
msgid "Echo"
@@ -486,7 +486,7 @@ msgstr "Hiiren painikkeen indeksi:"
#: core/os/input_event.cpp
msgid "Doubleclick"
-msgstr ""
+msgstr "Kaksoisnapsautus"
#: core/os/input_event.cpp
msgid "Tilt"
@@ -510,9 +510,8 @@ msgstr "Suhteellinen tarttuminen"
#: scene/3d/cpu_particles.cpp scene/3d/interpolated_camera.cpp
#: scene/animation/animation_player.cpp scene/resources/environment.cpp
#: scene/resources/particles_material.cpp
-#, fuzzy
msgid "Speed"
-msgstr "Nopeus:"
+msgstr "Nopeus"
#: core/os/input_event.cpp editor/project_settings_editor.cpp
#: scene/3d/sprite_3d.cpp
@@ -525,9 +524,8 @@ msgid "Axis Value"
msgstr "Kiinnitä arvo"
#: core/os/input_event.cpp modules/visual_script/visual_script_func_nodes.cpp
-#, fuzzy
msgid "Index"
-msgstr "Indeksi:"
+msgstr "Indeksi"
#: core/os/input_event.cpp editor/project_settings_editor.cpp
#: modules/visual_script/visual_script_nodes.cpp
@@ -639,15 +637,15 @@ msgstr "Toimintakyvytön osanen"
#: core/project_settings.cpp
msgid "Use Hidden Project Data Directory"
-msgstr ""
+msgstr "Käytä piilotettua projektin datahakemistoa"
#: core/project_settings.cpp
msgid "Use Custom User Dir"
-msgstr ""
+msgstr "Käytä mukautettua käyttäjähakemistoa"
#: core/project_settings.cpp
msgid "Custom User Dir Name"
-msgstr ""
+msgstr "Mukautetun käyttäjähakemiston nimi"
#: core/project_settings.cpp main/main.cpp
#: platform/javascript/export/export.cpp platform/osx/export/export.cpp
@@ -660,7 +658,7 @@ msgstr "Näytä kaikki"
#: 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 "Leveys"
#: core/project_settings.cpp main/main.cpp modules/csg/csg_shape.cpp
#: modules/gltf/gltf_node.cpp modules/opensimplex/noise_texture.cpp
@@ -674,7 +672,7 @@ msgstr "Valo"
#: core/project_settings.cpp
msgid "Always On Top"
-msgstr ""
+msgstr "Aina päällimmäisenä"
#: core/project_settings.cpp
#, fuzzy
@@ -818,7 +816,7 @@ msgstr " (fyysinen)"
#: scene/3d/physics_body.cpp scene/resources/world.cpp
#: servers/physics/space_sw.cpp servers/physics_server.cpp
msgid "3D"
-msgstr ""
+msgstr "3D"
#: core/project_settings.cpp
#, fuzzy
@@ -846,7 +844,7 @@ msgstr "Renderöijä:"
#: scene/resources/multimesh.cpp servers/visual/visual_server_scene.cpp
#: servers/visual_server.cpp
msgid "Quality"
-msgstr ""
+msgstr "Laatu"
#: core/project_settings.cpp scene/gui/file_dialog.cpp
#: scene/main/scene_tree.cpp scene/resources/navigation_mesh.cpp
@@ -915,15 +913,15 @@ msgstr ""
#: 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"
@@ -931,7 +929,7 @@ msgstr ""
#: core/register_core_types.cpp
msgid "TCP"
-msgstr ""
+msgstr "TCP"
#: core/register_core_types.cpp
#, fuzzy
@@ -948,7 +946,7 @@ msgstr ""
#: 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
#, fuzzy
@@ -1047,7 +1045,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
@@ -1126,7 +1124,7 @@ msgstr ""
#: drivers/gles3/rasterizer_scene_gles3.cpp scene/resources/environment.cpp
msgid "High Quality"
-msgstr ""
+msgstr "Korkea laatu"
#: drivers/gles3/rasterizer_storage_gles3.cpp
msgid "Blend Shape Max Buffer Size (KB)"
@@ -1399,9 +1397,8 @@ msgid "Remove this track."
msgstr "Poista tämä raita."
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Time (s):"
-msgstr "Aika (s): "
+msgstr "Aika (s):"
#: editor/animation_track_editor.cpp
#, fuzzy
@@ -1680,9 +1677,8 @@ msgid "Add Method Track Key"
msgstr "Lisää metodikutsuraidan avainruutu"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Method not found in object:"
-msgstr "Metodia ei löydy objektista: "
+msgstr "Metodia ei löydy objektista:"
#: editor/animation_track_editor.cpp
msgid "Anim Move Keys"
@@ -1702,7 +1698,7 @@ msgstr "Metodit"
#: editor/animation_track_editor.cpp
msgid "Bezier"
-msgstr ""
+msgstr "Bezier"
#: editor/animation_track_editor.cpp
#: modules/visual_script/visual_script_editor.cpp
@@ -2857,7 +2853,7 @@ msgstr "Valitse"
#: editor/editor_export.cpp
msgid "Project export for platform:"
-msgstr ""
+msgstr "Projektin vienti alustalle:"
#: editor/editor_export.cpp
#, fuzzy
@@ -2865,14 +2861,12 @@ msgid "Completed with warnings."
msgstr "Kopioi solmun polku"
#: editor/editor_export.cpp
-#, fuzzy
msgid "Completed successfully."
-msgstr "Paketti asennettu onnistuneesti!"
+msgstr "Paketti asennettu onnistuneesti."
#: editor/editor_export.cpp
-#, fuzzy
msgid "Failed."
-msgstr "Epäonnistui:"
+msgstr "Epäonnistui."
#: editor/editor_export.cpp
msgid "Storing File:"
@@ -2897,14 +2891,12 @@ msgid "Cannot create file \"%s\"."
msgstr "Kansiota ei voitu luoda."
#: editor/editor_export.cpp
-#, fuzzy
msgid "Failed to export project files."
-msgstr "Ei voitu viedä projektin tiedostoja"
+msgstr "Ei voitu viedä projektin tiedostoja."
#: editor/editor_export.cpp
-#, fuzzy
msgid "Can't open file to read from path \"%s\"."
-msgstr "Ei voida avata tiedostoa kirjoitettavaksi:"
+msgstr "Ei voida avata tiedostoa luettavaksi polulta \"%s\"."
#: editor/editor_export.cpp
#, fuzzy
@@ -2986,7 +2978,7 @@ msgstr "Värioperaattori."
#: editor/editor_export.cpp
msgid "64 Bits"
-msgstr ""
+msgstr "64 bittiä"
#: editor/editor_export.cpp
msgid "Embed PCK"
@@ -2999,19 +2991,19 @@ msgstr "Tekstuurialue"
#: 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
#, fuzzy
@@ -3036,19 +3028,16 @@ msgid "Prepare Template"
msgstr "Hallinnoi malleja"
#: editor/editor_export.cpp platform/osx/export/export.cpp
-#, fuzzy
msgid "The given export path doesn't exist."
-msgstr "Annettu vientipolku ei ole olemassa:"
+msgstr "Annettu vientipolku ei ole olemassa."
#: editor/editor_export.cpp platform/javascript/export/export.cpp
-#, fuzzy
msgid "Template file not found: \"%s\"."
-msgstr "Mallitiedostoa ei löytynyt:"
+msgstr "Mallitiedostoa \"%s\" ei löytynyt."
#: editor/editor_export.cpp
-#, fuzzy
msgid "Failed to copy export template."
-msgstr "Virheellinen vientimalli:"
+msgstr "Vientimallin kopiointi epäonnistui."
#: editor/editor_export.cpp platform/windows/export/export.cpp
#: platform/x11/export/export.cpp
@@ -5253,9 +5242,8 @@ msgid "Size:"
msgstr "Koko:"
#: editor/editor_properties_array_dict.cpp
-#, fuzzy
msgid "Page:"
-msgstr "Sivu: "
+msgstr "Sivu:"
#: editor/editor_properties_array_dict.cpp
#: editor/plugins/theme_editor_plugin.cpp
@@ -5548,9 +5536,8 @@ msgid "File Dialog"
msgstr "XForm-ikkuna"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Thumbnail Size"
-msgstr "Pienoiskuva..."
+msgstr "Pienoiskuvan koko"
#: editor/editor_settings.cpp
msgid "Docks"
@@ -6212,9 +6199,8 @@ msgid "Auto Save"
msgstr "Jaa automaattisesti"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Save Before Running"
-msgstr "Tallenna kohtaus ennen suorittamista..."
+msgstr "Tallenna kohtaus ennen suorittamista"
#: editor/editor_settings.cpp
#, fuzzy
@@ -6300,9 +6286,8 @@ msgstr "Varastoidaan tiedostoa:"
#: 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 "Virheellinen taustaväri."
+msgstr "Taustaväri"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
#, fuzzy
@@ -8450,9 +8435,8 @@ msgid "Set the end animation. This is useful for sub-transitions."
msgstr "Aseta loppuanimaatio. Tämä on hyödyllistä alisiirtymiä varten."
#: editor/plugins/animation_state_machine_editor.cpp
-#, fuzzy
msgid "Transition:"
-msgstr "Siirtymä: "
+msgstr "Siirtymä:"
#: editor/plugins/animation_state_machine_editor.cpp
msgid "Play Mode:"
@@ -10226,9 +10210,8 @@ msgid "Volume"
msgstr "Tilavuus"
#: editor/plugins/particles_editor_plugin.cpp
-#, fuzzy
msgid "Emission Source:"
-msgstr "Emission lähde: "
+msgstr "Emission lähde:"
#: editor/plugins/particles_editor_plugin.cpp
msgid "A processor material of type 'ParticlesMaterial' is required."
@@ -11879,19 +11862,16 @@ msgid "Sprite"
msgstr "Sprite"
#: editor/plugins/sprite_editor_plugin.cpp
-#, fuzzy
msgid "Simplification:"
-msgstr "Yksinkertaistus: "
+msgstr "Yksinkertaistus:"
#: editor/plugins/sprite_editor_plugin.cpp
-#, fuzzy
msgid "Shrink (Pixels):"
-msgstr "Kutista (pikseleissä): "
+msgstr "Kutista (pikseleissä):"
#: editor/plugins/sprite_editor_plugin.cpp
-#, fuzzy
msgid "Grow (Pixels):"
-msgstr "Suurrennus (pikseleissä): "
+msgstr "Suurrennus (pikseleissä):"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Update Preview"
@@ -13150,9 +13130,10 @@ msgstr "Tarttumisen asetukset"
#: scene/2d/path_2d.cpp scene/2d/polygon_2d.cpp scene/2d/sprite.cpp
#: scene/3d/cpu_particles.cpp scene/3d/label_3d.cpp scene/3d/path.cpp
#: scene/3d/physics_body.cpp scene/3d/soft_body.cpp scene/3d/sprite_3d.cpp
-#: 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
+#: scene/3d/visual_instance.cpp 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 "Siirtymä:"
@@ -14481,14 +14462,12 @@ msgid "More Info..."
msgstr "Siirrä..."
#: editor/project_export.cpp
-#, fuzzy
msgid "Export PCK/Zip..."
-msgstr "Vie PCK/Zip"
+msgstr "Vie PCK/Zip..."
#: editor/project_export.cpp
-#, fuzzy
msgid "Export Project..."
-msgstr "Vie projekti"
+msgstr "Vie projekti..."
#: editor/project_export.cpp
msgid "Export All"
@@ -14500,9 +14479,8 @@ msgid "Choose an export mode:"
msgstr "Ole hyvä ja valitse tyhjä kansio."
#: editor/project_export.cpp
-#, fuzzy
msgid "Export All..."
-msgstr "Vie kaikki"
+msgstr "Vie kaikki..."
#: editor/project_export.cpp editor/project_manager.cpp
msgid "ZIP File"
@@ -14586,16 +14564,17 @@ msgid "Invalid project path (changed anything?)."
msgstr "Virheellinen projektin polku (muuttuiko mikään?)."
#: editor/project_manager.cpp
+#, fuzzy
msgid ""
-"Couldn't load project.godot in project path (error %d). It may be missing or "
-"corrupted."
+"Couldn't load project at '%s' (error %d). It may be missing or corrupted."
msgstr ""
"Tiedoston project.godot lataus projektin polusta epäonnistui (virhe %d). Se "
"saattaa puuttua tai olla vioittunut."
#: editor/project_manager.cpp
-msgid "Couldn't edit project.godot in project path."
-msgstr "Ei voitu muokata project.godot tiedostoa projektin polussa."
+#, fuzzy
+msgid "Couldn't save project at '%s' (error %d)."
+msgstr "Ei voida avata projektia kohteesta '%s'."
#: editor/project_manager.cpp
msgid "Couldn't create project.godot in project path."
@@ -17139,9 +17118,8 @@ msgid "Disabled GDNative Singleton"
msgstr "GDNative singleton on poistettu käytöstä"
#: modules/gdnative/gdnative_library_singleton_editor.cpp
-#, fuzzy
msgid "Libraries:"
-msgstr "Kirjastot: "
+msgstr "Kirjastot:"
#: modules/gdnative/nativescript/nativescript.cpp
#, fuzzy
@@ -18063,18 +18041,16 @@ msgstr ""
"korjaa solmusi."
#: modules/visual_script/visual_script.cpp
-#, fuzzy
msgid "Node returned an invalid sequence output:"
-msgstr "Solmu palautti virheellisen jakson tulosteen: "
+msgstr "Solmu palautti virheellisen jakson tulosteen:"
#: modules/visual_script/visual_script.cpp
msgid "Found sequence bit but not the node in the stack, report bug!"
msgstr "Jaksobitti löytyi, mutta solmua ei löydy pinosta, raportoi bugi!"
#: modules/visual_script/visual_script.cpp
-#, fuzzy
msgid "Stack overflow with stack depth:"
-msgstr "Pinon ylivuoto pinosyvyydellä: "
+msgstr "Pinon ylivuoto pinosyvyydellä:"
#: modules/visual_script/visual_script.cpp
#, fuzzy
@@ -18444,18 +18420,16 @@ msgid "for (elem) in (input):"
msgstr "kullekin (elementille) (syötteessä):"
#: modules/visual_script/visual_script_flow_control.cpp
-#, fuzzy
msgid "Input type not iterable:"
-msgstr "Syötetyyppi ei ole iteroitavissa: "
+msgstr "Syötetyyppi ei ole iteroitavissa:"
#: modules/visual_script/visual_script_flow_control.cpp
msgid "Iterator became invalid"
msgstr "Iteraattori muuttui epäkelvoksi"
#: modules/visual_script/visual_script_flow_control.cpp
-#, fuzzy
msgid "Iterator became invalid:"
-msgstr "Iteraattori muuttui epäkelvoksi: "
+msgstr "Iteraattori muuttui epäkelvoksi:"
#: modules/visual_script/visual_script_flow_control.cpp
msgid "Sequence"
@@ -18613,19 +18587,16 @@ msgstr "Laadi taulukko"
#: modules/visual_script/visual_script_nodes.cpp scene/resources/material.cpp
#: scene/resources/visual_shader_nodes.cpp
-#, fuzzy
msgid "Operator"
-msgstr "Iteraattori"
+msgstr "Operaattori"
#: modules/visual_script/visual_script_nodes.cpp
-#, fuzzy
msgid "Invalid argument of type:"
-msgstr ": Virheellinen argumentti tyyppiä: "
+msgstr "Virheellinen argumentti tyyppiä:"
#: modules/visual_script/visual_script_nodes.cpp
-#, fuzzy
msgid "Invalid arguments:"
-msgstr ": Virheelliset argumentit: "
+msgstr "Virheelliset argumentit:"
#: modules/visual_script/visual_script_nodes.cpp
msgid "a if cond, else b"
@@ -18637,14 +18608,12 @@ msgid "Var Name"
msgstr "Nimi"
#: modules/visual_script/visual_script_nodes.cpp
-#, fuzzy
msgid "VariableGet not found in script:"
-msgstr "VariableGet ei löytynyt skriptistä: "
+msgstr "VariableGet ei löytynyt skriptistä:"
#: modules/visual_script/visual_script_nodes.cpp
-#, fuzzy
msgid "VariableSet not found in script:"
-msgstr "VariableSet ei löytynyt skriptistä: "
+msgstr "VariableSet ei löytynyt skriptistä:"
#: modules/visual_script/visual_script_nodes.cpp
msgid "Preload"
@@ -19341,15 +19310,13 @@ msgid "Code Signing"
msgstr "Allekirjoitetaan DMG-koodi"
#: 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' ei löydy.\n"
-"Ole hyvä ja tarkista, että komento on saatavilla Android SDK build-tools "
-"hakemistossa.\n"
-"Tuloksena syntynyt %s on allekirjoittamaton."
+"'apksigner' ei löydy. Ole hyvä ja tarkista, että komento on saatavilla "
+"Android SDK build-tools hakemistossa. Tuloksena syntynyt %s on "
+"allekirjoittamaton."
#: platform/android/export/export_plugin.cpp
msgid "Signing debug %s..."
@@ -19364,9 +19331,8 @@ msgid "Could not find keystore, unable to export."
msgstr "Keystorea ei löytynyt, ei voida viedä."
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Could not start apksigner executable."
-msgstr "Aliprosessia ei voitu käynnistää!"
+msgstr "apkgsigner-käynnistystiedostoa ei voitu käynnistää."
#: platform/android/export/export_plugin.cpp
msgid "'apksigner' returned with error #%d"
@@ -19400,9 +19366,8 @@ msgstr ""
"Virheellinen tiedostonimi! Android APK tarvitsee *.apk tiedostopäätteen."
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Unsupported export format!"
-msgstr "Vientiformaatti ei ole tuettu!\n"
+msgstr "Vientiformaatti ei ole tuettu!"
#: platform/android/export/export_plugin.cpp
msgid ""
@@ -19413,28 +19378,24 @@ msgstr ""
"versiotietoa. Ole hyvä ja uudelleenasenna se 'Projekti'-valikosta."
#: 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 ""
-"Androidin käännösversion epäyhteensopivuus:\n"
-" Malli asennettu: %s\n"
-" Godotin versio: %s\n"
-"Ole hyvä ja uudelleenasenna Androidin käännösmalli 'Projekti'-valikosta."
+"Androidin käännösversion epäyhteensopivuus: Malli asennettu: %s, Godotin "
+"versio: %s. Ole hyvä ja uudelleenasenna Androidin käännösmalli 'Projekti'-"
+"valikosta."
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid ""
"Unable to overwrite res://android/build/res/*.xml files with project name."
msgstr ""
"Ei voitu ylikirjoittaa res://android/build/res/*.xml tiedostoja projektin "
-"nimellä"
+"nimellä."
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Could not export project files to gradle project."
-msgstr "Ei voitu viedä projektitiedostoja gradle-projektiksi.\n"
+msgstr "Ei voitu viedä projektitiedostoja gradle-projektiksi."
#: platform/android/export/export_plugin.cpp
msgid "Could not write expansion package file!"
@@ -19445,12 +19406,11 @@ msgid "Building Android Project (gradle)"
msgstr "Käännetään Android-projektia (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-projektin käännös epäonnistui, tarkista virhe tulosteesta.\n"
+"Android-projektin käännös epäonnistui, tarkista virhe tulosteesta. "
"Vaihtoehtoisesti, lue docs.godotengine.org sivustolta Androidin "
"käännösdokumentaatio."
@@ -19467,30 +19427,25 @@ msgstr ""
"tulosteet gradle-projektin hakemistosta."
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Package not found: \"%s\"."
-msgstr "Pakettia ei löytynyt: %s"
+msgstr "Pakettia ei löytynyt: \"%s\"."
#: platform/android/export/export_plugin.cpp
msgid "Creating APK..."
msgstr "Luodaan APK:ta..."
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Could not find template APK to export: \"%s\"."
-msgstr ""
-"Ei löydetty APK-vientimallia vientiä varten:\n"
-"%s"
+msgstr "Ei löydetty APK-vientimallia vientiä varten: \"%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 ""
-"Vientimalleista puuttuu kirjastoja valituille arkkitehtuureille: %s.\n"
-"Ole hyvä ja kokoa malli, jossa on kaikki tarvittavat kirjastot, tai poista "
+"Vientimalleista puuttuu kirjastoja valituille arkkitehtuureille: %s. Ole "
+"hyvä ja kokoa malli, jossa on kaikki tarvittavat kirjastot, tai poista "
"puuttuvien arkkitehtuurien valinta viennin esiasetuksista."
#: platform/android/export/export_plugin.cpp
@@ -19498,9 +19453,8 @@ msgid "Adding files..."
msgstr "Lisätään tiedostoja..."
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Could not export project files."
-msgstr "Ei voitu viedä projektin tiedostoja"
+msgstr "Ei voitu viedä projektin tiedostoja."
#: platform/android/export/export_plugin.cpp
msgid "Aligning APK..."
@@ -19779,19 +19733,16 @@ msgid "Run exported HTML in the system's default browser."
msgstr "Suorita viety HTML järjestelmän oletusselaimessa."
#: platform/javascript/export/export.cpp
-#, fuzzy
msgid "Could not open template for export: \"%s\"."
-msgstr "Mallin avaus vientiin epäonnistui:"
+msgstr "Mallin avaus vientiin epäonnistui: \"%s\"."
#: platform/javascript/export/export.cpp
-#, fuzzy
msgid "Invalid export template: \"%s\"."
-msgstr "Virheellinen vientimalli:"
+msgstr "Virheellinen vientimalli: \"%s\"."
#: platform/javascript/export/export.cpp
-#, fuzzy
msgid "Could not write file: \"%s\"."
-msgstr "Ei voitu kirjoittaa tiedostoa:"
+msgstr "Ei voitu kirjoittaa tiedostoa: \"%s\"."
#: platform/javascript/export/export.cpp platform/osx/export/export.cpp
#, fuzzy
@@ -19799,9 +19750,8 @@ msgid "Icon Creation"
msgstr "Aseta marginaali"
#: platform/javascript/export/export.cpp
-#, fuzzy
msgid "Could not read file: \"%s\"."
-msgstr "Ei voitu lukea tiedostoa:"
+msgstr "Ei voitu lukea tiedostoa: \"%s\"."
#: platform/javascript/export/export.cpp
msgid "PWA"
@@ -19882,19 +19832,16 @@ msgid "Icon 512 X 512"
msgstr ""
#: platform/javascript/export/export.cpp
-#, fuzzy
msgid "Could not read HTML shell: \"%s\"."
-msgstr "Ei voitu lukea HTML tulkkia:"
+msgstr "Ei voitu lukea HTML tulkkia: \"%s\"."
#: platform/javascript/export/export.cpp
-#, fuzzy
msgid "Could not create HTTP server directory: %s."
-msgstr "Ei voitu luoda HTTP-palvelimen hakemistoa:"
+msgstr "Ei voitu luoda HTTP-palvelimen hakemistoa: %s."
#: platform/javascript/export/export.cpp
-#, fuzzy
msgid "Error starting HTTP server: %d."
-msgstr "Virhe käynnistettäessä HTTP-palvelinta:"
+msgstr "Virhe käynnistettäessä HTTP-palvelinta: %d."
#: platform/javascript/export/export.cpp
msgid "Web"
@@ -20191,9 +20138,8 @@ msgid "Could not open icon file \"%s\"."
msgstr "Ei voitu viedä projektin tiedostoja"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Could not start xcrun executable."
-msgstr "Aliprosessia ei voitu käynnistää!"
+msgstr "xcrun-käynnistystiedostoa ei voitu käynnistää."
#: platform/osx/export/export.cpp
#, fuzzy
@@ -20280,9 +20226,8 @@ msgid "DMG Creation"
msgstr "Suunnat"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Could not start hdiutil executable."
-msgstr "Aliprosessia ei voitu käynnistää!"
+msgstr "hkiutil-käynnistystiedostoa ei voitu käynnistää."
#: platform/osx/export/export.cpp
msgid "`hdiutil create` failed - file exists."
@@ -20302,9 +20247,8 @@ msgid "Could not find template app to export: \"%s\"."
msgstr "Ei löydetty app-vientimallia vientiä varten:"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Invalid export format."
-msgstr "Virheellinen vientimalli:"
+msgstr "Virheellinen vientimalli."
#: platform/osx/export/export.cpp
msgid ""
@@ -20369,9 +20313,8 @@ msgid "ZIP Creation"
msgstr "Projekti"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Could not open file to read from path \"%s\"."
-msgstr "Ei voitu viedä projektitiedostoja gradle-projektiksi.\n"
+msgstr "Ei voitu avata luettavaksi tiedostoa polulta \"%s\"."
#: platform/osx/export/export.cpp
msgid "Invalid bundle identifier:"
@@ -20839,9 +20782,8 @@ msgid "Signtool failed to sign executable: %s."
msgstr "Virheellinen käynnistystiedosto."
#: platform/windows/export/export.cpp
-#, fuzzy
msgid "Failed to remove temporary file \"%s\"."
-msgstr "Väliaikaista tiedosta ei voida poistaa:"
+msgstr "Väliaikaista tiedosta ei voida poistaa: \"%s\"."
#: platform/windows/export/export.cpp
msgid ""
@@ -21944,9 +21886,8 @@ msgstr "Matkaa"
#: scene/2d/node_2d.cpp scene/2d/polygon_2d.cpp scene/3d/spatial.cpp
#: scene/main/canvas_layer.cpp
-#, fuzzy
msgid "Rotation Degrees"
-msgstr "Kierto %s astetta."
+msgstr "Kierto asteina"
#: scene/2d/node_2d.cpp scene/3d/spatial.cpp
#, fuzzy
@@ -24204,6 +24145,15 @@ msgstr "Virhe"
msgid "AABB"
msgstr ""
+#: scene/3d/visual_instance.cpp
+#, fuzzy
+msgid "Sorting"
+msgstr "Lajittele"
+
+#: scene/3d/visual_instance.cpp
+msgid "Use AABB Center"
+msgstr ""
+
#: scene/3d/visual_instance.cpp scene/resources/navigation_mesh.cpp
#, fuzzy
msgid "Geometry"
@@ -25137,9 +25087,8 @@ msgid "Max Value"
msgstr "Arvo"
#: scene/gui/range.cpp
-#, fuzzy
msgid "Page"
-msgstr "Sivu: "
+msgstr "Sivu"
#: scene/gui/range.cpp
#, fuzzy
@@ -25575,9 +25524,8 @@ msgid "Max Redirects"
msgstr ""
#: scene/main/http_request.cpp
-#, fuzzy
msgid "Timeout"
-msgstr "Aikakatkaisu."
+msgstr "Aikakatkaisu"
#: scene/main/node.cpp
msgid ""
@@ -27045,9 +26993,8 @@ msgid "Distance"
msgstr "Poimintaetäisyys:"
#: scene/resources/environment.cpp
-#, fuzzy
msgid "Transition"
-msgstr "Siirtymä: "
+msgstr "Siirtymä"
#: scene/resources/environment.cpp
msgid "DOF Near Blur"
@@ -28401,9 +28348,8 @@ msgid "Physics Engine"
msgstr "Fysiikkaruutujen %"
#: servers/physics_server.cpp
-#, fuzzy
msgid "Center Of Mass"
-msgstr "Keskitä vasemmalle"
+msgstr "Massakeskipiste"
#: servers/physics_server.cpp
msgid "Principal Inertia Axes"
@@ -28459,29 +28405,24 @@ msgid "VRAM Compression"
msgstr "Lauseke"
#: servers/visual_server.cpp
-#, fuzzy
msgid "Import BPTC"
-msgstr "Tuo"
+msgstr "Tuo BPTC"
#: servers/visual_server.cpp
-#, fuzzy
msgid "Import S3TC"
-msgstr "Tuo"
+msgstr "Tuo S3TC"
#: servers/visual_server.cpp
-#, fuzzy
msgid "Import ETC"
-msgstr "Tuo"
+msgstr "Tuo ETC"
#: servers/visual_server.cpp
-#, fuzzy
msgid "Import ETC2"
-msgstr "Tuo"
+msgstr "Tuo ETC2"
#: servers/visual_server.cpp
-#, fuzzy
msgid "Import PVRTC"
-msgstr "Tuo teema"
+msgstr "Tuo PVRTC"
#: servers/visual_server.cpp
msgid "Lossless Compression"
@@ -28612,9 +28553,8 @@ msgid "Ninepatch Mode"
msgstr "Interpolaatiotila"
#: servers/visual_server.cpp
-#, fuzzy
msgid "OpenGL"
-msgstr "Avaa"
+msgstr "OpenGL"
#: servers/visual_server.cpp
msgid "Batching Send Null"
diff --git a/editor/translations/fil.po b/editor/translations/fil.po
index e6d675f5ca..71673d8255 100644
--- a/editor/translations/fil.po
+++ b/editor/translations/fil.po
@@ -12,7 +12,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"Report-Msgid-Bugs-To: https://github.com/godotengine/godot\n"
-"PO-Revision-Date: 2022-08-30 03:11+0000\n"
+"PO-Revision-Date: 2022-12-03 04:48+0000\n"
"Last-Translator: Marco Santos <enum.scima@gmail.com>\n"
"Language-Team: Filipino <https://hosted.weblate.org/projects/godot-engine/"
"godot/fil/>\n"
@@ -21,7 +21,7 @@ msgstr ""
"Content-Transfer-Encoding: 8-bit\n"
"Plural-Forms: nplurals=2; plural=n != 1 && n != 2 && n != 3 && (n % 10 == 4 "
"|| n % 10 == 6 || n % 10 == 9);\n"
-"X-Generator: Weblate 4.14.1-dev\n"
+"X-Generator: Weblate 4.15-dev\n"
#: core/bind/core_bind.cpp main/main.cpp
msgid "Tablet Driver"
@@ -300,7 +300,7 @@ msgstr "Max na Nakabinbing Koneksyon"
#: modules/visual_script/visual_script_builtin_funcs.cpp
msgid "Invalid type argument to convert(), use TYPE_* constants."
msgstr ""
-"Invalid na argumento ng type sa convert(), gumamit ng mga TYPE_* constant."
+"Invalid na type argument sa convert(), gamitin ang mga TYPE_* constant."
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
msgid "Expected a string of length 1 (a character)."
@@ -310,7 +310,7 @@ msgstr "Inaasahan ang isang string na may habang 1 (karakter)."
#: 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 "Kulang sa bytes para i-decode ang bytes, o invalid na format."
+msgstr "Kulang sa espasyo para ma-decode ang bytes, o invalid na format."
#: core/math/expression.cpp
msgid "Invalid input %d (not passed) in expression"
@@ -318,23 +318,23 @@ msgstr "Invalid na input na %d (di pinasa) sa expression"
#: core/math/expression.cpp
msgid "self can't be used because instance is null (not passed)"
-msgstr "Di magagamit ang self dahil null ang instance (di pinasa)"
+msgstr "Hindi magagamit ang self dahil null ang instance (di pinasa)"
#: core/math/expression.cpp
msgid "Invalid operands to operator %s, %s and %s."
-msgstr "Mga invalid na operand sa operator %s, %s, at %s."
+msgstr "Mga invalid na operand aa operator %s, %s, at %s."
#: core/math/expression.cpp
msgid "Invalid index of type %s for base type %s"
-msgstr "Invalid na index ng type na %s para sa base type na %s"
+msgstr "Invalid na index ng type %s para sa base type %s"
#: core/math/expression.cpp
msgid "Invalid named index '%s' for base type %s"
-msgstr "Invalid na napangalanang index na '%s' para sa base type na %s"
+msgstr "Invalid na may pangalang index '%s' para sa base type %s"
#: core/math/expression.cpp
msgid "Invalid arguments to construct '%s'"
-msgstr "Mga invalid na argumento para i-construct ang '%s'"
+msgstr "Mga invalid na argument para i-construct ang '%s'"
#: core/math/expression.cpp
msgid "On call to '%s':"
@@ -1033,7 +1033,7 @@ msgstr "Max na Laki ng Buffer ng Blend Shape (KB)"
#. TRANSLATORS: Adjective, refers to the mode for Bezier handles (Free, Balanced, Mirror).
#: editor/animation_bezier_editor.cpp
msgid "Free"
-msgstr "Libre"
+msgstr "Malaya"
#: editor/animation_bezier_editor.cpp
msgid "Balanced"
@@ -1053,51 +1053,51 @@ msgstr "Value:"
#: editor/animation_bezier_editor.cpp
msgid "Insert Key Here"
-msgstr "Magpasok ng Key Rito"
+msgstr "Mag-key rito"
#: editor/animation_bezier_editor.cpp
msgid "Duplicate Selected Key(s)"
-msgstr "Doblehin ang (mga) Napiling Key"
+msgstr "Doblehin ang (mga) napiling key"
#: editor/animation_bezier_editor.cpp
msgid "Delete Selected Key(s)"
-msgstr "Burahin ang (mga) Napiling Key"
+msgstr "Burahin ang (mga) napiling key"
#: editor/animation_bezier_editor.cpp
msgid "Add Bezier Point"
-msgstr "Magdagdag ng Bezier Point"
+msgstr "Magdagdag ng bezier point"
#: editor/animation_bezier_editor.cpp
msgid "Move Bezier Points"
-msgstr "Maglipat ng (mga) Bezier Point"
+msgstr "Maglipat ng (mga) bezier point"
#: editor/animation_bezier_editor.cpp editor/animation_track_editor.cpp
msgid "Anim Duplicate Keys"
-msgstr "Anim Duplicate Keys"
+msgstr "I-anim ang mga key sa pagdoble"
#: editor/animation_bezier_editor.cpp editor/animation_track_editor.cpp
msgid "Anim Delete Keys"
-msgstr "Anim Delete Keys"
+msgstr "I-anim ang mga key sa pagbura"
#: editor/animation_track_editor.cpp
msgid "Anim Change Keyframe Time"
-msgstr "Anim Change Keyframe Time"
+msgstr "I-anim ang oras ng pagpalit keyframe"
#: editor/animation_track_editor.cpp
msgid "Anim Change Transition"
-msgstr "Anim Change Transition"
+msgstr "I-anim ang pagpalit transition"
#: editor/animation_track_editor.cpp
msgid "Anim Change Transform"
-msgstr "Anim Change Transform"
+msgstr "I-anim ang pagpalit transform"
#: editor/animation_track_editor.cpp
msgid "Anim Change Keyframe Value"
-msgstr "Anim Change Keyframe Value"
+msgstr "I-anim ang value ng pagpalit keyframe"
#: editor/animation_track_editor.cpp
msgid "Anim Change Call"
-msgstr "Anim Change Call"
+msgstr "I-anim ang pagpalit call"
#: editor/animation_track_editor.cpp scene/2d/animated_sprite.cpp
#: scene/2d/sprite.cpp scene/3d/sprite_3d.cpp
@@ -1207,36 +1207,36 @@ msgstr "Anim Multi Change Call"
#: editor/animation_track_editor.cpp
msgid "Change Animation Length"
-msgstr "Baguhin ang Haba ng Animation"
+msgstr "Baguhin ang haba ng animation"
#: editor/animation_track_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Change Animation Loop"
-msgstr "Baguhin ang Animation Loop"
+msgstr "Baguhin ang loop sa animation"
#: editor/animation_track_editor.cpp
msgid "Property Track"
-msgstr "Property Track"
+msgstr "Katangian"
#: editor/animation_track_editor.cpp
msgid "3D Transform Track"
-msgstr "3D Transform Track"
+msgstr "3D Transform"
#: editor/animation_track_editor.cpp
msgid "Call Method Track"
-msgstr "Call Method Track"
+msgstr "Call Method"
#: editor/animation_track_editor.cpp
msgid "Bezier Curve Track"
-msgstr "Bezier Curve Track"
+msgstr "Kurbang Bezier"
#: editor/animation_track_editor.cpp
msgid "Audio Playback Track"
-msgstr "Audio Playback Track"
+msgstr "Pag-play ng tunog"
#: editor/animation_track_editor.cpp
msgid "Animation Playback Track"
-msgstr "Animation Playback Track"
+msgstr "Pag-play sa animation"
#: editor/animation_track_editor.cpp
msgid "Animation length (frames)"
@@ -1248,28 +1248,28 @@ msgstr "Haba ng animation (segundo)"
#: editor/animation_track_editor.cpp
msgid "Add Track"
-msgstr "Magdagdag ng Track"
+msgstr "Magdagdag ng track"
#: editor/animation_track_editor.cpp
msgid "Animation Looping"
-msgstr "Pag-loop sa Animation"
+msgstr "I-loop ang animation"
#: editor/animation_track_editor.cpp
#: modules/visual_script/visual_script_editor.cpp
msgid "Functions:"
-msgstr "Mga Function:"
+msgstr "Mga function:"
#: editor/animation_track_editor.cpp
msgid "Audio Clips:"
-msgstr "Mga Audio Clip:"
+msgstr "Mga tunog:"
#: editor/animation_track_editor.cpp
msgid "Anim Clips:"
-msgstr "Mga Anim Clip:"
+msgstr "Mga anim clip:"
#: editor/animation_track_editor.cpp
msgid "Change Track Path"
-msgstr "Baguhin ang Track Path"
+msgstr "Baguhin ang track path"
#: editor/animation_track_editor.cpp
msgid "Toggle this track on/off."
@@ -1277,15 +1277,15 @@ msgstr "Buksan/isara ang track na ito."
#: editor/animation_track_editor.cpp
msgid "Update Mode (How this property is set)"
-msgstr "Update Mode (kung paano itinatakda ang property na ito)"
+msgstr "Update Mode (Kung paano tinakda ang katangian na ito)"
#: editor/animation_track_editor.cpp scene/resources/gradient.cpp
msgid "Interpolation Mode"
-msgstr "Interpolation Mode"
+msgstr "Interpolation"
#: editor/animation_track_editor.cpp
msgid "Loop Wrap Mode (Interpolate end with beginning on loop)"
-msgstr "Loop Wrap Mode (ini-interpolate ang dulo sa simula ng loop)"
+msgstr "Paikot-ikot (i-interpolate ang dulo sa simula ng loop)"
#: editor/animation_track_editor.cpp
msgid "Remove this track."
@@ -1358,7 +1358,7 @@ msgstr "Mga Anim Clip:"
#: editor/animation_track_editor.cpp
msgid "Toggle Track Enabled"
-msgstr "Nakabukas ang Toggle Track"
+msgstr "Nakabukas ang toggle track"
#: editor/animation_track_editor.cpp
msgid "Continuous"
@@ -1378,7 +1378,7 @@ msgstr "I-capture"
#: editor/animation_track_editor.cpp
msgid "Nearest"
-msgstr "Pinakamalapit"
+msgstr "Malapit"
#: editor/animation_track_editor.cpp editor/plugins/curve_editor_plugin.cpp
#: editor/property_editor.cpp scene/2d/physics_body_2d.cpp
@@ -1392,20 +1392,20 @@ msgstr "Cubic"
#: editor/animation_track_editor.cpp
msgid "Clamp Loop Interp"
-msgstr "Clamp Loop Interp"
+msgstr "I-clamp ang loop interp"
#: editor/animation_track_editor.cpp
msgid "Wrap Loop Interp"
-msgstr "Wrap Loop Interp"
+msgstr "I-wrap ang loop interp"
#: editor/animation_track_editor.cpp
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Insert Key"
-msgstr "Magpasok ng Key"
+msgstr "Magsingit ng key"
#: editor/animation_track_editor.cpp
msgid "Duplicate Key(s)"
-msgstr "Doblehin ang (mga) Key"
+msgstr "Doblehin ang (mga) key"
#: editor/animation_track_editor.cpp
msgid "Add RESET Value(s)"
@@ -1413,23 +1413,23 @@ msgstr "Magdagdag ng (mga) RESET value"
#: editor/animation_track_editor.cpp
msgid "Delete Key(s)"
-msgstr "Burahin ang (mga) Key"
+msgstr "Burahin ang (mga) key"
#: editor/animation_track_editor.cpp
msgid "Change Animation Update Mode"
-msgstr "Baguhin ang Animation Update Mode"
+msgstr "Baguhin ang pag-update sa animation"
#: editor/animation_track_editor.cpp
msgid "Change Animation Interpolation Mode"
-msgstr "Baguhin ang Animation Interpolation Mode"
+msgstr "Baguhin ang interpolation ng animation"
#: editor/animation_track_editor.cpp
msgid "Change Animation Loop Mode"
-msgstr "Baguhin ang Animation Loop Mode"
+msgstr "Baguhin ang pag-loop sa animation"
#: editor/animation_track_editor.cpp
msgid "Remove Anim Track"
-msgstr "Tanggalin ang Anim Track"
+msgstr "Tanggalin ang anim track"
#: editor/animation_track_editor.cpp editor/editor_settings.cpp
#: editor/plugins/path_editor_plugin.cpp
@@ -1448,7 +1448,7 @@ msgstr ""
#. TRANSLATORS: %s will be replaced by a phrase describing the target of track.
#: editor/animation_track_editor.cpp
msgid "Create NEW track for %s and insert key?"
-msgstr ""
+msgstr "Gumawa ng BAGONG track para sa %s at magsingit ng key?"
#: editor/animation_track_editor.cpp
msgid "Create %d NEW tracks and insert keys?"
@@ -12480,9 +12480,10 @@ msgstr "Pag-snap"
#: scene/2d/path_2d.cpp scene/2d/polygon_2d.cpp scene/2d/sprite.cpp
#: scene/3d/cpu_particles.cpp scene/3d/label_3d.cpp scene/3d/path.cpp
#: scene/3d/physics_body.cpp scene/3d/soft_body.cpp scene/3d/sprite_3d.cpp
-#: 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
+#: scene/3d/visual_instance.cpp 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
msgid "Offset"
msgstr ""
@@ -13833,12 +13834,11 @@ msgstr ""
#: editor/project_manager.cpp
msgid ""
-"Couldn't load project.godot in project path (error %d). It may be missing or "
-"corrupted."
+"Couldn't load project at '%s' (error %d). It may be missing or corrupted."
msgstr ""
#: editor/project_manager.cpp
-msgid "Couldn't edit project.godot in project path."
+msgid "Couldn't save project at '%s' (error %d)."
msgstr ""
#: editor/project_manager.cpp
@@ -22508,6 +22508,15 @@ msgstr "Salamin"
msgid "AABB"
msgstr ""
+#: scene/3d/visual_instance.cpp
+#, fuzzy
+msgid "Sorting"
+msgstr "Pagsasaayos"
+
+#: scene/3d/visual_instance.cpp
+msgid "Use AABB Center"
+msgstr ""
+
#: scene/3d/visual_instance.cpp scene/resources/navigation_mesh.cpp
msgid "Geometry"
msgstr ""
diff --git a/editor/translations/fr.po b/editor/translations/fr.po
index e19c856222..17063caae8 100644
--- a/editor/translations/fr.po
+++ b/editor/translations/fr.po
@@ -105,13 +105,14 @@
# SCHUTZ Lucas <lucas.schutz0954@gmail.com>, 2022.
# EGuillemot <Elouen.Guillemot@gmail.com>, 2022.
# Entiz <maxime.salido@gmail.com>, 2022.
+# Callim Ethee <callimethee@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-09-27 21:37+0000\n"
-"Last-Translator: Entiz <maxime.salido@gmail.com>\n"
+"PO-Revision-Date: 2022-10-10 18:06+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"
@@ -3904,7 +3905,7 @@ msgstr ""
#: editor/editor_node.cpp
msgid "Could not save one or more scenes!"
-msgstr "Impossible de sauver la (les) scènes(s) !"
+msgstr "Impossible d'enregistrer la ou les scènes !"
#: editor/editor_node.cpp
msgid "Save All Scenes"
@@ -12942,9 +12943,10 @@ msgstr "Options de magnétisme"
#: scene/2d/path_2d.cpp scene/2d/polygon_2d.cpp scene/2d/sprite.cpp
#: scene/3d/cpu_particles.cpp scene/3d/label_3d.cpp scene/3d/path.cpp
#: scene/3d/physics_body.cpp scene/3d/soft_body.cpp scene/3d/sprite_3d.cpp
-#: 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
+#: scene/3d/visual_instance.cpp 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
msgid "Offset"
msgstr "Décalage"
@@ -14366,16 +14368,14 @@ msgstr "Chemin de projet non valide (avez-vous changé quelque chose ?)."
#: editor/project_manager.cpp
msgid ""
-"Couldn't load project.godot in project path (error %d). It may be missing or "
-"corrupted."
+"Couldn't load project at '%s' (error %d). It may be missing or corrupted."
msgstr ""
-"Impossible de charger le fichier project.godot dans le chemin du projet "
-"(erreur %d). Le fichier est manquant ou corrompu."
+"Impossible de charger le project à \"%s\" (erreur %d). Il peut être manquant "
+"ou corrompu."
#: editor/project_manager.cpp
-msgid "Couldn't edit project.godot in project path."
-msgstr ""
-"Impossible de modifier le fichier project.godot dans le chemin du projet."
+msgid "Couldn't save project at '%s' (error %d)."
+msgstr "Impossible d'enregistrer le projet à \"%s\" (erreur %d)."
#: editor/project_manager.cpp
msgid "Couldn't create project.godot in project path."
@@ -19384,7 +19384,7 @@ msgstr "Shell HTML personnalisé"
#: platform/javascript/export/export.cpp
msgid "Head Include"
-msgstr ""
+msgstr "Inclure la tête de fichier"
#: platform/javascript/export/export.cpp
msgid "Canvas Resize Policy"
@@ -19392,7 +19392,7 @@ msgstr "Politique de redimensionnement du canevas"
#: platform/javascript/export/export.cpp
msgid "Focus Canvas On Start"
-msgstr ""
+msgstr "Sélectionner le canevas au démarrage"
#: platform/javascript/export/export.cpp
msgid "Experimental Virtual Keyboard"
@@ -19499,9 +19499,8 @@ msgid "Failed to get CodeResources hash."
msgstr "La récupération du hachage de CodeResources a échouée."
#: platform/osx/export/codesign.cpp platform/osx/export/export.cpp
-#, fuzzy
msgid "Invalid entitlements file."
-msgstr "Extension invalide."
+msgstr "Fichier de permissions invalide."
#: platform/osx/export/codesign.cpp
msgid "Invalid executable file."
@@ -19582,16 +19581,15 @@ msgstr "Horodatage"
#: platform/osx/export/export.cpp
msgid "Hardened Runtime"
-msgstr ""
+msgstr "Environnement d'exécution Renforcé"
#: platform/osx/export/export.cpp
msgid "Replace Existing Signature"
msgstr "Remplacer la signature existante"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Entitlements"
-msgstr "Gadgets"
+msgstr "Permissions"
#: platform/osx/export/export.cpp
msgid "Custom File"
@@ -19607,7 +19605,7 @@ msgstr "Autoriser la mémoire exécutable non signée"
#: platform/osx/export/export.cpp
msgid "Allow Dyld Environment Variables"
-msgstr ""
+msgstr "Autoriser les variables d'environnement Dyld"
#: platform/osx/export/export.cpp
msgid "Disable Library Validation"
@@ -19662,28 +19660,24 @@ msgid "Files Downloads"
msgstr "Téléchargement de fichiers"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Files Pictures"
-msgstr "Fonctionnalités"
+msgstr "Fichiers Images"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Files Music"
-msgstr "Fichier"
+msgstr "Fichiers Musicaux"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Files Movies"
-msgstr "Filtrer les tuiles"
+msgstr "Fichiers Vidéo"
#: platform/osx/export/export.cpp platform/windows/export/export.cpp
msgid "Custom Options"
msgstr "Options personnalisées"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Notarization"
-msgstr "Localisation"
+msgstr "Notarisation"
#: platform/osx/export/export.cpp
msgid "Apple ID Name"
@@ -19711,7 +19705,7 @@ msgstr "Notarisation échouée."
#: platform/osx/export/export.cpp
msgid "Notarization request UUID: \"%s\""
-msgstr ""
+msgstr "UUID de la requête de notarisation : \"%s\""
#: platform/osx/export/export.cpp
msgid ""
@@ -19747,10 +19741,12 @@ msgstr ""
msgid ""
"Hardened Runtime is not compatible with ad-hoc signature, and was disabled!"
msgstr ""
+"L'Environnement d'exécution Renforcé n'est pas compatible avec la signature "
+"ad-hoc et a été désactivé !"
#: platform/osx/export/export.cpp
msgid "Built-in CodeSign failed with error \"%s\"."
-msgstr ""
+msgstr "CodeSign intégré a échoué avec l'erreur : \"%s\"."
#: platform/osx/export/export.cpp
msgid "Built-in CodeSign require regex module."
@@ -19908,33 +19904,32 @@ msgid "Notarization: Hardened runtime is required for notarization."
msgstr "Notarisation : exécution renforcée nécessaire pour la notarisation."
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Notarization: Timestamp runtime is required for notarization."
-msgstr "Certification : exécution renforcée requise."
+msgstr "Notarisation : Horodatage nécessaire à la notarisation."
#: platform/osx/export/export.cpp
msgid "Notarization: Apple ID name not specified."
-msgstr "Certification : Identifiant Apple ID non spécifié."
+msgstr "Notarisation : Identifiant Apple ID non spécifié."
#: platform/osx/export/export.cpp
msgid "Notarization: Apple ID password not specified."
-msgstr "Certification : Mot de passe Apple ID non spécifié."
+msgstr "Notarisation : Mot de passe Apple ID non spécifié."
#: platform/osx/export/export.cpp
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."
+"Attention : La notarisation est désactivée. Le projet exporté sera bloqué "
+"par Gatekeeper s'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 "
+"La signature du code est désactivée. Le projet exporté ne fonctionnera pas "
+"sur les Macs avec Gatekeeper activé ni sur les Macs fonctionnant sous Apple "
"Silicon."
#: platform/osx/export/export.cpp
@@ -19942,12 +19937,14 @@ msgid ""
"Hardened Runtime is not compatible with ad-hoc signature, and will be "
"disabled!"
msgstr ""
+"L'Environnement d'éxécution renforcé n'est pas compatible avec la signature "
+"ad-hoc et va être désactivé !"
#: platform/osx/export/export.cpp
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é "
+"L'horodatage n'est pas compatible avec la signature ad-hoc et va être "
"désactivé !"
#: platform/osx/export/export.cpp
@@ -19955,7 +19952,7 @@ 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 "
+"Attention : La notarisation 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."
@@ -19964,7 +19961,7 @@ msgid ""
"Privacy: Microphone access is enabled, but usage description is not "
"specified."
msgstr ""
-"Confidentialité : L'accès au microphone est actif, mais son usage n'a pas "
+"Confidentialité : L'accès au microphone est activé, mais son usage n'a pas "
"été spécifié."
#: platform/osx/export/export.cpp
@@ -20371,11 +20368,11 @@ msgstr "Rcedit"
#: platform/windows/export/export.cpp
msgid "Osslsigncode"
-msgstr "Osslsigncode"
+msgstr "Code Signature OpenSSL"
#: platform/windows/export/export.cpp
msgid "Wine"
-msgstr "Wine"
+msgstr "Vin"
#: platform/x11/export/export.cpp
msgid "32-bit executables cannot have embedded data >= 4 GiB."
@@ -20454,13 +20451,12 @@ msgid "Gravity"
msgstr "Gravité"
#: scene/2d/area_2d.cpp scene/3d/area.cpp
-#, fuzzy
msgid "Linear Damp"
-msgstr "Linéaire"
+msgstr "Amorti Linéaire"
#: scene/2d/area_2d.cpp scene/3d/area.cpp
msgid "Angular Damp"
-msgstr ""
+msgstr "Amorti Angulaire"
#: scene/2d/area_2d.cpp scene/3d/area.cpp
msgid "Audio Bus"
@@ -20539,9 +20535,8 @@ msgstr "Vue personnalisée"
#: 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 "Mode déplacement"
+msgstr "Mode de traitement"
#: scene/2d/camera_2d.cpp
msgid "Limit"
@@ -20564,9 +20559,8 @@ msgid "Bottom"
msgstr "Bas"
#: scene/2d/camera_2d.cpp
-#, fuzzy
msgid "Smoothed"
-msgstr "Progression douce"
+msgstr "Adouci"
#: scene/2d/camera_2d.cpp
msgid "Draw Margin"
@@ -20583,9 +20577,8 @@ msgid "Drag Margin V Enabled"
msgstr "Définir la marge"
#: scene/2d/camera_2d.cpp
-#, fuzzy
msgid "Smoothing"
-msgstr "Progression douce"
+msgstr "Adoucissement"
#: scene/2d/camera_2d.cpp
msgid "H"
@@ -20648,9 +20641,8 @@ msgid "Visible"
msgstr "Visible"
#: scene/2d/canvas_item.cpp
-#, fuzzy
msgid "Self Modulate"
-msgstr "Peupler"
+msgstr "Auto-modulation"
#: scene/2d/canvas_item.cpp
msgid "Show Behind Parent"
@@ -20822,12 +20814,12 @@ msgstr "FPS fixes"
#: scene/2d/cpu_particles_2d.cpp scene/2d/particles_2d.cpp
#: scene/3d/cpu_particles.cpp scene/3d/particles.cpp
msgid "Fract Delta"
-msgstr ""
+msgstr "Delta Fraction"
#: scene/2d/cpu_particles_2d.cpp scene/2d/particles_2d.cpp
#: scene/3d/cpu_particles.cpp scene/3d/particles.cpp
msgid "Drawing"
-msgstr ""
+msgstr "Dessin"
#: scene/2d/cpu_particles_2d.cpp scene/2d/particles_2d.cpp
#: scene/3d/cpu_particles.cpp scene/3d/particles.cpp
@@ -20850,9 +20842,8 @@ msgid "Sphere Radius"
msgstr "Rayon de la Sphère"
#: scene/2d/cpu_particles_2d.cpp
-#, fuzzy
msgid "Rect Extents"
-msgstr "Gadgets"
+msgstr "Étendue du rectangle"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
msgid "Normals"
@@ -20964,18 +20955,16 @@ msgid "Angle Curve"
msgstr "Courbe d'angle"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
-#, fuzzy
msgid "Scale Amount"
msgstr "Valeur d'échelle"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
msgid "Scale Amount Random"
-msgstr ""
+msgstr "Valeur d'échelle aléatoire"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
-#, fuzzy
msgid "Scale Amount Curve"
-msgstr "Agrandir/Rétrécir à partir du curseur"
+msgstr "Courbe de valeur d'échelle"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
@@ -21080,7 +21069,7 @@ msgstr "Décalage initial"
#: scene/2d/joints_2d.cpp scene/3d/vehicle_body.cpp
msgid "Rest Length"
-msgstr ""
+msgstr "Longueur au repos"
#: scene/2d/joints_2d.cpp scene/3d/physics_joint.cpp scene/3d/vehicle_body.cpp
msgid "Stiffness"
@@ -21126,7 +21115,7 @@ msgstr "Calque max"
#: scene/2d/light_2d.cpp
msgid "Item Cull Mask"
-msgstr ""
+msgstr "Masque d'élagage d'élément"
#: scene/2d/light_2d.cpp scene/3d/light.cpp scene/resources/style_box.cpp
msgid "Shadow"
@@ -21141,18 +21130,16 @@ msgid "Gradient Length"
msgstr "Longueur du dégradé"
#: scene/2d/light_2d.cpp
-#, fuzzy
msgid "Filter Smooth"
-msgstr "Filtrer les méthodes"
+msgstr "Filtre de lissage"
#: scene/2d/light_occluder_2d.cpp
msgid "Closed"
msgstr "Fermé"
#: scene/2d/light_occluder_2d.cpp scene/resources/material.cpp
-#, fuzzy
msgid "Cull Mode"
-msgstr "Mode Règle"
+msgstr "Mode Élagage"
#: scene/2d/light_occluder_2d.cpp
msgid ""
@@ -21196,13 +21183,12 @@ msgid "Joint Mode"
msgstr "Mode de jointure"
#: scene/2d/line_2d.cpp
-#, fuzzy
msgid "Begin Cap Mode"
-msgstr "Mode Région"
+msgstr "Lancer le mode capuchon"
#: scene/2d/line_2d.cpp
msgid "End Cap Mode"
-msgstr "Mode du capuchon de fin"
+msgstr "Terminer le mode capuchon"
#: scene/2d/line_2d.cpp scene/2d/polygon_2d.cpp scene/resources/style_box.cpp
msgid "Border"
@@ -21210,7 +21196,7 @@ msgstr "Bordure"
#: scene/2d/line_2d.cpp
msgid "Sharp Limit"
-msgstr ""
+msgstr "Limite Nette"
#: scene/2d/line_2d.cpp
msgid "Round Precision"
@@ -21222,9 +21208,8 @@ msgid "Antialiased"
msgstr "Anticrénelé"
#: scene/2d/multimesh_instance_2d.cpp scene/3d/multimesh_instance.cpp
-#, fuzzy
msgid "Multimesh"
-msgstr "Multiplier %s"
+msgstr "Multimaillage"
#: scene/2d/navigation_2d.cpp scene/3d/baked_lightmap.cpp
#: scene/3d/navigation.cpp scene/animation/root_motion_view.cpp
@@ -21247,9 +21232,8 @@ msgstr ""
"Navigation2DServer.map_get_path() » à la place."
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
msgid "Pathfinding"
-msgstr "Pathfinding"
+msgstr "Recherche de chemin"
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
msgid "Path Desired Distance"
@@ -21280,9 +21264,8 @@ msgid "Max Neighbors"
msgstr "Maximum de voisins"
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
msgid "Time Horizon"
-msgstr "Retourner horizontalement"
+msgstr "Horizon temporel"
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
msgid "Max Speed"
@@ -21587,7 +21570,7 @@ msgstr "Plateforme mobile"
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
msgid "Apply Velocity On Leave"
-msgstr ""
+msgstr "Appliquer la vélocité à la sortie"
#: scene/2d/physics_body_2d.cpp scene/2d/touch_screen_button.cpp
#: scene/3d/physics_body.cpp scene/gui/texture_button.cpp
@@ -21726,9 +21709,8 @@ msgid "Frame Coords"
msgstr "Coordonnées de trame"
#: scene/2d/sprite.cpp scene/resources/texture.cpp
-#, fuzzy
msgid "Filter Clip"
-msgstr "Filtrer les scripts"
+msgstr "Filtrer les clips"
#: scene/2d/tile_map.cpp
msgid ""
@@ -21749,9 +21731,8 @@ msgid "Quadrant Size"
msgstr "Taille de quadrant"
#: scene/2d/tile_map.cpp
-#, fuzzy
msgid "Custom Transform"
-msgstr "Transformation"
+msgstr "Transformation Personalisée"
#: scene/2d/tile_map.cpp
msgid "Half Offset"
@@ -21779,7 +21760,7 @@ msgstr "Textures Centrées"
#: scene/2d/tile_map.cpp
msgid "Cell Clip UV"
-msgstr ""
+msgstr "Cellule Clip UV"
#: scene/2d/tile_map.cpp
msgid "Use Parent"
@@ -21799,7 +21780,7 @@ msgstr "Forme Visible"
#: scene/2d/touch_screen_button.cpp
msgid "Passby Press"
-msgstr ""
+msgstr "Activation en passant"
#: scene/2d/touch_screen_button.cpp
msgid "Visibility Mode"
@@ -21839,7 +21820,7 @@ msgstr "Parent du Processus Physique"
#: scene/3d/area.cpp
msgid "Reverb Bus"
-msgstr ""
+msgstr "Bus de Réverb"
#: scene/3d/area.cpp
msgid "Uniformity"
@@ -21870,9 +21851,8 @@ msgstr ""
"aucun contrôleur."
#: scene/3d/arvr_nodes.cpp
-#, fuzzy
msgid "Anchor ID"
-msgstr "Uniquement les ancres"
+msgstr "ID de l'ancre"
#: scene/3d/arvr_nodes.cpp
msgid "ARVRAnchor must have an ARVROrigin node as its parent."
@@ -21912,7 +21892,7 @@ msgstr "Max (dB)"
#: scene/3d/audio_stream_player_3d.cpp
msgid "Out Of Range Mode"
-msgstr ""
+msgstr "Mode Hors-de-plage"
#: scene/3d/audio_stream_player_3d.cpp
msgid "Emission Angle"
@@ -21934,7 +21914,7 @@ msgstr "Filtre d’atténuation"
#: servers/audio/effects/audio_effect_chorus.cpp
#: servers/audio/effects/audio_effect_filter.cpp
msgid "Cutoff Hz"
-msgstr ""
+msgstr "Hz de coupure"
#: scene/3d/audio_stream_player_3d.cpp
#: servers/audio/effects/audio_effect_filter.cpp
@@ -21946,9 +21926,8 @@ msgid "Doppler"
msgstr "Doppler"
#: scene/3d/audio_stream_player_3d.cpp
-#, fuzzy
msgid "Tracking"
-msgstr "Empaquetage"
+msgstr "Suivi"
#: scene/3d/baked_lightmap.cpp scene/3d/gi_probe.cpp
#: scene/3d/reflection_probe.cpp
@@ -21982,9 +21961,8 @@ msgstr "Terminé"
#: 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 "Gadgets"
+msgstr "Étendues"
#: scene/3d/baked_lightmap.cpp
msgid "Tweaks"
@@ -22043,9 +22021,8 @@ msgid "Custom Energy"
msgstr "Énergie personnalisée"
#: scene/3d/baked_lightmap.cpp
-#, fuzzy
msgid "Min Light"
-msgstr "Indenter vers la droite"
+msgstr "Lumière Min"
#: scene/3d/baked_lightmap.cpp scene/3d/gi_probe.cpp
msgid "Propagation"
@@ -22069,12 +22046,11 @@ msgstr "Garder l'aspect"
#: scene/3d/camera.cpp scene/3d/light.cpp scene/3d/reflection_probe.cpp
msgid "Cull Mask"
-msgstr ""
+msgstr "Masque d'élagage"
#: scene/3d/camera.cpp
-#, fuzzy
msgid "Doppler Tracking"
-msgstr "Piste de propriété"
+msgstr "Effet Doppler de Suivi"
#: scene/3d/camera.cpp
msgid "Projection"
@@ -22105,18 +22081,16 @@ msgid "Margin"
msgstr "Marge"
#: scene/3d/camera.cpp
-#, fuzzy
msgid "Clip To"
-msgstr "Agrafe ci-dessus"
+msgstr "Agrafer à"
#: scene/3d/collision_object.cpp scene/3d/soft_body.cpp
msgid "Ray Pickable"
-msgstr ""
+msgstr "Sélectionnable par rayon"
#: scene/3d/collision_object.cpp
-#, fuzzy
msgid "Capture On Drag"
-msgstr "Capturer"
+msgstr "Capturer lors du glissement"
#: scene/3d/collision_object.cpp
msgid ""
@@ -22187,9 +22161,8 @@ msgstr ""
"Particles » activé."
#: scene/3d/cpu_particles.cpp scene/resources/particles_material.cpp
-#, fuzzy
msgid "Box Extents"
-msgstr "Gadgets"
+msgstr "Étendues de la boîte"
#: scene/3d/cpu_particles.cpp scene/resources/particles_material.cpp
msgid "Ring Radius"
@@ -22229,10 +22202,9 @@ msgstr "Mode portail"
#: scene/3d/cull_instance.cpp
msgid "Include In Bound"
-msgstr ""
+msgstr "Inclure dans la frontière"
#: scene/3d/cull_instance.cpp
-#, fuzzy
msgid "Allow Merging"
msgstr "Autoriser la fusion"
@@ -22363,37 +22335,32 @@ msgid "Contact"
msgstr "Contact"
#: scene/3d/light.cpp
-#, fuzzy
msgid "Reverse Cull Face"
-msgstr "Réinitialiser le volume de bus"
+msgstr "Élagage inversé de la face"
#: scene/3d/light.cpp servers/visual_server.cpp
msgid "Directional Shadow"
msgstr "Ombre directionnelle"
#: scene/3d/light.cpp
-#, fuzzy
msgid "Split 1"
-msgstr "Divisé"
+msgstr "Séparation 1"
#: scene/3d/light.cpp
-#, fuzzy
msgid "Split 2"
-msgstr "Divisé"
+msgstr "Séparation 2"
#: scene/3d/light.cpp
-#, fuzzy
msgid "Split 3"
-msgstr "Divisé"
+msgstr "Séparation 3"
#: scene/3d/light.cpp
msgid "Blend Splits"
-msgstr "Mélanger les écarts"
+msgstr "Mélanger les séparations"
#: scene/3d/light.cpp
-#, fuzzy
msgid "Bias Split Scale"
-msgstr "Utiliser le magnétisme d'échelle"
+msgstr "Échelle du biais de séparation"
#: scene/3d/light.cpp
msgid "Depth Range"
@@ -22427,7 +22394,7 @@ msgstr "Atténuation d'angle"
#: scene/3d/mesh_instance.cpp
msgid "Software Skinning"
-msgstr ""
+msgstr "Habillage Logiciel"
#: scene/3d/mesh_instance.cpp
msgid "Transform Normals"
@@ -22596,15 +22563,15 @@ msgstr "Z angulaire"
#: scene/3d/physics_body.cpp
msgid "Motion X"
-msgstr "X mouvement"
+msgstr "Mouvement X"
#: scene/3d/physics_body.cpp
msgid "Motion Y"
-msgstr "Y mouvement"
+msgstr "Mouvement Y"
#: scene/3d/physics_body.cpp
msgid "Motion Z"
-msgstr "Z mouvement"
+msgstr "Mouvement Z"
#: scene/3d/physics_body.cpp
msgid "Joint Constraints"
@@ -22729,7 +22696,7 @@ msgstr "Amortissement angulaire"
#: scene/3d/physics_body.cpp scene/3d/physics_joint.cpp
msgid "ERP"
-msgstr ""
+msgstr "ERP"
#: scene/3d/physics_body.cpp
msgid "Angular Spring Enabled"
@@ -22961,7 +22928,7 @@ msgstr "Nom de groupe"
#: scene/3d/proximity_group.cpp
msgid "Dispatch Mode"
-msgstr ""
+msgstr "Mode Répartition"
#: scene/3d/proximity_group.cpp
msgid "Grid Radius"
@@ -23000,9 +22967,8 @@ msgid "Ambient Energy"
msgstr "Énergie ambiante"
#: scene/3d/reflection_probe.cpp
-#, fuzzy
msgid "Ambient Contrib"
-msgstr "Indenter vers la droite"
+msgstr "Contribution Ambiante"
#: scene/3d/remote_transform.cpp
msgid ""
@@ -23036,20 +23002,19 @@ msgstr ""
#: scene/3d/room.cpp
msgid "Use Default Simplify"
-msgstr ""
+msgstr "Utiliser la simplification par défaut"
#: scene/3d/room.cpp scene/3d/room_manager.cpp
msgid "Room Simplify"
-msgstr ""
+msgstr "Simplifier la pièce"
#: scene/3d/room.cpp
msgid "Bound"
-msgstr ""
+msgstr "Frontière"
#: scene/3d/room_group.cpp
-#, fuzzy
msgid "Roomgroup Priority"
-msgstr "Priorité"
+msgstr "Priorité du groupe de pièces"
#: scene/3d/room_group.cpp
msgid "The RoomManager should not be placed inside a RoomGroup."
@@ -23077,67 +23042,58 @@ msgstr "Il ne doit y avoir qu'un seul RoomManager dans le 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
#: scene/animation/animation_tree_player.cpp
#: servers/audio/effects/audio_effect_delay.cpp
-#, fuzzy
msgid "Active"
-msgstr "Action"
+msgstr "Actif"
#: scene/3d/room_manager.cpp
msgid "Roomlist"
-msgstr ""
+msgstr "Liste des pièces"
#: scene/3d/room_manager.cpp servers/visual_server.cpp
-#, fuzzy
msgid "PVS"
-msgstr "IPS"
+msgstr "PVS"
#: scene/3d/room_manager.cpp
-#, fuzzy
msgid "PVS Mode"
-msgstr "Mode navigation"
+msgstr "Mode PVS"
#: scene/3d/room_manager.cpp
-#, fuzzy
msgid "PVS Filename"
-msgstr "Fichier ZIP"
+msgstr "Nom de ficher PVS"
#: scene/3d/room_manager.cpp servers/visual_server.cpp
msgid "Gameplay"
-msgstr ""
+msgstr "Jouabilité"
#: scene/3d/room_manager.cpp
-#, fuzzy
msgid "Gameplay Monitor"
-msgstr "Moniteur"
+msgstr "Moniteur de jouabilité"
#: scene/3d/room_manager.cpp
-#, fuzzy
msgid "Use Secondary PVS"
-msgstr "Utiliser le magnétisme d'échelle"
+msgstr "Utiliser PVS secondaire"
#: scene/3d/room_manager.cpp
-#, fuzzy
msgid "Merge Meshes"
-msgstr "Maillages"
+msgstr "Unifier les maillages"
#: scene/3d/room_manager.cpp
-#, fuzzy
msgid "Show Margins"
-msgstr "Afficher l'origine"
+msgstr "Afficher les marges"
#: scene/3d/room_manager.cpp
-#, fuzzy
msgid "Debug Sprawl"
-msgstr "Débogage"
+msgstr "Déboger le sprawl"
#: scene/3d/room_manager.cpp
msgid "Overlap Warning Threshold"
-msgstr ""
+msgstr "Seuil d'avertissement de superposition"
#: scene/3d/room_manager.cpp
msgid "Preview Camera"
@@ -23145,17 +23101,15 @@ msgstr "Aperçu de caméra"
#: scene/3d/room_manager.cpp
msgid "Portal Depth Limit"
-msgstr ""
+msgstr "Limite de profondeur du portail"
#: scene/3d/room_manager.cpp
-#, fuzzy
msgid "Default Portal Margin"
-msgstr "Définir la marge"
+msgstr "Marge de portail par défaut"
#: scene/3d/room_manager.cpp
-#, fuzzy
msgid "Roaming Expansion Margin"
-msgstr "Développer tout"
+msgstr "Marge d'expansion roaming"
#: scene/3d/room_manager.cpp
msgid ""
@@ -23210,43 +23164,36 @@ msgstr ""
"manuelles."
#: scene/3d/skeleton.cpp scene/resources/skin.cpp
-#, fuzzy
msgid "Pose"
-msgstr "Copier la pose"
+msgstr "Pose"
#: scene/3d/skeleton.cpp
-#, fuzzy
msgid "Bound Children"
-msgstr "Enfants modifiables"
+msgstr "Enfants liés"
#: scene/3d/soft_body.cpp
-#, fuzzy
msgid "Pinned Points"
-msgstr "Épinglé %s"
+msgstr "Points épinglés"
#: scene/3d/soft_body.cpp
-#, fuzzy
msgid "Attachments"
-msgstr "Gadgets"
+msgstr "Attachements"
#: scene/3d/soft_body.cpp
-#, fuzzy
msgid "Point Index"
-msgstr "Récupérer la position"
+msgstr "Index de point"
#: scene/3d/soft_body.cpp
msgid "Spatial Attachment Path"
-msgstr ""
+msgstr "Chemin de la pièce jointe spatiale"
#: scene/3d/soft_body.cpp
-#, fuzzy
msgid "Physics Enabled"
-msgstr "Image physique %"
+msgstr "Physique active"
#: scene/3d/soft_body.cpp
-#, fuzzy
msgid "Parent Collision Ignore"
-msgstr "Créer le polygone de collision"
+msgstr "Ignorer les collisions avec le parent"
#: scene/3d/soft_body.cpp
msgid "Simulation Precision"
@@ -23258,32 +23205,31 @@ msgstr "Masse totale"
#: scene/3d/soft_body.cpp
msgid "Linear Stiffness"
-msgstr ""
+msgstr "Rigidité Linéaire"
#: scene/3d/soft_body.cpp
msgid "Areaangular Stiffness"
-msgstr ""
+msgstr "Rigidité Aire Angulaire"
#: scene/3d/soft_body.cpp
msgid "Volume Stiffness"
-msgstr ""
+msgstr "Rigidité de volume"
#: scene/3d/soft_body.cpp
-#, fuzzy
msgid "Pressure Coefficient"
msgstr "Coefficient de pression"
#: scene/3d/soft_body.cpp
msgid "Damping Coefficient"
-msgstr ""
+msgstr "Coefficient d'amortissement"
#: scene/3d/soft_body.cpp
msgid "Drag Coefficient"
-msgstr ""
+msgstr "Coefficient de traînée"
#: scene/3d/soft_body.cpp
msgid "Pose Matching Coefficient"
-msgstr ""
+msgstr "Coefficient d'alignement de pose"
#: scene/3d/soft_body.cpp
msgid "This body will be ignored until you set a mesh."
@@ -23300,9 +23246,8 @@ msgstr ""
"Modifiez les tailles dans les formes de collision enfants à la place."
#: scene/3d/spatial.cpp
-#, fuzzy
msgid "Global Translation"
-msgstr "Transformation Globale"
+msgstr "Position globale"
#: scene/3d/spatial.cpp
msgid "Matrix"
@@ -23397,6 +23342,14 @@ msgstr "Force max"
msgid "AABB"
msgstr "AABB"
+#: scene/3d/visual_instance.cpp
+msgid "Sorting"
+msgstr "Arrangement"
+
+#: scene/3d/visual_instance.cpp
+msgid "Use AABB Center"
+msgstr "Utiliser le centre de l'AABB"
+
#: scene/3d/visual_instance.cpp scene/resources/navigation_mesh.cpp
msgid "Geometry"
msgstr "Géométrie"
@@ -23528,9 +23481,8 @@ msgid "Xfade Time"
msgstr "Durée du fondu croisé"
#: scene/animation/animation_node_state_machine.cpp
-#, fuzzy
msgid "Switch Mode"
-msgstr "Mode de Switch"
+msgstr "Changer de mode"
#: scene/animation/animation_node_state_machine.cpp
msgid "Auto Advance"
@@ -23628,14 +23580,12 @@ msgid "This node has been deprecated. Use AnimationTree instead."
msgstr "Ce nœud est désormais déprécié. Utilisez AnimationTree à la place."
#: scene/animation/animation_tree_player.cpp
-#, fuzzy
msgid "Playback"
-msgstr "Jouer"
+msgstr "Lecture"
#: scene/animation/animation_tree_player.cpp
-#, fuzzy
msgid "Master Player"
-msgstr "Coller les paramètres"
+msgstr "Lecteur principal"
#: scene/animation/animation_tree_player.cpp
msgid "Base Path"
@@ -23690,9 +23640,8 @@ msgid "Playback Speed"
msgstr "Vitesse de lecture"
#: scene/audio/audio_stream_player.cpp
-#, fuzzy
msgid "Mix Target"
-msgstr "Cible"
+msgstr "Cible Mixte"
#: scene/gui/aspect_ratio_container.cpp scene/gui/range.cpp
#: servers/audio/effects/audio_effect_compressor.cpp
@@ -23718,11 +23667,11 @@ msgstr "Mode d'action"
#: scene/gui/base_button.cpp
msgid "Enabled Focus Mode"
-msgstr ""
+msgstr "Mode Concentration activé"
#: scene/gui/base_button.cpp
msgid "Keep Pressed Outside"
-msgstr ""
+msgstr "Garder pressé à l'extérieur"
#: scene/gui/base_button.cpp scene/gui/shortcut.cpp
msgid "Shortcut"
@@ -23859,9 +23808,8 @@ msgid "Tooltip"
msgstr "Info-bulle"
#: scene/gui/control.cpp scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Focus"
-msgstr "Focaliser le chemin"
+msgstr "Focus"
#: scene/gui/control.cpp
msgid "Neighbour Left"
@@ -23922,7 +23870,7 @@ msgstr "Boîte de dialogue"
#: scene/gui/dialogs.cpp
msgid "Hide On OK"
-msgstr ""
+msgstr "Cacher quand OK"
#: scene/gui/dialogs.cpp
msgid "Alert!"
@@ -23955,29 +23903,25 @@ msgid "Snap Distance"
msgstr "Distance d'arrondissage"
#: scene/gui/graph_edit.cpp
-#, fuzzy
msgid "Zoom Min"
-msgstr "Zoomer"
+msgstr "Zoom Min"
#: scene/gui/graph_edit.cpp
-#, fuzzy
msgid "Zoom Max"
-msgstr "Zoomer"
+msgstr "Zoom Max"
#: scene/gui/graph_edit.cpp
-#, fuzzy
msgid "Zoom Step"
-msgstr "Dézoomer"
+msgstr "Pas de Zoom"
#: scene/gui/graph_edit.cpp
-#, fuzzy
msgid "Show Zoom Label"
-msgstr "Afficher les os"
+msgstr "Afficher le label de zoom"
#: scene/gui/graph_edit.cpp scene/gui/text_edit.cpp
#: scene/resources/default_theme/default_theme.cpp
msgid "Minimap"
-msgstr ""
+msgstr "Mini-carte"
#: scene/gui/graph_edit.cpp
msgid "Enable grid minimap."
@@ -23990,33 +23934,29 @@ msgstr "Afficher les os"
#: scene/gui/graph_node.cpp scene/gui/option_button.cpp
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Selected"
-msgstr "Sélectionner"
+msgstr "Sélectionné"
#: scene/gui/graph_node.cpp scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Comment"
-msgstr "Enregistrer"
+msgstr "Commentaire"
#: scene/gui/graph_node.cpp
msgid "Overlay"
-msgstr ""
+msgstr "Surcouche"
#: scene/gui/grid_container.cpp scene/gui/item_list.cpp scene/gui/tree.cpp
-#, fuzzy
msgid "Columns"
-msgstr "Volume"
+msgstr "Colonnes"
#: 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 "Temps"
+msgstr "Chronomètres"
#: scene/gui/item_list.cpp scene/gui/popup_menu.cpp scene/gui/tree.cpp
msgid "Incremental Search Max Interval Msec"
-msgstr ""
+msgstr "Intervalle max de recherche incrémentale (ms)"
#: scene/gui/item_list.cpp scene/gui/tree.cpp
#, fuzzy
@@ -24030,7 +23970,7 @@ msgstr "Remplir la sélection"
#: scene/gui/item_list.cpp
msgid "Max Text Lines"
-msgstr ""
+msgstr "Lignes de texte max"
#: scene/gui/item_list.cpp
#, fuzzy
@@ -24039,15 +23979,15 @@ msgstr "En période de test"
#: scene/gui/item_list.cpp
msgid "Max Columns"
-msgstr ""
+msgstr "Colonnes Max"
#: scene/gui/item_list.cpp
msgid "Same Column Width"
-msgstr ""
+msgstr "Même Largeur de Colonne"
#: scene/gui/item_list.cpp
msgid "Fixed Column Width"
-msgstr ""
+msgstr "Largeur de Colonne Fixe"
#: scene/gui/item_list.cpp
msgid "Icon Scale"
@@ -24074,19 +24014,19 @@ msgstr "Rendre visible"
#: scene/gui/label.cpp
msgid "Lines Skipped"
-msgstr ""
+msgstr "Lignes Ignorées"
#: scene/gui/label.cpp
msgid "Max Lines Visible"
-msgstr ""
+msgstr "Lignes Visibles Max"
#: scene/gui/line_edit.cpp scene/resources/navigation_mesh.cpp
msgid "Max Length"
-msgstr ""
+msgstr "Longueur Max"
#: scene/gui/line_edit.cpp
msgid "Secret"
-msgstr ""
+msgstr "Secret"
#: scene/gui/line_edit.cpp
msgid "Secret Character"
@@ -24094,7 +24034,7 @@ msgstr "Caractère secret"
#: scene/gui/line_edit.cpp
msgid "Expand To Text Length"
-msgstr ""
+msgstr "Etendre à la longueur du texte"
#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
#, fuzzy
@@ -24129,7 +24069,7 @@ msgstr "Sélection uniquement"
#: scene/gui/line_edit.cpp scene/gui/rich_text_label.cpp
#: scene/gui/text_edit.cpp
msgid "Deselect On Focus Loss Enabled"
-msgstr ""
+msgstr "Déselection à la perte de focus activée"
#: scene/gui/line_edit.cpp
#, fuzzy
@@ -24143,7 +24083,7 @@ msgstr "Charger en tant qu'instance temporaire"
#: scene/gui/line_edit.cpp
msgid "Alpha"
-msgstr ""
+msgstr "Alpha"
#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Caret"
@@ -24151,7 +24091,7 @@ msgstr "Caret"
#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Blink"
-msgstr ""
+msgstr "Clignoter"
#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Blink Speed"
@@ -24159,7 +24099,7 @@ msgstr "Vitesse de Clignotement"
#: scene/gui/link_button.cpp
msgid "Underline"
-msgstr ""
+msgstr "Souligner"
#: scene/gui/menu_button.cpp
#, fuzzy
@@ -24183,7 +24123,7 @@ msgstr "Définir la marge"
#: scene/gui/nine_patch_rect.cpp scene/resources/style_box.cpp
msgid "Axis Stretch"
-msgstr ""
+msgstr "Etirer les Axes"
#: scene/gui/nine_patch_rect.cpp
msgid ""
@@ -24373,11 +24313,11 @@ msgstr "Filtrer les signaux"
#: scene/gui/scroll_container.cpp
msgid "Default Scroll Deadzone"
-msgstr ""
+msgstr "Zone morte par défaut du défilement"
#: scene/gui/slider.cpp
msgid "Scrollable"
-msgstr ""
+msgstr "Défilant"
#: scene/gui/slider.cpp
#, fuzzy
@@ -24412,7 +24352,7 @@ msgstr "Basculer la visibilité"
#: scene/gui/tab_container.cpp scene/gui/tabs.cpp
msgid "Tab Align"
-msgstr ""
+msgstr "Alignement de l'onglet"
#: scene/gui/tab_container.cpp scene/gui/tabs.cpp
msgid "Current Tab"
@@ -24425,7 +24365,7 @@ msgstr "Rendre visible"
#: scene/gui/tab_container.cpp
msgid "All Tabs In Front"
-msgstr ""
+msgstr "Tous les Onglets au Premier Plan"
#: scene/gui/tab_container.cpp scene/gui/tabs.cpp
msgid "Drag To Rearrange Enabled"
@@ -24433,11 +24373,11 @@ msgstr "Glisser pour Réorganiser Activé"
#: scene/gui/tab_container.cpp
msgid "Use Hidden Tabs For Min Size"
-msgstr ""
+msgstr "Utiliser des onglets cachés pour la taille minimum"
#: scene/gui/tabs.cpp
msgid "Tab Close Display Policy"
-msgstr ""
+msgstr "Stratégie d'affichage pour la fermeture d'onglet"
#: scene/gui/tabs.cpp
msgid "Scrolling Enabled"
@@ -24445,7 +24385,7 @@ msgstr "Défilement activé"
#: scene/gui/text_edit.cpp
msgid "Readonly"
-msgstr ""
+msgstr "Lecture Seule"
#: scene/gui/text_edit.cpp
#, fuzzy
@@ -24495,19 +24435,20 @@ msgstr "Déverrouiller le nœud"
#: scene/gui/text_edit.cpp
msgid "Moving By Right Click"
-msgstr ""
+msgstr "Déplacer avec clic droit"
#: scene/gui/text_edit.cpp
msgid "Text Edit Idle Detect (sec)"
-msgstr ""
+msgstr "Détéction d'inactivité du champ de texte (s)"
#: scene/gui/text_edit.cpp
msgid "Text Edit Undo Stack Max Size"
msgstr ""
+"Nombre d'actions max dans le champ de texte à mémoriser pour l'annulation"
#: scene/gui/texture_button.cpp scene/resources/default_theme/default_theme.cpp
msgid "Hover"
-msgstr ""
+msgstr "Survoler"
#: scene/gui/texture_button.cpp
#, fuzzy
@@ -24527,7 +24468,7 @@ msgstr "Développer tout"
#: scene/gui/texture_progress.cpp
msgid "Under"
-msgstr ""
+msgstr "Sous"
#: scene/gui/texture_progress.cpp
#, fuzzy
@@ -24541,7 +24482,7 @@ msgstr "Propriétés du thème"
#: scene/gui/texture_progress.cpp
msgid "Progress Offset"
-msgstr ""
+msgstr "Décalage de la Progression"
#: scene/gui/texture_progress.cpp
msgid "Fill Mode"
@@ -24549,11 +24490,11 @@ msgstr "Mode de Remplissage"
#: scene/gui/texture_progress.cpp scene/resources/material.cpp
msgid "Tint"
-msgstr ""
+msgstr "Teinte"
#: scene/gui/texture_progress.cpp
msgid "Radial Fill"
-msgstr ""
+msgstr "Remplissage Radial"
#: scene/gui/texture_progress.cpp
#, fuzzy
@@ -24596,7 +24537,7 @@ msgstr "Mode sélection"
#: scene/gui/tree.cpp
msgid "Custom Minimum Height"
-msgstr ""
+msgstr "Taille Minimum Personnalisée"
#: scene/gui/tree.cpp
msgid "(Other)"
@@ -24618,7 +24559,7 @@ msgstr "Masquer la Racine"
#: scene/gui/tree.cpp
msgid "Drop Mode Flags"
-msgstr ""
+msgstr "Options du Mode Abandon"
#: scene/gui/video_player.cpp
#, fuzzy
@@ -24627,7 +24568,7 @@ msgstr "Ajouter une piste"
#: scene/gui/video_player.cpp scene/main/scene_tree.cpp scene/main/timer.cpp
msgid "Paused"
-msgstr ""
+msgstr "En Pause"
#: scene/gui/video_player.cpp
#, fuzzy
@@ -24661,11 +24602,11 @@ msgstr "Téléchargement en cours"
#: scene/main/http_request.cpp
msgid "Body Size Limit"
-msgstr ""
+msgstr "Taille Limite du Corps"
#: scene/main/http_request.cpp
msgid "Max Redirects"
-msgstr ""
+msgstr "Redirections Max"
#: scene/main/http_request.cpp
msgid "Timeout"
@@ -24676,6 +24617,8 @@ msgid ""
"Setting node name '%s' to be unique within scene for '%s', but it's already "
"claimed by '%s'. This node is no longer set unique."
msgstr ""
+"Impossible de déclarer le nom de nœud '%s' comme unique dans la scène pour "
+"'%s', car ce nom est déjà attribué à '%s'. Ce nœud n'est donc plus unique."
#: scene/main/node.cpp
#, fuzzy
@@ -24684,7 +24627,7 @@ msgstr "Séparateur nommé"
#: scene/main/node.cpp
msgid "Name Casing"
-msgstr ""
+msgstr "Convention de Nommage"
#: scene/main/node.cpp
#, fuzzy
@@ -24746,7 +24689,7 @@ msgstr "Mode Navigation"
#: scene/main/scene_tree.cpp
msgid "Use Font Oversampling"
-msgstr ""
+msgstr "Utiliser le Suréchantillonnage de Police"
#: scene/main/scene_tree.cpp
#, fuzzy
@@ -24812,7 +24755,7 @@ msgstr "Utiliser FXAA"
#: scene/main/scene_tree.cpp
msgid "Use Debanding"
-msgstr ""
+msgstr "Utiliser le Debanding"
#: scene/main/scene_tree.cpp scene/main/viewport.cpp
msgid "HDR"
@@ -25063,7 +25006,7 @@ msgstr "Demi résolution"
#: scene/resources/curve.cpp
msgid "Bake Interval"
-msgstr ""
+msgstr "Intervalle de Précalcul"
#: scene/resources/default_theme/default_theme.cpp
msgid "Panel"
@@ -25304,7 +25247,7 @@ msgstr "Poignée quand désactivée"
#: scene/resources/default_theme/default_theme.cpp
msgid "Tick"
-msgstr ""
+msgstr "Signet"
#: scene/resources/default_theme/default_theme.cpp
msgid "Updown"
@@ -25502,7 +25445,7 @@ msgstr "Couleur des lignes de relation"
#: scene/resources/default_theme/default_theme.cpp
msgid "Custom Button Font Highlight"
-msgstr ""
+msgstr "Surlignage Personnalisé de la Police du Bouton"
#: scene/resources/default_theme/default_theme.cpp
msgid "Item Margin"
@@ -25736,7 +25679,7 @@ msgstr "Déplacer des points de Bézier"
#: scene/resources/default_theme/default_theme.cpp
msgid "Bezier Len Neg"
-msgstr ""
+msgstr "Longueur Négative Courbe de Bézier"
#: scene/resources/default_theme/default_theme.cpp
msgid "Port Grab Distance Horizontal"
@@ -25808,7 +25751,7 @@ msgstr "Degrés de Rotation du Ciel"
#: scene/resources/environment.cpp
msgid "Canvas Max Layer"
-msgstr ""
+msgstr "Calque Max du Canvas"
#: scene/resources/environment.cpp scene/resources/texture.cpp
msgid "Camera Feed ID"
@@ -26083,7 +26026,7 @@ msgstr "Passe suivante"
#: scene/resources/material.cpp
msgid "Use Shadow To Opacity"
-msgstr ""
+msgstr "Utiliser l'ombre pour l'opacité"
#: scene/resources/material.cpp
msgid "Unshaded"
@@ -26240,7 +26183,7 @@ msgstr "Occlusion ambiante"
#: scene/resources/material.cpp
msgid "Deep Parallax"
-msgstr ""
+msgstr "Parallaxe Profonde"
#: scene/resources/material.cpp
#, fuzzy
@@ -26254,7 +26197,7 @@ msgstr "Calque"
#: scene/resources/material.cpp
msgid "Flip Tangent"
-msgstr ""
+msgstr "Inverser la Tangente"
#: scene/resources/material.cpp
#, fuzzy
@@ -26291,7 +26234,7 @@ msgstr "Triplanaire"
#: scene/resources/material.cpp
msgid "Triplanar Sharpness"
-msgstr ""
+msgstr "Netteté Triplanaire"
#: scene/resources/material.cpp
msgid "UV2"
@@ -26304,7 +26247,7 @@ msgstr "Mode prioritaire"
#: scene/resources/material.cpp
msgid "Distance Fade"
-msgstr ""
+msgstr "Fondu de Distance"
#: scene/resources/material.cpp
msgid "Async Mode"
@@ -26317,7 +26260,7 @@ msgstr "LightMap Bake"
#: scene/resources/mesh.cpp scene/resources/primitive_meshes.cpp
msgid "Custom AABB"
-msgstr ""
+msgstr "AABB Personnalisé"
#: scene/resources/mesh_library.cpp
msgid "Mesh Transform"
@@ -26337,7 +26280,7 @@ msgstr "Format de transformation"
#: scene/resources/multimesh.cpp
msgid "Custom Data Format"
-msgstr ""
+msgstr "Format de Données Personnalisé"
#: scene/resources/multimesh.cpp
msgid "Instance Count"
@@ -26361,7 +26304,7 @@ msgstr "Type de la géométrie analysée"
#: scene/resources/navigation_mesh.cpp
msgid "Source Geometry Mode"
-msgstr ""
+msgstr "Mode Géométrie Source"
#: scene/resources/navigation_mesh.cpp
#, fuzzy
@@ -26378,7 +26321,7 @@ msgstr "Agents"
#: scene/resources/navigation_mesh.cpp
msgid "Max Climb"
-msgstr ""
+msgstr "Escalade Max"
#: scene/resources/navigation_mesh.cpp
msgid "Max Slope"
@@ -26404,7 +26347,7 @@ msgstr "Erreur"
#: scene/resources/navigation_mesh.cpp
msgid "Verts Per Poly"
-msgstr ""
+msgstr "Sommets par Poly"
#: scene/resources/navigation_mesh.cpp
msgid "Details"
@@ -26421,15 +26364,15 @@ msgstr "Échantillonneur"
#: scene/resources/navigation_mesh.cpp
msgid "Low Hanging Obstacles"
-msgstr ""
+msgstr "Obstacles Suspendus Bas"
#: scene/resources/navigation_mesh.cpp
msgid "Ledge Spans"
-msgstr ""
+msgstr "Etendue de Rebord"
#: scene/resources/navigation_mesh.cpp
msgid "Walkable Low Height Spans"
-msgstr ""
+msgstr "Etendues de faible hauteur praticables"
#: scene/resources/navigation_mesh.cpp
#, fuzzy
@@ -26507,7 +26450,7 @@ msgstr "Fermer la courbe"
#: scene/resources/physics_material.cpp
msgid "Rough"
-msgstr ""
+msgstr "Rugueux"
#: scene/resources/physics_material.cpp
msgid "Absorbent"
@@ -26523,7 +26466,7 @@ msgstr "Retourner les faces"
#: scene/resources/primitive_meshes.cpp
msgid "Mid Height"
-msgstr ""
+msgstr "Mi-hauteur"
#: scene/resources/primitive_meshes.cpp
msgid "Subdivide Width"
@@ -26568,7 +26511,7 @@ msgstr "A"
#: scene/resources/shape_2d.cpp
msgid "Custom Solver Bias"
-msgstr ""
+msgstr "Biais Personnalisé du Solveur"
#: scene/resources/skin.cpp
msgid "Bind Count"
@@ -26646,7 +26589,7 @@ msgstr "Changer le rayon intérieur de la tour"
#: scene/resources/style_box.cpp
msgid "Corner Detail"
-msgstr ""
+msgstr "Détail des Coins"
#: scene/resources/style_box.cpp
msgid "Anti Aliasing"
@@ -26654,11 +26597,11 @@ msgstr "Anticrénelage"
#: scene/resources/style_box.cpp
msgid "Grow Begin"
-msgstr ""
+msgstr "Début d'Expansion"
#: scene/resources/style_box.cpp
msgid "Grow End"
-msgstr ""
+msgstr "Fin d'Expansion"
#: scene/resources/texture.cpp
#, fuzzy
@@ -26715,7 +26658,7 @@ msgstr "Pause"
#: scene/resources/texture.cpp
msgid "Which Feed"
-msgstr ""
+msgstr "Quel Flux"
#: scene/resources/texture.cpp
msgid "Camera Is Active"
@@ -27523,7 +27466,7 @@ msgstr "Nombre de compilations simultanées"
#: servers/visual_server.cpp
msgid "Log Active Async Compiles Count"
-msgstr ""
+msgstr "Noter le nombre de compilations asynchrones actives"
#: servers/visual_server.cpp
msgid "Shader Cache Size (MB)"
diff --git a/editor/translations/ga.po b/editor/translations/ga.po
index 246c04dc63..01810bb059 100644
--- a/editor/translations/ga.po
+++ b/editor/translations/ga.po
@@ -12451,9 +12451,10 @@ msgstr "Cruthaigh"
#: scene/2d/path_2d.cpp scene/2d/polygon_2d.cpp scene/2d/sprite.cpp
#: scene/3d/cpu_particles.cpp scene/3d/label_3d.cpp scene/3d/path.cpp
#: scene/3d/physics_body.cpp scene/3d/soft_body.cpp scene/3d/sprite_3d.cpp
-#: 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
+#: scene/3d/visual_instance.cpp 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
msgid "Offset"
msgstr ""
@@ -13796,12 +13797,11 @@ msgstr ""
#: editor/project_manager.cpp
msgid ""
-"Couldn't load project.godot in project path (error %d). It may be missing or "
-"corrupted."
+"Couldn't load project at '%s' (error %d). It may be missing or corrupted."
msgstr ""
#: editor/project_manager.cpp
-msgid "Couldn't edit project.godot in project path."
+msgid "Couldn't save project at '%s' (error %d)."
msgstr ""
#: editor/project_manager.cpp
@@ -22473,6 +22473,15 @@ msgstr ""
msgid "AABB"
msgstr ""
+#: scene/3d/visual_instance.cpp
+#, fuzzy
+msgid "Sorting"
+msgstr "Nód Beochana"
+
+#: scene/3d/visual_instance.cpp
+msgid "Use AABB Center"
+msgstr ""
+
#: scene/3d/visual_instance.cpp scene/resources/navigation_mesh.cpp
msgid "Geometry"
msgstr ""
diff --git a/editor/translations/gl.po b/editor/translations/gl.po
index 2445ec4783..1d2fbb333a 100644
--- a/editor/translations/gl.po
+++ b/editor/translations/gl.po
@@ -13135,9 +13135,10 @@ msgstr "Opcións de Axuste de Cuadrícula"
#: scene/2d/path_2d.cpp scene/2d/polygon_2d.cpp scene/2d/sprite.cpp
#: scene/3d/cpu_particles.cpp scene/3d/label_3d.cpp scene/3d/path.cpp
#: scene/3d/physics_body.cpp scene/3d/soft_body.cpp scene/3d/sprite_3d.cpp
-#: 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
+#: scene/3d/visual_instance.cpp 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 "Offset:"
@@ -14561,17 +14562,18 @@ msgid "Invalid project path (changed anything?)."
msgstr "A ruta ao proxecto non é valida. Cambiaches algo?"
#: editor/project_manager.cpp
+#, fuzzy
msgid ""
-"Couldn't load project.godot in project path (error %d). It may be missing or "
-"corrupted."
+"Couldn't load project at '%s' (error %d). It may be missing or corrupted."
msgstr ""
"Non se pudo cargar o arquivo de configuración 'project.godot' na ruta do "
"proxecto (erro %d). Pode ser que o arquivo non exista; ou que esté "
"corrompido."
#: editor/project_manager.cpp
-msgid "Couldn't edit project.godot in project path."
-msgstr "Non se pudo editar o arquivo 'project.godot' na ruta do proxecto."
+#, fuzzy
+msgid "Couldn't save project at '%s' (error %d)."
+msgstr "Non se pode abrir proxecto en '%s'."
#: editor/project_manager.cpp
msgid "Couldn't create project.godot in project path."
@@ -23866,6 +23868,15 @@ msgstr "Erro"
msgid "AABB"
msgstr ""
+#: scene/3d/visual_instance.cpp
+#, fuzzy
+msgid "Sorting"
+msgstr "Ordenar"
+
+#: scene/3d/visual_instance.cpp
+msgid "Use AABB Center"
+msgstr ""
+
#: scene/3d/visual_instance.cpp scene/resources/navigation_mesh.cpp
#, fuzzy
msgid "Geometry"
diff --git a/editor/translations/he.po b/editor/translations/he.po
index e0a690c9b4..57b2386570 100644
--- a/editor/translations/he.po
+++ b/editor/translations/he.po
@@ -23,13 +23,16 @@
# Shailee Eliyahu <dev.sle.il@gmail.com>, 2021.
# Mati Borlak <matiborlak@gmail.com>, 2022.
# Tamir Livneh <fkeyzuwu@gmail.com>, 2022.
+# Tomer Ben Rachel <tomerpacific@gmail.com>, 2022.
+# moshe mil <milgmoshe@gmail.com>, 2022.
+# Blawnode <blawnode@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-09-05 11:17+0000\n"
-"Last-Translator: Tamir Livneh <fkeyzuwu@gmail.com>\n"
+"PO-Revision-Date: 2022-11-23 20:47+0000\n"
+"Last-Translator: Blawnode <blawnode@gmail.com>\n"
"Language-Team: Hebrew <https://hosted.weblate.org/projects/godot-engine/"
"godot/he/>\n"
"Language: he\n"
@@ -38,7 +41,7 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=4; plural=(n == 1) ? 0 : ((n == 2) ? 1 : ((n > 10 && "
"n % 10 == 0) ? 2 : 3));\n"
-"X-Generator: Weblate 4.14.1-dev\n"
+"X-Generator: Weblate 4.15-dev\n"
#: core/bind/core_bind.cpp main/main.cpp
msgid "Tablet Driver"
@@ -57,26 +60,24 @@ msgid "Exit Code"
msgstr "קוד יצי××”"
#: core/bind/core_bind.cpp
-#, fuzzy
msgid "V-Sync Enabled"
-msgstr "הפעלה"
+msgstr "V-Sync מופעל"
#: core/bind/core_bind.cpp main/main.cpp
msgid "V-Sync Via Compositor"
-msgstr ""
+msgstr "V-Sync דרך Compositor"
#: core/bind/core_bind.cpp main/main.cpp
msgid "Delta Smoothing"
-msgstr ""
+msgstr "החלקת דלט×"
#: core/bind/core_bind.cpp
-#, fuzzy
msgid "Low Processor Usage Mode"
-msgstr "×™×™×¦×•× ×ž×™×–×"
+msgstr "מצב שימוש נמוך של מעבד"
#: core/bind/core_bind.cpp
msgid "Low Processor Usage Mode Sleep (µsec)"
-msgstr ""
+msgstr "מצב שינה שימוש נמוך במעבד (מיקרו שניות)"
#: core/bind/core_bind.cpp main/main.cpp platform/uwp/os_uwp.cpp
msgid "Keep Screen On"
@@ -105,7 +106,7 @@ msgstr "בלי קצה"
#: core/bind/core_bind.cpp
msgid "Per Pixel Transparency Enabled"
-msgstr ""
+msgstr "שקיפות-פר-פיקסל מופעלת"
#: core/bind/core_bind.cpp core/project_settings.cpp
msgid "Fullscreen"
@@ -146,7 +147,7 @@ msgstr "גודל"
#: core/bind/core_bind.cpp
msgid "Endian Swap"
-msgstr ""
+msgstr "החלפת סדר ×‘×ª×™× (Byte Order)"
#: core/bind/core_bind.cpp
msgid "Editor Hint"
@@ -161,28 +162,24 @@ msgid "Iterations Per Second"
msgstr "×יטרציות לשניה"
#: core/bind/core_bind.cpp
-#, fuzzy
msgid "Target FPS"
-msgstr "נתיב המש×ב"
+msgstr "יעד קצב פריימי×"
#: core/bind/core_bind.cpp
-#, fuzzy
msgid "Time Scale"
-msgstr "מפרק TimeScale"
+msgstr "ציר זמן"
#: core/bind/core_bind.cpp main/main.cpp
-#, fuzzy
msgid "Physics Jitter Fix"
-msgstr "שקופית פיזיקלית %"
+msgstr "תיקון רטט בפיזיקה"
#: core/bind/core_bind.cpp editor/plugins/version_control_editor_plugin.cpp
msgid "Error"
msgstr "שגי××”"
#: core/bind/core_bind.cpp
-#, fuzzy
msgid "Error String"
-msgstr "שגי××” בשמירה"
+msgstr "מחרוזת שגויה"
#: core/bind/core_bind.cpp
msgid "Error Line"
@@ -213,7 +210,7 @@ msgstr "תור פיקוד"
#: core/command_queue_mt.cpp
msgid "Multithreading Queue Size (KB)"
-msgstr ""
+msgstr "גודל תור תהליכי משנה (KB)"
#: core/func_ref.cpp modules/visual_script/visual_script_builtin_funcs.cpp
#: modules/visual_script/visual_script_func_nodes.cpp
@@ -236,9 +233,8 @@ msgid "Network"
msgstr "רשת"
#: core/io/file_access_network.cpp
-#, fuzzy
msgid "Remote FS"
-msgstr "מרוחק "
+msgstr "שרת ×§×‘×¦×™× ×ž×¨×•×—×§"
#: core/io/file_access_network.cpp
msgid "Page Size"
@@ -246,11 +242,11 @@ msgstr "גודל דף"
#: core/io/file_access_network.cpp
msgid "Page Read Ahead"
-msgstr ""
+msgstr "קרי××” מר×ש של דף"
#: core/io/http_client.cpp
msgid "Blocking Mode Enabled"
-msgstr ""
+msgstr "מצב חסימה מ×ופשר"
#: core/io/http_client.cpp
msgid "Connection"
@@ -258,25 +254,24 @@ msgstr "חיבור"
#: core/io/http_client.cpp
msgid "Read Chunk Size"
-msgstr ""
+msgstr "גודל קרי×ת נתח"
#: core/io/marshalls.cpp
msgid "Object ID"
msgstr "זהות ×וביקט"
#: core/io/multiplayer_api.cpp core/io/packet_peer.cpp
-#, fuzzy
msgid "Allow Object Decoding"
-msgstr "הפעלת שכבות בצל"
+msgstr "×פשר פענוח ×ובייקט"
#: core/io/multiplayer_api.cpp scene/main/scene_tree.cpp
msgid "Refuse New Network Connections"
-msgstr ""
+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
@@ -284,26 +279,24 @@ msgid "Root Node"
msgstr "שינוי ×©× ×ž×¤×¨×§ השורש"
#: core/io/networked_multiplayer_peer.cpp
-#, fuzzy
msgid "Refuse New Connections"
-msgstr "התחברות"
+msgstr "דחה ×—×™×‘×•×¨×™× ×—×“×©×™×"
#: core/io/networked_multiplayer_peer.cpp
-#, fuzzy
msgid "Transfer Mode"
-msgstr "מפרק מעברון"
+msgstr "מצב מעבר"
#: core/io/packet_peer.cpp
msgid "Encode Buffer Max Size"
-msgstr ""
+msgstr "קודד גודל מקסימלי של החוצץ"
#: core/io/packet_peer.cpp
msgid "Input Buffer Max Size"
-msgstr ""
+msgstr "הכנס גודל מירבי של החוצץ"
#: core/io/packet_peer.cpp
msgid "Output Buffer Max Size"
-msgstr ""
+msgstr "פלוט גודל מירבי של החוצץ"
#: core/io/packet_peer.cpp
msgid "Stream Peer"
@@ -314,17 +307,17 @@ msgid "Big Endian"
msgstr ""
#: core/io/stream_peer.cpp
+#, fuzzy
msgid "Data Array"
-msgstr ""
+msgstr "מערך מידע"
#: core/io/stream_peer_ssl.cpp
msgid "Blocking Handshake"
-msgstr ""
+msgstr "לחיצת ×™×“×™×™× ×—×•×¡×ž×ª"
#: core/io/udp_server.cpp
-#, fuzzy
msgid "Max Pending Connections"
-msgstr "עריכת חיבור:"
+msgstr "×ž×§×¡×™×ž×•× ×—×™×‘×•×¨×™× ×ž×ž×ª×™× ×™×"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
@@ -342,9 +335,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)"
@@ -373,7 +365,7 @@ msgstr "בקרי××” ל־‚%s’:"
#: core/math/random_number_generator.cpp
#: modules/opensimplex/open_simplex_noise.cpp
msgid "Seed"
-msgstr ""
+msgstr "גרעין"
#: core/math/random_number_generator.cpp
msgid "State"
@@ -381,7 +373,7 @@ msgstr "מצב"
#: core/message_queue.cpp
msgid "Message Queue"
-msgstr "תור הור×ות"
+msgstr "תור הודעות"
#: core/message_queue.cpp
msgid "Max Size (KB)"
@@ -409,7 +401,7 @@ msgstr "הכל"
#: core/os/input_event.cpp
msgid "Shift"
-msgstr ""
+msgstr "הסט"
#: core/os/input_event.cpp
#, fuzzy
@@ -418,11 +410,11 @@ msgstr "בקרת גירס×ות"
#: core/os/input_event.cpp
msgid "Meta"
-msgstr ""
+msgstr "מט×"
#: core/os/input_event.cpp
msgid "Command"
-msgstr "פיקוד"
+msgstr "פקודה"
#: core/os/input_event.cpp
#, fuzzy
@@ -442,11 +434,11 @@ msgstr "סריקת מקורות"
#: core/os/input_event.cpp
msgid "Physical Scancode"
-msgstr ""
+msgstr "קוד סריקה פיזי"
#: core/os/input_event.cpp
msgid "Unicode"
-msgstr ""
+msgstr "יוניקוד"
#: core/os/input_event.cpp
msgid "Echo"
@@ -473,11 +465,11 @@ msgstr "מפתח כפתורי עכבר:"
#: core/os/input_event.cpp
msgid "Doubleclick"
-msgstr ""
+msgstr "לחיצת עכבר כפולה"
#: core/os/input_event.cpp
msgid "Tilt"
-msgstr ""
+msgstr "הטייה"
#: core/os/input_event.cpp
msgid "Pressure"
@@ -539,7 +531,7 @@ msgstr "מסר"
#: core/os/input_event.cpp
#, fuzzy
msgid "Pitch"
-msgstr "קנה מידה:"
+msgstr "גובה צליל"
#: core/os/input_event.cpp scene/2d/cpu_particles_2d.cpp
#: scene/2d/physics_body_2d.cpp scene/3d/cpu_particles.cpp
@@ -608,14 +600,12 @@ msgid "Main Scene"
msgstr ""
#: core/project_settings.cpp
-#, fuzzy
msgid "Disable stdout"
-msgstr "כפתור ×מצעי"
+msgstr "בטל stdout"
#: core/project_settings.cpp
-#, fuzzy
msgid "Disable stderr"
-msgstr "מושבת"
+msgstr "השבת stderr"
#: core/project_settings.cpp
msgid "Use Hidden Project Data Directory"
@@ -857,9 +847,8 @@ msgid "Max Functions"
msgstr "יצירת פונקציה"
#: core/project_settings.cpp scene/3d/vehicle_body.cpp
-#, fuzzy
msgid "Compression"
-msgstr "גרסה נוכחית:"
+msgstr "כיווץ"
#: core/project_settings.cpp
#, fuzzy
@@ -900,12 +889,12 @@ msgstr ""
#: core/register_core_types.cpp
msgid "TCP"
-msgstr ""
+msgstr "TCP"
#: core/register_core_types.cpp
#, fuzzy
msgid "Connect Timeout Seconds"
-msgstr "התחברות למפרק:"
+msgstr "שניות קצובות להתחברות"
#: core/register_core_types.cpp
msgid "Packet Peer Stream"
@@ -917,12 +906,11 @@ msgstr ""
#: 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
-#, fuzzy
msgid "Certificates"
-msgstr "קודקודי×"
+msgstr "תעודות"
#: core/resource.cpp editor/dependency_editor.cpp
#: editor/editor_resource_picker.cpp
@@ -931,9 +919,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
@@ -943,13 +930,12 @@ msgid "Path"
msgstr "נתיב"
#: core/script_language.cpp
-#, fuzzy
msgid "Source Code"
-msgstr "מש×ב"
+msgstr "קוד מקור"
#: core/translation.cpp editor/project_settings_editor.cpp
msgid "Locale"
-msgstr ""
+msgstr "מקומי"
#: core/translation.cpp
msgid "Test"
@@ -3430,7 +3416,7 @@ msgstr "×™×™×‘×•× ×ž×©××‘×™× (מחדש)"
#: editor/editor_file_system.cpp
msgid "Reimport Missing Imported Files"
-msgstr ""
+msgstr "×™×™×‘×•× ×§×‘×¦×™× ×—×¡×¨×™× ×ž×—×“×©"
#: editor/editor_help.cpp scene/2d/camera_2d.cpp scene/gui/control.cpp
#: scene/gui/nine_patch_rect.cpp scene/resources/dynamic_font.cpp
@@ -4324,11 +4310,11 @@ msgstr "החלפת לשונית סצנה"
#: editor/editor_node.cpp
msgid "Always Show Close Button"
-msgstr ""
+msgstr "תמיד הר××” כפתור סגירה"
#: editor/editor_node.cpp editor/editor_settings.cpp
msgid "Resize If Many Tabs"
-msgstr ""
+msgstr "שינוי גודל כשט××‘×™× ×ž×¨×•×‘×™×"
#: editor/editor_node.cpp editor/editor_settings.cpp
msgid "Minimum Width"
@@ -4353,7 +4339,7 @@ msgstr ""
#: editor/editor_node.cpp
msgid "Save On Focus Loss"
-msgstr ""
+msgstr "שמור ב×יבוד פוקוס"
#: editor/editor_node.cpp editor/editor_settings.cpp
#, fuzzy
@@ -4385,13 +4371,12 @@ msgid "Localize Settings"
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"
-msgstr ""
+msgstr "הר××” דוגמית בריחוף מעל"
#: editor/editor_node.cpp editor/editor_settings.cpp
msgid "Inspector"
@@ -4435,7 +4420,7 @@ msgstr "פתיחה במפקח"
#: editor/editor_node.cpp
msgid "Default Color Picker Mode"
-msgstr ""
+msgstr "מצב ברירת מחדל לבחירת צבעי×"
#: editor/editor_node.cpp editor/plugins/version_control_editor_plugin.cpp
msgid "Version Control"
@@ -5364,7 +5349,7 @@ msgstr "ערכה מוגדרת…"
#: editor/editor_settings.cpp
msgid "Icon And Font Color"
-msgstr ""
+msgstr "צבע ×יקון ופונט"
#: editor/editor_settings.cpp
#, fuzzy
@@ -5524,9 +5509,8 @@ 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
@@ -5586,7 +5570,6 @@ msgid "Show Line Numbers"
msgstr "שורה מספר:"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Line Numbers Zero Padded"
msgstr "שורה מספר:"
@@ -5613,7 +5596,7 @@ msgstr ""
#: editor/editor_settings.cpp
msgid "Show Line Length Guidelines"
-msgstr ""
+msgstr "הר××” מדריך ×ורך קו"
#: editor/editor_settings.cpp
msgid "Line Length Guideline Soft Column"
@@ -5647,7 +5630,7 @@ msgstr ""
#: editor/editor_settings.cpp editor/plugins/script_editor_plugin.cpp
msgid "Restore Scripts On Load"
-msgstr ""
+msgstr "שיחזור ×¡×§×¨×™×¤×˜×™× ×‘×¢×ª טעינה"
#: editor/editor_settings.cpp
msgid "Auto Reload And Parse Scripts On Save"
@@ -5887,7 +5870,7 @@ msgstr ""
#: editor/editor_settings.cpp
msgid "Emulate 3 Button Mouse"
-msgstr ""
+msgstr "דמה עכבר בעל 3 כפתורי×"
#: editor/editor_settings.cpp
msgid "Orbit Modifier"
@@ -12414,23 +12397,20 @@ msgid "Edit Items"
msgstr "עריכת מסנני×"
#: editor/plugins/theme_editor_plugin.cpp
-#, fuzzy
msgid "Types:"
-msgstr "סוג"
+msgstr "סוגי×:"
#: editor/plugins/theme_editor_plugin.cpp
-#, fuzzy
msgid "Add Type:"
-msgstr "סוג"
+msgstr "הוסף סוג:"
#: editor/plugins/theme_editor_plugin.cpp
-#, fuzzy
msgid "Add Item:"
-msgstr "הוספת קלט"
+msgstr "הוסף פריט:"
#: editor/plugins/theme_editor_plugin.cpp
msgid "Add StyleBox Item"
-msgstr ""
+msgstr "הוסף פריט StyleBox"
#: editor/plugins/theme_editor_plugin.cpp
#, fuzzy
@@ -13243,9 +13223,10 @@ msgstr "הגדרות הצמדה"
#: scene/2d/path_2d.cpp scene/2d/polygon_2d.cpp scene/2d/sprite.cpp
#: scene/3d/cpu_particles.cpp scene/3d/label_3d.cpp scene/3d/path.cpp
#: scene/3d/physics_body.cpp scene/3d/soft_body.cpp scene/3d/sprite_3d.cpp
-#: 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
+#: scene/3d/visual_instance.cpp 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 "היסט רשת:"
@@ -13451,7 +13432,7 @@ msgstr ""
#: editor/plugins/version_control_editor_plugin.cpp
msgid "SSH Passphrase"
-msgstr ""
+msgstr "סיסמת SSH"
#: editor/plugins/version_control_editor_plugin.cpp
#, fuzzy
@@ -14667,13 +14648,13 @@ msgstr ""
#: editor/project_manager.cpp
msgid ""
-"Couldn't load project.godot in project path (error %d). It may be missing or "
-"corrupted."
+"Couldn't load project at '%s' (error %d). It may be missing or corrupted."
msgstr ""
#: editor/project_manager.cpp
-msgid "Couldn't edit project.godot in project path."
-msgstr ""
+#, fuzzy
+msgid "Couldn't save project at '%s' (error %d)."
+msgstr "×œ× × ×™×ª×Ÿ לפתוח ×ת ‚%s’."
#: editor/project_manager.cpp
msgid "Couldn't create project.godot in project path."
@@ -18440,7 +18421,7 @@ msgstr ""
#: modules/visual_script/visual_script_flow_control.cpp
msgid "While"
-msgstr ""
+msgstr "כל עוד"
#: modules/visual_script/visual_script_flow_control.cpp
msgid "while (cond):"
@@ -20462,16 +20443,15 @@ msgstr ""
#: platform/osx/export/export.cpp
msgid "macOS"
-msgstr ""
+msgstr "macOS"
#: platform/osx/export/export.cpp
msgid "Force Builtin Codesign"
msgstr ""
#: platform/uwp/export/export.cpp
-#, fuzzy
msgid "Architecture"
-msgstr "הוספת ערך ×רכיטקטורה"
+msgstr "×רכיטקטורה"
#: platform/uwp/export/export.cpp
#, fuzzy
@@ -20508,14 +20488,12 @@ msgid "Signing"
msgstr "×ות"
#: platform/uwp/export/export.cpp
-#, fuzzy
msgid "Certificate"
-msgstr "קודקודי×"
+msgstr "תעודה"
#: platform/uwp/export/export.cpp
-#, fuzzy
msgid "Algorithm"
-msgstr "ניפוי שגי×ות"
+msgstr "×לגורית×"
#: platform/uwp/export/export.cpp
msgid "Major"
@@ -20845,7 +20823,7 @@ msgstr ""
#: 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."
@@ -20886,12 +20864,12 @@ msgstr "×”×–×—×” משמ×ל"
#: 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 "הפוך ×ופקית"
#: 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 "הפוך ×נכית"
#: scene/2d/area_2d.cpp scene/3d/area.cpp
#, fuzzy
@@ -20931,7 +20909,7 @@ msgstr "תצוגה מקדימה:"
#: 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 "כוח כבידה"
#: scene/2d/area_2d.cpp scene/3d/area.cpp
#, fuzzy
@@ -20955,20 +20933,18 @@ msgstr "דריסה"
#: 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
msgid "Volume dB"
-msgstr ""
+msgstr "×•×•×œ×™×•× ×‘×“×¦×™×‘×œ×™×"
#: 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 "קנה מידה:"
+msgstr "גובל צליל"
#: 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 "הפעלת/ביטול הפעלה ×וטומטית"
+msgstr "הפעלה ×וטומטית"
#: scene/2d/audio_stream_player_2d.cpp scene/3d/audio_stream_player_3d.cpp
#: scene/audio/audio_stream_player.cpp
@@ -21861,9 +21837,8 @@ msgid "Rotation Degrees"
msgstr "הטיה של %s מעלות."
#: scene/2d/node_2d.cpp scene/3d/spatial.cpp
-#, fuzzy
msgid "Global Rotation"
-msgstr "קבוע"
+msgstr "רוטציה גלובלית"
#: scene/2d/node_2d.cpp
#, fuzzy
@@ -21887,12 +21862,11 @@ msgstr ""
#: scene/2d/parallax_background.cpp scene/gui/scroll_container.cpp
#: scene/resources/default_theme/default_theme.cpp
msgid "Scroll"
-msgstr ""
+msgstr "גלול"
#: scene/2d/parallax_background.cpp
-#, fuzzy
msgid "Base Offset"
-msgstr "היסט רשת:"
+msgstr "סטייה מהבסיס"
#: scene/2d/parallax_background.cpp
#, fuzzy
@@ -21910,7 +21884,7 @@ msgstr "בסוף"
#: scene/2d/parallax_background.cpp
msgid "Ignore Camera Zoom"
-msgstr ""
+msgstr "×”×ª×¢×œ× ×ž×–×•× ×”×ž×¦×œ×ž×”"
#: scene/2d/parallax_layer.cpp
msgid ""
@@ -22215,15 +22189,15 @@ msgstr "יצירת תיקייה"
#: scene/2d/ray_cast_2d.cpp scene/3d/ray_cast.cpp
msgid "Collide With"
-msgstr ""
+msgstr "מתנגש ×¢×"
#: scene/2d/ray_cast_2d.cpp scene/3d/camera.cpp scene/3d/ray_cast.cpp
msgid "Areas"
-msgstr ""
+msgstr "×זורי×"
#: scene/2d/ray_cast_2d.cpp scene/3d/camera.cpp scene/3d/ray_cast.cpp
msgid "Bodies"
-msgstr ""
+msgstr "גופי×"
#: scene/2d/remote_transform_2d.cpp
msgid "Path property must point to a valid Node2D node to work."
@@ -22264,11 +22238,11 @@ msgstr "×œ×¢×¦× ×–×• ×ין תנוחת REST ר×ויה. עבור למפרק ×”-
#: scene/2d/sprite.cpp scene/3d/sprite_3d.cpp
msgid "Hframes"
-msgstr ""
+msgstr "שקופיות ×ופקיות"
#: scene/2d/sprite.cpp scene/3d/sprite_3d.cpp
msgid "Vframes"
-msgstr ""
+msgstr "שקופיות ×נכיות"
#: scene/2d/sprite.cpp scene/3d/sprite_3d.cpp
#, fuzzy
@@ -22315,9 +22289,8 @@ msgid "Tile Origin"
msgstr ""
#: scene/2d/tile_map.cpp
-#, fuzzy
msgid "Y Sort"
-msgstr "מיון"
+msgstr "מיון ×× ×›×™"
#: scene/2d/tile_map.cpp
#, fuzzy
@@ -22339,13 +22312,12 @@ msgid "Cell Clip UV"
msgstr ""
#: scene/2d/tile_map.cpp
-#, fuzzy
msgid "Use Parent"
-msgstr "עריכת מצולע"
+msgstr "השתמש בהורה"
#: scene/2d/tile_map.cpp
msgid "Use Kinematic"
-msgstr ""
+msgstr "השתמש בפיזיקה קינמטית"
#: scene/2d/touch_screen_button.cpp
msgid "Shape Centered"
@@ -22380,7 +22352,7 @@ msgstr "הדבקת הנפשה"
#: scene/2d/visibility_notifier_2d.cpp scene/3d/visibility_notifier.cpp
msgid "Freeze Bodies"
-msgstr ""
+msgstr "×”×§×¤× ×’×•×¤×™×"
#: scene/2d/visibility_notifier_2d.cpp
#, fuzzy
@@ -22576,7 +22548,7 @@ msgstr "מסנני×..."
#: scene/3d/baked_lightmap.cpp scene/resources/texture.cpp
msgid "Use HDR"
-msgstr ""
+msgstr "השתמש בHDR"
#: scene/3d/baked_lightmap.cpp
#, fuzzy
@@ -22598,14 +22570,12 @@ msgid "Generate"
msgstr "כללי"
#: scene/3d/baked_lightmap.cpp
-#, fuzzy
msgid "Max Size"
-msgstr "מבט קדמי"
+msgstr "גודל מקסימלי"
#: scene/3d/baked_lightmap.cpp
-#, fuzzy
msgid "Custom Sky"
-msgstr "גזירת מפרקי×"
+msgstr "×©×ž×™×™× ×ž×•×ª××ž×™× ×ישית"
#: scene/3d/baked_lightmap.cpp
#, fuzzy
@@ -22613,9 +22583,8 @@ msgid "Custom Sky Rotation Degrees"
msgstr "הטיה של %s מעלות."
#: scene/3d/baked_lightmap.cpp scene/3d/ray_cast.cpp
-#, fuzzy
msgid "Custom Color"
-msgstr "גזירת מפרקי×"
+msgstr "צבע מות×× ×ישית"
#: scene/3d/baked_lightmap.cpp
#, fuzzy
@@ -22642,9 +22611,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"
@@ -22666,12 +22634,11 @@ msgstr "מיז×"
#: scene/3d/camera.cpp
msgid "FOV"
-msgstr ""
+msgstr "קוטר ר××™×™×”"
#: scene/3d/camera.cpp
-#, fuzzy
msgid "Frustum Offset"
-msgstr "היסט רשת:"
+msgstr "היסט רשת"
#: scene/3d/camera.cpp
#, fuzzy
@@ -23427,7 +23394,7 @@ msgstr "×ותיות קטנות"
#: scene/3d/physics_joint.cpp
msgid "Motor"
-msgstr ""
+msgstr "מוטורי"
#: scene/3d/physics_joint.cpp
#, fuzzy
@@ -24047,6 +24014,15 @@ msgstr "שגי××”!"
msgid "AABB"
msgstr ""
+#: scene/3d/visual_instance.cpp
+#, fuzzy
+msgid "Sorting"
+msgstr "מיון"
+
+#: scene/3d/visual_instance.cpp
+msgid "Use AABB Center"
+msgstr ""
+
#: scene/3d/visual_instance.cpp scene/resources/navigation_mesh.cpp
#, fuzzy
msgid "Geometry"
@@ -24350,7 +24326,7 @@ msgstr ""
#: scene/animation/skeleton_ik.cpp
msgid "Magnet"
-msgstr ""
+msgstr "מגנט"
#: scene/animation/skeleton_ik.cpp
#, fuzzy
@@ -25346,7 +25322,7 @@ msgstr "הוספת רצועה"
#: scene/gui/video_player.cpp scene/main/scene_tree.cpp scene/main/timer.cpp
msgid "Paused"
-msgstr ""
+msgstr "עצור"
#: scene/gui/video_player.cpp
#, fuzzy
@@ -25368,9 +25344,8 @@ msgid "Follow Viewport"
msgstr ""
#: scene/main/http_request.cpp
-#, fuzzy
msgid "Download File"
-msgstr "הורדה"
+msgstr "הורדת קובץ"
#: scene/main/http_request.cpp
#, fuzzy
@@ -25435,14 +25410,12 @@ msgid "Owner"
msgstr "×‘×¢×œ×™× ×©×œ:"
#: scene/main/node.cpp scene/main/scene_tree.cpp
-#, fuzzy
msgid "Multiplayer"
-msgstr "קביעה מרובה:"
+msgstr "רב-משתתפי×"
#: scene/main/node.cpp
-#, fuzzy
msgid "Custom Multiplayer"
-msgstr "קביעה מרובה:"
+msgstr "רב-×ž×©×ª×ª×¤×™× ×ž×•×ª×× ×ישית"
#: scene/main/node.cpp
#, fuzzy
@@ -25475,7 +25448,7 @@ msgstr "שורש סצינה חדש"
#: scene/main/scene_tree.cpp
msgid "Root"
-msgstr ""
+msgstr "שורש"
#: scene/main/scene_tree.cpp
#, fuzzy
@@ -25540,7 +25513,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"
@@ -25573,9 +25546,8 @@ msgid ""
msgstr ""
#: scene/main/timer.cpp
-#, fuzzy
msgid "Autostart"
-msgstr "התחלה מחדש ×וטומטית:"
+msgstr "התחלה ×וטומטית"
#: scene/main/viewport.cpp
#, fuzzy
@@ -25638,14 +25610,12 @@ msgid "Debanding"
msgstr "קישור"
#: scene/main/viewport.cpp
-#, fuzzy
msgid "Disable 3D"
-msgstr "מושבת"
+msgstr "השבת תלת מימד"
#: scene/main/viewport.cpp
-#, fuzzy
msgid "Keep 3D Linear"
-msgstr "ליני×רי"
+msgstr "הש×ר תלת מימד לינ×רי"
#: scene/main/viewport.cpp
msgid "Render Direct To Screen"
@@ -25735,11 +25705,11 @@ msgstr "ש×"
#: scene/register_scene_types.cpp
msgid "2D Render"
-msgstr ""
+msgstr "רנדור בדו-מימד"
#: scene/register_scene_types.cpp
msgid "3D Render"
-msgstr ""
+msgstr "רנדור בתלת-מימד"
#: scene/register_scene_types.cpp
#, fuzzy
@@ -25783,11 +25753,11 @@ msgstr "מפרק ערבוב"
#: scene/resources/audio_stream_sample.cpp
msgid "Stereo"
-msgstr ""
+msgstr "סטרי×ו"
#: scene/resources/concave_polygon_shape_2d.cpp
msgid "Segments"
-msgstr ""
+msgstr "חלקי×"
#: scene/resources/curve.cpp
#, fuzzy
@@ -25796,11 +25766,11 @@ msgstr "חצי רזולוציה"
#: scene/resources/curve.cpp
msgid "Bake Interval"
-msgstr ""
+msgstr "זמן בין ×פייה"
#: scene/resources/default_theme/default_theme.cpp
msgid "Panel"
-msgstr ""
+msgstr "לוח"
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
@@ -25839,7 +25809,7 @@ msgstr "לול×ת הנפשה"
#: scene/resources/default_theme/default_theme.cpp
msgid "Arrow"
-msgstr ""
+msgstr "×—×¥"
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
@@ -25958,7 +25928,7 @@ msgstr "סנן ×ותות"
#: scene/resources/default_theme/default_theme.cpp
msgid "Minimum Spaces"
-msgstr ""
+msgstr "×ž×™× ×™×ž×•× ×¨×•×•×—×™×"
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
@@ -25967,11 +25937,11 @@ msgstr "B"
#: scene/resources/default_theme/default_theme.cpp
msgid "FG"
-msgstr ""
+msgstr "FG"
#: scene/resources/default_theme/default_theme.cpp
msgid "Tab"
-msgstr ""
+msgstr "לשונית"
#: scene/resources/default_theme/default_theme.cpp
#: scene/resources/dynamic_font.cpp scene/resources/world.cpp
@@ -26044,7 +26014,7 @@ msgstr ""
#: scene/resources/default_theme/default_theme.cpp
msgid "Decrement"
-msgstr ""
+msgstr "הורדה ב1"
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
@@ -26355,7 +26325,7 @@ msgstr "מושבת"
#: scene/resources/default_theme/default_theme.cpp
msgid "Menu"
-msgstr ""
+msgstr "תפריט"
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
@@ -26392,7 +26362,7 @@ msgstr ""
#: scene/resources/default_theme/default_theme.cpp
msgid "Large"
-msgstr ""
+msgstr "גדול"
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
@@ -26436,7 +26406,7 @@ msgstr "מבט שמ×לי"
#: scene/resources/default_theme/default_theme.cpp
msgid "Screen Picker"
-msgstr ""
+msgstr "בוחר מהמסך"
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
@@ -26489,7 +26459,7 @@ msgstr "תכונות מרכזיות:"
#: scene/resources/default_theme/default_theme.cpp
msgid "Bold Italics Font"
-msgstr ""
+msgstr "גופן מודגש ומוטה"
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
@@ -26533,11 +26503,11 @@ msgstr "×”×–×—×” ×וטומטית"
#: scene/resources/default_theme/default_theme.cpp
msgid "Minus"
-msgstr ""
+msgstr "מינוס"
#: scene/resources/default_theme/default_theme.cpp
msgid "More"
-msgstr ""
+msgstr "עוד"
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
@@ -26584,7 +26554,7 @@ msgstr "עותק"
#: scene/resources/dynamic_font.cpp
msgid "Hinting"
-msgstr ""
+msgstr "רמיזה"
#: scene/resources/dynamic_font.cpp
#, fuzzy
@@ -26598,7 +26568,7 @@ msgstr "מיקוד נתיב"
#: scene/resources/dynamic_font.cpp
msgid "Outline Size"
-msgstr ""
+msgstr "גודל קו מת×ר"
#: scene/resources/dynamic_font.cpp
#, fuzzy
@@ -26627,11 +26597,11 @@ msgstr "קישור נתוני ‫מפרק"
#: scene/resources/environment.cpp
msgid "Background"
-msgstr ""
+msgstr "רקע"
#: scene/resources/environment.cpp scene/resources/sky.cpp
msgid "Sky"
-msgstr ""
+msgstr "שמיי×"
#: scene/resources/environment.cpp
#, fuzzy
@@ -26673,7 +26643,7 @@ msgstr "הנפשה"
#: scene/resources/environment.cpp
msgid "Fog"
-msgstr ""
+msgstr "×ובך"
#: scene/resources/environment.cpp
#, fuzzy
@@ -26746,7 +26716,7 @@ msgstr "ייצו×"
#: scene/resources/environment.cpp
msgid "White"
-msgstr ""
+msgstr "לבן"
#: scene/resources/environment.cpp
msgid "Auto Exposure"
@@ -26787,11 +26757,11 @@ msgstr "עומק"
#: scene/resources/environment.cpp scene/resources/material.cpp
msgid "Roughness"
-msgstr ""
+msgstr "חספוס"
#: scene/resources/environment.cpp
msgid "SSAO"
-msgstr ""
+msgstr "SSAO"
#: scene/resources/environment.cpp
#, fuzzy
@@ -26813,7 +26783,7 @@ msgstr ""
#: scene/resources/environment.cpp
msgid "Blur"
-msgstr ""
+msgstr "טשטוש"
#: scene/resources/environment.cpp
msgid "Edge Sharpness"
@@ -26849,7 +26819,7 @@ msgstr "מפתחי×"
#: scene/resources/environment.cpp
#: servers/audio/effects/audio_effect_chorus.cpp
msgid "1"
-msgstr ""
+msgstr "1"
#: scene/resources/environment.cpp
#: servers/audio/effects/audio_effect_chorus.cpp
@@ -28502,7 +28472,7 @@ msgstr "עריכת מצולע"
#: servers/visual_server.cpp
msgid "Max Active Spheres"
-msgstr ""
+msgstr "×ž×§×¡×™×ž×•× ×›×“×•×¨×™× ×קטיביי×"
#: servers/visual_server.cpp
#, fuzzy
diff --git a/editor/translations/hi.po b/editor/translations/hi.po
index 5e3b28ff79..657ee0ff41 100644
--- a/editor/translations/hi.po
+++ b/editor/translations/hi.po
@@ -16,13 +16,14 @@
# harvinder rathor <harvinderr09@gmail.com>, 2021.
# Sumanyu Aggarwal <sumanyu.code@gmail.com>, 2021.
# Arin <upadhyay.arin@gmail.com>, 2022.
+# Anime Fanz <accc1431@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-08 06:48+0000\n"
-"Last-Translator: Arin <upadhyay.arin@gmail.com>\n"
+"PO-Revision-Date: 2022-12-05 04:25+0000\n"
+"Last-Translator: Anime Fanz <accc1431@gmail.com>\n"
"Language-Team: Hindi <https://hosted.weblate.org/projects/godot-engine/godot/"
"hi/>\n"
"Language: hi\n"
@@ -30,7 +31,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-dev\n"
+"X-Generator: Weblate 4.15-dev\n"
#: core/bind/core_bind.cpp main/main.cpp
msgid "Tablet Driver"
@@ -242,72 +243,71 @@ msgid "Connection"
msgstr "संबंध"
#: core/io/http_client.cpp
+#, fuzzy
msgid "Read Chunk Size"
-msgstr ""
+msgstr "चंक आकार पढ़ें"
#: core/io/marshalls.cpp
msgid "Object ID"
-msgstr ""
+msgstr "वसà¥à¤¤à¥ आईडी"
#: core/io/multiplayer_api.cpp core/io/packet_peer.cpp
+#, fuzzy
msgid "Allow Object Decoding"
-msgstr ""
+msgstr "ऑबà¥à¤œà¥‡à¤•à¥à¤Ÿ डिकोडिंग की अनà¥à¤®à¤¤à¤¿ दें"
#: core/io/multiplayer_api.cpp scene/main/scene_tree.cpp
msgid "Refuse New Network Connections"
-msgstr ""
+msgstr "नठनेटवरà¥à¤• कनेकà¥à¤¶à¤¨ को मना करें"
#: core/io/multiplayer_api.cpp scene/main/scene_tree.cpp
msgid "Network Peer"
-msgstr ""
+msgstr "नेटवरà¥à¤• सहकरà¥à¤®à¥€"
#: core/io/multiplayer_api.cpp scene/animation/animation_player.cpp
-#, fuzzy
msgid "Root Node"
-msgstr "à¤à¤• नया बनाà¤à¤‚"
+msgstr "रूट नोड"
#: core/io/networked_multiplayer_peer.cpp
-#, fuzzy
msgid "Refuse New Connections"
-msgstr "जोड़िये"
+msgstr "नठकनेकà¥à¤¶à¤¨à¥‹à¤‚ को मना करें"
#: core/io/networked_multiplayer_peer.cpp
#, fuzzy
msgid "Transfer Mode"
-msgstr "सदसà¥à¤¯à¤¤à¤¾ बनाà¤à¤‚"
+msgstr "रीति का अंतरण करें"
#: core/io/packet_peer.cpp
msgid "Encode Buffer Max Size"
-msgstr ""
+msgstr "à¤à¤¨à¤•ोड बफर अधिकतम आकार"
#: core/io/packet_peer.cpp
msgid "Input Buffer Max Size"
-msgstr ""
+msgstr "इनपà¥à¤Ÿ बफर अधिकतम आकार"
#: core/io/packet_peer.cpp
msgid "Output Buffer Max Size"
-msgstr ""
+msgstr "आउटपà¥à¤Ÿ बफर अधिकतम आकार"
#: core/io/packet_peer.cpp
msgid "Stream Peer"
-msgstr ""
+msgstr "सà¥à¤Ÿà¥à¤°à¥€à¤® पीयर"
#: core/io/stream_peer.cpp
msgid "Big Endian"
-msgstr ""
+msgstr "बड़े à¤à¤‚डियन"
#: core/io/stream_peer.cpp
msgid "Data Array"
-msgstr ""
+msgstr "डेटा à¤à¤°à¥‡"
#: core/io/stream_peer_ssl.cpp
msgid "Blocking Handshake"
-msgstr ""
+msgstr "हैंडशेक बà¥à¤²à¥‰à¤• करना"
#: core/io/udp_server.cpp
-#, fuzzy
msgid "Max Pending Connections"
-msgstr "कनेकà¥à¤¶à¤¨ संपादित करें:"
+msgstr "अधिकतम लंबित कनेकà¥à¤¶à¤¨"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
@@ -325,9 +325,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)"
@@ -355,144 +354,141 @@ msgstr "'%s ' को कॉल करने पर:"
#: core/math/random_number_generator.cpp
#: modules/opensimplex/open_simplex_noise.cpp
+#, fuzzy
msgid "Seed"
-msgstr ""
+msgstr "बीज"
#: core/math/random_number_generator.cpp
+#, fuzzy
msgid "State"
-msgstr ""
+msgstr "राजà¥à¤¯"
#: core/message_queue.cpp
+#, fuzzy
msgid "Message Queue"
-msgstr ""
+msgstr "संदेश कतार"
#: core/message_queue.cpp
msgid "Max Size (KB)"
-msgstr ""
+msgstr "अधिकतम आकार (केबी)"
#: core/os/input.cpp
-#, fuzzy
msgid "Mouse Mode"
-msgstr "दृशà¥à¤¯ रोकें"
+msgstr "माउस मोड"
#: core/os/input.cpp
msgid "Use Accumulated Input"
-msgstr ""
+msgstr "संचित इनपà¥à¤Ÿ का पà¥à¤°à¤¯à¥‹à¤— करें"
#: core/os/input_event.cpp editor/project_settings_editor.cpp
#: servers/audio_server.cpp
msgid "Device"
-msgstr ""
+msgstr "उपकरण"
#: core/os/input_event.cpp
+#, fuzzy
msgid "Alt"
-msgstr ""
+msgstr "ऑलà¥à¤Ÿ"
#: core/os/input_event.cpp
msgid "Shift"
-msgstr ""
+msgstr "शिफà¥à¤Ÿ"
#: core/os/input_event.cpp
-#, fuzzy
msgid "Control"
-msgstr "वरà¥à¤œà¤¨ कंटà¥à¤°à¥‹à¤²"
+msgstr "कंटà¥à¤°à¥‹à¤²"
#: core/os/input_event.cpp
msgid "Meta"
-msgstr ""
+msgstr "मेटा"
#: core/os/input_event.cpp
-#, fuzzy
msgid "Command"
-msgstr "समà¥à¤¦à¤¾à¤¯"
+msgstr "कमांड"
#: core/os/input_event.cpp
#, fuzzy
msgid "Physical"
-msgstr "फिजिकà¥à¤¸ फà¥à¤°à¥‡à¤® %"
+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 "पà¥à¤°à¥€à¤¸à¥‡à¤Ÿ"
#: core/os/input_event.cpp
-#, fuzzy
msgid "Scancode"
-msgstr "सà¥à¤°à¥‹à¤¤à¤¸à¥à¤•ैन कीजिये"
+msgstr "सà¥à¤•ैनकोड"
#: core/os/input_event.cpp
msgid "Physical Scancode"
-msgstr ""
+msgstr "भौतिक सà¥à¤•ैनकोड"
#: core/os/input_event.cpp
msgid "Unicode"
-msgstr ""
+msgstr "यूनिकोड"
#: core/os/input_event.cpp
msgid "Echo"
-msgstr ""
+msgstr "इको"
#: core/os/input_event.cpp scene/gui/base_button.cpp
msgid "Button Mask"
-msgstr ""
+msgstr "बटन मासà¥à¤•"
#: core/os/input_event.cpp scene/2d/node_2d.cpp scene/gui/control.cpp
-#, fuzzy
msgid "Global Position"
-msgstr "कोनà¥à¤¸à¥à¤Ÿà¤¨à¥à¤Ÿ"
+msgstr "वैशà¥à¤µà¤¿à¤• सà¥à¤¥à¤¿à¤¤à¤¿"
#: core/os/input_event.cpp
msgid "Factor"
-msgstr ""
+msgstr "फैकà¥à¤Ÿà¤°"
#: core/os/input_event.cpp
msgid "Button Index"
-msgstr ""
+msgstr "बटन अनà¥à¤•à¥à¤°à¤®à¤£à¤¿à¤•ा"
#: core/os/input_event.cpp
msgid "Doubleclick"
-msgstr ""
+msgstr "डबलकà¥à¤²à¤¿à¤•"
#: core/os/input_event.cpp
msgid "Tilt"
-msgstr ""
+msgstr "टिलà¥à¤Ÿ"
#: core/os/input_event.cpp
-#, fuzzy
msgid "Pressure"
-msgstr "पà¥à¤°à¥€à¤¸à¥‡à¤Ÿ"
+msgstr "पà¥à¤°à¥‡à¤¶à¤°"
#: core/os/input_event.cpp
msgid "Pen Inverted"
-msgstr ""
+msgstr "पेन उलà¥à¤Ÿà¤¾"
#: core/os/input_event.cpp
+#, fuzzy
msgid "Relative"
-msgstr ""
+msgstr "रिशà¥à¤¤à¥‡à¤¦à¤¾à¤°"
#: 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
#: scene/animation/animation_player.cpp scene/resources/environment.cpp
#: scene/resources/particles_material.cpp
msgid "Speed"
-msgstr ""
+msgstr "सà¥à¤ªà¥€à¤¡"
#: core/os/input_event.cpp editor/project_settings_editor.cpp
#: scene/3d/sprite_3d.cpp
msgid "Axis"
-msgstr ""
+msgstr "अकà¥à¤·"
#: core/os/input_event.cpp
-#, fuzzy
msgid "Axis Value"
-msgstr "(मूलà¥à¤¯)"
+msgstr "à¤à¤•à¥à¤¸à¤¿à¤¸ वैलà¥à¤¯à¥‚"
#: core/os/input_event.cpp modules/visual_script/visual_script_func_nodes.cpp
msgid "Index"
-msgstr ""
+msgstr "इंडेकà¥à¤¸"
#: core/os/input_event.cpp editor/project_settings_editor.cpp
#: modules/visual_script/visual_script_nodes.cpp
@@ -503,60 +499,55 @@ msgstr "कारà¥à¤¯"
#: core/os/input_event.cpp scene/resources/environment.cpp
#: scene/resources/material.cpp
msgid "Strength"
-msgstr ""
+msgstr "शकà¥à¤¤à¤¿"
#: core/os/input_event.cpp
msgid "Delta"
-msgstr ""
+msgstr "डेलà¥à¤Ÿà¤¾"
#: core/os/input_event.cpp
-#, fuzzy
msgid "Channel"
-msgstr "बदली"
+msgstr "चैनल"
#: core/os/input_event.cpp main/main.cpp
-#, fuzzy
msgid "Message"
-msgstr "समà¥à¤¦à¤¾à¤¯"
+msgstr "मैसेज"
#: core/os/input_event.cpp
msgid "Pitch"
-msgstr ""
+msgstr "पिच"
#: core/os/input_event.cpp scene/2d/cpu_particles_2d.cpp
#: 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 "वेग"
#: core/os/input_event.cpp
msgid "Instrument"
-msgstr ""
+msgstr "साधन"
#: core/os/input_event.cpp
-#, fuzzy
msgid "Controller Number"
-msgstr "लाइन कà¥à¤°.:"
+msgstr "नियंतà¥à¤°à¤• संखà¥à¤¯à¤¾"
#: core/os/input_event.cpp
msgid "Controller Value"
-msgstr ""
+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 "कारà¥à¤¯"
+msgstr "अनà¥à¤ªà¥à¤°à¤¯à¥‹à¤—"
#: core/project_settings.cpp main/main.cpp
msgid "Config"
-msgstr ""
+msgstr "कॉनà¥à¤«à¤¼à¤¿à¤—"
#: core/project_settings.cpp
-#, fuzzy
msgid "Project Settings Override"
-msgstr "पà¥à¤°à¥‹à¤œà¥‡à¤•à¥à¤Ÿ सेटिंग ..."
+msgstr "पà¥à¤°à¥‹à¤œà¥‡à¤•à¥à¤Ÿ सेटिंगà¥à¤¸ ओवरराइड"
#: core/project_settings.cpp core/resource.cpp
#: editor/animation_track_editor.cpp editor/editor_autoload_settings.cpp
@@ -582,47 +573,44 @@ msgstr "विवरण"
#: main/main.cpp platform/android/export/export_plugin.cpp
#: platform/javascript/export/export.cpp
msgid "Run"
-msgstr ""
+msgstr "रन"
#: core/project_settings.cpp editor/editor_node.cpp
#: editor/run_settings_dialog.cpp main/main.cpp
msgid "Main Scene"
-msgstr ""
+msgstr "मà¥à¤–à¥à¤¯ दृशà¥à¤¯"
#: core/project_settings.cpp
-#, fuzzy
msgid "Disable stdout"
msgstr "बंद कर दिया गया है"
#: core/project_settings.cpp
-#, fuzzy
msgid "Disable stderr"
msgstr "बंद कर दिया गया है"
#: core/project_settings.cpp
msgid "Use Hidden Project Data Directory"
-msgstr ""
+msgstr "छिपी हà¥à¤ˆ पà¥à¤°à¥‹à¤œà¥‡à¤•à¥à¤Ÿ डेटा निरà¥à¤¦à¥‡à¤¶à¤¿à¤•ा का उपयोग करें"
#: core/project_settings.cpp
msgid "Use Custom User Dir"
-msgstr ""
+msgstr "कसà¥à¤Ÿà¤® उपयोगकरà¥à¤¤à¤¾ डायरेकà¥à¤Ÿà¤°à¥€ का उपयोग करें"
#: core/project_settings.cpp
msgid "Custom User Dir Name"
-msgstr ""
+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
@@ -631,19 +619,19 @@ msgstr ""
#: scene/resources/font.cpp scene/resources/navigation_mesh.cpp
#: scene/resources/primitive_meshes.cpp scene/resources/texture.cpp
msgid "Height"
-msgstr ""
+msgstr "ऊंचाई"
#: core/project_settings.cpp
msgid "Always On Top"
-msgstr ""
+msgstr "हमेशा शीरà¥à¤· पर"
#: core/project_settings.cpp
msgid "Test Width"
-msgstr ""
+msgstr "परीकà¥à¤·à¤£ चौड़ाई"
#: core/project_settings.cpp
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
@@ -651,9 +639,8 @@ msgid "Audio"
msgstr "ऑडियो"
#: core/project_settings.cpp
-#, fuzzy
msgid "Default Bus Layout"
-msgstr "पà¥à¤°à¤¾à¤¯à¤¿à¤• बस लेआउट लोड कीजिये."
+msgstr "डिफ़ॉलà¥à¤Ÿ बस लेआउट"
#: core/project_settings.cpp editor/editor_export.cpp
#: editor/editor_file_system.cpp editor/editor_node.cpp
@@ -664,93 +651,84 @@ msgstr "संपादक"
#: core/project_settings.cpp
msgid "Main Run Args"
-msgstr ""
+msgstr "मà¥à¤–à¥à¤¯ रन तरà¥à¤•"
#: core/project_settings.cpp
-#, fuzzy
msgid "Scene Naming"
-msgstr "दृशà¥à¤¯ पथ:"
+msgstr "दृशà¥à¤¯ नामकरण"
#: core/project_settings.cpp
msgid "Search In File Extensions"
-msgstr ""
+msgstr "फ़ाइल à¤à¤•à¥à¤¸à¤Ÿà¥‡à¤‚शन में खोजें"
#: core/project_settings.cpp
msgid "Script Templates Search Path"
-msgstr ""
+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
msgid "Input"
-msgstr ""
+msgstr "इनपà¥à¤Ÿ"
#: core/project_settings.cpp
msgid "UI Accept"
-msgstr ""
+msgstr "उपयोगकरà¥à¤¤à¤¾ हसà¥à¤¤à¤•à¥à¤·à¥‡à¤ª सà¥à¤µà¥€à¤•ार करें"
#: core/project_settings.cpp
-#, fuzzy
msgid "UI Select"
-msgstr "चà¥à¤¨à¥‡à¤‚"
+msgstr "उपयोगकरà¥à¤¤à¤¾ हसà¥à¤¤à¤•à¥à¤·à¥‡à¤ª का चयन करें"
#: core/project_settings.cpp
-#, fuzzy
msgid "UI Cancel"
-msgstr "रदà¥à¤¦ करें"
+msgstr "उपयोगकरà¥à¤¤à¤¾ हसà¥à¤¤à¤•à¥à¤·à¥‡à¤ª रदà¥à¤¦ करें"
#: core/project_settings.cpp
-#, fuzzy
msgid "UI Focus Next"
-msgstr "फ़ोकस पाथ"
+msgstr "उपयोगकरà¥à¤¤à¤¾ हसà¥à¤¤à¤•à¥à¤·à¥‡à¤ª फोकस अगला"
#: core/project_settings.cpp
-#, fuzzy
msgid "UI Focus Prev"
-msgstr "फ़ोकस पाथ"
+msgstr "उपयोगकरà¥à¤¤à¤¾ हसà¥à¤¤à¤•à¥à¤·à¥‡à¤ª फ़ोकस पिछला"
#: core/project_settings.cpp
msgid "UI Left"
-msgstr ""
+msgstr "उपयोगकरà¥à¤¤à¤¾ हसà¥à¤¤à¤•à¥à¤·à¥‡à¤ª छोड़ दिया गया"
#: core/project_settings.cpp
msgid "UI Right"
-msgstr ""
+msgstr "उपयोगकरà¥à¤¤à¤¾ हसà¥à¤¤à¤•à¥à¤·à¥‡à¤ª अधिकार"
#: core/project_settings.cpp
msgid "UI Up"
-msgstr ""
+msgstr "उपयोगकरà¥à¤¤à¤¾ हसà¥à¤¤à¤•à¥à¤·à¥‡à¤ª बढ़ा"
#: core/project_settings.cpp
-#, fuzzy
msgid "UI Down"
-msgstr "नीचे"
+msgstr "उपयोगकरà¥à¤¤à¤¾ हसà¥à¤¤à¤•à¥à¤·à¥‡à¤ª कम"
#: core/project_settings.cpp
-#, fuzzy
msgid "UI Page Up"
-msgstr "पृषà¥à¤ : "
+msgstr "उपयोगकरà¥à¤¤à¤¾ हसà¥à¤¤à¤•à¥à¤·à¥‡à¤ª पृषà¥à¤  अप"
#: core/project_settings.cpp
msgid "UI Page Down"
-msgstr ""
+msgstr "उपयोगकरà¥à¤¤à¤¾ हसà¥à¤¤à¤•à¥à¤·à¥‡à¤ª पृषà¥à¤  नीचे"
#: core/project_settings.cpp
msgid "UI Home"
-msgstr ""
+msgstr "उपयोगकरà¥à¤¤à¤¾ हसà¥à¤¤à¤•à¥à¤·à¥‡à¤ª घर"
#: core/project_settings.cpp
msgid "UI End"
-msgstr ""
+msgstr "उपयोगकरà¥à¤¤à¤¾ हसà¥à¤¤à¤•à¥à¤·à¥‡à¤ª समापà¥à¤¤ होता है"
#: core/project_settings.cpp main/main.cpp modules/bullet/register_types.cpp
#: modules/bullet/space_bullet.cpp scene/2d/physics_body_2d.cpp
@@ -760,9 +738,8 @@ msgstr ""
#: servers/physics_2d/physics_2d_server_wrap_mt.h
#: servers/physics_2d/space_2d_sw.cpp servers/physics_2d_server.cpp
#: servers/physics_server.cpp
-#, fuzzy
msgid "Physics"
-msgstr "फिजिकà¥à¤¸ फà¥à¤°à¥‡à¤® %"
+msgstr "फिजिकà¥à¤¸"
#: core/project_settings.cpp editor/editor_settings.cpp
#: editor/import/resource_importer_layered_texture.cpp
@@ -772,11 +749,11 @@ msgstr "फिजिकà¥à¤¸ फà¥à¤°à¥‡à¤® %"
#: scene/3d/physics_body.cpp scene/resources/world.cpp
#: servers/physics/space_sw.cpp servers/physics_server.cpp
msgid "3D"
-msgstr ""
+msgstr "3 डी"
#: core/project_settings.cpp
msgid "Smooth Trimesh Collision"
-msgstr ""
+msgstr "तà¥à¤°à¤¿à¤®à¥‡à¤¶ की टकà¥à¤•र"
#: core/project_settings.cpp drivers/gles2/rasterizer_canvas_base_gles2.cpp
#: drivers/gles2/rasterizer_scene_gles2.cpp
@@ -788,7 +765,7 @@ msgstr ""
#: scene/main/viewport.cpp servers/visual/visual_server_scene.cpp
#: servers/visual_server.cpp
msgid "Rendering"
-msgstr ""
+msgstr "रेंडरिंग"
#: core/project_settings.cpp drivers/gles2/rasterizer_storage_gles2.cpp
#: drivers/gles3/rasterizer_scene_gles3.cpp
@@ -798,18 +775,17 @@ msgstr ""
#: scene/resources/multimesh.cpp servers/visual/visual_server_scene.cpp
#: servers/visual_server.cpp
msgid "Quality"
-msgstr ""
+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 "फिलà¥à¤Ÿà¤°:"
+msgstr "फ़िलà¥à¤Ÿà¤°à¥à¤¸"
#: core/project_settings.cpp scene/main/viewport.cpp
msgid "Sharpen Intensity"
-msgstr ""
+msgstr "शॉरà¥à¤ª गहनता"
#: core/project_settings.cpp editor/editor_export.cpp editor/editor_node.cpp
#: editor/editor_settings.cpp editor/plugins/script_editor_plugin.cpp
@@ -825,86 +801,81 @@ msgstr "डीबग करें"
#: core/project_settings.cpp main/main.cpp modules/gdscript/gdscript.cpp
#: modules/visual_script/visual_script.cpp scene/resources/dynamic_font.cpp
-#, fuzzy
msgid "Settings"
-msgstr "à¤à¤¡à¥€à¤Ÿà¤° सेटिनà¥à¤—स..."
+msgstr "सेटिंगà¥à¤¸"
#: core/project_settings.cpp editor/script_editor_debugger.cpp main/main.cpp
#: modules/mono/mono_gd/gd_mono.cpp
msgid "Profiler"
-msgstr ""
+msgstr "पà¥à¤°à¥‹à¤«à¤¾à¤‡à¤²à¤°"
#: core/project_settings.cpp
-#, fuzzy
msgid "Max Functions"
-msgstr "कारà¥à¤¯à¥‹à¤‚:"
+msgstr "मैकà¥à¤¸ फ़ंकà¥à¤¶à¤¨"
#: core/project_settings.cpp scene/3d/vehicle_body.cpp
-#, fuzzy
msgid "Compression"
-msgstr "सदसà¥à¤¯à¤¤à¤¾ बनाà¤à¤‚"
+msgstr "कंपà¥à¤°à¥‡à¤¶à¤¨"
#: core/project_settings.cpp
msgid "Formats"
-msgstr ""
+msgstr "फारà¥à¤®à¥‡à¤Ÿ"
#: core/project_settings.cpp
msgid "Zstd"
-msgstr ""
+msgstr "Zstd"
#: core/project_settings.cpp
msgid "Long Distance Matching"
-msgstr ""
+msgstr "लंबी दूरी का मिलान"
#: core/project_settings.cpp
msgid "Compression Level"
-msgstr ""
+msgstr "संपीड़न सà¥à¤¤à¤°"
#: core/project_settings.cpp
msgid "Window Log Size"
-msgstr ""
+msgstr "विंडो लॉग आकार"
#: 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 "à¤à¤‚डà¥à¤°à¥‰à¤¯à¤¡"
#: core/project_settings.cpp
msgid "Modules"
-msgstr ""
+msgstr "मॉडà¥à¤¯à¥‚ल"
#: core/register_core_types.cpp
msgid "TCP"
-msgstr ""
+msgstr "टीसीपी"
#: core/register_core_types.cpp
-#, fuzzy
msgid "Connect Timeout Seconds"
-msgstr "Node से कनेकà¥à¤Ÿ करें:"
+msgstr "कनेकà¥à¤Ÿ टाइमआउट सेकंड"
#: core/register_core_types.cpp
msgid "Packet Peer Stream"
-msgstr ""
+msgstr "पैकेट पीयर सà¥à¤Ÿà¥à¤°à¥€à¤®"
#: core/register_core_types.cpp
msgid "Max Buffer (Power of 2)"
-msgstr ""
+msgstr "मैकà¥à¤¸ बफर (2 की शकà¥à¤¤à¤¿)"
#: core/register_core_types.cpp editor/editor_settings.cpp main/main.cpp
msgid "SSL"
-msgstr ""
+msgstr "à¤à¤¸à¤à¤¸à¤à¤²"
#: core/register_core_types.cpp main/main.cpp
-#, fuzzy
msgid "Certificates"
-msgstr "विशेषता"
+msgstr "पà¥à¤°à¤®à¤¾à¤£à¤ªà¤¤à¥à¤°"
#: core/resource.cpp editor/dependency_editor.cpp
#: editor/editor_resource_picker.cpp
@@ -913,9 +884,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
@@ -925,21 +895,20 @@ msgid "Path"
msgstr "पथ"
#: core/script_language.cpp
-#, fuzzy
msgid "Source Code"
-msgstr "संसाधन"
+msgstr "सà¥à¤°à¥‹à¤¤ कोड"
#: core/translation.cpp editor/project_settings_editor.cpp
msgid "Locale"
-msgstr ""
+msgstr "लोकेल"
#: core/translation.cpp
msgid "Test"
-msgstr ""
+msgstr "टेसà¥à¤Ÿ"
#: core/translation.cpp scene/resources/font.cpp
msgid "Fallback"
-msgstr ""
+msgstr "फ़ॉलबैक"
#: core/ustring.cpp scene/resources/segment_shape_2d.cpp
msgid "B"
@@ -975,17 +944,17 @@ msgstr "EiB"
#: drivers/gles3/rasterizer_scene_gles3.cpp
#: drivers/gles3/rasterizer_storage_gles3.cpp modules/gltf/gltf_state.cpp
msgid "Buffers"
-msgstr ""
+msgstr "बफ़रà¥à¤¸"
#: drivers/gles2/rasterizer_canvas_base_gles2.cpp
#: drivers/gles3/rasterizer_canvas_base_gles3.cpp
msgid "Canvas Polygon Buffer Size (KB)"
-msgstr ""
+msgstr "कैनवास बहà¥à¤­à¥à¤œ बफर आकार (KB)"
#: drivers/gles2/rasterizer_canvas_base_gles2.cpp
#: drivers/gles3/rasterizer_canvas_base_gles3.cpp
msgid "Canvas Polygon Index Buffer Size (KB)"
-msgstr ""
+msgstr "कैनवास बहà¥à¤­à¥à¤œ सूचकांक बफर आकार (KB)"
#: drivers/gles2/rasterizer_canvas_base_gles2.cpp
#: drivers/gles3/rasterizer_canvas_base_gles3.cpp editor/editor_settings.cpp
@@ -997,28 +966,27 @@ msgstr ""
#: servers/physics_2d/space_2d_sw.cpp servers/physics_2d_server.cpp
#: servers/visual_server.cpp
msgid "2D"
-msgstr ""
+msgstr "2डी"
#: drivers/gles2/rasterizer_canvas_base_gles2.cpp
#: drivers/gles3/rasterizer_canvas_base_gles3.cpp
-#, fuzzy
msgid "Snapping"
-msgstr "आकसà¥à¤®à¤¿à¤•:"
+msgstr "सà¥à¤¨à¥ˆà¤ªà¤¿à¤‚ग"
#: drivers/gles2/rasterizer_canvas_base_gles2.cpp
#: drivers/gles3/rasterizer_canvas_base_gles3.cpp
msgid "Use GPU Pixel Snap"
-msgstr ""
+msgstr "GPU Pixel Snap का उपयोग करें"
#: drivers/gles2/rasterizer_scene_gles2.cpp
#: drivers/gles3/rasterizer_scene_gles3.cpp
msgid "Immediate Buffer Size (KB)"
-msgstr ""
+msgstr "ततà¥à¤•ाल बफर आकार (KB)"
#: drivers/gles2/rasterizer_storage_gles2.cpp
#: drivers/gles3/rasterizer_storage_gles3.cpp
msgid "Lightmapping"
-msgstr ""
+msgstr "लाइटमैपिंग"
#: drivers/gles2/rasterizer_storage_gles2.cpp
#: drivers/gles3/rasterizer_storage_gles3.cpp
@@ -13001,9 +12969,10 @@ msgstr "आकसà¥à¤®à¤¿à¤•:"
#: scene/2d/path_2d.cpp scene/2d/polygon_2d.cpp scene/2d/sprite.cpp
#: scene/3d/cpu_particles.cpp scene/3d/label_3d.cpp scene/3d/path.cpp
#: scene/3d/physics_body.cpp scene/3d/soft_body.cpp scene/3d/sprite_3d.cpp
-#: 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
+#: scene/3d/visual_instance.cpp 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
msgid "Offset"
msgstr ""
@@ -14399,12 +14368,11 @@ msgstr ""
#: editor/project_manager.cpp
msgid ""
-"Couldn't load project.godot in project path (error %d). It may be missing or "
-"corrupted."
+"Couldn't load project at '%s' (error %d). It may be missing or corrupted."
msgstr ""
#: editor/project_manager.cpp
-msgid "Couldn't edit project.godot in project path."
+msgid "Couldn't save project at '%s' (error %d)."
msgstr ""
#: editor/project_manager.cpp
@@ -23488,6 +23456,15 @@ msgstr "पà¥à¤°à¤¤à¤¿à¤®à¤¾"
msgid "AABB"
msgstr ""
+#: scene/3d/visual_instance.cpp
+#, fuzzy
+msgid "Sorting"
+msgstr "आयात:"
+
+#: scene/3d/visual_instance.cpp
+msgid "Use AABB Center"
+msgstr ""
+
#: scene/3d/visual_instance.cpp scene/resources/navigation_mesh.cpp
msgid "Geometry"
msgstr ""
diff --git a/editor/translations/hr.po b/editor/translations/hr.po
index 21a20978a6..85fcb184f3 100644
--- a/editor/translations/hr.po
+++ b/editor/translations/hr.po
@@ -12654,9 +12654,10 @@ msgstr "Opcije Klase"
#: scene/2d/path_2d.cpp scene/2d/polygon_2d.cpp scene/2d/sprite.cpp
#: scene/3d/cpu_particles.cpp scene/3d/label_3d.cpp scene/3d/path.cpp
#: scene/3d/physics_body.cpp scene/3d/soft_body.cpp scene/3d/sprite_3d.cpp
-#: 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
+#: scene/3d/visual_instance.cpp 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
msgid "Offset"
msgstr ""
@@ -14032,12 +14033,11 @@ msgstr ""
#: editor/project_manager.cpp
msgid ""
-"Couldn't load project.godot in project path (error %d). It may be missing or "
-"corrupted."
+"Couldn't load project at '%s' (error %d). It may be missing or corrupted."
msgstr ""
#: editor/project_manager.cpp
-msgid "Couldn't edit project.godot in project path."
+msgid "Couldn't save project at '%s' (error %d)."
msgstr ""
#: editor/project_manager.cpp
@@ -22925,6 +22925,15 @@ msgstr "Greška!"
msgid "AABB"
msgstr ""
+#: scene/3d/visual_instance.cpp
+#, fuzzy
+msgid "Sorting"
+msgstr "Zalijepi Animaciju"
+
+#: scene/3d/visual_instance.cpp
+msgid "Use AABB Center"
+msgstr ""
+
#: scene/3d/visual_instance.cpp scene/resources/navigation_mesh.cpp
msgid "Geometry"
msgstr ""
diff --git a/editor/translations/hu.po b/editor/translations/hu.po
index 996249e619..b8bab10568 100644
--- a/editor/translations/hu.po
+++ b/editor/translations/hu.po
@@ -13160,9 +13160,10 @@ msgstr "Illesztési beállítások"
#: scene/2d/path_2d.cpp scene/2d/polygon_2d.cpp scene/2d/sprite.cpp
#: scene/3d/cpu_particles.cpp scene/3d/label_3d.cpp scene/3d/path.cpp
#: scene/3d/physics_body.cpp scene/3d/soft_body.cpp scene/3d/sprite_3d.cpp
-#: 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
+#: scene/3d/visual_instance.cpp 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 "Rács Eltolás:"
@@ -14544,13 +14545,13 @@ msgstr ""
#: editor/project_manager.cpp
msgid ""
-"Couldn't load project.godot in project path (error %d). It may be missing or "
-"corrupted."
+"Couldn't load project at '%s' (error %d). It may be missing or corrupted."
msgstr ""
#: editor/project_manager.cpp
-msgid "Couldn't edit project.godot in project path."
-msgstr ""
+#, fuzzy
+msgid "Couldn't save project at '%s' (error %d)."
+msgstr "A projekt nem nyitható meg a(z) %s helyen."
#: editor/project_manager.cpp
msgid "Couldn't create project.godot in project path."
@@ -23781,6 +23782,15 @@ msgstr "Hiba!"
msgid "AABB"
msgstr ""
+#: scene/3d/visual_instance.cpp
+#, fuzzy
+msgid "Sorting"
+msgstr "Rendezés"
+
+#: scene/3d/visual_instance.cpp
+msgid "Use AABB Center"
+msgstr ""
+
#: scene/3d/visual_instance.cpp scene/resources/navigation_mesh.cpp
#, fuzzy
msgid "Geometry"
diff --git a/editor/translations/id.po b/editor/translations/id.po
index ee7e21c0c0..89153d88d3 100644
--- a/editor/translations/id.po
+++ b/editor/translations/id.po
@@ -13105,9 +13105,10 @@ msgstr "Opsi-opsi Snap"
#: scene/2d/path_2d.cpp scene/2d/polygon_2d.cpp scene/2d/sprite.cpp
#: scene/3d/cpu_particles.cpp scene/3d/label_3d.cpp scene/3d/path.cpp
#: scene/3d/physics_body.cpp scene/3d/soft_body.cpp scene/3d/sprite_3d.cpp
-#: 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
+#: scene/3d/visual_instance.cpp 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 "Pengimbangan:"
@@ -14569,16 +14570,17 @@ msgid "Invalid project path (changed anything?)."
msgstr "Lokasi proyek tidak valid (mengubah sesuatu?)."
#: editor/project_manager.cpp
+#, fuzzy
msgid ""
-"Couldn't load project.godot in project path (error %d). It may be missing or "
-"corrupted."
+"Couldn't load project at '%s' (error %d). It may be missing or corrupted."
msgstr ""
"Tidak dapat memuat project.godot dalam lokasi proyek (galat %d). Mungkin "
"berkas itu tidak ada atau rusak."
#: editor/project_manager.cpp
-msgid "Couldn't edit project.godot in project path."
-msgstr "Tidak dapat menyunting project.godot dalam lokasi proyek."
+#, fuzzy
+msgid "Couldn't save project at '%s' (error %d)."
+msgstr "Tidak dapat membuka proyek di '%s'."
#: editor/project_manager.cpp
msgid "Couldn't create project.godot in project path."
@@ -23964,6 +23966,16 @@ msgstr "Galat"
msgid "AABB"
msgstr ""
+#: scene/3d/visual_instance.cpp
+#, fuzzy
+msgid "Sorting"
+msgstr "Urutkan"
+
+#: scene/3d/visual_instance.cpp
+#, fuzzy
+msgid "Use AABB Center"
+msgstr "Gunakan Sebagai Kemudi"
+
#: scene/3d/visual_instance.cpp scene/resources/navigation_mesh.cpp
#, fuzzy
msgid "Geometry"
diff --git a/editor/translations/ig.po b/editor/translations/ig.po
index 8d96de35f3..e0c1a85c99 100644
--- a/editor/translations/ig.po
+++ b/editor/translations/ig.po
@@ -12357,9 +12357,10 @@ msgstr ""
#: scene/2d/path_2d.cpp scene/2d/polygon_2d.cpp scene/2d/sprite.cpp
#: scene/3d/cpu_particles.cpp scene/3d/label_3d.cpp scene/3d/path.cpp
#: scene/3d/physics_body.cpp scene/3d/soft_body.cpp scene/3d/sprite_3d.cpp
-#: 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
+#: scene/3d/visual_instance.cpp 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
msgid "Offset"
msgstr ""
@@ -13688,12 +13689,11 @@ msgstr ""
#: editor/project_manager.cpp
msgid ""
-"Couldn't load project.godot in project path (error %d). It may be missing or "
-"corrupted."
+"Couldn't load project at '%s' (error %d). It may be missing or corrupted."
msgstr ""
#: editor/project_manager.cpp
-msgid "Couldn't edit project.godot in project path."
+msgid "Couldn't save project at '%s' (error %d)."
msgstr ""
#: editor/project_manager.cpp
@@ -22185,6 +22185,14 @@ msgstr ""
msgid "AABB"
msgstr ""
+#: scene/3d/visual_instance.cpp
+msgid "Sorting"
+msgstr ""
+
+#: scene/3d/visual_instance.cpp
+msgid "Use AABB Center"
+msgstr ""
+
#: scene/3d/visual_instance.cpp scene/resources/navigation_mesh.cpp
msgid "Geometry"
msgstr ""
diff --git a/editor/translations/is.po b/editor/translations/is.po
index 8514155c68..7551598f22 100644
--- a/editor/translations/is.po
+++ b/editor/translations/is.po
@@ -12635,9 +12635,10 @@ msgstr "Val á kvarða"
#: scene/2d/path_2d.cpp scene/2d/polygon_2d.cpp scene/2d/sprite.cpp
#: scene/3d/cpu_particles.cpp scene/3d/label_3d.cpp scene/3d/path.cpp
#: scene/3d/physics_body.cpp scene/3d/soft_body.cpp scene/3d/sprite_3d.cpp
-#: 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
+#: scene/3d/visual_instance.cpp 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
msgid "Offset"
msgstr ""
@@ -14004,12 +14005,11 @@ msgstr ""
#: editor/project_manager.cpp
msgid ""
-"Couldn't load project.godot in project path (error %d). It may be missing or "
-"corrupted."
+"Couldn't load project at '%s' (error %d). It may be missing or corrupted."
msgstr ""
#: editor/project_manager.cpp
-msgid "Couldn't edit project.godot in project path."
+msgid "Couldn't save project at '%s' (error %d)."
msgstr ""
#: editor/project_manager.cpp
@@ -22783,6 +22783,15 @@ msgstr ""
msgid "AABB"
msgstr ""
+#: scene/3d/visual_instance.cpp
+#, fuzzy
+msgid "Sorting"
+msgstr "Stillið breyting á:"
+
+#: scene/3d/visual_instance.cpp
+msgid "Use AABB Center"
+msgstr ""
+
#: scene/3d/visual_instance.cpp scene/resources/navigation_mesh.cpp
msgid "Geometry"
msgstr ""
diff --git a/editor/translations/it.po b/editor/translations/it.po
index 027f4609f8..f1ff871a69 100644
--- a/editor/translations/it.po
+++ b/editor/translations/it.po
@@ -61,7 +61,7 @@
# Daniele Basso <tiziodcaio@gmail.com>, 2021.
# Riteo Siuga <riteo@posteo.net>, 2021, 2022.
# Luigi <luibass92@live.it>, 2021.
-# Micky <micheledevita2@gmail.com>, 2021.
+# Micky <micheledevita2@gmail.com>, 2021, 2022.
# Fabio Plos <altre0cose@gmail.com>, 2021.
# Theraloss <danilo.polani@gmail.com>, 2021.
# Pietro Grungo <pietro.grungo@libero.it>, 2021.
@@ -73,13 +73,17 @@
# ale piccia <picciatialessio2@gmail.com>, 2022.
# Simone Starace <simone.starace93@gmail.com>, 2022.
# Daniele Giunta <danielegiunta2007@gmail.com>, 2022.
+# Damiano Guida <damiano.guida22@gmail.com>, 2022.
+# Silvia Scaglione <sissisoad@gmail.com>, 2022.
+# Cosimo Davide Viggiano <cosimod089@gmail.com>, 2022.
+# Francesco Cammarata <francescocammarata.fr@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-09-27 21:37+0000\n"
-"Last-Translator: Daniele Giunta <danielegiunta2007@gmail.com>\n"
+"PO-Revision-Date: 2022-11-22 20:37+0000\n"
+"Last-Translator: Francesco Cammarata <francescocammarata.fr@gmail.com>\n"
"Language-Team: Italian <https://hosted.weblate.org/projects/godot-engine/"
"godot/it/>\n"
"Language: it\n"
@@ -87,7 +91,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.14.1\n"
+"X-Generator: Weblate 4.15-dev\n"
#: core/bind/core_bind.cpp main/main.cpp
msgid "Tablet Driver"
@@ -213,7 +217,7 @@ msgstr "Target FPS"
#: core/bind/core_bind.cpp
msgid "Time Scale"
-msgstr "Scala Temporale"
+msgstr "Scala temporale"
#: core/bind/core_bind.cpp main/main.cpp
msgid "Physics Jitter Fix"
@@ -456,7 +460,6 @@ msgid "Command"
msgstr "Comando"
#: core/os/input_event.cpp
-#, fuzzy
msgid "Physical"
msgstr "Fisico"
@@ -468,14 +471,13 @@ msgstr "Premuto"
#: core/os/input_event.cpp
msgid "Scancode"
-msgstr "Codice di Scansione"
+msgstr "Codice di scansione"
#: core/os/input_event.cpp
msgid "Physical Scancode"
msgstr "Codice di Scansione Fisico"
#: core/os/input_event.cpp
-#, fuzzy
msgid "Unicode"
msgstr "Unicode"
@@ -1020,7 +1022,7 @@ msgstr "2D"
#: drivers/gles2/rasterizer_canvas_base_gles2.cpp
#: drivers/gles3/rasterizer_canvas_base_gles3.cpp
msgid "Snapping"
-msgstr "Ancoraggio"
+msgstr "Scatto"
#: drivers/gles2/rasterizer_canvas_base_gles2.cpp
#: drivers/gles3/rasterizer_canvas_base_gles3.cpp
@@ -2802,9 +2804,8 @@ msgid "Choose"
msgstr "Scegli"
#: editor/editor_export.cpp
-#, fuzzy
msgid "Project export for platform:"
-msgstr "Esportazione del progetto per la piattaforma:"
+msgstr "Esportazione del progetto per piattaforma:"
#: editor/editor_export.cpp
msgid "Completed with warnings."
@@ -2953,7 +2954,6 @@ msgid "ETC2"
msgstr "ETC2"
#: editor/editor_export.cpp
-#, fuzzy
msgid "No BPTC Fallbacks"
msgstr "Nessun fallback per BPTC"
@@ -2970,7 +2970,6 @@ msgid "Custom release template not found."
msgstr "Modello di rilascio personalizzato non trovato."
#: editor/editor_export.cpp
-#, fuzzy
msgid "Prepare Template"
msgstr "Prepara Modello"
@@ -2988,9 +2987,8 @@ msgstr "Copiatura del modello di esportazione fallita."
#: editor/editor_export.cpp platform/windows/export/export.cpp
#: platform/x11/export/export.cpp
-#, fuzzy
msgid "PCK Embedding"
-msgstr "PCK Incorporazione"
+msgstr "Incorporazione PCK"
#: editor/editor_export.cpp
msgid "On 32-bit exports the embedded PCK cannot be bigger than 4 GiB."
@@ -3167,7 +3165,7 @@ msgstr "Rendi attuale"
#: editor/plugins/theme_editor_plugin.cpp editor/project_manager.cpp
#: modules/fbx/editor_scene_importer_fbx.cpp
msgid "Import"
-msgstr "Importa"
+msgstr "Importare"
#: editor/editor_feature_profile.cpp editor/project_export.cpp
#: platform/android/export/export.cpp platform/android/export/export_plugin.cpp
@@ -3289,7 +3287,7 @@ msgstr "Accedi"
#: editor/editor_file_dialog.cpp editor/editor_settings.cpp
msgid "Display Mode"
-msgstr "Modalità Visualizzazione"
+msgstr "Modalità di visualizzazione"
#: editor/editor_file_dialog.cpp
#: editor/import/resource_importer_layered_texture.cpp
@@ -5304,11 +5302,11 @@ msgstr "Lingua dell'Editor"
#: editor/editor_settings.cpp
msgid "Display Scale"
-msgstr "Dimensione Display"
+msgstr "Scala di visualizzazione"
#: editor/editor_settings.cpp
msgid "Custom Display Scale"
-msgstr "Dimensione Display Personalizzata"
+msgstr "Scala di visualizzazione personalizzata"
#: editor/editor_settings.cpp
msgid "Main Font Size"
@@ -5554,14 +5552,12 @@ 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 Drag And Drop"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Stay In Script Editor On Node Selected"
-msgstr "Rimani nell'Editor degli Script quando un Nodo è selezionato"
+msgstr "Rimani nell'editor degli script quando un nodo è selezionato"
#: editor/editor_settings.cpp
msgid "Appearance"
@@ -5601,7 +5597,7 @@ msgstr "Mostra Linee Guida della Lunghezza della Linea"
#: editor/editor_settings.cpp
msgid "Line Length Guideline Soft Column"
-msgstr ""
+msgstr "Margine suggerito per lunghezza riga"
#: editor/editor_settings.cpp
msgid "Line Length Guideline Hard Column"
@@ -5719,7 +5715,6 @@ msgid "Help Font Size"
msgstr "Dimensione Carattere della Guida"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Help Source Font Size"
msgstr "Dimensione dei caratteri della sezione d'assistenza codice sorgente"
@@ -5829,7 +5824,6 @@ msgid "Lightmap Baking Number Of CPU Threads"
msgstr "Numero di Threads CPU del Baking di Lightmap"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Navigation Scheme"
msgstr "Schema di Navigazione"
@@ -5858,9 +5852,8 @@ msgid "Orbit Modifier"
msgstr "Modificatore Orbita"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Pan Modifier"
-msgstr "Modificatore di Pan"
+msgstr "Modificatore Pan"
#: editor/editor_settings.cpp
msgid "Zoom Modifier"
@@ -5871,9 +5864,8 @@ msgid "Warped Mouse Panning"
msgstr "Panning Continuo Del Mouse"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Navigation Feel"
-msgstr "Sensazione Navigazione"
+msgstr "Sensazione della Navigazione"
#: editor/editor_settings.cpp
msgid "Orbit Sensitivity"
@@ -5929,7 +5921,7 @@ msgstr "Colore Guide"
#: editor/editor_settings.cpp
msgid "Smart Snapping Line Color"
-msgstr "Colore Linea Agganciamento Intelligente"
+msgstr "Colore della linea dello scatto intelligente"
#: editor/editor_settings.cpp
msgid "Bone Width"
@@ -5948,9 +5940,8 @@ msgid "Bone Selected Color"
msgstr "Colore Osso Selezionato"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Bone IK Color"
-msgstr "Colore IK Osso"
+msgstr "Colore Osso IK"
#: editor/editor_settings.cpp
msgid "Bone Outline Color"
@@ -5986,7 +5977,6 @@ msgid "Poly Editor"
msgstr "Editor Poly"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Point Grab Radius"
msgstr "Raggio Afferramento Punti"
@@ -6099,9 +6089,8 @@ msgid "Keyword Color"
msgstr "Colore Parola Chiave"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Control Flow Keyword Color"
-msgstr "Colore Parola Chiave Controllo Flusso"
+msgstr "Colore della Parola Chiave del Controllo Flusso"
#: editor/editor_settings.cpp
msgid "Base Type Color"
@@ -6973,7 +6962,7 @@ msgstr "Filtro"
#: editor/import/resource_importer_layered_texture.cpp
#: editor/import/resource_importer_texture.cpp
msgid "Mipmaps"
-msgstr "Mipmaps"
+msgstr "Mappe errate"
#: editor/import/resource_importer_layered_texture.cpp
#: editor/import/resource_importer_texture.cpp
@@ -7079,7 +7068,7 @@ msgstr "Nome Root"
#: editor/import/resource_importer_scene.cpp
msgid "Root Scale"
-msgstr "Scala Root"
+msgstr "Scala di radice"
#: editor/import/resource_importer_scene.cpp
msgid "Custom Script"
@@ -8010,7 +7999,7 @@ msgstr "Posizione animazione (in secondi)."
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Scale animation playback globally for the node."
-msgstr "Scala playback dell'animazione globalmente per il nodo."
+msgstr "Scala la riproduzione dell'animazione globalmente per il nodo."
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Animation Tools"
@@ -8214,7 +8203,6 @@ msgid "Set the end animation. This is useful for sub-transitions."
msgstr "Assegna l'animazione finale. Utile per le sotto-transizioni."
#: editor/plugins/animation_state_machine_editor.cpp
-#, fuzzy
msgid "Transition:"
msgstr "Transizione:"
@@ -8328,12 +8316,13 @@ msgid "Blend4 Node"
msgstr "Nodo Blend4"
#: editor/plugins/animation_tree_player_editor_plugin.cpp
+#, fuzzy
msgid "TimeScale Node"
msgstr "Nodo TimeScale"
#: editor/plugins/animation_tree_player_editor_plugin.cpp
msgid "TimeSeek Node"
-msgstr "Nodo TimeScale"
+msgstr "Nodo TimeSeek"
#: editor/plugins/animation_tree_player_editor_plugin.cpp
msgid "Transition Node"
@@ -8465,7 +8454,7 @@ msgstr "Errore nel fare richiesta"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Idle"
-msgstr "Inattivo"
+msgstr "Inattività"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Install..."
@@ -8655,7 +8644,7 @@ msgstr "Anteprima"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Configure Snap"
-msgstr "Configura Agganciamento"
+msgstr "Configura scatto"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Grid Offset:"
@@ -8731,7 +8720,7 @@ msgstr "Sposta Ancora CanvasItem \"%s\""
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Scale Node2D \"%s\" to (%s, %s)"
-msgstr "Scala Node2D \"%s\" a (%s, %s)"
+msgstr "Ridimensiona Node2D \"%s\" a (%s, %s)"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Resize Control \"%s\" to (%d, %d)"
@@ -8739,11 +8728,11 @@ msgstr "Ridimensiona Control \"%s\" a (%d, %d)"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Scale %d CanvasItems"
-msgstr "Scala %d CanvasItem"
+msgstr "Ridimensiona %d CanvasItem"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Scale CanvasItem \"%s\" to (%s, %s)"
-msgstr "Scala CanvasItem \"%s\" a (%s, %s)"
+msgstr "Ridimensiona CanvasItem \"%s\" a (%s, %s)"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Move %d CanvasItems"
@@ -8960,7 +8949,7 @@ msgstr "Alt+Trascina: Muovi nodo selezionato."
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Alt+Drag: Scale selected node."
-msgstr "Alt+Trascina: Ridimensiona il nodo selezionato."
+msgstr "Alt+Trascinamento: Ridimensiona il nodo selezionato."
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "V: Set selected node's pivot position."
@@ -8994,7 +8983,7 @@ msgstr "Modalità scala"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Shift: Scale proportionally."
-msgstr "Shift: Ridimensiona proporzionalmente."
+msgstr "Maiusc: Ridimensiona proporzionalmente."
#: editor/plugins/canvas_item_editor_plugin.cpp
#: editor/plugins/spatial_editor_plugin.cpp
@@ -9019,7 +9008,7 @@ msgstr "Modalità Righello"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Toggle smart snapping."
-msgstr "Commuta l'agganciamento intelligente."
+msgstr "Commuta lo scatto intelligente."
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Use Smart Snap"
@@ -9035,7 +9024,7 @@ msgstr "Usa la griglia magnetica"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Snapping Options"
-msgstr "Opzioni Agganciamento"
+msgstr "Opzioni dello scatto"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Use Rotation Snap"
@@ -9043,19 +9032,19 @@ msgstr "Aggancia Rotazione"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Use Scale Snap"
-msgstr "Aggancia Ridimensionamento"
+msgstr "Scatta la scala"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Snap Relative"
-msgstr "Agganciamento Relativo"
+msgstr "Scatto relativo"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Use Pixel Snap"
-msgstr "Agganciamento su Pixel"
+msgstr "Scatta sui pixel"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Smart Snapping"
-msgstr "Agganciamento Intelligente"
+msgstr "Scatto intelligente"
#: editor/plugins/canvas_item_editor_plugin.cpp
#: editor/plugins/spatial_editor_plugin.cpp
@@ -9154,7 +9143,7 @@ msgstr "Mostra"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Show When Snapping"
-msgstr "Mostra Se Agganciamento"
+msgstr "Mostra durante lo scatto"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Hide"
@@ -9219,7 +9208,7 @@ msgstr "Maschera di rotazione per l'inserimento delle chiavi."
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Scale mask for inserting keys."
-msgstr "Maschera di scala per l'inserimento delle chiavi."
+msgstr "Scala maschera per l'inserimento delle chiavi."
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Insert keys (based on mask)."
@@ -9345,8 +9334,8 @@ msgid ""
"Drag & drop + Shift : Add node as sibling\n"
"Drag & drop + Alt : Change node type"
msgstr ""
-"Trascina & Rilascia + Shift : Aggiungi nodo come fratello\n"
-"Trascina & Rilascia + Alt : Cambia tipo del nodo"
+"Trascina e Rilascia + Shift : Aggiungi nodo come fratello\n"
+"Trascina e Rilascia + Alt : Cambia tipo del nodo"
#: editor/plugins/collision_polygon_editor_plugin.cpp
msgid "Create Polygon3D"
@@ -9442,7 +9431,7 @@ msgstr "Flat 0"
#: editor/plugins/curve_editor_plugin.cpp
msgid "Flat 1"
-msgstr "Flat 1"
+msgstr "Flat 1Flat 1"
#: editor/plugins/curve_editor_plugin.cpp editor/property_editor.cpp
msgid "Ease In"
@@ -9522,7 +9511,7 @@ msgstr "Scambia Punti di Riempimento del Gradiente"
#: editor/plugins/gradient_texture_2d_editor_plugin.cpp
msgid "Toggle Grid Snap"
-msgstr "Commuta Agganciamento Griglia"
+msgstr "Commuta scatto sulla griglia"
#: editor/plugins/item_list_editor_plugin.cpp editor/project_export.cpp
#: scene/3d/label_3d.cpp scene/gui/button.cpp scene/gui/dialogs.cpp
@@ -9540,7 +9529,6 @@ msgid "Icon"
msgstr "Icona"
#: editor/plugins/item_list_editor_plugin.cpp
-#, fuzzy
msgid "ID"
msgstr "ID"
@@ -9709,7 +9697,6 @@ msgstr ""
"collisioni."
#: editor/plugins/mesh_instance_editor_plugin.cpp
-#, fuzzy
msgid "Create Simplified Convex Collision Sibling"
msgstr "Crea Fratello di Collisione Convessa Semplificato"
@@ -9909,7 +9896,7 @@ msgstr "Inclinazione Casuale:"
#: editor/plugins/multimesh_editor_plugin.cpp
msgid "Random Scale:"
-msgstr "Scala Casuale:"
+msgstr "Scala casuale:"
#: editor/plugins/multimesh_editor_plugin.cpp
msgid "Populate"
@@ -10169,7 +10156,7 @@ msgstr ""
#: editor/plugins/polygon_2d_editor_plugin.cpp
msgid "Create Polygon & UV"
-msgstr "Crea Poligono & UV"
+msgstr "Crea Poligono e UV"
#: editor/plugins/polygon_2d_editor_plugin.cpp
msgid "Create Internal Vertex"
@@ -10265,7 +10252,7 @@ msgstr "Ruota poligono"
#: editor/plugins/polygon_2d_editor_plugin.cpp
msgid "Scale Polygon"
-msgstr "Scala poligono"
+msgstr "Ridimensiona poligono"
#: editor/plugins/polygon_2d_editor_plugin.cpp
msgid "Create a custom polygon. Enables custom polygon rendering."
@@ -10406,7 +10393,6 @@ msgid "Flip Portal"
msgstr "Ribalta Portale"
#: editor/plugins/room_manager_editor_plugin.cpp
-#, fuzzy
msgid "Occluder Set Transform"
msgstr "Imposta Trasformazione dell' Occlusore"
@@ -10758,7 +10744,7 @@ msgstr "[Ignora]"
#: editor/plugins/script_text_editor.cpp
msgid "Line"
-msgstr "Linea"
+msgstr "Riga"
#: editor/plugins/script_text_editor.cpp
msgid "Go to Function"
@@ -11006,7 +10992,7 @@ msgstr "Ortogonale dal Basso"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Bottom Perspective"
-msgstr "Prospettica dal Basso"
+msgstr "Prospettica dal basso"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Left Orthogonal"
@@ -11014,7 +11000,7 @@ msgstr "Ortogonale a Sinistra"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Left Perspective"
-msgstr "Prospettica a Sinistra"
+msgstr "Prospettica da sinistra"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Right Orthogonal"
@@ -11022,7 +11008,7 @@ msgstr "Ortogonale a Destra"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Right Perspective"
-msgstr "Prospettica a Destra"
+msgstr "Prospettica da destra"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Front Orthogonal"
@@ -11030,7 +11016,7 @@ msgstr "Ortogonale di Fronte"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Front Perspective"
-msgstr "Prospettica di Fronte"
+msgstr "Prospettica di fronte"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Rear Orthogonal"
@@ -11038,7 +11024,7 @@ msgstr "Ortogonale da Dietro"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Rear Perspective"
-msgstr "Prospettica da Dietro"
+msgstr "Prospettica da dietro"
#. TRANSLATORS: This will be appended to the view name when Auto Orthogonal is enabled.
#: editor/plugins/spatial_editor_plugin.cpp
@@ -11140,7 +11126,6 @@ msgid "Vertices:"
msgstr "Vertici:"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "FPS: %d (%s ms)"
msgstr "FPS: %d (%s ms)"
@@ -11186,31 +11171,31 @@ msgstr "Questa operazione richiede un solo nodo selezionato."
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Auto Orthogonal Enabled"
-msgstr "Ortogonale Automatico Abilitato"
+msgstr "Ortogonale automatica abilitata"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Lock View Rotation"
-msgstr "Blocca Rotazione Vista"
+msgstr "Blocca la rotazione della vista"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Display Normal"
-msgstr "Mostra Normale"
+msgstr "Visualizzazione predefinita"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Display Wireframe"
-msgstr "Mostra Wireframe"
+msgstr "Visualizzazione fildiferro"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Display Overdraw"
-msgstr "Mostra Overdraw"
+msgstr "Visualizza Overdraw"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Display Unshaded"
-msgstr "Mostra Unshaded"
+msgstr "Visualizzazione senza ombre"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "View Environment"
-msgstr "Mostra Ambiente"
+msgstr "Visualizza ambiente"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "View Gizmos"
@@ -11388,12 +11373,10 @@ msgid "Orbit View Right"
msgstr "Orbita la visuale a destra"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Orbit View Up"
msgstr "Orbita la visuale in sù"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Orbit View 180"
msgstr "Orbita la visuale 180"
@@ -11426,7 +11409,6 @@ msgid "Increase Field of View"
msgstr "Aumenta il Campo Visivo"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Reset Field of View to Default"
msgstr "Ripristina il Campo Visivo alle impostazioni predefinite"
@@ -11436,7 +11418,7 @@ msgstr "Scatta l'oggetto sul suolo"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Transform Dialog..."
-msgstr "Finestra di Transform..."
+msgstr "Modale di trasformazione..."
#: editor/plugins/spatial_editor_plugin.cpp
msgid "1 Viewport"
@@ -11468,11 +11450,11 @@ msgstr "Gizmos"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "View Origin"
-msgstr "Visualizza Origine"
+msgstr "Visualizza l'origine"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "View Grid"
-msgstr "Visualizza Griglia"
+msgstr "Visualizza la griglia"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "View Portal Culling"
@@ -11489,19 +11471,19 @@ msgstr "Impostazioni…"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Snap Settings"
-msgstr "Impostazioni Agganciamento"
+msgstr "Impostazioni dello scatto"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Translate Snap:"
-msgstr "Agganciamento Traslazione:"
+msgstr "Scatto di traslazione:"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Rotate Snap (deg.):"
-msgstr "Agganciamento Rotazione (gradi):"
+msgstr "Scatto di rotazione (gradi):"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Scale Snap (%):"
-msgstr "Agganciamento Ridimensionamento (%):"
+msgstr "Scatto della scala (%):"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Viewport Settings"
@@ -11521,7 +11503,7 @@ msgstr "Visualizza Z-Far:"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Transform Change"
-msgstr "Cambiamento Transform"
+msgstr "Cambio di trasformazione"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Translate:"
@@ -11537,7 +11519,7 @@ msgstr "Scala (rapporto):"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Transform Type"
-msgstr "Tipo Transform"
+msgstr "Tipo di trasformazione"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Pre"
@@ -11548,14 +11530,12 @@ msgid "Post"
msgstr "Post"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Manipulator Gizmo Size"
msgstr "Dimensione Gizmo Di Controllo"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Manipulator Gizmo Opacity"
-msgstr "Opacità Gizmo Di Controllo"
+msgstr "Opacità Gizmo Manipolatore"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Show Viewport Rotation Gizmo"
@@ -11716,9 +11696,8 @@ msgid "New Animation"
msgstr "Nuova Animazione"
#: editor/plugins/sprite_frames_editor_plugin.cpp
-#, fuzzy
msgid "Filter animations"
-msgstr "Modalità di filtraggio animazioni"
+msgstr "Filtraggio animazioni"
#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Speed:"
@@ -11809,11 +11788,11 @@ msgstr "Modalità dello scatto:"
#: editor/plugins/texture_region_editor_plugin.cpp
msgid "Pixel Snap"
-msgstr "Agganciamento Pixel"
+msgstr "Scatto sui pixel"
#: editor/plugins/texture_region_editor_plugin.cpp
msgid "Grid Snap"
-msgstr "Agganciamento Griglia"
+msgstr "Scatto sulla griglia"
#: editor/plugins/texture_region_editor_plugin.cpp
msgid "Auto Slice"
@@ -12387,7 +12366,7 @@ msgstr "Elemento Modificabile"
#: editor/plugins/theme_editor_preview.cpp
msgid "Subtree"
-msgstr "Sottoalbero"
+msgstr "Subtree"
#: editor/plugins/theme_editor_preview.cpp
msgid "Has,Many,Options"
@@ -12550,7 +12529,7 @@ msgstr "Lato Editor"
#: editor/plugins/tile_map_editor_plugin.cpp
msgid "Display Grid"
-msgstr "Mostra Griglia"
+msgstr "Visualizza griglia"
#: editor/plugins/tile_map_editor_plugin.cpp
msgid "Axis Color"
@@ -12706,7 +12685,7 @@ msgstr "Abilita lo scatto e mostra la griglia (configurabile dall'ispettore)."
#: editor/plugins/tile_set_editor_plugin.cpp
msgid "Display Tile Names (Hold Alt Key)"
-msgstr "Mostra i Nomi delle Tile (Tenere Premuto Tasto Alt)"
+msgstr "Visualizza i nomi dei tasselli (tenere premuto il tasto alt)"
#: editor/plugins/tile_set_editor_plugin.cpp
msgid ""
@@ -12895,7 +12874,7 @@ msgstr "Questa proprietà non può essere cambiata."
#: editor/plugins/tile_set_editor_plugin.cpp
msgid "Snap Options"
-msgstr "Opzioni Agganciamento"
+msgstr "Opzioni dello scatto"
#: editor/plugins/tile_set_editor_plugin.cpp scene/2d/animated_sprite.cpp
#: scene/2d/camera_2d.cpp scene/2d/cpu_particles_2d.cpp scene/2d/light_2d.cpp
@@ -12903,9 +12882,10 @@ msgstr "Opzioni Agganciamento"
#: scene/2d/path_2d.cpp scene/2d/polygon_2d.cpp scene/2d/sprite.cpp
#: scene/3d/cpu_particles.cpp scene/3d/label_3d.cpp scene/3d/path.cpp
#: scene/3d/physics_body.cpp scene/3d/soft_body.cpp scene/3d/sprite_3d.cpp
-#: 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
+#: scene/3d/visual_instance.cpp 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
msgid "Offset"
msgstr "Scostamento"
@@ -13083,9 +13063,8 @@ msgid "Select SSH private key path"
msgstr "Seleziona il percorso della chiave privata SSH"
#: editor/plugins/version_control_editor_plugin.cpp
-#, fuzzy
msgid "SSH Passphrase"
-msgstr "Frase di accesso SSH"
+msgstr "SSH Passphrase"
#: editor/plugins/version_control_editor_plugin.cpp
msgid "Detect new changes"
@@ -13157,11 +13136,11 @@ msgstr "URL Remoto"
#: 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
#, fuzzy
@@ -14328,16 +14307,17 @@ msgid "Invalid project path (changed anything?)."
msgstr "Percorso del progetto invalido (cambiato qualcosa?)."
#: editor/project_manager.cpp
+#, fuzzy
msgid ""
-"Couldn't load project.godot in project path (error %d). It may be missing or "
-"corrupted."
+"Couldn't load project at '%s' (error %d). It may be missing or corrupted."
msgstr ""
"Impossibile caricare project.godot nel percorso del progetto (errore %d). "
"Può essere mancante o corrotto."
#: editor/project_manager.cpp
-msgid "Couldn't edit project.godot in project path."
-msgstr "Impossibile modificare project.godot nel percorso del progetto."
+#, fuzzy
+msgid "Couldn't save project at '%s' (error %d)."
+msgstr "Impossibile aprire il progetto a \"%s\"."
#: editor/project_manager.cpp
msgid "Couldn't create project.godot in project path."
@@ -14365,7 +14345,7 @@ msgstr "Importa Progetto Esistente"
#: editor/project_manager.cpp
msgid "Import & Edit"
-msgstr "Importa & Modifica"
+msgstr "Importa e Modifica"
#: editor/project_manager.cpp
msgid "Create New Project"
@@ -14373,7 +14353,7 @@ msgstr "Crea Nuovo Progetto"
#: editor/project_manager.cpp
msgid "Create & Edit"
-msgstr "Crea & Modifica"
+msgstr "Crea e Modifica"
#: editor/project_manager.cpp
msgid "Install Project:"
@@ -14381,7 +14361,7 @@ msgstr "Installa Progetto:"
#: editor/project_manager.cpp
msgid "Install & Edit"
-msgstr "Installa & Modifica"
+msgstr "Installa e Modifica"
#: editor/project_manager.cpp
msgid "Project Name:"
@@ -15180,7 +15160,7 @@ msgstr "Mantieni Transform Globale"
#: editor/reparent_dialog.cpp editor/scene_tree_dock.cpp
msgid "Reparent"
-msgstr "Cambia Genitore"
+msgstr "Riaccoppiare"
#: editor/run_settings_dialog.cpp
msgid "Run Mode:"
@@ -15928,7 +15908,7 @@ msgstr "Monitor"
#: editor/script_editor_debugger.cpp
msgid "Pick one or more items from the list to display the graph."
-msgstr "Scegli uno o più elementi dall'elenco per mostrare il grafico."
+msgstr "Scegliere uno o più elementi dall'elenco per mostrare il grafico."
#: editor/script_editor_debugger.cpp
msgid "List of Video Memory Usage by Resource:"
@@ -16234,7 +16214,6 @@ msgid "Flush stdout On Print"
msgstr "Svuota stdout Alla Stampa"
#: main/main.cpp servers/visual_server.cpp
-#, fuzzy
msgid "Logging"
msgstr "Logging"
@@ -16316,11 +16295,11 @@ msgstr "Modello Thread"
#: main/main.cpp
msgid "Thread Safe BVH"
-msgstr ""
+msgstr "Thread sicuro BVH"
#: main/main.cpp
msgid "Handheld"
-msgstr ""
+msgstr "Maneggiato"
#: main/main.cpp platform/javascript/export/export.cpp
#: platform/uwp/export/export.cpp
@@ -16342,7 +16321,7 @@ msgstr "Forza FPS"
#: main/main.cpp
msgid "Enable Pause Aware Picking"
-msgstr ""
+msgstr "Abilita Picking Allerta Pausa"
#: 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
@@ -16352,7 +16331,7 @@ msgstr "Interfaccia Grafica"
#: main/main.cpp
msgid "Drop Mouse On GUI Input Disabled"
-msgstr ""
+msgstr "Rilascio del mouse sull'Input della GUI Disabilitato"
#: main/main.cpp
msgid "stdout"
@@ -16399,7 +16378,6 @@ msgid "Input Devices"
msgstr "Dispositivi Input"
#: main/main.cpp
-#, fuzzy
msgid "Pointing"
msgstr "Puntamento"
@@ -16426,7 +16404,6 @@ msgid "Environment"
msgstr "Ambiente"
#: main/main.cpp
-#, fuzzy
msgid "Default Clear Color"
msgstr "Colore Di Sfondo Di Default"
@@ -16468,7 +16445,7 @@ msgstr "Buffering"
#: main/main.cpp
msgid "Agile Event Flushing"
-msgstr ""
+msgstr "Svuotamento degli eventi usando l'algoritmo Agile"
#: main/main.cpp
msgid "Emulate Touch From Mouse"
@@ -16656,16 +16633,15 @@ msgstr "Gradi di Rotazione"
#: modules/csg/csg_shape.cpp
msgid "Spin Sides"
-msgstr ""
+msgstr "Lati rotazione"
#: modules/csg/csg_shape.cpp
msgid "Path Node"
msgstr "Percorso Nodo"
#: modules/csg/csg_shape.cpp
-#, fuzzy
msgid "Path Interval Type"
-msgstr "Crea Vertice Interno"
+msgstr "Tipo di intervallo del Percorso"
#: modules/csg/csg_shape.cpp
msgid "Path Interval"
@@ -16673,7 +16649,7 @@ msgstr "Intervallo Percorso"
#: modules/csg/csg_shape.cpp
msgid "Path Simplify Angle"
-msgstr ""
+msgstr "Angolo di semplificazione Percorso"
#: modules/csg/csg_shape.cpp
msgid "Path Rotation"
@@ -16694,7 +16670,6 @@ msgid "Path U Distance"
msgstr "Scegli la Distanza:"
#: modules/csg/csg_shape.cpp
-#, fuzzy
msgid "Path Joined"
msgstr "Percorsi Uniti"
@@ -16716,15 +16691,15 @@ msgstr "Sempre In Ordine"
#: modules/enet/networked_multiplayer_enet.cpp
msgid "Server Relay"
-msgstr ""
+msgstr "Rimbalzo Server"
#: modules/enet/networked_multiplayer_enet.cpp
msgid "DTLS Verify"
-msgstr ""
+msgstr "Verifica DTLS"
#: modules/enet/networked_multiplayer_enet.cpp
msgid "DTLS Hostname"
-msgstr ""
+msgstr "Nome host DTLS"
#: modules/enet/networked_multiplayer_enet.cpp
msgid "Use DTLS"
@@ -16732,7 +16707,7 @@ msgstr "Usa DTLS"
#: modules/fbx/editor_scene_importer_fbx.cpp
msgid "FBX"
-msgstr ""
+msgstr "FBX"
#: modules/fbx/editor_scene_importer_fbx.cpp
msgid "Use FBX"
@@ -16810,7 +16785,6 @@ msgid "Disabled GDNative Singleton"
msgstr "Singleton GDNative disabilitato"
#: modules/gdnative/gdnative_library_singleton_editor.cpp
-#, fuzzy
msgid "Libraries:"
msgstr "Librerie:"
@@ -16956,11 +16930,11 @@ msgstr "Conteggio Sparso"
#: modules/gltf/gltf_accessor.cpp
msgid "Sparse Indices Buffer View"
-msgstr ""
+msgstr "Vista indici sparsi dei buffer"
#: modules/gltf/gltf_accessor.cpp
msgid "Sparse Indices Byte Offset"
-msgstr ""
+msgstr "Scostamento Byte degli Indici Sparsi"
#: modules/gltf/gltf_accessor.cpp
msgid "Sparse Indices Component Type"
@@ -16968,11 +16942,11 @@ msgstr "Tipo di Componente degli Indici Sparsi"
#: modules/gltf/gltf_accessor.cpp
msgid "Sparse Values Buffer View"
-msgstr ""
+msgstr "Vista buffer dei valori sparsi"
#: modules/gltf/gltf_accessor.cpp
msgid "Sparse Values Byte Offset"
-msgstr ""
+msgstr "Scostamento Byte dei Valori Sparsi"
#: modules/gltf/gltf_buffer_view.cpp
msgid "Buffer"
@@ -16996,11 +16970,11 @@ msgstr "Dimensione Campo VIsivo"
#: modules/gltf/gltf_camera.cpp
msgid "Zfar"
-msgstr ""
+msgstr "Z Lontano"
#: modules/gltf/gltf_camera.cpp
msgid "Znear"
-msgstr "Znear"
+msgstr "Z Vicino"
#: 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
@@ -17048,11 +17022,11 @@ msgstr "Xform"
#: modules/gltf/gltf_node.cpp scene/3d/mesh_instance.cpp
msgid "Skin"
-msgstr ""
+msgstr "Skin"
#: modules/gltf/gltf_node.cpp scene/3d/spatial.cpp
msgid "Translation"
-msgstr "Traslazione"
+msgstr "Traduzione"
#: modules/gltf/gltf_node.cpp
msgid "Children"
@@ -17075,18 +17049,18 @@ msgid "Godot Bone Node"
msgstr "Nodo Osso Godot"
#: modules/gltf/gltf_skin.cpp
-#, fuzzy
msgid "Skin Root"
-msgstr "Nuova Scena Radice"
+msgstr "Radice della Skin"
#: modules/gltf/gltf_skin.cpp
#, fuzzy
msgid "Joints Original"
-msgstr "Centra Origine"
+msgstr "Articolazioni Originali"
#: modules/gltf/gltf_skin.cpp
+#, fuzzy
msgid "Inverse Binds"
-msgstr ""
+msgstr "Inverti Legamenti"
#: modules/gltf/gltf_skin.cpp
msgid "Non Joints"
@@ -17094,11 +17068,11 @@ msgstr "Non Articolazioni"
#: modules/gltf/gltf_skin.cpp
msgid "Joint I To Bone I"
-msgstr ""
+msgstr "Articolazione I ad Osso I"
#: modules/gltf/gltf_skin.cpp
msgid "Joint I To Name"
-msgstr ""
+msgstr "Articolazione I a Nome"
#: modules/gltf/gltf_skin.cpp
msgid "Godot Skin"
@@ -17126,7 +17100,7 @@ msgstr "Immagine Gloss Speculare"
#: modules/gltf/gltf_state.cpp
msgid "Json"
-msgstr ""
+msgstr "Json"
#: modules/gltf/gltf_state.cpp
msgid "Major Version"
@@ -17141,13 +17115,13 @@ msgid "GLB Data"
msgstr "Dati GLB"
#: modules/gltf/gltf_state.cpp
+#, fuzzy
msgid "Use Named Skin Binds"
-msgstr ""
+msgstr "Usa associazioni skin con nome"
#: modules/gltf/gltf_state.cpp
-#, fuzzy
msgid "Buffer Views"
-msgstr "Vista dal retro"
+msgstr "Viste dei Buffer"
#: modules/gltf/gltf_state.cpp
msgid "Accessors"
@@ -17237,17 +17211,15 @@ msgid "Mask"
msgstr "Maschera"
#: modules/gridmap/grid_map.cpp scene/2d/tile_map.cpp
-#, fuzzy
msgid "Bake Navigation"
-msgstr "Navigazione"
+msgstr "Preprocessa Navigazione"
#: 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 "Sensazione Navigazione"
+msgstr "Livelli Navigazione"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Next Plane"
@@ -17282,9 +17254,8 @@ msgid "GridMap Fill Selection"
msgstr "GridMap Riempi Selezione"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "GridMap Paste Selection"
-msgstr "Sezione GridMap incolla"
+msgstr "Incolla Selezione GridMap"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "GridMap Paint"
@@ -17299,9 +17270,8 @@ msgid "Snap View"
msgstr "Scatta Visuale"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Clip Disabled"
-msgstr "Clip Disabilitata"
+msgstr "Clip Disabilitato"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Clip Above"
@@ -17409,9 +17379,8 @@ msgid "Plotting lightmaps"
msgstr "Stampando le lightmap"
#: modules/lightmapper_cpu/register_types.cpp
-#, fuzzy
msgid "CPU Lightmapper"
-msgstr "Preprocessa Lightmaps"
+msgstr "CPU Mappatore Della Luce"
#: modules/lightmapper_cpu/register_types.cpp
msgid "Low Quality Ray Count"
@@ -17442,28 +17411,27 @@ msgstr "Altezza Occhio"
#: modules/mobile_vr/mobile_vr_interface.cpp
msgid "IOD"
-msgstr ""
+msgstr "IOD"
#: modules/mobile_vr/mobile_vr_interface.cpp
+#, fuzzy
msgid "Display Width"
msgstr "Larghezza Display"
#: modules/mobile_vr/mobile_vr_interface.cpp
#, fuzzy
msgid "Display To Lens"
-msgstr "Mostra Unshaded"
+msgstr "Mostra alle Lenti"
#: modules/mobile_vr/mobile_vr_interface.cpp
msgid "Oversample"
-msgstr ""
+msgstr "Sovracampionamento"
#: modules/mobile_vr/mobile_vr_interface.cpp
-#, fuzzy
msgid "K1"
msgstr "K1"
#: modules/mobile_vr/mobile_vr_interface.cpp
-#, fuzzy
msgid "K2"
msgstr "K2"
@@ -17482,20 +17450,17 @@ msgstr "Auto-Aggiorna Progetto"
#: modules/mono/godotsharp_dirs.cpp
#, fuzzy
msgid "Assembly Name"
-msgstr "Nome Display"
+msgstr "Nome Assemblaggio"
#: modules/mono/godotsharp_dirs.cpp
-#, fuzzy
msgid "Solution Directory"
-msgstr "Scegli una cartella"
+msgstr "Cartella di Soluzione"
#: modules/mono/godotsharp_dirs.cpp
-#, fuzzy
msgid "C# Project Directory"
-msgstr "Scegli una cartella"
+msgstr "Cartella Progetto C#"
#: modules/mono/mono_gd/gd_mono_utils.cpp
-#, fuzzy
msgid "End of inner exception stack trace"
msgstr "Fine dell'analisi dell’eccezione interna dello stack"
@@ -17620,11 +17585,11 @@ msgstr ""
#: modules/upnp/upnp.cpp
msgid "Discover Local Port"
-msgstr ""
+msgstr "Rileva Porta Locale"
#: modules/upnp/upnp.cpp
msgid "Discover IPv6"
-msgstr ""
+msgstr "Rilevamento IPv6"
#: modules/upnp/upnp_device.cpp
msgid "Description URL"
@@ -17636,21 +17601,19 @@ msgstr "Tipo Di Servizio"
#: modules/upnp/upnp_device.cpp
msgid "IGD Control URL"
-msgstr ""
+msgstr "URL di controllo IGD"
#: modules/upnp/upnp_device.cpp
-#, fuzzy
msgid "IGD Service Type"
-msgstr "Imposta Tipo di Variabile"
+msgstr "Tipo Servizio IGD"
#: modules/upnp/upnp_device.cpp
msgid "IGD Our Addr"
-msgstr ""
+msgstr "Indirizzo locale IGD"
#: modules/upnp/upnp_device.cpp
-#, fuzzy
msgid "IGD Status"
-msgstr "Stato"
+msgstr "Stato IGD"
#: modules/visual_script/visual_script.cpp
msgid ""
@@ -17677,7 +17640,6 @@ msgstr ""
"memoria di lavoro del nodo! Si prega di correggere il nodo."
#: modules/visual_script/visual_script.cpp
-#, fuzzy
msgid "Node returned an invalid sequence output:"
msgstr "Il nodo ha ritornato una sequenza di output invalida:"
@@ -17686,14 +17648,13 @@ msgid "Found sequence bit but not the node in the stack, report bug!"
msgstr "Trovato bit di sequenza ma non il nodo nello stack, segnalare il bug!"
#: modules/visual_script/visual_script.cpp
-#, fuzzy
msgid "Stack overflow with stack depth:"
msgstr "Overflow dello stack con profondità dello stack:"
#: modules/visual_script/visual_script.cpp
#, fuzzy
msgid "Visual Script"
-msgstr "Ricerca VisualScript"
+msgstr "Script Visivo"
#: modules/visual_script/visual_script_editor.cpp
msgid "Change Signal Arguments"
@@ -18014,7 +17975,6 @@ msgstr "Modifica membro"
#: modules/visual_script/visual_script_expression.cpp
#: scene/resources/visual_shader.cpp
-#, fuzzy
msgid "Expression"
msgstr "Espressione"
@@ -18023,9 +17983,8 @@ msgid "Return"
msgstr "Ritorno"
#: modules/visual_script/visual_script_flow_control.cpp
-#, fuzzy
msgid "Return Enabled"
-msgstr "Eseguibile"
+msgstr "Ritorno Abilitato"
#: modules/visual_script/visual_script_flow_control.cpp
msgid "Return Type"
@@ -18038,27 +17997,26 @@ msgstr "Condizione"
#: modules/visual_script/visual_script_flow_control.cpp
msgid "if (cond) is:"
-msgstr "if (cond) is:"
+msgstr "se (cond) è:"
#: modules/visual_script/visual_script_flow_control.cpp
-#, fuzzy
msgid "While"
-msgstr "While"
+msgstr "Mentre"
#: modules/visual_script/visual_script_flow_control.cpp
msgid "while (cond):"
-msgstr ""
+msgstr "mentre (cond):"
#: modules/visual_script/visual_script_flow_control.cpp
msgid "Iterator"
msgstr "Iteratore"
#: modules/visual_script/visual_script_flow_control.cpp
+#, fuzzy
msgid "for (elem) in (input):"
-msgstr ""
+msgstr "per (elem) in (input):"
#: modules/visual_script/visual_script_flow_control.cpp
-#, fuzzy
msgid "Input type not iterable:"
msgstr "Il tipo di input non è iterabile:"
@@ -18067,7 +18025,6 @@ msgid "Iterator became invalid"
msgstr "L'iteratore è diventato invalido"
#: modules/visual_script/visual_script_flow_control.cpp
-#, fuzzy
msgid "Iterator became invalid:"
msgstr "L'iteratore è diventato invalido:"
@@ -18080,9 +18037,8 @@ msgid "in order:"
msgstr "in ordine:"
#: modules/visual_script/visual_script_flow_control.cpp
-#, fuzzy
msgid "Steps"
-msgstr "Passo"
+msgstr "Passi"
#: modules/visual_script/visual_script_flow_control.cpp
msgid "Switch"
@@ -18095,7 +18051,7 @@ msgstr "'input' è:"
#: modules/visual_script/visual_script_flow_control.cpp
#, fuzzy
msgid "Type Cast"
-msgstr "Tipo:"
+msgstr "Conversione Tipo"
#: modules/visual_script/visual_script_flow_control.cpp
msgid "Is %s?"
@@ -18139,9 +18095,8 @@ msgid "Validate"
msgstr "Valida"
#: modules/visual_script/visual_script_func_nodes.cpp
-#, fuzzy
msgid "RPC Call Mode"
-msgstr "Modalità scala"
+msgstr "Modalità Chiamata RPC"
#: modules/visual_script/visual_script_func_nodes.cpp
msgid "Subtract %s"
@@ -18160,34 +18115,38 @@ msgid "Mod %s"
msgstr "Modulo %s"
#: modules/visual_script/visual_script_func_nodes.cpp
+#, fuzzy
msgid "ShiftLeft %s"
-msgstr "ShiftLeft %s"
+msgstr "SpostaSinistra %s"
#: modules/visual_script/visual_script_func_nodes.cpp
+#, fuzzy
msgid "ShiftRight %s"
-msgstr ""
+msgstr "SpostaDestra %s"
#: modules/visual_script/visual_script_func_nodes.cpp
+#, fuzzy
msgid "BitAnd %s"
-msgstr "BitAnd %s"
+msgstr "Bit E %s"
#: modules/visual_script/visual_script_func_nodes.cpp
+#, fuzzy
msgid "BitOr %s"
-msgstr ""
+msgstr "Bit O %s"
#: modules/visual_script/visual_script_func_nodes.cpp
+#, fuzzy
msgid "BitXor %s"
-msgstr ""
+msgstr "Bit XO %s"
#: modules/visual_script/visual_script_func_nodes.cpp
#, fuzzy
msgid "Set Mode"
-msgstr "Modalità di Selezione"
+msgstr "Modalità di Impostazione"
#: modules/visual_script/visual_script_func_nodes.cpp
-#, fuzzy
msgid "Assign Op"
-msgstr "Assegna"
+msgstr "Operatore Assegna"
#: modules/visual_script/visual_script_func_nodes.cpp
#: modules/visual_script/visual_script_nodes.cpp
@@ -18204,7 +18163,6 @@ msgid "Base object is not a Node!"
msgstr "L'oggetto base non è un Nodo!"
#: modules/visual_script/visual_script_func_nodes.cpp
-#, fuzzy
msgid "Path does not lead to Node!"
msgstr "Il percorso non conduce a un Nodo!"
@@ -18213,14 +18171,13 @@ msgid "Invalid index property name '%s' in node %s."
msgstr "Nome proprietà indice invalido \"%s\" nel nodo %s."
#: modules/visual_script/visual_script_func_nodes.cpp
-#, fuzzy
msgid "Emit %s"
-msgstr "Imposta %s"
+msgstr "Emetti %s"
#: modules/visual_script/visual_script_nodes.cpp
#, fuzzy
msgid "Compose Array"
-msgstr "Ridimensiona lista"
+msgstr "Componi Lista"
#: modules/visual_script/visual_script_nodes.cpp scene/resources/material.cpp
#: scene/resources/visual_shader_nodes.cpp
@@ -18228,12 +18185,10 @@ msgid "Operator"
msgstr "Operatore"
#: modules/visual_script/visual_script_nodes.cpp
-#, fuzzy
msgid "Invalid argument of type:"
msgstr "Argomento invalido di tipo:"
#: modules/visual_script/visual_script_nodes.cpp
-#, fuzzy
msgid "Invalid arguments:"
msgstr "Argomenti invalidi:"
@@ -18246,12 +18201,10 @@ msgid "Var Name"
msgstr "Var Nome"
#: modules/visual_script/visual_script_nodes.cpp
-#, fuzzy
msgid "VariableGet not found in script:"
msgstr "VariableGet non trovato nello script:"
#: modules/visual_script/visual_script_nodes.cpp
-#, fuzzy
msgid "VariableSet not found in script:"
msgstr "VariableSet non trovato nello script:"
@@ -18318,46 +18271,40 @@ msgstr ""
"oppure una stringa (errore)."
#: modules/visual_script/visual_script_nodes.cpp
-#, fuzzy
msgid "SubCall"
-msgstr "Chiamate"
+msgstr "SottoChiamata"
#: modules/visual_script/visual_script_nodes.cpp scene/gui/graph_node.cpp
msgid "Title"
msgstr "Titolo"
#: modules/visual_script/visual_script_nodes.cpp
-#, fuzzy
msgid "Construct %s"
-msgstr "Costanti"
+msgstr "Costruisci %s"
#: modules/visual_script/visual_script_nodes.cpp
-#, fuzzy
msgid "Get Local Var"
-msgstr "Usa Spazio Locale"
+msgstr "Ottieni Variabile Locale"
#: modules/visual_script/visual_script_nodes.cpp
-#, fuzzy
msgid "Set Local Var"
-msgstr "Usa Spazio Locale"
+msgstr "Imposta Variabile Locale"
#: modules/visual_script/visual_script_nodes.cpp
-#, fuzzy
msgid "Action %s"
-msgstr "Azione"
+msgstr "Azione %s"
#: modules/visual_script/visual_script_nodes.cpp
msgid "Deconstruct %s"
-msgstr ""
+msgstr "Decostruisci %s"
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Search VisualScript"
msgstr "Ricerca VisualScript"
#: modules/visual_script/visual_script_yield_nodes.cpp
-#, fuzzy
msgid "Yield"
-msgstr "Yield"
+msgstr "Rendi (Yield)"
#: modules/visual_script/visual_script_yield_nodes.cpp
msgid "Wait"
@@ -18382,31 +18329,31 @@ msgstr "Tempo Di Attesa"
#: modules/visual_script/visual_script_yield_nodes.cpp
#, fuzzy
msgid "WaitSignal"
-msgstr "WaitSignal"
+msgstr "SegnaleAspetta"
#: modules/visual_script/visual_script_yield_nodes.cpp
#, fuzzy
msgid "WaitNodeSignal"
-msgstr "WaitNodeSignal"
+msgstr "SegnaleAspettaNodo"
#: modules/visual_script/visual_script_yield_nodes.cpp
#, fuzzy
msgid "WaitInstanceSignal"
-msgstr "WaitInstanceSignal"
+msgstr "SegnaleAspettaIstanza"
#: modules/webrtc/webrtc_data_channel.cpp
#, fuzzy
msgid "Write Mode"
-msgstr "Modalità Priorità"
+msgstr "Modalità Scrittura"
#: modules/webrtc/webrtc_data_channel.h
+#, fuzzy
msgid "WebRTC"
-msgstr ""
+msgstr "RTCWeb"
#: modules/webrtc/webrtc_data_channel.h
-#, fuzzy
msgid "Max Channel In Buffer (KB)"
-msgstr "Dimensione Index Buffer dei Poligoni nel Canvas (KB)"
+msgstr "Canali In Buffer Massimi (KB)"
#: modules/websocket/websocket_client.cpp
msgid "Verify SSL"
@@ -18417,36 +18364,36 @@ msgid "Trusted SSL Certificate"
msgstr "Certificato SSL Fidato"
#: modules/websocket/websocket_macros.h
-#, fuzzy
msgid "WebSocket Client"
-msgstr "Peer di Rete"
+msgstr "Cliente WebSocket"
#: modules/websocket/websocket_macros.h
#, fuzzy
msgid "Max In Buffer (KB)"
-msgstr "Dimensione Massima (KB)"
+msgstr "In Buffer Massimi (KB)"
#: modules/websocket/websocket_macros.h
+#, fuzzy
msgid "Max In Packets"
-msgstr ""
+msgstr "Pacchetti In Massimi"
#: modules/websocket/websocket_macros.h
#, fuzzy
msgid "Max Out Buffer (KB)"
-msgstr "Dimensione Massima (KB)"
+msgstr "Out Buffer Massimi (KB)"
#: modules/websocket/websocket_macros.h
+#, fuzzy
msgid "Max Out Packets"
-msgstr ""
+msgstr "Pacchetti Out Massimi"
#: modules/websocket/websocket_macros.h
-#, fuzzy
msgid "WebSocket Server"
-msgstr "Peer di Rete"
+msgstr "Server WebSocket"
#: modules/websocket/websocket_server.cpp
msgid "Bind IP"
-msgstr ""
+msgstr "Collega IP"
#: modules/websocket/websocket_server.cpp
msgid "Private Key"
@@ -18457,9 +18404,8 @@ msgid "SSL Certificate"
msgstr "Certificato SSL"
#: modules/websocket/websocket_server.cpp
-#, fuzzy
msgid "CA Chain"
-msgstr "Elimina Catena IK"
+msgstr "Catena CA"
#: modules/websocket/websocket_server.cpp
msgid "Handshake Timeout"
@@ -18478,12 +18424,14 @@ msgid "Optional Features"
msgstr "Funzionalità Opzionali"
#: modules/webxr/webxr_interface.cpp
+#, fuzzy
msgid "Requested Reference Space Types"
-msgstr ""
+msgstr "Tipi di Riferimento Spazio Richiesti"
#: modules/webxr/webxr_interface.cpp
+#, fuzzy
msgid "Reference Space Type"
-msgstr ""
+msgstr "Tipi di Riferimento Spazio"
#: modules/webxr/webxr_interface.cpp
msgid "Visibility State"
@@ -18494,26 +18442,25 @@ msgid "Bounds Geometry"
msgstr "Confini Geometria"
#: modules/webxr/webxr_interface.cpp
-#, fuzzy
msgid "XR Standard Mapping"
-msgstr "Agganciamento Intelligente"
+msgstr "Mappamento Standard XR"
#: platform/android/export/export.cpp
msgid "Android SDK Path"
msgstr "Percorso SDK Android"
#: platform/android/export/export.cpp
-#, fuzzy
msgid "Debug Keystore"
-msgstr "Debugger"
+msgstr "Keystore di Debug"
#: platform/android/export/export.cpp
msgid "Debug Keystore User"
-msgstr ""
+msgstr "Keystore di Debug Utente"
#: platform/android/export/export.cpp
+#, fuzzy
msgid "Debug Keystore Pass"
-msgstr ""
+msgstr "Keystore di Debug Pass"
#: platform/android/export/export.cpp
msgid "Force System User"
@@ -18521,23 +18468,23 @@ msgstr "Forza Utente System"
#: platform/android/export/export.cpp
msgid "Shutdown ADB On Exit"
-msgstr ""
+msgstr "Spegni ADB In Uscita"
#: platform/android/export/export_plugin.cpp
msgid "Launcher Icons"
-msgstr ""
+msgstr "Icone del Launcher"
#: platform/android/export/export_plugin.cpp
msgid "Main 192 X 192"
-msgstr ""
+msgstr "Principale 192 X 192"
#: platform/android/export/export_plugin.cpp
msgid "Adaptive Foreground 432 X 432"
-msgstr ""
+msgstr "Primo Piano Adattivo 432 X 432"
#: platform/android/export/export_plugin.cpp
msgid "Adaptive Background 432 X 432"
-msgstr ""
+msgstr "Sfondo Adattivo 432 X 432"
#: platform/android/export/export_plugin.cpp
msgid "Package name is missing."
@@ -18569,9 +18516,8 @@ 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"
+msgstr "Build Personalizzata"
#: platform/android/export/export_plugin.cpp
msgid "Use Custom Build"
@@ -18590,22 +18536,20 @@ msgid "Target SDK"
msgstr "Target SDK"
#: platform/android/export/export_plugin.cpp platform/iphone/export/export.cpp
-#, fuzzy
msgid "Architectures"
-msgstr "Architettura"
+msgstr "Architetture"
#: platform/android/export/export_plugin.cpp
msgid "Keystore"
msgstr "Archivio Chiavi"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Debug User"
-msgstr "Debugger"
+msgstr "User di Debug"
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
msgid "Debug Password"
-msgstr ""
+msgstr "Password di Debug"
#: platform/android/export/export_plugin.cpp
msgid "Release User"
@@ -18617,7 +18561,7 @@ msgstr "Password Di Rilascio"
#: platform/android/export/export_plugin.cpp
msgid "One Click Deploy"
-msgstr ""
+msgstr "Distribuzione con un Click"
#: platform/android/export/export_plugin.cpp
msgid "Clear Previous Install"
@@ -18636,9 +18580,8 @@ msgid "Unique Name"
msgstr "Nome Unico"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Signed"
-msgstr "Segnale"
+msgstr "Firmato"
#: platform/android/export/export_plugin.cpp
msgid "Classify As Game"
@@ -18669,50 +18612,45 @@ msgid "XR Mode"
msgstr "Modalità XR"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Hand Tracking"
-msgstr "Impacchettando"
+msgstr "Tracciamento della Mano"
#: platform/android/export/export_plugin.cpp
msgid "Hand Tracking Frequency"
-msgstr ""
+msgstr "Frequenza Tracciamento della Mano"
#: platform/android/export/export_plugin.cpp
msgid "Passthrough"
-msgstr "Passthrough"
+msgstr "Passaggio"
#: platform/android/export/export_plugin.cpp
msgid "Immersive Mode"
msgstr "Modalità Immersiva"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Support Small"
-msgstr "Supporta"
+msgstr "Supporta Piccolo"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Support Normal"
-msgstr "Supporta"
+msgstr "Supporta Normale"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Support Large"
-msgstr "Supporta"
+msgstr "Supporta Grande"
#: platform/android/export/export_plugin.cpp
#, fuzzy
msgid "Support Xlarge"
-msgstr "Supporta"
+msgstr "Supporta Extra-Grande"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "User Data Backup"
-msgstr "Interfaccia Utente"
+msgstr "Backup Dati Utente"
#: platform/android/export/export_plugin.cpp
msgid "Allow"
-msgstr ""
+msgstr "Permetti"
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
msgid "Command Line"
@@ -18728,7 +18666,7 @@ msgstr "Espansione APK"
#: platform/android/export/export_plugin.cpp
msgid "Salt"
-msgstr ""
+msgstr "Sale"
#: platform/android/export/export_plugin.cpp
msgid "Public Key"
@@ -18852,6 +18790,7 @@ msgid "Invalid package name:"
msgstr "Nome del pacchetto non valido:"
#: platform/android/export/export_plugin.cpp
+#, fuzzy
msgid ""
"Invalid \"GodotPaymentV3\" module included in the \"android/modules\" "
"project setting (changed in Godot 3.2.2).\n"
@@ -18859,26 +18798,29 @@ msgid ""
"Note that the singleton was also renamed from \"GodotPayments\" to "
"\"GodotGooglePlayBilling\"."
msgstr ""
+"Invalido modulo \"GodotPaymentV3\" incluso nelle impostazioni progetto "
+"\"android/modules\" (cambiato in Godot 3.2.2).\n"
+"Rimpiazzalo con il plugin di prime parti \"GodotGooglePlayBilling\".\n"
+"Da notare che il singleton è stato rinominato da \"GodotPayments\" a "
+"\"GodotGooglePlayBilling\"."
#: platform/android/export/export_plugin.cpp
msgid "\"Use Custom Build\" must be enabled to use the plugins."
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\" "
"or \"OpenXR\"."
msgstr ""
-"\"Hand Tracking\" è valido solo quando \"Xr Mode\" è impostato su \"Oculus "
-"Mobile VR\"."
+"\"Tracciamento della Mano\" è valido solo quando \"Modalità XR\" è impostato "
+"su \"Oculus Mobile VrApi\" o \"OpenXR\"."
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "\"Passthrough\" is only valid when \"XR Mode\" is \"OpenXR\"."
msgstr ""
-"\"Hand Tracking\" è valido solo quando \"Xr Mode\" è impostato su \"Oculus "
-"Mobile VR\"."
+"\"Oltrepassaggio\" è valido solo quando \"Modalità XR\" è impostato su "
+"\"OpenXR\"."
#: platform/android/export/export_plugin.cpp
msgid "\"Export AAB\" is only valid when \"Use Custom Build\" is enabled."
@@ -18886,52 +18828,60 @@ msgstr ""
"\"Export AAB\" è valido soltanto quanto \"Use Custom Build\" è abilitato."
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid ""
"\"Min SDK\" can only be overridden when \"Use Custom Build\" is enabled."
msgstr ""
-"\"Export AAB\" è valido soltanto quanto \"Use Custom Build\" è abilitato."
+"\"Min SDK\" può essere sovrascritto solo se \"Utilizza Build "
+"Personalizzata\" è abilitato."
#: platform/android/export/export_plugin.cpp
msgid "\"Min SDK\" should be a valid integer, but got \"%s\" which is invalid."
msgstr ""
+"\"Min SDK\" dovrebbe essere un intero valido, ma si è ottenuto \"%s\" che è "
+"invalido."
#: 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\" non può essere più basso di %d, che è la versione richiesta "
+"dalla libreria Godot."
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid ""
"\"Target SDK\" can only be overridden when \"Use Custom Build\" is enabled."
msgstr ""
-"\"Export AAB\" è valido soltanto quanto \"Use Custom Build\" è abilitato."
+"\"Target SDK\" può essere sovrascritto solo se \"Utilizza Build "
+"Personalizzata\" è abilitato."
#: platform/android/export/export_plugin.cpp
msgid ""
"\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."
msgstr ""
+"\"Target SDK\" dovrebbe essere un intero valido, ma si è ottenuto \"%s\" che "
+"è invalido."
#: 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 ""
+"\"Target SDK\" %d è più alto della versione di default %d. Questo potrebbe "
+"funzionare, ma non è stato testato e potrebbe essere instabile."
#: platform/android/export/export_plugin.cpp
msgid "\"Target SDK\" version must be greater or equal to \"Min SDK\" version."
msgstr ""
+"La versione di \"Target SDK\" dovrebbe essere maggiore o uguale della "
+"versione di \"Min SDK\"."
#: platform/android/export/export_plugin.cpp platform/osx/export/export.cpp
#: platform/windows/export/export.cpp
-#, fuzzy
msgid "Code Signing"
-msgstr "Segnale"
+msgstr "Firmatura Codice"
#: 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."
@@ -18941,7 +18891,7 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid "Signing debug %s..."
-msgstr ""
+msgstr "Firmando debug %s..."
#: platform/android/export/export_plugin.cpp
msgid "Signing release %s..."
@@ -18952,7 +18902,6 @@ msgid "Could not find keystore, unable to export."
msgstr "Non è stato possibile trovare keystore, impossible esportare."
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Could not start apksigner executable."
msgstr "Non è stato possibile avviare l'eseguibile apksigner."
@@ -18969,7 +18918,6 @@ msgid "'apksigner' verification of %s failed."
msgstr "Verifica 'apksigner' di %s non riuscita."
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Exporting for Android"
msgstr "Esportazione per Android"
@@ -19000,25 +18948,22 @@ msgstr ""
"\"Progetto\"."
#: 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 ""
-"Versione build di Android non coerente: Template installato: %s, Versione "
-"Godot: %s. Per favore, reinstalla il build template di Android dal menu "
-"\"Progetto\"."
+"La Versione build di Android non corrisponde: Template installato: %s, "
+"Versione Godot: %s. Per favore, reinstalla il build template di Android dal "
+"menu \"Progetto\"."
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid ""
"Unable to overwrite res://android/build/res/*.xml files with project name."
msgstr ""
"Impossibile sovrascrivere i file res://android/build/res/*.xml con il nome "
-"del progetto"
+"del progetto."
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Could not export project files to gradle project."
msgstr "Impossibile esportare i file del progetto in un progetto gradle."
@@ -19031,7 +18976,6 @@ msgid "Building Android Project (gradle)"
msgstr "Compilazione di un progetto 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."
@@ -19053,38 +18997,35 @@ msgstr ""
"directory del progetto gradle per gli output."
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Package not found: \"%s\"."
-msgstr "Pacchetto non trovato: \"%s\""
+msgstr "Pacchetto non trovato: \"%s\"."
#: platform/android/export/export_plugin.cpp
msgid "Creating APK..."
msgstr "Creazione APK..."
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Could not find template APK to export: \"%s\"."
msgstr "Impossibile trovare il template APK per l'esportazione: \"%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 ""
"Librerie mancanti nel modello di esportazione per le architetture "
-"selezionate: %s. Creare un modello con tutte le librerie richieste o "
-"deselezionare le architetture mancanti nella preimpostazione di esportazione."
+"selezionate: %s. Per favore creare un modello con tutte le librerie "
+"richieste, o deselezionare le architetture mancanti nella preimpostazione di "
+"esportazione."
#: platform/android/export/export_plugin.cpp
msgid "Adding files..."
msgstr "Aggiungendo file..."
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Could not export project files."
-msgstr "Impossibile esportare i file del progetto"
+msgstr "Impossibile esportare i file del progetto."
#: platform/android/export/export_plugin.cpp
msgid "Aligning APK..."
@@ -19104,243 +19045,225 @@ msgstr "Il carattere \"%s\" non è consentito nell'Identificatore."
#: platform/iphone/export/export.cpp
msgid "Landscape Launch Screens"
-msgstr ""
+msgstr "Schermate di avvio Panorama"
#: 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 "Schermate di avvio Ritratto"
#: 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
+#, fuzzy
msgid "App Store Team ID"
-msgstr ""
+msgstr "ID App Store Team"
#: platform/iphone/export/export.cpp
msgid "Provisioning Profile UUID Debug"
-msgstr ""
+msgstr "Profilo di provisioning UUID Debug"
#: platform/iphone/export/export.cpp
+#, fuzzy
msgid "Code Sign Identity Debug"
-msgstr ""
+msgstr "Firma Codice Identità di Debug"
#: platform/iphone/export/export.cpp
-#, fuzzy
msgid "Export Method Debug"
-msgstr "Esporta Con Debug"
+msgstr "Metodo di Esportazione Debug"
#: platform/iphone/export/export.cpp
msgid "Provisioning Profile UUID Release"
-msgstr ""
+msgstr "Profilo di provisioning UUID Release"
#: platform/iphone/export/export.cpp
msgid "Code Sign Identity Release"
-msgstr ""
+msgstr "Identità firma del codice Release"
#: platform/iphone/export/export.cpp
-#, fuzzy
msgid "Export Method Release"
-msgstr "Modalità d'Esportazione:"
+msgstr "Metodo di Esportazione Rilascio"
#: platform/iphone/export/export.cpp
msgid "Targeted Device Family"
-msgstr ""
+msgstr "Famiglia di dispositivi selezionata"
#: 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
-#, fuzzy
msgid "Identifier"
-msgstr "Identificatore non valido:"
+msgstr "Identificatore"
#: platform/iphone/export/export.cpp platform/osx/export/export.cpp
-#, fuzzy
msgid "Signature"
-msgstr "Segnale"
+msgstr "Firma"
#: platform/iphone/export/export.cpp platform/osx/export/export.cpp
-#, fuzzy
msgid "Short Version"
-msgstr "Versione"
+msgstr "Versione Corta"
#: platform/iphone/export/export.cpp platform/osx/export/export.cpp
#: platform/windows/export/export.cpp
-#, fuzzy
msgid "Copyright"
-msgstr "In Alto A Destra"
+msgstr "Copyright"
#: platform/iphone/export/export.cpp
-#, fuzzy
msgid "Capabilities"
-msgstr "Compatibilità"
+msgstr "Possibilità"
#: platform/iphone/export/export.cpp
-#, fuzzy
msgid "Access Wi-Fi"
-msgstr "Accedi"
+msgstr "Accesso al Wi-Fi"
#: platform/iphone/export/export.cpp
-#, fuzzy
msgid "Push Notifications"
-msgstr "Rotazione Casuale:"
+msgstr "Notifiche Push"
#: platform/iphone/export/export.cpp
-#, fuzzy
msgid "User Data"
-msgstr "Interfaccia Utente"
+msgstr "Dati Utente"
#: platform/iphone/export/export.cpp
msgid "Accessible From Files App"
-msgstr ""
+msgstr "Accessibile dall'Applicazione File"
#: platform/iphone/export/export.cpp
msgid "Accessible From iTunes Sharing"
-msgstr ""
+msgstr "Accessibile dalla condivisione di iTunes"
#: platform/iphone/export/export.cpp platform/osx/export/export.cpp
-#, fuzzy
msgid "Privacy"
-msgstr "Tasto Fisico"
+msgstr "Privacy"
#: platform/iphone/export/export.cpp platform/osx/export/export.cpp
-#, fuzzy
msgid "Camera Usage Description"
-msgstr "Descrizione"
+msgstr "Descrizione Utilizzo Camera"
#: platform/iphone/export/export.cpp platform/osx/export/export.cpp
-#, fuzzy
msgid "Microphone Usage Description"
-msgstr "Descrizioni delle proprietà"
+msgstr "Descrizione Utilizzo Microfono"
#: platform/iphone/export/export.cpp
#, fuzzy
msgid "Photolibrary Usage Description"
-msgstr "Descrizioni delle proprietà"
+msgstr "Descrizione Utilizzo Fotolibreria"
#: 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 "Spotlight 40 X 40"
#: platform/iphone/export/export.cpp
msgid "Spotlight 80 X 80"
-msgstr ""
+msgstr "Spotlight 80 X 80"
#: platform/iphone/export/export.cpp
msgid "Storyboard"
-msgstr ""
+msgstr "Storyboard"
#: platform/iphone/export/export.cpp
msgid "Use Launch Screen Storyboard"
-msgstr ""
+msgstr "Usa schermata di avvio Storyboard"
#: platform/iphone/export/export.cpp
-#, fuzzy
msgid "Image Scale Mode"
-msgstr "Modalità scala"
+msgstr "Modalità di ridimensionamento dell'immagine"
#: platform/iphone/export/export.cpp
-#, fuzzy
msgid "Custom Image @2x"
-msgstr "Immagine Personalizzata"
+msgstr "Immagine Personalizzata @2x"
#: platform/iphone/export/export.cpp
-#, fuzzy
msgid "Custom Image @3x"
-msgstr "Immagine Personalizzata"
+msgstr "Immagine Personalizzata @3x"
#: platform/iphone/export/export.cpp
-#, fuzzy
msgid "Use Custom BG Color"
-msgstr "Taglia nodi"
+msgstr "Utilizza Colore di Sfondo Personalizzato"
#: platform/iphone/export/export.cpp
-#, fuzzy
msgid "Custom BG Color"
-msgstr "Taglia nodi"
+msgstr "Colore di Sfondo Personalizzato"
#: platform/iphone/export/export.cpp
-#, fuzzy
msgid "Export Icons"
-msgstr "Espandi Tutto"
+msgstr "Icone Esportazione"
#: platform/iphone/export/export.cpp platform/javascript/export/export.cpp
#: platform/osx/export/export.cpp
#, fuzzy
msgid "Prepare Templates"
-msgstr "Gestisci i modelli d'esportazione"
+msgstr "Prepara i modelli d'esportazione"
#: platform/iphone/export/export.cpp platform/osx/export/export.cpp
-#, fuzzy
msgid "Export template not found."
-msgstr "Modello di rilascio personalizzato non trovato."
+msgstr "Modello di esportazione non trovato."
#: platform/iphone/export/export.cpp
msgid "App Store Team ID not specified - cannot configure the project."
@@ -19364,122 +19287,110 @@ msgid "Run exported HTML in the system's default browser."
msgstr "Esegui il codice HTML esportato nel browser di sistema predefinito."
#: platform/javascript/export/export.cpp
-#, fuzzy
msgid "Could not open template for export: \"%s\"."
-msgstr "Impossibile aprire il template per l'esportazione:"
+msgstr "Non è stato possibile aprire il modello per l'esportazione: \"%s\"."
#: platform/javascript/export/export.cpp
-#, fuzzy
msgid "Invalid export template: \"%s\"."
-msgstr "Template di esportazione non valido:"
+msgstr "Modello di esportazione non valido: \"%s\"."
#: platform/javascript/export/export.cpp
-#, fuzzy
msgid "Could not write file: \"%s\"."
-msgstr "Impossibile scrivere il file:"
+msgstr "Non è stato possibile scrivere il file: \"%s\"."
#: platform/javascript/export/export.cpp platform/osx/export/export.cpp
-#, fuzzy
msgid "Icon Creation"
-msgstr "Imposta Margine"
+msgstr "Creazione Icona"
#: platform/javascript/export/export.cpp
-#, fuzzy
msgid "Could not read file: \"%s\"."
-msgstr "Impossibile leggere il file:"
+msgstr "Non è stato possibile leggere il file: \"%s\"."
#: platform/javascript/export/export.cpp
msgid "PWA"
-msgstr ""
+msgstr "PWA"
#: platform/javascript/export/export.cpp
-#, fuzzy
msgid "Variant"
-msgstr "Separazione:"
+msgstr "Variante"
#: platform/javascript/export/export.cpp
#, fuzzy
msgid "Export Type"
-msgstr "Esporta"
+msgstr "Tipo di Esportazione"
#: platform/javascript/export/export.cpp
-#, fuzzy
msgid "VRAM Texture Compression"
-msgstr "Cambia espressione"
+msgstr "Compressione Texture VRAM"
#: platform/javascript/export/export.cpp
msgid "For Desktop"
-msgstr ""
+msgstr "Per il Desktop"
#: platform/javascript/export/export.cpp
msgid "For Mobile"
-msgstr ""
+msgstr "Per dispositivi mobile"
#: platform/javascript/export/export.cpp
msgid "HTML"
-msgstr ""
+msgstr "HTML"
#: platform/javascript/export/export.cpp
-#, fuzzy
msgid "Export Icon"
-msgstr "Espandi Tutto"
+msgstr "Icona di Esportazione"
#: platform/javascript/export/export.cpp
-#, fuzzy
msgid "Custom HTML Shell"
-msgstr "Taglia nodi"
+msgstr "Shell HTML Personalizzato"
#: platform/javascript/export/export.cpp
msgid "Head Include"
-msgstr ""
+msgstr "Includi head"
#: platform/javascript/export/export.cpp
msgid "Canvas Resize Policy"
-msgstr ""
+msgstr "Regole di ridimensionamento canvas"
#: platform/javascript/export/export.cpp
msgid "Focus Canvas On Start"
-msgstr ""
+msgstr "Evidenzia Canvas all'avvio"
#: platform/javascript/export/export.cpp
-#, fuzzy
msgid "Experimental Virtual Keyboard"
-msgstr "Filtra segnali"
+msgstr "Tastiera Virtuale Sperimentale"
#: platform/javascript/export/export.cpp
msgid "Progressive Web App"
-msgstr ""
+msgstr "Applicazione Web progressiva"
#: platform/javascript/export/export.cpp
msgid "Offline Page"
-msgstr ""
+msgstr "Pagina Offline"
#: platform/javascript/export/export.cpp
msgid "Icon 144 X 144"
-msgstr ""
+msgstr "Icona 144 x 144"
#: platform/javascript/export/export.cpp
msgid "Icon 180 X 180"
-msgstr ""
+msgstr "Icona 180 x 180"
#: platform/javascript/export/export.cpp
msgid "Icon 512 X 512"
-msgstr ""
+msgstr "Icona 512 x 512"
#: platform/javascript/export/export.cpp
-#, fuzzy
msgid "Could not read HTML shell: \"%s\"."
-msgstr "Impossibile leggere la shell HTML:"
+msgstr "Non è stato possibile leggere lo shell HTML: \"%s\"."
#: platform/javascript/export/export.cpp
#, fuzzy
msgid "Could not create HTTP server directory: %s."
-msgstr "Impossibile creare la directory per il server HTTP:"
+msgstr "Impossibile creare la cartella per il server HTTP: %s."
#: platform/javascript/export/export.cpp
-#, fuzzy
msgid "Error starting HTTP server: %d."
-msgstr "Errore all'avvio del server HTTP:"
+msgstr "Errore all'avvio del server HTTP: %d."
#: platform/javascript/export/export.cpp
msgid "Web"
@@ -19487,69 +19398,63 @@ msgstr "Web"
#: platform/javascript/export/export.cpp
msgid "HTTP Host"
-msgstr ""
+msgstr "Host HTTP"
#: platform/javascript/export/export.cpp
msgid "HTTP Port"
-msgstr ""
+msgstr "Porta HTTP"
#: platform/javascript/export/export.cpp
-#, fuzzy
msgid "Use SSL"
-msgstr "Usa Scatto"
+msgstr "Usa SSL"
#: platform/javascript/export/export.cpp
msgid "SSL Key"
-msgstr ""
+msgstr "Chiave SSL"
#: platform/osx/export/codesign.cpp
msgid "Can't get filesystem access."
-msgstr ""
+msgstr "Non si può avere accesso al filesystem."
#: platform/osx/export/codesign.cpp
msgid "Failed to get Info.plist hash."
-msgstr ""
+msgstr "Recupero dell'hash di Info.plist fallito."
#: platform/osx/export/codesign.cpp
-#, fuzzy
msgid "Invalid Info.plist, no exe name."
-msgstr "Nome del progetto non valido."
+msgstr "Invalido Info.plist, nessun nome exe."
#: platform/osx/export/codesign.cpp
msgid "Invalid Info.plist, no bundle id."
-msgstr ""
+msgstr "Info.plist invalido, nessun bundle id."
#: platform/osx/export/codesign.cpp
-#, fuzzy
msgid "Invalid Info.plist, can't load."
-msgstr "Geometria non valida, impossibile creare il poligono."
+msgstr "Info.plist non valido, impossibile caricare."
#: platform/osx/export/codesign.cpp
-#, fuzzy
msgid "Failed to create \"%s\" subfolder."
-msgstr "Impossibile creare la cartella."
+msgstr "Impossibile creare la sottocartella \"%s\"."
#: platform/osx/export/codesign.cpp
msgid "Failed to extract thin binary."
-msgstr ""
+msgstr "Estrazione del file binario fallito."
#: platform/osx/export/codesign.cpp
-#, fuzzy
msgid "Invalid binary format."
-msgstr "Percorso di base non valido."
+msgstr "Formato eseguibile non valido."
#: platform/osx/export/codesign.cpp
msgid "Already signed!"
-msgstr ""
+msgstr "Già firmato!"
#: platform/osx/export/codesign.cpp
-#, fuzzy
msgid "Failed to process nested resources."
-msgstr "Caricamento della risorsa fallito."
+msgstr "Elaborazione risorse nidificate fallito."
#: platform/osx/export/codesign.cpp
msgid "Failed to create _CodeSignature subfolder."
-msgstr ""
+msgstr "Creazione sottocartella _CodeSignature fallita."
#: platform/osx/export/codesign.cpp
#, fuzzy
@@ -19557,53 +19462,48 @@ msgid "Failed to get CodeResources hash."
msgstr "Caricamento della risorsa fallito."
#: platform/osx/export/codesign.cpp platform/osx/export/export.cpp
-#, fuzzy
msgid "Invalid entitlements file."
-msgstr "Estensione non valida."
+msgstr "File di permessi non valido."
#: platform/osx/export/codesign.cpp
-#, fuzzy
msgid "Invalid executable file."
-msgstr "Estensione non valida."
+msgstr "File eseguibile non valido."
#: platform/osx/export/codesign.cpp
msgid "Can't resize signature load command."
-msgstr ""
+msgstr "Impossibile ridimensionare il comando caricamento firma."
#: platform/osx/export/codesign.cpp
msgid "Failed to create fat binary."
-msgstr ""
+msgstr "Creazione del file binario fat fallito."
#: platform/osx/export/codesign.cpp
msgid "Unknown bundle type."
-msgstr ""
+msgstr "Tipo di bundle sconosciuto."
#: platform/osx/export/codesign.cpp
msgid "Unknown object type."
-msgstr ""
+msgstr "Tipo di oggetto sconosciuto."
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "App Category"
-msgstr "Categoria:"
+msgstr "Categoria Applicazione"
#: platform/osx/export/export.cpp
msgid "High Res"
-msgstr ""
+msgstr "Alta Risoluzione"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Location Usage Description"
-msgstr "Descrizione"
+msgstr "Descrizione d'uso Posizione"
#: platform/osx/export/export.cpp
msgid "Address Book Usage Description"
-msgstr ""
+msgstr "Descrizione d'uso Rubrica"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Calendar Usage Description"
-msgstr "Descrizione"
+msgstr "Descrizione d'uso Calendario"
#: platform/osx/export/export.cpp
#, fuzzy
@@ -19611,37 +19511,33 @@ msgid "Photos Library Usage Description"
msgstr "Descrizioni delle proprietà"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Desktop Folder Usage Description"
-msgstr "Descrizioni del metodo"
+msgstr "Descrizione d'uso Cartella Desktop"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Documents Folder Usage Description"
-msgstr "Descrizioni del metodo"
+msgstr "Descrizione d'uso Cartella Documenti"
#: platform/osx/export/export.cpp
msgid "Downloads Folder Usage Description"
-msgstr ""
+msgstr "Descrizione d'uso Cartella Downloads"
#: platform/osx/export/export.cpp
msgid "Network Volumes Usage Description"
-msgstr ""
+msgstr "Descrizione d'uso Volumi di Rete"
#: platform/osx/export/export.cpp
msgid "Removable Volumes Usage Description"
-msgstr ""
+msgstr "Descrizione d'uso Volumi Rimovibili"
#: platform/osx/export/export.cpp platform/windows/export/export.cpp
-#, fuzzy
msgid "Codesign"
-msgstr "Nodo"
+msgstr "Firma del codice"
#: platform/osx/export/export.cpp platform/uwp/export/export.cpp
#: platform/windows/export/export.cpp
-#, fuzzy
msgid "Identity"
-msgstr "Indenta"
+msgstr "Identità"
#: platform/osx/export/export.cpp platform/windows/export/export.cpp
#, fuzzy
@@ -19653,59 +19549,52 @@ msgid "Hardened Runtime"
msgstr ""
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Replace Existing Signature"
-msgstr "Sostituisci nei file"
+msgstr "Sostituisci firma esistente"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Entitlements"
-msgstr "Gizmos"
+msgstr "Permessi"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Custom File"
-msgstr "Taglia nodi"
+msgstr "File Personalizzato"
#: platform/osx/export/export.cpp
msgid "Allow JIT Code Execution"
-msgstr ""
+msgstr "Consenti l'esecuzione di codice JIT"
#: platform/osx/export/export.cpp
msgid "Allow Unsigned Executable Memory"
-msgstr ""
+msgstr "Consenti memoria eseguibile non firmata"
#: platform/osx/export/export.cpp
msgid "Allow Dyld Environment Variables"
-msgstr ""
+msgstr "Consenti variabili d'ambiente Dyld"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Disable Library Validation"
-msgstr "Pulsante disabilitato"
+msgstr "Disabilita Convalida Libreria"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Audio Input"
-msgstr "Aggiungi Input"
+msgstr "Ingresso Audio"
#: platform/osx/export/export.cpp
msgid "Address Book"
-msgstr ""
+msgstr "Rubrica"
#: platform/osx/export/export.cpp
msgid "Calendars"
-msgstr ""
+msgstr "Calendari"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Photos Library"
-msgstr "Esporta Libreria"
+msgstr "Libreria Foto"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Apple Events"
-msgstr "Aggiungi Evento"
+msgstr "Eventi Apple"
#: platform/osx/export/export.cpp
#, fuzzy
@@ -19714,60 +19603,51 @@ msgstr "Debug"
#: platform/osx/export/export.cpp
msgid "App Sandbox"
-msgstr ""
+msgstr "Applicazione Sandbox"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Network Server"
-msgstr "Peer di Rete"
+msgstr "Server di Rete"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Network Client"
-msgstr "Peer di Rete"
+msgstr "Client di Rete"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Device USB"
-msgstr "Dispositivo"
+msgstr "Dispositivo USB"
#: platform/osx/export/export.cpp
msgid "Device Bluetooth"
-msgstr ""
+msgstr "Dispositivo Bluetooth"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Files Downloads"
-msgstr "Scarica"
+msgstr "File scaricati"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Files Pictures"
-msgstr "Funzionalità"
+msgstr "File Immagini"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Files Music"
-msgstr "Files"
+msgstr "File Audio"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Files Movies"
-msgstr "Filtra tiles"
+msgstr "File Video"
#: platform/osx/export/export.cpp platform/windows/export/export.cpp
-#, fuzzy
msgid "Custom Options"
-msgstr "Opzioni Bus"
+msgstr "Opzioni personalizzate"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Notarization"
-msgstr "Localizzazione"
+msgstr "Autenticazione"
#: platform/osx/export/export.cpp
msgid "Apple ID Name"
-msgstr ""
+msgstr "Nome Apple ID"
#: platform/osx/export/export.cpp
#, fuzzy
@@ -19789,9 +19669,8 @@ msgid "Could not start xcrun executable."
msgstr "Impossibile avviare l'eseguibile xcrun."
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Notarization failed."
-msgstr "Localizzazione"
+msgstr "Autenticazione fallita."
#: platform/osx/export/export.cpp
msgid "Notarization request UUID: \"%s\""
@@ -19802,22 +19681,30 @@ msgid ""
"The notarization process generally takes less than an hour. When the process "
"is completed, you'll receive an email."
msgstr ""
+"Il processo di autenticazione impiega generalmente meno di un'ora. Riceverai "
+"una email quando il processo sarà concluso."
#: platform/osx/export/export.cpp
msgid ""
"You can check progress manually by opening a Terminal and running the "
"following command:"
msgstr ""
+"Puoi controllare manualmente l'avanzamento aprendo il Terminale e lanciando "
+"il seguente comando:"
#: platform/osx/export/export.cpp
msgid ""
"Run the following command to staple the notarization ticket to the exported "
"application (optional):"
msgstr ""
+"Lancia il seguente comando per agganciare il ticket di notarizzazione "
+"all'applicazione esportata (opzionale):"
#: platform/osx/export/export.cpp
msgid "Timestamping is not compatible with ad-hoc signature, and was disabled!"
msgstr ""
+"La visualizzazione dell'orario non è compatibile con la firma ad-hoc, ed è "
+"stata disabilitata!"
#: platform/osx/export/export.cpp
msgid ""
@@ -19826,17 +19713,19 @@ msgstr ""
#: platform/osx/export/export.cpp
msgid "Built-in CodeSign failed with error \"%s\"."
-msgstr ""
+msgstr "Firma del codice incorporata fallita con errore \"%s\"."
#: platform/osx/export/export.cpp
msgid "Built-in CodeSign require regex module."
-msgstr ""
+msgstr "La firma del codice incorporata richiede il modulo regex."
#: platform/osx/export/export.cpp
msgid ""
"Could not start codesign executable, make sure Xcode command line tools are "
"installed."
msgstr ""
+"Non è stato possibile lanciare l'eseguibile di firma del codice, controllare "
+"che gli strumenti da linea di comando di Xcode siano installati."
#: platform/osx/export/export.cpp platform/windows/export/export.cpp
#, fuzzy
@@ -19851,11 +19740,12 @@ msgstr "Errore nel salvataggio del file: %s"
#: platform/osx/export/export.cpp
msgid "Relative symlinks are not supported, exported \"%s\" might be broken!"
msgstr ""
+"I link simbolici relativi non sono supportati, \"%s\" esportato potrebbe "
+"essere danneggiato!"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "DMG Creation"
-msgstr "Direzione"
+msgstr "Creazione del DMG"
#: platform/osx/export/export.cpp
#, fuzzy
@@ -19864,79 +19754,83 @@ msgstr "Impossibile avviare l'eseguibile hdiutil."
#: platform/osx/export/export.cpp
msgid "`hdiutil create` failed - file exists."
-msgstr ""
+msgstr "`hdutil create` fallito - Il file già esiste."
#: platform/osx/export/export.cpp
msgid "`hdiutil create` failed."
-msgstr ""
+msgstr "`hdutil create` fallito."
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Creating app bundle"
-msgstr "Creando la miniatura"
+msgstr "Creando il pacchetto dell'app"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Could not find template app to export: \"%s\"."
-msgstr "Impossibile trovare il template dell'app per l'esportazione:"
+msgstr "Impossibile trovare il template dell'app per l'esportazione:\"%s\"."
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Invalid export format."
-msgstr "Template di esportazione non valido:"
+msgstr "Formato di esportazione invalido."
#: platform/osx/export/export.cpp
msgid ""
"Relative symlinks are not supported on this OS, the exported project might "
"be broken!"
msgstr ""
+"I link simbolici relativi non sono supportati in questo Sistema Operativo, "
+"il progetto esportato potrebbe essere danneggiato!"
#: platform/osx/export/export.cpp
msgid ""
"Requested template binary \"%s\" not found. It might be missing from your "
"template archive."
msgstr ""
+"Il modello di eseguibile \"%s\" richiesto non è stato trovato. Potrebbe "
+"essere mancante dal tuo archivio dei modelli."
#: platform/osx/export/export.cpp
msgid "Making PKG"
-msgstr ""
+msgstr "Creando il PKG"
#: platform/osx/export/export.cpp
msgid ""
"Ad-hoc signed applications require the 'Disable Library Validation' "
"entitlement to load dynamic libraries."
msgstr ""
+"Le applicazioni firmate ad-hoc richiedono il permesso \"Disabilita verifica "
+"libreria\" per caricare le librerie dinamiche."
#: platform/osx/export/export.cpp
msgid "Code signing bundle"
-msgstr ""
+msgstr "Pacchetto di firma del codice"
#: platform/osx/export/export.cpp
msgid "Making DMG"
-msgstr ""
+msgstr "Creando il DMG"
#: platform/osx/export/export.cpp
msgid "Code signing DMG"
-msgstr ""
+msgstr "Firmando il codice DMG"
#: platform/osx/export/export.cpp
msgid "Making ZIP"
-msgstr ""
+msgstr "Creando lo ZIP"
#: platform/osx/export/export.cpp
msgid ""
"Notarization requires the app to be archived first, select the DMG or ZIP "
"export format instead."
msgstr ""
+"La notarizazzione richiede che l'app sia prima archiviata, seleziona invece "
+"il formato di esportazione DMG o ZIP."
#: platform/osx/export/export.cpp
msgid "Sending archive for notarization"
-msgstr ""
+msgstr "Inviando l'archivio per l'autenticazione"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "ZIP Creation"
-msgstr "Proiezione"
+msgstr "Creazione dello ZIP"
#: platform/osx/export/export.cpp
#, fuzzy
@@ -19952,16 +19846,22 @@ msgid ""
"Warning: Built-in \"codesign\" is selected in the Editor Settings. Code "
"signing is limited to ad-hoc signature only."
msgstr ""
+"Warning: \"firma del codice\" integrato è selezionato nelle impostazioni "
+"dell'editor. La firma del codice è limitata solo alle firme ad-hoc."
#: 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 ""
+"Warning: gli strumenti da linea di comando di Xcode non sono installati, "
+"usando la \"firma del codice\" integrata. La firma del codice è limitata "
+"solo alle firme ad-hoc."
#: platform/osx/export/export.cpp
msgid "Notarization: Notarization with an ad-hoc signature is not supported."
msgstr ""
+"Autenticazione: L'autenticazione con una firma ad-hoc non è supportata."
#: platform/osx/export/export.cpp
#, fuzzy
@@ -19991,12 +19891,16 @@ msgid ""
"Warning: Notarization is disabled. The exported project will be blocked by "
"Gatekeeper if it's downloaded from an unknown source."
msgstr ""
+"Warning: l'autenticazione è disabilitata. Il progetto esportato sarà "
+"bloccato dal Gatekeeper is è scaricato da una sorgente sconosciuta."
#: 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 firma del codice è disabilitata. Il progetto esportato non verrà eseguito "
+"su Mac con Gatekeeper abilitato e Mac alimentati da Apple Silicon."
#: platform/osx/export/export.cpp
msgid ""
@@ -20008,23 +19912,32 @@ msgstr ""
msgid ""
"Timestamping is not compatible with ad-hoc signature, and will be disabled!"
msgstr ""
+"La stampa dell'ora non è compatibile con la firma ad-hoc, e sarà "
+"disabilitata!"
#: 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 ""
+"Warning: la notarizzazione non è supportata da questo Sistema Operativo. Il "
+"progetto esportato sarà bloccato da Gatekeeper se è scaricato da una "
+"sorgente sconosciuta."
#: platform/osx/export/export.cpp
msgid ""
"Privacy: Microphone access is enabled, but usage description is not "
"specified."
msgstr ""
+"Privacy: L'accesso al microfono è abilitato, ma la descrizione dell'uso non "
+"è specificata."
#: platform/osx/export/export.cpp
msgid ""
"Privacy: Camera access is enabled, but usage description is not specified."
msgstr ""
+"Privacy: L'accesso alla Camera è abilitato, ma la descrizione d'uso non è "
+"specificata."
#: platform/osx/export/export.cpp
msgid ""
@@ -20062,6 +19975,7 @@ msgid "Architecture"
msgstr "Architettura"
#: platform/uwp/export/export.cpp
+#, fuzzy
msgid "Display Name"
msgstr "Nome Display"
@@ -20123,7 +20037,7 @@ msgstr "Cambia espressione"
#: platform/uwp/export/export.cpp
msgid "Landscape"
-msgstr ""
+msgstr "Panorama"
#: platform/uwp/export/export.cpp
#, fuzzy
@@ -20200,6 +20114,7 @@ msgid "Invalid package unique name."
msgstr "Nome univoco del pacchetto non valido."
#: platform/uwp/export/export.cpp
+#, fuzzy
msgid "Invalid package publisher display name."
msgstr "Nome visualizzato del publisher del pacchetto invalido."
@@ -20262,9 +20177,8 @@ msgid "UWP"
msgstr "UWP"
#: platform/uwp/export/export.cpp platform/windows/export/export.cpp
-#, fuzzy
msgid "Signtool"
-msgstr "Signtool"
+msgstr "Strumento di segno"
#: platform/uwp/export/export.cpp
msgid "Debug Certificate"
@@ -20440,7 +20354,7 @@ msgstr "Osslsigncode"
#: platform/windows/export/export.cpp
msgid "Wine"
-msgstr "Wine"
+msgstr "Vino"
#: platform/x11/export/export.cpp
msgid "32-bit executables cannot have embedded data >= 4 GiB."
@@ -20458,13 +20372,13 @@ msgid ""
"order for AnimatedSprite to display frames."
msgstr ""
"Una risorsa SpriteFrames deve essere creata o impostata nella proprietà "
-"\"Frames\" per permettere a AnimatedSprite di visualizzare i frame."
+"\"Frames\" per permettere all'AnimatedSprite di visualizzare i frame."
#: 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 "Scala"
+msgstr "Scala della velocità"
#: scene/2d/animated_sprite.cpp scene/2d/audio_stream_player_2d.cpp
#: scene/3d/audio_stream_player_3d.cpp scene/3d/sprite_3d.cpp
@@ -20516,7 +20430,7 @@ msgstr "Genera punti"
#: scene/2d/area_2d.cpp scene/3d/area.cpp
#, fuzzy
msgid "Gravity Distance Scale"
-msgstr "Istanza"
+msgstr "Scala della distanza della gravità"
#: scene/2d/area_2d.cpp scene/3d/area.cpp
#, fuzzy
@@ -20559,7 +20473,7 @@ msgstr "Volume"
#: servers/audio/effects/audio_effect_pitch_shift.cpp
#, fuzzy
msgid "Pitch Scale"
-msgstr "Scala"
+msgstr "Scala del 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
@@ -21389,7 +21303,6 @@ msgid "Antialiased"
msgstr "Inizializza"
#: scene/2d/multimesh_instance_2d.cpp scene/3d/multimesh_instance.cpp
-#, fuzzy
msgid "Multimesh"
msgstr "Multimesh"
@@ -21484,7 +21397,6 @@ msgstr ""
"poligono."
#: scene/2d/navigation_polygon.cpp
-#, fuzzy
msgid "Navpoly"
msgstr "Navpoly"
@@ -21530,7 +21442,7 @@ msgstr "Scatti relativi"
#: scene/2d/parallax_background.cpp scene/gui/scroll_container.cpp
#: scene/resources/default_theme/default_theme.cpp
msgid "Scroll"
-msgstr ""
+msgstr "Scorrere"
#: scene/2d/parallax_background.cpp
#, fuzzy
@@ -21841,7 +21753,7 @@ msgstr ""
#: scene/2d/polygon_2d.cpp
msgid "Invert"
-msgstr ""
+msgstr "Invertire"
#: scene/2d/polygon_2d.cpp
#, fuzzy
@@ -21921,12 +21833,10 @@ msgstr ""
"Skeleton2D e impostane una."
#: scene/2d/sprite.cpp scene/3d/sprite_3d.cpp
-#, fuzzy
msgid "Hframes"
msgstr "Hframes"
#: scene/2d/sprite.cpp scene/3d/sprite_3d.cpp
-#, fuzzy
msgid "Vframes"
msgstr "Vframes"
@@ -22328,9 +22238,8 @@ msgid "Projection"
msgstr "Proiezione"
#: scene/3d/camera.cpp
-#, fuzzy
msgid "FOV"
-msgstr "FOV"
+msgstr "Campo Visivo"
#: scene/3d/camera.cpp
#, fuzzy
@@ -22530,7 +22439,6 @@ msgstr ""
"Per rimuovere questo avviso, disattiva la proprietà Compress di GIProbe."
#: scene/3d/gi_probe.cpp
-#, fuzzy
msgid "Subdiv"
msgstr "Subdiv"
@@ -22597,9 +22505,8 @@ msgstr "Forza Modulazione Bianca"
#: 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 "Font"
+msgstr "Carattere"
#: scene/3d/label_3d.cpp scene/resources/primitive_meshes.cpp
#, fuzzy
@@ -22683,7 +22590,6 @@ msgid "Depth Range"
msgstr "Profondità"
#: scene/3d/light.cpp
-#, fuzzy
msgid "Omni"
msgstr "Omni"
@@ -23758,6 +23664,16 @@ msgstr "Errore"
msgid "AABB"
msgstr ""
+#: scene/3d/visual_instance.cpp
+#, fuzzy
+msgid "Sorting"
+msgstr "Ordina"
+
+#: scene/3d/visual_instance.cpp
+#, fuzzy
+msgid "Use AABB Center"
+msgstr "Usa Ambiente"
+
#: scene/3d/visual_instance.cpp scene/resources/navigation_mesh.cpp
#, fuzzy
msgid "Geometry"
@@ -24241,6 +24157,7 @@ msgid "Theme Overrides"
msgstr "Sovrascrizioni"
#: scene/gui/control.cpp
+#, fuzzy
msgid ""
"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\"."
@@ -24406,7 +24323,7 @@ msgstr "Mostra Ossa"
#: scene/gui/graph_edit.cpp scene/gui/text_edit.cpp
#: scene/resources/default_theme/default_theme.cpp
msgid "Minimap"
-msgstr ""
+msgstr "Minimappa"
#: scene/gui/graph_edit.cpp
msgid "Enable grid minimap."
@@ -25269,9 +25186,8 @@ msgid "Use 32 BPC Depth"
msgstr ""
#: scene/main/scene_tree.cpp
-#, fuzzy
msgid "Default Environment"
-msgstr "Mostra Ambiente"
+msgstr "Ambiente predefinito"
#: scene/main/scene_tree.cpp
msgid ""
@@ -27506,9 +27422,8 @@ msgid "Invalid comparison function for that type."
msgstr "Funzione di confronto non valida per quel tipo."
#: scene/resources/world.cpp
-#, fuzzy
msgid "Fallback Environment"
-msgstr "Mostra Ambiente"
+msgstr "Ambiente di ripiego"
#: scene/resources/world.cpp
#, fuzzy
@@ -27821,9 +27736,8 @@ msgid "Feed"
msgstr ""
#: servers/camera/camera_feed.cpp
-#, fuzzy
msgid "Is Active"
-msgstr "Prospettica"
+msgstr "È attiva"
#: servers/physics/space_sw.cpp servers/physics_2d/space_2d_sw.cpp
msgid "Sleep Threshold Linear"
diff --git a/editor/translations/ja.po b/editor/translations/ja.po
index 2570cb6288..dc17329ba7 100644
--- a/editor/translations/ja.po
+++ b/editor/translations/ja.po
@@ -43,13 +43,17 @@
# fadhliazhari <m.fadhliazhari@gmail.com>, 2022.
# Chia-Hsiang Cheng <cche0109@student.monash.edu>, 2022.
# meko <hirono.yoneyama@outlook.com>, 2022.
+# Fire Dingo <snowsable113@icloud.com>, 2022.
+# Narazaki Shuji <shujinarazaki@protonmail.com>, 2022.
+# ta ko <neji.cion@gmail.com>, 2022.
+# T K <kidaaam@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-09-27 21:37+0000\n"
-"Last-Translator: nitenook <admin@alterbaum.net>\n"
+"PO-Revision-Date: 2022-12-13 13:21+0000\n"
+"Last-Translator: T K <kidaaam@gmail.com>\n"
"Language-Team: Japanese <https://hosted.weblate.org/projects/godot-engine/"
"godot/ja/>\n"
"Language: ja\n"
@@ -57,7 +61,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.14.1\n"
+"X-Generator: Weblate 4.15-dev\n"
#: core/bind/core_bind.cpp main/main.cpp
msgid "Tablet Driver"
@@ -480,7 +484,6 @@ msgid "Pressure"
msgstr "圧力"
#: core/os/input_event.cpp
-#, fuzzy
msgid "Pen Inverted"
msgstr "ペンå転"
@@ -906,9 +909,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
@@ -1050,12 +1052,10 @@ msgid "Scale"
msgstr "スケール"
#: drivers/gles3/rasterizer_scene_gles3.cpp
-#, fuzzy
msgid "Follow Surface"
msgstr "サーフェスをフォローã™ã‚‹"
#: drivers/gles3/rasterizer_scene_gles3.cpp
-#, fuzzy
msgid "Weight Samples"
msgstr "é‡é‡ã‚µãƒ³ãƒ—ル"
@@ -1365,14 +1365,12 @@ msgid "Easing:"
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
msgid "Stream:"
@@ -1645,9 +1643,8 @@ msgid ""
msgstr "ã“ã®ã‚ªãƒ—ションã¯å˜ä¸€ãƒˆãƒ©ãƒƒã‚¯ã§ã®ãƒ™ã‚¸ã‚§ç·¨é›†ã§ã¯æ©Ÿèƒ½ã—ã¾ã›ã‚“。"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Anim Add RESET Keys"
-msgstr "ã‚¢ãƒ‹ãƒ¡ãƒ¼ã‚·ãƒ§ãƒ³ã‚­ãƒ¼ã®æ‹¡ç¸®"
+msgstr "リセットキーã®è¿½åŠ "
#: editor/animation_track_editor.cpp
msgid ""
@@ -3377,7 +3374,6 @@ msgid "ScanSources"
msgstr "スキャンソース"
#: editor/editor_file_system.cpp
-#, fuzzy
msgid ""
"There are multiple importers for different types pointing to file %s, import "
"aborted"
@@ -3600,14 +3596,12 @@ msgid "Checked"
msgstr "ãƒã‚§ãƒƒã‚¯æ¸ˆã¿"
#: editor/editor_inspector.cpp
-#, fuzzy
msgid "Draw Red"
-msgstr "ドローコール:"
+msgstr "èµ¤è‰²ã§æç”»"
#: editor/editor_inspector.cpp
-#, fuzzy
msgid "Keying"
-msgstr "実行"
+msgstr "キーイング"
#: editor/editor_inspector.cpp
msgid "Pin value"
@@ -4340,9 +4334,8 @@ msgid "Update Continuously"
msgstr "ç¶™ç¶šçš„ã«æ›´æ–°"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Update Vital Only"
-msgstr "マテリアルã®å¤‰æ›´:"
+msgstr "é‡è¦ãªå¤‰æ›´ç‚¹ã®ã¿ã‚’æ›´æ–°"
#: editor/editor_node.cpp
msgid "Localize Settings"
@@ -4377,12 +4370,10 @@ msgid "Auto Unfold Foreign Scenes"
msgstr "外部シーンã®è‡ªå‹•展開"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Horizontal Vector2 Editing"
msgstr "水平ベクトル2編集"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Horizontal Vector Types Editing"
msgstr "水平ベクトルタイプ編集"
@@ -5189,9 +5180,8 @@ 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
msgid "Edited Resource"
@@ -5297,7 +5287,6 @@ msgid "Dim Editor On Dialog Popup"
msgstr "ダイアログã®ãƒãƒƒãƒ—アップ時ã«ã‚¨ãƒ‡ã‚£ã‚¿ãƒ¼ã‚’è–„æš—ãã™ã‚‹"
#: editor/editor_settings.cpp main/main.cpp
-#, fuzzy
msgid "Low Processor Mode Sleep (µsec)"
msgstr "低プロセッサ モード スリープ (マイクロ秒)"
@@ -5307,16 +5296,14 @@ msgid "Unfocused Low Processor Mode Sleep (µsec)"
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 "ページã‚ãŸã‚Šã®æœ€å¤§é…列辞書項目数"
@@ -5347,7 +5334,6 @@ msgid "Contrast"
msgstr "コントラスト"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Relationship Line Opacity"
msgstr "関係線ã®ä¸é€æ˜Žåº¦"
@@ -5397,9 +5383,8 @@ msgid "Compress Binary Resources"
msgstr "ãƒã‚¤ãƒŠãƒªãƒªã‚½ãƒ¼ã‚¹ã®åœ§ç¸®"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Safe Save On Backup Then Rename"
-msgstr "ãƒãƒƒã‚¯ã‚¢ãƒƒãƒ—時ã«å®‰å…¨ã«ä¿å­˜ã—ã¦ã‹ã‚‰åå‰ã‚’変更ã™ã‚‹"
+msgstr "ãƒãƒƒã‚¯ã‚¢ãƒƒãƒ—ã¨ã—ã¦åå‰ã‚’変更ã—ã¦ã‹ã‚‰å®‰å…¨ã«ä¿å­˜ã™ã‚‹"
#: editor/editor_settings.cpp
msgid "File Dialog"
@@ -5434,9 +5419,8 @@ msgid "Auto Refresh Interval"
msgstr "自動リフレッシュã®é–“éš”"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Subresource Hue Tint"
-msgstr "サブリソース"
+msgstr "サブリソースã®è‰²ç›¸ãƒ»è‰²åˆã„"
#: editor/editor_settings.cpp
msgid "Color Theme"
@@ -5512,9 +5496,8 @@ 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"
@@ -5537,19 +5520,16 @@ msgid "Line Numbers Zero Padded"
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"
@@ -5564,23 +5544,20 @@ 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
msgid "Script List"
msgstr "スクリプト一覧"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Show Members Overview"
-msgstr "メンãƒãƒ¼æ¦‚è¦ã‚’表示"
+msgstr "クラスメンãƒãƒ¼ã®æ¦‚è¦ã‚’表示"
#: editor/editor_settings.cpp editor/plugins/script_editor_plugin.cpp
msgid "Files"
@@ -5611,9 +5588,8 @@ msgid "Create Signal Callbacks"
msgstr "シグナルã®ã‚³ãƒ¼ãƒ«ãƒãƒƒã‚¯ã‚’作æˆ"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Sort Members Outline Alphabetically"
-msgstr "メンãƒãƒ¼ã®ã‚¢ã‚¦ãƒˆãƒ©ã‚¤ãƒ³ã‚’アルファベット順ã«ä¸¦ã¹æ›¿ãˆã‚‹"
+msgstr "クラスメンãƒãƒ¼ã®æ¦‚è¦ã‚’アルファベット順ã«ä¸¦ã¹ã‚‹"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
msgid "Cursor"
@@ -5643,7 +5619,7 @@ msgstr "å³ã‚¯ãƒªãƒƒã‚¯ã§ã‚­ãƒ£ãƒ¬ãƒƒãƒˆã‚’移動"
#: modules/gdscript/gdscript_editor.cpp
#: scene/resources/default_theme/default_theme.cpp
msgid "Completion"
-msgstr "完了"
+msgstr "自動補完"
#: editor/editor_settings.cpp
msgid "Idle Parse Delay"
@@ -5670,9 +5646,8 @@ msgid "Complete File Paths"
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"
@@ -5699,9 +5674,8 @@ 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
msgid "Preview Size"
@@ -5749,9 +5723,8 @@ msgid "Shape"
msgstr "シェイプ"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Primary Grid Steps"
-msgstr "グリッドã®ã‚¹ãƒ†ãƒƒãƒ—:"
+msgstr "プライマリグリッドã®ã‚¹ãƒ†ãƒƒãƒ—æ•°"
#: editor/editor_settings.cpp
msgid "Grid Size"
@@ -6899,14 +6872,12 @@ msgid "Collada"
msgstr "Collada"
#: editor/import/editor_import_collada.cpp
-#, fuzzy
msgid "Use Ambient"
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
@@ -6927,7 +6898,7 @@ msgstr "区切り文字"
#: editor/import/resource_importer_layered_texture.cpp
msgid "ColorCorrect"
-msgstr "ColorCorrect"
+msgstr "カラーコレクト"
#: editor/import/resource_importer_layered_texture.cpp
msgid "No BPTC If RGB"
@@ -6960,7 +6931,6 @@ msgstr "ミップマップ"
#: editor/import/resource_importer_layered_texture.cpp
#: editor/import/resource_importer_texture.cpp
-#, fuzzy
msgid "Anisotropic"
msgstr "異方性"
@@ -6992,9 +6962,8 @@ msgid "Generate Tangents"
msgstr "接線を生æˆ"
#: editor/import/resource_importer_obj.cpp
-#, fuzzy
msgid "Scale Mesh"
-msgstr "スケールモード"
+msgstr "スケールメッシュ"
#: editor/import/resource_importer_obj.cpp
msgid "Offset Mesh"
@@ -7002,14 +6971,12 @@ msgstr "メッシュã®ã‚ªãƒ•セット"
#: 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 "メッシュ最é©åŒ–フラグ"
#: editor/import/resource_importer_scene.cpp
msgid "Import as Single Scene"
@@ -7069,9 +7036,8 @@ msgid "Root Scale"
msgstr "ルートã®ã‚¹ã‚±ãƒ¼ãƒ«"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Custom Script"
-msgstr "ノードを切りå–ã‚‹"
+msgstr "カスタムスクリプト"
#: editor/import/resource_importer_scene.cpp scene/resources/texture.cpp
msgid "Storage"
@@ -7086,28 +7052,24 @@ msgid "Materials"
msgstr "マテリアル"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Keep On Reimport"
-msgstr "å†ã‚¤ãƒ³ãƒãƒ¼ãƒˆ"
+msgstr "å†ã‚¤ãƒ³ãƒãƒ¼ãƒˆæ™‚ã«ä¿æŒ(Keep On Reimport)"
#: editor/import/resource_importer_scene.cpp modules/gltf/gltf_state.cpp
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 "ライトベーキング(Light Baking)"
#: 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"
@@ -7130,14 +7092,12 @@ 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 "オプティマイザー(Optimizer)"
#: editor/import/resource_importer_scene.cpp
#: editor/plugins/item_list_editor_plugin.cpp main/main.cpp
@@ -7155,19 +7115,16 @@ msgid "Enabled"
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
msgid "Remove Unused Tracks"
@@ -7197,9 +7154,8 @@ msgid "Generating Lightmaps"
msgstr "ライトマップã®ç”Ÿæˆ"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Generating for Mesh:"
-msgstr "メッシュã®ç”Ÿæˆ: "
+msgstr "メッシュã®ç”Ÿæˆ:"
#: editor/import/resource_importer_scene.cpp
msgid "Running Custom Script..."
@@ -7227,38 +7183,33 @@ msgid "Saving..."
msgstr "ä¿å­˜ä¸­..."
#: editor/import/resource_importer_texture.cpp
-#, fuzzy
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ã§æ³•線マップã¨ã—ã¦ä½¿ç”¨ã•れã¦ã„るテクスãƒãƒ£ãŒæ¤œå‡ºã•れã¾ã—ãŸã€‚赤緑テクス"
-"ãƒãƒ£åœ§ç¸®ã‚’有効ã«ã—ã¦ãƒ¡ãƒ¢ãƒªä½¿ç”¨é‡ã‚’削減ã—ã¾ã™ï¼ˆé’ãƒãƒ£ãƒ³ãƒãƒ«ã¯ã™ã§ã«ç ´æ£„ã•れã¾"
-"ã—ãŸï¼‰ã€‚"
+"%s: 3Dã§æ³•線マップã¨ã—ã¦ä½¿ç”¨ã•れã¦ã„るテクスãƒãƒ£ãŒæ¤œå‡ºã•れã¾ã—ãŸã€‚赤ã¨ç·‘ã®ãƒ†"
+"クスãƒãƒ£åœ§ç¸®ã‚’有効ã«ã—ã¦ãƒ¡ãƒ¢ãƒªä½¿ç”¨é‡ã‚’削減ã—ã¾ã™ï¼ˆé’ãƒãƒ£ãƒ³ãƒãƒ«ã¯ç ´æ£„ã•れã¾"
+"ã™ï¼‰ã€‚"
#: editor/import/resource_importer_texture.cpp
-#, fuzzy
msgid ""
"%s: Texture detected as used in 3D. Enabling filter, repeat, mipmap "
"generation and VRAM texture compression."
msgstr ""
-"%s: 3Dã§ä½¿ç”¨ã•れã¦ã„るテクスãƒãƒ£ãŒæ¤œå‡ºã•れã¾ã—ãŸã€‚フィルターã€ç¹°ã‚Šè¿”ã—ã€ãƒŸãƒƒ"
-"プマップ生æˆã€VRAMテクスãƒãƒ£åœ§ç¸®ã‚’有効ã«ã—ã¾ã™ã€‚"
+"%s: 3Dã§ä½¿ç”¨ã•れるテクスãƒãƒ£ãŒæ¤œå‡ºã•れã¾ã—ãŸã€‚フィルターã€ç¹°ã‚Šè¿”ã—ã€ãƒŸãƒƒãƒ—"
+"マップ生æˆã€VRAMテクスãƒãƒ£åœ§ç¸®ã‚’有効ã«ã—ã¾ã™ã€‚"
#: editor/import/resource_importer_texture.cpp
-#, fuzzy
msgid "2D, Detect 3D"
msgstr "2Dã€3D検出"
#: editor/import/resource_importer_texture.cpp
-#, fuzzy
msgid "2D Pixel"
msgstr "2Dピクセル"
#: editor/import/resource_importer_texture.cpp scene/resources/texture.cpp
-#, fuzzy
msgid "Lossy Quality"
-msgstr "æå¤±ã®ã‚ã‚‹å“質"
+msgstr "éžå¯é€†å“質"
#: editor/import/resource_importer_texture.cpp
msgid "HDR Mode"
@@ -7276,12 +7227,10 @@ msgid "Normal Map"
msgstr "法線マップ"
#: editor/import/resource_importer_texture.cpp
-#, fuzzy
msgid "Process"
-msgstr "å‰å‡¦ç†"
+msgstr "プロセス"
#: editor/import/resource_importer_texture.cpp
-#, fuzzy
msgid "Fix Alpha Border"
msgstr "アルファボーダーを修正"
@@ -7296,21 +7245,18 @@ msgid "Hdr As Srgb"
msgstr "Srgbã¨ã—ã¦Hdr"
#: 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
msgid "Size Limit"
msgstr "サイズ制é™"
#: editor/import/resource_importer_texture.cpp
-#, fuzzy
msgid "Detect 3D"
msgstr "3Dを検出"
@@ -7335,19 +7281,16 @@ msgid "Import Mode"
msgstr "インãƒãƒ¼ãƒˆãƒ¢ãƒ¼ãƒ‰"
#: editor/import/resource_importer_texture_atlas.cpp
-#, fuzzy
msgid "Crop To Region"
-msgstr "タイル領域を設定"
+msgstr "領域ã«ã‚ã‚ã›ã¦ãƒˆãƒªãƒŸãƒ³ã‚°"
#: editor/import/resource_importer_texture_atlas.cpp
-#, fuzzy
msgid "Trim Alpha Border From Region"
-msgstr "アルファ境界線を領域ã‹ã‚‰ãƒˆãƒªãƒŸãƒ³ã‚°"
+msgstr "領域ã‹ã‚‰ã‚¢ãƒ«ãƒ•ァボーダーをトリミング"
#: 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"
@@ -7360,14 +7303,12 @@ msgid "Mono"
msgstr "Mono"
#: editor/import/resource_importer_wav.cpp
-#, fuzzy
msgid "Max Rate"
-msgstr "ミックス ノード"
+msgstr "最大レート"
#: editor/import/resource_importer_wav.cpp
-#, fuzzy
msgid "Max Rate Hz"
-msgstr "ミックス ノード"
+msgstr "最大レート(Hz)"
#: editor/import/resource_importer_wav.cpp
msgid "Trim"
@@ -12888,9 +12829,8 @@ msgid "This property can't be changed."
msgstr "ã“ã®ãƒ—ロパティã¯å¤‰æ›´ã§ãã¾ã›ã‚“。"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Snap Options"
-msgstr "スナッピングオプション"
+msgstr "スナップオプション"
#: editor/plugins/tile_set_editor_plugin.cpp scene/2d/animated_sprite.cpp
#: scene/2d/camera_2d.cpp scene/2d/cpu_particles_2d.cpp scene/2d/light_2d.cpp
@@ -12898,9 +12838,10 @@ msgstr "スナッピングオプション"
#: scene/2d/path_2d.cpp scene/2d/polygon_2d.cpp scene/2d/sprite.cpp
#: scene/3d/cpu_particles.cpp scene/3d/label_3d.cpp scene/3d/path.cpp
#: scene/3d/physics_body.cpp scene/3d/soft_body.cpp scene/3d/sprite_3d.cpp
-#: 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
+#: scene/3d/visual_instance.cpp 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
msgid "Offset"
msgstr "オフセット"
@@ -12913,14 +12854,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
@@ -12933,9 +12872,8 @@ msgid "Texture"
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
@@ -12945,18 +12883,16 @@ 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
msgid "Tile Mode"
msgstr "タイルモード"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Autotile Bitmask Mode"
-msgstr "ビットマスクモード"
+msgstr "オートタイル ビットマスクモード"
#: editor/plugins/tile_set_editor_plugin.cpp
msgid "Subtile Size"
@@ -12975,44 +12911,36 @@ msgid "Navigation Offset"
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 "BVHコリジョンマージン"
+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"
@@ -14094,6 +14022,8 @@ msgstr "定義ã•れãŸã™ã¹ã¦ã®ãƒ—リセットã®ãƒ—ロジェクトをエク
#: editor/project_export.cpp
msgid "All presets must have an export path defined for Export All to work."
msgstr ""
+"å…¨ã¦ã®ãƒ—リセットã¯ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆãŒå…¨ã¦æ©Ÿèƒ½ã™ã‚‹ãŸã‚ã«ã€ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆãƒ‘スを定義ã™"
+"ã‚‹å¿…è¦ãŒã‚りã¾ã™ã€‚"
#: editor/project_export.cpp
msgid "Delete preset '%s'?"
@@ -14312,16 +14242,17 @@ msgid "Invalid project path (changed anything?)."
msgstr "無効ãªãƒ—ロジェクトパスã§ã™ (ãªã«ã‹å¤‰æ›´ãŒã‚りã¾ã—ãŸã‹ï¼Ÿ)。"
#: editor/project_manager.cpp
+#, fuzzy
msgid ""
-"Couldn't load project.godot in project path (error %d). It may be missing or "
-"corrupted."
+"Couldn't load project at '%s' (error %d). It may be missing or corrupted."
msgstr ""
"プロジェクトパス㮠project.godot を読ã¿è¾¼ã‚ã¾ã›ã‚“ã§ã—ãŸã€‚ (エラー %d)。見ã¤ã‹"
"らãªã„ã‹ç ´æã—ã¦ã„ã‚‹å¯èƒ½æ€§ãŒã‚りã¾ã™ã€‚"
#: editor/project_manager.cpp
-msgid "Couldn't edit project.godot in project path."
-msgstr "プロジェクトパス㮠project.godot を編集ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚"
+#, fuzzy
+msgid "Couldn't save project at '%s' (error %d)."
+msgstr "次ã®å ´æ‰€ã®ãƒ—ロジェクトを開ã‘ã¾ã›ã‚“ '%s'。"
#: editor/project_manager.cpp
msgid "Couldn't create project.godot in project path."
@@ -15353,19 +15284,16 @@ msgid "Make Local"
msgstr "ローカルã«ã™ã‚‹"
#: editor/scene_tree_dock.cpp
-#, fuzzy
msgid "Enable Scene Unique Name(s)"
-msgstr "ノードå:"
+msgstr "シーン固有åを有効ã«ã™ã‚‹"
#: editor/scene_tree_dock.cpp
-#, fuzzy
msgid "Unique names already used by another node in the scene:"
-msgstr "ä»–ã®é–¢æ•°/変数/シグナルã«ã‚ˆã‚Šã™ã§ã«ä½¿ã‚れã¦ã„ã‚‹åå‰:"
+msgstr "固有åãŒã‚·ãƒ¼ãƒ³å†…ã®ä»–ã®ãƒŽãƒ¼ãƒ‰ã«æ—¢ã«ä½¿ã‚れã¦ã„ã¾ã™:"
#: editor/scene_tree_dock.cpp
-#, fuzzy
msgid "Disable Scene Unique Name(s)"
-msgstr "ノードå:"
+msgstr "シーン固有åを無効ã«ã™ã‚‹"
#: editor/scene_tree_dock.cpp
msgid "New Scene Root"
@@ -15441,7 +15369,7 @@ msgstr "サブリソース"
#: editor/scene_tree_dock.cpp
msgid "Access as Scene Unique Name"
-msgstr ""
+msgstr "シーン固有åã§ã‚¢ã‚¯ã‚»ã‚¹"
#: editor/scene_tree_dock.cpp
msgid "Clear Inheritance"
@@ -15541,18 +15469,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"
@@ -15567,9 +15493,8 @@ msgid "Button Group"
msgstr "ボタングループ"
#: editor/scene_tree_editor.cpp
-#, fuzzy
msgid "Disable Scene Unique Name"
-msgstr "ノードå:"
+msgstr "シーン固有åを無効ã«ã™ã‚‹"
#: editor/scene_tree_editor.cpp
msgid "(Connecting From)"
@@ -15592,7 +15517,7 @@ msgid ""
"Click to show signals dock."
msgstr ""
"ノードã«ã¯ %s 接続㨠%s グループãŒã‚りã¾ã™ã€‚\n"
-"クリックã™ã‚‹ã¨ã€ä¿¡å·ãƒ‰ãƒƒã‚¯ãŒè¡¨ç¤ºã•れã¾ã™ã€‚"
+"クリックã™ã‚‹ã¨ã€ã‚·ã‚°ãƒŠãƒ«ãƒ‰ãƒƒã‚¯ãŒè¡¨ç¤ºã•れã¾ã™ã€‚"
#: editor/scene_tree_editor.cpp
msgid ""
@@ -16422,7 +16347,7 @@ msgstr "ボーンを表示ã™ã‚‹"
#: main/main.cpp
msgid "Image"
-msgstr ""
+msgstr "ç”»åƒ"
#: main/main.cpp
msgid "Fullsize"
@@ -16446,7 +16371,7 @@ msgstr "Windowsã®ãƒã‚¤ãƒ†ã‚£ãƒ–アイコン"
#: main/main.cpp
msgid "Buffering"
-msgstr ""
+msgstr "ãƒãƒƒãƒ•ァリング"
#: main/main.cpp
msgid "Agile Event Flushing"
@@ -16618,7 +16543,7 @@ msgstr "ガイドを表示"
#: modules/csg/csg_shape.cpp
msgid "Cone"
-msgstr ""
+msgstr "円éŒ"
#: modules/csg/csg_shape.cpp
#, fuzzy
@@ -16922,14 +16847,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
@@ -16937,19 +16860,16 @@ 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
msgid "Sparse Count"
-msgstr "インスタンス"
+msgstr "スパースカウント"
#: modules/gltf/gltf_accessor.cpp
msgid "Sparse Indices Buffer View"
@@ -17016,12 +16936,11 @@ 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"
@@ -17032,14 +16951,12 @@ msgid "Outer Cone Angle"
msgstr ""
#: modules/gltf/gltf_mesh.cpp
-#, fuzzy
msgid "Blend Weights"
-msgstr "ライトマップを焼ã込む"
+msgstr "ブレンドウエイト"
#: modules/gltf/gltf_mesh.cpp
-#, fuzzy
msgid "Instance Materials"
-msgstr "マテリアルã®å¤‰æ›´:"
+msgstr "マテリアルインスタンス"
#: modules/gltf/gltf_node.cpp scene/3d/skeleton.cpp
msgid "Parent"
@@ -17074,7 +16991,7 @@ msgstr ""
#: modules/gltf/gltf_skeleton.cpp modules/gltf/gltf_state.cpp
msgid "Unique Names"
-msgstr ""
+msgstr "固有å"
#: modules/gltf/gltf_skeleton.cpp
#, fuzzy
@@ -17177,7 +17094,7 @@ msgstr "テクスãƒãƒ£"
#: modules/gltf/gltf_state.cpp platform/uwp/export/export.cpp
msgid "Images"
-msgstr ""
+msgstr "ç”»åƒ"
#: modules/gltf/gltf_state.cpp
msgid "Cameras"
@@ -17188,9 +17105,8 @@ msgid "Lights"
msgstr "ライト"
#: modules/gltf/gltf_state.cpp
-#, fuzzy
msgid "Unique Animation Names"
-msgstr "æ–°è¦ã‚¢ãƒ‹ãƒ¡ãƒ¼ã‚·ãƒ§ãƒ³å:"
+msgstr "固有アニメーションå"
#: modules/gltf/gltf_state.cpp
msgid "Skeletons"
@@ -17225,7 +17141,7 @@ msgstr "ライトマップを焼ã込む"
#: modules/gridmap/grid_map.cpp scene/2d/tile_map.cpp
msgid "Cell"
-msgstr ""
+msgstr "セル"
#: modules/gridmap/grid_map.cpp
#, fuzzy
@@ -17582,13 +17498,12 @@ msgid "Seamless"
msgstr "シームレス"
#: modules/opensimplex/noise_texture.cpp
-#, fuzzy
msgid "As Normal Map"
-msgstr "ランダムãªç¸®å°º:"
+msgstr "法線マップã¨ã—ã¦"
#: modules/opensimplex/noise_texture.cpp
msgid "Bump Strength"
-msgstr ""
+msgstr "ãƒãƒ³ãƒ—強度"
#: modules/opensimplex/noise_texture.cpp
msgid "Noise"
@@ -17607,9 +17522,8 @@ msgid "Period"
msgstr "周期"
#: modules/opensimplex/open_simplex_noise.cpp
-#, fuzzy
msgid "Persistence"
-msgstr "é€è¦–投影"
+msgstr "パーシステンス"
#: modules/opensimplex/open_simplex_noise.cpp
#, fuzzy
@@ -17622,7 +17536,6 @@ msgid "Subject"
msgstr "対象"
#: modules/regex/regex.cpp
-#, fuzzy
msgid "Names"
msgstr "åå‰"
@@ -18048,14 +17961,12 @@ msgid "Return"
msgstr "Return(戻り値)"
#: modules/visual_script/visual_script_flow_control.cpp
-#, fuzzy
msgid "Return Enabled"
-msgstr "実行å¯èƒ½"
+msgstr "æˆ»ã‚Šå€¤ãŒæœ‰åй"
#: modules/visual_script/visual_script_flow_control.cpp
-#, fuzzy
msgid "Return Type"
-msgstr "Return(戻り値)"
+msgstr "戻り値ã®åž‹"
#: modules/visual_script/visual_script_flow_control.cpp
#: scene/resources/visual_shader_nodes.cpp
@@ -18067,9 +17978,8 @@ msgid "if (cond) is:"
msgstr ""
#: modules/visual_script/visual_script_flow_control.cpp
-#, fuzzy
msgid "While"
-msgstr "一方"
+msgstr "〜ã®é–“(While)"
#: modules/visual_script/visual_script_flow_control.cpp
msgid "while (cond):"
@@ -18084,18 +17994,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"
@@ -18192,11 +18100,11 @@ msgstr ""
#: modules/visual_script/visual_script_func_nodes.cpp
msgid "ShiftLeft %s"
-msgstr ""
+msgstr "左シフト%s"
#: modules/visual_script/visual_script_func_nodes.cpp
msgid "ShiftRight %s"
-msgstr ""
+msgstr "å³ã‚·ãƒ•ト%s"
#: modules/visual_script/visual_script_func_nodes.cpp
msgid "BitAnd %s"
@@ -18255,9 +18163,8 @@ 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
msgid "Invalid argument of type:"
@@ -18336,9 +18243,8 @@ msgid "Get Self"
msgstr "自己"
#: modules/visual_script/visual_script_nodes.cpp
-#, fuzzy
msgid "CustomNode"
-msgstr "ノードを切りå–ã‚‹"
+msgstr "カスタムノード"
#: modules/visual_script/visual_script_nodes.cpp
msgid "Custom node has no _step() method, can't process graph."
@@ -18661,7 +18567,7 @@ msgstr "パッケージ"
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
msgid "Unique Name"
-msgstr "ユニークå"
+msgstr "固有å"
#: platform/android/export/export_plugin.cpp
msgid "Signed"
@@ -19020,7 +18926,6 @@ 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."
@@ -20964,19 +20869,17 @@ msgstr "æ–¹å‘"
#: scene/resources/particles_material.cpp
#: servers/audio/effects/audio_effect_reverb.cpp
msgid "Spread"
-msgstr ""
+msgstr "広ãŒã‚Š"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
-#, fuzzy
msgid "Initial Velocity"
-msgstr "åˆæœŸåŒ–"
+msgstr "åˆæœŸé€Ÿåº¦"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
-#, fuzzy
msgid "Velocity Random"
-msgstr "オービットビュー å³"
+msgstr "速度ランダム化"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp servers/physics_2d_server.cpp
@@ -20986,15 +20889,13 @@ msgstr ""
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
-#, fuzzy
msgid "Velocity Curve"
-msgstr "オービットビュー å³"
+msgstr "速度曲線"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
-#, fuzzy
msgid "Orbit Velocity"
-msgstr "オービットビュー å³"
+msgstr "オービット速度"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
@@ -21004,25 +20905,23 @@ 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
msgid "Accel Random"
-msgstr ""
+msgstr "加速度ランダム化"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
-#, fuzzy
msgid "Accel Curve"
-msgstr "曲線を分割ã™ã‚‹"
+msgstr "加速度曲線"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
msgid "Radial Accel"
-msgstr ""
+msgstr "角化速度"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
@@ -21051,7 +20950,7 @@ msgstr "曲線を分割ã™ã‚‹"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp scene/3d/light.cpp
#: scene/resources/particles_material.cpp
msgid "Angle"
-msgstr ""
+msgstr "角度"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
@@ -21121,21 +21020,18 @@ msgstr "スケール"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
-#, fuzzy
msgid "Speed Curve"
-msgstr "曲線を分割ã™ã‚‹"
+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
-#, fuzzy
msgid "Offset Curve"
-msgstr "曲線を閉ã˜ã‚‹"
+msgstr "オフセット曲線"
#: scene/2d/joints_2d.cpp
msgid "Node A and Node B must be PhysicsBody2Ds"
@@ -21333,7 +21229,7 @@ msgstr ""
#: scene/2d/line_2d.cpp
msgid "Round Precision"
-msgstr ""
+msgstr "丸ã‚精度"
#: scene/2d/line_2d.cpp scene/2d/polygon_2d.cpp
#: scene/resources/dynamic_font.cpp
@@ -21349,7 +21245,7 @@ msgstr ""
#: 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 "セルサイズ"
#: scene/2d/navigation_2d.cpp scene/3d/navigation.cpp
#, fuzzy
@@ -22023,7 +21919,7 @@ msgstr "ARVRCameraã¯ARVROriginãƒŽãƒ¼ãƒ‰ã‚’è¦ªã«æŒã¤å¿…è¦ãŒã‚りã¾ã™ã€‚"
#: scene/3d/arvr_nodes.cpp
msgid "Controller ID"
-msgstr ""
+msgstr "コントローラーID"
#: scene/3d/arvr_nodes.cpp servers/arvr/arvr_positional_tracker.cpp
msgid "Rumble"
@@ -22081,7 +21977,7 @@ msgstr ""
#: scene/3d/audio_stream_player_3d.cpp
msgid "Max dB"
-msgstr ""
+msgstr "最大dB"
#: scene/3d/audio_stream_player_3d.cpp
msgid "Out Of Range Mode"
@@ -22807,15 +22703,15 @@ msgstr "リニア"
#: scene/3d/physics_body.cpp
msgid "Angular X"
-msgstr ""
+msgstr "角度X"
#: scene/3d/physics_body.cpp
msgid "Angular Y"
-msgstr ""
+msgstr "角度Y"
#: scene/3d/physics_body.cpp
msgid "Angular Z"
-msgstr ""
+msgstr "角度Z"
#: scene/3d/physics_body.cpp
#, fuzzy
@@ -23026,7 +22922,7 @@ msgstr "Node A 㨠Node B ã¯ç•°ãªã‚‹ PhysicsBody ã§ãªã‘れã°ãªã‚Šã¾ã›ã‚
#: scene/3d/physics_joint.cpp
msgid "Solver"
-msgstr ""
+msgstr "ソルãƒãƒ¼"
#: scene/3d/physics_joint.cpp
#, fuzzy
@@ -23553,11 +23449,11 @@ msgstr ""
#: scene/3d/soft_body.cpp
msgid "Pressure Coefficient"
-msgstr ""
+msgstr "圧力係数"
#: scene/3d/soft_body.cpp
msgid "Damping Coefficient"
-msgstr ""
+msgstr "減衰係数"
#: scene/3d/soft_body.cpp
msgid "Drag Coefficient"
@@ -23604,7 +23500,7 @@ msgstr ""
#: scene/3d/sprite_3d.cpp scene/gui/graph_edit.cpp
msgid "Opacity"
-msgstr ""
+msgstr "ä¸é€æ˜Žåº¦"
#: scene/3d/sprite_3d.cpp scene/resources/material.cpp
#, fuzzy
@@ -23685,6 +23581,16 @@ msgstr "エラー"
msgid "AABB"
msgstr ""
+#: scene/3d/visual_instance.cpp
+#, fuzzy
+msgid "Sorting"
+msgstr "ソート"
+
+#: scene/3d/visual_instance.cpp
+#, fuzzy
+msgid "Use AABB Center"
+msgstr "アンビエントを使用"
+
#: scene/3d/visual_instance.cpp scene/resources/navigation_mesh.cpp
#, fuzzy
msgid "Geometry"
@@ -24265,7 +24171,7 @@ msgstr "テーマ プロパティ"
#: scene/gui/dialogs.cpp
msgid "Window Title"
-msgstr ""
+msgstr "ウィンドウタイトル"
#: scene/gui/dialogs.cpp
#, fuzzy
@@ -24355,7 +24261,7 @@ msgstr "コミット"
#: scene/gui/graph_node.cpp
msgid "Overlay"
-msgstr ""
+msgstr "オーãƒãƒ¼ãƒ¬ã‚¤"
#: scene/gui/grid_container.cpp scene/gui/item_list.cpp scene/gui/tree.cpp
#, fuzzy
@@ -24438,7 +24344,7 @@ msgstr ""
#: scene/gui/line_edit.cpp scene/resources/navigation_mesh.cpp
msgid "Max Length"
-msgstr ""
+msgstr "最大長"
#: scene/gui/line_edit.cpp
msgid "Secret"
@@ -24825,7 +24731,7 @@ msgstr ""
#: scene/gui/text_edit.cpp
msgid "Readonly"
-msgstr ""
+msgstr "読ã¿å–り専用"
#: scene/gui/text_edit.cpp
#, fuzzy
@@ -25344,14 +25250,12 @@ msgid "Clear Mode"
msgstr "定è¦ãƒ¢ãƒ¼ãƒ‰"
#: scene/main/viewport.cpp
-#, fuzzy
msgid "Enable 2D"
-msgstr "有効"
+msgstr "2D有効化"
#: scene/main/viewport.cpp
-#, fuzzy
msgid "Enable 3D"
-msgstr "有効"
+msgstr "3D有効化"
#: scene/main/viewport.cpp
#, fuzzy
@@ -25359,9 +25263,8 @@ msgid "Object Picking"
msgstr "オニオンスキンを有効ã«ã™ã‚‹"
#: scene/main/viewport.cpp
-#, fuzzy
msgid "Disable Input"
-msgstr "アイテムを無効ã«ã™ã‚‹"
+msgstr "入力無効化"
#: scene/main/viewport.cpp servers/visual_server.cpp
msgid "Shadow Atlas"
@@ -26310,11 +26213,11 @@ msgstr "データ付"
#: scene/resources/environment.cpp
msgid "Background"
-msgstr ""
+msgstr "背景"
#: scene/resources/environment.cpp scene/resources/sky.cpp
msgid "Sky"
-msgstr ""
+msgstr "空"
#: scene/resources/environment.cpp
#, fuzzy
@@ -26322,19 +26225,16 @@ msgid "Sky Custom FOV"
msgstr "ノードを切りå–ã‚‹"
#: scene/resources/environment.cpp
-#, fuzzy
msgid "Sky Orientation"
-msgstr "オンラインドキュメント"
+msgstr "ç©ºã®æ–¹å‘"
#: scene/resources/environment.cpp
-#, fuzzy
msgid "Sky Rotation"
-msgstr "回転ã®ã‚¹ãƒ†ãƒƒãƒ—:"
+msgstr "空ã®å›žè»¢"
#: scene/resources/environment.cpp
-#, fuzzy
msgid "Sky Rotation Degrees"
-msgstr "%s 度回転。"
+msgstr "空ã®å›žè»¢è§’度"
#: scene/resources/environment.cpp
msgid "Canvas Max Layer"
@@ -26497,7 +26397,7 @@ msgstr "UVãƒãƒ£ãƒ³ãƒãƒ« デãƒãƒƒã‚°"
#: scene/resources/environment.cpp
msgid "Blur"
-msgstr ""
+msgstr "ブラー"
#: scene/resources/environment.cpp
msgid "Edge Sharpness"
@@ -26564,7 +26464,7 @@ msgstr ""
#: scene/resources/environment.cpp
msgid "Bloom"
-msgstr ""
+msgstr "ブルーム"
#: scene/resources/environment.cpp
msgid "HDR Threshold"
@@ -26789,7 +26689,7 @@ msgstr ""
#: scene/resources/material.cpp
msgid "NormalMap"
-msgstr ""
+msgstr "法線マップ"
#: scene/resources/material.cpp
msgid "Rim"
@@ -28128,17 +28028,15 @@ 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
-#, fuzzy
msgid "Precision"
-msgstr "ãƒãƒ¼ã‚¸ãƒ§ãƒ³"
+msgstr "精度"
#: servers/visual_server.cpp
msgid "UV Contract"
diff --git a/editor/translations/ka.po b/editor/translations/ka.po
index f085051bf7..629afaa429 100644
--- a/editor/translations/ka.po
+++ b/editor/translations/ka.po
@@ -12951,9 +12951,10 @@ msgstr "მáƒáƒœáƒ˜áƒ¨áƒœáƒ£áƒšáƒ˜ მხáƒáƒšáƒáƒ“"
#: scene/2d/path_2d.cpp scene/2d/polygon_2d.cpp scene/2d/sprite.cpp
#: scene/3d/cpu_particles.cpp scene/3d/label_3d.cpp scene/3d/path.cpp
#: scene/3d/physics_body.cpp scene/3d/soft_body.cpp scene/3d/sprite_3d.cpp
-#: 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
+#: scene/3d/visual_instance.cpp 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
msgid "Offset"
msgstr ""
@@ -14349,12 +14350,11 @@ msgstr ""
#: editor/project_manager.cpp
msgid ""
-"Couldn't load project.godot in project path (error %d). It may be missing or "
-"corrupted."
+"Couldn't load project at '%s' (error %d). It may be missing or corrupted."
msgstr ""
#: editor/project_manager.cpp
-msgid "Couldn't edit project.godot in project path."
+msgid "Couldn't save project at '%s' (error %d)."
msgstr ""
#: editor/project_manager.cpp
@@ -23337,6 +23337,15 @@ msgstr "სáƒáƒ áƒ™áƒ”"
msgid "AABB"
msgstr ""
+#: scene/3d/visual_instance.cpp
+#, fuzzy
+msgid "Sorting"
+msgstr "გáƒáƒ“áƒáƒ¡áƒ•ლები"
+
+#: scene/3d/visual_instance.cpp
+msgid "Use AABB Center"
+msgstr ""
+
#: scene/3d/visual_instance.cpp scene/resources/navigation_mesh.cpp
msgid "Geometry"
msgstr ""
diff --git a/editor/translations/km.po b/editor/translations/km.po
index 3d39686d68..ade147ec7e 100644
--- a/editor/translations/km.po
+++ b/editor/translations/km.po
@@ -12389,9 +12389,10 @@ msgstr "Anim ផ្លាស់ប្ážáž¼ážš Transform"
#: scene/2d/path_2d.cpp scene/2d/polygon_2d.cpp scene/2d/sprite.cpp
#: scene/3d/cpu_particles.cpp scene/3d/label_3d.cpp scene/3d/path.cpp
#: scene/3d/physics_body.cpp scene/3d/soft_body.cpp scene/3d/sprite_3d.cpp
-#: 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
+#: scene/3d/visual_instance.cpp 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
msgid "Offset"
msgstr ""
@@ -13726,12 +13727,11 @@ msgstr ""
#: editor/project_manager.cpp
msgid ""
-"Couldn't load project.godot in project path (error %d). It may be missing or "
-"corrupted."
+"Couldn't load project at '%s' (error %d). It may be missing or corrupted."
msgstr ""
#: editor/project_manager.cpp
-msgid "Couldn't edit project.godot in project path."
+msgid "Couldn't save project at '%s' (error %d)."
msgstr ""
#: editor/project_manager.cpp
@@ -22256,6 +22256,14 @@ msgstr "កញ្ចក់"
msgid "AABB"
msgstr ""
+#: scene/3d/visual_instance.cpp
+msgid "Sorting"
+msgstr ""
+
+#: scene/3d/visual_instance.cpp
+msgid "Use AABB Center"
+msgstr ""
+
#: scene/3d/visual_instance.cpp scene/resources/navigation_mesh.cpp
msgid "Geometry"
msgstr ""
diff --git a/editor/translations/ko.po b/editor/translations/ko.po
index e1940d698c..f43830b1e9 100644
--- a/editor/translations/ko.po
+++ b/editor/translations/ko.po
@@ -39,13 +39,15 @@
# 박민규 <80dots@gmail.com>, 2022.
# ì´ì§€ë¯¼ <jiminaleejung@gmail.com>, 2022.
# nulltable <un5450@naver.com>, 2022.
+# Godoto <aicompose@gmail.com>, 2022.
+# gaenyang <gaenyang@outlook.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-09-23 04:16+0000\n"
-"Last-Translator: nulltable <un5450@naver.com>\n"
+"PO-Revision-Date: 2022-10-24 12:41+0000\n"
+"Last-Translator: Godoto <aicompose@gmail.com>\n"
"Language-Team: Korean <https://hosted.weblate.org/projects/godot-engine/"
"godot/ko/>\n"
"Language: ko\n"
@@ -53,7 +55,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.14.1\n"
+"X-Generator: Weblate 4.14.2-dev\n"
#: core/bind/core_bind.cpp main/main.cpp
msgid "Tablet Driver"
@@ -270,7 +272,7 @@ msgstr "ì²­í¬ í¬ê¸° ì½ê¸°"
#: core/io/marshalls.cpp
msgid "Object ID"
-msgstr "오브ì íЏ ID"
+msgstr "오브ì íЏ ì•„ì´ë””"
#: core/io/multiplayer_api.cpp core/io/packet_peer.cpp
msgid "Allow Object Decoding"
@@ -394,9 +396,8 @@ msgid "Mouse Mode"
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
@@ -479,7 +480,7 @@ msgstr "ì••ë ¥"
#: core/os/input_event.cpp
msgid "Pen Inverted"
-msgstr ""
+msgstr "펜 반전"
#: core/os/input_event.cpp
msgid "Relative"
@@ -682,11 +683,11 @@ msgstr "스í¬ë¦½íЏ 템플릿 검색 경로"
#: core/project_settings.cpp
msgid "Version Control Autoload On Startup"
-msgstr "시작할 때 ìžë™ìœ¼ë¡œ Version Control 로드"
+msgstr "시작 시 버전 관리 ìžë™ì‹¤í–‰"
#: core/project_settings.cpp
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
@@ -1606,7 +1607,7 @@ msgstr "변형"
#: editor/animation_track_editor.cpp editor/editor_help.cpp
msgid "Methods"
-msgstr "메서드"
+msgstr "방법"
#: editor/animation_track_editor.cpp
msgid "Bezier"
@@ -2071,7 +2072,7 @@ msgstr "\"%s\" 시그ë„ì˜ ëª¨ë“  ì—°ê²°ì„ ì œê±°í•˜ì‹œê² ìŠµë‹ˆê¹Œ?"
#: editor/connections_dialog.cpp editor/editor_help.cpp editor/node_dock.cpp
msgid "Signals"
-msgstr "시그ë„"
+msgstr "신호"
#: editor/connections_dialog.cpp
msgid "Filter signals"
@@ -2200,7 +2201,7 @@ msgstr "열기"
#: editor/dependency_editor.cpp
msgid "Owners of: %s (Total: %d)"
-msgstr ""
+msgstr "소유ìž: %s(ì´: %d)"
#: editor/dependency_editor.cpp
msgid ""
@@ -2756,16 +2757,15 @@ msgstr "ì„ íƒ"
#: editor/editor_export.cpp
msgid "Project export for platform:"
-msgstr "플랫í¼ìœ¼ë¡œ 프로ì íЏ 내보내기:"
+msgstr "플랫í¼ìš© 프로ì íЏ 내보내기:"
#: editor/editor_export.cpp
msgid "Completed with warnings."
msgstr "완료하였지만 경고가 있습니다."
#: editor/editor_export.cpp
-#, fuzzy
msgid "Completed successfully."
-msgstr "패키지를 성공ì ìœ¼ë¡œ 설치했습니다!"
+msgstr "성공ì ìœ¼ë¡œ 완료ë˜ì—ˆìŠµë‹ˆë‹¤."
#: editor/editor_export.cpp
msgid "Failed."
@@ -2921,9 +2921,8 @@ 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
msgid "The given export path doesn't exist."
@@ -2939,9 +2938,8 @@ 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."
@@ -3435,7 +3433,7 @@ msgstr "스타ì¼"
#: editor/editor_help.cpp
msgid "Enumerations"
-msgstr "열거형"
+msgstr "목ë¡"
#: editor/editor_help.cpp
msgid "Property Descriptions"
@@ -5472,7 +5470,7 @@ msgstr "ì„ íƒëœ í•­ëª©ì„ Drag and drop"
#: editor/editor_settings.cpp
msgid "Stay In Script Editor On Node Selected"
-msgstr ""
+msgstr "ì„ íƒí•œ 노드ì—서 스í¬ë¦½íЏ 편집기 유지"
#: editor/editor_settings.cpp
msgid "Appearance"
@@ -5774,7 +5772,7 @@ msgstr "줌 변경"
#: editor/editor_settings.cpp editor/plugins/spatial_editor_plugin.cpp
msgid "Warped Mouse Panning"
-msgstr ""
+msgstr "뒤틀린 마우스 패ë‹"
#: editor/editor_settings.cpp
msgid "Navigation Feel"
@@ -5782,56 +5780,47 @@ 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
msgid "Grid Color"
@@ -5867,98 +5856,89 @@ 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 "í´ë¦¬ê³¤ 2D 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
msgid "Auto Save"
@@ -5974,20 +5954,17 @@ 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"
@@ -5995,13 +5972,13 @@ 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
@@ -6019,28 +5996,27 @@ 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
msgid "String Color"
@@ -6057,35 +6033,32 @@ msgid "Completion Background Color"
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
msgid "Line Number Color"
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"
@@ -6096,93 +6069,82 @@ msgid "Caret Background Color"
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 "함수(Function)"
+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를 눌러 좀 ë” ì •ë°€í•˜ê²Œ 조작합니다."
+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"
@@ -6190,11 +6152,11 @@ msgstr "가져올 노드 ì„ íƒ"
#: editor/editor_sub_scene.cpp editor/project_manager.cpp
msgid "Browse"
-msgstr "íƒìƒ‰"
+msgstr "검색"
#: editor/editor_sub_scene.cpp
msgid "Scene Path:"
-msgstr "씬 경로:"
+msgstr "장면 경로:"
#: editor/editor_sub_scene.cpp
msgid "Import From Node:"
@@ -6202,13 +6164,12 @@ 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."
-msgstr "ì´ í…œí”Œë¦¿ì„ í¬í•¨í•˜ëŠ” í´ë”를 엽니다."
+msgstr "ì´ í…œí”Œë¦¿ì´ í¬í•¨ëœ í´ë”를 엽니다."
#: editor/export_template_manager.cpp
msgid "Uninstall these templates."
@@ -6220,11 +6181,11 @@ msgstr "사용 가능한 미러가 없습니다."
#: editor/export_template_manager.cpp
msgid "Retrieving the mirror list..."
-msgstr "미러 목ë¡ì„ 검색하는 중..."
+msgstr "미러 목ë¡ì„ 가져오는 중..."
#: editor/export_template_manager.cpp
msgid "Starting the download..."
-msgstr "다운로드를 시작하는 중..."
+msgstr "다운로드 시작 중..."
#: editor/export_template_manager.cpp
msgid "Error requesting URL:"
@@ -6232,11 +6193,11 @@ msgstr "URL 요청 중 오류:"
#: editor/export_template_manager.cpp
msgid "Connecting to the mirror..."
-msgstr "ë¯¸ëŸ¬ì— ì—°ê²° 중..."
+msgstr "미러 연결 중..."
#: editor/export_template_manager.cpp
msgid "Can't resolve the requested address."
-msgstr "ìš”ì²­ëœ ì£¼ì†Œë¥¼ í•´ê²°í•  수 없습니다."
+msgstr "요청한 주소를 확ì¸í•  수 없습니다."
#: editor/export_template_manager.cpp
msgid "Can't connect to the mirror."
@@ -6472,13 +6433,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"
@@ -6539,6 +6500,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 ""
@@ -6760,14 +6724,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..."
@@ -6840,43 +6802,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
@@ -6884,13 +6843,13 @@ 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
@@ -6900,14 +6859,13 @@ msgstr "í•„í„°"
#: editor/import/resource_importer_layered_texture.cpp
#: editor/import/resource_importer_texture.cpp
-#, fuzzy
msgid "Mipmaps"
-msgstr "시그ë„"
+msgstr "밉맵"
#: 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
@@ -6915,9 +6873,8 @@ msgid "sRGB"
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
@@ -6934,14 +6891,12 @@ msgid "Vertical"
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
msgid "Offset Mesh"
@@ -6949,9 +6904,8 @@ msgstr "오프셋 메시"
#: editor/import/resource_importer_obj.cpp
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Octahedral Compression"
-msgstr "í‘œí˜„ì‹ ì„¤ì •"
+msgstr "팔면체 압축"
#: editor/import/resource_importer_obj.cpp
msgid "Optimize Mesh Flags"
@@ -6999,100 +6953,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
msgid "Materials"
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 "메시"
+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 "스킨"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Use Named Skins"
-msgstr "ìŠ¤ì¼€ì¼ ìŠ¤ëƒ… 사용"
+msgstr "네임드 스킨 사용"
#: 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 "스í¬ë¦½íЏ í•„í„°"
+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
@@ -7106,9 +7044,8 @@ 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
msgid "Max Linear Error"
@@ -7119,19 +7056,16 @@ msgid "Max Angular Error"
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 "애니메ì´ì…˜ í´ë¦½"
+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
@@ -7185,64 +7119,63 @@ 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ì—서 ì‚¬ìš©ëœ ê²ƒìœ¼ë¡œ ê°ì§€ë˜ì—ˆìŠµë‹ˆë‹¤. í•„í„°, 반복, 밉맵 ìƒì„± ë° "
+"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 "알파 í…Œë‘리 수정"
#: editor/import/resource_importer_texture.cpp
-#, fuzzy
msgid "Premult Alpha"
-msgstr "í´ë¦¬ê³¤ 편집"
+msgstr "프리멀트 알파"
#: editor/import/resource_importer_texture.cpp
msgid "Hdr As Srgb"
-msgstr ""
+msgstr "Srgb로 HDR"
#: editor/import/resource_importer_texture.cpp
-#, fuzzy
msgid "Invert Color"
-msgstr "ê¼­ì§“ì "
+msgstr "ìƒ‰ìƒ ë°˜ì „"
#: editor/import/resource_importer_texture.cpp
msgid "Normal Map Invert Y"
@@ -7254,18 +7187,19 @@ 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
msgid "Atlas File"
@@ -7276,65 +7210,57 @@ msgid "Import Mode"
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 "ì˜ì—­ì—서 알파 í…Œë‘리 ìžë¥´ê¸°"
#: 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/godotsharp_dirs.cpp
#: modules/mono/mono_gd/gd_mono.cpp
msgid "Mono"
-msgstr ""
+msgstr "모노"
#: editor/import/resource_importer_wav.cpp
-#, fuzzy
msgid "Max Rate"
-msgstr "믹스 노드"
+msgstr "최대 비율"
#: editor/import/resource_importer_wav.cpp
-#, fuzzy
msgid "Max Rate Hz"
-msgstr "믹스 노드"
+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"
@@ -7346,7 +7272,7 @@ msgstr "ìž„í¬í„°:"
#: editor/import_defaults_editor.cpp
msgid "Reset to Defaults"
-msgstr "ë””í´íŠ¸ë¡œ 재설정"
+msgstr "기본값으로 재설정"
#: editor/import_dock.cpp
msgid "Keep File (No Import)"
@@ -7358,11 +7284,11 @@ msgstr "íŒŒì¼ %dê°œ"
#: editor/import_dock.cpp
msgid "Set as Default for '%s'"
-msgstr "'%s'ì„(를) ë””í´íŠ¸ë¡œ 설정"
+msgstr "기본값으로 '%s' 설정"
#: editor/import_dock.cpp
msgid "Clear Default for '%s'"
-msgstr "'%s'ì„(를) ë””í´íЏì—서 지우기"
+msgstr "'%s'ì˜ ê¸°ë³¸ê°’ 지우기"
#: editor/import_dock.cpp
msgid "Reimport"
@@ -7382,55 +7308,54 @@ msgstr ""
#: editor/import_dock.cpp
msgid "Import As:"
-msgstr "ë‹¤ìŒ í˜•ì‹ìœ¼ë¡œ 가져오기:"
+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."
-msgstr "가져온 파ì¼ì˜ íƒ€ìž…ì„ ë°”ê¾¸ë ¤ë©´ ì—디터를 다시 시작해야 합니다."
+msgstr "가져온 파ì¼ì˜ ìœ í˜•ì„ ë³€ê²½í•˜ë ¤ë©´ 편집기를 다시 시작해야 합니다."
#: editor/import_dock.cpp
msgid ""
"WARNING: Assets exist that use this resource, they may stop loading properly."
msgstr ""
-"경고: ì´ ë¦¬ì†ŒìŠ¤ë¥¼ 사용하는 ì• ì…‹ì´ ìžˆìŠµë‹ˆë‹¤. ì •ìƒì ìœ¼ë¡œ 불러오지 못할 ìˆ˜ë„ ìžˆ"
-"습니다."
+"경고: ì´ ë¦¬ì†ŒìŠ¤ë¥¼ 사용하는 ì• ì…‹ì´ ìžˆìŠµë‹ˆë‹¤. ì •ìƒì ìœ¼ë¡œ 불러오지 못할 수 있습"
+"니다."
#: editor/import_dock.cpp
msgid ""
"Select a resource file in the filesystem or in the inspector to adjust "
"import settings."
msgstr ""
+"íŒŒì¼ ì‹œìŠ¤í…œ ë˜ëŠ” 검사기ì—서 리소스 파ì¼ì„ ì„ íƒí•˜ì—¬ 가져오기 ì„¤ì •ì„ ì¡°ì •í•˜ì‹­ì‹œ"
+"오."
#: editor/inspector_dock.cpp
msgid "Failed to load resource."
-msgstr "리소스 ë¶ˆëŸ¬ì˜¤ê¸°ì— ì‹¤íŒ¨í–ˆìŠµë‹ˆë‹¤."
+msgstr "리소스를 불러오지 못했습니다."
#: editor/inspector_dock.cpp
-#, fuzzy
msgid "Property Name Style"
-msgstr "프로ì íЏ ì´ë¦„:"
+msgstr "ì†ì„± ì´ë¦„ 스타ì¼"
#: editor/inspector_dock.cpp scene/gui/color_picker.cpp
msgid "Raw"
-msgstr "Raw"
+msgstr "RAW"
#: 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"
@@ -7973,9 +7898,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..."
@@ -8303,7 +8227,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:"
@@ -8430,9 +8354,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!"
@@ -8467,28 +8390,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 "ì´ì „"
#: editor/plugins/asset_library_editor_plugin.cpp
-#, fuzzy
msgctxt "Pagination"
msgid "Next"
msgstr "다ìŒ"
#: editor/plugins/asset_library_editor_plugin.cpp
-#, fuzzy
msgctxt "Pagination"
msgid "Last"
-msgstr "ë으로"
+msgstr "마지막"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "All"
@@ -8536,7 +8455,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"
@@ -8592,7 +8511,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:"
@@ -8902,9 +8821,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."
@@ -8937,7 +8855,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
@@ -9036,9 +8954,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
@@ -9047,9 +8964,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
@@ -9058,9 +8974,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
@@ -9069,9 +8984,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"
@@ -9096,23 +9010,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
@@ -9463,16 +9374,15 @@ msgstr "기울기 편집ë¨"
#: editor/plugins/gradient_texture_2d_editor_plugin.cpp
msgid "Swap GradientTexture2D Fill Points"
-msgstr ""
+msgstr "ê·¸ë¼ë””언트í…스처2D 채우기 í¬ì¸íЏ êµì²´"
#: editor/plugins/gradient_texture_2d_editor_plugin.cpp
msgid "Swap Gradient Fill Points"
-msgstr ""
+msgstr "ê·¸ë¼ë””언트 채우기 í¬ì¸íЏ êµì²´"
#: 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
@@ -9491,13 +9401,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"
@@ -9730,9 +9639,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"
@@ -9755,14 +9663,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)."
@@ -10286,7 +10192,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!"
@@ -10617,57 +10523,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
msgid "Current Script Background Color"
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"
@@ -10823,9 +10723,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"
@@ -11029,15 +10928,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."
@@ -11185,13 +11082,14 @@ 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 ""
+"디버그 그리기 모드는 GLES2ê°€ 아닌 GLES3 ë Œë”러를 사용할 때만 사용할 수 있습니"
+"다."
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Freelook Left"
@@ -11354,16 +11252,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"
@@ -11484,16 +11381,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"
@@ -11544,9 +11440,8 @@ msgid "Invalid geometry, can't replace by mesh."
msgstr "ìž˜ëª»ëœ ì§€ì˜¤ë©”íŠ¸ë¦¬. 메시로 대체할 수 없습니다."
#: editor/plugins/sprite_editor_plugin.cpp
-#, fuzzy
msgid "Convert to MeshInstance2D"
-msgstr "Mesh2D로 변환"
+msgstr "메쉬ì¸ìŠ¤í„´ìŠ¤2D로 변환"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Invalid geometry, can't create polygon."
@@ -11577,19 +11472,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"
@@ -11652,9 +11544,8 @@ msgid "New Animation"
msgstr "새 애니메ì´ì…˜"
#: editor/plugins/sprite_frames_editor_plugin.cpp
-#, fuzzy
msgid "Filter animations"
-msgstr "메서드 필터"
+msgstr "애니메ì´ì…˜ í•„í„°ë§"
#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Speed:"
@@ -11953,9 +11844,8 @@ msgstr ""
"무시하고 닫으시겠습니까?"
#: editor/plugins/theme_editor_plugin.cpp
-#, fuzzy
msgid "Remove Type"
-msgstr "íƒ€ì¼ ì œê±°"
+msgstr "유형 제거"
#: editor/plugins/theme_editor_plugin.cpp
msgid ""
@@ -11998,14 +11888,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"
@@ -12120,9 +12008,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"
@@ -12134,22 +12021,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"
@@ -12180,14 +12064,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"
@@ -12207,13 +12089,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:"
@@ -12450,55 +12332,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 "팔레트 항목 H 분리"
#: 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 "íƒ€ì¼ ì•„ì´ë”” 표시"
#: 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."
@@ -12560,7 +12433,7 @@ msgstr "콜리전"
#: editor/plugins/tile_set_editor_plugin.cpp
msgid "Occlusion"
-msgstr "오í´ë£¨ì „"
+msgstr "ì°¨í"
#: editor/plugins/tile_set_editor_plugin.cpp scene/2d/touch_screen_button.cpp
msgid "Bitmask"
@@ -12835,7 +12708,6 @@ msgid "This property can't be changed."
msgstr "ì´ ì†ì„±ì€ 바꿀 수 없습니다."
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Snap Options"
msgstr "스냅 설정"
@@ -12845,9 +12717,10 @@ msgstr "스냅 설정"
#: scene/2d/path_2d.cpp scene/2d/polygon_2d.cpp scene/2d/sprite.cpp
#: scene/3d/cpu_particles.cpp scene/3d/label_3d.cpp scene/3d/path.cpp
#: scene/3d/physics_body.cpp scene/3d/soft_body.cpp scene/3d/sprite_3d.cpp
-#: 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
+#: scene/3d/visual_instance.cpp 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
msgid "Offset"
msgstr "오프셋"
@@ -12860,14 +12733,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
@@ -12876,14 +12747,12 @@ 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
@@ -12893,112 +12762,95 @@ 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 "Occluder í´ë¦¬ê³¤ 만들기"
+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 ""
+"ì›ê²© ì„¤ì •ì´ ë¹„ì–´ 있습니다. 네트워í¬ë¥¼ 사용하는 VCS ê¸°ëŠ¥ì´ ìž‘ë™í•˜ì§€ ì•Šì„ ìˆ˜ 있"
+"습니다."
#: editor/plugins/version_control_editor_plugin.cpp
-#, fuzzy
msgid "No commit message was provided."
-msgstr "ì´ë¦„ì„ ì œê³µí•˜ì§€ 않았습니다."
+msgstr "커밋 메시지가 제공ë˜ì§€ 않았습니다."
#: 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
msgid "Commit:"
@@ -13006,26 +12858,23 @@ 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"
@@ -14037,11 +13886,13 @@ 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 ""
+"모든 사전 설정ì—는 ëª¨ë‘ ë‚´ë³´ë‚´ê¸°ê°€ ìž‘ë™í•˜ë„ë¡ ì •ì˜ëœ 내보내기 경로가 있어야 "
+"합니다."
#: editor/project_export.cpp
msgid "Delete preset '%s'?"
@@ -14152,11 +14003,12 @@ 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
msgid "Export PCK/Zip..."
@@ -14183,18 +14035,16 @@ 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"
@@ -14260,16 +14110,17 @@ msgid "Invalid project path (changed anything?)."
msgstr "ìž˜ëª»ëœ í”„ë¡œì íЏ 경로 (무언가를 변경하셨습니까?)."
#: editor/project_manager.cpp
+#, fuzzy
msgid ""
-"Couldn't load project.godot in project path (error %d). It may be missing or "
-"corrupted."
+"Couldn't load project at '%s' (error %d). It may be missing or corrupted."
msgstr ""
"프로ì íЏ 경로ì—서 project.godotì„ ë¶ˆëŸ¬ì˜¬ 수 없습니다 (오류 %d). 누ë½ë˜ê±°ë‚˜ ì†"
"ìƒëœ 모양입니다."
#: editor/project_manager.cpp
-msgid "Couldn't edit project.godot in project path."
-msgstr "프로ì íЏ 경로ì—서 project.godot 파ì¼ì„ 편집할 수 없습니다."
+#, fuzzy
+msgid "Couldn't save project at '%s' (error %d)."
+msgstr "'%s'ì—서 프로ì íŠ¸ë¥¼ ì—´ 수 없습니다."
#: editor/project_manager.cpp
msgid "Couldn't create project.godot in project path."
@@ -14501,7 +14352,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 "프로ì íЏ 매니저"
@@ -15255,6 +15105,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 ""
@@ -15262,6 +15115,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..."
@@ -15291,9 +15147,8 @@ msgid "Enable Scene Unique Name(s)"
msgstr "씬 고유 ì´ë¦„ 활성화"
#: editor/scene_tree_dock.cpp
-#, fuzzy
msgid "Unique names already used by another node in the scene:"
-msgstr "ì´ë¯¸ 다른 함수/변수/시그ë„로 ì‚¬ìš©ëœ ì´ë¦„:"
+msgstr "ìž¥ë©´ì˜ ë‹¤ë¥¸ 노드ì—서 ì´ë¯¸ 사용 ì¤‘ì¸ ê³ ìœ  ì´ë¦„:"
#: editor/scene_tree_dock.cpp
msgid "Disable Scene Unique Name(s)"
@@ -15372,7 +15227,7 @@ msgstr "하위 리소스"
#: editor/scene_tree_dock.cpp
msgid "Access as Scene Unique Name"
-msgstr ""
+msgstr "장면 고유 ì´ë¦„으로 액세스"
#: editor/scene_tree_dock.cpp
msgid "Clear Inheritance"
@@ -15469,18 +15324,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"
@@ -15512,6 +15365,9 @@ msgid ""
"with the '%s' prefix in a node path.\n"
"Click to disable this."
msgstr ""
+"ì´ ë…¸ë“œëŠ” 노드 경로ì—서 '%s' ì ‘ë‘사를 ì•žì— ë¶™ì—¬ ìž¥ë©´ì˜ ì–´ëŠ ê³³ì—서나 액세스"
+"할 수 있습니다.\n"
+"비활성화하려면 í´ë¦­í•˜ì„¸ìš”."
#: editor/scene_tree_editor.cpp
msgid ""
@@ -15575,7 +15431,7 @@ msgstr "ìž˜ëª»ëœ ë…¸ë“œ ì´ë¦„입니다. ë‹¤ìŒ ë¬¸ìžëŠ” 허용하지 않습ë‹
#: editor/scene_tree_editor.cpp
msgid "Another node already uses this unique name in the scene."
-msgstr ""
+msgstr "다른 노드가 ì´ë¯¸ 장면ì—서 ì´ ê³ ìœ í•œ ì´ë¦„ì„ ì‚¬ìš©í•˜ê³  있습니다."
#: editor/scene_tree_editor.cpp
msgid "Rename Node"
@@ -15802,21 +15658,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"
@@ -15914,7 +15769,7 @@ msgstr "ë¼ì´íЏ 반경 바꾸기"
#: editor/spatial_editor_gizmos.cpp
msgid "Stream Player 3D"
-msgstr ""
+msgstr "스트림 플레ì´ì–´ 3D"
#: editor/spatial_editor_gizmos.cpp
msgid "Change AudioStreamPlayer3D Emission Angle"
@@ -15924,7 +15779,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"
@@ -15936,7 +15791,7 @@ msgstr "ì¹´ë©”ë¼ í¬ê¸° 바꾸기"
#: editor/spatial_editor_gizmos.cpp
msgid "Visibility Notifier"
-msgstr ""
+msgstr "가시성 알리미"
#: editor/spatial_editor_gizmos.cpp
msgid "Change Notifier AABB"
@@ -15947,18 +15802,16 @@ 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
msgid "Baked Indirect Light"
@@ -15993,57 +15846,52 @@ 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
msgid "Navigation Solid"
-msgstr "내비게ì´ì…˜ 모드"
+msgstr "내비게ì´ì…˜ 솔리드"
#: editor/spatial_editor_gizmos.cpp
-#, fuzzy
msgid "Navigation Solid Disabled"
-msgstr "내비게ì´ì…˜ 모드"
+msgstr "내비게ì´ì…˜ 솔리드 비활성화ë¨"
#: editor/spatial_editor_gizmos.cpp
msgid "Joint Body A"
-msgstr ""
+msgstr "ì¡°ì¸íЏ 바디 A"
#: editor/spatial_editor_gizmos.cpp
msgid "Joint Body B"
-msgstr ""
+msgstr "ì¡°ì¸íЏ 바디 B"
#: editor/spatial_editor_gizmos.cpp
msgid "Room Edge"
-msgstr ""
+msgstr "ë°© 가장ìžë¦¬"
#: editor/spatial_editor_gizmos.cpp
msgid "Room Overlap"
-msgstr ""
+msgstr "룸 겹침"
#: editor/spatial_editor_gizmos.cpp
msgid "Set Room Point Position"
-msgstr "룸 ì  ìœ„ì¹˜ 설정"
+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
msgid "Set Portal Point Position"
@@ -16051,18 +15899,16 @@ msgstr "í¬í„¸ ì  ìœ„ì¹˜ 설정"
#: editor/spatial_editor_gizmos.cpp
msgid "Portal Front"
-msgstr ""
+msgstr "í¬í„¸ ì „ë©´"
#: editor/spatial_editor_gizmos.cpp
-#, fuzzy
msgid "Portal Back"
-msgstr "뒤로"
+msgstr "í¬í„¸ 뒤로"
#: editor/spatial_editor_gizmos.cpp scene/2d/light_occluder_2d.cpp
#: scene/2d/tile_map.cpp
-#, fuzzy
msgid "Occluder"
-msgstr "ì–´í´ë£¨ì „ 모드"
+msgstr "오í´ë£¨ë”"
#: editor/spatial_editor_gizmos.cpp
msgid "Set Occluder Sphere Radius"
@@ -16073,109 +15919,98 @@ msgid "Set Occluder Sphere Position"
msgstr "ì–´í´ë£¨ë” 구체 위치 설정"
#: editor/spatial_editor_gizmos.cpp
-#, fuzzy
msgid "Set Occluder Polygon Point Position"
-msgstr "í¬í„¸ ì  ìœ„ì¹˜ 설정"
+msgstr "오í´ë£¨ë” í´ë¦¬ê³¤ í¬ì¸íЏ 위치 설정"
#: editor/spatial_editor_gizmos.cpp
-#, fuzzy
msgid "Set Occluder Hole Point Position"
-msgstr "곡선 ì  ìœ„ì¹˜ 설정"
+msgstr "오í´ë£¨ë” 홀 í¬ì¸íЏ 위치 설정"
#: editor/spatial_editor_gizmos.cpp
-#, fuzzy
msgid "Occluder Polygon Front"
-msgstr "Occluder í´ë¦¬ê³¤ 만들기"
+msgstr "오í´ë£¨ë” í´ë¦¬ê³¤ 프론트"
#: editor/spatial_editor_gizmos.cpp
-#, fuzzy
msgid "Occluder Polygon Back"
-msgstr "Occluder í´ë¦¬ê³¤ 만들기"
+msgstr "오í´ë£¨ë” í´ë¦¬ê³¤ ë°±"
#: editor/spatial_editor_gizmos.cpp
-#, fuzzy
msgid "Occluder Hole"
-msgstr "Occluder í´ë¦¬ê³¤ 만들기"
+msgstr "오í´ë£¨ë” 홀"
#: main/main.cpp
msgid "Godot Physics"
-msgstr ""
+msgstr "Godot 물리"
#: main/main.cpp servers/physics_2d/physics_2d_server_sw.cpp
#: servers/visual/visual_server_scene.cpp
msgid "Use BVH"
-msgstr ""
+msgstr "BVH 사용"
#: main/main.cpp servers/physics_2d/physics_2d_server_sw.cpp
#: servers/visual/visual_server_scene.cpp
-#, fuzzy
msgid "BVH Collision Margin"
-msgstr "콜리전 모드"
+msgstr "BVH ì¶©ëŒ ì—¬ë°±"
#: main/main.cpp
-#, fuzzy
msgid "Crash Handler"
-msgstr "핸들 설정"
+msgstr "ì¶©ëŒ ì²˜ë¦¬ê¸°"
#: main/main.cpp
-#, fuzzy
msgid "Multithreaded Server"
-msgstr "다중 노드 설정"
+msgstr "멀티스레드 서버"
#: main/main.cpp
msgid "RID Pool Prealloc"
-msgstr ""
+msgstr "RID 풀 사전 할당"
#: main/main.cpp
-#, fuzzy
msgid "Debugger stdout"
-msgstr "디버거"
+msgstr "디버거 표준 출력"
#: main/main.cpp
msgid "Max Chars Per Second"
-msgstr ""
+msgstr "초당 최대 문ìž"
#: main/main.cpp
msgid "Max Messages Per Frame"
-msgstr ""
+msgstr "프레임당 최대 메시지"
#: main/main.cpp
msgid "Max Errors Per Second"
-msgstr ""
+msgstr "초당 최대 오류"
#: main/main.cpp
msgid "Max Warnings Per Second"
-msgstr ""
+msgstr "초당 최대 경고"
#: main/main.cpp
msgid "Flush stdout On Print"
-msgstr ""
+msgstr "ì¸ì‡„ 시 stdout 플러시"
#: main/main.cpp servers/visual_server.cpp
msgid "Logging"
-msgstr ""
+msgstr "로깅"
#: main/main.cpp
msgid "File Logging"
-msgstr ""
+msgstr "íŒŒì¼ ë¡œê¹…"
#: main/main.cpp
-#, fuzzy
msgid "Enable File Logging"
-msgstr "필터 활성화"
+msgstr "íŒŒì¼ ë¡œê¹… 활성화"
#: main/main.cpp
-#, fuzzy
msgid "Log Path"
-msgstr "경로 복사"
+msgstr "로그 경로"
#: main/main.cpp
msgid "Max Log Files"
-msgstr ""
+msgstr "최대 로그 파ì¼"
#: main/main.cpp
msgid "Driver"
-msgstr ""
+msgstr "드ë¼ì´ë²„"
#: main/main.cpp
msgid "Driver Name"
@@ -16183,85 +16018,77 @@ msgstr "드ë¼ì´ë²„ ì´ë¦„"
#: main/main.cpp
msgid "Fallback To GLES2"
-msgstr ""
+msgstr "GLES2로 대체"
#: main/main.cpp
msgid "Use Nvidia Rect Flicker Workaround"
-msgstr ""
+msgstr "Nvidia Rect 깜박임 해결 방법 사용"
#: main/main.cpp
msgid "DPI"
-msgstr ""
+msgstr "DPI"
#: main/main.cpp
msgid "Allow hiDPI"
-msgstr ""
+msgstr "hiDPI 허용"
#: main/main.cpp
-#, fuzzy
msgid "V-Sync"
-msgstr "ë™ê¸°í™”"
+msgstr "수ì§ë™ê¸°í™”"
#: main/main.cpp
-#, fuzzy
msgid "Use V-Sync"
-msgstr "스냅 사용"
+msgstr "V-Sync 사용"
#: main/main.cpp
msgid "Per Pixel Transparency"
-msgstr ""
+msgstr "픽셀당 투명ë„"
#: main/main.cpp
msgid "Allowed"
-msgstr ""
+msgstr "허용ë¨"
#: main/main.cpp
msgid "Intended Usage"
-msgstr ""
+msgstr "사용 목ì "
#: main/main.cpp
-#, fuzzy
msgid "Framebuffer Allocation"
-msgstr "프레임 ì„ íƒ"
+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"
-msgstr ""
+msgstr "스레드 세ì´í”„ BVH"
#: main/main.cpp
msgid "Handheld"
-msgstr ""
+msgstr "휴대용"
#: main/main.cpp platform/javascript/export/export.cpp
#: platform/uwp/export/export.cpp
-#, fuzzy
msgid "Orientation"
-msgstr "온ë¼ì¸ 문서"
+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
msgid "Physics FPS"
-msgstr "물리 프레임 %"
+msgstr "물리 FPS"
#: main/main.cpp
msgid "Force FPS"
@@ -16269,177 +16096,163 @@ msgstr "FPS 강제"
#: main/main.cpp
msgid "Enable Pause Aware Picking"
-msgstr ""
+msgstr "ì¼ì‹œ 중지 ì¸ì‹ ì„ íƒ í™œì„±í™”"
#: 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"
#: main/main.cpp
msgid "Drop Mouse On GUI Input Disabled"
-msgstr ""
+msgstr "GUI ìž…ë ¥ 시 마우스 놓기 비활성화ë¨"
#: main/main.cpp
msgid "stdout"
-msgstr ""
+msgstr "표준 출력"
#: main/main.cpp
msgid "Print FPS"
-msgstr ""
+msgstr "FPS ì¸ì‡„"
#: main/main.cpp
msgid "Verbose stdout"
-msgstr ""
+msgstr "ìžì„¸í•œ 표준 출력"
#: main/main.cpp scene/main/scene_tree.cpp scene/resources/multimesh.cpp
-#, fuzzy
msgid "Physics Interpolation"
-msgstr "보간 모드"
+msgstr "물리 보간"
#: main/main.cpp
-#, fuzzy
msgid "Enable Warnings"
-msgstr "필터 활성화"
+msgstr "경고 활성화"
#: main/main.cpp
-#, fuzzy
msgid "Frame Delay Msec"
-msgstr "프레임 ì„ íƒ"
+msgstr "프레임 지연 Msec"
#: main/main.cpp
msgid "Low Processor Mode"
-msgstr ""
+msgstr "ë‚®ì€ í”„ë¡œì„¸ì„œ 모드"
#: main/main.cpp
msgid "Delta Sync After Draw"
-msgstr ""
+msgstr "그리기 후 ë¸íƒ€ ë™ê¸°í™”"
#: main/main.cpp
msgid "iOS"
-msgstr ""
+msgstr "iOS"
#: main/main.cpp
msgid "Hide Home Indicator"
-msgstr ""
+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"
-msgstr ""
+msgstr "GLES3"
#: main/main.cpp servers/visual_server.cpp
-#, fuzzy
msgid "Shaders"
msgstr "ì…°ì´ë”"
#: main/main.cpp
msgid "Debug Shader Fallbacks"
-msgstr ""
+msgstr "ì…°ì´ë” í´ë°± 디버그"
#: 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 "환경 보기"
+msgstr "환경"
#: main/main.cpp
msgid "Default Clear Color"
-msgstr ""
+msgstr "기본 í´ë¦¬ì–´ 컬러"
#: main/main.cpp
msgid "Boot Splash"
-msgstr ""
+msgstr "부트 스플래쉬"
#: main/main.cpp
-#, fuzzy
msgid "Show Image"
-msgstr "본 ë³´ì´ê¸°"
+msgstr "ì´ë¯¸ì§€ 표시"
#: main/main.cpp
msgid "Image"
-msgstr ""
+msgstr "ì˜ìƒ"
#: main/main.cpp
msgid "Fullsize"
-msgstr ""
+msgstr "ì „ì²´ í¬ê¸°"
#: main/main.cpp scene/resources/dynamic_font.cpp
msgid "Use Filter"
msgstr "필터 사용"
#: main/main.cpp scene/resources/style_box.cpp
-#, fuzzy
msgid "BG Color"
-msgstr "색ìƒ"
+msgstr "배경색"
#: main/main.cpp
-#, fuzzy
msgid "macOS Native Icon"
-msgstr "íƒ€ì¼ ì•„ì´ì½˜ 설정"
+msgstr "ë§¥OS 네ì´í‹°ë¸Œ ì•„ì´ì½˜"
#: main/main.cpp
msgid "Windows Native Icon"
-msgstr ""
+msgstr "윈ë„ìš° 네ì´í‹°ë¸Œ ì•„ì´ì½˜"
#: main/main.cpp
msgid "Buffering"
-msgstr ""
+msgstr "버í¼ë§"
#: main/main.cpp
msgid "Agile Event Flushing"
-msgstr ""
+msgstr "ì• ìžì¼ ì´ë²¤íЏ 플러싱"
#: main/main.cpp
msgid "Emulate Touch From Mouse"
-msgstr ""
+msgstr "마우스 터치 ì—뮬레ì´íЏ"
#: main/main.cpp
msgid "Emulate Mouse From Touch"
-msgstr ""
+msgstr "터치로 마우스 ì—뮬레ì´íЏ"
#: main/main.cpp
-#, fuzzy
msgid "Mouse Cursor"
-msgstr "마우스 버튼"
+msgstr "마우스 커서"
#: main/main.cpp
-#, fuzzy
msgid "Custom Image"
-msgstr "노드 잘ë¼ë‚´ê¸°"
+msgstr "ì‚¬ìš©ìž ì •ì˜ ì´ë¯¸ì§€"
#: main/main.cpp
msgid "Custom Image Hotspot"
-msgstr ""
+msgstr "ì‚¬ìš©ìž ì •ì˜ ì´ë¯¸ì§€ 핫스팟"
#: main/main.cpp
msgid "Tooltip Position Offset"
msgstr "íˆ´íŒ ìœ„ì¹˜ 오프셋"
#: main/main.cpp modules/mono/mono_gd/gd_mono.cpp
-#, fuzzy
msgid "Debugger Agent"
-msgstr "디버거"
+msgstr "디버거 ì—ì´ì „트"
#: main/main.cpp modules/mono/mono_gd/gd_mono.cpp
-#, fuzzy
msgid "Wait For Debugger"
-msgstr "디버거"
+msgstr "디버거 대기"
#: main/main.cpp modules/mono/mono_gd/gd_mono.cpp
msgid "Wait Timeout"
@@ -16447,60 +16260,56 @@ msgstr "대기 타임아웃"
#: main/main.cpp
msgid "Runtime"
-msgstr ""
+msgstr "런타임"
#: main/main.cpp
msgid "Unhandled Exception Policy"
-msgstr ""
+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
msgid "Aspect"
-msgstr "ì¸ìŠ¤íŽ™í„°"
+msgstr "ì–‘ìƒ"
#: main/main.cpp
msgid "Shrink"
-msgstr ""
+msgstr "수축"
#: main/main.cpp scene/main/scene_tree.cpp
msgid "Auto Accept Quit"
-msgstr ""
+msgstr "ìžë™ ìˆ˜ë½ ì¢…ë£Œ"
#: main/main.cpp scene/main/scene_tree.cpp
-#, fuzzy
msgid "Quit On Go Back"
-msgstr "뒤로"
+msgstr "ëŒì•„가면서 종료"
#: main/main.cpp scene/main/viewport.cpp
-#, fuzzy
msgid "Snap Controls To Pixels"
-msgstr "노드 ì˜†ë©´ì— ìŠ¤ëƒ…"
+msgstr "í”½ì…€ì— ì»¨íŠ¸ë¡¤ 스냅"
#: main/main.cpp
msgid "Dynamic Fonts"
-msgstr ""
+msgstr "ë™ì  글꼴"
#: main/main.cpp
msgid "Use Oversampling"
-msgstr ""
+msgstr "ì˜¤ë²„ìƒ˜í”Œë§ ì‚¬ìš©"
#: modules/bullet/register_types.cpp modules/bullet/space_bullet.cpp
msgid "Active Soft World"
-msgstr ""
+msgstr "액티브 소프트 월드"
#: modules/csg/csg_gizmos.cpp
msgid "CSG"
-msgstr ""
+msgstr "CSG"
#: modules/csg/csg_gizmos.cpp
msgid "Change Cylinder Radius"
@@ -16519,35 +16328,30 @@ msgid "Change 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
@@ -16561,170 +16365,147 @@ msgid "Radius"
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
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 ""
+msgstr "ì›ë¿”"
#: modules/csg/csg_shape.cpp
-#, fuzzy
msgid "Inner Radius"
-msgstr "ë„ë„› ë‚´ë¶€ 반지름 바꾸기"
+msgstr "내부 반경"
#: modules/csg/csg_shape.cpp
-#, fuzzy
msgid "Outer Radius"
-msgstr "ë„ë„› 외부 반지름 바꾸기"
+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
#: scene/3d/collision_polygon.cpp
-#, fuzzy
msgid "Polygon"
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
msgid "Path Interval Type"
-msgstr "ë‚´ë¶€ ê¼­ì§“ì  ë§Œë“¤ê¸°"
+msgstr "경로 간격 유형"
#: modules/csg/csg_shape.cpp
msgid "Path Interval"
-msgstr ""
+msgstr "경로 간격"
#: modules/csg/csg_shape.cpp
msgid "Path Simplify Angle"
-msgstr ""
+msgstr "경로 단순화 ê°ë„"
#: modules/csg/csg_shape.cpp
-#, fuzzy
msgid "Path Rotation"
-msgstr "무작위 회전:"
+msgstr "경로 회전"
#: modules/csg/csg_shape.cpp
-#, fuzzy
msgid "Path Local"
-msgstr "로컬로 만들기"
+msgstr "경로 로컬"
#: modules/csg/csg_shape.cpp
-#, fuzzy
msgid "Path Continuous U"
-msgstr "ì—°ì†ì "
+msgstr "경로 ì—°ì† U"
#: 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
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
msgid "Server Relay"
-msgstr ""
+msgstr "서버 릴레ì´"
#: modules/enet/networked_multiplayer_enet.cpp
msgid "DTLS Verify"
-msgstr ""
+msgstr "DTLS 확ì¸"
#: modules/enet/networked_multiplayer_enet.cpp
msgid "DTLS Hostname"
-msgstr ""
+msgstr "DTLS 호스트 ì´ë¦„"
#: modules/enet/networked_multiplayer_enet.cpp
-#, fuzzy
msgid "Use DTLS"
-msgstr "스냅 사용"
+msgstr "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 "FBX 사용"
#: modules/gdnative/gdnative.cpp
msgid "Config File"
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
@@ -16789,9 +16570,8 @@ msgid "Script Class"
msgstr "스í¬ë¦½íЏ í´ëž˜ìФ"
#: modules/gdnative/nativescript/nativescript.cpp
-#, fuzzy
msgid "Icon Path"
-msgstr "경로 í¬ì»¤ìФ"
+msgstr "ì•„ì´ì½˜ 경로"
#: modules/gdnative/register_types.cpp
msgid "GDNative"
@@ -16799,34 +16579,32 @@ msgstr "GDNative"
#: modules/gdscript/editor/gdscript_highlighter.cpp
#: modules/gdscript/gdscript.cpp
-#, fuzzy
msgid "GDScript"
-msgstr "스í¬ë¦½íЏ"
+msgstr "GD스í¬ë¦½íЏ"
#: 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"
-msgstr ""
+msgstr "최대 호출 스íƒ"
#: modules/gdscript/gdscript.cpp
msgid "Treat Warnings As Errors"
-msgstr ""
+msgstr "경고를 오류로 처리"
#: modules/gdscript/gdscript.cpp
msgid "Exclude Addons"
-msgstr ""
+msgstr "애드온 제외"
#: modules/gdscript/gdscript.cpp
msgid "Autocomplete Setters And Getters"
-msgstr ""
+msgstr "ìžë™ 완성 ì„¤ì •ìž ë° ê²Œí„°"
#: modules/gdscript/gdscript_functions.cpp
msgid "Step argument is zero!"
@@ -16869,17 +16647,16 @@ msgid "Language Server"
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"
-msgstr ""
+msgstr "편집기ì—서 기본 기호 표시"
#: modules/gdscript/language_server/gdscript_language_server.cpp
msgid "Use Thread"
-msgstr ""
+msgstr "스레드 사용"
#: modules/gltf/editor_scene_exporter_gltf_plugin.cpp
msgid "Export Mesh GLTF2"
@@ -16890,96 +16667,84 @@ msgid "Export GLTF..."
msgstr "GLTF 내보내기..."
#: modules/gltf/gltf_accessor.cpp
-#, fuzzy
msgid "Buffer View"
-msgstr "후면 뷰"
+msgstr "ë²„í¼ ë³´ê¸°"
#: modules/gltf/gltf_accessor.cpp modules/gltf/gltf_buffer_view.cpp
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
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
msgid "Sparse Count"
-msgstr "ì¸ìŠ¤í„´ìŠ¤í•˜ê¸°"
+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
-#, fuzzy
msgid "Sparse Indices Component Type"
-msgstr "지오메트리 ë¶„ì„ ì¤‘..."
+msgstr "í¬ì†Œ ì¸ë±ìФ 구성 요소 유형"
#: modules/gltf/gltf_accessor.cpp
msgid "Sparse Values Buffer View"
-msgstr ""
+msgstr "í¬ì†Œ ê°’ ë²„í¼ ë³´ê¸°"
#: modules/gltf/gltf_accessor.cpp
msgid "Sparse Values Byte Offset"
-msgstr ""
+msgstr "í¬ì†Œ ê°’ ë°”ì´íЏ 오프셋"
#: modules/gltf/gltf_buffer_view.cpp
-#, fuzzy
msgid "Buffer"
-msgstr "후면 뷰"
+msgstr "버í¼"
#: modules/gltf/gltf_buffer_view.cpp
-#, fuzzy
msgid "Byte Length"
-msgstr "ë””í´íЏ 테마"
+msgstr "ë°”ì´íЏ 길ì´"
#: modules/gltf/gltf_buffer_view.cpp
msgid "Byte Stride"
-msgstr ""
+msgstr "ë°”ì´íЏ 스트ë¼ì´ë“œ"
#: modules/gltf/gltf_buffer_view.cpp
-#, fuzzy
msgid "Indices"
-msgstr "모든 기기"
+msgstr "ì¸ë±ìФ"
#: modules/gltf/gltf_camera.cpp
-#, fuzzy
msgid "FOV Size"
-msgstr "í¬ê¸°:"
+msgstr "FOV í¬ê¸°"
#: modules/gltf/gltf_camera.cpp
msgid "Zfar"
-msgstr ""
+msgstr "Z 멀리"
#: modules/gltf/gltf_camera.cpp
-#, fuzzy
msgid "Znear"
-msgstr "ì§ì„ í˜•"
+msgstr "Z 근처"
#: 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
@@ -16989,273 +16754,239 @@ 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
msgid "Blend Weights"
-msgstr "ë¼ì´íŠ¸ë§µ 굽기"
+msgstr "혼합 가중치"
#: modules/gltf/gltf_mesh.cpp
-#, fuzzy
msgid "Instance Materials"
-msgstr "머티리얼 바꾸기:"
+msgstr "ì¸ìŠ¤í„´ìŠ¤ 재료"
#: modules/gltf/gltf_node.cpp scene/3d/skeleton.cpp
-#, fuzzy
msgid "Parent"
-msgstr "부모 다시 지정"
+msgstr "부모"
#: modules/gltf/gltf_node.cpp
-#, fuzzy
msgid "Xform"
-msgstr "플랫í¼"
+msgstr "변형"
#: modules/gltf/gltf_node.cpp scene/3d/mesh_instance.cpp
msgid "Skin"
-msgstr ""
+msgstr "스킨"
#: modules/gltf/gltf_node.cpp scene/3d/spatial.cpp
-#, fuzzy
msgid "Translation"
msgstr "번역"
#: modules/gltf/gltf_node.cpp
-#, fuzzy
msgid "Children"
-msgstr "편집할 수 있는 ìžì‹"
+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 "Godot 본 노드"
#: modules/gltf/gltf_skin.cpp
-#, fuzzy
msgid "Skin Root"
-msgstr "새 씬 루트"
+msgstr "스킨 루트"
#: modules/gltf/gltf_skin.cpp
-#, fuzzy
msgid "Joints Original"
-msgstr "ì›ì  í¬ì»¤ìФ"
+msgstr "관절 ì›ë³¸"
#: modules/gltf/gltf_skin.cpp
msgid "Inverse Binds"
-msgstr ""
+msgstr "ì—­ê²°í•©"
#: modules/gltf/gltf_skin.cpp
-#, fuzzy
msgid "Non Joints"
-msgstr "관절 ì´ë™"
+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"
-msgstr ""
+msgstr "Godot 스킨"
#: modules/gltf/gltf_spec_gloss.cpp
msgid "Diffuse Img"
-msgstr ""
+msgstr "확산 ì´ë¯¸ì§€"
#: modules/gltf/gltf_spec_gloss.cpp
msgid "Diffuse Factor"
-msgstr ""
+msgstr "확산 계수"
#: modules/gltf/gltf_spec_gloss.cpp
msgid "Gloss Factor"
-msgstr ""
+msgstr "ê´‘íƒ ê³„ìˆ˜"
#: modules/gltf/gltf_spec_gloss.cpp
-#, fuzzy
msgid "Specular Factor"
-msgstr "ìŠ¤ì¹¼ë¼ ì—°ì‚°ìž."
+msgstr "반사 ì¸ìž"
#: modules/gltf/gltf_spec_gloss.cpp
msgid "Spec Gloss Img"
-msgstr ""
+msgstr "반사광 ì´ë¯¸ì§€"
#: modules/gltf/gltf_state.cpp
msgid "Json"
-msgstr ""
+msgstr "Json"
#: 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
msgid "GLB Data"
-msgstr "ë°ì´í„°ì™€ 함께"
+msgstr "GLB ë°ì´í„°"
#: modules/gltf/gltf_state.cpp
msgid "Use Named Skin Binds"
-msgstr ""
+msgstr "네임드 스킨 ë°”ì¸ë”© 사용"
#: modules/gltf/gltf_state.cpp
-#, fuzzy
msgid "Buffer Views"
-msgstr "후면 뷰"
+msgstr "ë²„í¼ ë³´ê¸°"
#: modules/gltf/gltf_state.cpp
msgid "Accessors"
-msgstr ""
+msgstr "ì ‘ê·¼ìž"
#: modules/gltf/gltf_state.cpp
msgid "Scene Name"
msgstr "씬 ì´ë¦„"
#: modules/gltf/gltf_state.cpp
-#, fuzzy
msgid "Root Nodes"
-msgstr "루트 노드 ì´ë¦„"
+msgstr "루트 노드"
#: modules/gltf/gltf_state.cpp scene/2d/particles_2d.cpp
#: scene/gui/texture_button.cpp scene/gui/texture_progress.cpp
-#, fuzzy
msgid "Textures"
-msgstr "기능"
+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
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 "SRC ì´ë¯¸ì§€"
#: 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
msgid "Octant Size"
-msgstr "ì •ë©´ ë·°"
+msgstr "옥탄트 í¬ê¸°"
#: modules/gridmap/grid_map.cpp
-#, fuzzy
msgid "Center X"
-msgstr "중앙"
+msgstr "중앙 X"
#: modules/gridmap/grid_map.cpp
-#, fuzzy
msgid "Center Y"
-msgstr "중앙"
+msgstr "중앙 Y"
#: modules/gridmap/grid_map.cpp
-#, fuzzy
msgid "Center Z"
-msgstr "중앙"
+msgstr "중앙 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 "마스í¬"
#: modules/gridmap/grid_map.cpp scene/2d/tile_map.cpp
-#, fuzzy
msgid "Bake Navigation"
-msgstr "네비게ì´ì…˜"
+msgstr "ë² ì´í¬ 내비게ì´ì…˜"
#: 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 "내비게ì´ì…˜ ê°ë„"
+msgstr "내비게ì´ì…˜ ë ˆì´ì–´"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Next Plane"
@@ -17414,63 +17145,59 @@ msgid "Plotting lightmaps"
msgstr "ë¼ì´íŠ¸ë§µ 그리는 중"
#: modules/lightmapper_cpu/register_types.cpp
-#, fuzzy
msgid "CPU Lightmapper"
-msgstr "ë¼ì´íŠ¸ë§µ 굽기"
+msgstr "CPU ë¼ì´íŠ¸ë§¤í¼"
#: modules/lightmapper_cpu/register_types.cpp
msgid "Low Quality Ray Count"
-msgstr ""
+msgstr "ë‚®ì€ í’ˆì§ˆì˜ ê´‘ì„  수"
#: modules/lightmapper_cpu/register_types.cpp
msgid "Medium Quality Ray Count"
-msgstr ""
+msgstr "중간 품질 광선 수"
#: modules/lightmapper_cpu/register_types.cpp
msgid "High Quality Ray Count"
-msgstr ""
+msgstr "고품질 광선 수"
#: modules/lightmapper_cpu/register_types.cpp
msgid "Ultra Quality Ray Count"
-msgstr ""
+msgstr "초고품질 광선 수"
#: modules/minimp3/audio_stream_mp3.cpp
#: 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 ""
+msgstr "IOD"
#: modules/mobile_vr/mobile_vr_interface.cpp
-#, fuzzy
msgid "Display Width"
-msgstr "와ì´ì–´í”„레임 표시"
+msgstr "ë””ìŠ¤í”Œë ˆì´ ë„ˆë¹„"
#: modules/mobile_vr/mobile_vr_interface.cpp
-#, fuzzy
msgid "Display To Lens"
-msgstr "ì…°ì´ë” ì—†ìŒ í‘œì‹œ"
+msgstr "ë Œì¦ˆì— í‘œì‹œ"
#: modules/mobile_vr/mobile_vr_interface.cpp
msgid "Oversample"
-msgstr ""
+msgstr "오버샘플"
#: 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"
@@ -17481,24 +17208,20 @@ msgid "Build Solution"
msgstr "솔루션 빌드"
#: modules/mono/editor/csharp_project.cpp
-#, fuzzy
msgid "Auto Update Project"
-msgstr "ì´ë¦„ 없는 프로ì íЏ"
+msgstr "ìžë™ ì—…ë°ì´íЏ 프로ì íЏ"
#: modules/mono/godotsharp_dirs.cpp
-#, fuzzy
msgid "Assembly Name"
-msgstr "ëª¨ë‘ í‘œì‹œ"
+msgstr "어셈블리 ì´ë¦„"
#: modules/mono/godotsharp_dirs.cpp
-#, fuzzy
msgid "Solution Directory"
-msgstr "디렉토리를 ì„ íƒí•˜ì„¸ìš”"
+msgstr "솔루션 디렉토리"
#: modules/mono/godotsharp_dirs.cpp
-#, fuzzy
msgid "C# Project Directory"
-msgstr "디렉토리를 ì„ íƒí•˜ì„¸ìš”"
+msgstr "C# 프로ì íЏ 디렉토리"
#: modules/mono/mono_gd/gd_mono_utils.cpp
msgid "End of inner exception stack trace"
@@ -17572,20 +17295,19 @@ msgstr "완료!"
#: modules/opensimplex/noise_texture.cpp
msgid "Seamless"
-msgstr ""
+msgstr "ì›í™œí•œ"
#: modules/opensimplex/noise_texture.cpp
-#, fuzzy
msgid "As Normal Map"
-msgstr "무작위 스케ì¼:"
+msgstr "노멀 맵으로"
#: modules/opensimplex/noise_texture.cpp
msgid "Bump Strength"
-msgstr ""
+msgstr "범프 ê°•ë„"
#: modules/opensimplex/noise_texture.cpp
msgid "Noise"
-msgstr ""
+msgstr "소ìŒ"
#: modules/opensimplex/noise_texture.cpp
msgid "Noise Offset"
@@ -17593,27 +17315,25 @@ msgstr "ë…¸ì´ì¦ˆ 오프셋"
#: modules/opensimplex/open_simplex_noise.cpp
msgid "Octaves"
-msgstr ""
+msgstr "옥타브"
#: modules/opensimplex/open_simplex_noise.cpp
msgid "Period"
-msgstr ""
+msgstr "기간"
#: modules/opensimplex/open_simplex_noise.cpp
-#, fuzzy
msgid "Persistence"
-msgstr "ì›ê·¼"
+msgstr "ì§€ì†ì„±"
#: modules/opensimplex/open_simplex_noise.cpp
msgid "Lacunarity"
-msgstr ""
+msgstr "세심함"
#: modules/regex/regex.cpp
msgid "Subject"
-msgstr ""
+msgstr "서브ì íЏ"
#: modules/regex/regex.cpp
-#, fuzzy
msgid "Names"
msgstr "ì´ë¦„"
@@ -17623,43 +17343,39 @@ msgstr "문ìžì—´"
#: modules/upnp/upnp.cpp
msgid "Discover Multicast If"
-msgstr ""
+msgstr "멀티ìºìŠ¤íŠ¸ë¥¼ 발견하면"
#: modules/upnp/upnp.cpp
msgid "Discover Local Port"
-msgstr ""
+msgstr "로컬 í¬íЏ 검색"
#: modules/upnp/upnp.cpp
msgid "Discover IPv6"
-msgstr ""
+msgstr "IPv6 발견"
#: modules/upnp/upnp_device.cpp
-#, fuzzy
msgid "Description URL"
-msgstr "설명"
+msgstr "설명 URL"
#: modules/upnp/upnp_device.cpp
-#, fuzzy
msgid "Service Type"
-msgstr "변수 타입 설정"
+msgstr "서비스 유형"
#: modules/upnp/upnp_device.cpp
msgid "IGD Control URL"
-msgstr ""
+msgstr "IGD 제어 URL"
#: modules/upnp/upnp_device.cpp
-#, fuzzy
msgid "IGD Service Type"
-msgstr "변수 타입 설정"
+msgstr "IGD 서비스 유형"
#: modules/upnp/upnp_device.cpp
msgid "IGD Our Addr"
-msgstr ""
+msgstr "IGD ìš°ë¦¬ì˜ ì£¼ì†Œ"
#: modules/upnp/upnp_device.cpp
-#, fuzzy
msgid "IGD Status"
-msgstr "ìƒíƒœ"
+msgstr "IGD ìƒíƒœ"
#: modules/visual_script/visual_script.cpp
msgid ""
@@ -17694,14 +17410,12 @@ msgstr ""
"시퀀스 비트를 발견했지만 ìŠ¤íƒ ì•ˆì˜ ë…¸ë“œì—는 없습니다. 버그를 신고하세요!"
#: modules/visual_script/visual_script.cpp
-#, fuzzy
msgid "Stack overflow with stack depth:"
-msgstr "ìŠ¤íƒ ê¹Šì´ë¡œ 오버플로우한 스íƒ: "
+msgstr "ìŠ¤íƒ ê¹Šì´ê°€ 있는 ìŠ¤íƒ ì˜¤ë²„í”Œë¡œ:"
#: modules/visual_script/visual_script.cpp
-#, fuzzy
msgid "Visual Script"
-msgstr "비주얼스í¬ë¦½íЏ 검색"
+msgstr "비주얼 스í¬ë¦½íЏ"
#: modules/visual_script/visual_script_editor.cpp
msgid "Change Signal Arguments"
@@ -18022,122 +17736,108 @@ msgstr "멤버 편집"
#: modules/visual_script/visual_script_expression.cpp
#: scene/resources/visual_shader.cpp
-#, fuzzy
msgid "Expression"
-msgstr "í‘œí˜„ì‹ ì„¤ì •"
+msgstr "표현"
#: modules/visual_script/visual_script_flow_control.cpp
msgid "Return"
-msgstr ""
+msgstr "반환"
#: modules/visual_script/visual_script_flow_control.cpp
-#, fuzzy
msgid "Return Enabled"
-msgstr "실행가능"
+msgstr "반환 활성화ë¨"
#: modules/visual_script/visual_script_flow_control.cpp
-#, fuzzy
msgid "Return Type"
-msgstr "멤버 타입"
+msgstr "반환 유형"
#: modules/visual_script/visual_script_flow_control.cpp
#: scene/resources/visual_shader_nodes.cpp
-#, fuzzy
msgid "Condition"
-msgstr "애니메ì´ì…˜"
+msgstr "ì¡°ê±´"
#: modules/visual_script/visual_script_flow_control.cpp
msgid "if (cond) is:"
-msgstr ""
+msgstr "(ì¡°ê±´)ì´ ë‹¤ìŒê³¼ 같으면:"
#: modules/visual_script/visual_script_flow_control.cpp
msgid "While"
-msgstr "While"
+msgstr "ë™ì•ˆ"
#: modules/visual_script/visual_script_flow_control.cpp
msgid "while (cond):"
-msgstr ""
+msgstr "ë™ì•ˆ(ì¡°ê±´):"
#: modules/visual_script/visual_script_flow_control.cpp
msgid "Iterator"
-msgstr ""
+msgstr "반복ìž"
#: modules/visual_script/visual_script_flow_control.cpp
msgid "for (elem) in (input):"
-msgstr ""
+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 "Iteratorê°€ 잘못ë˜ì—ˆìŠµë‹ˆë‹¤"
+msgstr "반복ìžê°€ 잘못ë˜ì—ˆìŠµë‹ˆë‹¤"
#: modules/visual_script/visual_script_flow_control.cpp
-#, fuzzy
msgid "Iterator became invalid:"
-msgstr "Iteratorê°€ 잘못ë¨: "
+msgstr "반복ìžê°€ 잘못ë˜ì—ˆìŠµë‹ˆë‹¤:"
#: modules/visual_script/visual_script_flow_control.cpp
msgid "Sequence"
-msgstr ""
+msgstr "순서"
#: modules/visual_script/visual_script_flow_control.cpp
-#, fuzzy
msgid "in order:"
-msgstr "í´ë” ì´ë¦„ 바꾸기:"
+msgstr "규칙대로:"
#: modules/visual_script/visual_script_flow_control.cpp
-#, fuzzy
msgid "Steps"
msgstr "단계"
#: modules/visual_script/visual_script_flow_control.cpp
-#, fuzzy
msgid "Switch"
-msgstr "Pitch:"
+msgstr "스위치"
#: modules/visual_script/visual_script_flow_control.cpp
msgid "'input' is:"
-msgstr ""
+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?"
-msgstr ""
+msgstr "%sì¸ê°€ìš”?"
#: modules/visual_script/visual_script_flow_control.cpp
#: modules/visual_script/visual_script_func_nodes.cpp
-#, fuzzy
msgid "Base Script"
-msgstr "새 스í¬ë¦½íЏ"
+msgstr "기본 스í¬ë¦½íЏ"
#: modules/visual_script/visual_script_func_nodes.cpp
msgid "On %s"
-msgstr ""
+msgstr "%sì—"
#: modules/visual_script/visual_script_func_nodes.cpp
-#, fuzzy
msgid "On Self"
-msgstr "ìžì²´"
+msgstr "온 셀프"
#: modules/visual_script/visual_script_func_nodes.cpp
#: modules/visual_script/visual_script_yield_nodes.cpp
-#, fuzzy
msgid "Call Mode"
-msgstr "ìŠ¤ì¼€ì¼ ëª¨ë“œ"
+msgstr "호출 모드"
#: modules/visual_script/visual_script_func_nodes.cpp
#: modules/visual_script/visual_script_nodes.cpp
-#, fuzzy
msgid "Basic Type"
-msgstr "기본 타입 바꾸기"
+msgstr "기본형"
#: modules/visual_script/visual_script_func_nodes.cpp
#: modules/visual_script/visual_script_nodes.cpp
@@ -20129,7 +19829,7 @@ msgstr "개정"
#: platform/uwp/export/export.cpp
msgid "Landscape"
-msgstr ""
+msgstr "í’ê²½"
#: platform/uwp/export/export.cpp
#, fuzzy
@@ -20426,7 +20126,7 @@ msgstr ""
#: platform/windows/export/export.cpp
msgid "Wine"
-msgstr ""
+msgstr "와ì¸"
#: platform/x11/export/export.cpp
msgid "32-bit executables cannot have embedded data >= 4 GiB."
@@ -20982,7 +20682,7 @@ msgstr "선회 뷰 오른쪽으로"
#: scene/resources/particles_material.cpp servers/physics_2d_server.cpp
#: servers/physics_server.cpp
msgid "Angular Velocity"
-msgstr ""
+msgstr "ê°ì†ë„"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
@@ -21427,7 +21127,7 @@ msgstr "ë„ë„› 외부 반지름 바꾸기"
msgid ""
"The NavigationObstacle2D only serves to provide collision avoidance to a "
"Node2D object."
-msgstr ""
+msgstr "NavigationObstacle2D는 Node2D ê°œì²´ì— ëŒ€í•œ ì¶©ëŒ ë°©ì§€ 기능만 제공합니다."
#: scene/2d/navigation_polygon.cpp
msgid ""
@@ -23668,6 +23368,16 @@ msgstr "오류"
msgid "AABB"
msgstr ""
+#: scene/3d/visual_instance.cpp
+#, fuzzy
+msgid "Sorting"
+msgstr "ì •ë ¬"
+
+#: scene/3d/visual_instance.cpp
+#, fuzzy
+msgid "Use AABB Center"
+msgstr "주변광 사용"
+
#: scene/3d/visual_instance.cpp scene/resources/navigation_mesh.cpp
#, fuzzy
msgid "Geometry"
@@ -26547,7 +26257,7 @@ msgstr ""
#: scene/resources/environment.cpp
msgid "Bloom"
-msgstr ""
+msgstr "블룸"
#: scene/resources/environment.cpp
msgid "HDR Threshold"
@@ -27176,9 +26886,8 @@ msgid "Bind"
msgstr "ë°”ì¸ë”©"
#: scene/resources/skin.cpp
-#, fuzzy
msgid "Bone"
-msgstr "본"
+msgstr "뼈"
#: scene/resources/sky.cpp
#, fuzzy
diff --git a/editor/translations/lt.po b/editor/translations/lt.po
index e89e801a9b..5f0c068dbb 100644
--- a/editor/translations/lt.po
+++ b/editor/translations/lt.po
@@ -12948,9 +12948,10 @@ msgstr "Žingsnis(iai):"
#: scene/2d/path_2d.cpp scene/2d/polygon_2d.cpp scene/2d/sprite.cpp
#: scene/3d/cpu_particles.cpp scene/3d/label_3d.cpp scene/3d/path.cpp
#: scene/3d/physics_body.cpp scene/3d/soft_body.cpp scene/3d/sprite_3d.cpp
-#: 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
+#: scene/3d/visual_instance.cpp 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
msgid "Offset"
msgstr ""
@@ -14343,12 +14344,11 @@ msgstr ""
#: editor/project_manager.cpp
msgid ""
-"Couldn't load project.godot in project path (error %d). It may be missing or "
-"corrupted."
+"Couldn't load project at '%s' (error %d). It may be missing or corrupted."
msgstr ""
#: editor/project_manager.cpp
-msgid "Couldn't edit project.godot in project path."
+msgid "Couldn't save project at '%s' (error %d)."
msgstr ""
#: editor/project_manager.cpp
@@ -23371,6 +23371,15 @@ msgstr "Įvyko klaida kraunant šriftą."
msgid "AABB"
msgstr ""
+#: scene/3d/visual_instance.cpp
+#, fuzzy
+msgid "Sorting"
+msgstr "Importuojama:"
+
+#: scene/3d/visual_instance.cpp
+msgid "Use AABB Center"
+msgstr ""
+
#: scene/3d/visual_instance.cpp scene/resources/navigation_mesh.cpp
#, fuzzy
msgid "Geometry"
diff --git a/editor/translations/lv.po b/editor/translations/lv.po
index 7234ac270a..51836c627b 100644
--- a/editor/translations/lv.po
+++ b/editor/translations/lv.po
@@ -12808,9 +12808,10 @@ msgstr "Opcijas"
#: scene/2d/path_2d.cpp scene/2d/polygon_2d.cpp scene/2d/sprite.cpp
#: scene/3d/cpu_particles.cpp scene/3d/label_3d.cpp scene/3d/path.cpp
#: scene/3d/physics_body.cpp scene/3d/soft_body.cpp scene/3d/sprite_3d.cpp
-#: 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
+#: scene/3d/visual_instance.cpp 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
msgid "Offset"
msgstr ""
@@ -14176,12 +14177,11 @@ msgstr ""
#: editor/project_manager.cpp
msgid ""
-"Couldn't load project.godot in project path (error %d). It may be missing or "
-"corrupted."
+"Couldn't load project at '%s' (error %d). It may be missing or corrupted."
msgstr ""
#: editor/project_manager.cpp
-msgid "Couldn't edit project.godot in project path."
+msgid "Couldn't save project at '%s' (error %d)."
msgstr ""
#: editor/project_manager.cpp
@@ -23214,6 +23214,15 @@ msgstr "%s Kļūda"
msgid "AABB"
msgstr ""
+#: scene/3d/visual_instance.cpp
+#, fuzzy
+msgid "Sorting"
+msgstr "Å Ä·irot"
+
+#: scene/3d/visual_instance.cpp
+msgid "Use AABB Center"
+msgstr ""
+
#: scene/3d/visual_instance.cpp scene/resources/navigation_mesh.cpp
#, fuzzy
msgid "Geometry"
diff --git a/editor/translations/mk.po b/editor/translations/mk.po
index d0be6e7036..6d725ac82b 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-07-23 03:57+0000\n"
+"PO-Revision-Date: 2022-10-24 12:41+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,11 +17,11 @@ 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.14-dev\n"
+"X-Generator: Weblate 4.14.2-dev\n"
#: core/bind/core_bind.cpp main/main.cpp
msgid "Tablet Driver"
-msgstr ""
+msgstr "Драјвер за Таблет"
#: core/bind/core_bind.cpp
msgid "Clipboard"
@@ -49,7 +49,7 @@ msgstr "Делта Измазнување"
#: core/bind/core_bind.cpp
msgid "Low Processor Usage Mode"
-msgstr ""
+msgstr "Режим за ниÑка употреба на процеÑор"
#: core/bind/core_bind.cpp
msgid "Low Processor Usage Mode Sleep (µsec)"
@@ -186,19 +186,19 @@ msgstr "Ред за наредби"
#: core/command_queue_mt.cpp
msgid "Multithreading Queue Size (KB)"
-msgstr ""
+msgstr "Големина на редот за Мултитрединг"
#: 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
msgid "Function"
-msgstr ""
+msgstr "Функција"
#: 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 "Дата"
#: core/io/file_access_network.cpp core/register_core_types.cpp
#: editor/editor_file_dialog.cpp editor/editor_settings.cpp main/main.cpp
@@ -206,16 +206,15 @@ msgstr ""
#: modules/webrtc/webrtc_data_channel.h modules/websocket/websocket_macros.h
#: scene/gui/file_dialog.cpp
msgid "Network"
-msgstr ""
+msgstr "Мрежа"
#: core/io/file_access_network.cpp
-#, fuzzy
msgid "Remote FS"
-msgstr "Избриши невалидни клучеви"
+msgstr "Далечен ФС"
#: core/io/file_access_network.cpp
msgid "Page Size"
-msgstr ""
+msgstr "Големина на Страница"
#: core/io/file_access_network.cpp
msgid "Page Read Ahead"
@@ -3357,7 +3356,7 @@ msgstr ""
#: editor/editor_help.cpp
msgid "Enumerations"
-msgstr ""
+msgstr "Енумерации"
#: editor/editor_help.cpp
msgid "Property Descriptions"
@@ -12418,9 +12417,10 @@ msgstr "СвојÑтва на анимацијата."
#: scene/2d/path_2d.cpp scene/2d/polygon_2d.cpp scene/2d/sprite.cpp
#: scene/3d/cpu_particles.cpp scene/3d/label_3d.cpp scene/3d/path.cpp
#: scene/3d/physics_body.cpp scene/3d/soft_body.cpp scene/3d/sprite_3d.cpp
-#: 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
+#: scene/3d/visual_instance.cpp 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
msgid "Offset"
msgstr ""
@@ -13759,12 +13759,11 @@ msgstr ""
#: editor/project_manager.cpp
msgid ""
-"Couldn't load project.godot in project path (error %d). It may be missing or "
-"corrupted."
+"Couldn't load project at '%s' (error %d). It may be missing or corrupted."
msgstr ""
#: editor/project_manager.cpp
-msgid "Couldn't edit project.godot in project path."
+msgid "Couldn't save project at '%s' (error %d)."
msgstr ""
#: editor/project_manager.cpp
@@ -22313,6 +22312,14 @@ msgstr "Огледало"
msgid "AABB"
msgstr ""
+#: scene/3d/visual_instance.cpp
+msgid "Sorting"
+msgstr ""
+
+#: scene/3d/visual_instance.cpp
+msgid "Use AABB Center"
+msgstr ""
+
#: scene/3d/visual_instance.cpp scene/resources/navigation_mesh.cpp
msgid "Geometry"
msgstr ""
diff --git a/editor/translations/ml.po b/editor/translations/ml.po
index 35845df066..171cc17fdb 100644
--- a/editor/translations/ml.po
+++ b/editor/translations/ml.po
@@ -12440,9 +12440,10 @@ msgstr "à´ªàµà´°à´µàµƒà´¤àµà´¤à´¿à´•ൾ:"
#: scene/2d/path_2d.cpp scene/2d/polygon_2d.cpp scene/2d/sprite.cpp
#: scene/3d/cpu_particles.cpp scene/3d/label_3d.cpp scene/3d/path.cpp
#: scene/3d/physics_body.cpp scene/3d/soft_body.cpp scene/3d/sprite_3d.cpp
-#: 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
+#: scene/3d/visual_instance.cpp 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
msgid "Offset"
msgstr ""
@@ -13783,12 +13784,11 @@ msgstr ""
#: editor/project_manager.cpp
msgid ""
-"Couldn't load project.godot in project path (error %d). It may be missing or "
-"corrupted."
+"Couldn't load project at '%s' (error %d). It may be missing or corrupted."
msgstr ""
#: editor/project_manager.cpp
-msgid "Couldn't edit project.godot in project path."
+msgid "Couldn't save project at '%s' (error %d)."
msgstr ""
#: editor/project_manager.cpp
@@ -22389,6 +22389,14 @@ msgstr "à´•à´£àµà´£à´¾à´Ÿà´¿"
msgid "AABB"
msgstr ""
+#: scene/3d/visual_instance.cpp
+msgid "Sorting"
+msgstr ""
+
+#: scene/3d/visual_instance.cpp
+msgid "Use AABB Center"
+msgstr ""
+
#: scene/3d/visual_instance.cpp scene/resources/navigation_mesh.cpp
msgid "Geometry"
msgstr ""
diff --git a/editor/translations/mr.po b/editor/translations/mr.po
index 6baf1dc52e..24300da41a 100644
--- a/editor/translations/mr.po
+++ b/editor/translations/mr.po
@@ -12432,9 +12432,10 @@ msgstr "अâ€à¥…निमेशन टà¥à¤°à¥€"
#: scene/2d/path_2d.cpp scene/2d/polygon_2d.cpp scene/2d/sprite.cpp
#: scene/3d/cpu_particles.cpp scene/3d/label_3d.cpp scene/3d/path.cpp
#: scene/3d/physics_body.cpp scene/3d/soft_body.cpp scene/3d/sprite_3d.cpp
-#: 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
+#: scene/3d/visual_instance.cpp 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
msgid "Offset"
msgstr ""
@@ -13776,12 +13777,11 @@ msgstr ""
#: editor/project_manager.cpp
msgid ""
-"Couldn't load project.godot in project path (error %d). It may be missing or "
-"corrupted."
+"Couldn't load project at '%s' (error %d). It may be missing or corrupted."
msgstr ""
#: editor/project_manager.cpp
-msgid "Couldn't edit project.godot in project path."
+msgid "Couldn't save project at '%s' (error %d)."
msgstr ""
#: editor/project_manager.cpp
@@ -22411,6 +22411,14 @@ msgstr "तà¥à¤°à¥à¤Ÿà¥€!"
msgid "AABB"
msgstr ""
+#: scene/3d/visual_instance.cpp
+msgid "Sorting"
+msgstr ""
+
+#: scene/3d/visual_instance.cpp
+msgid "Use AABB Center"
+msgstr ""
+
#: scene/3d/visual_instance.cpp scene/resources/navigation_mesh.cpp
msgid "Geometry"
msgstr ""
diff --git a/editor/translations/ms.po b/editor/translations/ms.po
index adb377d13a..3b34efe6f2 100644
--- a/editor/translations/ms.po
+++ b/editor/translations/ms.po
@@ -12936,9 +12936,10 @@ msgstr "Pilihan Snap"
#: scene/2d/path_2d.cpp scene/2d/polygon_2d.cpp scene/2d/sprite.cpp
#: scene/3d/cpu_particles.cpp scene/3d/label_3d.cpp scene/3d/path.cpp
#: scene/3d/physics_body.cpp scene/3d/soft_body.cpp scene/3d/sprite_3d.cpp
-#: 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
+#: scene/3d/visual_instance.cpp 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 "Grid Offset:"
@@ -14318,12 +14319,11 @@ msgstr ""
#: editor/project_manager.cpp
msgid ""
-"Couldn't load project.godot in project path (error %d). It may be missing or "
-"corrupted."
+"Couldn't load project at '%s' (error %d). It may be missing or corrupted."
msgstr ""
#: editor/project_manager.cpp
-msgid "Couldn't edit project.godot in project path."
+msgid "Couldn't save project at '%s' (error %d)."
msgstr ""
#: editor/project_manager.cpp
@@ -23441,6 +23441,15 @@ msgstr "%s Ralat"
msgid "AABB"
msgstr ""
+#: scene/3d/visual_instance.cpp
+#, fuzzy
+msgid "Sorting"
+msgstr "Mengimport:"
+
+#: scene/3d/visual_instance.cpp
+msgid "Use AABB Center"
+msgstr ""
+
#: scene/3d/visual_instance.cpp scene/resources/navigation_mesh.cpp
#, fuzzy
msgid "Geometry"
diff --git a/editor/translations/nb.po b/editor/translations/nb.po
index b39bc2a602..9d831aee5d 100644
--- a/editor/translations/nb.po
+++ b/editor/translations/nb.po
@@ -18,7 +18,7 @@
# Patrick Sletvold <patricksletvold@hotmail.com>, 2021.
# Kristoffer <kskau93@gmail.com>, 2021.
# Lili Zoey <sayaks1@gmail.com>, 2021.
-# slasken06 <ask.skivdal@gmail.com>, 2021.
+# slasken06 <ask.skivdal@gmail.com>, 2021, 2022.
# Daniel Skogly <daniel@klungo.no>, 2021.
# Imre Kristoffer Eilertsen <imreeil42@gmail.com>, 2022.
# Edvard Ekrem Sæther <edvardekrem@gmail.com>, 2022.
@@ -28,8 +28,8 @@ msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"Report-Msgid-Bugs-To: https://github.com/godotengine/godot\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2022-03-20 03:01+0000\n"
-"Last-Translator: Changry <c@changry.no>\n"
+"PO-Revision-Date: 2022-12-08 10:28+0000\n"
+"Last-Translator: slasken06 <ask.skivdal@gmail.com>\n"
"Language-Team: Norwegian Bokmål <https://hosted.weblate.org/projects/godot-"
"engine/godot/nb_NO/>\n"
"Language: nb\n"
@@ -37,7 +37,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
-"X-Generator: Weblate 4.12-dev\n"
+"X-Generator: Weblate 4.15-dev\n"
#: core/bind/core_bind.cpp main/main.cpp
msgid "Tablet Driver"
@@ -118,9 +118,8 @@ msgstr "Minimert"
#: core/bind/core_bind.cpp core/project_settings.cpp scene/gui/dialogs.cpp
#: scene/gui/graph_node.cpp
-#, fuzzy
msgid "Resizable"
-msgstr "Kan Endre Størrelse"
+msgstr "Skalerbar"
#: 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
@@ -230,7 +229,6 @@ msgid "Network"
msgstr "Nettverk"
#: core/io/file_access_network.cpp
-#, fuzzy
msgid "Remote FS"
msgstr "Fjernstyrt FS"
@@ -243,7 +241,6 @@ msgid "Page Read Ahead"
msgstr ""
#: core/io/http_client.cpp
-#, fuzzy
msgid "Blocking Mode Enabled"
msgstr "Blokkeringsmodus Aktivert"
@@ -252,7 +249,6 @@ msgid "Connection"
msgstr "Tilkobling"
#: core/io/http_client.cpp
-#, fuzzy
msgid "Read Chunk Size"
msgstr "Les Chunk Størrelse"
@@ -286,7 +282,7 @@ msgstr "Overføringsmodus"
#: core/io/packet_peer.cpp
msgid "Encode Buffer Max Size"
-msgstr ""
+msgstr "Enkodingsbuffer Maks Størrelse"
#: core/io/packet_peer.cpp
msgid "Input Buffer Max Size"
@@ -13499,9 +13495,10 @@ msgstr "Snapping innstillinger"
#: scene/2d/path_2d.cpp scene/2d/polygon_2d.cpp scene/2d/sprite.cpp
#: scene/3d/cpu_particles.cpp scene/3d/label_3d.cpp scene/3d/path.cpp
#: scene/3d/physics_body.cpp scene/3d/soft_body.cpp scene/3d/sprite_3d.cpp
-#: 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
+#: scene/3d/visual_instance.cpp 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 "Avstand:"
@@ -14927,16 +14924,17 @@ msgid "Invalid project path (changed anything?)."
msgstr ""
#: editor/project_manager.cpp
+#, fuzzy
msgid ""
-"Couldn't load project.godot in project path (error %d). It may be missing or "
-"corrupted."
+"Couldn't load project at '%s' (error %d). It may be missing or corrupted."
msgstr ""
"Kunne ikke laste project.godot i prosjektstien (feil %d). Den kan mangle "
"eller være korrupt."
#: editor/project_manager.cpp
-msgid "Couldn't edit project.godot in project path."
-msgstr "Kunne ikke endre project.godot i projsektstien."
+#, fuzzy
+msgid "Couldn't save project at '%s' (error %d)."
+msgstr "Kan ikke åpne prosjekt"
#: editor/project_manager.cpp
msgid "Couldn't create project.godot in project path."
@@ -24341,6 +24339,15 @@ msgstr "Feil!"
msgid "AABB"
msgstr ""
+#: scene/3d/visual_instance.cpp
+#, fuzzy
+msgid "Sorting"
+msgstr "Sortering"
+
+#: scene/3d/visual_instance.cpp
+msgid "Use AABB Center"
+msgstr ""
+
#: scene/3d/visual_instance.cpp scene/resources/navigation_mesh.cpp
#, fuzzy
msgid "Geometry"
diff --git a/editor/translations/nl.po b/editor/translations/nl.po
index 2b09ed5abc..5e80c53732 100644
--- a/editor/translations/nl.po
+++ b/editor/translations/nl.po
@@ -13261,9 +13261,10 @@ msgstr "Kleefinstellingen"
#: scene/2d/path_2d.cpp scene/2d/polygon_2d.cpp scene/2d/sprite.cpp
#: scene/3d/cpu_particles.cpp scene/3d/label_3d.cpp scene/3d/path.cpp
#: scene/3d/physics_body.cpp scene/3d/soft_body.cpp scene/3d/sprite_3d.cpp
-#: 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
+#: scene/3d/visual_instance.cpp 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 "Afstand:"
@@ -14731,16 +14732,17 @@ msgid "Invalid project path (changed anything?)."
msgstr "Ongeldig projectpad (iets veranderd?)."
#: editor/project_manager.cpp
+#, fuzzy
msgid ""
-"Couldn't load project.godot in project path (error %d). It may be missing or "
-"corrupted."
+"Couldn't load project at '%s' (error %d). It may be missing or corrupted."
msgstr ""
"Kan project.godot in project pad niet laden (error %d). Mogelijk is het "
"bestand niet aanwezig of corrupt."
#: editor/project_manager.cpp
-msgid "Couldn't edit project.godot in project path."
-msgstr "Kan project.godot niet bewerken in projectpad."
+#, fuzzy
+msgid "Couldn't save project at '%s' (error %d)."
+msgstr "Kan project niet openen op '%s'."
#: editor/project_manager.cpp
msgid "Couldn't create project.godot in project path."
@@ -24277,6 +24279,15 @@ msgstr "Fout"
msgid "AABB"
msgstr ""
+#: scene/3d/visual_instance.cpp
+#, fuzzy
+msgid "Sorting"
+msgstr "Sorteren"
+
+#: scene/3d/visual_instance.cpp
+msgid "Use AABB Center"
+msgstr ""
+
#: scene/3d/visual_instance.cpp scene/resources/navigation_mesh.cpp
#, fuzzy
msgid "Geometry"
diff --git a/editor/translations/pl.po b/editor/translations/pl.po
index 7b7e680cff..47b7bfe98a 100644
--- a/editor/translations/pl.po
+++ b/editor/translations/pl.po
@@ -64,13 +64,18 @@
# Dawid Skubij <davidsd@tlen.pl>, 2022.
# kingofsponges <q.patex.q@gmail.com>, 2022.
# Patryk Morawski <gormit7@gmail.com>, 2022.
+# Adrians <adrianspl@o2.pl>, 2022.
+# Wodorek <Krol.w94@gmail.com>, 2022.
+# Filip Gliszczyński <filipgliszczynski@gmail.com>, 2022.
+# Piotr Åšlusarz <piotrekslusarz@outlook.com>, 2022.
+# Jan Kurzak <Iqaz0oki@outlook.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-08-17 18:20+0000\n"
-"Last-Translator: Patryk Morawski <gormit7@gmail.com>\n"
+"PO-Revision-Date: 2022-12-12 09:46+0000\n"
+"Last-Translator: Tomek <kobewi4e@gmail.com>\n"
"Language-Team: Polish <https://hosted.weblate.org/projects/godot-engine/"
"godot/pl/>\n"
"Language: pl\n"
@@ -79,7 +84,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.14-dev\n"
+"X-Generator: Weblate 4.15-dev\n"
#: core/bind/core_bind.cpp main/main.cpp
msgid "Tablet Driver"
@@ -902,9 +907,8 @@ msgid "Connect Timeout Seconds"
msgstr "Sekundowy limit czasu połączenia"
#: core/register_core_types.cpp
-#, fuzzy
msgid "Packet Peer Stream"
-msgstr "Strumień członków pakietów"
+msgstr "Strumień pakietów równorzędnych"
#: core/register_core_types.cpp
msgid "Max Buffer (Power of 2)"
@@ -1159,9 +1163,8 @@ msgstr "Animacja Wywołanie funkcji"
#: 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 "Klatka %"
+msgstr "Klatka"
#: editor/animation_track_editor.cpp editor/editor_profiler.cpp
#: scene/2d/cpu_particles_2d.cpp scene/2d/particles_2d.cpp
@@ -1172,16 +1175,14 @@ msgstr "Czas"
#: editor/animation_track_editor.cpp editor/import/resource_importer_scene.cpp
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Location"
msgstr "Lokalizacja"
#: 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 "Krok obrotu:"
+msgstr "Obrót"
#: editor/animation_track_editor.cpp editor/script_editor_debugger.cpp
#: modules/visual_script/visual_script_nodes.cpp scene/gui/range.cpp
@@ -1189,9 +1190,8 @@ msgid "Value"
msgstr "Wartość"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Arg Count"
-msgstr "Ilośc:"
+msgstr "Liczba argumentów"
#: editor/animation_track_editor.cpp main/main.cpp
#: modules/mono/mono_gd/gd_mono.cpp
@@ -1206,14 +1206,12 @@ msgid "Type"
msgstr "Typ"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "In Handle"
-msgstr "Ustaw uchwyt"
+msgstr "Uchwyt wejściowy"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Out Handle"
-msgstr "Ustaw uchwyt"
+msgstr "Uchwyt wyjściowy"
#: editor/animation_track_editor.cpp
#: editor/import/resource_importer_texture.cpp
@@ -1223,14 +1221,12 @@ msgid "Stream"
msgstr "Strumień"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Start Offset"
-msgstr "Offset siatki:"
+msgstr "Rozpocznij przesunięcie"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "End Offset"
-msgstr "Przesunięcie:"
+msgstr "Koniec przesunięcia"
#: editor/animation_track_editor.cpp editor/editor_settings.cpp
#: editor/import/resource_importer_scene.cpp
@@ -1243,9 +1239,8 @@ msgid "Animation"
msgstr "Animacja"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Easing"
-msgstr "Åagodne wejÅ›cie-wyjÅ›cie"
+msgstr "Wygładzanie"
#: editor/animation_track_editor.cpp
msgid "Anim Multi Change Keyframe Time"
@@ -1354,19 +1349,16 @@ msgid "Remove this track."
msgstr "Usuń tę ścieżkę."
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Time (s):"
-msgstr "Czas (s): "
+msgstr "Czas (s):"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Position:"
-msgstr "Pozycja"
+msgstr "Pozycja:"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Rotation:"
-msgstr "Krok obrotu:"
+msgstr "Obrót:"
#: editor/animation_track_editor.cpp
#: editor/plugins/animation_tree_player_editor_plugin.cpp
@@ -1383,44 +1375,36 @@ msgid "Type:"
msgstr "Typ:"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "(Invalid, expected type: %s)"
-msgstr "Szablon eksportu nieprawidłowy:"
+msgstr "(Nieprawidłowy, oczekiwano typ: %s)"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Easing:"
-msgstr "Åagodne wejÅ›cie-wyjÅ›cie"
+msgstr "Åagodne wejÅ›cie-wyjÅ›cie:"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "In-Handle:"
-msgstr "Ustaw uchwyt"
+msgstr "Uchwyt wew.:"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Out-Handle:"
-msgstr "Ustaw uchwyt"
+msgstr "Uchwyt zew.:"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Stream:"
-msgstr "Członek transmisji"
+msgstr "Strumień:"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Start (s):"
-msgstr "Restart(y):"
+msgstr "Start (s):"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "End (s):"
-msgstr "Zanikanie w (s):"
+msgstr "Koniec (s):"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Animation Clip:"
-msgstr "Animacje:"
+msgstr "Animacja:"
#: editor/animation_track_editor.cpp
msgid "Toggle Track Enabled"
@@ -1634,9 +1618,8 @@ msgid "Add Method Track Key"
msgstr "Dodaj klucz ścieżki metody"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Method not found in object:"
-msgstr "Metoda nie znaleziona w obiekcie: "
+msgstr "Metoda nie znaleziona w obiekcie:"
#: editor/animation_track_editor.cpp
msgid "Anim Move Keys"
@@ -2601,9 +2584,8 @@ msgid "There is no '%s' file."
msgstr "Nie ma pliku \"%s\"."
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Layout:"
-msgstr "Układ"
+msgstr "Układ:"
#: editor/editor_audio_buses.cpp
msgid "Invalid file, not an audio bus layout."
@@ -2809,19 +2791,16 @@ msgid "Project export for platform:"
msgstr "Eksportowanie projektu dla platformy:"
#: editor/editor_export.cpp
-#, fuzzy
msgid "Completed with warnings."
-msgstr "Skopiuj ścieżkę węzła"
+msgstr "Ukończone z ostrzeżeniami."
#: editor/editor_export.cpp
-#, fuzzy
msgid "Completed successfully."
-msgstr "Pakiet zainstalowano poprawnie!"
+msgstr "Zakończono pomyślnie."
#: editor/editor_export.cpp
-#, fuzzy
msgid "Failed."
-msgstr "Nie powiodło się:"
+msgstr "Nie powiodło się."
#: editor/editor_export.cpp
msgid "Storing File:"
@@ -2844,19 +2823,16 @@ msgid "Cannot create file \"%s\"."
msgstr "Nie można utworzyć pliku \"%s\"."
#: editor/editor_export.cpp
-#, fuzzy
msgid "Failed to export project files."
-msgstr "Nie udało się eksportować plików projektu"
+msgstr "Eksportowanie plików projektu nie powiodło się."
#: editor/editor_export.cpp
-#, fuzzy
msgid "Can't open file to read from path \"%s\"."
msgstr "Nie można otworzyć pliku do zapisu:"
#: editor/editor_export.cpp
-#, fuzzy
msgid "Save ZIP"
-msgstr "Zapisz jako"
+msgstr "Zapisz plik ZIP"
#: editor/editor_export.cpp
msgid ""
@@ -2929,9 +2905,8 @@ msgid "Release"
msgstr "Wydanie"
#: editor/editor_export.cpp
-#, fuzzy
msgid "Binary Format"
-msgstr "Operator koloru."
+msgstr "Format binarny"
#: editor/editor_export.cpp
msgid "64 Bits"
@@ -2942,9 +2917,8 @@ msgid "Embed PCK"
msgstr "Osadź PCK"
#: editor/editor_export.cpp platform/osx/export/export.cpp
-#, fuzzy
msgid "Texture Format"
-msgstr "Obszar tekstury"
+msgstr "Format tekstury"
#: editor/editor_export.cpp
msgid "BPTC"
@@ -2955,19 +2929,16 @@ msgid "S3TC"
msgstr "S3TC"
#: editor/editor_export.cpp platform/osx/export/export.cpp
-#, fuzzy
msgid "ETC"
-msgstr "TCP"
+msgstr "ETC"
#: editor/editor_export.cpp platform/osx/export/export.cpp
-#, fuzzy
msgid "ETC2"
msgstr "ETC2"
#: editor/editor_export.cpp
-#, fuzzy
msgid "No BPTC Fallbacks"
-msgstr "Fallback"
+msgstr "Brak fallbacków BPTC"
#: editor/editor_export.cpp platform/android/export/export_plugin.cpp
#: platform/iphone/export/export.cpp platform/javascript/export/export.cpp
@@ -2982,30 +2953,25 @@ msgid "Custom release template not found."
msgstr "Nie znaleziono własnego szablonu wydania."
#: editor/editor_export.cpp
-#, fuzzy
msgid "Prepare Template"
-msgstr "ZarzÄ…dzaj szablonami"
+msgstr "Przygotuj szablon"
#: editor/editor_export.cpp platform/osx/export/export.cpp
-#, fuzzy
msgid "The given export path doesn't exist."
-msgstr "Podana ścieżka eksportu nie istnieje:"
+msgstr "Podana ścieżka eksportu nie istnieje."
#: editor/editor_export.cpp platform/javascript/export/export.cpp
-#, fuzzy
msgid "Template file not found: \"%s\"."
-msgstr "Nie znaleziono pliku szablonu:"
+msgstr "Nie znaleziono pliku szablonu: \"%s\"."
#: editor/editor_export.cpp
-#, fuzzy
msgid "Failed to copy export template."
-msgstr "Szablon eksportu nieprawidłowy:"
+msgstr "Kopiowanie szablonu eksportu nie powiodło się."
#: editor/editor_export.cpp platform/windows/export/export.cpp
#: platform/x11/export/export.cpp
-#, fuzzy
msgid "PCK Embedding"
-msgstr "Wyrównanie"
+msgstr "Osadzanie plików PCK"
#: editor/editor_export.cpp
msgid "On 32-bit exports the embedded PCK cannot be bigger than 4 GiB."
@@ -3218,9 +3184,8 @@ msgid "Manage Editor Feature Profiles"
msgstr "Zarządzaj profilami funkcjonalności edytora"
#: editor/editor_feature_profile.cpp
-#, fuzzy
msgid "Default Feature Profile"
-msgstr "Profil funkcjonalności Godota"
+msgstr "Profil domyślnych funkcji"
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "Select Current Folder"
@@ -3292,14 +3257,12 @@ msgid "Save a File"
msgstr "Zapisz plik"
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
-#, fuzzy
msgid "Access"
-msgstr "Sukces!"
+msgstr "Dostęp"
#: editor/editor_file_dialog.cpp editor/editor_settings.cpp
-#, fuzzy
msgid "Display Mode"
-msgstr "Tryb odtwarzania:"
+msgstr "Tryb wyświetlania"
#: editor/editor_file_dialog.cpp
#: editor/import/resource_importer_layered_texture.cpp
@@ -3312,30 +3275,25 @@ msgstr "Tryb odtwarzania:"
#: scene/resources/environment.cpp scene/resources/material.cpp
#: scene/resources/visual_shader.cpp
#: servers/audio/effects/audio_effect_distortion.cpp
-#, fuzzy
msgid "Mode"
-msgstr "Tryb przesuwania"
+msgstr "Tryb"
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
-#, fuzzy
msgid "Current Dir"
-msgstr "Bieżący:"
+msgstr "Bieżący katalog"
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
-#, fuzzy
msgid "Current File"
-msgstr "Bieżący profil:"
+msgstr "Bieżący Plik"
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
-#, fuzzy
msgid "Current Path"
-msgstr "Bieżący:"
+msgstr "Bieżąca ścieżka"
#: editor/editor_file_dialog.cpp editor/editor_settings.cpp
#: scene/gui/file_dialog.cpp
-#, fuzzy
msgid "Show Hidden Files"
-msgstr "Przełącz ukryte pliki"
+msgstr "Pokaż ukryte pliki"
#: editor/editor_file_dialog.cpp
msgid "Disable Overwrite Warning"
@@ -3439,7 +3397,6 @@ msgid "(Re)Importing Assets"
msgstr "(Ponowne) importowanie zasobów"
#: editor/editor_file_system.cpp
-#, fuzzy
msgid "Reimport Missing Imported Files"
msgstr "Zaimportuj ponownie brakujÄ…ce importowane pliki"
@@ -3632,36 +3589,30 @@ msgid "Property:"
msgstr "Właściwość:"
#: editor/editor_inspector.cpp editor/editor_spin_slider.cpp
-#, fuzzy
msgid "Label"
-msgstr "Wartość"
+msgstr "Etykieta"
#: editor/editor_inspector.cpp editor/editor_spin_slider.cpp
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Read Only"
-msgstr "Tylko metody"
+msgstr "Tylko do odczytu"
#: editor/editor_inspector.cpp editor/plugins/item_list_editor_plugin.cpp
-#, fuzzy
msgid "Checkable"
-msgstr "Element wyboru"
+msgstr "Zaznaczalne"
#: editor/editor_inspector.cpp editor/plugins/item_list_editor_plugin.cpp
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Checked"
-msgstr "Zaznaczony element wyboru"
+msgstr "Sprawdzone"
#: editor/editor_inspector.cpp
-#, fuzzy
msgid "Draw Red"
-msgstr "Wywołania rysowania:"
+msgstr "Rysuj czerwony"
#: editor/editor_inspector.cpp
-#, fuzzy
msgid "Keying"
-msgstr "Uruchom"
+msgstr "Kluczowanie"
#: editor/editor_inspector.cpp
msgid "Pin value"
@@ -4024,14 +3975,12 @@ msgid "Quick Open Script..."
msgstr "Szybkie otwieranie skryptu..."
#: editor/editor_node.cpp
-#, fuzzy
msgid "Save & Reload"
msgstr "Zapisz i zrestartuj"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Save changes to '%s' before reloading?"
-msgstr "Zapisać zmiany w \"%s\" przed zamknięciem?"
+msgstr "Zapisać zmiany w '%s' przed zrestartowaniem?"
#: editor/editor_node.cpp
msgid "Save & Close"
@@ -4150,9 +4099,8 @@ msgid "Open Project Manager?"
msgstr "Otworzyć menadżera projektów?"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Save changes to the following scene(s) before reloading?"
-msgstr "Czy zapisać zmiany w aktualnej scenie/scenach przed wyjściem?"
+msgstr "Czy zapisać zmiany w aktualnej scenie/scenach przed zrestartowaniem?"
#: editor/editor_node.cpp
msgid "Save & Quit"
@@ -4343,24 +4291,20 @@ msgstr ""
#: editor/editor_node.cpp editor/editor_settings.cpp editor/scene_tree_dock.cpp
#: servers/arvr/arvr_interface.cpp
-#, fuzzy
msgid "Interface"
-msgstr "Interfejs użytkownika"
+msgstr "Interfejs"
#: editor/editor_node.cpp editor/editor_settings.cpp
-#, fuzzy
msgid "Scene Tabs"
-msgstr "Przełącz zakładkę sceny"
+msgstr "Zakładki scen"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Always Show Close Button"
-msgstr "Zawsze pokazuj siatkÄ™"
+msgstr "Zawsze pokazuj przycisk wyjścia"
#: editor/editor_node.cpp editor/editor_settings.cpp
-#, fuzzy
msgid "Resize If Many Tabs"
-msgstr "Zmień rozmiar jeśli wyświetlonych jest wiele zakładek"
+msgstr "Rozszerz rozmiar jeżeli jest wiele zakładek"
#: editor/editor_node.cpp editor/editor_settings.cpp
msgid "Minimum Width"
@@ -4371,9 +4315,8 @@ msgid "Output"
msgstr "Konsola"
#: editor/editor_node.cpp editor/editor_settings.cpp
-#, fuzzy
msgid "Always Clear Output On Play"
-msgstr "Wyczyść wyjście"
+msgstr "Zawsze wyczyszczaj wyjście gdy włączono grę"
#: editor/editor_node.cpp editor/editor_settings.cpp
msgid "Always Open Output On Play"
@@ -4388,41 +4331,34 @@ msgid "Save On Focus Loss"
msgstr "Zapisz przy utracie skupienia"
#: editor/editor_node.cpp editor/editor_settings.cpp
-#, fuzzy
msgid "Save Each Scene On Quit"
-msgstr "Zapisz gałąź jako scenę"
+msgstr "Zapisz każdą scenę przed wyjściem"
#: editor/editor_node.cpp editor/editor_settings.cpp
-#, fuzzy
msgid "Quit Confirmation"
-msgstr "Wyświetlaj informacje"
+msgstr "Potwierdzenie wyjścia"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Show Update Spinner"
-msgstr "Ukryj wiatraczek aktualizacji"
+msgstr "Pokaż suwak aktualizacji"
#: editor/editor_node.cpp
msgid "Update Continuously"
msgstr "Aktualizuj ciÄ…gle"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Update Vital Only"
-msgstr "Zaktualizuj istotne zmiany"
+msgstr "Aktualizuj tylko istotne"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Localize Settings"
-msgstr "Lokalizacja"
+msgstr "Lokalizuj ustawienia"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Restore Scenes On Load"
-msgstr "Pozyskaj węzeł sceny"
+msgstr "Przywracaj sceny po załadowaniu"
#: editor/editor_node.cpp editor/editor_settings.cpp
-#, fuzzy
msgid "Show Thumbnail On Hover"
msgstr "Pokaż miniaturę po najechaniu kursorem"
@@ -4431,18 +4367,16 @@ msgid "Inspector"
msgstr "Inspektor"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Default Property Name Style"
-msgstr "Ścieżka do projektu:"
+msgstr "Domyślny styl nazw właściwości"
#: editor/editor_node.cpp
msgid "Default Float Step"
msgstr "Domyślny krok zmiennoprzecinkowy"
#: editor/editor_node.cpp scene/gui/tree.cpp
-#, fuzzy
msgid "Disable Folding"
-msgstr "Wyłączony przycisk"
+msgstr "Wyłącz zwijanie"
#: editor/editor_node.cpp
msgid "Auto Unfold Foreign Scenes"
@@ -4457,19 +4391,16 @@ msgid "Horizontal Vector Types Editing"
msgstr "Edycja poziomych typów wektorów"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Open Resources In Current Inspector"
-msgstr "Otwórz w inspektorze"
+msgstr "Otwórz zasoby w aktualnym inspektorze"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Resources To Open In New Inspector"
-msgstr "Otwórz w inspektorze"
+msgstr "Zasoby do otwarcia w nowym inspektorze"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Default Color Picker Mode"
-msgstr "Domyślny tryb pipety"
+msgstr "Domyślny tryb pobieracza kolorów"
#: editor/editor_node.cpp editor/plugins/version_control_editor_plugin.cpp
msgid "Version Control"
@@ -4477,7 +4408,7 @@ msgstr "Kontrola wersji"
#: editor/editor_node.cpp editor/plugins/version_control_editor_plugin.cpp
msgid "Username"
-msgstr "Użytkownik"
+msgstr "Nazwa użytkownika"
#: editor/editor_node.cpp editor/plugins/version_control_editor_plugin.cpp
msgid "SSH Public Key Path"
@@ -5121,14 +5052,12 @@ msgid "Debugger"
msgstr "Debugger"
#: editor/editor_profiler.cpp
-#, fuzzy
msgid "Profiler Frame History Size"
msgstr "Rozmiar historii klatek profilera"
#: editor/editor_profiler.cpp
-#, fuzzy
msgid "Profiler Frame Max Functions"
-msgstr "Zmień nazwę funkcji"
+msgstr "Maksymalna ilość funkcji klatki profilera"
#: editor/editor_properties.cpp
msgid "Edit Text:"
@@ -5197,9 +5126,8 @@ msgid "Size:"
msgstr "Rozmiar:"
#: editor/editor_properties_array_dict.cpp
-#, fuzzy
msgid "Page:"
-msgstr "Strona: "
+msgstr "Strona:"
#: editor/editor_properties_array_dict.cpp
#: editor/plugins/theme_editor_plugin.cpp
@@ -5261,20 +5189,17 @@ msgstr "Nowy %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 "Zmień typ podstawowy"
+msgstr "Typ bazowy"
#: editor/editor_resource_picker.cpp
-#, fuzzy
msgid "Edited Resource"
-msgstr "Dodaj Zasób"
+msgstr "Edytowany zasób"
#: editor/editor_resource_picker.cpp scene/gui/line_edit.cpp
#: scene/gui/slider.cpp scene/gui/spin_box.cpp
-#, fuzzy
msgid "Editable"
-msgstr "Edytowalny element"
+msgstr "Edytowalny"
#: editor/editor_resource_picker.cpp editor/property_editor.cpp
msgid "New Script"
@@ -5285,9 +5210,8 @@ msgid "Extend Script"
msgstr "Rozszerz skrypt"
#: editor/editor_resource_picker.cpp
-#, fuzzy
msgid "Script Owner"
-msgstr "Nazwa skryptu:"
+msgstr "Właściciel skryptu"
#: editor/editor_run_native.cpp
msgid ""
@@ -5300,9 +5224,8 @@ msgstr ""
"jako uruchamialny."
#: editor/editor_run_native.cpp
-#, fuzzy
msgid "Project Run"
-msgstr "Projekt"
+msgstr "Uruchom projekt"
#: editor/editor_run_script.cpp
msgid "Write your logic in the _run() method."
@@ -5329,14 +5252,12 @@ msgid "Did you forget the '_run' method?"
msgstr "Zapomniano metody \"_run\"?"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Editor Language"
-msgstr "Układ edytora"
+msgstr "Język edytora"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Display Scale"
-msgstr "Pokaż wszystko"
+msgstr "Rozmiar wyświetlania"
#: editor/editor_settings.cpp
msgid "Custom Display Scale"
@@ -5359,21 +5280,18 @@ msgid "Font Hinting"
msgstr "Czcionka podpowiedzi"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Main Font"
-msgstr "Scena główna"
+msgstr "Główna czcionka"
#: editor/editor_settings.cpp
msgid "Main Font Bold"
msgstr "Główna czcionka pogrubiona"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Code Font"
-msgstr "Dodaj punkt węzła"
+msgstr "Czcionka kodu"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Dim Editor On Dialog Popup"
msgstr "PrzygaÅ› edytor przy wyskakujÄ…cym oknie"
@@ -5386,9 +5304,8 @@ msgid "Unfocused Low Processor Mode Sleep (µsec)"
msgstr "Nieskoncentrowany tryb uśpienia w trybie niskiego procesora (µsec)"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Separate Distraction Mode"
-msgstr "Tryb bez rozproszeń"
+msgstr "Oddzielny tryb bez rozproszeń"
#: editor/editor_settings.cpp
msgid "Automatically Open Screenshots"
@@ -5413,14 +5330,12 @@ msgid "Icon And Font Color"
msgstr "Kolor ikony i czcionki"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Base Color"
-msgstr "Kolory"
+msgstr "Kolor podstawowy"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Accent Color"
-msgstr "Wybierz Kolor"
+msgstr "Kolor akcentu"
#: editor/editor_settings.cpp scene/resources/environment.cpp
msgid "Contrast"
@@ -5431,109 +5346,92 @@ msgid "Relationship Line Opacity"
msgstr "Przezroczystość linii relacji"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Highlight Tabs"
-msgstr "Zapisywanie map światła"
+msgstr "Podświetl zakładki"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Border Size"
-msgstr "Brzegowe piksele"
+msgstr "Rozmiar obwódki"
#: editor/editor_settings.cpp
msgid "Use Graph Node Headers"
msgstr "Użyj wykresu nagłówków węzłów"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Additional Spacing"
-msgstr "Zapętlenie animacji"
+msgstr "Dodatkowe odstępy"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Custom Theme"
-msgstr "Motyw edytora"
+msgstr "Własny motyw"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Show Script Button"
-msgstr "Kółko w prawo"
+msgstr "Pokaż przycisk skryptu"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Directories"
-msgstr "Kierunki"
+msgstr "Katalogi"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Autoscan Project Path"
-msgstr "Ścieżka do projektu:"
+msgstr "Automatycznie skanuj ścieżkę projektu"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Default Project Path"
-msgstr "Ścieżka do projektu:"
+msgstr "Domyślna ścieżka projektu"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "On Save"
-msgstr "Zapisz"
+msgstr "Przy zapisie"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Compress Binary Resources"
-msgstr "Kopiuj zasób"
+msgstr "Skompresuj binarne zasoby"
#: editor/editor_settings.cpp
msgid "Safe Save On Backup Then Rename"
msgstr "Bezpieczne zapisywanie kopii zapasowej, a następnie zmiana nazwy"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "File Dialog"
-msgstr "Okno dialogowe XForm"
+msgstr "Dialog plików"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Thumbnail Size"
-msgstr "Miniatura..."
+msgstr "Rozmiar miniaturki"
#: editor/editor_settings.cpp
msgid "Docks"
msgstr "Doki"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Scene Tree"
-msgstr "Pozyskaj drzewo sceny"
+msgstr "Drzewo sceny"
#: editor/editor_settings.cpp
msgid "Start Create Dialog Fully Expanded"
msgstr "Rozpocznij tworzenie w pełni rozwiniętego okna dialogowego"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Always Show Folders"
-msgstr "Zawsze pokazuj siatkÄ™"
+msgstr "Zawsze pokazuj foldery"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Property Editor"
-msgstr "Edytor grup"
+msgstr "Edytor właściwości"
#: editor/editor_settings.cpp
msgid "Auto Refresh Interval"
msgstr "Czas między automatycznym odświeżaniem"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Subresource Hue Tint"
-msgstr "Zasoby"
+msgstr "Odcień barwy zasobów podrzędnych"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Color Theme"
-msgstr "Motyw edytora"
+msgstr "Motyw koloru"
#: editor/editor_settings.cpp scene/3d/label_3d.cpp
#: scene/resources/default_theme/default_theme.cpp
@@ -5542,14 +5440,12 @@ msgstr "Odstępy między liniami"
#: editor/editor_settings.cpp editor/plugins/script_text_editor.cpp
#: modules/gdscript/editor/gdscript_highlighter.cpp
-#, fuzzy
msgid "Highlighting"
-msgstr "Oświetlenie bezpośrednie"
+msgstr "Podświetlanie"
#: editor/editor_settings.cpp scene/gui/text_edit.cpp
-#, fuzzy
msgid "Syntax Highlighting"
-msgstr "Podświetlacz składni"
+msgstr "Podświetlanie składni"
#: editor/editor_settings.cpp scene/gui/text_edit.cpp
msgid "Highlight All Occurrences"
@@ -5564,28 +5460,24 @@ msgid "Highlight Type Safe Lines"
msgstr "Wyróżnij typy bezpiecznych linii"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Indent"
-msgstr "Wcięcie w lewo"
+msgstr "Wcięcie"
#: editor/editor_settings.cpp editor/plugins/script_text_editor.cpp
msgid "Auto Indent"
msgstr "Automatyczne wcięcie"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Convert Indent On Save"
-msgstr "Zamień wcięcia na spacje"
+msgstr "Zamień wcięcia przy zapisie"
#: editor/editor_settings.cpp scene/gui/text_edit.cpp
-#, fuzzy
msgid "Draw Tabs"
-msgstr "Wywołania rysowania:"
+msgstr "Rysuj taby"
#: editor/editor_settings.cpp scene/gui/text_edit.cpp
-#, fuzzy
msgid "Draw Spaces"
-msgstr "Wywołania rysowania:"
+msgstr "Rysuj spacje"
#: editor/editor_settings.cpp editor/plugins/spatial_editor_plugin.cpp
#: editor/plugins/tile_set_editor_plugin.cpp scene/2d/tile_map.cpp
@@ -5603,9 +5495,8 @@ msgid "V Scroll Speed"
msgstr "Pionowa szybkość przewijania"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Show Minimap"
-msgstr "Pokaż pozycję początkową"
+msgstr "Pokaż minimapę"
#: editor/editor_settings.cpp
msgid "Minimap Width"
@@ -5616,9 +5507,8 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr "Historia nawigacji dodatkowych przycisków myszy"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Drag And Drop Selection"
-msgstr "Wybór GridMap"
+msgstr "Przeciągnij i upuść zaznaczenie"
#: editor/editor_settings.cpp
msgid "Stay In Script Editor On Node Selected"
@@ -5629,9 +5519,8 @@ msgid "Appearance"
msgstr "WyglÄ…d"
#: editor/editor_settings.cpp scene/gui/text_edit.cpp
-#, fuzzy
msgid "Show Line Numbers"
-msgstr "Numer linii:"
+msgstr "Pokaż numery linii"
#: editor/editor_settings.cpp
#, fuzzy
@@ -5669,7 +5558,7 @@ msgstr "Wytyczne dotyczące długości linii miękkiej kolumny"
#: editor/editor_settings.cpp
msgid "Line Length Guideline Hard Column"
-msgstr ""
+msgstr "Wytyczne dotyczące długości linii twardej kolumny"
#: editor/editor_settings.cpp editor/plugins/script_editor_plugin.cpp
#, fuzzy
@@ -5678,33 +5567,31 @@ msgstr "Edytor skryptów"
#: editor/editor_settings.cpp
msgid "Show Members Overview"
-msgstr ""
+msgstr "Pokaż podgląd członków"
#: editor/editor_settings.cpp editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Files"
-msgstr "Plik"
+msgstr "Pliki"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Trim Trailing Whitespace On Save"
-msgstr "Przytnij końcowe białe znaki"
+msgstr "Przytnij końcowe białe znaki przy zapisie"
#: editor/editor_settings.cpp
msgid "Autosave Interval Secs"
-msgstr ""
+msgstr "czas autozapisu sek"
#: editor/editor_settings.cpp editor/plugins/script_editor_plugin.cpp
msgid "Restore Scripts On Load"
-msgstr ""
+msgstr "Przywróć skrypty przy załadowaniu"
#: editor/editor_settings.cpp
msgid "Auto Reload And Parse Scripts On Save"
-msgstr ""
+msgstr "Automatycznie przeładuj i zanalizuj skrypty przy zapisie"
#: editor/editor_settings.cpp
msgid "Auto Reload Scripts On External Change"
-msgstr ""
+msgstr "Automatycznie przeładuj skrypty przy zmianie zewnętrznej"
#: editor/editor_settings.cpp
#, fuzzy
@@ -5713,7 +5600,7 @@ msgstr "Opóźnienia wymuszania shaderów"
#: editor/editor_settings.cpp
msgid "Sort Members Outline Alphabetically"
-msgstr ""
+msgstr "Posortuj szkic członków alfabetycznie"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
msgid "Cursor"
@@ -5721,19 +5608,19 @@ msgstr "Kursor"
#: editor/editor_settings.cpp
msgid "Scroll Past End Of File"
-msgstr ""
+msgstr "Przewijaj za koniec pliku"
#: editor/editor_settings.cpp
msgid "Block Caret"
-msgstr ""
+msgstr "Zablokuj Karete"
#: editor/editor_settings.cpp
msgid "Caret Blink"
-msgstr ""
+msgstr "Mignięcie karety"
#: editor/editor_settings.cpp
msgid "Caret Blink Speed"
-msgstr ""
+msgstr "Prędkość migania karety"
#: editor/editor_settings.cpp
#, fuzzy
@@ -5748,15 +5635,15 @@ msgstr "Ukończenie"
#: editor/editor_settings.cpp
msgid "Idle Parse Delay"
-msgstr ""
+msgstr "Opóźnienie interpretacji"
#: editor/editor_settings.cpp
msgid "Auto Brace Complete"
-msgstr ""
+msgstr "Automatyczne zamykanie nawiasów"
#: editor/editor_settings.cpp
msgid "Code Complete Delay"
-msgstr ""
+msgstr "Opóźnienie zakończenia kodu"
#: editor/editor_settings.cpp
msgid "Put Callhint Tooltip Below Current Line"
@@ -13095,9 +12982,10 @@ msgstr "Opcje przyciÄ…gania"
#: scene/2d/path_2d.cpp scene/2d/polygon_2d.cpp scene/2d/sprite.cpp
#: scene/3d/cpu_particles.cpp scene/3d/label_3d.cpp scene/3d/path.cpp
#: scene/3d/physics_body.cpp scene/3d/soft_body.cpp scene/3d/sprite_3d.cpp
-#: 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
+#: scene/3d/visual_instance.cpp 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 "Przesunięcie:"
@@ -14534,16 +14422,17 @@ msgid "Invalid project path (changed anything?)."
msgstr "Niepoprawna ścieżka projektu (zmienić cokolwiek?)."
#: editor/project_manager.cpp
+#, fuzzy
msgid ""
-"Couldn't load project.godot in project path (error %d). It may be missing or "
-"corrupted."
+"Couldn't load project at '%s' (error %d). It may be missing or corrupted."
msgstr ""
"Nie udało się wczytać project.godot w ścieżce projektu (błąd %d). Może go "
"brakować lub być uszkodzony."
#: editor/project_manager.cpp
-msgid "Couldn't edit project.godot in project path."
-msgstr "Nie można było edytować engine.cfg w ścieżce projektu."
+#, fuzzy
+msgid "Couldn't save project at '%s' (error %d)."
+msgstr "Nie można otworzyć projektu w \"%s\"."
#: editor/project_manager.cpp
msgid "Couldn't create project.godot in project path."
@@ -17074,7 +16963,7 @@ msgstr "Dodaj pole architektury"
#: modules/gdnative/gdnative_library_editor_plugin.cpp
msgid "GDNativeLibrary"
-msgstr "GDNativeLibrary"
+msgstr "Natywna biblioteka GD"
#: modules/gdnative/gdnative_library_singleton_editor.cpp
msgid "Enabled GDNative Singleton"
@@ -18383,7 +18272,7 @@ msgstr "Iterator"
#: modules/visual_script/visual_script_flow_control.cpp
msgid "for (elem) in (input):"
-msgstr "for (element) in (wejście):"
+msgstr "dla (elementu) w (input)"
#: modules/visual_script/visual_script_flow_control.cpp
#, fuzzy
@@ -18555,9 +18444,8 @@ msgstr "Utwórz Tablicę"
#: modules/visual_script/visual_script_nodes.cpp scene/resources/material.cpp
#: scene/resources/visual_shader_nodes.cpp
-#, fuzzy
msgid "Operator"
-msgstr "Iterator"
+msgstr "Operator"
#: modules/visual_script/visual_script_nodes.cpp
#, fuzzy
@@ -18634,7 +18522,7 @@ msgstr "Pozyskaj samego siebie"
#: modules/visual_script/visual_script_nodes.cpp
msgid "CustomNode"
-msgstr "NiestandardowyWęzeł"
+msgstr "Niestandardowy węzeł"
#: modules/visual_script/visual_script_nodes.cpp
msgid "Custom node has no _step() method, can't process graph."
@@ -24139,6 +24027,15 @@ msgstr "Błąd"
msgid "AABB"
msgstr ""
+#: scene/3d/visual_instance.cpp
+#, fuzzy
+msgid "Sorting"
+msgstr "Sortuj"
+
+#: scene/3d/visual_instance.cpp
+msgid "Use AABB Center"
+msgstr ""
+
#: scene/3d/visual_instance.cpp scene/resources/navigation_mesh.cpp
#, fuzzy
msgid "Geometry"
@@ -24954,7 +24851,7 @@ msgstr ""
#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Caret"
-msgstr "Karetka"
+msgstr "Kareta"
#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Blink"
diff --git a/editor/translations/pr.po b/editor/translations/pr.po
index e8e4e5c79d..45bbc8daf0 100644
--- a/editor/translations/pr.po
+++ b/editor/translations/pr.po
@@ -12947,9 +12947,10 @@ msgstr "Yar, Blow th' Selected Down!"
#: scene/2d/path_2d.cpp scene/2d/polygon_2d.cpp scene/2d/sprite.cpp
#: scene/3d/cpu_particles.cpp scene/3d/label_3d.cpp scene/3d/path.cpp
#: scene/3d/physics_body.cpp scene/3d/soft_body.cpp scene/3d/sprite_3d.cpp
-#: 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
+#: scene/3d/visual_instance.cpp 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
msgid "Offset"
msgstr ""
@@ -14341,12 +14342,11 @@ msgstr ""
#: editor/project_manager.cpp
msgid ""
-"Couldn't load project.godot in project path (error %d). It may be missing or "
-"corrupted."
+"Couldn't load project at '%s' (error %d). It may be missing or corrupted."
msgstr ""
#: editor/project_manager.cpp
-msgid "Couldn't edit project.godot in project path."
+msgid "Couldn't save project at '%s' (error %d)."
msgstr ""
#: editor/project_manager.cpp
@@ -23398,6 +23398,15 @@ msgstr "Error loading yer Calligraphy Pen."
msgid "AABB"
msgstr ""
+#: scene/3d/visual_instance.cpp
+#, fuzzy
+msgid "Sorting"
+msgstr "Discharge ye' Signal"
+
+#: scene/3d/visual_instance.cpp
+msgid "Use AABB Center"
+msgstr ""
+
#: scene/3d/visual_instance.cpp scene/resources/navigation_mesh.cpp
msgid "Geometry"
msgstr ""
diff --git a/editor/translations/pt.po b/editor/translations/pt.po
index 3052fff9bb..85814ded34 100644
--- a/editor/translations/pt.po
+++ b/editor/translations/pt.po
@@ -13,7 +13,7 @@
# Rueben Stevens <supercell03@gmail.com>, 2017.
# SARDON <fabio3_Santos@hotmail.com>, 2017.
# Vinicius Gonçalves <viniciusgoncalves21@gmail.com>, 2017.
-# ssantos <ssantos@web.de>, 2018, 2019, 2020, 2021.
+# ssantos <ssantos@web.de>, 2018, 2019, 2020, 2021, 2022.
# Gonçalo Dinis Guerreiro João <goncalojoao205@gmail.com>, 2019.
# Manuela Silva <mmsrs@sky.com>, 2020.
# Murilo Gama <murilovsky2030@gmail.com>, 2020, 2022.
@@ -29,13 +29,15 @@
# Rafael Testa <rafael1testa@gmail.com>, 2022.
# Baiterson <baiter160@gmail.com>, 2022.
# Tuily <brizolla.tuily@gmail.com>, 2022.
+# Thuany <thutymsoares@gmail.com>, 2022.
+# Isaque Mendes <isaquemendes405@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-09-19 05:22+0000\n"
-"Last-Translator: Tuily <brizolla.tuily@gmail.com>\n"
+"PO-Revision-Date: 2022-11-19 08:35+0000\n"
+"Last-Translator: ssantos <ssantos@web.de>\n"
"Language-Team: Portuguese <https://hosted.weblate.org/projects/godot-engine/"
"godot/pt/>\n"
"Language: pt\n"
@@ -43,7 +45,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.14.1\n"
+"X-Generator: Weblate 4.15-dev\n"
#: core/bind/core_bind.cpp main/main.cpp
msgid "Tablet Driver"
@@ -2901,9 +2903,8 @@ msgid "ETC2"
msgstr "ETC2"
#: editor/editor_export.cpp
-#, fuzzy
msgid "No BPTC Fallbacks"
-msgstr "Forçar Shader de Reserva"
+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
@@ -5593,9 +5594,8 @@ msgid "Caret Blink Speed"
msgstr "Velocidade do Piscamento do Cursor"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Right Click Moves Caret"
-msgstr "Clique direito para adicionar ponto"
+msgstr "Clique direito move cursor de texto"
#: editor/editor_settings.cpp modules/gdscript/gdscript.cpp
#: modules/gdscript/gdscript_editor.cpp
@@ -5624,23 +5624,20 @@ msgid "Callhint Tooltip Offset"
msgstr "Deslocamento da Sugestão de Chamada"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Complete File Paths"
-msgstr "Copiar Caminho do Nó"
+msgstr "Caminhos Completos dos Arquivos"
#: editor/editor_settings.cpp modules/gdscript/gdscript_editor.cpp
-#, fuzzy
msgid "Add Type Hints"
-msgstr "Adicionar Tipo"
+msgstr "Adicionar Dicas de Tipo"
#: editor/editor_settings.cpp
msgid "Use Single Quotes"
msgstr "Use Citação Única"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Show Help Index"
-msgstr "Mostrar Ajudantes"
+msgstr "Mostrar Ãndice de Dicas"
#: editor/editor_settings.cpp
msgid "Help Font Size"
@@ -5675,32 +5672,27 @@ msgid "Secondary Grid Color"
msgstr "Cor da Grade Secundária"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Selection Box Color"
-msgstr "Apenas seleção"
+msgstr "Seleção de Cor da Caixa"
#: 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 "Bugigangas"
+msgstr "Bugigangas 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 das Bugigangas"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Instanced"
-msgstr "Instância"
+msgstr "Instânciado"
#: editor/editor_settings.cpp modules/gltf/gltf_node.cpp
#: scene/3d/physics_body.cpp
-#, fuzzy
msgid "Joint"
-msgstr "Ponto"
+msgstr "Conjunto"
#: editor/editor_settings.cpp scene/2d/collision_shape_2d.cpp
#: scene/2d/cpu_particles_2d.cpp scene/2d/touch_screen_button.cpp
@@ -5732,58 +5724,48 @@ msgid "Grid Division Level Bias"
msgstr "Viés de Nível de Divisão de Grade"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Grid XZ Plane"
-msgstr "Pintura do GridMap"
+msgstr "Grade do Plano XZ"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Grid XY Plane"
-msgstr "Pintura do GridMap"
+msgstr "Grade do Plano XY"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Grid YZ Plane"
-msgstr "Pintura do GridMap"
+msgstr "Grade do Plano YZ"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Default FOV"
-msgstr "Predefinição"
+msgstr "Campo de Visão (FOV) Padrão"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Default Z Near"
-msgstr "Tema Predefinido"
+msgstr "Z Padrão Próximo"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Default Z Far"
-msgstr "Predefinição"
+msgstr "Z Padrão Longe"
#: editor/editor_settings.cpp
msgid "Lightmap Baking Number Of CPU Threads"
msgstr "Número de threads da CPU para Baking 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 "Editar 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 "Diminuir Zoom"
+msgstr "Estilo de Zoom"
#: editor/editor_settings.cpp
msgid "Emulate Numpad"
@@ -5794,28 +5776,24 @@ msgid "Emulate 3 Button Mouse"
msgstr "Emular Mouse de 3 Botões"
#: 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 deslocamento"
+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 "Panorama do Mouse Distorcido"
#: 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"
@@ -5826,82 +5804,68 @@ msgid "Orbit Inertia"
msgstr "Inércia da Ó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 "Aumentar Zoom"
+msgstr "Inércia de Zoom"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Freelook"
-msgstr "Freelook 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 "Freelook Esquerda"
+msgstr "Sensibilidade de visualização livre"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Freelook Inertia"
-msgstr "Freelook Esquerda"
+msgstr "Inércia de Visualização livre"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Freelook Base Speed"
-msgstr "Freelook Modificador de Velocidade"
+msgstr "Velocidade Base de Visão Livre"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Freelook Activation Modifier"
-msgstr "Freelook Modificador de Lentidão"
+msgstr "Modificador de Ativação de Visão Livre"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Freelook Speed Zoom Link"
-msgstr "Freelook Modificador de Velocidade"
+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 "Ajuste Inteligente"
+msgstr "Cor da Linha de Encaixe Inteligente"
#: editor/editor_settings.cpp
msgid "Bone Width"
msgstr "Largura do Osso"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Bone Color 1"
-msgstr "Renomear Item Cor"
+msgstr "Cor de Osso 1"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Bone Color 2"
-msgstr "Renomear Item Cor"
+msgstr "Cor de Osso 2"
#: editor/editor_settings.cpp
msgid "Bone Selected Color"
-msgstr "Cor dos Ossos Selecionados"
+msgstr "Cor Selecionada do Osso"
#: editor/editor_settings.cpp
msgid "Bone IK Color"
@@ -5936,32 +5900,28 @@ msgid "Pan Speed"
msgstr "Velocidade de Rotação"
#: editor/editor_settings.cpp editor/plugins/polygon_2d_editor_plugin.cpp
-#, fuzzy
msgid "Poly Editor"
-msgstr "Editor UV de Polígono 2D"
+msgstr "Editor de Polígonos"
#: editor/editor_settings.cpp
msgid "Point Grab Radius"
msgstr "Raio do Ponto de Captura"
#: 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 "Criar Faixas de Bézier Padrão"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Default Create Reset Tracks"
-msgstr "Criar Pista(s) RESET"
+msgstr "Criar Faixa RESET Por Padrão"
#: editor/editor_settings.cpp
msgid "Onion Layers Past Color"
@@ -6877,9 +6837,8 @@ msgid "Use Ambient"
msgstr "Usar Ambiente"
#: 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
@@ -6891,18 +6850,16 @@ msgstr "Limite"
#: 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 "Delimitador"
#: editor/import/resource_importer_layered_texture.cpp
-#, fuzzy
msgid "ColorCorrect"
-msgstr "Função Cor."
+msgstr "Corrigir as Cores"
#: editor/import/resource_importer_layered_texture.cpp
msgid "No BPTC If RGB"
@@ -6945,9 +6902,8 @@ msgid "sRGB"
msgstr "sRGB"
#: editor/import/resource_importer_layered_texture.cpp
-#, fuzzy
msgid "Slices"
-msgstr "Corte automático"
+msgstr "Fatias"
#: editor/import/resource_importer_layered_texture.cpp
#: scene/gui/aspect_ratio_container.cpp scene/gui/control.cpp
@@ -6964,9 +6920,8 @@ 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
msgid "Scale Mesh"
@@ -7095,19 +7050,16 @@ msgid "Store In Subdir"
msgstr "Armazenar no Subdiretório"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Filter Script"
-msgstr "Scripts de filtro"
+msgstr "Filtrar Script"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Keep Custom Tracks"
-msgstr "Transformar"
+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
@@ -7121,9 +7073,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 "Ativar"
+msgstr "Ativado"
#: editor/import/resource_importer_scene.cpp
msgid "Max Linear Error"
@@ -7134,19 +7085,16 @@ msgid "Max Angular Error"
msgstr "Máximo de Erros Angulares"
#: 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 Pista de Animação"
+msgstr "Remover Faixas não Utilizadas"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Clips"
-msgstr "Clips Anim"
+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
@@ -7428,14 +7376,12 @@ msgid "Raw"
msgstr "Raw"
#: editor/inspector_dock.cpp
-#, fuzzy
msgid "Capitalized"
-msgstr "Capitalizar"
+msgstr "Capitalizado"
#: editor/inspector_dock.cpp
-#, fuzzy
msgid "Localized"
-msgstr "Localização"
+msgstr "Localizado"
#: editor/inspector_dock.cpp
msgid "Localization not available for current language."
@@ -7984,9 +7930,8 @@ msgid "New"
msgstr "Novo"
#: editor/plugins/animation_player_editor_plugin.cpp
-#, fuzzy
msgid "Paste As Reference"
-msgstr "Referência de classe %s"
+msgstr "Colar como Referência"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Edit Transitions..."
@@ -8176,9 +8121,8 @@ msgid "Set the end animation. This is useful for sub-transitions."
msgstr "Definir a animação final. Útil para sub-transições."
#: editor/plugins/animation_state_machine_editor.cpp
-#, fuzzy
msgid "Transition:"
-msgstr "Transição: "
+msgstr "Transição:"
#: editor/plugins/animation_state_machine_editor.cpp
msgid "Play Mode:"
@@ -8478,25 +8422,21 @@ msgid "Loading..."
msgstr "A Carregar..."
#: 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"
@@ -9110,23 +9050,20 @@ msgid "View"
msgstr "Vista"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#, fuzzy
msgid "Show"
-msgstr "Mostrar grelha"
+msgstr "Exibir"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#, fuzzy
msgid "Show When Snapping"
-msgstr "Ajuste Inteligente"
+msgstr "Exibir ao Encaixar"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Hide"
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
@@ -9485,9 +9422,8 @@ msgid "Swap Gradient Fill Points"
msgstr "Trocar Pontos de Preenchimento de Gradiente"
#: 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
@@ -9510,9 +9446,8 @@ 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"
@@ -9747,9 +9682,8 @@ msgstr ""
"%s"
#: editor/plugins/mesh_library_editor_plugin.cpp
-#, fuzzy
msgid "MeshLibrary"
-msgstr "Bib. de Malhas"
+msgstr "Biblioteca de Malhas"
#: editor/plugins/mesh_library_editor_plugin.cpp
msgid "Add Item"
@@ -9772,14 +9706,12 @@ msgid "Update from Scene"
msgstr "Atualizar a partir da Cena"
#: editor/plugins/mesh_library_editor_plugin.cpp
-#, fuzzy
msgid "Apply without Transforms"
-msgstr "Aplicar Transformações do MeshInstance"
+msgstr "Aplicar sem Transformações"
#: editor/plugins/mesh_library_editor_plugin.cpp
-#, fuzzy
msgid "Apply with Transforms"
-msgstr "Aplicar Transformações do MeshInstance"
+msgstr "Aplicar com Transformações"
#: editor/plugins/multimesh_editor_plugin.cpp
msgid "No mesh source specified (and no MultiMesh set in node)."
@@ -9945,9 +9877,8 @@ msgid "Volume"
msgstr "Volume"
#: editor/plugins/particles_editor_plugin.cpp
-#, fuzzy
msgid "Emission Source:"
-msgstr "Fonte de emissão: "
+msgstr "Fonte de emissão:"
#: editor/plugins/particles_editor_plugin.cpp
msgid "A processor material of type 'ParticlesMaterial' is required."
@@ -10641,19 +10572,16 @@ msgid "External"
msgstr "Externo"
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Use External Editor"
-msgstr "Depurar com Editor Externo"
+msgstr "Utilizar Editor Externo"
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Exec Path"
-msgstr "Exportar Caminho"
+msgstr "Caminho de Execução"
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Script Temperature Enabled"
-msgstr "Selecionar Ficheiro de Modelo"
+msgstr "Temperatura de Script Ativado"
#: editor/plugins/script_editor_plugin.cpp
msgid "Highlight Current Script"
@@ -10668,19 +10596,16 @@ msgid "Current Script Background Color"
msgstr "Cor de Fundo Script Atual"
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Group Help Pages"
-msgstr "Agrupar Seleção"
+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
-#, fuzzy
msgid "List Script Names As"
-msgstr "Nome do Script:"
+msgstr "Listar Nomes de Script Como"
#: editor/plugins/script_editor_plugin.cpp
msgid "Exec Flags"
@@ -11042,15 +10967,13 @@ msgstr "Translação"
#. TRANSLATORS: Refers to changing the scale of a node in the 3D editor.
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Scaling:"
-msgstr "A escalar: "
+msgstr "Escala:"
#. TRANSLATORS: Refers to changing the position of a node in the 3D editor.
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Translating:"
-msgstr "A transladar: "
+msgstr "Traduzir:"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Rotating %s degrees."
@@ -11201,10 +11124,11 @@ msgid "(Not in GLES2)"
msgstr "(Não 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 para 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"
@@ -11506,9 +11430,8 @@ msgid "Manipulator Gizmo Opacity"
msgstr "Opacidade do Gizmo do Manipulador"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Show Viewport Rotation Gizmo"
-msgstr "Bloquear Rotação da Vista"
+msgstr "Exibir Gizmo de Rotação do Viewport"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Unnamed Gizmo"
@@ -11559,9 +11482,8 @@ msgid "Invalid geometry, can't replace by mesh."
msgstr "Geometria inválida, não substituível por malha."
#: editor/plugins/sprite_editor_plugin.cpp
-#, fuzzy
msgid "Convert to MeshInstance2D"
-msgstr "Converter para Mesh2D"
+msgstr "Converter para MeshInstance2D"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Invalid geometry, can't create polygon."
@@ -11592,19 +11514,16 @@ msgid "Sprite"
msgstr "Sprite"
#: editor/plugins/sprite_editor_plugin.cpp
-#, fuzzy
msgid "Simplification:"
-msgstr "Simplificação: "
+msgstr "Simplificação:"
#: editor/plugins/sprite_editor_plugin.cpp
-#, fuzzy
msgid "Shrink (Pixels):"
-msgstr "Encolher (Pixeis): "
+msgstr "Encolher (Pixels):"
#: editor/plugins/sprite_editor_plugin.cpp
-#, fuzzy
msgid "Grow (Pixels):"
-msgstr "Aumentar (Pixeis): "
+msgstr "Crescer (Pixels):"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Update Preview"
@@ -11667,9 +11586,8 @@ msgid "New Animation"
msgstr "Nova Animação"
#: editor/plugins/sprite_frames_editor_plugin.cpp
-#, fuzzy
msgid "Filter animations"
-msgstr "Métodos de filtro"
+msgstr "Filtrar animações"
#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Speed:"
@@ -11969,9 +11887,8 @@ msgstr ""
"Fechar na mesma?"
#: editor/plugins/theme_editor_plugin.cpp
-#, fuzzy
msgid "Remove Type"
-msgstr "Remover Tile"
+msgstr "Remover Tipo"
#: editor/plugins/theme_editor_plugin.cpp
msgid ""
@@ -12015,14 +11932,12 @@ msgstr ""
"Adicione-lhe mais itens manualmente ou importando-os 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"
@@ -12137,9 +12052,8 @@ msgid "Select Another Theme Resource:"
msgstr "Selecionar Outro Recurso 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"
@@ -12476,45 +12390,37 @@ msgid "Palette Min Width"
msgstr "Largura Mínima da Paleta"
#: editor/plugins/tile_map_editor_plugin.cpp
-#, fuzzy
msgid "Palette Item H Separation"
-msgstr "Separador Nomeado"
+msgstr "Separação Horizontal dos Itens de Paleta"
#: editor/plugins/tile_map_editor_plugin.cpp
-#, fuzzy
msgid "Show Tile Names"
-msgstr "Mostrar Todos os Idiomas"
+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 ficheiros"
+msgstr "Ordenar Tiles por Nome"
#: editor/plugins/tile_map_editor_plugin.cpp
-#, fuzzy
msgid "Bucket Fill Preview"
-msgstr "Balde de Enchimento"
+msgstr "Pré-visualização do Preenchimento de Balde"
#: editor/plugins/tile_map_editor_plugin.cpp
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Editor Side"
-msgstr "Editor"
+msgstr "Lado do Editor"
#: editor/plugins/tile_map_editor_plugin.cpp
-#, fuzzy
msgid "Display Grid"
-msgstr "Vista Overdraw"
+msgstr "Mostrar Grid"
#: editor/plugins/tile_map_editor_plugin.cpp
-#, fuzzy
msgid "Axis Color"
-msgstr "Escolher cor"
+msgstr "Cor do Eixo"
#: editor/plugins/tile_set_editor_plugin.cpp
msgid "Add Texture(s) to TileSet."
@@ -12851,9 +12757,8 @@ msgid "This property can't be changed."
msgstr "Esta propriedade não pode ser alterada."
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Snap Options"
-msgstr "Opções de Ajuste"
+msgstr "Opções de Encaixe"
#: editor/plugins/tile_set_editor_plugin.cpp scene/2d/animated_sprite.cpp
#: scene/2d/camera_2d.cpp scene/2d/cpu_particles_2d.cpp scene/2d/light_2d.cpp
@@ -12861,12 +12766,12 @@ msgstr "Opções de Ajuste"
#: scene/2d/path_2d.cpp scene/2d/polygon_2d.cpp scene/2d/sprite.cpp
#: scene/3d/cpu_particles.cpp scene/3d/label_3d.cpp scene/3d/path.cpp
#: scene/3d/physics_body.cpp scene/3d/soft_body.cpp scene/3d/sprite_3d.cpp
-#: 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
+#: scene/3d/visual_instance.cpp 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
msgid "Offset"
-msgstr "Compensação:"
+msgstr "Deslocamento"
#: editor/plugins/tile_set_editor_plugin.cpp editor/rename_dialog.cpp
#: scene/gui/range.cpp scene/resources/animation.cpp
@@ -12877,14 +12782,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
@@ -12893,97 +12796,79 @@ 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
msgid "Tex Offset"
-msgstr "Compensação da grelha:"
+msgstr "Deslocamento da Textura"
#: 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 "Mudanças de Material:"
+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 "Povoar"
+msgstr "Modular"
#: 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
msgid "Autotile Bitmask Mode"
-msgstr "Modo Bitmask"
+msgstr "Modo Bitmask do Autotile"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Subtile Size"
-msgstr "Tamanho do contorno:"
+msgstr "Tamanho do Subtile"
#: 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
msgid "Occluder Offset"
-msgstr "Criar Polígono Oclusor"
+msgstr "Deslocamento de Oclusor"
#: 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 "Compensação:"
+msgstr "Deslocamento da Forma"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Shape Transform"
-msgstr "Transformar"
+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
msgid "Selected Collision One Way"
-msgstr "Apenas seleção"
+msgstr "Colisão em sentido único selecionada"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Selected Collision One Way Margin"
-msgstr "Modo Colisão"
+msgstr "Margem de colisão em sentido único selecionada"
#: 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 "Scripts de filtro"
+msgstr "Scripts do Tileset"
#: editor/plugins/tile_set_editor_plugin.cpp
msgid "TileSet"
@@ -14188,51 +14073,44 @@ msgstr ""
"você precisa construir os modelos de exportação da fonte."
#: editor/project_export.cpp
-#, fuzzy
msgid "More Info..."
-msgstr "Mover para..."
+msgstr "Mais Informações..."
#: editor/project_export.cpp
-#, fuzzy
msgid "Export PCK/Zip..."
-msgstr "Exportar PCK/Zip"
+msgstr "Exportar PCK/Zip..."
#: editor/project_export.cpp
-#, fuzzy
msgid "Export Project..."
-msgstr "Exportar Projeto"
+msgstr "Exportar Projeto…"
#: editor/project_export.cpp
msgid "Export All"
msgstr "Exportar Tudo"
#: editor/project_export.cpp
-#, fuzzy
msgid "Choose an export mode:"
-msgstr "Por favor escolha uma pasta vazia."
+msgstr "Escolha um modo de exportação:"
#: editor/project_export.cpp
-#, fuzzy
msgid "Export All..."
-msgstr "Exportar Tudo"
+msgstr "Exportar tudo…"
#: editor/project_export.cpp editor/project_manager.cpp
msgid "ZIP File"
msgstr "Ficheiro ZIP"
#: editor/project_export.cpp
-#, fuzzy
msgid "Godot Project Pack"
-msgstr "Pacote de Jogo Godot"
+msgstr "Pacote do Projeto Godot"
#: editor/project_export.cpp
msgid "Export templates for this platform are missing:"
msgstr "Não existem Modelos de exportação para esta plataforma:"
#: editor/project_export.cpp
-#, fuzzy
msgid "Project Export"
-msgstr "Fundadores do Projeto"
+msgstr "Exportar Projeto"
#: editor/project_export.cpp
msgid "Manage Export Templates"
@@ -14298,16 +14176,17 @@ msgid "Invalid project path (changed anything?)."
msgstr "Caminho de projeto inválido (alguma alteração?)."
#: editor/project_manager.cpp
+#, fuzzy
msgid ""
-"Couldn't load project.godot in project path (error %d). It may be missing or "
-"corrupted."
+"Couldn't load project at '%s' (error %d). It may be missing or corrupted."
msgstr ""
"Não consegui carregar o project.godot no caminho do projeto (erro %d). "
"Poderá estar em falta ou corrompido."
#: editor/project_manager.cpp
-msgid "Couldn't edit project.godot in project path."
-msgstr "Incapaz de editar project.godot no caminho do projeto."
+#, fuzzy
+msgid "Couldn't save project at '%s' (error %d)."
+msgstr "Incapaz de abrir projeto em '%s'."
#: editor/project_manager.cpp
msgid "Couldn't create project.godot in project path."
@@ -14546,7 +14425,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 "Gestor de Projetos"
@@ -15343,19 +15221,16 @@ msgid "Make Local"
msgstr "Tornar Local"
#: editor/scene_tree_dock.cpp
-#, fuzzy
msgid "Enable Scene Unique Name(s)"
-msgstr "Nome do Nó:"
+msgstr "Ativar Nome(s) Único(s) de Cena"
#: editor/scene_tree_dock.cpp
-#, fuzzy
msgid "Unique names already used by another node in the scene:"
-msgstr "Outro nó já usa esse nome exclusivo na cena."
+msgstr "Nomes únicos já estão sendo usados por outro nó na cena:"
#: editor/scene_tree_dock.cpp
-#, fuzzy
msgid "Disable Scene Unique Name(s)"
-msgstr "Nome do Nó:"
+msgstr "Desativar Nome(s) Único(s) de Cena"
#: editor/scene_tree_dock.cpp
msgid "New Scene Root"
@@ -15530,18 +15405,16 @@ msgid "Clear Inheritance? (No Undo!)"
msgstr "Limpar herança? (Definitivo!)"
#: editor/scene_tree_dock.cpp
-#, fuzzy
msgid "Show Scene Tree Root Selection"
-msgstr "Centrar Seleção"
+msgstr "Mostrar seleção da hierarquia de cenas"
#: editor/scene_tree_dock.cpp
msgid "Derive Script Globals By Name"
msgstr "Derivar Globais de Script Por Nome"
#: editor/scene_tree_dock.cpp
-#, fuzzy
msgid "Use Favorites Root Selection"
-msgstr "Seleção de Frame"
+msgstr "Seleção de favoritos da raíz"
#: editor/scene_tree_editor.cpp
msgid "Toggle Visible"
@@ -15556,9 +15429,8 @@ msgid "Button Group"
msgstr "Grupo Botão"
#: editor/scene_tree_editor.cpp
-#, fuzzy
msgid "Disable Scene Unique Name"
-msgstr "Nome do Nó:"
+msgstr "Desativar Nome Único de Cena"
#: editor/scene_tree_editor.cpp
msgid "(Connecting From)"
@@ -15791,9 +15663,8 @@ msgid "Attach Node Script"
msgstr "Anexar Script de Nó"
#: editor/script_editor_debugger.cpp
-#, fuzzy
msgid "Remote %s:"
-msgstr "Remoto "
+msgstr "%s remoto:"
#: editor/script_editor_debugger.cpp
msgid "Bytes:"
@@ -15868,9 +15739,8 @@ msgid "Stack Frames"
msgstr "Empilhar Frames"
#: editor/script_editor_debugger.cpp
-#, fuzzy
msgid "Filter stack variables"
-msgstr "Filtrar Tiles"
+msgstr "Filtrar variáveis stack"
#: editor/script_editor_debugger.cpp
msgid "Auto Switch To Remote Scene Tree"
@@ -16547,26 +16417,22 @@ msgid "Calculate Tangents"
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 maiúsculas/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
@@ -16576,43 +16442,36 @@ msgstr "Converter maiúsculas/minúsculas"
#: 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 "Raio:"
+msgstr "Raio"
#: modules/csg/csg_shape.cpp scene/resources/primitive_meshes.cpp
-#, fuzzy
msgid "Radial Segments"
-msgstr "Argumentos da Cena Principal:"
+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 "Smoothstep"
+msgstr "Suavizar Faces"
#: modules/csg/csg_shape.cpp
-#, fuzzy
msgid "Sides"
-msgstr "Mostrar Guias"
+msgstr "Lados"
#: modules/csg/csg_shape.cpp
msgid "Cone"
msgstr "Cone"
#: modules/csg/csg_shape.cpp
-#, fuzzy
msgid "Inner Radius"
-msgstr "Mudar Raio Interno do Toro"
+msgstr "Raio Interno"
#: modules/csg/csg_shape.cpp
-#, fuzzy
msgid "Outer Radius"
-msgstr "Mudar Raio Externo do Toro"
+msgstr "Raio Externo"
#: modules/csg/csg_shape.cpp
msgid "Ring Sides"
@@ -16621,9 +16480,8 @@ msgstr "Lados do 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"
@@ -16634,14 +16492,12 @@ msgid "Spin Sides"
msgstr "Girar Lados"
#: modules/csg/csg_shape.cpp
-#, fuzzy
msgid "Path Node"
-msgstr "Colar Nós"
+msgstr "Caminho do Nó"
#: modules/csg/csg_shape.cpp
-#, fuzzy
msgid "Path Interval Type"
-msgstr "Criar vértice interno"
+msgstr "Tipo de Intervalo de Caminho"
#: modules/csg/csg_shape.cpp
msgid "Path Interval"
@@ -16652,14 +16508,12 @@ msgid "Path Simplify Angle"
msgstr "Simplifique o Ângulo do Caminho"
#: modules/csg/csg_shape.cpp
-#, fuzzy
msgid "Path Rotation"
-msgstr "Rotação aleatória:"
+msgstr "Rotação do Caminho"
#: modules/csg/csg_shape.cpp
-#, fuzzy
msgid "Path Local"
-msgstr "Tornar Local"
+msgstr "Caminho Local"
#: modules/csg/csg_shape.cpp
#, fuzzy
@@ -16667,34 +16521,28 @@ msgid "Path Continuous U"
msgstr "Contínuo"
#: modules/csg/csg_shape.cpp
-#, fuzzy
msgid "Path U Distance"
-msgstr "Distância de escolha:"
+msgstr "Distância do Caminho U"
#: modules/csg/csg_shape.cpp
-#, fuzzy
msgid "Path Joined"
-msgstr "Rotação aleatória:"
+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 "Mudar 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 "Mostrar Grelha Sempre"
+msgstr "Sempre Ordenado"
#: modules/enet/networked_multiplayer_enet.cpp
msgid "Server Relay"
@@ -16709,9 +16557,8 @@ msgid "DTLS Hostname"
msgstr "Nome do Host DTLS"
#: modules/enet/networked_multiplayer_enet.cpp
-#, fuzzy
msgid "Use DTLS"
-msgstr "Usar Ajuste"
+msgstr "Usar DTLS"
#: modules/fbx/editor_scene_importer_fbx.cpp
msgid "FBX"
@@ -16722,14 +16569,12 @@ msgid "Use FBX"
msgstr "Usar FBX"
#: modules/gdnative/gdnative.cpp
-#, fuzzy
msgid "Config File"
-msgstr "Armazenar o Ficheiro:"
+msgstr "Ficheiro 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
@@ -16738,14 +16583,12 @@ msgid "Singleton"
msgstr "Esqueleto"
#: modules/gdnative/gdnative.cpp
-#, fuzzy
msgid "Symbol Prefix"
-msgstr "Prefixo:"
+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
@@ -16798,24 +16641,20 @@ msgid "Disabled GDNative Singleton"
msgstr "Instância única GDNative desativada"
#: modules/gdnative/gdnative_library_singleton_editor.cpp
-#, fuzzy
msgid "Libraries:"
-msgstr "Bibliotecas: "
+msgstr "Bibliotecas:"
#: modules/gdnative/nativescript/nativescript.cpp
-#, fuzzy
msgid "Class Name"
-msgstr "Nome de Classe:"
+msgstr "Nome da Classe"
#: modules/gdnative/nativescript/nativescript.cpp
-#, fuzzy
msgid "Script Class"
-msgstr "Nome do Script:"
+msgstr "Classe do Script"
#: modules/gdnative/nativescript/nativescript.cpp
-#, fuzzy
msgid "Icon Path"
-msgstr "Caminho de Foco"
+msgstr "Caminho para Ãcone"
#: modules/gdnative/register_types.cpp
msgid "GDNative"
@@ -16823,18 +16662,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 "Função de Definição de Cor"
#: modules/gdscript/editor/gdscript_highlighter.cpp
-#, fuzzy
msgid "Node Path Color"
-msgstr "Copiar Caminho do Nó"
+msgstr "Cor do Caminho do Nó"
#: modules/gdscript/gdscript.cpp modules/visual_script/visual_script.cpp
msgid "Max Call Stack"
@@ -16891,9 +16728,8 @@ msgid "Object can't provide a length."
msgstr "Objeto não fornece um comprimento."
#: modules/gdscript/language_server/gdscript_language_server.cpp
-#, fuzzy
msgid "Language Server"
-msgstr "Linguagem:"
+msgstr "Servidor de Idioma"
#: modules/gdscript/language_server/gdscript_language_server.cpp
msgid "Enable Smart Resolve"
@@ -16916,44 +16752,36 @@ msgid "Export GLTF..."
msgstr "Exportar GLTF..."
#: modules/gltf/gltf_accessor.cpp
-#, fuzzy
msgid "Buffer View"
-msgstr "Vista de Trás"
+msgstr "Visão de Buffer"
#: modules/gltf/gltf_accessor.cpp modules/gltf/gltf_buffer_view.cpp
-#, fuzzy
msgid "Byte Offset"
-msgstr "Compensação da grelha:"
+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
msgid "Normalized"
-msgstr "Formato"
+msgstr "Normalizado"
#: modules/gltf/gltf_accessor.cpp
-#, fuzzy
msgid "Count"
-msgstr "Valor:"
+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 "Combinar"
+msgstr "Max"
#: modules/gltf/gltf_accessor.cpp
-#, fuzzy
msgid "Sparse Count"
-msgstr "Instância"
+msgstr "Contagem Escassa"
#: modules/gltf/gltf_accessor.cpp
msgid "Sparse Indices Buffer View"
@@ -16964,9 +16792,8 @@ msgid "Sparse Indices Byte Offset"
msgstr "Deslocamento de Bytes de Ãndices Esparsos"
#: modules/gltf/gltf_accessor.cpp
-#, fuzzy
msgid "Sparse Indices Component Type"
-msgstr "A analisar geometria..."
+msgstr "Tipo de Componente de Ãndices Esparsos"
#: modules/gltf/gltf_accessor.cpp
msgid "Sparse Values Buffer View"
@@ -16977,37 +16804,32 @@ msgid "Sparse Values Byte Offset"
msgstr "Deslocamento de Bytes de Valores Esparsos"
#: modules/gltf/gltf_buffer_view.cpp
-#, fuzzy
msgid "Buffer"
-msgstr "Vista de Trás"
+msgstr "Buffer"
#: modules/gltf/gltf_buffer_view.cpp
-#, fuzzy
msgid "Byte Length"
-msgstr "Tema Predefinido"
+msgstr "Largura do byte"
#: modules/gltf/gltf_buffer_view.cpp
msgid "Byte Stride"
msgstr "Passo de Byte"
#: modules/gltf/gltf_buffer_view.cpp
-#, fuzzy
msgid "Indices"
-msgstr "Todos os Aparelhos"
+msgstr "Ãndices"
#: modules/gltf/gltf_camera.cpp
-#, fuzzy
msgid "FOV Size"
-msgstr "Tamanho:"
+msgstr "Tamanho do FOV"
#: modules/gltf/gltf_camera.cpp
msgid "Zfar"
msgstr "Zfar"
#: modules/gltf/gltf_camera.cpp
-#, fuzzy
msgid "Znear"
-msgstr "Linear"
+msgstr "Z perto"
#: 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
@@ -17017,9 +16839,8 @@ 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
@@ -17027,9 +16848,8 @@ msgid "Intensity"
msgstr "Intensidade"
#: modules/gltf/gltf_light.cpp scene/2d/light_2d.cpp scene/3d/light.cpp
-#, fuzzy
msgid "Range"
-msgstr "Mudar"
+msgstr "Intervalo"
#: modules/gltf/gltf_light.cpp
msgid "Inner Cone Angle"
@@ -17040,19 +16860,16 @@ msgid "Outer Cone Angle"
msgstr "Ângulo do Cone Externo"
#: modules/gltf/gltf_mesh.cpp
-#, fuzzy
msgid "Blend Weights"
-msgstr "Consolidar Lightmaps"
+msgstr "Peso da mesclagem"
#: modules/gltf/gltf_mesh.cpp
-#, fuzzy
msgid "Instance Materials"
-msgstr "Mudanças de Material:"
+msgstr "Materiais da Instância"
#: modules/gltf/gltf_node.cpp scene/3d/skeleton.cpp
-#, fuzzy
msgid "Parent"
-msgstr "Reassociar"
+msgstr "Pai"
#: modules/gltf/gltf_node.cpp
#, fuzzy
@@ -17064,19 +16881,16 @@ msgid "Skin"
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"
@@ -17087,28 +16901,24 @@ msgid "Unique Names"
msgstr "Nomes Únicos"
#: modules/gltf/gltf_skeleton.cpp
-#, fuzzy
msgid "Godot Bone Node"
-msgstr "Obter Nó da Cena"
+msgstr "Nó de Osso Godot"
#: modules/gltf/gltf_skin.cpp
-#, fuzzy
msgid "Skin Root"
-msgstr "Nova Raiz da Cena"
+msgstr "Raiz da Skin"
#: modules/gltf/gltf_skin.cpp
-#, fuzzy
msgid "Joints Original"
-msgstr "Focar na Origem"
+msgstr "Pontos Originais"
#: modules/gltf/gltf_skin.cpp
msgid "Inverse Binds"
msgstr "Inverter Ligações"
#: modules/gltf/gltf_skin.cpp
-#, fuzzy
msgid "Non Joints"
-msgstr "Mover Junta"
+msgstr "Não-Juntas"
#: modules/gltf/gltf_skin.cpp
msgid "Joint I To Bone I"
@@ -17147,48 +16957,41 @@ msgid "Json"
msgstr "Json"
#: modules/gltf/gltf_state.cpp
-#, fuzzy
msgid "Major Version"
-msgstr "Versão"
+msgstr "Versão Importante"
#: modules/gltf/gltf_state.cpp
-#, fuzzy
msgid "Minor Version"
-msgstr "Versão"
+msgstr "Versão Minoritária"
#: modules/gltf/gltf_state.cpp
-#, fuzzy
msgid "GLB Data"
-msgstr "Com Dados"
+msgstr "Dados do GLB"
#: modules/gltf/gltf_state.cpp
msgid "Use Named Skin Binds"
msgstr "Usar Ligações de Skin Nomeadas"
#: modules/gltf/gltf_state.cpp
-#, fuzzy
msgid "Buffer Views"
-msgstr "Vista de Trás"
+msgstr "Visão Buffer"
#: modules/gltf/gltf_state.cpp
msgid "Accessors"
msgstr "Assessores"
#: modules/gltf/gltf_state.cpp
-#, fuzzy
msgid "Scene Name"
-msgstr "Caminho da Cena:"
+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"
@@ -17199,72 +17002,60 @@ msgid "Cameras"
msgstr "Câmeras"
#: modules/gltf/gltf_state.cpp servers/visual_server.cpp
-#, fuzzy
msgid "Lights"
-msgstr "Luz"
+msgstr "Luzes"
#: modules/gltf/gltf_state.cpp
-#, fuzzy
msgid "Unique Animation Names"
-msgstr "Novo Nome da Animação:"
+msgstr "Nomes de Animação Únicos"
#: modules/gltf/gltf_state.cpp
-#, fuzzy
msgid "Skeletons"
-msgstr "Esqueleto"
+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
-#, fuzzy
msgid "Animations"
-msgstr "Animações:"
+msgstr "Animações"
#: modules/gltf/gltf_texture.cpp
-#, fuzzy
msgid "Src Image"
-msgstr "Mostrar ossos"
+msgstr "Imagem fonte"
#: modules/gridmap/grid_map.cpp
msgid "Mesh Library"
msgstr "Bib. de Malhas"
#: modules/gridmap/grid_map.cpp
-#, fuzzy
msgid "Physics Material"
-msgstr "Frame 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 "Consolidar Lightmaps"
+msgstr "Usar no mapa de luz"
#: modules/gridmap/grid_map.cpp scene/2d/tile_map.cpp
msgid "Cell"
msgstr "Célula"
#: modules/gridmap/grid_map.cpp
-#, fuzzy
msgid "Octant Size"
-msgstr "Vista de Frente"
+msgstr "Tamanho 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
@@ -17273,17 +17064,15 @@ msgid "Mask"
msgstr "Máscara"
#: modules/gridmap/grid_map.cpp scene/2d/tile_map.cpp
-#, fuzzy
msgid "Bake Navigation"
-msgstr "Navegação"
+msgstr "Navegação Pré-Processada"
#: 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 Navegação"
+msgstr "Camadas da Navegação"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Next Plane"
@@ -17442,9 +17231,8 @@ msgid "Plotting lightmaps"
msgstr "A Traçar lightmaps"
#: modules/lightmapper_cpu/register_types.cpp
-#, fuzzy
msgid "CPU Lightmapper"
-msgstr "Consolidar Lightmaps"
+msgstr "Mapeamento de Luz da CPU"
#: modules/lightmapper_cpu/register_types.cpp
msgid "Low Quality Ray Count"
@@ -17466,9 +17254,8 @@ msgstr "Contagem de Raios de Ultra Qualidade"
#: 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 "Compensação:"
+msgstr "Deslocamento do Loop"
#: modules/mobile_vr/mobile_vr_interface.cpp
msgid "Eye Height"
@@ -17479,14 +17266,12 @@ msgid "IOD"
msgstr "IOD"
#: modules/mobile_vr/mobile_vr_interface.cpp
-#, fuzzy
msgid "Display Width"
-msgstr "Vista Wireframe"
+msgstr "Largura de Ecrã"
#: modules/mobile_vr/mobile_vr_interface.cpp
-#, fuzzy
msgid "Display To Lens"
-msgstr "Vista sem sombras"
+msgstr "Exibir às Lentes"
#: modules/mobile_vr/mobile_vr_interface.cpp
msgid "Oversample"
@@ -17509,24 +17294,20 @@ msgid "Build Solution"
msgstr "Construir Solução"
#: modules/mono/editor/csharp_project.cpp
-#, fuzzy
msgid "Auto Update Project"
-msgstr "Projeto sem nome"
+msgstr "Atualizar Projeto Automaticamente"
#: modules/mono/godotsharp_dirs.cpp
-#, fuzzy
msgid "Assembly Name"
-msgstr "Mostrar Tudo"
+msgstr "Nome de Montagem"
#: modules/mono/godotsharp_dirs.cpp
-#, fuzzy
msgid "Solution Directory"
-msgstr "Escolha uma Diretoria"
+msgstr "Diretório da Solução"
#: modules/mono/godotsharp_dirs.cpp
-#, fuzzy
msgid "C# Project Directory"
-msgstr "Escolha uma Diretoria"
+msgstr "Diretório do Projeto C#"
#: modules/mono/mono_gd/gd_mono_utils.cpp
msgid "End of inner exception stack trace"
@@ -17604,9 +17385,8 @@ msgid "Seamless"
msgstr "Sem Emenda"
#: modules/opensimplex/noise_texture.cpp
-#, fuzzy
msgid "As Normal Map"
-msgstr "Escala aleatória:"
+msgstr "Como Mapa Normal"
#: modules/opensimplex/noise_texture.cpp
msgid "Bump Strength"
@@ -17617,9 +17397,8 @@ msgid "Noise"
msgstr "Ruido"
#: modules/opensimplex/noise_texture.cpp
-#, fuzzy
msgid "Noise Offset"
-msgstr "Compensação da grelha:"
+msgstr "Deslocamento do Ruído"
#: modules/opensimplex/open_simplex_noise.cpp
msgid "Octaves"
@@ -17630,9 +17409,8 @@ msgid "Period"
msgstr "Periodo"
#: modules/opensimplex/open_simplex_noise.cpp
-#, fuzzy
msgid "Persistence"
-msgstr "Perspetiva"
+msgstr "Persistência"
#: modules/opensimplex/open_simplex_noise.cpp
msgid "Lacunarity"
@@ -17643,14 +17421,12 @@ msgid "Subject"
msgstr "Sujeito"
#: modules/regex/regex.cpp
-#, fuzzy
msgid "Names"
-msgstr "Nome"
+msgstr "Nomes"
#: modules/regex/regex.cpp
-#, fuzzy
msgid "Strings"
-msgstr "Configuração:"
+msgstr "Strings"
#: modules/upnp/upnp.cpp
msgid "Discover Multicast If"
@@ -17665,32 +17441,28 @@ msgid "Discover IPv6"
msgstr "Descobrir IPv6"
#: modules/upnp/upnp_device.cpp
-#, fuzzy
msgid "Description URL"
-msgstr "Descrição"
+msgstr "URL Descritiva"
#: modules/upnp/upnp_device.cpp
-#, fuzzy
msgid "Service Type"
-msgstr "Definir tipo de variável"
+msgstr "Tipo de Serviço"
#: modules/upnp/upnp_device.cpp
msgid "IGD Control URL"
msgstr "URL de controle IGD"
#: modules/upnp/upnp_device.cpp
-#, fuzzy
msgid "IGD Service Type"
-msgstr "Definir tipo de variável"
+msgstr "Tipo de Serviço IGD"
#: modules/upnp/upnp_device.cpp
msgid "IGD Our Addr"
msgstr "IGD Nosso Endereço"
#: modules/upnp/upnp_device.cpp
-#, fuzzy
msgid "IGD Status"
-msgstr "Status"
+msgstr "Estado do IGD"
#: modules/visual_script/visual_script.cpp
msgid ""
@@ -17717,9 +17489,8 @@ msgstr ""
"trabalho de nós! Corrija o seu nó por favor."
#: modules/visual_script/visual_script.cpp
-#, fuzzy
msgid "Node returned an invalid sequence output:"
-msgstr "O nó retornou uma sequência de saída incorreta: "
+msgstr "O nó retornou uma saída de sequência inválida:"
#: modules/visual_script/visual_script.cpp
msgid "Found sequence bit but not the node in the stack, report bug!"
@@ -17727,14 +17498,12 @@ msgstr ""
"Foi encontrada o bit da sequência mas não o nó na pilha, denuncie o bug!"
#: modules/visual_script/visual_script.cpp
-#, fuzzy
msgid "Stack overflow with stack depth:"
-msgstr "Pilha cheia com a profundidade da pilha: "
+msgstr "Sobrecarga da pilha com profundidade:"
#: modules/visual_script/visual_script.cpp
-#, fuzzy
msgid "Visual Script"
-msgstr "Procurar VisualScript"
+msgstr "Script Visual"
#: modules/visual_script/visual_script_editor.cpp
msgid "Change Signal Arguments"
@@ -18062,14 +17831,12 @@ msgid "Return"
msgstr "Voltar"
#: modules/visual_script/visual_script_flow_control.cpp
-#, fuzzy
msgid "Return Enabled"
-msgstr "Executável"
+msgstr "Retorno Ativado"
#: modules/visual_script/visual_script_flow_control.cpp
-#, fuzzy
msgid "Return Type"
-msgstr "Voltar"
+msgstr "Tipo de Retorno"
#: modules/visual_script/visual_script_flow_control.cpp
#: scene/resources/visual_shader_nodes.cpp
@@ -18097,18 +17864,16 @@ msgid "for (elem) in (input):"
msgstr "para (elem) em (input):"
#: modules/visual_script/visual_script_flow_control.cpp
-#, fuzzy
msgid "Input type not iterable:"
-msgstr "Tipo de Input não iterável: "
+msgstr "Tipo de entrada não iterável:"
#: modules/visual_script/visual_script_flow_control.cpp
msgid "Iterator became invalid"
msgstr "O iterador tornou-se inválido"
#: modules/visual_script/visual_script_flow_control.cpp
-#, fuzzy
msgid "Iterator became invalid:"
-msgstr "O iterador tornou-se inválido: "
+msgstr "Iterador tornou-se inválido:"
#: modules/visual_script/visual_script_flow_control.cpp
msgid "Sequence"
@@ -18119,9 +17884,8 @@ msgid "in order:"
msgstr "em ordem:"
#: modules/visual_script/visual_script_flow_control.cpp
-#, fuzzy
msgid "Steps"
-msgstr "Passo"
+msgstr "Passos"
#: modules/visual_script/visual_script_flow_control.cpp
msgid "Switch"
@@ -18141,9 +17905,8 @@ msgstr "É %s?"
#: modules/visual_script/visual_script_flow_control.cpp
#: modules/visual_script/visual_script_func_nodes.cpp
-#, fuzzy
msgid "Base Script"
-msgstr "Novo Script"
+msgstr "Script Base"
#: modules/visual_script/visual_script_func_nodes.cpp
msgid "On %s"
@@ -18155,37 +17918,31 @@ msgstr "Nele Próprio"
#: modules/visual_script/visual_script_func_nodes.cpp
#: modules/visual_script/visual_script_yield_nodes.cpp
-#, fuzzy
msgid "Call Mode"
-msgstr "Modo Escalar"
+msgstr "Modo de Chamada"
#: modules/visual_script/visual_script_func_nodes.cpp
#: modules/visual_script/visual_script_nodes.cpp
-#, fuzzy
msgid "Basic Type"
-msgstr "Mudar tipo base"
+msgstr "Tipo Base"
#: 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 Caminho do Nó"
+msgstr "Caminho do Nó"
#: modules/visual_script/visual_script_func_nodes.cpp
-#, fuzzy
msgid "Use Default Args"
-msgstr "Restaurar Predefinições"
+msgstr "Usar Argumentos Padrão"
#: modules/visual_script/visual_script_func_nodes.cpp
-#, fuzzy
msgid "Validate"
-msgstr "Caracteres válidos:"
+msgstr "Validar"
#: modules/visual_script/visual_script_func_nodes.cpp
-#, fuzzy
msgid "RPC Call Mode"
-msgstr "Modo Escalar"
+msgstr "Modo de Chamada RPC"
#: modules/visual_script/visual_script_func_nodes.cpp
msgid "Subtract %s"
@@ -18224,14 +17981,12 @@ msgid "BitXor %s"
msgstr "BitXor %s"
#: modules/visual_script/visual_script_func_nodes.cpp
-#, fuzzy
msgid "Set Mode"
-msgstr "Modo Seleção"
+msgstr "Modo de Definição"
#: modules/visual_script/visual_script_func_nodes.cpp
-#, fuzzy
msgid "Assign Op"
-msgstr "Atribuir"
+msgstr "Atribuir Op"
#: modules/visual_script/visual_script_func_nodes.cpp
#: modules/visual_script/visual_script_nodes.cpp
@@ -18248,9 +18003,8 @@ msgid "Base object is not a Node!"
msgstr "Objeto de base não é um Nó!"
#: modules/visual_script/visual_script_func_nodes.cpp
-#, fuzzy
msgid "Path does not lead to Node!"
-msgstr "Caminho não conduz Nó!"
+msgstr "Caminho não leva ao Nó!"
#: modules/visual_script/visual_script_func_nodes.cpp
msgid "Invalid index property name '%s' in node %s."
@@ -18266,38 +18020,32 @@ msgstr "Compor 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
-#, fuzzy
msgid "Invalid argument of type:"
-msgstr ": Argumento inválido de tipo: "
+msgstr "Argumento inválido do tipo:"
#: modules/visual_script/visual_script_nodes.cpp
-#, fuzzy
msgid "Invalid arguments:"
-msgstr ": Argumentos inválidos: "
+msgstr "Argumentos inválidos:"
#: modules/visual_script/visual_script_nodes.cpp
msgid "a if cond, else b"
msgstr "a se cond, senão b"
#: modules/visual_script/visual_script_nodes.cpp
-#, fuzzy
msgid "Var Name"
-msgstr "Nome"
+msgstr "Nome da Variável"
#: modules/visual_script/visual_script_nodes.cpp
-#, fuzzy
msgid "VariableGet not found in script:"
-msgstr "VariableGet não encontrado no script: "
+msgstr "VariableGet não encontrado no script:"
#: modules/visual_script/visual_script_nodes.cpp
-#, fuzzy
msgid "VariableSet not found in script:"
-msgstr "VariableSet não encontrado no script: "
+msgstr "VariableSet não encontrado no script:"
#: modules/visual_script/visual_script_nodes.cpp
msgid "Preload"
@@ -18413,9 +18161,8 @@ msgid "%s sec(s)"
msgstr "%s sec(s)"
#: modules/visual_script/visual_script_yield_nodes.cpp scene/main/timer.cpp
-#, fuzzy
msgid "Wait Time"
-msgstr "Pintar Tile"
+msgstr "Tempo de Espera"
#: modules/visual_script/visual_script_yield_nodes.cpp
msgid "WaitSignal"
@@ -18430,9 +18177,8 @@ msgid "WaitInstanceSignal"
msgstr "WaitInstanceSignal"
#: modules/webrtc/webrtc_data_channel.cpp
-#, fuzzy
msgid "Write Mode"
-msgstr "Modo Prioridade"
+msgstr "Modo de Escrita"
#: modules/webrtc/webrtc_data_channel.h
msgid "WebRTC"
@@ -18451,69 +18197,60 @@ msgid "Trusted SSL Certificate"
msgstr "Certificado SSL Confiável"
#: modules/websocket/websocket_macros.h
-#, fuzzy
msgid "WebSocket Client"
-msgstr "Analisador de Rede"
+msgstr "Cliente WebSocket"
#: modules/websocket/websocket_macros.h
-#, fuzzy
msgid "Max In Buffer (KB)"
-msgstr "Tamanho Máximo (KB)"
+msgstr "Buffer de Entrada Máximo (KB)"
#: modules/websocket/websocket_macros.h
msgid "Max In Packets"
msgstr "Máximo de Pacotes de Entrada"
#: modules/websocket/websocket_macros.h
-#, fuzzy
msgid "Max Out Buffer (KB)"
-msgstr "Tamanho Máximo (KB)"
+msgstr "Buffer de Saída Máximo (KB)"
#: modules/websocket/websocket_macros.h
msgid "Max Out Packets"
msgstr "Máximo de Pacotes de Saida"
#: modules/websocket/websocket_macros.h
-#, fuzzy
msgid "WebSocket Server"
-msgstr "Analisador de Rede"
+msgstr "Servidor WebSocket"
#: modules/websocket/websocket_server.cpp
msgid "Bind IP"
msgstr "Associar IP"
#: modules/websocket/websocket_server.cpp
-#, fuzzy
msgid "Private Key"
-msgstr "Caminho da Chave Privada SSH"
+msgstr "Chave Privada"
#: modules/websocket/websocket_server.cpp platform/javascript/export/export.cpp
msgid "SSL Certificate"
msgstr "Certificado SSL"
#: modules/websocket/websocket_server.cpp
-#, fuzzy
msgid "CA Chain"
-msgstr "Apagar corrente IK"
+msgstr "Cadeia CA"
#: modules/websocket/websocket_server.cpp
msgid "Handshake Timeout"
msgstr "Timeout de Handshake"
#: modules/webxr/webxr_interface.cpp
-#, fuzzy
msgid "Session Mode"
-msgstr "Modo Região"
+msgstr "Modo Sessão"
#: modules/webxr/webxr_interface.cpp
-#, fuzzy
msgid "Required Features"
-msgstr "Funcionalidades Principais:"
+msgstr "Funcionalidades Necessárias"
#: modules/webxr/webxr_interface.cpp
-#, fuzzy
msgid "Optional Features"
-msgstr "Funcionalidades Principais:"
+msgstr "Funcionalidades Opcionais"
#: modules/webxr/webxr_interface.cpp
msgid "Requested Reference Space Types"
@@ -18524,28 +18261,24 @@ msgid "Reference Space Type"
msgstr "Tipo de Espaço de Referência"
#: modules/webxr/webxr_interface.cpp
-#, fuzzy
msgid "Visibility State"
-msgstr "Alternar visibilidade"
+msgstr "Estado de Visibilidade"
#: modules/webxr/webxr_interface.cpp
-#, fuzzy
msgid "Bounds Geometry"
-msgstr "Repetir"
+msgstr "Limita a Geometria"
#: modules/webxr/webxr_interface.cpp
-#, fuzzy
msgid "XR Standard Mapping"
-msgstr "Ajuste Inteligente"
+msgstr "Mapeamento XR Padrão"
#: platform/android/export/export.cpp
msgid "Android SDK Path"
msgstr "Caminho do SDK Android"
#: platform/android/export/export.cpp
-#, fuzzy
msgid "Debug Keystore"
-msgstr "Depurador"
+msgstr "Depurar Keystore"
#: platform/android/export/export.cpp
msgid "Debug Keystore User"
@@ -18606,33 +18339,28 @@ 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"
+msgstr "Build Personalizada"
#: platform/android/export/export_plugin.cpp
msgid "Use Custom Build"
msgstr "Usar Compilação Personalizada"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Export Format"
-msgstr "Exportar Caminho"
+msgstr "Exportar Formato"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Min SDK"
-msgstr "Tamanho do contorno:"
+msgstr "SDK Mínimo"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Target SDK"
-msgstr "Alvo"
+msgstr "SDK Alvo"
#: platform/android/export/export_plugin.cpp platform/iphone/export/export.cpp
-#, fuzzy
msgid "Architectures"
-msgstr "Adicionar uma entrada arquitetura"
+msgstr "Arquiteturas"
#: platform/android/export/export_plugin.cpp
#, fuzzy
@@ -18640,86 +18368,72 @@ msgid "Keystore"
msgstr "Depurador"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Debug User"
-msgstr "Depurador"
+msgstr "Depurar Utilizador"
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
-#, fuzzy
msgid "Debug Password"
-msgstr "Senha"
+msgstr "Depurar Palavra-passe"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Release User"
-msgstr "Libertar"
+msgstr "Liberar Utilizador"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Release Password"
-msgstr "Senha"
+msgstr "Liberar Palavra-passe"
#: platform/android/export/export_plugin.cpp
msgid "One Click Deploy"
msgstr "Implantação com Um Clique"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Clear Previous Install"
-msgstr "Inspecionar instância anterior"
+msgstr "Limpar Instalação Anterior"
#: platform/android/export/export_plugin.cpp
msgid "Code"
msgstr "Código"
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
-#, fuzzy
msgid "Package"
-msgstr "Empacotamento"
+msgstr "Pacote"
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
-#, fuzzy
msgid "Unique Name"
-msgstr "Nome do Nó:"
+msgstr "Nome Único"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Signed"
-msgstr "Sinal"
+msgstr "Assinado"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Classify As Game"
-msgstr "Nome de Classe:"
+msgstr "Classificar como Jogo"
#: platform/android/export/export_plugin.cpp
msgid "Retain Data On Uninstall"
msgstr "Reter Dados na Desinstalação"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Exclude From Recents"
-msgstr "Apagar Nós"
+msgstr "Excluir de Recentes"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Graphics"
-msgstr "Compensação da grelha:"
+msgstr "Gráficos"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "OpenGL Debug"
-msgstr "Abrir"
+msgstr "Depurar OpenGL"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "XR Features"
-msgstr "Funcionalidades"
+msgstr "Funcionalidades XR"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "XR Mode"
-msgstr "Modo deslocamento"
+msgstr "Modo XR"
#: platform/android/export/export_plugin.cpp
#, fuzzy
@@ -18735,72 +18449,60 @@ msgid "Passthrough"
msgstr "Atravessar"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Immersive Mode"
-msgstr "Modo Prioridade"
+msgstr "Modo Imersivo"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Support Small"
-msgstr "Suporte"
+msgstr "Suporte Pequeno"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Support Normal"
-msgstr "Suporte"
+msgstr "Suporte Normal"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Support Large"
-msgstr "Suporte"
+msgstr "Suporte Grande"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Support Xlarge"
-msgstr "Suporte"
+msgstr "Suporte Extra-grande"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "User Data Backup"
-msgstr "Interface do Utilizador"
+msgstr "Backup de Dados do Utilizador"
#: platform/android/export/export_plugin.cpp
msgid "Allow"
msgstr "Permitir"
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
-#, fuzzy
msgid "Command Line"
-msgstr "Comunidade"
+msgstr "Linha de Comando"
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
-#, fuzzy
msgid "Extra Args"
-msgstr "Argumentos de chamada extra:"
+msgstr "Argumentos Extra"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "APK Expansion"
-msgstr "Expressão"
+msgstr "Expansão APK"
#: platform/android/export/export_plugin.cpp
msgid "Salt"
msgstr "Sal"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Public Key"
-msgstr "Caminho da Chave Pública SSH"
+msgstr "Chave Pública"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Permissions"
-msgstr "Máscara de Emissão"
+msgstr "Permissões"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Custom Permissions"
-msgstr "Executar Cena Personalizada"
+msgstr "Permissões Personalizadas"
#: platform/android/export/export_plugin.cpp
msgid "Select device from the list"
@@ -18927,69 +18629,74 @@ 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\" "
"or \"OpenXR\"."
msgstr ""
-"\"Rastreamento de Mão\" só é válido quando \"Modo Xr\" é \"Oculus Mobile "
-"VrApi\" ou \"OpenXR\"."
+"\"Hand Tracking\" só é válido quando o \"XR Mode\" é \"Oculus Mobile VrApi\" "
+"ou \"OpenXR\"."
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "\"Passthrough\" is only valid when \"XR Mode\" is \"OpenXR\"."
-msgstr "\"Passthrough\" só é válido quando \"Modo Xr\" é \"OpenXR\"."
+msgstr "\"Passthrough\" só é válido quando o \"XR Mode\" é \"OpenXR\"."
#: platform/android/export/export_plugin.cpp
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 ""
"\"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."
+"\"Min SDK\" só pode ser substituído quando \"Usar Compilação Customizada\" "
+"está ativado."
#: platform/android/export/export_plugin.cpp
msgid "\"Min SDK\" should be a valid integer, but got \"%s\" which is invalid."
msgstr ""
+"\"Min SDK\" deve ser um número inteiro válido, mas obteve \"%s\" que é "
+"inválido."
#: 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\" não pode ser inferior a %d, que é a versão necessária para a "
+"biblioteca Godot."
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid ""
"\"Target SDK\" can only be overridden when \"Use Custom Build\" is enabled."
msgstr ""
-"Mudança de \"Target Sdk\" só é válida quando \"Use Custom Build\" está ativa."
+"\"Target SDK\" só pode ser substituído quando \"Usar Compilação "
+"Customizada\" está ativado."
#: platform/android/export/export_plugin.cpp
msgid ""
"\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."
msgstr ""
+"\"Target SDK\" deve ser um número inteiro válido, mas obteve \"%s\", que é "
+"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 ""
+"\"Target SDK\" %d é superior à versão padrão %d. Isso pode funcionar, mas "
+"não foi testado e pode ser instável."
#: 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\"."
+"Versão do \"Target SDK\" precisa ser igual ou maior que a versão do \"Min "
+"SDK\"."
#: platform/android/export/export_plugin.cpp platform/osx/export/export.cpp
#: platform/windows/export/export.cpp
-#, fuzzy
msgid "Code Signing"
-msgstr "Sinal"
+msgstr "Assinatura de Código"
#: platform/android/export/export_plugin.cpp
msgid ""
@@ -19066,12 +18773,11 @@ msgstr ""
"menu 'Projeto'."
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid ""
"Unable to overwrite res://android/build/res/*.xml files with project name."
msgstr ""
-"Incapaz de sobrescrever ficheiros res://android/build/res/*.xml com o nome "
-"do projeto"
+"Incapaz de sobrescrever os ficheiros res://android/build/res/*.xml com o "
+"nome do projeto."
#: platform/android/export/export_plugin.cpp
msgid "Could not export project files to gradle project."
@@ -19107,9 +18813,8 @@ msgstr ""
"projeto gradle por resultados."
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Package not found: \"%s\"."
-msgstr "Pacote não encontrado: '%s'"
+msgstr "Pacote não encontrado: \"%s\"."
#: platform/android/export/export_plugin.cpp
msgid "Creating APK..."
@@ -19134,9 +18839,8 @@ msgid "Adding files..."
msgstr "A adicionar ficheiros..."
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Could not export project files."
-msgstr "Incapaz de exportar ficheiros do projeto"
+msgstr "Não foi possível exportar os ficheiros do projeto."
#: platform/android/export/export_plugin.cpp
msgid "Aligning APK..."
@@ -19232,9 +18936,8 @@ msgid "Code Sign Identity Release"
msgstr "Liberação de Identidade de Sinal de Código"
#: platform/iphone/export/export.cpp
-#, fuzzy
msgid "Export Method Release"
-msgstr "Modo exportação:"
+msgstr "Modo de Exportação Lançamento"
#: platform/iphone/export/export.cpp
msgid "Targeted Device Family"
@@ -19245,44 +18948,37 @@ msgid "Info"
msgstr "Informações"
#: platform/iphone/export/export.cpp platform/osx/export/export.cpp
-#, fuzzy
msgid "Identifier"
-msgstr "Identificador Inválido:"
+msgstr "Identificador"
#: platform/iphone/export/export.cpp platform/osx/export/export.cpp
-#, fuzzy
msgid "Signature"
-msgstr "Sinal"
+msgstr "Assinatura"
#: platform/iphone/export/export.cpp platform/osx/export/export.cpp
-#, fuzzy
msgid "Short Version"
-msgstr "Versão"
+msgstr "Versão Curta"
#: platform/iphone/export/export.cpp platform/osx/export/export.cpp
#: platform/windows/export/export.cpp
-#, fuzzy
msgid "Copyright"
-msgstr "Topo Direita"
+msgstr "Direitos Autorais"
#: platform/iphone/export/export.cpp
-#, fuzzy
msgid "Capabilities"
-msgstr "Colar Propriedades"
+msgstr "Capacidades"
#: platform/iphone/export/export.cpp
msgid "Access Wi-Fi"
msgstr "Acesso Wi-Fi"
#: platform/iphone/export/export.cpp
-#, fuzzy
msgid "Push Notifications"
-msgstr "Rotação aleatória:"
+msgstr "Notificações Push"
#: platform/iphone/export/export.cpp
-#, fuzzy
msgid "User Data"
-msgstr "Interface do Utilizador"
+msgstr "Dados do Utilizador"
#: platform/iphone/export/export.cpp
msgid "Accessible From Files App"
@@ -19293,19 +18989,16 @@ msgid "Accessible From iTunes Sharing"
msgstr "Acessível a partir do Compartilhamento do iTunes"
#: platform/iphone/export/export.cpp platform/osx/export/export.cpp
-#, fuzzy
msgid "Privacy"
-msgstr "Caminho da Chave Privada SSH"
+msgstr "Privacidade"
#: platform/iphone/export/export.cpp platform/osx/export/export.cpp
-#, fuzzy
msgid "Camera Usage Description"
-msgstr "Descrição"
+msgstr "Descrição do Uso da Câmara"
#: platform/iphone/export/export.cpp platform/osx/export/export.cpp
-#, fuzzy
msgid "Microphone Usage Description"
-msgstr "Descrições da Propriedade"
+msgstr "Descrição do Uso do Microfone"
#: platform/iphone/export/export.cpp
#, fuzzy
@@ -19353,9 +19046,8 @@ msgid "Use Launch Screen Storyboard"
msgstr "Use o Storyboard da Tela de Inicialização"
#: platform/iphone/export/export.cpp
-#, fuzzy
msgid "Image Scale Mode"
-msgstr "Modo Escalar"
+msgstr "Modo de Escalonamento de Imagem"
#: platform/iphone/export/export.cpp
#, fuzzy
@@ -19368,30 +19060,25 @@ msgid "Custom Image @3x"
msgstr "CustomNode"
#: platform/iphone/export/export.cpp
-#, fuzzy
msgid "Use Custom BG Color"
-msgstr "CustomNode"
+msgstr "Usar Cor Personalizada de Fundo"
#: platform/iphone/export/export.cpp
-#, fuzzy
msgid "Custom BG Color"
-msgstr "CustomNode"
+msgstr "Cor Personalizada de Fundo"
#: platform/iphone/export/export.cpp
-#, fuzzy
msgid "Export Icons"
-msgstr "Expandir Tudo"
+msgstr "Exportar Ãcones"
#: platform/iphone/export/export.cpp platform/javascript/export/export.cpp
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Prepare Templates"
-msgstr "Gerir Modelos"
+msgstr "Preparar Templates"
#: platform/iphone/export/export.cpp platform/osx/export/export.cpp
-#, fuzzy
msgid "Export template not found."
-msgstr "Modelo de lançamento personalizado não encontrado."
+msgstr "Template exportado não encontrado."
#: platform/iphone/export/export.cpp
msgid "App Store Team ID not specified - cannot configure the project."
@@ -19415,48 +19102,40 @@ msgid "Run exported HTML in the system's default browser."
msgstr "Executar HTML exportado no navegador predefinido do sistema."
#: platform/javascript/export/export.cpp
-#, fuzzy
msgid "Could not open template for export: \"%s\"."
-msgstr "Incapaz de abrir modelo para exportação:"
+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 "Modelo 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 "Incapaz de escrever ficheiro:"
+msgstr "Não foi possível escrever o ficheiro: \"%s\"."
#: platform/javascript/export/export.cpp platform/osx/export/export.cpp
-#, fuzzy
msgid "Icon Creation"
-msgstr "Definir Margem"
+msgstr "Criação de Ãcone"
#: platform/javascript/export/export.cpp
-#, fuzzy
msgid "Could not read file: \"%s\"."
-msgstr "Incapaz de ler ficheiro:"
+msgstr "Não foi possível ler o ficheiro: \"%s\"."
#: platform/javascript/export/export.cpp
msgid "PWA"
msgstr "PWA"
#: platform/javascript/export/export.cpp
-#, fuzzy
msgid "Variant"
-msgstr "Separação:"
+msgstr "Variante"
#: platform/javascript/export/export.cpp
-#, fuzzy
msgid "Export Type"
-msgstr "Exportar"
+msgstr "Tipo de Exportação"
#: platform/javascript/export/export.cpp
-#, fuzzy
msgid "VRAM Texture Compression"
-msgstr "Expressão"
+msgstr "Compressão de Texturas na VRAM"
#: platform/javascript/export/export.cpp
msgid "For Desktop"
@@ -19471,9 +19150,8 @@ msgid "HTML"
msgstr "HTML"
#: platform/javascript/export/export.cpp
-#, fuzzy
msgid "Export Icon"
-msgstr "Expandir Tudo"
+msgstr "Exportar Ãcone"
#: platform/javascript/export/export.cpp
#, fuzzy
@@ -19493,9 +19171,8 @@ msgid "Focus Canvas On Start"
msgstr "Focar Tela ao Iniciar"
#: platform/javascript/export/export.cpp
-#, fuzzy
msgid "Experimental Virtual Keyboard"
-msgstr "Filtrar sinais"
+msgstr "Teclado Virtual Experimental"
#: platform/javascript/export/export.cpp
msgid "Progressive Web App"
@@ -19518,19 +19195,16 @@ msgid "Icon 512 X 512"
msgstr "Ãcone 512 X 512"
#: platform/javascript/export/export.cpp
-#, fuzzy
msgid "Could not read HTML shell: \"%s\"."
-msgstr "Incapaz de ler shell HTML:"
+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 "Incapaz de criar diretoria do servidor HTTP:"
+msgstr "Não foi possível criar o diretório do servidor HTTP: \"%s\"."
#: platform/javascript/export/export.cpp
-#, fuzzy
msgid "Error starting HTTP server: %d."
-msgstr "Erro ao iniciar servidor HTTP:"
+msgstr "Erro ao iniciar o servidor HTTP: %d."
#: platform/javascript/export/export.cpp
msgid "Web"
@@ -19545,9 +19219,8 @@ msgid "HTTP Port"
msgstr "Porta HTTP"
#: platform/javascript/export/export.cpp
-#, fuzzy
msgid "Use SSL"
-msgstr "Usar Ajuste"
+msgstr "Usar SSL"
#: platform/javascript/export/export.cpp
msgid "SSL Key"
@@ -19576,27 +19249,24 @@ msgid "Invalid Info.plist, can't load."
msgstr "Geometria inválida, incapaz de criar polígono."
#: platform/osx/export/codesign.cpp
-#, fuzzy
msgid "Failed to create \"%s\" subfolder."
-msgstr "Não consegui criar pasta."
+msgstr "Falha ao criar sub-pasta \"%s\"."
#: platform/osx/export/codesign.cpp
msgid "Failed to extract thin binary."
msgstr "Falha ao extrair o binário fino."
#: platform/osx/export/codesign.cpp
-#, fuzzy
msgid "Invalid binary format."
-msgstr "Caminho base inválido."
+msgstr "Formato de binário inválido."
#: platform/osx/export/codesign.cpp
msgid "Already signed!"
msgstr "Já assinado!"
#: platform/osx/export/codesign.cpp
-#, fuzzy
msgid "Failed to process nested resources."
-msgstr "Falha ao carregar recurso."
+msgstr "Falha ao processar recursos aninhados."
#: platform/osx/export/codesign.cpp
msgid "Failed to create _CodeSignature subfolder."
@@ -19613,9 +19283,8 @@ msgid "Invalid entitlements file."
msgstr "Extensão inválida."
#: platform/osx/export/codesign.cpp
-#, fuzzy
msgid "Invalid executable file."
-msgstr "Extensão inválida."
+msgstr "Ficheiro executável inválido."
#: platform/osx/export/codesign.cpp
msgid "Can't resize signature load command."
@@ -19634,42 +19303,36 @@ msgid "Unknown object type."
msgstr "Tipo de objeto desconhecido."
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "App Category"
-msgstr "Categoria:"
+msgstr "Categoria da App"
#: platform/osx/export/export.cpp
msgid "High Res"
msgstr "Alta resolução"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Location Usage Description"
-msgstr "Descrição"
+msgstr "Descrição do Uso da Localização"
#: platform/osx/export/export.cpp
msgid "Address Book Usage Description"
msgstr "Descrição de Uso do Catálogo de Endereços"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Calendar Usage Description"
-msgstr "Descrição"
+msgstr "Descrição do Uso do Calendário"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Photos Library Usage Description"
-msgstr "Descrições da Propriedade"
+msgstr "Descrição do Uso da Biblioteca de Fotos"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Desktop Folder Usage Description"
-msgstr "Descrições do Método"
+msgstr "Descrição do Uso da Pasta da Ãrea de Trabalho"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Documents Folder Usage Description"
-msgstr "Descrições do Método"
+msgstr "Descrição do Uso da Pasta de Documentos"
#: platform/osx/export/export.cpp
msgid "Downloads Folder Usage Description"
@@ -19690,23 +19353,20 @@ msgstr "Nó"
#: platform/osx/export/export.cpp platform/uwp/export/export.cpp
#: platform/windows/export/export.cpp
-#, fuzzy
msgid "Identity"
-msgstr "Indentar à esquerda"
+msgstr "Identidade"
#: platform/osx/export/export.cpp platform/windows/export/export.cpp
-#, fuzzy
msgid "Timestamp"
-msgstr "Tempo"
+msgstr "Registo do Tempo"
#: platform/osx/export/export.cpp
msgid "Hardened Runtime"
msgstr "Tempo de Execução Reforçado"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Replace Existing Signature"
-msgstr "Substituir em Ficheiros"
+msgstr "Substituir Assinatura Existente"
#: platform/osx/export/export.cpp
#, fuzzy
@@ -19714,13 +19374,12 @@ msgid "Entitlements"
msgstr "Bugigangas"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Custom File"
-msgstr "CustomNode"
+msgstr "Ficheiro Personalizado"
#: 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"
@@ -19731,65 +19390,56 @@ msgid "Allow Dyld Environment Variables"
msgstr ""
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Disable Library Validation"
-msgstr "Desativar Botão"
+msgstr "Desativar Validação da Biblioteca"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Audio Input"
-msgstr "Adicionar entrada"
+msgstr "Entrada de Ãudio"
#: platform/osx/export/export.cpp
msgid "Address Book"
-msgstr ""
+msgstr "Contatos"
#: platform/osx/export/export.cpp
msgid "Calendars"
-msgstr ""
+msgstr "Calendários"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Photos Library"
-msgstr "Exportar Biblioteca"
+msgstr "Biblioteca de Fotos"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Apple Events"
-msgstr "Adicionar evento"
+msgstr "Eventos Apple"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Debugging"
-msgstr "Depurar"
+msgstr "Depuração"
#: platform/osx/export/export.cpp
msgid "App Sandbox"
msgstr ""
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Network Server"
-msgstr "Analisador de Rede"
+msgstr "Servidor de Rede"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Network Client"
-msgstr "Analisador de Rede"
+msgstr "Cliente de Rede"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Device USB"
-msgstr "Aparelho"
+msgstr "Aparelho USB"
#: platform/osx/export/export.cpp
msgid "Device Bluetooth"
-msgstr ""
+msgstr "Bluetooth do Aparelho"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Files Downloads"
-msgstr "Descarrega"
+msgstr "Descarregas de Ficheiros"
#: platform/osx/export/export.cpp
#, fuzzy
@@ -19807,9 +19457,8 @@ msgid "Files Movies"
msgstr "Filtrar Tiles"
#: platform/osx/export/export.cpp platform/windows/export/export.cpp
-#, fuzzy
msgid "Custom Options"
-msgstr "Opções de Barramento"
+msgstr "Opções Personalizadas"
#: platform/osx/export/export.cpp
#, fuzzy
@@ -19818,7 +19467,7 @@ msgstr "Localização"
#: platform/osx/export/export.cpp
msgid "Apple ID Name"
-msgstr ""
+msgstr "Nome Apple ID"
#: platform/osx/export/export.cpp
#, fuzzy
@@ -19827,21 +19476,19 @@ msgstr "Senha"
#: platform/osx/export/export.cpp
msgid "Apple Team ID"
-msgstr ""
+msgstr "ID Apple Team"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Could not open icon file \"%s\"."
-msgstr "Incapaz de exportar ficheiros do projeto"
+msgstr "Não foi possível abrir o ficheiro de ícone \"%s\"."
#: platform/osx/export/export.cpp
msgid "Could not start xcrun executable."
msgstr "Não foi possível iniciar o executável xcrun."
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Notarization failed."
-msgstr "Localização"
+msgstr "Falha na notarização."
#: platform/osx/export/export.cpp
msgid "Notarization request UUID: \"%s\""
@@ -19858,6 +19505,8 @@ msgid ""
"You can check progress manually by opening a Terminal and running the "
"following command:"
msgstr ""
+"Pode verificar o progresso manualmente abrindo um Terminal e a executar o "
+"seguinte comando:"
#: platform/osx/export/export.cpp
msgid ""
@@ -19887,25 +19536,24 @@ 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
msgid "No identity found."
-msgstr "Ãcones não encontrados."
+msgstr "Nenhuma identidade encontrada."
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Cannot sign file %s."
-msgstr "Erro ao guardar ficheiro: %s"
+msgstr "Erro ao assinar o ficheiro %s."
#: platform/osx/export/export.cpp
msgid "Relative symlinks are not supported, exported \"%s\" might be broken!"
msgstr ""
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "DMG Creation"
-msgstr "Direções"
+msgstr "Criação de DMG"
#: platform/osx/export/export.cpp
msgid "Could not start hdiutil executable."
@@ -19913,11 +19561,11 @@ msgstr "Não foi possível iniciar o executável hdiutil."
#: platform/osx/export/export.cpp
msgid "`hdiutil create` failed - file exists."
-msgstr ""
+msgstr "`hdiutil create` falhou - o ficheiro existe."
#: platform/osx/export/export.cpp
msgid "`hdiutil create` failed."
-msgstr ""
+msgstr "`hdiutil create` falhou."
#: platform/osx/export/export.cpp
#, fuzzy
@@ -19925,14 +19573,13 @@ msgid "Creating app bundle"
msgstr "A criar miniatura"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Could not find template app to export: \"%s\"."
-msgstr "Incapaz de encontrar modelo app para exportar:"
+msgstr ""
+"Não foi possível encontrar a aplicação de modelo para exportar: \"%s\"."
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Invalid export format."
-msgstr "Modelo de exportação inválido:"
+msgstr "Formato de exportação inválido."
#: platform/osx/export/export.cpp
msgid ""
@@ -19948,7 +19595,7 @@ msgstr ""
#: platform/osx/export/export.cpp
msgid "Making PKG"
-msgstr ""
+msgstr "Criando PKG"
#: platform/osx/export/export.cpp
msgid ""
@@ -19962,7 +19609,7 @@ msgstr ""
#: platform/osx/export/export.cpp
msgid "Making DMG"
-msgstr ""
+msgstr "Criando DMG"
#: platform/osx/export/export.cpp
msgid "Code signing DMG"
@@ -19970,7 +19617,7 @@ msgstr ""
#: platform/osx/export/export.cpp
msgid "Making ZIP"
-msgstr ""
+msgstr "Criando ZIP"
#: platform/osx/export/export.cpp
msgid ""
@@ -19983,9 +19630,8 @@ msgid "Sending archive for notarization"
msgstr ""
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "ZIP Creation"
-msgstr "Projeto"
+msgstr "Criação de ZIP"
#: platform/osx/export/export.cpp
msgid "Could not open file to read from path \"%s\"."
@@ -20039,6 +19685,8 @@ msgid ""
"Warning: Notarization is disabled. The exported project will be blocked by "
"Gatekeeper if it's downloaded from an unknown source."
msgstr ""
+"Aviso: Notarização está desativada. O projeto exportado será bloqueado pelo "
+"Gatekeeper se for descarregado de uma fonte desconhecida."
#: platform/osx/export/export.cpp
msgid ""
@@ -20068,70 +19716,78 @@ msgid ""
"Privacy: Microphone access is enabled, but usage description is not "
"specified."
msgstr ""
+"Privacidade: O acesso ao microfone está ativado, mas a descrição de uso não "
+"é especificada."
#: platform/osx/export/export.cpp
msgid ""
"Privacy: Camera access is enabled, but usage description is not specified."
msgstr ""
+"Privacidade: O acesso à câmara está ativado, mas a descrição de uso não é "
+"especificada."
#: platform/osx/export/export.cpp
msgid ""
"Privacy: Location information access is enabled, but usage description is "
"not specified."
msgstr ""
+"Privacidade: O acesso à localização está ativado, mas a descrição de uso não "
+"é especificada."
#: platform/osx/export/export.cpp
msgid ""
"Privacy: Address book access is enabled, but usage description is not "
"specified."
msgstr ""
+"Privacidade: O acesso ao livro de endereços está ativado, mas a descrição de "
+"uso não é especificada."
#: platform/osx/export/export.cpp
msgid ""
"Privacy: Calendar access is enabled, but usage description is not specified."
msgstr ""
+"Privacidade: O acesso ao calendário está ativado, mas a descrição de uso não "
+"é especificada."
#: platform/osx/export/export.cpp
msgid ""
"Privacy: Photo library access is enabled, but usage description is not "
"specified."
msgstr ""
+"Privacidade: O acesso à biblioteca de fotos está ativado, mas a descrição de "
+"uso não é especificada."
#: platform/osx/export/export.cpp
msgid "macOS"
-msgstr ""
+msgstr "macOS"
#: platform/osx/export/export.cpp
msgid "Force Builtin Codesign"
msgstr ""
#: platform/uwp/export/export.cpp
-#, fuzzy
msgid "Architecture"
-msgstr "Adicionar uma entrada arquitetura"
+msgstr "Arquitetura"
#: platform/uwp/export/export.cpp
-#, fuzzy
msgid "Display Name"
-msgstr "Mostrar Tudo"
+msgstr "Nome de Exibição"
#: platform/uwp/export/export.cpp
-#, fuzzy
msgid "Short Name"
-msgstr "Nome do Script:"
+msgstr "Nome Curto"
#: platform/uwp/export/export.cpp
msgid "Publisher"
-msgstr ""
+msgstr "Publicadora"
#: platform/uwp/export/export.cpp
msgid "Publisher Display Name"
msgstr "Nome de Exibição do Editor"
#: platform/uwp/export/export.cpp
-#, fuzzy
msgid "Product GUID"
-msgstr "GUID do produto inválido."
+msgstr "GUID do produto"
#: platform/uwp/export/export.cpp
#, fuzzy
@@ -20144,14 +19800,12 @@ msgid "Signing"
msgstr "Sinal"
#: platform/uwp/export/export.cpp
-#, fuzzy
msgid "Certificate"
-msgstr "Vértices:"
+msgstr "Certificado"
#: platform/uwp/export/export.cpp
-#, fuzzy
msgid "Algorithm"
-msgstr "Depurador"
+msgstr "Algoritmo"
#: platform/uwp/export/export.cpp
msgid "Major"
@@ -20167,26 +19821,24 @@ msgid "Build"
msgstr "Modo Régua"
#: platform/uwp/export/export.cpp
-#, fuzzy
msgid "Revision"
-msgstr "Expressão"
+msgstr "Revisão"
#: platform/uwp/export/export.cpp
msgid "Landscape"
-msgstr ""
+msgstr "Paisagem"
#: platform/uwp/export/export.cpp
-#, fuzzy
msgid "Portrait"
-msgstr "Inverter Portais"
+msgstr "Retrato"
#: 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
@@ -20195,33 +19847,31 @@ msgstr "Modo Escalar"
#: platform/uwp/export/export.cpp
msgid "Square 44 X 44 Logo"
-msgstr ""
+msgstr "Logo Quadrada 44 X 44"
#: platform/uwp/export/export.cpp
msgid "Square 71 X 71 Logo"
-msgstr ""
+msgstr "Logo Quadrada 71 X 71"
#: platform/uwp/export/export.cpp
msgid "Square 150 X 150 Logo"
-msgstr ""
+msgstr "Logo Quadrada 150 X 150"
#: platform/uwp/export/export.cpp
msgid "Square 310 X 310 Logo"
-msgstr ""
+msgstr "Logo Quadrada 310 X 310"
#: platform/uwp/export/export.cpp
msgid "Wide 310 X 150 Logo"
msgstr ""
#: platform/uwp/export/export.cpp
-#, fuzzy
msgid "Splash Screen"
-msgstr "Chamadas de Desenho:"
+msgstr "Escrã de Abertura"
#: platform/uwp/export/export.cpp
-#, fuzzy
msgid "Tiles"
-msgstr "Ficheiro"
+msgstr "Tiles"
#: platform/uwp/export/export.cpp
msgid "Show Name On Square 150 X 150"
@@ -20240,6 +19890,8 @@ msgid ""
"Godot's Mono version does not support the UWP platform. Use the standard "
"build (no C# support) if you wish to target UWP."
msgstr ""
+"A versão Mono do Godot não suporta a plataforma UWP. Use a build padrão (sem "
+"suporte a C#) se deseja exportar para UWP."
#: platform/uwp/export/export.cpp
msgid "Invalid package short name."
@@ -20301,7 +19953,7 @@ msgstr "Dimensões inválidas da imagem do ecrã inicial (deve ser 620x300)."
#: platform/uwp/export/export.cpp
msgid "UWP"
-msgstr ""
+msgstr "UWP"
#: platform/uwp/export/export.cpp platform/windows/export/export.cpp
#, fuzzy
@@ -20313,18 +19965,16 @@ msgid "Debug Certificate"
msgstr ""
#: platform/uwp/export/export.cpp
-#, fuzzy
msgid "Debug Algorithm"
-msgstr "Depurador"
+msgstr "Algoritmo de Depuração"
#: platform/windows/export/export.cpp
-#, fuzzy
msgid "Failed to rename temporary file \"%s\"."
-msgstr "Incapaz de remover ficheiro temporário:"
+msgstr "Falha ao renomear o ficheiro temporário \"%s\"."
#: platform/windows/export/export.cpp
msgid "Identity Type"
-msgstr ""
+msgstr "Tipo de Identidade"
#: platform/windows/export/export.cpp
msgid "Timestamp Server URL"
@@ -20336,42 +19986,36 @@ msgid "Digest Algorithm"
msgstr "Depurador"
#: 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 "Versão"
+msgstr "Versão do Ficheiro"
#: platform/windows/export/export.cpp
msgid "Product Version"
msgstr "Versão do Produto"
#: platform/windows/export/export.cpp
-#, fuzzy
msgid "Company Name"
-msgstr "Nome do Nó:"
+msgstr "Nome da Empresa"
#: platform/windows/export/export.cpp
-#, fuzzy
msgid "Product Name"
-msgstr "Nome do Projeto:"
+msgstr "Nome do Produto"
#: platform/windows/export/export.cpp
-#, fuzzy
msgid "File Description"
-msgstr "Descrição"
+msgstr "Descrição do Ficheiro"
#: platform/windows/export/export.cpp
msgid "Trademarks"
-msgstr ""
+msgstr "Marca Registada (Trademarks)"
#: platform/windows/export/export.cpp
-#, fuzzy
msgid "Resources Modification"
-msgstr "Rotação aleatória:"
+msgstr "Modificações dos Recursos"
#: platform/windows/export/export.cpp
#, fuzzy
@@ -20406,9 +20050,8 @@ msgid "Could not find osslsigncode executable at \"%s\"."
msgstr "Incapaz de encontrar keystore e exportar."
#: platform/windows/export/export.cpp
-#, fuzzy
msgid "Invalid identity type."
-msgstr "Identificador Inválido:"
+msgstr "Tipo de identidade inválido."
#: platform/windows/export/export.cpp
#, fuzzy
@@ -20428,9 +20071,8 @@ msgid "Signtool failed to sign executable: %s."
msgstr "Extensão inválida."
#: platform/windows/export/export.cpp
-#, fuzzy
msgid "Failed to remove temporary file \"%s\"."
-msgstr "Incapaz de remover ficheiro temporário:"
+msgstr "Falha ao remover o ficheiro temporário \"%s\"."
#: platform/windows/export/export.cpp
msgid ""
@@ -20452,7 +20094,7 @@ msgstr "Versão de produto inválida:"
#: platform/windows/export/export.cpp
msgid "Windows executables cannot be >= 4 GiB."
-msgstr ""
+msgstr "Executáveis Windows não podem ser >= 4GiB."
#: platform/windows/export/export.cpp platform/x11/export/export.cpp
#, fuzzy
@@ -20465,12 +20107,11 @@ msgstr ""
#: platform/windows/export/export.cpp platform/x11/export/export.cpp
msgid "Executable \"pck\" section not found."
-msgstr ""
+msgstr "Secção executável \"pck\" não encontrada."
#: platform/windows/export/export.cpp
-#, fuzzy
msgid "Windows"
-msgstr "Nova Janela"
+msgstr "Windows"
#: platform/windows/export/export.cpp
msgid "Rcedit"
@@ -20482,7 +20123,7 @@ msgstr ""
#: platform/windows/export/export.cpp
msgid "Wine"
-msgstr ""
+msgstr "Vinho"
#: platform/x11/export/export.cpp
msgid "32-bit executables cannot have embedded data >= 4 GiB."
@@ -20490,9 +20131,8 @@ msgstr ""
#: scene/2d/animated_sprite.cpp scene/3d/sprite_3d.cpp
#: scene/resources/texture.cpp
-#, fuzzy
msgid "Frames"
-msgstr "Frame %"
+msgstr "Quadros"
#: scene/2d/animated_sprite.cpp
msgid ""
@@ -20504,21 +20144,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 "Escalonamento da Velocidade"
#: 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 "Executar"
+msgstr "A executar"
#: scene/2d/animated_sprite.cpp scene/2d/sprite.cpp scene/3d/sprite_3d.cpp
-#, fuzzy
msgid "Centered"
-msgstr "Centro"
+msgstr "Centralizado"
#: scene/2d/animated_sprite.cpp scene/2d/sprite.cpp scene/3d/sprite_3d.cpp
#: scene/gui/texture_button.cpp scene/gui/texture_rect.cpp
@@ -20531,14 +20168,12 @@ msgid "Flip V"
msgstr ""
#: scene/2d/area_2d.cpp scene/3d/area.cpp
-#, fuzzy
msgid "Monitoring"
-msgstr "Monitor"
+msgstr "Monitorando"
#: scene/2d/area_2d.cpp scene/3d/area.cpp
-#, fuzzy
msgid "Monitorable"
-msgstr "Monitor"
+msgstr "Monitorável"
#: scene/2d/area_2d.cpp scene/3d/area.cpp
#, fuzzy
@@ -20551,9 +20186,8 @@ msgid "Space Override"
msgstr "Sobrepõe"
#: scene/2d/area_2d.cpp scene/3d/area.cpp
-#, fuzzy
msgid "Gravity Point"
-msgstr "Gerar Pontos"
+msgstr "Ponto de Gravidade"
#: scene/2d/area_2d.cpp scene/3d/area.cpp
#, fuzzy
@@ -20568,7 +20202,7 @@ msgstr "Pré-visualização Predefinida"
#: 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 "Gravidade"
#: scene/2d/area_2d.cpp scene/3d/area.cpp
#, fuzzy
@@ -20580,46 +20214,40 @@ msgid "Angular Damp"
msgstr ""
#: scene/2d/area_2d.cpp scene/3d/area.cpp
-#, fuzzy
msgid "Audio Bus"
-msgstr "Adicionar barramento de áudio"
+msgstr "Canal de Ãudio"
#: scene/2d/area_2d.cpp scene/3d/area.cpp
-#, fuzzy
msgid "Override"
-msgstr "Sobrepõe"
+msgstr "Sobrescrever"
#: 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 (decibéis)"
#: 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 "Escalonamento 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 "Alternar reprodução automática"
+msgstr "Reproduzir automaticamente"
#: 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 "Fluxo Pausado"
#: scene/2d/audio_stream_player_2d.cpp scene/3d/audio_stream_player_3d.cpp
#: 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 "Distância de escolha:"
+msgstr "Distância Máxima"
#: scene/2d/audio_stream_player_2d.cpp scene/3d/light.cpp
#, fuzzy
@@ -20628,39 +20256,33 @@ msgstr "Animação"
#: 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 "Adicionar Barramento"
+msgstr "Canal"
#: 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 Nós"
+msgstr "Mode de Cópia"
#: scene/2d/camera_2d.cpp
-#, fuzzy
msgid "Anchor Mode"
-msgstr "Modo Ãcone"
+msgstr "Modo de Âncora"
#: scene/2d/camera_2d.cpp
-#, fuzzy
msgid "Rotating"
-msgstr "Passo da rotação:"
+msgstr "Rotacionando"
#: 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 "Atual:"
+msgstr "Atual"
#: scene/2d/camera_2d.cpp scene/gui/graph_edit.cpp
-#, fuzzy
msgid "Zoom"
-msgstr "Aumentar Zoom"
+msgstr "Zoom"
#: scene/2d/camera_2d.cpp scene/main/canvas_layer.cpp
#, fuzzy
@@ -20676,31 +20298,27 @@ msgstr "Modo Mover"
#: 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 "Topo Esquerda"
+msgstr "Esquerda"
#: 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 "Direita"
#: 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 "Fundo Esquerda"
+msgstr "Embaixo"
#: scene/2d/camera_2d.cpp
-#, fuzzy
msgid "Smoothed"
-msgstr "Smoothstep"
+msgstr "Suavizado"
#: scene/2d/camera_2d.cpp
#, fuzzy
@@ -20718,9 +20336,8 @@ msgid "Drag Margin V Enabled"
msgstr "Definir Margem"
#: scene/2d/camera_2d.cpp
-#, fuzzy
msgid "Smoothing"
-msgstr "Smoothstep"
+msgstr "Suavizamento"
#: scene/2d/camera_2d.cpp
msgid "H"
@@ -20737,14 +20354,12 @@ msgid "Drag Margin"
msgstr "Definir Margem"
#: scene/2d/camera_2d.cpp
-#, fuzzy
msgid "Draw Screen"
-msgstr "Chamadas de Desenho:"
+msgstr "Ecrã de Desenho"
#: scene/2d/camera_2d.cpp
-#, fuzzy
msgid "Draw Limits"
-msgstr "Chamadas de Desenho:"
+msgstr "Limites de Desenho"
#: scene/2d/camera_2d.cpp
#, fuzzy
@@ -20763,9 +20378,8 @@ msgid "Light Mode"
msgstr "Direita Wide"
#: scene/2d/canvas_item.cpp
-#, fuzzy
msgid "Particles Animation"
-msgstr "Partículas"
+msgstr "Animação de Partículas"
#: scene/2d/canvas_item.cpp
msgid "Particles Anim H Frames"
@@ -20781,39 +20395,34 @@ msgid "Particles Anim Loop"
msgstr "Partículas"
#: scene/2d/canvas_item.cpp scene/3d/spatial.cpp
-#, fuzzy
msgid "Visibility"
-msgstr "Alternar visibilidade"
+msgstr "Visibilidade"
#: 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 "Alternar visibilidade"
+msgstr "Visível"
#: scene/2d/canvas_item.cpp
-#, fuzzy
msgid "Self Modulate"
-msgstr "Povoar"
+msgstr "Auto Modular"
#: scene/2d/canvas_item.cpp
msgid "Show Behind Parent"
-msgstr ""
+msgstr "Mostrar Atrás do Pai"
#: scene/2d/canvas_item.cpp
-#, fuzzy
msgid "Show On Top"
-msgstr "Mostrar Origem"
+msgstr "Mostrar Em Cima"
#: 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"
-msgstr ""
+msgstr "Usar Material do Pai"
#: scene/2d/canvas_modulate.cpp
msgid ""
@@ -20835,9 +20444,8 @@ msgstr ""
"para definir a sua forma."
#: scene/2d/collision_object_2d.cpp
-#, fuzzy
msgid "Pickable"
-msgstr "Escolher Tile"
+msgstr "Pegável"
#: scene/2d/collision_polygon_2d.cpp
msgid ""
@@ -20879,9 +20487,8 @@ msgstr "Modo Régua"
#: 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 Desativado"
+msgstr "Desativado"
#: scene/2d/collision_polygon_2d.cpp scene/2d/collision_shape_2d.cpp
#, fuzzy
@@ -20929,9 +20536,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 "Configuração:"
+msgstr "Emitindo"
#: scene/2d/cpu_particles_2d.cpp scene/2d/particles_2d.cpp
#: scene/3d/cpu_particles.cpp scene/3d/particles.cpp
@@ -20946,20 +20552,18 @@ msgstr "Nó OneShot"
#: scene/2d/cpu_particles_2d.cpp scene/2d/particles_2d.cpp
#: scene/3d/cpu_particles.cpp scene/3d/particles.cpp
-#, fuzzy
msgid "Preprocess"
-msgstr "Pós-processamento"
+msgstr "Pré processamento"
#: scene/2d/cpu_particles_2d.cpp scene/2d/particles_2d.cpp
#: scene/3d/cpu_particles.cpp scene/3d/particles.cpp
msgid "Explosiveness"
-msgstr ""
+msgstr "Explosividade"
#: scene/2d/cpu_particles_2d.cpp scene/2d/particles_2d.cpp
#: scene/3d/cpu_particles.cpp scene/3d/particles.cpp
-#, fuzzy
msgid "Randomness"
-msgstr "Reinício aleatório (s):"
+msgstr "Aleatoriedade"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
@@ -20968,9 +20572,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 Fixado"
#: scene/2d/cpu_particles_2d.cpp scene/2d/particles_2d.cpp
#: scene/3d/cpu_particles.cpp scene/3d/particles.cpp
@@ -20980,24 +20583,22 @@ 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
-#, fuzzy
msgid "Local Coords"
-msgstr "Projetos Locais"
+msgstr "Coordenadas 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
-#, fuzzy
msgid "Emission Shape"
-msgstr "Máscara de Emissão"
+msgstr "Forma de Emissão"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
@@ -21010,9 +20611,8 @@ msgid "Rect Extents"
msgstr "Bugigangas"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
-#, fuzzy
msgid "Normals"
-msgstr "Formato"
+msgstr "Normais"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
@@ -21022,51 +20622,45 @@ msgstr "Atribuir"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
-#, fuzzy
msgid "Direction"
-msgstr "Direções"
+msgstr "Direção"
#: 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 "Espalhar"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
-#, fuzzy
msgid "Initial Velocity"
-msgstr "Inicializar"
+msgstr "Velocidade Inicial"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
-#, fuzzy
msgid "Velocity Random"
-msgstr "Vista Órbita Direita"
+msgstr "Velocidade Aleatória"
#: 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 "Velocidade Angular"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
-#, fuzzy
msgid "Velocity Curve"
-msgstr "Vista Órbita Direita"
+msgstr "Curva de Velocidade"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
-#, fuzzy
msgid "Orbit Velocity"
-msgstr "Vista Órbita Direita"
+msgstr "Velocidade Orbital"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
-#, fuzzy
msgid "Linear Accel"
-msgstr "Linear"
+msgstr "Aceleração Linear"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
@@ -21076,23 +20670,22 @@ msgstr "Acel"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
msgid "Accel Random"
-msgstr ""
+msgstr "Aceleração Aleatória"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
-#, fuzzy
msgid "Accel Curve"
-msgstr "Dividir Curva"
+msgstr "Curva de Aceleração"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
msgid "Radial Accel"
-msgstr ""
+msgstr "Aceleração Radial"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
msgid "Tangential Accel"
-msgstr ""
+msgstr "Aceleração Tangencial"
#: scene/2d/cpu_particles_2d.cpp scene/2d/joints_2d.cpp
#: scene/3d/cpu_particles.cpp scene/3d/physics_body.cpp
@@ -21116,23 +20709,21 @@ msgstr "Dividir 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
msgid "Angle Random"
-msgstr ""
+msgstr "Ângulo Aleatório"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
-#, fuzzy
msgid "Angle Curve"
-msgstr "Fechar curva"
+msgstr "Curva do Ângulo"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
-#, fuzzy
msgid "Scale Amount"
-msgstr "Valor:"
+msgstr "Quantidade da Escala"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
msgid "Scale Amount Random"
@@ -21156,45 +20747,38 @@ msgstr ""
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
-#, fuzzy
msgid "Hue Variation"
-msgstr "Separação:"
+msgstr "Variação da Tonalidade"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
-#, fuzzy
msgid "Variation"
-msgstr "Separação:"
+msgstr "Variação"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
-#, fuzzy
msgid "Variation Random"
-msgstr "Separação:"
+msgstr "Variação Aleatória"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
-#, fuzzy
msgid "Variation Curve"
-msgstr "Separação:"
+msgstr "Curva de Variação"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
-#, fuzzy
msgid "Speed Random"
-msgstr "Escala"
+msgstr "Velocidade Aleatória"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
-#, fuzzy
msgid "Speed Curve"
-msgstr "Dividir Curva"
+msgstr "Curva de Velocidade"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
-#, fuzzy
msgid "Offset Random"
-msgstr "Compensação:"
+msgstr "Deslocamento Aleatório"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
@@ -21223,14 +20807,12 @@ msgid "Node A and Node B must be different PhysicsBody2Ds"
msgstr "Nó A e Nó B têm de ser PhysicsBody2Ds diferentes"
#: scene/2d/joints_2d.cpp scene/3d/physics_joint.cpp
-#, fuzzy
msgid "Node A"
-msgstr "Nó"
+msgstr "Nó A"
#: scene/2d/joints_2d.cpp scene/3d/physics_joint.cpp
-#, fuzzy
msgid "Node B"
-msgstr "Nó"
+msgstr "Nó 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
@@ -21239,9 +20821,8 @@ msgid "Bias"
msgstr ""
#: scene/2d/joints_2d.cpp
-#, fuzzy
msgid "Disable Collision"
-msgstr "Desativar Botão"
+msgstr "Desativar Colisão"
#: scene/2d/joints_2d.cpp scene/3d/physics_body.cpp scene/3d/physics_joint.cpp
msgid "Softness"
@@ -21250,7 +20831,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
@@ -21274,20 +20855,18 @@ msgstr ""
"\"Textura\"."
#: scene/2d/light_2d.cpp scene/3d/light.cpp scene/gui/reference_rect.cpp
-#, fuzzy
msgid "Editor Only"
-msgstr "Editor"
+msgstr "Somente Editor"
#: scene/2d/light_2d.cpp
-#, fuzzy
msgid "Texture Scale"
-msgstr "TextureRegion"
+msgstr "Escalonamento da Textura"
#: 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 "Energia"
#: scene/2d/light_2d.cpp
msgid "Z Min"
@@ -21312,9 +20891,8 @@ 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
@@ -21322,9 +20900,8 @@ msgid "Buffer Size"
msgstr "Vista de Trás"
#: scene/2d/light_2d.cpp
-#, fuzzy
msgid "Gradient Length"
-msgstr "Gradiente Editado"
+msgstr "Comprimento do Gradiente"
#: scene/2d/light_2d.cpp
#, fuzzy
@@ -21332,9 +20909,8 @@ msgid "Filter Smooth"
msgstr "Métodos de filtro"
#: scene/2d/light_occluder_2d.cpp
-#, fuzzy
msgid "Closed"
-msgstr "Fechar"
+msgstr "Fechado"
#: scene/2d/light_occluder_2d.cpp scene/resources/material.cpp
#, fuzzy
@@ -21353,28 +20929,24 @@ msgid "The occluder polygon for this occluder is empty. Please draw a polygon."
msgstr "O polígono oclusor deste oclusor está vazio. Desenhe um polígono."
#: scene/2d/line_2d.cpp
-#, fuzzy
msgid "Width Curve"
-msgstr "Dividir Curva"
+msgstr "Largura da Curva"
#: scene/2d/line_2d.cpp scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Default Color"
-msgstr "Predefinição"
+msgstr "Cor 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
msgid "Gradient"
-msgstr "Gradiente Editado"
+msgstr "Gradiente"
#: scene/2d/line_2d.cpp
-#, fuzzy
msgid "Texture Mode"
-msgstr "TextureRegion"
+msgstr "Modo de Textura"
#: scene/2d/line_2d.cpp
msgid "Capping"
@@ -21391,14 +20963,12 @@ msgid "Begin Cap Mode"
msgstr "Modo Região"
#: scene/2d/line_2d.cpp
-#, fuzzy
msgid "End Cap Mode"
-msgstr "Modo Ajuste:"
+msgstr "Modo de Limite Final"
#: scene/2d/line_2d.cpp scene/2d/polygon_2d.cpp scene/resources/style_box.cpp
-#, fuzzy
msgid "Border"
-msgstr "em ordem:"
+msgstr "Borda"
#: scene/2d/line_2d.cpp
msgid "Sharp Limit"
@@ -21406,7 +20976,7 @@ msgstr ""
#: scene/2d/line_2d.cpp
msgid "Round Precision"
-msgstr ""
+msgstr "Precisão do Arredondamento"
#: scene/2d/line_2d.cpp scene/2d/polygon_2d.cpp
#: scene/resources/dynamic_font.cpp
@@ -21426,9 +20996,8 @@ msgid "Cell Size"
msgstr ""
#: scene/2d/navigation_2d.cpp scene/3d/navigation.cpp
-#, fuzzy
msgid "Edge Connection Margin"
-msgstr "Editar Conexão:"
+msgstr "Margem de Ligação da Borda"
#: scene/2d/navigation_2d.cpp
msgid ""
@@ -21452,9 +21021,8 @@ 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:"
+msgstr "Distância Máxima do Caminho"
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
#, fuzzy
@@ -21480,9 +21048,8 @@ msgid "Time Horizon"
msgstr "Inverter na Horizontal"
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
msgid "Max Speed"
-msgstr "Velocidade:"
+msgstr "Velocidade Máxima"
#: scene/2d/navigation_agent_2d.cpp
#, fuzzy
@@ -21491,9 +21058,8 @@ msgid ""
msgstr "O NavigationAgent2D pode ser apenas usado dentro de um nó Node2D."
#: scene/2d/navigation_obstacle_2d.cpp scene/3d/navigation_obstacle.cpp
-#, fuzzy
msgid "Estimate Radius"
-msgstr "Mudar Raio Externo do Toro"
+msgstr "Raio Estimado"
#: scene/2d/navigation_obstacle_2d.cpp
msgid ""
@@ -21531,18 +21097,16 @@ msgid "Rotation Degrees"
msgstr "Graus de Rotação"
#: scene/2d/node_2d.cpp scene/3d/spatial.cpp
-#, fuzzy
msgid "Global Rotation"
-msgstr "Constante Global"
+msgstr "Rotação Global"
#: scene/2d/node_2d.cpp
msgid "Global Rotation Degrees"
msgstr "Graus de Rotação Global"
#: scene/2d/node_2d.cpp
-#, fuzzy
msgid "Global Scale"
-msgstr "Escala aleatória:"
+msgstr "Escala Global"
#: scene/2d/node_2d.cpp scene/3d/spatial.cpp
#, fuzzy
@@ -21557,12 +21121,11 @@ msgstr "Ajuste Relativo"
#: scene/2d/parallax_background.cpp scene/gui/scroll_container.cpp
#: scene/resources/default_theme/default_theme.cpp
msgid "Scroll"
-msgstr ""
+msgstr "Rolagem"
#: scene/2d/parallax_background.cpp
-#, fuzzy
msgid "Base Offset"
-msgstr "Compensação:"
+msgstr "Deslocamento Base"
#: scene/2d/parallax_background.cpp
#, fuzzy
@@ -21571,16 +21134,15 @@ msgstr "Usar Ajuste de Escala"
#: scene/2d/parallax_background.cpp
msgid "Limit Begin"
-msgstr ""
+msgstr "Início do Limite"
#: scene/2d/parallax_background.cpp
-#, fuzzy
msgid "Limit End"
-msgstr "No Fim"
+msgstr "Fim do limite"
#: scene/2d/parallax_background.cpp
msgid "Ignore Camera Zoom"
-msgstr ""
+msgstr "Ignorar Zoom da Câmara"
#: scene/2d/parallax_layer.cpp
msgid ""
@@ -21653,9 +21215,8 @@ msgstr ""
#: scene/2d/path_2d.cpp scene/3d/path.cpp scene/resources/sky.cpp
#: scene/resources/texture.cpp
-#, fuzzy
msgid "Curve"
-msgstr "Dividir Curva"
+msgstr "Curva"
#: scene/2d/path_2d.cpp
msgid "PathFollow2D only works when set as a child of a Path2D node."
@@ -21663,48 +21224,41 @@ msgstr ""
"PathFollow2D apenas funciona quando definido como filho de um nó Path2D."
#: scene/2d/path_2d.cpp scene/3d/path.cpp
-#, fuzzy
msgid "Unit Offset"
-msgstr "Compensação da grelha:"
+msgstr "Deslocamento da Unidade"
#: scene/2d/path_2d.cpp scene/3d/camera.cpp scene/3d/path.cpp
-#, fuzzy
msgid "H Offset"
-msgstr "Compensação:"
+msgstr "Deslocamento H"
#: scene/2d/path_2d.cpp scene/3d/camera.cpp scene/3d/path.cpp
-#, fuzzy
msgid "V Offset"
-msgstr "Compensação:"
+msgstr "Deslocamento V"
#: scene/2d/path_2d.cpp scene/3d/path.cpp
msgid "Cubic Interp"
-msgstr ""
+msgstr "Interpolação Cúbica"
#: scene/2d/path_2d.cpp
msgid "Lookahead"
msgstr ""
#: scene/2d/physics_body_2d.cpp scene/3d/visual_instance.cpp
-#, fuzzy
msgid "Layers"
-msgstr "Camada"
+msgstr "Camadas"
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
-#, fuzzy
msgid "Constant Linear Velocity"
-msgstr "Inicializar"
+msgstr "Velocidade Linear Constante"
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
-#, fuzzy
msgid "Constant Angular Velocity"
-msgstr "Inicializar"
+msgstr "Velocidade 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 "Função"
+msgstr "Fricção"
#: scene/2d/physics_body_2d.cpp scene/2d/tile_map.cpp scene/3d/physics_body.cpp
#: scene/resources/physics_material.cpp
@@ -21717,9 +21271,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 "Pré-visualização Predefinida"
+msgstr "Gravidade Padrão"
#: scene/2d/physics_body_2d.cpp
msgid ""
@@ -21733,26 +21286,23 @@ msgstr ""
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
msgid "Mass"
-msgstr ""
+msgstr "Massa"
#: scene/2d/physics_body_2d.cpp
-#, fuzzy
msgid "Inertia"
-msgstr "Vertical:"
+msgstr "Inércia"
#: 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 ""
+msgstr "Escala da Gravidade"
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
-#, fuzzy
msgid "Custom Integrator"
-msgstr "CustomNode"
+msgstr "Integrador Customizado"
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
#, fuzzy
@@ -21775,25 +21325,24 @@ msgid "Sleeping"
msgstr "Ajuste Inteligente"
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
-#, fuzzy
msgid "Can Sleep"
-msgstr "Velocidade:"
+msgstr "Pode Dormir"
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
msgid "Damp"
-msgstr ""
+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"
-msgstr ""
+msgstr "Forças Aplicadas"
#: scene/2d/physics_body_2d.cpp
msgid "Torque"
-msgstr ""
+msgstr "Torque"
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
#, fuzzy
@@ -21805,73 +21354,64 @@ msgid "Sync To Physics"
msgstr "Sincronizar com Física"
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
-#, fuzzy
msgid "Moving Platform"
-msgstr "A mover saída"
+msgstr "Plataforma Móvel"
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
msgid "Apply Velocity On Leave"
-msgstr ""
+msgstr "Aplicar Velocidade ao Sair"
#: scene/2d/physics_body_2d.cpp scene/2d/touch_screen_button.cpp
#: 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
-#, fuzzy
msgid "Remainder"
-msgstr "Renderizador:"
+msgstr "Restante"
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
-#, fuzzy
msgid "Local Shape"
-msgstr "Localização"
+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 Colisão"
+msgstr "Colisor"
#: 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 do Colisor"
#: 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 "RID do Colisor"
#: 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 Colisão"
+msgstr "Forma do Colisor"
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
-#, fuzzy
msgid "Collider Shape Index"
-msgstr "Modo Colisão"
+msgstr "Ãndice da Forma do Colisor"
#: 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 Órbita Direita"
+msgstr "Velocidade do Colisor"
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
msgid "Collider Metadata"
-msgstr ""
+msgstr "Metadados do Colisor"
#: scene/2d/polygon_2d.cpp
msgid "Invert"
-msgstr ""
+msgstr "Inverter"
#: scene/2d/polygon_2d.cpp
#, fuzzy
@@ -21890,7 +21430,7 @@ msgstr "Bugigangas"
#: scene/2d/ray_cast_2d.cpp scene/3d/ray_cast.cpp
msgid "Exclude Parent"
-msgstr ""
+msgstr "Excluir Pai"
#: scene/2d/ray_cast_2d.cpp scene/3d/ray_cast.cpp
#, fuzzy
@@ -21899,15 +21439,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."
@@ -21916,14 +21456,12 @@ msgstr ""
"válido."
#: scene/2d/remote_transform_2d.cpp scene/3d/remote_transform.cpp
-#, fuzzy
msgid "Remote Path"
-msgstr "Remover Ponto"
+msgstr "Remover Caminho"
#: scene/2d/remote_transform_2d.cpp scene/3d/remote_transform.cpp
-#, fuzzy
msgid "Use Global Coordinates"
-msgstr "Próxima Coordenada"
+msgstr "Usar Coordenadas Globais"
#: scene/2d/skeleton_2d.cpp scene/3d/skeleton.cpp
#, fuzzy
@@ -21931,9 +21469,8 @@ msgid "Rest"
msgstr "Reiniciar"
#: scene/2d/skeleton_2d.cpp
-#, fuzzy
msgid "Default Length"
-msgstr "Tema Predefinido"
+msgstr "Comprimento Padrão"
#: scene/2d/skeleton_2d.cpp
msgid "This Bone2D chain should end at a Skeleton2D node."
@@ -21977,14 +21514,12 @@ msgstr ""
"RigidBody2D, KinematicBody2D, etc. para lhes dar uma 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 "Mudar tamanho da Câmara"
+msgstr "Tamanho do Quadrante"
#: scene/2d/tile_map.cpp
#, fuzzy
@@ -21997,9 +21532,8 @@ msgid "Half Offset"
msgstr "Inicializar"
#: scene/2d/tile_map.cpp
-#, fuzzy
msgid "Tile Origin"
-msgstr "Ver origem"
+msgstr "Origem do Tile"
#: scene/2d/tile_map.cpp
#, fuzzy
@@ -22007,51 +21541,44 @@ msgid "Y Sort"
msgstr "Ordenar"
#: scene/2d/tile_map.cpp
-#, fuzzy
msgid "Show Collision"
-msgstr "Colisão"
+msgstr "Mostrar Colisão"
#: scene/2d/tile_map.cpp
-#, fuzzy
msgid "Compatibility Mode"
-msgstr "Modo Prioridade"
+msgstr "Modo de Compatibilidade"
#: scene/2d/tile_map.cpp
-#, fuzzy
msgid "Centered Textures"
-msgstr "Funcionalidades Principais:"
+msgstr "Texturas Centradas"
#: scene/2d/tile_map.cpp
msgid "Cell Clip UV"
msgstr ""
#: scene/2d/tile_map.cpp
-#, fuzzy
msgid "Use Parent"
-msgstr "Modo Colisão"
+msgstr "Usar Pai"
#: scene/2d/tile_map.cpp
msgid "Use Kinematic"
msgstr ""
#: scene/2d/touch_screen_button.cpp
-#, fuzzy
msgid "Shape Centered"
-msgstr "Ajustar ao Centro do Nó"
+msgstr "Forma Centralizada"
#: scene/2d/touch_screen_button.cpp
-#, fuzzy
msgid "Shape Visible"
-msgstr "Alternar Visibilidade"
+msgstr "Forma Visível"
#: scene/2d/touch_screen_button.cpp
msgid "Passby Press"
msgstr ""
#: scene/2d/touch_screen_button.cpp
-#, fuzzy
msgid "Visibility Mode"
-msgstr "Modo Prioridade"
+msgstr "Modo de Visibilidade"
#: scene/2d/visibility_notifier_2d.cpp
msgid ""
@@ -22062,23 +21589,20 @@ msgstr ""
"na cena raiz editada."
#: scene/2d/visibility_notifier_2d.cpp scene/3d/visibility_notifier.cpp
-#, fuzzy
msgid "Pause Animations"
-msgstr "Colar Animação"
+msgstr "Pausar Animações"
#: scene/2d/visibility_notifier_2d.cpp scene/3d/visibility_notifier.cpp
msgid "Freeze Bodies"
-msgstr ""
+msgstr "Congelar Corpos"
#: 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 "Colar Animação"
+msgstr "Pausar Sprites Animados"
#: scene/2d/visibility_notifier_2d.cpp
#, fuzzy
@@ -22108,7 +21632,7 @@ msgstr ""
#: scene/3d/arvr_nodes.cpp servers/arvr/arvr_positional_tracker.cpp
msgid "Rumble"
-msgstr ""
+msgstr "Vibrar"
#: scene/3d/arvr_nodes.cpp
msgid "ARVRController must have an ARVROrigin node as its parent."
@@ -22144,9 +21668,8 @@ msgid "ARVROrigin requires an ARVRCamera child node."
msgstr "ARVROrigin exige um nó filho ARVRCamera."
#: scene/3d/arvr_nodes.cpp servers/arvr_server.cpp
-#, fuzzy
msgid "World Scale"
-msgstr "Escala aleatória:"
+msgstr "Escala do Mundo"
#: scene/3d/audio_stream_player_3d.cpp
#, fuzzy
@@ -22155,24 +21678,23 @@ msgstr "Nó Animation"
#: 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"
msgstr ""
#: scene/3d/audio_stream_player_3d.cpp
-#, fuzzy
msgid "Emission Angle"
-msgstr "Cores de Emissão"
+msgstr "Ângulo de Emissão"
#: scene/3d/audio_stream_player_3d.cpp
msgid "Degrees"
@@ -22185,7 +21707,7 @@ msgstr "Animação"
#: scene/3d/audio_stream_player_3d.cpp
msgid "Attenuation Filter"
-msgstr ""
+msgstr "Filtro de Atenuação"
#: scene/3d/audio_stream_player_3d.cpp
#: servers/audio/effects/audio_effect_chorus.cpp
@@ -22195,14 +21717,12 @@ 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 "Ativar Doppler"
+msgstr "Doppler"
#: scene/3d/audio_stream_player_3d.cpp
#, fuzzy
@@ -22212,7 +21732,7 @@ msgstr "Empacotamento"
#: 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"
@@ -22247,7 +21767,7 @@ msgstr "Bugigangas"
#: scene/3d/baked_lightmap.cpp
msgid "Tweaks"
-msgstr ""
+msgstr "Ajustes"
#: scene/3d/baked_lightmap.cpp
msgid "Bounces"
@@ -22258,18 +21778,16 @@ msgid "Bounce Indirect Energy"
msgstr ""
#: scene/3d/baked_lightmap.cpp
-#, fuzzy
msgid "Use Denoiser"
-msgstr "Filtro:"
+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
msgid "Use Color"
-msgstr "Cores"
+msgstr "Usar Cor"
#: scene/3d/baked_lightmap.cpp
#, fuzzy
@@ -22277,38 +21795,32 @@ msgid "Default Texels Per Unit"
msgstr "Tema Predefinido"
#: scene/3d/baked_lightmap.cpp scene/resources/texture.cpp
-#, fuzzy
msgid "Atlas"
-msgstr "Novo Atlas"
+msgstr "Atlas"
#: scene/3d/baked_lightmap.cpp
-#, fuzzy
msgid "Generate"
-msgstr "Geral"
+msgstr "Gerar"
#: scene/3d/baked_lightmap.cpp
-#, fuzzy
msgid "Max Size"
-msgstr "Tamanho:"
+msgstr "Tamanho Máximo"
#: scene/3d/baked_lightmap.cpp
-#, fuzzy
msgid "Custom Sky"
-msgstr "CustomNode"
+msgstr "Céu Personalizado"
#: scene/3d/baked_lightmap.cpp
msgid "Custom Sky Rotation Degrees"
msgstr "Graus de Rotação do Céu Personalizado"
#: scene/3d/baked_lightmap.cpp scene/3d/ray_cast.cpp
-#, fuzzy
msgid "Custom Color"
-msgstr "CustomNode"
+msgstr "Cor Personalizada"
#: scene/3d/baked_lightmap.cpp
-#, fuzzy
msgid "Custom Energy"
-msgstr "Mover Efeito de Barramento"
+msgstr "Energia Personalizada"
#: scene/3d/baked_lightmap.cpp
#, fuzzy
@@ -22322,7 +21834,7 @@ msgstr "Navegação"
#: scene/3d/baked_lightmap.cpp
msgid "Image Path"
-msgstr ""
+msgstr "Caminho da Imagem"
#: scene/3d/baked_lightmap.cpp
#, fuzzy
@@ -22330,13 +21842,12 @@ msgid "Light Data"
msgstr "Com Dados"
#: scene/3d/bone_attachment.cpp scene/3d/physics_body.cpp
-#, fuzzy
msgid "Bone Name"
-msgstr "Nome do Nó:"
+msgstr "Nome do Osso"
#: scene/3d/camera.cpp
msgid "Keep Aspect"
-msgstr ""
+msgstr "Manter Aspeto"
#: scene/3d/camera.cpp scene/3d/light.cpp scene/3d/reflection_probe.cpp
msgid "Cull Mask"
@@ -22348,18 +21859,16 @@ msgid "Doppler Tracking"
msgstr "Pista de Propriedades"
#: scene/3d/camera.cpp
-#, fuzzy
msgid "Projection"
-msgstr "Projeto"
+msgstr "Projeção"
#: scene/3d/camera.cpp
msgid "FOV"
-msgstr ""
+msgstr "FOV"
#: scene/3d/camera.cpp
-#, fuzzy
msgid "Frustum Offset"
-msgstr "Compensação da grelha:"
+msgstr "Deslocamento do Frustum"
#: scene/3d/camera.cpp
#, fuzzy
@@ -22368,16 +21877,15 @@ 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
#: 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 "Definir Margem"
+msgstr "Margem"
#: scene/3d/camera.cpp
#, fuzzy
@@ -22486,28 +21994,24 @@ msgid "Ring Axis"
msgstr "Avisos"
#: scene/3d/cpu_particles.cpp scene/resources/particles_material.cpp
-#, fuzzy
msgid "Rotate Y"
-msgstr "Rodar"
+msgstr "Rotacionar em Y"
#: scene/3d/cpu_particles.cpp scene/resources/particles_material.cpp
-#, fuzzy
msgid "Disable Z"
-msgstr "Item Desativado"
+msgstr "Desativar 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 "Inverter Portais"
+msgstr "Portais"
#: scene/3d/cull_instance.cpp
-#, fuzzy
msgid "Portal Mode"
-msgstr "Modo Prioridade"
+msgstr "Modo Portal"
#: scene/3d/cull_instance.cpp
msgid "Include In Bound"
@@ -22515,7 +22019,7 @@ msgstr ""
#: scene/3d/cull_instance.cpp
msgid "Allow Merging"
-msgstr ""
+msgstr "Permitir Junção"
#: scene/3d/cull_instance.cpp
#, fuzzy
@@ -22553,9 +22057,8 @@ msgid "Subdiv"
msgstr ""
#: scene/3d/gi_probe.cpp
-#, fuzzy
msgid "Dynamic Range"
-msgstr "Biblioteca Dinâmica"
+msgstr "Alcance Dinâmico"
#: scene/3d/gi_probe.cpp scene/3d/light.cpp
msgid "Normal Bias"
@@ -22563,9 +22066,8 @@ msgstr ""
#: scene/3d/label_3d.cpp scene/3d/sprite_3d.cpp
#: scene/resources/primitive_meshes.cpp
-#, fuzzy
msgid "Pixel Size"
-msgstr "Ajuste de Pixel"
+msgstr "Tamanho de Pixel"
#: scene/3d/label_3d.cpp scene/3d/sprite_3d.cpp
msgid "Billboard"
@@ -22585,9 +22087,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 de Frente"
+msgstr "Tamanho Fixo"
#: scene/3d/label_3d.cpp scene/3d/sprite_3d.cpp
msgid "Alpha Cut"
@@ -22614,19 +22115,16 @@ msgstr "Forçar modulação branca"
#: 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 "Fontes"
+msgstr "Fonte"
#: 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
msgid "Vertical Alignment"
-msgstr "Filtrar sinais"
+msgstr "Alinhamento Vertical"
#: scene/3d/label_3d.cpp scene/gui/dialogs.cpp scene/gui/label.cpp
#, fuzzy
@@ -22634,14 +22132,12 @@ msgid "Autowrap"
msgstr "Carregamento automático"
#: scene/3d/light.cpp
-#, fuzzy
msgid "Indirect Energy"
-msgstr "Cores de Emissão"
+msgstr "Energia Indireta"
#: scene/3d/light.cpp
-#, fuzzy
msgid "Negative"
-msgstr "GDNative"
+msgstr "Negativo"
#: scene/3d/light.cpp scene/resources/material.cpp
#: scene/resources/visual_shader.cpp
@@ -22655,9 +22151,8 @@ msgid "Bake Mode"
msgstr "Modo Bitmask"
#: scene/3d/light.cpp
-#, fuzzy
msgid "Contact"
-msgstr "Escolher cor"
+msgstr "Contato"
#: scene/3d/light.cpp
#, fuzzy
@@ -22665,29 +22160,24 @@ msgid "Reverse Cull Face"
msgstr "Repor Volume do Barramento"
#: scene/3d/light.cpp servers/visual_server.cpp
-#, fuzzy
msgid "Directional Shadow"
-msgstr "Direções"
+msgstr "Sombra Direcional"
#: scene/3d/light.cpp
-#, fuzzy
msgid "Split 1"
-msgstr "Separar"
+msgstr "Dividir 1"
#: scene/3d/light.cpp
-#, fuzzy
msgid "Split 2"
-msgstr "Separar"
+msgstr "Dividir 2"
#: scene/3d/light.cpp
-#, fuzzy
msgid "Split 3"
-msgstr "Separar"
+msgstr "Dividir 3"
#: scene/3d/light.cpp
-#, fuzzy
msgid "Blend Splits"
-msgstr "Tempos de Mistura:"
+msgstr "Divisões de Mistura"
#: scene/3d/light.cpp
#, fuzzy
@@ -22695,9 +22185,8 @@ msgid "Bias Split Scale"
msgstr "Usar Ajuste de Escala"
#: scene/3d/light.cpp
-#, fuzzy
msgid "Depth Range"
-msgstr "Profundidade"
+msgstr "Alcance de Profundidade"
#: scene/3d/light.cpp
msgid "Omni"
@@ -22719,12 +22208,11 @@ msgstr "Uma SpotLight com ângulo superior a 90 graus não cria sombras."
#: scene/3d/light.cpp
msgid "Spot"
-msgstr ""
+msgstr "Ponto"
#: scene/3d/light.cpp
-#, fuzzy
msgid "Angle Attenuation"
-msgstr "Animação"
+msgstr "Atenuação Angular"
#: scene/3d/mesh_instance.cpp
msgid "Software Skinning"
@@ -22740,6 +22228,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
@@ -22756,9 +22246,8 @@ 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
@@ -22767,9 +22256,8 @@ msgid ""
msgstr "O NavigationAgent pode ser apenas usado dentro de um nó espacial."
#: scene/3d/navigation_mesh_instance.cpp scene/resources/mesh_library.cpp
-#, fuzzy
msgid "NavMesh"
-msgstr "Consolidar NavMesh"
+msgstr "NavMesh"
#: scene/3d/navigation_obstacle.cpp
#, fuzzy
@@ -22827,19 +22315,16 @@ msgstr ""
"definido como \"Billboard Particles\"."
#: scene/3d/particles.cpp
-#, fuzzy
msgid "Visibility AABB"
-msgstr "Alternar visibilidade"
+msgstr "Visibilidade AABB"
#: scene/3d/particles.cpp
-#, fuzzy
msgid "Draw Passes"
-msgstr "Chamadas de Desenho:"
+msgstr "Passos de Desenho"
#: scene/3d/particles.cpp
-#, fuzzy
msgid "Passes"
-msgstr "Chamadas de Desenho:"
+msgstr "Passos"
#: scene/3d/path.cpp
msgid "PathFollow only works when set as a child of a Path node."
@@ -22854,9 +22339,8 @@ msgstr ""
"Curva do Caminho do seu progenitor."
#: scene/3d/path.cpp
-#, fuzzy
msgid "Rotation Mode"
-msgstr "Modo Rodar"
+msgstr "Modo de Rotação"
#: scene/3d/physics_body.cpp
msgid ""
@@ -22874,46 +22358,40 @@ msgid "Axis Lock"
msgstr "Eixo"
#: scene/3d/physics_body.cpp
-#, fuzzy
msgid "Linear X"
-msgstr "Linear"
+msgstr "X Linear"
#: scene/3d/physics_body.cpp
-#, fuzzy
msgid "Linear Y"
-msgstr "Linear"
+msgstr "Y Linear"
#: scene/3d/physics_body.cpp
-#, fuzzy
msgid "Linear Z"
-msgstr "Linear"
+msgstr "Z Linear"
#: scene/3d/physics_body.cpp
msgid "Angular X"
-msgstr ""
+msgstr "X Angular"
#: scene/3d/physics_body.cpp
msgid "Angular Y"
-msgstr ""
+msgstr "Y Angular"
#: scene/3d/physics_body.cpp
msgid "Angular Z"
-msgstr ""
+msgstr "Z Angular"
#: scene/3d/physics_body.cpp
-#, fuzzy
msgid "Motion X"
-msgstr "Ação"
+msgstr "Movimento X"
#: scene/3d/physics_body.cpp
-#, fuzzy
msgid "Motion Y"
-msgstr "Ação"
+msgstr "Movimento Y"
#: scene/3d/physics_body.cpp
-#, fuzzy
msgid "Motion Z"
-msgstr "Ação"
+msgstr "Movimento Z"
#: scene/3d/physics_body.cpp
#, fuzzy
@@ -22935,14 +22413,12 @@ msgstr ""
#: scene/3d/physics_body.cpp scene/3d/physics_joint.cpp
#: scene/3d/vehicle_body.cpp
-#, fuzzy
msgid "Relaxation"
-msgstr "Separação:"
+msgstr "Relaxamento"
#: scene/3d/physics_body.cpp
-#, fuzzy
msgid "Angular Limit Enabled"
-msgstr "Filtrar sinais"
+msgstr "Limite Angular Ativado"
#: scene/3d/physics_body.cpp
#, fuzzy
@@ -23006,20 +22482,19 @@ 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
msgid "Linear Limit Enabled"
-msgstr "Linear"
+msgstr "Limite Linear Ativado"
#: scene/3d/physics_body.cpp
#, fuzzy
@@ -23037,9 +22512,8 @@ msgid "Linear Spring Damping"
msgstr "Linear"
#: scene/3d/physics_body.cpp
-#, fuzzy
msgid "Linear Equilibrium Point"
-msgstr "Linear"
+msgstr "Ponto de Equilíbrio Linear"
#: scene/3d/physics_body.cpp
#, fuzzy
@@ -23063,7 +22537,7 @@ msgstr "Animação"
#: scene/3d/physics_body.cpp scene/3d/physics_joint.cpp
msgid "ERP"
-msgstr ""
+msgstr "ERP"
#: scene/3d/physics_body.cpp
#, fuzzy
@@ -23080,12 +22554,11 @@ msgstr ""
#: scene/3d/physics_body.cpp
msgid "Angular Equilibrium Point"
-msgstr ""
+msgstr "Ponto de Equilíbrio Angular"
#: scene/3d/physics_body.cpp
-#, fuzzy
msgid "Body Offset"
-msgstr "Compensação:"
+msgstr "Deslocamento do Corpo"
#: scene/3d/physics_joint.cpp
msgid "Node A and Node B must be PhysicsBodies"
@@ -23112,18 +22585,16 @@ msgid "Solver"
msgstr ""
#: scene/3d/physics_joint.cpp
-#, fuzzy
msgid "Exclude Nodes"
-msgstr "Apagar Nós"
+msgstr "Excluir Nós"
#: scene/3d/physics_joint.cpp
-#, fuzzy
msgid "Params"
-msgstr "Parâmetro Alterado:"
+msgstr "Parâmetros"
#: scene/3d/physics_joint.cpp
msgid "Angular Limit"
-msgstr ""
+msgstr "Limite Angular"
#: scene/3d/physics_joint.cpp
#, fuzzy
@@ -23145,24 +22616,20 @@ msgid "Target Velocity"
msgstr "Vista Órbita Direita"
#: scene/3d/physics_joint.cpp
-#, fuzzy
msgid "Max Impulse"
-msgstr "Velocidade:"
+msgstr "Impulso Máximo"
#: scene/3d/physics_joint.cpp
-#, fuzzy
msgid "Linear Limit"
-msgstr "Linear"
+msgstr "Limite Linear"
#: scene/3d/physics_joint.cpp
-#, fuzzy
msgid "Upper Distance"
-msgstr "Distância de escolha:"
+msgstr "Distância mais Alta"
#: scene/3d/physics_joint.cpp
-#, fuzzy
msgid "Lower Distance"
-msgstr "Distância de escolha:"
+msgstr "Distância mais Baixa"
#: scene/3d/physics_joint.cpp
#, fuzzy
@@ -23195,9 +22662,8 @@ msgid "Angular Motion"
msgstr "Animação"
#: scene/3d/physics_joint.cpp
-#, fuzzy
msgid "Angular Ortho"
-msgstr "Máximo de Erros Angulares:"
+msgstr "Orto Angular"
#: scene/3d/physics_joint.cpp
#, fuzzy
@@ -23210,9 +22676,8 @@ msgid "Linear Motor X"
msgstr "Inicializar"
#: scene/3d/physics_joint.cpp
-#, fuzzy
msgid "Force Limit"
-msgstr "Chamadas de Desenho:"
+msgstr "Limite de Força"
#: scene/3d/physics_joint.cpp
#, fuzzy
@@ -23221,7 +22686,7 @@ msgstr "Linear"
#: scene/3d/physics_joint.cpp
msgid "Equilibrium Point"
-msgstr ""
+msgstr "Ponto de Equilíbrio"
#: scene/3d/physics_joint.cpp
msgid "Angular Limit X"
@@ -23310,9 +22775,8 @@ msgid "Two Way"
msgstr ""
#: scene/3d/portal.cpp
-#, fuzzy
msgid "Linked Room"
-msgstr "Raiz de Edição ao Vivo:"
+msgstr "Sala Vinculada"
#: scene/3d/portal.cpp
#, fuzzy
@@ -23320,18 +22784,16 @@ msgid "Use Default Margin"
msgstr "Predefinição"
#: scene/3d/proximity_group.cpp
-#, fuzzy
msgid "Group Name"
-msgstr "Agrupado"
+msgstr "Nome do Grupo"
#: scene/3d/proximity_group.cpp
msgid "Dispatch Mode"
msgstr ""
#: scene/3d/proximity_group.cpp
-#, fuzzy
msgid "Grid Radius"
-msgstr "Raio:"
+msgstr "Raio da Grade"
#: scene/3d/ray_cast.cpp
#, fuzzy
@@ -23340,7 +22802,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
@@ -23348,9 +22810,8 @@ msgid "Update Mode"
msgstr "Modo Rodar"
#: scene/3d/reflection_probe.cpp
-#, fuzzy
msgid "Origin Offset"
-msgstr "Compensação da grelha:"
+msgstr "Deslocamento da Origem"
#: scene/3d/reflection_probe.cpp
#, fuzzy
@@ -23358,19 +22819,16 @@ msgid "Box Projection"
msgstr "Projeto"
#: scene/3d/reflection_probe.cpp
-#, fuzzy
msgid "Enable Shadows"
-msgstr "Ativar Ajuste"
+msgstr "Ativar Sombras"
#: scene/3d/reflection_probe.cpp
-#, fuzzy
msgid "Ambient Color"
-msgstr "Escolher cor"
+msgstr "Cor Ambiente"
#: scene/3d/reflection_probe.cpp
-#, fuzzy
msgid "Ambient Energy"
-msgstr "Cores de Emissão"
+msgstr "Energia Ambiente"
#: scene/3d/reflection_probe.cpp
#, fuzzy
@@ -23448,38 +22906,34 @@ 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
#: scene/animation/animation_tree_player.cpp
#: servers/audio/effects/audio_effect_delay.cpp
-#, fuzzy
msgid "Active"
-msgstr "Ação"
+msgstr "Ativo"
#: 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 deslocamento"
+msgstr "Modo PVS"
#: scene/3d/room_manager.cpp
-#, fuzzy
msgid "PVS Filename"
-msgstr "Ficheiro ZIP"
+msgstr "Nome do Ficheiro PVS"
#: scene/3d/room_manager.cpp servers/visual_server.cpp
msgid "Gameplay"
-msgstr ""
+msgstr "Jogabilidade"
#: scene/3d/room_manager.cpp
#, fuzzy
@@ -23487,19 +22941,16 @@ msgid "Gameplay Monitor"
msgstr "Monitor"
#: scene/3d/room_manager.cpp
-#, fuzzy
msgid "Use Secondary PVS"
-msgstr "Usar Ajuste de Escala"
+msgstr "Usar PVS Secundário"
#: scene/3d/room_manager.cpp
-#, fuzzy
msgid "Merge Meshes"
-msgstr "Malha"
+msgstr "Mesclar Malhas"
#: scene/3d/room_manager.cpp
-#, fuzzy
msgid "Show Margins"
-msgstr "Mostrar Origem"
+msgstr "Mostrar Margens"
#: scene/3d/room_manager.cpp
#, fuzzy
@@ -23511,18 +22962,16 @@ msgid "Overlap Warning Threshold"
msgstr ""
#: scene/3d/room_manager.cpp
-#, fuzzy
msgid "Preview Camera"
-msgstr "Pré-visualização"
+msgstr "Visualizar Câmara"
#: scene/3d/room_manager.cpp
msgid "Portal Depth Limit"
msgstr ""
#: scene/3d/room_manager.cpp
-#, fuzzy
msgid "Default Portal Margin"
-msgstr "Definir Margem"
+msgstr "Margem Padrão de Portal"
#: scene/3d/room_manager.cpp
#, fuzzy
@@ -23607,9 +23056,8 @@ msgid "Spatial Attachment Path"
msgstr ""
#: scene/3d/soft_body.cpp
-#, fuzzy
msgid "Physics Enabled"
-msgstr "Frame de Física %"
+msgstr "Física Ativada"
#: scene/3d/soft_body.cpp
#, fuzzy
@@ -23621,9 +23069,8 @@ msgid "Simulation Precision"
msgstr "Precisão da Simulação"
#: scene/3d/soft_body.cpp
-#, fuzzy
msgid "Total Mass"
-msgstr "Total:"
+msgstr "Massa Total"
#: scene/3d/soft_body.cpp
msgid "Linear Stiffness"
@@ -23639,7 +23086,7 @@ msgstr ""
#: scene/3d/soft_body.cpp
msgid "Pressure Coefficient"
-msgstr ""
+msgstr "Coeficiente de Pressão"
#: scene/3d/soft_body.cpp
msgid "Damping Coefficient"
@@ -23668,18 +23115,16 @@ 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"
+msgstr "Transformação Global"
#: scene/3d/spatial.cpp
msgid "Matrix"
-msgstr ""
+msgstr "Matriz"
#: scene/3d/spatial.cpp
-#, fuzzy
msgid "Gizmo"
-msgstr "Bugigangas"
+msgstr "Gizmo"
#: scene/3d/spatial_velocity_tracker.cpp
#, fuzzy
@@ -23692,12 +23137,11 @@ 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
-#, fuzzy
msgid "Transparent"
-msgstr "Transpor"
+msgstr "Transparente"
#: scene/3d/sprite_3d.cpp
msgid ""
@@ -23721,13 +23165,12 @@ msgid "Per-Wheel Motion"
msgstr "Botão roda para baixo"
#: scene/3d/vehicle_body.cpp
-#, fuzzy
msgid "Engine Force"
-msgstr "Documentação Online"
+msgstr "Força do Motor"
#: scene/3d/vehicle_body.cpp
msgid "Brake"
-msgstr ""
+msgstr "Freio"
#: scene/3d/vehicle_body.cpp
msgid "Steering"
@@ -23738,9 +23181,8 @@ msgid "VehicleBody Motion"
msgstr ""
#: scene/3d/vehicle_body.cpp
-#, fuzzy
msgid "Use As Traction"
-msgstr "Separação:"
+msgstr "Usar Como Tração"
#: scene/3d/vehicle_body.cpp
msgid "Use As Steering"
@@ -23760,9 +23202,8 @@ msgid "Friction Slip"
msgstr "Função"
#: scene/3d/vehicle_body.cpp
-#, fuzzy
msgid "Suspension"
-msgstr "Expressão"
+msgstr "Suspensão"
#: scene/3d/vehicle_body.cpp
#, fuzzy
@@ -23771,12 +23212,21 @@ msgstr "Erro"
#: scene/3d/visibility_notifier.cpp
msgid "AABB"
-msgstr ""
+msgstr "AABB"
-#: scene/3d/visual_instance.cpp scene/resources/navigation_mesh.cpp
+#: scene/3d/visual_instance.cpp
+#, fuzzy
+msgid "Sorting"
+msgstr "Ordenar"
+
+#: scene/3d/visual_instance.cpp
#, fuzzy
+msgid "Use AABB Center"
+msgstr "Usar Ambiente"
+
+#: scene/3d/visual_instance.cpp scene/resources/navigation_mesh.cpp
msgid "Geometry"
-msgstr "Repetir"
+msgstr "Geometria"
#: scene/3d/visual_instance.cpp
#, fuzzy
@@ -23784,9 +23234,8 @@ msgid "Material Override"
msgstr "Sobrepõe"
#: scene/3d/visual_instance.cpp
-#, fuzzy
msgid "Material Overlay"
-msgstr "Mudanças de Material:"
+msgstr "Sobreposição do Material"
#: scene/3d/visual_instance.cpp
#, fuzzy
@@ -23794,9 +23243,8 @@ msgid "Cast Shadow"
msgstr "Criar Nó Shader"
#: scene/3d/visual_instance.cpp
-#, fuzzy
msgid "Extra Cull Margin"
-msgstr "Argumentos de chamada extra:"
+msgstr "Margem de Descarte Extra"
#: scene/3d/visual_instance.cpp
#, fuzzy
@@ -23814,13 +23262,12 @@ msgstr ""
#: scene/3d/visual_instance.cpp
msgid "LOD"
-msgstr ""
+msgstr "LOD (Nível de Detalhe)"
#: scene/3d/visual_instance.cpp scene/animation/skeleton_ik.cpp
#: scene/resources/material.cpp
-#, fuzzy
msgid "Min Distance"
-msgstr "Distância de escolha:"
+msgstr "Distância Mínima"
#: scene/3d/visual_instance.cpp
msgid "Min Hysteresis"
@@ -23867,33 +23314,28 @@ msgid "Mix Mode"
msgstr "Nó Mix"
#: scene/animation/animation_blend_tree.cpp
-#, fuzzy
msgid "Fadein Time"
-msgstr "Tempo X-Fade (s):"
+msgstr "Tempo de Esmaecer de Entrada"
#: scene/animation/animation_blend_tree.cpp
-#, fuzzy
msgid "Fadeout Time"
-msgstr "Tempo 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
@@ -23917,9 +23359,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 X-Fade (s):"
+msgstr "Tempo do Esmaecer Cruzado"
#: scene/animation/animation_node_state_machine.cpp
#, fuzzy
@@ -23952,7 +23393,7 @@ msgstr "Adicionar Animação"
#: scene/animation/animation_player.cpp
msgid "Reset On Save"
-msgstr ""
+msgstr "Redefinir ao Gravar"
#: scene/animation/animation_player.cpp
#, fuzzy
@@ -23965,9 +23406,8 @@ msgid "Current Animation Position"
msgstr "Adicionar Ponto 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
@@ -24009,9 +23449,8 @@ msgid "The AnimationPlayer root node is not a valid node."
msgstr "O nó raiz de 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
@@ -24067,9 +23506,8 @@ msgid "Tip Bone"
msgstr "Ossos"
#: scene/animation/skeleton_ik.cpp
-#, fuzzy
msgid "Interpolation"
-msgstr "Modo de Interpolação"
+msgstr "Interpolação"
#: scene/animation/skeleton_ik.cpp
#, fuzzy
@@ -24122,7 +23560,7 @@ msgstr "Modo Seleção"
#: scene/gui/aspect_ratio_container.cpp scene/gui/box_container.cpp
msgid "Alignment"
-msgstr ""
+msgstr "Alinhamento"
#: scene/gui/base_button.cpp
#, fuzzy
@@ -24160,11 +23598,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
@@ -24268,14 +23706,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 "Compensação da grelha:"
+msgstr "Deslocamento do Pivô"
#: scene/gui/control.cpp
#, fuzzy
@@ -24323,7 +23759,7 @@ msgstr "Anterior"
#: scene/gui/control.cpp
msgid "Mouse"
-msgstr ""
+msgstr "Mouse"
#: scene/gui/control.cpp
msgid "Default Cursor Shape"
@@ -24349,7 +23785,7 @@ msgstr "Propriedades do Tema"
#: scene/gui/dialogs.cpp
msgid "Window Title"
-msgstr ""
+msgstr "Título da Janela"
#: scene/gui/dialogs.cpp
#, fuzzy
@@ -24383,14 +23819,12 @@ msgid "Right Disconnects"
msgstr "Desligar"
#: scene/gui/graph_edit.cpp
-#, fuzzy
msgid "Scroll Offset"
-msgstr "Compensação da grelha:"
+msgstr "Deslocamento da Rolagem"
#: scene/gui/graph_edit.cpp
-#, fuzzy
msgid "Snap Distance"
-msgstr "Distância de escolha:"
+msgstr "Distância de Encaixe"
#: scene/gui/graph_edit.cpp
#, fuzzy
@@ -24415,7 +23849,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."
@@ -24488,9 +23922,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
@@ -24503,9 +23936,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
@@ -24529,9 +23961,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"
@@ -24584,24 +24015,23 @@ msgstr "Carregar como marcador de posição"
#: scene/gui/line_edit.cpp
msgid "Alpha"
-msgstr ""
+msgstr "Alfa"
#: 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
@@ -24683,9 +24113,8 @@ msgid "Allow Search"
msgstr "Procurar"
#: scene/gui/progress_bar.cpp
-#, fuzzy
msgid "Percent"
-msgstr "Recente:"
+msgstr "Percentagem"
#: scene/gui/range.cpp
msgid "If \"Exp Edit\" is enabled, \"Min Value\" must be greater than 0."
@@ -24744,9 +24173,8 @@ msgid "Absolute Index"
msgstr "Indentação Automática"
#: scene/gui/rich_text_effect.cpp
-#, fuzzy
msgid "Elapsed Time"
-msgstr "Tempos de Mistura:"
+msgstr "Tempo Decorrido"
#: scene/gui/rich_text_effect.cpp
#, fuzzy
@@ -24754,9 +24182,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"
@@ -24767,9 +24194,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
@@ -24790,9 +24216,8 @@ msgid "Selection Enabled"
msgstr "Apenas seleção"
#: 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
@@ -24820,9 +24245,8 @@ msgid "Follow Focus"
msgstr "Povoar superfície"
#: scene/gui/scroll_container.cpp
-#, fuzzy
msgid "Horizontal Enabled"
-msgstr "Horizontal:"
+msgstr "Horizontal Ativado"
#: scene/gui/scroll_container.cpp
#, fuzzy
@@ -24843,24 +24267,20 @@ msgid "Tick Count"
msgstr "Escolher cor"
#: scene/gui/slider.cpp
-#, fuzzy
msgid "Ticks On Borders"
-msgstr "em ordem:"
+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 "Compensação da grelha:"
+msgstr "Deslocamento de Divisão"
#: scene/gui/split_container.cpp scene/gui/tree.cpp
#, fuzzy
@@ -24877,9 +24297,8 @@ msgid "Tab Align"
msgstr ""
#: scene/gui/tab_container.cpp scene/gui/tabs.cpp
-#, fuzzy
msgid "Current Tab"
-msgstr "Atual:"
+msgstr "Guia Atual"
#: scene/gui/tab_container.cpp
#, fuzzy
@@ -24891,9 +24310,8 @@ msgid "All Tabs In Front"
msgstr ""
#: scene/gui/tab_container.cpp scene/gui/tabs.cpp
-#, fuzzy
msgid "Drag To Rearrange Enabled"
-msgstr "Arrastar e largar para reorganizar."
+msgstr "Arrastar Para Reorganizar Ativado"
#: scene/gui/tab_container.cpp
msgid "Use Hidden Tabs For Min Size"
@@ -24922,9 +24340,8 @@ msgid "Breakpoint Gutter"
msgstr "Saltar Pontos de Paragem"
#: scene/gui/text_edit.cpp
-#, fuzzy
msgid "Fold Gutter"
-msgstr "Pasta:"
+msgstr "Espaçamento de Dobra"
#: scene/gui/text_edit.cpp
#, fuzzy
@@ -24942,19 +24359,16 @@ msgid "Wrap Enabled"
msgstr "Ativar"
#: 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
@@ -25012,9 +24426,8 @@ msgid "Progress Offset"
msgstr ""
#: scene/gui/texture_progress.cpp
-#, fuzzy
msgid "Fill Mode"
-msgstr "Modo Jogo:"
+msgstr "Modo de Preenchimento"
#: scene/gui/texture_progress.cpp scene/resources/material.cpp
msgid "Tint"
@@ -25030,9 +24443,8 @@ msgid "Initial Angle"
msgstr "Inicializar"
#: scene/gui/texture_progress.cpp
-#, fuzzy
msgid "Fill Degrees"
-msgstr "A rodar %s graus."
+msgstr "Graus de Preenchimento"
#: scene/gui/texture_progress.cpp scene/resources/primitive_meshes.cpp
#, fuzzy
@@ -25083,9 +24495,8 @@ msgid "Hide Folding"
msgstr "Desativar Botão"
#: scene/gui/tree.cpp
-#, fuzzy
msgid "Hide Root"
-msgstr "Criar Nó Raiz:"
+msgstr "Esconder Raiz"
#: scene/gui/tree.cpp
msgid "Drop Mode Flags"
@@ -25098,7 +24509,7 @@ msgstr "Adicionar Pista"
#: 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
@@ -25139,9 +24550,8 @@ msgid "Max Redirects"
msgstr ""
#: scene/main/http_request.cpp
-#, fuzzy
msgid "Timeout"
-msgstr "Tempo expirado."
+msgstr "Tempo esgotado"
#: scene/main/node.cpp
msgid ""
@@ -25156,7 +24566,7 @@ msgstr "Separador Nomeado"
#: scene/main/node.cpp
msgid "Name Casing"
-msgstr ""
+msgstr "Capitalização do Nome"
#: scene/main/node.cpp
#, fuzzy
@@ -25169,9 +24579,8 @@ msgid "Pause Mode"
msgstr "Modo deslocamento"
#: scene/main/node.cpp
-#, fuzzy
msgid "Physics Interpolation Mode"
-msgstr "Modo de Interpolação"
+msgstr "Modo de Interpolação da Física"
#: scene/main/node.cpp
#, fuzzy
@@ -25184,19 +24593,16 @@ msgid "Filename"
msgstr "Renomear"
#: scene/main/node.cpp
-#, fuzzy
msgid "Owner"
-msgstr "Proprietários de:"
+msgstr "Dono"
#: scene/main/node.cpp scene/main/scene_tree.cpp
-#, fuzzy
msgid "Multiplayer"
-msgstr "Multiplicar %s"
+msgstr "Multijogador"
#: scene/main/node.cpp
-#, fuzzy
msgid "Custom Multiplayer"
-msgstr "Definir Múltiplo:"
+msgstr "Multijogador Personalizado"
#: scene/main/node.cpp
#, fuzzy
@@ -25229,7 +24635,7 @@ msgstr "Nova Raiz da Cena"
#: scene/main/scene_tree.cpp
msgid "Root"
-msgstr ""
+msgstr "Raiz"
#: scene/main/scene_tree.cpp
#, fuzzy
@@ -25239,11 +24645,11 @@ msgstr "Multiplicar %s"
#: 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"
-msgstr ""
+msgstr "Cor da Forma"
#: scene/main/scene_tree.cpp
#, fuzzy
@@ -25252,7 +24658,7 @@ msgstr "Escolher cor"
#: scene/main/scene_tree.cpp
msgid "Geometry Color"
-msgstr ""
+msgstr "Cor da Geometria"
#: scene/main/scene_tree.cpp
#, fuzzy
@@ -25269,14 +24675,12 @@ msgid "Draw 2D Outlines"
msgstr "Criar contorno"
#: scene/main/scene_tree.cpp servers/visual_server.cpp
-#, fuzzy
msgid "Reflections"
-msgstr "Direções"
+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"
@@ -25288,7 +24692,7 @@ msgstr ""
#: scene/main/scene_tree.cpp
msgid "Use FXAA"
-msgstr ""
+msgstr "Usar FXAA"
#: scene/main/scene_tree.cpp
msgid "Use Debanding"
@@ -25296,16 +24700,15 @@ 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"
msgstr ""
#: scene/main/scene_tree.cpp
-#, fuzzy
msgid "Default Environment"
-msgstr "Ver ambiente"
+msgstr "Ambiente Padrão"
#: scene/main/scene_tree.cpp
msgid ""
@@ -25334,9 +24737,8 @@ msgstr ""
"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
@@ -25362,7 +24764,7 @@ msgstr ""
#: scene/main/viewport.cpp
msgid "ARVR"
-msgstr ""
+msgstr "ARVR"
#: scene/main/viewport.cpp
#, fuzzy
@@ -25375,16 +24777,15 @@ 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
msgid "Transparent BG"
-msgstr "Transpor"
+msgstr "Fundo Transparente"
#: scene/main/viewport.cpp
#, fuzzy
@@ -25393,7 +24794,7 @@ msgstr "Mudar valor de entrada"
#: scene/main/viewport.cpp
msgid "FXAA"
-msgstr ""
+msgstr "FXAA"
#: scene/main/viewport.cpp
#, fuzzy
@@ -25412,7 +24813,7 @@ msgstr "Linear Esquerda"
#: scene/main/viewport.cpp
msgid "Render Direct To Screen"
-msgstr ""
+msgstr "Renderizar Diretamente ao Ecrã"
#: scene/main/viewport.cpp
#, fuzzy
@@ -25420,9 +24821,8 @@ msgid "Debug Draw"
msgstr "Depurar"
#: scene/main/viewport.cpp
-#, fuzzy
msgid "Render Target"
-msgstr "Renderizador:"
+msgstr "Alvo do Renderizador"
#: scene/main/viewport.cpp
msgid "V Flip"
@@ -25530,7 +24930,7 @@ msgstr "Navegação"
#: scene/register_scene_types.cpp
msgid "Use hiDPI"
-msgstr ""
+msgstr "Usar hiDPI"
#: scene/register_scene_types.cpp
#, fuzzy
@@ -25550,12 +24950,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
@@ -25568,7 +24967,7 @@ msgstr ""
#: scene/resources/default_theme/default_theme.cpp
msgid "Panel"
-msgstr ""
+msgstr "Painel"
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
@@ -25596,9 +24995,8 @@ msgid "Font Color Disabled"
msgstr "Recorte desativado"
#: 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
@@ -25607,7 +25005,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
@@ -25686,14 +25084,12 @@ msgid "Font Outline Modulate"
msgstr "Forçar modulação branca"
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Shadow Offset X"
-msgstr "Deslocação X da grelha:"
+msgstr "Deslocamento da Sombra em X"
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Shadow Offset Y"
-msgstr "Deslocação Y da grelha:"
+msgstr "Deslocamento da Sombra em Y"
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
@@ -25751,14 +25147,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"
@@ -25922,14 +25316,12 @@ msgid "Font Color Accel"
msgstr "Renomear Item Cor"
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Font Color Separator"
-msgstr "Operador de Cor."
+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
@@ -25982,9 +25374,8 @@ msgid "Close Offset"
msgstr "Compensação da grelha:"
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Port Offset"
-msgstr "Compensação da grelha:"
+msgstr "Deslocamento de Porta"
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
@@ -25998,7 +25389,7 @@ msgstr "Selecionar"
#: scene/resources/default_theme/default_theme.cpp
msgid "Cursor Unfocused"
-msgstr ""
+msgstr "Cursor Desfocado"
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
@@ -26094,14 +25485,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 "Compensação da grelha:"
+msgstr "Velocidade de Rolagem"
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
@@ -26109,9 +25498,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
@@ -26119,9 +25507,8 @@ msgid "Tab FG"
msgstr "Aba 1"
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Tab BG"
-msgstr "Aba 1"
+msgstr "BG da Guia"
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
@@ -26130,7 +25517,7 @@ msgstr "Item Desativado"
#: scene/resources/default_theme/default_theme.cpp
msgid "Menu"
-msgstr ""
+msgstr "Menu"
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
@@ -26171,9 +25558,8 @@ msgid "Large"
msgstr "Alvo"
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Folder"
-msgstr "Pasta:"
+msgstr "Pasta"
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
@@ -26211,9 +25597,8 @@ msgid "Label Width"
msgstr "Esquerda Wide"
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Screen Picker"
-msgstr "Operador Ecrã."
+msgstr "Seletor de Ecrã"
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
@@ -26231,9 +25616,8 @@ msgid "Color Sample"
msgstr "Cores"
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Preset BG"
-msgstr "Predefinições"
+msgstr "Fundo Predefinido"
#: scene/resources/default_theme/default_theme.cpp
msgid "Overbright Indicator"
@@ -26245,9 +25629,8 @@ msgid "Preset FG"
msgstr "Predefinições"
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Preset BG Icon"
-msgstr "Predefinições"
+msgstr "Ãcone de Fundo Predefinido"
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
@@ -26266,7 +25649,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
@@ -26274,14 +25657,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
@@ -26310,11 +25691,11 @@ msgstr "Corte automático"
#: 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
@@ -26374,9 +25755,8 @@ msgid "Font Path"
msgstr "Caminho de Foco"
#: scene/resources/dynamic_font.cpp
-#, fuzzy
msgid "Outline Size"
-msgstr "Tamanho do contorno:"
+msgstr "Tamanho do Contorno"
#: scene/resources/dynamic_font.cpp
#, fuzzy
@@ -26389,14 +25769,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
@@ -26405,11 +25783,11 @@ msgstr "Com Dados"
#: scene/resources/environment.cpp
msgid "Background"
-msgstr ""
+msgstr "Plano de Fundo"
#: scene/resources/environment.cpp scene/resources/sky.cpp
msgid "Sky"
-msgstr ""
+msgstr "Céu"
#: scene/resources/environment.cpp
#, fuzzy
@@ -26422,14 +25800,12 @@ msgid "Sky Orientation"
msgstr "Documentação Online"
#: scene/resources/environment.cpp
-#, fuzzy
msgid "Sky Rotation"
-msgstr "Passo da rotação:"
+msgstr "Rotação do Céu"
#: scene/resources/environment.cpp
-#, fuzzy
msgid "Sky Rotation Degrees"
-msgstr "A rodar %s graus."
+msgstr "Graus de Rotação do Céu"
#: scene/resources/environment.cpp
msgid "Canvas Max Layer"
@@ -26451,17 +25827,15 @@ msgstr "Condição"
#: scene/resources/environment.cpp
msgid "Fog"
-msgstr ""
+msgstr "Névoa"
#: scene/resources/environment.cpp
-#, fuzzy
msgid "Sun Color"
-msgstr "Armazenar o Ficheiro:"
+msgstr "Cor do Sol"
#: scene/resources/environment.cpp
-#, fuzzy
msgid "Sun Amount"
-msgstr "Valor:"
+msgstr "Quantidade do Sol"
#: scene/resources/environment.cpp
#, fuzzy
@@ -26525,7 +25899,7 @@ msgstr "Exportar"
#: scene/resources/environment.cpp
msgid "White"
-msgstr ""
+msgstr "Branco"
#: scene/resources/environment.cpp
msgid "Auto Exposure"
@@ -26550,14 +25924,12 @@ msgid "Max Steps"
msgstr "Passo"
#: scene/resources/environment.cpp
-#, fuzzy
msgid "Fade In"
-msgstr "Aparecer (s):"
+msgstr "Esmaecer de Entrada"
#: scene/resources/environment.cpp
-#, fuzzy
msgid "Fade Out"
-msgstr "Desvanecer (s):"
+msgstr "Esmaecer de Saída"
#: scene/resources/environment.cpp
#, fuzzy
@@ -26566,16 +25938,15 @@ msgstr "Profundidade"
#: scene/resources/environment.cpp scene/resources/material.cpp
msgid "Roughness"
-msgstr ""
+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"
@@ -26604,9 +25975,8 @@ msgid "DOF Far Blur"
msgstr ""
#: scene/resources/environment.cpp scene/resources/material.cpp
-#, fuzzy
msgid "Distance"
-msgstr "Distância de escolha:"
+msgstr "Distância"
#: scene/resources/environment.cpp
msgid "Transition"
@@ -26618,7 +25988,7 @@ msgstr ""
#: scene/resources/environment.cpp
msgid "Glow"
-msgstr ""
+msgstr "Brilho"
#: scene/resources/environment.cpp
#, fuzzy
@@ -26680,7 +26050,7 @@ msgstr ""
#: scene/resources/environment.cpp
msgid "Adjustments"
-msgstr ""
+msgstr "Ajustamentos"
#: scene/resources/environment.cpp
#, fuzzy
@@ -26688,19 +26058,16 @@ msgid "Brightness"
msgstr "Luz"
#: scene/resources/environment.cpp
-#, fuzzy
msgid "Saturation"
-msgstr "Separação:"
+msgstr "Separação"
#: scene/resources/environment.cpp
-#, fuzzy
msgid "Color Correction"
-msgstr "Função Cor."
+msgstr "Correção de Cor"
#: scene/resources/font.cpp
-#, fuzzy
msgid "Ascent"
-msgstr "Recente:"
+msgstr "Subida"
#: scene/resources/font.cpp
#, fuzzy
@@ -26713,9 +26080,8 @@ msgid "Raw Data"
msgstr "Profundidade"
#: scene/resources/gradient.cpp
-#, fuzzy
msgid "Offsets"
-msgstr "Compensação:"
+msgstr "Deslocamentos"
#: scene/resources/height_map_shape.cpp
msgid "Map Width"
@@ -26745,9 +26111,8 @@ msgid "Use Shadow To Opacity"
msgstr ""
#: scene/resources/material.cpp
-#, fuzzy
msgid "Unshaded"
-msgstr "Vista sem sombras"
+msgstr "Sem sombra"
#: scene/resources/material.cpp
#, fuzzy
@@ -26769,7 +26134,7 @@ msgstr ""
#: scene/resources/material.cpp
msgid "Do Not Receive Shadows"
-msgstr ""
+msgstr "Não Receber Sombras"
#: scene/resources/material.cpp
#, fuzzy
@@ -26796,12 +26161,11 @@ msgstr ""
#: scene/resources/material.cpp
msgid "Is sRGB"
-msgstr ""
+msgstr "É sRGB"
#: scene/resources/material.cpp servers/visual_server.cpp
-#, fuzzy
msgid "Parameters"
-msgstr "Parâmetro Alterado:"
+msgstr "Parâmetros"
#: scene/resources/material.cpp
#, fuzzy
@@ -26840,12 +26204,11 @@ msgstr "Modo Régua"
#: scene/resources/material.cpp
msgid "Grow"
-msgstr ""
+msgstr "Crescer"
#: scene/resources/material.cpp
-#, fuzzy
msgid "Grow Amount"
-msgstr "Valor:"
+msgstr "Quantidade de Crescimento"
#: scene/resources/material.cpp
msgid "Use Alpha Scissor"
@@ -26868,11 +26231,11 @@ msgstr "Frame %"
#: scene/resources/material.cpp
msgid "Albedo"
-msgstr ""
+msgstr "Albedo"
#: scene/resources/material.cpp
msgid "Metallic"
-msgstr ""
+msgstr "Metálico"
#: scene/resources/material.cpp
#, fuzzy
@@ -26880,9 +26243,8 @@ msgid "Texture Channel"
msgstr "TextureRegion"
#: scene/resources/material.cpp
-#, fuzzy
msgid "Emission"
-msgstr "Máscara de Emissão"
+msgstr "Emissão"
#: scene/resources/material.cpp
msgid "On UV2"
@@ -26907,7 +26269,7 @@ msgstr ""
#: scene/resources/material.cpp
msgid "Anisotropy"
-msgstr ""
+msgstr "Anisotrópico"
#: scene/resources/material.cpp
msgid "Flowmap"
@@ -26950,13 +26312,12 @@ msgid "Transmission"
msgstr "Transmissão"
#: scene/resources/material.cpp
-#, fuzzy
msgid "Refraction"
-msgstr "Separação:"
+msgstr "Refração"
#: scene/resources/material.cpp
msgid "Detail"
-msgstr ""
+msgstr "Detalhe"
#: scene/resources/material.cpp
#, fuzzy
@@ -27002,7 +26363,7 @@ msgstr "Consolidar Lightmaps"
#: scene/resources/mesh.cpp scene/resources/primitive_meshes.cpp
msgid "Custom AABB"
-msgstr ""
+msgstr "AABB Personalizado"
#: scene/resources/mesh_library.cpp
#, fuzzy
@@ -27015,14 +26376,12 @@ msgid "NavMesh Transform"
msgstr "Limpar Transformação"
#: scene/resources/multimesh.cpp
-#, fuzzy
msgid "Color Format"
-msgstr "Operador de Cor."
+msgstr "Formato de Cor"
#: scene/resources/multimesh.cpp
-#, fuzzy
msgid "Transform Format"
-msgstr "Transformação Abortada."
+msgstr "Formato de Transformação"
#: scene/resources/multimesh.cpp
msgid "Custom Data Format"
@@ -27035,12 +26394,11 @@ msgstr "Instância"
#: scene/resources/multimesh.cpp
msgid "Visible Instance Count"
-msgstr ""
+msgstr "Quantidade de Instâncias Visíveis"
#: scene/resources/navigation_mesh.cpp
-#, fuzzy
msgid "Sampling"
-msgstr "A escalar: "
+msgstr "Mostragem"
#: scene/resources/navigation_mesh.cpp
#, fuzzy
@@ -27048,27 +26406,24 @@ msgid "Partition Type"
msgstr "Definir tipo de variável"
#: scene/resources/navigation_mesh.cpp
-#, fuzzy
msgid "Parsed Geometry Type"
-msgstr "A analisar geometria..."
+msgstr "Tipo de Geometria Analisada"
#: scene/resources/navigation_mesh.cpp
msgid "Source Geometry Mode"
msgstr ""
#: scene/resources/navigation_mesh.cpp
-#, fuzzy
msgid "Source Group Name"
-msgstr "Fonte"
+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"
@@ -27090,7 +26445,7 @@ msgstr "Mesclar a partir da Cena"
#: scene/resources/navigation_mesh.cpp
msgid "Edges"
-msgstr ""
+msgstr "Arestas"
#: scene/resources/navigation_mesh.cpp
#, fuzzy
@@ -27099,7 +26454,7 @@ msgstr "Erro"
#: scene/resources/navigation_mesh.cpp
msgid "Verts Per Poly"
-msgstr ""
+msgstr "Vértices Por Polígono"
#: scene/resources/navigation_mesh.cpp
#, fuzzy
@@ -27107,9 +26462,8 @@ msgid "Details"
msgstr "Mostrar Predefinição"
#: scene/resources/navigation_mesh.cpp
-#, fuzzy
msgid "Sample Distance"
-msgstr "Distância de escolha:"
+msgstr "Distância de Amostra"
#: scene/resources/navigation_mesh.cpp
#, fuzzy
@@ -27140,7 +26494,7 @@ msgstr "Compensação:"
#: scene/resources/occluder_shape.cpp
msgid "Spheres"
-msgstr ""
+msgstr "Esferas"
#: scene/resources/occluder_shape.cpp
msgid "OccluderShapeSphere Set Spheres"
@@ -27180,9 +26534,8 @@ msgid "Color Modifier"
msgstr "Freelook Modificador de Lentidão"
#: 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"
@@ -27199,9 +26552,8 @@ msgid "Point Count"
msgstr "Adicionar Porta de Entrada"
#: scene/resources/particles_material.cpp
-#, fuzzy
msgid "Scale Random"
-msgstr "Proporção de Escala:"
+msgstr "Randomização de Escala"
#: scene/resources/particles_material.cpp
#, fuzzy
@@ -27217,9 +26569,8 @@ msgid "Absorbent"
msgstr ""
#: scene/resources/plane_shape.cpp
-#, fuzzy
msgid "Plane"
-msgstr "Plano:"
+msgstr "Plano"
#: scene/resources/primitive_meshes.cpp
#, fuzzy
@@ -27243,9 +26594,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
@@ -27294,9 +26644,8 @@ 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"
@@ -27308,9 +26657,8 @@ msgid "Top Color"
msgstr "Próximo Piso"
#: scene/resources/sky.cpp
-#, fuzzy
msgid "Horizon Color"
-msgstr "Armazenar o Ficheiro:"
+msgstr "Cor do Horizonte"
#: scene/resources/sky.cpp
#, fuzzy
@@ -27334,7 +26682,7 @@ msgstr "Substituto"
#: scene/resources/sky.cpp
msgid "Longitude"
-msgstr ""
+msgstr "Longitude"
#: scene/resources/sky.cpp
msgid "Angle Min"
@@ -27369,7 +26717,7 @@ msgstr ""
#: scene/resources/style_box.cpp
msgid "Anti Aliasing"
-msgstr ""
+msgstr "Anti Serrilhamento"
#: scene/resources/style_box.cpp
msgid "Grow Begin"
@@ -27419,9 +26767,8 @@ msgid "Lossy Storage Quality"
msgstr "Capturar"
#: scene/resources/texture.cpp
-#, fuzzy
msgid "From"
-msgstr "Modo Jogo:"
+msgstr "À Partir de"
#: scene/resources/texture.cpp
#, fuzzy
@@ -27595,11 +26942,11 @@ msgstr "Editar Conexão:"
#: scene/resources/world_2d.cpp
msgid "Canvas"
-msgstr ""
+msgstr "Tela"
#: servers/arvr/arvr_interface.cpp
msgid "Is Primary"
-msgstr ""
+msgstr "É Principal"
#: servers/arvr/arvr_interface.cpp
#, fuzzy
@@ -27625,9 +26972,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
@@ -27637,27 +26983,27 @@ msgstr ""
#: servers/audio/effects/audio_effect_chorus.cpp
msgid "Voice Count"
-msgstr ""
+msgstr "Quantidade de Vozes"
#: servers/audio/effects/audio_effect_chorus.cpp
#: 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
@@ -27672,7 +27018,7 @@ 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
@@ -27684,11 +27030,11 @@ msgstr "Plano:"
#: 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
@@ -27725,7 +27071,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"
@@ -27775,13 +27121,12 @@ 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"
@@ -27789,7 +27134,7 @@ msgstr ""
#: servers/audio/effects/audio_effect_reverb.cpp
msgid "Room Size"
-msgstr ""
+msgstr "Tamanho da Sala"
#: servers/audio/effects/audio_effect_reverb.cpp
#, fuzzy
@@ -27805,9 +27150,8 @@ msgid "Pan Pullout"
msgstr ""
#: servers/audio/effects/audio_effect_stereo_enhance.cpp
-#, fuzzy
msgid "Time Pullout (ms)"
-msgstr "Tempo expirado."
+msgstr "Retirada de Tempo (ms)"
#: servers/audio/effects/audio_effect_stereo_enhance.cpp
msgid "Surround"
@@ -27819,9 +27163,8 @@ msgid "Enable Audio Input"
msgstr "Renomear o barramento de áudio"
#: servers/audio_server.cpp
-#, fuzzy
msgid "Output Latency"
-msgstr "Saída"
+msgstr "Latência de Saída"
#: servers/audio_server.cpp
msgid "Channel Disable Threshold dB"
@@ -27870,12 +27213,11 @@ msgstr ""
#: servers/physics/space_sw.cpp servers/physics_2d/space_2d_sw.cpp
msgid "Time Before Sleep"
-msgstr ""
+msgstr "Tempo Antes de Dormir"
#: 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"
@@ -27883,12 +27225,11 @@ msgstr ""
#: servers/physics_2d_server.cpp servers/physics_server.cpp
msgid "Inverse Mass"
-msgstr ""
+msgstr "Inverter Massa"
#: servers/physics_2d_server.cpp servers/physics_server.cpp
-#, fuzzy
msgid "Inverse Inertia"
-msgstr "Freelook Esquerda"
+msgstr "Inverter Inércia"
#: servers/physics_2d_server.cpp servers/physics_server.cpp
msgid "Total Angular Damp"
@@ -27911,7 +27252,7 @@ msgstr "Inicializar"
#: servers/physics_2d_server.cpp servers/physics_server.cpp
msgid "Exclude"
-msgstr ""
+msgstr "Excluir"
#: servers/physics_2d_server.cpp servers/physics_server.cpp
msgid "Shape RID"
@@ -27924,7 +27265,7 @@ msgstr "Modo Colisão"
#: servers/physics_2d_server.cpp servers/physics_server.cpp
msgid "Collide With Areas"
-msgstr ""
+msgstr "Colidir com Ãreas"
#: servers/physics_2d_server.cpp servers/physics_server.cpp
msgid "Motion Remainder"
@@ -28004,9 +27345,8 @@ msgid "Constants cannot be modified."
msgstr "Constantes não podem ser modificadas."
#: servers/visual/visual_server_scene.cpp
-#, fuzzy
msgid "Spatial Partitioning"
-msgstr "A segmentar..."
+msgstr "Particionamento Espacial"
#: servers/visual_server.cpp
#, fuzzy
@@ -28045,16 +27385,15 @@ msgstr "Importar tema"
#: servers/visual_server.cpp
msgid "Lossless Compression"
-msgstr ""
+msgstr "Compressão Sem Perda"
#: servers/visual_server.cpp
-#, fuzzy
msgid "Force PNG"
-msgstr "Forçar Impulso"
+msgstr "Forçar PNG"
#: servers/visual_server.cpp
msgid "WebP Compression Level"
-msgstr ""
+msgstr "Nível de Compressão WebP"
#: servers/visual_server.cpp
msgid "Time Rollover Secs"
@@ -28098,7 +27437,7 @@ msgstr "Centrar Seleção"
#: servers/visual_server.cpp
msgid "High Quality GGX"
-msgstr ""
+msgstr "GGX de Alta Qualidade"
#: servers/visual_server.cpp
msgid "Irradiance Max Size"
@@ -28172,9 +27511,8 @@ msgid "Ninepatch Mode"
msgstr "Modo de Interpolação"
#: servers/visual_server.cpp
-#, fuzzy
msgid "OpenGL"
-msgstr "Abrir"
+msgstr "abrir"
#: servers/visual_server.cpp
msgid "Batching Send Null"
@@ -28194,9 +27532,8 @@ msgid "Legacy Stream"
msgstr ""
#: servers/visual_server.cpp
-#, fuzzy
msgid "Batching"
-msgstr "A procurar..."
+msgstr "Loteamento"
#: servers/visual_server.cpp
msgid "Use Batching"
@@ -28224,9 +27561,8 @@ msgid "Scissor Area Threshold"
msgstr ""
#: servers/visual_server.cpp
-#, fuzzy
msgid "Max Join Items"
-msgstr "Gerir Itens..."
+msgstr "Máximo de Itens de Junção"
#: servers/visual_server.cpp
msgid "Batch Buffer Size"
@@ -28238,7 +27574,7 @@ msgstr ""
#: servers/visual_server.cpp
msgid "Flash Batching"
-msgstr ""
+msgstr "Loteamento de Flashes"
#: servers/visual_server.cpp
#, fuzzy
@@ -28247,15 +27583,15 @@ msgstr "Colar Frame"
#: servers/visual_server.cpp
msgid "GLES2"
-msgstr ""
+msgstr "GLES2"
#: servers/visual_server.cpp
msgid "Compatibility"
-msgstr ""
+msgstr "Compatibilidade"
#: servers/visual_server.cpp
msgid "Disable Half Float"
-msgstr ""
+msgstr "Desativar Meia Float"
#: servers/visual_server.cpp
#, fuzzy
@@ -28269,11 +27605,11 @@ msgstr "Expressão"
#: servers/visual_server.cpp
msgid "UV Contract"
-msgstr ""
+msgstr "Contrato UV"
#: servers/visual_server.cpp
msgid "UV Contract Amount"
-msgstr ""
+msgstr "Valor do Contrato UV"
#: servers/visual_server.cpp
#, fuzzy
@@ -28282,7 +27618,7 @@ msgstr "Usar Ajuste de Escala"
#: servers/visual_server.cpp
msgid "PVS Logging"
-msgstr ""
+msgstr "Registo PVS"
#: servers/visual_server.cpp
#, fuzzy
@@ -28306,12 +27642,11 @@ msgstr "Ver Culling da Oclusão"
#: servers/visual_server.cpp
msgid "Max Active Spheres"
-msgstr ""
+msgstr "Máximo de Esferas Ativas"
#: servers/visual_server.cpp
-#, fuzzy
msgid "Max Active Polygons"
-msgstr "Mover Polígono"
+msgstr "Máximo de Polígonos Ativos"
#: servers/visual_server.cpp
#, fuzzy
diff --git a/editor/translations/pt_BR.po b/editor/translations/pt_BR.po
index 30ad718462..8e574f992d 100644
--- a/editor/translations/pt_BR.po
+++ b/editor/translations/pt_BR.po
@@ -38,7 +38,7 @@
# Pedro Pacheco <pedroxixipa@hotmail.com>, 2018, 2019.
# Bruno Henrique <nimbusdroid@gmail.com>, 2018, 2019.
# Luciano Scilletta <lucianoscilletta@gmail.com>, 2018.
-# Julio Yagami <juliohenrique31501234@hotmail.com>, 2018, 2019.
+# Julio Yagami <juliohenrique31501234@hotmail.com>, 2018, 2019, 2022.
# Fernando Martinez <contact@fernandodev.com>, 2018.
# Marcelo <mitissa@gmail.com>, 2018, 2019.
# Walter Bolitto <wrcarval@live.com>, 2018, 2019.
@@ -95,21 +95,21 @@
# Felipe Jesus Macedo <fmacedo746@gmail.com>, 2020.
# José Paulo <jose.paulo1919@gmail.com>, 2020.
# Necco <necco@outlook.com>, 2020.
-# Marcelo Silveira Hayden <mshayden.1998@gmail.com>, 2020, 2021.
+# Marcelo Silveira Hayden <mshayden.1998@gmail.com>, 2020, 2021, 2022.
# GUILHERME SOUZA REIS DE MELO LOPES <guilhermesrml@unipam.edu.br>, 2020.
# Gabriela Araújo <Gabirin@outlook.com.br>, 2020.
# Jairo Tuboi <tuboi.jairo@gmail.com>, 2020.
# Felipe Fetter <felipetfetter@gmail.com>, 2020.
# Rafael Henrique Capati <rhcapati@gmail.com>, 2020.
-# NogardRyuu <nogardryuu@gmail.com>, 2020, 2021.
+# NogardRyuu <nogardryuu@gmail.com>, 2020, 2021, 2022.
# Elton <eltondeoliveira@outlook.com>, 2020, 2021.
-# ThiagoCTN <thiagocampostn@gmail.com>, 2020.
+# ThiagoCTN <thiagocampostn@gmail.com>, 2020, 2022.
# Alec Santos <alecsantos96@gmail.com>, 2020.
# Augusto Milão <augusto.milao01@gmail.com>, 2021, 2022.
# Gabriel Gavazzi Felix <mutcholoko32@gmail.com>, 2021.
# Lucas Dantas <lucas.lucantas38@gmail.com>, 2021.
-# Carlos Bonifacio <carlosboni.sa@gmail.com>, 2021.
-# Lucas Castro <castroclucas@gmail.com>, 2021.
+# Carlos Bonifacio <carlosboni.sa@gmail.com>, 2021, 2022.
+# Lucas Castro <castroclucas@gmail.com>, 2021, 2022.
# Ricardo Zamarrenho Carvalho Correa <ricardozcc17@gmail.com>, 2021.
# Diego dos Reis Macedo <diego_dragon97@hotmail.com>, 2021.
# Lucas E. <lukas.ed45@gmail.com>, 2021.
@@ -153,13 +153,16 @@
# Mauricio Mazur <mauricio.mazur12@gmail.com>, 2022.
# ! Zyll <emanueljunior756@gmail.com>, 2022.
# Kirrby <kirrby.gaming@gmail.com>, 2022.
+# Murilo Gama <murilovsky2030@gmail.com>, 2022.
+# Kauã Azevedo <Kazevic@pm.me>, 2022.
+# Zer0-Zer0 <dankmemerson@tutanota.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-09-27 21:37+0000\n"
-"Last-Translator: Kirrby <kirrby.gaming@gmail.com>\n"
+"PO-Revision-Date: 2022-12-10 02:13+0000\n"
+"Last-Translator: Julio Yagami <juliohenrique31501234@hotmail.com>\n"
"Language-Team: Portuguese (Brazil) <https://hosted.weblate.org/projects/"
"godot-engine/godot/pt_BR/>\n"
"Language: pt_BR\n"
@@ -167,7 +170,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.14.1\n"
+"X-Generator: Weblate 4.15-dev\n"
#: core/bind/core_bind.cpp main/main.cpp
msgid "Tablet Driver"
@@ -1293,7 +1296,7 @@ msgstr "Manipulador de Entrada"
#: editor/animation_track_editor.cpp
msgid "Out Handle"
-msgstr "Manipulador de Saída"
+msgstr "Fora do controle"
#: editor/animation_track_editor.cpp
#: editor/import/resource_importer_texture.cpp
@@ -1575,7 +1578,7 @@ msgstr "Editores"
#: editor/animation_track_editor.cpp editor/editor_settings.cpp
msgid "Confirm Insert Track"
-msgstr "Confirmar Inserção de Trilha"
+msgstr "Confirmar inserção de faixa"
#. TRANSLATORS: %s will be replaced by a phrase describing the target of track.
#: editor/animation_track_editor.cpp
@@ -1746,7 +1749,7 @@ msgstr ""
#: editor/animation_track_editor.cpp
msgid "Anim Add RESET Keys"
-msgstr "Anim Adicionar Teclas de RESET"
+msgstr "Anim adicionar teclas de RESET"
#: editor/animation_track_editor.cpp
msgid ""
@@ -3065,7 +3068,7 @@ msgstr "Em exportações de 32 bits, o PCK embutido não pode ser maior que 4GB.
#: editor/editor_export.cpp
msgid "Convert Text Resources To Binary On Export"
-msgstr "Converter Recursos de Texto para Binário na Exportação"
+msgstr "Converter recursos de texto para binário na exportação"
#: editor/editor_feature_profile.cpp
msgid "3D Editor"
@@ -4416,7 +4419,7 @@ msgstr "Sempre Limpar Output no modo Play"
#: editor/editor_node.cpp editor/editor_settings.cpp
msgid "Always Open Output On Play"
-msgstr "Sempre abrir a saída ao jogar"
+msgstr "Sempre abrir a saída ao reproduzir"
#: editor/editor_node.cpp editor/editor_settings.cpp
msgid "Always Close Output On Stop"
@@ -4424,7 +4427,7 @@ msgstr "Sempre fechar a saída ao parar"
#: editor/editor_node.cpp
msgid "Save On Focus Loss"
-msgstr "Salvar em caso de perda de foco"
+msgstr "Salvar ao perder o foco"
#: editor/editor_node.cpp editor/editor_settings.cpp
msgid "Save Each Scene On Quit"
@@ -4456,7 +4459,7 @@ msgstr "Restaurar Cenas ao Carregar"
#: editor/editor_node.cpp editor/editor_settings.cpp
msgid "Show Thumbnail On Hover"
-msgstr "Mostrar miniatura ao passar o mouse"
+msgstr "Exibir miniatura ao passar o mouse por cima"
#: editor/editor_node.cpp editor/editor_settings.cpp
msgid "Inspector"
@@ -4464,11 +4467,11 @@ msgstr "Inspetor"
#: editor/editor_node.cpp
msgid "Default Property Name Style"
-msgstr "Estilo de Nome de Propriedade Padrão"
+msgstr "Estilo de Nome Padrão de Propriedade"
#: editor/editor_node.cpp
msgid "Default Float Step"
-msgstr "Passo de ponto flutuante padrão"
+msgstr "Passo de Float padrão"
#: editor/editor_node.cpp scene/gui/tree.cpp
msgid "Disable Folding"
@@ -5359,7 +5362,7 @@ msgstr "Linguagem do Editor"
#: editor/editor_settings.cpp
msgid "Display Scale"
-msgstr "Escala de Exibição"
+msgstr "Exibir Escala"
#: editor/editor_settings.cpp
msgid "Custom Display Scale"
@@ -5367,15 +5370,15 @@ msgstr "Escala de Exibição Customizada"
#: editor/editor_settings.cpp
msgid "Main Font Size"
-msgstr "Tamanho de Fonte Principal"
+msgstr "Tamanho da Fonte Principal"
#: editor/editor_settings.cpp
msgid "Code Font Size"
-msgstr "Tamanho de Fonte (Tipo) no Código"
+msgstr "Tamanho da Fonte do Código"
#: editor/editor_settings.cpp
msgid "Font Antialiased"
-msgstr "Fonte Com Serrilhado Suavizado"
+msgstr "Fonte com Anti-aliasing"
#: editor/editor_settings.cpp
msgid "Font Hinting"
@@ -5387,27 +5390,27 @@ msgstr "Fonte Principal"
#: editor/editor_settings.cpp
msgid "Main Font Bold"
-msgstr "Fonte Principal (Negrito)"
+msgstr "Fonte Principal com Negrito"
#: editor/editor_settings.cpp
msgid "Code Font"
-msgstr "Fonte para Código"
+msgstr "Fonte do Código"
#: editor/editor_settings.cpp
msgid "Dim Editor On Dialog Popup"
-msgstr "Escurecer o Editor ao Abir Janela Popup"
+msgstr "Escurecer Editor no Pop-up de Diálogo"
#: editor/editor_settings.cpp main/main.cpp
msgid "Low Processor Mode Sleep (µsec)"
-msgstr "Tempo de Espera em Modo de Hibernação (µseg)"
+msgstr "Modo de baixo processamento tempo (µsec)"
#: editor/editor_settings.cpp
msgid "Unfocused Low Processor Mode Sleep (µsec)"
-msgstr "Tempo de Espera em Modo de Hibernação Quando Fora de Foco (µseg)"
+msgstr "Modo de baixo processamento não focado (µsec)"
#: editor/editor_settings.cpp
msgid "Separate Distraction Mode"
-msgstr "Modo \"Sem Distrações\" Desacoplado"
+msgstr "Separar Modo Distração"
#: editor/editor_settings.cpp
msgid "Automatically Open Screenshots"
@@ -5429,7 +5432,7 @@ msgstr "Predefinição"
#: editor/editor_settings.cpp
msgid "Icon And Font Color"
-msgstr "Cor da Fonte e do Ãcone"
+msgstr "Cores do ícone e da fonte"
#: editor/editor_settings.cpp
msgid "Base Color"
@@ -5505,7 +5508,7 @@ msgstr "Tamanho da Miniatura"
#: editor/editor_settings.cpp
msgid "Docks"
-msgstr "Docks"
+msgstr "Painéis"
#: editor/editor_settings.cpp
msgid "Scene Tree"
@@ -5702,7 +5705,7 @@ msgstr "Ordenar Prévia de Membros Automaticamente"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
msgid "Cursor"
-msgstr "Cursor"
+msgstr "Ponteiro"
#: editor/editor_settings.cpp
msgid "Scroll Past End Of File"
@@ -8485,7 +8488,7 @@ msgstr "Obtido:"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Failed SHA-256 hash check"
-msgstr "Falha na verificação do hash SHA-256"
+msgstr "Falha na verificação da hash SHA-256"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Asset Download Error:"
@@ -8669,8 +8672,8 @@ msgid ""
"Some mesh is invalid. Make sure the UV2 channel values are contained within "
"the [0.0,1.0] square region."
msgstr ""
-"Alguma malha é inválida. Certifique-se de que os valores do canal UV2 estão "
-"contidos na região quadrada [0.0,1.0]."
+"Algum mesh é invalido. Tenha certeza que os valores do canal UV2 estão "
+"contidos dentro da região quadrática [0.0,1.0]."
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
@@ -8811,8 +8814,8 @@ msgid ""
"Children of containers have their anchors and margins values overridden by "
"their parent."
msgstr ""
-"Filhos de contêineres têm suas posições e tamanhos sobrescritos pelos seus "
-"pais."
+"Filhos de contêineres têm seus valores de âncoras e margens substituídos "
+"pelos seus pais."
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Presets for the anchors and margins values of a Control node."
@@ -11405,11 +11408,11 @@ msgstr "Orbitar Visão Para Baixo"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Orbit View Left"
-msgstr "Orbitar Visão para a Esquerda"
+msgstr "Orbitar Visão à Esquerda"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Orbit View Right"
-msgstr "Orbitar Visão para a Direita"
+msgstr "Orbitar Visão à Direita"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Orbit View Up"
@@ -11417,7 +11420,7 @@ msgstr "Orbitar Visão para Cima"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Orbit View 180"
-msgstr "Orbitar Visão em 180"
+msgstr "Orbitar Visão 180º"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Switch Perspective/Orthogonal View"
@@ -12322,7 +12325,7 @@ msgid ""
"Toggle the control picker, allowing to visually select control types for "
"edit."
msgstr ""
-"Acionar o selecionador de controles, permitindo selecionar visualmente os "
+"Acionar o selecionador de controles, permitindo visualmente selecionar os "
"tipos de controles para edição."
#: editor/plugins/theme_editor_preview.cpp
@@ -12529,6 +12532,7 @@ msgid "Clear Transform"
msgstr "Limpar Transformação"
#: editor/plugins/tile_map_editor_plugin.cpp
+#, fuzzy
msgid "Tile Map"
msgstr "Tile Map"
@@ -12559,9 +12563,8 @@ msgstr "Pré-visualização do Preenchimento de Balde"
#: editor/plugins/tile_map_editor_plugin.cpp
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Editor Side"
-msgstr "Editor"
+msgstr "Lado do Editor"
#: editor/plugins/tile_map_editor_plugin.cpp
msgid "Display Grid"
@@ -12915,9 +12918,10 @@ msgstr "Opções de Encaixe"
#: scene/2d/path_2d.cpp scene/2d/polygon_2d.cpp scene/2d/sprite.cpp
#: scene/3d/cpu_particles.cpp scene/3d/label_3d.cpp scene/3d/path.cpp
#: scene/3d/physics_body.cpp scene/3d/soft_body.cpp scene/3d/sprite_3d.cpp
-#: 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
+#: scene/3d/visual_instance.cpp 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
msgid "Offset"
msgstr "Deslocamento"
@@ -13003,9 +13007,8 @@ msgid "Selected Collision One Way"
msgstr "Colisão em sentido único selecionada"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Selected Collision One Way Margin"
-msgstr "Modo Colisão"
+msgstr "Margem de colisão em sentido único selecionada"
#: editor/plugins/tile_set_editor_plugin.cpp
msgid "Selected Navigation"
@@ -13147,9 +13150,8 @@ msgid "Branch Name"
msgstr "Nome do Ramo"
#: editor/plugins/version_control_editor_plugin.cpp
-#, fuzzy
msgid "Remotes"
-msgstr "Remoto"
+msgstr "Remotos"
#: editor/plugins/version_control_editor_plugin.cpp
msgid "Create New Remote"
@@ -13160,7 +13162,6 @@ msgid "Remove Remote"
msgstr "Remover remoto"
#: editor/plugins/version_control_editor_plugin.cpp
-#, fuzzy
msgid "Remote Name"
msgstr "Nome Remoto"
@@ -14330,16 +14331,17 @@ msgid "Invalid project path (changed anything?)."
msgstr "Caminho de projeto inválido (mudou alguma coisa?)."
#: editor/project_manager.cpp
+#, fuzzy
msgid ""
-"Couldn't load project.godot in project path (error %d). It may be missing or "
-"corrupted."
+"Couldn't load project at '%s' (error %d). It may be missing or corrupted."
msgstr ""
"Não foi possível carregar project.godot no caminho do projeto (erro %d). Ele "
"pode estar ausente ou corrompido."
#: editor/project_manager.cpp
-msgid "Couldn't edit project.godot in project path."
-msgstr "Não foi possível editar project.godot no caminho do projeto."
+#, fuzzy
+msgid "Couldn't save project at '%s' (error %d)."
+msgstr "Não é possível abrir o projeto em '%s'."
#: editor/project_manager.cpp
msgid "Couldn't create project.godot in project path."
@@ -15561,18 +15563,16 @@ msgid "Clear Inheritance? (No Undo!)"
msgstr "Limpar Herança? (Irreversível!)"
#: editor/scene_tree_dock.cpp
-#, fuzzy
msgid "Show Scene Tree Root Selection"
-msgstr "Seleção Central"
+msgstr "Mostrar seleção da hierarquia de cenas"
#: editor/scene_tree_dock.cpp
msgid "Derive Script Globals By Name"
msgstr "Obter Globais de Script por Nome"
#: editor/scene_tree_dock.cpp
-#, fuzzy
msgid "Use Favorites Root Selection"
-msgstr "Seleção de Frame"
+msgstr "Seleção de favoritos da raíz"
#: editor/scene_tree_editor.cpp
msgid "Toggle Visible"
@@ -15874,7 +15874,7 @@ msgstr "Copiar Erro"
#: editor/script_editor_debugger.cpp
msgid "Open C++ Source on GitHub"
-msgstr "Abrir Código C++ no GitHub"
+msgstr "Abrir código C++ no GitHub"
#: editor/script_editor_debugger.cpp
msgid "Video RAM"
@@ -16158,12 +16158,10 @@ msgid "Set Occluder Sphere Position"
msgstr "Definir Posição Da Esfera Do Oclusor"
#: editor/spatial_editor_gizmos.cpp
-#, fuzzy
msgid "Set Occluder Polygon Point Position"
msgstr "Definir Posição do Ponto do Polígono Oclusor"
#: editor/spatial_editor_gizmos.cpp
-#, fuzzy
msgid "Set Occluder Hole Point Position"
msgstr "Definir Posição do Ponto do Buraco Oclusor"
@@ -16172,9 +16170,8 @@ msgid "Occluder Polygon Front"
msgstr "Frente do Polígono Oclusor"
#: editor/spatial_editor_gizmos.cpp
-#, fuzzy
msgid "Occluder Polygon Back"
-msgstr "Costas do Polígono Oclusor"
+msgstr "Traseira do Polígono Oclusor"
#: editor/spatial_editor_gizmos.cpp
msgid "Occluder Hole"
@@ -16182,7 +16179,7 @@ msgstr "Buraco Oclusor"
#: main/main.cpp
msgid "Godot Physics"
-msgstr "Godot Physics"
+msgstr "Física Godot"
#: main/main.cpp servers/physics_2d/physics_2d_server_sw.cpp
#: servers/visual/visual_server_scene.cpp
@@ -16203,8 +16200,9 @@ msgid "Multithreaded Server"
msgstr "Servidor com Multi-Thread"
#: main/main.cpp
+#, fuzzy
msgid "RID Pool Prealloc"
-msgstr ""
+msgstr "Pre-alocação de Pool RID"
#: main/main.cpp
msgid "Debugger stdout"
@@ -16371,9 +16369,8 @@ msgid "Enable Warnings"
msgstr "Habilitar Avisos"
#: main/main.cpp
-#, fuzzy
msgid "Frame Delay Msec"
-msgstr "Seleção de Frame"
+msgstr "Atraso de quadro Mseg"
#: main/main.cpp
msgid "Low Processor Mode"
@@ -16531,14 +16528,12 @@ msgid "Auto Accept Quit"
msgstr "Aceitar Sair Automaticamente"
#: main/main.cpp scene/main/scene_tree.cpp
-#, fuzzy
msgid "Quit On Go Back"
-msgstr "Sair em Voltar"
+msgstr "Sair ao Voltar"
#: main/main.cpp scene/main/viewport.cpp
-#, fuzzy
msgid "Snap Controls To Pixels"
-msgstr "Encaixar nos Lados do Nó"
+msgstr "Encaixar Nós de Controle nos pixels"
#: main/main.cpp
msgid "Dynamic Fonts"
@@ -16660,9 +16655,8 @@ msgid "Path Node"
msgstr "Caminho do Nó"
#: modules/csg/csg_shape.cpp
-#, fuzzy
msgid "Path Interval Type"
-msgstr "Criar Vertex Interno"
+msgstr "Tipo de Intervalo de Caminho"
#: modules/csg/csg_shape.cpp
msgid "Path Interval"
@@ -16677,14 +16671,13 @@ msgid "Path Rotation"
msgstr "Rotação do Caminho"
#: modules/csg/csg_shape.cpp
-#, fuzzy
msgid "Path Local"
-msgstr "Tornar Local"
+msgstr "Caminho Local"
#: modules/csg/csg_shape.cpp
#, fuzzy
msgid "Path Continuous U"
-msgstr "Contínuo"
+msgstr "Caminho Contínuo"
#: modules/csg/csg_shape.cpp
msgid "Path U Distance"
@@ -16917,9 +16910,8 @@ msgid "Export GLTF..."
msgstr "Exportar GLTF..."
#: modules/gltf/gltf_accessor.cpp
-#, fuzzy
msgid "Buffer View"
-msgstr "Visão Traseira"
+msgstr "Visão de Buffer"
#: modules/gltf/gltf_accessor.cpp modules/gltf/gltf_buffer_view.cpp
msgid "Byte Offset"
@@ -16946,9 +16938,8 @@ msgid "Max"
msgstr "Max"
#: modules/gltf/gltf_accessor.cpp
-#, fuzzy
msgid "Sparse Count"
-msgstr "Instância"
+msgstr "Contagem Escassa"
#: modules/gltf/gltf_accessor.cpp
msgid "Sparse Indices Buffer View"
@@ -16971,14 +16962,12 @@ msgid "Sparse Values Byte Offset"
msgstr ""
#: modules/gltf/gltf_buffer_view.cpp
-#, fuzzy
msgid "Buffer"
-msgstr "Visão Traseira"
+msgstr "Buffer"
#: modules/gltf/gltf_buffer_view.cpp
-#, fuzzy
msgid "Byte Length"
-msgstr "Tema Padrão"
+msgstr "Largura do byte"
#: modules/gltf/gltf_buffer_view.cpp
msgid "Byte Stride"
@@ -16994,12 +16983,11 @@ msgstr "Tamanho do FOV"
#: modules/gltf/gltf_camera.cpp
msgid "Zfar"
-msgstr ""
+msgstr "Z longe"
#: modules/gltf/gltf_camera.cpp
-#, fuzzy
msgid "Znear"
-msgstr "Linear"
+msgstr "Z perto"
#: 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
@@ -17030,9 +17018,8 @@ msgid "Outer Cone Angle"
msgstr "Ângulo externo do cone"
#: modules/gltf/gltf_mesh.cpp
-#, fuzzy
msgid "Blend Weights"
-msgstr "Faça mapas de luz"
+msgstr "Peso da mesclagem"
#: modules/gltf/gltf_mesh.cpp
msgid "Instance Materials"
@@ -17043,13 +17030,12 @@ msgid "Parent"
msgstr "Pai"
#: modules/gltf/gltf_node.cpp
-#, fuzzy
msgid "Xform"
-msgstr "Plataforma"
+msgstr ""
#: modules/gltf/gltf_node.cpp scene/3d/mesh_instance.cpp
msgid "Skin"
-msgstr "Skin"
+msgstr ""
#: modules/gltf/gltf_node.cpp scene/3d/spatial.cpp
msgid "Translation"
@@ -17085,12 +17071,11 @@ msgstr "Pontos Originais"
#: modules/gltf/gltf_skin.cpp
msgid "Inverse Binds"
-msgstr ""
+msgstr "Designações invertidas"
#: modules/gltf/gltf_skin.cpp
-#, fuzzy
msgid "Non Joints"
-msgstr "Mover Junta"
+msgstr "Não-Juntas"
#: modules/gltf/gltf_skin.cpp
msgid "Joint I To Bone I"
@@ -17102,15 +17087,15 @@ msgstr "Junta I ao Nome"
#: modules/gltf/gltf_skin.cpp
msgid "Godot Skin"
-msgstr ""
+msgstr "Skin Godot"
#: modules/gltf/gltf_spec_gloss.cpp
msgid "Diffuse Img"
-msgstr "Difusa Img"
+msgstr "Imagem Difusa"
#: modules/gltf/gltf_spec_gloss.cpp
msgid "Diffuse Factor"
-msgstr "Difusa Fator"
+msgstr "Fator de Difusão"
#: modules/gltf/gltf_spec_gloss.cpp
msgid "Gloss Factor"
@@ -17126,30 +17111,27 @@ msgstr ""
#: modules/gltf/gltf_state.cpp
msgid "Json"
-msgstr "Json"
+msgstr ""
#: modules/gltf/gltf_state.cpp
msgid "Major Version"
msgstr "Versão Importante"
#: modules/gltf/gltf_state.cpp
-#, fuzzy
msgid "Minor Version"
-msgstr "Versão"
+msgstr "Versão Minoritária"
#: modules/gltf/gltf_state.cpp
-#, fuzzy
msgid "GLB Data"
-msgstr "Com Dados"
+msgstr "Dados do GLB"
#: modules/gltf/gltf_state.cpp
msgid "Use Named Skin Binds"
msgstr ""
#: modules/gltf/gltf_state.cpp
-#, fuzzy
msgid "Buffer Views"
-msgstr "Visão Traseira"
+msgstr "Visão Buffer"
#: modules/gltf/gltf_state.cpp
msgid "Accessors"
@@ -17197,9 +17179,8 @@ msgid "Animations"
msgstr "Animações"
#: modules/gltf/gltf_texture.cpp
-#, fuzzy
msgid "Src Image"
-msgstr "Mostrar Ossos"
+msgstr "Imagem fonte"
#: modules/gridmap/grid_map.cpp
msgid "Mesh Library"
@@ -17210,18 +17191,16 @@ msgid "Physics Material"
msgstr "Material de Física"
#: modules/gridmap/grid_map.cpp scene/3d/visual_instance.cpp
-#, fuzzy
msgid "Use In Baked Light"
-msgstr "Faça mapas de luz"
+msgstr "Usar no mapa de luz"
#: modules/gridmap/grid_map.cpp scene/2d/tile_map.cpp
msgid "Cell"
msgstr "Célula"
#: modules/gridmap/grid_map.cpp
-#, fuzzy
msgid "Octant Size"
-msgstr "Visão Frontal"
+msgstr "Tamanho Octante"
#: modules/gridmap/grid_map.cpp
msgid "Center X"
@@ -17382,7 +17361,7 @@ msgstr "Atribua um recurso MeshLibrary a este GridMap para usar seus meshes."
#: modules/lightmapper_cpu/lightmapper_cpu.cpp
msgid "Begin Bake"
-msgstr "Iniciar bake"
+msgstr "Iniciar Bake"
#: modules/lightmapper_cpu/lightmapper_cpu.cpp
msgid "Preparing data structures"
@@ -17394,7 +17373,7 @@ msgstr "Gerar buffers"
#: modules/lightmapper_cpu/lightmapper_cpu.cpp
msgid "Direct lighting"
-msgstr "Iluminação direta"
+msgstr "Iluminação Direta"
#: modules/lightmapper_cpu/lightmapper_cpu.cpp
msgid "Indirect lighting"
@@ -17406,7 +17385,7 @@ msgstr "Pós-processamento"
#: modules/lightmapper_cpu/lightmapper_cpu.cpp
msgid "Plotting lightmaps"
-msgstr "Traçando mapas de luz"
+msgstr "Planejando Luzes"
#: modules/lightmapper_cpu/register_types.cpp
msgid "CPU Lightmapper"
@@ -17448,9 +17427,8 @@ msgid "Display Width"
msgstr "Largura de Tela"
#: modules/mobile_vr/mobile_vr_interface.cpp
-#, fuzzy
msgid "Display To Lens"
-msgstr "Exibir Sem Sombreamento"
+msgstr "Exibir para as Lentes"
#: modules/mobile_vr/mobile_vr_interface.cpp
msgid "Oversample"
@@ -17477,9 +17455,8 @@ msgid "Auto Update Project"
msgstr "Atualizar Projeto Automaticamente"
#: modules/mono/godotsharp_dirs.cpp
-#, fuzzy
msgid "Assembly Name"
-msgstr "Nome de Exibição"
+msgstr "Nome de Montagem"
#: modules/mono/godotsharp_dirs.cpp
msgid "Solution Directory"
@@ -17569,9 +17546,8 @@ msgid "As Normal Map"
msgstr "Como Mapa Normal"
#: modules/opensimplex/noise_texture.cpp
-#, fuzzy
msgid "Bump Strength"
-msgstr "Força da colisão"
+msgstr "Força do Bump"
#: modules/opensimplex/noise_texture.cpp
msgid "Noise"
@@ -17611,7 +17587,7 @@ msgstr "Strings"
#: modules/upnp/upnp.cpp
msgid "Discover Multicast If"
-msgstr ""
+msgstr "Descobrir if Multicast"
#: modules/upnp/upnp.cpp
msgid "Discover Local Port"
@@ -17622,9 +17598,8 @@ msgid "Discover IPv6"
msgstr "Descobrir IPv6"
#: modules/upnp/upnp_device.cpp
-#, fuzzy
msgid "Description URL"
-msgstr "Descrição"
+msgstr "URL Descritiva"
#: modules/upnp/upnp_device.cpp
msgid "Service Type"
@@ -18014,9 +17989,8 @@ msgid "Return"
msgstr "Retornar"
#: modules/visual_script/visual_script_flow_control.cpp
-#, fuzzy
msgid "Return Enabled"
-msgstr "Executável"
+msgstr "Retorno Ativado"
#: modules/visual_script/visual_script_flow_control.cpp
msgid "Return Type"
@@ -18045,7 +18019,7 @@ msgstr "Iterador"
#: modules/visual_script/visual_script_flow_control.cpp
msgid "for (elem) in (input):"
-msgstr "para (elem) em (input):"
+msgstr ""
#: modules/visual_script/visual_script_flow_control.cpp
msgid "Input type not iterable:"
@@ -18097,9 +18071,8 @@ msgid "On %s"
msgstr "Em %s"
#: modules/visual_script/visual_script_func_nodes.cpp
-#, fuzzy
msgid "On Self"
-msgstr "Self"
+msgstr "Em sí mesmo"
#: modules/visual_script/visual_script_func_nodes.cpp
#: modules/visual_script/visual_script_yield_nodes.cpp
@@ -18142,23 +18115,20 @@ msgid "Divide %s"
msgstr "Dividir %s"
#: modules/visual_script/visual_script_func_nodes.cpp
-#, fuzzy
msgid "Mod %s"
-msgstr "Mod %s"
+msgstr "[code]Mod %s[/code]"
#: modules/visual_script/visual_script_func_nodes.cpp
-#, fuzzy
msgid "ShiftLeft %s"
-msgstr "ShiftLeft %s"
+msgstr ""
#: modules/visual_script/visual_script_func_nodes.cpp
msgid "ShiftRight %s"
msgstr ""
#: modules/visual_script/visual_script_func_nodes.cpp
-#, fuzzy
msgid "BitAnd %s"
-msgstr "BitAnd %s"
+msgstr ""
#: modules/visual_script/visual_script_func_nodes.cpp
msgid "BitOr %s"
@@ -18169,12 +18139,10 @@ msgid "BitXor %s"
msgstr ""
#: modules/visual_script/visual_script_func_nodes.cpp
-#, fuzzy
msgid "Set Mode"
-msgstr "Modo de Seleção"
+msgstr "Modo de Definição"
#: modules/visual_script/visual_script_func_nodes.cpp
-#, fuzzy
msgid "Assign Op"
msgstr "Atribuir Op"
@@ -18282,9 +18250,8 @@ msgid "Get Self"
msgstr "Obter Sí Mesmo"
#: modules/visual_script/visual_script_nodes.cpp
-#, fuzzy
msgid "CustomNode"
-msgstr "CustomNode"
+msgstr ""
#: modules/visual_script/visual_script_nodes.cpp
msgid "Custom node has no _step() method, can't process graph."
@@ -18301,9 +18268,8 @@ msgstr ""
"string (erro)."
#: modules/visual_script/visual_script_nodes.cpp
-#, fuzzy
msgid "SubCall"
-msgstr "SubCall"
+msgstr ""
#: modules/visual_script/visual_script_nodes.cpp scene/gui/graph_node.cpp
msgid "Title"
@@ -18335,11 +18301,11 @@ msgstr "Buscar VisualScript"
#: modules/visual_script/visual_script_yield_nodes.cpp
msgid "Yield"
-msgstr "Yield"
+msgstr ""
#: modules/visual_script/visual_script_yield_nodes.cpp
msgid "Wait"
-msgstr "Esperar"
+msgstr ""
#: modules/visual_script/visual_script_yield_nodes.cpp
msgid "Next Frame"
@@ -18358,33 +18324,28 @@ msgid "Wait Time"
msgstr "Tempo de Espera"
#: modules/visual_script/visual_script_yield_nodes.cpp
-#, fuzzy
msgid "WaitSignal"
-msgstr "WaitSignal"
+msgstr ""
#: modules/visual_script/visual_script_yield_nodes.cpp
-#, fuzzy
msgid "WaitNodeSignal"
-msgstr "WaitNodeSignal"
+msgstr ""
#: modules/visual_script/visual_script_yield_nodes.cpp
-#, fuzzy
msgid "WaitInstanceSignal"
-msgstr "WaitInstanceSignal"
+msgstr ""
#: modules/webrtc/webrtc_data_channel.cpp
-#, fuzzy
msgid "Write Mode"
-msgstr "Modo Prioridade"
+msgstr "Modo de Escrita"
#: modules/webrtc/webrtc_data_channel.h
msgid "WebRTC"
-msgstr "WebRTC"
+msgstr ""
#: modules/webrtc/webrtc_data_channel.h
-#, fuzzy
msgid "Max Channel In Buffer (KB)"
-msgstr "Tamanho do buffer do índice do polígono da tela (KB)"
+msgstr "Canal Máximo no Buffer (KB)"
#: modules/websocket/websocket_client.cpp
msgid "Verify SSL"
@@ -18439,9 +18400,8 @@ msgid "Handshake Timeout"
msgstr "Tempo de Handshake Esgotado"
#: modules/webxr/webxr_interface.cpp
-#, fuzzy
msgid "Session Mode"
-msgstr "Modo Região"
+msgstr "Modo Sessão"
#: modules/webxr/webxr_interface.cpp
msgid "Required Features"
@@ -18452,12 +18412,10 @@ msgid "Optional Features"
msgstr "Funcionalidades Opcionais"
#: modules/webxr/webxr_interface.cpp
-#, fuzzy
msgid "Requested Reference Space Types"
msgstr "Tipos de Espaço de Referência Solicitados"
#: modules/webxr/webxr_interface.cpp
-#, fuzzy
msgid "Reference Space Type"
msgstr "Tipo de Espaço de Referência"
@@ -18466,23 +18424,20 @@ msgid "Visibility State"
msgstr "Estado de Visibilidade"
#: modules/webxr/webxr_interface.cpp
-#, fuzzy
msgid "Bounds Geometry"
-msgstr "Tentar Novamente"
+msgstr "Limita a Geometria"
#: modules/webxr/webxr_interface.cpp
-#, fuzzy
msgid "XR Standard Mapping"
-msgstr "Encaixe inteligente"
+msgstr "Mapeamento XR Padrão"
#: platform/android/export/export.cpp
msgid "Android SDK Path"
msgstr "Caminho para SDK Android"
#: platform/android/export/export.cpp
-#, fuzzy
msgid "Debug Keystore"
-msgstr "Depurador"
+msgstr "Depurar Keystore"
#: platform/android/export/export.cpp
msgid "Debug Keystore User"
@@ -18493,7 +18448,6 @@ msgid "Debug Keystore Pass"
msgstr ""
#: platform/android/export/export.cpp
-#, fuzzy
msgid "Force System User"
msgstr "Forçar Usuário do Sistema"
@@ -18545,14 +18499,12 @@ 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 Diretório de Usuário Personalizado"
+msgstr "Build Personalizada"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Use Custom Build"
-msgstr "Usar Diretório de Usuário Personalizado"
+msgstr "Usar Build Personalizada"
#: platform/android/export/export_plugin.cpp
msgid "Export Format"
@@ -18571,29 +18523,24 @@ msgid "Architectures"
msgstr "Arquiteturas"
#: 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 "Depurar Usuário"
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
-#, fuzzy
msgid "Debug Password"
-msgstr "Senha"
+msgstr "Depurar Senha"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Release User"
-msgstr "Lançamento"
+msgstr "Liberar Usuário"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Release Password"
-msgstr "Senha"
+msgstr "Liberar Senha"
#: platform/android/export/export_plugin.cpp
msgid "One Click Deploy"
@@ -18636,9 +18583,8 @@ msgid "Graphics"
msgstr "Gráficos"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "OpenGL Debug"
-msgstr "Abrir"
+msgstr "Depurar OpenGL"
#: platform/android/export/export_plugin.cpp
msgid "XR Features"
@@ -18651,7 +18597,7 @@ msgstr "Modo XR"
#: platform/android/export/export_plugin.cpp
#, fuzzy
msgid "Hand Tracking"
-msgstr "Empacotando"
+msgstr "Detecção de Mãos"
#: platform/android/export/export_plugin.cpp
msgid "Hand Tracking Frequency"
@@ -18666,24 +18612,20 @@ msgid "Immersive Mode"
msgstr "Modo Imersivo"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Support Small"
-msgstr "Suporte"
+msgstr "Suporte Pequeno"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Support Normal"
-msgstr "Suporte"
+msgstr "Suporte Normal"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Support Large"
-msgstr "Suporte"
+msgstr "Suporte Grande"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Support Xlarge"
-msgstr "Suporte"
+msgstr "Suporte Extra-grande"
#: platform/android/export/export_plugin.cpp
msgid "User Data Backup"
@@ -18702,9 +18644,8 @@ msgid "Extra Args"
msgstr "Argumentos Extra"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "APK Expansion"
-msgstr "Expressão"
+msgstr "Expansão APK"
#: platform/android/export/export_plugin.cpp
msgid "Salt"
@@ -18796,7 +18737,7 @@ msgstr "Um caminho Android SDK é necessário nas Configurações do Editor."
#: platform/android/export/export_plugin.cpp
msgid "Invalid Android SDK path in Editor Settings."
-msgstr "Caminho do Android SDK está inválido nas Configurações do Editor."
+msgstr "Caminho do Android SDK inválido nas Configurações do Editor."
#: platform/android/export/export_plugin.cpp
msgid "Missing 'platform-tools' directory!"
@@ -18815,7 +18756,7 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid "Missing 'build-tools' directory!"
-msgstr "Diretório 'build-tools' está faltando!"
+msgstr "Diretório 'build-tools' ausente!"
#: platform/android/export/export_plugin.cpp
msgid "Unable to find Android SDK build-tools' apksigner command."
@@ -18852,18 +18793,16 @@ msgstr ""
"utilizar plugins."
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid ""
"\"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\"."
+"\"Hand Tracking\" só é válido quando o \"XR Mode\" é \"Oculus Mobile VrApi\" "
+"ou \"OpenXR\"."
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "\"Passthrough\" is only valid when \"XR Mode\" is \"OpenXR\"."
-msgstr ""
-"\"Passthrough\" só é válido quando o \"Xr Mode\" é \"Oculus Mobile VR\"."
+msgstr "\"Passthrough\" só é válido quando o \"XR Mode\" é \"OpenXR\"."
#: platform/android/export/export_plugin.cpp
msgid "\"Export AAB\" is only valid when \"Use Custom Build\" is enabled."
@@ -18872,12 +18811,11 @@ msgstr ""
"habilitado."
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid ""
"\"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."
+"\"Min SDK\" só pode ser substituído 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."
@@ -18894,12 +18832,11 @@ msgstr ""
"biblioteca Godot."
#: 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."
+"\"Target SDK\" só pode ser substituído quando \"Usar Compilação "
+"Customizada\" está habilitado."
#: platform/android/export/export_plugin.cpp
msgid ""
@@ -18917,11 +18854,10 @@ msgstr ""
"não foi testado e pode ser instável."
#: 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\"."
+"Versão do \"Target SDK\" precisa ser igual ou maior que a versão do \"Min "
+"SDK\"."
#: platform/android/export/export_plugin.cpp platform/osx/export/export.cpp
#: platform/windows/export/export.cpp
@@ -18971,11 +18907,12 @@ msgstr "Exportando para Android"
#: platform/android/export/export_plugin.cpp
msgid "Invalid filename! Android App Bundle requires the *.aab extension."
-msgstr "Nome de arquivo inválido! Android App Bundle requer a extensão *.aab."
+msgstr ""
+"Nome de arquivo inválido! O Android App Bundle requer a extensão *.aab."
#: platform/android/export/export_plugin.cpp
msgid "APK Expansion not compatible with Android App Bundle."
-msgstr "A expansão APK não é compatível com o Android App Bundle."
+msgstr "Expansão do APK não é compatível com Android App Bundle."
#: platform/android/export/export_plugin.cpp
msgid "Invalid filename! Android APK requires the *.apk extension."
@@ -19091,7 +19028,6 @@ msgid "The character '%s' is not allowed in Identifier."
msgstr "O caractere '%s' não é permitido no identificador."
#: platform/iphone/export/export.cpp
-#, fuzzy
msgid "Landscape Launch Screens"
msgstr "Telas de Inicialização de Paisagem"
@@ -19101,15 +19037,15 @@ msgstr "IPhone 2436 X 1125"
#: platform/iphone/export/export.cpp
msgid "iPhone 2208 X 1242"
-msgstr "iPhone 2208 X 1242"
+msgstr ""
#: platform/iphone/export/export.cpp
msgid "iPad 1024 X 768"
-msgstr "iPad 1024 X 768"
+msgstr ""
#: platform/iphone/export/export.cpp
msgid "iPad 2048 X 1536"
-msgstr "iPad 2048 X 1536"
+msgstr ""
#: platform/iphone/export/export.cpp
msgid "Portrait Launch Screens"
@@ -19117,31 +19053,31 @@ msgstr ""
#: platform/iphone/export/export.cpp
msgid "iPhone 640 X 960"
-msgstr "iPhone 640 X 960"
+msgstr ""
#: platform/iphone/export/export.cpp
msgid "iPhone 640 X 1136"
-msgstr "iPhone 640 X 1136"
+msgstr ""
#: platform/iphone/export/export.cpp
msgid "iPhone 750 X 1334"
-msgstr "iPhone 750 X 1334"
+msgstr ""
#: platform/iphone/export/export.cpp
msgid "iPhone 1125 X 2436"
-msgstr "iPhone 1125 X 2436"
+msgstr ""
#: platform/iphone/export/export.cpp
msgid "iPad 768 X 1024"
-msgstr "iPad 768 X 1024"
+msgstr ""
#: platform/iphone/export/export.cpp
msgid "iPad 1536 X 2048"
-msgstr "iPad 1536 X 2048"
+msgstr ""
#: platform/iphone/export/export.cpp
msgid "iPhone 1242 X 2208"
-msgstr "iPhone 1242 X 2208"
+msgstr ""
#: platform/iphone/export/export.cpp
msgid "App Store Team ID"
@@ -19240,23 +19176,23 @@ msgstr "Descrições da Propriedade"
#: platform/iphone/export/export.cpp
msgid "iPhone 120 X 120"
-msgstr "iPhone 120 X 120"
+msgstr ""
#: platform/iphone/export/export.cpp
msgid "iPhone 180 X 180"
-msgstr "iPhone 180 X 180"
+msgstr ""
#: platform/iphone/export/export.cpp
msgid "iPad 76 X 76"
-msgstr "iPad 76 X 76"
+msgstr ""
#: platform/iphone/export/export.cpp
msgid "iPad 152 X 152"
-msgstr "iPad 152 X 152"
+msgstr ""
#: platform/iphone/export/export.cpp
msgid "iPad 167 X 167"
-msgstr "iPad 167 X 167"
+msgstr ""
#: platform/iphone/export/export.cpp
msgid "App Store 1024 X 1024"
@@ -19367,9 +19303,8 @@ msgid "Export Type"
msgstr "Tipo de Exportação"
#: platform/javascript/export/export.cpp
-#, fuzzy
msgid "VRAM Texture Compression"
-msgstr "Expressão"
+msgstr "Compressão de Texturas na VRAM"
#: platform/javascript/export/export.cpp
msgid "For Desktop"
@@ -19410,7 +19345,7 @@ msgstr "Teclado Virtual Experimental"
#: platform/javascript/export/export.cpp
msgid "Progressive Web App"
-msgstr "Progressive Web App"
+msgstr "Aplicativo Web Progressivo"
#: platform/javascript/export/export.cpp
msgid "Offline Page"
@@ -19521,9 +19456,8 @@ msgid "Invalid executable file."
msgstr "Arquivo executável inválido."
#: platform/osx/export/codesign.cpp
-#, fuzzy
msgid "Can't resize signature load command."
-msgstr "Não é possível redimensionar o comando de carregamento da assinatura."
+msgstr "Não é possível redimensionar o comando de carregamento de assinatura."
#: platform/osx/export/codesign.cpp
msgid "Failed to create fat binary."
@@ -20203,7 +20137,6 @@ msgid "Failed to rename temporary file \"%s\"."
msgstr "Falha ao renomear arquivo temporário \"%s\"."
#: platform/windows/export/export.cpp
-#, fuzzy
msgid "Identity Type"
msgstr "Tipo de Identidade"
@@ -20337,9 +20270,8 @@ msgid "Executable file header corrupted."
msgstr ""
#: platform/windows/export/export.cpp platform/x11/export/export.cpp
-#, fuzzy
msgid "Executable \"pck\" section not found."
-msgstr "Executável seção \"pck\" não encontrado."
+msgstr "Seção executável \"pck\" não encontrada."
#: platform/windows/export/export.cpp
msgid "Windows"
@@ -20347,7 +20279,7 @@ msgstr "Windows"
#: platform/windows/export/export.cpp
msgid "Rcedit"
-msgstr "Rcedit"
+msgstr ""
#: platform/windows/export/export.cpp
msgid "Osslsigncode"
@@ -20355,7 +20287,7 @@ msgstr ""
#: platform/windows/export/export.cpp
msgid "Wine"
-msgstr "Wine"
+msgstr "Vinho"
#: platform/x11/export/export.cpp
msgid "32-bit executables cannot have embedded data >= 4 GiB."
@@ -20636,9 +20568,8 @@ msgid "Visible"
msgstr "Visível"
#: scene/2d/canvas_item.cpp
-#, fuzzy
msgid "Self Modulate"
-msgstr "Popular"
+msgstr "Auto Modular"
#: scene/2d/canvas_item.cpp
msgid "Show Behind Parent"
@@ -21088,9 +21019,8 @@ msgstr ""
"Uma textura com a forma da luz deve ser fornecida na propriedade \"textura\"."
#: scene/2d/light_2d.cpp scene/3d/light.cpp scene/gui/reference_rect.cpp
-#, fuzzy
msgid "Editor Only"
-msgstr "Editor"
+msgstr "Somente Editor"
#: scene/2d/light_2d.cpp
msgid "Texture Scale"
@@ -21579,9 +21509,8 @@ msgid "Sync To Physics"
msgstr "Sincronizar com a Física"
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
-#, fuzzy
msgid "Moving Platform"
-msgstr "Movendo saída"
+msgstr "Plataforma Móvel"
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
msgid "Apply Velocity On Leave"
@@ -21980,7 +21909,7 @@ msgstr "Gerando captura"
#: scene/3d/baked_lightmap.cpp
msgid "Saving lightmaps"
-msgstr "Salvando mapas de luz"
+msgstr "Salvando lightmaps"
#: scene/3d/baked_lightmap.cpp
msgid "Done"
@@ -22416,9 +22345,8 @@ msgid "Bias Split Scale"
msgstr "Usar Encaixe Escalar"
#: scene/3d/light.cpp
-#, fuzzy
msgid "Depth Range"
-msgstr "Profundidade"
+msgstr "Alcance de Profundidade"
#: scene/3d/light.cpp
msgid "Omni"
@@ -22604,19 +22532,16 @@ msgid "Angular Z"
msgstr "Z Angular"
#: scene/3d/physics_body.cpp
-#, fuzzy
msgid "Motion X"
-msgstr "Ação"
+msgstr "Movimento X"
#: scene/3d/physics_body.cpp
-#, fuzzy
msgid "Motion Y"
-msgstr "Ação"
+msgstr "Movimento Y"
#: scene/3d/physics_body.cpp
-#, fuzzy
msgid "Motion Z"
-msgstr "Ação"
+msgstr "Movimento Z"
#: scene/3d/physics_body.cpp
#, fuzzy
@@ -23187,9 +23112,8 @@ msgid "Overlap Warning Threshold"
msgstr ""
#: scene/3d/room_manager.cpp
-#, fuzzy
msgid "Preview Camera"
-msgstr "Visualização"
+msgstr "Visualizar Câmera"
#: scene/3d/room_manager.cpp
msgid "Portal Depth Limit"
@@ -23441,6 +23365,16 @@ msgstr "Erro"
msgid "AABB"
msgstr "AABB"
+#: scene/3d/visual_instance.cpp
+#, fuzzy
+msgid "Sorting"
+msgstr "Ordenar"
+
+#: scene/3d/visual_instance.cpp
+#, fuzzy
+msgid "Use AABB Center"
+msgstr "Utilizar Ambient"
+
#: scene/3d/visual_instance.cpp scene/resources/navigation_mesh.cpp
msgid "Geometry"
msgstr "Geometria"
@@ -23895,7 +23829,7 @@ msgid ""
"children placement behavior.\n"
"If you don't intend to add a script, use a plain Control node instead."
msgstr ""
-"O contêiner por si só não possui propósito algum, a menos que um script "
+"O contêiner por si só não tem nenhum propósito, a menos que um script "
"configure seu comportamento de posicionamento dos filhos.\n"
"Se você não pretende adicionar um script, use um nó de Controle simples."
@@ -24071,7 +24005,7 @@ msgstr "Mini-Mapa"
#: scene/gui/graph_edit.cpp
msgid "Enable grid minimap."
-msgstr "Ativar minimap em grade."
+msgstr "Ativar o minimapa de grade."
#: scene/gui/graph_node.cpp
#, fuzzy
@@ -24407,7 +24341,7 @@ msgstr "Caractere"
#: scene/gui/rich_text_label.cpp
msgid "BBCode"
-msgstr "BBCode"
+msgstr ""
#: scene/gui/rich_text_label.cpp
msgid "Meta Underlined"
@@ -25345,9 +25279,8 @@ msgid "Minimum Spaces"
msgstr "Cena Principal"
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "BG"
-msgstr "Plano de Fundo"
+msgstr ""
#: scene/resources/default_theme/default_theme.cpp
msgid "FG"
@@ -25726,9 +25659,8 @@ msgid "Tab FG"
msgstr "Guia 1"
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Tab BG"
-msgstr "Plano de Fundo da Aba"
+msgstr "BG da Aba"
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
@@ -26184,7 +26116,7 @@ msgstr "Depuração do Canal UV"
#: scene/resources/environment.cpp
msgid "Blur"
-msgstr "Blur"
+msgstr ""
#: scene/resources/environment.cpp
msgid "Edge Sharpness"
@@ -26869,7 +26801,7 @@ msgstr "Tamanho da Radiância"
#: scene/resources/sky.cpp
msgid "Panorama"
-msgstr "Panorama"
+msgstr ""
#: scene/resources/sky.cpp
#, fuzzy
@@ -26937,7 +26869,7 @@ msgstr ""
#: scene/resources/style_box.cpp
msgid "Anti Aliasing"
-msgstr "Anti Aliasing"
+msgstr "Anti Serrilhamento"
#: scene/resources/style_box.cpp
msgid "Grow Begin"
@@ -27162,7 +27094,7 @@ msgstr "Margem de Ligação da Borda"
#: scene/resources/world_2d.cpp
msgid "Canvas"
-msgstr "Canvas"
+msgstr "Tela"
#: servers/arvr/arvr_interface.cpp
msgid "Is Primary"
@@ -27244,7 +27176,7 @@ msgstr "Nível dB"
#: servers/audio/effects/audio_effect_delay.cpp
#: servers/audio/effects/audio_effect_panner.cpp
msgid "Pan"
-msgstr "Panoramizar"
+msgstr ""
#: servers/audio/effects/audio_effect_compressor.cpp
#: servers/audio/effects/audio_effect_filter.cpp
@@ -27298,7 +27230,7 @@ msgstr ""
#: servers/audio/effects/audio_effect_distortion.cpp
msgid "Drive"
-msgstr "Drive"
+msgstr ""
#: servers/audio/effects/audio_effect_distortion.cpp
#, fuzzy
@@ -27349,7 +27281,7 @@ msgstr "Pré Atraso"
#: servers/audio/effects/audio_effect_reverb.cpp
msgid "Msec"
-msgstr "Msec"
+msgstr ""
#: servers/audio/effects/audio_effect_reverb.cpp
msgid "Room Size"
@@ -27607,9 +27539,8 @@ msgid "Lossless Compression"
msgstr "Compressão Sem Perda"
#: servers/visual_server.cpp
-#, fuzzy
msgid "Force PNG"
-msgstr "Forçar Push"
+msgstr "Forçar PNG"
#: servers/visual_server.cpp
msgid "WebP Compression Level"
@@ -27731,9 +27662,8 @@ msgid "Ninepatch Mode"
msgstr "Modo de Interpolação"
#: servers/visual_server.cpp
-#, fuzzy
msgid "OpenGL"
-msgstr "Abrir"
+msgstr "abrir"
#: servers/visual_server.cpp
msgid "Batching Send Null"
@@ -27795,7 +27725,7 @@ msgstr ""
#: servers/visual_server.cpp
msgid "Flash Batching"
-msgstr ""
+msgstr "Loteamento de Flashes"
#: servers/visual_server.cpp
#, fuzzy
@@ -27812,7 +27742,7 @@ msgstr "Compatibilidade"
#: servers/visual_server.cpp
msgid "Disable Half Float"
-msgstr ""
+msgstr "Desativar Meia Float"
#: servers/visual_server.cpp
#, fuzzy
@@ -27839,7 +27769,7 @@ msgstr "Usar Encaixe Escalar"
#: servers/visual_server.cpp
msgid "PVS Logging"
-msgstr ""
+msgstr "Registro PVS"
#: servers/visual_server.cpp
#, fuzzy
@@ -27866,9 +27796,8 @@ msgid "Max Active Spheres"
msgstr "Máximo de Esferas Ativas"
#: servers/visual_server.cpp
-#, fuzzy
msgid "Max Active Polygons"
-msgstr "Mover Polígono"
+msgstr "Máximo de Polígonos Ativos"
#: servers/visual_server.cpp
#, fuzzy
@@ -27880,8 +27809,9 @@ msgid "Max Simultaneous Compiles"
msgstr "Compilações Simultâneas Máximas"
#: servers/visual_server.cpp
+#, fuzzy
msgid "Log Active Async Compiles Count"
-msgstr ""
+msgstr "Registro do Número de Compilações Assíncronas Ativas"
#: servers/visual_server.cpp
msgid "Shader Cache Size (MB)"
diff --git a/editor/translations/ro.po b/editor/translations/ro.po
index e01815b513..906d6aee71 100644
--- a/editor/translations/ro.po
+++ b/editor/translations/ro.po
@@ -19,13 +19,14 @@
# N3mEee <n3mebusiness@gmail.com>, 2021.
# Psynt <nichita@cadvegra.com>, 2022.
# Ilie Adrian Avramescu <himark1977@protonmail.com>, 2022.
+# Andres Ene <grassiscomplex420@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-09-27 21:37+0000\n"
-"Last-Translator: Ilie Adrian Avramescu <himark1977@protonmail.com>\n"
+"PO-Revision-Date: 2022-11-22 20:37+0000\n"
+"Last-Translator: Andres Ene <grassiscomplex420@gmail.com>\n"
"Language-Team: Romanian <https://hosted.weblate.org/projects/godot-engine/"
"godot/ro/>\n"
"Language: ro\n"
@@ -34,7 +35,7 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=n==1 ? 0 : (n==0 || (n%100 > 0 && n%100 < "
"20)) ? 1 : 2;\n"
-"X-Generator: Weblate 4.14.1\n"
+"X-Generator: Weblate 4.15-dev\n"
#: core/bind/core_bind.cpp main/main.cpp
msgid "Tablet Driver"
@@ -200,9 +201,8 @@ msgid "Limits"
msgstr "Limite"
#: core/command_queue_mt.cpp
-#, fuzzy
msgid "Command Queue"
-msgstr "Trage: Rotire"
+msgstr "Lista de comenzi"
#: core/command_queue_mt.cpp
msgid "Multithreading Queue Size (KB)"
@@ -313,9 +313,8 @@ msgid "Blocking Handshake"
msgstr "Blocare Handshake"
#: core/io/udp_server.cpp
-#, fuzzy
msgid "Max Pending Connections"
-msgstr "Modifică Conexiunea:"
+msgstr "Număr maxim de conexiuni în așteptare"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
@@ -544,9 +543,8 @@ msgid "Instrument"
msgstr ""
#: core/os/input_event.cpp
-#, fuzzy
msgid "Controller Number"
-msgstr "Linia Numărul:"
+msgstr "Numărul controlerului"
#: core/os/input_event.cpp
msgid "Controller Value"
@@ -680,9 +678,8 @@ msgid "Main Run Args"
msgstr "Argumente principale ale rulării"
#: core/project_settings.cpp
-#, fuzzy
msgid "Scene Naming"
-msgstr "Calea Scenei:"
+msgstr "Denumirea scenei"
#: core/project_settings.cpp
msgid "Search In File Extensions"
@@ -818,9 +815,8 @@ msgstr "Calitate"
#: 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 "Filtre:"
+msgstr "Filtre"
#: core/project_settings.cpp scene/main/viewport.cpp
msgid "Sharpen Intensity"
@@ -840,9 +836,8 @@ msgstr "Depanare"
#: core/project_settings.cpp main/main.cpp modules/gdscript/gdscript.cpp
#: modules/visual_script/visual_script.cpp scene/resources/dynamic_font.cpp
-#, fuzzy
msgid "Settings"
-msgstr "Setări:"
+msgstr "Setări"
#: core/project_settings.cpp editor/script_editor_debugger.cpp main/main.cpp
#: modules/mono/mono_gd/gd_mono.cpp
@@ -1074,9 +1069,8 @@ msgstr ""
#: scene/animation/animation_blend_tree.cpp scene/gui/control.cpp
#: scene/main/canvas_layer.cpp scene/resources/environment.cpp
#: scene/resources/material.cpp scene/resources/particles_material.cpp
-#, fuzzy
msgid "Scale"
-msgstr "Dimensiune:"
+msgstr "Scară"
#: drivers/gles3/rasterizer_scene_gles3.cpp
#, fuzzy
@@ -1184,16 +1178,14 @@ msgstr "Timp"
#: editor/animation_track_editor.cpp editor/import/resource_importer_scene.cpp
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Location"
-msgstr "Pas Rotație:"
+msgstr "Locație"
#: 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 "Pas Rotație:"
+msgstr "Rotație"
#: editor/animation_track_editor.cpp editor/script_editor_debugger.cpp
#: modules/visual_script/visual_script_nodes.cpp scene/gui/range.cpp
@@ -1235,14 +1227,12 @@ msgid "Stream"
msgstr ""
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Start Offset"
-msgstr "Compensare Grilă:"
+msgstr "Decalaj de pornire"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "End Offset"
-msgstr "Compensare Grilă:"
+msgstr "Decalaj de sfarsire"
#: editor/animation_track_editor.cpp editor/editor_settings.cpp
#: editor/import/resource_importer_scene.cpp
@@ -1366,14 +1356,12 @@ msgid "Remove this track."
msgstr "Ștergeți pista selectată."
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Time (s):"
-msgstr "Timp (s): "
+msgstr "Timp (s):"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Position:"
-msgstr "Poziție"
+msgstr "Poziție:"
#: editor/animation_track_editor.cpp
#, fuzzy
@@ -1414,9 +1402,8 @@ msgid "Out-Handle:"
msgstr "Setează Mâner"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Stream:"
-msgstr "Închidere curbă"
+msgstr "Curent:"
#: editor/animation_track_editor.cpp
#, fuzzy
@@ -1646,9 +1633,8 @@ msgid "Add Method Track Key"
msgstr "Inserați Pistă și Cheie"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Method not found in object:"
-msgstr "Metoda nu a fost găsită în obiect: "
+msgstr "Metoda nu a fost găsită în obiect:"
#: editor/animation_track_editor.cpp
msgid "Anim Move Keys"
@@ -2621,9 +2607,8 @@ msgid "There is no '%s' file."
msgstr "Nu este niciun '%s' în filă."
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Layout:"
-msgstr "Schemă"
+msgstr "Dispunere:"
#: editor/editor_audio_buses.cpp
msgid "Invalid file, not an audio bus layout."
@@ -2876,9 +2861,8 @@ msgid "Failed to export project files."
msgstr "Nu s-a putut porni subprocesul!"
#: editor/editor_export.cpp
-#, fuzzy
msgid "Can't open file to read from path \"%s\"."
-msgstr "Nu pot deschide fiÅŸierul pentru scris:"
+msgstr "Nu se poate deschide fiÅŸierul pentru a citi din \"%s\":"
#: editor/editor_export.cpp
#, fuzzy
@@ -3019,9 +3003,8 @@ msgid "The given export path doesn't exist."
msgstr "Fișierul nu există."
#: editor/editor_export.cpp platform/javascript/export/export.cpp
-#, fuzzy
msgid "Template file not found: \"%s\"."
-msgstr "Fișierul șablon nu a fost găsit:"
+msgstr "Fișierul șablonului nu a fost găsit: \"%s\"."
#: editor/editor_export.cpp
#, fuzzy
@@ -3325,9 +3308,8 @@ msgid "Access"
msgstr "Succes!"
#: editor/editor_file_dialog.cpp editor/editor_settings.cpp
-#, fuzzy
msgid "Display Mode"
-msgstr "Mod redare:"
+msgstr "Modul de afișare"
#: editor/editor_file_dialog.cpp
#: editor/import/resource_importer_layered_texture.cpp
@@ -3347,17 +3329,15 @@ msgstr "Mod ÃŽn Jur"
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
#, fuzzy
msgid "Current Dir"
-msgstr "Curent:"
+msgstr "Dir curent"
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
-#, fuzzy
msgid "Current File"
-msgstr "Profil Curent:"
+msgstr "Fișier curent"
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
-#, fuzzy
msgid "Current Path"
-msgstr "Curent:"
+msgstr "Calea curentă"
#: editor/editor_file_dialog.cpp editor/editor_settings.cpp
#: scene/gui/file_dialog.cpp
@@ -4930,9 +4910,8 @@ msgid "Install from file"
msgstr "Instalează Din Fișier"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Select android sources file"
-msgstr "Selectează un Mesh Sursă:"
+msgstr "Selectează fisierele sursa android"
#: editor/editor_node.cpp
msgid ""
@@ -5080,9 +5059,8 @@ msgstr "Actualizare"
#: editor/editor_plugin_settings.cpp platform/android/export/export_plugin.cpp
#: platform/iphone/export/export.cpp platform/osx/export/export.cpp
#: platform/uwp/export/export.cpp
-#, fuzzy
msgid "Version"
-msgstr "Versiune:"
+msgstr "Versiune"
#: editor/editor_plugin_settings.cpp
#, fuzzy
@@ -5280,9 +5258,8 @@ msgstr ""
#: 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 "Modificare tip bază:"
+msgstr "Tip de bază"
#: editor/editor_resource_picker.cpp
#, fuzzy
@@ -5379,9 +5356,8 @@ msgid "Font Hinting"
msgstr ""
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Main Font"
-msgstr "Caracteristici active:"
+msgstr "Font principal"
#: editor/editor_settings.cpp
msgid "Main Font Bold"
@@ -5642,9 +5618,8 @@ msgid "Appearance"
msgstr ""
#: editor/editor_settings.cpp scene/gui/text_edit.cpp
-#, fuzzy
msgid "Show Line Numbers"
-msgstr "Linia Numărul:"
+msgstr "Afiseaza numerele liniei"
#: editor/editor_settings.cpp
#, fuzzy
@@ -5694,9 +5669,8 @@ msgid "Show Members Overview"
msgstr ""
#: editor/editor_settings.cpp editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Files"
-msgstr "Fișier:"
+msgstr "Fișiere"
#: editor/editor_settings.cpp
msgid "Trim Trailing Whitespace On Save"
@@ -5867,14 +5841,12 @@ msgid "Shape"
msgstr ""
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Primary Grid Steps"
-msgstr "Pas Grilă:"
+msgstr "Pași de grilă primară"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Grid Size"
-msgstr "Pas Grilă:"
+msgstr "Dimensiunea grilei"
#: editor/editor_settings.cpp
msgid "Grid Division Level Max"
@@ -6045,9 +6017,8 @@ msgid "Bone Color 2"
msgstr "Redenumiţi Autoload"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Bone Selected Color"
-msgstr "Configură Profilul Selectat:"
+msgstr "Culoarea osului selectat"
#: editor/editor_settings.cpp
msgid "Bone IK Color"
@@ -6058,9 +6029,8 @@ msgid "Bone Outline Color"
msgstr ""
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Bone Outline Size"
-msgstr "Dimensiunea Conturului:"
+msgstr "Dimensiunea conturului osului"
#: editor/editor_settings.cpp
msgid "Viewport Border Color"
@@ -6198,9 +6168,8 @@ msgstr ""
#. TRANSLATORS: Project Manager here refers to the tool used to create/manage Godot projects.
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Sorting Order"
-msgstr "Redenumind directorul:"
+msgstr "Ordinea de sortare"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
msgid "Symbol Color"
@@ -6215,9 +6184,8 @@ msgid "Control Flow Keyword Color"
msgstr ""
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Base Type Color"
-msgstr "Modificare tip bază:"
+msgstr "Culoare tip de bază"
#: editor/editor_settings.cpp
msgid "Engine Type Color"
@@ -6270,14 +6238,12 @@ msgid "Text Color"
msgstr ""
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Line Number Color"
-msgstr "Linia Numărul:"
+msgstr "Culoare numărul liniei"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Safe Line Number Color"
-msgstr "Linia Numărul:"
+msgstr "Culoarea numărului liniei sigură"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
msgid "Caret Color"
@@ -6429,17 +6395,15 @@ msgstr "Se conectează la Oglinda..."
#: editor/export_template_manager.cpp
#, fuzzy
msgid "Can't resolve the requested address."
-msgstr "Nu se poate rezolva numele gazdei:"
+msgstr "Nu se poate rezolva adresa solicitată."
#: editor/export_template_manager.cpp
-#, fuzzy
msgid "Can't connect to the mirror."
-msgstr "Nu se poate conecta la gazda:"
+msgstr "Nu se poate conecta la oglindă."
#: editor/export_template_manager.cpp
-#, fuzzy
msgid "No response from the mirror."
-msgstr "Nciun răspuns de la gazda:"
+msgstr "Niciun răspuns de la oglinda."
#: editor/export_template_manager.cpp
#: editor/plugins/asset_library_editor_plugin.cpp
@@ -6453,9 +6417,8 @@ msgid "Request ended up in a redirect loop."
msgstr "Cerere eșuată, prea multe redirecționări"
#: editor/export_template_manager.cpp
-#, fuzzy
msgid "Request failed:"
-msgstr "Cerere Eșuată."
+msgstr "Cerere Eșuată:"
#: editor/export_template_manager.cpp
msgid "Download complete; extracting templates..."
@@ -6604,9 +6567,8 @@ msgid "Uninstall templates for the current version."
msgstr ""
#: editor/export_template_manager.cpp
-#, fuzzy
msgid "Download from:"
-msgstr "Eroare Descărcare"
+msgstr "Descărcați din:"
#: editor/export_template_manager.cpp
#, fuzzy
@@ -7098,9 +7060,8 @@ 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 "Filtre:"
+msgstr "Filtru:"
#: editor/import/resource_importer_layered_texture.cpp
#: editor/import/resource_importer_texture.cpp
@@ -7139,9 +7100,8 @@ msgid "Vertical"
msgstr "Mută ghidul vertical"
#: editor/import/resource_importer_obj.cpp
-#, fuzzy
msgid "Generate Tangents"
-msgstr "Număr de Puncte Generate:"
+msgstr "Generează tangente"
#: editor/import/resource_importer_obj.cpp
#, fuzzy
@@ -7217,12 +7177,11 @@ msgstr "Tip Membru"
#: editor/import/resource_importer_scene.cpp
#, fuzzy
msgid "Root Name"
-msgstr "Nume Nod:"
+msgstr "Nume rădăcină"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Root Scale"
-msgstr "Dimensiune:"
+msgstr "Dimensiune Radacina"
#: editor/import/resource_importer_scene.cpp
#, fuzzy
@@ -7230,9 +7189,8 @@ msgid "Custom Script"
msgstr "Creează Nod"
#: editor/import/resource_importer_scene.cpp scene/resources/texture.cpp
-#, fuzzy
msgid "Storage"
-msgstr "Fişierul se Stochează:"
+msgstr "Stochare"
#: editor/import/resource_importer_scene.cpp
msgid "Use Legacy Names"
@@ -7318,9 +7276,8 @@ msgid "Enabled"
msgstr "Activați"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Max Linear Error"
-msgstr "Eroare Lineară Max:"
+msgstr "Eroare liniară maximă"
#: editor/import/resource_importer_scene.cpp
#, fuzzy
@@ -7328,9 +7285,8 @@ msgid "Max Angular Error"
msgstr "Eroare Angulară Max:"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Max Angle"
-msgstr "Valoare:"
+msgstr "Unghiul maxim"
#: editor/import/resource_importer_scene.cpp
#, fuzzy
@@ -7338,16 +7294,14 @@ msgid "Remove Unused Tracks"
msgstr "Elimină Pista Anim"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Clips"
-msgstr "Secvențe Anim:"
+msgstr "Clipuri"
#: 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 "Cantitate:"
+msgstr "Cantitate"
#: editor/import/resource_importer_scene.cpp
#: editor/plugins/mesh_library_editor_plugin.cpp
@@ -7455,9 +7409,8 @@ msgid "Invert Color"
msgstr "Culori de Emisie"
#: editor/import/resource_importer_texture.cpp
-#, fuzzy
msgid "Normal Map Invert Y"
-msgstr "Dimensiune Aleatorie:"
+msgstr "Hartă normală inversează Y"
#: editor/import/resource_importer_texture.cpp
#, fuzzy
@@ -7479,9 +7432,8 @@ msgid ""
msgstr ""
#: editor/import/resource_importer_texture_atlas.cpp
-#, fuzzy
msgid "Atlas File"
-msgstr "Dimensiunea Conturului:"
+msgstr "Fișierul Atlasului"
#: editor/import/resource_importer_texture_atlas.cpp
#, fuzzy
@@ -7498,9 +7450,8 @@ msgid "Trim Alpha Border From Region"
msgstr ""
#: editor/import/resource_importer_wav.cpp scene/2d/physics_body_2d.cpp
-#, fuzzy
msgid "Force"
-msgstr "Mesh Sursă:"
+msgstr "Forță"
#: editor/import/resource_importer_wav.cpp
msgid "8 Bit"
@@ -7527,9 +7478,8 @@ msgid "Trim"
msgstr ""
#: editor/import/resource_importer_wav.cpp
-#, fuzzy
msgid "Normalize"
-msgstr "Dimensiune Aleatorie:"
+msgstr "Normalizați"
#: editor/import/resource_importer_wav.cpp
#: scene/resources/audio_stream_sample.cpp
@@ -7633,9 +7583,8 @@ msgid "Capitalized"
msgstr "Proprietăți"
#: editor/inspector_dock.cpp
-#, fuzzy
msgid "Localized"
-msgstr "Dimensiune Aleatorie:"
+msgstr "Localizat"
#: editor/inspector_dock.cpp
msgid "Localization not available for current language."
@@ -7982,9 +7931,8 @@ msgid "Blend:"
msgstr "Amestec:"
#: editor/plugins/animation_blend_tree_editor_plugin.cpp
-#, fuzzy
msgid "Parameter Changed:"
-msgstr "Modificări ale Actualizării"
+msgstr "Parametru modificat:"
#: editor/plugins/animation_blend_tree_editor_plugin.cpp
#: editor/plugins/animation_tree_player_editor_plugin.cpp
@@ -8402,9 +8350,8 @@ msgid "Set the end animation. This is useful for sub-transitions."
msgstr ""
#: editor/plugins/animation_state_machine_editor.cpp
-#, fuzzy
msgid "Transition:"
-msgstr "Tranziție: "
+msgstr "Tranziție:"
#: editor/plugins/animation_state_machine_editor.cpp
msgid "Play Mode:"
@@ -8673,7 +8620,7 @@ msgstr "Eroare Descărcare"
#: editor/plugins/asset_library_editor_plugin.cpp
#, fuzzy
msgid "Available URLs"
-msgstr "Profile Disponibile:"
+msgstr "URL-uri disponibile"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Download for this asset is already in progress!"
@@ -9803,9 +9750,8 @@ msgstr ""
#: editor/plugins/item_list_editor_plugin.cpp
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Separator"
-msgstr "Enumerări:"
+msgstr "Separator"
#: editor/plugins/item_list_editor_plugin.cpp
msgid "Item %d"
@@ -10237,9 +10183,8 @@ msgid "Volume"
msgstr "Volum"
#: editor/plugins/particles_editor_plugin.cpp
-#, fuzzy
msgid "Emission Source:"
-msgstr "Sursă de Emisie: "
+msgstr "Sursă de Emisie:"
#: editor/plugins/particles_editor_plugin.cpp
msgid "A processor material of type 'ParticlesMaterial' is required."
@@ -10659,9 +10604,8 @@ msgid "Flip Portals"
msgstr ""
#: editor/plugins/room_manager_editor_plugin.cpp
-#, fuzzy
msgid "Room Generate Points"
-msgstr "Număr de Puncte Generate:"
+msgstr "Cameră Genereaza puncte"
#: editor/plugins/room_manager_editor_plugin.cpp
#, fuzzy
@@ -13303,9 +13247,10 @@ msgstr "Opțiuni Snapping"
#: scene/2d/path_2d.cpp scene/2d/polygon_2d.cpp scene/2d/sprite.cpp
#: scene/3d/cpu_particles.cpp scene/3d/label_3d.cpp scene/3d/path.cpp
#: scene/3d/physics_body.cpp scene/3d/soft_body.cpp scene/3d/sprite_3d.cpp
-#: 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
+#: scene/3d/visual_instance.cpp 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 "Compensare Grilă:"
@@ -14712,13 +14657,13 @@ msgstr ""
#: editor/project_manager.cpp
msgid ""
-"Couldn't load project.godot in project path (error %d). It may be missing or "
-"corrupted."
+"Couldn't load project at '%s' (error %d). It may be missing or corrupted."
msgstr ""
#: editor/project_manager.cpp
-msgid "Couldn't edit project.godot in project path."
-msgstr ""
+#, fuzzy
+msgid "Couldn't save project at '%s' (error %d)."
+msgstr "Imposibil de deschis '%s'."
#: editor/project_manager.cpp
msgid "Couldn't create project.godot in project path."
@@ -18774,9 +18719,8 @@ msgid "Get Self"
msgstr "Propriu"
#: modules/visual_script/visual_script_nodes.cpp
-#, fuzzy
msgid "CustomNode"
-msgstr "Creează Nod"
+msgstr "Nod Custom"
#: modules/visual_script/visual_script_nodes.cpp
msgid "Custom node has no _step() method, can't process graph."
@@ -22635,7 +22579,7 @@ msgstr ""
#: scene/3d/camera.cpp scene/3d/light.cpp scene/3d/reflection_probe.cpp
msgid "Cull Mask"
-msgstr ""
+msgstr "Masca Cull"
#: scene/3d/camera.cpp
#, fuzzy
@@ -23987,6 +23931,15 @@ msgstr "Eroare!"
msgid "AABB"
msgstr ""
+#: scene/3d/visual_instance.cpp
+#, fuzzy
+msgid "Sorting"
+msgstr "Se importă:"
+
+#: scene/3d/visual_instance.cpp
+msgid "Use AABB Center"
+msgstr ""
+
#: scene/3d/visual_instance.cpp scene/resources/navigation_mesh.cpp
msgid "Geometry"
msgstr "Geometria"
@@ -24779,7 +24732,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"
@@ -26737,7 +26690,7 @@ msgstr ""
#: scene/resources/environment.cpp
msgid "Blur"
-msgstr ""
+msgstr "Blur"
#: scene/resources/environment.cpp
msgid "Edge Sharpness"
diff --git a/editor/translations/ru.po b/editor/translations/ru.po
index 0432de4da5..d746bb61ad 100644
--- a/editor/translations/ru.po
+++ b/editor/translations/ru.po
@@ -126,13 +126,14 @@
# Дмитрий <Dimega@inbox.ru>, 2022.
# Vladimir Kirillovskiy <vladimir.kirillovskiy@gmail.com>, 2022.
# Evgeniy Khramov <thejenjagamertjg@gmail.com>, 2022.
+# kirill blaze <kirillblaze2@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-09-27 21:37+0000\n"
-"Last-Translator: Evgeniy Khramov <thejenjagamertjg@gmail.com>\n"
+"PO-Revision-Date: 2022-11-25 12:13+0000\n"
+"Last-Translator: Vladimir Kirillovskiy <vladimir.kirillovskiy@gmail.com>\n"
"Language-Team: Russian <https://hosted.weblate.org/projects/godot-engine/"
"godot/ru/>\n"
"Language: ru\n"
@@ -141,7 +142,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.14.1\n"
+"X-Generator: Weblate 4.15-dev\n"
#: core/bind/core_bind.cpp main/main.cpp
msgid "Tablet Driver"
@@ -1298,9 +1299,8 @@ msgid "Animation"
msgstr "ÐнимациÑ"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Easing"
-msgstr "Переход В-ИЗ"
+msgstr "Облегчение"
#: editor/animation_track_editor.cpp
msgid "Anim Multi Change Keyframe Time"
@@ -1443,12 +1443,10 @@ msgid "Easing:"
msgstr "Переход В-ИЗ:"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "In-Handle:"
msgstr "Обработчик Ввода:"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Out-Handle:"
msgstr "Обработчик Вывода:"
@@ -11695,9 +11693,8 @@ msgid "New Animation"
msgstr "ÐÐ¾Ð²Ð°Ñ Ð°Ð½Ð¸Ð¼Ð°Ñ†Ð¸Ñ"
#: editor/plugins/sprite_frames_editor_plugin.cpp
-#, fuzzy
msgid "Filter animations"
-msgstr "Фильтровать анимации"
+msgstr "Фильтр анимации"
#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Speed:"
@@ -12878,9 +12875,10 @@ msgstr "Параметры привÑзки"
#: scene/2d/path_2d.cpp scene/2d/polygon_2d.cpp scene/2d/sprite.cpp
#: scene/3d/cpu_particles.cpp scene/3d/label_3d.cpp scene/3d/path.cpp
#: scene/3d/physics_body.cpp scene/3d/soft_body.cpp scene/3d/sprite_3d.cpp
-#: 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
+#: scene/3d/visual_instance.cpp 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
msgid "Offset"
msgstr "Смещение"
@@ -12911,9 +12909,8 @@ msgid "Texture"
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
@@ -12931,44 +12928,36 @@ msgid "Tile Mode"
msgstr "Режим плитки"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Autotile Bitmask Mode"
msgstr "Режим битовой маÑки"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Subtile Size"
msgstr "Размер контура"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Subtile Spacing"
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 "ЧувÑтвительноÑть навигации"
#: 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
@@ -12991,9 +12980,8 @@ msgid "Selected Occlusion"
msgstr "Выделение"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Tileset Script"
-msgstr "Фильтр Ñценариев"
+msgstr "Скрипт набора тайлов"
#: editor/plugins/tile_set_editor_plugin.cpp
msgid "TileSet"
@@ -14305,16 +14293,17 @@ msgid "Invalid project path (changed anything?)."
msgstr "Ðеверный путь к проекту (Что-то изменили?)."
#: editor/project_manager.cpp
+#, fuzzy
msgid ""
-"Couldn't load project.godot in project path (error %d). It may be missing or "
-"corrupted."
+"Couldn't load project at '%s' (error %d). It may be missing or corrupted."
msgstr ""
"Ðе удалоÑÑŒ загрузить project.godot в пути проекта (ошибка %d). Возможно, он "
"отÑутÑтвует или поврежден."
#: editor/project_manager.cpp
-msgid "Couldn't edit project.godot in project path."
-msgstr "Ðе удалоÑÑŒ изменить project.godot в папке проекта."
+#, fuzzy
+msgid "Couldn't save project at '%s' (error %d)."
+msgstr "Ðе удаётÑÑ Ð¾Ñ‚ÐºÑ€Ñ‹Ñ‚ÑŒ проект в «%s»."
#: editor/project_manager.cpp
msgid "Couldn't create project.godot in project path."
@@ -19322,11 +19311,11 @@ msgstr ""
#: platform/javascript/export/export.cpp
msgid "For Mobile"
-msgstr ""
+msgstr "Ð”Ð»Ñ Ð¼Ð¾Ð±Ð¸Ð»ÑŒÐ½Ñ‹Ñ… уÑтройÑтв"
#: platform/javascript/export/export.cpp
msgid "HTML"
-msgstr ""
+msgstr "HTML"
#: platform/javascript/export/export.cpp
msgid "Export Icon"
@@ -23386,6 +23375,16 @@ msgstr "ÐœÐ°ÐºÑ Ð¡Ð¸Ð»Ð°"
msgid "AABB"
msgstr ""
+#: scene/3d/visual_instance.cpp
+#, fuzzy
+msgid "Sorting"
+msgstr "Сортировать"
+
+#: scene/3d/visual_instance.cpp
+#, fuzzy
+msgid "Use AABB Center"
+msgstr "ИÑпользовать Ambient"
+
#: scene/3d/visual_instance.cpp scene/resources/navigation_mesh.cpp
msgid "Geometry"
msgstr "ГеометриÑ"
@@ -25895,9 +25894,8 @@ msgid "Height Curve"
msgstr "ÐšÑ€Ð¸Ð²Ð°Ñ Ð²Ñ‹Ñоты"
#: scene/resources/environment.cpp
-#, fuzzy
msgid "Tonemap"
-msgstr "ПереназначениÑ"
+msgstr "Карта тональноÑти"
#: scene/resources/environment.cpp
#, fuzzy
@@ -26011,7 +26009,7 @@ msgstr ""
#: scene/resources/environment.cpp
#: servers/audio/effects/audio_effect_chorus.cpp
msgid "2"
-msgstr ""
+msgstr "2"
#: scene/resources/environment.cpp
#: servers/audio/effects/audio_effect_chorus.cpp
diff --git a/editor/translations/si.po b/editor/translations/si.po
index 5e99894cf1..d0fcba8cfd 100644
--- a/editor/translations/si.po
+++ b/editor/translations/si.po
@@ -12562,9 +12562,10 @@ msgstr "à·à·Šâ€à¶»à·’à¶­:"
#: scene/2d/path_2d.cpp scene/2d/polygon_2d.cpp scene/2d/sprite.cpp
#: scene/3d/cpu_particles.cpp scene/3d/label_3d.cpp scene/3d/path.cpp
#: scene/3d/physics_body.cpp scene/3d/soft_body.cpp scene/3d/sprite_3d.cpp
-#: 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
+#: scene/3d/visual_instance.cpp 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
msgid "Offset"
msgstr ""
@@ -13926,12 +13927,11 @@ msgstr ""
#: editor/project_manager.cpp
msgid ""
-"Couldn't load project.godot in project path (error %d). It may be missing or "
-"corrupted."
+"Couldn't load project at '%s' (error %d). It may be missing or corrupted."
msgstr ""
#: editor/project_manager.cpp
-msgid "Couldn't edit project.godot in project path."
+msgid "Couldn't save project at '%s' (error %d)."
msgstr ""
#: editor/project_manager.cpp
@@ -22683,6 +22683,15 @@ msgstr "à¶šà·à¶©à¶´à¶­"
msgid "AABB"
msgstr ""
+#: scene/3d/visual_instance.cpp
+#, fuzzy
+msgid "Sorting"
+msgstr "නිවේà·à¶± මà·à¶¯à·’ලිය"
+
+#: scene/3d/visual_instance.cpp
+msgid "Use AABB Center"
+msgstr ""
+
#: scene/3d/visual_instance.cpp scene/resources/navigation_mesh.cpp
msgid "Geometry"
msgstr ""
diff --git a/editor/translations/sk.po b/editor/translations/sk.po
index ebd2256728..43c2fa6b5b 100644
--- a/editor/translations/sk.po
+++ b/editor/translations/sk.po
@@ -13245,9 +13245,10 @@ msgstr "Možnosti Prichytávania"
#: scene/2d/path_2d.cpp scene/2d/polygon_2d.cpp scene/2d/sprite.cpp
#: scene/3d/cpu_particles.cpp scene/3d/label_3d.cpp scene/3d/path.cpp
#: scene/3d/physics_body.cpp scene/3d/soft_body.cpp scene/3d/sprite_3d.cpp
-#: 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
+#: scene/3d/visual_instance.cpp 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 "Odchýlka Mriežky:"
@@ -14658,12 +14659,11 @@ msgstr ""
#: editor/project_manager.cpp
msgid ""
-"Couldn't load project.godot in project path (error %d). It may be missing or "
-"corrupted."
+"Couldn't load project at '%s' (error %d). It may be missing or corrupted."
msgstr ""
#: editor/project_manager.cpp
-msgid "Couldn't edit project.godot in project path."
+msgid "Couldn't save project at '%s' (error %d)."
msgstr ""
#: editor/project_manager.cpp
@@ -23921,6 +23921,15 @@ msgstr "Chyba!"
msgid "AABB"
msgstr ""
+#: scene/3d/visual_instance.cpp
+#, fuzzy
+msgid "Sorting"
+msgstr "Importovanie:"
+
+#: scene/3d/visual_instance.cpp
+msgid "Use AABB Center"
+msgstr ""
+
#: scene/3d/visual_instance.cpp scene/resources/navigation_mesh.cpp
#, fuzzy
msgid "Geometry"
diff --git a/editor/translations/sl.po b/editor/translations/sl.po
index f0e227266d..864dac1b8d 100644
--- a/editor/translations/sl.po
+++ b/editor/translations/sl.po
@@ -13421,9 +13421,10 @@ msgstr "Možnosti pripenjanja"
#: scene/2d/path_2d.cpp scene/2d/polygon_2d.cpp scene/2d/sprite.cpp
#: scene/3d/cpu_particles.cpp scene/3d/label_3d.cpp scene/3d/path.cpp
#: scene/3d/physics_body.cpp scene/3d/soft_body.cpp scene/3d/sprite_3d.cpp
-#: 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
+#: scene/3d/visual_instance.cpp 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 "Mrežni Zamik:"
@@ -14850,13 +14851,13 @@ msgstr ""
#: editor/project_manager.cpp
msgid ""
-"Couldn't load project.godot in project path (error %d). It may be missing or "
-"corrupted."
+"Couldn't load project at '%s' (error %d). It may be missing or corrupted."
msgstr ""
#: editor/project_manager.cpp
-msgid "Couldn't edit project.godot in project path."
-msgstr ""
+#, fuzzy
+msgid "Couldn't save project at '%s' (error %d)."
+msgstr "Ni mogoÄe odpreti '%s'."
#: editor/project_manager.cpp
msgid "Couldn't create project.godot in project path."
@@ -24167,6 +24168,15 @@ msgstr "Napaka!"
msgid "AABB"
msgstr ""
+#: scene/3d/visual_instance.cpp
+#, fuzzy
+msgid "Sorting"
+msgstr "Uvažanje:"
+
+#: scene/3d/visual_instance.cpp
+msgid "Use AABB Center"
+msgstr ""
+
#: scene/3d/visual_instance.cpp scene/resources/navigation_mesh.cpp
#, fuzzy
msgid "Geometry"
diff --git a/editor/translations/sq.po b/editor/translations/sq.po
index f8ffd0e88d..1215b7dbcb 100644
--- a/editor/translations/sq.po
+++ b/editor/translations/sq.po
@@ -13106,9 +13106,10 @@ msgstr "Përshkrimi i Klasës"
#: scene/2d/path_2d.cpp scene/2d/polygon_2d.cpp scene/2d/sprite.cpp
#: scene/3d/cpu_particles.cpp scene/3d/label_3d.cpp scene/3d/path.cpp
#: scene/3d/physics_body.cpp scene/3d/soft_body.cpp scene/3d/sprite_3d.cpp
-#: 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
+#: scene/3d/visual_instance.cpp 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
msgid "Offset"
msgstr ""
@@ -14502,12 +14503,11 @@ msgstr ""
#: editor/project_manager.cpp
msgid ""
-"Couldn't load project.godot in project path (error %d). It may be missing or "
-"corrupted."
+"Couldn't load project at '%s' (error %d). It may be missing or corrupted."
msgstr ""
#: editor/project_manager.cpp
-msgid "Couldn't edit project.godot in project path."
+msgid "Couldn't save project at '%s' (error %d)."
msgstr ""
#: editor/project_manager.cpp
@@ -23576,6 +23576,15 @@ msgstr "Pasqyrë"
msgid "AABB"
msgstr ""
+#: scene/3d/visual_instance.cpp
+#, fuzzy
+msgid "Sorting"
+msgstr "Duke Importuar:"
+
+#: scene/3d/visual_instance.cpp
+msgid "Use AABB Center"
+msgstr ""
+
#: scene/3d/visual_instance.cpp scene/resources/navigation_mesh.cpp
msgid "Geometry"
msgstr ""
diff --git a/editor/translations/sr_Cyrl.po b/editor/translations/sr_Cyrl.po
index f2f6a5bf09..419e33c494 100644
--- a/editor/translations/sr_Cyrl.po
+++ b/editor/translations/sr_Cyrl.po
@@ -14116,9 +14116,10 @@ msgstr "ПоÑтавке Залепљавања"
#: scene/2d/path_2d.cpp scene/2d/polygon_2d.cpp scene/2d/sprite.cpp
#: scene/3d/cpu_particles.cpp scene/3d/label_3d.cpp scene/3d/path.cpp
#: scene/3d/physics_body.cpp scene/3d/soft_body.cpp scene/3d/sprite_3d.cpp
-#: 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
+#: scene/3d/visual_instance.cpp 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 "ОфÑет:"
@@ -15791,16 +15792,15 @@ msgstr "Ðеважећа путања пројекта(нешто је измеÑ
#: editor/project_manager.cpp
#, fuzzy
msgid ""
-"Couldn't load project.godot in project path (error %d). It may be missing or "
-"corrupted."
+"Couldn't load project at '%s' (error %d). It may be missing or corrupted."
msgstr ""
"ÐеуÑпешно учитавање project.godot-а у његовој путањи (грешка %d). Могуће да "
"нешто недоÑтаје или је корумпирано."
#: editor/project_manager.cpp
#, fuzzy
-msgid "Couldn't edit project.godot in project path."
-msgstr "ÐеуÑпешна измена project.godot-а у путањи пројекта."
+msgid "Couldn't save project at '%s' (error %d)."
+msgstr "Ðе могу отворити '%s'."
#: editor/project_manager.cpp
#, fuzzy
@@ -25808,6 +25808,15 @@ msgstr "Грешка"
msgid "AABB"
msgstr ""
+#: scene/3d/visual_instance.cpp
+#, fuzzy
+msgid "Sorting"
+msgstr "Сортирање"
+
+#: scene/3d/visual_instance.cpp
+msgid "Use AABB Center"
+msgstr ""
+
#: scene/3d/visual_instance.cpp scene/resources/navigation_mesh.cpp
#, fuzzy
msgid "Geometry"
diff --git a/editor/translations/sr_Latn.po b/editor/translations/sr_Latn.po
index 8af5b1daaf..7973756c7e 100644
--- a/editor/translations/sr_Latn.po
+++ b/editor/translations/sr_Latn.po
@@ -12586,9 +12586,10 @@ msgstr "KaÄenje:"
#: scene/2d/path_2d.cpp scene/2d/polygon_2d.cpp scene/2d/sprite.cpp
#: scene/3d/cpu_particles.cpp scene/3d/label_3d.cpp scene/3d/path.cpp
#: scene/3d/physics_body.cpp scene/3d/soft_body.cpp scene/3d/sprite_3d.cpp
-#: 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
+#: scene/3d/visual_instance.cpp 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
msgid "Offset"
msgstr ""
@@ -13957,12 +13958,11 @@ msgstr ""
#: editor/project_manager.cpp
msgid ""
-"Couldn't load project.godot in project path (error %d). It may be missing or "
-"corrupted."
+"Couldn't load project at '%s' (error %d). It may be missing or corrupted."
msgstr ""
#: editor/project_manager.cpp
-msgid "Couldn't edit project.godot in project path."
+msgid "Couldn't save project at '%s' (error %d)."
msgstr ""
#: editor/project_manager.cpp
@@ -22819,6 +22819,15 @@ msgstr "%s Greška"
msgid "AABB"
msgstr ""
+#: scene/3d/visual_instance.cpp
+#, fuzzy
+msgid "Sorting"
+msgstr "Postavke UreÄ‘ivaÄa..."
+
+#: scene/3d/visual_instance.cpp
+msgid "Use AABB Center"
+msgstr ""
+
#: scene/3d/visual_instance.cpp scene/resources/navigation_mesh.cpp
msgid "Geometry"
msgstr ""
diff --git a/editor/translations/sv.po b/editor/translations/sv.po
index 44b6fcf8b6..04965e6c69 100644
--- a/editor/translations/sv.po
+++ b/editor/translations/sv.po
@@ -32,8 +32,8 @@ msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"Report-Msgid-Bugs-To: https://github.com/godotengine/godot\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2022-08-30 03:11+0000\n"
-"Last-Translator: Björn Åkesson <bjorn.akesson@gmail.com>\n"
+"PO-Revision-Date: 2022-09-29 19:16+0000\n"
+"Last-Translator: Kristoffer Grundström <swedishsailfishosuser@tutanota.com>\n"
"Language-Team: Swedish <https://hosted.weblate.org/projects/godot-engine/"
"godot/sv/>\n"
"Language: sv\n"
@@ -41,7 +41,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.14.1-dev\n"
+"X-Generator: Weblate 4.14.1\n"
#: core/bind/core_bind.cpp main/main.cpp
#, fuzzy
@@ -7177,7 +7177,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
@@ -13310,9 +13310,10 @@ msgstr "Alternativ"
#: scene/2d/path_2d.cpp scene/2d/polygon_2d.cpp scene/2d/sprite.cpp
#: scene/3d/cpu_particles.cpp scene/3d/label_3d.cpp scene/3d/path.cpp
#: scene/3d/physics_body.cpp scene/3d/soft_body.cpp scene/3d/sprite_3d.cpp
-#: 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
+#: scene/3d/visual_instance.cpp 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
msgid "Offset"
msgstr ""
@@ -13515,7 +13516,7 @@ msgstr ""
#: editor/plugins/version_control_editor_plugin.cpp
msgid "SSH Passphrase"
-msgstr ""
+msgstr "Lösenordsfras för SSH"
#: editor/plugins/version_control_editor_plugin.cpp
#, fuzzy
@@ -14713,13 +14714,13 @@ msgstr ""
#: editor/project_manager.cpp
msgid ""
-"Couldn't load project.godot in project path (error %d). It may be missing or "
-"corrupted."
+"Couldn't load project at '%s' (error %d). It may be missing or corrupted."
msgstr ""
#: editor/project_manager.cpp
-msgid "Couldn't edit project.godot in project path."
-msgstr ""
+#, fuzzy
+msgid "Couldn't save project at '%s' (error %d)."
+msgstr "Kan inte öppna projekt vid '%s'."
#: editor/project_manager.cpp
msgid "Couldn't create project.godot in project path."
@@ -18486,7 +18487,7 @@ msgstr ""
#: modules/visual_script/visual_script_flow_control.cpp
msgid "While"
-msgstr ""
+msgstr "Medans"
#: modules/visual_script/visual_script_flow_control.cpp
msgid "while (cond):"
@@ -23988,6 +23989,15 @@ msgstr "Fel"
msgid "AABB"
msgstr ""
+#: scene/3d/visual_instance.cpp
+#, fuzzy
+msgid "Sorting"
+msgstr "Sortera"
+
+#: scene/3d/visual_instance.cpp
+msgid "Use AABB Center"
+msgstr ""
+
#: scene/3d/visual_instance.cpp scene/resources/navigation_mesh.cpp
#, fuzzy
msgid "Geometry"
diff --git a/editor/translations/te.po b/editor/translations/te.po
index fe9f95b213..22474ca4ba 100644
--- a/editor/translations/te.po
+++ b/editor/translations/te.po
@@ -12382,9 +12382,10 @@ msgstr "గణనలà±"
#: scene/2d/path_2d.cpp scene/2d/polygon_2d.cpp scene/2d/sprite.cpp
#: scene/3d/cpu_particles.cpp scene/3d/label_3d.cpp scene/3d/path.cpp
#: scene/3d/physics_body.cpp scene/3d/soft_body.cpp scene/3d/sprite_3d.cpp
-#: 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
+#: scene/3d/visual_instance.cpp 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
msgid "Offset"
msgstr ""
@@ -13718,12 +13719,11 @@ msgstr ""
#: editor/project_manager.cpp
msgid ""
-"Couldn't load project.godot in project path (error %d). It may be missing or "
-"corrupted."
+"Couldn't load project at '%s' (error %d). It may be missing or corrupted."
msgstr ""
#: editor/project_manager.cpp
-msgid "Couldn't edit project.godot in project path."
+msgid "Couldn't save project at '%s' (error %d)."
msgstr ""
#: editor/project_manager.cpp
@@ -22285,6 +22285,15 @@ msgstr ""
msgid "AABB"
msgstr ""
+#: scene/3d/visual_instance.cpp
+#, fuzzy
+msgid "Sorting"
+msgstr "à°¸à±à°¥à°¿à°°à°¾à°‚కాలà±"
+
+#: scene/3d/visual_instance.cpp
+msgid "Use AABB Center"
+msgstr ""
+
#: scene/3d/visual_instance.cpp scene/resources/navigation_mesh.cpp
msgid "Geometry"
msgstr ""
diff --git a/editor/translations/th.po b/editor/translations/th.po
index 6e4b0e578f..5f4ee76a4d 100644
--- a/editor/translations/th.po
+++ b/editor/translations/th.po
@@ -13,13 +13,14 @@
# PT 07 <porton555@gmail.com>, 2021.
# SysError_ <ictsanook@hotmail.com>, 2021.
# Kanda Ninthfish <akkhaporn@gmail.com>, 2022.
+# Absurdnoobman <jakkalin91@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-04-18 09:10+0000\n"
-"Last-Translator: Kanda Ninthfish <akkhaporn@gmail.com>\n"
+"PO-Revision-Date: 2022-11-26 14:36+0000\n"
+"Last-Translator: Absurdnoobman <jakkalin91@gmail.com>\n"
"Language-Team: Thai <https://hosted.weblate.org/projects/godot-engine/godot/"
"th/>\n"
"Language: th\n"
@@ -27,7 +28,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.12-dev\n"
+"X-Generator: Weblate 4.15-dev\n"
#: core/bind/core_bind.cpp main/main.cpp
msgid "Tablet Driver"
@@ -48,9 +49,8 @@ msgid "Exit Code"
msgstr ""
#: core/bind/core_bind.cpp
-#, fuzzy
msgid "V-Sync Enabled"
-msgstr "เปิด"
+msgstr "เปิด V-Sync"
#: core/bind/core_bind.cpp main/main.cpp
msgid "V-Sync Via Compositor"
@@ -114,14 +114,13 @@ msgid "Maximized"
msgstr ""
#: core/bind/core_bind.cpp
-#, fuzzy
msgid "Minimized"
-msgstr "เริ่มต้น"
+msgstr "ย่อขนาด"
#: core/bind/core_bind.cpp core/project_settings.cpp scene/gui/dialogs.cpp
#: scene/gui/graph_node.cpp
msgid "Resizable"
-msgstr ""
+msgstr "ปรับขนาดได้"
#: 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
@@ -185,12 +184,11 @@ msgstr "ผิดพลาด"
#: core/bind/core_bind.cpp
#, fuzzy
msgid "Error String"
-msgstr "ผิดพลาดขณะบันทึà¸"
+msgstr "String ผิดพลาด"
#: core/bind/core_bind.cpp
-#, fuzzy
msgid "Error Line"
-msgstr "ผิดพลาดขณะบันทึà¸"
+msgstr "บรรทัดผิดพลาด"
#: core/bind/core_bind.cpp
#, fuzzy
@@ -213,9 +211,8 @@ msgid "Limits"
msgstr ""
#: core/command_queue_mt.cpp
-#, fuzzy
msgid "Command Queue"
-msgstr "ctrl: หมุน"
+msgstr "คิวคำสั่ง"
#: core/command_queue_mt.cpp
msgid "Multithreading Queue Size (KB)"
@@ -232,7 +229,7 @@ msgstr "ฟังà¸à¹Œà¸Šà¸±à¸™"
#: 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 "ข้อมูล"
#: core/io/file_access_network.cpp core/register_core_types.cpp
#: editor/editor_file_dialog.cpp editor/editor_settings.cpp main/main.cpp
@@ -13201,9 +13198,10 @@ msgstr "ตัวเลือà¸à¸à¸²à¸£à¸ªà¹à¸™à¸›"
#: scene/2d/path_2d.cpp scene/2d/polygon_2d.cpp scene/2d/sprite.cpp
#: scene/3d/cpu_particles.cpp scene/3d/label_3d.cpp scene/3d/path.cpp
#: scene/3d/physics_body.cpp scene/3d/soft_body.cpp scene/3d/sprite_3d.cpp
-#: 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
+#: scene/3d/visual_instance.cpp 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 "เลื่อน:"
@@ -14635,15 +14633,16 @@ msgid "Invalid project path (changed anything?)."
msgstr "ตำà¹à¸«à¸™à¹ˆà¸‡à¹‚ปรเจà¸à¸•์ผิดพลาด (ได้à¹à¸à¹‰à¹„ขอะไรไปหรือไม่?)"
#: editor/project_manager.cpp
+#, fuzzy
msgid ""
-"Couldn't load project.godot in project path (error %d). It may be missing or "
-"corrupted."
+"Couldn't load project at '%s' (error %d). It may be missing or corrupted."
msgstr ""
"โหลดไฟล์ project.godot ในโฟลเดอร์โปรเจà¸à¸•์ไม่ได้ (ข้อผิดพลาด %d) ไฟล์อาจสูà¸à¸«à¸²à¸¢à¸«à¸£à¸·à¸­à¹€à¸ªà¸µà¸¢à¸«à¸²à¸¢"
#: editor/project_manager.cpp
-msgid "Couldn't edit project.godot in project path."
-msgstr "à¹à¸à¹‰à¹„ขไฟล์ project.godot ไม่ได้"
+#, fuzzy
+msgid "Couldn't save project at '%s' (error %d)."
+msgstr "ไม่สามารถเปิดโปรเจà¸à¸•์ที่ '%s'"
#: editor/project_manager.cpp
msgid "Couldn't create project.godot in project path."
@@ -24074,6 +24073,15 @@ msgstr "ผิดพลาด"
msgid "AABB"
msgstr ""
+#: scene/3d/visual_instance.cpp
+#, fuzzy
+msgid "Sorting"
+msgstr "เรียง"
+
+#: scene/3d/visual_instance.cpp
+msgid "Use AABB Center"
+msgstr ""
+
#: scene/3d/visual_instance.cpp scene/resources/navigation_mesh.cpp
#, fuzzy
msgid "Geometry"
@@ -26878,7 +26886,7 @@ msgstr "ดีบั๊ภUV"
#: scene/resources/environment.cpp
msgid "Blur"
-msgstr ""
+msgstr "เบลอร์"
#: scene/resources/environment.cpp
msgid "Edge Sharpness"
diff --git a/editor/translations/tl.po b/editor/translations/tl.po
index bf39f11166..670e52056d 100644
--- a/editor/translations/tl.po
+++ b/editor/translations/tl.po
@@ -12724,9 +12724,10 @@ msgstr "Pagsasaayos ng Kalansay"
#: scene/2d/path_2d.cpp scene/2d/polygon_2d.cpp scene/2d/sprite.cpp
#: scene/3d/cpu_particles.cpp scene/3d/label_3d.cpp scene/3d/path.cpp
#: scene/3d/physics_body.cpp scene/3d/soft_body.cpp scene/3d/sprite_3d.cpp
-#: 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
+#: scene/3d/visual_instance.cpp 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 "Usog:"
@@ -14099,12 +14100,11 @@ msgstr ""
#: editor/project_manager.cpp
msgid ""
-"Couldn't load project.godot in project path (error %d). It may be missing or "
-"corrupted."
+"Couldn't load project at '%s' (error %d). It may be missing or corrupted."
msgstr ""
#: editor/project_manager.cpp
-msgid "Couldn't edit project.godot in project path."
+msgid "Couldn't save project at '%s' (error %d)."
msgstr ""
#: editor/project_manager.cpp
@@ -23165,6 +23165,15 @@ msgstr "Nabigo"
msgid "AABB"
msgstr ""
+#: scene/3d/visual_instance.cpp
+#, fuzzy
+msgid "Sorting"
+msgstr "Pagkakaayos"
+
+#: scene/3d/visual_instance.cpp
+msgid "Use AABB Center"
+msgstr ""
+
#: scene/3d/visual_instance.cpp scene/resources/navigation_mesh.cpp
#, fuzzy
msgid "Geometry"
diff --git a/editor/translations/tr.po b/editor/translations/tr.po
index 8cbf35a18b..ac4b509150 100644
--- a/editor/translations/tr.po
+++ b/editor/translations/tr.po
@@ -85,13 +85,17 @@
# bsr <bsndrn16@gmail.com>, 2022.
# Ramazan SANCAR <ramazansancar4545@gmail.com>, 2022.
# Burak Orcun OZKABLAN <borcunozkablan@gmail.com>, 2022.
+# arda4888 <ardagaming2006@gmail.com>, 2022.
+# Dream Drunk <myemailpoly149@gmail.com>, 2022.
+# alpdenthedev <ekrem_ekrem_45@hotmail.com>, 2022.
+# Muhammed Said Gülberk <msgulberk@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-09-11 22:22+0000\n"
-"Last-Translator: Burak Orcun OZKABLAN <borcunozkablan@gmail.com>\n"
+"PO-Revision-Date: 2022-12-05 10:16+0000\n"
+"Last-Translator: Muhammed Said Gülberk <msgulberk@gmail.com>\n"
"Language-Team: Turkish <https://hosted.weblate.org/projects/godot-engine/"
"godot/tr/>\n"
"Language: tr\n"
@@ -99,11 +103,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.14.1-dev\n"
+"X-Generator: Weblate 4.15-dev\n"
#: core/bind/core_bind.cpp main/main.cpp
msgid "Tablet Driver"
-msgstr "Tablet Sürücü"
+msgstr "Tablet Sürücüsü"
#: core/bind/core_bind.cpp
msgid "Clipboard"
@@ -114,7 +118,6 @@ msgid "Current Screen"
msgstr "Åžu anki Ekran"
#: core/bind/core_bind.cpp
-#, fuzzy
msgid "Exit Code"
msgstr "Çıkış Kodu"
@@ -132,11 +135,11 @@ msgstr "Delta YumuÅŸatma"
#: core/bind/core_bind.cpp
msgid "Low Processor Usage Mode"
-msgstr "Düşük İşlemci Kullanım Modu"
+msgstr "İşlemci Dostu Mod"
#: core/bind/core_bind.cpp
msgid "Low Processor Usage Mode Sleep (µsec)"
-msgstr "Düşük İşlemci Kullanımı Uyku Modu (μsn)"
+msgstr "Uykulu İşlemci Modu (µsec)"
#: core/bind/core_bind.cpp main/main.cpp platform/uwp/os_uwp.cpp
msgid "Keep Screen On"
@@ -152,7 +155,7 @@ msgstr "Maksimum Ekran Boyutu"
#: core/bind/core_bind.cpp
msgid "Screen Orientation"
-msgstr "Ekran Yönü"
+msgstr "Ekran oryantasyonu"
#: core/bind/core_bind.cpp core/project_settings.cpp main/main.cpp
#: platform/uwp/os_uwp.cpp
@@ -161,7 +164,7 @@ msgstr "Pencere"
#: core/bind/core_bind.cpp core/project_settings.cpp
msgid "Borderless"
-msgstr "Kenarlıksız"
+msgstr "Kenarsız"
#: core/bind/core_bind.cpp
msgid "Per Pixel Transparency Enabled"
@@ -333,7 +336,7 @@ msgstr "AÄŸ Profilcisi"
#: core/io/multiplayer_api.cpp scene/animation/animation_player.cpp
msgid "Root Node"
-msgstr "Kök Düğüm Adı"
+msgstr "Kök Düğümü"
#: core/io/networked_multiplayer_peer.cpp
msgid "Refuse New Connections"
@@ -361,7 +364,7 @@ msgstr "Akış Eşi"
#: core/io/stream_peer.cpp
msgid "Big Endian"
-msgstr "big-endian"
+msgstr "Big Endian"
#: core/io/stream_peer.cpp
msgid "Data Array"
@@ -369,7 +372,7 @@ msgstr "Veri Dizisi"
#: core/io/stream_peer_ssl.cpp
msgid "Blocking Handshake"
-msgstr "Tokalaşmayı blokla"
+msgstr "El Sıkışmayı Blokla"
#: core/io/udp_server.cpp
msgid "Max Pending Connections"
@@ -388,7 +391,7 @@ msgstr "1(bir) karakter uzunluÄŸunda bir dize bekleniyor ."
#: 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 "Baytları çözümlemek için yetersiz miktarda bayt ya da geçersiz format."
+msgstr "Baytları çözümlemek için yetersiz bayt miktarı veya geçersiz format."
#: core/math/expression.cpp
msgid "Invalid input %d (not passed) in expression"
@@ -396,7 +399,7 @@ msgstr "İfadede geçersiz giriş %d"
#: core/math/expression.cpp
msgid "self can't be used because instance is null (not passed)"
-msgstr "self kullanılamaz çünkü örnek boş (geçilmedi)"
+msgstr "örnek boş olduğu için self kullanılamaz (geçilmedi)"
#: core/math/expression.cpp
msgid "Invalid operands to operator %s, %s and %s."
@@ -7222,6 +7225,9 @@ 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: Dokunun 3D'de normal haritası olarak kullanıldığı algılandı. Bellek "
+"kullanımını azaltmak için kırmızı-yeşil doku sıkıştırma etkinleştiriliyor. "
+"(mavi kanal kullanılmıyor)."
#: editor/import/resource_importer_texture.cpp
#, fuzzy
@@ -7251,7 +7257,7 @@ msgstr "HDR Modu"
#: 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
@@ -7359,7 +7365,7 @@ msgstr "Maximum Hz Oranı"
#: editor/import/resource_importer_wav.cpp
msgid "Trim"
-msgstr ""
+msgstr "Kırp"
#: editor/import/resource_importer_wav.cpp
msgid "Normalize"
@@ -9535,7 +9541,7 @@ msgstr "Simge"
#: 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
@@ -10708,7 +10714,7 @@ msgstr "Script İsimlerini Listele"
#: editor/plugins/script_editor_plugin.cpp
msgid "Exec Flags"
-msgstr ""
+msgstr "Çalıştırma Bayrakları"
#: editor/plugins/script_editor_plugin.cpp
msgid "Clear Recent Scripts"
@@ -12891,9 +12897,10 @@ msgstr "Hizalama Ayarları"
#: scene/2d/path_2d.cpp scene/2d/polygon_2d.cpp scene/2d/sprite.cpp
#: scene/3d/cpu_particles.cpp scene/3d/label_3d.cpp scene/3d/path.cpp
#: scene/3d/physics_body.cpp scene/3d/soft_body.cpp scene/3d/sprite_3d.cpp
-#: 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
+#: scene/3d/visual_instance.cpp 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
msgid "Offset"
msgstr "Kaydırma"
@@ -14319,16 +14326,17 @@ msgid "Invalid project path (changed anything?)."
msgstr "Geçersiz proje yolu (bir şey değişti mi?)."
#: editor/project_manager.cpp
+#, fuzzy
msgid ""
-"Couldn't load project.godot in project path (error %d). It may be missing or "
-"corrupted."
+"Couldn't load project at '%s' (error %d). It may be missing or corrupted."
msgstr ""
"Proje yolundaki proje.godot düzenlenemedi (error %d). Eksik veya bozulmuş "
"olabilir."
#: editor/project_manager.cpp
-msgid "Couldn't edit project.godot in project path."
-msgstr "proje yolundaki proje.godot düzenlenemedi."
+#, fuzzy
+msgid "Couldn't save project at '%s' (error %d)."
+msgstr "'%s' adresindeki proje açılamıyor."
#: editor/project_manager.cpp
msgid "Couldn't create project.godot in project path."
@@ -15326,6 +15334,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 ""
+"Halihazırda örneklendirilmiş bir sahnenin alt öğesi olan dal kaydedilemez.\n"
+"Bu dalı kendisine ait sahneye kaydetmek için, orijinal sahneyi açın, bu dala "
+"sağ tıklayın, ve \"Dalı Sahne olarak Kaydet\"i seçin."
#: editor/scene_tree_dock.cpp
msgid ""
@@ -15333,6 +15344,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 ""
+"Devralınan sahnenin parçası olan bir dal kaydedilemez.\n"
+"Bu dalı kendisine ait sahneye kaydetmek için, orijinal sahneyi açın, bu dala "
+"sağ tıklayın, ve \"Dalı Sahne olarak Kaydet\"i seçin."
#: editor/scene_tree_dock.cpp
msgid "Save New Scene As..."
@@ -15360,19 +15374,18 @@ msgid "Make Local"
msgstr "YerelleÅŸtir"
#: editor/scene_tree_dock.cpp
-#, fuzzy
msgid "Enable Scene Unique Name(s)"
-msgstr "Sahne Benzersiz İsmini Etkin Kıl"
+msgstr "Sahne İçi Benzersiz İsim(ler)i Etkin Kıl"
#: editor/scene_tree_dock.cpp
-#, fuzzy
msgid "Unique names already used by another node in the scene:"
-msgstr "Başka bir düğüm sahnede bu benzersiz adı zaten kullanıyor."
+msgstr ""
+"Halihazırda sahnedeki başka bir düğüm tarafından kullanılan benzersiz "
+"isimler:"
#: editor/scene_tree_dock.cpp
-#, fuzzy
msgid "Disable Scene Unique Name(s)"
-msgstr "Sahne Benzersiz İsmini Etkisiz Kıl"
+msgstr "Sahne İçi Benzersiz İsim(ler)i Etkisiz Kıl"
#: editor/scene_tree_dock.cpp
msgid "New Scene Root"
@@ -15400,7 +15413,7 @@ msgstr "Diğer Düğüm"
#: editor/scene_tree_dock.cpp
msgid "Can't operate on nodes from a foreign scene!"
-msgstr "Yad bir sahnedeki düğümler üzerinde çalışamaz!"
+msgstr "Yabancı bir sahnedeki düğümler üzerinde çalışılamaz!"
#: editor/scene_tree_dock.cpp
msgid "Can't operate on nodes the current scene inherits from!"
@@ -15439,7 +15452,7 @@ msgstr "Sahne kaydedilirken hata."
#: editor/scene_tree_dock.cpp
msgid "Error duplicating scene to save it."
-msgstr "Kaydetmek için sahne çoğaltılırken hata."
+msgstr "Sahne kaydetmek için çoğaltılırken hata."
#: editor/scene_tree_dock.cpp
msgid "Sub-Resources"
@@ -15447,11 +15460,11 @@ msgstr "Alt Kaynaklar"
#: editor/scene_tree_dock.cpp
msgid "Access as Scene Unique Name"
-msgstr ""
+msgstr "Sahne İçi Benzersiz İsim olarak Erişim"
#: editor/scene_tree_dock.cpp
msgid "Clear Inheritance"
-msgstr "Kalıtı Temizle"
+msgstr "Kalıtımı Temizle"
#: editor/scene_tree_dock.cpp
msgid "Editable Children"
@@ -15476,7 +15489,7 @@ msgstr "Alt Düğüm Ekle"
#: editor/scene_tree_dock.cpp
msgid "Expand/Collapse All"
-msgstr "Hepsini Aç/Kapa"
+msgstr "Hepsini GeniÅŸlet/Daralt"
#: editor/scene_tree_dock.cpp
msgid "Change Type"
@@ -16193,7 +16206,7 @@ msgstr "Godot FiziÄŸi"
#: main/main.cpp servers/physics_2d/physics_2d_server_sw.cpp
#: servers/visual/visual_server_scene.cpp
msgid "Use BVH"
-msgstr ""
+msgstr "BVH Kullan"
#: main/main.cpp servers/physics_2d/physics_2d_server_sw.cpp
#: servers/visual/visual_server_scene.cpp
@@ -16213,7 +16226,7 @@ msgstr "MultiNode Kur"
#: main/main.cpp
msgid "RID Pool Prealloc"
-msgstr ""
+msgstr "RID Havuzu Ön Tahsisi"
#: main/main.cpp
#, fuzzy
@@ -16275,7 +16288,7 @@ msgstr "Sürücü Adı"
#: main/main.cpp
msgid "Fallback To GLES2"
-msgstr ""
+msgstr "GLES2'ye Geri Dön"
#: main/main.cpp
msgid "Use Nvidia Rect Flicker Workaround"
@@ -16889,9 +16902,8 @@ msgid "Script Class"
msgstr "Betik Sınıfı"
#: modules/gdnative/nativescript/nativescript.cpp
-#, fuzzy
msgid "Icon Path"
-msgstr "Yola Odaklan"
+msgstr "İkon Yolu"
#: modules/gdnative/register_types.cpp
msgid "GDNative"
@@ -16899,9 +16911,8 @@ msgstr "GDYerel"
#: modules/gdscript/editor/gdscript_highlighter.cpp
#: modules/gdscript/gdscript.cpp
-#, fuzzy
msgid "GDScript"
-msgstr "Betik"
+msgstr "GDScript"
#: modules/gdscript/editor/gdscript_highlighter.cpp
msgid "Function Definition Color"
@@ -18203,7 +18214,7 @@ msgstr ""
#: modules/visual_script/visual_script_flow_control.cpp
msgid "Type Cast"
-msgstr "Tür Değişimi"
+msgstr "Tür Dönüştür"
#: modules/visual_script/visual_script_flow_control.cpp
msgid "Is %s?"
@@ -18253,9 +18264,8 @@ msgid "Validate"
msgstr "DoÄŸrula"
#: modules/visual_script/visual_script_func_nodes.cpp
-#, fuzzy
msgid "RPC Call Mode"
-msgstr "Esnetme Åžekli"
+msgstr "RPC çağrı modu"
#: modules/visual_script/visual_script_func_nodes.cpp
msgid "Subtract %s"
@@ -23138,7 +23148,7 @@ msgstr "Küçük harf"
#: scene/3d/physics_joint.cpp
msgid "Motor"
-msgstr ""
+msgstr "Motor"
#: scene/3d/physics_joint.cpp
#, fuzzy
@@ -23771,6 +23781,16 @@ msgstr "Hata"
msgid "AABB"
msgstr ""
+#: scene/3d/visual_instance.cpp
+#, fuzzy
+msgid "Sorting"
+msgstr "Sırala"
+
+#: scene/3d/visual_instance.cpp
+#, fuzzy
+msgid "Use AABB Center"
+msgstr "Çevreyi Kullan"
+
#: scene/3d/visual_instance.cpp scene/resources/navigation_mesh.cpp
#, fuzzy
msgid "Geometry"
diff --git a/editor/translations/uk.po b/editor/translations/uk.po
index 07cfe5b6b1..f9a6c787a5 100644
--- a/editor/translations/uk.po
+++ b/editor/translations/uk.po
@@ -30,8 +30,8 @@ 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-09-27 21:37+0000\n"
-"Last-Translator: Teashrock <kajitsu22@gmail.com>\n"
+"PO-Revision-Date: 2022-10-03 12:44+0000\n"
+"Last-Translator: Yuri Chornoivan <yurchor@ukr.net>\n"
"Language-Team: Ukrainian <https://hosted.weblate.org/projects/godot-engine/"
"godot/uk/>\n"
"Language: uk\n"
@@ -12804,9 +12804,10 @@ msgstr "Параметри прилипаннÑ"
#: scene/2d/path_2d.cpp scene/2d/polygon_2d.cpp scene/2d/sprite.cpp
#: scene/3d/cpu_particles.cpp scene/3d/label_3d.cpp scene/3d/path.cpp
#: scene/3d/physics_body.cpp scene/3d/soft_body.cpp scene/3d/sprite_3d.cpp
-#: 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
+#: scene/3d/visual_instance.cpp 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
msgid "Offset"
msgstr "ЗміщеннÑ"
@@ -14218,16 +14219,17 @@ msgid "Invalid project path (changed anything?)."
msgstr "Ðекоректний шлÑÑ… до проєкту (щоÑÑŒ змінилоÑÑ?)."
#: editor/project_manager.cpp
+#, fuzzy
msgid ""
-"Couldn't load project.godot in project path (error %d). It may be missing or "
-"corrupted."
+"Couldn't load project at '%s' (error %d). It may be missing or corrupted."
msgstr ""
"Ðе вдалоÑÑ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶Ð¸Ñ‚Ð¸ project.godot у каталозі проєкту (помилка %d). "
"Можливо, файл вилучено або пошкоджено."
#: editor/project_manager.cpp
-msgid "Couldn't edit project.godot in project path."
-msgstr "Ðе вдалоÑÑ Ñ€ÐµÐ´Ð°Ð³ÑƒÐ²Ð°Ñ‚Ð¸ project.godot у каталозі проєкту."
+#, fuzzy
+msgid "Couldn't save project at '%s' (error %d)."
+msgstr "Ðе вдалоÑÑ Ð²Ñ–Ð´ÐºÑ€Ð¸Ñ‚Ð¸ проєкт у «%s»."
#: editor/project_manager.cpp
msgid "Couldn't create project.godot in project path."
@@ -20477,7 +20479,7 @@ msgstr "Режим змішуваннÑ"
#: scene/2d/canvas_item.cpp
msgid "Light Mode"
-msgstr "Праворуч за шириною"
+msgstr "Режим оÑвітленнÑ"
#: scene/2d/canvas_item.cpp
msgid "Particles Animation"
@@ -23232,6 +23234,16 @@ msgstr "МакÑимальна Ñила"
msgid "AABB"
msgstr ""
+#: scene/3d/visual_instance.cpp
+#, fuzzy
+msgid "Sorting"
+msgstr "Сортувати"
+
+#: scene/3d/visual_instance.cpp
+#, fuzzy
+msgid "Use AABB Center"
+msgstr "ВикориÑтовувати адаптивний"
+
#: scene/3d/visual_instance.cpp scene/resources/navigation_mesh.cpp
msgid "Geometry"
msgstr "ГеометріÑ"
diff --git a/editor/translations/ur_PK.po b/editor/translations/ur_PK.po
index d09218a600..1046f11996 100644
--- a/editor/translations/ur_PK.po
+++ b/editor/translations/ur_PK.po
@@ -12827,9 +12827,10 @@ msgstr ".تمام کا انتخاب"
#: scene/2d/path_2d.cpp scene/2d/polygon_2d.cpp scene/2d/sprite.cpp
#: scene/3d/cpu_particles.cpp scene/3d/label_3d.cpp scene/3d/path.cpp
#: scene/3d/physics_body.cpp scene/3d/soft_body.cpp scene/3d/sprite_3d.cpp
-#: 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
+#: scene/3d/visual_instance.cpp 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
msgid "Offset"
msgstr ""
@@ -14217,12 +14218,11 @@ msgstr ""
#: editor/project_manager.cpp
msgid ""
-"Couldn't load project.godot in project path (error %d). It may be missing or "
-"corrupted."
+"Couldn't load project at '%s' (error %d). It may be missing or corrupted."
msgstr ""
#: editor/project_manager.cpp
-msgid "Couldn't edit project.godot in project path."
+msgid "Couldn't save project at '%s' (error %d)."
msgstr ""
#: editor/project_manager.cpp
@@ -23156,6 +23156,15 @@ msgstr ""
msgid "AABB"
msgstr ""
+#: scene/3d/visual_instance.cpp
+#, fuzzy
+msgid "Sorting"
+msgstr ".تمام کا انتخاب"
+
+#: scene/3d/visual_instance.cpp
+msgid "Use AABB Center"
+msgstr ""
+
#: scene/3d/visual_instance.cpp scene/resources/navigation_mesh.cpp
msgid "Geometry"
msgstr ""
diff --git a/editor/translations/vi.po b/editor/translations/vi.po
index 2a0fadcf9f..b4a5f4494b 100644
--- a/editor/translations/vi.po
+++ b/editor/translations/vi.po
@@ -22,13 +22,14 @@
# Hung <hungthitkhia@gmail.com>, 2021.
# Paweł Fertyk <pfertyk@pfertyk.me>, 2022.
# MInhTriet <luckyblockblack@gmail.com>, 2022.
+# Nhật Huy <nhat.huy.7996@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-08-17 18:20+0000\n"
-"Last-Translator: MInhTriet <luckyblockblack@gmail.com>\n"
+"PO-Revision-Date: 2022-11-30 15:16+0000\n"
+"Last-Translator: Nhật Huy <nhat.huy.7996@gmail.com>\n"
"Language-Team: Vietnamese <https://hosted.weblate.org/projects/godot-engine/"
"godot/vi/>\n"
"Language: vi\n"
@@ -36,7 +37,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.14-dev\n"
+"X-Generator: Weblate 4.15-dev\n"
#: core/bind/core_bind.cpp main/main.cpp
msgid "Tablet Driver"
@@ -63,9 +64,8 @@ msgid "V-Sync Via Compositor"
msgstr "V-Sync thông qua Compositor"
#: core/bind/core_bind.cpp main/main.cpp
-#, fuzzy
msgid "Delta Smoothing"
-msgstr "Delta smoothing"
+msgstr "Dealta smooth"
#: core/bind/core_bind.cpp
msgid "Low Processor Usage Mode"
@@ -162,9 +162,8 @@ msgid "Target FPS"
msgstr "FPS cần đạt tới"
#: core/bind/core_bind.cpp
-#, fuzzy
msgid "Time Scale"
-msgstr "Nút TimeScale"
+msgstr "độ giãn nở thá»i gian"
#: core/bind/core_bind.cpp main/main.cpp
#, fuzzy
@@ -13042,9 +13041,10 @@ msgstr "Tùy chá»n Dính"
#: scene/2d/path_2d.cpp scene/2d/polygon_2d.cpp scene/2d/sprite.cpp
#: scene/3d/cpu_particles.cpp scene/3d/label_3d.cpp scene/3d/path.cpp
#: scene/3d/physics_body.cpp scene/3d/soft_body.cpp scene/3d/sprite_3d.cpp
-#: 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
+#: scene/3d/visual_instance.cpp 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 "Äá»™ dá»i:"
@@ -14457,16 +14457,17 @@ msgid "Invalid project path (changed anything?)."
msgstr "ÄÆ°á»ng dẫn dá»± án không hợp lệ (bạn có thay đổi Ä‘iá»u gì?)."
#: editor/project_manager.cpp
+#, fuzzy
msgid ""
-"Couldn't load project.godot in project path (error %d). It may be missing or "
-"corrupted."
+"Couldn't load project at '%s' (error %d). It may be missing or corrupted."
msgstr ""
"Không thể nạp 'project.godot' trong đưá»ng dẫn dá»± án (lá»—i %d). Nó có thể bị "
"thiếu hoặc đã há»ng."
#: editor/project_manager.cpp
-msgid "Couldn't edit project.godot in project path."
-msgstr "Không thể chỉnh sá»­a 'project.godot' trong đưá»ng dẫn dá»± án."
+#, fuzzy
+msgid "Couldn't save project at '%s' (error %d)."
+msgstr "Không thể mở dự án tại '%s'."
#: editor/project_manager.cpp
msgid "Couldn't create project.godot in project path."
@@ -23932,6 +23933,15 @@ msgstr "Lá»—i"
msgid "AABB"
msgstr ""
+#: scene/3d/visual_instance.cpp
+#, fuzzy
+msgid "Sorting"
+msgstr "Sắp xếp"
+
+#: scene/3d/visual_instance.cpp
+msgid "Use AABB Center"
+msgstr ""
+
#: scene/3d/visual_instance.cpp scene/resources/navigation_mesh.cpp
#, fuzzy
msgid "Geometry"
diff --git a/editor/translations/zh_CN.po b/editor/translations/zh_CN.po
index 1aeaea7087..52f072e946 100644
--- a/editor/translations/zh_CN.po
+++ b/editor/translations/zh_CN.po
@@ -84,12 +84,15 @@
# nitenook <admin@alterbaum.net>, 2021.
# jker <cxgmfy@163.com>, 2021.
# Ankar <1511276198@qq.com>, 2022.
+# 风é’å±± <idleman@yeah.net>, 2022.
+# 1104 EXSPIRAVIT_ <m18621006730@gmail.com>, 2022.
+# ChairC <974833488@qq.com>, 2022.
msgid ""
msgstr ""
"Project-Id-Version: Chinese (Simplified) (Godot Engine)\n"
"Report-Msgid-Bugs-To: https://github.com/godotengine/godot\n"
"POT-Creation-Date: 2018-01-20 12:15+0200\n"
-"PO-Revision-Date: 2022-09-22 15:26+0000\n"
+"PO-Revision-Date: 2022-12-05 08:51+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 +101,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.14.1\n"
+"X-Generator: Weblate 4.15-dev\n"
#: core/bind/core_bind.cpp main/main.cpp
msgid "Tablet Driver"
@@ -142,11 +145,11 @@ msgstr "å±å¹•常亮"
#: core/bind/core_bind.cpp
msgid "Min Window Size"
-msgstr "çª—å£æœ€å°å¤§å°"
+msgstr "最å°çª—å£å¤§å°"
#: core/bind/core_bind.cpp
msgid "Max Window Size"
-msgstr "çª—å£æœ€å¤§å¤§å°"
+msgstr "最大窗å£å¤§å°"
#: core/bind/core_bind.cpp
msgid "Screen Orientation"
@@ -4148,7 +4151,7 @@ msgstr ""
#: editor/editor_node.cpp
msgid "Scene '%s' has broken dependencies:"
-msgstr "场景 “%s†的ä¾èµ–已被破å:"
+msgstr "场景 “%s†的ä¾èµ–å·²æŸå:"
#: editor/editor_node.cpp
msgid "Clear Recent Scenes"
@@ -5637,12 +5640,12 @@ msgstr "选择框颜色"
#: editor/editor_settings.cpp editor/plugins/path_editor_plugin.cpp
#: editor/spatial_editor_gizmos.cpp modules/csg/csg_gizmos.cpp
msgid "3D Gizmos"
-msgstr "3D 控制器"
+msgstr "3D å°å·¥å…·"
#: editor/editor_settings.cpp editor/plugins/path_editor_plugin.cpp
#: editor/spatial_editor_gizmos.cpp modules/csg/csg_gizmos.cpp
msgid "Gizmo Colors"
-msgstr "控制器颜色"
+msgstr "å°å·¥å…·é¢œè‰²"
#: editor/editor_settings.cpp
msgid "Instanced"
@@ -7920,7 +7923,7 @@ msgstr "强制用白色调和"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Include Gizmos (3D)"
-msgstr "包括控制器(3D)"
+msgstr "包括å°å·¥å…·ï¼ˆ3D)"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Pin AnimationPlayer"
@@ -8439,7 +8442,7 @@ msgstr "åˆ›å»ºå…‰ç…§è´´å›¾å¤±è´¥ï¼Œåˆ‡ç¡®ä¿æ–‡ä»¶æ˜¯å¯å†™çš„。"
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid "Failed determining lightmap size. Maximum lightmap size too small?"
-msgstr "无法确定光照贴图大å°ã€‚最大光照贴图大å°å¤ªå°ï¼Ÿ"
+msgstr "无法确定光照贴图大å°ã€‚最大光照贴图尺寸太å°ï¼Ÿ"
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
@@ -10984,7 +10987,7 @@ msgstr "查看环境"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "View Gizmos"
-msgstr "查看控制器"
+msgstr "查看å°å·¥å…·"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "View Information"
@@ -11090,9 +11093,9 @@ msgid ""
msgstr ""
"点击以切æ¢å¯è§çжæ€ã€‚\n"
"\n"
-"ç眼:控制器å¯è§ã€‚\n"
-"闭眼:控制器éšè—。\n"
-"åŠç眼:控制器也å¯ç©¿è¿‡ä¸é€æ˜Žçš„表é¢å¯è§ï¼ˆâ€œX å…‰â€ï¼‰ã€‚"
+"ç眼:å°å·¥å…·å¯è§ã€‚\n"
+"闭眼:å°å·¥å…·éšè—。\n"
+"åŠç眼:å°å·¥å…·ä¹Ÿå¯ç©¿è¿‡ä¸é€æ˜Žçš„表é¢å¯è§ï¼ˆâ€œX å…‰â€ï¼‰ã€‚"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Snap Nodes to Floor"
@@ -11224,7 +11227,7 @@ msgstr "4 个视窗"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Gizmos"
-msgstr "控制器"
+msgstr "å°å·¥å…·"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "View Origin"
@@ -11309,19 +11312,19 @@ 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
msgid "Show Viewport Rotation Gizmo"
-msgstr "显示视区旋转控制器"
+msgstr "显示视区旋转å°å·¥å…·"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Unnamed Gizmo"
-msgstr "æœªå‘½åæŽ§åˆ¶å™¨"
+msgstr "未命åå°å·¥å…·"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Create Mesh2D"
@@ -12636,9 +12639,10 @@ msgstr "å¸é™„选项"
#: scene/2d/path_2d.cpp scene/2d/polygon_2d.cpp scene/2d/sprite.cpp
#: scene/3d/cpu_particles.cpp scene/3d/label_3d.cpp scene/3d/path.cpp
#: scene/3d/physics_body.cpp scene/3d/soft_body.cpp scene/3d/sprite_3d.cpp
-#: 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
+#: scene/3d/visual_instance.cpp 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
msgid "Offset"
msgstr "åç§»"
@@ -14006,15 +14010,16 @@ msgid "Invalid project path (changed anything?)."
msgstr "项目路径无效(被外部修改?)。"
#: editor/project_manager.cpp
+#, fuzzy
msgid ""
-"Couldn't load project.godot in project path (error %d). It may be missing or "
-"corrupted."
+"Couldn't load project at '%s' (error %d). It may be missing or corrupted."
msgstr ""
"无法在项目路径中加载 project.godot 文件(错误 %d)。该文件å¯èƒ½ç¼ºå¤±æˆ–å·²æŸå。"
#: editor/project_manager.cpp
-msgid "Couldn't edit project.godot in project path."
-msgstr "无法在项目路径下编辑 project.godot 文件。"
+#, fuzzy
+msgid "Couldn't save project at '%s' (error %d)."
+msgstr "无法打开ä½äºŽâ€œ%sâ€çš„项目。"
#: editor/project_manager.cpp
msgid "Couldn't create project.godot in project path."
@@ -16418,7 +16423,7 @@ msgstr "添加架构项"
#: modules/gdnative/gdnative_library_editor_plugin.cpp
msgid "GDNativeLibrary"
-msgstr "GDNative 库"
+msgstr "GDNativeLibrary"
#: modules/gdnative/gdnative_library_singleton_editor.cpp
msgid "Enabled GDNative Singleton"
@@ -20691,7 +20696,7 @@ msgstr "NavigationAgent2D åªèƒ½åœ¨ç»§æ‰¿ Node2D 的父节点下使用。"
#: scene/2d/navigation_obstacle_2d.cpp scene/3d/navigation_obstacle.cpp
msgid "Estimate Radius"
-msgstr "估计åŠå¾„"
+msgstr "ä¼°ç®—åŠå¾„"
#: scene/2d/navigation_obstacle_2d.cpp
msgid ""
@@ -21033,7 +21038,7 @@ msgstr "内部顶点数"
#: scene/2d/position_2d.cpp
msgid "Gizmo Extents"
-msgstr "控制器大å°"
+msgstr "å°å·¥å…·èŒƒå›´"
#: scene/2d/ray_cast_2d.cpp scene/3d/ray_cast.cpp
msgid "Exclude Parent"
@@ -22607,7 +22612,7 @@ msgstr "矩阵"
#: scene/3d/spatial.cpp
msgid "Gizmo"
-msgstr "控制器"
+msgstr "å°å·¥å…·"
#: scene/3d/spatial_velocity_tracker.cpp
msgid "Track Physics Step"
@@ -22693,6 +22698,16 @@ msgstr "最大力度"
msgid "AABB"
msgstr "AABB"
+#: scene/3d/visual_instance.cpp
+#, fuzzy
+msgid "Sorting"
+msgstr "排åº"
+
+#: scene/3d/visual_instance.cpp
+#, fuzzy
+msgid "Use AABB Center"
+msgstr "使用环境光"
+
#: scene/3d/visual_instance.cpp scene/resources/navigation_mesh.cpp
msgid "Geometry"
msgstr "几何体"
@@ -25193,7 +25208,7 @@ msgstr "亮度"
#: scene/resources/environment.cpp
msgid "Saturation"
-msgstr "对比度"
+msgstr "饱和度"
#: scene/resources/environment.cpp
msgid "Color Correction"
diff --git a/editor/translations/zh_HK.po b/editor/translations/zh_HK.po
index f8529ea3ca..8af64cfc4e 100644
--- a/editor/translations/zh_HK.po
+++ b/editor/translations/zh_HK.po
@@ -13397,9 +13397,10 @@ msgstr "é¸é …"
#: scene/2d/path_2d.cpp scene/2d/polygon_2d.cpp scene/2d/sprite.cpp
#: scene/3d/cpu_particles.cpp scene/3d/label_3d.cpp scene/3d/path.cpp
#: scene/3d/physics_body.cpp scene/3d/soft_body.cpp scene/3d/sprite_3d.cpp
-#: 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
+#: scene/3d/visual_instance.cpp 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
msgid "Offset"
msgstr ""
@@ -14821,13 +14822,13 @@ msgstr ""
#: editor/project_manager.cpp
msgid ""
-"Couldn't load project.godot in project path (error %d). It may be missing or "
-"corrupted."
+"Couldn't load project at '%s' (error %d). It may be missing or corrupted."
msgstr ""
#: editor/project_manager.cpp
-msgid "Couldn't edit project.godot in project path."
-msgstr ""
+#, fuzzy
+msgid "Couldn't save project at '%s' (error %d)."
+msgstr "ä¸èƒ½é€£æŽ¥ã€‚"
#: editor/project_manager.cpp
msgid "Couldn't create project.godot in project path."
@@ -24070,6 +24071,15 @@ msgstr "錯誤!"
msgid "AABB"
msgstr ""
+#: scene/3d/visual_instance.cpp
+#, fuzzy
+msgid "Sorting"
+msgstr "排åºï¼š"
+
+#: scene/3d/visual_instance.cpp
+msgid "Use AABB Center"
+msgstr ""
+
#: scene/3d/visual_instance.cpp scene/resources/navigation_mesh.cpp
#, fuzzy
msgid "Geometry"
diff --git a/editor/translations/zh_TW.po b/editor/translations/zh_TW.po
index 4cd08539e4..dd54885310 100644
--- a/editor/translations/zh_TW.po
+++ b/editor/translations/zh_TW.po
@@ -43,8 +43,8 @@ msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"Report-Msgid-Bugs-To: https://github.com/godotengine/godot\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2022-09-27 21:37+0000\n"
-"Last-Translator: nitenook <admin@alterbaum.net>\n"
+"PO-Revision-Date: 2022-10-16 07:25+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"
@@ -52,7 +52,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.14.1\n"
+"X-Generator: Weblate 4.15-dev\n"
#: core/bind/core_bind.cpp main/main.cpp
msgid "Tablet Driver"
@@ -4148,7 +4148,7 @@ msgstr "刪除é…ç½®"
#: editor/editor_node.cpp editor/import_dock.cpp
#: editor/script_create_dialog.cpp
msgid "Default"
-msgstr "默èª"
+msgstr "é è¨­"
#: editor/editor_node.cpp editor/editor_resource_picker.cpp
#: editor/plugins/script_editor_plugin.cpp editor/property_editor.cpp
@@ -12591,9 +12591,10 @@ msgstr "å¸é™„é¸é …"
#: scene/2d/path_2d.cpp scene/2d/polygon_2d.cpp scene/2d/sprite.cpp
#: scene/3d/cpu_particles.cpp scene/3d/label_3d.cpp scene/3d/path.cpp
#: scene/3d/physics_body.cpp scene/3d/soft_body.cpp scene/3d/sprite_3d.cpp
-#: 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
+#: scene/3d/visual_instance.cpp 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
msgid "Offset"
msgstr "åç§»"
@@ -13962,14 +13963,15 @@ msgid "Invalid project path (changed anything?)."
msgstr "䏿­£ç¢ºçš„專案路徑(有修改了什麼嗎?)。"
#: editor/project_manager.cpp
+#, fuzzy
msgid ""
-"Couldn't load project.godot in project path (error %d). It may be missing or "
-"corrupted."
+"Couldn't load project at '%s' (error %d). It may be missing or corrupted."
msgstr "無法自專案路徑內載入 project.godot(錯誤 %d)。檔案å¯èƒ½éºå¤±æˆ–ææ¯€ã€‚"
#: editor/project_manager.cpp
-msgid "Couldn't edit project.godot in project path."
-msgstr "無法在專案路徑中編輯 project.godot。"
+#, fuzzy
+msgid "Couldn't save project at '%s' (error %d)."
+msgstr "無法於「%sã€æ‰“開專案。"
#: editor/project_manager.cpp
msgid "Couldn't create project.godot in project path."
@@ -17240,7 +17242,7 @@ msgstr "ç™¼ç¾æœ¬åœ°é€šè¨ŠåŸ "
#: modules/upnp/upnp.cpp
msgid "Discover IPv6"
-msgstr "DiscoverIPv6"
+msgstr "Discover IPv6"
#: modules/upnp/upnp_device.cpp
#, fuzzy
@@ -18168,7 +18170,7 @@ 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."
@@ -18201,7 +18203,7 @@ msgstr "剪下節點"
#: platform/android/export/export_plugin.cpp
msgid "Use Custom Build"
-msgstr ""
+msgstr "使用自定義建構"
#: platform/android/export/export_plugin.cpp
#, fuzzy
@@ -18234,7 +18236,7 @@ msgstr "除錯工具"
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
msgid "Debug Password"
-msgstr ""
+msgstr "åµéŒ¯å¯†ç¢¼"
#: platform/android/export/export_plugin.cpp
#, fuzzy
@@ -18248,7 +18250,7 @@ msgstr "發行"
#: platform/android/export/export_plugin.cpp
msgid "One Click Deploy"
-msgstr ""
+msgstr "一éµéƒ¨ç½²"
#: platform/android/export/export_plugin.cpp
#, fuzzy
@@ -18257,7 +18259,7 @@ msgstr "嵿Ÿ¥å‰ä¸€å€‹å¯¦é«”"
#: platform/android/export/export_plugin.cpp
msgid "Code"
-msgstr ""
+msgstr "程å¼ç¢¼"
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
#, fuzzy
@@ -18279,7 +18281,7 @@ msgstr "åˆ†é¡žç‚ºéŠæˆ²"
#: platform/android/export/export_plugin.cpp
msgid "Retain Data On Uninstall"
-msgstr ""
+msgstr "å–æ¶ˆå®‰è£æ™‚ä¿ç•™è³‡æ–™"
#: platform/android/export/export_plugin.cpp
#, fuzzy
@@ -18312,11 +18314,11 @@ msgstr "正在打包"
#: platform/android/export/export_plugin.cpp
msgid "Hand Tracking Frequency"
-msgstr ""
+msgstr "手勢追蹤頻率"
#: platform/android/export/export_plugin.cpp
msgid "Passthrough"
-msgstr ""
+msgstr "ç©¿é€"
#: platform/android/export/export_plugin.cpp
#, fuzzy
@@ -18350,7 +18352,7 @@ msgstr "使用者界é¢"
#: platform/android/export/export_plugin.cpp
msgid "Allow"
-msgstr ""
+msgstr "å…許"
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
#, fuzzy
@@ -18368,7 +18370,7 @@ msgstr "設定表示å¼"
#: platform/android/export/export_plugin.cpp
msgid "Salt"
-msgstr ""
+msgstr "Salt"
#: platform/android/export/export_plugin.cpp
#, fuzzy
@@ -18488,6 +18490,10 @@ msgid ""
"Note that the singleton was also renamed from \"GodotPayments\" to "
"\"GodotGooglePlayBilling\"."
msgstr ""
+"「android/modulesã€å°ˆæ¡ˆè¨­å®šä¸­åŒ…å«äº†ç„¡æ•ˆçš„「GodotPaymentV3ã€ï¼ˆåœ¨ Godot 3.2.2 "
+"中已更改)。\n"
+"請將其更æ›ç‚ºç¬¬ä¸€æ–¹çš„「GodotGooglePlayBillingã€å¤–掛。\n"
+"請注æ„,該單例已從「GodotPaymentsã€æ›´æ”¹ç‚ºã€ŒGodotGooglePlayBillingã€ã€‚"
#: platform/android/export/export_plugin.cpp
msgid "\"Use Custom Build\" must be enabled to use the plugins."
@@ -18519,13 +18525,13 @@ 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 ""
+msgstr "ã€Œæœ€å° SDKã€æ‡‰ç‚ºæœ‰æ•ˆæ•´æ•¸ï¼Œä½†ç›®å‰å€¼ç‚ºç„¡æ•ˆçš„「%sã€ã€‚"
#: platform/android/export/export_plugin.cpp
msgid ""
"\"Min SDK\" cannot be lower than %d, which is the version needed by the "
"Godot library."
-msgstr ""
+msgstr "ã€Œæœ€å° SDKã€ä¸å¯ä½Žæ–¼ %d,因 Godot 函å¼åº«éœ€è¦è©²æœ€å°ç‰ˆæœ¬ã€‚"
#: platform/android/export/export_plugin.cpp
#, fuzzy
@@ -23175,6 +23181,16 @@ msgstr "錯誤"
msgid "AABB"
msgstr ""
+#: scene/3d/visual_instance.cpp
+#, fuzzy
+msgid "Sorting"
+msgstr "排åº"
+
+#: scene/3d/visual_instance.cpp
+#, fuzzy
+msgid "Use AABB Center"
+msgstr "使用環境通é“"
+
#: scene/3d/visual_instance.cpp scene/resources/navigation_mesh.cpp
#, fuzzy
msgid "Geometry"
diff --git a/gles3_builders.py b/gles3_builders.py
index 46ab1bbc03..0d0037dea1 100644
--- a/gles3_builders.py
+++ b/gles3_builders.py
@@ -20,6 +20,7 @@ class GLES3HeaderStruct:
self.texunit_names = []
self.ubos = []
self.ubo_names = []
+ self.feedbacks = []
self.vertex_included_files = []
self.fragment_included_files = []
@@ -168,6 +169,20 @@ def include_file_in_gles3_header(filename: str, header_data: GLES3HeaderStruct,
if not x in header_data.uniforms:
header_data.uniforms += [x]
+ if (line.strip().find("out ") == 0 or line.strip().find("flat ") == 0) and line.find("tfb:") != -1:
+ uline = line.replace("flat ", "")
+ uline = uline.replace("out ", "")
+ uline = uline.replace("highp ", "")
+ uline = uline.replace(";", "")
+ uline = uline[uline.find(" ") :].strip()
+
+ if uline.find("//") != -1:
+ name, bind = uline.split("//")
+ if bind.find("tfb:") != -1:
+ name = name.strip()
+ bind = bind.replace("tfb:", "").strip()
+ header_data.feedbacks += [(name, bind)]
+
line = line.replace("\r", "")
line = line.replace("\n", "")
@@ -240,11 +255,11 @@ def build_gles3_header(filename: str, include: str, class_suffix: str, header_da
defspec |= 1 << i
fd.write(
- "\t_FORCE_INLINE_ void version_bind_shader(RID p_version,ShaderVariant p_variant"
+ "\t_FORCE_INLINE_ bool version_bind_shader(RID p_version,ShaderVariant p_variant"
+ defvariant
+ ",uint64_t p_specialization="
+ str(defspec)
- + ") { _version_bind_shader(p_version,p_variant,p_specialization); }\n\n"
+ + ") { return _version_bind_shader(p_version,p_variant,p_specialization); }\n\n"
)
if header_data.uniforms:
@@ -278,7 +293,7 @@ def build_gles3_header(filename: str, include: str, class_suffix: str, header_da
+ defvariant
+ ",uint64_t p_specialization="
+ str(defspec)
- + ") { _FU glUniform1i(version_get_uniform(p_uniform,p_version,p_variant,p_specialization),p_value); }\n\n"
+ + ") { _FU glUniform1ui(version_get_uniform(p_uniform,p_version,p_variant,p_specialization),p_value); }\n\n"
)
fd.write(
"\t_FORCE_INLINE_ void version_set_uniform(Uniforms p_uniform, int8_t p_value,RID p_version,ShaderVariant p_variant"
@@ -292,7 +307,7 @@ def build_gles3_header(filename: str, include: str, class_suffix: str, header_da
+ defvariant
+ ",uint64_t p_specialization="
+ str(defspec)
- + ") { _FU glUniform1i(version_get_uniform(p_uniform,p_version,p_variant,p_specialization),p_value); }\n\n"
+ + ") { _FU glUniform1ui(version_get_uniform(p_uniform,p_version,p_variant,p_specialization),p_value); }\n\n"
)
fd.write(
"\t_FORCE_INLINE_ void version_set_uniform(Uniforms p_uniform, int16_t p_value,RID p_version,ShaderVariant p_variant"
@@ -306,7 +321,7 @@ def build_gles3_header(filename: str, include: str, class_suffix: str, header_da
+ defvariant
+ ",uint64_t p_specialization="
+ str(defspec)
- + ") { _FU glUniform1i(version_get_uniform(p_uniform,p_version,p_variant,p_specialization),p_value); }\n\n"
+ + ") { _FU glUniform1ui(version_get_uniform(p_uniform,p_version,p_variant,p_specialization),p_value); }\n\n"
)
fd.write(
"\t_FORCE_INLINE_ void version_set_uniform(Uniforms p_uniform, int32_t p_value,RID p_version,ShaderVariant p_variant"
@@ -497,6 +512,8 @@ def build_gles3_header(filename: str, include: str, class_suffix: str, header_da
else:
fd.write("\t\tstatic UBOPair *_ubo_pairs=nullptr;\n")
+ specializations_found = []
+
if header_data.specialization_names:
fd.write("\t\tstatic Specialization _spec_pairs[]={\n")
for i in range(len(header_data.specialization_names)):
@@ -507,10 +524,30 @@ def build_gles3_header(filename: str, include: str, class_suffix: str, header_da
defval = "false"
fd.write('\t\t\t{"' + header_data.specialization_names[i] + '",' + defval + "},\n")
+ specializations_found.append(header_data.specialization_names[i])
fd.write("\t\t};\n\n")
else:
fd.write("\t\tstatic Specialization *_spec_pairs=nullptr;\n")
+ feedback_count = 0
+
+ if header_data.feedbacks:
+
+ fd.write("\t\tstatic const Feedback _feedbacks[]={\n")
+ for x in header_data.feedbacks:
+ name = x[0]
+ spec = x[1]
+ if spec in specializations_found:
+ fd.write('\t\t\t{"' + name + '",' + str(1 << specializations_found.index(spec)) + "},\n")
+ else:
+ fd.write('\t\t\t{"' + name + '",0},\n')
+
+ feedback_count += 1
+
+ fd.write("\t\t};\n\n")
+ else:
+ fd.write("\t\tstatic const Feedback* _feedbacks=nullptr;\n")
+
fd.write("\t\tstatic const char _vertex_code[]={\n")
for x in header_data.vertex_lines:
for c in x:
@@ -535,6 +572,8 @@ def build_gles3_header(filename: str, include: str, class_suffix: str, header_da
+ ",_uniform_strings,"
+ str(len(header_data.ubos))
+ ",_ubo_pairs,"
+ + str(feedback_count)
+ + ",_feedbacks,"
+ str(len(header_data.texunits))
+ ",_texunit_pairs,"
+ str(len(header_data.specialization_names))
diff --git a/main/main.cpp b/main/main.cpp
index 0fce8e3d94..7e1fd38e14 100644
--- a/main/main.cpp
+++ b/main/main.cpp
@@ -36,8 +36,8 @@
#include "core/crypto/crypto.h"
#include "core/debugger/engine_debugger.h"
#include "core/extension/extension_api_dump.h"
-#include "core/extension/gdnative_interface_dump.gen.h"
-#include "core/extension/native_extension_manager.h"
+#include "core/extension/gdextension_interface_dump.gen.h"
+#include "core/extension/gdextension_manager.h"
#include "core/input/input.h"
#include "core/input/input_map.h"
#include "core/io/dir_access.h"
@@ -85,6 +85,7 @@
#endif
#ifdef TOOLS_ENABLED
+#include "editor/debugger/editor_debugger_node.h"
#include "editor/doc_data_class_path.gen.h"
#include "editor/doc_tools.h"
#include "editor/editor_node.h"
@@ -94,6 +95,7 @@
#include "editor/progress_dialog.h"
#include "editor/project_converter_3_to_4.h"
#include "editor/project_manager.h"
+#include "editor/register_editor_types.h"
#ifndef NO_EDITOR_SPLASH
#include "main/splash_editor.gen.h"
#endif
@@ -200,7 +202,7 @@ static MovieWriter *movie_writer = nullptr;
static bool disable_vsync = false;
static bool print_fps = false;
#ifdef TOOLS_ENABLED
-static bool dump_gdnative_interface = false;
+static bool dump_gdextension_interface = false;
static bool dump_extension_api = false;
#endif
bool profile_gpu = false;
@@ -309,29 +311,29 @@ void Main::print_help(const char *p_binary) {
OS::get_singleton()->print("\n");
OS::get_singleton()->print("General options:\n");
- OS::get_singleton()->print(" -h, --help Display this help message.\n");
- OS::get_singleton()->print(" --version Display the version string.\n");
- OS::get_singleton()->print(" -v, --verbose Use verbose stdout mode.\n");
- OS::get_singleton()->print(" -q, --quiet Quiet mode, silences stdout messages. Errors are still displayed.\n");
+ OS::get_singleton()->print(" -h, --help Display this help message.\n");
+ OS::get_singleton()->print(" --version Display the version string.\n");
+ OS::get_singleton()->print(" -v, --verbose Use verbose stdout mode.\n");
+ OS::get_singleton()->print(" -q, --quiet Quiet mode, silences stdout messages. Errors are still displayed.\n");
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");
+ 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");
- OS::get_singleton()->print(" --debug-server <uri> Start the editor debug server (<protocol>://<host/IP>[:<port>], e.g. tcp://127.0.0.1:6007)\n");
+ 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");
+ OS::get_singleton()->print(" --debug-server <uri> Start the editor debug server (<protocol>://<host/IP>[:<port>], e.g. tcp://127.0.0.1:6007)\n");
#endif
- OS::get_singleton()->print(" --quit Quit after the first iteration.\n");
- OS::get_singleton()->print(" -l, --language <locale> Use a specific locale (<locale> being a two-letter code).\n");
- OS::get_singleton()->print(" --path <directory> Path to a project (<directory> must contain a 'project.godot' file).\n");
- OS::get_singleton()->print(" -u, --upwards Scan folders upwards for project.godot file.\n");
- OS::get_singleton()->print(" --main-pack <file> Path to a pack (.pck) file to load.\n");
- OS::get_singleton()->print(" --render-thread <mode> Render thread mode ('unsafe', 'safe', 'separate').\n");
- OS::get_singleton()->print(" --remote-fs <address> Remote filesystem (<host/IP>[:<port>] address).\n");
- OS::get_singleton()->print(" --remote-fs-password <password> Password for remote filesystem.\n");
-
- OS::get_singleton()->print(" --audio-driver <driver> Audio driver [");
+ OS::get_singleton()->print(" --quit Quit after the first iteration.\n");
+ OS::get_singleton()->print(" -l, --language <locale> Use a specific locale (<locale> being a two-letter code).\n");
+ OS::get_singleton()->print(" --path <directory> Path to a project (<directory> must contain a 'project.godot' file).\n");
+ OS::get_singleton()->print(" -u, --upwards Scan folders upwards for project.godot file.\n");
+ OS::get_singleton()->print(" --main-pack <file> Path to a pack (.pck) file to load.\n");
+ OS::get_singleton()->print(" --render-thread <mode> Render thread mode ['unsafe', 'safe', 'separate'].\n");
+ OS::get_singleton()->print(" --remote-fs <address> Remote filesystem (<host/IP>[:<port>] address).\n");
+ OS::get_singleton()->print(" --remote-fs-password <password> Password for remote filesystem.\n");
+
+ OS::get_singleton()->print(" --audio-driver <driver> Audio driver [");
for (int i = 0; i < AudioDriverManager::get_driver_count(); i++) {
if (i > 0) {
OS::get_singleton()->print(", ");
@@ -340,7 +342,7 @@ void Main::print_help(const char *p_binary) {
}
OS::get_singleton()->print("].\n");
- OS::get_singleton()->print(" --display-driver <driver> Display driver (and rendering driver) [");
+ OS::get_singleton()->print(" --display-driver <driver> Display driver (and rendering driver) [");
for (int i = 0; i < DisplayServer::get_create_function_count(); i++) {
if (i > 0) {
OS::get_singleton()->print(", ");
@@ -357,72 +359,76 @@ void Main::print_help(const char *p_binary) {
}
OS::get_singleton()->print("].\n");
- OS::get_singleton()->print(" --rendering-method <renderer> Renderer name. Requires driver support.\n");
- OS::get_singleton()->print(" --rendering-driver <driver> Rendering driver (depends on display driver).\n");
- OS::get_singleton()->print(" --gpu-index <device_index> Use a specific GPU (run with --verbose to get available device list).\n");
- OS::get_singleton()->print(" --text-driver <driver> Text driver (Fonts, BiDi, shaping)\n");
- OS::get_singleton()->print(" --tablet-driver <driver> Pen tablet input driver.\n");
- OS::get_singleton()->print(" --headless Enable headless mode (--display-driver headless --audio-driver Dummy). Useful for servers and with --script.\n");
- OS::get_singleton()->print(" --write-movie <file> Run the engine in a way that a movie is written (by default .avi MJPEG). Fixed FPS is forced when enabled, but can be used to change movie FPS. Disabling vsync can speed up movie writing but makes interaction more difficult.\n");
- OS::get_singleton()->print(" --disable-vsync Force disabling of vsync. Run the engine in a way that a movie is written (by default .avi MJPEG). Fixed FPS is forced when enabled, but can be used to change movie FPS.\n");
+ OS::get_singleton()->print(" --rendering-method <renderer> Renderer name. Requires driver support.\n");
+ OS::get_singleton()->print(" --rendering-driver <driver> Rendering driver (depends on display driver).\n");
+ OS::get_singleton()->print(" --gpu-index <device_index> Use a specific GPU (run with --verbose to get available device list).\n");
+ OS::get_singleton()->print(" --text-driver <driver> Text driver (Fonts, BiDi, shaping).\n");
+ OS::get_singleton()->print(" --tablet-driver <driver> Pen tablet input driver.\n");
+ OS::get_singleton()->print(" --headless Enable headless mode (--display-driver headless --audio-driver Dummy). Useful for servers and with --script.\n");
+ OS::get_singleton()->print(" --write-movie <file> Writes a video to the specified path (usually with .avi or .png extension).\n");
+ OS::get_singleton()->print(" --fixed-fps is forced when enabled, but it can be used to change movie FPS.\n");
+ OS::get_singleton()->print(" --disable-vsync can speed up movie writing but makes interaction more difficult.\n");
OS::get_singleton()->print("\n");
OS::get_singleton()->print("Display options:\n");
- OS::get_singleton()->print(" -f, --fullscreen Request fullscreen mode.\n");
- OS::get_singleton()->print(" -m, --maximized Request a maximized window.\n");
- OS::get_singleton()->print(" -w, --windowed Request windowed mode.\n");
- OS::get_singleton()->print(" -t, --always-on-top Request an always-on-top window.\n");
- 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(" -f, --fullscreen Request fullscreen mode.\n");
+ OS::get_singleton()->print(" -m, --maximized Request a maximized window.\n");
+ OS::get_singleton()->print(" -w, --windowed Request windowed mode.\n");
+ OS::get_singleton()->print(" -t, --always-on-top Request an always-on-top window.\n");
+ 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 (Extended Reality) mode ['default', 'off', 'on'].\n");
OS::get_singleton()->print("\n");
OS::get_singleton()->print("Debug options:\n");
- OS::get_singleton()->print(" -d, --debug Debug (local stdout debugger).\n");
- OS::get_singleton()->print(" -b, --breakpoints Breakpoint list as source::line comma-separated pairs, no spaces (use %%20 instead).\n");
- OS::get_singleton()->print(" --profiling Enable profiling in the script debugger.\n");
- OS::get_singleton()->print(" --gpu-profile Show a GPU profile of the tasks that took the most time during frame rendering.\n");
- OS::get_singleton()->print(" --gpu-validation Enable graphics API validation layers for debugging.\n");
+ OS::get_singleton()->print(" -d, --debug Debug (local stdout debugger).\n");
+ OS::get_singleton()->print(" -b, --breakpoints Breakpoint list as source::line comma-separated pairs, no spaces (use %%20 instead).\n");
+ OS::get_singleton()->print(" --profiling Enable profiling in the script debugger.\n");
+ OS::get_singleton()->print(" --gpu-profile Show a GPU profile of the tasks that took the most time during frame rendering.\n");
+ OS::get_singleton()->print(" --gpu-validation Enable graphics API validation layers for debugging.\n");
#if DEBUG_ENABLED
- OS::get_singleton()->print(" --gpu-abort Abort on graphics API usage errors (usually validation layer errors). May help see the problem if your system freezes.\n");
+ OS::get_singleton()->print(" --gpu-abort Abort on graphics API usage errors (usually validation layer errors). May help see the problem if your system freezes.\n");
#endif
- OS::get_singleton()->print(" --remote-debug <uri> Remote debug (<protocol>://<host/IP>[:<port>], e.g. tcp://127.0.0.1:6007).\n");
+ OS::get_singleton()->print(" --remote-debug <uri> Remote debug (<protocol>://<host/IP>[:<port>], e.g. tcp://127.0.0.1:6007).\n");
#if defined(DEBUG_ENABLED)
- OS::get_singleton()->print(" --debug-collisions Show collision shapes when running the scene.\n");
- OS::get_singleton()->print(" --debug-paths Show path lines when running the scene.\n");
- OS::get_singleton()->print(" --debug-navigation Show navigation polygons when running the scene.\n");
- OS::get_singleton()->print(" --debug-stringnames Print all StringName allocations to stdout when the engine quits.\n");
+ OS::get_singleton()->print(" --debug-collisions Show collision shapes when running the scene.\n");
+ OS::get_singleton()->print(" --debug-paths Show path lines when running the scene.\n");
+ OS::get_singleton()->print(" --debug-navigation Show navigation polygons when running the scene.\n");
+ OS::get_singleton()->print(" --debug-stringnames Print all StringName allocations to stdout when the engine quits.\n");
#endif
- OS::get_singleton()->print(" --frame-delay <ms> Simulate high CPU load (delay each frame by <ms> milliseconds).\n");
- OS::get_singleton()->print(" --time-scale <scale> Force time scale (higher values are faster, 1.0 is normal speed).\n");
- OS::get_singleton()->print(" --disable-render-loop Disable render loop so rendering only occurs when called explicitly from script.\n");
- OS::get_singleton()->print(" --disable-crash-handler Disable crash handler when supported by the platform code.\n");
- OS::get_singleton()->print(" --fixed-fps <fps> Force a fixed number of frames per second. This setting disables real-time synchronization.\n");
- OS::get_singleton()->print(" --print-fps Print the frames per second to the stdout.\n");
+ OS::get_singleton()->print(" --frame-delay <ms> Simulate high CPU load (delay each frame by <ms> milliseconds).\n");
+ OS::get_singleton()->print(" --time-scale <scale> Force time scale (higher values are faster, 1.0 is normal speed).\n");
+ OS::get_singleton()->print(" --disable-vsync Forces disabling of vertical synchronization, even if enabled in the project settings. Does not override driver-level V-Sync enforcement.\n");
+ OS::get_singleton()->print(" --disable-render-loop Disable render loop so rendering only occurs when called explicitly from script.\n");
+ OS::get_singleton()->print(" --disable-crash-handler Disable crash handler when supported by the platform code.\n");
+ OS::get_singleton()->print(" --fixed-fps <fps> Force a fixed number of frames per second. This setting disables real-time synchronization.\n");
+ OS::get_singleton()->print(" --print-fps Print the frames per second to the stdout.\n");
OS::get_singleton()->print("\n");
OS::get_singleton()->print("Standalone tools:\n");
- OS::get_singleton()->print(" -s, --script <script> Run a script.\n");
- OS::get_singleton()->print(" --check-only Only parse for errors and quit (use with --script).\n");
+ OS::get_singleton()->print(" -s, --script <script> Run a script.\n");
+ OS::get_singleton()->print(" --check-only Only parse for errors and quit (use with --script).\n");
#ifdef TOOLS_ENABLED
- OS::get_singleton()->print(" --export-release <preset> <path> Export the project in release mode using the given preset and output path. The preset name should match one defined in export_presets.cfg.\n");
- OS::get_singleton()->print(" <path> should be absolute or relative to the project directory, and include the filename for the binary (e.g. 'builds/game.exe').\n");
- OS::get_singleton()->print(" The target directory must exist.\n");
- OS::get_singleton()->print(" --export-debug <preset> <path> Export the project in debug mode using the given preset and output path. The preset name should match one defined in export_presets.cfg.\n");
- OS::get_singleton()->print(" --export-pack <preset> <path> Export the project data only using the given preset and output path. The <path> extension determines whether it will be in PCK or ZIP format.\n");
- OS::get_singleton()->print(" --convert-3to4 [<max_file_kb>] [<max_line_size>] Converts project from Godot 3.x to Godot 4.x.\n");
- OS::get_singleton()->print(" --validate-conversion-3to4 [<max_file_kb>] [<max_line_size>] Shows what elements will be renamed when converting project from Godot 3.x to Godot 4.x.\n");
- OS::get_singleton()->print(" --doctool [<path>] Dump the engine API reference to the given <path> (defaults to current dir) in XML format, merging if existing files are found.\n");
- OS::get_singleton()->print(" --no-docbase Disallow dumping the base types (used with --doctool).\n");
- OS::get_singleton()->print(" --build-solutions Build the scripting solutions (e.g. for C# projects). Implies --editor and requires a valid project to edit.\n");
- OS::get_singleton()->print(" --dump-gdextension-interface Generate GDExtension header file 'gdnative_interface.h' in the current folder. This file is the base file required to implement a GDExtension.\n");
- OS::get_singleton()->print(" --dump-extension-api Generate JSON dump of the Godot API for GDExtension bindings named 'extension_api.json' in the current folder.\n");
- OS::get_singleton()->print(" --startup-benchmark Benchmark the startup time and print it to console.\n");
- OS::get_singleton()->print(" --startup-benchmark-file <path> Benchmark the startup time and save it to a given file in JSON format.\n");
+ OS::get_singleton()->print(" --export-release <preset> <path> Export the project in release mode using the given preset and output path. The preset name should match one defined in export_presets.cfg.\n");
+ OS::get_singleton()->print(" <path> should be absolute or relative to the project directory, and include the filename for the binary (e.g. 'builds/game.exe').\n");
+ OS::get_singleton()->print(" The target directory must exist.\n");
+ OS::get_singleton()->print(" --export-debug <preset> <path> Export the project in debug mode using the given preset and output path. See --export-release description for other considerations.\n");
+ OS::get_singleton()->print(" --export-pack <preset> <path> Export the project data only using the given preset and output path. The <path> extension determines whether it will be in PCK or ZIP format.\n");
+ OS::get_singleton()->print(" --convert-3to4 [<max_file_kb>] [<max_line_size>]\n");
+ OS::get_singleton()->print(" Converts project from Godot 3.x to Godot 4.x.\n");
+ OS::get_singleton()->print(" --validate-conversion-3to4 [<max_file_kb>] [<max_line_size>]\n");
+ OS::get_singleton()->print(" Shows what elements will be renamed when converting project from Godot 3.x to Godot 4.x.\n");
+ OS::get_singleton()->print(" --doctool [<path>] Dump the engine API reference to the given <path> (defaults to current dir) in XML format, merging if existing files are found.\n");
+ OS::get_singleton()->print(" --no-docbase Disallow dumping the base types (used with --doctool).\n");
+ OS::get_singleton()->print(" --build-solutions Build the scripting solutions (e.g. for C# projects). Implies --editor and requires a valid project to edit.\n");
+ OS::get_singleton()->print(" --dump-gdextension-interface Generate GDExtension header file 'gdextension_interface.h' in the current folder. This file is the base file required to implement a GDExtension.\n");
+ OS::get_singleton()->print(" --dump-extension-api Generate JSON dump of the Godot API for GDExtension bindings named 'extension_api.json' in the current folder.\n");
+ OS::get_singleton()->print(" --startup-benchmark Benchmark the startup time and print it to console.\n");
+ OS::get_singleton()->print(" --startup-benchmark-file <path> Benchmark the startup time and save it to a given file in JSON format.\n");
#ifdef TESTS_ENABLED
- OS::get_singleton()->print(" --test [--help] Run unit tests. Use --test --help for more information.\n");
+ OS::get_singleton()->print(" --test [--help] Run unit tests. Use --test --help for more information.\n");
#endif
#endif
OS::get_singleton()->print("\n");
@@ -467,7 +473,7 @@ Error Main::test_setup() {
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);
+ GDExtensionManager::get_singleton()->initialize_extensions(GDExtension::INITIALIZATION_LEVEL_SERVERS);
translation_server->setup(); //register translations, load them, etc.
if (!locale.is_empty()) {
@@ -482,14 +488,14 @@ Error Main::test_setup() {
register_driver_types();
initialize_modules(MODULE_INITIALIZATION_LEVEL_SCENE);
- NativeExtensionManager::get_singleton()->initialize_extensions(NativeExtension::INITIALIZATION_LEVEL_SCENE);
+ GDExtensionManager::get_singleton()->initialize_extensions(GDExtension::INITIALIZATION_LEVEL_SCENE);
#ifdef TOOLS_ENABLED
ClassDB::set_current_api(ClassDB::API_EDITOR);
- EditorNode::register_editor_types();
+ register_editor_types();
initialize_modules(MODULE_INITIALIZATION_LEVEL_EDITOR);
- NativeExtensionManager::get_singleton()->initialize_extensions(NativeExtension::INITIALIZATION_LEVEL_EDITOR);
+ GDExtensionManager::get_singleton()->initialize_extensions(GDExtension::INITIALIZATION_LEVEL_EDITOR);
ClassDB::set_current_api(ClassDB::API_CORE);
#endif
@@ -531,18 +537,22 @@ Error Main::test_setup() {
void Main::test_cleanup() {
ERR_FAIL_COND(!_start_success);
+ for (int i = 0; i < TextServerManager::get_singleton()->get_interface_count(); i++) {
+ TextServerManager::get_singleton()->get_interface(i)->cleanup();
+ }
+
EngineDebugger::deinitialize();
ResourceLoader::remove_custom_loaders();
ResourceSaver::remove_custom_savers();
#ifdef TOOLS_ENABLED
- NativeExtensionManager::get_singleton()->deinitialize_extensions(NativeExtension::INITIALIZATION_LEVEL_EDITOR);
+ GDExtensionManager::get_singleton()->deinitialize_extensions(GDExtension::INITIALIZATION_LEVEL_EDITOR);
uninitialize_modules(MODULE_INITIALIZATION_LEVEL_EDITOR);
- EditorNode::unregister_editor_types();
+ unregister_editor_types();
#endif
- NativeExtensionManager::get_singleton()->deinitialize_extensions(NativeExtension::INITIALIZATION_LEVEL_SCENE);
+ GDExtensionManager::get_singleton()->deinitialize_extensions(GDExtension::INITIALIZATION_LEVEL_SCENE);
uninitialize_modules(MODULE_INITIALIZATION_LEVEL_SCENE);
unregister_platform_apis();
unregister_driver_types();
@@ -550,7 +560,7 @@ void Main::test_cleanup() {
finalize_theme_db();
- NativeExtensionManager::get_singleton()->deinitialize_extensions(NativeExtension::INITIALIZATION_LEVEL_SERVERS);
+ GDExtensionManager::get_singleton()->deinitialize_extensions(GDExtension::INITIALIZATION_LEVEL_SERVERS);
uninitialize_modules(MODULE_INITIALIZATION_LEVEL_SERVERS);
unregister_server_types();
@@ -1053,8 +1063,8 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
// Register as an editor instance to use low-end fallback if relevant.
editor = true;
cmdline_tool = true;
- dump_gdnative_interface = true;
- print_line("Dumping gdnative interface header file");
+ dump_gdextension_interface = true;
+ print_line("Dumping GDExtension interface header file");
// Hack. Not needed but otherwise we end up detecting that this should
// run the project instead of a cmdline tool.
// Needs full refactoring to fix properly.
@@ -1286,7 +1296,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
goto error;
}
- } else if (I->get() == "--") {
+ } else if (I->get() == "--" || I->get() == "++") {
adding_user_args = true;
} else {
main_args.push_back(I->get());
@@ -1538,6 +1548,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
if (rendering_driver.is_empty() && rendering_method.is_empty() && project_manager) {
rendering_driver = "opengl3";
rendering_method = "gl_compatibility";
+ default_renderer_mobile = "gl_compatibility";
}
#endif
if (renderer_hints.is_empty()) {
@@ -1788,6 +1799,12 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
ProjectSettings::get_singleton()->set_custom_property_info("physics/common/physics_ticks_per_second",
PropertyInfo(Variant::INT, "physics/common/physics_ticks_per_second",
PROPERTY_HINT_RANGE, "1,1000,1"));
+
+ Engine::get_singleton()->set_max_physics_steps_per_frame(GLOBAL_DEF("physics/common/max_physics_steps_per_frame", 8));
+ ProjectSettings::get_singleton()->set_custom_property_info("physics/common/max_physics_steps_per_frame",
+ PropertyInfo(Variant::INT, "physics/common/max_physics_steps_per_frame",
+ PROPERTY_HINT_RANGE, "1,100,1"));
+
Engine::get_singleton()->set_physics_jitter_fix(GLOBAL_DEF("physics/common/physics_jitter_fix", 0.5));
Engine::get_singleton()->set_max_fps(GLOBAL_DEF("application/run/max_fps", 0));
ProjectSettings::get_singleton()->set_custom_property_info("application/run/max_fps",
@@ -1845,6 +1862,8 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
GLOBAL_DEF_BASIC("xr/openxr/reference_space", "1");
ProjectSettings::get_singleton()->set_custom_property_info("xr/openxr/reference_space", PropertyInfo(Variant::INT, "xr/openxr/reference_space", PROPERTY_HINT_ENUM, "Local,Stage"));
+ GLOBAL_DEF_BASIC("xr/openxr/submit_depth_buffer", false);
+
#ifdef TOOLS_ENABLED
// Disabled for now, using XR inside of the editor we'll be working on during the coming months.
@@ -1925,6 +1944,9 @@ error:
}
Error Main::setup2(Thread::ID p_main_tid_override) {
+ // Print engine name and version
+ print_line(String(VERSION_NAME) + " v" + get_full_version_string() + " - " + String(VERSION_WEBSITE));
+
engine->startup_benchmark_begin_measure("servers");
tsman = memnew(TextServerManager);
@@ -1940,10 +1962,7 @@ Error Main::setup2(Thread::ID p_main_tid_override) {
register_server_types();
initialize_modules(MODULE_INITIALIZATION_LEVEL_SERVERS);
- NativeExtensionManager::get_singleton()->initialize_extensions(NativeExtension::INITIALIZATION_LEVEL_SERVERS);
-
- // Print engine name and version
- print_line(String(VERSION_NAME) + " v" + get_full_version_string() + " - " + String(VERSION_WEBSITE));
+ GDExtensionManager::get_singleton()->initialize_extensions(GDExtension::INITIALIZATION_LEVEL_SERVERS);
if (p_main_tid_override) {
Thread::main_thread_id = p_main_tid_override;
@@ -2102,7 +2121,7 @@ Error Main::setup2(Thread::ID p_main_tid_override) {
MAIN_PRINT("Main: Setup Logo");
-#if defined(WEB_ENABLED) || defined(ANDROID_ENABLED)
+#if !defined(TOOLS_ENABLED) && (defined(WEB_ENABLED) || defined(ANDROID_ENABLED))
bool show_logo = false;
#else
bool show_logo = true;
@@ -2216,13 +2235,7 @@ Error Main::setup2(Thread::ID p_main_tid_override) {
if (bool(GLOBAL_DEF("input_devices/pointing/emulate_touch_from_mouse", false)) &&
!(editor || project_manager)) {
- bool found_touchscreen = false;
- for (int i = 0; i < DisplayServer::get_singleton()->get_screen_count(); i++) {
- if (DisplayServer::get_singleton()->screen_is_touchscreen(i)) {
- found_touchscreen = true;
- }
- }
- if (!found_touchscreen) {
+ if (!DisplayServer::get_singleton()->is_touchscreen_available()) {
//only if no touchscreen ui hint, set emulation
id->set_emulate_touch_from_mouse(true);
}
@@ -2308,13 +2321,13 @@ Error Main::setup2(Thread::ID p_main_tid_override) {
register_driver_types();
initialize_modules(MODULE_INITIALIZATION_LEVEL_SCENE);
- NativeExtensionManager::get_singleton()->initialize_extensions(NativeExtension::INITIALIZATION_LEVEL_SCENE);
+ GDExtensionManager::get_singleton()->initialize_extensions(GDExtension::INITIALIZATION_LEVEL_SCENE);
#ifdef TOOLS_ENABLED
ClassDB::set_current_api(ClassDB::API_EDITOR);
- EditorNode::register_editor_types();
+ register_editor_types();
initialize_modules(MODULE_INITIALIZATION_LEVEL_EDITOR);
- NativeExtensionManager::get_singleton()->initialize_extensions(NativeExtension::INITIALIZATION_LEVEL_EDITOR);
+ GDExtensionManager::get_singleton()->initialize_extensions(GDExtension::INITIALIZATION_LEVEL_EDITOR);
ClassDB::set_current_api(ClassDB::API_CORE);
@@ -2572,15 +2585,16 @@ bool Main::start() {
return false;
}
- if (dump_gdnative_interface) {
- GDNativeInterfaceDump::generate_gdnative_interface_file("gdnative_interface.h");
+ if (dump_gdextension_interface) {
+ GDExtensionInterfaceDump::generate_gdextension_interface_file("gdextension_interface.h");
}
if (dump_extension_api) {
- NativeExtensionAPIDump::generate_extension_json_file("extension_api.json");
+ GDExtensionAPIDump::generate_extension_json_file("extension_api.json");
}
- if (dump_gdnative_interface || dump_extension_api) {
+ if (dump_gdextension_interface || dump_extension_api) {
+ OS::get_singleton()->set_exit_code(EXIT_SUCCESS);
return false;
}
@@ -2652,7 +2666,11 @@ bool Main::start() {
if (!editor && !ClassDB::class_exists(main_loop_type) && ScriptServer::is_global_class(main_loop_type)) {
String script_path = ScriptServer::get_global_class_path(main_loop_type);
Ref<Script> script_res = ResourceLoader::load(script_path);
- StringName script_base = ScriptServer::get_global_class_native_base(main_loop_type);
+ if (script_res.is_null()) {
+ OS::get_singleton()->alert("Error: Could not load MainLoop script type: " + main_loop_type);
+ ERR_FAIL_V_MSG(false, vformat("Could not load global class %s.", main_loop_type));
+ }
+ StringName script_base = script_res->get_instance_base_type();
Object *obj = ClassDB::instantiate(script_base);
MainLoop *script_loop = Object::cast_to<MainLoop>(obj);
if (!script_loop) {
@@ -2734,27 +2752,38 @@ bool Main::start() {
for (const KeyValue<StringName, ProjectSettings::AutoloadInfo> &E : autoloads) {
const ProjectSettings::AutoloadInfo &info = E.value;
- Ref<Resource> res = ResourceLoader::load(info.path);
- ERR_CONTINUE_MSG(res.is_null(), "Can't autoload: " + info.path);
Node *n = nullptr;
- Ref<PackedScene> scn = res;
- Ref<Script> script_res = res;
- if (scn.is_valid()) {
- n = scn->instantiate();
- } else if (script_res.is_valid()) {
- StringName ibt = script_res->get_instance_base_type();
- bool valid_type = ClassDB::is_parent_class(ibt, "Node");
- ERR_CONTINUE_MSG(!valid_type, "Script does not inherit from Node: " + info.path);
+ if (ResourceLoader::get_resource_type(info.path) == "PackedScene") {
+ // Cache the scene reference before loading it (for cyclic references)
+ Ref<PackedScene> scn;
+ scn.instantiate();
+ scn->set_path(info.path);
+ scn->reload_from_file();
+ ERR_CONTINUE_MSG(!scn.is_valid(), vformat("Can't autoload: %s.", info.path));
+
+ if (scn.is_valid()) {
+ n = scn->instantiate();
+ }
+ } else {
+ Ref<Resource> res = ResourceLoader::load(info.path);
+ ERR_CONTINUE_MSG(res.is_null(), vformat("Can't autoload: %s.", info.path));
+
+ Ref<Script> script_res = res;
+ if (script_res.is_valid()) {
+ StringName ibt = script_res->get_instance_base_type();
+ bool valid_type = ClassDB::is_parent_class(ibt, "Node");
+ ERR_CONTINUE_MSG(!valid_type, vformat("Script does not inherit from Node: %s.", info.path));
- Object *obj = ClassDB::instantiate(ibt);
+ Object *obj = ClassDB::instantiate(ibt);
- ERR_CONTINUE_MSG(!obj, "Cannot instance script for autoload, expected 'Node' inheritance, got: " + String(ibt) + ".");
+ ERR_CONTINUE_MSG(!obj, vformat("Cannot instance script for autoload, expected 'Node' inheritance, got: %s."));
- n = Object::cast_to<Node>(obj);
- n->set_script(script_res);
+ n = Object::cast_to<Node>(obj);
+ n->set_script(script_res);
+ }
}
- ERR_CONTINUE_MSG(!n, "Path in autoload not a node or script: " + info.path);
+ ERR_CONTINUE_MSG(!n, vformat("Path in autoload not a node or script: %s.", info.path));
n->set_name(info.name);
//defer so references are all valid on _ready()
@@ -2944,6 +2973,7 @@ bool Main::start() {
DisplayServer::get_singleton()->set_context(DisplayServer::CONTEXT_EDITOR);
if (!debug_server_uri.is_empty()) {
EditorDebuggerNode::get_singleton()->start(debug_server_uri);
+ EditorDebuggerNode::get_singleton()->set_keep_open(true);
}
}
#endif
@@ -3104,7 +3134,7 @@ bool Main::iteration() {
last_ticks = ticks;
- static const int max_physics_steps = 8;
+ const int max_physics_steps = Engine::get_singleton()->get_max_physics_steps_per_frame();
if (fixed_fps == -1 && advance.physics_steps > max_physics_steps) {
process_step -= (advance.physics_steps - max_physics_steps) * physics_step;
advance.physics_steps = max_physics_steps;
@@ -3275,6 +3305,10 @@ void Main::cleanup(bool p_force) {
ERR_FAIL_COND(!_start_success);
}
+ for (int i = 0; i < TextServerManager::get_singleton()->get_interface_count(); i++) {
+ TextServerManager::get_singleton()->get_interface(i)->cleanup();
+ }
+
if (movie_writer) {
movie_writer->end();
}
@@ -3295,6 +3329,8 @@ void Main::cleanup(bool p_force) {
ResourceLoader::clear_translation_remaps();
ResourceLoader::clear_path_remaps();
+ ResourceLoader::clear_thread_load_tasks();
+
ScriptServer::finish_languages();
// Sync pending commands that may have been queued from a different thread during ScriptServer finalization
@@ -3310,15 +3346,15 @@ void Main::cleanup(bool p_force) {
}
#ifdef TOOLS_ENABLED
- NativeExtensionManager::get_singleton()->deinitialize_extensions(NativeExtension::INITIALIZATION_LEVEL_EDITOR);
+ GDExtensionManager::get_singleton()->deinitialize_extensions(GDExtension::INITIALIZATION_LEVEL_EDITOR);
uninitialize_modules(MODULE_INITIALIZATION_LEVEL_EDITOR);
- EditorNode::unregister_editor_types();
+ unregister_editor_types();
#endif
ImageLoader::cleanup();
- NativeExtensionManager::get_singleton()->deinitialize_extensions(NativeExtension::INITIALIZATION_LEVEL_SCENE);
+ GDExtensionManager::get_singleton()->deinitialize_extensions(GDExtension::INITIALIZATION_LEVEL_SCENE);
uninitialize_modules(MODULE_INITIALIZATION_LEVEL_SCENE);
unregister_platform_apis();
@@ -3328,9 +3364,10 @@ void Main::cleanup(bool p_force) {
finalize_theme_db();
// Before deinitializing server extensions, finalize servers which may be loaded as extensions.
+ finalize_navigation_server();
finalize_physics();
- NativeExtensionManager::get_singleton()->deinitialize_extensions(NativeExtension::INITIALIZATION_LEVEL_SERVERS);
+ GDExtensionManager::get_singleton()->deinitialize_extensions(GDExtension::INITIALIZATION_LEVEL_SERVERS);
uninitialize_modules(MODULE_INITIALIZATION_LEVEL_SERVERS);
unregister_server_types();
@@ -3351,7 +3388,6 @@ void Main::cleanup(bool p_force) {
OS::get_singleton()->finalize();
- finalize_navigation_server();
finalize_display();
if (input) {
diff --git a/methods.py b/methods.py
index f4afead9f4..99a59b49e3 100644
--- a/methods.py
+++ b/methods.py
@@ -774,7 +774,7 @@ def generate_vs_project(env, num_jobs):
for platform in ModuleConfigs.PLATFORMS
]
self.arg_dict["runfile"] += [
- f'bin\\godot.windows.{config}{ModuleConfigs.DEV_SUFFIX}{".double" if env["float"] == "64" else ""}.{plat_id}{f".{name}" if name else ""}.exe'
+ f'bin\\godot.windows.{config}{ModuleConfigs.DEV_SUFFIX}{".double" if env["precision"] == "double" else ""}.{plat_id}{f".{name}" if name else ""}.exe'
for config in ModuleConfigs.CONFIGURATIONS
for plat_id in ModuleConfigs.PLATFORM_IDS
]
@@ -820,8 +820,8 @@ def generate_vs_project(env, num_jobs):
if env["custom_modules"]:
common_build_postfix.append("custom_modules=%s" % env["custom_modules"])
- if env["float"] == "64":
- common_build_postfix.append("float=64")
+ if env["precision"] == "double":
+ common_build_postfix.append("precision=double")
result = " ^& ".join(common_build_prefix + [" ".join([commands] + common_build_postfix)])
return result
diff --git a/misc/dist/html/full-size.html b/misc/dist/html/full-size.html
index 6ae3e5cc73..6710cb1533 100644
--- a/misc/dist/html/full-size.html
+++ b/misc/dist/html/full-size.html
@@ -215,7 +215,7 @@ const engine = new Engine(GODOT_CONFIG);
const missing = Engine.getMissingFeatures();
if (missing.length !== 0) {
- const missingMsg = 'Warning!\nThe following features required to run Godot projects on the Web are missing:\n';
+ const missingMsg = 'Error\nThe following features required to run Godot projects on the Web are missing:\n';
displayFailureNotice(missingMsg + missing.join('\n'));
} else {
setStatusMode('indeterminate');
diff --git a/misc/dist/icon_console.svg b/misc/dist/icon_console.svg
new file mode 100644
index 0000000000..d486482f3b
--- /dev/null
+++ b/misc/dist/icon_console.svg
@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ width="1024"
+ height="1024"
+ id="svg3030"
+ version="1.1"
+ inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)"
+ sodipodi:docname="icon_console.svg"
+ inkscape:export-filename="/home/akien/Projects/godot/godot.git/icon.png"
+ inkscape:export-xdpi="24"
+ inkscape:export-ydpi="24"
+ xml:space="preserve"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:dc="http://purl.org/dc/elements/1.1/"><defs
+ id="defs3032" /><sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="0.28259086"
+ inkscape:cx="955.44491"
+ inkscape:cy="1380.0871"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:window-width="3840"
+ inkscape:window-height="2054"
+ inkscape:window-x="-11"
+ inkscape:window-y="594"
+ inkscape:window-maximized="1"
+ inkscape:document-rotation="0"
+ inkscape:showpageshadow="0"
+ inkscape:pagecheckerboard="0"
+ inkscape:deskcolor="#d1d1d1" /><metadata
+ id="metadata3035"><rdf:RDF><cc:Work
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(0,-98.519719)"><g
+ inkscape:label="Layer 1"
+ id="layer1-6"
+ transform="translate(1.7750003e-7,-2.4372979)"><g
+ id="g78-0"
+ transform="matrix(4.162611,0,0,-4.162611,919.24059,771.67186)"
+ style="stroke-width:0.320312"><path
+ d="m 0,0 c 0,0 -0.325,1.994 -0.515,1.976 l -36.182,-3.491 c -2.879,-0.278 -5.115,-2.574 -5.317,-5.459 l -0.994,-14.247 -27.992,-1.997 -1.904,12.912 c -0.424,2.872 -2.932,5.037 -5.835,5.037 h -38.188 c -2.902,0 -5.41,-2.165 -5.834,-5.037 l -1.905,-12.912 -27.992,1.997 -0.994,14.247 c -0.202,2.886 -2.438,5.182 -5.317,5.46 l -36.2,3.49 c -0.187,0.018 -0.324,-1.978 -0.511,-1.978 l -0.049,-7.83 30.658,-4.944 1.004,-14.374 c 0.203,-2.91 2.551,-5.263 5.463,-5.472 l 38.551,-2.75 c 0.146,-0.01 0.29,-0.016 0.434,-0.016 2.897,0 5.401,2.166 5.825,5.038 l 1.959,13.286 h 28.005 l 1.959,-13.286 c 0.423,-2.871 2.93,-5.037 5.831,-5.037 0.142,0 0.284,0.005 0.423,0.015 l 38.556,2.75 c 2.911,0.209 5.26,2.562 5.463,5.472 l 1.003,14.374 30.645,4.966 z"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.320312"
+ id="path80-3"
+ inkscape:connector-curvature="0" /></g><g
+ id="g82-3-2"
+ transform="matrix(4.162611,0,0,-4.162611,104.69892,525.90697)"
+ style="stroke-width:0.320312"><path
+ d="m 0,0 v -47.514 -6.035 -5.492 c 0.108,-0.001 0.216,-0.005 0.323,-0.015 l 36.196,-3.49 c 1.896,-0.183 3.382,-1.709 3.514,-3.609 l 1.116,-15.978 31.574,-2.253 2.175,14.747 c 0.282,1.912 1.922,3.329 3.856,3.329 h 38.188 c 1.933,0 3.573,-1.417 3.855,-3.329 l 2.175,-14.747 31.575,2.253 1.115,15.978 c 0.133,1.9 1.618,3.425 3.514,3.609 l 36.182,3.49 c 0.107,0.01 0.214,0.014 0.322,0.015 v 4.711 l 0.015,0.005 V 0 c 5.09692,6.4164715 9.92323,13.494208 13.621,19.449 -5.651,9.62 -12.575,18.217 -19.976,26.182 -6.864,-3.455 -13.531,-7.369 -19.828,-11.534 -3.151,3.132 -6.7,5.694 -10.186,8.372 -3.425,2.751 -7.285,4.768 -10.946,7.118 1.09,8.117 1.629,16.108 1.846,24.448 -9.446,4.754 -19.519,7.906 -29.708,10.17 -4.068,-6.837 -7.788,-14.241 -11.028,-21.479 -3.842,0.642 -7.702,0.88 -11.567,0.926 v 0.006 c -0.027,0 -0.052,-0.006 -0.075,-0.006 -0.024,0 -0.049,0.006 -0.073,0.006 V 63.652 C 93.903,63.606 90.046,63.368 86.203,62.726 82.965,69.964 79.247,77.368 75.173,84.205 64.989,81.941 54.915,78.789 45.47,74.035 45.686,65.695 46.225,57.704 47.318,49.587 43.65,47.237 39.795,45.22 36.369,42.469 32.888,39.791 29.333,37.229 26.181,34.097 19.884,38.262 13.219,42.176 6.353,45.631 -1.048,37.666 -7.968,29.069 -13.621,19.449 -9.1783421,12.475308 -4.4130298,5.4661124 0,0 Z"
+ style="fill:#478cbf;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.320312"
+ id="path84-6-6"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccccccsssscccccccccccccccccccsccccccccccc" /></g><g
+ id="g86-7-9"
+ transform="matrix(4.162611,0,0,-4.162611,784.07144,817.24284)"
+ style="stroke-width:0.320312"><path
+ d="m 0,0 -1.121,-16.063 c -0.135,-1.936 -1.675,-3.477 -3.611,-3.616 l -38.555,-2.751 c -0.094,-0.007 -0.188,-0.01 -0.281,-0.01 -1.916,0 -3.569,1.406 -3.852,3.33 l -2.211,14.994 H -81.09 l -2.211,-14.994 c -0.297,-2.018 -2.101,-3.469 -4.133,-3.32 l -38.555,2.751 c -1.936,0.139 -3.476,1.68 -3.611,3.616 L -130.721,0 -163.268,3.138 c 0.015,-3.498 0.06,-7.33 0.06,-8.093 0,-34.374 43.605,-50.896 97.781,-51.086 h 0.066 0.067 c 54.176,0.19 97.766,16.712 97.766,51.086 0,0.777 0.047,4.593 0.063,8.093 z"
+ style="fill:#478cbf;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.320312"
+ id="path88-5-4"
+ inkscape:connector-curvature="0" /></g><g
+ id="g90-3-1"
+ transform="matrix(4.162611,0,0,-4.162611,389.21484,625.67104)"
+ style="stroke-width:0.320312"><path
+ d="m 0,0 c 0,-12.052 -9.765,-21.815 -21.813,-21.815 -12.042,0 -21.81,9.763 -21.81,21.815 0,12.044 9.768,21.802 21.81,21.802 C -9.765,21.802 0,12.044 0,0"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.320312"
+ id="path92-5-3"
+ inkscape:connector-curvature="0" /></g><g
+ id="g94-6-7"
+ transform="matrix(4.162611,0,0,-4.162611,367.36686,631.05679)"
+ style="stroke-width:0.320312"><path
+ d="m 0,0 c 0,-7.994 -6.479,-14.473 -14.479,-14.473 -7.996,0 -14.479,6.479 -14.479,14.473 0,7.994 6.483,14.479 14.479,14.479 C -6.479,14.479 0,7.994 0,0"
+ style="fill:#414042;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.320312"
+ id="path96-2-8"
+ inkscape:connector-curvature="0" /></g><g
+ id="g98-9-8"
+ transform="matrix(4.162611,0,0,-4.162611,511.99336,724.73954)"
+ style="stroke-width:0.320312"><path
+ d="m 0,0 c -3.878,0 -7.021,2.858 -7.021,6.381 v 20.081 c 0,3.52 3.143,6.381 7.021,6.381 3.878,0 7.028,-2.861 7.028,-6.381 V 6.381 C 7.028,2.858 3.878,0 0,0"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.320312"
+ id="path100-1-3"
+ inkscape:connector-curvature="0" /></g><g
+ id="g102-2-8"
+ transform="matrix(4.162611,0,0,-4.162611,634.78706,625.67104)"
+ style="stroke-width:0.320312"><path
+ d="m 0,0 c 0,-12.052 9.765,-21.815 21.815,-21.815 12.041,0 21.808,9.763 21.808,21.815 0,12.044 -9.767,21.802 -21.808,21.802 C 9.765,21.802 0,12.044 0,0"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.320312"
+ id="path104-7-1"
+ inkscape:connector-curvature="0" /></g><g
+ id="g106-0-5"
+ transform="matrix(4.162611,0,0,-4.162611,656.64056,631.05679)"
+ style="stroke-width:0.320312"><path
+ d="m 0,0 c 0,-7.994 6.477,-14.473 14.471,-14.473 8.002,0 14.479,6.479 14.479,14.473 0,7.994 -6.477,14.479 -14.479,14.479 C 6.477,14.479 0,7.994 0,0"
+ style="fill:#414042;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.320312"
+ id="path108-9-3"
+ inkscape:connector-curvature="0" /></g></g><path
+ id="path581"
+ style="fill:#414042;fill-opacity:1;stroke-width:20;stroke:#ffffff;stroke-opacity:1;stroke-dasharray:none"
+ d="m 559.63672,752.49433 c -9.61602,0 -17.48438,7.86834 -17.48438,17.48437 v 295.125 c 0,9.6161 7.86836,17.4844 17.48438,17.4844 h 384.64062 c 9.61603,0 17.48438,-7.8683 17.48438,-17.4844 v -295.125 c 0,-9.61603 -7.86835,-17.48437 -17.48438,-17.48437 z"
+ sodipodi:nodetypes="sccssccss" /><path
+ id="path10"
+ style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:10.7638"
+ d="m 604.19435,828.87215 -19.37462,19.37464 c -5.38188,4.3055 -5.38188,11.84096 0,17.22283 l 66.73589,66.73469 -66.73589,66.73589 c -5.38188,5.3819 -5.38188,12.9161 0,17.2216 l 19.37462,19.3747 c 5.38188,5.3818 12.91613,5.3818 17.22163,0 l 75.33586,-75.33592 19.38547,-19.38425 c 5.46258,-5.17192 5.07049,-13.02396 0,-17.22284 l -19.37462,-19.37462 -75.34671,-75.34672 c -4.96088,-4.18442 -12.91229,-4.15049 -17.22163,0 z"
+ sodipodi:nodetypes="ccccscsccccccc" /><path
+ d="M 917.91967,991.872 H 760.9701 c -5.88562,0 -9.80935,3.9237 -9.80935,9.8093 v 29.4281 c 0,5.8856 3.92373,9.8093 9.80935,9.8093 h 156.94957 c 5.88561,0 9.80934,-3.9237 9.80934,-9.8093 v -29.4281 c 0,-5.8856 -3.92373,-9.8093 -9.80934,-9.8093 z"
+ fill="url(#paint5_linear)"
+ id="path25"
+ style="fill:#ffffff;fill-opacity:1;stroke-width:9.80938" /></g></svg>
diff --git a/misc/dist/ios_xcode/godot_ios.xcodeproj/project.pbxproj b/misc/dist/ios_xcode/godot_ios.xcodeproj/project.pbxproj
index b58f002f3c..e717b501f4 100644
--- a/misc/dist/ios_xcode/godot_ios.xcodeproj/project.pbxproj
+++ b/misc/dist/ios_xcode/godot_ios.xcodeproj/project.pbxproj
@@ -164,7 +164,7 @@
};
buildConfigurationList = D0BCFE2F18AEBDA2004A7AAE /* Build configuration list for PBXProject "$binary" */;
compatibilityVersion = "Xcode 3.2";
- developmentRegion = English;
+ developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
diff --git a/misc/dist/linux/godot.6 b/misc/dist/linux/godot.6
index 2af0cb1965..2481869d8a 100644
--- a/misc/dist/linux/godot.6
+++ b/misc/dist/linux/godot.6
@@ -157,7 +157,7 @@ Disallow dumping the base types (used with \fB\-\-doctool\fR).
Build the scripting solutions (e.g. for C# projects). Implies \-\-editor and requires a valid project to edit.
.TP
\fB\-\-dump\-gdextension\-interface\fR
-Generate GDExtension header file 'gdnative_interface.h' in the current folder. This file is the base file required to implement a GDExtension.
+Generate GDExtension header file 'gdextension_interface.h' in the current folder. This file is the base file required to implement a GDExtension.
.TP
\fB\-\-dump\-extension\-api\fR
Generate JSON dump of the Godot API for GDExtension bindings named 'extension_api.json' in the current folder.
diff --git a/misc/dist/shell/_godot.zsh-completion b/misc/dist/shell/_godot.zsh-completion
index 9b4ef52f3f..8e2f6a92bd 100644
--- a/misc/dist/shell/_godot.zsh-completion
+++ b/misc/dist/shell/_godot.zsh-completion
@@ -50,14 +50,15 @@ _arguments \
'--text-driver[set the text driver]:text driver name' \
'--tablet-driver[set the pen tablet input driver]:tablet driver name' \
'--headless[enable headless mode (--display-driver headless --audio-driver Dummy), useful for servers and with --script]' \
+ '--write-movie[writes a video to the specified path (usually with .avi or .png extension)]:path to output video file' \
'(-f --fullscreen)'{-f,--fullscreen}'[request fullscreen mode]' \
'(-m --maximized)'{-m,--maximized}'[request a maximized window]' \
'(-w --windowed)'{-w,--windowed}'[request windowed mode]' \
'(-t --always-on-top)'{-t,--always-on-top}'[request an always-on-top window]' \
'--resolution[request window resolution]:resolution in WxH format' \
'--position[request window position]:position in X,Y format' \
- '--headless[enable headless mode (--display-driver headless --audio-driver Dummy). Useful for servers and with --script]' \
'--single-window[use a single window (no separate subwindows)]' \
+ '--xr-mode[select Extended Reality (XR) mode]:Extended Reality (XR) mode:(default off on)' \
'(-d --debug)'{-d,--debug}'[debug (local stdout debugger)]' \
'(-b --breakpoints)'{-b,--breakpoints}'[specify the breakpoint list as source::line comma-separated pairs, no spaces (use %20 instead)]:breakpoint list' \
'--profiling[enable profiling in the script debugger]' \
@@ -70,6 +71,7 @@ _arguments \
'--debug-stringnames[print all StringName allocations to stdout when the engine quits]' \
'--frame-delay[simulate high CPU load (delay each frame by the given number of milliseconds)]:number of milliseconds' \
'--time-scale[force time scale (higher values are faster, 1.0 is normal speed)]:time scale' \
+ '--disable-vsync[disable vertical synchronization even if enabled in the project settings]' \
'--disable-render-loop[disable render loop so rendering only occurs when called explicitly from script]' \
'--disable-crash-handler[disable crash handler when supported by the platform code]' \
'--fixed-fps[force a fixed number of frames per second (this setting disables real-time synchronization)]:frames per second' \
@@ -84,6 +86,8 @@ _arguments \
'--doctool[dump the engine API reference to the given path in XML format, merging if existing files are found]:path to base Godot build directory (optional):_dirs' \
'--no-docbase[disallow dumping the base types (used with --doctool)]' \
'--build-solutions[build the scripting solutions (e.g. for C# projects)]' \
- '--dump-gdextension-interface[generate GDExtension header file 'gdnative_interface.h' in the current folder. This file is the base file required to implement a GDExtension.]' \
+ '--dump-gdextension-interface[generate GDExtension header file 'gdextension_interface.h' in the current folder. This file is the base file required to implement a GDExtension.]' \
'--dump-extension-api[generate JSON dump of the Godot API for GDExtension bindings named "extension_api.json" in the current folder]' \
+ '--startup-benchmark[benchmark the startup time and print it to console]' \
+ '--startup-benchmark-file[benchmark the startup time and save it to a given file in JSON format]:path to output JSON file' \
'--test[run all unit tests; run with "--test --help" for more information]'
diff --git a/misc/dist/shell/godot.bash-completion b/misc/dist/shell/godot.bash-completion
index 02dcc94033..73107c0cf3 100644
--- a/misc/dist/shell/godot.bash-completion
+++ b/misc/dist/shell/godot.bash-completion
@@ -53,6 +53,7 @@ _complete_godot_options() {
--text-driver
--tablet-driver
--headless
+--write-movie
--fullscreen
--maximized
--windowed
@@ -60,6 +61,7 @@ _complete_godot_options() {
--resolution
--position
--single-window
+--xr-mode
--debug
--breakpoints
--profiling
@@ -72,6 +74,7 @@ _complete_godot_options() {
--debug-stringnames
--frame-delay
--time-scale
+--disable-vsync
--disable-render-loop
--disable-crash-handler
--fixed-fps
@@ -88,6 +91,8 @@ _complete_godot_options() {
--build-solutions
--dump-gdextension-interface
--dump-extension-api
+--startup-benchmark
+--startup-benchmark-file
--test
" -- "$1"))
}
@@ -121,6 +126,10 @@ _complete_godot_bash() {
local IFS=$' \n\t'
# shellcheck disable=SC2207
COMPREPLY=($(compgen -W "vulkan opengl3 dummy" -- "$cur"))
+ elif [[ $prev == "--xr-mode" ]]; then
+ local IFS=$' \n\t'
+ # shellcheck disable=SC2207
+ COMPREPLY=($(compgen -W "default off on" -- "$cur"))
elif [[ $prev == "--path" || $prev == "--doctool" ]]; then
local IFS=$'\n\t'
# shellcheck disable=SC2207
diff --git a/misc/dist/shell/godot.fish b/misc/dist/shell/godot.fish
index 4f7803124b..83680214f2 100644
--- a/misc/dist/shell/godot.fish
+++ b/misc/dist/shell/godot.fish
@@ -66,6 +66,7 @@ complete -c godot -l gpu-index -d "Use a specific GPU (run with --verbose to get
complete -c godot -l text-driver -d "Set the text driver" -x
complete -c godot -l tablet-driver -d "Set the pen tablet input driver" -x
complete -c godot -l headless -d "Enable headless mode (--display-driver headless --audio-driver Dummy). Useful for servers and with --script"
+complete -c godot -l write-movie -d "Writes a video to the specified path (usually with .avi or .png extension). --fixed-fps is forced when enabled" -x
# Display options:
complete -c godot -s f -l fullscreen -d "Request fullscreen mode"
@@ -74,8 +75,8 @@ complete -c godot -s w -l windowed -d "Request windowed mode"
complete -c godot -s t -l always-on-top -d "Request an always-on-top window"
complete -c godot -l resolution -d "Request window resolution" -x
complete -c godot -l position -d "Request window position" -x
-complete -c godot -l headless -d "Enable headless mode (--display-driver headless --audio-driver Dummy). Useful for servers and with --script"
complete -c godot -l single-window -d "Use a single window (no separate subwindows)"
+complete -c godot -l xr-mode -d "Select Extended Reality (XR) mode" -a "default off on"
# Debug options:
complete -c godot -s d -l debug -d "Debug (local stdout debugger)"
@@ -106,6 +107,8 @@ complete -c godot -l validate-conversion-3to4 -d "Shows what elements will be re
complete -c godot -l doctool -d "Dump the engine API reference to the given path in XML format, merging if existing files are found" -r
complete -c godot -l no-docbase -d "Disallow dumping the base types (used with --doctool)"
complete -c godot -l build-solutions -d "Build the scripting solutions (e.g. for C# projects)"
-complete -c godot -l dump-gdextension-interface -d "Generate GDExtension header file 'gdnative_interface.h' in the current folder. This file is the base file required to implement a GDExtension"
+complete -c godot -l dump-gdextension-interface -d "Generate GDExtension header file 'gdextension_interface.h' in the current folder. This file is the base file required to implement a GDExtension"
complete -c godot -l dump-extension-api -d "Generate JSON dump of the Godot API for GDExtension bindings named 'extension_api.json' in the current folder"
+complete -c godot -l startup-benchmark -d "Benchmark the startup time and print it to console"
+complete -c godot -l startup-benchmark-file -d "Benchmark the startup time and save it to a given file in JSON format" -x
complete -c godot -l test -d "Run all unit tests; run with '--test --help' for more information" -x
diff --git a/misc/scripts/compare_extension_api.py b/misc/scripts/compare_extension_api.py
deleted file mode 100755
index f96db4278c..0000000000
--- a/misc/scripts/compare_extension_api.py
+++ /dev/null
@@ -1,11 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-
-import sys
-
-# TODO:
-# Add a process that compares the original godot-cpp/godot-headers/extension_api.json with the new extension_api.json (both passed as arguments) and reports any API calls that have been removed.
-# If we only have additions or no changes to the file, we pass
-# For now we deem this too early because the API isn't stable enough yet.
-
-sys.exit(0)
diff --git a/misc/scripts/file_format.sh b/misc/scripts/file_format.sh
index 1200b96ea0..a2f33692f9 100755
--- a/misc/scripts/file_format.sh
+++ b/misc/scripts/file_format.sh
@@ -31,7 +31,9 @@ while IFS= read -rd '' f; do
continue
elif [[ "$f" == *"po" ]]; then
continue
- elif [[ "$f" == "thirdparty"* ]]; then
+ elif [[ "$f" == "thirdparty/"* ]]; then
+ continue
+ elif [[ "$f" == *"/thirdparty/"* ]]; then
continue
elif [[ "$f" == "platform/android/java/lib/src/com/google"* ]]; then
continue
diff --git a/modules/basis_universal/register_types.cpp b/modules/basis_universal/register_types.cpp
index 155f7809b0..8d21541341 100644
--- a/modules/basis_universal/register_types.cpp
+++ b/modules/basis_universal/register_types.cpp
@@ -277,6 +277,7 @@ void initialize_basis_universal_module(ModuleInitializationLevel p_level) {
basisu_encoder_init();
Image::basis_universal_packer = basis_universal_packer;
#endif
+ basist::basisu_transcoder_init();
Image::basis_universal_unpacker = basis_universal_unpacker;
Image::basis_universal_unpacker_ptr = basis_universal_unpacker_ptr;
}
diff --git a/modules/etcpak/image_compress_etcpak.cpp b/modules/etcpak/image_compress_etcpak.cpp
index 3d66b27556..e467ed60ee 100644
--- a/modules/etcpak/image_compress_etcpak.cpp
+++ b/modules/etcpak/image_compress_etcpak.cpp
@@ -111,13 +111,16 @@ void _compress_etcpak(EtcpakType p_compresstype, Image *r_img, float p_lossy_qua
Image::Format target_format = Image::FORMAT_RGBA8;
if (p_compresstype == EtcpakType::ETCPAK_TYPE_ETC1) {
target_format = Image::FORMAT_ETC;
+ r_img->convert_rgba8_to_bgra8(); // It's badly documented but ETCPAK seems to be expected BGRA8 for ETC.
} else if (p_compresstype == EtcpakType::ETCPAK_TYPE_ETC2) {
target_format = Image::FORMAT_ETC2_RGB8;
+ r_img->convert_rgba8_to_bgra8(); // It's badly documented but ETCPAK seems to be expected BGRA8 for ETC.
} else if (p_compresstype == EtcpakType::ETCPAK_TYPE_ETC2_RA_AS_RG) {
target_format = Image::FORMAT_ETC2_RA_AS_RG;
r_img->convert_rg_to_ra_rgba8();
} else if (p_compresstype == EtcpakType::ETCPAK_TYPE_ETC2_ALPHA) {
target_format = Image::FORMAT_ETC2_RGBA8;
+ r_img->convert_rgba8_to_bgra8(); // It's badly documented but ETCPAK seems to be expected BGRA8 for ETC.
} else if (p_compresstype == EtcpakType::ETCPAK_TYPE_DXT1) {
target_format = Image::FORMAT_DXT1;
} else if (p_compresstype == EtcpakType::ETCPAK_TYPE_DXT5_RA_AS_RG) {
diff --git a/modules/gdscript/doc_classes/@GDScript.xml b/modules/gdscript/doc_classes/@GDScript.xml
index c8eda53a2d..fd748ea569 100644
--- a/modules/gdscript/doc_classes/@GDScript.xml
+++ b/modules/gdscript/doc_classes/@GDScript.xml
@@ -106,6 +106,7 @@
<param index="0" name="instance" type="Object" />
<description>
Returns the passed [param instance] converted to a Dictionary. Can be useful for serializing.
+ [b]Note:[/b] Cannot be used to serialize objects with built-in scripts attached or objects allocated within built-in scripts.
[codeblock]
var foo = "bar"
func _ready():
@@ -547,7 +548,7 @@
<return type="void" />
<param index="0" name="icon_path" type="String" />
<description>
- Add a custom icon to the current script. After loading an icon at [param icon_path], the icon is displayed in the Scene dock for every node that the script is attached to. For named classes, the icon is also displayed in various editor dialogs.
+ Add a custom icon to the current script. The script must be registered as a global class using the [code]class_name[/code] keyword for this to have a visible effect. The icon specified at [param icon_path] is displayed in the Scene dock for every node of that class, as well as in various editor dialogs.
[codeblock]
@icon("res://path/to/class/icon.svg")
[/codeblock]
diff --git a/modules/gdscript/editor/gdscript_highlighter.cpp b/modules/gdscript/editor/gdscript_highlighter.cpp
index 420401cb79..0ebdbf090d 100644
--- a/modules/gdscript/editor/gdscript_highlighter.cpp
+++ b/modules/gdscript/editor/gdscript_highlighter.cpp
@@ -322,7 +322,7 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting_impl(int p_l
}
String word = str.substr(j, to - j);
- Color col = Color();
+ Color col;
if (global_functions.has(word)) {
// "assert" and "preload" are reserved, so highlight even if not followed by a bracket.
if (word == GDScriptTokenizer::get_token_name(GDScriptTokenizer::Token::ASSERT) || word == GDScriptTokenizer::get_token_name(GDScriptTokenizer::Token::PRELOAD)) {
diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp
index b4da9c1224..1fe1561559 100644
--- a/modules/gdscript/gdscript.cpp
+++ b/modules/gdscript/gdscript.cpp
@@ -478,7 +478,7 @@ void GDScript::_clear_doc() {
void GDScript::_update_doc() {
_clear_doc();
- doc.script_path = "\"" + get_path().get_slice("://", 1) + "\"";
+ doc.script_path = vformat(R"("%s")", get_script_path().get_slice("://", 1));
if (!name.is_empty()) {
doc.name = name;
} else {
@@ -629,10 +629,6 @@ void GDScript::_update_doc() {
}
}
- for (KeyValue<StringName, Ref<GDScript>> &E : subclasses) {
- E.value->_update_doc();
- }
-
_add_doc(doc);
}
#endif
@@ -674,36 +670,14 @@ bool GDScript::_update_exports(bool *r_err, bool p_recursive_call, PlaceHolderSc
base_cache = Ref<GDScript>();
}
- if (c->extends_used) {
- String ext_path = "";
- if (String(c->extends_path) != "" && String(c->extends_path) != get_path()) {
- ext_path = c->extends_path;
- if (ext_path.is_relative_path()) {
- String base_path = get_path();
- if (base_path.is_empty() || base_path.is_relative_path()) {
- ERR_PRINT(("Could not resolve relative path for parent class: " + ext_path).utf8().get_data());
- } else {
- ext_path = base_path.get_base_dir().path_join(ext_path);
- }
- }
- } else if (c->extends.size() != 0) {
- const StringName &base_class = c->extends[0];
-
- if (ScriptServer::is_global_class(base_class)) {
- ext_path = ScriptServer::get_global_class_path(base_class);
- }
- }
-
- if (!ext_path.is_empty()) {
- if (ext_path != get_path()) {
- Ref<GDScript> bf = ResourceLoader::load(ext_path);
-
- if (bf.is_valid()) {
- base_cache = bf;
- bf->inheriters_cache.insert(get_instance_id());
- }
- } else {
- ERR_PRINT(("Path extending itself in " + ext_path).utf8().get_data());
+ GDScriptParser::DataType base_type = parser.get_tree()->base_type;
+ if (base_type.kind == GDScriptParser::DataType::CLASS) {
+ Ref<GDScript> bf = GDScriptCache::get_full_script(base_type.script_path, err, path);
+ if (err == OK) {
+ bf = Ref<GDScript>(bf->find_class(base_type.class_type->fqcn));
+ if (bf.is_valid()) {
+ base_cache = bf;
+ bf->inheriters_cache.insert(get_instance_id());
}
}
}
@@ -727,6 +701,7 @@ bool GDScript::_update_exports(bool *r_err, bool p_recursive_call, PlaceHolderSc
Variant default_value;
if (member.variable->initializer && member.variable->initializer->is_constant) {
default_value = member.variable->initializer->reduced_value;
+ GDScriptCompiler::convert_to_initializer_type(default_value, member.variable);
}
member_default_values_cache[member.variable->identifier->name] = default_value;
} break;
@@ -825,22 +800,20 @@ void GDScript::update_exports() {
#endif
}
-void GDScript::_set_subclass_path(Ref<GDScript> &p_sc, const String &p_path) {
- p_sc->path = p_path;
- for (KeyValue<StringName, Ref<GDScript>> &E : p_sc->subclasses) {
- _set_subclass_path(E.value, p_path);
- }
-}
-
String GDScript::_get_debug_path() const {
if (is_built_in() && !get_name().is_empty()) {
- return get_name() + " (" + get_path() + ")";
+ return vformat("%s(%s)", get_name(), get_script_path());
} else {
- return get_path();
+ return get_script_path();
}
}
Error GDScript::reload(bool p_keep_state) {
+ if (reloading) {
+ return OK;
+ }
+ reloading = true;
+
bool has_instances;
{
MutexLock lock(GDScriptLanguage::singleton->mutex);
@@ -860,9 +833,10 @@ Error GDScript::reload(bool p_keep_state) {
basedir = basedir.get_base_dir();
}
-// Loading a template, don't parse.
+ // Loading a template, don't parse.
#ifdef TOOLS_ENABLED
if (EditorPaths::get_singleton() && basedir.begins_with(EditorPaths::get_singleton()->get_project_script_templates_dir())) {
+ reloading = false;
return OK;
}
#endif
@@ -872,11 +846,10 @@ Error GDScript::reload(bool p_keep_state) {
if (source_path.is_empty()) {
source_path = get_path();
}
- if (!source_path.is_empty()) {
- MutexLock lock(GDScriptCache::singleton->lock);
- if (!GDScriptCache::singleton->shallow_gdscript_cache.has(source_path)) {
- GDScriptCache::singleton->shallow_gdscript_cache[source_path] = this;
- }
+ Ref<GDScript> cached_script = GDScriptCache::get_cached_script(source_path);
+ if (!source_path.is_empty() && cached_script.is_null()) {
+ MutexLock lock(GDScriptCache::singleton->mutex);
+ GDScriptCache::singleton->shallow_gdscript_cache[source_path] = Ref<GDScript>(this);
}
}
@@ -889,6 +862,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);
+ reloading = false;
return ERR_PARSE_ERROR;
}
@@ -905,6 +879,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();
}
+ reloading = false;
return ERR_PARSE_ERROR;
}
@@ -913,18 +888,16 @@ Error GDScript::reload(bool p_keep_state) {
GDScriptCompiler compiler;
err = compiler.compile(&parser, this, p_keep_state);
-#ifdef TOOLS_ENABLED
- _update_doc();
-#endif
-
if (err) {
if (can_run) {
if (EngineDebugger::is_active()) {
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);
+ reloading = false;
return ERR_COMPILATION_FAILED;
} else {
+ reloading = false;
return err;
}
}
@@ -932,19 +905,12 @@ Error GDScript::reload(bool p_keep_state) {
for (const GDScriptWarning &warning : parser.get_warnings()) {
if (EngineDebugger::is_active()) {
Vector<ScriptLanguage::StackInfo> si;
- EngineDebugger::get_script_debugger()->send_error("", get_path(), warning.start_line, warning.get_name(), warning.get_message(), false, ERR_HANDLER_WARNING, si);
+ EngineDebugger::get_script_debugger()->send_error("", get_script_path(), warning.start_line, warning.get_name(), warning.get_message(), false, ERR_HANDLER_WARNING, si);
}
}
#endif
- valid = true;
-
- for (KeyValue<StringName, Ref<GDScript>> &E : subclasses) {
- _set_subclass_path(E.value, path);
- }
-
- _init_rpc_methods_properties();
-
+ reloading = false;
return OK;
}
@@ -1051,11 +1017,26 @@ Error GDScript::load_byte_code(const String &p_path) {
}
void GDScript::set_path(const String &p_path, bool p_take_over) {
- Script::set_path(p_path, p_take_over);
+ String old_path = path;
+ if (is_root_script()) {
+ Script::set_path(p_path, p_take_over);
+ }
this->path = p_path;
+ GDScriptCache::move_script(old_path, p_path);
+ for (KeyValue<StringName, Ref<GDScript>> &kv : subclasses) {
+ kv.value->set_path(p_path, p_take_over);
+ }
+}
+
+String GDScript::get_script_path() const {
+ return path;
}
Error GDScript::load_source_code(const String &p_path) {
+ if (p_path.is_empty() || ResourceLoader::get_resource_type(p_path.get_slice("::", 0)) == "PackedScene") {
+ return OK;
+ }
+
Vector<uint8_t> sourcef;
Error err;
Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ, &err);
@@ -1127,6 +1108,131 @@ bool GDScript::inherits_script(const Ref<Script> &p_script) const {
return false;
}
+GDScript *GDScript::find_class(const String &p_qualified_name) {
+ String first = p_qualified_name.get_slice("::", 0);
+
+ Vector<String> class_names;
+ GDScript *result = nullptr;
+ // Empty initial name means start here.
+ if (first.is_empty() || first == name) {
+ class_names = p_qualified_name.split("::");
+ result = this;
+ } else if (p_qualified_name.begins_with(get_root_script()->path)) {
+ // Script path could have a class path separator("::") in it.
+ class_names = p_qualified_name.trim_prefix(get_root_script()->path).split("::");
+ result = get_root_script();
+ } else if (HashMap<StringName, Ref<GDScript>>::Iterator E = subclasses.find(first)) {
+ class_names = p_qualified_name.split("::");
+ result = E->value.ptr();
+ } else if (_owner != nullptr) {
+ // Check parent scope.
+ return _owner->find_class(p_qualified_name);
+ }
+
+ // Starts at index 1 because index 0 was handled above.
+ for (int i = 1; result != nullptr && i < class_names.size(); i++) {
+ String current_name = class_names[i];
+ if (HashMap<StringName, Ref<GDScript>>::Iterator E = result->subclasses.find(current_name)) {
+ result = E->value.ptr();
+ } else {
+ // Couldn't find inner class.
+ return nullptr;
+ }
+ }
+
+ return result;
+}
+
+bool GDScript::has_class(const GDScript *p_script) {
+ String fqn = p_script->fully_qualified_name;
+ if (fully_qualified_name.is_empty() && fqn.get_slice("::", 0).is_empty()) {
+ return p_script == this;
+ } else if (fqn.begins_with(fully_qualified_name)) {
+ return p_script == find_class(fqn.trim_prefix(fully_qualified_name));
+ }
+ return false;
+}
+
+GDScript *GDScript::get_root_script() {
+ GDScript *result = this;
+ while (result->_owner) {
+ result = result->_owner;
+ }
+ return result;
+}
+
+RBSet<GDScript *> GDScript::get_dependencies() {
+ RBSet<GDScript *> dependencies;
+
+ _get_dependencies(dependencies, this);
+ dependencies.erase(this);
+
+ return dependencies;
+}
+
+RBSet<GDScript *> GDScript::get_inverted_dependencies() {
+ RBSet<GDScript *> inverted_dependencies;
+
+ List<GDScript *> scripts;
+ {
+ MutexLock lock(GDScriptLanguage::singleton->mutex);
+
+ SelfList<GDScript> *elem = GDScriptLanguage::singleton->script_list.first();
+ while (elem) {
+ scripts.push_back(elem->self());
+ elem = elem->next();
+ }
+ }
+
+ for (GDScript *scr : scripts) {
+ if (scr == nullptr || scr == this || scr->destructing) {
+ continue;
+ }
+
+ RBSet<GDScript *> scr_dependencies = scr->get_dependencies();
+ if (scr_dependencies.has(this)) {
+ inverted_dependencies.insert(scr);
+ }
+ }
+
+ return inverted_dependencies;
+}
+
+RBSet<GDScript *> GDScript::get_must_clear_dependencies() {
+ RBSet<GDScript *> dependencies = get_dependencies();
+ RBSet<GDScript *> must_clear_dependencies;
+ HashMap<GDScript *, RBSet<GDScript *>> inverted_dependencies;
+
+ for (GDScript *E : dependencies) {
+ inverted_dependencies.insert(E, E->get_inverted_dependencies());
+ }
+
+ RBSet<GDScript *> cant_clear;
+ for (KeyValue<GDScript *, RBSet<GDScript *>> &E : inverted_dependencies) {
+ for (GDScript *F : E.value) {
+ if (!dependencies.has(F)) {
+ cant_clear.insert(E.key);
+ for (GDScript *G : E.key->get_dependencies()) {
+ cant_clear.insert(G);
+ }
+ break;
+ }
+ }
+ }
+
+ for (KeyValue<GDScript *, RBSet<GDScript *>> &E : inverted_dependencies) {
+ if (cant_clear.has(E.key) || ScriptServer::is_global_class(E.key->get_fully_qualified_name())) {
+ continue;
+ }
+ must_clear_dependencies.insert(E.key);
+ }
+
+ cant_clear.clear();
+ dependencies.clear();
+ inverted_dependencies.clear();
+ return must_clear_dependencies;
+}
+
bool GDScript::has_script_signal(const StringName &p_signal) const {
if (_signals.has(p_signal)) {
return true;
@@ -1188,15 +1294,71 @@ String GDScript::_get_gdscript_reference_class_name(const GDScript *p_gdscript)
return class_name;
}
+GDScript *GDScript::_get_gdscript_from_variant(const Variant &p_variant) {
+ Object *obj = p_variant;
+ if (obj == nullptr || obj->get_instance_id().is_null()) {
+ return nullptr;
+ }
+ return Object::cast_to<GDScript>(obj);
+}
+
+void GDScript::_get_dependencies(RBSet<GDScript *> &p_dependencies, const GDScript *p_except) {
+ if (skip_dependencies || p_dependencies.has(this)) {
+ return;
+ }
+ p_dependencies.insert(this);
+
+ for (const KeyValue<StringName, GDScriptFunction *> &E : member_functions) {
+ if (E.value == nullptr) {
+ continue;
+ }
+ for (const Variant &V : E.value->constants) {
+ GDScript *scr = _get_gdscript_from_variant(V);
+ if (scr != nullptr && scr != p_except) {
+ scr->_get_dependencies(p_dependencies, p_except);
+ }
+ }
+ }
+
+ if (implicit_initializer) {
+ for (const Variant &V : implicit_initializer->constants) {
+ GDScript *scr = _get_gdscript_from_variant(V);
+ if (scr != nullptr && scr != p_except) {
+ scr->_get_dependencies(p_dependencies, p_except);
+ }
+ }
+ }
+
+ if (implicit_ready) {
+ for (const Variant &V : implicit_ready->constants) {
+ GDScript *scr = _get_gdscript_from_variant(V);
+ if (scr != nullptr && scr != p_except) {
+ scr->_get_dependencies(p_dependencies, p_except);
+ }
+ }
+ }
+
+ for (KeyValue<StringName, Ref<GDScript>> &E : subclasses) {
+ if (E.value != p_except) {
+ E.value->_get_dependencies(p_dependencies, p_except);
+ }
+ }
+
+ for (const KeyValue<StringName, Variant> &E : constants) {
+ GDScript *scr = _get_gdscript_from_variant(E.value);
+ if (scr != nullptr && scr != p_except) {
+ scr->_get_dependencies(p_dependencies, p_except);
+ }
+ }
+}
+
GDScript::GDScript() :
script_list(this) {
-#ifdef DEBUG_ENABLED
{
MutexLock lock(GDScriptLanguage::get_singleton()->mutex);
GDScriptLanguage::get_singleton()->script_list.add(&script_list);
}
-#endif
}
void GDScript::_save_orphaned_subclasses() {
@@ -1238,56 +1400,67 @@ void GDScript::_init_rpc_methods_properties() {
rpc_config = base->rpc_config.duplicate();
}
- GDScript *cscript = this;
- HashMap<StringName, Ref<GDScript>>::Iterator sub_E = subclasses.begin();
- while (cscript) {
- // RPC Methods
- for (KeyValue<StringName, GDScriptFunction *> &E : cscript->member_functions) {
- Variant config = E.value->get_rpc_config();
- if (config.get_type() != Variant::NIL) {
- rpc_config[E.value->get_name()] = config;
- }
- }
-
- if (cscript != this) {
- ++sub_E;
- }
-
- if (sub_E) {
- cscript = sub_E->value.ptr();
- } else {
- cscript = nullptr;
+ // RPC Methods
+ for (KeyValue<StringName, GDScriptFunction *> &E : member_functions) {
+ Variant config = E.value->get_rpc_config();
+ if (config.get_type() != Variant::NIL) {
+ rpc_config[E.value->get_name()] = config;
}
}
}
-GDScript::~GDScript() {
- {
- MutexLock lock(GDScriptLanguage::get_singleton()->mutex);
+void GDScript::clear() {
+ if (clearing) {
+ return;
+ }
+ clearing = true;
- while (SelfList<GDScriptFunctionState> *E = pending_func_states.first()) {
- // Order matters since clearing the stack may already cause
- // the GDSCriptFunctionState to be destroyed and thus removed from the list.
- pending_func_states.remove(E);
- E->self()->_clear_stack();
+ RBSet<GDScript *> must_clear_dependencies = get_must_clear_dependencies();
+ HashMap<GDScript *, ObjectID> must_clear_dependencies_objectids;
+
+ // Log the objectids before clearing, as a cascade of clear could
+ // remove instances that are still in the clear loop
+ for (GDScript *E : must_clear_dependencies) {
+ must_clear_dependencies_objectids.insert(E, E->get_instance_id());
+ }
+
+ for (GDScript *E : must_clear_dependencies) {
+ Object *obj = ObjectDB::get_instance(must_clear_dependencies_objectids[E]);
+ if (obj == nullptr) {
+ continue;
}
+
+ E->skip_dependencies = true;
+ E->clear();
+ E->skip_dependencies = false;
+ GDScriptCache::remove_script(E->get_path());
}
+ RBSet<StringName> member_function_names;
for (const KeyValue<StringName, GDScriptFunction *> &E : member_functions) {
- memdelete(E.value);
+ member_function_names.insert(E.key);
+ }
+ for (const StringName &E : member_function_names) {
+ if (member_functions.has(E)) {
+ memdelete(member_functions[E]);
+ }
+ }
+ member_function_names.clear();
+ member_functions.clear();
+
+ for (KeyValue<StringName, GDScript::MemberInfo> &E : member_indices) {
+ E.value.data_type.script_type_ref = Ref<Script>();
}
if (implicit_initializer) {
memdelete(implicit_initializer);
}
+ implicit_initializer = nullptr;
if (implicit_ready) {
memdelete(implicit_ready);
}
-
- if (GDScriptCache::singleton) { // Cache may have been already destroyed at engine shutdown.
- GDScriptCache::remove_script(get_path());
- }
+ implicit_ready = nullptr;
_save_orphaned_subclasses();
@@ -1297,14 +1470,37 @@ GDScript::~GDScript() {
_clear_doc();
}
#endif
+ clearing = false;
+}
+
+GDScript::~GDScript() {
+ if (destructing) {
+ return;
+ }
+ destructing = true;
+
+ clear();
+
+ {
+ MutexLock lock(GDScriptLanguage::get_singleton()->mutex);
+
+ while (SelfList<GDScriptFunctionState> *E = pending_func_states.first()) {
+ // Order matters since clearing the stack may already cause
+ // the GDScriptFunctionState to be destroyed and thus removed from the list.
+ pending_func_states.remove(E);
+ E->self()->_clear_stack();
+ }
+ }
-#ifdef DEBUG_ENABLED
{
MutexLock lock(GDScriptLanguage::get_singleton()->mutex);
GDScriptLanguage::get_singleton()->script_list.remove(&script_list);
}
-#endif
+
+ if (GDScriptCache::singleton) { // Cache may have been already destroyed at engine shutdown.
+ GDScriptCache::remove_script(get_path());
+ }
}
//////////////////////////////
@@ -1770,6 +1966,16 @@ void GDScriptLanguage::add_named_global_constant(const StringName &p_name, const
named_globals[p_name] = p_value;
}
+Variant GDScriptLanguage::get_any_global_constant(const StringName &p_name) {
+ if (named_globals.has(p_name)) {
+ return named_globals[p_name];
+ }
+ if (globals.has(p_name)) {
+ return _global_array[globals[p_name]];
+ }
+ ERR_FAIL_V_MSG(Variant(), vformat("Could not find any global constant with name: %s.", p_name));
+}
+
void GDScriptLanguage::remove_named_global_constant(const StringName &p_name) {
ERR_FAIL_COND(!named_globals.has(p_name));
named_globals.erase(p_name);
@@ -1826,6 +2032,42 @@ Error GDScriptLanguage::execute_file(const String &p_path) {
}
void GDScriptLanguage::finish() {
+ if (_call_stack) {
+ memdelete_arr(_call_stack);
+ _call_stack = nullptr;
+ }
+
+ // Clear the cache before parsing the script_list
+ GDScriptCache::clear();
+
+ // Clear dependencies between scripts, to ensure cyclic references are broken
+ // (to avoid leaks at exit).
+ SelfList<GDScript> *s = script_list.first();
+ while (s) {
+ // This ensures the current script is not released before we can check
+ // what's the next one in the list (we can't get the next upfront because we
+ // don't know if the reference breaking will cause it -or any other after
+ // it, for that matter- to be released so the next one is not the same as
+ // before).
+ Ref<GDScript> scr = s->self();
+ if (scr.is_valid()) {
+ for (KeyValue<StringName, GDScriptFunction *> &E : scr->member_functions) {
+ GDScriptFunction *func = E.value;
+ for (int i = 0; i < func->argument_types.size(); i++) {
+ func->argument_types.write[i].script_type_ref = Ref<Script>();
+ }
+ func->return_type.script_type_ref = Ref<Script>();
+ }
+ for (KeyValue<StringName, GDScript::MemberInfo> &E : scr->member_indices) {
+ E.value.data_type.script_type_ref = Ref<Script>();
+ }
+
+ // Clear backup for scripts that could slip out of the cyclic reference
+ // check
+ scr->clear();
+ }
+ s = s->next();
+ }
}
void GDScriptLanguage::profiling_start() {
@@ -1935,7 +2177,8 @@ void GDScriptLanguage::reload_all_scripts() {
SelfList<GDScript> *elem = script_list.first();
while (elem) {
- if (elem->self()->get_path().is_resource_file()) {
+ // Scripts will reload all subclasses, so only reload root scripts.
+ if (elem->self()->is_root_script() && elem->self()->get_path().is_resource_file()) {
print_verbose("GDScript: Found: " + elem->self()->get_path());
scripts.push_back(Ref<GDScript>(elem->self())); //cast to gdscript to avoid being erased by accident
}
@@ -1964,7 +2207,8 @@ void GDScriptLanguage::reload_tool_script(const Ref<Script> &p_script, bool p_so
SelfList<GDScript> *elem = script_list.first();
while (elem) {
- if (elem->self()->get_path().is_resource_file()) {
+ // Scripts will reload all subclasses, so only reload root scripts.
+ if (elem->self()->is_root_script() && elem->self()->get_path().is_resource_file()) {
scripts.push_back(Ref<GDScript>(elem->self())); //cast to gdscript to avoid being erased by accident
}
elem = elem->next();
@@ -2337,35 +2581,6 @@ GDScriptLanguage::GDScriptLanguage() {
}
GDScriptLanguage::~GDScriptLanguage() {
- if (_call_stack) {
- memdelete_arr(_call_stack);
- }
-
- // Clear dependencies between scripts, to ensure cyclic references are broken (to avoid leaks at exit).
- SelfList<GDScript> *s = script_list.first();
- while (s) {
- GDScript *scr = s->self();
- // This ensures the current script is not released before we can check what's the next one
- // in the list (we can't get the next upfront because we don't know if the reference breaking
- // will cause it -or any other after it, for that matter- to be released so the next one
- // is not the same as before).
- scr->reference();
-
- for (KeyValue<StringName, GDScriptFunction *> &E : scr->member_functions) {
- GDScriptFunction *func = E.value;
- for (int i = 0; i < func->argument_types.size(); i++) {
- func->argument_types.write[i].script_type_ref = Ref<Script>();
- }
- func->return_type.script_type_ref = Ref<Script>();
- }
- for (KeyValue<StringName, GDScript::MemberInfo> &E : scr->member_indices) {
- E.value.data_type.script_type_ref = Ref<Script>();
- }
-
- s = s->next();
- scr->unreference();
- }
-
singleton = nullptr;
}
@@ -2387,6 +2602,26 @@ Ref<GDScript> GDScriptLanguage::get_orphan_subclass(const String &p_qualified_na
return Ref<GDScript>(Object::cast_to<GDScript>(obj));
}
+Ref<GDScript> GDScriptLanguage::get_script_by_fully_qualified_name(const String &p_name) {
+ {
+ MutexLock lock(mutex);
+
+ SelfList<GDScript> *elem = script_list.first();
+ while (elem) {
+ GDScript *scr = elem->self();
+ if (scr->fully_qualified_name == p_name) {
+ return scr;
+ }
+ elem = elem->next();
+ }
+ }
+
+ Ref<GDScript> scr;
+ scr.instantiate();
+ scr->fully_qualified_name = p_name;
+ return scr;
+}
+
/*************** RESOURCE ***************/
Ref<Resource> ResourceFormatLoaderGDScript::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) {
diff --git a/modules/gdscript/gdscript.h b/modules/gdscript/gdscript.h
index 72ad890fbc..39367e377b 100644
--- a/modules/gdscript/gdscript.h
+++ b/modules/gdscript/gdscript.h
@@ -61,6 +61,8 @@ class GDScript : public Script {
GDCLASS(GDScript, Script);
bool tool = false;
bool valid = false;
+ bool reloading = false;
+ bool skip_dependencies = false;
struct MemberInfo {
int index = 0;
@@ -124,6 +126,8 @@ class GDScript : public Script {
int subclass_count = 0;
RBSet<Object *> instances;
+ bool destructing = false;
+ bool clearing = false;
//exported members
String source;
String path;
@@ -137,7 +141,6 @@ class GDScript : public Script {
void _super_implicit_constructor(GDScript *p_script, GDScriptInstance *p_instance, Callable::CallError &r_error);
GDScriptInstance *_create_instance(const Variant **p_args, int p_argcount, Object *p_owner, bool p_is_ref_counted, Callable::CallError &r_error);
- void _set_subclass_path(Ref<GDScript> &p_sc, const String &p_path);
String _get_debug_path() const;
#ifdef TOOLS_ENABLED
@@ -164,6 +167,9 @@ class GDScript : public Script {
// This method will map the class name from "RefCounted" to "MyClass.InnerClass".
static String _get_gdscript_reference_class_name(const GDScript *p_gdscript);
+ GDScript *_get_gdscript_from_variant(const Variant &p_variant);
+ void _get_dependencies(RBSet<GDScript *> &p_dependencies, const GDScript *p_except);
+
protected:
bool _get(const StringName &p_name, Variant &r_ret) const;
bool _set(const StringName &p_name, const Variant &p_value);
@@ -174,10 +180,17 @@ protected:
static void _bind_methods();
public:
+ void clear();
+
virtual bool is_valid() const override { return valid; }
bool inherits_script(const Ref<Script> &p_script) const override;
+ GDScript *find_class(const String &p_qualified_name);
+ bool has_class(const GDScript *p_script);
+ GDScript *get_root_script();
+ bool is_root_script() const { return _owner == nullptr; }
+ String get_fully_qualified_name() const { return fully_qualified_name; }
const HashMap<StringName, Ref<GDScript>> &get_subclasses() const { return subclasses; }
const HashMap<StringName, Variant> &get_constants() const { return constants; }
const HashSet<StringName> &get_members() const { return members; }
@@ -189,6 +202,10 @@ public:
const Ref<GDScriptNativeClass> &get_native() const { return native; }
const String &get_script_class_name() const { return name; }
+ RBSet<GDScript *> get_dependencies();
+ RBSet<GDScript *> get_inverted_dependencies();
+ RBSet<GDScript *> get_must_clear_dependencies();
+
virtual bool has_script_signal(const StringName &p_signal) const override;
virtual void get_script_signal_list(List<MethodInfo> *r_signals) const override;
@@ -223,7 +240,7 @@ public:
virtual Error reload(bool p_keep_state = false) override;
virtual void set_path(const String &p_path, bool p_take_over = false) override;
- void set_script_path(const String &p_path) { path = p_path; } //because subclasses need a path too...
+ String get_script_path() const;
Error load_source_code(const String &p_path);
Error load_byte_code(const String &p_path);
@@ -267,6 +284,7 @@ class GDScriptInstance : public ScriptInstance {
friend class GDScriptLambdaCallable;
friend class GDScriptLambdaSelfCallable;
friend class GDScriptCompiler;
+ friend class GDScriptCache;
friend struct GDScriptUtilityFunctionsDefinitions;
ObjectID owner_id;
@@ -415,7 +433,7 @@ public:
csi.write[_debug_call_stack_pos - i - 1].line = _call_stack[i].line ? *_call_stack[i].line : 0;
if (_call_stack[i].function) {
csi.write[_debug_call_stack_pos - i - 1].func = _call_stack[i].function->get_name();
- csi.write[_debug_call_stack_pos - i - 1].file = _call_stack[i].function->get_script()->get_path();
+ csi.write[_debug_call_stack_pos - i - 1].file = _call_stack[i].function->get_script()->get_script_path();
}
}
return csi;
@@ -437,6 +455,9 @@ public:
_FORCE_INLINE_ Variant *get_global_array() { return _global_array; }
_FORCE_INLINE_ const HashMap<StringName, int> &get_global_map() const { return globals; }
_FORCE_INLINE_ const HashMap<StringName, Variant> &get_named_globals_map() const { return named_globals; }
+ // These two functions should be used when behavior needs to be consistent between in-editor and running the scene
+ bool has_any_global_constant(const StringName &p_name) { return named_globals.has(p_name) || globals.has(p_name); }
+ Variant get_any_global_constant(const StringName &p_name);
_FORCE_INLINE_ static GDScriptLanguage *get_singleton() { return singleton; }
@@ -515,6 +536,8 @@ public:
void add_orphan_subclass(const String &p_qualified_name, const ObjectID &p_subclass);
Ref<GDScript> get_orphan_subclass(const String &p_qualified_name);
+ Ref<GDScript> get_script_by_fully_qualified_name(const String &p_name);
+
GDScriptLanguage();
~GDScriptLanguage();
};
diff --git a/modules/gdscript/gdscript_analyzer.cpp b/modules/gdscript/gdscript_analyzer.cpp
index 704dda8045..1556957074 100644
--- a/modules/gdscript/gdscript_analyzer.cpp
+++ b/modules/gdscript/gdscript_analyzer.cpp
@@ -32,6 +32,7 @@
#include "core/config/engine.h"
#include "core/config/project_settings.h"
+#include "core/core_string_names.h"
#include "core/io/file_access.h"
#include "core/io/resource_loader.h"
#include "core/object/class_db.h"
@@ -39,6 +40,7 @@
#include "core/templates/hash_map.h"
#include "gdscript.h"
#include "gdscript_utility_functions.h"
+#include "scene/resources/packed_scene.h"
static MethodInfo info_from_utility_func(const StringName &p_function) {
ERR_FAIL_COND_V(!Variant::has_utility_function(p_function), MethodInfo());
@@ -132,7 +134,7 @@ static GDScriptParser::DataType make_builtin_meta_type(Variant::Type p_type) {
return type;
}
-bool GDScriptAnalyzer::has_member_name_conflict_in_script_class(const StringName &p_member_name, const GDScriptParser::ClassNode *p_class) {
+bool GDScriptAnalyzer::has_member_name_conflict_in_script_class(const StringName &p_member_name, const GDScriptParser::ClassNode *p_class, const GDScriptParser::Node *p_member) {
if (p_class->members_indices.has(p_member_name)) {
int index = p_class->members_indices[p_member_name];
const GDScriptParser::ClassNode::Member *member = &p_class->members[index];
@@ -145,6 +147,9 @@ bool GDScriptAnalyzer::has_member_name_conflict_in_script_class(const StringName
member->type == GDScriptParser::ClassNode::Member::SIGNAL) {
return true;
}
+ if (p_member->type != GDScriptParser::Node::FUNCTION && member->type == GDScriptParser::ClassNode::Member::FUNCTION) {
+ return true;
+ }
}
return false;
@@ -160,6 +165,9 @@ bool GDScriptAnalyzer::has_member_name_conflict_in_native_type(const StringName
if (ClassDB::has_integer_constant(p_native_type_string, p_member_name)) {
return true;
}
+ if (p_member_name == CoreStringNames::get_singleton()->_script) {
+ return true;
+ }
return false;
}
@@ -187,14 +195,18 @@ Error GDScriptAnalyzer::check_class_member_name_conflict(const GDScriptParser::C
const GDScriptParser::DataType *current_data_type = &p_class_node->base_type;
while (current_data_type && current_data_type->kind == GDScriptParser::DataType::Kind::CLASS) {
GDScriptParser::ClassNode *current_class_node = current_data_type->class_type;
- if (has_member_name_conflict_in_script_class(p_member_name, current_class_node)) {
- push_error(vformat(R"(The member "%s" already exists in a parent class.)", p_member_name),
- p_member_node);
+ if (has_member_name_conflict_in_script_class(p_member_name, current_class_node, p_member_node)) {
+ String parent_class_name = current_class_node->fqcn;
+ if (current_class_node->identifier != nullptr) {
+ parent_class_name = current_class_node->identifier->name;
+ }
+ push_error(vformat(R"(The member "%s" already exists in parent class %s.)", p_member_name, parent_class_name), p_member_node);
return ERR_PARSE_ERROR;
}
current_data_type = &current_class_node->base_type;
}
+ // No need for native class recursion because Node exposes all Object's properties.
if (current_data_type && current_data_type->kind == GDScriptParser::DataType::Kind::NATIVE) {
if (current_data_type->native_type != StringName()) {
return check_native_member_name_conflict(
@@ -207,25 +219,76 @@ Error GDScriptAnalyzer::check_class_member_name_conflict(const GDScriptParser::C
return OK;
}
-Error GDScriptAnalyzer::resolve_inheritance(GDScriptParser::ClassNode *p_class, bool p_recursive) {
- if (p_class->base_type.is_set()) {
- // Already resolved
+void GDScriptAnalyzer::get_class_node_current_scope_classes(GDScriptParser::ClassNode *p_node, List<GDScriptParser::ClassNode *> *p_list) {
+ if (p_list->find(p_node) != nullptr) {
+ return;
+ }
+ p_list->push_back(p_node);
+
+ // TODO: Try to solve class inheritance if not yet resolving.
+
+ // Prioritize node base type over its outer class
+ if (p_node->base_type.class_type != nullptr) {
+ get_class_node_current_scope_classes(p_node->base_type.class_type, p_list);
+ }
+
+ if (p_node->outer != nullptr) {
+ get_class_node_current_scope_classes(p_node->outer, p_list);
+ }
+}
+
+Error GDScriptAnalyzer::resolve_class_inheritance(GDScriptParser::ClassNode *p_class, const GDScriptParser::Node *p_source) {
+ if (p_source == nullptr && parser->has_class(p_class)) {
+ p_source = p_class;
+ }
+
+ if (p_class->base_type.is_resolving()) {
+ push_error(vformat(R"(Could not resolve class "%s": Cyclic reference.)", type_from_metatype(p_class->get_datatype()).to_string()), p_source);
+ return ERR_PARSE_ERROR;
+ }
+
+ if (!p_class->base_type.has_no_type()) {
+ // Already resolved.
return OK;
}
- if (p_class == parser->head) {
- if (p_class->identifier) {
- p_class->fqcn = p_class->identifier->name;
- } else {
- p_class->fqcn = parser->script_path;
+ if (!parser->has_class(p_class)) {
+ String script_path = p_class->get_datatype().script_path;
+ Ref<GDScriptParserRef> parser_ref = get_parser_for(script_path);
+ if (parser_ref.is_null()) {
+ push_error(vformat(R"(Could not find script "%s".)", script_path), p_source);
+ return ERR_PARSE_ERROR;
}
- } else {
- p_class->fqcn = p_class->outer->fqcn + "::" + String(p_class->identifier->name);
+
+ Error err = parser_ref->raise_status(GDScriptParserRef::PARSED);
+ if (err) {
+ push_error(vformat(R"(Could not parse script "%s": %s.)", script_path, error_names[err]), p_source);
+ return ERR_PARSE_ERROR;
+ }
+
+ ERR_FAIL_COND_V_MSG(!parser_ref->get_parser()->has_class(p_class), ERR_PARSE_ERROR, R"(Parser bug: Mismatched external parser.)");
+
+ GDScriptAnalyzer *other_analyzer = parser_ref->get_analyzer();
+ GDScriptParser *other_parser = parser_ref->get_parser();
+
+ int error_count = other_parser->errors.size();
+ other_analyzer->resolve_class_inheritance(p_class);
+ if (other_parser->errors.size() > error_count) {
+ push_error(vformat(R"(Could not resolve inheritance for class "%s".)", p_class->fqcn), p_source);
+ return ERR_PARSE_ERROR;
+ }
+
+ return OK;
}
+ GDScriptParser::ClassNode *previous_class = parser->current_class;
+ parser->current_class = p_class;
+
if (p_class->identifier) {
StringName class_name = p_class->identifier->name;
- if (class_exists(class_name)) {
+ if (GDScriptParser::get_builtin_type(class_name) < Variant::VARIANT_MAX) {
+ push_error(vformat(R"(Class "%s" hides a built-in type.)", class_name), p_class->identifier);
+ } else if (class_exists(class_name)) {
push_error(vformat(R"(Class "%s" hides a native class.)", class_name), p_class->identifier);
} else if (ScriptServer::is_global_class(class_name) && (ScriptServer::get_global_class_path(class_name) != parser->script_path || p_class != parser->head)) {
push_error(vformat(R"(Class "%s" hides a global script class.)", class_name), p_class->identifier);
@@ -234,7 +297,9 @@ Error GDScriptAnalyzer::resolve_inheritance(GDScriptParser::ClassNode *p_class,
}
}
- GDScriptParser::DataType result;
+ GDScriptParser::DataType resolving_datatype;
+ resolving_datatype.kind = GDScriptParser::DataType::RESOLVING;
+ p_class->base_type = resolving_datatype;
// Set datatype for class.
GDScriptParser::DataType class_type;
@@ -247,6 +312,7 @@ Error GDScriptAnalyzer::resolve_inheritance(GDScriptParser::ClassNode *p_class,
class_type.builtin_type = Variant::OBJECT;
p_class->set_datatype(class_type);
+ GDScriptParser::DataType result;
if (!p_class->extends_used) {
result.type_source = GDScriptParser::DataType::ANNOTATED_INFERRED;
result.kind = GDScriptParser::DataType::NATIVE;
@@ -268,7 +334,7 @@ Error GDScriptAnalyzer::resolve_inheritance(GDScriptParser::ClassNode *p_class,
return ERR_PARSE_ERROR;
}
- Error err = ext_parser->raise_status(GDScriptParserRef::INTERFACE_SOLVED);
+ Error err = ext_parser->raise_status(GDScriptParserRef::INHERITANCE_SOLVED);
if (err != OK) {
push_error(vformat(R"(Could not resolve super class inheritance from "%s".)", p_class->extends_path), p_class);
return err;
@@ -295,7 +361,7 @@ Error GDScriptAnalyzer::resolve_inheritance(GDScriptParser::ClassNode *p_class,
return ERR_PARSE_ERROR;
}
- Error err = base_parser->raise_status(GDScriptParserRef::INTERFACE_SOLVED);
+ Error err = base_parser->raise_status(GDScriptParserRef::INHERITANCE_SOLVED);
if (err != OK) {
push_error(vformat(R"(Could not resolve super class inheritance from "%s".)", name), p_class);
return err;
@@ -304,7 +370,7 @@ Error GDScriptAnalyzer::resolve_inheritance(GDScriptParser::ClassNode *p_class,
}
} else if (ProjectSettings::get_singleton()->has_autoload(name) && ProjectSettings::get_singleton()->get_autoload(name).is_singleton) {
const ProjectSettings::AutoloadInfo &info = ProjectSettings::get_singleton()->get_autoload(name);
- if (info.path.get_extension().to_lower() != ".gd") {
+ if (info.path.get_extension().to_lower() != GDScriptLanguage::get_singleton()->get_extension()) {
push_error(vformat(R"(Singleton %s is not a GDScript.)", info.name), p_class);
return ERR_PARSE_ERROR;
}
@@ -315,22 +381,24 @@ Error GDScriptAnalyzer::resolve_inheritance(GDScriptParser::ClassNode *p_class,
return ERR_PARSE_ERROR;
}
- Error err = info_parser->raise_status(GDScriptParserRef::INTERFACE_SOLVED);
+ Error err = info_parser->raise_status(GDScriptParserRef::INHERITANCE_SOLVED);
if (err != OK) {
push_error(vformat(R"(Could not resolve super class inheritance from "%s".)", name), p_class);
return err;
}
+ base = info_parser->get_parser()->head->get_datatype();
} else if (class_exists(name) && ClassDB::can_instantiate(name)) {
base.kind = GDScriptParser::DataType::NATIVE;
base.native_type = name;
} else {
// Look for other classes in script.
- GDScriptParser::ClassNode *look_class = p_class;
bool found = false;
- while (look_class != nullptr) {
+ List<GDScriptParser::ClassNode *> script_classes;
+ get_class_node_current_scope_classes(p_class, &script_classes);
+ for (GDScriptParser::ClassNode *look_class : script_classes) {
if (look_class->identifier && look_class->identifier->name == name) {
if (!look_class->get_datatype().is_set()) {
- Error err = resolve_inheritance(look_class, false);
+ Error err = resolve_class_inheritance(look_class, p_class);
if (err) {
return err;
}
@@ -339,19 +407,12 @@ Error GDScriptAnalyzer::resolve_inheritance(GDScriptParser::ClassNode *p_class,
found = true;
break;
}
- if (look_class->members_indices.has(name) && look_class->get_member(name).type == GDScriptParser::ClassNode::Member::CLASS) {
- GDScriptParser::ClassNode::Member member = look_class->get_member(name);
- if (!member.m_class->get_datatype().is_set()) {
- Error err = resolve_inheritance(member.m_class, false);
- if (err) {
- return err;
- }
- }
- base = member.m_class->get_datatype();
+ if (look_class->has_member(name)) {
+ resolve_class_member(look_class, name, p_class);
+ base = look_class->get_member(name).get_datatype();
found = true;
break;
}
- look_class = look_class->outer;
}
if (!found) {
@@ -384,7 +445,7 @@ Error GDScriptAnalyzer::resolve_inheritance(GDScriptParser::ClassNode *p_class,
result = base;
}
- if (!result.is_set()) {
+ if (!result.is_set() || result.has_no_type()) {
// TODO: More specific error messages.
push_error(vformat(R"(Could not resolve inheritance for class "%s".)", p_class->identifier == nullptr ? "<main>" : p_class->identifier->name), p_class);
return ERR_PARSE_ERROR;
@@ -404,10 +465,21 @@ Error GDScriptAnalyzer::resolve_inheritance(GDScriptParser::ClassNode *p_class,
class_type.native_type = result.native_type;
p_class->set_datatype(class_type);
+ parser->current_class = previous_class;
+
+ return OK;
+}
+
+Error GDScriptAnalyzer::resolve_class_inheritance(GDScriptParser::ClassNode *p_class, bool p_recursive) {
+ Error err = resolve_class_inheritance(p_class);
+ if (err) {
+ return err;
+ }
+
if (p_recursive) {
for (int i = 0; i < p_class->members.size(); i++) {
if (p_class->members[i].type == GDScriptParser::ClassNode::Member::CLASS) {
- Error err = resolve_inheritance(p_class->members[i].m_class, true);
+ err = resolve_class_inheritance(p_class->members[i].m_class, true);
if (err) {
return err;
}
@@ -419,14 +491,29 @@ Error GDScriptAnalyzer::resolve_inheritance(GDScriptParser::ClassNode *p_class,
}
GDScriptParser::DataType GDScriptAnalyzer::resolve_datatype(GDScriptParser::TypeNode *p_type) {
- GDScriptParser::DataType result;
+ GDScriptParser::DataType bad_type;
+ bad_type.kind = GDScriptParser::DataType::VARIANT;
+ bad_type.type_source = GDScriptParser::DataType::INFERRED;
if (p_type == nullptr) {
- result.kind = GDScriptParser::DataType::VARIANT;
- return result;
+ return bad_type;
}
- result.type_source = result.ANNOTATED_EXPLICIT;
+ if (p_type->get_datatype().is_resolving()) {
+ push_error(R"(Could not resolve datatype: Cyclic reference.)", p_type);
+ return bad_type;
+ }
+
+ if (!p_type->get_datatype().has_no_type()) {
+ return p_type->get_datatype();
+ }
+
+ GDScriptParser::DataType resolving_datatype;
+ resolving_datatype.kind = GDScriptParser::DataType::RESOLVING;
+ p_type->set_datatype(resolving_datatype);
+
+ GDScriptParser::DataType result;
+ result.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT;
result.builtin_type = Variant::OBJECT;
if (p_type->type_chain.is_empty()) {
@@ -440,29 +527,21 @@ GDScriptParser::DataType GDScriptAnalyzer::resolve_datatype(GDScriptParser::Type
StringName first = p_type->type_chain[0]->name;
if (first == SNAME("Variant")) {
- result.kind = GDScriptParser::DataType::VARIANT;
if (p_type->type_chain.size() > 1) {
- push_error(R"("Variant" type don't contain nested types.)", p_type->type_chain[1]);
- return GDScriptParser::DataType();
+ // TODO: Variant does actually have a nested Type though.
+ push_error(R"(Variant doesn't contain nested types.)", p_type->type_chain[1]);
+ return bad_type;
}
- return result;
- }
-
- if (first == SNAME("Object")) {
+ result.kind = GDScriptParser::DataType::VARIANT;
+ } else if (first == SNAME("Object")) {
+ // Object is treated like a native type, not a built-in.
result.kind = GDScriptParser::DataType::NATIVE;
result.native_type = SNAME("Object");
- if (p_type->type_chain.size() > 1) {
- push_error(R"("Object" type don't contain nested types.)", p_type->type_chain[1]);
- return GDScriptParser::DataType();
- }
- return result;
- }
-
- if (GDScriptParser::get_builtin_type(first) < Variant::VARIANT_MAX) {
+ } else if (GDScriptParser::get_builtin_type(first) < Variant::VARIANT_MAX) {
// Built-in types.
if (p_type->type_chain.size() > 1) {
push_error(R"(Built-in types don't contain nested types.)", p_type->type_chain[1]);
- return GDScriptParser::DataType();
+ return bad_type;
}
result.kind = GDScriptParser::DataType::BUILTIN;
result.builtin_type = GDScriptParser::get_builtin_type(first);
@@ -488,15 +567,15 @@ GDScriptParser::DataType GDScriptAnalyzer::resolve_datatype(GDScriptParser::Type
String ext = path.get_extension();
if (ext == GDScriptLanguage::get_singleton()->get_extension()) {
Ref<GDScriptParserRef> ref = get_parser_for(path);
- if (!ref.is_valid() || ref->raise_status(GDScriptParserRef::INTERFACE_SOLVED) != OK) {
+ if (!ref.is_valid() || ref->raise_status(GDScriptParserRef::INHERITANCE_SOLVED) != OK) {
push_error(vformat(R"(Could not parse global class "%s" from "%s".)", first, ScriptServer::get_global_class_path(first)), p_type);
- return GDScriptParser::DataType();
+ return bad_type;
}
result = ref->get_parser()->head->get_datatype();
} else {
result.kind = GDScriptParser::DataType::SCRIPT;
- result.native_type = ScriptServer::get_global_class_native_base(first);
result.script_type = ResourceLoader::load(path, "Script");
+ result.native_type = result.script_type->get_instance_base_type();
result.script_path = path;
result.is_constant = true;
result.is_meta_type = false;
@@ -505,9 +584,9 @@ GDScriptParser::DataType GDScriptAnalyzer::resolve_datatype(GDScriptParser::Type
} else if (ProjectSettings::get_singleton()->has_autoload(first) && ProjectSettings::get_singleton()->get_autoload(first).is_singleton) {
const ProjectSettings::AutoloadInfo &autoload = ProjectSettings::get_singleton()->get_autoload(first);
Ref<GDScriptParserRef> ref = get_parser_for(autoload.path);
- if (ref->raise_status(GDScriptParserRef::INTERFACE_SOLVED) != OK) {
+ if (ref->raise_status(GDScriptParserRef::INHERITANCE_SOLVED) != OK) {
push_error(vformat(R"(Could not parse singleton "%s" from "%s".)", first, autoload.path), p_type);
- return GDScriptParser::DataType();
+ return bad_type;
}
result = ref->get_parser()->head->get_datatype();
} else if (ClassDB::has_enum(parser->current_class->base_type.native_type, first)) {
@@ -515,38 +594,36 @@ GDScriptParser::DataType GDScriptAnalyzer::resolve_datatype(GDScriptParser::Type
result = make_native_enum_type(parser->current_class->base_type.native_type, first);
} else {
// Classes in current scope.
- GDScriptParser::ClassNode *script_class = parser->current_class;
- bool found = false;
- while (!found && script_class != nullptr) {
+ List<GDScriptParser::ClassNode *> script_classes;
+ get_class_node_current_scope_classes(parser->current_class, &script_classes);
+ for (GDScriptParser::ClassNode *script_class : script_classes) {
if (script_class->identifier && script_class->identifier->name == first) {
result = script_class->get_datatype();
- found = true;
break;
}
if (script_class->members_indices.has(first)) {
- GDScriptParser::ClassNode::Member member = script_class->members[script_class->members_indices[first]];
+ resolve_class_member(script_class, first, p_type);
+
+ GDScriptParser::ClassNode::Member member = script_class->get_member(first);
switch (member.type) {
case GDScriptParser::ClassNode::Member::CLASS:
- result = member.m_class->get_datatype();
- found = true;
+ result = member.get_datatype();
break;
case GDScriptParser::ClassNode::Member::ENUM:
- result = member.m_enum->get_datatype();
- found = true;
+ result = member.get_datatype();
break;
case GDScriptParser::ClassNode::Member::CONSTANT:
- if (member.constant->get_datatype().is_meta_type) {
- result = member.constant->get_datatype();
+ if (member.get_datatype().is_meta_type) {
+ result = member.get_datatype();
result.is_meta_type = false;
- found = true;
break;
} else if (Ref<Script>(member.constant->initializer->reduced_value).is_valid()) {
Ref<GDScript> gdscript = member.constant->initializer->reduced_value;
if (gdscript.is_valid()) {
- Ref<GDScriptParserRef> ref = get_parser_for(gdscript->get_path());
- if (ref->raise_status(GDScriptParserRef::INTERFACE_SOLVED) != OK) {
- push_error(vformat(R"(Could not parse script from "%s".)", gdscript->get_path()), p_type);
- return GDScriptParser::DataType();
+ Ref<GDScriptParserRef> ref = get_parser_for(gdscript->get_script_path());
+ if (ref->raise_status(GDScriptParserRef::INHERITANCE_SOLVED) != OK) {
+ push_error(vformat(R"(Could not parse script from "%s".)", gdscript->get_script_path()), p_type);
+ return bad_type;
}
result = ref->get_parser()->head->get_datatype();
result.is_meta_type = false;
@@ -564,16 +641,14 @@ GDScriptParser::DataType GDScriptAnalyzer::resolve_datatype(GDScriptParser::Type
[[fallthrough]];
default:
push_error(vformat(R"("%s" is a %s but does not contain a type.)", first, member.get_type_name()), p_type);
- return GDScriptParser::DataType();
+ return bad_type;
}
}
- script_class = script_class->outer;
}
}
if (!result.is_set()) {
push_error(vformat(R"("%s" was not found in the current scope.)", first), p_type);
- result.kind = GDScriptParser::DataType::VARIANT; // Leave Variant anyway so future type check don't use an unresolved type.
- return result;
+ return bad_type;
}
if (p_type->type_chain.size() > 1) {
@@ -584,27 +659,26 @@ GDScriptParser::DataType GDScriptAnalyzer::resolve_datatype(GDScriptParser::Type
result = p_type->type_chain[i]->get_datatype();
if (!result.is_set()) {
push_error(vformat(R"(Could not find type "%s" under base "%s".)", p_type->type_chain[i]->name, base.to_string()), p_type->type_chain[1]);
- result.kind = GDScriptParser::DataType::VARIANT; // Leave Variant anyway so future type check don't use an unresolved type.
- return result;
+ return bad_type;
} else if (!result.is_meta_type) {
push_error(vformat(R"(Member "%s" under base "%s" is not a valid type.)", p_type->type_chain[i]->name, base.to_string()), p_type->type_chain[1]);
- result.kind = GDScriptParser::DataType::VARIANT; // Leave Variant anyway so future type check don't use an unresolved type.
- return result;
+ return bad_type;
}
}
} else if (result.kind == GDScriptParser::DataType::NATIVE) {
// Only enums allowed for native.
- if (ClassDB::has_enum(result.native_type, p_type->type_chain[1]->name)) {
- if (p_type->type_chain.size() > 2) {
- push_error(R"(Enums cannot contain nested types.)", p_type->type_chain[2]);
- } else {
- result = make_native_enum_type(result.native_type, p_type->type_chain[1]->name);
- }
+ if (!ClassDB::has_enum(result.native_type, p_type->type_chain[1]->name)) {
+ push_error(vformat(R"(Could not find nested type "%s" under base "%s".)", p_type->type_chain[1]->name, result.to_string()), p_type->type_chain[1]);
+ return bad_type;
}
+ if (p_type->type_chain.size() > 2) {
+ push_error(R"(Enums cannot contain nested types.)", p_type->type_chain[2]);
+ return bad_type;
+ }
+ result = make_native_enum_type(result.native_type, p_type->type_chain[1]->name);
} else {
push_error(vformat(R"(Could not find nested type "%s" under base "%s".)", p_type->type_chain[1]->name, result.to_string()), p_type->type_chain[1]);
- result.kind = GDScriptParser::DataType::VARIANT; // Leave Variant anyway so future type check don't use an unresolved type.
- return result;
+ return bad_type;
}
}
@@ -616,22 +690,77 @@ GDScriptParser::DataType GDScriptAnalyzer::resolve_datatype(GDScriptParser::Type
return result;
}
-void GDScriptAnalyzer::resolve_class_interface(GDScriptParser::ClassNode *p_class) {
- if (p_class->resolved_interface) {
+void GDScriptAnalyzer::resolve_class_member(GDScriptParser::ClassNode *p_class, StringName p_name, const GDScriptParser::Node *p_source) {
+ ERR_FAIL_COND(!p_class->has_member(p_name));
+ resolve_class_member(p_class, p_class->members_indices[p_name], p_source);
+}
+
+void GDScriptAnalyzer::resolve_class_member(GDScriptParser::ClassNode *p_class, int p_index, const GDScriptParser::Node *p_source) {
+ ERR_FAIL_INDEX(p_index, p_class->members.size());
+
+ GDScriptParser::ClassNode::Member &member = p_class->members.write[p_index];
+ if (p_source == nullptr && parser->has_class(p_class)) {
+ p_source = member.get_source_node();
+ }
+
+ if (member.get_datatype().is_resolving()) {
+ push_error(vformat(R"(Could not resolve member "%s": Cyclic reference.)", member.get_name()), p_source);
+ return;
+ }
+
+ if (member.get_datatype().is_set()) {
+ return;
+ }
+
+ if (!parser->has_class(p_class)) {
+ String script_path = p_class->get_datatype().script_path;
+ Ref<GDScriptParserRef> parser_ref = get_parser_for(script_path);
+ if (parser_ref.is_null()) {
+ push_error(vformat(R"(Could not find script "%s" (While resolving "%s").)", script_path, member.get_name()), p_source);
+ return;
+ }
+
+ Error err = parser_ref->raise_status(GDScriptParserRef::PARSED);
+ if (err) {
+ push_error(vformat(R"(Could not resolve script "%s": %s (While resolving "%s").)", script_path, error_names[err], member.get_name()), p_source);
+ return;
+ }
+
+ ERR_FAIL_COND_MSG(!parser_ref->get_parser()->has_class(p_class), R"(Parser bug: Mismatched external parser.)");
+
+ GDScriptAnalyzer *other_analyzer = parser_ref->get_analyzer();
+ GDScriptParser *other_parser = parser_ref->get_parser();
+
+ int error_count = other_parser->errors.size();
+ other_analyzer->resolve_class_member(p_class, p_index);
+ if (other_parser->errors.size() > error_count) {
+ push_error(vformat(R"(Could not resolve member "%s".)", member.get_name()), p_source);
+ }
+
return;
}
- p_class->resolved_interface = true;
+
+ // If it's already resolving, that's ok.
+ if (!p_class->base_type.is_resolving()) {
+ Error err = resolve_class_inheritance(p_class);
+ if (err) {
+ return;
+ }
+ }
GDScriptParser::ClassNode *previous_class = parser->current_class;
parser->current_class = p_class;
- for (int i = 0; i < p_class->members.size(); i++) {
- GDScriptParser::ClassNode::Member member = p_class->members[i];
+ GDScriptParser::DataType resolving_datatype;
+ resolving_datatype.kind = GDScriptParser::DataType::RESOLVING;
+ {
switch (member.type) {
case GDScriptParser::ClassNode::Member::VARIABLE: {
check_class_member_name_conflict(p_class, member.variable->identifier->name, member.variable);
+ member.variable->set_datatype(resolving_datatype);
+
GDScriptParser::DataType datatype;
datatype.kind = GDScriptParser::DataType::VARIANT;
datatype.type_source = GDScriptParser::DataType::UNDETECTED;
@@ -643,7 +772,6 @@ void GDScriptAnalyzer::resolve_class_interface(GDScriptParser::ClassNode *p_clas
}
if (member.variable->initializer != nullptr) {
- member.variable->set_datatype(datatype); // Allow recursive usage.
reduce_expression(member.variable->initializer);
if ((member.variable->infer_datatype || (member.variable->datatype_specifier != nullptr && specified_type.has_container_element_type())) && member.variable->initializer->type == GDScriptParser::Node::ARRAY) {
// Typed array.
@@ -654,18 +782,14 @@ void GDScriptAnalyzer::resolve_class_interface(GDScriptParser::ClassNode *p_clas
}
}
datatype = member.variable->initializer->get_datatype();
+
if (datatype.type_source != GDScriptParser::DataType::UNDETECTED) {
datatype.type_source = GDScriptParser::DataType::INFERRED;
}
- }
- // Check if initializer is an unset identifier (ie: a variable within scope, but declared below)
- if (member.variable->initializer && !member.variable->initializer->get_datatype().is_set()) {
- if (member.variable->initializer->type == GDScriptParser::Node::IDENTIFIER) {
- GDScriptParser::IdentifierNode *initializer_identifier = static_cast<GDScriptParser::IdentifierNode *>(member.variable->initializer);
- push_error(vformat(R"(Identifier "%s" must be declared above current variable.)", initializer_identifier->name), member.variable->initializer);
- } else {
- ERR_PRINT("Parser bug (please report): tried to assign unset node without an identifier.");
+ if (!datatype.is_set()) {
+ push_error(vformat(R"(Could not resolve initializer for member "%s".)", member.variable->identifier->name), member.variable->initializer);
+ datatype.kind = GDScriptParser::DataType::VARIANT;
}
}
@@ -717,10 +841,9 @@ void GDScriptAnalyzer::resolve_class_interface(GDScriptParser::ClassNode *p_clas
case GDScriptParser::ClassNode::Member::CONSTANT: {
check_class_member_name_conflict(p_class, member.constant->identifier->name, member.constant);
- reduce_expression(member.constant->initializer);
+ member.constant->set_datatype(resolving_datatype);
GDScriptParser::DataType specified_type;
-
if (member.constant->datatype_specifier != nullptr) {
specified_type = resolve_datatype(member.constant->datatype_specifier);
specified_type.is_meta_type = false;
@@ -728,7 +851,9 @@ void GDScriptAnalyzer::resolve_class_interface(GDScriptParser::ClassNode *p_clas
GDScriptParser::DataType datatype;
if (member.constant->initializer) {
+ reduce_expression(member.constant->initializer);
datatype = member.constant->initializer->get_datatype();
+
if (member.constant->initializer->type == GDScriptParser::Node::ARRAY) {
GDScriptParser::ArrayNode *array = static_cast<GDScriptParser::ArrayNode *>(member.constant->initializer);
const_fold_array(array);
@@ -741,6 +866,11 @@ void GDScriptAnalyzer::resolve_class_interface(GDScriptParser::ClassNode *p_clas
const_fold_dictionary(static_cast<GDScriptParser::DictionaryNode *>(member.constant->initializer));
}
+ if (!datatype.is_set()) {
+ push_error(vformat(R"(Could not resolve initializer for member "%s".)", member.constant->identifier->name), member.constant->initializer);
+ datatype.kind = GDScriptParser::DataType::VARIANT;
+ }
+
if (!member.constant->initializer->is_constant) {
push_error(R"(Initializer for a constant must be a constant expression.)", member.constant->initializer);
}
@@ -769,18 +899,21 @@ void GDScriptAnalyzer::resolve_class_interface(GDScriptParser::ClassNode *p_clas
case GDScriptParser::ClassNode::Member::SIGNAL: {
check_class_member_name_conflict(p_class, member.signal->identifier->name, member.signal);
+ member.signal->set_datatype(resolving_datatype);
+
+ // This is the _only_ way to declare a signal. Therefore, we can generate its
+ // MethodInfo inline so it's a tiny bit more efficient.
+ MethodInfo mi = MethodInfo(member.signal->identifier->name);
+
for (int j = 0; j < member.signal->parameters.size(); j++) {
- GDScriptParser::DataType signal_type = resolve_datatype(member.signal->parameters[j]->datatype_specifier);
- signal_type.is_meta_type = false;
- member.signal->parameters[j]->set_datatype(signal_type);
+ GDScriptParser::ParameterNode *param = member.signal->parameters[j];
+ GDScriptParser::DataType param_type = resolve_datatype(param->datatype_specifier);
+ param_type.is_meta_type = false;
+ param->set_datatype(param_type);
+ mi.arguments.push_back(PropertyInfo(param_type.builtin_type, param->identifier->name));
+ // TODO: add signal parameter default values
}
- // TODO: Make MethodInfo from signal.
- GDScriptParser::DataType signal_type;
- signal_type.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT;
- signal_type.kind = GDScriptParser::DataType::BUILTIN;
- signal_type.builtin_type = Variant::SIGNAL;
-
- member.signal->set_datatype(signal_type);
+ member.signal->set_datatype(make_signal_type(mi));
// Apply annotations.
for (GDScriptParser::AnnotationNode *&E : member.signal->annotations) {
@@ -790,6 +923,8 @@ void GDScriptAnalyzer::resolve_class_interface(GDScriptParser::ClassNode *p_clas
case GDScriptParser::ClassNode::Member::ENUM: {
check_class_member_name_conflict(p_class, member.m_enum->identifier->name, member.m_enum);
+ member.m_enum->set_datatype(resolving_datatype);
+
GDScriptParser::DataType enum_type;
enum_type.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT;
enum_type.kind = GDScriptParser::DataType::ENUM;
@@ -799,9 +934,10 @@ void GDScriptAnalyzer::resolve_class_interface(GDScriptParser::ClassNode *p_clas
enum_type.is_meta_type = true;
enum_type.is_constant = true;
- // Enums can't be nested, so we can safely override this.
+ const GDScriptParser::EnumNode *prev_enum = current_enum;
current_enum = member.m_enum;
+ Dictionary dictionary;
for (int j = 0; j < member.m_enum->values.size(); j++) {
GDScriptParser::EnumNode::Value &element = member.m_enum->values.write[j];
@@ -825,11 +961,13 @@ void GDScriptAnalyzer::resolve_class_interface(GDScriptParser::ClassNode *p_clas
}
enum_type.enum_values[element.identifier->name] = element.value;
+ dictionary[String(element.identifier->name)] = element.value;
}
- current_enum = nullptr;
+ current_enum = prev_enum;
member.m_enum->set_datatype(enum_type);
+ member.m_enum->dictionary = dictionary;
// Apply annotations.
for (GDScriptParser::AnnotationNode *&E : member.m_enum->annotations) {
@@ -837,15 +975,18 @@ void GDScriptAnalyzer::resolve_class_interface(GDScriptParser::ClassNode *p_clas
}
} break;
case GDScriptParser::ClassNode::Member::FUNCTION:
- resolve_function_signature(member.function);
+ resolve_function_signature(member.function, p_source);
break;
case GDScriptParser::ClassNode::Member::ENUM_VALUE: {
if (member.enum_value.custom_value) {
check_class_member_name_conflict(p_class, member.enum_value.identifier->name, member.enum_value.custom_value);
+ member.enum_value.identifier->set_datatype(resolving_datatype);
+
+ const GDScriptParser::EnumNode *prev_enum = current_enum;
current_enum = member.enum_value.parent_enum;
reduce_expression(member.enum_value.custom_value);
- current_enum = nullptr;
+ current_enum = prev_enum;
if (!member.enum_value.custom_value->is_constant) {
push_error(R"(Enum values must be constant.)", member.enum_value.custom_value);
@@ -859,18 +1000,30 @@ void GDScriptAnalyzer::resolve_class_interface(GDScriptParser::ClassNode *p_clas
check_class_member_name_conflict(p_class, member.enum_value.identifier->name, member.enum_value.parent_enum);
if (member.enum_value.index > 0) {
- member.enum_value.value = member.enum_value.parent_enum->values[member.enum_value.index - 1].value + 1;
+ const GDScriptParser::EnumNode::Value &prev_value = member.enum_value.parent_enum->values[member.enum_value.index - 1];
+ resolve_class_member(p_class, prev_value.identifier->name, member.enum_value.identifier);
+ member.enum_value.value = prev_value.value + 1;
} else {
member.enum_value.value = 0;
}
member.enum_value.resolved = true;
}
+
// Also update the original references.
- member.enum_value.parent_enum->values.write[member.enum_value.index] = member.enum_value;
- p_class->members.write[i].enum_value = member.enum_value;
+ member.enum_value.parent_enum->values.set(member.enum_value.index, member.enum_value);
+
+ GDScriptParser::DataType datatype;
+ datatype.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT;
+ datatype.kind = GDScriptParser::DataType::BUILTIN;
+ datatype.builtin_type = Variant::INT;
+ member.enum_value.identifier->set_datatype(datatype);
} break;
case GDScriptParser::ClassNode::Member::CLASS:
check_class_member_name_conflict(p_class, member.m_class->identifier->name, member.m_class);
+ // If it's already resolving, that's ok.
+ if (!member.m_class->base_type.is_resolving()) {
+ resolve_class_inheritance(member.m_class, p_source);
+ }
break;
case GDScriptParser::ClassNode::Member::GROUP:
// No-op, but needed to silence warnings.
@@ -881,28 +1034,123 @@ void GDScriptAnalyzer::resolve_class_interface(GDScriptParser::ClassNode *p_clas
}
}
- // Recurse nested classes.
- for (int i = 0; i < p_class->members.size(); i++) {
- GDScriptParser::ClassNode::Member member = p_class->members[i];
- if (member.type != GDScriptParser::ClassNode::Member::CLASS) {
- continue;
+ parser->current_class = previous_class;
+}
+
+void GDScriptAnalyzer::resolve_class_interface(GDScriptParser::ClassNode *p_class, const GDScriptParser::Node *p_source) {
+ if (p_source == nullptr && parser->has_class(p_class)) {
+ p_source = p_class;
+ }
+
+ if (!p_class->resolved_interface) {
+ if (!parser->has_class(p_class)) {
+ String script_path = p_class->get_datatype().script_path;
+ Ref<GDScriptParserRef> parser_ref = get_parser_for(script_path);
+ if (parser_ref.is_null()) {
+ push_error(vformat(R"(Could not find script "%s".)", script_path), p_source);
+ return;
+ }
+
+ Error err = parser_ref->raise_status(GDScriptParserRef::PARSED);
+ if (err) {
+ push_error(vformat(R"(Could not resolve script "%s": %s.)", script_path, error_names[err]), p_source);
+ return;
+ }
+
+ ERR_FAIL_COND_MSG(!parser_ref->get_parser()->has_class(p_class), R"(Parser bug: Mismatched external parser.)");
+
+ GDScriptAnalyzer *other_analyzer = parser_ref->get_analyzer();
+ GDScriptParser *other_parser = parser_ref->get_parser();
+
+ int error_count = other_parser->errors.size();
+ other_analyzer->resolve_class_interface(p_class);
+ if (other_parser->errors.size() > error_count) {
+ push_error(vformat(R"(Could not resolve class "%s".)", p_class->fqcn), p_source);
+ }
+
+ return;
+ }
+ p_class->resolved_interface = true;
+
+ if (resolve_class_inheritance(p_class) != OK) {
+ return;
+ }
+
+ GDScriptParser::DataType base_type = p_class->base_type;
+ if (base_type.kind == GDScriptParser::DataType::CLASS) {
+ GDScriptParser::ClassNode *base_class = base_type.class_type;
+ resolve_class_interface(base_class, p_class);
}
- resolve_class_interface(member.m_class);
+ for (int i = 0; i < p_class->members.size(); i++) {
+ resolve_class_member(p_class, i);
+ }
}
+}
- parser->current_class = previous_class;
+void GDScriptAnalyzer::resolve_class_interface(GDScriptParser::ClassNode *p_class, bool p_recursive) {
+ resolve_class_interface(p_class);
+
+ if (p_recursive) {
+ for (int i = 0; i < p_class->members.size(); i++) {
+ GDScriptParser::ClassNode::Member member = p_class->members[i];
+ if (member.type == GDScriptParser::ClassNode::Member::CLASS) {
+ resolve_class_interface(member.m_class, true);
+ }
+ }
+ }
}
-void GDScriptAnalyzer::resolve_class_body(GDScriptParser::ClassNode *p_class) {
+void GDScriptAnalyzer::resolve_class_body(GDScriptParser::ClassNode *p_class, const GDScriptParser::Node *p_source) {
+ if (p_source == nullptr && parser->has_class(p_class)) {
+ p_source = p_class;
+ }
+
if (p_class->resolved_body) {
return;
}
+
+ if (!parser->has_class(p_class)) {
+ String script_path = p_class->get_datatype().script_path;
+ Ref<GDScriptParserRef> parser_ref = get_parser_for(script_path);
+ if (parser_ref.is_null()) {
+ push_error(vformat(R"(Could not find script "%s".)", script_path), p_source);
+ return;
+ }
+
+ Error err = parser_ref->raise_status(GDScriptParserRef::PARSED);
+ if (err) {
+ push_error(vformat(R"(Could not resolve script "%s": %s.)", script_path, error_names[err]), p_source);
+ return;
+ }
+
+ ERR_FAIL_COND_MSG(!parser_ref->get_parser()->has_class(p_class), R"(Parser bug: Mismatched external parser.)");
+
+ GDScriptAnalyzer *other_analyzer = parser_ref->get_analyzer();
+ GDScriptParser *other_parser = parser_ref->get_parser();
+
+ int error_count = other_parser->errors.size();
+ other_analyzer->resolve_class_body(p_class);
+ if (other_parser->errors.size() > error_count) {
+ push_error(vformat(R"(Could not resolve class "%s".)", p_class->fqcn), p_source);
+ }
+
+ return;
+ }
+
p_class->resolved_body = true;
GDScriptParser::ClassNode *previous_class = parser->current_class;
parser->current_class = p_class;
+ resolve_class_interface(p_class, p_source);
+
+ GDScriptParser::DataType base_type = p_class->base_type;
+ if (base_type.kind == GDScriptParser::DataType::CLASS) {
+ GDScriptParser::ClassNode *base_class = base_type.class_type;
+ resolve_class_body(base_class, p_class);
+ }
+
// Do functions and properties now.
for (int i = 0; i < p_class->members.size(); i++) {
GDScriptParser::ClassNode::Member member = p_class->members[i];
@@ -945,18 +1193,6 @@ void GDScriptAnalyzer::resolve_class_body(GDScriptParser::ClassNode *p_class) {
}
}
- parser->current_class = previous_class;
-
- // Recurse nested classes.
- for (int i = 0; i < p_class->members.size(); i++) {
- GDScriptParser::ClassNode::Member member = p_class->members[i];
- if (member.type != GDScriptParser::ClassNode::Member::CLASS) {
- continue;
- }
-
- resolve_class_body(member.m_class);
- }
-
// Check unused variables and datatypes of property getters and setters.
for (int i = 0; i < p_class->members.size(); i++) {
GDScriptParser::ClassNode::Member member = p_class->members[i];
@@ -1044,6 +1280,21 @@ void GDScriptAnalyzer::resolve_class_body(GDScriptParser::ClassNode *p_class) {
}
}
}
+
+ parser->current_class = previous_class;
+}
+
+void GDScriptAnalyzer::resolve_class_body(GDScriptParser::ClassNode *p_class, bool p_recursive) {
+ resolve_class_body(p_class);
+
+ if (p_recursive) {
+ for (int i = 0; i < p_class->members.size(); i++) {
+ GDScriptParser::ClassNode::Member member = p_class->members[i];
+ if (member.type == GDScriptParser::ClassNode::Member::CLASS) {
+ resolve_class_body(member.m_class, true);
+ }
+ }
+ }
}
void GDScriptAnalyzer::resolve_node(GDScriptParser::Node *p_node, bool p_is_root) {
@@ -1053,8 +1304,10 @@ void GDScriptAnalyzer::resolve_node(GDScriptParser::Node *p_node, bool p_is_root
case GDScriptParser::Node::NONE:
break; // Unreachable.
case GDScriptParser::Node::CLASS:
- resolve_class_interface(static_cast<GDScriptParser::ClassNode *>(p_node));
- resolve_class_body(static_cast<GDScriptParser::ClassNode *>(p_node));
+ if (OK == resolve_class_inheritance(static_cast<GDScriptParser::ClassNode *>(p_node), true)) {
+ resolve_class_interface(static_cast<GDScriptParser::ClassNode *>(p_node), true);
+ resolve_class_body(static_cast<GDScriptParser::ClassNode *>(p_node), true);
+ }
break;
case GDScriptParser::Node::CONSTANT:
resolve_constant(static_cast<GDScriptParser::ConstantNode *>(p_node));
@@ -1136,7 +1389,16 @@ void GDScriptAnalyzer::resolve_annotation(GDScriptParser::AnnotationNode *p_anno
// TODO: Add second validation function for annotations, so they can use checked types.
}
-void GDScriptAnalyzer::resolve_function_signature(GDScriptParser::FunctionNode *p_function) {
+void GDScriptAnalyzer::resolve_function_signature(GDScriptParser::FunctionNode *p_function, const GDScriptParser::Node *p_source) {
+ if (p_source == nullptr) {
+ p_source = p_function;
+ }
+
+ if (p_function->get_datatype().is_resolving()) {
+ push_error(vformat(R"(Could not resolve function "%s": Cyclic reference.)", p_function->identifier->name), p_source);
+ return;
+ }
+
if (p_function->resolved_signature) {
return;
}
@@ -1145,6 +1407,12 @@ void GDScriptAnalyzer::resolve_function_signature(GDScriptParser::FunctionNode *
GDScriptParser::FunctionNode *previous_function = parser->current_function;
parser->current_function = p_function;
+ GDScriptParser::DataType prev_datatype = p_function->get_datatype();
+
+ GDScriptParser::DataType resolving_datatype;
+ resolving_datatype.kind = GDScriptParser::DataType::RESOLVING;
+ p_function->set_datatype(resolving_datatype);
+
#ifdef TOOLS_ENABLED
int default_value_count = 0;
#endif // TOOLS_ENABLED
@@ -1163,6 +1431,8 @@ void GDScriptAnalyzer::resolve_function_signature(GDScriptParser::FunctionNode *
if (p_function->parameters[i]->default_value->is_constant) {
p_function->default_arg_values.push_back(p_function->parameters[i]->default_value->reduced_value);
+ } else {
+ p_function->default_arg_values.push_back(Variant()); // Prevent shift.
}
}
#endif // TOOLS_ENABLED
@@ -1215,11 +1485,7 @@ void GDScriptAnalyzer::resolve_function_signature(GDScriptParser::FunctionNode *
if (!valid) {
// Compute parent signature as a string to show in the error message.
- String parent_signature = parent_return_type.is_hard_type() ? parent_return_type.to_string() : "Variant";
- if (parent_signature == "null") {
- parent_signature = "void";
- }
- parent_signature += " " + p_function->identifier->name.operator String() + "(";
+ String parent_signature = p_function->identifier->name.operator String() + "(";
int j = 0;
for (const GDScriptParser::DataType &par_type : parameters_types) {
if (j > 0) {
@@ -1236,13 +1502,25 @@ void GDScriptAnalyzer::resolve_function_signature(GDScriptParser::FunctionNode *
j++;
}
- parent_signature += ")";
+ parent_signature += ") -> ";
+
+ const String return_type = parent_return_type.is_hard_type() ? parent_return_type.to_string() : "Variant";
+ if (return_type == "null") {
+ parent_signature += "void";
+ } else {
+ parent_signature += return_type;
+ }
+
push_error(vformat(R"(The function signature doesn't match the parent. Parent signature is "%s".)", parent_signature), p_function);
}
}
#endif // TOOLS_ENABLED
}
+ if (p_function->get_datatype().is_resolving()) {
+ p_function->set_datatype(prev_datatype);
+ }
+
parser->current_function = previous_function;
}
@@ -1473,6 +1751,12 @@ void GDScriptAnalyzer::resolve_variable(GDScriptParser::VariableNode *p_variable
type = p_variable->initializer->get_datatype();
+#ifdef DEBUG_ENABLED
+ if (p_variable->initializer->type == GDScriptParser::Node::CALL && type.is_hard_type() && type.kind == GDScriptParser::DataType::BUILTIN && type.builtin_type == Variant::NIL) {
+ parser->push_warning(p_variable->initializer, GDScriptWarning::VOID_ASSIGNMENT, static_cast<GDScriptParser::CallNode *>(p_variable->initializer)->function_name);
+ }
+#endif
+
if (p_variable->infer_datatype) {
type.type_source = GDScriptParser::DataType::ANNOTATED_INFERRED;
@@ -1486,11 +1770,6 @@ void GDScriptAnalyzer::resolve_variable(GDScriptParser::VariableNode *p_variable
} else {
type.type_source = GDScriptParser::DataType::INFERRED;
}
-#ifdef DEBUG_ENABLED
- if (p_variable->initializer->type == GDScriptParser::Node::CALL && type.kind == GDScriptParser::DataType::BUILTIN && type.builtin_type == Variant::NIL) {
- parser->push_warning(p_variable->initializer, GDScriptWarning::VOID_ASSIGNMENT, static_cast<GDScriptParser::CallNode *>(p_variable->initializer)->function_name);
- }
-#endif
}
if (p_variable->datatype_specifier != nullptr) {
@@ -1569,14 +1848,14 @@ void GDScriptAnalyzer::resolve_constant(GDScriptParser::ConstantNode *p_constant
type = p_constant->initializer->get_datatype();
#ifdef DEBUG_ENABLED
- if (p_constant->initializer->type == GDScriptParser::Node::CALL && type.kind == GDScriptParser::DataType::BUILTIN && type.builtin_type == Variant::NIL) {
+ if (p_constant->initializer->type == GDScriptParser::Node::CALL && type.is_hard_type() && type.kind == GDScriptParser::DataType::BUILTIN && type.builtin_type == Variant::NIL) {
parser->push_warning(p_constant->initializer, GDScriptWarning::VOID_ASSIGNMENT, static_cast<GDScriptParser::CallNode *>(p_constant->initializer)->function_name);
}
#endif
}
if (p_constant->datatype_specifier != nullptr) {
- if (!is_type_compatible(explicit_type, type)) {
+ if (!is_type_compatible(explicit_type, type, true)) {
push_error(vformat(R"(Assigned value for constant "%s" has type %s which is not compatible with defined type %s.)", p_constant->identifier->name, type.to_string(), explicit_type.to_string()), p_constant->initializer);
#ifdef DEBUG_ENABLED
} else if (explicit_type.builtin_type == Variant::INT && type.builtin_type == Variant::FLOAT) {
@@ -1726,7 +2005,6 @@ void GDScriptAnalyzer::resolve_parameter(GDScriptParser::ParameterNode *p_parame
} else {
result.type_source = GDScriptParser::DataType::INFERRED;
}
- result.is_constant = false;
}
if (p_parameter->datatype_specifier != nullptr) {
@@ -1746,6 +2024,7 @@ void GDScriptAnalyzer::resolve_parameter(GDScriptParser::ParameterNode *p_parame
push_error(vformat(R"(Could not infer the type of the variable "%s" because the initial value is "null".)", p_parameter->identifier->name), p_parameter->default_value);
}
+ result.is_constant = false;
p_parameter->set_datatype(result);
}
@@ -1983,30 +2262,26 @@ void GDScriptAnalyzer::reduce_assignment(GDScriptParser::AssignmentNode *p_assig
}
p_assignment->set_datatype(op_type);
- if (!assignee_type.is_variant() && assigned_value_type.is_hard_type()) {
+ if (assignee_type.is_hard_type() && !assignee_type.is_variant() && op_type.is_hard_type()) {
if (compatible) {
compatible = is_type_compatible(assignee_type, op_type, true, p_assignment->assigned_value);
if (!compatible) {
- if (assignee_type.is_hard_type()) {
- // Try reverse test since it can be a masked subtype.
- if (!is_type_compatible(op_type, assignee_type, true, p_assignment->assigned_value)) {
- push_error(vformat(R"(Cannot assign a value of type "%s" to a target of type "%s".)", assigned_value_type.to_string(), assignee_type.to_string()), p_assignment->assigned_value);
- } else {
- // TODO: Add warning.
- mark_node_unsafe(p_assignment);
- p_assignment->use_conversion_assign = true;
- }
+ // Try reverse test since it can be a masked subtype.
+ if (!is_type_compatible(op_type, assignee_type, true)) {
+ push_error(vformat(R"(Cannot assign a value of type "%s" to a target of type "%s".)", assigned_value_type.to_string(), assignee_type.to_string()), p_assignment->assigned_value);
} else {
- // TODO: Warning in this case.
+ // TODO: Add warning.
mark_node_unsafe(p_assignment);
+ p_assignment->use_conversion_assign = true;
}
}
} else {
push_error(vformat(R"(Invalid operands "%s" and "%s" for assignment operator.)", assignee_type.to_string(), assigned_value_type.to_string()), p_assignment);
}
- }
-
- if (assignee_type.has_no_type() || assigned_value_type.is_variant()) {
+ } else if (assignee_type.is_hard_type() && !assignee_type.is_variant()) {
+ mark_node_unsafe(p_assignment);
+ p_assignment->use_conversion_assign = true;
+ } else {
mark_node_unsafe(p_assignment);
if (assignee_type.is_hard_type() && !assignee_type.is_variant()) {
p_assignment->use_conversion_assign = true;
@@ -2057,7 +2332,7 @@ void GDScriptAnalyzer::reduce_assignment(GDScriptParser::AssignmentNode *p_assig
}
#ifdef DEBUG_ENABLED
- if (p_assignment->assigned_value->type == GDScriptParser::Node::CALL && assigned_value_type.kind == GDScriptParser::DataType::BUILTIN && assigned_value_type.builtin_type == Variant::NIL) {
+ if (p_assignment->assigned_value->type == GDScriptParser::Node::CALL && assigned_value_type.is_hard_type() && assigned_value_type.kind == GDScriptParser::DataType::BUILTIN && assigned_value_type.builtin_type == Variant::NIL) {
parser->push_warning(p_assignment->assigned_value, GDScriptWarning::VOID_ASSIGNMENT, static_cast<GDScriptParser::CallNode *>(p_assignment->assigned_value)->function_name);
} else if (assignee_type.is_hard_type() && assignee_type.builtin_type == Variant::INT && assigned_value_type.builtin_type == Variant::FLOAT) {
parser->push_warning(p_assignment->assigned_value, GDScriptWarning::NARROWING_CONVERSION);
@@ -2152,7 +2427,7 @@ void GDScriptAnalyzer::reduce_binary_op(GDScriptParser::BinaryOpNode *p_binary_o
GDScriptParser::DataType test_type = right_type;
test_type.is_meta_type = false;
- if (!is_type_compatible(test_type, p_binary_op->left_operand->get_datatype(), false)) {
+ if (!is_type_compatible(test_type, left_type, false)) {
push_error(vformat(R"(Expression is of type "%s" so it can't be of type "%s".)"), p_binary_op->left_operand);
p_binary_op->reduced_value = false;
} else {
@@ -2186,11 +2461,11 @@ void GDScriptAnalyzer::reduce_binary_op(GDScriptParser::BinaryOpNode *p_binary_o
GDScriptParser::DataType test_type = right_type;
test_type.is_meta_type = false;
- if (!is_type_compatible(test_type, p_binary_op->left_operand->get_datatype(), false)) {
+ if (!is_type_compatible(test_type, left_type, false)) {
// Test reverse as well to consider for subtypes.
- if (!is_type_compatible(p_binary_op->left_operand->get_datatype(), test_type, false)) {
- if (p_binary_op->left_operand->get_datatype().is_hard_type()) {
- push_error(vformat(R"(Expression is of type "%s" so it can't be of type "%s".)", p_binary_op->left_operand->get_datatype().to_string(), test_type.to_string()), p_binary_op->left_operand);
+ if (!is_type_compatible(left_type, test_type, false)) {
+ if (left_type.is_hard_type()) {
+ push_error(vformat(R"(Expression is of type "%s" so it can't be of type "%s".)", left_type.to_string(), test_type.to_string()), p_binary_op->left_operand);
} else {
// TODO: Warning.
mark_node_unsafe(p_binary_op);
@@ -2564,8 +2839,14 @@ void GDScriptAnalyzer::reduce_call(GDScriptParser::CallNode *p_call, bool p_is_a
parser->push_warning(p_call, GDScriptWarning::RETURN_VALUE_DISCARDED, p_call->function_name);
}
- if (is_static && !base_type.is_meta_type && !(callee_type != GDScriptParser::Node::SUBSCRIPT && parser->current_function != nullptr && parser->current_function->is_static)) {
- parser->push_warning(p_call, GDScriptWarning::STATIC_CALLED_ON_INSTANCE, p_call->function_name, base_type.to_string());
+ if (is_static && !base_type.is_meta_type && !(is_self && parser->current_function != nullptr && parser->current_function->is_static)) {
+ String caller_type = String(base_type.native_type);
+
+ if (caller_type.is_empty()) {
+ caller_type = base_type.to_string();
+ }
+
+ parser->push_warning(p_call, GDScriptWarning::STATIC_CALLED_ON_INSTANCE, p_call->function_name, caller_type);
}
#endif // DEBUG_ENABLED
@@ -2662,7 +2943,7 @@ void GDScriptAnalyzer::reduce_cast(GDScriptParser::CastNode *p_cast) {
}
void GDScriptAnalyzer::reduce_dictionary(GDScriptParser::DictionaryNode *p_dictionary) {
- HashMap<Variant, GDScriptParser::ExpressionNode *, VariantHasher, VariantComparator> elements;
+ HashMap<Variant, GDScriptParser::ExpressionNode *, VariantHasher, StringLikeVariantComparator> elements;
for (int i = 0; i < p_dictionary->elements.size(); i++) {
const GDScriptParser::DictionaryNode::Pair &element = p_dictionary->elements[i];
@@ -2720,7 +3001,7 @@ GDScriptParser::DataType GDScriptAnalyzer::make_global_class_meta_type(const Str
return type;
}
- Error err = ref->raise_status(GDScriptParserRef::INTERFACE_SOLVED);
+ Error err = ref->raise_status(GDScriptParserRef::INHERITANCE_SOLVED);
if (err) {
push_error(vformat(R"(Could not resolve class "%s", because of a parser error.)", p_class_name), p_source);
type.type_source = GDScriptParser::DataType::UNDETECTED;
@@ -2728,21 +3009,13 @@ GDScriptParser::DataType GDScriptAnalyzer::make_global_class_meta_type(const Str
return type;
}
- type.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT;
- type.kind = GDScriptParser::DataType::CLASS;
- type.builtin_type = Variant::OBJECT;
- type.native_type = ScriptServer::get_global_class_native_base(p_class_name);
- type.class_type = ref->get_parser()->head;
- type.script_path = ref->get_parser()->script_path;
- type.is_constant = true;
- type.is_meta_type = true;
- return type;
+ return ref->get_parser()->head->get_datatype();
} else {
type.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT;
type.kind = GDScriptParser::DataType::SCRIPT;
type.builtin_type = Variant::OBJECT;
- type.native_type = ScriptServer::get_global_class_native_base(p_class_name);
type.script_type = ResourceLoader::load(path, "Script");
+ type.native_type = type.script_type->get_instance_base_type();
type.script_path = path;
type.is_constant = true;
type.is_meta_type = true;
@@ -2751,6 +3024,10 @@ GDScriptParser::DataType GDScriptAnalyzer::make_global_class_meta_type(const Str
}
void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNode *p_identifier, GDScriptParser::DataType *p_base) {
+ if (!p_identifier->get_datatype().has_no_type()) {
+ return;
+ }
+
GDScriptParser::DataType base;
if (p_base == nullptr) {
base = type_from_metatype(parser->current_class->get_datatype());
@@ -2843,16 +3120,16 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod
p_identifier->set_datatype(base_class->get_datatype());
return;
}
+
if (base_class->has_member(name)) {
- const GDScriptParser::ClassNode::Member &member = base_class->get_member(name);
+ resolve_class_member(base_class, name, p_identifier);
+
+ GDScriptParser::ClassNode::Member member = base_class->get_member(name);
p_identifier->set_datatype(member.get_datatype());
switch (member.type) {
case GDScriptParser::ClassNode::Member::CONSTANT:
- // For out-of-order resolution:
- reduce_expression(member.constant->initializer);
p_identifier->is_constant = true;
p_identifier->reduced_value = member.constant->initializer->reduced_value;
- p_identifier->set_datatype(member.constant->initializer->get_datatype());
p_identifier->source = GDScriptParser::IdentifierNode::MEMBER_CONSTANT;
p_identifier->constant_source = member.constant;
break;
@@ -2861,19 +3138,33 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod
p_identifier->reduced_value = member.enum_value.value;
p_identifier->source = GDScriptParser::IdentifierNode::MEMBER_CONSTANT;
break;
+ case GDScriptParser::ClassNode::Member::ENUM:
+ p_identifier->is_constant = true;
+ p_identifier->reduced_value = member.m_enum->dictionary;
+ p_identifier->source = GDScriptParser::IdentifierNode::MEMBER_CONSTANT;
+ break;
case GDScriptParser::ClassNode::Member::VARIABLE:
p_identifier->source = GDScriptParser::IdentifierNode::MEMBER_VARIABLE;
p_identifier->variable_source = member.variable;
member.variable->usages += 1;
break;
+ case GDScriptParser::ClassNode::Member::SIGNAL:
+ p_identifier->source = GDScriptParser::IdentifierNode::MEMBER_SIGNAL;
+ break;
case GDScriptParser::ClassNode::Member::FUNCTION:
- resolve_function_signature(member.function);
p_identifier->set_datatype(make_callable_type(member.function->info));
break;
case GDScriptParser::ClassNode::Member::CLASS:
- // For out-of-order resolution:
- resolve_class_interface(member.m_class);
- p_identifier->set_datatype(member.m_class->get_datatype());
+ if (p_base != nullptr && p_base->is_constant) {
+ p_identifier->is_constant = true;
+ p_identifier->source = GDScriptParser::IdentifierNode::MEMBER_CONSTANT;
+
+ Error err = OK;
+ GDScript *scr = GDScriptCache::get_full_script(base.script_path, err).ptr();
+ ERR_FAIL_COND_MSG(err != OK, "Error while getting subscript full script.");
+ scr = scr->find_class(p_identifier->get_datatype().class_type->fqcn);
+ p_identifier->reduced_value = scr;
+ }
break;
default:
break; // Type already set.
@@ -2882,47 +3173,45 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod
}
// Check outer constants.
// TODO: Allow outer static functions.
- GDScriptParser::ClassNode *outer = base_class->outer;
- while (outer != nullptr) {
- if (outer->has_member(name)) {
- const GDScriptParser::ClassNode::Member &member = outer->get_member(name);
- switch (member.type) {
- case GDScriptParser::ClassNode::Member::CONSTANT: {
- // TODO: Make sure loops won't cause problem. And make special error message for those.
- // For out-of-order resolution:
- reduce_expression(member.constant->initializer);
- p_identifier->set_datatype(member.get_datatype());
- p_identifier->is_constant = true;
- p_identifier->reduced_value = member.constant->initializer->reduced_value;
- return;
- } break;
- case GDScriptParser::ClassNode::Member::ENUM_VALUE: {
- p_identifier->set_datatype(member.get_datatype());
- p_identifier->is_constant = true;
- p_identifier->reduced_value = member.enum_value.value;
- return;
- } break;
- case GDScriptParser::ClassNode::Member::ENUM: {
- p_identifier->set_datatype(member.get_datatype());
- p_identifier->is_constant = false;
- return;
- } break;
- case GDScriptParser::ClassNode::Member::CLASS: {
- resolve_class_interface(member.m_class);
- p_identifier->set_datatype(member.m_class->get_datatype());
- return;
- } break;
- default:
- break;
+ if (base_class->outer != nullptr) {
+ List<GDScriptParser::ClassNode *> script_classes;
+ get_class_node_current_scope_classes(base_class->outer, &script_classes);
+ for (GDScriptParser::ClassNode *script_class : script_classes) {
+ if (script_class->has_member(name)) {
+ resolve_class_member(script_class, name, p_identifier);
+
+ GDScriptParser::ClassNode::Member member = script_class->get_member(name);
+ switch (member.type) {
+ case GDScriptParser::ClassNode::Member::CONSTANT:
+ // TODO: Make sure loops won't cause problem. And make special error message for those.
+ p_identifier->set_datatype(member.get_datatype());
+ p_identifier->is_constant = true;
+ p_identifier->reduced_value = member.constant->initializer->reduced_value;
+ return;
+ case GDScriptParser::ClassNode::Member::ENUM_VALUE:
+ p_identifier->set_datatype(member.get_datatype());
+ p_identifier->is_constant = true;
+ p_identifier->reduced_value = member.enum_value.value;
+ return;
+ case GDScriptParser::ClassNode::Member::ENUM:
+ p_identifier->set_datatype(member.get_datatype());
+ p_identifier->is_constant = true;
+ p_identifier->reduced_value = member.m_enum->dictionary;
+ return;
+ case GDScriptParser::ClassNode::Member::CLASS:
+ p_identifier->set_datatype(member.get_datatype());
+ return;
+ default:
+ break;
+ }
}
}
- outer = outer->outer;
}
base_class = base_class->base_type.class_type;
}
- // Check native members.
+ // Check native members. No need for native class recursion because Node exposes all Object's properties.
const StringName &native = base.native_type;
if (class_exists(native)) {
@@ -3010,6 +3299,7 @@ void GDScriptAnalyzer::reduce_identifier(GDScriptParser::IdentifierNode *p_ident
p_identifier->reduced_value = p_identifier->constant_source->initializer->reduced_value;
found_source = true;
break;
+ case GDScriptParser::IdentifierNode::MEMBER_SIGNAL:
case GDScriptParser::IdentifierNode::INHERITED_VARIABLE:
mark_lambda_use_self();
break;
@@ -3113,14 +3403,31 @@ void GDScriptAnalyzer::reduce_identifier(GDScriptParser::IdentifierNode *p_ident
GDScriptParser::DataType result;
result.kind = GDScriptParser::DataType::NATIVE;
result.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT;
- if (autoload.path.to_lower().ends_with(GDScriptLanguage::get_singleton()->get_extension())) {
+ if (ResourceLoader::get_resource_type(autoload.path) == "GDScript") {
Ref<GDScriptParserRef> singl_parser = get_parser_for(autoload.path);
if (singl_parser.is_valid()) {
- Error err = singl_parser->raise_status(GDScriptParserRef::INTERFACE_SOLVED);
+ Error err = singl_parser->raise_status(GDScriptParserRef::INHERITANCE_SOLVED);
if (err == OK) {
result = type_from_metatype(singl_parser->get_parser()->head->get_datatype());
}
}
+ } else if (ResourceLoader::get_resource_type(autoload.path) == "PackedScene") {
+ if (GDScriptLanguage::get_singleton()->has_any_global_constant(name)) {
+ Variant constant = GDScriptLanguage::get_singleton()->get_any_global_constant(name);
+ Node *node = Object::cast_to<Node>(constant);
+ if (node != nullptr) {
+ Ref<GDScript> scr = node->get_script();
+ if (scr.is_valid()) {
+ Ref<GDScriptParserRef> singl_parser = get_parser_for(scr->get_script_path());
+ if (singl_parser.is_valid()) {
+ Error err = singl_parser->raise_status(GDScriptParserRef::INHERITANCE_SOLVED);
+ if (err == OK) {
+ result = type_from_metatype(singl_parser->get_parser()->head->get_datatype());
+ }
+ }
+ }
+ }
+ }
}
result.is_constant = true;
p_identifier->set_datatype(result);
@@ -3128,17 +3435,8 @@ void GDScriptAnalyzer::reduce_identifier(GDScriptParser::IdentifierNode *p_ident
}
}
- if (GDScriptLanguage::get_singleton()->get_global_map().has(name)) {
- int idx = GDScriptLanguage::get_singleton()->get_global_map()[name];
- Variant constant = GDScriptLanguage::get_singleton()->get_global_array()[idx];
- p_identifier->set_datatype(type_from_variant(constant, p_identifier));
- p_identifier->is_constant = true;
- p_identifier->reduced_value = constant;
- return;
- }
-
- if (GDScriptLanguage::get_singleton()->get_named_globals_map().has(name)) {
- Variant constant = GDScriptLanguage::get_singleton()->get_named_globals_map()[name];
+ if (GDScriptLanguage::get_singleton()->has_any_global_constant(name)) {
+ Variant constant = GDScriptLanguage::get_singleton()->get_any_global_constant(name);
p_identifier->set_datatype(type_from_variant(constant, p_identifier));
p_identifier->is_constant = true;
p_identifier->reduced_value = constant;
@@ -3246,9 +3544,28 @@ void GDScriptAnalyzer::reduce_preload(GDScriptParser::PreloadNode *p_preload) {
}
} else {
// TODO: Don't load if validating: use completion cache.
- p_preload->resource = ResourceLoader::load(p_preload->resolved_path);
- if (p_preload->resource.is_null()) {
- push_error(vformat(R"(Could not preload resource file "%s".)", p_preload->resolved_path), p_preload->path);
+
+ // Must load GDScript and PackedScenes separately to permit cyclic references
+ // as ResourceLoader::load() detect and reject those.
+ if (ResourceLoader::get_resource_type(p_preload->resolved_path) == "GDScript") {
+ Error err = OK;
+ Ref<GDScript> res = GDScriptCache::get_shallow_script(p_preload->resolved_path, err, parser->script_path);
+ p_preload->resource = res;
+ if (err != OK) {
+ push_error(vformat(R"(Could not preload resource script "%s".)", p_preload->resolved_path), p_preload->path);
+ }
+ } else if (ResourceLoader::get_resource_type(p_preload->resolved_path) == "PackedScene") {
+ Error err = OK;
+ Ref<PackedScene> res = GDScriptCache::get_packed_scene(p_preload->resolved_path, err, parser->script_path);
+ p_preload->resource = res;
+ if (err != OK) {
+ push_error(vformat(R"(Could not preload resource scene "%s".)", p_preload->resolved_path), p_preload->path);
+ }
+ } else {
+ p_preload->resource = ResourceLoader::load(p_preload->resolved_path);
+ if (p_preload->resource.is_null()) {
+ push_error(vformat(R"(Could not preload resource file "%s".)", p_preload->resolved_path), p_preload->path);
+ }
}
}
}
@@ -3286,43 +3603,44 @@ void GDScriptAnalyzer::reduce_subscript(GDScriptParser::SubscriptNode *p_subscri
if (p_subscript->attribute == nullptr) {
return;
}
- if (p_subscript->base->is_constant) {
+
+ GDScriptParser::DataType base_type = p_subscript->base->get_datatype();
+ bool valid = false;
+ // If the base is a metatype, use the analyzer instead.
+ if (p_subscript->base->is_constant && !base_type.is_meta_type) {
// Just try to get it.
- bool valid = false;
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 {
+ if (valid) {
p_subscript->is_constant = true;
p_subscript->reduced_value = value;
result_type = type_from_variant(value, p_subscript);
}
+ } else if (base_type.is_variant() || !base_type.is_hard_type()) {
+ valid = true;
+ result_type.kind = GDScriptParser::DataType::VARIANT;
+ mark_node_unsafe(p_subscript);
} else {
- GDScriptParser::DataType base_type = p_subscript->base->get_datatype();
-
- if (base_type.is_variant() || !base_type.is_hard_type()) {
- result_type.kind = GDScriptParser::DataType::VARIANT;
- mark_node_unsafe(p_subscript);
- } else {
- reduce_identifier_from_base(p_subscript->attribute, &base_type);
- GDScriptParser::DataType attr_type = p_subscript->attribute->get_datatype();
- if (attr_type.is_set()) {
- result_type = attr_type;
- p_subscript->is_constant = p_subscript->attribute->is_constant;
- p_subscript->reduced_value = p_subscript->attribute->reduced_value;
- } else {
- if (base_type.kind == GDScriptParser::DataType::BUILTIN) {
- push_error(vformat(R"(Cannot find member "%s" in base "%s".)", p_subscript->attribute->name, base_type.to_string()), p_subscript->attribute);
+ reduce_identifier_from_base(p_subscript->attribute, &base_type);
+ GDScriptParser::DataType attr_type = p_subscript->attribute->get_datatype();
+ if (attr_type.is_set()) {
+ valid = true;
+ result_type = attr_type;
+ p_subscript->is_constant = p_subscript->attribute->is_constant;
+ p_subscript->reduced_value = p_subscript->attribute->reduced_value;
+ } else if (!base_type.is_meta_type || !base_type.is_constant) {
+ valid = base_type.kind != GDScriptParser::DataType::BUILTIN;
#ifdef DEBUG_ENABLED
- } else {
- parser->push_warning(p_subscript, GDScriptWarning::UNSAFE_PROPERTY_ACCESS, p_subscript->attribute->name, base_type.to_string());
-#endif
- }
- result_type.kind = GDScriptParser::DataType::VARIANT;
+ if (valid) {
+ parser->push_warning(p_subscript, GDScriptWarning::UNSAFE_PROPERTY_ACCESS, p_subscript->attribute->name, base_type.to_string());
}
+#endif
+ result_type.kind = GDScriptParser::DataType::VARIANT;
}
}
+ if (!valid) {
+ push_error(vformat(R"(Cannot find member "%s" in base "%s".)", p_subscript->attribute->name, type_from_metatype(base_type).to_string()), p_subscript->attribute);
+ result_type.kind = GDScriptParser::DataType::VARIANT;
+ }
} else {
if (p_subscript->index == nullptr) {
return;
@@ -3375,7 +3693,7 @@ void GDScriptAnalyzer::reduce_subscript(GDScriptParser::SubscriptNode *p_subscri
case Variant::QUATERNION:
case Variant::AABB:
case Variant::OBJECT:
- error = index_type.builtin_type != Variant::STRING;
+ error = index_type.builtin_type != Variant::STRING && index_type.builtin_type != Variant::STRING_NAME;
break;
// Expect String or number.
case Variant::BASIS:
@@ -3389,11 +3707,11 @@ void GDScriptAnalyzer::reduce_subscript(GDScriptParser::SubscriptNode *p_subscri
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;
+ index_type.builtin_type != Variant::STRING && index_type.builtin_type != Variant::STRING_NAME;
break;
// Expect String or int.
case Variant::COLOR:
- error = index_type.builtin_type != Variant::INT && index_type.builtin_type != Variant::STRING;
+ error = index_type.builtin_type != Variant::INT && index_type.builtin_type != Variant::STRING && index_type.builtin_type != Variant::STRING_NAME;
break;
// Don't support indexing, but we will check it later.
case Variant::RID:
@@ -3577,19 +3895,23 @@ void GDScriptAnalyzer::reduce_unary_op(GDScriptParser::UnaryOpNode *p_unary_op)
return;
}
+ GDScriptParser::DataType operand_type = p_unary_op->operand->get_datatype();
+
if (p_unary_op->operand->is_constant) {
p_unary_op->is_constant = true;
p_unary_op->reduced_value = Variant::evaluate(p_unary_op->variant_op, p_unary_op->operand->reduced_value, Variant());
result = type_from_variant(p_unary_op->reduced_value, p_unary_op);
- } else if (p_unary_op->operand->get_datatype().is_variant()) {
+ }
+
+ if (operand_type.is_variant()) {
result.kind = GDScriptParser::DataType::VARIANT;
mark_node_unsafe(p_unary_op);
} else {
bool valid = false;
- result = get_operation_type(p_unary_op->variant_op, p_unary_op->operand->get_datatype(), valid, p_unary_op);
+ result = get_operation_type(p_unary_op->variant_op, operand_type, valid, p_unary_op);
if (!valid) {
- push_error(vformat(R"(Invalid operand of type "%s" for unary operator "%s".)", p_unary_op->operand->get_datatype().to_string(), Variant::get_operator_name(p_unary_op->variant_op)), p_unary_op->operand);
+ push_error(vformat(R"(Invalid operand of type "%s" for unary operator "%s".)", operand_type.to_string(), Variant::get_operator_name(p_unary_op->variant_op)), p_unary_op);
}
}
@@ -3658,6 +3980,9 @@ GDScriptParser::DataType GDScriptAnalyzer::type_from_variant(const Variant &p_va
result.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT; // Constant has explicit type.
if (p_value.get_type() == Variant::OBJECT) {
+ // Object is treated as a native type, not a builtin type.
+ result.kind = GDScriptParser::DataType::NATIVE;
+
Object *obj = p_value;
if (!obj) {
return GDScriptParser::DataType();
@@ -3672,50 +3997,42 @@ GDScriptParser::DataType GDScriptAnalyzer::type_from_variant(const Variant &p_va
scr = obj->get_script();
}
if (scr.is_valid()) {
- if (scr->is_valid()) {
- result.script_type = scr;
- result.script_path = scr->get_path();
- Ref<GDScript> gds = scr;
- if (gds.is_valid()) {
- result.kind = GDScriptParser::DataType::CLASS;
- // This might be an inner class, so we want to get the parser for the root.
- // But still get the inner class from that tree.
- GDScript *current = gds.ptr();
- List<StringName> class_chain;
- while (current->_owner) {
- // Push to front so it's in reverse.
- class_chain.push_front(current->name);
- current = current->_owner;
- }
-
- Ref<GDScriptParserRef> ref = get_parser_for(current->get_path());
- if (ref.is_null()) {
- push_error("Could not find script in path.", p_source);
- GDScriptParser::DataType error_type;
- error_type.kind = GDScriptParser::DataType::VARIANT;
- return error_type;
- }
- ref->raise_status(GDScriptParserRef::INTERFACE_SOLVED);
-
- GDScriptParser::ClassNode *found = ref->get_parser()->head;
-
- // It should be okay to assume this exists, since we have a complete script already.
- for (const StringName &E : class_chain) {
- found = found->get_member(E).m_class;
+ result.script_path = scr->get_path();
+ Ref<GDScript> gds = scr;
+ if (gds.is_valid()) {
+ result.kind = GDScriptParser::DataType::CLASS;
+ // This might be an inner class, so we want to get the parser for the root.
+ // But still get the inner class from that tree.
+ String script_path = gds->get_script_path();
+ Ref<GDScriptParserRef> ref = get_parser_for(script_path);
+ if (ref.is_null()) {
+ push_error(vformat(R"(Could not find script "%s".)", script_path), p_source);
+ GDScriptParser::DataType error_type;
+ error_type.kind = GDScriptParser::DataType::VARIANT;
+ return error_type;
+ }
+ Error err = ref->raise_status(GDScriptParserRef::INHERITANCE_SOLVED);
+ GDScriptParser::ClassNode *found = nullptr;
+ if (err == OK) {
+ found = ref->get_parser()->find_class(gds->fully_qualified_name);
+ if (found != nullptr) {
+ err = resolve_class_inheritance(found, p_source);
}
-
- result.class_type = found;
- result.script_path = ref->get_parser()->script_path;
- } else {
- result.kind = GDScriptParser::DataType::SCRIPT;
}
- result.native_type = scr->get_instance_base_type();
+ if (err || found == nullptr) {
+ push_error(vformat(R"(Could not resolve script "%s".)", script_path), p_source);
+ GDScriptParser::DataType error_type;
+ error_type.kind = GDScriptParser::DataType::VARIANT;
+ return error_type;
+ }
+
+ result.class_type = found;
+ result.script_path = ref->get_parser()->script_path;
} else {
- push_error(vformat(R"(Constant value uses script from "%s" which is loaded but not compiled.)", scr->get_path()), p_source);
- result.kind = GDScriptParser::DataType::VARIANT;
- result.type_source = GDScriptParser::DataType::UNDETECTED;
- result.is_meta_type = false;
+ result.kind = GDScriptParser::DataType::SCRIPT;
+ result.native_type = scr->get_instance_base_type();
}
+ result.script_type = scr;
} else {
result.kind = GDScriptParser::DataType::NATIVE;
if (result.native_type == GDScriptNativeClass::get_class_static()) {
@@ -3839,8 +4156,12 @@ bool GDScriptAnalyzer::get_function_signature(GDScriptParser::Node *p_source, bo
push_error(vformat(R"(Member "%s" is not a function.)", function_name), p_source);
return false;
}
+
+ resolve_class_member(base_class, function_name, p_source);
found_function = base_class->get_member(function_name).function;
}
+
+ resolve_class_inheritance(base_class, p_source);
base_class = base_class->base_type.class_type;
}
@@ -3852,7 +4173,7 @@ bool GDScriptAnalyzer::get_function_signature(GDScriptParser::Node *p_source, bo
r_default_arg_count++;
}
}
- r_return_type = found_function->get_datatype();
+ r_return_type = p_is_constructor ? p_base_type : found_function->get_datatype();
r_return_type.is_meta_type = false;
r_return_type.is_coroutine = found_function->is_coroutine;
@@ -4009,12 +4330,10 @@ bool GDScriptAnalyzer::is_shadowing(GDScriptParser::IdentifierNode *p_local, con
base_class = base_class->base_type.class_type;
}
- StringName base_native = base.native_type;
-
- ERR_FAIL_COND_V_MSG(!class_exists(base_native), false, "Non-existent native base class.");
-
- StringName parent = base_native;
+ StringName parent = base.native_type;
while (parent != StringName()) {
+ ERR_FAIL_COND_V_MSG(!class_exists(parent), false, "Non-existent native base class.");
+
if (ClassDB::has_method(parent, name, true)) {
parser->push_warning(p_local, GDScriptWarning::SHADOWED_VARIABLE_BASE_CLASS, p_context, p_local->name, "method", parent);
return true;
@@ -4129,7 +4448,7 @@ bool GDScriptAnalyzer::is_type_compatible(const GDScriptParser::DataType &p_targ
// Variant array can't be appended to typed array.
valid = false;
} else {
- valid = is_type_compatible(p_target.get_container_element_type(), p_source.get_container_element_type(), false);
+ valid = is_type_compatible(p_target.get_container_element_type(), p_source.get_container_element_type(), p_allow_implicit_conversion);
}
}
}
@@ -4204,6 +4523,7 @@ bool GDScriptAnalyzer::is_type_compatible(const GDScriptParser::DataType &p_targ
case GDScriptParser::DataType::VARIANT:
case GDScriptParser::DataType::BUILTIN:
case GDScriptParser::DataType::ENUM:
+ case GDScriptParser::DataType::RESOLVING:
case GDScriptParser::DataType::UNRESOLVED:
break; // Already solved before.
}
@@ -4240,6 +4560,7 @@ bool GDScriptAnalyzer::is_type_compatible(const GDScriptParser::DataType &p_targ
case GDScriptParser::DataType::VARIANT:
case GDScriptParser::DataType::BUILTIN:
case GDScriptParser::DataType::ENUM:
+ case GDScriptParser::DataType::RESOLVING:
case GDScriptParser::DataType::UNRESOLVED:
break; // Already solved before.
}
@@ -4254,6 +4575,10 @@ void GDScriptAnalyzer::push_error(const String &p_message, const GDScriptParser:
void GDScriptAnalyzer::mark_node_unsafe(const GDScriptParser::Node *p_node) {
#ifdef DEBUG_ENABLED
+ if (p_node == nullptr) {
+ return;
+ }
+
for (int i = p_node->start_line; i <= p_node->end_line; i++) {
parser->unsafe_lines.insert(i);
}
@@ -4286,39 +4611,46 @@ Ref<GDScriptParserRef> GDScriptAnalyzer::get_parser_for(const String &p_path) {
}
Error GDScriptAnalyzer::resolve_inheritance() {
- return resolve_inheritance(parser->head);
+ return resolve_class_inheritance(parser->head, true);
}
Error GDScriptAnalyzer::resolve_interface() {
- resolve_class_interface(parser->head);
+ resolve_class_interface(parser->head, true);
return parser->errors.is_empty() ? OK : ERR_PARSE_ERROR;
}
Error GDScriptAnalyzer::resolve_body() {
- resolve_class_body(parser->head);
+ resolve_class_body(parser->head, true);
return parser->errors.is_empty() ? OK : ERR_PARSE_ERROR;
}
-Error GDScriptAnalyzer::resolve_program() {
- resolve_class_interface(parser->head);
- resolve_class_body(parser->head);
-
+Error GDScriptAnalyzer::resolve_dependencies() {
for (KeyValue<String, Ref<GDScriptParserRef>> &K : depended_parsers) {
if (K.value.is_null()) {
return ERR_PARSE_ERROR;
}
- K.value->raise_status(GDScriptParserRef::FULLY_SOLVED);
+ K.value->raise_status(GDScriptParserRef::INHERITANCE_SOLVED);
}
+
return parser->errors.is_empty() ? OK : ERR_PARSE_ERROR;
}
Error GDScriptAnalyzer::analyze() {
parser->errors.clear();
- Error err = resolve_inheritance(parser->head);
+ Error err = OK;
+
+ err = resolve_inheritance();
if (err) {
return err;
}
- return resolve_program();
+
+ resolve_interface();
+ resolve_body();
+ if (!parser->errors.is_empty()) {
+ return ERR_PARSE_ERROR;
+ }
+
+ return resolve_dependencies();
}
GDScriptAnalyzer::GDScriptAnalyzer(GDScriptParser *p_parser) {
diff --git a/modules/gdscript/gdscript_analyzer.h b/modules/gdscript/gdscript_analyzer.h
index 217a856ce0..a4d9efb094 100644
--- a/modules/gdscript/gdscript_analyzer.h
+++ b/modules/gdscript/gdscript_analyzer.h
@@ -45,23 +45,27 @@ class GDScriptAnalyzer {
List<GDScriptParser::LambdaNode *> lambda_stack;
// Tests for detecting invalid overloading of script members
- static _FORCE_INLINE_ bool has_member_name_conflict_in_script_class(const StringName &p_name, const GDScriptParser::ClassNode *p_current_class_node);
+ static _FORCE_INLINE_ bool has_member_name_conflict_in_script_class(const StringName &p_name, const GDScriptParser::ClassNode *p_current_class_node, const GDScriptParser::Node *p_member);
static _FORCE_INLINE_ bool has_member_name_conflict_in_native_type(const StringName &p_name, const StringName &p_native_type_string);
Error check_native_member_name_conflict(const StringName &p_member_name, const GDScriptParser::Node *p_member_node, const StringName &p_native_type_string);
Error check_class_member_name_conflict(const GDScriptParser::ClassNode *p_class_node, const StringName &p_member_name, const GDScriptParser::Node *p_member_node);
- Error resolve_inheritance(GDScriptParser::ClassNode *p_class, bool p_recursive = true);
+ void get_class_node_current_scope_classes(GDScriptParser::ClassNode *p_node, List<GDScriptParser::ClassNode *> *p_list);
+
+ Error resolve_class_inheritance(GDScriptParser::ClassNode *p_class, const GDScriptParser::Node *p_source = nullptr);
+ Error resolve_class_inheritance(GDScriptParser::ClassNode *p_class, bool p_recursive);
GDScriptParser::DataType resolve_datatype(GDScriptParser::TypeNode *p_type);
void decide_suite_type(GDScriptParser::Node *p_suite, GDScriptParser::Node *p_statement);
- // This traverses the tree to resolve all TypeNodes.
- Error resolve_program();
-
void resolve_annotation(GDScriptParser::AnnotationNode *p_annotation);
- void resolve_class_interface(GDScriptParser::ClassNode *p_class);
- void resolve_class_body(GDScriptParser::ClassNode *p_class);
- void resolve_function_signature(GDScriptParser::FunctionNode *p_function);
+ void resolve_class_member(GDScriptParser::ClassNode *p_class, StringName p_name, const GDScriptParser::Node *p_source = nullptr);
+ void resolve_class_member(GDScriptParser::ClassNode *p_class, int p_index, const GDScriptParser::Node *p_source = nullptr);
+ void resolve_class_interface(GDScriptParser::ClassNode *p_class, const GDScriptParser::Node *p_source = nullptr);
+ void resolve_class_interface(GDScriptParser::ClassNode *p_class, bool p_recursive);
+ void resolve_class_body(GDScriptParser::ClassNode *p_class, const GDScriptParser::Node *p_source = nullptr);
+ void resolve_class_body(GDScriptParser::ClassNode *p_class, bool p_recursive);
+ void resolve_function_signature(GDScriptParser::FunctionNode *p_function, const GDScriptParser::Node *p_source = nullptr);
void resolve_function_body(GDScriptParser::FunctionNode *p_function);
void resolve_node(GDScriptParser::Node *p_node, bool p_is_root = true);
void resolve_suite(GDScriptParser::SuiteNode *p_suite);
@@ -113,7 +117,7 @@ class GDScriptAnalyzer {
GDScriptParser::DataType get_operation_type(Variant::Operator p_operation, const GDScriptParser::DataType &p_a, bool &r_valid, const GDScriptParser::Node *p_source);
void update_array_literal_element_type(const GDScriptParser::DataType &p_base_type, GDScriptParser::ArrayNode *p_array_literal);
bool is_type_compatible(const GDScriptParser::DataType &p_target, const GDScriptParser::DataType &p_source, bool p_allow_implicit_conversion = false, const GDScriptParser::Node *p_source_node = nullptr);
- void push_error(const String &p_message, const GDScriptParser::Node *p_origin);
+ void push_error(const String &p_message, const GDScriptParser::Node *p_origin = nullptr);
void mark_node_unsafe(const GDScriptParser::Node *p_node);
void mark_lambda_use_self();
bool class_exists(const StringName &p_class) const;
@@ -126,6 +130,7 @@ public:
Error resolve_inheritance();
Error resolve_interface();
Error resolve_body();
+ Error resolve_dependencies();
Error analyze();
GDScriptAnalyzer(GDScriptParser *p_parser);
diff --git a/modules/gdscript/gdscript_byte_codegen.cpp b/modules/gdscript/gdscript_byte_codegen.cpp
index fa158591fd..1bc83fbbb5 100644
--- a/modules/gdscript/gdscript_byte_codegen.cpp
+++ b/modules/gdscript/gdscript_byte_codegen.cpp
@@ -164,7 +164,7 @@ void GDScriptByteCodeGenerator::write_start(GDScript *p_script, const StringName
function->name = p_function_name;
function->_script = p_script;
- function->source = p_script->get_path();
+ function->source = p_script->get_script_path();
#ifdef DEBUG_ENABLED
function->func_cname = (String(function->source) + " - " + String(p_function_name)).utf8();
diff --git a/modules/gdscript/gdscript_cache.cpp b/modules/gdscript/gdscript_cache.cpp
index 271296c2f9..6faf2dde73 100644
--- a/modules/gdscript/gdscript_cache.cpp
+++ b/modules/gdscript/gdscript_cache.cpp
@@ -34,7 +34,9 @@
#include "core/templates/vector.h"
#include "gdscript.h"
#include "gdscript_analyzer.h"
+#include "gdscript_compiler.h"
#include "gdscript_parser.h"
+#include "scene/resources/packed_scene.h"
bool GDScriptParserRef::is_valid() const {
return parser != nullptr;
@@ -48,6 +50,13 @@ GDScriptParser *GDScriptParserRef::get_parser() const {
return parser;
}
+GDScriptAnalyzer *GDScriptParserRef::get_analyzer() {
+ if (analyzer == nullptr) {
+ analyzer = memnew(GDScriptAnalyzer(parser));
+ }
+ return analyzer;
+}
+
Error GDScriptParserRef::raise_status(Status p_new_status) {
ERR_FAIL_COND_V(parser == nullptr, ERR_INVALID_DATA);
@@ -62,23 +71,22 @@ Error GDScriptParserRef::raise_status(Status p_new_status) {
result = parser->parse(GDScriptCache::get_source_code(path), path, false);
break;
case PARSED: {
- analyzer = memnew(GDScriptAnalyzer(parser));
status = INHERITANCE_SOLVED;
- Error inheritance_result = analyzer->resolve_inheritance();
+ Error inheritance_result = get_analyzer()->resolve_inheritance();
if (result == OK) {
result = inheritance_result;
}
} break;
case INHERITANCE_SOLVED: {
status = INTERFACE_SOLVED;
- Error interface_result = analyzer->resolve_interface();
+ Error interface_result = get_analyzer()->resolve_interface();
if (result == OK) {
result = interface_result;
}
} break;
case INTERFACE_SOLVED: {
status = FULLY_SOLVED;
- Error body_result = analyzer->resolve_body();
+ Error body_result = get_analyzer()->resolve_body();
if (result == OK) {
result = body_result;
}
@@ -95,27 +103,96 @@ Error GDScriptParserRef::raise_status(Status p_new_status) {
return result;
}
-GDScriptParserRef::~GDScriptParserRef() {
+void GDScriptParserRef::clear() {
+ if (cleared) {
+ return;
+ }
+ cleared = true;
+
if (parser != nullptr) {
memdelete(parser);
}
+
if (analyzer != nullptr) {
memdelete(analyzer);
}
- MutexLock lock(GDScriptCache::singleton->lock);
+}
+
+GDScriptParserRef::~GDScriptParserRef() {
+ clear();
+
+ MutexLock lock(GDScriptCache::singleton->mutex);
GDScriptCache::singleton->parser_map.erase(path);
}
GDScriptCache *GDScriptCache::singleton = nullptr;
+void GDScriptCache::move_script(const String &p_from, const String &p_to) {
+ if (singleton == nullptr || p_from == p_to) {
+ return;
+ }
+
+ MutexLock lock(singleton->mutex);
+
+ if (singleton->cleared) {
+ return;
+ }
+
+ for (KeyValue<String, HashSet<String>> &E : singleton->packed_scene_dependencies) {
+ if (E.value.has(p_from)) {
+ E.value.insert(p_to);
+ E.value.erase(p_from);
+ }
+ }
+
+ if (singleton->parser_map.has(p_from) && !p_from.is_empty()) {
+ singleton->parser_map[p_to] = singleton->parser_map[p_from];
+ }
+ singleton->parser_map.erase(p_from);
+
+ if (singleton->shallow_gdscript_cache.has(p_from) && !p_from.is_empty()) {
+ singleton->shallow_gdscript_cache[p_to] = singleton->shallow_gdscript_cache[p_from];
+ }
+ singleton->shallow_gdscript_cache.erase(p_from);
+
+ if (singleton->full_gdscript_cache.has(p_from) && !p_from.is_empty()) {
+ singleton->full_gdscript_cache[p_to] = singleton->full_gdscript_cache[p_from];
+ }
+ singleton->full_gdscript_cache.erase(p_from);
+}
+
void GDScriptCache::remove_script(const String &p_path) {
- MutexLock lock(singleton->lock);
+ if (singleton == nullptr) {
+ return;
+ }
+
+ MutexLock lock(singleton->mutex);
+
+ if (singleton->cleared) {
+ return;
+ }
+
+ for (KeyValue<String, HashSet<String>> &E : singleton->packed_scene_dependencies) {
+ if (!E.value.has(p_path)) {
+ continue;
+ }
+ E.value.erase(p_path);
+ }
+
+ GDScriptCache::clear_unreferenced_packed_scenes();
+
+ if (singleton->parser_map.has(p_path)) {
+ singleton->parser_map[p_path]->clear();
+ singleton->parser_map.erase(p_path);
+ }
+
+ singleton->dependencies.erase(p_path);
singleton->shallow_gdscript_cache.erase(p_path);
singleton->full_gdscript_cache.erase(p_path);
}
Ref<GDScriptParserRef> GDScriptCache::get_parser(const String &p_path, GDScriptParserRef::Status p_status, Error &r_error, const String &p_owner) {
- MutexLock lock(singleton->lock);
+ MutexLock lock(singleton->mutex);
Ref<GDScriptParserRef> ref;
if (!p_owner.is_empty()) {
singleton->dependencies[p_owner].insert(p_path);
@@ -161,8 +238,8 @@ String GDScriptCache::get_source_code(const String &p_path) {
return source;
}
-Ref<GDScript> GDScriptCache::get_shallow_script(const String &p_path, const String &p_owner) {
- MutexLock lock(singleton->lock);
+Ref<GDScript> GDScriptCache::get_shallow_script(const String &p_path, Error &r_error, const String &p_owner) {
+ MutexLock lock(singleton->mutex);
if (!p_owner.is_empty()) {
singleton->dependencies[p_owner].insert(p_path);
}
@@ -176,15 +253,19 @@ Ref<GDScript> GDScriptCache::get_shallow_script(const String &p_path, const Stri
Ref<GDScript> script;
script.instantiate();
script->set_path(p_path, true);
- script->set_script_path(p_path);
script->load_source_code(p_path);
- singleton->shallow_gdscript_cache[p_path] = script.ptr();
+ Ref<GDScriptParserRef> parser_ref = get_parser(p_path, GDScriptParserRef::PARSED, r_error);
+ if (r_error == OK) {
+ GDScriptCompiler::make_scripts(script.ptr(), parser_ref->get_parser()->get_tree(), true);
+ }
+
+ singleton->shallow_gdscript_cache[p_path] = script;
return script;
}
Ref<GDScript> GDScriptCache::get_full_script(const String &p_path, Error &r_error, const String &p_owner, bool p_update_from_disk) {
- MutexLock lock(singleton->lock);
+ MutexLock lock(singleton->mutex);
if (!p_owner.is_empty()) {
singleton->dependencies[p_owner].insert(p_path);
@@ -193,38 +274,60 @@ Ref<GDScript> GDScriptCache::get_full_script(const String &p_path, Error &r_erro
Ref<GDScript> script;
r_error = OK;
if (singleton->full_gdscript_cache.has(p_path)) {
- script = Ref<GDScript>(singleton->full_gdscript_cache[p_path]);
+ script = singleton->full_gdscript_cache[p_path];
if (!p_update_from_disk) {
return script;
}
}
if (script.is_null()) {
- script = get_shallow_script(p_path);
- ERR_FAIL_COND_V(script.is_null(), Ref<GDScript>());
+ script = get_shallow_script(p_path, r_error);
+ if (r_error) {
+ return script;
+ }
}
- r_error = script->load_source_code(p_path);
+ if (p_update_from_disk) {
+ r_error = script->load_source_code(p_path);
+ }
if (r_error) {
return script;
}
- r_error = script->reload();
+ singleton->full_gdscript_cache[p_path] = script;
+ singleton->shallow_gdscript_cache.erase(p_path);
+
+ r_error = script->reload(true);
if (r_error) {
+ singleton->shallow_gdscript_cache[p_path] = script;
+ singleton->full_gdscript_cache.erase(p_path);
return script;
}
- singleton->full_gdscript_cache[p_path] = script.ptr();
- singleton->shallow_gdscript_cache.erase(p_path);
-
return script;
}
+Ref<GDScript> GDScriptCache::get_cached_script(const String &p_path) {
+ MutexLock lock(singleton->mutex);
+
+ if (singleton->full_gdscript_cache.has(p_path)) {
+ return singleton->full_gdscript_cache[p_path];
+ }
+
+ if (singleton->shallow_gdscript_cache.has(p_path)) {
+ return singleton->shallow_gdscript_cache[p_path];
+ }
+
+ return Ref<GDScript>();
+}
+
Error GDScriptCache::finish_compiling(const String &p_owner) {
+ MutexLock lock(singleton->mutex);
+
// Mark this as compiled.
- Ref<GDScript> script = get_shallow_script(p_owner);
- singleton->full_gdscript_cache[p_owner] = script.ptr();
+ Ref<GDScript> script = get_cached_script(p_owner);
+ singleton->full_gdscript_cache[p_owner] = script;
singleton->shallow_gdscript_cache.erase(p_owner);
HashSet<String> depends = singleton->dependencies[p_owner];
@@ -245,13 +348,98 @@ Error GDScriptCache::finish_compiling(const String &p_owner) {
return err;
}
+Ref<PackedScene> GDScriptCache::get_packed_scene(const String &p_path, Error &r_error, const String &p_owner) {
+ MutexLock lock(singleton->mutex);
+
+ if (singleton->packed_scene_cache.has(p_path)) {
+ singleton->packed_scene_dependencies[p_path].insert(p_owner);
+ return singleton->packed_scene_cache[p_path];
+ }
+
+ Ref<PackedScene> scene = ResourceCache::get_ref(p_path);
+ if (scene.is_valid()) {
+ singleton->packed_scene_cache[p_path] = scene;
+ singleton->packed_scene_dependencies[p_path].insert(p_owner);
+ return scene;
+ }
+ scene.instantiate();
+
+ r_error = OK;
+ if (p_path.is_empty()) {
+ r_error = ERR_FILE_BAD_PATH;
+ return scene;
+ }
+
+ scene->set_path(p_path);
+ singleton->packed_scene_cache[p_path] = scene;
+ singleton->packed_scene_dependencies[p_path].insert(p_owner);
+
+ scene->reload_from_file();
+ return scene;
+}
+
+void GDScriptCache::clear_unreferenced_packed_scenes() {
+ if (singleton == nullptr) {
+ return;
+ }
+
+ MutexLock lock(singleton->mutex);
+
+ if (singleton->cleared) {
+ return;
+ }
+
+ for (KeyValue<String, HashSet<String>> &E : singleton->packed_scene_dependencies) {
+ if (E.value.size() > 0 || !ResourceLoader::is_imported(E.key)) {
+ continue;
+ }
+
+ singleton->packed_scene_dependencies.erase(E.key);
+ singleton->packed_scene_cache.erase(E.key);
+ }
+}
+
+void GDScriptCache::clear() {
+ if (singleton == nullptr) {
+ return;
+ }
+
+ MutexLock lock(singleton->mutex);
+
+ if (singleton->cleared) {
+ return;
+ }
+ singleton->cleared = true;
+
+ RBSet<Ref<GDScriptParserRef>> parser_map_refs;
+ for (KeyValue<String, GDScriptParserRef *> &E : singleton->parser_map) {
+ parser_map_refs.insert(E.value);
+ }
+
+ for (Ref<GDScriptParserRef> &E : parser_map_refs) {
+ if (E.is_valid())
+ E->clear();
+ }
+
+ singleton->packed_scene_dependencies.clear();
+ singleton->packed_scene_cache.clear();
+
+ parser_map_refs.clear();
+ singleton->parser_map.clear();
+ singleton->shallow_gdscript_cache.clear();
+ singleton->full_gdscript_cache.clear();
+
+ singleton->packed_scene_cache.clear();
+ singleton->packed_scene_dependencies.clear();
+}
+
GDScriptCache::GDScriptCache() {
singleton = this;
}
GDScriptCache::~GDScriptCache() {
- parser_map.clear();
- shallow_gdscript_cache.clear();
- full_gdscript_cache.clear();
+ if (!cleared) {
+ clear();
+ }
singleton = nullptr;
}
diff --git a/modules/gdscript/gdscript_cache.h b/modules/gdscript/gdscript_cache.h
index 3d111ea229..43a45bfef6 100644
--- a/modules/gdscript/gdscript_cache.h
+++ b/modules/gdscript/gdscript_cache.h
@@ -36,6 +36,7 @@
#include "core/templates/hash_map.h"
#include "core/templates/hash_set.h"
#include "gdscript.h"
+#include "scene/resources/packed_scene.h"
class GDScriptAnalyzer;
class GDScriptParser;
@@ -56,6 +57,7 @@ private:
Status status = EMPTY;
Error result = OK;
String path;
+ bool cleared = false;
friend class GDScriptCache;
@@ -63,7 +65,9 @@ public:
bool is_valid() const;
Status get_status() const;
GDScriptParser *get_parser() const;
+ GDScriptAnalyzer *get_analyzer();
Error raise_status(Status p_new_status);
+ void clear();
GDScriptParserRef() {}
~GDScriptParserRef();
@@ -72,25 +76,37 @@ public:
class GDScriptCache {
// String key is full path.
HashMap<String, GDScriptParserRef *> parser_map;
- HashMap<String, GDScript *> shallow_gdscript_cache;
- HashMap<String, GDScript *> full_gdscript_cache;
+ HashMap<String, Ref<GDScript>> shallow_gdscript_cache;
+ HashMap<String, Ref<GDScript>> full_gdscript_cache;
HashMap<String, HashSet<String>> dependencies;
+ HashMap<String, Ref<PackedScene>> packed_scene_cache;
+ HashMap<String, HashSet<String>> packed_scene_dependencies;
friend class GDScript;
friend class GDScriptParserRef;
+ friend class GDScriptInstance;
static GDScriptCache *singleton;
- Mutex lock;
- static void remove_script(const String &p_path);
+ bool cleared = false;
+
+ Mutex mutex;
public:
+ static void move_script(const String &p_from, const String &p_to);
+ static void remove_script(const String &p_path);
static Ref<GDScriptParserRef> get_parser(const String &p_path, GDScriptParserRef::Status status, Error &r_error, const String &p_owner = String());
static String get_source_code(const String &p_path);
- static Ref<GDScript> get_shallow_script(const String &p_path, const String &p_owner = String());
+ static Ref<GDScript> get_shallow_script(const String &p_path, Error &r_error, const String &p_owner = String());
static Ref<GDScript> get_full_script(const String &p_path, Error &r_error, const String &p_owner = String(), bool p_update_from_disk = false);
+ static Ref<GDScript> get_cached_script(const String &p_path);
static Error finish_compiling(const String &p_owner);
+ static Ref<PackedScene> get_packed_scene(const String &p_path, Error &r_error, const String &p_owner = "");
+ static void clear_unreferenced_packed_scenes();
+
+ static void clear();
+
GDScriptCache();
~GDScriptCache();
};
diff --git a/modules/gdscript/gdscript_codegen.h b/modules/gdscript/gdscript_codegen.h
index 5972481c3a..6a94c25c88 100644
--- a/modules/gdscript/gdscript_codegen.h
+++ b/modules/gdscript/gdscript_codegen.h
@@ -59,7 +59,7 @@ public:
type = p_type;
}
Address(AddressMode p_mode, uint32_t p_address, const GDScriptDataType &p_type = GDScriptDataType()) {
- mode = p_mode,
+ mode = p_mode;
address = p_address;
type = p_type;
}
diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp
index fd13edc4cf..6c7b5d534e 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.parameters.has(p_name) || codegen.locals.has(p_name)) {
+ if (_is_local_or_parameter(codegen, p_name)) {
return false; //shadowed
}
@@ -65,6 +65,10 @@ bool GDScriptCompiler::_is_class_member_property(GDScript *owner, const StringNa
return ClassDB::has_property(nc->get_name(), p_name);
}
+bool GDScriptCompiler::_is_local_or_parameter(CodeGen &codegen, const StringName &p_name) {
+ return codegen.parameters.has(p_name) || codegen.locals.has(p_name);
+}
+
void GDScriptCompiler::_set_error(const String &p_error, const GDScriptParser::Node *p_node) {
if (!error.is_empty()) {
return;
@@ -80,7 +84,7 @@ void GDScriptCompiler::_set_error(const String &p_error, const GDScriptParser::N
}
}
-GDScriptDataType GDScriptCompiler::_gdtype_from_datatype(const GDScriptParser::DataType &p_datatype, GDScript *p_owner) const {
+GDScriptDataType GDScriptCompiler::_gdtype_from_datatype(const GDScriptParser::DataType &p_datatype, GDScript *p_owner) {
if (!p_datatype.is_set() || !p_datatype.is_hard_type()) {
return GDScriptDataType();
}
@@ -103,74 +107,44 @@ GDScriptDataType GDScriptCompiler::_gdtype_from_datatype(const GDScriptParser::D
} break;
case GDScriptParser::DataType::SCRIPT: {
result.kind = GDScriptDataType::SCRIPT;
- result.script_type_ref = Ref<Script>(p_datatype.script_type);
+ result.builtin_type = p_datatype.builtin_type;
+ result.script_type_ref = p_datatype.script_type;
result.script_type = result.script_type_ref.ptr();
- result.native_type = result.script_type->get_instance_base_type();
+ result.native_type = p_datatype.native_type;
} break;
case GDScriptParser::DataType::CLASS: {
- // Locate class by constructing the path to it and following that path.
- GDScriptParser::ClassNode *class_type = p_datatype.class_type;
- if (class_type) {
- result.kind = GDScriptDataType::GDSCRIPT;
- result.builtin_type = p_datatype.builtin_type;
-
- String class_name = class_type->fqcn.split("::")[0];
- const bool is_inner_by_path = (!main_script->path.is_empty()) && (class_name == main_script->path);
- const bool is_inner_by_name = (!main_script->name.is_empty()) && (class_name == main_script->name);
- if (is_inner_by_path || is_inner_by_name) {
- // Local class.
- List<StringName> names;
- while (class_type->outer) {
- names.push_back(class_type->identifier->name);
- class_type = class_type->outer;
- }
+ result.kind = GDScriptDataType::GDSCRIPT;
+ result.builtin_type = p_datatype.builtin_type;
+ result.native_type = p_datatype.native_type;
- Ref<GDScript> script = Ref<GDScript>(main_script);
- while (names.back()) {
- if (!script->subclasses.has(names.back()->get())) {
- ERR_PRINT("Parser bug: Cannot locate datatype class.");
- result.has_type = false;
- return GDScriptDataType();
- }
- script = script->subclasses[names.back()->get()];
- names.pop_back();
- }
- result.script_type = script.ptr();
- result.native_type = script->get_instance_base_type();
- } else {
- // Inner class.
- PackedStringArray classes = class_type->fqcn.split("::");
- if (!classes.is_empty()) {
- for (GDScript *script : parsed_classes) {
- // Checking of inheritance structure of inner class to find a correct script link.
- if (script->name == classes[classes.size() - 1]) {
- PackedStringArray classes2 = script->fully_qualified_name.split("::");
- bool valid = true;
- if (classes.size() != classes2.size()) {
- valid = false;
- } else {
- for (int i = 0; i < classes.size(); i++) {
- if (classes[i] != classes2[i]) {
- valid = false;
- break;
- }
- }
- }
- if (!valid) {
- continue;
- }
- result.script_type_ref = Ref<GDScript>(script);
- break;
- }
- }
- }
- if (result.script_type_ref.is_null()) {
- result.script_type_ref = GDScriptCache::get_shallow_script(p_datatype.script_path, main_script->path);
- }
+ bool is_local_class = parser->has_class(p_datatype.class_type);
+
+ Ref<GDScript> script;
+ if (is_local_class) {
+ script = Ref<GDScript>(main_script);
+ } else {
+ Error err = OK;
+ script = GDScriptCache::get_shallow_script(p_datatype.script_path, err, p_owner->path);
+ if (err) {
+ _set_error(vformat(R"(Could not find script "%s": %s)", p_datatype.script_path, error_names[err]), nullptr);
+ }
+ }
+
+ if (script.is_valid()) {
+ script = Ref<GDScript>(script->find_class(p_datatype.class_type->fqcn));
+ }
- result.script_type = result.script_type_ref.ptr();
- result.native_type = p_datatype.native_type;
+ if (script.is_null()) {
+ _set_error(vformat(R"(Could not find class "%s" in "%s".)", p_datatype.class_type->fqcn, p_datatype.script_path), nullptr);
+ return GDScriptDataType();
+ } else {
+ // Only hold a strong reference if the owner of the element qualified with this type is not local, to avoid cyclic references (leaks).
+ // TODO: Might lead to use after free if script_type is a subclass and is used after its parent is freed.
+ if (!is_local_class) {
+ result.script_type_ref = script;
}
+ result.script_type = script.ptr();
+ result.native_type = p_datatype.native_type;
}
} break;
case GDScriptParser::DataType::ENUM:
@@ -182,6 +156,7 @@ GDScriptDataType GDScriptCompiler::_gdtype_from_datatype(const GDScriptParser::D
result.builtin_type = Variant::INT;
}
break;
+ case GDScriptParser::DataType::RESOLVING:
case GDScriptParser::DataType::UNRESOLVED: {
ERR_PRINT("Parser bug: converting unresolved type.");
return GDScriptDataType();
@@ -189,13 +164,7 @@ GDScriptDataType GDScriptCompiler::_gdtype_from_datatype(const GDScriptParser::D
}
if (p_datatype.has_container_element_type()) {
- result.set_container_element_type(_gdtype_from_datatype(p_datatype.get_container_element_type()));
- }
-
- // Only hold strong reference to the script if it's not the owner of the
- // element qualified with this type, to avoid cyclic references (leaks).
- if (result.script_type && result.script_type == p_owner) {
- result.script_type_ref = Ref<Script>();
+ result.set_container_element_type(_gdtype_from_datatype(p_datatype.get_container_element_type(), p_owner));
}
return result;
@@ -367,7 +336,7 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
// This is so one autoload doesn't try to load another before it's compiled.
HashMap<StringName, ProjectSettings::AutoloadInfo> autoloads = ProjectSettings::get_singleton()->get_autoload_list();
if (autoloads.has(identifier) && autoloads[identifier].is_singleton) {
- GDScriptCodeGenerator::Address global = codegen.add_temporary(_gdtype_from_datatype(in->get_datatype()));
+ GDScriptCodeGenerator::Address global = codegen.add_temporary(_gdtype_from_datatype(in->get_datatype(), codegen.script));
int idx = GDScriptLanguage::get_singleton()->get_global_map()[identifier];
gen->write_store_global(global, idx);
return global;
@@ -390,11 +359,22 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
if (class_node->identifier && class_node->identifier->name == identifier) {
res = Ref<GDScript>(main_script);
} else {
- res = ResourceLoader::load(ScriptServer::get_global_class_path(identifier));
- if (res.is_null()) {
- _set_error("Can't load global class " + String(identifier) + ", cyclic reference?", p_expression);
- r_error = ERR_COMPILATION_FAILED;
- return GDScriptCodeGenerator::Address();
+ String global_class_path = ScriptServer::get_global_class_path(identifier);
+ if (ResourceLoader::get_resource_type(global_class_path) == "GDScript") {
+ Error err = OK;
+ res = GDScriptCache::get_full_script(global_class_path, err);
+ if (err != OK) {
+ _set_error("Can't load global class " + String(identifier), p_expression);
+ r_error = ERR_COMPILATION_FAILED;
+ return GDScriptCodeGenerator::Address();
+ }
+ } else {
+ res = ResourceLoader::load(global_class_path);
+ if (res.is_null()) {
+ _set_error("Can't load global class " + String(identifier) + ", cyclic reference?", p_expression);
+ r_error = ERR_COMPILATION_FAILED;
+ return GDScriptCodeGenerator::Address();
+ }
}
}
@@ -434,7 +414,7 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
Vector<GDScriptCodeGenerator::Address> values;
// Create the result temporary first since it's the last to be killed.
- GDScriptDataType array_type = _gdtype_from_datatype(an->get_datatype());
+ GDScriptDataType array_type = _gdtype_from_datatype(an->get_datatype(), codegen.script);
GDScriptCodeGenerator::Address result = codegen.add_temporary(array_type);
for (int i = 0; i < an->elements.size(); i++) {
@@ -510,31 +490,36 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
} break;
case GDScriptParser::Node::CAST: {
const GDScriptParser::CastNode *cn = static_cast<const GDScriptParser::CastNode *>(p_expression);
- GDScriptParser::DataType og_cast_type = cn->cast_type->get_datatype();
- GDScriptDataType cast_type = _gdtype_from_datatype(og_cast_type);
+ GDScriptParser::DataType og_cast_type = cn->get_datatype();
+ GDScriptDataType cast_type = _gdtype_from_datatype(og_cast_type, codegen.script);
- if (og_cast_type.kind == GDScriptParser::DataType::ENUM) {
- // Enum types are usually treated as dictionaries, but in this case we want to cast to an integer.
- cast_type.kind = GDScriptDataType::BUILTIN;
- cast_type.builtin_type = Variant::INT;
- }
+ GDScriptCodeGenerator::Address result;
+ if (cast_type.has_type) {
+ if (og_cast_type.kind == GDScriptParser::DataType::ENUM) {
+ // Enum types are usually treated as dictionaries, but in this case we want to cast to an integer.
+ cast_type.kind = GDScriptDataType::BUILTIN;
+ cast_type.builtin_type = Variant::INT;
+ }
- // Create temporary for result first since it will be deleted last.
- GDScriptCodeGenerator::Address result = codegen.add_temporary(cast_type);
+ // Create temporary for result first since it will be deleted last.
+ result = codegen.add_temporary(cast_type);
- GDScriptCodeGenerator::Address src = _parse_expression(codegen, r_error, cn->operand);
+ GDScriptCodeGenerator::Address src = _parse_expression(codegen, r_error, cn->operand);
- gen->write_cast(result, src, cast_type);
+ gen->write_cast(result, src, cast_type);
- if (src.mode == GDScriptCodeGenerator::Address::TEMPORARY) {
- gen->pop_temporary();
+ if (src.mode == GDScriptCodeGenerator::Address::TEMPORARY) {
+ gen->pop_temporary();
+ }
+ } else {
+ result = _parse_expression(codegen, r_error, cn->operand);
}
return result;
} break;
case GDScriptParser::Node::CALL: {
const GDScriptParser::CallNode *call = static_cast<const GDScriptParser::CallNode *>(p_expression);
- GDScriptDataType type = _gdtype_from_datatype(call->get_datatype());
+ GDScriptDataType type = _gdtype_from_datatype(call->get_datatype(), codegen.script);
GDScriptCodeGenerator::Address result = codegen.add_temporary(type);
GDScriptCodeGenerator::Address nil = GDScriptCodeGenerator::Address(GDScriptCodeGenerator::Address::NIL);
@@ -670,7 +655,7 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
Vector<GDScriptCodeGenerator::Address> args;
args.push_back(codegen.add_constant(NodePath(get_node->full_path)));
- GDScriptCodeGenerator::Address result = codegen.add_temporary(_gdtype_from_datatype(get_node->get_datatype()));
+ GDScriptCodeGenerator::Address result = codegen.add_temporary(_gdtype_from_datatype(get_node->get_datatype(), codegen.script));
MethodBind *get_node_method = ClassDB::get_method("Node", "get_node");
gen->write_call_ptrcall(result, GDScriptCodeGenerator::Address(GDScriptCodeGenerator::Address::SELF), get_node_method, args);
@@ -686,7 +671,7 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
case GDScriptParser::Node::AWAIT: {
const GDScriptParser::AwaitNode *await = static_cast<const GDScriptParser::AwaitNode *>(p_expression);
- GDScriptCodeGenerator::Address result = codegen.add_temporary(_gdtype_from_datatype(p_expression->get_datatype()));
+ GDScriptCodeGenerator::Address result = codegen.add_temporary(_gdtype_from_datatype(p_expression->get_datatype(), codegen.script));
within_await = true;
GDScriptCodeGenerator::Address argument = _parse_expression(codegen, r_error, await->to_await);
within_await = false;
@@ -705,7 +690,7 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
// Indexing operator.
case GDScriptParser::Node::SUBSCRIPT: {
const GDScriptParser::SubscriptNode *subscript = static_cast<const GDScriptParser::SubscriptNode *>(p_expression);
- GDScriptCodeGenerator::Address result = codegen.add_temporary(_gdtype_from_datatype(subscript->get_datatype()));
+ GDScriptCodeGenerator::Address result = codegen.add_temporary(_gdtype_from_datatype(subscript->get_datatype(), codegen.script));
GDScriptCodeGenerator::Address base = _parse_expression(codegen, r_error, subscript->base);
if (r_error) {
@@ -735,7 +720,7 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
// Remove result temp as we don't need it.
gen->pop_temporary();
// Faster than indexing self (as if no self. had been used).
- return GDScriptCodeGenerator::Address(GDScriptCodeGenerator::Address::MEMBER, MI->value.index, _gdtype_from_datatype(subscript->get_datatype()));
+ return GDScriptCodeGenerator::Address(GDScriptCodeGenerator::Address::MEMBER, MI->value.index, _gdtype_from_datatype(subscript->get_datatype(), codegen.script));
}
}
@@ -773,7 +758,7 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
case GDScriptParser::Node::UNARY_OPERATOR: {
const GDScriptParser::UnaryOpNode *unary = static_cast<const GDScriptParser::UnaryOpNode *>(p_expression);
- GDScriptCodeGenerator::Address result = codegen.add_temporary(_gdtype_from_datatype(unary->get_datatype()));
+ GDScriptCodeGenerator::Address result = codegen.add_temporary(_gdtype_from_datatype(unary->get_datatype(), codegen.script));
GDScriptCodeGenerator::Address operand = _parse_expression(codegen, r_error, unary->operand);
if (r_error) {
@@ -791,7 +776,7 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
case GDScriptParser::Node::BINARY_OPERATOR: {
const GDScriptParser::BinaryOpNode *binary = static_cast<const GDScriptParser::BinaryOpNode *>(p_expression);
- GDScriptCodeGenerator::Address result = codegen.add_temporary(_gdtype_from_datatype(binary->get_datatype()));
+ GDScriptCodeGenerator::Address result = codegen.add_temporary(_gdtype_from_datatype(binary->get_datatype(), codegen.script));
switch (binary->operation) {
case GDScriptParser::BinaryOpNode::OP_LOGIC_AND: {
@@ -867,7 +852,7 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
case GDScriptParser::Node::TERNARY_OPERATOR: {
// x IF a ELSE y operator with early out on failure.
const GDScriptParser::TernaryOpNode *ternary = static_cast<const GDScriptParser::TernaryOpNode *>(p_expression);
- GDScriptCodeGenerator::Address result = codegen.add_temporary(_gdtype_from_datatype(ternary->get_datatype()));
+ GDScriptCodeGenerator::Address result = codegen.add_temporary(_gdtype_from_datatype(ternary->get_datatype(), codegen.script));
gen->write_start_ternary(result);
@@ -944,7 +929,7 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
StringName var_name = identifier->name;
if (_is_class_member_property(codegen, var_name)) {
assign_class_member_property = var_name;
- } else if (!codegen.locals.has(var_name) && codegen.script->member_indices.has(var_name)) {
+ } else if (!_is_local_or_parameter(codegen, var_name) && codegen.script->member_indices.has(var_name)) {
is_member_property = true;
member_property_setter_function = codegen.script->member_indices[var_name].setter;
member_property_has_setter = member_property_setter_function != StringName();
@@ -985,7 +970,7 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
break;
}
const GDScriptParser::SubscriptNode *subscript_elem = E->get();
- GDScriptCodeGenerator::Address value = codegen.add_temporary(_gdtype_from_datatype(subscript_elem->get_datatype()));
+ GDScriptCodeGenerator::Address value = codegen.add_temporary(_gdtype_from_datatype(subscript_elem->get_datatype(), codegen.script));
GDScriptCodeGenerator::Address key;
StringName name;
@@ -1024,8 +1009,8 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
// Perform operator if any.
if (assignment->operation != GDScriptParser::AssignmentNode::OP_NONE) {
- GDScriptCodeGenerator::Address op_result = codegen.add_temporary(_gdtype_from_datatype(assignment->get_datatype()));
- GDScriptCodeGenerator::Address value = codegen.add_temporary(_gdtype_from_datatype(subscript->get_datatype()));
+ GDScriptCodeGenerator::Address op_result = codegen.add_temporary(_gdtype_from_datatype(assignment->get_datatype(), codegen.script));
+ GDScriptCodeGenerator::Address value = codegen.add_temporary(_gdtype_from_datatype(subscript->get_datatype(), codegen.script));
if (subscript->is_attribute) {
gen->write_get_named(value, name, prev_base);
} else {
@@ -1130,8 +1115,8 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
StringName name = static_cast<GDScriptParser::IdentifierNode *>(assignment->assignee)->name;
if (has_operation) {
- GDScriptCodeGenerator::Address op_result = codegen.add_temporary(_gdtype_from_datatype(assignment->get_datatype()));
- GDScriptCodeGenerator::Address member = codegen.add_temporary(_gdtype_from_datatype(assignment->assignee->get_datatype()));
+ GDScriptCodeGenerator::Address op_result = codegen.add_temporary(_gdtype_from_datatype(assignment->get_datatype(), codegen.script));
+ GDScriptCodeGenerator::Address member = codegen.add_temporary(_gdtype_from_datatype(assignment->assignee->get_datatype(), codegen.script));
gen->write_get_member(member, name);
gen->write_binary_operator(op_result, assignment->variant_op, member, assigned_value);
gen->pop_temporary(); // Pop member temp.
@@ -1155,7 +1140,7 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
bool is_in_setter = false;
StringName setter_function;
StringName var_name = static_cast<const GDScriptParser::IdentifierNode *>(assignment->assignee)->name;
- if (!codegen.locals.has(var_name) && codegen.script->member_indices.has(var_name)) {
+ if (!_is_local_or_parameter(codegen, var_name) && codegen.script->member_indices.has(var_name)) {
is_member = true;
setter_function = codegen.script->member_indices[var_name].setter;
has_setter = setter_function != StringName();
@@ -1184,7 +1169,7 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
bool has_operation = assignment->operation != GDScriptParser::AssignmentNode::OP_NONE;
if (has_operation) {
// Perform operation.
- GDScriptCodeGenerator::Address op_result = codegen.add_temporary(_gdtype_from_datatype(assignment->get_datatype()));
+ GDScriptCodeGenerator::Address op_result = codegen.add_temporary(_gdtype_from_datatype(assignment->get_datatype(), codegen.script));
GDScriptCodeGenerator::Address og_value = _parse_expression(codegen, r_error, assignment->assignee);
gen->write_binary_operator(op_result, assignment->variant_op, og_value, assigned_value);
to_assign = op_result;
@@ -1196,7 +1181,7 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
to_assign = assigned_value;
}
- GDScriptDataType assign_type = _gdtype_from_datatype(assignment->assignee->get_datatype());
+ GDScriptDataType assign_type = _gdtype_from_datatype(assignment->assignee->get_datatype(), codegen.script);
if (has_setter && !is_in_setter) {
// Call setter.
@@ -1226,7 +1211,7 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
} break;
case GDScriptParser::Node::LAMBDA: {
const GDScriptParser::LambdaNode *lambda = static_cast<const GDScriptParser::LambdaNode *>(p_expression);
- GDScriptCodeGenerator::Address result = codegen.add_temporary(_gdtype_from_datatype(lambda->get_datatype()));
+ GDScriptCodeGenerator::Address result = codegen.add_temporary(_gdtype_from_datatype(lambda->get_datatype(), codegen.script));
Vector<GDScriptCodeGenerator::Address> captures;
captures.resize(lambda->captures.size());
@@ -1276,9 +1261,30 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_match_pattern(CodeGen &c
equality_type.kind = GDScriptDataType::BUILTIN;
equality_type.builtin_type = Variant::BOOL;
+ GDScriptCodeGenerator::Address type_string_addr = codegen.add_constant(Variant::STRING);
+ GDScriptCodeGenerator::Address type_string_name_addr = codegen.add_constant(Variant::STRING_NAME);
+
// Check type equality.
GDScriptCodeGenerator::Address type_equality_addr = codegen.add_temporary(equality_type);
codegen.generator->write_binary_operator(type_equality_addr, Variant::OP_EQUAL, p_type_addr, literal_type_addr);
+
+ // Check if StringName <-> String comparison is possible.
+ GDScriptCodeGenerator::Address type_comp_addr_1 = codegen.add_temporary(equality_type);
+ GDScriptCodeGenerator::Address type_comp_addr_2 = codegen.add_temporary(equality_type);
+
+ codegen.generator->write_binary_operator(type_comp_addr_1, Variant::OP_EQUAL, p_type_addr, type_string_addr);
+ codegen.generator->write_binary_operator(type_comp_addr_2, Variant::OP_EQUAL, literal_type_addr, type_string_name_addr);
+ codegen.generator->write_binary_operator(type_comp_addr_1, Variant::OP_AND, type_comp_addr_1, type_comp_addr_2);
+ codegen.generator->write_binary_operator(type_equality_addr, Variant::OP_OR, type_equality_addr, type_comp_addr_1);
+
+ codegen.generator->write_binary_operator(type_comp_addr_1, Variant::OP_EQUAL, p_type_addr, type_string_name_addr);
+ codegen.generator->write_binary_operator(type_comp_addr_2, Variant::OP_EQUAL, literal_type_addr, type_string_addr);
+ codegen.generator->write_binary_operator(type_comp_addr_1, Variant::OP_AND, type_comp_addr_1, type_comp_addr_2);
+ codegen.generator->write_binary_operator(type_equality_addr, Variant::OP_OR, type_equality_addr, type_comp_addr_1);
+
+ codegen.generator->pop_temporary(); // Remove type_comp_addr_2 from stack.
+ codegen.generator->pop_temporary(); // Remove type_comp_addr_1 from stack.
+
codegen.generator->write_and_left_operand(type_equality_addr);
// Get literal.
@@ -1645,7 +1651,7 @@ void GDScriptCompiler::_add_locals_in_block(CodeGen &codegen, const GDScriptPars
// Parameters are added directly from function and loop variables are declared explicitly.
continue;
}
- codegen.add_local(p_block->locals[i].name, _gdtype_from_datatype(p_block->locals[i].get_datatype()));
+ codegen.add_local(p_block->locals[i].name, _gdtype_from_datatype(p_block->locals[i].get_datatype(), codegen.script));
}
}
@@ -1675,7 +1681,7 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Sui
codegen.start_block();
// Evaluate the match expression.
- GDScriptCodeGenerator::Address value = codegen.add_local("@match_value", _gdtype_from_datatype(match->test->get_datatype()));
+ GDScriptCodeGenerator::Address value = codegen.add_local("@match_value", _gdtype_from_datatype(match->test->get_datatype(), codegen.script));
GDScriptCodeGenerator::Address value_expr = _parse_expression(codegen, err, match->test);
if (err) {
return err;
@@ -1784,9 +1790,9 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Sui
const GDScriptParser::ForNode *for_n = static_cast<const GDScriptParser::ForNode *>(s);
codegen.start_block();
- GDScriptCodeGenerator::Address iterator = codegen.add_local(for_n->variable->name, _gdtype_from_datatype(for_n->variable->get_datatype()));
+ GDScriptCodeGenerator::Address iterator = codegen.add_local(for_n->variable->name, _gdtype_from_datatype(for_n->variable->get_datatype(), codegen.script));
- gen->start_for(iterator.type, _gdtype_from_datatype(for_n->list->get_datatype()));
+ gen->start_for(iterator.type, _gdtype_from_datatype(for_n->list->get_datatype(), codegen.script));
GDScriptCodeGenerator::Address list = _parse_expression(codegen, err, for_n->list);
if (err) {
@@ -1897,13 +1903,14 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Sui
const GDScriptParser::VariableNode *lv = static_cast<const GDScriptParser::VariableNode *>(s);
// Should be already in stack when the block began.
GDScriptCodeGenerator::Address local = codegen.locals[lv->identifier->name];
- GDScriptParser::DataType local_type = lv->get_datatype();
+ GDScriptDataType local_type = _gdtype_from_datatype(lv->get_datatype(), codegen.script);
+ bool initialized = false;
if (lv->initializer != nullptr) {
// For typed arrays we need to make sure this is already initialized correctly so typed assignment work.
- if (local_type.is_hard_type() && local_type.builtin_type == Variant::ARRAY) {
+ if (local_type.has_type && local_type.builtin_type == Variant::ARRAY) {
if (local_type.has_container_element_type()) {
- codegen.generator->write_construct_typed_array(local, _gdtype_from_datatype(local_type.get_container_element_type(), codegen.script), Vector<GDScriptCodeGenerator::Address>());
+ codegen.generator->write_construct_typed_array(local, local_type.get_container_element_type(), Vector<GDScriptCodeGenerator::Address>());
} else {
codegen.generator->write_construct_array(local, Vector<GDScriptCodeGenerator::Address>());
}
@@ -1920,15 +1927,23 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Sui
if (src_address.mode == GDScriptCodeGenerator::Address::TEMPORARY) {
codegen.generator->pop_temporary();
}
- } else if (lv->get_datatype().is_hard_type()) {
+ initialized = true;
+ } else if (local_type.has_type) {
// Initialize with default for type.
if (local_type.has_container_element_type()) {
- codegen.generator->write_construct_typed_array(local, _gdtype_from_datatype(local_type.get_container_element_type(), codegen.script), Vector<GDScriptCodeGenerator::Address>());
- } else if (local_type.kind == GDScriptParser::DataType::BUILTIN) {
+ codegen.generator->write_construct_typed_array(local, local_type.get_container_element_type(), Vector<GDScriptCodeGenerator::Address>());
+ initialized = true;
+ } else if (local_type.kind == GDScriptDataType::BUILTIN) {
codegen.generator->write_construct(local, local_type.builtin_type, Vector<GDScriptCodeGenerator::Address>());
+ initialized = true;
}
// The `else` branch is for objects, in such case we leave it as `null`.
}
+
+ // Assigns a null for the unassigned variables in loops.
+ if (!initialized && p_block->is_loop) {
+ codegen.generator->write_construct(local, Variant::NIL, Vector<GDScriptCodeGenerator::Address>());
+ }
} break;
case GDScriptParser::Node::CONSTANT: {
// Local constants.
@@ -2033,17 +2048,17 @@ GDScriptFunction *GDScriptCompiler::_parse_function(Error &r_error, GDScript *p_
continue;
}
- GDScriptParser::DataType field_type = field->get_datatype();
+ GDScriptDataType field_type = _gdtype_from_datatype(field->get_datatype(), codegen.script);
- GDScriptCodeGenerator::Address dst_address(GDScriptCodeGenerator::Address::MEMBER, codegen.script->member_indices[field->identifier->name].index, _gdtype_from_datatype(field->get_datatype()));
+ GDScriptCodeGenerator::Address dst_address(GDScriptCodeGenerator::Address::MEMBER, codegen.script->member_indices[field->identifier->name].index, field_type);
if (field->initializer) {
// Emit proper line change.
codegen.generator->write_newline(field->initializer->start_line);
// For typed arrays we need to make sure this is already initialized correctly so typed assignment work.
- if (field_type.is_hard_type() && field_type.builtin_type == Variant::ARRAY) {
+ if (field_type.has_type && field_type.builtin_type == Variant::ARRAY) {
if (field_type.has_container_element_type()) {
- codegen.generator->write_construct_typed_array(dst_address, _gdtype_from_datatype(field_type.get_container_element_type(), codegen.script), Vector<GDScriptCodeGenerator::Address>());
+ codegen.generator->write_construct_typed_array(dst_address, field_type.get_container_element_type(), Vector<GDScriptCodeGenerator::Address>());
} else {
codegen.generator->write_construct_array(dst_address, Vector<GDScriptCodeGenerator::Address>());
}
@@ -2062,13 +2077,13 @@ GDScriptFunction *GDScriptCompiler::_parse_function(Error &r_error, GDScript *p_
if (src_address.mode == GDScriptCodeGenerator::Address::TEMPORARY) {
codegen.generator->pop_temporary();
}
- } else if (field->get_datatype().is_hard_type()) {
+ } else if (field_type.has_type) {
codegen.generator->write_newline(field->start_line);
// Initialize with default for type.
if (field_type.has_container_element_type()) {
- codegen.generator->write_construct_typed_array(dst_address, _gdtype_from_datatype(field_type.get_container_element_type(), codegen.script), Vector<GDScriptCodeGenerator::Address>());
- } else if (field_type.kind == GDScriptParser::DataType::BUILTIN) {
+ codegen.generator->write_construct_typed_array(dst_address, field_type.get_container_element_type(), Vector<GDScriptCodeGenerator::Address>());
+ } else if (field_type.kind == GDScriptDataType::BUILTIN) {
codegen.generator->write_construct(dst_address, field_type.builtin_type, Vector<GDScriptCodeGenerator::Address>());
}
// The `else` branch is for objects, in such case we leave it as `null`.
@@ -2107,8 +2122,8 @@ GDScriptFunction *GDScriptCompiler::_parse_function(Error &r_error, GDScript *p_
if (EngineDebugger::is_active()) {
String signature;
// Path.
- if (!p_script->get_path().is_empty()) {
- signature += p_script->get_path();
+ if (!p_script->get_script_path().is_empty()) {
+ signature += p_script->get_script_path();
}
// Location.
if (p_func) {
@@ -2195,23 +2210,20 @@ Error GDScriptCompiler::_parse_setter_getter(GDScript *p_script, const GDScriptP
return err;
}
-Error GDScriptCompiler::_parse_class_level(GDScript *p_script, const GDScriptParser::ClassNode *p_class, bool p_keep_state) {
- parsing_classes.insert(p_script);
+Error GDScriptCompiler::_populate_class_members(GDScript *p_script, const GDScriptParser::ClassNode *p_class, bool p_keep_state) {
+ if (parsed_classes.has(p_script)) {
+ return OK;
+ }
- if (p_class->outer && p_class->outer->outer) {
- // Owner is not root
- if (!parsed_classes.has(p_script->_owner)) {
- if (parsing_classes.has(p_script->_owner)) {
- _set_error("Cyclic class reference for '" + String(p_class->identifier->name) + "'.", p_class);
- return ERR_PARSE_ERROR;
- }
- Error err = _parse_class_level(p_script->_owner, p_class->outer, p_keep_state);
- if (err) {
- return err;
- }
- }
+ if (parsing_classes.has(p_script)) {
+ String class_name = p_class->identifier ? String(p_class->identifier->name) : p_class->fqcn;
+ _set_error(vformat(R"(Cyclic class reference for "%s".)", class_name), p_class);
+ return ERR_PARSE_ERROR;
}
+ parsing_classes.insert(p_script);
+
+ p_script->clearing = true;
#ifdef TOOLS_ENABLED
p_script->doc_functions.clear();
p_script->doc_variables.clear();
@@ -2234,10 +2246,24 @@ Error GDScriptCompiler::_parse_class_level(GDScript *p_script, const GDScriptPar
p_script->base = Ref<GDScript>();
p_script->_base = nullptr;
p_script->members.clear();
+
+ // This makes possible to clear script constants and member_functions without heap-use-after-free errors.
+ HashMap<StringName, Variant> constants;
+ for (const KeyValue<StringName, Variant> &E : p_script->constants) {
+ constants.insert(E.key, E.value);
+ }
p_script->constants.clear();
+ constants.clear();
+ HashMap<StringName, GDScriptFunction *> member_functions;
for (const KeyValue<StringName, GDScriptFunction *> &E : p_script->member_functions) {
+ member_functions.insert(E.key, E.value);
+ }
+ p_script->member_functions.clear();
+ for (const KeyValue<StringName, GDScriptFunction *> &E : member_functions) {
memdelete(E.value);
}
+ member_functions.clear();
+
if (p_script->implicit_initializer) {
memdelete(p_script->implicit_initializer);
}
@@ -2252,8 +2278,9 @@ Error GDScriptCompiler::_parse_class_level(GDScript *p_script, const GDScriptPar
p_script->implicit_initializer = nullptr;
p_script->implicit_ready = nullptr;
+ p_script->clearing = false;
+
p_script->tool = parser->is_tool();
- p_script->name = p_class->identifier ? p_class->identifier->name : "";
if (!p_script->name.is_empty()) {
if (ClassDB::class_exists(p_script->name) && ClassDB::is_class_exposed(p_script->name)) {
@@ -2262,53 +2289,50 @@ Error GDScriptCompiler::_parse_class_level(GDScript *p_script, const GDScriptPar
}
}
- Ref<GDScriptNativeClass> native;
+ GDScriptDataType base_type = _gdtype_from_datatype(p_class->base_type, p_script);
- GDScriptDataType base_type = _gdtype_from_datatype(p_class->base_type);
// Inheritance
switch (base_type.kind) {
case GDScriptDataType::NATIVE: {
int native_idx = GDScriptLanguage::get_singleton()->get_global_map()[base_type.native_type];
- native = GDScriptLanguage::get_singleton()->get_global_array()[native_idx];
- ERR_FAIL_COND_V(native.is_null(), ERR_BUG);
- p_script->native = native;
+ p_script->native = GDScriptLanguage::get_singleton()->get_global_array()[native_idx];
+ ERR_FAIL_COND_V(p_script->native.is_null(), ERR_BUG);
} break;
case GDScriptDataType::GDSCRIPT: {
Ref<GDScript> base = Ref<GDScript>(base_type.script_type);
- p_script->base = base;
- p_script->_base = base.ptr();
+ if (base.is_null()) {
+ return ERR_COMPILATION_FAILED;
+ }
- if (p_class->base_type.kind == GDScriptParser::DataType::CLASS && p_class->base_type.class_type != nullptr) {
- if (p_class->base_type.script_path == main_script->path) {
- if (!parsed_classes.has(p_script->_base)) {
- if (parsing_classes.has(p_script->_base)) {
- String class_name = p_class->identifier ? p_class->identifier->name : "<main>";
- _set_error("Cyclic class reference for '" + class_name + "'.", p_class);
- return ERR_PARSE_ERROR;
- }
- Error err = _parse_class_level(p_script->_base, p_class->base_type.class_type, p_keep_state);
- if (err) {
- return err;
- }
- }
- } else {
- Error err = OK;
- base = GDScriptCache::get_full_script(p_class->base_type.script_path, err, main_script->path);
- if (err) {
- return err;
- }
- if (base.is_null() || !base->is_valid()) {
- return ERR_COMPILATION_FAILED;
- }
+ if (main_script->has_class(base.ptr())) {
+ Error err = _populate_class_members(base.ptr(), p_class->base_type.class_type, p_keep_state);
+ if (err) {
+ return err;
+ }
+ } else if (!base->is_valid()) {
+ Error err = OK;
+ Ref<GDScript> base_root = GDScriptCache::get_full_script(base->path, err, p_script->path);
+ if (err) {
+ _set_error(vformat(R"(Could not compile base class "%s" from "%s": %s)", base->fully_qualified_name, base->path, error_names[err]), nullptr);
+ return err;
+ }
+ if (base_root.is_valid()) {
+ base = Ref<GDScript>(base_root->find_class(base->fully_qualified_name));
}
+ if (base.is_null()) {
+ _set_error(vformat(R"(Could not find class "%s" in "%s".)", base->fully_qualified_name, base->path), nullptr);
+ return ERR_COMPILATION_FAILED;
+ }
+ ERR_FAIL_COND_V(!base->is_valid() && !base->reloading, ERR_BUG);
}
+ p_script->base = base;
+ p_script->_base = base.ptr();
p_script->member_indices = base->member_indices;
- native = base->native;
- p_script->native = native;
+ p_script->native = base->native;
} break;
default: {
- _set_error("Parser bug: invalid inheritance.", p_class);
+ _set_error("Parser bug: invalid inheritance.", nullptr);
return ERR_BUG;
} break;
}
@@ -2370,6 +2394,7 @@ Error GDScriptCompiler::_parse_class_level(GDScript *p_script, const GDScriptPar
#ifdef TOOLS_ENABLED
if (variable->initializer != nullptr && variable->initializer->is_constant) {
p_script->member_default_values[name] = variable->initializer->reduced_value;
+ GDScriptCompiler::convert_to_initializer_type(p_script->member_default_values[name], variable);
} else {
p_script->member_default_values.erase(name);
}
@@ -2428,26 +2453,20 @@ Error GDScriptCompiler::_parse_class_level(GDScript *p_script, const GDScriptPar
case GDScriptParser::ClassNode::Member::ENUM: {
const GDScriptParser::EnumNode *enum_n = member.m_enum;
+ StringName name = enum_n->identifier->name;
- // TODO: Make enums not be just a dictionary?
- Dictionary new_enum;
- for (int j = 0; j < enum_n->values.size(); j++) {
- // Needs to be string because Variant::get will convert to String.
- new_enum[String(enum_n->values[j].identifier->name)] = enum_n->values[j].value;
- }
-
- p_script->constants.insert(enum_n->identifier->name, new_enum);
+ p_script->constants.insert(name, enum_n->dictionary);
#ifdef TOOLS_ENABLED
- p_script->member_lines[enum_n->identifier->name] = enum_n->start_line;
- p_script->doc_enums[enum_n->identifier->name] = DocData::EnumDoc();
- p_script->doc_enums[enum_n->identifier->name].name = enum_n->identifier->name;
- p_script->doc_enums[enum_n->identifier->name].description = enum_n->doc_description;
+ p_script->member_lines[name] = enum_n->start_line;
+ p_script->doc_enums[name] = DocData::EnumDoc();
+ p_script->doc_enums[name].name = name;
+ p_script->doc_enums[name].description = enum_n->doc_description;
for (int j = 0; j < enum_n->values.size(); j++) {
DocData::ConstantDoc const_doc;
const_doc.name = enum_n->values[j].identifier->name;
const_doc.value = Variant(enum_n->values[j].value).operator String();
const_doc.description = enum_n->values[j].doc_description;
- p_script->doc_enums[enum_n->identifier->name].values.push_back(const_doc);
+ p_script->doc_enums[name].values.push_back(const_doc);
}
#endif
} break;
@@ -2478,8 +2497,7 @@ Error GDScriptCompiler::_parse_class_level(GDScript *p_script, const GDScriptPar
parsed_classes.insert(p_script);
parsing_classes.erase(p_script);
- //parse sub-classes
-
+ // Populate sub-classes.
for (int i = 0; i < p_class->members.size(); i++) {
const GDScriptParser::ClassNode::Member &member = p_class->members[i];
if (member.type != member.CLASS) {
@@ -2491,27 +2509,24 @@ Error GDScriptCompiler::_parse_class_level(GDScript *p_script, const GDScriptPar
GDScript *subclass_ptr = subclass.ptr();
// Subclass might still be parsing, just skip it
- if (!parsed_classes.has(subclass_ptr) && !parsing_classes.has(subclass_ptr)) {
- Error err = _parse_class_level(subclass_ptr, inner_class, p_keep_state);
+ if (!parsing_classes.has(subclass_ptr)) {
+ Error err = _populate_class_members(subclass_ptr, inner_class, p_keep_state);
if (err) {
return err;
}
}
#ifdef TOOLS_ENABLED
-
p_script->member_lines[name] = inner_class->start_line;
#endif
-
p_script->constants.insert(name, subclass); //once parsed, goes to the list of constants
}
return OK;
}
-Error GDScriptCompiler::_parse_class_blocks(GDScript *p_script, const GDScriptParser::ClassNode *p_class, bool p_keep_state) {
- //parse methods
-
+Error GDScriptCompiler::_compile_class(GDScript *p_script, const GDScriptParser::ClassNode *p_class, bool p_keep_state) {
+ // Compile member functions, getters, and setters.
for (int i = 0; i < p_class->members.size(); i++) {
const GDScriptParser::ClassNode::Member &member = p_class->members[i];
if (member.type == member.FUNCTION) {
@@ -2615,17 +2630,40 @@ Error GDScriptCompiler::_parse_class_blocks(GDScript *p_script, const GDScriptPa
StringName name = inner_class->identifier->name;
GDScript *subclass = p_script->subclasses[name].ptr();
- Error err = _parse_class_blocks(subclass, inner_class, p_keep_state);
+ Error err = _compile_class(subclass, inner_class, p_keep_state);
if (err) {
return err;
}
}
+#ifdef TOOLS_ENABLED
+ p_script->_update_doc();
+#endif
+
+ p_script->_init_rpc_methods_properties();
+
p_script->valid = true;
return OK;
}
-void GDScriptCompiler::_make_scripts(GDScript *p_script, const GDScriptParser::ClassNode *p_class, bool p_keep_state) {
+void GDScriptCompiler::convert_to_initializer_type(Variant &p_variant, const GDScriptParser::VariableNode *p_node) {
+ // Set p_variant to the value of p_node's initializer, with the type of p_node's variable.
+ GDScriptParser::DataType member_t = p_node->datatype;
+ GDScriptParser::DataType init_t = p_node->initializer->datatype;
+ if (member_t.is_hard_type() && init_t.is_hard_type() &&
+ member_t.kind == GDScriptParser::DataType::BUILTIN && init_t.kind == GDScriptParser::DataType::BUILTIN) {
+ if (Variant::can_convert_strict(init_t.builtin_type, member_t.builtin_type)) {
+ Variant *v = &p_node->initializer->reduced_value;
+ Callable::CallError ce;
+ Variant::construct(member_t.builtin_type, p_variant, const_cast<const Variant **>(&v), 1, ce);
+ }
+ }
+}
+
+void GDScriptCompiler::make_scripts(GDScript *p_script, const GDScriptParser::ClassNode *p_class, bool p_keep_state) {
+ p_script->fully_qualified_name = p_class->fqcn;
+ p_script->name = p_class->identifier ? p_class->identifier->name : "";
+
HashMap<StringName, Ref<GDScript>> old_subclasses;
if (p_keep_state) {
@@ -2642,24 +2680,22 @@ void GDScriptCompiler::_make_scripts(GDScript *p_script, const GDScriptParser::C
StringName name = inner_class->identifier->name;
Ref<GDScript> subclass;
- String fully_qualified_name = p_script->fully_qualified_name + "::" + name;
if (old_subclasses.has(name)) {
subclass = old_subclasses[name];
} else {
- Ref<GDScript> orphan_subclass = GDScriptLanguage::get_singleton()->get_orphan_subclass(fully_qualified_name);
- if (orphan_subclass.is_valid()) {
- subclass = orphan_subclass;
- } else {
- subclass.instantiate();
- }
+ subclass = GDScriptLanguage::get_singleton()->get_orphan_subclass(inner_class->fqcn);
+ }
+
+ if (subclass.is_null()) {
+ subclass.instantiate();
}
subclass->_owner = p_script;
- subclass->fully_qualified_name = fully_qualified_name;
+ subclass->path = p_script->path;
p_script->subclasses.insert(name, subclass);
- _make_scripts(subclass.ptr(), inner_class, false);
+ make_scripts(subclass.ptr(), inner_class, p_keep_state);
}
}
@@ -2673,26 +2709,22 @@ Error GDScriptCompiler::compile(const GDScriptParser *p_parser, GDScript *p_scri
source = p_script->get_path();
- // The best fully qualified name for a base level script is its file path
- p_script->fully_qualified_name = p_script->path;
-
// Create scripts for subclasses beforehand so they can be referenced
- _make_scripts(p_script, root, p_keep_state);
+ make_scripts(p_script, root, p_keep_state);
- p_script->_owner = nullptr;
- Error err = _parse_class_level(p_script, root, p_keep_state);
+ main_script->_owner = nullptr;
+ Error err = _populate_class_members(main_script, parser->get_tree(), p_keep_state);
if (err) {
return err;
}
- err = _parse_class_blocks(p_script, root, p_keep_state);
-
+ err = _compile_class(main_script, root, p_keep_state);
if (err) {
return err;
}
- return GDScriptCache::finish_compiling(p_script->get_path());
+ return GDScriptCache::finish_compiling(main_script->get_path());
}
String GDScriptCompiler::get_error() const {
diff --git a/modules/gdscript/gdscript_compiler.h b/modules/gdscript/gdscript_compiler.h
index e4264ea55b..fc5aa05190 100644
--- a/modules/gdscript/gdscript_compiler.h
+++ b/modules/gdscript/gdscript_compiler.h
@@ -115,13 +115,14 @@ class GDScriptCompiler {
bool _is_class_member_property(CodeGen &codegen, const StringName &p_name);
bool _is_class_member_property(GDScript *owner, const StringName &p_name);
+ bool _is_local_or_parameter(CodeGen &codegen, const StringName &p_name);
void _set_error(const String &p_error, const GDScriptParser::Node *p_node);
Error _create_binary_operator(CodeGen &codegen, const GDScriptParser::BinaryOpNode *on, Variant::Operator op, bool p_initializer = false, const GDScriptCodeGenerator::Address &p_index_addr = GDScriptCodeGenerator::Address());
Error _create_binary_operator(CodeGen &codegen, const GDScriptParser::ExpressionNode *p_left_operand, const GDScriptParser::ExpressionNode *p_right_operand, Variant::Operator op, bool p_initializer = false, const GDScriptCodeGenerator::Address &p_index_addr = GDScriptCodeGenerator::Address());
- GDScriptDataType _gdtype_from_datatype(const GDScriptParser::DataType &p_datatype, GDScript *p_owner = nullptr) const;
+ GDScriptDataType _gdtype_from_datatype(const GDScriptParser::DataType &p_datatype, GDScript *p_owner);
GDScriptCodeGenerator::Address _parse_assign_right_expression(CodeGen &codegen, Error &r_error, const GDScriptParser::AssignmentNode *p_assignmentint, const GDScriptCodeGenerator::Address &p_index_addr = GDScriptCodeGenerator::Address());
GDScriptCodeGenerator::Address _parse_expression(CodeGen &codegen, Error &r_error, const GDScriptParser::ExpressionNode *p_expression, bool p_root = false, bool p_initializer = false, const GDScriptCodeGenerator::Address &p_index_addr = GDScriptCodeGenerator::Address());
@@ -130,9 +131,8 @@ class GDScriptCompiler {
Error _parse_block(CodeGen &codegen, const GDScriptParser::SuiteNode *p_block, bool p_add_locals = true);
GDScriptFunction *_parse_function(Error &r_error, GDScript *p_script, const GDScriptParser::ClassNode *p_class, const GDScriptParser::FunctionNode *p_func, bool p_for_ready = false, bool p_for_lambda = false);
Error _parse_setter_getter(GDScript *p_script, const GDScriptParser::ClassNode *p_class, const GDScriptParser::VariableNode *p_variable, bool p_is_setter);
- Error _parse_class_level(GDScript *p_script, const GDScriptParser::ClassNode *p_class, bool p_keep_state);
- Error _parse_class_blocks(GDScript *p_script, const GDScriptParser::ClassNode *p_class, bool p_keep_state);
- void _make_scripts(GDScript *p_script, const GDScriptParser::ClassNode *p_class, bool p_keep_state);
+ Error _populate_class_members(GDScript *p_script, const GDScriptParser::ClassNode *p_class, bool p_keep_state);
+ Error _compile_class(GDScript *p_script, const GDScriptParser::ClassNode *p_class, bool p_keep_state);
int err_line = 0;
int err_column = 0;
StringName source;
@@ -140,6 +140,8 @@ class GDScriptCompiler {
bool within_await = false;
public:
+ static void convert_to_initializer_type(Variant &p_variant, const GDScriptParser::VariableNode *p_node);
+ static void make_scripts(GDScript *p_script, const GDScriptParser::ClassNode *p_class, bool p_keep_state);
Error compile(const GDScriptParser *p_parser, GDScript *p_script, bool p_keep_state = false);
String get_error() const;
diff --git a/modules/gdscript/gdscript_editor.cpp b/modules/gdscript/gdscript_editor.cpp
index f33d1409bc..d84af0c63c 100644
--- a/modules/gdscript/gdscript_editor.cpp
+++ b/modules/gdscript/gdscript_editor.cpp
@@ -1612,7 +1612,7 @@ static bool _guess_expression_type(GDScriptParser::CompletionContext &p_context,
}
}
- if (!found) {
+ if (!found && base.value.get_type() != Variant::NIL) {
found = _guess_method_return_type_from_base(c, base, call->function_name, r_type);
}
}
@@ -2272,6 +2272,11 @@ static bool _guess_method_return_type_from_base(GDScriptParser::CompletionContex
if (base_type.class_type->has_function(p_method)) {
const GDScriptParser::FunctionNode *method = base_type.class_type->get_member(p_method).function;
if (!is_static || method->is_static) {
+ if (method->get_datatype().is_set() && !method->get_datatype().is_variant()) {
+ r_type.type = method->get_datatype();
+ return true;
+ }
+
int last_return_line = -1;
const GDScriptParser::ExpressionNode *last_returned_value = nullptr;
GDScriptParser::CompletionContext c = p_context;
@@ -2285,10 +2290,6 @@ static bool _guess_method_return_type_from_base(GDScriptParser::CompletionContex
if (_guess_expression_type(c, last_returned_value, r_type)) {
return true;
}
- if (method->get_datatype().is_set() && !method->get_datatype().is_variant()) {
- r_type.type = method->get_datatype();
- return true;
- }
}
}
}
@@ -2511,6 +2512,69 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c
}
}
+static bool _get_subscript_type(GDScriptParser::CompletionContext &p_context, const GDScriptParser::SubscriptNode *p_subscript, GDScriptParser::DataType &r_base_type, Variant *r_base = nullptr) {
+ if (p_context.base == nullptr) {
+ return false;
+ }
+ const GDScriptParser::GetNodeNode *get_node = nullptr;
+
+ switch (p_subscript->base->type) {
+ case GDScriptParser::Node::GET_NODE: {
+ get_node = static_cast<GDScriptParser::GetNodeNode *>(p_subscript->base);
+ } break;
+
+ case GDScriptParser::Node::IDENTIFIER: {
+ const GDScriptParser::IdentifierNode *identifier_node = static_cast<GDScriptParser::IdentifierNode *>(p_subscript->base);
+
+ switch (identifier_node->source) {
+ case GDScriptParser::IdentifierNode::Source::MEMBER_VARIABLE: {
+ if (p_context.current_class != nullptr) {
+ const StringName &member_name = identifier_node->name;
+ const GDScriptParser::ClassNode *current_class = p_context.current_class;
+
+ if (current_class->has_member(member_name)) {
+ const GDScriptParser::ClassNode::Member &member = current_class->get_member(member_name);
+
+ if (member.type == GDScriptParser::ClassNode::Member::VARIABLE) {
+ const GDScriptParser::VariableNode *variable = static_cast<GDScriptParser::VariableNode *>(member.variable);
+
+ if (variable->initializer && variable->initializer->type == GDScriptParser::Node::GET_NODE) {
+ get_node = static_cast<GDScriptParser::GetNodeNode *>(variable->initializer);
+ }
+ }
+ }
+ }
+ } break;
+ case GDScriptParser::IdentifierNode::Source::LOCAL_VARIABLE: {
+ if (identifier_node->next != nullptr && identifier_node->next->type == GDScriptParser::ClassNode::Node::GET_NODE) {
+ get_node = static_cast<GDScriptParser::GetNodeNode *>(identifier_node->next);
+ }
+ } break;
+ default: {
+ } break;
+ }
+ } break;
+ default: {
+ } break;
+ }
+
+ if (get_node != nullptr) {
+ const Object *node = p_context.base->call("get_node_or_null", NodePath(get_node->full_path));
+ if (node != nullptr) {
+ if (r_base != nullptr) {
+ *r_base = node;
+ }
+ r_base_type.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT;
+ r_base_type.kind = GDScriptParser::DataType::NATIVE;
+ r_base_type.native_type = node->get_class_name();
+ r_base_type.builtin_type = Variant::OBJECT;
+ return true;
+ }
+ }
+
+ return false;
+}
+
static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, const GDScriptParser::Node *p_call, int p_argidx, HashMap<String, ScriptLanguage::CodeCompletionOption> &r_result, bool &r_forced, String &r_arghint) {
if (p_call->type == GDScriptParser::Node::PRELOAD) {
if (p_argidx == 0 && bool(EDITOR_GET("text_editor/completion/complete_file_paths"))) {
@@ -2562,12 +2626,16 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c
}
if (subscript->is_attribute) {
- GDScriptCompletionIdentifier ci;
- if (_guess_expression_type(p_context, subscript->base, ci)) {
- base_type = ci.type;
- base = ci.value;
- } else {
- return;
+ bool found_type = _get_subscript_type(p_context, subscript, base_type, &base);
+
+ if (!found_type) {
+ GDScriptCompletionIdentifier ci;
+ if (_guess_expression_type(p_context, subscript->base, ci)) {
+ base_type = ci.type;
+ base = ci.value;
+ } else {
+ return;
+ }
}
_static = base_type.is_meta_type;
@@ -2765,7 +2833,8 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c
const GDScriptParser::SubscriptNode *attr = static_cast<const GDScriptParser::SubscriptNode *>(completion_context.node);
if (attr->base) {
GDScriptCompletionIdentifier base;
- if (!_guess_expression_type(completion_context, attr->base, base)) {
+ bool found_type = _get_subscript_type(completion_context, attr, base.type);
+ if (!found_type && !_guess_expression_type(completion_context, attr->base, base)) {
break;
}
@@ -2779,16 +2848,6 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c
break;
}
- GDScriptParser::CompletionContext c = completion_context;
- c.current_function = nullptr;
- c.current_suite = nullptr;
- c.base = base.value.get_type() == Variant::OBJECT ? base.value.operator Object *() : nullptr;
- if (base.type.kind == GDScriptParser::DataType::CLASS) {
- c.current_class = base.type.class_type;
- } else {
- c.current_class = nullptr;
- }
-
_find_identifiers_in_base(base, false, options, 0);
} break;
case GDScriptParser::COMPLETION_TYPE_ATTRIBUTE: {
@@ -3051,8 +3110,9 @@ static Error _lookup_symbol_from_base(const GDScriptParser::DataType &p_base, co
r_result.type = ScriptLanguage::LOOKUP_RESULT_SCRIPT_LOCATION;
r_result.location = base_type.class_type->get_member(p_symbol).get_line();
r_result.class_path = base_type.script_path;
- r_result.script = GDScriptCache::get_shallow_script(r_result.class_path);
- return OK;
+ Error err = OK;
+ r_result.script = GDScriptCache::get_shallow_script(r_result.class_path, err);
+ return err;
}
base_type = base_type.class_type->base_type;
}
@@ -3208,15 +3268,6 @@ static Error _lookup_symbol_from_base(const GDScriptParser::DataType &p_base, co
}
}
- // Need special checks for assert and preload as they are technically
- // keywords, so are not registered in GDScriptUtilityFunctions.
- if (GDScriptUtilityFunctions::function_exists(p_symbol) || "assert" == p_symbol || "preload" == p_symbol) {
- r_result.type = ScriptLanguage::LOOKUP_RESULT_CLASS_METHOD;
- r_result.class_name = "@GDScript";
- r_result.class_member = p_symbol;
- return OK;
- }
-
if ("PI" == p_symbol || "TAU" == p_symbol || "INF" == p_symbol || "NAN" == p_symbol) {
r_result.type = ScriptLanguage::LOOKUP_RESULT_CLASS_CONSTANT;
r_result.class_name = "@GDScript";
@@ -3226,10 +3277,24 @@ static Error _lookup_symbol_from_base(const GDScriptParser::DataType &p_base, co
GDScriptParser parser;
parser.parse(p_code, p_path, true);
- GDScriptAnalyzer analyzer(&parser);
- analyzer.analyze();
GDScriptParser::CompletionContext context = parser.get_completion_context();
+ context.base = p_owner;
+
+ // Allows class functions with the names like built-ins to be handled properly.
+ if (context.type != GDScriptParser::COMPLETION_ATTRIBUTE) {
+ // Need special checks for assert and preload as they are technically
+ // keywords, so are not registered in GDScriptUtilityFunctions.
+ if (GDScriptUtilityFunctions::function_exists(p_symbol) || "assert" == p_symbol || "preload" == p_symbol) {
+ r_result.type = ScriptLanguage::LOOKUP_RESULT_CLASS_METHOD;
+ r_result.class_name = "@GDScript";
+ r_result.class_member = p_symbol;
+ return OK;
+ }
+ }
+
+ GDScriptAnalyzer analyzer(&parser);
+ analyzer.analyze();
if (context.current_class && context.current_class->extends.size() > 0) {
bool success = false;
@@ -3387,7 +3452,9 @@ static Error _lookup_symbol_from_base(const GDScriptParser::DataType &p_base, co
break;
}
GDScriptCompletionIdentifier base;
- if (!_guess_expression_type(context, subscript->base, base)) {
+
+ bool found_type = _get_subscript_type(context, subscript, base.type);
+ if (!found_type && !_guess_expression_type(context, subscript->base, base)) {
break;
}
diff --git a/modules/gdscript/gdscript_function.cpp b/modules/gdscript/gdscript_function.cpp
index 98b3e40f1b..24a614b1ad 100644
--- a/modules/gdscript/gdscript_function.cpp
+++ b/modules/gdscript/gdscript_function.cpp
@@ -149,10 +149,17 @@ GDScriptFunction::GDScriptFunction() {
}
GDScriptFunction::~GDScriptFunction() {
+ get_script()->member_functions.erase(name);
+
for (int i = 0; i < lambdas.size(); i++) {
memdelete(lambdas[i]);
}
+ for (int i = 0; i < argument_types.size(); i++) {
+ argument_types.write[i].script_type_ref = Ref<Script>();
+ }
+ return_type.script_type_ref = Ref<Script>();
+
#ifdef DEBUG_ENABLED
MutexLock lock(GDScriptLanguage::get_singleton()->mutex);
diff --git a/modules/gdscript/gdscript_function.h b/modules/gdscript/gdscript_function.h
index e44038d6da..6e5f7a8520 100644
--- a/modules/gdscript/gdscript_function.h
+++ b/modules/gdscript/gdscript_function.h
@@ -430,6 +430,7 @@ public:
};
private:
+ friend class GDScript;
friend class GDScriptCompiler;
friend class GDScriptByteCodeGenerator;
diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp
index 6842a1ff49..103269f0f5 100644
--- a/modules/gdscript/gdscript_parser.cpp
+++ b/modules/gdscript/gdscript_parser.cpp
@@ -147,6 +147,10 @@ GDScriptParser::GDScriptParser() {
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::rpc_annotation, varray("", "", "", 0), true);
+
+#ifdef DEBUG_ENABLED
+ is_ignoring_warnings = !(bool)GLOBAL_GET("debug/gdscript/warnings/enable");
+#endif
}
GDScriptParser::~GDScriptParser() {
@@ -230,7 +234,7 @@ void GDScriptParser::push_warning(const Node *p_source, GDScriptWarning::Code p_
warning.leftmost_column = p_source->leftmost_column;
warning.rightmost_column = p_source->rightmost_column;
- if (warn_level == GDScriptWarning::WarnLevel::ERROR) {
+ if (warn_level == GDScriptWarning::WarnLevel::ERROR || bool(GLOBAL_GET("debug/gdscript/warnings/treat_warnings_as_errors"))) {
push_error(warning.get_message(), p_source);
return;
}
@@ -534,6 +538,7 @@ void GDScriptParser::end_statement(const String &p_context) {
void GDScriptParser::parse_program() {
head = alloc_node<ClassNode>();
+ head->fqcn = script_path;
current_class = head;
// If we happen to parse an annotation before extends or class_name keywords, track it.
@@ -637,6 +642,53 @@ void GDScriptParser::parse_program() {
clear_unused_annotations();
}
+GDScriptParser::ClassNode *GDScriptParser::find_class(const String &p_qualified_name) const {
+ String first = p_qualified_name.get_slice("::", 0);
+
+ Vector<String> class_names;
+ GDScriptParser::ClassNode *result = nullptr;
+ // Empty initial name means start at the head.
+ if (first.is_empty() || (head->identifier && first == head->identifier->name)) {
+ class_names = p_qualified_name.split("::");
+ result = head;
+ } else if (p_qualified_name.begins_with(script_path)) {
+ // Script path could have a class path separator("::") in it.
+ class_names = p_qualified_name.trim_prefix(script_path).split("::");
+ result = head;
+ } else if (head->has_member(first)) {
+ class_names = p_qualified_name.split("::");
+ GDScriptParser::ClassNode::Member member = head->get_member(first);
+ if (member.type == GDScriptParser::ClassNode::Member::CLASS) {
+ result = member.m_class;
+ }
+ }
+
+ // Starts at index 1 because index 0 was handled above.
+ for (int i = 1; result != nullptr && i < class_names.size(); i++) {
+ String current_name = class_names[i];
+ GDScriptParser::ClassNode *next = nullptr;
+ if (result->has_member(current_name)) {
+ GDScriptParser::ClassNode::Member member = result->get_member(current_name);
+ if (member.type == GDScriptParser::ClassNode::Member::CLASS) {
+ next = member.m_class;
+ }
+ }
+ result = next;
+ }
+
+ return result;
+}
+
+bool GDScriptParser::has_class(const GDScriptParser::ClassNode *p_class) const {
+ if (head->fqcn.is_empty() && p_class->fqcn.get_slice("::", 0).is_empty()) {
+ return p_class == head;
+ } else if (p_class->fqcn.begins_with(head->fqcn)) {
+ return find_class(p_class->fqcn.trim_prefix(head->fqcn)) == p_class;
+ }
+
+ return false;
+}
+
GDScriptParser::ClassNode *GDScriptParser::parse_class() {
ClassNode *n_class = alloc_node<ClassNode>();
@@ -646,6 +698,15 @@ GDScriptParser::ClassNode *GDScriptParser::parse_class() {
if (consume(GDScriptTokenizer::Token::IDENTIFIER, R"(Expected identifier for the class name after "class".)")) {
n_class->identifier = parse_identifier();
+ if (n_class->outer) {
+ String fqcn = n_class->outer->fqcn;
+ if (fqcn.is_empty()) {
+ fqcn = script_path;
+ }
+ n_class->fqcn = fqcn + "::" + n_class->identifier->name;
+ } else {
+ n_class->fqcn = n_class->identifier->name;
+ }
}
if (match(GDScriptTokenizer::Token::EXTENDS)) {
@@ -684,6 +745,7 @@ GDScriptParser::ClassNode *GDScriptParser::parse_class() {
void GDScriptParser::parse_class_name() {
if (consume(GDScriptTokenizer::Token::IDENTIFIER, R"(Expected identifier for the global class name after "class_name".)")) {
current_class->identifier = parse_identifier();
+ current_class->fqcn = String(current_class->identifier->name);
}
if (match(GDScriptTokenizer::Token::EXTENDS)) {
@@ -1530,7 +1592,7 @@ GDScriptParser::SuiteNode *GDScriptParser::parse_suite(const String &p_context,
VariableNode *variable = static_cast<VariableNode *>(statement);
const SuiteNode::Local &local = current_suite->get_local(variable->identifier->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(), variable->identifier->name));
+ push_error(vformat(R"(There is already a %s named "%s" declared in this scope.)", local.get_name(), variable->identifier->name), variable->identifier);
}
current_suite->add_local(variable, current_function);
break;
@@ -1545,7 +1607,7 @@ GDScriptParser::SuiteNode *GDScriptParser::parse_suite(const String &p_context,
} else {
name = "variable";
}
- push_error(vformat(R"(There is already a %s named "%s" declared in this scope.)", name, constant->identifier->name));
+ push_error(vformat(R"(There is already a %s named "%s" declared in this scope.)", name, constant->identifier->name), constant->identifier);
}
current_suite->add_local(constant, current_function);
break;
@@ -1820,9 +1882,9 @@ GDScriptParser::ForNode *GDScriptParser::parse_for() {
}
suite->add_local(SuiteNode::Local(n_for->variable, current_function));
}
- suite->parent_for = n_for;
n_for->loop = parse_suite(R"("for" block)", suite);
+ n_for->loop->is_loop = true;
complete_extents(n_for);
// Reset break/continue state.
@@ -2154,6 +2216,7 @@ GDScriptParser::WhileNode *GDScriptParser::parse_while() {
is_continue_match = false;
n_while->loop = parse_suite(R"("while" block)");
+ n_while->loop->is_loop = true;
complete_extents(n_while);
// Reset break/continue state.
@@ -2224,7 +2287,7 @@ GDScriptParser::IdentifierNode *GDScriptParser::parse_identifier() {
GDScriptParser::ExpressionNode *GDScriptParser::parse_identifier(ExpressionNode *p_previous_operand, bool p_can_assign) {
if (!previous.is_identifier()) {
- ERR_FAIL_V_MSG(nullptr, "Parser bug: parsing literal node without literal token.");
+ ERR_FAIL_V_MSG(nullptr, "Parser bug: parsing identifier node without identifier token.");
}
IdentifierNode *identifier = alloc_node<IdentifierNode>();
complete_extents(identifier);
@@ -3725,6 +3788,12 @@ bool GDScriptParser::export_annotations(const AnnotationNode *p_annotation, Node
// This is called after the analyzer is done finding the type, so this should be set here.
DataType export_type = variable->get_datatype();
+ if (p_annotation->name == SNAME("@export_range")) {
+ if (export_type.builtin_type == Variant::INT) {
+ variable->export_info.type = Variant::INT;
+ }
+ }
+
if (p_annotation->name == SNAME("@export")) {
if (variable->datatype_specifier == nullptr && variable->initializer == nullptr) {
push_error(R"(Cannot use simple "@export" annotation with variable without type or initializer, since type can't be inferred.)", p_annotation);
@@ -3764,15 +3833,14 @@ bool GDScriptParser::export_annotations(const AnnotationNode *p_annotation, Node
}
break;
case GDScriptParser::DataType::CLASS:
- // Can assume type is a global GDScript class.
if (ClassDB::is_parent_class(export_type.native_type, SNAME("Resource"))) {
variable->export_info.type = Variant::OBJECT;
variable->export_info.hint = PROPERTY_HINT_RESOURCE_TYPE;
- variable->export_info.hint_string = export_type.class_type->identifier->name;
+ variable->export_info.hint_string = export_type.to_string();
} else if (ClassDB::is_parent_class(export_type.native_type, SNAME("Node"))) {
variable->export_info.type = Variant::OBJECT;
variable->export_info.hint = PROPERTY_HINT_NODE_TYPE;
- variable->export_info.hint_string = export_type.class_type->identifier->name;
+ variable->export_info.hint_string = export_type.to_string();
} else {
push_error(R"(Export type can only be built-in, a resource, a node or an enum.)", variable);
return false;
@@ -3781,16 +3849,19 @@ bool GDScriptParser::export_annotations(const AnnotationNode *p_annotation, Node
break;
case GDScriptParser::DataType::SCRIPT: {
StringName class_name;
- if (export_type.script_type != nullptr && export_type.script_type.is_valid()) {
+ StringName native_base;
+ if (export_type.script_type.is_valid()) {
class_name = export_type.script_type->get_language()->get_global_class_name(export_type.script_type->get_path());
+ native_base = export_type.script_type->get_instance_base_type();
}
if (class_name == StringName()) {
Ref<Script> script = ResourceLoader::load(export_type.script_path, SNAME("Script"));
if (script.is_valid()) {
class_name = script->get_language()->get_global_class_name(export_type.script_path);
+ native_base = script->get_instance_base_type();
}
}
- if (class_name != StringName() && ClassDB::is_parent_class(ScriptServer::get_global_class_native_base(class_name), SNAME("Resource"))) {
+ if (class_name != StringName() && native_base != StringName() && ClassDB::is_parent_class(native_base, SNAME("Resource"))) {
variable->export_info.type = Variant::OBJECT;
variable->export_info.hint = PROPERTY_HINT_RESOURCE_TYPE;
variable->export_info.hint_string = class_name;
@@ -4018,11 +4089,12 @@ String GDScriptParser::DataType::to_string() const {
}
case ENUM:
return enum_type.operator String() + " (enum)";
+ case RESOLVING:
case UNRESOLVED:
return "<unresolved type>";
}
- ERR_FAIL_V_MSG("<unresolved type", "Kind set outside the enum range.");
+ ERR_FAIL_V_MSG("<unresolved type>", "Kind set outside the enum range.");
}
static Variant::Type _variant_type_to_typed_array_element_type(Variant::Type p_type) {
diff --git a/modules/gdscript/gdscript_parser.h b/modules/gdscript/gdscript_parser.h
index d8f5b866aa..fd2f7b3288 100644
--- a/modules/gdscript/gdscript_parser.h
+++ b/modules/gdscript/gdscript_parser.h
@@ -107,6 +107,7 @@ public:
CLASS, // GDScript.
ENUM, // Enumeration.
VARIANT, // Can be any type.
+ RESOLVING, // Currently resolving.
UNRESOLVED,
};
Kind kind = UNRESOLVED;
@@ -133,9 +134,10 @@ public:
MethodInfo method_info; // For callable/signals.
HashMap<StringName, int64_t> enum_values; // For enums.
- _FORCE_INLINE_ bool is_set() const { return kind != UNRESOLVED; }
+ _FORCE_INLINE_ bool is_set() const { return kind != RESOLVING && kind != UNRESOLVED; }
+ _FORCE_INLINE_ bool is_resolving() const { return kind == RESOLVING; }
_FORCE_INLINE_ bool has_no_type() const { return type_source == UNDETECTED; }
- _FORCE_INLINE_ bool is_variant() const { return kind == VARIANT || kind == UNRESOLVED; }
+ _FORCE_INLINE_ bool is_variant() const { return kind == VARIANT || kind == RESOLVING || kind == UNRESOLVED; }
_FORCE_INLINE_ bool is_hard_type() const { return type_source > INFERRED; }
String to_string() const;
@@ -188,6 +190,7 @@ public:
return script_type == p_other.script_type;
case CLASS:
return class_type == p_other.class_type;
+ case RESOLVING:
case UNRESOLVED:
break;
}
@@ -480,6 +483,7 @@ public:
IdentifierNode *identifier = nullptr;
Vector<Value> values;
+ Variant dictionary;
#ifdef TOOLS_ENABLED
String doc_description;
#endif // TOOLS_ENABLED
@@ -516,6 +520,32 @@ public:
};
EnumNode::Value enum_value;
+ String get_name() const {
+ switch (type) {
+ case UNDEFINED:
+ return "<undefined member>";
+ case CLASS:
+ // All class-type members have an id.
+ return m_class->identifier->name;
+ case CONSTANT:
+ return constant->identifier->name;
+ case FUNCTION:
+ return function->identifier->name;
+ case SIGNAL:
+ return signal->identifier->name;
+ case VARIABLE:
+ return variable->identifier->name;
+ case ENUM:
+ // All enum-type members have an id.
+ return m_enum->identifier->name;
+ case ENUM_VALUE:
+ return enum_value.identifier->name;
+ case GROUP:
+ return annotation->export_info.name;
+ }
+ return "";
+ }
+
String get_type_name() const {
switch (type) {
case UNDEFINED:
@@ -576,31 +606,42 @@ public:
return variable->get_datatype();
case ENUM:
return m_enum->get_datatype();
- case ENUM_VALUE: {
- // Always integer.
- DataType out_type;
- out_type.type_source = DataType::ANNOTATED_EXPLICIT;
- out_type.kind = DataType::BUILTIN;
- out_type.builtin_type = Variant::INT;
- return out_type;
- }
- case SIGNAL: {
- DataType out_type;
- out_type.type_source = DataType::ANNOTATED_EXPLICIT;
- out_type.kind = DataType::BUILTIN;
- out_type.builtin_type = Variant::SIGNAL;
- // TODO: Add parameter info.
- return out_type;
- }
- case GROUP: {
+ case ENUM_VALUE:
+ return enum_value.identifier->get_datatype();
+ case SIGNAL:
+ return signal->get_datatype();
+ case GROUP:
return DataType();
- }
case UNDEFINED:
return DataType();
}
ERR_FAIL_V_MSG(DataType(), "Reaching unhandled type.");
}
+ Node *get_source_node() const {
+ switch (type) {
+ case CLASS:
+ return m_class;
+ case CONSTANT:
+ return constant;
+ case FUNCTION:
+ return function;
+ case VARIABLE:
+ return variable;
+ case ENUM:
+ return m_enum;
+ case ENUM_VALUE:
+ return enum_value.identifier;
+ case SIGNAL:
+ return signal;
+ case GROUP:
+ return annotation;
+ case UNDEFINED:
+ return nullptr;
+ }
+ ERR_FAIL_V_MSG(nullptr, "Reaching unhandled type.");
+ }
+
Member() {}
Member(ClassNode *p_class) {
@@ -786,6 +827,7 @@ public:
LOCAL_VARIABLE,
LOCAL_ITERATOR, // `for` loop iterator.
LOCAL_BIND, // Pattern bind.
+ MEMBER_SIGNAL,
MEMBER_VARIABLE,
MEMBER_CONSTANT,
INHERITED_VARIABLE,
@@ -1054,12 +1096,12 @@ public:
HashMap<StringName, int> locals_indices;
FunctionNode *parent_function = nullptr;
- ForNode *parent_for = nullptr;
IfNode *parent_if = nullptr;
bool has_return = false;
bool has_continue = false;
bool has_unreachable_code = false; // Just so warnings aren't given more than once per block.
+ bool is_loop = false;
bool has_local(const StringName &p_name) const;
const Local &get_local(const StringName &p_name) const;
@@ -1216,13 +1258,14 @@ private:
bool can_break = false;
bool can_continue = false;
bool is_continue_match = false; // Whether a `continue` will act on a `match`.
- bool is_ignoring_warnings = false;
List<bool> multiline_stack;
ClassNode *head = nullptr;
Node *list = nullptr;
List<ParserError> errors;
+
#ifdef DEBUG_ENABLED
+ bool is_ignoring_warnings = false;
List<GDScriptWarning> warnings;
HashSet<String> ignored_warnings;
HashSet<uint32_t> ignored_warning_codes;
@@ -1428,6 +1471,8 @@ public:
Error parse(const String &p_source_code, const String &p_script_path, bool p_for_completion);
ClassNode *get_tree() const { return head; }
bool is_tool() const { return _is_tool; }
+ ClassNode *find_class(const String &p_qualified_name) const;
+ bool has_class(const GDScriptParser::ClassNode *p_class) const;
static Variant::Type get_builtin_type(const StringName &p_type);
CompletionContext get_completion_context() const { return completion_context; }
diff --git a/modules/gdscript/gdscript_utility_functions.cpp b/modules/gdscript/gdscript_utility_functions.cpp
index bcbe8b8d2b..27b6792e84 100644
--- a/modules/gdscript/gdscript_utility_functions.cpp
+++ b/modules/gdscript/gdscript_utility_functions.cpp
@@ -294,6 +294,7 @@ struct GDScriptUtilityFunctionsDefinitions {
}
GDScript *p = base.ptr();
+ String path = p->get_script_path();
Vector<StringName> sname;
while (p->_owner) {
@@ -302,7 +303,7 @@ struct GDScriptUtilityFunctionsDefinitions {
}
sname.reverse();
- if (!p->path.is_resource_file()) {
+ if (!path.is_resource_file()) {
r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = 0;
r_error.expected = Variant::DICTIONARY;
@@ -317,7 +318,7 @@ struct GDScriptUtilityFunctionsDefinitions {
Dictionary d;
d["@subpath"] = cp;
- d["@path"] = p->get_path();
+ d["@path"] = path;
for (const KeyValue<StringName, GDScript::MemberInfo> &E : base->member_indices) {
if (!d.has(E.key)) {
diff --git a/modules/gdscript/gdscript_vm.cpp b/modules/gdscript/gdscript_vm.cpp
index c73ba798aa..fdcc0625d7 100644
--- a/modules/gdscript/gdscript_vm.cpp
+++ b/modules/gdscript/gdscript_vm.cpp
@@ -2227,7 +2227,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
}
#ifdef DEBUG_ENABLED
gdfs->state.function_name = name;
- gdfs->state.script_path = _script->get_path();
+ gdfs->state.script_path = _script->get_script_path();
#endif
gdfs->state.defarg = defarg;
gdfs->function = this;
diff --git a/modules/gdscript/gdscript_warning.cpp b/modules/gdscript/gdscript_warning.cpp
index a0c107aa53..36bc051643 100644
--- a/modules/gdscript/gdscript_warning.cpp
+++ b/modules/gdscript/gdscript_warning.cpp
@@ -96,7 +96,7 @@ String GDScriptWarning::get_message() const {
} break;
case RETURN_VALUE_DISCARDED: {
CHECK_SYMBOLS(1);
- return "The function '" + symbols[0] + "()' returns a value, but this value is never used.";
+ return "The function '" + symbols[0] + "()' returns a value that will be discarded if not used.";
} break;
case PROPERTY_USED_AS_FUNCTION: {
CHECK_SYMBOLS(2);
@@ -171,6 +171,10 @@ int GDScriptWarning::get_default_value(Code p_code) {
if (get_name_from_code(p_code).to_lower().begins_with("unsafe_")) {
return WarnLevel::IGNORE;
}
+ // Too spammy by default on common cases (connect, Tween, etc.).
+ if (p_code == RETURN_VALUE_DISCARDED) {
+ return WarnLevel::IGNORE;
+ }
return WarnLevel::WARN;
}
diff --git a/modules/gdscript/language_server/gdscript_extend_parser.cpp b/modules/gdscript/language_server/gdscript_extend_parser.cpp
index de3becbaf8..e442bf8159 100644
--- a/modules/gdscript/language_server/gdscript_extend_parser.cpp
+++ b/modules/gdscript/language_server/gdscript_extend_parser.cpp
@@ -844,8 +844,9 @@ Error ExtendGDScriptParser::parse(const String &p_code, const String &p_path) {
lines = p_code.split("\n");
Error err = GDScriptParser::parse(p_code, p_path, false);
+ GDScriptAnalyzer analyzer(this);
+
if (err == OK) {
- GDScriptAnalyzer analyzer(this);
err = analyzer.analyze();
}
update_diagnostics();
diff --git a/modules/gdscript/language_server/gdscript_language_protocol.cpp b/modules/gdscript/language_server/gdscript_language_protocol.cpp
index 39f4c976a4..551973140d 100644
--- a/modules/gdscript/language_server/gdscript_language_protocol.cpp
+++ b/modules/gdscript/language_server/gdscript_language_protocol.cpp
@@ -32,6 +32,7 @@
#include "core/config/project_settings.h"
#include "editor/doc_tools.h"
+#include "editor/editor_help.h"
#include "editor/editor_log.h"
#include "editor/editor_node.h"
#include "editor/editor_settings.h"
diff --git a/modules/gdscript/language_server/godot_lsp.h b/modules/gdscript/language_server/godot_lsp.h
index 024da1cab7..8b58d7731e 100644
--- a/modules/gdscript/language_server/godot_lsp.h
+++ b/modules/gdscript/language_server/godot_lsp.h
@@ -702,7 +702,7 @@ struct DiagnosticRelatedInformation {
Dictionary to_json() const {
Dictionary dict;
- dict["location"] = location.to_json(),
+ dict["location"] = location.to_json();
dict["message"] = message;
return dict;
}
diff --git a/modules/gdscript/tests/gdscript_test_runner.cpp b/modules/gdscript/tests/gdscript_test_runner.cpp
index 15131afde7..f59983ca90 100644
--- a/modules/gdscript/tests/gdscript_test_runner.cpp
+++ b/modules/gdscript/tests/gdscript_test_runner.cpp
@@ -71,27 +71,38 @@ void init_autoloads() {
continue;
}
- Ref<Resource> res = ResourceLoader::load(info.path);
- ERR_CONTINUE_MSG(res.is_null(), "Can't autoload: " + info.path);
Node *n = nullptr;
- Ref<PackedScene> scn = res;
- Ref<Script> script = res;
- if (scn.is_valid()) {
- n = scn->instantiate();
- } else if (script.is_valid()) {
- StringName ibt = script->get_instance_base_type();
- bool valid_type = ClassDB::is_parent_class(ibt, "Node");
- ERR_CONTINUE_MSG(!valid_type, "Script does not inherit from Node: " + info.path);
+ if (ResourceLoader::get_resource_type(info.path) == "PackedScene") {
+ // Cache the scene reference before loading it (for cyclic references)
+ Ref<PackedScene> scn;
+ scn.instantiate();
+ scn->set_path(info.path);
+ scn->reload_from_file();
+ ERR_CONTINUE_MSG(!scn.is_valid(), vformat("Can't autoload: %s.", info.path));
+
+ if (scn.is_valid()) {
+ n = scn->instantiate();
+ }
+ } else {
+ Ref<Resource> res = ResourceLoader::load(info.path);
+ ERR_CONTINUE_MSG(res.is_null(), vformat("Can't autoload: %s.", info.path));
- Object *obj = ClassDB::instantiate(ibt);
+ Ref<Script> scr = res;
+ if (scr.is_valid()) {
+ StringName ibt = scr->get_instance_base_type();
+ bool valid_type = ClassDB::is_parent_class(ibt, "Node");
+ ERR_CONTINUE_MSG(!valid_type, vformat("Script does not inherit from Node: %s.", info.path));
- ERR_CONTINUE_MSG(!obj, "Cannot instance script for autoload, expected 'Node' inheritance, got: " + String(ibt) + ".");
+ Object *obj = ClassDB::instantiate(ibt);
- n = Object::cast_to<Node>(obj);
- n->set_script(script);
+ ERR_CONTINUE_MSG(!obj, vformat("Cannot instance script for Autoload, expected 'Node' inheritance, got: %s.", ibt));
+
+ n = Object::cast_to<Node>(obj);
+ n->set_script(scr);
+ }
}
- ERR_CONTINUE_MSG(!n, "Path in autoload not a node or script: " + info.path);
+ ERR_CONTINUE_MSG(!n, vformat("Path in autoload not a node or script: %s.", info.path));
n->set_name(info.name);
for (int i = 0; i < ScriptServer::get_language_count(); i++) {
@@ -251,7 +262,10 @@ bool GDScriptTestRunner::make_tests_for_dir(const String &p_dir) {
return false;
}
} else {
- if (next.get_extension().to_lower() == "gd") {
+ if (next.ends_with(".notest.gd")) {
+ next = dir->get_next();
+ continue;
+ } else if (next.get_extension().to_lower() == "gd") {
#ifndef DEBUG_ENABLED
// On release builds, skip tests marked as debug only.
Error open_err = OK;
@@ -461,7 +475,6 @@ GDScriptTest::TestResult GDScriptTest::execute_test_code(bool p_is_generating) {
Ref<GDScript> script;
script.instantiate();
script->set_path(source_file);
- script->set_script_path(source_file);
err = script->load_source_code(source_file);
if (err != OK) {
enable_stdout();
@@ -598,6 +611,9 @@ GDScriptTest::TestResult GDScriptTest::execute_test_code(bool p_is_generating) {
}
enable_stdout();
+
+ GDScriptCache::remove_script(script->get_path());
+
return result;
}
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/assign_signal.gd b/modules/gdscript/tests/scripts/analyzer/errors/assign_signal.gd
new file mode 100644
index 0000000000..0e1f7256f8
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/assign_signal.gd
@@ -0,0 +1,4 @@
+signal your_base
+signal my_base
+func test():
+ your_base = my_base
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/assign_signal.out b/modules/gdscript/tests/scripts/analyzer/errors/assign_signal.out
new file mode 100644
index 0000000000..5275183da2
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/assign_signal.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Cannot assign a new value to a constant.
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/class_name_shadows_builtin_type.out b/modules/gdscript/tests/scripts/analyzer/errors/class_name_shadows_builtin_type.out
index 87863baf75..b9a1d301ad 100644
--- a/modules/gdscript/tests/scripts/analyzer/errors/class_name_shadows_builtin_type.out
+++ b/modules/gdscript/tests/scripts/analyzer/errors/class_name_shadows_builtin_type.out
@@ -1,2 +1,2 @@
GDTEST_ANALYZER_ERROR
-The member "Vector2" cannot have the same name as a builtin type.
+Class "Vector2" hides a built-in type.
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/constructor_call_type.gd b/modules/gdscript/tests/scripts/analyzer/errors/constructor_call_type.gd
new file mode 100644
index 0000000000..251be70088
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/constructor_call_type.gd
@@ -0,0 +1,10 @@
+class A:
+ func _init():
+ pass
+
+class B extends A: pass
+class C extends A: pass
+
+func test():
+ var x := B.new()
+ print(x is C)
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/constructor_call_type.out b/modules/gdscript/tests/scripts/analyzer/errors/constructor_call_type.out
new file mode 100644
index 0000000000..91d5125ec0
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/constructor_call_type.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Expression is of type "B" so it can't be of type "C".
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/cyclic_inheritance.gd b/modules/gdscript/tests/scripts/analyzer/errors/cyclic_inheritance.gd
new file mode 100644
index 0000000000..d2f6404cd2
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/cyclic_inheritance.gd
@@ -0,0 +1,8 @@
+func test():
+ print(InnerA.new())
+
+class InnerA extends InnerB:
+ pass
+
+class InnerB extends InnerA:
+ pass
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/cyclic_inheritance.out b/modules/gdscript/tests/scripts/analyzer/errors/cyclic_inheritance.out
new file mode 100644
index 0000000000..75a94baa17
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/cyclic_inheritance.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Cyclic inheritance.
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/cyclic_ref_const.gd b/modules/gdscript/tests/scripts/analyzer/errors/cyclic_ref_const.gd
new file mode 100644
index 0000000000..4292534951
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/cyclic_ref_const.gd
@@ -0,0 +1,5 @@
+func test():
+ print(c1)
+
+const c1 = c2
+const c2 = c1
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/cyclic_ref_const.out b/modules/gdscript/tests/scripts/analyzer/errors/cyclic_ref_const.out
new file mode 100644
index 0000000000..e71b3fc56a
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/cyclic_ref_const.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Could not resolve member "c1": Cyclic reference.
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/cyclic_ref_enum.gd b/modules/gdscript/tests/scripts/analyzer/errors/cyclic_ref_enum.gd
new file mode 100644
index 0000000000..1caef3d366
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/cyclic_ref_enum.gd
@@ -0,0 +1,5 @@
+func test():
+ print(E1.V)
+
+enum E1 {V = E2.V}
+enum E2 {V = E1.V}
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/cyclic_ref_enum.out b/modules/gdscript/tests/scripts/analyzer/errors/cyclic_ref_enum.out
new file mode 100644
index 0000000000..1b6569ba3a
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/cyclic_ref_enum.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Could not resolve member "E1": Cyclic reference.
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/cyclic_ref_enum_value.gd b/modules/gdscript/tests/scripts/analyzer/errors/cyclic_ref_enum_value.gd
new file mode 100644
index 0000000000..237758f340
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/cyclic_ref_enum_value.gd
@@ -0,0 +1,5 @@
+func test():
+ print(EV1)
+
+enum {EV1 = EV2}
+enum {EV2 = EV1}
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/cyclic_ref_enum_value.out b/modules/gdscript/tests/scripts/analyzer/errors/cyclic_ref_enum_value.out
new file mode 100644
index 0000000000..233f5fee25
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/cyclic_ref_enum_value.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Could not resolve member "EV1": Cyclic reference.
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/cyclic_ref_external.gd b/modules/gdscript/tests/scripts/analyzer/errors/cyclic_ref_external.gd
new file mode 100644
index 0000000000..52e0d60389
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/cyclic_ref_external.gd
@@ -0,0 +1,6 @@
+func test():
+ print(v)
+
+var v = A.v
+
+const A = preload("cyclic_ref_external_a.notest.gd")
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/cyclic_ref_external.out b/modules/gdscript/tests/scripts/analyzer/errors/cyclic_ref_external.out
new file mode 100644
index 0000000000..64a6bd417d
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/cyclic_ref_external.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Could not resolve member "v".
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/cyclic_ref_external_a.notest.gd b/modules/gdscript/tests/scripts/analyzer/errors/cyclic_ref_external_a.notest.gd
new file mode 100644
index 0000000000..9ef1769250
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/cyclic_ref_external_a.notest.gd
@@ -0,0 +1,3 @@
+const B = preload("cyclic_ref_external.gd")
+
+var v = B.v
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/cyclic_ref_func.gd b/modules/gdscript/tests/scripts/analyzer/errors/cyclic_ref_func.gd
new file mode 100644
index 0000000000..b610464c44
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/cyclic_ref_func.gd
@@ -0,0 +1,9 @@
+func test():
+ print(f1())
+ print(f2())
+
+static func f1(p := f2()) -> int:
+ return 1
+
+static func f2(p := f1()) -> int:
+ return 2
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/cyclic_ref_func.out b/modules/gdscript/tests/scripts/analyzer/errors/cyclic_ref_func.out
new file mode 100644
index 0000000000..d3ec4b0692
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/cyclic_ref_func.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Could not resolve member "f1": Cyclic reference.
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/cyclic_ref_override.gd b/modules/gdscript/tests/scripts/analyzer/errors/cyclic_ref_override.gd
new file mode 100644
index 0000000000..f750715838
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/cyclic_ref_override.gd
@@ -0,0 +1,12 @@
+func test():
+ print(v)
+
+var v := InnerA.new().f()
+
+class InnerA:
+ func f(p := InnerB.new().f()) -> int:
+ return 1
+
+class InnerB extends InnerA:
+ func f(p := 1) -> int:
+ return super.f()
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/cyclic_ref_override.out b/modules/gdscript/tests/scripts/analyzer/errors/cyclic_ref_override.out
new file mode 100644
index 0000000000..6bca25b330
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/cyclic_ref_override.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Could not resolve member "f": Cyclic reference.
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/cyclic_ref_var.gd b/modules/gdscript/tests/scripts/analyzer/errors/cyclic_ref_var.gd
new file mode 100644
index 0000000000..6913888724
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/cyclic_ref_var.gd
@@ -0,0 +1,5 @@
+func test():
+ print(v1)
+
+var v1 := v2
+var v2 := v1
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/cyclic_ref_var.out b/modules/gdscript/tests/scripts/analyzer/errors/cyclic_ref_var.out
new file mode 100644
index 0000000000..c337882d9c
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/cyclic_ref_var.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Could not resolve member "v1": Cyclic reference.
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/dictionary_string_stringname_equivalent.gd b/modules/gdscript/tests/scripts/analyzer/errors/dictionary_string_stringname_equivalent.gd
new file mode 100644
index 0000000000..4dd2b556ee
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/dictionary_string_stringname_equivalent.gd
@@ -0,0 +1,9 @@
+# https://github.com/godotengine/godot/issues/62957
+
+func test():
+ var dict = {
+ &"key": "StringName",
+ "key": "String"
+ }
+
+ print("Invalid dictionary: %s" % dict)
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/dictionary_string_stringname_equivalent.out b/modules/gdscript/tests/scripts/analyzer/errors/dictionary_string_stringname_equivalent.out
new file mode 100644
index 0000000000..189d8a7955
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/dictionary_string_stringname_equivalent.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Key "key" was already used in this dictionary (at line 5).
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_parameter_count_less.out b/modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_parameter_count_less.out
index 3baeb17066..4ccd2da381 100644
--- a/modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_parameter_count_less.out
+++ b/modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_parameter_count_less.out
@@ -1,2 +1,2 @@
GDTEST_ANALYZER_ERROR
-The function signature doesn't match the parent. Parent signature is "int my_function(int)".
+The function signature doesn't match the parent. Parent signature is "my_function(int) -> int".
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_parameter_count_more.out b/modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_parameter_count_more.out
index 3baeb17066..4ccd2da381 100644
--- a/modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_parameter_count_more.out
+++ b/modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_parameter_count_more.out
@@ -1,2 +1,2 @@
GDTEST_ANALYZER_ERROR
-The function signature doesn't match the parent. Parent signature is "int my_function(int)".
+The function signature doesn't match the parent. Parent signature is "my_function(int) -> int".
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_parameter_default_values.out b/modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_parameter_default_values.out
index 665c229339..c70a1df10d 100644
--- a/modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_parameter_default_values.out
+++ b/modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_parameter_default_values.out
@@ -1,2 +1,2 @@
GDTEST_ANALYZER_ERROR
-The function signature doesn't match the parent. Parent signature is "int my_function(int = default)".
+The function signature doesn't match the parent. Parent signature is "my_function(int = default) -> int".
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_parameter_type.out b/modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_parameter_type.out
index 3baeb17066..4ccd2da381 100644
--- a/modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_parameter_type.out
+++ b/modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_parameter_type.out
@@ -1,2 +1,2 @@
GDTEST_ANALYZER_ERROR
-The function signature doesn't match the parent. Parent signature is "int my_function(int)".
+The function signature doesn't match the parent. Parent signature is "my_function(int) -> int".
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_return_type.out b/modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_return_type.out
index 5b22739a93..61004ff627 100644
--- a/modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_return_type.out
+++ b/modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_return_type.out
@@ -1,2 +1,2 @@
GDTEST_ANALYZER_ERROR
-The function signature doesn't match the parent. Parent signature is "int my_function()".
+The function signature doesn't match the parent. Parent signature is "my_function() -> int".
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/outer_class_lookup.gd b/modules/gdscript/tests/scripts/analyzer/errors/outer_class_lookup.gd
new file mode 100644
index 0000000000..65c0d9dabc
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/outer_class_lookup.gd
@@ -0,0 +1,12 @@
+class A:
+ class B:
+ func test():
+ print(A.B.D)
+
+class C:
+ class D:
+ pass
+
+func test():
+ var inst = A.B.new()
+ inst.test()
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/outer_class_lookup.out b/modules/gdscript/tests/scripts/analyzer/errors/outer_class_lookup.out
new file mode 100644
index 0000000000..6baed366f6
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/outer_class_lookup.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Cannot find member "D" in base "B".
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/overload_script_variable.gd b/modules/gdscript/tests/scripts/analyzer/errors/overload_script_variable.gd
new file mode 100644
index 0000000000..5c8b9fa4ae
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/overload_script_variable.gd
@@ -0,0 +1,6 @@
+extends Node
+
+var script: int
+
+func test():
+ pass
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/overload_script_variable.out b/modules/gdscript/tests/scripts/analyzer/errors/overload_script_variable.out
new file mode 100644
index 0000000000..8454aaa404
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/overload_script_variable.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Member "script" redefined (original in native class 'Node')
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/variable_overloads_superclass_function.gd b/modules/gdscript/tests/scripts/analyzer/errors/variable_overloads_superclass_function.gd
new file mode 100644
index 0000000000..28561ff94b
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/variable_overloads_superclass_function.gd
@@ -0,0 +1,9 @@
+func test():
+ pass
+
+class A:
+ func overload_me():
+ pass
+
+class B extends A:
+ var overload_me
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/variable_overloads_superclass_function.out b/modules/gdscript/tests/scripts/analyzer/errors/variable_overloads_superclass_function.out
new file mode 100644
index 0000000000..32357f9f6a
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/variable_overloads_superclass_function.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+The member "overload_me" already exists in parent class A.
diff --git a/modules/gdscript/tests/scripts/analyzer/features/array_string_stringname_equivalent.gd b/modules/gdscript/tests/scripts/analyzer/features/array_string_stringname_equivalent.gd
new file mode 100644
index 0000000000..eb0003eed8
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/array_string_stringname_equivalent.gd
@@ -0,0 +1,15 @@
+
+var m_string_array: Array[String] = [&"abc"]
+var m_stringname_array: Array[StringName] = ["abc"]
+
+func test():
+ print(m_string_array)
+ print(m_stringname_array)
+
+ # Converted to String when initialized
+ var string_array: Array[String] = [&"abc"]
+ print(string_array)
+
+ # Converted to StringName when initialized
+ var stringname_array: Array[StringName] = ["abc"]
+ print(stringname_array)
diff --git a/modules/gdscript/tests/scripts/analyzer/features/array_string_stringname_equivalent.out b/modules/gdscript/tests/scripts/analyzer/features/array_string_stringname_equivalent.out
new file mode 100644
index 0000000000..09c199bde1
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/array_string_stringname_equivalent.out
@@ -0,0 +1,5 @@
+GDTEST_OK
+["abc"]
+[&"abc"]
+["abc"]
+[&"abc"]
diff --git a/modules/gdscript/tests/scripts/analyzer/features/base_outer_resolution.gd b/modules/gdscript/tests/scripts/analyzer/features/base_outer_resolution.gd
new file mode 100644
index 0000000000..7881a0feb6
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/base_outer_resolution.gd
@@ -0,0 +1,14 @@
+const A: = preload("base_outer_resolution_a.notest.gd")
+const B: = preload("base_outer_resolution_b.notest.gd")
+const C: = preload("base_outer_resolution_c.notest.gd")
+
+const Extend: = preload("base_outer_resolution_extend.notest.gd")
+
+func test() -> void:
+ Extend.test_a(A.new())
+ Extend.test_b(B.new())
+ Extend.InnerClass.test_c(C.new())
+ Extend.InnerClass.InnerInnerClass.test_a_b_c(A.new(), B.new(), C.new())
+ Extend.InnerClass.InnerInnerClass.test_enum(C.TestEnum.HELLO_WORLD)
+ Extend.InnerClass.InnerInnerClass.test_a_prime(A.APrime.new())
+
diff --git a/modules/gdscript/tests/scripts/analyzer/features/base_outer_resolution.out b/modules/gdscript/tests/scripts/analyzer/features/base_outer_resolution.out
new file mode 100644
index 0000000000..bd27bd31f6
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/base_outer_resolution.out
@@ -0,0 +1,7 @@
+GDTEST_OK
+true
+true
+true
+true
+true
+true
diff --git a/modules/gdscript/tests/scripts/analyzer/features/base_outer_resolution_a.notest.gd b/modules/gdscript/tests/scripts/analyzer/features/base_outer_resolution_a.notest.gd
new file mode 100644
index 0000000000..966c8bfc8f
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/base_outer_resolution_a.notest.gd
@@ -0,0 +1,2 @@
+class APrime:
+ pass
diff --git a/modules/gdscript/tests/scripts/analyzer/features/base_outer_resolution_b.notest.gd b/modules/gdscript/tests/scripts/analyzer/features/base_outer_resolution_b.notest.gd
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/base_outer_resolution_b.notest.gd
diff --git a/modules/gdscript/tests/scripts/analyzer/features/base_outer_resolution_base.notest.gd b/modules/gdscript/tests/scripts/analyzer/features/base_outer_resolution_base.notest.gd
new file mode 100644
index 0000000000..666b147ced
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/base_outer_resolution_base.notest.gd
@@ -0,0 +1,4 @@
+const A: = preload("base_outer_resolution_a.notest.gd")
+
+class InnerClassInBase:
+ const C: = preload("base_outer_resolution_c.notest.gd")
diff --git a/modules/gdscript/tests/scripts/analyzer/features/base_outer_resolution_c.notest.gd b/modules/gdscript/tests/scripts/analyzer/features/base_outer_resolution_c.notest.gd
new file mode 100644
index 0000000000..814be35314
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/base_outer_resolution_c.notest.gd
@@ -0,0 +1,3 @@
+enum TestEnum {
+ HELLO_WORLD
+}
diff --git a/modules/gdscript/tests/scripts/analyzer/features/base_outer_resolution_extend.notest.gd b/modules/gdscript/tests/scripts/analyzer/features/base_outer_resolution_extend.notest.gd
new file mode 100644
index 0000000000..fbd28779d4
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/base_outer_resolution_extend.notest.gd
@@ -0,0 +1,23 @@
+extends "base_outer_resolution_base.notest.gd"
+
+const B: = preload("base_outer_resolution_b.notest.gd")
+
+static func test_a(a: A) -> void:
+ print(a is A)
+
+static func test_b(b: B) -> void:
+ print(b is B)
+
+class InnerClass extends InnerClassInBase:
+ static func test_c(c: C) -> void:
+ print(c is C)
+
+ class InnerInnerClass:
+ static func test_a_b_c(a: A, b: B, c: C) -> void:
+ print(a is A and b is B and c is C)
+
+ static func test_enum(test_enum: C.TestEnum) -> void:
+ print(test_enum == C.TestEnum.HELLO_WORLD)
+
+ static func test_a_prime(a_prime: A.APrime) -> void:
+ print(a_prime is A.APrime)
diff --git a/modules/gdscript/tests/scripts/analyzer/features/cast_non_null.gd b/modules/gdscript/tests/scripts/analyzer/features/cast_non_null.gd
new file mode 100644
index 0000000000..ba1b198cbf
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/cast_non_null.gd
@@ -0,0 +1,5 @@
+# https://github.com/godotengine/godot/issues/69504#issuecomment-1345725988
+
+func test():
+ print("cast to Variant == null: ", 1 as Variant == null)
+ print("cast to Object == null: ", self as Object == null)
diff --git a/modules/gdscript/tests/scripts/analyzer/features/cast_non_null.out b/modules/gdscript/tests/scripts/analyzer/features/cast_non_null.out
new file mode 100644
index 0000000000..541de99b8e
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/cast_non_null.out
@@ -0,0 +1,3 @@
+GDTEST_OK
+cast to Variant == null: false
+cast to Object == null: false
diff --git a/modules/gdscript/tests/scripts/analyzer/features/enum_as_const.gd b/modules/gdscript/tests/scripts/analyzer/features/enum_as_const.gd
new file mode 100644
index 0000000000..2ce588373b
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/enum_as_const.gd
@@ -0,0 +1,29 @@
+class Outer:
+ enum OuterEnum { OuterValue = 3 }
+ const OuterConst := OuterEnum
+
+ class Inner:
+ enum InnerEnum { InnerValue = 7 }
+ const InnerConst := InnerEnum
+
+ static func test() -> void:
+ print(OuterEnum.size());
+ print(OuterEnum.OuterValue);
+ print(OuterConst.size());
+ print(OuterConst.OuterValue);
+ print(Outer.OuterEnum.size());
+ print(Outer.OuterEnum.OuterValue);
+ print(Outer.OuterConst.size());
+ print(Outer.OuterConst.OuterValue);
+
+ print(InnerEnum.size());
+ print(InnerEnum.InnerValue);
+ print(InnerConst.size());
+ print(InnerConst.InnerValue);
+ print(Inner.InnerEnum.size());
+ print(Inner.InnerEnum.InnerValue);
+ print(Inner.InnerConst.size());
+ print(Inner.InnerConst.InnerValue);
+
+func test():
+ Outer.Inner.test()
diff --git a/modules/gdscript/tests/scripts/analyzer/features/enum_as_const.out b/modules/gdscript/tests/scripts/analyzer/features/enum_as_const.out
new file mode 100644
index 0000000000..e049f85b6e
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/enum_as_const.out
@@ -0,0 +1,17 @@
+GDTEST_OK
+1
+3
+1
+3
+1
+3
+1
+3
+1
+7
+1
+7
+1
+7
+1
+7
diff --git a/modules/gdscript/tests/scripts/analyzer/features/external_enum_as_constant.gd b/modules/gdscript/tests/scripts/analyzer/features/external_enum_as_constant.gd
new file mode 100644
index 0000000000..757744b6f1
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/external_enum_as_constant.gd
@@ -0,0 +1,6 @@
+const External = preload("external_enum_as_constant_external.notest.gd")
+const MyEnum = External.MyEnum
+
+func test():
+ print(MyEnum.WAITING == 0)
+ print(MyEnum.GODOT == 1)
diff --git a/modules/gdscript/tests/scripts/analyzer/features/external_enum_as_constant.out b/modules/gdscript/tests/scripts/analyzer/features/external_enum_as_constant.out
new file mode 100644
index 0000000000..9d111a8322
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/external_enum_as_constant.out
@@ -0,0 +1,3 @@
+GDTEST_OK
+true
+true
diff --git a/modules/gdscript/tests/scripts/analyzer/features/external_enum_as_constant_external.notest.gd b/modules/gdscript/tests/scripts/analyzer/features/external_enum_as_constant_external.notest.gd
new file mode 100644
index 0000000000..7c090844d0
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/external_enum_as_constant_external.notest.gd
@@ -0,0 +1,4 @@
+enum MyEnum {
+ WAITING,
+ GODOT
+}
diff --git a/modules/gdscript/tests/scripts/analyzer/features/external_inner_base.gd b/modules/gdscript/tests/scripts/analyzer/features/external_inner_base.gd
new file mode 100644
index 0000000000..3f9bfe189c
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/external_inner_base.gd
@@ -0,0 +1,4 @@
+extends "inner_base.gd".InnerA.InnerAB
+
+func test():
+ super.test()
diff --git a/modules/gdscript/tests/scripts/analyzer/features/external_inner_base.out b/modules/gdscript/tests/scripts/analyzer/features/external_inner_base.out
new file mode 100644
index 0000000000..62f1383392
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/external_inner_base.out
@@ -0,0 +1,3 @@
+GDTEST_OK
+InnerA.InnerAB.test
+InnerB.test
diff --git a/modules/gdscript/tests/scripts/analyzer/features/external_inner_class_as_constant.gd b/modules/gdscript/tests/scripts/analyzer/features/external_inner_class_as_constant.gd
new file mode 100644
index 0000000000..18dca109fb
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/external_inner_class_as_constant.gd
@@ -0,0 +1,7 @@
+const External = preload("external_inner_class_as_constant_external.notest.gd")
+const ExternalInnerClass = External.InnerClass
+
+func test():
+ var inst_external: ExternalInnerClass = ExternalInnerClass.new()
+ inst_external.x = 4.0
+ print(inst_external.x)
diff --git a/modules/gdscript/tests/scripts/analyzer/features/gdscript_to_preload.out b/modules/gdscript/tests/scripts/analyzer/features/external_inner_class_as_constant.out
index d73c5eb7cd..15666c46ad 100644
--- a/modules/gdscript/tests/scripts/analyzer/features/gdscript_to_preload.out
+++ b/modules/gdscript/tests/scripts/analyzer/features/external_inner_class_as_constant.out
@@ -1 +1,2 @@
GDTEST_OK
+4
diff --git a/modules/gdscript/tests/scripts/analyzer/features/external_inner_class_as_constant_external.notest.gd b/modules/gdscript/tests/scripts/analyzer/features/external_inner_class_as_constant_external.notest.gd
new file mode 100644
index 0000000000..788c99d469
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/external_inner_class_as_constant_external.notest.gd
@@ -0,0 +1,2 @@
+class InnerClass:
+ var x: = 3.0
diff --git a/modules/gdscript/tests/scripts/analyzer/features/gdscript_to_preload.gd b/modules/gdscript/tests/scripts/analyzer/features/gdscript_to_preload.notest.gd
index ea744e3027..c3fc176679 100644
--- a/modules/gdscript/tests/scripts/analyzer/features/gdscript_to_preload.gd
+++ b/modules/gdscript/tests/scripts/analyzer/features/gdscript_to_preload.notest.gd
@@ -1,7 +1,4 @@
const A := 42
-func test():
- pass
-
func something():
return "OK"
diff --git a/modules/gdscript/tests/scripts/analyzer/features/inferred_return_type.gd b/modules/gdscript/tests/scripts/analyzer/features/inferred_return_type.gd
new file mode 100644
index 0000000000..39ced354df
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/inferred_return_type.gd
@@ -0,0 +1,9 @@
+# https://github.com/godotengine/godot/issues/61159
+
+func get_param():
+ return null
+
+func test():
+ var v = get_param()
+ v = get_param()
+ print(v)
diff --git a/modules/gdscript/tests/scripts/analyzer/features/inferred_return_type.out b/modules/gdscript/tests/scripts/analyzer/features/inferred_return_type.out
new file mode 100644
index 0000000000..f0c83a69b3
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/inferred_return_type.out
@@ -0,0 +1,2 @@
+GDTEST_OK
+<null>
diff --git a/modules/gdscript/tests/scripts/analyzer/features/inner_base.gd b/modules/gdscript/tests/scripts/analyzer/features/inner_base.gd
new file mode 100644
index 0000000000..a825b59255
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/inner_base.gd
@@ -0,0 +1,18 @@
+extends InnerA
+
+func test():
+ super.test()
+
+class InnerA extends InnerAB:
+ func test():
+ print("InnerA.test")
+ super.test()
+
+ class InnerAB extends InnerB:
+ func test():
+ print("InnerA.InnerAB.test")
+ super.test()
+
+class InnerB:
+ func test():
+ print("InnerB.test")
diff --git a/modules/gdscript/tests/scripts/analyzer/features/inner_base.out b/modules/gdscript/tests/scripts/analyzer/features/inner_base.out
new file mode 100644
index 0000000000..ddd5ffcfd3
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/inner_base.out
@@ -0,0 +1,4 @@
+GDTEST_OK
+InnerA.test
+InnerA.InnerAB.test
+InnerB.test
diff --git a/modules/gdscript/tests/scripts/analyzer/features/out_of_order.gd b/modules/gdscript/tests/scripts/analyzer/features/out_of_order.gd
new file mode 100644
index 0000000000..11349cc916
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/out_of_order.gd
@@ -0,0 +1,51 @@
+func test():
+ print("v1: ", v1)
+ print("v1 is String: ", v1 is String)
+ print("v2: ", v2)
+ print("v2 is bool: ", v2 is bool)
+ print("c1: ", c1)
+ print("c1 is int: ", c1 is int)
+ print("c2: ", c2)
+ print("c2 is int: ", c2 is int)
+ print("E1.V1: ", E1.V1)
+ print("E1.V2: ", E1.V2)
+ print("E2.V: ", E2.V)
+ print("EV1: ", EV1)
+ print("EV2: ", EV2)
+ print("EV3: ", EV3)
+
+var v1 := InnerA.new().fn()
+
+class InnerA extends InnerAB:
+ func fn(p2 := E1.V2) -> String:
+ return "%s, p2=%s" % [super.fn(), p2]
+
+ class InnerAB:
+ func fn(p1 := c1) -> String:
+ return "p1=%s" % p1
+
+var v2 := f()
+
+func f() -> bool:
+ return true
+
+const c1 := E1.V1
+
+enum E1 {
+ V1 = E2.V + 2,
+ V2 = V1 - 1
+}
+
+enum E2 {V = 2}
+
+const c2 := EV2
+
+enum {
+ EV1 = 42,
+ UNUSED = EV3,
+ EV2
+}
+
+enum {
+ EV3 = EV1 + 1
+}
diff --git a/modules/gdscript/tests/scripts/analyzer/features/out_of_order.out b/modules/gdscript/tests/scripts/analyzer/features/out_of_order.out
new file mode 100644
index 0000000000..b1e75d611d
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/out_of_order.out
@@ -0,0 +1,15 @@
+GDTEST_OK
+v1: p1=4, p2=3
+v1 is String: true
+v2: true
+v2 is bool: true
+c1: 4
+c1 is int: true
+c2: 44
+c2 is int: true
+E1.V1: 4
+E1.V2: 3
+E2.V: 2
+EV1: 42
+EV2: 44
+EV3: 43
diff --git a/modules/gdscript/tests/scripts/analyzer/features/out_of_order_external.gd b/modules/gdscript/tests/scripts/analyzer/features/out_of_order_external.gd
new file mode 100644
index 0000000000..0b162bdff8
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/out_of_order_external.gd
@@ -0,0 +1,39 @@
+const B = preload("out_of_order_external_a.notest.gd")
+
+func test():
+ print("v1: ", v1)
+ print("v1 is String: ", v1 is String)
+ print("v2: ", v2)
+ print("v2 is bool: ", v2 is bool)
+ print("c1: ", c1)
+ print("c1 is int: ", c1 is int)
+ print("c2: ", c2)
+ print("c2 is int: ", c2 is int)
+ print("E1.V1: ", E1.V1)
+ print("E1.V2: ", E1.V2)
+ print("B.E2.V: ", B.E2.V)
+ print("EV1: ", EV1)
+ print("EV2: ", EV2)
+ print("B.EV3: ", B.EV3)
+
+var v1 := Inner.new().fn()
+
+class Inner extends B.Inner:
+ func fn(p2 := E1.V2) -> String:
+ return "%s, p2=%s" % [super.fn(), p2]
+
+var v2 := B.new().f()
+
+const c1 := E1.V1
+
+enum E1 {
+ V1 = B.E2.V + 2,
+ V2 = V1 - 1
+}
+
+const c2 := EV2
+
+enum {
+ EV1 = 42,
+ EV2 = B.EV3 + 1
+}
diff --git a/modules/gdscript/tests/scripts/analyzer/features/out_of_order_external.out b/modules/gdscript/tests/scripts/analyzer/features/out_of_order_external.out
new file mode 100644
index 0000000000..437f782fe6
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/out_of_order_external.out
@@ -0,0 +1,15 @@
+GDTEST_OK
+v1: p1=4, p2=3
+v1 is String: true
+v2: true
+v2 is bool: true
+c1: 4
+c1 is int: true
+c2: 44
+c2 is int: true
+E1.V1: 4
+E1.V2: 3
+B.E2.V: 2
+EV1: 42
+EV2: 44
+B.EV3: 43
diff --git a/modules/gdscript/tests/scripts/analyzer/features/out_of_order_external_a.notest.gd b/modules/gdscript/tests/scripts/analyzer/features/out_of_order_external_a.notest.gd
new file mode 100644
index 0000000000..d276f72fcf
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/out_of_order_external_a.notest.gd
@@ -0,0 +1,12 @@
+const A = preload("out_of_order_external.gd")
+
+class Inner:
+ func fn(p1 := A.c1) -> String:
+ return "p1=%s" % p1
+
+func f(p := A.c1) -> bool:
+ return p is int
+
+enum E2 {V = 2}
+
+enum {EV3 = A.EV1 + 1}
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
index 276875dd5a..9d0324ead8 100644
--- 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
@@ -1,4 +1,4 @@
-const Constants = preload("gdscript_to_preload.gd")
+const Constants = preload("gdscript_to_preload.notest.gd")
func test():
var a := Constants.A
diff --git a/modules/gdscript/tests/scripts/analyzer/features/preload_cyclic_reference.gd b/modules/gdscript/tests/scripts/analyzer/features/preload_cyclic_reference.gd
new file mode 100644
index 0000000000..b730453a8a
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/preload_cyclic_reference.gd
@@ -0,0 +1,4 @@
+const A = preload("preload_cyclic_reference_a.notest.gd")
+
+func test():
+ A.test_cyclic_reference()
diff --git a/modules/gdscript/tests/scripts/analyzer/features/preload_cyclic_reference.out b/modules/gdscript/tests/scripts/analyzer/features/preload_cyclic_reference.out
new file mode 100644
index 0000000000..14bb971221
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/preload_cyclic_reference.out
@@ -0,0 +1,2 @@
+GDTEST_OK
+godot
diff --git a/modules/gdscript/tests/scripts/analyzer/features/preload_cyclic_reference_a.notest.gd b/modules/gdscript/tests/scripts/analyzer/features/preload_cyclic_reference_a.notest.gd
new file mode 100644
index 0000000000..7a6035ded1
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/preload_cyclic_reference_a.notest.gd
@@ -0,0 +1,12 @@
+const B = preload("preload_cyclic_reference_b.notest.gd")
+
+const WAITING_FOR = "godot"
+
+static func test_cyclic_reference():
+ B.test_cyclic_reference()
+
+static func test_cyclic_reference_2():
+ B.test_cyclic_reference_2()
+
+static func test_cyclic_reference_3():
+ B.test_cyclic_reference_3()
diff --git a/modules/gdscript/tests/scripts/analyzer/features/preload_cyclic_reference_b.notest.gd b/modules/gdscript/tests/scripts/analyzer/features/preload_cyclic_reference_b.notest.gd
new file mode 100644
index 0000000000..3ea5b01156
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/preload_cyclic_reference_b.notest.gd
@@ -0,0 +1,10 @@
+const A = preload("preload_cyclic_reference_a.notest.gd")
+
+static func test_cyclic_reference():
+ A.test_cyclic_reference_2()
+
+static func test_cyclic_reference_2():
+ A.test_cyclic_reference_3()
+
+static func test_cyclic_reference_3():
+ print(A.WAITING_FOR)
diff --git a/modules/gdscript/tests/scripts/analyzer/features/use_preload_script_as_type.gd b/modules/gdscript/tests/scripts/analyzer/features/use_preload_script_as_type.gd
index 5f73064cc0..beabf3d2e5 100644
--- a/modules/gdscript/tests/scripts/analyzer/features/use_preload_script_as_type.gd
+++ b/modules/gdscript/tests/scripts/analyzer/features/use_preload_script_as_type.gd
@@ -1,4 +1,4 @@
-const preloaded : GDScript = preload("gdscript_to_preload.gd")
+const preloaded : GDScript = preload("gdscript_to_preload.notest.gd")
func test():
var preloaded_instance: preloaded = preloaded.new()
diff --git a/modules/gdscript/tests/scripts/parser/warnings/return_value_discarded.out b/modules/gdscript/tests/scripts/parser/warnings/return_value_discarded.out
index 13f759dd46..e89bb9226f 100644
--- a/modules/gdscript/tests/scripts/parser/warnings/return_value_discarded.out
+++ b/modules/gdscript/tests/scripts/parser/warnings/return_value_discarded.out
@@ -2,4 +2,4 @@ GDTEST_OK
>> WARNING
>> Line: 6
>> RETURN_VALUE_DISCARDED
->> The function 'i_return_int()' returns a value, but this value is never used.
+>> The function 'i_return_int()' returns a value that will be discarded if not used.
diff --git a/modules/gdscript/tests/scripts/runtime/features/array_string_stringname_equivalent.gd b/modules/gdscript/tests/scripts/runtime/features/array_string_stringname_equivalent.gd
new file mode 100644
index 0000000000..5303fb04e2
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/features/array_string_stringname_equivalent.gd
@@ -0,0 +1,35 @@
+# https://github.com/godotengine/godot/issues/63965
+
+func test():
+ var array_str: Array = []
+ array_str.push_back("godot")
+ print("StringName in Array: ", &"godot" in array_str)
+
+ var array_sname: Array = []
+ array_sname.push_back(&"godot")
+ print("String in Array: ", "godot" in array_sname)
+
+ # Not equal because the values are different types.
+ print("Arrays not equal: ", array_str != array_sname)
+
+ var string_array: Array[String] = []
+ var stringname_array: Array[StringName] = []
+
+ assert(!string_array.push_back(&"abc"))
+ print("Array[String] insert converted: ", typeof(string_array[0]) == TYPE_STRING)
+
+ assert(!stringname_array.push_back("abc"))
+ print("Array[StringName] insert converted: ", typeof(stringname_array[0]) == TYPE_STRING_NAME)
+
+ print("StringName in Array[String]: ", &"abc" in string_array)
+ print("String in Array[StringName]: ", "abc" in stringname_array)
+
+ var packed_string_array: PackedStringArray = []
+ assert(!packed_string_array.push_back("abc"))
+ print("StringName in PackedStringArray: ", &"abc" in packed_string_array)
+
+ assert(!string_array.push_back("abc"))
+ print("StringName finds String in Array: ", string_array.find(&"abc"))
+
+ assert(!stringname_array.push_back(&"abc"))
+ print("String finds StringName in Array: ", stringname_array.find("abc"))
diff --git a/modules/gdscript/tests/scripts/runtime/features/array_string_stringname_equivalent.out b/modules/gdscript/tests/scripts/runtime/features/array_string_stringname_equivalent.out
new file mode 100644
index 0000000000..98ab78e8f1
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/features/array_string_stringname_equivalent.out
@@ -0,0 +1,11 @@
+GDTEST_OK
+StringName in Array: true
+String in Array: true
+Arrays not equal: true
+Array[String] insert converted: true
+Array[StringName] insert converted: true
+StringName in Array[String]: true
+String in Array[StringName]: true
+StringName in PackedStringArray: true
+StringName finds String in Array: 0
+String finds StringName in Array: 0
diff --git a/modules/gdscript/tests/scripts/runtime/features/dictionary_string_stringname_equivalent.gd b/modules/gdscript/tests/scripts/runtime/features/dictionary_string_stringname_equivalent.gd
new file mode 100644
index 0000000000..1f15026f17
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/features/dictionary_string_stringname_equivalent.gd
@@ -0,0 +1,17 @@
+# https://github.com/godotengine/godot/issues/62957
+
+func test():
+ var string_dict = {}
+ string_dict["abc"] = 42
+ var stringname_dict = {}
+ stringname_dict[&"abc"] = 24
+
+ print("String key is TYPE_STRING: ", typeof(string_dict.keys()[0]) == TYPE_STRING)
+ print("StringName key is TYPE_STRING: ", typeof(stringname_dict.keys()[0]) == TYPE_STRING)
+
+ print("StringName gets String: ", string_dict.get(&"abc"))
+ print("String gets StringName: ", stringname_dict.get("abc"))
+
+ stringname_dict[&"abc"] = 42
+ # They compare equal because StringName keys are converted to String.
+ print("String Dictionary == StringName Dictionary: ", string_dict == stringname_dict)
diff --git a/modules/gdscript/tests/scripts/runtime/features/dictionary_string_stringname_equivalent.out b/modules/gdscript/tests/scripts/runtime/features/dictionary_string_stringname_equivalent.out
new file mode 100644
index 0000000000..ab5b89d55c
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/features/dictionary_string_stringname_equivalent.out
@@ -0,0 +1,6 @@
+GDTEST_OK
+String key is TYPE_STRING: true
+StringName key is TYPE_STRING: true
+StringName gets String: 42
+String gets StringName: 24
+String Dictionary == StringName Dictionary: true
diff --git a/modules/gdscript/tests/scripts/runtime/features/match_string_stringname_equivalent.gd b/modules/gdscript/tests/scripts/runtime/features/match_string_stringname_equivalent.gd
new file mode 100644
index 0000000000..55be021a90
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/features/match_string_stringname_equivalent.gd
@@ -0,0 +1,14 @@
+# https://github.com/godotengine/godot/issues/60145
+
+func test():
+ match "abc":
+ &"abc":
+ print("String matched StringName")
+ _:
+ print("no match")
+
+ match &"abc":
+ "abc":
+ print("StringName matched String")
+ _:
+ print("no match")
diff --git a/modules/gdscript/tests/scripts/runtime/features/match_string_stringname_equivalent.out b/modules/gdscript/tests/scripts/runtime/features/match_string_stringname_equivalent.out
new file mode 100644
index 0000000000..9d5a18da3d
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/features/match_string_stringname_equivalent.out
@@ -0,0 +1,3 @@
+GDTEST_OK
+String matched StringName
+StringName matched String
diff --git a/modules/gdscript/tests/scripts/runtime/features/parameter_shadowing.gd b/modules/gdscript/tests/scripts/runtime/features/parameter_shadowing.gd
new file mode 100644
index 0000000000..f33ba7dffd
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/features/parameter_shadowing.gd
@@ -0,0 +1,25 @@
+# https://github.com/godotengine/godot/pull/69620
+
+var a: int = 1
+
+func shadow_regular_assignment(a: Variant, b: Variant) -> void:
+ print(a)
+ print(self.a)
+ a = b
+ print(a)
+ print(self.a)
+
+
+var v := Vector2(0.0, 0.0)
+
+func shadow_subscript_assignment(v: Vector2, x: float) -> void:
+ print(v)
+ print(self.v)
+ v.x += x
+ print(v)
+ print(self.v)
+
+
+func test():
+ shadow_regular_assignment('a', 'b')
+ shadow_subscript_assignment(Vector2(1.0, 1.0), 5.0)
diff --git a/modules/gdscript/tests/scripts/runtime/features/parameter_shadowing.out b/modules/gdscript/tests/scripts/runtime/features/parameter_shadowing.out
new file mode 100644
index 0000000000..5b981bc8bb
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/features/parameter_shadowing.out
@@ -0,0 +1,17 @@
+GDTEST_OK
+>> WARNING
+>> Line: 5
+>> SHADOWED_VARIABLE
+>> The local function parameter "a" is shadowing an already-declared variable at line 3.
+>> WARNING
+>> Line: 15
+>> SHADOWED_VARIABLE
+>> The local function parameter "v" is shadowing an already-declared variable at line 13.
+a
+1
+b
+1
+(1, 1)
+(0, 0)
+(6, 1)
+(0, 0)
diff --git a/modules/gdscript/tests/scripts/runtime/features/string_stringname_equivalent.gd b/modules/gdscript/tests/scripts/runtime/features/string_stringname_equivalent.gd
new file mode 100644
index 0000000000..f8bd46523e
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/features/string_stringname_equivalent.gd
@@ -0,0 +1,11 @@
+# https://github.com/godotengine/godot/issues/64171
+
+func test():
+ print("Compare ==: ", "abc" == &"abc")
+ print("Compare ==: ", &"abc" == "abc")
+ print("Compare !=: ", "abc" != &"abc")
+ print("Compare !=: ", &"abc" != "abc")
+
+ print("Concat: ", "abc" + &"def")
+ print("Concat: ", &"abc" + "def")
+ print("Concat: ", &"abc" + &"def")
diff --git a/modules/gdscript/tests/scripts/runtime/features/string_stringname_equivalent.out b/modules/gdscript/tests/scripts/runtime/features/string_stringname_equivalent.out
new file mode 100644
index 0000000000..7e9c364b60
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/features/string_stringname_equivalent.out
@@ -0,0 +1,8 @@
+GDTEST_OK
+Compare ==: true
+Compare ==: true
+Compare !=: false
+Compare !=: false
+Concat: abcdef
+Concat: abcdef
+Concat: abcdef
diff --git a/modules/gdscript/tests/scripts/runtime/features/typed_assignment.gd b/modules/gdscript/tests/scripts/runtime/features/typed_assignment.gd
new file mode 100644
index 0000000000..22e54cf91c
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/features/typed_assignment.gd
@@ -0,0 +1,9 @@
+func test():
+ var x: int = 2
+ var y = 3.14
+ var z := 2.72
+ print(typeof(x))
+ x = y
+ print(typeof(x))
+ x = z
+ print(typeof(x))
diff --git a/modules/gdscript/tests/scripts/runtime/features/typed_assignment.out b/modules/gdscript/tests/scripts/runtime/features/typed_assignment.out
new file mode 100644
index 0000000000..4a268dd8e0
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/features/typed_assignment.out
@@ -0,0 +1,12 @@
+GDTEST_OK
+>> WARNING
+>> Line: 6
+>> NARROWING_CONVERSION
+>> Narrowing conversion (float is converted to int and loses precision).
+>> WARNING
+>> Line: 8
+>> NARROWING_CONVERSION
+>> Narrowing conversion (float is converted to int and loses precision).
+2
+2
+2
diff --git a/modules/gltf/doc_classes/GLTFDocument.xml b/modules/gltf/doc_classes/GLTFDocument.xml
index 3cd0f5c0f9..f313f4b28f 100644
--- a/modules/gltf/doc_classes/GLTFDocument.xml
+++ b/modules/gltf/doc_classes/GLTFDocument.xml
@@ -14,8 +14,9 @@
<param index="1" name="base_path" type="String" />
<param index="2" name="state" type="GLTFState" />
<param index="3" name="flags" type="int" default="0" />
- <param index="4" name="bake_fps" type="int" default="30" />
<description>
+ Takes a [PackedByteArray] defining a gLTF and returns a [GLTFState] object through the [param state] parameter.
+ [b]Note:[/b] The [param base_path] tells [method append_from_buffer] where to find dependencies and can be empty.
</description>
</method>
<method name="append_from_file">
@@ -23,9 +24,10 @@
<param index="0" name="path" type="String" />
<param index="1" name="state" type="GLTFState" />
<param index="2" name="flags" type="int" default="0" />
- <param index="3" name="bake_fps" type="int" default="30" />
- <param index="4" name="base_path" type="String" default="&quot;&quot;" />
+ <param index="3" name="base_path" type="String" default="&quot;&quot;" />
<description>
+ Takes a path to a gLTF file and returns a [GLTFState] object through the [param state] parameter.
+ [b]Note:[/b] The [param base_path] tells [method append_from_file] where to find dependencies and can be empty.
</description>
</method>
<method name="append_from_scene">
@@ -33,21 +35,40 @@
<param index="0" name="node" type="Node" />
<param index="1" name="state" type="GLTFState" />
<param index="2" name="flags" type="int" default="0" />
- <param index="3" name="bake_fps" type="int" default="30" />
<description>
+ Takes a Godot Engine scene node and returns a [GLTFState] object through the [param state] parameter.
</description>
</method>
<method name="generate_buffer">
<return type="PackedByteArray" />
<param index="0" name="state" type="GLTFState" />
<description>
+ Takes a [GLTFState] object through the [param state] parameter and returns a gLTF [PackedByteArray].
</description>
</method>
<method name="generate_scene">
<return type="Node" />
<param index="0" name="state" type="GLTFState" />
- <param index="1" name="bake_fps" type="int" default="30" />
+ <param index="1" name="bake_fps" type="float" default="30" />
+ <param index="2" name="trimming" type="bool" default="false" />
<description>
+ Takes a [GLTFState] object through the [param state] parameter and returns a Godot Engine scene node.
+ </description>
+ </method>
+ <method name="register_gltf_document_extension" qualifiers="static">
+ <return type="void" />
+ <param index="0" name="extension" type="GLTFDocumentExtension" />
+ <param index="1" name="first_priority" type="bool" default="false" />
+ <description>
+ Registers the given [GLTFDocumentExtension] instance with GLTFDocument. If [param first_priority] is true, this extension will be run first. Otherwise, it will be run last.
+ [b]Note:[/b] Like GLTFDocument itself, all GLTFDocumentExtension classes must be stateless in order to function properly. If you need to store data, use the [code]set_additional_data[/code] and [code]get_additional_data[/code] methods in [GLTFState] or [GLTFNode].
+ </description>
+ </method>
+ <method name="unregister_gltf_document_extension" qualifiers="static">
+ <return type="void" />
+ <param index="0" name="extension" type="GLTFDocumentExtension" />
+ <description>
+ Unregisters the given [GLTFDocumentExtension] instance.
</description>
</method>
<method name="write_to_filesystem">
@@ -55,11 +76,9 @@
<param index="0" name="state" type="GLTFState" />
<param index="1" name="path" type="String" />
<description>
+ Takes a [GLTFState] object through the [param state] parameter and writes a glTF file to the filesystem.
+ [b]Note:[/b] The extension of the glTF file determines if it is a .glb binary file or a .gltf file.
</description>
</method>
</methods>
- <members>
- <member name="extensions" type="GLTFDocumentExtension[]" setter="set_extensions" getter="get_extensions" default="[]">
- </member>
- </members>
</class>
diff --git a/modules/gltf/doc_classes/GLTFDocumentExtension.xml b/modules/gltf/doc_classes/GLTFDocumentExtension.xml
index 936794976d..6004de32f1 100644
--- a/modules/gltf/doc_classes/GLTFDocumentExtension.xml
+++ b/modules/gltf/doc_classes/GLTFDocumentExtension.xml
@@ -5,10 +5,22 @@
</brief_description>
<description>
Extends the functionality of the [GLTFDocument] class by allowing you to run arbitrary code at various stages of GLTF import or export.
+ To use, make a new class extending GLTFDocumentExtension, override any methods you need, make an instance of your class, and register it using [method GLTFDocument.register_gltf_document_extension].
+ [b]Note:[/b] Like GLTFDocument itself, all GLTFDocumentExtension classes must be stateless in order to function properly. If you need to store data, use the [code]set_additional_data[/code] and [code]get_additional_data[/code] methods in [GLTFState] or [GLTFNode].
</description>
<tutorials>
</tutorials>
<methods>
+ <method name="_convert_scene_node" qualifiers="virtual">
+ <return type="void" />
+ <param index="0" name="state" type="GLTFState" />
+ <param index="1" name="gltf_node" type="GLTFNode" />
+ <param index="2" name="scene_node" type="Node" />
+ <description>
+ Part of the export process. This method is run after [method _export_preflight] and before [method _export_node].
+ Runs when converting the data from a Godot scene node. This method can be used to process the Godot scene node data into a format that can be used by [method _export_node].
+ </description>
+ </method>
<method name="_export_node" qualifiers="virtual">
<return type="int" />
<param index="0" name="state" type="GLTFState" />
@@ -16,23 +28,41 @@
<param index="2" name="json" type="Dictionary" />
<param index="3" name="node" type="Node" />
<description>
+ Part of the export process. This method is run after [method _convert_scene_node] and before [method _export_post].
+ This method can be used to modify the final JSON of each node.
</description>
</method>
<method name="_export_post" qualifiers="virtual">
<return type="int" />
<param index="0" name="state" type="GLTFState" />
<description>
+ Part of the export process. This method is run last, after all other parts of the export process.
+ This method can be used to modify the final JSON of the generated GLTF file.
</description>
</method>
<method name="_export_preflight" qualifiers="virtual">
<return type="int" />
- <param index="0" name="root" type="Node" />
+ <param index="0" name="state" type="GLTFState" />
+ <param index="1" name="root" type="Node" />
+ <description>
+ Part of the export process. This method is run first, before all other parts of the export process.
+ The return value is used to determine if this [GLTFDocumentExtension] instance should be used for exporting a given GLTF file. If [constant OK], the export will use this [GLTFDocumentExtension] instance. If not overridden, [constant OK] is returned.
+ </description>
+ </method>
+ <method name="_generate_scene_node" qualifiers="virtual">
+ <return type="Node3D" />
+ <param index="0" name="state" type="GLTFState" />
+ <param index="1" name="gltf_node" type="GLTFNode" />
+ <param index="2" name="scene_parent" type="Node" />
<description>
+ Part of the import process. This method is run after [method _parse_node_extensions] and before [method _import_post_parse].
+ Runs when generating a Godot scene node from a GLTFNode. The returned node will be added to the scene tree. Multiple nodes can be generated in this step if they are added as a child of the returned node.
</description>
</method>
<method name="_get_supported_extensions" qualifiers="virtual">
<return type="PackedStringArray" />
<description>
+ Part of the import process. This method is run after [method _import_preflight] and before [method _parse_node_extensions].
Returns an array of the GLTF extensions supported by this GLTFDocumentExtension class. This is used to validate if a GLTF file with required extensions can be loaded.
</description>
</method>
@@ -43,6 +73,8 @@
<param index="2" name="json" type="Dictionary" />
<param index="3" name="node" type="Node" />
<description>
+ Part of the import process. This method is run after [method _import_post_parse] and before [method _import_post].
+ This method can be used to make modifications to each of the generated Godot scene nodes.
</description>
</method>
<method name="_import_post" qualifiers="virtual">
@@ -50,18 +82,35 @@
<param index="0" name="state" type="GLTFState" />
<param index="1" name="root" type="Node" />
<description>
+ Part of the import process. This method is run last, after all other parts of the import process.
+ This method can be used to modify the final Godot scene generated by the import process.
</description>
</method>
<method name="_import_post_parse" qualifiers="virtual">
<return type="int" />
<param index="0" name="state" type="GLTFState" />
<description>
+ Part of the import process. This method is run after [method _generate_scene_node] and before [method _import_node].
+ This method can be used to modify any of the data imported so far, including any scene nodes, before running the final per-node import step.
</description>
</method>
<method name="_import_preflight" qualifiers="virtual">
<return type="int" />
<param index="0" name="state" type="GLTFState" />
+ <param index="1" name="extensions" type="PackedStringArray" />
+ <description>
+ Part of the import process. This method is run first, before all other parts of the import process.
+ The return value is used to determine if this [GLTFDocumentExtension] instance should be used for importing a given GLTF file. If [constant OK], the import will use this [GLTFDocumentExtension] instance. If not overridden, [constant OK] is returned.
+ </description>
+ </method>
+ <method name="_parse_node_extensions" qualifiers="virtual">
+ <return type="int" />
+ <param index="0" name="state" type="GLTFState" />
+ <param index="1" name="gltf_node" type="GLTFNode" />
+ <param index="2" name="extensions" type="Dictionary" />
<description>
+ Part of the import process. This method is run after [method _get_supported_extensions] and before [method _generate_scene_node].
+ Runs when parsing the node extensions of a GLTFNode. This method can be used to process the extension JSON data into a format that can be used by [method _generate_scene_node]. The return value should be a member of the [enum Error] enum.
</description>
</method>
</methods>
diff --git a/modules/gltf/doc_classes/GLTFState.xml b/modules/gltf/doc_classes/GLTFState.xml
index d0740cf7ca..9a554a0d49 100644
--- a/modules/gltf/doc_classes/GLTFState.xml
+++ b/modules/gltf/doc_classes/GLTFState.xml
@@ -66,7 +66,7 @@
</description>
</method>
<method name="get_materials">
- <return type="BaseMaterial3D[]" />
+ <return type="Material[]" />
<description>
</description>
</method>
@@ -169,7 +169,7 @@
</method>
<method name="set_materials">
<return type="void" />
- <param index="0" name="materials" type="BaseMaterial3D[]" />
+ <param index="0" name="materials" type="Material[]" />
<description>
</description>
</method>
diff --git a/modules/gltf/editor/editor_scene_exporter_gltf_plugin.cpp b/modules/gltf/editor/editor_scene_exporter_gltf_plugin.cpp
index 95db1c0965..fe63afcc56 100644
--- a/modules/gltf/editor/editor_scene_exporter_gltf_plugin.cpp
+++ b/modules/gltf/editor/editor_scene_exporter_gltf_plugin.cpp
@@ -33,18 +33,10 @@
#include "editor_scene_exporter_gltf_plugin.h"
#include "../gltf_document.h"
-#include "../gltf_state.h"
-#include "core/config/project_settings.h"
-#include "core/error/error_list.h"
-#include "core/object/object.h"
-#include "core/templates/vector.h"
#include "editor/editor_file_dialog.h"
#include "editor/editor_file_system.h"
#include "editor/editor_node.h"
-#include "scene/3d/mesh_instance_3d.h"
-#include "scene/gui/check_box.h"
-#include "scene/main/node.h"
String SceneExporterGLTFPlugin::get_name() const {
return "ConvertGLTF2";
@@ -85,7 +77,7 @@ void SceneExporterGLTFPlugin::_gltf2_dialog_action(String p_file) {
state.instantiate();
int32_t flags = 0;
flags |= EditorSceneFormatImporter::IMPORT_USE_NAMED_SKIN_BINDS;
- Error err = doc->append_from_scene(root, state, flags, 30.0f);
+ Error err = doc->append_from_scene(root, state, flags);
if (err != OK) {
ERR_PRINT(vformat("glTF2 save scene error %s.", itos(err)));
}
diff --git a/modules/gltf/editor/editor_scene_exporter_gltf_plugin.h b/modules/gltf/editor/editor_scene_exporter_gltf_plugin.h
index 5af46bc752..66fd27b449 100644
--- a/modules/gltf/editor/editor_scene_exporter_gltf_plugin.h
+++ b/modules/gltf/editor/editor_scene_exporter_gltf_plugin.h
@@ -36,6 +36,8 @@
#include "editor/editor_plugin.h"
#include "editor_scene_importer_gltf.h"
+class EditorFileDialog;
+
class SceneExporterGLTFPlugin : public EditorPlugin {
GDCLASS(SceneExporterGLTFPlugin, EditorPlugin);
diff --git a/modules/gltf/editor/editor_scene_importer_blend.cpp b/modules/gltf/editor/editor_scene_importer_blend.cpp
index 20c9508474..4dafa746bc 100644
--- a/modules/gltf/editor/editor_scene_importer_blend.cpp
+++ b/modules/gltf/editor/editor_scene_importer_blend.cpp
@@ -33,7 +33,6 @@
#ifdef TOOLS_ENABLED
#include "../gltf_document.h"
-#include "../gltf_state.h"
#include "core/config/project_settings.h"
#include "editor/editor_file_dialog.h"
@@ -41,8 +40,7 @@
#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "main/main.h"
-#include "scene/main/node.h"
-#include "scene/resources/animation.h"
+#include "scene/gui/line_edit.h"
#ifdef WINDOWS_ENABLED
// Code by Pedro Estebanez (https://github.com/godotengine/godot/pull/59766)
@@ -58,7 +56,7 @@ void EditorSceneFormatImporterBlend::get_extensions(List<String> *r_extensions)
}
Node *EditorSceneFormatImporterBlend::import_scene(const String &p_path, uint32_t p_flags,
- const HashMap<StringName, Variant> &p_options, int p_bake_fps,
+ const HashMap<StringName, Variant> &p_options,
List<String> *r_missing_deps, Error *r_err) {
// Get global paths for source and sink.
@@ -227,14 +225,14 @@ Node *EditorSceneFormatImporterBlend::import_scene(const String &p_path, uint32_
if (p_options.has(SNAME("blender/materials/unpack_enabled")) && p_options[SNAME("blender/materials/unpack_enabled")]) {
base_dir = sink.get_base_dir();
}
- Error err = gltf->append_from_file(sink.get_basename() + ".gltf", state, p_flags, p_bake_fps, base_dir);
+ Error err = gltf->append_from_file(sink.get_basename() + ".gltf", state, p_flags, base_dir);
if (err != OK) {
if (r_err) {
*r_err = FAILED;
}
return nullptr;
}
- return gltf->generate_scene(state, p_bake_fps);
+ return gltf->generate_scene(state, (float)p_options["animation/fps"], (bool)p_options["animation/trimming"]);
}
Variant EditorSceneFormatImporterBlend::get_option_visibility(const String &p_path, bool p_for_animation, const String &p_option,
diff --git a/modules/gltf/editor/editor_scene_importer_blend.h b/modules/gltf/editor/editor_scene_importer_blend.h
index a1485ff82e..fe687f19fc 100644
--- a/modules/gltf/editor/editor_scene_importer_blend.h
+++ b/modules/gltf/editor/editor_scene_importer_blend.h
@@ -66,7 +66,7 @@ public:
virtual uint32_t get_import_flags() const override;
virtual void get_extensions(List<String> *r_extensions) const override;
virtual Node *import_scene(const String &p_path, uint32_t p_flags,
- const HashMap<StringName, Variant> &p_options, int p_bake_fps,
+ const HashMap<StringName, Variant> &p_options,
List<String> *r_missing_deps, Error *r_err = nullptr) override;
virtual void get_import_options(const String &p_path,
List<ResourceImporter::ImportOption> *r_options) override;
diff --git a/modules/gltf/editor/editor_scene_importer_fbx.cpp b/modules/gltf/editor/editor_scene_importer_fbx.cpp
index 017a44cccf..27e0052c1a 100644
--- a/modules/gltf/editor/editor_scene_importer_fbx.cpp
+++ b/modules/gltf/editor/editor_scene_importer_fbx.cpp
@@ -33,12 +33,10 @@
#ifdef TOOLS_ENABLED
#include "../gltf_document.h"
-#include "../gltf_state.h"
#include "core/config/project_settings.h"
#include "editor/editor_settings.h"
-#include "scene/main/node.h"
-#include "scene/resources/animation.h"
+#include "main/main.h"
uint32_t EditorSceneFormatImporterFBX::get_import_flags() const {
return ImportFlags::IMPORT_SCENE | ImportFlags::IMPORT_ANIMATION;
@@ -49,7 +47,7 @@ void EditorSceneFormatImporterFBX::get_extensions(List<String> *r_extensions) co
}
Node *EditorSceneFormatImporterFBX::import_scene(const String &p_path, uint32_t p_flags,
- const HashMap<StringName, Variant> &p_options, int p_bake_fps,
+ const HashMap<StringName, Variant> &p_options,
List<String> *r_missing_deps, Error *r_err) {
// Get global paths for source and sink.
@@ -95,14 +93,14 @@ Node *EditorSceneFormatImporterFBX::import_scene(const String &p_path, uint32_t
Ref<GLTFState> state;
state.instantiate();
print_verbose(vformat("glTF path: %s", sink));
- Error err = gltf->append_from_file(sink, state, p_flags, p_bake_fps);
+ Error err = gltf->append_from_file(sink, state, p_flags);
if (err != OK) {
if (r_err) {
*r_err = FAILED;
}
return nullptr;
}
- return gltf->generate_scene(state, p_bake_fps);
+ return gltf->generate_scene(state, (float)p_options["animation/fps"], (bool)p_options["animation/trimming"]);
}
Variant EditorSceneFormatImporterFBX::get_option_visibility(const String &p_path, bool p_for_animation,
@@ -114,4 +112,30 @@ void EditorSceneFormatImporterFBX::get_import_options(const String &p_path,
List<ResourceImporter::ImportOption> *r_options) {
}
+bool EditorFileSystemImportFormatSupportQueryFBX::is_active() const {
+ String fbx2gltf_path = EDITOR_GET("filesystem/import/fbx/fbx2gltf_path");
+ return !FileAccess::exists(fbx2gltf_path);
+}
+
+Vector<String> EditorFileSystemImportFormatSupportQueryFBX::get_file_extensions() const {
+ Vector<String> ret;
+ ret.push_back("fbx");
+ return ret;
+}
+
+bool EditorFileSystemImportFormatSupportQueryFBX::query() {
+ FBXImporterManager::get_singleton()->show_dialog(true);
+
+ while (true) {
+ OS::get_singleton()->delay_usec(1);
+ DisplayServer::get_singleton()->process_events();
+ Main::iteration();
+ if (!FBXImporterManager::get_singleton()->is_visible()) {
+ break;
+ }
+ }
+
+ return false;
+}
+
#endif // TOOLS_ENABLED
diff --git a/modules/gltf/editor/editor_scene_importer_fbx.h b/modules/gltf/editor/editor_scene_importer_fbx.h
index b0039b1c8f..82179cc460 100644
--- a/modules/gltf/editor/editor_scene_importer_fbx.h
+++ b/modules/gltf/editor/editor_scene_importer_fbx.h
@@ -33,6 +33,8 @@
#ifdef TOOLS_ENABLED
+#include "editor/editor_file_system.h"
+#include "editor/fbx_importer_manager.h"
#include "editor/import/resource_importer_scene.h"
class Animation;
@@ -45,7 +47,7 @@ public:
virtual uint32_t get_import_flags() const override;
virtual void get_extensions(List<String> *r_extensions) const override;
virtual Node *import_scene(const String &p_path, uint32_t p_flags,
- const HashMap<StringName, Variant> &p_options, int p_bake_fps,
+ const HashMap<StringName, Variant> &p_options,
List<String> *r_missing_deps, Error *r_err = nullptr) override;
virtual void get_import_options(const String &p_path,
List<ResourceImporter::ImportOption> *r_options) override;
@@ -53,6 +55,15 @@ public:
const HashMap<StringName, Variant> &p_options) override;
};
+class EditorFileSystemImportFormatSupportQueryFBX : public EditorFileSystemImportFormatSupportQuery {
+ GDCLASS(EditorFileSystemImportFormatSupportQueryFBX, EditorFileSystemImportFormatSupportQuery);
+
+public:
+ virtual bool is_active() const override;
+ virtual Vector<String> get_file_extensions() const override;
+ virtual bool query() override;
+};
+
#endif // TOOLS_ENABLED
#endif // EDITOR_SCENE_IMPORTER_FBX_H
diff --git a/modules/gltf/editor/editor_scene_importer_gltf.cpp b/modules/gltf/editor/editor_scene_importer_gltf.cpp
index 161808aade..bd1ba85abf 100644
--- a/modules/gltf/editor/editor_scene_importer_gltf.cpp
+++ b/modules/gltf/editor/editor_scene_importer_gltf.cpp
@@ -33,9 +33,6 @@
#include "editor_scene_importer_gltf.h"
#include "../gltf_document.h"
-#include "../gltf_state.h"
-
-#include "scene/resources/animation.h"
uint32_t EditorSceneFormatImporterGLTF::get_import_flags() const {
return ImportFlags::IMPORT_SCENE | ImportFlags::IMPORT_ANIMATION;
@@ -47,13 +44,13 @@ void EditorSceneFormatImporterGLTF::get_extensions(List<String> *r_extensions) c
}
Node *EditorSceneFormatImporterGLTF::import_scene(const String &p_path, uint32_t p_flags,
- const HashMap<StringName, Variant> &p_options, int p_bake_fps,
+ const HashMap<StringName, Variant> &p_options,
List<String> *r_missing_deps, Error *r_err) {
Ref<GLTFDocument> doc;
doc.instantiate();
Ref<GLTFState> state;
state.instantiate();
- Error err = doc->append_from_file(p_path, state, p_flags, p_bake_fps);
+ Error err = doc->append_from_file(p_path, state, p_flags);
if (err != OK) {
if (r_err) {
*r_err = err;
@@ -63,7 +60,12 @@ Node *EditorSceneFormatImporterGLTF::import_scene(const String &p_path, uint32_t
if (p_options.has("animation/import")) {
state->set_create_animations(bool(p_options["animation/import"]));
}
- return doc->generate_scene(state, p_bake_fps);
+
+ if (p_options.has("animation/trimming")) {
+ return doc->generate_scene(state, (float)p_options["animation/fps"], (bool)p_options["animation/trimming"]);
+ } else {
+ return doc->generate_scene(state, (float)p_options["animation/fps"], false);
+ }
}
#endif // TOOLS_ENABLED
diff --git a/modules/gltf/editor/editor_scene_importer_gltf.h b/modules/gltf/editor/editor_scene_importer_gltf.h
index b17a1e4eaa..c0582b26c1 100644
--- a/modules/gltf/editor/editor_scene_importer_gltf.h
+++ b/modules/gltf/editor/editor_scene_importer_gltf.h
@@ -33,9 +33,6 @@
#ifdef TOOLS_ENABLED
-#include "../gltf_document_extension.h"
-#include "../gltf_state.h"
-
#include "editor/import/resource_importer_scene.h"
class Animation;
@@ -48,7 +45,7 @@ public:
virtual uint32_t get_import_flags() const override;
virtual void get_extensions(List<String> *r_extensions) const override;
virtual Node *import_scene(const String &p_path, uint32_t p_flags,
- const HashMap<StringName, Variant> &p_options, int p_bake_fps,
+ const HashMap<StringName, Variant> &p_options,
List<String> *r_missing_deps, Error *r_err = nullptr) override;
};
diff --git a/modules/gltf/gltf_document_extension.cpp b/modules/gltf/extensions/gltf_document_extension.cpp
index 713779712c..630a62ba5c 100644
--- a/modules/gltf/gltf_document_extension.cpp
+++ b/modules/gltf/extensions/gltf_document_extension.cpp
@@ -31,35 +31,50 @@
#include "gltf_document_extension.h"
void GLTFDocumentExtension::_bind_methods() {
+ // Import process.
+ GDVIRTUAL_BIND(_import_preflight, "state", "extensions");
GDVIRTUAL_BIND(_get_supported_extensions);
- GDVIRTUAL_BIND(_import_preflight, "state");
+ GDVIRTUAL_BIND(_parse_node_extensions, "state", "gltf_node", "extensions");
+ GDVIRTUAL_BIND(_generate_scene_node, "state", "gltf_node", "scene_parent");
GDVIRTUAL_BIND(_import_post_parse, "state");
GDVIRTUAL_BIND(_import_node, "state", "gltf_node", "json", "node");
GDVIRTUAL_BIND(_import_post, "state", "root");
- GDVIRTUAL_BIND(_export_preflight, "root");
+ // Export process.
+ GDVIRTUAL_BIND(_export_preflight, "state", "root");
+ GDVIRTUAL_BIND(_convert_scene_node, "state", "gltf_node", "scene_node");
GDVIRTUAL_BIND(_export_node, "state", "gltf_node", "json", "node");
GDVIRTUAL_BIND(_export_post, "state");
}
+// Import process.
+Error GLTFDocumentExtension::import_preflight(Ref<GLTFState> p_state, Vector<String> p_extensions) {
+ ERR_FAIL_NULL_V(p_state, ERR_INVALID_PARAMETER);
+ int err = OK;
+ GDVIRTUAL_CALL(_import_preflight, p_state, p_extensions, err);
+ return Error(err);
+}
+
Vector<String> GLTFDocumentExtension::get_supported_extensions() {
Vector<String> ret;
GDVIRTUAL_CALL(_get_supported_extensions, ret);
return ret;
}
-Error GLTFDocumentExtension::import_post(Ref<GLTFState> p_state, Node *p_root) {
- ERR_FAIL_NULL_V(p_root, ERR_INVALID_PARAMETER);
+Error GLTFDocumentExtension::parse_node_extensions(Ref<GLTFState> p_state, Ref<GLTFNode> p_gltf_node, Dictionary &p_extensions) {
ERR_FAIL_NULL_V(p_state, ERR_INVALID_PARAMETER);
+ ERR_FAIL_NULL_V(p_gltf_node, ERR_INVALID_PARAMETER);
int err = OK;
- GDVIRTUAL_CALL(_import_post, p_state, p_root, err);
+ GDVIRTUAL_CALL(_parse_node_extensions, p_state, p_gltf_node, p_extensions, err);
return Error(err);
}
-Error GLTFDocumentExtension::import_preflight(Ref<GLTFState> p_state) {
- ERR_FAIL_NULL_V(p_state, ERR_INVALID_PARAMETER);
- int err = OK;
- GDVIRTUAL_CALL(_import_preflight, p_state, err);
- return Error(err);
+Node3D *GLTFDocumentExtension::generate_scene_node(Ref<GLTFState> p_state, Ref<GLTFNode> p_gltf_node, Node *p_scene_parent) {
+ ERR_FAIL_NULL_V(p_state, nullptr);
+ ERR_FAIL_NULL_V(p_gltf_node, nullptr);
+ ERR_FAIL_NULL_V(p_scene_parent, nullptr);
+ Node3D *ret_node = nullptr;
+ GDVIRTUAL_CALL(_generate_scene_node, p_state, p_gltf_node, p_scene_parent, ret_node);
+ return ret_node;
}
Error GLTFDocumentExtension::import_post_parse(Ref<GLTFState> p_state) {
@@ -69,28 +84,38 @@ Error GLTFDocumentExtension::import_post_parse(Ref<GLTFState> p_state) {
return Error(err);
}
-Error GLTFDocumentExtension::export_post(Ref<GLTFState> p_state) {
+Error GLTFDocumentExtension::import_node(Ref<GLTFState> p_state, Ref<GLTFNode> p_gltf_node, Dictionary &r_dict, Node *p_node) {
ERR_FAIL_NULL_V(p_state, ERR_INVALID_PARAMETER);
+ ERR_FAIL_NULL_V(p_gltf_node, ERR_INVALID_PARAMETER);
+ ERR_FAIL_NULL_V(p_node, ERR_INVALID_PARAMETER);
int err = OK;
- GDVIRTUAL_CALL(_export_post, p_state, err);
+ GDVIRTUAL_CALL(_import_node, p_state, p_gltf_node, r_dict, p_node, err);
return Error(err);
}
-Error GLTFDocumentExtension::export_preflight(Node *p_root) {
+
+Error GLTFDocumentExtension::import_post(Ref<GLTFState> p_state, Node *p_root) {
ERR_FAIL_NULL_V(p_root, ERR_INVALID_PARAMETER);
+ ERR_FAIL_NULL_V(p_state, ERR_INVALID_PARAMETER);
int err = OK;
- GDVIRTUAL_CALL(_export_preflight, p_root, err);
+ GDVIRTUAL_CALL(_import_post, p_state, p_root, err);
return Error(err);
}
-Error GLTFDocumentExtension::import_node(Ref<GLTFState> p_state, Ref<GLTFNode> p_gltf_node, Dictionary &r_dict, Node *p_node) {
- ERR_FAIL_NULL_V(p_state, ERR_INVALID_PARAMETER);
- ERR_FAIL_NULL_V(p_gltf_node, ERR_INVALID_PARAMETER);
- ERR_FAIL_NULL_V(p_node, ERR_INVALID_PARAMETER);
+// Export process.
+Error GLTFDocumentExtension::export_preflight(Ref<GLTFState> p_state, Node *p_root) {
+ ERR_FAIL_NULL_V(p_root, ERR_INVALID_PARAMETER);
int err = OK;
- GDVIRTUAL_CALL(_import_node, p_state, p_gltf_node, r_dict, p_node, err);
+ GDVIRTUAL_CALL(_export_preflight, p_state, p_root, err);
return Error(err);
}
+void GLTFDocumentExtension::convert_scene_node(Ref<GLTFState> p_state, Ref<GLTFNode> p_gltf_node, Node *p_scene_node) {
+ ERR_FAIL_NULL(p_state);
+ ERR_FAIL_NULL(p_gltf_node);
+ ERR_FAIL_NULL(p_scene_node);
+ GDVIRTUAL_CALL(_convert_scene_node, p_state, p_gltf_node, p_scene_node);
+}
+
Error GLTFDocumentExtension::export_node(Ref<GLTFState> p_state, Ref<GLTFNode> p_gltf_node, Dictionary &r_dict, Node *p_node) {
ERR_FAIL_NULL_V(p_state, ERR_INVALID_PARAMETER);
ERR_FAIL_NULL_V(p_gltf_node, ERR_INVALID_PARAMETER);
@@ -99,3 +124,10 @@ Error GLTFDocumentExtension::export_node(Ref<GLTFState> p_state, Ref<GLTFNode> p
GDVIRTUAL_CALL(_export_node, p_state, p_gltf_node, r_dict, p_node, err);
return Error(err);
}
+
+Error GLTFDocumentExtension::export_post(Ref<GLTFState> p_state) {
+ ERR_FAIL_NULL_V(p_state, ERR_INVALID_PARAMETER);
+ int err = OK;
+ GDVIRTUAL_CALL(_export_post, p_state, err);
+ return Error(err);
+}
diff --git a/modules/gltf/gltf_document_extension.h b/modules/gltf/extensions/gltf_document_extension.h
index d4bb3993dc..66cb9a3c33 100644
--- a/modules/gltf/gltf_document_extension.h
+++ b/modules/gltf/extensions/gltf_document_extension.h
@@ -31,8 +31,7 @@
#ifndef GLTF_DOCUMENT_EXTENSION_H
#define GLTF_DOCUMENT_EXTENSION_H
-#include "gltf_state.h"
-#include "structures/gltf_node.h"
+#include "../gltf_state.h"
class GLTFDocumentExtension : public Resource {
GDCLASS(GLTFDocumentExtension, Resource);
@@ -41,20 +40,31 @@ protected:
static void _bind_methods();
public:
+ // Import process.
+ virtual Error import_preflight(Ref<GLTFState> p_state, Vector<String> p_extensions);
virtual Vector<String> get_supported_extensions();
- virtual Error import_preflight(Ref<GLTFState> p_state);
+ virtual Error parse_node_extensions(Ref<GLTFState> p_state, Ref<GLTFNode> p_gltf_node, Dictionary &p_extensions);
+ virtual Node3D *generate_scene_node(Ref<GLTFState> p_state, Ref<GLTFNode> p_gltf_node, Node *p_scene_parent);
virtual Error import_post_parse(Ref<GLTFState> p_state);
- virtual Error export_post(Ref<GLTFState> p_state);
- virtual Error import_post(Ref<GLTFState> p_state, Node *p_node);
- virtual Error export_preflight(Node *p_state);
virtual Error import_node(Ref<GLTFState> p_state, Ref<GLTFNode> p_gltf_node, Dictionary &r_json, Node *p_node);
+ virtual Error import_post(Ref<GLTFState> p_state, Node *p_node);
+ // Export process.
+ virtual Error export_preflight(Ref<GLTFState> p_state, Node *p_root);
+ virtual void convert_scene_node(Ref<GLTFState> p_state, Ref<GLTFNode> p_gltf_node, Node *p_scene_node);
virtual Error export_node(Ref<GLTFState> p_state, Ref<GLTFNode> p_gltf_node, Dictionary &r_json, Node *p_node);
+ virtual Error export_post(Ref<GLTFState> p_state);
+
+ // Import process.
+ GDVIRTUAL2R(int, _import_preflight, Ref<GLTFState>, Vector<String>);
GDVIRTUAL0R(Vector<String>, _get_supported_extensions);
- GDVIRTUAL1R(int, _import_preflight, Ref<GLTFState>);
+ GDVIRTUAL3R(int, _parse_node_extensions, Ref<GLTFState>, Ref<GLTFNode>, Dictionary);
+ GDVIRTUAL3R(Node3D *, _generate_scene_node, Ref<GLTFState>, Ref<GLTFNode>, Node *);
GDVIRTUAL1R(int, _import_post_parse, Ref<GLTFState>);
GDVIRTUAL4R(int, _import_node, Ref<GLTFState>, Ref<GLTFNode>, Dictionary, Node *);
GDVIRTUAL2R(int, _import_post, Ref<GLTFState>, Node *);
- GDVIRTUAL1R(int, _export_preflight, Node *);
+ // Export process.
+ GDVIRTUAL2R(int, _export_preflight, Ref<GLTFState>, Node *);
+ GDVIRTUAL3(_convert_scene_node, Ref<GLTFState>, Ref<GLTFNode>, Node *);
GDVIRTUAL4R(int, _export_node, Ref<GLTFState>, Ref<GLTFNode>, Dictionary, Node *);
GDVIRTUAL1R(int, _export_post, Ref<GLTFState>);
};
diff --git a/modules/gltf/gltf_document_extension_convert_importer_mesh.cpp b/modules/gltf/extensions/gltf_document_extension_convert_importer_mesh.cpp
index 1620900a04..cfa498af65 100644
--- a/modules/gltf/gltf_document_extension_convert_importer_mesh.cpp
+++ b/modules/gltf/extensions/gltf_document_extension_convert_importer_mesh.cpp
@@ -30,9 +30,7 @@
#include "gltf_document_extension_convert_importer_mesh.h"
-#include "gltf_state.h"
-
-#include "core/error/error_macros.h"
+#include "scene/3d/importer_mesh_instance_3d.h"
#include "scene/3d/mesh_instance_3d.h"
#include "scene/resources/importer_mesh.h"
diff --git a/modules/gltf/gltf_document_extension_convert_importer_mesh.h b/modules/gltf/extensions/gltf_document_extension_convert_importer_mesh.h
index 00e664e73f..4fbfa0e066 100644
--- a/modules/gltf/gltf_document_extension_convert_importer_mesh.h
+++ b/modules/gltf/extensions/gltf_document_extension_convert_importer_mesh.h
@@ -33,10 +33,6 @@
#include "gltf_document_extension.h"
-#include "scene/3d/importer_mesh_instance_3d.h"
-#include "scene/3d/mesh_instance_3d.h"
-#include "scene/resources/importer_mesh.h"
-
class GLTFDocumentExtensionConvertImporterMesh : public GLTFDocumentExtension {
GDCLASS(GLTFDocumentExtensionConvertImporterMesh, GLTFDocumentExtension);
diff --git a/modules/gltf/extensions/gltf_light.cpp b/modules/gltf/extensions/gltf_light.cpp
index d00bead61c..0379c62c9d 100644
--- a/modules/gltf/extensions/gltf_light.cpp
+++ b/modules/gltf/extensions/gltf_light.cpp
@@ -30,6 +30,8 @@
#include "gltf_light.h"
+#include "scene/3d/light_3d.h"
+
void GLTFLight::_bind_methods() {
ClassDB::bind_static_method("GLTFLight", D_METHOD("from_node", "light_node"), &GLTFLight::from_node);
ClassDB::bind_method(D_METHOD("to_node"), &GLTFLight::to_node);
diff --git a/modules/gltf/extensions/gltf_light.h b/modules/gltf/extensions/gltf_light.h
index 04980e144c..85284f1d0e 100644
--- a/modules/gltf/extensions/gltf_light.h
+++ b/modules/gltf/extensions/gltf_light.h
@@ -31,9 +31,9 @@
#ifndef GLTF_LIGHT_H
#define GLTF_LIGHT_H
-#include "core/config/engine.h"
#include "core/io/resource.h"
-#include "scene/3d/light_3d.h"
+
+class Light3D;
// https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_lights_punctual
diff --git a/modules/gltf/extensions/gltf_spec_gloss.cpp b/modules/gltf/extensions/gltf_spec_gloss.cpp
index 83af91bfcc..0645f31e01 100644
--- a/modules/gltf/extensions/gltf_spec_gloss.cpp
+++ b/modules/gltf/extensions/gltf_spec_gloss.cpp
@@ -30,6 +30,8 @@
#include "gltf_spec_gloss.h"
+#include "core/io/image.h"
+
void GLTFSpecGloss::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_diffuse_img"), &GLTFSpecGloss::get_diffuse_img);
ClassDB::bind_method(D_METHOD("set_diffuse_img", "diffuse_img"), &GLTFSpecGloss::set_diffuse_img);
diff --git a/modules/gltf/extensions/gltf_spec_gloss.h b/modules/gltf/extensions/gltf_spec_gloss.h
index 2b4d3ee609..56474acd03 100644
--- a/modules/gltf/extensions/gltf_spec_gloss.h
+++ b/modules/gltf/extensions/gltf_spec_gloss.h
@@ -31,9 +31,10 @@
#ifndef GLTF_SPEC_GLOSS_H
#define GLTF_SPEC_GLOSS_H
-#include "core/io/image.h"
#include "core/io/resource.h"
+class Image;
+
// KHR_materials_pbrSpecularGlossiness is an archived GLTF extension.
// This means that it is deprecated and not recommended for new files.
// However, it is still supported for loading old files.
diff --git a/modules/gltf/gltf_defines.h b/modules/gltf/gltf_defines.h
index 23bf33869e..7b990e6573 100644
--- a/modules/gltf/gltf_defines.h
+++ b/modules/gltf/gltf_defines.h
@@ -36,9 +36,10 @@
// Godot classes used by GLTF headers.
class BoneAttachment3D;
class CSGShape3D;
-class DirectionalLight3D;
class GridMap;
+class ImporterMeshInstance3D;
class Light3D;
+class MeshInstance3D;
class MultiMeshInstance3D;
class Skeleton3D;
class Skin;
diff --git a/modules/gltf/gltf_document.cpp b/modules/gltf/gltf_document.cpp
index 99803ed05d..d858f76b28 100644
--- a/modules/gltf/gltf_document.cpp
+++ b/modules/gltf/gltf_document.cpp
@@ -31,33 +31,23 @@
#include "gltf_document.h"
#include "extensions/gltf_spec_gloss.h"
-#include "gltf_document_extension.h"
-#include "gltf_document_extension_convert_importer_mesh.h"
-#include "gltf_state.h"
#include "core/crypto/crypto_core.h"
-#include "core/error/error_macros.h"
#include "core/io/dir_access.h"
#include "core/io/file_access.h"
#include "core/io/file_access_memory.h"
#include "core/io/json.h"
#include "core/io/stream_peer.h"
#include "core/math/disjoint_set.h"
-#include "core/math/vector2.h"
-#include "core/variant/dictionary.h"
-#include "core/variant/typed_array.h"
-#include "core/variant/variant.h"
#include "core/version.h"
#include "drivers/png/png_driver_common.h"
-#include "scene/2d/node_2d.h"
+#include "scene/3d/bone_attachment_3d.h"
+#include "scene/3d/camera_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/3d/multimesh_instance_3d.h"
-#include "scene/3d/node_3d.h"
-#include "scene/animation/animation_player.h"
-#include "scene/resources/importer_mesh.h"
-#include "scene/resources/material.h"
-#include "scene/resources/mesh.h"
-#include "scene/resources/multimesh.h"
+#include "scene/resources/skin.h"
#include "scene/resources/surface_tool.h"
#include "modules/modules_enabled.gen.h" // For csg, gridmap.
@@ -113,148 +103,147 @@ static Ref<ImporterMesh> _mesh_to_importer_mesh(Ref<Mesh> p_mesh) {
return importer_mesh;
}
-Error GLTFDocument::_serialize(Ref<GLTFState> state, const String &p_path) {
- if (!state->buffers.size()) {
- state->buffers.push_back(Vector<uint8_t>());
+Error GLTFDocument::_serialize(Ref<GLTFState> p_state, const String &p_path) {
+ if (!p_state->buffers.size()) {
+ p_state->buffers.push_back(Vector<uint8_t>());
}
/* STEP CONVERT MESH INSTANCES */
- _convert_mesh_instances(state);
+ _convert_mesh_instances(p_state);
/* STEP SERIALIZE CAMERAS */
- Error err = _serialize_cameras(state);
+ Error err = _serialize_cameras(p_state);
if (err != OK) {
return Error::FAILED;
}
/* STEP 3 CREATE SKINS */
- err = _serialize_skins(state);
+ err = _serialize_skins(p_state);
if (err != OK) {
return Error::FAILED;
}
/* STEP SERIALIZE MESHES (we have enough info now) */
- err = _serialize_meshes(state);
+ err = _serialize_meshes(p_state);
if (err != OK) {
return Error::FAILED;
}
/* STEP SERIALIZE TEXTURES */
- err = _serialize_materials(state);
+ err = _serialize_materials(p_state);
if (err != OK) {
return Error::FAILED;
}
/* STEP SERIALIZE TEXTURE SAMPLERS */
- err = _serialize_texture_samplers(state);
+ err = _serialize_texture_samplers(p_state);
if (err != OK) {
return Error::FAILED;
}
/* STEP SERIALIZE ANIMATIONS */
- err = _serialize_animations(state);
+ err = _serialize_animations(p_state);
if (err != OK) {
return Error::FAILED;
}
/* STEP SERIALIZE ACCESSORS */
- err = _encode_accessors(state);
+ err = _encode_accessors(p_state);
if (err != OK) {
return Error::FAILED;
}
/* STEP SERIALIZE IMAGES */
- err = _serialize_images(state, p_path);
+ err = _serialize_images(p_state, p_path);
if (err != OK) {
return Error::FAILED;
}
/* STEP SERIALIZE TEXTURES */
- err = _serialize_textures(state);
+ err = _serialize_textures(p_state);
if (err != OK) {
return Error::FAILED;
}
- for (GLTFBufferViewIndex i = 0; i < state->buffer_views.size(); i++) {
- state->buffer_views.write[i]->buffer = 0;
+ for (GLTFBufferViewIndex i = 0; i < p_state->buffer_views.size(); i++) {
+ p_state->buffer_views.write[i]->buffer = 0;
}
/* STEP SERIALIZE BUFFER VIEWS */
- err = _encode_buffer_views(state);
+ err = _encode_buffer_views(p_state);
if (err != OK) {
return Error::FAILED;
}
/* STEP SERIALIZE NODES */
- err = _serialize_nodes(state);
+ err = _serialize_nodes(p_state);
if (err != OK) {
return Error::FAILED;
}
/* STEP SERIALIZE SCENE */
- err = _serialize_scenes(state);
+ err = _serialize_scenes(p_state);
if (err != OK) {
return Error::FAILED;
}
/* STEP SERIALIZE LIGHTS */
- err = _serialize_lights(state);
+ err = _serialize_lights(p_state);
if (err != OK) {
return Error::FAILED;
}
/* STEP SERIALIZE EXTENSIONS */
- err = _serialize_gltf_extensions(state);
+ err = _serialize_gltf_extensions(p_state);
if (err != OK) {
return Error::FAILED;
}
/* STEP SERIALIZE VERSION */
- err = _serialize_version(state);
+ err = _serialize_version(p_state);
if (err != OK) {
return Error::FAILED;
}
- for (int32_t ext_i = 0; ext_i < document_extensions.size(); ext_i++) {
- Ref<GLTFDocumentExtension> ext = document_extensions[ext_i];
+ for (Ref<GLTFDocumentExtension> ext : document_extensions) {
ERR_CONTINUE(ext.is_null());
- err = ext->export_post(state);
+ err = ext->export_post(p_state);
ERR_FAIL_COND_V(err != OK, err);
}
return OK;
}
-Error GLTFDocument::_serialize_gltf_extensions(Ref<GLTFState> state) const {
- Vector<String> extensions_used = state->extensions_used;
- Vector<String> extensions_required = state->extensions_required;
- if (!state->lights.is_empty()) {
+Error GLTFDocument::_serialize_gltf_extensions(Ref<GLTFState> p_state) const {
+ Vector<String> extensions_used = p_state->extensions_used;
+ Vector<String> extensions_required = p_state->extensions_required;
+ if (!p_state->lights.is_empty()) {
extensions_used.push_back("KHR_lights_punctual");
}
- if (state->use_khr_texture_transform) {
+ if (p_state->use_khr_texture_transform) {
extensions_used.push_back("KHR_texture_transform");
extensions_required.push_back("KHR_texture_transform");
}
if (!extensions_used.is_empty()) {
extensions_used.sort();
- state->json["extensionsUsed"] = extensions_used;
+ p_state->json["extensionsUsed"] = extensions_used;
}
if (!extensions_required.is_empty()) {
extensions_required.sort();
- state->json["extensionsRequired"] = extensions_required;
+ p_state->json["extensionsRequired"] = extensions_required;
}
return OK;
}
-Error GLTFDocument::_serialize_scenes(Ref<GLTFState> state) {
+Error GLTFDocument::_serialize_scenes(Ref<GLTFState> p_state) {
Array scenes;
const int loaded_scene = 0;
- state->json["scene"] = loaded_scene;
+ p_state->json["scene"] = loaded_scene;
- if (state->nodes.size()) {
+ if (p_state->nodes.size()) {
Dictionary s;
- if (!state->scene_name.is_empty()) {
- s["name"] = state->scene_name;
+ if (!p_state->scene_name.is_empty()) {
+ s["name"] = p_state->scene_name;
}
Array nodes;
@@ -262,21 +251,21 @@ Error GLTFDocument::_serialize_scenes(Ref<GLTFState> state) {
s["nodes"] = nodes;
scenes.push_back(s);
}
- state->json["scenes"] = scenes;
+ p_state->json["scenes"] = scenes;
return OK;
}
-Error GLTFDocument::_parse_json(const String &p_path, Ref<GLTFState> state) {
+Error GLTFDocument::_parse_json(const String &p_path, Ref<GLTFState> p_state) {
Error err;
- Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ, &err);
- if (f.is_null()) {
+ Ref<FileAccess> file = FileAccess::open(p_path, FileAccess::READ, &err);
+ if (file.is_null()) {
return err;
}
Vector<uint8_t> array;
- array.resize(f->get_length());
- f->get_buffer(array.ptrw(), array.size());
+ array.resize(file->get_length());
+ file->get_buffer(array.ptrw(), array.size());
String text;
text.parse_utf8((const char *)array.ptr(), array.size());
@@ -286,26 +275,26 @@ Error GLTFDocument::_parse_json(const String &p_path, Ref<GLTFState> state) {
_err_print_error("", p_path.utf8().get_data(), json.get_error_line(), json.get_error_message().utf8().get_data(), false, ERR_HANDLER_SCRIPT);
return err;
}
- state->json = json.get_data();
+ p_state->json = json.get_data();
return OK;
}
-Error GLTFDocument::_parse_glb(Ref<FileAccess> f, Ref<GLTFState> state) {
- ERR_FAIL_NULL_V(f, ERR_INVALID_PARAMETER);
- ERR_FAIL_NULL_V(state, ERR_INVALID_PARAMETER);
- ERR_FAIL_COND_V(f->get_position() != 0, ERR_FILE_CANT_READ);
- uint32_t magic = f->get_32();
+Error GLTFDocument::_parse_glb(Ref<FileAccess> p_file, Ref<GLTFState> p_state) {
+ ERR_FAIL_NULL_V(p_file, ERR_INVALID_PARAMETER);
+ ERR_FAIL_NULL_V(p_state, ERR_INVALID_PARAMETER);
+ ERR_FAIL_COND_V(p_file->get_position() != 0, ERR_FILE_CANT_READ);
+ uint32_t magic = p_file->get_32();
ERR_FAIL_COND_V(magic != 0x46546C67, ERR_FILE_UNRECOGNIZED); //glTF
- f->get_32(); // version
- f->get_32(); // length
- uint32_t chunk_length = f->get_32();
- uint32_t chunk_type = f->get_32();
+ p_file->get_32(); // version
+ p_file->get_32(); // length
+ uint32_t chunk_length = p_file->get_32();
+ uint32_t chunk_type = p_file->get_32();
ERR_FAIL_COND_V(chunk_type != 0x4E4F534A, ERR_PARSE_ERROR); //JSON
Vector<uint8_t> json_data;
json_data.resize(chunk_length);
- uint32_t len = f->get_buffer(json_data.ptrw(), chunk_length);
+ uint32_t len = p_file->get_buffer(json_data.ptrw(), chunk_length);
ERR_FAIL_COND_V(len != chunk_length, ERR_FILE_CORRUPT);
String text;
@@ -318,21 +307,21 @@ Error GLTFDocument::_parse_glb(Ref<FileAccess> f, Ref<GLTFState> state) {
return err;
}
- state->json = json.get_data();
+ p_state->json = json.get_data();
//data?
- chunk_length = f->get_32();
- chunk_type = f->get_32();
+ chunk_length = p_file->get_32();
+ chunk_type = p_file->get_32();
- if (f->eof_reached()) {
+ if (p_file->eof_reached()) {
return OK; //all good
}
ERR_FAIL_COND_V(chunk_type != 0x004E4942, ERR_PARSE_ERROR); //BIN
- state->glb_data.resize(chunk_length);
- len = f->get_buffer(state->glb_data.ptrw(), chunk_length);
+ p_state->glb_data.resize(chunk_length);
+ len = p_file->get_buffer(p_state->glb_data.ptrw(), chunk_length);
ERR_FAIL_COND_V(len != chunk_length, ERR_FILE_CORRUPT);
return OK;
@@ -405,11 +394,11 @@ static Vector<real_t> _xform_to_array(const Transform3D p_transform) {
return array;
}
-Error GLTFDocument::_serialize_nodes(Ref<GLTFState> state) {
+Error GLTFDocument::_serialize_nodes(Ref<GLTFState> p_state) {
Array nodes;
- for (int i = 0; i < state->nodes.size(); i++) {
+ for (int i = 0; i < p_state->nodes.size(); i++) {
Dictionary node;
- Ref<GLTFNode> gltf_node = state->nodes[i];
+ Ref<GLTFNode> gltf_node = p_state->nodes[i];
Dictionary extensions;
node["extensions"] = extensions;
if (!gltf_node->get_name().is_empty()) {
@@ -454,21 +443,20 @@ Error GLTFDocument::_serialize_nodes(Ref<GLTFState> state) {
node["children"] = children;
}
- for (int32_t ext_i = 0; ext_i < document_extensions.size(); ext_i++) {
- Ref<GLTFDocumentExtension> ext = document_extensions[ext_i];
+ for (Ref<GLTFDocumentExtension> ext : document_extensions) {
ERR_CONTINUE(ext.is_null());
- ERR_CONTINUE(!state->scene_nodes.find(i));
- Error err = ext->export_node(state, gltf_node, node, state->scene_nodes[i]);
+ ERR_CONTINUE(!p_state->scene_nodes.find(i));
+ Error err = ext->export_node(p_state, gltf_node, node, p_state->scene_nodes[i]);
ERR_CONTINUE(err != OK);
}
nodes.push_back(node);
}
- state->json["nodes"] = nodes;
+ p_state->json["nodes"] = nodes;
return OK;
}
-String GLTFDocument::_gen_unique_name(Ref<GLTFState> state, const String &p_name) {
+String GLTFDocument::_gen_unique_name(Ref<GLTFState> p_state, const String &p_name) {
const String s_name = p_name.validate_node_name();
String u_name;
@@ -479,13 +467,13 @@ String GLTFDocument::_gen_unique_name(Ref<GLTFState> state, const String &p_name
if (index > 1) {
u_name += itos(index);
}
- if (!state->unique_names.has(u_name)) {
+ if (!p_state->unique_names.has(u_name)) {
break;
}
index++;
}
- state->unique_names.insert(u_name);
+ p_state->unique_names.insert(u_name);
return u_name;
}
@@ -501,7 +489,7 @@ String GLTFDocument::_sanitize_animation_name(const String &p_name) {
return anim_name;
}
-String GLTFDocument::_gen_unique_animation_name(Ref<GLTFState> state, const String &p_name) {
+String GLTFDocument::_gen_unique_animation_name(Ref<GLTFState> p_state, const String &p_name) {
const String s_name = _sanitize_animation_name(p_name);
String u_name;
@@ -512,13 +500,13 @@ String GLTFDocument::_gen_unique_animation_name(Ref<GLTFState> state, const Stri
if (index > 1) {
u_name += itos(index);
}
- if (!state->unique_animation_names.has(u_name)) {
+ if (!p_state->unique_animation_names.has(u_name)) {
break;
}
index++;
}
- state->unique_animation_names.insert(u_name);
+ p_state->unique_animation_names.insert(u_name);
return u_name;
}
@@ -530,7 +518,7 @@ String GLTFDocument::_sanitize_bone_name(const String &p_name) {
return bone_name;
}
-String GLTFDocument::_gen_unique_bone_name(Ref<GLTFState> state, const GLTFSkeletonIndex skel_i, const String &p_name) {
+String GLTFDocument::_gen_unique_bone_name(Ref<GLTFState> p_state, const GLTFSkeletonIndex p_skel_i, const String &p_name) {
String s_name = _sanitize_bone_name(p_name);
if (s_name.is_empty()) {
s_name = "bone";
@@ -543,23 +531,23 @@ String GLTFDocument::_gen_unique_bone_name(Ref<GLTFState> state, const GLTFSkele
if (index > 1) {
u_name += "_" + itos(index);
}
- if (!state->skeletons[skel_i]->unique_names.has(u_name)) {
+ if (!p_state->skeletons[p_skel_i]->unique_names.has(u_name)) {
break;
}
index++;
}
- state->skeletons.write[skel_i]->unique_names.insert(u_name);
+ p_state->skeletons.write[p_skel_i]->unique_names.insert(u_name);
return u_name;
}
-Error GLTFDocument::_parse_scenes(Ref<GLTFState> state) {
- ERR_FAIL_COND_V(!state->json.has("scenes"), ERR_FILE_CORRUPT);
- const Array &scenes = state->json["scenes"];
+Error GLTFDocument::_parse_scenes(Ref<GLTFState> p_state) {
+ ERR_FAIL_COND_V(!p_state->json.has("scenes"), ERR_FILE_CORRUPT);
+ const Array &scenes = p_state->json["scenes"];
int loaded_scene = 0;
- if (state->json.has("scene")) {
- loaded_scene = state->json["scene"];
+ if (p_state->json.has("scene")) {
+ loaded_scene = p_state->json["scene"];
} else {
WARN_PRINT("The load-time scene is not defined in the glTF2 file. Picking the first scene.");
}
@@ -570,22 +558,22 @@ Error GLTFDocument::_parse_scenes(Ref<GLTFState> state) {
ERR_FAIL_COND_V(!s.has("nodes"), ERR_UNAVAILABLE);
const Array &nodes = s["nodes"];
for (int j = 0; j < nodes.size(); j++) {
- state->root_nodes.push_back(nodes[j]);
+ p_state->root_nodes.push_back(nodes[j]);
}
if (s.has("name") && !String(s["name"]).is_empty() && !((String)s["name"]).begins_with("Scene")) {
- state->scene_name = _gen_unique_name(state, s["name"]);
+ p_state->scene_name = _gen_unique_name(p_state, s["name"]);
} else {
- state->scene_name = _gen_unique_name(state, state->filename);
+ p_state->scene_name = _gen_unique_name(p_state, p_state->filename);
}
}
return OK;
}
-Error GLTFDocument::_parse_nodes(Ref<GLTFState> state) {
- ERR_FAIL_COND_V(!state->json.has("nodes"), ERR_FILE_CORRUPT);
- const Array &nodes = state->json["nodes"];
+Error GLTFDocument::_parse_nodes(Ref<GLTFState> p_state) {
+ ERR_FAIL_COND_V(!p_state->json.has("nodes"), ERR_FILE_CORRUPT);
+ const Array &nodes = p_state->json["nodes"];
for (int i = 0; i < nodes.size(); i++) {
Ref<GLTFNode> node;
node.instantiate();
@@ -629,6 +617,11 @@ Error GLTFDocument::_parse_nodes(Ref<GLTFState> state) {
node->light = light;
}
}
+ for (Ref<GLTFDocumentExtension> ext : document_extensions) {
+ ERR_CONTINUE(ext.is_null());
+ Error err = ext->parse_node_extensions(p_state, node, extensions);
+ ERR_CONTINUE_MSG(err != OK, "GLTF: Encountered error " + itos(err) + " when parsing node extensions for node " + node->get_name() + " in file " + p_state->filename + ". Continuing.");
+ }
}
if (n.has("children")) {
@@ -638,35 +631,35 @@ Error GLTFDocument::_parse_nodes(Ref<GLTFState> state) {
}
}
- state->nodes.push_back(node);
+ p_state->nodes.push_back(node);
}
// build the hierarchy
- for (GLTFNodeIndex node_i = 0; node_i < state->nodes.size(); node_i++) {
- for (int j = 0; j < state->nodes[node_i]->children.size(); j++) {
- GLTFNodeIndex child_i = state->nodes[node_i]->children[j];
+ for (GLTFNodeIndex node_i = 0; node_i < p_state->nodes.size(); node_i++) {
+ for (int j = 0; j < p_state->nodes[node_i]->children.size(); j++) {
+ GLTFNodeIndex child_i = p_state->nodes[node_i]->children[j];
- ERR_FAIL_INDEX_V(child_i, state->nodes.size(), ERR_FILE_CORRUPT);
- ERR_CONTINUE(state->nodes[child_i]->parent != -1); //node already has a parent, wtf.
+ ERR_FAIL_INDEX_V(child_i, p_state->nodes.size(), ERR_FILE_CORRUPT);
+ ERR_CONTINUE(p_state->nodes[child_i]->parent != -1); //node already has a parent, wtf.
- state->nodes.write[child_i]->parent = node_i;
+ p_state->nodes.write[child_i]->parent = node_i;
}
}
- _compute_node_heights(state);
+ _compute_node_heights(p_state);
return OK;
}
-void GLTFDocument::_compute_node_heights(Ref<GLTFState> state) {
- state->root_nodes.clear();
- for (GLTFNodeIndex node_i = 0; node_i < state->nodes.size(); ++node_i) {
- Ref<GLTFNode> node = state->nodes[node_i];
+void GLTFDocument::_compute_node_heights(Ref<GLTFState> p_state) {
+ p_state->root_nodes.clear();
+ for (GLTFNodeIndex node_i = 0; node_i < p_state->nodes.size(); ++node_i) {
+ Ref<GLTFNode> node = p_state->nodes[node_i];
node->height = 0;
GLTFNodeIndex current_i = node_i;
while (current_i >= 0) {
- const GLTFNodeIndex parent_i = state->nodes[current_i]->parent;
+ const GLTFNodeIndex parent_i = p_state->nodes[current_i]->parent;
if (parent_i >= 0) {
++node->height;
}
@@ -674,7 +667,7 @@ void GLTFDocument::_compute_node_heights(Ref<GLTFState> state) {
}
if (node->height == 0) {
- state->root_nodes.push_back(node_i);
+ p_state->root_nodes.push_back(node_i);
}
}
}
@@ -697,86 +690,86 @@ static Vector<uint8_t> _parse_base64_uri(const String &uri) {
return buf;
}
-Error GLTFDocument::_encode_buffer_glb(Ref<GLTFState> state, const String &p_path) {
- print_verbose("glTF: Total buffers: " + itos(state->buffers.size()));
+Error GLTFDocument::_encode_buffer_glb(Ref<GLTFState> p_state, const String &p_path) {
+ print_verbose("glTF: Total buffers: " + itos(p_state->buffers.size()));
- if (!state->buffers.size()) {
+ if (!p_state->buffers.size()) {
return OK;
}
Array buffers;
- if (state->buffers.size()) {
- Vector<uint8_t> buffer_data = state->buffers[0];
+ if (p_state->buffers.size()) {
+ Vector<uint8_t> buffer_data = p_state->buffers[0];
Dictionary gltf_buffer;
gltf_buffer["byteLength"] = buffer_data.size();
buffers.push_back(gltf_buffer);
}
- for (GLTFBufferIndex i = 1; i < state->buffers.size() - 1; i++) {
- Vector<uint8_t> buffer_data = state->buffers[i];
+ for (GLTFBufferIndex i = 1; i < p_state->buffers.size() - 1; i++) {
+ Vector<uint8_t> buffer_data = p_state->buffers[i];
Dictionary gltf_buffer;
String filename = p_path.get_basename().get_file() + itos(i) + ".bin";
String path = p_path.get_base_dir() + "/" + filename;
Error err;
- Ref<FileAccess> f = FileAccess::open(path, FileAccess::WRITE, &err);
- if (f.is_null()) {
+ Ref<FileAccess> file = FileAccess::open(path, FileAccess::WRITE, &err);
+ if (file.is_null()) {
return err;
}
if (buffer_data.size() == 0) {
return OK;
}
- f->create(FileAccess::ACCESS_RESOURCES);
- f->store_buffer(buffer_data.ptr(), buffer_data.size());
+ file->create(FileAccess::ACCESS_RESOURCES);
+ file->store_buffer(buffer_data.ptr(), buffer_data.size());
gltf_buffer["uri"] = filename;
gltf_buffer["byteLength"] = buffer_data.size();
buffers.push_back(gltf_buffer);
}
- state->json["buffers"] = buffers;
+ p_state->json["buffers"] = buffers;
return OK;
}
-Error GLTFDocument::_encode_buffer_bins(Ref<GLTFState> state, const String &p_path) {
- print_verbose("glTF: Total buffers: " + itos(state->buffers.size()));
+Error GLTFDocument::_encode_buffer_bins(Ref<GLTFState> p_state, const String &p_path) {
+ print_verbose("glTF: Total buffers: " + itos(p_state->buffers.size()));
- if (!state->buffers.size()) {
+ if (!p_state->buffers.size()) {
return OK;
}
Array buffers;
- for (GLTFBufferIndex i = 0; i < state->buffers.size(); i++) {
- Vector<uint8_t> buffer_data = state->buffers[i];
+ for (GLTFBufferIndex i = 0; i < p_state->buffers.size(); i++) {
+ Vector<uint8_t> buffer_data = p_state->buffers[i];
Dictionary gltf_buffer;
String filename = p_path.get_basename().get_file() + itos(i) + ".bin";
String path = p_path.get_base_dir() + "/" + filename;
Error err;
- Ref<FileAccess> f = FileAccess::open(path, FileAccess::WRITE, &err);
- if (f.is_null()) {
+ Ref<FileAccess> file = FileAccess::open(path, FileAccess::WRITE, &err);
+ if (file.is_null()) {
return err;
}
if (buffer_data.size() == 0) {
return OK;
}
- f->create(FileAccess::ACCESS_RESOURCES);
- f->store_buffer(buffer_data.ptr(), buffer_data.size());
+ file->create(FileAccess::ACCESS_RESOURCES);
+ file->store_buffer(buffer_data.ptr(), buffer_data.size());
gltf_buffer["uri"] = filename;
gltf_buffer["byteLength"] = buffer_data.size();
buffers.push_back(gltf_buffer);
}
- state->json["buffers"] = buffers;
+ p_state->json["buffers"] = buffers;
return OK;
}
-Error GLTFDocument::_parse_buffers(Ref<GLTFState> state, const String &p_base_path) {
- if (!state->json.has("buffers")) {
+Error GLTFDocument::_parse_buffers(Ref<GLTFState> p_state, const String &p_base_path) {
+ if (!p_state->json.has("buffers")) {
return OK;
}
- const Array &buffers = state->json["buffers"];
+ const Array &buffers = p_state->json["buffers"];
for (GLTFBufferIndex i = 0; i < buffers.size(); i++) {
- if (i == 0 && state->glb_data.size()) {
- state->buffers.push_back(state->glb_data);
+ if (i == 0 && p_state->glb_data.size()) {
+ p_state->buffers.push_back(p_state->glb_data);
} else {
const Dictionary &buffer = buffers[i];
@@ -795,29 +788,29 @@ Error GLTFDocument::_parse_buffers(Ref<GLTFState> state, const String &p_base_pa
ERR_FAIL_COND_V(p_base_path.is_empty(), ERR_INVALID_PARAMETER);
uri = uri.uri_decode();
uri = p_base_path.path_join(uri).replace("\\", "/"); // Fix for Windows.
- buffer_data = FileAccess::get_file_as_array(uri);
+ buffer_data = FileAccess::get_file_as_bytes(uri);
ERR_FAIL_COND_V_MSG(buffer.size() == 0, ERR_PARSE_ERROR, "glTF: Couldn't load binary file as an array: " + uri);
}
ERR_FAIL_COND_V(!buffer.has("byteLength"), ERR_PARSE_ERROR);
int byteLength = buffer["byteLength"];
ERR_FAIL_COND_V(byteLength < buffer_data.size(), ERR_PARSE_ERROR);
- state->buffers.push_back(buffer_data);
+ p_state->buffers.push_back(buffer_data);
}
}
}
- print_verbose("glTF: Total buffers: " + itos(state->buffers.size()));
+ print_verbose("glTF: Total buffers: " + itos(p_state->buffers.size()));
return OK;
}
-Error GLTFDocument::_encode_buffer_views(Ref<GLTFState> state) {
+Error GLTFDocument::_encode_buffer_views(Ref<GLTFState> p_state) {
Array buffers;
- for (GLTFBufferViewIndex i = 0; i < state->buffer_views.size(); i++) {
+ for (GLTFBufferViewIndex i = 0; i < p_state->buffer_views.size(); i++) {
Dictionary d;
- Ref<GLTFBufferView> buffer_view = state->buffer_views[i];
+ Ref<GLTFBufferView> buffer_view = p_state->buffer_views[i];
d["buffer"] = buffer_view->buffer;
d["byteLength"] = buffer_view->byte_length;
@@ -835,19 +828,19 @@ Error GLTFDocument::_encode_buffer_views(Ref<GLTFState> state) {
ERR_FAIL_COND_V(!d.has("byteLength"), ERR_INVALID_DATA);
buffers.push_back(d);
}
- print_verbose("glTF: Total buffer views: " + itos(state->buffer_views.size()));
+ print_verbose("glTF: Total buffer views: " + itos(p_state->buffer_views.size()));
if (!buffers.size()) {
return OK;
}
- state->json["bufferViews"] = buffers;
+ p_state->json["bufferViews"] = buffers;
return OK;
}
-Error GLTFDocument::_parse_buffer_views(Ref<GLTFState> state) {
- if (!state->json.has("bufferViews")) {
+Error GLTFDocument::_parse_buffer_views(Ref<GLTFState> p_state) {
+ if (!p_state->json.has("bufferViews")) {
return OK;
}
- const Array &buffers = state->json["bufferViews"];
+ const Array &buffers = p_state->json["bufferViews"];
for (GLTFBufferViewIndex i = 0; i < buffers.size(); i++) {
const Dictionary &d = buffers[i];
@@ -872,20 +865,20 @@ Error GLTFDocument::_parse_buffer_views(Ref<GLTFState> state) {
buffer_view->indices = target == GLTFDocument::ELEMENT_ARRAY_BUFFER;
}
- state->buffer_views.push_back(buffer_view);
+ p_state->buffer_views.push_back(buffer_view);
}
- print_verbose("glTF: Total buffer views: " + itos(state->buffer_views.size()));
+ print_verbose("glTF: Total buffer views: " + itos(p_state->buffer_views.size()));
return OK;
}
-Error GLTFDocument::_encode_accessors(Ref<GLTFState> state) {
+Error GLTFDocument::_encode_accessors(Ref<GLTFState> p_state) {
Array accessors;
- for (GLTFAccessorIndex i = 0; i < state->accessors.size(); i++) {
+ for (GLTFAccessorIndex i = 0; i < p_state->accessors.size(); i++) {
Dictionary d;
- Ref<GLTFAccessor> accessor = state->accessors[i];
+ Ref<GLTFAccessor> accessor = p_state->accessors[i];
d["componentType"] = accessor->component_type;
d["count"] = accessor->count;
d["type"] = _get_accessor_type_name(accessor->type);
@@ -931,9 +924,9 @@ Error GLTFDocument::_encode_accessors(Ref<GLTFState> state) {
if (!accessors.size()) {
return OK;
}
- state->json["accessors"] = accessors;
- ERR_FAIL_COND_V(!state->json.has("accessors"), ERR_FILE_CORRUPT);
- print_verbose("glTF: Total accessors: " + itos(state->accessors.size()));
+ p_state->json["accessors"] = accessors;
+ ERR_FAIL_COND_V(!p_state->json.has("accessors"), ERR_FILE_CORRUPT);
+ print_verbose("glTF: Total accessors: " + itos(p_state->accessors.size()));
return OK;
}
@@ -992,11 +985,11 @@ GLTFType GLTFDocument::_get_type_from_str(const String &p_string) {
ERR_FAIL_V(GLTFType::TYPE_SCALAR);
}
-Error GLTFDocument::_parse_accessors(Ref<GLTFState> state) {
- if (!state->json.has("accessors")) {
+Error GLTFDocument::_parse_accessors(Ref<GLTFState> p_state) {
+ if (!p_state->json.has("accessors")) {
return OK;
}
- const Array &accessors = state->json["accessors"];
+ const Array &accessors = p_state->json["accessors"];
for (GLTFAccessorIndex i = 0; i < accessors.size(); i++) {
const Dictionary &d = accessors[i];
@@ -1059,10 +1052,10 @@ Error GLTFDocument::_parse_accessors(Ref<GLTFState> state) {
}
}
- state->accessors.push_back(accessor);
+ p_state->accessors.push_back(accessor);
}
- print_verbose("glTF: Total accessors: " + itos(state->accessors.size()));
+ print_verbose("glTF: Total accessors: " + itos(p_state->accessors.size()));
return OK;
}
@@ -1107,33 +1100,33 @@ String GLTFDocument::_get_type_name(const GLTFType p_component) {
return names[p_component];
}
-Error GLTFDocument::_encode_buffer_view(Ref<GLTFState> state, const double *src, const int count, const GLTFType type, const int component_type, const bool normalized, const int byte_offset, const bool for_vertex, GLTFBufferViewIndex &r_accessor) {
+Error GLTFDocument::_encode_buffer_view(Ref<GLTFState> p_state, const double *p_src, const int p_count, const GLTFType p_type, const int p_component_type, const bool p_normalized, const int p_byte_offset, const bool p_for_vertex, GLTFBufferViewIndex &r_accessor) {
const int component_count_for_type[7] = {
1, 2, 3, 4, 4, 9, 16
};
- const int component_count = component_count_for_type[type];
- const int component_size = _get_component_type_size(component_type);
+ const int component_count = component_count_for_type[p_type];
+ const int component_size = _get_component_type_size(p_component_type);
ERR_FAIL_COND_V(component_size == 0, FAILED);
int skip_every = 0;
int skip_bytes = 0;
//special case of alignments, as described in spec
- switch (component_type) {
+ switch (p_component_type) {
case COMPONENT_TYPE_BYTE:
case COMPONENT_TYPE_UNSIGNED_BYTE: {
- if (type == TYPE_MAT2) {
+ if (p_type == TYPE_MAT2) {
skip_every = 2;
skip_bytes = 2;
}
- if (type == TYPE_MAT3) {
+ if (p_type == TYPE_MAT3) {
skip_every = 3;
skip_bytes = 1;
}
} break;
case COMPONENT_TYPE_SHORT:
case COMPONENT_TYPE_UNSIGNED_SHORT: {
- if (type == TYPE_MAT3) {
+ if (p_type == TYPE_MAT3) {
skip_every = 6;
skip_bytes = 4;
}
@@ -1144,39 +1137,39 @@ Error GLTFDocument::_encode_buffer_view(Ref<GLTFState> state, const double *src,
Ref<GLTFBufferView> bv;
bv.instantiate();
- const uint32_t offset = bv->byte_offset = byte_offset;
- Vector<uint8_t> &gltf_buffer = state->buffers.write[0];
+ const uint32_t offset = bv->byte_offset = p_byte_offset;
+ Vector<uint8_t> &gltf_buffer = p_state->buffers.write[0];
- int stride = _get_component_type_size(component_type);
- if (for_vertex && stride % 4) {
+ int stride = _get_component_type_size(p_component_type);
+ if (p_for_vertex && stride % 4) {
stride += 4 - (stride % 4); //according to spec must be multiple of 4
}
//use to debug
- print_verbose("glTF: encoding type " + _get_type_name(type) + " component type: " + _get_component_type_name(component_type) + " stride: " + itos(stride) + " amount " + itos(count));
+ print_verbose("glTF: encoding type " + _get_type_name(p_type) + " component type: " + _get_component_type_name(p_component_type) + " stride: " + itos(stride) + " amount " + itos(p_count));
- print_verbose("glTF: encoding accessor offset " + itos(byte_offset) + " view offset: " + itos(bv->byte_offset) + " total buffer len: " + itos(gltf_buffer.size()) + " view len " + itos(bv->byte_length));
+ print_verbose("glTF: encoding accessor offset " + itos(p_byte_offset) + " view offset: " + itos(bv->byte_offset) + " total buffer len: " + itos(gltf_buffer.size()) + " view len " + itos(bv->byte_length));
- const int buffer_end = (stride * (count - 1)) + _get_component_type_size(component_type);
+ const int buffer_end = (stride * (p_count - 1)) + _get_component_type_size(p_component_type);
// TODO define bv->byte_stride
bv->byte_offset = gltf_buffer.size();
- switch (component_type) {
+ switch (p_component_type) {
case COMPONENT_TYPE_BYTE: {
Vector<int8_t> buffer;
- buffer.resize(count * component_count);
+ buffer.resize(p_count * component_count);
int32_t dst_i = 0;
- for (int i = 0; i < count; i++) {
+ for (int i = 0; i < p_count; i++) {
for (int j = 0; j < component_count; j++) {
if (skip_every && j > 0 && (j % skip_every) == 0) {
dst_i += skip_bytes;
}
- double d = *src;
- if (normalized) {
+ double d = *p_src;
+ if (p_normalized) {
buffer.write[dst_i] = d * 128.0;
} else {
buffer.write[dst_i] = d;
}
- src++;
+ p_src++;
dst_i++;
}
}
@@ -1187,20 +1180,20 @@ Error GLTFDocument::_encode_buffer_view(Ref<GLTFState> state, const double *src,
} break;
case COMPONENT_TYPE_UNSIGNED_BYTE: {
Vector<uint8_t> buffer;
- buffer.resize(count * component_count);
+ buffer.resize(p_count * component_count);
int32_t dst_i = 0;
- for (int i = 0; i < count; i++) {
+ for (int i = 0; i < p_count; i++) {
for (int j = 0; j < component_count; j++) {
if (skip_every && j > 0 && (j % skip_every) == 0) {
dst_i += skip_bytes;
}
- double d = *src;
- if (normalized) {
+ double d = *p_src;
+ if (p_normalized) {
buffer.write[dst_i] = d * 255.0;
} else {
buffer.write[dst_i] = d;
}
- src++;
+ p_src++;
dst_i++;
}
}
@@ -1209,20 +1202,20 @@ Error GLTFDocument::_encode_buffer_view(Ref<GLTFState> state, const double *src,
} break;
case COMPONENT_TYPE_SHORT: {
Vector<int16_t> buffer;
- buffer.resize(count * component_count);
+ buffer.resize(p_count * component_count);
int32_t dst_i = 0;
- for (int i = 0; i < count; i++) {
+ for (int i = 0; i < p_count; i++) {
for (int j = 0; j < component_count; j++) {
if (skip_every && j > 0 && (j % skip_every) == 0) {
dst_i += skip_bytes;
}
- double d = *src;
- if (normalized) {
+ double d = *p_src;
+ if (p_normalized) {
buffer.write[dst_i] = d * 32768.0;
} else {
buffer.write[dst_i] = d;
}
- src++;
+ p_src++;
dst_i++;
}
}
@@ -1233,20 +1226,20 @@ Error GLTFDocument::_encode_buffer_view(Ref<GLTFState> state, const double *src,
} break;
case COMPONENT_TYPE_UNSIGNED_SHORT: {
Vector<uint16_t> buffer;
- buffer.resize(count * component_count);
+ buffer.resize(p_count * component_count);
int32_t dst_i = 0;
- for (int i = 0; i < count; i++) {
+ for (int i = 0; i < p_count; i++) {
for (int j = 0; j < component_count; j++) {
if (skip_every && j > 0 && (j % skip_every) == 0) {
dst_i += skip_bytes;
}
- double d = *src;
- if (normalized) {
+ double d = *p_src;
+ if (p_normalized) {
buffer.write[dst_i] = d * 65535.0;
} else {
buffer.write[dst_i] = d;
}
- src++;
+ p_src++;
dst_i++;
}
}
@@ -1257,16 +1250,16 @@ Error GLTFDocument::_encode_buffer_view(Ref<GLTFState> state, const double *src,
} break;
case COMPONENT_TYPE_INT: {
Vector<int> buffer;
- buffer.resize(count * component_count);
+ buffer.resize(p_count * component_count);
int32_t dst_i = 0;
- for (int i = 0; i < count; i++) {
+ for (int i = 0; i < p_count; i++) {
for (int j = 0; j < component_count; j++) {
if (skip_every && j > 0 && (j % skip_every) == 0) {
dst_i += skip_bytes;
}
- double d = *src;
+ double d = *p_src;
buffer.write[dst_i] = d;
- src++;
+ p_src++;
dst_i++;
}
}
@@ -1277,16 +1270,16 @@ Error GLTFDocument::_encode_buffer_view(Ref<GLTFState> state, const double *src,
} break;
case COMPONENT_TYPE_FLOAT: {
Vector<float> buffer;
- buffer.resize(count * component_count);
+ buffer.resize(p_count * component_count);
int32_t dst_i = 0;
- for (int i = 0; i < count; i++) {
+ for (int i = 0; i < p_count; i++) {
for (int j = 0; j < component_count; j++) {
if (skip_every && j > 0 && (j % skip_every) == 0) {
dst_i += skip_bytes;
}
- double d = *src;
+ double d = *p_src;
buffer.write[dst_i] = d;
- src++;
+ p_src++;
dst_i++;
}
}
@@ -1299,53 +1292,53 @@ Error GLTFDocument::_encode_buffer_view(Ref<GLTFState> state, const double *src,
ERR_FAIL_COND_V(buffer_end > bv->byte_length, ERR_INVALID_DATA);
ERR_FAIL_COND_V((int)(offset + buffer_end) > gltf_buffer.size(), ERR_INVALID_DATA);
- r_accessor = bv->buffer = state->buffer_views.size();
- state->buffer_views.push_back(bv);
+ r_accessor = bv->buffer = p_state->buffer_views.size();
+ p_state->buffer_views.push_back(bv);
return OK;
}
-Error GLTFDocument::_decode_buffer_view(Ref<GLTFState> state, double *dst, const GLTFBufferViewIndex p_buffer_view, const int skip_every, const int skip_bytes, const int element_size, const int count, const GLTFType type, const int component_count, const int component_type, const int component_size, const bool normalized, const int byte_offset, const bool for_vertex) {
- const Ref<GLTFBufferView> bv = state->buffer_views[p_buffer_view];
+Error GLTFDocument::_decode_buffer_view(Ref<GLTFState> p_state, double *p_dst, const GLTFBufferViewIndex p_buffer_view, const int p_skip_every, const int p_skip_bytes, const int p_element_size, const int p_count, const GLTFType p_type, const int p_component_count, const int p_component_type, const int p_component_size, const bool p_normalized, const int p_byte_offset, const bool p_for_vertex) {
+ const Ref<GLTFBufferView> bv = p_state->buffer_views[p_buffer_view];
- int stride = element_size;
+ int stride = p_element_size;
if (bv->byte_stride != -1) {
stride = bv->byte_stride;
}
- if (for_vertex && stride % 4) {
+ if (p_for_vertex && stride % 4) {
stride += 4 - (stride % 4); //according to spec must be multiple of 4
}
- ERR_FAIL_INDEX_V(bv->buffer, state->buffers.size(), ERR_PARSE_ERROR);
+ ERR_FAIL_INDEX_V(bv->buffer, p_state->buffers.size(), ERR_PARSE_ERROR);
- const uint32_t offset = bv->byte_offset + byte_offset;
- Vector<uint8_t> buffer = state->buffers[bv->buffer]; //copy on write, so no performance hit
+ const uint32_t offset = bv->byte_offset + p_byte_offset;
+ Vector<uint8_t> buffer = p_state->buffers[bv->buffer]; //copy on write, so no performance hit
const uint8_t *bufptr = buffer.ptr();
//use to debug
- print_verbose("glTF: type " + _get_type_name(type) + " component type: " + _get_component_type_name(component_type) + " stride: " + itos(stride) + " amount " + itos(count));
- print_verbose("glTF: accessor offset " + itos(byte_offset) + " view offset: " + itos(bv->byte_offset) + " total buffer len: " + itos(buffer.size()) + " view len " + itos(bv->byte_length));
+ print_verbose("glTF: type " + _get_type_name(p_type) + " component type: " + _get_component_type_name(p_component_type) + " stride: " + itos(stride) + " amount " + itos(p_count));
+ print_verbose("glTF: accessor offset " + itos(p_byte_offset) + " view offset: " + itos(bv->byte_offset) + " total buffer len: " + itos(buffer.size()) + " view len " + itos(bv->byte_length));
- const int buffer_end = (stride * (count - 1)) + element_size;
+ const int buffer_end = (stride * (p_count - 1)) + p_element_size;
ERR_FAIL_COND_V(buffer_end > bv->byte_length, ERR_PARSE_ERROR);
ERR_FAIL_COND_V((int)(offset + buffer_end) > buffer.size(), ERR_PARSE_ERROR);
//fill everything as doubles
- for (int i = 0; i < count; i++) {
+ for (int i = 0; i < p_count; i++) {
const uint8_t *src = &bufptr[offset + i * stride];
- for (int j = 0; j < component_count; j++) {
- if (skip_every && j > 0 && (j % skip_every) == 0) {
- src += skip_bytes;
+ for (int j = 0; j < p_component_count; j++) {
+ if (p_skip_every && j > 0 && (j % p_skip_every) == 0) {
+ src += p_skip_bytes;
}
double d = 0;
- switch (component_type) {
+ switch (p_component_type) {
case COMPONENT_TYPE_BYTE: {
int8_t b = int8_t(*src);
- if (normalized) {
+ if (p_normalized) {
d = (double(b) / 128.0);
} else {
d = double(b);
@@ -1353,7 +1346,7 @@ Error GLTFDocument::_decode_buffer_view(Ref<GLTFState> state, double *dst, const
} break;
case COMPONENT_TYPE_UNSIGNED_BYTE: {
uint8_t b = *src;
- if (normalized) {
+ if (p_normalized) {
d = (double(b) / 255.0);
} else {
d = double(b);
@@ -1361,7 +1354,7 @@ Error GLTFDocument::_decode_buffer_view(Ref<GLTFState> state, double *dst, const
} break;
case COMPONENT_TYPE_SHORT: {
int16_t s = *(int16_t *)src;
- if (normalized) {
+ if (p_normalized) {
d = (double(s) / 32768.0);
} else {
d = double(s);
@@ -1369,7 +1362,7 @@ Error GLTFDocument::_decode_buffer_view(Ref<GLTFState> state, double *dst, const
} break;
case COMPONENT_TYPE_UNSIGNED_SHORT: {
uint16_t s = *(uint16_t *)src;
- if (normalized) {
+ if (p_normalized) {
d = (double(s) / 65535.0);
} else {
d = double(s);
@@ -1383,16 +1376,16 @@ Error GLTFDocument::_decode_buffer_view(Ref<GLTFState> state, double *dst, const
} break;
}
- *dst++ = d;
- src += component_size;
+ *p_dst++ = d;
+ src += p_component_size;
}
}
return OK;
}
-int GLTFDocument::_get_component_type_size(const int component_type) {
- switch (component_type) {
+int GLTFDocument::_get_component_type_size(const int p_component_type) {
+ switch (p_component_type) {
case COMPONENT_TYPE_BYTE:
case COMPONENT_TYPE_UNSIGNED_BYTE:
return 1;
@@ -1412,13 +1405,13 @@ int GLTFDocument::_get_component_type_size(const int component_type) {
return 0;
}
-Vector<double> GLTFDocument::_decode_accessor(Ref<GLTFState> state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) {
+Vector<double> GLTFDocument::_decode_accessor(Ref<GLTFState> p_state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) {
//spec, for reference:
//https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#data-alignment
- ERR_FAIL_INDEX_V(p_accessor, state->accessors.size(), Vector<double>());
+ ERR_FAIL_INDEX_V(p_accessor, p_state->accessors.size(), Vector<double>());
- const Ref<GLTFAccessor> a = state->accessors[p_accessor];
+ const Ref<GLTFAccessor> a = p_state->accessors[p_accessor];
const int component_count_for_type[7] = {
1, 2, 3, 4, 4, 9, 16
@@ -1463,9 +1456,9 @@ Vector<double> GLTFDocument::_decode_accessor(Ref<GLTFState> state, const GLTFAc
double *dst = dst_buffer.ptrw();
if (a->buffer_view >= 0) {
- ERR_FAIL_INDEX_V(a->buffer_view, state->buffer_views.size(), Vector<double>());
+ ERR_FAIL_INDEX_V(a->buffer_view, p_state->buffer_views.size(), Vector<double>());
- const Error err = _decode_buffer_view(state, dst, a->buffer_view, skip_every, skip_bytes, element_size, a->count, a->type, component_count, a->component_type, component_size, a->normalized, a->byte_offset, p_for_vertex);
+ const Error err = _decode_buffer_view(p_state, dst, a->buffer_view, skip_every, skip_bytes, element_size, a->count, a->type, component_count, a->component_type, component_size, a->normalized, a->byte_offset, p_for_vertex);
if (err != OK) {
return Vector<double>();
}
@@ -1482,14 +1475,14 @@ Vector<double> GLTFDocument::_decode_accessor(Ref<GLTFState> state, const GLTFAc
indices.resize(a->sparse_count);
const int indices_component_size = _get_component_type_size(a->sparse_indices_component_type);
- Error err = _decode_buffer_view(state, indices.ptrw(), a->sparse_indices_buffer_view, 0, 0, indices_component_size, a->sparse_count, TYPE_SCALAR, 1, a->sparse_indices_component_type, indices_component_size, false, a->sparse_indices_byte_offset, false);
+ Error err = _decode_buffer_view(p_state, indices.ptrw(), a->sparse_indices_buffer_view, 0, 0, indices_component_size, a->sparse_count, TYPE_SCALAR, 1, a->sparse_indices_component_type, indices_component_size, false, a->sparse_indices_byte_offset, false);
if (err != OK) {
return Vector<double>();
}
Vector<double> data;
data.resize(component_count * a->sparse_count);
- err = _decode_buffer_view(state, data.ptrw(), a->sparse_values_buffer_view, skip_every, skip_bytes, element_size, a->sparse_count, a->type, component_count, a->component_type, component_size, a->normalized, a->sparse_values_byte_offset, p_for_vertex);
+ err = _decode_buffer_view(p_state, data.ptrw(), a->sparse_values_buffer_view, skip_every, skip_bytes, element_size, a->sparse_count, a->type, component_count, a->component_type, component_size, a->normalized, a->sparse_values_byte_offset, p_for_vertex);
if (err != OK) {
return Vector<double>();
}
@@ -1506,7 +1499,7 @@ Vector<double> GLTFDocument::_decode_accessor(Ref<GLTFState> state, const GLTFAc
return dst_buffer;
}
-GLTFAccessorIndex GLTFDocument::_encode_accessor_as_ints(Ref<GLTFState> state, const Vector<int32_t> p_attribs, const bool p_for_vertex) {
+GLTFAccessorIndex GLTFDocument::_encode_accessor_as_ints(Ref<GLTFState> p_state, const Vector<int32_t> p_attribs, const bool p_for_vertex) {
if (p_attribs.size() == 0) {
return -1;
}
@@ -1539,7 +1532,7 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_ints(Ref<GLTFState> state, c
Ref<GLTFAccessor> accessor;
accessor.instantiate();
GLTFBufferIndex buffer_view_i;
- int64_t size = state->buffers[0].size();
+ int64_t size = p_state->buffers[0].size();
const GLTFType type = GLTFType::TYPE_SCALAR;
const int component_type = GLTFDocument::COMPONENT_TYPE_INT;
@@ -1550,17 +1543,17 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_ints(Ref<GLTFState> state, c
accessor->type = type;
accessor->component_type = component_type;
accessor->byte_offset = 0;
- Error err = _encode_buffer_view(state, attribs.ptr(), attribs.size(), type, component_type, accessor->normalized, size, p_for_vertex, buffer_view_i);
+ Error err = _encode_buffer_view(p_state, attribs.ptr(), attribs.size(), type, component_type, accessor->normalized, size, p_for_vertex, buffer_view_i);
if (err != OK) {
return -1;
}
accessor->buffer_view = buffer_view_i;
- state->accessors.push_back(accessor);
- return state->accessors.size() - 1;
+ p_state->accessors.push_back(accessor);
+ return p_state->accessors.size() - 1;
}
-Vector<int> GLTFDocument::_decode_accessor_as_ints(Ref<GLTFState> state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) {
- const Vector<double> attribs = _decode_accessor(state, p_accessor, p_for_vertex);
+Vector<int> GLTFDocument::_decode_accessor_as_ints(Ref<GLTFState> p_state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) {
+ const Vector<double> attribs = _decode_accessor(p_state, p_accessor, p_for_vertex);
Vector<int> ret;
if (attribs.size() == 0) {
@@ -1578,8 +1571,8 @@ Vector<int> GLTFDocument::_decode_accessor_as_ints(Ref<GLTFState> state, const G
return ret;
}
-Vector<float> GLTFDocument::_decode_accessor_as_floats(Ref<GLTFState> state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) {
- const Vector<double> attribs = _decode_accessor(state, p_accessor, p_for_vertex);
+Vector<float> GLTFDocument::_decode_accessor_as_floats(Ref<GLTFState> p_state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) {
+ const Vector<double> attribs = _decode_accessor(p_state, p_accessor, p_for_vertex);
Vector<float> ret;
if (attribs.size() == 0) {
@@ -1597,7 +1590,7 @@ Vector<float> GLTFDocument::_decode_accessor_as_floats(Ref<GLTFState> state, con
return ret;
}
-GLTFAccessorIndex GLTFDocument::_encode_accessor_as_vec2(Ref<GLTFState> state, const Vector<Vector2> p_attribs, const bool p_for_vertex) {
+GLTFAccessorIndex GLTFDocument::_encode_accessor_as_vec2(Ref<GLTFState> p_state, const Vector<Vector2> p_attribs, const bool p_for_vertex) {
if (p_attribs.size() == 0) {
return -1;
}
@@ -1623,7 +1616,7 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_vec2(Ref<GLTFState> state, c
Ref<GLTFAccessor> accessor;
accessor.instantiate();
GLTFBufferIndex buffer_view_i;
- int64_t size = state->buffers[0].size();
+ int64_t size = p_state->buffers[0].size();
const GLTFType type = GLTFType::TYPE_VEC2;
const int component_type = GLTFDocument::COMPONENT_TYPE_FLOAT;
@@ -1634,16 +1627,16 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_vec2(Ref<GLTFState> state, c
accessor->type = type;
accessor->component_type = component_type;
accessor->byte_offset = 0;
- Error err = _encode_buffer_view(state, attribs.ptr(), p_attribs.size(), type, component_type, accessor->normalized, size, p_for_vertex, buffer_view_i);
+ Error err = _encode_buffer_view(p_state, attribs.ptr(), p_attribs.size(), type, component_type, accessor->normalized, size, p_for_vertex, buffer_view_i);
if (err != OK) {
return -1;
}
accessor->buffer_view = buffer_view_i;
- state->accessors.push_back(accessor);
- return state->accessors.size() - 1;
+ p_state->accessors.push_back(accessor);
+ return p_state->accessors.size() - 1;
}
-GLTFAccessorIndex GLTFDocument::_encode_accessor_as_color(Ref<GLTFState> state, const Vector<Color> p_attribs, const bool p_for_vertex) {
+GLTFAccessorIndex GLTFDocument::_encode_accessor_as_color(Ref<GLTFState> p_state, const Vector<Color> p_attribs, const bool p_for_vertex) {
if (p_attribs.size() == 0) {
return -1;
}
@@ -1672,7 +1665,7 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_color(Ref<GLTFState> state,
Ref<GLTFAccessor> accessor;
accessor.instantiate();
GLTFBufferIndex buffer_view_i;
- int64_t size = state->buffers[0].size();
+ int64_t size = p_state->buffers[0].size();
const GLTFType type = GLTFType::TYPE_VEC4;
const int component_type = GLTFDocument::COMPONENT_TYPE_FLOAT;
@@ -1683,31 +1676,31 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_color(Ref<GLTFState> state,
accessor->type = type;
accessor->component_type = component_type;
accessor->byte_offset = 0;
- Error err = _encode_buffer_view(state, attribs.ptr(), p_attribs.size(), type, component_type, accessor->normalized, size, p_for_vertex, buffer_view_i);
+ Error err = _encode_buffer_view(p_state, attribs.ptr(), p_attribs.size(), type, component_type, accessor->normalized, size, p_for_vertex, buffer_view_i);
if (err != OK) {
return -1;
}
accessor->buffer_view = buffer_view_i;
- state->accessors.push_back(accessor);
- return state->accessors.size() - 1;
+ p_state->accessors.push_back(accessor);
+ return p_state->accessors.size() - 1;
}
-void GLTFDocument::_calc_accessor_min_max(int i, const int element_count, Vector<double> &type_max, Vector<double> attribs, Vector<double> &type_min) {
- if (i == 0) {
- for (int32_t type_i = 0; type_i < element_count; type_i++) {
- type_max.write[type_i] = attribs[(i * element_count) + type_i];
- type_min.write[type_i] = attribs[(i * element_count) + type_i];
+void GLTFDocument::_calc_accessor_min_max(int p_i, const int p_element_count, Vector<double> &p_type_max, Vector<double> p_attribs, Vector<double> &p_type_min) {
+ if (p_i == 0) {
+ for (int32_t type_i = 0; type_i < p_element_count; type_i++) {
+ p_type_max.write[type_i] = p_attribs[(p_i * p_element_count) + type_i];
+ p_type_min.write[type_i] = p_attribs[(p_i * p_element_count) + type_i];
}
}
- for (int32_t type_i = 0; type_i < element_count; type_i++) {
- type_max.write[type_i] = MAX(attribs[(i * element_count) + type_i], type_max[type_i]);
- type_min.write[type_i] = MIN(attribs[(i * element_count) + type_i], type_min[type_i]);
- type_max.write[type_i] = _filter_number(type_max.write[type_i]);
- type_min.write[type_i] = _filter_number(type_min.write[type_i]);
+ for (int32_t type_i = 0; type_i < p_element_count; type_i++) {
+ p_type_max.write[type_i] = MAX(p_attribs[(p_i * p_element_count) + type_i], p_type_max[type_i]);
+ p_type_min.write[type_i] = MIN(p_attribs[(p_i * p_element_count) + type_i], p_type_min[type_i]);
+ p_type_max.write[type_i] = _filter_number(p_type_max.write[type_i]);
+ p_type_min.write[type_i] = _filter_number(p_type_min.write[type_i]);
}
}
-GLTFAccessorIndex GLTFDocument::_encode_accessor_as_weights(Ref<GLTFState> state, const Vector<Color> p_attribs, const bool p_for_vertex) {
+GLTFAccessorIndex GLTFDocument::_encode_accessor_as_weights(Ref<GLTFState> p_state, const Vector<Color> p_attribs, const bool p_for_vertex) {
if (p_attribs.size() == 0) {
return -1;
}
@@ -1737,7 +1730,7 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_weights(Ref<GLTFState> state
Ref<GLTFAccessor> accessor;
accessor.instantiate();
GLTFBufferIndex buffer_view_i;
- int64_t size = state->buffers[0].size();
+ int64_t size = p_state->buffers[0].size();
const GLTFType type = GLTFType::TYPE_VEC4;
const int component_type = GLTFDocument::COMPONENT_TYPE_FLOAT;
@@ -1748,16 +1741,16 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_weights(Ref<GLTFState> state
accessor->type = type;
accessor->component_type = component_type;
accessor->byte_offset = 0;
- Error err = _encode_buffer_view(state, attribs.ptr(), p_attribs.size(), type, component_type, accessor->normalized, size, p_for_vertex, buffer_view_i);
+ Error err = _encode_buffer_view(p_state, attribs.ptr(), p_attribs.size(), type, component_type, accessor->normalized, size, p_for_vertex, buffer_view_i);
if (err != OK) {
return -1;
}
accessor->buffer_view = buffer_view_i;
- state->accessors.push_back(accessor);
- return state->accessors.size() - 1;
+ p_state->accessors.push_back(accessor);
+ return p_state->accessors.size() - 1;
}
-GLTFAccessorIndex GLTFDocument::_encode_accessor_as_joints(Ref<GLTFState> state, const Vector<Color> p_attribs, const bool p_for_vertex) {
+GLTFAccessorIndex GLTFDocument::_encode_accessor_as_joints(Ref<GLTFState> p_state, const Vector<Color> p_attribs, const bool p_for_vertex) {
if (p_attribs.size() == 0) {
return -1;
}
@@ -1784,7 +1777,7 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_joints(Ref<GLTFState> state,
Ref<GLTFAccessor> accessor;
accessor.instantiate();
GLTFBufferIndex buffer_view_i;
- int64_t size = state->buffers[0].size();
+ int64_t size = p_state->buffers[0].size();
const GLTFType type = GLTFType::TYPE_VEC4;
const int component_type = GLTFDocument::COMPONENT_TYPE_UNSIGNED_SHORT;
@@ -1795,16 +1788,16 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_joints(Ref<GLTFState> state,
accessor->type = type;
accessor->component_type = component_type;
accessor->byte_offset = 0;
- Error err = _encode_buffer_view(state, attribs.ptr(), p_attribs.size(), type, component_type, accessor->normalized, size, p_for_vertex, buffer_view_i);
+ Error err = _encode_buffer_view(p_state, attribs.ptr(), p_attribs.size(), type, component_type, accessor->normalized, size, p_for_vertex, buffer_view_i);
if (err != OK) {
return -1;
}
accessor->buffer_view = buffer_view_i;
- state->accessors.push_back(accessor);
- return state->accessors.size() - 1;
+ p_state->accessors.push_back(accessor);
+ return p_state->accessors.size() - 1;
}
-GLTFAccessorIndex GLTFDocument::_encode_accessor_as_quaternions(Ref<GLTFState> state, const Vector<Quaternion> p_attribs, const bool p_for_vertex) {
+GLTFAccessorIndex GLTFDocument::_encode_accessor_as_quaternions(Ref<GLTFState> p_state, const Vector<Quaternion> p_attribs, const bool p_for_vertex) {
if (p_attribs.size() == 0) {
return -1;
}
@@ -1833,7 +1826,7 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_quaternions(Ref<GLTFState> s
Ref<GLTFAccessor> accessor;
accessor.instantiate();
GLTFBufferIndex buffer_view_i;
- int64_t size = state->buffers[0].size();
+ int64_t size = p_state->buffers[0].size();
const GLTFType type = GLTFType::TYPE_VEC4;
const int component_type = GLTFDocument::COMPONENT_TYPE_FLOAT;
@@ -1844,17 +1837,17 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_quaternions(Ref<GLTFState> s
accessor->type = type;
accessor->component_type = component_type;
accessor->byte_offset = 0;
- Error err = _encode_buffer_view(state, attribs.ptr(), p_attribs.size(), type, component_type, accessor->normalized, size, p_for_vertex, buffer_view_i);
+ Error err = _encode_buffer_view(p_state, attribs.ptr(), p_attribs.size(), type, component_type, accessor->normalized, size, p_for_vertex, buffer_view_i);
if (err != OK) {
return -1;
}
accessor->buffer_view = buffer_view_i;
- state->accessors.push_back(accessor);
- return state->accessors.size() - 1;
+ p_state->accessors.push_back(accessor);
+ return p_state->accessors.size() - 1;
}
-Vector<Vector2> GLTFDocument::_decode_accessor_as_vec2(Ref<GLTFState> state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) {
- const Vector<double> attribs = _decode_accessor(state, p_accessor, p_for_vertex);
+Vector<Vector2> GLTFDocument::_decode_accessor_as_vec2(Ref<GLTFState> p_state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) {
+ const Vector<double> attribs = _decode_accessor(p_state, p_accessor, p_for_vertex);
Vector<Vector2> ret;
if (attribs.size() == 0) {
@@ -1873,7 +1866,7 @@ Vector<Vector2> GLTFDocument::_decode_accessor_as_vec2(Ref<GLTFState> state, con
return ret;
}
-GLTFAccessorIndex GLTFDocument::_encode_accessor_as_floats(Ref<GLTFState> state, const Vector<real_t> p_attribs, const bool p_for_vertex) {
+GLTFAccessorIndex GLTFDocument::_encode_accessor_as_floats(Ref<GLTFState> p_state, const Vector<real_t> p_attribs, const bool p_for_vertex) {
if (p_attribs.size() == 0) {
return -1;
}
@@ -1898,7 +1891,7 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_floats(Ref<GLTFState> state,
Ref<GLTFAccessor> accessor;
accessor.instantiate();
GLTFBufferIndex buffer_view_i;
- int64_t size = state->buffers[0].size();
+ int64_t size = p_state->buffers[0].size();
const GLTFType type = GLTFType::TYPE_SCALAR;
const int component_type = GLTFDocument::COMPONENT_TYPE_FLOAT;
@@ -1909,16 +1902,16 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_floats(Ref<GLTFState> state,
accessor->type = type;
accessor->component_type = component_type;
accessor->byte_offset = 0;
- Error err = _encode_buffer_view(state, attribs.ptr(), attribs.size(), type, component_type, accessor->normalized, size, p_for_vertex, buffer_view_i);
+ Error err = _encode_buffer_view(p_state, attribs.ptr(), attribs.size(), type, component_type, accessor->normalized, size, p_for_vertex, buffer_view_i);
if (err != OK) {
return -1;
}
accessor->buffer_view = buffer_view_i;
- state->accessors.push_back(accessor);
- return state->accessors.size() - 1;
+ p_state->accessors.push_back(accessor);
+ return p_state->accessors.size() - 1;
}
-GLTFAccessorIndex GLTFDocument::_encode_accessor_as_vec3(Ref<GLTFState> state, const Vector<Vector3> p_attribs, const bool p_for_vertex) {
+GLTFAccessorIndex GLTFDocument::_encode_accessor_as_vec3(Ref<GLTFState> p_state, const Vector<Vector3> p_attribs, const bool p_for_vertex) {
if (p_attribs.size() == 0) {
return -1;
}
@@ -1944,7 +1937,7 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_vec3(Ref<GLTFState> state, c
Ref<GLTFAccessor> accessor;
accessor.instantiate();
GLTFBufferIndex buffer_view_i;
- int64_t size = state->buffers[0].size();
+ int64_t size = p_state->buffers[0].size();
const GLTFType type = GLTFType::TYPE_VEC3;
const int component_type = GLTFDocument::COMPONENT_TYPE_FLOAT;
@@ -1955,16 +1948,16 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_vec3(Ref<GLTFState> state, c
accessor->type = type;
accessor->component_type = component_type;
accessor->byte_offset = 0;
- Error err = _encode_buffer_view(state, attribs.ptr(), p_attribs.size(), type, component_type, accessor->normalized, size, p_for_vertex, buffer_view_i);
+ Error err = _encode_buffer_view(p_state, attribs.ptr(), p_attribs.size(), type, component_type, accessor->normalized, size, p_for_vertex, buffer_view_i);
if (err != OK) {
return -1;
}
accessor->buffer_view = buffer_view_i;
- state->accessors.push_back(accessor);
- return state->accessors.size() - 1;
+ p_state->accessors.push_back(accessor);
+ return p_state->accessors.size() - 1;
}
-GLTFAccessorIndex GLTFDocument::_encode_accessor_as_xform(Ref<GLTFState> state, const Vector<Transform3D> p_attribs, const bool p_for_vertex) {
+GLTFAccessorIndex GLTFDocument::_encode_accessor_as_xform(Ref<GLTFState> p_state, const Vector<Transform3D> p_attribs, const bool p_for_vertex) {
if (p_attribs.size() == 0) {
return -1;
}
@@ -2012,7 +2005,7 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_xform(Ref<GLTFState> state,
Ref<GLTFAccessor> accessor;
accessor.instantiate();
GLTFBufferIndex buffer_view_i;
- int64_t size = state->buffers[0].size();
+ int64_t size = p_state->buffers[0].size();
const GLTFType type = GLTFType::TYPE_MAT4;
const int component_type = GLTFDocument::COMPONENT_TYPE_FLOAT;
@@ -2023,17 +2016,17 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_xform(Ref<GLTFState> state,
accessor->type = type;
accessor->component_type = component_type;
accessor->byte_offset = 0;
- Error err = _encode_buffer_view(state, attribs.ptr(), p_attribs.size(), type, component_type, accessor->normalized, size, p_for_vertex, buffer_view_i);
+ Error err = _encode_buffer_view(p_state, attribs.ptr(), p_attribs.size(), type, component_type, accessor->normalized, size, p_for_vertex, buffer_view_i);
if (err != OK) {
return -1;
}
accessor->buffer_view = buffer_view_i;
- state->accessors.push_back(accessor);
- return state->accessors.size() - 1;
+ p_state->accessors.push_back(accessor);
+ return p_state->accessors.size() - 1;
}
-Vector<Vector3> GLTFDocument::_decode_accessor_as_vec3(Ref<GLTFState> state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) {
- const Vector<double> attribs = _decode_accessor(state, p_accessor, p_for_vertex);
+Vector<Vector3> GLTFDocument::_decode_accessor_as_vec3(Ref<GLTFState> p_state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) {
+ const Vector<double> attribs = _decode_accessor(p_state, p_accessor, p_for_vertex);
Vector<Vector3> ret;
if (attribs.size() == 0) {
@@ -2052,15 +2045,15 @@ Vector<Vector3> GLTFDocument::_decode_accessor_as_vec3(Ref<GLTFState> state, con
return ret;
}
-Vector<Color> GLTFDocument::_decode_accessor_as_color(Ref<GLTFState> state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) {
- const Vector<double> attribs = _decode_accessor(state, p_accessor, p_for_vertex);
+Vector<Color> GLTFDocument::_decode_accessor_as_color(Ref<GLTFState> p_state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) {
+ const Vector<double> attribs = _decode_accessor(p_state, p_accessor, p_for_vertex);
Vector<Color> ret;
if (attribs.size() == 0) {
return ret;
}
- const int type = state->accessors[p_accessor]->type;
+ const int type = p_state->accessors[p_accessor]->type;
ERR_FAIL_COND_V(!(type == TYPE_VEC3 || type == TYPE_VEC4), ret);
int vec_len = 3;
if (type == TYPE_VEC4) {
@@ -2078,8 +2071,8 @@ Vector<Color> GLTFDocument::_decode_accessor_as_color(Ref<GLTFState> state, cons
}
return ret;
}
-Vector<Quaternion> GLTFDocument::_decode_accessor_as_quaternion(Ref<GLTFState> state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) {
- const Vector<double> attribs = _decode_accessor(state, p_accessor, p_for_vertex);
+Vector<Quaternion> GLTFDocument::_decode_accessor_as_quaternion(Ref<GLTFState> p_state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) {
+ const Vector<double> attribs = _decode_accessor(p_state, p_accessor, p_for_vertex);
Vector<Quaternion> ret;
if (attribs.size() == 0) {
@@ -2097,8 +2090,8 @@ Vector<Quaternion> GLTFDocument::_decode_accessor_as_quaternion(Ref<GLTFState> s
}
return ret;
}
-Vector<Transform2D> GLTFDocument::_decode_accessor_as_xform2d(Ref<GLTFState> state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) {
- const Vector<double> attribs = _decode_accessor(state, p_accessor, p_for_vertex);
+Vector<Transform2D> GLTFDocument::_decode_accessor_as_xform2d(Ref<GLTFState> p_state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) {
+ const Vector<double> attribs = _decode_accessor(p_state, p_accessor, p_for_vertex);
Vector<Transform2D> ret;
if (attribs.size() == 0) {
@@ -2114,8 +2107,8 @@ Vector<Transform2D> GLTFDocument::_decode_accessor_as_xform2d(Ref<GLTFState> sta
return ret;
}
-Vector<Basis> GLTFDocument::_decode_accessor_as_basis(Ref<GLTFState> state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) {
- const Vector<double> attribs = _decode_accessor(state, p_accessor, p_for_vertex);
+Vector<Basis> GLTFDocument::_decode_accessor_as_basis(Ref<GLTFState> p_state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) {
+ const Vector<double> attribs = _decode_accessor(p_state, p_accessor, p_for_vertex);
Vector<Basis> ret;
if (attribs.size() == 0) {
@@ -2132,8 +2125,8 @@ Vector<Basis> GLTFDocument::_decode_accessor_as_basis(Ref<GLTFState> state, cons
return ret;
}
-Vector<Transform3D> GLTFDocument::_decode_accessor_as_xform(Ref<GLTFState> state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) {
- const Vector<double> attribs = _decode_accessor(state, p_accessor, p_for_vertex);
+Vector<Transform3D> GLTFDocument::_decode_accessor_as_xform(Ref<GLTFState> p_state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) {
+ const Vector<double> attribs = _decode_accessor(p_state, p_accessor, p_for_vertex);
Vector<Transform3D> ret;
if (attribs.size() == 0) {
@@ -2151,15 +2144,15 @@ Vector<Transform3D> GLTFDocument::_decode_accessor_as_xform(Ref<GLTFState> state
return ret;
}
-Error GLTFDocument::_serialize_meshes(Ref<GLTFState> state) {
+Error GLTFDocument::_serialize_meshes(Ref<GLTFState> p_state) {
Array meshes;
- for (GLTFMeshIndex gltf_mesh_i = 0; gltf_mesh_i < state->meshes.size(); gltf_mesh_i++) {
+ for (GLTFMeshIndex gltf_mesh_i = 0; gltf_mesh_i < p_state->meshes.size(); gltf_mesh_i++) {
print_verbose("glTF: Serializing mesh: " + itos(gltf_mesh_i));
- Ref<ImporterMesh> import_mesh = state->meshes.write[gltf_mesh_i]->get_mesh();
+ Ref<ImporterMesh> import_mesh = p_state->meshes.write[gltf_mesh_i]->get_mesh();
if (import_mesh.is_null()) {
continue;
}
- Array instance_materials = state->meshes.write[gltf_mesh_i]->get_instance_materials();
+ Array instance_materials = p_state->meshes.write[gltf_mesh_i]->get_instance_materials();
Array primitives;
Dictionary gltf_mesh;
Array target_names;
@@ -2212,7 +2205,7 @@ Error GLTFDocument::_serialize_meshes(Ref<GLTFState> state) {
{
Vector<Vector3> a = array[Mesh::ARRAY_VERTEX];
ERR_FAIL_COND_V(!a.size(), ERR_INVALID_DATA);
- attributes["POSITION"] = _encode_accessor_as_vec3(state, a, true);
+ attributes["POSITION"] = _encode_accessor_as_vec3(p_state, a, true);
vertex_num = a.size();
}
{
@@ -2229,7 +2222,7 @@ Error GLTFDocument::_serialize_meshes(Ref<GLTFState> state) {
out.a = a[(i * 4) + 3];
attribs.write[i] = out;
}
- attributes["TANGENT"] = _encode_accessor_as_color(state, attribs, true);
+ attributes["TANGENT"] = _encode_accessor_as_color(p_state, attribs, true);
}
}
{
@@ -2241,19 +2234,19 @@ Error GLTFDocument::_serialize_meshes(Ref<GLTFState> state) {
for (int i = 0; i < ret_size; i++) {
attribs.write[i] = Vector3(a[i]).normalized();
}
- attributes["NORMAL"] = _encode_accessor_as_vec3(state, attribs, true);
+ attributes["NORMAL"] = _encode_accessor_as_vec3(p_state, attribs, true);
}
}
{
Vector<Vector2> a = array[Mesh::ARRAY_TEX_UV];
if (a.size()) {
- attributes["TEXCOORD_0"] = _encode_accessor_as_vec2(state, a, true);
+ attributes["TEXCOORD_0"] = _encode_accessor_as_vec2(p_state, a, true);
}
}
{
Vector<Vector2> a = array[Mesh::ARRAY_TEX_UV2];
if (a.size()) {
- attributes["TEXCOORD_1"] = _encode_accessor_as_vec2(state, a, true);
+ attributes["TEXCOORD_1"] = _encode_accessor_as_vec2(p_state, a, true);
}
}
for (int custom_i = 0; custom_i < 3; custom_i++) {
@@ -2282,7 +2275,7 @@ Error GLTFDocument::_serialize_meshes(Ref<GLTFState> state) {
if (!attributes.has(gltf_texcoord_key)) {
Vector<Vector2> empty;
empty.resize(vertex_num);
- attributes[gltf_texcoord_key] = _encode_accessor_as_vec2(state, empty, true);
+ attributes[gltf_texcoord_key] = _encode_accessor_as_vec2(p_state, empty, true);
}
}
@@ -2303,25 +2296,25 @@ Error GLTFDocument::_serialize_meshes(Ref<GLTFState> state) {
}
}
gltf_texcoord_key = vformat("TEXCOORD_%d", texcoord_i);
- attributes[gltf_texcoord_key] = _encode_accessor_as_vec2(state, first_channel, true);
+ attributes[gltf_texcoord_key] = _encode_accessor_as_vec2(p_state, first_channel, true);
gltf_texcoord_key = vformat("TEXCOORD_%d", texcoord_i + 1);
- attributes[gltf_texcoord_key] = _encode_accessor_as_vec2(state, second_channel, true);
+ attributes[gltf_texcoord_key] = _encode_accessor_as_vec2(p_state, second_channel, true);
}
}
{
Vector<Color> a = array[Mesh::ARRAY_COLOR];
if (a.size()) {
- attributes["COLOR_0"] = _encode_accessor_as_color(state, a, true);
+ attributes["COLOR_0"] = _encode_accessor_as_color(p_state, a, true);
}
}
HashMap<int, int> joint_i_to_bone_i;
- for (GLTFNodeIndex node_i = 0; node_i < state->nodes.size(); node_i++) {
+ for (GLTFNodeIndex node_i = 0; node_i < p_state->nodes.size(); node_i++) {
GLTFSkinIndex skin_i = -1;
- if (state->nodes[node_i]->mesh == gltf_mesh_i) {
- skin_i = state->nodes[node_i]->skin;
+ if (p_state->nodes[node_i]->mesh == gltf_mesh_i) {
+ skin_i = p_state->nodes[node_i]->skin;
}
if (skin_i != -1) {
- joint_i_to_bone_i = state->skins[skin_i]->joint_i_to_bone_i;
+ joint_i_to_bone_i = p_state->skins[skin_i]->joint_i_to_bone_i;
break;
}
}
@@ -2341,7 +2334,7 @@ Error GLTFDocument::_serialize_meshes(Ref<GLTFState> state) {
attribs.write[array_i] = Color(joint_0, joint_1, joint_2, joint_3);
}
}
- attributes["JOINTS_0"] = _encode_accessor_as_joints(state, attribs, true);
+ attributes["JOINTS_0"] = _encode_accessor_as_joints(p_state, attribs, true);
} else if ((a.size() / (JOINT_GROUP_SIZE * 2)) >= vertex_array.size()) {
Vector<Color> joints_0;
joints_0.resize(vertex_num);
@@ -2362,8 +2355,8 @@ Error GLTFDocument::_serialize_meshes(Ref<GLTFState> state) {
joint_1.a = a[vertex_i * weights_8_count + 7];
joints_1.write[vertex_i] = joint_1;
}
- attributes["JOINTS_0"] = _encode_accessor_as_joints(state, joints_0, true);
- attributes["JOINTS_1"] = _encode_accessor_as_joints(state, joints_1, true);
+ attributes["JOINTS_0"] = _encode_accessor_as_joints(p_state, joints_0, true);
+ attributes["JOINTS_1"] = _encode_accessor_as_joints(p_state, joints_1, true);
}
}
{
@@ -2376,7 +2369,7 @@ Error GLTFDocument::_serialize_meshes(Ref<GLTFState> state) {
for (int i = 0; i < vertex_count; i++) {
attribs.write[i] = Color(a[(i * JOINT_GROUP_SIZE) + 0], a[(i * JOINT_GROUP_SIZE) + 1], a[(i * JOINT_GROUP_SIZE) + 2], a[(i * JOINT_GROUP_SIZE) + 3]);
}
- attributes["WEIGHTS_0"] = _encode_accessor_as_weights(state, attribs, true);
+ attributes["WEIGHTS_0"] = _encode_accessor_as_weights(p_state, attribs, true);
} else if ((a.size() / (JOINT_GROUP_SIZE * 2)) >= vertex_array.size()) {
Vector<Color> weights_0;
weights_0.resize(vertex_num);
@@ -2397,8 +2390,8 @@ Error GLTFDocument::_serialize_meshes(Ref<GLTFState> state) {
weight_1.a = a[vertex_i * weights_8_count + 7];
weights_1.write[vertex_i] = weight_1;
}
- attributes["WEIGHTS_0"] = _encode_accessor_as_weights(state, weights_0, true);
- attributes["WEIGHTS_1"] = _encode_accessor_as_weights(state, weights_1, true);
+ attributes["WEIGHTS_0"] = _encode_accessor_as_weights(p_state, weights_0, true);
+ attributes["WEIGHTS_1"] = _encode_accessor_as_weights(p_state, weights_1, true);
}
}
{
@@ -2411,7 +2404,7 @@ Error GLTFDocument::_serialize_meshes(Ref<GLTFState> state) {
SWAP(mesh_indices.write[k + 0], mesh_indices.write[k + 2]);
}
}
- primitive["indices"] = _encode_accessor_as_ints(state, mesh_indices, true);
+ primitive["indices"] = _encode_accessor_as_ints(p_state, mesh_indices, true);
} else {
if (primitive_type == Mesh::PRIMITIVE_TRIANGLES) {
//generate indices because they need to be swapped for CW/CCW
@@ -2430,7 +2423,7 @@ Error GLTFDocument::_serialize_meshes(Ref<GLTFState> state) {
generated_indices.write[k + 2] = k + 1;
}
}
- primitive["indices"] = _encode_accessor_as_ints(state, generated_indices, true);
+ primitive["indices"] = _encode_accessor_as_ints(p_state, generated_indices, true);
}
}
}
@@ -2455,12 +2448,12 @@ Error GLTFDocument::_serialize_meshes(Ref<GLTFState> state) {
}
}
- t["POSITION"] = _encode_accessor_as_vec3(state, varr, true);
+ t["POSITION"] = _encode_accessor_as_vec3(p_state, varr, true);
}
Vector<Vector3> narr = array_morph[Mesh::ARRAY_NORMAL];
if (narr.size()) {
- t["NORMAL"] = _encode_accessor_as_vec3(state, narr, true);
+ t["NORMAL"] = _encode_accessor_as_vec3(p_state, narr, true);
}
Vector<real_t> tarr = array_morph[Mesh::ARRAY_TANGENT];
if (tarr.size()) {
@@ -2473,7 +2466,7 @@ Error GLTFDocument::_serialize_meshes(Ref<GLTFState> state) {
vec3.y = tarr[(i * 4) + 1];
vec3.z = tarr[(i * 4) + 2];
}
- t["TANGENT"] = _encode_accessor_as_vec3(state, attribs, true);
+ t["TANGENT"] = _encode_accessor_as_vec3(p_state, attribs, true);
}
targets.push_back(t);
}
@@ -2483,19 +2476,19 @@ Error GLTFDocument::_serialize_meshes(Ref<GLTFState> state) {
if (surface_i < instance_materials.size()) {
v = instance_materials.get(surface_i);
}
- Ref<BaseMaterial3D> mat = v;
+ Ref<Material> mat = v;
if (!mat.is_valid()) {
mat = import_mesh->get_surface_material(surface_i);
}
if (mat.is_valid()) {
- HashMap<Ref<BaseMaterial3D>, GLTFMaterialIndex>::Iterator material_cache_i = state->material_cache.find(mat);
+ HashMap<Ref<Material>, GLTFMaterialIndex>::Iterator material_cache_i = p_state->material_cache.find(mat);
if (material_cache_i && material_cache_i->value != -1) {
primitive["material"] = material_cache_i->value;
} else {
- GLTFMaterialIndex mat_i = state->materials.size();
- state->materials.push_back(mat);
+ GLTFMaterialIndex mat_i = p_state->materials.size();
+ p_state->materials.push_back(mat);
primitive["material"] = mat_i;
- state->material_cache.insert(mat, mat_i);
+ p_state->material_cache.insert(mat, mat_i);
}
}
@@ -2512,8 +2505,8 @@ Error GLTFDocument::_serialize_meshes(Ref<GLTFState> state) {
weights.resize(target_names.size());
for (int name_i = 0; name_i < target_names.size(); name_i++) {
real_t weight = 0.0;
- if (name_i < state->meshes.write[gltf_mesh_i]->get_blend_weights().size()) {
- weight = state->meshes.write[gltf_mesh_i]->get_blend_weights()[name_i];
+ if (name_i < p_state->meshes.write[gltf_mesh_i]->get_blend_weights().size()) {
+ weight = p_state->meshes.write[gltf_mesh_i]->get_blend_weights()[name_i];
}
weights[name_i] = weight;
}
@@ -2533,18 +2526,18 @@ Error GLTFDocument::_serialize_meshes(Ref<GLTFState> state) {
if (!meshes.size()) {
return OK;
}
- state->json["meshes"] = meshes;
+ p_state->json["meshes"] = meshes;
print_verbose("glTF: Total meshes: " + itos(meshes.size()));
return OK;
}
-Error GLTFDocument::_parse_meshes(Ref<GLTFState> state) {
- if (!state->json.has("meshes")) {
+Error GLTFDocument::_parse_meshes(Ref<GLTFState> p_state) {
+ if (!p_state->json.has("meshes")) {
return OK;
}
- Array meshes = state->json["meshes"];
+ Array meshes = p_state->json["meshes"];
for (GLTFMeshIndex i = 0; i < meshes.size(); i++) {
print_verbose("glTF: Parsing mesh: " + itos(i));
Dictionary d = meshes[i];
@@ -2563,7 +2556,7 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> state) {
if (d.has("name") && !String(d["name"]).is_empty()) {
mesh_name = d["name"];
}
- import_mesh->set_name(_gen_unique_name(state, vformat("%s_%s", state->scene_name, mesh_name)));
+ import_mesh->set_name(_gen_unique_name(p_state, vformat("%s_%s", p_state->scene_name, mesh_name)));
for (int j = 0; j < primitives.size(); j++) {
uint32_t flags = 0;
@@ -2599,21 +2592,21 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> state) {
ERR_FAIL_COND_V(!a.has("POSITION"), ERR_PARSE_ERROR);
int32_t vertex_num = 0;
if (a.has("POSITION")) {
- PackedVector3Array vertices = _decode_accessor_as_vec3(state, a["POSITION"], true);
+ PackedVector3Array vertices = _decode_accessor_as_vec3(p_state, a["POSITION"], true);
array[Mesh::ARRAY_VERTEX] = vertices;
vertex_num = vertices.size();
}
if (a.has("NORMAL")) {
- array[Mesh::ARRAY_NORMAL] = _decode_accessor_as_vec3(state, a["NORMAL"], true);
+ array[Mesh::ARRAY_NORMAL] = _decode_accessor_as_vec3(p_state, a["NORMAL"], true);
}
if (a.has("TANGENT")) {
- array[Mesh::ARRAY_TANGENT] = _decode_accessor_as_floats(state, a["TANGENT"], true);
+ array[Mesh::ARRAY_TANGENT] = _decode_accessor_as_floats(p_state, a["TANGENT"], true);
}
if (a.has("TEXCOORD_0")) {
- array[Mesh::ARRAY_TEX_UV] = _decode_accessor_as_vec2(state, a["TEXCOORD_0"], true);
+ array[Mesh::ARRAY_TEX_UV] = _decode_accessor_as_vec2(p_state, a["TEXCOORD_0"], true);
}
if (a.has("TEXCOORD_1")) {
- array[Mesh::ARRAY_TEX_UV2] = _decode_accessor_as_vec2(state, a["TEXCOORD_1"], true);
+ array[Mesh::ARRAY_TEX_UV2] = _decode_accessor_as_vec2(p_state, a["TEXCOORD_1"], true);
}
for (int custom_i = 0; custom_i < 3; custom_i++) {
Vector<float> cur_custom;
@@ -2624,12 +2617,12 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> state) {
String gltf_texcoord_key = vformat("TEXCOORD_%d", texcoord_i);
int num_channels = 0;
if (a.has(gltf_texcoord_key)) {
- texcoord_first = _decode_accessor_as_vec2(state, a[gltf_texcoord_key], true);
+ texcoord_first = _decode_accessor_as_vec2(p_state, a[gltf_texcoord_key], true);
num_channels = 2;
}
gltf_texcoord_key = vformat("TEXCOORD_%d", texcoord_i + 1);
if (a.has(gltf_texcoord_key)) {
- texcoord_second = _decode_accessor_as_vec2(state, a[gltf_texcoord_key], true);
+ texcoord_second = _decode_accessor_as_vec2(p_state, a[gltf_texcoord_key], true);
num_channels = 4;
}
if (!num_channels) {
@@ -2670,14 +2663,14 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> state) {
}
}
if (a.has("COLOR_0")) {
- array[Mesh::ARRAY_COLOR] = _decode_accessor_as_color(state, a["COLOR_0"], true);
+ array[Mesh::ARRAY_COLOR] = _decode_accessor_as_color(p_state, a["COLOR_0"], true);
has_vertex_color = true;
}
if (a.has("JOINTS_0") && !a.has("JOINTS_1")) {
- array[Mesh::ARRAY_BONES] = _decode_accessor_as_ints(state, a["JOINTS_0"], true);
+ array[Mesh::ARRAY_BONES] = _decode_accessor_as_ints(p_state, a["JOINTS_0"], true);
} else if (a.has("JOINTS_0") && a.has("JOINTS_1")) {
- PackedInt32Array joints_0 = _decode_accessor_as_ints(state, a["JOINTS_0"], true);
- PackedInt32Array joints_1 = _decode_accessor_as_ints(state, a["JOINTS_1"], true);
+ PackedInt32Array joints_0 = _decode_accessor_as_ints(p_state, a["JOINTS_0"], true);
+ PackedInt32Array joints_1 = _decode_accessor_as_ints(p_state, a["JOINTS_1"], true);
ERR_FAIL_COND_V(joints_0.size() != joints_1.size(), ERR_INVALID_DATA);
int32_t weight_8_count = JOINT_GROUP_SIZE * 2;
Vector<int> joints;
@@ -2695,7 +2688,7 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> state) {
array[Mesh::ARRAY_BONES] = joints;
}
if (a.has("WEIGHTS_0") && !a.has("WEIGHTS_1")) {
- Vector<float> weights = _decode_accessor_as_floats(state, a["WEIGHTS_0"], true);
+ Vector<float> weights = _decode_accessor_as_floats(p_state, a["WEIGHTS_0"], true);
{ //gltf does not seem to normalize the weights for some reason..
int wc = weights.size();
float *w = weights.ptrw();
@@ -2716,8 +2709,8 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> state) {
}
array[Mesh::ARRAY_WEIGHTS] = weights;
} else if (a.has("WEIGHTS_0") && a.has("WEIGHTS_1")) {
- Vector<float> weights_0 = _decode_accessor_as_floats(state, a["WEIGHTS_0"], true);
- Vector<float> weights_1 = _decode_accessor_as_floats(state, a["WEIGHTS_1"], true);
+ Vector<float> weights_0 = _decode_accessor_as_floats(p_state, a["WEIGHTS_0"], true);
+ Vector<float> weights_1 = _decode_accessor_as_floats(p_state, a["WEIGHTS_1"], true);
Vector<float> weights;
ERR_FAIL_COND_V(weights_0.size() != weights_1.size(), ERR_INVALID_DATA);
int32_t weight_8_count = JOINT_GROUP_SIZE * 2;
@@ -2762,7 +2755,7 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> state) {
}
if (p.has("indices")) {
- Vector<int> indices = _decode_accessor_as_ints(state, p["indices"], false);
+ Vector<int> indices = _decode_accessor_as_ints(p_state, p["indices"], false);
if (primitive == Mesh::PRIMITIVE_TRIANGLES) {
//swap around indices, convert ccw to cw for front face
@@ -2836,7 +2829,7 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> state) {
}
if (t.has("POSITION")) {
- Vector<Vector3> varr = _decode_accessor_as_vec3(state, t["POSITION"], true);
+ Vector<Vector3> varr = _decode_accessor_as_vec3(p_state, t["POSITION"], true);
const Vector<Vector3> src_varr = array[Mesh::ARRAY_VERTEX];
const int size = src_varr.size();
ERR_FAIL_COND_V(size == 0, ERR_PARSE_ERROR);
@@ -2858,7 +2851,7 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> state) {
array_copy[Mesh::ARRAY_VERTEX] = varr;
}
if (t.has("NORMAL")) {
- Vector<Vector3> narr = _decode_accessor_as_vec3(state, t["NORMAL"], true);
+ Vector<Vector3> narr = _decode_accessor_as_vec3(p_state, t["NORMAL"], true);
const Vector<Vector3> src_narr = array[Mesh::ARRAY_NORMAL];
int size = src_narr.size();
ERR_FAIL_COND_V(size == 0, ERR_PARSE_ERROR);
@@ -2880,7 +2873,7 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> state) {
array_copy[Mesh::ARRAY_NORMAL] = narr;
}
if (t.has("TANGENT")) {
- const Vector<Vector3> tangents_v3 = _decode_accessor_as_vec3(state, t["TANGENT"], true);
+ const Vector<Vector3> tangents_v3 = _decode_accessor_as_vec3(p_state, t["TANGENT"], true);
const Vector<float> src_tangents = array[Mesh::ARRAY_TANGENT];
ERR_FAIL_COND_V(src_tangents.size() == 0, ERR_PARSE_ERROR);
@@ -2936,16 +2929,18 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> state) {
}
}
- Ref<BaseMaterial3D> mat;
+ Ref<Material> mat;
String mat_name;
- if (!state->discard_meshes_and_materials) {
+ if (!p_state->discard_meshes_and_materials) {
if (p.has("material")) {
const int material = p["material"];
- ERR_FAIL_INDEX_V(material, state->materials.size(), ERR_FILE_CORRUPT);
- Ref<BaseMaterial3D> mat3d = state->materials[material];
+ ERR_FAIL_INDEX_V(material, p_state->materials.size(), ERR_FILE_CORRUPT);
+ Ref<Material> mat3d = p_state->materials[material];
ERR_FAIL_NULL_V(mat3d, ERR_FILE_CORRUPT);
- if (has_vertex_color) {
- mat3d->set_flag(BaseMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true);
+
+ Ref<BaseMaterial3D> base_material = mat3d;
+ if (has_vertex_color && base_material.is_valid()) {
+ base_material->set_flag(BaseMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true);
}
mat = mat3d;
@@ -2953,7 +2948,7 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> state) {
Ref<StandardMaterial3D> mat3d;
mat3d.instantiate();
if (has_vertex_color) {
- mat3d->set_flag(BaseMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true);
+ mat3d->set_flag(StandardMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true);
}
mat = mat3d;
}
@@ -2982,22 +2977,22 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> state) {
mesh->set_blend_weights(blend_weights);
mesh->set_mesh(import_mesh);
- state->meshes.push_back(mesh);
+ p_state->meshes.push_back(mesh);
}
- print_verbose("glTF: Total meshes: " + itos(state->meshes.size()));
+ print_verbose("glTF: Total meshes: " + itos(p_state->meshes.size()));
return OK;
}
-Error GLTFDocument::_serialize_images(Ref<GLTFState> state, const String &p_path) {
+Error GLTFDocument::_serialize_images(Ref<GLTFState> p_state, const String &p_path) {
Array images;
- for (int i = 0; i < state->images.size(); i++) {
+ for (int i = 0; i < p_state->images.size(); i++) {
Dictionary d;
- ERR_CONTINUE(state->images[i].is_null());
+ ERR_CONTINUE(p_state->images[i].is_null());
- Ref<Image> image = state->images[i]->get_image();
+ Ref<Image> image = p_state->images[i]->get_image();
ERR_CONTINUE(image.is_null());
if (p_path.to_lower().ends_with("glb") || p_path.is_empty()) {
@@ -3008,8 +3003,8 @@ Error GLTFDocument::_serialize_images(Ref<GLTFState> state, const String &p_path
const GLTFBufferIndex bi = 0;
bv->buffer = bi;
- bv->byte_offset = state->buffers[bi].size();
- ERR_FAIL_INDEX_V(bi, state->buffers.size(), ERR_PARAMETER_RANGE_ERROR);
+ bv->byte_offset = p_state->buffers[bi].size();
+ ERR_FAIL_INDEX_V(bi, p_state->buffers.size(), ERR_PARAMETER_RANGE_ERROR);
Vector<uint8_t> buffer;
Ref<ImageTexture> img_tex = image;
@@ -3020,21 +3015,21 @@ Error GLTFDocument::_serialize_images(Ref<GLTFState> state, const String &p_path
ERR_FAIL_COND_V_MSG(err, err, "Can't convert image to PNG.");
bv->byte_length = buffer.size();
- state->buffers.write[bi].resize(state->buffers[bi].size() + bv->byte_length);
- memcpy(&state->buffers.write[bi].write[bv->byte_offset], buffer.ptr(), buffer.size());
- ERR_FAIL_COND_V(bv->byte_offset + bv->byte_length > state->buffers[bi].size(), ERR_FILE_CORRUPT);
+ p_state->buffers.write[bi].resize(p_state->buffers[bi].size() + bv->byte_length);
+ memcpy(&p_state->buffers.write[bi].write[bv->byte_offset], buffer.ptr(), buffer.size());
+ ERR_FAIL_COND_V(bv->byte_offset + bv->byte_length > p_state->buffers[bi].size(), ERR_FILE_CORRUPT);
- state->buffer_views.push_back(bv);
- bvi = state->buffer_views.size() - 1;
+ p_state->buffer_views.push_back(bv);
+ bvi = p_state->buffer_views.size() - 1;
d["bufferView"] = bvi;
d["mimeType"] = "image/png";
} else {
ERR_FAIL_COND_V(p_path.is_empty(), ERR_INVALID_PARAMETER);
- String img_name = state->images[i]->get_name();
+ String img_name = p_state->images[i]->get_name();
if (img_name.is_empty()) {
img_name = itos(i);
}
- img_name = _gen_unique_name(state, img_name);
+ img_name = _gen_unique_name(p_state, img_name);
img_name = img_name.pad_zeros(3) + ".png";
String texture_dir = "textures";
String path = p_path.get_base_dir();
@@ -3049,25 +3044,25 @@ Error GLTFDocument::_serialize_images(Ref<GLTFState> state, const String &p_path
images.push_back(d);
}
- print_verbose("Total images: " + itos(state->images.size()));
+ print_verbose("Total images: " + itos(p_state->images.size()));
if (!images.size()) {
return OK;
}
- state->json["images"] = images;
+ p_state->json["images"] = images;
return OK;
}
-Error GLTFDocument::_parse_images(Ref<GLTFState> state, const String &p_base_path) {
- ERR_FAIL_NULL_V(state, ERR_INVALID_PARAMETER);
- if (!state->json.has("images")) {
+Error GLTFDocument::_parse_images(Ref<GLTFState> p_state, const String &p_base_path) {
+ ERR_FAIL_NULL_V(p_state, ERR_INVALID_PARAMETER);
+ if (!p_state->json.has("images")) {
return OK;
}
// Ref: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#images
- const Array &images = state->json["images"];
+ const Array &images = p_state->json["images"];
for (int i = 0; i < images.size(); i++) {
const Dictionary &d = images[i];
@@ -3105,7 +3100,7 @@ Error GLTFDocument::_parse_images(Ref<GLTFState> state, const String &p_base_pat
!uri.begins_with("data:image/png;base64") &&
!uri.begins_with("data:image/jpeg;base64")) {
WARN_PRINT(vformat("glTF: Image index '%d' uses an unsupported URI data type: %s. Skipping it.", i, uri));
- state->images.push_back(Ref<Texture2D>()); // Placeholder to keep count.
+ p_state->images.push_back(Ref<Texture2D>()); // Placeholder to keep count.
continue;
}
data = _parse_base64_uri(uri);
@@ -3130,23 +3125,23 @@ Error GLTFDocument::_parse_images(Ref<GLTFState> state, const String &p_base_pat
// the material), so we do this only as fallback.
Ref<Texture2D> texture = ResourceLoader::load(uri);
if (texture.is_valid()) {
- state->images.push_back(texture);
+ p_state->images.push_back(texture);
continue;
} else if (mimetype == "image/png" || mimetype == "image/jpeg") {
// Fallback to loading as byte array.
// This enables us to support the spec's requirement that we honor mimetype
// regardless of file URI.
- data = FileAccess::get_file_as_array(uri);
+ data = FileAccess::get_file_as_bytes(uri);
if (data.size() == 0) {
WARN_PRINT(vformat("glTF: Image index '%d' couldn't be loaded as a buffer of MIME type '%s' from URI: %s. Skipping it.", i, mimetype, uri));
- state->images.push_back(Ref<Texture2D>()); // Placeholder to keep count.
+ p_state->images.push_back(Ref<Texture2D>()); // Placeholder to keep count.
continue;
}
data_ptr = data.ptr();
data_size = data.size();
} else {
WARN_PRINT(vformat("glTF: Image index '%d' couldn't be loaded from URI: %s. Skipping it.", i, uri));
- state->images.push_back(Ref<Texture2D>()); // Placeholder to keep count.
+ p_state->images.push_back(Ref<Texture2D>()); // Placeholder to keep count.
continue;
}
}
@@ -3157,16 +3152,16 @@ Error GLTFDocument::_parse_images(Ref<GLTFState> state, const String &p_base_pat
const GLTFBufferViewIndex bvi = d["bufferView"];
- ERR_FAIL_INDEX_V(bvi, state->buffer_views.size(), ERR_PARAMETER_RANGE_ERROR);
+ ERR_FAIL_INDEX_V(bvi, p_state->buffer_views.size(), ERR_PARAMETER_RANGE_ERROR);
- Ref<GLTFBufferView> bv = state->buffer_views[bvi];
+ Ref<GLTFBufferView> bv = p_state->buffer_views[bvi];
const GLTFBufferIndex bi = bv->buffer;
- ERR_FAIL_INDEX_V(bi, state->buffers.size(), ERR_PARAMETER_RANGE_ERROR);
+ ERR_FAIL_INDEX_V(bi, p_state->buffers.size(), ERR_PARAMETER_RANGE_ERROR);
- ERR_FAIL_COND_V(bv->byte_offset + bv->byte_length > state->buffers[bi].size(), ERR_FILE_CORRUPT);
+ ERR_FAIL_COND_V(bv->byte_offset + bv->byte_length > p_state->buffers[bi].size(), ERR_FILE_CORRUPT);
- data_ptr = &state->buffers[bi][bv->byte_offset];
+ data_ptr = &p_state->buffers[bi][bv->byte_offset];
data_size = bv->byte_length;
}
@@ -3199,26 +3194,26 @@ Error GLTFDocument::_parse_images(Ref<GLTFState> state, const String &p_base_pat
// Now we've done our best, fix your scenes.
if (img.is_null()) {
ERR_PRINT(vformat("glTF: Couldn't load image index '%d' with its given mimetype: %s.", i, mimetype));
- state->images.push_back(Ref<Texture2D>());
+ p_state->images.push_back(Ref<Texture2D>());
continue;
}
- state->images.push_back(ImageTexture::create_from_image(img));
+ p_state->images.push_back(ImageTexture::create_from_image(img));
}
- print_verbose("glTF: Total images: " + itos(state->images.size()));
+ print_verbose("glTF: Total images: " + itos(p_state->images.size()));
return OK;
}
-Error GLTFDocument::_serialize_textures(Ref<GLTFState> state) {
- if (!state->textures.size()) {
+Error GLTFDocument::_serialize_textures(Ref<GLTFState> p_state) {
+ if (!p_state->textures.size()) {
return OK;
}
Array textures;
- for (int32_t i = 0; i < state->textures.size(); i++) {
+ for (int32_t i = 0; i < p_state->textures.size(); i++) {
Dictionary d;
- Ref<GLTFTexture> t = state->textures[i];
+ Ref<GLTFTexture> t = p_state->textures[i];
ERR_CONTINUE(t->get_src_image() == -1);
d["source"] = t->get_src_image();
@@ -3228,17 +3223,17 @@ Error GLTFDocument::_serialize_textures(Ref<GLTFState> state) {
}
textures.push_back(d);
}
- state->json["textures"] = textures;
+ p_state->json["textures"] = textures;
return OK;
}
-Error GLTFDocument::_parse_textures(Ref<GLTFState> state) {
- if (!state->json.has("textures")) {
+Error GLTFDocument::_parse_textures(Ref<GLTFState> p_state) {
+ if (!p_state->json.has("textures")) {
return OK;
}
- const Array &textures = state->json["textures"];
+ const Array &textures = p_state->json["textures"];
for (GLTFTextureIndex i = 0; i < textures.size(); i++) {
const Dictionary &d = textures[i];
@@ -3252,96 +3247,96 @@ Error GLTFDocument::_parse_textures(Ref<GLTFState> state) {
} else {
t->set_sampler(-1);
}
- state->textures.push_back(t);
+ p_state->textures.push_back(t);
}
return OK;
}
-GLTFTextureIndex GLTFDocument::_set_texture(Ref<GLTFState> state, Ref<Texture2D> p_texture, StandardMaterial3D::TextureFilter p_filter_mode, bool p_repeats) {
+GLTFTextureIndex GLTFDocument::_set_texture(Ref<GLTFState> p_state, Ref<Texture2D> p_texture, StandardMaterial3D::TextureFilter p_filter_mode, bool p_repeats) {
ERR_FAIL_COND_V(p_texture.is_null(), -1);
Ref<GLTFTexture> gltf_texture;
gltf_texture.instantiate();
ERR_FAIL_COND_V(p_texture->get_image().is_null(), -1);
- GLTFImageIndex gltf_src_image_i = state->images.size();
- state->images.push_back(p_texture);
+ GLTFImageIndex gltf_src_image_i = p_state->images.size();
+ p_state->images.push_back(p_texture);
gltf_texture->set_src_image(gltf_src_image_i);
- gltf_texture->set_sampler(_set_sampler_for_mode(state, p_filter_mode, p_repeats));
- GLTFTextureIndex gltf_texture_i = state->textures.size();
- state->textures.push_back(gltf_texture);
+ gltf_texture->set_sampler(_set_sampler_for_mode(p_state, p_filter_mode, p_repeats));
+ GLTFTextureIndex gltf_texture_i = p_state->textures.size();
+ p_state->textures.push_back(gltf_texture);
return gltf_texture_i;
}
-Ref<Texture2D> GLTFDocument::_get_texture(Ref<GLTFState> state, const GLTFTextureIndex p_texture) {
- ERR_FAIL_INDEX_V(p_texture, state->textures.size(), Ref<Texture2D>());
- const GLTFImageIndex image = state->textures[p_texture]->get_src_image();
+Ref<Texture2D> GLTFDocument::_get_texture(Ref<GLTFState> p_state, const GLTFTextureIndex p_texture) {
+ ERR_FAIL_INDEX_V(p_texture, p_state->textures.size(), Ref<Texture2D>());
+ const GLTFImageIndex image = p_state->textures[p_texture]->get_src_image();
- ERR_FAIL_INDEX_V(image, state->images.size(), Ref<Texture2D>());
+ ERR_FAIL_INDEX_V(image, p_state->images.size(), Ref<Texture2D>());
- return state->images[image];
+ return p_state->images[image];
}
-GLTFTextureSamplerIndex GLTFDocument::_set_sampler_for_mode(Ref<GLTFState> state, StandardMaterial3D::TextureFilter p_filter_mode, bool p_repeats) {
- for (int i = 0; i < state->texture_samplers.size(); ++i) {
- if (state->texture_samplers[i]->get_filter_mode() == p_filter_mode) {
+GLTFTextureSamplerIndex GLTFDocument::_set_sampler_for_mode(Ref<GLTFState> p_state, StandardMaterial3D::TextureFilter p_filter_mode, bool p_repeats) {
+ for (int i = 0; i < p_state->texture_samplers.size(); ++i) {
+ if (p_state->texture_samplers[i]->get_filter_mode() == p_filter_mode) {
return i;
}
}
- GLTFTextureSamplerIndex gltf_sampler_i = state->texture_samplers.size();
+ GLTFTextureSamplerIndex gltf_sampler_i = p_state->texture_samplers.size();
Ref<GLTFTextureSampler> gltf_sampler;
gltf_sampler.instantiate();
gltf_sampler->set_filter_mode(p_filter_mode);
gltf_sampler->set_wrap_mode(p_repeats);
- state->texture_samplers.push_back(gltf_sampler);
+ p_state->texture_samplers.push_back(gltf_sampler);
return gltf_sampler_i;
}
-Ref<GLTFTextureSampler> GLTFDocument::_get_sampler_for_texture(Ref<GLTFState> state, const GLTFTextureIndex p_texture) {
- ERR_FAIL_INDEX_V(p_texture, state->textures.size(), Ref<Texture2D>());
- const GLTFTextureSamplerIndex sampler = state->textures[p_texture]->get_sampler();
+Ref<GLTFTextureSampler> GLTFDocument::_get_sampler_for_texture(Ref<GLTFState> p_state, const GLTFTextureIndex p_texture) {
+ ERR_FAIL_INDEX_V(p_texture, p_state->textures.size(), Ref<Texture2D>());
+ const GLTFTextureSamplerIndex sampler = p_state->textures[p_texture]->get_sampler();
if (sampler == -1) {
- return state->default_texture_sampler;
+ return p_state->default_texture_sampler;
} else {
- ERR_FAIL_INDEX_V(sampler, state->texture_samplers.size(), Ref<GLTFTextureSampler>());
+ ERR_FAIL_INDEX_V(sampler, p_state->texture_samplers.size(), Ref<GLTFTextureSampler>());
- return state->texture_samplers[sampler];
+ return p_state->texture_samplers[sampler];
}
}
-Error GLTFDocument::_serialize_texture_samplers(Ref<GLTFState> state) {
- if (!state->texture_samplers.size()) {
+Error GLTFDocument::_serialize_texture_samplers(Ref<GLTFState> p_state) {
+ if (!p_state->texture_samplers.size()) {
return OK;
}
Array samplers;
- for (int32_t i = 0; i < state->texture_samplers.size(); ++i) {
+ for (int32_t i = 0; i < p_state->texture_samplers.size(); ++i) {
Dictionary d;
- Ref<GLTFTextureSampler> s = state->texture_samplers[i];
+ Ref<GLTFTextureSampler> s = p_state->texture_samplers[i];
d["magFilter"] = s->get_mag_filter();
d["minFilter"] = s->get_min_filter();
d["wrapS"] = s->get_wrap_s();
d["wrapT"] = s->get_wrap_t();
samplers.push_back(d);
}
- state->json["samplers"] = samplers;
+ p_state->json["samplers"] = samplers;
return OK;
}
-Error GLTFDocument::_parse_texture_samplers(Ref<GLTFState> state) {
- state->default_texture_sampler.instantiate();
- state->default_texture_sampler->set_min_filter(GLTFTextureSampler::FilterMode::LINEAR_MIPMAP_LINEAR);
- state->default_texture_sampler->set_mag_filter(GLTFTextureSampler::FilterMode::LINEAR);
- state->default_texture_sampler->set_wrap_s(GLTFTextureSampler::WrapMode::REPEAT);
- state->default_texture_sampler->set_wrap_t(GLTFTextureSampler::WrapMode::REPEAT);
+Error GLTFDocument::_parse_texture_samplers(Ref<GLTFState> p_state) {
+ p_state->default_texture_sampler.instantiate();
+ p_state->default_texture_sampler->set_min_filter(GLTFTextureSampler::FilterMode::LINEAR_MIPMAP_LINEAR);
+ p_state->default_texture_sampler->set_mag_filter(GLTFTextureSampler::FilterMode::LINEAR);
+ p_state->default_texture_sampler->set_wrap_s(GLTFTextureSampler::WrapMode::REPEAT);
+ p_state->default_texture_sampler->set_wrap_t(GLTFTextureSampler::WrapMode::REPEAT);
- if (!state->json.has("samplers")) {
+ if (!p_state->json.has("samplers")) {
return OK;
}
- const Array &samplers = state->json["samplers"];
+ const Array &samplers = p_state->json["samplers"];
for (int i = 0; i < samplers.size(); ++i) {
const Dictionary &d = samplers[i];
@@ -3371,199 +3366,203 @@ Error GLTFDocument::_parse_texture_samplers(Ref<GLTFState> state) {
sampler->set_wrap_t(GLTFTextureSampler::WrapMode::DEFAULT);
}
- state->texture_samplers.push_back(sampler);
+ p_state->texture_samplers.push_back(sampler);
}
return OK;
}
-Error GLTFDocument::_serialize_materials(Ref<GLTFState> state) {
+Error GLTFDocument::_serialize_materials(Ref<GLTFState> p_state) {
Array materials;
- for (int32_t i = 0; i < state->materials.size(); i++) {
+ for (int32_t i = 0; i < p_state->materials.size(); i++) {
Dictionary d;
-
- Ref<BaseMaterial3D> material = state->materials[i];
+ Ref<Material> material = p_state->materials[i];
if (material.is_null()) {
materials.push_back(d);
continue;
}
if (!material->get_name().is_empty()) {
- d["name"] = _gen_unique_name(state, material->get_name());
+ d["name"] = _gen_unique_name(p_state, material->get_name());
+ }
+
+ Ref<BaseMaterial3D> base_material = material;
+ if (base_material.is_null()) {
+ materials.push_back(d);
+ continue;
}
+
+ Dictionary mr;
{
- Dictionary mr;
- {
- Array arr;
- const Color c = material->get_albedo().srgb_to_linear();
- arr.push_back(c.r);
- arr.push_back(c.g);
- arr.push_back(c.b);
- arr.push_back(c.a);
- mr["baseColorFactor"] = arr;
- }
- {
- Dictionary bct;
- Ref<Texture2D> albedo_texture = material->get_texture(BaseMaterial3D::TEXTURE_ALBEDO);
- GLTFTextureIndex gltf_texture_index = -1;
+ Array arr;
+ const Color c = base_material->get_albedo().srgb_to_linear();
+ arr.push_back(c.r);
+ arr.push_back(c.g);
+ arr.push_back(c.b);
+ arr.push_back(c.a);
+ mr["baseColorFactor"] = arr;
+ }
+ {
+ Dictionary bct;
+ Ref<Texture2D> albedo_texture = base_material->get_texture(BaseMaterial3D::TEXTURE_ALBEDO);
+ GLTFTextureIndex gltf_texture_index = -1;
- if (albedo_texture.is_valid() && albedo_texture->get_image().is_valid()) {
- albedo_texture->set_name(material->get_name() + "_albedo");
- gltf_texture_index = _set_texture(state, albedo_texture, material->get_texture_filter(), material->get_flag(BaseMaterial3D::FLAG_USE_TEXTURE_REPEAT));
- }
- if (gltf_texture_index != -1) {
- bct["index"] = gltf_texture_index;
- Dictionary extensions = _serialize_texture_transform_uv1(material);
- if (!extensions.is_empty()) {
- bct["extensions"] = extensions;
- state->use_khr_texture_transform = true;
- }
- mr["baseColorTexture"] = bct;
- }
+ if (albedo_texture.is_valid() && albedo_texture->get_image().is_valid()) {
+ albedo_texture->set_name(material->get_name() + "_albedo");
+ gltf_texture_index = _set_texture(p_state, albedo_texture, base_material->get_texture_filter(), base_material->get_flag(BaseMaterial3D::FLAG_USE_TEXTURE_REPEAT));
}
-
- mr["metallicFactor"] = material->get_metallic();
- mr["roughnessFactor"] = material->get_roughness();
- bool has_roughness = material->get_texture(BaseMaterial3D::TEXTURE_ROUGHNESS).is_valid() && material->get_texture(BaseMaterial3D::TEXTURE_ROUGHNESS)->get_image().is_valid();
- bool has_ao = material->get_feature(BaseMaterial3D::FEATURE_AMBIENT_OCCLUSION) && material->get_texture(BaseMaterial3D::TEXTURE_AMBIENT_OCCLUSION).is_valid();
- bool has_metalness = material->get_texture(BaseMaterial3D::TEXTURE_METALLIC).is_valid() && material->get_texture(BaseMaterial3D::TEXTURE_METALLIC)->get_image().is_valid();
- if (has_ao || has_roughness || has_metalness) {
- Dictionary mrt;
- Ref<Texture2D> roughness_texture = material->get_texture(BaseMaterial3D::TEXTURE_ROUGHNESS);
- BaseMaterial3D::TextureChannel roughness_channel = material->get_roughness_texture_channel();
- Ref<Texture2D> metallic_texture = material->get_texture(BaseMaterial3D::TEXTURE_METALLIC);
- BaseMaterial3D::TextureChannel metalness_channel = material->get_metallic_texture_channel();
- Ref<Texture2D> ao_texture = material->get_texture(BaseMaterial3D::TEXTURE_AMBIENT_OCCLUSION);
- BaseMaterial3D::TextureChannel ao_channel = material->get_ao_texture_channel();
- Ref<ImageTexture> orm_texture;
- orm_texture.instantiate();
- Ref<Image> orm_image;
- orm_image.instantiate();
- int32_t height = 0;
- int32_t width = 0;
- Ref<Image> ao_image;
- if (has_ao) {
- height = ao_texture->get_height();
- width = ao_texture->get_width();
- ao_image = ao_texture->get_image();
- Ref<ImageTexture> img_tex = ao_image;
- if (img_tex.is_valid()) {
- ao_image = img_tex->get_image();
- }
- if (ao_image->is_compressed()) {
- ao_image->decompress();
- }
+ if (gltf_texture_index != -1) {
+ bct["index"] = gltf_texture_index;
+ Dictionary extensions = _serialize_texture_transform_uv1(material);
+ if (!extensions.is_empty()) {
+ bct["extensions"] = extensions;
+ p_state->use_khr_texture_transform = true;
}
- Ref<Image> roughness_image;
- if (has_roughness) {
- height = roughness_texture->get_height();
- width = roughness_texture->get_width();
- roughness_image = roughness_texture->get_image();
- Ref<ImageTexture> img_tex = roughness_image;
- if (img_tex.is_valid()) {
- roughness_image = img_tex->get_image();
- }
- if (roughness_image->is_compressed()) {
- roughness_image->decompress();
- }
+ mr["baseColorTexture"] = bct;
+ }
+ }
+
+ mr["metallicFactor"] = base_material->get_metallic();
+ mr["roughnessFactor"] = base_material->get_roughness();
+ bool has_roughness = base_material->get_texture(BaseMaterial3D::TEXTURE_ROUGHNESS).is_valid() && base_material->get_texture(BaseMaterial3D::TEXTURE_ROUGHNESS)->get_image().is_valid();
+ bool has_ao = base_material->get_feature(BaseMaterial3D::FEATURE_AMBIENT_OCCLUSION) && base_material->get_texture(BaseMaterial3D::TEXTURE_AMBIENT_OCCLUSION).is_valid();
+ bool has_metalness = base_material->get_texture(BaseMaterial3D::TEXTURE_METALLIC).is_valid() && base_material->get_texture(BaseMaterial3D::TEXTURE_METALLIC)->get_image().is_valid();
+ if (has_ao || has_roughness || has_metalness) {
+ Dictionary mrt;
+ Ref<Texture2D> roughness_texture = base_material->get_texture(BaseMaterial3D::TEXTURE_ROUGHNESS);
+ BaseMaterial3D::TextureChannel roughness_channel = base_material->get_roughness_texture_channel();
+ Ref<Texture2D> metallic_texture = base_material->get_texture(BaseMaterial3D::TEXTURE_METALLIC);
+ BaseMaterial3D::TextureChannel metalness_channel = base_material->get_metallic_texture_channel();
+ Ref<Texture2D> ao_texture = base_material->get_texture(BaseMaterial3D::TEXTURE_AMBIENT_OCCLUSION);
+ BaseMaterial3D::TextureChannel ao_channel = base_material->get_ao_texture_channel();
+ Ref<ImageTexture> orm_texture;
+ orm_texture.instantiate();
+ Ref<Image> orm_image;
+ orm_image.instantiate();
+ int32_t height = 0;
+ int32_t width = 0;
+ Ref<Image> ao_image;
+ if (has_ao) {
+ height = ao_texture->get_height();
+ width = ao_texture->get_width();
+ ao_image = ao_texture->get_image();
+ Ref<ImageTexture> img_tex = ao_image;
+ if (img_tex.is_valid()) {
+ ao_image = img_tex->get_image();
}
- Ref<Image> metallness_image;
- if (has_metalness) {
- height = metallic_texture->get_height();
- width = metallic_texture->get_width();
- metallness_image = metallic_texture->get_image();
- Ref<ImageTexture> img_tex = metallness_image;
- if (img_tex.is_valid()) {
- metallness_image = img_tex->get_image();
- }
- if (metallness_image->is_compressed()) {
- metallness_image->decompress();
- }
+ if (ao_image->is_compressed()) {
+ ao_image->decompress();
}
- Ref<Texture2D> albedo_texture = material->get_texture(BaseMaterial3D::TEXTURE_ALBEDO);
- if (albedo_texture.is_valid() && albedo_texture->get_image().is_valid()) {
- height = albedo_texture->get_height();
- width = albedo_texture->get_width();
+ }
+ Ref<Image> roughness_image;
+ if (has_roughness) {
+ height = roughness_texture->get_height();
+ width = roughness_texture->get_width();
+ roughness_image = roughness_texture->get_image();
+ Ref<ImageTexture> img_tex = roughness_image;
+ if (img_tex.is_valid()) {
+ roughness_image = img_tex->get_image();
}
- orm_image->initialize_data(width, height, false, Image::FORMAT_RGBA8);
- if (ao_image.is_valid() && ao_image->get_size() != Vector2(width, height)) {
- ao_image->resize(width, height, Image::INTERPOLATE_LANCZOS);
+ if (roughness_image->is_compressed()) {
+ roughness_image->decompress();
}
- if (roughness_image.is_valid() && roughness_image->get_size() != Vector2(width, height)) {
- roughness_image->resize(width, height, Image::INTERPOLATE_LANCZOS);
+ }
+ Ref<Image> metallness_image;
+ if (has_metalness) {
+ height = metallic_texture->get_height();
+ width = metallic_texture->get_width();
+ metallness_image = metallic_texture->get_image();
+ Ref<ImageTexture> img_tex = metallness_image;
+ if (img_tex.is_valid()) {
+ metallness_image = img_tex->get_image();
}
- if (metallness_image.is_valid() && metallness_image->get_size() != Vector2(width, height)) {
- metallness_image->resize(width, height, Image::INTERPOLATE_LANCZOS);
+ if (metallness_image->is_compressed()) {
+ metallness_image->decompress();
}
- for (int32_t h = 0; h < height; h++) {
- for (int32_t w = 0; w < width; w++) {
- Color c = Color(1.0f, 1.0f, 1.0f);
- if (has_ao) {
- if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_RED == ao_channel) {
- c.r = ao_image->get_pixel(w, h).r;
- } else if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_GREEN == ao_channel) {
- c.r = ao_image->get_pixel(w, h).g;
- } else if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_BLUE == ao_channel) {
- c.r = ao_image->get_pixel(w, h).b;
- } else if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_ALPHA == ao_channel) {
- c.r = ao_image->get_pixel(w, h).a;
- }
+ }
+ Ref<Texture2D> albedo_texture = base_material->get_texture(BaseMaterial3D::TEXTURE_ALBEDO);
+ if (albedo_texture.is_valid() && albedo_texture->get_image().is_valid()) {
+ height = albedo_texture->get_height();
+ width = albedo_texture->get_width();
+ }
+ orm_image->initialize_data(width, height, false, Image::FORMAT_RGBA8);
+ if (ao_image.is_valid() && ao_image->get_size() != Vector2(width, height)) {
+ ao_image->resize(width, height, Image::INTERPOLATE_LANCZOS);
+ }
+ if (roughness_image.is_valid() && roughness_image->get_size() != Vector2(width, height)) {
+ roughness_image->resize(width, height, Image::INTERPOLATE_LANCZOS);
+ }
+ if (metallness_image.is_valid() && metallness_image->get_size() != Vector2(width, height)) {
+ metallness_image->resize(width, height, Image::INTERPOLATE_LANCZOS);
+ }
+ for (int32_t h = 0; h < height; h++) {
+ for (int32_t w = 0; w < width; w++) {
+ Color c = Color(1.0f, 1.0f, 1.0f);
+ if (has_ao) {
+ if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_RED == ao_channel) {
+ c.r = ao_image->get_pixel(w, h).r;
+ } else if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_GREEN == ao_channel) {
+ c.r = ao_image->get_pixel(w, h).g;
+ } else if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_BLUE == ao_channel) {
+ c.r = ao_image->get_pixel(w, h).b;
+ } else if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_ALPHA == ao_channel) {
+ c.r = ao_image->get_pixel(w, h).a;
}
- if (has_roughness) {
- if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_RED == roughness_channel) {
- c.g = roughness_image->get_pixel(w, h).r;
- } else if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_GREEN == roughness_channel) {
- c.g = roughness_image->get_pixel(w, h).g;
- } else if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_BLUE == roughness_channel) {
- c.g = roughness_image->get_pixel(w, h).b;
- } else if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_ALPHA == roughness_channel) {
- c.g = roughness_image->get_pixel(w, h).a;
- }
+ }
+ if (has_roughness) {
+ if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_RED == roughness_channel) {
+ c.g = roughness_image->get_pixel(w, h).r;
+ } else if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_GREEN == roughness_channel) {
+ c.g = roughness_image->get_pixel(w, h).g;
+ } else if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_BLUE == roughness_channel) {
+ c.g = roughness_image->get_pixel(w, h).b;
+ } else if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_ALPHA == roughness_channel) {
+ c.g = roughness_image->get_pixel(w, h).a;
}
- if (has_metalness) {
- if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_RED == metalness_channel) {
- c.b = metallness_image->get_pixel(w, h).r;
- } else if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_GREEN == metalness_channel) {
- c.b = metallness_image->get_pixel(w, h).g;
- } else if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_BLUE == metalness_channel) {
- c.b = metallness_image->get_pixel(w, h).b;
- } else if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_ALPHA == metalness_channel) {
- c.b = metallness_image->get_pixel(w, h).a;
- }
+ }
+ if (has_metalness) {
+ if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_RED == metalness_channel) {
+ c.b = metallness_image->get_pixel(w, h).r;
+ } else if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_GREEN == metalness_channel) {
+ c.b = metallness_image->get_pixel(w, h).g;
+ } else if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_BLUE == metalness_channel) {
+ c.b = metallness_image->get_pixel(w, h).b;
+ } else if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_ALPHA == metalness_channel) {
+ c.b = metallness_image->get_pixel(w, h).a;
}
- orm_image->set_pixel(w, h, c);
}
+ orm_image->set_pixel(w, h, c);
}
- orm_image->generate_mipmaps();
- 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");
- orm_texture_index = _set_texture(state, orm_texture, material->get_texture_filter(), material->get_flag(BaseMaterial3D::FLAG_USE_TEXTURE_REPEAT));
- }
- if (has_ao) {
- Dictionary occt;
- occt["index"] = orm_texture_index;
- d["occlusionTexture"] = occt;
- }
- if (has_roughness || has_metalness) {
- mrt["index"] = orm_texture_index;
- Dictionary extensions = _serialize_texture_transform_uv1(material);
- if (!extensions.is_empty()) {
- mrt["extensions"] = extensions;
- state->use_khr_texture_transform = true;
- }
- mr["metallicRoughnessTexture"] = mrt;
+ }
+ orm_image->generate_mipmaps();
+ 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");
+ orm_texture_index = _set_texture(p_state, orm_texture, base_material->get_texture_filter(), base_material->get_flag(BaseMaterial3D::FLAG_USE_TEXTURE_REPEAT));
+ }
+ if (has_ao) {
+ Dictionary occt;
+ occt["index"] = orm_texture_index;
+ d["occlusionTexture"] = occt;
+ }
+ if (has_roughness || has_metalness) {
+ mrt["index"] = orm_texture_index;
+ Dictionary extensions = _serialize_texture_transform_uv1(material);
+ if (!extensions.is_empty()) {
+ mrt["extensions"] = extensions;
+ p_state->use_khr_texture_transform = true;
}
+ mr["metallicRoughnessTexture"] = mrt;
}
- d["pbrMetallicRoughness"] = mr;
}
- if (material->get_feature(BaseMaterial3D::FEATURE_NORMAL_MAPPING)) {
+ d["pbrMetallicRoughness"] = mr;
+ if (base_material->get_feature(BaseMaterial3D::FEATURE_NORMAL_MAPPING)) {
Dictionary nt;
Ref<ImageTexture> tex;
tex.instantiate();
{
- Ref<Texture2D> normal_texture = material->get_texture(BaseMaterial3D::TEXTURE_NORMAL);
+ Ref<Texture2D> normal_texture = base_material->get_texture(BaseMaterial3D::TEXTURE_NORMAL);
if (normal_texture.is_valid()) {
// Code for uncompressing RG normal maps
Ref<Image> img = normal_texture->get_image();
@@ -3593,30 +3592,31 @@ Error GLTFDocument::_serialize_materials(Ref<GLTFState> state) {
GLTFTextureIndex gltf_texture_index = -1;
if (tex.is_valid() && tex->get_image().is_valid()) {
tex->set_name(material->get_name() + "_normal");
- gltf_texture_index = _set_texture(state, tex, material->get_texture_filter(), material->get_flag(BaseMaterial3D::FLAG_USE_TEXTURE_REPEAT));
+ gltf_texture_index = _set_texture(p_state, tex, base_material->get_texture_filter(), base_material->get_flag(BaseMaterial3D::FLAG_USE_TEXTURE_REPEAT));
}
- nt["scale"] = material->get_normal_scale();
+ nt["scale"] = base_material->get_normal_scale();
if (gltf_texture_index != -1) {
nt["index"] = gltf_texture_index;
d["normalTexture"] = nt;
}
}
- if (material->get_feature(BaseMaterial3D::FEATURE_EMISSION)) {
- const Color c = material->get_emission().linear_to_srgb();
+ if (base_material->get_feature(BaseMaterial3D::FEATURE_EMISSION)) {
+ const Color c = base_material->get_emission().linear_to_srgb();
Array arr;
arr.push_back(c.r);
arr.push_back(c.g);
arr.push_back(c.b);
d["emissiveFactor"] = arr;
}
- if (material->get_feature(BaseMaterial3D::FEATURE_EMISSION)) {
+
+ if (base_material->get_feature(BaseMaterial3D::FEATURE_EMISSION)) {
Dictionary et;
- Ref<Texture2D> emission_texture = material->get_texture(BaseMaterial3D::TEXTURE_EMISSION);
+ Ref<Texture2D> emission_texture = base_material->get_texture(BaseMaterial3D::TEXTURE_EMISSION);
GLTFTextureIndex gltf_texture_index = -1;
if (emission_texture.is_valid() && emission_texture->get_image().is_valid()) {
emission_texture->set_name(material->get_name() + "_emission");
- gltf_texture_index = _set_texture(state, emission_texture, material->get_texture_filter(), material->get_flag(BaseMaterial3D::FLAG_USE_TEXTURE_REPEAT));
+ gltf_texture_index = _set_texture(p_state, emission_texture, base_material->get_texture_filter(), base_material->get_flag(BaseMaterial3D::FLAG_USE_TEXTURE_REPEAT));
}
if (gltf_texture_index != -1) {
@@ -3624,33 +3624,36 @@ Error GLTFDocument::_serialize_materials(Ref<GLTFState> state) {
d["emissiveTexture"] = et;
}
}
- const bool ds = material->get_cull_mode() == BaseMaterial3D::CULL_DISABLED;
+
+ const bool ds = base_material->get_cull_mode() == BaseMaterial3D::CULL_DISABLED;
if (ds) {
d["doubleSided"] = ds;
}
- if (material->get_transparency() == BaseMaterial3D::TRANSPARENCY_ALPHA_SCISSOR) {
+
+ if (base_material->get_transparency() == BaseMaterial3D::TRANSPARENCY_ALPHA_SCISSOR) {
d["alphaMode"] = "MASK";
- d["alphaCutoff"] = material->get_alpha_scissor_threshold();
- } else if (material->get_transparency() != BaseMaterial3D::TRANSPARENCY_DISABLED) {
+ d["alphaCutoff"] = base_material->get_alpha_scissor_threshold();
+ } else if (base_material->get_transparency() != BaseMaterial3D::TRANSPARENCY_DISABLED) {
d["alphaMode"] = "BLEND";
}
+
materials.push_back(d);
}
if (!materials.size()) {
return OK;
}
- state->json["materials"] = materials;
- print_verbose("Total materials: " + itos(state->materials.size()));
+ p_state->json["materials"] = materials;
+ print_verbose("Total materials: " + itos(p_state->materials.size()));
return OK;
}
-Error GLTFDocument::_parse_materials(Ref<GLTFState> state) {
- if (!state->json.has("materials")) {
+Error GLTFDocument::_parse_materials(Ref<GLTFState> p_state) {
+ if (!p_state->json.has("materials")) {
return OK;
}
- const Array &materials = state->json["materials"];
+ const Array &materials = p_state->json["materials"];
for (GLTFMaterialIndex i = 0; i < materials.size(); i++) {
const Dictionary &d = materials[i];
@@ -3675,12 +3678,12 @@ Error GLTFDocument::_parse_materials(Ref<GLTFState> state) {
if (sgm.has("diffuseTexture")) {
const Dictionary &diffuse_texture_dict = sgm["diffuseTexture"];
if (diffuse_texture_dict.has("index")) {
- Ref<GLTFTextureSampler> diffuse_sampler = _get_sampler_for_texture(state, diffuse_texture_dict["index"]);
+ Ref<GLTFTextureSampler> diffuse_sampler = _get_sampler_for_texture(p_state, diffuse_texture_dict["index"]);
if (diffuse_sampler.is_valid()) {
material->set_texture_filter(diffuse_sampler->get_filter_mode());
material->set_flag(BaseMaterial3D::FLAG_USE_TEXTURE_REPEAT, diffuse_sampler->get_wrap_mode());
}
- Ref<Texture2D> diffuse_texture = _get_texture(state, diffuse_texture_dict["index"]);
+ Ref<Texture2D> diffuse_texture = _get_texture(p_state, diffuse_texture_dict["index"]);
if (diffuse_texture.is_valid()) {
spec_gloss->diffuse_img = diffuse_texture->get_image();
material->set_texture(BaseMaterial3D::TEXTURE_ALBEDO, diffuse_texture);
@@ -3708,7 +3711,7 @@ Error GLTFDocument::_parse_materials(Ref<GLTFState> state) {
if (sgm.has("specularGlossinessTexture")) {
const Dictionary &spec_gloss_texture = sgm["specularGlossinessTexture"];
if (spec_gloss_texture.has("index")) {
- const Ref<Texture2D> orig_texture = _get_texture(state, spec_gloss_texture["index"]);
+ const Ref<Texture2D> orig_texture = _get_texture(p_state, spec_gloss_texture["index"]);
if (orig_texture.is_valid()) {
spec_gloss->spec_gloss_img = orig_texture->get_image();
}
@@ -3728,10 +3731,10 @@ Error GLTFDocument::_parse_materials(Ref<GLTFState> state) {
if (mr.has("baseColorTexture")) {
const Dictionary &bct = mr["baseColorTexture"];
if (bct.has("index")) {
- Ref<GLTFTextureSampler> bct_sampler = _get_sampler_for_texture(state, bct["index"]);
+ Ref<GLTFTextureSampler> bct_sampler = _get_sampler_for_texture(p_state, bct["index"]);
material->set_texture_filter(bct_sampler->get_filter_mode());
material->set_flag(BaseMaterial3D::FLAG_USE_TEXTURE_REPEAT, bct_sampler->get_wrap_mode());
- material->set_texture(BaseMaterial3D::TEXTURE_ALBEDO, _get_texture(state, bct["index"]));
+ material->set_texture(BaseMaterial3D::TEXTURE_ALBEDO, _get_texture(p_state, bct["index"]));
}
if (!mr.has("baseColorFactor")) {
material->set_albedo(Color(1, 1, 1));
@@ -3754,7 +3757,7 @@ Error GLTFDocument::_parse_materials(Ref<GLTFState> state) {
if (mr.has("metallicRoughnessTexture")) {
const Dictionary &bct = mr["metallicRoughnessTexture"];
if (bct.has("index")) {
- const Ref<Texture2D> t = _get_texture(state, bct["index"]);
+ const Ref<Texture2D> t = _get_texture(p_state, bct["index"]);
material->set_texture(BaseMaterial3D::TEXTURE_METALLIC, t);
material->set_metallic_texture_channel(BaseMaterial3D::TEXTURE_CHANNEL_BLUE);
material->set_texture(BaseMaterial3D::TEXTURE_ROUGHNESS, t);
@@ -3772,7 +3775,7 @@ Error GLTFDocument::_parse_materials(Ref<GLTFState> state) {
if (d.has("normalTexture")) {
const Dictionary &bct = d["normalTexture"];
if (bct.has("index")) {
- material->set_texture(BaseMaterial3D::TEXTURE_NORMAL, _get_texture(state, bct["index"]));
+ material->set_texture(BaseMaterial3D::TEXTURE_NORMAL, _get_texture(p_state, bct["index"]));
material->set_feature(BaseMaterial3D::FEATURE_NORMAL_MAPPING, true);
}
if (bct.has("scale")) {
@@ -3782,7 +3785,7 @@ Error GLTFDocument::_parse_materials(Ref<GLTFState> state) {
if (d.has("occlusionTexture")) {
const Dictionary &bct = d["occlusionTexture"];
if (bct.has("index")) {
- material->set_texture(BaseMaterial3D::TEXTURE_AMBIENT_OCCLUSION, _get_texture(state, bct["index"]));
+ material->set_texture(BaseMaterial3D::TEXTURE_AMBIENT_OCCLUSION, _get_texture(p_state, bct["index"]));
material->set_ao_texture_channel(BaseMaterial3D::TEXTURE_CHANNEL_RED);
material->set_feature(BaseMaterial3D::FEATURE_AMBIENT_OCCLUSION, true);
}
@@ -3800,7 +3803,7 @@ Error GLTFDocument::_parse_materials(Ref<GLTFState> state) {
if (d.has("emissiveTexture")) {
const Dictionary &bct = d["emissiveTexture"];
if (bct.has("index")) {
- material->set_texture(BaseMaterial3D::TEXTURE_EMISSION, _get_texture(state, bct["index"]));
+ material->set_texture(BaseMaterial3D::TEXTURE_EMISSION, _get_texture(p_state, bct["index"]));
material->set_feature(BaseMaterial3D::FEATURE_EMISSION, true);
material->set_emission(Color(0, 0, 0));
}
@@ -3825,41 +3828,49 @@ Error GLTFDocument::_parse_materials(Ref<GLTFState> state) {
}
}
}
- state->materials.push_back(material);
+ p_state->materials.push_back(material);
}
- print_verbose("Total materials: " + itos(state->materials.size()));
+ print_verbose("Total materials: " + itos(p_state->materials.size()));
return OK;
}
-void GLTFDocument::_set_texture_transform_uv1(const Dictionary &d, Ref<BaseMaterial3D> material) {
- if (d.has("extensions")) {
- const Dictionary &extensions = d["extensions"];
+void GLTFDocument::_set_texture_transform_uv1(const Dictionary &p_dict, Ref<BaseMaterial3D> p_material) {
+ if (p_dict.has("extensions")) {
+ const Dictionary &extensions = p_dict["extensions"];
if (extensions.has("KHR_texture_transform")) {
- const Dictionary &texture_transform = extensions["KHR_texture_transform"];
- const Array &offset_arr = texture_transform["offset"];
- if (offset_arr.size() == 2) {
- const Vector3 offset_vector3 = Vector3(offset_arr[0], offset_arr[1], 0.0f);
- material->set_uv1_offset(offset_vector3);
- }
+ if (p_material.is_valid()) {
+ const Dictionary &texture_transform = extensions["KHR_texture_transform"];
+ const Array &offset_arr = texture_transform["offset"];
+ if (offset_arr.size() == 2) {
+ const Vector3 offset_vector3 = Vector3(offset_arr[0], offset_arr[1], 0.0f);
+ p_material->set_uv1_offset(offset_vector3);
+ }
- const Array &scale_arr = texture_transform["scale"];
- if (scale_arr.size() == 2) {
- const Vector3 scale_vector3 = Vector3(scale_arr[0], scale_arr[1], 1.0f);
- material->set_uv1_scale(scale_vector3);
+ const Array &scale_arr = texture_transform["scale"];
+ if (scale_arr.size() == 2) {
+ const Vector3 scale_vector3 = Vector3(scale_arr[0], scale_arr[1], 1.0f);
+ p_material->set_uv1_scale(scale_vector3);
+ }
}
}
}
}
void GLTFDocument::spec_gloss_to_rough_metal(Ref<GLTFSpecGloss> r_spec_gloss, Ref<BaseMaterial3D> p_material) {
+ if (r_spec_gloss.is_null()) {
+ return;
+ }
if (r_spec_gloss->spec_gloss_img.is_null()) {
return;
}
if (r_spec_gloss->diffuse_img.is_null()) {
return;
}
+ if (p_material.is_null()) {
+ return;
+ }
bool has_roughness = false;
bool has_metal = false;
p_material->set_roughness(1.0f);
@@ -3931,13 +3942,13 @@ void GLTFDocument::spec_gloss_to_metal_base_color(const Color &p_specular_factor
r_base_color = r_base_color.clamp();
}
-GLTFNodeIndex GLTFDocument::_find_highest_node(Ref<GLTFState> state, const Vector<GLTFNodeIndex> &subset) {
+GLTFNodeIndex GLTFDocument::_find_highest_node(Ref<GLTFState> p_state, const Vector<GLTFNodeIndex> &p_subset) {
int highest = -1;
GLTFNodeIndex best_node = -1;
- for (int i = 0; i < subset.size(); ++i) {
- const GLTFNodeIndex node_i = subset[i];
- const Ref<GLTFNode> node = state->nodes[node_i];
+ for (int i = 0; i < p_subset.size(); ++i) {
+ const GLTFNodeIndex node_i = p_subset[i];
+ const Ref<GLTFNode> node = p_state->nodes[node_i];
if (highest == -1 || node->height < highest) {
highest = node->height;
@@ -3948,38 +3959,38 @@ GLTFNodeIndex GLTFDocument::_find_highest_node(Ref<GLTFState> state, const Vecto
return best_node;
}
-bool GLTFDocument::_capture_nodes_in_skin(Ref<GLTFState> state, Ref<GLTFSkin> skin, const GLTFNodeIndex node_index) {
+bool GLTFDocument::_capture_nodes_in_skin(Ref<GLTFState> p_state, Ref<GLTFSkin> p_skin, const GLTFNodeIndex p_node_index) {
bool found_joint = false;
- for (int i = 0; i < state->nodes[node_index]->children.size(); ++i) {
- found_joint |= _capture_nodes_in_skin(state, skin, state->nodes[node_index]->children[i]);
+ for (int i = 0; i < p_state->nodes[p_node_index]->children.size(); ++i) {
+ found_joint |= _capture_nodes_in_skin(p_state, p_skin, p_state->nodes[p_node_index]->children[i]);
}
if (found_joint) {
// Mark it if we happen to find another skins joint...
- if (state->nodes[node_index]->joint && skin->joints.find(node_index) < 0) {
- skin->joints.push_back(node_index);
- } else if (skin->non_joints.find(node_index) < 0) {
- skin->non_joints.push_back(node_index);
+ if (p_state->nodes[p_node_index]->joint && p_skin->joints.find(p_node_index) < 0) {
+ p_skin->joints.push_back(p_node_index);
+ } else if (p_skin->non_joints.find(p_node_index) < 0) {
+ p_skin->non_joints.push_back(p_node_index);
}
}
- if (skin->joints.find(node_index) > 0) {
+ if (p_skin->joints.find(p_node_index) > 0) {
return true;
}
return false;
}
-void GLTFDocument::_capture_nodes_for_multirooted_skin(Ref<GLTFState> state, Ref<GLTFSkin> skin) {
+void GLTFDocument::_capture_nodes_for_multirooted_skin(Ref<GLTFState> p_state, Ref<GLTFSkin> p_skin) {
DisjointSet<GLTFNodeIndex> disjoint_set;
- for (int i = 0; i < skin->joints.size(); ++i) {
- const GLTFNodeIndex node_index = skin->joints[i];
- const GLTFNodeIndex parent = state->nodes[node_index]->parent;
+ for (int i = 0; i < p_skin->joints.size(); ++i) {
+ const GLTFNodeIndex node_index = p_skin->joints[i];
+ const GLTFNodeIndex parent = p_state->nodes[node_index]->parent;
disjoint_set.insert(node_index);
- if (skin->joints.find(parent) >= 0) {
+ if (p_skin->joints.find(parent) >= 0) {
disjoint_set.create_union(parent, node_index);
}
}
@@ -3997,8 +4008,8 @@ void GLTFDocument::_capture_nodes_for_multirooted_skin(Ref<GLTFState> state, Ref
for (int i = 0; i < roots.size(); ++i) {
const GLTFNodeIndex root = roots[i];
- if (maxHeight == -1 || state->nodes[root]->height < maxHeight) {
- maxHeight = state->nodes[root]->height;
+ if (maxHeight == -1 || p_state->nodes[root]->height < maxHeight) {
+ maxHeight = p_state->nodes[root]->height;
}
}
@@ -4006,13 +4017,13 @@ void GLTFDocument::_capture_nodes_for_multirooted_skin(Ref<GLTFState> state, Ref
// This sucks, but 99% of all game engines (not just Godot) would have this same issue.
for (int i = 0; i < roots.size(); ++i) {
GLTFNodeIndex current_node = roots[i];
- while (state->nodes[current_node]->height > maxHeight) {
- GLTFNodeIndex parent = state->nodes[current_node]->parent;
+ while (p_state->nodes[current_node]->height > maxHeight) {
+ GLTFNodeIndex parent = p_state->nodes[current_node]->parent;
- if (state->nodes[parent]->joint && skin->joints.find(parent) < 0) {
- skin->joints.push_back(parent);
- } else if (skin->non_joints.find(parent) < 0) {
- skin->non_joints.push_back(parent);
+ if (p_state->nodes[parent]->joint && p_skin->joints.find(parent) < 0) {
+ p_skin->joints.push_back(parent);
+ } else if (p_skin->non_joints.find(parent) < 0) {
+ p_skin->non_joints.push_back(parent);
}
current_node = parent;
@@ -4027,21 +4038,21 @@ void GLTFDocument::_capture_nodes_for_multirooted_skin(Ref<GLTFState> state, Ref
do {
all_same = true;
- const GLTFNodeIndex first_parent = state->nodes[roots[0]]->parent;
+ const GLTFNodeIndex first_parent = p_state->nodes[roots[0]]->parent;
for (int i = 1; i < roots.size(); ++i) {
- all_same &= (first_parent == state->nodes[roots[i]]->parent);
+ all_same &= (first_parent == p_state->nodes[roots[i]]->parent);
}
if (!all_same) {
for (int i = 0; i < roots.size(); ++i) {
const GLTFNodeIndex current_node = roots[i];
- const GLTFNodeIndex parent = state->nodes[current_node]->parent;
+ const GLTFNodeIndex parent = p_state->nodes[current_node]->parent;
- if (state->nodes[parent]->joint && skin->joints.find(parent) < 0) {
- skin->joints.push_back(parent);
- } else if (skin->non_joints.find(parent) < 0) {
- skin->non_joints.push_back(parent);
+ if (p_state->nodes[parent]->joint && p_skin->joints.find(parent) < 0) {
+ p_skin->joints.push_back(parent);
+ } else if (p_skin->non_joints.find(parent) < 0) {
+ p_skin->non_joints.push_back(parent);
}
roots.write[i] = parent;
@@ -4051,19 +4062,19 @@ void GLTFDocument::_capture_nodes_for_multirooted_skin(Ref<GLTFState> state, Ref
} while (!all_same);
}
-Error GLTFDocument::_expand_skin(Ref<GLTFState> state, Ref<GLTFSkin> skin) {
- _capture_nodes_for_multirooted_skin(state, skin);
+Error GLTFDocument::_expand_skin(Ref<GLTFState> p_state, Ref<GLTFSkin> p_skin) {
+ _capture_nodes_for_multirooted_skin(p_state, p_skin);
// Grab all nodes that lay in between skin joints/nodes
DisjointSet<GLTFNodeIndex> disjoint_set;
Vector<GLTFNodeIndex> all_skin_nodes;
- all_skin_nodes.append_array(skin->joints);
- all_skin_nodes.append_array(skin->non_joints);
+ all_skin_nodes.append_array(p_skin->joints);
+ all_skin_nodes.append_array(p_skin->non_joints);
for (int i = 0; i < all_skin_nodes.size(); ++i) {
const GLTFNodeIndex node_index = all_skin_nodes[i];
- const GLTFNodeIndex parent = state->nodes[node_index]->parent;
+ const GLTFNodeIndex parent = p_state->nodes[node_index]->parent;
disjoint_set.insert(node_index);
if (all_skin_nodes.find(parent) >= 0) {
@@ -4080,7 +4091,7 @@ Error GLTFDocument::_expand_skin(Ref<GLTFState> state, Ref<GLTFSkin> skin) {
Vector<GLTFNodeIndex> set;
disjoint_set.get_members(set, out_owners[i]);
- const GLTFNodeIndex root = _find_highest_node(state, set);
+ const GLTFNodeIndex root = _find_highest_node(p_state, set);
ERR_FAIL_COND_V(root < 0, FAILED);
out_roots.push_back(root);
}
@@ -4088,15 +4099,15 @@ Error GLTFDocument::_expand_skin(Ref<GLTFState> state, Ref<GLTFSkin> skin) {
out_roots.sort();
for (int i = 0; i < out_roots.size(); ++i) {
- _capture_nodes_in_skin(state, skin, out_roots[i]);
+ _capture_nodes_in_skin(p_state, p_skin, out_roots[i]);
}
- skin->roots = out_roots;
+ p_skin->roots = out_roots;
return OK;
}
-Error GLTFDocument::_verify_skin(Ref<GLTFState> state, Ref<GLTFSkin> skin) {
+Error GLTFDocument::_verify_skin(Ref<GLTFState> p_state, Ref<GLTFSkin> p_skin) {
// This may seem duplicated from expand_skins, but this is really a sanity check! (so it kinda is)
// In case additional interpolating logic is added to the skins, this will help ensure that you
// do not cause it to self implode into a fiery blaze
@@ -4108,12 +4119,12 @@ Error GLTFDocument::_verify_skin(Ref<GLTFState> state, Ref<GLTFSkin> skin) {
DisjointSet<GLTFNodeIndex> disjoint_set;
Vector<GLTFNodeIndex> all_skin_nodes;
- all_skin_nodes.append_array(skin->joints);
- all_skin_nodes.append_array(skin->non_joints);
+ all_skin_nodes.append_array(p_skin->joints);
+ all_skin_nodes.append_array(p_skin->non_joints);
for (int i = 0; i < all_skin_nodes.size(); ++i) {
const GLTFNodeIndex node_index = all_skin_nodes[i];
- const GLTFNodeIndex parent = state->nodes[node_index]->parent;
+ const GLTFNodeIndex parent = p_state->nodes[node_index]->parent;
disjoint_set.insert(node_index);
if (all_skin_nodes.find(parent) >= 0) {
@@ -4130,7 +4141,7 @@ Error GLTFDocument::_verify_skin(Ref<GLTFState> state, Ref<GLTFSkin> skin) {
Vector<GLTFNodeIndex> set;
disjoint_set.get_members(set, out_owners[i]);
- const GLTFNodeIndex root = _find_highest_node(state, set);
+ const GLTFNodeIndex root = _find_highest_node(p_state, set);
ERR_FAIL_COND_V(root < 0, FAILED);
out_roots.push_back(root);
}
@@ -4140,9 +4151,9 @@ Error GLTFDocument::_verify_skin(Ref<GLTFState> state, Ref<GLTFSkin> skin) {
ERR_FAIL_COND_V(out_roots.size() == 0, FAILED);
// Make sure the roots are the exact same (they better be)
- ERR_FAIL_COND_V(out_roots.size() != skin->roots.size(), FAILED);
+ ERR_FAIL_COND_V(out_roots.size() != p_skin->roots.size(), FAILED);
for (int i = 0; i < out_roots.size(); ++i) {
- ERR_FAIL_COND_V(out_roots[i] != skin->roots[i], FAILED);
+ ERR_FAIL_COND_V(out_roots[i] != p_skin->roots[i], FAILED);
}
// Single rooted skin? Perfectly ok!
@@ -4151,9 +4162,9 @@ Error GLTFDocument::_verify_skin(Ref<GLTFState> state, Ref<GLTFSkin> skin) {
}
// Make sure all parents of a multi-rooted skin are the SAME
- const GLTFNodeIndex parent = state->nodes[out_roots[0]]->parent;
+ const GLTFNodeIndex parent = p_state->nodes[out_roots[0]]->parent;
for (int i = 1; i < out_roots.size(); ++i) {
- if (state->nodes[out_roots[i]]->parent != parent) {
+ if (p_state->nodes[out_roots[i]]->parent != parent) {
return FAILED;
}
}
@@ -4161,12 +4172,12 @@ Error GLTFDocument::_verify_skin(Ref<GLTFState> state, Ref<GLTFSkin> skin) {
return OK;
}
-Error GLTFDocument::_parse_skins(Ref<GLTFState> state) {
- if (!state->json.has("skins")) {
+Error GLTFDocument::_parse_skins(Ref<GLTFState> p_state) {
+ if (!p_state->json.has("skins")) {
return OK;
}
- const Array &skins = state->json["skins"];
+ const Array &skins = p_state->json["skins"];
// Create the base skins, and mark nodes that are joints
for (int i = 0; i < skins.size(); i++) {
@@ -4180,18 +4191,18 @@ Error GLTFDocument::_parse_skins(Ref<GLTFState> state) {
const Array &joints = d["joints"];
if (d.has("inverseBindMatrices")) {
- skin->inverse_binds = _decode_accessor_as_xform(state, d["inverseBindMatrices"], false);
+ skin->inverse_binds = _decode_accessor_as_xform(p_state, d["inverseBindMatrices"], false);
ERR_FAIL_COND_V(skin->inverse_binds.size() != joints.size(), ERR_PARSE_ERROR);
}
for (int j = 0; j < joints.size(); j++) {
const GLTFNodeIndex node = joints[j];
- ERR_FAIL_INDEX_V(node, state->nodes.size(), ERR_PARSE_ERROR);
+ ERR_FAIL_INDEX_V(node, p_state->nodes.size(), ERR_PARSE_ERROR);
skin->joints.push_back(node);
skin->joints_original.push_back(node);
- state->nodes.write[node]->joint = true;
+ p_state->nodes.write[node]->joint = true;
}
if (d.has("name") && !String(d["name"]).is_empty()) {
@@ -4204,32 +4215,32 @@ Error GLTFDocument::_parse_skins(Ref<GLTFState> state) {
skin->skin_root = d["skeleton"];
}
- state->skins.push_back(skin);
+ p_state->skins.push_back(skin);
}
- for (GLTFSkinIndex i = 0; i < state->skins.size(); ++i) {
- Ref<GLTFSkin> skin = state->skins.write[i];
+ for (GLTFSkinIndex i = 0; i < p_state->skins.size(); ++i) {
+ Ref<GLTFSkin> skin = p_state->skins.write[i];
// Expand the skin to capture all the extra non-joints that lie in between the actual joints,
// and expand the hierarchy to ensure multi-rooted trees lie on the same height level
- ERR_FAIL_COND_V(_expand_skin(state, skin), ERR_PARSE_ERROR);
- ERR_FAIL_COND_V(_verify_skin(state, skin), ERR_PARSE_ERROR);
+ ERR_FAIL_COND_V(_expand_skin(p_state, skin), ERR_PARSE_ERROR);
+ ERR_FAIL_COND_V(_verify_skin(p_state, skin), ERR_PARSE_ERROR);
}
- print_verbose("glTF: Total skins: " + itos(state->skins.size()));
+ print_verbose("glTF: Total skins: " + itos(p_state->skins.size()));
return OK;
}
-Error GLTFDocument::_determine_skeletons(Ref<GLTFState> state) {
+Error GLTFDocument::_determine_skeletons(Ref<GLTFState> p_state) {
// Using a disjoint set, we are going to potentially combine all skins that are actually branches
// of a main skeleton, or treat skins defining the same set of nodes as ONE skeleton.
// This is another unclear issue caused by the current glTF specification.
DisjointSet<GLTFNodeIndex> skeleton_sets;
- for (GLTFSkinIndex skin_i = 0; skin_i < state->skins.size(); ++skin_i) {
- const Ref<GLTFSkin> skin = state->skins[skin_i];
+ for (GLTFSkinIndex skin_i = 0; skin_i < p_state->skins.size(); ++skin_i) {
+ const Ref<GLTFSkin> skin = p_state->skins[skin_i];
Vector<GLTFNodeIndex> all_skin_nodes;
all_skin_nodes.append_array(skin->joints);
@@ -4237,7 +4248,7 @@ Error GLTFDocument::_determine_skeletons(Ref<GLTFState> state) {
for (int i = 0; i < all_skin_nodes.size(); ++i) {
const GLTFNodeIndex node_index = all_skin_nodes[i];
- const GLTFNodeIndex parent = state->nodes[node_index]->parent;
+ const GLTFNodeIndex parent = p_state->nodes[node_index]->parent;
skeleton_sets.insert(node_index);
if (all_skin_nodes.find(parent) >= 0) {
@@ -4261,7 +4272,7 @@ Error GLTFDocument::_determine_skeletons(Ref<GLTFState> state) {
for (int i = 0; i < groups_representatives.size(); ++i) {
Vector<GLTFNodeIndex> group;
skeleton_sets.get_members(group, groups_representatives[i]);
- highest_group_members.push_back(_find_highest_node(state, group));
+ highest_group_members.push_back(_find_highest_node(p_state, group));
groups.push_back(group);
}
@@ -4273,13 +4284,13 @@ Error GLTFDocument::_determine_skeletons(Ref<GLTFState> state) {
const GLTFNodeIndex node_j = highest_group_members[j];
// Even if they are siblings under the root! :)
- if (state->nodes[node_i]->parent == state->nodes[node_j]->parent) {
+ if (p_state->nodes[node_i]->parent == p_state->nodes[node_j]->parent) {
skeleton_sets.create_union(node_i, node_j);
}
}
// Attach any parenting going on together (we need to do this n^2 times)
- const GLTFNodeIndex node_i_parent = state->nodes[node_i]->parent;
+ const GLTFNodeIndex node_i_parent = p_state->nodes[node_i]->parent;
if (node_i_parent >= 0) {
for (int j = 0; j < groups.size() && i != j; ++j) {
const Vector<GLTFNodeIndex> &group = groups[j];
@@ -4306,8 +4317,8 @@ Error GLTFDocument::_determine_skeletons(Ref<GLTFState> state) {
Vector<GLTFNodeIndex> skeleton_nodes;
skeleton_sets.get_members(skeleton_nodes, skeleton_owner);
- for (GLTFSkinIndex skin_i = 0; skin_i < state->skins.size(); ++skin_i) {
- Ref<GLTFSkin> skin = state->skins.write[skin_i];
+ for (GLTFSkinIndex skin_i = 0; skin_i < p_state->skins.size(); ++skin_i) {
+ Ref<GLTFSkin> skin = p_state->skins.write[skin_i];
// If any of the the skeletons nodes exist in a skin, that skin now maps to the skeleton
for (int i = 0; i < skeleton_nodes.size(); ++i) {
@@ -4323,37 +4334,37 @@ Error GLTFDocument::_determine_skeletons(Ref<GLTFState> state) {
for (int i = 0; i < skeleton_nodes.size(); ++i) {
const GLTFNodeIndex node_i = skeleton_nodes[i];
- if (state->nodes[node_i]->joint) {
+ if (p_state->nodes[node_i]->joint) {
skeleton->joints.push_back(node_i);
} else {
non_joints.push_back(node_i);
}
}
- state->skeletons.push_back(skeleton);
+ p_state->skeletons.push_back(skeleton);
- _reparent_non_joint_skeleton_subtrees(state, state->skeletons.write[skel_i], non_joints);
+ _reparent_non_joint_skeleton_subtrees(p_state, p_state->skeletons.write[skel_i], non_joints);
}
- for (GLTFSkeletonIndex skel_i = 0; skel_i < state->skeletons.size(); ++skel_i) {
- Ref<GLTFSkeleton> skeleton = state->skeletons.write[skel_i];
+ for (GLTFSkeletonIndex skel_i = 0; skel_i < p_state->skeletons.size(); ++skel_i) {
+ Ref<GLTFSkeleton> skeleton = p_state->skeletons.write[skel_i];
for (int i = 0; i < skeleton->joints.size(); ++i) {
const GLTFNodeIndex node_i = skeleton->joints[i];
- Ref<GLTFNode> node = state->nodes[node_i];
+ Ref<GLTFNode> node = p_state->nodes[node_i];
ERR_FAIL_COND_V(!node->joint, ERR_PARSE_ERROR);
ERR_FAIL_COND_V(node->skeleton >= 0, ERR_PARSE_ERROR);
node->skeleton = skel_i;
}
- ERR_FAIL_COND_V(_determine_skeleton_roots(state, skel_i), ERR_PARSE_ERROR);
+ ERR_FAIL_COND_V(_determine_skeleton_roots(p_state, skel_i), ERR_PARSE_ERROR);
}
return OK;
}
-Error GLTFDocument::_reparent_non_joint_skeleton_subtrees(Ref<GLTFState> state, Ref<GLTFSkeleton> skeleton, const Vector<GLTFNodeIndex> &non_joints) {
+Error GLTFDocument::_reparent_non_joint_skeleton_subtrees(Ref<GLTFState> p_state, Ref<GLTFSkeleton> p_skeleton, const Vector<GLTFNodeIndex> &p_non_joints) {
DisjointSet<GLTFNodeIndex> subtree_set;
// Populate the disjoint set with ONLY non joints that are in the skeleton hierarchy (non_joints vector)
@@ -4364,13 +4375,13 @@ Error GLTFDocument::_reparent_non_joint_skeleton_subtrees(Ref<GLTFState> state,
// skinD depicted here explains this issue:
// https://github.com/KhronosGroup/glTF-Asset-Generator/blob/master/Output/Positive/Animation_Skin
- for (int i = 0; i < non_joints.size(); ++i) {
- const GLTFNodeIndex node_i = non_joints[i];
+ for (int i = 0; i < p_non_joints.size(); ++i) {
+ const GLTFNodeIndex node_i = p_non_joints[i];
subtree_set.insert(node_i);
- const GLTFNodeIndex parent_i = state->nodes[node_i]->parent;
- if (parent_i >= 0 && non_joints.find(parent_i) >= 0 && !state->nodes[parent_i]->joint) {
+ const GLTFNodeIndex parent_i = p_state->nodes[node_i]->parent;
+ if (parent_i >= 0 && p_non_joints.find(parent_i) >= 0 && !p_state->nodes[parent_i]->joint) {
subtree_set.create_union(parent_i, node_i);
}
}
@@ -4387,34 +4398,34 @@ Error GLTFDocument::_reparent_non_joint_skeleton_subtrees(Ref<GLTFState> state,
subtree_set.get_members(subtree_nodes, subtree_root);
for (int subtree_i = 0; subtree_i < subtree_nodes.size(); ++subtree_i) {
- Ref<GLTFNode> node = state->nodes[subtree_nodes[subtree_i]];
+ Ref<GLTFNode> node = p_state->nodes[subtree_nodes[subtree_i]];
node->joint = true;
// Add the joint to the skeletons joints
- skeleton->joints.push_back(subtree_nodes[subtree_i]);
+ p_skeleton->joints.push_back(subtree_nodes[subtree_i]);
}
}
return OK;
}
-Error GLTFDocument::_determine_skeleton_roots(Ref<GLTFState> state, const GLTFSkeletonIndex skel_i) {
+Error GLTFDocument::_determine_skeleton_roots(Ref<GLTFState> p_state, const GLTFSkeletonIndex p_skel_i) {
DisjointSet<GLTFNodeIndex> disjoint_set;
- for (GLTFNodeIndex i = 0; i < state->nodes.size(); ++i) {
- const Ref<GLTFNode> node = state->nodes[i];
+ for (GLTFNodeIndex i = 0; i < p_state->nodes.size(); ++i) {
+ const Ref<GLTFNode> node = p_state->nodes[i];
- if (node->skeleton != skel_i) {
+ if (node->skeleton != p_skel_i) {
continue;
}
disjoint_set.insert(i);
- if (node->parent >= 0 && state->nodes[node->parent]->skeleton == skel_i) {
+ if (node->parent >= 0 && p_state->nodes[node->parent]->skeleton == p_skel_i) {
disjoint_set.create_union(node->parent, i);
}
}
- Ref<GLTFSkeleton> skeleton = state->skeletons.write[skel_i];
+ Ref<GLTFSkeleton> skeleton = p_state->skeletons.write[p_skel_i];
Vector<GLTFNodeIndex> representatives;
disjoint_set.get_representatives(representatives);
@@ -4424,7 +4435,7 @@ Error GLTFDocument::_determine_skeleton_roots(Ref<GLTFState> state, const GLTFSk
for (int i = 0; i < representatives.size(); ++i) {
Vector<GLTFNodeIndex> set;
disjoint_set.get_members(set, representatives[i]);
- const GLTFNodeIndex root = _find_highest_node(state, set);
+ const GLTFNodeIndex root = _find_highest_node(p_state, set);
ERR_FAIL_COND_V(root < 0, FAILED);
roots.push_back(root);
}
@@ -4440,9 +4451,9 @@ Error GLTFDocument::_determine_skeleton_roots(Ref<GLTFState> state, const GLTFSk
}
// Check that the subtrees have the same parent root
- const GLTFNodeIndex parent = state->nodes[roots[0]]->parent;
+ const GLTFNodeIndex parent = p_state->nodes[roots[0]]->parent;
for (int i = 1; i < roots.size(); ++i) {
- if (state->nodes[roots[i]]->parent != parent) {
+ if (p_state->nodes[roots[i]]->parent != parent) {
return FAILED;
}
}
@@ -4450,16 +4461,16 @@ Error GLTFDocument::_determine_skeleton_roots(Ref<GLTFState> state, const GLTFSk
return OK;
}
-Error GLTFDocument::_create_skeletons(Ref<GLTFState> state) {
- for (GLTFSkeletonIndex skel_i = 0; skel_i < state->skeletons.size(); ++skel_i) {
- Ref<GLTFSkeleton> gltf_skeleton = state->skeletons.write[skel_i];
+Error GLTFDocument::_create_skeletons(Ref<GLTFState> p_state) {
+ for (GLTFSkeletonIndex skel_i = 0; skel_i < p_state->skeletons.size(); ++skel_i) {
+ Ref<GLTFSkeleton> gltf_skeleton = p_state->skeletons.write[skel_i];
Skeleton3D *skeleton = memnew(Skeleton3D);
gltf_skeleton->godot_skeleton = skeleton;
- state->skeleton3d_to_gltf_skeleton[skeleton->get_instance_id()] = skel_i;
+ p_state->skeleton3d_to_gltf_skeleton[skeleton->get_instance_id()] = skel_i;
// Make a unique name, no gltf node represents this skeleton
- skeleton->set_name(_gen_unique_name(state, "Skeleton3D"));
+ skeleton->set_name(_gen_unique_name(p_state, "Skeleton3D"));
List<GLTFNodeIndex> bones;
@@ -4475,14 +4486,14 @@ Error GLTFDocument::_create_skeletons(Ref<GLTFState> state) {
const GLTFNodeIndex node_i = bones.front()->get();
bones.pop_front();
- Ref<GLTFNode> node = state->nodes[node_i];
+ Ref<GLTFNode> node = p_state->nodes[node_i];
ERR_FAIL_COND_V(node->skeleton != skel_i, FAILED);
{ // Add all child nodes to the stack (deterministically)
Vector<GLTFNodeIndex> child_nodes;
for (int i = 0; i < node->children.size(); ++i) {
const GLTFNodeIndex child_i = node->children[i];
- if (state->nodes[child_i]->skeleton == skel_i) {
+ if (p_state->nodes[child_i]->skeleton == skel_i) {
child_nodes.push_back(child_i);
}
}
@@ -4500,7 +4511,7 @@ Error GLTFDocument::_create_skeletons(Ref<GLTFState> state) {
node->set_name("bone");
}
- node->set_name(_gen_unique_bone_name(state, skel_i, node->get_name()));
+ node->set_name(_gen_unique_bone_name(p_state, skel_i, node->get_name()));
skeleton->add_bone(node->get_name());
skeleton->set_bone_rest(bone_index, node->xform);
@@ -4508,30 +4519,30 @@ Error GLTFDocument::_create_skeletons(Ref<GLTFState> state) {
skeleton->set_bone_pose_rotation(bone_index, node->rotation.normalized());
skeleton->set_bone_pose_scale(bone_index, node->scale);
- if (node->parent >= 0 && state->nodes[node->parent]->skeleton == skel_i) {
- const int bone_parent = skeleton->find_bone(state->nodes[node->parent]->get_name());
+ if (node->parent >= 0 && p_state->nodes[node->parent]->skeleton == skel_i) {
+ const int bone_parent = skeleton->find_bone(p_state->nodes[node->parent]->get_name());
ERR_FAIL_COND_V(bone_parent < 0, FAILED);
- skeleton->set_bone_parent(bone_index, skeleton->find_bone(state->nodes[node->parent]->get_name()));
+ skeleton->set_bone_parent(bone_index, skeleton->find_bone(p_state->nodes[node->parent]->get_name()));
}
- state->scene_nodes.insert(node_i, skeleton);
+ p_state->scene_nodes.insert(node_i, skeleton);
}
}
- ERR_FAIL_COND_V(_map_skin_joints_indices_to_skeleton_bone_indices(state), ERR_PARSE_ERROR);
+ ERR_FAIL_COND_V(_map_skin_joints_indices_to_skeleton_bone_indices(p_state), ERR_PARSE_ERROR);
return OK;
}
-Error GLTFDocument::_map_skin_joints_indices_to_skeleton_bone_indices(Ref<GLTFState> state) {
- for (GLTFSkinIndex skin_i = 0; skin_i < state->skins.size(); ++skin_i) {
- Ref<GLTFSkin> skin = state->skins.write[skin_i];
+Error GLTFDocument::_map_skin_joints_indices_to_skeleton_bone_indices(Ref<GLTFState> p_state) {
+ for (GLTFSkinIndex skin_i = 0; skin_i < p_state->skins.size(); ++skin_i) {
+ Ref<GLTFSkin> skin = p_state->skins.write[skin_i];
- Ref<GLTFSkeleton> skeleton = state->skeletons[skin->skeleton];
+ Ref<GLTFSkeleton> skeleton = p_state->skeletons[skin->skeleton];
for (int joint_index = 0; joint_index < skin->joints_original.size(); ++joint_index) {
const GLTFNodeIndex node_i = skin->joints_original[joint_index];
- const Ref<GLTFNode> node = state->nodes[node_i];
+ const Ref<GLTFNode> node = p_state->nodes[node_i];
const int bone_index = skeleton->godot_skeleton->find_bone(node->get_name());
ERR_FAIL_COND_V(bone_index < 0, FAILED);
@@ -4543,28 +4554,28 @@ Error GLTFDocument::_map_skin_joints_indices_to_skeleton_bone_indices(Ref<GLTFSt
return OK;
}
-Error GLTFDocument::_serialize_skins(Ref<GLTFState> state) {
- _remove_duplicate_skins(state);
+Error GLTFDocument::_serialize_skins(Ref<GLTFState> p_state) {
+ _remove_duplicate_skins(p_state);
Array json_skins;
- for (int skin_i = 0; skin_i < state->skins.size(); skin_i++) {
- Ref<GLTFSkin> gltf_skin = state->skins[skin_i];
+ for (int skin_i = 0; skin_i < p_state->skins.size(); skin_i++) {
+ Ref<GLTFSkin> gltf_skin = p_state->skins[skin_i];
Dictionary json_skin;
- json_skin["inverseBindMatrices"] = _encode_accessor_as_xform(state, gltf_skin->inverse_binds, false);
+ json_skin["inverseBindMatrices"] = _encode_accessor_as_xform(p_state, gltf_skin->inverse_binds, false);
json_skin["joints"] = gltf_skin->get_joints();
json_skin["name"] = gltf_skin->get_name();
json_skins.push_back(json_skin);
}
- if (!state->skins.size()) {
+ if (!p_state->skins.size()) {
return OK;
}
- state->json["skins"] = json_skins;
+ p_state->json["skins"] = json_skins;
return OK;
}
-Error GLTFDocument::_create_skins(Ref<GLTFState> state) {
- for (GLTFSkinIndex skin_i = 0; skin_i < state->skins.size(); ++skin_i) {
- Ref<GLTFSkin> gltf_skin = state->skins.write[skin_i];
+Error GLTFDocument::_create_skins(Ref<GLTFState> p_state) {
+ for (GLTFSkinIndex skin_i = 0; skin_i < p_state->skins.size(); ++skin_i) {
+ Ref<GLTFSkin> gltf_skin = p_state->skins.write[skin_i];
Ref<Skin> skin;
skin.instantiate();
@@ -4574,14 +4585,14 @@ Error GLTFDocument::_create_skins(Ref<GLTFState> state) {
for (int joint_i = 0; joint_i < gltf_skin->joints_original.size(); ++joint_i) {
GLTFNodeIndex node = gltf_skin->joints_original[joint_i];
- String bone_name = state->nodes[node]->get_name();
+ String bone_name = p_state->nodes[node]->get_name();
Transform3D xform;
if (has_ibms) {
xform = gltf_skin->inverse_binds[joint_i];
}
- if (state->use_named_skin_binds) {
+ if (p_state->use_named_skin_binds) {
skin->add_named_bind(bone_name, xform);
} else {
int32_t bone_i = gltf_skin->joint_i_to_bone_i[joint_i];
@@ -4593,35 +4604,35 @@ Error GLTFDocument::_create_skins(Ref<GLTFState> state) {
}
// Purge the duplicates!
- _remove_duplicate_skins(state);
+ _remove_duplicate_skins(p_state);
// Create unique names now, after removing duplicates
- for (GLTFSkinIndex skin_i = 0; skin_i < state->skins.size(); ++skin_i) {
- Ref<Skin> skin = state->skins.write[skin_i]->godot_skin;
+ for (GLTFSkinIndex skin_i = 0; skin_i < p_state->skins.size(); ++skin_i) {
+ Ref<Skin> skin = p_state->skins.write[skin_i]->godot_skin;
if (skin->get_name().is_empty()) {
// Make a unique name, no gltf node represents this skin
- skin->set_name(_gen_unique_name(state, "Skin"));
+ skin->set_name(_gen_unique_name(p_state, "Skin"));
}
}
return OK;
}
-bool GLTFDocument::_skins_are_same(const Ref<Skin> skin_a, const Ref<Skin> skin_b) {
- if (skin_a->get_bind_count() != skin_b->get_bind_count()) {
+bool GLTFDocument::_skins_are_same(const Ref<Skin> p_skin_a, const Ref<Skin> p_skin_b) {
+ if (p_skin_a->get_bind_count() != p_skin_b->get_bind_count()) {
return false;
}
- for (int i = 0; i < skin_a->get_bind_count(); ++i) {
- if (skin_a->get_bind_bone(i) != skin_b->get_bind_bone(i)) {
+ for (int i = 0; i < p_skin_a->get_bind_count(); ++i) {
+ if (p_skin_a->get_bind_bone(i) != p_skin_b->get_bind_bone(i)) {
return false;
}
- if (skin_a->get_bind_name(i) != skin_b->get_bind_name(i)) {
+ if (p_skin_a->get_bind_name(i) != p_skin_b->get_bind_name(i)) {
return false;
}
- Transform3D a_xform = skin_a->get_bind_pose(i);
- Transform3D b_xform = skin_b->get_bind_pose(i);
+ Transform3D a_xform = p_skin_a->get_bind_pose(i);
+ Transform3D b_xform = p_skin_b->get_bind_pose(i);
if (a_xform != b_xform) {
return false;
@@ -4631,67 +4642,67 @@ bool GLTFDocument::_skins_are_same(const Ref<Skin> skin_a, const Ref<Skin> skin_
return true;
}
-void GLTFDocument::_remove_duplicate_skins(Ref<GLTFState> state) {
- for (int i = 0; i < state->skins.size(); ++i) {
- for (int j = i + 1; j < state->skins.size(); ++j) {
- const Ref<Skin> skin_i = state->skins[i]->godot_skin;
- const Ref<Skin> skin_j = state->skins[j]->godot_skin;
+void GLTFDocument::_remove_duplicate_skins(Ref<GLTFState> p_state) {
+ for (int i = 0; i < p_state->skins.size(); ++i) {
+ for (int j = i + 1; j < p_state->skins.size(); ++j) {
+ const Ref<Skin> skin_i = p_state->skins[i]->godot_skin;
+ const Ref<Skin> skin_j = p_state->skins[j]->godot_skin;
if (_skins_are_same(skin_i, skin_j)) {
// replace it and delete the old
- state->skins.write[j]->godot_skin = skin_i;
+ p_state->skins.write[j]->godot_skin = skin_i;
}
}
}
}
-Error GLTFDocument::_serialize_lights(Ref<GLTFState> state) {
- if (state->lights.is_empty()) {
+Error GLTFDocument::_serialize_lights(Ref<GLTFState> p_state) {
+ if (p_state->lights.is_empty()) {
return OK;
}
Array lights;
- for (GLTFLightIndex i = 0; i < state->lights.size(); i++) {
- lights.push_back(state->lights[i]->to_dictionary());
+ for (GLTFLightIndex i = 0; i < p_state->lights.size(); i++) {
+ lights.push_back(p_state->lights[i]->to_dictionary());
}
Dictionary extensions;
- if (state->json.has("extensions")) {
- extensions = state->json["extensions"];
+ if (p_state->json.has("extensions")) {
+ extensions = p_state->json["extensions"];
} else {
- state->json["extensions"] = extensions;
+ p_state->json["extensions"] = extensions;
}
Dictionary lights_punctual;
extensions["KHR_lights_punctual"] = lights_punctual;
lights_punctual["lights"] = lights;
- print_verbose("glTF: Total lights: " + itos(state->lights.size()));
+ print_verbose("glTF: Total lights: " + itos(p_state->lights.size()));
return OK;
}
-Error GLTFDocument::_serialize_cameras(Ref<GLTFState> state) {
+Error GLTFDocument::_serialize_cameras(Ref<GLTFState> p_state) {
Array cameras;
- cameras.resize(state->cameras.size());
- for (GLTFCameraIndex i = 0; i < state->cameras.size(); i++) {
- cameras[i] = state->cameras[i]->to_dictionary();
+ cameras.resize(p_state->cameras.size());
+ for (GLTFCameraIndex i = 0; i < p_state->cameras.size(); i++) {
+ cameras[i] = p_state->cameras[i]->to_dictionary();
}
- if (!state->cameras.size()) {
+ if (!p_state->cameras.size()) {
return OK;
}
- state->json["cameras"] = cameras;
+ p_state->json["cameras"] = cameras;
- print_verbose("glTF: Total cameras: " + itos(state->cameras.size()));
+ print_verbose("glTF: Total cameras: " + itos(p_state->cameras.size()));
return OK;
}
-Error GLTFDocument::_parse_lights(Ref<GLTFState> state) {
- if (!state->json.has("extensions")) {
+Error GLTFDocument::_parse_lights(Ref<GLTFState> p_state) {
+ if (!p_state->json.has("extensions")) {
return OK;
}
- Dictionary extensions = state->json["extensions"];
+ Dictionary extensions = p_state->json["extensions"];
if (!extensions.has("KHR_lights_punctual")) {
return OK;
}
@@ -4707,26 +4718,26 @@ Error GLTFDocument::_parse_lights(Ref<GLTFState> state) {
if (light.is_null()) {
return Error::ERR_PARSE_ERROR;
}
- state->lights.push_back(light);
+ p_state->lights.push_back(light);
}
- print_verbose("glTF: Total lights: " + itos(state->lights.size()));
+ print_verbose("glTF: Total lights: " + itos(p_state->lights.size()));
return OK;
}
-Error GLTFDocument::_parse_cameras(Ref<GLTFState> state) {
- if (!state->json.has("cameras")) {
+Error GLTFDocument::_parse_cameras(Ref<GLTFState> p_state) {
+ if (!p_state->json.has("cameras")) {
return OK;
}
- const Array cameras = state->json["cameras"];
+ const Array cameras = p_state->json["cameras"];
for (GLTFCameraIndex i = 0; i < cameras.size(); i++) {
- state->cameras.push_back(GLTFCamera::from_dictionary(cameras[i]));
+ p_state->cameras.push_back(GLTFCamera::from_dictionary(cameras[i]));
}
- print_verbose("glTF: Total cameras: " + itos(state->cameras.size()));
+ print_verbose("glTF: Total cameras: " + itos(p_state->cameras.size()));
return OK;
}
@@ -4746,24 +4757,24 @@ String GLTFDocument::interpolation_to_string(const GLTFAnimation::Interpolation
return interp;
}
-Error GLTFDocument::_serialize_animations(Ref<GLTFState> state) {
- if (!state->animation_players.size()) {
+Error GLTFDocument::_serialize_animations(Ref<GLTFState> p_state) {
+ if (!p_state->animation_players.size()) {
return OK;
}
- for (int32_t player_i = 0; player_i < state->animation_players.size(); player_i++) {
+ for (int32_t player_i = 0; player_i < p_state->animation_players.size(); player_i++) {
List<StringName> animation_names;
- AnimationPlayer *animation_player = state->animation_players[player_i];
+ AnimationPlayer *animation_player = p_state->animation_players[player_i];
animation_player->get_animation_list(&animation_names);
if (animation_names.size()) {
for (int animation_name_i = 0; animation_name_i < animation_names.size(); animation_name_i++) {
- _convert_animation(state, animation_player, animation_names[animation_name_i]);
+ _convert_animation(p_state, animation_player, animation_names[animation_name_i]);
}
}
}
Array animations;
- for (GLTFAnimationIndex animation_i = 0; animation_i < state->animations.size(); animation_i++) {
+ for (GLTFAnimationIndex animation_i = 0; animation_i < p_state->animations.size(); animation_i++) {
Dictionary d;
- Ref<GLTFAnimation> gltf_animation = state->animations[animation_i];
+ Ref<GLTFAnimation> gltf_animation = p_state->animations[animation_i];
if (!gltf_animation->get_tracks().size()) {
continue;
}
@@ -4783,9 +4794,9 @@ Error GLTFDocument::_serialize_animations(Ref<GLTFState> state) {
s["interpolation"] = interpolation_to_string(track.position_track.interpolation);
Vector<real_t> times = Variant(track.position_track.times);
- s["input"] = _encode_accessor_as_floats(state, times, false);
+ s["input"] = _encode_accessor_as_floats(p_state, times, false);
Vector<Vector3> values = Variant(track.position_track.values);
- s["output"] = _encode_accessor_as_vec3(state, values, false);
+ s["output"] = _encode_accessor_as_vec3(p_state, values, false);
samplers.push_back(s);
@@ -4803,9 +4814,9 @@ Error GLTFDocument::_serialize_animations(Ref<GLTFState> state) {
s["interpolation"] = interpolation_to_string(track.rotation_track.interpolation);
Vector<real_t> times = Variant(track.rotation_track.times);
- s["input"] = _encode_accessor_as_floats(state, times, false);
+ s["input"] = _encode_accessor_as_floats(p_state, times, false);
Vector<Quaternion> values = track.rotation_track.values;
- s["output"] = _encode_accessor_as_quaternions(state, values, false);
+ s["output"] = _encode_accessor_as_quaternions(p_state, values, false);
samplers.push_back(s);
@@ -4823,9 +4834,9 @@ Error GLTFDocument::_serialize_animations(Ref<GLTFState> state) {
s["interpolation"] = interpolation_to_string(track.scale_track.interpolation);
Vector<real_t> times = Variant(track.scale_track.times);
- s["input"] = _encode_accessor_as_floats(state, times, false);
+ s["input"] = _encode_accessor_as_floats(p_state, times, false);
Vector<Vector3> values = Variant(track.scale_track.values);
- s["output"] = _encode_accessor_as_vec3(state, values, false);
+ s["output"] = _encode_accessor_as_vec3(p_state, values, false);
samplers.push_back(s);
@@ -4903,8 +4914,8 @@ Error GLTFDocument::_serialize_animations(Ref<GLTFState> state) {
}
s["interpolation"] = interpolation_to_string(track.weight_tracks[track.weight_tracks.size() - 1].interpolation);
- s["input"] = _encode_accessor_as_floats(state, all_track_times, false);
- s["output"] = _encode_accessor_as_floats(state, all_track_values, false);
+ s["input"] = _encode_accessor_as_floats(p_state, all_track_times, false);
+ s["output"] = _encode_accessor_as_floats(p_state, all_track_values, false);
samplers.push_back(s);
@@ -4926,19 +4937,19 @@ Error GLTFDocument::_serialize_animations(Ref<GLTFState> state) {
if (!animations.size()) {
return OK;
}
- state->json["animations"] = animations;
+ p_state->json["animations"] = animations;
- print_verbose("glTF: Total animations '" + itos(state->animations.size()) + "'.");
+ print_verbose("glTF: Total animations '" + itos(p_state->animations.size()) + "'.");
return OK;
}
-Error GLTFDocument::_parse_animations(Ref<GLTFState> state) {
- if (!state->json.has("animations")) {
+Error GLTFDocument::_parse_animations(Ref<GLTFState> p_state) {
+ if (!p_state->json.has("animations")) {
return OK;
}
- const Array &animations = state->json["animations"];
+ const Array &animations = p_state->json["animations"];
for (GLTFAnimationIndex i = 0; i < animations.size(); i++) {
const Dictionary &d = animations[i];
@@ -4959,7 +4970,7 @@ Error GLTFDocument::_parse_animations(Ref<GLTFState> state) {
if (anim_name_lower.begins_with("loop") || anim_name_lower.ends_with("loop") || anim_name_lower.begins_with("cycle") || anim_name_lower.ends_with("cycle")) {
animation->set_loop(true);
}
- animation->set_name(_gen_unique_animation_name(state, anim_name));
+ animation->set_name(_gen_unique_animation_name(p_state, anim_name));
}
for (int j = 0; j < channels.size(); j++) {
@@ -4980,7 +4991,7 @@ Error GLTFDocument::_parse_animations(Ref<GLTFState> state) {
GLTFNodeIndex node = t["node"];
String path = t["path"];
- ERR_FAIL_INDEX_V(node, state->nodes.size(), ERR_PARSE_ERROR);
+ ERR_FAIL_INDEX_V(node, p_state->nodes.size(), ERR_PARSE_ERROR);
GLTFAnimation::Track *track = nullptr;
@@ -5015,27 +5026,27 @@ Error GLTFDocument::_parse_animations(Ref<GLTFState> state) {
}
}
- const Vector<float> times = _decode_accessor_as_floats(state, input, false);
+ const Vector<float> times = _decode_accessor_as_floats(p_state, input, false);
if (path == "translation") {
- const Vector<Vector3> positions = _decode_accessor_as_vec3(state, output, false);
+ const Vector<Vector3> positions = _decode_accessor_as_vec3(p_state, output, false);
track->position_track.interpolation = interp;
track->position_track.times = Variant(times); //convert via variant
track->position_track.values = Variant(positions); //convert via variant
} else if (path == "rotation") {
- const Vector<Quaternion> rotations = _decode_accessor_as_quaternion(state, output, false);
+ const Vector<Quaternion> rotations = _decode_accessor_as_quaternion(p_state, output, false);
track->rotation_track.interpolation = interp;
track->rotation_track.times = Variant(times); //convert via variant
track->rotation_track.values = rotations;
} else if (path == "scale") {
- const Vector<Vector3> scales = _decode_accessor_as_vec3(state, output, false);
+ const Vector<Vector3> scales = _decode_accessor_as_vec3(p_state, output, false);
track->scale_track.interpolation = interp;
track->scale_track.times = Variant(times); //convert via variant
track->scale_track.values = Variant(scales); //convert via variant
} else if (path == "weights") {
- const Vector<float> weights = _decode_accessor_as_floats(state, output, false);
+ const Vector<float> weights = _decode_accessor_as_floats(p_state, output, false);
- ERR_FAIL_INDEX_V(state->nodes[node]->mesh, state->meshes.size(), ERR_PARSE_ERROR);
- Ref<GLTFMesh> mesh = state->meshes[state->nodes[node]->mesh];
+ ERR_FAIL_INDEX_V(p_state->nodes[node]->mesh, p_state->meshes.size(), ERR_PARSE_ERROR);
+ Ref<GLTFMesh> mesh = p_state->meshes[p_state->nodes[node]->mesh];
ERR_CONTINUE(!mesh->get_blend_weights().size());
const int wc = mesh->get_blend_weights().size();
@@ -5063,17 +5074,17 @@ Error GLTFDocument::_parse_animations(Ref<GLTFState> state) {
}
}
- state->animations.push_back(animation);
+ p_state->animations.push_back(animation);
}
- print_verbose("glTF: Total animations '" + itos(state->animations.size()) + "'.");
+ print_verbose("glTF: Total animations '" + itos(p_state->animations.size()) + "'.");
return OK;
}
-void GLTFDocument::_assign_scene_names(Ref<GLTFState> state) {
- for (int i = 0; i < state->nodes.size(); i++) {
- Ref<GLTFNode> n = state->nodes[i];
+void GLTFDocument::_assign_scene_names(Ref<GLTFState> p_state) {
+ for (int i = 0; i < p_state->nodes.size(); i++) {
+ Ref<GLTFNode> n = p_state->nodes[i];
// Any joints get unique names generated when the skeleton is made, unique to the skeleton
if (n->skeleton >= 0) {
@@ -5082,21 +5093,21 @@ void GLTFDocument::_assign_scene_names(Ref<GLTFState> state) {
if (n->get_name().is_empty()) {
if (n->mesh >= 0) {
- n->set_name(_gen_unique_name(state, "Mesh"));
+ n->set_name(_gen_unique_name(p_state, "Mesh"));
} else if (n->camera >= 0) {
- n->set_name(_gen_unique_name(state, "Camera3D"));
+ n->set_name(_gen_unique_name(p_state, "Camera3D"));
} else {
- n->set_name(_gen_unique_name(state, "Node"));
+ n->set_name(_gen_unique_name(p_state, "Node"));
}
}
- n->set_name(_gen_unique_name(state, n->get_name()));
+ n->set_name(_gen_unique_name(p_state, n->get_name()));
}
}
-BoneAttachment3D *GLTFDocument::_generate_bone_attachment(Ref<GLTFState> state, Skeleton3D *skeleton, const GLTFNodeIndex node_index, const GLTFNodeIndex bone_index) {
- Ref<GLTFNode> gltf_node = state->nodes[node_index];
- Ref<GLTFNode> bone_node = state->nodes[bone_index];
+BoneAttachment3D *GLTFDocument::_generate_bone_attachment(Ref<GLTFState> p_state, Skeleton3D *p_skeleton, const GLTFNodeIndex p_node_index, const GLTFNodeIndex p_bone_index) {
+ Ref<GLTFNode> gltf_node = p_state->nodes[p_node_index];
+ Ref<GLTFNode> bone_node = p_state->nodes[p_bone_index];
BoneAttachment3D *bone_attachment = memnew(BoneAttachment3D);
print_verbose("glTF: Creating bone attachment for: " + gltf_node->get_name());
@@ -5107,7 +5118,7 @@ BoneAttachment3D *GLTFDocument::_generate_bone_attachment(Ref<GLTFState> state,
return bone_attachment;
}
-GLTFMeshIndex GLTFDocument::_convert_mesh_to_gltf(Ref<GLTFState> state, MeshInstance3D *p_mesh_instance) {
+GLTFMeshIndex GLTFDocument::_convert_mesh_to_gltf(Ref<GLTFState> p_state, MeshInstance3D *p_mesh_instance) {
ERR_FAIL_NULL_V(p_mesh_instance, -1);
if (p_mesh_instance->get_mesh().is_null()) {
return -1;
@@ -5138,20 +5149,20 @@ GLTFMeshIndex GLTFDocument::_convert_mesh_to_gltf(Ref<GLTFState> state, MeshInst
gltf_mesh->set_instance_materials(instance_materials);
gltf_mesh->set_mesh(current_mesh);
gltf_mesh->set_blend_weights(blend_weights);
- GLTFMeshIndex mesh_i = state->meshes.size();
- state->meshes.push_back(gltf_mesh);
+ GLTFMeshIndex mesh_i = p_state->meshes.size();
+ p_state->meshes.push_back(gltf_mesh);
return mesh_i;
}
-ImporterMeshInstance3D *GLTFDocument::_generate_mesh_instance(Ref<GLTFState> state, const GLTFNodeIndex node_index) {
- Ref<GLTFNode> gltf_node = state->nodes[node_index];
+ImporterMeshInstance3D *GLTFDocument::_generate_mesh_instance(Ref<GLTFState> p_state, const GLTFNodeIndex p_node_index) {
+ Ref<GLTFNode> gltf_node = p_state->nodes[p_node_index];
- ERR_FAIL_INDEX_V(gltf_node->mesh, state->meshes.size(), nullptr);
+ ERR_FAIL_INDEX_V(gltf_node->mesh, p_state->meshes.size(), nullptr);
ImporterMeshInstance3D *mi = memnew(ImporterMeshInstance3D);
print_verbose("glTF: Creating mesh for: " + gltf_node->get_name());
- Ref<GLTFMesh> mesh = state->meshes.write[gltf_node->mesh];
+ Ref<GLTFMesh> mesh = p_state->meshes.write[gltf_node->mesh];
if (mesh.is_null()) {
return mi;
}
@@ -5163,56 +5174,56 @@ ImporterMeshInstance3D *GLTFDocument::_generate_mesh_instance(Ref<GLTFState> sta
return mi;
}
-Light3D *GLTFDocument::_generate_light(Ref<GLTFState> state, const GLTFNodeIndex node_index) {
- Ref<GLTFNode> gltf_node = state->nodes[node_index];
+Light3D *GLTFDocument::_generate_light(Ref<GLTFState> p_state, const GLTFNodeIndex p_node_index) {
+ Ref<GLTFNode> gltf_node = p_state->nodes[p_node_index];
- ERR_FAIL_INDEX_V(gltf_node->light, state->lights.size(), nullptr);
+ ERR_FAIL_INDEX_V(gltf_node->light, p_state->lights.size(), nullptr);
print_verbose("glTF: Creating light for: " + gltf_node->get_name());
- Ref<GLTFLight> l = state->lights[gltf_node->light];
+ Ref<GLTFLight> l = p_state->lights[gltf_node->light];
return l->to_node();
}
-Camera3D *GLTFDocument::_generate_camera(Ref<GLTFState> state, const GLTFNodeIndex node_index) {
- Ref<GLTFNode> gltf_node = state->nodes[node_index];
+Camera3D *GLTFDocument::_generate_camera(Ref<GLTFState> p_state, const GLTFNodeIndex p_node_index) {
+ Ref<GLTFNode> gltf_node = p_state->nodes[p_node_index];
- ERR_FAIL_INDEX_V(gltf_node->camera, state->cameras.size(), nullptr);
+ ERR_FAIL_INDEX_V(gltf_node->camera, p_state->cameras.size(), nullptr);
print_verbose("glTF: Creating camera for: " + gltf_node->get_name());
- Ref<GLTFCamera> c = state->cameras[gltf_node->camera];
+ Ref<GLTFCamera> c = p_state->cameras[gltf_node->camera];
return c->to_node();
}
-GLTFCameraIndex GLTFDocument::_convert_camera(Ref<GLTFState> state, Camera3D *p_camera) {
+GLTFCameraIndex GLTFDocument::_convert_camera(Ref<GLTFState> p_state, Camera3D *p_camera) {
print_verbose("glTF: Converting camera: " + p_camera->get_name());
Ref<GLTFCamera> c = GLTFCamera::from_node(p_camera);
- GLTFCameraIndex camera_index = state->cameras.size();
- state->cameras.push_back(c);
+ GLTFCameraIndex camera_index = p_state->cameras.size();
+ p_state->cameras.push_back(c);
return camera_index;
}
-GLTFLightIndex GLTFDocument::_convert_light(Ref<GLTFState> state, Light3D *p_light) {
+GLTFLightIndex GLTFDocument::_convert_light(Ref<GLTFState> p_state, Light3D *p_light) {
print_verbose("glTF: Converting light: " + p_light->get_name());
Ref<GLTFLight> l = GLTFLight::from_node(p_light);
- GLTFLightIndex light_index = state->lights.size();
- state->lights.push_back(l);
+ GLTFLightIndex light_index = p_state->lights.size();
+ p_state->lights.push_back(l);
return light_index;
}
-void GLTFDocument::_convert_spatial(Ref<GLTFState> state, Node3D *p_spatial, Ref<GLTFNode> p_node) {
+void GLTFDocument::_convert_spatial(Ref<GLTFState> p_state, Node3D *p_spatial, Ref<GLTFNode> p_node) {
Transform3D xform = p_spatial->get_transform();
p_node->scale = xform.basis.get_scale();
p_node->rotation = xform.basis.get_rotation_quaternion();
p_node->position = xform.origin;
}
-Node3D *GLTFDocument::_generate_spatial(Ref<GLTFState> state, const GLTFNodeIndex node_index) {
- Ref<GLTFNode> gltf_node = state->nodes[node_index];
+Node3D *GLTFDocument::_generate_spatial(Ref<GLTFState> p_state, const GLTFNodeIndex p_node_index) {
+ Ref<GLTFNode> gltf_node = p_state->nodes[p_node_index];
Node3D *spatial = memnew(Node3D);
print_verbose("glTF: Converting spatial: " + gltf_node->get_name());
@@ -5220,7 +5231,7 @@ Node3D *GLTFDocument::_generate_spatial(Ref<GLTFState> state, const GLTFNodeInde
return spatial;
}
-void GLTFDocument::_convert_scene_node(Ref<GLTFState> state, Node *p_current, const GLTFNodeIndex p_gltf_parent, const GLTFNodeIndex p_gltf_root) {
+void GLTFDocument::_convert_scene_node(Ref<GLTFState> p_state, Node *p_current, const GLTFNodeIndex p_gltf_parent, const GLTFNodeIndex p_gltf_root) {
bool retflag = true;
_check_visibility(p_current, retflag);
if (retflag) {
@@ -5228,64 +5239,68 @@ void GLTFDocument::_convert_scene_node(Ref<GLTFState> state, Node *p_current, co
}
Ref<GLTFNode> gltf_node;
gltf_node.instantiate();
- gltf_node->set_name(_gen_unique_name(state, p_current->get_name()));
+ gltf_node->set_name(_gen_unique_name(p_state, p_current->get_name()));
if (cast_to<Node3D>(p_current)) {
Node3D *spatial = cast_to<Node3D>(p_current);
- _convert_spatial(state, spatial, gltf_node);
+ _convert_spatial(p_state, spatial, gltf_node);
}
if (cast_to<MeshInstance3D>(p_current)) {
MeshInstance3D *mi = cast_to<MeshInstance3D>(p_current);
- _convert_mesh_instance_to_gltf(mi, state, gltf_node);
+ _convert_mesh_instance_to_gltf(mi, p_state, gltf_node);
} else if (cast_to<BoneAttachment3D>(p_current)) {
BoneAttachment3D *bone = cast_to<BoneAttachment3D>(p_current);
- _convert_bone_attachment_to_gltf(bone, state, p_gltf_parent, p_gltf_root, gltf_node);
+ _convert_bone_attachment_to_gltf(bone, p_state, p_gltf_parent, p_gltf_root, gltf_node);
return;
} else if (cast_to<Skeleton3D>(p_current)) {
Skeleton3D *skel = cast_to<Skeleton3D>(p_current);
- _convert_skeleton_to_gltf(skel, state, p_gltf_parent, p_gltf_root, gltf_node);
+ _convert_skeleton_to_gltf(skel, p_state, p_gltf_parent, p_gltf_root, gltf_node);
// We ignore the Godot Engine node that is the skeleton.
return;
} else if (cast_to<MultiMeshInstance3D>(p_current)) {
MultiMeshInstance3D *multi = cast_to<MultiMeshInstance3D>(p_current);
- _convert_multi_mesh_instance_to_gltf(multi, p_gltf_parent, p_gltf_root, gltf_node, state);
+ _convert_multi_mesh_instance_to_gltf(multi, p_gltf_parent, p_gltf_root, gltf_node, p_state);
#ifdef MODULE_CSG_ENABLED
} else if (cast_to<CSGShape3D>(p_current)) {
CSGShape3D *shape = cast_to<CSGShape3D>(p_current);
if (shape->get_parent() && shape->is_root_shape()) {
- _convert_csg_shape_to_gltf(shape, p_gltf_parent, gltf_node, state);
+ _convert_csg_shape_to_gltf(shape, p_gltf_parent, gltf_node, p_state);
}
#endif // MODULE_CSG_ENABLED
#ifdef MODULE_GRIDMAP_ENABLED
} else if (cast_to<GridMap>(p_current)) {
GridMap *gridmap = Object::cast_to<GridMap>(p_current);
- _convert_grid_map_to_gltf(gridmap, p_gltf_parent, p_gltf_root, gltf_node, state);
+ _convert_grid_map_to_gltf(gridmap, p_gltf_parent, p_gltf_root, gltf_node, p_state);
#endif // MODULE_GRIDMAP_ENABLED
} else if (cast_to<Camera3D>(p_current)) {
Camera3D *camera = Object::cast_to<Camera3D>(p_current);
- _convert_camera_to_gltf(camera, state, gltf_node);
+ _convert_camera_to_gltf(camera, p_state, gltf_node);
} else if (cast_to<Light3D>(p_current)) {
Light3D *light = Object::cast_to<Light3D>(p_current);
- _convert_light_to_gltf(light, state, gltf_node);
+ _convert_light_to_gltf(light, p_state, gltf_node);
} else if (cast_to<AnimationPlayer>(p_current)) {
AnimationPlayer *animation_player = Object::cast_to<AnimationPlayer>(p_current);
- _convert_animation_player_to_gltf(animation_player, state, p_gltf_parent, p_gltf_root, gltf_node, p_current);
+ _convert_animation_player_to_gltf(animation_player, p_state, p_gltf_parent, p_gltf_root, gltf_node, p_current);
}
- GLTFNodeIndex current_node_i = state->nodes.size();
+ for (Ref<GLTFDocumentExtension> ext : document_extensions) {
+ ERR_CONTINUE(ext.is_null());
+ ext->convert_scene_node(p_state, gltf_node, p_current);
+ }
+ GLTFNodeIndex current_node_i = p_state->nodes.size();
GLTFNodeIndex gltf_root = p_gltf_root;
if (gltf_root == -1) {
gltf_root = current_node_i;
Array scenes;
scenes.push_back(gltf_root);
- state->json["scene"] = scenes;
+ p_state->json["scene"] = scenes;
}
- _create_gltf_node(state, p_current, current_node_i, p_gltf_parent, gltf_root, gltf_node);
+ _create_gltf_node(p_state, p_current, current_node_i, p_gltf_parent, gltf_root, gltf_node);
for (int node_i = 0; node_i < p_current->get_child_count(); node_i++) {
- _convert_scene_node(state, p_current->get_child(node_i), current_node_i, gltf_root);
+ _convert_scene_node(p_state, p_current->get_child(node_i), current_node_i, gltf_root);
}
}
#ifdef MODULE_CSG_ENABLED
-void GLTFDocument::_convert_csg_shape_to_gltf(CSGShape3D *p_current, GLTFNodeIndex p_gltf_parent, Ref<GLTFNode> gltf_node, Ref<GLTFState> state) {
+void GLTFDocument::_convert_csg_shape_to_gltf(CSGShape3D *p_current, GLTFNodeIndex p_gltf_parent, Ref<GLTFNode> p_gltf_node, Ref<GLTFState> p_state) {
CSGShape3D *csg = p_current;
csg->call("_update_shape");
Array meshes = csg->get_meshes();
@@ -5317,34 +5332,34 @@ void GLTFDocument::_convert_csg_shape_to_gltf(CSGShape3D *p_current, GLTFNodeInd
Ref<GLTFMesh> gltf_mesh;
gltf_mesh.instantiate();
gltf_mesh->set_mesh(mesh);
- GLTFMeshIndex mesh_i = state->meshes.size();
- state->meshes.push_back(gltf_mesh);
- gltf_node->mesh = mesh_i;
- gltf_node->xform = csg->get_meshes()[0];
- gltf_node->set_name(_gen_unique_name(state, csg->get_name()));
+ GLTFMeshIndex mesh_i = p_state->meshes.size();
+ p_state->meshes.push_back(gltf_mesh);
+ p_gltf_node->mesh = mesh_i;
+ p_gltf_node->xform = csg->get_meshes()[0];
+ p_gltf_node->set_name(_gen_unique_name(p_state, csg->get_name()));
}
#endif // MODULE_CSG_ENABLED
-void GLTFDocument::_create_gltf_node(Ref<GLTFState> state, Node *p_scene_parent, GLTFNodeIndex current_node_i,
- GLTFNodeIndex p_parent_node_index, GLTFNodeIndex p_root_gltf_node, Ref<GLTFNode> gltf_node) {
- state->scene_nodes.insert(current_node_i, p_scene_parent);
- state->nodes.push_back(gltf_node);
- ERR_FAIL_COND(current_node_i == p_parent_node_index);
- state->nodes.write[current_node_i]->parent = p_parent_node_index;
+void GLTFDocument::_create_gltf_node(Ref<GLTFState> p_state, Node *p_scene_parent, GLTFNodeIndex p_current_node_i,
+ GLTFNodeIndex p_parent_node_index, GLTFNodeIndex p_root_gltf_node, Ref<GLTFNode> p_gltf_node) {
+ p_state->scene_nodes.insert(p_current_node_i, p_scene_parent);
+ p_state->nodes.push_back(p_gltf_node);
+ ERR_FAIL_COND(p_current_node_i == p_parent_node_index);
+ p_state->nodes.write[p_current_node_i]->parent = p_parent_node_index;
if (p_parent_node_index == -1) {
return;
}
- state->nodes.write[p_parent_node_index]->children.push_back(current_node_i);
+ p_state->nodes.write[p_parent_node_index]->children.push_back(p_current_node_i);
}
-void GLTFDocument::_convert_animation_player_to_gltf(AnimationPlayer *animation_player, Ref<GLTFState> state, GLTFNodeIndex p_gltf_current, GLTFNodeIndex p_gltf_root_index, Ref<GLTFNode> p_gltf_node, Node *p_scene_parent) {
- ERR_FAIL_COND(!animation_player);
- state->animation_players.push_back(animation_player);
- print_verbose(String("glTF: Converting animation player: ") + animation_player->get_name());
+void GLTFDocument::_convert_animation_player_to_gltf(AnimationPlayer *p_animation_player, Ref<GLTFState> p_state, GLTFNodeIndex p_gltf_current, GLTFNodeIndex p_gltf_root_index, Ref<GLTFNode> p_gltf_node, Node *p_scene_parent) {
+ ERR_FAIL_COND(!p_animation_player);
+ p_state->animation_players.push_back(p_animation_player);
+ print_verbose(String("glTF: Converting animation player: ") + p_animation_player->get_name());
}
-void GLTFDocument::_check_visibility(Node *p_node, bool &retflag) {
- retflag = true;
+void GLTFDocument::_check_visibility(Node *p_node, bool &r_retflag) {
+ r_retflag = true;
Node3D *spatial = Object::cast_to<Node3D>(p_node);
Node2D *node_2d = Object::cast_to<Node2D>(p_node);
if (node_2d && !node_2d->is_visible()) {
@@ -5353,32 +5368,32 @@ void GLTFDocument::_check_visibility(Node *p_node, bool &retflag) {
if (spatial && !spatial->is_visible()) {
return;
}
- retflag = false;
+ r_retflag = false;
}
-void GLTFDocument::_convert_camera_to_gltf(Camera3D *camera, Ref<GLTFState> state, Ref<GLTFNode> gltf_node) {
+void GLTFDocument::_convert_camera_to_gltf(Camera3D *camera, Ref<GLTFState> p_state, Ref<GLTFNode> p_gltf_node) {
ERR_FAIL_COND(!camera);
- GLTFCameraIndex camera_index = _convert_camera(state, camera);
+ GLTFCameraIndex camera_index = _convert_camera(p_state, camera);
if (camera_index != -1) {
- gltf_node->camera = camera_index;
+ p_gltf_node->camera = camera_index;
}
}
-void GLTFDocument::_convert_light_to_gltf(Light3D *light, Ref<GLTFState> state, Ref<GLTFNode> gltf_node) {
+void GLTFDocument::_convert_light_to_gltf(Light3D *light, Ref<GLTFState> p_state, Ref<GLTFNode> p_gltf_node) {
ERR_FAIL_COND(!light);
- GLTFLightIndex light_index = _convert_light(state, light);
+ GLTFLightIndex light_index = _convert_light(p_state, light);
if (light_index != -1) {
- gltf_node->light = light_index;
+ p_gltf_node->light = light_index;
}
}
#ifdef MODULE_GRIDMAP_ENABLED
-void GLTFDocument::_convert_grid_map_to_gltf(GridMap *p_grid_map, GLTFNodeIndex p_parent_node_index, GLTFNodeIndex p_root_node_index, Ref<GLTFNode> gltf_node, Ref<GLTFState> state) {
+void GLTFDocument::_convert_grid_map_to_gltf(GridMap *p_grid_map, GLTFNodeIndex p_parent_node_index, GLTFNodeIndex p_root_node_index, Ref<GLTFNode> p_gltf_node, Ref<GLTFState> p_state) {
Array cells = p_grid_map->get_used_cells();
for (int32_t k = 0; k < cells.size(); k++) {
GLTFNode *new_gltf_node = memnew(GLTFNode);
- gltf_node->children.push_back(state->nodes.size());
- state->nodes.push_back(new_gltf_node);
+ p_gltf_node->children.push_back(p_state->nodes.size());
+ p_state->nodes.push_back(new_gltf_node);
Vector3 cell_location = cells[k];
int32_t cell = p_grid_map->get_cell_item(
Vector3(cell_location.x, cell_location.y, cell_location.z));
@@ -5394,10 +5409,10 @@ void GLTFDocument::_convert_grid_map_to_gltf(GridMap *p_grid_map, GLTFNodeIndex
Ref<GLTFMesh> gltf_mesh;
gltf_mesh.instantiate();
gltf_mesh->set_mesh(_mesh_to_importer_mesh(p_grid_map->get_mesh_library()->get_item_mesh(cell)));
- new_gltf_node->mesh = state->meshes.size();
- state->meshes.push_back(gltf_mesh);
+ new_gltf_node->mesh = p_state->meshes.size();
+ p_state->meshes.push_back(gltf_mesh);
new_gltf_node->xform = cell_xform * p_grid_map->get_transform();
- new_gltf_node->set_name(_gen_unique_name(state, p_grid_map->get_mesh_library()->get_item_name(cell)));
+ new_gltf_node->set_name(_gen_unique_name(p_state, p_grid_map->get_mesh_library()->get_item_name(cell)));
}
}
#endif // MODULE_GRIDMAP_ENABLED
@@ -5406,7 +5421,7 @@ void GLTFDocument::_convert_multi_mesh_instance_to_gltf(
MultiMeshInstance3D *p_multi_mesh_instance,
GLTFNodeIndex p_parent_node_index,
GLTFNodeIndex p_root_node_index,
- Ref<GLTFNode> gltf_node, Ref<GLTFState> state) {
+ Ref<GLTFNode> p_gltf_node, Ref<GLTFState> p_state) {
ERR_FAIL_COND(!p_multi_mesh_instance);
Ref<MultiMesh> multi_mesh = p_multi_mesh_instance->get_multimesh();
if (multi_mesh.is_null()) {
@@ -5442,8 +5457,8 @@ void GLTFDocument::_convert_multi_mesh_instance_to_gltf(
blend_arrays, mesh->surface_get_lods(surface_i), mat, material_name, mesh->surface_get_format(surface_i));
}
gltf_mesh->set_mesh(importer_mesh);
- GLTFMeshIndex mesh_index = state->meshes.size();
- state->meshes.push_back(gltf_mesh);
+ GLTFMeshIndex mesh_index = p_state->meshes.size();
+ p_state->meshes.push_back(gltf_mesh);
for (int32_t instance_i = 0; instance_i < multi_mesh->get_instance_count();
instance_i++) {
Transform3D transform;
@@ -5465,22 +5480,22 @@ void GLTFDocument::_convert_multi_mesh_instance_to_gltf(
new_gltf_node.instantiate();
new_gltf_node->mesh = mesh_index;
new_gltf_node->xform = transform;
- new_gltf_node->set_name(_gen_unique_name(state, p_multi_mesh_instance->get_name()));
- gltf_node->children.push_back(state->nodes.size());
- state->nodes.push_back(new_gltf_node);
+ new_gltf_node->set_name(_gen_unique_name(p_state, p_multi_mesh_instance->get_name()));
+ p_gltf_node->children.push_back(p_state->nodes.size());
+ p_state->nodes.push_back(new_gltf_node);
}
}
-void GLTFDocument::_convert_skeleton_to_gltf(Skeleton3D *p_skeleton3d, Ref<GLTFState> state, GLTFNodeIndex p_parent_node_index, GLTFNodeIndex p_root_node_index, Ref<GLTFNode> gltf_node) {
+void GLTFDocument::_convert_skeleton_to_gltf(Skeleton3D *p_skeleton3d, Ref<GLTFState> p_state, GLTFNodeIndex p_parent_node_index, GLTFNodeIndex p_root_node_index, Ref<GLTFNode> p_gltf_node) {
Skeleton3D *skeleton = p_skeleton3d;
Ref<GLTFSkeleton> gltf_skeleton;
gltf_skeleton.instantiate();
- // GLTFSkeleton is only used to hold internal state data. It will not be written to the document.
+ // GLTFSkeleton is only used to hold internal p_state data. It will not be written to the document.
//
gltf_skeleton->godot_skeleton = skeleton;
- GLTFSkeletonIndex skeleton_i = state->skeletons.size();
- state->skeleton3d_to_gltf_skeleton[skeleton->get_instance_id()] = skeleton_i;
- state->skeletons.push_back(gltf_skeleton);
+ GLTFSkeletonIndex skeleton_i = p_state->skeletons.size();
+ p_state->skeleton3d_to_gltf_skeleton[skeleton->get_instance_id()] = skeleton_i;
+ p_state->skeletons.push_back(gltf_skeleton);
BoneId bone_count = skeleton->get_bone_count();
for (BoneId bone_i = 0; bone_i < bone_count; bone_i++) {
@@ -5488,15 +5503,15 @@ void GLTFDocument::_convert_skeleton_to_gltf(Skeleton3D *p_skeleton3d, Ref<GLTFS
joint_node.instantiate();
// Note that we cannot use _gen_unique_bone_name here, because glTF spec requires all node
// names to be unique regardless of whether or not they are used as joints.
- joint_node->set_name(_gen_unique_name(state, skeleton->get_bone_name(bone_i)));
+ joint_node->set_name(_gen_unique_name(p_state, skeleton->get_bone_name(bone_i)));
Transform3D xform = skeleton->get_bone_pose(bone_i);
joint_node->scale = xform.basis.get_scale();
joint_node->rotation = xform.basis.get_rotation_quaternion();
joint_node->position = xform.origin;
joint_node->joint = true;
- GLTFNodeIndex current_node_i = state->nodes.size();
- state->scene_nodes.insert(current_node_i, skeleton);
- state->nodes.push_back(joint_node);
+ GLTFNodeIndex current_node_i = p_state->nodes.size();
+ p_state->scene_nodes.insert(current_node_i, skeleton);
+ p_state->nodes.push_back(joint_node);
gltf_skeleton->joints.push_back(current_node_i);
if (skeleton->get_bone_parent(bone_i) == -1) {
@@ -5509,23 +5524,23 @@ void GLTFDocument::_convert_skeleton_to_gltf(Skeleton3D *p_skeleton3d, Ref<GLTFS
BoneId parent_bone_id = skeleton->get_bone_parent(bone_i);
if (parent_bone_id == -1) {
if (p_parent_node_index != -1) {
- state->nodes.write[current_node_i]->parent = p_parent_node_index;
- state->nodes.write[p_parent_node_index]->children.push_back(current_node_i);
+ p_state->nodes.write[current_node_i]->parent = p_parent_node_index;
+ p_state->nodes.write[p_parent_node_index]->children.push_back(current_node_i);
}
} else {
GLTFNodeIndex parent_node_i = gltf_skeleton->godot_bone_node[parent_bone_id];
- state->nodes.write[current_node_i]->parent = parent_node_i;
- state->nodes.write[parent_node_i]->children.push_back(current_node_i);
+ p_state->nodes.write[current_node_i]->parent = parent_node_i;
+ p_state->nodes.write[parent_node_i]->children.push_back(current_node_i);
}
}
// Remove placeholder skeleton3d node by not creating the gltf node
// Skins are per mesh
for (int node_i = 0; node_i < skeleton->get_child_count(); node_i++) {
- _convert_scene_node(state, skeleton->get_child(node_i), p_parent_node_index, p_root_node_index);
+ _convert_scene_node(p_state, skeleton->get_child(node_i), p_parent_node_index, p_root_node_index);
}
}
-void GLTFDocument::_convert_bone_attachment_to_gltf(BoneAttachment3D *p_bone_attachment, Ref<GLTFState> state, GLTFNodeIndex p_parent_node_index, GLTFNodeIndex p_root_node_index, Ref<GLTFNode> gltf_node) {
+void GLTFDocument::_convert_bone_attachment_to_gltf(BoneAttachment3D *p_bone_attachment, Ref<GLTFState> p_state, GLTFNodeIndex p_parent_node_index, GLTFNodeIndex p_root_node_index, Ref<GLTFNode> p_gltf_node) {
Skeleton3D *skeleton;
// Note that relative transforms to external skeletons and pose overrides are not supported.
if (p_bone_attachment->get_use_external_skeleton()) {
@@ -5534,8 +5549,8 @@ void GLTFDocument::_convert_bone_attachment_to_gltf(BoneAttachment3D *p_bone_att
skeleton = cast_to<Skeleton3D>(p_bone_attachment->get_parent());
}
GLTFSkeletonIndex skel_gltf_i = -1;
- if (skeleton != nullptr && state->skeleton3d_to_gltf_skeleton.has(skeleton->get_instance_id())) {
- skel_gltf_i = state->skeleton3d_to_gltf_skeleton[skeleton->get_instance_id()];
+ if (skeleton != nullptr && p_state->skeleton3d_to_gltf_skeleton.has(skeleton->get_instance_id())) {
+ skel_gltf_i = p_state->skeleton3d_to_gltf_skeleton[skeleton->get_instance_id()];
}
int bone_idx = -1;
if (skeleton != nullptr) {
@@ -5546,28 +5561,28 @@ void GLTFDocument::_convert_bone_attachment_to_gltf(BoneAttachment3D *p_bone_att
}
GLTFNodeIndex par_node_index = p_parent_node_index;
if (skeleton != nullptr && bone_idx != -1 && skel_gltf_i != -1) {
- Ref<GLTFSkeleton> gltf_skeleton = state->skeletons.write[skel_gltf_i];
+ Ref<GLTFSkeleton> gltf_skeleton = p_state->skeletons.write[skel_gltf_i];
gltf_skeleton->bone_attachments.push_back(p_bone_attachment);
par_node_index = gltf_skeleton->joints[bone_idx];
}
for (int node_i = 0; node_i < p_bone_attachment->get_child_count(); node_i++) {
- _convert_scene_node(state, p_bone_attachment->get_child(node_i), par_node_index, p_root_node_index);
+ _convert_scene_node(p_state, p_bone_attachment->get_child(node_i), par_node_index, p_root_node_index);
}
}
-void GLTFDocument::_convert_mesh_instance_to_gltf(MeshInstance3D *p_scene_parent, Ref<GLTFState> state, Ref<GLTFNode> gltf_node) {
- GLTFMeshIndex gltf_mesh_index = _convert_mesh_to_gltf(state, p_scene_parent);
+void GLTFDocument::_convert_mesh_instance_to_gltf(MeshInstance3D *p_scene_parent, Ref<GLTFState> p_state, Ref<GLTFNode> p_gltf_node) {
+ GLTFMeshIndex gltf_mesh_index = _convert_mesh_to_gltf(p_state, p_scene_parent);
if (gltf_mesh_index != -1) {
- gltf_node->mesh = gltf_mesh_index;
+ p_gltf_node->mesh = gltf_mesh_index;
}
}
-void GLTFDocument::_generate_scene_node(Ref<GLTFState> state, Node *scene_parent, Node3D *scene_root, const GLTFNodeIndex node_index) {
- Ref<GLTFNode> gltf_node = state->nodes[node_index];
+void GLTFDocument::_generate_scene_node(Ref<GLTFState> p_state, Node *scene_parent, Node3D *scene_root, const GLTFNodeIndex node_index) {
+ Ref<GLTFNode> gltf_node = p_state->nodes[node_index];
if (gltf_node->skeleton >= 0) {
- _generate_skeleton_bone_node(state, scene_parent, scene_root, node_index);
+ _generate_skeleton_bone_node(p_state, scene_parent, scene_root, node_index);
return;
}
@@ -5581,76 +5596,87 @@ void GLTFDocument::_generate_scene_node(Ref<GLTFState> state, Node *scene_parent
// skinned meshes must not be placed in a bone attachment.
if (non_bone_parented_to_skeleton && gltf_node->skin < 0) {
// Bone Attachment - Parent Case
- BoneAttachment3D *bone_attachment = _generate_bone_attachment(state, active_skeleton, node_index, gltf_node->parent);
+ BoneAttachment3D *bone_attachment = _generate_bone_attachment(p_state, active_skeleton, node_index, gltf_node->parent);
scene_parent->add_child(bone_attachment, true);
bone_attachment->set_owner(scene_root);
// There is no gltf_node that represent this, so just directly create a unique name
- bone_attachment->set_name(_gen_unique_name(state, "BoneAttachment3D"));
+ bone_attachment->set_name(_gen_unique_name(p_state, "BoneAttachment3D"));
// We change the scene_parent to our bone attachment now. We do not set current_node because we want to make the node
// and attach it to the bone_attachment
scene_parent = bone_attachment;
}
- if (gltf_node->mesh >= 0) {
- current_node = _generate_mesh_instance(state, node_index);
- } else if (gltf_node->camera >= 0) {
- current_node = _generate_camera(state, node_index);
- } else if (gltf_node->light >= 0) {
- current_node = _generate_light(state, node_index);
+ // Check if any GLTFDocumentExtension classes want to generate a node for us.
+ for (Ref<GLTFDocumentExtension> ext : document_extensions) {
+ ERR_CONTINUE(ext.is_null());
+ current_node = ext->generate_scene_node(p_state, gltf_node, scene_parent);
+ if (current_node) {
+ break;
+ }
}
-
- // We still have not managed to make a node.
+ // If none of our GLTFDocumentExtension classes generated us a node, we generate one.
if (!current_node) {
- current_node = _generate_spatial(state, node_index);
+ if (gltf_node->mesh >= 0) {
+ current_node = _generate_mesh_instance(p_state, node_index);
+ } else if (gltf_node->camera >= 0) {
+ current_node = _generate_camera(p_state, node_index);
+ } else if (gltf_node->light >= 0) {
+ current_node = _generate_light(p_state, node_index);
+ } else {
+ current_node = _generate_spatial(p_state, node_index);
+ }
}
+ // Add the node we generated and set the owner to the scene root.
scene_parent->add_child(current_node, true);
if (current_node != scene_root) {
- current_node->set_owner(scene_root);
+ Array args;
+ args.append(scene_root);
+ current_node->propagate_call(StringName("set_owner"), args);
}
current_node->set_transform(gltf_node->xform);
current_node->set_name(gltf_node->get_name());
- state->scene_nodes.insert(node_index, current_node);
+ p_state->scene_nodes.insert(node_index, current_node);
for (int i = 0; i < gltf_node->children.size(); ++i) {
- _generate_scene_node(state, current_node, scene_root, gltf_node->children[i]);
+ _generate_scene_node(p_state, current_node, scene_root, gltf_node->children[i]);
}
}
-void GLTFDocument::_generate_skeleton_bone_node(Ref<GLTFState> state, Node *scene_parent, Node3D *scene_root, const GLTFNodeIndex node_index) {
- Ref<GLTFNode> gltf_node = state->nodes[node_index];
+void GLTFDocument::_generate_skeleton_bone_node(Ref<GLTFState> p_state, Node *p_scene_parent, Node3D *p_scene_root, const GLTFNodeIndex p_node_index) {
+ Ref<GLTFNode> gltf_node = p_state->nodes[p_node_index];
Node3D *current_node = nullptr;
- Skeleton3D *skeleton = state->skeletons[gltf_node->skeleton]->godot_skeleton;
+ Skeleton3D *skeleton = p_state->skeletons[gltf_node->skeleton]->godot_skeleton;
// In this case, this node is already a bone in skeleton.
const bool is_skinned_mesh = (gltf_node->skin >= 0 && gltf_node->mesh >= 0);
const bool requires_extra_node = (gltf_node->mesh >= 0 || gltf_node->camera >= 0 || gltf_node->light >= 0);
- Skeleton3D *active_skeleton = Object::cast_to<Skeleton3D>(scene_parent);
+ Skeleton3D *active_skeleton = Object::cast_to<Skeleton3D>(p_scene_parent);
if (active_skeleton != skeleton) {
if (active_skeleton) {
// Bone Attachment - Direct Parented Skeleton Case
- BoneAttachment3D *bone_attachment = _generate_bone_attachment(state, active_skeleton, node_index, gltf_node->parent);
+ BoneAttachment3D *bone_attachment = _generate_bone_attachment(p_state, active_skeleton, p_node_index, gltf_node->parent);
- scene_parent->add_child(bone_attachment, true);
- bone_attachment->set_owner(scene_root);
+ p_scene_parent->add_child(bone_attachment, true);
+ bone_attachment->set_owner(p_scene_root);
// There is no gltf_node that represent this, so just directly create a unique name
- bone_attachment->set_name(_gen_unique_name(state, "BoneAttachment3D"));
+ bone_attachment->set_name(_gen_unique_name(p_state, "BoneAttachment3D"));
// We change the scene_parent to our bone attachment now. We do not set current_node because we want to make the node
// and attach it to the bone_attachment
- scene_parent = bone_attachment;
- WARN_PRINT(vformat("glTF: Generating scene detected direct parented Skeletons at node %d", node_index));
+ p_scene_parent = bone_attachment;
+ WARN_PRINT(vformat("glTF: Generating scene detected direct parented Skeletons at node %d", p_node_index));
}
// Add it to the scene if it has not already been added
if (skeleton->get_parent() == nullptr) {
- scene_parent->add_child(skeleton, true);
- skeleton->set_owner(scene_root);
+ p_scene_parent->add_child(skeleton, true);
+ skeleton->set_owner(p_scene_root);
}
}
@@ -5661,40 +5687,53 @@ void GLTFDocument::_generate_skeleton_bone_node(Ref<GLTFState> state, Node *scen
// skinned meshes must not be placed in a bone attachment.
if (!is_skinned_mesh) {
// Bone Attachment - Same Node Case
- BoneAttachment3D *bone_attachment = _generate_bone_attachment(state, active_skeleton, node_index, node_index);
+ BoneAttachment3D *bone_attachment = _generate_bone_attachment(p_state, active_skeleton, p_node_index, p_node_index);
- scene_parent->add_child(bone_attachment, true);
- bone_attachment->set_owner(scene_root);
+ p_scene_parent->add_child(bone_attachment, true);
+ bone_attachment->set_owner(p_scene_root);
// There is no gltf_node that represent this, so just directly create a unique name
- bone_attachment->set_name(_gen_unique_name(state, "BoneAttachment3D"));
+ bone_attachment->set_name(_gen_unique_name(p_state, "BoneAttachment3D"));
// We change the scene_parent to our bone attachment now. We do not set current_node because we want to make the node
// and attach it to the bone_attachment
- scene_parent = bone_attachment;
+ p_scene_parent = bone_attachment;
}
-
- // We still have not managed to make a node
- if (gltf_node->mesh >= 0) {
- current_node = _generate_mesh_instance(state, node_index);
- } else if (gltf_node->camera >= 0) {
- current_node = _generate_camera(state, node_index);
- } else if (gltf_node->light >= 0) {
- current_node = _generate_light(state, node_index);
+ // Check if any GLTFDocumentExtension classes want to generate a node for us.
+ for (Ref<GLTFDocumentExtension> ext : document_extensions) {
+ ERR_CONTINUE(ext.is_null());
+ current_node = ext->generate_scene_node(p_state, gltf_node, p_scene_parent);
+ if (current_node) {
+ break;
+ }
+ }
+ // If none of our GLTFDocumentExtension classes generated us a node, we generate one.
+ if (!current_node) {
+ if (gltf_node->mesh >= 0) {
+ current_node = _generate_mesh_instance(p_state, p_node_index);
+ } else if (gltf_node->camera >= 0) {
+ current_node = _generate_camera(p_state, p_node_index);
+ } else if (gltf_node->light >= 0) {
+ current_node = _generate_light(p_state, p_node_index);
+ } else {
+ current_node = _generate_spatial(p_state, p_node_index);
+ }
}
-
- scene_parent->add_child(current_node, true);
- if (current_node != scene_root) {
- current_node->set_owner(scene_root);
+ // Add the node we generated and set the owner to the scene root.
+ p_scene_parent->add_child(current_node, true);
+ if (current_node != p_scene_root) {
+ Array args;
+ args.append(p_scene_root);
+ current_node->propagate_call(StringName("set_owner"), args);
}
// Do not set transform here. Transform is already applied to our bone.
current_node->set_name(gltf_node->get_name());
}
- state->scene_nodes.insert(node_index, current_node);
+ p_state->scene_nodes.insert(p_node_index, current_node);
for (int i = 0; i < gltf_node->children.size(); ++i) {
- _generate_scene_node(state, active_skeleton, scene_root, gltf_node->children[i]);
+ _generate_scene_node(p_state, active_skeleton, p_scene_root, gltf_node->children[i]);
}
}
@@ -5819,13 +5858,13 @@ T GLTFDocument::_interpolate_track(const Vector<real_t> &p_times, const Vector<T
ERR_FAIL_V(p_values[0]);
}
-void GLTFDocument::_import_animation(Ref<GLTFState> state, AnimationPlayer *ap, const GLTFAnimationIndex index, const int bake_fps) {
- Ref<GLTFAnimation> anim = state->animations[index];
+void GLTFDocument::_import_animation(Ref<GLTFState> p_state, AnimationPlayer *p_animation_player, const GLTFAnimationIndex p_index, const float p_bake_fps, const bool p_trimming) {
+ Ref<GLTFAnimation> anim = p_state->animations[p_index];
String anim_name = anim->get_name();
if (anim_name.is_empty()) {
// No node represent these, and they are not in the hierarchy, so just make a unique name
- anim_name = _gen_unique_name(state, "Animation");
+ anim_name = _gen_unique_name(p_state, "Animation");
}
Ref<Animation> animation;
@@ -5836,7 +5875,8 @@ void GLTFDocument::_import_animation(Ref<GLTFState> state, AnimationPlayer *ap,
animation->set_loop_mode(Animation::LOOP_LINEAR);
}
- float length = 0.0;
+ double anim_start = p_trimming ? INFINITY : 0.0;
+ double anim_end = 0.0;
for (const KeyValue<int, GLTFAnimation::Track> &track_i : anim->get_tracks()) {
const GLTFAnimation::Track &track = track_i.value;
@@ -5847,38 +5887,59 @@ void GLTFDocument::_import_animation(Ref<GLTFState> state, AnimationPlayer *ap,
GLTFNodeIndex node_index = track_i.key;
- const Ref<GLTFNode> gltf_node = state->nodes[track_i.key];
+ const Ref<GLTFNode> gltf_node = p_state->nodes[track_i.key];
- Node *root = ap->get_parent();
+ Node *root = p_animation_player->get_parent();
ERR_FAIL_COND(root == nullptr);
- HashMap<GLTFNodeIndex, Node *>::Iterator node_element = state->scene_nodes.find(node_index);
+ HashMap<GLTFNodeIndex, Node *>::Iterator node_element = p_state->scene_nodes.find(node_index);
ERR_CONTINUE_MSG(!node_element, vformat("Unable to find node %d for animation", node_index));
node_path = root->get_path_to(node_element->value);
if (gltf_node->skeleton >= 0) {
- const Skeleton3D *sk = state->skeletons[gltf_node->skeleton]->godot_skeleton;
+ const Skeleton3D *sk = p_state->skeletons[gltf_node->skeleton]->godot_skeleton;
ERR_FAIL_COND(sk == nullptr);
- const String path = ap->get_parent()->get_path_to(sk);
+ const String path = p_animation_player->get_parent()->get_path_to(sk);
const String bone = gltf_node->get_name();
transform_node_path = path + ":" + bone;
} else {
transform_node_path = node_path;
}
- for (int i = 0; i < track.rotation_track.times.size(); i++) {
- length = MAX(length, track.rotation_track.times[i]);
- }
- for (int i = 0; i < track.position_track.times.size(); i++) {
- length = MAX(length, track.position_track.times[i]);
- }
- for (int i = 0; i < track.scale_track.times.size(); i++) {
- length = MAX(length, track.scale_track.times[i]);
- }
-
- for (int i = 0; i < track.weight_tracks.size(); i++) {
- for (int j = 0; j < track.weight_tracks[i].times.size(); j++) {
- length = MAX(length, track.weight_tracks[i].times[j]);
+ if (p_trimming) {
+ for (int i = 0; i < track.rotation_track.times.size(); i++) {
+ anim_start = MIN(anim_start, track.rotation_track.times[i]);
+ anim_end = MAX(anim_end, track.rotation_track.times[i]);
+ }
+ for (int i = 0; i < track.position_track.times.size(); i++) {
+ anim_start = MIN(anim_start, track.position_track.times[i]);
+ anim_end = MAX(anim_end, track.position_track.times[i]);
+ }
+ for (int i = 0; i < track.scale_track.times.size(); i++) {
+ anim_start = MIN(anim_start, track.scale_track.times[i]);
+ anim_end = MAX(anim_end, track.scale_track.times[i]);
+ }
+ for (int i = 0; i < track.weight_tracks.size(); i++) {
+ for (int j = 0; j < track.weight_tracks[i].times.size(); j++) {
+ anim_start = MIN(anim_start, track.weight_tracks[i].times[j]);
+ anim_end = MAX(anim_end, track.weight_tracks[i].times[j]);
+ }
+ }
+ } else {
+ // If you don't use trimming and the first key time is not at 0.0, fake keys will be inserted.
+ for (int i = 0; i < track.rotation_track.times.size(); i++) {
+ anim_end = MAX(anim_end, track.rotation_track.times[i]);
+ }
+ for (int i = 0; i < track.position_track.times.size(); i++) {
+ anim_end = MAX(anim_end, track.position_track.times[i]);
+ }
+ for (int i = 0; i < track.scale_track.times.size(); i++) {
+ anim_end = MAX(anim_end, track.scale_track.times[i]);
+ }
+ for (int i = 0; i < track.weight_tracks.size(); i++) {
+ for (int j = 0; j < track.weight_tracks[i].times.size(); j++) {
+ anim_end = MAX(anim_end, track.weight_tracks[i].times[j]);
+ }
}
}
@@ -5892,7 +5953,7 @@ void GLTFDocument::_import_animation(Ref<GLTFState> state, AnimationPlayer *ap,
int scale_idx = -1;
if (track.position_track.values.size()) {
- Vector3 base_pos = state->nodes[track_i.key]->position;
+ Vector3 base_pos = p_state->nodes[track_i.key]->position;
bool not_default = false; //discard the track if all it contains is default values
for (int i = 0; i < track.position_track.times.size(); i++) {
Vector3 value = track.position_track.values[track.position_track.interpolation == GLTFAnimation::INTERP_CUBIC_SPLINE ? (1 + i * 3) : i];
@@ -5911,7 +5972,7 @@ void GLTFDocument::_import_animation(Ref<GLTFState> state, AnimationPlayer *ap,
}
}
if (track.rotation_track.values.size()) {
- Quaternion base_rot = state->nodes[track_i.key]->rotation.normalized();
+ Quaternion base_rot = p_state->nodes[track_i.key]->rotation.normalized();
bool not_default = false; //discard the track if all it contains is default values
for (int i = 0; i < track.rotation_track.times.size(); i++) {
Quaternion value = track.rotation_track.values[track.rotation_track.interpolation == GLTFAnimation::INTERP_CUBIC_SPLINE ? (1 + i * 3) : i].normalized();
@@ -5929,7 +5990,7 @@ void GLTFDocument::_import_animation(Ref<GLTFState> state, AnimationPlayer *ap,
}
}
if (track.scale_track.values.size()) {
- Vector3 base_scale = state->nodes[track_i.key]->scale;
+ Vector3 base_scale = p_state->nodes[track_i.key]->scale;
bool not_default = false; //discard the track if all it contains is default values
for (int i = 0; i < track.scale_track.times.size(); i++) {
Vector3 value = track.scale_track.values[track.scale_track.interpolation == GLTFAnimation::INTERP_CUBIC_SPLINE ? (1 + i * 3) : i];
@@ -5947,25 +6008,23 @@ void GLTFDocument::_import_animation(Ref<GLTFState> state, AnimationPlayer *ap,
}
}
- //first determine animation length
-
- const double increment = 1.0 / bake_fps;
- double time = 0.0;
+ const double increment = 1.0 / p_bake_fps;
+ double time = anim_start;
Vector3 base_pos;
Quaternion base_rot;
Vector3 base_scale = Vector3(1, 1, 1);
if (rotation_idx == -1) {
- base_rot = state->nodes[track_i.key]->rotation.normalized();
+ base_rot = p_state->nodes[track_i.key]->rotation.normalized();
}
if (position_idx == -1) {
- base_pos = state->nodes[track_i.key]->position;
+ base_pos = p_state->nodes[track_i.key]->position;
}
if (scale_idx == -1) {
- base_scale = state->nodes[track_i.key]->scale;
+ base_scale = p_state->nodes[track_i.key]->scale;
}
bool last = false;
@@ -5976,33 +6035,33 @@ void GLTFDocument::_import_animation(Ref<GLTFState> state, AnimationPlayer *ap,
if (position_idx >= 0) {
pos = _interpolate_track<Vector3>(track.position_track.times, track.position_track.values, time, track.position_track.interpolation);
- animation->position_track_insert_key(position_idx, time, pos);
+ animation->position_track_insert_key(position_idx, time - anim_start, pos);
}
if (rotation_idx >= 0) {
rot = _interpolate_track<Quaternion>(track.rotation_track.times, track.rotation_track.values, time, track.rotation_track.interpolation);
- animation->rotation_track_insert_key(rotation_idx, time, rot);
+ animation->rotation_track_insert_key(rotation_idx, time - anim_start, rot);
}
if (scale_idx >= 0) {
scale = _interpolate_track<Vector3>(track.scale_track.times, track.scale_track.values, time, track.scale_track.interpolation);
- animation->scale_track_insert_key(scale_idx, time, scale);
+ animation->scale_track_insert_key(scale_idx, time - anim_start, scale);
}
if (last) {
break;
}
time += increment;
- if (time >= length) {
+ if (time >= anim_end) {
last = true;
- time = length;
+ time = anim_end;
}
}
}
for (int i = 0; i < track.weight_tracks.size(); i++) {
- ERR_CONTINUE(gltf_node->mesh < 0 || gltf_node->mesh >= state->meshes.size());
- Ref<GLTFMesh> mesh = state->meshes[gltf_node->mesh];
+ ERR_CONTINUE(gltf_node->mesh < 0 || gltf_node->mesh >= p_state->meshes.size());
+ Ref<GLTFMesh> mesh = p_state->meshes[gltf_node->mesh];
ERR_CONTINUE(mesh.is_null());
ERR_CONTINUE(mesh->get_mesh().is_null());
ERR_CONTINUE(mesh->get_mesh()->get_mesh().is_null());
@@ -6025,45 +6084,45 @@ void GLTFDocument::_import_animation(Ref<GLTFState> state, AnimationPlayer *ap,
}
} else {
// CATMULLROMSPLINE or CUBIC_SPLINE have to be baked, apologies.
- const double increment = 1.0 / bake_fps;
+ const double increment = 1.0 / p_bake_fps;
double time = 0.0;
bool last = false;
while (true) {
real_t blend = _interpolate_track<real_t>(track.weight_tracks[i].times, track.weight_tracks[i].values, time, gltf_interp);
- animation->blend_shape_track_insert_key(track_idx, time, blend);
+ animation->blend_shape_track_insert_key(track_idx, time - anim_start, blend);
if (last) {
break;
}
time += increment;
- if (time >= length) {
+ if (time >= anim_end) {
last = true;
- time = length;
+ time = anim_end;
}
}
}
}
}
- animation->set_length(length);
+ animation->set_length(anim_end - anim_start);
Ref<AnimationLibrary> library;
- if (!ap->has_animation_library("")) {
+ if (!p_animation_player->has_animation_library("")) {
library.instantiate();
- ap->add_animation_library("", library);
+ p_animation_player->add_animation_library("", library);
} else {
- library = ap->get_animation_library("");
+ library = p_animation_player->get_animation_library("");
}
library->add_animation(anim_name, animation);
}
-void GLTFDocument::_convert_mesh_instances(Ref<GLTFState> state) {
- for (GLTFNodeIndex mi_node_i = 0; mi_node_i < state->nodes.size(); ++mi_node_i) {
- Ref<GLTFNode> node = state->nodes[mi_node_i];
+void GLTFDocument::_convert_mesh_instances(Ref<GLTFState> p_state) {
+ for (GLTFNodeIndex mi_node_i = 0; mi_node_i < p_state->nodes.size(); ++mi_node_i) {
+ Ref<GLTFNode> node = p_state->nodes[mi_node_i];
if (node->mesh < 0) {
continue;
}
- HashMap<GLTFNodeIndex, Node *>::Iterator mi_element = state->scene_nodes.find(mi_node_i);
+ HashMap<GLTFNodeIndex, Node *>::Iterator mi_element = p_state->scene_nodes.find(mi_node_i);
if (!mi_element) {
continue;
}
@@ -6094,10 +6153,10 @@ void GLTFDocument::_convert_mesh_instances(Ref<GLTFState> state) {
if (skel_node != nullptr) {
godot_skeleton = cast_to<Skeleton3D>(skel_node);
}
- if (godot_skeleton != nullptr && state->skeleton3d_to_gltf_skeleton.has(godot_skeleton->get_instance_id())) {
+ if (godot_skeleton != nullptr && p_state->skeleton3d_to_gltf_skeleton.has(godot_skeleton->get_instance_id())) {
// This is a skinned mesh. If the mesh has no ARRAY_WEIGHTS or ARRAY_BONES, it will be invisible.
- const GLTFSkeletonIndex skeleton_gltf_i = state->skeleton3d_to_gltf_skeleton[godot_skeleton->get_instance_id()];
- Ref<GLTFSkeleton> gltf_skeleton = state->skeletons[skeleton_gltf_i];
+ const GLTFSkeletonIndex skeleton_gltf_i = p_state->skeleton3d_to_gltf_skeleton[godot_skeleton->get_instance_id()];
+ Ref<GLTFSkeleton> gltf_skeleton = p_state->skeletons[skeleton_gltf_i];
int bone_cnt = skeleton->get_bone_count();
ERR_FAIL_COND(bone_cnt != gltf_skeleton->joints.size());
@@ -6111,8 +6170,8 @@ void GLTFDocument::_convert_mesh_instances(Ref<GLTFState> state) {
if (!gltf_skeleton->roots.is_empty()) {
root_gltf_i = gltf_skeleton->roots[0];
}
- if (state->skin_and_skeleton3d_to_gltf_skin.has(gltf_skin_key) && state->skin_and_skeleton3d_to_gltf_skin[gltf_skin_key].has(gltf_skel_key)) {
- skin_gltf_i = state->skin_and_skeleton3d_to_gltf_skin[gltf_skin_key][gltf_skel_key];
+ if (p_state->skin_and_skeleton3d_to_gltf_skin.has(gltf_skin_key) && p_state->skin_and_skeleton3d_to_gltf_skin[gltf_skin_key].has(gltf_skel_key)) {
+ skin_gltf_i = p_state->skin_and_skeleton3d_to_gltf_skin[gltf_skin_key][gltf_skel_key];
} else {
if (skin.is_null()) {
// Note that gltf_skin_key should remain null, so these can share a reference.
@@ -6149,9 +6208,9 @@ void GLTFDocument::_convert_mesh_instances(Ref<GLTFState> state) {
gltf_skin->joint_i_to_bone_i[bind_i] = bone_i;
gltf_skin->joint_i_to_name[bind_i] = bind_name;
}
- skin_gltf_i = state->skins.size();
- state->skins.push_back(gltf_skin);
- state->skin_and_skeleton3d_to_gltf_skin[gltf_skin_key][gltf_skel_key] = skin_gltf_i;
+ skin_gltf_i = p_state->skins.size();
+ p_state->skins.push_back(gltf_skin);
+ p_state->skin_and_skeleton3d_to_gltf_skin[gltf_skin_key][gltf_skel_key] = skin_gltf_i;
}
node->skin = skin_gltf_i;
node->skeleton = skeleton_gltf_i;
@@ -6159,14 +6218,14 @@ void GLTFDocument::_convert_mesh_instances(Ref<GLTFState> state) {
}
}
-float GLTFDocument::solve_metallic(float p_dielectric_specular, float diffuse, float specular, float p_one_minus_specular_strength) {
- if (specular <= p_dielectric_specular) {
+float GLTFDocument::solve_metallic(float p_dielectric_specular, float p_diffuse, float p_specular, float p_one_minus_specular_strength) {
+ if (p_specular <= p_dielectric_specular) {
return 0.0f;
}
const float a = p_dielectric_specular;
- const float b = diffuse * p_one_minus_specular_strength / (1.0f - p_dielectric_specular) + specular - 2.0f * p_dielectric_specular;
- const float c = p_dielectric_specular - specular;
+ const float b = p_diffuse * p_one_minus_specular_strength / (1.0f - p_dielectric_specular) + p_specular - 2.0f * p_dielectric_specular;
+ const float c = p_dielectric_specular - p_specular;
const float D = b * b - 4.0f * a * c;
return CLAMP((-b + Math::sqrt(D)) / (2.0f * a), 0.0f, 1.0f);
}
@@ -6190,21 +6249,21 @@ float GLTFDocument::get_max_component(const Color &p_color) {
return MAX(MAX(r, g), b);
}
-void GLTFDocument::_process_mesh_instances(Ref<GLTFState> state, Node *scene_root) {
- for (GLTFNodeIndex node_i = 0; node_i < state->nodes.size(); ++node_i) {
- Ref<GLTFNode> node = state->nodes[node_i];
+void GLTFDocument::_process_mesh_instances(Ref<GLTFState> p_state, Node *p_scene_root) {
+ for (GLTFNodeIndex node_i = 0; node_i < p_state->nodes.size(); ++node_i) {
+ Ref<GLTFNode> node = p_state->nodes[node_i];
if (node->skin >= 0 && node->mesh >= 0) {
const GLTFSkinIndex skin_i = node->skin;
- HashMap<GLTFNodeIndex, Node *>::Iterator mi_element = state->scene_nodes.find(node_i);
+ HashMap<GLTFNodeIndex, Node *>::Iterator mi_element = p_state->scene_nodes.find(node_i);
ERR_CONTINUE_MSG(!mi_element, vformat("Unable to find node %d", node_i));
ImporterMeshInstance3D *mi = Object::cast_to<ImporterMeshInstance3D>(mi_element->value);
ERR_CONTINUE_MSG(mi == nullptr, vformat("Unable to cast node %d of type %s to ImporterMeshInstance3D", node_i, mi_element->value->get_class_name()));
- const GLTFSkeletonIndex skel_i = state->skins.write[node->skin]->skeleton;
- Ref<GLTFSkeleton> gltf_skeleton = state->skeletons.write[skel_i];
+ const GLTFSkeletonIndex skel_i = p_state->skins.write[node->skin]->skeleton;
+ Ref<GLTFSkeleton> gltf_skeleton = p_state->skeletons.write[skel_i];
Skeleton3D *skeleton = gltf_skeleton->godot_skeleton;
ERR_CONTINUE_MSG(skeleton == nullptr, vformat("Unable to find Skeleton for node %d skin %d", node_i, skin_i));
@@ -6212,14 +6271,14 @@ void GLTFDocument::_process_mesh_instances(Ref<GLTFState> state, Node *scene_roo
skeleton->add_child(mi, true);
mi->set_owner(skeleton->get_owner());
- mi->set_skin(state->skins.write[skin_i]->godot_skin);
+ mi->set_skin(p_state->skins.write[skin_i]->godot_skin);
mi->set_skeleton_path(mi->get_path_to(skeleton));
mi->set_transform(Transform3D());
}
}
}
-GLTFAnimation::Track GLTFDocument::_convert_animation_track(Ref<GLTFState> state, GLTFAnimation::Track p_track, Ref<Animation> p_animation, int32_t p_track_i, GLTFNodeIndex p_node_i) {
+GLTFAnimation::Track GLTFDocument::_convert_animation_track(Ref<GLTFState> p_state, GLTFAnimation::Track p_track, Ref<Animation> p_animation, int32_t p_track_i, GLTFNodeIndex p_node_i) {
Animation::InterpolationType interpolation = p_animation->track_get_interpolation_type(p_track_i);
GLTFAnimation::Interpolation gltf_interpolation = GLTFAnimation::INTERP_LINEAR;
@@ -6365,11 +6424,11 @@ GLTFAnimation::Track GLTFDocument::_convert_animation_track(Ref<GLTFState> state
return p_track;
}
-void GLTFDocument::_convert_animation(Ref<GLTFState> state, AnimationPlayer *ap, String p_animation_track_name) {
- Ref<Animation> animation = ap->get_animation(p_animation_track_name);
+void GLTFDocument::_convert_animation(Ref<GLTFState> p_state, AnimationPlayer *p_animation_player, String p_animation_track_name) {
+ Ref<Animation> animation = p_animation_player->get_animation(p_animation_track_name);
Ref<GLTFAnimation> gltf_animation;
gltf_animation.instantiate();
- gltf_animation->set_name(_gen_unique_name(state, p_animation_track_name));
+ gltf_animation->set_name(_gen_unique_name(p_state, p_animation_track_name));
for (int32_t track_i = 0; track_i < animation->get_track_count(); track_i++) {
if (!animation->track_is_enabled(track_i)) {
@@ -6379,8 +6438,8 @@ void GLTFDocument::_convert_animation(Ref<GLTFState> state, AnimationPlayer *ap,
if (String(orig_track_path).contains(":position")) {
const Vector<String> node_suffix = String(orig_track_path).split(":position");
const NodePath path = node_suffix[0];
- const Node *node = ap->get_parent()->get_node_or_null(path);
- for (const KeyValue<GLTFNodeIndex, Node *> &position_scene_node_i : state->scene_nodes) {
+ const Node *node = p_animation_player->get_parent()->get_node_or_null(path);
+ for (const KeyValue<GLTFNodeIndex, Node *> &position_scene_node_i : p_state->scene_nodes) {
if (position_scene_node_i.value == node) {
GLTFNodeIndex node_index = position_scene_node_i.key;
HashMap<int, GLTFAnimation::Track>::Iterator position_track_i = gltf_animation->get_tracks().find(node_index);
@@ -6388,15 +6447,15 @@ void GLTFDocument::_convert_animation(Ref<GLTFState> state, AnimationPlayer *ap,
if (position_track_i) {
track = position_track_i->value;
}
- track = _convert_animation_track(state, track, animation, track_i, node_index);
+ track = _convert_animation_track(p_state, track, animation, track_i, node_index);
gltf_animation->get_tracks().insert(node_index, track);
}
}
} else if (String(orig_track_path).contains(":rotation_degrees")) {
const Vector<String> node_suffix = String(orig_track_path).split(":rotation_degrees");
const NodePath path = node_suffix[0];
- const Node *node = ap->get_parent()->get_node_or_null(path);
- for (const KeyValue<GLTFNodeIndex, Node *> &rotation_degree_scene_node_i : state->scene_nodes) {
+ const Node *node = p_animation_player->get_parent()->get_node_or_null(path);
+ for (const KeyValue<GLTFNodeIndex, Node *> &rotation_degree_scene_node_i : p_state->scene_nodes) {
if (rotation_degree_scene_node_i.value == node) {
GLTFNodeIndex node_index = rotation_degree_scene_node_i.key;
HashMap<int, GLTFAnimation::Track>::Iterator rotation_degree_track_i = gltf_animation->get_tracks().find(node_index);
@@ -6404,15 +6463,15 @@ void GLTFDocument::_convert_animation(Ref<GLTFState> state, AnimationPlayer *ap,
if (rotation_degree_track_i) {
track = rotation_degree_track_i->value;
}
- track = _convert_animation_track(state, track, animation, track_i, node_index);
+ track = _convert_animation_track(p_state, track, animation, track_i, node_index);
gltf_animation->get_tracks().insert(node_index, track);
}
}
} else if (String(orig_track_path).contains(":scale")) {
const Vector<String> node_suffix = String(orig_track_path).split(":scale");
const NodePath path = node_suffix[0];
- const Node *node = ap->get_parent()->get_node_or_null(path);
- for (const KeyValue<GLTFNodeIndex, Node *> &scale_scene_node_i : state->scene_nodes) {
+ const Node *node = p_animation_player->get_parent()->get_node_or_null(path);
+ for (const KeyValue<GLTFNodeIndex, Node *> &scale_scene_node_i : p_state->scene_nodes) {
if (scale_scene_node_i.value == node) {
GLTFNodeIndex node_index = scale_scene_node_i.key;
HashMap<int, GLTFAnimation::Track>::Iterator scale_track_i = gltf_animation->get_tracks().find(node_index);
@@ -6420,18 +6479,18 @@ void GLTFDocument::_convert_animation(Ref<GLTFState> state, AnimationPlayer *ap,
if (scale_track_i) {
track = scale_track_i->value;
}
- track = _convert_animation_track(state, track, animation, track_i, node_index);
+ track = _convert_animation_track(p_state, track, animation, track_i, node_index);
gltf_animation->get_tracks().insert(node_index, track);
}
}
} else if (String(orig_track_path).contains(":transform")) {
const Vector<String> node_suffix = String(orig_track_path).split(":transform");
const NodePath path = node_suffix[0];
- const Node *node = ap->get_parent()->get_node_or_null(path);
- for (const KeyValue<GLTFNodeIndex, Node *> &transform_track_i : state->scene_nodes) {
+ const Node *node = p_animation_player->get_parent()->get_node_or_null(path);
+ for (const KeyValue<GLTFNodeIndex, Node *> &transform_track_i : p_state->scene_nodes) {
if (transform_track_i.value == node) {
GLTFAnimation::Track track;
- track = _convert_animation_track(state, track, animation, track_i, transform_track_i.key);
+ track = _convert_animation_track(p_state, track, animation, track_i, transform_track_i.key);
gltf_animation->get_tracks().insert(transform_track_i.key, track);
}
}
@@ -6439,12 +6498,12 @@ void GLTFDocument::_convert_animation(Ref<GLTFState> state, AnimationPlayer *ap,
const Vector<String> node_suffix = String(orig_track_path).split(":");
const NodePath path = node_suffix[0];
const String suffix = node_suffix[1];
- Node *node = ap->get_parent()->get_node_or_null(path);
+ Node *node = p_animation_player->get_parent()->get_node_or_null(path);
MeshInstance3D *mi = cast_to<MeshInstance3D>(node);
Ref<Mesh> mesh = mi->get_mesh();
ERR_CONTINUE(mesh.is_null());
int32_t mesh_index = -1;
- for (const KeyValue<GLTFNodeIndex, Node *> &mesh_track_i : state->scene_nodes) {
+ for (const KeyValue<GLTFNodeIndex, Node *> &mesh_track_i : p_state->scene_nodes) {
if (mesh_track_i.value == node) {
mesh_index = mesh_track_i.key;
}
@@ -6497,15 +6556,15 @@ void GLTFDocument::_convert_animation(Ref<GLTFState> state, AnimationPlayer *ap,
const String node = node_suffix[0];
const NodePath node_path = node;
const String suffix = node_suffix[1];
- Node *godot_node = ap->get_parent()->get_node_or_null(node_path);
+ Node *godot_node = p_animation_player->get_parent()->get_node_or_null(node_path);
Skeleton3D *skeleton = nullptr;
GLTFSkeletonIndex skeleton_gltf_i = -1;
- for (GLTFSkeletonIndex skeleton_i = 0; skeleton_i < state->skeletons.size(); skeleton_i++) {
- if (state->skeletons[skeleton_i]->godot_skeleton == cast_to<Skeleton3D>(godot_node)) {
- skeleton = state->skeletons[skeleton_i]->godot_skeleton;
+ for (GLTFSkeletonIndex skeleton_i = 0; skeleton_i < p_state->skeletons.size(); skeleton_i++) {
+ if (p_state->skeletons[skeleton_i]->godot_skeleton == cast_to<Skeleton3D>(godot_node)) {
+ skeleton = p_state->skeletons[skeleton_i]->godot_skeleton;
skeleton_gltf_i = skeleton_i;
ERR_CONTINUE(!skeleton);
- Ref<GLTFSkeleton> skeleton_gltf = state->skeletons[skeleton_gltf_i];
+ Ref<GLTFSkeleton> skeleton_gltf = p_state->skeletons[skeleton_gltf_i];
int32_t bone = skeleton->find_bone(suffix);
ERR_CONTINUE(bone == -1);
if (!skeleton_gltf->godot_bone_node.has(bone)) {
@@ -6517,14 +6576,14 @@ void GLTFDocument::_convert_animation(Ref<GLTFState> state, AnimationPlayer *ap,
if (property_track_i) {
track = property_track_i->value;
}
- track = _convert_animation_track(state, track, animation, track_i, node_i);
+ track = _convert_animation_track(p_state, track, animation, track_i, node_i);
gltf_animation->get_tracks()[node_i] = track;
}
}
} else if (!String(orig_track_path).contains(":")) {
- ERR_CONTINUE(!ap->get_parent());
- Node *godot_node = ap->get_parent()->get_node_or_null(orig_track_path);
- for (const KeyValue<GLTFNodeIndex, Node *> &scene_node_i : state->scene_nodes) {
+ ERR_CONTINUE(!p_animation_player->get_parent());
+ Node *godot_node = p_animation_player->get_parent()->get_node_or_null(orig_track_path);
+ for (const KeyValue<GLTFNodeIndex, Node *> &scene_node_i : p_state->scene_nodes) {
if (scene_node_i.value == godot_node) {
GLTFNodeIndex node_i = scene_node_i.key;
HashMap<int, GLTFAnimation::Track>::Iterator node_track_i = gltf_animation->get_tracks().find(node_i);
@@ -6532,7 +6591,7 @@ void GLTFDocument::_convert_animation(Ref<GLTFState> state, AnimationPlayer *ap,
if (node_track_i) {
track = node_track_i->value;
}
- track = _convert_animation_track(state, track, animation, track_i, node_i);
+ track = _convert_animation_track(p_state, track, animation, track_i, node_i);
gltf_animation->get_tracks()[node_i] = track;
break;
}
@@ -6540,42 +6599,42 @@ void GLTFDocument::_convert_animation(Ref<GLTFState> state, AnimationPlayer *ap,
}
}
if (gltf_animation->get_tracks().size()) {
- state->animations.push_back(gltf_animation);
+ p_state->animations.push_back(gltf_animation);
}
}
-Error GLTFDocument::_parse(Ref<GLTFState> state, String p_path, Ref<FileAccess> f, int p_bake_fps) {
+Error GLTFDocument::_parse(Ref<GLTFState> p_state, String p_path, Ref<FileAccess> p_file) {
Error err;
- if (f.is_null()) {
+ if (p_file.is_null()) {
return FAILED;
}
- f->seek(0);
- uint32_t magic = f->get_32();
+ p_file->seek(0);
+ uint32_t magic = p_file->get_32();
if (magic == 0x46546C67) {
//binary file
//text file
- f->seek(0);
- err = _parse_glb(f, state);
+ p_file->seek(0);
+ err = _parse_glb(p_file, p_state);
if (err != OK) {
return err;
}
} else {
- f->seek(0);
- String text = f->get_as_utf8_string();
+ p_file->seek(0);
+ String text = p_file->get_as_utf8_string();
JSON json;
err = json.parse(text);
if (err != OK) {
_err_print_error("", "", json.get_error_line(), json.get_error_message().utf8().get_data(), false, ERR_HANDLER_SCRIPT);
}
ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR);
- state->json = json.get_data();
+ p_state->json = json.get_data();
}
- if (!state->json.has("asset")) {
+ if (!p_state->json.has("asset")) {
return ERR_PARSE_ERROR;
}
- Dictionary asset = state->json["asset"];
+ Dictionary asset = p_state->json["asset"];
if (!asset.has("version")) {
return ERR_PARSE_ERROR;
@@ -6583,17 +6642,19 @@ Error GLTFDocument::_parse(Ref<GLTFState> state, String p_path, Ref<FileAccess>
String version = asset["version"];
- state->major_version = version.get_slice(".", 0).to_int();
- state->minor_version = version.get_slice(".", 1).to_int();
+ p_state->major_version = version.get_slice(".", 0).to_int();
+ p_state->minor_version = version.get_slice(".", 1).to_int();
- for (int32_t ext_i = 0; ext_i < document_extensions.size(); ext_i++) {
- Ref<GLTFDocumentExtension> ext = document_extensions[ext_i];
+ document_extensions.clear();
+ for (Ref<GLTFDocumentExtension> ext : all_document_extensions) {
ERR_CONTINUE(ext.is_null());
- err = ext->import_preflight(state);
- ERR_FAIL_COND_V(err != OK, err);
+ err = ext->import_preflight(p_state, p_state->json["extensionsUsed"]);
+ if (err == OK) {
+ document_extensions.push_back(ext);
+ }
}
- err = _parse_gltf_state(state, p_path, p_bake_fps);
+ err = _parse_gltf_state(p_state, p_path);
ERR_FAIL_COND_V(err != OK, err);
return OK;
@@ -6626,47 +6687,43 @@ Dictionary _serialize_texture_transform_uv(Vector2 p_offset, Vector2 p_scale) {
}
Dictionary GLTFDocument::_serialize_texture_transform_uv1(Ref<BaseMaterial3D> p_material) {
- if (p_material.is_valid()) {
- 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 Dictionary();
+ ERR_FAIL_NULL_V(p_material, Dictionary());
+ 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));
}
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();
+ ERR_FAIL_NULL_V(p_material, Dictionary());
+ 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));
}
-Error GLTFDocument::_serialize_version(Ref<GLTFState> state) {
+Error GLTFDocument::_serialize_version(Ref<GLTFState> p_state) {
const String version = "2.0";
- state->major_version = version.get_slice(".", 0).to_int();
- state->minor_version = version.get_slice(".", 1).to_int();
+ p_state->major_version = version.get_slice(".", 0).to_int();
+ p_state->minor_version = version.get_slice(".", 1).to_int();
Dictionary asset;
asset["version"] = version;
String hash = String(VERSION_HASH);
asset["generator"] = String(VERSION_FULL_NAME) + String("@") + (hash.is_empty() ? String("unknown") : hash);
- state->json["asset"] = asset;
+ p_state->json["asset"] = asset;
ERR_FAIL_COND_V(!asset.has("version"), Error::FAILED);
- ERR_FAIL_COND_V(!state->json.has("asset"), Error::FAILED);
+ ERR_FAIL_COND_V(!p_state->json.has("asset"), Error::FAILED);
return OK;
}
-Error GLTFDocument::_serialize_file(Ref<GLTFState> state, const String p_path) {
+Error GLTFDocument::_serialize_file(Ref<GLTFState> p_state, const String p_path) {
Error err = FAILED;
if (p_path.to_lower().ends_with("glb")) {
- err = _encode_buffer_glb(state, p_path);
+ err = _encode_buffer_glb(p_state, p_path);
ERR_FAIL_COND_V(err != OK, err);
- Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::WRITE, &err);
- ERR_FAIL_COND_V(f.is_null(), FAILED);
+ Ref<FileAccess> file = FileAccess::open(p_path, FileAccess::WRITE, &err);
+ ERR_FAIL_COND_V(file.is_null(), FAILED);
- String json = Variant(state->json).to_json_string();
+ String json = Variant(p_state->json).to_json_string();
const uint32_t magic = 0x46546C67; // GLTF
const int32_t header_size = 12;
@@ -6677,106 +6734,104 @@ Error GLTFDocument::_serialize_file(Ref<GLTFState> state, const String p_path) {
const uint32_t text_chunk_type = 0x4E4F534A; //JSON
uint32_t binary_data_length = 0;
- if (state->buffers.size()) {
- binary_data_length = state->buffers[0].size();
+ if (p_state->buffers.size()) {
+ binary_data_length = p_state->buffers[0].size();
}
const uint32_t binary_chunk_length = ((binary_data_length + 3) & (~3));
const uint32_t binary_chunk_type = 0x004E4942; //BIN
- f->create(FileAccess::ACCESS_RESOURCES);
- f->store_32(magic);
- f->store_32(state->major_version); // version
- f->store_32(header_size + chunk_header_size + text_chunk_length + chunk_header_size + binary_chunk_length); // length
- f->store_32(text_chunk_length);
- f->store_32(text_chunk_type);
- f->store_buffer((uint8_t *)&cs[0], cs.length());
+ file->create(FileAccess::ACCESS_RESOURCES);
+ file->store_32(magic);
+ file->store_32(p_state->major_version); // version
+ file->store_32(header_size + chunk_header_size + text_chunk_length + chunk_header_size + binary_chunk_length); // length
+ file->store_32(text_chunk_length);
+ file->store_32(text_chunk_type);
+ file->store_buffer((uint8_t *)&cs[0], cs.length());
for (uint32_t pad_i = text_data_length; pad_i < text_chunk_length; pad_i++) {
- f->store_8(' ');
+ file->store_8(' ');
}
if (binary_chunk_length) {
- f->store_32(binary_chunk_length);
- f->store_32(binary_chunk_type);
- f->store_buffer(state->buffers[0].ptr(), binary_data_length);
+ file->store_32(binary_chunk_length);
+ file->store_32(binary_chunk_type);
+ file->store_buffer(p_state->buffers[0].ptr(), binary_data_length);
}
for (uint32_t pad_i = binary_data_length; pad_i < binary_chunk_length; pad_i++) {
- f->store_8(0);
+ file->store_8(0);
}
} else {
- err = _encode_buffer_bins(state, p_path);
+ err = _encode_buffer_bins(p_state, p_path);
ERR_FAIL_COND_V(err != OK, err);
- Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::WRITE, &err);
- ERR_FAIL_COND_V(f.is_null(), FAILED);
+ Ref<FileAccess> file = FileAccess::open(p_path, FileAccess::WRITE, &err);
+ ERR_FAIL_COND_V(file.is_null(), FAILED);
- f->create(FileAccess::ACCESS_RESOURCES);
- String json = Variant(state->json).to_json_string();
- f->store_string(json);
+ file->create(FileAccess::ACCESS_RESOURCES);
+ String json = Variant(p_state->json).to_json_string();
+ file->store_string(json);
}
return err;
}
void GLTFDocument::_bind_methods() {
- ClassDB::bind_method(D_METHOD("append_from_file", "path", "state", "flags", "bake_fps", "base_path"),
- &GLTFDocument::append_from_file, DEFVAL(0), DEFVAL(30), DEFVAL(String()));
- ClassDB::bind_method(D_METHOD("append_from_buffer", "bytes", "base_path", "state", "flags", "bake_fps"),
- &GLTFDocument::append_from_buffer, DEFVAL(0), DEFVAL(30));
- ClassDB::bind_method(D_METHOD("append_from_scene", "node", "state", "flags", "bake_fps"),
- &GLTFDocument::append_from_scene, DEFVAL(0), DEFVAL(30));
- ClassDB::bind_method(D_METHOD("generate_scene", "state", "bake_fps"),
- &GLTFDocument::generate_scene, DEFVAL(30));
+ ClassDB::bind_method(D_METHOD("append_from_file", "path", "state", "flags", "base_path"),
+ &GLTFDocument::append_from_file, DEFVAL(0), DEFVAL(String()));
+ ClassDB::bind_method(D_METHOD("append_from_buffer", "bytes", "base_path", "state", "flags"),
+ &GLTFDocument::append_from_buffer, DEFVAL(0));
+ ClassDB::bind_method(D_METHOD("append_from_scene", "node", "state", "flags"),
+ &GLTFDocument::append_from_scene, DEFVAL(0));
+ ClassDB::bind_method(D_METHOD("generate_scene", "state", "bake_fps", "trimming"),
+ &GLTFDocument::generate_scene, DEFVAL(30), DEFVAL(false));
ClassDB::bind_method(D_METHOD("generate_buffer", "state"),
&GLTFDocument::generate_buffer);
ClassDB::bind_method(D_METHOD("write_to_filesystem", "state", "path"),
&GLTFDocument::write_to_filesystem);
- ClassDB::bind_method(D_METHOD("set_extensions", "extensions"),
- &GLTFDocument::set_extensions);
- ClassDB::bind_method(D_METHOD("get_extensions"),
- &GLTFDocument::get_extensions);
- ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "extensions", PROPERTY_HINT_ARRAY_TYPE,
- vformat("%s/%s:%s", Variant::OBJECT, PROPERTY_HINT_RESOURCE_TYPE, "GLTFDocumentExtension"),
- PROPERTY_USAGE_DEFAULT),
- "set_extensions", "get_extensions");
+ ClassDB::bind_static_method("GLTFDocument", D_METHOD("register_gltf_document_extension", "extension", "first_priority"),
+ &GLTFDocument::register_gltf_document_extension, DEFVAL(false));
+ ClassDB::bind_static_method("GLTFDocument", D_METHOD("unregister_gltf_document_extension", "extension"),
+ &GLTFDocument::unregister_gltf_document_extension);
}
-void GLTFDocument::_build_parent_hierachy(Ref<GLTFState> state) {
+void GLTFDocument::_build_parent_hierachy(Ref<GLTFState> p_state) {
// build the hierarchy
- for (GLTFNodeIndex node_i = 0; node_i < state->nodes.size(); node_i++) {
- for (int j = 0; j < state->nodes[node_i]->children.size(); j++) {
- GLTFNodeIndex child_i = state->nodes[node_i]->children[j];
- ERR_FAIL_INDEX(child_i, state->nodes.size());
- if (state->nodes.write[child_i]->parent != -1) {
+ for (GLTFNodeIndex node_i = 0; node_i < p_state->nodes.size(); node_i++) {
+ for (int j = 0; j < p_state->nodes[node_i]->children.size(); j++) {
+ GLTFNodeIndex child_i = p_state->nodes[node_i]->children[j];
+ ERR_FAIL_INDEX(child_i, p_state->nodes.size());
+ if (p_state->nodes.write[child_i]->parent != -1) {
continue;
}
- state->nodes.write[child_i]->parent = node_i;
+ p_state->nodes.write[child_i]->parent = node_i;
}
}
}
-void GLTFDocument::set_extensions(TypedArray<GLTFDocumentExtension> p_extensions) {
- document_extensions = p_extensions;
+Vector<Ref<GLTFDocumentExtension>> GLTFDocument::all_document_extensions;
+
+void GLTFDocument::register_gltf_document_extension(Ref<GLTFDocumentExtension> p_extension, bool p_first_priority) {
+ if (all_document_extensions.find(p_extension) == -1) {
+ if (p_first_priority) {
+ all_document_extensions.insert(0, p_extension);
+ } else {
+ all_document_extensions.push_back(p_extension);
+ }
+ }
}
-TypedArray<GLTFDocumentExtension> GLTFDocument::get_extensions() const {
- return document_extensions;
+void GLTFDocument::unregister_gltf_document_extension(Ref<GLTFDocumentExtension> p_extension) {
+ all_document_extensions.erase(p_extension);
}
-GLTFDocument::GLTFDocument() {
- bool is_editor = ::Engine::get_singleton()->is_editor_hint();
- if (is_editor) {
- return;
- }
- Ref<GLTFDocumentExtensionConvertImporterMesh> extension_editor;
- extension_editor.instantiate();
- document_extensions.push_back(extension_editor);
+void GLTFDocument::unregister_all_gltf_document_extensions() {
+ all_document_extensions.clear();
}
-PackedByteArray GLTFDocument::_serialize_glb_buffer(Ref<GLTFState> state, Error *r_err) {
- Error err = _encode_buffer_glb(state, "");
+PackedByteArray GLTFDocument::_serialize_glb_buffer(Ref<GLTFState> p_state, Error *r_err) {
+ Error err = _encode_buffer_glb(p_state, "");
if (r_err) {
*r_err = err;
}
ERR_FAIL_COND_V(err != OK, PackedByteArray());
- String json = Variant(state->json).to_json_string();
+ String json = Variant(p_state->json).to_json_string();
const uint32_t magic = 0x46546C67; // GLTF
const int32_t header_size = 12;
@@ -6790,8 +6845,8 @@ PackedByteArray GLTFDocument::_serialize_glb_buffer(Ref<GLTFState> state, Error
const uint32_t text_chunk_type = 0x4E4F534A; //JSON
int32_t binary_data_length = 0;
- if (state->buffers.size()) {
- binary_data_length = state->buffers[0].size();
+ if (p_state->buffers.size()) {
+ binary_data_length = p_state->buffers[0].size();
}
const int32_t binary_chunk_length = binary_data_length;
const int32_t binary_chunk_type = 0x004E4942; //BIN
@@ -6799,7 +6854,7 @@ PackedByteArray GLTFDocument::_serialize_glb_buffer(Ref<GLTFState> state, Error
Ref<StreamPeerBuffer> buffer;
buffer.instantiate();
buffer->put_32(magic);
- buffer->put_32(state->major_version); // version
+ buffer->put_32(p_state->major_version); // version
buffer->put_32(header_size + chunk_header_size + text_chunk_length + chunk_header_size + binary_data_length); // length
buffer->put_32(text_chunk_length);
buffer->put_32(text_chunk_type);
@@ -6807,211 +6862,210 @@ PackedByteArray GLTFDocument::_serialize_glb_buffer(Ref<GLTFState> state, Error
if (binary_chunk_length) {
buffer->put_32(binary_chunk_length);
buffer->put_32(binary_chunk_type);
- buffer->put_data(state->buffers[0].ptr(), binary_data_length);
+ buffer->put_data(p_state->buffers[0].ptr(), binary_data_length);
}
return buffer->get_data_array();
}
-PackedByteArray GLTFDocument::generate_buffer(Ref<GLTFState> state) {
- ERR_FAIL_NULL_V(state, PackedByteArray());
- Error err = _serialize(state, "");
+PackedByteArray GLTFDocument::generate_buffer(Ref<GLTFState> p_state) {
+ ERR_FAIL_NULL_V(p_state, PackedByteArray());
+ Error err = _serialize(p_state, "");
ERR_FAIL_COND_V(err != OK, PackedByteArray());
- PackedByteArray bytes = _serialize_glb_buffer(state, &err);
+ PackedByteArray bytes = _serialize_glb_buffer(p_state, &err);
return bytes;
}
-Error GLTFDocument::write_to_filesystem(Ref<GLTFState> state, const String &p_path) {
- ERR_FAIL_NULL_V(state, ERR_INVALID_PARAMETER);
- Error err = _serialize(state, p_path);
+Error GLTFDocument::write_to_filesystem(Ref<GLTFState> p_state, const String &p_path) {
+ ERR_FAIL_NULL_V(p_state, ERR_INVALID_PARAMETER);
+ Error err = _serialize(p_state, p_path);
if (err != OK) {
return err;
}
- err = _serialize_file(state, p_path);
+ err = _serialize_file(p_state, p_path);
if (err != OK) {
return Error::FAILED;
}
return OK;
}
-Node *GLTFDocument::generate_scene(Ref<GLTFState> state, int32_t p_bake_fps) {
- ERR_FAIL_NULL_V(state, nullptr);
- ERR_FAIL_INDEX_V(0, state->root_nodes.size(), nullptr);
+Node *GLTFDocument::generate_scene(Ref<GLTFState> p_state, float p_bake_fps, bool p_trimming) {
+ ERR_FAIL_NULL_V(p_state, nullptr);
+ ERR_FAIL_INDEX_V(0, p_state->root_nodes.size(), nullptr);
Error err = OK;
- GLTFNodeIndex gltf_root = state->root_nodes.write[0];
- Node *gltf_root_node = state->get_scene_node(gltf_root);
+ GLTFNodeIndex gltf_root = p_state->root_nodes.write[0];
+ Node *gltf_root_node = p_state->get_scene_node(gltf_root);
Node *root = gltf_root_node->get_parent();
ERR_FAIL_NULL_V(root, nullptr);
- _process_mesh_instances(state, root);
- if (state->get_create_animations() && state->animations.size()) {
+ _process_mesh_instances(p_state, root);
+ if (p_state->get_create_animations() && p_state->animations.size()) {
AnimationPlayer *ap = memnew(AnimationPlayer);
root->add_child(ap, true);
ap->set_owner(root);
- for (int i = 0; i < state->animations.size(); i++) {
- _import_animation(state, ap, i, p_bake_fps);
+ for (int i = 0; i < p_state->animations.size(); i++) {
+ _import_animation(p_state, ap, i, p_bake_fps, p_trimming);
}
}
- for (KeyValue<GLTFNodeIndex, Node *> E : state->scene_nodes) {
+ for (KeyValue<GLTFNodeIndex, Node *> E : p_state->scene_nodes) {
ERR_CONTINUE(!E.value);
- for (int32_t ext_i = 0; ext_i < document_extensions.size(); ext_i++) {
- Ref<GLTFDocumentExtension> ext = document_extensions[ext_i];
+ for (Ref<GLTFDocumentExtension> ext : document_extensions) {
ERR_CONTINUE(ext.is_null());
- ERR_CONTINUE(!state->json.has("nodes"));
- Array nodes = state->json["nodes"];
+ ERR_CONTINUE(!p_state->json.has("nodes"));
+ Array nodes = p_state->json["nodes"];
ERR_CONTINUE(E.key >= nodes.size());
ERR_CONTINUE(E.key < 0);
Dictionary node_json = nodes[E.key];
- Ref<GLTFNode> gltf_node = state->nodes[E.key];
- err = ext->import_node(state, gltf_node, node_json, E.value);
+ Ref<GLTFNode> gltf_node = p_state->nodes[E.key];
+ err = ext->import_node(p_state, gltf_node, node_json, E.value);
ERR_CONTINUE(err != OK);
}
}
- for (int32_t ext_i = 0; ext_i < document_extensions.size(); ext_i++) {
- Ref<GLTFDocumentExtension> ext = document_extensions[ext_i];
+ for (Ref<GLTFDocumentExtension> ext : document_extensions) {
ERR_CONTINUE(ext.is_null());
- err = ext->import_post(state, root);
+ err = ext->import_post(p_state, root);
ERR_CONTINUE(err != OK);
}
ERR_FAIL_NULL_V(root, nullptr);
return root;
}
-Error GLTFDocument::append_from_scene(Node *p_node, Ref<GLTFState> state, uint32_t p_flags, int32_t p_bake_fps) {
- ERR_FAIL_COND_V(state.is_null(), FAILED);
- 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;
+Error GLTFDocument::append_from_scene(Node *p_node, Ref<GLTFState> p_state, uint32_t p_flags) {
+ ERR_FAIL_COND_V(p_state.is_null(), FAILED);
+ p_state->use_named_skin_binds = p_flags & GLTF_IMPORT_USE_NAMED_SKIN_BINDS;
+ p_state->discard_meshes_and_materials = p_flags & GLTF_IMPORT_DISCARD_MESHES_AND_MATERIALS;
- for (int32_t ext_i = 0; ext_i < document_extensions.size(); ext_i++) {
- Ref<GLTFDocumentExtension> ext = document_extensions[ext_i];
+ document_extensions.clear();
+ for (Ref<GLTFDocumentExtension> ext : all_document_extensions) {
ERR_CONTINUE(ext.is_null());
- Error err = ext->export_preflight(p_node);
- ERR_FAIL_COND_V(err != OK, FAILED);
+ Error err = ext->export_preflight(p_state, p_node);
+ if (err == OK) {
+ document_extensions.push_back(ext);
+ }
}
- _convert_scene_node(state, p_node, -1, -1);
- if (!state->buffers.size()) {
- state->buffers.push_back(Vector<uint8_t>());
+ _convert_scene_node(p_state, p_node, -1, -1);
+ if (!p_state->buffers.size()) {
+ p_state->buffers.push_back(Vector<uint8_t>());
}
return OK;
}
-Error GLTFDocument::append_from_buffer(PackedByteArray p_bytes, String p_base_path, Ref<GLTFState> state, uint32_t p_flags, int32_t p_bake_fps) {
- ERR_FAIL_COND_V(state.is_null(), FAILED);
+Error GLTFDocument::append_from_buffer(PackedByteArray p_bytes, String p_base_path, Ref<GLTFState> p_state, uint32_t p_flags) {
+ ERR_FAIL_COND_V(p_state.is_null(), FAILED);
// TODO Add missing texture and missing .bin file paths to r_missing_deps 2021-09-10 fire
Error err = FAILED;
- 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;
+ p_state->use_named_skin_binds = p_flags & GLTF_IMPORT_USE_NAMED_SKIN_BINDS;
+ p_state->discard_meshes_and_materials = p_flags & GLTF_IMPORT_DISCARD_MESHES_AND_MATERIALS;
Ref<FileAccessMemory> file_access;
file_access.instantiate();
file_access->open_custom(p_bytes.ptr(), p_bytes.size());
- state->base_path = p_base_path.get_base_dir();
- err = _parse(state, state->base_path, file_access, p_bake_fps);
+ p_state->base_path = p_base_path.get_base_dir();
+ err = _parse(p_state, p_state->base_path, file_access);
ERR_FAIL_COND_V(err != OK, err);
- for (int32_t ext_i = 0; ext_i < document_extensions.size(); ext_i++) {
- Ref<GLTFDocumentExtension> ext = document_extensions[ext_i];
+ for (Ref<GLTFDocumentExtension> ext : document_extensions) {
ERR_CONTINUE(ext.is_null());
- err = ext->import_post_parse(state);
+ err = ext->import_post_parse(p_state);
ERR_FAIL_COND_V(err != OK, err);
}
return OK;
}
-Error GLTFDocument::_parse_gltf_state(Ref<GLTFState> state, const String &p_search_path, float p_bake_fps) {
+Error GLTFDocument::_parse_gltf_state(Ref<GLTFState> p_state, const String &p_search_path) {
Error err;
/* PARSE EXTENSIONS */
- err = _parse_gltf_extensions(state);
+ err = _parse_gltf_extensions(p_state);
ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR);
/* PARSE SCENE */
- err = _parse_scenes(state);
+ err = _parse_scenes(p_state);
ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR);
/* PARSE NODES */
- err = _parse_nodes(state);
+ err = _parse_nodes(p_state);
ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR);
/* PARSE BUFFERS */
- err = _parse_buffers(state, p_search_path);
+ err = _parse_buffers(p_state, p_search_path);
ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR);
/* PARSE BUFFER VIEWS */
- err = _parse_buffer_views(state);
+ err = _parse_buffer_views(p_state);
ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR);
/* PARSE ACCESSORS */
- err = _parse_accessors(state);
+ err = _parse_accessors(p_state);
ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR);
- if (!state->discard_meshes_and_materials) {
+ if (!p_state->discard_meshes_and_materials) {
/* PARSE IMAGES */
- err = _parse_images(state, p_search_path);
+ err = _parse_images(p_state, p_search_path);
ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR);
/* PARSE TEXTURE SAMPLERS */
- err = _parse_texture_samplers(state);
+ err = _parse_texture_samplers(p_state);
ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR);
/* PARSE TEXTURES */
- err = _parse_textures(state);
+ err = _parse_textures(p_state);
ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR);
/* PARSE TEXTURES */
- err = _parse_materials(state);
+ err = _parse_materials(p_state);
ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR);
}
/* PARSE SKINS */
- err = _parse_skins(state);
+ err = _parse_skins(p_state);
ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR);
/* DETERMINE SKELETONS */
- err = _determine_skeletons(state);
+ err = _determine_skeletons(p_state);
ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR);
/* CREATE SKELETONS */
- err = _create_skeletons(state);
+ err = _create_skeletons(p_state);
ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR);
/* CREATE SKINS */
- err = _create_skins(state);
+ err = _create_skins(p_state);
ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR);
/* PARSE MESHES (we have enough info now) */
- err = _parse_meshes(state);
+ err = _parse_meshes(p_state);
ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR);
/* PARSE LIGHTS */
- err = _parse_lights(state);
+ err = _parse_lights(p_state);
ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR);
/* PARSE CAMERAS */
- err = _parse_cameras(state);
+ err = _parse_cameras(p_state);
ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR);
/* PARSE ANIMATIONS */
- err = _parse_animations(state);
+ err = _parse_animations(p_state);
ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR);
/* ASSIGN SCENE NAMES */
- _assign_scene_names(state);
+ _assign_scene_names(p_state);
Node3D *root = memnew(Node3D);
- for (int32_t root_i = 0; root_i < state->root_nodes.size(); root_i++) {
- _generate_scene_node(state, root, root, state->root_nodes[root_i]);
+ for (int32_t root_i = 0; root_i < p_state->root_nodes.size(); root_i++) {
+ _generate_scene_node(p_state, root, root, p_state->root_nodes[root_i]);
}
return OK;
}
-Error GLTFDocument::append_from_file(String p_path, Ref<GLTFState> r_state, uint32_t p_flags, int32_t p_bake_fps, String p_base_path) {
+Error GLTFDocument::append_from_file(String p_path, Ref<GLTFState> r_state, uint32_t p_flags, String p_base_path) {
// TODO Add missing texture and missing .bin file paths to r_missing_deps 2021-09-10 fire
if (r_state == Ref<GLTFState>()) {
r_state.instantiate();
@@ -7020,18 +7074,17 @@ Error GLTFDocument::append_from_file(String p_path, Ref<GLTFState> r_state, uint
r_state->use_named_skin_binds = p_flags & GLTF_IMPORT_USE_NAMED_SKIN_BINDS;
r_state->discard_meshes_and_materials = p_flags & GLTF_IMPORT_DISCARD_MESHES_AND_MATERIALS;
Error err;
- Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ, &err);
+ Ref<FileAccess> file = FileAccess::open(p_path, FileAccess::READ, &err);
ERR_FAIL_COND_V(err != OK, ERR_FILE_CANT_OPEN);
- ERR_FAIL_NULL_V(f, ERR_FILE_CANT_OPEN);
+ ERR_FAIL_NULL_V(file, ERR_FILE_CANT_OPEN);
String base_path = p_base_path;
if (base_path.is_empty()) {
base_path = p_path.get_base_dir();
}
r_state->base_path = base_path;
- err = _parse(r_state, base_path, f, p_bake_fps);
+ err = _parse(r_state, base_path, file);
ERR_FAIL_COND_V(err != OK, err);
- for (int32_t ext_i = 0; ext_i < document_extensions.size(); ext_i++) {
- Ref<GLTFDocumentExtension> ext = document_extensions[ext_i];
+ for (Ref<GLTFDocumentExtension> ext : document_extensions) {
ERR_CONTINUE(ext.is_null());
err = ext->import_post_parse(r_state);
ERR_FAIL_COND_V(err != OK, err);
@@ -7039,22 +7092,21 @@ Error GLTFDocument::append_from_file(String p_path, Ref<GLTFState> r_state, uint
return OK;
}
-Error GLTFDocument::_parse_gltf_extensions(Ref<GLTFState> state) {
- ERR_FAIL_NULL_V(state, ERR_PARSE_ERROR);
- if (state->json.has("extensionsUsed")) {
- Vector<String> ext_array = state->json["extensionsUsed"];
- state->extensions_used = ext_array;
+Error GLTFDocument::_parse_gltf_extensions(Ref<GLTFState> p_state) {
+ ERR_FAIL_NULL_V(p_state, ERR_PARSE_ERROR);
+ if (p_state->json.has("extensionsUsed")) {
+ Vector<String> ext_array = p_state->json["extensionsUsed"];
+ p_state->extensions_used = ext_array;
}
- if (state->json.has("extensionsRequired")) {
- Vector<String> ext_array = state->json["extensionsRequired"];
- state->extensions_required = ext_array;
+ if (p_state->json.has("extensionsRequired")) {
+ Vector<String> ext_array = p_state->json["extensionsRequired"];
+ p_state->extensions_required = ext_array;
}
HashSet<String> supported_extensions;
supported_extensions.insert("KHR_lights_punctual");
supported_extensions.insert("KHR_materials_pbrSpecularGlossiness");
supported_extensions.insert("KHR_texture_transform");
- for (int ext_i = 0; ext_i < document_extensions.size(); ext_i++) {
- Ref<GLTFDocumentExtension> ext = document_extensions[ext_i];
+ for (Ref<GLTFDocumentExtension> ext : document_extensions) {
ERR_CONTINUE(ext.is_null());
Vector<String> ext_supported_extensions = ext->get_supported_extensions();
for (int i = 0; i < ext_supported_extensions.size(); ++i) {
@@ -7062,9 +7114,9 @@ Error GLTFDocument::_parse_gltf_extensions(Ref<GLTFState> state) {
}
}
Error ret = Error::OK;
- for (int i = 0; i < state->extensions_required.size(); i++) {
- if (!supported_extensions.has(state->extensions_required[i])) {
- ERR_PRINT("GLTF: Can't import file '" + state->filename + "', required extension '" + String(state->extensions_required[i]) + "' is not supported. Are you missing a GLTFDocumentExtension plugin?");
+ for (int i = 0; i < p_state->extensions_required.size(); i++) {
+ if (!supported_extensions.has(p_state->extensions_required[i])) {
+ ERR_PRINT("GLTF: Can't import file '" + p_state->filename + "', required extension '" + String(p_state->extensions_required[i]) + "' is not supported. Are you missing a GLTFDocumentExtension plugin?");
ret = ERR_UNAVAILABLE;
}
}
diff --git a/modules/gltf/gltf_document.h b/modules/gltf/gltf_document.h
index 62b6e29fe0..6e2d0e2fd4 100644
--- a/modules/gltf/gltf_document.h
+++ b/modules/gltf/gltf_document.h
@@ -31,26 +31,19 @@
#ifndef GLTF_DOCUMENT_H
#define GLTF_DOCUMENT_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/mesh_instance_3d.h"
-#include "scene/animation/animation_player.h"
-#include "scene/resources/material.h"
+#include "extensions/gltf_document_extension.h"
#include "modules/modules_enabled.gen.h" // For csg, gridmap.
class GLTFDocument : public Resource {
GDCLASS(GLTFDocument, Resource);
- TypedArray<GLTFDocumentExtension> document_extensions;
+ static Vector<Ref<GLTFDocumentExtension>> all_document_extensions;
+ Vector<Ref<GLTFDocumentExtension>> document_extensions;
private:
const float BAKE_FPS = 30.0f;
public:
- GLTFDocument();
const int32_t JOINT_GROUP_SIZE = 4;
enum {
@@ -76,203 +69,204 @@ protected:
static void _bind_methods();
public:
- void set_extensions(TypedArray<GLTFDocumentExtension> p_extensions);
- TypedArray<GLTFDocumentExtension> get_extensions() const;
+ static void register_gltf_document_extension(Ref<GLTFDocumentExtension> p_extension, bool p_first_priority = false);
+ static void unregister_gltf_document_extension(Ref<GLTFDocumentExtension> p_extension);
+ static void unregister_all_gltf_document_extensions();
private:
- void _build_parent_hierachy(Ref<GLTFState> state);
+ void _build_parent_hierachy(Ref<GLTFState> p_state);
double _filter_number(double p_float);
String _get_component_type_name(const uint32_t p_component);
- int _get_component_type_size(const int component_type);
- Error _parse_scenes(Ref<GLTFState> state);
- Error _parse_nodes(Ref<GLTFState> state);
+ int _get_component_type_size(const int p_component_type);
+ Error _parse_scenes(Ref<GLTFState> p_state);
+ Error _parse_nodes(Ref<GLTFState> p_state);
String _get_type_name(const GLTFType p_component);
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);
- String _sanitize_bone_name(const String &name);
- String _gen_unique_bone_name(Ref<GLTFState> state,
- const GLTFSkeletonIndex skel_i,
+ String _gen_unique_name(Ref<GLTFState> p_state, const String &p_name);
+ String _sanitize_animation_name(const String &p_name);
+ String _gen_unique_animation_name(Ref<GLTFState> p_state, const String &p_name);
+ String _sanitize_bone_name(const String &p_name);
+ String _gen_unique_bone_name(Ref<GLTFState> p_state,
+ const GLTFSkeletonIndex p_skel_i,
const String &p_name);
- GLTFTextureIndex _set_texture(Ref<GLTFState> state, Ref<Texture2D> p_texture,
+ GLTFTextureIndex _set_texture(Ref<GLTFState> p_state, Ref<Texture2D> p_texture,
StandardMaterial3D::TextureFilter p_filter_mode, bool p_repeats);
- Ref<Texture2D> _get_texture(Ref<GLTFState> state,
+ Ref<Texture2D> _get_texture(Ref<GLTFState> p_state,
const GLTFTextureIndex p_texture);
- GLTFTextureSamplerIndex _set_sampler_for_mode(Ref<GLTFState> state,
+ GLTFTextureSamplerIndex _set_sampler_for_mode(Ref<GLTFState> p_state,
StandardMaterial3D::TextureFilter p_filter_mode, bool p_repeats);
- Ref<GLTFTextureSampler> _get_sampler_for_texture(Ref<GLTFState> state,
+ Ref<GLTFTextureSampler> _get_sampler_for_texture(Ref<GLTFState> p_state,
const GLTFTextureIndex p_texture);
- Error _parse_json(const String &p_path, Ref<GLTFState> state);
- Error _parse_glb(Ref<FileAccess> f, Ref<GLTFState> state);
- void _compute_node_heights(Ref<GLTFState> state);
- Error _parse_buffers(Ref<GLTFState> state, const String &p_base_path);
- Error _parse_buffer_views(Ref<GLTFState> state);
+ Error _parse_json(const String &p_path, Ref<GLTFState> p_state);
+ Error _parse_glb(Ref<FileAccess> p_file, Ref<GLTFState> p_state);
+ void _compute_node_heights(Ref<GLTFState> p_state);
+ Error _parse_buffers(Ref<GLTFState> p_state, const String &p_base_path);
+ Error _parse_buffer_views(Ref<GLTFState> p_state);
GLTFType _get_type_from_str(const String &p_string);
- Error _parse_accessors(Ref<GLTFState> state);
- Error _decode_buffer_view(Ref<GLTFState> state, double *dst,
+ Error _parse_accessors(Ref<GLTFState> p_state);
+ Error _decode_buffer_view(Ref<GLTFState> p_state, double *p_dst,
const GLTFBufferViewIndex p_buffer_view,
- const int skip_every, const int skip_bytes,
- const int element_size, const int count,
- const GLTFType type, const int component_count,
- const int component_type, const int component_size,
- const bool normalized, const int byte_offset,
- const bool for_vertex);
- Vector<double> _decode_accessor(Ref<GLTFState> state,
+ const int p_skip_every, const int p_skip_bytes,
+ const int p_element_size, const int p_count,
+ const GLTFType p_type, const int p_component_count,
+ const int p_component_type, const int p_component_size,
+ const bool p_normalized, const int p_byte_offset,
+ const bool p_for_vertex);
+ Vector<double> _decode_accessor(Ref<GLTFState> p_state,
const GLTFAccessorIndex p_accessor,
const bool p_for_vertex);
- Vector<float> _decode_accessor_as_floats(Ref<GLTFState> state,
+ Vector<float> _decode_accessor_as_floats(Ref<GLTFState> p_state,
const GLTFAccessorIndex p_accessor,
const bool p_for_vertex);
- Vector<int> _decode_accessor_as_ints(Ref<GLTFState> state,
+ Vector<int> _decode_accessor_as_ints(Ref<GLTFState> p_state,
const GLTFAccessorIndex p_accessor,
const bool p_for_vertex);
- Vector<Vector2> _decode_accessor_as_vec2(Ref<GLTFState> state,
+ Vector<Vector2> _decode_accessor_as_vec2(Ref<GLTFState> p_state,
const GLTFAccessorIndex p_accessor,
const bool p_for_vertex);
- Vector<Vector3> _decode_accessor_as_vec3(Ref<GLTFState> state,
+ Vector<Vector3> _decode_accessor_as_vec3(Ref<GLTFState> p_state,
const GLTFAccessorIndex p_accessor,
const bool p_for_vertex);
- Vector<Color> _decode_accessor_as_color(Ref<GLTFState> state,
+ Vector<Color> _decode_accessor_as_color(Ref<GLTFState> p_state,
const GLTFAccessorIndex p_accessor,
const bool p_for_vertex);
- Vector<Quaternion> _decode_accessor_as_quaternion(Ref<GLTFState> state,
+ Vector<Quaternion> _decode_accessor_as_quaternion(Ref<GLTFState> p_state,
const GLTFAccessorIndex p_accessor,
const bool p_for_vertex);
- Vector<Transform2D> _decode_accessor_as_xform2d(Ref<GLTFState> state,
+ Vector<Transform2D> _decode_accessor_as_xform2d(Ref<GLTFState> p_state,
const GLTFAccessorIndex p_accessor,
const bool p_for_vertex);
- Vector<Basis> _decode_accessor_as_basis(Ref<GLTFState> state,
+ Vector<Basis> _decode_accessor_as_basis(Ref<GLTFState> p_state,
const GLTFAccessorIndex p_accessor,
const bool p_for_vertex);
- Vector<Transform3D> _decode_accessor_as_xform(Ref<GLTFState> state,
+ Vector<Transform3D> _decode_accessor_as_xform(Ref<GLTFState> p_state,
const GLTFAccessorIndex p_accessor,
const bool p_for_vertex);
- Error _parse_meshes(Ref<GLTFState> state);
- Error _serialize_textures(Ref<GLTFState> state);
- Error _serialize_texture_samplers(Ref<GLTFState> state);
- Error _serialize_images(Ref<GLTFState> state, const String &p_path);
- Error _serialize_lights(Ref<GLTFState> state);
- Error _parse_images(Ref<GLTFState> state, const String &p_base_path);
- Error _parse_textures(Ref<GLTFState> state);
- Error _parse_texture_samplers(Ref<GLTFState> state);
- Error _parse_materials(Ref<GLTFState> state);
- void _set_texture_transform_uv1(const Dictionary &d, Ref<BaseMaterial3D> material);
+ Error _parse_meshes(Ref<GLTFState> p_state);
+ Error _serialize_textures(Ref<GLTFState> p_state);
+ Error _serialize_texture_samplers(Ref<GLTFState> p_state);
+ Error _serialize_images(Ref<GLTFState> p_state, const String &p_path);
+ Error _serialize_lights(Ref<GLTFState> p_state);
+ Error _parse_images(Ref<GLTFState> p_state, const String &p_base_path);
+ Error _parse_textures(Ref<GLTFState> p_state);
+ Error _parse_texture_samplers(Ref<GLTFState> p_state);
+ Error _parse_materials(Ref<GLTFState> p_state);
+ void _set_texture_transform_uv1(const Dictionary &d, Ref<BaseMaterial3D> p_material);
void spec_gloss_to_rough_metal(Ref<GLTFSpecGloss> r_spec_gloss,
Ref<BaseMaterial3D> p_material);
static void spec_gloss_to_metal_base_color(const Color &p_specular_factor,
const Color &p_diffuse,
Color &r_base_color,
float &r_metallic);
- GLTFNodeIndex _find_highest_node(Ref<GLTFState> state,
- const Vector<GLTFNodeIndex> &subset);
- bool _capture_nodes_in_skin(Ref<GLTFState> state, Ref<GLTFSkin> skin,
- const GLTFNodeIndex node_index);
- void _capture_nodes_for_multirooted_skin(Ref<GLTFState> state, Ref<GLTFSkin> skin);
- Error _expand_skin(Ref<GLTFState> state, Ref<GLTFSkin> skin);
- Error _verify_skin(Ref<GLTFState> state, Ref<GLTFSkin> skin);
- Error _parse_skins(Ref<GLTFState> state);
- Error _determine_skeletons(Ref<GLTFState> state);
+ GLTFNodeIndex _find_highest_node(Ref<GLTFState> p_state,
+ const Vector<GLTFNodeIndex> &p_subset);
+ bool _capture_nodes_in_skin(Ref<GLTFState> p_state, Ref<GLTFSkin> p_skin,
+ const GLTFNodeIndex p_node_index);
+ void _capture_nodes_for_multirooted_skin(Ref<GLTFState> p_state, Ref<GLTFSkin> p_skin);
+ Error _expand_skin(Ref<GLTFState> p_state, Ref<GLTFSkin> p_skin);
+ Error _verify_skin(Ref<GLTFState> p_state, Ref<GLTFSkin> p_skin);
+ Error _parse_skins(Ref<GLTFState> p_state);
+ Error _determine_skeletons(Ref<GLTFState> p_state);
Error _reparent_non_joint_skeleton_subtrees(
- Ref<GLTFState> state, Ref<GLTFSkeleton> skeleton,
- const Vector<GLTFNodeIndex> &non_joints);
- Error _determine_skeleton_roots(Ref<GLTFState> state,
- const GLTFSkeletonIndex skel_i);
- Error _create_skeletons(Ref<GLTFState> state);
- Error _map_skin_joints_indices_to_skeleton_bone_indices(Ref<GLTFState> state);
- Error _serialize_skins(Ref<GLTFState> state);
- Error _create_skins(Ref<GLTFState> state);
- bool _skins_are_same(const Ref<Skin> skin_a, const Ref<Skin> skin_b);
- void _remove_duplicate_skins(Ref<GLTFState> state);
- Error _serialize_cameras(Ref<GLTFState> state);
- Error _parse_cameras(Ref<GLTFState> state);
- Error _parse_lights(Ref<GLTFState> state);
- Error _parse_animations(Ref<GLTFState> state);
- Error _serialize_animations(Ref<GLTFState> state);
- BoneAttachment3D *_generate_bone_attachment(Ref<GLTFState> state,
- Skeleton3D *skeleton,
- const GLTFNodeIndex node_index,
- const GLTFNodeIndex bone_index);
- ImporterMeshInstance3D *_generate_mesh_instance(Ref<GLTFState> state, const GLTFNodeIndex node_index);
- Camera3D *_generate_camera(Ref<GLTFState> state, const GLTFNodeIndex node_index);
- Light3D *_generate_light(Ref<GLTFState> state, const GLTFNodeIndex node_index);
- Node3D *_generate_spatial(Ref<GLTFState> state, const GLTFNodeIndex node_index);
- void _assign_scene_names(Ref<GLTFState> state);
+ Ref<GLTFState> p_state, Ref<GLTFSkeleton> p_skeleton,
+ const Vector<GLTFNodeIndex> &p_non_joints);
+ Error _determine_skeleton_roots(Ref<GLTFState> p_state,
+ const GLTFSkeletonIndex p_skel_i);
+ Error _create_skeletons(Ref<GLTFState> p_state);
+ Error _map_skin_joints_indices_to_skeleton_bone_indices(Ref<GLTFState> p_state);
+ Error _serialize_skins(Ref<GLTFState> p_state);
+ Error _create_skins(Ref<GLTFState> p_state);
+ bool _skins_are_same(const Ref<Skin> p_skin_a, const Ref<Skin> p_skin_b);
+ void _remove_duplicate_skins(Ref<GLTFState> p_state);
+ Error _serialize_cameras(Ref<GLTFState> p_state);
+ Error _parse_cameras(Ref<GLTFState> p_state);
+ Error _parse_lights(Ref<GLTFState> p_state);
+ Error _parse_animations(Ref<GLTFState> p_state);
+ Error _serialize_animations(Ref<GLTFState> p_state);
+ BoneAttachment3D *_generate_bone_attachment(Ref<GLTFState> p_state,
+ Skeleton3D *p_skeleton,
+ const GLTFNodeIndex p_node_index,
+ const GLTFNodeIndex p_bone_index);
+ ImporterMeshInstance3D *_generate_mesh_instance(Ref<GLTFState> p_state, const GLTFNodeIndex p_node_index);
+ Camera3D *_generate_camera(Ref<GLTFState> p_state, const GLTFNodeIndex p_node_index);
+ Light3D *_generate_light(Ref<GLTFState> p_state, const GLTFNodeIndex p_node_index);
+ Node3D *_generate_spatial(Ref<GLTFState> p_state, const GLTFNodeIndex p_node_index);
+ void _assign_scene_names(Ref<GLTFState> p_state);
template <class T>
T _interpolate_track(const Vector<real_t> &p_times, const Vector<T> &p_values,
const float p_time,
const GLTFAnimation::Interpolation p_interp);
- GLTFAccessorIndex _encode_accessor_as_quaternions(Ref<GLTFState> state,
+ GLTFAccessorIndex _encode_accessor_as_quaternions(Ref<GLTFState> p_state,
const Vector<Quaternion> p_attribs,
const bool p_for_vertex);
- GLTFAccessorIndex _encode_accessor_as_weights(Ref<GLTFState> state,
+ GLTFAccessorIndex _encode_accessor_as_weights(Ref<GLTFState> p_state,
const Vector<Color> p_attribs,
const bool p_for_vertex);
- GLTFAccessorIndex _encode_accessor_as_joints(Ref<GLTFState> state,
+ GLTFAccessorIndex _encode_accessor_as_joints(Ref<GLTFState> p_state,
const Vector<Color> p_attribs,
const bool p_for_vertex);
- GLTFAccessorIndex _encode_accessor_as_floats(Ref<GLTFState> state,
+ GLTFAccessorIndex _encode_accessor_as_floats(Ref<GLTFState> p_state,
const Vector<real_t> p_attribs,
const bool p_for_vertex);
- GLTFAccessorIndex _encode_accessor_as_vec2(Ref<GLTFState> state,
+ GLTFAccessorIndex _encode_accessor_as_vec2(Ref<GLTFState> p_state,
const Vector<Vector2> p_attribs,
const bool p_for_vertex);
- void _calc_accessor_vec2_min_max(int i, const int element_count, Vector<double> &type_max, Vector2 attribs, Vector<double> &type_min) {
- if (i == 0) {
- for (int32_t type_i = 0; type_i < element_count; type_i++) {
- type_max.write[type_i] = attribs[(i * element_count) + type_i];
- type_min.write[type_i] = attribs[(i * element_count) + type_i];
+ void _calc_accessor_vec2_min_max(int p_i, const int p_element_count, Vector<double> &p_type_max, Vector2 p_attribs, Vector<double> &p_type_min) {
+ if (p_i == 0) {
+ for (int32_t type_i = 0; type_i < p_element_count; type_i++) {
+ p_type_max.write[type_i] = p_attribs[(p_i * p_element_count) + type_i];
+ p_type_min.write[type_i] = p_attribs[(p_i * p_element_count) + type_i];
}
}
- for (int32_t type_i = 0; type_i < element_count; type_i++) {
- type_max.write[type_i] = MAX(attribs[(i * element_count) + type_i], type_max[type_i]);
- type_min.write[type_i] = MIN(attribs[(i * element_count) + type_i], type_min[type_i]);
- type_max.write[type_i] = _filter_number(type_max.write[type_i]);
- type_min.write[type_i] = _filter_number(type_min.write[type_i]);
+ for (int32_t type_i = 0; type_i < p_element_count; type_i++) {
+ p_type_max.write[type_i] = MAX(p_attribs[(p_i * p_element_count) + type_i], p_type_max[type_i]);
+ p_type_min.write[type_i] = MIN(p_attribs[(p_i * p_element_count) + type_i], p_type_min[type_i]);
+ p_type_max.write[type_i] = _filter_number(p_type_max.write[type_i]);
+ p_type_min.write[type_i] = _filter_number(p_type_min.write[type_i]);
}
}
- GLTFAccessorIndex _encode_accessor_as_vec3(Ref<GLTFState> state,
+ GLTFAccessorIndex _encode_accessor_as_vec3(Ref<GLTFState> p_state,
const Vector<Vector3> p_attribs,
const bool p_for_vertex);
- GLTFAccessorIndex _encode_accessor_as_color(Ref<GLTFState> state,
+ GLTFAccessorIndex _encode_accessor_as_color(Ref<GLTFState> p_state,
const Vector<Color> p_attribs,
const bool p_for_vertex);
void _calc_accessor_min_max(int p_i, const int p_element_count, Vector<double> &p_type_max, Vector<double> p_attribs, Vector<double> &p_type_min);
- GLTFAccessorIndex _encode_accessor_as_ints(Ref<GLTFState> state,
+ GLTFAccessorIndex _encode_accessor_as_ints(Ref<GLTFState> p_state,
const Vector<int32_t> p_attribs,
const bool p_for_vertex);
- GLTFAccessorIndex _encode_accessor_as_xform(Ref<GLTFState> state,
+ GLTFAccessorIndex _encode_accessor_as_xform(Ref<GLTFState> p_state,
const Vector<Transform3D> p_attribs,
const bool p_for_vertex);
- Error _encode_buffer_view(Ref<GLTFState> state, const double *src,
- const int count, const GLTFType type,
- const int component_type, const bool normalized,
- const int byte_offset, const bool for_vertex,
+ Error _encode_buffer_view(Ref<GLTFState> p_state, const double *p_src,
+ const int p_count, const GLTFType p_type,
+ const int p_component_type, const bool p_normalized,
+ const int p_byte_offset, const bool p_for_vertex,
GLTFBufferViewIndex &r_accessor);
- Error _encode_accessors(Ref<GLTFState> state);
- Error _encode_buffer_views(Ref<GLTFState> state);
- Error _serialize_materials(Ref<GLTFState> state);
- Error _serialize_meshes(Ref<GLTFState> state);
- Error _serialize_nodes(Ref<GLTFState> state);
- Error _serialize_scenes(Ref<GLTFState> state);
+ Error _encode_accessors(Ref<GLTFState> p_state);
+ Error _encode_buffer_views(Ref<GLTFState> p_state);
+ Error _serialize_materials(Ref<GLTFState> p_state);
+ Error _serialize_meshes(Ref<GLTFState> p_state);
+ Error _serialize_nodes(Ref<GLTFState> p_state);
+ Error _serialize_scenes(Ref<GLTFState> p_state);
String interpolation_to_string(const GLTFAnimation::Interpolation p_interp);
- GLTFAnimation::Track _convert_animation_track(Ref<GLTFState> state,
+ GLTFAnimation::Track _convert_animation_track(Ref<GLTFState> p_state,
GLTFAnimation::Track p_track,
Ref<Animation> p_animation,
int32_t p_track_i,
GLTFNodeIndex p_node_i);
- Error _encode_buffer_bins(Ref<GLTFState> state, const String &p_path);
- Error _encode_buffer_glb(Ref<GLTFState> state, const String &p_path);
- PackedByteArray _serialize_glb_buffer(Ref<GLTFState> state, Error *r_err);
+ Error _encode_buffer_bins(Ref<GLTFState> p_state, const String &p_path);
+ Error _encode_buffer_glb(Ref<GLTFState> p_state, const String &p_path);
+ PackedByteArray _serialize_glb_buffer(Ref<GLTFState> p_state, Error *r_err);
Dictionary _serialize_texture_transform_uv1(Ref<BaseMaterial3D> p_material);
Dictionary _serialize_texture_transform_uv2(Ref<BaseMaterial3D> p_material);
- Error _serialize_version(Ref<GLTFState> state);
- Error _serialize_file(Ref<GLTFState> state, const String p_path);
- Error _serialize_gltf_extensions(Ref<GLTFState> state) const;
+ Error _serialize_version(Ref<GLTFState> p_state);
+ Error _serialize_file(Ref<GLTFState> p_state, const String p_path);
+ Error _serialize_gltf_extensions(Ref<GLTFState> p_state) const;
public:
// https://www.itu.int/rec/R-REC-BT.601
@@ -284,90 +278,90 @@ public:
private:
// https://github.com/microsoft/glTF-SDK/blob/master/GLTFSDK/Source/PBRUtils.cpp#L9
// https://bghgary.github.io/glTF/convert-between-workflows-bjs/js/babylon.pbrUtilities.js
- static float solve_metallic(float p_dielectric_specular, float diffuse,
- float specular,
+ static float solve_metallic(float p_dielectric_specular, float p_diffuse,
+ float p_specular,
float p_one_minus_specular_strength);
static float get_perceived_brightness(const Color p_color);
static float get_max_component(const Color &p_color);
public:
- Error append_from_file(String p_path, Ref<GLTFState> r_state, uint32_t p_flags = 0, int32_t p_bake_fps = 30, String p_base_path = String());
- Error append_from_buffer(PackedByteArray p_bytes, String p_base_path, Ref<GLTFState> r_state, uint32_t p_flags = 0, int32_t p_bake_fps = 30);
- Error append_from_scene(Node *p_node, Ref<GLTFState> r_state, uint32_t p_flags = 0, int32_t p_bake_fps = 30);
+ Error append_from_file(String p_path, Ref<GLTFState> r_state, uint32_t p_flags = 0, String p_base_path = String());
+ Error append_from_buffer(PackedByteArray p_bytes, String p_base_path, Ref<GLTFState> r_state, uint32_t p_flags = 0);
+ Error append_from_scene(Node *p_node, Ref<GLTFState> r_state, uint32_t p_flags = 0);
public:
- Node *generate_scene(Ref<GLTFState> state, int32_t p_bake_fps = 30.0f);
- PackedByteArray generate_buffer(Ref<GLTFState> state);
- Error write_to_filesystem(Ref<GLTFState> state, const String &p_path);
+ Node *generate_scene(Ref<GLTFState> p_state, float p_bake_fps = 30.0f, bool p_trimming = false);
+ PackedByteArray generate_buffer(Ref<GLTFState> p_state);
+ Error write_to_filesystem(Ref<GLTFState> p_state, const String &p_path);
public:
- Error _parse_gltf_state(Ref<GLTFState> state, const String &p_search_path, float p_bake_fps);
- Error _parse_gltf_extensions(Ref<GLTFState> state);
- void _process_mesh_instances(Ref<GLTFState> state, Node *scene_root);
- void _generate_scene_node(Ref<GLTFState> state, Node *scene_parent,
- Node3D *scene_root,
- const GLTFNodeIndex node_index);
- void _generate_skeleton_bone_node(Ref<GLTFState> state, Node *scene_parent, Node3D *scene_root, const GLTFNodeIndex node_index);
- void _import_animation(Ref<GLTFState> state, AnimationPlayer *ap,
- const GLTFAnimationIndex index, const int bake_fps);
- void _convert_mesh_instances(Ref<GLTFState> state);
- GLTFCameraIndex _convert_camera(Ref<GLTFState> state, Camera3D *p_camera);
- void _convert_light_to_gltf(Light3D *light, Ref<GLTFState> state, Ref<GLTFNode> gltf_node);
- GLTFLightIndex _convert_light(Ref<GLTFState> state, Light3D *p_light);
- void _convert_spatial(Ref<GLTFState> state, Node3D *p_spatial, Ref<GLTFNode> p_node);
- void _convert_scene_node(Ref<GLTFState> state, Node *p_current,
+ Error _parse_gltf_state(Ref<GLTFState> p_state, const String &p_search_path);
+ Error _parse_gltf_extensions(Ref<GLTFState> p_state);
+ void _process_mesh_instances(Ref<GLTFState> p_state, Node *p_scene_root);
+ void _generate_scene_node(Ref<GLTFState> p_state, Node *p_scene_parent,
+ Node3D *p_scene_root,
+ const GLTFNodeIndex p_node_index);
+ void _generate_skeleton_bone_node(Ref<GLTFState> p_state, Node *p_scene_parent, Node3D *p_scene_root, const GLTFNodeIndex p_node_index);
+ void _import_animation(Ref<GLTFState> p_state, AnimationPlayer *p_animation_player,
+ const GLTFAnimationIndex p_index, const float p_bake_fps, const bool p_trimming);
+ void _convert_mesh_instances(Ref<GLTFState> p_state);
+ GLTFCameraIndex _convert_camera(Ref<GLTFState> p_state, Camera3D *p_camera);
+ void _convert_light_to_gltf(Light3D *p_light, Ref<GLTFState> p_state, Ref<GLTFNode> p_gltf_node);
+ GLTFLightIndex _convert_light(Ref<GLTFState> p_state, Light3D *p_light);
+ void _convert_spatial(Ref<GLTFState> p_state, Node3D *p_spatial, Ref<GLTFNode> p_node);
+ void _convert_scene_node(Ref<GLTFState> p_state, Node *p_current,
const GLTFNodeIndex p_gltf_current,
const GLTFNodeIndex p_gltf_root);
#ifdef MODULE_CSG_ENABLED
- void _convert_csg_shape_to_gltf(CSGShape3D *p_current, GLTFNodeIndex p_gltf_parent, Ref<GLTFNode> gltf_node, Ref<GLTFState> state);
+ void _convert_csg_shape_to_gltf(CSGShape3D *p_current, GLTFNodeIndex p_gltf_parent, Ref<GLTFNode> p_gltf_node, Ref<GLTFState> p_state);
#endif // MODULE_CSG_ENABLED
- void _create_gltf_node(Ref<GLTFState> state,
+ void _create_gltf_node(Ref<GLTFState> p_state,
Node *p_scene_parent,
- GLTFNodeIndex current_node_i,
+ GLTFNodeIndex p_current_node_i,
GLTFNodeIndex p_parent_node_index,
GLTFNodeIndex p_root_gltf_node,
- Ref<GLTFNode> gltf_node);
+ Ref<GLTFNode> p_gltf_node);
void _convert_animation_player_to_gltf(
- AnimationPlayer *animation_player, Ref<GLTFState> state,
+ AnimationPlayer *p_animation_player, Ref<GLTFState> p_state,
GLTFNodeIndex p_gltf_current,
GLTFNodeIndex p_gltf_root_index,
Ref<GLTFNode> p_gltf_node, Node *p_scene_parent);
- void _check_visibility(Node *p_node, bool &retflag);
- void _convert_camera_to_gltf(Camera3D *camera, Ref<GLTFState> state,
- Ref<GLTFNode> gltf_node);
+ void _check_visibility(Node *p_node, bool &r_retflag);
+ void _convert_camera_to_gltf(Camera3D *p_camera, Ref<GLTFState> p_state,
+ Ref<GLTFNode> p_gltf_node);
#ifdef MODULE_GRIDMAP_ENABLED
void _convert_grid_map_to_gltf(
GridMap *p_grid_map,
GLTFNodeIndex p_parent_node_index,
GLTFNodeIndex p_root_node_index,
- Ref<GLTFNode> gltf_node, Ref<GLTFState> state);
+ Ref<GLTFNode> p_gltf_node, Ref<GLTFState> p_state);
#endif // MODULE_GRIDMAP_ENABLED
void _convert_multi_mesh_instance_to_gltf(
MultiMeshInstance3D *p_multi_mesh_instance,
GLTFNodeIndex p_parent_node_index,
GLTFNodeIndex p_root_node_index,
- Ref<GLTFNode> gltf_node, Ref<GLTFState> state);
+ Ref<GLTFNode> p_gltf_node, Ref<GLTFState> p_state);
void _convert_skeleton_to_gltf(
- Skeleton3D *p_scene_parent, Ref<GLTFState> state,
+ Skeleton3D *p_scene_parent, Ref<GLTFState> p_state,
GLTFNodeIndex p_parent_node_index,
GLTFNodeIndex p_root_node_index,
- Ref<GLTFNode> gltf_node);
+ Ref<GLTFNode> p_gltf_node);
void _convert_bone_attachment_to_gltf(BoneAttachment3D *p_bone_attachment,
- Ref<GLTFState> state,
+ Ref<GLTFState> p_state,
GLTFNodeIndex p_parent_node_index,
GLTFNodeIndex p_root_node_index,
- Ref<GLTFNode> gltf_node);
+ Ref<GLTFNode> p_gltf_node);
void _convert_mesh_instance_to_gltf(MeshInstance3D *p_mesh_instance,
- Ref<GLTFState> state,
- Ref<GLTFNode> gltf_node);
- GLTFMeshIndex _convert_mesh_to_gltf(Ref<GLTFState> state,
+ Ref<GLTFState> p_state,
+ Ref<GLTFNode> p_gltf_node);
+ GLTFMeshIndex _convert_mesh_to_gltf(Ref<GLTFState> p_state,
MeshInstance3D *p_mesh_instance);
- void _convert_animation(Ref<GLTFState> state, AnimationPlayer *ap,
+ void _convert_animation(Ref<GLTFState> p_state, AnimationPlayer *p_animation_player,
String p_animation_track_name);
- Error _serialize(Ref<GLTFState> state, const String &p_path);
- Error _parse(Ref<GLTFState> state, String p_path, Ref<FileAccess> f, int p_bake_fps);
+ Error _serialize(Ref<GLTFState> p_state, const String &p_path);
+ Error _parse(Ref<GLTFState> p_state, String p_path, Ref<FileAccess> p_file);
};
#endif // GLTF_DOCUMENT_H
diff --git a/modules/gltf/gltf_state.cpp b/modules/gltf/gltf_state.cpp
index ac5665e396..9f6cb20935 100644
--- a/modules/gltf/gltf_state.cpp
+++ b/modules/gltf/gltf_state.cpp
@@ -30,6 +30,8 @@
#include "gltf_state.h"
+#include "gltf_template_convert.h"
+
void GLTFState::_bind_methods() {
ClassDB::bind_method(D_METHOD("add_used_extension", "extension_name", "required"), &GLTFState::add_used_extension);
ClassDB::bind_method(D_METHOD("get_json"), &GLTFState::get_json);
@@ -209,11 +211,11 @@ void GLTFState::set_meshes(TypedArray<GLTFMesh> p_meshes) {
GLTFTemplateConvert::set_from_array(meshes, p_meshes);
}
-TypedArray<BaseMaterial3D> GLTFState::get_materials() {
+TypedArray<Material> GLTFState::get_materials() {
return GLTFTemplateConvert::to_array(materials);
}
-void GLTFState::set_materials(TypedArray<BaseMaterial3D> p_materials) {
+void GLTFState::set_materials(TypedArray<Material> p_materials) {
GLTFTemplateConvert::set_from_array(materials, p_materials);
}
diff --git a/modules/gltf/gltf_state.h b/modules/gltf/gltf_state.h
index e24017b0fd..e264da69e0 100644
--- a/modules/gltf/gltf_state.h
+++ b/modules/gltf/gltf_state.h
@@ -32,7 +32,6 @@
#define GLTF_STATE_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"
@@ -44,10 +43,6 @@
#include "structures/gltf_texture.h"
#include "structures/gltf_texture_sampler.h"
-#include "core/templates/rb_map.h"
-#include "scene/animation/animation_player.h"
-#include "scene/resources/texture.h"
-
class GLTFState : public Resource {
GDCLASS(GLTFState, Resource);
friend class GLTFDocument;
@@ -72,8 +67,8 @@ class GLTFState : public Resource {
Vector<Ref<GLTFMesh>> meshes; // meshes are loaded directly, no reason not to.
Vector<AnimationPlayer *> animation_players;
- HashMap<Ref<BaseMaterial3D>, GLTFMaterialIndex> material_cache;
- Vector<Ref<BaseMaterial3D>> materials;
+ HashMap<Ref<Material>, GLTFMaterialIndex> material_cache;
+ Vector<Ref<Material>> materials;
String scene_name;
Vector<int> root_nodes;
@@ -138,8 +133,8 @@ public:
TypedArray<GLTFMesh> get_meshes();
void set_meshes(TypedArray<GLTFMesh> p_meshes);
- TypedArray<BaseMaterial3D> get_materials();
- void set_materials(TypedArray<BaseMaterial3D> p_materials);
+ TypedArray<Material> get_materials();
+ void set_materials(TypedArray<Material> p_materials);
String get_scene_name();
void set_scene_name(String p_scene_name);
@@ -194,21 +189,6 @@ public:
Variant get_additional_data(const StringName &p_extension_name);
void set_additional_data(const StringName &p_extension_name, Variant p_additional_data);
-
- //void set_scene_nodes(RBMap<GLTFNodeIndex, Node *> p_scene_nodes) {
- // this->scene_nodes = p_scene_nodes;
- //}
-
- //void set_animation_players(Vector<AnimationPlayer *> p_animation_players) {
- // this->animation_players = p_animation_players;
- //}
-
- //RBMap<Ref<Material>, GLTFMaterialIndex> get_material_cache() {
- // return this->material_cache;
- //}
- //void set_material_cache(RBMap<Ref<Material>, GLTFMaterialIndex> p_material_cache) {
- // this->material_cache = p_material_cache;
- //}
};
#endif // GLTF_STATE_H
diff --git a/modules/gltf/register_types.cpp b/modules/gltf/register_types.cpp
index b9027f6e3d..2322e13ae2 100644
--- a/modules/gltf/register_types.cpp
+++ b/modules/gltf/register_types.cpp
@@ -30,24 +30,9 @@
#include "register_types.h"
-#ifndef _3D_DISABLED
-
-#include "extensions/gltf_light.h"
+#include "extensions/gltf_document_extension_convert_importer_mesh.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_state.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 "structures/gltf_texture_sampler.h"
#ifdef TOOLS_ENABLED
#include "core/config/project_settings.h"
@@ -95,20 +80,22 @@ static void _editor_init() {
EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING,
"filesystem/import/fbx/fbx2gltf_path", PROPERTY_HINT_GLOBAL_FILE));
if (fbx_enabled) {
- Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
- if (fbx2gltf_path.is_empty()) {
- WARN_PRINT("FBX file import is enabled in the project settings, but no FBX2glTF path is configured in the editor settings. FBX files will not be imported.");
- } else if (!da->file_exists(fbx2gltf_path)) {
- WARN_PRINT("FBX file import is enabled, but the FBX2glTF path doesn't point to an accessible file. FBX files will not be imported.");
- } else {
- Ref<EditorSceneFormatImporterFBX> importer;
- importer.instantiate();
- ResourceImporterScene::add_importer(importer);
- }
+ Ref<EditorSceneFormatImporterFBX> importer;
+ importer.instantiate();
+ ResourceImporterScene::get_scene_singleton()->add_importer(importer);
+
+ Ref<EditorFileSystemImportFormatSupportQueryFBX> fbx_import_query;
+ fbx_import_query.instantiate();
+ EditorFileSystem::get_singleton()->add_import_format_support_query(fbx_import_query);
}
}
#endif // TOOLS_ENABLED
+#define GLTF_REGISTER_DOCUMENT_EXTENSION(m_doc_ext_class) \
+ Ref<m_doc_ext_class> extension_##m_doc_ext_class; \
+ extension_##m_doc_ext_class.instantiate(); \
+ GLTFDocument::register_gltf_document_extension(extension_##m_doc_ext_class);
+
void initialize_gltf_module(ModuleInitializationLevel p_level) {
if (p_level == MODULE_INITIALIZATION_LEVEL_SCENE) {
// glTF API available at runtime.
@@ -128,6 +115,11 @@ void initialize_gltf_module(ModuleInitializationLevel p_level) {
GDREGISTER_CLASS(GLTFState);
GDREGISTER_CLASS(GLTFTexture);
GDREGISTER_CLASS(GLTFTextureSampler);
+ // Register GLTFDocumentExtension classes with GLTFDocument.
+ bool is_editor = ::Engine::get_singleton()->is_editor_hint();
+ if (!is_editor) {
+ GLTF_REGISTER_DOCUMENT_EXTENSION(GLTFDocumentExtensionConvertImporterMesh);
+ }
}
#ifdef TOOLS_ENABLED
@@ -161,6 +153,5 @@ void uninitialize_gltf_module(ModuleInitializationLevel p_level) {
if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) {
return;
}
+ GLTFDocument::unregister_all_gltf_document_extensions();
}
-
-#endif // _3D_DISABLED
diff --git a/modules/gltf/structures/gltf_accessor.h b/modules/gltf/structures/gltf_accessor.h
index bfb71d57fe..8e4bb2d3f9 100644
--- a/modules/gltf/structures/gltf_accessor.h
+++ b/modules/gltf/structures/gltf_accessor.h
@@ -31,9 +31,8 @@
#ifndef GLTF_ACCESSOR_H
#define GLTF_ACCESSOR_H
-#include "core/io/resource.h"
-
#include "../gltf_defines.h"
+#include "core/io/resource.h"
struct GLTFAccessor : public Resource {
GDCLASS(GLTFAccessor, Resource);
diff --git a/modules/gltf/structures/gltf_animation.h b/modules/gltf/structures/gltf_animation.h
index 3777f579f6..fc535631bb 100644
--- a/modules/gltf/structures/gltf_animation.h
+++ b/modules/gltf/structures/gltf_animation.h
@@ -31,7 +31,7 @@
#ifndef GLTF_ANIMATION_H
#define GLTF_ANIMATION_H
-#include "core/io/resource.h"
+#include "scene/animation/animation_player.h"
class GLTFAnimation : public Resource {
GDCLASS(GLTFAnimation, Resource);
diff --git a/modules/gltf/structures/gltf_buffer_view.cpp b/modules/gltf/structures/gltf_buffer_view.cpp
index ba19ed8628..a15141225b 100644
--- a/modules/gltf/structures/gltf_buffer_view.cpp
+++ b/modules/gltf/structures/gltf_buffer_view.cpp
@@ -30,8 +30,6 @@
#include "gltf_buffer_view.h"
-#include "../gltf_document_extension.h"
-
void GLTFBufferView::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_buffer"), &GLTFBufferView::get_buffer);
ClassDB::bind_method(D_METHOD("set_buffer", "buffer"), &GLTFBufferView::set_buffer);
diff --git a/modules/gltf/structures/gltf_camera.cpp b/modules/gltf/structures/gltf_camera.cpp
index 212b9b80c8..7a5ab2763c 100644
--- a/modules/gltf/structures/gltf_camera.cpp
+++ b/modules/gltf/structures/gltf_camera.cpp
@@ -30,6 +30,8 @@
#include "gltf_camera.h"
+#include "scene/3d/camera_3d.h"
+
void GLTFCamera::_bind_methods() {
ClassDB::bind_static_method("GLTFCamera", D_METHOD("from_node", "camera_node"), &GLTFCamera::from_node);
ClassDB::bind_method(D_METHOD("to_node"), &GLTFCamera::to_node);
diff --git a/modules/gltf/structures/gltf_camera.h b/modules/gltf/structures/gltf_camera.h
index 50ae10e17a..5e8a1da5f7 100644
--- a/modules/gltf/structures/gltf_camera.h
+++ b/modules/gltf/structures/gltf_camera.h
@@ -32,7 +32,8 @@
#define GLTF_CAMERA_H
#include "core/io/resource.h"
-#include "scene/3d/camera_3d.h"
+
+class Camera3D;
// Reference and test file:
// https://github.com/KhronosGroup/glTF-Tutorials/blob/master/gltfTutorial/gltfTutorial_015_SimpleCameras.md
@@ -64,7 +65,7 @@ public:
real_t get_depth_near() const { return depth_near; }
void set_depth_near(real_t p_val) { depth_near = p_val; }
- static Ref<GLTFCamera> from_node(const Camera3D *p_light);
+ static Ref<GLTFCamera> from_node(const Camera3D *p_camera);
Camera3D *to_node() const;
static Ref<GLTFCamera> from_dictionary(const Dictionary p_dictionary);
diff --git a/modules/gltf/structures/gltf_mesh.h b/modules/gltf/structures/gltf_mesh.h
index 2fa37fd727..92722ce75c 100644
--- a/modules/gltf/structures/gltf_mesh.h
+++ b/modules/gltf/structures/gltf_mesh.h
@@ -31,10 +31,8 @@
#ifndef GLTF_MESH_H
#define GLTF_MESH_H
-#include "core/io/resource.h"
-#include "scene/3d/importer_mesh_instance_3d.h"
+#include "../gltf_defines.h"
#include "scene/resources/importer_mesh.h"
-#include "scene/resources/mesh.h"
class GLTFMesh : public Resource {
GDCLASS(GLTFMesh, Resource);
diff --git a/modules/gltf/structures/gltf_texture_sampler.h b/modules/gltf/structures/gltf_texture_sampler.h
index 3fad31bbee..7bb7cd62e3 100644
--- a/modules/gltf/structures/gltf_texture_sampler.h
+++ b/modules/gltf/structures/gltf_texture_sampler.h
@@ -31,7 +31,6 @@
#ifndef GLTF_TEXTURE_SAMPLER_H
#define GLTF_TEXTURE_SAMPLER_H
-#include "core/io/resource.h"
#include "scene/resources/material.h"
class GLTFTextureSampler : public Resource {
diff --git a/modules/gridmap/doc_classes/GridMap.xml b/modules/gridmap/doc_classes/GridMap.xml
index 0f3662c3cf..e0fc4e2697 100644
--- a/modules/gridmap/doc_classes/GridMap.xml
+++ b/modules/gridmap/doc_classes/GridMap.xml
@@ -25,12 +25,14 @@
<method name="clear_baked_meshes">
<return type="void" />
<description>
+ Clears all baked meshes. See [method make_baked_meshes].
</description>
</method>
<method name="get_bake_mesh_instance">
<return type="RID" />
<param index="0" name="idx" type="int" />
<description>
+ Returns [RID] of a baked mesh with the given [param idx].
</description>
</method>
<method name="get_bake_meshes">
@@ -87,13 +89,6 @@
Returns an array of [Transform3D] and [Mesh] references corresponding to the non-empty cells in the grid. The transforms are specified in local space.
</description>
</method>
- <method name="get_navigation_layer_value" qualifiers="const">
- <return type="bool" />
- <param index="0" name="layer_number" type="int" />
- <description>
- Returns whether or not the specified layer of the [member navigation_layers] bitmask is enabled, given a [code]layer_number[/code] between 1 and 32.
- </description>
- </method>
<method name="get_navigation_map" qualifiers="const">
<return type="RID" />
<description>
@@ -133,6 +128,7 @@
<param index="0" name="gen_lightmap_uv" type="bool" default="false" />
<param index="1" name="lightmap_uv_texel_size" type="float" default="0.1" />
<description>
+ Bakes lightmap data for all meshes in the assigned [MeshLibrary].
</description>
</method>
<method name="map_to_local" qualifiers="const">
@@ -146,6 +142,7 @@
<return type="void" />
<param index="0" name="resource" type="Resource" />
<description>
+ Notifies the [GridMap] about changed resource and recreates octant data.
</description>
</method>
<method name="set_cell_item">
@@ -175,14 +172,6 @@
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>
- <method name="set_navigation_layer_value">
- <return type="void" />
- <param index="0" name="layer_number" type="int" />
- <param index="1" name="value" type="bool" />
- <description>
- Based on [code]value[/code], enables or disables the specified layer in the [member navigation_layers] bitmask, given a [code]layer_number[/code] between 1 and 32.
- </description>
- </method>
<method name="set_navigation_map">
<return type="void" />
<param index="0" name="navigation_map" type="RID" />
@@ -193,7 +182,7 @@
</methods>
<members>
<member name="bake_navigation" type="bool" setter="set_bake_navigation" getter="is_baking_navigation" default="false">
- If [code]true[/code], this GridMap bakes a navigation region.
+ If [code]true[/code], this GridMap creates a navigation region for each cell that uses a [member mesh_library] item with a navigation mesh. The created navigation region will use the navigation layers bitmask assigned to the [MeshLibrary]'s item.
</member>
<member name="cell_center_x" type="bool" setter="set_center_x" getter="get_center_x" default="true">
If [code]true[/code], grid items are centered on the X axis.
@@ -222,12 +211,12 @@
<member name="collision_mask" type="int" setter="set_collision_mask" getter="get_collision_mask" default="1">
The physics layers this GridMap detects collisions in. 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_priority" type="float" setter="set_collision_priority" getter="get_collision_priority" default="1.0">
+ The priority used to solve colliding when occurring penetration. The higher the priority is, the lower the penetration into the object will be. This can for example be used to prevent the player from breaking through the boundaries of a level.
+ </member>
<member name="mesh_library" type="MeshLibrary" setter="set_mesh_library" getter="get_mesh_library">
The assigned [MeshLibrary].
</member>
- <member name="navigation_layers" type="int" setter="set_navigation_layers" getter="get_navigation_layers" default="1">
- A bitmask determining all navigation layers the GridMap generated navigation regions belong to. These navigation layers can be checked upon when requesting a path with [method NavigationServer3D.map_get_path].
- </member>
<member name="physics_material" type="PhysicsMaterial" setter="set_physics_material" getter="get_physics_material">
Overrides the default friction and bounce physics properties for the whole [GridMap].
</member>
diff --git a/modules/gridmap/editor/grid_map_editor_plugin.cpp b/modules/gridmap/editor/grid_map_editor_plugin.cpp
index 9c6cbebf0e..89ef9ddd90 100644
--- a/modules/gridmap/editor/grid_map_editor_plugin.cpp
+++ b/modules/gridmap/editor/grid_map_editor_plugin.cpp
@@ -40,6 +40,8 @@
#include "editor/editor_undo_redo_manager.h"
#include "editor/plugins/node_3d_editor_plugin.h"
#include "scene/3d/camera_3d.h"
+#include "scene/gui/menu_button.h"
+#include "scene/gui/separator.h"
#include "scene/main/window.h"
void GridMapEditor::_node_removed(Node *p_node) {
@@ -459,6 +461,7 @@ void GridMapEditor::_delete_selection() {
return;
}
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("GridMap Delete Selection"));
for (int i = selection.begin.x; i <= selection.end.x; i++) {
for (int j = selection.begin.y; j <= selection.end.y; j++) {
@@ -479,6 +482,7 @@ void GridMapEditor::_fill_selection() {
return;
}
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("GridMap Fill Selection"));
for (int i = selection.begin.x; i <= selection.end.x; i++) {
for (int j = selection.begin.y; j <= selection.end.y; j++) {
@@ -572,6 +576,7 @@ void GridMapEditor::_do_paste() {
rot = node->get_basis_with_orthogonal_index(paste_indicator.orientation);
Vector3 ofs = paste_indicator.current - paste_indicator.click;
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("GridMap Paste Selection"));
for (const ClipboardItem &item : clipboard_items) {
@@ -659,6 +664,7 @@ EditorPlugin::AfterGUIInput GridMapEditor::forward_spatial_input_event(Camera3D
} else {
if ((mb->get_button_index() == MouseButton::RIGHT && input_action == INPUT_ERASE) || (mb->get_button_index() == MouseButton::LEFT && input_action == INPUT_PAINT)) {
if (set_items.size()) {
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("GridMap Paint"));
for (const SetItem &si : set_items) {
undo_redo->add_do_method(node, "set_cell_item", si.position, si.new_value, si.new_orientation);
@@ -680,6 +686,7 @@ EditorPlugin::AfterGUIInput GridMapEditor::forward_spatial_input_event(Camera3D
}
if (mb->get_button_index() == MouseButton::LEFT && input_action == INPUT_SELECT) {
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("GridMap Selection"));
undo_redo->add_do_method(this, "_set_selection", selection.active, selection.begin, selection.end);
undo_redo->add_undo_method(this, "_set_selection", last_selection.active, last_selection.begin, last_selection.end);
@@ -1142,8 +1149,6 @@ void GridMapEditor::_bind_methods() {
}
GridMapEditor::GridMapEditor() {
- undo_redo = EditorNode::get_singleton()->get_undo_redo();
-
int mw = EDITOR_DEF("editors/grid_map/palette_min_width", 230);
Control *ec = memnew(Control);
ec->set_custom_minimum_size(Size2(mw, 0) * EDSCALE);
diff --git a/modules/gridmap/editor/grid_map_editor_plugin.h b/modules/gridmap/editor/grid_map_editor_plugin.h
index 6fd38d9445..1cf2e4cb89 100644
--- a/modules/gridmap/editor/grid_map_editor_plugin.h
+++ b/modules/gridmap/editor/grid_map_editor_plugin.h
@@ -35,11 +35,13 @@
#include "../grid_map.h"
#include "editor/editor_plugin.h"
+#include "scene/gui/box_container.h"
#include "scene/gui/item_list.h"
#include "scene/gui/slider.h"
#include "scene/gui/spin_box.h"
-class EditorUndoRedoManager;
+class ConfirmationDialog;
+class MenuButton;
class Node3DEditorPlugin;
class GridMapEditor : public VBoxContainer {
@@ -63,7 +65,6 @@ class GridMapEditor : public VBoxContainer {
DISPLAY_LIST
};
- Ref<EditorUndoRedoManager> undo_redo;
InputAction input_action = INPUT_NONE;
Panel *panel = nullptr;
MenuButton *options = nullptr;
diff --git a/modules/gridmap/grid_map.cpp b/modules/gridmap/grid_map.cpp
index de50e9ea1e..e396d77d86 100644
--- a/modules/gridmap/grid_map.cpp
+++ b/modules/gridmap/grid_map.cpp
@@ -74,7 +74,7 @@ bool GridMap::_set(const StringName &p_name, const Variant &p_value) {
bm.mesh = meshes[i];
ERR_CONTINUE(!bm.mesh.is_valid());
bm.instance = RS::get_singleton()->instance_create();
- RS::get_singleton()->get_singleton()->instance_set_base(bm.instance, bm.mesh->get_rid());
+ RS::get_singleton()->instance_set_base(bm.instance, bm.mesh->get_rid());
RS::get_singleton()->instance_attach_object_instance_id(bm.instance, get_instance_id());
if (is_inside_tree()) {
RS::get_singleton()->instance_set_scenario(bm.instance, get_world_3d()->get_scenario());
@@ -138,7 +138,7 @@ void GridMap::_get_property_list(List<PropertyInfo> *p_list) const {
void GridMap::set_collision_layer(uint32_t p_layer) {
collision_layer = p_layer;
- _reset_physic_bodies_collision_filters();
+ _update_physics_bodies_collision_properties();
}
uint32_t GridMap::get_collision_layer() const {
@@ -147,7 +147,7 @@ uint32_t GridMap::get_collision_layer() const {
void GridMap::set_collision_mask(uint32_t p_mask) {
collision_mask = p_mask;
- _reset_physic_bodies_collision_filters();
+ _update_physics_bodies_collision_properties();
}
uint32_t GridMap::get_collision_mask() const {
@@ -184,6 +184,15 @@ void GridMap::set_collision_mask_value(int p_layer_number, bool p_value) {
set_collision_mask(mask);
}
+void GridMap::set_collision_priority(real_t p_priority) {
+ collision_priority = p_priority;
+ _update_physics_bodies_collision_properties();
+}
+
+real_t GridMap::get_collision_priority() const {
+ return collision_priority;
+}
+
void GridMap::set_physics_material(Ref<PhysicsMaterial> p_material) {
physics_material = p_material;
_recreate_octant_data();
@@ -230,7 +239,7 @@ void GridMap::set_navigation_map(RID p_navigation_map) {
map_override = p_navigation_map;
for (const KeyValue<OctantKey, Octant *> &E : octant_map) {
Octant &g = *octant_map[E.key];
- for (KeyValue<IndexKey, Octant::NavMesh> &F : g.navmesh_ids) {
+ for (KeyValue<IndexKey, Octant::NavigationCell> &F : g.navigation_cell_ids) {
if (F.value.region.is_valid()) {
NavigationServer3D::get_singleton()->region_set_map(F.value.region, map_override);
}
@@ -247,33 +256,6 @@ RID GridMap::get_navigation_map() const {
return RID();
}
-void GridMap::set_navigation_layers(uint32_t p_navigation_layers) {
- navigation_layers = p_navigation_layers;
- _recreate_octant_data();
-}
-
-uint32_t GridMap::get_navigation_layers() const {
- return navigation_layers;
-}
-
-void GridMap::set_navigation_layer_value(int p_layer_number, bool p_value) {
- ERR_FAIL_COND_MSG(p_layer_number < 1, "Navigation layer number must be between 1 and 32 inclusive.");
- ERR_FAIL_COND_MSG(p_layer_number > 32, "Navigation layer number must be between 1 and 32 inclusive.");
- uint32_t _navigation_layers = get_navigation_layers();
- if (p_value) {
- _navigation_layers |= 1 << (p_layer_number - 1);
- } else {
- _navigation_layers &= ~(1 << (p_layer_number - 1));
- }
- set_navigation_layers(_navigation_layers);
-}
-
-bool GridMap::get_navigation_layer_value(int p_layer_number) const {
- ERR_FAIL_COND_V_MSG(p_layer_number < 1, false, "Navigation layer number must be between 1 and 32 inclusive.");
- ERR_FAIL_COND_V_MSG(p_layer_number > 32, false, "Navigation layer number must be between 1 and 32 inclusive.");
- return get_navigation_layers() & (1 << (p_layer_number - 1));
-}
-
void GridMap::set_mesh_library(const Ref<MeshLibrary> &p_mesh_library) {
if (!mesh_library.is_null()) {
mesh_library->unregister_owner(this);
@@ -385,6 +367,7 @@ void GridMap::set_cell_item(const Vector3i &p_position, int p_item, int p_rot) {
PhysicsServer3D::get_singleton()->body_attach_object_instance_id(g->static_body, get_instance_id());
PhysicsServer3D::get_singleton()->body_set_collision_layer(g->static_body, collision_layer);
PhysicsServer3D::get_singleton()->body_set_collision_mask(g->static_body, collision_mask);
+ PhysicsServer3D::get_singleton()->body_set_collision_priority(g->static_body, collision_priority);
if (physics_material.is_valid()) {
PhysicsServer3D::get_singleton()->body_set_param(g->static_body, PhysicsServer3D::BODY_PARAM_FRICTION, physics_material->get_friction());
PhysicsServer3D::get_singleton()->body_set_param(g->static_body, PhysicsServer3D::BODY_PARAM_BOUNCE, physics_material->get_bounce());
@@ -542,13 +525,13 @@ void GridMap::_octant_transform(const OctantKey &p_key) {
}
// update transform for NavigationServer regions and navigation debugmesh instances
- for (const KeyValue<IndexKey, Octant::NavMesh> &E : g.navmesh_ids) {
+ for (const KeyValue<IndexKey, Octant::NavigationCell> &E : g.navigation_cell_ids) {
if (bake_navigation) {
if (E.value.region.is_valid()) {
NavigationServer3D::get_singleton()->region_set_transform(E.value.region, get_global_transform() * E.value.xform);
}
- if (E.value.navmesh_debug_instance.is_valid()) {
- RS::get_singleton()->instance_set_transform(E.value.navmesh_debug_instance, get_global_transform() * E.value.xform);
+ if (E.value.navigation_mesh_debug_instance.is_valid()) {
+ RS::get_singleton()->instance_set_transform(E.value.navigation_mesh_debug_instance, get_global_transform() * E.value.xform);
}
}
}
@@ -574,13 +557,13 @@ bool GridMap::_octant_update(const OctantKey &p_key) {
}
//erase navigation
- for (const KeyValue<IndexKey, Octant::NavMesh> &E : g.navmesh_ids) {
+ for (const KeyValue<IndexKey, Octant::NavigationCell> &E : g.navigation_cell_ids) {
NavigationServer3D::get_singleton()->free(E.value.region);
- if (E.value.navmesh_debug_instance.is_valid()) {
- RS::get_singleton()->free(E.value.navmesh_debug_instance);
+ if (E.value.navigation_mesh_debug_instance.is_valid()) {
+ RS::get_singleton()->free(E.value.navigation_mesh_debug_instance);
}
}
- g.navmesh_ids.clear();
+ g.navigation_cell_ids.clear();
//erase multimeshes
@@ -648,16 +631,18 @@ bool GridMap::_octant_update(const OctantKey &p_key) {
}
}
- // add the item's navmesh at given xform to GridMap's Navigation ancestor
- Ref<NavigationMesh> navmesh = mesh_library->get_item_navmesh(c.item);
- if (navmesh.is_valid()) {
- Octant::NavMesh nm;
- nm.xform = xform * mesh_library->get_item_navmesh_transform(c.item);
+ // add the item's navigation_mesh at given xform to GridMap's Navigation ancestor
+ Ref<NavigationMesh> navigation_mesh = mesh_library->get_item_navigation_mesh(c.item);
+ if (navigation_mesh.is_valid()) {
+ Octant::NavigationCell nm;
+ nm.xform = xform * mesh_library->get_item_navigation_mesh_transform(c.item);
+ nm.navigation_layers = mesh_library->get_item_navigation_layers(c.item);
if (bake_navigation) {
RID region = NavigationServer3D::get_singleton()->region_create();
- NavigationServer3D::get_singleton()->region_set_navigation_layers(region, navigation_layers);
- NavigationServer3D::get_singleton()->region_set_navmesh(region, navmesh);
+ NavigationServer3D::get_singleton()->region_set_owner_id(region, get_instance_id());
+ NavigationServer3D::get_singleton()->region_set_navigation_layers(region, nm.navigation_layers);
+ NavigationServer3D::get_singleton()->region_set_navigation_mesh(region, navigation_mesh);
NavigationServer3D::get_singleton()->region_set_transform(region, get_global_transform() * nm.xform);
if (is_inside_tree()) {
if (map_override.is_valid()) {
@@ -672,19 +657,19 @@ bool GridMap::_octant_update(const OctantKey &p_key) {
// add navigation debugmesh visual instances if debug is enabled
SceneTree *st = SceneTree::get_singleton();
if (st && st->is_debugging_navigation_hint()) {
- if (!nm.navmesh_debug_instance.is_valid()) {
- RID navmesh_debug_rid = navmesh->get_debug_mesh()->get_rid();
- nm.navmesh_debug_instance = RS::get_singleton()->instance_create();
- RS::get_singleton()->instance_set_base(nm.navmesh_debug_instance, navmesh_debug_rid);
+ if (!nm.navigation_mesh_debug_instance.is_valid()) {
+ RID navigation_mesh_debug_rid = navigation_mesh->get_debug_mesh()->get_rid();
+ nm.navigation_mesh_debug_instance = RS::get_singleton()->instance_create();
+ RS::get_singleton()->instance_set_base(nm.navigation_mesh_debug_instance, navigation_mesh_debug_rid);
}
if (is_inside_tree()) {
- RS::get_singleton()->instance_set_scenario(nm.navmesh_debug_instance, get_world_3d()->get_scenario());
- RS::get_singleton()->instance_set_transform(nm.navmesh_debug_instance, get_global_transform() * nm.xform);
+ RS::get_singleton()->instance_set_scenario(nm.navigation_mesh_debug_instance, get_world_3d()->get_scenario());
+ RS::get_singleton()->instance_set_transform(nm.navigation_mesh_debug_instance, get_global_transform() * nm.xform);
}
}
#endif // DEBUG_ENABLED
}
- g.navmesh_ids[E] = nm;
+ g.navigation_cell_ids[E] = nm;
}
}
@@ -750,10 +735,11 @@ bool GridMap::_octant_update(const OctantKey &p_key) {
return false;
}
-void GridMap::_reset_physic_bodies_collision_filters() {
+void GridMap::_update_physics_bodies_collision_properties() {
for (const KeyValue<OctantKey, Octant *> &E : octant_map) {
PhysicsServer3D::get_singleton()->body_set_collision_layer(E.value->static_body, collision_layer);
PhysicsServer3D::get_singleton()->body_set_collision_mask(E.value->static_body, collision_mask);
+ PhysicsServer3D::get_singleton()->body_set_collision_priority(E.value->static_body, collision_priority);
}
}
@@ -774,13 +760,14 @@ void GridMap::_octant_enter_world(const OctantKey &p_key) {
}
if (bake_navigation && mesh_library.is_valid()) {
- for (KeyValue<IndexKey, Octant::NavMesh> &F : g.navmesh_ids) {
+ for (KeyValue<IndexKey, Octant::NavigationCell> &F : g.navigation_cell_ids) {
if (cell_map.has(F.key) && F.value.region.is_valid() == false) {
- Ref<NavigationMesh> nm = mesh_library->get_item_navmesh(cell_map[F.key].item);
- if (nm.is_valid()) {
+ Ref<NavigationMesh> navigation_mesh = mesh_library->get_item_navigation_mesh(cell_map[F.key].item);
+ if (navigation_mesh.is_valid()) {
RID region = NavigationServer3D::get_singleton()->region_create();
- NavigationServer3D::get_singleton()->region_set_navigation_layers(region, navigation_layers);
- NavigationServer3D::get_singleton()->region_set_navmesh(region, nm);
+ NavigationServer3D::get_singleton()->region_set_owner_id(region, get_instance_id());
+ NavigationServer3D::get_singleton()->region_set_navigation_layers(region, F.value.navigation_layers);
+ NavigationServer3D::get_singleton()->region_set_navigation_mesh(region, navigation_mesh);
NavigationServer3D::get_singleton()->region_set_transform(region, get_global_transform() * F.value.xform);
if (map_override.is_valid()) {
NavigationServer3D::get_singleton()->region_set_map(region, map_override);
@@ -822,14 +809,14 @@ void GridMap::_octant_exit_world(const OctantKey &p_key) {
RS::get_singleton()->instance_set_scenario(g.multimesh_instances[i].instance, RID());
}
- for (KeyValue<IndexKey, Octant::NavMesh> &F : g.navmesh_ids) {
+ for (KeyValue<IndexKey, Octant::NavigationCell> &F : g.navigation_cell_ids) {
if (F.value.region.is_valid()) {
NavigationServer3D::get_singleton()->free(F.value.region);
F.value.region = RID();
}
- if (F.value.navmesh_debug_instance.is_valid()) {
- RS::get_singleton()->free(F.value.navmesh_debug_instance);
- F.value.navmesh_debug_instance = RID();
+ if (F.value.navigation_mesh_debug_instance.is_valid()) {
+ RS::get_singleton()->free(F.value.navigation_mesh_debug_instance);
+ F.value.navigation_mesh_debug_instance = RID();
}
}
@@ -860,15 +847,15 @@ void GridMap::_octant_clean_up(const OctantKey &p_key) {
PhysicsServer3D::get_singleton()->free(g.static_body);
// Erase navigation
- for (const KeyValue<IndexKey, Octant::NavMesh> &E : g.navmesh_ids) {
+ for (const KeyValue<IndexKey, Octant::NavigationCell> &E : g.navigation_cell_ids) {
if (E.value.region.is_valid()) {
NavigationServer3D::get_singleton()->free(E.value.region);
}
- if (E.value.navmesh_debug_instance.is_valid()) {
- RS::get_singleton()->free(E.value.navmesh_debug_instance);
+ if (E.value.navigation_mesh_debug_instance.is_valid()) {
+ RS::get_singleton()->free(E.value.navigation_mesh_debug_instance);
}
}
- g.navmesh_ids.clear();
+ g.navigation_cell_ids.clear();
#ifdef DEBUG_ENABLED
if (bake_navigation) {
@@ -1045,6 +1032,9 @@ void GridMap::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_collision_layer_value", "layer_number", "value"), &GridMap::set_collision_layer_value);
ClassDB::bind_method(D_METHOD("get_collision_layer_value", "layer_number"), &GridMap::get_collision_layer_value);
+ ClassDB::bind_method(D_METHOD("set_collision_priority", "priority"), &GridMap::set_collision_priority);
+ ClassDB::bind_method(D_METHOD("get_collision_priority"), &GridMap::get_collision_priority);
+
ClassDB::bind_method(D_METHOD("set_physics_material", "material"), &GridMap::set_physics_material);
ClassDB::bind_method(D_METHOD("get_physics_material"), &GridMap::get_physics_material);
@@ -1054,12 +1044,6 @@ void GridMap::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_navigation_map", "navigation_map"), &GridMap::set_navigation_map);
ClassDB::bind_method(D_METHOD("get_navigation_map"), &GridMap::get_navigation_map);
- ClassDB::bind_method(D_METHOD("set_navigation_layers", "layers"), &GridMap::set_navigation_layers);
- ClassDB::bind_method(D_METHOD("get_navigation_layers"), &GridMap::get_navigation_layers);
-
- ClassDB::bind_method(D_METHOD("set_navigation_layer_value", "layer_number", "value"), &GridMap::set_navigation_layer_value);
- ClassDB::bind_method(D_METHOD("get_navigation_layer_value", "layer_number"), &GridMap::get_navigation_layer_value);
-
ClassDB::bind_method(D_METHOD("set_mesh_library", "mesh_library"), &GridMap::set_mesh_library);
ClassDB::bind_method(D_METHOD("get_mesh_library"), &GridMap::get_mesh_library);
@@ -1116,9 +1100,9 @@ void GridMap::_bind_methods() {
ADD_GROUP("Collision", "collision_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_layer", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_layer", "get_collision_layer");
ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_mask", "get_collision_mask");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "collision_priority"), "set_collision_priority", "get_collision_priority");
ADD_GROUP("Navigation", "");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "bake_navigation"), "set_bake_navigation", "is_baking_navigation");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "navigation_layers", PROPERTY_HINT_LAYERS_3D_NAVIGATION), "set_navigation_layers", "get_navigation_layers");
BIND_CONSTANT(INVALID_CELL_ITEM);
@@ -1279,7 +1263,7 @@ void GridMap::make_baked_meshes(bool p_gen_lightmap_uv, float p_lightmap_uv_texe
BakedMesh bm;
bm.mesh = mesh;
bm.instance = RS::get_singleton()->instance_create();
- RS::get_singleton()->get_singleton()->instance_set_base(bm.instance, bm.mesh->get_rid());
+ RS::get_singleton()->instance_set_base(bm.instance, bm.mesh->get_rid());
RS::get_singleton()->instance_attach_object_instance_id(bm.instance, get_instance_id());
if (is_inside_tree()) {
RS::get_singleton()->instance_set_scenario(bm.instance, get_world_3d()->get_scenario());
@@ -1388,7 +1372,7 @@ void GridMap::_update_octant_navigation_debug_edge_connections_mesh(const Octant
Vector<Vector3> vertex_array;
- for (KeyValue<IndexKey, Octant::NavMesh> &F : g.navmesh_ids) {
+ for (KeyValue<IndexKey, Octant::NavigationCell> &F : g.navigation_cell_ids) {
if (cell_map.has(F.key) && F.value.region.is_valid()) {
int connections_count = NavigationServer3D::get_singleton()->region_get_connections_count(F.value.region);
if (connections_count == 0) {
diff --git a/modules/gridmap/grid_map.h b/modules/gridmap/grid_map.h
index 6a53457d25..2a9f34bdda 100644
--- a/modules/gridmap/grid_map.h
+++ b/modules/gridmap/grid_map.h
@@ -95,10 +95,11 @@ class GridMap : public Node3D {
* A GridMap can have multiple Octants.
*/
struct Octant {
- struct NavMesh {
+ struct NavigationCell {
RID region;
Transform3D xform;
- RID navmesh_debug_instance;
+ RID navigation_mesh_debug_instance;
+ uint32_t navigation_layers = 1;
};
struct MultimeshInstance {
@@ -124,7 +125,7 @@ class GridMap : public Node3D {
bool dirty = false;
RID static_body;
- HashMap<IndexKey, NavMesh> navmesh_ids;
+ HashMap<IndexKey, NavigationCell> navigation_cell_ids;
};
union OctantKey {
@@ -150,6 +151,7 @@ class GridMap : public Node3D {
uint32_t collision_layer = 1;
uint32_t collision_mask = 1;
+ real_t collision_priority = 1.0;
Ref<PhysicsMaterial> physics_material;
bool bake_navigation = false;
RID map_override;
@@ -185,7 +187,7 @@ class GridMap : public Node3D {
return Vector3(p_key.x, p_key.y, p_key.z) * cell_size * octant_size;
}
- void _reset_physic_bodies_collision_filters();
+ void _update_physics_bodies_collision_properties();
void _octant_enter_world(const OctantKey &p_key);
void _octant_exit_world(const OctantKey &p_key);
bool _octant_update(const OctantKey &p_key);
@@ -240,6 +242,9 @@ public:
void set_collision_mask_value(int p_layer_number, bool p_value);
bool get_collision_mask_value(int p_layer_number) const;
+ void set_collision_priority(real_t p_priority);
+ real_t get_collision_priority() const;
+
void set_physics_material(Ref<PhysicsMaterial> p_material);
Ref<PhysicsMaterial> get_physics_material() const;
@@ -251,12 +256,6 @@ public:
void set_navigation_map(RID p_navigation_map);
RID get_navigation_map() const;
- void set_navigation_layers(uint32_t p_navigation_layers);
- uint32_t get_navigation_layers() const;
-
- void set_navigation_layer_value(int p_layer_number, bool p_value);
- bool get_navigation_layer_value(int p_layer_number) const;
-
void set_mesh_library(const Ref<MeshLibrary> &p_mesh_library);
Ref<MeshLibrary> get_mesh_library() const;
diff --git a/modules/lightmapper_rd/register_types.cpp b/modules/lightmapper_rd/register_types.cpp
index 0e0330c1a1..ed223e1faa 100644
--- a/modules/lightmapper_rd/register_types.cpp
+++ b/modules/lightmapper_rd/register_types.cpp
@@ -57,6 +57,7 @@ void initialize_lightmapper_rd_module(ModuleInitializationLevel p_level) {
GLOBAL_DEF("rendering/lightmapping/bake_quality/high_quality_probe_ray_count", 512);
GLOBAL_DEF("rendering/lightmapping/bake_quality/ultra_quality_probe_ray_count", 2048);
GLOBAL_DEF("rendering/lightmapping/bake_performance/max_rays_per_probe_pass", 64);
+ GLOBAL_DEF("rendering/lightmapping/primitive_meshes/texel_size", 0.2);
#ifndef _3D_DISABLED
GDREGISTER_CLASS(LightmapperRD);
Lightmapper::create_gpu = create_lightmapper_rd;
diff --git a/modules/mbedtls/packet_peer_mbed_dtls.cpp b/modules/mbedtls/packet_peer_mbed_dtls.cpp
index e84d95773d..e658668355 100644
--- a/modules/mbedtls/packet_peer_mbed_dtls.cpp
+++ b/modules/mbedtls/packet_peer_mbed_dtls.cpp
@@ -118,7 +118,6 @@ Error PacketPeerMbedDTLS::connect_to_peer(Ref<PacketPeerUDP> p_base, bool p_vali
ERR_FAIL_COND_V(!p_base.is_valid() || !p_base->is_socket_connected(), ERR_INVALID_PARAMETER);
base = p_base;
- int ret = 0;
int authmode = p_validate_certs ? MBEDTLS_SSL_VERIFY_REQUIRED : MBEDTLS_SSL_VERIFY_NONE;
Error err = tls_ctx->init_client(MBEDTLS_SSL_TRANSPORT_DATAGRAM, authmode, p_ca_certs);
@@ -130,7 +129,7 @@ Error PacketPeerMbedDTLS::connect_to_peer(Ref<PacketPeerUDP> p_base, bool p_vali
status = STATUS_HANDSHAKING;
- if ((ret = _do_handshake()) != OK) {
+ if (_do_handshake() != OK) {
status = STATUS_ERROR_HOSTNAME_MISMATCH;
return FAILED;
}
@@ -158,7 +157,7 @@ Error PacketPeerMbedDTLS::accept_peer(Ref<PacketPeerUDP> p_base, Ref<CryptoKey>
status = STATUS_HANDSHAKING;
- if ((ret = _do_handshake()) != OK) {
+ if (_do_handshake() != OK) {
status = STATUS_ERROR;
return FAILED;
}
@@ -175,7 +174,7 @@ Error PacketPeerMbedDTLS::put_packet(const uint8_t *p_buffer, int p_bytes) {
int ret = mbedtls_ssl_write(tls_ctx->get_context(), p_buffer, p_bytes);
if (ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE) {
- ret = 0; // non blocking io
+ // Non blocking io.
} else if (ret <= 0) {
TLSContextMbedTLS::print_mbedtls_error(ret);
_cleanup();
diff --git a/modules/mono/README.md b/modules/mono/README.md
index 366777cfc1..74b4531dfb 100644
--- a/modules/mono/README.md
+++ b/modules/mono/README.md
@@ -46,10 +46,10 @@ C# solutions during development to avoid mistakes.
# Double Precision Support (REAL_T_IS_DOUBLE)
-Follow the above instructions but build Godot with the float=64 argument to scons
+Follow the above instructions but build Godot with the precision=double argument to scons
-When building the NuGet packages, specify `--float=64` - for example:
+When building the NuGet packages, specify `--precision=double` - for example:
```sh
./modules/mono/build_scripts/build_assemblies.py --godot-output-dir ./bin \
- --push-nupkgs-local ~/MyLocalNugetSource --float=64
+ --push-nupkgs-local ~/MyLocalNugetSource --precision=double
```
diff --git a/modules/mono/build_scripts/build_assemblies.py b/modules/mono/build_scripts/build_assemblies.py
index 7343af0b39..0b91cda9b8 100755
--- a/modules/mono/build_scripts/build_assemblies.py
+++ b/modules/mono/build_scripts/build_assemblies.py
@@ -193,7 +193,7 @@ def run_msbuild(tools: ToolsLocation, sln: str, msbuild_args: Optional[List[str]
return subprocess.call(args, env=msbuild_env)
-def build_godot_api(msbuild_tool, module_dir, output_dir, push_nupkgs_local, float_size):
+def build_godot_api(msbuild_tool, module_dir, output_dir, push_nupkgs_local, precision):
target_filenames = [
"GodotSharp.dll",
"GodotSharp.pdb",
@@ -214,7 +214,7 @@ def build_godot_api(msbuild_tool, module_dir, output_dir, push_nupkgs_local, flo
args = ["/restore", "/t:Build", "/p:Configuration=" + build_config, "/p:NoWarn=1591"]
if push_nupkgs_local:
args += ["/p:ClearNuGetLocalCache=true", "/p:PushNuGetToLocalSource=" + push_nupkgs_local]
- if float_size == "64":
+ if precision == "double":
args += ["/p:GodotFloat64=true"]
sln = os.path.join(module_dir, "glue/GodotSharp/GodotSharp.sln")
@@ -303,12 +303,12 @@ def generate_sdk_package_versions():
f.close()
-def build_all(msbuild_tool, module_dir, output_dir, godot_platform, dev_debug, push_nupkgs_local, float_size):
+def build_all(msbuild_tool, module_dir, output_dir, godot_platform, dev_debug, push_nupkgs_local, precision):
# Generate SdkPackageVersions.props
generate_sdk_package_versions()
# Godot API
- exit_code = build_godot_api(msbuild_tool, module_dir, output_dir, push_nupkgs_local, float_size)
+ exit_code = build_godot_api(msbuild_tool, module_dir, output_dir, push_nupkgs_local, precision)
if exit_code != 0:
return exit_code
@@ -319,7 +319,7 @@ def build_all(msbuild_tool, module_dir, output_dir, godot_platform, dev_debug, p
)
if push_nupkgs_local:
args += ["/p:ClearNuGetLocalCache=true", "/p:PushNuGetToLocalSource=" + push_nupkgs_local]
- if float_size == "64":
+ if precision == "double":
args += ["/p:GodotFloat64=true"]
exit_code = run_msbuild(msbuild_tool, sln=sln, msbuild_args=args)
if exit_code != 0:
@@ -329,7 +329,7 @@ def build_all(msbuild_tool, module_dir, output_dir, godot_platform, dev_debug, p
args = ["/restore", "/t:Build", "/p:Configuration=Release"]
if push_nupkgs_local:
args += ["/p:ClearNuGetLocalCache=true", "/p:PushNuGetToLocalSource=" + push_nupkgs_local]
- if float_size == "64":
+ if precision == "double":
args += ["/p:GodotFloat64=true"]
sln = os.path.join(module_dir, "editor/Godot.NET.Sdk/Godot.NET.Sdk.sln")
exit_code = run_msbuild(msbuild_tool, sln=sln, msbuild_args=args)
@@ -354,7 +354,9 @@ def main():
parser.add_argument("--godot-platform", type=str, default="")
parser.add_argument("--mono-prefix", type=str, default="")
parser.add_argument("--push-nupkgs-local", type=str, default="")
- parser.add_argument("--float", type=str, default="32", choices=["32", "64"], help="Floating-point precision")
+ parser.add_argument(
+ "--precision", type=str, default="single", choices=["single", "double"], help="Floating-point precision level"
+ )
args = parser.parse_args()
@@ -378,7 +380,7 @@ def main():
args.godot_platform,
args.dev_debug,
push_nupkgs_local,
- args.float,
+ args.precision,
)
sys.exit(exit_code)
diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp
index 345d2e4694..26739bcdea 100644
--- a/modules/mono/csharp_script.cpp
+++ b/modules/mono/csharp_script.cpp
@@ -46,6 +46,7 @@
#include "editor/editor_internal_calls.h"
#include "editor/editor_node.h"
#include "editor/editor_settings.h"
+#include "editor/inspector_dock.h"
#include "editor/node_dock.h"
#include "editor/script_templates/templates.gen.h"
#endif
@@ -72,7 +73,7 @@ static bool _create_project_solution_if_needed() {
CSharpLanguage *CSharpLanguage::singleton = nullptr;
-GDNativeInstanceBindingCallbacks CSharpLanguage::_instance_binding_callbacks = {
+GDExtensionInstanceBindingCallbacks CSharpLanguage::_instance_binding_callbacks = {
&_instance_binding_create_callback,
&_instance_binding_free_callback,
&_instance_binding_reference_callback
@@ -390,10 +391,10 @@ bool CSharpLanguage::supports_builtin_mode() const {
#ifdef TOOLS_ENABLED
static String variant_type_to_managed_name(const String &p_var_type_name) {
if (p_var_type_name.is_empty()) {
- return "object";
+ return "Variant";
}
- if (!ClassDB::class_exists(p_var_type_name)) {
+ if (ClassDB::class_exists(p_var_type_name)) {
return p_var_type_name;
}
@@ -401,12 +402,12 @@ static String variant_type_to_managed_name(const String &p_var_type_name) {
return "Godot.Object";
}
+ if (p_var_type_name == Variant::get_type_name(Variant::INT)) {
+ return "long";
+ }
+
if (p_var_type_name == Variant::get_type_name(Variant::FLOAT)) {
-#ifdef REAL_T_IS_DOUBLE
return "double";
-#else
- return "float";
-#endif
}
if (p_var_type_name == Variant::get_type_name(Variant::STRING)) {
@@ -450,7 +451,7 @@ static String variant_type_to_managed_name(const String &p_var_type_name) {
}
if (p_var_type_name == Variant::get_type_name(Variant::SIGNAL)) {
- return "SignalInfo";
+ return "Signal";
}
Variant::Type var_types[] = {
@@ -484,7 +485,7 @@ static String variant_type_to_managed_name(const String &p_var_type_name) {
}
}
- return "object";
+ return "Variant";
}
String CSharpLanguage::make_function(const String &, const String &p_name, const PackedStringArray &p_args) const {
@@ -710,6 +711,12 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) {
return;
}
+ if (!Engine::get_singleton()->is_editor_hint()) {
+ // We disable collectible assemblies in the game player, because the limitations cause
+ // issues with mocking libraries. As such, we can only reload assemblies in the editor.
+ return;
+ }
+
// TODO:
// Currently, this reloads all scripts, including those whose class is not part of the
// assembly load context being unloaded. As such, we unnecessarily reload GodotTools.
@@ -1286,7 +1293,7 @@ void CSharpLanguage::_instance_binding_free_callback(void *, void *, void *p_bin
}
}
-GDNativeBool CSharpLanguage::_instance_binding_reference_callback(void *p_token, void *p_binding, GDNativeBool p_reference) {
+GDExtensionBool CSharpLanguage::_instance_binding_reference_callback(void *p_token, void *p_binding, GDExtensionBool p_reference) {
CRASH_COND(!p_binding);
CSharpScriptBinding &script_binding = ((RBMap<Object *, CSharpScriptBinding>::Element *)p_binding)->get();
@@ -2195,7 +2202,7 @@ void CSharpScript::reload_registered_script(Ref<CSharpScript> p_script) {
void CSharpScript::update_script_class_info(Ref<CSharpScript> p_script) {
bool tool = false;
- // TODO: Use GDNative godot_dictionary
+ // TODO: Use GDExtension godot_dictionary
Array methods_array;
methods_array.~Array();
Dictionary rpc_functions_dict;
@@ -2285,7 +2292,7 @@ bool CSharpScript::can_instantiate() const {
// For tool scripts, this will never fire if the class is not found. That's because we
// don't know if it's a tool script if we can't find the class to access the attributes.
if (extra_cond && !valid) {
- ERR_FAIL_V_MSG(false, "Cannot instance script because the associated class could not be found. Script: '" + get_path() + "'.");
+ ERR_FAIL_V_MSG(false, "Cannot instance script because the associated class could not be found. Script: '" + get_path() + "'. Make sure the script exists and contains a class definition with a name that matches the filename of the script exactly (it's case-sensitive).");
}
return valid && extra_cond;
diff --git a/modules/mono/csharp_script.h b/modules/mono/csharp_script.h
index e5e53acb07..68d374d262 100644
--- a/modules/mono/csharp_script.h
+++ b/modules/mono/csharp_script.h
@@ -352,9 +352,9 @@ class CSharpLanguage : public ScriptLanguage {
static void *_instance_binding_create_callback(void *p_token, void *p_instance);
static void _instance_binding_free_callback(void *p_token, void *p_instance, void *p_binding);
- static GDNativeBool _instance_binding_reference_callback(void *p_token, void *p_binding, GDNativeBool p_reference);
+ static GDExtensionBool _instance_binding_reference_callback(void *p_token, void *p_binding, GDExtensionBool p_reference);
- static GDNativeInstanceBindingCallbacks _instance_binding_callbacks;
+ static GDExtensionInstanceBindingCallbacks _instance_binding_callbacks;
public:
static void *get_instance_binding(Object *p_object);
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 0459257106..0d0889c491 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
@@ -12,8 +12,7 @@
<Configurations>Debug;ExportDebug;ExportRelease</Configurations>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
- <GodotProjectDir Condition=" '$(SolutionDir)' != '' ">$(SolutionDir)</GodotProjectDir>
- <GodotProjectDir Condition=" '$(SolutionDir)' == '' ">$(MSBuildProjectDirectory)</GodotProjectDir>
+ <GodotProjectDir Condition=" '$(GodotProjectDir)' == '' ">$(MSBuildProjectDirectory)</GodotProjectDir>
<GodotProjectDir>$([MSBuild]::EnsureTrailingSlash('$(GodotProjectDir)'))</GodotProjectDir>
<!-- Custom output paths for Godot projects. In brief, 'bin\' and 'obj\' are moved to '$(GodotProjectDir)\.godot\mono\temp\'. -->
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/ExportedFields.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/ExportedFields.cs
index ac8d6473a6..ccaba4d727 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/ExportedFields.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/ExportedFields.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
#pragma warning disable CS0169
@@ -44,7 +45,7 @@ namespace Godot.SourceGenerators.Sample
[Export] private Color field_Color = Colors.Aquamarine;
[Export] private Plane field_Plane = Plane.PlaneXZ;
[Export] private Callable field_Callable = new Callable(Engine.GetMainLoop(), "_process");
- [Export] private SignalInfo field_SignalInfo = new SignalInfo(Engine.GetMainLoop(), "property_list_changed");
+ [Export] private Signal field_Signal = new Signal(Engine.GetMainLoop(), "property_list_changed");
// Enums
[SuppressMessage("ReSharper", "UnusedMember.Local")]
@@ -83,6 +84,10 @@ namespace Godot.SourceGenerators.Sample
[Export] private StringName[] field_StringNameArray = { "foo", "bar" };
[Export] private NodePath[] field_NodePathArray = { "foo", "bar" };
[Export] private RID[] field_RIDArray = { default, default, default };
+ // Note we use Array and not System.Array. This tests the generated namespace qualification.
+ [Export] private Int32[] field_empty_Int32Array = Array.Empty<Int32>();
+ // Note we use List and not System.Collections.Generic.
+ [Export] private int[] field_array_from_list = new List<int>(Array.Empty<int>()).ToArray();
// Variant
[Export] private Variant field_Variant = "foo";
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/ExportedProperties.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/ExportedProperties.cs
index 3020cfbc50..5afaeb736f 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/ExportedProperties.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/ExportedProperties.cs
@@ -12,6 +12,95 @@ namespace Godot.SourceGenerators.Sample
[SuppressMessage("ReSharper", "InconsistentNaming")]
public partial class ExportedProperties : Godot.Object
{
+ // Do not generate default value
+ private String _notGenerate_Property_String = new string("not generate");
+ [Export]
+ public String NotGenerate_Complex_Lamda_Property
+ {
+ get => _notGenerate_Property_String + Convert.ToInt32("1");
+ set => _notGenerate_Property_String = value;
+ }
+
+ [Export]
+ public String NotGenerate_Lamda_NoField_Property
+ {
+ get => new string("not generate");
+ set => _notGenerate_Property_String = value;
+ }
+
+ [Export]
+ public String NotGenerate_Complex_Return_Property
+ {
+ get
+ {
+ return _notGenerate_Property_String + Convert.ToInt32("1");
+ }
+ set
+ {
+ _notGenerate_Property_String = value;
+ }
+ }
+
+ private int _notGenerate_Property_Int = 1;
+ [Export]
+ public string NotGenerate_Returns_Property
+ {
+ get
+ {
+ if (_notGenerate_Property_Int == 1)
+ {
+ return "a";
+ }
+ else
+ {
+ return "b";
+ }
+ }
+ set
+ {
+ _notGenerate_Property_Int = value == "a" ? 1 : 2;
+ }
+ }
+
+ // Full Property
+ private String _fullProperty_String = "FullProperty_String";
+ [Export]
+ public String FullProperty_String
+ {
+ get
+ {
+ return _fullProperty_String;
+ }
+ set
+ {
+ _fullProperty_String = value;
+ }
+ }
+
+ private String _fullProperty_String_Complex = new string("FullProperty_String_Complex") + Convert.ToInt32("1");
+ [Export]
+ public String FullProperty_String_Complex
+ {
+ get
+ {
+ return _fullProperty_String_Complex;
+ }
+ set
+ {
+ _fullProperty_String_Complex = value;
+ }
+ }
+
+ // Lambda Property
+ private String _lamdaProperty_String = "LamdaProperty_String";
+ [Export]
+ public String LamdaProperty_String
+ {
+ get => _lamdaProperty_String;
+ set => _lamdaProperty_String = value;
+ }
+
+ // Auto Property
[Export] private Boolean property_Boolean { get; set; } = true;
[Export] private Char property_Char { get; set; } = 'f';
[Export] private SByte property_SByte { get; set; } = 10;
@@ -44,7 +133,7 @@ namespace Godot.SourceGenerators.Sample
[Export] private Color property_Color { get; set; } = Colors.Aquamarine;
[Export] private Plane property_Plane { get; set; } = Plane.PlaneXZ;
[Export] private Callable property_Callable { get; set; } = new Callable(Engine.GetMainLoop(), "_process");
- [Export] private SignalInfo property_SignalInfo { get; set; } = new SignalInfo(Engine.GetMainLoop(), "property_list_changed");
+ [Export] private Signal property_Signal { get; set; } = new Signal(Engine.GetMainLoop(), "property_list_changed");
// Enums
[SuppressMessage("ReSharper", "UnusedMember.Local")]
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/MoreExportedFields.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/MoreExportedFields.cs
new file mode 100644
index 0000000000..a6c8e52667
--- /dev/null
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/MoreExportedFields.cs
@@ -0,0 +1,19 @@
+using System;
+using System.Diagnostics.CodeAnalysis;
+
+#pragma warning disable CS0169
+#pragma warning disable CS0414
+
+namespace Godot.SourceGenerators.Sample
+{
+ [SuppressMessage("ReSharper", "BuiltInTypeReferenceStyle")]
+ [SuppressMessage("ReSharper", "RedundantNameQualifier")]
+ [SuppressMessage("ReSharper", "ArrangeObjectCreationWhenTypeEvident")]
+ [SuppressMessage("ReSharper", "InconsistentNaming")]
+ // We split the definition of ExportedFields to verify properties work across multiple files.
+ public partial class ExportedFields : Godot.Object
+ {
+ // Note we use Array and not System.Array. This tests the generated namespace qualification.
+ [Export] private Int64[] field_empty_Int64Array = Array.Empty<Int64>();
+ }
+}
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Common.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Common.cs
index e28788ec0b..4eed2d7b7b 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Common.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Common.cs
@@ -14,7 +14,7 @@ namespace Godot.SourceGenerators
{
string message =
"Missing partial modifier on declaration of type '" +
- $"{symbol.FullQualifiedName()}' which is a subclass of '{GodotClasses.Object}'";
+ $"{symbol.FullQualifiedNameOmitGlobal()}' which is a subclass of '{GodotClasses.Object}'";
string description = $"{message}. Subclasses of '{GodotClasses.Object}' " +
"must be declared with the partial modifier.";
@@ -41,7 +41,7 @@ namespace Godot.SourceGenerators
.GetDeclaredSymbol(outerTypeDeclSyntax);
string fullQualifiedName = outerSymbol is INamedTypeSymbol namedTypeSymbol ?
- namedTypeSymbol.FullQualifiedName() :
+ namedTypeSymbol.FullQualifiedNameOmitGlobal() :
"type not found";
string message =
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ExtensionMethods.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ExtensionMethods.cs
index 8de12de23b..8852b7ebad 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ExtensionMethods.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ExtensionMethods.cs
@@ -2,6 +2,7 @@ using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
+using System.Text;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
@@ -148,22 +149,73 @@ namespace Godot.SourceGenerators
};
}
+ public static string NameWithTypeParameters(this INamedTypeSymbol symbol)
+ {
+ return symbol.IsGenericType ?
+ string.Concat(symbol.Name, "<", string.Join(", ", symbol.TypeParameters), ">") :
+ symbol.Name;
+ }
+
private static SymbolDisplayFormat FullyQualifiedFormatOmitGlobal { get; } =
SymbolDisplayFormat.FullyQualifiedFormat
.WithGlobalNamespaceStyle(SymbolDisplayGlobalNamespaceStyle.Omitted);
- public static string FullQualifiedName(this ITypeSymbol symbol)
+ private static SymbolDisplayFormat FullyQualifiedFormatIncludeGlobal { get; } =
+ SymbolDisplayFormat.FullyQualifiedFormat
+ .WithGlobalNamespaceStyle(SymbolDisplayGlobalNamespaceStyle.Included);
+
+ public static string FullQualifiedNameOmitGlobal(this ITypeSymbol symbol)
=> symbol.ToDisplayString(NullableFlowState.NotNull, FullyQualifiedFormatOmitGlobal);
- public static string NameWithTypeParameters(this INamedTypeSymbol symbol)
+ public static string FullQualifiedNameOmitGlobal(this INamespaceSymbol namespaceSymbol)
+ => namespaceSymbol.ToDisplayString(FullyQualifiedFormatOmitGlobal);
+
+ public static string FullQualifiedNameIncludeGlobal(this ITypeSymbol symbol)
+ => symbol.ToDisplayString(NullableFlowState.NotNull, FullyQualifiedFormatIncludeGlobal);
+
+ public static string FullQualifiedNameIncludeGlobal(this INamespaceSymbol namespaceSymbol)
+ => namespaceSymbol.ToDisplayString(FullyQualifiedFormatIncludeGlobal);
+
+ public static string FullQualifiedSyntax(this SyntaxNode node, SemanticModel sm)
{
- return symbol.IsGenericType ?
- string.Concat(symbol.Name, "<", string.Join(", ", symbol.TypeParameters), ">") :
- symbol.Name;
+ StringBuilder sb = new();
+ FullQualifiedSyntax(node, sm, sb, true);
+ return sb.ToString();
}
- public static string FullQualifiedName(this INamespaceSymbol namespaceSymbol)
- => namespaceSymbol.ToDisplayString(FullyQualifiedFormatOmitGlobal);
+ private static void FullQualifiedSyntax(SyntaxNode node, SemanticModel sm, StringBuilder sb, bool isFirstNode)
+ {
+ if (node is NameSyntax ns && isFirstNode)
+ {
+ SymbolInfo nameInfo = sm.GetSymbolInfo(ns);
+ sb.Append(nameInfo.Symbol?.ToDisplayString(FullyQualifiedFormatIncludeGlobal) ?? ns.ToString());
+ return;
+ }
+
+ bool innerIsFirstNode = true;
+ foreach (var child in node.ChildNodesAndTokens())
+ {
+ if (child.HasLeadingTrivia)
+ {
+ sb.Append(child.GetLeadingTrivia());
+ }
+
+ if (child.IsNode)
+ {
+ FullQualifiedSyntax(child.AsNode()!, sm, sb, isFirstNode: innerIsFirstNode);
+ innerIsFirstNode = false;
+ }
+ else
+ {
+ sb.Append(child);
+ }
+
+ if (child.HasTrailingTrivia)
+ {
+ sb.Append(child.GetTrailingTrivia());
+ }
+ }
+ }
public static string SanitizeQualifiedNameForUniqueHint(this string qualifiedName)
=> qualifiedName
@@ -216,8 +268,9 @@ namespace Godot.SourceGenerators
if (parameters.Length > paramTypes.Length)
return null; // Ignore incompatible method
- return new GodotMethodData(method, paramTypes, parameters
- .Select(p => p.Type).ToImmutableArray(), retType, retSymbol);
+ return new GodotMethodData(method, paramTypes,
+ parameters.Select(p => p.Type).ToImmutableArray(),
+ retType != null ? (retType.Value, retSymbol) : null);
}
public static IEnumerable<GodotMethodData> WhereHasGodotCompatibleSignature(
@@ -242,8 +295,8 @@ namespace Godot.SourceGenerators
foreach (var property in properties)
{
// TODO: We should still restore read-only properties after reloading assembly. Two possible ways: reflection or turn RestoreGodotObjectData into a constructor overload.
- // Ignore properties without a getter or without a setter. Godot properties must be both readable and writable.
- if (property.IsWriteOnly || property.IsReadOnly)
+ // Ignore properties without a getter, without a setter or with an init-only setter. Godot properties must be both readable and writable.
+ if (property.IsWriteOnly || property.IsReadOnly || property.SetMethod!.IsInitOnly)
continue;
var marshalType = MarshalUtils.ConvertManagedTypeToMarshalType(property.Type, typeCache);
@@ -278,10 +331,10 @@ namespace Godot.SourceGenerators
public static string Path(this Location location)
=> location.SourceTree?.GetLineSpan(location.SourceSpan).Path
- ?? location.GetLineSpan().Path;
+ ?? location.GetLineSpan().Path;
public static int StartLine(this Location location)
=> location.SourceTree?.GetLineSpan(location.SourceSpan).StartLinePosition.Line
- ?? location.GetLineSpan().StartLinePosition.Line;
+ ?? location.GetLineSpan().StartLinePosition.Line;
}
}
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotEnums.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotEnums.cs
index 1a25d684a0..7f1231dbcb 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotEnums.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotEnums.cs
@@ -71,29 +71,29 @@ namespace Godot.SourceGenerators
Expression = 19,
PlaceholderText = 20,
ColorNoAlpha = 21,
- ImageCompressLossy = 22,
- ImageCompressLossless = 23,
- ObjectId = 24,
- TypeString = 25,
- NodePathToEditedNode = 26,
- MethodOfVariantType = 27,
- MethodOfBaseType = 28,
- MethodOfInstance = 29,
- MethodOfScript = 30,
- PropertyOfVariantType = 31,
- PropertyOfBaseType = 32,
- PropertyOfInstance = 33,
- PropertyOfScript = 34,
- ObjectTooBig = 35,
- NodePathValidTypes = 36,
- SaveFile = 37,
- GlobalSaveFile = 38,
- IntIsObjectid = 39,
- IntIsPointer = 41,
- ArrayType = 40,
- LocaleId = 42,
- LocalizableString = 43,
- NodeType = 44,
+ ObjectId = 22,
+ TypeString = 23,
+ NodePathToEditedNode = 24,
+ MethodOfVariantType = 25,
+ MethodOfBaseType = 26,
+ MethodOfInstance = 27,
+ MethodOfScript = 28,
+ PropertyOfVariantType = 29,
+ PropertyOfBaseType = 30,
+ PropertyOfInstance = 31,
+ PropertyOfScript = 32,
+ ObjectTooBig = 33,
+ NodePathValidTypes = 34,
+ SaveFile = 35,
+ GlobalSaveFile = 36,
+ IntIsObjectid = 37,
+ IntIsPointer = 38,
+ ArrayType = 39,
+ LocaleId = 40,
+ LocalizableString = 41,
+ NodeType = 42,
+ HideQuaternionEdit = 43,
+ Password = 44,
Max = 45
}
@@ -114,26 +114,27 @@ namespace Godot.SourceGenerators
RestartIfChanged = 2048,
ScriptVariable = 4096,
StoreIfNull = 8192,
- AnimateAsTrigger = 16384,
- UpdateAllIfModified = 32768,
- ScriptDefaultValue = 65536,
- ClassIsEnum = 131072,
- NilIsVariant = 262144,
- Internal = 524288,
- DoNotShareOnDuplicate = 1048576,
- HighEndGfx = 2097152,
- NodePathFromSceneRoot = 4194304,
- ResourceNotPersistent = 8388608,
- KeyingIncrements = 16777216,
- DeferredSetResource = 33554432,
- EditorInstantiateObject = 67108864,
- EditorBasicSetting = 134217728,
- Array = 536870912,
+ UpdateAllIfModified = 16384,
+ ScriptDefaultValue = 32768,
+ ClassIsEnum = 65536,
+ NilIsVariant = 131072,
+ Internal = 262144,
+ DoNotShareOnDuplicate = 524288,
+ HighEndGfx = 1048576,
+ NodePathFromSceneRoot = 2097152,
+ ResourceNotPersistent = 4194304,
+ KeyingIncrements = 8388608,
+ DeferredSetResource = 16777216,
+ EditorInstantiateObject = 33554432,
+ EditorBasicSetting = 67108864,
+ ReadOnly = 134217728,
+ Array = 268435456,
Default = 6,
DefaultIntl = 38,
NoEditor = 2
}
+ [Flags]
public enum MethodFlags
{
Normal = 1,
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotMemberData.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotMemberData.cs
index db395e21cb..0760ea11bb 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotMemberData.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotMemberData.cs
@@ -3,26 +3,24 @@ using Microsoft.CodeAnalysis;
namespace Godot.SourceGenerators
{
- public struct GodotMethodData
+ public readonly struct GodotMethodData
{
public GodotMethodData(IMethodSymbol method, ImmutableArray<MarshalType> paramTypes,
- ImmutableArray<ITypeSymbol> paramTypeSymbols, MarshalType? retType, ITypeSymbol? retSymbol)
+ ImmutableArray<ITypeSymbol> paramTypeSymbols, (MarshalType MarshalType, ITypeSymbol TypeSymbol)? retType)
{
Method = method;
ParamTypes = paramTypes;
ParamTypeSymbols = paramTypeSymbols;
RetType = retType;
- RetSymbol = retSymbol;
}
public IMethodSymbol Method { get; }
public ImmutableArray<MarshalType> ParamTypes { get; }
public ImmutableArray<ITypeSymbol> ParamTypeSymbols { get; }
- public MarshalType? RetType { get; }
- public ITypeSymbol? RetSymbol { get; }
+ public (MarshalType MarshalType, ITypeSymbol TypeSymbol)? RetType { get; }
}
- public struct GodotSignalDelegateData
+ public readonly struct GodotSignalDelegateData
{
public GodotSignalDelegateData(string name, INamedTypeSymbol delegateSymbol, GodotMethodData invokeMethodData)
{
@@ -36,7 +34,7 @@ namespace Godot.SourceGenerators
public GodotMethodData InvokeMethodData { get; }
}
- public struct GodotPropertyData
+ public readonly struct GodotPropertyData
{
public GodotPropertyData(IPropertySymbol propertySymbol, MarshalType type)
{
@@ -48,7 +46,7 @@ namespace Godot.SourceGenerators
public MarshalType Type { get; }
}
- public struct GodotFieldData
+ public readonly struct GodotFieldData
{
public GodotFieldData(IFieldSymbol fieldSymbol, MarshalType type)
{
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MarshalType.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MarshalType.cs
index 15f5803bf0..ee1374d0b9 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MarshalType.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MarshalType.cs
@@ -37,7 +37,7 @@ namespace Godot.SourceGenerators
Color,
Plane,
Callable,
- SignalInfo,
+ Signal,
// Enums
Enum,
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MarshalUtils.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MarshalUtils.cs
index bd40675fd3..f0a6a72281 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MarshalUtils.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MarshalUtils.cs
@@ -56,7 +56,7 @@ namespace Godot.SourceGenerators
MarshalType.Color => VariantType.Color,
MarshalType.Plane => VariantType.Plane,
MarshalType.Callable => VariantType.Callable,
- MarshalType.SignalInfo => VariantType.Signal,
+ MarshalType.Signal => VariantType.Signal,
MarshalType.Enum => VariantType.Int,
MarshalType.ByteArray => VariantType.PackedByteArray,
MarshalType.Int32Array => VariantType.PackedInt32Array,
@@ -147,7 +147,7 @@ namespace Godot.SourceGenerators
{ Name: "Plane" } => MarshalType.Plane,
{ Name: "RID" } => MarshalType.RID,
{ Name: "Callable" } => MarshalType.Callable,
- { Name: "SignalInfo" } => MarshalType.SignalInfo,
+ { Name: "Signal" } => MarshalType.Signal,
{ Name: "Variant" } => MarshalType.Variant,
_ => null
};
@@ -220,7 +220,7 @@ namespace Godot.SourceGenerators
_ => null
};
case "Collections"
- when type.ContainingNamespace?.FullQualifiedName() == "Godot.Collections":
+ when type.ContainingNamespace?.FullQualifiedNameOmitGlobal() == "Godot.Collections":
return type switch
{
{ Name: "Dictionary" } =>
@@ -304,240 +304,41 @@ namespace Godot.SourceGenerators
{
return marshalType switch
{
- MarshalType.Boolean =>
- source.Append(VariantUtils, ".ConvertToBool(", inputExpr, ")"),
- MarshalType.Char =>
- source.Append("(char)", VariantUtils, ".ConvertToUInt16(", inputExpr, ")"),
- MarshalType.SByte =>
- source.Append(VariantUtils, ".ConvertToInt8(", inputExpr, ")"),
- MarshalType.Int16 =>
- source.Append(VariantUtils, ".ConvertToInt16(", inputExpr, ")"),
- MarshalType.Int32 =>
- source.Append(VariantUtils, ".ConvertToInt32(", inputExpr, ")"),
- MarshalType.Int64 =>
- source.Append(VariantUtils, ".ConvertToInt64(", inputExpr, ")"),
- MarshalType.Byte =>
- source.Append(VariantUtils, ".ConvertToUInt8(", inputExpr, ")"),
- MarshalType.UInt16 =>
- source.Append(VariantUtils, ".ConvertToUInt16(", inputExpr, ")"),
- MarshalType.UInt32 =>
- source.Append(VariantUtils, ".ConvertToUInt32(", inputExpr, ")"),
- MarshalType.UInt64 =>
- source.Append(VariantUtils, ".ConvertToUInt64(", inputExpr, ")"),
- MarshalType.Single =>
- source.Append(VariantUtils, ".ConvertToFloat32(", inputExpr, ")"),
- MarshalType.Double =>
- source.Append(VariantUtils, ".ConvertToFloat64(", inputExpr, ")"),
- MarshalType.String =>
- source.Append(VariantUtils, ".ConvertToStringObject(", inputExpr, ")"),
- MarshalType.Vector2 =>
- source.Append(VariantUtils, ".ConvertToVector2(", inputExpr, ")"),
- MarshalType.Vector2i =>
- source.Append(VariantUtils, ".ConvertToVector2i(", inputExpr, ")"),
- MarshalType.Rect2 =>
- source.Append(VariantUtils, ".ConvertToRect2(", inputExpr, ")"),
- MarshalType.Rect2i =>
- source.Append(VariantUtils, ".ConvertToRect2i(", inputExpr, ")"),
- MarshalType.Transform2D =>
- source.Append(VariantUtils, ".ConvertToTransform2D(", inputExpr, ")"),
- MarshalType.Vector3 =>
- source.Append(VariantUtils, ".ConvertToVector3(", inputExpr, ")"),
- MarshalType.Vector3i =>
- source.Append(VariantUtils, ".ConvertToVector3i(", inputExpr, ")"),
- MarshalType.Basis =>
- source.Append(VariantUtils, ".ConvertToBasis(", inputExpr, ")"),
- MarshalType.Quaternion =>
- source.Append(VariantUtils, ".ConvertToQuaternion(", inputExpr, ")"),
- MarshalType.Transform3D =>
- source.Append(VariantUtils, ".ConvertToTransform3D(", inputExpr, ")"),
- MarshalType.Vector4 =>
- source.Append(VariantUtils, ".ConvertToVector4(", inputExpr, ")"),
- MarshalType.Vector4i =>
- source.Append(VariantUtils, ".ConvertToVector4i(", inputExpr, ")"),
- MarshalType.Projection =>
- source.Append(VariantUtils, ".ConvertToProjection(", inputExpr, ")"),
- MarshalType.AABB =>
- source.Append(VariantUtils, ".ConvertToAABB(", inputExpr, ")"),
- MarshalType.Color =>
- source.Append(VariantUtils, ".ConvertToColor(", inputExpr, ")"),
- MarshalType.Plane =>
- source.Append(VariantUtils, ".ConvertToPlane(", inputExpr, ")"),
- MarshalType.Callable =>
- source.Append(VariantUtils, ".ConvertToCallableManaged(", inputExpr, ")"),
- MarshalType.SignalInfo =>
- source.Append(VariantUtils, ".ConvertToSignalInfo(", inputExpr, ")"),
- MarshalType.Enum =>
- source.Append("(", typeSymbol.FullQualifiedName(),
- ")", VariantUtils, ".ConvertToInt32(", inputExpr, ")"),
- MarshalType.ByteArray =>
- source.Append(VariantUtils, ".ConvertAsPackedByteArrayToSystemArray(", inputExpr, ")"),
- MarshalType.Int32Array =>
- source.Append(VariantUtils, ".ConvertAsPackedInt32ArrayToSystemArray(", inputExpr, ")"),
- MarshalType.Int64Array =>
- source.Append(VariantUtils, ".ConvertAsPackedInt64ArrayToSystemArray(", inputExpr, ")"),
- MarshalType.Float32Array =>
- source.Append(VariantUtils, ".ConvertAsPackedFloat32ArrayToSystemArray(", inputExpr, ")"),
- MarshalType.Float64Array =>
- source.Append(VariantUtils, ".ConvertAsPackedFloat64ArrayToSystemArray(", inputExpr, ")"),
- MarshalType.StringArray =>
- source.Append(VariantUtils, ".ConvertAsPackedStringArrayToSystemArray(", inputExpr, ")"),
- MarshalType.Vector2Array =>
- source.Append(VariantUtils, ".ConvertAsPackedVector2ArrayToSystemArray(", inputExpr, ")"),
- MarshalType.Vector3Array =>
- source.Append(VariantUtils, ".ConvertAsPackedVector3ArrayToSystemArray(", inputExpr, ")"),
- MarshalType.ColorArray =>
- source.Append(VariantUtils, ".ConvertAsPackedColorArrayToSystemArray(", inputExpr, ")"),
+ // We need a special case for GodotObjectOrDerived[], because it's not supported by VariantUtils.ConvertTo<T>
MarshalType.GodotObjectOrDerivedArray =>
source.Append(VariantUtils, ".ConvertToSystemArrayOfGodotObject<",
- ((IArrayTypeSymbol)typeSymbol).ElementType.FullQualifiedName(), ">(", inputExpr, ")"),
- MarshalType.SystemArrayOfStringName =>
- source.Append(VariantUtils, ".ConvertToSystemArrayOfStringName(", inputExpr, ")"),
- MarshalType.SystemArrayOfNodePath =>
- source.Append(VariantUtils, ".ConvertToSystemArrayOfNodePath(", inputExpr, ")"),
- MarshalType.SystemArrayOfRID =>
- source.Append(VariantUtils, ".ConvertToSystemArrayOfRID(", inputExpr, ")"),
- MarshalType.Variant =>
- source.Append("global::Godot.Variant.CreateCopyingBorrowed(", inputExpr, ")"),
- MarshalType.GodotObjectOrDerived =>
- source.Append("(", typeSymbol.FullQualifiedName(),
- ")", VariantUtils, ".ConvertToGodotObject(", inputExpr, ")"),
- MarshalType.StringName =>
- source.Append(VariantUtils, ".ConvertToStringNameObject(", inputExpr, ")"),
- MarshalType.NodePath =>
- source.Append(VariantUtils, ".ConvertToNodePathObject(", inputExpr, ")"),
- MarshalType.RID =>
- source.Append(VariantUtils, ".ConvertToRID(", inputExpr, ")"),
- MarshalType.GodotDictionary =>
- source.Append(VariantUtils, ".ConvertToDictionaryObject(", inputExpr, ")"),
- MarshalType.GodotArray =>
- source.Append(VariantUtils, ".ConvertToArrayObject(", inputExpr, ")"),
+ ((IArrayTypeSymbol)typeSymbol).ElementType.FullQualifiedNameIncludeGlobal(), ">(",
+ inputExpr, ")"),
+ // We need a special case for generic Godot collections and GodotObjectOrDerived[], because VariantUtils.ConvertTo<T> is slower
MarshalType.GodotGenericDictionary =>
- source.Append(VariantUtils, ".ConvertToDictionaryObject<",
- ((INamedTypeSymbol)typeSymbol).TypeArguments[0].FullQualifiedName(), ", ",
- ((INamedTypeSymbol)typeSymbol).TypeArguments[1].FullQualifiedName(), ">(", inputExpr, ")"),
+ source.Append(VariantUtils, ".ConvertToDictionary<",
+ ((INamedTypeSymbol)typeSymbol).TypeArguments[0].FullQualifiedNameIncludeGlobal(), ", ",
+ ((INamedTypeSymbol)typeSymbol).TypeArguments[1].FullQualifiedNameIncludeGlobal(), ">(",
+ inputExpr, ")"),
MarshalType.GodotGenericArray =>
- source.Append(VariantUtils, ".ConvertToArrayObject<",
- ((INamedTypeSymbol)typeSymbol).TypeArguments[0].FullQualifiedName(), ">(", inputExpr, ")"),
- _ => throw new ArgumentOutOfRangeException(nameof(marshalType), marshalType,
- "Received unexpected marshal type")
+ source.Append(VariantUtils, ".ConvertToArray<",
+ ((INamedTypeSymbol)typeSymbol).TypeArguments[0].FullQualifiedNameIncludeGlobal(), ">(",
+ inputExpr, ")"),
+ _ => source.Append(VariantUtils, ".ConvertTo<",
+ typeSymbol.FullQualifiedNameIncludeGlobal(), ">(", inputExpr, ")"),
};
}
- public static StringBuilder AppendManagedToNativeVariantExpr(
- this StringBuilder source, string inputExpr, MarshalType marshalType)
+ public static StringBuilder AppendManagedToNativeVariantExpr(this StringBuilder source,
+ string inputExpr, ITypeSymbol typeSymbol, MarshalType marshalType)
{
return marshalType switch
{
- MarshalType.Boolean =>
- source.Append(VariantUtils, ".CreateFromBool(", inputExpr, ")"),
- MarshalType.Char =>
- source.Append(VariantUtils, ".CreateFromInt((ushort)", inputExpr, ")"),
- MarshalType.SByte =>
- source.Append(VariantUtils, ".CreateFromInt(", inputExpr, ")"),
- MarshalType.Int16 =>
- source.Append(VariantUtils, ".CreateFromInt(", inputExpr, ")"),
- MarshalType.Int32 =>
- source.Append(VariantUtils, ".CreateFromInt(", inputExpr, ")"),
- MarshalType.Int64 =>
- source.Append(VariantUtils, ".CreateFromInt(", inputExpr, ")"),
- MarshalType.Byte =>
- source.Append(VariantUtils, ".CreateFromInt(", inputExpr, ")"),
- MarshalType.UInt16 =>
- source.Append(VariantUtils, ".CreateFromInt(", inputExpr, ")"),
- MarshalType.UInt32 =>
- source.Append(VariantUtils, ".CreateFromInt(", inputExpr, ")"),
- MarshalType.UInt64 =>
- source.Append(VariantUtils, ".CreateFromInt(", inputExpr, ")"),
- MarshalType.Single =>
- source.Append(VariantUtils, ".CreateFromFloat(", inputExpr, ")"),
- MarshalType.Double =>
- source.Append(VariantUtils, ".CreateFromFloat(", inputExpr, ")"),
- MarshalType.String =>
- source.Append(VariantUtils, ".CreateFromString(", inputExpr, ")"),
- MarshalType.Vector2 =>
- source.Append(VariantUtils, ".CreateFromVector2(", inputExpr, ")"),
- MarshalType.Vector2i =>
- source.Append(VariantUtils, ".CreateFromVector2i(", inputExpr, ")"),
- MarshalType.Rect2 =>
- source.Append(VariantUtils, ".CreateFromRect2(", inputExpr, ")"),
- MarshalType.Rect2i =>
- source.Append(VariantUtils, ".CreateFromRect2i(", inputExpr, ")"),
- MarshalType.Transform2D =>
- source.Append(VariantUtils, ".CreateFromTransform2D(", inputExpr, ")"),
- MarshalType.Vector3 =>
- source.Append(VariantUtils, ".CreateFromVector3(", inputExpr, ")"),
- MarshalType.Vector3i =>
- source.Append(VariantUtils, ".CreateFromVector3i(", inputExpr, ")"),
- MarshalType.Basis =>
- source.Append(VariantUtils, ".CreateFromBasis(", inputExpr, ")"),
- MarshalType.Quaternion =>
- source.Append(VariantUtils, ".CreateFromQuaternion(", inputExpr, ")"),
- MarshalType.Transform3D =>
- source.Append(VariantUtils, ".CreateFromTransform3D(", inputExpr, ")"),
- MarshalType.Vector4 =>
- source.Append(VariantUtils, ".CreateFromVector4(", inputExpr, ")"),
- MarshalType.Vector4i =>
- source.Append(VariantUtils, ".CreateFromVector4i(", inputExpr, ")"),
- MarshalType.Projection =>
- source.Append(VariantUtils, ".CreateFromProjection(", inputExpr, ")"),
- MarshalType.AABB =>
- source.Append(VariantUtils, ".CreateFromAABB(", inputExpr, ")"),
- MarshalType.Color =>
- source.Append(VariantUtils, ".CreateFromColor(", inputExpr, ")"),
- MarshalType.Plane =>
- source.Append(VariantUtils, ".CreateFromPlane(", inputExpr, ")"),
- MarshalType.Callable =>
- source.Append(VariantUtils, ".CreateFromCallable(", inputExpr, ")"),
- MarshalType.SignalInfo =>
- source.Append(VariantUtils, ".CreateFromSignalInfo(", inputExpr, ")"),
- MarshalType.Enum =>
- source.Append(VariantUtils, ".CreateFromInt((int)", inputExpr, ")"),
- MarshalType.ByteArray =>
- source.Append(VariantUtils, ".CreateFromPackedByteArray(", inputExpr, ")"),
- MarshalType.Int32Array =>
- source.Append(VariantUtils, ".CreateFromPackedInt32Array(", inputExpr, ")"),
- MarshalType.Int64Array =>
- source.Append(VariantUtils, ".CreateFromPackedInt64Array(", inputExpr, ")"),
- MarshalType.Float32Array =>
- source.Append(VariantUtils, ".CreateFromPackedFloat32Array(", inputExpr, ")"),
- MarshalType.Float64Array =>
- source.Append(VariantUtils, ".CreateFromPackedFloat64Array(", inputExpr, ")"),
- MarshalType.StringArray =>
- source.Append(VariantUtils, ".CreateFromPackedStringArray(", inputExpr, ")"),
- MarshalType.Vector2Array =>
- source.Append(VariantUtils, ".CreateFromPackedVector2Array(", inputExpr, ")"),
- MarshalType.Vector3Array =>
- source.Append(VariantUtils, ".CreateFromPackedVector3Array(", inputExpr, ")"),
- MarshalType.ColorArray =>
- source.Append(VariantUtils, ".CreateFromPackedColorArray(", inputExpr, ")"),
+ // We need a special case for GodotObjectOrDerived[], because it's not supported by VariantUtils.CreateFrom<T>
MarshalType.GodotObjectOrDerivedArray =>
source.Append(VariantUtils, ".CreateFromSystemArrayOfGodotObject(", inputExpr, ")"),
- MarshalType.SystemArrayOfStringName =>
- source.Append(VariantUtils, ".CreateFromSystemArrayOfStringName(", inputExpr, ")"),
- MarshalType.SystemArrayOfNodePath =>
- source.Append(VariantUtils, ".CreateFromSystemArrayOfNodePath(", inputExpr, ")"),
- MarshalType.SystemArrayOfRID =>
- source.Append(VariantUtils, ".CreateFromSystemArrayOfRID(", inputExpr, ")"),
- MarshalType.Variant =>
- source.Append(inputExpr, ".CopyNativeVariant()"),
- MarshalType.GodotObjectOrDerived =>
- source.Append(VariantUtils, ".CreateFromGodotObject(", inputExpr, ")"),
- MarshalType.StringName =>
- source.Append(VariantUtils, ".CreateFromStringName(", inputExpr, ")"),
- MarshalType.NodePath =>
- source.Append(VariantUtils, ".CreateFromNodePath(", inputExpr, ")"),
- MarshalType.RID =>
- source.Append(VariantUtils, ".CreateFromRID(", inputExpr, ")"),
- MarshalType.GodotDictionary =>
- source.Append(VariantUtils, ".CreateFromDictionary(", inputExpr, ")"),
- MarshalType.GodotArray =>
- source.Append(VariantUtils, ".CreateFromArray(", inputExpr, ")"),
+ // We need a special case for generic Godot collections and GodotObjectOrDerived[], because VariantUtils.CreateFrom<T> is slower
MarshalType.GodotGenericDictionary =>
source.Append(VariantUtils, ".CreateFromDictionary(", inputExpr, ")"),
MarshalType.GodotGenericArray =>
source.Append(VariantUtils, ".CreateFromArray(", inputExpr, ")"),
- _ => throw new ArgumentOutOfRangeException(nameof(marshalType), marshalType,
- "Received unexpected marshal type")
+ _ => source.Append(VariantUtils, ".CreateFrom<",
+ typeSymbol.FullQualifiedNameIncludeGlobal(), ">(", inputExpr, ")"),
};
}
@@ -546,137 +347,37 @@ namespace Godot.SourceGenerators
{
return marshalType switch
{
- MarshalType.Boolean => source.Append(inputExpr, ".AsBool()"),
- MarshalType.Char => source.Append(inputExpr, ".AsChar()"),
- MarshalType.SByte => source.Append(inputExpr, ".AsSByte()"),
- MarshalType.Int16 => source.Append(inputExpr, ".AsInt16()"),
- MarshalType.Int32 => source.Append(inputExpr, ".AsInt32()"),
- MarshalType.Int64 => source.Append(inputExpr, ".AsInt64()"),
- MarshalType.Byte => source.Append(inputExpr, ".AsByte()"),
- MarshalType.UInt16 => source.Append(inputExpr, ".AsUInt16()"),
- MarshalType.UInt32 => source.Append(inputExpr, ".AsUInt32()"),
- MarshalType.UInt64 => source.Append(inputExpr, ".AsUInt64()"),
- MarshalType.Single => source.Append(inputExpr, ".AsSingle()"),
- MarshalType.Double => source.Append(inputExpr, ".AsDouble()"),
- MarshalType.String => source.Append(inputExpr, ".AsString()"),
- MarshalType.Vector2 => source.Append(inputExpr, ".AsVector2()"),
- MarshalType.Vector2i => source.Append(inputExpr, ".AsVector2i()"),
- MarshalType.Rect2 => source.Append(inputExpr, ".AsRect2()"),
- MarshalType.Rect2i => source.Append(inputExpr, ".AsRect2i()"),
- MarshalType.Transform2D => source.Append(inputExpr, ".AsTransform2D()"),
- MarshalType.Vector3 => source.Append(inputExpr, ".AsVector3()"),
- MarshalType.Vector3i => source.Append(inputExpr, ".AsVector3i()"),
- MarshalType.Basis => source.Append(inputExpr, ".AsBasis()"),
- MarshalType.Quaternion => source.Append(inputExpr, ".AsQuaternion()"),
- MarshalType.Transform3D => source.Append(inputExpr, ".AsTransform3D()"),
- MarshalType.Vector4 => source.Append(inputExpr, ".AsVector4()"),
- MarshalType.Vector4i => source.Append(inputExpr, ".AsVector4i()"),
- MarshalType.Projection => source.Append(inputExpr, ".AsProjection()"),
- MarshalType.AABB => source.Append(inputExpr, ".AsAABB()"),
- MarshalType.Color => source.Append(inputExpr, ".AsColor()"),
- MarshalType.Plane => source.Append(inputExpr, ".AsPlane()"),
- MarshalType.Callable => source.Append(inputExpr, ".AsCallable()"),
- MarshalType.SignalInfo => source.Append(inputExpr, ".AsSignalInfo()"),
- MarshalType.Enum =>
- source.Append("(", typeSymbol.FullQualifiedName(), ")", inputExpr, ".AsInt64()"),
- MarshalType.ByteArray => source.Append(inputExpr, ".AsByteArray()"),
- MarshalType.Int32Array => source.Append(inputExpr, ".AsInt32Array()"),
- MarshalType.Int64Array => source.Append(inputExpr, ".AsInt64Array()"),
- MarshalType.Float32Array => source.Append(inputExpr, ".AsFloat32Array()"),
- MarshalType.Float64Array => source.Append(inputExpr, ".AsFloat64Array()"),
- MarshalType.StringArray => source.Append(inputExpr, ".AsStringArray()"),
- MarshalType.Vector2Array => source.Append(inputExpr, ".AsVector2Array()"),
- MarshalType.Vector3Array => source.Append(inputExpr, ".AsVector3Array()"),
- MarshalType.ColorArray => source.Append(inputExpr, ".AsColorArray()"),
- MarshalType.GodotObjectOrDerivedArray => source.Append(inputExpr, ".AsGodotObjectArray<",
- ((IArrayTypeSymbol)typeSymbol).ElementType.FullQualifiedName(), ">()"),
- MarshalType.SystemArrayOfStringName => source.Append(inputExpr, ".AsSystemArrayOfStringName()"),
- MarshalType.SystemArrayOfNodePath => source.Append(inputExpr, ".AsSystemArrayOfNodePath()"),
- MarshalType.SystemArrayOfRID => source.Append(inputExpr, ".AsSystemArrayOfRID()"),
- MarshalType.Variant => source.Append(inputExpr),
- MarshalType.GodotObjectOrDerived => source.Append("(",
- typeSymbol.FullQualifiedName(), ")", inputExpr, ".AsGodotObject()"),
- MarshalType.StringName => source.Append(inputExpr, ".AsStringName()"),
- MarshalType.NodePath => source.Append(inputExpr, ".AsNodePath()"),
- MarshalType.RID => source.Append(inputExpr, ".AsRID()"),
- MarshalType.GodotDictionary => source.Append(inputExpr, ".AsGodotDictionary()"),
- MarshalType.GodotArray => source.Append(inputExpr, ".AsGodotArray()"),
- MarshalType.GodotGenericDictionary => source.Append(inputExpr, ".AsGodotDictionary<",
- ((INamedTypeSymbol)typeSymbol).TypeArguments[0].FullQualifiedName(), ", ",
- ((INamedTypeSymbol)typeSymbol).TypeArguments[1].FullQualifiedName(), ">()"),
- MarshalType.GodotGenericArray => source.Append(inputExpr, ".AsGodotArray<",
- ((INamedTypeSymbol)typeSymbol).TypeArguments[0].FullQualifiedName(), ">()"),
- _ => throw new ArgumentOutOfRangeException(nameof(marshalType), marshalType,
- "Received unexpected marshal type")
+ // We need a special case for GodotObjectOrDerived[], because it's not supported by Variant.As<T>
+ MarshalType.GodotObjectOrDerivedArray =>
+ source.Append(inputExpr, ".AsGodotObjectArray<",
+ ((IArrayTypeSymbol)typeSymbol).ElementType.FullQualifiedNameIncludeGlobal(), ">()"),
+ // We need a special case for generic Godot collections and GodotObjectOrDerived[], because Variant.As<T> is slower
+ MarshalType.GodotGenericDictionary =>
+ source.Append(inputExpr, ".AsGodotDictionary<",
+ ((INamedTypeSymbol)typeSymbol).TypeArguments[0].FullQualifiedNameIncludeGlobal(), ", ",
+ ((INamedTypeSymbol)typeSymbol).TypeArguments[1].FullQualifiedNameIncludeGlobal(), ">()"),
+ MarshalType.GodotGenericArray =>
+ source.Append(inputExpr, ".AsGodotArray<",
+ ((INamedTypeSymbol)typeSymbol).TypeArguments[0].FullQualifiedNameIncludeGlobal(), ">()"),
+ _ => source.Append(inputExpr, ".As<",
+ typeSymbol.FullQualifiedNameIncludeGlobal(), ">()")
};
}
public static StringBuilder AppendManagedToVariantExpr(this StringBuilder source,
- string inputExpr, MarshalType marshalType)
+ string inputExpr, ITypeSymbol typeSymbol, MarshalType marshalType)
{
- switch (marshalType)
+ return marshalType switch
{
- case MarshalType.Boolean:
- case MarshalType.Char:
- case MarshalType.SByte:
- case MarshalType.Int16:
- case MarshalType.Int32:
- case MarshalType.Int64:
- case MarshalType.Byte:
- case MarshalType.UInt16:
- case MarshalType.UInt32:
- case MarshalType.UInt64:
- case MarshalType.Single:
- case MarshalType.Double:
- case MarshalType.String:
- case MarshalType.Vector2:
- case MarshalType.Vector2i:
- case MarshalType.Rect2:
- case MarshalType.Rect2i:
- case MarshalType.Transform2D:
- case MarshalType.Vector3:
- case MarshalType.Vector3i:
- case MarshalType.Basis:
- case MarshalType.Quaternion:
- case MarshalType.Transform3D:
- case MarshalType.Vector4:
- case MarshalType.Vector4i:
- case MarshalType.Projection:
- case MarshalType.AABB:
- case MarshalType.Color:
- case MarshalType.Plane:
- case MarshalType.Callable:
- case MarshalType.SignalInfo:
- case MarshalType.ByteArray:
- case MarshalType.Int32Array:
- case MarshalType.Int64Array:
- case MarshalType.Float32Array:
- case MarshalType.Float64Array:
- case MarshalType.StringArray:
- case MarshalType.Vector2Array:
- case MarshalType.Vector3Array:
- case MarshalType.ColorArray:
- case MarshalType.GodotObjectOrDerivedArray:
- case MarshalType.SystemArrayOfStringName:
- case MarshalType.SystemArrayOfNodePath:
- case MarshalType.SystemArrayOfRID:
- case MarshalType.GodotObjectOrDerived:
- case MarshalType.StringName:
- case MarshalType.NodePath:
- case MarshalType.RID:
- case MarshalType.GodotDictionary:
- case MarshalType.GodotArray:
- case MarshalType.GodotGenericDictionary:
- case MarshalType.GodotGenericArray:
- return source.Append("Variant.CreateFrom(", inputExpr, ")");
- case MarshalType.Enum:
- return source.Append("Variant.CreateFrom((long)", inputExpr, ")");
- case MarshalType.Variant:
- return source.Append(inputExpr);
- default:
- throw new ArgumentOutOfRangeException(nameof(marshalType), marshalType,
- "Received unexpected marshal type");
- }
+ // We need a special case for GodotObjectOrDerived[], because it's not supported by Variant.From<T>
+ MarshalType.GodotObjectOrDerivedArray =>
+ source.Append("global::Godot.Variant.CreateFrom(", inputExpr, ")"),
+ // We need a special case for generic Godot collections, because Variant.From<T> is slower
+ MarshalType.GodotGenericDictionary or MarshalType.GodotGenericArray =>
+ source.Append("global::Godot.Variant.CreateFrom(", inputExpr, ")"),
+ _ => source.Append("global::Godot.Variant.From<",
+ typeSymbol.FullQualifiedNameIncludeGlobal(), ">(", inputExpr, ")")
+ };
}
}
}
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MethodInfo.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MethodInfo.cs
index 81c6f2b7d5..bb9be862c4 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MethodInfo.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MethodInfo.cs
@@ -2,7 +2,7 @@ using System.Collections.Generic;
namespace Godot.SourceGenerators
{
- internal struct MethodInfo
+ internal readonly struct MethodInfo
{
public MethodInfo(string name, PropertyInfo returnVal, MethodFlags flags,
List<PropertyInfo>? arguments,
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/PropertyInfo.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/PropertyInfo.cs
index b345f5f84d..2b89633ef6 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/PropertyInfo.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/PropertyInfo.cs
@@ -1,6 +1,6 @@
namespace Godot.SourceGenerators
{
- internal struct PropertyInfo
+ internal readonly struct PropertyInfo
{
public PropertyInfo(VariantType type, string name, PropertyHint hint,
string? hintString, PropertyUsageFlags usage, bool exported)
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptMethodsGenerator.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptMethodsGenerator.cs
index d5d80df643..f79909589e 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptMethodsGenerator.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptMethodsGenerator.cs
@@ -80,13 +80,13 @@ namespace Godot.SourceGenerators
{
INamespaceSymbol namespaceSymbol = symbol.ContainingNamespace;
string classNs = namespaceSymbol != null && !namespaceSymbol.IsGlobalNamespace ?
- namespaceSymbol.FullQualifiedName() :
+ namespaceSymbol.FullQualifiedNameOmitGlobal() :
string.Empty;
bool hasNamespace = classNs.Length != 0;
bool isInnerClass = symbol.ContainingType != null;
- string uniqueHint = symbol.FullQualifiedName().SanitizeQualifiedNameForUniqueHint()
+ string uniqueHint = symbol.FullQualifiedNameOmitGlobal().SanitizeQualifiedNameForUniqueHint()
+ "_ScriptMethods.generated";
var source = new StringBuilder();
@@ -135,7 +135,8 @@ namespace Godot.SourceGenerators
source.Append("#pragma warning disable CS0109 // Disable warning about redundant 'new' keyword\n");
- source.Append($" public new class MethodName : {symbol.BaseType.FullQualifiedName()}.MethodName {{\n");
+ source.Append(
+ $" public new class MethodName : {symbol.BaseType.FullQualifiedNameIncludeGlobal()}.MethodName {{\n");
// Generate cached StringNames for methods and properties, for fast lookup
@@ -146,7 +147,7 @@ namespace Godot.SourceGenerators
foreach (string methodName in distinctMethodNames)
{
- source.Append(" public new static readonly StringName ");
+ source.Append(" public new static readonly global::Godot.StringName ");
source.Append(methodName);
source.Append(" = \"");
source.Append(methodName);
@@ -159,7 +160,7 @@ namespace Godot.SourceGenerators
if (godotClassMethods.Length > 0)
{
- const string listType = "System.Collections.Generic.List<global::Godot.Bridge.MethodInfo>";
+ const string listType = "global::System.Collections.Generic.List<global::Godot.Bridge.MethodInfo>";
source.Append(" internal new static ")
.Append(listType)
@@ -248,7 +249,7 @@ namespace Godot.SourceGenerators
AppendPropertyInfo(source, methodInfo.ReturnVal);
- source.Append(", flags: (Godot.MethodFlags)")
+ source.Append(", flags: (global::Godot.MethodFlags)")
.Append((int)methodInfo.Flags)
.Append(", arguments: ");
@@ -276,15 +277,15 @@ namespace Godot.SourceGenerators
private static void AppendPropertyInfo(StringBuilder source, PropertyInfo propertyInfo)
{
- source.Append("new(type: (Godot.Variant.Type)")
+ source.Append("new(type: (global::Godot.Variant.Type)")
.Append((int)propertyInfo.Type)
.Append(", name: \"")
.Append(propertyInfo.Name)
- .Append("\", hint: (Godot.PropertyHint)")
+ .Append("\", hint: (global::Godot.PropertyHint)")
.Append((int)propertyInfo.Hint)
.Append(", hintString: \"")
.Append(propertyInfo.HintString)
- .Append("\", usage: (Godot.PropertyUsageFlags)")
+ .Append("\", usage: (global::Godot.PropertyUsageFlags)")
.Append((int)propertyInfo.Usage)
.Append(", exported: ")
.Append(propertyInfo.Exported ? "true" : "false")
@@ -297,7 +298,7 @@ namespace Godot.SourceGenerators
if (method.RetType != null)
{
- returnVal = DeterminePropertyInfo(method.RetType.Value, name: string.Empty);
+ returnVal = DeterminePropertyInfo(method.RetType.Value.MarshalType, name: string.Empty);
}
else
{
@@ -391,7 +392,8 @@ namespace Godot.SourceGenerators
{
source.Append(" ret = ");
- source.AppendManagedToNativeVariantExpr("callRet", method.RetType.Value);
+ source.AppendManagedToNativeVariantExpr("callRet",
+ method.RetType.Value.TypeSymbol, method.RetType.Value.MarshalType);
source.Append(";\n");
source.Append(" return true;\n");
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPathAttributeGenerator.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPathAttributeGenerator.cs
index ccfb405d26..eae7e41da8 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPathAttributeGenerator.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPathAttributeGenerator.cs
@@ -45,8 +45,11 @@ namespace Godot.SourceGenerators
return false;
})
)
- // Ignore classes whose name is not the same as the file name
- .Where(x => Path.GetFileNameWithoutExtension(x.cds.SyntaxTree.FilePath) == x.symbol.Name)
+ .Where(x =>
+ // Ignore classes whose name is not the same as the file name
+ Path.GetFileNameWithoutExtension(x.cds.SyntaxTree.FilePath) == x.symbol.Name &&
+ // Ignore generic classes
+ !x.symbol.IsGenericType)
.GroupBy(x => x.symbol)
.ToDictionary(g => g.Key, g => g.Select(x => x.cds));
@@ -92,11 +95,11 @@ namespace Godot.SourceGenerators
INamespaceSymbol namespaceSymbol = symbol.ContainingNamespace;
string classNs = namespaceSymbol != null && !namespaceSymbol.IsGlobalNamespace ?
- namespaceSymbol.FullQualifiedName() :
+ namespaceSymbol.FullQualifiedNameOmitGlobal() :
string.Empty;
bool hasNamespace = classNs.Length != 0;
- string uniqueHint = symbol.FullQualifiedName().SanitizeQualifiedNameForUniqueHint()
+ string uniqueHint = symbol.FullQualifiedNameOmitGlobal().SanitizeQualifiedNameForUniqueHint()
+ "_ScriptPath.generated";
var source = new StringBuilder();
@@ -150,8 +153,6 @@ namespace Godot.SourceGenerators
first = false;
sourceBuilder.Append("typeof(");
sourceBuilder.Append(qualifiedName);
- if (godotClass.Key.IsGenericType)
- sourceBuilder.Append($"<{new string(',', godotClass.Key.TypeParameters.Count() - 1)}>");
sourceBuilder.Append(")");
}
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertiesGenerator.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertiesGenerator.cs
index 1198c633d9..b64b843b7c 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertiesGenerator.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertiesGenerator.cs
@@ -66,13 +66,13 @@ namespace Godot.SourceGenerators
{
INamespaceSymbol namespaceSymbol = symbol.ContainingNamespace;
string classNs = namespaceSymbol != null && !namespaceSymbol.IsGlobalNamespace ?
- namespaceSymbol.FullQualifiedName() :
+ namespaceSymbol.FullQualifiedNameOmitGlobal() :
string.Empty;
bool hasNamespace = classNs.Length != 0;
bool isInnerClass = symbol.ContainingType != null;
- string uniqueHint = symbol.FullQualifiedName().SanitizeQualifiedNameForUniqueHint()
+ string uniqueHint = symbol.FullQualifiedNameOmitGlobal().SanitizeQualifiedNameForUniqueHint()
+ "_ScriptProperties.generated";
var source = new StringBuilder();
@@ -124,14 +124,15 @@ namespace Godot.SourceGenerators
source.Append("#pragma warning disable CS0109 // Disable warning about redundant 'new' keyword\n");
- source.Append($" public new class PropertyName : {symbol.BaseType.FullQualifiedName()}.PropertyName {{\n");
+ source.Append(
+ $" public new class PropertyName : {symbol.BaseType.FullQualifiedNameIncludeGlobal()}.PropertyName {{\n");
// Generate cached StringNames for methods and properties, for fast lookup
foreach (var property in godotClassProperties)
{
string propertyName = property.PropertySymbol.Name;
- source.Append(" public new static readonly StringName ");
+ source.Append(" public new static readonly global::Godot.StringName ");
source.Append(propertyName);
source.Append(" = \"");
source.Append(propertyName);
@@ -141,7 +142,7 @@ namespace Godot.SourceGenerators
foreach (var field in godotClassFields)
{
string fieldName = field.FieldSymbol.Name;
- source.Append(" public new static readonly StringName ");
+ source.Append(" public new static readonly global::Godot.StringName ");
source.Append(fieldName);
source.Append(" = \"");
source.Append(fieldName);
@@ -157,7 +158,7 @@ namespace Godot.SourceGenerators
// Generate SetGodotClassPropertyValue
bool allPropertiesAreReadOnly = godotClassFields.All(fi => fi.FieldSymbol.IsReadOnly) &&
- godotClassProperties.All(pi => pi.PropertySymbol.IsReadOnly);
+ godotClassProperties.All(pi => pi.PropertySymbol.IsReadOnly || pi.PropertySymbol.SetMethod!.IsInitOnly);
if (!allPropertiesAreReadOnly)
{
@@ -167,7 +168,7 @@ namespace Godot.SourceGenerators
isFirstEntry = true;
foreach (var property in godotClassProperties)
{
- if (property.PropertySymbol.IsReadOnly)
+ if (property.PropertySymbol.IsReadOnly || property.PropertySymbol.SetMethod!.IsInitOnly)
continue;
GeneratePropertySetter(property.PropertySymbol.Name,
@@ -199,14 +200,14 @@ namespace Godot.SourceGenerators
foreach (var property in godotClassProperties)
{
GeneratePropertyGetter(property.PropertySymbol.Name,
- property.Type, source, isFirstEntry);
+ property.PropertySymbol.Type, property.Type, source, isFirstEntry);
isFirstEntry = false;
}
foreach (var field in godotClassFields)
{
GeneratePropertyGetter(field.FieldSymbol.Name,
- field.Type, source, isFirstEntry);
+ field.FieldSymbol.Type, field.Type, source, isFirstEntry);
isFirstEntry = false;
}
@@ -216,7 +217,7 @@ namespace Godot.SourceGenerators
// Generate GetGodotPropertyList
- string dictionaryType = "System.Collections.Generic.List<global::Godot.Bridge.PropertyInfo>";
+ string dictionaryType = "global::System.Collections.Generic.List<global::Godot.Bridge.PropertyInfo>";
source.Append(" internal new static ")
.Append(dictionaryType)
@@ -292,7 +293,7 @@ namespace Godot.SourceGenerators
source.Append("if (name == PropertyName.")
.Append(propertyMemberName)
.Append(") {\n")
- .Append(" ")
+ .Append(" this.")
.Append(propertyMemberName)
.Append(" = ")
.AppendNativeVariantToManagedExpr("value", propertyTypeSymbol, propertyMarshalType)
@@ -303,6 +304,7 @@ namespace Godot.SourceGenerators
private static void GeneratePropertyGetter(
string propertyMemberName,
+ ITypeSymbol propertyTypeSymbol,
MarshalType propertyMarshalType,
StringBuilder source,
bool isFirstEntry
@@ -317,7 +319,8 @@ namespace Godot.SourceGenerators
.Append(propertyMemberName)
.Append(") {\n")
.Append(" value = ")
- .AppendManagedToNativeVariantExpr(propertyMemberName, propertyMarshalType)
+ .AppendManagedToNativeVariantExpr("this." + propertyMemberName,
+ propertyTypeSymbol, propertyMarshalType)
.Append(";\n")
.Append(" return true;\n")
.Append(" }\n");
@@ -340,15 +343,15 @@ namespace Godot.SourceGenerators
private static void AppendPropertyInfo(StringBuilder source, PropertyInfo propertyInfo)
{
- source.Append(" properties.Add(new(type: (Godot.Variant.Type)")
+ source.Append(" properties.Add(new(type: (global::Godot.Variant.Type)")
.Append((int)propertyInfo.Type)
.Append(", name: PropertyName.")
.Append(propertyInfo.Name)
- .Append(", hint: (Godot.PropertyHint)")
+ .Append(", hint: (global::Godot.PropertyHint)")
.Append((int)propertyInfo.Hint)
.Append(", hintString: \"")
.Append(propertyInfo.HintString)
- .Append("\", usage: (Godot.PropertyUsageFlags)")
+ .Append("\", usage: (global::Godot.PropertyUsageFlags)")
.Append((int)propertyInfo.Usage)
.Append(", exported: ")
.Append(propertyInfo.Exported ? "true" : "false")
@@ -376,7 +379,8 @@ namespace Godot.SourceGenerators
if (propertyUsage != PropertyUsageFlags.Category && attr.ConstructorArguments.Length > 1)
hintString = attr.ConstructorArguments[1].Value?.ToString();
- yield return new PropertyInfo(VariantType.Nil, name, PropertyHint.None, hintString, propertyUsage.Value, true);
+ yield return new PropertyInfo(VariantType.Nil, name, PropertyHint.None, hintString,
+ propertyUsage.Value, true);
}
}
}
@@ -403,7 +407,7 @@ namespace Godot.SourceGenerators
return null;
}
- if (propertySymbol.SetMethod == null)
+ if (propertySymbol.SetMethod == null || propertySymbol.SetMethod.IsInitOnly)
{
// This should never happen, as we filtered ReadOnly properties, but just in case.
Common.ReportExportedMemberIsReadOnly(context, propertySymbol);
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertyDefValGenerator.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertyDefValGenerator.cs
index 98b9745c16..99a4c95e73 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertyDefValGenerator.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertyDefValGenerator.cs
@@ -2,6 +2,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Text;
@@ -66,21 +67,17 @@ namespace Godot.SourceGenerators
{
INamespaceSymbol namespaceSymbol = symbol.ContainingNamespace;
string classNs = namespaceSymbol != null && !namespaceSymbol.IsGlobalNamespace ?
- namespaceSymbol.FullQualifiedName() :
+ namespaceSymbol.FullQualifiedNameOmitGlobal() :
string.Empty;
bool hasNamespace = classNs.Length != 0;
bool isInnerClass = symbol.ContainingType != null;
- string uniqueHint = symbol.FullQualifiedName().SanitizeQualifiedNameForUniqueHint()
+ string uniqueHint = symbol.FullQualifiedNameOmitGlobal().SanitizeQualifiedNameForUniqueHint()
+ "_ScriptPropertyDefVal.generated";
var source = new StringBuilder();
- source.Append("using Godot;\n");
- source.Append("using Godot.NativeInterop;\n");
- source.Append("\n");
-
if (hasNamespace)
{
source.Append("namespace ");
@@ -141,14 +138,14 @@ namespace Godot.SourceGenerators
}
// TODO: We should still restore read-only properties after reloading assembly. Two possible ways: reflection or turn RestoreGodotObjectData into a constructor overload.
- // Ignore properties without a getter or without a setter. Godot properties must be both readable and writable.
+ // Ignore properties without a getter, without a setter or with an init-only setter. Godot properties must be both readable and writable.
if (property.IsWriteOnly)
{
Common.ReportExportedMemberIsWriteOnly(context, property);
continue;
}
- if (property.IsReadOnly)
+ if (property.IsReadOnly || property.SetMethod!.IsInitOnly)
{
Common.ReportExportedMemberIsReadOnly(context, property);
continue;
@@ -163,14 +160,71 @@ namespace Godot.SourceGenerators
continue;
}
- // TODO: Detect default value from simple property getters (currently we only detect from initializers)
-
- EqualsValueClauseSyntax? initializer = property.DeclaringSyntaxReferences
- .Select(r => r.GetSyntax() as PropertyDeclarationSyntax)
- .Select(s => s?.Initializer ?? null)
- .FirstOrDefault();
+ var propertyDeclarationSyntax = property.DeclaringSyntaxReferences
+ .Select(r => r.GetSyntax() as PropertyDeclarationSyntax).FirstOrDefault();
- string? value = initializer?.Value.ToString();
+ // Fully qualify the value to avoid issues with namespaces.
+ string? value = null;
+ if (propertyDeclarationSyntax != null)
+ {
+ if (propertyDeclarationSyntax.Initializer != null)
+ {
+ var sm = context.Compilation.GetSemanticModel(propertyDeclarationSyntax.Initializer.SyntaxTree);
+ value = propertyDeclarationSyntax.Initializer.Value.FullQualifiedSyntax(sm);
+ }
+ else
+ {
+ var propertyGet = propertyDeclarationSyntax.AccessorList?.Accessors
+ .Where(a => a.Keyword.IsKind(SyntaxKind.GetKeyword)).FirstOrDefault();
+ if (propertyGet != null)
+ {
+ if (propertyGet.ExpressionBody != null)
+ {
+ if (propertyGet.ExpressionBody.Expression is IdentifierNameSyntax identifierNameSyntax)
+ {
+ var sm = context.Compilation.GetSemanticModel(identifierNameSyntax.SyntaxTree);
+ var fieldSymbol = sm.GetSymbolInfo(identifierNameSyntax).Symbol as IFieldSymbol;
+ EqualsValueClauseSyntax? initializer = fieldSymbol?.DeclaringSyntaxReferences
+ .Select(r => r.GetSyntax())
+ .OfType<VariableDeclaratorSyntax>()
+ .Select(s => s.Initializer)
+ .FirstOrDefault(i => i != null);
+
+ if (initializer != null)
+ {
+ sm = context.Compilation.GetSemanticModel(initializer.SyntaxTree);
+ value = initializer.Value.FullQualifiedSyntax(sm);
+ }
+ }
+ }
+ else
+ {
+ var returns = propertyGet.DescendantNodes().OfType<ReturnStatementSyntax>();
+ if (returns.Count() == 1)
+ {
+ // Generate only single return
+ var returnStatementSyntax = returns.Single();
+ if (returnStatementSyntax.Expression is IdentifierNameSyntax identifierNameSyntax)
+ {
+ var sm = context.Compilation.GetSemanticModel(identifierNameSyntax.SyntaxTree);
+ var fieldSymbol = sm.GetSymbolInfo(identifierNameSyntax).Symbol as IFieldSymbol;
+ EqualsValueClauseSyntax? initializer = fieldSymbol?.DeclaringSyntaxReferences
+ .Select(r => r.GetSyntax())
+ .OfType<VariableDeclaratorSyntax>()
+ .Select(s => s.Initializer)
+ .FirstOrDefault(i => i != null);
+
+ if (initializer != null)
+ {
+ sm = context.Compilation.GetSemanticModel(initializer.SyntaxTree);
+ value = initializer.Value.FullQualifiedSyntax(sm);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
exportedMembers.Add(new ExportedPropertyMetadata(
property.Name, marshalType.Value, propertyType, value));
@@ -207,7 +261,13 @@ namespace Godot.SourceGenerators
.Select(s => s.Initializer)
.FirstOrDefault(i => i != null);
- string? value = initializer?.Value.ToString();
+ // This needs to be fully qualified to avoid issues with namespaces.
+ string? value = null;
+ if (initializer != null)
+ {
+ var sm = context.Compilation.GetSemanticModel(initializer.SyntaxTree);
+ value = initializer.Value.FullQualifiedSyntax(sm);
+ }
exportedMembers.Add(new ExportedPropertyMetadata(
field.Name, marshalType.Value, fieldType, value));
@@ -219,7 +279,8 @@ namespace Godot.SourceGenerators
{
source.Append("#pragma warning disable CS0109 // Disable warning about redundant 'new' keyword\n");
- string dictionaryType = "System.Collections.Generic.Dictionary<StringName, object>";
+ string dictionaryType =
+ "global::System.Collections.Generic.Dictionary<global::Godot.StringName, global::Godot.Variant>";
source.Append("#if TOOLS\n");
source.Append(" internal new static ");
@@ -237,7 +298,7 @@ namespace Godot.SourceGenerators
string defaultValueLocalName = string.Concat("__", exportedMember.Name, "_default_value");
source.Append(" ");
- source.Append(exportedMember.TypeSymbol.FullQualifiedName());
+ source.Append(exportedMember.TypeSymbol.FullQualifiedNameIncludeGlobal());
source.Append(" ");
source.Append(defaultValueLocalName);
source.Append(" = ");
@@ -246,7 +307,8 @@ namespace Godot.SourceGenerators
source.Append(" values.Add(PropertyName.");
source.Append(exportedMember.Name);
source.Append(", ");
- source.Append(defaultValueLocalName);
+ source.AppendManagedToVariantExpr(defaultValueLocalName,
+ exportedMember.TypeSymbol, exportedMember.Type);
source.Append(");\n");
}
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSerializationGenerator.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSerializationGenerator.cs
index 11e0a6fa21..821f3af75f 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSerializationGenerator.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSerializationGenerator.cs
@@ -66,13 +66,13 @@ namespace Godot.SourceGenerators
{
INamespaceSymbol namespaceSymbol = symbol.ContainingNamespace;
string classNs = namespaceSymbol != null && !namespaceSymbol.IsGlobalNamespace ?
- namespaceSymbol.FullQualifiedName() :
+ namespaceSymbol.FullQualifiedNameOmitGlobal() :
string.Empty;
bool hasNamespace = classNs.Length != 0;
bool isInnerClass = symbol.ContainingType != null;
- string uniqueHint = symbol.FullQualifiedName().SanitizeQualifiedNameForUniqueHint()
+ string uniqueHint = symbol.FullQualifiedNameOmitGlobal().SanitizeQualifiedNameForUniqueHint()
+ "_ScriptSerialization.generated";
var source = new StringBuilder();
@@ -162,7 +162,8 @@ namespace Godot.SourceGenerators
source.Append(" info.AddProperty(PropertyName.")
.Append(propertyName)
.Append(", ")
- .AppendManagedToVariantExpr(string.Concat("this.", propertyName), property.Type)
+ .AppendManagedToVariantExpr(string.Concat("this.", propertyName),
+ property.PropertySymbol.Type, property.Type)
.Append(");\n");
}
@@ -175,7 +176,8 @@ namespace Godot.SourceGenerators
source.Append(" info.AddProperty(PropertyName.")
.Append(fieldName)
.Append(", ")
- .AppendManagedToVariantExpr(string.Concat("this.", fieldName), field.Type)
+ .AppendManagedToVariantExpr(string.Concat("this.", fieldName),
+ field.FieldSymbol.Type, field.Type)
.Append(");\n");
}
@@ -241,7 +243,7 @@ namespace Godot.SourceGenerators
foreach (var signalDelegate in godotSignalDelegates)
{
string signalName = signalDelegate.Name;
- string signalDelegateQualifiedName = signalDelegate.DelegateSymbol.FullQualifiedName();
+ string signalDelegateQualifiedName = signalDelegate.DelegateSymbol.FullQualifiedNameIncludeGlobal();
source.Append(" if (info.TryGetSignalEventDelegate<")
.Append(signalDelegateQualifiedName)
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSignalsGenerator.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSignalsGenerator.cs
index 50196b84f0..ba6c10aa31 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSignalsGenerator.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSignalsGenerator.cs
@@ -75,13 +75,13 @@ namespace Godot.SourceGenerators
{
INamespaceSymbol namespaceSymbol = symbol.ContainingNamespace;
string classNs = namespaceSymbol != null && !namespaceSymbol.IsGlobalNamespace ?
- namespaceSymbol.FullQualifiedName() :
+ namespaceSymbol.FullQualifiedNameOmitGlobal() :
string.Empty;
bool hasNamespace = classNs.Length != 0;
bool isInnerClass = symbol.ContainingType != null;
- string uniqueHint = symbol.FullQualifiedName().SanitizeQualifiedNameForUniqueHint()
+ string uniqueHint = symbol.FullQualifiedNameOmitGlobal().SanitizeQualifiedNameForUniqueHint()
+ "_ScriptSignals.generated";
var source = new StringBuilder();
@@ -176,14 +176,15 @@ namespace Godot.SourceGenerators
source.Append("#pragma warning disable CS0109 // Disable warning about redundant 'new' keyword\n");
- source.Append($" public new class SignalName : {symbol.BaseType.FullQualifiedName()}.SignalName {{\n");
+ source.Append(
+ $" public new class SignalName : {symbol.BaseType.FullQualifiedNameIncludeGlobal()}.SignalName {{\n");
// Generate cached StringNames for methods and properties, for fast lookup
foreach (var signalDelegate in godotSignalDelegates)
{
string signalName = signalDelegate.Name;
- source.Append(" public new static readonly StringName ");
+ source.Append(" public new static readonly global::Godot.StringName ");
source.Append(signalName);
source.Append(" = \"");
source.Append(signalName);
@@ -196,7 +197,7 @@ namespace Godot.SourceGenerators
if (godotSignalDelegates.Count > 0)
{
- const string listType = "System.Collections.Generic.List<global::Godot.Bridge.MethodInfo>";
+ const string listType = "global::System.Collections.Generic.List<global::Godot.Bridge.MethodInfo>";
source.Append(" internal new static ")
.Append(listType)
@@ -231,15 +232,16 @@ namespace Godot.SourceGenerators
// as it doesn't emit the signal, only the event delegates. This can confuse users.
// Maybe we should directly connect the delegates, as we do with native signals?
source.Append(" private ")
- .Append(signalDelegate.DelegateSymbol.FullQualifiedName())
+ .Append(signalDelegate.DelegateSymbol.FullQualifiedNameIncludeGlobal())
.Append(" backing_")
.Append(signalName)
.Append(";\n");
- source.Append($" /// <inheritdoc cref=\"{signalDelegate.DelegateSymbol.FullQualifiedName()}\"/>\n");
+ source.Append(
+ $" /// <inheritdoc cref=\"{signalDelegate.DelegateSymbol.FullQualifiedNameIncludeGlobal()}\"/>\n");
source.Append(" public event ")
- .Append(signalDelegate.DelegateSymbol.FullQualifiedName())
+ .Append(signalDelegate.DelegateSymbol.FullQualifiedNameIncludeGlobal())
.Append(" ")
.Append(signalName)
.Append(" {\n")
@@ -300,7 +302,7 @@ namespace Godot.SourceGenerators
AppendPropertyInfo(source, methodInfo.ReturnVal);
- source.Append(", flags: (Godot.MethodFlags)")
+ source.Append(", flags: (global::Godot.MethodFlags)")
.Append((int)methodInfo.Flags)
.Append(", arguments: ");
@@ -328,15 +330,15 @@ namespace Godot.SourceGenerators
private static void AppendPropertyInfo(StringBuilder source, PropertyInfo propertyInfo)
{
- source.Append("new(type: (Godot.Variant.Type)")
+ source.Append("new(type: (global::Godot.Variant.Type)")
.Append((int)propertyInfo.Type)
.Append(", name: \"")
.Append(propertyInfo.Name)
- .Append("\", hint: (Godot.PropertyHint)")
+ .Append("\", hint: (global::Godot.PropertyHint)")
.Append((int)propertyInfo.Hint)
.Append(", hintString: \"")
.Append(propertyInfo.HintString)
- .Append("\", usage: (Godot.PropertyUsageFlags)")
+ .Append("\", usage: (global::Godot.PropertyUsageFlags)")
.Append((int)propertyInfo.Usage)
.Append(", exported: ")
.Append(propertyInfo.Exported ? "true" : "false")
@@ -351,7 +353,7 @@ namespace Godot.SourceGenerators
if (invokeMethodData.RetType != null)
{
- returnVal = DeterminePropertyInfo(invokeMethodData.RetType.Value, name: string.Empty);
+ returnVal = DeterminePropertyInfo(invokeMethodData.RetType.Value.MarshalType, name: string.Empty);
}
else
{
diff --git a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/Utils/SemaphoreExtensions.cs b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/Utils/SemaphoreExtensions.cs
index 9d593fbf8a..ab21527344 100644
--- a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/Utils/SemaphoreExtensions.cs
+++ b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/Utils/SemaphoreExtensions.cs
@@ -13,7 +13,7 @@ namespace GodotTools.IdeMessaging.Utils
return waitAsyncTask.ContinueWith<IDisposable>(t => wrapper, cancellationToken).ConfigureAwait(false);
}
- private struct SemaphoreSlimWaitReleaseWrapper : IDisposable
+ private readonly struct SemaphoreSlimWaitReleaseWrapper : IDisposable
{
private readonly SemaphoreSlim semaphoreSlim;
diff --git a/modules/mono/editor/GodotTools/GodotTools/Export/AotBuilder.cs b/modules/mono/editor/GodotTools/GodotTools/Export/AotBuilder.cs
index 2184cae6d6..94efcba3f1 100644
--- a/modules/mono/editor/GodotTools/GodotTools/Export/AotBuilder.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/Export/AotBuilder.cs
@@ -22,7 +22,7 @@ namespace GodotTools.Export
public bool FullAot;
private bool _useInterpreter;
- public bool UseInterpreter { get => _useInterpreter && !LLVMOnly; set => _useInterpreter = value; }
+ public bool UseInterpreter { readonly get => _useInterpreter && !LLVMOnly; set => _useInterpreter = value; }
public string[] ExtraAotOptions;
public string[] ExtraOptimizerOptions;
diff --git a/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs b/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs
index 89364d1c02..de10c04e31 100644
--- a/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs
@@ -57,24 +57,22 @@ namespace GodotTools
{
pr.Step("Generating C# project...".TTR());
- string resourceDir = ProjectSettings.GlobalizePath("res://");
-
- string path = resourceDir;
+ string csprojDir = Path.GetDirectoryName(GodotSharpDirs.ProjectCsProjPath);
+ string slnDir = Path.GetDirectoryName(GodotSharpDirs.ProjectSlnPath);
string name = GodotSharpDirs.ProjectAssemblyName;
-
- string guid = CsProjOperations.GenerateGameProject(path, name);
+ string guid = CsProjOperations.GenerateGameProject(csprojDir, name);
if (guid.Length > 0)
{
var solution = new DotNetSolution(name)
{
- DirectoryPath = path
+ DirectoryPath = slnDir
};
var projectInfo = new DotNetSolution.ProjectInfo
{
Guid = guid,
- PathRelativeToSolution = name + ".csproj",
+ PathRelativeToSolution = Path.GetRelativePath(slnDir, GodotSharpDirs.ProjectCsProjPath),
Configs = new List<string> { "Debug", "ExportDebug", "ExportRelease" }
};
@@ -375,6 +373,8 @@ namespace GodotTools
{
base._EnablePlugin();
+ ProjectSettingsChanged += GodotSharpDirs.DetermineProjectLocation;
+
if (Instance != null)
throw new InvalidOperationException();
Instance = this;
@@ -455,7 +455,7 @@ namespace GodotTools
_menuPopup.IdPressed += _MenuOptionPressed;
// External editor settings
- EditorDef("mono/editor/external_editor", ExternalEditorId.None);
+ EditorDef("mono/editor/external_editor", Variant.From(ExternalEditorId.None));
string settingsHintStr = "Disabled";
diff --git a/modules/mono/editor/GodotTools/GodotTools/Internals/Globals.cs b/modules/mono/editor/GodotTools/GodotTools/Internals/Globals.cs
index acb7cc3ab0..45ae7eb86b 100644
--- a/modules/mono/editor/GodotTools/GodotTools/Internals/Globals.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/Internals/Globals.cs
@@ -1,3 +1,4 @@
+using Godot;
using Godot.NativeInterop;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
@@ -8,30 +9,31 @@ namespace GodotTools.Internals
{
public static float EditorScale => Internal.godot_icall_Globals_EditorScale();
- public static unsafe object GlobalDef(string setting, object defaultValue, bool restartIfChanged = false)
+ // ReSharper disable once UnusedMethodReturnValue.Global
+ public static Variant GlobalDef(string setting, Variant defaultValue, bool restartIfChanged = false)
{
using godot_string settingIn = Marshaling.ConvertStringToNative(setting);
- using godot_variant defaultValueIn = Marshaling.ConvertManagedObjectToVariant(defaultValue);
- Internal.godot_icall_Globals_GlobalDef(settingIn, defaultValueIn, restartIfChanged, out godot_variant result);
- using (result)
- return Marshaling.ConvertVariantToManagedObject(result);
+ using godot_variant defaultValueIn = defaultValue.CopyNativeVariant();
+ Internal.godot_icall_Globals_GlobalDef(settingIn, defaultValueIn, restartIfChanged,
+ out godot_variant result);
+ return Variant.CreateTakingOwnershipOfDisposableValue(result);
}
- public static unsafe object EditorDef(string setting, object defaultValue, bool restartIfChanged = false)
+ // ReSharper disable once UnusedMethodReturnValue.Global
+ public static Variant EditorDef(string setting, Variant defaultValue, bool restartIfChanged = false)
{
using godot_string settingIn = Marshaling.ConvertStringToNative(setting);
- using godot_variant defaultValueIn = Marshaling.ConvertManagedObjectToVariant(defaultValue);
- Internal.godot_icall_Globals_EditorDef(settingIn, defaultValueIn, restartIfChanged, out godot_variant result);
- using (result)
- return Marshaling.ConvertVariantToManagedObject(result);
+ using godot_variant defaultValueIn = defaultValue.CopyNativeVariant();
+ Internal.godot_icall_Globals_EditorDef(settingIn, defaultValueIn, restartIfChanged,
+ out godot_variant result);
+ return Variant.CreateTakingOwnershipOfDisposableValue(result);
}
- public static object EditorShortcut(string setting)
+ public static Variant EditorShortcut(string setting)
{
using godot_string settingIn = Marshaling.ConvertStringToNative(setting);
Internal.godot_icall_Globals_EditorShortcut(settingIn, out godot_variant result);
- using (result)
- return Marshaling.ConvertVariantToManagedObject(result);
+ return Variant.CreateTakingOwnershipOfDisposableValue(result);
}
[SuppressMessage("ReSharper", "InconsistentNaming")]
diff --git a/modules/mono/editor/GodotTools/GodotTools/Internals/GodotSharpDirs.cs b/modules/mono/editor/GodotTools/GodotTools/Internals/GodotSharpDirs.cs
index 14285cc0f1..4e892be55c 100644
--- a/modules/mono/editor/GodotTools/GodotTools/Internals/GodotSharpDirs.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/Internals/GodotSharpDirs.cs
@@ -52,10 +52,9 @@ namespace GodotTools.Internals
{
GlobalDef("dotnet/project/assembly_name", "");
GlobalDef("dotnet/project/solution_directory", "");
- GlobalDef("dotnet/project/c#_project_directory", "");
}
- private static void DetermineProjectLocation()
+ public static void DetermineProjectLocation()
{
static string DetermineProjectName()
{
@@ -76,10 +75,11 @@ namespace GodotTools.Internals
string slnParentDir = (string)ProjectSettings.GetSetting("dotnet/project/solution_directory");
if (string.IsNullOrEmpty(slnParentDir))
slnParentDir = "res://";
+ else if (!slnParentDir.StartsWith("res://"))
+ slnParentDir = "res://" + slnParentDir;
- string csprojParentDir = (string)ProjectSettings.GetSetting("dotnet/project/c#_project_directory");
- if (string.IsNullOrEmpty(csprojParentDir))
- csprojParentDir = "res://";
+ // The csproj should be in the same folder as project.godot.
+ string csprojParentDir = "res://";
_projectSlnPath = Path.Combine(ProjectSettings.GlobalizePath(slnParentDir),
string.Concat(_projectAssemblyName, ".sln"));
diff --git a/modules/mono/editor/GodotTools/GodotTools/PlaySettings.cs b/modules/mono/editor/GodotTools/GodotTools/PlaySettings.cs
index 820d0c0b83..9a8fdcc7c5 100644
--- a/modules/mono/editor/GodotTools/GodotTools/PlaySettings.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/PlaySettings.cs
@@ -1,6 +1,6 @@
namespace GodotTools
{
- public struct PlaySettings
+ public readonly struct PlaySettings
{
public bool HasDebugger { get; }
public string DebuggerHost { get; }
diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp
index b90321b586..6cfdb15627 100644
--- a/modules/mono/editor/bindings_generator.cpp
+++ b/modules/mono/editor/bindings_generator.cpp
@@ -2274,7 +2274,7 @@ Error BindingsGenerator::_generate_cs_signal(const BindingsGenerator::TypeInterf
p_output.append(");\n");
// Generate Callable trampoline for the delegate
- p_output << MEMBER_BEGIN "private static unsafe void " << p_isignal.proxy_name << "Trampoline"
+ p_output << MEMBER_BEGIN "private static void " << p_isignal.proxy_name << "Trampoline"
<< "(object delegateObj, NativeVariantPtrArgs args, out godot_variant ret)\n"
<< INDENT1 "{\n"
<< INDENT2 "Callable.ThrowIfArgCountMismatch(args, " << itos(p_isignal.arguments.size()) << ");\n"
@@ -2289,9 +2289,8 @@ Error BindingsGenerator::_generate_cs_signal(const BindingsGenerator::TypeInterf
p_output << ",";
}
- // TODO: We don't need to use VariantConversionCallbacks. We have the type information so we can use [cs_variant_to_managed] and [cs_managed_to_variant].
- p_output << "\n" INDENT3 "VariantConversionCallbacks.GetToManagedCallback<"
- << arg_type->cs_type << ">()(args[" << itos(idx) << "])";
+ p_output << sformat(arg_type->cs_variant_to_managed,
+ "args[" + itos(idx) + "]", arg_type->cs_type, arg_type->name);
idx++;
}
@@ -2490,9 +2489,12 @@ Error BindingsGenerator::_generate_cs_native_calls(const InternalCall &p_icall,
if (!ret_void) {
if (return_type->cname != name_cache.type_Variant) {
+ // Usually the return value takes ownership, but in this case the variant is only used
+ // for conversion to another return type. As such, the local variable takes ownership.
r_output << "using godot_variant " << C_LOCAL_VARARG_RET " = ";
} else {
- r_output << "using godot_variant " << C_LOCAL_RET " = ";
+ // Variant's [c_out] takes ownership of the variant value
+ r_output << "godot_variant " << C_LOCAL_RET " = ";
}
}
@@ -2543,15 +2545,13 @@ Error BindingsGenerator::_generate_cs_native_calls(const InternalCall &p_icall,
<< INDENT2 "int total_length = " << real_argc_str << " + vararg_length;\n";
r_output << INDENT2 "Span<godot_variant.movable> varargs_span = vararg_length <= VarArgsSpanThreshold ?\n"
- << INDENT3 "stackalloc godot_variant.movable[VarArgsSpanThreshold].Cleared() :\n"
+ << INDENT3 "stackalloc godot_variant.movable[VarArgsSpanThreshold] :\n"
<< INDENT3 "new godot_variant.movable[vararg_length];\n";
r_output << INDENT2 "Span<IntPtr> " C_LOCAL_PTRCALL_ARGS "_span = total_length <= VarArgsSpanThreshold ?\n"
<< INDENT3 "stackalloc IntPtr[VarArgsSpanThreshold] :\n"
<< INDENT3 "new IntPtr[total_length];\n";
- r_output << INDENT2 "using var variantSpanDisposer = new VariantSpanDisposer(varargs_span);\n";
-
r_output << INDENT2 "fixed (godot_variant.movable* varargs = &MemoryMarshal.GetReference(varargs_span))\n"
<< INDENT2 "fixed (IntPtr* " C_LOCAL_PTRCALL_ARGS " = "
"&MemoryMarshal.GetReference(" C_LOCAL_PTRCALL_ARGS "_span))\n"
@@ -2840,9 +2840,6 @@ bool BindingsGenerator::_populate_object_type_interfaces() {
itype.is_ref_counted = ClassDB::is_parent_class(type_cname, name_cache.type_RefCounted);
itype.memory_own = itype.is_ref_counted;
- itype.cs_variant_to_managed = "(%1)VariantUtils.ConvertToGodotObject(%0)";
- itype.cs_managed_to_variant = "VariantUtils.CreateFromGodotObject(%0)";
-
itype.c_out = "%5return ";
itype.c_out += C_METHOD_UNMANAGED_GET_MANAGED;
itype.c_out += itype.is_ref_counted ? "(%1.Reference);\n" : "(%1);\n";
@@ -3221,8 +3218,6 @@ bool BindingsGenerator::_populate_object_type_interfaces() {
enum_itype.cname = StringName(enum_itype.name);
enum_itype.proxy_name = itype.proxy_name + "." + enum_proxy_name;
TypeInterface::postsetup_enum_type(enum_itype);
- enum_itype.cs_variant_to_managed = "(%1)VariantUtils.ConvertToInt32(%0)";
- enum_itype.cs_managed_to_variant = "VariantUtils.CreateFromInt((int)%0)";
enum_types.insert(enum_itype.cname, enum_itype);
}
@@ -3451,16 +3446,14 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
TypeInterface itype;
-#define INSERT_STRUCT_TYPE(m_type) \
- { \
- itype = TypeInterface::create_value_type(String(#m_type)); \
- itype.c_type_in = #m_type "*"; \
- itype.c_type_out = itype.cs_type; \
- itype.cs_in_expr = "&%0"; \
- itype.cs_in_expr_is_unsafe = true; \
- itype.cs_variant_to_managed = "VariantUtils.ConvertTo%2(%0)"; \
- itype.cs_managed_to_variant = "VariantUtils.CreateFrom%2(%0)"; \
- builtin_types.insert(itype.cname, itype); \
+#define INSERT_STRUCT_TYPE(m_type) \
+ { \
+ itype = TypeInterface::create_value_type(String(#m_type)); \
+ itype.c_type_in = #m_type "*"; \
+ itype.c_type_out = itype.cs_type; \
+ itype.cs_in_expr = "&%0"; \
+ itype.cs_in_expr_is_unsafe = true; \
+ builtin_types.insert(itype.cname, itype); \
}
INSERT_STRUCT_TYPE(Vector2)
@@ -3491,8 +3484,6 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
itype.c_type_out = itype.c_type;
itype.c_arg_in = "&%s";
itype.c_in_vararg = "%5using godot_variant %1_in = VariantUtils.CreateFromBool(%1);\n";
- itype.cs_variant_to_managed = "VariantUtils.ConvertToBool(%0)";
- itype.cs_managed_to_variant = "VariantUtils.CreateFromBool(%0)";
builtin_types.insert(itype.cname, itype);
// Integer types
@@ -3513,8 +3504,6 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
itype.c_type_in = itype.name; \
itype.c_type_out = itype.name; \
itype.c_in_vararg = "%5using godot_variant %1_in = VariantUtils.CreateFromInt(%1);\n"; \
- itype.cs_variant_to_managed = "VariantUtils.ConvertTo" m_int_struct_name "(%0)"; \
- itype.cs_managed_to_variant = "VariantUtils.CreateFromInt(%0)"; \
builtin_types.insert(itype.cname, itype); \
}
@@ -3550,8 +3539,6 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
itype.c_type_in = itype.proxy_name;
itype.c_type_out = itype.proxy_name;
itype.c_in_vararg = "%5using godot_variant %1_in = VariantUtils.CreateFromFloat(%1);\n";
- itype.cs_variant_to_managed = "VariantUtils.ConvertToFloat32(%0)";
- itype.cs_managed_to_variant = "VariantUtils.CreateFromFloat(%0)";
builtin_types.insert(itype.cname, itype);
// double
@@ -3565,8 +3552,6 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
itype.c_type_in = itype.proxy_name;
itype.c_type_out = itype.proxy_name;
itype.c_in_vararg = "%5using godot_variant %1_in = VariantUtils.CreateFromFloat(%1);\n";
- itype.cs_variant_to_managed = "VariantUtils.ConvertToFloat64(%0)";
- itype.cs_managed_to_variant = "VariantUtils.CreateFromFloat(%0)";
builtin_types.insert(itype.cname, itype);
}
@@ -3584,8 +3569,6 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
itype.c_type_out = itype.cs_type;
itype.c_type_is_disposable_struct = true;
itype.c_in_vararg = "%5using godot_variant %1_in = VariantUtils.CreateFromString(%1);\n";
- itype.cs_variant_to_managed = "VariantUtils.ConvertToStringObject(%0)";
- itype.cs_managed_to_variant = "VariantUtils.CreateFromString(%0)";
builtin_types.insert(itype.cname, itype);
// StringName
@@ -3604,8 +3587,6 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
itype.c_in_vararg = "%5using godot_variant %1_in = VariantUtils.CreateFromStringName(%1);\n";
itype.c_type_is_disposable_struct = false; // [c_out] takes ownership
itype.c_ret_needs_default_initialization = true;
- itype.cs_variant_to_managed = "VariantUtils.ConvertToStringNameObject(%0)";
- itype.cs_managed_to_variant = "VariantUtils.CreateFromStringName(%0)";
builtin_types.insert(itype.cname, itype);
// NodePath
@@ -3623,8 +3604,6 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
itype.c_type_out = itype.cs_type;
itype.c_type_is_disposable_struct = false; // [c_out] takes ownership
itype.c_ret_needs_default_initialization = true;
- itype.cs_variant_to_managed = "VariantUtils.ConvertToNodePathObject(%0)";
- itype.cs_managed_to_variant = "VariantUtils.CreateFromNodePath(%0)";
builtin_types.insert(itype.cname, itype);
// RID
@@ -3637,8 +3616,6 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
itype.c_type = itype.cs_type;
itype.c_type_in = itype.c_type;
itype.c_type_out = itype.c_type;
- itype.cs_variant_to_managed = "VariantUtils.ConvertToRID(%0)";
- itype.cs_managed_to_variant = "VariantUtils.CreateFromRID(%0)";
builtin_types.insert(itype.cname, itype);
// Variant
@@ -3655,8 +3632,6 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
itype.c_type_out = itype.cs_type;
itype.c_type_is_disposable_struct = false; // [c_out] takes ownership
itype.c_ret_needs_default_initialization = true;
- itype.cs_variant_to_managed = "Variant.CreateCopyingBorrowed(%0)";
- itype.cs_managed_to_variant = "%0.CopyNativeVariant()";
builtin_types.insert(itype.cname, itype);
// Callable
@@ -3669,26 +3644,22 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
itype.c_type_in = "in " + itype.cs_type;
itype.c_type_out = itype.cs_type;
itype.c_type_is_disposable_struct = true;
- itype.cs_variant_to_managed = "VariantUtils.ConvertToCallableManaged(%0)";
- itype.cs_managed_to_variant = "VariantUtils.CreateFromCallable(%0)";
builtin_types.insert(itype.cname, itype);
// Signal
itype = TypeInterface();
itype.name = "Signal";
itype.cname = itype.name;
- itype.proxy_name = "SignalInfo";
+ itype.proxy_name = "Signal";
itype.cs_type = itype.proxy_name;
itype.cs_in_expr = "%0";
itype.c_in = "%5using %0 %1_in = " C_METHOD_MANAGED_TO_SIGNAL "(in %1);\n";
- itype.c_out = "%5return " C_METHOD_MANAGED_FROM_SIGNAL "(&%1);\n";
+ itype.c_out = "%5return " C_METHOD_MANAGED_FROM_SIGNAL "(in %1);\n";
itype.c_arg_in = "&%s_in";
itype.c_type = "godot_signal";
itype.c_type_in = "in " + itype.cs_type;
itype.c_type_out = itype.cs_type;
itype.c_type_is_disposable_struct = true;
- itype.cs_variant_to_managed = "VariantUtils.ConvertToSignalInfo(%0)";
- itype.cs_managed_to_variant = "VariantUtils.CreateFromSignalInfo(%0)";
builtin_types.insert(itype.cname, itype);
// VarArg (fictitious type to represent variable arguments)
@@ -3718,8 +3689,6 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
itype.c_type_in = itype.proxy_name; \
itype.c_type_out = itype.proxy_name; \
itype.c_type_is_disposable_struct = true; \
- itype.cs_variant_to_managed = "VariantUtils.ConvertAs%2ToSystemArray(%0)"; \
- itype.cs_managed_to_variant = "VariantUtils.CreateFrom%2(%0)"; \
builtin_types.insert(itype.name, itype); \
}
@@ -3755,8 +3724,6 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
itype.c_type_out = itype.cs_type;
itype.c_type_is_disposable_struct = false; // [c_out] takes ownership
itype.c_ret_needs_default_initialization = true;
- itype.cs_variant_to_managed = "VariantUtils.ConvertToArrayObject(%0)";
- itype.cs_managed_to_variant = "VariantUtils.CreateFromArray(%0)";
builtin_types.insert(itype.cname, itype);
// Array_@generic
@@ -3764,6 +3731,9 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
itype.name = "Array_@generic";
itype.cname = itype.name;
itype.cs_out = "%5return new %2(%0(%1));";
+ // For generic Godot collections, Variant.From<T>/As<T> is slower, so we need this special case
+ itype.cs_variant_to_managed = "VariantUtils.ConvertToArray(%0)";
+ itype.cs_managed_to_variant = "VariantUtils.CreateFromArray(%0)";
builtin_types.insert(itype.cname, itype);
// Dictionary
@@ -3781,8 +3751,6 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
itype.c_type_out = itype.cs_type;
itype.c_type_is_disposable_struct = false; // [c_out] takes ownership
itype.c_ret_needs_default_initialization = true;
- itype.cs_variant_to_managed = "VariantUtils.ConvertToDictionaryObject(%0)";
- itype.cs_managed_to_variant = "VariantUtils.CreateFromDictionary(%0)";
builtin_types.insert(itype.cname, itype);
// Dictionary_@generic
@@ -3790,6 +3758,9 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
itype.name = "Dictionary_@generic";
itype.cname = itype.name;
itype.cs_out = "%5return new %2(%0(%1));";
+ // For generic Godot collections, Variant.From<T>/As<T> is slower, so we need this special case
+ itype.cs_variant_to_managed = "VariantUtils.ConvertToDictionary(%0)";
+ itype.cs_managed_to_variant = "VariantUtils.CreateFromDictionary(%0)";
builtin_types.insert(itype.cname, itype);
// void (fictitious type to represent the return type of methods that do not return anything)
@@ -3855,8 +3826,6 @@ void BindingsGenerator::_populate_global_constants() {
enum_itype.cname = ienum.cname;
enum_itype.proxy_name = enum_itype.name;
TypeInterface::postsetup_enum_type(enum_itype);
- enum_itype.cs_variant_to_managed = "(%1)VariantUtils.ConvertToInt32(%0)";
- enum_itype.cs_managed_to_variant = "VariantUtils.CreateFromInt((int)%0)";
enum_types.insert(enum_itype.cname, enum_itype);
int prefix_length = _determine_enum_prefix(ienum);
@@ -3889,8 +3858,6 @@ void BindingsGenerator::_populate_global_constants() {
enum_itype.cname = enum_cname;
enum_itype.proxy_name = enum_itype.name;
TypeInterface::postsetup_enum_type(enum_itype);
- enum_itype.cs_variant_to_managed = "(%1)VariantUtils.ConvertToInt32(%0)";
- enum_itype.cs_managed_to_variant = "VariantUtils.CreateFromInt((int)%0)";
enum_types.insert(enum_itype.cname, enum_itype);
}
}
diff --git a/modules/mono/editor/bindings_generator.h b/modules/mono/editor/bindings_generator.h
index a479c44368..6d172f4fb8 100644
--- a/modules/mono/editor/bindings_generator.h
+++ b/modules/mono/editor/bindings_generator.h
@@ -209,7 +209,7 @@ class BindingsGenerator {
String name;
StringName cname;
- int type_parameter_count;
+ int type_parameter_count = 0;
/**
* Identifier name of the base class.
@@ -514,7 +514,12 @@ class BindingsGenerator {
static void postsetup_enum_type(TypeInterface &r_enum_itype);
- TypeInterface() {}
+ TypeInterface() {
+ static String default_cs_variant_to_managed = "VariantUtils.ConvertTo<%1>(%0)";
+ static String default_cs_managed_to_variant = "VariantUtils.CreateFrom<%1>(%0)";
+ cs_variant_to_managed = default_cs_variant_to_managed;
+ cs_managed_to_variant = default_cs_managed_to_variant;
+ }
};
struct InternalCall {
diff --git a/modules/mono/glue/GodotSharp/Godot.SourceGenerators.Internal/CallbacksInfo.cs b/modules/mono/glue/GodotSharp/Godot.SourceGenerators.Internal/CallbacksInfo.cs
index 686023a077..ae51c07386 100644
--- a/modules/mono/glue/GodotSharp/Godot.SourceGenerators.Internal/CallbacksInfo.cs
+++ b/modules/mono/glue/GodotSharp/Godot.SourceGenerators.Internal/CallbacksInfo.cs
@@ -4,7 +4,7 @@ using Microsoft.CodeAnalysis;
namespace Godot.SourceGenerators.Internal;
-internal struct CallbacksData
+internal readonly struct CallbacksData
{
public CallbacksData(INamedTypeSymbol nativeTypeSymbol, INamedTypeSymbol funcStructSymbol)
{
diff --git a/modules/mono/glue/GodotSharp/Godot.SourceGenerators.Internal/Common.cs b/modules/mono/glue/GodotSharp/Godot.SourceGenerators.Internal/Common.cs
index 16e96c725a..d3726d69f0 100644
--- a/modules/mono/glue/GodotSharp/Godot.SourceGenerators.Internal/Common.cs
+++ b/modules/mono/glue/GodotSharp/Godot.SourceGenerators.Internal/Common.cs
@@ -12,7 +12,7 @@ internal static class Common
{
string message =
"Missing partial modifier on declaration of type '" +
- $"{symbol.FullQualifiedName()}' which has attribute '{GeneratorClasses.GenerateUnmanagedCallbacksAttr}'";
+ $"{symbol.FullQualifiedNameOmitGlobal()}' which has attribute '{GeneratorClasses.GenerateUnmanagedCallbacksAttr}'";
string description = $"{message}. Classes with attribute '{GeneratorClasses.GenerateUnmanagedCallbacksAttr}' " +
"must be declared with the partial modifier.";
@@ -39,7 +39,7 @@ internal static class Common
.GetDeclaredSymbol(outerTypeDeclSyntax);
string fullQualifiedName = outerSymbol is INamedTypeSymbol namedTypeSymbol ?
- namedTypeSymbol.FullQualifiedName() :
+ namedTypeSymbol.FullQualifiedNameOmitGlobal() :
"type not found";
string message =
diff --git a/modules/mono/glue/GodotSharp/Godot.SourceGenerators.Internal/ExtensionMethods.cs b/modules/mono/glue/GodotSharp/Godot.SourceGenerators.Internal/ExtensionMethods.cs
index fac362479a..37f7005d01 100644
--- a/modules/mono/glue/GodotSharp/Godot.SourceGenerators.Internal/ExtensionMethods.cs
+++ b/modules/mono/glue/GodotSharp/Godot.SourceGenerators.Internal/ExtensionMethods.cs
@@ -94,13 +94,6 @@ internal static class ExtensionMethods
};
}
- private static SymbolDisplayFormat FullyQualifiedFormatOmitGlobal { get; } =
- SymbolDisplayFormat.FullyQualifiedFormat
- .WithGlobalNamespaceStyle(SymbolDisplayGlobalNamespaceStyle.Omitted);
-
- public static string FullQualifiedName(this ITypeSymbol symbol)
- => symbol.ToDisplayString(NullableFlowState.NotNull, FullyQualifiedFormatOmitGlobal);
-
public static string NameWithTypeParameters(this INamedTypeSymbol symbol)
{
return symbol.IsGenericType ?
@@ -108,8 +101,25 @@ internal static class ExtensionMethods
symbol.Name;
}
- public static string FullQualifiedName(this INamespaceSymbol symbol)
- => symbol.ToDisplayString(FullyQualifiedFormatOmitGlobal);
+ private static SymbolDisplayFormat FullyQualifiedFormatOmitGlobal { get; } =
+ SymbolDisplayFormat.FullyQualifiedFormat
+ .WithGlobalNamespaceStyle(SymbolDisplayGlobalNamespaceStyle.Omitted);
+
+ private static SymbolDisplayFormat FullyQualifiedFormatIncludeGlobal { get; } =
+ SymbolDisplayFormat.FullyQualifiedFormat
+ .WithGlobalNamespaceStyle(SymbolDisplayGlobalNamespaceStyle.Included);
+
+ public static string FullQualifiedNameOmitGlobal(this ITypeSymbol symbol)
+ => symbol.ToDisplayString(NullableFlowState.NotNull, FullyQualifiedFormatOmitGlobal);
+
+ public static string FullQualifiedNameOmitGlobal(this INamespaceSymbol namespaceSymbol)
+ => namespaceSymbol.ToDisplayString(FullyQualifiedFormatOmitGlobal);
+
+ public static string FullQualifiedNameIncludeGlobal(this ITypeSymbol symbol)
+ => symbol.ToDisplayString(NullableFlowState.NotNull, FullyQualifiedFormatIncludeGlobal);
+
+ public static string FullQualifiedNameIncludeGlobal(this INamespaceSymbol namespaceSymbol)
+ => namespaceSymbol.ToDisplayString(FullyQualifiedFormatIncludeGlobal);
public static string SanitizeQualifiedNameForUniqueHint(this string qualifiedName)
=> qualifiedName
diff --git a/modules/mono/glue/GodotSharp/Godot.SourceGenerators.Internal/UnmanagedCallbacksGenerator.cs b/modules/mono/glue/GodotSharp/Godot.SourceGenerators.Internal/UnmanagedCallbacksGenerator.cs
index da578309bc..3226ca79e5 100644
--- a/modules/mono/glue/GodotSharp/Godot.SourceGenerators.Internal/UnmanagedCallbacksGenerator.cs
+++ b/modules/mono/glue/GodotSharp/Godot.SourceGenerators.Internal/UnmanagedCallbacksGenerator.cs
@@ -96,7 +96,7 @@ internal class GenerateUnmanagedCallbacksAttribute : Attribute
INamespaceSymbol namespaceSymbol = symbol.ContainingNamespace;
string classNs = namespaceSymbol != null && !namespaceSymbol.IsGlobalNamespace ?
- namespaceSymbol.FullQualifiedName() :
+ namespaceSymbol.FullQualifiedNameOmitGlobal() :
string.Empty;
bool hasNamespace = classNs.Length != 0;
bool isInnerClass = symbol.ContainingType != null;
@@ -144,7 +144,7 @@ using Godot.NativeInterop;
source.Append("[System.Runtime.CompilerServices.SkipLocalsInit]\n");
source.Append($"unsafe partial class {symbol.Name}\n");
source.Append("{\n");
- source.Append($" private static {data.FuncStructSymbol.FullQualifiedName()} _unmanagedCallbacks;\n\n");
+ source.Append($" private static {data.FuncStructSymbol.FullQualifiedNameIncludeGlobal()} _unmanagedCallbacks;\n\n");
foreach (var callback in data.Methods)
{
@@ -159,7 +159,7 @@ using Godot.NativeInterop;
source.Append("static ");
source.Append("partial ");
- source.Append(callback.ReturnType.FullQualifiedName());
+ source.Append(callback.ReturnType.FullQualifiedNameIncludeGlobal());
source.Append(' ');
source.Append(callback.Name);
source.Append('(');
@@ -228,7 +228,7 @@ using Godot.NativeInterop;
if (!callback.ReturnsVoid)
{
if (methodSourceAfterCall.Length != 0)
- source.Append($"{callback.ReturnType.FullQualifiedName()} ret = ");
+ source.Append($"{callback.ReturnType.FullQualifiedNameIncludeGlobal()} ret = ");
else
source.Append("return ");
}
@@ -267,7 +267,7 @@ using Godot.NativeInterop;
source.Append("\n\n#pragma warning restore CA1707\n");
- context.AddSource($"{data.NativeTypeSymbol.FullQualifiedName().SanitizeQualifiedNameForUniqueHint()}.generated",
+ context.AddSource($"{data.NativeTypeSymbol.FullQualifiedNameOmitGlobal().SanitizeQualifiedNameForUniqueHint()}.generated",
SourceText.From(source.ToString(), Encoding.UTF8));
}
@@ -277,7 +277,7 @@ using Godot.NativeInterop;
INamespaceSymbol namespaceSymbol = symbol.ContainingNamespace;
string classNs = namespaceSymbol != null && !namespaceSymbol.IsGlobalNamespace ?
- namespaceSymbol.FullQualifiedName() :
+ namespaceSymbol.FullQualifiedNameOmitGlobal() :
string.Empty;
bool hasNamespace = classNs.Length != 0;
bool isInnerClass = symbol.ContainingType != null;
@@ -338,18 +338,18 @@ using Godot.NativeInterop;
// just pass it by-ref and let it be pinned.
AppendRefKind(source, parameter.RefKind)
.Append(' ')
- .Append(parameter.Type.FullQualifiedName());
+ .Append(parameter.Type.FullQualifiedNameIncludeGlobal());
}
}
else
{
- source.Append(parameter.Type.FullQualifiedName());
+ source.Append(parameter.Type.FullQualifiedNameIncludeGlobal());
}
source.Append(", ");
}
- source.Append(callback.ReturnType.FullQualifiedName());
+ source.Append(callback.ReturnType.FullQualifiedNameIncludeGlobal());
source.Append($"> {callback.Name};\n");
}
@@ -372,12 +372,12 @@ using Godot.NativeInterop;
source.Append("\n#pragma warning restore CA1707\n");
- context.AddSource($"{symbol.FullQualifiedName().SanitizeQualifiedNameForUniqueHint()}.generated",
+ context.AddSource($"{symbol.FullQualifiedNameOmitGlobal().SanitizeQualifiedNameForUniqueHint()}.generated",
SourceText.From(source.ToString(), Encoding.UTF8));
}
private static bool IsGodotInteropStruct(ITypeSymbol type) =>
- GodotInteropStructs.Contains(type.FullQualifiedName());
+ GodotInteropStructs.Contains(type.FullQualifiedNameOmitGlobal());
private static bool IsByRefParameter(IParameterSymbol parameter) =>
parameter.RefKind is RefKind.In or RefKind.Out or RefKind.Ref;
@@ -393,7 +393,7 @@ using Godot.NativeInterop;
private static void AppendPointerType(StringBuilder source, ITypeSymbol type)
{
- source.Append(type.FullQualifiedName());
+ source.Append(type.FullQualifiedNameIncludeGlobal());
source.Append('*');
}
@@ -426,7 +426,7 @@ using Godot.NativeInterop;
{
varName = $"{parameter.Name}_copy";
- source.Append(parameter.Type.FullQualifiedName());
+ source.Append(parameter.Type.FullQualifiedNameIncludeGlobal());
source.Append(' ');
source.Append(varName);
if (parameter.RefKind is RefKind.In or RefKind.Ref)
diff --git a/modules/mono/glue/GodotSharp/GodotPlugins/Main.cs b/modules/mono/glue/GodotSharp/GodotPlugins/Main.cs
index 8308bada24..4ce02d221e 100644
--- a/modules/mono/glue/GodotSharp/GodotPlugins/Main.cs
+++ b/modules/mono/glue/GodotSharp/GodotPlugins/Main.cs
@@ -28,17 +28,24 @@ namespace GodotPlugins
get => _pluginLoadContext?.AssemblyLoadedPath;
}
+ public bool IsCollectible
+ {
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ get => _pluginLoadContext?.IsCollectible ?? false;
+ }
+
[MethodImpl(MethodImplOptions.NoInlining)]
public static (Assembly, PluginLoadContextWrapper) CreateAndLoadFromAssemblyName(
AssemblyName assemblyName,
string pluginPath,
ICollection<string> sharedAssemblies,
- AssemblyLoadContext mainLoadContext
+ AssemblyLoadContext mainLoadContext,
+ bool isCollectible
)
{
var wrapper = new PluginLoadContextWrapper();
wrapper._pluginLoadContext = new PluginLoadContext(
- pluginPath, sharedAssemblies, mainLoadContext);
+ pluginPath, sharedAssemblies, mainLoadContext, isCollectible);
var assembly = wrapper._pluginLoadContext.LoadFromAssemblyName(assemblyName);
return (assembly, wrapper);
}
@@ -61,6 +68,7 @@ namespace GodotPlugins
private static readonly Assembly CoreApiAssembly = typeof(Godot.Object).Assembly;
private static Assembly? _editorApiAssembly;
private static PluginLoadContextWrapper? _projectLoadContext;
+ private static bool _editorHint = false;
private static readonly AssemblyLoadContext MainLoadContext =
AssemblyLoadContext.GetLoadContext(Assembly.GetExecutingAssembly()) ??
@@ -77,15 +85,17 @@ namespace GodotPlugins
{
try
{
+ _editorHint = editorHint.ToBool();
+
_dllImportResolver = new GodotDllImportResolver(godotDllHandle).OnResolveDllImport;
SharedAssemblies.Add(CoreApiAssembly.GetName());
NativeLibrary.SetDllImportResolver(CoreApiAssembly, _dllImportResolver);
- AlcReloadCfg.Configure(alcReloadEnabled: editorHint.ToBool());
+ AlcReloadCfg.Configure(alcReloadEnabled: _editorHint);
NativeFuncs.Initialize(unmanagedCallbacks, unmanagedCallbacksSize);
- if (editorHint.ToBool())
+ if (_editorHint)
{
_editorApiAssembly = Assembly.Load("GodotSharpEditor");
SharedAssemblies.Add(_editorApiAssembly.GetName());
@@ -128,7 +138,7 @@ namespace GodotPlugins
string assemblyPath = new(nAssemblyPath);
- (var projectAssembly, _projectLoadContext) = LoadPlugin(assemblyPath);
+ (var projectAssembly, _projectLoadContext) = LoadPlugin(assemblyPath, isCollectible: _editorHint);
string loadedAssemblyPath = _projectLoadContext.AssemblyLoadedPath ?? assemblyPath;
*outLoadedAssemblyPath = Marshaling.ConvertStringToNative(loadedAssemblyPath);
@@ -155,7 +165,7 @@ namespace GodotPlugins
if (_editorApiAssembly == null)
throw new InvalidOperationException("The Godot editor API assembly is not loaded.");
- var (assembly, _) = LoadPlugin(assemblyPath);
+ var (assembly, _) = LoadPlugin(assemblyPath, isCollectible: _editorHint);
NativeLibrary.SetDllImportResolver(assembly, _dllImportResolver!);
@@ -180,7 +190,7 @@ namespace GodotPlugins
}
}
- private static (Assembly, PluginLoadContextWrapper) LoadPlugin(string assemblyPath)
+ private static (Assembly, PluginLoadContextWrapper) LoadPlugin(string assemblyPath, bool isCollectible)
{
string assemblyName = Path.GetFileNameWithoutExtension(assemblyPath);
@@ -194,7 +204,7 @@ namespace GodotPlugins
}
return PluginLoadContextWrapper.CreateAndLoadFromAssemblyName(
- new AssemblyName(assemblyName), assemblyPath, sharedAssemblies, MainLoadContext);
+ new AssemblyName(assemblyName), assemblyPath, sharedAssemblies, MainLoadContext, isCollectible);
}
[UnmanagedCallersOnly]
@@ -218,6 +228,12 @@ namespace GodotPlugins
if (pluginLoadContext == null)
return true;
+ if (!pluginLoadContext.IsCollectible)
+ {
+ Console.Error.WriteLine("Cannot unload a non-collectible assembly load context.");
+ return false;
+ }
+
Console.WriteLine("Unloading assembly load context...");
var alcWeakReference = pluginLoadContext.CreateWeakReference();
diff --git a/modules/mono/glue/GodotSharp/GodotPlugins/PluginLoadContext.cs b/modules/mono/glue/GodotSharp/GodotPlugins/PluginLoadContext.cs
index dcd572c65e..344b76a202 100644
--- a/modules/mono/glue/GodotSharp/GodotPlugins/PluginLoadContext.cs
+++ b/modules/mono/glue/GodotSharp/GodotPlugins/PluginLoadContext.cs
@@ -15,8 +15,8 @@ namespace GodotPlugins
public string? AssemblyLoadedPath { get; private set; }
public PluginLoadContext(string pluginPath, ICollection<string> sharedAssemblies,
- AssemblyLoadContext mainLoadContext)
- : base(isCollectible: true)
+ AssemblyLoadContext mainLoadContext, bool isCollectible)
+ : base(isCollectible)
{
_resolver = new AssemblyDependencyResolver(pluginPath);
_sharedAssemblies = sharedAssemblies;
diff --git a/modules/mono/glue/GodotSharp/GodotSharp.sln.DotSettings b/modules/mono/glue/GodotSharp/GodotSharp.sln.DotSettings
index ba65b61e95..65f33e43a8 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp.sln.DotSettings
+++ b/modules/mono/glue/GodotSharp/GodotSharp.sln.DotSettings
@@ -1,7 +1,7 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=GC/@EntryIndexedValue">GC</s:String>
<s:Boolean x:Key="/Default/UserDictionary/Words/=alcs/@EntryIndexedValue">True</s:Boolean>
- <s:Boolean x:Key="/Default/UserDictionary/Words/=gdnative/@EntryIndexedValue">True</s:Boolean>
+ <s:Boolean x:Key="/Default/UserDictionary/Words/=gdextension/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=godotsharp/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=icall/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=quat/@EntryIndexedValue">True</s:Boolean>
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/AABB.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/AABB.cs
index d8a6644a66..a2916d4ae8 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/AABB.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/AABB.cs
@@ -20,7 +20,7 @@ namespace Godot
/// <value>Directly uses a private field.</value>
public Vector3 Position
{
- get { return _position; }
+ readonly get { return _position; }
set { _position = value; }
}
@@ -31,7 +31,7 @@ namespace Godot
/// <value>Directly uses a private field.</value>
public Vector3 Size
{
- get { return _size; }
+ readonly get { return _size; }
set { _size = value; }
}
@@ -45,7 +45,7 @@ namespace Godot
/// </value>
public Vector3 End
{
- get { return _position + _size; }
+ readonly get { return _position + _size; }
set { _size = value - _position; }
}
@@ -54,7 +54,7 @@ namespace Godot
/// the most-negative corner is the origin and the size is positive.
/// </summary>
/// <returns>The modified <see cref="AABB"/>.</returns>
- public AABB Abs()
+ public readonly AABB Abs()
{
Vector3 end = End;
Vector3 topLeft = new Vector3(Mathf.Min(_position.x, end.x), Mathf.Min(_position.y, end.y), Mathf.Min(_position.z, end.z));
@@ -66,7 +66,7 @@ namespace Godot
/// to <see cref="Position"/> + (<see cref="Size"/> / 2).
/// </summary>
/// <returns>The center.</returns>
- public Vector3 GetCenter()
+ public readonly Vector3 GetCenter()
{
return _position + (_size * 0.5f);
}
@@ -78,7 +78,7 @@ namespace Godot
/// <returns>
/// A <see langword="bool"/> for whether or not this <see cref="AABB"/> encloses <paramref name="with"/>.
/// </returns>
- public bool Encloses(AABB with)
+ public readonly bool Encloses(AABB with)
{
Vector3 srcMin = _position;
Vector3 srcMax = _position + _size;
@@ -98,7 +98,7 @@ namespace Godot
/// </summary>
/// <param name="point">The point to include.</param>
/// <returns>The expanded <see cref="AABB"/>.</returns>
- public AABB Expand(Vector3 point)
+ public readonly AABB Expand(Vector3 point)
{
Vector3 begin = _position;
Vector3 end = _position + _size;
@@ -140,7 +140,7 @@ namespace Godot
/// <paramref name="idx"/> is less than 0 or greater than 7.
/// </exception>
/// <returns>An endpoint of the <see cref="AABB"/>.</returns>
- public Vector3 GetEndpoint(int idx)
+ public readonly Vector3 GetEndpoint(int idx)
{
switch (idx)
{
@@ -172,7 +172,7 @@ namespace Godot
/// Returns the normalized longest axis of the <see cref="AABB"/>.
/// </summary>
/// <returns>A vector representing the normalized longest axis of the <see cref="AABB"/>.</returns>
- public Vector3 GetLongestAxis()
+ public readonly Vector3 GetLongestAxis()
{
var axis = new Vector3(1f, 0f, 0f);
real_t maxSize = _size.x;
@@ -195,7 +195,7 @@ namespace Godot
/// Returns the <see cref="Vector3.Axis"/> index of the longest axis of the <see cref="AABB"/>.
/// </summary>
/// <returns>A <see cref="Vector3.Axis"/> index for which axis is longest.</returns>
- public Vector3.Axis GetLongestAxisIndex()
+ public readonly Vector3.Axis GetLongestAxisIndex()
{
var axis = Vector3.Axis.X;
real_t maxSize = _size.x;
@@ -218,7 +218,7 @@ namespace Godot
/// Returns the scalar length of the longest axis of the <see cref="AABB"/>.
/// </summary>
/// <returns>The scalar length of the longest axis of the <see cref="AABB"/>.</returns>
- public real_t GetLongestAxisSize()
+ public readonly real_t GetLongestAxisSize()
{
real_t maxSize = _size.x;
@@ -235,7 +235,7 @@ namespace Godot
/// Returns the normalized shortest axis of the <see cref="AABB"/>.
/// </summary>
/// <returns>A vector representing the normalized shortest axis of the <see cref="AABB"/>.</returns>
- public Vector3 GetShortestAxis()
+ public readonly Vector3 GetShortestAxis()
{
var axis = new Vector3(1f, 0f, 0f);
real_t maxSize = _size.x;
@@ -258,7 +258,7 @@ namespace Godot
/// Returns the <see cref="Vector3.Axis"/> index of the shortest axis of the <see cref="AABB"/>.
/// </summary>
/// <returns>A <see cref="Vector3.Axis"/> index for which axis is shortest.</returns>
- public Vector3.Axis GetShortestAxisIndex()
+ public readonly Vector3.Axis GetShortestAxisIndex()
{
var axis = Vector3.Axis.X;
real_t maxSize = _size.x;
@@ -281,7 +281,7 @@ namespace Godot
/// Returns the scalar length of the shortest axis of the <see cref="AABB"/>.
/// </summary>
/// <returns>The scalar length of the shortest axis of the <see cref="AABB"/>.</returns>
- public real_t GetShortestAxisSize()
+ public readonly real_t GetShortestAxisSize()
{
real_t maxSize = _size.x;
@@ -300,7 +300,7 @@ namespace Godot
/// </summary>
/// <param name="dir">The direction to find support for.</param>
/// <returns>A vector representing the support.</returns>
- public Vector3 GetSupport(Vector3 dir)
+ public readonly Vector3 GetSupport(Vector3 dir)
{
Vector3 halfExtents = _size * 0.5f;
Vector3 ofs = _position + halfExtents;
@@ -315,7 +315,7 @@ namespace Godot
/// Returns the volume of the <see cref="AABB"/>.
/// </summary>
/// <returns>The volume.</returns>
- public real_t GetVolume()
+ public readonly real_t GetVolume()
{
return _size.x * _size.y * _size.z;
}
@@ -325,7 +325,7 @@ namespace Godot
/// </summary>
/// <param name="by">The amount to grow by.</param>
/// <returns>The grown <see cref="AABB"/>.</returns>
- public AABB Grow(real_t by)
+ public readonly AABB Grow(real_t by)
{
AABB res = this;
@@ -347,7 +347,7 @@ namespace Godot
/// <returns>
/// A <see langword="bool"/> for whether or not the <see cref="AABB"/> contains <paramref name="point"/>.
/// </returns>
- public bool HasPoint(Vector3 point)
+ public readonly bool HasPoint(Vector3 point)
{
if (point.x < _position.x)
return false;
@@ -374,7 +374,7 @@ namespace Godot
/// <returns>
/// A <see langword="bool"/> for whether or not the <see cref="AABB"/> has surface.
/// </returns>
- public bool HasSurface()
+ public readonly bool HasSurface()
{
return _size.x > 0.0f || _size.y > 0.0f || _size.z > 0.0f;
}
@@ -388,7 +388,7 @@ namespace Godot
/// <returns>
/// A <see langword="bool"/> for whether or not the <see cref="AABB"/> has volume.
/// </returns>
- public bool HasVolume()
+ public readonly bool HasVolume()
{
return _size.x > 0.0f && _size.y > 0.0f && _size.z > 0.0f;
}
@@ -398,7 +398,7 @@ namespace Godot
/// </summary>
/// <param name="with">The other <see cref="AABB"/>.</param>
/// <returns>The clipped <see cref="AABB"/>.</returns>
- public AABB Intersection(AABB with)
+ public readonly AABB Intersection(AABB with)
{
Vector3 srcMin = _position;
Vector3 srcMax = _position + _size;
@@ -447,7 +447,7 @@ namespace Godot
/// <returns>
/// A <see langword="bool"/> for whether or not they are intersecting.
/// </returns>
- public bool Intersects(AABB with, bool includeBorders = false)
+ public readonly bool Intersects(AABB with, bool includeBorders = false)
{
if (includeBorders)
{
@@ -490,7 +490,7 @@ namespace Godot
/// <returns>
/// A <see langword="bool"/> for whether or not the <see cref="AABB"/> intersects the <see cref="Plane"/>.
/// </returns>
- public bool IntersectsPlane(Plane plane)
+ public readonly bool IntersectsPlane(Plane plane)
{
Vector3[] points =
{
@@ -531,7 +531,7 @@ namespace Godot
/// <returns>
/// A <see langword="bool"/> for whether or not the <see cref="AABB"/> intersects the line segment.
/// </returns>
- public bool IntersectsSegment(Vector3 from, Vector3 to)
+ public readonly bool IntersectsSegment(Vector3 from, Vector3 to)
{
real_t min = 0f;
real_t max = 1f;
@@ -590,7 +590,7 @@ namespace Godot
/// </summary>
/// <param name="with">The other <see cref="AABB"/>.</param>
/// <returns>The merged <see cref="AABB"/>.</returns>
- public AABB Merge(AABB with)
+ public readonly AABB Merge(AABB with)
{
Vector3 beg1 = _position;
Vector3 beg2 = with._position;
@@ -702,7 +702,7 @@ namespace Godot
/// </summary>
/// <param name="obj">The object to compare with.</param>
/// <returns>Whether or not the AABB and the object are equal.</returns>
- public override bool Equals(object obj)
+ public override readonly bool Equals(object obj)
{
return obj is AABB other && Equals(other);
}
@@ -714,7 +714,7 @@ namespace Godot
/// </summary>
/// <param name="other">The other AABB.</param>
/// <returns>Whether or not the AABBs are exactly equal.</returns>
- public bool Equals(AABB other)
+ public readonly bool Equals(AABB other)
{
return _position == other._position && _size == other._size;
}
@@ -725,7 +725,7 @@ namespace Godot
/// </summary>
/// <param name="other">The other AABB to compare.</param>
/// <returns>Whether or not the AABBs structures are approximately equal.</returns>
- public bool IsEqualApprox(AABB other)
+ public readonly bool IsEqualApprox(AABB other)
{
return _position.IsEqualApprox(other._position) && _size.IsEqualApprox(other._size);
}
@@ -734,7 +734,7 @@ namespace Godot
/// Serves as the hash function for <see cref="AABB"/>.
/// </summary>
/// <returns>A hash code for this AABB.</returns>
- public override int GetHashCode()
+ public override readonly int GetHashCode()
{
return _position.GetHashCode() ^ _size.GetHashCode();
}
@@ -743,7 +743,7 @@ namespace Godot
/// Converts this <see cref="AABB"/> to a string.
/// </summary>
/// <returns>A string representation of this AABB.</returns>
- public override string ToString()
+ public override readonly string ToString()
{
return $"{_position}, {_size}";
}
@@ -752,7 +752,7 @@ namespace Godot
/// Converts this <see cref="AABB"/> to a string with the given <paramref name="format"/>.
/// </summary>
/// <returns>A string representation of this AABB.</returns>
- public string ToString(string format)
+ public readonly string ToString(string format)
{
return $"{_position.ToString(format)}, {_size.ToString(format)}";
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Array.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Array.cs
index f1b46e293b..df306e5244 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Array.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Array.cs
@@ -418,8 +418,8 @@ namespace Godot.Collections
{
for (int i = 0; i < count; i++)
{
- object obj = Marshaling.ConvertVariantToManagedObject(NativeValue.DangerousSelfRef.Elements[i]);
- array.SetValue(obj, index);
+ object boxedVariant = Variant.CreateCopyingBorrowed(NativeValue.DangerousSelfRef.Elements[i]);
+ array.SetValue(boxedVariant, index);
index++;
}
}
@@ -474,6 +474,11 @@ namespace Godot.Collections
}
}
+ internal interface IGenericGodotArray
+ {
+ public Array UnderlyingArray { get; }
+ }
+
/// <summary>
/// Typed wrapper around Godot's Array class, an array of Variant
/// typed elements allocated in the engine in C++. Useful when
@@ -487,47 +492,25 @@ namespace Godot.Collections
IList<T>,
IReadOnlyList<T>,
ICollection<T>,
- IEnumerable<T>
+ IEnumerable<T>,
+ IGenericGodotArray
{
private static godot_variant ToVariantFunc(in Array<T> godotArray) =>
VariantUtils.CreateFromArray(godotArray);
private static Array<T> FromVariantFunc(in godot_variant variant) =>
- VariantUtils.ConvertToArrayObject<T>(variant);
-
- // ReSharper disable StaticMemberInGenericType
- // Warning is about unique static fields being created for each generic type combination:
- // https://www.jetbrains.com/help/resharper/StaticMemberInGenericType.html
- // In our case this is exactly what we want.
-
- private static readonly unsafe delegate* managed<in T, godot_variant> ConvertToVariantCallback;
- private static readonly unsafe delegate* managed<in godot_variant, T> ConvertToManagedCallback;
-
- // ReSharper restore StaticMemberInGenericType
+ VariantUtils.ConvertToArray<T>(variant);
static unsafe Array()
{
- VariantConversionCallbacks.GenericConversionCallbacks[typeof(Array<T>)] =
- (
- (IntPtr)(delegate* managed<in Array<T>, godot_variant>)&ToVariantFunc,
- (IntPtr)(delegate* managed<in godot_variant, Array<T>>)&FromVariantFunc
- );
-
- ConvertToVariantCallback = VariantConversionCallbacks.GetToVariantCallback<T>();
- ConvertToManagedCallback = VariantConversionCallbacks.GetToManagedCallback<T>();
- }
-
- private static unsafe void ValidateVariantConversionCallbacks()
- {
- if (ConvertToVariantCallback == null || ConvertToManagedCallback == null)
- {
- throw new InvalidOperationException(
- $"The array element type is not supported for conversion to Variant: '{typeof(T).FullName}'.");
- }
+ VariantUtils.GenericConversion<Array<T>>.ToVariantCb = &ToVariantFunc;
+ VariantUtils.GenericConversion<Array<T>>.FromVariantCb = &FromVariantFunc;
}
private readonly Array _underlyingArray;
+ Array IGenericGodotArray.UnderlyingArray => _underlyingArray;
+
internal ref godot_array.movable NativeValue
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -539,8 +522,6 @@ namespace Godot.Collections
/// </summary>
public Array()
{
- ValidateVariantConversionCallbacks();
-
_underlyingArray = new Array();
}
@@ -551,8 +532,6 @@ namespace Godot.Collections
/// <returns>A new Godot Array.</returns>
public Array(IEnumerable<T> collection)
{
- ValidateVariantConversionCallbacks();
-
if (collection == null)
throw new ArgumentNullException(nameof(collection));
@@ -569,8 +548,6 @@ namespace Godot.Collections
/// <returns>A new Godot Array.</returns>
public Array(T[] array) : this()
{
- ValidateVariantConversionCallbacks();
-
if (array == null)
throw new ArgumentNullException(nameof(array));
@@ -586,8 +563,6 @@ namespace Godot.Collections
/// <param name="array">The untyped array to construct from.</param>
public Array(Array array)
{
- ValidateVariantConversionCallbacks();
-
_underlyingArray = array;
}
@@ -665,7 +640,7 @@ namespace Godot.Collections
get
{
_underlyingArray.GetVariantBorrowElementAt(index, out godot_variant borrowElem);
- return ConvertToManagedCallback(borrowElem);
+ return VariantUtils.ConvertTo<T>(borrowElem);
}
set
{
@@ -675,7 +650,7 @@ namespace Godot.Collections
godot_variant* ptrw = NativeFuncs.godotsharp_array_ptrw(ref self);
godot_variant* itemPtr = &ptrw[index];
(*itemPtr).Dispose();
- *itemPtr = ConvertToVariantCallback(value);
+ *itemPtr = VariantUtils.CreateFrom(value);
}
}
@@ -685,9 +660,9 @@ namespace Godot.Collections
/// </summary>
/// <param name="item">The item to search for.</param>
/// <returns>The index of the item, or -1 if not found.</returns>
- public unsafe int IndexOf(T item)
+ public int IndexOf(T item)
{
- using var variantValue = ConvertToVariantCallback(item);
+ using var variantValue = VariantUtils.CreateFrom(item);
var self = (godot_array)_underlyingArray.NativeValue;
return NativeFuncs.godotsharp_array_index_of(ref self, variantValue);
}
@@ -700,12 +675,12 @@ namespace Godot.Collections
/// </summary>
/// <param name="index">The index to insert at.</param>
/// <param name="item">The item to insert.</param>
- public unsafe void Insert(int index, T item)
+ public void Insert(int index, T item)
{
if (index < 0 || index > Count)
throw new ArgumentOutOfRangeException(nameof(index));
- using var variantValue = ConvertToVariantCallback(item);
+ using var variantValue = VariantUtils.CreateFrom(item);
var self = (godot_array)_underlyingArray.NativeValue;
NativeFuncs.godotsharp_array_insert(ref self, index, variantValue);
}
@@ -736,9 +711,9 @@ namespace Godot.Collections
/// </summary>
/// <param name="item">The item to add.</param>
/// <returns>The new size after adding the item.</returns>
- public unsafe void Add(T item)
+ public void Add(T item)
{
- using var variantValue = ConvertToVariantCallback(item);
+ using var variantValue = VariantUtils.CreateFrom(item);
var self = (godot_array)_underlyingArray.NativeValue;
_ = NativeFuncs.godotsharp_array_add(ref self, variantValue);
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/AssemblyHasScriptsAttribute.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/AssemblyHasScriptsAttribute.cs
index b7d633517a..acdae83d2e 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/AssemblyHasScriptsAttribute.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/AssemblyHasScriptsAttribute.cs
@@ -1,20 +1,32 @@
using System;
+using System.Diagnostics.CodeAnalysis;
#nullable enable
namespace Godot
{
/// <summary>
- /// An attribute that determines if an assembly has scripts. If so, what types of scripts the assembly has.
+ /// Attribute that determines that the assembly contains Godot scripts and, optionally, the
+ /// collection of types that implement scripts; otherwise, retrieving the types requires lookup.
/// </summary>
[AttributeUsage(AttributeTargets.Assembly)]
public class AssemblyHasScriptsAttribute : Attribute
{
+ /// <summary>
+ /// If the Godot scripts contained in the assembly require lookup
+ /// and can't rely on <see cref="ScriptTypes"/>.
+ /// </summary>
+ [MemberNotNullWhen(false, nameof(ScriptTypes))]
public bool RequiresLookup { get; }
+
+ /// <summary>
+ /// The collection of types that implement a Godot script.
+ /// </summary>
public Type[]? ScriptTypes { get; }
/// <summary>
- /// Constructs a new AssemblyHasScriptsAttribute instance.
+ /// Constructs a new AssemblyHasScriptsAttribute instance
+ /// that requires lookup to get the Godot scripts.
/// </summary>
public AssemblyHasScriptsAttribute()
{
@@ -23,9 +35,10 @@ namespace Godot
}
/// <summary>
- /// Constructs a new AssemblyHasScriptsAttribute instance.
+ /// Constructs a new AssemblyHasScriptsAttribute instance
+ /// that includes the Godot script types and requires no lookup.
/// </summary>
- /// <param name="scriptTypes">The specified type(s) of scripts.</param>
+ /// <param name="scriptTypes">The collection of types that implement a Godot script.</param>
public AssemblyHasScriptsAttribute(Type[] scriptTypes)
{
RequiresLookup = false;
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ExportAttribute.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ExportAttribute.cs
index 3d204bdf9f..a48d79091f 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ExportAttribute.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ExportAttribute.cs
@@ -3,23 +3,30 @@ using System;
namespace Godot
{
/// <summary>
- /// An attribute used to export objects.
+ /// Exports the annotated member as a property of the Godot Object.
/// </summary>
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
public sealed class ExportAttribute : Attribute
{
- private PropertyHint hint;
- private string hintString;
+ /// <summary>
+ /// Optional hint that determines how the property should be handled by the editor.
+ /// </summary>
+ public PropertyHint Hint { get; }
+
+ /// <summary>
+ /// Optional string that can contain additional metadata for the <see cref="Hint"/>.
+ /// </summary>
+ public string HintString { get; }
/// <summary>
/// Constructs a new ExportAttribute Instance.
/// </summary>
- /// <param name="hint">A hint to the exported object.</param>
- /// <param name="hintString">A string representing the exported object.</param>
+ /// <param name="hint">The hint for the exported property.</param>
+ /// <param name="hintString">A string that may contain additional metadata for the hint.</param>
public ExportAttribute(PropertyHint hint = PropertyHint.None, string hintString = "")
{
- this.hint = hint;
- this.hintString = hintString;
+ Hint = hint;
+ HintString = hintString;
}
}
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ExportCategoryAttribute.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ExportCategoryAttribute.cs
index 101e56f8d3..2ae55acd3e 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ExportCategoryAttribute.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ExportCategoryAttribute.cs
@@ -8,7 +8,10 @@ namespace Godot
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
public sealed class ExportCategoryAttribute : Attribute
{
- private string name;
+ /// <summary>
+ /// Name of the category.
+ /// </summary>
+ public string Name { get; }
/// <summary>
/// Define a new category for the following exported properties.
@@ -16,7 +19,7 @@ namespace Godot
/// <param name="name">The name of the category.</param>
public ExportCategoryAttribute(string name)
{
- this.name = name;
+ Name = name;
}
}
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ExportGroupAttribute.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ExportGroupAttribute.cs
index 3bd532cec1..82bd446640 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ExportGroupAttribute.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ExportGroupAttribute.cs
@@ -1,5 +1,7 @@
using System;
+#nullable enable
+
namespace Godot
{
/// <summary>
@@ -8,8 +10,15 @@ namespace Godot
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
public sealed class ExportGroupAttribute : Attribute
{
- private string name;
- private string prefix;
+ /// <summary>
+ /// Name of the group.
+ /// </summary>
+ public string Name { get; }
+
+ /// <summary>
+ /// If provided, the prefix that all properties must have to be considered part of the group.
+ /// </summary>
+ public string? Prefix { get; }
/// <summary>
/// Define a new group for the following exported properties.
@@ -18,8 +27,8 @@ namespace Godot
/// <param name="prefix">If provided, the group would make group to only consider properties that have this prefix.</param>
public ExportGroupAttribute(string name, string prefix = "")
{
- this.name = name;
- this.prefix = prefix;
+ Name = name;
+ Prefix = prefix;
}
}
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ExportSubgroupAttribute.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ExportSubgroupAttribute.cs
index 2ae6eb0b68..3282b466f6 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ExportSubgroupAttribute.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ExportSubgroupAttribute.cs
@@ -1,5 +1,7 @@
using System;
+#nullable enable
+
namespace Godot
{
/// <summary>
@@ -8,8 +10,15 @@ namespace Godot
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
public sealed class ExportSubgroupAttribute : Attribute
{
- private string name;
- private string prefix;
+ /// <summary>
+ /// Name of the subgroup.
+ /// </summary>
+ public string Name { get; }
+
+ /// <summary>
+ /// If provided, the prefix that all properties must have to be considered part of the subgroup.
+ /// </summary>
+ public string? Prefix { get; }
/// <summary>
/// Define a new subgroup for the following exported properties. This helps to organize properties in the Inspector dock.
@@ -18,8 +27,8 @@ namespace Godot
/// <param name="prefix">If provided, the subgroup would make group to only consider properties that have this prefix.</param>
public ExportSubgroupAttribute(string name, string prefix = "")
{
- this.name = name;
- this.prefix = prefix;
+ Name = name;
+ Prefix = prefix;
}
}
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/RPCAttribute.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/RPCAttribute.cs
index fb37838ffa..afee926464 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/RPCAttribute.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/RPCAttribute.cs
@@ -19,17 +19,17 @@ namespace Godot
/// <summary>
/// If the method will also be called locally; otherwise, it is only called remotely.
/// </summary>
- public bool CallLocal { get; set; } = false;
+ public bool CallLocal { get; init; } = false;
/// <summary>
/// Transfer mode for the annotated method.
/// </summary>
- public MultiplayerPeer.TransferModeEnum TransferMode { get; set; } = MultiplayerPeer.TransferModeEnum.Reliable;
+ public MultiplayerPeer.TransferModeEnum TransferMode { get; init; } = MultiplayerPeer.TransferModeEnum.Reliable;
/// <summary>
/// Transfer channel for the annotated mode.
/// </summary>
- public int TransferChannel { get; set; } = 0;
+ public int TransferChannel { get; init; } = 0;
/// <summary>
/// Constructs a <see cref="RPCAttribute"/> instance.
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ScriptPathAttribute.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ScriptPathAttribute.cs
index 2c8a53ae1c..f05bcdac38 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ScriptPathAttribute.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ScriptPathAttribute.cs
@@ -8,6 +8,9 @@ namespace Godot
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
public class ScriptPathAttribute : Attribute
{
+ /// <summary>
+ /// File path to the script.
+ /// </summary>
public string Path { get; }
/// <summary>
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs
index bb1d6e1661..5d390a298d 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs
@@ -29,7 +29,7 @@ namespace Godot
/// <value>Equivalent to <see cref="Column0"/> and array index <c>[0]</c>.</value>
public Vector3 x
{
- get => Column0;
+ readonly get => Column0;
set => Column0 = value;
}
@@ -39,7 +39,7 @@ namespace Godot
/// <value>Equivalent to <see cref="Column1"/> and array index <c>[1]</c>.</value>
public Vector3 y
{
- get => Column1;
+ readonly get => Column1;
set => Column1 = value;
}
@@ -49,7 +49,7 @@ namespace Godot
/// <value>Equivalent to <see cref="Column2"/> and array index <c>[2]</c>.</value>
public Vector3 z
{
- get => Column2;
+ readonly get => Column2;
set => Column2 = value;
}
@@ -80,7 +80,7 @@ namespace Godot
/// <value>Equivalent to <see cref="x"/> and array index <c>[0]</c>.</value>
public Vector3 Column0
{
- get => new Vector3(Row0.x, Row1.x, Row2.x);
+ readonly get => new Vector3(Row0.x, Row1.x, Row2.x);
set
{
Row0.x = value.x;
@@ -95,7 +95,7 @@ namespace Godot
/// <value>Equivalent to <see cref="y"/> and array index <c>[1]</c>.</value>
public Vector3 Column1
{
- get => new Vector3(Row0.y, Row1.y, Row2.y);
+ readonly get => new Vector3(Row0.y, Row1.y, Row2.y);
set
{
Row0.y = value.x;
@@ -110,7 +110,7 @@ namespace Godot
/// <value>Equivalent to <see cref="z"/> and array index <c>[2]</c>.</value>
public Vector3 Column2
{
- get => new Vector3(Row0.z, Row1.z, Row2.z);
+ readonly get => new Vector3(Row0.z, Row1.z, Row2.z);
set
{
Row0.z = value.x;
@@ -125,7 +125,7 @@ namespace Godot
/// <value>Equivalent to the lengths of each column vector, but negative if the determinant is negative.</value>
public Vector3 Scale
{
- get
+ readonly get
{
real_t detSign = Mathf.Sign(Determinant());
return detSign * new Vector3
@@ -154,7 +154,7 @@ namespace Godot
/// <value>The basis column.</value>
public Vector3 this[int column]
{
- get
+ readonly get
{
switch (column)
{
@@ -195,7 +195,7 @@ namespace Godot
/// <value>The matrix element.</value>
public real_t this[int column, int row]
{
- get
+ readonly get
{
return this[column][row];
}
@@ -234,7 +234,7 @@ namespace Godot
/// and is usually considered invalid.
/// </summary>
/// <returns>The determinant of the basis matrix.</returns>
- public real_t Determinant()
+ public readonly real_t Determinant()
{
real_t cofac00 = Row1[1] * Row2[2] - Row1[2] * Row2[1];
real_t cofac10 = Row1[2] * Row2[0] - Row1[0] * Row2[2];
@@ -255,7 +255,7 @@ namespace Godot
/// </summary>
/// <param name="order">The Euler order to use. By default, use YXZ order (most common).</param>
/// <returns>A <see cref="Vector3"/> representing the basis rotation in Euler angles.</returns>
- public Vector3 GetEuler(EulerOrder order = EulerOrder.Yxz)
+ public readonly Vector3 GetEuler(EulerOrder order = EulerOrder.Yxz)
{
switch (order)
{
@@ -499,7 +499,7 @@ namespace Godot
/// mind that quaternions should generally be preferred to Euler angles.
/// </summary>
/// <returns>A <see cref="Quaternion"/> representing the basis's rotation.</returns>
- internal Quaternion GetQuaternion()
+ internal readonly Quaternion GetQuaternion()
{
real_t trace = Row0[0] + Row1[1] + Row2[2];
@@ -558,7 +558,7 @@ namespace Godot
/// be preferred to Euler angles.
/// </summary>
/// <returns>The basis rotation.</returns>
- public Quaternion GetRotationQuaternion()
+ public readonly Quaternion GetRotationQuaternion()
{
Basis orthonormalizedBasis = Orthonormalized();
real_t det = orthonormalizedBasis.Determinant();
@@ -581,7 +581,7 @@ namespace Godot
/// <paramref name="index"/> is not 0, 1 or 2.
/// </exception>
/// <returns>One of <c>Row0</c>, <c>Row1</c>, or <c>Row2</c>.</returns>
- public Vector3 GetRow(int index)
+ public readonly Vector3 GetRow(int index)
{
switch (index)
{
@@ -633,7 +633,7 @@ namespace Godot
/// For further details, refer to the Godot source code.
/// </summary>
/// <returns>The orthogonal index.</returns>
- public int GetOrthogonalIndex()
+ public readonly int GetOrthogonalIndex()
{
var orth = this;
@@ -679,7 +679,7 @@ namespace Godot
/// Returns the inverse of the matrix.
/// </summary>
/// <returns>The inverse matrix.</returns>
- public Basis Inverse()
+ public readonly Basis Inverse()
{
real_t cofac00 = Row1[1] * Row2[2] - Row1[2] * Row2[1];
real_t cofac10 = Row1[2] * Row2[0] - Row1[0] * Row2[2];
@@ -709,7 +709,7 @@ namespace Godot
);
}
- internal Basis Lerp(Basis to, real_t weight)
+ internal readonly Basis Lerp(Basis to, real_t weight)
{
Basis b = this;
b.Row0 = Row0.Lerp(to.Row0, weight);
@@ -724,7 +724,7 @@ namespace Godot
/// This performs a Gram-Schmidt orthonormalization on the basis of the matrix.
/// </summary>
/// <returns>An orthonormalized basis matrix.</returns>
- public Basis Orthonormalized()
+ public readonly Basis Orthonormalized()
{
Vector3 column0 = this[0];
Vector3 column1 = this[1];
@@ -746,7 +746,7 @@ 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 angle)
+ public readonly Basis Rotated(Vector3 axis, real_t angle)
{
return new Basis(axis, angle) * this;
}
@@ -756,7 +756,7 @@ namespace Godot
/// </summary>
/// <param name="scale">The scale to introduce.</param>
/// <returns>The scaled basis matrix.</returns>
- public Basis Scaled(Vector3 scale)
+ public readonly Basis Scaled(Vector3 scale)
{
Basis b = this;
b.Row0 *= scale.x;
@@ -772,7 +772,7 @@ namespace Godot
/// <param name="target">The destination basis 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 basis matrix of the interpolation.</returns>
- public Basis Slerp(Basis target, real_t weight)
+ public readonly Basis Slerp(Basis target, real_t weight)
{
Quaternion from = new Quaternion(this);
Quaternion to = new Quaternion(target);
@@ -790,7 +790,7 @@ namespace Godot
/// </summary>
/// <param name="with">A vector to calculate the dot product with.</param>
/// <returns>The resulting dot product.</returns>
- public real_t Tdotx(Vector3 with)
+ public readonly real_t Tdotx(Vector3 with)
{
return Row0[0] * with[0] + Row1[0] * with[1] + Row2[0] * with[2];
}
@@ -800,7 +800,7 @@ namespace Godot
/// </summary>
/// <param name="with">A vector to calculate the dot product with.</param>
/// <returns>The resulting dot product.</returns>
- public real_t Tdoty(Vector3 with)
+ public readonly real_t Tdoty(Vector3 with)
{
return Row0[1] * with[0] + Row1[1] * with[1] + Row2[1] * with[2];
}
@@ -810,7 +810,7 @@ namespace Godot
/// </summary>
/// <param name="with">A vector to calculate the dot product with.</param>
/// <returns>The resulting dot product.</returns>
- public real_t Tdotz(Vector3 with)
+ public readonly real_t Tdotz(Vector3 with)
{
return Row0[2] * with[0] + Row1[2] * with[1] + Row2[2] * with[2];
}
@@ -819,21 +819,18 @@ namespace Godot
/// Returns the transposed version of the basis matrix.
/// </summary>
/// <returns>The transposed basis matrix.</returns>
- public Basis Transposed()
+ public readonly Basis Transposed()
{
Basis tr = this;
- real_t temp = tr.Row0[1];
- tr.Row0[1] = tr.Row1[0];
- tr.Row1[0] = temp;
+ tr.Row0[1] = Row1[0];
+ tr.Row1[0] = Row0[1];
- temp = tr.Row0[2];
- tr.Row0[2] = tr.Row2[0];
- tr.Row2[0] = temp;
+ tr.Row0[2] = Row2[0];
+ tr.Row2[0] = Row0[2];
- temp = tr.Row1[2];
- tr.Row1[2] = tr.Row2[1];
- tr.Row2[1] = temp;
+ tr.Row1[2] = Row2[1];
+ tr.Row2[1] = Row1[2];
return tr;
}
@@ -1121,7 +1118,7 @@ namespace Godot
/// </summary>
/// <param name="obj">The object to compare with.</param>
/// <returns>Whether or not the basis matrix and the object are exactly equal.</returns>
- public override bool Equals(object obj)
+ public override readonly bool Equals(object obj)
{
return obj is Basis other && Equals(other);
}
@@ -1133,7 +1130,7 @@ namespace Godot
/// </summary>
/// <param name="other">The other basis.</param>
/// <returns>Whether or not the basis matrices are exactly equal.</returns>
- public bool Equals(Basis other)
+ public readonly bool Equals(Basis other)
{
return Row0.Equals(other.Row0) && Row1.Equals(other.Row1) && Row2.Equals(other.Row2);
}
@@ -1144,7 +1141,7 @@ namespace Godot
/// </summary>
/// <param name="other">The other basis to compare.</param>
/// <returns>Whether or not the bases are approximately equal.</returns>
- public bool IsEqualApprox(Basis other)
+ public readonly bool IsEqualApprox(Basis other)
{
return Row0.IsEqualApprox(other.Row0) && Row1.IsEqualApprox(other.Row1) && Row2.IsEqualApprox(other.Row2);
}
@@ -1153,7 +1150,7 @@ namespace Godot
/// Serves as the hash function for <see cref="Basis"/>.
/// </summary>
/// <returns>A hash code for this basis.</returns>
- public override int GetHashCode()
+ public override readonly int GetHashCode()
{
return Row0.GetHashCode() ^ Row1.GetHashCode() ^ Row2.GetHashCode();
}
@@ -1162,7 +1159,7 @@ namespace Godot
/// Converts this <see cref="Basis"/> to a string.
/// </summary>
/// <returns>A string representation of this basis.</returns>
- public override string ToString()
+ public override readonly string ToString()
{
return $"[X: {x}, Y: {y}, Z: {z}]";
}
@@ -1171,7 +1168,7 @@ namespace Godot
/// Converts this <see cref="Basis"/> to a string with the given <paramref name="format"/>.
/// </summary>
/// <returns>A string representation of this basis.</returns>
- public string ToString(string format)
+ public readonly string ToString(string format)
{
return $"[X: {x.ToString(format)}, Y: {y.ToString(format)}, Z: {z.ToString(format)}]";
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/MethodInfo.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/MethodInfo.cs
index 647ae436ff..85d38f9727 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/MethodInfo.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/MethodInfo.cs
@@ -4,7 +4,7 @@ namespace Godot.Bridge;
#nullable enable
-public struct MethodInfo
+public readonly struct MethodInfo
{
public StringName Name { get; init; }
public PropertyInfo ReturnVal { get; init; }
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/PropertyInfo.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/PropertyInfo.cs
index 80d6f7b4a5..0f447b93c8 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/PropertyInfo.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/PropertyInfo.cs
@@ -2,7 +2,7 @@ namespace Godot.Bridge;
#nullable enable
-public struct PropertyInfo
+public readonly struct PropertyInfo
{
public Variant.Type Type { get; init; }
public StringName Name { get; init; }
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs
index d83cf43eb2..dafa83431b 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs
@@ -159,7 +159,7 @@ namespace Godot.Bridge
for (int i = 0; i < paramCount; i++)
{
- invokeParams[i] = Marshaling.ConvertVariantToManagedObjectOfType(
+ invokeParams[i] = DelegateUtils.RuntimeTypeConversionHelper.ConvertToObjectOfType(
*args[i], parameters[i].ParameterType);
}
@@ -297,7 +297,7 @@ namespace Godot.Bridge
foreach (var type in assembly.GetTypes())
{
- if (type.IsNested)
+ if (type.IsNested || type.IsGenericType)
continue;
if (!typeOfGodotObject.IsAssignableFrom(type))
@@ -314,9 +314,12 @@ namespace Godot.Bridge
if (scriptTypes != null)
{
- for (int i = 0; i < scriptTypes.Length; i++)
+ foreach (var type in scriptTypes)
{
- LookupScriptForClass(scriptTypes[i]);
+ if (type.IsGenericType)
+ continue;
+
+ LookupScriptForClass(type);
}
}
}
@@ -729,6 +732,7 @@ namespace Godot.Bridge
{
ExceptionUtils.LogException(e);
*outTool = godot_bool.False;
+ *outMethodsDest = NativeFuncs.godotsharp_array_new();
*outRpcFunctionsDest = NativeFuncs.godotsharp_dictionary_new();
*outEventSignalsDest = NativeFuncs.godotsharp_dictionary_new();
*outBaseScript = default;
@@ -827,12 +831,13 @@ namespace Godot.Bridge
{
// Weird limitation, hence the need for aux:
// "In the case of pointer types, you can use a stackalloc expression only in a local variable declaration to initialize the variable."
- var aux = stackalloc godotsharp_property_info[length];
+ var aux = stackalloc godotsharp_property_info[stackMaxLength];
interopProperties = aux;
}
else
{
- interopProperties = ((godotsharp_property_info*)NativeMemory.Alloc((nuint)length, (nuint)sizeof(godotsharp_property_info)))!;
+ interopProperties = ((godotsharp_property_info*)NativeMemory.Alloc(
+ (nuint)length, (nuint)sizeof(godotsharp_property_info)))!;
}
try
@@ -858,8 +863,8 @@ namespace Godot.Bridge
addPropInfoFunc(scriptPtr, &currentClassName, interopProperties, length);
- // We're borrowing the StringName's without making an owning copy, so the
- // managed collection needs to be kept alive until `addPropInfoFunc` returns.
+ // We're borrowing the native value of the StringName entries.
+ // The dictionary needs to be kept alive until `addPropInfoFunc` returns.
GC.KeepAlive(properties);
}
finally
@@ -884,12 +889,7 @@ namespace Godot.Bridge
{
// Careful with padding...
public godot_string_name Name; // Not owned
- public godot_variant Value;
-
- public void Dispose()
- {
- Value.Dispose();
- }
+ public godot_variant Value; // Not owned
}
[UnmanagedCallersOnly]
@@ -928,10 +928,35 @@ namespace Godot.Bridge
if (getGodotPropertyDefaultValuesMethod == null)
return;
- var defaultValues = (Dictionary<StringName, object>?)
- getGodotPropertyDefaultValuesMethod.Invoke(null, null);
+ var defaultValuesObj = getGodotPropertyDefaultValuesMethod.Invoke(null, null);
+
+ if (defaultValuesObj == null)
+ return;
+
+ Dictionary<StringName, Variant> defaultValues;
+
+ if (defaultValuesObj is Dictionary<StringName, object> defaultValuesLegacy)
+ {
+ // We have to support this for some time, otherwise this could cause data loss for projects
+ // built with previous releases. Ideally, we should remove this before Godot 4.0 stable.
+
+ if (defaultValuesLegacy.Count <= 0)
+ return;
+
+ defaultValues = new();
- if (defaultValues == null || defaultValues.Count <= 0)
+ foreach (var pair in defaultValuesLegacy)
+ {
+ defaultValues[pair.Key] = Variant.CreateTakingOwnershipOfDisposableValue(
+ DelegateUtils.RuntimeTypeConversionHelper.ConvertToVariant(pair.Value));
+ }
+ }
+ else
+ {
+ defaultValues = (Dictionary<StringName, Variant>)defaultValuesObj;
+ }
+
+ if (defaultValues.Count <= 0)
return;
int length = defaultValues.Count;
@@ -947,12 +972,13 @@ namespace Godot.Bridge
{
// Weird limitation, hence the need for aux:
// "In the case of pointer types, you can use a stackalloc expression only in a local variable declaration to initialize the variable."
- var aux = stackalloc godotsharp_property_def_val_pair[length];
+ var aux = stackalloc godotsharp_property_def_val_pair[stackMaxLength];
interopDefaultValues = aux;
}
else
{
- interopDefaultValues = ((godotsharp_property_def_val_pair*)NativeMemory.Alloc((nuint)length, (nuint)sizeof(godotsharp_property_def_val_pair)))!;
+ interopDefaultValues = ((godotsharp_property_def_val_pair*)NativeMemory.Alloc(
+ (nuint)length, (nuint)sizeof(godotsharp_property_def_val_pair)))!;
}
try
@@ -963,7 +989,7 @@ namespace Godot.Bridge
godotsharp_property_def_val_pair interopProperty = new()
{
Name = (godot_string_name)defaultValuePair.Key.NativeValue, // Not owned
- Value = Marshaling.ConvertManagedObjectToVariant(defaultValuePair.Value)
+ Value = (godot_variant)defaultValuePair.Value.NativeVar // Not owned
};
interopDefaultValues[i] = interopProperty;
@@ -973,15 +999,12 @@ namespace Godot.Bridge
addDefValFunc(scriptPtr, interopDefaultValues, length);
- // We're borrowing the StringName's without making an owning copy, so the
- // managed collection needs to be kept alive until `addDefValFunc` returns.
+ // We're borrowing the native value of the StringName and Variant entries.
+ // The dictionary needs to be kept alive until `addDefValFunc` returns.
GC.KeepAlive(defaultValues);
}
finally
{
- for (int i = 0; i < length; i++)
- interopDefaultValues[i].Dispose();
-
if (!useStack)
NativeMemory.Free(interopDefaultValues);
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Callable.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Callable.cs
index f9309ca13e..23b0aa9204 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Callable.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Callable.cs
@@ -77,7 +77,7 @@ namespace Godot
_trampoline = trampoline;
}
- private const int VarArgsSpanThreshold = 5;
+ private const int VarArgsSpanThreshold = 10;
/// <summary>
/// Calls the method represented by this <see cref="Callable"/>.
@@ -92,15 +92,13 @@ namespace Godot
int argc = args.Length;
Span<godot_variant.movable> argsStoreSpan = argc <= VarArgsSpanThreshold ?
- stackalloc godot_variant.movable[VarArgsSpanThreshold].Cleared() :
+ stackalloc godot_variant.movable[VarArgsSpanThreshold] :
new godot_variant.movable[argc];
- Span<IntPtr> argsSpan = argc <= 10 ?
- stackalloc IntPtr[argc] :
+ Span<IntPtr> argsSpan = argc <= VarArgsSpanThreshold ?
+ stackalloc IntPtr[VarArgsSpanThreshold] :
new IntPtr[argc];
- using var variantSpanDisposer = new VariantSpanDisposer(argsStoreSpan);
-
fixed (godot_variant* varargs = &MemoryMarshal.GetReference(argsStoreSpan).DangerousSelfRef)
fixed (IntPtr* argsPtr = &MemoryMarshal.GetReference(argsSpan))
{
@@ -128,15 +126,13 @@ namespace Godot
int argc = args.Length;
Span<godot_variant.movable> argsStoreSpan = argc <= VarArgsSpanThreshold ?
- stackalloc godot_variant.movable[VarArgsSpanThreshold].Cleared() :
+ stackalloc godot_variant.movable[VarArgsSpanThreshold] :
new godot_variant.movable[argc];
- Span<IntPtr> argsSpan = argc <= 10 ?
- stackalloc IntPtr[argc] :
+ Span<IntPtr> argsSpan = argc <= VarArgsSpanThreshold ?
+ stackalloc IntPtr[VarArgsSpanThreshold] :
new IntPtr[argc];
- using var variantSpanDisposer = new VariantSpanDisposer(argsStoreSpan);
-
fixed (godot_variant* varargs = &MemoryMarshal.GetReference(argsStoreSpan).DangerousSelfRef)
fixed (IntPtr* argsPtr = &MemoryMarshal.GetReference(argsSpan))
{
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Callable.generics.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Callable.generics.cs
index 6c6a104019..ff385da1c9 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Callable.generics.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Callable.generics.cs
@@ -54,7 +54,7 @@ public readonly partial struct Callable
ThrowIfArgCountMismatch(args, 1);
((Action<T0>)delegateObj)(
- VariantConversionCallbacks.GetToManagedCallback<T0>()(args[0])
+ VariantUtils.ConvertTo<T0>(args[0])
);
ret = default;
@@ -73,8 +73,8 @@ public readonly partial struct Callable
ThrowIfArgCountMismatch(args, 2);
((Action<T0, T1>)delegateObj)(
- VariantConversionCallbacks.GetToManagedCallback<T0>()(args[0]),
- VariantConversionCallbacks.GetToManagedCallback<T1>()(args[1])
+ VariantUtils.ConvertTo<T0>(args[0]),
+ VariantUtils.ConvertTo<T1>(args[1])
);
ret = default;
@@ -93,9 +93,9 @@ public readonly partial struct Callable
ThrowIfArgCountMismatch(args, 3);
((Action<T0, T1, T2>)delegateObj)(
- VariantConversionCallbacks.GetToManagedCallback<T0>()(args[0]),
- VariantConversionCallbacks.GetToManagedCallback<T1>()(args[1]),
- VariantConversionCallbacks.GetToManagedCallback<T2>()(args[2])
+ VariantUtils.ConvertTo<T0>(args[0]),
+ VariantUtils.ConvertTo<T1>(args[1]),
+ VariantUtils.ConvertTo<T2>(args[2])
);
ret = default;
@@ -114,10 +114,10 @@ public readonly partial struct Callable
ThrowIfArgCountMismatch(args, 4);
((Action<T0, T1, T2, T3>)delegateObj)(
- VariantConversionCallbacks.GetToManagedCallback<T0>()(args[0]),
- VariantConversionCallbacks.GetToManagedCallback<T1>()(args[1]),
- VariantConversionCallbacks.GetToManagedCallback<T2>()(args[2]),
- VariantConversionCallbacks.GetToManagedCallback<T3>()(args[3])
+ VariantUtils.ConvertTo<T0>(args[0]),
+ VariantUtils.ConvertTo<T1>(args[1]),
+ VariantUtils.ConvertTo<T2>(args[2]),
+ VariantUtils.ConvertTo<T3>(args[3])
);
ret = default;
@@ -136,11 +136,11 @@ public readonly partial struct Callable
ThrowIfArgCountMismatch(args, 5);
((Action<T0, T1, T2, T3, T4>)delegateObj)(
- VariantConversionCallbacks.GetToManagedCallback<T0>()(args[0]),
- VariantConversionCallbacks.GetToManagedCallback<T1>()(args[1]),
- VariantConversionCallbacks.GetToManagedCallback<T2>()(args[2]),
- VariantConversionCallbacks.GetToManagedCallback<T3>()(args[3]),
- VariantConversionCallbacks.GetToManagedCallback<T4>()(args[4])
+ VariantUtils.ConvertTo<T0>(args[0]),
+ VariantUtils.ConvertTo<T1>(args[1]),
+ VariantUtils.ConvertTo<T2>(args[2]),
+ VariantUtils.ConvertTo<T3>(args[3]),
+ VariantUtils.ConvertTo<T4>(args[4])
);
ret = default;
@@ -159,12 +159,12 @@ public readonly partial struct Callable
ThrowIfArgCountMismatch(args, 6);
((Action<T0, T1, T2, T3, T4, T5>)delegateObj)(
- VariantConversionCallbacks.GetToManagedCallback<T0>()(args[0]),
- VariantConversionCallbacks.GetToManagedCallback<T1>()(args[1]),
- VariantConversionCallbacks.GetToManagedCallback<T2>()(args[2]),
- VariantConversionCallbacks.GetToManagedCallback<T3>()(args[3]),
- VariantConversionCallbacks.GetToManagedCallback<T4>()(args[4]),
- VariantConversionCallbacks.GetToManagedCallback<T5>()(args[5])
+ VariantUtils.ConvertTo<T0>(args[0]),
+ VariantUtils.ConvertTo<T1>(args[1]),
+ VariantUtils.ConvertTo<T2>(args[2]),
+ VariantUtils.ConvertTo<T3>(args[3]),
+ VariantUtils.ConvertTo<T4>(args[4]),
+ VariantUtils.ConvertTo<T5>(args[5])
);
ret = default;
@@ -183,13 +183,13 @@ public readonly partial struct Callable
ThrowIfArgCountMismatch(args, 7);
((Action<T0, T1, T2, T3, T4, T5, T6>)delegateObj)(
- VariantConversionCallbacks.GetToManagedCallback<T0>()(args[0]),
- VariantConversionCallbacks.GetToManagedCallback<T1>()(args[1]),
- VariantConversionCallbacks.GetToManagedCallback<T2>()(args[2]),
- VariantConversionCallbacks.GetToManagedCallback<T3>()(args[3]),
- VariantConversionCallbacks.GetToManagedCallback<T4>()(args[4]),
- VariantConversionCallbacks.GetToManagedCallback<T5>()(args[5]),
- VariantConversionCallbacks.GetToManagedCallback<T6>()(args[6])
+ VariantUtils.ConvertTo<T0>(args[0]),
+ VariantUtils.ConvertTo<T1>(args[1]),
+ VariantUtils.ConvertTo<T2>(args[2]),
+ VariantUtils.ConvertTo<T3>(args[3]),
+ VariantUtils.ConvertTo<T4>(args[4]),
+ VariantUtils.ConvertTo<T5>(args[5]),
+ VariantUtils.ConvertTo<T6>(args[6])
);
ret = default;
@@ -208,14 +208,14 @@ public readonly partial struct Callable
ThrowIfArgCountMismatch(args, 8);
((Action<T0, T1, T2, T3, T4, T5, T6, T7>)delegateObj)(
- VariantConversionCallbacks.GetToManagedCallback<T0>()(args[0]),
- VariantConversionCallbacks.GetToManagedCallback<T1>()(args[1]),
- VariantConversionCallbacks.GetToManagedCallback<T2>()(args[2]),
- VariantConversionCallbacks.GetToManagedCallback<T3>()(args[3]),
- VariantConversionCallbacks.GetToManagedCallback<T4>()(args[4]),
- VariantConversionCallbacks.GetToManagedCallback<T5>()(args[5]),
- VariantConversionCallbacks.GetToManagedCallback<T6>()(args[6]),
- VariantConversionCallbacks.GetToManagedCallback<T7>()(args[7])
+ VariantUtils.ConvertTo<T0>(args[0]),
+ VariantUtils.ConvertTo<T1>(args[1]),
+ VariantUtils.ConvertTo<T2>(args[2]),
+ VariantUtils.ConvertTo<T3>(args[3]),
+ VariantUtils.ConvertTo<T4>(args[4]),
+ VariantUtils.ConvertTo<T5>(args[5]),
+ VariantUtils.ConvertTo<T6>(args[6]),
+ VariantUtils.ConvertTo<T7>(args[7])
);
ret = default;
@@ -234,15 +234,15 @@ public readonly partial struct Callable
ThrowIfArgCountMismatch(args, 9);
((Action<T0, T1, T2, T3, T4, T5, T6, T7, T8>)delegateObj)(
- VariantConversionCallbacks.GetToManagedCallback<T0>()(args[0]),
- VariantConversionCallbacks.GetToManagedCallback<T1>()(args[1]),
- VariantConversionCallbacks.GetToManagedCallback<T2>()(args[2]),
- VariantConversionCallbacks.GetToManagedCallback<T3>()(args[3]),
- VariantConversionCallbacks.GetToManagedCallback<T4>()(args[4]),
- VariantConversionCallbacks.GetToManagedCallback<T5>()(args[5]),
- VariantConversionCallbacks.GetToManagedCallback<T6>()(args[6]),
- VariantConversionCallbacks.GetToManagedCallback<T7>()(args[7]),
- VariantConversionCallbacks.GetToManagedCallback<T8>()(args[8])
+ VariantUtils.ConvertTo<T0>(args[0]),
+ VariantUtils.ConvertTo<T1>(args[1]),
+ VariantUtils.ConvertTo<T2>(args[2]),
+ VariantUtils.ConvertTo<T3>(args[3]),
+ VariantUtils.ConvertTo<T4>(args[4]),
+ VariantUtils.ConvertTo<T5>(args[5]),
+ VariantUtils.ConvertTo<T6>(args[6]),
+ VariantUtils.ConvertTo<T7>(args[7]),
+ VariantUtils.ConvertTo<T8>(args[8])
);
ret = default;
@@ -265,7 +265,7 @@ public readonly partial struct Callable
TResult res = ((Func<TResult>)delegateObj)();
- ret = VariantConversionCallbacks.GetToVariantCallback<TResult>()(res);
+ ret = VariantUtils.CreateFrom(res);
}
return CreateWithUnsafeTrampoline(func, &Trampoline);
@@ -281,10 +281,10 @@ public readonly partial struct Callable
ThrowIfArgCountMismatch(args, 1);
TResult res = ((Func<T0, TResult>)delegateObj)(
- VariantConversionCallbacks.GetToManagedCallback<T0>()(args[0])
+ VariantUtils.ConvertTo<T0>(args[0])
);
- ret = VariantConversionCallbacks.GetToVariantCallback<TResult>()(res);
+ ret = VariantUtils.CreateFrom(res);
}
return CreateWithUnsafeTrampoline(func, &Trampoline);
@@ -300,11 +300,11 @@ public readonly partial struct Callable
ThrowIfArgCountMismatch(args, 2);
TResult res = ((Func<T0, T1, TResult>)delegateObj)(
- VariantConversionCallbacks.GetToManagedCallback<T0>()(args[0]),
- VariantConversionCallbacks.GetToManagedCallback<T1>()(args[1])
+ VariantUtils.ConvertTo<T0>(args[0]),
+ VariantUtils.ConvertTo<T1>(args[1])
);
- ret = VariantConversionCallbacks.GetToVariantCallback<TResult>()(res);
+ ret = VariantUtils.CreateFrom(res);
}
return CreateWithUnsafeTrampoline(func, &Trampoline);
@@ -320,12 +320,12 @@ public readonly partial struct Callable
ThrowIfArgCountMismatch(args, 3);
TResult res = ((Func<T0, T1, T2, TResult>)delegateObj)(
- VariantConversionCallbacks.GetToManagedCallback<T0>()(args[0]),
- VariantConversionCallbacks.GetToManagedCallback<T1>()(args[1]),
- VariantConversionCallbacks.GetToManagedCallback<T2>()(args[2])
+ VariantUtils.ConvertTo<T0>(args[0]),
+ VariantUtils.ConvertTo<T1>(args[1]),
+ VariantUtils.ConvertTo<T2>(args[2])
);
- ret = VariantConversionCallbacks.GetToVariantCallback<TResult>()(res);
+ ret = VariantUtils.CreateFrom(res);
}
return CreateWithUnsafeTrampoline(func, &Trampoline);
@@ -341,13 +341,13 @@ public readonly partial struct Callable
ThrowIfArgCountMismatch(args, 4);
TResult res = ((Func<T0, T1, T2, T3, TResult>)delegateObj)(
- VariantConversionCallbacks.GetToManagedCallback<T0>()(args[0]),
- VariantConversionCallbacks.GetToManagedCallback<T1>()(args[1]),
- VariantConversionCallbacks.GetToManagedCallback<T2>()(args[2]),
- VariantConversionCallbacks.GetToManagedCallback<T3>()(args[3])
+ VariantUtils.ConvertTo<T0>(args[0]),
+ VariantUtils.ConvertTo<T1>(args[1]),
+ VariantUtils.ConvertTo<T2>(args[2]),
+ VariantUtils.ConvertTo<T3>(args[3])
);
- ret = VariantConversionCallbacks.GetToVariantCallback<TResult>()(res);
+ ret = VariantUtils.CreateFrom(res);
}
return CreateWithUnsafeTrampoline(func, &Trampoline);
@@ -363,14 +363,14 @@ public readonly partial struct Callable
ThrowIfArgCountMismatch(args, 5);
TResult res = ((Func<T0, T1, T2, T3, T4, TResult>)delegateObj)(
- VariantConversionCallbacks.GetToManagedCallback<T0>()(args[0]),
- VariantConversionCallbacks.GetToManagedCallback<T1>()(args[1]),
- VariantConversionCallbacks.GetToManagedCallback<T2>()(args[2]),
- VariantConversionCallbacks.GetToManagedCallback<T3>()(args[3]),
- VariantConversionCallbacks.GetToManagedCallback<T4>()(args[4])
+ VariantUtils.ConvertTo<T0>(args[0]),
+ VariantUtils.ConvertTo<T1>(args[1]),
+ VariantUtils.ConvertTo<T2>(args[2]),
+ VariantUtils.ConvertTo<T3>(args[3]),
+ VariantUtils.ConvertTo<T4>(args[4])
);
- ret = VariantConversionCallbacks.GetToVariantCallback<TResult>()(res);
+ ret = VariantUtils.CreateFrom(res);
}
return CreateWithUnsafeTrampoline(func, &Trampoline);
@@ -386,15 +386,15 @@ public readonly partial struct Callable
ThrowIfArgCountMismatch(args, 6);
TResult res = ((Func<T0, T1, T2, T3, T4, T5, TResult>)delegateObj)(
- VariantConversionCallbacks.GetToManagedCallback<T0>()(args[0]),
- VariantConversionCallbacks.GetToManagedCallback<T1>()(args[1]),
- VariantConversionCallbacks.GetToManagedCallback<T2>()(args[2]),
- VariantConversionCallbacks.GetToManagedCallback<T3>()(args[3]),
- VariantConversionCallbacks.GetToManagedCallback<T4>()(args[4]),
- VariantConversionCallbacks.GetToManagedCallback<T5>()(args[5])
+ VariantUtils.ConvertTo<T0>(args[0]),
+ VariantUtils.ConvertTo<T1>(args[1]),
+ VariantUtils.ConvertTo<T2>(args[2]),
+ VariantUtils.ConvertTo<T3>(args[3]),
+ VariantUtils.ConvertTo<T4>(args[4]),
+ VariantUtils.ConvertTo<T5>(args[5])
);
- ret = VariantConversionCallbacks.GetToVariantCallback<TResult>()(res);
+ ret = VariantUtils.CreateFrom(res);
}
return CreateWithUnsafeTrampoline(func, &Trampoline);
@@ -410,16 +410,16 @@ public readonly partial struct Callable
ThrowIfArgCountMismatch(args, 7);
TResult res = ((Func<T0, T1, T2, T3, T4, T5, T6, TResult>)delegateObj)(
- VariantConversionCallbacks.GetToManagedCallback<T0>()(args[0]),
- VariantConversionCallbacks.GetToManagedCallback<T1>()(args[1]),
- VariantConversionCallbacks.GetToManagedCallback<T2>()(args[2]),
- VariantConversionCallbacks.GetToManagedCallback<T3>()(args[3]),
- VariantConversionCallbacks.GetToManagedCallback<T4>()(args[4]),
- VariantConversionCallbacks.GetToManagedCallback<T5>()(args[5]),
- VariantConversionCallbacks.GetToManagedCallback<T6>()(args[6])
+ VariantUtils.ConvertTo<T0>(args[0]),
+ VariantUtils.ConvertTo<T1>(args[1]),
+ VariantUtils.ConvertTo<T2>(args[2]),
+ VariantUtils.ConvertTo<T3>(args[3]),
+ VariantUtils.ConvertTo<T4>(args[4]),
+ VariantUtils.ConvertTo<T5>(args[5]),
+ VariantUtils.ConvertTo<T6>(args[6])
);
- ret = VariantConversionCallbacks.GetToVariantCallback<TResult>()(res);
+ ret = VariantUtils.CreateFrom(res);
}
return CreateWithUnsafeTrampoline(func, &Trampoline);
@@ -435,17 +435,17 @@ public readonly partial struct Callable
ThrowIfArgCountMismatch(args, 8);
TResult res = ((Func<T0, T1, T2, T3, T4, T5, T6, T7, TResult>)delegateObj)(
- VariantConversionCallbacks.GetToManagedCallback<T0>()(args[0]),
- VariantConversionCallbacks.GetToManagedCallback<T1>()(args[1]),
- VariantConversionCallbacks.GetToManagedCallback<T2>()(args[2]),
- VariantConversionCallbacks.GetToManagedCallback<T3>()(args[3]),
- VariantConversionCallbacks.GetToManagedCallback<T4>()(args[4]),
- VariantConversionCallbacks.GetToManagedCallback<T5>()(args[5]),
- VariantConversionCallbacks.GetToManagedCallback<T6>()(args[6]),
- VariantConversionCallbacks.GetToManagedCallback<T7>()(args[7])
+ VariantUtils.ConvertTo<T0>(args[0]),
+ VariantUtils.ConvertTo<T1>(args[1]),
+ VariantUtils.ConvertTo<T2>(args[2]),
+ VariantUtils.ConvertTo<T3>(args[3]),
+ VariantUtils.ConvertTo<T4>(args[4]),
+ VariantUtils.ConvertTo<T5>(args[5]),
+ VariantUtils.ConvertTo<T6>(args[6]),
+ VariantUtils.ConvertTo<T7>(args[7])
);
- ret = VariantConversionCallbacks.GetToVariantCallback<TResult>()(res);
+ ret = VariantUtils.CreateFrom(res);
}
return CreateWithUnsafeTrampoline(func, &Trampoline);
@@ -461,18 +461,18 @@ public readonly partial struct Callable
ThrowIfArgCountMismatch(args, 9);
TResult res = ((Func<T0, T1, T2, T3, T4, T5, T6, T7, T8, TResult>)delegateObj)(
- VariantConversionCallbacks.GetToManagedCallback<T0>()(args[0]),
- VariantConversionCallbacks.GetToManagedCallback<T1>()(args[1]),
- VariantConversionCallbacks.GetToManagedCallback<T2>()(args[2]),
- VariantConversionCallbacks.GetToManagedCallback<T3>()(args[3]),
- VariantConversionCallbacks.GetToManagedCallback<T4>()(args[4]),
- VariantConversionCallbacks.GetToManagedCallback<T5>()(args[5]),
- VariantConversionCallbacks.GetToManagedCallback<T6>()(args[6]),
- VariantConversionCallbacks.GetToManagedCallback<T7>()(args[7]),
- VariantConversionCallbacks.GetToManagedCallback<T8>()(args[8])
+ VariantUtils.ConvertTo<T0>(args[0]),
+ VariantUtils.ConvertTo<T1>(args[1]),
+ VariantUtils.ConvertTo<T2>(args[2]),
+ VariantUtils.ConvertTo<T3>(args[3]),
+ VariantUtils.ConvertTo<T4>(args[4]),
+ VariantUtils.ConvertTo<T5>(args[5]),
+ VariantUtils.ConvertTo<T6>(args[6]),
+ VariantUtils.ConvertTo<T7>(args[7]),
+ VariantUtils.ConvertTo<T8>(args[8])
);
- ret = VariantConversionCallbacks.GetToVariantCallback<TResult>()(res);
+ ret = VariantUtils.CreateFrom(res);
}
return CreateWithUnsafeTrampoline(func, &Trampoline);
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs
index ee9e59f9fa..4075a878d2 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs
@@ -1,5 +1,6 @@
using System;
using System.Runtime.InteropServices;
+using Godot.NativeInterop;
namespace Godot
{
@@ -43,7 +44,7 @@ namespace Godot
/// <value>Getting is equivalent to multiplying by 255 and rounding. Setting is equivalent to dividing by 255.</value>
public int r8
{
- get
+ readonly get
{
return (int)Math.Round(r * 255.0f);
}
@@ -59,7 +60,7 @@ namespace Godot
/// <value>Getting is equivalent to multiplying by 255 and rounding. Setting is equivalent to dividing by 255.</value>
public int g8
{
- get
+ readonly get
{
return (int)Math.Round(g * 255.0f);
}
@@ -75,7 +76,7 @@ namespace Godot
/// <value>Getting is equivalent to multiplying by 255 and rounding. Setting is equivalent to dividing by 255.</value>
public int b8
{
- get
+ readonly get
{
return (int)Math.Round(b * 255.0f);
}
@@ -91,7 +92,7 @@ namespace Godot
/// <value>Getting is equivalent to multiplying by 255 and rounding. Setting is equivalent to dividing by 255.</value>
public int a8
{
- get
+ readonly get
{
return (int)Math.Round(a * 255.0f);
}
@@ -107,7 +108,7 @@ namespace Godot
/// <value>Getting is a long process, refer to the source code for details. Setting uses <see cref="FromHSV"/>.</value>
public float h
{
- get
+ readonly get
{
float max = Math.Max(r, Math.Max(g, b));
float min = Math.Min(r, Math.Min(g, b));
@@ -155,7 +156,7 @@ namespace Godot
/// <value>Getting is equivalent to the ratio between the min and max RGB value. Setting uses <see cref="FromHSV"/>.</value>
public float s
{
- get
+ readonly get
{
float max = Math.Max(r, Math.Max(g, b));
float min = Math.Min(r, Math.Min(g, b));
@@ -176,7 +177,7 @@ namespace Godot
/// <value>Getting is equivalent to using <see cref="Math.Max(float, float)"/> on the RGB components. Setting uses <see cref="FromHSV"/>.</value>
public float v
{
- get
+ readonly get
{
return Math.Max(r, Math.Max(g, b));
}
@@ -187,6 +188,19 @@ namespace Godot
}
/// <summary>
+ /// Returns the light intensity of the color, as a value between 0.0 and 1.0 (inclusive).
+ /// This is useful when determining light or dark color. Colors with a luminance smaller
+ /// than 0.5 can be generally considered dark.
+ /// Note: <see cref="Luminance"/> relies on the color being in the linear color space to
+ /// return an accurate relative luminance value. If the color is in the sRGB color space
+ /// use <see cref="SrgbToLinear"/> to convert it to the linear color space first.
+ /// </summary>
+ public readonly float Luminance
+ {
+ get { return 0.2126f * r + 0.7152f * g + 0.0722f * b; }
+ }
+
+ /// <summary>
/// Access color components using their index.
/// </summary>
/// <value>
@@ -197,7 +211,7 @@ namespace Godot
/// </value>
public float this[int index]
{
- get
+ readonly get
{
switch (index)
{
@@ -242,7 +256,7 @@ namespace Godot
/// </summary>
/// <param name="over">The color to blend over.</param>
/// <returns>This color blended over <paramref name="over"/>.</returns>
- public Color Blend(Color over)
+ public readonly Color Blend(Color over)
{
Color res;
@@ -269,7 +283,7 @@ namespace Godot
/// <param name="min">The color with minimum allowed values.</param>
/// <param name="max">The color with maximum allowed values.</param>
/// <returns>The color with all components clamped.</returns>
- public Color Clamp(Color? min = null, Color? max = null)
+ public readonly Color Clamp(Color? min = null, Color? max = null)
{
Color minimum = min ?? new Color(0, 0, 0, 0);
Color maximum = max ?? new Color(1, 1, 1, 1);
@@ -288,7 +302,7 @@ namespace Godot
/// </summary>
/// <param name="amount">The ratio to darken by.</param>
/// <returns>The darkened color.</returns>
- public Color Darkened(float amount)
+ public readonly Color Darkened(float amount)
{
Color res = this;
res.r *= 1.0f - amount;
@@ -301,7 +315,7 @@ namespace Godot
/// Returns the inverted color: <c>(1 - r, 1 - g, 1 - b, a)</c>.
/// </summary>
/// <returns>The inverted color.</returns>
- public Color Inverted()
+ public readonly Color Inverted()
{
return new Color(
1.0f - r,
@@ -317,7 +331,7 @@ namespace Godot
/// </summary>
/// <param name="amount">The ratio to lighten by.</param>
/// <returns>The darkened color.</returns>
- public Color Lightened(float amount)
+ public readonly Color Lightened(float amount)
{
Color res = this;
res.r += (1.0f - res.r) * amount;
@@ -333,7 +347,7 @@ namespace Godot
/// <param name="to">The destination color 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 color of the interpolation.</returns>
- public Color Lerp(Color to, real_t weight)
+ public readonly Color Lerp(Color to, real_t weight)
{
return new Color
(
@@ -351,7 +365,7 @@ namespace Godot
/// <param name="to">The destination color for interpolation.</param>
/// <param name="weight">A color with components on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
/// <returns>The resulting color of the interpolation.</returns>
- public Color Lerp(Color to, Color weight)
+ public readonly Color Lerp(Color to, Color weight)
{
return new Color
(
@@ -363,12 +377,41 @@ namespace Godot
}
/// <summary>
+ /// Returns the color converted to the sRGB color space.
+ /// This method assumes the original color is in the linear color space.
+ /// See also <see cref="SrgbToLinear"/> which performs the opposite operation.
+ /// </summary>
+ /// <returns>The sRGB color.</returns>
+ public readonly Color LinearToSrgb()
+ {
+ return new Color(
+ r < 0.0031308f ? 12.92f * r : (1.0f + 0.055f) * (float)Mathf.Pow(r, 1.0f / 2.4f) - 0.055f,
+ g < 0.0031308f ? 12.92f * g : (1.0f + 0.055f) * (float)Mathf.Pow(g, 1.0f / 2.4f) - 0.055f,
+ b < 0.0031308f ? 12.92f * b : (1.0f + 0.055f) * (float)Mathf.Pow(b, 1.0f / 2.4f) - 0.055f, a);
+ }
+
+ /// <summary>
+ /// Returns the color converted to linear color space.
+ /// This method assumes the original color already is in sRGB color space.
+ /// See also <see cref="LinearToSrgb"/> which performs the opposite operation.
+ /// </summary>
+ /// <returns>The color in linear color space.</returns>
+ public readonly Color SrgbToLinear()
+ {
+ return new Color(
+ r < 0.04045f ? r * (1.0f / 12.92f) : (float)Mathf.Pow((r + 0.055f) * (float)(1.0 / (1.0 + 0.055)), 2.4f),
+ g < 0.04045f ? g * (1.0f / 12.92f) : (float)Mathf.Pow((g + 0.055f) * (float)(1.0 / (1.0 + 0.055)), 2.4f),
+ b < 0.04045f ? b * (1.0f / 12.92f) : (float)Mathf.Pow((b + 0.055f) * (float)(1.0 / (1.0 + 0.055)), 2.4f),
+ a);
+ }
+
+ /// <summary>
/// Returns the color converted to an unsigned 32-bit integer in ABGR
/// format (each byte represents a color channel).
/// ABGR is the reversed version of the default format.
/// </summary>
/// <returns>A <see langword="uint"/> representing this color in ABGR32 format.</returns>
- public uint ToAbgr32()
+ public readonly uint ToAbgr32()
{
uint c = (byte)Math.Round(a * 255);
c <<= 8;
@@ -387,7 +430,7 @@ namespace Godot
/// ABGR is the reversed version of the default format.
/// </summary>
/// <returns>A <see langword="ulong"/> representing this color in ABGR64 format.</returns>
- public ulong ToAbgr64()
+ public readonly ulong ToAbgr64()
{
ulong c = (ushort)Math.Round(a * 65535);
c <<= 16;
@@ -406,7 +449,7 @@ namespace Godot
/// ARGB is more compatible with DirectX, but not used much in Godot.
/// </summary>
/// <returns>A <see langword="uint"/> representing this color in ARGB32 format.</returns>
- public uint ToArgb32()
+ public readonly uint ToArgb32()
{
uint c = (byte)Math.Round(a * 255);
c <<= 8;
@@ -425,7 +468,7 @@ namespace Godot
/// ARGB is more compatible with DirectX, but not used much in Godot.
/// </summary>
/// <returns>A <see langword="ulong"/> representing this color in ARGB64 format.</returns>
- public ulong ToArgb64()
+ public readonly ulong ToArgb64()
{
ulong c = (ushort)Math.Round(a * 65535);
c <<= 16;
@@ -444,7 +487,7 @@ namespace Godot
/// RGBA is Godot's default and recommended format.
/// </summary>
/// <returns>A <see langword="uint"/> representing this color in RGBA32 format.</returns>
- public uint ToRgba32()
+ public readonly uint ToRgba32()
{
uint c = (byte)Math.Round(r * 255);
c <<= 8;
@@ -463,7 +506,7 @@ namespace Godot
/// RGBA is Godot's default and recommended format.
/// </summary>
/// <returns>A <see langword="ulong"/> representing this color in RGBA64 format.</returns>
- public ulong ToRgba64()
+ public readonly ulong ToRgba64()
{
ulong c = (ushort)Math.Round(r * 65535);
c <<= 16;
@@ -483,7 +526,7 @@ namespace Godot
/// Whether or not to include alpha. If <see langword="false"/>, the color is RGB instead of RGBA.
/// </param>
/// <returns>A string for the HTML hexadecimal representation of this color.</returns>
- public string ToHTML(bool includeAlpha = true)
+ public readonly string ToHTML(bool includeAlpha = true)
{
string txt = string.Empty;
@@ -565,6 +608,10 @@ namespace Godot
/// <see cref="Colors"/> constants.
/// </summary>
/// <param name="code">The HTML color code or color name to construct from.</param>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// A color cannot be inferred from the given <paramref name="code"/>.
+ /// It was invalid HTML and a color with that name was not found.
+ /// </exception>
public Color(string code)
{
if (HtmlIsValid(code))
@@ -597,7 +644,7 @@ namespace Godot
/// <exception name="ArgumentOutOfRangeException">
/// <paramref name="rgba"/> color code is invalid.
/// </exception>
- private static Color FromHTML(ReadOnlySpan<char> rgba)
+ public static Color FromHTML(ReadOnlySpan<char> rgba)
{
Color c;
if (rgba.Length == 0)
@@ -705,28 +752,59 @@ namespace Godot
/// the constants defined in <see cref="Colors"/>.
/// </summary>
/// <param name="name">The name of the color.</param>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// A color with the given name is not found.
+ /// </exception>
/// <returns>The constructed color.</returns>
private static Color Named(string name)
{
+ if (!FindNamedColor(name, out Color color))
+ {
+ throw new ArgumentOutOfRangeException($"Invalid Color Name: {name}");
+ }
+
+ return color;
+ }
+
+ /// <summary>
+ /// Returns a color according to the standardized name, with the
+ /// specified alpha value. Supported color names are the same as
+ /// the constants defined in <see cref="Colors"/>.
+ /// If a color with the given name is not found, it returns
+ /// <paramref name="default"/>.
+ /// </summary>
+ /// <param name="name">The name of the color.</param>
+ /// <param name="default">
+ /// The default color to return when a color with the given name
+ /// is not found.
+ /// </param>
+ /// <returns>The constructed color.</returns>
+ private static Color Named(string name, Color @default)
+ {
+ if (!FindNamedColor(name, out Color color))
+ {
+ return @default;
+ }
+
+ return color;
+ }
+
+ private static bool FindNamedColor(string name, out Color color)
+ {
name = name.Replace(" ", string.Empty);
name = name.Replace("-", string.Empty);
name = name.Replace("_", string.Empty);
name = name.Replace("'", string.Empty);
name = name.Replace(".", string.Empty);
- name = name.ToUpper();
-
- if (!Colors.namedColors.ContainsKey(name))
- {
- throw new ArgumentOutOfRangeException($"Invalid Color Name: {name}");
- }
+ name = name.ToUpperInvariant();
- return Colors.namedColors[name];
+ return Colors.namedColors.TryGetValue(name, out color);
}
/// <summary>
- /// Constructs a color from an HSV profile, with values on the
- /// range of 0 to 1. This is equivalent to using each of
- /// the <c>h</c>/<c>s</c>/<c>v</c> properties, but much more efficient.
+ /// Constructs a color from an HSV profile. The <paramref name="hue"/>,
+ /// <paramref name="saturation"/>, and <paramref name="value"/> are typically
+ /// between 0.0 and 1.0.
/// </summary>
/// <param name="hue">The HSV hue, typically on the range of 0 to 1.</param>
/// <param name="saturation">The HSV saturation, typically on the range of 0 to 1.</param>
@@ -777,7 +855,7 @@ namespace Godot
/// <param name="hue">Output parameter for the HSV hue.</param>
/// <param name="saturation">Output parameter for the HSV saturation.</param>
/// <param name="value">Output parameter for the HSV value.</param>
- public void ToHSV(out float hue, out float saturation, out float value)
+ public readonly void ToHSV(out float hue, out float saturation, out float value)
{
float max = (float)Mathf.Max(r, Mathf.Max(g, b));
float min = (float)Mathf.Min(r, Mathf.Min(g, b));
@@ -841,13 +919,78 @@ namespace Godot
return ParseCol4(str, index) * 16 + ParseCol4(str, index + 1);
}
+ /// <summary>
+ /// Constructs a color from an OK HSL profile. The <paramref name="hue"/>,
+ /// <paramref name="saturation"/>, and <paramref name="lightness"/> are typically
+ /// between 0.0 and 1.0.
+ /// </summary>
+ /// <param name="hue">The OK HSL hue, typically on the range of 0 to 1.</param>
+ /// <param name="saturation">The OK HSL saturation, typically on the range of 0 to 1.</param>
+ /// <param name="lightness">The OK HSL lightness, typically on the range of 0 to 1.</param>
+ /// <param name="alpha">The alpha (transparency) value, typically on the range of 0 to 1.</param>
+ /// <returns>The constructed color.</returns>
+ public static Color FromOkHsl(float hue, float saturation, float lightness, float alpha = 1.0f)
+ {
+ return NativeFuncs.godotsharp_color_from_ok_hsl(hue, saturation, lightness, alpha);
+ }
+
+ /// <summary>
+ /// Encodes a <see cref="Color"/> from a RGBE9995 format integer.
+ /// See <see cref="Image.Format.Rgbe9995"/>.
+ /// </summary>
+ /// <param name="rgbe">The RGBE9995 encoded color.</param>
+ /// <returns>The constructed color.</returns>
+ public static Color FromRgbe9995(uint rgbe)
+ {
+ float r = rgbe & 0x1ff;
+ float g = (rgbe >> 9) & 0x1ff;
+ float b = (rgbe >> 18) & 0x1ff;
+ float e = rgbe >> 27;
+ float m = (float)Mathf.Pow(2.0f, e - 15.0f - 9.0f);
+
+ float rd = r * m;
+ float gd = g * m;
+ float bd = b * m;
+
+ return new Color(rd, gd, bd, 1.0f);
+ }
+
+ /// <summary>
+ /// Constructs a color from the given string, which can be either an HTML color
+ /// code or a named color. Returns <paramref name="default"/> if the color cannot
+ /// be inferred from the string. Supported color names are the same as the
+ /// <see cref="Colors"/> constants.
+ /// </summary>
+ /// <param name="str">The HTML color code or color name.</param>
+ /// <param name="default">The fallback color to return if the color cannot be inferred.</param>
+ /// <returns>The constructed color.</returns>
+ public static Color FromString(string str, Color @default)
+ {
+ if (HtmlIsValid(str))
+ {
+ return FromHTML(str);
+ }
+ else
+ {
+ return Named(str, @default);
+ }
+ }
+
private static string ToHex32(float val)
{
byte b = (byte)Mathf.RoundToInt(Mathf.Clamp(val * 255, 0, 255));
return b.HexEncode();
}
- internal static bool HtmlIsValid(ReadOnlySpan<char> color)
+ /// <summary>
+ /// Returns <see langword="true"/> if <paramref name="color"/> is a valid HTML hexadecimal
+ /// color string. The string must be a hexadecimal value (case-insensitive) of either 3,
+ /// 4, 6 or 8 digits, and may be prefixed by a hash sign (<c>#</c>). This method is
+ /// identical to <see cref="StringExtensions.IsValidHtmlColor(string)"/>.
+ /// </summary>
+ /// <param name="color">The HTML hexadecimal color string.</param>
+ /// <returns>Whether or not the string was a valid HTML hexadecimal color string.</returns>
+ public static bool HtmlIsValid(ReadOnlySpan<char> color)
{
if (color.IsEmpty)
{
@@ -1149,7 +1292,7 @@ namespace Godot
/// </summary>
/// <param name="obj">The other object to compare.</param>
/// <returns>Whether or not the color and the other object are equal.</returns>
- public override bool Equals(object obj)
+ public override readonly bool Equals(object obj)
{
return obj is Color other && Equals(other);
}
@@ -1161,7 +1304,7 @@ namespace Godot
/// </summary>
/// <param name="other">The other color.</param>
/// <returns>Whether or not the colors are equal.</returns>
- public bool Equals(Color other)
+ public readonly bool Equals(Color other)
{
return r == other.r && g == other.g && b == other.b && a == other.a;
}
@@ -1172,7 +1315,7 @@ namespace Godot
/// </summary>
/// <param name="other">The other color to compare.</param>
/// <returns>Whether or not the colors are approximately equal.</returns>
- public bool IsEqualApprox(Color other)
+ public readonly bool IsEqualApprox(Color other)
{
return Mathf.IsEqualApprox(r, other.r) && Mathf.IsEqualApprox(g, other.g) && Mathf.IsEqualApprox(b, other.b) && Mathf.IsEqualApprox(a, other.a);
}
@@ -1181,7 +1324,7 @@ namespace Godot
/// Serves as the hash function for <see cref="Color"/>.
/// </summary>
/// <returns>A hash code for this color.</returns>
- public override int GetHashCode()
+ public override readonly int GetHashCode()
{
return r.GetHashCode() ^ g.GetHashCode() ^ b.GetHashCode() ^ a.GetHashCode();
}
@@ -1190,7 +1333,7 @@ namespace Godot
/// Converts this <see cref="Color"/> to a string.
/// </summary>
/// <returns>A string representation of this color.</returns>
- public override string ToString()
+ public override readonly string ToString()
{
return $"({r}, {g}, {b}, {a})";
}
@@ -1199,7 +1342,7 @@ namespace Godot
/// Converts this <see cref="Color"/> to a string with the given <paramref name="format"/>.
/// </summary>
/// <returns>A string representation of this color.</returns>
- public string ToString(string format)
+ public readonly string ToString(string format)
{
return $"({r.ToString(format)}, {g.ToString(format)}, {b.ToString(format)}, {a.ToString(format)})";
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/DelegateUtils.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/DelegateUtils.cs
index d19e0c08f2..d94fbff331 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/DelegateUtils.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/DelegateUtils.cs
@@ -186,7 +186,7 @@ namespace Godot
writer.Write(field.Name);
var fieldValue = field.GetValue(target);
- using var fieldValueVariant = Marshaling.ConvertManagedObjectToVariant(fieldValue);
+ using var fieldValueVariant = RuntimeTypeConversionHelper.ConvertToVariant(fieldValue);
byte[] valueBuffer = VarToBytes(fieldValueVariant);
writer.Write(valueBuffer.Length);
writer.Write(valueBuffer);
@@ -443,7 +443,14 @@ namespace Godot
FieldInfo? fieldInfo = targetType.GetField(name,
BindingFlags.Instance | BindingFlags.Public);
- fieldInfo?.SetValue(recreatedTarget, GD.BytesToVar(valueBuffer));
+
+ if (fieldInfo != null)
+ {
+ var variantValue = GD.BytesToVar(valueBuffer);
+ object? managedValue = RuntimeTypeConversionHelper.ConvertToObjectOfType(
+ (godot_variant)variantValue.NativeVar, fieldInfo.FieldType);
+ fieldInfo.SetValue(recreatedTarget, managedValue);
+ }
}
@delegate = Delegate.CreateDelegate(delegateType, recreatedTarget, methodInfo,
@@ -537,5 +544,289 @@ namespace Godot
return type;
}
+
+ internal static class RuntimeTypeConversionHelper
+ {
+ [SuppressMessage("ReSharper", "RedundantNameQualifier")]
+ public static godot_variant ConvertToVariant(object? obj)
+ {
+ if (obj == null)
+ return default;
+
+ switch (obj)
+ {
+ case bool @bool:
+ return VariantUtils.CreateFrom(@bool);
+ case char @char:
+ return VariantUtils.CreateFrom(@char);
+ case sbyte int8:
+ return VariantUtils.CreateFrom(int8);
+ case short int16:
+ return VariantUtils.CreateFrom(int16);
+ case int int32:
+ return VariantUtils.CreateFrom(int32);
+ case long int64:
+ return VariantUtils.CreateFrom(int64);
+ case byte uint8:
+ return VariantUtils.CreateFrom(uint8);
+ case ushort uint16:
+ return VariantUtils.CreateFrom(uint16);
+ case uint uint32:
+ return VariantUtils.CreateFrom(uint32);
+ case ulong uint64:
+ return VariantUtils.CreateFrom(uint64);
+ case float @float:
+ return VariantUtils.CreateFrom(@float);
+ case double @double:
+ return VariantUtils.CreateFrom(@double);
+ case Vector2 vector2:
+ return VariantUtils.CreateFrom(vector2);
+ case Vector2i vector2I:
+ return VariantUtils.CreateFrom(vector2I);
+ case Rect2 rect2:
+ return VariantUtils.CreateFrom(rect2);
+ case Rect2i rect2I:
+ return VariantUtils.CreateFrom(rect2I);
+ case Transform2D transform2D:
+ return VariantUtils.CreateFrom(transform2D);
+ case Vector3 vector3:
+ return VariantUtils.CreateFrom(vector3);
+ case Vector3i vector3I:
+ return VariantUtils.CreateFrom(vector3I);
+ case Vector4 vector4:
+ return VariantUtils.CreateFrom(vector4);
+ case Vector4i vector4I:
+ return VariantUtils.CreateFrom(vector4I);
+ case Basis basis:
+ return VariantUtils.CreateFrom(basis);
+ case Quaternion quaternion:
+ return VariantUtils.CreateFrom(quaternion);
+ case Transform3D transform3d:
+ return VariantUtils.CreateFrom(transform3d);
+ case Projection projection:
+ return VariantUtils.CreateFrom(projection);
+ case AABB aabb:
+ return VariantUtils.CreateFrom(aabb);
+ case Color color:
+ return VariantUtils.CreateFrom(color);
+ case Plane plane:
+ return VariantUtils.CreateFrom(plane);
+ case Callable callable:
+ return VariantUtils.CreateFrom(callable);
+ case Signal signal:
+ return VariantUtils.CreateFrom(signal);
+ case string @string:
+ return VariantUtils.CreateFrom(@string);
+ case byte[] byteArray:
+ return VariantUtils.CreateFrom(byteArray);
+ case int[] int32Array:
+ return VariantUtils.CreateFrom(int32Array);
+ case long[] int64Array:
+ return VariantUtils.CreateFrom(int64Array);
+ case float[] floatArray:
+ return VariantUtils.CreateFrom(floatArray);
+ case double[] doubleArray:
+ return VariantUtils.CreateFrom(doubleArray);
+ case string[] stringArray:
+ return VariantUtils.CreateFrom(stringArray);
+ case Vector2[] vector2Array:
+ return VariantUtils.CreateFrom(vector2Array);
+ case Vector3[] vector3Array:
+ return VariantUtils.CreateFrom(vector3Array);
+ case Color[] colorArray:
+ return VariantUtils.CreateFrom(colorArray);
+ case StringName[] stringNameArray:
+ return VariantUtils.CreateFrom(stringNameArray);
+ case NodePath[] nodePathArray:
+ return VariantUtils.CreateFrom(nodePathArray);
+ case RID[] ridArray:
+ return VariantUtils.CreateFrom(ridArray);
+ case Godot.Object[] godotObjectArray:
+ return VariantUtils.CreateFrom(godotObjectArray);
+ case StringName stringName:
+ return VariantUtils.CreateFrom(stringName);
+ case NodePath nodePath:
+ return VariantUtils.CreateFrom(nodePath);
+ case RID rid:
+ return VariantUtils.CreateFrom(rid);
+ case Collections.Dictionary godotDictionary:
+ return VariantUtils.CreateFrom(godotDictionary);
+ case Collections.Array godotArray:
+ return VariantUtils.CreateFrom(godotArray);
+ case Variant variant:
+ return VariantUtils.CreateFrom(variant);
+ case Godot.Object godotObject:
+ return VariantUtils.CreateFrom(godotObject);
+ case Enum @enum:
+ return VariantUtils.CreateFrom(Convert.ToInt64(@enum));
+ case Collections.IGenericGodotDictionary godotDictionary:
+ return VariantUtils.CreateFrom(godotDictionary.UnderlyingDictionary);
+ case Collections.IGenericGodotArray godotArray:
+ return VariantUtils.CreateFrom(godotArray.UnderlyingArray);
+ }
+
+ GD.PushError("Attempted to convert an unmarshallable managed type to Variant. Name: '" +
+ obj.GetType().FullName + ".");
+ return new godot_variant();
+ }
+
+ private delegate object? ConvertToSystemObjectFunc(in godot_variant managed);
+
+ [SuppressMessage("ReSharper", "RedundantNameQualifier")]
+ // ReSharper disable once RedundantNameQualifier
+ private static readonly System.Collections.Generic.Dictionary<Type, ConvertToSystemObjectFunc>
+ ToSystemObjectFuncByType = new()
+ {
+ [typeof(bool)] = (in godot_variant variant) => VariantUtils.ConvertTo<bool>(variant),
+ [typeof(char)] = (in godot_variant variant) => VariantUtils.ConvertTo<char>(variant),
+ [typeof(sbyte)] = (in godot_variant variant) => VariantUtils.ConvertTo<sbyte>(variant),
+ [typeof(short)] = (in godot_variant variant) => VariantUtils.ConvertTo<short>(variant),
+ [typeof(int)] = (in godot_variant variant) => VariantUtils.ConvertTo<int>(variant),
+ [typeof(long)] = (in godot_variant variant) => VariantUtils.ConvertTo<long>(variant),
+ [typeof(byte)] = (in godot_variant variant) => VariantUtils.ConvertTo<byte>(variant),
+ [typeof(ushort)] = (in godot_variant variant) => VariantUtils.ConvertTo<ushort>(variant),
+ [typeof(uint)] = (in godot_variant variant) => VariantUtils.ConvertTo<uint>(variant),
+ [typeof(ulong)] = (in godot_variant variant) => VariantUtils.ConvertTo<ulong>(variant),
+ [typeof(float)] = (in godot_variant variant) => VariantUtils.ConvertTo<float>(variant),
+ [typeof(double)] = (in godot_variant variant) => VariantUtils.ConvertTo<double>(variant),
+ [typeof(Vector2)] = (in godot_variant variant) => VariantUtils.ConvertTo<Vector2>(variant),
+ [typeof(Vector2i)] = (in godot_variant variant) => VariantUtils.ConvertTo<Vector2i>(variant),
+ [typeof(Rect2)] = (in godot_variant variant) => VariantUtils.ConvertTo<Rect2>(variant),
+ [typeof(Rect2i)] = (in godot_variant variant) => VariantUtils.ConvertTo<Rect2i>(variant),
+ [typeof(Transform2D)] = (in godot_variant variant) => VariantUtils.ConvertTo<Transform2D>(variant),
+ [typeof(Vector3)] = (in godot_variant variant) => VariantUtils.ConvertTo<Vector3>(variant),
+ [typeof(Vector3i)] = (in godot_variant variant) => VariantUtils.ConvertTo<Vector3i>(variant),
+ [typeof(Basis)] = (in godot_variant variant) => VariantUtils.ConvertTo<Basis>(variant),
+ [typeof(Quaternion)] = (in godot_variant variant) => VariantUtils.ConvertTo<Quaternion>(variant),
+ [typeof(Transform3D)] = (in godot_variant variant) => VariantUtils.ConvertTo<Transform3D>(variant),
+ [typeof(Vector4)] = (in godot_variant variant) => VariantUtils.ConvertTo<Vector4>(variant),
+ [typeof(Vector4i)] = (in godot_variant variant) => VariantUtils.ConvertTo<Vector4i>(variant),
+ [typeof(AABB)] = (in godot_variant variant) => VariantUtils.ConvertTo<AABB>(variant),
+ [typeof(Color)] = (in godot_variant variant) => VariantUtils.ConvertTo<Color>(variant),
+ [typeof(Plane)] = (in godot_variant variant) => VariantUtils.ConvertTo<Plane>(variant),
+ [typeof(Callable)] = (in godot_variant variant) => VariantUtils.ConvertTo<Callable>(variant),
+ [typeof(Signal)] = (in godot_variant variant) => VariantUtils.ConvertTo<Signal>(variant),
+ [typeof(string)] = (in godot_variant variant) => VariantUtils.ConvertTo<string>(variant),
+ [typeof(byte[])] = (in godot_variant variant) => VariantUtils.ConvertTo<byte[]>(variant),
+ [typeof(int[])] = (in godot_variant variant) => VariantUtils.ConvertTo<int[]>(variant),
+ [typeof(long[])] = (in godot_variant variant) => VariantUtils.ConvertTo<long[]>(variant),
+ [typeof(float[])] = (in godot_variant variant) => VariantUtils.ConvertTo<float[]>(variant),
+ [typeof(double[])] = (in godot_variant variant) => VariantUtils.ConvertTo<double[]>(variant),
+ [typeof(string[])] = (in godot_variant variant) => VariantUtils.ConvertTo<string[]>(variant),
+ [typeof(Vector2[])] = (in godot_variant variant) => VariantUtils.ConvertTo<Vector2[]>(variant),
+ [typeof(Vector3[])] = (in godot_variant variant) => VariantUtils.ConvertTo<Vector3[]>(variant),
+ [typeof(Color[])] = (in godot_variant variant) => VariantUtils.ConvertTo<Color[]>(variant),
+ [typeof(StringName[])] =
+ (in godot_variant variant) => VariantUtils.ConvertTo<StringName[]>(variant),
+ [typeof(NodePath[])] = (in godot_variant variant) => VariantUtils.ConvertTo<NodePath[]>(variant),
+ [typeof(RID[])] = (in godot_variant variant) => VariantUtils.ConvertTo<RID[]>(variant),
+ [typeof(StringName)] = (in godot_variant variant) => VariantUtils.ConvertTo<StringName>(variant),
+ [typeof(NodePath)] = (in godot_variant variant) => VariantUtils.ConvertTo<NodePath>(variant),
+ [typeof(RID)] = (in godot_variant variant) => VariantUtils.ConvertTo<RID>(variant),
+ [typeof(Godot.Collections.Dictionary)] = (in godot_variant variant) =>
+ VariantUtils.ConvertTo<Godot.Collections.Dictionary>(variant),
+ [typeof(Godot.Collections.Array)] =
+ (in godot_variant variant) => VariantUtils.ConvertTo<Godot.Collections.Array>(variant),
+ [typeof(Variant)] = (in godot_variant variant) => VariantUtils.ConvertTo<Variant>(variant),
+ };
+
+ [SuppressMessage("ReSharper", "RedundantNameQualifier")]
+ public static object? ConvertToObjectOfType(in godot_variant variant, Type type)
+ {
+ if (ToSystemObjectFuncByType.TryGetValue(type, out var func))
+ return func(variant);
+
+ if (typeof(Godot.Object).IsAssignableFrom(type))
+ return Convert.ChangeType(VariantUtils.ConvertTo<Godot.Object>(variant), type);
+
+ if (typeof(Godot.Object[]).IsAssignableFrom(type))
+ {
+ static Godot.Object[] ConvertToSystemArrayOfGodotObject(in godot_array nativeArray, Type type)
+ {
+ var array = Collections.Array.CreateTakingOwnershipOfDisposableValue(
+ NativeFuncs.godotsharp_array_new_copy(nativeArray));
+
+ int length = array.Count;
+ var ret = (Godot.Object[])Activator.CreateInstance(type, length)!;
+
+ for (int i = 0; i < length; i++)
+ ret[i] = array[i].AsGodotObject();
+
+ return ret;
+ }
+
+ using var godotArray = NativeFuncs.godotsharp_variant_as_array(variant);
+ return Convert.ChangeType(ConvertToSystemArrayOfGodotObject(godotArray, type), type);
+ }
+
+ if (type.IsEnum)
+ {
+ var enumUnderlyingType = type.GetEnumUnderlyingType();
+
+ switch (Type.GetTypeCode(enumUnderlyingType))
+ {
+ case TypeCode.SByte:
+ return Enum.ToObject(type, VariantUtils.ConvertToInt8(variant));
+ case TypeCode.Int16:
+ return Enum.ToObject(type, VariantUtils.ConvertToInt16(variant));
+ case TypeCode.Int32:
+ return Enum.ToObject(type, VariantUtils.ConvertToInt32(variant));
+ case TypeCode.Int64:
+ return Enum.ToObject(type, VariantUtils.ConvertToInt64(variant));
+ case TypeCode.Byte:
+ return Enum.ToObject(type, VariantUtils.ConvertToUInt8(variant));
+ case TypeCode.UInt16:
+ return Enum.ToObject(type, VariantUtils.ConvertToUInt16(variant));
+ case TypeCode.UInt32:
+ return Enum.ToObject(type, VariantUtils.ConvertToUInt32(variant));
+ case TypeCode.UInt64:
+ return Enum.ToObject(type, VariantUtils.ConvertToUInt64(variant));
+ default:
+ {
+ GD.PushError(
+ "Attempted to convert Variant to enum value of unsupported underlying type. Name: " +
+ type.FullName + " : " + enumUnderlyingType.FullName + ".");
+ return null;
+ }
+ }
+ }
+
+ if (type.IsGenericType)
+ {
+ var genericTypeDef = type.GetGenericTypeDefinition();
+
+ if (genericTypeDef == typeof(Godot.Collections.Dictionary<,>))
+ {
+ var ctor = type.GetConstructor(BindingFlags.Default,
+ new[] { typeof(Godot.Collections.Dictionary) });
+
+ if (ctor == null)
+ throw new InvalidOperationException("Dictionary constructor not found");
+
+ return ctor.Invoke(new object?[]
+ {
+ VariantUtils.ConvertTo<Godot.Collections.Dictionary>(variant)
+ });
+ }
+
+ if (genericTypeDef == typeof(Godot.Collections.Array<>))
+ {
+ var ctor = type.GetConstructor(BindingFlags.Default,
+ new[] { typeof(Godot.Collections.Array) });
+
+ if (ctor == null)
+ throw new InvalidOperationException("Array constructor not found");
+
+ return ctor.Invoke(new object?[]
+ {
+ VariantUtils.ConvertTo<Godot.Collections.Array>(variant)
+ });
+ }
+ }
+
+ GD.PushError($"Attempted to convert Variant to unsupported type. Name: {type.FullName}.");
+ return null;
+ }
+ }
}
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Dictionary.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Dictionary.cs
index f8793332a0..b5a8742d3d 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Dictionary.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Dictionary.cs
@@ -344,6 +344,11 @@ namespace Godot.Collections
}
}
+ internal interface IGenericGodotDictionary
+ {
+ public Dictionary UnderlyingDictionary { get; }
+ }
+
/// <summary>
/// Typed wrapper around Godot's Dictionary class, a dictionary of Variant
/// typed elements allocated in the engine in C++. Useful when
@@ -354,57 +359,25 @@ namespace Godot.Collections
/// <typeparam name="TValue">The type of the dictionary's values.</typeparam>
public class Dictionary<[MustBeVariant] TKey, [MustBeVariant] TValue> :
IDictionary<TKey, TValue>,
- IReadOnlyDictionary<TKey, TValue>
+ IReadOnlyDictionary<TKey, TValue>,
+ IGenericGodotDictionary
{
private static godot_variant ToVariantFunc(in Dictionary<TKey, TValue> godotDictionary) =>
VariantUtils.CreateFromDictionary(godotDictionary);
private static Dictionary<TKey, TValue> FromVariantFunc(in godot_variant variant) =>
- VariantUtils.ConvertToDictionaryObject<TKey, TValue>(variant);
-
- // ReSharper disable StaticMemberInGenericType
- // Warning is about unique static fields being created for each generic type combination:
- // https://www.jetbrains.com/help/resharper/StaticMemberInGenericType.html
- // In our case this is exactly what we want.
-
- private static readonly unsafe delegate* managed<in TKey, godot_variant> ConvertKeyToVariantCallback;
- private static readonly unsafe delegate* managed<in godot_variant, TKey> ConvertKeyToManagedCallback;
- private static readonly unsafe delegate* managed<in TValue, godot_variant> ConvertValueToVariantCallback;
- private static readonly unsafe delegate* managed<in godot_variant, TValue> ConvertValueToManagedCallback;
-
- // ReSharper restore StaticMemberInGenericType
+ VariantUtils.ConvertToDictionary<TKey, TValue>(variant);
static unsafe Dictionary()
{
- VariantConversionCallbacks.GenericConversionCallbacks[typeof(Dictionary<TKey, TValue>)] =
- (
- (IntPtr)(delegate* managed<in Dictionary<TKey, TValue>, godot_variant>)&ToVariantFunc,
- (IntPtr)(delegate* managed<in godot_variant, Dictionary<TKey, TValue>>)&FromVariantFunc
- );
-
- ConvertKeyToVariantCallback = VariantConversionCallbacks.GetToVariantCallback<TKey>();
- ConvertKeyToManagedCallback = VariantConversionCallbacks.GetToManagedCallback<TKey>();
- ConvertValueToVariantCallback = VariantConversionCallbacks.GetToVariantCallback<TValue>();
- ConvertValueToManagedCallback = VariantConversionCallbacks.GetToManagedCallback<TValue>();
- }
-
- private static unsafe void ValidateVariantConversionCallbacks()
- {
- if (ConvertKeyToVariantCallback == null || ConvertKeyToManagedCallback == null)
- {
- throw new InvalidOperationException(
- $"The dictionary key type is not supported for conversion to Variant: '{typeof(TKey).FullName}'.");
- }
-
- if (ConvertValueToVariantCallback == null || ConvertValueToManagedCallback == null)
- {
- throw new InvalidOperationException(
- $"The dictionary value type is not supported for conversion to Variant: '{typeof(TValue).FullName}'.");
- }
+ VariantUtils.GenericConversion<Dictionary<TKey, TValue>>.ToVariantCb = &ToVariantFunc;
+ VariantUtils.GenericConversion<Dictionary<TKey, TValue>>.FromVariantCb = &FromVariantFunc;
}
private readonly Dictionary _underlyingDict;
+ Dictionary IGenericGodotDictionary.UnderlyingDictionary => _underlyingDict;
+
internal ref godot_dictionary.movable NativeValue
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -416,8 +389,6 @@ namespace Godot.Collections
/// </summary>
public Dictionary()
{
- ValidateVariantConversionCallbacks();
-
_underlyingDict = new Dictionary();
}
@@ -428,8 +399,6 @@ namespace Godot.Collections
/// <returns>A new Godot Dictionary.</returns>
public Dictionary(IDictionary<TKey, TValue> dictionary)
{
- ValidateVariantConversionCallbacks();
-
if (dictionary == null)
throw new ArgumentNullException(nameof(dictionary));
@@ -446,8 +415,6 @@ namespace Godot.Collections
/// <returns>A new Godot Dictionary.</returns>
public Dictionary(Dictionary dictionary)
{
- ValidateVariantConversionCallbacks();
-
_underlyingDict = dictionary;
}
@@ -481,18 +448,18 @@ namespace Godot.Collections
/// Returns the value at the given <paramref name="key"/>.
/// </summary>
/// <value>The value at the given <paramref name="key"/>.</value>
- public unsafe TValue this[TKey key]
+ public TValue this[TKey key]
{
get
{
- using var variantKey = ConvertKeyToVariantCallback(key);
+ using var variantKey = VariantUtils.CreateFrom(key);
var self = (godot_dictionary)_underlyingDict.NativeValue;
if (NativeFuncs.godotsharp_dictionary_try_get_value(ref self,
variantKey, out godot_variant value).ToBool())
{
using (value)
- return ConvertValueToManagedCallback(value);
+ return VariantUtils.ConvertTo<TValue>(value);
}
else
{
@@ -501,8 +468,8 @@ namespace Godot.Collections
}
set
{
- using var variantKey = ConvertKeyToVariantCallback(key);
- using var variantValue = ConvertValueToVariantCallback(value);
+ using var variantKey = VariantUtils.CreateFrom(key);
+ using var variantValue = VariantUtils.CreateFrom(value);
var self = (godot_dictionary)_underlyingDict.NativeValue;
NativeFuncs.godotsharp_dictionary_set_value(ref self,
variantKey, variantValue);
@@ -541,7 +508,7 @@ namespace Godot.Collections
IEnumerable<TValue> IReadOnlyDictionary<TKey, TValue>.Values => Values;
- private unsafe KeyValuePair<TKey, TValue> GetKeyValuePair(int index)
+ private KeyValuePair<TKey, TValue> GetKeyValuePair(int index)
{
var self = (godot_dictionary)_underlyingDict.NativeValue;
NativeFuncs.godotsharp_dictionary_key_value_pair_at(ref self, index,
@@ -551,8 +518,8 @@ namespace Godot.Collections
using (value)
{
return new KeyValuePair<TKey, TValue>(
- ConvertKeyToManagedCallback(key),
- ConvertValueToManagedCallback(value));
+ VariantUtils.ConvertTo<TKey>(key),
+ VariantUtils.ConvertTo<TValue>(value));
}
}
@@ -562,15 +529,15 @@ namespace Godot.Collections
/// </summary>
/// <param name="key">The key at which to add the object.</param>
/// <param name="value">The object to add.</param>
- public unsafe void Add(TKey key, TValue value)
+ public void Add(TKey key, TValue value)
{
- using var variantKey = ConvertKeyToVariantCallback(key);
+ using var variantKey = VariantUtils.CreateFrom(key);
var self = (godot_dictionary)_underlyingDict.NativeValue;
if (NativeFuncs.godotsharp_dictionary_contains_key(ref self, variantKey).ToBool())
throw new ArgumentException("An element with the same key already exists.", nameof(key));
- using var variantValue = ConvertValueToVariantCallback(value);
+ using var variantValue = VariantUtils.CreateFrom(value);
NativeFuncs.godotsharp_dictionary_add(ref self, variantKey, variantValue);
}
@@ -579,9 +546,9 @@ namespace Godot.Collections
/// </summary>
/// <param name="key">The key to look for.</param>
/// <returns>Whether or not this dictionary contains the given key.</returns>
- public unsafe bool ContainsKey(TKey key)
+ public bool ContainsKey(TKey key)
{
- using var variantKey = ConvertKeyToVariantCallback(key);
+ using var variantKey = VariantUtils.CreateFrom(key);
var self = (godot_dictionary)_underlyingDict.NativeValue;
return NativeFuncs.godotsharp_dictionary_contains_key(ref self, variantKey).ToBool();
}
@@ -590,9 +557,9 @@ namespace Godot.Collections
/// Removes an element from this <see cref="Dictionary{TKey, TValue}"/> by key.
/// </summary>
/// <param name="key">The key of the element to remove.</param>
- public unsafe bool Remove(TKey key)
+ public bool Remove(TKey key)
{
- using var variantKey = ConvertKeyToVariantCallback(key);
+ using var variantKey = VariantUtils.CreateFrom(key);
var self = (godot_dictionary)_underlyingDict.NativeValue;
return NativeFuncs.godotsharp_dictionary_remove_key(ref self, variantKey).ToBool();
}
@@ -603,15 +570,15 @@ namespace Godot.Collections
/// <param name="key">The key of the element to get.</param>
/// <param name="value">The value at the given <paramref name="key"/>.</param>
/// <returns>If an object was found for the given <paramref name="key"/>.</returns>
- public unsafe bool TryGetValue(TKey key, [MaybeNullWhen(false)] out TValue value)
+ public bool TryGetValue(TKey key, [MaybeNullWhen(false)] out TValue value)
{
- using var variantKey = ConvertKeyToVariantCallback(key);
+ using var variantKey = VariantUtils.CreateFrom(key);
var self = (godot_dictionary)_underlyingDict.NativeValue;
bool found = NativeFuncs.godotsharp_dictionary_try_get_value(ref self,
variantKey, out godot_variant retValue).ToBool();
using (retValue)
- value = found ? ConvertValueToManagedCallback(retValue) : default;
+ value = found ? VariantUtils.ConvertTo<TValue>(retValue) : default;
return found;
}
@@ -635,9 +602,9 @@ namespace Godot.Collections
/// </summary>
public void Clear() => _underlyingDict.Clear();
- unsafe bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> item)
+ bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> item)
{
- using var variantKey = ConvertKeyToVariantCallback(item.Key);
+ using var variantKey = VariantUtils.CreateFrom(item.Key);
var self = (godot_dictionary)_underlyingDict.NativeValue;
bool found = NativeFuncs.godotsharp_dictionary_try_get_value(ref self,
variantKey, out godot_variant retValue).ToBool();
@@ -647,7 +614,7 @@ namespace Godot.Collections
if (!found)
return false;
- using var variantValue = ConvertValueToVariantCallback(item.Value);
+ using var variantValue = VariantUtils.CreateFrom(item.Value);
return NativeFuncs.godotsharp_variant_equals(variantValue, retValue).ToBool();
}
}
@@ -680,9 +647,9 @@ namespace Godot.Collections
}
}
- unsafe bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> item)
+ bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> item)
{
- using var variantKey = ConvertKeyToVariantCallback(item.Key);
+ using var variantKey = VariantUtils.CreateFrom(item.Key);
var self = (godot_dictionary)_underlyingDict.NativeValue;
bool found = NativeFuncs.godotsharp_dictionary_try_get_value(ref self,
variantKey, out godot_variant retValue).ToBool();
@@ -692,7 +659,7 @@ namespace Godot.Collections
if (!found)
return false;
- using var variantValue = ConvertValueToVariantCallback(item.Value);
+ using var variantValue = VariantUtils.CreateFrom(item.Value);
if (NativeFuncs.godotsharp_variant_equals(variantValue, retValue).ToBool())
{
return NativeFuncs.godotsharp_dictionary_remove_key(
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Mathf.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Mathf.cs
index f2667c6807..3f9e986f62 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Mathf.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Mathf.cs
@@ -282,7 +282,7 @@ 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.
+ /// 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>
@@ -303,6 +303,27 @@ namespace Godot
}
/// <summary>
+ /// Returns the derivative 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 BezierDerivative(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 t2 = t * t;
+
+ real_t d = (control1 - start) * 3 * omt2 + (control2 - control1) * 6 * omt * t + (end - control2) * 3 * t2;
+ return d;
+ }
+
+ /// <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/NativeInterop/Marshaling.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/Marshaling.cs
index 649661ee06..0d9a698af0 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/Marshaling.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/Marshaling.cs
@@ -1,5 +1,7 @@
using System;
using System.Runtime.InteropServices;
+using Godot.Collections;
+using Array = System.Array;
// ReSharper disable InconsistentNaming
@@ -97,7 +99,7 @@ namespace Godot.NativeInterop
if (type == typeof(Callable))
return Variant.Type.Callable;
- if (type == typeof(SignalInfo))
+ if (type == typeof(Signal))
return Variant.Type.Signal;
if (type.IsEnum)
@@ -148,6 +150,15 @@ namespace Godot.NativeInterop
{
if (typeof(Godot.Object).IsAssignableFrom(type))
return Variant.Type.Object;
+
+ // We use `IsAssignableFrom` with our helper interfaces to detect generic Godot collections
+ // because `GetGenericTypeDefinition` is not supported in NativeAOT reflection-free mode.
+
+ if (typeof(IGenericGodotDictionary).IsAssignableFrom(type))
+ return Variant.Type.Dictionary;
+
+ if (typeof(IGenericGodotArray).IsAssignableFrom(type))
+ return Variant.Type.Array;
}
else if (type == typeof(Variant))
{
@@ -183,508 +194,6 @@ namespace Godot.NativeInterop
return Variant.Type.Nil;
}
- /* TODO: Reflection and type checking each time is slow. This will be replaced with source generators. */
- public static godot_variant ConvertManagedObjectToVariant(object? p_obj)
- {
- if (p_obj == null)
- return new godot_variant();
-
- switch (p_obj)
- {
- case bool @bool:
- return VariantUtils.CreateFromBool(@bool);
- case char @char:
- return VariantUtils.CreateFromInt(@char);
- case sbyte @int8:
- return VariantUtils.CreateFromInt(@int8);
- case short @int16:
- return VariantUtils.CreateFromInt(@int16);
- case int @int32:
- return VariantUtils.CreateFromInt(@int32);
- case long @int64:
- return VariantUtils.CreateFromInt(@int64);
- case byte @uint8:
- return VariantUtils.CreateFromInt(@uint8);
- case ushort @uint16:
- return VariantUtils.CreateFromInt(@uint16);
- case uint @uint32:
- return VariantUtils.CreateFromInt(@uint32);
- case ulong @uint64:
- return VariantUtils.CreateFromInt(@uint64);
- case float @float:
- return VariantUtils.CreateFromFloat(@float);
- case double @double:
- return VariantUtils.CreateFromFloat(@double);
- case Vector2 @vector2:
- return VariantUtils.CreateFromVector2(@vector2);
- case Vector2i @vector2i:
- return VariantUtils.CreateFromVector2i(@vector2i);
- case Rect2 @rect2:
- return VariantUtils.CreateFromRect2(@rect2);
- case Rect2i @rect2i:
- return VariantUtils.CreateFromRect2i(@rect2i);
- case Transform2D @transform2D:
- return VariantUtils.CreateFromTransform2D(@transform2D);
- case Vector3 @vector3:
- return VariantUtils.CreateFromVector3(@vector3);
- case Vector3i @vector3i:
- return VariantUtils.CreateFromVector3i(@vector3i);
- case Vector4 @vector4:
- return VariantUtils.CreateFromVector4(@vector4);
- case Vector4i @vector4i:
- return VariantUtils.CreateFromVector4i(@vector4i);
- case Basis @basis:
- return VariantUtils.CreateFromBasis(@basis);
- case Quaternion @quaternion:
- return VariantUtils.CreateFromQuaternion(@quaternion);
- case Transform3D @transform3d:
- return VariantUtils.CreateFromTransform3D(@transform3d);
- case Projection @projection:
- return VariantUtils.CreateFromProjection(@projection);
- case AABB @aabb:
- return VariantUtils.CreateFromAABB(@aabb);
- case Color @color:
- return VariantUtils.CreateFromColor(@color);
- case Plane @plane:
- return VariantUtils.CreateFromPlane(@plane);
- case Callable @callable:
- return VariantUtils.CreateFromCallable(@callable);
- case SignalInfo @signalInfo:
- return VariantUtils.CreateFromSignalInfo(@signalInfo);
- case Enum @enum:
- return VariantUtils.CreateFromInt(Convert.ToInt64(@enum));
- case string @string:
- return VariantUtils.CreateFromString(@string);
- case byte[] byteArray:
- return VariantUtils.CreateFromPackedByteArray(byteArray);
- case int[] int32Array:
- return VariantUtils.CreateFromPackedInt32Array(int32Array);
- case long[] int64Array:
- return VariantUtils.CreateFromPackedInt64Array(int64Array);
- case float[] floatArray:
- return VariantUtils.CreateFromPackedFloat32Array(floatArray);
- case double[] doubleArray:
- return VariantUtils.CreateFromPackedFloat64Array(doubleArray);
- case string[] stringArray:
- return VariantUtils.CreateFromPackedStringArray(stringArray);
- case Vector2[] vector2Array:
- return VariantUtils.CreateFromPackedVector2Array(vector2Array);
- case Vector3[] vector3Array:
- return VariantUtils.CreateFromPackedVector3Array(vector3Array);
- case Color[] colorArray:
- return VariantUtils.CreateFromPackedColorArray(colorArray);
- case StringName[] stringNameArray:
- return VariantUtils.CreateFromSystemArrayOfStringName(stringNameArray);
- case NodePath[] nodePathArray:
- return VariantUtils.CreateFromSystemArrayOfNodePath(nodePathArray);
- case RID[] ridArray:
- return VariantUtils.CreateFromSystemArrayOfRID(ridArray);
- case Godot.Object[] godotObjectArray:
- return VariantUtils.CreateFromSystemArrayOfGodotObject(godotObjectArray);
- case Godot.Object godotObject:
- return VariantUtils.CreateFromGodotObject(godotObject);
- case StringName stringName:
- return VariantUtils.CreateFromStringName(stringName);
- case NodePath nodePath:
- return VariantUtils.CreateFromNodePath(nodePath);
- case RID rid:
- return VariantUtils.CreateFromRID(rid);
- case Collections.Dictionary godotDictionary:
- return VariantUtils.CreateFromDictionary(godotDictionary);
- case Collections.Array godotArray:
- return VariantUtils.CreateFromArray(godotArray);
- case Variant variant:
- return NativeFuncs.godotsharp_variant_new_copy((godot_variant)variant.NativeVar);
- }
-
- GD.PushError("Attempted to convert an unmarshallable managed type to Variant. Name: '" +
- p_obj.GetType().FullName + ".");
- return new godot_variant();
- }
-
- public static object? ConvertVariantToManagedObjectOfType(in godot_variant p_var, Type type)
- {
- // This function is only needed to set the value of properties. Fields have their own implementation, set_value_from_variant.
- switch (Type.GetTypeCode(type))
- {
- case TypeCode.Boolean:
- return VariantUtils.ConvertToBool(p_var);
- case TypeCode.Char:
- return VariantUtils.ConvertToChar(p_var);
- case TypeCode.SByte:
- return VariantUtils.ConvertToInt8(p_var);
- case TypeCode.Int16:
- return VariantUtils.ConvertToInt16(p_var);
- case TypeCode.Int32:
- return VariantUtils.ConvertToInt32(p_var);
- case TypeCode.Int64:
- return VariantUtils.ConvertToInt64(p_var);
- case TypeCode.Byte:
- return VariantUtils.ConvertToUInt8(p_var);
- case TypeCode.UInt16:
- return VariantUtils.ConvertToUInt16(p_var);
- case TypeCode.UInt32:
- return VariantUtils.ConvertToUInt32(p_var);
- case TypeCode.UInt64:
- return VariantUtils.ConvertToUInt64(p_var);
- case TypeCode.Single:
- return VariantUtils.ConvertToFloat32(p_var);
- case TypeCode.Double:
- return VariantUtils.ConvertToFloat64(p_var);
- case TypeCode.String:
- return VariantUtils.ConvertToStringObject(p_var);
- default:
- {
- if (type == typeof(Vector2))
- return VariantUtils.ConvertToVector2(p_var);
-
- if (type == typeof(Vector2i))
- return VariantUtils.ConvertToVector2i(p_var);
-
- if (type == typeof(Rect2))
- return VariantUtils.ConvertToRect2(p_var);
-
- if (type == typeof(Rect2i))
- return VariantUtils.ConvertToRect2i(p_var);
-
- if (type == typeof(Transform2D))
- return VariantUtils.ConvertToTransform2D(p_var);
-
- if (type == typeof(Vector3))
- return VariantUtils.ConvertToVector3(p_var);
-
- if (type == typeof(Vector3i))
- return VariantUtils.ConvertToVector3i(p_var);
-
- if (type == typeof(Vector4))
- return VariantUtils.ConvertToVector4(p_var);
-
- if (type == typeof(Vector4i))
- return VariantUtils.ConvertToVector4i(p_var);
-
- if (type == typeof(Basis))
- return VariantUtils.ConvertToBasis(p_var);
-
- if (type == typeof(Quaternion))
- return VariantUtils.ConvertToQuaternion(p_var);
-
- if (type == typeof(Transform3D))
- return VariantUtils.ConvertToTransform3D(p_var);
-
- if (type == typeof(Projection))
- return VariantUtils.ConvertToProjection(p_var);
-
- if (type == typeof(AABB))
- return VariantUtils.ConvertToAABB(p_var);
-
- if (type == typeof(Color))
- return VariantUtils.ConvertToColor(p_var);
-
- if (type == typeof(Plane))
- return VariantUtils.ConvertToPlane(p_var);
-
- if (type == typeof(Callable))
- return VariantUtils.ConvertToCallableManaged(p_var);
-
- if (type == typeof(SignalInfo))
- return VariantUtils.ConvertToSignalInfo(p_var);
-
- if (type.IsEnum)
- {
- var enumUnderlyingType = type.GetEnumUnderlyingType();
- switch (Type.GetTypeCode(enumUnderlyingType))
- {
- case TypeCode.SByte:
- return VariantUtils.ConvertToInt8(p_var);
- case TypeCode.Int16:
- return VariantUtils.ConvertToInt16(p_var);
- case TypeCode.Int32:
- return VariantUtils.ConvertToInt32(p_var);
- case TypeCode.Int64:
- return VariantUtils.ConvertToInt64(p_var);
- case TypeCode.Byte:
- return VariantUtils.ConvertToUInt8(p_var);
- case TypeCode.UInt16:
- return VariantUtils.ConvertToUInt16(p_var);
- case TypeCode.UInt32:
- return VariantUtils.ConvertToUInt32(p_var);
- case TypeCode.UInt64:
- return VariantUtils.ConvertToUInt64(p_var);
- default:
- {
- GD.PushError(
- "Attempted to convert Variant to enum value of unsupported underlying type. Name: " +
- type.FullName + " : " + enumUnderlyingType.FullName + ".");
- return null;
- }
- }
- }
-
- if (type.IsArray || type.IsSZArray)
- {
- return ConvertVariantToSystemArrayOfType(p_var, type);
- }
- else if (type.IsGenericType)
- {
- if (typeof(Godot.Object).IsAssignableFrom(type))
- {
- var godotObject = VariantUtils.ConvertToGodotObject(p_var);
-
- if (!type.IsInstanceOfType(godotObject))
- {
- GD.PushError("Invalid cast when marshaling Godot.Object type." +
- $" `{godotObject.GetType()}` is not assignable to `{type.FullName}`.");
- return null;
- }
-
- return godotObject;
- }
-
- return null;
- }
- else if (type == typeof(Variant))
- {
- return Variant.CreateCopyingBorrowed(p_var);
- }
-
- if (ConvertVariantToManagedObjectOfClass(p_var, type, out object? res))
- return res;
-
- break;
- }
- }
-
- GD.PushError("Attempted to convert Variant to unsupported type. Name: " +
- type.FullName + ".");
- return null;
- }
-
- private static object? ConvertVariantToSystemArrayOfType(in godot_variant p_var, Type type)
- {
- if (type == typeof(byte[]))
- return VariantUtils.ConvertAsPackedByteArrayToSystemArray(p_var);
-
- if (type == typeof(int[]))
- return VariantUtils.ConvertAsPackedInt32ArrayToSystemArray(p_var);
-
- if (type == typeof(long[]))
- return VariantUtils.ConvertAsPackedInt64ArrayToSystemArray(p_var);
-
- if (type == typeof(float[]))
- return VariantUtils.ConvertAsPackedFloat32ArrayToSystemArray(p_var);
-
- if (type == typeof(double[]))
- return VariantUtils.ConvertAsPackedFloat64ArrayToSystemArray(p_var);
-
- if (type == typeof(string[]))
- return VariantUtils.ConvertAsPackedStringArrayToSystemArray(p_var);
-
- if (type == typeof(Vector2[]))
- return VariantUtils.ConvertAsPackedVector2ArrayToSystemArray(p_var);
-
- if (type == typeof(Vector3[]))
- return VariantUtils.ConvertAsPackedVector3ArrayToSystemArray(p_var);
-
- if (type == typeof(Color[]))
- return VariantUtils.ConvertAsPackedColorArrayToSystemArray(p_var);
-
- if (type == typeof(StringName[]))
- return VariantUtils.ConvertToSystemArrayOfStringName(p_var);
-
- if (type == typeof(NodePath[]))
- return VariantUtils.ConvertToSystemArrayOfNodePath(p_var);
-
- if (type == typeof(RID[]))
- return VariantUtils.ConvertToSystemArrayOfRID(p_var);
-
- if (typeof(Godot.Object[]).IsAssignableFrom(type))
- return VariantUtils.ConvertToSystemArrayOfGodotObject(p_var, type);
-
- GD.PushError("Attempted to convert Variant to array of unsupported element type. Name: " +
- type.GetElementType()!.FullName + ".");
- return null;
- }
-
- private static bool ConvertVariantToManagedObjectOfClass(in godot_variant p_var, Type type,
- out object? res)
- {
- if (typeof(Godot.Object).IsAssignableFrom(type))
- {
- if (p_var.Type == Variant.Type.Nil)
- {
- res = null;
- return true;
- }
-
- if (p_var.Type != Variant.Type.Object)
- {
- GD.PushError("Invalid cast when marshaling Godot.Object type." +
- $" Variant type is `{p_var.Type}`; expected `{p_var.Object}`.");
- res = null;
- return true;
- }
-
- var godotObjectPtr = VariantUtils.ConvertToGodotObjectPtr(p_var);
-
- if (godotObjectPtr == IntPtr.Zero)
- {
- res = null;
- return true;
- }
-
- var godotObject = InteropUtils.UnmanagedGetManaged(godotObjectPtr);
-
- if (!type.IsInstanceOfType(godotObject))
- {
- GD.PushError("Invalid cast when marshaling Godot.Object type." +
- $" `{godotObject.GetType()}` is not assignable to `{type.FullName}`.");
- res = null;
- return false;
- }
-
- res = godotObject;
- return true;
- }
-
- if (typeof(StringName) == type)
- {
- res = VariantUtils.ConvertToStringNameObject(p_var);
- return true;
- }
-
- if (typeof(NodePath) == type)
- {
- res = VariantUtils.ConvertToNodePathObject(p_var);
- return true;
- }
-
- if (typeof(RID) == type)
- {
- res = VariantUtils.ConvertToRID(p_var);
- return true;
- }
-
- if (typeof(Collections.Dictionary) == type)
- {
- res = VariantUtils.ConvertToDictionaryObject(p_var);
- return true;
- }
-
- if (typeof(Collections.Array) == type)
- {
- res = VariantUtils.ConvertToArrayObject(p_var);
- return true;
- }
-
- res = null;
- return false;
- }
-
- public static unsafe object? ConvertVariantToManagedObject(in godot_variant p_var)
- {
- switch (p_var.Type)
- {
- case Variant.Type.Bool:
- return p_var.Bool.ToBool();
- case Variant.Type.Int:
- return p_var.Int;
- case Variant.Type.Float:
- {
-#if REAL_T_IS_DOUBLE
- return p_var.Float;
-#else
- return (float)p_var.Float;
-#endif
- }
- case Variant.Type.String:
- return ConvertStringToManaged(p_var.String);
- case Variant.Type.Vector2:
- return p_var.Vector2;
- case Variant.Type.Vector2i:
- return p_var.Vector2i;
- case Variant.Type.Rect2:
- return p_var.Rect2;
- case Variant.Type.Rect2i:
- return p_var.Rect2i;
- case Variant.Type.Vector3:
- return p_var.Vector3;
- case Variant.Type.Vector3i:
- return p_var.Vector3i;
- case Variant.Type.Transform2d:
- return *p_var.Transform2D;
- case Variant.Type.Vector4:
- return p_var.Vector4;
- case Variant.Type.Vector4i:
- return p_var.Vector4i;
- case Variant.Type.Plane:
- return p_var.Plane;
- case Variant.Type.Quaternion:
- return p_var.Quaternion;
- case Variant.Type.Aabb:
- return *p_var.AABB;
- case Variant.Type.Basis:
- return *p_var.Basis;
- case Variant.Type.Transform3d:
- return *p_var.Transform3D;
- case Variant.Type.Projection:
- return *p_var.Projection;
- case Variant.Type.Color:
- return p_var.Color;
- case Variant.Type.StringName:
- {
- // The Variant owns the value, so we need to make a copy
- return StringName.CreateTakingOwnershipOfDisposableValue(
- NativeFuncs.godotsharp_string_name_new_copy(p_var.StringName));
- }
- case Variant.Type.NodePath:
- {
- // The Variant owns the value, so we need to make a copy
- return NodePath.CreateTakingOwnershipOfDisposableValue(
- NativeFuncs.godotsharp_node_path_new_copy(p_var.NodePath));
- }
- case Variant.Type.Rid:
- return p_var.RID;
- case Variant.Type.Object:
- return InteropUtils.UnmanagedGetManaged(p_var.Object);
- case Variant.Type.Callable:
- return ConvertCallableToManaged(p_var.Callable);
- case Variant.Type.Signal:
- return ConvertSignalToManaged(p_var.Signal);
- case Variant.Type.Dictionary:
- {
- // The Variant owns the value, so we need to make a copy
- return Collections.Dictionary.CreateTakingOwnershipOfDisposableValue(
- NativeFuncs.godotsharp_dictionary_new_copy(p_var.Dictionary));
- }
- case Variant.Type.Array:
- {
- // The Variant owns the value, so we need to make a copy
- return Collections.Array.CreateTakingOwnershipOfDisposableValue(
- NativeFuncs.godotsharp_array_new_copy(p_var.Array));
- }
- case Variant.Type.PackedByteArray:
- return VariantUtils.ConvertAsPackedByteArrayToSystemArray(p_var);
- case Variant.Type.PackedInt32Array:
- return VariantUtils.ConvertAsPackedInt32ArrayToSystemArray(p_var);
- case Variant.Type.PackedInt64Array:
- return VariantUtils.ConvertAsPackedInt64ArrayToSystemArray(p_var);
- case Variant.Type.PackedFloat32Array:
- return VariantUtils.ConvertAsPackedFloat32ArrayToSystemArray(p_var);
- case Variant.Type.PackedFloat64Array:
- return VariantUtils.ConvertAsPackedFloat64ArrayToSystemArray(p_var);
- case Variant.Type.PackedStringArray:
- return VariantUtils.ConvertAsPackedStringArrayToSystemArray(p_var);
- case Variant.Type.PackedVector2Array:
- return VariantUtils.ConvertAsPackedVector2ArrayToSystemArray(p_var);
- case Variant.Type.PackedVector3Array:
- return VariantUtils.ConvertAsPackedVector3ArrayToSystemArray(p_var);
- case Variant.Type.PackedColorArray:
- return VariantUtils.ConvertAsPackedColorArrayToSystemArray(p_var);
- default:
- return null;
- }
- }
-
// String
public static unsafe godot_string ConvertStringToNative(string? p_mono_string)
@@ -779,9 +288,9 @@ namespace Godot.NativeInterop
return new Callable();
}
- // SignalInfo
+ // Signal
- public static godot_signal ConvertSignalToNative(in SignalInfo p_managed_signal)
+ public static godot_signal ConvertSignalToNative(in Signal p_managed_signal)
{
ulong ownerId = p_managed_signal.Owner.GetInstanceId();
godot_string_name name;
@@ -799,12 +308,12 @@ namespace Godot.NativeInterop
return new godot_signal(name, ownerId);
}
- public static SignalInfo ConvertSignalToManaged(in godot_signal p_signal)
+ public static Signal ConvertSignalToManaged(in godot_signal p_signal)
{
var owner = GD.InstanceFromId(p_signal.ObjectId);
var name = StringName.CreateTakingOwnershipOfDisposableValue(
NativeFuncs.godotsharp_string_name_new_copy(p_signal.Name));
- return new SignalInfo(owner, name);
+ return new Signal(owner, name);
}
// Array
@@ -824,22 +333,6 @@ namespace Godot.NativeInterop
return ret;
}
- // TODO: This needs reflection. Look for an alternative.
- internal static Godot.Object[] ConvertNativeGodotArrayToSystemArrayOfGodotObjectType(in godot_array p_array,
- Type type)
- {
- var array = Collections.Array.CreateTakingOwnershipOfDisposableValue(
- NativeFuncs.godotsharp_array_new_copy(p_array));
-
- int length = array.Count;
- var ret = (Godot.Object[])Activator.CreateInstance(type, length)!;
-
- for (int i = 0; i < length; i++)
- ret[i] = array[i].AsGodotObject();
-
- return ret;
- }
-
internal static StringName[] ConvertNativeGodotArrayToSystemArrayOfStringName(in godot_array p_array)
{
var array = Collections.Array.CreateTakingOwnershipOfDisposableValue(
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.cs
index b30b6a0752..57488bd586 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.cs
@@ -153,6 +153,8 @@ namespace Godot.NativeInterop
internal static partial void godotsharp_callable_call_deferred(in godot_callable p_callable,
godot_variant** p_args, int p_arg_count);
+ internal static partial Color godotsharp_color_from_ok_hsl(float p_h, float p_s, float p_l, float p_alpha);
+
// GDNative functions
// gdnative.h
@@ -414,21 +416,6 @@ namespace Godot.NativeInterop
// StringExtensions
- public static partial void godotsharp_string_md5_buffer(in godot_string p_self,
- out godot_packed_byte_array r_md5_buffer);
-
- public static partial void godotsharp_string_md5_text(in godot_string p_self, out godot_string r_md5_text);
-
- public static partial int godotsharp_string_rfind(in godot_string p_self, in godot_string p_what, int p_from);
-
- public static partial int godotsharp_string_rfindn(in godot_string p_self, in godot_string p_what, int p_from);
-
- public static partial void godotsharp_string_sha256_buffer(in godot_string p_self,
- out godot_packed_byte_array r_sha256_buffer);
-
- public static partial void godotsharp_string_sha256_text(in godot_string p_self,
- out godot_string r_sha256_text);
-
public static partial void godotsharp_string_simplify_path(in godot_string p_self,
out godot_string r_simplified_path);
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantConversionCallbacks.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantConversionCallbacks.cs
deleted file mode 100644
index 4b3db0c01a..0000000000
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantConversionCallbacks.cs
+++ /dev/null
@@ -1,1057 +0,0 @@
-using System;
-using System.Diagnostics.CodeAnalysis;
-using System.Runtime.CompilerServices;
-
-namespace Godot.NativeInterop;
-
-// TODO: Change VariantConversionCallbacks<T>. Store the callback in a static field for quick repeated access, instead of checking every time.
-internal static unsafe class VariantConversionCallbacks
-{
- internal static System.Collections.Generic.Dictionary<Type, (IntPtr ToVariant, IntPtr FromVariant)>
- GenericConversionCallbacks = new();
-
- [SuppressMessage("ReSharper", "RedundantNameQualifier")]
- internal static delegate*<in T, godot_variant> GetToVariantCallback<T>()
- {
- static godot_variant FromBool(in bool @bool) =>
- VariantUtils.CreateFromBool(@bool);
-
- static godot_variant FromChar(in char @char) =>
- VariantUtils.CreateFromInt(@char);
-
- static godot_variant FromInt8(in sbyte @int8) =>
- VariantUtils.CreateFromInt(@int8);
-
- static godot_variant FromInt16(in short @int16) =>
- VariantUtils.CreateFromInt(@int16);
-
- static godot_variant FromInt32(in int @int32) =>
- VariantUtils.CreateFromInt(@int32);
-
- static godot_variant FromInt64(in long @int64) =>
- VariantUtils.CreateFromInt(@int64);
-
- static godot_variant FromUInt8(in byte @uint8) =>
- VariantUtils.CreateFromInt(@uint8);
-
- static godot_variant FromUInt16(in ushort @uint16) =>
- VariantUtils.CreateFromInt(@uint16);
-
- static godot_variant FromUInt32(in uint @uint32) =>
- VariantUtils.CreateFromInt(@uint32);
-
- static godot_variant FromUInt64(in ulong @uint64) =>
- VariantUtils.CreateFromInt(@uint64);
-
- static godot_variant FromFloat(in float @float) =>
- VariantUtils.CreateFromFloat(@float);
-
- static godot_variant FromDouble(in double @double) =>
- VariantUtils.CreateFromFloat(@double);
-
- static godot_variant FromVector2(in Vector2 @vector2) =>
- VariantUtils.CreateFromVector2(@vector2);
-
- static godot_variant FromVector2I(in Vector2i vector2I) =>
- VariantUtils.CreateFromVector2i(vector2I);
-
- static godot_variant FromRect2(in Rect2 @rect2) =>
- VariantUtils.CreateFromRect2(@rect2);
-
- static godot_variant FromRect2I(in Rect2i rect2I) =>
- VariantUtils.CreateFromRect2i(rect2I);
-
- static godot_variant FromTransform2D(in Transform2D @transform2D) =>
- VariantUtils.CreateFromTransform2D(@transform2D);
-
- static godot_variant FromVector3(in Vector3 @vector3) =>
- VariantUtils.CreateFromVector3(@vector3);
-
- static godot_variant FromVector3I(in Vector3i vector3I) =>
- VariantUtils.CreateFromVector3i(vector3I);
-
- static godot_variant FromBasis(in Basis @basis) =>
- VariantUtils.CreateFromBasis(@basis);
-
- static godot_variant FromQuaternion(in Quaternion @quaternion) =>
- VariantUtils.CreateFromQuaternion(@quaternion);
-
- static godot_variant FromTransform3D(in Transform3D @transform3d) =>
- VariantUtils.CreateFromTransform3D(@transform3d);
-
- static godot_variant FromVector4(in Vector4 @vector4) =>
- VariantUtils.CreateFromVector4(@vector4);
-
- static godot_variant FromVector4I(in Vector4i vector4I) =>
- VariantUtils.CreateFromVector4i(vector4I);
-
- static godot_variant FromAabb(in AABB @aabb) =>
- VariantUtils.CreateFromAABB(@aabb);
-
- static godot_variant FromColor(in Color @color) =>
- VariantUtils.CreateFromColor(@color);
-
- static godot_variant FromPlane(in Plane @plane) =>
- VariantUtils.CreateFromPlane(@plane);
-
- static godot_variant FromCallable(in Callable @callable) =>
- VariantUtils.CreateFromCallable(@callable);
-
- static godot_variant FromSignalInfo(in SignalInfo @signalInfo) =>
- VariantUtils.CreateFromSignalInfo(@signalInfo);
-
- static godot_variant FromString(in string @string) =>
- VariantUtils.CreateFromString(@string);
-
- static godot_variant FromByteArray(in byte[] byteArray) =>
- VariantUtils.CreateFromPackedByteArray(byteArray);
-
- static godot_variant FromInt32Array(in int[] int32Array) =>
- VariantUtils.CreateFromPackedInt32Array(int32Array);
-
- static godot_variant FromInt64Array(in long[] int64Array) =>
- VariantUtils.CreateFromPackedInt64Array(int64Array);
-
- static godot_variant FromFloatArray(in float[] floatArray) =>
- VariantUtils.CreateFromPackedFloat32Array(floatArray);
-
- static godot_variant FromDoubleArray(in double[] doubleArray) =>
- VariantUtils.CreateFromPackedFloat64Array(doubleArray);
-
- static godot_variant FromStringArray(in string[] stringArray) =>
- VariantUtils.CreateFromPackedStringArray(stringArray);
-
- static godot_variant FromVector2Array(in Vector2[] vector2Array) =>
- VariantUtils.CreateFromPackedVector2Array(vector2Array);
-
- static godot_variant FromVector3Array(in Vector3[] vector3Array) =>
- VariantUtils.CreateFromPackedVector3Array(vector3Array);
-
- static godot_variant FromColorArray(in Color[] colorArray) =>
- VariantUtils.CreateFromPackedColorArray(colorArray);
-
- static godot_variant FromStringNameArray(in StringName[] stringNameArray) =>
- VariantUtils.CreateFromSystemArrayOfStringName(stringNameArray);
-
- static godot_variant FromNodePathArray(in NodePath[] nodePathArray) =>
- VariantUtils.CreateFromSystemArrayOfNodePath(nodePathArray);
-
- static godot_variant FromRidArray(in RID[] ridArray) =>
- VariantUtils.CreateFromSystemArrayOfRID(ridArray);
-
- static godot_variant FromGodotObject(in Godot.Object godotObject) =>
- VariantUtils.CreateFromGodotObject(godotObject);
-
- static godot_variant FromStringName(in StringName stringName) =>
- VariantUtils.CreateFromStringName(stringName);
-
- static godot_variant FromNodePath(in NodePath nodePath) =>
- VariantUtils.CreateFromNodePath(nodePath);
-
- static godot_variant FromRid(in RID rid) =>
- VariantUtils.CreateFromRID(rid);
-
- static godot_variant FromGodotDictionary(in Collections.Dictionary godotDictionary) =>
- VariantUtils.CreateFromDictionary(godotDictionary);
-
- static godot_variant FromGodotArray(in Collections.Array godotArray) =>
- VariantUtils.CreateFromArray(godotArray);
-
- static godot_variant FromVariant(in Variant variant) =>
- NativeFuncs.godotsharp_variant_new_copy((godot_variant)variant.NativeVar);
-
- var typeOfT = typeof(T);
-
- if (typeOfT == typeof(bool))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in bool, godot_variant>)
- &FromBool;
- }
-
- if (typeOfT == typeof(char))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in char, godot_variant>)
- &FromChar;
- }
-
- if (typeOfT == typeof(sbyte))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in sbyte, godot_variant>)
- &FromInt8;
- }
-
- if (typeOfT == typeof(short))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in short, godot_variant>)
- &FromInt16;
- }
-
- if (typeOfT == typeof(int))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in int, godot_variant>)
- &FromInt32;
- }
-
- if (typeOfT == typeof(long))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in long, godot_variant>)
- &FromInt64;
- }
-
- if (typeOfT == typeof(byte))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in byte, godot_variant>)
- &FromUInt8;
- }
-
- if (typeOfT == typeof(ushort))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in ushort, godot_variant>)
- &FromUInt16;
- }
-
- if (typeOfT == typeof(uint))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in uint, godot_variant>)
- &FromUInt32;
- }
-
- if (typeOfT == typeof(ulong))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in ulong, godot_variant>)
- &FromUInt64;
- }
-
- if (typeOfT == typeof(float))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in float, godot_variant>)
- &FromFloat;
- }
-
- if (typeOfT == typeof(double))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in double, godot_variant>)
- &FromDouble;
- }
-
- if (typeOfT == typeof(Vector2))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in Vector2, godot_variant>)
- &FromVector2;
- }
-
- if (typeOfT == typeof(Vector2i))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in Vector2i, godot_variant>)
- &FromVector2I;
- }
-
- if (typeOfT == typeof(Rect2))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in Rect2, godot_variant>)
- &FromRect2;
- }
-
- if (typeOfT == typeof(Rect2i))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in Rect2i, godot_variant>)
- &FromRect2I;
- }
-
- if (typeOfT == typeof(Transform2D))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in Transform2D, godot_variant>)
- &FromTransform2D;
- }
-
- if (typeOfT == typeof(Vector3))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in Vector3, godot_variant>)
- &FromVector3;
- }
-
- if (typeOfT == typeof(Vector3i))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in Vector3i, godot_variant>)
- &FromVector3I;
- }
-
- if (typeOfT == typeof(Basis))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in Basis, godot_variant>)
- &FromBasis;
- }
-
- if (typeOfT == typeof(Quaternion))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in Quaternion, godot_variant>)
- &FromQuaternion;
- }
-
- if (typeOfT == typeof(Transform3D))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in Transform3D, godot_variant>)
- &FromTransform3D;
- }
-
- if (typeOfT == typeof(Vector4))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in Vector4, godot_variant>)
- &FromVector4;
- }
-
- if (typeOfT == typeof(Vector4i))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in Vector4i, godot_variant>)
- &FromVector4I;
- }
-
- if (typeOfT == typeof(AABB))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in AABB, godot_variant>)
- &FromAabb;
- }
-
- if (typeOfT == typeof(Color))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in Color, godot_variant>)
- &FromColor;
- }
-
- if (typeOfT == typeof(Plane))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in Plane, godot_variant>)
- &FromPlane;
- }
-
- if (typeOfT == typeof(Callable))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in Callable, godot_variant>)
- &FromCallable;
- }
-
- if (typeOfT == typeof(SignalInfo))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in SignalInfo, godot_variant>)
- &FromSignalInfo;
- }
-
- if (typeOfT.IsEnum)
- {
- var enumUnderlyingType = typeOfT.GetEnumUnderlyingType();
-
- switch (Type.GetTypeCode(enumUnderlyingType))
- {
- case TypeCode.SByte:
- {
- return (delegate*<in T, godot_variant>)(delegate*<in sbyte, godot_variant>)
- &FromInt8;
- }
- case TypeCode.Int16:
- {
- return (delegate*<in T, godot_variant>)(delegate*<in short, godot_variant>)
- &FromInt16;
- }
- case TypeCode.Int32:
- {
- return (delegate*<in T, godot_variant>)(delegate*<in int, godot_variant>)
- &FromInt32;
- }
- case TypeCode.Int64:
- {
- return (delegate*<in T, godot_variant>)(delegate*<in long, godot_variant>)
- &FromInt64;
- }
- case TypeCode.Byte:
- {
- return (delegate*<in T, godot_variant>)(delegate*<in byte, godot_variant>)
- &FromUInt8;
- }
- case TypeCode.UInt16:
- {
- return (delegate*<in T, godot_variant>)(delegate*<in ushort, godot_variant>)
- &FromUInt16;
- }
- case TypeCode.UInt32:
- {
- return (delegate*<in T, godot_variant>)(delegate*<in uint, godot_variant>)
- &FromUInt32;
- }
- case TypeCode.UInt64:
- {
- return (delegate*<in T, godot_variant>)(delegate*<in ulong, godot_variant>)
- &FromUInt64;
- }
- default:
- return null;
- }
- }
-
- if (typeOfT == typeof(string))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in string, godot_variant>)
- &FromString;
- }
-
- if (typeOfT == typeof(byte[]))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in byte[], godot_variant>)
- &FromByteArray;
- }
-
- if (typeOfT == typeof(int[]))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in int[], godot_variant>)
- &FromInt32Array;
- }
-
- if (typeOfT == typeof(long[]))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in long[], godot_variant>)
- &FromInt64Array;
- }
-
- if (typeOfT == typeof(float[]))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in float[], godot_variant>)
- &FromFloatArray;
- }
-
- if (typeOfT == typeof(double[]))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in double[], godot_variant>)
- &FromDoubleArray;
- }
-
- if (typeOfT == typeof(string[]))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in string[], godot_variant>)
- &FromStringArray;
- }
-
- if (typeOfT == typeof(Vector2[]))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in Vector2[], godot_variant>)
- &FromVector2Array;
- }
-
- if (typeOfT == typeof(Vector3[]))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in Vector3[], godot_variant>)
- &FromVector3Array;
- }
-
- if (typeOfT == typeof(Color[]))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in Color[], godot_variant>)
- &FromColorArray;
- }
-
- if (typeOfT == typeof(StringName[]))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in StringName[], godot_variant>)
- &FromStringNameArray;
- }
-
- if (typeOfT == typeof(NodePath[]))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in NodePath[], godot_variant>)
- &FromNodePathArray;
- }
-
- if (typeOfT == typeof(RID[]))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in RID[], godot_variant>)
- &FromRidArray;
- }
-
- if (typeof(Godot.Object).IsAssignableFrom(typeOfT))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in Godot.Object, godot_variant>)
- &FromGodotObject;
- }
-
- if (typeOfT == typeof(StringName))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in StringName, godot_variant>)
- &FromStringName;
- }
-
- if (typeOfT == typeof(NodePath))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in NodePath, godot_variant>)
- &FromNodePath;
- }
-
- if (typeOfT == typeof(RID))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in RID, godot_variant>)
- &FromRid;
- }
-
- if (typeOfT == typeof(Godot.Collections.Dictionary))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in Godot.Collections.Dictionary, godot_variant>)
- &FromGodotDictionary;
- }
-
- if (typeOfT == typeof(Godot.Collections.Array))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in Godot.Collections.Array, godot_variant>)
- &FromGodotArray;
- }
-
- if (typeOfT == typeof(Variant))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in Variant, godot_variant>)
- &FromVariant;
- }
-
- // TODO:
- // IsGenericType and GetGenericTypeDefinition don't work in NativeAOT's reflection-free mode.
- // We could make the Godot collections implement an interface and use IsAssignableFrom instead.
- // Or we could just skip the check and always look for a conversion callback for the type.
- if (typeOfT.IsGenericType)
- {
- var genericTypeDef = typeOfT.GetGenericTypeDefinition();
-
- if (genericTypeDef == typeof(Godot.Collections.Dictionary<,>) ||
- genericTypeDef == typeof(Godot.Collections.Array<>))
- {
- RuntimeHelpers.RunClassConstructor(typeOfT.TypeHandle);
-
- if (GenericConversionCallbacks.TryGetValue(typeOfT, out var genericConversion))
- {
- return (delegate*<in T, godot_variant>)genericConversion.ToVariant;
- }
- }
- }
-
- return null;
- }
-
- [SuppressMessage("ReSharper", "RedundantNameQualifier")]
- internal static delegate*<in godot_variant, T> GetToManagedCallback<T>()
- {
- static bool ToBool(in godot_variant variant) =>
- VariantUtils.ConvertToBool(variant);
-
- static char ToChar(in godot_variant variant) =>
- VariantUtils.ConvertToChar(variant);
-
- static sbyte ToInt8(in godot_variant variant) =>
- VariantUtils.ConvertToInt8(variant);
-
- static short ToInt16(in godot_variant variant) =>
- VariantUtils.ConvertToInt16(variant);
-
- static int ToInt32(in godot_variant variant) =>
- VariantUtils.ConvertToInt32(variant);
-
- static long ToInt64(in godot_variant variant) =>
- VariantUtils.ConvertToInt64(variant);
-
- static byte ToUInt8(in godot_variant variant) =>
- VariantUtils.ConvertToUInt8(variant);
-
- static ushort ToUInt16(in godot_variant variant) =>
- VariantUtils.ConvertToUInt16(variant);
-
- static uint ToUInt32(in godot_variant variant) =>
- VariantUtils.ConvertToUInt32(variant);
-
- static ulong ToUInt64(in godot_variant variant) =>
- VariantUtils.ConvertToUInt64(variant);
-
- static float ToFloat(in godot_variant variant) =>
- VariantUtils.ConvertToFloat32(variant);
-
- static double ToDouble(in godot_variant variant) =>
- VariantUtils.ConvertToFloat64(variant);
-
- static Vector2 ToVector2(in godot_variant variant) =>
- VariantUtils.ConvertToVector2(variant);
-
- static Vector2i ToVector2I(in godot_variant variant) =>
- VariantUtils.ConvertToVector2i(variant);
-
- static Rect2 ToRect2(in godot_variant variant) =>
- VariantUtils.ConvertToRect2(variant);
-
- static Rect2i ToRect2I(in godot_variant variant) =>
- VariantUtils.ConvertToRect2i(variant);
-
- static Transform2D ToTransform2D(in godot_variant variant) =>
- VariantUtils.ConvertToTransform2D(variant);
-
- static Vector3 ToVector3(in godot_variant variant) =>
- VariantUtils.ConvertToVector3(variant);
-
- static Vector3i ToVector3I(in godot_variant variant) =>
- VariantUtils.ConvertToVector3i(variant);
-
- static Basis ToBasis(in godot_variant variant) =>
- VariantUtils.ConvertToBasis(variant);
-
- static Quaternion ToQuaternion(in godot_variant variant) =>
- VariantUtils.ConvertToQuaternion(variant);
-
- static Transform3D ToTransform3D(in godot_variant variant) =>
- VariantUtils.ConvertToTransform3D(variant);
-
- static Vector4 ToVector4(in godot_variant variant) =>
- VariantUtils.ConvertToVector4(variant);
-
- static Vector4i ToVector4I(in godot_variant variant) =>
- VariantUtils.ConvertToVector4i(variant);
-
- static AABB ToAabb(in godot_variant variant) =>
- VariantUtils.ConvertToAABB(variant);
-
- static Color ToColor(in godot_variant variant) =>
- VariantUtils.ConvertToColor(variant);
-
- static Plane ToPlane(in godot_variant variant) =>
- VariantUtils.ConvertToPlane(variant);
-
- static Callable ToCallable(in godot_variant variant) =>
- VariantUtils.ConvertToCallableManaged(variant);
-
- static SignalInfo ToSignalInfo(in godot_variant variant) =>
- VariantUtils.ConvertToSignalInfo(variant);
-
- static string ToString(in godot_variant variant) =>
- VariantUtils.ConvertToStringObject(variant);
-
- static byte[] ToByteArray(in godot_variant variant) =>
- VariantUtils.ConvertAsPackedByteArrayToSystemArray(variant);
-
- static int[] ToInt32Array(in godot_variant variant) =>
- VariantUtils.ConvertAsPackedInt32ArrayToSystemArray(variant);
-
- static long[] ToInt64Array(in godot_variant variant) =>
- VariantUtils.ConvertAsPackedInt64ArrayToSystemArray(variant);
-
- static float[] ToFloatArray(in godot_variant variant) =>
- VariantUtils.ConvertAsPackedFloat32ArrayToSystemArray(variant);
-
- static double[] ToDoubleArray(in godot_variant variant) =>
- VariantUtils.ConvertAsPackedFloat64ArrayToSystemArray(variant);
-
- static string[] ToStringArray(in godot_variant variant) =>
- VariantUtils.ConvertAsPackedStringArrayToSystemArray(variant);
-
- static Vector2[] ToVector2Array(in godot_variant variant) =>
- VariantUtils.ConvertAsPackedVector2ArrayToSystemArray(variant);
-
- static Vector3[] ToVector3Array(in godot_variant variant) =>
- VariantUtils.ConvertAsPackedVector3ArrayToSystemArray(variant);
-
- static Color[] ToColorArray(in godot_variant variant) =>
- VariantUtils.ConvertAsPackedColorArrayToSystemArray(variant);
-
- static StringName[] ToStringNameArray(in godot_variant variant) =>
- VariantUtils.ConvertToSystemArrayOfStringName(variant);
-
- static NodePath[] ToNodePathArray(in godot_variant variant) =>
- VariantUtils.ConvertToSystemArrayOfNodePath(variant);
-
- static RID[] ToRidArray(in godot_variant variant) =>
- VariantUtils.ConvertToSystemArrayOfRID(variant);
-
- static Godot.Object ToGodotObject(in godot_variant variant) =>
- VariantUtils.ConvertToGodotObject(variant);
-
- static StringName ToStringName(in godot_variant variant) =>
- VariantUtils.ConvertToStringNameObject(variant);
-
- static NodePath ToNodePath(in godot_variant variant) =>
- VariantUtils.ConvertToNodePathObject(variant);
-
- static RID ToRid(in godot_variant variant) =>
- VariantUtils.ConvertToRID(variant);
-
- static Collections.Dictionary ToGodotDictionary(in godot_variant variant) =>
- VariantUtils.ConvertToDictionaryObject(variant);
-
- static Collections.Array ToGodotArray(in godot_variant variant) =>
- VariantUtils.ConvertToArrayObject(variant);
-
- static Variant ToVariant(in godot_variant variant) =>
- Variant.CreateCopyingBorrowed(variant);
-
- var typeOfT = typeof(T);
-
- // ReSharper disable RedundantCast
- // Rider is being stupid here. These casts are definitely needed. We get build errors without them.
-
- if (typeOfT == typeof(bool))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, bool>)
- &ToBool;
- }
-
- if (typeOfT == typeof(char))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, char>)
- &ToChar;
- }
-
- if (typeOfT == typeof(sbyte))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, sbyte>)
- &ToInt8;
- }
-
- if (typeOfT == typeof(short))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, short>)
- &ToInt16;
- }
-
- if (typeOfT == typeof(int))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, int>)
- &ToInt32;
- }
-
- if (typeOfT == typeof(long))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, long>)
- &ToInt64;
- }
-
- if (typeOfT == typeof(byte))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, byte>)
- &ToUInt8;
- }
-
- if (typeOfT == typeof(ushort))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, ushort>)
- &ToUInt16;
- }
-
- if (typeOfT == typeof(uint))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, uint>)
- &ToUInt32;
- }
-
- if (typeOfT == typeof(ulong))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, ulong>)
- &ToUInt64;
- }
-
- if (typeOfT == typeof(float))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, float>)
- &ToFloat;
- }
-
- if (typeOfT == typeof(double))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, double>)
- &ToDouble;
- }
-
- if (typeOfT == typeof(Vector2))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, Vector2>)
- &ToVector2;
- }
-
- if (typeOfT == typeof(Vector2i))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, Vector2i>)
- &ToVector2I;
- }
-
- if (typeOfT == typeof(Rect2))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, Rect2>)
- &ToRect2;
- }
-
- if (typeOfT == typeof(Rect2i))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, Rect2i>)
- &ToRect2I;
- }
-
- if (typeOfT == typeof(Transform2D))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, Transform2D>)
- &ToTransform2D;
- }
-
- if (typeOfT == typeof(Vector3))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, Vector3>)
- &ToVector3;
- }
-
- if (typeOfT == typeof(Vector3i))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, Vector3i>)
- &ToVector3I;
- }
-
- if (typeOfT == typeof(Basis))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, Basis>)
- &ToBasis;
- }
-
- if (typeOfT == typeof(Quaternion))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, Quaternion>)
- &ToQuaternion;
- }
-
- if (typeOfT == typeof(Transform3D))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, Transform3D>)
- &ToTransform3D;
- }
-
- if (typeOfT == typeof(Vector4))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, Vector4>)
- &ToVector4;
- }
-
- if (typeOfT == typeof(Vector4i))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, Vector4i>)
- &ToVector4I;
- }
-
- if (typeOfT == typeof(AABB))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, AABB>)
- &ToAabb;
- }
-
- if (typeOfT == typeof(Color))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, Color>)
- &ToColor;
- }
-
- if (typeOfT == typeof(Plane))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, Plane>)
- &ToPlane;
- }
-
- if (typeOfT == typeof(Callable))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, Callable>)
- &ToCallable;
- }
-
- if (typeOfT == typeof(SignalInfo))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, SignalInfo>)
- &ToSignalInfo;
- }
-
- if (typeOfT.IsEnum)
- {
- var enumUnderlyingType = typeOfT.GetEnumUnderlyingType();
-
- switch (Type.GetTypeCode(enumUnderlyingType))
- {
- case TypeCode.SByte:
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, sbyte>)
- &ToInt8;
- }
- case TypeCode.Int16:
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, short>)
- &ToInt16;
- }
- case TypeCode.Int32:
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, int>)
- &ToInt32;
- }
- case TypeCode.Int64:
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, long>)
- &ToInt64;
- }
- case TypeCode.Byte:
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, byte>)
- &ToUInt8;
- }
- case TypeCode.UInt16:
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, ushort>)
- &ToUInt16;
- }
- case TypeCode.UInt32:
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, uint>)
- &ToUInt32;
- }
- case TypeCode.UInt64:
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, ulong>)
- &ToUInt64;
- }
- default:
- return null;
- }
- }
-
- if (typeOfT == typeof(string))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, string>)
- &ToString;
- }
-
- if (typeOfT == typeof(byte[]))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, byte[]>)
- &ToByteArray;
- }
-
- if (typeOfT == typeof(int[]))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, int[]>)
- &ToInt32Array;
- }
-
- if (typeOfT == typeof(long[]))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, long[]>)
- &ToInt64Array;
- }
-
- if (typeOfT == typeof(float[]))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, float[]>)
- &ToFloatArray;
- }
-
- if (typeOfT == typeof(double[]))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, double[]>)
- &ToDoubleArray;
- }
-
- if (typeOfT == typeof(string[]))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, string[]>)
- &ToStringArray;
- }
-
- if (typeOfT == typeof(Vector2[]))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, Vector2[]>)
- &ToVector2Array;
- }
-
- if (typeOfT == typeof(Vector3[]))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, Vector3[]>)
- &ToVector3Array;
- }
-
- if (typeOfT == typeof(Color[]))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, Color[]>)
- &ToColorArray;
- }
-
- if (typeOfT == typeof(StringName[]))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, StringName[]>)
- &ToStringNameArray;
- }
-
- if (typeOfT == typeof(NodePath[]))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, NodePath[]>)
- &ToNodePathArray;
- }
-
- if (typeOfT == typeof(RID[]))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, RID[]>)
- &ToRidArray;
- }
-
- if (typeof(Godot.Object).IsAssignableFrom(typeOfT))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, Godot.Object>)
- &ToGodotObject;
- }
-
- if (typeOfT == typeof(StringName))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, StringName>)
- &ToStringName;
- }
-
- if (typeOfT == typeof(NodePath))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, NodePath>)
- &ToNodePath;
- }
-
- if (typeOfT == typeof(RID))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, RID>)
- &ToRid;
- }
-
- if (typeOfT == typeof(Godot.Collections.Dictionary))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, Godot.Collections.Dictionary>)
- &ToGodotDictionary;
- }
-
- if (typeOfT == typeof(Godot.Collections.Array))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, Godot.Collections.Array>)
- &ToGodotArray;
- }
-
- if (typeOfT == typeof(Variant))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, Variant>)
- &ToVariant;
- }
-
- // TODO:
- // IsGenericType and GetGenericTypeDefinition don't work in NativeAOT's reflection-free mode.
- // We could make the Godot collections implement an interface and use IsAssignableFrom instead.
- // Or we could just skip the check and always look for a conversion callback for the type.
- if (typeOfT.IsGenericType)
- {
- var genericTypeDef = typeOfT.GetGenericTypeDefinition();
-
- if (genericTypeDef == typeof(Godot.Collections.Dictionary<,>) ||
- genericTypeDef == typeof(Godot.Collections.Array<>))
- {
- RuntimeHelpers.RunClassConstructor(typeOfT.TypeHandle);
-
- if (GenericConversionCallbacks.TryGetValue(typeOfT, out var genericConversion))
- {
- return (delegate*<in godot_variant, T>)genericConversion.FromVariant;
- }
- }
- }
-
- // ReSharper restore RedundantCast
-
- return null;
- }
-}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantSpanHelpers.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantSpanHelpers.cs
deleted file mode 100644
index 46f31bbf4e..0000000000
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantSpanHelpers.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-using System;
-
-namespace Godot.NativeInterop
-{
- internal readonly ref struct VariantSpanDisposer
- {
- private readonly Span<godot_variant.movable> _variantSpan;
-
- // IMPORTANT: The span element must be default initialized.
- // Make sure call Clear() on the span if it was created with stackalloc.
- public VariantSpanDisposer(Span<godot_variant.movable> variantSpan)
- {
- _variantSpan = variantSpan;
- }
-
- public void Dispose()
- {
- for (int i = 0; i < _variantSpan.Length; i++)
- _variantSpan[i].DangerousSelfRef.Dispose();
- }
- }
-
- internal static class VariantSpanExtensions
- {
- // Used to make sure we always initialize the span values to the default,
- // as we need that in order to safely dispose all elements after.
- public static Span<godot_variant.movable> Cleared(this Span<godot_variant.movable> span)
- {
- span.Clear();
- return span;
- }
- }
-}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantUtils.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantUtils.cs
index 57f9ec7d95..9c9258dd9e 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantUtils.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantUtils.cs
@@ -8,7 +8,7 @@ using Godot.Collections;
namespace Godot.NativeInterop
{
- public static class VariantUtils
+ public static partial class VariantUtils
{
public static godot_variant CreateFromRID(RID from)
=> new() { Type = Variant.Type.Rid, RID = from };
@@ -102,7 +102,7 @@ namespace Godot.NativeInterop
=> new() { Type = Variant.Type.Signal, Signal = from };
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static godot_variant CreateFromSignalInfo(SignalInfo from)
+ public static godot_variant CreateFromSignal(Signal from)
=> CreateFromSignalTakingOwnershipOfDisposableValue(
Marshaling.ConvertSignalToNative(from));
@@ -170,39 +170,66 @@ namespace Godot.NativeInterop
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static godot_variant CreateFromPackedByteArray(Span<byte> from)
- => CreateFromPackedByteArray(Marshaling.ConvertSystemArrayToNativePackedByteArray(from));
+ {
+ using var nativePackedArray = Marshaling.ConvertSystemArrayToNativePackedByteArray(from);
+ return CreateFromPackedByteArray(nativePackedArray);
+ }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static godot_variant CreateFromPackedInt32Array(Span<int> from)
- => CreateFromPackedInt32Array(Marshaling.ConvertSystemArrayToNativePackedInt32Array(from));
+ {
+ using var nativePackedArray = Marshaling.ConvertSystemArrayToNativePackedInt32Array(from);
+ return CreateFromPackedInt32Array(nativePackedArray);
+ }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static godot_variant CreateFromPackedInt64Array(Span<long> from)
- => CreateFromPackedInt64Array(Marshaling.ConvertSystemArrayToNativePackedInt64Array(from));
+ {
+ using var nativePackedArray = Marshaling.ConvertSystemArrayToNativePackedInt64Array(from);
+ return CreateFromPackedInt64Array(nativePackedArray);
+ }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static godot_variant CreateFromPackedFloat32Array(Span<float> from)
- => CreateFromPackedFloat32Array(Marshaling.ConvertSystemArrayToNativePackedFloat32Array(from));
+ {
+ using var nativePackedArray = Marshaling.ConvertSystemArrayToNativePackedFloat32Array(from);
+ return CreateFromPackedFloat32Array(nativePackedArray);
+ }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static godot_variant CreateFromPackedFloat64Array(Span<double> from)
- => CreateFromPackedFloat64Array(Marshaling.ConvertSystemArrayToNativePackedFloat64Array(from));
+ {
+ using var nativePackedArray = Marshaling.ConvertSystemArrayToNativePackedFloat64Array(from);
+ return CreateFromPackedFloat64Array(nativePackedArray);
+ }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static godot_variant CreateFromPackedStringArray(Span<string> from)
- => CreateFromPackedStringArray(Marshaling.ConvertSystemArrayToNativePackedStringArray(from));
+ {
+ using var nativePackedArray = Marshaling.ConvertSystemArrayToNativePackedStringArray(from);
+ return CreateFromPackedStringArray(nativePackedArray);
+ }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static godot_variant CreateFromPackedVector2Array(Span<Vector2> from)
- => CreateFromPackedVector2Array(Marshaling.ConvertSystemArrayToNativePackedVector2Array(from));
+ {
+ using var nativePackedArray = Marshaling.ConvertSystemArrayToNativePackedVector2Array(from);
+ return CreateFromPackedVector2Array(nativePackedArray);
+ }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static godot_variant CreateFromPackedVector3Array(Span<Vector3> from)
- => CreateFromPackedVector3Array(Marshaling.ConvertSystemArrayToNativePackedVector3Array(from));
+ {
+ using var nativePackedArray = Marshaling.ConvertSystemArrayToNativePackedVector3Array(from);
+ return CreateFromPackedVector3Array(nativePackedArray);
+ }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static godot_variant CreateFromPackedColorArray(Span<Color> from)
- => CreateFromPackedColorArray(Marshaling.ConvertSystemArrayToNativePackedColorArray(from));
+ {
+ using var nativePackedArray = Marshaling.ConvertSystemArrayToNativePackedColorArray(from);
+ return CreateFromPackedColorArray(nativePackedArray);
+ }
public static godot_variant CreateFromSystemArrayOfStringName(Span<StringName> from)
=> CreateFromArray(new Collections.Array(from));
@@ -436,7 +463,7 @@ namespace Godot.NativeInterop
public static Godot.Object ConvertToGodotObject(in godot_variant p_var)
=> InteropUtils.UnmanagedGetManaged(ConvertToGodotObjectPtr(p_var));
- public static string ConvertToStringObject(in godot_variant p_var)
+ public static string ConvertToString(in godot_variant p_var)
{
switch (p_var.Type)
{
@@ -455,65 +482,65 @@ namespace Godot.NativeInterop
}
}
- public static godot_string_name ConvertToStringName(in godot_variant p_var)
+ public static godot_string_name ConvertToNativeStringName(in godot_variant p_var)
=> p_var.Type == Variant.Type.StringName ?
NativeFuncs.godotsharp_string_name_new_copy(p_var.StringName) :
NativeFuncs.godotsharp_variant_as_string_name(p_var);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static StringName ConvertToStringNameObject(in godot_variant p_var)
- => StringName.CreateTakingOwnershipOfDisposableValue(ConvertToStringName(p_var));
+ public static StringName ConvertToStringName(in godot_variant p_var)
+ => StringName.CreateTakingOwnershipOfDisposableValue(ConvertToNativeStringName(p_var));
- public static godot_node_path ConvertToNodePath(in godot_variant p_var)
+ public static godot_node_path ConvertToNativeNodePath(in godot_variant p_var)
=> p_var.Type == Variant.Type.NodePath ?
NativeFuncs.godotsharp_node_path_new_copy(p_var.NodePath) :
NativeFuncs.godotsharp_variant_as_node_path(p_var);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static NodePath ConvertToNodePathObject(in godot_variant p_var)
- => NodePath.CreateTakingOwnershipOfDisposableValue(ConvertToNodePath(p_var));
+ public static NodePath ConvertToNodePath(in godot_variant p_var)
+ => NodePath.CreateTakingOwnershipOfDisposableValue(ConvertToNativeNodePath(p_var));
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static godot_callable ConvertToCallable(in godot_variant p_var)
+ public static godot_callable ConvertToNativeCallable(in godot_variant p_var)
=> NativeFuncs.godotsharp_variant_as_callable(p_var);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Callable ConvertToCallableManaged(in godot_variant p_var)
- => Marshaling.ConvertCallableToManaged(ConvertToCallable(p_var));
+ public static Callable ConvertToCallable(in godot_variant p_var)
+ => Marshaling.ConvertCallableToManaged(ConvertToNativeCallable(p_var));
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static godot_signal ConvertToSignal(in godot_variant p_var)
+ public static godot_signal ConvertToNativeSignal(in godot_variant p_var)
=> NativeFuncs.godotsharp_variant_as_signal(p_var);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static SignalInfo ConvertToSignalInfo(in godot_variant p_var)
- => Marshaling.ConvertSignalToManaged(ConvertToSignal(p_var));
+ public static Signal ConvertToSignal(in godot_variant p_var)
+ => Marshaling.ConvertSignalToManaged(ConvertToNativeSignal(p_var));
- public static godot_array ConvertToArray(in godot_variant p_var)
+ public static godot_array ConvertToNativeArray(in godot_variant p_var)
=> p_var.Type == Variant.Type.Array ?
NativeFuncs.godotsharp_array_new_copy(p_var.Array) :
NativeFuncs.godotsharp_variant_as_array(p_var);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Collections.Array ConvertToArrayObject(in godot_variant p_var)
- => Collections.Array.CreateTakingOwnershipOfDisposableValue(ConvertToArray(p_var));
+ public static Collections.Array ConvertToArray(in godot_variant p_var)
+ => Collections.Array.CreateTakingOwnershipOfDisposableValue(ConvertToNativeArray(p_var));
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Array<T> ConvertToArrayObject<T>(in godot_variant p_var)
- => Array<T>.CreateTakingOwnershipOfDisposableValue(ConvertToArray(p_var));
+ public static Array<T> ConvertToArray<T>(in godot_variant p_var)
+ => Array<T>.CreateTakingOwnershipOfDisposableValue(ConvertToNativeArray(p_var));
- public static godot_dictionary ConvertToDictionary(in godot_variant p_var)
+ public static godot_dictionary ConvertToNativeDictionary(in godot_variant p_var)
=> p_var.Type == Variant.Type.Dictionary ?
NativeFuncs.godotsharp_dictionary_new_copy(p_var.Dictionary) :
NativeFuncs.godotsharp_variant_as_dictionary(p_var);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Dictionary ConvertToDictionaryObject(in godot_variant p_var)
- => Dictionary.CreateTakingOwnershipOfDisposableValue(ConvertToDictionary(p_var));
+ public static Dictionary ConvertToDictionary(in godot_variant p_var)
+ => Dictionary.CreateTakingOwnershipOfDisposableValue(ConvertToNativeDictionary(p_var));
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Dictionary<TKey, TValue> ConvertToDictionaryObject<TKey, TValue>(in godot_variant p_var)
- => Dictionary<TKey, TValue>.CreateTakingOwnershipOfDisposableValue(ConvertToDictionary(p_var));
+ public static Dictionary<TKey, TValue> ConvertToDictionary<TKey, TValue>(in godot_variant p_var)
+ => Dictionary<TKey, TValue>.CreateTakingOwnershipOfDisposableValue(ConvertToNativeDictionary(p_var));
public static byte[] ConvertAsPackedByteArrayToSystemArray(in godot_variant p_var)
{
@@ -594,12 +621,5 @@ namespace Godot.NativeInterop
using var godotArray = NativeFuncs.godotsharp_variant_as_array(p_var);
return Marshaling.ConvertNativeGodotArrayToSystemArrayOfGodotObjectType<T>(godotArray);
}
-
- // ReSharper disable once RedundantNameQualifier
- public static Godot.Object[] ConvertToSystemArrayOfGodotObject(in godot_variant p_var, Type type)
- {
- using var godotArray = NativeFuncs.godotsharp_variant_as_array(p_var);
- return Marshaling.ConvertNativeGodotArrayToSystemArrayOfGodotObjectType(godotArray, type);
- }
}
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantUtils.generic.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantUtils.generic.cs
new file mode 100644
index 0000000000..3d64533269
--- /dev/null
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantUtils.generic.cs
@@ -0,0 +1,414 @@
+using System;
+using System.Diagnostics.CodeAnalysis;
+using System.Runtime.CompilerServices;
+
+namespace Godot.NativeInterop;
+
+#nullable enable
+
+public partial class VariantUtils
+{
+ private static Exception UnsupportedType<T>() => new InvalidOperationException(
+ $"The type is not supported for conversion to/from Variant: '{typeof(T).FullName}'");
+
+ internal static class GenericConversion<T>
+ {
+ public static unsafe godot_variant ToVariant(in T from) =>
+ ToVariantCb != null ? ToVariantCb(from) : throw UnsupportedType<T>();
+
+ public static unsafe T FromVariant(in godot_variant variant) =>
+ FromVariantCb != null ? FromVariantCb(variant) : throw UnsupportedType<T>();
+
+ // ReSharper disable once StaticMemberInGenericType
+ internal static unsafe delegate*<in T, godot_variant> ToVariantCb;
+
+ // ReSharper disable once StaticMemberInGenericType
+ internal static unsafe delegate*<in godot_variant, T> FromVariantCb;
+
+ [SuppressMessage("ReSharper", "RedundantNameQualifier")]
+ static GenericConversion()
+ {
+ RuntimeHelpers.RunClassConstructor(typeof(T).TypeHandle);
+ }
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
+ [SuppressMessage("ReSharper", "RedundantNameQualifier")]
+ public static godot_variant CreateFrom<[MustBeVariant] T>(in T from)
+ {
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ static TTo UnsafeAs<TTo>(in T f) => Unsafe.As<T, TTo>(ref Unsafe.AsRef(f));
+
+ // `typeof(T) == typeof(X)` is optimized away. We cannot cache `typeof(T)` in a local variable, as it's not optimized when done like that.
+
+ if (typeof(T) == typeof(bool))
+ return CreateFromBool(UnsafeAs<bool>(from));
+
+ if (typeof(T) == typeof(char))
+ return CreateFromInt(UnsafeAs<char>(from));
+
+ if (typeof(T) == typeof(sbyte))
+ return CreateFromInt(UnsafeAs<sbyte>(from));
+
+ if (typeof(T) == typeof(short))
+ return CreateFromInt(UnsafeAs<short>(from));
+
+ if (typeof(T) == typeof(int))
+ return CreateFromInt(UnsafeAs<int>(from));
+
+ if (typeof(T) == typeof(long))
+ return CreateFromInt(UnsafeAs<long>(from));
+
+ if (typeof(T) == typeof(byte))
+ return CreateFromInt(UnsafeAs<byte>(from));
+
+ if (typeof(T) == typeof(ushort))
+ return CreateFromInt(UnsafeAs<ushort>(from));
+
+ if (typeof(T) == typeof(uint))
+ return CreateFromInt(UnsafeAs<uint>(from));
+
+ if (typeof(T) == typeof(ulong))
+ return CreateFromInt(UnsafeAs<ulong>(from));
+
+ if (typeof(T) == typeof(float))
+ return CreateFromFloat(UnsafeAs<float>(from));
+
+ if (typeof(T) == typeof(double))
+ return CreateFromFloat(UnsafeAs<double>(from));
+
+ if (typeof(T) == typeof(Vector2))
+ return CreateFromVector2(UnsafeAs<Vector2>(from));
+
+ if (typeof(T) == typeof(Vector2i))
+ return CreateFromVector2i(UnsafeAs<Vector2i>(from));
+
+ if (typeof(T) == typeof(Rect2))
+ return CreateFromRect2(UnsafeAs<Rect2>(from));
+
+ if (typeof(T) == typeof(Rect2i))
+ return CreateFromRect2i(UnsafeAs<Rect2i>(from));
+
+ if (typeof(T) == typeof(Transform2D))
+ return CreateFromTransform2D(UnsafeAs<Transform2D>(from));
+
+ if (typeof(T) == typeof(Projection))
+ return CreateFromProjection(UnsafeAs<Projection>(from));
+
+ if (typeof(T) == typeof(Vector3))
+ return CreateFromVector3(UnsafeAs<Vector3>(from));
+
+ if (typeof(T) == typeof(Vector3i))
+ return CreateFromVector3i(UnsafeAs<Vector3i>(from));
+
+ if (typeof(T) == typeof(Basis))
+ return CreateFromBasis(UnsafeAs<Basis>(from));
+
+ if (typeof(T) == typeof(Quaternion))
+ return CreateFromQuaternion(UnsafeAs<Quaternion>(from));
+
+ if (typeof(T) == typeof(Transform3D))
+ return CreateFromTransform3D(UnsafeAs<Transform3D>(from));
+
+ if (typeof(T) == typeof(Vector4))
+ return CreateFromVector4(UnsafeAs<Vector4>(from));
+
+ if (typeof(T) == typeof(Vector4i))
+ return CreateFromVector4i(UnsafeAs<Vector4i>(from));
+
+ if (typeof(T) == typeof(AABB))
+ return CreateFromAABB(UnsafeAs<AABB>(from));
+
+ if (typeof(T) == typeof(Color))
+ return CreateFromColor(UnsafeAs<Color>(from));
+
+ if (typeof(T) == typeof(Plane))
+ return CreateFromPlane(UnsafeAs<Plane>(from));
+
+ if (typeof(T) == typeof(Callable))
+ return CreateFromCallable(UnsafeAs<Callable>(from));
+
+ if (typeof(T) == typeof(Signal))
+ return CreateFromSignal(UnsafeAs<Signal>(from));
+
+ if (typeof(T) == typeof(string))
+ return CreateFromString(UnsafeAs<string>(from));
+
+ if (typeof(T) == typeof(byte[]))
+ return CreateFromPackedByteArray(UnsafeAs<byte[]>(from));
+
+ if (typeof(T) == typeof(int[]))
+ return CreateFromPackedInt32Array(UnsafeAs<int[]>(from));
+
+ if (typeof(T) == typeof(long[]))
+ return CreateFromPackedInt64Array(UnsafeAs<long[]>(from));
+
+ if (typeof(T) == typeof(float[]))
+ return CreateFromPackedFloat32Array(UnsafeAs<float[]>(from));
+
+ if (typeof(T) == typeof(double[]))
+ return CreateFromPackedFloat64Array(UnsafeAs<double[]>(from));
+
+ if (typeof(T) == typeof(string[]))
+ return CreateFromPackedStringArray(UnsafeAs<string[]>(from));
+
+ if (typeof(T) == typeof(Vector2[]))
+ return CreateFromPackedVector2Array(UnsafeAs<Vector2[]>(from));
+
+ if (typeof(T) == typeof(Vector3[]))
+ return CreateFromPackedVector3Array(UnsafeAs<Vector3[]>(from));
+
+ if (typeof(T) == typeof(Color[]))
+ return CreateFromPackedColorArray(UnsafeAs<Color[]>(from));
+
+ if (typeof(T) == typeof(StringName[]))
+ return CreateFromSystemArrayOfStringName(UnsafeAs<StringName[]>(from));
+
+ if (typeof(T) == typeof(NodePath[]))
+ return CreateFromSystemArrayOfNodePath(UnsafeAs<NodePath[]>(from));
+
+ if (typeof(T) == typeof(RID[]))
+ return CreateFromSystemArrayOfRID(UnsafeAs<RID[]>(from));
+
+ if (typeof(T) == typeof(StringName))
+ return CreateFromStringName(UnsafeAs<StringName>(from));
+
+ if (typeof(T) == typeof(NodePath))
+ return CreateFromNodePath(UnsafeAs<NodePath>(from));
+
+ if (typeof(T) == typeof(RID))
+ return CreateFromRID(UnsafeAs<RID>(from));
+
+ if (typeof(T) == typeof(Godot.Collections.Dictionary))
+ return CreateFromDictionary(UnsafeAs<Godot.Collections.Dictionary>(from));
+
+ if (typeof(T) == typeof(Godot.Collections.Array))
+ return CreateFromArray(UnsafeAs<Godot.Collections.Array>(from));
+
+ if (typeof(T) == typeof(Variant))
+ return NativeFuncs.godotsharp_variant_new_copy((godot_variant)UnsafeAs<Variant>(from).NativeVar);
+
+ // More complex checks here at the end, to avoid screwing the simple ones in case they're not optimized away.
+
+ // `typeof(X).IsAssignableFrom(typeof(T))` is optimized away
+
+ if (typeof(Godot.Object).IsAssignableFrom(typeof(T)))
+ return CreateFromGodotObject(UnsafeAs<Godot.Object>(from));
+
+ // `typeof(T).IsValueType` is optimized away
+ // `typeof(T).IsEnum` is NOT optimized away: https://github.com/dotnet/runtime/issues/67113
+ // Fortunately, `typeof(System.Enum).IsAssignableFrom(typeof(T))` does the job!
+
+ if (typeof(T).IsValueType && typeof(System.Enum).IsAssignableFrom(typeof(T)))
+ {
+ // `Type.GetTypeCode(typeof(T).GetEnumUnderlyingType())` is not optimized away.
+ // Fortunately, `Unsafe.SizeOf<T>()` works and is optimized away.
+ // We don't need to know whether it's signed or unsigned.
+
+ if (Unsafe.SizeOf<T>() == 1)
+ return CreateFromInt(UnsafeAs<sbyte>(from));
+
+ if (Unsafe.SizeOf<T>() == 2)
+ return CreateFromInt(UnsafeAs<short>(from));
+
+ if (Unsafe.SizeOf<T>() == 4)
+ return CreateFromInt(UnsafeAs<int>(from));
+
+ if (Unsafe.SizeOf<T>() == 8)
+ return CreateFromInt(UnsafeAs<long>(from));
+
+ throw UnsupportedType<T>();
+ }
+
+ return GenericConversion<T>.ToVariant(from);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
+ [SuppressMessage("ReSharper", "RedundantNameQualifier")]
+ public static T ConvertTo<[MustBeVariant] T>(in godot_variant variant)
+ {
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ static T UnsafeAsT<TFrom>(TFrom f) => Unsafe.As<TFrom, T>(ref Unsafe.AsRef(f));
+
+ if (typeof(T) == typeof(bool))
+ return UnsafeAsT(ConvertToBool(variant));
+
+ if (typeof(T) == typeof(char))
+ return UnsafeAsT(ConvertToChar(variant));
+
+ if (typeof(T) == typeof(sbyte))
+ return UnsafeAsT(ConvertToInt8(variant));
+
+ if (typeof(T) == typeof(short))
+ return UnsafeAsT(ConvertToInt16(variant));
+
+ if (typeof(T) == typeof(int))
+ return UnsafeAsT(ConvertToInt32(variant));
+
+ if (typeof(T) == typeof(long))
+ return UnsafeAsT(ConvertToInt64(variant));
+
+ if (typeof(T) == typeof(byte))
+ return UnsafeAsT(ConvertToUInt8(variant));
+
+ if (typeof(T) == typeof(ushort))
+ return UnsafeAsT(ConvertToUInt16(variant));
+
+ if (typeof(T) == typeof(uint))
+ return UnsafeAsT(ConvertToUInt32(variant));
+
+ if (typeof(T) == typeof(ulong))
+ return UnsafeAsT(ConvertToUInt64(variant));
+
+ if (typeof(T) == typeof(float))
+ return UnsafeAsT(ConvertToFloat32(variant));
+
+ if (typeof(T) == typeof(double))
+ return UnsafeAsT(ConvertToFloat64(variant));
+
+ if (typeof(T) == typeof(Vector2))
+ return UnsafeAsT(ConvertToVector2(variant));
+
+ if (typeof(T) == typeof(Vector2i))
+ return UnsafeAsT(ConvertToVector2i(variant));
+
+ if (typeof(T) == typeof(Rect2))
+ return UnsafeAsT(ConvertToRect2(variant));
+
+ if (typeof(T) == typeof(Rect2i))
+ return UnsafeAsT(ConvertToRect2i(variant));
+
+ if (typeof(T) == typeof(Transform2D))
+ return UnsafeAsT(ConvertToTransform2D(variant));
+
+ if (typeof(T) == typeof(Vector3))
+ return UnsafeAsT(ConvertToVector3(variant));
+
+ if (typeof(T) == typeof(Vector3i))
+ return UnsafeAsT(ConvertToVector3i(variant));
+
+ if (typeof(T) == typeof(Basis))
+ return UnsafeAsT(ConvertToBasis(variant));
+
+ if (typeof(T) == typeof(Quaternion))
+ return UnsafeAsT(ConvertToQuaternion(variant));
+
+ if (typeof(T) == typeof(Transform3D))
+ return UnsafeAsT(ConvertToTransform3D(variant));
+
+ if (typeof(T) == typeof(Projection))
+ return UnsafeAsT(ConvertToProjection(variant));
+
+ if (typeof(T) == typeof(Vector4))
+ return UnsafeAsT(ConvertToVector4(variant));
+
+ if (typeof(T) == typeof(Vector4i))
+ return UnsafeAsT(ConvertToVector4i(variant));
+
+ if (typeof(T) == typeof(AABB))
+ return UnsafeAsT(ConvertToAABB(variant));
+
+ if (typeof(T) == typeof(Color))
+ return UnsafeAsT(ConvertToColor(variant));
+
+ if (typeof(T) == typeof(Plane))
+ return UnsafeAsT(ConvertToPlane(variant));
+
+ if (typeof(T) == typeof(Callable))
+ return UnsafeAsT(ConvertToCallable(variant));
+
+ if (typeof(T) == typeof(Signal))
+ return UnsafeAsT(ConvertToSignal(variant));
+
+ if (typeof(T) == typeof(string))
+ return UnsafeAsT(ConvertToString(variant));
+
+ if (typeof(T) == typeof(byte[]))
+ return UnsafeAsT(ConvertAsPackedByteArrayToSystemArray(variant));
+
+ if (typeof(T) == typeof(int[]))
+ return UnsafeAsT(ConvertAsPackedInt32ArrayToSystemArray(variant));
+
+ if (typeof(T) == typeof(long[]))
+ return UnsafeAsT(ConvertAsPackedInt64ArrayToSystemArray(variant));
+
+ if (typeof(T) == typeof(float[]))
+ return UnsafeAsT(ConvertAsPackedFloat32ArrayToSystemArray(variant));
+
+ if (typeof(T) == typeof(double[]))
+ return UnsafeAsT(ConvertAsPackedFloat64ArrayToSystemArray(variant));
+
+ if (typeof(T) == typeof(string[]))
+ return UnsafeAsT(ConvertAsPackedStringArrayToSystemArray(variant));
+
+ if (typeof(T) == typeof(Vector2[]))
+ return UnsafeAsT(ConvertAsPackedVector2ArrayToSystemArray(variant));
+
+ if (typeof(T) == typeof(Vector3[]))
+ return UnsafeAsT(ConvertAsPackedVector3ArrayToSystemArray(variant));
+
+ if (typeof(T) == typeof(Color[]))
+ return UnsafeAsT(ConvertAsPackedColorArrayToSystemArray(variant));
+
+ if (typeof(T) == typeof(StringName[]))
+ return UnsafeAsT(ConvertToSystemArrayOfStringName(variant));
+
+ if (typeof(T) == typeof(NodePath[]))
+ return UnsafeAsT(ConvertToSystemArrayOfNodePath(variant));
+
+ if (typeof(T) == typeof(RID[]))
+ return UnsafeAsT(ConvertToSystemArrayOfRID(variant));
+
+ if (typeof(T) == typeof(StringName))
+ return UnsafeAsT(ConvertToStringName(variant));
+
+ if (typeof(T) == typeof(NodePath))
+ return UnsafeAsT(ConvertToNodePath(variant));
+
+ if (typeof(T) == typeof(RID))
+ return UnsafeAsT(ConvertToRID(variant));
+
+ if (typeof(T) == typeof(Godot.Collections.Dictionary))
+ return UnsafeAsT(ConvertToDictionary(variant));
+
+ if (typeof(T) == typeof(Godot.Collections.Array))
+ return UnsafeAsT(ConvertToArray(variant));
+
+ if (typeof(T) == typeof(Variant))
+ return UnsafeAsT(Variant.CreateCopyingBorrowed(variant));
+
+ // More complex checks here at the end, to avoid screwing the simple ones in case they're not optimized away.
+
+ // `typeof(X).IsAssignableFrom(typeof(T))` is optimized away
+
+ if (typeof(Godot.Object).IsAssignableFrom(typeof(T)))
+ return (T)(object)ConvertToGodotObject(variant);
+
+ // `typeof(T).IsValueType` is optimized away
+ // `typeof(T).IsEnum` is NOT optimized away: https://github.com/dotnet/runtime/issues/67113
+ // Fortunately, `typeof(System.Enum).IsAssignableFrom(typeof(T))` does the job!
+
+ if (typeof(T).IsValueType && typeof(System.Enum).IsAssignableFrom(typeof(T)))
+ {
+ // `Type.GetTypeCode(typeof(T).GetEnumUnderlyingType())` is not optimized away.
+ // Fortunately, `Unsafe.SizeOf<T>()` works and is optimized away.
+ // We don't need to know whether it's signed or unsigned.
+
+ if (Unsafe.SizeOf<T>() == 1)
+ return UnsafeAsT(ConvertToInt8(variant));
+
+ if (Unsafe.SizeOf<T>() == 2)
+ return UnsafeAsT(ConvertToInt16(variant));
+
+ if (Unsafe.SizeOf<T>() == 4)
+ return UnsafeAsT(ConvertToInt32(variant));
+
+ if (Unsafe.SizeOf<T>() == 8)
+ return UnsafeAsT(ConvertToInt64(variant));
+
+ throw UnsupportedType<T>();
+ }
+
+ return GenericConversion<T>.FromVariant(variant);
+ }
+}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Plane.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Plane.cs
index 664b2e0f34..42c6b0a37e 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Plane.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Plane.cs
@@ -22,7 +22,7 @@ namespace Godot
/// <value>Equivalent to <see cref="x"/>, <see cref="y"/>, and <see cref="z"/>.</value>
public Vector3 Normal
{
- get { return _normal; }
+ readonly get { return _normal; }
set { _normal = value; }
}
@@ -32,7 +32,7 @@ namespace Godot
/// <value>Equivalent to <see cref="Normal"/>'s X value.</value>
public real_t x
{
- get
+ readonly get
{
return _normal.x;
}
@@ -48,7 +48,7 @@ namespace Godot
/// <value>Equivalent to <see cref="Normal"/>'s Y value.</value>
public real_t y
{
- get
+ readonly get
{
return _normal.y;
}
@@ -64,7 +64,7 @@ namespace Godot
/// <value>Equivalent to <see cref="Normal"/>'s Z value.</value>
public real_t z
{
- get
+ readonly get
{
return _normal.z;
}
@@ -90,7 +90,7 @@ namespace Godot
/// <value>Equivalent to <see cref="Normal"/> multiplied by <see cref="D"/>.</value>
public Vector3 Center
{
- get
+ readonly get
{
return _normal * D;
}
@@ -106,7 +106,7 @@ namespace Godot
/// </summary>
/// <param name="point">The position to use for the calculation.</param>
/// <returns>The shortest distance.</returns>
- public real_t DistanceTo(Vector3 point)
+ public readonly real_t DistanceTo(Vector3 point)
{
return _normal.Dot(point) - D;
}
@@ -118,7 +118,7 @@ namespace Godot
/// <param name="point">The point to check.</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 tolerance = Mathf.Epsilon)
+ public readonly bool HasPoint(Vector3 point, real_t tolerance = Mathf.Epsilon)
{
real_t dist = _normal.Dot(point) - D;
return Mathf.Abs(dist) <= tolerance;
@@ -131,7 +131,7 @@ namespace Godot
/// <param name="b">One of the three planes to use in the calculation.</param>
/// <param name="c">One of the three planes to use in the calculation.</param>
/// <returns>The intersection, or <see langword="null"/> if none is found.</returns>
- public Vector3? Intersect3(Plane b, Plane c)
+ public readonly Vector3? Intersect3(Plane b, Plane c)
{
real_t denom = _normal.Cross(b._normal).Dot(c._normal);
@@ -155,7 +155,7 @@ namespace Godot
/// <param name="from">The start of the ray.</param>
/// <param name="dir">The direction of the ray, normalized.</param>
/// <returns>The intersection, or <see langword="null"/> if none is found.</returns>
- public Vector3? IntersectRay(Vector3 from, Vector3 dir)
+ public readonly Vector3? IntersectRay(Vector3 from, Vector3 dir)
{
real_t den = _normal.Dot(dir);
@@ -183,7 +183,7 @@ namespace Godot
/// <param name="begin">The start of the line segment.</param>
/// <param name="end">The end of the line segment.</param>
/// <returns>The intersection, or <see langword="null"/> if none is found.</returns>
- public Vector3? IntersectSegment(Vector3 begin, Vector3 end)
+ public readonly Vector3? IntersectSegment(Vector3 begin, Vector3 end)
{
Vector3 segment = begin - end;
real_t den = _normal.Dot(segment);
@@ -209,7 +209,7 @@ namespace Godot
/// </summary>
/// <param name="point">The point to check.</param>
/// <returns>A <see langword="bool"/> for whether or not the point is above the plane.</returns>
- public bool IsPointOver(Vector3 point)
+ public readonly bool IsPointOver(Vector3 point)
{
return _normal.Dot(point) > D;
}
@@ -218,7 +218,7 @@ namespace Godot
/// Returns the plane scaled to unit length.
/// </summary>
/// <returns>A normalized version of the plane.</returns>
- public Plane Normalized()
+ public readonly Plane Normalized()
{
real_t len = _normal.Length();
@@ -235,7 +235,7 @@ namespace Godot
/// </summary>
/// <param name="point">The point to project.</param>
/// <returns>The projected point.</returns>
- public Vector3 Project(Vector3 point)
+ public readonly Vector3 Project(Vector3 point)
{
return point - (_normal * DistanceTo(point));
}
@@ -363,7 +363,7 @@ namespace Godot
/// </summary>
/// <param name="obj">The other object to compare.</param>
/// <returns>Whether or not the plane and the other object are exactly equal.</returns>
- public override bool Equals(object obj)
+ public override readonly bool Equals(object obj)
{
return obj is Plane other && Equals(other);
}
@@ -373,7 +373,7 @@ namespace Godot
/// </summary>
/// <param name="other">The other plane to compare.</param>
/// <returns>Whether or not the planes are exactly equal.</returns>
- public bool Equals(Plane other)
+ public readonly bool Equals(Plane other)
{
return _normal == other._normal && D == other.D;
}
@@ -384,7 +384,7 @@ namespace Godot
/// </summary>
/// <param name="other">The other plane to compare.</param>
/// <returns>Whether or not the planes are approximately equal.</returns>
- public bool IsEqualApprox(Plane other)
+ public readonly bool IsEqualApprox(Plane other)
{
return _normal.IsEqualApprox(other._normal) && Mathf.IsEqualApprox(D, other.D);
}
@@ -393,7 +393,7 @@ namespace Godot
/// Serves as the hash function for <see cref="Plane"/>.
/// </summary>
/// <returns>A hash code for this plane.</returns>
- public override int GetHashCode()
+ public override readonly int GetHashCode()
{
return _normal.GetHashCode() ^ D.GetHashCode();
}
@@ -402,7 +402,7 @@ namespace Godot
/// Converts this <see cref="Plane"/> to a string.
/// </summary>
/// <returns>A string representation of this plane.</returns>
- public override string ToString()
+ public override readonly string ToString()
{
return $"{_normal}, {D}";
}
@@ -411,7 +411,7 @@ namespace Godot
/// Converts this <see cref="Plane"/> to a string with the given <paramref name="format"/>.
/// </summary>
/// <returns>A string representation of this plane.</returns>
- public string ToString(string format)
+ public readonly string ToString(string format)
{
return $"{_normal.ToString(format)}, {D.ToString(format)}";
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Projection.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Projection.cs
index da895fd121..fd37f8d9e8 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Projection.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Projection.cs
@@ -3,6 +3,14 @@ using System.Runtime.InteropServices;
namespace Godot
{
+ /// <summary>
+ /// A 4x4 matrix used for 3D projective transformations. It can represent transformations such as
+ /// translation, rotation, scaling, shearing, and perspective division. It consists of four
+ /// <see cref="Vector4"/> columns.
+ /// For purely linear transformations (translation, rotation, and scale), it is recommended to use
+ /// <see cref="Transform3D"/>, as it is more performant and has a lower memory footprint.
+ /// Used internally as <see cref="Camera3D"/>'s projection matrix.
+ /// </summary>
[Serializable]
[StructLayout(LayoutKind.Sequential)]
public struct Projection : IEquatable<Projection>
@@ -59,48 +67,107 @@ namespace Godot
public Vector4 w;
/// <summary>
- /// Constructs a projection from 4 vectors (matrix columns).
+ /// Access whole columns in the form of <see cref="Vector4"/>.
/// </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)
+ /// <param name="column">Which column vector.</param>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// <paramref name="column"/> is not 0, 1, 2 or 3.
+ /// </exception>
+ public Vector4 this[int column]
{
- this.x = x;
- this.y = y;
- this.z = z;
- this.w = w;
+ readonly get
+ {
+ switch (column)
+ {
+ case 0:
+ return x;
+ case 1:
+ return y;
+ case 2:
+ return z;
+ case 3:
+ return w;
+ default:
+ throw new ArgumentOutOfRangeException(nameof(column));
+ }
+ }
+ 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 ArgumentOutOfRangeException(nameof(column));
+ }
+ }
}
/// <summary>
- /// Constructs a new <see cref="Projection"/> from a <see cref="Transform3D"/>.
+ /// Access single values.
/// </summary>
- /// <param name="transform">The <see cref="Transform3D"/>.</param>
- public Projection(Transform3D transform)
+ /// <param name="column">Which column vector.</param>
+ /// <param name="row">Which row of the column.</param>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// <paramref name="column"/> or <paramref name="row"/> are not 0, 1, 2 or 3.
+ /// </exception>
+ public real_t this[int column, int row]
{
- 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);
+ readonly 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 ArgumentOutOfRangeException(nameof(column));
+ }
+ }
+ 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 ArgumentOutOfRangeException(nameof(column));
+ }
+ }
}
/// <summary>
- /// Constructs a new <see cref="Transform3D"/> from the <see cref="Projection"/>.
+ /// Creates a new <see cref="Projection"/> that projects positions from a depth range of
+ /// <c>-1</c> to <c>1</c> to one that ranges from <c>0</c> to <c>1</c>, and flips the projected
+ /// positions vertically, according to <paramref name="flipY"/>.
/// </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)
- );
- }
-
+ /// <param name="flipY">If the projection should be flipped vertically.</param>
+ /// <returns>The created projection.</returns>
public static Projection CreateDepthCorrection(bool flipY)
{
return new Projection(
@@ -111,6 +178,12 @@ namespace Godot
);
}
+ /// <summary>
+ /// Creates a new <see cref="Projection"/> that scales a given projection to fit around
+ /// a given <see cref="AABB"/> in projection space.
+ /// </summary>
+ /// <param name="aabb">The AABB to fit the projection around.</param>
+ /// <returns>The created projection.</returns>
public static Projection CreateFitAabb(AABB aabb)
{
Vector3 min = aabb.Position;
@@ -124,6 +197,25 @@ namespace Godot
);
}
+ /// <summary>
+ /// Creates a new <see cref="Projection"/> for projecting positions onto a head-mounted display with
+ /// the given X:Y aspect ratio, distance between eyes, display width, distance to lens, oversampling factor,
+ /// and depth clipping planes.
+ /// <paramref name="eye"/> creates the projection for the left eye when set to 1,
+ /// or the right eye when set to 2.
+ /// </summary>
+ /// <param name="eye">
+ /// The eye to create the projection for.
+ /// The left eye when set to 1, the right eye when set to 2.
+ /// </param>
+ /// <param name="aspect">The aspect ratio.</param>
+ /// <param name="intraocularDist">The distance between the eyes.</param>
+ /// <param name="displayWidth">The display width.</param>
+ /// <param name="displayToLens">The distance to the lens.</param>
+ /// <param name="oversample">The oversampling factor.</param>
+ /// <param name="zNear">The near clipping distance.</param>
+ /// <param name="zFar">The far clipping distance.</param>
+ /// <returns>The created projection.</returns>
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;
@@ -148,6 +240,17 @@ namespace Godot
}
}
+ /// <summary>
+ /// Creates a new <see cref="Projection"/> that projects positions in a frustum with
+ /// the given clipping planes.
+ /// </summary>
+ /// <param name="left">The left clipping distance.</param>
+ /// <param name="right">The right clipping distance.</param>
+ /// <param name="bottom">The bottom clipping distance.</param>
+ /// <param name="top">The top clipping distance.</param>
+ /// <param name="near">The near clipping distance.</param>
+ /// <param name="far">The far clipping distance.</param>
+ /// <returns>The created projection.</returns>
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)
@@ -179,6 +282,18 @@ namespace Godot
);
}
+ /// <summary>
+ /// Creates a new <see cref="Projection"/> that projects positions in a frustum with
+ /// the given size, X:Y aspect ratio, offset, and clipping planes.
+ /// <paramref name="flipFov"/> determines whether the projection's field of view is flipped over its diagonal.
+ /// </summary>
+ /// <param name="size">The frustum size.</param>
+ /// <param name="aspect">The aspect ratio.</param>
+ /// <param name="offset">The offset to apply.</param>
+ /// <param name="near">The near clipping distance.</param>
+ /// <param name="far">The far clipping distance.</param>
+ /// <param name="flipFov">If the field of view is flipped over the projection's diagonal.</param>
+ /// <returns>The created projection.</returns>
public static Projection CreateFrustumAspect(real_t size, real_t aspect, Vector2 offset, real_t near, real_t far, bool flipFov)
{
if (!flipFov)
@@ -188,6 +303,11 @@ namespace Godot
return CreateFrustum(-size / 2 + offset.x, +size / 2 + offset.x, -size / aspect / 2 + offset.y, +size / aspect / 2 + offset.y, near, far);
}
+ /// <summary>
+ /// Creates a new <see cref="Projection"/> that projects positions into the given <see cref="Rect2"/>.
+ /// </summary>
+ /// <param name="rect">The Rect2 to project positions into.</param>
+ /// <returns>The created projection.</returns>
public static Projection CreateLightAtlasRect(Rect2 rect)
{
return new Projection(
@@ -198,6 +318,17 @@ namespace Godot
);
}
+ /// <summary>
+ /// Creates a new <see cref="Projection"/> that projects positions using an orthogonal projection with
+ /// the given clipping planes.
+ /// </summary>
+ /// <param name="left">The left clipping distance.</param>
+ /// <param name="right">The right clipping distance.</param>
+ /// <param name="bottom">The bottom clipping distance.</param>
+ /// <param name="top">The top clipping distance.</param>
+ /// <param name="zNear">The near clipping distance.</param>
+ /// <param name="zFar">The far clipping distance.</param>
+ /// <returns>The created projection.</returns>
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;
@@ -211,6 +342,17 @@ namespace Godot
return proj;
}
+ /// <summary>
+ /// Creates a new <see cref="Projection"/> that projects positions using an orthogonal projection with
+ /// the given size, X:Y aspect ratio, and clipping planes.
+ /// <paramref name="flipFov"/> determines whether the projection's field of view is flipped over its diagonal.
+ /// </summary>
+ /// <param name="size">The frustum size.</param>
+ /// <param name="aspect">The aspect ratio.</param>
+ /// <param name="zNear">The near clipping distance.</param>
+ /// <param name="zFar">The far clipping distance.</param>
+ /// <param name="flipFov">If the field of view is flipped over the projection's diagonal.</param>
+ /// <returns>The created projection.</returns>
public static Projection CreateOrthogonalAspect(real_t size, real_t aspect, real_t zNear, real_t zFar, bool flipFov)
{
if (!flipFov)
@@ -220,6 +362,17 @@ namespace Godot
return CreateOrthogonal(-size / 2, +size / 2, -size / aspect / 2, +size / aspect / 2, zNear, zFar);
}
+ /// <summary>
+ /// Creates a new <see cref="Projection"/> that projects positions using a perspective projection with
+ /// the given Y-axis field of view (in degrees), X:Y aspect ratio, and clipping planes.
+ /// <paramref name="flipFov"/> determines whether the projection's field of view is flipped over its diagonal.
+ /// </summary>
+ /// <param name="fovyDegrees">The vertical field of view (in degrees).</param>
+ /// <param name="aspect">The aspect ratio.</param>
+ /// <param name="zNear">The near clipping distance.</param>
+ /// <param name="zFar">The far clipping distance.</param>
+ /// <param name="flipFov">If the field of view is flipped over the projection's diagonal.</param>
+ /// <returns>The created projection.</returns>
public static Projection CreatePerspective(real_t fovyDegrees, real_t aspect, real_t zNear, real_t zFar, bool flipFov)
{
if (flipFov)
@@ -249,6 +402,27 @@ namespace Godot
return proj;
}
+ /// <summary>
+ /// Creates a new <see cref="Projection"/> that projects positions using a perspective projection with
+ /// the given Y-axis field of view (in degrees), X:Y aspect ratio, and clipping distances.
+ /// The projection is adjusted for a head-mounted display with the given distance between eyes and distance
+ /// to a point that can be focused on.
+ /// <paramref name="eye"/> creates the projection for the left eye when set to 1,
+ /// or the right eye when set to 2.
+ /// <paramref name="flipFov"/> determines whether the projection's field of view is flipped over its diagonal.
+ /// </summary>
+ /// <param name="fovyDegrees">The vertical field of view (in degrees).</param>
+ /// <param name="aspect">The aspect ratio.</param>
+ /// <param name="zNear">The near clipping distance.</param>
+ /// <param name="zFar">The far clipping distance.</param>
+ /// <param name="flipFov">If the field of view is flipped over the projection's diagonal.</param>
+ /// <param name="eye">
+ /// The eye to create the projection for.
+ /// The left eye when set to 1, the right eye when set to 2.
+ /// </param>
+ /// <param name="intraocularDist">The distance between the eyes.</param>
+ /// <param name="convergenceDist">The distance to a point of convergence that can be focused on.</param>
+ /// <returns>The created projection.</returns>
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)
@@ -286,7 +460,14 @@ namespace Godot
return proj * cm;
}
- public real_t Determinant()
+ /// <summary>
+ /// Returns a scalar value that is the signed factor by which areas are scaled by this matrix.
+ /// If the sign is negative, the matrix flips the orientation of the area.
+ /// The determinant can be used to calculate the invertibility of a matrix or solve linear systems
+ /// of equations involving the matrix, among other applications.
+ /// </summary>
+ /// <returns>The determinant calculated from this projection.</returns>
+ public readonly 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 +
@@ -302,13 +483,21 @@ namespace Godot
x.y * y.x * z.z * w.w + x.x * y.y * z.z * w.w;
}
- public real_t GetAspect()
+ /// <summary>
+ /// Returns the X:Y aspect ratio of this <see cref="Projection"/>'s viewport.
+ /// </summary>
+ /// <returns>The aspect ratio from this projection's viewport.</returns>
+ public readonly real_t GetAspect()
{
Vector2 vpHe = GetViewportHalfExtents();
return vpHe.x / vpHe.y;
}
- public real_t GetFov()
+ /// <summary>
+ /// Returns the horizontal field of view of the projection (in degrees).
+ /// </summary>
+ /// <returns>The horizontal field of view of this projection.</returns>
+ public readonly 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)
@@ -322,12 +511,23 @@ namespace Godot
}
}
+ /// <summary>
+ /// Returns the vertical field of view of the projection (in degrees) associated with
+ /// the given horizontal field of view (in degrees) and aspect ratio.
+ /// </summary>
+ /// <param name="fovx">The horizontal field of view (in degrees).</param>
+ /// <param name="aspect">The aspect ratio.</param>
+ /// <returns>The vertical field of view of this projection.</returns>
public static real_t GetFovy(real_t fovx, real_t aspect)
{
return Mathf.RadToDeg(Mathf.Atan(aspect * Mathf.Tan(Mathf.DegToRad(fovx) * (real_t)0.5)) * (real_t)2.0);
}
- public real_t GetLodMultiplier()
+ /// <summary>
+ /// Returns the factor by which the visible level of detail is scaled by this <see cref="Projection"/>.
+ /// </summary>
+ /// <returns>The level of detail factor for this projection.</returns>
+ public readonly real_t GetLodMultiplier()
{
if (IsOrthogonal())
{
@@ -341,14 +541,29 @@ namespace Godot
}
}
- public int GetPixelsPerMeter(int forPixelWidth)
+ /// <summary>
+ /// Returns the number of pixels with the given pixel width displayed per meter, after
+ /// this <see cref="Projection"/> is applied.
+ /// </summary>
+ /// <param name="forPixelWidth">The width for each pixel (in meters).</param>
+ /// <returns>The number of pixels per meter.</returns>
+ public readonly int GetPixelsPerMeter(int forPixelWidth)
{
Vector3 result = this * new Vector3(1, 0, -1);
return (int)((result.x * (real_t)0.5 + (real_t)0.5) * forPixelWidth);
}
- public Plane GetProjectionPlane(Planes plane)
+ /// <summary>
+ /// Returns the clipping plane of this <see cref="Projection"/> whose index is given
+ /// by <paramref name="plane"/>.
+ /// <paramref name="plane"/> should be equal to one of <see cref="Planes.Near"/>,
+ /// <see cref="Planes.Far"/>, <see cref="Planes.Left"/>, <see cref="Planes.Top"/>,
+ /// <see cref="Planes.Right"/>, or <see cref="Planes.Bottom"/>.
+ /// </summary>
+ /// <param name="plane">The kind of clipping plane to get from the projection.</param>
+ /// <returns>The clipping plane of this projection.</returns>
+ public readonly Plane GetProjectionPlane(Planes plane)
{
Plane newPlane = plane switch
{
@@ -364,36 +579,64 @@ namespace Godot
return newPlane.Normalized();
}
- public Vector2 GetFarPlaneHalfExtents()
+ /// <summary>
+ /// Returns the dimensions of the far clipping plane of the projection, divided by two.
+ /// </summary>
+ /// <returns>The half extents for this projection's far plane.</returns>
+ public readonly 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()
+ /// <summary>
+ /// Returns the dimensions of the viewport plane that this <see cref="Projection"/>
+ /// projects positions onto, divided by two.
+ /// </summary>
+ /// <returns>The half extents for this projection's viewport plane.</returns>
+ public readonly 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()
+ /// <summary>
+ /// Returns the distance for this <see cref="Projection"/> beyond which positions are clipped.
+ /// </summary>
+ /// <returns>The distance beyond which positions are clipped.</returns>
+ public readonly real_t GetZFar()
{
return GetProjectionPlane(Planes.Far).D;
}
- public real_t GetZNear()
+ /// <summary>
+ /// Returns the distance for this <see cref="Projection"/> before which positions are clipped.
+ /// </summary>
+ /// <returns>The distance before which positions are clipped.</returns>
+ public readonly real_t GetZNear()
{
return -GetProjectionPlane(Planes.Near).D;
}
- public Projection FlippedY()
+ /// <summary>
+ /// Returns a copy of this <see cref="Projection"/> with the signs of the values of the Y column flipped.
+ /// </summary>
+ /// <returns>The flipped projection.</returns>
+ public readonly Projection FlippedY()
{
Projection proj = this;
proj.y = -proj.y;
return proj;
}
- public Projection PerspectiveZNearAdjusted(real_t newZNear)
+ /// <summary>
+ /// Returns a <see cref="Projection"/> with the near clipping distance adjusted to be
+ /// <paramref name="newZNear"/>.
+ /// Note: The original <see cref="Projection"/> must be a perspective projection.
+ /// </summary>
+ /// <param name="newZNear">The near clipping distance to adjust the projection to.</param>
+ /// <returns>The adjusted projection.</returns>
+ public readonly Projection PerspectiveZNearAdjusted(real_t newZNear)
{
Projection proj = this;
real_t zFar = GetZFar();
@@ -404,7 +647,13 @@ namespace Godot
return proj;
}
- public Projection JitterOffseted(Vector2 offset)
+ /// <summary>
+ /// Returns a <see cref="Projection"/> with the X and Y values from the given <see cref="Vector2"/>
+ /// added to the first and second values of the final column respectively.
+ /// </summary>
+ /// <param name="offset">The offset to apply to the projection.</param>
+ /// <returns>The offsetted projection.</returns>
+ public readonly Projection JitterOffseted(Vector2 offset)
{
Projection proj = this;
proj.w.x += offset.x;
@@ -412,7 +661,12 @@ namespace Godot
return proj;
}
- public Projection Inverse()
+ /// <summary>
+ /// Returns a <see cref="Projection"/> that performs the inverse of this <see cref="Projection"/>'s
+ /// projective transformation.
+ /// </summary>
+ /// <returns>The inverted projection.</returns>
+ public readonly Projection Inverse()
{
Projection proj = this;
int i, j, k;
@@ -535,11 +789,70 @@ namespace Godot
return proj;
}
- public bool IsOrthogonal()
+ /// <summary>
+ /// Returns <see langword="true"/> if this <see cref="Projection"/> performs an orthogonal projection.
+ /// </summary>
+ /// <returns>If the projection performs an orthogonal projection.</returns>
+ public readonly bool IsOrthogonal()
{
return w.w == (real_t)1.0;
}
+ // 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>
+ /// 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 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>
/// Composes these two projections by multiplying them
/// together. This has the effect of applying the right
@@ -646,133 +959,47 @@ namespace Godot
}
/// <summary>
- /// Access whole columns in the form of <see cref="Vector4"/>.
+ /// Constructs a new <see cref="Transform3D"/> from the <see cref="Projection"/>.
/// </summary>
- /// <param name="column">Which column vector.</param>
- /// <exception cref="ArgumentOutOfRangeException">
- /// <paramref name="column"/> is not 0, 1, 2 or 3.
- /// </exception>
- public Vector4 this[int column]
+ /// <param name="proj">The <see cref="Projection"/>.</param>
+ public static explicit operator Transform3D(Projection proj)
{
- get
- {
- switch (column)
- {
- case 0:
- return x;
- case 1:
- return y;
- case 2:
- return z;
- case 3:
- return w;
- default:
- throw new ArgumentOutOfRangeException(nameof(column));
- }
- }
- 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 ArgumentOutOfRangeException(nameof(column));
- }
- }
+ 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)
+ );
}
/// <summary>
- /// Access single values.
+ /// Returns <see langword="true"/> if the projection is exactly equal
+ /// to the given object (<see paramref="obj"/>).
/// </summary>
- /// <param name="column">Which column vector.</param>
- /// <param name="row">Which row of the column.</param>
- /// <exception cref="ArgumentOutOfRangeException">
- /// <paramref name="column"/> or <paramref name="row"/> are not 0, 1, 2 or 3.
- /// </exception>
- public real_t this[int column, int row]
+ /// <param name="obj">The object to compare with.</param>
+ /// <returns>Whether or not the vector and the object are equal.</returns>
+ public override readonly bool Equals(object obj)
{
- 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 ArgumentOutOfRangeException(nameof(column));
- }
- }
- 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 ArgumentOutOfRangeException(nameof(column));
- }
- }
+ return obj is Projection other && Equals(other);
}
- // 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.
+ /// Returns <see langword="true"/> if the projections are exactly equal.
/// </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; } }
+ /// <param name="other">The other projection.</param>
+ /// <returns>Whether or not the projections are exactly equal.</returns>
+ public readonly bool Equals(Projection other)
+ {
+ return x == other.x && y == other.y && z == other.z && w == other.w;
+ }
/// <summary>
/// Serves as the hash function for <see cref="Projection"/>.
/// </summary>
/// <returns>A hash code for this projection.</returns>
- public override int GetHashCode()
+ public override readonly int GetHashCode()
{
return y.GetHashCode() ^ x.GetHashCode() ^ z.GetHashCode() ^ w.GetHashCode();
}
@@ -781,7 +1008,7 @@ namespace Godot
/// Converts this <see cref="Projection"/> to a string.
/// </summary>
/// <returns>A string representation of this projection.</returns>
- public override string ToString()
+ public override readonly 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";
}
@@ -790,33 +1017,12 @@ namespace Godot
/// 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)
+ public readonly 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)
- {
- return obj is Projection other && Equals(other);
- }
-
- /// <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/Quaternion.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Quaternion.cs
index f01f0be985..c55003586b 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Quaternion.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Quaternion.cs
@@ -58,7 +58,7 @@ namespace Godot
/// </value>
public real_t this[int index]
{
- get
+ readonly get
{
switch (index)
{
@@ -101,7 +101,7 @@ namespace Godot
/// </summary>
/// <seealso cref="LengthSquared"/>
/// <value>Equivalent to <c>Mathf.Sqrt(LengthSquared)</c>.</value>
- public real_t Length
+ public readonly real_t Length
{
get { return Mathf.Sqrt(LengthSquared); }
}
@@ -112,7 +112,7 @@ namespace Godot
/// you need to compare quaternions or need the squared length for some formula.
/// </summary>
/// <value>Equivalent to <c>Dot(this)</c>.</value>
- public real_t LengthSquared
+ public readonly real_t LengthSquared
{
get { return Dot(this); }
}
@@ -128,7 +128,7 @@ namespace Godot
/// </summary>
/// <param name="to">The other quaternion.</param>
/// <returns>The angle between the quaternions.</returns>
- public real_t AngleTo(Quaternion to)
+ public readonly real_t AngleTo(Quaternion to)
{
real_t dot = Dot(to);
return Mathf.Acos(Mathf.Clamp(dot * dot * 2 - 1, -1, 1));
@@ -143,7 +143,7 @@ namespace Godot
/// <param name="postB">A quaternion after <paramref name="b"/>.</param>
/// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
/// <returns>The interpolated quaternion.</returns>
- public Quaternion SphericalCubicInterpolate(Quaternion b, Quaternion preA, Quaternion postB, real_t weight)
+ public readonly Quaternion SphericalCubicInterpolate(Quaternion b, Quaternion preA, Quaternion postB, real_t weight)
{
#if DEBUG
if (!IsNormalized())
@@ -212,7 +212,7 @@ namespace Godot
/// <param name="preAT"></param>
/// <param name="postBT"></param>
/// <returns>The interpolated quaternion.</returns>
- public Quaternion SphericalCubicInterpolateInTime(Quaternion b, Quaternion preA, Quaternion postB, real_t weight, real_t bT, real_t preAT, real_t postBT)
+ public readonly Quaternion SphericalCubicInterpolateInTime(Quaternion b, Quaternion preA, Quaternion postB, real_t weight, real_t bT, real_t preAT, real_t postBT)
{
#if DEBUG
if (!IsNormalized())
@@ -272,12 +272,12 @@ namespace Godot
/// </summary>
/// <param name="b">The other quaternion.</param>
/// <returns>The dot product.</returns>
- public real_t Dot(Quaternion b)
+ public readonly real_t Dot(Quaternion b)
{
return (x * b.x) + (y * b.y) + (z * b.z) + (w * b.w);
}
- public Quaternion Exp()
+ public readonly Quaternion Exp()
{
Vector3 v = new Vector3(x, y, z);
real_t theta = v.Length();
@@ -289,12 +289,12 @@ namespace Godot
return new Quaternion(v, theta);
}
- public real_t GetAngle()
+ public readonly real_t GetAngle()
{
return 2 * Mathf.Acos(w);
}
- public Vector3 GetAxis()
+ public readonly Vector3 GetAxis()
{
if (Mathf.Abs(w) > 1 - Mathf.Epsilon)
{
@@ -312,7 +312,7 @@ namespace Godot
/// the rotation angles in the format (X angle, Y angle, Z angle).
/// </summary>
/// <returns>The Euler angle representation of this quaternion.</returns>
- public Vector3 GetEuler(EulerOrder order = EulerOrder.Yxz)
+ public readonly Vector3 GetEuler(EulerOrder order = EulerOrder.Yxz)
{
#if DEBUG
if (!IsNormalized())
@@ -328,7 +328,7 @@ namespace Godot
/// Returns the inverse of the quaternion.
/// </summary>
/// <returns>The inverse quaternion.</returns>
- public Quaternion Inverse()
+ public readonly Quaternion Inverse()
{
#if DEBUG
if (!IsNormalized())
@@ -343,12 +343,12 @@ namespace Godot
/// Returns whether the quaternion is normalized or not.
/// </summary>
/// <returns>A <see langword="bool"/> for whether the quaternion is normalized or not.</returns>
- public bool IsNormalized()
+ public readonly bool IsNormalized()
{
return Mathf.Abs(LengthSquared - 1) <= Mathf.Epsilon;
}
- public Quaternion Log()
+ public readonly Quaternion Log()
{
Vector3 v = GetAxis() * GetAngle();
return new Quaternion(v.x, v.y, v.z, 0);
@@ -358,7 +358,7 @@ namespace Godot
/// Returns a copy of the quaternion, normalized to unit length.
/// </summary>
/// <returns>The normalized quaternion.</returns>
- public Quaternion Normalized()
+ public readonly Quaternion Normalized()
{
return this / Length;
}
@@ -372,7 +372,7 @@ namespace Godot
/// <param name="to">The destination quaternion for interpolation. Must be normalized.</param>
/// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
/// <returns>The resulting quaternion of the interpolation.</returns>
- public Quaternion Slerp(Quaternion to, real_t weight)
+ public readonly Quaternion Slerp(Quaternion to, real_t weight)
{
#if DEBUG
if (!IsNormalized())
@@ -437,7 +437,7 @@ namespace Godot
/// <param name="to">The destination quaternion for interpolation. Must be normalized.</param>
/// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
/// <returns>The resulting quaternion of the interpolation.</returns>
- public Quaternion Slerpni(Quaternion to, real_t weight)
+ public readonly Quaternion Slerpni(Quaternion to, real_t weight)
{
#if DEBUG
if (!IsNormalized())
@@ -762,7 +762,7 @@ namespace Godot
/// </summary>
/// <param name="obj">The other object to compare.</param>
/// <returns>Whether or not the quaternion and the other object are exactly equal.</returns>
- public override bool Equals(object obj)
+ public override readonly bool Equals(object obj)
{
return obj is Quaternion other && Equals(other);
}
@@ -772,7 +772,7 @@ namespace Godot
/// </summary>
/// <param name="other">The other quaternion to compare.</param>
/// <returns>Whether or not the quaternions are exactly equal.</returns>
- public bool Equals(Quaternion other)
+ public readonly bool Equals(Quaternion other)
{
return x == other.x && y == other.y && z == other.z && w == other.w;
}
@@ -783,7 +783,7 @@ namespace Godot
/// </summary>
/// <param name="other">The other quaternion to compare.</param>
/// <returns>Whether or not the quaternions are approximately equal.</returns>
- public bool IsEqualApprox(Quaternion other)
+ public readonly bool IsEqualApprox(Quaternion other)
{
return Mathf.IsEqualApprox(x, other.x) && Mathf.IsEqualApprox(y, other.y) && Mathf.IsEqualApprox(z, other.z) && Mathf.IsEqualApprox(w, other.w);
}
@@ -792,7 +792,7 @@ namespace Godot
/// Serves as the hash function for <see cref="Quaternion"/>.
/// </summary>
/// <returns>A hash code for this quaternion.</returns>
- public override int GetHashCode()
+ public override readonly int GetHashCode()
{
return y.GetHashCode() ^ x.GetHashCode() ^ z.GetHashCode() ^ w.GetHashCode();
}
@@ -801,7 +801,7 @@ namespace Godot
/// Converts this <see cref="Quaternion"/> to a string.
/// </summary>
/// <returns>A string representation of this quaternion.</returns>
- public override string ToString()
+ public override readonly string ToString()
{
return $"({x}, {y}, {z}, {w})";
}
@@ -810,7 +810,7 @@ namespace Godot
/// Converts this <see cref="Quaternion"/> to a string with the given <paramref name="format"/>.
/// </summary>
/// <returns>A string representation of this quaternion.</returns>
- public string ToString(string format)
+ public readonly 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/RID.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/RID.cs
index a31fef8360..59b9faf16c 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/RID.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/RID.cs
@@ -12,9 +12,9 @@ namespace Godot
/// classes such as <see cref="RenderingServer"/>.
/// </summary>
[StructLayout(LayoutKind.Sequential)]
- public struct RID
+ public readonly struct RID
{
- private ulong _id; // Default is 0
+ private readonly ulong _id; // Default is 0
internal RID(ulong id)
{
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2.cs
index e80d75dacf..b0e0e75a34 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2.cs
@@ -20,7 +20,7 @@ namespace Godot
/// <value>Directly uses a private field.</value>
public Vector2 Position
{
- get { return _position; }
+ readonly get { return _position; }
set { _position = value; }
}
@@ -31,7 +31,7 @@ namespace Godot
/// <value>Directly uses a private field.</value>
public Vector2 Size
{
- get { return _size; }
+ readonly get { return _size; }
set { _size = value; }
}
@@ -45,7 +45,7 @@ namespace Godot
/// </value>
public Vector2 End
{
- get { return _position + _size; }
+ readonly get { return _position + _size; }
set { _size = value - _position; }
}
@@ -53,7 +53,7 @@ namespace Godot
/// The area of this <see cref="Rect2"/>.
/// </summary>
/// <value>Equivalent to <see cref="GetArea()"/>.</value>
- public real_t Area
+ public readonly real_t Area
{
get { return GetArea(); }
}
@@ -63,7 +63,7 @@ namespace Godot
/// the top-left corner is the origin and width and height are positive.
/// </summary>
/// <returns>The modified <see cref="Rect2"/>.</returns>
- public Rect2 Abs()
+ public readonly Rect2 Abs()
{
Vector2 end = End;
Vector2 topLeft = new Vector2(Mathf.Min(_position.x, end.x), Mathf.Min(_position.y, end.y));
@@ -79,7 +79,7 @@ namespace Godot
/// The intersection of this <see cref="Rect2"/> and <paramref name="b"/>,
/// or an empty <see cref="Rect2"/> if they do not intersect.
/// </returns>
- public Rect2 Intersection(Rect2 b)
+ public readonly Rect2 Intersection(Rect2 b)
{
Rect2 newRect = b;
@@ -107,7 +107,7 @@ namespace Godot
/// <returns>
/// A <see langword="bool"/> for whether or not this <see cref="Rect2"/> encloses <paramref name="b"/>.
/// </returns>
- public bool Encloses(Rect2 b)
+ public readonly bool Encloses(Rect2 b)
{
return b._position.x >= _position.x && b._position.y >= _position.y &&
b._position.x + b._size.x < _position.x + _size.x &&
@@ -119,7 +119,7 @@ namespace Godot
/// </summary>
/// <param name="to">The point to include.</param>
/// <returns>The expanded <see cref="Rect2"/>.</returns>
- public Rect2 Expand(Vector2 to)
+ public readonly Rect2 Expand(Vector2 to)
{
Rect2 expanded = this;
@@ -154,7 +154,7 @@ namespace Godot
/// Returns the area of the <see cref="Rect2"/>.
/// </summary>
/// <returns>The area.</returns>
- public real_t GetArea()
+ public readonly real_t GetArea()
{
return _size.x * _size.y;
}
@@ -164,7 +164,7 @@ namespace Godot
/// to <see cref="Position"/> + (<see cref="Size"/> / 2).
/// </summary>
/// <returns>The center.</returns>
- public Vector2 GetCenter()
+ public readonly Vector2 GetCenter()
{
return _position + (_size * 0.5f);
}
@@ -177,7 +177,7 @@ namespace Godot
/// <seealso cref="GrowSide(Side, real_t)"/>
/// <param name="by">The amount to grow by.</param>
/// <returns>The grown <see cref="Rect2"/>.</returns>
- public Rect2 Grow(real_t by)
+ public readonly Rect2 Grow(real_t by)
{
Rect2 g = this;
@@ -200,7 +200,7 @@ namespace Godot
/// <param name="right">The amount to grow by on the right side.</param>
/// <param name="bottom">The amount to grow by on the bottom side.</param>
/// <returns>The grown <see cref="Rect2"/>.</returns>
- public Rect2 GrowIndividual(real_t left, real_t top, real_t right, real_t bottom)
+ public readonly Rect2 GrowIndividual(real_t left, real_t top, real_t right, real_t bottom)
{
Rect2 g = this;
@@ -221,7 +221,7 @@ namespace Godot
/// <param name="side">The side to grow.</param>
/// <param name="by">The amount to grow by.</param>
/// <returns>The grown <see cref="Rect2"/>.</returns>
- public Rect2 GrowSide(Side side, real_t by)
+ public readonly Rect2 GrowSide(Side side, real_t by)
{
Rect2 g = this;
@@ -242,7 +242,7 @@ namespace Godot
/// <returns>
/// A <see langword="bool"/> for whether or not the <see cref="Rect2"/> has area.
/// </returns>
- public bool HasArea()
+ public readonly bool HasArea()
{
return _size.x > 0.0f && _size.y > 0.0f;
}
@@ -255,7 +255,7 @@ namespace Godot
/// <returns>
/// A <see langword="bool"/> for whether or not the <see cref="Rect2"/> contains <paramref name="point"/>.
/// </returns>
- public bool HasPoint(Vector2 point)
+ public readonly bool HasPoint(Vector2 point)
{
if (point.x < _position.x)
return false;
@@ -281,7 +281,7 @@ namespace Godot
/// <param name="b">The other <see cref="Rect2"/> to check for intersections with.</param>
/// <param name="includeBorders">Whether or not to consider borders.</param>
/// <returns>A <see langword="bool"/> for whether or not they are intersecting.</returns>
- public bool Intersects(Rect2 b, bool includeBorders = false)
+ public readonly bool Intersects(Rect2 b, bool includeBorders = false)
{
if (includeBorders)
{
@@ -330,7 +330,7 @@ namespace Godot
/// </summary>
/// <param name="b">The other <see cref="Rect2"/>.</param>
/// <returns>The merged <see cref="Rect2"/>.</returns>
- public Rect2 Merge(Rect2 b)
+ public readonly Rect2 Merge(Rect2 b)
{
Rect2 newRect;
@@ -426,7 +426,7 @@ namespace Godot
/// </summary>
/// <param name="obj">The other object to compare.</param>
/// <returns>Whether or not the rect and the other object are exactly equal.</returns>
- public override bool Equals(object obj)
+ public override readonly bool Equals(object obj)
{
return obj is Rect2 other && Equals(other);
}
@@ -436,7 +436,7 @@ namespace Godot
/// </summary>
/// <param name="other">The other rect to compare.</param>
/// <returns>Whether or not the rects are exactly equal.</returns>
- public bool Equals(Rect2 other)
+ public readonly bool Equals(Rect2 other)
{
return _position.Equals(other._position) && _size.Equals(other._size);
}
@@ -447,7 +447,7 @@ namespace Godot
/// </summary>
/// <param name="other">The other rect to compare.</param>
/// <returns>Whether or not the rects are approximately equal.</returns>
- public bool IsEqualApprox(Rect2 other)
+ public readonly bool IsEqualApprox(Rect2 other)
{
return _position.IsEqualApprox(other._position) && _size.IsEqualApprox(other.Size);
}
@@ -456,7 +456,7 @@ namespace Godot
/// Serves as the hash function for <see cref="Rect2"/>.
/// </summary>
/// <returns>A hash code for this rect.</returns>
- public override int GetHashCode()
+ public override readonly int GetHashCode()
{
return _position.GetHashCode() ^ _size.GetHashCode();
}
@@ -465,7 +465,7 @@ namespace Godot
/// Converts this <see cref="Rect2"/> to a string.
/// </summary>
/// <returns>A string representation of this rect.</returns>
- public override string ToString()
+ public override readonly string ToString()
{
return $"{_position}, {_size}";
}
@@ -474,7 +474,7 @@ namespace Godot
/// Converts this <see cref="Rect2"/> to a string with the given <paramref name="format"/>.
/// </summary>
/// <returns>A string representation of this rect.</returns>
- public string ToString(string format)
+ public readonly string ToString(string format)
{
return $"{_position.ToString(format)}, {_size.ToString(format)}";
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2i.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2i.cs
index b2768476cc..faee81a98a 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2i.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2i.cs
@@ -20,7 +20,7 @@ namespace Godot
/// <value>Directly uses a private field.</value>
public Vector2i Position
{
- get { return _position; }
+ readonly get { return _position; }
set { _position = value; }
}
@@ -31,7 +31,7 @@ namespace Godot
/// <value>Directly uses a private field.</value>
public Vector2i Size
{
- get { return _size; }
+ readonly get { return _size; }
set { _size = value; }
}
@@ -45,7 +45,7 @@ namespace Godot
/// </value>
public Vector2i End
{
- get { return _position + _size; }
+ readonly get { return _position + _size; }
set { _size = value - _position; }
}
@@ -53,7 +53,7 @@ namespace Godot
/// The area of this <see cref="Rect2i"/>.
/// </summary>
/// <value>Equivalent to <see cref="GetArea()"/>.</value>
- public int Area
+ public readonly int Area
{
get { return GetArea(); }
}
@@ -63,7 +63,7 @@ namespace Godot
/// the top-left corner is the origin and width and height are positive.
/// </summary>
/// <returns>The modified <see cref="Rect2i"/>.</returns>
- public Rect2i Abs()
+ public readonly Rect2i Abs()
{
Vector2i end = End;
Vector2i topLeft = new Vector2i(Mathf.Min(_position.x, end.x), Mathf.Min(_position.y, end.y));
@@ -79,7 +79,7 @@ namespace Godot
/// The intersection of this <see cref="Rect2i"/> and <paramref name="b"/>,
/// or an empty <see cref="Rect2i"/> if they do not intersect.
/// </returns>
- public Rect2i Intersection(Rect2i b)
+ public readonly Rect2i Intersection(Rect2i b)
{
Rect2i newRect = b;
@@ -107,7 +107,7 @@ namespace Godot
/// <returns>
/// A <see langword="bool"/> for whether or not this <see cref="Rect2i"/> encloses <paramref name="b"/>.
/// </returns>
- public bool Encloses(Rect2i b)
+ public readonly bool Encloses(Rect2i b)
{
return b._position.x >= _position.x && b._position.y >= _position.y &&
b._position.x + b._size.x < _position.x + _size.x &&
@@ -119,7 +119,7 @@ namespace Godot
/// </summary>
/// <param name="to">The point to include.</param>
/// <returns>The expanded <see cref="Rect2i"/>.</returns>
- public Rect2i Expand(Vector2i to)
+ public readonly Rect2i Expand(Vector2i to)
{
Rect2i expanded = this;
@@ -154,7 +154,7 @@ namespace Godot
/// Returns the area of the <see cref="Rect2i"/>.
/// </summary>
/// <returns>The area.</returns>
- public int GetArea()
+ public readonly int GetArea()
{
return _size.x * _size.y;
}
@@ -166,7 +166,7 @@ namespace Godot
/// value will be rounded towards <see cref="Position"/>.
/// </summary>
/// <returns>The center.</returns>
- public Vector2i GetCenter()
+ public readonly Vector2i GetCenter()
{
return _position + (_size / 2);
}
@@ -179,7 +179,7 @@ namespace Godot
/// <seealso cref="GrowSide(Side, int)"/>
/// <param name="by">The amount to grow by.</param>
/// <returns>The grown <see cref="Rect2i"/>.</returns>
- public Rect2i Grow(int by)
+ public readonly Rect2i Grow(int by)
{
Rect2i g = this;
@@ -202,7 +202,7 @@ namespace Godot
/// <param name="right">The amount to grow by on the right side.</param>
/// <param name="bottom">The amount to grow by on the bottom side.</param>
/// <returns>The grown <see cref="Rect2i"/>.</returns>
- public Rect2i GrowIndividual(int left, int top, int right, int bottom)
+ public readonly Rect2i GrowIndividual(int left, int top, int right, int bottom)
{
Rect2i g = this;
@@ -223,7 +223,7 @@ namespace Godot
/// <param name="side">The side to grow.</param>
/// <param name="by">The amount to grow by.</param>
/// <returns>The grown <see cref="Rect2i"/>.</returns>
- public Rect2i GrowSide(Side side, int by)
+ public readonly Rect2i GrowSide(Side side, int by)
{
Rect2i g = this;
@@ -244,7 +244,7 @@ namespace Godot
/// <returns>
/// A <see langword="bool"/> for whether or not the <see cref="Rect2i"/> has area.
/// </returns>
- public bool HasArea()
+ public readonly bool HasArea()
{
return _size.x > 0 && _size.y > 0;
}
@@ -257,7 +257,7 @@ namespace Godot
/// <returns>
/// A <see langword="bool"/> for whether or not the <see cref="Rect2i"/> contains <paramref name="point"/>.
/// </returns>
- public bool HasPoint(Vector2i point)
+ public readonly bool HasPoint(Vector2i point)
{
if (point.x < _position.x)
return false;
@@ -283,7 +283,7 @@ namespace Godot
/// <param name="b">The other <see cref="Rect2i"/> to check for intersections with.</param>
/// <param name="includeBorders">Whether or not to consider borders.</param>
/// <returns>A <see langword="bool"/> for whether or not they are intersecting.</returns>
- public bool Intersects(Rect2i b, bool includeBorders = false)
+ public readonly bool Intersects(Rect2i b, bool includeBorders = false)
{
if (includeBorders)
{
@@ -316,7 +316,7 @@ namespace Godot
/// </summary>
/// <param name="b">The other <see cref="Rect2i"/>.</param>
/// <returns>The merged <see cref="Rect2i"/>.</returns>
- public Rect2i Merge(Rect2i b)
+ public readonly Rect2i Merge(Rect2i b)
{
Rect2i newRect;
@@ -426,7 +426,7 @@ namespace Godot
/// </summary>
/// <param name="obj">The other object to compare.</param>
/// <returns>Whether or not the rect and the other object are equal.</returns>
- public override bool Equals(object obj)
+ public override readonly bool Equals(object obj)
{
return obj is Rect2i other && Equals(other);
}
@@ -436,7 +436,7 @@ namespace Godot
/// </summary>
/// <param name="other">The other rect to compare.</param>
/// <returns>Whether or not the rects are equal.</returns>
- public bool Equals(Rect2i other)
+ public readonly bool Equals(Rect2i other)
{
return _position.Equals(other._position) && _size.Equals(other._size);
}
@@ -445,7 +445,7 @@ namespace Godot
/// Serves as the hash function for <see cref="Rect2i"/>.
/// </summary>
/// <returns>A hash code for this rect.</returns>
- public override int GetHashCode()
+ public override readonly int GetHashCode()
{
return _position.GetHashCode() ^ _size.GetHashCode();
}
@@ -454,7 +454,7 @@ namespace Godot
/// Converts this <see cref="Rect2i"/> to a string.
/// </summary>
/// <returns>A string representation of this rect.</returns>
- public override string ToString()
+ public override readonly string ToString()
{
return $"{_position}, {_size}";
}
@@ -463,7 +463,7 @@ namespace Godot
/// Converts this <see cref="Rect2i"/> to a string with the given <paramref name="format"/>.
/// </summary>
/// <returns>A string representation of this rect.</returns>
- public string ToString(string format)
+ public readonly string ToString(string format)
{
return $"{_position.ToString(format)}, {_size.ToString(format)}";
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/SignalInfo.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Signal.cs
index 3f50df0a0d..f9b8f06603 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/SignalInfo.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Signal.cs
@@ -3,7 +3,7 @@ namespace Godot
/// <summary>
/// Represents a signal defined in an object.
/// </summary>
- public readonly struct SignalInfo
+ public readonly struct Signal : IAwaitable<Variant[]>
{
private readonly Object _owner;
private readonly StringName _signalName;
@@ -18,15 +18,20 @@ namespace Godot
public StringName Name => _signalName;
/// <summary>
- /// Creates a new <see cref="SignalInfo"/> with the name <paramref name="name"/>
+ /// Creates a new <see cref="Signal"/> with the name <paramref name="name"/>
/// in the specified <paramref name="owner"/>.
/// </summary>
/// <param name="owner">Object that contains the signal.</param>
/// <param name="name">Name of the signal.</param>
- public SignalInfo(Object owner, StringName name)
+ public Signal(Object owner, StringName name)
{
_owner = owner;
_signalName = name;
}
+
+ public IAwaiter<Variant[]> GetAwaiter()
+ {
+ return new SignalAwaiter(_owner, _signalName, _owner);
+ }
}
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs
index d77baab24b..d4329d78c1 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs
@@ -1,7 +1,9 @@
using System;
using System.Collections.Generic;
using System.Globalization;
+using System.IO;
using System.Security;
+using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using Godot.NativeInterop;
@@ -67,30 +69,13 @@ namespace Godot
}
/// <summary>
- /// If the string is a path to a file, return the path to the file without the extension.
- /// </summary>
- /// <seealso cref="GetExtension(string)"/>
- /// <seealso cref="GetBaseDir(string)"/>
- /// <seealso cref="GetFile(string)"/>
- /// <param name="instance">The path to a file.</param>
- /// <returns>The path to the file without the extension.</returns>
- public static string GetBaseName(this string instance)
- {
- int index = instance.LastIndexOf('.');
-
- if (index > 0)
- return instance.Substring(0, index);
-
- return instance;
- }
-
- /// <summary>
/// Returns <see langword="true"/> if the strings begins
/// with the given string <paramref name="text"/>.
/// </summary>
/// <param name="instance">The string to check.</param>
/// <param name="text">The beginning string.</param>
/// <returns>If the string begins with the given string.</returns>
+ [Obsolete("Use string.StartsWith instead.")]
public static bool BeginsWith(this string instance, string text)
{
return instance.StartsWith(text);
@@ -144,15 +129,15 @@ namespace Godot
}
/// <summary>
- /// Returns the amount of substrings <paramref name="what"/> in the string.
+ /// Returns the number of occurrences of substring <paramref name="what"/> in the string.
/// </summary>
/// <param name="instance">The string where the substring will be searched.</param>
/// <param name="what">The substring that will be counted.</param>
- /// <param name="caseSensitive">If the search is case sensitive.</param>
/// <param name="from">Index to start searching from.</param>
/// <param name="to">Index to stop searching at.</param>
- /// <returns>Amount of substrings in the string.</returns>
- public static int Count(this string instance, string what, bool caseSensitive = true, int from = 0, int to = 0)
+ /// <param name="caseSensitive">If the search is case sensitive.</param>
+ /// <returns>Number of occurrences of the substring in the string.</returns>
+ public static int Count(this string instance, string what, int from = 0, int to = 0, bool caseSensitive = true)
{
if (what.Length == 0)
{
@@ -211,6 +196,82 @@ namespace Godot
}
/// <summary>
+ /// Returns the number of occurrences of substring <paramref name="what"/> (ignoring case)
+ /// between <paramref name="from"/> and <paramref name="to"/> positions. If <paramref name="from"/>
+ /// and <paramref name="to"/> equals 0 the whole string will be used. If only <paramref name="to"/>
+ /// equals 0 the remained substring will be used.
+ /// </summary>
+ /// <param name="instance">The string where the substring will be searched.</param>
+ /// <param name="what">The substring that will be counted.</param>
+ /// <param name="from">Index to start searching from.</param>
+ /// <param name="to">Index to stop searching at.</param>
+ /// <returns>Number of occurrences of the substring in the string.</returns>
+ public static int CountN(this string instance, string what, int from = 0, int to = 0)
+ {
+ return instance.Count(what, from, to, caseSensitive: false);
+ }
+
+ /// <summary>
+ /// Returns a copy of the string with indentation (leading tabs and spaces) removed.
+ /// See also <see cref="Indent"/> to add indentation.
+ /// </summary>
+ /// <param name="instance">The string to remove the indentation from.</param>
+ /// <returns>The string with the indentation removed.</returns>
+ public static string Dedent(this string instance)
+ {
+ var sb = new StringBuilder();
+ string indent = "";
+ bool hasIndent = false;
+ bool hasText = false;
+ int lineStart = 0;
+ int indentStop = -1;
+
+ for (int i = 0; i < instance.Length; i++)
+ {
+ char c = instance[i];
+ if (c == '\n')
+ {
+ if (hasText)
+ {
+ sb.Append(instance.Substring(indentStop, i - indentStop));
+ }
+ sb.Append('\n');
+ hasText = false;
+ lineStart = i + 1;
+ indentStop = -1;
+ }
+ else if (!hasText)
+ {
+ if (c > 32)
+ {
+ hasText = true;
+ if (!hasIndent)
+ {
+ hasIndent = true;
+ indent = instance.Substring(lineStart, i - lineStart);
+ indentStop = i;
+ }
+ }
+ if (hasIndent && indentStop < 0)
+ {
+ int j = i - lineStart;
+ if (j >= indent.Length || c != indent[j])
+ {
+ indentStop = i;
+ }
+ }
+ }
+ }
+
+ if (hasText)
+ {
+ sb.Append(instance.Substring(indentStop, instance.Length - indentStop));
+ }
+
+ return sb.ToString();
+ }
+
+ /// <summary>
/// Returns a copy of the string with special characters escaped using the C language standard.
/// </summary>
/// <param name="instance">The string to escape.</param>
@@ -229,7 +290,6 @@ namespace Godot
sb.Replace("\v", "\\v");
sb.Replace("\'", "\\'");
sb.Replace("\"", "\\\"");
- sb.Replace("?", "\\?");
return sb.ToString();
}
@@ -253,7 +313,6 @@ namespace Godot
sb.Replace("\\v", "\v");
sb.Replace("\\'", "\'");
sb.Replace("\\\"", "\"");
- sb.Replace("\\?", "?");
sb.Replace("\\\\", "\\");
return sb.ToString();
@@ -445,29 +504,6 @@ namespace Godot
}
/// <summary>
- /// Returns <see langword="true"/> if the strings ends
- /// with the given string <paramref name="text"/>.
- /// </summary>
- /// <param name="instance">The string to check.</param>
- /// <param name="text">The ending string.</param>
- /// <returns>If the string ends with the given string.</returns>
- public static bool EndsWith(this string instance, string text)
- {
- return instance.EndsWith(text);
- }
-
- /// <summary>
- /// Erase <paramref name="chars"/> characters from the string starting from <paramref name="pos"/>.
- /// </summary>
- /// <param name="instance">The string to modify.</param>
- /// <param name="pos">Starting position from which to erase.</param>
- /// <param name="chars">Amount of characters to erase.</param>
- public static void Erase(this StringBuilder instance, int pos, int chars)
- {
- instance.Remove(pos, chars);
- }
-
- /// <summary>
/// Returns the extension without the leading period character (<c>.</c>)
/// if the string is a valid file name or path. If the string does not contain
/// an extension, returns an empty string instead.
@@ -491,7 +527,7 @@ namespace Godot
/// <returns>The extension of the file or an empty string.</returns>
public static string GetExtension(this string instance)
{
- int pos = instance.FindLast(".");
+ int pos = instance.RFind(".");
if (pos < 0)
return instance;
@@ -500,12 +536,16 @@ namespace Godot
}
/// <summary>
- /// Find the first occurrence of a substring. Optionally, the search starting position can be passed.
+ /// Returns the index of the first occurrence of the specified string in this instance,
+ /// or <c>-1</c>. Optionally, the starting search index can be specified, continuing
+ /// to the end of the string.
+ /// Note: If you just want to know whether a string contains a substring, use the
+ /// <see cref="string.Contains(string)"/> method.
/// </summary>
/// <seealso cref="Find(string, char, int, bool)"/>
- /// <seealso cref="FindLast(string, string, bool)"/>
- /// <seealso cref="FindLast(string, string, int, bool)"/>
/// <seealso cref="FindN(string, string, int)"/>
+ /// <seealso cref="RFind(string, string, int, bool)"/>
+ /// <seealso cref="RFindN(string, string, int)"/>
/// <param name="instance">The string that will be searched.</param>
/// <param name="what">The substring to find.</param>
/// <param name="from">The search starting position.</param>
@@ -521,9 +561,9 @@ namespace Godot
/// Find the first occurrence of a char. Optionally, the search starting position can be passed.
/// </summary>
/// <seealso cref="Find(string, string, int, bool)"/>
- /// <seealso cref="FindLast(string, string, bool)"/>
- /// <seealso cref="FindLast(string, string, int, bool)"/>
/// <seealso cref="FindN(string, string, int)"/>
+ /// <seealso cref="RFind(string, string, int, bool)"/>
+ /// <seealso cref="RFindN(string, string, int)"/>
/// <param name="instance">The string that will be searched.</param>
/// <param name="what">The substring to find.</param>
/// <param name="from">The search starting position.</param>
@@ -531,50 +571,21 @@ namespace Godot
/// <returns>The first instance of the char, or -1 if not found.</returns>
public static int Find(this string instance, char what, int from = 0, bool caseSensitive = true)
{
- // TODO: Could be more efficient if we get a char version of `IndexOf`.
- // See https://github.com/dotnet/runtime/issues/44116
- return instance.IndexOf(what.ToString(), from,
- caseSensitive ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase);
- }
+ if (caseSensitive)
+ return instance.IndexOf(what, from);
- /// <summary>Find the last occurrence of a substring.</summary>
- /// <seealso cref="Find(string, string, int, bool)"/>
- /// <seealso cref="Find(string, char, int, bool)"/>
- /// <seealso cref="FindLast(string, string, int, bool)"/>
- /// <seealso cref="FindN(string, string, int)"/>
- /// <param name="instance">The string that will be searched.</param>
- /// <param name="what">The substring to find.</param>
- /// <param name="caseSensitive">If <see langword="true"/>, the search is case sensitive.</param>
- /// <returns>The starting position of the substring, or -1 if not found.</returns>
- public static int FindLast(this string instance, string what, bool caseSensitive = true)
- {
- return instance.FindLast(what, instance.Length - 1, caseSensitive);
- }
-
- /// <summary>Find the last occurrence of a substring specifying the search starting position.</summary>
- /// <seealso cref="Find(string, string, int, bool)"/>
- /// <seealso cref="Find(string, char, int, bool)"/>
- /// <seealso cref="FindLast(string, string, bool)"/>
- /// <seealso cref="FindN(string, string, int)"/>
- /// <param name="instance">The string that will be searched.</param>
- /// <param name="what">The substring to find.</param>
- /// <param name="from">The search starting position.</param>
- /// <param name="caseSensitive">If <see langword="true"/>, the search is case sensitive.</param>
- /// <returns>The starting position of the substring, or -1 if not found.</returns>
- public static int FindLast(this string instance, string what, int from, bool caseSensitive = true)
- {
- return instance.LastIndexOf(what, from,
- caseSensitive ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase);
+ return CultureInfo.InvariantCulture.CompareInfo.IndexOf(instance, what, from, CompareOptions.OrdinalIgnoreCase);
}
/// <summary>
- /// Find the first occurrence of a substring but search as case-insensitive.
- /// Optionally, the search starting position can be passed.
+ /// Returns the index of the first case-insensitive occurrence of the specified string in this instance,
+ /// or <c>-1</c>. Optionally, the starting search index can be specified, continuing
+ /// to the end of the string.
/// </summary>
/// <seealso cref="Find(string, string, int, bool)"/>
/// <seealso cref="Find(string, char, int, bool)"/>
- /// <seealso cref="FindLast(string, string, bool)"/>
- /// <seealso cref="FindLast(string, string, int, bool)"/>
+ /// <seealso cref="RFind(string, string, int, bool)"/>
+ /// <seealso cref="RFindN(string, string, int)"/>
/// <param name="instance">The string that will be searched.</param>
/// <param name="what">The substring to find.</param>
/// <param name="from">The search starting position.</param>
@@ -618,7 +629,7 @@ namespace Godot
}
}
- int sep = Mathf.Max(rs.FindLast("/"), rs.FindLast("\\"));
+ int sep = Mathf.Max(rs.RFind("/"), rs.RFind("\\"));
if (sep == -1)
return directory;
@@ -627,6 +638,24 @@ namespace Godot
}
/// <summary>
+ /// If the string is a path to a file, return the path to the file without the extension.
+ /// </summary>
+ /// <seealso cref="GetExtension(string)"/>
+ /// <seealso cref="GetBaseDir(string)"/>
+ /// <seealso cref="GetFile(string)"/>
+ /// <param name="instance">The path to a file.</param>
+ /// <returns>The path to the file without the extension.</returns>
+ public static string GetBaseName(this string instance)
+ {
+ int index = instance.RFind(".");
+
+ if (index > 0)
+ return instance.Substring(0, index);
+
+ return instance;
+ }
+
+ /// <summary>
/// If the string is a path to a file, return the file and ignore the base directory.
/// </summary>
/// <seealso cref="GetBaseName(string)"/>
@@ -636,7 +665,7 @@ namespace Godot
/// <returns>The file name.</returns>
public static string GetFile(this string instance)
{
- int sep = Mathf.Max(instance.FindLast("/"), instance.FindLast("\\"));
+ int sep = Mathf.Max(instance.RFind("/"), instance.RFind("\\"));
if (sep == -1)
return instance;
@@ -645,8 +674,8 @@ namespace Godot
}
/// <summary>
- /// Converts the given byte array of ASCII encoded text to a string.
- /// Faster alternative to <see cref="GetStringFromUTF8"/> if the
+ /// Converts ASCII encoded array to string.
+ /// Fast alternative to <see cref="GetStringFromUTF8"/> if the
/// content is ASCII-only. Unlike the UTF-8 function this function
/// maps every byte to a character in the array. Multibyte sequences
/// will not be interpreted correctly. For parsing user input always
@@ -660,13 +689,35 @@ namespace Godot
}
/// <summary>
- /// Converts the given byte array of UTF-8 encoded text to a string.
+ /// Converts UTF-16 encoded array to string using the little endian byte order.
+ /// </summary>
+ /// <param name="bytes">A byte array of UTF-16 characters.</param>
+ /// <returns>A string created from the bytes.</returns>
+ public static string GetStringFromUTF16(this byte[] bytes)
+ {
+ return Encoding.Unicode.GetString(bytes);
+ }
+
+ /// <summary>
+ /// Converts UTF-32 encoded array to string using the little endian byte order.
+ /// </summary>
+ /// <param name="bytes">A byte array of UTF-32 characters.</param>
+ /// <returns>A string created from the bytes.</returns>
+ public static string GetStringFromUTF32(this byte[] bytes)
+ {
+ return Encoding.UTF32.GetString(bytes);
+ }
+
+ /// <summary>
+ /// Converts UTF-8 encoded array to string.
/// Slower than <see cref="GetStringFromASCII"/> but supports UTF-8
/// encoded data. Use this function if you are unsure about the
/// source of the data. For user input this function
/// should always be preferred.
/// </summary>
- /// <param name="bytes">A byte array of UTF-8 characters (a character may take up multiple bytes).</param>
+ /// <param name="bytes">
+ /// A byte array of UTF-8 characters (a character may take up multiple bytes).
+ /// </param>
/// <returns>A string created from the bytes.</returns>
public static string GetStringFromUTF8(this byte[] bytes)
{
@@ -768,18 +819,44 @@ namespace Godot
}
/// <summary>
- /// Inserts a substring at a given position.
+ /// Returns a copy of the string with lines indented with <paramref name="prefix"/>.
+ /// For example, the string can be indented with two tabs using <c>"\t\t"</c>,
+ /// or four spaces using <c>" "</c>. The prefix can be any string so it can
+ /// also be used to comment out strings with e.g. <c>"// </c>.
+ /// See also <see cref="Dedent"/> to remove indentation.
+ /// Note: Empty lines are kept empty.
/// </summary>
- /// <param name="instance">The string to modify.</param>
- /// <param name="pos">Position at which to insert the substring.</param>
- /// <param name="what">Substring to insert.</param>
- /// <returns>
- /// The string with <paramref name="what"/> inserted at the given
- /// position <paramref name="pos"/>.
- /// </returns>
- public static string Insert(this string instance, int pos, string what)
+ /// <param name="instance">The string to add indentation to.</param>
+ /// <param name="prefix">The string to use as indentation.</param>
+ /// <returns>The string with indentation added.</returns>
+ public static string Indent(this string instance, string prefix)
{
- return instance.Insert(pos, what);
+ var sb = new StringBuilder();
+ int lineStart = 0;
+
+ for (int i = 0; i < instance.Length; i++)
+ {
+ char c = instance[i];
+ if (c == '\n')
+ {
+ if (i == lineStart)
+ {
+ sb.Append(c); // Leave empty lines empty.
+ }
+ else
+ {
+ sb.Append(prefix);
+ sb.Append(instance.Substring(lineStart, i - lineStart + 1));
+ }
+ lineStart = i + 1;
+ }
+ }
+ if (lineStart != instance.Length)
+ {
+ sb.Append(prefix);
+ sb.Append(instance.Substring(lineStart));
+ }
+ return sb.ToString();
}
/// <summary>
@@ -875,19 +952,94 @@ namespace Godot
return instance.IsSubsequenceOf(text, caseSensitive: false);
}
+ private static readonly char[] _invalidFileNameCharacters = { ':', '/', '\\', '?', '*', '"', '|', '%', '<', '>' };
+
+ /// <summary>
+ /// Returns <see langword="true"/> if this string is free from characters that
+ /// aren't allowed in file names.
+ /// </summary>
+ /// <param name="instance">The string to check.</param>
+ /// <returns>If the string contains a valid file name.</returns>
+ public static bool IsValidFileName(this string instance)
+ {
+ var stripped = instance.Trim();
+ if (instance != stripped)
+ return false;
+
+ if (string.IsNullOrEmpty(stripped))
+ return false;
+
+ return instance.IndexOfAny(_invalidFileNameCharacters) == -1;
+ }
+
/// <summary>
- /// Check whether the string contains a valid <see langword="float"/>.
+ /// Returns <see langword="true"/> if this string contains a valid <see langword="float"/>.
+ /// This is inclusive of integers, and also supports exponents.
/// </summary>
+ /// <example>
+ /// <code>
+ /// GD.Print("1.7".IsValidFloat()) // Prints "True"
+ /// GD.Print("24".IsValidFloat()) // Prints "True"
+ /// GD.Print("7e3".IsValidFloat()) // Prints "True"
+ /// GD.Print("Hello".IsValidFloat()) // Prints "False"
+ /// </code>
+ /// </example>
/// <param name="instance">The string to check.</param>
/// <returns>If the string contains a valid floating point number.</returns>
public static bool IsValidFloat(this string instance)
{
- float f;
- return float.TryParse(instance, out f);
+ return float.TryParse(instance, out _);
+ }
+
+ /// <summary>
+ /// Returns <see langword="true"/> if this string contains a valid hexadecimal number.
+ /// If <paramref name="withPrefix"/> is <see langword="true"/>, then a validity of the
+ /// hexadecimal number is determined by <c>0x</c> prefix, for instance: <c>0xDEADC0DE</c>.
+ /// </summary>
+ /// <param name="instance">The string to check.</param>
+ /// <param name="withPrefix">If the string must contain the <c>0x</c> prefix to be valid.</param>
+ /// <returns>If the string contains a valid hexadecimal number.</returns>
+ public static bool IsValidHexNumber(this string instance, bool withPrefix = false)
+ {
+ if (string.IsNullOrEmpty(instance))
+ return false;
+
+ int from = 0;
+ if (instance.Length != 1 && instance[0] == '+' || instance[0] == '-')
+ {
+ from++;
+ }
+
+ if (withPrefix)
+ {
+ if (instance.Length < 3)
+ return false;
+ if (instance[from] != '0' || instance[from + 1] != 'x')
+ return false;
+ from += 2;
+ }
+
+ for (int i = from; i < instance.Length; i++)
+ {
+ char c = instance[i];
+ if (IsHexDigit(c))
+ continue;
+
+ return false;
+ }
+
+ return true;
+
+ static bool IsHexDigit(char c)
+ {
+ return char.IsDigit(c) || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F');
+ }
}
/// <summary>
- /// Check whether the string contains a valid color in HTML notation.
+ /// Returns <see langword="true"/> if this string contains a valid color in hexadecimal
+ /// HTML notation. Other HTML notations such as named colors or <c>hsl()</c> aren't
+ /// considered valid by this method and will return <see langword="false"/>.
/// </summary>
/// <param name="instance">The string to check.</param>
/// <returns>If the string contains a valid HTML color.</returns>
@@ -897,10 +1049,17 @@ namespace Godot
}
/// <summary>
- /// Check whether the string is a valid identifier. As is common in
- /// programming languages, a valid identifier may contain only letters,
- /// digits and underscores (_) and the first character may not be a digit.
+ /// Returns <see langword="true"/> if this string is a valid identifier.
+ /// A valid identifier may contain only letters, digits and underscores (<c>_</c>)
+ /// and the first character may not be a digit.
/// </summary>
+ /// <example>
+ /// <code>
+ /// GD.Print("good_ident_1".IsValidIdentifier()) // Prints "True"
+ /// GD.Print("1st_bad_ident".IsValidIdentifier()) // Prints "False"
+ /// GD.Print("bad_ident_#2".IsValidIdentifier()) // Prints "False"
+ /// </code>
+ /// </example>
/// <param name="instance">The string to check.</param>
/// <returns>If the string contains a valid identifier.</returns>
public static bool IsValidIdentifier(this string instance)
@@ -928,38 +1087,73 @@ namespace Godot
}
/// <summary>
- /// Check whether the string contains a valid integer.
+ /// Returns <see langword="true"/> if this string contains a valid <see langword="int"/>.
/// </summary>
+ /// <example>
+ /// <code>
+ /// GD.Print("7".IsValidInt()) // Prints "True"
+ /// GD.Print("14.6".IsValidInt()) // Prints "False"
+ /// GD.Print("L".IsValidInt()) // Prints "False"
+ /// GD.Print("+3".IsValidInt()) // Prints "True"
+ /// GD.Print("-12".IsValidInt()) // Prints "True"
+ /// </code>
+ /// </example>
/// <param name="instance">The string to check.</param>
/// <returns>If the string contains a valid integer.</returns>
- public static bool IsValidInteger(this string instance)
+ public static bool IsValidInt(this string instance)
{
- int f;
- return int.TryParse(instance, out f);
+ return int.TryParse(instance, out _);
}
/// <summary>
- /// Check whether the string contains a valid IP address.
+ /// Returns <see langword="true"/> if this string contains only a well-formatted
+ /// IPv4 or IPv6 address. This method considers reserved IP addresses such as
+ /// <c>0.0.0.0</c> as valid.
/// </summary>
/// <param name="instance">The string to check.</param>
/// <returns>If the string contains a valid IP address.</returns>
public static bool IsValidIPAddress(this string instance)
{
- // TODO: Support IPv6 addresses
- string[] ip = instance.Split(".");
+ if (instance.Contains(':'))
+ {
+ string[] ip = instance.Split(':');
- if (ip.Length != 4)
- return false;
+ for (int i = 0; i < ip.Length; i++)
+ {
+ string n = ip[i];
+ if (n.Length == 0)
+ continue;
+
+ if (n.IsValidHexNumber(withPrefix: false))
+ {
+ long nint = n.HexToInt();
+ if (nint < 0 || nint > 0xffff)
+ return false;
- for (int i = 0; i < ip.Length; i++)
+ continue;
+ }
+
+ if (!n.IsValidIPAddress())
+ return false;
+ }
+ }
+ else
{
- string n = ip[i];
- if (!n.IsValidInteger())
- return false;
+ string[] ip = instance.Split('.');
- int val = n.ToInt();
- if (val < 0 || val > 255)
+ if (ip.Length != 4)
return false;
+
+ for (int i = 0; i < ip.Length; i++)
+ {
+ string n = ip[i];
+ if (!n.IsValidInt())
+ return false;
+
+ int val = n.ToInt();
+ if (val < 0 || val > 255)
+ return false;
+ }
}
return true;
@@ -1005,41 +1199,20 @@ namespace Godot
}
/// <summary>
- /// Returns the length of the string in characters.
- /// </summary>
- /// <param name="instance">The string to check.</param>
- /// <returns>The length of the string.</returns>
- public static int Length(this string instance)
- {
- return instance.Length;
- }
-
- /// <summary>
/// Returns a copy of the string with characters removed from the left.
+ /// The <paramref name="chars"/> argument is a string specifying the set of characters
+ /// to be removed.
+ /// Note: The <paramref name="chars"/> is not a prefix. See <see cref="TrimPrefix"/>
+ /// method that will remove a single prefix string rather than a set of characters.
/// </summary>
/// <seealso cref="RStrip(string, string)"/>
/// <param name="instance">The string to remove characters from.</param>
/// <param name="chars">The characters to be removed.</param>
/// <returns>A copy of the string with characters removed from the left.</returns>
+ [Obsolete("Use string.TrimStart instead.")]
public static string LStrip(this string instance, string chars)
{
- int len = instance.Length;
- int beg;
-
- for (beg = 0; beg < len; beg++)
- {
- if (chars.Find(instance[beg]) == -1)
- {
- break;
- }
- }
-
- if (beg == 0)
- {
- return instance;
- }
-
- return instance.Substr(beg, len - beg);
+ return instance.TrimStart(chars.ToCharArray());
}
/// <summary>
@@ -1119,10 +1292,9 @@ namespace Godot
/// <returns>The MD5 hash of the string.</returns>
public static byte[] MD5Buffer(this string instance)
{
- using godot_string instanceStr = Marshaling.ConvertStringToNative(instance);
- NativeFuncs.godotsharp_string_md5_buffer(instanceStr, out var md5Buffer);
- using (md5Buffer)
- return Marshaling.ConvertNativePackedByteArrayToSystemArray(md5Buffer);
+#pragma warning disable CA5351 // Do Not Use Broken Cryptographic Algorithms
+ return MD5.HashData(Encoding.UTF8.GetBytes(instance));
+#pragma warning restore CA5351
}
/// <summary>
@@ -1133,10 +1305,7 @@ namespace Godot
/// <returns>The MD5 hash of the string.</returns>
public static string MD5Text(this string instance)
{
- using godot_string instanceStr = Marshaling.ConvertStringToNative(instance);
- NativeFuncs.godotsharp_string_md5_text(instanceStr, out var md5Text);
- using (md5Text)
- return Marshaling.ConvertStringToManaged(md5Text);
+ return instance.MD5Buffer().HexEncode();
}
/// <summary>
@@ -1153,17 +1322,6 @@ namespace Godot
}
/// <summary>
- /// Returns the character code at position <paramref name="at"/>.
- /// </summary>
- /// <param name="instance">The string to check.</param>
- /// <param name="at">The position int the string for the character to check.</param>
- /// <returns>The character code.</returns>
- public static int OrdAt(this string instance, int at)
- {
- return instance[at];
- }
-
- /// <summary>
/// Format a number to have an exact number of <paramref name="digits"/>
/// after the decimal point.
/// </summary>
@@ -1284,34 +1442,47 @@ namespace Godot
}
/// <summary>
- /// Perform a search for a substring, but start from the end of the string instead of the beginning.
+ /// Returns the index of the last occurrence of the specified string in this instance,
+ /// or <c>-1</c>. Optionally, the starting search index can be specified, continuing to
+ /// the beginning of the string.
/// </summary>
+ /// <seealso cref="Find(string, string, int, bool)"/>
+ /// <seealso cref="Find(string, char, int, bool)"/>
+ /// <seealso cref="FindN(string, string, int)"/>
/// <seealso cref="RFindN(string, string, int)"/>
/// <param name="instance">The string that will be searched.</param>
/// <param name="what">The substring to search in the string.</param>
/// <param name="from">The position at which to start searching.</param>
+ /// <param name="caseSensitive">If <see langword="true"/>, the search is case sensitive.</param>
/// <returns>The position at which the substring was found, or -1 if not found.</returns>
- public static int RFind(this string instance, string what, int from = -1)
+ public static int RFind(this string instance, string what, int from = -1, bool caseSensitive = true)
{
- using godot_string instanceStr = Marshaling.ConvertStringToNative(instance);
- using godot_string whatStr = Marshaling.ConvertStringToNative(instance);
- return NativeFuncs.godotsharp_string_rfind(instanceStr, whatStr, from);
+ if (from == -1)
+ from = instance.Length - 1;
+
+ return instance.LastIndexOf(what, from,
+ caseSensitive ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase);
}
/// <summary>
- /// Perform a search for a substring, but start from the end of the string instead of the beginning.
- /// Also search case-insensitive.
+ /// Returns the index of the last case-insensitive occurrence of the specified string in this instance,
+ /// or <c>-1</c>. Optionally, the starting search index can be specified, continuing to
+ /// the beginning of the string.
/// </summary>
- /// <seealso cref="RFind(string, string, int)"/>
+ /// <seealso cref="Find(string, string, int, bool)"/>
+ /// <seealso cref="Find(string, char, int, bool)"/>
+ /// <seealso cref="FindN(string, string, int)"/>
+ /// <seealso cref="RFind(string, string, int, bool)"/>
/// <param name="instance">The string that will be searched.</param>
/// <param name="what">The substring to search in the string.</param>
/// <param name="from">The position at which to start searching.</param>
/// <returns>The position at which the substring was found, or -1 if not found.</returns>
public static int RFindN(this string instance, string what, int from = -1)
{
- using godot_string instanceStr = Marshaling.ConvertStringToNative(instance);
- using godot_string whatStr = Marshaling.ConvertStringToNative(instance);
- return NativeFuncs.godotsharp_string_rfindn(instanceStr, whatStr, from);
+ if (from == -1)
+ from = instance.Length - 1;
+
+ return instance.LastIndexOf(what, from, StringComparison.OrdinalIgnoreCase);
}
/// <summary>
@@ -1334,30 +1505,43 @@ namespace Godot
/// <summary>
/// Returns a copy of the string with characters removed from the right.
+ /// The <paramref name="chars"/> argument is a string specifying the set of characters
+ /// to be removed.
+ /// Note: The <paramref name="chars"/> is not a suffix. See <see cref="TrimSuffix"/>
+ /// method that will remove a single suffix string rather than a set of characters.
/// </summary>
/// <seealso cref="LStrip(string, string)"/>
/// <param name="instance">The string to remove characters from.</param>
/// <param name="chars">The characters to be removed.</param>
/// <returns>A copy of the string with characters removed from the right.</returns>
+ [Obsolete("Use string.TrimEnd instead.")]
public static string RStrip(this string instance, string chars)
{
- int len = instance.Length;
- int end;
-
- for (end = len - 1; end >= 0; end--)
- {
- if (chars.Find(instance[end]) == -1)
- {
- break;
- }
- }
+ return instance.TrimEnd(chars.ToCharArray());
+ }
- if (end == len - 1)
- {
- return instance;
- }
+ /// <summary>
+ /// Returns the SHA-1 hash of the string as an array of bytes.
+ /// </summary>
+ /// <seealso cref="SHA1Text(string)"/>
+ /// <param name="instance">The string to hash.</param>
+ /// <returns>The SHA-1 hash of the string.</returns>
+ public static byte[] SHA1Buffer(this string instance)
+ {
+#pragma warning disable CA5350 // Do Not Use Weak Cryptographic Algorithms
+ return SHA1.HashData(Encoding.UTF8.GetBytes(instance));
+#pragma warning restore CA5350
+ }
- return instance.Substr(0, end + 1);
+ /// <summary>
+ /// Returns the SHA-1 hash of the string as a string.
+ /// </summary>
+ /// <seealso cref="SHA1Buffer(string)"/>
+ /// <param name="instance">The string to hash.</param>
+ /// <returns>The SHA-1 hash of the string.</returns>
+ public static string SHA1Text(this string instance)
+ {
+ return instance.SHA1Buffer().HexEncode();
}
/// <summary>
@@ -1368,10 +1552,7 @@ namespace Godot
/// <returns>The SHA-256 hash of the string.</returns>
public static byte[] SHA256Buffer(this string instance)
{
- using godot_string instanceStr = Marshaling.ConvertStringToNative(instance);
- NativeFuncs.godotsharp_string_sha256_buffer(instanceStr, out var sha256Buffer);
- using (sha256Buffer)
- return Marshaling.ConvertNativePackedByteArrayToSystemArray(sha256Buffer);
+ return SHA256.HashData(Encoding.UTF8.GetBytes(instance));
}
/// <summary>
@@ -1382,10 +1563,7 @@ namespace Godot
/// <returns>The SHA-256 hash of the string.</returns>
public static string SHA256Text(this string instance)
{
- using godot_string instanceStr = Marshaling.ConvertStringToNative(instance);
- NativeFuncs.godotsharp_string_sha256_text(instanceStr, out var sha256Text);
- using (sha256Text)
- return Marshaling.ConvertStringToManaged(sha256Text);
+ return instance.SHA256Buffer().HexEncode();
}
/// <summary>
@@ -1457,7 +1635,7 @@ namespace Godot
/// <returns>The array of strings split from the string.</returns>
public static string[] Split(this string instance, string divisor, bool allowEmpty = true)
{
- return instance.Split(new[] { divisor },
+ return instance.Split(divisor,
allowEmpty ? StringSplitOptions.None : StringSplitOptions.RemoveEmptyEntries);
}
@@ -1505,8 +1683,10 @@ namespace Godot
};
/// <summary>
- /// Returns a copy of the string stripped of any non-printable character at the beginning and the end.
- /// The optional arguments are used to toggle stripping on the left and right edges respectively.
+ /// Returns a copy of the string stripped of any non-printable character
+ /// (including tabulations, spaces and line breaks) at the beginning and the end.
+ /// The optional arguments are used to toggle stripping on the left and right
+ /// edges respectively.
/// </summary>
/// <param name="instance">The string to strip.</param>
/// <param name="left">If the left side should be stripped.</param>
@@ -1524,6 +1704,30 @@ namespace Godot
return instance.TrimEnd(_nonPrintable);
}
+
+ /// <summary>
+ /// Returns a copy of the string stripped of any escape character.
+ /// These include all non-printable control characters of the first page
+ /// of the ASCII table (&lt; 32), such as tabulation (<c>\t</c>) and
+ /// newline (<c>\n</c> and <c>\r</c>) characters, but not spaces.
+ /// </summary>
+ /// <param name="instance">The string to strip.</param>
+ /// <returns>The string stripped of any escape characters.</returns>
+ public static string StripEscapes(this string instance)
+ {
+ var sb = new StringBuilder();
+ for (int i = 0; i < instance.Length; i++)
+ {
+ // Escape characters on first page of the ASCII table, before 32 (Space).
+ if (instance[i] < 32)
+ continue;
+
+ sb.Append(instance[i]);
+ }
+
+ return sb.ToString();
+ }
+
/// <summary>
/// Returns part of the string from the position <paramref name="from"/>, with length <paramref name="len"/>.
/// </summary>
@@ -1541,13 +1745,15 @@ namespace Godot
/// <summary>
/// Converts the String (which is a character array) to PackedByteArray (which is an array of bytes).
- /// The conversion is speeded up in comparison to <see cref="ToUTF8(string)"/> with the assumption
- /// that all the characters the String contains are only ASCII characters.
+ /// The conversion is faster compared to <see cref="ToUTF8Buffer(string)"/>,
+ /// as this method assumes that all the characters in the String are ASCII characters.
/// </summary>
- /// <seealso cref="ToUTF8(string)"/>
+ /// <seealso cref="ToUTF8Buffer(string)"/>
+ /// <seealso cref="ToUTF16Buffer(string)"/>
+ /// <seealso cref="ToUTF32Buffer(string)"/>
/// <param name="instance">The string to convert.</param>
/// <returns>The string as ASCII encoded bytes.</returns>
- public static byte[] ToAscii(this string instance)
+ public static byte[] ToASCIIBuffer(this string instance)
{
return Encoding.ASCII.GetBytes(instance);
}
@@ -1575,41 +1781,76 @@ namespace Godot
}
/// <summary>
- /// Returns the string converted to lowercase.
+ /// Converts the string (which is an array of characters) to an UTF-16 encoded array of bytes.
/// </summary>
- /// <seealso cref="ToUpper(string)"/>
+ /// <seealso cref="ToASCIIBuffer(string)"/>
+ /// <seealso cref="ToUTF32Buffer(string)"/>
+ /// <seealso cref="ToUTF8Buffer(string)"/>
/// <param name="instance">The string to convert.</param>
- /// <returns>The string converted to lowercase.</returns>
- public static string ToLower(this string instance)
+ /// <returns>The string as UTF-16 encoded bytes.</returns>
+ public static byte[] ToUTF16Buffer(this string instance)
{
- return instance.ToLower();
+ return Encoding.Unicode.GetBytes(instance);
}
/// <summary>
- /// Returns the string converted to uppercase.
+ /// Converts the string (which is an array of characters) to an UTF-32 encoded array of bytes.
/// </summary>
- /// <seealso cref="ToLower(string)"/>
+ /// <seealso cref="ToASCIIBuffer(string)"/>
+ /// <seealso cref="ToUTF16Buffer(string)"/>
+ /// <seealso cref="ToUTF8Buffer(string)"/>
/// <param name="instance">The string to convert.</param>
- /// <returns>The string converted to uppercase.</returns>
- public static string ToUpper(this string instance)
+ /// <returns>The string as UTF-32 encoded bytes.</returns>
+ public static byte[] ToUTF32Buffer(this string instance)
{
- return instance.ToUpper();
+ return Encoding.UTF32.GetBytes(instance);
}
/// <summary>
- /// Converts the String (which is an array of characters) to PackedByteArray (which is an array of bytes).
- /// The conversion is a bit slower than <see cref="ToAscii(string)"/>, but supports all UTF-8 characters.
- /// Therefore, you should prefer this function over <see cref="ToAscii(string)"/>.
+ /// Converts the string (which is an array of characters) to an UTF-8 encoded array of bytes.
+ /// The conversion is a bit slower than <see cref="ToASCIIBuffer(string)"/>,
+ /// but supports all UTF-8 characters. Therefore, you should prefer this function
+ /// over <see cref="ToASCIIBuffer(string)"/>.
/// </summary>
- /// <seealso cref="ToAscii(string)"/>
+ /// <seealso cref="ToASCIIBuffer(string)"/>
+ /// <seealso cref="ToUTF16Buffer(string)"/>
+ /// <seealso cref="ToUTF32Buffer(string)"/>
/// <param name="instance">The string to convert.</param>
/// <returns>The string as UTF-8 encoded bytes.</returns>
- public static byte[] ToUTF8(this string instance)
+ public static byte[] ToUTF8Buffer(this string instance)
{
return Encoding.UTF8.GetBytes(instance);
}
/// <summary>
+ /// Removes a given string from the start if it starts with it or leaves the string unchanged.
+ /// </summary>
+ /// <param name="instance">The string to remove the prefix from.</param>
+ /// <param name="prefix">The string to remove from the start.</param>
+ /// <returns>A copy of the string with the prefix string removed from the start.</returns>
+ public static string TrimPrefix(this string instance, string prefix)
+ {
+ if (instance.StartsWith(prefix))
+ return instance.Substring(prefix.Length);
+
+ return instance;
+ }
+
+ /// <summary>
+ /// Removes a given string from the end if it ends with it or leaves the string unchanged.
+ /// </summary>
+ /// <param name="instance">The string to remove the suffix from.</param>
+ /// <param name="suffix">The string to remove from the end.</param>
+ /// <returns>A copy of the string with the suffix string removed from the end.</returns>
+ public static string TrimSuffix(this string instance, string suffix)
+ {
+ if (instance.EndsWith(suffix))
+ return instance.Substring(0, instance.Length - suffix.Length);
+
+ return instance;
+ }
+
+ /// <summary>
/// Decodes a string in URL encoded format. This is meant to
/// decode parameters in a URL when receiving an HTTP request.
/// This mostly wraps around <see cref="Uri.UnescapeDataString"/>,
@@ -1636,6 +1877,25 @@ namespace Godot
return Uri.EscapeDataString(instance);
}
+ private const string _uniqueNodePrefix = "%";
+ private static readonly string[] _invalidNodeNameCharacters = { ".", ":", "@", "/", "\"", _uniqueNodePrefix };
+
+ /// <summary>
+ /// Removes any characters from the string that are prohibited in
+ /// <see cref="Node"/> names (<c>.</c> <c>:</c> <c>@</c> <c>/</c> <c>"</c>).
+ /// </summary>
+ /// <param name="instance">The string to sanitize.</param>
+ /// <returns>The string sanitized as a valid node name.</returns>
+ public static string ValidateNodeName(this string instance)
+ {
+ string name = instance.Replace(_invalidNodeNameCharacters[0], "");
+ for (int i = 1; i < _invalidNodeNameCharacters.Length; i++)
+ {
+ name = name.Replace(_invalidNodeNameCharacters[i], "");
+ }
+ return name;
+ }
+
/// <summary>
/// Returns a copy of the string with special characters escaped using the XML standard.
/// </summary>
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs
index 894667db76..756f71e5b2 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs
@@ -37,7 +37,7 @@ namespace Godot
/// <value>Getting is equivalent to calling <see cref="Mathf.Atan2(real_t, real_t)"/> with the values of <see cref="x"/>.</value>
public real_t Rotation
{
- get
+ readonly get
{
return Mathf.Atan2(x.y, x.x);
}
@@ -57,7 +57,7 @@ namespace Godot
/// <value>Equivalent to the lengths of each column vector, but Y is negative if the determinant is negative.</value>
public Vector2 Scale
{
- get
+ readonly get
{
real_t detSign = Mathf.Sign(BasisDeterminant());
return new Vector2(x.Length(), detSign * y.Length());
@@ -80,7 +80,7 @@ namespace Godot
/// </exception>
public Vector2 this[int column]
{
- get
+ readonly get
{
switch (column)
{
@@ -121,7 +121,7 @@ namespace Godot
/// <param name="row">Which row, the matrix vertical position.</param>
public real_t this[int column, int row]
{
- get
+ readonly get
{
return this[column][row];
}
@@ -139,7 +139,7 @@ namespace Godot
/// </summary>
/// <seealso cref="Inverse"/>
/// <returns>The inverse transformation matrix.</returns>
- public Transform2D AffineInverse()
+ public readonly Transform2D AffineInverse()
{
real_t det = BasisDeterminant();
@@ -148,9 +148,8 @@ namespace Godot
Transform2D inv = this;
- real_t temp = inv[0, 0];
- inv[0, 0] = inv[1, 1];
- inv[1, 1] = temp;
+ inv[0, 0] = this[1, 1];
+ inv[1, 1] = this[0, 0];
real_t detInv = 1.0f / det;
@@ -171,7 +170,7 @@ namespace Godot
/// and is usually considered invalid.
/// </summary>
/// <returns>The determinant of the basis matrix.</returns>
- private real_t BasisDeterminant()
+ private readonly real_t BasisDeterminant()
{
return (x.x * y.y) - (x.y * y.x);
}
@@ -183,7 +182,7 @@ namespace Godot
/// <seealso cref="BasisXformInv(Vector2)"/>
/// <param name="v">A vector to transform.</param>
/// <returns>The transformed vector.</returns>
- public Vector2 BasisXform(Vector2 v)
+ public readonly Vector2 BasisXform(Vector2 v)
{
return new Vector2(Tdotx(v), Tdoty(v));
}
@@ -198,7 +197,7 @@ namespace Godot
/// <seealso cref="BasisXform(Vector2)"/>
/// <param name="v">A vector to inversely transform.</param>
/// <returns>The inversely transformed vector.</returns>
- public Vector2 BasisXformInv(Vector2 v)
+ public readonly Vector2 BasisXformInv(Vector2 v)
{
return new Vector2(x.Dot(v), y.Dot(v));
}
@@ -209,7 +208,7 @@ namespace Godot
/// <param name="transform">The other transform.</param>
/// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
/// <returns>The interpolated transform.</returns>
- public Transform2D InterpolateWith(Transform2D transform, real_t weight)
+ public readonly Transform2D InterpolateWith(Transform2D transform, real_t weight)
{
real_t r1 = Rotation;
real_t r2 = transform.Rotation;
@@ -258,14 +257,13 @@ namespace Godot
/// (no scaling, use <see cref="AffineInverse"/> for transforms with scaling).
/// </summary>
/// <returns>The inverse matrix.</returns>
- public Transform2D Inverse()
+ public readonly Transform2D Inverse()
{
Transform2D inv = this;
// Swap
- real_t temp = inv.x.y;
- inv.x.y = inv.y.x;
- inv.y.x = temp;
+ inv.x.y = y.x;
+ inv.y.x = x.y;
inv.origin = inv.BasisXform(-inv.origin);
@@ -277,7 +275,7 @@ namespace Godot
/// and normalized axis vectors (scale of 1 or -1).
/// </summary>
/// <returns>The orthonormalized transform.</returns>
- public Transform2D Orthonormalized()
+ public readonly Transform2D Orthonormalized()
{
Transform2D on = this;
@@ -301,7 +299,7 @@ namespace Godot
/// </summary>
/// <param name="angle">The angle to rotate, in radians.</param>
/// <returns>The rotated transformation matrix.</returns>
- public Transform2D Rotated(real_t angle)
+ public readonly Transform2D Rotated(real_t angle)
{
return this * new Transform2D(angle, new Vector2());
}
@@ -313,7 +311,7 @@ namespace Godot
/// </summary>
/// <param name="angle">The angle to rotate, in radians.</param>
/// <returns>The rotated transformation matrix.</returns>
- public Transform2D RotatedLocal(real_t angle)
+ public readonly Transform2D RotatedLocal(real_t angle)
{
return new Transform2D(angle, new Vector2()) * this;
}
@@ -325,7 +323,7 @@ namespace Godot
/// </summary>
/// <param name="scale">The scale to introduce.</param>
/// <returns>The scaled transformation matrix.</returns>
- public Transform2D Scaled(Vector2 scale)
+ public readonly Transform2D Scaled(Vector2 scale)
{
Transform2D copy = this;
copy.x *= scale;
@@ -341,7 +339,7 @@ namespace Godot
/// </summary>
/// <param name="scale">The scale to introduce.</param>
/// <returns>The scaled transformation matrix.</returns>
- public Transform2D ScaledLocal(Vector2 scale)
+ public readonly Transform2D ScaledLocal(Vector2 scale)
{
Transform2D copy = this;
copy.x *= scale;
@@ -349,12 +347,12 @@ namespace Godot
return copy;
}
- private real_t Tdotx(Vector2 with)
+ private readonly real_t Tdotx(Vector2 with)
{
return (this[0, 0] * with[0]) + (this[1, 0] * with[1]);
}
- private real_t Tdoty(Vector2 with)
+ private readonly real_t Tdoty(Vector2 with)
{
return (this[0, 1] * with[0]) + (this[1, 1] * with[1]);
}
@@ -366,7 +364,7 @@ namespace Godot
/// </summary>
/// <param name="offset">The offset to translate by.</param>
/// <returns>The translated matrix.</returns>
- public Transform2D Translated(Vector2 offset)
+ public readonly Transform2D Translated(Vector2 offset)
{
Transform2D copy = this;
copy.origin += offset;
@@ -380,7 +378,7 @@ namespace Godot
/// </summary>
/// <param name="offset">The offset to translate by.</param>
/// <returns>The translated matrix.</returns>
- public Transform2D TranslatedLocal(Vector2 offset)
+ public readonly Transform2D TranslatedLocal(Vector2 offset)
{
Transform2D copy = this;
copy.origin += copy.BasisXform(offset);
@@ -603,7 +601,7 @@ namespace Godot
/// </summary>
/// <param name="obj">The object to compare with.</param>
/// <returns>Whether or not the transform and the object are exactly equal.</returns>
- public override bool Equals(object obj)
+ public override readonly bool Equals(object obj)
{
return obj is Transform2D other && Equals(other);
}
@@ -615,7 +613,7 @@ namespace Godot
/// </summary>
/// <param name="other">The other transform to compare.</param>
/// <returns>Whether or not the matrices are exactly equal.</returns>
- public bool Equals(Transform2D other)
+ public readonly bool Equals(Transform2D other)
{
return x.Equals(other.x) && y.Equals(other.y) && origin.Equals(other.origin);
}
@@ -626,7 +624,7 @@ namespace Godot
/// </summary>
/// <param name="other">The other transform to compare.</param>
/// <returns>Whether or not the matrices are approximately equal.</returns>
- public bool IsEqualApprox(Transform2D other)
+ public readonly bool IsEqualApprox(Transform2D other)
{
return x.IsEqualApprox(other.x) && y.IsEqualApprox(other.y) && origin.IsEqualApprox(other.origin);
}
@@ -635,7 +633,7 @@ namespace Godot
/// Serves as the hash function for <see cref="Transform2D"/>.
/// </summary>
/// <returns>A hash code for this transform.</returns>
- public override int GetHashCode()
+ public override readonly int GetHashCode()
{
return x.GetHashCode() ^ y.GetHashCode() ^ origin.GetHashCode();
}
@@ -644,7 +642,7 @@ namespace Godot
/// Converts this <see cref="Transform2D"/> to a string.
/// </summary>
/// <returns>A string representation of this transform.</returns>
- public override string ToString()
+ public override readonly string ToString()
{
return $"[X: {x}, Y: {y}, O: {origin}]";
}
@@ -653,7 +651,7 @@ namespace Godot
/// Converts this <see cref="Transform2D"/> to a string with the given <paramref name="format"/>.
/// </summary>
/// <returns>A string representation of this transform.</returns>
- public string ToString(string format)
+ public readonly string ToString(string format)
{
return $"[X: {x.ToString(format)}, Y: {y.ToString(format)}, O: {origin.ToString(format)}]";
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs
index 2f7891e7ef..39167bd116 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs
@@ -37,7 +37,7 @@ namespace Godot
/// </exception>
public Vector3 this[int column]
{
- get
+ readonly get
{
switch (column)
{
@@ -83,7 +83,7 @@ namespace Godot
/// <param name="row">Which row, the matrix vertical position.</param>
public real_t this[int column, int row]
{
- get
+ readonly get
{
if (column == 3)
{
@@ -108,7 +108,7 @@ namespace Godot
/// </summary>
/// <seealso cref="Inverse"/>
/// <returns>The inverse transformation matrix.</returns>
- public Transform3D AffineInverse()
+ public readonly Transform3D AffineInverse()
{
Basis basisInv = basis.Inverse();
return new Transform3D(basisInv, basisInv * -origin);
@@ -120,7 +120,7 @@ namespace Godot
/// <param name="transform">The other transform.</param>
/// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
/// <returns>The interpolated transform.</returns>
- public Transform3D InterpolateWith(Transform3D transform, real_t weight)
+ public readonly Transform3D InterpolateWith(Transform3D transform, real_t weight)
{
Basis retBasis = basis.Lerp(transform.basis, weight);
Vector3 retOrigin = origin.Lerp(transform.origin, weight);
@@ -133,7 +133,7 @@ namespace Godot
/// (no scaling, use <see cref="AffineInverse"/> for transforms with scaling).
/// </summary>
/// <returns>The inverse matrix.</returns>
- public Transform3D Inverse()
+ public readonly Transform3D Inverse()
{
Basis basisTr = basis.Transposed();
return new Transform3D(basisTr, basisTr * -origin);
@@ -164,7 +164,7 @@ namespace Godot
/// and normalized axis vectors (scale of 1 or -1).
/// </summary>
/// <returns>The orthonormalized transform.</returns>
- public Transform3D Orthonormalized()
+ public readonly Transform3D Orthonormalized()
{
return new Transform3D(basis.Orthonormalized(), origin);
}
@@ -192,7 +192,7 @@ 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 transformation matrix.</returns>
- public Transform3D RotatedLocal(Vector3 axis, real_t angle)
+ public readonly Transform3D RotatedLocal(Vector3 axis, real_t angle)
{
Basis tmpBasis = new Basis(axis, angle);
return new Transform3D(basis * tmpBasis, origin);
@@ -205,7 +205,7 @@ namespace Godot
/// </summary>
/// <param name="scale">The scale to introduce.</param>
/// <returns>The scaled transformation matrix.</returns>
- public Transform3D Scaled(Vector3 scale)
+ public readonly Transform3D Scaled(Vector3 scale)
{
return new Transform3D(basis.Scaled(scale), origin * scale);
}
@@ -217,7 +217,7 @@ namespace Godot
/// </summary>
/// <param name="scale">The scale to introduce.</param>
/// <returns>The scaled transformation matrix.</returns>
- public Transform3D ScaledLocal(Vector3 scale)
+ public readonly Transform3D ScaledLocal(Vector3 scale)
{
Basis tmpBasis = Basis.FromScale(scale);
return new Transform3D(basis * tmpBasis, origin);
@@ -230,7 +230,7 @@ namespace Godot
/// <param name="transform">The other transform.</param>
/// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
/// <returns>The interpolated transform.</returns>
- public Transform3D SphericalInterpolateWith(Transform3D transform, real_t weight)
+ public readonly Transform3D SphericalInterpolateWith(Transform3D transform, real_t weight)
{
/* not sure if very "efficient" but good enough? */
@@ -281,7 +281,7 @@ namespace Godot
/// </summary>
/// <param name="offset">The offset to translate by.</param>
/// <returns>The translated matrix.</returns>
- public Transform3D Translated(Vector3 offset)
+ public readonly Transform3D Translated(Vector3 offset)
{
return new Transform3D(basis, origin + offset);
}
@@ -293,7 +293,7 @@ namespace Godot
/// </summary>
/// <param name="offset">The offset to translate by.</param>
/// <returns>The translated matrix.</returns>
- public Transform3D TranslatedLocal(Vector3 offset)
+ public readonly Transform3D TranslatedLocal(Vector3 offset)
{
return new Transform3D(basis, new Vector3
(
@@ -617,7 +617,7 @@ namespace Godot
/// </summary>
/// <param name="other">The other transform to compare.</param>
/// <returns>Whether or not the matrices are approximately equal.</returns>
- public bool IsEqualApprox(Transform3D other)
+ public readonly bool IsEqualApprox(Transform3D other)
{
return basis.IsEqualApprox(other.basis) && origin.IsEqualApprox(other.origin);
}
@@ -626,7 +626,7 @@ namespace Godot
/// Serves as the hash function for <see cref="Transform3D"/>.
/// </summary>
/// <returns>A hash code for this transform.</returns>
- public override int GetHashCode()
+ public override readonly int GetHashCode()
{
return basis.GetHashCode() ^ origin.GetHashCode();
}
@@ -635,7 +635,7 @@ namespace Godot
/// Converts this <see cref="Transform3D"/> to a string.
/// </summary>
/// <returns>A string representation of this transform.</returns>
- public override string ToString()
+ public override readonly string ToString()
{
return $"[X: {basis.x}, Y: {basis.y}, Z: {basis.z}, O: {origin}]";
}
@@ -644,7 +644,7 @@ namespace Godot
/// Converts this <see cref="Transform3D"/> to a string with the given <paramref name="format"/>.
/// </summary>
/// <returns>A string representation of this transform.</returns>
- public string ToString(string format)
+ public readonly string ToString(string format)
{
return $"[X: {basis.x.ToString(format)}, Y: {basis.y.ToString(format)}, Z: {basis.z.ToString(format)}, O: {origin.ToString(format)}]";
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Variant.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Variant.cs
index d354509dbf..da12309217 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Variant.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Variant.cs
@@ -109,16 +109,58 @@ public partial struct Variant : IDisposable
public override string ToString() => AsString();
- public object? Obj
- {
- get
+ public object? Obj =>
+ _obj ??= NativeVar.DangerousSelfRef.Type switch
{
- if (_obj == null)
- _obj = Marshaling.ConvertVariantToManagedObject((godot_variant)NativeVar);
-
- return _obj;
- }
- }
+ Type.Bool => AsBool(),
+ Type.Int => AsInt64(),
+ Type.Float => AsDouble(),
+ Type.String => AsString(),
+ Type.Vector2 => AsVector2(),
+ Type.Vector2i => AsVector2i(),
+ Type.Rect2 => AsRect2(),
+ Type.Rect2i => AsRect2i(),
+ Type.Vector3 => AsVector3(),
+ Type.Vector3i => AsVector3i(),
+ Type.Transform2d => AsTransform2D(),
+ Type.Vector4 => AsVector4(),
+ Type.Vector4i => AsVector4i(),
+ Type.Plane => AsPlane(),
+ Type.Quaternion => AsQuaternion(),
+ Type.Aabb => AsAABB(),
+ Type.Basis => AsBasis(),
+ Type.Transform3d => AsTransform3D(),
+ Type.Projection => AsProjection(),
+ Type.Color => AsColor(),
+ Type.StringName => AsStringName(),
+ Type.NodePath => AsNodePath(),
+ Type.Rid => AsRID(),
+ Type.Object => AsGodotObject(),
+ Type.Callable => AsCallable(),
+ Type.Signal => AsSignal(),
+ Type.Dictionary => AsGodotDictionary(),
+ Type.Array => AsGodotArray(),
+ Type.PackedByteArray => AsByteArray(),
+ Type.PackedInt32Array => AsInt32Array(),
+ Type.PackedInt64Array => AsInt64Array(),
+ Type.PackedFloat32Array => AsFloat32Array(),
+ Type.PackedFloat64Array => AsFloat64Array(),
+ Type.PackedStringArray => AsStringArray(),
+ Type.PackedVector2Array => AsVector2Array(),
+ Type.PackedVector3Array => AsVector3Array(),
+ Type.PackedColorArray => AsColorArray(),
+ Type.Nil => null,
+ Type.Max or _ =>
+ throw new InvalidOperationException($"Invalid Variant type: {NativeVar.DangerousSelfRef.Type}"),
+ };
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Variant From<[MustBeVariant] T>(in T from) =>
+ CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFrom(from));
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public T As<[MustBeVariant] T>() =>
+ VariantUtils.ConvertTo<T>(NativeVar.DangerousSelfRef);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool AsBool() =>
@@ -170,7 +212,7 @@ public partial struct Variant : IDisposable
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public string AsString() =>
- VariantUtils.ConvertToStringObject((godot_variant)NativeVar);
+ VariantUtils.ConvertToString((godot_variant)NativeVar);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Vector2 AsVector2() =>
@@ -238,11 +280,11 @@ public partial struct Variant : IDisposable
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Callable AsCallable() =>
- VariantUtils.ConvertToCallableManaged((godot_variant)NativeVar);
+ VariantUtils.ConvertToCallable((godot_variant)NativeVar);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public SignalInfo AsSignalInfo() =>
- VariantUtils.ConvertToSignalInfo((godot_variant)NativeVar);
+ public Signal AsSignal() =>
+ VariantUtils.ConvertToSignal((godot_variant)NativeVar);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public byte[] AsByteArray() =>
@@ -287,11 +329,11 @@ public partial struct Variant : IDisposable
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Collections.Dictionary<TKey, TValue> AsGodotDictionary<TKey, TValue>() =>
- VariantUtils.ConvertToDictionaryObject<TKey, TValue>((godot_variant)NativeVar);
+ VariantUtils.ConvertToDictionary<TKey, TValue>((godot_variant)NativeVar);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Collections.Array<T> AsGodotArray<T>() =>
- VariantUtils.ConvertToArrayObject<T>((godot_variant)NativeVar);
+ VariantUtils.ConvertToArray<T>((godot_variant)NativeVar);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public StringName[] AsSystemArrayOfStringName() =>
@@ -311,11 +353,11 @@ public partial struct Variant : IDisposable
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public StringName AsStringName() =>
- VariantUtils.ConvertToStringNameObject((godot_variant)NativeVar);
+ VariantUtils.ConvertToStringName((godot_variant)NativeVar);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public NodePath AsNodePath() =>
- VariantUtils.ConvertToNodePathObject((godot_variant)NativeVar);
+ VariantUtils.ConvertToNodePath((godot_variant)NativeVar);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public RID AsRID() =>
@@ -323,11 +365,11 @@ public partial struct Variant : IDisposable
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Collections.Dictionary AsGodotDictionary() =>
- VariantUtils.ConvertToDictionaryObject((godot_variant)NativeVar);
+ VariantUtils.ConvertToDictionary((godot_variant)NativeVar);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Collections.Array AsGodotArray() =>
- VariantUtils.ConvertToArrayObject((godot_variant)NativeVar);
+ VariantUtils.ConvertToArray((godot_variant)NativeVar);
// Explicit conversion operators to supported types
@@ -422,7 +464,7 @@ public partial struct Variant : IDisposable
public static explicit operator Callable(Variant from) => from.AsCallable();
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static explicit operator SignalInfo(Variant from) => from.AsSignalInfo();
+ public static explicit operator Signal(Variant from) => from.AsSignal();
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static explicit operator byte[](Variant from) => from.AsByteArray();
@@ -572,7 +614,7 @@ public partial struct Variant : IDisposable
public static Variant CreateFrom(Callable from) => from;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Variant CreateFrom(SignalInfo from) => from;
+ public static Variant CreateFrom(Signal from) => from;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Variant CreateFrom(Span<byte> from) => from;
@@ -762,8 +804,8 @@ public partial struct Variant : IDisposable
CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromCallable(from));
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static implicit operator Variant(SignalInfo from) =>
- CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromSignalInfo(from));
+ public static implicit operator Variant(Signal from) =>
+ CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromSignal(from));
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator Variant(byte[] from) =>
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs
index 87f397891e..4c60080ee9 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs
@@ -48,7 +48,7 @@ namespace Godot
/// </value>
public real_t this[int index]
{
- get
+ readonly get
{
switch (index)
{
@@ -79,7 +79,7 @@ namespace Godot
/// <summary>
/// Helper method for deconstruction into a tuple.
/// </summary>
- public void Deconstruct(out real_t x, out real_t y)
+ public readonly void Deconstruct(out real_t x, out real_t y)
{
x = this.x;
y = this.y;
@@ -105,7 +105,7 @@ namespace Godot
/// 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 Vector2 Abs()
+ public readonly Vector2 Abs()
{
return new Vector2(Mathf.Abs(x), Mathf.Abs(y));
}
@@ -117,7 +117,7 @@ namespace Godot
/// called with the vector's <see cref="y"/> and <see cref="x"/> as parameters: <c>Mathf.Atan2(v.y, v.x)</c>.
/// </summary>
/// <returns>The angle of this vector, in radians.</returns>
- public real_t Angle()
+ public readonly real_t Angle()
{
return Mathf.Atan2(y, x);
}
@@ -127,7 +127,7 @@ namespace Godot
/// </summary>
/// <param name="to">The other vector to compare this vector to.</param>
/// <returns>The angle between the two vectors, in radians.</returns>
- public real_t AngleTo(Vector2 to)
+ public readonly real_t AngleTo(Vector2 to)
{
return Mathf.Atan2(Cross(to), Dot(to));
}
@@ -137,16 +137,16 @@ namespace Godot
/// </summary>
/// <param name="to">The other vector to compare this vector to.</param>
/// <returns>The angle between the two vectors, in radians.</returns>
- public real_t AngleToPoint(Vector2 to)
+ public readonly real_t AngleToPoint(Vector2 to)
{
- return Mathf.Atan2(y - to.y, x - to.x);
+ return Mathf.Atan2(to.y - y, to.x - x);
}
/// <summary>
/// Returns the aspect ratio of this vector, the ratio of <see cref="x"/> to <see cref="y"/>.
/// </summary>
/// <returns>The <see cref="x"/> component divided by the <see cref="y"/> component.</returns>
- public real_t Aspect()
+ public readonly real_t Aspect()
{
return x / y;
}
@@ -156,7 +156,7 @@ namespace Godot
/// </summary>
/// <param name="normal">The normal vector defining the plane to bounce off. Must be normalized.</param>
/// <returns>The bounced vector.</returns>
- public Vector2 Bounce(Vector2 normal)
+ public readonly Vector2 Bounce(Vector2 normal)
{
return -Reflect(normal);
}
@@ -165,7 +165,7 @@ namespace Godot
/// 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 Vector2 Ceil()
+ public readonly Vector2 Ceil()
{
return new Vector2(Mathf.Ceil(x), Mathf.Ceil(y));
}
@@ -178,7 +178,7 @@ namespace Godot
/// <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 Vector2 Clamp(Vector2 min, Vector2 max)
+ public readonly Vector2 Clamp(Vector2 min, Vector2 max)
{
return new Vector2
(
@@ -192,7 +192,7 @@ namespace Godot
/// </summary>
/// <param name="with">The other vector.</param>
/// <returns>The cross product value.</returns>
- public real_t Cross(Vector2 with)
+ public readonly real_t Cross(Vector2 with)
{
return (x * with.y) - (y * with.x);
}
@@ -206,7 +206,7 @@ namespace Godot
/// <param name="postB">A vector after <paramref name="b"/>.</param>
/// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
/// <returns>The interpolated vector.</returns>
- public Vector2 CubicInterpolate(Vector2 b, Vector2 preA, Vector2 postB, real_t weight)
+ public readonly Vector2 CubicInterpolate(Vector2 b, Vector2 preA, Vector2 postB, real_t weight)
{
return new Vector2
(
@@ -229,7 +229,7 @@ namespace Godot
/// <param name="preAT"></param>
/// <param name="postBT"></param>
/// <returns>The interpolated vector.</returns>
- public Vector2 CubicInterpolateInTime(Vector2 b, Vector2 preA, Vector2 postB, real_t weight, real_t t, real_t preAT, real_t postBT)
+ public readonly Vector2 CubicInterpolateInTime(Vector2 b, Vector2 preA, Vector2 postB, real_t weight, real_t t, real_t preAT, real_t postBT)
{
return new Vector2
(
@@ -240,23 +240,37 @@ 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.
+ /// 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)
+ public readonly 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 new Vector2
+ (
+ Mathf.BezierInterpolate(x, control1.x, control2.x, end.x, t),
+ Mathf.BezierInterpolate(y, control1.y, control2.y, end.y, t)
+ );
+ }
- return this * omt3 + control1 * omt2 * t * 3 + control2 * omt * t2 * 3 + end * t3;
+ /// <summary>
+ /// Returns the derivative at the given <paramref name="t"/> on the 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 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 readonly Vector2 BezierDerivative(Vector2 control1, Vector2 control2, Vector2 end, real_t t)
+ {
+ return new Vector2(
+ Mathf.BezierDerivative(x, control1.x, control2.x, end.x, t),
+ Mathf.BezierDerivative(y, control1.y, control2.y, end.y, t)
+ );
}
/// <summary>
@@ -264,7 +278,7 @@ namespace Godot
/// </summary>
/// <param name="to">The other vector to point towards.</param>
/// <returns>The direction from this vector to <paramref name="to"/>.</returns>
- public Vector2 DirectionTo(Vector2 to)
+ public readonly Vector2 DirectionTo(Vector2 to)
{
return new Vector2(to.x - x, to.y - y).Normalized();
}
@@ -276,7 +290,7 @@ namespace Godot
/// </summary>
/// <param name="to">The other vector to use.</param>
/// <returns>The squared distance between the two vectors.</returns>
- public real_t DistanceSquaredTo(Vector2 to)
+ public readonly real_t DistanceSquaredTo(Vector2 to)
{
return (x - to.x) * (x - to.x) + (y - to.y) * (y - to.y);
}
@@ -286,7 +300,7 @@ namespace Godot
/// </summary>
/// <param name="to">The other vector to use.</param>
/// <returns>The distance between the two vectors.</returns>
- public real_t DistanceTo(Vector2 to)
+ public readonly real_t DistanceTo(Vector2 to)
{
return Mathf.Sqrt((x - to.x) * (x - to.x) + (y - to.y) * (y - to.y));
}
@@ -296,7 +310,7 @@ namespace Godot
/// </summary>
/// <param name="with">The other vector to use.</param>
/// <returns>The dot product of the two vectors.</returns>
- public real_t Dot(Vector2 with)
+ public readonly real_t Dot(Vector2 with)
{
return (x * with.x) + (y * with.y);
}
@@ -305,7 +319,7 @@ namespace Godot
/// 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 Vector2 Floor()
+ public readonly Vector2 Floor()
{
return new Vector2(Mathf.Floor(x), Mathf.Floor(y));
}
@@ -314,7 +328,7 @@ namespace Godot
/// Returns the inverse of this vector. This is the same as <c>new Vector2(1 / v.x, 1 / v.y)</c>.
/// </summary>
/// <returns>The inverse of this vector.</returns>
- public Vector2 Inverse()
+ public readonly Vector2 Inverse()
{
return new Vector2(1 / x, 1 / y);
}
@@ -323,7 +337,7 @@ namespace Godot
/// 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()
+ public readonly bool IsNormalized()
{
return Mathf.Abs(LengthSquared() - 1.0f) < Mathf.Epsilon;
}
@@ -333,7 +347,7 @@ namespace Godot
/// </summary>
/// <seealso cref="LengthSquared"/>
/// <returns>The length of this vector.</returns>
- public real_t Length()
+ public readonly real_t Length()
{
return Mathf.Sqrt((x * x) + (y * y));
}
@@ -344,7 +358,7 @@ namespace Godot
/// 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()
+ public readonly real_t LengthSquared()
{
return (x * x) + (y * y);
}
@@ -356,7 +370,7 @@ namespace Godot
/// <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 Vector2 Lerp(Vector2 to, real_t weight)
+ public readonly Vector2 Lerp(Vector2 to, real_t weight)
{
return new Vector2
(
@@ -374,7 +388,7 @@ namespace Godot
/// A vector with components on the range of 0.0 to 1.0, representing the amount of interpolation.
/// </param>
/// <returns>The resulting vector of the interpolation.</returns>
- public Vector2 Lerp(Vector2 to, Vector2 weight)
+ public readonly Vector2 Lerp(Vector2 to, Vector2 weight)
{
return new Vector2
(
@@ -388,7 +402,7 @@ namespace Godot
/// </summary>
/// <param name="length">The length to limit to.</param>
/// <returns>The vector with its length limited.</returns>
- public Vector2 LimitLength(real_t length = 1.0f)
+ public readonly Vector2 LimitLength(real_t length = 1.0f)
{
Vector2 v = this;
real_t l = Length();
@@ -407,7 +421,7 @@ namespace Godot
/// If both components are equal, this method returns <see cref="Axis.X"/>.
/// </summary>
/// <returns>The index of the highest axis.</returns>
- public Axis MaxAxisIndex()
+ public readonly Axis MaxAxisIndex()
{
return x < y ? Axis.Y : Axis.X;
}
@@ -417,7 +431,7 @@ namespace Godot
/// If both components are equal, this method returns <see cref="Axis.Y"/>.
/// </summary>
/// <returns>The index of the lowest axis.</returns>
- public Axis MinAxisIndex()
+ public readonly Axis MinAxisIndex()
{
return x < y ? Axis.X : Axis.Y;
}
@@ -428,7 +442,7 @@ namespace Godot
/// <param name="to">The vector to move towards.</param>
/// <param name="delta">The amount to move towards by.</param>
/// <returns>The resulting vector.</returns>
- public Vector2 MoveToward(Vector2 to, real_t delta)
+ public readonly Vector2 MoveToward(Vector2 to, real_t delta)
{
Vector2 v = this;
Vector2 vd = to - v;
@@ -443,7 +457,7 @@ namespace Godot
/// Returns the vector scaled to unit length. Equivalent to <c>v / v.Length()</c>.
/// </summary>
/// <returns>A normalized version of the vector.</returns>
- public Vector2 Normalized()
+ public readonly Vector2 Normalized()
{
Vector2 v = this;
v.Normalize();
@@ -458,7 +472,7 @@ namespace Godot
/// <returns>
/// A vector with each component <see cref="Mathf.PosMod(real_t, real_t)"/> by <paramref name="mod"/>.
/// </returns>
- public Vector2 PosMod(real_t mod)
+ public readonly Vector2 PosMod(real_t mod)
{
Vector2 v;
v.x = Mathf.PosMod(x, mod);
@@ -474,7 +488,7 @@ namespace Godot
/// <returns>
/// A vector with each component <see cref="Mathf.PosMod(real_t, real_t)"/> by <paramref name="modv"/>'s components.
/// </returns>
- public Vector2 PosMod(Vector2 modv)
+ public readonly Vector2 PosMod(Vector2 modv)
{
Vector2 v;
v.x = Mathf.PosMod(x, modv.x);
@@ -487,7 +501,7 @@ namespace Godot
/// </summary>
/// <param name="onNormal">The vector to project onto.</param>
/// <returns>The projected vector.</returns>
- public Vector2 Project(Vector2 onNormal)
+ public readonly Vector2 Project(Vector2 onNormal)
{
return onNormal * (Dot(onNormal) / onNormal.LengthSquared());
}
@@ -497,7 +511,7 @@ namespace Godot
/// </summary>
/// <param name="normal">The normal vector defining the plane to reflect from. Must be normalized.</param>
/// <returns>The reflected vector.</returns>
- public Vector2 Reflect(Vector2 normal)
+ public readonly Vector2 Reflect(Vector2 normal)
{
#if DEBUG
if (!normal.IsNormalized())
@@ -513,7 +527,7 @@ namespace Godot
/// </summary>
/// <param name="angle">The angle to rotate by, in radians.</param>
/// <returns>The rotated vector.</returns>
- public Vector2 Rotated(real_t angle)
+ public readonly Vector2 Rotated(real_t angle)
{
real_t sine = Mathf.Sin(angle);
real_t cosi = Mathf.Cos(angle);
@@ -527,7 +541,7 @@ namespace Godot
/// with halfway cases rounded towards the nearest multiple of two.
/// </summary>
/// <returns>The rounded vector.</returns>
- public Vector2 Round()
+ public readonly Vector2 Round()
{
return new Vector2(Mathf.Round(x), Mathf.Round(y));
}
@@ -538,7 +552,7 @@ namespace Godot
/// 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 Vector2 Sign()
+ public readonly Vector2 Sign()
{
Vector2 v;
v.x = Mathf.Sign(x);
@@ -557,7 +571,7 @@ namespace Godot
/// <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 Vector2 Slerp(Vector2 to, real_t weight)
+ public readonly Vector2 Slerp(Vector2 to, real_t weight)
{
real_t startLengthSquared = LengthSquared();
real_t endLengthSquared = to.LengthSquared();
@@ -577,7 +591,7 @@ namespace Godot
/// </summary>
/// <param name="normal">The normal vector defining the plane to slide on.</param>
/// <returns>The slid vector.</returns>
- public Vector2 Slide(Vector2 normal)
+ public readonly Vector2 Slide(Vector2 normal)
{
return this - (normal * Dot(normal));
}
@@ -588,7 +602,7 @@ namespace Godot
/// </summary>
/// <param name="step">A vector value representing the step size to snap to.</param>
/// <returns>The snapped vector.</returns>
- public Vector2 Snapped(Vector2 step)
+ public readonly Vector2 Snapped(Vector2 step)
{
return new Vector2(Mathf.Snapped(x, step.x), Mathf.Snapped(y, step.y));
}
@@ -598,7 +612,7 @@ namespace Godot
/// compared to the original, with the same length.
/// </summary>
/// <returns>The perpendicular vector.</returns>
- public Vector2 Orthogonal()
+ public readonly Vector2 Orthogonal()
{
return new Vector2(y, -x);
}
@@ -946,7 +960,7 @@ namespace Godot
/// </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)
+ public override readonly bool Equals(object obj)
{
return obj is Vector2 other && Equals(other);
}
@@ -958,7 +972,7 @@ namespace Godot
/// </summary>
/// <param name="other">The other vector.</param>
/// <returns>Whether or not the vectors are exactly equal.</returns>
- public bool Equals(Vector2 other)
+ public readonly bool Equals(Vector2 other)
{
return x == other.x && y == other.y;
}
@@ -969,7 +983,7 @@ namespace Godot
/// </summary>
/// <param name="other">The other vector to compare.</param>
/// <returns>Whether or not the vectors are approximately equal.</returns>
- public bool IsEqualApprox(Vector2 other)
+ public readonly bool IsEqualApprox(Vector2 other)
{
return Mathf.IsEqualApprox(x, other.x) && Mathf.IsEqualApprox(y, other.y);
}
@@ -978,7 +992,7 @@ namespace Godot
/// Serves as the hash function for <see cref="Vector2"/>.
/// </summary>
/// <returns>A hash code for this vector.</returns>
- public override int GetHashCode()
+ public override readonly int GetHashCode()
{
return y.GetHashCode() ^ x.GetHashCode();
}
@@ -987,7 +1001,7 @@ namespace Godot
/// Converts this <see cref="Vector2"/> to a string.
/// </summary>
/// <returns>A string representation of this vector.</returns>
- public override string ToString()
+ public override readonly string ToString()
{
return $"({x}, {y})";
}
@@ -996,7 +1010,7 @@ namespace Godot
/// Converts this <see cref="Vector2"/> to a string with the given <paramref name="format"/>.
/// </summary>
/// <returns>A string representation of this vector.</returns>
- public string ToString(string format)
+ public readonly string ToString(string format)
{
return $"({x.ToString(format)}, {y.ToString(format)})";
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs
index bdadf696e3..91be548a21 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs
@@ -48,7 +48,7 @@ namespace Godot
/// </value>
public int this[int index]
{
- get
+ readonly get
{
switch (index)
{
@@ -79,7 +79,7 @@ namespace Godot
/// <summary>
/// Helper method for deconstruction into a tuple.
/// </summary>
- public void Deconstruct(out int x, out int y)
+ public readonly void Deconstruct(out int x, out int y)
{
x = this.x;
y = this.y;
@@ -89,7 +89,7 @@ namespace Godot
/// 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 Vector2i Abs()
+ public readonly Vector2i Abs()
{
return new Vector2i(Mathf.Abs(x), Mathf.Abs(y));
}
@@ -101,7 +101,7 @@ namespace Godot
/// called with the vector's <see cref="y"/> and <see cref="x"/> as parameters: <c>Mathf.Atan2(v.y, v.x)</c>.
/// </summary>
/// <returns>The angle of this vector, in radians.</returns>
- public real_t Angle()
+ public readonly real_t Angle()
{
return Mathf.Atan2(y, x);
}
@@ -111,7 +111,7 @@ namespace Godot
/// </summary>
/// <param name="to">The other vector to compare this vector to.</param>
/// <returns>The angle between the two vectors, in radians.</returns>
- public real_t AngleTo(Vector2i to)
+ public readonly real_t AngleTo(Vector2i to)
{
return Mathf.Atan2(Cross(to), Dot(to));
}
@@ -121,16 +121,16 @@ namespace Godot
/// </summary>
/// <param name="to">The other vector to compare this vector to.</param>
/// <returns>The angle between the two vectors, in radians.</returns>
- public real_t AngleToPoint(Vector2i to)
+ public readonly real_t AngleToPoint(Vector2i to)
{
- return Mathf.Atan2(y - to.y, x - to.x);
+ return Mathf.Atan2(to.y - y, to.x - x);
}
/// <summary>
/// Returns the aspect ratio of this vector, the ratio of <see cref="x"/> to <see cref="y"/>.
/// </summary>
/// <returns>The <see cref="x"/> component divided by the <see cref="y"/> component.</returns>
- public real_t Aspect()
+ public readonly real_t Aspect()
{
return x / (real_t)y;
}
@@ -143,7 +143,7 @@ namespace Godot
/// <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 Vector2i Clamp(Vector2i min, Vector2i max)
+ public readonly Vector2i Clamp(Vector2i min, Vector2i max)
{
return new Vector2i
(
@@ -157,7 +157,7 @@ namespace Godot
/// </summary>
/// <param name="with">The other vector.</param>
/// <returns>The cross product vector.</returns>
- public int Cross(Vector2i with)
+ public readonly int Cross(Vector2i with)
{
return x * with.y - y * with.x;
}
@@ -169,7 +169,7 @@ namespace Godot
/// </summary>
/// <param name="to">The other vector to use.</param>
/// <returns>The squared distance between the two vectors.</returns>
- public int DistanceSquaredTo(Vector2i to)
+ public readonly int DistanceSquaredTo(Vector2i to)
{
return (to - this).LengthSquared();
}
@@ -179,7 +179,7 @@ namespace Godot
/// </summary>
/// <param name="to">The other vector to use.</param>
/// <returns>The distance between the two vectors.</returns>
- public real_t DistanceTo(Vector2i to)
+ public readonly real_t DistanceTo(Vector2i to)
{
return (to - this).Length();
}
@@ -189,7 +189,7 @@ namespace Godot
/// </summary>
/// <param name="with">The other vector to use.</param>
/// <returns>The dot product of the two vectors.</returns>
- public int Dot(Vector2i with)
+ public readonly int Dot(Vector2i with)
{
return x * with.x + y * with.y;
}
@@ -199,7 +199,7 @@ namespace Godot
/// </summary>
/// <seealso cref="LengthSquared"/>
/// <returns>The length of this vector.</returns>
- public real_t Length()
+ public readonly real_t Length()
{
int x2 = x * x;
int y2 = y * y;
@@ -213,7 +213,7 @@ namespace Godot
/// 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()
+ public readonly int LengthSquared()
{
int x2 = x * x;
int y2 = y * y;
@@ -226,7 +226,7 @@ namespace Godot
/// If both components are equal, this method returns <see cref="Axis.X"/>.
/// </summary>
/// <returns>The index of the highest axis.</returns>
- public Axis MaxAxisIndex()
+ public readonly Axis MaxAxisIndex()
{
return x < y ? Axis.Y : Axis.X;
}
@@ -236,7 +236,7 @@ namespace Godot
/// If both components are equal, this method returns <see cref="Axis.Y"/>.
/// </summary>
/// <returns>The index of the lowest axis.</returns>
- public Axis MinAxisIndex()
+ public readonly Axis MinAxisIndex()
{
return x < y ? Axis.X : Axis.Y;
}
@@ -249,7 +249,7 @@ namespace Godot
/// <returns>
/// A vector with each component <see cref="Mathf.PosMod(int, int)"/> by <paramref name="mod"/>.
/// </returns>
- public Vector2i PosMod(int mod)
+ public readonly Vector2i PosMod(int mod)
{
Vector2i v = this;
v.x = Mathf.PosMod(v.x, mod);
@@ -265,7 +265,7 @@ namespace Godot
/// <returns>
/// A vector with each component <see cref="Mathf.PosMod(int, int)"/> by <paramref name="modv"/>'s components.
/// </returns>
- public Vector2i PosMod(Vector2i modv)
+ public readonly Vector2i PosMod(Vector2i modv)
{
Vector2i v = this;
v.x = Mathf.PosMod(v.x, modv.x);
@@ -279,7 +279,7 @@ namespace Godot
/// 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 Vector2i Sign()
+ public readonly Vector2i Sign()
{
Vector2i v = this;
v.x = Mathf.Sign(v.x);
@@ -292,7 +292,7 @@ namespace Godot
/// compared to the original, with the same length.
/// </summary>
/// <returns>The perpendicular vector.</returns>
- public Vector2i Orthogonal()
+ public readonly Vector2i Orthogonal()
{
return new Vector2i(y, -x);
}
@@ -665,7 +665,7 @@ namespace Godot
/// </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)
+ public override readonly bool Equals(object obj)
{
return obj is Vector2i other && Equals(other);
}
@@ -675,7 +675,7 @@ namespace Godot
/// </summary>
/// <param name="other">The other vector.</param>
/// <returns>Whether or not the vectors are equal.</returns>
- public bool Equals(Vector2i other)
+ public readonly bool Equals(Vector2i other)
{
return x == other.x && y == other.y;
}
@@ -684,7 +684,7 @@ namespace Godot
/// Serves as the hash function for <see cref="Vector2i"/>.
/// </summary>
/// <returns>A hash code for this vector.</returns>
- public override int GetHashCode()
+ public override readonly int GetHashCode()
{
return y.GetHashCode() ^ x.GetHashCode();
}
@@ -693,7 +693,7 @@ namespace Godot
/// Converts this <see cref="Vector2i"/> to a string.
/// </summary>
/// <returns>A string representation of this vector.</returns>
- public override string ToString()
+ public override readonly string ToString()
{
return $"({x}, {y})";
}
@@ -702,7 +702,7 @@ namespace Godot
/// Converts this <see cref="Vector2i"/> to a string with the given <paramref name="format"/>.
/// </summary>
/// <returns>A string representation of this vector.</returns>
- public string ToString(string format)
+ public readonly string ToString(string format)
{
return $"({x.ToString(format)}, {y.ToString(format)})";
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs
index 6649f3b784..fefdee33a5 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs
@@ -58,7 +58,7 @@ namespace Godot
/// </value>
public real_t this[int index]
{
- get
+ readonly get
{
switch (index)
{
@@ -94,7 +94,7 @@ namespace Godot
/// <summary>
/// Helper method for deconstruction into a tuple.
/// </summary>
- public void Deconstruct(out real_t x, out real_t y, out real_t z)
+ public readonly void Deconstruct(out real_t x, out real_t y, out real_t z)
{
x = this.x;
y = this.y;
@@ -122,7 +122,7 @@ namespace Godot
/// 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 Vector3 Abs()
+ public readonly Vector3 Abs()
{
return new Vector3(Mathf.Abs(x), Mathf.Abs(y), Mathf.Abs(z));
}
@@ -132,7 +132,7 @@ namespace Godot
/// </summary>
/// <param name="to">The other vector to compare this vector to.</param>
/// <returns>The unsigned angle between the two vectors, in radians.</returns>
- public real_t AngleTo(Vector3 to)
+ public readonly real_t AngleTo(Vector3 to)
{
return Mathf.Atan2(Cross(to).Length(), Dot(to));
}
@@ -142,7 +142,7 @@ namespace Godot
/// </summary>
/// <param name="normal">The normal vector defining the plane to bounce off. Must be normalized.</param>
/// <returns>The bounced vector.</returns>
- public Vector3 Bounce(Vector3 normal)
+ public readonly Vector3 Bounce(Vector3 normal)
{
return -Reflect(normal);
}
@@ -151,7 +151,7 @@ namespace Godot
/// 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 Vector3 Ceil()
+ public readonly Vector3 Ceil()
{
return new Vector3(Mathf.Ceil(x), Mathf.Ceil(y), Mathf.Ceil(z));
}
@@ -164,7 +164,7 @@ namespace Godot
/// <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 Vector3 Clamp(Vector3 min, Vector3 max)
+ public readonly Vector3 Clamp(Vector3 min, Vector3 max)
{
return new Vector3
(
@@ -179,7 +179,7 @@ namespace Godot
/// </summary>
/// <param name="with">The other vector.</param>
/// <returns>The cross product vector.</returns>
- public Vector3 Cross(Vector3 with)
+ public readonly Vector3 Cross(Vector3 with)
{
return new Vector3
(
@@ -198,7 +198,7 @@ namespace Godot
/// <param name="postB">A vector after <paramref name="b"/>.</param>
/// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
/// <returns>The interpolated vector.</returns>
- public Vector3 CubicInterpolate(Vector3 b, Vector3 preA, Vector3 postB, real_t weight)
+ public readonly Vector3 CubicInterpolate(Vector3 b, Vector3 preA, Vector3 postB, real_t weight)
{
return new Vector3
(
@@ -222,7 +222,7 @@ namespace Godot
/// <param name="preAT"></param>
/// <param name="postBT"></param>
/// <returns>The interpolated vector.</returns>
- public Vector3 CubicInterpolateInTime(Vector3 b, Vector3 preA, Vector3 postB, real_t weight, real_t t, real_t preAT, real_t postBT)
+ public readonly Vector3 CubicInterpolateInTime(Vector3 b, Vector3 preA, Vector3 postB, real_t weight, real_t t, real_t preAT, real_t postBT)
{
return new Vector3
(
@@ -234,23 +234,39 @@ 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.
+ /// 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)
+ public readonly 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 new Vector3
+ (
+ Mathf.BezierInterpolate(x, control1.x, control2.x, end.x, t),
+ Mathf.BezierInterpolate(y, control1.y, control2.y, end.y, t),
+ Mathf.BezierInterpolate(z, control1.z, control2.z, end.z, t)
+ );
+ }
- return this * omt3 + control1 * omt2 * t * 3 + control2 * omt * t2 * 3 + end * t3;
+ /// <summary>
+ /// Returns the derivative at the given <paramref name="t"/> on the 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 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 readonly Vector3 BezierDerivative(Vector3 control1, Vector3 control2, Vector3 end, real_t t)
+ {
+ return new Vector3(
+ Mathf.BezierDerivative(x, control1.x, control2.x, end.x, t),
+ Mathf.BezierDerivative(y, control1.y, control2.y, end.y, t),
+ Mathf.BezierDerivative(z, control1.z, control2.z, end.y, t)
+ );
}
/// <summary>
@@ -258,7 +274,7 @@ namespace Godot
/// </summary>
/// <param name="to">The other vector to point towards.</param>
/// <returns>The direction from this vector to <paramref name="to"/>.</returns>
- public Vector3 DirectionTo(Vector3 to)
+ public readonly Vector3 DirectionTo(Vector3 to)
{
return new Vector3(to.x - x, to.y - y, to.z - z).Normalized();
}
@@ -270,7 +286,7 @@ namespace Godot
/// </summary>
/// <param name="to">The other vector to use.</param>
/// <returns>The squared distance between the two vectors.</returns>
- public real_t DistanceSquaredTo(Vector3 to)
+ public readonly real_t DistanceSquaredTo(Vector3 to)
{
return (to - this).LengthSquared();
}
@@ -281,7 +297,7 @@ namespace Godot
/// <seealso cref="DistanceSquaredTo(Vector3)"/>
/// <param name="to">The other vector to use.</param>
/// <returns>The distance between the two vectors.</returns>
- public real_t DistanceTo(Vector3 to)
+ public readonly real_t DistanceTo(Vector3 to)
{
return (to - this).Length();
}
@@ -291,7 +307,7 @@ namespace Godot
/// </summary>
/// <param name="with">The other vector to use.</param>
/// <returns>The dot product of the two vectors.</returns>
- public real_t Dot(Vector3 with)
+ public readonly real_t Dot(Vector3 with)
{
return (x * with.x) + (y * with.y) + (z * with.z);
}
@@ -300,7 +316,7 @@ namespace Godot
/// 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 Vector3 Floor()
+ public readonly Vector3 Floor()
{
return new Vector3(Mathf.Floor(x), Mathf.Floor(y), Mathf.Floor(z));
}
@@ -309,7 +325,7 @@ namespace Godot
/// Returns the inverse of this vector. This is the same as <c>new Vector3(1 / v.x, 1 / v.y, 1 / v.z)</c>.
/// </summary>
/// <returns>The inverse of this vector.</returns>
- public Vector3 Inverse()
+ public readonly Vector3 Inverse()
{
return new Vector3(1 / x, 1 / y, 1 / z);
}
@@ -318,7 +334,7 @@ namespace Godot
/// 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()
+ public readonly bool IsNormalized()
{
return Mathf.Abs(LengthSquared() - 1.0f) < Mathf.Epsilon;
}
@@ -328,7 +344,7 @@ namespace Godot
/// </summary>
/// <seealso cref="LengthSquared"/>
/// <returns>The length of this vector.</returns>
- public real_t Length()
+ public readonly real_t Length()
{
real_t x2 = x * x;
real_t y2 = y * y;
@@ -343,7 +359,7 @@ namespace Godot
/// 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()
+ public readonly real_t LengthSquared()
{
real_t x2 = x * x;
real_t y2 = y * y;
@@ -359,7 +375,7 @@ namespace Godot
/// <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 Vector3 Lerp(Vector3 to, real_t weight)
+ public readonly Vector3 Lerp(Vector3 to, real_t weight)
{
return new Vector3
(
@@ -376,7 +392,7 @@ namespace Godot
/// <param name="to">The destination vector for interpolation.</param>
/// <param name="weight">A vector with components on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
/// <returns>The resulting vector of the interpolation.</returns>
- public Vector3 Lerp(Vector3 to, Vector3 weight)
+ public readonly Vector3 Lerp(Vector3 to, Vector3 weight)
{
return new Vector3
(
@@ -391,7 +407,7 @@ namespace Godot
/// </summary>
/// <param name="length">The length to limit to.</param>
/// <returns>The vector with its length limited.</returns>
- public Vector3 LimitLength(real_t length = 1.0f)
+ public readonly Vector3 LimitLength(real_t length = 1.0f)
{
Vector3 v = this;
real_t l = Length();
@@ -410,7 +426,7 @@ namespace Godot
/// If all components are equal, this method returns <see cref="Axis.X"/>.
/// </summary>
/// <returns>The index of the highest axis.</returns>
- public Axis MaxAxisIndex()
+ public readonly Axis MaxAxisIndex()
{
return x < y ? (y < z ? Axis.Z : Axis.Y) : (x < z ? Axis.Z : Axis.X);
}
@@ -420,7 +436,7 @@ namespace Godot
/// If all components are equal, this method returns <see cref="Axis.Z"/>.
/// </summary>
/// <returns>The index of the lowest axis.</returns>
- public Axis MinAxisIndex()
+ public readonly Axis MinAxisIndex()
{
return x < y ? (x < z ? Axis.X : Axis.Z) : (y < z ? Axis.Y : Axis.Z);
}
@@ -431,7 +447,7 @@ namespace Godot
/// <param name="to">The vector to move towards.</param>
/// <param name="delta">The amount to move towards by.</param>
/// <returns>The resulting vector.</returns>
- public Vector3 MoveToward(Vector3 to, real_t delta)
+ public readonly Vector3 MoveToward(Vector3 to, real_t delta)
{
Vector3 v = this;
Vector3 vd = to - v;
@@ -446,7 +462,7 @@ namespace Godot
/// Returns the vector scaled to unit length. Equivalent to <c>v / v.Length()</c>.
/// </summary>
/// <returns>A normalized version of the vector.</returns>
- public Vector3 Normalized()
+ public readonly Vector3 Normalized()
{
Vector3 v = this;
v.Normalize();
@@ -458,7 +474,7 @@ namespace Godot
/// </summary>
/// <param name="with">The other vector.</param>
/// <returns>A <see cref="Basis"/> representing the outer product matrix.</returns>
- public Basis Outer(Vector3 with)
+ public readonly Basis Outer(Vector3 with)
{
return new Basis(
x * with.x, x * with.y, x * with.z,
@@ -475,7 +491,7 @@ namespace Godot
/// <returns>
/// A vector with each component <see cref="Mathf.PosMod(real_t, real_t)"/> by <paramref name="mod"/>.
/// </returns>
- public Vector3 PosMod(real_t mod)
+ public readonly Vector3 PosMod(real_t mod)
{
Vector3 v;
v.x = Mathf.PosMod(x, mod);
@@ -492,7 +508,7 @@ namespace Godot
/// <returns>
/// A vector with each component <see cref="Mathf.PosMod(real_t, real_t)"/> by <paramref name="modv"/>'s components.
/// </returns>
- public Vector3 PosMod(Vector3 modv)
+ public readonly Vector3 PosMod(Vector3 modv)
{
Vector3 v;
v.x = Mathf.PosMod(x, modv.x);
@@ -506,7 +522,7 @@ namespace Godot
/// </summary>
/// <param name="onNormal">The vector to project onto.</param>
/// <returns>The projected vector.</returns>
- public Vector3 Project(Vector3 onNormal)
+ public readonly Vector3 Project(Vector3 onNormal)
{
return onNormal * (Dot(onNormal) / onNormal.LengthSquared());
}
@@ -516,7 +532,7 @@ namespace Godot
/// </summary>
/// <param name="normal">The normal vector defining the plane to reflect from. Must be normalized.</param>
/// <returns>The reflected vector.</returns>
- public Vector3 Reflect(Vector3 normal)
+ public readonly Vector3 Reflect(Vector3 normal)
{
#if DEBUG
if (!normal.IsNormalized())
@@ -534,7 +550,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 angle)
+ public readonly Vector3 Rotated(Vector3 axis, real_t angle)
{
#if DEBUG
if (!axis.IsNormalized())
@@ -550,7 +566,7 @@ namespace Godot
/// with halfway cases rounded towards the nearest multiple of two.
/// </summary>
/// <returns>The rounded vector.</returns>
- public Vector3 Round()
+ public readonly Vector3 Round()
{
return new Vector3(Mathf.Round(x), Mathf.Round(y), Mathf.Round(z));
}
@@ -561,7 +577,7 @@ namespace Godot
/// 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 Vector3 Sign()
+ public readonly Vector3 Sign()
{
Vector3 v;
v.x = Mathf.Sign(x);
@@ -579,7 +595,7 @@ namespace Godot
/// <param name="to">The other vector to compare this vector to.</param>
/// <param name="axis">The reference axis to use for the angle sign.</param>
/// <returns>The signed angle between the two vectors, in radians.</returns>
- public real_t SignedAngleTo(Vector3 to, Vector3 axis)
+ public readonly real_t SignedAngleTo(Vector3 to, Vector3 axis)
{
Vector3 crossTo = Cross(to);
real_t unsignedAngle = Mathf.Atan2(crossTo.Length(), Dot(to));
@@ -598,7 +614,7 @@ namespace Godot
/// <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 Vector3 Slerp(Vector3 to, real_t weight)
+ public readonly Vector3 Slerp(Vector3 to, real_t weight)
{
real_t startLengthSquared = LengthSquared();
real_t endLengthSquared = to.LengthSquared();
@@ -618,7 +634,7 @@ namespace Godot
/// </summary>
/// <param name="normal">The normal vector defining the plane to slide on.</param>
/// <returns>The slid vector.</returns>
- public Vector3 Slide(Vector3 normal)
+ public readonly Vector3 Slide(Vector3 normal)
{
return this - (normal * Dot(normal));
}
@@ -629,7 +645,7 @@ namespace Godot
/// </summary>
/// <param name="step">A vector value representing the step size to snap to.</param>
/// <returns>The snapped vector.</returns>
- public Vector3 Snapped(Vector3 step)
+ public readonly Vector3 Snapped(Vector3 step)
{
return new Vector3
(
@@ -1015,7 +1031,7 @@ namespace Godot
/// </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)
+ public override readonly bool Equals(object obj)
{
return obj is Vector3 other && Equals(other);
}
@@ -1027,7 +1043,7 @@ namespace Godot
/// </summary>
/// <param name="other">The other vector.</param>
/// <returns>Whether or not the vectors are exactly equal.</returns>
- public bool Equals(Vector3 other)
+ public readonly bool Equals(Vector3 other)
{
return x == other.x && y == other.y && z == other.z;
}
@@ -1038,7 +1054,7 @@ namespace Godot
/// </summary>
/// <param name="other">The other vector to compare.</param>
/// <returns>Whether or not the vectors are approximately equal.</returns>
- public bool IsEqualApprox(Vector3 other)
+ public readonly bool IsEqualApprox(Vector3 other)
{
return Mathf.IsEqualApprox(x, other.x) && Mathf.IsEqualApprox(y, other.y) && Mathf.IsEqualApprox(z, other.z);
}
@@ -1047,7 +1063,7 @@ namespace Godot
/// Serves as the hash function for <see cref="Vector3"/>.
/// </summary>
/// <returns>A hash code for this vector.</returns>
- public override int GetHashCode()
+ public override readonly int GetHashCode()
{
return y.GetHashCode() ^ x.GetHashCode() ^ z.GetHashCode();
}
@@ -1056,7 +1072,7 @@ namespace Godot
/// Converts this <see cref="Vector3"/> to a string.
/// </summary>
/// <returns>A string representation of this vector.</returns>
- public override string ToString()
+ public override readonly string ToString()
{
return $"({x}, {y}, {z})";
}
@@ -1065,7 +1081,7 @@ namespace Godot
/// Converts this <see cref="Vector3"/> to a string with the given <paramref name="format"/>.
/// </summary>
/// <returns>A string representation of this vector.</returns>
- public string ToString(string format)
+ public readonly string ToString(string format)
{
return $"({x.ToString(format)}, {y.ToString(format)}, {z.ToString(format)})";
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs
index e88a043cb3..e631a9f443 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs
@@ -58,7 +58,7 @@ namespace Godot
/// </value>
public int this[int index]
{
- get
+ readonly get
{
switch (index)
{
@@ -94,7 +94,7 @@ namespace Godot
/// <summary>
/// Helper method for deconstruction into a tuple.
/// </summary>
- public void Deconstruct(out int x, out int y, out int z)
+ public readonly void Deconstruct(out int x, out int y, out int z)
{
x = this.x;
y = this.y;
@@ -105,7 +105,7 @@ namespace Godot
/// 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 Vector3i Abs()
+ public readonly Vector3i Abs()
{
return new Vector3i(Mathf.Abs(x), Mathf.Abs(y), Mathf.Abs(z));
}
@@ -118,7 +118,7 @@ namespace Godot
/// <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 Vector3i Clamp(Vector3i min, Vector3i max)
+ public readonly Vector3i Clamp(Vector3i min, Vector3i max)
{
return new Vector3i
(
@@ -135,7 +135,7 @@ namespace Godot
/// </summary>
/// <param name="to">The other vector to use.</param>
/// <returns>The squared distance between the two vectors.</returns>
- public int DistanceSquaredTo(Vector3i to)
+ public readonly int DistanceSquaredTo(Vector3i to)
{
return (to - this).LengthSquared();
}
@@ -146,7 +146,7 @@ namespace Godot
/// <seealso cref="DistanceSquaredTo(Vector3i)"/>
/// <param name="to">The other vector to use.</param>
/// <returns>The distance between the two vectors.</returns>
- public real_t DistanceTo(Vector3i to)
+ public readonly real_t DistanceTo(Vector3i to)
{
return (to - this).Length();
}
@@ -156,7 +156,7 @@ namespace Godot
/// </summary>
/// <param name="with">The other vector to use.</param>
/// <returns>The dot product of the two vectors.</returns>
- public int Dot(Vector3i with)
+ public readonly int Dot(Vector3i with)
{
return x * with.x + y * with.y + z * with.z;
}
@@ -166,7 +166,7 @@ namespace Godot
/// </summary>
/// <seealso cref="LengthSquared"/>
/// <returns>The length of this vector.</returns>
- public real_t Length()
+ public readonly real_t Length()
{
int x2 = x * x;
int y2 = y * y;
@@ -181,7 +181,7 @@ namespace Godot
/// 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()
+ public readonly int LengthSquared()
{
int x2 = x * x;
int y2 = y * y;
@@ -195,7 +195,7 @@ namespace Godot
/// If all components are equal, this method returns <see cref="Axis.X"/>.
/// </summary>
/// <returns>The index of the highest axis.</returns>
- public Axis MaxAxisIndex()
+ public readonly Axis MaxAxisIndex()
{
return x < y ? (y < z ? Axis.Z : Axis.Y) : (x < z ? Axis.Z : Axis.X);
}
@@ -205,7 +205,7 @@ namespace Godot
/// If all components are equal, this method returns <see cref="Axis.Z"/>.
/// </summary>
/// <returns>The index of the lowest axis.</returns>
- public Axis MinAxisIndex()
+ public readonly Axis MinAxisIndex()
{
return x < y ? (x < z ? Axis.X : Axis.Z) : (y < z ? Axis.Y : Axis.Z);
}
@@ -218,7 +218,7 @@ namespace Godot
/// <returns>
/// A vector with each component <see cref="Mathf.PosMod(int, int)"/> by <paramref name="mod"/>.
/// </returns>
- public Vector3i PosMod(int mod)
+ public readonly Vector3i PosMod(int mod)
{
Vector3i v = this;
v.x = Mathf.PosMod(v.x, mod);
@@ -235,7 +235,7 @@ namespace Godot
/// <returns>
/// A vector with each component <see cref="Mathf.PosMod(int, int)"/> by <paramref name="modv"/>'s components.
/// </returns>
- public Vector3i PosMod(Vector3i modv)
+ public readonly Vector3i PosMod(Vector3i modv)
{
Vector3i v = this;
v.x = Mathf.PosMod(v.x, modv.x);
@@ -250,7 +250,7 @@ namespace Godot
/// 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 Vector3i Sign()
+ public readonly Vector3i Sign()
{
Vector3i v = this;
v.x = Mathf.Sign(v.x);
@@ -674,7 +674,7 @@ namespace Godot
/// </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)
+ public override readonly bool Equals(object obj)
{
return obj is Vector3i other && Equals(other);
}
@@ -684,7 +684,7 @@ namespace Godot
/// </summary>
/// <param name="other">The other vector.</param>
/// <returns>Whether or not the vectors are equal.</returns>
- public bool Equals(Vector3i other)
+ public readonly bool Equals(Vector3i other)
{
return x == other.x && y == other.y && z == other.z;
}
@@ -693,7 +693,7 @@ namespace Godot
/// Serves as the hash function for <see cref="Vector3i"/>.
/// </summary>
/// <returns>A hash code for this vector.</returns>
- public override int GetHashCode()
+ public override readonly int GetHashCode()
{
return y.GetHashCode() ^ x.GetHashCode() ^ z.GetHashCode();
}
@@ -702,7 +702,7 @@ namespace Godot
/// Converts this <see cref="Vector3i"/> to a string.
/// </summary>
/// <returns>A string representation of this vector.</returns>
- public override string ToString()
+ public override readonly string ToString()
{
return $"({x}, {y}, {z})";
}
@@ -711,7 +711,7 @@ namespace Godot
/// Converts this <see cref="Vector3i"/> to a string with the given <paramref name="format"/>.
/// </summary>
/// <returns>A string representation of this vector.</returns>
- public string ToString(string format)
+ public readonly string ToString(string format)
{
return $"({x.ToString(format)}, {y.ToString(format)}, {z.ToString(format)})";
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4.cs
index e2da41ff47..3191e8adc0 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4.cs
@@ -68,7 +68,7 @@ namespace Godot
/// </value>
public real_t this[int index]
{
- get
+ readonly get
{
switch (index)
{
@@ -109,7 +109,7 @@ namespace Godot
/// <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)
+ public readonly void Deconstruct(out real_t x, out real_t y, out real_t z, out real_t w)
{
x = this.x;
y = this.y;
@@ -139,7 +139,7 @@ namespace Godot
/// 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()
+ public readonly Vector4 Abs()
{
return new Vector4(Mathf.Abs(x), Mathf.Abs(y), Mathf.Abs(z), Mathf.Abs(w));
}
@@ -148,7 +148,7 @@ namespace Godot
/// 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()
+ public readonly Vector4 Ceil()
{
return new Vector4(Mathf.Ceil(x), Mathf.Ceil(y), Mathf.Ceil(z), Mathf.Ceil(w));
}
@@ -161,7 +161,7 @@ namespace Godot
/// <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)
+ public readonly Vector4 Clamp(Vector4 min, Vector4 max)
{
return new Vector4
(
@@ -181,7 +181,7 @@ namespace Godot
/// <param name="postB">A vector after <paramref name="b"/>.</param>
/// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
/// <returns>The interpolated vector.</returns>
- public Vector4 CubicInterpolate(Vector4 b, Vector4 preA, Vector4 postB, real_t weight)
+ public readonly Vector4 CubicInterpolate(Vector4 b, Vector4 preA, Vector4 postB, real_t weight)
{
return new Vector4
(
@@ -206,7 +206,7 @@ namespace Godot
/// <param name="preAT"></param>
/// <param name="postBT"></param>
/// <returns>The interpolated vector.</returns>
- public Vector4 CubicInterpolateInTime(Vector4 b, Vector4 preA, Vector4 postB, real_t weight, real_t t, real_t preAT, real_t postBT)
+ public readonly Vector4 CubicInterpolateInTime(Vector4 b, Vector4 preA, Vector4 postB, real_t weight, real_t t, real_t preAT, real_t postBT)
{
return new Vector4
(
@@ -222,7 +222,7 @@ namespace Godot
/// </summary>
/// <param name="to">The other vector to point towards.</param>
/// <returns>The direction from this vector to <paramref name="to"/>.</returns>
- public Vector4 DirectionTo(Vector4 to)
+ public readonly Vector4 DirectionTo(Vector4 to)
{
Vector4 ret = new Vector4(to.x - x, to.y - y, to.z - z, to.w - w);
ret.Normalize();
@@ -236,7 +236,7 @@ namespace Godot
/// </summary>
/// <param name="to">The other vector to use.</param>
/// <returns>The squared distance between the two vectors.</returns>
- public real_t DistanceSquaredTo(Vector4 to)
+ public readonly real_t DistanceSquaredTo(Vector4 to)
{
return (to - this).LengthSquared();
}
@@ -246,7 +246,7 @@ namespace Godot
/// </summary>
/// <param name="to">The other vector to use.</param>
/// <returns>The distance between the two vectors.</returns>
- public real_t DistanceTo(Vector4 to)
+ public readonly real_t DistanceTo(Vector4 to)
{
return (to - this).Length();
}
@@ -256,7 +256,7 @@ namespace Godot
/// </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)
+ public readonly real_t Dot(Vector4 with)
{
return (x * with.x) + (y * with.y) + (z * with.z) + (w * with.w);
}
@@ -265,7 +265,7 @@ namespace Godot
/// 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()
+ public readonly Vector4 Floor()
{
return new Vector4(Mathf.Floor(x), Mathf.Floor(y), Mathf.Floor(z), Mathf.Floor(w));
}
@@ -274,7 +274,7 @@ namespace Godot
/// 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()
+ public readonly Vector4 Inverse()
{
return new Vector4(1 / x, 1 / y, 1 / z, 1 / w);
}
@@ -283,7 +283,7 @@ namespace Godot
/// 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()
+ public readonly bool IsNormalized()
{
return Mathf.Abs(LengthSquared() - 1.0f) < Mathf.Epsilon;
}
@@ -293,7 +293,7 @@ namespace Godot
/// </summary>
/// <seealso cref="LengthSquared"/>
/// <returns>The length of this vector.</returns>
- public real_t Length()
+ public readonly real_t Length()
{
real_t x2 = x * x;
real_t y2 = y * y;
@@ -309,7 +309,7 @@ namespace Godot
/// 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()
+ public readonly real_t LengthSquared()
{
real_t x2 = x * x;
real_t y2 = y * y;
@@ -326,7 +326,7 @@ namespace Godot
/// <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)
+ public readonly Vector4 Lerp(Vector4 to, real_t weight)
{
return new Vector4
(
@@ -342,7 +342,7 @@ namespace Godot
/// If all components are equal, this method returns <see cref="Axis.X"/>.
/// </summary>
/// <returns>The index of the highest axis.</returns>
- public Axis MaxAxisIndex()
+ public readonly Axis MaxAxisIndex()
{
int max_index = 0;
real_t max_value = x;
@@ -362,7 +362,7 @@ namespace Godot
/// If all components are equal, this method returns <see cref="Axis.W"/>.
/// </summary>
/// <returns>The index of the lowest axis.</returns>
- public Axis MinAxisIndex()
+ public readonly Axis MinAxisIndex()
{
int min_index = 0;
real_t min_value = x;
@@ -381,7 +381,7 @@ namespace Godot
/// 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()
+ public readonly Vector4 Normalized()
{
Vector4 v = this;
v.Normalize();
@@ -396,7 +396,7 @@ namespace Godot
/// <returns>
/// A vector with each component <see cref="Mathf.PosMod(real_t, real_t)"/> by <paramref name="mod"/>.
/// </returns>
- public Vector4 PosMod(real_t mod)
+ public readonly Vector4 PosMod(real_t mod)
{
return new Vector4(
Mathf.PosMod(x, mod),
@@ -414,7 +414,7 @@ namespace Godot
/// <returns>
/// A vector with each component <see cref="Mathf.PosMod(real_t, real_t)"/> by <paramref name="modv"/>'s components.
/// </returns>
- public Vector4 PosMod(Vector4 modv)
+ public readonly Vector4 PosMod(Vector4 modv)
{
return new Vector4(
Mathf.PosMod(x, modv.x),
@@ -429,7 +429,7 @@ namespace Godot
/// with halfway cases rounded towards the nearest multiple of two.
/// </summary>
/// <returns>The rounded vector.</returns>
- public Vector4 Round()
+ public readonly Vector4 Round()
{
return new Vector4(Mathf.Round(x), Mathf.Round(y), Mathf.Round(z), Mathf.Round(w));
}
@@ -440,7 +440,7 @@ namespace Godot
/// 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()
+ public readonly Vector4 Sign()
{
Vector4 v;
v.x = Mathf.Sign(x);
@@ -456,7 +456,7 @@ namespace Godot
/// </summary>
/// <param name="step">A vector value representing the step size to snap to.</param>
/// <returns>The snapped vector.</returns>
- public Vector4 Snapped(Vector4 step)
+ public readonly Vector4 Snapped(Vector4 step)
{
return new Vector4(
Mathf.Snapped(x, step.x),
@@ -828,7 +828,7 @@ namespace Godot
/// </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)
+ public override readonly bool Equals(object obj)
{
return obj is Vector4 other && Equals(other);
}
@@ -840,7 +840,7 @@ namespace Godot
/// </summary>
/// <param name="other">The other vector.</param>
/// <returns>Whether or not the vectors are exactly equal.</returns>
- public bool Equals(Vector4 other)
+ public readonly bool Equals(Vector4 other)
{
return x == other.x && y == other.y && z == other.z && w == other.w;
}
@@ -851,7 +851,7 @@ namespace Godot
/// </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)
+ public readonly 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);
}
@@ -860,7 +860,7 @@ namespace Godot
/// Serves as the hash function for <see cref="Vector4"/>.
/// </summary>
/// <returns>A hash code for this vector.</returns>
- public override int GetHashCode()
+ public override readonly int GetHashCode()
{
return y.GetHashCode() ^ x.GetHashCode() ^ z.GetHashCode() ^ w.GetHashCode();
}
@@ -878,7 +878,7 @@ namespace Godot
/// 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)
+ public readonly 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
index 4b1bb3ba19..8146991fd7 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4i.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4i.cs
@@ -68,7 +68,7 @@ namespace Godot
/// </value>
public int this[int index]
{
- get
+ readonly get
{
switch (index)
{
@@ -109,7 +109,7 @@ namespace Godot
/// <summary>
/// Helper method for deconstruction into a tuple.
/// </summary>
- public void Deconstruct(out int x, out int y, out int z, out int w)
+ public readonly void Deconstruct(out int x, out int y, out int z, out int w)
{
x = this.x;
y = this.y;
@@ -121,7 +121,7 @@ namespace Godot
/// 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()
+ public readonly Vector4i Abs()
{
return new Vector4i(Mathf.Abs(x), Mathf.Abs(y), Mathf.Abs(z), Mathf.Abs(w));
}
@@ -134,7 +134,7 @@ namespace Godot
/// <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)
+ public readonly Vector4i Clamp(Vector4i min, Vector4i max)
{
return new Vector4i
(
@@ -150,7 +150,7 @@ namespace Godot
/// </summary>
/// <seealso cref="LengthSquared"/>
/// <returns>The length of this vector.</returns>
- public real_t Length()
+ public readonly real_t Length()
{
int x2 = x * x;
int y2 = y * y;
@@ -166,7 +166,7 @@ namespace Godot
/// 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()
+ public readonly int LengthSquared()
{
int x2 = x * x;
int y2 = y * y;
@@ -181,7 +181,7 @@ namespace Godot
/// If all components are equal, this method returns <see cref="Axis.X"/>.
/// </summary>
/// <returns>The index of the highest axis.</returns>
- public Axis MaxAxisIndex()
+ public readonly Axis MaxAxisIndex()
{
int max_index = 0;
int max_value = x;
@@ -201,7 +201,7 @@ namespace Godot
/// If all components are equal, this method returns <see cref="Axis.W"/>.
/// </summary>
/// <returns>The index of the lowest axis.</returns>
- public Axis MinAxisIndex()
+ public readonly Axis MinAxisIndex()
{
int min_index = 0;
int min_value = x;
@@ -222,7 +222,7 @@ namespace Godot
/// 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()
+ public readonly Vector4i Sign()
{
return new Vector4i(Mathf.Sign(x), Mathf.Sign(y), Mathf.Sign(z), Mathf.Sign(w));
}
@@ -627,7 +627,7 @@ namespace Godot
/// </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)
+ public override readonly bool Equals(object obj)
{
return obj is Vector4i other && Equals(other);
}
@@ -637,7 +637,7 @@ namespace Godot
/// </summary>
/// <param name="other">The other vector.</param>
/// <returns>Whether or not the vectors are equal.</returns>
- public bool Equals(Vector4i other)
+ public readonly bool Equals(Vector4i other)
{
return x == other.x && y == other.y && z == other.z && w == other.w;
}
@@ -646,7 +646,7 @@ namespace Godot
/// Serves as the hash function for <see cref="Vector4i"/>.
/// </summary>
/// <returns>A hash code for this vector.</returns>
- public override int GetHashCode()
+ public override readonly int GetHashCode()
{
return y.GetHashCode() ^ x.GetHashCode() ^ z.GetHashCode() ^ w.GetHashCode();
}
@@ -655,7 +655,7 @@ namespace Godot
/// Converts this <see cref="Vector4i"/> to a string.
/// </summary>
/// <returns>A string representation of this vector.</returns>
- public override string ToString()
+ public override readonly string ToString()
{
return $"({x}, {y}, {z}, {w})";
}
@@ -664,7 +664,7 @@ namespace Godot
/// 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)
+ public readonly 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 e3fb254f49..644212c74d 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj
+++ b/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj
@@ -101,9 +101,8 @@
<Compile Include="Core\NativeInterop\InteropUtils.cs" />
<Compile Include="Core\NativeInterop\NativeFuncs.extended.cs" />
<Compile Include="Core\NativeInterop\NativeVariantPtrArgs.cs" />
- <Compile Include="Core\NativeInterop\VariantConversionCallbacks.cs" />
- <Compile Include="Core\NativeInterop\VariantSpanHelpers.cs" />
<Compile Include="Core\NativeInterop\VariantUtils.cs" />
+ <Compile Include="Core\NativeInterop\VariantUtils.generic.cs" />
<Compile Include="Core\NodePath.cs" />
<Compile Include="Core\Object.base.cs" />
<Compile Include="Core\Object.exceptions.cs" />
@@ -117,12 +116,13 @@
<Compile Include="Core\NativeInterop\NativeFuncs.cs" />
<Compile Include="Core\NativeInterop\InteropStructs.cs" />
<Compile Include="Core\NativeInterop\Marshaling.cs" />
- <Compile Include="Core\SignalInfo.cs" />
+ <Compile Include="Core\Signal.cs" />
<Compile Include="Core\SignalAwaiter.cs" />
<Compile Include="Core\StringExtensions.cs" />
<Compile Include="Core\StringName.cs" />
<Compile Include="Core\Transform2D.cs" />
<Compile Include="Core\Transform3D.cs" />
+ <Compile Include="Core\Variant.cs" />
<Compile Include="Core\Vector2.cs" />
<Compile Include="Core\Vector2i.cs" />
<Compile Include="Core\Vector3.cs" />
@@ -131,7 +131,6 @@
<Compile Include="Core\Vector4i.cs" />
<Compile Include="GlobalUsings.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
- <Compile Include="Variant.cs" />
</ItemGroup>
<!--
We import a props file with auto-generated includes. This works well with Rider.
diff --git a/modules/mono/glue/runtime_interop.cpp b/modules/mono/glue/runtime_interop.cpp
index e20a88076a..a3280a0739 100644
--- a/modules/mono/glue/runtime_interop.cpp
+++ b/modules/mono/glue/runtime_interop.cpp
@@ -514,6 +514,13 @@ void godotsharp_callable_call_deferred(Callable *p_callable, const Variant **p_a
p_callable->call_deferredp(p_args, p_arg_count);
}
+godot_color godotsharp_color_from_ok_hsl(float p_h, float p_s, float p_l, float p_alpha) {
+ godot_color ret;
+ Color *dest = (Color *)&ret;
+ memnew_placement(dest, Color(Color::from_ok_hsl(p_h, p_s, p_l, p_alpha)));
+ return ret;
+}
+
// GDNative functions
// gdnative.h
@@ -1067,30 +1074,6 @@ void godotsharp_dictionary_to_string(const Dictionary *p_self, String *r_str) {
*r_str = Variant(*p_self).operator String();
}
-void godotsharp_string_md5_buffer(const String *p_self, PackedByteArray *r_md5_buffer) {
- memnew_placement(r_md5_buffer, PackedByteArray(p_self->md5_buffer()));
-}
-
-void godotsharp_string_md5_text(const String *p_self, String *r_md5_text) {
- memnew_placement(r_md5_text, String(p_self->md5_text()));
-}
-
-int32_t godotsharp_string_rfind(const String *p_self, const String *p_what, int32_t p_from) {
- return p_self->rfind(*p_what, p_from);
-}
-
-int32_t godotsharp_string_rfindn(const String *p_self, const String *p_what, int32_t p_from) {
- return p_self->rfindn(*p_what, p_from);
-}
-
-void godotsharp_string_sha256_buffer(const String *p_self, PackedByteArray *r_sha256_buffer) {
- memnew_placement(r_sha256_buffer, PackedByteArray(p_self->sha256_buffer()));
-}
-
-void godotsharp_string_sha256_text(const String *p_self, String *r_sha256_text) {
- memnew_placement(r_sha256_text, String(p_self->sha256_text()));
-}
-
void godotsharp_string_simplify_path(const String *p_self, String *r_simplified_path) {
memnew_placement(r_simplified_path, String(p_self->simplify_path()));
}
@@ -1369,6 +1352,7 @@ static const void *unmanaged_callbacks[]{
(void *)godotsharp_callable_get_data_for_marshalling,
(void *)godotsharp_callable_call,
(void *)godotsharp_callable_call_deferred,
+ (void *)godotsharp_color_from_ok_hsl,
(void *)godotsharp_method_bind_ptrcall,
(void *)godotsharp_method_bind_call,
(void *)godotsharp_variant_new_string_name,
@@ -1473,12 +1457,6 @@ static const void *unmanaged_callbacks[]{
(void *)godotsharp_dictionary_duplicate,
(void *)godotsharp_dictionary_remove_key,
(void *)godotsharp_dictionary_to_string,
- (void *)godotsharp_string_md5_buffer,
- (void *)godotsharp_string_md5_text,
- (void *)godotsharp_string_rfind,
- (void *)godotsharp_string_rfindn,
- (void *)godotsharp_string_sha256_buffer,
- (void *)godotsharp_string_sha256_text,
(void *)godotsharp_string_simplify_path,
(void *)godotsharp_string_to_camel_case,
(void *)godotsharp_string_to_pascal_case,
diff --git a/modules/multiplayer/doc_classes/MultiplayerSynchronizer.xml b/modules/multiplayer/doc_classes/MultiplayerSynchronizer.xml
index 7ed6255a62..af7c345f15 100644
--- a/modules/multiplayer/doc_classes/MultiplayerSynchronizer.xml
+++ b/modules/multiplayer/doc_classes/MultiplayerSynchronizer.xml
@@ -17,7 +17,7 @@
<param 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].
+ [code]filter[/code] should take a peer ID [int] and return a [bool].
</description>
</method>
<method name="get_visibility_for" qualifiers="const">
diff --git a/editor/debugger/editor_network_profiler.cpp b/modules/multiplayer/editor/editor_network_profiler.cpp
index 8c18eba71d..cce22b9084 100644
--- a/editor/debugger/editor_network_profiler.cpp
+++ b/modules/multiplayer/editor/editor_network_profiler.cpp
@@ -36,13 +36,19 @@
void EditorNetworkProfiler::_bind_methods() {
ADD_SIGNAL(MethodInfo("enable_profiling", PropertyInfo(Variant::BOOL, "enable")));
+ ADD_SIGNAL(MethodInfo("open_request", PropertyInfo(Variant::STRING, "path")));
}
void EditorNetworkProfiler::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE:
case NOTIFICATION_THEME_CHANGED: {
- activate->set_icon(get_theme_icon(SNAME("Play"), SNAME("EditorIcons")));
+ node_icon = get_theme_icon(SNAME("Node"), SNAME("EditorIcons"));
+ if (activate->is_pressed()) {
+ activate->set_icon(get_theme_icon(SNAME("Stop"), SNAME("EditorIcons")));
+ } else {
+ activate->set_icon(get_theme_icon(SNAME("Play"), SNAME("EditorIcons")));
+ }
clear_button->set_icon(get_theme_icon(SNAME("Clear"), SNAME("EditorIcons")));
incoming_bandwidth_text->set_right_icon(get_theme_icon(SNAME("ArrowDown"), SNAME("EditorIcons")));
outgoing_bandwidth_text->set_right_icon(get_theme_icon(SNAME("ArrowUp"), SNAME("EditorIcons")));
@@ -54,29 +60,104 @@ void EditorNetworkProfiler::_notification(int p_what) {
}
}
-void EditorNetworkProfiler::_update_frame() {
+void EditorNetworkProfiler::_refresh() {
+ if (!dirty) {
+ return;
+ }
+ dirty = false;
+ refresh_rpc_data();
+ refresh_replication_data();
+}
+
+void EditorNetworkProfiler::refresh_rpc_data() {
counters_display->clear();
TreeItem *root = counters_display->create_item();
+ int cols = counters_display->get_columns();
- for (const KeyValue<ObjectID, SceneDebugger::RPCNodeInfo> &E : nodes_data) {
+ for (const KeyValue<ObjectID, RPCNodeInfo> &E : rpc_data) {
TreeItem *node = counters_display->create_item(root);
- for (int j = 0; j < counters_display->get_columns(); ++j) {
+ for (int j = 0; j < cols; ++j) {
node->set_text_alignment(j, j > 0 ? HORIZONTAL_ALIGNMENT_RIGHT : HORIZONTAL_ALIGNMENT_LEFT);
}
node->set_text(0, E.value.node_path);
- node->set_text(1, E.value.incoming_rpc == 0 ? "-" : itos(E.value.incoming_rpc));
- node->set_text(2, E.value.outgoing_rpc == 0 ? "-" : itos(E.value.outgoing_rpc));
+ node->set_text(1, E.value.incoming_rpc == 0 ? "-" : vformat(TTR("%d (%s)"), E.value.incoming_rpc, String::humanize_size(E.value.incoming_size)));
+ node->set_text(2, E.value.outgoing_rpc == 0 ? "-" : vformat(TTR("%d (%s)"), E.value.outgoing_rpc, String::humanize_size(E.value.outgoing_size)));
+ }
+}
+
+void EditorNetworkProfiler::refresh_replication_data() {
+ replication_display->clear();
+
+ TreeItem *root = replication_display->create_item();
+
+ for (const KeyValue<ObjectID, SyncInfo> &E : sync_data) {
+ // Ensure the nodes have at least a temporary cache.
+ ObjectID ids[3] = { E.value.synchronizer, E.value.config, E.value.root_node };
+ for (uint32_t i = 0; i < 3; i++) {
+ const ObjectID &id = ids[i];
+ if (!node_data.has(id)) {
+ missing_node_data.insert(id);
+ node_data[id] = NodeInfo(id);
+ }
+ }
+
+ TreeItem *node = replication_display->create_item(root);
+
+ const NodeInfo &root_info = node_data[E.value.root_node];
+ const NodeInfo &sync_info = node_data[E.value.synchronizer];
+ const NodeInfo &cfg_info = node_data[E.value.config];
+
+ node->set_text(0, root_info.path.get_file());
+ node->set_icon(0, has_theme_icon(root_info.type, SNAME("EditorIcons")) ? get_theme_icon(root_info.type, SNAME("EditorIcons")) : node_icon);
+ node->set_tooltip_text(0, root_info.path);
+
+ node->set_text(1, sync_info.path.get_file());
+ node->set_icon(1, get_theme_icon("MultiplayerSynchronizer", SNAME("EditorIcons")));
+ node->set_tooltip_text(1, sync_info.path);
+
+ int cfg_idx = cfg_info.path.find("::");
+ if (cfg_info.path.begins_with("res://") && ResourceLoader::exists(cfg_info.path) && cfg_idx > 0) {
+ String res_idstr = cfg_info.path.substr(cfg_idx + 2).replace("SceneReplicationConfig_", "");
+ String scene_path = cfg_info.path.substr(0, cfg_idx);
+ node->set_text(2, vformat("%s (%s)", res_idstr, scene_path.get_file()));
+ node->add_button(2, get_theme_icon(SNAME("InstanceOptions"), SNAME("EditorIcons")));
+ node->set_tooltip_text(2, cfg_info.path);
+ node->set_metadata(2, scene_path);
+ } else {
+ node->set_text(2, cfg_info.path);
+ node->set_metadata(2, "");
+ }
+
+ node->set_text(3, vformat("%d - %d", E.value.incoming_syncs, E.value.outgoing_syncs));
+ node->set_text(4, vformat("%d - %d", E.value.incoming_size, E.value.outgoing_size));
}
}
+Array EditorNetworkProfiler::pop_missing_node_data() {
+ Array out;
+ for (const ObjectID &id : missing_node_data) {
+ out.push_back(id);
+ }
+ missing_node_data.clear();
+ return out;
+}
+
+void EditorNetworkProfiler::add_node_data(const NodeInfo &p_info) {
+ ERR_FAIL_COND(!node_data.has(p_info.id));
+ node_data[p_info.id] = p_info;
+ dirty = true;
+}
+
void EditorNetworkProfiler::_activate_pressed() {
if (activate->is_pressed()) {
+ refresh_timer->start();
activate->set_icon(get_theme_icon(SNAME("Stop"), SNAME("EditorIcons")));
activate->set_text(TTR("Stop"));
} else {
+ refresh_timer->stop();
activate->set_icon(get_theme_icon(SNAME("Play"), SNAME("EditorIcons")));
activate->set_text(TTR("Start"));
}
@@ -84,25 +165,55 @@ void EditorNetworkProfiler::_activate_pressed() {
}
void EditorNetworkProfiler::_clear_pressed() {
- nodes_data.clear();
+ rpc_data.clear();
+ sync_data.clear();
+ node_data.clear();
+ missing_node_data.clear();
set_bandwidth(0, 0);
- if (frame_delay->is_stopped()) {
- frame_delay->set_wait_time(0.1);
- frame_delay->start();
+ refresh_rpc_data();
+ refresh_replication_data();
+}
+
+void EditorNetworkProfiler::_replication_button_clicked(TreeItem *p_item, int p_column, int p_idx, MouseButton p_button) {
+ if (!p_item) {
+ return;
+ }
+ String meta = p_item->get_metadata(p_column);
+ if (meta.size() && ResourceLoader::exists(meta)) {
+ emit_signal("open_request", meta);
}
}
-void EditorNetworkProfiler::add_node_frame_data(const SceneDebugger::RPCNodeInfo p_frame) {
- if (!nodes_data.has(p_frame.node)) {
- nodes_data.insert(p_frame.node, p_frame);
+void EditorNetworkProfiler::add_rpc_frame_data(const RPCNodeInfo &p_frame) {
+ dirty = true;
+ if (!rpc_data.has(p_frame.node)) {
+ rpc_data.insert(p_frame.node, p_frame);
} else {
- nodes_data[p_frame.node].incoming_rpc += p_frame.incoming_rpc;
- nodes_data[p_frame.node].outgoing_rpc += p_frame.outgoing_rpc;
+ rpc_data[p_frame.node].incoming_rpc += p_frame.incoming_rpc;
+ rpc_data[p_frame.node].outgoing_rpc += p_frame.outgoing_rpc;
}
+ if (p_frame.incoming_rpc) {
+ rpc_data[p_frame.node].incoming_size = p_frame.incoming_size / p_frame.incoming_rpc;
+ }
+ if (p_frame.outgoing_rpc) {
+ rpc_data[p_frame.node].outgoing_size = p_frame.outgoing_size / p_frame.outgoing_rpc;
+ }
+}
- if (frame_delay->is_stopped()) {
- frame_delay->set_wait_time(0.1);
- frame_delay->start();
+void EditorNetworkProfiler::add_sync_frame_data(const SyncInfo &p_frame) {
+ dirty = true;
+ if (!sync_data.has(p_frame.synchronizer)) {
+ sync_data[p_frame.synchronizer] = p_frame;
+ } else {
+ sync_data[p_frame.synchronizer].incoming_syncs += p_frame.incoming_syncs;
+ sync_data[p_frame.synchronizer].outgoing_syncs += p_frame.outgoing_syncs;
+ }
+ SyncInfo &info = sync_data[p_frame.synchronizer];
+ if (info.incoming_syncs) {
+ info.incoming_size = p_frame.incoming_size / p_frame.incoming_syncs;
+ }
+ if (info.outgoing_syncs) {
+ info.outgoing_size = p_frame.outgoing_size / p_frame.outgoing_syncs;
}
}
@@ -168,9 +279,17 @@ EditorNetworkProfiler::EditorNetworkProfiler() {
// Set initial texts in the incoming/outgoing bandwidth labels
set_bandwidth(0, 0);
+ HSplitContainer *sc = memnew(HSplitContainer);
+ add_child(sc);
+ sc->set_v_size_flags(SIZE_EXPAND_FILL);
+ sc->set_h_size_flags(SIZE_EXPAND_FILL);
+ sc->set_split_offset(100 * EDSCALE);
+
+ // RPC
counters_display = memnew(Tree);
- counters_display->set_custom_minimum_size(Size2(300, 0) * EDSCALE);
+ counters_display->set_custom_minimum_size(Size2(320, 0) * EDSCALE);
counters_display->set_v_size_flags(SIZE_EXPAND_FILL);
+ counters_display->set_h_size_flags(SIZE_EXPAND_FILL);
counters_display->set_hide_folding(true);
counters_display->set_hide_root(true);
counters_display->set_columns(3);
@@ -187,11 +306,42 @@ EditorNetworkProfiler::EditorNetworkProfiler() {
counters_display->set_column_expand(2, false);
counters_display->set_column_clip_content(2, true);
counters_display->set_column_custom_minimum_width(2, 120 * EDSCALE);
- add_child(counters_display);
+ sc->add_child(counters_display);
+
+ // Replication
+ replication_display = memnew(Tree);
+ replication_display->set_custom_minimum_size(Size2(320, 0) * EDSCALE);
+ replication_display->set_v_size_flags(SIZE_EXPAND_FILL);
+ replication_display->set_h_size_flags(SIZE_EXPAND_FILL);
+ replication_display->set_hide_folding(true);
+ replication_display->set_hide_root(true);
+ replication_display->set_columns(5);
+ replication_display->set_column_titles_visible(true);
+ replication_display->set_column_title(0, TTR("Root"));
+ replication_display->set_column_expand(0, true);
+ replication_display->set_column_clip_content(0, true);
+ replication_display->set_column_custom_minimum_width(0, 80 * EDSCALE);
+ replication_display->set_column_title(1, TTR("Synchronizer"));
+ replication_display->set_column_expand(1, true);
+ replication_display->set_column_clip_content(1, true);
+ replication_display->set_column_custom_minimum_width(1, 80 * EDSCALE);
+ replication_display->set_column_title(2, TTR("Config"));
+ replication_display->set_column_expand(2, true);
+ replication_display->set_column_clip_content(2, true);
+ replication_display->set_column_custom_minimum_width(2, 80 * EDSCALE);
+ replication_display->set_column_title(3, TTR("Count"));
+ replication_display->set_column_expand(3, false);
+ replication_display->set_column_clip_content(3, true);
+ replication_display->set_column_custom_minimum_width(3, 80 * EDSCALE);
+ replication_display->set_column_title(4, TTR("Size"));
+ replication_display->set_column_expand(4, false);
+ replication_display->set_column_clip_content(4, true);
+ replication_display->set_column_custom_minimum_width(4, 80 * EDSCALE);
+ replication_display->connect("button_clicked", callable_mp(this, &EditorNetworkProfiler::_replication_button_clicked));
+ sc->add_child(replication_display);
- frame_delay = memnew(Timer);
- frame_delay->set_wait_time(0.1);
- frame_delay->set_one_shot(true);
- add_child(frame_delay);
- frame_delay->connect("timeout", callable_mp(this, &EditorNetworkProfiler::_update_frame));
+ refresh_timer = memnew(Timer);
+ refresh_timer->set_wait_time(0.5);
+ refresh_timer->connect("timeout", callable_mp(this, &EditorNetworkProfiler::_refresh));
+ add_child(refresh_timer);
}
diff --git a/editor/debugger/editor_network_profiler.h b/modules/multiplayer/editor/editor_network_profiler.h
index aea7ce3eec..630747d988 100644
--- a/editor/debugger/editor_network_profiler.h
+++ b/modules/multiplayer/editor/editor_network_profiler.h
@@ -38,31 +38,60 @@
#include "scene/gui/split_container.h"
#include "scene/gui/tree.h"
+#include "../multiplayer_debugger.h"
+
class EditorNetworkProfiler : public VBoxContainer {
GDCLASS(EditorNetworkProfiler, VBoxContainer)
+public:
+ struct NodeInfo {
+ ObjectID id;
+ String type;
+ String path;
+
+ NodeInfo() {}
+ NodeInfo(const ObjectID &p_id) {
+ id = p_id;
+ path = String::num_int64(p_id);
+ }
+ };
+
private:
+ using RPCNodeInfo = MultiplayerDebugger::RPCNodeInfo;
+ using SyncInfo = MultiplayerDebugger::SyncInfo;
+
+ bool dirty = false;
+ Timer *refresh_timer = nullptr;
Button *activate = nullptr;
Button *clear_button = nullptr;
Tree *counters_display = nullptr;
LineEdit *incoming_bandwidth_text = nullptr;
LineEdit *outgoing_bandwidth_text = nullptr;
+ Tree *replication_display = nullptr;
- Timer *frame_delay = nullptr;
-
- HashMap<ObjectID, SceneDebugger::RPCNodeInfo> nodes_data;
-
- void _update_frame();
+ HashMap<ObjectID, RPCNodeInfo> rpc_data;
+ HashMap<ObjectID, SyncInfo> sync_data;
+ HashMap<ObjectID, NodeInfo> node_data;
+ HashSet<ObjectID> missing_node_data;
+ Ref<Texture2D> node_icon;
void _activate_pressed();
void _clear_pressed();
+ void _refresh();
+ void _replication_button_clicked(TreeItem *p_item, int p_column, int p_idx, MouseButton p_button);
protected:
void _notification(int p_what);
static void _bind_methods();
public:
- void add_node_frame_data(const SceneDebugger::RPCNodeInfo p_frame);
+ void refresh_rpc_data();
+ void refresh_replication_data();
+
+ Array pop_missing_node_data();
+ void add_node_data(const NodeInfo &p_info);
+ void add_rpc_frame_data(const RPCNodeInfo &p_frame);
+ void add_sync_frame_data(const SyncInfo &p_frame);
void set_bandwidth(int p_incoming, int p_outgoing);
bool is_profiling();
diff --git a/modules/multiplayer/editor/multiplayer_editor_plugin.cpp b/modules/multiplayer/editor/multiplayer_editor_plugin.cpp
new file mode 100644
index 0000000000..c5cf3e6f24
--- /dev/null
+++ b/modules/multiplayer/editor/multiplayer_editor_plugin.cpp
@@ -0,0 +1,175 @@
+/*************************************************************************/
+/* multiplayer_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 "multiplayer_editor_plugin.h"
+
+#include "../multiplayer_synchronizer.h"
+#include "editor_network_profiler.h"
+#include "replication_editor.h"
+
+#include "editor/editor_node.h"
+
+void MultiplayerEditorDebugger::_bind_methods() {
+ ADD_SIGNAL(MethodInfo("open_request", PropertyInfo(Variant::STRING, "path")));
+}
+
+bool MultiplayerEditorDebugger::has_capture(const String &p_capture) const {
+ return p_capture == "multiplayer";
+}
+
+void MultiplayerEditorDebugger::_open_request(const String &p_path) {
+ emit_signal("open_request", p_path);
+}
+
+bool MultiplayerEditorDebugger::capture(const String &p_message, const Array &p_data, int p_session) {
+ ERR_FAIL_COND_V(!profilers.has(p_session), false);
+ EditorNetworkProfiler *profiler = profilers[p_session];
+ if (p_message == "multiplayer:rpc") {
+ MultiplayerDebugger::RPCFrame frame;
+ frame.deserialize(p_data);
+ for (int i = 0; i < frame.infos.size(); i++) {
+ profiler->add_rpc_frame_data(frame.infos[i]);
+ }
+ return true;
+ } else if (p_message == "multiplayer:syncs") {
+ MultiplayerDebugger::ReplicationFrame frame;
+ frame.deserialize(p_data);
+ for (const KeyValue<ObjectID, MultiplayerDebugger::SyncInfo> &E : frame.infos) {
+ profiler->add_sync_frame_data(E.value);
+ }
+ Array missing = profiler->pop_missing_node_data();
+ if (missing.size()) {
+ // Asks for the object information.
+ get_session(p_session)->send_message("multiplayer:cache", missing);
+ }
+ return true;
+ } else if (p_message == "multiplayer:cache") {
+ ERR_FAIL_COND_V(p_data.size() % 3, false);
+ for (int i = 0; i < p_data.size(); i += 3) {
+ EditorNetworkProfiler::NodeInfo info;
+ info.id = p_data[i].operator ObjectID();
+ info.type = p_data[i + 1].operator String();
+ info.path = p_data[i + 2].operator String();
+ profiler->add_node_data(info);
+ }
+ return true;
+ } else if (p_message == "multiplayer:bandwidth") {
+ ERR_FAIL_COND_V(p_data.size() < 2, false);
+ profiler->set_bandwidth(p_data[0], p_data[1]);
+ return true;
+ }
+ return false;
+}
+
+void MultiplayerEditorDebugger::_profiler_activate(bool p_enable, int p_session_id) {
+ Ref<EditorDebuggerSession> session = get_session(p_session_id);
+ ERR_FAIL_COND(session.is_null());
+ session->toggle_profiler("multiplayer:bandwidth", p_enable);
+ session->toggle_profiler("multiplayer:rpc", p_enable);
+ session->toggle_profiler("multiplayer:replication", p_enable);
+}
+
+void MultiplayerEditorDebugger::setup_session(int p_session_id) {
+ Ref<EditorDebuggerSession> session = get_session(p_session_id);
+ ERR_FAIL_COND(session.is_null());
+ EditorNetworkProfiler *profiler = memnew(EditorNetworkProfiler);
+ profiler->connect("enable_profiling", callable_mp(this, &MultiplayerEditorDebugger::_profiler_activate).bind(p_session_id));
+ profiler->connect("open_request", callable_mp(this, &MultiplayerEditorDebugger::_open_request));
+ profiler->set_name(TTR("Network Profiler"));
+ session->add_session_tab(profiler);
+ profilers[p_session_id] = profiler;
+}
+
+/// MultiplayerEditorPlugin
+
+MultiplayerEditorPlugin::MultiplayerEditorPlugin() {
+ repl_editor = memnew(ReplicationEditor);
+ button = EditorNode::get_singleton()->add_bottom_panel_item(TTR("Replication"), repl_editor);
+ button->hide();
+ repl_editor->get_pin()->connect("pressed", callable_mp(this, &MultiplayerEditorPlugin::_pinned));
+ debugger.instantiate();
+ debugger->connect("open_request", callable_mp(this, &MultiplayerEditorPlugin::_open_request));
+}
+
+void MultiplayerEditorPlugin::_open_request(const String &p_path) {
+ get_editor_interface()->open_scene_from_path(p_path);
+}
+
+void MultiplayerEditorPlugin::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_ENTER_TREE: {
+ get_tree()->connect("node_removed", callable_mp(this, &MultiplayerEditorPlugin::_node_removed));
+ add_debugger_plugin(debugger);
+ } break;
+ case NOTIFICATION_EXIT_TREE: {
+ remove_debugger_plugin(debugger);
+ }
+ }
+}
+
+void MultiplayerEditorPlugin::_node_removed(Node *p_node) {
+ if (p_node && p_node == repl_editor->get_current()) {
+ repl_editor->edit(nullptr);
+ if (repl_editor->is_visible_in_tree()) {
+ EditorNode::get_singleton()->hide_bottom_panel();
+ }
+ button->hide();
+ repl_editor->get_pin()->set_pressed(false);
+ }
+}
+
+void MultiplayerEditorPlugin::_pinned() {
+ if (!repl_editor->get_pin()->is_pressed()) {
+ if (repl_editor->is_visible_in_tree()) {
+ EditorNode::get_singleton()->hide_bottom_panel();
+ }
+ button->hide();
+ }
+}
+
+void MultiplayerEditorPlugin::edit(Object *p_object) {
+ repl_editor->edit(Object::cast_to<MultiplayerSynchronizer>(p_object));
+}
+
+bool MultiplayerEditorPlugin::handles(Object *p_object) const {
+ return p_object->is_class("MultiplayerSynchronizer");
+}
+
+void MultiplayerEditorPlugin::make_visible(bool p_visible) {
+ if (p_visible) {
+ button->show();
+ EditorNode::get_singleton()->make_bottom_panel_item_visible(repl_editor);
+ } else if (!repl_editor->get_pin()->is_pressed()) {
+ if (repl_editor->is_visible_in_tree()) {
+ EditorNode::get_singleton()->hide_bottom_panel();
+ }
+ button->hide();
+ }
+}
diff --git a/modules/multiplayer/editor/multiplayer_editor_plugin.h b/modules/multiplayer/editor/multiplayer_editor_plugin.h
new file mode 100644
index 0000000000..f29a70e897
--- /dev/null
+++ b/modules/multiplayer/editor/multiplayer_editor_plugin.h
@@ -0,0 +1,85 @@
+/*************************************************************************/
+/* multiplayer_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 MULTIPLAYER_EDITOR_PLUGIN_H
+#define MULTIPLAYER_EDITOR_PLUGIN_H
+
+#include "editor/editor_plugin.h"
+
+#include "editor/plugins/editor_debugger_plugin.h"
+
+class EditorNetworkProfiler;
+class MultiplayerEditorDebugger : public EditorDebuggerPlugin {
+ GDCLASS(MultiplayerEditorDebugger, EditorDebuggerPlugin);
+
+private:
+ HashMap<int, EditorNetworkProfiler *> profilers;
+
+ void _open_request(const String &p_path);
+ void _profiler_activate(bool p_enable, int p_session_id);
+
+protected:
+ static void _bind_methods();
+
+public:
+ virtual bool has_capture(const String &p_capture) const override;
+ virtual bool capture(const String &p_message, const Array &p_data, int p_index) override;
+ virtual void setup_session(int p_session_id) override;
+
+ MultiplayerEditorDebugger() {}
+};
+
+class ReplicationEditor;
+
+class MultiplayerEditorPlugin : public EditorPlugin {
+ GDCLASS(MultiplayerEditorPlugin, EditorPlugin);
+
+private:
+ Button *button = nullptr;
+ ReplicationEditor *repl_editor = nullptr;
+ Ref<MultiplayerEditorDebugger> debugger;
+
+ void _open_request(const String &p_path);
+ void _node_removed(Node *p_node);
+
+ void _pinned();
+
+protected:
+ void _notification(int p_what);
+
+public:
+ virtual void edit(Object *p_object) override;
+ virtual bool handles(Object *p_object) const override;
+ virtual void make_visible(bool p_visible) override;
+
+ MultiplayerEditorPlugin();
+};
+
+#endif // MULTIPLAYER_EDITOR_PLUGIN_H
diff --git a/modules/multiplayer/editor/replication_editor_plugin.cpp b/modules/multiplayer/editor/replication_editor.cpp
index aee5f5b483..ccde9fed22 100644
--- a/modules/multiplayer/editor/replication_editor_plugin.cpp
+++ b/modules/multiplayer/editor/replication_editor.cpp
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* replication_editor_plugin.cpp */
+/* replication_editor.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,15 +28,17 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "replication_editor_plugin.h"
+#include "replication_editor.h"
+
+#include "../multiplayer_synchronizer.h"
#include "editor/editor_node.h"
#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_undo_redo_manager.h"
#include "editor/inspector_dock.h"
+#include "editor/property_selector.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"
@@ -140,7 +142,7 @@ void ReplicationEditor::_add_sync_property(String p_path) {
return;
}
- Ref<EditorUndoRedoManager> undo_redo = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_singleton()->get_undo_redo();
undo_redo->create_action(TTR("Add property to synchronizer"));
if (config.is_null()) {
@@ -200,7 +202,7 @@ ReplicationEditor::ReplicationEditor() {
add_pick_button = memnew(Button);
add_pick_button->connect("pressed", callable_mp(this, &ReplicationEditor::_pick_new_property));
- add_pick_button->set_text(TTR("Add property to sync.."));
+ add_pick_button->set_text(TTR("Add property to sync..."));
hb->add_child(add_pick_button);
VSeparator *vs = memnew(VSeparator);
vs->set_custom_minimum_size(Size2(30 * EDSCALE, 0));
@@ -492,62 +494,3 @@ void ReplicationEditor::_add_property(const NodePath &p_property, bool p_spawn,
item->set_checked(2, p_sync);
item->set_editable(2, true);
}
-
-/// ReplicationEditorPlugin
-ReplicationEditorPlugin::ReplicationEditorPlugin() {
- repl_editor = memnew(ReplicationEditor);
- button = EditorNode::get_singleton()->add_bottom_panel_item(TTR("Replication"), repl_editor);
- button->hide();
- repl_editor->get_pin()->connect("pressed", callable_mp(this, &ReplicationEditorPlugin::_pinned));
-}
-
-ReplicationEditorPlugin::~ReplicationEditorPlugin() {
-}
-
-void ReplicationEditorPlugin::_notification(int p_what) {
- switch (p_what) {
- case NOTIFICATION_ENTER_TREE: {
- get_tree()->connect("node_removed", callable_mp(this, &ReplicationEditorPlugin::_node_removed));
- } break;
- }
-}
-
-void ReplicationEditorPlugin::_node_removed(Node *p_node) {
- if (p_node && p_node == repl_editor->get_current()) {
- repl_editor->edit(nullptr);
- if (repl_editor->is_visible_in_tree()) {
- EditorNode::get_singleton()->hide_bottom_panel();
- }
- button->hide();
- repl_editor->get_pin()->set_pressed(false);
- }
-}
-
-void ReplicationEditorPlugin::_pinned() {
- if (!repl_editor->get_pin()->is_pressed()) {
- if (repl_editor->is_visible_in_tree()) {
- EditorNode::get_singleton()->hide_bottom_panel();
- }
- button->hide();
- }
-}
-
-void ReplicationEditorPlugin::edit(Object *p_object) {
- repl_editor->edit(Object::cast_to<MultiplayerSynchronizer>(p_object));
-}
-
-bool ReplicationEditorPlugin::handles(Object *p_object) const {
- return p_object->is_class("MultiplayerSynchronizer");
-}
-
-void ReplicationEditorPlugin::make_visible(bool p_visible) {
- if (p_visible) {
- button->show();
- EditorNode::get_singleton()->make_bottom_panel_item_visible(repl_editor);
- } else if (!repl_editor->get_pin()->is_pressed()) {
- if (repl_editor->is_visible_in_tree()) {
- EditorNode::get_singleton()->hide_bottom_panel();
- }
- button->hide();
- }
-}
diff --git a/modules/multiplayer/editor/replication_editor_plugin.h b/modules/multiplayer/editor/replication_editor.h
index e60e49cc25..8a48e8dbe7 100644
--- a/modules/multiplayer/editor/replication_editor_plugin.h
+++ b/modules/multiplayer/editor/replication_editor.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* replication_editor_plugin.h */
+/* replication_editor.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,21 +28,21 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef REPLICATION_EDITOR_PLUGIN_H
-#define REPLICATION_EDITOR_PLUGIN_H
+#ifndef REPLICATION_EDITOR_H
+#define REPLICATION_EDITOR_H
#include "editor/editor_plugin.h"
-
-#include "editor/editor_spin_slider.h"
-#include "editor/property_selector.h"
-
-#include "../scene_replication_config.h"
+#include "modules/multiplayer/scene_replication_config.h"
+#include "scene/gui/box_container.h"
class ConfirmationDialog;
class MultiplayerSynchronizer;
-class SceneTreeDialog;
+class AcceptDialog;
+class LineEdit;
class Tree;
class TreeItem;
+class PropertySelector;
+class SceneTreeDialog;
class ReplicationEditor : public VBoxContainer {
GDCLASS(ReplicationEditor, VBoxContainer);
@@ -105,27 +105,4 @@ public:
~ReplicationEditor() {}
};
-class ReplicationEditorPlugin : public EditorPlugin {
- GDCLASS(ReplicationEditorPlugin, EditorPlugin);
-
-private:
- Button *button = nullptr;
- ReplicationEditor *repl_editor = nullptr;
-
- void _node_removed(Node *p_node);
-
- void _pinned();
-
-protected:
- void _notification(int p_what);
-
-public:
- virtual void edit(Object *p_object) override;
- virtual bool handles(Object *p_object) const override;
- virtual void make_visible(bool p_visible) override;
-
- ReplicationEditorPlugin();
- ~ReplicationEditorPlugin();
-};
-
-#endif // REPLICATION_EDITOR_PLUGIN_H
+#endif // REPLICATION_EDITOR_H
diff --git a/modules/multiplayer/multiplayer_debugger.cpp b/modules/multiplayer/multiplayer_debugger.cpp
new file mode 100644
index 0000000000..9086ee6ec9
--- /dev/null
+++ b/modules/multiplayer/multiplayer_debugger.cpp
@@ -0,0 +1,333 @@
+/*************************************************************************/
+/* multiplayer_debugger.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_debugger.h"
+
+#include "multiplayer_synchronizer.h"
+#include "scene_replication_config.h"
+
+#include "core/debugger/engine_debugger.h"
+#include "scene/main/node.h"
+
+List<Ref<EngineProfiler>> multiplayer_profilers;
+
+void MultiplayerDebugger::initialize() {
+ Ref<BandwidthProfiler> bandwidth;
+ bandwidth.instantiate();
+ bandwidth->bind("multiplayer:bandwidth");
+ multiplayer_profilers.push_back(bandwidth);
+
+ Ref<RPCProfiler> rpc_profiler;
+ rpc_profiler.instantiate();
+ rpc_profiler->bind("multiplayer:rpc");
+ multiplayer_profilers.push_back(rpc_profiler);
+
+ Ref<ReplicationProfiler> replication_profiler;
+ replication_profiler.instantiate();
+ replication_profiler->bind("multiplayer:replication");
+ multiplayer_profilers.push_back(replication_profiler);
+
+ EngineDebugger::register_message_capture("multiplayer", EngineDebugger::Capture(nullptr, &_capture));
+}
+
+void MultiplayerDebugger::deinitialize() {
+ multiplayer_profilers.clear();
+}
+
+Error MultiplayerDebugger::_capture(void *p_user, const String &p_msg, const Array &p_args, bool &r_captured) {
+ if (p_msg == "cache") {
+ Array out;
+ for (int i = 0; i < p_args.size(); i++) {
+ ObjectID id = p_args[i].operator ObjectID();
+ Object *obj = ObjectDB::get_instance(id);
+ ERR_CONTINUE(!obj);
+ if (Object::cast_to<SceneReplicationConfig>(obj)) {
+ out.push_back(id);
+ out.push_back(obj->get_class());
+ out.push_back(((SceneReplicationConfig *)obj)->get_path());
+ } else if (Object::cast_to<Node>(obj)) {
+ out.push_back(id);
+ out.push_back(obj->get_class());
+ out.push_back(String(((Node *)obj)->get_path()));
+ } else {
+ ERR_FAIL_V(FAILED);
+ }
+ }
+ EngineDebugger::get_singleton()->send_message("multiplayer:cache", out);
+ return OK;
+ }
+ ERR_FAIL_V(FAILED);
+}
+
+// BandwidthProfiler
+
+int MultiplayerDebugger::BandwidthProfiler::bandwidth_usage(const Vector<BandwidthFrame> &p_buffer, int p_pointer) {
+ ERR_FAIL_COND_V(p_buffer.size() == 0, 0);
+ int total_bandwidth = 0;
+
+ uint64_t timestamp = OS::get_singleton()->get_ticks_msec();
+ uint64_t final_timestamp = timestamp - 1000;
+
+ int i = (p_pointer + p_buffer.size() - 1) % p_buffer.size();
+
+ while (i != p_pointer && p_buffer[i].packet_size > 0) {
+ if (p_buffer[i].timestamp < final_timestamp) {
+ return total_bandwidth;
+ }
+ total_bandwidth += p_buffer[i].packet_size;
+ i = (i + p_buffer.size() - 1) % p_buffer.size();
+ }
+
+ ERR_FAIL_COND_V_MSG(i == p_pointer, total_bandwidth, "Reached the end of the bandwidth profiler buffer, values might be inaccurate.");
+ return total_bandwidth;
+}
+
+void MultiplayerDebugger::BandwidthProfiler::toggle(bool p_enable, const Array &p_opts) {
+ if (!p_enable) {
+ bandwidth_in.clear();
+ bandwidth_out.clear();
+ } else {
+ bandwidth_in_ptr = 0;
+ bandwidth_in.resize(16384); // ~128kB
+ for (int i = 0; i < bandwidth_in.size(); ++i) {
+ bandwidth_in.write[i].packet_size = -1;
+ }
+ bandwidth_out_ptr = 0;
+ bandwidth_out.resize(16384); // ~128kB
+ for (int i = 0; i < bandwidth_out.size(); ++i) {
+ bandwidth_out.write[i].packet_size = -1;
+ }
+ }
+}
+
+void MultiplayerDebugger::BandwidthProfiler::add(const Array &p_data) {
+ ERR_FAIL_COND(p_data.size() < 3);
+ const String inout = p_data[0];
+ int time = p_data[1];
+ int size = p_data[2];
+ if (inout == "in") {
+ bandwidth_in.write[bandwidth_in_ptr].timestamp = time;
+ bandwidth_in.write[bandwidth_in_ptr].packet_size = size;
+ bandwidth_in_ptr = (bandwidth_in_ptr + 1) % bandwidth_in.size();
+ } else if (inout == "out") {
+ bandwidth_out.write[bandwidth_out_ptr].timestamp = time;
+ bandwidth_out.write[bandwidth_out_ptr].packet_size = size;
+ bandwidth_out_ptr = (bandwidth_out_ptr + 1) % bandwidth_out.size();
+ }
+}
+
+void MultiplayerDebugger::BandwidthProfiler::tick(double p_frame_time, double p_process_time, double p_physics_time, double p_physics_frame_time) {
+ uint64_t pt = OS::get_singleton()->get_ticks_msec();
+ if (pt - last_bandwidth_time > 200) {
+ last_bandwidth_time = pt;
+ int incoming_bandwidth = bandwidth_usage(bandwidth_in, bandwidth_in_ptr);
+ int outgoing_bandwidth = bandwidth_usage(bandwidth_out, bandwidth_out_ptr);
+
+ Array arr;
+ arr.push_back(incoming_bandwidth);
+ arr.push_back(outgoing_bandwidth);
+ EngineDebugger::get_singleton()->send_message("multiplayer:bandwidth", arr);
+ }
+}
+
+// RPCProfiler
+
+Array MultiplayerDebugger::RPCFrame::serialize() {
+ Array arr;
+ arr.push_back(infos.size() * 6);
+ for (int i = 0; i < infos.size(); ++i) {
+ arr.push_back(uint64_t(infos[i].node));
+ arr.push_back(infos[i].node_path);
+ arr.push_back(infos[i].incoming_rpc);
+ arr.push_back(infos[i].incoming_size);
+ arr.push_back(infos[i].outgoing_rpc);
+ arr.push_back(infos[i].outgoing_size);
+ }
+ return arr;
+}
+
+bool MultiplayerDebugger::RPCFrame::deserialize(const Array &p_arr) {
+ ERR_FAIL_COND_V(p_arr.size() < 1, false);
+ uint32_t size = p_arr[0];
+ ERR_FAIL_COND_V(size % 6, false);
+ ERR_FAIL_COND_V((uint32_t)p_arr.size() != size + 1, false);
+ infos.resize(size / 6);
+ int idx = 1;
+ for (uint32_t i = 0; i < size / 6; i++) {
+ infos.write[i].node = uint64_t(p_arr[idx]);
+ infos.write[i].node_path = p_arr[idx + 1];
+ infos.write[i].incoming_rpc = p_arr[idx + 2];
+ infos.write[i].incoming_size = p_arr[idx + 3];
+ infos.write[i].outgoing_rpc = p_arr[idx + 4];
+ infos.write[i].outgoing_size = p_arr[idx + 5];
+ idx += 6;
+ }
+ return true;
+}
+
+void MultiplayerDebugger::RPCProfiler::init_node(const ObjectID p_node) {
+ if (rpc_node_data.has(p_node)) {
+ return;
+ }
+ rpc_node_data.insert(p_node, RPCNodeInfo());
+ rpc_node_data[p_node].node = p_node;
+ rpc_node_data[p_node].node_path = Object::cast_to<Node>(ObjectDB::get_instance(p_node))->get_path();
+}
+
+void MultiplayerDebugger::RPCProfiler::toggle(bool p_enable, const Array &p_opts) {
+ rpc_node_data.clear();
+}
+
+void MultiplayerDebugger::RPCProfiler::add(const Array &p_data) {
+ ERR_FAIL_COND(p_data.size() != 3);
+ const String what = p_data[0];
+ const ObjectID id = p_data[1];
+ const int size = p_data[2];
+ init_node(id);
+ RPCNodeInfo &info = rpc_node_data[id];
+ if (what == "rpc_in") {
+ info.incoming_rpc++;
+ info.incoming_size += size;
+ } else if (what == "rpc_out") {
+ info.outgoing_rpc++;
+ info.outgoing_size += size;
+ }
+}
+
+void MultiplayerDebugger::RPCProfiler::tick(double p_frame_time, double p_process_time, double p_physics_time, double p_physics_frame_time) {
+ uint64_t pt = OS::get_singleton()->get_ticks_msec();
+ if (pt - last_profile_time > 100) {
+ last_profile_time = pt;
+ RPCFrame frame;
+ for (const KeyValue<ObjectID, RPCNodeInfo> &E : rpc_node_data) {
+ frame.infos.push_back(E.value);
+ }
+ rpc_node_data.clear();
+ EngineDebugger::get_singleton()->send_message("multiplayer:rpc", frame.serialize());
+ }
+}
+
+// ReplicationProfiler
+
+MultiplayerDebugger::SyncInfo::SyncInfo(MultiplayerSynchronizer *p_sync) {
+ ERR_FAIL_COND(!p_sync);
+ synchronizer = p_sync->get_instance_id();
+ if (p_sync->get_replication_config().is_valid()) {
+ config = p_sync->get_replication_config()->get_instance_id();
+ }
+ if (p_sync->get_root_node()) {
+ root_node = p_sync->get_root_node()->get_instance_id();
+ }
+}
+
+void MultiplayerDebugger::SyncInfo::write_to_array(Array &r_arr) const {
+ r_arr.push_back(synchronizer);
+ r_arr.push_back(config);
+ r_arr.push_back(root_node);
+ r_arr.push_back(incoming_syncs);
+ r_arr.push_back(incoming_size);
+ r_arr.push_back(outgoing_syncs);
+ r_arr.push_back(outgoing_size);
+}
+
+bool MultiplayerDebugger::SyncInfo::read_from_array(const Array &p_arr, int p_offset) {
+ ERR_FAIL_COND_V(p_arr.size() - p_offset < 7, false);
+ synchronizer = int64_t(p_arr[p_offset]);
+ config = int64_t(p_arr[p_offset + 1]);
+ root_node = int64_t(p_arr[p_offset + 2]);
+ incoming_syncs = p_arr[p_offset + 3];
+ incoming_size = p_arr[p_offset + 4];
+ outgoing_syncs = p_arr[p_offset + 5];
+ outgoing_size = p_arr[p_offset + 6];
+ return true;
+}
+
+Array MultiplayerDebugger::ReplicationFrame::serialize() {
+ Array arr;
+ arr.push_back(infos.size() * 7);
+ for (const KeyValue<ObjectID, SyncInfo> &E : infos) {
+ E.value.write_to_array(arr);
+ }
+ return arr;
+}
+
+bool MultiplayerDebugger::ReplicationFrame::deserialize(const Array &p_arr) {
+ ERR_FAIL_COND_V(p_arr.size() < 1, false);
+ uint32_t size = p_arr[0];
+ ERR_FAIL_COND_V(size % 7, false);
+ ERR_FAIL_COND_V((uint32_t)p_arr.size() != size + 1, false);
+ int idx = 1;
+ for (uint32_t i = 0; i < size / 7; i++) {
+ SyncInfo info;
+ if (!info.read_from_array(p_arr, idx)) {
+ return false;
+ }
+ infos[info.synchronizer] = info;
+ idx += 7;
+ }
+ return true;
+}
+
+void MultiplayerDebugger::ReplicationProfiler::toggle(bool p_enable, const Array &p_opts) {
+ sync_data.clear();
+}
+
+void MultiplayerDebugger::ReplicationProfiler::add(const Array &p_data) {
+ ERR_FAIL_COND(p_data.size() != 3);
+ const String what = p_data[0];
+ const ObjectID id = p_data[1];
+ const uint64_t size = p_data[2];
+ MultiplayerSynchronizer *sync = Object::cast_to<MultiplayerSynchronizer>(ObjectDB::get_instance(id));
+ ERR_FAIL_COND(!sync);
+ if (!sync_data.has(id)) {
+ sync_data[id] = SyncInfo(sync);
+ }
+ SyncInfo &info = sync_data[id];
+ if (what == "sync_in") {
+ info.incoming_syncs++;
+ info.incoming_size += size;
+ } else if (what == "sync_out") {
+ info.outgoing_syncs++;
+ info.outgoing_size += size;
+ }
+}
+
+void MultiplayerDebugger::ReplicationProfiler::tick(double p_frame_time, double p_process_time, double p_physics_time, double p_physics_frame_time) {
+ uint64_t pt = OS::get_singleton()->get_ticks_msec();
+ if (pt - last_profile_time > 100) {
+ last_profile_time = pt;
+ ReplicationFrame frame;
+ for (const KeyValue<ObjectID, SyncInfo> &E : sync_data) {
+ frame.infos[E.key] = E.value;
+ }
+ sync_data.clear();
+ EngineDebugger::get_singleton()->send_message("multiplayer:syncs", frame.serialize());
+ }
+}
diff --git a/modules/multiplayer/multiplayer_debugger.h b/modules/multiplayer/multiplayer_debugger.h
new file mode 100644
index 0000000000..f5c092f0f9
--- /dev/null
+++ b/modules/multiplayer/multiplayer_debugger.h
@@ -0,0 +1,134 @@
+/*************************************************************************/
+/* multiplayer_debugger.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_DEBUGGER_H
+#define MULTIPLAYER_DEBUGGER_H
+
+#include "core/debugger/engine_profiler.h"
+
+#include "core/os/os.h"
+
+class MultiplayerSynchronizer;
+
+class MultiplayerDebugger {
+public:
+ struct RPCNodeInfo {
+ ObjectID node;
+ String node_path;
+ int incoming_rpc = 0;
+ int incoming_size = 0;
+ int outgoing_rpc = 0;
+ int outgoing_size = 0;
+ };
+
+ struct RPCFrame {
+ Vector<RPCNodeInfo> infos;
+
+ Array serialize();
+ bool deserialize(const Array &p_arr);
+ };
+
+ struct SyncInfo {
+ ObjectID synchronizer;
+ ObjectID config;
+ ObjectID root_node;
+ int incoming_syncs = 0;
+ int incoming_size = 0;
+ int outgoing_syncs = 0;
+ int outgoing_size = 0;
+
+ void write_to_array(Array &r_arr) const;
+ bool read_from_array(const Array &p_arr, int p_offset);
+
+ SyncInfo() {}
+ SyncInfo(MultiplayerSynchronizer *p_sync);
+ };
+
+ struct ReplicationFrame {
+ HashMap<ObjectID, SyncInfo> infos;
+
+ Array serialize();
+ bool deserialize(const Array &p_arr);
+ };
+
+private:
+ class BandwidthProfiler : public EngineProfiler {
+ protected:
+ struct BandwidthFrame {
+ uint32_t timestamp;
+ int packet_size;
+ };
+
+ int bandwidth_in_ptr = 0;
+ Vector<BandwidthFrame> bandwidth_in;
+ int bandwidth_out_ptr = 0;
+ Vector<BandwidthFrame> bandwidth_out;
+ uint64_t last_bandwidth_time = 0;
+
+ int bandwidth_usage(const Vector<BandwidthFrame> &p_buffer, int p_pointer);
+
+ public:
+ void toggle(bool p_enable, const Array &p_opts);
+ void add(const Array &p_data);
+ void tick(double p_frame_time, double p_process_time, double p_physics_time, double p_physics_frame_time);
+ };
+
+ class RPCProfiler : public EngineProfiler {
+ private:
+ HashMap<ObjectID, RPCNodeInfo> rpc_node_data;
+ uint64_t last_profile_time = 0;
+
+ void init_node(const ObjectID p_node);
+
+ public:
+ void toggle(bool p_enable, const Array &p_opts);
+ void add(const Array &p_data);
+ void tick(double p_frame_time, double p_process_time, double p_physics_time, double p_physics_frame_time);
+ };
+
+ class ReplicationProfiler : public EngineProfiler {
+ private:
+ HashMap<ObjectID, SyncInfo> sync_data;
+ uint64_t last_profile_time = 0;
+
+ public:
+ void toggle(bool p_enable, const Array &p_opts);
+ void add(const Array &p_data);
+ void tick(double p_frame_time, double p_process_time, double p_physics_time, double p_physics_frame_time);
+ };
+
+ static Error _capture(void *p_user, const String &p_msg, const Array &p_args, bool &r_captured);
+
+public:
+ static void initialize();
+ static void deinitialize();
+};
+
+#endif // MULTIPLAYER_DEBUGGER_H
diff --git a/modules/multiplayer/register_types.cpp b/modules/multiplayer/register_types.cpp
index a2c524da80..ca85a46f31 100644
--- a/modules/multiplayer/register_types.cpp
+++ b/modules/multiplayer/register_types.cpp
@@ -36,9 +36,10 @@
#include "scene_replication_interface.h"
#include "scene_rpc_interface.h"
+#include "multiplayer_debugger.h"
+
#ifdef TOOLS_ENABLED
-#include "editor/editor_plugin.h"
-#include "editor/replication_editor_plugin.h"
+#include "editor/multiplayer_editor_plugin.h"
#endif
void initialize_multiplayer_module(ModuleInitializationLevel p_level) {
@@ -46,15 +47,18 @@ void initialize_multiplayer_module(ModuleInitializationLevel p_level) {
GDREGISTER_CLASS(SceneReplicationConfig);
GDREGISTER_CLASS(MultiplayerSpawner);
GDREGISTER_CLASS(MultiplayerSynchronizer);
+ GDREGISTER_CLASS(OfflineMultiplayerPeer);
GDREGISTER_CLASS(SceneMultiplayer);
MultiplayerAPI::set_default_interface("SceneMultiplayer");
+ MultiplayerDebugger::initialize();
}
#ifdef TOOLS_ENABLED
if (p_level == MODULE_INITIALIZATION_LEVEL_EDITOR) {
- EditorPlugins::add_by_type<ReplicationEditorPlugin>();
+ EditorPlugins::add_by_type<MultiplayerEditorPlugin>();
}
#endif
}
void uninitialize_multiplayer_module(ModuleInitializationLevel p_level) {
+ MultiplayerDebugger::deinitialize();
}
diff --git a/modules/multiplayer/scene_cache_interface.cpp b/modules/multiplayer/scene_cache_interface.cpp
index 7df9b95b30..f0da4f9dfc 100644
--- a/modules/multiplayer/scene_cache_interface.cpp
+++ b/modules/multiplayer/scene_cache_interface.cpp
@@ -99,10 +99,6 @@ void SceneCacheInterface::process_simplify_path(int p_from, const uint8_t *p_pac
Ref<MultiplayerPeer> multiplayer_peer = multiplayer->get_multiplayer_peer();
ERR_FAIL_COND(multiplayer_peer.is_null());
-#ifdef DEBUG_ENABLED
- multiplayer->profile_bandwidth("out", packet.size());
-#endif
-
multiplayer_peer->set_transfer_channel(0);
multiplayer_peer->set_transfer_mode(MultiplayerPeer::TRANSFER_MODE_RELIABLE);
multiplayer->send_command(p_from, packet.ptr(), packet.size());
@@ -155,10 +151,6 @@ Error SceneCacheInterface::_send_confirm_path(Node *p_node, NodePath p_path, Pat
Ref<MultiplayerPeer> multiplayer_peer = multiplayer->get_multiplayer_peer();
ERR_FAIL_COND_V(multiplayer_peer.is_null(), ERR_BUG);
-#ifdef DEBUG_ENABLED
- multiplayer->profile_bandwidth("out", packet.size() * p_peers.size());
-#endif
-
Error err = OK;
for (int peer_id : p_peers) {
multiplayer_peer->set_transfer_channel(0);
diff --git a/modules/multiplayer/scene_multiplayer.cpp b/modules/multiplayer/scene_multiplayer.cpp
index db7c5037cd..5042a0502d 100644
--- a/modules/multiplayer/scene_multiplayer.cpp
+++ b/modules/multiplayer/scene_multiplayer.cpp
@@ -40,13 +40,13 @@
#endif
#ifdef DEBUG_ENABLED
-void SceneMultiplayer::profile_bandwidth(const String &p_inout, int p_size) {
- if (EngineDebugger::is_profiling("multiplayer")) {
+_FORCE_INLINE_ void SceneMultiplayer::_profile_bandwidth(const String &p_what, int p_value) {
+ if (EngineDebugger::is_profiling("multiplayer:bandwidth")) {
Array values;
- values.push_back(p_inout);
+ values.push_back(p_what);
values.push_back(OS::get_singleton()->get_ticks_msec());
- values.push_back(p_size);
- EngineDebugger::profiler_add_frame_data("multiplayer", values);
+ values.push_back(p_value);
+ EngineDebugger::profiler_add_frame_data("multiplayer:bandwidth", values);
}
}
#endif
@@ -91,6 +91,10 @@ Error SceneMultiplayer::poll() {
Error err = multiplayer_peer->get_packet(&packet, len);
ERR_FAIL_COND_V_MSG(err != OK, err, vformat("Error getting packet! %d", err));
+#ifdef DEBUG_ENABLED
+ _profile_bandwidth("in", len);
+#endif
+
if (pending_peers.has(sender)) {
if (pending_peers[sender].local) {
// If the auth is over, admit the peer at the first packet.
@@ -220,10 +224,6 @@ void SceneMultiplayer::_process_packet(int p_from, const uint8_t *p_packet, int
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;
@@ -258,6 +258,13 @@ void SceneMultiplayer::_process_packet(int p_from, const uint8_t *p_packet, int
}
}
+#ifdef DEBUG_ENABLED
+_FORCE_INLINE_ Error SceneMultiplayer::_send(const uint8_t *p_packet, int p_packet_len) {
+ _profile_bandwidth("out", p_packet_len);
+ return multiplayer_peer->put_packet(p_packet, p_packet_len);
+}
+#endif
+
Error SceneMultiplayer::send_command(int p_to, const uint8_t *p_packet, int p_packet_len) {
if (server_relay && get_unique_id() != 1 && p_to != 1 && multiplayer_peer->is_server_relay_supported()) {
// Send relay packet.
@@ -268,19 +275,19 @@ Error SceneMultiplayer::send_command(int p_to, const uint8_t *p_packet, int p_pa
relay_buffer->put_data(p_packet, p_packet_len);
multiplayer_peer->set_target_peer(1);
const Vector<uint8_t> data = relay_buffer->get_data_array();
- return multiplayer_peer->put_packet(data.ptr(), relay_buffer->get_position());
+ return _send(data.ptr(), relay_buffer->get_position());
}
if (p_to > 0) {
ERR_FAIL_COND_V(!connected_peers.has(p_to), ERR_BUG);
multiplayer_peer->set_target_peer(p_to);
- return multiplayer_peer->put_packet(p_packet, p_packet_len);
+ return _send(p_packet, p_packet_len);
} else {
for (const int &pid : connected_peers) {
if (p_to && pid == -p_to) {
continue;
}
multiplayer_peer->set_target_peer(pid);
- multiplayer_peer->put_packet(p_packet, p_packet_len);
+ _send(p_packet, p_packet_len);
}
return OK;
}
@@ -319,7 +326,7 @@ void SceneMultiplayer::_process_sys(int p_from, const uint8_t *p_packet, int p_p
multiplayer_peer->set_transfer_channel(p_channel);
if (peer > 0) {
multiplayer_peer->set_target_peer(peer);
- multiplayer_peer->put_packet(data.ptr(), relay_buffer->get_position());
+ _send(data.ptr(), relay_buffer->get_position());
} else {
for (const int &P : connected_peers) {
// Not to sender, nor excluded.
@@ -327,7 +334,7 @@ void SceneMultiplayer::_process_sys(int p_from, const uint8_t *p_packet, int p_p
continue;
}
multiplayer_peer->set_target_peer(P);
- multiplayer_peer->put_packet(data.ptr(), relay_buffer->get_position());
+ _send(data.ptr(), relay_buffer->get_position());
}
}
if (peer == 0 || peer == -1) {
@@ -373,11 +380,11 @@ void SceneMultiplayer::_admit_peer(int p_id) {
// Send new peer to already connected.
encode_uint32(p_id, &buf[2]);
multiplayer_peer->set_target_peer(P);
- multiplayer_peer->put_packet(buf, sizeof(buf));
+ _send(buf, sizeof(buf));
// Send already connected to new peer.
encode_uint32(P, &buf[2]);
multiplayer_peer->set_target_peer(p_id);
- multiplayer_peer->put_packet(buf, sizeof(buf));
+ _send(buf, sizeof(buf));
}
}
@@ -412,7 +419,7 @@ void SceneMultiplayer::_del_peer(int p_id) {
continue;
}
multiplayer_peer->set_target_peer(P);
- multiplayer_peer->put_packet(buf, sizeof(buf));
+ _send(buf, sizeof(buf));
}
}
@@ -468,7 +475,7 @@ Error SceneMultiplayer::send_auth(int p_to, Vector<uint8_t> p_data) {
multiplayer_peer->set_target_peer(p_to);
multiplayer_peer->set_transfer_channel(0);
multiplayer_peer->set_transfer_mode(MultiplayerPeer::TRANSFER_MODE_RELIABLE);
- return multiplayer_peer->put_packet(packet_cache.ptr(), p_data.size() + 2);
+ return _send(packet_cache.ptr(), p_data.size() + 2);
}
Error SceneMultiplayer::complete_auth(int p_peer) {
@@ -478,7 +485,7 @@ Error SceneMultiplayer::complete_auth(int p_peer) {
pending_peers[p_peer].local = true;
// Notify the remote peer that the authentication has completed.
uint8_t buf[2] = { NETWORK_COMMAND_SYS, SYS_COMMAND_AUTH };
- Error err = multiplayer_peer->put_packet(buf, 2);
+ Error err = _send(buf, 2);
// The remote peer already reported the authentication as completed, so admit the peer.
// May generate new packets, so it must happen after sending confirmation.
if (pending_peers[p_peer].remote) {
@@ -654,6 +661,7 @@ SceneMultiplayer::SceneMultiplayer() {
replicator = Ref<SceneReplicationInterface>(memnew(SceneReplicationInterface(this)));
rpc = Ref<SceneRPCInterface>(memnew(SceneRPCInterface(this)));
cache = Ref<SceneCacheInterface>(memnew(SceneCacheInterface(this)));
+ set_multiplayer_peer(Ref<OfflineMultiplayerPeer>(memnew(OfflineMultiplayerPeer)));
}
SceneMultiplayer::~SceneMultiplayer() {
diff --git a/modules/multiplayer/scene_multiplayer.h b/modules/multiplayer/scene_multiplayer.h
index b0ecc48f8c..1a8de11f3f 100644
--- a/modules/multiplayer/scene_multiplayer.h
+++ b/modules/multiplayer/scene_multiplayer.h
@@ -37,6 +37,31 @@
#include "scene_replication_interface.h"
#include "scene_rpc_interface.h"
+class OfflineMultiplayerPeer : public MultiplayerPeer {
+ GDCLASS(OfflineMultiplayerPeer, MultiplayerPeer);
+
+public:
+ virtual int get_available_packet_count() const override { return 0; }
+ virtual Error get_packet(const uint8_t **r_buffer, int &r_buffer_size) override {
+ *r_buffer = nullptr;
+ r_buffer_size = 0;
+ return OK;
+ }
+ virtual Error put_packet(const uint8_t *p_buffer, int p_buffer_size) override { return OK; }
+ virtual int get_max_packet_size() const override { return 0; }
+
+ virtual void set_target_peer(int p_peer_id) override {}
+ virtual int get_packet_peer() const override { return 0; }
+ virtual TransferMode get_packet_mode() const override { return TRANSFER_MODE_RELIABLE; };
+ virtual int get_packet_channel() const override { return 0; }
+ virtual void disconnect_peer(int p_peer, bool p_force = false) override {}
+ virtual bool is_server() const override { return true; }
+ virtual void poll() override {}
+ virtual void close() override {}
+ virtual int get_unique_id() const override { return TARGET_PEER_SERVER; }
+ virtual ConnectionStatus get_connection_status() const override { return CONNECTION_CONNECTED; };
+};
+
class SceneMultiplayer : public MultiplayerAPI {
GDCLASS(SceneMultiplayer, MultiplayerAPI);
@@ -103,6 +128,15 @@ private:
Ref<SceneReplicationInterface> replicator;
Ref<SceneRPCInterface> rpc;
+#ifdef DEBUG_ENABLED
+ _FORCE_INLINE_ void _profile_bandwidth(const String &p_what, int p_value);
+ _FORCE_INLINE_ Error _send(const uint8_t *p_packet, int p_packet_len); // Also profiles.
+#else
+ _FORCE_INLINE_ Error _send(const uint8_t *p_packet, int p_packet_len) {
+ return multiplayer_peer->put_packet(p_packet, p_packet_len);
+ }
+#endif
+
protected:
static void _bind_methods();
@@ -162,10 +196,7 @@ public:
bool is_server_relay_enabled() const;
Ref<SceneCacheInterface> get_path_cache() { return cache; }
-
-#ifdef DEBUG_ENABLED
- void profile_bandwidth(const String &p_inout, int p_size);
-#endif
+ Ref<SceneReplicationInterface> get_replicator() { return replicator; }
SceneMultiplayer();
~SceneMultiplayer();
diff --git a/modules/multiplayer/scene_replication_interface.cpp b/modules/multiplayer/scene_replication_interface.cpp
index f1bab7327a..7d9437936a 100644
--- a/modules/multiplayer/scene_replication_interface.cpp
+++ b/modules/multiplayer/scene_replication_interface.cpp
@@ -32,6 +32,7 @@
#include "scene_multiplayer.h"
+#include "core/debugger/engine_debugger.h"
#include "core/io/marshalls.h"
#include "scene/main/node.h"
#include "scene/scene_string_names.h"
@@ -40,6 +41,18 @@
if (packet_cache.size() < m_amount) \
packet_cache.resize(m_amount);
+#ifdef DEBUG_ENABLED
+_FORCE_INLINE_ void SceneReplicationInterface::_profile_node_data(const String &p_what, ObjectID p_id, int p_size) {
+ if (EngineDebugger::is_profiling("multiplayer:replication")) {
+ Array values;
+ values.push_back(p_what);
+ values.push_back(p_id);
+ values.push_back(p_size);
+ EngineDebugger::profiler_add_frame_data("multiplayer:replication", values);
+ }
+}
+#endif
+
SceneReplicationInterface::TrackedNode &SceneReplicationInterface::_track(const ObjectID &p_id) {
if (!tracked_nodes.has(p_id)) {
tracked_nodes[p_id] = TrackedNode(p_id);
@@ -244,15 +257,54 @@ void SceneReplicationInterface::_visibility_changed(int p_peer, ObjectID p_sid)
Node *node = sync->get_root_node();
ERR_FAIL_COND(!node); // Bug.
const ObjectID oid = node->get_instance_id();
- if (spawned_nodes.has(oid)) {
+ if (spawned_nodes.has(oid) && p_peer != multiplayer->get_unique_id()) {
_update_spawn_visibility(p_peer, oid);
}
_update_sync_visibility(p_peer, sync);
}
+bool SceneReplicationInterface::is_rpc_visible(const ObjectID &p_oid, int p_peer) const {
+ if (!tracked_nodes.has(p_oid)) {
+ return true; // Untracked nodes are always visible to RPCs.
+ }
+ ERR_FAIL_COND_V(p_peer < 0, false);
+ const TrackedNode &tnode = tracked_nodes[p_oid];
+ if (tnode.synchronizers.is_empty()) {
+ return true; // No synchronizers means no visibility restrictions.
+ }
+ if (tnode.remote_peer && uint32_t(p_peer) == tnode.remote_peer) {
+ return true; // RPCs on spawned nodes are always visible to spawner.
+ } else if (spawned_nodes.has(p_oid)) {
+ // It's a spwaned node we control, this can be fast
+ if (p_peer) {
+ return peers_info.has(p_peer) && peers_info[p_peer].spawn_nodes.has(p_oid);
+ } else {
+ for (const KeyValue<int, PeerInfo> &E : peers_info) {
+ if (!E.value.spawn_nodes.has(p_oid)) {
+ return false; // Not public.
+ }
+ }
+ return true; // All peers have this node.
+ }
+ } else {
+ // Cycle object synchronizers to check visibility.
+ for (const ObjectID &sid : tnode.synchronizers) {
+ MultiplayerSynchronizer *sync = get_id_as<MultiplayerSynchronizer>(sid);
+ ERR_CONTINUE(!sync);
+ // RPC visibility is composed using OR when multiple synchronizers are present.
+ // Note that we don't really care about authority here which may lead to unexpected
+ // results when using multiple synchronizers to control the same node.
+ if (sync->is_visible_to(p_peer)) {
+ return true;
+ }
+ }
+ return false; // Not visible.
+ }
+}
+
Error SceneReplicationInterface::_update_sync_visibility(int p_peer, MultiplayerSynchronizer *p_sync) {
ERR_FAIL_COND_V(!p_sync, ERR_BUG);
- if (!multiplayer->has_multiplayer_peer() || !p_sync->is_multiplayer_authority()) {
+ if (!multiplayer->has_multiplayer_peer() || !p_sync->is_multiplayer_authority() || p_peer == multiplayer->get_unique_id()) {
return OK;
}
@@ -362,13 +414,8 @@ Error SceneReplicationInterface::_update_spawn_visibility(int p_peer, const Obje
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);
ERR_FAIL_COND_V(!multiplayer->has_multiplayer_peer(), ERR_UNCONFIGURED);
-#ifdef DEBUG_ENABLED
- multiplayer->profile_bandwidth("out", p_size);
-#endif
-
Ref<MultiplayerPeer> peer = multiplayer->get_multiplayer_peer();
peer->set_transfer_channel(0);
peer->set_transfer_mode(p_reliable ? MultiplayerPeer::TRANSFER_MODE_RELIABLE : MultiplayerPeer::TRANSFER_MODE_UNRELIABLE);
@@ -640,6 +687,9 @@ void SceneReplicationInterface::_send_sync(int p_peer, const HashSet<ObjectID> p
MultiplayerAPI::encode_and_compress_variants(varp.ptrw(), varp.size(), &ptr[ofs], size);
ofs += size;
}
+#ifdef DEBUG_ENABLED
+ _profile_node_data("sync_out", oid, size);
+#endif
}
if (ofs > 3) {
// Got some left over to send.
@@ -687,6 +737,9 @@ Error SceneReplicationInterface::on_sync_receive(int p_from, const uint8_t *p_bu
err = MultiplayerSynchronizer::set_state(props, node, vars);
ERR_FAIL_COND_V(err, err);
ofs += size;
+#ifdef DEBUG_ENABLED
+ _profile_node_data("sync_in", sync->get_instance_id(), size);
+#endif
}
return OK;
}
diff --git a/modules/multiplayer/scene_replication_interface.h b/modules/multiplayer/scene_replication_interface.h
index c8bd96eb87..30d58f7129 100644
--- a/modules/multiplayer/scene_replication_interface.h
+++ b/modules/multiplayer/scene_replication_interface.h
@@ -105,6 +105,10 @@ private:
return p_id.is_valid() ? Object::cast_to<T>(ObjectDB::get_instance(p_id)) : nullptr;
}
+#ifdef DEBUG_ENABLED
+ _FORCE_INLINE_ void _profile_node_data(const String &p_what, ObjectID p_id, int p_size);
+#endif
+
public:
static void make_default();
@@ -121,6 +125,8 @@ public:
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);
+ bool is_rpc_visible(const ObjectID &p_oid, int p_peer) const;
+
SceneReplicationInterface(SceneMultiplayer *p_multiplayer) {
multiplayer = p_multiplayer;
}
diff --git a/modules/multiplayer/scene_rpc_interface.cpp b/modules/multiplayer/scene_rpc_interface.cpp
index acc113c901..a7e29dfcc7 100644
--- a/modules/multiplayer/scene_rpc_interface.cpp
+++ b/modules/multiplayer/scene_rpc_interface.cpp
@@ -52,16 +52,15 @@
#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) {
- if (EngineDebugger::is_profiling("rpc")) {
+_FORCE_INLINE_ void SceneRPCInterface::_profile_node_data(const String &p_what, ObjectID p_id, int p_size) {
+ if (EngineDebugger::is_profiling("multiplayer:rpc")) {
Array values;
- values.push_back(p_id);
values.push_back(p_what);
- EngineDebugger::profiler_add_frame_data("rpc", values);
+ values.push_back(p_id);
+ values.push_back(p_size);
+ EngineDebugger::profiler_add_frame_data("multiplayer:rpc", values);
}
}
-#else
-_FORCE_INLINE_ void SceneRPCInterface::_profile_node_data(const String &p_what, ObjectID p_id) {}
#endif
// Returns the packet size stripping the node path added when the node is not yet cached.
@@ -83,7 +82,7 @@ void SceneRPCInterface::_parse_rpc_config(const Variant &p_config, bool p_for_no
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);
+ ERR_CONTINUE(names[i].get_type() != Variant::STRING && names[i].get_type() != Variant::STRING_NAME);
String name = names[i].operator String();
ERR_CONTINUE(config[name].get_type() != Variant::DICTIONARY);
ERR_CONTINUE(!config[name].operator Dictionary().has("rpc_mode"));
@@ -277,7 +276,7 @@ void SceneRPCInterface::_process_rpc(Node *p_node, const uint16_t p_rpc_method_i
argp.resize(argc);
#ifdef DEBUG_ENABLED
- _profile_node_data("rpc_in", p_node->get_instance_id());
+ _profile_node_data("rpc_in", p_node->get_instance_id(), p_packet_len);
#endif
int out;
@@ -296,7 +295,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 RPCConfig &p_config, const StringName &p_name, const Variant **p_arg, int p_argcount) {
+void SceneRPCInterface::_send_rpc(Node *p_node, 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.");
@@ -312,12 +311,35 @@ void SceneRPCInterface::_send_rpc(Node *p_from, int p_to, uint16_t p_rpc_id, con
ERR_FAIL_MSG("Attempt to call RPC with unknown peer ID: " + itos(p_to) + ".");
}
- // See if all peers have cached path (if so, call can be fast).
- int psc_id;
- const bool has_all_peers = multiplayer->get_path_cache()->send_object_cache(p_from, p_to, psc_id);
+ // See if all peers have cached path (if so, call can be fast) while building the RPC target list.
+ HashSet<int> targets;
+ Ref<SceneCacheInterface> cache = multiplayer->get_path_cache();
+ int psc_id = -1;
+ bool has_all_peers = true;
+ const ObjectID oid = p_node->get_instance_id();
+ if (p_to > 0) {
+ ERR_FAIL_COND_MSG(!multiplayer->get_replicator()->is_rpc_visible(oid, p_to), "Attempt to call an RPC to a peer that cannot see this node. Peer ID: " + itos(p_to));
+ targets.insert(p_to);
+ has_all_peers = cache->send_object_cache(p_node, p_to, psc_id);
+ } else {
+ bool restricted = !multiplayer->get_replicator()->is_rpc_visible(oid, 0);
+ for (const int &P : multiplayer->get_connected_peers()) {
+ if (p_to < 0 && P == -p_to) {
+ continue; // Excluded peer.
+ }
+ if (restricted && !multiplayer->get_replicator()->is_rpc_visible(oid, P)) {
+ continue; // Not visible to this peer.
+ }
+ targets.insert(P);
+ bool has_peer = cache->send_object_cache(p_node, P, psc_id);
+ has_all_peers = has_all_peers && has_peer;
+ }
+ }
+ if (targets.is_empty()) {
+ return; // No one in sight.
+ }
// Create base packet, lots of hardcode because it must be tight.
-
int ofs = 0;
#define MAKE_ROOM(m_amount) \
@@ -399,20 +421,21 @@ void SceneRPCInterface::_send_rpc(Node *p_from, int p_to, uint16_t p_rpc_id, con
ERR_FAIL_COND(node_id_compression > 3);
ERR_FAIL_COND(name_id_compression > 1);
- // We can now set the meta
- packet_cache.write[0] = command_type + (node_id_compression << NODE_ID_COMPRESSION_SHIFT) + (name_id_compression << NAME_ID_COMPRESSION_SHIFT) + (byte_only_or_no_args ? BYTE_ONLY_OR_NO_ARGS_FLAG : 0);
-
#ifdef DEBUG_ENABLED
- multiplayer->profile_bandwidth("out", ofs);
+ _profile_node_data("rpc_out", p_node->get_instance_id(), ofs);
#endif
+ // We can now set the meta
+ packet_cache.write[0] = command_type + (node_id_compression << NODE_ID_COMPRESSION_SHIFT) + (name_id_compression << NAME_ID_COMPRESSION_SHIFT) + (byte_only_or_no_args ? BYTE_ONLY_OR_NO_ARGS_FLAG : 0);
+
// Take chance and set transfer mode, since all send methods will use it.
peer->set_transfer_channel(p_config.channel);
peer->set_transfer_mode(p_config.transfer_mode);
if (has_all_peers) {
- // They all have verified paths, so send fast.
- multiplayer->send_command(p_to, packet_cache.ptr(), ofs);
+ for (const int P : targets) {
+ multiplayer->send_command(P, packet_cache.ptr(), ofs);
+ }
} else {
// Unreachable because the node ID is never compressed if the peers doesn't know it.
CRASH_COND(node_id_compression != NETWORK_NODE_ID_COMPRESSION_32);
@@ -420,23 +443,15 @@ 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());
+ NodePath from_path = multiplayer->get_root_path().rel_path_to(p_node->get_path());
CharString pname = String(from_path).utf8();
int path_len = encode_cstring(pname.get_data(), nullptr);
MAKE_ROOM(ofs + path_len);
encode_cstring(pname.get_data(), &(packet_cache.write[ofs]));
- for (const int &P : multiplayer->get_connected_peers()) {
- if (p_to < 0 && P == -p_to) {
- continue; // Continue, excluded.
- }
-
- if (p_to > 0 && P != p_to) {
- continue; // Continue, not for this peer.
- }
-
+ // Not all verified path, so check which needs the longer packet.
+ for (const int P : targets) {
bool confirmed = multiplayer->get_path_cache()->is_cache_confirmed(from_path, P);
-
if (confirmed) {
// This one confirmed path, so use id.
encode_uint32(psc_id, &(packet_cache.write[1]));
@@ -477,10 +492,6 @@ Error SceneRPCInterface::rpcp(Object *p_obj, int p_peer_id, const StringName &p_
}
if (p_peer_id != caller_id) {
-#ifdef DEBUG_ENABLED
- _profile_node_data("rpc_out", node->get_instance_id());
-#endif
-
_send_rpc(node, p_peer_id, rpc_id, config, p_method, p_arg, p_argcount);
}
diff --git a/modules/multiplayer/scene_rpc_interface.h b/modules/multiplayer/scene_rpc_interface.h
index aa9be525a2..800293714c 100644
--- a/modules/multiplayer/scene_rpc_interface.h
+++ b/modules/multiplayer/scene_rpc_interface.h
@@ -81,8 +81,11 @@ private:
HashMap<ObjectID, RPCConfigCache> rpc_cache;
+#ifdef DEBUG_ENABLED
+ _FORCE_INLINE_ void _profile_node_data(const String &p_what, ObjectID p_id, int p_size);
+#endif
+
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 RPCConfig &p_config, const StringName &p_name, const Variant **p_arg, int p_argcount);
diff --git a/modules/navigation/editor/navigation_mesh_editor_plugin.h b/modules/navigation/editor/navigation_mesh_editor_plugin.h
index bc9e4185b7..b7bde98131 100644
--- a/modules/navigation/editor/navigation_mesh_editor_plugin.h
+++ b/modules/navigation/editor/navigation_mesh_editor_plugin.h
@@ -35,6 +35,8 @@
#include "editor/editor_plugin.h"
+class AcceptDialog;
+class HBoxContainer;
class NavigationRegion3D;
class NavigationMeshEditor : public Control {
diff --git a/modules/navigation/godot_navigation_server.cpp b/modules/navigation/godot_navigation_server.cpp
index 8ca73a3adb..58a0982425 100644
--- a/modules/navigation/godot_navigation_server.cpp
+++ b/modules/navigation/godot_navigation_server.cpp
@@ -36,6 +36,8 @@
#include "navigation_mesh_generator.h"
#endif
+using namespace NavigationUtilities;
+
/// Creates a struct for each function and a function that once called creates
/// an instance of that struct with the submitted parameters.
/// Then, that struct is stored in an array; the `sync` function consume that array.
@@ -228,7 +230,7 @@ Vector<Vector3> GodotNavigationServer::map_get_path(RID p_map, Vector3 p_origin,
const NavMap *map = map_owner.get_or_null(p_map);
ERR_FAIL_COND_V(map == nullptr, Vector<Vector3>());
- return map->get_path(p_origin, p_destination, p_optimize, p_navigation_layers);
+ return map->get_path(p_origin, p_destination, p_optimize, p_navigation_layers, nullptr, nullptr, nullptr);
}
Vector3 GodotNavigationServer::map_get_closest_point_to_segment(RID p_map, const Vector3 &p_from, const Vector3 &p_to, const bool p_use_collision) const {
@@ -383,6 +385,20 @@ real_t GodotNavigationServer::region_get_travel_cost(RID p_region) const {
return region->get_travel_cost();
}
+COMMAND_2(region_set_owner_id, RID, p_region, ObjectID, p_owner_id) {
+ NavRegion *region = region_owner.get_or_null(p_region);
+ ERR_FAIL_COND(region == nullptr);
+
+ region->set_owner_id(p_owner_id);
+}
+
+ObjectID GodotNavigationServer::region_get_owner_id(RID p_region) const {
+ const NavRegion *region = region_owner.get_or_null(p_region);
+ ERR_FAIL_COND_V(region == nullptr, ObjectID());
+
+ return region->get_owner_id();
+}
+
bool GodotNavigationServer::region_owns_point(RID p_region, const Vector3 &p_point) const {
const NavRegion *region = region_owner.get_or_null(p_region);
ERR_FAIL_COND_V(region == nullptr, false);
@@ -407,20 +423,20 @@ uint32_t GodotNavigationServer::region_get_navigation_layers(RID p_region) const
return region->get_navigation_layers();
}
-COMMAND_2(region_set_navmesh, RID, p_region, Ref<NavigationMesh>, p_nav_mesh) {
+COMMAND_2(region_set_navigation_mesh, RID, p_region, Ref<NavigationMesh>, p_navigation_mesh) {
NavRegion *region = region_owner.get_or_null(p_region);
ERR_FAIL_COND(region == nullptr);
- region->set_mesh(p_nav_mesh);
+ region->set_mesh(p_navigation_mesh);
}
-void GodotNavigationServer::region_bake_navmesh(Ref<NavigationMesh> r_mesh, Node *p_node) const {
- ERR_FAIL_COND(r_mesh.is_null());
- ERR_FAIL_COND(p_node == nullptr);
+void GodotNavigationServer::region_bake_navigation_mesh(Ref<NavigationMesh> p_navigation_mesh, Node *p_root_node) const {
+ ERR_FAIL_COND(p_navigation_mesh.is_null());
+ ERR_FAIL_COND(p_root_node == nullptr);
#ifndef _3D_DISABLED
- NavigationMeshGenerator::get_singleton()->clear(r_mesh);
- NavigationMeshGenerator::get_singleton()->bake(r_mesh, p_node);
+ NavigationMeshGenerator::get_singleton()->clear(p_navigation_mesh);
+ NavigationMeshGenerator::get_singleton()->bake(p_navigation_mesh, p_root_node);
#endif
}
@@ -570,6 +586,20 @@ real_t GodotNavigationServer::link_get_travel_cost(const RID p_link) const {
return link->get_travel_cost();
}
+COMMAND_2(link_set_owner_id, RID, p_link, ObjectID, p_owner_id) {
+ NavLink *link = link_owner.get_or_null(p_link);
+ ERR_FAIL_COND(link == nullptr);
+
+ link->set_owner_id(p_owner_id);
+}
+
+ObjectID GodotNavigationServer::link_get_owner_id(RID p_link) const {
+ const NavLink *link = link_owner.get_or_null(p_link);
+ ERR_FAIL_COND_V(link == nullptr, ObjectID());
+
+ return link->get_owner_id();
+}
+
RID GodotNavigationServer::agent_create() const {
GodotNavigationServer *mut_this = const_cast<GodotNavigationServer *>(this);
MutexLock lock(mut_this->operations_mutex);
@@ -676,14 +706,14 @@ bool GodotNavigationServer::agent_is_map_changed(RID p_agent) const {
return agent->is_map_changed();
}
-COMMAND_4(agent_set_callback, RID, p_agent, Object *, p_receiver, StringName, p_method, Variant, p_udata) {
+COMMAND_4(agent_set_callback, RID, p_agent, ObjectID, p_object_id, StringName, p_method, Variant, p_udata) {
RvoAgent *agent = agent_owner.get_or_null(p_agent);
ERR_FAIL_COND(agent == nullptr);
- agent->set_callback(p_receiver == nullptr ? ObjectID() : p_receiver->get_instance_id(), p_method, p_udata);
+ agent->set_callback(p_object_id, p_method, p_udata);
if (agent->get_map()) {
- if (p_receiver == nullptr) {
+ if (p_object_id == ObjectID()) {
agent->get_map()->remove_agent_as_controlled(agent);
} else {
agent->get_map()->set_agent_as_controlled(agent);
@@ -810,20 +840,34 @@ void GodotNavigationServer::process(real_t p_delta_time) {
}
}
-NavigationUtilities::PathQueryResult GodotNavigationServer::_query_path(const NavigationUtilities::PathQueryParameters &p_parameters) const {
- NavigationUtilities::PathQueryResult r_query_result;
+PathQueryResult GodotNavigationServer::_query_path(const PathQueryParameters &p_parameters) const {
+ PathQueryResult r_query_result;
const NavMap *map = map_owner.get_or_null(p_parameters.map);
ERR_FAIL_COND_V(map == nullptr, r_query_result);
// run the pathfinding
- if (p_parameters.pathfinding_algorithm == NavigationUtilities::PathfindingAlgorithm::PATHFINDING_ALGORITHM_ASTAR) {
+ if (p_parameters.pathfinding_algorithm == PathfindingAlgorithm::PATHFINDING_ALGORITHM_ASTAR) {
// while postprocessing is still part of map.get_path() need to check and route it here for the correct "optimize" post-processing
- if (p_parameters.path_postprocessing == NavigationUtilities::PathPostProcessing::PATH_POSTPROCESSING_CORRIDORFUNNEL) {
- r_query_result.path = map->get_path(p_parameters.start_position, p_parameters.target_position, true, p_parameters.navigation_layers);
- } else if (p_parameters.path_postprocessing == NavigationUtilities::PathPostProcessing::PATH_POSTPROCESSING_EDGECENTERED) {
- r_query_result.path = map->get_path(p_parameters.start_position, p_parameters.target_position, false, p_parameters.navigation_layers);
+ if (p_parameters.path_postprocessing == PathPostProcessing::PATH_POSTPROCESSING_CORRIDORFUNNEL) {
+ r_query_result.path = map->get_path(
+ p_parameters.start_position,
+ p_parameters.target_position,
+ true,
+ p_parameters.navigation_layers,
+ p_parameters.metadata_flags.has_flag(PathMetadataFlags::PATH_INCLUDE_TYPES) ? &r_query_result.path_types : nullptr,
+ p_parameters.metadata_flags.has_flag(PathMetadataFlags::PATH_INCLUDE_RIDS) ? &r_query_result.path_rids : nullptr,
+ p_parameters.metadata_flags.has_flag(PathMetadataFlags::PATH_INCLUDE_OWNERS) ? &r_query_result.path_owner_ids : nullptr);
+ } else if (p_parameters.path_postprocessing == PathPostProcessing::PATH_POSTPROCESSING_EDGECENTERED) {
+ r_query_result.path = map->get_path(
+ p_parameters.start_position,
+ p_parameters.target_position,
+ false,
+ p_parameters.navigation_layers,
+ p_parameters.metadata_flags.has_flag(PathMetadataFlags::PATH_INCLUDE_TYPES) ? &r_query_result.path_types : nullptr,
+ p_parameters.metadata_flags.has_flag(PathMetadataFlags::PATH_INCLUDE_RIDS) ? &r_query_result.path_rids : nullptr,
+ p_parameters.metadata_flags.has_flag(PathMetadataFlags::PATH_INCLUDE_OWNERS) ? &r_query_result.path_owner_ids : nullptr);
}
} else {
return r_query_result;
diff --git a/modules/navigation/godot_navigation_server.h b/modules/navigation/godot_navigation_server.h
index ab5e722d35..6f39420c67 100644
--- a/modules/navigation/godot_navigation_server.h
+++ b/modules/navigation/godot_navigation_server.h
@@ -125,6 +125,9 @@ public:
COMMAND_2(region_set_travel_cost, RID, p_region, real_t, p_travel_cost);
virtual real_t region_get_travel_cost(RID p_region) const override;
+ COMMAND_2(region_set_owner_id, RID, p_region, ObjectID, p_owner_id);
+ virtual ObjectID region_get_owner_id(RID p_region) const override;
+
virtual bool region_owns_point(RID p_region, const Vector3 &p_point) const override;
COMMAND_2(region_set_map, RID, p_region, RID, p_map);
@@ -132,8 +135,8 @@ public:
COMMAND_2(region_set_navigation_layers, RID, p_region, uint32_t, p_navigation_layers);
virtual uint32_t region_get_navigation_layers(RID p_region) const override;
COMMAND_2(region_set_transform, RID, p_region, Transform3D, p_transform);
- COMMAND_2(region_set_navmesh, RID, p_region, Ref<NavigationMesh>, p_nav_mesh);
- virtual void region_bake_navmesh(Ref<NavigationMesh> r_mesh, Node *p_node) const override;
+ COMMAND_2(region_set_navigation_mesh, RID, p_region, Ref<NavigationMesh>, p_navigation_mesh);
+ virtual void region_bake_navigation_mesh(Ref<NavigationMesh> p_navigation_mesh, Node *p_root_node) const override;
virtual int region_get_connections_count(RID p_region) const override;
virtual Vector3 region_get_connection_pathway_start(RID p_region, int p_connection_id) const override;
virtual Vector3 region_get_connection_pathway_end(RID p_region, int p_connection_id) const override;
@@ -153,6 +156,8 @@ public:
virtual real_t link_get_enter_cost(RID p_link) const override;
COMMAND_2(link_set_travel_cost, RID, p_link, real_t, p_travel_cost);
virtual real_t link_get_travel_cost(RID p_link) const override;
+ COMMAND_2(link_set_owner_id, RID, p_link, ObjectID, p_owner_id);
+ virtual ObjectID link_get_owner_id(RID p_link) const override;
virtual RID agent_create() const override;
COMMAND_2(agent_set_map, RID, p_agent, RID, p_map);
@@ -167,7 +172,7 @@ public:
COMMAND_2(agent_set_position, RID, p_agent, Vector3, p_position);
COMMAND_2(agent_set_ignore_y, RID, p_agent, bool, p_ignore);
virtual bool agent_is_map_changed(RID p_agent) const override;
- COMMAND_4_DEF(agent_set_callback, RID, p_agent, Object *, p_receiver, StringName, p_method, Variant, p_udata, Variant());
+ COMMAND_4_DEF(agent_set_callback, RID, p_agent, ObjectID, p_object_id, StringName, p_method, Variant, p_udata, Variant());
COMMAND_1(free, RID, p_object);
diff --git a/modules/navigation/nav_base.h b/modules/navigation/nav_base.h
index 6dfaaf9af4..a3ab77301b 100644
--- a/modules/navigation/nav_base.h
+++ b/modules/navigation/nav_base.h
@@ -33,6 +33,7 @@
#include "nav_rid.h"
#include "nav_utils.h"
+#include "servers/navigation/navigation_utilities.h"
class NavMap;
@@ -41,8 +42,12 @@ protected:
uint32_t navigation_layers = 1;
float enter_cost = 0.0;
float travel_cost = 1.0;
+ ObjectID owner_id;
+ NavigationUtilities::PathSegmentType type;
public:
+ NavigationUtilities::PathSegmentType get_type() const { return type; }
+
void set_navigation_layers(uint32_t p_navigation_layers) { navigation_layers = p_navigation_layers; }
uint32_t get_navigation_layers() const { return navigation_layers; }
@@ -51,6 +56,9 @@ public:
void set_travel_cost(float p_travel_cost) { travel_cost = MAX(p_travel_cost, 0.0); }
float get_travel_cost() const { return travel_cost; }
+
+ void set_owner_id(ObjectID p_owner_id) { owner_id = p_owner_id; }
+ ObjectID get_owner_id() const { return owner_id; }
};
#endif // NAV_BASE_H
diff --git a/modules/navigation/nav_link.h b/modules/navigation/nav_link.h
index 8d57f076c0..e9c69286f9 100644
--- a/modules/navigation/nav_link.h
+++ b/modules/navigation/nav_link.h
@@ -37,12 +37,16 @@
class NavLink : public NavBase {
NavMap *map = nullptr;
bool bidirectional = true;
- Vector3 start_location = Vector3();
- Vector3 end_location = Vector3();
+ Vector3 start_location;
+ Vector3 end_location;
bool link_dirty = true;
public:
+ NavLink() {
+ type = NavigationUtilities::PathSegmentType::PATH_SEGMENT_TYPE_LINK;
+ }
+
void set_map(NavMap *p_map);
NavMap *get_map() const {
return map;
diff --git a/modules/navigation/nav_map.cpp b/modules/navigation/nav_map.cpp
index 83862e1e34..8d58c9335d 100644
--- a/modules/navigation/nav_map.cpp
+++ b/modules/navigation/nav_map.cpp
@@ -38,6 +38,18 @@
#define THREE_POINTS_CROSS_PRODUCT(m_a, m_b, m_c) (((m_c) - (m_a)).cross((m_b) - (m_a)))
+// Helper macro
+#define APPEND_METADATA(poly) \
+ if (r_path_types) { \
+ r_path_types->push_back(poly->owner->get_type()); \
+ } \
+ if (r_path_rids) { \
+ r_path_rids->push_back(poly->owner->get_self()); \
+ } \
+ if (r_path_owners) { \
+ r_path_owners->push_back(poly->owner->get_owner_id()); \
+ }
+
void NavMap::set_up(Vector3 p_up) {
up = p_up;
regenerate_polygons = true;
@@ -71,7 +83,18 @@ gd::PointKey NavMap::get_point_key(const Vector3 &p_pos) const {
return p;
}
-Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p_optimize, uint32_t p_navigation_layers) const {
+Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p_optimize, uint32_t p_navigation_layers, Vector<int32_t> *r_path_types, TypedArray<RID> *r_path_rids, Vector<int64_t> *r_path_owners) const {
+ // Clear metadata outputs.
+ if (r_path_types) {
+ r_path_types->clear();
+ }
+ if (r_path_rids) {
+ r_path_rids->clear();
+ }
+ if (r_path_owners) {
+ r_path_owners->clear();
+ }
+
// Find the start poly and the end poly on this map.
const gd::Polygon *begin_poly = nullptr;
const gd::Polygon *end_poly = nullptr;
@@ -115,6 +138,24 @@ Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p
return Vector<Vector3>();
}
if (begin_poly == end_poly) {
+ if (r_path_types) {
+ r_path_types->resize(2);
+ r_path_types->write[0] = begin_poly->owner->get_type();
+ r_path_types->write[1] = end_poly->owner->get_type();
+ }
+
+ if (r_path_rids) {
+ r_path_rids->resize(2);
+ (*r_path_rids)[0] = begin_poly->owner->get_self();
+ (*r_path_rids)[1] = end_poly->owner->get_self();
+ }
+
+ if (r_path_owners) {
+ r_path_owners->resize(2);
+ r_path_owners->write[0] = begin_poly->owner->get_owner_id();
+ r_path_owners->write[1] = end_poly->owner->get_owner_id();
+ }
+
Vector<Vector3> path;
path.resize(2);
path.write[0] = begin_point;
@@ -296,6 +337,7 @@ Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p
gd::NavigationPoly *p = apex_poly;
path.push_back(end_point);
+ APPEND_METADATA(end_poly);
while (p) {
// Set left and right points of the pathway between polygons.
@@ -312,7 +354,7 @@ Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p
left_poly = p;
left_portal = left;
} else {
- clip_path(navigation_polys, path, apex_poly, right_portal, right_poly);
+ clip_path(navigation_polys, path, apex_poly, right_portal, right_poly, r_path_types, r_path_rids, r_path_owners);
apex_point = right_portal;
p = right_poly;
@@ -320,7 +362,9 @@ Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p
apex_poly = p;
left_portal = apex_point;
right_portal = apex_point;
+
path.push_back(apex_point);
+ APPEND_METADATA(apex_poly->poly);
skip = true;
}
}
@@ -331,7 +375,7 @@ Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p
right_poly = p;
right_portal = right;
} else {
- clip_path(navigation_polys, path, apex_poly, left_portal, left_poly);
+ clip_path(navigation_polys, path, apex_poly, left_portal, left_poly, r_path_types, r_path_rids, r_path_owners);
apex_point = left_portal;
p = left_poly;
@@ -339,7 +383,9 @@ Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p
apex_poly = p;
right_portal = apex_point;
left_portal = apex_point;
+
path.push_back(apex_point);
+ APPEND_METADATA(apex_poly->poly);
}
}
@@ -355,12 +401,23 @@ Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p
// If the last point is not the begin point, add it to the list.
if (path[path.size() - 1] != begin_point) {
path.push_back(begin_point);
+ APPEND_METADATA(begin_poly);
}
path.reverse();
+ if (r_path_types) {
+ r_path_types->reverse();
+ }
+ if (r_path_rids) {
+ r_path_rids->reverse();
+ }
+ if (r_path_owners) {
+ r_path_owners->reverse();
+ }
} else {
path.push_back(end_point);
+ APPEND_METADATA(end_poly);
// Add mid points
int np_id = least_cost_id;
@@ -369,18 +426,37 @@ Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p
int prev = navigation_polys[np_id].back_navigation_edge;
int prev_n = (navigation_polys[np_id].back_navigation_edge + 1) % navigation_polys[np_id].poly->points.size();
Vector3 point = (navigation_polys[np_id].poly->points[prev].pos + navigation_polys[np_id].poly->points[prev_n].pos) * 0.5;
+
path.push_back(point);
+ APPEND_METADATA(navigation_polys[np_id].poly);
} else {
path.push_back(navigation_polys[np_id].entry);
+ APPEND_METADATA(navigation_polys[np_id].poly);
}
np_id = navigation_polys[np_id].back_navigation_poly_id;
}
path.push_back(begin_point);
+ APPEND_METADATA(begin_poly);
+
path.reverse();
+ if (r_path_types) {
+ r_path_types->reverse();
+ }
+ if (r_path_rids) {
+ r_path_rids->reverse();
+ }
+ if (r_path_owners) {
+ r_path_owners->reverse();
+ }
}
+ // Ensure post conditions (path arrays MUST match in size).
+ CRASH_COND(r_path_types && path.size() != r_path_types->size());
+ CRASH_COND(r_path_rids && path.size() != r_path_rids->size());
+ CRASH_COND(r_path_owners && path.size() != r_path_owners->size());
+
return path;
}
@@ -837,7 +913,7 @@ void NavMap::dispatch_callbacks() {
}
}
-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 {
+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, Vector<int32_t> *r_path_types, TypedArray<RID> *r_path_rids, Vector<int64_t> *r_path_owners) const {
Vector3 from = path[path.size() - 1];
if (from.is_equal_approx(p_to_point)) {
@@ -863,6 +939,7 @@ void NavMap::clip_path(const LocalVector<gd::NavigationPoly> &p_navigation_polys
if (cut_plane.intersects_segment(pathway_start, pathway_end, &inters)) {
if (!inters.is_equal_approx(p_to_point) && !inters.is_equal_approx(path[path.size() - 1])) {
path.push_back(inters);
+ APPEND_METADATA(from_poly->poly);
}
}
}
diff --git a/modules/navigation/nav_map.h b/modules/navigation/nav_map.h
index a3da9fa727..3be13133d2 100644
--- a/modules/navigation/nav_map.h
+++ b/modules/navigation/nav_map.h
@@ -115,7 +115,7 @@ public:
gd::PointKey get_point_key(const Vector3 &p_pos) const;
- Vector<Vector3> get_path(Vector3 p_origin, Vector3 p_destination, bool p_optimize, uint32_t p_navigation_layers = 1) const;
+ Vector<Vector3> get_path(Vector3 p_origin, Vector3 p_destination, bool p_optimize, uint32_t p_navigation_layers, Vector<int32_t> *r_path_types, TypedArray<RID> *r_path_rids, Vector<int64_t> *r_path_owners) const;
Vector3 get_closest_point_to_segment(const Vector3 &p_from, const Vector3 &p_to, const bool p_use_collision) const;
Vector3 get_closest_point(const Vector3 &p_point) const;
Vector3 get_closest_point_normal(const Vector3 &p_point) const;
@@ -154,7 +154,7 @@ public:
private:
void compute_single_step(uint32_t index, RvoAgent **agent);
- 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;
+ 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, Vector<int32_t> *r_path_types, TypedArray<RID> *r_path_rids, Vector<int64_t> *r_path_owners) const;
};
#endif // NAV_MAP_H
diff --git a/modules/navigation/nav_region.h b/modules/navigation/nav_region.h
index 8d2b5aa9eb..3ef3ef5748 100644
--- a/modules/navigation/nav_region.h
+++ b/modules/navigation/nav_region.h
@@ -48,7 +48,9 @@ class NavRegion : public NavBase {
LocalVector<gd::Polygon> polygons;
public:
- NavRegion() {}
+ NavRegion() {
+ type = NavigationUtilities::PathSegmentType::PATH_SEGMENT_TYPE_REGION;
+ }
void scratch_polygons() {
polygons_dirty = true;
diff --git a/modules/navigation/navigation_mesh_generator.cpp b/modules/navigation/navigation_mesh_generator.cpp
index f0d3e329ce..62db6ff4e9 100644
--- a/modules/navigation/navigation_mesh_generator.cpp
+++ b/modules/navigation/navigation_mesh_generator.cpp
@@ -470,14 +470,14 @@ void NavigationMeshGenerator::_parse_geometry(const Transform3D &p_navmesh_trans
}
}
-void NavigationMeshGenerator::_convert_detail_mesh_to_native_navigation_mesh(const rcPolyMeshDetail *p_detail_mesh, Ref<NavigationMesh> p_nav_mesh) {
+void NavigationMeshGenerator::_convert_detail_mesh_to_native_navigation_mesh(const rcPolyMeshDetail *p_detail_mesh, Ref<NavigationMesh> p_navigation_mesh) {
Vector<Vector3> nav_vertices;
for (int i = 0; i < p_detail_mesh->nverts; i++) {
const float *v = &p_detail_mesh->verts[i * 3];
nav_vertices.push_back(Vector3(v[0], v[1], v[2]));
}
- p_nav_mesh->set_vertices(nav_vertices);
+ p_navigation_mesh->set_vertices(nav_vertices);
for (int i = 0; i < p_detail_mesh->nmeshes; i++) {
const unsigned int *m = &p_detail_mesh->meshes[i * 4];
@@ -492,13 +492,13 @@ void NavigationMeshGenerator::_convert_detail_mesh_to_native_navigation_mesh(con
nav_indices.write[0] = ((int)(bverts + tris[j * 4 + 0]));
nav_indices.write[1] = ((int)(bverts + tris[j * 4 + 2]));
nav_indices.write[2] = ((int)(bverts + tris[j * 4 + 1]));
- p_nav_mesh->add_polygon(nav_indices);
+ p_navigation_mesh->add_polygon(nav_indices);
}
}
}
void NavigationMeshGenerator::_build_recast_navigation_mesh(
- Ref<NavigationMesh> p_nav_mesh,
+ Ref<NavigationMesh> p_navigation_mesh,
#ifdef TOOLS_ENABLED
EditorProgress *ep,
#endif
@@ -528,42 +528,42 @@ void NavigationMeshGenerator::_build_recast_navigation_mesh(
rcConfig cfg;
memset(&cfg, 0, sizeof(cfg));
- cfg.cs = p_nav_mesh->get_cell_size();
- cfg.ch = p_nav_mesh->get_cell_height();
- cfg.walkableSlopeAngle = p_nav_mesh->get_agent_max_slope();
- cfg.walkableHeight = (int)Math::ceil(p_nav_mesh->get_agent_height() / cfg.ch);
- cfg.walkableClimb = (int)Math::floor(p_nav_mesh->get_agent_max_climb() / cfg.ch);
- cfg.walkableRadius = (int)Math::ceil(p_nav_mesh->get_agent_radius() / cfg.cs);
- cfg.maxEdgeLen = (int)(p_nav_mesh->get_edge_max_length() / p_nav_mesh->get_cell_size());
- cfg.maxSimplificationError = p_nav_mesh->get_edge_max_error();
- cfg.minRegionArea = (int)(p_nav_mesh->get_region_min_size() * p_nav_mesh->get_region_min_size());
- cfg.mergeRegionArea = (int)(p_nav_mesh->get_region_merge_size() * p_nav_mesh->get_region_merge_size());
- cfg.maxVertsPerPoly = (int)p_nav_mesh->get_verts_per_poly();
- cfg.detailSampleDist = MAX(p_nav_mesh->get_cell_size() * p_nav_mesh->get_detail_sample_distance(), 0.1f);
- cfg.detailSampleMaxError = p_nav_mesh->get_cell_height() * p_nav_mesh->get_detail_sample_max_error();
-
- if (!Math::is_equal_approx((float)cfg.walkableHeight * cfg.ch, p_nav_mesh->get_agent_height())) {
+ cfg.cs = p_navigation_mesh->get_cell_size();
+ cfg.ch = p_navigation_mesh->get_cell_height();
+ cfg.walkableSlopeAngle = p_navigation_mesh->get_agent_max_slope();
+ cfg.walkableHeight = (int)Math::ceil(p_navigation_mesh->get_agent_height() / cfg.ch);
+ cfg.walkableClimb = (int)Math::floor(p_navigation_mesh->get_agent_max_climb() / cfg.ch);
+ cfg.walkableRadius = (int)Math::ceil(p_navigation_mesh->get_agent_radius() / cfg.cs);
+ cfg.maxEdgeLen = (int)(p_navigation_mesh->get_edge_max_length() / p_navigation_mesh->get_cell_size());
+ cfg.maxSimplificationError = p_navigation_mesh->get_edge_max_error();
+ cfg.minRegionArea = (int)(p_navigation_mesh->get_region_min_size() * p_navigation_mesh->get_region_min_size());
+ cfg.mergeRegionArea = (int)(p_navigation_mesh->get_region_merge_size() * p_navigation_mesh->get_region_merge_size());
+ cfg.maxVertsPerPoly = (int)p_navigation_mesh->get_vertices_per_polygon();
+ cfg.detailSampleDist = MAX(p_navigation_mesh->get_cell_size() * p_navigation_mesh->get_detail_sample_distance(), 0.1f);
+ cfg.detailSampleMaxError = p_navigation_mesh->get_cell_height() * p_navigation_mesh->get_detail_sample_max_error();
+
+ if (!Math::is_equal_approx((float)cfg.walkableHeight * cfg.ch, p_navigation_mesh->get_agent_height())) {
WARN_PRINT("Property agent_height is ceiled to cell_height voxel units and loses precision.");
}
- if (!Math::is_equal_approx((float)cfg.walkableClimb * cfg.ch, p_nav_mesh->get_agent_max_climb())) {
+ if (!Math::is_equal_approx((float)cfg.walkableClimb * cfg.ch, p_navigation_mesh->get_agent_max_climb())) {
WARN_PRINT("Property agent_max_climb is floored to cell_height voxel units and loses precision.");
}
- if (!Math::is_equal_approx((float)cfg.walkableRadius * cfg.cs, p_nav_mesh->get_agent_radius())) {
+ if (!Math::is_equal_approx((float)cfg.walkableRadius * cfg.cs, p_navigation_mesh->get_agent_radius())) {
WARN_PRINT("Property agent_radius is ceiled to cell_size voxel units and loses precision.");
}
- if (!Math::is_equal_approx((float)cfg.maxEdgeLen * cfg.cs, p_nav_mesh->get_edge_max_length())) {
+ if (!Math::is_equal_approx((float)cfg.maxEdgeLen * cfg.cs, p_navigation_mesh->get_edge_max_length())) {
WARN_PRINT("Property edge_max_length is rounded to cell_size voxel units and loses precision.");
}
- if (!Math::is_equal_approx((float)cfg.minRegionArea, p_nav_mesh->get_region_min_size() * p_nav_mesh->get_region_min_size())) {
+ if (!Math::is_equal_approx((float)cfg.minRegionArea, p_navigation_mesh->get_region_min_size() * p_navigation_mesh->get_region_min_size())) {
WARN_PRINT("Property region_min_size is converted to int and loses precision.");
}
- if (!Math::is_equal_approx((float)cfg.mergeRegionArea, p_nav_mesh->get_region_merge_size() * p_nav_mesh->get_region_merge_size())) {
+ if (!Math::is_equal_approx((float)cfg.mergeRegionArea, p_navigation_mesh->get_region_merge_size() * p_navigation_mesh->get_region_merge_size())) {
WARN_PRINT("Property region_merge_size is converted to int and loses precision.");
}
- if (!Math::is_equal_approx((float)cfg.maxVertsPerPoly, p_nav_mesh->get_verts_per_poly())) {
- WARN_PRINT("Property verts_per_poly is converted to int and loses precision.");
+ if (!Math::is_equal_approx((float)cfg.maxVertsPerPoly, p_navigation_mesh->get_vertices_per_polygon())) {
+ WARN_PRINT("Property vertices_per_polygon is converted to int and loses precision.");
}
- if (p_nav_mesh->get_cell_size() * p_nav_mesh->get_detail_sample_distance() < 0.1f) {
+ if (p_navigation_mesh->get_cell_size() * p_navigation_mesh->get_detail_sample_distance() < 0.1f) {
WARN_PRINT("Property detail_sample_distance is clamped to 0.1 world units as the resulting value from multiplying with cell_size is too low.");
}
@@ -574,9 +574,9 @@ void NavigationMeshGenerator::_build_recast_navigation_mesh(
cfg.bmax[1] = bmax[1];
cfg.bmax[2] = bmax[2];
- AABB baking_aabb = p_nav_mesh->get_filter_baking_aabb();
+ AABB baking_aabb = p_navigation_mesh->get_filter_baking_aabb();
if (baking_aabb.has_volume()) {
- Vector3 baking_aabb_offset = p_nav_mesh->get_filter_baking_aabb_offset();
+ Vector3 baking_aabb_offset = p_navigation_mesh->get_filter_baking_aabb_offset();
cfg.bmin[0] = baking_aabb.position[0] + baking_aabb_offset.x;
cfg.bmin[1] = baking_aabb.position[1] + baking_aabb_offset.y;
cfg.bmin[2] = baking_aabb.position[2] + baking_aabb_offset.z;
@@ -627,13 +627,13 @@ void NavigationMeshGenerator::_build_recast_navigation_mesh(
ERR_FAIL_COND(!rcRasterizeTriangles(&ctx, verts, nverts, tris, tri_areas.ptr(), ntris, *hf, cfg.walkableClimb));
}
- if (p_nav_mesh->get_filter_low_hanging_obstacles()) {
+ if (p_navigation_mesh->get_filter_low_hanging_obstacles()) {
rcFilterLowHangingWalkableObstacles(&ctx, cfg.walkableClimb, *hf);
}
- if (p_nav_mesh->get_filter_ledge_spans()) {
+ if (p_navigation_mesh->get_filter_ledge_spans()) {
rcFilterLedgeSpans(&ctx, cfg.walkableHeight, cfg.walkableClimb, *hf);
}
- if (p_nav_mesh->get_filter_walkable_low_height_spans()) {
+ if (p_navigation_mesh->get_filter_walkable_low_height_spans()) {
rcFilterWalkableLowHeightSpans(&ctx, cfg.walkableHeight, *hf);
}
@@ -665,10 +665,10 @@ void NavigationMeshGenerator::_build_recast_navigation_mesh(
}
#endif
- if (p_nav_mesh->get_sample_partition_type() == NavigationMesh::SAMPLE_PARTITION_WATERSHED) {
+ if (p_navigation_mesh->get_sample_partition_type() == NavigationMesh::SAMPLE_PARTITION_WATERSHED) {
ERR_FAIL_COND(!rcBuildDistanceField(&ctx, *chf));
ERR_FAIL_COND(!rcBuildRegions(&ctx, *chf, 0, cfg.minRegionArea, cfg.mergeRegionArea));
- } else if (p_nav_mesh->get_sample_partition_type() == NavigationMesh::SAMPLE_PARTITION_MONOTONE) {
+ } else if (p_navigation_mesh->get_sample_partition_type() == NavigationMesh::SAMPLE_PARTITION_MONOTONE) {
ERR_FAIL_COND(!rcBuildRegionsMonotone(&ctx, *chf, 0, cfg.minRegionArea, cfg.mergeRegionArea));
} else {
ERR_FAIL_COND(!rcBuildLayerRegions(&ctx, *chf, 0, cfg.minRegionArea));
@@ -710,7 +710,7 @@ void NavigationMeshGenerator::_build_recast_navigation_mesh(
}
#endif
- _convert_detail_mesh_to_native_navigation_mesh(detail_mesh, p_nav_mesh);
+ _convert_detail_mesh_to_native_navigation_mesh(detail_mesh, p_navigation_mesh);
rcFreePolyMesh(poly_mesh);
poly_mesh = nullptr;
@@ -729,8 +729,8 @@ NavigationMeshGenerator::NavigationMeshGenerator() {
NavigationMeshGenerator::~NavigationMeshGenerator() {
}
-void NavigationMeshGenerator::bake(Ref<NavigationMesh> p_nav_mesh, Node *p_node) {
- ERR_FAIL_COND_MSG(!p_nav_mesh.is_valid(), "Invalid navigation mesh.");
+void NavigationMeshGenerator::bake(Ref<NavigationMesh> p_navigation_mesh, Node *p_root_node) {
+ ERR_FAIL_COND_MSG(!p_navigation_mesh.is_valid(), "Invalid navigation mesh.");
#ifdef TOOLS_ENABLED
EditorProgress *ep(nullptr);
@@ -755,17 +755,17 @@ void NavigationMeshGenerator::bake(Ref<NavigationMesh> p_nav_mesh, Node *p_node)
List<Node *> parse_nodes;
- if (p_nav_mesh->get_source_geometry_mode() == NavigationMesh::SOURCE_GEOMETRY_NAVMESH_CHILDREN) {
- parse_nodes.push_back(p_node);
+ if (p_navigation_mesh->get_source_geometry_mode() == NavigationMesh::SOURCE_GEOMETRY_ROOT_NODE_CHILDREN) {
+ parse_nodes.push_back(p_root_node);
} else {
- p_node->get_tree()->get_nodes_in_group(p_nav_mesh->get_source_group_name(), &parse_nodes);
+ p_root_node->get_tree()->get_nodes_in_group(p_navigation_mesh->get_source_group_name(), &parse_nodes);
}
- Transform3D navmesh_xform = Object::cast_to<Node3D>(p_node)->get_global_transform().affine_inverse();
+ Transform3D navmesh_xform = Object::cast_to<Node3D>(p_root_node)->get_global_transform().affine_inverse();
for (Node *E : parse_nodes) {
- NavigationMesh::ParsedGeometryType geometry_type = p_nav_mesh->get_parsed_geometry_type();
- uint32_t collision_mask = p_nav_mesh->get_collision_mask();
- bool recurse_children = p_nav_mesh->get_source_geometry_mode() != NavigationMesh::SOURCE_GEOMETRY_GROUPS_EXPLICIT;
+ NavigationMesh::ParsedGeometryType geometry_type = p_navigation_mesh->get_parsed_geometry_type();
+ uint32_t collision_mask = p_navigation_mesh->get_collision_mask();
+ bool recurse_children = p_navigation_mesh->get_source_geometry_mode() != NavigationMesh::SOURCE_GEOMETRY_GROUPS_EXPLICIT;
_parse_geometry(navmesh_xform, E, vertices, indices, geometry_type, collision_mask, recurse_children);
}
@@ -777,7 +777,7 @@ void NavigationMeshGenerator::bake(Ref<NavigationMesh> p_nav_mesh, Node *p_node)
rcPolyMeshDetail *detail_mesh = nullptr;
_build_recast_navigation_mesh(
- p_nav_mesh,
+ p_navigation_mesh,
#ifdef TOOLS_ENABLED
ep,
#endif
@@ -816,16 +816,16 @@ void NavigationMeshGenerator::bake(Ref<NavigationMesh> p_nav_mesh, Node *p_node)
#endif
}
-void NavigationMeshGenerator::clear(Ref<NavigationMesh> p_nav_mesh) {
- if (p_nav_mesh.is_valid()) {
- p_nav_mesh->clear_polygons();
- p_nav_mesh->set_vertices(Vector<Vector3>());
+void NavigationMeshGenerator::clear(Ref<NavigationMesh> p_navigation_mesh) {
+ if (p_navigation_mesh.is_valid()) {
+ p_navigation_mesh->clear_polygons();
+ p_navigation_mesh->set_vertices(Vector<Vector3>());
}
}
void NavigationMeshGenerator::_bind_methods() {
- ClassDB::bind_method(D_METHOD("bake", "nav_mesh", "root_node"), &NavigationMeshGenerator::bake);
- ClassDB::bind_method(D_METHOD("clear", "nav_mesh"), &NavigationMeshGenerator::clear);
+ ClassDB::bind_method(D_METHOD("bake", "navigation_mesh", "root_node"), &NavigationMeshGenerator::bake);
+ ClassDB::bind_method(D_METHOD("clear", "navigation_mesh"), &NavigationMeshGenerator::clear);
}
#endif
diff --git a/modules/navigation/navigation_mesh_generator.h b/modules/navigation/navigation_mesh_generator.h
index 8cc1531b53..f6bf39d714 100644
--- a/modules/navigation/navigation_mesh_generator.h
+++ b/modules/navigation/navigation_mesh_generator.h
@@ -55,9 +55,9 @@ protected:
static void _add_faces(const PackedVector3Array &p_faces, const Transform3D &p_xform, Vector<float> &p_vertices, Vector<int> &p_indices);
static void _parse_geometry(const Transform3D &p_navmesh_transform, Node *p_node, Vector<float> &p_vertices, Vector<int> &p_indices, NavigationMesh::ParsedGeometryType p_generate_from, uint32_t p_collision_mask, bool p_recurse_children);
- static void _convert_detail_mesh_to_native_navigation_mesh(const rcPolyMeshDetail *p_detail_mesh, Ref<NavigationMesh> p_nav_mesh);
+ static void _convert_detail_mesh_to_native_navigation_mesh(const rcPolyMeshDetail *p_detail_mesh, Ref<NavigationMesh> p_navigation_mesh);
static void _build_recast_navigation_mesh(
- Ref<NavigationMesh> p_nav_mesh,
+ Ref<NavigationMesh> p_navigation_mesh,
#ifdef TOOLS_ENABLED
EditorProgress *ep,
#endif
@@ -75,8 +75,8 @@ public:
NavigationMeshGenerator();
~NavigationMeshGenerator();
- void bake(Ref<NavigationMesh> p_nav_mesh, Node *p_node);
- void clear(Ref<NavigationMesh> p_nav_mesh);
+ void bake(Ref<NavigationMesh> p_navigation_mesh, Node *p_root_node);
+ void clear(Ref<NavigationMesh> p_navigation_mesh);
};
#endif
diff --git a/modules/noise/editor/noise_editor_plugin.cpp b/modules/noise/editor/noise_editor_plugin.cpp
index e8e73e4fd9..a8e376e142 100644
--- a/modules/noise/editor/noise_editor_plugin.cpp
+++ b/modules/noise/editor/noise_editor_plugin.cpp
@@ -32,7 +32,10 @@
#ifdef TOOLS_ENABLED
+#include "editor/editor_inspector.h"
#include "editor/editor_scale.h"
+#include "scene/gui/button.h"
+#include "scene/gui/texture_rect.h"
#include "modules/noise/noise.h"
#include "modules/noise/noise_texture_2d.h"
diff --git a/modules/openxr/action_map/openxr_action.cpp b/modules/openxr/action_map/openxr_action.cpp
index 0fb4f0773f..634f653376 100644
--- a/modules/openxr/action_map/openxr_action.cpp
+++ b/modules/openxr/action_map/openxr_action.cpp
@@ -42,7 +42,7 @@ void OpenXRAction::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_toplevel_paths", "toplevel_paths"), &OpenXRAction::set_toplevel_paths);
ClassDB::bind_method(D_METHOD("get_toplevel_paths"), &OpenXRAction::get_toplevel_paths);
- ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "toplevel_paths", PROPERTY_HINT_ARRAY_TYPE, "STRING"), "set_toplevel_paths", "get_toplevel_paths");
+ ADD_PROPERTY(PropertyInfo(Variant::PACKED_STRING_ARRAY, "toplevel_paths"), "set_toplevel_paths", "get_toplevel_paths");
BIND_ENUM_CONSTANT(OPENXR_ACTION_BOOL);
BIND_ENUM_CONSTANT(OPENXR_ACTION_FLOAT);
@@ -75,6 +75,7 @@ String OpenXRAction::get_name_with_set() const {
void OpenXRAction::set_localized_name(const String p_localized_name) {
localized_name = p_localized_name;
+ emit_changed();
}
String OpenXRAction::get_localized_name() const {
@@ -83,6 +84,7 @@ String OpenXRAction::get_localized_name() const {
void OpenXRAction::set_action_type(const OpenXRAction::ActionType p_action_type) {
action_type = p_action_type;
+ emit_changed();
}
OpenXRAction::ActionType OpenXRAction::get_action_type() const {
@@ -91,6 +93,7 @@ OpenXRAction::ActionType OpenXRAction::get_action_type() const {
void OpenXRAction::set_toplevel_paths(const PackedStringArray p_toplevel_paths) {
toplevel_paths = p_toplevel_paths;
+ emit_changed();
}
PackedStringArray OpenXRAction::get_toplevel_paths() const {
@@ -100,15 +103,18 @@ PackedStringArray OpenXRAction::get_toplevel_paths() const {
void OpenXRAction::add_toplevel_path(const String p_toplevel_path) {
if (!toplevel_paths.has(p_toplevel_path)) {
toplevel_paths.push_back(p_toplevel_path);
+ emit_changed();
}
}
void OpenXRAction::rem_toplevel_path(const String p_toplevel_path) {
if (toplevel_paths.has(p_toplevel_path)) {
toplevel_paths.erase(p_toplevel_path);
+ emit_changed();
}
}
void OpenXRAction::parse_toplevel_paths(const String p_toplevel_paths) {
toplevel_paths = p_toplevel_paths.split(",", false);
+ emit_changed();
}
diff --git a/modules/openxr/action_map/openxr_action_map.cpp b/modules/openxr/action_map/openxr_action_map.cpp
index 123f860ce9..226bfa18ba 100644
--- a/modules/openxr/action_map/openxr_action_map.cpp
+++ b/modules/openxr/action_map/openxr_action_map.cpp
@@ -95,6 +95,7 @@ void OpenXRActionMap::add_action_set(Ref<OpenXRActionSet> p_action_set) {
if (action_sets.find(p_action_set) == -1) {
action_sets.push_back(p_action_set);
+ emit_changed();
}
}
@@ -102,6 +103,7 @@ void OpenXRActionMap::remove_action_set(Ref<OpenXRActionSet> p_action_set) {
int idx = action_sets.find(p_action_set);
if (idx != -1) {
action_sets.remove_at(idx);
+ emit_changed();
}
}
@@ -146,6 +148,7 @@ void OpenXRActionMap::add_interaction_profile(Ref<OpenXRInteractionProfile> p_in
if (interaction_profiles.find(p_interaction_profile) == -1) {
interaction_profiles.push_back(p_interaction_profile);
+ emit_changed();
}
}
@@ -153,6 +156,7 @@ void OpenXRActionMap::remove_interaction_profile(Ref<OpenXRInteractionProfile> p
int idx = interaction_profiles.find(p_interaction_profile);
if (idx != -1) {
interaction_profiles.remove_at(idx);
+ emit_changed();
}
}
@@ -489,30 +493,34 @@ Ref<OpenXRAction> OpenXRActionMap::get_action(const String p_path) const {
return Ref<OpenXRAction>();
}
-void OpenXRActionMap::remove_action(const String p_path) {
+void OpenXRActionMap::remove_action(const String p_path, bool p_remove_interaction_profiles) {
Ref<OpenXRAction> action = get_action(p_path);
if (action.is_valid()) {
+ for (int i = 0; i < interaction_profiles.size(); i++) {
+ Ref<OpenXRInteractionProfile> interaction_profile = interaction_profiles[i];
+
+ if (p_remove_interaction_profiles) {
+ // Remove any bindings for this action
+ interaction_profile->remove_binding_for_action(action);
+ } else {
+ ERR_FAIL_COND(interaction_profile->has_binding_for_action(action));
+ }
+ }
+
OpenXRActionSet *action_set = action->get_action_set();
if (action_set != nullptr) {
// Remove the action from this action set
action_set->remove_action(action);
}
-
- for (int i = 0; i < interaction_profiles.size(); i++) {
- Ref<OpenXRInteractionProfile> interaction_profile = interaction_profiles[i];
-
- // Remove any bindings for this action
- interaction_profile->remove_binding_for_action(action);
- }
}
}
-PackedStringArray OpenXRActionMap::get_top_level_paths(Ref<OpenXRAction> p_action) {
+PackedStringArray OpenXRActionMap::get_top_level_paths(const Ref<OpenXRAction> p_action) {
PackedStringArray arr;
for (int i = 0; i < interaction_profiles.size(); i++) {
Ref<OpenXRInteractionProfile> ip = interaction_profiles[i];
- const OpenXRDefs::InteractionProfile *profile = OpenXRDefs::get_profile(ip->get_interaction_profile_path());
+ const OpenXRInteractionProfileMetaData::InteractionProfile *profile = OpenXRInteractionProfileMetaData::get_singleton()->get_profile(ip->get_interaction_profile_path());
if (profile != nullptr) {
for (int j = 0; j < ip->get_binding_count(); j++) {
@@ -521,9 +529,9 @@ PackedStringArray OpenXRActionMap::get_top_level_paths(Ref<OpenXRAction> p_actio
PackedStringArray paths = binding->get_paths();
for (int k = 0; k < paths.size(); k++) {
- const OpenXRDefs::IOPath *io_path = profile->get_io_path(paths[k]);
+ const OpenXRInteractionProfileMetaData::IOPath *io_path = profile->get_io_path(paths[k]);
if (io_path != nullptr) {
- String top_path = String(io_path->top_level_path->openxr_path);
+ String top_path = io_path->top_level_path;
if (!arr.has(top_path)) {
arr.push_back(top_path);
@@ -535,7 +543,7 @@ PackedStringArray OpenXRActionMap::get_top_level_paths(Ref<OpenXRAction> p_actio
}
}
- print_line("Toplevel paths for", p_action->get_name_with_set(), "are", arr);
+ // print_line("Toplevel paths for", p_action->get_name_with_set(), "are", arr);
return arr;
}
diff --git a/modules/openxr/action_map/openxr_action_map.h b/modules/openxr/action_map/openxr_action_map.h
index 8659cd3942..43a4d741f4 100644
--- a/modules/openxr/action_map/openxr_action_map.h
+++ b/modules/openxr/action_map/openxr_action_map.h
@@ -71,8 +71,8 @@ public:
// Helper functions for editor
Ref<OpenXRAction> get_action(const String p_path) const; // Retrieve an action using <action name>/<action> as our parameter
- void remove_action(const String p_path); // Remove action from action set, also removes it from interaction profiles
- PackedStringArray get_top_level_paths(Ref<OpenXRAction> p_action); // Determines the top level paths based on where an action is bound in interaction profiles
+ void remove_action(const String p_path, bool p_remove_interaction_profiles = false); // Remove action from action set, also removes it from interaction profiles
+ PackedStringArray get_top_level_paths(const Ref<OpenXRAction> p_action); // Determines the top level paths based on where an action is bound in interaction profiles
// TODO add validation to display in the interface that checks if we have action sets with the same name or if we have interaction profiles for the same path
diff --git a/modules/openxr/action_map/openxr_action_set.cpp b/modules/openxr/action_map/openxr_action_set.cpp
index be45218300..f46ac4a5ce 100644
--- a/modules/openxr/action_map/openxr_action_set.cpp
+++ b/modules/openxr/action_map/openxr_action_set.cpp
@@ -62,6 +62,7 @@ Ref<OpenXRActionSet> OpenXRActionSet::new_action_set(const char *p_name, const c
void OpenXRActionSet::set_localized_name(const String p_localized_name) {
localized_name = p_localized_name;
+ emit_changed();
}
String OpenXRActionSet::get_localized_name() const {
@@ -70,6 +71,7 @@ String OpenXRActionSet::get_localized_name() const {
void OpenXRActionSet::set_priority(const int p_priority) {
priority = p_priority;
+ emit_changed();
}
int OpenXRActionSet::get_priority() const {
@@ -82,11 +84,16 @@ int OpenXRActionSet::get_action_count() const {
void OpenXRActionSet::clear_actions() {
// Actions held within our action set should be released and destroyed but just in case they are still used some where else
+ if (actions.size() == 0) {
+ return;
+ }
+
for (int i = 0; i < actions.size(); i++) {
Ref<OpenXRAction> action = actions[i];
action->action_set = nullptr;
}
actions.clear();
+ emit_changed();
}
void OpenXRActionSet::set_actions(Array p_actions) {
@@ -125,6 +132,7 @@ void OpenXRActionSet::add_action(Ref<OpenXRAction> p_action) {
p_action->action_set = this;
actions.push_back(p_action);
+ emit_changed();
}
}
@@ -135,6 +143,8 @@ void OpenXRActionSet::remove_action(Ref<OpenXRAction> p_action) {
ERR_FAIL_COND_MSG(p_action->action_set != this, "Removing action that belongs to this action set but had incorrect action set pointer."); // this should never happen!
p_action->action_set = nullptr;
+
+ emit_changed();
}
}
diff --git a/modules/openxr/action_map/openxr_defs.cpp b/modules/openxr/action_map/openxr_defs.cpp
deleted file mode 100644
index 59ce829f1b..0000000000
--- a/modules/openxr/action_map/openxr_defs.cpp
+++ /dev/null
@@ -1,671 +0,0 @@
-/*************************************************************************/
-/* openxr_defs.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 "openxr_defs.h"
-
-// Our top level paths to which devices can be bound
-OpenXRDefs::TopLevelPath OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_TOP_LEVEL_PATH_MAX] = {
- // Core OpenXR paths
- { "Left hand controller", "/user/hand/left" },
- { "Right hand controller", "/user/hand/right" },
- { "Head", "/user/head" },
- { "Gamepad", "/user/gamepad" },
- { "Treadmill", "/user/treadmill" },
-
- // Specific to HTC tracker extension
- // { "Handheld object tracker", "/user/vive_tracker_htcx/role/handheld_object" },
- { "Left foot tracker", "/user/vive_tracker_htcx/role/left_foot" },
- { "Right foot tracker", "/user/vive_tracker_htcx/role/right_foot" },
- { "Left shoulder tracker", "/user/vive_tracker_htcx/role/left_shoulder" },
- { "Right shoulder tracker", "/user/vive_tracker_htcx/role/right_shoulder" },
- { "Left elbow tracker", "/user/vive_tracker_htcx/role/left_elbow" },
- { "Right elbow tracker", "/user/vive_tracker_htcx/role/right_elbow" },
- { "Left knee tracker", "/user/vive_tracker_htcx/role/left_knee" },
- { "Right knee tracker", "/user/vive_tracker_htcx/role/right_knee" },
- { "Waist tracker", "/user/vive_tracker_htcx/role/waist" },
- { "Chest tracker", "/user/vive_tracker_htcx/role/chest" },
- { "Camera tracker", "/user/vive_tracker_htcx/role/camera" },
- { "Keyboard tracker", "/user/vive_tracker_htcx/role/keyboard" },
-
-};
-
-// Fallback Khronos simple controller
-OpenXRDefs::IOPath OpenXRDefs::simple_io_paths[] = {
- { "Grip pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/grip/pose", OpenXRAction::OPENXR_ACTION_POSE },
- { "Grip pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/grip/pose", OpenXRAction::OPENXR_ACTION_POSE },
- { "Aim pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/aim/pose", OpenXRAction::OPENXR_ACTION_POSE },
- { "Aim pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/aim/pose", OpenXRAction::OPENXR_ACTION_POSE },
- { "Palm pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/palm_ext/pose", OpenXRAction::OPENXR_ACTION_POSE },
- { "Palm pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/palm_ext/pose", OpenXRAction::OPENXR_ACTION_POSE },
-
- { "Menu click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/menu/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Menu click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/menu/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Select click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/select/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Select click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/select/click", OpenXRAction::OPENXR_ACTION_BOOL },
-
- { "Haptic output", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/output/haptic", OpenXRAction::OPENXR_ACTION_HAPTIC },
- { "Haptic output", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/output/haptic", OpenXRAction::OPENXR_ACTION_HAPTIC },
-};
-
-// Original HTC Vive wands
-OpenXRDefs::IOPath OpenXRDefs::vive_io_paths[] = {
- { "Grip pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/grip/pose", OpenXRAction::OPENXR_ACTION_POSE },
- { "Grip pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/grip/pose", OpenXRAction::OPENXR_ACTION_POSE },
- { "Aim pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/aim/pose", OpenXRAction::OPENXR_ACTION_POSE },
- { "Aim pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/aim/pose", OpenXRAction::OPENXR_ACTION_POSE },
- { "Palm pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/palm_ext/pose", OpenXRAction::OPENXR_ACTION_POSE },
- { "Palm pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/palm_ext/pose", OpenXRAction::OPENXR_ACTION_POSE },
-
- { "Menu click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/menu/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Menu click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/menu/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "System click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/system/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "System click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/system/click", OpenXRAction::OPENXR_ACTION_BOOL },
-
- { "Trigger", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trigger/value", OpenXRAction::OPENXR_ACTION_FLOAT },
- { "Trigger click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trigger/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Trigger", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trigger/value", OpenXRAction::OPENXR_ACTION_FLOAT },
- { "Trigger click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trigger/click", OpenXRAction::OPENXR_ACTION_BOOL },
-
- { "Squeeze click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/squeeze/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Squeeze click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/squeeze/click", OpenXRAction::OPENXR_ACTION_BOOL },
-
- { "Trackpad", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trackpad", OpenXRAction::OPENXR_ACTION_VECTOR2 },
- { "Trackpad click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trackpad/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Trackpad touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trackpad/touch", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Trackpad", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trackpad", OpenXRAction::OPENXR_ACTION_VECTOR2 },
- { "Trackpad click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trackpad/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Trackpad touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trackpad/touch", OpenXRAction::OPENXR_ACTION_BOOL },
-
- { "Haptic output", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/output/haptic", OpenXRAction::OPENXR_ACTION_HAPTIC },
- { "Haptic output", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/output/haptic", OpenXRAction::OPENXR_ACTION_HAPTIC },
-};
-
-// Microsoft motion controller (original WMR controllers)
-OpenXRDefs::IOPath OpenXRDefs::motion_io_paths[] = {
- { "Grip pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/grip/pose", OpenXRAction::OPENXR_ACTION_POSE },
- { "Grip pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/grip/pose", OpenXRAction::OPENXR_ACTION_POSE },
- { "Aim pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/aim/pose", OpenXRAction::OPENXR_ACTION_POSE },
- { "Aim pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/aim/pose", OpenXRAction::OPENXR_ACTION_POSE },
- { "Palm pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/palm_ext/pose", OpenXRAction::OPENXR_ACTION_POSE },
- { "Palm pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/palm_ext/pose", OpenXRAction::OPENXR_ACTION_POSE },
-
- { "Menu click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/menu/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Menu click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/menu/click", OpenXRAction::OPENXR_ACTION_BOOL },
-
- { "Trigger", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trigger/value", OpenXRAction::OPENXR_ACTION_FLOAT },
- { "Trigger click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trigger/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Trigger", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trigger/value", OpenXRAction::OPENXR_ACTION_FLOAT },
- { "Trigger click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trigger/click", OpenXRAction::OPENXR_ACTION_BOOL },
-
- { "Squeeze click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/squeeze/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Squeeze click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/squeeze/click", OpenXRAction::OPENXR_ACTION_BOOL },
-
- { "Thumbstick", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/thumbstick", OpenXRAction::OPENXR_ACTION_VECTOR2 },
- { "Thumbstick click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/thumbstick/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Thumbstick", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/thumbstick", OpenXRAction::OPENXR_ACTION_VECTOR2 },
- { "Thumbstick click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/thumbstick/click", OpenXRAction::OPENXR_ACTION_BOOL },
-
- { "Trackpad", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trackpad", OpenXRAction::OPENXR_ACTION_VECTOR2 },
- { "Trackpad click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trackpad/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Trackpad touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trackpad/touch", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Trackpad", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trackpad", OpenXRAction::OPENXR_ACTION_VECTOR2 },
- { "Trackpad click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trackpad/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Trackpad touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trackpad/touch", OpenXRAction::OPENXR_ACTION_BOOL },
-
- { "Haptic output", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/output/haptic", OpenXRAction::OPENXR_ACTION_HAPTIC },
- { "Haptic output", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/output/haptic", OpenXRAction::OPENXR_ACTION_HAPTIC },
-};
-
-// HP MR controller (newer G2 controllers)
-OpenXRDefs::IOPath OpenXRDefs::hpmr_io_paths[] = {
- { "Grip pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/grip/pose", OpenXRAction::OPENXR_ACTION_POSE },
- { "Grip pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/grip/pose", OpenXRAction::OPENXR_ACTION_POSE },
- { "Aim pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/aim/pose", OpenXRAction::OPENXR_ACTION_POSE },
- { "Aim pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/aim/pose", OpenXRAction::OPENXR_ACTION_POSE },
- { "Palm pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/palm_ext/pose", OpenXRAction::OPENXR_ACTION_POSE },
- { "Palm pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/palm_ext/pose", OpenXRAction::OPENXR_ACTION_POSE },
-
- { "Menu click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/menu/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Menu click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/menu/click", OpenXRAction::OPENXR_ACTION_BOOL },
-
- { "X click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/x/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Y click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/y/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "A click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/a/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "B click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/b/click", OpenXRAction::OPENXR_ACTION_BOOL },
-
- { "Trigger", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trigger/value", OpenXRAction::OPENXR_ACTION_FLOAT },
- { "Trigger click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trigger/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Trigger", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trigger/value", OpenXRAction::OPENXR_ACTION_FLOAT },
- { "Trigger click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trigger/click", OpenXRAction::OPENXR_ACTION_BOOL },
-
- { "Squeeze", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/squeeze/value", OpenXRAction::OPENXR_ACTION_FLOAT },
- { "Squeeze", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/squeeze/value", OpenXRAction::OPENXR_ACTION_FLOAT },
-
- { "Thumbstick", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/thumbstick", OpenXRAction::OPENXR_ACTION_VECTOR2 },
- { "Thumbstick click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/thumbstick/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Thumbstick", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/thumbstick", OpenXRAction::OPENXR_ACTION_VECTOR2 },
- { "Thumbstick click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/thumbstick/click", OpenXRAction::OPENXR_ACTION_BOOL },
-
- { "Haptic output", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/output/haptic", OpenXRAction::OPENXR_ACTION_HAPTIC },
- { "Haptic output", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/output/haptic", OpenXRAction::OPENXR_ACTION_HAPTIC },
-};
-
-// Meta touch controller (original touch controllers, Quest 1 and Quest 2 controllers)
-OpenXRDefs::IOPath OpenXRDefs::touch_io_paths[] = {
- { "Grip pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/grip/pose", OpenXRAction::OPENXR_ACTION_POSE },
- { "Grip pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/grip/pose", OpenXRAction::OPENXR_ACTION_POSE },
- { "Aim pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/aim/pose", OpenXRAction::OPENXR_ACTION_POSE },
- { "Aim pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/aim/pose", OpenXRAction::OPENXR_ACTION_POSE },
- { "Palm pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/palm_ext/pose", OpenXRAction::OPENXR_ACTION_POSE },
- { "Palm pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/palm_ext/pose", OpenXRAction::OPENXR_ACTION_POSE },
-
- { "Menu click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/menu/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "System click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/system/click", OpenXRAction::OPENXR_ACTION_BOOL },
-
- { "X click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/x/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "X touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/x/touch", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Y click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/y/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Y touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/y/touch", OpenXRAction::OPENXR_ACTION_BOOL },
- { "A click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/a/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "A touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/a/touch", OpenXRAction::OPENXR_ACTION_BOOL },
- { "B click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/b/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "B touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/b/touch", OpenXRAction::OPENXR_ACTION_BOOL },
-
- { "Trigger", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trigger/value", OpenXRAction::OPENXR_ACTION_FLOAT },
- { "Trigger touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trigger/touch", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Trigger", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trigger/value", OpenXRAction::OPENXR_ACTION_FLOAT },
- { "Trigger touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trigger/touch", OpenXRAction::OPENXR_ACTION_BOOL },
-
- { "Squeeze", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/squeeze/value", OpenXRAction::OPENXR_ACTION_FLOAT },
- { "Squeeze", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/squeeze/value", OpenXRAction::OPENXR_ACTION_FLOAT },
-
- { "Thumbstick", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/thumbstick", OpenXRAction::OPENXR_ACTION_VECTOR2 },
- { "Thumbstick click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/thumbstick/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Thumbstick touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/thumbstick/touch", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Thumbstick", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/thumbstick", OpenXRAction::OPENXR_ACTION_VECTOR2 },
- { "Thumbstick click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/thumbstick/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Thumbstick touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/thumbstick/touch", OpenXRAction::OPENXR_ACTION_BOOL },
-
- { "Haptic output", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/output/haptic", OpenXRAction::OPENXR_ACTION_HAPTIC },
- { "Haptic output", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/output/haptic", OpenXRAction::OPENXR_ACTION_HAPTIC },
-};
-
-// Valve index controller
-OpenXRDefs::IOPath OpenXRDefs::index_io_paths[] = {
- { "Grip pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/grip/pose", OpenXRAction::OPENXR_ACTION_POSE },
- { "Grip pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/grip/pose", OpenXRAction::OPENXR_ACTION_POSE },
- { "Aim pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/aim/pose", OpenXRAction::OPENXR_ACTION_POSE },
- { "Aim pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/aim/pose", OpenXRAction::OPENXR_ACTION_POSE },
- { "Palm pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/palm_ext/pose", OpenXRAction::OPENXR_ACTION_POSE },
- { "Palm pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/palm_ext/pose", OpenXRAction::OPENXR_ACTION_POSE },
-
- { "System click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/system/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "System click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/system/click", OpenXRAction::OPENXR_ACTION_BOOL },
-
- { "A click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/a/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "A touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/a/touch", OpenXRAction::OPENXR_ACTION_BOOL },
- { "A click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/a/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "A touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/a/touch", OpenXRAction::OPENXR_ACTION_BOOL },
- { "B click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/b/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "B touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/b/touch", OpenXRAction::OPENXR_ACTION_BOOL },
- { "B click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/b/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "B touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/b/touch", OpenXRAction::OPENXR_ACTION_BOOL },
-
- { "Trigger", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trigger/value", OpenXRAction::OPENXR_ACTION_FLOAT },
- { "Trigger click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trigger/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Trigger touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trigger/touch", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Trigger", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trigger/value", OpenXRAction::OPENXR_ACTION_FLOAT },
- { "Trigger click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trigger/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Trigger touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trigger/touch", OpenXRAction::OPENXR_ACTION_BOOL },
-
- { "Squeeze", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/squeeze/value", OpenXRAction::OPENXR_ACTION_FLOAT },
- { "Squeeze", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/squeeze/value", OpenXRAction::OPENXR_ACTION_FLOAT },
-
- { "Thumbstick", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/thumbstick", OpenXRAction::OPENXR_ACTION_VECTOR2 },
- { "Thumbstick click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/thumbstick/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Thumbstick touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/thumbstick/touch", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Thumbstick", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/thumbstick", OpenXRAction::OPENXR_ACTION_VECTOR2 },
- { "Thumbstick click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/thumbstick/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Thumbstick touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/thumbstick/touch", OpenXRAction::OPENXR_ACTION_BOOL },
-
- { "Trackpad", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trackpad", OpenXRAction::OPENXR_ACTION_VECTOR2 },
- { "Trackpad force", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trackpad/force", OpenXRAction::OPENXR_ACTION_FLOAT },
- { "Trackpad touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trackpad/touch", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Trackpad", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trackpad", OpenXRAction::OPENXR_ACTION_VECTOR2 },
- { "Trackpad force", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trackpad/force", OpenXRAction::OPENXR_ACTION_FLOAT },
- { "Trackpad touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trackpad/touch", OpenXRAction::OPENXR_ACTION_BOOL },
-
- { "Haptic output", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/output/haptic", OpenXRAction::OPENXR_ACTION_HAPTIC },
- { "Haptic output", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/output/haptic", OpenXRAction::OPENXR_ACTION_HAPTIC },
-};
-
-// Samsung odyssey controller
-OpenXRDefs::IOPath OpenXRDefs::odyssey_io_paths[] = {
- { "Grip pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/grip/pose", OpenXRAction::OPENXR_ACTION_POSE },
- { "Grip pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/grip/pose", OpenXRAction::OPENXR_ACTION_POSE },
- { "Aim pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/aim/pose", OpenXRAction::OPENXR_ACTION_POSE },
- { "Aim pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/aim/pose", OpenXRAction::OPENXR_ACTION_POSE },
- { "Palm pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/palm_ext/pose", OpenXRAction::OPENXR_ACTION_POSE },
- { "Palm pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/palm_ext/pose", OpenXRAction::OPENXR_ACTION_POSE },
-
- { "Menu click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/menu/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Menu click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/menu/click", OpenXRAction::OPENXR_ACTION_BOOL },
-
- { "Trigger", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trigger/value", OpenXRAction::OPENXR_ACTION_FLOAT },
- { "Trigger click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trigger/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Trigger", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trigger/value", OpenXRAction::OPENXR_ACTION_FLOAT },
- { "Trigger click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trigger/click", OpenXRAction::OPENXR_ACTION_BOOL },
-
- { "Squeeze click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/squeeze/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Squeeze click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/squeeze/click", OpenXRAction::OPENXR_ACTION_BOOL },
-
- { "Thumbstick", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/thumbstick", OpenXRAction::OPENXR_ACTION_VECTOR2 },
- { "Thumbstick click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/thumbstick/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Thumbstick", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/thumbstick", OpenXRAction::OPENXR_ACTION_VECTOR2 },
- { "Thumbstick click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/thumbstick/click", OpenXRAction::OPENXR_ACTION_BOOL },
-
- { "Trackpad", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trackpad", OpenXRAction::OPENXR_ACTION_VECTOR2 },
- { "Trackpad click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trackpad/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Trackpad touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trackpad/touch", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Trackpad", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trackpad", OpenXRAction::OPENXR_ACTION_VECTOR2 },
- { "Trackpad click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trackpad/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Trackpad touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trackpad/touch", OpenXRAction::OPENXR_ACTION_BOOL },
-
- { "Haptic output", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/output/haptic", OpenXRAction::OPENXR_ACTION_HAPTIC },
- { "Haptic output", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/output/haptic", OpenXRAction::OPENXR_ACTION_HAPTIC },
-};
-
-// Vive Cosmos controller
-OpenXRDefs::IOPath OpenXRDefs::vive_cosmos_paths[] = {
- { "Grip pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/grip/pose", OpenXRAction::OPENXR_ACTION_POSE },
- { "Grip pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/grip/pose", OpenXRAction::OPENXR_ACTION_POSE },
- { "Aim pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/aim/pose", OpenXRAction::OPENXR_ACTION_POSE },
- { "Aim pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/aim/pose", OpenXRAction::OPENXR_ACTION_POSE },
- { "Palm pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/palm_ext/pose", OpenXRAction::OPENXR_ACTION_POSE },
- { "Palm pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/palm_ext/pose", OpenXRAction::OPENXR_ACTION_POSE },
-
- { "Menu click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/menu/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "System click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/system/click", OpenXRAction::OPENXR_ACTION_BOOL },
-
- { "X click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/x/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Y click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/y/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "A click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/a/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "B click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/b/click", OpenXRAction::OPENXR_ACTION_BOOL },
-
- { "Shoulder click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/right/input/shoulder/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Shoulder click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/shoulder/click", OpenXRAction::OPENXR_ACTION_BOOL },
-
- { "Trigger", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trigger/value", OpenXRAction::OPENXR_ACTION_FLOAT },
- { "Trigger click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trigger/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Trigger", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trigger/value", OpenXRAction::OPENXR_ACTION_FLOAT },
- { "Trigger click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trigger/click", OpenXRAction::OPENXR_ACTION_BOOL },
-
- { "Squeeze click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/squeeze/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Squeeze click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/squeeze/click", OpenXRAction::OPENXR_ACTION_BOOL },
-
- { "Thumbstick", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/thumbstick", OpenXRAction::OPENXR_ACTION_VECTOR2 },
- { "Thumbstick click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/thumbstick/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Thumbstick touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/thumbstick/touch", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Thumbstick", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/thumbstick", OpenXRAction::OPENXR_ACTION_VECTOR2 },
- { "Thumbstick click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/thumbstick/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Thumbstick touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/thumbstick/touch", OpenXRAction::OPENXR_ACTION_BOOL },
-
- { "Haptic output", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/output/haptic", OpenXRAction::OPENXR_ACTION_HAPTIC },
- { "Haptic output", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/output/haptic", OpenXRAction::OPENXR_ACTION_HAPTIC },
-};
-
-// Vive Focus 3 controller
-OpenXRDefs::IOPath OpenXRDefs::vive_focus3_paths[] = {
- { "Grip pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/grip/pose", OpenXRAction::OPENXR_ACTION_POSE },
- { "Grip pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/grip/pose", OpenXRAction::OPENXR_ACTION_POSE },
- { "Aim pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/aim/pose", OpenXRAction::OPENXR_ACTION_POSE },
- { "Aim pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/aim/pose", OpenXRAction::OPENXR_ACTION_POSE },
- { "Palm pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/palm_ext/pose", OpenXRAction::OPENXR_ACTION_POSE },
- { "Palm pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/palm_ext/pose", OpenXRAction::OPENXR_ACTION_POSE },
-
- { "Menu click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/menu/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "System click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/system/click", OpenXRAction::OPENXR_ACTION_BOOL },
-
- { "X click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/x/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Y click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/y/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "A click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/a/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "B click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/b/click", OpenXRAction::OPENXR_ACTION_BOOL },
-
- { "Trigger", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trigger/value", OpenXRAction::OPENXR_ACTION_FLOAT },
- { "Trigger click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trigger/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Trigger touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trigger/touch", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Trigger", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trigger/value", OpenXRAction::OPENXR_ACTION_FLOAT },
- { "Trigger click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trigger/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Trigger touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trigger/touch ", OpenXRAction::OPENXR_ACTION_BOOL },
-
- { "Squeeze click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/squeeze/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Squeeze touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/squeeze/touch", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Squeeze click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/squeeze/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Squeeze touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/squeeze/touch", OpenXRAction::OPENXR_ACTION_BOOL },
-
- { "Thumbstick", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/thumbstick", OpenXRAction::OPENXR_ACTION_VECTOR2 },
- { "Thumbstick click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/thumbstick/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Thumbstick touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/thumbstick/touch", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Thumbstick", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/thumbstick", OpenXRAction::OPENXR_ACTION_VECTOR2 },
- { "Thumbstick click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/thumbstick/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Thumbstick touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/thumbstick/touch", OpenXRAction::OPENXR_ACTION_BOOL },
-
- { "Thumbrest touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/thumbrest/touch", OpenXRAction::OPENXR_ACTION_BOOL },
-
- { "Haptic output", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/output/haptic", OpenXRAction::OPENXR_ACTION_HAPTIC },
- { "Haptic output", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/output/haptic", OpenXRAction::OPENXR_ACTION_HAPTIC },
-};
-
-// Huawei controller
-OpenXRDefs::IOPath OpenXRDefs::huawei_controller_paths[] = {
- { "Grip pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/grip/pose", OpenXRAction::OPENXR_ACTION_POSE },
- { "Grip pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/grip/pose", OpenXRAction::OPENXR_ACTION_POSE },
- { "Aim pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/aim/pose", OpenXRAction::OPENXR_ACTION_POSE },
- { "Aim pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/aim/pose", OpenXRAction::OPENXR_ACTION_POSE },
- { "Palm pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/palm_ext/pose", OpenXRAction::OPENXR_ACTION_POSE },
- { "Palm pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/palm_ext/pose", OpenXRAction::OPENXR_ACTION_POSE },
-
- { "Home click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/home/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Home click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/home/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Back click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/back/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Back click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/back/click", OpenXRAction::OPENXR_ACTION_BOOL },
-
- { "Volume up click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/volume_up/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Volume up click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/volume_up/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Volume down click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/volume_down/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Volume down click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/volume_down/click", OpenXRAction::OPENXR_ACTION_BOOL },
-
- { "Trigger", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trigger/value", OpenXRAction::OPENXR_ACTION_FLOAT },
- { "Trigger click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trigger/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Trigger", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trigger/value", OpenXRAction::OPENXR_ACTION_FLOAT },
- { "Trigger click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trigger/click", OpenXRAction::OPENXR_ACTION_BOOL },
-
- { "Trackpad", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trackpad", OpenXRAction::OPENXR_ACTION_VECTOR2 },
- { "Trackpad click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trackpad/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Trackpad touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trackpad/touch", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Trackpad", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trackpad", OpenXRAction::OPENXR_ACTION_VECTOR2 },
- { "Trackpad click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trackpad/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Trackpad touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trackpad/touch", OpenXRAction::OPENXR_ACTION_BOOL },
-
- { "Haptic output", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/output/haptic", OpenXRAction::OPENXR_ACTION_HAPTIC },
- { "Haptic output", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/output/haptic", OpenXRAction::OPENXR_ACTION_HAPTIC },
-};
-
-// HTC Vive tracker
-// Interestingly enough trackers don't have buttons or inputs, yet these are defined in the spec.
-// I think this can be supported through attachments on the trackers.
-OpenXRDefs::IOPath OpenXRDefs::vive_tracker_controller_paths[] = {
- // { "Menu click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_HANDHELD_TRACKER], "/user/vive_tracker_htcx/role/handheld_object/input/menu/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Menu click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_LEFT_FOOT_TRACKER], "/user/vive_tracker_htcx/role/left_foot/input/menu/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Menu click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_RIGHT_FOOT_TRACKER], "/user/vive_tracker_htcx/role/right_foot/input/menu/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Menu click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_LEFT_SHOULDER_TRACKER], "/user/vive_tracker_htcx/role/left_shoulder/input/menu/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Menu click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_RIGHT_SHOULDER_TRACKER], "/user/vive_tracker_htcx/role/right_shoulder/input/menu/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Menu click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_LEFT_ELBOW_TRACKER], "/user/vive_tracker_htcx/role/left_elbow/input/menu/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Menu click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_RIGHT_ELBOW_TRACKER], "/user/vive_tracker_htcx/role/right_elbow/input/menu/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Menu click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_LEFT_KNEE_TRACKER], "/user/vive_tracker_htcx/role/left_knee/input/menu/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Menu click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_RIGHT_KNEE_TRACKER], "/user/vive_tracker_htcx/role/right_knee/input/menu/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Menu click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_WAIST_TRACKER], "/user/vive_tracker_htcx/role/waist/input/menu/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Menu click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_CHEST_TRACKER], "/user/vive_tracker_htcx/role/chest/input/menu/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Menu click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_CAMERA_TRACKER], "/user/vive_tracker_htcx/role/camera/input/menu/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Menu click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_KEYBOARD_TRACKER], "/user/vive_tracker_htcx/role/keyboard/input/menu/click", OpenXRAction::OPENXR_ACTION_BOOL },
-
- // { "Trigger", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_HANDHELD_TRACKER], "/user/vive_tracker_htcx/role/handheld_object/input/trigger/value", OpenXRAction::OPENXR_ACTION_FLOAT },
- { "Trigger", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_LEFT_FOOT_TRACKER], "/user/vive_tracker_htcx/role/left_foot/input/trigger/value", OpenXRAction::OPENXR_ACTION_FLOAT },
- { "Trigger", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_RIGHT_FOOT_TRACKER], "/user/vive_tracker_htcx/role/right_foot/input/trigger/value", OpenXRAction::OPENXR_ACTION_FLOAT },
- { "Trigger", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_LEFT_SHOULDER_TRACKER], "/user/vive_tracker_htcx/role/left_shoulder/input/trigger/value", OpenXRAction::OPENXR_ACTION_FLOAT },
- { "Trigger", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_RIGHT_SHOULDER_TRACKER], "/user/vive_tracker_htcx/role/right_shoulder/input/trigger/value", OpenXRAction::OPENXR_ACTION_FLOAT },
- { "Trigger", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_LEFT_ELBOW_TRACKER], "/user/vive_tracker_htcx/role/left_elbow/input/trigger/value", OpenXRAction::OPENXR_ACTION_FLOAT },
- { "Trigger", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_RIGHT_ELBOW_TRACKER], "/user/vive_tracker_htcx/role/right_elbow/input/trigger/value", OpenXRAction::OPENXR_ACTION_FLOAT },
- { "Trigger", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_LEFT_KNEE_TRACKER], "/user/vive_tracker_htcx/role/left_knee/input/trigger/value", OpenXRAction::OPENXR_ACTION_FLOAT },
- { "Trigger", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_RIGHT_KNEE_TRACKER], "/user/vive_tracker_htcx/role/right_knee/input/trigger/value", OpenXRAction::OPENXR_ACTION_FLOAT },
- { "Trigger", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_WAIST_TRACKER], "/user/vive_tracker_htcx/role/waist/input/trigger/value", OpenXRAction::OPENXR_ACTION_FLOAT },
- { "Trigger", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_CHEST_TRACKER], "/user/vive_tracker_htcx/role/chest/input/trigger/value", OpenXRAction::OPENXR_ACTION_FLOAT },
- { "Trigger", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_CAMERA_TRACKER], "/user/vive_tracker_htcx/role/camera/input/trigger/value", OpenXRAction::OPENXR_ACTION_FLOAT },
- { "Trigger", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_KEYBOARD_TRACKER], "/user/vive_tracker_htcx/role/keyboard/input/trigger/value", OpenXRAction::OPENXR_ACTION_FLOAT },
-
- // { "Trigger click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_HANDHELD_TRACKER], "/user/vive_tracker_htcx/role/handheld_object/input/trigger/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Trigger click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_LEFT_FOOT_TRACKER], "/user/vive_tracker_htcx/role/left_foot/input/trigger/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Trigger click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_RIGHT_FOOT_TRACKER], "/user/vive_tracker_htcx/role/right_foot/input/trigger/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Trigger click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_LEFT_SHOULDER_TRACKER], "/user/vive_tracker_htcx/role/left_shoulder/input/trigger/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Trigger click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_RIGHT_SHOULDER_TRACKER], "/user/vive_tracker_htcx/role/right_shoulder/input/trigger/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Trigger click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_LEFT_ELBOW_TRACKER], "/user/vive_tracker_htcx/role/left_elbow/input/trigger/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Trigger click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_RIGHT_ELBOW_TRACKER], "/user/vive_tracker_htcx/role/right_elbow/input/trigger/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Trigger click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_LEFT_KNEE_TRACKER], "/user/vive_tracker_htcx/role/left_knee/input/trigger/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Trigger click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_RIGHT_KNEE_TRACKER], "/user/vive_tracker_htcx/role/right_knee/input/trigger/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Trigger click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_WAIST_TRACKER], "/user/vive_tracker_htcx/role/waist/input/trigger/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Trigger click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_CHEST_TRACKER], "/user/vive_tracker_htcx/role/chest/input/trigger/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Trigger click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_CAMERA_TRACKER], "/user/vive_tracker_htcx/role/camera/input/trigger/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Trigger click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_KEYBOARD_TRACKER], "/user/vive_tracker_htcx/role/keyboard/input/trigger/click", OpenXRAction::OPENXR_ACTION_BOOL },
-
- // { "Squeeze click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_HANDHELD_TRACKER], "/user/vive_tracker_htcx/role/handheld_object/input/squeeze/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Squeeze click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_LEFT_FOOT_TRACKER], "/user/vive_tracker_htcx/role/left_foot/input/squeeze/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Squeeze click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_RIGHT_FOOT_TRACKER], "/user/vive_tracker_htcx/role/right_foot/input/squeeze/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Squeeze click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_LEFT_SHOULDER_TRACKER], "/user/vive_tracker_htcx/role/left_shoulder/input/squeeze/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Squeeze click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_RIGHT_SHOULDER_TRACKER], "/user/vive_tracker_htcx/role/right_shoulder/input/squeeze/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Squeeze click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_LEFT_ELBOW_TRACKER], "/user/vive_tracker_htcx/role/left_elbow/input/squeeze/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Squeeze click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_RIGHT_ELBOW_TRACKER], "/user/vive_tracker_htcx/role/right_elbow/input/squeeze/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Squeeze click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_LEFT_KNEE_TRACKER], "/user/vive_tracker_htcx/role/left_knee/input/squeeze/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Squeeze click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_RIGHT_KNEE_TRACKER], "/user/vive_tracker_htcx/role/right_knee/input/squeeze/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Squeeze click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_WAIST_TRACKER], "/user/vive_tracker_htcx/role/waist/input/squeeze/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Squeeze click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_CHEST_TRACKER], "/user/vive_tracker_htcx/role/chest/input/squeeze/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Squeeze click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_CAMERA_TRACKER], "/user/vive_tracker_htcx/role/camera/input/squeeze/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Squeeze click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_KEYBOARD_TRACKER], "/user/vive_tracker_htcx/role/keyboard/input/squeeze/click", OpenXRAction::OPENXR_ACTION_BOOL },
-
- // { "Trackpad", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_HANDHELD_TRACKER], "/user/vive_tracker_htcx/role/handheld_object/input/trackpad", OpenXRAction::OPENXR_ACTION_VECTOR2 },
- { "Trackpad", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_LEFT_FOOT_TRACKER], "/user/vive_tracker_htcx/role/left_foot/input/trackpad", OpenXRAction::OPENXR_ACTION_VECTOR2 },
- { "Trackpad", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_RIGHT_FOOT_TRACKER], "/user/vive_tracker_htcx/role/right_foot/input/trackpad", OpenXRAction::OPENXR_ACTION_VECTOR2 },
- { "Trackpad", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_LEFT_SHOULDER_TRACKER], "/user/vive_tracker_htcx/role/left_shoulder/input/trackpad", OpenXRAction::OPENXR_ACTION_VECTOR2 },
- { "Trackpad", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_RIGHT_SHOULDER_TRACKER], "/user/vive_tracker_htcx/role/right_shoulder/input/trackpad", OpenXRAction::OPENXR_ACTION_VECTOR2 },
- { "Trackpad", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_LEFT_ELBOW_TRACKER], "/user/vive_tracker_htcx/role/left_elbow/input/trackpad", OpenXRAction::OPENXR_ACTION_VECTOR2 },
- { "Trackpad", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_RIGHT_ELBOW_TRACKER], "/user/vive_tracker_htcx/role/right_elbow/input/trackpad", OpenXRAction::OPENXR_ACTION_VECTOR2 },
- { "Trackpad", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_LEFT_KNEE_TRACKER], "/user/vive_tracker_htcx/role/left_knee/input/trackpad", OpenXRAction::OPENXR_ACTION_VECTOR2 },
- { "Trackpad", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_RIGHT_KNEE_TRACKER], "/user/vive_tracker_htcx/role/right_knee/input/trackpad", OpenXRAction::OPENXR_ACTION_VECTOR2 },
- { "Trackpad", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_WAIST_TRACKER], "/user/vive_tracker_htcx/role/waist/input/trackpad", OpenXRAction::OPENXR_ACTION_VECTOR2 },
- { "Trackpad", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_CHEST_TRACKER], "/user/vive_tracker_htcx/role/chest/input/trackpad", OpenXRAction::OPENXR_ACTION_VECTOR2 },
- { "Trackpad", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_CAMERA_TRACKER], "/user/vive_tracker_htcx/role/camera/input/trackpad", OpenXRAction::OPENXR_ACTION_VECTOR2 },
- { "Trackpad", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_KEYBOARD_TRACKER], "/user/vive_tracker_htcx/role/keyboard/input/trackpad", OpenXRAction::OPENXR_ACTION_VECTOR2 },
-
- // { "Trackpad click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_HANDHELD_TRACKER], "/user/vive_tracker_htcx/role/handheld_object/input/trackpad/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Trackpad click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_LEFT_FOOT_TRACKER], "/user/vive_tracker_htcx/role/left_foot/input/trackpad/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Trackpad click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_RIGHT_FOOT_TRACKER], "/user/vive_tracker_htcx/role/right_foot/input/trackpad/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Trackpad click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_LEFT_SHOULDER_TRACKER], "/user/vive_tracker_htcx/role/left_shoulder/input/trackpad/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Trackpad click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_RIGHT_SHOULDER_TRACKER], "/user/vive_tracker_htcx/role/right_shoulder/input/trackpad/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Trackpad click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_LEFT_ELBOW_TRACKER], "/user/vive_tracker_htcx/role/left_elbow/input/trackpad/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Trackpad click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_RIGHT_ELBOW_TRACKER], "/user/vive_tracker_htcx/role/right_elbow/input/trackpad/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Trackpad click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_LEFT_KNEE_TRACKER], "/user/vive_tracker_htcx/role/left_knee/input/trackpad/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Trackpad click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_RIGHT_KNEE_TRACKER], "/user/vive_tracker_htcx/role/right_knee/input/trackpad/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Trackpad click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_WAIST_TRACKER], "/user/vive_tracker_htcx/role/waist/input/trackpad/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Trackpad click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_CHEST_TRACKER], "/user/vive_tracker_htcx/role/chest/input/trackpad/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Trackpad click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_CAMERA_TRACKER], "/user/vive_tracker_htcx/role/camera/input/trackpad/click", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Trackpad click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_KEYBOARD_TRACKER], "/user/vive_tracker_htcx/role/keyboard/input/trackpad/click", OpenXRAction::OPENXR_ACTION_BOOL },
-
- // { "Trackpad touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_HANDHELD_TRACKER], "/user/vive_tracker_htcx/role/handheld_object/input/trackpad/touch", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Trackpad touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_LEFT_FOOT_TRACKER], "/user/vive_tracker_htcx/role/left_foot/input/trackpad/touch", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Trackpad touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_RIGHT_FOOT_TRACKER], "/user/vive_tracker_htcx/role/right_foot/input/trackpad/touch", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Trackpad touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_LEFT_SHOULDER_TRACKER], "/user/vive_tracker_htcx/role/left_shoulder/input/trackpad/touch", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Trackpad touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_RIGHT_SHOULDER_TRACKER], "/user/vive_tracker_htcx/role/right_shoulder/input/trackpad/touch", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Trackpad touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_LEFT_ELBOW_TRACKER], "/user/vive_tracker_htcx/role/left_elbow/input/trackpad/touch", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Trackpad touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_RIGHT_ELBOW_TRACKER], "/user/vive_tracker_htcx/role/right_elbow/input/trackpad/touch", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Trackpad touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_LEFT_KNEE_TRACKER], "/user/vive_tracker_htcx/role/left_knee/input/trackpad/touch", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Trackpad touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_RIGHT_KNEE_TRACKER], "/user/vive_tracker_htcx/role/right_knee/input/trackpad/touch", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Trackpad touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_WAIST_TRACKER], "/user/vive_tracker_htcx/role/waist/input/trackpad/touch", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Trackpad touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_CHEST_TRACKER], "/user/vive_tracker_htcx/role/chest/input/trackpad/touch", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Trackpad touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_CAMERA_TRACKER], "/user/vive_tracker_htcx/role/camera/input/trackpad/touch", OpenXRAction::OPENXR_ACTION_BOOL },
- { "Trackpad touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_KEYBOARD_TRACKER], "/user/vive_tracker_htcx/role/keyboard/input/trackpad/touch", OpenXRAction::OPENXR_ACTION_BOOL },
-
- // { "Grip pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_HANDHELD_TRACKER], "/user/vive_tracker_htcx/role/handheld_object/input/grip/pose", OpenXRAction::OPENXR_ACTION_POSE },
- { "Grip pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_LEFT_FOOT_TRACKER], "/user/vive_tracker_htcx/role/left_foot/input/grip/pose", OpenXRAction::OPENXR_ACTION_POSE },
- { "Grip pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_RIGHT_FOOT_TRACKER], "/user/vive_tracker_htcx/role/right_foot/input/grip/pose", OpenXRAction::OPENXR_ACTION_POSE },
- { "Grip pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_LEFT_SHOULDER_TRACKER], "/user/vive_tracker_htcx/role/left_shoulder/input/grip/pose", OpenXRAction::OPENXR_ACTION_POSE },
- { "Grip pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_RIGHT_SHOULDER_TRACKER], "/user/vive_tracker_htcx/role/right_shoulder/input/grip/pose", OpenXRAction::OPENXR_ACTION_POSE },
- { "Grip pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_LEFT_ELBOW_TRACKER], "/user/vive_tracker_htcx/role/left_elbow/input/grip/pose", OpenXRAction::OPENXR_ACTION_POSE },
- { "Grip pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_RIGHT_ELBOW_TRACKER], "/user/vive_tracker_htcx/role/right_elbow/input/grip/pose", OpenXRAction::OPENXR_ACTION_POSE },
- { "Grip pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_LEFT_KNEE_TRACKER], "/user/vive_tracker_htcx/role/left_knee/input/grip/pose", OpenXRAction::OPENXR_ACTION_POSE },
- { "Grip pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_RIGHT_KNEE_TRACKER], "/user/vive_tracker_htcx/role/right_knee/input/grip/pose", OpenXRAction::OPENXR_ACTION_POSE },
- { "Grip pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_WAIST_TRACKER], "/user/vive_tracker_htcx/role/waist/input/grip/pose", OpenXRAction::OPENXR_ACTION_POSE },
- { "Grip pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_CHEST_TRACKER], "/user/vive_tracker_htcx/role/chest/input/grip/pose", OpenXRAction::OPENXR_ACTION_POSE },
- { "Grip pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_CAMERA_TRACKER], "/user/vive_tracker_htcx/role/camera/input/grip/pose", OpenXRAction::OPENXR_ACTION_POSE },
- { "Grip pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_KEYBOARD_TRACKER], "/user/vive_tracker_htcx/role/keyboard/input/grip/pose", OpenXRAction::OPENXR_ACTION_POSE },
-
- // { "Haptic output", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_HANDHELD_TRACKER], "/user/vive_tracker_htcx/role/handheld_object/output/haptic", OpenXRAction::OPENXR_ACTION_HAPTIC },
- { "Haptic output", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_LEFT_FOOT_TRACKER], "/user/vive_tracker_htcx/role/left_foot/output/haptic", OpenXRAction::OPENXR_ACTION_HAPTIC },
- { "Haptic output", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_RIGHT_FOOT_TRACKER], "/user/vive_tracker_htcx/role/right_foot/output/haptic", OpenXRAction::OPENXR_ACTION_HAPTIC },
- { "Haptic output", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_LEFT_SHOULDER_TRACKER], "/user/vive_tracker_htcx/role/left_shoulder/output/haptic", OpenXRAction::OPENXR_ACTION_HAPTIC },
- { "Haptic output", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_RIGHT_SHOULDER_TRACKER], "/user/vive_tracker_htcx/role/right_shoulder/output/haptic", OpenXRAction::OPENXR_ACTION_HAPTIC },
- { "Haptic output", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_LEFT_ELBOW_TRACKER], "/user/vive_tracker_htcx/role/left_elbow/output/haptic", OpenXRAction::OPENXR_ACTION_HAPTIC },
- { "Haptic output", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_RIGHT_ELBOW_TRACKER], "/user/vive_tracker_htcx/role/right_elbow/output/haptic", OpenXRAction::OPENXR_ACTION_HAPTIC },
- { "Haptic output", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_LEFT_KNEE_TRACKER], "/user/vive_tracker_htcx/role/left_knee/output/haptic", OpenXRAction::OPENXR_ACTION_HAPTIC },
- { "Haptic output", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_RIGHT_KNEE_TRACKER], "/user/vive_tracker_htcx/role/right_knee/output/haptic", OpenXRAction::OPENXR_ACTION_HAPTIC },
- { "Haptic output", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_WAIST_TRACKER], "/user/vive_tracker_htcx/role/waist/output/haptic", OpenXRAction::OPENXR_ACTION_HAPTIC },
- { "Haptic output", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_CHEST_TRACKER], "/user/vive_tracker_htcx/role/chest/output/haptic", OpenXRAction::OPENXR_ACTION_HAPTIC },
- { "Haptic output", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_CAMERA_TRACKER], "/user/vive_tracker_htcx/role/camera/output/haptic", OpenXRAction::OPENXR_ACTION_HAPTIC },
- { "Haptic output", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_KEYBOARD_TRACKER], "/user/vive_tracker_htcx/role/keyboard/output/haptic", OpenXRAction::OPENXR_ACTION_HAPTIC },
-};
-
-OpenXRDefs::InteractionProfile OpenXRDefs::available_interaction_profiles[] = {
- {
- "Simple controller", // display_name
- "/interaction_profiles/khr/simple_controller", // openxr_path
- simple_io_paths, // io_paths
- sizeof(simple_io_paths) / sizeof(OpenXRDefs::IOPath) // io_path_count
- },
- {
- "HTC Vive wand", // display_name
- "/interaction_profiles/htc/vive_controller", // openxr_path
- vive_io_paths, // io_paths
- sizeof(vive_io_paths) / sizeof(OpenXRDefs::IOPath) // io_path_count
- },
- {
- "MS Motion controller", // display_name
- "/interaction_profiles/microsoft/motion_controller", // openxr_path
- motion_io_paths, // io_paths
- sizeof(motion_io_paths) / sizeof(OpenXRDefs::IOPath) // io_path_count
- },
- {
- "HPMR controller", // display_name
- "/interaction_profiles/hp/mixed_reality_controller", // openxr_path
- hpmr_io_paths, // io_paths
- sizeof(hpmr_io_paths) / sizeof(OpenXRDefs::IOPath) // io_path_count
- },
- {
- "Touch controller", // display_name
- "/interaction_profiles/oculus/touch_controller", // openxr_path
- touch_io_paths, // io_paths
- sizeof(touch_io_paths) / sizeof(OpenXRDefs::IOPath) // io_path_count
- },
- {
- "Index controller", // display_name
- "/interaction_profiles/valve/index_controller", // openxr_path
- index_io_paths, // io_paths
- sizeof(index_io_paths) / sizeof(OpenXRDefs::IOPath) // io_path_count
- },
- {
- "Samsung Odyssey controller", // display_name
- "/interaction_profiles/samsung/odyssey_controller", // openxr_path
- odyssey_io_paths, // io_paths
- sizeof(odyssey_io_paths) / sizeof(OpenXRDefs::IOPath) // io_path_count
- },
- {
- "Vive Cosmos controller", // display_name
- "/interaction_profiles/htc/vive_cosmos_controller", // openxr_path
- vive_cosmos_paths, // io_paths
- sizeof(vive_cosmos_paths) / sizeof(OpenXRDefs::IOPath) // io_path_count
- },
- {
- "Vive Focus 3 controller", // display_name
- "/interaction_profiles/htc/vive_focus3_controller", // openxr_path
- vive_focus3_paths, // io_paths
- sizeof(vive_focus3_paths) / sizeof(OpenXRDefs::IOPath) // io_path_count
- },
- {
- "Huawei controller", // display_name
- "/interaction_profiles/huawei/controller", // openxr_path
- huawei_controller_paths, // io_paths
- sizeof(huawei_controller_paths) / sizeof(OpenXRDefs::IOPath) // io_path_count
- },
-
- {
- "HTC Vive tracker", // display_name
- "/interaction_profiles/htc/vive_tracker_htcx", // openxr_path
- vive_tracker_controller_paths, // io_paths
- sizeof(vive_tracker_controller_paths) / sizeof(OpenXRDefs::IOPath) // io_path_count
- },
-};
-
-int OpenXRDefs::available_interaction_profile_count = sizeof(OpenXRDefs::available_interaction_profiles) / sizeof(OpenXRDefs::InteractionProfile);
-
-const OpenXRDefs::TopLevelPath *OpenXRDefs::get_top_level_path(const String p_top_level_path) {
- for (int i = 0; i < OPENXR_TOP_LEVEL_PATH_MAX; i++) {
- if (available_top_level_paths[i].openxr_path == p_top_level_path) {
- return &OpenXRDefs::available_top_level_paths[i];
- }
- }
-
- return nullptr;
-}
-
-const OpenXRDefs::InteractionProfile *OpenXRDefs::get_profile(const String p_interaction_profile_path) {
- for (int i = 0; i < available_interaction_profile_count; i++) {
- if (available_interaction_profiles[i].openxr_path == p_interaction_profile_path) {
- return &available_interaction_profiles[i];
- }
- }
-
- return nullptr;
-}
-
-const OpenXRDefs::IOPath *OpenXRDefs::InteractionProfile::get_io_path(const String p_io_path) const {
- for (int i = 0; i < available_interaction_profiles[i].io_path_count; i++) {
- if (io_paths[i].openxr_path == p_io_path) {
- return &io_paths[i];
- }
- }
-
- return nullptr;
-}
-
-const OpenXRDefs::IOPath *OpenXRDefs::get_io_path(const String p_interaction_profile_path, const String p_io_path) {
- const OpenXRDefs::InteractionProfile *profile = OpenXRDefs::get_profile(p_interaction_profile_path);
- if (profile != nullptr) {
- return profile->get_io_path(p_io_path);
- }
-
- return nullptr;
-}
-
-PackedStringArray OpenXRDefs::get_interaction_profile_paths() {
- PackedStringArray arr;
-
- for (int i = 0; i < available_interaction_profile_count; i++) {
- arr.push_back(available_interaction_profiles[i].openxr_path);
- }
-
- return arr;
-}
diff --git a/modules/openxr/action_map/openxr_defs.h b/modules/openxr/action_map/openxr_defs.h
deleted file mode 100644
index 446e6eb9c6..0000000000
--- a/modules/openxr/action_map/openxr_defs.h
+++ /dev/null
@@ -1,124 +0,0 @@
-/*************************************************************************/
-/* openxr_defs.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 OPENXR_DEFS_H
-#define OPENXR_DEFS_H
-
-#include "openxr_action.h"
-
-///////////////////////////////////////////////////////////////////////////
-// Stores available interaction profiles
-//
-// OpenXR defines and hardcodes all the supported input devices and their
-// paths as part of the OpenXR spec. When support for new devices is
-// introduced this often starts life as extensions that need to be enabled
-// until they are adopted into the core. As there is no interface to
-// enumerate the possibly paths, and that any OpenXR runtime would likely
-// limit such enumeration to those input devices supported by that runtime
-// there is no other option than to hardcode this.
-//
-// Note on action type that automatic conversions between boolean and float
-// are supported but otherwise action types should match between action and
-// input/output paths.
-
-class OpenXRDefs {
-public:
- enum TOP_LEVEL_PATH {
- // Core OpenXR toplevel paths
- OPENXR_LEFT_HAND,
- OPENXR_RIGHT_HAND,
- OPENXR_HEAD,
- OPENXR_GAMEPAD,
- OPENXR_TREADMILL,
-
- // HTC tracker extension toplevel paths
- // OPENXR_HTC_HANDHELD_TRACKER,
- OPENXR_HTC_LEFT_FOOT_TRACKER,
- OPENXR_HTC_RIGHT_FOOT_TRACKER,
- OPENXR_HTC_LEFT_SHOULDER_TRACKER,
- OPENXR_HTC_RIGHT_SHOULDER_TRACKER,
- OPENXR_HTC_LEFT_ELBOW_TRACKER,
- OPENXR_HTC_RIGHT_ELBOW_TRACKER,
- OPENXR_HTC_LEFT_KNEE_TRACKER,
- OPENXR_HTC_RIGHT_KNEE_TRACKER,
- OPENXR_HTC_WAIST_TRACKER,
- OPENXR_HTC_CHEST_TRACKER,
- OPENXR_HTC_CAMERA_TRACKER,
- OPENXR_HTC_KEYBOARD_TRACKER,
-
- OPENXR_TOP_LEVEL_PATH_MAX
- };
-
- struct TopLevelPath {
- const char *display_name; // User friendly display name (i.e. Left controller)
- const char *openxr_path; // Path in OpenXR (i.e. /user/hand/left)
- };
-
- struct IOPath {
- const char *display_name; // User friendly display name (i.e. Grip pose (left controller))
- const TopLevelPath *top_level_path; // Top level path identifying the usage of the device in relation to this input/output
- const char *openxr_path; // Path in OpenXR (i.e. /user/hand/left/input/grip/pose)
- const OpenXRAction::ActionType action_type; // Type of input/output
- };
-
- struct InteractionProfile {
- const char *display_name; // User friendly display name (i.e. Simple controller)
- const char *openxr_path; // Path in OpenXR (i.e. /interaction_profiles/khr/simple_controller)
- const IOPath *io_paths; // Inputs and outputs for this device
- const int io_path_count; // Number of inputs and outputs for this device
-
- const IOPath *get_io_path(const String p_io_path) const;
- };
-
-private:
- static TopLevelPath available_top_level_paths[OPENXR_TOP_LEVEL_PATH_MAX];
- static IOPath simple_io_paths[];
- static IOPath vive_io_paths[];
- static IOPath motion_io_paths[];
- static IOPath hpmr_io_paths[];
- static IOPath touch_io_paths[];
- static IOPath index_io_paths[];
- static IOPath odyssey_io_paths[];
- static IOPath vive_cosmos_paths[];
- static IOPath vive_focus3_paths[];
- static IOPath huawei_controller_paths[];
- static IOPath vive_tracker_controller_paths[];
- static InteractionProfile available_interaction_profiles[];
- static int available_interaction_profile_count;
-
-public:
- static const TopLevelPath *get_top_level_path(const String p_top_level_path);
- static const InteractionProfile *get_profile(const String p_interaction_profile_path);
- static const IOPath *get_io_path(const String p_interaction_profile_path, const String p_io_path);
-
- static PackedStringArray get_interaction_profile_paths();
-};
-
-#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 99d7a17acf..8bb657a2db 100644
--- a/modules/openxr/action_map/openxr_interaction_profile.cpp
+++ b/modules/openxr/action_map/openxr_interaction_profile.cpp
@@ -38,7 +38,7 @@ void OpenXRIPBinding::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_path_count"), &OpenXRIPBinding::get_path_count);
ClassDB::bind_method(D_METHOD("set_paths", "paths"), &OpenXRIPBinding::set_paths);
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");
+ ADD_PROPERTY(PropertyInfo(Variant::PACKED_STRING_ARRAY, "paths"), "set_paths", "get_paths");
ClassDB::bind_method(D_METHOD("has_path", "path"), &OpenXRIPBinding::has_path);
ClassDB::bind_method(D_METHOD("add_path", "path"), &OpenXRIPBinding::add_path);
@@ -58,6 +58,7 @@ Ref<OpenXRIPBinding> OpenXRIPBinding::new_binding(const Ref<OpenXRAction> p_acti
void OpenXRIPBinding::set_action(const Ref<OpenXRAction> p_action) {
action = p_action;
+ emit_changed();
}
Ref<OpenXRAction> OpenXRIPBinding::get_action() const {
@@ -70,6 +71,7 @@ int OpenXRIPBinding::get_path_count() const {
void OpenXRIPBinding::set_paths(const PackedStringArray p_paths) {
paths = p_paths;
+ emit_changed();
}
PackedStringArray OpenXRIPBinding::get_paths() const {
@@ -78,6 +80,7 @@ PackedStringArray OpenXRIPBinding::get_paths() const {
void OpenXRIPBinding::parse_paths(const String p_paths) {
paths = p_paths.split(",", false);
+ emit_changed();
}
bool OpenXRIPBinding::has_path(const String p_path) const {
@@ -87,12 +90,14 @@ bool OpenXRIPBinding::has_path(const String p_path) const {
void OpenXRIPBinding::add_path(const String p_path) {
if (!paths.has(p_path)) {
paths.push_back(p_path);
+ emit_changed();
}
}
void OpenXRIPBinding::remove_path(const String p_path) {
if (paths.has(p_path)) {
paths.erase(p_path);
+ emit_changed();
}
}
@@ -122,6 +127,7 @@ Ref<OpenXRInteractionProfile> OpenXRInteractionProfile::new_profile(const char *
void OpenXRInteractionProfile::set_interaction_profile_path(const String p_input_profile_path) {
interaction_profile_path = p_input_profile_path;
+ emit_changed();
}
String OpenXRInteractionProfile::get_interaction_profile_path() const {
@@ -139,9 +145,10 @@ Ref<OpenXRIPBinding> OpenXRInteractionProfile::get_binding(int p_index) const {
}
void OpenXRInteractionProfile::set_bindings(Array p_bindings) {
- bindings = p_bindings;
-
// TODO add check here that our bindings don't contain duplicate actions
+
+ bindings = p_bindings;
+ emit_changed();
}
Array OpenXRInteractionProfile::get_bindings() const {
@@ -166,6 +173,7 @@ void OpenXRInteractionProfile::add_binding(Ref<OpenXRIPBinding> p_binding) {
ERR_FAIL_COND_MSG(get_binding_for_action(p_binding->get_action()).is_valid(), "There is already a binding for this action in this interaction profile");
bindings.push_back(p_binding);
+ emit_changed();
}
}
@@ -173,6 +181,7 @@ void OpenXRInteractionProfile::remove_binding(Ref<OpenXRIPBinding> p_binding) {
int idx = bindings.find(p_binding);
if (idx != -1) {
bindings.remove_at(idx);
+ emit_changed();
}
}
@@ -192,6 +201,17 @@ void OpenXRInteractionProfile::remove_binding_for_action(const Ref<OpenXRAction>
}
}
+bool OpenXRInteractionProfile::has_binding_for_action(const Ref<OpenXRAction> p_action) {
+ for (int i = bindings.size() - 1; i >= 0; i--) {
+ Ref<OpenXRIPBinding> binding = bindings[i];
+ if (binding->get_action() == p_action) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
OpenXRInteractionProfile::~OpenXRInteractionProfile() {
bindings.clear();
}
diff --git a/modules/openxr/action_map/openxr_interaction_profile.h b/modules/openxr/action_map/openxr_interaction_profile.h
index c77fd490bb..c7db77870e 100644
--- a/modules/openxr/action_map/openxr_interaction_profile.h
+++ b/modules/openxr/action_map/openxr_interaction_profile.h
@@ -34,7 +34,7 @@
#include "core/io/resource.h"
#include "openxr_action.h"
-#include "openxr_defs.h"
+#include "openxr_interaction_profile_meta_data.h"
class OpenXRIPBinding : public Resource {
GDCLASS(OpenXRIPBinding, Resource);
@@ -94,6 +94,7 @@ public:
void add_new_binding(const Ref<OpenXRAction> p_action, const char *p_paths); // Create a new binding for this profile
void remove_binding_for_action(const Ref<OpenXRAction> p_action); // Remove all bindings for this action
+ bool has_binding_for_action(const Ref<OpenXRAction> p_action); // Returns true if we have a binding for this action
~OpenXRInteractionProfile();
};
diff --git a/modules/openxr/action_map/openxr_interaction_profile_meta_data.cpp b/modules/openxr/action_map/openxr_interaction_profile_meta_data.cpp
new file mode 100644
index 0000000000..db4062b196
--- /dev/null
+++ b/modules/openxr/action_map/openxr_interaction_profile_meta_data.cpp
@@ -0,0 +1,713 @@
+/*************************************************************************/
+/* openxr_interaction_profile_meta_data.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 "openxr_interaction_profile_meta_data.h"
+
+#include <openxr/openxr.h>
+
+OpenXRInteractionProfileMetaData *OpenXRInteractionProfileMetaData::singleton = nullptr;
+
+OpenXRInteractionProfileMetaData::OpenXRInteractionProfileMetaData() {
+ singleton = this;
+
+ _register_core_metadata();
+}
+
+OpenXRInteractionProfileMetaData::~OpenXRInteractionProfileMetaData() {
+ singleton = nullptr;
+}
+
+void OpenXRInteractionProfileMetaData::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("register_top_level_path", "display_name", "openxr_path", "openxr_extension_name"), &OpenXRInteractionProfileMetaData::register_top_level_path);
+ ClassDB::bind_method(D_METHOD("register_interaction_profile", "display_name", "openxr_path", "openxr_extension_name"), &OpenXRInteractionProfileMetaData::register_interaction_profile);
+ ClassDB::bind_method(D_METHOD("register_io_path", "interaction_profile", "display_name", "toplevel_path", "openxr_path", "openxr_extension_name", "action_type"), &OpenXRInteractionProfileMetaData::register_io_path);
+}
+
+void OpenXRInteractionProfileMetaData::register_top_level_path(const String &p_display_name, const String &p_openxr_path, const String &p_openxr_extension_name) {
+ ERR_FAIL_COND_MSG(has_top_level_path(p_openxr_path), p_openxr_path + " had already been registered");
+
+ TopLevelPath new_toplevel_path = {
+ p_display_name,
+ p_openxr_path,
+ p_openxr_extension_name
+ };
+
+ top_level_paths.push_back(new_toplevel_path);
+}
+
+void OpenXRInteractionProfileMetaData::register_interaction_profile(const String &p_display_name, const String &p_openxr_path, const String &p_openxr_extension_name) {
+ ERR_FAIL_COND_MSG(has_interaction_profile(p_openxr_path), p_openxr_path + " has already been registered");
+
+ InteractionProfile new_profile;
+ new_profile.display_name = p_display_name;
+ new_profile.openxr_path = p_openxr_path;
+ new_profile.openxr_extension_name = p_openxr_extension_name;
+
+ interaction_profiles.push_back(new_profile);
+}
+
+void OpenXRInteractionProfileMetaData::register_io_path(const String &p_interaction_profile, const String &p_display_name, const String &p_toplevel_path, const String &p_openxr_path, const String &p_openxr_extension_name, OpenXRAction::ActionType p_action_type) {
+ ERR_FAIL_COND_MSG(!has_interaction_profile(p_interaction_profile), "Unknown interaction profile " + p_interaction_profile);
+ ERR_FAIL_COND_MSG(!has_top_level_path(p_toplevel_path), "Unknown top level path " + p_toplevel_path);
+
+ for (int i = 0; i < interaction_profiles.size(); i++) {
+ if (interaction_profiles[i].openxr_path == p_interaction_profile) {
+ ERR_FAIL_COND_MSG(interaction_profiles[i].has_io_path(p_openxr_path), p_interaction_profile + " already has io path " + p_openxr_path + " registered!");
+
+ IOPath new_io_path = {
+ p_display_name,
+ p_toplevel_path,
+ p_openxr_path,
+ p_openxr_extension_name,
+ p_action_type
+ };
+
+ interaction_profiles.ptrw()[i].io_paths.push_back(new_io_path);
+ }
+ }
+}
+
+bool OpenXRInteractionProfileMetaData::has_top_level_path(const String p_openxr_path) const {
+ for (int i = 0; i < top_level_paths.size(); i++) {
+ if (top_level_paths[i].openxr_path == p_openxr_path) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+String OpenXRInteractionProfileMetaData::get_top_level_name(const String p_openxr_path) const {
+ for (int i = 0; i < top_level_paths.size(); i++) {
+ if (top_level_paths[i].openxr_path == p_openxr_path) {
+ return top_level_paths[i].display_name;
+ }
+ }
+
+ return String();
+}
+
+String OpenXRInteractionProfileMetaData::get_top_level_extension(const String p_openxr_path) const {
+ for (int i = 0; i < top_level_paths.size(); i++) {
+ if (top_level_paths[i].openxr_path == p_openxr_path) {
+ return top_level_paths[i].openxr_extension_name;
+ }
+ }
+
+ return XR_PATH_UNSUPPORTED_NAME;
+}
+
+bool OpenXRInteractionProfileMetaData::has_interaction_profile(const String p_openxr_path) const {
+ for (int i = 0; i < interaction_profiles.size(); i++) {
+ if (interaction_profiles[i].openxr_path == p_openxr_path) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+String OpenXRInteractionProfileMetaData::get_interaction_profile_extension(const String p_openxr_path) const {
+ for (int i = 0; i < interaction_profiles.size(); i++) {
+ if (interaction_profiles[i].openxr_path == p_openxr_path) {
+ return interaction_profiles[i].openxr_extension_name;
+ }
+ }
+
+ return XR_PATH_UNSUPPORTED_NAME;
+}
+
+const OpenXRInteractionProfileMetaData::InteractionProfile *OpenXRInteractionProfileMetaData::get_profile(const String p_openxr_path) const {
+ for (int i = 0; i < interaction_profiles.size(); i++) {
+ if (interaction_profiles[i].openxr_path == p_openxr_path) {
+ return &interaction_profiles[i];
+ }
+ }
+
+ return nullptr;
+}
+
+bool OpenXRInteractionProfileMetaData::InteractionProfile::has_io_path(const String p_io_path) const {
+ for (int i = 0; i < io_paths.size(); i++) {
+ if (io_paths[i].openxr_path == p_io_path) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+const OpenXRInteractionProfileMetaData::IOPath *OpenXRInteractionProfileMetaData::InteractionProfile::get_io_path(const String p_io_path) const {
+ for (int i = 0; i < io_paths.size(); i++) {
+ if (io_paths[i].openxr_path == p_io_path) {
+ return &io_paths[i];
+ }
+ }
+
+ return nullptr;
+}
+
+const OpenXRInteractionProfileMetaData::IOPath *OpenXRInteractionProfileMetaData::get_io_path(const String p_interaction_profile, const String p_io_path) const {
+ const OpenXRInteractionProfileMetaData::InteractionProfile *profile = get_profile(p_interaction_profile);
+ if (profile != nullptr) {
+ return profile->get_io_path(p_io_path);
+ }
+
+ return nullptr;
+}
+
+PackedStringArray OpenXRInteractionProfileMetaData::get_interaction_profile_paths() const {
+ PackedStringArray arr;
+
+ for (int i = 0; i < interaction_profiles.size(); i++) {
+ arr.push_back(interaction_profiles[i].openxr_path);
+ }
+
+ return arr;
+}
+
+void OpenXRInteractionProfileMetaData::_register_core_metadata() {
+ // Note, currently we add definitions that belong in extensions.
+ // Extensions are registered when our OpenXRAPI is instantiated
+ // however this does not happen in the editor.
+ // We are changing this in another PR, once that is accepted we
+ // can make the changes to move code into extensions where needed.
+
+ // Note that we'll make an exception for XR_EXT_palm_pose, which is used everywhere
+
+ // Our core toplevel paths
+ register_top_level_path("Left hand controller", "/user/hand/left", "");
+ register_top_level_path("Right hand controller", "/user/hand/right", "");
+ register_top_level_path("Head", "/user/head", "");
+ register_top_level_path("Gamepad", "/user/gamepad", "");
+ register_top_level_path("Treadmill", "/user/treadmill", "");
+
+ // TODO move this into OpenXRHTCViveTrackerExtension once this is supported.
+ // register_top_level_path("Handheld object tracker", "/user/vive_tracker_htcx/role/handheld_object", XR_HTCX_VIVE_TRACKER_INTERACTION_EXTENSION_NAME);
+ register_top_level_path("Left foot tracker", "/user/vive_tracker_htcx/role/left_foot", XR_HTCX_VIVE_TRACKER_INTERACTION_EXTENSION_NAME);
+ register_top_level_path("Right foot tracker", "/user/vive_tracker_htcx/role/right_foot", XR_HTCX_VIVE_TRACKER_INTERACTION_EXTENSION_NAME);
+ register_top_level_path("Left shoulder tracker", "/user/vive_tracker_htcx/role/left_shoulder", XR_HTCX_VIVE_TRACKER_INTERACTION_EXTENSION_NAME);
+ register_top_level_path("Right shoulder tracker", "/user/vive_tracker_htcx/role/right_shoulder", XR_HTCX_VIVE_TRACKER_INTERACTION_EXTENSION_NAME);
+ register_top_level_path("Left elbow tracker", "/user/vive_tracker_htcx/role/left_elbow", XR_HTCX_VIVE_TRACKER_INTERACTION_EXTENSION_NAME);
+ register_top_level_path("Right elbow tracker", "/user/vive_tracker_htcx/role/right_elbow", XR_HTCX_VIVE_TRACKER_INTERACTION_EXTENSION_NAME);
+ register_top_level_path("Left knee tracker", "/user/vive_tracker_htcx/role/left_knee", XR_HTCX_VIVE_TRACKER_INTERACTION_EXTENSION_NAME);
+ register_top_level_path("Right knee tracker", "/user/vive_tracker_htcx/role/right_knee", XR_HTCX_VIVE_TRACKER_INTERACTION_EXTENSION_NAME);
+ register_top_level_path("Waist tracker", "/user/vive_tracker_htcx/role/waist", XR_HTCX_VIVE_TRACKER_INTERACTION_EXTENSION_NAME);
+ register_top_level_path("Chest tracker", "/user/vive_tracker_htcx/role/chest", XR_HTCX_VIVE_TRACKER_INTERACTION_EXTENSION_NAME);
+ register_top_level_path("Camera tracker", "/user/vive_tracker_htcx/role/camera", XR_HTCX_VIVE_TRACKER_INTERACTION_EXTENSION_NAME);
+ register_top_level_path("Keyboard tracker", "/user/vive_tracker_htcx/role/keyboard", XR_HTCX_VIVE_TRACKER_INTERACTION_EXTENSION_NAME);
+
+ // Fallback Khronos simple controller
+ register_interaction_profile("Simple controller", "/interaction_profiles/khr/simple_controller", "");
+ register_io_path("/interaction_profiles/khr/simple_controller", "Grip pose", "/user/hand/left", "/user/hand/left/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
+ register_io_path("/interaction_profiles/khr/simple_controller", "Grip pose", "/user/hand/right", "/user/hand/right/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
+ register_io_path("/interaction_profiles/khr/simple_controller", "Aim pose", "/user/hand/left", "/user/hand/left/input/aim/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
+ register_io_path("/interaction_profiles/khr/simple_controller", "Aim pose", "/user/hand/right", "/user/hand/right/input/aim/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
+ register_io_path("/interaction_profiles/khr/simple_controller", "Palm pose", "/user/hand/left", "/user/hand/left/input/palm_ext/pose", XR_EXT_PALM_POSE_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_POSE);
+ register_io_path("/interaction_profiles/khr/simple_controller", "Palm pose", "/user/hand/right", "/user/hand/right/input/palm_ext/pose", XR_EXT_PALM_POSE_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_POSE);
+
+ register_io_path("/interaction_profiles/khr/simple_controller", "Menu click", "/user/hand/left", "/user/hand/left/input/menu/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/khr/simple_controller", "Menu click", "/user/hand/right", "/user/hand/right/input/menu/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/khr/simple_controller", "Select click", "/user/hand/left", "/user/hand/left/input/select/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/khr/simple_controller", "Select click", "/user/hand/right", "/user/hand/right/input/select/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+
+ register_io_path("/interaction_profiles/khr/simple_controller", "Haptic output", "/user/hand/left", "/user/hand/left/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC);
+ register_io_path("/interaction_profiles/khr/simple_controller", "Haptic output", "/user/hand/right", "/user/hand/right/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC);
+
+ // Original HTC Vive wands
+ register_interaction_profile("HTC Vive wand", "/interaction_profiles/htc/vive_controller", "");
+ register_io_path("/interaction_profiles/htc/vive_controller", "Grip pose", "/user/hand/left", "/user/hand/left/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
+ register_io_path("/interaction_profiles/htc/vive_controller", "Grip pose", "/user/hand/right", "/user/hand/right/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
+ register_io_path("/interaction_profiles/htc/vive_controller", "Aim pose", "/user/hand/left", "/user/hand/left/input/aim/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
+ register_io_path("/interaction_profiles/htc/vive_controller", "Aim pose", "/user/hand/right", "/user/hand/right/input/aim/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
+ register_io_path("/interaction_profiles/htc/vive_controller", "Palm pose", "/user/hand/left", "/user/hand/left/input/palm_ext/pose", XR_EXT_PALM_POSE_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_POSE);
+ register_io_path("/interaction_profiles/htc/vive_controller", "Palm pose", "/user/hand/right", "/user/hand/right/input/palm_ext/pose", XR_EXT_PALM_POSE_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_POSE);
+
+ register_io_path("/interaction_profiles/htc/vive_controller", "Menu click", "/user/hand/left", "/user/hand/left/input/menu/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_controller", "Menu click", "/user/hand/right", "/user/hand/right/input/menu/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_controller", "System click", "/user/hand/left", "/user/hand/left/input/system/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_controller", "System click", "/user/hand/right", "/user/hand/right/input/system/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+
+ register_io_path("/interaction_profiles/htc/vive_controller", "Trigger", "/user/hand/left", "/user/hand/left/input/trigger/value", "", OpenXRAction::OPENXR_ACTION_FLOAT);
+ register_io_path("/interaction_profiles/htc/vive_controller", "Trigger click", "/user/hand/left", "/user/hand/left/input/trigger/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_controller", "Trigger", "/user/hand/right", "/user/hand/right/input/trigger/value", "", OpenXRAction::OPENXR_ACTION_FLOAT);
+ register_io_path("/interaction_profiles/htc/vive_controller", "Trigger click", "/user/hand/right", "/user/hand/right/input/trigger/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+
+ register_io_path("/interaction_profiles/htc/vive_controller", "Squeeze click", "/user/hand/left", "/user/hand/left/input/squeeze/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_controller", "Squeeze click", "/user/hand/right", "/user/hand/right/input/squeeze/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+
+ register_io_path("/interaction_profiles/htc/vive_controller", "Trackpad", "/user/hand/left", "/user/hand/left/input/trackpad", "", OpenXRAction::OPENXR_ACTION_VECTOR2);
+ register_io_path("/interaction_profiles/htc/vive_controller", "Trackpad click", "/user/hand/left", "/user/hand/left/input/trackpad/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_controller", "Trackpad touch", "/user/hand/left", "/user/hand/left/input/trackpad/touch", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_controller", "Trackpad", "/user/hand/right", "/user/hand/right/input/trackpad", "", OpenXRAction::OPENXR_ACTION_VECTOR2);
+ register_io_path("/interaction_profiles/htc/vive_controller", "Trackpad click", "/user/hand/right", "/user/hand/right/input/trackpad/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_controller", "Trackpad touch", "/user/hand/right", "/user/hand/right/input/trackpad/touch", "", OpenXRAction::OPENXR_ACTION_BOOL);
+
+ register_io_path("/interaction_profiles/htc/vive_controller", "Haptic output", "/user/hand/left", "/user/hand/left/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC);
+ register_io_path("/interaction_profiles/htc/vive_controller", "Haptic output", "/user/hand/right", "/user/hand/right/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC);
+
+ // Microsoft motion controller (original WMR controllers)
+ register_interaction_profile("MS Motion controller", "/interaction_profiles/microsoft/motion_controller", "");
+ register_io_path("/interaction_profiles/microsoft/motion_controller", "Grip pose", "/user/hand/left", "/user/hand/left/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
+ register_io_path("/interaction_profiles/microsoft/motion_controller", "Grip pose", "/user/hand/right", "/user/hand/right/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
+ register_io_path("/interaction_profiles/microsoft/motion_controller", "Aim pose", "/user/hand/left", "/user/hand/left/input/aim/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
+ register_io_path("/interaction_profiles/microsoft/motion_controller", "Aim pose", "/user/hand/right", "/user/hand/right/input/aim/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
+ register_io_path("/interaction_profiles/microsoft/motion_controller", "Palm pose", "/user/hand/left", "/user/hand/left/input/palm_ext/pose", XR_EXT_PALM_POSE_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_POSE);
+ register_io_path("/interaction_profiles/microsoft/motion_controller", "Palm pose", "/user/hand/right", "/user/hand/right/input/palm_ext/pose", XR_EXT_PALM_POSE_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_POSE);
+
+ register_io_path("/interaction_profiles/microsoft/motion_controller", "Menu click", "/user/hand/left", "/user/hand/left/input/menu/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/microsoft/motion_controller", "Menu click", "/user/hand/right", "/user/hand/right/input/menu/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+
+ register_io_path("/interaction_profiles/microsoft/motion_controller", "Trigger", "/user/hand/left", "/user/hand/left/input/trigger/value", "", OpenXRAction::OPENXR_ACTION_FLOAT);
+ register_io_path("/interaction_profiles/microsoft/motion_controller", "Trigger click", "/user/hand/left", "/user/hand/left/input/trigger/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/microsoft/motion_controller", "Trigger", "/user/hand/right", "/user/hand/right/input/trigger/value", "", OpenXRAction::OPENXR_ACTION_FLOAT);
+ register_io_path("/interaction_profiles/microsoft/motion_controller", "Trigger click", "/user/hand/right", "/user/hand/right/input/trigger/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+
+ register_io_path("/interaction_profiles/microsoft/motion_controller", "Squeeze click", "/user/hand/left", "/user/hand/left/input/squeeze/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/microsoft/motion_controller", "Squeeze click", "/user/hand/right", "/user/hand/right/input/squeeze/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+
+ register_io_path("/interaction_profiles/microsoft/motion_controller", "Thumbstick", "/user/hand/left", "/user/hand/left/input/thumbstick", "", OpenXRAction::OPENXR_ACTION_VECTOR2);
+ register_io_path("/interaction_profiles/microsoft/motion_controller", "Thumbstick click", "/user/hand/left", "/user/hand/left/input/thumbstick/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/microsoft/motion_controller", "Thumbstick", "/user/hand/right", "/user/hand/right/input/thumbstick", "", OpenXRAction::OPENXR_ACTION_VECTOR2);
+ register_io_path("/interaction_profiles/microsoft/motion_controller", "Thumbstick click", "/user/hand/right", "/user/hand/right/input/thumbstick/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+
+ register_io_path("/interaction_profiles/microsoft/motion_controller", "Trackpad", "/user/hand/left", "/user/hand/left/input/trackpad", "", OpenXRAction::OPENXR_ACTION_VECTOR2);
+ register_io_path("/interaction_profiles/microsoft/motion_controller", "Trackpad click", "/user/hand/left", "/user/hand/left/input/trackpad/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/microsoft/motion_controller", "Trackpad touch", "/user/hand/left", "/user/hand/left/input/trackpad/touch", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/microsoft/motion_controller", "Trackpad", "/user/hand/right", "/user/hand/right/input/trackpad", "", OpenXRAction::OPENXR_ACTION_VECTOR2);
+ register_io_path("/interaction_profiles/microsoft/motion_controller", "Trackpad click", "/user/hand/right", "/user/hand/right/input/trackpad/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/microsoft/motion_controller", "Trackpad touch", "/user/hand/right", "/user/hand/right/input/trackpad/touch", "", OpenXRAction::OPENXR_ACTION_BOOL);
+
+ register_io_path("/interaction_profiles/microsoft/motion_controller", "Haptic output", "/user/hand/left", "/user/hand/left/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC);
+ register_io_path("/interaction_profiles/microsoft/motion_controller", "Haptic output", "/user/hand/right", "/user/hand/right/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC);
+
+ // Meta touch controller (original touch controllers, Quest 1 and Quest 2 controllers)
+ register_interaction_profile("Touch controller", "/interaction_profiles/oculus/touch_controller", "");
+ register_io_path("/interaction_profiles/oculus/touch_controller", "Grip pose", "/user/hand/left", "/user/hand/left/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
+ register_io_path("/interaction_profiles/oculus/touch_controller", "Grip pose", "/user/hand/right", "/user/hand/right/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
+ register_io_path("/interaction_profiles/oculus/touch_controller", "Aim pose", "/user/hand/left", "/user/hand/left/input/aim/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
+ register_io_path("/interaction_profiles/oculus/touch_controller", "Aim pose", "/user/hand/right", "/user/hand/right/input/aim/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
+ register_io_path("/interaction_profiles/oculus/touch_controller", "Palm pose", "/user/hand/left", "/user/hand/left/input/palm_ext/pose", XR_EXT_PALM_POSE_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_POSE);
+ register_io_path("/interaction_profiles/oculus/touch_controller", "Palm pose", "/user/hand/right", "/user/hand/right/input/palm_ext/pose", XR_EXT_PALM_POSE_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_POSE);
+
+ register_io_path("/interaction_profiles/oculus/touch_controller", "Menu click", "/user/hand/left", "/user/hand/left/input/menu/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/oculus/touch_controller", "System click", "/user/hand/right", "/user/hand/right/input/system/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+
+ register_io_path("/interaction_profiles/oculus/touch_controller", "X click", "/user/hand/left", "/user/hand/left/input/x/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/oculus/touch_controller", "X touch", "/user/hand/left", "/user/hand/left/input/x/touch", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/oculus/touch_controller", "Y click", "/user/hand/left", "/user/hand/left/input/y/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/oculus/touch_controller", "Y touch", "/user/hand/left", "/user/hand/left/input/y/touch", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/oculus/touch_controller", "A click", "/user/hand/right", "/user/hand/right/input/a/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/oculus/touch_controller", "A touch", "/user/hand/right", "/user/hand/right/input/a/touch", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/oculus/touch_controller", "B click", "/user/hand/right", "/user/hand/right/input/b/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/oculus/touch_controller", "B touch", "/user/hand/right", "/user/hand/right/input/b/touch", "", OpenXRAction::OPENXR_ACTION_BOOL);
+
+ register_io_path("/interaction_profiles/oculus/touch_controller", "Trigger", "/user/hand/left", "/user/hand/left/input/trigger/value", "", OpenXRAction::OPENXR_ACTION_FLOAT);
+ register_io_path("/interaction_profiles/oculus/touch_controller", "Trigger touch", "/user/hand/left", "/user/hand/left/input/trigger/touch", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/oculus/touch_controller", "Trigger", "/user/hand/right", "/user/hand/right/input/trigger/value", "", OpenXRAction::OPENXR_ACTION_FLOAT);
+ register_io_path("/interaction_profiles/oculus/touch_controller", "Trigger touch", "/user/hand/right", "/user/hand/right/input/trigger/touch", "", OpenXRAction::OPENXR_ACTION_BOOL);
+
+ register_io_path("/interaction_profiles/oculus/touch_controller", "Squeeze", "/user/hand/left", "/user/hand/left/input/squeeze/value", "", OpenXRAction::OPENXR_ACTION_FLOAT);
+ register_io_path("/interaction_profiles/oculus/touch_controller", "Squeeze", "/user/hand/right", "/user/hand/right/input/squeeze/value", "", OpenXRAction::OPENXR_ACTION_FLOAT);
+
+ register_io_path("/interaction_profiles/oculus/touch_controller", "Thumbstick", "/user/hand/left", "/user/hand/left/input/thumbstick", "", OpenXRAction::OPENXR_ACTION_VECTOR2);
+ register_io_path("/interaction_profiles/oculus/touch_controller", "Thumbstick click", "/user/hand/left", "/user/hand/left/input/thumbstick/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/oculus/touch_controller", "Thumbstick touch", "/user/hand/left", "/user/hand/left/input/thumbstick/touch", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/oculus/touch_controller", "Thumbstick", "/user/hand/right", "/user/hand/right/input/thumbstick", "", OpenXRAction::OPENXR_ACTION_VECTOR2);
+ register_io_path("/interaction_profiles/oculus/touch_controller", "Thumbstick click", "/user/hand/right", "/user/hand/right/input/thumbstick/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/oculus/touch_controller", "Thumbstick touch", "/user/hand/right", "/user/hand/right/input/thumbstick/touch", "", OpenXRAction::OPENXR_ACTION_BOOL);
+
+ register_io_path("/interaction_profiles/oculus/touch_controller", "Haptic output", "/user/hand/left", "/user/hand/left/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC);
+ register_io_path("/interaction_profiles/oculus/touch_controller", "Haptic output", "/user/hand/right", "/user/hand/right/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC);
+
+ // Valve Index controller
+ register_interaction_profile("Index controller", "/interaction_profiles/valve/index_controller", "");
+ register_io_path("/interaction_profiles/valve/index_controller", "Grip pose", "/user/hand/left", "/user/hand/left/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
+ register_io_path("/interaction_profiles/valve/index_controller", "Grip pose", "/user/hand/right", "/user/hand/right/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
+ register_io_path("/interaction_profiles/valve/index_controller", "Aim pose", "/user/hand/left", "/user/hand/left/input/aim/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
+ register_io_path("/interaction_profiles/valve/index_controller", "Aim pose", "/user/hand/right", "/user/hand/right/input/aim/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
+ register_io_path("/interaction_profiles/valve/index_controller", "Palm pose", "/user/hand/left", "/user/hand/left/input/palm_ext/pose", XR_EXT_PALM_POSE_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_POSE);
+ register_io_path("/interaction_profiles/valve/index_controller", "Palm pose", "/user/hand/right", "/user/hand/right/input/palm_ext/pose", XR_EXT_PALM_POSE_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_POSE);
+
+ register_io_path("/interaction_profiles/valve/index_controller", "System click", "/user/hand/left", "/user/hand/left/input/system/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/valve/index_controller", "System click", "/user/hand/right", "/user/hand/right/input/system/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+
+ register_io_path("/interaction_profiles/valve/index_controller", "A click", "/user/hand/left", "/user/hand/left/input/a/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/valve/index_controller", "A touch", "/user/hand/left", "/user/hand/left/input/a/touch", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/valve/index_controller", "A click", "/user/hand/right", "/user/hand/right/input/a/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/valve/index_controller", "A touch", "/user/hand/right", "/user/hand/right/input/a/touch", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/valve/index_controller", "B click", "/user/hand/left", "/user/hand/left/input/b/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/valve/index_controller", "B touch", "/user/hand/left", "/user/hand/left/input/b/touch", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/valve/index_controller", "B click", "/user/hand/right", "/user/hand/right/input/b/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/valve/index_controller", "B touch", "/user/hand/right", "/user/hand/right/input/b/touch", "", OpenXRAction::OPENXR_ACTION_BOOL);
+
+ register_io_path("/interaction_profiles/valve/index_controller", "Trigger", "/user/hand/left", "/user/hand/left/input/trigger/value", "", OpenXRAction::OPENXR_ACTION_FLOAT);
+ register_io_path("/interaction_profiles/valve/index_controller", "Trigger click", "/user/hand/left", "/user/hand/left/input/trigger/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/valve/index_controller", "Trigger touch", "/user/hand/left", "/user/hand/left/input/trigger/touch", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/valve/index_controller", "Trigger", "/user/hand/right", "/user/hand/right/input/trigger/value", "", OpenXRAction::OPENXR_ACTION_FLOAT);
+ register_io_path("/interaction_profiles/valve/index_controller", "Trigger click", "/user/hand/right", "/user/hand/right/input/trigger/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/valve/index_controller", "Trigger touch", "/user/hand/right", "/user/hand/right/input/trigger/touch", "", OpenXRAction::OPENXR_ACTION_BOOL);
+
+ register_io_path("/interaction_profiles/valve/index_controller", "Squeeze", "/user/hand/left", "/user/hand/left/input/squeeze/value", "", OpenXRAction::OPENXR_ACTION_FLOAT);
+ register_io_path("/interaction_profiles/valve/index_controller", "Squeeze", "/user/hand/right", "/user/hand/right/input/squeeze/value", "", OpenXRAction::OPENXR_ACTION_FLOAT);
+
+ register_io_path("/interaction_profiles/valve/index_controller", "Thumbstick", "/user/hand/left", "/user/hand/left/input/thumbstick", "", OpenXRAction::OPENXR_ACTION_VECTOR2);
+ register_io_path("/interaction_profiles/valve/index_controller", "Thumbstick click", "/user/hand/left", "/user/hand/left/input/thumbstick/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/valve/index_controller", "Thumbstick touch", "/user/hand/left", "/user/hand/left/input/thumbstick/touch", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/valve/index_controller", "Thumbstick", "/user/hand/right", "/user/hand/right/input/thumbstick", "", OpenXRAction::OPENXR_ACTION_VECTOR2);
+ register_io_path("/interaction_profiles/valve/index_controller", "Thumbstick click", "/user/hand/right", "/user/hand/right/input/thumbstick/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/valve/index_controller", "Thumbstick touch", "/user/hand/right", "/user/hand/right/input/thumbstick/touch", "", OpenXRAction::OPENXR_ACTION_BOOL);
+
+ register_io_path("/interaction_profiles/valve/index_controller", "Trackpad", "/user/hand/left", "/user/hand/left/input/trackpad", "", OpenXRAction::OPENXR_ACTION_VECTOR2);
+ register_io_path("/interaction_profiles/valve/index_controller", "Trackpad force", "/user/hand/left", "/user/hand/left/input/trackpad/force", "", OpenXRAction::OPENXR_ACTION_FLOAT);
+ register_io_path("/interaction_profiles/valve/index_controller", "Trackpad touch", "/user/hand/left", "/user/hand/left/input/trackpad/touch", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/valve/index_controller", "Trackpad", "/user/hand/right", "/user/hand/right/input/trackpad", "", OpenXRAction::OPENXR_ACTION_VECTOR2);
+ register_io_path("/interaction_profiles/valve/index_controller", "Trackpad force", "/user/hand/right", "/user/hand/right/input/trackpad/force", "", OpenXRAction::OPENXR_ACTION_FLOAT);
+ register_io_path("/interaction_profiles/valve/index_controller", "Trackpad touch", "/user/hand/right", "/user/hand/right/input/trackpad/touch", "", OpenXRAction::OPENXR_ACTION_BOOL);
+
+ register_io_path("/interaction_profiles/valve/index_controller", "Haptic output", "/user/hand/left", "/user/hand/left/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC);
+ register_io_path("/interaction_profiles/valve/index_controller", "Haptic output", "/user/hand/right", "/user/hand/right/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC);
+
+ // HP MR controller (newer G2 controllers)
+ // TODO move this into an extension once this is supported.
+ register_interaction_profile("HPMR controller", "/interaction_profiles/hp/mixed_reality_controller", XR_EXT_HP_MIXED_REALITY_CONTROLLER_EXTENSION_NAME);
+ register_io_path("/interaction_profiles/hp/mixed_reality_controller", "Grip pose", "/user/hand/left", "/user/hand/left/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
+ register_io_path("/interaction_profiles/hp/mixed_reality_controller", "Grip pose", "/user/hand/right", "/user/hand/right/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
+ register_io_path("/interaction_profiles/hp/mixed_reality_controller", "Aim pose", "/user/hand/left", "/user/hand/left/input/aim/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
+ register_io_path("/interaction_profiles/hp/mixed_reality_controller", "Aim pose", "/user/hand/right", "/user/hand/right/input/aim/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
+ register_io_path("/interaction_profiles/hp/mixed_reality_controller", "Palm pose", "/user/hand/left", "/user/hand/left/input/palm_ext/pose", XR_EXT_PALM_POSE_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_POSE);
+ register_io_path("/interaction_profiles/hp/mixed_reality_controller", "Palm pose", "/user/hand/right", "/user/hand/right/input/palm_ext/pose", XR_EXT_PALM_POSE_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_POSE);
+
+ register_io_path("/interaction_profiles/hp/mixed_reality_controller", "Menu click", "/user/hand/left", "/user/hand/left/input/menu/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/hp/mixed_reality_controller", "Menu click", "/user/hand/right", "/user/hand/right/input/menu/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+
+ register_io_path("/interaction_profiles/hp/mixed_reality_controller", "X click", "/user/hand/left", "/user/hand/left/input/x/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/hp/mixed_reality_controller", "Y click", "/user/hand/left", "/user/hand/left/input/y/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/hp/mixed_reality_controller", "A click", "/user/hand/right", "/user/hand/right/input/a/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/hp/mixed_reality_controller", "B click", "/user/hand/right", "/user/hand/right/input/b/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+
+ register_io_path("/interaction_profiles/hp/mixed_reality_controller", "Trigger", "/user/hand/left", "/user/hand/left/input/trigger/value", "", OpenXRAction::OPENXR_ACTION_FLOAT);
+ register_io_path("/interaction_profiles/hp/mixed_reality_controller", "Trigger click", "/user/hand/left", "/user/hand/left/input/trigger/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/hp/mixed_reality_controller", "Trigger", "/user/hand/right", "/user/hand/right/input/trigger/value", "", OpenXRAction::OPENXR_ACTION_FLOAT);
+ register_io_path("/interaction_profiles/hp/mixed_reality_controller", "Trigger click", "/user/hand/right", "/user/hand/right/input/trigger/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+
+ register_io_path("/interaction_profiles/hp/mixed_reality_controller", "Squeeze", "/user/hand/left", "/user/hand/left/input/squeeze/value", "", OpenXRAction::OPENXR_ACTION_FLOAT);
+ register_io_path("/interaction_profiles/hp/mixed_reality_controller", "Squeeze", "/user/hand/right", "/user/hand/right/input/squeeze/value", "", OpenXRAction::OPENXR_ACTION_FLOAT);
+
+ register_io_path("/interaction_profiles/hp/mixed_reality_controller", "Thumbstick", "/user/hand/left", "/user/hand/left/input/thumbstick", "", OpenXRAction::OPENXR_ACTION_VECTOR2);
+ register_io_path("/interaction_profiles/hp/mixed_reality_controller", "Thumbstick click", "/user/hand/left", "/user/hand/left/input/thumbstick/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/hp/mixed_reality_controller", "Thumbstick", "/user/hand/right", "/user/hand/right/input/thumbstick", "", OpenXRAction::OPENXR_ACTION_VECTOR2);
+ register_io_path("/interaction_profiles/hp/mixed_reality_controller", "Thumbstick click", "/user/hand/right", "/user/hand/right/input/thumbstick/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+
+ register_io_path("/interaction_profiles/hp/mixed_reality_controller", "Haptic output", "/user/hand/left", "/user/hand/left/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC);
+ register_io_path("/interaction_profiles/hp/mixed_reality_controller", "Haptic output", "/user/hand/right", "/user/hand/right/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC);
+
+ // Samsung Odyssey controller
+ // TODO move this into an extension once this is supported.
+ register_interaction_profile("Samsung Odyssey controller", "/interaction_profiles/samsung/odyssey_controller", XR_EXT_SAMSUNG_ODYSSEY_CONTROLLER_EXTENSION_NAME);
+ register_io_path("/interaction_profiles/samsung/odyssey_controller", "Grip pose", "/user/hand/left", "/user/hand/left/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
+ register_io_path("/interaction_profiles/samsung/odyssey_controller", "Grip pose", "/user/hand/right", "/user/hand/right/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
+ register_io_path("/interaction_profiles/samsung/odyssey_controller", "Aim pose", "/user/hand/left", "/user/hand/left/input/aim/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
+ register_io_path("/interaction_profiles/samsung/odyssey_controller", "Aim pose", "/user/hand/right", "/user/hand/right/input/aim/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
+ register_io_path("/interaction_profiles/samsung/odyssey_controller", "Palm pose", "/user/hand/left", "/user/hand/left/input/palm_ext/pose", XR_EXT_PALM_POSE_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_POSE);
+ register_io_path("/interaction_profiles/samsung/odyssey_controller", "Palm pose", "/user/hand/right", "/user/hand/right/input/palm_ext/pose", XR_EXT_PALM_POSE_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_POSE);
+
+ register_io_path("/interaction_profiles/samsung/odyssey_controller", "Menu click", "/user/hand/left", "/user/hand/left/input/menu/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/samsung/odyssey_controller", "Menu click", "/user/hand/right", "/user/hand/right/input/menu/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+
+ register_io_path("/interaction_profiles/samsung/odyssey_controller", "Trigger", "/user/hand/left", "/user/hand/left/input/trigger/value", "", OpenXRAction::OPENXR_ACTION_FLOAT);
+ register_io_path("/interaction_profiles/samsung/odyssey_controller", "Trigger click", "/user/hand/left", "/user/hand/left/input/trigger/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/samsung/odyssey_controller", "Trigger", "/user/hand/right", "/user/hand/right/input/trigger/value", "", OpenXRAction::OPENXR_ACTION_FLOAT);
+ register_io_path("/interaction_profiles/samsung/odyssey_controller", "Trigger click", "/user/hand/right", "/user/hand/right/input/trigger/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+
+ register_io_path("/interaction_profiles/samsung/odyssey_controller", "Squeeze click", "/user/hand/left", "/user/hand/left/input/squeeze/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/samsung/odyssey_controller", "Squeeze click", "/user/hand/right", "/user/hand/right/input/squeeze/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+
+ register_io_path("/interaction_profiles/samsung/odyssey_controller", "Thumbstick", "/user/hand/left", "/user/hand/left/input/thumbstick", "", OpenXRAction::OPENXR_ACTION_VECTOR2);
+ register_io_path("/interaction_profiles/samsung/odyssey_controller", "Thumbstick click", "/user/hand/left", "/user/hand/left/input/thumbstick/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/samsung/odyssey_controller", "Thumbstick", "/user/hand/right", "/user/hand/right/input/thumbstick", "", OpenXRAction::OPENXR_ACTION_VECTOR2);
+ register_io_path("/interaction_profiles/samsung/odyssey_controller", "Thumbstick click", "/user/hand/right", "/user/hand/right/input/thumbstick/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+
+ register_io_path("/interaction_profiles/samsung/odyssey_controller", "Trackpad", "/user/hand/left", "/user/hand/left/input/trackpad", "", OpenXRAction::OPENXR_ACTION_VECTOR2);
+ register_io_path("/interaction_profiles/samsung/odyssey_controller", "Trackpad click", "/user/hand/left", "/user/hand/left/input/trackpad/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/samsung/odyssey_controller", "Trackpad touch", "/user/hand/left", "/user/hand/left/input/trackpad/touch", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/samsung/odyssey_controller", "Trackpad", "/user/hand/right", "/user/hand/right/input/trackpad", "", OpenXRAction::OPENXR_ACTION_VECTOR2);
+ register_io_path("/interaction_profiles/samsung/odyssey_controller", "Trackpad click", "/user/hand/right", "/user/hand/right/input/trackpad/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/samsung/odyssey_controller", "Trackpad touch", "/user/hand/right", "/user/hand/right/input/trackpad/touch", "", OpenXRAction::OPENXR_ACTION_BOOL);
+
+ register_io_path("/interaction_profiles/samsung/odyssey_controller", "Haptic output", "/user/hand/left", "/user/hand/left/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC);
+ register_io_path("/interaction_profiles/samsung/odyssey_controller", "Haptic output", "/user/hand/right", "/user/hand/right/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC);
+
+ // HTC Vive Cosmos controller
+ // TODO move this into an extension once this is supported.
+ register_interaction_profile("Vive Cosmos controller", "/interaction_profiles/htc/vive_cosmos_controller", XR_HTC_VIVE_COSMOS_CONTROLLER_INTERACTION_EXTENSION_NAME);
+ register_io_path("/interaction_profiles/htc/vive_cosmos_controller", "Grip pose", "/user/hand/left", "/user/hand/left/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
+ register_io_path("/interaction_profiles/htc/vive_cosmos_controller", "Grip pose", "/user/hand/right", "/user/hand/right/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
+ register_io_path("/interaction_profiles/htc/vive_cosmos_controller", "Aim pose", "/user/hand/left", "/user/hand/left/input/aim/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
+ register_io_path("/interaction_profiles/htc/vive_cosmos_controller", "Aim pose", "/user/hand/right", "/user/hand/right/input/aim/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
+ register_io_path("/interaction_profiles/htc/vive_cosmos_controller", "Palm pose", "/user/hand/left", "/user/hand/left/input/palm_ext/pose", XR_EXT_PALM_POSE_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_POSE);
+ register_io_path("/interaction_profiles/htc/vive_cosmos_controller", "Palm pose", "/user/hand/right", "/user/hand/right/input/palm_ext/pose", XR_EXT_PALM_POSE_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_POSE);
+
+ register_io_path("/interaction_profiles/htc/vive_cosmos_controller", "Menu click", "/user/hand/left", "/user/hand/left/input/menu/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_cosmos_controller", "System click", "/user/hand/right", "/user/hand/right/input/system/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+
+ register_io_path("/interaction_profiles/htc/vive_cosmos_controller", "X click", "/user/hand/left", "/user/hand/left/input/x/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_cosmos_controller", "Y click", "/user/hand/left", "/user/hand/left/input/y/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_cosmos_controller", "A click", "/user/hand/right", "/user/hand/right/input/a/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_cosmos_controller", "B click", "/user/hand/right", "/user/hand/right/input/b/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+
+ register_io_path("/interaction_profiles/htc/vive_cosmos_controller", "Shoulder click", "/user/hand/left", "/user/hand/left/input/shoulder/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_cosmos_controller", "Shoulder click", "/user/hand/right", "/user/hand/right/input/shoulder/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+
+ register_io_path("/interaction_profiles/htc/vive_cosmos_controller", "Trigger", "/user/hand/left", "/user/hand/left/input/trigger/value", "", OpenXRAction::OPENXR_ACTION_FLOAT);
+ register_io_path("/interaction_profiles/htc/vive_cosmos_controller", "Trigger click", "/user/hand/left", "/user/hand/left/input/trigger/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_cosmos_controller", "Trigger", "/user/hand/right", "/user/hand/right/input/trigger/value", "", OpenXRAction::OPENXR_ACTION_FLOAT);
+ register_io_path("/interaction_profiles/htc/vive_cosmos_controller", "Trigger click", "/user/hand/right", "/user/hand/right/input/trigger/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+
+ register_io_path("/interaction_profiles/htc/vive_cosmos_controller", "Squeeze click", "/user/hand/left", "/user/hand/left/input/squeeze/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_cosmos_controller", "Squeeze click", "/user/hand/right", "/user/hand/right/input/squeeze/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+
+ register_io_path("/interaction_profiles/htc/vive_cosmos_controller", "Thumbstick", "/user/hand/left", "/user/hand/left/input/thumbstick", "", OpenXRAction::OPENXR_ACTION_VECTOR2);
+ register_io_path("/interaction_profiles/htc/vive_cosmos_controller", "Thumbstick click", "/user/hand/left", "/user/hand/left/input/thumbstick/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_cosmos_controller", "Thumbstick touch", "/user/hand/left", "/user/hand/left/input/thumbstick/touch", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_cosmos_controller", "Thumbstick", "/user/hand/right", "/user/hand/right/input/thumbstick", "", OpenXRAction::OPENXR_ACTION_VECTOR2);
+ register_io_path("/interaction_profiles/htc/vive_cosmos_controller", "Thumbstick click", "/user/hand/right", "/user/hand/right/input/thumbstick/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_cosmos_controller", "Thumbstick touch", "/user/hand/right", "/user/hand/right/input/thumbstick/touch", "", OpenXRAction::OPENXR_ACTION_BOOL);
+
+ register_io_path("/interaction_profiles/htc/vive_cosmos_controller", "Haptic output", "/user/hand/left", "/user/hand/left/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC);
+ register_io_path("/interaction_profiles/htc/vive_cosmos_controller", "Haptic output", "/user/hand/right", "/user/hand/right/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC);
+
+ // HTC Vive Focus 3 controller
+ // TODO move this into an extension once this is supported.
+ register_interaction_profile("Vive Focus 3 controller", "/interaction_profiles/htc/vive_focus3_controller", XR_HTC_VIVE_FOCUS3_CONTROLLER_INTERACTION_EXTENSION_NAME);
+ register_io_path("/interaction_profiles/htc/vive_focus3_controller", "Grip pose", "/user/hand/left", "/user/hand/left/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
+ register_io_path("/interaction_profiles/htc/vive_focus3_controller", "Grip pose", "/user/hand/right", "/user/hand/right/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
+ register_io_path("/interaction_profiles/htc/vive_focus3_controller", "Aim pose", "/user/hand/left", "/user/hand/left/input/aim/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
+ register_io_path("/interaction_profiles/htc/vive_focus3_controller", "Aim pose", "/user/hand/right", "/user/hand/right/input/aim/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
+ register_io_path("/interaction_profiles/htc/vive_focus3_controller", "Palm pose", "/user/hand/left", "/user/hand/left/input/palm_ext/pose", XR_EXT_PALM_POSE_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_POSE);
+ register_io_path("/interaction_profiles/htc/vive_focus3_controller", "Palm pose", "/user/hand/right", "/user/hand/right/input/palm_ext/pose", XR_EXT_PALM_POSE_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_POSE);
+
+ register_io_path("/interaction_profiles/htc/vive_focus3_controller", "Menu click", "/user/hand/left", "/user/hand/left/input/menu/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_focus3_controller", "System click", "/user/hand/right", "/user/hand/right/input/system/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+
+ register_io_path("/interaction_profiles/htc/vive_focus3_controller", "X click", "/user/hand/left", "/user/hand/left/input/x/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_focus3_controller", "Y click", "/user/hand/left", "/user/hand/left/input/y/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_focus3_controller", "A click", "/user/hand/right", "/user/hand/right/input/a/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_focus3_controller", "B click", "/user/hand/right", "/user/hand/right/input/b/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+
+ register_io_path("/interaction_profiles/htc/vive_focus3_controller", "Trigger", "/user/hand/left", "/user/hand/left/input/trigger/value", "", OpenXRAction::OPENXR_ACTION_FLOAT);
+ register_io_path("/interaction_profiles/htc/vive_focus3_controller", "Trigger click", "/user/hand/left", "/user/hand/left/input/trigger/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_focus3_controller", "Trigger touch", "/user/hand/left", "/user/hand/left/input/trigger/touch", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_focus3_controller", "Trigger", "/user/hand/right", "/user/hand/right/input/trigger/value", "", OpenXRAction::OPENXR_ACTION_FLOAT);
+ register_io_path("/interaction_profiles/htc/vive_focus3_controller", "Trigger click", "/user/hand/right", "/user/hand/right/input/trigger/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_focus3_controller", "Trigger touch", "/user/hand/right", "/user/hand/right/input/trigger/touch ", "", OpenXRAction::OPENXR_ACTION_BOOL);
+
+ register_io_path("/interaction_profiles/htc/vive_focus3_controller", "Squeeze click", "/user/hand/left", "/user/hand/left/input/squeeze/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_focus3_controller", "Squeeze touch", "/user/hand/left", "/user/hand/left/input/squeeze/touch", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_focus3_controller", "Squeeze click", "/user/hand/right", "/user/hand/right/input/squeeze/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_focus3_controller", "Squeeze touch", "/user/hand/right", "/user/hand/right/input/squeeze/touch", "", OpenXRAction::OPENXR_ACTION_BOOL);
+
+ register_io_path("/interaction_profiles/htc/vive_focus3_controller", "Thumbstick", "/user/hand/left", "/user/hand/left/input/thumbstick", "", OpenXRAction::OPENXR_ACTION_VECTOR2);
+ register_io_path("/interaction_profiles/htc/vive_focus3_controller", "Thumbstick click", "/user/hand/left", "/user/hand/left/input/thumbstick/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_focus3_controller", "Thumbstick touch", "/user/hand/left", "/user/hand/left/input/thumbstick/touch", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_focus3_controller", "Thumbstick", "/user/hand/right", "/user/hand/right/input/thumbstick", "", OpenXRAction::OPENXR_ACTION_VECTOR2);
+ register_io_path("/interaction_profiles/htc/vive_focus3_controller", "Thumbstick click", "/user/hand/right", "/user/hand/right/input/thumbstick/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_focus3_controller", "Thumbstick touch", "/user/hand/right", "/user/hand/right/input/thumbstick/touch", "", OpenXRAction::OPENXR_ACTION_BOOL);
+
+ register_io_path("/interaction_profiles/htc/vive_focus3_controller", "Thumbrest touch", "/user/hand/right", "/user/hand/right/input/thumbrest/touch", "", OpenXRAction::OPENXR_ACTION_BOOL);
+
+ register_io_path("/interaction_profiles/htc/vive_focus3_controller", "Haptic output", "/user/hand/left", "/user/hand/left/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC);
+ register_io_path("/interaction_profiles/htc/vive_focus3_controller", "Haptic output", "/user/hand/right", "/user/hand/right/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC);
+
+ // Huawei controller
+ // TODO move this into an extension once this is supported.
+ register_interaction_profile("Huawei controller", "/interaction_profiles/huawei/controller", XR_HUAWEI_CONTROLLER_INTERACTION_EXTENSION_NAME);
+ register_io_path("/interaction_profiles/huawei/controller", "Grip pose", "/user/hand/left", "/user/hand/left/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
+ register_io_path("/interaction_profiles/huawei/controller", "Grip pose", "/user/hand/right", "/user/hand/right/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
+ register_io_path("/interaction_profiles/huawei/controller", "Aim pose", "/user/hand/left", "/user/hand/left/input/aim/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
+ register_io_path("/interaction_profiles/huawei/controller", "Aim pose", "/user/hand/right", "/user/hand/right/input/aim/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
+ register_io_path("/interaction_profiles/huawei/controller", "Palm pose", "/user/hand/left", "/user/hand/left/input/palm_ext/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
+ register_io_path("/interaction_profiles/huawei/controller", "Palm pose", "/user/hand/right", "/user/hand/right/input/palm_ext/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
+
+ register_io_path("/interaction_profiles/huawei/controller", "Home click", "/user/hand/left", "/user/hand/left/input/home/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/huawei/controller", "Home click", "/user/hand/right", "/user/hand/right/input/home/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/huawei/controller", "Back click", "/user/hand/left", "/user/hand/left/input/back/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/huawei/controller", "Back click", "/user/hand/right", "/user/hand/right/input/back/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+
+ register_io_path("/interaction_profiles/huawei/controller", "Volume up click", "/user/hand/left", "/user/hand/left/input/volume_up/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/huawei/controller", "Volume up click", "/user/hand/right", "/user/hand/right/input/volume_up/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/huawei/controller", "Volume down click", "/user/hand/left", "/user/hand/left/input/volume_down/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/huawei/controller", "Volume down click", "/user/hand/right", "/user/hand/right/input/volume_down/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+
+ register_io_path("/interaction_profiles/huawei/controller", "Trigger", "/user/hand/left", "/user/hand/left/input/trigger/value", "", OpenXRAction::OPENXR_ACTION_FLOAT);
+ register_io_path("/interaction_profiles/huawei/controller", "Trigger click", "/user/hand/left", "/user/hand/left/input/trigger/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/huawei/controller", "Trigger", "/user/hand/right", "/user/hand/right/input/trigger/value", "", OpenXRAction::OPENXR_ACTION_FLOAT);
+ register_io_path("/interaction_profiles/huawei/controller", "Trigger click", "/user/hand/right", "/user/hand/right/input/trigger/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+
+ register_io_path("/interaction_profiles/huawei/controller", "Trackpad", "/user/hand/left", "/user/hand/left/input/trackpad", "", OpenXRAction::OPENXR_ACTION_VECTOR2);
+ register_io_path("/interaction_profiles/huawei/controller", "Trackpad click", "/user/hand/left", "/user/hand/left/input/trackpad/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/huawei/controller", "Trackpad touch", "/user/hand/left", "/user/hand/left/input/trackpad/touch", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/huawei/controller", "Trackpad", "/user/hand/right", "/user/hand/right/input/trackpad", "", OpenXRAction::OPENXR_ACTION_VECTOR2);
+ register_io_path("/interaction_profiles/huawei/controller", "Trackpad click", "/user/hand/right", "/user/hand/right/input/trackpad/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/huawei/controller", "Trackpad touch", "/user/hand/right", "/user/hand/right/input/trackpad/touch", "", OpenXRAction::OPENXR_ACTION_BOOL);
+
+ register_io_path("/interaction_profiles/huawei/controller", "Haptic output", "/user/hand/left", "/user/hand/left/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC);
+ register_io_path("/interaction_profiles/huawei/controller", "Haptic output", "/user/hand/right", "/user/hand/right/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC);
+
+ // HTC Vive tracker
+ // Interestingly enough trackers don't have buttons or inputs, yet these are defined in the spec.
+ // I think this can be supported through attachments on the trackers.
+ // TODO move this into an extension once this is supported.
+ register_interaction_profile("HTC Vive tracker", "/interaction_profiles/htc/vive_tracker_htcx", XR_HTCX_VIVE_TRACKER_INTERACTION_EXTENSION_NAME);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Menu click", "/user/vive_tracker_htcx/role/left_foot", "/user/vive_tracker_htcx/role/left_foot/input/menu/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Menu click", "/user/vive_tracker_htcx/role/right_foot", "/user/vive_tracker_htcx/role/right_foot/input/menu/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Menu click", "/user/vive_tracker_htcx/role/left_shoulder", "/user/vive_tracker_htcx/role/left_shoulder/input/menu/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Menu click", "/user/vive_tracker_htcx/role/right_shoulder", "/user/vive_tracker_htcx/role/right_shoulder/input/menu/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Menu click", "/user/vive_tracker_htcx/role/left_elbow", "/user/vive_tracker_htcx/role/left_elbow/input/menu/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Menu click", "/user/vive_tracker_htcx/role/right_elbow", "/user/vive_tracker_htcx/role/right_elbow/input/menu/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Menu click", "/user/vive_tracker_htcx/role/left_knee", "/user/vive_tracker_htcx/role/left_knee/input/menu/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Menu click", "/user/vive_tracker_htcx/role/right_knee", "/user/vive_tracker_htcx/role/right_knee/input/menu/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Menu click", "/user/vive_tracker_htcx/role/waist", "/user/vive_tracker_htcx/role/waist/input/menu/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Menu click", "/user/vive_tracker_htcx/role/chest", "/user/vive_tracker_htcx/role/chest/input/menu/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Menu click", "/user/vive_tracker_htcx/role/camera", "/user/vive_tracker_htcx/role/camera/input/menu/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Menu click", "/user/vive_tracker_htcx/role/keyboard", "/user/vive_tracker_htcx/role/keyboard/input/menu/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+
+ // register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trigger", "/user/vive_tracker_htcx/role/handheld_object", "/user/vive_tracker_htcx/role/handheld_object/input/trigger/value", "", OpenXRAction::OPENXR_ACTION_FLOAT);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trigger", "/user/vive_tracker_htcx/role/left_foot", "/user/vive_tracker_htcx/role/left_foot/input/trigger/value", "", OpenXRAction::OPENXR_ACTION_FLOAT);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trigger", "/user/vive_tracker_htcx/role/right_foot", "/user/vive_tracker_htcx/role/right_foot/input/trigger/value", "", OpenXRAction::OPENXR_ACTION_FLOAT);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trigger", "/user/vive_tracker_htcx/role/left_shoulder", "/user/vive_tracker_htcx/role/left_shoulder/input/trigger/value", "", OpenXRAction::OPENXR_ACTION_FLOAT);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trigger", "/user/vive_tracker_htcx/role/right_shoulder", "/user/vive_tracker_htcx/role/right_shoulder/input/trigger/value", "", OpenXRAction::OPENXR_ACTION_FLOAT);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trigger", "/user/vive_tracker_htcx/role/left_elbow", "/user/vive_tracker_htcx/role/left_elbow/input/trigger/value", "", OpenXRAction::OPENXR_ACTION_FLOAT);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trigger", "/user/vive_tracker_htcx/role/right_elbow", "/user/vive_tracker_htcx/role/right_elbow/input/trigger/value", "", OpenXRAction::OPENXR_ACTION_FLOAT);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trigger", "/user/vive_tracker_htcx/role/left_knee", "/user/vive_tracker_htcx/role/left_knee/input/trigger/value", "", OpenXRAction::OPENXR_ACTION_FLOAT);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trigger", "/user/vive_tracker_htcx/role/right_knee", "/user/vive_tracker_htcx/role/right_knee/input/trigger/value", "", OpenXRAction::OPENXR_ACTION_FLOAT);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trigger", "/user/vive_tracker_htcx/role/waist", "/user/vive_tracker_htcx/role/waist/input/trigger/value", "", OpenXRAction::OPENXR_ACTION_FLOAT);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trigger", "/user/vive_tracker_htcx/role/chest", "/user/vive_tracker_htcx/role/chest/input/trigger/value", "", OpenXRAction::OPENXR_ACTION_FLOAT);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trigger", "/user/vive_tracker_htcx/role/camera", "/user/vive_tracker_htcx/role/camera/input/trigger/value", "", OpenXRAction::OPENXR_ACTION_FLOAT);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trigger", "/user/vive_tracker_htcx/role/keyboard", "/user/vive_tracker_htcx/role/keyboard/input/trigger/value", "", OpenXRAction::OPENXR_ACTION_FLOAT);
+
+ // register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trigger click", "/user/vive_tracker_htcx/role/handheld_object", "/user/vive_tracker_htcx/role/handheld_object/input/trigger/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trigger click", "/user/vive_tracker_htcx/role/left_foot", "/user/vive_tracker_htcx/role/left_foot/input/trigger/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trigger click", "/user/vive_tracker_htcx/role/right_foot", "/user/vive_tracker_htcx/role/right_foot/input/trigger/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trigger click", "/user/vive_tracker_htcx/role/left_shoulder", "/user/vive_tracker_htcx/role/left_shoulder/input/trigger/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trigger click", "/user/vive_tracker_htcx/role/right_shoulder", "/user/vive_tracker_htcx/role/right_shoulder/input/trigger/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trigger click", "/user/vive_tracker_htcx/role/left_elbow", "/user/vive_tracker_htcx/role/left_elbow/input/trigger/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trigger click", "/user/vive_tracker_htcx/role/right_elbow", "/user/vive_tracker_htcx/role/right_elbow/input/trigger/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trigger click", "/user/vive_tracker_htcx/role/left_knee", "/user/vive_tracker_htcx/role/left_knee/input/trigger/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trigger click", "/user/vive_tracker_htcx/role/right_knee", "/user/vive_tracker_htcx/role/right_knee/input/trigger/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trigger click", "/user/vive_tracker_htcx/role/waist", "/user/vive_tracker_htcx/role/waist/input/trigger/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trigger click", "/user/vive_tracker_htcx/role/chest", "/user/vive_tracker_htcx/role/chest/input/trigger/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trigger click", "/user/vive_tracker_htcx/role/camera", "/user/vive_tracker_htcx/role/camera/input/trigger/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trigger click", "/user/vive_tracker_htcx/role/keyboard", "/user/vive_tracker_htcx/role/keyboard/input/trigger/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+
+ // register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Squeeze click", "/user/vive_tracker_htcx/role/handheld_object", "/user/vive_tracker_htcx/role/handheld_object/input/squeeze/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Squeeze click", "/user/vive_tracker_htcx/role/left_foot", "/user/vive_tracker_htcx/role/left_foot/input/squeeze/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Squeeze click", "/user/vive_tracker_htcx/role/right_foot", "/user/vive_tracker_htcx/role/right_foot/input/squeeze/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Squeeze click", "/user/vive_tracker_htcx/role/left_shoulder", "/user/vive_tracker_htcx/role/left_shoulder/input/squeeze/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Squeeze click", "/user/vive_tracker_htcx/role/right_shoulder", "/user/vive_tracker_htcx/role/right_shoulder/input/squeeze/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Squeeze click", "/user/vive_tracker_htcx/role/left_elbow", "/user/vive_tracker_htcx/role/left_elbow/input/squeeze/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Squeeze click", "/user/vive_tracker_htcx/role/right_elbow", "/user/vive_tracker_htcx/role/right_elbow/input/squeeze/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Squeeze click", "/user/vive_tracker_htcx/role/left_knee", "/user/vive_tracker_htcx/role/left_knee/input/squeeze/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Squeeze click", "/user/vive_tracker_htcx/role/right_knee", "/user/vive_tracker_htcx/role/right_knee/input/squeeze/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Squeeze click", "/user/vive_tracker_htcx/role/waist", "/user/vive_tracker_htcx/role/waist/input/squeeze/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Squeeze click", "/user/vive_tracker_htcx/role/chest", "/user/vive_tracker_htcx/role/chest/input/squeeze/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Squeeze click", "/user/vive_tracker_htcx/role/camera", "/user/vive_tracker_htcx/role/camera/input/squeeze/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Squeeze click", "/user/vive_tracker_htcx/role/keyboard", "/user/vive_tracker_htcx/role/keyboard/input/squeeze/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+
+ // register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trackpad", "/user/vive_tracker_htcx/role/handheld_object", "/user/vive_tracker_htcx/role/handheld_object/input/trackpad", "", OpenXRAction::OPENXR_ACTION_VECTOR2);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trackpad", "/user/vive_tracker_htcx/role/left_foot", "/user/vive_tracker_htcx/role/left_foot/input/trackpad", "", OpenXRAction::OPENXR_ACTION_VECTOR2);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trackpad", "/user/vive_tracker_htcx/role/right_foot", "/user/vive_tracker_htcx/role/right_foot/input/trackpad", "", OpenXRAction::OPENXR_ACTION_VECTOR2);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trackpad", "/user/vive_tracker_htcx/role/left_shoulder", "/user/vive_tracker_htcx/role/left_shoulder/input/trackpad", "", OpenXRAction::OPENXR_ACTION_VECTOR2);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trackpad", "/user/vive_tracker_htcx/role/right_shoulder", "/user/vive_tracker_htcx/role/right_shoulder/input/trackpad", "", OpenXRAction::OPENXR_ACTION_VECTOR2);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trackpad", "/user/vive_tracker_htcx/role/left_elbow", "/user/vive_tracker_htcx/role/left_elbow/input/trackpad", "", OpenXRAction::OPENXR_ACTION_VECTOR2);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trackpad", "/user/vive_tracker_htcx/role/right_elbow", "/user/vive_tracker_htcx/role/right_elbow/input/trackpad", "", OpenXRAction::OPENXR_ACTION_VECTOR2);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trackpad", "/user/vive_tracker_htcx/role/left_knee", "/user/vive_tracker_htcx/role/left_knee/input/trackpad", "", OpenXRAction::OPENXR_ACTION_VECTOR2);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trackpad", "/user/vive_tracker_htcx/role/right_knee", "/user/vive_tracker_htcx/role/right_knee/input/trackpad", "", OpenXRAction::OPENXR_ACTION_VECTOR2);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trackpad", "/user/vive_tracker_htcx/role/waist", "/user/vive_tracker_htcx/role/waist/input/trackpad", "", OpenXRAction::OPENXR_ACTION_VECTOR2);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trackpad", "/user/vive_tracker_htcx/role/chest", "/user/vive_tracker_htcx/role/chest/input/trackpad", "", OpenXRAction::OPENXR_ACTION_VECTOR2);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trackpad", "/user/vive_tracker_htcx/role/camera", "/user/vive_tracker_htcx/role/camera/input/trackpad", "", OpenXRAction::OPENXR_ACTION_VECTOR2);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trackpad", "/user/vive_tracker_htcx/role/keyboard", "/user/vive_tracker_htcx/role/keyboard/input/trackpad", "", OpenXRAction::OPENXR_ACTION_VECTOR2);
+
+ // register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trackpad click", "/user/vive_tracker_htcx/role/handheld_object", "/user/vive_tracker_htcx/role/handheld_object/input/trackpad/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trackpad click", "/user/vive_tracker_htcx/role/left_foot", "/user/vive_tracker_htcx/role/left_foot/input/trackpad/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trackpad click", "/user/vive_tracker_htcx/role/right_foot", "/user/vive_tracker_htcx/role/right_foot/input/trackpad/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trackpad click", "/user/vive_tracker_htcx/role/left_shoulder", "/user/vive_tracker_htcx/role/left_shoulder/input/trackpad/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trackpad click", "/user/vive_tracker_htcx/role/right_shoulder", "/user/vive_tracker_htcx/role/right_shoulder/input/trackpad/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trackpad click", "/user/vive_tracker_htcx/role/left_elbow", "/user/vive_tracker_htcx/role/left_elbow/input/trackpad/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trackpad click", "/user/vive_tracker_htcx/role/right_elbow", "/user/vive_tracker_htcx/role/right_elbow/input/trackpad/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trackpad click", "/user/vive_tracker_htcx/role/left_knee", "/user/vive_tracker_htcx/role/left_knee/input/trackpad/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trackpad click", "/user/vive_tracker_htcx/role/right_knee", "/user/vive_tracker_htcx/role/right_knee/input/trackpad/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trackpad click", "/user/vive_tracker_htcx/role/waist", "/user/vive_tracker_htcx/role/waist/input/trackpad/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trackpad click", "/user/vive_tracker_htcx/role/chest", "/user/vive_tracker_htcx/role/chest/input/trackpad/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trackpad click", "/user/vive_tracker_htcx/role/camera", "/user/vive_tracker_htcx/role/camera/input/trackpad/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trackpad click", "/user/vive_tracker_htcx/role/keyboard", "/user/vive_tracker_htcx/role/keyboard/input/trackpad/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
+
+ // register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trackpad touch", "/user/vive_tracker_htcx/role/handheld_object", "/user/vive_tracker_htcx/role/handheld_object/input/trackpad/touch", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trackpad touch", "/user/vive_tracker_htcx/role/left_foot", "/user/vive_tracker_htcx/role/left_foot/input/trackpad/touch", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trackpad touch", "/user/vive_tracker_htcx/role/right_foot", "/user/vive_tracker_htcx/role/right_foot/input/trackpad/touch", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trackpad touch", "/user/vive_tracker_htcx/role/left_shoulder", "/user/vive_tracker_htcx/role/left_shoulder/input/trackpad/touch", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trackpad touch", "/user/vive_tracker_htcx/role/right_shoulder", "/user/vive_tracker_htcx/role/right_shoulder/input/trackpad/touch", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trackpad touch", "/user/vive_tracker_htcx/role/left_elbow", "/user/vive_tracker_htcx/role/left_elbow/input/trackpad/touch", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trackpad touch", "/user/vive_tracker_htcx/role/right_elbow", "/user/vive_tracker_htcx/role/right_elbow/input/trackpad/touch", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trackpad touch", "/user/vive_tracker_htcx/role/left_knee", "/user/vive_tracker_htcx/role/left_knee/input/trackpad/touch", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trackpad touch", "/user/vive_tracker_htcx/role/right_knee", "/user/vive_tracker_htcx/role/right_knee/input/trackpad/touch", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trackpad touch", "/user/vive_tracker_htcx/role/waist", "/user/vive_tracker_htcx/role/waist/input/trackpad/touch", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trackpad touch", "/user/vive_tracker_htcx/role/chest", "/user/vive_tracker_htcx/role/chest/input/trackpad/touch", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trackpad touch", "/user/vive_tracker_htcx/role/camera", "/user/vive_tracker_htcx/role/camera/input/trackpad/touch", "", OpenXRAction::OPENXR_ACTION_BOOL);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trackpad touch", "/user/vive_tracker_htcx/role/keyboard", "/user/vive_tracker_htcx/role/keyboard/input/trackpad/touch", "", OpenXRAction::OPENXR_ACTION_BOOL);
+
+ // register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Grip pose", "/user/vive_tracker_htcx/role/handheld_object", "/user/vive_tracker_htcx/role/handheld_object/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Grip pose", "/user/vive_tracker_htcx/role/left_foot", "/user/vive_tracker_htcx/role/left_foot/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Grip pose", "/user/vive_tracker_htcx/role/right_foot", "/user/vive_tracker_htcx/role/right_foot/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Grip pose", "/user/vive_tracker_htcx/role/left_shoulder", "/user/vive_tracker_htcx/role/left_shoulder/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Grip pose", "/user/vive_tracker_htcx/role/right_shoulder", "/user/vive_tracker_htcx/role/right_shoulder/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Grip pose", "/user/vive_tracker_htcx/role/left_elbow", "/user/vive_tracker_htcx/role/left_elbow/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Grip pose", "/user/vive_tracker_htcx/role/right_elbow", "/user/vive_tracker_htcx/role/right_elbow/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Grip pose", "/user/vive_tracker_htcx/role/left_knee", "/user/vive_tracker_htcx/role/left_knee/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Grip pose", "/user/vive_tracker_htcx/role/right_knee", "/user/vive_tracker_htcx/role/right_knee/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Grip pose", "/user/vive_tracker_htcx/role/waist", "/user/vive_tracker_htcx/role/waist/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Grip pose", "/user/vive_tracker_htcx/role/chest", "/user/vive_tracker_htcx/role/chest/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Grip pose", "/user/vive_tracker_htcx/role/camera", "/user/vive_tracker_htcx/role/camera/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Grip pose", "/user/vive_tracker_htcx/role/keyboard", "/user/vive_tracker_htcx/role/keyboard/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
+
+ // register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Haptic output", "/user/vive_tracker_htcx/role/handheld_object", "/user/vive_tracker_htcx/role/handheld_object/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Haptic output", "/user/vive_tracker_htcx/role/left_foot", "/user/vive_tracker_htcx/role/left_foot/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Haptic output", "/user/vive_tracker_htcx/role/right_foot", "/user/vive_tracker_htcx/role/right_foot/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Haptic output", "/user/vive_tracker_htcx/role/left_shoulder", "/user/vive_tracker_htcx/role/left_shoulder/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Haptic output", "/user/vive_tracker_htcx/role/right_shoulder", "/user/vive_tracker_htcx/role/right_shoulder/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Haptic output", "/user/vive_tracker_htcx/role/left_elbow", "/user/vive_tracker_htcx/role/left_elbow/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Haptic output", "/user/vive_tracker_htcx/role/right_elbow", "/user/vive_tracker_htcx/role/right_elbow/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Haptic output", "/user/vive_tracker_htcx/role/left_knee", "/user/vive_tracker_htcx/role/left_knee/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Haptic output", "/user/vive_tracker_htcx/role/right_knee", "/user/vive_tracker_htcx/role/right_knee/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Haptic output", "/user/vive_tracker_htcx/role/waist", "/user/vive_tracker_htcx/role/waist/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Haptic output", "/user/vive_tracker_htcx/role/chest", "/user/vive_tracker_htcx/role/chest/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Haptic output", "/user/vive_tracker_htcx/role/camera", "/user/vive_tracker_htcx/role/camera/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC);
+ register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Haptic output", "/user/vive_tracker_htcx/role/keyboard", "/user/vive_tracker_htcx/role/keyboard/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC);
+}
diff --git a/modules/openxr/action_map/openxr_interaction_profile_meta_data.h b/modules/openxr/action_map/openxr_interaction_profile_meta_data.h
new file mode 100644
index 0000000000..0ae6454be7
--- /dev/null
+++ b/modules/openxr/action_map/openxr_interaction_profile_meta_data.h
@@ -0,0 +1,118 @@
+/*************************************************************************/
+/* openxr_interaction_profile_meta_data.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 OPENXR_INTERACTION_PROFILE_META_DATA_H
+#define OPENXR_INTERACTION_PROFILE_META_DATA_H
+
+#include "openxr_action.h"
+
+///////////////////////////////////////////////////////////////////////////
+// Stores available interaction profile meta data
+//
+// OpenXR defines and hardcodes all the supported input devices and their
+// paths as part of the OpenXR spec. When support for new devices is
+// introduced this often starts life as an extension that needs to be enabled
+// until it's adopted into the core. As there is no interface to
+// enumerate the possibly paths, and that any OpenXR runtime would likely
+// limit such enumeration to those input devices supported by that runtime
+// there is no other option than to hardcode this.
+//
+// Note that we need to include paths of our extensions in our action map
+// regardless of whether the developers machine supports the extension or
+// not. Unsupported paths are filtered out when the action map is submitted
+// to the OpenXR runtime.
+//
+// Note on action type that automatic conversions between boolean and float
+// are supported but otherwise action types should match between action and
+// input/output paths.
+
+#include "core/object/object.h"
+
+#define XR_PATH_UNSUPPORTED_NAME "unsupported"
+
+class OpenXRInteractionProfileMetaData : public Object {
+public:
+ struct TopLevelPath {
+ String display_name; // User friendly display name (i.e. Left controller)
+ String openxr_path; // Path in OpenXR (i.e. /user/hand/left)
+ String openxr_extension_name; // If set, only available if extension is enabled (i.e. XR_HTCX_vive_tracker_interaction)
+ };
+
+ struct IOPath {
+ String display_name; // User friendly display name (i.e. Grip pose (left controller))
+ String top_level_path; // Top level path identifying the usage of the device in relation to this input/output
+ String openxr_path; // Path in OpenXR (i.e. /user/hand/left/input/grip/pose)
+ String openxr_extension_name; // If set, only available if extension is enabled (i.e. XR_EXT_palm_pose)
+ OpenXRAction::ActionType action_type; // Type of input/output
+ };
+
+ struct InteractionProfile {
+ String display_name; // User friendly display name (i.e. Simple controller)
+ String openxr_path; // Path in OpenXR (i.e. /interaction_profiles/khr/simple_controller)
+ String openxr_extension_name; // If set, only available if extension is enabled (i.e. XR_HTCX_vive_tracker_interaction)
+ Vector<IOPath> io_paths; // Inputs and outputs for this device
+
+ bool has_io_path(const String p_io_path) const;
+ const IOPath *get_io_path(const String p_io_path) const;
+ };
+
+private:
+ static OpenXRInteractionProfileMetaData *singleton;
+
+ Vector<TopLevelPath> top_level_paths;
+ Vector<InteractionProfile> interaction_profiles;
+
+ void _register_core_metadata();
+
+protected:
+ static void _bind_methods();
+
+public:
+ static OpenXRInteractionProfileMetaData *get_singleton() { return singleton; }
+
+ OpenXRInteractionProfileMetaData();
+ ~OpenXRInteractionProfileMetaData();
+
+ void register_top_level_path(const String &p_display_name, const String &p_openxr_path, const String &p_openxr_extension_name);
+ bool has_top_level_path(const String p_openxr_path) const;
+ String get_top_level_name(const String p_openxr_path) const;
+ String get_top_level_extension(const String p_openxr_path) const;
+
+ void register_interaction_profile(const String &p_display_name, const String &p_openxr_path, const String &p_openxr_extension_name);
+ bool has_interaction_profile(const String p_openxr_path) const;
+ String get_interaction_profile_extension(const String p_openxr_path) const;
+ const InteractionProfile *get_profile(const String p_openxr_path) const;
+ PackedStringArray get_interaction_profile_paths() const;
+
+ void register_io_path(const String &p_interaction_profile, const String &p_display_name, const String &p_toplevel_path, const String &p_openxr_path, const String &p_openxr_extension_name, OpenXRAction::ActionType p_action_type);
+ const IOPath *get_io_path(const String p_interaction_profile, const String p_io_path) const;
+};
+
+#endif // OPENXR_INTERACTION_PROFILE_META_DATA_H
diff --git a/modules/openxr/config.py b/modules/openxr/config.py
index 279168cc59..e503f12739 100644
--- a/modules/openxr/config.py
+++ b/modules/openxr/config.py
@@ -1,6 +1,6 @@
def can_build(env, platform):
if platform in ("linuxbsd", "windows", "android"):
- return env["openxr"]
+ return env["openxr"] and not env["disable_3d"]
else:
# not supported on these platforms
return False
diff --git a/modules/openxr/editor/openxr_action_editor.cpp b/modules/openxr/editor/openxr_action_editor.cpp
index 52216fa483..a6c99741d7 100644
--- a/modules/openxr/editor/openxr_action_editor.cpp
+++ b/modules/openxr/editor/openxr_action_editor.cpp
@@ -29,8 +29,13 @@
/*************************************************************************/
#include "openxr_action_editor.h"
+#include "editor/editor_node.h"
void OpenXRActionEditor::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("_do_set_name", "name"), &OpenXRActionEditor::_do_set_name);
+ ClassDB::bind_method(D_METHOD("_do_set_localized_name", "name"), &OpenXRActionEditor::_do_set_localized_name);
+ ClassDB::bind_method(D_METHOD("_do_set_action_type", "type"), &OpenXRActionEditor::_do_set_action_type);
+
ADD_SIGNAL(MethodInfo("remove", PropertyInfo(Variant::OBJECT, "action_editor")));
}
@@ -48,24 +53,71 @@ void OpenXRActionEditor::_notification(int p_what) {
}
void OpenXRActionEditor::_on_action_name_changed(const String p_new_text) {
- // TODO validate if entry is allowed
-
- // If our localized name matches our action name, set this too
- if (action->get_name() == action->get_localized_name()) {
- action->set_localized_name(p_new_text);
- action_localized_name->set_text(p_new_text);
+ if (action->get_name() != p_new_text) {
+ undo_redo->create_action(TTR("Rename Action"));
+ undo_redo->add_do_method(this, "_do_set_name", p_new_text);
+ undo_redo->add_undo_method(this, "_do_set_name", action->get_name());
+ undo_redo->commit_action(false);
+
+ // If our localized name matches our action name, set this too
+ if (action->get_name() == action->get_localized_name()) {
+ undo_redo->create_action(TTR("Rename Actions Localized name"));
+ undo_redo->add_do_method(this, "_do_set_localized_name", p_new_text);
+ undo_redo->add_undo_method(this, "_do_set_localized_name", action->get_localized_name());
+ undo_redo->commit_action(false);
+
+ action->set_localized_name(p_new_text);
+ action_localized_name->set_text(p_new_text);
+ }
+ action->set_name(p_new_text);
+ action->set_edited(true);
}
+}
+
+void OpenXRActionEditor::_do_set_name(const String p_new_text) {
action->set_name(p_new_text);
+ action->set_edited(true);
+ action_name->set_text(p_new_text);
}
void OpenXRActionEditor::_on_action_localized_name_changed(const String p_new_text) {
+ if (action->get_localized_name() != p_new_text) {
+ undo_redo->create_action(TTR("Rename Actions Localized name"));
+ undo_redo->add_do_method(this, "_do_set_localized_name", p_new_text);
+ undo_redo->add_undo_method(this, "_do_set_localized_name", action->get_localized_name());
+ undo_redo->commit_action(false);
+
+ action->set_localized_name(p_new_text);
+ action->set_edited(true);
+ }
+}
+
+void OpenXRActionEditor::_do_set_localized_name(const String p_new_text) {
action->set_localized_name(p_new_text);
+ action->set_edited(true);
+ action_localized_name->set_text(p_new_text);
}
void OpenXRActionEditor::_on_item_selected(int p_idx) {
ERR_FAIL_INDEX(p_idx, OpenXRAction::OPENXR_ACTION_MAX);
- action->set_action_type(OpenXRAction::ActionType(p_idx));
+ OpenXRAction::ActionType action_type = OpenXRAction::ActionType(p_idx);
+
+ if (action->get_action_type() != action_type) {
+ undo_redo->create_action(TTR("Change Action Type"));
+ undo_redo->add_do_method(this, "_do_set_action_type", action_type);
+ undo_redo->add_undo_method(this, "_do_set_action_type", action->get_action_type());
+ undo_redo->commit_action(false);
+
+ action->set_action_type(action_type);
+ action->set_edited(true);
+ }
+}
+
+void OpenXRActionEditor::_do_set_action_type(OpenXRAction::ActionType p_action_type) {
+ action->set_action_type(p_action_type);
+ action->set_edited(true);
+ action_type_button->select(int(action->get_action_type()));
}
void OpenXRActionEditor::_on_remove_action() {
@@ -73,6 +125,7 @@ void OpenXRActionEditor::_on_remove_action() {
}
OpenXRActionEditor::OpenXRActionEditor(Ref<OpenXRAction> p_action) {
+ undo_redo = EditorNode::get_undo_redo();
action = p_action;
set_h_size_flags(Control::SIZE_EXPAND_FILL);
@@ -90,16 +143,16 @@ OpenXRActionEditor::OpenXRActionEditor(Ref<OpenXRAction> p_action) {
action_localized_name->connect("text_changed", callable_mp(this, &OpenXRActionEditor::_on_action_localized_name_changed));
add_child(action_localized_name);
- action_type = memnew(OptionButton);
- action_type->add_item("Bool", OpenXRAction::OPENXR_ACTION_BOOL);
- action_type->add_item("Float", OpenXRAction::OPENXR_ACTION_FLOAT);
- action_type->add_item("Vector2", OpenXRAction::OPENXR_ACTION_VECTOR2);
- action_type->add_item("Pose", OpenXRAction::OPENXR_ACTION_POSE);
- action_type->add_item("Haptic", OpenXRAction::OPENXR_ACTION_HAPTIC);
- action_type->select(int(action->get_action_type()));
- action_type->set_custom_minimum_size(Size2(100.0, 0.0));
- action_type->connect("item_selected", callable_mp(this, &OpenXRActionEditor::_on_item_selected));
- add_child(action_type);
+ action_type_button = memnew(OptionButton);
+ action_type_button->add_item("Bool", OpenXRAction::OPENXR_ACTION_BOOL);
+ action_type_button->add_item("Float", OpenXRAction::OPENXR_ACTION_FLOAT);
+ action_type_button->add_item("Vector2", OpenXRAction::OPENXR_ACTION_VECTOR2);
+ action_type_button->add_item("Pose", OpenXRAction::OPENXR_ACTION_POSE);
+ action_type_button->add_item("Haptic", OpenXRAction::OPENXR_ACTION_HAPTIC);
+ action_type_button->select(int(action->get_action_type()));
+ action_type_button->set_custom_minimum_size(Size2(100.0, 0.0));
+ action_type_button->connect("item_selected", callable_mp(this, &OpenXRActionEditor::_on_item_selected));
+ add_child(action_type_button);
// maybe add dropdown to edit our toplevel paths, or do we deduce them from our suggested bindings?
diff --git a/modules/openxr/editor/openxr_action_editor.h b/modules/openxr/editor/openxr_action_editor.h
index 6cf098cf08..66b7eebaeb 100644
--- a/modules/openxr/editor/openxr_action_editor.h
+++ b/modules/openxr/editor/openxr_action_editor.h
@@ -32,6 +32,7 @@
#define OPENXR_ACTION_EDITOR_H
#include "../action_map/openxr_action.h"
+#include "editor/editor_undo_redo_manager.h"
#include "scene/gui/box_container.h"
#include "scene/gui/button.h"
#include "scene/gui/line_edit.h"
@@ -42,11 +43,12 @@ class OpenXRActionEditor : public HBoxContainer {
GDCLASS(OpenXRActionEditor, HBoxContainer);
private:
+ Ref<EditorUndoRedoManager> undo_redo;
Ref<OpenXRAction> action;
LineEdit *action_name = nullptr;
LineEdit *action_localized_name = nullptr;
- OptionButton *action_type = nullptr;
+ OptionButton *action_type_button = nullptr;
Button *rem_action = nullptr;
void _theme_changed();
@@ -59,6 +61,11 @@ protected:
static void _bind_methods();
void _notification(int p_what);
+ // used for undo/redo
+ void _do_set_name(const String p_new_text);
+ void _do_set_localized_name(const String p_new_text);
+ void _do_set_action_type(OpenXRAction::ActionType p_action_type);
+
public:
Ref<OpenXRAction> get_action() { return action; };
OpenXRActionEditor(Ref<OpenXRAction> p_action);
diff --git a/modules/openxr/editor/openxr_action_map_editor.cpp b/modules/openxr/editor/openxr_action_map_editor.cpp
index b5223e5903..71fcd3ce7f 100644
--- a/modules/openxr/editor/openxr_action_map_editor.cpp
+++ b/modules/openxr/editor/openxr_action_map_editor.cpp
@@ -40,14 +40,16 @@
void OpenXRActionMapEditor::_bind_methods() {
ClassDB::bind_method("_add_action_set_editor", &OpenXRActionMapEditor::_add_action_set_editor);
- ClassDB::bind_method("_update_action_sets", &OpenXRActionMapEditor::_update_action_sets);
-
ClassDB::bind_method("_add_interaction_profile_editor", &OpenXRActionMapEditor::_add_interaction_profile_editor);
- ClassDB::bind_method("_update_interaction_profiles", &OpenXRActionMapEditor::_update_interaction_profiles);
ClassDB::bind_method(D_METHOD("_add_action_set", "name"), &OpenXRActionMapEditor::_add_action_set);
ClassDB::bind_method(D_METHOD("_set_focus_on_action_set", "action_set"), &OpenXRActionMapEditor::_set_focus_on_action_set);
ClassDB::bind_method(D_METHOD("_remove_action_set", "name"), &OpenXRActionMapEditor::_remove_action_set);
+
+ ClassDB::bind_method(D_METHOD("_do_add_action_set_editor", "action_set_editor"), &OpenXRActionMapEditor::_do_add_action_set_editor);
+ ClassDB::bind_method(D_METHOD("_do_remove_action_set_editor", "action_set_editor"), &OpenXRActionMapEditor::_do_remove_action_set_editor);
+ ClassDB::bind_method(D_METHOD("_do_add_interaction_profile_editor", "interaction_profile_editor"), &OpenXRActionMapEditor::_do_add_interaction_profile_editor);
+ ClassDB::bind_method(D_METHOD("_do_remove_interaction_profile_editor", "interaction_profile_editor"), &OpenXRActionMapEditor::_do_remove_interaction_profile_editor);
}
void OpenXRActionMapEditor::_notification(int p_what) {
@@ -55,7 +57,7 @@ void OpenXRActionMapEditor::_notification(int p_what) {
case NOTIFICATION_ENTER_TREE:
case NOTIFICATION_THEME_CHANGED: {
for (int i = 0; i < tabs->get_child_count(); i++) {
- Control *tab = static_cast<Control *>(tabs->get_child(i));
+ Control *tab = Object::cast_to<Control>(tabs->get_child(i));
if (tab) {
tab->add_theme_style_override("panel", get_theme_stylebox(SNAME("panel"), SNAME("Tree")));
}
@@ -63,8 +65,8 @@ void OpenXRActionMapEditor::_notification(int p_what) {
} break;
case NOTIFICATION_READY: {
- _update_action_sets();
- _update_interaction_profiles();
+ _create_action_sets();
+ _create_interaction_profiles();
} break;
}
}
@@ -75,18 +77,13 @@ OpenXRActionSetEditor *OpenXRActionMapEditor::_add_action_set_editor(Ref<OpenXRA
OpenXRActionSetEditor *action_set_editor = memnew(OpenXRActionSetEditor(action_map, p_action_set));
action_set_editor->connect("remove", callable_mp(this, &OpenXRActionMapEditor::_on_remove_action_set));
action_set_editor->connect("action_removed", callable_mp(this, &OpenXRActionMapEditor::_on_action_removed));
+
actionsets_vb->add_child(action_set_editor);
return action_set_editor;
}
-void OpenXRActionMapEditor::_update_action_sets() {
- // out with the old...
- while (actionsets_vb->get_child_count() > 0) {
- memdelete(actionsets_vb->get_child(0));
- }
-
- // in with the new...
+void OpenXRActionMapEditor::_create_action_sets() {
if (action_map.is_valid()) {
Array action_sets = action_map->get_action_sets();
for (int i = 0; i < action_sets.size(); i++) {
@@ -116,22 +113,10 @@ OpenXRInteractionProfileEditorBase *OpenXRActionMapEditor::_add_interaction_prof
new_profile_editor->add_theme_style_override("panel", get_theme_stylebox(SNAME("panel"), SNAME("Tree")));
tabs->set_tab_button_icon(tabs->get_tab_count() - 1, get_theme_icon(SNAME("close"), SNAME("TabBar")));
- interaction_profiles.push_back(new_profile_editor);
-
return new_profile_editor;
}
-void OpenXRActionMapEditor::_update_interaction_profiles() {
- // out with the old...
- while (interaction_profiles.size() > 0) {
- Node *interaction_profile = interaction_profiles[0];
- interaction_profiles.remove_at(0);
-
- tabs->remove_child(interaction_profile);
- interaction_profile->queue_free();
- }
-
- // in with the new...
+void OpenXRActionMapEditor::_create_interaction_profiles() {
if (action_map.is_valid()) {
Array new_interaction_profiles = action_map->get_interaction_profiles();
for (int i = 0; i < new_interaction_profiles.size(); i++) {
@@ -150,9 +135,17 @@ OpenXRActionSetEditor *OpenXRActionMapEditor::_add_action_set(String p_name) {
new_action_set->set_name(p_name);
new_action_set->set_localized_name(p_name);
action_map->add_action_set(new_action_set);
+ action_map->set_edited(true);
// update our editor right away
- return _add_action_set_editor(new_action_set);
+ OpenXRActionSetEditor *action_set_editor = _add_action_set_editor(new_action_set);
+
+ undo_redo->create_action(TTR("Add action set"));
+ undo_redo->add_do_method(this, "_do_add_action_set_editor", action_set_editor);
+ undo_redo->add_undo_method(this, "_do_remove_action_set_editor", action_set_editor);
+ undo_redo->commit_action(false);
+
+ return action_set_editor;
}
void OpenXRActionMapEditor::_remove_action_set(String p_name) {
@@ -160,13 +153,12 @@ void OpenXRActionMapEditor::_remove_action_set(String p_name) {
Ref<OpenXRActionSet> action_set = action_map->find_action_set(p_name);
ERR_FAIL_COND(action_set.is_null());
- if (action_set->get_action_count() > 0) {
- // we should remove these and add to our redo/undo step before calling _remove_action_set
- WARN_PRINT("Action set still has associated actions before being removed!");
+ for (int i = 0; i < actionsets_vb->get_child_count(); i++) {
+ OpenXRActionSetEditor *action_set_editor = Object::cast_to<OpenXRActionSetEditor>(actionsets_vb->get_child(i));
+ if (action_set_editor && action_set_editor->get_action_set() == action_set) {
+ _on_remove_action_set(action_set_editor);
+ }
}
-
- // now we remove it
- action_map->remove_action_set(action_set);
}
void OpenXRActionMapEditor::_on_add_action_set() {
@@ -203,14 +195,24 @@ void OpenXRActionMapEditor::_on_remove_action_set(Object *p_action_set_editor) {
Ref<OpenXRActionSet> action_set = action_set_editor->get_action_set();
ERR_FAIL_COND(action_set.is_null());
- action_map->remove_action_set(action_set);
- actionsets_vb->remove_child(action_set_editor);
- action_set_editor->queue_free();
+ action_set_editor->remove_all_actions();
+
+ undo_redo->create_action(TTR("Remove action set"));
+ undo_redo->add_do_method(this, "_do_remove_action_set_editor", action_set_editor);
+ undo_redo->add_undo_method(this, "_do_add_action_set_editor", action_set_editor);
+ undo_redo->commit_action(true);
+
+ action_map->set_edited(true);
}
-void OpenXRActionMapEditor::_on_action_removed() {
- // make sure our interaction profiles are updated
- _update_interaction_profiles();
+void OpenXRActionMapEditor::_on_action_removed(Ref<OpenXRAction> p_action) {
+ for (int i = 0; i < tabs->get_tab_count(); i++) {
+ // First tab won't be an interaction profile editor, but being thorough..
+ OpenXRInteractionProfileEditorBase *interaction_profile_editor = Object::cast_to<OpenXRInteractionProfileEditorBase>(tabs->get_tab_control(i));
+ if (interaction_profile_editor) {
+ interaction_profile_editor->remove_all_bindings_for_action(p_action);
+ }
+ }
}
void OpenXRActionMapEditor::_on_add_interaction_profile() {
@@ -232,20 +234,35 @@ void OpenXRActionMapEditor::_on_interaction_profile_selected(const String p_path
new_profile.instantiate();
new_profile->set_interaction_profile_path(p_path);
action_map->add_interaction_profile(new_profile);
+ action_map->set_edited(true);
- _add_interaction_profile_editor(new_profile);
+ OpenXRInteractionProfileEditorBase *interaction_profile_editor = _add_interaction_profile_editor(new_profile);
+
+ undo_redo->create_action(TTR("Add interaction profile"));
+ undo_redo->add_do_method(this, "_do_add_interaction_profile_editor", interaction_profile_editor);
+ undo_redo->add_undo_method(this, "_do_remove_interaction_profile_editor", interaction_profile_editor);
+ undo_redo->commit_action(false);
tabs->set_current_tab(tabs->get_tab_count() - 1);
}
void OpenXRActionMapEditor::_load_action_map(const String p_path, bool p_create_new_if_missing) {
- action_map = ResourceLoader::load(p_path, "", ResourceFormatLoader::CACHE_MODE_IGNORE);
- if (action_map.is_null()) {
- if (p_create_new_if_missing) {
+ Error err = OK;
+ action_map = ResourceLoader::load(p_path, "", ResourceFormatLoader::CACHE_MODE_IGNORE, &err);
+ if (err != OK) {
+ if ((err == ERR_FILE_NOT_FOUND || err == ERR_CANT_OPEN) && p_create_new_if_missing) {
action_map.instantiate();
action_map->create_default_action_sets();
+
+ // Save it immediately
+ err = ResourceSaver::save(action_map, p_path);
+ if (err != OK) {
+ // show warning but continue
+ EditorNode::get_singleton()->show_warning(vformat(TTR("Error saving file %s: %s"), edited_path, error_names[err]));
+ }
+
} else {
- EditorNode::get_singleton()->show_warning(TTR("Invalid file, not an OpenXR action map."));
+ EditorNode::get_singleton()->show_warning(vformat(TTR("Error loading %s: %s."), edited_path, error_names[err]));
edited_path = "";
header_label->set_text("");
@@ -254,55 +271,123 @@ void OpenXRActionMapEditor::_load_action_map(const String p_path, bool p_create_
}
edited_path = p_path;
- header_label->set_text(TTR("OpenXR Action map:") + " " + p_path.get_file());
+ header_label->set_text(TTR("OpenXR Action map:") + " " + edited_path.get_file());
}
void OpenXRActionMapEditor::_on_save_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));
+ EditorNode::get_singleton()->show_warning(vformat(TTR("Error saving file %s: %s"), edited_path, error_names[err]));
return;
}
- _update_action_sets();
- _update_interaction_profiles();
+ // TODO should clear undo/redo history
+
+ // out with the old
+ _clear_action_map();
+
+ _create_action_sets();
+ _create_interaction_profiles();
}
void OpenXRActionMapEditor::_on_reset_to_default_layout() {
+ // TODO should clear undo/redo history
+
+ // out with the old
+ _clear_action_map();
+
// create a new one
action_map.unref();
action_map.instantiate();
action_map->create_default_action_sets();
+ action_map->set_edited(true);
- _update_action_sets();
- _update_interaction_profiles();
+ _create_action_sets();
+ _create_interaction_profiles();
}
void OpenXRActionMapEditor::_on_tabs_tab_changed(int p_tab) {
}
void OpenXRActionMapEditor::_on_tab_button_pressed(int p_tab) {
- OpenXRInteractionProfileEditorBase *profile_editor = static_cast<OpenXRInteractionProfileEditorBase *>(tabs->get_tab_control(p_tab));
- ERR_FAIL_NULL(profile_editor);
+ OpenXRInteractionProfileEditorBase *interaction_profile_editor = Object::cast_to<OpenXRInteractionProfileEditorBase>(tabs->get_tab_control(p_tab));
+ ERR_FAIL_NULL(interaction_profile_editor);
+
+ undo_redo->create_action(TTR("Remove interaction profile"));
+ undo_redo->add_do_method(this, "_do_remove_interaction_profile_editor", interaction_profile_editor);
+ undo_redo->add_undo_method(this, "_do_add_interaction_profile_editor", interaction_profile_editor);
+ undo_redo->commit_action(true);
+
+ action_map->set_edited(true);
+}
+
+void OpenXRActionMapEditor::_do_add_action_set_editor(OpenXRActionSetEditor *p_action_set_editor) {
+ Ref<OpenXRActionSet> action_set = p_action_set_editor->get_action_set();
+ ERR_FAIL_COND(action_set.is_null());
+
+ action_map->add_action_set(action_set);
+ actionsets_vb->add_child(p_action_set_editor);
+}
+
+void OpenXRActionMapEditor::_do_remove_action_set_editor(OpenXRActionSetEditor *p_action_set_editor) {
+ Ref<OpenXRActionSet> action_set = p_action_set_editor->get_action_set();
+ ERR_FAIL_COND(action_set.is_null());
+
+ actionsets_vb->remove_child(p_action_set_editor);
+ action_map->remove_action_set(action_set);
+}
+
+void OpenXRActionMapEditor::_do_add_interaction_profile_editor(OpenXRInteractionProfileEditorBase *p_interaction_profile_editor) {
+ Ref<OpenXRInteractionProfile> interaction_profile = p_interaction_profile_editor->get_interaction_profile();
+ ERR_FAIL_COND(interaction_profile.is_null());
+
+ action_map->add_interaction_profile(interaction_profile);
+ tabs->add_child(p_interaction_profile_editor);
+ tabs->set_tab_button_icon(tabs->get_tab_count() - 1, get_theme_icon(SNAME("close"), SNAME("TabBar")));
+
+ tabs->set_current_tab(tabs->get_tab_count() - 1);
+}
- Ref<OpenXRInteractionProfile> interaction_profile = profile_editor->get_interaction_profile();
+void OpenXRActionMapEditor::_do_remove_interaction_profile_editor(OpenXRInteractionProfileEditorBase *p_interaction_profile_editor) {
+ Ref<OpenXRInteractionProfile> interaction_profile = p_interaction_profile_editor->get_interaction_profile();
ERR_FAIL_COND(interaction_profile.is_null());
+ tabs->remove_child(p_interaction_profile_editor);
action_map->remove_interaction_profile(interaction_profile);
- tabs->remove_child(profile_editor);
- profile_editor->queue_free();
}
void OpenXRActionMapEditor::open_action_map(String p_path) {
EditorNode::get_singleton()->make_bottom_panel_item_visible(this);
+ // out with the old...
+ _clear_action_map();
+
+ // now load in our new action map
_load_action_map(p_path);
- _update_action_sets();
- _update_interaction_profiles();
+ _create_action_sets();
+ _create_interaction_profiles();
+}
+
+void OpenXRActionMapEditor::_clear_action_map() {
+ while (actionsets_vb->get_child_count() > 0) {
+ Node *child = actionsets_vb->get_child(0);
+ actionsets_vb->remove_child(child);
+ child->queue_free();
+ }
+
+ for (int i = tabs->get_tab_count() - 1; i >= 0; --i) {
+ // First tab won't be an interaction profile editor, but being thorough..
+ OpenXRInteractionProfileEditorBase *interaction_profile_editor = Object::cast_to<OpenXRInteractionProfileEditorBase>(tabs->get_tab_control(i));
+ if (interaction_profile_editor) {
+ tabs->remove_child(interaction_profile_editor);
+ interaction_profile_editor->queue_free();
+ }
+ }
}
OpenXRActionMapEditor::OpenXRActionMapEditor() {
+ undo_redo = EditorNode::get_undo_redo();
set_custom_minimum_size(Size2(0.0, 300.0));
top_hb = memnew(HBoxContainer);
@@ -364,7 +449,9 @@ OpenXRActionMapEditor::OpenXRActionMapEditor() {
select_interaction_profile_dialog->connect("interaction_profile_selected", callable_mp(this, &OpenXRActionMapEditor::_on_interaction_profile_selected));
add_child(select_interaction_profile_dialog);
- _load_action_map(GLOBAL_GET("xr/openxr/default_action_map"));
+ // Our Action map editor is only shown if openxr is enabled in project settings
+ // So load our action map and if it doesn't exist, create it right away.
+ _load_action_map(GLOBAL_GET("xr/openxr/default_action_map"), true);
}
OpenXRActionMapEditor::~OpenXRActionMapEditor() {
diff --git a/modules/openxr/editor/openxr_action_map_editor.h b/modules/openxr/editor/openxr_action_map_editor.h
index a19bc90f56..2ff6ddf785 100644
--- a/modules/openxr/editor/openxr_action_map_editor.h
+++ b/modules/openxr/editor/openxr_action_map_editor.h
@@ -37,6 +37,7 @@
#include "../editor/openxr_select_interaction_profile_dialog.h"
#include "editor/editor_plugin.h"
+#include "editor/editor_undo_redo_manager.h"
#include "scene/gui/box_container.h"
#include "scene/gui/button.h"
#include "scene/gui/label.h"
@@ -47,9 +48,9 @@ class OpenXRActionMapEditor : public VBoxContainer {
GDCLASS(OpenXRActionMapEditor, VBoxContainer);
private:
+ Ref<EditorUndoRedoManager> undo_redo;
String edited_path;
Ref<OpenXRActionMap> action_map;
- Vector<Node *> interaction_profiles;
HBoxContainer *top_hb = nullptr;
Label *header_label = nullptr;
@@ -64,9 +65,9 @@ private:
OpenXRSelectInteractionProfileDialog *select_interaction_profile_dialog = nullptr;
OpenXRActionSetEditor *_add_action_set_editor(Ref<OpenXRActionSet> p_action_set);
- void _update_action_sets();
+ void _create_action_sets();
OpenXRInteractionProfileEditorBase *_add_interaction_profile_editor(Ref<OpenXRInteractionProfile> p_interaction_profile);
- void _update_interaction_profiles();
+ void _create_interaction_profiles();
OpenXRActionSetEditor *_add_action_set(String p_name);
void _remove_action_set(String p_name);
@@ -74,7 +75,7 @@ private:
void _on_add_action_set();
void _set_focus_on_action_set(OpenXRActionSetEditor *p_action_set_editor);
void _on_remove_action_set(Object *p_action_set_editor);
- void _on_action_removed();
+ void _on_action_removed(Ref<OpenXRAction> p_action);
void _on_add_interaction_profile();
void _on_interaction_profile_selected(const String p_path);
@@ -90,6 +91,14 @@ protected:
static void _bind_methods();
void _notification(int p_what);
+ void _clear_action_map();
+
+ // used for undo/redo
+ void _do_add_action_set_editor(OpenXRActionSetEditor *p_action_set_editor);
+ void _do_remove_action_set_editor(OpenXRActionSetEditor *p_action_set_editor);
+ void _do_add_interaction_profile_editor(OpenXRInteractionProfileEditorBase *p_interaction_profile_editor);
+ void _do_remove_interaction_profile_editor(OpenXRInteractionProfileEditorBase *p_interaction_profile_editor);
+
public:
void open_action_map(String p_path);
diff --git a/modules/openxr/editor/openxr_action_set_editor.cpp b/modules/openxr/editor/openxr_action_set_editor.cpp
index 3869146e8e..7f4da8b312 100644
--- a/modules/openxr/editor/openxr_action_set_editor.cpp
+++ b/modules/openxr/editor/openxr_action_set_editor.cpp
@@ -29,11 +29,18 @@
/*************************************************************************/
#include "openxr_action_set_editor.h"
+#include "editor/editor_node.h"
#include "openxr_action_editor.h"
void OpenXRActionSetEditor::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("_do_set_name", "name"), &OpenXRActionSetEditor::_do_set_name);
+ ClassDB::bind_method(D_METHOD("_do_set_localized_name", "name"), &OpenXRActionSetEditor::_do_set_localized_name);
+ ClassDB::bind_method(D_METHOD("_do_set_priority", "value"), &OpenXRActionSetEditor::_do_set_priority);
+ ClassDB::bind_method(D_METHOD("_do_add_action_editor", "action_editor"), &OpenXRActionSetEditor::_do_add_action_editor);
+ ClassDB::bind_method(D_METHOD("_do_remove_action_editor", "action_editor"), &OpenXRActionSetEditor::_do_remove_action_editor);
+
ADD_SIGNAL(MethodInfo("remove", PropertyInfo(Variant::OBJECT, "action_set_editor")));
- ADD_SIGNAL(MethodInfo("action_removed"));
+ ADD_SIGNAL(MethodInfo("action_removed", PropertyInfo(Variant::OBJECT, "action")));
}
void OpenXRActionSetEditor::_set_fold_icon() {
@@ -68,20 +75,6 @@ OpenXRActionEditor *OpenXRActionSetEditor::_add_action_editor(Ref<OpenXRAction>
return action_editor;
}
-void OpenXRActionSetEditor::_update_actions() {
- // out with the old...
- while (actions_vb->get_child_count() > 0) {
- memdelete(actions_vb->get_child(0));
- }
-
- // in with the new...
- Array actions = action_set->get_actions();
- for (int i = 0; i < actions.size(); i++) {
- Ref<OpenXRAction> action = actions[i];
- _add_action_editor(action);
- }
-}
-
void OpenXRActionSetEditor::_on_toggle_expand() {
is_expanded = !is_expanded;
actions_vb->set_visible(is_expanded);
@@ -89,24 +82,66 @@ void OpenXRActionSetEditor::_on_toggle_expand() {
}
void OpenXRActionSetEditor::_on_action_set_name_changed(const String p_new_text) {
- // TODO validate if entry is allowed
-
- // If our localized name matches our action set name, set this too
- if (action_set->get_name() == action_set->get_localized_name()) {
- action_set->set_localized_name(p_new_text);
- action_set_localized_name->set_text(p_new_text);
+ if (action_set->get_name() != p_new_text) {
+ undo_redo->create_action(TTR("Rename Action Set"));
+ undo_redo->add_do_method(this, "_do_set_name", p_new_text);
+ undo_redo->add_undo_method(this, "_do_set_name", action_set->get_name());
+ undo_redo->commit_action(false);
+
+ // If our localized name matches our action set name, set this too
+ if (action_set->get_name() == action_set->get_localized_name()) {
+ undo_redo->create_action(TTR("Rename Action Sets Localized name"));
+ undo_redo->add_do_method(this, "_do_set_localized_name", p_new_text);
+ undo_redo->add_undo_method(this, "_do_set_localized_name", action_set->get_localized_name());
+ undo_redo->commit_action(false);
+
+ action_set->set_localized_name(p_new_text);
+ action_set_localized_name->set_text(p_new_text);
+ }
+ action_set->set_name(p_new_text);
+ action_set->set_edited(true);
}
+}
+
+void OpenXRActionSetEditor::_do_set_name(const String p_new_text) {
action_set->set_name(p_new_text);
+ action_set_name->set_text(p_new_text);
}
void OpenXRActionSetEditor::_on_action_set_localized_name_changed(const String p_new_text) {
+ if (action_set->get_localized_name() != p_new_text) {
+ undo_redo->create_action(TTR("Rename Action Sets Localized name"));
+ undo_redo->add_do_method(this, "_do_set_localized_name", p_new_text);
+ undo_redo->add_undo_method(this, "_do_set_localized_name", action_set->get_localized_name());
+ undo_redo->commit_action(false);
+
+ action_set->set_localized_name(p_new_text);
+ action_set->set_edited(true);
+ }
+}
+
+void OpenXRActionSetEditor::_do_set_localized_name(const String p_new_text) {
action_set->set_localized_name(p_new_text);
+ action_set_localized_name->set_text(p_new_text);
}
void OpenXRActionSetEditor::_on_action_set_priority_changed(const String p_new_text) {
int64_t value = p_new_text.to_int();
- action_set->set_priority(value);
+ if (action_set->get_priority() != value) {
+ undo_redo->create_action(TTR("Change Action Sets priority"));
+ undo_redo->add_do_method(this, "_do_set_priority", value);
+ undo_redo->add_undo_method(this, "_do_set_priority", action_set->get_priority());
+ undo_redo->commit_action(false);
+
+ action_set->set_priority(value);
+ action_set->set_edited(true);
+ }
+}
+
+void OpenXRActionSetEditor::_do_set_priority(int64_t p_value) {
+ action_set->set_priority(p_value);
+ action_set_priority->set_text(itos(p_value));
}
void OpenXRActionSetEditor::_on_add_action() {
@@ -116,8 +151,14 @@ void OpenXRActionSetEditor::_on_add_action() {
new_action->set_name("New");
new_action->set_localized_name("New");
action_set->add_action(new_action);
+ action_set->set_edited(true);
- _add_action_editor(new_action);
+ OpenXRActionEditor *action_editor = _add_action_editor(new_action);
+
+ undo_redo->create_action(TTR("Add action"));
+ undo_redo->add_do_method(this, "_do_add_action_editor", action_editor);
+ undo_redo->add_undo_method(this, "_do_remove_action_editor", action_editor);
+ undo_redo->commit_action(false);
// TODO handle focus
}
@@ -133,17 +174,36 @@ void OpenXRActionSetEditor::_on_remove_action(Object *p_action_editor) {
Ref<OpenXRAction> action = action_editor->get_action();
ERR_FAIL_COND(action.is_null());
- // TODO add undo/redo action
+ emit_signal("action_removed", action);
+
+ undo_redo->create_action(TTR("Delete action"));
+ undo_redo->add_do_method(this, "_do_remove_action_editor", action_editor);
+ undo_redo->add_undo_method(this, "_do_add_action_editor", action_editor);
+ undo_redo->commit_action(true);
- // TODO find where this action is used by our interaction profiles and remove it there
+ action_set->set_edited(true);
+}
- // And remove it....
- action_map->remove_action(action->get_name_with_set()); // remove it from the set and any interaction profile it relates to
- actions_vb->remove_child(action_editor);
- action_editor->queue_free();
+void OpenXRActionSetEditor::_do_add_action_editor(OpenXRActionEditor *p_action_editor) {
+ Ref<OpenXRAction> action = p_action_editor->get_action();
+ ERR_FAIL_COND(action.is_null());
- // Let action map editor know so we can update our interaction profiles
- emit_signal("action_removed");
+ action_set->add_action(action);
+ actions_vb->add_child(p_action_editor);
+}
+
+void OpenXRActionSetEditor::_do_remove_action_editor(OpenXRActionEditor *p_action_editor) {
+ Ref<OpenXRAction> action = p_action_editor->get_action();
+ ERR_FAIL_COND(action.is_null());
+
+ actions_vb->remove_child(p_action_editor);
+ action_set->remove_action(action);
+}
+
+void OpenXRActionSetEditor::remove_all_actions() {
+ for (int i = actions_vb->get_child_count(); i > 0; --i) {
+ _on_remove_action(actions_vb->get_child(i));
+ }
}
void OpenXRActionSetEditor::set_focus_on_entry() {
@@ -152,6 +212,7 @@ void OpenXRActionSetEditor::set_focus_on_entry() {
}
OpenXRActionSetEditor::OpenXRActionSetEditor(Ref<OpenXRActionMap> p_action_map, Ref<OpenXRActionSet> p_action_set) {
+ undo_redo = EditorNode::get_undo_redo();
action_map = p_action_map;
action_set = p_action_set;
@@ -214,5 +275,10 @@ OpenXRActionSetEditor::OpenXRActionSetEditor(Ref<OpenXRActionMap> p_action_map,
actions_vb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
main_vb->add_child(actions_vb);
- _update_actions();
+ // Add our existing actions
+ Array actions = action_set->get_actions();
+ for (int i = 0; i < actions.size(); i++) {
+ Ref<OpenXRAction> action = actions[i];
+ _add_action_editor(action);
+ }
}
diff --git a/modules/openxr/editor/openxr_action_set_editor.h b/modules/openxr/editor/openxr_action_set_editor.h
index d8c85d03dd..7a8dc0dcbf 100644
--- a/modules/openxr/editor/openxr_action_set_editor.h
+++ b/modules/openxr/editor/openxr_action_set_editor.h
@@ -44,6 +44,7 @@ class OpenXRActionSetEditor : public HBoxContainer {
GDCLASS(OpenXRActionSetEditor, HBoxContainer);
private:
+ Ref<EditorUndoRedoManager> undo_redo;
Ref<OpenXRActionMap> action_map;
Ref<OpenXRActionSet> action_set;
@@ -63,7 +64,6 @@ private:
void _set_fold_icon();
void _theme_changed();
OpenXRActionEditor *_add_action_editor(Ref<OpenXRAction> p_action);
- void _update_actions();
void _on_toggle_expand();
void _on_action_set_name_changed(const String p_new_text);
@@ -78,10 +78,19 @@ protected:
static void _bind_methods();
void _notification(int p_what);
+ // used for undo/redo
+ void _do_set_name(const String p_new_text);
+ void _do_set_localized_name(const String p_new_text);
+ void _do_set_priority(int64_t value);
+ void _do_add_action_editor(OpenXRActionEditor *p_action_editor);
+ void _do_remove_action_editor(OpenXRActionEditor *p_action_editor);
+
public:
Ref<OpenXRActionSet> get_action_set() { return action_set; };
void set_focus_on_entry();
+ void remove_all_actions();
+
OpenXRActionSetEditor(Ref<OpenXRActionMap> p_action_map, Ref<OpenXRActionSet> p_action_set);
};
diff --git a/modules/openxr/editor/openxr_interaction_profile_editor.cpp b/modules/openxr/editor/openxr_interaction_profile_editor.cpp
index e2dc2d1b74..9d8ac76187 100644
--- a/modules/openxr/editor/openxr_interaction_profile_editor.cpp
+++ b/modules/openxr/editor/openxr_interaction_profile_editor.cpp
@@ -29,6 +29,7 @@
/*************************************************************************/
#include "openxr_interaction_profile_editor.h"
+#include "editor/editor_node.h"
#include "scene/gui/box_container.h"
#include "scene/gui/button.h"
#include "scene/gui/label.h"
@@ -58,6 +59,13 @@ void OpenXRInteractionProfileEditorBase::_notification(int p_what) {
}
}
+void OpenXRInteractionProfileEditorBase::_do_update_interaction_profile() {
+ if (!is_dirty) {
+ is_dirty = true;
+ call_deferred("_update_interaction_profile");
+ }
+}
+
void OpenXRInteractionProfileEditorBase::_add_binding(const String p_action, const String p_path) {
ERR_FAIL_COND(action_map.is_null());
ERR_FAIL_COND(interaction_profile.is_null());
@@ -71,14 +79,16 @@ void OpenXRInteractionProfileEditorBase::_add_binding(const String p_action, con
binding.instantiate();
binding->set_action(action);
interaction_profile->add_binding(binding);
+ interaction_profile->set_edited(true);
}
binding->add_path(p_path);
+ binding->set_edited(true);
// Update our toplevel paths
action->set_toplevel_paths(action_map->get_top_level_paths(action));
- call_deferred("_update_interaction_profile");
+ _do_update_interaction_profile();
}
void OpenXRInteractionProfileEditorBase::_remove_binding(const String p_action, const String p_path) {
@@ -91,25 +101,54 @@ void OpenXRInteractionProfileEditorBase::_remove_binding(const String p_action,
Ref<OpenXRIPBinding> binding = interaction_profile->get_binding_for_action(action);
if (binding.is_valid()) {
binding->remove_path(p_path);
+ binding->set_edited(true);
if (binding->get_path_count() == 0) {
interaction_profile->remove_binding(binding);
+ interaction_profile->set_edited(true);
}
// Update our toplevel paths
action->set_toplevel_paths(action_map->get_top_level_paths(action));
- call_deferred("_update_interaction_profile");
+ _do_update_interaction_profile();
+ }
+}
+
+void OpenXRInteractionProfileEditorBase::remove_all_bindings_for_action(Ref<OpenXRAction> p_action) {
+ Ref<OpenXRIPBinding> binding = interaction_profile->get_binding_for_action(p_action);
+ if (binding.is_valid()) {
+ String action_name = p_action->get_name_with_set();
+
+ // for our undo/redo we process all paths
+ undo_redo->create_action(TTR("Remove action from interaction profile"));
+ PackedStringArray paths = binding->get_paths();
+ for (const String &path : paths) {
+ undo_redo->add_do_method(this, "_remove_binding", action_name, path);
+ undo_redo->add_undo_method(this, "_add_binding", action_name, path);
+ }
+ undo_redo->commit_action(false);
+
+ // but we take a shortcut here :)
+ interaction_profile->remove_binding(binding);
+ interaction_profile->set_edited(true);
+
+ // Update our toplevel paths
+ p_action->set_toplevel_paths(action_map->get_top_level_paths(p_action));
+
+ _do_update_interaction_profile();
}
}
OpenXRInteractionProfileEditorBase::OpenXRInteractionProfileEditorBase(Ref<OpenXRActionMap> p_action_map, Ref<OpenXRInteractionProfile> p_interaction_profile) {
+ undo_redo = EditorNode::get_undo_redo();
+
action_map = p_action_map;
interaction_profile = p_interaction_profile;
String profile_path = interaction_profile->get_interaction_profile_path();
String profile_name = profile_path;
- profile_def = OpenXRDefs::get_profile(profile_path);
+ profile_def = OpenXRInteractionProfileMetaData::get_singleton()->get_profile(profile_path);
if (profile_def != nullptr) {
profile_name = profile_def->display_name;
}
@@ -117,6 +156,9 @@ OpenXRInteractionProfileEditorBase::OpenXRInteractionProfileEditorBase(Ref<OpenX
set_name(profile_name);
set_h_size_flags(SIZE_EXPAND_FILL);
set_v_size_flags(SIZE_EXPAND_FILL);
+
+ // Make sure it is updated when it enters the tree...
+ is_dirty = true;
}
///////////////////////////////////////////////////////////////////////////
@@ -128,11 +170,22 @@ void OpenXRInteractionProfileEditor::select_action_for(const String p_io_path) {
}
void OpenXRInteractionProfileEditor::action_selected(const String p_action) {
- _add_binding(p_action, selecting_for_io_path);
+ undo_redo->create_action(TTR("Add binding"));
+ undo_redo->add_do_method(this, "_add_binding", p_action, selecting_for_io_path);
+ undo_redo->add_undo_method(this, "_remove_binding", p_action, selecting_for_io_path);
+ undo_redo->commit_action(true);
+
selecting_for_io_path = "";
}
-void OpenXRInteractionProfileEditor::_add_io_path(VBoxContainer *p_container, const OpenXRDefs::IOPath *p_io_path) {
+void OpenXRInteractionProfileEditor::_on_remove_pressed(const String p_action, const String p_for_io_path) {
+ undo_redo->create_action(TTR("Remove binding"));
+ undo_redo->add_do_method(this, "_remove_binding", p_action, p_for_io_path);
+ undo_redo->add_undo_method(this, "_add_binding", p_action, p_for_io_path);
+ undo_redo->commit_action(true);
+}
+
+void OpenXRInteractionProfileEditor::_add_io_path(VBoxContainer *p_container, const OpenXRInteractionProfileMetaData::IOPath *p_io_path) {
HBoxContainer *path_hb = memnew(HBoxContainer);
path_hb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
p_container->add_child(path_hb);
@@ -196,7 +249,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")));
- action_rem->connect("pressed", callable_mp((OpenXRInteractionProfileEditorBase *)this, &OpenXRInteractionProfileEditorBase::_remove_binding).bind(action->get_name_with_set(), String(p_io_path->openxr_path)));
+ action_rem->connect("pressed", callable_mp((OpenXRInteractionProfileEditor *)this, &OpenXRInteractionProfileEditor::_on_remove_pressed).bind(action->get_name_with_set(), String(p_io_path->openxr_path)));
action_hb->add_child(action_rem);
}
}
@@ -206,6 +259,11 @@ void OpenXRInteractionProfileEditor::_add_io_path(VBoxContainer *p_container, co
void OpenXRInteractionProfileEditor::_update_interaction_profile() {
ERR_FAIL_NULL(profile_def);
+ if (!is_dirty) {
+ // no need to update
+ return;
+ }
+
// out with the old...
while (main_hb->get_child_count() > 0) {
memdelete(main_hb->get_child(0));
@@ -214,9 +272,9 @@ void OpenXRInteractionProfileEditor::_update_interaction_profile() {
// in with the new...
// Determine toplevel paths
- Vector<const OpenXRDefs::TopLevelPath *> top_level_paths;
- for (int i = 0; i < profile_def->io_path_count; i++) {
- const OpenXRDefs::IOPath *io_path = &profile_def->io_paths[i];
+ Vector<String> top_level_paths;
+ for (int i = 0; i < profile_def->io_paths.size(); i++) {
+ const OpenXRInteractionProfileMetaData::IOPath *io_path = &profile_def->io_paths[i];
if (!top_level_paths.has(io_path->top_level_path)) {
top_level_paths.push_back(io_path->top_level_path);
@@ -233,21 +291,24 @@ void OpenXRInteractionProfileEditor::_update_interaction_profile() {
panel->add_child(container);
Label *label = memnew(Label);
- label->set_text(top_level_paths[i]->display_name);
+ label->set_text(OpenXRInteractionProfileMetaData::get_singleton()->get_top_level_name(top_level_paths[i]));
container->add_child(label);
- for (int j = 0; j < profile_def->io_path_count; j++) {
- const OpenXRDefs::IOPath *io_path = &profile_def->io_paths[j];
+ for (int j = 0; j < profile_def->io_paths.size(); j++) {
+ const OpenXRInteractionProfileMetaData::IOPath *io_path = &profile_def->io_paths[j];
if (io_path->top_level_path == top_level_paths[i]) {
_add_io_path(container, io_path);
}
}
}
+
+ // and we've updated it...
+ is_dirty = false;
}
void OpenXRInteractionProfileEditor::_theme_changed() {
for (int i = 0; i < main_hb->get_child_count(); i++) {
- Control *panel = static_cast<Control *>(main_hb->get_child(i));
+ Control *panel = Object::cast_to<Control>(main_hb->get_child(i));
if (panel) {
panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("panel"), SNAME("TabContainer")));
}
@@ -256,14 +317,10 @@ void OpenXRInteractionProfileEditor::_theme_changed() {
OpenXRInteractionProfileEditor::OpenXRInteractionProfileEditor(Ref<OpenXRActionMap> p_action_map, Ref<OpenXRInteractionProfile> p_interaction_profile) :
OpenXRInteractionProfileEditorBase(p_action_map, p_interaction_profile) {
- // TODO background of scrollbox should be darker with our VBoxContainers we're adding in _update_interaction_profile the normal color
-
main_hb = memnew(HBoxContainer);
add_child(main_hb);
select_action_dialog = memnew(OpenXRSelectActionDialog(p_action_map));
select_action_dialog->connect("action_selected", callable_mp(this, &OpenXRInteractionProfileEditor::action_selected));
add_child(select_action_dialog);
-
- _update_interaction_profile();
}
diff --git a/modules/openxr/editor/openxr_interaction_profile_editor.h b/modules/openxr/editor/openxr_interaction_profile_editor.h
index 20a37a80eb..14af702b94 100644
--- a/modules/openxr/editor/openxr_interaction_profile_editor.h
+++ b/modules/openxr/editor/openxr_interaction_profile_editor.h
@@ -32,8 +32,9 @@
#define OPENXR_INTERACTION_PROFILE_EDITOR_H
#include "../action_map/openxr_action_map.h"
-#include "../action_map/openxr_defs.h"
#include "../action_map/openxr_interaction_profile.h"
+#include "../action_map/openxr_interaction_profile_meta_data.h"
+#include "editor/editor_undo_redo_manager.h"
#include "scene/gui/scroll_container.h"
#include "openxr_select_action_dialog.h"
@@ -42,22 +43,29 @@ class OpenXRInteractionProfileEditorBase : public ScrollContainer {
GDCLASS(OpenXRInteractionProfileEditorBase, ScrollContainer);
protected:
+ Ref<EditorUndoRedoManager> undo_redo;
Ref<OpenXRInteractionProfile> interaction_profile;
Ref<OpenXRActionMap> action_map;
+ bool is_dirty = false;
+
static void _bind_methods();
void _notification(int p_what);
- const OpenXRDefs::InteractionProfile *profile_def = nullptr;
+ const OpenXRInteractionProfileMetaData::InteractionProfile *profile_def = nullptr;
public:
Ref<OpenXRInteractionProfile> get_interaction_profile() { return interaction_profile; }
virtual void _update_interaction_profile() {}
virtual void _theme_changed() {}
+
+ void _do_update_interaction_profile();
void _add_binding(const String p_action, const String p_path);
void _remove_binding(const String p_action, const String p_path);
+ void remove_all_bindings_for_action(Ref<OpenXRAction> p_action);
+
OpenXRInteractionProfileEditorBase(Ref<OpenXRActionMap> p_action_map, Ref<OpenXRInteractionProfile> p_interaction_profile);
};
@@ -69,11 +77,12 @@ private:
HBoxContainer *main_hb = nullptr;
OpenXRSelectActionDialog *select_action_dialog = nullptr;
- void _add_io_path(VBoxContainer *p_container, const OpenXRDefs::IOPath *p_io_path);
+ void _add_io_path(VBoxContainer *p_container, const OpenXRInteractionProfileMetaData::IOPath *p_io_path);
public:
void select_action_for(const String p_io_path);
void action_selected(const String p_action);
+ void _on_remove_pressed(const String p_action, const String p_for_io_path);
virtual void _update_interaction_profile() override;
virtual void _theme_changed() override;
diff --git a/modules/openxr/editor/openxr_select_action_dialog.cpp b/modules/openxr/editor/openxr_select_action_dialog.cpp
index 5f018291d5..c4b2ef95c5 100644
--- a/modules/openxr/editor/openxr_select_action_dialog.cpp
+++ b/modules/openxr/editor/openxr_select_action_dialog.cpp
@@ -47,7 +47,7 @@ void OpenXRSelectActionDialog::_notification(int p_what) {
void OpenXRSelectActionDialog::_on_select_action(const String p_action) {
if (selected_action != "") {
NodePath button_path = action_buttons[selected_action];
- Button *button = static_cast<Button *>(get_node(button_path));
+ Button *button = Object::cast_to<Button>(get_node(button_path));
if (button != nullptr) {
button->set_flat(true);
}
@@ -57,7 +57,7 @@ void OpenXRSelectActionDialog::_on_select_action(const String p_action) {
if (selected_action != "") {
NodePath button_path = action_buttons[selected_action];
- Button *button = static_cast<Button *>(get_node(button_path));
+ Button *button = Object::cast_to<Button>(get_node(button_path));
if (button != nullptr) {
button->set_flat(false);
}
diff --git a/modules/openxr/editor/openxr_select_interaction_profile_dialog.cpp b/modules/openxr/editor/openxr_select_interaction_profile_dialog.cpp
index e92519aec2..b871840cb2 100644
--- a/modules/openxr/editor/openxr_select_interaction_profile_dialog.cpp
+++ b/modules/openxr/editor/openxr_select_interaction_profile_dialog.cpp
@@ -46,7 +46,7 @@ void OpenXRSelectInteractionProfileDialog::_notification(int p_what) {
void OpenXRSelectInteractionProfileDialog::_on_select_interaction_profile(const String p_interaction_profile) {
if (selected_interaction_profile != "") {
NodePath button_path = ip_buttons[selected_interaction_profile];
- Button *button = static_cast<Button *>(get_node(button_path));
+ Button *button = Object::cast_to<Button>(get_node(button_path));
if (button != nullptr) {
button->set_flat(true);
}
@@ -56,7 +56,7 @@ void OpenXRSelectInteractionProfileDialog::_on_select_interaction_profile(const
if (selected_interaction_profile != "") {
NodePath button_path = ip_buttons[selected_interaction_profile];
- Button *button = static_cast<Button *>(get_node(button_path));
+ Button *button = Object::cast_to<Button>(get_node(button_path));
if (button != nullptr) {
button->set_flat(false);
}
@@ -75,13 +75,13 @@ void OpenXRSelectInteractionProfileDialog::open(PackedStringArray p_do_not_inclu
ip_buttons.clear();
// in with the new
- PackedStringArray interaction_profiles = OpenXRDefs::get_interaction_profile_paths();
+ PackedStringArray interaction_profiles = OpenXRInteractionProfileMetaData::get_singleton()->get_interaction_profile_paths();
for (int i = 0; i < interaction_profiles.size(); i++) {
String path = interaction_profiles[i];
if (!p_do_not_include.has(path)) {
Button *ip_button = memnew(Button);
ip_button->set_flat(true);
- ip_button->set_text(OpenXRDefs::get_profile(path)->display_name);
+ ip_button->set_text(OpenXRInteractionProfileMetaData::get_singleton()->get_profile(path)->display_name);
ip_button->connect("pressed", callable_mp(this, &OpenXRSelectInteractionProfileDialog::_on_select_interaction_profile).bind(path));
main_vb->add_child(ip_button);
diff --git a/modules/openxr/editor/openxr_select_interaction_profile_dialog.h b/modules/openxr/editor/openxr_select_interaction_profile_dialog.h
index 54bfe3120a..767326bc46 100644
--- a/modules/openxr/editor/openxr_select_interaction_profile_dialog.h
+++ b/modules/openxr/editor/openxr_select_interaction_profile_dialog.h
@@ -31,7 +31,7 @@
#ifndef OPENXR_SELECT_INTERACTION_PROFILE_DIALOG_H
#define OPENXR_SELECT_INTERACTION_PROFILE_DIALOG_H
-#include "../action_map/openxr_defs.h"
+#include "../action_map/openxr_interaction_profile_meta_data.h"
#include "scene/gui/box_container.h"
#include "scene/gui/button.h"
#include "scene/gui/dialogs.h"
diff --git a/modules/openxr/extensions/openxr_android_extension.cpp b/modules/openxr/extensions/openxr_android_extension.cpp
index 8f6d5c28db..402a2ee707 100644
--- a/modules/openxr/extensions/openxr_android_extension.cpp
+++ b/modules/openxr/extensions/openxr_android_extension.cpp
@@ -47,10 +47,15 @@ OpenXRAndroidExtension *OpenXRAndroidExtension::get_singleton() {
OpenXRAndroidExtension::OpenXRAndroidExtension(OpenXRAPI *p_openxr_api) :
OpenXRExtensionWrapper(p_openxr_api) {
singleton = this;
- request_extensions[XR_KHR_ANDROID_THREAD_SETTINGS_EXTENSION_NAME] = nullptr; // must be available
+ request_extensions[XR_KHR_LOADER_INIT_ANDROID_EXTENSION_NAME] = &loader_init_extension_available;
+ request_extensions[XR_KHR_ANDROID_CREATE_INSTANCE_EXTENSION_NAME] = &create_instance_extension_available;
}
void OpenXRAndroidExtension::on_before_instance_created() {
+ if (!loader_init_extension_available) {
+ print_line("OpenXR: XR_KHR_loader_init_android is not reported as available - trying to initialize anyway...");
+ }
+
EXT_INIT_XR_FUNC(xrInitializeLoaderKHR);
JNIEnv *env = get_jni_env();
@@ -68,6 +73,29 @@ void OpenXRAndroidExtension::on_before_instance_created() {
ERR_FAIL_COND_MSG(XR_FAILED(result), "Failed to call xrInitializeLoaderKHR");
}
+// We're keeping the Android create info struct here to avoid including openxr_platform.h in a header, which would break other extensions.
+// This is reasonably safe as the struct is only used during initialization and the extension is a singleton.
+static XrInstanceCreateInfoAndroidKHR instance_create_info;
+
+void *OpenXRAndroidExtension::set_instance_create_info_and_get_next_pointer(void *p_next_pointer) {
+ if (!create_instance_extension_available) {
+ return nullptr;
+ }
+
+ JNIEnv *env = get_jni_env();
+ JavaVM *vm;
+ env->GetJavaVM(&vm);
+ jobject activity_object = env->NewGlobalRef(static_cast<OS_Android *>(OS::get_singleton())->get_godot_java()->get_activity());
+
+ instance_create_info = {
+ .type = XR_TYPE_INSTANCE_CREATE_INFO_ANDROID_KHR,
+ .next = p_next_pointer,
+ .applicationVM = vm,
+ .applicationActivity = activity_object
+ };
+ return &instance_create_info;
+}
+
OpenXRAndroidExtension::~OpenXRAndroidExtension() {
singleton = nullptr;
}
diff --git a/modules/openxr/extensions/openxr_android_extension.h b/modules/openxr/extensions/openxr_android_extension.h
index eda7022064..087b634756 100644
--- a/modules/openxr/extensions/openxr_android_extension.h
+++ b/modules/openxr/extensions/openxr_android_extension.h
@@ -41,12 +41,16 @@ public:
OpenXRAndroidExtension(OpenXRAPI *p_openxr_api);
virtual void on_before_instance_created() override;
+ virtual void *set_instance_create_info_and_get_next_pointer(void *p_next_pointer) override;
virtual ~OpenXRAndroidExtension() override;
private:
static OpenXRAndroidExtension *singleton;
+ bool loader_init_extension_available = false;
+ bool create_instance_extension_available = false;
+
// Initialize the loader
EXT_PROTO_XRRESULT_FUNC1(xrInitializeLoaderKHR, (const XrLoaderInitInfoBaseHeaderKHR *), loaderInitInfo)
};
diff --git a/modules/openxr/extensions/openxr_extension_wrapper.h b/modules/openxr/extensions/openxr_extension_wrapper.h
index c417c90d11..eed969d628 100644
--- a/modules/openxr/extensions/openxr_extension_wrapper.h
+++ b/modules/openxr/extensions/openxr_extension_wrapper.h
@@ -65,6 +65,7 @@ public:
virtual void *set_system_properties_and_get_next_pointer(void *p_next_pointer) { return p_next_pointer; }
virtual void *set_session_create_and_get_next_pointer(void *p_next_pointer) { return p_next_pointer; }
virtual void *set_swapchain_create_info_and_get_next_pointer(void *p_next_pointer) { return p_next_pointer; }
+ virtual void *set_instance_create_info_and_get_next_pointer(void *p_next_pointer) { return p_next_pointer; }
virtual void on_before_instance_created() {}
virtual void on_instance_created(const XrInstance p_instance) {}
@@ -88,11 +89,6 @@ public:
return false;
}
- // Return false if this extension is responsible for this path but the path is not enabled
- virtual bool is_path_supported(const String &p_path) {
- return true;
- }
-
OpenXRExtensionWrapper(OpenXRAPI *p_openxr_api) { openxr_api = p_openxr_api; };
virtual ~OpenXRExtensionWrapper() = default;
};
diff --git a/modules/openxr/extensions/openxr_htc_vive_tracker_extension.cpp b/modules/openxr/extensions/openxr_htc_vive_tracker_extension.cpp
index 4d996e6283..302acf4e30 100644
--- a/modules/openxr/extensions/openxr_htc_vive_tracker_extension.cpp
+++ b/modules/openxr/extensions/openxr_htc_vive_tracker_extension.cpp
@@ -65,40 +65,3 @@ bool OpenXRHTCViveTrackerExtension::on_event_polled(const XrEventDataBuffer &eve
} break;
}
}
-
-bool OpenXRHTCViveTrackerExtension::is_path_supported(const String &p_path) {
- if (p_path == "/interaction_profiles/htc/vive_tracker_htcx") {
- return available;
- } else if (p_path == "/user/vive_tracker_htcx/role/handheld_object") {
- return available;
- } else if (p_path == "/user/vive_tracker_htcx/role/left_foot") {
- return available;
- } else if (p_path == "/user/vive_tracker_htcx/role/right_foot") {
- return available;
- } else if (p_path == "/user/vive_tracker_htcx/role/left_shoulder") {
- return available;
- } else if (p_path == "/user/vive_tracker_htcx/role/right_shoulder") {
- return available;
- } else if (p_path == "/user/vive_tracker_htcx/role/left_elbow") {
- return available;
- } else if (p_path == "/user/vive_tracker_htcx/role/right_elbow") {
- return available;
- } else if (p_path == "/user/vive_tracker_htcx/role/left_knee") {
- return available;
- } else if (p_path == "/user/vive_tracker_htcx/role/right_knee") {
- return available;
- } else if (p_path == "/user/vive_tracker_htcx/role/waist") {
- return available;
- } else if (p_path == "/user/vive_tracker_htcx/role/chest") {
- return available;
- } else if (p_path == "/user/vive_tracker_htcx/role/chest") {
- return available;
- } else if (p_path == "/user/vive_tracker_htcx/role/camera") {
- return available;
- } else if (p_path == "/user/vive_tracker_htcx/role/keyboard") {
- return available;
- }
-
- // Not a path under this extensions control, so we return true;
- return true;
-}
diff --git a/modules/openxr/extensions/openxr_htc_vive_tracker_extension.h b/modules/openxr/extensions/openxr_htc_vive_tracker_extension.h
index ab8e8535f1..376af35e37 100644
--- a/modules/openxr/extensions/openxr_htc_vive_tracker_extension.h
+++ b/modules/openxr/extensions/openxr_htc_vive_tracker_extension.h
@@ -43,7 +43,6 @@ public:
bool is_available();
virtual bool on_event_polled(const XrEventDataBuffer &event) override;
- virtual bool is_path_supported(const String &p_path) override;
private:
static OpenXRHTCViveTrackerExtension *singleton;
diff --git a/modules/openxr/extensions/openxr_opengl_extension.cpp b/modules/openxr/extensions/openxr_opengl_extension.cpp
index ee69144123..3b7c130149 100644
--- a/modules/openxr/extensions/openxr_opengl_extension.cpp
+++ b/modules/openxr/extensions/openxr_opengl_extension.cpp
@@ -136,9 +136,9 @@ void *OpenXROpenGLExtension::set_session_create_and_get_next_pointer(void *p_nex
graphics_binding_gl.type = XR_TYPE_GRAPHICS_BINDING_OPENGL_ES_ANDROID_KHR;
graphics_binding_gl.next = p_next_pointer;
- graphics_binding_gl.display = eglGetCurrentDisplay();
+ graphics_binding_gl.display = (void *)display_server->window_get_native_handle(DisplayServer::DISPLAY_HANDLE);
graphics_binding_gl.config = (EGLConfig)0; // https://github.com/KhronosGroup/OpenXR-SDK-Source/blob/master/src/tests/hello_xr/graphicsplugin_opengles.cpp#L122
- graphics_binding_gl.context = eglGetCurrentContext();
+ graphics_binding_gl.context = (void *)display_server->window_get_native_handle(DisplayServer::OPENGL_CONTEXT);
#else
graphics_binding_gl.type = XR_TYPE_GRAPHICS_BINDING_OPENGL_XLIB_KHR;
graphics_binding_gl.next = p_next_pointer;
@@ -160,16 +160,8 @@ void *OpenXROpenGLExtension::set_session_create_and_get_next_pointer(void *p_nex
}
void OpenXROpenGLExtension::get_usable_swapchain_formats(Vector<int64_t> &p_usable_swap_chains) {
-#ifdef WIN32
- p_usable_swap_chains.push_back(GL_SRGB8_ALPHA8);
- p_usable_swap_chains.push_back(GL_RGBA8);
-#elif ANDROID_ENABLED
p_usable_swap_chains.push_back(GL_SRGB8_ALPHA8);
p_usable_swap_chains.push_back(GL_RGBA8);
-#else
- p_usable_swap_chains.push_back(GL_SRGB8_ALPHA8_EXT);
- p_usable_swap_chains.push_back(GL_RGBA8_EXT);
-#endif
}
void OpenXROpenGLExtension::get_usable_depth_formats(Vector<int64_t> &p_usable_depth_formats) {
@@ -294,59 +286,7 @@ void OpenXROpenGLExtension::cleanup_swapchain_graphics_data(void **p_swapchain_g
String OpenXROpenGLExtension::get_swapchain_format_name(int64_t p_swapchain_format) const {
// These are somewhat different per platform, will need to weed some stuff out...
switch (p_swapchain_format) {
-#ifdef WIN32
- // using definitions from GLAD
- ENUM_TO_STRING_CASE(GL_R8_SNORM)
- ENUM_TO_STRING_CASE(GL_RG8_SNORM)
- ENUM_TO_STRING_CASE(GL_RGB8_SNORM)
- ENUM_TO_STRING_CASE(GL_RGBA8_SNORM)
- ENUM_TO_STRING_CASE(GL_R16_SNORM)
- ENUM_TO_STRING_CASE(GL_RG16_SNORM)
- ENUM_TO_STRING_CASE(GL_RGB16_SNORM)
- ENUM_TO_STRING_CASE(GL_RGBA16_SNORM)
- ENUM_TO_STRING_CASE(GL_RGB4)
- ENUM_TO_STRING_CASE(GL_RGB5)
- ENUM_TO_STRING_CASE(GL_RGB8)
- ENUM_TO_STRING_CASE(GL_RGB10)
- ENUM_TO_STRING_CASE(GL_RGB12)
- ENUM_TO_STRING_CASE(GL_RGB16)
- ENUM_TO_STRING_CASE(GL_RGBA2)
- ENUM_TO_STRING_CASE(GL_RGBA4)
- ENUM_TO_STRING_CASE(GL_RGB5_A1)
- ENUM_TO_STRING_CASE(GL_RGBA8)
- ENUM_TO_STRING_CASE(GL_RGB10_A2)
- ENUM_TO_STRING_CASE(GL_RGBA12)
- ENUM_TO_STRING_CASE(GL_RGBA16)
- ENUM_TO_STRING_CASE(GL_RGBA32F)
- ENUM_TO_STRING_CASE(GL_RGB32F)
- ENUM_TO_STRING_CASE(GL_RGBA16F)
- ENUM_TO_STRING_CASE(GL_RGB16F)
- ENUM_TO_STRING_CASE(GL_RGBA32UI)
- ENUM_TO_STRING_CASE(GL_RGB32UI)
- ENUM_TO_STRING_CASE(GL_RGBA16UI)
- ENUM_TO_STRING_CASE(GL_RGB16UI)
- ENUM_TO_STRING_CASE(GL_RGBA8UI)
- ENUM_TO_STRING_CASE(GL_RGB8UI)
- ENUM_TO_STRING_CASE(GL_RGBA32I)
- ENUM_TO_STRING_CASE(GL_RGB32I)
- ENUM_TO_STRING_CASE(GL_RGBA16I)
- ENUM_TO_STRING_CASE(GL_RGB16I)
- ENUM_TO_STRING_CASE(GL_RGBA8I)
- ENUM_TO_STRING_CASE(GL_RGB8I)
- ENUM_TO_STRING_CASE(GL_RGB10_A2UI)
- ENUM_TO_STRING_CASE(GL_SRGB)
- ENUM_TO_STRING_CASE(GL_SRGB8)
- ENUM_TO_STRING_CASE(GL_SRGB_ALPHA)
- ENUM_TO_STRING_CASE(GL_SRGB8_ALPHA8)
- ENUM_TO_STRING_CASE(GL_DEPTH_COMPONENT16)
- ENUM_TO_STRING_CASE(GL_DEPTH_COMPONENT24)
- ENUM_TO_STRING_CASE(GL_DEPTH_COMPONENT32)
- ENUM_TO_STRING_CASE(GL_DEPTH24_STENCIL8)
- ENUM_TO_STRING_CASE(GL_R11F_G11F_B10F)
- ENUM_TO_STRING_CASE(GL_DEPTH_COMPONENT32F)
- ENUM_TO_STRING_CASE(GL_DEPTH32F_STENCIL8)
-
-#elif ANDROID_ENABLED
+#ifdef ANDROID_ENABLED
// using definitions from GLES3/gl3.h
ENUM_TO_STRING_CASE(GL_RGBA4)
@@ -418,44 +358,56 @@ String OpenXROpenGLExtension::get_swapchain_format_name(int64_t p_swapchain_form
ENUM_TO_STRING_CASE(GL_DEPTH24_STENCIL8)
#else
- // using definitions from GL/gl.h
- ENUM_TO_STRING_CASE(GL_ALPHA4_EXT)
- ENUM_TO_STRING_CASE(GL_ALPHA8_EXT)
- ENUM_TO_STRING_CASE(GL_ALPHA12_EXT)
- ENUM_TO_STRING_CASE(GL_ALPHA16_EXT)
- ENUM_TO_STRING_CASE(GL_LUMINANCE4_EXT)
- ENUM_TO_STRING_CASE(GL_LUMINANCE8_EXT)
- ENUM_TO_STRING_CASE(GL_LUMINANCE12_EXT)
- ENUM_TO_STRING_CASE(GL_LUMINANCE16_EXT)
- ENUM_TO_STRING_CASE(GL_LUMINANCE4_ALPHA4_EXT)
- ENUM_TO_STRING_CASE(GL_LUMINANCE6_ALPHA2_EXT)
- ENUM_TO_STRING_CASE(GL_LUMINANCE8_ALPHA8_EXT)
- ENUM_TO_STRING_CASE(GL_LUMINANCE12_ALPHA4_EXT)
- ENUM_TO_STRING_CASE(GL_LUMINANCE12_ALPHA12_EXT)
- ENUM_TO_STRING_CASE(GL_LUMINANCE16_ALPHA16_EXT)
- ENUM_TO_STRING_CASE(GL_INTENSITY_EXT)
- ENUM_TO_STRING_CASE(GL_INTENSITY4_EXT)
- ENUM_TO_STRING_CASE(GL_INTENSITY8_EXT)
- ENUM_TO_STRING_CASE(GL_INTENSITY12_EXT)
- ENUM_TO_STRING_CASE(GL_INTENSITY16_EXT)
- ENUM_TO_STRING_CASE(GL_RGB2_EXT)
- ENUM_TO_STRING_CASE(GL_RGB4_EXT)
- ENUM_TO_STRING_CASE(GL_RGB5_EXT)
- ENUM_TO_STRING_CASE(GL_RGB8_EXT)
- ENUM_TO_STRING_CASE(GL_RGB10_EXT)
- ENUM_TO_STRING_CASE(GL_RGB12_EXT)
- ENUM_TO_STRING_CASE(GL_RGB16_EXT)
- ENUM_TO_STRING_CASE(GL_RGBA2_EXT)
- ENUM_TO_STRING_CASE(GL_RGBA4_EXT)
- ENUM_TO_STRING_CASE(GL_RGB5_A1_EXT)
- ENUM_TO_STRING_CASE(GL_RGBA8_EXT)
- ENUM_TO_STRING_CASE(GL_RGB10_A2_EXT)
- ENUM_TO_STRING_CASE(GL_RGBA12_EXT)
- ENUM_TO_STRING_CASE(GL_RGBA16_EXT)
- ENUM_TO_STRING_CASE(GL_SRGB_EXT)
- ENUM_TO_STRING_CASE(GL_SRGB8_EXT)
- ENUM_TO_STRING_CASE(GL_SRGB_ALPHA_EXT)
- ENUM_TO_STRING_CASE(GL_SRGB8_ALPHA8_EXT)
+ // using definitions from GLAD
+ ENUM_TO_STRING_CASE(GL_R8_SNORM)
+ ENUM_TO_STRING_CASE(GL_RG8_SNORM)
+ ENUM_TO_STRING_CASE(GL_RGB8_SNORM)
+ ENUM_TO_STRING_CASE(GL_RGBA8_SNORM)
+ ENUM_TO_STRING_CASE(GL_R16_SNORM)
+ ENUM_TO_STRING_CASE(GL_RG16_SNORM)
+ ENUM_TO_STRING_CASE(GL_RGB16_SNORM)
+ ENUM_TO_STRING_CASE(GL_RGBA16_SNORM)
+ ENUM_TO_STRING_CASE(GL_RGB4)
+ ENUM_TO_STRING_CASE(GL_RGB5)
+ ENUM_TO_STRING_CASE(GL_RGB8)
+ ENUM_TO_STRING_CASE(GL_RGB10)
+ ENUM_TO_STRING_CASE(GL_RGB12)
+ ENUM_TO_STRING_CASE(GL_RGB16)
+ ENUM_TO_STRING_CASE(GL_RGBA2)
+ ENUM_TO_STRING_CASE(GL_RGBA4)
+ ENUM_TO_STRING_CASE(GL_RGB5_A1)
+ ENUM_TO_STRING_CASE(GL_RGBA8)
+ ENUM_TO_STRING_CASE(GL_RGB10_A2)
+ ENUM_TO_STRING_CASE(GL_RGBA12)
+ ENUM_TO_STRING_CASE(GL_RGBA16)
+ ENUM_TO_STRING_CASE(GL_RGBA32F)
+ ENUM_TO_STRING_CASE(GL_RGB32F)
+ ENUM_TO_STRING_CASE(GL_RGBA16F)
+ ENUM_TO_STRING_CASE(GL_RGB16F)
+ ENUM_TO_STRING_CASE(GL_RGBA32UI)
+ ENUM_TO_STRING_CASE(GL_RGB32UI)
+ ENUM_TO_STRING_CASE(GL_RGBA16UI)
+ ENUM_TO_STRING_CASE(GL_RGB16UI)
+ ENUM_TO_STRING_CASE(GL_RGBA8UI)
+ ENUM_TO_STRING_CASE(GL_RGB8UI)
+ ENUM_TO_STRING_CASE(GL_RGBA32I)
+ ENUM_TO_STRING_CASE(GL_RGB32I)
+ ENUM_TO_STRING_CASE(GL_RGBA16I)
+ ENUM_TO_STRING_CASE(GL_RGB16I)
+ ENUM_TO_STRING_CASE(GL_RGBA8I)
+ ENUM_TO_STRING_CASE(GL_RGB8I)
+ ENUM_TO_STRING_CASE(GL_RGB10_A2UI)
+ ENUM_TO_STRING_CASE(GL_SRGB)
+ ENUM_TO_STRING_CASE(GL_SRGB8)
+ ENUM_TO_STRING_CASE(GL_SRGB_ALPHA)
+ ENUM_TO_STRING_CASE(GL_SRGB8_ALPHA8)
+ ENUM_TO_STRING_CASE(GL_DEPTH_COMPONENT16)
+ ENUM_TO_STRING_CASE(GL_DEPTH_COMPONENT24)
+ ENUM_TO_STRING_CASE(GL_DEPTH_COMPONENT32)
+ ENUM_TO_STRING_CASE(GL_DEPTH24_STENCIL8)
+ ENUM_TO_STRING_CASE(GL_R11F_G11F_B10F)
+ ENUM_TO_STRING_CASE(GL_DEPTH_COMPONENT32F)
+ ENUM_TO_STRING_CASE(GL_DEPTH32F_STENCIL8)
#endif
default: {
return String("Swapchain format 0x") + String::num_int64(p_swapchain_format, 16);
diff --git a/modules/openxr/extensions/openxr_opengl_extension.h b/modules/openxr/extensions/openxr_opengl_extension.h
index b666653c8e..473c5157c0 100644
--- a/modules/openxr/extensions/openxr_opengl_extension.h
+++ b/modules/openxr/extensions/openxr_opengl_extension.h
@@ -59,9 +59,8 @@
#include OPENGL_INCLUDE_H
#define GL_GLEXT_PROTOTYPES 1
#define GL3_PROTOTYPES 1
-#include <GL/gl.h>
-#include <GL/glext.h>
-#include <GL/glx.h>
+#include "thirdparty/glad/glad/gl.h"
+#include "thirdparty/glad/glad/glx.h"
#include <X11/Xlib.h>
#endif
diff --git a/modules/openxr/extensions/openxr_palm_pose_extension.cpp b/modules/openxr/extensions/openxr_palm_pose_extension.cpp
index fd3b8f50fe..8f87aaea7f 100644
--- a/modules/openxr/extensions/openxr_palm_pose_extension.cpp
+++ b/modules/openxr/extensions/openxr_palm_pose_extension.cpp
@@ -51,16 +51,3 @@ OpenXRPalmPoseExtension::~OpenXRPalmPoseExtension() {
bool OpenXRPalmPoseExtension::is_available() {
return available;
}
-
-bool OpenXRPalmPoseExtension::is_path_supported(const String &p_path) {
- if (p_path == "/user/hand/left/input/palm_ext/pose") {
- return available;
- }
-
- if (p_path == "/user/hand/right/input/palm_ext/pose") {
- return available;
- }
-
- // Not a path under this extensions control, so we return true;
- return true;
-}
diff --git a/modules/openxr/extensions/openxr_palm_pose_extension.h b/modules/openxr/extensions/openxr_palm_pose_extension.h
index a7ef83c5d5..a63c57eb51 100644
--- a/modules/openxr/extensions/openxr_palm_pose_extension.h
+++ b/modules/openxr/extensions/openxr_palm_pose_extension.h
@@ -42,8 +42,6 @@ public:
bool is_available();
- virtual bool is_path_supported(const String &p_path) override;
-
private:
static OpenXRPalmPoseExtension *singleton;
diff --git a/modules/openxr/openxr_api.cpp b/modules/openxr/openxr_api.cpp
index 88111afede..a075031ac9 100644
--- a/modules/openxr/openxr_api.cpp
+++ b/modules/openxr/openxr_api.cpp
@@ -51,7 +51,7 @@
#define XR_USE_GRAPHICS_API_VULKAN
#endif
#ifdef GLES3_ENABLED
-#ifdef ANDROID
+#ifdef ANDROID_ENABLED
#define XR_USE_GRAPHICS_API_OPENGL_ES
#include <EGL/egl.h>
#include <EGL/eglext.h>
@@ -59,14 +59,13 @@
#include <GLES3/gl3ext.h>
#else
#define XR_USE_GRAPHICS_API_OPENGL
-#endif // ANDROID
+#endif // ANDROID_ENABLED
#ifdef X11_ENABLED
#include OPENGL_INCLUDE_H
#define GL_GLEXT_PROTOTYPES 1
#define GL3_PROTOTYPES 1
-#include <GL/gl.h>
-#include <GL/glext.h>
-#include <GL/glx.h>
+#include "thirdparty/glad/glad/gl.h"
+#include "thirdparty/glad/glad/glx.h"
#include <X11/Xlib.h>
#endif // X11_ENABLED
#endif // GLES_ENABLED
@@ -209,17 +208,79 @@ bool OpenXRAPI::is_extension_supported(const String &p_extension) const {
return false;
}
-bool OpenXRAPI::is_path_supported(const String &p_path) {
- // This checks with extensions whether a path is *unsupported* and returns false if this is so.
- // This allows us to filter out paths that are only available if related extensions are supported.
- // WARNING: This method will return true for unknown/mistyped paths as we have no way to validate those.
+bool OpenXRAPI::is_extension_enabled(const String &p_extension) const {
+ CharString extension = p_extension.ascii();
- for (OpenXRExtensionWrapper *wrapper : registered_extension_wrappers) {
- if (!wrapper->is_path_supported(p_path)) {
- return false;
+ for (int i = 0; i < enabled_extensions.size(); i++) {
+ if (strcmp(enabled_extensions[i].ptr(), extension.ptr()) == 0) {
+ return true;
}
}
+ return false;
+}
+
+bool OpenXRAPI::is_top_level_path_supported(const String &p_toplevel_path) {
+ String required_extension = OpenXRInteractionProfileMetaData::get_singleton()->get_top_level_extension(p_toplevel_path);
+
+ // If unsupported is returned we likely have a misspelled interaction profile path in our action map. Always output that as an error.
+ ERR_FAIL_COND_V_MSG(required_extension == XR_PATH_UNSUPPORTED_NAME, false, "OpenXR: Unsupported interaction profile " + p_toplevel_path);
+
+ if (required_extension == "") {
+ // no extension needed, core top level are always "supported", they just won't be used if not really supported
+ return true;
+ }
+
+ if (!is_extension_enabled(required_extension)) {
+ // It is very likely we have top level paths for which the extension is not available so don't flood the logs with unnecessary spam.
+ print_verbose("OpenXR: Top level path " + p_toplevel_path + " requires extension " + required_extension);
+ return false;
+ }
+
+ return true;
+}
+
+bool OpenXRAPI::is_interaction_profile_supported(const String &p_ip_path) {
+ String required_extension = OpenXRInteractionProfileMetaData::get_singleton()->get_interaction_profile_extension(p_ip_path);
+
+ // If unsupported is returned we likely have a misspelled interaction profile path in our action map. Always output that as an error.
+ ERR_FAIL_COND_V_MSG(required_extension == XR_PATH_UNSUPPORTED_NAME, false, "OpenXR: Unsupported interaction profile " + p_ip_path);
+
+ if (required_extension == "") {
+ // no extension needed, core interaction profiles are always "supported", they just won't be used if not really supported
+ return true;
+ }
+
+ if (!is_extension_enabled(required_extension)) {
+ // It is very likely we have interaction profiles for which the extension is not available so don't flood the logs with unnecessary spam.
+ print_verbose("OpenXR: Interaction profile " + p_ip_path + " requires extension " + required_extension);
+ return false;
+ }
+
+ return true;
+}
+
+bool OpenXRAPI::interaction_profile_supports_io_path(const String &p_ip_path, const String &p_io_path) {
+ if (!is_interaction_profile_supported(p_ip_path)) {
+ return false;
+ }
+
+ const OpenXRInteractionProfileMetaData::IOPath *io_path = OpenXRInteractionProfileMetaData::get_singleton()->get_io_path(p_ip_path, p_io_path);
+
+ // If the io_path is not part of our meta data we've likely got a misspelled name or a bad action map, report
+ ERR_FAIL_NULL_V_MSG(io_path, false, "OpenXR: Unsupported io path " + String(p_ip_path) + String(p_io_path));
+
+ if (io_path->openxr_extension_name == "") {
+ // no extension needed, core io paths are always "supported", they just won't be used if not really supported
+ return true;
+ }
+
+ if (!is_extension_enabled(io_path->openxr_extension_name)) {
+ // It is very likely we have io paths for which the extension is not available so don't flood the logs with unnecessary spam.
+ print_verbose("OpenXR: IO path " + String(p_ip_path) + String(p_io_path) + " requires extension " + io_path->openxr_extension_name);
+ return false;
+ }
+
return true;
}
@@ -284,6 +345,7 @@ bool OpenXRAPI::create_instance() {
Vector<const char *> extension_ptrs;
for (int i = 0; i < enabled_extensions.size(); i++) {
+ print_verbose(String("OpenXR: Enabling extension ") + String(enabled_extensions[i]));
extension_ptrs.push_back(enabled_extensions[i].get_data());
}
@@ -299,9 +361,17 @@ bool OpenXRAPI::create_instance() {
XR_CURRENT_API_VERSION // apiVersion
};
+ void *next_pointer = nullptr;
+ for (OpenXRExtensionWrapper *wrapper : registered_extension_wrappers) {
+ void *np = wrapper->set_instance_create_info_and_get_next_pointer(next_pointer);
+ if (np != nullptr) {
+ next_pointer = np;
+ }
+ }
+
XrInstanceCreateInfo instance_create_info = {
XR_TYPE_INSTANCE_CREATE_INFO, // type
- nullptr, // next
+ next_pointer, // next
0, // createFlags
application_info, // applicationInfo
0, // enabledApiLayerCount, need to find out if we need support for this?
@@ -733,9 +803,10 @@ bool OpenXRAPI::create_swapchains() {
ERR_FAIL_NULL_V_MSG(projection_views, false, "OpenXR Couldn't allocate memory for projection views");
// We create our depth swapchain if:
+ // - we've enabled submitting depth buffer
// - we support our depth layer extension
// - we have our spacewarp extension (not yet implemented)
- if (OpenXRCompositionLayerDepthExtension::get_singleton()->is_available()) {
+ if (submit_depth_buffer && OpenXRCompositionLayerDepthExtension::get_singleton()->is_available()) {
// Build a vector with swapchain formats we want to use, from best fit to worst
Vector<int64_t> usable_swapchain_formats;
int64_t swapchain_format_to_use = 0;
@@ -783,13 +854,13 @@ bool OpenXRAPI::create_swapchains() {
projection_views[i].subImage.imageRect.extent.width = recommended_size.width;
projection_views[i].subImage.imageRect.extent.height = recommended_size.height;
- if (OpenXRCompositionLayerDepthExtension::get_singleton()->is_available() && depth_views) {
+ if (submit_depth_buffer && OpenXRCompositionLayerDepthExtension::get_singleton()->is_available() && depth_views) {
projection_views[i].next = &depth_views[i];
depth_views[i].type = XR_TYPE_COMPOSITION_LAYER_DEPTH_INFO_KHR;
depth_views[i].next = nullptr;
depth_views[i].subImage.swapchain = swapchains[OPENXR_SWAPCHAIN_DEPTH].swapchain;
- depth_views[i].subImage.imageArrayIndex = 0;
+ depth_views[i].subImage.imageArrayIndex = i;
depth_views[i].subImage.imageRect.offset.x = 0;
depth_views[i].subImage.imageRect.offset.y = 0;
depth_views[i].subImage.imageRect.extent.width = recommended_size.width;
@@ -1059,6 +1130,30 @@ bool OpenXRAPI::on_state_exiting() {
return true;
}
+void OpenXRAPI::set_form_factor(XrFormFactor p_form_factor) {
+ ERR_FAIL_COND(is_initialized());
+
+ form_factor = p_form_factor;
+}
+
+void OpenXRAPI::set_view_configuration(XrViewConfigurationType p_view_configuration) {
+ ERR_FAIL_COND(is_initialized());
+
+ view_configuration = p_view_configuration;
+}
+
+void OpenXRAPI::set_reference_space(XrReferenceSpaceType p_reference_space) {
+ ERR_FAIL_COND(is_initialized());
+
+ reference_space = p_reference_space;
+}
+
+void OpenXRAPI::set_submit_depth_buffer(bool p_submit_depth_buffer) {
+ ERR_FAIL_COND(is_initialized());
+
+ submit_depth_buffer = p_submit_depth_buffer;
+}
+
bool OpenXRAPI::is_initialized() {
return (instance != XR_NULL_HANDLE);
}
@@ -1677,7 +1772,7 @@ RID OpenXRAPI::get_color_texture() {
}
RID OpenXRAPI::get_depth_texture() {
- if (swapchains[OPENXR_SWAPCHAIN_DEPTH].image_acquired) {
+ if (submit_depth_buffer && swapchains[OPENXR_SWAPCHAIN_DEPTH].image_acquired) {
return graphics_extension->get_texture(swapchains[OPENXR_SWAPCHAIN_DEPTH].swapchain_graphics_data, swapchains[OPENXR_SWAPCHAIN_DEPTH].image_index);
} else {
return RID();
@@ -1855,6 +1950,8 @@ OpenXRAPI::OpenXRAPI() {
default:
break;
}
+
+ submit_depth_buffer = GLOBAL_GET("xr/openxr/submit_depth_buffer");
}
// reset a few things that can't be done in our class definition
@@ -2307,7 +2404,7 @@ XrPath OpenXRAPI::get_interaction_profile_path(RID p_interaction_profile) {
}
RID OpenXRAPI::interaction_profile_create(const String p_name) {
- if (!is_path_supported(p_name)) {
+ if (!is_interaction_profile_supported(p_name)) {
// The extension enabling this path must not be active, we will silently skip this interaction profile
return RID();
}
@@ -2348,14 +2445,13 @@ void OpenXRAPI::interaction_profile_clear_bindings(RID p_interaction_profile) {
}
bool OpenXRAPI::interaction_profile_add_binding(RID p_interaction_profile, RID p_action, const String p_path) {
- if (!is_path_supported(p_path)) {
- // The extension enabling this path must not be active, we will silently skip this binding
- return false;
- }
-
InteractionProfile *ip = interaction_profile_owner.get_or_null(p_interaction_profile);
ERR_FAIL_NULL_V(ip, false);
+ if (!interaction_profile_supports_io_path(ip->name, p_path)) {
+ return false;
+ }
+
XrActionSuggestedBinding binding;
Action *action = action_owner.get_or_null(p_action);
diff --git a/modules/openxr/openxr_api.h b/modules/openxr/openxr_api.h
index 5dce749351..806e859da0 100644
--- a/modules/openxr/openxr_api.h
+++ b/modules/openxr/openxr_api.h
@@ -104,6 +104,7 @@ private:
XrViewConfigurationType view_configuration = XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO;
XrReferenceSpaceType reference_space = XR_REFERENCE_SPACE_TYPE_STAGE;
// XrEnvironmentBlendMode environment_blend_mode = XR_ENVIRONMENT_BLEND_MODE_OPAQUE;
+ bool submit_depth_buffer = false; // if set to true we submit depth buffers to OpenXR if a suitable extension is enabled.
// state
XrInstance instance = XR_NULL_HANDLE;
@@ -149,6 +150,7 @@ private:
bool load_layer_properties();
bool load_supported_extensions();
bool is_extension_supported(const String &p_extension) const;
+ bool is_extension_enabled(const String &p_extension) const;
bool openxr_loader_init();
bool resolve_instance_openxr_symbols();
@@ -300,7 +302,9 @@ public:
void parse_velocities(const XrSpaceVelocity &p_velocity, Vector3 &r_linear_velocity, Vector3 &r_angular_velocity);
bool xr_result(XrResult result, const char *format, Array args = Array()) const;
- bool is_path_supported(const String &p_path);
+ bool is_top_level_path_supported(const String &p_toplevel_path);
+ bool is_interaction_profile_supported(const String &p_ip_path);
+ bool interaction_profile_supports_io_path(const String &p_ip_path, const String &p_io_path);
static bool openxr_is_enabled(bool p_check_run_in_editor = true);
static OpenXRAPI *get_singleton();
@@ -312,6 +316,18 @@ public:
void set_xr_interface(OpenXRInterface *p_xr_interface);
void register_extension_wrapper(OpenXRExtensionWrapper *p_extension_wrapper);
+ void set_form_factor(XrFormFactor p_form_factor);
+ XrFormFactor get_form_factor() const { return form_factor; }
+
+ void set_view_configuration(XrViewConfigurationType p_view_configuration);
+ XrViewConfigurationType get_view_configuration() const { return view_configuration; }
+
+ void set_reference_space(XrReferenceSpaceType p_reference_space);
+ XrReferenceSpaceType get_reference_space() const { return reference_space; }
+
+ void set_submit_depth_buffer(bool p_submit_depth_buffer);
+ bool get_submit_depth_buffer() const { return submit_depth_buffer; }
+
bool is_initialized();
bool is_running();
bool initialize(const String &p_rendering_driver);
diff --git a/modules/openxr/openxr_interface.cpp b/modules/openxr/openxr_interface.cpp
index 1db8f5e665..d6f7cd7b3e 100644
--- a/modules/openxr/openxr_interface.cpp
+++ b/modules/openxr/openxr_interface.cpp
@@ -45,7 +45,7 @@ void OpenXRInterface::_bind_methods() {
// Display refresh rate
ClassDB::bind_method(D_METHOD("get_display_refresh_rate"), &OpenXRInterface::get_display_refresh_rate);
ClassDB::bind_method(D_METHOD("set_display_refresh_rate", "refresh_rate"), &OpenXRInterface::set_display_refresh_rate);
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "display_refresh_rate"), "set_display_refresh_rate", "get_display_refresh_rate");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "display_refresh_rate"), "set_display_refresh_rate", "get_display_refresh_rate");
ClassDB::bind_method(D_METHOD("get_available_display_refresh_rates"), &OpenXRInterface::get_available_display_refresh_rates);
}
@@ -158,7 +158,7 @@ void OpenXRInterface::_load_action_map() {
for (int k = 0; k < toplevel_paths.size(); k++) {
// Only check for our tracker if our path is supported.
- if (openxr_api->is_path_supported(toplevel_paths[k])) {
+ if (openxr_api->is_top_level_path_supported(toplevel_paths[k])) {
Tracker *tracker = find_tracker(toplevel_paths[k], true);
if (tracker) {
trackers_for_action.push_back(tracker);
@@ -345,7 +345,7 @@ OpenXRInterface::Tracker *OpenXRInterface::find_tracker(const String &p_tracker_
return nullptr;
}
- ERR_FAIL_COND_V(!openxr_api->is_path_supported(p_tracker_name), nullptr);
+ ERR_FAIL_COND_V(!openxr_api->is_top_level_path_supported(p_tracker_name), nullptr);
// Create our RID
RID tracker_rid = openxr_api->tracker_create(p_tracker_name);
@@ -666,7 +666,7 @@ Transform3D OpenXRInterface::get_camera_transform() {
Transform3D OpenXRInterface::get_transform_for_view(uint32_t p_view, const Transform3D &p_cam_transform) {
XRServer *xr_server = XRServer::get_singleton();
ERR_FAIL_NULL_V(xr_server, Transform3D());
- ERR_FAIL_INDEX_V_MSG(p_view, get_view_count(), Transform3D(), "View index outside bounds.");
+ ERR_FAIL_UNSIGNED_INDEX_V_MSG(p_view, get_view_count(), Transform3D(), "View index outside bounds.");
Transform3D t;
if (openxr_api && openxr_api->get_view_transform(p_view, t)) {
@@ -686,7 +686,7 @@ Transform3D OpenXRInterface::get_transform_for_view(uint32_t p_view, const Trans
Projection OpenXRInterface::get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) {
Projection cm;
- ERR_FAIL_INDEX_V_MSG(p_view, get_view_count(), cm, "View index outside bounds.");
+ ERR_FAIL_UNSIGNED_INDEX_V_MSG(p_view, get_view_count(), cm, "View index outside bounds.");
if (openxr_api) {
if (openxr_api->get_view_projection(p_view, p_z_near, p_z_far, cm)) {
diff --git a/modules/openxr/register_types.cpp b/modules/openxr/register_types.cpp
index 5694fffe39..0835bbd642 100644
--- a/modules/openxr/register_types.cpp
+++ b/modules/openxr/register_types.cpp
@@ -37,9 +37,14 @@
#include "action_map/openxr_action_map.h"
#include "action_map/openxr_action_set.h"
#include "action_map/openxr_interaction_profile.h"
+#include "action_map/openxr_interaction_profile_meta_data.h"
#include "scene/openxr_hand.h"
+static OpenXRAPI *openxr_api = nullptr;
+static OpenXRInteractionProfileMetaData *openxr_interaction_profile_meta_data = nullptr;
+static Ref<OpenXRInterface> openxr_interface;
+
#ifdef TOOLS_ENABLED
#include "editor/editor_node.h"
@@ -49,6 +54,12 @@ static void _editor_init() {
if (OpenXRAPI::openxr_is_enabled(false)) {
// Only add our OpenXR action map editor if OpenXR is enabled for our project
+ if (openxr_interaction_profile_meta_data == nullptr) {
+ // If we didn't initialize our actionmap meta data at startup, we initialise it now.
+ openxr_interaction_profile_meta_data = memnew(OpenXRInteractionProfileMetaData);
+ ERR_FAIL_NULL(openxr_interaction_profile_meta_data);
+ }
+
OpenXREditorPlugin *openxr_plugin = memnew(OpenXREditorPlugin());
EditorNode::get_singleton()->add_editor_plugin(openxr_plugin);
}
@@ -56,14 +67,13 @@ static void _editor_init() {
#endif
-static OpenXRAPI *openxr_api = nullptr;
-static Ref<OpenXRInterface> openxr_interface;
-
void initialize_openxr_module(ModuleInitializationLevel p_level) {
if (p_level == MODULE_INITIALIZATION_LEVEL_SERVERS) {
// For now we create our openxr device here. If we merge it with openxr_interface we'll create that here soon.
if (OpenXRAPI::openxr_is_enabled()) {
+ openxr_interaction_profile_meta_data = memnew(OpenXRInteractionProfileMetaData);
+ ERR_FAIL_NULL(openxr_interaction_profile_meta_data);
openxr_api = memnew(OpenXRAPI);
ERR_FAIL_NULL(openxr_api);
@@ -81,6 +91,7 @@ void initialize_openxr_module(ModuleInitializationLevel p_level) {
GDREGISTER_CLASS(OpenXRAction);
GDREGISTER_CLASS(OpenXRActionSet);
GDREGISTER_CLASS(OpenXRActionMap);
+ GDREGISTER_CLASS(OpenXRInteractionProfileMetaData);
GDREGISTER_CLASS(OpenXRIPBinding);
GDREGISTER_CLASS(OpenXRInteractionProfile);
@@ -131,4 +142,9 @@ void uninitialize_openxr_module(ModuleInitializationLevel p_level) {
memdelete(openxr_api);
openxr_api = nullptr;
}
+
+ if (openxr_interaction_profile_meta_data) {
+ memdelete(openxr_interaction_profile_meta_data);
+ openxr_interaction_profile_meta_data = nullptr;
+ }
}
diff --git a/modules/raycast/SCsub b/modules/raycast/SCsub
index 20b05816e1..37c8a95905 100644
--- a/modules/raycast/SCsub
+++ b/modules/raycast/SCsub
@@ -67,11 +67,11 @@ if env["builtin_embree"]:
env_raycast.AppendUnique(CPPDEFINES=["NDEBUG"]) # No assert() even in debug builds.
if not env.msvc:
- if env["arch"] == "x86_64":
- env_raycast.Append(CPPFLAGS=["-msse2", "-mxsave"])
+ if env["arch"] in ["x86_64", "x86_32"]:
+ env_raycast.Append(CCFLAGS=["-msse2", "-mxsave"])
if env["platform"] == "windows":
- env_raycast.Append(CPPFLAGS=["-mstackrealign"])
+ env_raycast.Append(CCFLAGS=["-mstackrealign"])
if env["platform"] == "windows":
if env.msvc:
@@ -87,13 +87,20 @@ if env["builtin_embree"]:
env_thirdparty.disable_warnings()
env_thirdparty.add_source_files(thirdparty_obj, thirdparty_sources)
- if env["arch"] == "arm64" or env.msvc:
+ if env["arch"] != "x86_64" or env.msvc:
# Embree needs those, it will automatically use SSE2NEON in ARM
env_thirdparty.Append(CPPDEFINES=["__SSE2__", "__SSE__"])
+ if env["platform"] == "web":
+ env_thirdparty.Append(CXXFLAGS=["-msimd128"])
+
if not env.msvc:
+ # Flags synced with upstream gnu.cmake.
+ if env["arch"] == "arm64" and env["platform"] == "linuxbsd":
+ env_thirdparty.Append(CXXFLAGS=["-flax-vector-conversions"])
+
env_thirdparty.Append(
- CPPFLAGS=[
+ CXXFLAGS=[
"-fno-strict-overflow",
"-fno-delete-null-pointer-checks",
"-fwrapv",
diff --git a/modules/raycast/config.py b/modules/raycast/config.py
index 833ad50018..26329d813a 100644
--- a/modules/raycast/config.py
+++ b/modules/raycast/config.py
@@ -1,9 +1,11 @@
def can_build(env, platform):
- # Depends on Embree library, which only supports x86_64 and arm64.
- if platform == "windows":
- return env["arch"] == "x86_64" # TODO build for Windows on ARM
-
- return env["arch"] in ["x86_64", "arm64"]
+ # Supported architectures depend on the Embree library.
+ if env["arch"] in ["x86_64", "arm64", "wasm32"]:
+ return True
+ # x86_32 only seems supported on Windows for now.
+ if env["arch"] == "x86_32" and platform == "windows":
+ return True
+ return False
def configure(env):
diff --git a/modules/raycast/godot_update_embree.py b/modules/raycast/godot_update_embree.py
index e31d88b741..527e02f855 100644
--- a/modules/raycast/godot_update_embree.py
+++ b/modules/raycast/godot_update_embree.py
@@ -1,5 +1,7 @@
import glob, os, shutil, subprocess, re
+git_tag = "v3.13.5"
+
include_dirs = [
"common/tasking",
"kernels/bvh",
@@ -12,6 +14,7 @@ include_dirs = [
"common/lexers",
"common/simd",
"common/simd/arm",
+ "common/simd/wasm",
"include/embree3",
"kernels/subdiv",
"kernels/geometry",
@@ -76,6 +79,7 @@ if os.path.exists(dir_name):
subprocess.run(["git", "clone", "https://github.com/embree/embree.git", "embree-tmp"])
os.chdir("embree-tmp")
+subprocess.run(["git", "checkout", git_tag])
commit_hash = str(subprocess.check_output(["git", "rev-parse", "HEAD"], universal_newlines=True)).strip()
@@ -94,8 +98,7 @@ for f in all_files:
with open(os.path.join(dest_dir, "kernels/hash.h"), "w") as hash_file:
hash_file.write(
- f"""
-// Copyright 2009-2020 Intel Corporation
+ f"""// Copyright 2009-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
#define RTC_HASH "{commit_hash}"
@@ -104,8 +107,7 @@ with open(os.path.join(dest_dir, "kernels/hash.h"), "w") as hash_file:
with open(os.path.join(dest_dir, "kernels/config.h"), "w") as config_file:
config_file.write(
- """
-// Copyright 2009-2020 Intel Corporation
+ """// Copyright 2009-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
/* #undef EMBREE_RAY_MASK */
@@ -126,6 +128,7 @@ with open(os.path.join(dest_dir, "kernels/config.h"), "w") as config_file:
/* #undef EMBREE_COMPACT_POLYS */
#define EMBREE_CURVE_SELF_INTERSECTION_AVOIDANCE_FACTOR 2.0
+#define EMBREE_DISC_POINT_SELF_INTERSECTION_AVOIDANCE
#if defined(EMBREE_GEOMETRY_TRIANGLE)
#define IF_ENABLED_TRIS(x) x
@@ -192,8 +195,7 @@ with open("CMakeLists.txt", "r") as cmake_file:
with open(os.path.join(dest_dir, "include/embree3/rtcore_config.h"), "w") as config_file:
config_file.write(
- f"""
-// Copyright 2009-2021 Intel Corporation
+ f"""// Copyright 2009-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
#pragma once
@@ -209,14 +211,16 @@ with open(os.path.join(dest_dir, "include/embree3/rtcore_config.h"), "w") as con
#define EMBREE_MIN_WIDTH 0
#define RTC_MIN_WIDTH EMBREE_MIN_WIDTH
-#define EMBREE_STATIC_LIB
-/* #undef EMBREE_API_NAMESPACE */
+#if !defined(EMBREE_STATIC_LIB)
+# define EMBREE_STATIC_LIB
+#endif
+/* #undef EMBREE_API_NAMESPACE*/
#if defined(EMBREE_API_NAMESPACE)
# define RTC_NAMESPACE
-# define RTC_NAMESPACE_BEGIN namespace {{
+# define RTC_NAMESPACE_BEGIN namespace {{
# define RTC_NAMESPACE_END }}
-# define RTC_NAMESPACE_USE using namespace ;
+# define RTC_NAMESPACE_USE using namespace;
# define RTC_API_EXTERN_C
# undef EMBREE_API_NAMESPACE
#else
diff --git a/modules/regex/regex.cpp b/modules/regex/regex.cpp
index c808211d68..6f02d20c25 100644
--- a/modules/regex/regex.cpp
+++ b/modules/regex/regex.cpp
@@ -50,8 +50,7 @@ int RegExMatch::_find(const Variant &p_name) const {
return -1;
}
return i;
-
- } else if (p_name.get_type() == Variant::STRING) {
+ } else if (p_name.get_type() == Variant::STRING || p_name.get_type() == Variant::STRING_NAME) {
HashMap<String, int>::ConstIterator found = names.find((String)p_name);
if (found) {
return found->value;
diff --git a/modules/register_module_types.h b/modules/register_module_types.h
index cfd1b355d4..706e641735 100644
--- a/modules/register_module_types.h
+++ b/modules/register_module_types.h
@@ -31,13 +31,13 @@
#ifndef REGISTER_MODULE_TYPES_H
#define REGISTER_MODULE_TYPES_H
-#include "core/extension/gdnative_interface.h"
+#include "core/extension/gdextension_interface.h"
enum ModuleInitializationLevel {
- MODULE_INITIALIZATION_LEVEL_CORE = GDNATIVE_INITIALIZATION_CORE,
- MODULE_INITIALIZATION_LEVEL_SERVERS = GDNATIVE_INITIALIZATION_SERVERS,
- MODULE_INITIALIZATION_LEVEL_SCENE = GDNATIVE_INITIALIZATION_SCENE,
- MODULE_INITIALIZATION_LEVEL_EDITOR = GDNATIVE_INITIALIZATION_EDITOR
+ MODULE_INITIALIZATION_LEVEL_CORE = GDEXTENSION_INITIALIZATION_CORE,
+ MODULE_INITIALIZATION_LEVEL_SERVERS = GDEXTENSION_INITIALIZATION_SERVERS,
+ MODULE_INITIALIZATION_LEVEL_SCENE = GDEXTENSION_INITIALIZATION_SCENE,
+ MODULE_INITIALIZATION_LEVEL_EDITOR = GDEXTENSION_INITIALIZATION_EDITOR
};
void initialize_modules(ModuleInitializationLevel p_level);
diff --git a/modules/svg/image_loader_svg.cpp b/modules/svg/image_loader_svg.cpp
index b8c412a201..b194e7cb3f 100644
--- a/modules/svg/image_loader_svg.cpp
+++ b/modules/svg/image_loader_svg.cpp
@@ -67,27 +67,30 @@ void ImageLoaderSVG::_replace_color_property(const HashMap<Color, Color> &p_colo
}
}
-void ImageLoaderSVG::create_image_from_string(Ref<Image> p_image, String p_string, float p_scale, bool p_upsample, const HashMap<Color, Color> &p_color_map) {
- ERR_FAIL_COND(Math::is_zero_approx(p_scale));
-
- if (p_color_map.size()) {
- _replace_color_property(p_color_map, "stop-color=\"", p_string);
- _replace_color_property(p_color_map, "fill=\"", p_string);
- _replace_color_property(p_color_map, "stroke=\"", p_string);
- }
+Error ImageLoaderSVG::create_image_from_utf8_buffer(Ref<Image> p_image, const PackedByteArray &p_buffer, float p_scale, bool p_upsample) {
+ ERR_FAIL_COND_V_MSG(Math::is_zero_approx(p_scale), ERR_INVALID_PARAMETER, "ImageLoaderSVG: Can't load SVG with a scale of 0.");
std::unique_ptr<tvg::Picture> picture = tvg::Picture::gen();
- PackedByteArray bytes = p_string.to_utf8_buffer();
- tvg::Result result = picture->load((const char *)bytes.ptr(), bytes.size(), "svg", true);
+ tvg::Result result = picture->load((const char *)p_buffer.ptr(), p_buffer.size(), "svg", true);
if (result != tvg::Result::Success) {
- return;
+ return ERR_INVALID_DATA;
}
float fw, fh;
picture->size(&fw, &fh);
- uint32_t width = MIN(round(fw * p_scale), 16 * 1024);
- uint32_t height = MIN(round(fh * p_scale), 16 * 1024);
+ uint32_t width = round(fw * p_scale);
+ uint32_t height = round(fh * p_scale);
+
+ const uint32_t max_dimension = 16384;
+ if (width > max_dimension || height > max_dimension) {
+ WARN_PRINT(vformat(
+ String::utf8("ImageLoaderSVG: Target canvas dimensions %d×%d (with scale %.2f) exceed the max supported dimensions %d×%d. The target canvas will be scaled down."),
+ width, height, p_scale, max_dimension, max_dimension));
+ width = MIN(width, max_dimension);
+ height = MIN(height, max_dimension);
+ }
+
picture->size(width, height);
std::unique_ptr<tvg::SwCanvas> sw_canvas = tvg::SwCanvas::gen();
@@ -97,25 +100,25 @@ void ImageLoaderSVG::create_image_from_string(Ref<Image> p_image, String p_strin
tvg::Result res = sw_canvas->target(buffer, width, width, height, tvg::SwCanvas::ARGB8888_STRAIGHT);
if (res != tvg::Result::Success) {
memfree(buffer);
- ERR_FAIL_MSG("ImageLoaderSVG can't create image.");
+ ERR_FAIL_V_MSG(FAILED, "ImageLoaderSVG: Couldn't set target on ThorVG canvas.");
}
res = sw_canvas->push(std::move(picture));
if (res != tvg::Result::Success) {
memfree(buffer);
- ERR_FAIL_MSG("ImageLoaderSVG can't create image.");
+ ERR_FAIL_V_MSG(FAILED, "ImageLoaderSVG: Couldn't insert ThorVG picture on canvas.");
}
res = sw_canvas->draw();
if (res != tvg::Result::Success) {
memfree(buffer);
- ERR_FAIL_MSG("ImageLoaderSVG can't create image.");
+ ERR_FAIL_V_MSG(FAILED, "ImageLoaderSVG: Couldn't draw ThorVG pictures on canvas.");
}
res = sw_canvas->sync();
if (res != tvg::Result::Success) {
memfree(buffer);
- ERR_FAIL_MSG("ImageLoaderSVG can't create image.");
+ ERR_FAIL_V_MSG(FAILED, "ImageLoaderSVG: Couldn't sync ThorVG canvas.");
}
Vector<uint8_t> image;
@@ -136,6 +139,19 @@ void ImageLoaderSVG::create_image_from_string(Ref<Image> p_image, String p_strin
memfree(buffer);
p_image->set_data(width, height, false, Image::FORMAT_RGBA8, image);
+ return OK;
+}
+
+Error ImageLoaderSVG::create_image_from_string(Ref<Image> p_image, String p_string, float p_scale, bool p_upsample, const HashMap<Color, Color> &p_color_map) {
+ if (p_color_map.size()) {
+ _replace_color_property(p_color_map, "stop-color=\"", p_string);
+ _replace_color_property(p_color_map, "fill=\"", p_string);
+ _replace_color_property(p_color_map, "stroke=\"", p_string);
+ }
+
+ PackedByteArray bytes = p_string.to_utf8_buffer();
+
+ return create_image_from_utf8_buffer(p_image, bytes, p_scale, p_upsample);
}
void ImageLoaderSVG::get_recognized_extensions(List<String> *p_extensions) const {
@@ -145,13 +161,19 @@ void ImageLoaderSVG::get_recognized_extensions(List<String> *p_extensions) const
Error ImageLoaderSVG::load_image(Ref<Image> p_image, Ref<FileAccess> p_fileaccess, BitField<ImageFormatLoader::LoaderFlags> p_flags, float p_scale) {
String svg = p_fileaccess->get_as_utf8_string();
+ Error err;
if (p_flags & FLAG_CONVERT_COLORS) {
- create_image_from_string(p_image, svg, p_scale, false, forced_color_map);
+ err = create_image_from_string(p_image, svg, p_scale, false, forced_color_map);
} else {
- create_image_from_string(p_image, svg, p_scale, false, HashMap<Color, Color>());
+ err = create_image_from_string(p_image, svg, p_scale, false, HashMap<Color, Color>());
+ }
+
+ if (err != OK) {
+ return err;
+ } else if (p_image->is_empty()) {
+ return ERR_INVALID_DATA;
}
- ERR_FAIL_COND_V(p_image->is_empty(), FAILED);
if (p_flags & FLAG_FORCE_LINEAR) {
p_image->srgb_to_linear();
}
diff --git a/modules/svg/image_loader_svg.h b/modules/svg/image_loader_svg.h
index b0b0963c15..d955a04f1e 100644
--- a/modules/svg/image_loader_svg.h
+++ b/modules/svg/image_loader_svg.h
@@ -41,7 +41,8 @@ class ImageLoaderSVG : public ImageFormatLoader {
public:
static void set_forced_color_map(const HashMap<Color, Color> &p_color_map);
- void create_image_from_string(Ref<Image> p_image, String p_string, float p_scale, bool p_upsample, const HashMap<Color, Color> &p_color_map);
+ Error create_image_from_utf8_buffer(Ref<Image> p_image, const PackedByteArray &p_buffer, float p_scale, bool p_upsample);
+ Error create_image_from_string(Ref<Image> p_image, String p_string, float p_scale, bool p_upsample, const HashMap<Color, Color> &p_color_map);
virtual Error load_image(Ref<Image> p_image, Ref<FileAccess> p_fileaccess, BitField<ImageFormatLoader::LoaderFlags> p_flags, float p_scale) override;
virtual void get_recognized_extensions(List<String> *p_extensions) const override;
diff --git a/modules/text_server_adv/SCsub b/modules/text_server_adv/SCsub
index bd208a8429..4a9c7b3567 100644
--- a/modules/text_server_adv/SCsub
+++ b/modules/text_server_adv/SCsub
@@ -39,6 +39,9 @@ thirdparty_obj = []
freetype_enabled = "freetype" in env.module_list
msdfgen_enabled = "msdfgen" in env.module_list
+if "svg" in env.module_list:
+ env_text_server_adv.Prepend(CPPPATH=["#thirdparty/thorvg/inc", "#thirdparty/thorvg/src/lib"])
+
if env["builtin_harfbuzz"]:
env_harfbuzz = env_modules.Clone()
env_harfbuzz.disable_warnings()
@@ -220,9 +223,6 @@ if env["builtin_graphite"] and freetype_enabled and env["graphite"]:
]
)
- if env.msvc: # Not our business to fix.
- env_graphite.Append(CCFLAGS=["-D_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS"])
-
lib = env_graphite.add_library("graphite_builtin", thirdparty_sources)
thirdparty_obj += lib
diff --git a/modules/text_server_adv/gdextension_build/SConstruct b/modules/text_server_adv/gdextension_build/SConstruct
index 65b41e46ce..4a363fdd7a 100644
--- a/modules/text_server_adv/gdextension_build/SConstruct
+++ b/modules/text_server_adv/gdextension_build/SConstruct
@@ -23,6 +23,7 @@ opts.Add(BoolVariable("brotli_enabled", "Use Brotli library", True))
opts.Add(BoolVariable("freetype_enabled", "Use FreeType library", True))
opts.Add(BoolVariable("msdfgen_enabled", "Use MSDFgen library (require FreeType)", True))
opts.Add(BoolVariable("graphite_enabled", "Use Graphite library (require FreeType)", True))
+opts.Add(BoolVariable("thorvg_enabled", "Use ThorVG library (require FreeType)", True))
opts.Add(BoolVariable("static_icu_data", "Use built-in ICU data", True))
opts.Add(BoolVariable("verbose", "Enable verbose output for the compilation", False))
@@ -34,6 +35,79 @@ if not env["verbose"]:
if env["platform"] == "windows" and not env["use_mingw"]:
env.AppendUnique(CCFLAGS=["/utf-8"]) # Force to use Unicode encoding.
+# ThorVG
+if env["thorvg_enabled"] and env["freetype_enabled"]:
+ env_tvg = env.Clone()
+ env_tvg.disable_warnings()
+
+ thirdparty_tvg_dir = "../../../thirdparty/thorvg/"
+ thirdparty_tvg_sources = [
+ "src/lib/sw_engine/tvgSwFill.cpp",
+ "src/lib/sw_engine/tvgSwImage.cpp",
+ "src/lib/sw_engine/tvgSwMath.cpp",
+ "src/lib/sw_engine/tvgSwMemPool.cpp",
+ "src/lib/sw_engine/tvgSwRaster.cpp",
+ "src/lib/sw_engine/tvgSwRenderer.cpp",
+ "src/lib/sw_engine/tvgSwRle.cpp",
+ "src/lib/sw_engine/tvgSwShape.cpp",
+ "src/lib/sw_engine/tvgSwStroke.cpp",
+ "src/lib/tvgAccessor.cpp",
+ "src/lib/tvgBezier.cpp",
+ "src/lib/tvgCanvas.cpp",
+ "src/lib/tvgFill.cpp",
+ "src/lib/tvgGlCanvas.cpp",
+ "src/lib/tvgInitializer.cpp",
+ "src/lib/tvgLinearGradient.cpp",
+ "src/lib/tvgLoader.cpp",
+ "src/lib/tvgLzw.cpp",
+ "src/lib/tvgPaint.cpp",
+ "src/lib/tvgPicture.cpp",
+ "src/lib/tvgRadialGradient.cpp",
+ "src/lib/tvgRender.cpp",
+ "src/lib/tvgSaver.cpp",
+ "src/lib/tvgScene.cpp",
+ "src/lib/tvgShape.cpp",
+ "src/lib/tvgSwCanvas.cpp",
+ "src/lib/tvgTaskScheduler.cpp",
+ "src/loaders/external_png/tvgPngLoader.cpp",
+ "src/loaders/jpg/tvgJpgd.cpp",
+ "src/loaders/jpg/tvgJpgLoader.cpp",
+ "src/loaders/raw/tvgRawLoader.cpp",
+ "src/loaders/svg/tvgSvgCssStyle.cpp",
+ "src/loaders/svg/tvgSvgLoader.cpp",
+ "src/loaders/svg/tvgSvgPath.cpp",
+ "src/loaders/svg/tvgSvgSceneBuilder.cpp",
+ "src/loaders/svg/tvgSvgUtil.cpp",
+ "src/loaders/svg/tvgXmlParser.cpp",
+ "src/loaders/tvg/tvgTvgBinInterpreter.cpp",
+ "src/loaders/tvg/tvgTvgLoader.cpp",
+ "src/savers/tvg/tvgTvgSaver.cpp",
+ ]
+ thirdparty_tvg_sources = [thirdparty_tvg_dir + file for file in thirdparty_tvg_sources]
+
+ env_tvg.Append(
+ CPPPATH=[
+ "../../../thirdparty/thorvg/inc",
+ "../../../thirdparty/thorvg/src/lib",
+ "../../../thirdparty/thorvg/src/lib/sw_engine",
+ "../../../thirdparty/thorvg/src/loaders/external_png",
+ "../../../thirdparty/thorvg/src/loaders/jpg",
+ "../../../thirdparty/thorvg/src/loaders/raw",
+ "../../../thirdparty/thorvg/src/loaders/svg",
+ "../../../thirdparty/thorvg/src/loaders/tvg",
+ "../../../thirdparty/thorvg/src/savers/tvg",
+ "../../../thirdparty/libpng",
+ ]
+ )
+ env.Append(CPPPATH=["../../../thirdparty/thorvg/inc", "../../../thirdparty/thorvg/src/lib"])
+ env.Append(CPPDEFINES=["MODULE_SVG_ENABLED"])
+
+ lib = env_tvg.Library(
+ f'tvg_builtin{env["suffix"]}{env["LIBSUFFIX"]}',
+ thirdparty_tvg_sources,
+ )
+ env.Append(LIBS=[lib])
+
# MSDFGEN
if env["msdfgen_enabled"] and env["freetype_enabled"]:
env_msdfgen = env.Clone()
diff --git a/modules/text_server_adv/register_types.cpp b/modules/text_server_adv/register_types.cpp
index 6a26584506..64373e9f2b 100644
--- a/modules/text_server_adv/register_types.cpp
+++ b/modules/text_server_adv/register_types.cpp
@@ -62,7 +62,7 @@ using namespace godot;
extern "C" {
-GDNativeBool GDN_EXPORT textserver_advanced_init(const GDNativeInterface *p_interface, const GDNativeExtensionClassLibraryPtr p_library, GDNativeInitialization *r_initialization) {
+GDExtensionBool GDN_EXPORT textserver_advanced_init(const GDExtensionInterface *p_interface, const GDExtensionClassLibraryPtr p_library, GDExtensionInitialization *r_initialization) {
GDExtensionBinding::InitObject init_obj(p_interface, p_library, r_initialization);
init_obj.register_initializer(&initialize_text_server_adv_module);
diff --git a/modules/text_server_adv/text_server_adv.cpp b/modules/text_server_adv/text_server_adv.cpp
index 155da3c67b..f3e7ae9b83 100644
--- a/modules/text_server_adv/text_server_adv.cpp
+++ b/modules/text_server_adv/text_server_adv.cpp
@@ -34,6 +34,7 @@
// Headers for building as GDExtension plug-in.
#include <godot_cpp/classes/file_access.hpp>
+#include <godot_cpp/classes/os.hpp>
#include <godot_cpp/classes/project_settings.hpp>
#include <godot_cpp/classes/rendering_server.hpp>
#include <godot_cpp/classes/translation_server.hpp>
@@ -41,6 +42,8 @@
using namespace godot;
+#define GLOBAL_GET(m_var) ProjectSettings::get_singleton()->get(m_var)
+
#else
// Headers for building as built-in module.
@@ -50,7 +53,7 @@ using namespace godot;
#include "core/string/print_string.h"
#include "core/string/translation.h"
-#include "modules/modules_enabled.gen.h" // For freetype, msdfgen.
+#include "modules/modules_enabled.gen.h" // For freetype, msdfgen, svg.
#endif
@@ -69,6 +72,10 @@ using namespace godot;
#include "msdfgen.h"
#endif
+#ifdef MODULE_SVG_ENABLED
+#include "thorvg_svg_in_ot.h"
+#endif
+
/*************************************************************************/
/* bmp_font_t HarfBuzz Bitmap font interface */
/*************************************************************************/
@@ -1346,6 +1353,9 @@ _FORCE_INLINE_ bool TextServerAdvanced::_ensure_cache_for_size(FontAdvanced *p_f
memdelete(fd);
ERR_FAIL_V_MSG(false, "FreeType: Error initializing library: '" + String(FT_Error_String(error)) + "'.");
}
+#ifdef MODULE_SVG_ENABLED
+ FT_Property_Set(ft_library, "ot-svg", "svg-hooks", get_tvg_svg_in_ot_hooks());
+#endif
}
memset(&fd->stream, 0, sizeof(FT_StreamRec));
@@ -1428,11 +1438,13 @@ _FORCE_INLINE_ bool TextServerAdvanced::_ensure_cache_for_size(FontAdvanced *p_f
if (fd->face->style_name != nullptr) {
p_font_data->style_name = String::utf8((const char *)fd->face->style_name);
}
+ p_font_data->weight = _font_get_weight_by_name(p_font_data->style_name.to_lower());
+ p_font_data->stretch = _font_get_stretch_by_name(p_font_data->style_name.to_lower());
p_font_data->style_flags = 0;
- if (fd->face->style_flags & FT_STYLE_FLAG_BOLD) {
+ if ((fd->face->style_flags & FT_STYLE_FLAG_BOLD) || p_font_data->weight >= 700) {
p_font_data->style_flags.set_flag(FONT_BOLD);
}
- if (fd->face->style_flags & FT_STYLE_FLAG_ITALIC) {
+ if ((fd->face->style_flags & FT_STYLE_FLAG_ITALIC) || _is_ital_style(p_font_data->style_name.to_lower())) {
p_font_data->style_flags.set_flag(FONT_ITALIC);
}
if (fd->face->face_flags & FT_FACE_FLAG_FIXED_WIDTH) {
@@ -1888,6 +1900,9 @@ int64_t TextServerAdvanced::_font_get_face_count(const RID &p_font_rid) const {
if (!ft_library) {
error = FT_Init_FreeType(&ft_library);
ERR_FAIL_COND_V_MSG(error != 0, false, "FreeType: Error initializing library: '" + String(FT_Error_String(error)) + "'.");
+#ifdef MODULE_SVG_ENABLED
+ FT_Property_Set(ft_library, "ot-svg", "svg-hooks", get_tvg_svg_in_ot_hooks());
+#endif
}
FT_StreamRec stream;
@@ -1955,6 +1970,46 @@ String TextServerAdvanced::_font_get_style_name(const RID &p_font_rid) const {
return fd->style_name;
}
+void TextServerAdvanced::_font_set_weight(const RID &p_font_rid, int64_t p_weight) {
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ ERR_FAIL_COND(!fd);
+
+ MutexLock lock(fd->mutex);
+ Vector2i size = _get_size(fd, 16);
+ ERR_FAIL_COND(!_ensure_cache_for_size(fd, size));
+ fd->weight = CLAMP(p_weight, 100, 999);
+}
+
+int64_t TextServerAdvanced::_font_get_weight(const RID &p_font_rid) const {
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ ERR_FAIL_COND_V(!fd, 400);
+
+ MutexLock lock(fd->mutex);
+ Vector2i size = _get_size(fd, 16);
+ ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), 400);
+ return fd->weight;
+}
+
+void TextServerAdvanced::_font_set_stretch(const RID &p_font_rid, int64_t p_stretch) {
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ ERR_FAIL_COND(!fd);
+
+ MutexLock lock(fd->mutex);
+ Vector2i size = _get_size(fd, 16);
+ ERR_FAIL_COND(!_ensure_cache_for_size(fd, size));
+ fd->stretch = CLAMP(p_stretch, 50, 200);
+}
+
+int64_t TextServerAdvanced::_font_get_stretch(const RID &p_font_rid) const {
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ ERR_FAIL_COND_V(!fd, 100);
+
+ MutexLock lock(fd->mutex);
+ Vector2i size = _get_size(fd, 16);
+ ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), 100);
+ return fd->stretch;
+}
+
void TextServerAdvanced::_font_set_name(const RID &p_font_rid, const String &p_name) {
FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
@@ -2091,6 +2146,22 @@ int64_t TextServerAdvanced::_font_get_fixed_size(const RID &p_font_rid) const {
return fd->fixed_size;
}
+void TextServerAdvanced::_font_set_allow_system_fallback(const RID &p_font_rid, bool p_allow_system_fallback) {
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ ERR_FAIL_COND(!fd);
+
+ MutexLock lock(fd->mutex);
+ fd->allow_system_fallback = p_allow_system_fallback;
+}
+
+bool TextServerAdvanced::_font_is_allow_system_fallback(const RID &p_font_rid) const {
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ ERR_FAIL_COND_V(!fd, false);
+
+ MutexLock lock(fd->mutex);
+ return fd->allow_system_fallback;
+}
+
void TextServerAdvanced::_font_set_force_autohinter(const RID &p_font_rid, bool p_force_autohinter) {
FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
@@ -3225,7 +3296,7 @@ void TextServerAdvanced::_font_draw_glyph(const RID &p_font_rid, const RID &p_ca
Point2 cpos = p_pos;
cpos += gl.rect.position * (double)p_size / (double)fd->msdf_source_size;
Size2 csize = gl.rect.size * (double)p_size / (double)fd->msdf_source_size;
- RenderingServer::get_singleton()->canvas_item_add_msdf_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate, 0, fd->msdf_range);
+ RenderingServer::get_singleton()->canvas_item_add_msdf_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate, 0, fd->msdf_range, (double)p_size / (double)fd->msdf_source_size);
} else {
double scale = _font_get_scale(p_font_rid, p_size);
Point2 cpos = p_pos;
@@ -3317,7 +3388,7 @@ void TextServerAdvanced::_font_draw_glyph_outline(const RID &p_font_rid, const R
Point2 cpos = p_pos;
cpos += gl.rect.position * (double)p_size / (double)fd->msdf_source_size;
Size2 csize = gl.rect.size * (double)p_size / (double)fd->msdf_source_size;
- RenderingServer::get_singleton()->canvas_item_add_msdf_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate, p_outline_size * 2, fd->msdf_range);
+ RenderingServer::get_singleton()->canvas_item_add_msdf_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate, p_outline_size, fd->msdf_range, (double)p_size / (double)fd->msdf_source_size);
} else {
Point2 cpos = p_pos;
double scale = _font_get_scale(p_font_rid, p_size);
@@ -3844,7 +3915,7 @@ bool TextServerAdvanced::_shaped_text_add_string(const RID &p_shaped, const Stri
return true;
}
-bool TextServerAdvanced::_shaped_text_add_object(const RID &p_shaped, const Variant &p_key, const Size2 &p_size, InlineAlignment p_inline_align, int64_t p_length) {
+bool TextServerAdvanced::_shaped_text_add_object(const RID &p_shaped, const Variant &p_key, const Size2 &p_size, InlineAlignment p_inline_align, int64_t p_length, float p_baseline) {
_THREAD_SAFE_METHOD_
ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped);
ERR_FAIL_COND_V(!sd, false);
@@ -3864,6 +3935,7 @@ bool TextServerAdvanced::_shaped_text_add_object(const RID &p_shaped, const Vari
obj.inline_align = p_inline_align;
obj.rect.size = p_size;
obj.pos = span.start;
+ obj.baseline = p_baseline;
sd->spans.push_back(span);
sd->text = sd->text + String::chr(0xfffc).repeat(p_length);
@@ -3874,7 +3946,7 @@ bool TextServerAdvanced::_shaped_text_add_object(const RID &p_shaped, const Vari
return true;
}
-bool TextServerAdvanced::_shaped_text_resize_object(const RID &p_shaped, const Variant &p_key, const Size2 &p_size, InlineAlignment p_inline_align) {
+bool TextServerAdvanced::_shaped_text_resize_object(const RID &p_shaped, const Variant &p_key, const Size2 &p_size, InlineAlignment p_inline_align, float p_baseline) {
ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped);
ERR_FAIL_COND_V(!sd, false);
@@ -3882,6 +3954,7 @@ bool TextServerAdvanced::_shaped_text_resize_object(const RID &p_shaped, const V
ERR_FAIL_COND_V(!sd->objects.has(p_key), false);
sd->objects[p_key].rect.size = p_size;
sd->objects[p_key].inline_align = p_inline_align;
+ sd->objects[p_key].baseline = p_baseline;
if (sd->valid) {
// Recalc string metrics.
sd->ascent = 0;
@@ -3968,6 +4041,9 @@ void TextServerAdvanced::_realign(ShapedTextDataAdvanced *p_sd) const {
case INLINE_ALIGNMENT_CENTER_TO: {
E.value.rect.position.y -= E.value.rect.size.y / 2;
} break;
+ case INLINE_ALIGNMENT_BASELINE_TO: {
+ E.value.rect.position.y -= E.value.baseline;
+ } break;
case INLINE_ALIGNMENT_TOP_TO: {
// NOP
} break;
@@ -3996,6 +4072,9 @@ void TextServerAdvanced::_realign(ShapedTextDataAdvanced *p_sd) const {
case INLINE_ALIGNMENT_CENTER_TO: {
E.value.rect.position.x -= E.value.rect.size.x / 2;
} break;
+ case INLINE_ALIGNMENT_BASELINE_TO: {
+ E.value.rect.position.x -= E.value.baseline;
+ } break;
case INLINE_ALIGNMENT_TOP_TO: {
// NOP
} break;
@@ -4620,12 +4699,11 @@ bool TextServerAdvanced::_shaped_text_update_breaks(const RID &p_shaped) {
sd->breaks[pos] = true;
} else if ((ubrk_getRuleStatus(bi) >= UBRK_LINE_SOFT) && (ubrk_getRuleStatus(bi) < UBRK_LINE_SOFT_LIMIT)) {
sd->breaks[pos] = false;
-
- int pos_p = pos - 1 - sd->start;
- char32_t c = sd->text[pos_p];
- if (pos - sd->start != sd->end && !is_whitespace(c) && (c != 0xfffc)) {
- sd->break_inserts++;
- }
+ }
+ int pos_p = pos - 1 - sd->start;
+ char32_t c = sd->text[pos_p];
+ if (pos - sd->start != sd->end && !is_whitespace(c) && (c != 0xfffc)) {
+ sd->break_inserts++;
}
}
}
@@ -4738,7 +4816,10 @@ bool TextServerAdvanced::_shaped_text_update_breaks(const RID &p_shaped) {
i += (sd_glyphs[i].count - 1);
}
}
- ERR_FAIL_COND_V_MSG(sd_shift != sd->break_inserts, false, "Invalid break insert count!");
+ if (sd_shift < sd->break_inserts) {
+ // Note: should not happen with a normal text, but might be a case with special fonts that substitute a long string (with breaks opportunities in it) with a single glyph (like Font Awesome).
+ glyphs_new.resize(sd->glyphs.size() + sd_shift);
+ }
if (sd->break_inserts > 0) {
sd->glyphs = glyphs_new;
@@ -5051,10 +5132,177 @@ _FORCE_INLINE_ void TextServerAdvanced::_add_featuers(const Dictionary &p_source
}
}
-void TextServerAdvanced::_shape_run(ShapedTextDataAdvanced *p_sd, int64_t p_start, int64_t p_end, hb_script_t p_script, hb_direction_t p_direction, TypedArray<RID> p_fonts, int64_t p_span, int64_t p_fb_index) {
+void TextServerAdvanced::_shape_run(ShapedTextDataAdvanced *p_sd, int64_t p_start, int64_t p_end, hb_script_t p_script, hb_direction_t p_direction, TypedArray<RID> p_fonts, int64_t p_span, int64_t p_fb_index, int64_t p_prev_start, int64_t p_prev_end) {
+ RID f;
int fs = p_sd->spans[p_span].font_size;
- if (p_fb_index >= p_fonts.size()) {
- // Add fallback glyphs.
+
+ if (p_fb_index >= 0 && p_fb_index < p_fonts.size()) {
+ // Try font from list.
+ f = p_fonts[p_fb_index];
+ } else if (OS::get_singleton()->has_feature("system_fonts") && p_fonts.size() > 0 && ((p_fb_index == p_fonts.size()) || (p_fb_index > p_fonts.size() && p_start != p_prev_start))) {
+ // Try system fallback.
+ RID fdef = p_fonts[0];
+ if (_font_is_allow_system_fallback(fdef)) {
+ String text = p_sd->text.substr(p_start, 1);
+ String font_name = _font_get_name(fdef);
+ BitField<FontStyle> font_style = _font_get_style(fdef);
+ int font_weight = _font_get_weight(fdef);
+ int font_stretch = _font_get_stretch(fdef);
+ Dictionary dvar = _font_get_variation_coordinates(fdef);
+ static int64_t wgth_tag = _name_to_tag("weight");
+ static int64_t wdth_tag = _name_to_tag("width");
+ static int64_t ital_tag = _name_to_tag("italic");
+ if (dvar.has(wgth_tag)) {
+ font_weight = dvar[wgth_tag].operator int();
+ }
+ if (dvar.has(wdth_tag)) {
+ font_stretch = dvar[wdth_tag].operator int();
+ }
+ if (dvar.has(ital_tag) && dvar[ital_tag].operator int() == 1) {
+ font_style.set_flag(TextServer::FONT_ITALIC);
+ }
+
+ char scr_buffer[5] = { 0, 0, 0, 0, 0 };
+ hb_tag_to_string(hb_script_to_iso15924_tag(p_script), scr_buffer);
+ String script_code = String(scr_buffer);
+ String locale = (p_sd->spans[p_span].language.is_empty()) ? TranslationServer::get_singleton()->get_tool_locale() : p_sd->spans[p_span].language;
+
+ PackedStringArray fallback_font_name = OS::get_singleton()->get_system_font_path_for_text(font_name, text, locale, script_code, font_weight, font_stretch, font_style & TextServer::FONT_ITALIC);
+#ifdef GDEXTENSION
+ for (int fb = 0; fb < fallback_font_name.size(); fb++) {
+ const String &E = fallback_font_name[fb];
+#else
+ for (const String &E : fallback_font_name) {
+#endif
+ SystemFontKey key = SystemFontKey(E, font_style & TextServer::FONT_ITALIC, font_weight, font_stretch, fdef, this);
+ if (system_fonts.has(key)) {
+ const SystemFontCache &sysf_cache = system_fonts[key];
+ int best_score = 0;
+ int best_match = -1;
+ for (int face_idx = 0; face_idx < sysf_cache.var.size(); face_idx++) {
+ const SystemFontCacheRec &F = sysf_cache.var[face_idx];
+ if (unlikely(!_font_has_char(F.rid, text[0]))) {
+ continue;
+ }
+ BitField<FontStyle> style = _font_get_style(F.rid);
+ int weight = _font_get_weight(F.rid);
+ int stretch = _font_get_stretch(F.rid);
+ int score = (20 - Math::abs(weight - font_weight) / 50);
+ score += (20 - Math::abs(stretch - font_stretch) / 10);
+ if (bool(style & TextServer::FONT_ITALIC) == bool(font_style & TextServer::FONT_ITALIC)) {
+ score += 30;
+ }
+ if (score >= best_score) {
+ best_score = score;
+ best_match = face_idx;
+ }
+ if (best_score == 70) {
+ break;
+ }
+ }
+ if (best_match != -1) {
+ f = sysf_cache.var[best_match].rid;
+ }
+ }
+ if (!f.is_valid()) {
+ if (system_fonts.has(key)) {
+ const SystemFontCache &sysf_cache = system_fonts[key];
+ if (sysf_cache.max_var == sysf_cache.var.size()) {
+ // All subfonts already tested, skip.
+ continue;
+ }
+ }
+
+ if (!system_font_data.has(E)) {
+ system_font_data[E] = FileAccess::get_file_as_bytes(E);
+ }
+
+ const PackedByteArray &font_data = system_font_data[E];
+
+ SystemFontCacheRec sysf;
+ sysf.rid = _create_font();
+ _font_set_data_ptr(sysf.rid, font_data.ptr(), font_data.size());
+
+ Dictionary var = dvar;
+ // Select matching style from collection.
+ int best_score = 0;
+ int best_match = -1;
+ for (int face_idx = 0; face_idx < _font_get_face_count(sysf.rid); face_idx++) {
+ _font_set_face_index(sysf.rid, face_idx);
+ if (unlikely(!_font_has_char(sysf.rid, text[0]))) {
+ continue;
+ }
+ BitField<FontStyle> style = _font_get_style(sysf.rid);
+ int weight = _font_get_weight(sysf.rid);
+ int stretch = _font_get_stretch(sysf.rid);
+ int score = (20 - Math::abs(weight - font_weight) / 50);
+ score += (20 - Math::abs(stretch - font_stretch) / 10);
+ if (bool(style & TextServer::FONT_ITALIC) == bool(font_style & TextServer::FONT_ITALIC)) {
+ score += 30;
+ }
+ if (score >= best_score) {
+ best_score = score;
+ best_match = face_idx;
+ }
+ if (best_score == 70) {
+ break;
+ }
+ }
+ if (best_match == -1) {
+ _free_rid(sysf.rid);
+ continue;
+ } else {
+ _font_set_face_index(sysf.rid, best_match);
+ }
+ sysf.index = best_match;
+
+ // If it's a variable font, apply weight, stretch and italic coordinates to match requested style.
+ if (best_score != 70) {
+ Dictionary ftr = _font_supported_variation_list(sysf.rid);
+ if (ftr.has(wdth_tag)) {
+ var[wdth_tag] = font_stretch;
+ _font_set_stretch(sysf.rid, font_stretch);
+ }
+ if (ftr.has(wgth_tag)) {
+ var[wgth_tag] = font_weight;
+ _font_set_weight(sysf.rid, font_weight);
+ }
+ if ((font_style & TextServer::FONT_ITALIC) && ftr.has(ital_tag)) {
+ var[ital_tag] = 1;
+ _font_set_style(sysf.rid, _font_get_style(sysf.rid) | TextServer::FONT_ITALIC);
+ }
+ }
+
+ _font_set_antialiasing(sysf.rid, key.antialiasing);
+ _font_set_generate_mipmaps(sysf.rid, key.mipmaps);
+ _font_set_multichannel_signed_distance_field(sysf.rid, key.msdf);
+ _font_set_msdf_pixel_range(sysf.rid, key.msdf_range);
+ _font_set_msdf_size(sysf.rid, key.msdf_source_size);
+ _font_set_fixed_size(sysf.rid, key.fixed_size);
+ _font_set_force_autohinter(sysf.rid, key.force_autohinter);
+ _font_set_hinting(sysf.rid, key.hinting);
+ _font_set_subpixel_positioning(sysf.rid, key.subpixel_positioning);
+ _font_set_variation_coordinates(sysf.rid, var);
+ _font_set_oversampling(sysf.rid, key.oversampling);
+ _font_set_embolden(sysf.rid, key.embolden);
+ _font_set_transform(sysf.rid, key.transform);
+
+ if (system_fonts.has(key)) {
+ system_fonts[key].var.push_back(sysf);
+ } else {
+ SystemFontCache &sysf_cache = system_fonts[key];
+ sysf_cache.max_var = _font_get_face_count(sysf.rid);
+ sysf_cache.var.push_back(sysf);
+ }
+ f = sysf.rid;
+ }
+ break;
+ }
+ }
+ }
+
+ if (!f.is_valid()) {
+ // No valid font, use fallback hex code boxes.
for (int i = p_start; i < p_end; i++) {
if (p_sd->preserve_invalid || (p_sd->preserve_control && is_control(p_sd->text[i]))) {
Glyph gl;
@@ -5085,7 +5333,6 @@ void TextServerAdvanced::_shape_run(ShapedTextDataAdvanced *p_sd, int64_t p_star
return;
}
- RID f = p_fonts[p_fb_index];
FontAdvanced *fd = font_owner.get_or_null(f);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -5180,7 +5427,7 @@ void TextServerAdvanced::_shape_run(ShapedTextDataAdvanced *p_sd, int64_t p_star
gl.end = end;
gl.count = 0;
- gl.font_rid = p_fonts[p_fb_index];
+ gl.font_rid = f;
gl.font_size = fs;
if (glyph_info[i].mask & HB_GLYPH_FLAG_UNSAFE_TO_BREAK) {
@@ -5247,7 +5494,7 @@ void TextServerAdvanced::_shape_run(ShapedTextDataAdvanced *p_sd, int64_t p_star
for (unsigned int i = 0; i < glyph_count; i++) {
if ((w[i].flags & GRAPHEME_IS_VALID) == GRAPHEME_IS_VALID) {
if (failed_subrun_start != p_end + 1) {
- _shape_run(p_sd, failed_subrun_start, failed_subrun_end, p_script, p_direction, p_fonts, p_span, p_fb_index + 1);
+ _shape_run(p_sd, failed_subrun_start, failed_subrun_end, p_script, p_direction, p_fonts, p_span, p_fb_index + 1, p_start, p_end);
failed_subrun_start = p_end + 1;
failed_subrun_end = p_start;
}
@@ -5277,7 +5524,7 @@ void TextServerAdvanced::_shape_run(ShapedTextDataAdvanced *p_sd, int64_t p_star
}
memfree(w);
if (failed_subrun_start != p_end + 1) {
- _shape_run(p_sd, failed_subrun_start, failed_subrun_end, p_script, p_direction, p_fonts, p_span, p_fb_index + 1);
+ _shape_run(p_sd, failed_subrun_start, failed_subrun_end, p_script, p_direction, p_fonts, p_span, p_fb_index + 1, p_start, p_end);
}
p_sd->ascent = MAX(p_sd->ascent, _font_get_ascent(f, fs));
p_sd->descent = MAX(p_sd->descent, _font_get_descent(f, fs));
@@ -5449,7 +5696,7 @@ bool TextServerAdvanced::_shaped_text_shape(const RID &p_shaped) {
}
fonts.append_array(fonts_scr_only);
fonts.append_array(fonts_no_match);
- _shape_run(sd, MAX(sd->spans[k].start - sd->start, script_run_start), MIN(sd->spans[k].end - sd->start, script_run_end), sd->script_iter->script_ranges[j].script, bidi_run_direction, fonts, k, 0);
+ _shape_run(sd, MAX(sd->spans[k].start - sd->start, script_run_start), MIN(sd->spans[k].end - sd->start, script_run_end), sd->script_iter->script_ranges[j].script, bidi_run_direction, fonts, k, 0, 0, 0);
}
}
}
@@ -5946,13 +6193,20 @@ String TextServerAdvanced::_strip_diacritics(const String &p_string) const {
String result;
for (int i = 0; i < normalized_string.length(); i++) {
if (u_getCombiningClass(normalized_string[i]) == 0) {
+#ifdef GDEXTENSION
+ result = result + String::chr(normalized_string[i]);
+#else
result = result + normalized_string[i];
+#endif
}
}
return result;
}
String TextServerAdvanced::_string_to_upper(const String &p_string, const String &p_language) const {
+ if (p_string.is_empty()) {
+ return p_string;
+ }
const String lang = (p_language.is_empty()) ? TranslationServer::get_singleton()->get_tool_locale() : p_language;
// Convert to UTF-16.
@@ -5972,6 +6226,9 @@ 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 {
+ if (p_string.is_empty()) {
+ return p_string;
+ }
const String lang = (p_language.is_empty()) ? TranslationServer::get_singleton()->get_tool_locale() : p_language;
// Convert to UTF-16.
Char16String utf16 = p_string.utf16();
@@ -5989,7 +6246,7 @@ String TextServerAdvanced::_string_to_lower(const String &p_string, const String
return String::utf16(lower.ptr(), len);
}
-PackedInt32Array TextServerAdvanced::_string_get_word_breaks(const String &p_string, const String &p_language) const {
+PackedInt32Array TextServerAdvanced::_string_get_word_breaks(const String &p_string, const String &p_language, int p_chars_per_line) 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();
@@ -5997,15 +6254,7 @@ PackedInt32Array TextServerAdvanced::_string_get_word_breaks(const String &p_str
HashSet<int> breaks;
UErrorCode err = U_ZERO_ERROR;
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++) {
- char32_t c = p_string[i];
- if (is_whitespace(c) || is_linebreak(c)) {
- breaks.insert(i);
- }
- }
- } else {
+ if (U_SUCCESS(err)) {
while (ubrk_next(bi) != UBRK_DONE) {
int pos = _convert_pos(p_string, utf16, ubrk_current(bi)) - 1;
if (pos != p_string.length() - 1) {
@@ -6016,24 +6265,80 @@ PackedInt32Array TextServerAdvanced::_string_get_word_breaks(const String &p_str
ubrk_close(bi);
PackedInt32Array ret;
+
+ int line_start = 0;
+ int line_end = 0; // End of last word on current line.
+ int word_start = 0; // -1 if no word encountered. Leading spaces are part of a word.
+ int word_length = 0;
+
for (int i = 0; i < p_string.length(); i++) {
- char32_t c = p_string[i];
- if (c == 0xfffc) {
- continue;
- }
- if (u_ispunct(c) && c != 0x005F) {
- ret.push_back(i);
- continue;
- }
- if (is_underscore(c)) {
- ret.push_back(i);
- continue;
- }
- if (breaks.has(i)) {
+ const char32_t c = p_string[i];
+
+ if (is_linebreak(c)) {
+ // Force newline.
+ ret.push_back(line_start);
ret.push_back(i);
+ line_start = i + 1;
+ line_end = line_start;
+ word_start = line_start;
+ word_length = 0;
+ } else if (c == 0xfffc) {
continue;
+ } else if ((u_ispunct(c) && c != 0x005F) || is_underscore(c) || c == '\t' || is_whitespace(c)) {
+ // A whitespace ends current word.
+ if (word_length > 0) {
+ line_end = i - 1;
+ word_start = -1;
+ word_length = 0;
+ }
+ } else if (breaks.has(i)) {
+ // End current word, no space.
+ if (word_length > 0) {
+ line_end = i;
+ word_start = i + 1;
+ word_length = 0;
+ }
+ if (p_chars_per_line <= 0) {
+ ret.push_back(line_start);
+ ret.push_back(line_end + 1);
+ line_start = word_start;
+ line_end = line_start;
+ }
+ } else {
+ if (word_start == -1) {
+ word_start = i;
+ if (p_chars_per_line <= 0) {
+ ret.push_back(line_start);
+ ret.push_back(line_end + 1);
+ line_start = word_start;
+ line_end = line_start;
+ }
+ }
+ word_length += 1;
+
+ if (p_chars_per_line > 0) {
+ if (word_length > p_chars_per_line) {
+ // Word too long: wrap before current character.
+ ret.push_back(line_start);
+ ret.push_back(i);
+ line_start = i;
+ line_end = i;
+ word_start = i;
+ word_length = 1;
+ } else if (i - line_start + 1 > p_chars_per_line) {
+ // Line too long: wrap after the last word.
+ ret.push_back(line_start);
+ ret.push_back(line_end + 1);
+ line_start = word_start;
+ line_end = line_start;
+ }
+ }
}
}
+ if (line_start < p_string.length()) {
+ ret.push_back(line_start);
+ ret.push_back(p_string.length());
+ }
return ret;
}
@@ -6228,6 +6533,17 @@ TextServerAdvanced::TextServerAdvanced() {
_bmp_create_font_funcs();
}
+void TextServerAdvanced::_cleanup() {
+ for (const KeyValue<SystemFontKey, SystemFontCache> &E : system_fonts) {
+ const Vector<SystemFontCacheRec> &sysf_cache = E.value.var;
+ for (const SystemFontCacheRec &F : sysf_cache) {
+ _free_rid(F.rid);
+ }
+ }
+ system_fonts.clear();
+ system_font_data.clear();
+}
+
TextServerAdvanced::~TextServerAdvanced() {
_bmp_free_font_funcs();
#ifdef MODULE_FREETYPE_ENABLED
diff --git a/modules/text_server_adv/text_server_adv.h b/modules/text_server_adv/text_server_adv.h
index 33fa1e117e..59f44cf142 100644
--- a/modules/text_server_adv/text_server_adv.h
+++ b/modules/text_server_adv/text_server_adv.h
@@ -88,7 +88,7 @@ using namespace godot;
#include "core/templates/rid_owner.h"
#include "scene/resources/texture.h"
-#include "modules/modules_enabled.gen.h" // For freetype, msdfgen.
+#include "modules/modules_enabled.gen.h" // For freetype, msdfgen, svg.
#endif
@@ -117,6 +117,7 @@ using namespace godot;
#include FT_ADVANCES_H
#include FT_MULTIPLE_MASTERS_H
#include FT_BBOX_H
+#include FT_MODULE_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.
@@ -299,6 +300,7 @@ class TextServerAdvanced : public TextServerExtension {
int msdf_range = 14;
int msdf_source_size = 48;
int fixed_size = 0;
+ bool allow_system_fallback = true;
bool force_autohinter = false;
TextServer::Hinting hinting = TextServer::HINTING_LIGHT;
TextServer::SubpixelPositioning subpixel_positioning = TextServer::SUBPIXEL_POSITIONING_AUTO;
@@ -310,6 +312,8 @@ class TextServerAdvanced : public TextServerExtension {
BitField<TextServer::FontStyle> style_flags = 0;
String font_name;
String style_name;
+ int weight = 400;
+ int stretch = 100;
HashMap<Vector2i, FontForSizeAdvanced *, VariantHasher, VariantComparator> cache;
@@ -371,6 +375,57 @@ 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;
+ _FORCE_INLINE_ int _font_get_weight_by_name(const String &p_sty_name) const {
+ String sty_name = p_sty_name.replace(" ", "").replace("-", "");
+ if (sty_name.find("thin") >= 0 || sty_name.find("hairline") >= 0) {
+ return 100;
+ } else if (sty_name.find("extralight") >= 0 || sty_name.find("ultralight") >= 0) {
+ return 200;
+ } else if (sty_name.find("light") >= 0) {
+ return 300;
+ } else if (sty_name.find("semilight") >= 0) {
+ return 350;
+ } else if (sty_name.find("regular") >= 0) {
+ return 400;
+ } else if (sty_name.find("medium") >= 0) {
+ return 500;
+ } else if (sty_name.find("semibold") >= 0 || sty_name.find("demibold") >= 0) {
+ return 600;
+ } else if (sty_name.find("bold") >= 0) {
+ return 700;
+ } else if (sty_name.find("extrabold") >= 0 || sty_name.find("ultrabold") >= 0) {
+ return 800;
+ } else if (sty_name.find("black") >= 0 || sty_name.find("heavy") >= 0) {
+ return 900;
+ } else if (sty_name.find("extrablack") >= 0 || sty_name.find("ultrablack") >= 0) {
+ return 950;
+ }
+ return 400;
+ }
+ _FORCE_INLINE_ int _font_get_stretch_by_name(const String &p_sty_name) const {
+ String sty_name = p_sty_name.replace(" ", "").replace("-", "");
+ if (sty_name.find("ultracondensed") >= 0) {
+ return 50;
+ } else if (sty_name.find("extracondensed") >= 0) {
+ return 63;
+ } else if (sty_name.find("condensed") >= 0) {
+ return 75;
+ } else if (sty_name.find("semicondensed") >= 0) {
+ return 87;
+ } else if (sty_name.find("semiexpanded") >= 0) {
+ return 113;
+ } else if (sty_name.find("expanded") >= 0) {
+ return 125;
+ } else if (sty_name.find("extraexpanded") >= 0) {
+ return 150;
+ } else if (sty_name.find("ultraexpanded") >= 0) {
+ return 200;
+ }
+ return 100;
+ }
+ _FORCE_INLINE_ bool _is_ital_style(const String &p_sty_name) const {
+ return (p_sty_name.find("italic") >= 0) || (p_sty_name.find("oblique") >= 0);
+ }
// Shaped text cache data.
struct TrimData {
@@ -412,6 +467,7 @@ class TextServerAdvanced : public TextServerExtension {
int pos = 0;
InlineAlignment inline_align = INLINE_ALIGNMENT_CENTER;
Rect2 rect;
+ float baseline = 0;
};
HashMap<Variant, EmbeddedObject, VariantHasher, VariantComparator> objects;
@@ -473,12 +529,87 @@ class TextServerAdvanced : public TextServerExtension {
mutable RID_PtrOwner<FontAdvanced> font_owner;
mutable RID_PtrOwner<ShapedTextDataAdvanced> shaped_owner;
+ struct SystemFontKey {
+ String font_name;
+ TextServer::FontAntialiasing antialiasing = TextServer::FONT_ANTIALIASING_GRAY;
+ bool italic = false;
+ bool mipmaps = false;
+ bool msdf = false;
+ bool force_autohinter = false;
+ int weight = 400;
+ int stretch = 100;
+ int msdf_range = 14;
+ int msdf_source_size = 48;
+ int fixed_size = 0;
+ TextServer::Hinting hinting = TextServer::HINTING_LIGHT;
+ TextServer::SubpixelPositioning subpixel_positioning = TextServer::SUBPIXEL_POSITIONING_AUTO;
+ Dictionary variation_coordinates;
+ double oversampling = 0.0;
+ double embolden = 0.0;
+ Transform2D transform;
+
+ bool operator==(const SystemFontKey &p_b) const {
+ return (font_name == p_b.font_name) && (antialiasing == p_b.antialiasing) && (italic == p_b.italic) && (mipmaps == p_b.mipmaps) && (msdf == p_b.msdf) && (force_autohinter == p_b.force_autohinter) && (weight == p_b.weight) && (stretch == p_b.stretch) && (msdf_range == p_b.msdf_range) && (msdf_source_size == p_b.msdf_source_size) && (fixed_size == p_b.fixed_size) && (hinting == p_b.hinting) && (subpixel_positioning == p_b.subpixel_positioning) && (variation_coordinates == p_b.variation_coordinates) && (oversampling == p_b.oversampling) && (embolden == p_b.embolden) && (transform == p_b.transform);
+ }
+
+ SystemFontKey(const String &p_font_name, bool p_italic, int p_weight, int p_stretch, RID p_font, const TextServerAdvanced *p_fb) {
+ font_name = p_font_name;
+ italic = p_italic;
+ weight = p_weight;
+ stretch = p_stretch;
+ antialiasing = p_fb->_font_get_antialiasing(p_font);
+ mipmaps = p_fb->_font_get_generate_mipmaps(p_font);
+ msdf = p_fb->_font_is_multichannel_signed_distance_field(p_font);
+ msdf_range = p_fb->_font_get_msdf_pixel_range(p_font);
+ msdf_source_size = p_fb->_font_get_msdf_size(p_font);
+ fixed_size = p_fb->_font_get_fixed_size(p_font);
+ force_autohinter = p_fb->_font_is_force_autohinter(p_font);
+ hinting = p_fb->_font_get_hinting(p_font);
+ subpixel_positioning = p_fb->_font_get_subpixel_positioning(p_font);
+ variation_coordinates = p_fb->_font_get_variation_coordinates(p_font);
+ oversampling = p_fb->_font_get_oversampling(p_font);
+ embolden = p_fb->_font_get_embolden(p_font);
+ transform = p_fb->_font_get_transform(p_font);
+ }
+ };
+
+ struct SystemFontCacheRec {
+ RID rid;
+ int index = 0;
+ };
+
+ struct SystemFontCache {
+ Vector<SystemFontCacheRec> var;
+ int max_var = 0;
+ };
+
+ struct SystemFontKeyHasher {
+ _FORCE_INLINE_ static uint32_t hash(const SystemFontKey &p_a) {
+ uint32_t hash = p_a.font_name.hash();
+ hash = hash_murmur3_one_32(p_a.variation_coordinates.hash(), hash);
+ hash = hash_murmur3_one_32(p_a.weight, hash);
+ hash = hash_murmur3_one_32(p_a.stretch, hash);
+ hash = hash_murmur3_one_32(p_a.msdf_range, hash);
+ hash = hash_murmur3_one_32(p_a.msdf_source_size, hash);
+ hash = hash_murmur3_one_32(p_a.fixed_size, hash);
+ hash = hash_murmur3_one_double(p_a.oversampling, hash);
+ hash = hash_murmur3_one_double(p_a.embolden, hash);
+ hash = hash_murmur3_one_real(p_a.transform[0].x, hash);
+ hash = hash_murmur3_one_real(p_a.transform[0].y, hash);
+ hash = hash_murmur3_one_real(p_a.transform[1].x, hash);
+ hash = hash_murmur3_one_real(p_a.transform[1].y, hash);
+ return hash_fmix32(hash_murmur3_one_32(((int)p_a.mipmaps) | ((int)p_a.msdf << 1) | ((int)p_a.italic << 2) | ((int)p_a.force_autohinter << 3) | ((int)p_a.hinting << 4) | ((int)p_a.subpixel_positioning << 8) | ((int)p_a.antialiasing << 12), hash));
+ }
+ };
+ mutable HashMap<SystemFontKey, SystemFontCache, SystemFontKeyHasher> system_fonts;
+ mutable HashMap<String, PackedByteArray> system_font_data;
+
void _realign(ShapedTextDataAdvanced *p_sd) const;
int64_t _convert_pos(const String &p_utf32, const Char16String &p_utf16, int64_t p_pos) const;
int64_t _convert_pos(const ShapedTextDataAdvanced *p_sd, int64_t p_pos) const;
int64_t _convert_pos_inv(const ShapedTextDataAdvanced *p_sd, int64_t p_pos) const;
bool _shape_substr(ShapedTextDataAdvanced *p_new_sd, const ShapedTextDataAdvanced *p_sd, int64_t p_start, int64_t p_length) const;
- void _shape_run(ShapedTextDataAdvanced *p_sd, int64_t p_start, int64_t p_end, hb_script_t p_script, hb_direction_t p_direction, TypedArray<RID> p_fonts, int64_t p_span, int64_t p_fb_index);
+ void _shape_run(ShapedTextDataAdvanced *p_sd, int64_t p_start, int64_t p_end, hb_script_t p_script, hb_direction_t p_direction, TypedArray<RID> p_fonts, int64_t p_span, int64_t p_fb_index, int64_t p_prev_start, int64_t p_prev_end);
Glyph _shape_single_glyph(ShapedTextDataAdvanced *p_sd, char32_t p_char, hb_script_t p_script, hb_direction_t p_direction, const RID &p_font, int64_t p_font_size);
_FORCE_INLINE_ void _add_featuers(const Dictionary &p_source, Vector<hb_feature_t> &r_ftrs);
@@ -567,6 +698,12 @@ public:
MODBIND2(font_set_style_name, const RID &, const String &);
MODBIND1RC(String, font_get_style_name, const RID &);
+ MODBIND2(font_set_weight, const RID &, int64_t);
+ MODBIND1RC(int64_t, font_get_weight, const RID &);
+
+ MODBIND2(font_set_stretch, const RID &, int64_t);
+ MODBIND1RC(int64_t, font_get_stretch, const RID &);
+
MODBIND2(font_set_name, const RID &, const String &);
MODBIND1RC(String, font_get_name, const RID &);
@@ -588,6 +725,9 @@ public:
MODBIND2(font_set_fixed_size, const RID &, int64_t);
MODBIND1RC(int64_t, font_get_fixed_size, const RID &);
+ MODBIND2(font_set_allow_system_fallback, const RID &, bool);
+ MODBIND1RC(bool, font_is_allow_system_fallback, const RID &);
+
MODBIND2(font_set_force_autohinter, const RID &, bool);
MODBIND1RC(bool, font_is_force_autohinter, const RID &);
@@ -729,8 +869,8 @@ public:
MODBIND2RC(int64_t, shaped_text_get_spacing, const RID &, SpacingType);
MODBIND7R(bool, shaped_text_add_string, const RID &, const String &, const TypedArray<RID> &, int64_t, const Dictionary &, const String &, const Variant &);
- MODBIND5R(bool, shaped_text_add_object, const RID &, const Variant &, const Size2 &, InlineAlignment, int64_t);
- MODBIND4R(bool, shaped_text_resize_object, const RID &, const Variant &, const Size2 &, InlineAlignment);
+ MODBIND6R(bool, shaped_text_add_object, const RID &, const Variant &, const Size2 &, InlineAlignment, int64_t, float);
+ MODBIND5R(bool, shaped_text_resize_object, const RID &, const Variant &, const Size2 &, InlineAlignment, float);
MODBIND1RC(int64_t, shaped_get_span_count, const RID &);
MODBIND2RC(Variant, shaped_get_span_meta, const RID &, int64_t);
@@ -775,7 +915,7 @@ public:
MODBIND2RC(String, parse_number, const String &, const String &);
MODBIND1RC(String, percent_sign, const String &);
- MODBIND2RC(PackedInt32Array, string_get_word_breaks, const String &, const String &);
+ MODBIND3RC(PackedInt32Array, string_get_word_breaks, const String &, const String &, int);
MODBIND2RC(int64_t, is_confusable, const String &, const PackedStringArray &);
MODBIND1RC(bool, spoof_check, const String &);
@@ -786,6 +926,8 @@ public:
MODBIND2RC(String, string_to_upper, const String &, const String &);
MODBIND2RC(String, string_to_lower, const String &, const String &);
+ MODBIND0(cleanup);
+
TextServerAdvanced();
~TextServerAdvanced();
};
diff --git a/modules/text_server_adv/thorvg_bounds_iterator.cpp b/modules/text_server_adv/thorvg_bounds_iterator.cpp
new file mode 100644
index 0000000000..54a6136134
--- /dev/null
+++ b/modules/text_server_adv/thorvg_bounds_iterator.cpp
@@ -0,0 +1,70 @@
+/*************************************************************************/
+/* thorvg_bounds_iterator.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 GDEXTENSION
+// Headers for building as GDExtension plug-in.
+
+#include <godot_cpp/godot.hpp>
+
+using namespace godot;
+
+#else
+// Headers for building as built-in module.
+
+#include "core/typedefs.h"
+
+#include "modules/modules_enabled.gen.h" // For svg.
+#endif
+
+#ifdef MODULE_SVG_ENABLED
+
+#include "thorvg_bounds_iterator.h"
+
+#include <tvgIteratorAccessor.h>
+#include <tvgPaint.h>
+
+// This function uses private ThorVG API to get bounding box of top level children elements.
+
+void tvg_get_bounds(tvg::Picture *p_picture, float &r_min_x, float &r_min_y, float &r_max_x, float &r_max_y) {
+ tvg::IteratorAccessor itrAccessor;
+ if (tvg::Iterator *it = itrAccessor.iterator(p_picture)) {
+ while (const tvg::Paint *child = it->next()) {
+ float x = 0, y = 0, w = 0, h = 0;
+ child->bounds(&x, &y, &w, &h, true);
+ r_min_x = MIN(x, r_min_x);
+ r_min_y = MIN(y, r_min_y);
+ r_max_x = MAX(x + w, r_max_x);
+ r_max_y = MAX(y + h, r_max_y);
+ }
+ delete (it);
+ }
+}
+
+#endif // MODULE_SVG_ENABLED
diff --git a/modules/text_server_adv/thorvg_bounds_iterator.h b/modules/text_server_adv/thorvg_bounds_iterator.h
new file mode 100644
index 0000000000..e54e30eaa2
--- /dev/null
+++ b/modules/text_server_adv/thorvg_bounds_iterator.h
@@ -0,0 +1,58 @@
+/*************************************************************************/
+/* thorvg_bounds_iterator.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 THORVG_BOUNDS_ITERATOR_H
+#define THORVG_BOUNDS_ITERATOR_H
+
+#ifdef GDEXTENSION
+// Headers for building as GDExtension plug-in.
+
+#include <godot_cpp/core/mutex_lock.hpp>
+#include <godot_cpp/godot.hpp>
+
+using namespace godot;
+
+#else
+// Headers for building as built-in module.
+
+#include "core/typedefs.h"
+
+#include "modules/modules_enabled.gen.h" // For svg.
+#endif
+
+#ifdef MODULE_SVG_ENABLED
+
+#include <thorvg.h>
+
+void tvg_get_bounds(tvg::Picture *p_picture, float &r_min_x, float &r_min_y, float &r_max_x, float &r_max_y);
+
+#endif // MODULE_SVG_ENABLED
+
+#endif // THORVG_BOUNDS_ITERATOR_H
diff --git a/modules/text_server_adv/thorvg_svg_in_ot.cpp b/modules/text_server_adv/thorvg_svg_in_ot.cpp
new file mode 100644
index 0000000000..7863ab67fa
--- /dev/null
+++ b/modules/text_server_adv/thorvg_svg_in_ot.cpp
@@ -0,0 +1,320 @@
+/*************************************************************************/
+/* thorvg_svg_in_ot.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 GDEXTENSION
+// Headers for building as GDExtension plug-in.
+
+#include <godot_cpp/classes/xml_parser.hpp>
+#include <godot_cpp/core/mutex_lock.hpp>
+#include <godot_cpp/godot.hpp>
+#include <godot_cpp/templates/vector.hpp>
+
+using namespace godot;
+
+#else
+// Headers for building as built-in module.
+
+#include "core/error/error_macros.h"
+#include "core/io/xml_parser.h"
+#include "core/os/memory.h"
+#include "core/os/os.h"
+#include "core/string/ustring.h"
+#include "core/typedefs.h"
+#include "core/variant/variant.h"
+
+#include "modules/modules_enabled.gen.h" // For svg.
+#endif
+
+#ifdef MODULE_SVG_ENABLED
+
+#include "thorvg_bounds_iterator.h"
+#include "thorvg_svg_in_ot.h"
+
+#include <freetype/otsvg.h>
+#include <ft2build.h>
+
+#include <math.h>
+#include <stdlib.h>
+
+FT_Error tvg_svg_in_ot_init(FT_Pointer *p_state) {
+ *p_state = memnew(TVG_State);
+
+ return FT_Err_Ok;
+}
+
+void tvg_svg_in_ot_free(FT_Pointer *p_state) {
+ TVG_State *state = *reinterpret_cast<TVG_State **>(p_state);
+ memdelete(state);
+}
+
+FT_Error tvg_svg_in_ot_preset_slot(FT_GlyphSlot p_slot, FT_Bool p_cache, FT_Pointer *p_state) {
+ TVG_State *state = *reinterpret_cast<TVG_State **>(p_state);
+ if (!state) {
+ ERR_FAIL_V_MSG(FT_Err_Invalid_SVG_Document, "SVG in OT state not initialized.");
+ }
+ MutexLock lock(state->mutex);
+
+ FT_SVG_Document document = (FT_SVG_Document)p_slot->other;
+ FT_Size_Metrics metrics = document->metrics;
+
+ GL_State &gl_state = state->glyph_map[p_slot->glyph_index];
+ if (!gl_state.ready) {
+ Ref<XMLParser> parser;
+ parser.instantiate();
+#ifdef GDEXTENSION
+ PackedByteArray data;
+ data.resize(document->svg_document_length);
+ memcpy(data.ptrw(), document->svg_document, document->svg_document_length);
+ parser->open_buffer(data);
+#else
+ parser->_open_buffer((const uint8_t *)document->svg_document, document->svg_document_length);
+#endif
+
+ float aspect = 1.0f;
+ String xml_body;
+ while (parser->read() == OK) {
+ if (parser->has_attribute("id")) {
+#ifdef GDEXTENSION
+ const String &gl_name = parser->get_named_attribute_value("id");
+#else
+ const String &gl_name = parser->get_attribute_value("id");
+#endif
+ if (gl_name.begins_with("glyph")) {
+ int dot_pos = gl_name.find(".");
+ int64_t gl_idx = gl_name.substr(5, (dot_pos > 0) ? dot_pos - 5 : -1).to_int();
+ if (p_slot->glyph_index != gl_idx) {
+ parser->skip_section();
+ continue;
+ }
+ }
+ }
+ if (parser->get_node_type() == XMLParser::NODE_ELEMENT && parser->get_node_name() == "svg") {
+ if (parser->has_attribute("viewBox")) {
+#ifdef GDEXTENSION
+ PackedStringArray vb = parser->get_named_attribute_value("viewBox").split(" ");
+#else
+ Vector<String> vb = parser->get_attribute_value("viewBox").split(" ");
+#endif
+
+ if (vb.size() == 4) {
+ aspect = vb[2].to_float() / vb[3].to_float();
+ }
+ }
+ continue;
+ }
+#ifdef GDEXTENSION
+ if (parser->get_node_type() == XMLParser::NODE_ELEMENT) {
+ xml_body = xml_body + "<" + parser->get_node_name();
+ for (int i = 0; i < parser->get_attribute_count(); i++) {
+ xml_body = xml_body + " " + parser->get_attribute_name(i) + "=\"" + parser->get_attribute_value(i) + "\"";
+ }
+ xml_body = xml_body + ">";
+ } else if (parser->get_node_type() == XMLParser::NODE_TEXT) {
+ xml_body = xml_body + parser->get_node_data();
+ } else if (parser->get_node_type() == XMLParser::NODE_ELEMENT_END) {
+ xml_body = xml_body + "</" + parser->get_node_name() + ">";
+ }
+#else
+ if (parser->get_node_type() == XMLParser::NODE_ELEMENT) {
+ xml_body += vformat("<%s", parser->get_node_name());
+ for (int i = 0; i < parser->get_attribute_count(); i++) {
+ xml_body += vformat(" %s=\"%s\"", parser->get_attribute_name(i), parser->get_attribute_value(i));
+ }
+ xml_body += ">";
+ } else if (parser->get_node_type() == XMLParser::NODE_TEXT) {
+ xml_body += parser->get_node_data();
+ } else if (parser->get_node_type() == XMLParser::NODE_ELEMENT_END) {
+ xml_body += vformat("</%s>", parser->get_node_name());
+ }
+#endif
+ }
+ String temp_xml = "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 0 0\">" + xml_body;
+
+ std::unique_ptr<tvg::Picture> picture = tvg::Picture::gen();
+ tvg::Result result = picture->load(temp_xml.utf8().get_data(), temp_xml.utf8().length(), "svg+xml", false);
+ if (result != tvg::Result::Success) {
+ ERR_FAIL_V_MSG(FT_Err_Invalid_SVG_Document, "Failed to load SVG document (bounds detection).");
+ }
+
+ float min_x = INFINITY, min_y = INFINITY, max_x = -INFINITY, max_y = -INFINITY;
+ tvg_get_bounds(picture.get(), min_x, min_y, max_x, max_y);
+
+ float new_h = (max_y - min_y);
+ float new_w = (max_x - min_x);
+
+ if (new_h * aspect >= new_w) {
+ new_w = (new_h * aspect);
+ } else {
+ new_h = (new_w / aspect);
+ }
+
+#ifdef GDEXTENSION
+ gl_state.xml_code = "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"" + rtos(min_x) + " " + rtos(min_y) + " " + rtos(new_w) + " " + rtos(new_h) + "\">" + xml_body;
+#else
+ gl_state.xml_code = vformat("<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"%f %f %f %f\">", min_x, min_y, new_w, new_h) + xml_body;
+#endif
+
+ picture = tvg::Picture::gen();
+ result = picture->load(gl_state.xml_code.utf8().get_data(), gl_state.xml_code.utf8().length(), "svg+xml", false);
+ if (result != tvg::Result::Success) {
+ ERR_FAIL_V_MSG(FT_Err_Invalid_SVG_Document, "Failed to load SVG document (glyph metrics).");
+ }
+
+ float x_svg_to_out, y_svg_to_out;
+ x_svg_to_out = (float)metrics.x_ppem / new_w;
+ y_svg_to_out = (float)metrics.y_ppem / new_h;
+
+ gl_state.m.e11 = (double)document->transform.xx / (1 << 16) * x_svg_to_out;
+ gl_state.m.e12 = -(double)document->transform.xy / (1 << 16) * x_svg_to_out;
+ gl_state.m.e21 = -(double)document->transform.yx / (1 << 16) * y_svg_to_out;
+ gl_state.m.e22 = (double)document->transform.yy / (1 << 16) * y_svg_to_out;
+ gl_state.m.e13 = (double)document->delta.x / 64 * new_w / metrics.x_ppem;
+ gl_state.m.e23 = -(double)document->delta.y / 64 * new_h / metrics.y_ppem;
+ gl_state.m.e31 = 0;
+ gl_state.m.e32 = 0;
+ gl_state.m.e33 = 1;
+
+ result = picture->transform(gl_state.m);
+ if (result != tvg::Result::Success) {
+ ERR_FAIL_V_MSG(FT_Err_Invalid_SVG_Document, "Failed to apply transform to SVG document.");
+ }
+
+ result = picture->bounds(&gl_state.x, &gl_state.y, &gl_state.w, &gl_state.h, true);
+ if (result != tvg::Result::Success) {
+ ERR_FAIL_V_MSG(FT_Err_Invalid_SVG_Document, "Failed to get SVG bounds.");
+ }
+
+ gl_state.bmp_y = -min_y * gl_state.h / new_h;
+ gl_state.bmp_x = min_x * gl_state.w / new_w;
+
+ gl_state.ready = true;
+ }
+
+ p_slot->bitmap_left = (FT_Int)gl_state.bmp_x;
+ p_slot->bitmap_top = (FT_Int)gl_state.bmp_y;
+
+ float tmp = ceil(gl_state.h);
+ p_slot->bitmap.rows = (unsigned int)tmp;
+ tmp = ceil(gl_state.w);
+ p_slot->bitmap.width = (unsigned int)tmp;
+ p_slot->bitmap.pitch = (int)p_slot->bitmap.width * 4;
+ p_slot->bitmap.pixel_mode = FT_PIXEL_MODE_BGRA;
+
+ float metrics_width, metrics_height;
+ float horiBearingX, horiBearingY;
+ float vertBearingX, vertBearingY;
+
+ metrics_width = (float)gl_state.w;
+ metrics_height = (float)gl_state.h;
+ horiBearingX = (float)gl_state.x;
+ horiBearingY = (float)-gl_state.y;
+ vertBearingX = p_slot->metrics.horiBearingX / 64.0f - p_slot->metrics.horiAdvance / 64.0f / 2;
+ vertBearingY = (p_slot->metrics.vertAdvance / 64.0f - p_slot->metrics.height / 64.0f) / 2;
+
+ tmp = roundf(metrics_width * 64);
+ p_slot->metrics.width = (FT_Pos)tmp;
+ tmp = roundf(metrics_height * 64);
+ p_slot->metrics.height = (FT_Pos)tmp;
+
+ p_slot->metrics.horiBearingX = (FT_Pos)(horiBearingX * 64);
+ p_slot->metrics.horiBearingY = (FT_Pos)(horiBearingY * 64);
+ p_slot->metrics.vertBearingX = (FT_Pos)(vertBearingX * 64);
+ p_slot->metrics.vertBearingY = (FT_Pos)(vertBearingY * 64);
+
+ if (p_slot->metrics.vertAdvance == 0) {
+ p_slot->metrics.vertAdvance = (FT_Pos)(metrics_height * 1.2f * 64);
+ }
+
+ return FT_Err_Ok;
+}
+
+FT_Error tvg_svg_in_ot_render(FT_GlyphSlot p_slot, FT_Pointer *p_state) {
+ TVG_State *state = *reinterpret_cast<TVG_State **>(p_state);
+ if (!state) {
+ ERR_FAIL_V_MSG(FT_Err_Invalid_SVG_Document, "SVG in OT state not initialized.");
+ }
+ MutexLock lock(state->mutex);
+
+ if (!state->glyph_map.has(p_slot->glyph_index)) {
+ ERR_FAIL_V_MSG(FT_Err_Invalid_SVG_Document, "SVG glyph not loaded.");
+ }
+
+ GL_State &gl_state = state->glyph_map[p_slot->glyph_index];
+ ERR_FAIL_COND_V_MSG(!gl_state.ready, FT_Err_Invalid_SVG_Document, "SVG glyph not ready.");
+
+ std::unique_ptr<tvg::Picture> picture = tvg::Picture::gen();
+ tvg::Result res = picture->load(gl_state.xml_code.utf8().get_data(), gl_state.xml_code.utf8().length(), "svg+xml", false);
+ if (res != tvg::Result::Success) {
+ ERR_FAIL_V_MSG(FT_Err_Invalid_SVG_Document, "Failed to load SVG document (glyph rendering).");
+ }
+ res = picture->transform(gl_state.m);
+ if (res != tvg::Result::Success) {
+ ERR_FAIL_V_MSG(FT_Err_Invalid_SVG_Document, "Failed to apply transform to SVG document.");
+ }
+
+ std::unique_ptr<tvg::SwCanvas> sw_canvas = tvg::SwCanvas::gen();
+ res = sw_canvas->target((uint32_t *)p_slot->bitmap.buffer, (int)p_slot->bitmap.width, (int)p_slot->bitmap.width, (int)p_slot->bitmap.rows, tvg::SwCanvas::ARGB8888_STRAIGHT);
+ if (res != tvg::Result::Success) {
+ ERR_FAIL_V_MSG(FT_Err_Invalid_Outline, "Failed to create SVG canvas.");
+ }
+ res = sw_canvas->push(std::move(picture));
+ if (res != tvg::Result::Success) {
+ ERR_FAIL_V_MSG(FT_Err_Invalid_Outline, "Failed to set SVG canvas source.");
+ }
+ res = sw_canvas->draw();
+ if (res != tvg::Result::Success) {
+ ERR_FAIL_V_MSG(FT_Err_Invalid_Outline, "Failed to draw to SVG canvas.");
+ }
+ res = sw_canvas->sync();
+ if (res != tvg::Result::Success) {
+ ERR_FAIL_V_MSG(FT_Err_Invalid_Outline, "Failed to sync SVG canvas.");
+ }
+
+ state->glyph_map.erase(p_slot->glyph_index);
+
+ p_slot->bitmap.pixel_mode = FT_PIXEL_MODE_BGRA;
+ p_slot->bitmap.num_grays = 256;
+ p_slot->format = FT_GLYPH_FORMAT_BITMAP;
+
+ return FT_Err_Ok;
+}
+
+SVG_RendererHooks tvg_svg_in_ot_hooks = {
+ (SVG_Lib_Init_Func)tvg_svg_in_ot_init,
+ (SVG_Lib_Free_Func)tvg_svg_in_ot_free,
+ (SVG_Lib_Render_Func)tvg_svg_in_ot_render,
+ (SVG_Lib_Preset_Slot_Func)tvg_svg_in_ot_preset_slot,
+};
+
+SVG_RendererHooks *get_tvg_svg_in_ot_hooks() {
+ return &tvg_svg_in_ot_hooks;
+}
+
+#endif // MODULE_SVG_ENABLED
diff --git a/modules/text_server_adv/thorvg_svg_in_ot.h b/modules/text_server_adv/thorvg_svg_in_ot.h
new file mode 100644
index 0000000000..b2816193d9
--- /dev/null
+++ b/modules/text_server_adv/thorvg_svg_in_ot.h
@@ -0,0 +1,86 @@
+/*************************************************************************/
+/* thorvg_svg_in_ot.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 THORVG_SVG_IN_OT_H
+#define THORVG_SVG_IN_OT_H
+
+#ifdef GDEXTENSION
+// Headers for building as GDExtension plug-in.
+
+#include <godot_cpp/core/mutex_lock.hpp>
+#include <godot_cpp/godot.hpp>
+#include <godot_cpp/templates/hash_map.hpp>
+
+using namespace godot;
+
+#else
+// Headers for building as built-in module.
+
+#include "core/os/mutex.h"
+#include "core/templates/hash_map.h"
+#include "core/typedefs.h"
+
+#include "modules/modules_enabled.gen.h" // For svg.
+#endif
+
+#ifdef MODULE_SVG_ENABLED
+
+#include <freetype/freetype.h>
+#include <freetype/otsvg.h>
+#include <ft2build.h>
+#include <thorvg.h>
+
+struct GL_State {
+ bool ready = false;
+ float bmp_x = 0;
+ float bmp_y = 0;
+ float x = 0;
+ float y = 0;
+ float w = 0;
+ float h = 0;
+ String xml_code;
+ tvg::Matrix m;
+};
+
+struct TVG_State {
+ Mutex mutex;
+ HashMap<uint32_t, GL_State> glyph_map;
+};
+
+FT_Error tvg_svg_in_ot_init(FT_Pointer *p_state);
+void tvg_svg_in_ot_free(FT_Pointer *p_state);
+FT_Error tvg_svg_in_ot_preset_slot(FT_GlyphSlot p_slot, FT_Bool p_cache, FT_Pointer *p_state);
+FT_Error tvg_svg_in_ot_render(FT_GlyphSlot p_slot, FT_Pointer *p_state);
+
+SVG_RendererHooks *get_tvg_svg_in_ot_hooks();
+
+#endif // MODULE_SVG_ENABLED
+
+#endif // THORVG_SVG_IN_OT_H
diff --git a/modules/text_server_fb/SCsub b/modules/text_server_fb/SCsub
index 429d2e1fdc..f1d57ec4d3 100644
--- a/modules/text_server_fb/SCsub
+++ b/modules/text_server_fb/SCsub
@@ -8,6 +8,9 @@ msdfgen_enabled = "msdfgen" in env.module_list
env_text_server_fb = env_modules.Clone()
+if "svg" in env.module_list:
+ env_text_server_fb.Prepend(CPPPATH=["#thirdparty/thorvg/inc", "#thirdparty/thorvg/src/lib"])
+
if env["builtin_msdfgen"] and msdfgen_enabled:
env_text_server_fb.Prepend(CPPPATH=["#thirdparty/msdfgen"])
diff --git a/modules/text_server_fb/gdextension_build/SConstruct b/modules/text_server_fb/gdextension_build/SConstruct
index 8ed8f61a43..7b4c548a21 100644
--- a/modules/text_server_fb/gdextension_build/SConstruct
+++ b/modules/text_server_fb/gdextension_build/SConstruct
@@ -22,6 +22,7 @@ opts = Variables([], ARGUMENTS)
opts.Add(BoolVariable("brotli_enabled", "Use Brotli library", True))
opts.Add(BoolVariable("freetype_enabled", "Use FreeType library", True))
opts.Add(BoolVariable("msdfgen_enabled", "Use MSDFgen library (require FreeType)", True))
+opts.Add(BoolVariable("thorvg_enabled", "Use ThorVG library (require FreeType)", True))
opts.Add(BoolVariable("verbose", "Enable verbose output for the compilation", False))
opts.Update(env)
@@ -29,6 +30,79 @@ opts.Update(env)
if not env["verbose"]:
methods.no_verbose(sys, env)
+# ThorVG
+if env["thorvg_enabled"] and env["freetype_enabled"]:
+ env_tvg = env.Clone()
+ env_tvg.disable_warnings()
+
+ thirdparty_tvg_dir = "../../../thirdparty/thorvg/"
+ thirdparty_tvg_sources = [
+ "src/lib/sw_engine/tvgSwFill.cpp",
+ "src/lib/sw_engine/tvgSwImage.cpp",
+ "src/lib/sw_engine/tvgSwMath.cpp",
+ "src/lib/sw_engine/tvgSwMemPool.cpp",
+ "src/lib/sw_engine/tvgSwRaster.cpp",
+ "src/lib/sw_engine/tvgSwRenderer.cpp",
+ "src/lib/sw_engine/tvgSwRle.cpp",
+ "src/lib/sw_engine/tvgSwShape.cpp",
+ "src/lib/sw_engine/tvgSwStroke.cpp",
+ "src/lib/tvgAccessor.cpp",
+ "src/lib/tvgBezier.cpp",
+ "src/lib/tvgCanvas.cpp",
+ "src/lib/tvgFill.cpp",
+ "src/lib/tvgGlCanvas.cpp",
+ "src/lib/tvgInitializer.cpp",
+ "src/lib/tvgLinearGradient.cpp",
+ "src/lib/tvgLoader.cpp",
+ "src/lib/tvgLzw.cpp",
+ "src/lib/tvgPaint.cpp",
+ "src/lib/tvgPicture.cpp",
+ "src/lib/tvgRadialGradient.cpp",
+ "src/lib/tvgRender.cpp",
+ "src/lib/tvgSaver.cpp",
+ "src/lib/tvgScene.cpp",
+ "src/lib/tvgShape.cpp",
+ "src/lib/tvgSwCanvas.cpp",
+ "src/lib/tvgTaskScheduler.cpp",
+ "src/loaders/external_png/tvgPngLoader.cpp",
+ "src/loaders/jpg/tvgJpgd.cpp",
+ "src/loaders/jpg/tvgJpgLoader.cpp",
+ "src/loaders/raw/tvgRawLoader.cpp",
+ "src/loaders/svg/tvgSvgCssStyle.cpp",
+ "src/loaders/svg/tvgSvgLoader.cpp",
+ "src/loaders/svg/tvgSvgPath.cpp",
+ "src/loaders/svg/tvgSvgSceneBuilder.cpp",
+ "src/loaders/svg/tvgSvgUtil.cpp",
+ "src/loaders/svg/tvgXmlParser.cpp",
+ "src/loaders/tvg/tvgTvgBinInterpreter.cpp",
+ "src/loaders/tvg/tvgTvgLoader.cpp",
+ "src/savers/tvg/tvgTvgSaver.cpp",
+ ]
+ thirdparty_tvg_sources = [thirdparty_tvg_dir + file for file in thirdparty_tvg_sources]
+
+ env_tvg.Append(
+ CPPPATH=[
+ "../../../thirdparty/thorvg/inc",
+ "../../../thirdparty/thorvg/src/lib",
+ "../../../thirdparty/thorvg/src/lib/sw_engine",
+ "../../../thirdparty/thorvg/src/loaders/external_png",
+ "../../../thirdparty/thorvg/src/loaders/jpg",
+ "../../../thirdparty/thorvg/src/loaders/raw",
+ "../../../thirdparty/thorvg/src/loaders/svg",
+ "../../../thirdparty/thorvg/src/loaders/tvg",
+ "../../../thirdparty/thorvg/src/savers/tvg",
+ "../../../thirdparty/libpng",
+ ]
+ )
+ env.Append(CPPPATH=["../../../thirdparty/thorvg/inc", "../../../thirdparty/thorvg/src/lib"])
+ env.Append(CPPDEFINES=["MODULE_SVG_ENABLED"])
+
+ lib = env_tvg.Library(
+ f'tvg_builtin{env["suffix"]}{env["LIBSUFFIX"]}',
+ thirdparty_tvg_sources,
+ )
+ env.Append(LIBS=[lib])
+
# MSDFGEN
if env["msdfgen_enabled"] and env["freetype_enabled"]:
env_msdfgen = env.Clone()
diff --git a/modules/text_server_fb/register_types.cpp b/modules/text_server_fb/register_types.cpp
index fa7b87fc17..98a8f466b3 100644
--- a/modules/text_server_fb/register_types.cpp
+++ b/modules/text_server_fb/register_types.cpp
@@ -62,7 +62,7 @@ using namespace godot;
extern "C" {
-GDNativeBool GDN_EXPORT textserver_fallback_init(const GDNativeInterface *p_interface, const GDNativeExtensionClassLibraryPtr p_library, GDNativeInitialization *r_initialization) {
+GDExtensionBool GDN_EXPORT textserver_fallback_init(const GDExtensionInterface *p_interface, const GDExtensionClassLibraryPtr p_library, GDExtensionInitialization *r_initialization) {
GDExtensionBinding::InitObject init_obj(p_interface, p_library, r_initialization);
init_obj.register_initializer(&initialize_text_server_fb_module);
diff --git a/modules/text_server_fb/text_server_fb.cpp b/modules/text_server_fb/text_server_fb.cpp
index 999870b904..ea7b7a271b 100644
--- a/modules/text_server_fb/text_server_fb.cpp
+++ b/modules/text_server_fb/text_server_fb.cpp
@@ -34,6 +34,7 @@
// Headers for building as GDExtension plug-in.
#include <godot_cpp/classes/file_access.hpp>
+#include <godot_cpp/classes/os.hpp>
#include <godot_cpp/classes/project_settings.hpp>
#include <godot_cpp/classes/rendering_server.hpp>
#include <godot_cpp/classes/translation_server.hpp>
@@ -41,15 +42,18 @@
using namespace godot;
+#define GLOBAL_GET(m_var) ProjectSettings::get_singleton()->get(m_var)
+
#else
// Headers for building as built-in module.
#include "core/config/project_settings.h"
#include "core/error/error_macros.h"
#include "core/string/print_string.h"
+#include "core/string/translation.h"
#include "core/string/ucaps.h"
-#include "modules/modules_enabled.gen.h" // For freetype, msdfgen.
+#include "modules/modules_enabled.gen.h" // For freetype, msdfgen, svg.
#endif
@@ -62,6 +66,10 @@ using namespace godot;
#include "msdfgen.h"
#endif
+#ifdef MODULE_SVG_ENABLED
+#include "thorvg_svg_in_ot.h"
+#endif
+
/*************************************************************************/
#define OT_TAG(c1, c2, c3, c4) ((int32_t)((((uint32_t)(c1)&0xff) << 24) | (((uint32_t)(c2)&0xff) << 16) | (((uint32_t)(c3)&0xff) << 8) | ((uint32_t)(c4)&0xff)))
@@ -771,6 +779,9 @@ _FORCE_INLINE_ bool TextServerFallback::_ensure_cache_for_size(FontFallback *p_f
memdelete(fd);
ERR_FAIL_V_MSG(false, "FreeType: Error initializing library: '" + String(FT_Error_String(error)) + "'.");
}
+#ifdef MODULE_SVG_ENABLED
+ FT_Property_Set(ft_library, "ot-svg", "svg-hooks", get_tvg_svg_in_ot_hooks());
+#endif
}
memset(&fd->stream, 0, sizeof(FT_StreamRec));
@@ -843,11 +854,13 @@ _FORCE_INLINE_ bool TextServerFallback::_ensure_cache_for_size(FontFallback *p_f
if (fd->face->style_name != nullptr) {
p_font_data->style_name = String::utf8((const char *)fd->face->style_name);
}
+ p_font_data->weight = _font_get_weight_by_name(p_font_data->style_name.to_lower());
+ p_font_data->stretch = _font_get_stretch_by_name(p_font_data->style_name.to_lower());
p_font_data->style_flags = 0;
- if (fd->face->style_flags & FT_STYLE_FLAG_BOLD) {
+ if ((fd->face->style_flags & FT_STYLE_FLAG_BOLD) || p_font_data->weight >= 700) {
p_font_data->style_flags.set_flag(FONT_BOLD);
}
- if (fd->face->style_flags & FT_STYLE_FLAG_ITALIC) {
+ if ((fd->face->style_flags & FT_STYLE_FLAG_ITALIC) || _is_ital_style(p_font_data->style_name.to_lower())) {
p_font_data->style_flags.set_flag(FONT_ITALIC);
}
if (fd->face->face_flags & FT_FACE_FLAG_FIXED_WIDTH) {
@@ -992,6 +1005,9 @@ int64_t TextServerFallback::_font_get_face_count(const RID &p_font_rid) const {
if (!ft_library) {
error = FT_Init_FreeType(&ft_library);
ERR_FAIL_COND_V_MSG(error != 0, false, "FreeType: Error initializing library: '" + String(FT_Error_String(error)) + "'.");
+#ifdef MODULE_SVG_ENABLED
+ FT_Property_Set(ft_library, "ot-svg", "svg-hooks", get_tvg_svg_in_ot_hooks());
+#endif
}
FT_StreamRec stream;
@@ -1049,6 +1065,46 @@ String TextServerFallback::_font_get_style_name(const RID &p_font_rid) const {
return fd->style_name;
}
+void TextServerFallback::_font_set_weight(const RID &p_font_rid, int64_t p_weight) {
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
+ ERR_FAIL_COND(!fd);
+
+ MutexLock lock(fd->mutex);
+ Vector2i size = _get_size(fd, 16);
+ ERR_FAIL_COND(!_ensure_cache_for_size(fd, size));
+ fd->weight = CLAMP(p_weight, 100, 999);
+}
+
+int64_t TextServerFallback::_font_get_weight(const RID &p_font_rid) const {
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
+ ERR_FAIL_COND_V(!fd, 400);
+
+ MutexLock lock(fd->mutex);
+ Vector2i size = _get_size(fd, 16);
+ ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), 400);
+ return fd->weight;
+}
+
+void TextServerFallback::_font_set_stretch(const RID &p_font_rid, int64_t p_stretch) {
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
+ ERR_FAIL_COND(!fd);
+
+ MutexLock lock(fd->mutex);
+ Vector2i size = _get_size(fd, 16);
+ ERR_FAIL_COND(!_ensure_cache_for_size(fd, size));
+ fd->stretch = CLAMP(p_stretch, 50, 200);
+}
+
+int64_t TextServerFallback::_font_get_stretch(const RID &p_font_rid) const {
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
+ ERR_FAIL_COND_V(!fd, 100);
+
+ MutexLock lock(fd->mutex);
+ Vector2i size = _get_size(fd, 16);
+ ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), 100);
+ return fd->stretch;
+}
+
void TextServerFallback::_font_set_name(const RID &p_font_rid, const String &p_name) {
FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
@@ -1185,6 +1241,22 @@ int64_t TextServerFallback::_font_get_fixed_size(const RID &p_font_rid) const {
return fd->fixed_size;
}
+void TextServerFallback::_font_set_allow_system_fallback(const RID &p_font_rid, bool p_allow_system_fallback) {
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
+ ERR_FAIL_COND(!fd);
+
+ MutexLock lock(fd->mutex);
+ fd->allow_system_fallback = p_allow_system_fallback;
+}
+
+bool TextServerFallback::_font_is_allow_system_fallback(const RID &p_font_rid) const {
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
+ ERR_FAIL_COND_V(!fd, false);
+
+ MutexLock lock(fd->mutex);
+ return fd->allow_system_fallback;
+}
+
void TextServerFallback::_font_set_force_autohinter(const RID &p_font_rid, bool p_force_autohinter) {
FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
@@ -2287,7 +2359,7 @@ void TextServerFallback::_font_draw_glyph(const RID &p_font_rid, const RID &p_ca
Point2 cpos = p_pos;
cpos += gl.rect.position * (double)p_size / (double)fd->msdf_source_size;
Size2 csize = gl.rect.size * (double)p_size / (double)fd->msdf_source_size;
- RenderingServer::get_singleton()->canvas_item_add_msdf_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate, 0, fd->msdf_range);
+ RenderingServer::get_singleton()->canvas_item_add_msdf_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate, 0, fd->msdf_range, (double)p_size / (double)fd->msdf_source_size);
} else {
Point2 cpos = p_pos;
double scale = _font_get_scale(p_font_rid, p_size);
@@ -2379,7 +2451,7 @@ void TextServerFallback::_font_draw_glyph_outline(const RID &p_font_rid, const R
Point2 cpos = p_pos;
cpos += gl.rect.position * (double)p_size / (double)fd->msdf_source_size;
Size2 csize = gl.rect.size * (double)p_size / (double)fd->msdf_source_size;
- RenderingServer::get_singleton()->canvas_item_add_msdf_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate, p_outline_size * 2, fd->msdf_range);
+ RenderingServer::get_singleton()->canvas_item_add_msdf_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate, p_outline_size, fd->msdf_range, (double)p_size / (double)fd->msdf_source_size);
} else {
Point2 cpos = p_pos;
double scale = _font_get_scale(p_font_rid, p_size);
@@ -2845,7 +2917,7 @@ bool TextServerFallback::_shaped_text_add_string(const RID &p_shaped, const Stri
return true;
}
-bool TextServerFallback::_shaped_text_add_object(const RID &p_shaped, const Variant &p_key, const Size2 &p_size, InlineAlignment p_inline_align, int64_t p_length) {
+bool TextServerFallback::_shaped_text_add_object(const RID &p_shaped, const Variant &p_key, const Size2 &p_size, InlineAlignment p_inline_align, int64_t p_length, float p_baseline) {
ShapedTextDataFallback *sd = shaped_owner.get_or_null(p_shaped);
ERR_FAIL_COND_V(!sd, false);
@@ -2866,6 +2938,7 @@ bool TextServerFallback::_shaped_text_add_object(const RID &p_shaped, const Vari
obj.inline_align = p_inline_align;
obj.rect.size = p_size;
obj.pos = span.start;
+ obj.baseline = p_baseline;
sd->spans.push_back(span);
sd->text = sd->text + String::chr(0xfffc).repeat(p_length);
@@ -2876,7 +2949,7 @@ bool TextServerFallback::_shaped_text_add_object(const RID &p_shaped, const Vari
return true;
}
-bool TextServerFallback::_shaped_text_resize_object(const RID &p_shaped, const Variant &p_key, const Size2 &p_size, InlineAlignment p_inline_align) {
+bool TextServerFallback::_shaped_text_resize_object(const RID &p_shaped, const Variant &p_key, const Size2 &p_size, InlineAlignment p_inline_align, float p_baseline) {
ShapedTextDataFallback *sd = shaped_owner.get_or_null(p_shaped);
ERR_FAIL_COND_V(!sd, false);
@@ -2884,6 +2957,7 @@ bool TextServerFallback::_shaped_text_resize_object(const RID &p_shaped, const V
ERR_FAIL_COND_V(!sd->objects.has(p_key), false);
sd->objects[p_key].rect.size = p_size;
sd->objects[p_key].inline_align = p_inline_align;
+ sd->objects[p_key].baseline = p_baseline;
if (sd->valid) {
// Recalc string metrics.
sd->ascent = 0;
@@ -2970,6 +3044,9 @@ void TextServerFallback::_realign(ShapedTextDataFallback *p_sd) const {
case INLINE_ALIGNMENT_CENTER_TO: {
E.value.rect.position.y -= E.value.rect.size.y / 2;
} break;
+ case INLINE_ALIGNMENT_BASELINE_TO: {
+ E.value.rect.position.y -= E.value.baseline;
+ } break;
case INLINE_ALIGNMENT_TOP_TO: {
// NOP
} break;
@@ -2998,6 +3075,9 @@ void TextServerFallback::_realign(ShapedTextDataFallback *p_sd) const {
case INLINE_ALIGNMENT_CENTER_TO: {
E.value.rect.position.x -= E.value.rect.size.x / 2;
} break;
+ case INLINE_ALIGNMENT_BASELINE_TO: {
+ E.value.rect.position.x -= E.value.baseline;
+ } break;
case INLINE_ALIGNMENT_TOP_TO: {
// NOP
} break;
@@ -3591,6 +3671,7 @@ bool TextServerFallback::_shaped_text_shape(const RID &p_shaped) {
sd->glyphs.push_back(gl);
} else {
// Text span.
+ RID prev_font;
for (int j = span.start; j < span.end; j++) {
Glyph gl;
gl.start = j;
@@ -3611,6 +3692,170 @@ bool TextServerFallback::_shaped_text_shape(const RID &p_shaped) {
break;
}
}
+ if (!gl.font_rid.is_valid() && prev_font.is_valid()) {
+ if (_font_has_char(prev_font, gl.index)) {
+ gl.font_rid = prev_font;
+ }
+ }
+ if (!gl.font_rid.is_valid() && OS::get_singleton()->has_feature("system_fonts") && span.fonts.size() > 0) {
+ // Try system fallback.
+ RID fdef = span.fonts[0];
+ if (_font_is_allow_system_fallback(fdef)) {
+ String text = sd->text.substr(j, 1);
+ String font_name = _font_get_name(fdef);
+ BitField<FontStyle> font_style = _font_get_style(fdef);
+ int font_weight = _font_get_weight(fdef);
+ int font_stretch = _font_get_stretch(fdef);
+ Dictionary dvar = _font_get_variation_coordinates(fdef);
+ static int64_t wgth_tag = _name_to_tag("weight");
+ static int64_t wdth_tag = _name_to_tag("width");
+ static int64_t ital_tag = _name_to_tag("italic");
+ if (dvar.has(wgth_tag)) {
+ font_weight = dvar[wgth_tag].operator int();
+ }
+ if (dvar.has(wdth_tag)) {
+ font_stretch = dvar[wdth_tag].operator int();
+ }
+ if (dvar.has(ital_tag) && dvar[ital_tag].operator int() == 1) {
+ font_style.set_flag(TextServer::FONT_ITALIC);
+ }
+
+ String locale = (span.language.is_empty()) ? TranslationServer::get_singleton()->get_tool_locale() : span.language;
+
+ PackedStringArray fallback_font_name = OS::get_singleton()->get_system_font_path_for_text(font_name, text, locale, String(), font_weight, font_stretch, font_style & TextServer::FONT_ITALIC);
+#ifdef GDEXTENSION
+ for (int fb = 0; fb < fallback_font_name.size(); fb++) {
+ const String &E = fallback_font_name[fb];
+#else
+ for (const String &E : fallback_font_name) {
+#endif
+ SystemFontKey key = SystemFontKey(E, font_style & TextServer::FONT_ITALIC, font_weight, font_stretch, fdef, this);
+ if (system_fonts.has(key)) {
+ const SystemFontCache &sysf_cache = system_fonts[key];
+ int best_score = 0;
+ int best_match = -1;
+ for (int face_idx = 0; face_idx < sysf_cache.var.size(); face_idx++) {
+ const SystemFontCacheRec &F = sysf_cache.var[face_idx];
+ if (unlikely(!_font_has_char(F.rid, text[0]))) {
+ continue;
+ }
+ BitField<FontStyle> style = _font_get_style(F.rid);
+ int weight = _font_get_weight(F.rid);
+ int stretch = _font_get_stretch(F.rid);
+ int score = (20 - Math::abs(weight - font_weight) / 50);
+ score += (20 - Math::abs(stretch - font_stretch) / 10);
+ if (bool(style & TextServer::FONT_ITALIC) == bool(font_style & TextServer::FONT_ITALIC)) {
+ score += 30;
+ }
+ if (score >= best_score) {
+ best_score = score;
+ best_match = face_idx;
+ }
+ if (best_score == 70) {
+ break;
+ }
+ }
+ if (best_match != -1) {
+ gl.font_rid = sysf_cache.var[best_match].rid;
+ }
+ }
+ if (!gl.font_rid.is_valid()) {
+ if (system_fonts.has(key)) {
+ const SystemFontCache &sysf_cache = system_fonts[key];
+ if (sysf_cache.max_var == sysf_cache.var.size()) {
+ // All subfonts already tested, skip.
+ continue;
+ }
+ }
+
+ if (!system_font_data.has(E)) {
+ system_font_data[E] = FileAccess::get_file_as_bytes(E);
+ }
+
+ const PackedByteArray &font_data = system_font_data[E];
+
+ SystemFontCacheRec sysf;
+ sysf.rid = _create_font();
+ _font_set_data_ptr(sysf.rid, font_data.ptr(), font_data.size());
+
+ Dictionary var = dvar;
+ // Select matching style from collection.
+ int best_score = 0;
+ int best_match = -1;
+ for (int face_idx = 0; face_idx < _font_get_face_count(sysf.rid); face_idx++) {
+ _font_set_face_index(sysf.rid, face_idx);
+ if (unlikely(!_font_has_char(sysf.rid, text[0]))) {
+ continue;
+ }
+ BitField<FontStyle> style = _font_get_style(sysf.rid);
+ int weight = _font_get_weight(sysf.rid);
+ int stretch = _font_get_stretch(sysf.rid);
+ int score = (20 - Math::abs(weight - font_weight) / 50);
+ score += (20 - Math::abs(stretch - font_stretch) / 10);
+ if (bool(style & TextServer::FONT_ITALIC) == bool(font_style & TextServer::FONT_ITALIC)) {
+ score += 30;
+ }
+ if (score >= best_score) {
+ best_score = score;
+ best_match = face_idx;
+ }
+ if (best_score == 70) {
+ break;
+ }
+ }
+ if (best_match == -1) {
+ _free_rid(sysf.rid);
+ continue;
+ } else {
+ _font_set_face_index(sysf.rid, best_match);
+ }
+ sysf.index = best_match;
+
+ // If it's a variable font, apply weight, stretch and italic coordinates to match requested style.
+ if (best_score != 70) {
+ Dictionary ftr = _font_supported_variation_list(sysf.rid);
+ if (ftr.has(wdth_tag)) {
+ var[wdth_tag] = font_stretch;
+ _font_set_stretch(sysf.rid, font_stretch);
+ }
+ if (ftr.has(wgth_tag)) {
+ var[wgth_tag] = font_weight;
+ _font_set_weight(sysf.rid, font_weight);
+ }
+ if ((font_style & TextServer::FONT_ITALIC) && ftr.has(ital_tag)) {
+ var[ital_tag] = 1;
+ _font_set_style(sysf.rid, _font_get_style(sysf.rid) | TextServer::FONT_ITALIC);
+ }
+ }
+
+ _font_set_antialiasing(sysf.rid, key.antialiasing);
+ _font_set_generate_mipmaps(sysf.rid, key.mipmaps);
+ _font_set_multichannel_signed_distance_field(sysf.rid, key.msdf);
+ _font_set_msdf_pixel_range(sysf.rid, key.msdf_range);
+ _font_set_msdf_size(sysf.rid, key.msdf_source_size);
+ _font_set_fixed_size(sysf.rid, key.fixed_size);
+ _font_set_force_autohinter(sysf.rid, key.force_autohinter);
+ _font_set_hinting(sysf.rid, key.hinting);
+ _font_set_subpixel_positioning(sysf.rid, key.subpixel_positioning);
+ _font_set_variation_coordinates(sysf.rid, var);
+ _font_set_oversampling(sysf.rid, key.oversampling);
+ _font_set_embolden(sysf.rid, key.embolden);
+ _font_set_transform(sysf.rid, key.transform);
+
+ if (system_fonts.has(key)) {
+ system_fonts[key].var.push_back(sysf);
+ } else {
+ SystemFontCache &sysf_cache = system_fonts[key];
+ sysf_cache.max_var = _font_get_face_count(sysf.rid);
+ sysf_cache.var.push_back(sysf);
+ }
+ gl.font_rid = sysf.rid;
+ }
+ break;
+ }
+ }
+ }
+ prev_font = gl.font_rid;
double scale = _font_get_scale(gl.font_rid, gl.font_size);
if (gl.font_rid.is_valid()) {
@@ -3854,26 +4099,69 @@ String TextServerFallback::_string_to_lower(const String &p_string, const String
return lower;
}
-PackedInt32Array TextServerFallback::_string_get_word_breaks(const String &p_string, const String &p_language) const {
+PackedInt32Array TextServerFallback::_string_get_word_breaks(const String &p_string, const String &p_language, int p_chars_per_line) const {
PackedInt32Array ret;
+
+ int line_start = 0;
+ int line_end = 0; // End of last word on current line.
+ int word_start = 0; // -1 if no word encountered. Leading spaces are part of a word.
+ int word_length = 0;
+
for (int i = 0; i < p_string.length(); i++) {
- char32_t c = p_string[i];
- if (c == 0xfffc) {
- continue;
- }
- if (is_punct(c) && c != 0x005F) {
- ret.push_back(i);
- continue;
- }
- if (is_underscore(c)) {
- ret.push_back(i);
- continue;
- }
- if (is_whitespace(c) || is_linebreak(c)) {
+ const char32_t c = p_string[i];
+
+ if (is_linebreak(c)) {
+ // Force newline.
+ ret.push_back(line_start);
ret.push_back(i);
+ line_start = i + 1;
+ line_end = line_start;
+ word_start = line_start;
+ word_length = 0;
+ } else if (c == 0xfffc) {
continue;
+ } else if ((is_punct(c) && c != 0x005F) || is_underscore(c) || c == '\t' || is_whitespace(c)) {
+ // A whitespace ends current word.
+ if (word_length > 0) {
+ line_end = i - 1;
+ word_start = -1;
+ word_length = 0;
+ }
+ } else {
+ if (word_start == -1) {
+ word_start = i;
+ if (p_chars_per_line <= 0) {
+ ret.push_back(line_start);
+ ret.push_back(line_end + 1);
+ line_start = word_start;
+ line_end = line_start;
+ }
+ }
+ word_length += 1;
+
+ if (p_chars_per_line > 0) {
+ if (word_length > p_chars_per_line) {
+ // Word too long: wrap before current character.
+ ret.push_back(line_start);
+ ret.push_back(i);
+ line_start = i;
+ line_end = i;
+ word_start = i;
+ word_length = 1;
+ } else if (i - line_start + 1 > p_chars_per_line) {
+ // Line too long: wrap after the last word.
+ ret.push_back(line_start);
+ ret.push_back(line_end + 1);
+ line_start = word_start;
+ line_end = line_start;
+ }
+ }
}
}
+ if (line_start < p_string.length()) {
+ ret.push_back(line_start);
+ ret.push_back(p_string.length());
+ }
return ret;
}
@@ -3881,6 +4169,17 @@ TextServerFallback::TextServerFallback() {
_insert_feature_sets();
};
+void TextServerFallback::_cleanup() {
+ for (const KeyValue<SystemFontKey, SystemFontCache> &E : system_fonts) {
+ const Vector<SystemFontCacheRec> &sysf_cache = E.value.var;
+ for (const SystemFontCacheRec &F : sysf_cache) {
+ _free_rid(F.rid);
+ }
+ }
+ system_fonts.clear();
+ system_font_data.clear();
+}
+
TextServerFallback::~TextServerFallback() {
#ifdef MODULE_FREETYPE_ENABLED
if (ft_library != nullptr) {
diff --git a/modules/text_server_fb/text_server_fb.h b/modules/text_server_fb/text_server_fb.h
index 151ae13904..49e89214ec 100644
--- a/modules/text_server_fb/text_server_fb.h
+++ b/modules/text_server_fb/text_server_fb.h
@@ -87,7 +87,7 @@ using namespace godot;
#include "core/templates/rid_owner.h"
#include "scene/resources/texture.h"
-#include "modules/modules_enabled.gen.h" // For freetype, msdfgen.
+#include "modules/modules_enabled.gen.h" // For freetype, msdfgen, svg.
#endif
@@ -101,6 +101,7 @@ using namespace godot;
#include FT_ADVANCES_H
#include FT_MULTIPLE_MASTERS_H
#include FT_BBOX_H
+#include FT_MODULE_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.
@@ -255,6 +256,7 @@ class TextServerFallback : public TextServerExtension {
int msdf_source_size = 48;
int fixed_size = 0;
bool force_autohinter = false;
+ bool allow_system_fallback = true;
TextServer::Hinting hinting = TextServer::HINTING_LIGHT;
TextServer::SubpixelPositioning subpixel_positioning = TextServer::SUBPIXEL_POSITIONING_AUTO;
Dictionary variation_coordinates;
@@ -265,6 +267,8 @@ class TextServerFallback : public TextServerExtension {
BitField<TextServer::FontStyle> style_flags = 0;
String font_name;
String style_name;
+ int weight = 400;
+ int stretch = 100;
HashMap<Vector2i, FontForSizeFallback *, VariantHasher, VariantComparator> cache;
@@ -321,6 +325,58 @@ class TextServerFallback : public TextServerExtension {
}
}
+ _FORCE_INLINE_ int _font_get_weight_by_name(const String &p_sty_name) const {
+ String sty_name = p_sty_name.replace(" ", "").replace("-", "");
+ if (sty_name.find("thin") >= 0 || sty_name.find("hairline") >= 0) {
+ return 100;
+ } else if (sty_name.find("extralight") >= 0 || sty_name.find("ultralight") >= 0) {
+ return 200;
+ } else if (sty_name.find("light") >= 0) {
+ return 300;
+ } else if (sty_name.find("semilight") >= 0) {
+ return 350;
+ } else if (sty_name.find("regular") >= 0) {
+ return 400;
+ } else if (sty_name.find("medium") >= 0) {
+ return 500;
+ } else if (sty_name.find("semibold") >= 0 || sty_name.find("demibold") >= 0) {
+ return 600;
+ } else if (sty_name.find("bold") >= 0) {
+ return 700;
+ } else if (sty_name.find("extrabold") >= 0 || sty_name.find("ultrabold") >= 0) {
+ return 800;
+ } else if (sty_name.find("black") >= 0 || sty_name.find("heavy") >= 0) {
+ return 900;
+ } else if (sty_name.find("extrablack") >= 0 || sty_name.find("ultrablack") >= 0) {
+ return 950;
+ }
+ return 400;
+ }
+ _FORCE_INLINE_ int _font_get_stretch_by_name(const String &p_sty_name) const {
+ String sty_name = p_sty_name.replace(" ", "").replace("-", "");
+ if (sty_name.find("ultracondensed") >= 0) {
+ return 50;
+ } else if (sty_name.find("extracondensed") >= 0) {
+ return 63;
+ } else if (sty_name.find("condensed") >= 0) {
+ return 75;
+ } else if (sty_name.find("semicondensed") >= 0) {
+ return 87;
+ } else if (sty_name.find("semiexpanded") >= 0) {
+ return 113;
+ } else if (sty_name.find("expanded") >= 0) {
+ return 125;
+ } else if (sty_name.find("extraexpanded") >= 0) {
+ return 150;
+ } else if (sty_name.find("ultraexpanded") >= 0) {
+ return 200;
+ }
+ return 100;
+ }
+ _FORCE_INLINE_ bool _is_ital_style(const String &p_sty_name) const {
+ return (p_sty_name.find("italic") >= 0) || (p_sty_name.find("oblique") >= 0);
+ }
+
// Shaped text cache data.
struct TrimData {
int trim_pos = -1;
@@ -361,6 +417,7 @@ class TextServerFallback : public TextServerExtension {
int pos = 0;
InlineAlignment inline_align = INLINE_ALIGNMENT_CENTER;
Rect2 rect;
+ float baseline = 0;
};
HashMap<Variant, EmbeddedObject, VariantHasher, VariantComparator> objects;
@@ -397,6 +454,81 @@ class TextServerFallback : public TextServerExtension {
mutable RID_PtrOwner<FontFallback> font_owner;
mutable RID_PtrOwner<ShapedTextDataFallback> shaped_owner;
+ struct SystemFontKey {
+ String font_name;
+ TextServer::FontAntialiasing antialiasing = TextServer::FONT_ANTIALIASING_GRAY;
+ bool italic = false;
+ bool mipmaps = false;
+ bool msdf = false;
+ bool force_autohinter = false;
+ int weight = 400;
+ int stretch = 100;
+ int msdf_range = 14;
+ int msdf_source_size = 48;
+ int fixed_size = 0;
+ TextServer::Hinting hinting = TextServer::HINTING_LIGHT;
+ TextServer::SubpixelPositioning subpixel_positioning = TextServer::SUBPIXEL_POSITIONING_AUTO;
+ Dictionary variation_coordinates;
+ double oversampling = 0.0;
+ double embolden = 0.0;
+ Transform2D transform;
+
+ bool operator==(const SystemFontKey &p_b) const {
+ return (font_name == p_b.font_name) && (antialiasing == p_b.antialiasing) && (italic == p_b.italic) && (mipmaps == p_b.mipmaps) && (msdf == p_b.msdf) && (force_autohinter == p_b.force_autohinter) && (weight == p_b.weight) && (stretch == p_b.stretch) && (msdf_range == p_b.msdf_range) && (msdf_source_size == p_b.msdf_source_size) && (fixed_size == p_b.fixed_size) && (hinting == p_b.hinting) && (subpixel_positioning == p_b.subpixel_positioning) && (variation_coordinates == p_b.variation_coordinates) && (oversampling == p_b.oversampling) && (embolden == p_b.embolden) && (transform == p_b.transform);
+ }
+
+ SystemFontKey(const String &p_font_name, bool p_italic, int p_weight, int p_stretch, RID p_font, const TextServerFallback *p_fb) {
+ font_name = p_font_name;
+ italic = p_italic;
+ weight = p_weight;
+ stretch = p_stretch;
+ antialiasing = p_fb->_font_get_antialiasing(p_font);
+ mipmaps = p_fb->_font_get_generate_mipmaps(p_font);
+ msdf = p_fb->_font_is_multichannel_signed_distance_field(p_font);
+ msdf_range = p_fb->_font_get_msdf_pixel_range(p_font);
+ msdf_source_size = p_fb->_font_get_msdf_size(p_font);
+ fixed_size = p_fb->_font_get_fixed_size(p_font);
+ force_autohinter = p_fb->_font_is_force_autohinter(p_font);
+ hinting = p_fb->_font_get_hinting(p_font);
+ subpixel_positioning = p_fb->_font_get_subpixel_positioning(p_font);
+ variation_coordinates = p_fb->_font_get_variation_coordinates(p_font);
+ oversampling = p_fb->_font_get_oversampling(p_font);
+ embolden = p_fb->_font_get_embolden(p_font);
+ transform = p_fb->_font_get_transform(p_font);
+ }
+ };
+
+ struct SystemFontCacheRec {
+ RID rid;
+ int index = 0;
+ };
+
+ struct SystemFontCache {
+ Vector<SystemFontCacheRec> var;
+ int max_var = 0;
+ };
+
+ struct SystemFontKeyHasher {
+ _FORCE_INLINE_ static uint32_t hash(const SystemFontKey &p_a) {
+ uint32_t hash = p_a.font_name.hash();
+ hash = hash_murmur3_one_32(p_a.variation_coordinates.hash(), hash);
+ hash = hash_murmur3_one_32(p_a.weight, hash);
+ hash = hash_murmur3_one_32(p_a.stretch, hash);
+ hash = hash_murmur3_one_32(p_a.msdf_range, hash);
+ hash = hash_murmur3_one_32(p_a.msdf_source_size, hash);
+ hash = hash_murmur3_one_32(p_a.fixed_size, hash);
+ hash = hash_murmur3_one_double(p_a.oversampling, hash);
+ hash = hash_murmur3_one_double(p_a.embolden, hash);
+ hash = hash_murmur3_one_real(p_a.transform[0].x, hash);
+ hash = hash_murmur3_one_real(p_a.transform[0].y, hash);
+ hash = hash_murmur3_one_real(p_a.transform[1].x, hash);
+ hash = hash_murmur3_one_real(p_a.transform[1].y, hash);
+ return hash_fmix32(hash_murmur3_one_32(((int)p_a.mipmaps) | ((int)p_a.msdf << 1) | ((int)p_a.italic << 2) | ((int)p_a.force_autohinter << 3) | ((int)p_a.hinting << 4) | ((int)p_a.subpixel_positioning << 8) | ((int)p_a.antialiasing << 12), hash));
+ }
+ };
+ mutable HashMap<SystemFontKey, SystemFontCache, SystemFontKeyHasher> system_fonts;
+ mutable HashMap<String, PackedByteArray> system_font_data;
+
void _realign(ShapedTextDataFallback *p_sd) const;
protected:
@@ -441,6 +573,12 @@ public:
MODBIND2(font_set_style_name, const RID &, const String &);
MODBIND1RC(String, font_get_style_name, const RID &);
+ MODBIND2(font_set_weight, const RID &, int64_t);
+ MODBIND1RC(int64_t, font_get_weight, const RID &);
+
+ MODBIND2(font_set_stretch, const RID &, int64_t);
+ MODBIND1RC(int64_t, font_get_stretch, const RID &);
+
MODBIND2(font_set_name, const RID &, const String &);
MODBIND1RC(String, font_get_name, const RID &);
@@ -462,6 +600,9 @@ public:
MODBIND2(font_set_fixed_size, const RID &, int64_t);
MODBIND1RC(int64_t, font_get_fixed_size, const RID &);
+ MODBIND2(font_set_allow_system_fallback, const RID &, bool);
+ MODBIND1RC(bool, font_is_allow_system_fallback, const RID &);
+
MODBIND2(font_set_force_autohinter, const RID &, bool);
MODBIND1RC(bool, font_is_force_autohinter, const RID &);
@@ -603,8 +744,8 @@ public:
MODBIND2RC(int64_t, shaped_text_get_spacing, const RID &, SpacingType);
MODBIND7R(bool, shaped_text_add_string, const RID &, const String &, const TypedArray<RID> &, int64_t, const Dictionary &, const String &, const Variant &);
- MODBIND5R(bool, shaped_text_add_object, const RID &, const Variant &, const Size2 &, InlineAlignment, int64_t);
- MODBIND4R(bool, shaped_text_resize_object, const RID &, const Variant &, const Size2 &, InlineAlignment);
+ MODBIND6R(bool, shaped_text_add_object, const RID &, const Variant &, const Size2 &, InlineAlignment, int64_t, float);
+ MODBIND5R(bool, shaped_text_resize_object, const RID &, const Variant &, const Size2 &, InlineAlignment, float);
MODBIND1RC(int64_t, shaped_get_span_count, const RID &);
MODBIND2RC(Variant, shaped_get_span_meta, const RID &, int64_t);
@@ -645,11 +786,13 @@ public:
MODBIND1RC(double, shaped_text_get_underline_position, const RID &);
MODBIND1RC(double, shaped_text_get_underline_thickness, const RID &);
- MODBIND2RC(PackedInt32Array, string_get_word_breaks, const String &, const String &);
+ MODBIND3RC(PackedInt32Array, string_get_word_breaks, const String &, const String &, int);
MODBIND2RC(String, string_to_upper, const String &, const String &);
MODBIND2RC(String, string_to_lower, const String &, const String &);
+ MODBIND0(cleanup);
+
TextServerFallback();
~TextServerFallback();
};
diff --git a/modules/text_server_fb/thorvg_bounds_iterator.cpp b/modules/text_server_fb/thorvg_bounds_iterator.cpp
new file mode 100644
index 0000000000..54a6136134
--- /dev/null
+++ b/modules/text_server_fb/thorvg_bounds_iterator.cpp
@@ -0,0 +1,70 @@
+/*************************************************************************/
+/* thorvg_bounds_iterator.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 GDEXTENSION
+// Headers for building as GDExtension plug-in.
+
+#include <godot_cpp/godot.hpp>
+
+using namespace godot;
+
+#else
+// Headers for building as built-in module.
+
+#include "core/typedefs.h"
+
+#include "modules/modules_enabled.gen.h" // For svg.
+#endif
+
+#ifdef MODULE_SVG_ENABLED
+
+#include "thorvg_bounds_iterator.h"
+
+#include <tvgIteratorAccessor.h>
+#include <tvgPaint.h>
+
+// This function uses private ThorVG API to get bounding box of top level children elements.
+
+void tvg_get_bounds(tvg::Picture *p_picture, float &r_min_x, float &r_min_y, float &r_max_x, float &r_max_y) {
+ tvg::IteratorAccessor itrAccessor;
+ if (tvg::Iterator *it = itrAccessor.iterator(p_picture)) {
+ while (const tvg::Paint *child = it->next()) {
+ float x = 0, y = 0, w = 0, h = 0;
+ child->bounds(&x, &y, &w, &h, true);
+ r_min_x = MIN(x, r_min_x);
+ r_min_y = MIN(y, r_min_y);
+ r_max_x = MAX(x + w, r_max_x);
+ r_max_y = MAX(y + h, r_max_y);
+ }
+ delete (it);
+ }
+}
+
+#endif // MODULE_SVG_ENABLED
diff --git a/modules/text_server_fb/thorvg_bounds_iterator.h b/modules/text_server_fb/thorvg_bounds_iterator.h
new file mode 100644
index 0000000000..e54e30eaa2
--- /dev/null
+++ b/modules/text_server_fb/thorvg_bounds_iterator.h
@@ -0,0 +1,58 @@
+/*************************************************************************/
+/* thorvg_bounds_iterator.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 THORVG_BOUNDS_ITERATOR_H
+#define THORVG_BOUNDS_ITERATOR_H
+
+#ifdef GDEXTENSION
+// Headers for building as GDExtension plug-in.
+
+#include <godot_cpp/core/mutex_lock.hpp>
+#include <godot_cpp/godot.hpp>
+
+using namespace godot;
+
+#else
+// Headers for building as built-in module.
+
+#include "core/typedefs.h"
+
+#include "modules/modules_enabled.gen.h" // For svg.
+#endif
+
+#ifdef MODULE_SVG_ENABLED
+
+#include <thorvg.h>
+
+void tvg_get_bounds(tvg::Picture *p_picture, float &r_min_x, float &r_min_y, float &r_max_x, float &r_max_y);
+
+#endif // MODULE_SVG_ENABLED
+
+#endif // THORVG_BOUNDS_ITERATOR_H
diff --git a/modules/text_server_fb/thorvg_svg_in_ot.cpp b/modules/text_server_fb/thorvg_svg_in_ot.cpp
new file mode 100644
index 0000000000..7863ab67fa
--- /dev/null
+++ b/modules/text_server_fb/thorvg_svg_in_ot.cpp
@@ -0,0 +1,320 @@
+/*************************************************************************/
+/* thorvg_svg_in_ot.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 GDEXTENSION
+// Headers for building as GDExtension plug-in.
+
+#include <godot_cpp/classes/xml_parser.hpp>
+#include <godot_cpp/core/mutex_lock.hpp>
+#include <godot_cpp/godot.hpp>
+#include <godot_cpp/templates/vector.hpp>
+
+using namespace godot;
+
+#else
+// Headers for building as built-in module.
+
+#include "core/error/error_macros.h"
+#include "core/io/xml_parser.h"
+#include "core/os/memory.h"
+#include "core/os/os.h"
+#include "core/string/ustring.h"
+#include "core/typedefs.h"
+#include "core/variant/variant.h"
+
+#include "modules/modules_enabled.gen.h" // For svg.
+#endif
+
+#ifdef MODULE_SVG_ENABLED
+
+#include "thorvg_bounds_iterator.h"
+#include "thorvg_svg_in_ot.h"
+
+#include <freetype/otsvg.h>
+#include <ft2build.h>
+
+#include <math.h>
+#include <stdlib.h>
+
+FT_Error tvg_svg_in_ot_init(FT_Pointer *p_state) {
+ *p_state = memnew(TVG_State);
+
+ return FT_Err_Ok;
+}
+
+void tvg_svg_in_ot_free(FT_Pointer *p_state) {
+ TVG_State *state = *reinterpret_cast<TVG_State **>(p_state);
+ memdelete(state);
+}
+
+FT_Error tvg_svg_in_ot_preset_slot(FT_GlyphSlot p_slot, FT_Bool p_cache, FT_Pointer *p_state) {
+ TVG_State *state = *reinterpret_cast<TVG_State **>(p_state);
+ if (!state) {
+ ERR_FAIL_V_MSG(FT_Err_Invalid_SVG_Document, "SVG in OT state not initialized.");
+ }
+ MutexLock lock(state->mutex);
+
+ FT_SVG_Document document = (FT_SVG_Document)p_slot->other;
+ FT_Size_Metrics metrics = document->metrics;
+
+ GL_State &gl_state = state->glyph_map[p_slot->glyph_index];
+ if (!gl_state.ready) {
+ Ref<XMLParser> parser;
+ parser.instantiate();
+#ifdef GDEXTENSION
+ PackedByteArray data;
+ data.resize(document->svg_document_length);
+ memcpy(data.ptrw(), document->svg_document, document->svg_document_length);
+ parser->open_buffer(data);
+#else
+ parser->_open_buffer((const uint8_t *)document->svg_document, document->svg_document_length);
+#endif
+
+ float aspect = 1.0f;
+ String xml_body;
+ while (parser->read() == OK) {
+ if (parser->has_attribute("id")) {
+#ifdef GDEXTENSION
+ const String &gl_name = parser->get_named_attribute_value("id");
+#else
+ const String &gl_name = parser->get_attribute_value("id");
+#endif
+ if (gl_name.begins_with("glyph")) {
+ int dot_pos = gl_name.find(".");
+ int64_t gl_idx = gl_name.substr(5, (dot_pos > 0) ? dot_pos - 5 : -1).to_int();
+ if (p_slot->glyph_index != gl_idx) {
+ parser->skip_section();
+ continue;
+ }
+ }
+ }
+ if (parser->get_node_type() == XMLParser::NODE_ELEMENT && parser->get_node_name() == "svg") {
+ if (parser->has_attribute("viewBox")) {
+#ifdef GDEXTENSION
+ PackedStringArray vb = parser->get_named_attribute_value("viewBox").split(" ");
+#else
+ Vector<String> vb = parser->get_attribute_value("viewBox").split(" ");
+#endif
+
+ if (vb.size() == 4) {
+ aspect = vb[2].to_float() / vb[3].to_float();
+ }
+ }
+ continue;
+ }
+#ifdef GDEXTENSION
+ if (parser->get_node_type() == XMLParser::NODE_ELEMENT) {
+ xml_body = xml_body + "<" + parser->get_node_name();
+ for (int i = 0; i < parser->get_attribute_count(); i++) {
+ xml_body = xml_body + " " + parser->get_attribute_name(i) + "=\"" + parser->get_attribute_value(i) + "\"";
+ }
+ xml_body = xml_body + ">";
+ } else if (parser->get_node_type() == XMLParser::NODE_TEXT) {
+ xml_body = xml_body + parser->get_node_data();
+ } else if (parser->get_node_type() == XMLParser::NODE_ELEMENT_END) {
+ xml_body = xml_body + "</" + parser->get_node_name() + ">";
+ }
+#else
+ if (parser->get_node_type() == XMLParser::NODE_ELEMENT) {
+ xml_body += vformat("<%s", parser->get_node_name());
+ for (int i = 0; i < parser->get_attribute_count(); i++) {
+ xml_body += vformat(" %s=\"%s\"", parser->get_attribute_name(i), parser->get_attribute_value(i));
+ }
+ xml_body += ">";
+ } else if (parser->get_node_type() == XMLParser::NODE_TEXT) {
+ xml_body += parser->get_node_data();
+ } else if (parser->get_node_type() == XMLParser::NODE_ELEMENT_END) {
+ xml_body += vformat("</%s>", parser->get_node_name());
+ }
+#endif
+ }
+ String temp_xml = "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 0 0\">" + xml_body;
+
+ std::unique_ptr<tvg::Picture> picture = tvg::Picture::gen();
+ tvg::Result result = picture->load(temp_xml.utf8().get_data(), temp_xml.utf8().length(), "svg+xml", false);
+ if (result != tvg::Result::Success) {
+ ERR_FAIL_V_MSG(FT_Err_Invalid_SVG_Document, "Failed to load SVG document (bounds detection).");
+ }
+
+ float min_x = INFINITY, min_y = INFINITY, max_x = -INFINITY, max_y = -INFINITY;
+ tvg_get_bounds(picture.get(), min_x, min_y, max_x, max_y);
+
+ float new_h = (max_y - min_y);
+ float new_w = (max_x - min_x);
+
+ if (new_h * aspect >= new_w) {
+ new_w = (new_h * aspect);
+ } else {
+ new_h = (new_w / aspect);
+ }
+
+#ifdef GDEXTENSION
+ gl_state.xml_code = "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"" + rtos(min_x) + " " + rtos(min_y) + " " + rtos(new_w) + " " + rtos(new_h) + "\">" + xml_body;
+#else
+ gl_state.xml_code = vformat("<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"%f %f %f %f\">", min_x, min_y, new_w, new_h) + xml_body;
+#endif
+
+ picture = tvg::Picture::gen();
+ result = picture->load(gl_state.xml_code.utf8().get_data(), gl_state.xml_code.utf8().length(), "svg+xml", false);
+ if (result != tvg::Result::Success) {
+ ERR_FAIL_V_MSG(FT_Err_Invalid_SVG_Document, "Failed to load SVG document (glyph metrics).");
+ }
+
+ float x_svg_to_out, y_svg_to_out;
+ x_svg_to_out = (float)metrics.x_ppem / new_w;
+ y_svg_to_out = (float)metrics.y_ppem / new_h;
+
+ gl_state.m.e11 = (double)document->transform.xx / (1 << 16) * x_svg_to_out;
+ gl_state.m.e12 = -(double)document->transform.xy / (1 << 16) * x_svg_to_out;
+ gl_state.m.e21 = -(double)document->transform.yx / (1 << 16) * y_svg_to_out;
+ gl_state.m.e22 = (double)document->transform.yy / (1 << 16) * y_svg_to_out;
+ gl_state.m.e13 = (double)document->delta.x / 64 * new_w / metrics.x_ppem;
+ gl_state.m.e23 = -(double)document->delta.y / 64 * new_h / metrics.y_ppem;
+ gl_state.m.e31 = 0;
+ gl_state.m.e32 = 0;
+ gl_state.m.e33 = 1;
+
+ result = picture->transform(gl_state.m);
+ if (result != tvg::Result::Success) {
+ ERR_FAIL_V_MSG(FT_Err_Invalid_SVG_Document, "Failed to apply transform to SVG document.");
+ }
+
+ result = picture->bounds(&gl_state.x, &gl_state.y, &gl_state.w, &gl_state.h, true);
+ if (result != tvg::Result::Success) {
+ ERR_FAIL_V_MSG(FT_Err_Invalid_SVG_Document, "Failed to get SVG bounds.");
+ }
+
+ gl_state.bmp_y = -min_y * gl_state.h / new_h;
+ gl_state.bmp_x = min_x * gl_state.w / new_w;
+
+ gl_state.ready = true;
+ }
+
+ p_slot->bitmap_left = (FT_Int)gl_state.bmp_x;
+ p_slot->bitmap_top = (FT_Int)gl_state.bmp_y;
+
+ float tmp = ceil(gl_state.h);
+ p_slot->bitmap.rows = (unsigned int)tmp;
+ tmp = ceil(gl_state.w);
+ p_slot->bitmap.width = (unsigned int)tmp;
+ p_slot->bitmap.pitch = (int)p_slot->bitmap.width * 4;
+ p_slot->bitmap.pixel_mode = FT_PIXEL_MODE_BGRA;
+
+ float metrics_width, metrics_height;
+ float horiBearingX, horiBearingY;
+ float vertBearingX, vertBearingY;
+
+ metrics_width = (float)gl_state.w;
+ metrics_height = (float)gl_state.h;
+ horiBearingX = (float)gl_state.x;
+ horiBearingY = (float)-gl_state.y;
+ vertBearingX = p_slot->metrics.horiBearingX / 64.0f - p_slot->metrics.horiAdvance / 64.0f / 2;
+ vertBearingY = (p_slot->metrics.vertAdvance / 64.0f - p_slot->metrics.height / 64.0f) / 2;
+
+ tmp = roundf(metrics_width * 64);
+ p_slot->metrics.width = (FT_Pos)tmp;
+ tmp = roundf(metrics_height * 64);
+ p_slot->metrics.height = (FT_Pos)tmp;
+
+ p_slot->metrics.horiBearingX = (FT_Pos)(horiBearingX * 64);
+ p_slot->metrics.horiBearingY = (FT_Pos)(horiBearingY * 64);
+ p_slot->metrics.vertBearingX = (FT_Pos)(vertBearingX * 64);
+ p_slot->metrics.vertBearingY = (FT_Pos)(vertBearingY * 64);
+
+ if (p_slot->metrics.vertAdvance == 0) {
+ p_slot->metrics.vertAdvance = (FT_Pos)(metrics_height * 1.2f * 64);
+ }
+
+ return FT_Err_Ok;
+}
+
+FT_Error tvg_svg_in_ot_render(FT_GlyphSlot p_slot, FT_Pointer *p_state) {
+ TVG_State *state = *reinterpret_cast<TVG_State **>(p_state);
+ if (!state) {
+ ERR_FAIL_V_MSG(FT_Err_Invalid_SVG_Document, "SVG in OT state not initialized.");
+ }
+ MutexLock lock(state->mutex);
+
+ if (!state->glyph_map.has(p_slot->glyph_index)) {
+ ERR_FAIL_V_MSG(FT_Err_Invalid_SVG_Document, "SVG glyph not loaded.");
+ }
+
+ GL_State &gl_state = state->glyph_map[p_slot->glyph_index];
+ ERR_FAIL_COND_V_MSG(!gl_state.ready, FT_Err_Invalid_SVG_Document, "SVG glyph not ready.");
+
+ std::unique_ptr<tvg::Picture> picture = tvg::Picture::gen();
+ tvg::Result res = picture->load(gl_state.xml_code.utf8().get_data(), gl_state.xml_code.utf8().length(), "svg+xml", false);
+ if (res != tvg::Result::Success) {
+ ERR_FAIL_V_MSG(FT_Err_Invalid_SVG_Document, "Failed to load SVG document (glyph rendering).");
+ }
+ res = picture->transform(gl_state.m);
+ if (res != tvg::Result::Success) {
+ ERR_FAIL_V_MSG(FT_Err_Invalid_SVG_Document, "Failed to apply transform to SVG document.");
+ }
+
+ std::unique_ptr<tvg::SwCanvas> sw_canvas = tvg::SwCanvas::gen();
+ res = sw_canvas->target((uint32_t *)p_slot->bitmap.buffer, (int)p_slot->bitmap.width, (int)p_slot->bitmap.width, (int)p_slot->bitmap.rows, tvg::SwCanvas::ARGB8888_STRAIGHT);
+ if (res != tvg::Result::Success) {
+ ERR_FAIL_V_MSG(FT_Err_Invalid_Outline, "Failed to create SVG canvas.");
+ }
+ res = sw_canvas->push(std::move(picture));
+ if (res != tvg::Result::Success) {
+ ERR_FAIL_V_MSG(FT_Err_Invalid_Outline, "Failed to set SVG canvas source.");
+ }
+ res = sw_canvas->draw();
+ if (res != tvg::Result::Success) {
+ ERR_FAIL_V_MSG(FT_Err_Invalid_Outline, "Failed to draw to SVG canvas.");
+ }
+ res = sw_canvas->sync();
+ if (res != tvg::Result::Success) {
+ ERR_FAIL_V_MSG(FT_Err_Invalid_Outline, "Failed to sync SVG canvas.");
+ }
+
+ state->glyph_map.erase(p_slot->glyph_index);
+
+ p_slot->bitmap.pixel_mode = FT_PIXEL_MODE_BGRA;
+ p_slot->bitmap.num_grays = 256;
+ p_slot->format = FT_GLYPH_FORMAT_BITMAP;
+
+ return FT_Err_Ok;
+}
+
+SVG_RendererHooks tvg_svg_in_ot_hooks = {
+ (SVG_Lib_Init_Func)tvg_svg_in_ot_init,
+ (SVG_Lib_Free_Func)tvg_svg_in_ot_free,
+ (SVG_Lib_Render_Func)tvg_svg_in_ot_render,
+ (SVG_Lib_Preset_Slot_Func)tvg_svg_in_ot_preset_slot,
+};
+
+SVG_RendererHooks *get_tvg_svg_in_ot_hooks() {
+ return &tvg_svg_in_ot_hooks;
+}
+
+#endif // MODULE_SVG_ENABLED
diff --git a/modules/text_server_fb/thorvg_svg_in_ot.h b/modules/text_server_fb/thorvg_svg_in_ot.h
new file mode 100644
index 0000000000..b2816193d9
--- /dev/null
+++ b/modules/text_server_fb/thorvg_svg_in_ot.h
@@ -0,0 +1,86 @@
+/*************************************************************************/
+/* thorvg_svg_in_ot.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 THORVG_SVG_IN_OT_H
+#define THORVG_SVG_IN_OT_H
+
+#ifdef GDEXTENSION
+// Headers for building as GDExtension plug-in.
+
+#include <godot_cpp/core/mutex_lock.hpp>
+#include <godot_cpp/godot.hpp>
+#include <godot_cpp/templates/hash_map.hpp>
+
+using namespace godot;
+
+#else
+// Headers for building as built-in module.
+
+#include "core/os/mutex.h"
+#include "core/templates/hash_map.h"
+#include "core/typedefs.h"
+
+#include "modules/modules_enabled.gen.h" // For svg.
+#endif
+
+#ifdef MODULE_SVG_ENABLED
+
+#include <freetype/freetype.h>
+#include <freetype/otsvg.h>
+#include <ft2build.h>
+#include <thorvg.h>
+
+struct GL_State {
+ bool ready = false;
+ float bmp_x = 0;
+ float bmp_y = 0;
+ float x = 0;
+ float y = 0;
+ float w = 0;
+ float h = 0;
+ String xml_code;
+ tvg::Matrix m;
+};
+
+struct TVG_State {
+ Mutex mutex;
+ HashMap<uint32_t, GL_State> glyph_map;
+};
+
+FT_Error tvg_svg_in_ot_init(FT_Pointer *p_state);
+void tvg_svg_in_ot_free(FT_Pointer *p_state);
+FT_Error tvg_svg_in_ot_preset_slot(FT_GlyphSlot p_slot, FT_Bool p_cache, FT_Pointer *p_state);
+FT_Error tvg_svg_in_ot_render(FT_GlyphSlot p_slot, FT_Pointer *p_state);
+
+SVG_RendererHooks *get_tvg_svg_in_ot_hooks();
+
+#endif // MODULE_SVG_ENABLED
+
+#endif // THORVG_SVG_IN_OT_H
diff --git a/modules/theora/SCsub b/modules/theora/SCsub
index 6038ea086a..ca666050dd 100644
--- a/modules/theora/SCsub
+++ b/modules/theora/SCsub
@@ -15,7 +15,7 @@ if env["builtin_libtheora"]:
# "analyze.c",
# "apiwrapper.c",
"bitpack.c",
- "cpu.c",
+ # "collect.c",
# "decapiwrapper.c",
"decinfo.c",
"decode.c",
@@ -47,8 +47,12 @@ if env["builtin_libtheora"]:
"x86/mmxfrag.c",
"x86/mmxidct.c",
"x86/mmxstate.c",
+ # "x86/sse2encfrag.c",
# "x86/sse2fdct.c",
+ "x86/sse2idct.c",
+ "x86/x86cpu.c",
# "x86/x86enc.c",
+ # "x86/x86enquant.c"
"x86/x86state.c",
]
@@ -58,6 +62,7 @@ if env["builtin_libtheora"]:
"x86_vc/mmxfrag.c",
"x86_vc/mmxidct.c",
"x86_vc/mmxstate.c",
+ "x86_vc/x86cpu.c",
# "x86_vc/x86enc.c",
"x86_vc/x86state.c",
]
diff --git a/modules/vorbis/audio_stream_ogg_vorbis.cpp b/modules/vorbis/audio_stream_ogg_vorbis.cpp
index 792103cd31..63909257d9 100644
--- a/modules/vorbis/audio_stream_ogg_vorbis.cpp
+++ b/modules/vorbis/audio_stream_ogg_vorbis.cpp
@@ -438,9 +438,7 @@ void AudioStreamOggVorbis::maybe_update_info() {
}
if (i == 0) {
packet->b_o_s = 1;
- }
- if (i == 0) {
ERR_FAIL_COND(!vorbis_synthesis_idheader(packet));
}
diff --git a/modules/webp/webp_common.cpp b/modules/webp/webp_common.cpp
index af98788420..572a33653e 100644
--- a/modules/webp/webp_common.cpp
+++ b/modules/webp/webp_common.cpp
@@ -41,40 +41,21 @@ namespace WebPCommon {
Vector<uint8_t> _webp_lossy_pack(const Ref<Image> &p_image, float p_quality) {
ERR_FAIL_COND_V(p_image.is_null() || p_image->is_empty(), Vector<uint8_t>());
- Ref<Image> img = p_image->duplicate();
- if (img->detect_alpha()) {
- img->convert(Image::FORMAT_RGBA8);
- } else {
- img->convert(Image::FORMAT_RGB8);
- }
-
- Size2 s(img->get_width(), img->get_height());
- Vector<uint8_t> data = img->get_data();
- const uint8_t *r = data.ptr();
-
- uint8_t *dst_buff = nullptr;
- size_t dst_size = 0;
- if (img->get_format() == Image::FORMAT_RGB8) {
- dst_size = WebPEncodeRGB(r, s.width, s.height, 3 * s.width, CLAMP(p_quality * 100.0f, 0.0f, 100.0f), &dst_buff);
- } else {
- dst_size = WebPEncodeRGBA(r, s.width, s.height, 4 * s.width, CLAMP(p_quality * 100.0f, 0.0f, 100.0f), &dst_buff);
- }
-
- ERR_FAIL_COND_V(dst_size == 0, Vector<uint8_t>());
- Vector<uint8_t> dst;
- dst.resize(dst_size);
- uint8_t *w = dst.ptrw();
- memcpy(w, dst_buff, dst_size);
- WebPFree(dst_buff);
-
- return dst;
+ return _webp_packer(p_image, CLAMP(p_quality * 100.0f, 0.0f, 100.0f), false);
}
Vector<uint8_t> _webp_lossless_pack(const Ref<Image> &p_image) {
ERR_FAIL_COND_V(p_image.is_null() || p_image->is_empty(), Vector<uint8_t>());
- int compression_level = GLOBAL_GET("rendering/textures/lossless_compression/webp_compression_level");
- compression_level = CLAMP(compression_level, 0, 9);
+ float compression_factor = GLOBAL_GET("rendering/textures/webp_compression/lossless_compression_factor");
+ compression_factor = CLAMP(compression_factor, 0.0f, 100.0f);
+
+ return _webp_packer(p_image, compression_factor, true);
+}
+
+Vector<uint8_t> _webp_packer(const Ref<Image> &p_image, float p_quality, bool p_lossless) {
+ int compression_method = GLOBAL_GET("rendering/textures/webp_compression/compression_method");
+ compression_method = CLAMP(compression_method, 0, 6);
Ref<Image> img = p_image->duplicate();
if (img->detect_alpha()) {
@@ -87,16 +68,21 @@ Vector<uint8_t> _webp_lossless_pack(const Ref<Image> &p_image) {
Vector<uint8_t> data = img->get_data();
const uint8_t *r = data.ptr();
- // we need to use the more complex API in order to access the 'exact' flag...
+ // we need to use the more complex API in order to access specific flags...
WebPConfig config;
WebPPicture pic;
- if (!WebPConfigInit(&config) || !WebPConfigLosslessPreset(&config, compression_level) || !WebPPictureInit(&pic)) {
+ if (!WebPConfigInit(&config) || !WebPPictureInit(&pic)) {
ERR_FAIL_V(Vector<uint8_t>());
}
WebPMemoryWriter wrt;
- config.exact = 1;
+ if (p_lossless) {
+ config.lossless = 1;
+ config.exact = 1;
+ }
+ config.method = compression_method;
+ config.quality = p_quality;
pic.use_argb = 1;
pic.width = s.width;
pic.height = s.height;
diff --git a/modules/webp/webp_common.h b/modules/webp/webp_common.h
index 11bef40256..23b433ad79 100644
--- a/modules/webp/webp_common.h
+++ b/modules/webp/webp_common.h
@@ -37,6 +37,8 @@ namespace WebPCommon {
// Given an image, pack this data into a WebP file.
Vector<uint8_t> _webp_lossy_pack(const Ref<Image> &p_image, float p_quality);
Vector<uint8_t> _webp_lossless_pack(const Ref<Image> &p_image);
+// Helper function for those above.
+Vector<uint8_t> _webp_packer(const Ref<Image> &p_image, float p_quality, bool p_lossless);
// Given a WebP file, unpack it into an image.
Ref<Image> _webp_unpack(const Vector<uint8_t> &p_buffer);
Error webp_load_image_from_buffer(Image *p_image, const uint8_t *p_buffer, int p_buffer_len);
diff --git a/modules/webrtc/doc_classes/WebRTCDataChannel.xml b/modules/webrtc/doc_classes/WebRTCDataChannel.xml
index a9ba8a23de..a186631ca8 100644
--- a/modules/webrtc/doc_classes/WebRTCDataChannel.xml
+++ b/modules/webrtc/doc_classes/WebRTCDataChannel.xml
@@ -22,8 +22,8 @@
<method name="get_id" qualifiers="const">
<return type="int" />
<description>
- Returns the id assigned to this channel during creation (or auto-assigned during negotiation).
- If the channel is not negotiated out-of-band the id will only be available after the connection is established (will return [code]65535[/code] until then).
+ Returns the ID assigned to this channel during creation (or auto-assigned during negotiation).
+ If the channel is not negotiated out-of-band the ID will only be available after the connection is established (will return [code]65535[/code] until then).
</description>
</method>
<method name="get_label" qualifiers="const">
diff --git a/modules/webrtc/webrtc_data_channel_extension.h b/modules/webrtc/webrtc_data_channel_extension.h
index 467163ed93..92bd9619ef 100644
--- a/modules/webrtc/webrtc_data_channel_extension.h
+++ b/modules/webrtc/webrtc_data_channel_extension.h
@@ -70,8 +70,8 @@ public:
virtual Error put_packet(const uint8_t *p_buffer, int p_buffer_size) override;
/** GDExtension **/
- GDVIRTUAL2R(Error, _get_packet, GDNativeConstPtr<const uint8_t *>, GDNativePtr<int>);
- GDVIRTUAL2R(Error, _put_packet, GDNativeConstPtr<const uint8_t>, int);
+ GDVIRTUAL2R(Error, _get_packet, GDExtensionConstPtr<const uint8_t *>, GDExtensionPtr<int>);
+ GDVIRTUAL2R(Error, _put_packet, GDExtensionConstPtr<const uint8_t>, int);
WebRTCDataChannelExtension() {}
};
diff --git a/modules/webxr/doc_classes/WebXRInterface.xml b/modules/webxr/doc_classes/WebXRInterface.xml
index 49dd9f7318..f5964eb4d1 100644
--- a/modules/webxr/doc_classes/WebXRInterface.xml
+++ b/modules/webxr/doc_classes/WebXRInterface.xml
@@ -1,13 +1,13 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="WebXRInterface" inherits="XRInterface" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd">
<brief_description>
- AR/VR interface using WebXR.
+ XR interface using WebXR.
</brief_description>
<description>
WebXR is an open standard that allows creating VR and AR applications that run in the web browser.
As such, this interface is only available when running in Web exports.
WebXR supports a wide range of devices, from the very capable (like Valve Index, HTC Vive, Oculus Rift and Quest) down to the much less capable (like Google Cardboard, Oculus Go, GearVR, or plain smartphones).
- Since WebXR is based on JavaScript, it makes extensive use of callbacks, which means that [WebXRInterface] is forced to use signals, where other AR/VR interfaces would instead use functions that return a result immediately. This makes [WebXRInterface] quite a bit more complicated to initialize than other AR/VR interfaces.
+ Since WebXR is based on JavaScript, it makes extensive use of callbacks, which means that [WebXRInterface] is forced to use signals, where other XR interfaces would instead use functions that return a result immediately. This makes [WebXRInterface] quite a bit more complicated to initialize than other XR interfaces.
Here's the minimum code required to start an immersive VR session:
[codeblock]
extends Node3D
@@ -69,7 +69,7 @@
func _webxr_session_started():
$Button.visible = false
# This tells Godot to start rendering to the headset.
- get_viewport().xr = true
+ get_viewport().use_xr = true
# This will be the reference space type you ultimately got, out of the
# types that you requested above. This is useful if you want the game to
# work a little differently in 'bounded-floor' versus 'local-floor'.
@@ -79,28 +79,35 @@
$Button.visible = true
# If the user exits immersive mode, then we tell Godot to render to the web
# page again.
- get_viewport().xr = false
+ get_viewport().use_xr = false
func _webxr_session_failed(message):
OS.alert("Failed to initialize: " + message)
[/codeblock]
- There are several ways to handle "controller" input:
- - Using [XRController3D] nodes and their [signal XRController3D.button_pressed] and [signal XRController3D.button_released] signals. This is how controllers are typically handled in AR/VR apps in Godot, however, this will only work with advanced VR controllers like the Oculus Touch or Index controllers, for example. The buttons codes are defined by [url=https://immersive-web.github.io/webxr-gamepads-module/#xr-standard-gamepad-mapping]Section 3.3 of the WebXR Gamepads Module[/url].
- - Using [method Node._unhandled_input] and [InputEventJoypadButton] or [InputEventJoypadMotion]. This works the same as normal joypads, except the [member InputEvent.device] starts at 100, so the left controller is 100 and the right controller is 101, and the button codes are also defined by [url=https://immersive-web.github.io/webxr-gamepads-module/#xr-standard-gamepad-mapping]Section 3.3 of the WebXR Gamepads Module[/url].
- - Using the [signal select], [signal squeeze] and related signals. This method will work for both advanced VR controllers, and non-traditional "controllers" like a tap on the screen, a spoken voice command or a button press on the device itself.
- You can use one or all of these methods to allow your game or app to support a wider or narrower set of devices and input methods, or to allow more advanced interactions with more advanced devices.
+ There are a couple ways to handle "controller" input:
+ - Using [XRController3D] nodes and their [signal XRController3D.button_pressed] and [signal XRController3D.button_released] signals. This is how controllers are typically handled in XR apps in Godot, however, this will only work with advanced VR controllers like the Oculus Touch or Index controllers, for example.
+ - Using the [signal select], [signal squeeze] and related signals. This method will work for both advanced VR controllers, and non-traditional input sources like a tap on the screen, a spoken voice command or a button press on the device itself.
+ You can use both methods to allow your game or app to support a wider or narrower set of devices and input methods, or to allow more advanced interactions with more advanced devices.
</description>
<tutorials>
<link title="How to make a VR game for WebXR with Godot">https://www.snopekgames.com/blog/2020/how-make-vr-game-webxr-godot</link>
</tutorials>
<methods>
- <method name="get_controller" qualifiers="const">
+ <method name="get_input_source_target_ray_mode" qualifiers="const">
+ <return type="int" enum="WebXRInterface.TargetRayMode" />
+ <param index="0" name="input_source_id" type="int" />
+ <description>
+ Returns the target ray mode for the given [code]input_source_id[/code].
+ This can help interpret the input coming from that input source. See [url=https://developer.mozilla.org/en-US/docs/Web/API/XRInputSource/targetRayMode]XRInputSource.targetRayMode[/url] for more information.
+ </description>
+ </method>
+ <method name="get_input_source_tracker" qualifiers="const">
<return type="XRPositionalTracker" />
- <param index="0" name="controller_id" type="int" />
+ <param index="0" name="input_source_id" type="int" />
<description>
- Gets an [XRPositionalTracker] for the given [code]controller_id[/code].
- In the context of WebXR, a "controller" can be an advanced VR controller like the Oculus Touch or Index controllers, or even a tap on the screen, a spoken voice command or a button press on the device itself. When a non-traditional controller is used, interpret the position and orientation of the [XRPositionalTracker] as a ray pointing at the object the user wishes to interact with.
- Use this method to get information about the controller that triggered one of these signals:
+ Gets an [XRPositionalTracker] for the given [code]input_source_id[/code].
+ In the context of WebXR, an input source can be an advanced VR controller like the Oculus Touch or Index controllers, or even a tap on the screen, a spoken voice command or a button press on the device itself. When a non-traditional input source is used, interpret the position and orientation of the [XRPositionalTracker] as a ray pointing at the object the user wishes to interact with.
+ Use this method to get information about the input source that triggered one of these signals:
- [signal selectstart]
- [signal select]
- [signal selectend]
@@ -109,6 +116,13 @@
- [signal squeezestart]
</description>
</method>
+ <method name="is_input_source_active" qualifiers="const">
+ <return type="bool" />
+ <param index="0" name="input_source_id" type="int" />
+ <description>
+ Returns [code]true[/code] if there is an active input source with the given [code]input_source_id[/code].
+ </description>
+ </method>
<method name="is_session_supported">
<return type="void" />
<param index="0" name="session_mode" type="String" />
@@ -120,11 +134,6 @@
</method>
</methods>
<members>
- <member name="bounds_geometry" type="PackedVector3Array" setter="" getter="get_bounds_geometry">
- The vertices of a polygon which defines the boundaries of the user's play area.
- This will only be available if [member reference_space_type] is [code]"bounded-floor"[/code] and only on certain browsers and devices that support it.
- The [signal reference_space_reset] signal may indicate when this changes.
- </member>
<member name="optional_features" type="String" setter="set_optional_features" getter="get_optional_features">
A comma-seperated list of optional features used by [method XRInterface.initialize] when setting up the WebXR session.
If a user's browser or device doesn't support one of the given features, initialization will continue, but you won't be able to use the requested feature.
@@ -137,7 +146,7 @@
</member>
<member name="requested_reference_space_types" type="String" setter="set_requested_reference_space_types" getter="get_requested_reference_space_types">
A comma-seperated list of reference space types used by [method XRInterface.initialize] when setting up the WebXR session.
- The reference space types are requested in order, and the first on supported by the users device or browser will be used. The [member reference_space_type] property contains the reference space type that was ultimately used.
+ The reference space types are requested in order, and the first one supported by the users device or browser will be used. The [member reference_space_type] property contains the reference space type that was ultimately selected.
This doesn't have any effect on the interface when already initialized.
Possible values come from [url=https://developer.mozilla.org/en-US/docs/Web/API/XRReferenceSpaceType]WebXR's XRReferenceSpaceType[/url]. If you want to use a particular reference space type, it must be listed in either [member required_features] or [member optional_features].
</member>
@@ -161,35 +170,35 @@
<signal name="reference_space_reset">
<description>
Emitted to indicate that the reference space has been reset or reconfigured.
- When (or whether) this is emitted depends on the user's browser or device, but may include when the user has changed the dimensions of their play space (which you may be able to access via [member bounds_geometry]) or pressed/held a button to recenter their position.
+ When (or whether) this is emitted depends on the user's browser or device, but may include when the user has changed the dimensions of their play space (which you may be able to access via [method XRInterface.get_play_area]) or pressed/held a button to recenter their position.
See [url=https://developer.mozilla.org/en-US/docs/Web/API/XRReferenceSpace/reset_event]WebXR's XRReferenceSpace reset event[/url] for more information.
</description>
</signal>
<signal name="select">
- <param index="0" name="controller_id" type="int" />
+ <param index="0" name="input_source_id" type="int" />
<description>
- Emitted after one of the "controllers" has finished its "primary action".
- Use [method get_controller] to get more information about the controller.
+ Emitted after one of the input sources has finished its "primary action".
+ Use [method get_input_source_tracker] and [method get_input_source_target_ray_mode] to get more information about the input source.
</description>
</signal>
<signal name="selectend">
- <param index="0" name="controller_id" type="int" />
+ <param index="0" name="input_source_id" type="int" />
<description>
- Emitted when one of the "controllers" has finished its "primary action".
- Use [method get_controller] to get more information about the controller.
+ Emitted when one of the input sources has finished its "primary action".
+ Use [method get_input_source_tracker] and [method get_input_source_target_ray_mode] to get more information about the input source.
</description>
</signal>
<signal name="selectstart">
- <param index="0" name="controller_id" type="int" />
+ <param index="0" name="input_source_id" type="int" />
<description>
- Emitted when one of the "controllers" has started its "primary action".
- Use [method get_controller] to get more information about the controller.
+ Emitted when one of the input source has started its "primary action".
+ Use [method get_input_source_tracker] and [method get_input_source_target_ray_mode] to get more information about the input source.
</description>
</signal>
<signal name="session_ended">
<description>
Emitted when the user ends the WebXR session (which can be done using UI from the browser or device).
- At this point, you should do [code]get_viewport().xr = false[/code] to instruct Godot to resume rendering to the screen.
+ At this point, you should do [code]get_viewport().use_xr = false[/code] to instruct Godot to resume rendering to the screen.
</description>
</signal>
<signal name="session_failed">
@@ -202,7 +211,7 @@
<signal name="session_started">
<description>
Emitted by [method XRInterface.initialize] if the session is successfully started.
- At this point, it's safe to do [code]get_viewport().xr = true[/code] to instruct Godot to start rendering to the AR/VR device.
+ At this point, it's safe to do [code]get_viewport().use_xr = true[/code] to instruct Godot to start rendering to the XR device.
</description>
</signal>
<signal name="session_supported">
@@ -213,24 +222,24 @@
</description>
</signal>
<signal name="squeeze">
- <param index="0" name="controller_id" type="int" />
+ <param index="0" name="input_source_id" type="int" />
<description>
- Emitted after one of the "controllers" has finished its "primary squeeze action".
- Use [method get_controller] to get more information about the controller.
+ Emitted after one of the input sources has finished its "primary squeeze action".
+ Use [method get_input_source_tracker] and [method get_input_source_target_ray_mode] to get more information about the input source.
</description>
</signal>
<signal name="squeezeend">
- <param index="0" name="controller_id" type="int" />
+ <param index="0" name="input_source_id" type="int" />
<description>
- Emitted when one of the "controllers" has finished its "primary squeeze action".
- Use [method get_controller] to get more information about the controller.
+ Emitted when one of the input sources has finished its "primary squeeze action".
+ Use [method get_input_source_tracker] and [method get_input_source_target_ray_mode] to get more information about the input source.
</description>
</signal>
<signal name="squeezestart">
- <param index="0" name="controller_id" type="int" />
+ <param index="0" name="input_source_id" type="int" />
<description>
- Emitted when one of the "controllers" has started its "primary squeeze action".
- Use [method get_controller] to get more information about the controller.
+ Emitted when one of the input sources has started its "primary squeeze action".
+ Use [method get_input_source_tracker] and [method get_input_source_target_ray_mode] to get more information about the input source.
</description>
</signal>
<signal name="visibility_state_changed">
@@ -239,4 +248,18 @@
</description>
</signal>
</signals>
+ <constants>
+ <constant name="TARGET_RAY_MODE_UNKNOWN" value="0" enum="TargetRayMode">
+ We don't know the the target ray mode.
+ </constant>
+ <constant name="TARGET_RAY_MODE_GAZE" value="1" enum="TargetRayMode">
+ Target ray originates at the viewer's eyes and points in the direction they are looking.
+ </constant>
+ <constant name="TARGET_RAY_MODE_TRACKED_POINTER" value="2" enum="TargetRayMode">
+ Target ray from a handheld pointer, most likely a VR touch controller.
+ </constant>
+ <constant name="TARGET_RAY_MODE_SCREEN" value="3" enum="TargetRayMode">
+ Target ray from touch screen, mouse or other tactile input device.
+ </constant>
+ </constants>
</class>
diff --git a/modules/webxr/godot_webxr.h b/modules/webxr/godot_webxr.h
index d8d5bd99cc..e31a1d307e 100644
--- a/modules/webxr/godot_webxr.h
+++ b/modules/webxr/godot_webxr.h
@@ -37,12 +37,18 @@ extern "C" {
#include "stddef.h"
+enum WebXRInputEvent {
+ WEBXR_INPUT_EVENT_SELECTSTART,
+ WEBXR_INPUT_EVENT_SELECTEND,
+ WEBXR_INPUT_EVENT_SQUEEZESTART,
+ WEBXR_INPUT_EVENT_SQUEEZEEND,
+};
+
typedef void (*GodotWebXRSupportedCallback)(char *p_session_mode, int p_supported);
typedef void (*GodotWebXRStartedCallback)(char *p_reference_space_type);
typedef void (*GodotWebXREndedCallback)();
typedef void (*GodotWebXRFailedCallback)(char *p_message);
-typedef void (*GodotWebXRControllerCallback)();
-typedef void (*GodotWebXRInputEventCallback)(char *p_signal_name, int p_controller_id);
+typedef void (*GodotWebXRInputEventCallback)(int p_event_type, int p_input_source_id);
typedef void (*GodotWebXRSimpleEventCallback)(char *p_signal_name);
extern int godot_webxr_is_supported();
@@ -56,26 +62,33 @@ extern void godot_webxr_initialize(
GodotWebXRStartedCallback p_on_session_started,
GodotWebXREndedCallback p_on_session_ended,
GodotWebXRFailedCallback p_on_session_failed,
- GodotWebXRControllerCallback p_on_controller_changed,
GodotWebXRInputEventCallback p_on_input_event,
GodotWebXRSimpleEventCallback p_on_simple_event);
extern void godot_webxr_uninitialize();
extern int godot_webxr_get_view_count();
-extern int *godot_webxr_get_render_target_size();
-extern float *godot_webxr_get_transform_for_eye(int p_eye);
-extern float *godot_webxr_get_projection_for_eye(int p_eye);
-extern void godot_webxr_commit(unsigned int p_texture);
+extern bool godot_webxr_get_render_target_size(int *r_size);
+extern bool godot_webxr_get_transform_for_view(int p_view, float *r_transform);
+extern bool godot_webxr_get_projection_for_view(int p_view, float *r_transform);
+extern unsigned int godot_webxr_get_color_texture();
+extern unsigned int godot_webxr_get_depth_texture();
+extern unsigned int godot_webxr_get_velocity_texture();
-extern void godot_webxr_sample_controller_data();
-extern int godot_webxr_get_controller_count();
-extern int godot_webxr_is_controller_connected(int p_controller);
-extern float *godot_webxr_get_controller_transform(int p_controller);
-extern int *godot_webxr_get_controller_buttons(int p_controller);
-extern int *godot_webxr_get_controller_axes(int p_controller);
+extern bool godot_webxr_update_input_source(
+ int p_input_source_id,
+ float *r_target_pose,
+ int *r_target_ray_mode,
+ int *r_touch_index,
+ int *r_has_grip_pose,
+ float *r_grip_pose,
+ int *r_has_standard_mapping,
+ int *r_button_count,
+ float *r_buttons,
+ int *r_axes_count,
+ float *r_axes);
extern char *godot_webxr_get_visibility_state();
-extern int *godot_webxr_get_bounds_geometry();
+extern int godot_webxr_get_bounds_geometry(float **r_points);
#ifdef __cplusplus
}
diff --git a/modules/webxr/native/library_godot_webxr.js b/modules/webxr/native/library_godot_webxr.js
index c476a54c59..eaf251d48f 100644
--- a/modules/webxr/native/library_godot_webxr.js
+++ b/modules/webxr/native/library_godot_webxr.js
@@ -28,14 +28,19 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
const GodotWebXR = {
- $GodotWebXR__deps: ['$Browser', '$GL', '$GodotRuntime'],
+ $GodotWebXR__deps: ['$Browser', '$GL', '$GodotRuntime', '$runtimeKeepalivePush', '$runtimeKeepalivePop'],
$GodotWebXR: {
gl: null,
session: null,
+ gl_binding: null,
+ layer: null,
space: null,
frame: null,
pose: null,
+ view_count: 1,
+ input_sources: new Array(16),
+ touches: new Array(5),
// Monkey-patch the requestAnimationFrame() used by Emscripten for the main
// loop, so that we can swap it out for XRSession.requestAnimationFrame()
@@ -69,39 +74,135 @@ const GodotWebXR = {
// gets picked up automatically, however, in the Oculus Browser
// on the Quest, we need to pause and resume the main loop.
Browser.mainLoop.pause();
+ runtimeKeepalivePush(); // eslint-disable-line no-undef
window.setTimeout(function () {
+ runtimeKeepalivePop(); // eslint-disable-line no-undef
Browser.mainLoop.resume();
}, 0);
},
- // Holds the controllers list between function calls.
- controllers: [],
+ getLayer: () => {
+ const new_view_count = (GodotWebXR.pose) ? GodotWebXR.pose.views.length : 1;
+ let layer = GodotWebXR.layer;
- // Updates controllers array, where the left hand (or sole tracker) is
- // the first element, and the right hand is the second element, and any
- // others placed at the 3rd position and up.
- sampleControllers: () => {
- if (!GodotWebXR.session || !GodotWebXR.frame) {
- return;
+ // If the view count hasn't changed since creating this layer, then
+ // we can simply return it.
+ if (layer && GodotWebXR.view_count === new_view_count) {
+ return layer;
}
- let other_index = 2;
- const controllers = [];
- GodotWebXR.session.inputSources.forEach((input_source) => {
- if (input_source.targetRayMode === 'tracked-pointer') {
- if (input_source.handedness === 'right') {
- controllers[1] = input_source;
- } else if (input_source.handedness === 'left' || !controllers[0]) {
- controllers[0] = input_source;
+ if (!GodotWebXR.session || !GodotWebXR.gl_binding) {
+ return null;
+ }
+
+ const gl = GodotWebXR.gl;
+
+ layer = GodotWebXR.gl_binding.createProjectionLayer({
+ textureType: new_view_count > 1 ? 'texture-array' : 'texture',
+ colorFormat: gl.RGBA8,
+ depthFormat: gl.DEPTH_COMPONENT24,
+ });
+ GodotWebXR.session.updateRenderState({ layers: [layer] });
+
+ GodotWebXR.layer = layer;
+ GodotWebXR.view_count = new_view_count;
+ return layer;
+ },
+
+ getSubImage: () => {
+ if (!GodotWebXR.pose) {
+ return null;
+ }
+ const layer = GodotWebXR.getLayer();
+ if (layer === null) {
+ return null;
+ }
+
+ // Because we always use "texture-array" for multiview and "texture"
+ // when there is only 1 view, it should be safe to only grab the
+ // subimage for the first view.
+ return GodotWebXR.gl_binding.getViewSubImage(layer, GodotWebXR.pose.views[0]);
+ },
+
+ getTextureId: (texture) => {
+ if (texture.name !== undefined) {
+ return texture.name;
+ }
+
+ const id = GL.getNewId(GL.textures);
+ texture.name = id;
+ GL.textures[id] = texture;
+
+ return id;
+ },
+
+ addInputSource: (input_source) => {
+ let name = -1;
+ if (input_source.targetRayMode === 'tracked-pointer' && input_source.handedness === 'left') {
+ name = 0;
+ } else if (input_source.targetRayMode === 'tracked-pointer' && input_source.handedness === 'right') {
+ name = 1;
+ } else {
+ for (let i = 2; i < 16; i++) {
+ if (!GodotWebXR.input_sources[i]) {
+ name = i;
+ break;
}
- } else {
- controllers[other_index++] = input_source;
}
- });
- GodotWebXR.controllers = controllers;
+ }
+ if (name >= 0) {
+ GodotWebXR.input_sources[name] = input_source;
+ input_source.name = name;
+
+ // Find a free touch index for screen sources.
+ if (input_source.targetRayMode === 'screen') {
+ let touch_index = -1;
+ for (let i = 0; i < 5; i++) {
+ if (!GodotWebXR.touches[i]) {
+ touch_index = i;
+ break;
+ }
+ }
+ if (touch_index >= 0) {
+ GodotWebXR.touches[touch_index] = input_source;
+ input_source.touch_index = touch_index;
+ }
+ }
+ }
+ return name;
},
- getControllerId: (input_source) => GodotWebXR.controllers.indexOf(input_source),
+ removeInputSource: (input_source) => {
+ if (input_source.name !== undefined) {
+ const name = input_source.name;
+ if (name >= 0 && name < 16) {
+ GodotWebXR.input_sources[name] = null;
+ }
+
+ if (input_source.touch_index !== undefined) {
+ const touch_index = input_source.touch_index;
+ if (touch_index >= 0 && touch_index < 5) {
+ GodotWebXR.touches[touch_index] = null;
+ }
+ }
+ return name;
+ }
+ return -1;
+ },
+
+ getInputSourceId: (input_source) => {
+ if (input_source !== undefined) {
+ return input_source.name;
+ }
+ return -1;
+ },
+
+ getTouchIndex: (input_source) => {
+ if (input_source.touch_index !== undefined) {
+ return input_source.touch_index;
+ }
+ return -1;
+ },
},
godot_webxr_is_supported__proxy: 'sync',
@@ -130,8 +231,8 @@ const GodotWebXR = {
godot_webxr_initialize__deps: ['emscripten_webgl_get_current_context'],
godot_webxr_initialize__proxy: 'sync',
- godot_webxr_initialize__sig: 'viiiiiiiiii',
- godot_webxr_initialize: function (p_session_mode, p_required_features, p_optional_features, p_requested_reference_spaces, p_on_session_started, p_on_session_ended, p_on_session_failed, p_on_controller_changed, p_on_input_event, p_on_simple_event) {
+ godot_webxr_initialize__sig: 'viiiiiiiii',
+ godot_webxr_initialize: function (p_session_mode, p_required_features, p_optional_features, p_requested_reference_spaces, p_on_session_started, p_on_session_ended, p_on_session_failed, p_on_input_event, p_on_simple_event) {
GodotWebXR.monkeyPatchRequestAnimationFrame(true);
const session_mode = GodotRuntime.parseString(p_session_mode);
@@ -141,7 +242,6 @@ const GodotWebXR = {
const onstarted = GodotRuntime.get_func(p_on_session_started);
const onended = GodotRuntime.get_func(p_on_session_ended);
const onfailed = GodotRuntime.get_func(p_on_session_failed);
- const oncontroller = GodotRuntime.get_func(p_on_controller_changed);
const oninputevent = GodotRuntime.get_func(p_on_input_event);
const onsimpleevent = GodotRuntime.get_func(p_on_simple_event);
@@ -161,24 +261,18 @@ const GodotWebXR = {
});
session.addEventListener('inputsourceschange', function (evt) {
- let controller_changed = false;
- [evt.added, evt.removed].forEach((lst) => {
- lst.forEach((input_source) => {
- if (input_source.targetRayMode === 'tracked-pointer') {
- controller_changed = true;
- }
- });
- });
- if (controller_changed) {
- oncontroller();
- }
+ evt.added.forEach(GodotWebXR.addInputSource);
+ evt.removed.forEach(GodotWebXR.removeInputSource);
});
- ['selectstart', 'select', 'selectend', 'squeezestart', 'squeeze', 'squeezeend'].forEach((input_event) => {
+ ['selectstart', 'selectend', 'squeezestart', 'squeezeend'].forEach((input_event, index) => {
session.addEventListener(input_event, function (evt) {
- const c_str = GodotRuntime.allocString(input_event);
- oninputevent(c_str, GodotWebXR.getControllerId(evt.inputSource));
- GodotRuntime.free(c_str);
+ // Since this happens in-between normal frames, we need to
+ // grab the frame from the event in order to get poses for
+ // the input sources.
+ GodotWebXR.frame = evt.frame;
+ oninputevent(index, GodotWebXR.getInputSourceId(evt.inputSource));
+ GodotWebXR.frame = null;
});
});
@@ -193,9 +287,10 @@ const GodotWebXR = {
GodotWebXR.gl = gl;
gl.makeXRCompatible().then(function () {
- session.updateRenderState({
- baseLayer: new XRWebGLLayer(session, gl),
- });
+ GodotWebXR.gl_binding = new XRWebGLBinding(session, gl); // eslint-disable-line no-undef
+
+ // This will trigger the layer to get created.
+ GodotWebXR.getLayer();
function onReferenceSpaceSuccess(reference_space, reference_space_type) {
GodotWebXR.space = reference_space;
@@ -264,9 +359,14 @@ const GodotWebXR = {
}
GodotWebXR.session = null;
+ GodotWebXR.gl_binding = null;
+ GodotWebXR.layer = null;
GodotWebXR.space = null;
GodotWebXR.frame = null;
GodotWebXR.pose = null;
+ GodotWebXR.view_count = 1;
+ GodotWebXR.input_sources = new Array(16);
+ GodotWebXR.touches = new Array(5);
// Disable the monkey-patched window.requestAnimationFrame() and
// pause/restart the main loop to activate it on all platforms.
@@ -278,215 +378,186 @@ const GodotWebXR = {
godot_webxr_get_view_count__sig: 'i',
godot_webxr_get_view_count: function () {
if (!GodotWebXR.session || !GodotWebXR.pose) {
- return 0;
+ return 1;
}
- return GodotWebXR.pose.views.length;
+ const view_count = GodotWebXR.pose.views.length;
+ return view_count > 0 ? view_count : 1;
},
godot_webxr_get_render_target_size__proxy: 'sync',
- godot_webxr_get_render_target_size__sig: 'i',
- godot_webxr_get_render_target_size: function () {
- if (!GodotWebXR.session || !GodotWebXR.pose) {
- return 0;
+ godot_webxr_get_render_target_size__sig: 'ii',
+ godot_webxr_get_render_target_size: function (r_size) {
+ const subimage = GodotWebXR.getSubImage();
+ if (subimage === null) {
+ return false;
}
- const glLayer = GodotWebXR.session.renderState.baseLayer;
- const view = GodotWebXR.pose.views[0];
- const viewport = glLayer.getViewport(view);
+ GodotRuntime.setHeapValue(r_size + 0, subimage.viewport.width, 'i32');
+ GodotRuntime.setHeapValue(r_size + 4, subimage.viewport.height, 'i32');
- const buf = GodotRuntime.malloc(2 * 4);
- GodotRuntime.setHeapValue(buf + 0, viewport.width, 'i32');
- GodotRuntime.setHeapValue(buf + 4, viewport.height, 'i32');
- return buf;
+ return true;
},
- godot_webxr_get_transform_for_eye__proxy: 'sync',
- godot_webxr_get_transform_for_eye__sig: 'ii',
- godot_webxr_get_transform_for_eye: function (p_eye) {
+ godot_webxr_get_transform_for_view__proxy: 'sync',
+ godot_webxr_get_transform_for_view__sig: 'iii',
+ godot_webxr_get_transform_for_view: function (p_view, r_transform) {
if (!GodotWebXR.session || !GodotWebXR.pose) {
- return 0;
+ return false;
}
const views = GodotWebXR.pose.views;
let matrix;
- if (p_eye === 0) {
- matrix = GodotWebXR.pose.transform.matrix;
+ if (p_view >= 0) {
+ matrix = views[p_view].transform.matrix;
} else {
- matrix = views[p_eye - 1].transform.matrix;
- }
- const buf = GodotRuntime.malloc(16 * 4);
- for (let i = 0; i < 16; i++) {
- GodotRuntime.setHeapValue(buf + (i * 4), matrix[i], 'float');
- }
- return buf;
- },
-
- godot_webxr_get_projection_for_eye__proxy: 'sync',
- godot_webxr_get_projection_for_eye__sig: 'ii',
- godot_webxr_get_projection_for_eye: function (p_eye) {
- if (!GodotWebXR.session || !GodotWebXR.pose) {
- return 0;
+ // For -1 (or any other negative value) return the HMD transform.
+ matrix = GodotWebXR.pose.transform.matrix;
}
- const view_index = (p_eye === 2 /* ARVRInterface::EYE_RIGHT */) ? 1 : 0;
- const matrix = GodotWebXR.pose.views[view_index].projectionMatrix;
- const buf = GodotRuntime.malloc(16 * 4);
for (let i = 0; i < 16; i++) {
- GodotRuntime.setHeapValue(buf + (i * 4), matrix[i], 'float');
+ GodotRuntime.setHeapValue(r_transform + (i * 4), matrix[i], 'float');
}
- return buf;
+
+ return true;
},
- godot_webxr_commit__proxy: 'sync',
- godot_webxr_commit__sig: 'vi',
- godot_webxr_commit: function (p_texture) {
+ godot_webxr_get_projection_for_view__proxy: 'sync',
+ godot_webxr_get_projection_for_view__sig: 'iii',
+ godot_webxr_get_projection_for_view: function (p_view, r_transform) {
if (!GodotWebXR.session || !GodotWebXR.pose) {
- return;
+ return false;
}
- const glLayer = GodotWebXR.session.renderState.baseLayer;
- const views = GodotWebXR.pose.views;
- const gl = GodotWebXR.gl;
-
- const texture = GL.textures[p_texture];
-
- const orig_framebuffer = gl.getParameter(gl.FRAMEBUFFER_BINDING);
- const orig_read_framebuffer = gl.getParameter(gl.READ_FRAMEBUFFER_BINDING);
- const orig_read_buffer = gl.getParameter(gl.READ_BUFFER);
- const orig_draw_framebuffer = gl.getParameter(gl.DRAW_FRAMEBUFFER_BINDING);
-
- // Copy from Godot render target into framebuffer from WebXR.
- gl.bindFramebuffer(gl.FRAMEBUFFER, null);
- for (let i = 0; i < views.length; i++) {
- const viewport = glLayer.getViewport(views[i]);
-
- const read_fbo = gl.createFramebuffer();
- gl.bindFramebuffer(gl.READ_FRAMEBUFFER, read_fbo);
- if (views.length > 1) {
- gl.framebufferTextureLayer(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, texture, 0, i);
- } else {
- gl.framebufferTexture2D(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
- }
- gl.readBuffer(gl.COLOR_ATTACHMENT0);
- gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, glLayer.framebuffer);
-
- // Flip Y upside down on destination.
- gl.blitFramebuffer(0, 0, viewport.width, viewport.height,
- viewport.x, viewport.y + viewport.height, viewport.x + viewport.width, viewport.y,
- gl.COLOR_BUFFER_BIT, gl.NEAREST);
-
- gl.bindFramebuffer(gl.READ_FRAMEBUFFER, null);
- gl.deleteFramebuffer(read_fbo);
+ const matrix = GodotWebXR.pose.views[p_view].projectionMatrix;
+ for (let i = 0; i < 16; i++) {
+ GodotRuntime.setHeapValue(r_transform + (i * 4), matrix[i], 'float');
}
- // Restore state.
- gl.bindFramebuffer(gl.FRAMEBUFFER, orig_framebuffer);
- gl.bindFramebuffer(gl.READ_FRAMEBUFFER, orig_read_framebuffer);
- gl.readBuffer(orig_read_buffer);
- gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, orig_draw_framebuffer);
+ return true;
},
- godot_webxr_sample_controller_data__proxy: 'sync',
- godot_webxr_sample_controller_data__sig: 'v',
- godot_webxr_sample_controller_data: function () {
- GodotWebXR.sampleControllers();
+ godot_webxr_get_color_texture__proxy: 'sync',
+ godot_webxr_get_color_texture__sig: 'i',
+ godot_webxr_get_color_texture: function () {
+ const subimage = GodotWebXR.getSubImage();
+ if (subimage === null) {
+ return 0;
+ }
+ return GodotWebXR.getTextureId(subimage.colorTexture);
},
- godot_webxr_get_controller_count__proxy: 'sync',
- godot_webxr_get_controller_count__sig: 'i',
- godot_webxr_get_controller_count: function () {
- if (!GodotWebXR.session || !GodotWebXR.frame) {
+ godot_webxr_get_depth_texture__proxy: 'sync',
+ godot_webxr_get_depth_texture__sig: 'i',
+ godot_webxr_get_depth_texture: function () {
+ const subimage = GodotWebXR.getSubImage();
+ if (subimage === null) {
return 0;
}
- return GodotWebXR.controllers.length;
+ if (!subimage.depthStencilTexture) {
+ return 0;
+ }
+ return GodotWebXR.getTextureId(subimage.depthStencilTexture);
},
- godot_webxr_is_controller_connected__proxy: 'sync',
- godot_webxr_is_controller_connected__sig: 'ii',
- godot_webxr_is_controller_connected: function (p_controller) {
- if (!GodotWebXR.session || !GodotWebXR.frame) {
- return false;
+ godot_webxr_get_velocity_texture__proxy: 'sync',
+ godot_webxr_get_velocity_texture__sig: 'i',
+ godot_webxr_get_velocity_texture: function () {
+ const subimage = GodotWebXR.getSubImage();
+ if (subimage === null) {
+ return 0;
+ }
+ if (!subimage.motionVectorTexture) {
+ return 0;
}
- return !!GodotWebXR.controllers[p_controller];
+ return GodotWebXR.getTextureId(subimage.motionVectorTexture);
},
- godot_webxr_get_controller_transform__proxy: 'sync',
- godot_webxr_get_controller_transform__sig: 'ii',
- godot_webxr_get_controller_transform: function (p_controller) {
+ godot_webxr_update_input_source__proxy: 'sync',
+ godot_webxr_update_input_source__sig: 'iiiiiiiiiiii',
+ godot_webxr_update_input_source: function (p_input_source_id, r_target_pose, r_target_ray_mode, r_touch_index, r_has_grip_pose, r_grip_pose, r_has_standard_mapping, r_button_count, r_buttons, r_axes_count, r_axes) {
if (!GodotWebXR.session || !GodotWebXR.frame) {
return 0;
}
- const controller = GodotWebXR.controllers[p_controller];
- if (!controller) {
- return 0;
+ if (p_input_source_id < 0 || p_input_source_id >= GodotWebXR.input_sources.length || !GodotWebXR.input_sources[p_input_source_id]) {
+ return false;
}
+ const input_source = GodotWebXR.input_sources[p_input_source_id];
const frame = GodotWebXR.frame;
const space = GodotWebXR.space;
- const pose = frame.getPose(controller.targetRaySpace, space);
- if (!pose) {
+ // Target pose.
+ const target_pose = frame.getPose(input_source.targetRaySpace, space);
+ if (!target_pose) {
// This can mean that the controller lost tracking.
- return 0;
+ return false;
}
- const matrix = pose.transform.matrix;
-
- const buf = GodotRuntime.malloc(16 * 4);
+ const target_pose_matrix = target_pose.transform.matrix;
for (let i = 0; i < 16; i++) {
- GodotRuntime.setHeapValue(buf + (i * 4), matrix[i], 'float');
+ GodotRuntime.setHeapValue(r_target_pose + (i * 4), target_pose_matrix[i], 'float');
}
- return buf;
- },
- godot_webxr_get_controller_buttons__proxy: 'sync',
- godot_webxr_get_controller_buttons__sig: 'ii',
- godot_webxr_get_controller_buttons: function (p_controller) {
- if (GodotWebXR.controllers.length === 0) {
- return 0;
- }
+ // Target ray mode.
+ let target_ray_mode = 0;
+ switch (input_source.targetRayMode) {
+ case 'gaze':
+ target_ray_mode = 1;
+ break;
- const controller = GodotWebXR.controllers[p_controller];
- if (!controller || !controller.gamepad) {
- return 0;
- }
-
- const button_count = controller.gamepad.buttons.length;
+ case 'tracked-pointer':
+ target_ray_mode = 2;
+ break;
- const buf = GodotRuntime.malloc((button_count + 1) * 4);
- GodotRuntime.setHeapValue(buf, button_count, 'i32');
- for (let i = 0; i < button_count; i++) {
- GodotRuntime.setHeapValue(buf + 4 + (i * 4), controller.gamepad.buttons[i].value, 'float');
- }
- return buf;
- },
+ case 'screen':
+ target_ray_mode = 3;
+ break;
- godot_webxr_get_controller_axes__proxy: 'sync',
- godot_webxr_get_controller_axes__sig: 'ii',
- godot_webxr_get_controller_axes: function (p_controller) {
- if (GodotWebXR.controllers.length === 0) {
- return 0;
+ default:
}
-
- const controller = GodotWebXR.controllers[p_controller];
- if (!controller || !controller.gamepad) {
- return 0;
+ GodotRuntime.setHeapValue(r_target_ray_mode, target_ray_mode, 'i32');
+
+ // Touch index.
+ GodotRuntime.setHeapValue(r_touch_index, GodotWebXR.getTouchIndex(input_source), 'i32');
+
+ // Grip pose.
+ let has_grip_pose = false;
+ if (input_source.gripSpace) {
+ const grip_pose = frame.getPose(input_source.gripSpace, space);
+ if (grip_pose) {
+ const grip_pose_matrix = grip_pose.transform.matrix;
+ for (let i = 0; i < 16; i++) {
+ GodotRuntime.setHeapValue(r_grip_pose + (i * 4), grip_pose_matrix[i], 'float');
+ }
+ has_grip_pose = true;
+ }
}
+ GodotRuntime.setHeapValue(r_has_grip_pose, has_grip_pose ? 1 : 0, 'i32');
+
+ // Gamepad data (mapping, buttons and axes).
+ let has_standard_mapping = false;
+ let button_count = 0;
+ let axes_count = 0;
+ if (input_source.gamepad) {
+ if (input_source.gamepad.mapping === 'xr-standard') {
+ has_standard_mapping = true;
+ }
- const axes_count = controller.gamepad.axes.length;
+ button_count = Math.min(input_source.gamepad.buttons.length, 10);
+ for (let i = 0; i < button_count; i++) {
+ GodotRuntime.setHeapValue(r_buttons + (i * 4), input_source.gamepad.buttons[i].value, 'float');
+ }
- const buf = GodotRuntime.malloc((axes_count + 1) * 4);
- GodotRuntime.setHeapValue(buf, axes_count, 'i32');
- for (let i = 0; i < axes_count; i++) {
- let value = controller.gamepad.axes[i];
- if (i === 1 || i === 3) {
- // Invert the Y-axis on thumbsticks and trackpads, in order to
- // match OpenXR and other XR platform SDKs.
- value *= -1.0;
+ axes_count = Math.min(input_source.gamepad.axes.length, 10);
+ for (let i = 0; i < axes_count; i++) {
+ GodotRuntime.setHeapValue(r_axes + (i * 4), input_source.gamepad.axes[i], 'float');
}
- GodotRuntime.setHeapValue(buf + 4 + (i * 4), value, 'float');
}
- return buf;
+ GodotRuntime.setHeapValue(r_has_standard_mapping, has_standard_mapping ? 1 : 0, 'i32');
+ GodotRuntime.setHeapValue(r_button_count, button_count, 'i32');
+ GodotRuntime.setHeapValue(r_axes_count, axes_count, 'i32');
+
+ return true;
},
godot_webxr_get_visibility_state__proxy: 'sync',
@@ -500,8 +571,8 @@ const GodotWebXR = {
},
godot_webxr_get_bounds_geometry__proxy: 'sync',
- godot_webxr_get_bounds_geometry__sig: 'i',
- godot_webxr_get_bounds_geometry: function () {
+ godot_webxr_get_bounds_geometry__sig: 'ii',
+ godot_webxr_get_bounds_geometry: function (r_points) {
if (!GodotWebXR.space || !GodotWebXR.space.boundsGeometry) {
return 0;
}
@@ -511,7 +582,7 @@ const GodotWebXR = {
return 0;
}
- const buf = GodotRuntime.malloc(((point_count * 3) + 1) * 4);
+ const buf = GodotRuntime.malloc(point_count * 3 * 4);
GodotRuntime.setHeapValue(buf, point_count, 'i32');
for (let i = 0; i < point_count; i++) {
const point = GodotWebXR.space.boundsGeometry[i];
@@ -519,8 +590,9 @@ const GodotWebXR = {
GodotRuntime.setHeapValue(buf + ((i * 3) + 2) * 4, point.y, 'float');
GodotRuntime.setHeapValue(buf + ((i * 3) + 3) * 4, point.z, 'float');
}
+ GodotRuntime.setHeapValue(r_points, buf, 'i32');
- return buf;
+ return point_count;
},
};
diff --git a/modules/webxr/native/webxr.externs.js b/modules/webxr/native/webxr.externs.js
index 9ea105aa93..4b88820b19 100644
--- a/modules/webxr/native/webxr.externs.js
+++ b/modules/webxr/native/webxr.externs.js
@@ -1,3 +1,7 @@
+/*
+ * WebXR Device API
+ */
+
/**
* @type {XR}
*/
@@ -497,3 +501,681 @@ XRPose.prototype.transform;
* @type {boolean}
*/
XRPose.prototype.emulatedPosition;
+
+/*
+ * WebXR Layers API Level 1
+ */
+
+/**
+ * @constructor XRLayer
+ */
+function XRLayer() {}
+
+/**
+ * @constructor XRLayerEventInit
+ */
+function XRLayerEventInit() {}
+
+/**
+ * @type {XRLayer}
+ */
+XRLayerEventInit.prototype.layer;
+
+/**
+ * @constructor XRLayerEvent
+ *
+ * @param {string} type
+ * @param {XRLayerEventInit} init
+ */
+function XRLayerEvent(type, init) {};
+
+/**
+ * @type {XRLayer}
+ */
+XRLayerEvent.prototype.layer;
+
+/**
+ * @constructor XRCompositionLayer
+ * @extends {XRLayer}
+ */
+function XRCompositionLayer() {};
+
+/**
+ * @type {string}
+ */
+XRCompositionLayer.prototype.layout;
+
+/**
+ * @type {boolean}
+ */
+XRCompositionLayer.prototype.blendTextureAberrationCorrection;
+
+/**
+ * @type {?boolean}
+ */
+XRCompositionLayer.prototype.chromaticAberrationCorrection;
+
+/**
+ * @type {boolean}
+ */
+XRCompositionLayer.prototype.forceMonoPresentation;
+
+/**
+ * @type {number}
+ */
+XRCompositionLayer.prototype.opacity;
+
+/**
+ * @type {number}
+ */
+XRCompositionLayer.prototype.mipLevels;
+
+/**
+ * @type {boolean}
+ */
+XRCompositionLayer.prototype.needsRedraw;
+
+/**
+ * @return {void}
+ */
+XRCompositionLayer.prototype.destroy = function () {};
+
+/**
+ * @constructor XRProjectionLayer
+ * @extends {XRCompositionLayer}
+ */
+function XRProjectionLayer() {}
+
+/**
+ * @type {number}
+ */
+XRProjectionLayer.prototype.textureWidth;
+
+/**
+ * @type {number}
+ */
+XRProjectionLayer.prototype.textureHeight;
+
+/**
+ * @type {number}
+ */
+XRProjectionLayer.prototype.textureArrayLength;
+
+/**
+ * @type {boolean}
+ */
+XRProjectionLayer.prototype.ignoreDepthValues;
+
+/**
+ * @type {?number}
+ */
+XRProjectionLayer.prototype.fixedFoveation;
+
+/**
+ * @type {XRRigidTransform}
+ */
+XRProjectionLayer.prototype.deltaPose;
+
+/**
+ * @constructor XRQuadLayer
+ * @extends {XRCompositionLayer}
+ */
+function XRQuadLayer() {}
+
+/**
+ * @type {XRSpace}
+ */
+XRQuadLayer.prototype.space;
+
+/**
+ * @type {XRRigidTransform}
+ */
+XRQuadLayer.prototype.transform;
+
+/**
+ * @type {number}
+ */
+XRQuadLayer.prototype.width;
+
+/**
+ * @type {number}
+ */
+XRQuadLayer.prototype.height;
+
+/**
+ * @type {?function (XRLayerEvent)}
+ */
+XRQuadLayer.prototype.onredraw;
+
+/**
+ * @constructor XRCylinderLayer
+ * @extends {XRCompositionLayer}
+ */
+function XRCylinderLayer() {}
+
+/**
+ * @type {XRSpace}
+ */
+XRCylinderLayer.prototype.space;
+
+/**
+ * @type {XRRigidTransform}
+ */
+XRCylinderLayer.prototype.transform;
+
+/**
+ * @type {number}
+ */
+XRCylinderLayer.prototype.radius;
+
+/**
+ * @type {number}
+ */
+XRCylinderLayer.prototype.centralAngle;
+
+/**
+ * @type {number}
+ */
+XRCylinderLayer.prototype.aspectRatio;
+
+/**
+ * @type {?function (XRLayerEvent)}
+ */
+XRCylinderLayer.prototype.onredraw;
+
+/**
+ * @constructor XREquirectLayer
+ * @extends {XRCompositionLayer}
+ */
+function XREquirectLayer() {}
+
+/**
+ * @type {XRSpace}
+ */
+XREquirectLayer.prototype.space;
+
+/**
+ * @type {XRRigidTransform}
+ */
+XREquirectLayer.prototype.transform;
+
+/**
+ * @type {number}
+ */
+XREquirectLayer.prototype.radius;
+
+/**
+ * @type {number}
+ */
+XREquirectLayer.prototype.centralHorizontalAngle;
+
+/**
+ * @type {number}
+ */
+XREquirectLayer.prototype.upperVerticalAngle;
+
+/**
+ * @type {number}
+ */
+XREquirectLayer.prototype.lowerVerticalAngle;
+
+/**
+ * @type {?function (XRLayerEvent)}
+ */
+XREquirectLayer.prototype.onredraw;
+
+/**
+ * @constructor XRCubeLayer
+ * @extends {XRCompositionLayer}
+ */
+function XRCubeLayer() {}
+
+/**
+ * @type {XRSpace}
+ */
+XRCubeLayer.prototype.space;
+
+/**
+ * @type {DOMPointReadOnly}
+ */
+XRCubeLayer.prototype.orientation;
+
+/**
+ * @type {?function (XRLayerEvent)}
+ */
+XRCubeLayer.prototype.onredraw;
+
+/**
+ * @constructor XRSubImage
+ */
+function XRSubImage() {}
+
+/**
+ * @type {XRViewport}
+ */
+XRSubImage.prototype.viewport;
+
+/**
+ * @constructor XRWebGLSubImage
+ * @extends {XRSubImage}
+ */
+function XRWebGLSubImage () {}
+
+/**
+ * @type {WebGLTexture}
+ */
+XRWebGLSubImage.prototype.colorTexture;
+
+/**
+ * @type {?WebGLTexture}
+ */
+XRWebGLSubImage.prototype.depthStencilTexture;
+
+/**
+ * @type {?WebGLTexture}
+ */
+XRWebGLSubImage.prototype.motionVectorTexture;
+
+/**
+ * @type {?number}
+ */
+XRWebGLSubImage.prototype.imageIndex;
+
+/**
+ * @type {number}
+ */
+XRWebGLSubImage.prototype.colorTextureWidth;
+
+/**
+ * @type {number}
+ */
+XRWebGLSubImage.prototype.colorTextureHeight;
+
+/**
+ * @type {?number}
+ */
+XRWebGLSubImage.prototype.depthStencilTextureWidth;
+
+/**
+ * @type {?number}
+ */
+XRWebGLSubImage.prototype.depthStencilTextureHeight;
+
+/**
+ * @type {?number}
+ */
+
+XRWebGLSubImage.prototype.motionVectorTextureWidth;
+
+/**
+ * @type {?number}
+ */
+XRWebGLSubImage.prototype.motionVectorTextureHeight;
+
+/**
+ * @constructor XRProjectionLayerInit
+ */
+function XRProjectionLayerInit() {}
+
+/**
+ * @type {string}
+ */
+XRProjectionLayerInit.prototype.textureType;
+
+/**
+ * @type {number}
+ */
+XRProjectionLayerInit.prototype.colorFormat;
+
+/**
+ * @type {number}
+ */
+XRProjectionLayerInit.prototype.depthFormat;
+
+/**
+ * @type {number}
+ */
+XRProjectionLayerInit.prototype.scaleFactor;
+
+/**
+ * @constructor XRLayerInit
+ */
+function XRLayerInit() {}
+
+/**
+ * @type {XRSpace}
+ */
+XRLayerInit.prototype.space;
+
+/**
+ * @type {number}
+ */
+XRLayerInit.prototype.colorFormat;
+
+/**
+ * @type {number}
+ */
+XRLayerInit.prototype.depthFormat;
+
+/**
+ * @type {number}
+ */
+XRLayerInit.prototype.mipLevels;
+
+/**
+ * @type {number}
+ */
+XRLayerInit.prototype.viewPixelWidth;
+
+/**
+ * @type {number}
+ */
+XRLayerInit.prototype.viewPixelHeight;
+
+/**
+ * @type {string}
+ */
+XRLayerInit.prototype.layout;
+
+/**
+ * @type {boolean}
+ */
+XRLayerInit.prototype.isStatic;
+
+/**
+ * @constructor XRQuadLayerInit
+ * @extends {XRLayerInit}
+ */
+function XRQuadLayerInit() {}
+
+/**
+ * @type {string}
+ */
+XRQuadLayerInit.prototype.textureType;
+
+/**
+ * @type {?XRRigidTransform}
+ */
+XRQuadLayerInit.prototype.transform;
+
+/**
+ * @type {number}
+ */
+XRQuadLayerInit.prototype.width;
+
+/**
+ * @type {number}
+ */
+XRQuadLayerInit.prototype.height;
+
+/**
+ * @constructor XRCylinderLayerInit
+ * @extends {XRLayerInit}
+ */
+function XRCylinderLayerInit() {}
+
+/**
+ * @type {string}
+ */
+XRCylinderLayerInit.prototype.textureType;
+
+/**
+ * @type {?XRRigidTransform}
+ */
+XRCylinderLayerInit.prototype.transform;
+
+/**
+ * @type {number}
+ */
+XRCylinderLayerInit.prototype.radius;
+
+/**
+ * @type {number}
+ */
+XRCylinderLayerInit.prototype.centralAngle;
+
+/**
+ * @type {number}
+ */
+XRCylinderLayerInit.prototype.aspectRatio;
+
+/**
+ * @constructor XREquirectLayerInit
+ * @extends {XRLayerInit}
+ */
+function XREquirectLayerInit() {}
+
+/**
+ * @type {string}
+ */
+XREquirectLayerInit.prototype.textureType;
+
+/**
+ * @type {?XRRigidTransform}
+ */
+XREquirectLayerInit.prototype.transform;
+
+/**
+ * @type {number}
+ */
+XREquirectLayerInit.prototype.radius;
+
+/**
+ * @type {number}
+ */
+XREquirectLayerInit.prototype.centralHorizontalAngle;
+
+/**
+ * @type {number}
+ */
+XREquirectLayerInit.prototype.upperVerticalAngle;
+
+/**
+ * @type {number}
+ */
+XREquirectLayerInit.prototype.lowerVerticalAngle;
+
+/**
+ * @constructor XRCubeLayerInit
+ * @extends {XRLayerInit}
+ */
+function XRCubeLayerInit() {}
+
+/**
+ * @type {DOMPointReadOnly}
+ */
+XRCubeLayerInit.prototype.orientation;
+
+/**
+ * @constructor XRWebGLBinding
+ *
+ * @param {XRSession} session
+ * @param {WebGLRenderContext|WebGL2RenderingContext} context
+ */
+function XRWebGLBinding(session, context) {}
+
+/**
+ * @type {number}
+ */
+XRWebGLBinding.prototype.nativeProjectionScaleFactor;
+
+/**
+ * @type {number}
+ */
+XRWebGLBinding.prototype.usesDepthValues;
+
+/**
+ * @param {XRProjectionLayerInit} init
+ * @return {XRProjectionLayer}
+ */
+XRWebGLBinding.prototype.createProjectionLayer = function (init) {};
+
+/**
+ * @param {XRQuadLayerInit} init
+ * @return {XRQuadLayer}
+ */
+XRWebGLBinding.prototype.createQuadLayer = function (init) {};
+
+/**
+ * @param {XRCylinderLayerInit} init
+ * @return {XRCylinderLayer}
+ */
+XRWebGLBinding.prototype.createCylinderLayer = function (init) {};
+
+/**
+ * @param {XREquirectLayerInit} init
+ * @return {XREquirectLayer}
+ */
+XRWebGLBinding.prototype.createEquirectLayer = function (init) {};
+
+/**
+ * @param {XRCubeLayerInit} init
+ * @return {XRCubeLayer}
+ */
+XRWebGLBinding.prototype.createCubeLayer = function (init) {};
+
+/**
+ * @param {XRCompositionLayer} layer
+ * @param {XRFrame} frame
+ * @param {string} eye
+ * @return {XRWebGLSubImage}
+ */
+XRWebGLBinding.prototype.getSubImage = function (layer, frame, eye) {};
+
+/**
+ * @param {XRProjectionLayer} layer
+ * @param {XRView} view
+ * @return {XRWebGLSubImage}
+ */
+XRWebGLBinding.prototype.getViewSubImage = function (layer, view) {};
+
+/**
+ * @constructor XRMediaLayerInit
+ */
+function XRMediaLayerInit() {}
+
+/**
+ * @type {XRSpace}
+ */
+XRMediaLayerInit.prototype.space;
+
+/**
+ * @type {string}
+ */
+XRMediaLayerInit.prototype.layout;
+
+/**
+ * @type {boolean}
+ */
+XRMediaLayerInit.prototype.invertStereo;
+
+/**
+ * @constructor XRMediaQuadLayerInit
+ * @extends {XRMediaLayerInit}
+ */
+function XRMediaQuadLayerInit() {}
+
+/**
+ * @type {XRRigidTransform}
+ */
+XRMediaQuadLayerInit.prototype.transform;
+
+/**
+ * @type {number}
+ */
+XRMediaQuadLayerInit.prototype.width;
+
+/**
+ * @type {number}
+ */
+XRMediaQuadLayerInit.prototype.height;
+
+/**
+ * @constructor XRMediaCylinderLayerInit
+ * @extends {XRMediaLayerInit}
+ */
+function XRMediaCylinderLayerInit() {}
+
+/**
+ * @type {XRRigidTransform}
+ */
+XRMediaCylinderLayerInit.prototype.transform;
+
+/**
+ * @type {number}
+ */
+XRMediaCylinderLayerInit.prototype.radius;
+
+/**
+ * @type {number}
+ */
+XRMediaCylinderLayerInit.prototype.centralAngle;
+
+/**
+ * @type {?number}
+ */
+XRMediaCylinderLayerInit.prototype.aspectRatio;
+
+/**
+ * @constructor XRMediaEquirectLayerInit
+ * @extends {XRMediaLayerInit}
+ */
+function XRMediaEquirectLayerInit() {}
+
+/**
+ * @type {XRRigidTransform}
+ */
+XRMediaEquirectLayerInit.prototype.transform;
+
+/**
+ * @type {number}
+ */
+XRMediaEquirectLayerInit.prototype.radius;
+
+/**
+ * @type {number}
+ */
+XRMediaEquirectLayerInit.prototype.centralHorizontalAngle;
+
+/**
+ * @type {number}
+ */
+XRMediaEquirectLayerInit.prototype.upperVerticalAngle;
+
+/**
+ * @type {number}
+ */
+XRMediaEquirectLayerInit.prototype.lowerVerticalAngle;
+
+/**
+ * @constructor XRMediaBinding
+ *
+ * @param {XRSession} session
+ */
+function XRMediaBinding(session) {}
+
+/**
+ * @param {HTMLVideoElement} video
+ * @param {XRMediaQuadLayerInit} init
+ * @return {XRQuadLayer}
+ */
+XRMediaBinding.prototype.createQuadLayer = function(video, init) {};
+
+/**
+ * @param {HTMLVideoElement} video
+ * @param {XRMediaCylinderLayerInit} init
+ * @return {XRCylinderLayer}
+ */
+XRMediaBinding.prototype.createCylinderLayer = function(video, init) {};
+
+/**
+ * @param {HTMLVideoElement} video
+ * @param {XRMediaEquirectLayerInit} init
+ * @return {XREquirectLayer}
+ */
+XRMediaBinding.prototype.createEquirectLayer = function(video, init) {};
+
+/**
+ * @type {Array<XRLayer>}
+ */
+XRRenderState.prototype.layers;
diff --git a/modules/webxr/webxr_interface.cpp b/modules/webxr/webxr_interface.cpp
index b0ad53523a..c0580df172 100644
--- a/modules/webxr/webxr_interface.cpp
+++ b/modules/webxr/webxr_interface.cpp
@@ -42,9 +42,10 @@ void WebXRInterface::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_reference_space_type"), &WebXRInterface::get_reference_space_type);
ClassDB::bind_method(D_METHOD("set_requested_reference_space_types", "requested_reference_space_types"), &WebXRInterface::set_requested_reference_space_types);
ClassDB::bind_method(D_METHOD("get_requested_reference_space_types"), &WebXRInterface::get_requested_reference_space_types);
- ClassDB::bind_method(D_METHOD("get_controller", "controller_id"), &WebXRInterface::get_controller);
+ ClassDB::bind_method(D_METHOD("is_input_source_active", "input_source_id"), &WebXRInterface::is_input_source_active);
+ ClassDB::bind_method(D_METHOD("get_input_source_tracker", "input_source_id"), &WebXRInterface::get_input_source_tracker);
+ ClassDB::bind_method(D_METHOD("get_input_source_target_ray_mode", "input_source_id"), &WebXRInterface::get_input_source_target_ray_mode);
ClassDB::bind_method(D_METHOD("get_visibility_state"), &WebXRInterface::get_visibility_state);
- ClassDB::bind_method(D_METHOD("get_bounds_geometry"), &WebXRInterface::get_bounds_geometry);
ADD_PROPERTY(PropertyInfo(Variant::STRING, "session_mode", PROPERTY_HINT_NONE), "set_session_mode", "get_session_mode");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "required_features", PROPERTY_HINT_NONE), "set_required_features", "get_required_features");
@@ -52,20 +53,24 @@ void WebXRInterface::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::STRING, "requested_reference_space_types", PROPERTY_HINT_NONE), "set_requested_reference_space_types", "get_requested_reference_space_types");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "reference_space_type", PROPERTY_HINT_NONE), "", "get_reference_space_type");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "visibility_state", PROPERTY_HINT_NONE), "", "get_visibility_state");
- ADD_PROPERTY(PropertyInfo(Variant::PACKED_VECTOR3_ARRAY, "bounds_geometry", PROPERTY_HINT_NONE), "", "get_bounds_geometry");
ADD_SIGNAL(MethodInfo("session_supported", PropertyInfo(Variant::STRING, "session_mode"), PropertyInfo(Variant::BOOL, "supported")));
ADD_SIGNAL(MethodInfo("session_started"));
ADD_SIGNAL(MethodInfo("session_ended"));
ADD_SIGNAL(MethodInfo("session_failed", PropertyInfo(Variant::STRING, "message")));
- ADD_SIGNAL(MethodInfo("selectstart", PropertyInfo(Variant::INT, "controller_id")));
- ADD_SIGNAL(MethodInfo("select", PropertyInfo(Variant::INT, "controller_id")));
- ADD_SIGNAL(MethodInfo("selectend", PropertyInfo(Variant::INT, "controller_id")));
- ADD_SIGNAL(MethodInfo("squeezestart", PropertyInfo(Variant::INT, "controller_id")));
- ADD_SIGNAL(MethodInfo("squeeze", PropertyInfo(Variant::INT, "controller_id")));
- ADD_SIGNAL(MethodInfo("squeezeend", PropertyInfo(Variant::INT, "controller_id")));
+ ADD_SIGNAL(MethodInfo("selectstart", PropertyInfo(Variant::INT, "input_source_id")));
+ ADD_SIGNAL(MethodInfo("select", PropertyInfo(Variant::INT, "input_source_id")));
+ ADD_SIGNAL(MethodInfo("selectend", PropertyInfo(Variant::INT, "input_source_id")));
+ ADD_SIGNAL(MethodInfo("squeezestart", PropertyInfo(Variant::INT, "input_source_id")));
+ ADD_SIGNAL(MethodInfo("squeeze", PropertyInfo(Variant::INT, "input_source_id")));
+ ADD_SIGNAL(MethodInfo("squeezeend", PropertyInfo(Variant::INT, "input_source_id")));
ADD_SIGNAL(MethodInfo("visibility_state_changed"));
ADD_SIGNAL(MethodInfo("reference_space_reset"));
+
+ BIND_ENUM_CONSTANT(TARGET_RAY_MODE_UNKNOWN);
+ BIND_ENUM_CONSTANT(TARGET_RAY_MODE_GAZE);
+ BIND_ENUM_CONSTANT(TARGET_RAY_MODE_TRACKED_POINTER);
+ BIND_ENUM_CONSTANT(TARGET_RAY_MODE_SCREEN);
}
diff --git a/modules/webxr/webxr_interface.h b/modules/webxr/webxr_interface.h
index 801643bfa6..1afeb5bab0 100644
--- a/modules/webxr/webxr_interface.h
+++ b/modules/webxr/webxr_interface.h
@@ -45,6 +45,13 @@ protected:
static void _bind_methods();
public:
+ enum TargetRayMode {
+ TARGET_RAY_MODE_UNKNOWN,
+ TARGET_RAY_MODE_GAZE,
+ TARGET_RAY_MODE_TRACKED_POINTER,
+ TARGET_RAY_MODE_SCREEN,
+ };
+
virtual void is_session_supported(const String &p_session_mode) = 0;
virtual void set_session_mode(String p_session_mode) = 0;
virtual String get_session_mode() const = 0;
@@ -55,9 +62,12 @@ public:
virtual void set_requested_reference_space_types(String p_requested_reference_space_types) = 0;
virtual String get_requested_reference_space_types() const = 0;
virtual String get_reference_space_type() const = 0;
- virtual Ref<XRPositionalTracker> get_controller(int p_controller_id) const = 0;
+ virtual bool is_input_source_active(int p_input_source_id) const = 0;
+ virtual Ref<XRPositionalTracker> get_input_source_tracker(int p_input_source_id) const = 0;
+ virtual TargetRayMode get_input_source_target_ray_mode(int p_input_source_id) const = 0;
virtual String get_visibility_state() const = 0;
- virtual PackedVector3Array get_bounds_geometry() const = 0;
};
+VARIANT_ENUM_CAST(WebXRInterface::TargetRayMode);
+
#endif // WEBXR_INTERFACE_H
diff --git a/modules/webxr/webxr_interface_js.cpp b/modules/webxr/webxr_interface_js.cpp
index f6ed9f027e..265f6626a7 100644
--- a/modules/webxr/webxr_interface_js.cpp
+++ b/modules/webxr/webxr_interface_js.cpp
@@ -37,6 +37,8 @@
#include "drivers/gles3/storage/texture_storage.h"
#include "emscripten.h"
#include "godot_webxr.h"
+#include "scene/main/scene_tree.h"
+#include "scene/main/window.h"
#include "servers/rendering/renderer_compositor.h"
#include "servers/rendering/rendering_server_globals.h"
@@ -89,25 +91,14 @@ void _emwebxr_on_session_failed(char *p_message) {
interface->emit_signal(SNAME("session_failed"), message);
}
-void _emwebxr_on_controller_changed() {
+extern "C" EMSCRIPTEN_KEEPALIVE void _emwebxr_on_input_event(int p_event_type, int p_input_source_id) {
XRServer *xr_server = XRServer::get_singleton();
ERR_FAIL_NULL(xr_server);
Ref<XRInterface> interface = xr_server->find_interface("WebXR");
ERR_FAIL_COND(interface.is_null());
- static_cast<WebXRInterfaceJS *>(interface.ptr())->_on_controller_changed();
-}
-
-extern "C" EMSCRIPTEN_KEEPALIVE void _emwebxr_on_input_event(char *p_signal_name, int p_input_source) {
- XRServer *xr_server = XRServer::get_singleton();
- ERR_FAIL_NULL(xr_server);
-
- Ref<XRInterface> interface = xr_server->find_interface("WebXR");
- ERR_FAIL_COND(interface.is_null());
-
- StringName signal_name = StringName(p_signal_name);
- interface->emit_signal(signal_name, p_input_source + 1);
+ ((WebXRInterfaceJS *)interface.ptr())->_on_input_event(p_event_type, p_input_source_id);
}
extern "C" EMSCRIPTEN_KEEPALIVE void _emwebxr_on_simple_event(char *p_signal_name) {
@@ -165,16 +156,22 @@ String WebXRInterfaceJS::get_reference_space_type() const {
return reference_space_type;
}
-Ref<XRPositionalTracker> WebXRInterfaceJS::get_controller(int p_controller_id) const {
- XRServer *xr_server = XRServer::get_singleton();
- ERR_FAIL_NULL_V(xr_server, Ref<XRPositionalTracker>());
+bool WebXRInterfaceJS::is_input_source_active(int p_input_source_id) const {
+ ERR_FAIL_INDEX_V(p_input_source_id, input_source_count, false);
+ return input_sources[p_input_source_id].active;
+}
- // TODO support more then two controllers
- if (p_controller_id >= 0 && p_controller_id < 2) {
- return controllers[p_controller_id];
- };
+Ref<XRPositionalTracker> WebXRInterfaceJS::get_input_source_tracker(int p_input_source_id) const {
+ ERR_FAIL_INDEX_V(p_input_source_id, input_source_count, Ref<XRPositionalTracker>());
+ return input_sources[p_input_source_id].tracker;
+}
- return Ref<XRPositionalTracker>();
+WebXRInterface::TargetRayMode WebXRInterfaceJS::get_input_source_target_ray_mode(int p_input_source_id) const {
+ ERR_FAIL_INDEX_V(p_input_source_id, input_source_count, WebXRInterface::TARGET_RAY_MODE_UNKNOWN);
+ if (!input_sources[p_input_source_id].active) {
+ return WebXRInterface::TARGET_RAY_MODE_UNKNOWN;
+ }
+ return input_sources[p_input_source_id].target_ray_mode;
}
String WebXRInterfaceJS::get_visibility_state() const {
@@ -188,17 +185,18 @@ String WebXRInterfaceJS::get_visibility_state() const {
return String();
}
-PackedVector3Array WebXRInterfaceJS::get_bounds_geometry() const {
+PackedVector3Array WebXRInterfaceJS::get_play_area() const {
PackedVector3Array ret;
- int *js_bounds = godot_webxr_get_bounds_geometry();
- if (js_bounds) {
- ret.resize(js_bounds[0]);
- for (int i = 0; i < js_bounds[0]; i++) {
- float *js_vector3 = ((float *)js_bounds) + (i * 3) + 1;
+ float *points;
+ int point_count = godot_webxr_get_bounds_geometry(&points);
+ if (point_count > 0) {
+ ret.resize(point_count);
+ for (int i = 0; i < point_count; i++) {
+ float *js_vector3 = points + (i * 3);
ret.set(i, Vector3(js_vector3[0], js_vector3[1], js_vector3[2]));
}
- free(js_bounds);
+ free(points);
}
return ret;
@@ -209,7 +207,7 @@ StringName WebXRInterfaceJS::get_name() const {
};
uint32_t WebXRInterfaceJS::get_capabilities() const {
- return XRInterface::XR_STEREO | XRInterface::XR_MONO;
+ return XRInterface::XR_STEREO | XRInterface::XR_MONO | XRInterface::XR_VR | XRInterface::XR_AR;
};
uint32_t WebXRInterfaceJS::get_view_count() {
@@ -261,7 +259,6 @@ bool WebXRInterfaceJS::initialize() {
&_emwebxr_on_session_started,
&_emwebxr_on_session_ended,
&_emwebxr_on_session_failed,
- &_emwebxr_on_controller_changed,
&_emwebxr_on_input_event,
&_emwebxr_on_simple_event);
};
@@ -287,6 +284,18 @@ void WebXRInterfaceJS::uninitialize() {
godot_webxr_uninitialize();
+ GLES3::TextureStorage *texture_storage = dynamic_cast<GLES3::TextureStorage *>(RSG::texture_storage);
+ if (texture_storage != nullptr) {
+ for (KeyValue<unsigned int, RID> &E : texture_cache) {
+ // Forcibly mark as not part of a render target so we can free it.
+ GLES3::Texture *texture = texture_storage->get_texture(E.value);
+ texture->is_render_target = false;
+
+ texture_storage->texture_free(E.value);
+ }
+ }
+
+ texture_cache.clear();
reference_space_type = "";
initialized = false;
};
@@ -316,27 +325,26 @@ Size2 WebXRInterfaceJS::get_render_target_size() {
return render_targetsize;
}
- int *js_size = godot_webxr_get_render_target_size();
- if (!initialized || js_size == nullptr) {
- // As a temporary default (until WebXR is fully initialized), use half the window size.
- Size2 temp = DisplayServer::get_singleton()->window_get_size();
- temp.width /= 2.0;
- return temp;
- }
+ int js_size[2];
+ bool has_size = godot_webxr_get_render_target_size(js_size);
- render_targetsize.width = js_size[0];
- render_targetsize.height = js_size[1];
+ if (!initialized || !has_size) {
+ // As a temporary default (until WebXR is fully initialized), use the
+ // window size.
+ return DisplayServer::get_singleton()->window_get_size();
+ }
- free(js_size);
+ render_targetsize.width = (float)js_size[0];
+ render_targetsize.height = (float)js_size[1];
return render_targetsize;
};
Transform3D WebXRInterfaceJS::get_camera_transform() {
- Transform3D transform_for_eye;
+ Transform3D camera_transform;
XRServer *xr_server = XRServer::get_singleton();
- ERR_FAIL_NULL_V(xr_server, transform_for_eye);
+ ERR_FAIL_NULL_V(xr_server, camera_transform);
if (initialized) {
float world_scale = xr_server->get_world_scale();
@@ -345,181 +353,382 @@ Transform3D WebXRInterfaceJS::get_camera_transform() {
Transform3D _head_transform = head_transform;
_head_transform.origin *= world_scale;
- transform_for_eye = (xr_server->get_reference_frame()) * _head_transform;
+ camera_transform = (xr_server->get_reference_frame()) * _head_transform;
}
- return transform_for_eye;
+ return camera_transform;
};
Transform3D WebXRInterfaceJS::get_transform_for_view(uint32_t p_view, const Transform3D &p_cam_transform) {
- Transform3D transform_for_eye;
-
XRServer *xr_server = XRServer::get_singleton();
- ERR_FAIL_NULL_V(xr_server, transform_for_eye);
+ ERR_FAIL_NULL_V(xr_server, p_cam_transform);
+ ERR_FAIL_COND_V(!initialized, p_cam_transform);
- float *js_matrix = godot_webxr_get_transform_for_eye(p_view + 1);
- if (!initialized || js_matrix == nullptr) {
- transform_for_eye = p_cam_transform;
- return transform_for_eye;
+ float js_matrix[16];
+ bool has_transform = godot_webxr_get_transform_for_view(p_view, js_matrix);
+ if (!has_transform) {
+ return p_cam_transform;
}
- transform_for_eye = _js_matrix_to_transform(js_matrix);
- free(js_matrix);
+ Transform3D transform_for_view = _js_matrix_to_transform(js_matrix);
float world_scale = xr_server->get_world_scale();
// Scale only the center point of our eye transform, so we don't scale the
// distance between the eyes.
Transform3D _head_transform = head_transform;
- transform_for_eye.origin -= _head_transform.origin;
+ transform_for_view.origin -= _head_transform.origin;
_head_transform.origin *= world_scale;
- transform_for_eye.origin += _head_transform.origin;
+ transform_for_view.origin += _head_transform.origin;
- return p_cam_transform * xr_server->get_reference_frame() * transform_for_eye;
+ return p_cam_transform * xr_server->get_reference_frame() * transform_for_view;
};
Projection WebXRInterfaceJS::get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) {
- Projection eye;
+ Projection view;
+
+ ERR_FAIL_COND_V(!initialized, view);
- float *js_matrix = godot_webxr_get_projection_for_eye(p_view + 1);
- if (!initialized || js_matrix == nullptr) {
- return eye;
+ float js_matrix[16];
+ bool has_projection = godot_webxr_get_projection_for_view(p_view, js_matrix);
+ if (!has_projection) {
+ return view;
}
int k = 0;
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
- eye.columns[i][j] = js_matrix[k++];
+ view.columns[i][j] = js_matrix[k++];
}
}
- free(js_matrix);
-
// Copied from godot_oculus_mobile's ovr_mobile_session.cpp
- eye.columns[2][2] = -(p_z_far + p_z_near) / (p_z_far - p_z_near);
- eye.columns[3][2] = -(2.0f * p_z_far * p_z_near) / (p_z_far - p_z_near);
+ view.columns[2][2] = -(p_z_far + p_z_near) / (p_z_far - p_z_near);
+ view.columns[3][2] = -(2.0f * p_z_far * p_z_near) / (p_z_far - p_z_near);
- return eye;
+ return view;
+}
+
+bool WebXRInterfaceJS::pre_draw_viewport(RID p_render_target) {
+ GLES3::TextureStorage *texture_storage = dynamic_cast<GLES3::TextureStorage *>(RSG::texture_storage);
+ if (texture_storage == nullptr) {
+ return false;
+ }
+
+ GLES3::RenderTarget *rt = texture_storage->get_render_target(p_render_target);
+ if (rt == nullptr) {
+ return false;
+ }
+
+ // Cache the resources so we don't have to get them from JS twice.
+ color_texture = _get_color_texture();
+ depth_texture = _get_depth_texture();
+
+ // Per the WebXR spec, it returns "opaque textures" to us, which may be the
+ // same WebGLTexture object (which would be the same GLuint in C++) but
+ // represent a different underlying resource (probably the next texture in
+ // the XR device's swap chain). In order to render to this texture, we need
+ // to re-attach it to the FBO, otherwise we get an "incomplete FBO" error.
+ //
+ // See: https://immersive-web.github.io/layers/#xropaquetextures
+ //
+ // This is why we're doing this sort of silly check: if the color and depth
+ // textures are the same this frame as last frame, we need to attach them
+ // again, despite the fact that the GLuint for them hasn't changed.
+ if (rt->overridden.is_overridden && rt->overridden.color == color_texture && rt->overridden.depth == depth_texture) {
+ GLES3::Config *config = GLES3::Config::get_singleton();
+ bool use_multiview = rt->view_count > 1 && config->multiview_supported;
+
+ glBindFramebuffer(GL_FRAMEBUFFER, rt->fbo);
+ if (use_multiview) {
+ glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, rt->color, 0, 0, rt->view_count);
+ glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, rt->depth, 0, 0, rt->view_count);
+ } else {
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->color, 0);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, rt->depth, 0);
+ }
+ glBindFramebuffer(GL_FRAMEBUFFER, texture_storage->system_fbo);
+ }
+
+ return true;
}
Vector<BlitToScreen> WebXRInterfaceJS::post_draw_viewport(RID p_render_target, const Rect2 &p_screen_rect) {
Vector<BlitToScreen> blit_to_screen;
- if (!initialized) {
- return blit_to_screen;
+ // We don't need to do anything here.
+
+ return blit_to_screen;
+};
+
+RID WebXRInterfaceJS::_get_color_texture() {
+ unsigned int texture_id = godot_webxr_get_color_texture();
+ if (texture_id == 0) {
+ return RID();
+ }
+
+ return _get_texture(texture_id);
+}
+
+RID WebXRInterfaceJS::_get_depth_texture() {
+ unsigned int texture_id = godot_webxr_get_depth_texture();
+ if (texture_id == 0) {
+ return RID();
+ }
+
+ return _get_texture(texture_id);
+}
+
+RID WebXRInterfaceJS::_get_texture(unsigned int p_texture_id) {
+ RBMap<unsigned int, RID>::Element *cache = texture_cache.find(p_texture_id);
+ if (cache != nullptr) {
+ return cache->get();
}
GLES3::TextureStorage *texture_storage = dynamic_cast<GLES3::TextureStorage *>(RSG::texture_storage);
- if (!texture_storage) {
- return blit_to_screen;
+ if (texture_storage == nullptr) {
+ return RID();
}
- GLES3::RenderTarget *rt = texture_storage->get_render_target(p_render_target);
+ uint32_t view_count = godot_webxr_get_view_count();
+ Size2 texture_size = get_render_target_size();
- godot_webxr_commit(rt->color);
+ RID texture = texture_storage->texture_create_external(
+ view_count == 1 ? GLES3::Texture::TYPE_2D : GLES3::Texture::TYPE_LAYERED,
+ Image::FORMAT_RGBA8,
+ p_texture_id,
+ (int)texture_size.width,
+ (int)texture_size.height,
+ 1,
+ view_count);
- return blit_to_screen;
-};
+ texture_cache.insert(p_texture_id, texture);
+
+ return texture;
+}
+
+RID WebXRInterfaceJS::get_color_texture() {
+ return color_texture;
+}
+
+RID WebXRInterfaceJS::get_depth_texture() {
+ return depth_texture;
+}
+
+RID WebXRInterfaceJS::get_velocity_texture() {
+ unsigned int texture_id = godot_webxr_get_velocity_texture();
+ if (texture_id == 0) {
+ return RID();
+ }
+
+ return _get_texture(texture_id);
+}
void WebXRInterfaceJS::process() {
if (initialized) {
// Get the "head" position.
- float *js_matrix = godot_webxr_get_transform_for_eye(0);
- if (js_matrix != nullptr) {
+ float js_matrix[16];
+ if (godot_webxr_get_transform_for_view(-1, js_matrix)) {
head_transform = _js_matrix_to_transform(js_matrix);
- free(js_matrix);
}
if (head_tracker.is_valid()) {
head_tracker->set_pose("default", head_transform, Vector3(), Vector3());
}
- godot_webxr_sample_controller_data();
- int controller_count = godot_webxr_get_controller_count();
- for (int i = 0; i < controller_count; i++) {
- _update_tracker(i);
+ // Update all input sources.
+ for (int i = 0; i < input_source_count; i++) {
+ _update_input_source(i);
}
};
};
-void WebXRInterfaceJS::_update_tracker(int p_controller_id) {
+void WebXRInterfaceJS::_update_input_source(int p_input_source_id) {
XRServer *xr_server = XRServer::get_singleton();
ERR_FAIL_NULL(xr_server);
- // need to support more then two controllers...
- if (p_controller_id < 0 || p_controller_id > 1) {
+ InputSource &input_source = input_sources[p_input_source_id];
+
+ float target_pose[16];
+ int tmp_target_ray_mode;
+ int touch_index;
+ int has_grip_pose;
+ float grip_pose[16];
+ int has_standard_mapping;
+ int button_count;
+ float buttons[10];
+ int axes_count;
+ float axes[10];
+
+ input_source.active = godot_webxr_update_input_source(
+ p_input_source_id,
+ target_pose,
+ &tmp_target_ray_mode,
+ &touch_index,
+ &has_grip_pose,
+ grip_pose,
+ &has_standard_mapping,
+ &button_count,
+ buttons,
+ &axes_count,
+ axes);
+
+ if (!input_source.active) {
+ if (input_source.tracker.is_valid()) {
+ xr_server->remove_tracker(input_source.tracker);
+ input_source.tracker.unref();
+ }
return;
}
- Ref<XRPositionalTracker> tracker = controllers[p_controller_id];
- if (godot_webxr_is_controller_connected(p_controller_id)) {
- if (tracker.is_null()) {
- tracker.instantiate();
- tracker->set_tracker_type(XRServer::TRACKER_CONTROLLER);
- // Controller id's 0 and 1 are always the left and right hands.
- if (p_controller_id < 2) {
- tracker->set_tracker_name(p_controller_id == 0 ? "left_hand" : "right_hand");
- tracker->set_tracker_desc(p_controller_id == 0 ? "Left hand controller" : "Right hand controller");
- tracker->set_tracker_hand(p_controller_id == 0 ? XRPositionalTracker::TRACKER_HAND_LEFT : XRPositionalTracker::TRACKER_HAND_RIGHT);
- } else {
- char name[1024];
- sprintf(name, "tracker_%i", p_controller_id);
- tracker->set_tracker_name(name);
- tracker->set_tracker_desc(name);
- }
- xr_server->add_tracker(tracker);
+ input_source.target_ray_mode = (WebXRInterface::TargetRayMode)tmp_target_ray_mode;
+ input_source.touch_index = touch_index;
+
+ Ref<XRPositionalTracker> &tracker = input_source.tracker;
+
+ if (tracker.is_null()) {
+ tracker.instantiate();
+
+ StringName tracker_name;
+ if (input_source.target_ray_mode == WebXRInterface::TargetRayMode::TARGET_RAY_MODE_SCREEN) {
+ tracker_name = touch_names[touch_index];
+ } else {
+ tracker_name = tracker_names[p_input_source_id];
}
- float *tracker_matrix = godot_webxr_get_controller_transform(p_controller_id);
- if (tracker_matrix) {
- // Note, poses should NOT have world scale and our reference frame applied!
- Transform3D transform = _js_matrix_to_transform(tracker_matrix);
- tracker->set_pose("default", transform, Vector3(), Vector3());
- free(tracker_matrix);
+ // Input source id's 0 and 1 are always the left and right hands.
+ if (p_input_source_id < 2) {
+ tracker->set_tracker_type(XRServer::TRACKER_CONTROLLER);
+ tracker->set_tracker_name(tracker_name);
+ tracker->set_tracker_desc(p_input_source_id == 0 ? "Left hand controller" : "Right hand controller");
+ tracker->set_tracker_hand(p_input_source_id == 0 ? XRPositionalTracker::TRACKER_HAND_LEFT : XRPositionalTracker::TRACKER_HAND_RIGHT);
+ } else {
+ tracker->set_tracker_name(tracker_name);
+ tracker->set_tracker_desc(tracker_name);
}
+ xr_server->add_tracker(tracker);
+ }
- // TODO implement additional poses such as "aim" and "grip"
+ Transform3D aim_transform = _js_matrix_to_transform(target_pose);
+ tracker->set_pose(SNAME("default"), aim_transform, Vector3(), Vector3());
+ tracker->set_pose(SNAME("aim"), aim_transform, Vector3(), Vector3());
+ if (has_grip_pose) {
+ tracker->set_pose(SNAME("grip"), _js_matrix_to_transform(grip_pose), Vector3(), Vector3());
+ }
- int *buttons = godot_webxr_get_controller_buttons(p_controller_id);
- if (buttons) {
- // TODO buttons should be named properly, this is just a temporary fix
- for (int i = 0; i < buttons[0]; i++) {
- char name[1024];
- sprintf(name, "button_%i", i);
+ for (int i = 0; i < button_count; i++) {
+ StringName button_name = has_standard_mapping ? standard_button_names[i] : unknown_button_names[i];
+ StringName button_pressure_name = has_standard_mapping ? standard_button_pressure_names[i] : unknown_button_pressure_names[i];
+ float value = buttons[i];
+ bool state = value > 0.0;
+ tracker->set_input(button_name, state);
+ tracker->set_input(button_pressure_name, value);
+ }
- float value = *((float *)buttons + (i + 1));
- bool state = value > 0.0;
- tracker->set_input(name, state);
- }
- free(buttons);
+ for (int i = 0; i < axes_count; i++) {
+ StringName axis_name = has_standard_mapping ? standard_axis_names[i] : unknown_axis_names[i];
+ float value = axes[i];
+ if (has_standard_mapping && (i == 1 || i == 3)) {
+ // Invert the Y-axis on thumbsticks and trackpads, in order to
+ // match OpenXR and other XR platform SDKs.
+ value = -value;
}
+ tracker->set_input(axis_name, value);
+ }
- int *axes = godot_webxr_get_controller_axes(p_controller_id);
- if (axes) {
- // TODO again just a temporary fix, split these between proper float and vector2 inputs
- for (int i = 0; i < axes[0]; i++) {
- char name[1024];
- sprintf(name, "axis_%i", i);
+ // Also create Vector2's for the thumbstick and trackpad when we have the
+ // standard mapping.
+ if (has_standard_mapping) {
+ if (axes_count >= 2) {
+ tracker->set_input(standard_vector_names[0], Vector2(axes[0], -axes[1]));
+ }
+ if (axes_count >= 4) {
+ tracker->set_input(standard_vector_names[1], Vector2(axes[2], -axes[3]));
+ }
+ }
- float value = *((float *)axes + (i + 1));
- tracker->set_input(name, value);
+ if (input_source.target_ray_mode == WebXRInterface::TARGET_RAY_MODE_SCREEN) {
+ if (touch_index < 5 && axes_count >= 2) {
+ Vector2 joy_vector = Vector2(axes[0], axes[1]);
+ Vector2 position = _get_screen_position_from_joy_vector(joy_vector);
+
+ if (touches[touch_index].is_touching) {
+ Vector2 delta = position - touches[touch_index].position;
+
+ // If position has changed by at least 1 pixel, generate a drag event.
+ if (abs(delta.x) >= 1.0 || abs(delta.y) >= 1.0) {
+ Ref<InputEventScreenDrag> event;
+ event.instantiate();
+ event->set_index(touch_index);
+ event->set_position(position);
+ event->set_relative(delta);
+ Input::get_singleton()->parse_input_event(event);
+ }
}
- free(axes);
+
+ touches[touch_index].position = position;
}
- } else if (tracker.is_valid()) {
- xr_server->remove_tracker(tracker);
- controllers[p_controller_id].unref();
}
}
-void WebXRInterfaceJS::_on_controller_changed() {
- // Register "virtual" gamepads with Godot for the ones we get from WebXR.
- godot_webxr_sample_controller_data();
- for (int i = 0; i < 2; i++) {
- bool controller_connected = godot_webxr_is_controller_connected(i);
- if (controllers_state[i] != controller_connected) {
- // Input::get_singleton()->joy_connection_changed(i + 100, controller_connected, i == 0 ? "Left" : "Right", "");
- controllers_state[i] = controller_connected;
+void WebXRInterfaceJS::_on_input_event(int p_event_type, int p_input_source_id) {
+ // Get the latest data for this input source. For transient input sources,
+ // we may not have any data at all yet!
+ _update_input_source(p_input_source_id);
+
+ if (p_event_type == WEBXR_INPUT_EVENT_SELECTSTART || p_event_type == WEBXR_INPUT_EVENT_SELECTEND) {
+ const InputSource &input_source = input_sources[p_input_source_id];
+ if (input_source.target_ray_mode == WebXRInterface::TARGET_RAY_MODE_SCREEN) {
+ int touch_index = input_source.touch_index;
+ if (touch_index >= 0 && touch_index < 5) {
+ touches[touch_index].is_touching = (p_event_type == WEBXR_INPUT_EVENT_SELECTSTART);
+
+ Ref<InputEventScreenTouch> event;
+ event.instantiate();
+ event->set_index(touch_index);
+ event->set_position(touches[touch_index].position);
+ event->set_pressed(p_event_type == WEBXR_INPUT_EVENT_SELECTSTART);
+
+ Input::get_singleton()->parse_input_event(event);
+ }
}
}
+
+ switch (p_event_type) {
+ case WEBXR_INPUT_EVENT_SELECTSTART:
+ emit_signal("selectstart", p_input_source_id);
+ break;
+
+ case WEBXR_INPUT_EVENT_SELECTEND:
+ emit_signal("selectend", p_input_source_id);
+ // Emit the 'select' event on our own (rather than intercepting the
+ // one from JavaScript) so that we don't have to needlessly call
+ // _update_input_source() a second time.
+ emit_signal("select", p_input_source_id);
+ break;
+
+ case WEBXR_INPUT_EVENT_SQUEEZESTART:
+ emit_signal("squeezestart", p_input_source_id);
+ break;
+
+ case WEBXR_INPUT_EVENT_SQUEEZEEND:
+ emit_signal("squeezeend", p_input_source_id);
+ // Again, we emit the 'squeeze' event on our own to avoid extra work.
+ emit_signal("squeeze", p_input_source_id);
+ break;
+ }
+}
+
+Vector2 WebXRInterfaceJS::_get_screen_position_from_joy_vector(const Vector2 &p_joy_vector) {
+ SceneTree *scene_tree = Object::cast_to<SceneTree>(OS::get_singleton()->get_main_loop());
+ if (!scene_tree) {
+ return Vector2();
+ }
+
+ Window *viewport = scene_tree->get_root();
+
+ Vector2 position_percentage((p_joy_vector.x + 1.0f) / 2.0f, ((p_joy_vector.y) + 1.0f) / 2.0f);
+ Vector2 position = (Size2)viewport->get_size() * position_percentage;
+
+ return position;
}
WebXRInterfaceJS::WebXRInterfaceJS() {
diff --git a/modules/webxr/webxr_interface_js.h b/modules/webxr/webxr_interface_js.h
index 319adc2ac9..6b484a8872 100644
--- a/modules/webxr/webxr_interface_js.h
+++ b/modules/webxr/webxr_interface_js.h
@@ -39,6 +39,10 @@
The WebXR interface is a VR/AR interface that can be used on the web.
*/
+namespace GLES3 {
+class TextureStorage;
+}
+
class WebXRInterfaceJS : public WebXRInterface {
GDCLASS(WebXRInterfaceJS, WebXRInterface);
@@ -53,13 +57,32 @@ private:
String requested_reference_space_types;
String reference_space_type;
- // TODO maybe turn into a vector to support more then 2 controllers...
- bool controllers_state[2];
- Ref<XRPositionalTracker> controllers[2];
Size2 render_targetsize;
-
+ RBMap<unsigned int, RID> texture_cache;
+ struct Touch {
+ bool is_touching = false;
+ Vector2 position;
+ } touches[5];
+
+ static constexpr uint8_t input_source_count = 16;
+
+ struct InputSource {
+ Ref<XRPositionalTracker> tracker;
+ bool active = false;
+ TargetRayMode target_ray_mode;
+ int touch_index = -1;
+ } input_sources[input_source_count];
+
+ RID color_texture;
+ RID depth_texture;
+
+ RID _get_color_texture();
+ RID _get_depth_texture();
+ RID _get_texture(unsigned int p_texture_id);
Transform3D _js_matrix_to_transform(float *p_js_matrix);
- void _update_tracker(int p_controller_id);
+ void _update_input_source(int p_input_source_id);
+
+ Vector2 _get_screen_position_from_joy_vector(const Vector2 &p_joy_vector);
public:
virtual void is_session_supported(const String &p_session_mode) override;
@@ -73,9 +96,11 @@ public:
virtual String get_requested_reference_space_types() const override;
void _set_reference_space_type(String p_reference_space_type);
virtual String get_reference_space_type() const override;
- virtual Ref<XRPositionalTracker> get_controller(int p_controller_id) const override;
+ virtual bool is_input_source_active(int p_input_source_id) const override;
+ virtual Ref<XRPositionalTracker> get_input_source_tracker(int p_input_source_id) const override;
+ virtual TargetRayMode get_input_source_target_ray_mode(int p_input_source_id) const override;
virtual String get_visibility_state() const override;
- virtual PackedVector3Array get_bounds_geometry() const override;
+ virtual PackedVector3Array get_play_area() const override;
virtual StringName get_name() const override;
virtual uint32_t get_capabilities() const override;
@@ -89,14 +114,129 @@ public:
virtual Transform3D get_camera_transform() override;
virtual Transform3D get_transform_for_view(uint32_t p_view, const Transform3D &p_cam_transform) override;
virtual Projection get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) override;
+ virtual bool pre_draw_viewport(RID p_render_target) override;
virtual Vector<BlitToScreen> post_draw_viewport(RID p_render_target, const Rect2 &p_screen_rect) override;
+ virtual RID get_color_texture() override;
+ virtual RID get_depth_texture() override;
+ virtual RID get_velocity_texture() override;
virtual void process() override;
- void _on_controller_changed();
+ void _on_input_event(int p_event_type, int p_input_source_id);
WebXRInterfaceJS();
~WebXRInterfaceJS();
+
+private:
+ StringName tracker_names[16] = {
+ StringName("left_hand"),
+ StringName("right_hand"),
+ StringName("tracker_2"),
+ StringName("tracker_3"),
+ StringName("tracker_4"),
+ StringName("tracker_5"),
+ StringName("tracker_6"),
+ StringName("tracker_7"),
+ StringName("tracker_8"),
+ StringName("tracker_9"),
+ StringName("tracker_10"),
+ StringName("tracker_11"),
+ StringName("tracker_12"),
+ StringName("tracker_13"),
+ StringName("tracker_14"),
+ StringName("tracker_15"),
+ };
+
+ StringName touch_names[5] = {
+ StringName("touch_0"),
+ StringName("touch_1"),
+ StringName("touch_2"),
+ StringName("touch_3"),
+ StringName("touch_4"),
+ };
+
+ StringName standard_axis_names[10] = {
+ StringName("touchpad_x"),
+ StringName("touchpad_y"),
+ StringName("thumbstick_x"),
+ StringName("thumbstick_y"),
+ StringName("axis_4"),
+ StringName("axis_5"),
+ StringName("axis_6"),
+ StringName("axis_7"),
+ StringName("axis_8"),
+ StringName("axis_9"),
+ };
+
+ StringName standard_vector_names[2] = {
+ StringName("touchpad"),
+ StringName("thumbstick"),
+ };
+
+ StringName standard_button_names[10] = {
+ StringName("trigger_click"),
+ StringName("grip_click"),
+ StringName("touchpad_click"),
+ StringName("thumbstick_click"),
+ StringName("ax_button"),
+ StringName("by_button"),
+ StringName("button_6"),
+ StringName("button_7"),
+ StringName("button_8"),
+ StringName("button_9"),
+ };
+
+ StringName standard_button_pressure_names[10] = {
+ StringName("trigger"),
+ StringName("grip"),
+ StringName("touchpad_click_pressure"),
+ StringName("thumbstick_click_pressure"),
+ StringName("ax_button_pressure"),
+ StringName("by_button_pressure"),
+ StringName("button_pressure_6"),
+ StringName("button_pressure_7"),
+ StringName("button_pressure_8"),
+ StringName("button_pressure_9"),
+ };
+
+ StringName unknown_button_names[10] = {
+ StringName("button_0"),
+ StringName("button_1"),
+ StringName("button_2"),
+ StringName("button_3"),
+ StringName("button_4"),
+ StringName("button_5"),
+ StringName("button_6"),
+ StringName("button_7"),
+ StringName("button_8"),
+ StringName("button_9"),
+ };
+
+ StringName unknown_axis_names[10] = {
+ StringName("axis_0"),
+ StringName("axis_1"),
+ StringName("axis_2"),
+ StringName("axis_3"),
+ StringName("axis_4"),
+ StringName("axis_5"),
+ StringName("axis_6"),
+ StringName("axis_7"),
+ StringName("axis_8"),
+ StringName("axis_9"),
+ };
+
+ StringName unknown_button_pressure_names[10] = {
+ StringName("button_pressure_0"),
+ StringName("button_pressure_1"),
+ StringName("button_pressure_2"),
+ StringName("button_pressure_3"),
+ StringName("button_pressure_4"),
+ StringName("button_pressure_5"),
+ StringName("button_pressure_6"),
+ StringName("button_pressure_7"),
+ StringName("button_pressure_8"),
+ StringName("button_pressure_9"),
+ };
};
#endif // WEB_ENABLED
diff --git a/modules/zip/doc_classes/ZIPReader.xml b/modules/zip/doc_classes/ZIPReader.xml
index 717116a531..055201b105 100644
--- a/modules/zip/doc_classes/ZIPReader.xml
+++ b/modules/zip/doc_classes/ZIPReader.xml
@@ -9,7 +9,7 @@
func read_zip_file():
var reader := ZIPReader.new()
var err := reader.open("user://archive.zip")
- if err == OK:
+ if err != OK:
return PackedByteArray()
var res := reader.read_file("hello.txt")
reader.close()
diff --git a/modules/zip/zip_packer.cpp b/modules/zip/zip_packer.cpp
index e62700f191..5566848087 100644
--- a/modules/zip/zip_packer.cpp
+++ b/modules/zip/zip_packer.cpp
@@ -46,7 +46,11 @@ Error ZIPPacker::open(String p_path, ZipAppend p_append) {
Error ZIPPacker::close() {
ERR_FAIL_COND_V_MSG(fa.is_null(), FAILED, "ZIPPacker cannot be closed because it is not open.");
- return zipClose(zf, NULL) == ZIP_OK ? OK : FAILED;
+ Error err = zipClose(zf, NULL) == ZIP_OK ? OK : FAILED;
+ if (err == OK) {
+ zf = NULL;
+ }
+ return err;
}
Error ZIPPacker::start_file(String p_path) {
@@ -79,11 +83,7 @@ Error ZIPPacker::write_file(Vector<uint8_t> p_data) {
Error ZIPPacker::close_file() {
ERR_FAIL_COND_V_MSG(fa.is_null(), FAILED, "ZIPPacker must be opened before use.");
- Error err = zipCloseFileInZip(zf) == ZIP_OK ? OK : FAILED;
- if (err == OK) {
- zf = NULL;
- }
- return err;
+ return zipCloseFileInZip(zf) == ZIP_OK ? OK : FAILED;
}
void ZIPPacker::_bind_methods() {
diff --git a/platform/android/api/jni_singleton.h b/platform/android/api/jni_singleton.h
index 895bc70103..afe7dcaeff 100644
--- a/platform/android/api/jni_singleton.h
+++ b/platform/android/api/jni_singleton.h
@@ -137,6 +137,18 @@ public:
ret = sarr;
env->DeleteLocalRef(arr);
} break;
+ case Variant::PACKED_INT64_ARRAY: {
+ jlongArray arr = (jlongArray)env->CallObjectMethodA(instance, E->get().method, v);
+
+ int fCount = env->GetArrayLength(arr);
+ Vector<int64_t> sarr;
+ sarr.resize(fCount);
+
+ int64_t *w = sarr.ptrw();
+ env->GetLongArrayRegion(arr, 0, fCount, w);
+ ret = sarr;
+ env->DeleteLocalRef(arr);
+ } break;
case Variant::PACKED_FLOAT32_ARRAY: {
jfloatArray arr = (jfloatArray)env->CallObjectMethodA(instance, E->get().method, v);
@@ -149,9 +161,18 @@ public:
ret = sarr;
env->DeleteLocalRef(arr);
} break;
+ case Variant::PACKED_FLOAT64_ARRAY: {
+ jdoubleArray arr = (jdoubleArray)env->CallObjectMethodA(instance, E->get().method, v);
- // TODO: This is missing 64 bits arrays, I have no idea how to do it in JNI.
+ int fCount = env->GetArrayLength(arr);
+ Vector<double> sarr;
+ sarr.resize(fCount);
+ double *w = sarr.ptrw();
+ env->GetDoubleArrayRegion(arr, 0, fCount, w);
+ ret = sarr;
+ env->DeleteLocalRef(arr);
+ } break;
case Variant::DICTIONARY: {
jobject obj = env->CallObjectMethodA(instance, E->get().method, v);
ret = _jobject_to_variant(env, obj);
diff --git a/platform/android/detect.py b/platform/android/detect.py
index 6eb8ba34ed..ec36a40941 100644
--- a/platform/android/detect.py
+++ b/platform/android/detect.py
@@ -24,7 +24,11 @@ def can_build():
def get_opts():
return [
("ANDROID_SDK_ROOT", "Path to the Android SDK", get_env_android_sdk_root()),
- ("ndk_platform", 'Target platform (android-<api>, e.g. "android-24")', "android-24"),
+ (
+ "ndk_platform",
+ 'Target platform (android-<api>, e.g. "android-' + str(get_min_target_api()) + '")',
+ "android-" + str(get_min_target_api()),
+ ),
]
@@ -46,6 +50,11 @@ def get_ndk_version():
return "23.2.8568313"
+# This is kept in sync with the value in 'platform/android/java/app/config.gradle'.
+def get_min_target_api():
+ return 21
+
+
def get_flags():
return [
("arch", "arm64"), # Default for convenience.
@@ -87,30 +96,26 @@ def configure(env: "Environment"):
)
sys.exit()
+ if get_min_sdk_version(env["ndk_platform"]) < get_min_target_api():
+ print(
+ "WARNING: minimum supported Android target api is %d. Forcing target api %d."
+ % (get_min_target_api(), get_min_target_api())
+ )
+ env["ndk_platform"] = "android-" + str(get_min_target_api())
+
install_ndk_if_needed(env)
ndk_root = env["ANDROID_NDK_ROOT"]
# Architecture
- if get_min_sdk_version(env["ndk_platform"]) < 21 and env["arch"] in ["x86_64", "arm64"]:
- print(
- 'WARNING: arch="%s" is not supported with "ndk_platform" lower than "android-21". Forcing platform 21.'
- % env["arch"]
- )
- env["ndk_platform"] = "android-21"
-
if env["arch"] == "arm32":
target_triple = "armv7a-linux-androideabi"
- env.extra_suffix = ".armv7" + env.extra_suffix
elif env["arch"] == "arm64":
target_triple = "aarch64-linux-android"
- env.extra_suffix = ".armv8" + env.extra_suffix
elif env["arch"] == "x86_32":
target_triple = "i686-linux-android"
- env.extra_suffix = ".x86" + env.extra_suffix
elif env["arch"] == "x86_64":
target_triple = "x86_64-linux-android"
- 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"])
@@ -165,7 +170,6 @@ def configure(env: "Environment"):
"-fpic -ffunction-sections -funwind-tables -fstack-protector-strong -fvisibility=hidden -fno-strict-aliasing".split()
)
)
- env.Append(CPPDEFINES=["GLES_ENABLED"])
if get_min_sdk_version(env["ndk_platform"]) >= 24:
env.Append(CPPDEFINES=[("_FILE_OFFSET_BITS", 64)])
@@ -188,9 +192,13 @@ def configure(env: "Environment"):
env.Prepend(CPPPATH=["#platform/android"])
env.Append(CPPDEFINES=["ANDROID_ENABLED", "UNIX_ENABLED"])
- env.Append(LIBS=["OpenSLES", "EGL", "GLESv2", "android", "log", "z", "dl"])
+ env.Append(LIBS=["OpenSLES", "EGL", "android", "log", "z", "dl"])
if env["vulkan"]:
env.Append(CPPDEFINES=["VULKAN_ENABLED"])
if not env["use_volk"]:
env.Append(LIBS=["vulkan"])
+
+ if env["opengl3"]:
+ env.Append(CPPDEFINES=["GLES3_ENABLED"])
+ env.Append(LIBS=["GLESv3"])
diff --git a/platform/android/display_server_android.cpp b/platform/android/display_server_android.cpp
index 967f5c7dae..9c796a8c07 100644
--- a/platform/android/display_server_android.cpp
+++ b/platform/android/display_server_android.cpp
@@ -41,6 +41,10 @@
#include "platform/android/vulkan/vulkan_context_android.h"
#include "servers/rendering/renderer_rd/renderer_compositor_rd.h"
#endif
+#ifdef GLES3_ENABLED
+#include "drivers/gles3/rasterizer_gles3.h"
+#include <EGL/egl.h>
+#endif
DisplayServerAndroid *DisplayServerAndroid::get_singleton() {
return static_cast<DisplayServerAndroid *>(DisplayServer::get_singleton());
@@ -217,7 +221,7 @@ float DisplayServerAndroid::screen_get_refresh_rate(int p_screen) const {
return godot_io_java->get_screen_refresh_rate(SCREEN_REFRESH_RATE_FALLBACK);
}
-bool DisplayServerAndroid::screen_is_touchscreen(int p_screen) const {
+bool DisplayServerAndroid::is_touchscreen_available() const {
return true;
}
@@ -312,9 +316,6 @@ DisplayServer::WindowID DisplayServerAndroid::get_window_at_screen_position(cons
int64_t DisplayServerAndroid::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: {
- return 0; // Not supported.
- }
case WINDOW_HANDLE: {
return reinterpret_cast<int64_t>(static_cast<OS_Android *>(OS::get_singleton())->get_godot_java()->get_activity());
}
@@ -322,8 +323,17 @@ int64_t DisplayServerAndroid::window_get_native_handle(HandleType p_handle_type,
return 0; // Not supported.
}
#ifdef GLES3_ENABLED
+ case DISPLAY_HANDLE: {
+ if (rendering_driver == "opengl3") {
+ return reinterpret_cast<int64_t>(eglGetCurrentDisplay());
+ }
+ return 0;
+ }
case OPENGL_CONTEXT: {
- return eglGetCurrentContext();
+ if (rendering_driver == "opengl3") {
+ return reinterpret_cast<int64_t>(eglGetCurrentContext());
+ }
+ return 0;
}
#endif
default: {
@@ -356,6 +366,10 @@ Point2i DisplayServerAndroid::window_get_position(DisplayServer::WindowID p_wind
return Point2i();
}
+Point2i DisplayServerAndroid::window_get_position_with_decorations(DisplayServer::WindowID p_window) const {
+ return Point2i();
+}
+
void DisplayServerAndroid::window_set_position(const Point2i &p_position, DisplayServer::WindowID p_window) {
// Not supported on Android.
}
@@ -388,7 +402,7 @@ Size2i DisplayServerAndroid::window_get_size(DisplayServer::WindowID p_window) c
return OS_Android::get_singleton()->get_display_size();
}
-Size2i DisplayServerAndroid::window_get_real_size(DisplayServer::WindowID p_window) const {
+Size2i DisplayServerAndroid::window_get_size_with_decorations(DisplayServer::WindowID p_window) const {
return OS_Android::get_singleton()->get_display_size();
}
@@ -449,6 +463,14 @@ DisplayServer *DisplayServerAndroid::create_func(const String &p_rendering_drive
DisplayServer *ds = memnew(DisplayServerAndroid(p_rendering_driver, p_mode, p_vsync_mode, p_flags, p_position, p_resolution, r_error));
if (r_error != OK) {
OS::get_singleton()->alert("Your video card driver does not support any of the supported Vulkan versions.", "Unable to initialize Video driver");
+ if (p_rendering_driver == "vulkan") {
+ OS::get_singleton()->alert("Your video card driver does not support the selected Vulkan version.\n"
+ "Please try exporting your game using the gl_compatibility renderer.",
+ "Unable to initialize Video driver");
+ } else {
+ OS::get_singleton()->alert("Your video card driver does not support OpenGL ES 3.0.",
+ "Unable to initialize Video driver");
+ }
}
return ds;
}
@@ -493,28 +515,11 @@ void DisplayServerAndroid::notify_surface_changed(int p_width, int p_height) {
DisplayServerAndroid::DisplayServerAndroid(const String &p_rendering_driver, DisplayServer::WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, Error &r_error) {
rendering_driver = p_rendering_driver;
- // TODO: rendering_driver is broken, change when different drivers are supported again
- rendering_driver = "vulkan";
-
keep_screen_on = GLOBAL_GET("display/window/energy_saving/keep_screen_on");
#if defined(GLES3_ENABLED)
if (rendering_driver == "opengl3") {
- bool gl_initialization_error = false;
-
- if (RasterizerGLES3::is_viable() == OK) {
- RasterizerGLES3::register_config();
- RasterizerGLES3::make_current();
- } else {
- gl_initialization_error = true;
- }
-
- if (gl_initialization_error) {
- OS::get_singleton()->alert("Your device does not support any of the supported OpenGL versions.\n"
- "Please try updating your Android version.",
- "Unable to initialize video driver");
- return;
- }
+ RasterizerGLES3::make_current();
}
#endif
@@ -619,11 +624,11 @@ MouseButton DisplayServerAndroid::mouse_get_button_state() const {
return (MouseButton)Input::get_singleton()->get_mouse_button_mask();
}
-void DisplayServerAndroid::cursor_set_shape(DisplayServer::CursorShape p_shape) {
+void DisplayServerAndroid::_cursor_set_shape_helper(CursorShape p_shape, bool force) {
if (!OS_Android::get_singleton()->get_godot_java()->get_godot_view()->can_update_pointer_icon()) {
return;
}
- if (cursor_shape == p_shape) {
+ if (cursor_shape == p_shape && !force) {
return;
}
@@ -634,10 +639,23 @@ void DisplayServerAndroid::cursor_set_shape(DisplayServer::CursorShape p_shape)
}
}
+void DisplayServerAndroid::cursor_set_shape(DisplayServer::CursorShape p_shape) {
+ _cursor_set_shape_helper(p_shape);
+}
+
DisplayServer::CursorShape DisplayServerAndroid::cursor_get_shape() const {
return cursor_shape;
}
+void DisplayServerAndroid::cursor_set_custom_image(const Ref<Resource> &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) {
+ String cursor_path = p_cursor.is_valid() ? p_cursor->get_path() : "";
+ if (!cursor_path.is_empty()) {
+ cursor_path = ProjectSettings::get_singleton()->globalize_path(cursor_path);
+ }
+ OS_Android::get_singleton()->get_godot_java()->get_godot_view()->configure_pointer_icon(android_cursors[cursor_shape], cursor_path, p_hotspot);
+ _cursor_set_shape_helper(p_shape, true);
+}
+
void DisplayServerAndroid::window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mode, WindowID p_window) {
#if defined(VULKAN_ENABLED)
context_vulkan->set_vsync_mode(p_window, p_vsync_mode);
@@ -651,3 +669,23 @@ DisplayServer::VSyncMode DisplayServerAndroid::window_get_vsync_mode(WindowID p_
return DisplayServer::VSYNC_ENABLED;
#endif
}
+
+void DisplayServerAndroid::reset_swap_buffers_flag() {
+ swap_buffers_flag = false;
+}
+
+bool DisplayServerAndroid::should_swap_buffers() const {
+ return swap_buffers_flag;
+}
+
+void DisplayServerAndroid::swap_buffers() {
+ swap_buffers_flag = true;
+}
+
+void DisplayServerAndroid::set_native_icon(const String &p_filename) {
+ // NOT SUPPORTED
+}
+
+void DisplayServerAndroid::set_icon(const Ref<Image> &p_icon) {
+ // NOT SUPPORTED
+}
diff --git a/platform/android/display_server_android.h b/platform/android/display_server_android.h
index a6bc88e048..9ed07ca971 100644
--- a/platform/android/display_server_android.h
+++ b/platform/android/display_server_android.h
@@ -66,6 +66,7 @@ class DisplayServerAndroid : public DisplayServer {
MouseMode mouse_mode = MouseMode::MOUSE_MODE_VISIBLE;
bool keep_screen_on;
+ bool swap_buffers_flag;
CursorShape cursor_shape = CursorShape::CURSOR_ARROW;
@@ -120,7 +121,7 @@ public:
virtual int screen_get_dpi(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
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 bool screen_is_touchscreen(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
+ virtual bool is_touchscreen_available() const 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;
@@ -149,6 +150,7 @@ public:
virtual void window_set_current_screen(int p_screen, WindowID p_window = MAIN_WINDOW_ID) override;
virtual Point2i window_get_position(WindowID p_window = MAIN_WINDOW_ID) const override;
+ virtual Point2i window_get_position_with_decorations(WindowID p_window = MAIN_WINDOW_ID) const override;
virtual void window_set_position(const Point2i &p_position, WindowID p_window = MAIN_WINDOW_ID) override;
virtual void window_set_transient(WindowID p_window, WindowID p_parent) override;
@@ -161,7 +163,7 @@ public:
virtual void window_set_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID) override;
virtual Size2i window_get_size(WindowID p_window = MAIN_WINDOW_ID) const override;
- virtual Size2i window_get_real_size(WindowID p_window = MAIN_WINDOW_ID) const override;
+ virtual Size2i window_get_size_with_decorations(WindowID p_window = MAIN_WINDOW_ID) const override;
virtual void window_set_mode(WindowMode p_mode, WindowID p_window = MAIN_WINDOW_ID) override;
virtual WindowMode window_get_mode(WindowID p_window = MAIN_WINDOW_ID) const override;
@@ -188,8 +190,10 @@ public:
void process_magnetometer(const Vector3 &p_magnetometer);
void process_gyroscope(const Vector3 &p_gyroscope);
+ void _cursor_set_shape_helper(CursorShape p_shape, bool force = false);
virtual void cursor_set_shape(CursorShape p_shape) override;
virtual CursorShape cursor_get_shape() const override;
+ virtual void cursor_set_custom_image(const Ref<Resource> &p_cursor, CursorShape p_shape = CURSOR_ARROW, const Vector2 &p_hotspot = Vector2()) override;
virtual void mouse_set_mode(MouseMode p_mode) override;
virtual MouseMode mouse_get_mode() const override;
@@ -204,6 +208,13 @@ public:
virtual Point2i mouse_get_position() const override;
virtual MouseButton mouse_get_button_state() const override;
+ void reset_swap_buffers_flag();
+ bool should_swap_buffers() const;
+ virtual void swap_buffers() override;
+
+ virtual void set_native_icon(const String &p_filename) override;
+ virtual void set_icon(const Ref<Image> &p_icon) override;
+
DisplayServerAndroid(const String &p_rendering_driver, WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, Error &r_error);
~DisplayServerAndroid();
};
diff --git a/platform/android/export/export_plugin.cpp b/platform/android/export/export_plugin.cpp
index 9919268375..77cfa99aee 100644
--- a/platform/android/export/export_plugin.cpp
+++ b/platform/android/export/export_plugin.cpp
@@ -205,7 +205,7 @@ static const char *LEGACY_BUILD_SPLASH_IMAGE_EXPORT_PATH = "res/drawable-nodpi-v
static const char *SPLASH_BG_COLOR_PATH = "res/drawable-nodpi/splash_bg_color.png";
static const char *LEGACY_BUILD_SPLASH_BG_COLOR_PATH = "res/drawable-nodpi-v4/splash_bg_color.png";
static const char *SPLASH_CONFIG_PATH = "res://android/build/res/drawable/splash_drawable.xml";
-static const char *GDNATIVE_LIBS_PATH = "res://android/build/libs/gdnativelibs.json";
+static const char *GDEXTENSION_LIBS_PATH = "res://android/build/libs/gdextensionlibs.json";
static const int icon_densities_count = 6;
static const char *launcher_icon_option = PNAME("launcher_icons/main_192x192");
@@ -245,7 +245,7 @@ static const int EXPORT_FORMAT_AAB = 1;
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_MIN_SDK_VERSION = 21; // Should match the value in 'platform/android/java/app/config.gradle#minSdk'
static const int DEFAULT_TARGET_SDK_VERSION = 32; // Should match the value in 'platform/android/java/app/config.gradle#targetSdk'
#ifndef ANDROID_ENABLED
@@ -703,7 +703,7 @@ Error EditorExportPlatformAndroid::save_apk_so(void *p_userdata, const SharedObj
exported = true;
String abi = abis[abi_index].abi;
String dst_path = String("lib").path_join(abi).path_join(p_so.path.get_file());
- Vector<uint8_t> array = FileAccess::get_file_as_array(p_so.path);
+ Vector<uint8_t> array = FileAccess::get_file_as_bytes(p_so.path);
Error store_err = store_in_apk(ed, dst_path, array);
ERR_FAIL_COND_V_MSG(store_err, store_err, "Cannot store in apk file '" + dst_path + "'.");
}
@@ -748,7 +748,7 @@ Error EditorExportPlatformAndroid::copy_gradle_so(void *p_userdata, const Shared
String abi = abis[abi_index].abi;
String filename = p_so.path.get_file();
String dst_path = base.path_join(type).path_join(abi).path_join(filename);
- Vector<uint8_t> data = FileAccess::get_file_as_array(p_so.path);
+ Vector<uint8_t> data = FileAccess::get_file_as_bytes(p_so.path);
print_verbose("Copying .so file from " + p_so.path + " to " + dst_path);
Error err = store_file_at_path(dst_path, data);
ERR_FAIL_COND_V_MSG(err, err, "Failed to copy .so file from " + p_so.path + " to " + dst_path);
@@ -802,7 +802,7 @@ void EditorExportPlatformAndroid::_get_permissions(const Ref<EditorExportPreset>
}
void EditorExportPlatformAndroid::_write_tmp_manifest(const Ref<EditorExportPreset> &p_preset, bool p_give_internet, bool p_debug) {
- print_verbose("Building temporary manifest..");
+ print_verbose("Building temporary manifest...");
String manifest_text =
"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
"<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n"
@@ -2011,7 +2011,10 @@ String EditorExportPlatformAndroid::get_adb_path() {
return sdk_path.path_join("platform-tools/adb" + exe_ext);
}
-String EditorExportPlatformAndroid::get_apksigner_path() {
+String EditorExportPlatformAndroid::get_apksigner_path(int p_target_sdk, bool p_check_executes) {
+ if (p_target_sdk == -1) {
+ p_target_sdk = DEFAULT_TARGET_SDK_VERSION;
+ }
String exe_ext = "";
if (OS::get_singleton()->get_name() == "Windows") {
exe_ext = ".bat";
@@ -2029,23 +2032,89 @@ String EditorExportPlatformAndroid::get_apksigner_path() {
}
// There are additional versions directories we need to go through.
- da->list_dir_begin();
- String sub_dir = da->get_next();
- while (!sub_dir.is_empty()) {
- if (!sub_dir.begins_with(".") && da->current_is_dir()) {
- // Check if the tool is here.
- String tool_path = build_tools_dir.path_join(sub_dir).path_join(apksigner_command_name);
- if (FileAccess::exists(tool_path)) {
- apksigner_path = tool_path;
- break;
+ Vector<String> dir_list = da->get_directories();
+
+ // We need to use the version of build_tools that matches the Target SDK
+ // If somehow we can't find that, we see if a version between 28 and the default target SDK exists.
+ // We need to avoid versions <= 27 because they fail on Java versions >9
+ // If we can't find that, we just use the first valid version.
+ Vector<String> ideal_versions;
+ Vector<String> other_versions;
+ Vector<String> versions;
+ bool found_target_sdk = false;
+ // We only allow for versions <= 27 if specifically set
+ int min_version = p_target_sdk <= 27 ? p_target_sdk : 28;
+ for (String sub_dir : dir_list) {
+ if (!sub_dir.begins_with(".")) {
+ Vector<String> ver_numbers = sub_dir.split(".");
+ // Dir not a version number, will use as last resort
+ if (!ver_numbers.size() || !ver_numbers[0].is_valid_int()) {
+ other_versions.push_back(sub_dir);
+ continue;
+ }
+ int ver_number = ver_numbers[0].to_int();
+ if (ver_number == p_target_sdk) {
+ found_target_sdk = true;
+ //ensure this is in front of the ones we check
+ versions.push_back(sub_dir);
+ } else {
+ if (ver_number >= min_version && ver_number <= DEFAULT_TARGET_SDK_VERSION) {
+ ideal_versions.push_back(sub_dir);
+ } else {
+ other_versions.push_back(sub_dir);
+ }
}
}
- sub_dir = da->get_next();
}
- da->list_dir_end();
+ // we will check ideal versions first, then other versions.
+ versions.append_array(ideal_versions);
+ versions.append_array(other_versions);
- if (apksigner_path.is_empty()) {
+ if (!versions.size()) {
print_error("Unable to find the 'apksigner' tool.");
+ return apksigner_path;
+ }
+
+ int i;
+ bool failed = false;
+ String version_to_use;
+
+ List<String> args;
+ args.push_back("--version");
+ String output;
+ int retval;
+ Error err;
+ for (i = 0; i < versions.size(); i++) {
+ // Check if the tool is here.
+ apksigner_path = build_tools_dir.path_join(versions[i]).path_join(apksigner_command_name);
+ if (FileAccess::exists(apksigner_path)) {
+ version_to_use = versions[i];
+ // If we aren't exporting, just break here.
+ if (!p_check_executes) {
+ break;
+ }
+ // we only check to see if it executes on export because it is slow to load
+ err = OS::get_singleton()->execute(apksigner_path, args, &output, &retval, false);
+ if (err || retval) {
+ failed = true;
+ } else {
+ break;
+ }
+ }
+ }
+ if (i == versions.size()) {
+ if (failed) {
+ print_error("All located 'apksigner' tools in " + build_tools_dir + " failed to execute");
+ return "<FAILED>";
+ } else {
+ print_error("Unable to find the 'apksigner' tool.");
+ return "";
+ }
+ }
+ if (!found_target_sdk) {
+ print_line("Could not find version of build tools that matches Target SDK, using " + version_to_use);
+ } else if (failed && found_target_sdk) {
+ print_line("Version of build tools that matches Target SDK failed to execute, using " + version_to_use);
}
return apksigner_path;
@@ -2165,8 +2234,12 @@ bool EditorExportPlatformAndroid::has_valid_export_configuration(const Ref<Edito
valid = false;
}
+ 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);
+ }
// Validate that apksigner is available
- String apksigner_path = get_apksigner_path();
+ String apksigner_path = get_apksigner_path(target_sdk_version.to_int());
if (!FileAccess::exists(apksigner_path)) {
err += TTR("Unable to find Android SDK build-tools' apksigner command.");
err += TTR("Please check in the Android SDK directory specified in Editor Settings.");
@@ -2389,9 +2462,16 @@ Error EditorExportPlatformAndroid::sign_apk(const Ref<EditorExportPreset> &p_pre
String release_keystore = p_preset->get("keystore/release");
String release_username = p_preset->get("keystore/release_user");
String release_password = p_preset->get("keystore/release_password");
-
- String apksigner = get_apksigner_path();
+ 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 apksigner = get_apksigner_path(target_sdk_version.to_int(), true);
print_verbose("Starting signing of the " + export_label + " binary using " + apksigner);
+ if (apksigner == "<FAILED>") {
+ add_message(EXPORT_MESSAGE_WARNING, TTR("Code Signing"), vformat(TTR("All 'apksigner' tools located in Android SDK 'build-tools' directory failed to execute. Please check that you have the correct version installed for your target sdk version. The resulting %s is unsigned."), export_label));
+ return OK;
+ }
if (!FileAccess::exists(apksigner)) {
add_message(EXPORT_MESSAGE_WARNING, TTR("Code Signing"), vformat(TTR("'apksigner' could not be found. Please check that the command is available in the Android SDK build-tools directory. The resulting %s is unsigned."), export_label));
return OK;
@@ -2441,20 +2521,27 @@ Error EditorExportPlatformAndroid::sign_apk(const Ref<EditorExportPreset> &p_pre
args.push_back("--ks-key-alias");
args.push_back(user);
args.push_back(export_path);
- if (p_debug) {
- // We only print verbose logs for debug builds to avoid leaking release keystore credentials.
+ if (OS::get_singleton()->is_stdout_verbose() && p_debug) {
+ // We only print verbose logs with credentials for debug builds to avoid leaking release keystore credentials.
print_verbose("Signing debug binary using: " + String("\n") + apksigner + " " + join_list(args, String(" ")));
+ } else {
+ List<String> redacted_args = List<String>(args);
+ redacted_args.find(keystore)->set("<REDACTED>");
+ redacted_args.find("pass:" + password)->set("pass:<REDACTED>");
+ redacted_args.find(user)->set("<REDACTED>");
+ print_line("Signing binary using: " + String("\n") + apksigner + " " + join_list(redacted_args, String(" ")));
}
int retval;
- output.clear();
Error err = OS::get_singleton()->execute(apksigner, args, &output, &retval, true);
if (err != OK) {
add_message(EXPORT_MESSAGE_WARNING, TTR("Code Signing"), TTR("Could not start apksigner executable."));
return err;
}
- print_verbose(output);
+ // By design, apksigner does not output credentials in its output unless --verbose is used
+ print_line(output);
if (retval) {
add_message(EXPORT_MESSAGE_WARNING, TTR("Code Signing"), vformat(TTR("'apksigner' returned with error #%d"), retval));
+ add_message(EXPORT_MESSAGE_WARNING, TTR("Code Signing"), vformat(TTR("output: \n%s"), output));
return ERR_CANT_CREATE;
}
@@ -2479,6 +2566,7 @@ Error EditorExportPlatformAndroid::sign_apk(const Ref<EditorExportPreset> &p_pre
print_verbose(output);
if (retval) {
add_message(EXPORT_MESSAGE_WARNING, TTR("Code Signing"), vformat(TTR("'apksigner' verification of %s failed."), export_label));
+ add_message(EXPORT_MESSAGE_WARNING, TTR("Code Signing"), vformat(TTR("output: \n%s"), output));
return ERR_CANT_CREATE;
}
@@ -2491,7 +2579,7 @@ void EditorExportPlatformAndroid::_clear_assets_directory() {
// Clear the APK assets directory
if (da_res->dir_exists(APK_ASSETS_DIRECTORY)) {
- print_verbose("Clearing APK assets directory..");
+ print_verbose("Clearing APK assets directory...");
Ref<DirAccess> da_assets = DirAccess::open(APK_ASSETS_DIRECTORY);
da_assets->erase_contents_recursive();
da_res->remove(APK_ASSETS_DIRECTORY);
@@ -2499,7 +2587,7 @@ void EditorExportPlatformAndroid::_clear_assets_directory() {
// Clear the AAB assets directory
if (da_res->dir_exists(AAB_ASSETS_DIRECTORY)) {
- print_verbose("Clearing AAB assets directory..");
+ print_verbose("Clearing AAB assets directory...");
Ref<DirAccess> da_assets = DirAccess::open(AAB_ASSETS_DIRECTORY);
da_assets->erase_contents_recursive();
da_res->remove(AAB_ASSETS_DIRECTORY);
@@ -2509,7 +2597,7 @@ void EditorExportPlatformAndroid::_clear_assets_directory() {
void EditorExportPlatformAndroid::_remove_copied_libs() {
print_verbose("Removing previously installed libraries...");
Error error;
- String libs_json = FileAccess::get_file_as_string(GDNATIVE_LIBS_PATH, &error);
+ String libs_json = FileAccess::get_file_as_string(GDEXTENSION_LIBS_PATH, &error);
if (error || libs_json.is_empty()) {
print_verbose("No previously installed libraries found");
return;
@@ -2525,7 +2613,7 @@ void EditorExportPlatformAndroid::_remove_copied_libs() {
print_verbose("Removing previously installed library " + libs[i]);
da->remove(libs[i]);
}
- da->remove(GDNATIVE_LIBS_PATH);
+ da->remove(GDEXTENSION_LIBS_PATH);
}
String EditorExportPlatformAndroid::join_list(const List<String> &p_parts, const String &p_separator) {
@@ -2615,10 +2703,10 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP
}
if (use_custom_build) {
- print_verbose("Starting custom build..");
+ print_verbose("Starting custom build...");
//test that installed build version is alright
{
- print_verbose("Checking build version..");
+ print_verbose("Checking build version...");
Ref<FileAccess> f = FileAccess::open("res://android/.build_version", FileAccess::READ);
if (f.is_null()) {
add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), TTR("Trying to build from a custom built template, but no version info for it exists. Please reinstall from the 'Project' menu."));
@@ -2651,7 +2739,7 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP
_clear_assets_directory();
_remove_copied_libs();
if (!apk_expansion) {
- print_verbose("Exporting project files..");
+ print_verbose("Exporting project files...");
CustomExportData user_data;
user_data.assets_directory = assets_directory;
user_data.debug = p_debug;
@@ -2661,18 +2749,18 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP
return err;
}
if (user_data.libs.size() > 0) {
- Ref<FileAccess> fa = FileAccess::open(GDNATIVE_LIBS_PATH, FileAccess::WRITE);
+ Ref<FileAccess> fa = FileAccess::open(GDEXTENSION_LIBS_PATH, FileAccess::WRITE);
fa->store_string(JSON::stringify(user_data.libs, "\t"));
}
} else {
- print_verbose("Saving apk expansion file..");
+ print_verbose("Saving apk expansion file...");
err = save_apk_expansion_file(p_preset, p_debug, p_path);
if (err != OK) {
add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), TTR("Could not write expansion package file!"));
return err;
}
}
- print_verbose("Storing command line flags..");
+ print_verbose("Storing command line flags...");
store_file_at_path(assets_directory + "/_cl_", command_line_flags);
print_verbose("Updating ANDROID_HOME environment to " + sdk_path);
@@ -2825,7 +2913,7 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP
return OK;
}
// This is the start of the Legacy build system
- print_verbose("Starting legacy build system..");
+ print_verbose("Starting legacy build system...");
if (p_debug) {
src_apk = p_preset->get("custom_template/debug");
} else {
diff --git a/platform/android/export/export_plugin.h b/platform/android/export/export_plugin.h
index c8fcb761fe..b9630858d3 100644
--- a/platform/android/export/export_plugin.h
+++ b/platform/android/export/export_plugin.h
@@ -201,7 +201,7 @@ public:
static String get_adb_path();
- static String get_apksigner_path();
+ static String get_apksigner_path(int p_target_sdk = -1, bool p_check_executes = false);
virtual bool has_valid_export_configuration(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) const override;
virtual bool has_valid_project_configuration(const Ref<EditorExportPreset> &p_preset, String &r_error) const override;
diff --git a/platform/android/java/app/AndroidManifest.xml b/platform/android/java/app/AndroidManifest.xml
index 2d4c4763a2..1db135826a 100644
--- a/platform/android/java/app/AndroidManifest.xml
+++ b/platform/android/java/app/AndroidManifest.xml
@@ -13,7 +13,7 @@
android:xlargeScreens="true" />
<uses-feature
- android:glEsVersion="0x00020000"
+ android:glEsVersion="0x00030000"
android:required="true" />
<application
diff --git a/platform/android/java/app/config.gradle b/platform/android/java/app/config.gradle
index e1d9dc4cde..f1b4bfd534 100644
--- a/platform/android/java/app/config.gradle
+++ b/platform/android/java/app/config.gradle
@@ -1,14 +1,17 @@
ext.versions = [
androidGradlePlugin: '7.2.1',
compileSdk : 32,
- minSdk : 19, // Also update 'platform/android/export/export_plugin.cpp#DEFAULT_MIN_SDK_VERSION'
- targetSdk : 32, // Also update 'platform/android/export/export_plugin.cpp#DEFAULT_TARGET_SDK_VERSION'
+ // Also update 'platform/android/export/export_plugin.cpp#DEFAULT_MIN_SDK_VERSION'
+ minSdk : 21,
+ // Also update 'platform/android/export/export_plugin.cpp#DEFAULT_TARGET_SDK_VERSION'
+ targetSdk : 32,
buildTools : '32.0.0',
kotlinVersion : '1.7.0',
fragmentVersion : '1.3.6',
nexusPublishVersion: '1.1.0',
javaVersion : 11,
- ndkVersion : '23.2.8568313' // Also update 'platform/android/detect.py#get_ndk_version()' when this is updated.
+ // Also update 'platform/android/detect.py#get_ndk_version()' when this is updated.
+ ndkVersion : '23.2.8568313'
]
diff --git a/platform/android/java/editor/src/main/AndroidManifest.xml b/platform/android/java/editor/src/main/AndroidManifest.xml
index 6aa5f06f31..80ef10b6a4 100644
--- a/platform/android/java/editor/src/main/AndroidManifest.xml
+++ b/platform/android/java/editor/src/main/AndroidManifest.xml
@@ -11,7 +11,7 @@
android:xlargeScreens="true" />
<uses-feature
- android:glEsVersion="0x00020000"
+ android:glEsVersion="0x00030000"
android:required="true" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"
@@ -27,6 +27,7 @@
android:icon="@mipmap/icon"
android:label="@string/godot_editor_name_string"
tools:ignore="GoogleAppIndexingWarning"
+ android:theme="@style/GodotEditorTheme"
android:requestLegacyExternalStorage="true">
<activity
@@ -35,7 +36,6 @@
android:launchMode="singleTask"
android:screenOrientation="userLandscape"
android:exported="true"
- android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen"
android:process=":GodotProjectManager">
<layout android:defaultHeight="@dimen/editor_default_window_height"
@@ -53,8 +53,7 @@
android:process=":GodotEditor"
android:launchMode="singleTask"
android:screenOrientation="userLandscape"
- android:exported="false"
- android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen">
+ android:exported="false">
<layout android:defaultHeight="@dimen/editor_default_window_height"
android:defaultWidth="@dimen/editor_default_window_width" />
</activity>
@@ -66,8 +65,7 @@
android:process=":GodotGame"
android:launchMode="singleTask"
android:exported="false"
- android:screenOrientation="userLandscape"
- android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen">
+ android:screenOrientation="userLandscape">
<layout android:defaultHeight="@dimen/editor_default_window_height"
android:defaultWidth="@dimen/editor_default_window_width" />
</activity>
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 489a81fc1a..46a334ef38 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
@@ -37,10 +37,12 @@ import android.os.Build
import android.os.Bundle
import android.os.Debug
import android.os.Environment
+import android.util.Log
import android.widget.Toast
import androidx.window.layout.WindowMetricsCalculator
import org.godotengine.godot.FullScreenGodotApp
import org.godotengine.godot.utils.PermissionsUtil
+import org.godotengine.godot.utils.ProcessPhoenix
import java.util.*
import kotlin.math.min
@@ -56,12 +58,17 @@ import kotlin.math.min
open class GodotEditor : FullScreenGodotApp() {
companion object {
+ private val TAG = GodotEditor::class.java.simpleName
+
private const val WAIT_FOR_DEBUGGER = false
private const val COMMAND_LINE_PARAMS = "command_line_params"
private const val EDITOR_ARG = "--editor"
+ private const val EDITOR_ARG_SHORT = "-e"
+
private const val PROJECT_MANAGER_ARG = "--project-manager"
+ private const val PROJECT_MANAGER_ARG_SHORT = "-p"
}
private val commandLineParams = ArrayList<String>()
@@ -105,13 +112,13 @@ open class GodotEditor : FullScreenGodotApp() {
Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && (isInMultiWindowMode || isLargeScreen)
for (arg in args) {
- if (EDITOR_ARG == arg) {
+ if (EDITOR_ARG == arg || EDITOR_ARG_SHORT == arg) {
targetClass = GodotEditor::class.java
launchAdjacent = false
break
}
- if (PROJECT_MANAGER_ARG == arg) {
+ if (PROJECT_MANAGER_ARG == arg || PROJECT_MANAGER_ARG_SHORT == arg) {
targetClass = GodotProjectManager::class.java
launchAdjacent = false
break
@@ -125,7 +132,13 @@ open class GodotEditor : FullScreenGodotApp() {
if (launchAdjacent) {
newInstance.addFlags(Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT)
}
- startActivity(newInstance)
+ if (targetClass == javaClass) {
+ Log.d(TAG, "Restarting $targetClass")
+ ProcessPhoenix.triggerRebirth(this, newInstance)
+ } else {
+ Log.d(TAG, "Starting $targetClass")
+ startActivity(newInstance)
+ }
}
// Get the screen's density scale
diff --git a/platform/android/java/editor/src/main/res/values/themes.xml b/platform/android/java/editor/src/main/res/values/themes.xml
new file mode 100644
index 0000000000..fda04d6dc7
--- /dev/null
+++ b/platform/android/java/editor/src/main/res/values/themes.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <style name="GodotEditorTheme" parent="@android:style/Theme.Black.NoTitleBar.Fullscreen">
+ </style>
+</resources>
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 92e5e59496..3487e5019c 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/Godot.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/Godot.java
@@ -175,6 +175,7 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC
public GodotIO io;
public GodotNetUtils netUtils;
public GodotTTS tts;
+ DirectoryAccessHandler directoryAccessHandler;
public interface ResultCallback {
void callback(int requestCode, int resultCode, Intent data);
@@ -299,7 +300,7 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC
for (GodotPlugin plugin : pluginRegistry.getAllPlugins()) {
plugin.onRegisterPluginWithGodotNative();
}
- setKeepScreenOn("True".equals(GodotLib.getGlobal("display/window/energy_saving/keep_screen_on")));
+ setKeepScreenOn(Boolean.parseBoolean(GodotLib.getGlobal("display/window/energy_saving/keep_screen_on")));
});
// Include the returned non-null views in the Godot view hierarchy.
@@ -488,7 +489,7 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC
netUtils = new GodotNetUtils(activity);
tts = new GodotTTS(activity);
Context context = getContext();
- DirectoryAccessHandler directoryAccessHandler = new DirectoryAccessHandler(context);
+ directoryAccessHandler = new DirectoryAccessHandler(context);
FileAccessHandler fileAccessHandler = new FileAccessHandler(context);
mSensorManager = (SensorManager)activity.getSystemService(Context.SENSOR_SERVICE);
mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotGLRenderView.java b/platform/android/java/lib/src/org/godotengine/godot/GodotGLRenderView.java
index 3dfc37f6b0..f8d937521b 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/GodotGLRenderView.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/GodotGLRenderView.java
@@ -43,8 +43,13 @@ import org.godotengine.godot.xr.regular.RegularFallbackConfigChooser;
import android.annotation.SuppressLint;
import android.content.Context;
+import android.content.res.AssetManager;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
import android.graphics.PixelFormat;
import android.os.Build;
+import android.text.TextUtils;
+import android.util.SparseArray;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.PointerIcon;
@@ -52,6 +57,8 @@ import android.view.SurfaceView;
import androidx.annotation.Keep;
+import java.io.InputStream;
+
/**
* A simple GLSurfaceView sub-class that demonstrate how to perform
* OpenGL ES 2.0 rendering into a GL Surface. Note the following important
@@ -61,7 +68,7 @@ import androidx.annotation.Keep;
* See ContextFactory class definition below.
*
* - The class must use a custom EGLConfigChooser to be able to select
- * an EGLConfig that supports 2.0. This is done by providing a config
+ * an EGLConfig that supports 3.0. This is done by providing a config
* specification to eglChooseConfig() that has the attribute
* EGL10.ELG_RENDERABLE_TYPE containing the EGL_OPENGL_ES2_BIT flag
* set. See ConfigChooser class definition below.
@@ -74,6 +81,7 @@ public class GodotGLRenderView extends GLSurfaceView implements GodotRenderView
private final Godot godot;
private final GodotInputHandler inputHandler;
private final GodotRenderer godotRenderer;
+ private final SparseArray<PointerIcon> customPointerIcons = new SparseArray<>();
public GodotGLRenderView(Context context, Godot godot, XRMode xrMode, boolean p_use_debug_opengl) {
super(context);
@@ -169,12 +177,49 @@ public class GodotGLRenderView extends GLSurfaceView implements GodotRenderView
}
/**
+ * Used to configure the PointerIcon for the given type.
+ *
+ * Called from JNI
+ */
+ @Keep
+ @Override
+ public void configurePointerIcon(int pointerType, String imagePath, float hotSpotX, float hotSpotY) {
+ if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
+ try {
+ Bitmap bitmap = null;
+ if (!TextUtils.isEmpty(imagePath)) {
+ if (godot.directoryAccessHandler.filesystemFileExists(imagePath)) {
+ // Try to load the bitmap from the file system
+ bitmap = BitmapFactory.decodeFile(imagePath);
+ } else if (godot.directoryAccessHandler.assetsFileExists(imagePath)) {
+ // Try to load the bitmap from the assets directory
+ AssetManager am = getContext().getAssets();
+ InputStream imageInputStream = am.open(imagePath);
+ bitmap = BitmapFactory.decodeStream(imageInputStream);
+ }
+ }
+
+ PointerIcon customPointerIcon = PointerIcon.create(bitmap, hotSpotX, hotSpotY);
+ customPointerIcons.put(pointerType, customPointerIcon);
+ } catch (Exception e) {
+ // Reset the custom pointer icon
+ customPointerIcons.delete(pointerType);
+ }
+ }
+ }
+
+ /**
* called from JNI to change pointer icon
*/
@Keep
+ @Override
public void setPointerIcon(int pointerType) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
- setPointerIcon(PointerIcon.getSystemIcon(getContext(), pointerType));
+ PointerIcon pointerIcon = customPointerIcons.get(pointerType);
+ if (pointerIcon == null) {
+ pointerIcon = PointerIcon.getSystemIcon(getContext(), pointerType);
+ }
+ setPointerIcon(pointerIcon);
}
}
diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotRenderView.java b/platform/android/java/lib/src/org/godotengine/godot/GodotRenderView.java
index cb63fd885f..ab74ba037d 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/GodotRenderView.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/GodotRenderView.java
@@ -48,5 +48,7 @@ public interface GodotRenderView {
GodotInputHandler getInputHandler();
+ void configurePointerIcon(int pointerType, String imagePath, float hotSpotX, float hotSpotY);
+
void setPointerIcon(int pointerType);
}
diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotVulkanRenderView.java b/platform/android/java/lib/src/org/godotengine/godot/GodotVulkanRenderView.java
index 0becf00d93..56bc7f9e76 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/GodotVulkanRenderView.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/GodotVulkanRenderView.java
@@ -36,7 +36,12 @@ import org.godotengine.godot.vulkan.VkSurfaceView;
import android.annotation.SuppressLint;
import android.content.Context;
+import android.content.res.AssetManager;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
import android.os.Build;
+import android.text.TextUtils;
+import android.util.SparseArray;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.PointerIcon;
@@ -44,10 +49,13 @@ import android.view.SurfaceView;
import androidx.annotation.Keep;
+import java.io.InputStream;
+
public class GodotVulkanRenderView extends VkSurfaceView implements GodotRenderView {
private final Godot godot;
private final GodotInputHandler mInputHandler;
private final VkRenderer mRenderer;
+ private final SparseArray<PointerIcon> customPointerIcons = new SparseArray<>();
public GodotVulkanRenderView(Context context, Godot godot) {
super(context);
@@ -143,12 +151,49 @@ public class GodotVulkanRenderView extends VkSurfaceView implements GodotRenderV
}
/**
+ * Used to configure the PointerIcon for the given type.
+ *
+ * Called from JNI
+ */
+ @Keep
+ @Override
+ public void configurePointerIcon(int pointerType, String imagePath, float hotSpotX, float hotSpotY) {
+ if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
+ try {
+ Bitmap bitmap = null;
+ if (!TextUtils.isEmpty(imagePath)) {
+ if (godot.directoryAccessHandler.filesystemFileExists(imagePath)) {
+ // Try to load the bitmap from the file system
+ bitmap = BitmapFactory.decodeFile(imagePath);
+ } else if (godot.directoryAccessHandler.assetsFileExists(imagePath)) {
+ // Try to load the bitmap from the assets directory
+ AssetManager am = getContext().getAssets();
+ InputStream imageInputStream = am.open(imagePath);
+ bitmap = BitmapFactory.decodeStream(imageInputStream);
+ }
+ }
+
+ PointerIcon customPointerIcon = PointerIcon.create(bitmap, hotSpotX, hotSpotY);
+ customPointerIcons.put(pointerType, customPointerIcon);
+ } catch (Exception e) {
+ // Reset the custom pointer icon
+ customPointerIcons.delete(pointerType);
+ }
+ }
+ }
+
+ /**
* called from JNI to change pointer icon
*/
@Keep
+ @Override
public void setPointerIcon(int pointerType) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
- setPointerIcon(PointerIcon.getSystemIcon(getContext(), pointerType));
+ PointerIcon pointerIcon = customPointerIcons.get(pointerType);
+ if (pointerIcon == null) {
+ pointerIcon = PointerIcon.getSystemIcon(getContext(), pointerType);
+ }
+ setPointerIcon(pointerIcon);
}
}
diff --git a/platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java b/platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java
index 2f26497cc8..0ba86e4316 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java
@@ -422,7 +422,7 @@ public class GodotInputHandler implements InputManager.InputDeviceListener {
}
private static boolean isMouseEvent(int eventSource) {
- boolean mouseSource = ((eventSource & InputDevice.SOURCE_MOUSE) == InputDevice.SOURCE_MOUSE) || ((eventSource & InputDevice.SOURCE_STYLUS) == InputDevice.SOURCE_STYLUS);
+ boolean mouseSource = ((eventSource & InputDevice.SOURCE_MOUSE) == InputDevice.SOURCE_MOUSE) || ((eventSource & (InputDevice.SOURCE_TOUCHSCREEN | InputDevice.SOURCE_STYLUS)) == InputDevice.SOURCE_STYLUS);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
mouseSource = mouseSource || ((eventSource & InputDevice.SOURCE_MOUSE_RELATIVE) == InputDevice.SOURCE_MOUSE_RELATIVE);
}
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
index c9282dd247..1a3576a6a9 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/io/StorageScope.kt
+++ b/platform/android/java/lib/src/org/godotengine/godot/io/StorageScope.kt
@@ -90,6 +90,11 @@ internal enum class StorageScope {
return APP
}
+ var rootDir: String? = System.getenv("ANDROID_ROOT")
+ if (rootDir != null && canonicalPathFile.startsWith(rootDir)) {
+ 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
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
index fedcf4843f..6bc317415f 100644
--- 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
@@ -79,6 +79,9 @@ class DirectoryAccessHandler(context: Context) {
private val assetsDirAccess = AssetsDirectoryAccess(context)
private val fileSystemDirAccess = FilesystemDirectoryAccess(context)
+ fun assetsFileExists(assetsPath: String) = assetsDirAccess.fileExists(assetsPath)
+ fun filesystemFileExists(path: String) = fileSystemDirAccess.fileExists(path)
+
private fun hasDirId(accessType: AccessType, dirId: Int): Boolean {
return when (accessType) {
ACCESS_RESOURCES -> assetsDirAccess.hasDirId(dirId)
diff --git a/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPlugin.java b/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPlugin.java
index bb5042fa09..8ca5bcaa6e 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPlugin.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPlugin.java
@@ -71,11 +71,11 @@ import javax.microedition.khronos.opengles.GL10;
* - 'plugin.init.ClassFullName' is the full name (package + class name) of the plugin class
* extending {@link GodotPlugin}.
*
- * A plugin can also define and provide c/c++ gdnative libraries and nativescripts for the target
+ * A plugin can also define and provide c/c++ gdextension libraries and nativescripts for the target
* app/game to leverage.
- * The shared library for the gdnative library will be automatically bundled by the aar build
+ * The shared library for the gdextension library will be automatically bundled by the aar build
* system.
- * Godot '*.gdnlib' and '*.gdns' resource files must however be manually defined in the project
+ * Godot '*.gdextension' resource files must however be manually defined in the project
* 'assets' directory. The recommended path for these resources in the 'assets' directory should be:
* 'godot/plugin/v1/[PluginName]/'
*/
@@ -112,7 +112,7 @@ public abstract class GodotPlugin {
public final void onRegisterPluginWithGodotNative() {
registeredSignals.putAll(
registerPluginWithGodotNative(this, getPluginName(), getPluginMethods(), getPluginSignals(),
- getPluginGDNativeLibrariesPaths()));
+ getPluginGDExtensionLibrariesPaths()));
}
/**
@@ -124,7 +124,7 @@ public abstract class GodotPlugin {
GodotPluginInfoProvider pluginInfoProvider) {
registerPluginWithGodotNative(pluginObject, pluginInfoProvider.getPluginName(),
Collections.emptyList(), pluginInfoProvider.getPluginSignals(),
- pluginInfoProvider.getPluginGDNativeLibrariesPaths());
+ pluginInfoProvider.getPluginGDExtensionLibrariesPaths());
// Notify that registration is complete.
pluginInfoProvider.onPluginRegistered();
@@ -132,7 +132,7 @@ public abstract class GodotPlugin {
private static Map<String, SignalInfo> registerPluginWithGodotNative(Object pluginObject,
String pluginName, List<String> pluginMethods, Set<SignalInfo> pluginSignals,
- Set<String> pluginGDNativeLibrariesPaths) {
+ Set<String> pluginGDExtensionLibrariesPaths) {
nativeRegisterSingleton(pluginName, pluginObject);
Set<Method> filteredMethods = new HashSet<>();
@@ -176,9 +176,9 @@ public abstract class GodotPlugin {
registeredSignals.put(signalName, signalInfo);
}
- // Get the list of gdnative libraries to register.
- if (!pluginGDNativeLibrariesPaths.isEmpty()) {
- nativeRegisterGDNativeLibraries(pluginGDNativeLibrariesPaths.toArray(new String[0]));
+ // Get the list of gdextension libraries to register.
+ if (!pluginGDExtensionLibrariesPaths.isEmpty()) {
+ nativeRegisterGDExtensionLibraries(pluginGDExtensionLibrariesPaths.toArray(new String[0]));
}
return registeredSignals;
@@ -304,12 +304,12 @@ public abstract class GodotPlugin {
}
/**
- * Returns the paths for the plugin's gdnative libraries.
+ * Returns the paths for the plugin's gdextension libraries.
*
- * The paths must be relative to the 'assets' directory and point to a '*.gdnlib' file.
+ * The paths must be relative to the 'assets' directory and point to a '*.gdextension' file.
*/
@NonNull
- protected Set<String> getPluginGDNativeLibrariesPaths() {
+ protected Set<String> getPluginGDExtensionLibrariesPaths() {
return Collections.emptySet();
}
@@ -420,10 +420,10 @@ public abstract class GodotPlugin {
private static native void nativeRegisterMethod(String p_sname, String p_name, String p_ret, String[] p_params);
/**
- * Used to register gdnative libraries bundled by the plugin.
- * @param gdnlibPaths Paths to the libraries relative to the 'assets' directory.
+ * Used to register gdextension libraries bundled by the plugin.
+ * @param gdextensionPaths Paths to the libraries relative to the 'assets' directory.
*/
- private static native void nativeRegisterGDNativeLibraries(String[] gdnlibPaths);
+ private static native void nativeRegisterGDExtensionLibraries(String[] gdextensionPaths);
/**
* Used to complete registration of the {@link GodotPlugin} instance's methods.
diff --git a/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPluginInfoProvider.java b/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPluginInfoProvider.java
index cfb84c3931..53b78aebfb 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPluginInfoProvider.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPluginInfoProvider.java
@@ -54,12 +54,12 @@ public interface GodotPluginInfoProvider {
}
/**
- * Returns the paths for the plugin's gdnative libraries (if any).
+ * Returns the paths for the plugin's gdextension libraries (if any).
*
- * The paths must be relative to the 'assets' directory and point to a '*.gdnlib' file.
+ * The paths must be relative to the 'assets' directory and point to a '*.gdextension' file.
*/
@NonNull
- default Set<String> getPluginGDNativeLibrariesPaths() {
+ default Set<String> getPluginGDExtensionLibrariesPaths() {
return Collections.emptySet();
}
diff --git a/platform/android/java/lib/src/org/godotengine/godot/xr/regular/RegularConfigChooser.java b/platform/android/java/lib/src/org/godotengine/godot/xr/regular/RegularConfigChooser.java
index 445238b1c2..9834fdfb88 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/xr/regular/RegularConfigChooser.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/xr/regular/RegularConfigChooser.java
@@ -45,20 +45,18 @@ public class RegularConfigChooser implements GLSurfaceView.EGLConfigChooser {
private int[] mValue = new int[1];
- // FIXME: Add support for Vulkan.
-
- /* This EGL config specification is used to specify 2.0 rendering.
+ /* This EGL config specification is used to specify 3.0 rendering.
* We use a minimum size of 4 bits for red/green/blue, but will
* perform actual matching in chooseConfig() below.
*/
private static int EGL_OPENGL_ES2_BIT = 4;
- private static int[] s_configAttribs2 = {
+ private static int[] s_configAttribs = {
EGL10.EGL_RED_SIZE, 4,
EGL10.EGL_GREEN_SIZE, 4,
EGL10.EGL_BLUE_SIZE, 4,
- // EGL10.EGL_DEPTH_SIZE, 16,
+ // EGL10.EGL_DEPTH_SIZE, 16,
// EGL10.EGL_STENCIL_SIZE, EGL10.EGL_DONT_CARE,
- EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+ EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, //apparently there is no EGL_OPENGL_ES3_BIT
EGL10.EGL_NONE
};
@@ -75,7 +73,7 @@ public class RegularConfigChooser implements GLSurfaceView.EGLConfigChooser {
/* Get the number of minimally matching EGL configurations
*/
int[] num_config = new int[1];
- egl.eglChooseConfig(display, s_configAttribs2, null, 0, num_config);
+ egl.eglChooseConfig(display, s_configAttribs, null, 0, num_config);
int numConfigs = num_config[0];
@@ -86,7 +84,7 @@ public class RegularConfigChooser implements GLSurfaceView.EGLConfigChooser {
/* Allocate then read the array of minimally matching EGL configs
*/
EGLConfig[] configs = new EGLConfig[numConfigs];
- egl.eglChooseConfig(display, s_configAttribs2, configs, numConfigs, num_config);
+ egl.eglChooseConfig(display, s_configAttribs, configs, numConfigs, num_config);
if (GLUtils.DEBUG) {
GLUtils.printConfigs(egl, display, configs);
diff --git a/platform/android/java/lib/src/org/godotengine/godot/xr/regular/RegularContextFactory.java b/platform/android/java/lib/src/org/godotengine/godot/xr/regular/RegularContextFactory.java
index 5d62723170..8fb86bf6d0 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/xr/regular/RegularContextFactory.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/xr/regular/RegularContextFactory.java
@@ -52,17 +52,16 @@ public class RegularContextFactory implements GLSurfaceView.EGLContextFactory {
private static int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
public EGLContext createContext(EGL10 egl, EGLDisplay display, EGLConfig eglConfig) {
- // FIXME: Add support for Vulkan.
- Log.w(TAG, "creating OpenGL ES 2.0 context :");
+ Log.w(TAG, "creating OpenGL ES 3.0 context :");
GLUtils.checkEglError(TAG, "Before eglCreateContext", egl);
EGLContext context;
if (GLUtils.use_debug_opengl) {
- int[] attrib_list2 = { EGL_CONTEXT_CLIENT_VERSION, 2, _EGL_CONTEXT_FLAGS_KHR, _EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR, EGL10.EGL_NONE };
- context = egl.eglCreateContext(display, eglConfig, EGL10.EGL_NO_CONTEXT, attrib_list2);
+ int[] attrib_list = { EGL_CONTEXT_CLIENT_VERSION, 3, _EGL_CONTEXT_FLAGS_KHR, _EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR, EGL10.EGL_NONE };
+ context = egl.eglCreateContext(display, eglConfig, EGL10.EGL_NO_CONTEXT, attrib_list);
} else {
- int[] attrib_list2 = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL10.EGL_NONE };
- context = egl.eglCreateContext(display, eglConfig, EGL10.EGL_NO_CONTEXT, attrib_list2);
+ int[] attrib_list = { EGL_CONTEXT_CLIENT_VERSION, 3, EGL10.EGL_NONE };
+ context = egl.eglCreateContext(display, eglConfig, EGL10.EGL_NO_CONTEXT, attrib_list);
}
GLUtils.checkEglError(TAG, "After eglCreateContext", egl);
return context;
diff --git a/platform/android/java/nativeSrcsConfigs/CMakeLists.txt b/platform/android/java/nativeSrcsConfigs/CMakeLists.txt
index 711f7cd502..e1534c7685 100644
--- a/platform/android/java/nativeSrcsConfigs/CMakeLists.txt
+++ b/platform/android/java/nativeSrcsConfigs/CMakeLists.txt
@@ -17,4 +17,4 @@ target_include_directories(${PROJECT_NAME}
SYSTEM PUBLIC
${GODOT_ROOT_DIR})
-add_definitions(-DUNIX_ENABLED -DVULKAN_ENABLED -DANDROID_ENABLED)
+add_definitions(-DUNIX_ENABLED -DVULKAN_ENABLED -DANDROID_ENABLED -DGLES3_ENABLED -DTOOLS_ENABLED)
diff --git a/platform/android/java_godot_lib_jni.cpp b/platform/android/java_godot_lib_jni.cpp
index b5cb9d341d..c2c25601d7 100644
--- a/platform/android/java_godot_lib_jni.cpp
+++ b/platform/android/java_godot_lib_jni.cpp
@@ -71,6 +71,39 @@ static Vector3 gravity;
static Vector3 magnetometer;
static Vector3 gyroscope;
+static void _terminate(JNIEnv *env, bool p_restart = false) {
+ step.set(-1); // Ensure no further steps are attempted and no further events are sent
+
+ // lets cleanup
+ if (java_class_wrapper) {
+ memdelete(java_class_wrapper);
+ }
+ if (input_handler) {
+ delete input_handler;
+ }
+ // Whether restarting is handled by 'Main::cleanup()'
+ bool restart_on_cleanup = false;
+ if (os_android) {
+ restart_on_cleanup = os_android->is_restart_on_exit_set();
+ os_android->main_loop_end();
+ Main::cleanup();
+ delete os_android;
+ }
+ if (godot_io_java) {
+ delete godot_io_java;
+ }
+ if (godot_java) {
+ if (!restart_on_cleanup) {
+ if (p_restart) {
+ godot_java->restart(env);
+ } else {
+ godot_java->force_quit(env);
+ }
+ }
+ delete godot_java;
+ }
+}
+
extern "C" {
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_setVirtualKeyboardHeight(JNIEnv *env, jclass clazz, jint p_height) {
@@ -104,23 +137,7 @@ JNIEXPORT jboolean JNICALL Java_org_godotengine_godot_GodotLib_initialize(JNIEnv
}
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_ondestroy(JNIEnv *env, jclass clazz) {
- // lets cleanup
- if (java_class_wrapper) {
- memdelete(java_class_wrapper);
- }
- if (godot_io_java) {
- delete godot_io_java;
- }
- if (godot_java) {
- delete godot_java;
- }
- if (input_handler) {
- delete input_handler;
- }
- if (os_android) {
- os_android->main_loop_end();
- delete os_android;
- }
+ _terminate(env, false);
}
JNIEXPORT jboolean JNICALL Java_org_godotengine_godot_GodotLib_setup(JNIEnv *env, jclass clazz, jobjectArray p_cmdline) {
@@ -196,9 +213,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_newcontext(JNIEnv *en
}
} else {
// Rendering context recreated because it was lost; restart app to let it reload everything
- step.set(-1); // Ensure no further steps are attempted and no further events are sent
- os_android->main_loop_end();
- godot_java->restart(env);
+ _terminate(env, true);
}
}
}
@@ -249,7 +264,7 @@ JNIEXPORT jboolean JNICALL Java_org_godotengine_godot_GodotLib_step(JNIEnv *env,
bool should_swap_buffers = false;
if (os_android->main_loop_iterate(&should_swap_buffers)) {
- godot_java->force_quit(env);
+ _terminate(env, false);
}
return should_swap_buffers;
diff --git a/platform/android/java_godot_view_wrapper.cpp b/platform/android/java_godot_view_wrapper.cpp
index 378a467772..23cfc5f2e6 100644
--- a/platform/android/java_godot_view_wrapper.cpp
+++ b/platform/android/java_godot_view_wrapper.cpp
@@ -42,6 +42,7 @@ GodotJavaViewWrapper::GodotJavaViewWrapper(jobject godot_view) {
int android_device_api_level = android_get_device_api_level();
if (android_device_api_level >= __ANDROID_API_N__) {
+ _configure_pointer_icon = env->GetMethodID(_cls, "configurePointerIcon", "(ILjava/lang/String;FF)V");
_set_pointer_icon = env->GetMethodID(_cls, "setPointerIcon", "(I)V");
}
if (android_device_api_level >= __ANDROID_API_O__) {
@@ -51,7 +52,7 @@ GodotJavaViewWrapper::GodotJavaViewWrapper(jobject godot_view) {
}
bool GodotJavaViewWrapper::can_update_pointer_icon() const {
- return _set_pointer_icon != nullptr;
+ return _configure_pointer_icon != nullptr && _set_pointer_icon != nullptr;
}
bool GodotJavaViewWrapper::can_capture_pointer() const {
@@ -76,6 +77,16 @@ void GodotJavaViewWrapper::release_pointer_capture() {
}
}
+void GodotJavaViewWrapper::configure_pointer_icon(int pointer_type, const String &image_path, const Vector2 &p_hotspot) {
+ if (_configure_pointer_icon != nullptr) {
+ JNIEnv *env = get_jni_env();
+ ERR_FAIL_NULL(env);
+
+ jstring jImagePath = env->NewStringUTF(image_path.utf8().get_data());
+ env->CallVoidMethod(_godot_view, _configure_pointer_icon, pointer_type, jImagePath, p_hotspot.x, p_hotspot.y);
+ }
+}
+
void GodotJavaViewWrapper::set_pointer_icon(int pointer_type) {
if (_set_pointer_icon != nullptr) {
JNIEnv *env = get_jni_env();
diff --git a/platform/android/java_godot_view_wrapper.h b/platform/android/java_godot_view_wrapper.h
index b398c73cac..b58a6607ce 100644
--- a/platform/android/java_godot_view_wrapper.h
+++ b/platform/android/java_godot_view_wrapper.h
@@ -31,6 +31,7 @@
#ifndef JAVA_GODOT_VIEW_WRAPPER_H
#define JAVA_GODOT_VIEW_WRAPPER_H
+#include "core/math/vector2.h"
#include <android/log.h>
#include <jni.h>
@@ -45,6 +46,8 @@ private:
jmethodID _request_pointer_capture = 0;
jmethodID _release_pointer_capture = 0;
+
+ jmethodID _configure_pointer_icon = 0;
jmethodID _set_pointer_icon = 0;
public:
@@ -55,6 +58,8 @@ public:
void request_pointer_capture();
void release_pointer_capture();
+
+ void configure_pointer_icon(int pointer_type, const String &image_path, const Vector2 &p_hotspot);
void set_pointer_icon(int pointer_type);
~GodotJavaViewWrapper();
diff --git a/platform/android/jni_utils.cpp b/platform/android/jni_utils.cpp
index 2b0ee50570..8b29670542 100644
--- a/platform/android/jni_utils.cpp
+++ b/platform/android/jni_utils.cpp
@@ -149,6 +149,15 @@ jvalret _variant_to_jvalue(JNIEnv *env, Variant::Type p_type, const Variant *p_a
v.obj = arr;
} break;
+ case Variant::PACKED_INT64_ARRAY: {
+ Vector<int64_t> array = *p_arg;
+ jlongArray arr = env->NewLongArray(array.size());
+ const int64_t *r = array.ptr();
+ env->SetLongArrayRegion(arr, 0, array.size(), r);
+ v.val.l = arr;
+ v.obj = arr;
+
+ } break;
case Variant::PACKED_BYTE_ARRAY: {
Vector<uint8_t> array = *p_arg;
jbyteArray arr = env->NewByteArray(array.size());
@@ -167,8 +176,15 @@ jvalret _variant_to_jvalue(JNIEnv *env, Variant::Type p_type, const Variant *p_a
v.obj = arr;
} break;
+ case Variant::PACKED_FLOAT64_ARRAY: {
+ Vector<double> array = *p_arg;
+ jdoubleArray arr = env->NewDoubleArray(array.size());
+ const double *r = array.ptr();
+ env->SetDoubleArrayRegion(arr, 0, array.size(), r);
+ v.val.l = arr;
+ v.obj = arr;
- // TODO: This is missing 64 bits arrays, I have no idea how to do it in JNI.
+ } break;
default: {
v.val.i = 0;
@@ -244,6 +260,17 @@ Variant _jobject_to_variant(JNIEnv *env, jobject obj) {
return sarr;
}
+ if (name == "[J") {
+ jlongArray arr = (jlongArray)obj;
+ int fCount = env->GetArrayLength(arr);
+ Vector<int64_t> sarr;
+ sarr.resize(fCount);
+
+ int64_t *w = sarr.ptrw();
+ env->GetLongArrayRegion(arr, 0, fCount, w);
+ return sarr;
+ }
+
if (name == "[B") {
jbyteArray arr = (jbyteArray)obj;
int fCount = env->GetArrayLength(arr);
@@ -344,12 +371,15 @@ Variant::Type get_jni_type(const String &p_type) {
{ "void", Variant::NIL },
{ "boolean", Variant::BOOL },
{ "int", Variant::INT },
+ { "long", Variant::INT },
{ "float", Variant::FLOAT },
{ "double", Variant::FLOAT },
{ "java.lang.String", Variant::STRING },
{ "[I", Variant::PACKED_INT32_ARRAY },
+ { "[J", Variant::PACKED_INT64_ARRAY },
{ "[B", Variant::PACKED_BYTE_ARRAY },
{ "[F", Variant::PACKED_FLOAT32_ARRAY },
+ { "[D", Variant::PACKED_FLOAT64_ARRAY },
{ "[Ljava.lang.String;", Variant::PACKED_STRING_ARRAY },
{ "org.godotengine.godot.Dictionary", Variant::DICTIONARY },
{ nullptr, Variant::NIL }
@@ -376,13 +406,16 @@ const char *get_jni_sig(const String &p_type) {
{ "void", "V" },
{ "boolean", "Z" },
{ "int", "I" },
+ { "long", "J" },
{ "float", "F" },
{ "double", "D" },
{ "java.lang.String", "Ljava/lang/String;" },
{ "org.godotengine.godot.Dictionary", "Lorg/godotengine/godot/Dictionary;" },
{ "[I", "[I" },
+ { "[J", "[J" },
{ "[B", "[B" },
{ "[F", "[F" },
+ { "[D", "[D" },
{ "[Ljava.lang.String;", "[Ljava/lang/String;" },
{ nullptr, "V" }
};
diff --git a/platform/android/os_android.cpp b/platform/android/os_android.cpp
index 97fa90b1d2..317a63f21f 100644
--- a/platform/android/os_android.cpp
+++ b/platform/android/os_android.cpp
@@ -268,12 +268,16 @@ bool OS_Android::main_loop_iterate(bool *r_should_swap_buffers) {
if (!main_loop) {
return false;
}
+ DisplayServerAndroid::get_singleton()->reset_swap_buffers_flag();
DisplayServerAndroid::get_singleton()->process_events();
uint64_t current_frames_drawn = Engine::get_singleton()->get_frames_drawn();
bool exit = Main::iteration();
if (r_should_swap_buffers) {
- *r_should_swap_buffers = !is_in_low_processor_usage_mode() || RenderingServer::get_singleton()->has_changed() || current_frames_drawn != Engine::get_singleton()->get_frames_drawn();
+ *r_should_swap_buffers = !is_in_low_processor_usage_mode() ||
+ DisplayServerAndroid::get_singleton()->should_swap_buffers() ||
+ RenderingServer::get_singleton()->has_changed() ||
+ current_frames_drawn != Engine::get_singleton()->get_frames_drawn();
}
return exit;
@@ -333,6 +337,229 @@ String OS_Android::get_data_path() const {
return get_user_data_dir();
}
+void OS_Android::_load_system_font_config() {
+ font_aliases.clear();
+ fonts.clear();
+ font_names.clear();
+
+ Ref<XMLParser> parser;
+ parser.instantiate();
+
+ Error err = parser->open(String(getenv("ANDROID_ROOT")).path_join("/etc/fonts.xml"));
+ if (err == OK) {
+ bool in_font_node = false;
+ String fb, fn;
+ FontInfo fi;
+
+ while (parser->read() == OK) {
+ if (parser->get_node_type() == XMLParser::NODE_ELEMENT) {
+ in_font_node = false;
+ if (parser->get_node_name() == "familyset") {
+ int ver = parser->has_attribute("version") ? parser->get_attribute_value("version").to_int() : 0;
+ if (ver < 21) {
+ ERR_PRINT(vformat("Unsupported font config version %s", ver));
+ break;
+ }
+ } else if (parser->get_node_name() == "alias") {
+ String name = parser->has_attribute("name") ? parser->get_attribute_value("name").strip_edges() : String();
+ String to = parser->has_attribute("to") ? parser->get_attribute_value("to").strip_edges() : String();
+ if (!name.is_empty() && !to.is_empty()) {
+ font_aliases[name] = to;
+ }
+ } else if (parser->get_node_name() == "family") {
+ fn = parser->has_attribute("name") ? parser->get_attribute_value("name").strip_edges() : String();
+ String lang_code = parser->has_attribute("lang") ? parser->get_attribute_value("lang").strip_edges() : String();
+ Vector<String> lang_codes = lang_code.split(",");
+ for (int i = 0; i < lang_codes.size(); i++) {
+ Vector<String> lang_code_elements = lang_codes[i].split("-");
+ if (lang_code_elements.size() >= 1 && lang_code_elements[0] != "und") {
+ // Add missing script codes.
+ if (lang_code_elements[0] == "ko") {
+ fi.script.insert("Hani");
+ fi.script.insert("Hang");
+ }
+ if (lang_code_elements[0] == "ja") {
+ fi.script.insert("Hani");
+ fi.script.insert("Kana");
+ fi.script.insert("Hira");
+ }
+ if (!lang_code_elements[0].is_empty()) {
+ fi.lang.insert(lang_code_elements[0]);
+ }
+ }
+ if (lang_code_elements.size() >= 2) {
+ // Add common codes for variants and remove variants not supported by HarfBuzz/ICU.
+ if (lang_code_elements[1] == "Aran") {
+ fi.script.insert("Arab");
+ }
+ if (lang_code_elements[1] == "Cyrs") {
+ fi.script.insert("Cyrl");
+ }
+ if (lang_code_elements[1] == "Hanb") {
+ fi.script.insert("Hani");
+ fi.script.insert("Bopo");
+ }
+ if (lang_code_elements[1] == "Hans" || lang_code_elements[1] == "Hant") {
+ fi.script.insert("Hani");
+ }
+ if (lang_code_elements[1] == "Syrj" || lang_code_elements[1] == "Syre" || lang_code_elements[1] == "Syrn") {
+ fi.script.insert("Syrc");
+ }
+ if (!lang_code_elements[1].is_empty() && lang_code_elements[1] != "Zsym" && lang_code_elements[1] != "Zsye" && lang_code_elements[1] != "Zmth") {
+ fi.script.insert(lang_code_elements[1]);
+ }
+ }
+ }
+ } else if (parser->get_node_name() == "font") {
+ in_font_node = true;
+ fb = parser->has_attribute("fallbackFor") ? parser->get_attribute_value("fallbackFor").strip_edges() : String();
+ fi.weight = parser->has_attribute("weight") ? parser->get_attribute_value("weight").to_int() : 400;
+ fi.italic = parser->has_attribute("style") && parser->get_attribute_value("style").strip_edges() == "italic";
+ }
+ }
+ if (parser->get_node_type() == XMLParser::NODE_TEXT) {
+ if (in_font_node) {
+ fi.filename = parser->get_node_data().strip_edges();
+ fi.font_name = fn;
+ if (!fb.is_empty() && fn.is_empty()) {
+ fi.font_name = fb;
+ fi.priority = 2;
+ }
+ if (fi.font_name.is_empty()) {
+ fi.font_name = "sans-serif";
+ fi.priority = 5;
+ }
+ if (fi.font_name.ends_with("-condensed")) {
+ fi.stretch = 75;
+ fi.font_name = fi.font_name.trim_suffix("-condensed");
+ }
+ fonts.push_back(fi);
+ font_names.insert(fi.font_name);
+ }
+ }
+ if (parser->get_node_type() == XMLParser::NODE_ELEMENT_END) {
+ in_font_node = false;
+ if (parser->get_node_name() == "font") {
+ fb = String();
+ fi.font_name = String();
+ fi.priority = 0;
+ fi.weight = 400;
+ fi.stretch = 100;
+ fi.italic = false;
+ } else if (parser->get_node_name() == "family") {
+ fi = FontInfo();
+ fn = String();
+ }
+ }
+ }
+ parser->close();
+ } else {
+ ERR_PRINT("Unable to load font config");
+ }
+
+ font_config_loaded = true;
+}
+
+Vector<String> OS_Android::get_system_fonts() const {
+ if (!font_config_loaded) {
+ const_cast<OS_Android *>(this)->_load_system_font_config();
+ }
+ Vector<String> ret;
+ for (const String &E : font_names) {
+ ret.push_back(E);
+ }
+ return ret;
+}
+
+Vector<String> OS_Android::get_system_font_path_for_text(const String &p_font_name, const String &p_text, const String &p_locale, const String &p_script, int p_weight, int p_stretch, bool p_italic) const {
+ if (!font_config_loaded) {
+ const_cast<OS_Android *>(this)->_load_system_font_config();
+ }
+ String font_name = p_font_name.to_lower();
+ if (font_aliases.has(font_name)) {
+ font_name = font_aliases[font_name];
+ }
+ String root = String(getenv("ANDROID_ROOT")).path_join("fonts");
+ String lang_prefix = p_locale.split("_")[0];
+ Vector<String> ret;
+ int best_score = 0;
+ for (const List<FontInfo>::Element *E = fonts.front(); E; E = E->next()) {
+ int score = 0;
+ if (!E->get().script.is_empty() && !p_script.is_empty() && !E->get().script.has(p_script)) {
+ continue;
+ }
+ float sim = E->get().font_name.similarity(font_name);
+ if (sim > 0.0) {
+ score += (60 * sim + 5 - E->get().priority);
+ }
+ if (E->get().lang.has(p_locale)) {
+ score += 120;
+ } else if (E->get().lang.has(lang_prefix)) {
+ score += 115;
+ }
+ if (E->get().script.has(p_script)) {
+ score += 240;
+ }
+ score += (20 - Math::abs(E->get().weight - p_weight) / 50);
+ score += (20 - Math::abs(E->get().stretch - p_stretch) / 10);
+ if (E->get().italic == p_italic) {
+ score += 30;
+ }
+ if (score > best_score) {
+ best_score = score;
+ if (ret.find(root.path_join(E->get().filename)) < 0) {
+ ret.insert(0, root.path_join(E->get().filename));
+ }
+ } else if (score == best_score || E->get().script.is_empty()) {
+ if (ret.find(root.path_join(E->get().filename)) < 0) {
+ ret.push_back(root.path_join(E->get().filename));
+ }
+ }
+ if (score >= 490) {
+ break; // Perfect match.
+ }
+ }
+
+ return ret;
+}
+
+String OS_Android::get_system_font_path(const String &p_font_name, int p_weight, int p_stretch, bool p_italic) const {
+ if (!font_config_loaded) {
+ const_cast<OS_Android *>(this)->_load_system_font_config();
+ }
+ String font_name = p_font_name.to_lower();
+ if (font_aliases.has(font_name)) {
+ font_name = font_aliases[font_name];
+ }
+ String root = String(getenv("ANDROID_ROOT")).path_join("fonts");
+
+ int best_score = 0;
+ const List<FontInfo>::Element *best_match = nullptr;
+
+ for (const List<FontInfo>::Element *E = fonts.front(); E; E = E->next()) {
+ int score = 0;
+ if (E->get().font_name == font_name) {
+ score += (65 - E->get().priority);
+ }
+ score += (20 - Math::abs(E->get().weight - p_weight) / 50);
+ score += (20 - Math::abs(E->get().stretch - p_stretch) / 10);
+ if (E->get().italic == p_italic) {
+ score += 30;
+ }
+ if (score >= 60 && score > best_score) {
+ best_score = score;
+ best_match = E;
+ }
+ if (score >= 140) {
+ break; // Perfect match.
+ }
+ }
+ if (best_match) {
+ return root.path_join(best_match->get().filename);
+ }
+ return String();
+}
+
String OS_Android::get_executable_path() const {
// Since unix process creation is restricted on Android, we bypass
// OS_Unix::get_executable_path() so we can return ANDROID_EXEC_PATH.
@@ -445,6 +672,9 @@ String OS_Android::get_config_path() const {
}
bool OS_Android::_check_internal_feature_support(const String &p_feature) {
+ if (p_feature == "system_fonts") {
+ return true;
+ }
if (p_feature == "mobile") {
return true;
}
@@ -474,7 +704,6 @@ OS_Android::OS_Android(GodotJavaWrapper *p_godot_java, GodotIOJavaWrapper *p_god
#if defined(GLES3_ENABLED)
gl_extensions = nullptr;
- use_gl2 = false;
#endif
#if defined(VULKAN_ENABLED)
diff --git a/platform/android/os_android.h b/platform/android/os_android.h
index d6546a3507..9034615fc4 100644
--- a/platform/android/os_android.h
+++ b/platform/android/os_android.h
@@ -62,9 +62,26 @@ private:
MainLoop *main_loop = nullptr;
+ struct FontInfo {
+ String font_name;
+ HashSet<String> lang;
+ HashSet<String> script;
+ int weight = 400;
+ int stretch = 100;
+ bool italic = false;
+ int priority = 0;
+ String filename;
+ };
+
+ HashMap<String, String> font_aliases;
+ List<FontInfo> fonts;
+ HashSet<String> font_names;
+ bool font_config_loaded = false;
+
GodotJavaWrapper *godot_java = nullptr;
GodotIOJavaWrapper *godot_io_java = nullptr;
+ void _load_system_font_config();
String get_system_property(const char *key) const;
public:
@@ -114,6 +131,10 @@ public:
ANativeWindow *get_native_window() const;
virtual Error shell_open(String p_uri) override;
+
+ virtual Vector<String> get_system_fonts() const override;
+ virtual String get_system_font_path(const String &p_font_name, int p_weight = 400, int p_stretch = 100, bool p_italic = false) const override;
+ virtual Vector<String> get_system_font_path_for_text(const String &p_font_name, const String &p_text, const String &p_locale = String(), const String &p_script = String(), int p_weight = 400, int p_stretch = 100, bool p_italic = false) const override;
virtual String get_executable_path() const override;
virtual String get_user_data_dir() const override;
virtual String get_data_path() const override;
diff --git a/platform/android/plugin/godot_plugin_jni.cpp b/platform/android/plugin/godot_plugin_jni.cpp
index 498977ad49..fe35babba6 100644
--- a/platform/android/plugin/godot_plugin_jni.cpp
+++ b/platform/android/plugin/godot_plugin_jni.cpp
@@ -128,21 +128,21 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeEmitS
singleton->emit_signalp(StringName(signal_name), args, count);
}
-JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeRegisterGDNativeLibraries(JNIEnv *env, jclass clazz, jobjectArray gdnlib_paths) {
- int gdnlib_count = env->GetArrayLength(gdnlib_paths);
- if (gdnlib_count == 0) {
+JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeRegisterGDExtensionLibraries(JNIEnv *env, jclass clazz, jobjectArray gdextension_paths) {
+ int gdextension_count = env->GetArrayLength(gdextension_paths);
+ if (gdextension_count == 0) {
return;
}
- // Retrieve the current list of gdnative libraries.
- Array singletons = Array();
- if (ProjectSettings::get_singleton()->has_setting("gdnative/singletons")) {
- singletons = GLOBAL_GET("gdnative/singletons");
+ // Retrieve the current list of gdextension libraries.
+ Array singletons;
+ if (ProjectSettings::get_singleton()->has_setting("gdextension/singletons")) {
+ singletons = GLOBAL_GET("gdextension/singletons");
}
// Insert the libraries provided by the plugin
- for (int i = 0; i < gdnlib_count; i++) {
- jstring relative_path = (jstring)env->GetObjectArrayElement(gdnlib_paths, i);
+ for (int i = 0; i < gdextension_count; i++) {
+ jstring relative_path = (jstring)env->GetObjectArrayElement(gdextension_paths, i);
String path = "res://" + jstring_to_string(relative_path, env);
if (!singletons.has(path)) {
@@ -152,6 +152,6 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeRegis
}
// Insert the updated list back into project settings.
- ProjectSettings::get_singleton()->set("gdnative/singletons", singletons);
+ ProjectSettings::get_singleton()->set("gdextension/singletons", singletons);
}
}
diff --git a/platform/android/plugin/godot_plugin_jni.h b/platform/android/plugin/godot_plugin_jni.h
index 35f9d5b513..e36cc8b0e3 100644
--- a/platform/android/plugin/godot_plugin_jni.h
+++ b/platform/android/plugin/godot_plugin_jni.h
@@ -39,7 +39,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeRegis
JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeRegisterMethod(JNIEnv *env, jclass clazz, jstring sname, jstring name, jstring ret, jobjectArray args);
JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeRegisterSignal(JNIEnv *env, jclass clazz, jstring j_plugin_name, jstring j_signal_name, jobjectArray j_signal_param_types);
JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeEmitSignal(JNIEnv *env, jclass clazz, jstring j_plugin_name, jstring j_signal_name, jobjectArray j_signal_params);
-JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeRegisterGDNativeLibraries(JNIEnv *env, jclass clazz, jobjectArray gdnlib_paths);
+JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeRegisterGDExtensionLibraries(JNIEnv *env, jclass clazz, jobjectArray gdextension_paths);
}
#endif // GODOT_PLUGIN_JNI_H
diff --git a/platform/ios/app_delegate.mm b/platform/ios/app_delegate.mm
index fb183d52d4..3ebd530585 100644
--- a/platform/ios/app_delegate.mm
+++ b/platform/ios/app_delegate.mm
@@ -45,7 +45,7 @@
extern int gargc;
extern char **gargv;
-extern int ios_main(int, char **, String, String);
+extern int ios_main(int, char **);
extern void ios_finish();
@implementation AppDelegate
@@ -66,12 +66,7 @@ static ViewController *mainViewController = nil;
// Create a full-screen window
self.window = [[UIWindow alloc] initWithFrame:windowBounds];
- NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
- NSString *documentsDirectory = [paths objectAtIndex:0];
- paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
- NSString *cacheDirectory = [paths objectAtIndex:0];
-
- int err = ios_main(gargc, gargv, String::utf8([documentsDirectory UTF8String]), String::utf8([cacheDirectory UTF8String]));
+ int err = ios_main(gargc, gargv);
if (err != 0) {
// bail, things did not go very well for us, should probably output a message on screen with our error code...
diff --git a/platform/ios/display_server_ios.h b/platform/ios/display_server_ios.h
index 447f919139..0ca0d3d1fe 100644
--- a/platform/ios/display_server_ios.h
+++ b/platform/ios/display_server_ios.h
@@ -113,7 +113,7 @@ public:
// MARK: Keyboard
- void key(Key p_key, bool p_pressed);
+ void key(Key p_key, char32_t p_char, bool p_pressed);
// MARK: Motion
@@ -162,6 +162,7 @@ public:
virtual void window_set_current_screen(int p_screen, WindowID p_window = MAIN_WINDOW_ID) override;
virtual Point2i window_get_position(WindowID p_window = MAIN_WINDOW_ID) const override;
+ virtual Point2i window_get_position_with_decorations(WindowID p_window = MAIN_WINDOW_ID) const override;
virtual void window_set_position(const Point2i &p_position, WindowID p_window = MAIN_WINDOW_ID) override;
virtual void window_set_transient(WindowID p_window, WindowID p_parent) override;
@@ -174,7 +175,7 @@ public:
virtual void window_set_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID) override;
virtual Size2i window_get_size(WindowID p_window = MAIN_WINDOW_ID) const override;
- virtual Size2i window_get_real_size(WindowID p_window = MAIN_WINDOW_ID) const override;
+ virtual Size2i window_get_size_with_decorations(WindowID p_window = MAIN_WINDOW_ID) const override;
virtual void window_set_mode(WindowMode p_mode, WindowID p_window = MAIN_WINDOW_ID) override;
virtual WindowMode window_get_mode(WindowID p_window = MAIN_WINDOW_ID) const override;
@@ -199,7 +200,7 @@ public:
virtual void window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mode, WindowID p_window = MAIN_WINDOW_ID) override;
virtual DisplayServer::VSyncMode window_get_vsync_mode(WindowID p_vsync_mode) const override;
- virtual bool screen_is_touchscreen(int p_screen) const override;
+ virtual bool is_touchscreen_available() const 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;
diff --git a/platform/ios/display_server_ios.mm b/platform/ios/display_server_ios.mm
index 6793b40dd4..ce78b8d20f 100644
--- a/platform/ios/display_server_ios.mm
+++ b/platform/ios/display_server_ios.mm
@@ -227,27 +227,23 @@ void DisplayServerIOS::_window_callback(const Callable &p_callable, const Varian
// MARK: Touches
void DisplayServerIOS::touch_press(int p_idx, int p_x, int p_y, bool p_pressed, bool p_double_click) {
- if (!GLOBAL_GET("debug/disable_touch")) {
- Ref<InputEventScreenTouch> ev;
- ev.instantiate();
-
- ev->set_index(p_idx);
- ev->set_pressed(p_pressed);
- ev->set_position(Vector2(p_x, p_y));
- ev->set_double_tap(p_double_click);
- perform_event(ev);
- }
+ Ref<InputEventScreenTouch> ev;
+ ev.instantiate();
+
+ ev->set_index(p_idx);
+ ev->set_pressed(p_pressed);
+ ev->set_position(Vector2(p_x, p_y));
+ ev->set_double_tap(p_double_click);
+ perform_event(ev);
}
void DisplayServerIOS::touch_drag(int p_idx, int p_prev_x, int p_prev_y, int p_x, int p_y) {
- if (!GLOBAL_GET("debug/disable_touch")) {
- Ref<InputEventScreenDrag> ev;
- ev.instantiate();
- ev->set_index(p_idx);
- ev->set_position(Vector2(p_x, p_y));
- ev->set_relative(Vector2(p_x - p_prev_x, p_y - p_prev_y));
- perform_event(ev);
- }
+ Ref<InputEventScreenDrag> ev;
+ ev.instantiate();
+ ev->set_index(p_idx);
+ ev->set_position(Vector2(p_x, p_y));
+ ev->set_relative(Vector2(p_x - p_prev_x, p_y - p_prev_y));
+ perform_event(ev);
}
void DisplayServerIOS::perform_event(const Ref<InputEvent> &p_event) {
@@ -260,14 +256,14 @@ void DisplayServerIOS::touches_cancelled(int p_idx) {
// MARK: Keyboard
-void DisplayServerIOS::key(Key p_key, bool p_pressed) {
+void DisplayServerIOS::key(Key p_key, char32_t p_char, bool p_pressed) {
Ref<InputEventKey> ev;
ev.instantiate();
ev->set_echo(false);
ev->set_pressed(p_pressed);
ev->set_keycode(p_key);
ev->set_physical_keycode(p_key);
- ev->set_unicode((char32_t)p_key);
+ ev->set_unicode(p_char);
perform_event(ev);
}
@@ -441,7 +437,7 @@ float DisplayServerIOS::screen_get_refresh_rate(int p_screen) const {
}
float DisplayServerIOS::screen_get_scale(int p_screen) const {
- return [UIScreen mainScreen].nativeScale;
+ return [UIScreen mainScreen].scale;
}
Vector<DisplayServer::WindowID> DisplayServerIOS::get_window_list() const {
@@ -496,6 +492,10 @@ Point2i DisplayServerIOS::window_get_position(WindowID p_window) const {
return Point2i();
}
+Point2i DisplayServerIOS::window_get_position_with_decorations(WindowID p_window) const {
+ return Point2i();
+}
+
void DisplayServerIOS::window_set_position(const Point2i &p_position, WindowID p_window) {
// Probably not supported for single window iOS app
}
@@ -529,7 +529,7 @@ Size2i DisplayServerIOS::window_get_size(WindowID p_window) const {
return Size2i(screenBounds.size.width, screenBounds.size.height) * screen_get_max_scale();
}
-Size2i DisplayServerIOS::window_get_real_size(WindowID p_window) const {
+Size2i DisplayServerIOS::window_get_size_with_decorations(WindowID p_window) const {
return window_get_size(p_window);
}
@@ -581,10 +581,20 @@ bool DisplayServerIOS::can_any_window_draw() const {
return true;
}
-bool DisplayServerIOS::screen_is_touchscreen(int p_screen) const {
+bool DisplayServerIOS::is_touchscreen_available() const {
return true;
}
+_FORCE_INLINE_ int _convert_utf32_offset_to_utf16(const String &p_existing_text, int p_pos) {
+ int limit = p_pos;
+ for (int i = 0; i < MIN(p_existing_text.length(), p_pos); i++) {
+ if (p_existing_text[i] > 0xffff) {
+ limit++;
+ }
+ }
+ return limit;
+}
+
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()];
@@ -623,8 +633,8 @@ void DisplayServerIOS::virtual_keyboard_show(const String &p_existing_text, cons
[AppDelegate.viewController.keyboardView
becomeFirstResponderWithString:existingString
- cursorStart:p_cursor_start
- cursorEnd:p_cursor_end];
+ cursorStart:_convert_utf32_offset_to_utf16(p_existing_text, p_cursor_start)
+ cursorEnd:_convert_utf32_offset_to_utf16(p_existing_text, p_cursor_end)];
}
void DisplayServerIOS::virtual_keyboard_hide() {
diff --git a/platform/ios/export/export_plugin.cpp b/platform/ios/export/export_plugin.cpp
index 8e4d91ac50..ea37278309 100644
--- a/platform/ios/export/export_plugin.cpp
+++ b/platform/ios/export/export_plugin.cpp
@@ -49,6 +49,46 @@ Vector<EditorExportPlatformIOS::ExportArchitecture> EditorExportPlatformIOS::_ge
return archs;
}
+struct IconInfo {
+ const char *preset_key;
+ const char *idiom;
+ const char *export_name;
+ const char *actual_size_side;
+ const char *scale;
+ const char *unscaled_size;
+ const bool force_opaque;
+};
+
+static const IconInfo icon_infos[] = {
+ // Home screen on iPhone
+ { PNAME("icons/iphone_120x120"), "iphone", "Icon-120.png", "120", "2x", "60x60", false },
+ { PNAME("icons/iphone_120x120"), "iphone", "Icon-120.png", "120", "3x", "40x40", false },
+ { PNAME("icons/iphone_180x180"), "iphone", "Icon-180.png", "180", "3x", "60x60", false },
+
+ // Home screen on iPad
+ { PNAME("icons/ipad_76x76"), "ipad", "Icon-76.png", "76", "1x", "76x76", false },
+ { PNAME("icons/ipad_152x152"), "ipad", "Icon-152.png", "152", "2x", "76x76", false },
+ { PNAME("icons/ipad_167x167"), "ipad", "Icon-167.png", "167", "2x", "83.5x83.5", false },
+
+ // App Store
+ { PNAME("icons/app_store_1024x1024"), "ios-marketing", "Icon-1024.png", "1024", "1x", "1024x1024", true },
+
+ // Spotlight
+ { PNAME("icons/spotlight_40x40"), "ipad", "Icon-40.png", "40", "1x", "40x40", false },
+ { PNAME("icons/spotlight_80x80"), "iphone", "Icon-80.png", "80", "2x", "40x40", false },
+ { PNAME("icons/spotlight_80x80"), "ipad", "Icon-80.png", "80", "2x", "40x40", false },
+
+ // Settings
+ { PNAME("icons/settings_58x58"), "iphone", "Icon-58.png", "58", "2x", "29x29", false },
+ { PNAME("icons/settings_58x58"), "ipad", "Icon-58.png", "58", "2x", "29x29", false },
+ { PNAME("icons/settings_87x87"), "iphone", "Icon-87.png", "87", "3x", "29x29", false },
+
+ // Notification
+ { PNAME("icons/notification_40x40"), "iphone", "Icon-40.png", "40", "2x", "20x20", false },
+ { PNAME("icons/notification_40x40"), "ipad", "Icon-40.png", "40", "2x", "20x20", false },
+ { PNAME("icons/notification_60x60"), "iphone", "Icon-60.png", "60", "3x", "20x20", false }
+};
+
struct LoadingScreenInfo {
const char *preset_key;
const char *export_name;
@@ -97,6 +137,9 @@ void EditorExportPlatformIOS::get_export_options(List<ExportOption> *r_options)
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/short_version"), "1.0"));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/version"), "1.0"));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "application/icon_interpolation", PROPERTY_HINT_ENUM, "Nearest neighbor,Bilinear,Cubic,Trilinear,Lanczos"), 4));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "application/launch_screens_interpolation", PROPERTY_HINT_ENUM, "Nearest neighbor,Bilinear,Cubic,Trilinear,Lanczos"), 4));
+
Vector<PluginConfigIOS> found_plugins = get_plugins();
for (int i = 0; i < found_plugins.size(); i++) {
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, vformat("%s/%s", PNAME("plugins"), found_plugins[i].name)), false));
@@ -139,18 +182,13 @@ void EditorExportPlatformIOS::get_export_options(List<ExportOption> *r_options)
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/photolibrary_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need access to the photo library"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/photolibrary_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary()));
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "icons/iphone_120x120", PROPERTY_HINT_FILE, "*.png,*.jpg,*.jpeg"), "")); // Home screen on iPhone/iPod Touch with Retina display
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "icons/iphone_180x180", PROPERTY_HINT_FILE, "*.png,*.jpg,*.jpeg"), "")); // Home screen on iPhone with Retina HD display
-
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "icons/ipad_76x76", PROPERTY_HINT_FILE, "*.png,*.jpg,*.jpeg"), "")); // Home screen on iPad
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "icons/ipad_152x152", PROPERTY_HINT_FILE, "*.png,*.jpg,*.jpeg"), "")); // Home screen on iPad with Retina display
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "icons/ipad_167x167", PROPERTY_HINT_FILE, "*.png,*.jpg,*.jpeg"), "")); // Home screen on iPad Pro
-
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "icons/app_store_1024x1024", PROPERTY_HINT_FILE, "*.png,*.jpg,*.jpeg"), "")); // App Store
-
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "icons/spotlight_40x40", PROPERTY_HINT_FILE, "*.png,*.jpg,*.jpeg"), "")); // Spotlight
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "icons/spotlight_80x80", PROPERTY_HINT_FILE, "*.png,*.jpg,*.jpeg"), "")); // Spotlight on devices with Retina display
-
+ HashSet<String> used_names;
+ for (uint64_t i = 0; i < sizeof(icon_infos) / sizeof(icon_infos[0]); ++i) {
+ if (!used_names.has(icon_infos[i].preset_key)) {
+ used_names.insert(icon_infos[i].preset_key);
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, icon_infos[i].preset_key, PROPERTY_HINT_FILE, "*.png,*.jpg,*.jpeg"), ""));
+ }
+ }
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "storyboard/use_launch_screen_storyboard"), false));
r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "storyboard/image_scale_mode", PROPERTY_HINT_ENUM, "Same as Logo,Center,Scale to Fit,Scale to Fill,Scale"), 0));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "storyboard/custom_image@2x", PROPERTY_HINT_FILE, "*.png,*.jpg,*.jpeg"), ""));
@@ -531,36 +569,6 @@ void EditorExportPlatformIOS::_blend_and_rotate(Ref<Image> &p_dst, Ref<Image> &p
}
}
-struct IconInfo {
- const char *preset_key;
- const char *idiom;
- const char *export_name;
- const char *actual_size_side;
- const char *scale;
- const char *unscaled_size;
- const bool force_opaque;
-};
-
-static const IconInfo icon_infos[] = {
- // Home screen on iPhone
- { "icons/iphone_120x120", "iphone", "Icon-120.png", "120", "2x", "60x60", false },
- { "icons/iphone_120x120", "iphone", "Icon-120.png", "120", "3x", "40x40", false },
- { "icons/iphone_180x180", "iphone", "Icon-180.png", "180", "3x", "60x60", false },
-
- // Home screen on iPad
- { "icons/ipad_76x76", "ipad", "Icon-76.png", "76", "1x", "76x76", false },
- { "icons/ipad_152x152", "ipad", "Icon-152.png", "152", "2x", "76x76", false },
- { "icons/ipad_167x167", "ipad", "Icon-167.png", "167", "2x", "83.5x83.5", false },
-
- // App Store
- { "icons/app_store_1024x1024", "ios-marketing", "Icon-1024.png", "1024", "1x", "1024x1024", true },
-
- // Spotlight
- { "icons/spotlight_40x40", "ipad", "Icon-40.png", "40", "1x", "40x40", false },
- { "icons/spotlight_80x80", "iphone", "Icon-80.png", "80", "2x", "40x40", false },
- { "icons/spotlight_80x80", "ipad", "Icon-80.png", "80", "2x", "40x40", false }
-};
-
Error EditorExportPlatformIOS::_export_icons(const Ref<EditorExportPreset> &p_preset, const String &p_iconset_dir) {
String json_description = "{\"images\":[";
String sizes;
@@ -568,6 +576,8 @@ Error EditorExportPlatformIOS::_export_icons(const Ref<EditorExportPreset> &p_pr
Ref<DirAccess> da = DirAccess::open(p_iconset_dir);
ERR_FAIL_COND_V_MSG(da.is_null(), ERR_CANT_OPEN, "Cannot open directory '" + p_iconset_dir + "'.");
+ Color boot_bg_color = GLOBAL_GET("application/boot_splash/bg_color");
+
for (uint64_t i = 0; i < (sizeof(icon_infos) / sizeof(icon_infos[0])); ++i) {
IconInfo info = icon_infos[i];
int side_size = String(info.actual_size_side).to_int();
@@ -580,13 +590,17 @@ Error EditorExportPlatformIOS::_export_icons(const Ref<EditorExportPreset> &p_pr
if (err != OK) {
add_message(EXPORT_MESSAGE_ERROR, TTR("Export Icons"), vformat("Invalid icon (%s): '%s'.", info.preset_key, icon_path));
return ERR_UNCONFIGURED;
+ } else if (info.force_opaque && img->detect_alpha() != Image::ALPHA_NONE) {
+ add_message(EXPORT_MESSAGE_WARNING, TTR("Export Icons"), vformat("Icon (%s) must be opaque.", info.preset_key));
+ img->resize(side_size, side_size, (Image::Interpolation)(p_preset->get("application/icon_interpolation").operator int()));
+ Ref<Image> new_img = Image::create_empty(side_size, side_size, false, Image::FORMAT_RGBA8);
+ new_img->fill(boot_bg_color);
+ _blend_and_rotate(new_img, img, false);
+ err = new_img->save_png(p_iconset_dir + info.export_name);
+ } else {
+ img->resize(side_size, side_size, (Image::Interpolation)(p_preset->get("application/icon_interpolation").operator int()));
+ err = img->save_png(p_iconset_dir + info.export_name);
}
- if (info.force_opaque && img->detect_alpha() != Image::ALPHA_NONE) {
- add_message(EXPORT_MESSAGE_ERROR, TTR("Export Icons"), vformat("Icon (%s) must be opaque.", info.preset_key));
- return ERR_UNCONFIGURED;
- }
- img->resize(side_size, side_size);
- err = img->save_png(p_iconset_dir + info.export_name);
if (err) {
add_message(EXPORT_MESSAGE_ERROR, TTR("Export Icons"), vformat("Failed to export icon (%s): '%s'.", info.preset_key, icon_path));
return err;
@@ -598,14 +612,16 @@ Error EditorExportPlatformIOS::_export_icons(const Ref<EditorExportPreset> &p_pr
if (err != OK) {
add_message(EXPORT_MESSAGE_ERROR, TTR("Export Icons"), vformat("Invalid icon (%s): '%s'.", info.preset_key, icon_path));
return ERR_UNCONFIGURED;
- }
- if (info.force_opaque && img->detect_alpha() != Image::ALPHA_NONE) {
- add_message(EXPORT_MESSAGE_ERROR, TTR("Export Icons"), vformat("Icon (%s) must be opaque.", info.preset_key));
- return ERR_UNCONFIGURED;
- }
- if (img->get_width() != side_size || img->get_height() != side_size) {
+ } else if (info.force_opaque && img->detect_alpha() != Image::ALPHA_NONE) {
+ add_message(EXPORT_MESSAGE_WARNING, TTR("Export Icons"), vformat("Icon (%s) must be opaque.", info.preset_key));
+ img->resize(side_size, side_size, (Image::Interpolation)(p_preset->get("application/icon_interpolation").operator int()));
+ Ref<Image> new_img = Image::create_empty(side_size, side_size, false, Image::FORMAT_RGBA8);
+ new_img->fill(boot_bg_color);
+ _blend_and_rotate(new_img, img, false);
+ err = new_img->save_png(p_iconset_dir + info.export_name);
+ } else if (img->get_width() != side_size || img->get_height() != side_size) {
add_message(EXPORT_MESSAGE_WARNING, TTR("Export Icons"), vformat("Icon (%s): '%s' has incorrect size %s and was automatically resized to %s.", info.preset_key, icon_path, img->get_size(), Vector2i(side_size, side_size)));
- img->resize(side_size, side_size);
+ img->resize(side_size, side_size, (Image::Interpolation)(p_preset->get("application/icon_interpolation").operator int()));
err = img->save_png(p_iconset_dir + info.export_name);
} else {
err = da->copy(icon_path, p_iconset_dir + info.export_name);
@@ -650,7 +666,7 @@ Error EditorExportPlatformIOS::_export_loading_screen_file(const Ref<EditorExpor
Ref<Image> image;
String image_path = p_dest_dir.path_join("splash@2x.png");
image.instantiate();
- Error err = image->load(custom_launch_image_2x);
+ Error err = ImageLoader::load_image(custom_launch_image_2x, image);
if (err) {
image.unref();
@@ -664,7 +680,7 @@ Error EditorExportPlatformIOS::_export_loading_screen_file(const Ref<EditorExpor
image.unref();
image_path = p_dest_dir.path_join("splash@3x.png");
image.instantiate();
- err = image->load(custom_launch_image_3x);
+ err = ImageLoader::load_image(custom_launch_image_3x, image);
if (err) {
image.unref();
@@ -681,7 +697,7 @@ Error EditorExportPlatformIOS::_export_loading_screen_file(const Ref<EditorExpor
if (!splash_path.is_empty()) {
splash.instantiate();
- const Error err = splash->load(splash_path);
+ const Error err = ImageLoader::load_image(splash_path, splash);
if (err) {
splash.unref();
}
@@ -735,9 +751,9 @@ Error EditorExportPlatformIOS::_export_loading_screen_images(const Ref<EditorExp
float aspect_ratio = (float)img->get_width() / (float)img->get_height();
if (boot_logo_scale) {
if (info.height * aspect_ratio <= info.width) {
- img->resize(info.height * aspect_ratio, info.height);
+ img->resize(info.height * aspect_ratio, info.height, (Image::Interpolation)(p_preset->get("application/launch_screens_interpolation").operator int()));
} else {
- img->resize(info.width, info.width / aspect_ratio);
+ img->resize(info.width, info.width / aspect_ratio, (Image::Interpolation)(p_preset->get("application/launch_screens_interpolation").operator int()));
}
}
Ref<Image> new_img = Image::create_empty(info.width, info.height, false, Image::FORMAT_RGBA8);
@@ -771,17 +787,17 @@ Error EditorExportPlatformIOS::_export_loading_screen_images(const Ref<EditorExp
if (info.rotate) {
if (boot_logo_scale) {
if (info.width * aspect_ratio <= info.height) {
- img_bs->resize(info.width * aspect_ratio, info.width);
+ img_bs->resize(info.width * aspect_ratio, info.width, (Image::Interpolation)(p_preset->get("application/launch_screens_interpolation").operator int()));
} else {
- img_bs->resize(info.height, info.height / aspect_ratio);
+ img_bs->resize(info.height, info.height / aspect_ratio, (Image::Interpolation)(p_preset->get("application/launch_screens_interpolation").operator int()));
}
}
} else {
if (boot_logo_scale) {
if (info.height * aspect_ratio <= info.width) {
- img_bs->resize(info.height * aspect_ratio, info.height);
+ img_bs->resize(info.height * aspect_ratio, info.height, (Image::Interpolation)(p_preset->get("application/launch_screens_interpolation").operator int()));
} else {
- img_bs->resize(info.width, info.width / aspect_ratio);
+ img_bs->resize(info.width, info.width / aspect_ratio, (Image::Interpolation)(p_preset->get("application/launch_screens_interpolation").operator int()));
}
}
}
@@ -1118,7 +1134,7 @@ Error EditorExportPlatformIOS::_copy_asset(const String &p_out_dir, const String
"<key>CFBundleShortVersionString</key>\n"
"<string>1.0</string>\n"
"<key>CFBundleIdentifier</key>\n"
- "<string>com.gdnative.framework.$name</string>\n"
+ "<string>com.gdextension.framework.$name</string>\n"
"<key>CFBundleName</key>\n"
"<string>$name</string>\n"
"<key>CFBundleExecutable</key>\n"
diff --git a/platform/ios/godot_ios.mm b/platform/ios/godot_ios.mm
index 5f3e786b8a..abe7c59ce2 100644
--- a/platform/ios/godot_ios.mm
+++ b/platform/ios/godot_ios.mm
@@ -38,10 +38,6 @@
static OS_IOS *os = nullptr;
-int add_path(int, char **);
-int add_cmdline(int, char **);
-int ios_main(int, char **, String);
-
int add_path(int p_argc, char **p_args) {
NSString *str = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"godot_path"];
if (!str) {
@@ -74,7 +70,7 @@ int add_cmdline(int p_argc, char **p_args) {
return p_argc;
}
-int ios_main(int argc, char **argv, String data_dir, String cache_dir) {
+int ios_main(int argc, char **argv) {
size_t len = strlen(argv[0]);
while (len--) {
@@ -95,7 +91,7 @@ int ios_main(int argc, char **argv, String data_dir, String cache_dir) {
char cwd[512];
getcwd(cwd, sizeof(cwd));
printf("cwd %s\n", cwd);
- os = new OS_IOS(data_dir, cache_dir);
+ os = new OS_IOS();
// We must override main when testing is enabled
TEST_MAIN_OVERRIDE
diff --git a/platform/ios/godot_view.mm b/platform/ios/godot_view.mm
index 4537dc2985..19cb914521 100644
--- a/platform/ios/godot_view.mm
+++ b/platform/ios/godot_view.mm
@@ -151,7 +151,7 @@ static const float earth_gravity = 9.80665;
}
- (void)godot_commonInit {
- self.contentScaleFactor = [UIScreen mainScreen].nativeScale;
+ self.contentScaleFactor = [UIScreen mainScreen].scale;
[self initTouches];
diff --git a/platform/ios/keyboard_input_view.mm b/platform/ios/keyboard_input_view.mm
index f031a1de22..8fb5656c24 100644
--- a/platform/ios/keyboard_input_view.mm
+++ b/platform/ios/keyboard_input_view.mm
@@ -115,8 +115,8 @@
- (void)deleteText:(NSInteger)charactersToDelete {
for (int i = 0; i < charactersToDelete; i++) {
- DisplayServerIOS::get_singleton()->key(Key::BACKSPACE, true);
- DisplayServerIOS::get_singleton()->key(Key::BACKSPACE, false);
+ DisplayServerIOS::get_singleton()->key(Key::BACKSPACE, 0, true);
+ DisplayServerIOS::get_singleton()->key(Key::BACKSPACE, 0, false);
}
}
@@ -126,20 +126,28 @@
for (int i = 0; i < characters.size(); i++) {
int character = characters[i];
-
- switch (character) {
- case 10:
- character = (int)Key::ENTER;
- break;
- case 8198:
- character = (int)Key::SPACE;
- break;
- default:
- break;
+ Key key = Key::NONE;
+
+ if (character == '\t') { // 0x09
+ key = Key::TAB;
+ } else if (character == '\n') { // 0x0A
+ key = Key::ENTER;
+ } else if (character == 0x2006) {
+ key = Key::SPACE;
+ } else if (character == U'Â¥') {
+ key = Key::YEN;
+ } else if (character == U'§') {
+ key = Key::SECTION;
+ } else if (character >= 0x20 && character <= 0x7E) { // ASCII.
+ if (character > 0x60 && character < 0x7B) { // Lowercase ASCII.
+ key = (Key)(character - 32);
+ } else {
+ key = (Key)character;
+ }
}
- DisplayServerIOS::get_singleton()->key((Key)character, true);
- DisplayServerIOS::get_singleton()->key((Key)character, false);
+ DisplayServerIOS::get_singleton()->key(key, character, true);
+ DisplayServerIOS::get_singleton()->key(key, character, false);
}
}
diff --git a/platform/ios/os_ios.h b/platform/ios/os_ios.h
index 400040875f..3589dd17c9 100644
--- a/platform/ios/os_ios.h
+++ b/platform/ios/os_ios.h
@@ -71,17 +71,20 @@ private:
virtual void finalize() override;
- String user_data_dir;
- String cache_dir;
-
bool is_focused = false;
+ CGFloat _weight_to_ct(int p_weight) const;
+ CGFloat _stretch_to_ct(int p_stretch) const;
+ String _get_default_fontname(const String &p_font_name) const;
+
+ static _FORCE_INLINE_ String get_framework_executable(const String &p_path);
+
void deinitialize_modules();
public:
static OS_IOS *get_singleton();
- OS_IOS(String p_data_dir, String p_cache_dir);
+ OS_IOS();
~OS_IOS();
void initialize_modules();
@@ -93,7 +96,8 @@ 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 Vector<String> get_system_font_path_for_text(const String &p_font_name, const String &p_text, const String &p_locale = String(), const String &p_script = String(), int p_weight = 400, int p_stretch = 100, bool p_italic = false) const override;
+ virtual String get_system_font_path(const String &p_font_name, int p_weight = 400, int p_stretch = 100, 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;
@@ -106,7 +110,6 @@ public:
virtual Error shell_open(String p_uri) override;
- void set_user_data_dir(String p_dir);
virtual String get_user_data_dir() const override;
virtual String get_cache_path() const override;
diff --git a/platform/ios/os_ios.mm b/platform/ios/os_ios.mm
index b6b94d2f5e..d0c367cc45 100644
--- a/platform/ios/os_ios.mm
+++ b/platform/ios/os_ios.mm
@@ -90,7 +90,7 @@ OS_IOS *OS_IOS::get_singleton() {
return (OS_IOS *)OS::get_singleton();
}
-OS_IOS::OS_IOS(String p_data_dir, String p_cache_dir) {
+OS_IOS::OS_IOS() {
for (int i = 0; i < ios_init_callbacks_count; ++i) {
ios_init_callbacks[i]();
}
@@ -101,11 +101,6 @@ OS_IOS::OS_IOS(String p_data_dir, String p_cache_dir) {
main_loop = nullptr;
- // can't call set_data_dir from here, since it requires DirAccess
- // which is initialized in initialize_core
- user_data_dir = p_data_dir;
- cache_dir = p_cache_dir;
-
Vector<Logger *> loggers;
loggers.push_back(memnew(SyslogLogger));
#ifdef DEBUG_ENABLED
@@ -130,8 +125,6 @@ void OS_IOS::alert(const String &p_alert, const String &p_title) {
void OS_IOS::initialize_core() {
OS_Unix::initialize_core();
-
- set_user_data_dir(user_data_dir);
}
void OS_IOS::initialize() {
@@ -205,8 +198,31 @@ void OS_IOS::finalize() {
// MARK: Dynamic Libraries
+_FORCE_INLINE_ String OS_IOS::get_framework_executable(const String &p_path) {
+ Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+
+ // Read framework bundle to get executable name.
+ NSURL *url = [NSURL fileURLWithPath:@(p_path.utf8().get_data())];
+ NSBundle *bundle = [NSBundle bundleWithURL:url];
+ if (bundle) {
+ String exe_path = String::utf8([[bundle executablePath] UTF8String]);
+ if (da->file_exists(exe_path)) {
+ return exe_path;
+ }
+ }
+
+ // Try default executable name (invalid framework).
+ if (da->dir_exists(p_path) && da->file_exists(p_path.path_join(p_path.get_file().get_basename()))) {
+ return p_path.path_join(p_path.get_file().get_basename());
+ }
+
+ // Not a framework, try loading as .dylib.
+ return p_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) {
+ // Static xcframework.
p_library_handle = RTLD_SELF;
if (r_resolved_path != nullptr) {
@@ -215,7 +231,27 @@ Error OS_IOS::open_dynamic_library(const String p_path, void *&p_library_handle,
return OK;
}
- return OS_Unix::open_dynamic_library(p_path, p_library_handle, p_also_set_library_path, r_resolved_path);
+
+ String path = get_framework_executable(p_path);
+
+ if (!FileAccess::exists(path)) {
+ // Load .dylib or framework from within the executable path.
+ path = get_framework_executable(get_executable_path().get_base_dir().path_join(p_path.get_file()));
+ }
+
+ if (!FileAccess::exists(path)) {
+ // Load .dylib or framework from a standard iOS location.
+ path = get_framework_executable(get_executable_path().get_base_dir().path_join("Frameworks").path_join(p_path.get_file()));
+ }
+
+ p_library_handle = dlopen(path.utf8().get_data(), RTLD_NOW);
+ ERR_FAIL_COND_V_MSG(!p_library_handle, ERR_CANT_OPEN, "Can't open dynamic library: " + p_path + ", error: " + dlerror() + ".");
+
+ if (r_resolved_path != nullptr) {
+ *r_resolved_path = path;
+ }
+
+ return OK;
}
Error OS_IOS::close_dynamic_library(void *p_library_handle) {
@@ -273,18 +309,26 @@ Error OS_IOS::shell_open(String p_uri) {
return OK;
}
-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 OS_IOS::get_user_data_dir() const {
- return user_data_dir;
+ static String ret;
+ if (ret.is_empty()) {
+ NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
+ if (paths && [paths count] >= 1) {
+ ret.parse_utf8([[paths firstObject] UTF8String]);
+ }
+ }
+ return ret;
}
String OS_IOS::get_cache_path() const {
- return cache_dir;
+ static String ret;
+ if (ret.is_empty()) {
+ NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
+ if (paths && [paths count] >= 1) {
+ ret.parse_utf8([[paths firstObject] UTF8String]);
+ }
+ }
+ return ret;
}
String OS_IOS::get_locale() const {
@@ -333,9 +377,7 @@ Vector<String> OS_IOS::get_system_fonts() const {
return ret;
}
-String OS_IOS::get_system_font_path(const String &p_font_name, bool p_bold, bool p_italic) const {
- String ret;
-
+String OS_IOS::_get_default_fontname(const String &p_font_name) const {
String font_name = p_font_name;
if (font_name.to_lower() == "sans-serif") {
font_name = "Helvetica";
@@ -348,21 +390,153 @@ String OS_IOS::get_system_font_path(const String &p_font_name, bool p_bold, bool
} else if (font_name.to_lower() == "cursive") {
font_name = "Apple Chancery";
};
+ return font_name;
+}
+
+CGFloat OS_IOS::_weight_to_ct(int p_weight) const {
+ if (p_weight < 150) {
+ return -0.80;
+ } else if (p_weight < 250) {
+ return -0.60;
+ } else if (p_weight < 350) {
+ return -0.40;
+ } else if (p_weight < 450) {
+ return 0.0;
+ } else if (p_weight < 550) {
+ return 0.23;
+ } else if (p_weight < 650) {
+ return 0.30;
+ } else if (p_weight < 750) {
+ return 0.40;
+ } else if (p_weight < 850) {
+ return 0.56;
+ } else if (p_weight < 925) {
+ return 0.62;
+ } else {
+ return 1.00;
+ }
+}
+
+CGFloat OS_IOS::_stretch_to_ct(int p_stretch) const {
+ if (p_stretch < 56) {
+ return -0.5;
+ } else if (p_stretch < 69) {
+ return -0.37;
+ } else if (p_stretch < 81) {
+ return -0.25;
+ } else if (p_stretch < 93) {
+ return -0.13;
+ } else if (p_stretch < 106) {
+ return 0.0;
+ } else if (p_stretch < 137) {
+ return 0.13;
+ } else if (p_stretch < 144) {
+ return 0.25;
+ } else if (p_stretch < 162) {
+ return 0.37;
+ } else {
+ return 0.5;
+ }
+}
+
+Vector<String> OS_IOS::get_system_font_path_for_text(const String &p_font_name, const String &p_text, const String &p_locale, const String &p_script, int p_weight, int p_stretch, bool p_italic) const {
+ Vector<String> ret;
+ String font_name = _get_default_fontname(p_font_name);
+
+ CFStringRef name = CFStringCreateWithCString(kCFAllocatorDefault, font_name.utf8().get_data(), kCFStringEncodingUTF8);
+ CTFontSymbolicTraits traits = 0;
+ if (p_weight >= 700) {
+ traits |= kCTFontBoldTrait;
+ }
+ if (p_italic) {
+ traits |= kCTFontItalicTrait;
+ }
+ if (p_stretch < 100) {
+ traits |= kCTFontCondensedTrait;
+ } else if (p_stretch > 100) {
+ traits |= kCTFontExpandedTrait;
+ }
+
+ CFNumberRef sym_traits = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &traits);
+ CFMutableDictionaryRef traits_dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, nullptr, nullptr);
+ CFDictionaryAddValue(traits_dict, kCTFontSymbolicTrait, sym_traits);
+
+ CGFloat weight = _weight_to_ct(p_weight);
+ CFNumberRef font_weight = CFNumberCreate(kCFAllocatorDefault, kCFNumberCGFloatType, &weight);
+ CFDictionaryAddValue(traits_dict, kCTFontWeightTrait, font_weight);
+
+ CGFloat stretch = _stretch_to_ct(p_stretch);
+ CFNumberRef font_stretch = CFNumberCreate(kCFAllocatorDefault, kCFNumberCGFloatType, &stretch);
+ CFDictionaryAddValue(traits_dict, kCTFontWidthTrait, font_stretch);
+
+ CFMutableDictionaryRef attributes = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, nullptr, nullptr);
+ CFDictionaryAddValue(attributes, kCTFontFamilyNameAttribute, name);
+ CFDictionaryAddValue(attributes, kCTFontTraitsAttribute, traits_dict);
+
+ CTFontDescriptorRef font = CTFontDescriptorCreateWithAttributes(attributes);
+ if (font) {
+ CTFontRef family = CTFontCreateWithFontDescriptor(font, 0, nullptr);
+ CFStringRef string = CFStringCreateWithCString(kCFAllocatorDefault, p_text.utf8().get_data(), kCFStringEncodingUTF8);
+ CFRange range = CFRangeMake(0, CFStringGetLength(string));
+ CTFontRef fallback_family = CTFontCreateForString(family, string, range);
+ if (fallback_family) {
+ CTFontDescriptorRef fallback_font = CTFontCopyFontDescriptor(fallback_family);
+ if (fallback_font) {
+ CFURLRef url = (CFURLRef)CTFontDescriptorCopyAttribute(fallback_font, kCTFontURLAttribute);
+ if (url) {
+ NSString *font_path = [NSString stringWithString:[(__bridge NSURL *)url path]];
+ ret.push_back(String::utf8([font_path UTF8String]));
+ CFRelease(url);
+ }
+ CFRelease(fallback_font);
+ }
+ CFRelease(fallback_family);
+ }
+ CFRelease(string);
+ CFRelease(font);
+ }
+
+ CFRelease(attributes);
+ CFRelease(traits_dict);
+ CFRelease(sym_traits);
+ CFRelease(font_stretch);
+ CFRelease(font_weight);
+ CFRelease(name);
+
+ return ret;
+}
+
+String OS_IOS::get_system_font_path(const String &p_font_name, int p_weight, int p_stretch, bool p_italic) const {
+ String ret;
+ String font_name = _get_default_fontname(p_font_name);
CFStringRef name = CFStringCreateWithCString(kCFAllocatorDefault, font_name.utf8().get_data(), kCFStringEncodingUTF8);
CTFontSymbolicTraits traits = 0;
- if (p_bold) {
+ if (p_weight >= 700) {
traits |= kCTFontBoldTrait;
}
if (p_italic) {
traits |= kCTFontItalicTrait;
}
+ if (p_stretch < 100) {
+ traits |= kCTFontCondensedTrait;
+ } else if (p_stretch > 100) {
+ traits |= kCTFontExpandedTrait;
+ }
CFNumberRef sym_traits = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &traits);
CFMutableDictionaryRef traits_dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, nullptr, nullptr);
CFDictionaryAddValue(traits_dict, kCTFontSymbolicTrait, sym_traits);
+ CGFloat weight = _weight_to_ct(p_weight);
+ CFNumberRef font_weight = CFNumberCreate(kCFAllocatorDefault, kCFNumberCGFloatType, &weight);
+ CFDictionaryAddValue(traits_dict, kCTFontWeightTrait, font_weight);
+
+ CGFloat stretch = _stretch_to_ct(p_stretch);
+ CFNumberRef font_stretch = CFNumberCreate(kCFAllocatorDefault, kCFNumberCGFloatType, &stretch);
+ CFDictionaryAddValue(traits_dict, kCTFontWidthTrait, font_stretch);
+
CFMutableDictionaryRef attributes = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, nullptr, nullptr);
CFDictionaryAddValue(attributes, kCTFontFamilyNameAttribute, name);
CFDictionaryAddValue(attributes, kCTFontTraitsAttribute, traits_dict);
@@ -381,6 +555,8 @@ String OS_IOS::get_system_font_path(const String &p_font_name, bool p_bold, bool
CFRelease(attributes);
CFRelease(traits_dict);
CFRelease(sym_traits);
+ CFRelease(font_stretch);
+ CFRelease(font_weight);
CFRelease(name);
return ret;
diff --git a/platform/linuxbsd/dbus-so_wrap.c b/platform/linuxbsd/dbus-so_wrap.c
index 0876bc88b0..48d0d9b907 100644
--- a/platform/linuxbsd/dbus-so_wrap.c
+++ b/platform/linuxbsd/dbus-so_wrap.c
@@ -1,7 +1,7 @@
// 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
+// flags: ./generate-wrapper.py --include /usr/include/dbus-1.0/dbus/dbus.h --sys-include <dbus/dbus.h> --soname libdbus-1.so.3 --init-name dbus --output-header dbus-so_wrap.h --output-implementation dbus-so_wrap.c
//
#include <stdint.h>
@@ -725,7 +725,7 @@ 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);
+ handle = dlopen("libdbus-1.so.3", RTLD_LAZY);
if (!handle) {
if (verbose) {
fprintf(stderr, "%s\n", dlerror());
diff --git a/platform/linuxbsd/detect.py b/platform/linuxbsd/detect.py
index ac69f3806b..844b15e9fb 100644
--- a/platform/linuxbsd/detect.py
+++ b/platform/linuxbsd/detect.py
@@ -184,13 +184,14 @@ def configure(env: "Environment"):
## Dependencies
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")
+ # Only cflags, we dlopen the libraries.
+ env.ParseConfig("pkg-config x11 --cflags")
+ env.ParseConfig("pkg-config xcursor --cflags")
+ env.ParseConfig("pkg-config xinerama --cflags")
+ env.ParseConfig("pkg-config xext --cflags")
+ env.ParseConfig("pkg-config xrandr --cflags")
+ env.ParseConfig("pkg-config xrender --cflags")
+ env.ParseConfig("pkg-config xi --cflags")
if env["touch"]:
env.Append(CPPDEFINES=["TOUCH_ENABLED"])
@@ -356,7 +357,6 @@ def configure(env: "Environment"):
if env["opengl3"]:
env.Append(CPPDEFINES=["GLES3_ENABLED"])
- env.ParseConfig("pkg-config gl --cflags --libs")
env.Append(LIBS=["pthread"])
diff --git a/platform/linuxbsd/fontconfig-so_wrap.c b/platform/linuxbsd/fontconfig-so_wrap.c
index 1a915faf98..62901b14a9 100644
--- a/platform/linuxbsd/fontconfig-so_wrap.c
+++ b/platform/linuxbsd/fontconfig-so_wrap.c
@@ -1,7 +1,7 @@
// 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
+// generated by ./generate-wrapper.py 0.3 on 2022-11-22 10:28:00
+// flags: ./generate-wrapper.py --include /usr/include/fontconfig/fontconfig.h --sys-include <fontconfig/fontconfig.h> --soname libfontconfig.so.1 --init-name fontconfig --output-header fontconfig-so_wrap.h --output-implementation fontconfig-so_wrap.c --omit-prefix FcCharSetFirst --omit-prefix FcCharSetNext
//
#include <stdint.h>
@@ -18,6 +18,8 @@
#define FcDirCacheValid FcDirCacheValid_dylibloader_orig_fontconfig
#define FcDirCacheClean FcDirCacheClean_dylibloader_orig_fontconfig
#define FcCacheCreateTagFile FcCacheCreateTagFile_dylibloader_orig_fontconfig
+#define FcDirCacheCreateUUID FcDirCacheCreateUUID_dylibloader_orig_fontconfig
+#define FcDirCacheDeleteUUID FcDirCacheDeleteUUID_dylibloader_orig_fontconfig
#define FcConfigHome FcConfigHome_dylibloader_orig_fontconfig
#define FcConfigEnableHome FcConfigEnableHome_dylibloader_orig_fontconfig
#define FcConfigFilename FcConfigFilename_dylibloader_orig_fontconfig
@@ -44,6 +46,26 @@
#define FcConfigSubstitute FcConfigSubstitute_dylibloader_orig_fontconfig
#define FcConfigGetSysRoot FcConfigGetSysRoot_dylibloader_orig_fontconfig
#define FcConfigSetSysRoot FcConfigSetSysRoot_dylibloader_orig_fontconfig
+#define FcConfigFileInfoIterInit FcConfigFileInfoIterInit_dylibloader_orig_fontconfig
+#define FcConfigFileInfoIterNext FcConfigFileInfoIterNext_dylibloader_orig_fontconfig
+#define FcConfigFileInfoIterGet FcConfigFileInfoIterGet_dylibloader_orig_fontconfig
+#define FcCharSetCreate FcCharSetCreate_dylibloader_orig_fontconfig
+#define FcCharSetNew FcCharSetNew_dylibloader_orig_fontconfig
+#define FcCharSetDestroy FcCharSetDestroy_dylibloader_orig_fontconfig
+#define FcCharSetAddChar FcCharSetAddChar_dylibloader_orig_fontconfig
+#define FcCharSetDelChar FcCharSetDelChar_dylibloader_orig_fontconfig
+#define FcCharSetCopy FcCharSetCopy_dylibloader_orig_fontconfig
+#define FcCharSetEqual FcCharSetEqual_dylibloader_orig_fontconfig
+#define FcCharSetIntersect FcCharSetIntersect_dylibloader_orig_fontconfig
+#define FcCharSetUnion FcCharSetUnion_dylibloader_orig_fontconfig
+#define FcCharSetSubtract FcCharSetSubtract_dylibloader_orig_fontconfig
+#define FcCharSetMerge FcCharSetMerge_dylibloader_orig_fontconfig
+#define FcCharSetHasChar FcCharSetHasChar_dylibloader_orig_fontconfig
+#define FcCharSetCount FcCharSetCount_dylibloader_orig_fontconfig
+#define FcCharSetIntersectCount FcCharSetIntersectCount_dylibloader_orig_fontconfig
+#define FcCharSetSubtractCount FcCharSetSubtractCount_dylibloader_orig_fontconfig
+#define FcCharSetIsSubset FcCharSetIsSubset_dylibloader_orig_fontconfig
+#define FcCharSetCoverage FcCharSetCoverage_dylibloader_orig_fontconfig
#define FcValuePrint FcValuePrint_dylibloader_orig_fontconfig
#define FcPatternPrint FcPatternPrint_dylibloader_orig_fontconfig
#define FcFontSetPrint FcFontSetPrint_dylibloader_orig_fontconfig
@@ -59,6 +81,7 @@
#define FcDirCacheLoadFile FcDirCacheLoadFile_dylibloader_orig_fontconfig
#define FcDirCacheUnload FcDirCacheUnload_dylibloader_orig_fontconfig
#define FcFreeTypeQuery FcFreeTypeQuery_dylibloader_orig_fontconfig
+#define FcFreeTypeQueryAll FcFreeTypeQueryAll_dylibloader_orig_fontconfig
#define FcFontSetCreate FcFontSetCreate_dylibloader_orig_fontconfig
#define FcFontSetDestroy FcFontSetDestroy_dylibloader_orig_fontconfig
#define FcFontSetAdd FcFontSetAdd_dylibloader_orig_fontconfig
@@ -129,6 +152,7 @@
#define FcValueEqual FcValueEqual_dylibloader_orig_fontconfig
#define FcValueSave FcValueSave_dylibloader_orig_fontconfig
#define FcPatternDestroy FcPatternDestroy_dylibloader_orig_fontconfig
+#define FcPatternObjectCount FcPatternObjectCount_dylibloader_orig_fontconfig
#define FcPatternEqual FcPatternEqual_dylibloader_orig_fontconfig
#define FcPatternEqualSubset FcPatternEqualSubset_dylibloader_orig_fontconfig
#define FcPatternHash FcPatternHash_dylibloader_orig_fontconfig
@@ -162,8 +186,18 @@
#define FcRangeDestroy FcRangeDestroy_dylibloader_orig_fontconfig
#define FcRangeCopy FcRangeCopy_dylibloader_orig_fontconfig
#define FcRangeGetDouble FcRangeGetDouble_dylibloader_orig_fontconfig
+#define FcPatternIterStart FcPatternIterStart_dylibloader_orig_fontconfig
+#define FcPatternIterNext FcPatternIterNext_dylibloader_orig_fontconfig
+#define FcPatternIterEqual FcPatternIterEqual_dylibloader_orig_fontconfig
+#define FcPatternFindIter FcPatternFindIter_dylibloader_orig_fontconfig
+#define FcPatternIterIsValid FcPatternIterIsValid_dylibloader_orig_fontconfig
+#define FcPatternIterGetObject FcPatternIterGetObject_dylibloader_orig_fontconfig
+#define FcPatternIterValueCount FcPatternIterValueCount_dylibloader_orig_fontconfig
+#define FcPatternIterGetValue FcPatternIterGetValue_dylibloader_orig_fontconfig
#define FcWeightFromOpenType FcWeightFromOpenType_dylibloader_orig_fontconfig
+#define FcWeightFromOpenTypeDouble FcWeightFromOpenTypeDouble_dylibloader_orig_fontconfig
#define FcWeightToOpenType FcWeightToOpenType_dylibloader_orig_fontconfig
+#define FcWeightToOpenTypeDouble FcWeightToOpenTypeDouble_dylibloader_orig_fontconfig
#define FcStrCopy FcStrCopy_dylibloader_orig_fontconfig
#define FcStrCopyFilename FcStrCopyFilename_dylibloader_orig_fontconfig
#define FcStrPlus FcStrPlus_dylibloader_orig_fontconfig
@@ -207,6 +241,8 @@
#undef FcDirCacheValid
#undef FcDirCacheClean
#undef FcCacheCreateTagFile
+#undef FcDirCacheCreateUUID
+#undef FcDirCacheDeleteUUID
#undef FcConfigHome
#undef FcConfigEnableHome
#undef FcConfigFilename
@@ -233,6 +269,26 @@
#undef FcConfigSubstitute
#undef FcConfigGetSysRoot
#undef FcConfigSetSysRoot
+#undef FcConfigFileInfoIterInit
+#undef FcConfigFileInfoIterNext
+#undef FcConfigFileInfoIterGet
+#undef FcCharSetCreate
+#undef FcCharSetNew
+#undef FcCharSetDestroy
+#undef FcCharSetAddChar
+#undef FcCharSetDelChar
+#undef FcCharSetCopy
+#undef FcCharSetEqual
+#undef FcCharSetIntersect
+#undef FcCharSetUnion
+#undef FcCharSetSubtract
+#undef FcCharSetMerge
+#undef FcCharSetHasChar
+#undef FcCharSetCount
+#undef FcCharSetIntersectCount
+#undef FcCharSetSubtractCount
+#undef FcCharSetIsSubset
+#undef FcCharSetCoverage
#undef FcValuePrint
#undef FcPatternPrint
#undef FcFontSetPrint
@@ -248,6 +304,7 @@
#undef FcDirCacheLoadFile
#undef FcDirCacheUnload
#undef FcFreeTypeQuery
+#undef FcFreeTypeQueryAll
#undef FcFontSetCreate
#undef FcFontSetDestroy
#undef FcFontSetAdd
@@ -318,6 +375,7 @@
#undef FcValueEqual
#undef FcValueSave
#undef FcPatternDestroy
+#undef FcPatternObjectCount
#undef FcPatternEqual
#undef FcPatternEqualSubset
#undef FcPatternHash
@@ -351,8 +409,18 @@
#undef FcRangeDestroy
#undef FcRangeCopy
#undef FcRangeGetDouble
+#undef FcPatternIterStart
+#undef FcPatternIterNext
+#undef FcPatternIterEqual
+#undef FcPatternFindIter
+#undef FcPatternIterIsValid
+#undef FcPatternIterGetObject
+#undef FcPatternIterValueCount
+#undef FcPatternIterGetValue
#undef FcWeightFromOpenType
+#undef FcWeightFromOpenTypeDouble
#undef FcWeightToOpenType
+#undef FcWeightToOpenTypeDouble
#undef FcStrCopy
#undef FcStrCopyFilename
#undef FcStrPlus
@@ -397,6 +465,8 @@ FcBool (*FcDirCacheUnlink_dylibloader_wrapper_fontconfig)(const FcChar8*, FcConf
FcBool (*FcDirCacheValid_dylibloader_wrapper_fontconfig)(const FcChar8*);
FcBool (*FcDirCacheClean_dylibloader_wrapper_fontconfig)(const FcChar8*, FcBool);
void (*FcCacheCreateTagFile_dylibloader_wrapper_fontconfig)(const FcConfig*);
+FcBool (*FcDirCacheCreateUUID_dylibloader_wrapper_fontconfig)( FcChar8*, FcBool, FcConfig*);
+FcBool (*FcDirCacheDeleteUUID_dylibloader_wrapper_fontconfig)(const FcChar8*, FcConfig*);
FcChar8* (*FcConfigHome_dylibloader_wrapper_fontconfig)( void);
FcBool (*FcConfigEnableHome_dylibloader_wrapper_fontconfig)( FcBool);
FcChar8* (*FcConfigFilename_dylibloader_wrapper_fontconfig)(const FcChar8*);
@@ -423,6 +493,26 @@ FcBool (*FcConfigSubstituteWithPat_dylibloader_wrapper_fontconfig)( FcConfig*, F
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 (*FcConfigFileInfoIterInit_dylibloader_wrapper_fontconfig)( FcConfig*, FcConfigFileInfoIter*);
+FcBool (*FcConfigFileInfoIterNext_dylibloader_wrapper_fontconfig)( FcConfig*, FcConfigFileInfoIter*);
+FcBool (*FcConfigFileInfoIterGet_dylibloader_wrapper_fontconfig)( FcConfig*, FcConfigFileInfoIter*, FcChar8**, FcChar8**, FcBool*);
+FcCharSet* (*FcCharSetCreate_dylibloader_wrapper_fontconfig)( void);
+FcCharSet* (*FcCharSetNew_dylibloader_wrapper_fontconfig)( void);
+void (*FcCharSetDestroy_dylibloader_wrapper_fontconfig)( FcCharSet*);
+FcBool (*FcCharSetAddChar_dylibloader_wrapper_fontconfig)( FcCharSet*, FcChar32);
+FcBool (*FcCharSetDelChar_dylibloader_wrapper_fontconfig)( FcCharSet*, FcChar32);
+FcCharSet* (*FcCharSetCopy_dylibloader_wrapper_fontconfig)( FcCharSet*);
+FcBool (*FcCharSetEqual_dylibloader_wrapper_fontconfig)(const FcCharSet*,const FcCharSet*);
+FcCharSet* (*FcCharSetIntersect_dylibloader_wrapper_fontconfig)(const FcCharSet*,const FcCharSet*);
+FcCharSet* (*FcCharSetUnion_dylibloader_wrapper_fontconfig)(const FcCharSet*,const FcCharSet*);
+FcCharSet* (*FcCharSetSubtract_dylibloader_wrapper_fontconfig)(const FcCharSet*,const FcCharSet*);
+FcBool (*FcCharSetMerge_dylibloader_wrapper_fontconfig)( FcCharSet*,const FcCharSet*, FcBool*);
+FcBool (*FcCharSetHasChar_dylibloader_wrapper_fontconfig)(const FcCharSet*, FcChar32);
+FcChar32 (*FcCharSetCount_dylibloader_wrapper_fontconfig)(const FcCharSet*);
+FcChar32 (*FcCharSetIntersectCount_dylibloader_wrapper_fontconfig)(const FcCharSet*,const FcCharSet*);
+FcChar32 (*FcCharSetSubtractCount_dylibloader_wrapper_fontconfig)(const FcCharSet*,const FcCharSet*);
+FcBool (*FcCharSetIsSubset_dylibloader_wrapper_fontconfig)(const FcCharSet*,const FcCharSet*);
+FcChar32 (*FcCharSetCoverage_dylibloader_wrapper_fontconfig)(const FcCharSet*, FcChar32, FcChar32*);
void (*FcValuePrint_dylibloader_wrapper_fontconfig)(const FcValue);
void (*FcPatternPrint_dylibloader_wrapper_fontconfig)(const FcPattern*);
void (*FcFontSetPrint_dylibloader_wrapper_fontconfig)(const FcFontSet*);
@@ -437,7 +527,8 @@ FcCache* (*FcDirCacheRescan_dylibloader_wrapper_fontconfig)(const FcChar8*, FcCo
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*);
+FcPattern* (*FcFreeTypeQuery_dylibloader_wrapper_fontconfig)(const FcChar8*, unsigned int, FcBlanks*, int*);
+unsigned int (*FcFreeTypeQueryAll_dylibloader_wrapper_fontconfig)(const FcChar8*, unsigned int, FcBlanks*, int*, FcFontSet*);
FcFontSet* (*FcFontSetCreate_dylibloader_wrapper_fontconfig)( void);
void (*FcFontSetDestroy_dylibloader_wrapper_fontconfig)( FcFontSet*);
FcBool (*FcFontSetAdd_dylibloader_wrapper_fontconfig)( FcFontSet*, FcPattern*);
@@ -508,6 +599,7 @@ 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*);
+int (*FcPatternObjectCount_dylibloader_wrapper_fontconfig)(const 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*);
@@ -541,8 +633,18 @@ FcRange* (*FcRangeCreateInteger_dylibloader_wrapper_fontconfig)( FcChar32, FcCha
void (*FcRangeDestroy_dylibloader_wrapper_fontconfig)( FcRange*);
FcRange* (*FcRangeCopy_dylibloader_wrapper_fontconfig)(const FcRange*);
FcBool (*FcRangeGetDouble_dylibloader_wrapper_fontconfig)(const FcRange*, double*, double*);
+void (*FcPatternIterStart_dylibloader_wrapper_fontconfig)(const FcPattern*, FcPatternIter*);
+FcBool (*FcPatternIterNext_dylibloader_wrapper_fontconfig)(const FcPattern*, FcPatternIter*);
+FcBool (*FcPatternIterEqual_dylibloader_wrapper_fontconfig)(const FcPattern*, FcPatternIter*,const FcPattern*, FcPatternIter*);
+FcBool (*FcPatternFindIter_dylibloader_wrapper_fontconfig)(const FcPattern*, FcPatternIter*,const char*);
+FcBool (*FcPatternIterIsValid_dylibloader_wrapper_fontconfig)(const FcPattern*, FcPatternIter*);
+const char* (*FcPatternIterGetObject_dylibloader_wrapper_fontconfig)(const FcPattern*, FcPatternIter*);
+int (*FcPatternIterValueCount_dylibloader_wrapper_fontconfig)(const FcPattern*, FcPatternIter*);
+FcResult (*FcPatternIterGetValue_dylibloader_wrapper_fontconfig)(const FcPattern*, FcPatternIter*, int, FcValue*, FcValueBinding*);
int (*FcWeightFromOpenType_dylibloader_wrapper_fontconfig)( int);
+double (*FcWeightFromOpenTypeDouble_dylibloader_wrapper_fontconfig)( double);
int (*FcWeightToOpenType_dylibloader_wrapper_fontconfig)( int);
+double (*FcWeightToOpenTypeDouble_dylibloader_wrapper_fontconfig)( double);
FcChar8* (*FcStrCopy_dylibloader_wrapper_fontconfig)(const FcChar8*);
FcChar8* (*FcStrCopyFilename_dylibloader_wrapper_fontconfig)(const FcChar8*);
FcChar8* (*FcStrPlus_dylibloader_wrapper_fontconfig)(const FcChar8*,const FcChar8*);
@@ -575,7 +677,7 @@ FcBool (*FcConfigParseAndLoadFromMemory_dylibloader_wrapper_fontconfig)( FcConfi
int initialize_fontconfig(int verbose) {
void *handle;
char *error;
- handle = dlopen("libfontconfig.so", RTLD_LAZY);
+ handle = dlopen("libfontconfig.so.1", RTLD_LAZY);
if (!handle) {
if (verbose) {
fprintf(stderr, "%s\n", dlerror());
@@ -687,6 +789,22 @@ int initialize_fontconfig(int verbose) {
fprintf(stderr, "%s\n", error);
}
}
+// FcDirCacheCreateUUID
+ *(void **) (&FcDirCacheCreateUUID_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcDirCacheCreateUUID");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcDirCacheDeleteUUID
+ *(void **) (&FcDirCacheDeleteUUID_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcDirCacheDeleteUUID");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
// FcConfigHome
*(void **) (&FcConfigHome_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcConfigHome");
if (verbose) {
@@ -895,6 +1013,166 @@ int initialize_fontconfig(int verbose) {
fprintf(stderr, "%s\n", error);
}
}
+// FcConfigFileInfoIterInit
+ *(void **) (&FcConfigFileInfoIterInit_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcConfigFileInfoIterInit");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcConfigFileInfoIterNext
+ *(void **) (&FcConfigFileInfoIterNext_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcConfigFileInfoIterNext");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcConfigFileInfoIterGet
+ *(void **) (&FcConfigFileInfoIterGet_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcConfigFileInfoIterGet");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcCharSetCreate
+ *(void **) (&FcCharSetCreate_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcCharSetCreate");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcCharSetNew
+ *(void **) (&FcCharSetNew_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcCharSetNew");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcCharSetDestroy
+ *(void **) (&FcCharSetDestroy_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcCharSetDestroy");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcCharSetAddChar
+ *(void **) (&FcCharSetAddChar_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcCharSetAddChar");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcCharSetDelChar
+ *(void **) (&FcCharSetDelChar_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcCharSetDelChar");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcCharSetCopy
+ *(void **) (&FcCharSetCopy_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcCharSetCopy");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcCharSetEqual
+ *(void **) (&FcCharSetEqual_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcCharSetEqual");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcCharSetIntersect
+ *(void **) (&FcCharSetIntersect_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcCharSetIntersect");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcCharSetUnion
+ *(void **) (&FcCharSetUnion_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcCharSetUnion");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcCharSetSubtract
+ *(void **) (&FcCharSetSubtract_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcCharSetSubtract");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcCharSetMerge
+ *(void **) (&FcCharSetMerge_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcCharSetMerge");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcCharSetHasChar
+ *(void **) (&FcCharSetHasChar_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcCharSetHasChar");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcCharSetCount
+ *(void **) (&FcCharSetCount_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcCharSetCount");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcCharSetIntersectCount
+ *(void **) (&FcCharSetIntersectCount_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcCharSetIntersectCount");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcCharSetSubtractCount
+ *(void **) (&FcCharSetSubtractCount_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcCharSetSubtractCount");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcCharSetIsSubset
+ *(void **) (&FcCharSetIsSubset_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcCharSetIsSubset");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcCharSetCoverage
+ *(void **) (&FcCharSetCoverage_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcCharSetCoverage");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
// FcValuePrint
*(void **) (&FcValuePrint_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcValuePrint");
if (verbose) {
@@ -1015,6 +1293,14 @@ int initialize_fontconfig(int verbose) {
fprintf(stderr, "%s\n", error);
}
}
+// FcFreeTypeQueryAll
+ *(void **) (&FcFreeTypeQueryAll_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcFreeTypeQueryAll");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
// FcFontSetCreate
*(void **) (&FcFontSetCreate_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcFontSetCreate");
if (verbose) {
@@ -1575,6 +1861,14 @@ int initialize_fontconfig(int verbose) {
fprintf(stderr, "%s\n", error);
}
}
+// FcPatternObjectCount
+ *(void **) (&FcPatternObjectCount_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcPatternObjectCount");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
// FcPatternEqual
*(void **) (&FcPatternEqual_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcPatternEqual");
if (verbose) {
@@ -1839,6 +2133,70 @@ int initialize_fontconfig(int verbose) {
fprintf(stderr, "%s\n", error);
}
}
+// FcPatternIterStart
+ *(void **) (&FcPatternIterStart_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcPatternIterStart");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcPatternIterNext
+ *(void **) (&FcPatternIterNext_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcPatternIterNext");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcPatternIterEqual
+ *(void **) (&FcPatternIterEqual_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcPatternIterEqual");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcPatternFindIter
+ *(void **) (&FcPatternFindIter_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcPatternFindIter");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcPatternIterIsValid
+ *(void **) (&FcPatternIterIsValid_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcPatternIterIsValid");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcPatternIterGetObject
+ *(void **) (&FcPatternIterGetObject_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcPatternIterGetObject");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcPatternIterValueCount
+ *(void **) (&FcPatternIterValueCount_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcPatternIterValueCount");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcPatternIterGetValue
+ *(void **) (&FcPatternIterGetValue_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcPatternIterGetValue");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
// FcWeightFromOpenType
*(void **) (&FcWeightFromOpenType_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcWeightFromOpenType");
if (verbose) {
@@ -1847,6 +2205,14 @@ int initialize_fontconfig(int verbose) {
fprintf(stderr, "%s\n", error);
}
}
+// FcWeightFromOpenTypeDouble
+ *(void **) (&FcWeightFromOpenTypeDouble_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcWeightFromOpenTypeDouble");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
// FcWeightToOpenType
*(void **) (&FcWeightToOpenType_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcWeightToOpenType");
if (verbose) {
@@ -1855,6 +2221,14 @@ int initialize_fontconfig(int verbose) {
fprintf(stderr, "%s\n", error);
}
}
+// FcWeightToOpenTypeDouble
+ *(void **) (&FcWeightToOpenTypeDouble_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcWeightToOpenTypeDouble");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
// FcStrCopy
*(void **) (&FcStrCopy_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcStrCopy");
if (verbose) {
diff --git a/platform/linuxbsd/fontconfig-so_wrap.h b/platform/linuxbsd/fontconfig-so_wrap.h
index f0794cce8b..0c8259deb7 100644
--- a/platform/linuxbsd/fontconfig-so_wrap.h
+++ b/platform/linuxbsd/fontconfig-so_wrap.h
@@ -2,8 +2,8 @@
#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
+// generated by ./generate-wrapper.py 0.3 on 2022-11-22 10:28:00
+// 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 FcCharSetFirst --omit-prefix FcCharSetNext
//
#include <stdint.h>
@@ -20,6 +20,8 @@
#define FcDirCacheValid FcDirCacheValid_dylibloader_orig_fontconfig
#define FcDirCacheClean FcDirCacheClean_dylibloader_orig_fontconfig
#define FcCacheCreateTagFile FcCacheCreateTagFile_dylibloader_orig_fontconfig
+#define FcDirCacheCreateUUID FcDirCacheCreateUUID_dylibloader_orig_fontconfig
+#define FcDirCacheDeleteUUID FcDirCacheDeleteUUID_dylibloader_orig_fontconfig
#define FcConfigHome FcConfigHome_dylibloader_orig_fontconfig
#define FcConfigEnableHome FcConfigEnableHome_dylibloader_orig_fontconfig
#define FcConfigFilename FcConfigFilename_dylibloader_orig_fontconfig
@@ -46,6 +48,26 @@
#define FcConfigSubstitute FcConfigSubstitute_dylibloader_orig_fontconfig
#define FcConfigGetSysRoot FcConfigGetSysRoot_dylibloader_orig_fontconfig
#define FcConfigSetSysRoot FcConfigSetSysRoot_dylibloader_orig_fontconfig
+#define FcConfigFileInfoIterInit FcConfigFileInfoIterInit_dylibloader_orig_fontconfig
+#define FcConfigFileInfoIterNext FcConfigFileInfoIterNext_dylibloader_orig_fontconfig
+#define FcConfigFileInfoIterGet FcConfigFileInfoIterGet_dylibloader_orig_fontconfig
+#define FcCharSetCreate FcCharSetCreate_dylibloader_orig_fontconfig
+#define FcCharSetNew FcCharSetNew_dylibloader_orig_fontconfig
+#define FcCharSetDestroy FcCharSetDestroy_dylibloader_orig_fontconfig
+#define FcCharSetAddChar FcCharSetAddChar_dylibloader_orig_fontconfig
+#define FcCharSetDelChar FcCharSetDelChar_dylibloader_orig_fontconfig
+#define FcCharSetCopy FcCharSetCopy_dylibloader_orig_fontconfig
+#define FcCharSetEqual FcCharSetEqual_dylibloader_orig_fontconfig
+#define FcCharSetIntersect FcCharSetIntersect_dylibloader_orig_fontconfig
+#define FcCharSetUnion FcCharSetUnion_dylibloader_orig_fontconfig
+#define FcCharSetSubtract FcCharSetSubtract_dylibloader_orig_fontconfig
+#define FcCharSetMerge FcCharSetMerge_dylibloader_orig_fontconfig
+#define FcCharSetHasChar FcCharSetHasChar_dylibloader_orig_fontconfig
+#define FcCharSetCount FcCharSetCount_dylibloader_orig_fontconfig
+#define FcCharSetIntersectCount FcCharSetIntersectCount_dylibloader_orig_fontconfig
+#define FcCharSetSubtractCount FcCharSetSubtractCount_dylibloader_orig_fontconfig
+#define FcCharSetIsSubset FcCharSetIsSubset_dylibloader_orig_fontconfig
+#define FcCharSetCoverage FcCharSetCoverage_dylibloader_orig_fontconfig
#define FcValuePrint FcValuePrint_dylibloader_orig_fontconfig
#define FcPatternPrint FcPatternPrint_dylibloader_orig_fontconfig
#define FcFontSetPrint FcFontSetPrint_dylibloader_orig_fontconfig
@@ -61,6 +83,7 @@
#define FcDirCacheLoadFile FcDirCacheLoadFile_dylibloader_orig_fontconfig
#define FcDirCacheUnload FcDirCacheUnload_dylibloader_orig_fontconfig
#define FcFreeTypeQuery FcFreeTypeQuery_dylibloader_orig_fontconfig
+#define FcFreeTypeQueryAll FcFreeTypeQueryAll_dylibloader_orig_fontconfig
#define FcFontSetCreate FcFontSetCreate_dylibloader_orig_fontconfig
#define FcFontSetDestroy FcFontSetDestroy_dylibloader_orig_fontconfig
#define FcFontSetAdd FcFontSetAdd_dylibloader_orig_fontconfig
@@ -131,6 +154,7 @@
#define FcValueEqual FcValueEqual_dylibloader_orig_fontconfig
#define FcValueSave FcValueSave_dylibloader_orig_fontconfig
#define FcPatternDestroy FcPatternDestroy_dylibloader_orig_fontconfig
+#define FcPatternObjectCount FcPatternObjectCount_dylibloader_orig_fontconfig
#define FcPatternEqual FcPatternEqual_dylibloader_orig_fontconfig
#define FcPatternEqualSubset FcPatternEqualSubset_dylibloader_orig_fontconfig
#define FcPatternHash FcPatternHash_dylibloader_orig_fontconfig
@@ -164,8 +188,18 @@
#define FcRangeDestroy FcRangeDestroy_dylibloader_orig_fontconfig
#define FcRangeCopy FcRangeCopy_dylibloader_orig_fontconfig
#define FcRangeGetDouble FcRangeGetDouble_dylibloader_orig_fontconfig
+#define FcPatternIterStart FcPatternIterStart_dylibloader_orig_fontconfig
+#define FcPatternIterNext FcPatternIterNext_dylibloader_orig_fontconfig
+#define FcPatternIterEqual FcPatternIterEqual_dylibloader_orig_fontconfig
+#define FcPatternFindIter FcPatternFindIter_dylibloader_orig_fontconfig
+#define FcPatternIterIsValid FcPatternIterIsValid_dylibloader_orig_fontconfig
+#define FcPatternIterGetObject FcPatternIterGetObject_dylibloader_orig_fontconfig
+#define FcPatternIterValueCount FcPatternIterValueCount_dylibloader_orig_fontconfig
+#define FcPatternIterGetValue FcPatternIterGetValue_dylibloader_orig_fontconfig
#define FcWeightFromOpenType FcWeightFromOpenType_dylibloader_orig_fontconfig
+#define FcWeightFromOpenTypeDouble FcWeightFromOpenTypeDouble_dylibloader_orig_fontconfig
#define FcWeightToOpenType FcWeightToOpenType_dylibloader_orig_fontconfig
+#define FcWeightToOpenTypeDouble FcWeightToOpenTypeDouble_dylibloader_orig_fontconfig
#define FcStrCopy FcStrCopy_dylibloader_orig_fontconfig
#define FcStrCopyFilename FcStrCopyFilename_dylibloader_orig_fontconfig
#define FcStrPlus FcStrPlus_dylibloader_orig_fontconfig
@@ -209,6 +243,8 @@
#undef FcDirCacheValid
#undef FcDirCacheClean
#undef FcCacheCreateTagFile
+#undef FcDirCacheCreateUUID
+#undef FcDirCacheDeleteUUID
#undef FcConfigHome
#undef FcConfigEnableHome
#undef FcConfigFilename
@@ -235,6 +271,26 @@
#undef FcConfigSubstitute
#undef FcConfigGetSysRoot
#undef FcConfigSetSysRoot
+#undef FcConfigFileInfoIterInit
+#undef FcConfigFileInfoIterNext
+#undef FcConfigFileInfoIterGet
+#undef FcCharSetCreate
+#undef FcCharSetNew
+#undef FcCharSetDestroy
+#undef FcCharSetAddChar
+#undef FcCharSetDelChar
+#undef FcCharSetCopy
+#undef FcCharSetEqual
+#undef FcCharSetIntersect
+#undef FcCharSetUnion
+#undef FcCharSetSubtract
+#undef FcCharSetMerge
+#undef FcCharSetHasChar
+#undef FcCharSetCount
+#undef FcCharSetIntersectCount
+#undef FcCharSetSubtractCount
+#undef FcCharSetIsSubset
+#undef FcCharSetCoverage
#undef FcValuePrint
#undef FcPatternPrint
#undef FcFontSetPrint
@@ -250,6 +306,7 @@
#undef FcDirCacheLoadFile
#undef FcDirCacheUnload
#undef FcFreeTypeQuery
+#undef FcFreeTypeQueryAll
#undef FcFontSetCreate
#undef FcFontSetDestroy
#undef FcFontSetAdd
@@ -320,6 +377,7 @@
#undef FcValueEqual
#undef FcValueSave
#undef FcPatternDestroy
+#undef FcPatternObjectCount
#undef FcPatternEqual
#undef FcPatternEqualSubset
#undef FcPatternHash
@@ -353,8 +411,18 @@
#undef FcRangeDestroy
#undef FcRangeCopy
#undef FcRangeGetDouble
+#undef FcPatternIterStart
+#undef FcPatternIterNext
+#undef FcPatternIterEqual
+#undef FcPatternFindIter
+#undef FcPatternIterIsValid
+#undef FcPatternIterGetObject
+#undef FcPatternIterValueCount
+#undef FcPatternIterGetValue
#undef FcWeightFromOpenType
+#undef FcWeightFromOpenTypeDouble
#undef FcWeightToOpenType
+#undef FcWeightToOpenTypeDouble
#undef FcStrCopy
#undef FcStrCopyFilename
#undef FcStrPlus
@@ -400,6 +468,8 @@ extern "C" {
#define FcDirCacheValid FcDirCacheValid_dylibloader_wrapper_fontconfig
#define FcDirCacheClean FcDirCacheClean_dylibloader_wrapper_fontconfig
#define FcCacheCreateTagFile FcCacheCreateTagFile_dylibloader_wrapper_fontconfig
+#define FcDirCacheCreateUUID FcDirCacheCreateUUID_dylibloader_wrapper_fontconfig
+#define FcDirCacheDeleteUUID FcDirCacheDeleteUUID_dylibloader_wrapper_fontconfig
#define FcConfigHome FcConfigHome_dylibloader_wrapper_fontconfig
#define FcConfigEnableHome FcConfigEnableHome_dylibloader_wrapper_fontconfig
#define FcConfigFilename FcConfigFilename_dylibloader_wrapper_fontconfig
@@ -426,6 +496,26 @@ extern "C" {
#define FcConfigSubstitute FcConfigSubstitute_dylibloader_wrapper_fontconfig
#define FcConfigGetSysRoot FcConfigGetSysRoot_dylibloader_wrapper_fontconfig
#define FcConfigSetSysRoot FcConfigSetSysRoot_dylibloader_wrapper_fontconfig
+#define FcConfigFileInfoIterInit FcConfigFileInfoIterInit_dylibloader_wrapper_fontconfig
+#define FcConfigFileInfoIterNext FcConfigFileInfoIterNext_dylibloader_wrapper_fontconfig
+#define FcConfigFileInfoIterGet FcConfigFileInfoIterGet_dylibloader_wrapper_fontconfig
+#define FcCharSetCreate FcCharSetCreate_dylibloader_wrapper_fontconfig
+#define FcCharSetNew FcCharSetNew_dylibloader_wrapper_fontconfig
+#define FcCharSetDestroy FcCharSetDestroy_dylibloader_wrapper_fontconfig
+#define FcCharSetAddChar FcCharSetAddChar_dylibloader_wrapper_fontconfig
+#define FcCharSetDelChar FcCharSetDelChar_dylibloader_wrapper_fontconfig
+#define FcCharSetCopy FcCharSetCopy_dylibloader_wrapper_fontconfig
+#define FcCharSetEqual FcCharSetEqual_dylibloader_wrapper_fontconfig
+#define FcCharSetIntersect FcCharSetIntersect_dylibloader_wrapper_fontconfig
+#define FcCharSetUnion FcCharSetUnion_dylibloader_wrapper_fontconfig
+#define FcCharSetSubtract FcCharSetSubtract_dylibloader_wrapper_fontconfig
+#define FcCharSetMerge FcCharSetMerge_dylibloader_wrapper_fontconfig
+#define FcCharSetHasChar FcCharSetHasChar_dylibloader_wrapper_fontconfig
+#define FcCharSetCount FcCharSetCount_dylibloader_wrapper_fontconfig
+#define FcCharSetIntersectCount FcCharSetIntersectCount_dylibloader_wrapper_fontconfig
+#define FcCharSetSubtractCount FcCharSetSubtractCount_dylibloader_wrapper_fontconfig
+#define FcCharSetIsSubset FcCharSetIsSubset_dylibloader_wrapper_fontconfig
+#define FcCharSetCoverage FcCharSetCoverage_dylibloader_wrapper_fontconfig
#define FcValuePrint FcValuePrint_dylibloader_wrapper_fontconfig
#define FcPatternPrint FcPatternPrint_dylibloader_wrapper_fontconfig
#define FcFontSetPrint FcFontSetPrint_dylibloader_wrapper_fontconfig
@@ -441,6 +531,7 @@ extern "C" {
#define FcDirCacheLoadFile FcDirCacheLoadFile_dylibloader_wrapper_fontconfig
#define FcDirCacheUnload FcDirCacheUnload_dylibloader_wrapper_fontconfig
#define FcFreeTypeQuery FcFreeTypeQuery_dylibloader_wrapper_fontconfig
+#define FcFreeTypeQueryAll FcFreeTypeQueryAll_dylibloader_wrapper_fontconfig
#define FcFontSetCreate FcFontSetCreate_dylibloader_wrapper_fontconfig
#define FcFontSetDestroy FcFontSetDestroy_dylibloader_wrapper_fontconfig
#define FcFontSetAdd FcFontSetAdd_dylibloader_wrapper_fontconfig
@@ -511,6 +602,7 @@ extern "C" {
#define FcValueEqual FcValueEqual_dylibloader_wrapper_fontconfig
#define FcValueSave FcValueSave_dylibloader_wrapper_fontconfig
#define FcPatternDestroy FcPatternDestroy_dylibloader_wrapper_fontconfig
+#define FcPatternObjectCount FcPatternObjectCount_dylibloader_wrapper_fontconfig
#define FcPatternEqual FcPatternEqual_dylibloader_wrapper_fontconfig
#define FcPatternEqualSubset FcPatternEqualSubset_dylibloader_wrapper_fontconfig
#define FcPatternHash FcPatternHash_dylibloader_wrapper_fontconfig
@@ -544,8 +636,18 @@ extern "C" {
#define FcRangeDestroy FcRangeDestroy_dylibloader_wrapper_fontconfig
#define FcRangeCopy FcRangeCopy_dylibloader_wrapper_fontconfig
#define FcRangeGetDouble FcRangeGetDouble_dylibloader_wrapper_fontconfig
+#define FcPatternIterStart FcPatternIterStart_dylibloader_wrapper_fontconfig
+#define FcPatternIterNext FcPatternIterNext_dylibloader_wrapper_fontconfig
+#define FcPatternIterEqual FcPatternIterEqual_dylibloader_wrapper_fontconfig
+#define FcPatternFindIter FcPatternFindIter_dylibloader_wrapper_fontconfig
+#define FcPatternIterIsValid FcPatternIterIsValid_dylibloader_wrapper_fontconfig
+#define FcPatternIterGetObject FcPatternIterGetObject_dylibloader_wrapper_fontconfig
+#define FcPatternIterValueCount FcPatternIterValueCount_dylibloader_wrapper_fontconfig
+#define FcPatternIterGetValue FcPatternIterGetValue_dylibloader_wrapper_fontconfig
#define FcWeightFromOpenType FcWeightFromOpenType_dylibloader_wrapper_fontconfig
+#define FcWeightFromOpenTypeDouble FcWeightFromOpenTypeDouble_dylibloader_wrapper_fontconfig
#define FcWeightToOpenType FcWeightToOpenType_dylibloader_wrapper_fontconfig
+#define FcWeightToOpenTypeDouble FcWeightToOpenTypeDouble_dylibloader_wrapper_fontconfig
#define FcStrCopy FcStrCopy_dylibloader_wrapper_fontconfig
#define FcStrCopyFilename FcStrCopyFilename_dylibloader_wrapper_fontconfig
#define FcStrPlus FcStrPlus_dylibloader_wrapper_fontconfig
@@ -588,6 +690,8 @@ extern FcBool (*FcDirCacheUnlink_dylibloader_wrapper_fontconfig)(const FcChar8*,
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 FcBool (*FcDirCacheCreateUUID_dylibloader_wrapper_fontconfig)( FcChar8*, FcBool, FcConfig*);
+extern FcBool (*FcDirCacheDeleteUUID_dylibloader_wrapper_fontconfig)(const FcChar8*, FcConfig*);
extern FcChar8* (*FcConfigHome_dylibloader_wrapper_fontconfig)( void);
extern FcBool (*FcConfigEnableHome_dylibloader_wrapper_fontconfig)( FcBool);
extern FcChar8* (*FcConfigFilename_dylibloader_wrapper_fontconfig)(const FcChar8*);
@@ -614,6 +718,26 @@ extern FcBool (*FcConfigSubstituteWithPat_dylibloader_wrapper_fontconfig)( FcCon
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 (*FcConfigFileInfoIterInit_dylibloader_wrapper_fontconfig)( FcConfig*, FcConfigFileInfoIter*);
+extern FcBool (*FcConfigFileInfoIterNext_dylibloader_wrapper_fontconfig)( FcConfig*, FcConfigFileInfoIter*);
+extern FcBool (*FcConfigFileInfoIterGet_dylibloader_wrapper_fontconfig)( FcConfig*, FcConfigFileInfoIter*, FcChar8**, FcChar8**, FcBool*);
+extern FcCharSet* (*FcCharSetCreate_dylibloader_wrapper_fontconfig)( void);
+extern FcCharSet* (*FcCharSetNew_dylibloader_wrapper_fontconfig)( void);
+extern void (*FcCharSetDestroy_dylibloader_wrapper_fontconfig)( FcCharSet*);
+extern FcBool (*FcCharSetAddChar_dylibloader_wrapper_fontconfig)( FcCharSet*, FcChar32);
+extern FcBool (*FcCharSetDelChar_dylibloader_wrapper_fontconfig)( FcCharSet*, FcChar32);
+extern FcCharSet* (*FcCharSetCopy_dylibloader_wrapper_fontconfig)( FcCharSet*);
+extern FcBool (*FcCharSetEqual_dylibloader_wrapper_fontconfig)(const FcCharSet*,const FcCharSet*);
+extern FcCharSet* (*FcCharSetIntersect_dylibloader_wrapper_fontconfig)(const FcCharSet*,const FcCharSet*);
+extern FcCharSet* (*FcCharSetUnion_dylibloader_wrapper_fontconfig)(const FcCharSet*,const FcCharSet*);
+extern FcCharSet* (*FcCharSetSubtract_dylibloader_wrapper_fontconfig)(const FcCharSet*,const FcCharSet*);
+extern FcBool (*FcCharSetMerge_dylibloader_wrapper_fontconfig)( FcCharSet*,const FcCharSet*, FcBool*);
+extern FcBool (*FcCharSetHasChar_dylibloader_wrapper_fontconfig)(const FcCharSet*, FcChar32);
+extern FcChar32 (*FcCharSetCount_dylibloader_wrapper_fontconfig)(const FcCharSet*);
+extern FcChar32 (*FcCharSetIntersectCount_dylibloader_wrapper_fontconfig)(const FcCharSet*,const FcCharSet*);
+extern FcChar32 (*FcCharSetSubtractCount_dylibloader_wrapper_fontconfig)(const FcCharSet*,const FcCharSet*);
+extern FcBool (*FcCharSetIsSubset_dylibloader_wrapper_fontconfig)(const FcCharSet*,const FcCharSet*);
+extern FcChar32 (*FcCharSetCoverage_dylibloader_wrapper_fontconfig)(const FcCharSet*, FcChar32, FcChar32*);
extern void (*FcValuePrint_dylibloader_wrapper_fontconfig)(const FcValue);
extern void (*FcPatternPrint_dylibloader_wrapper_fontconfig)(const FcPattern*);
extern void (*FcFontSetPrint_dylibloader_wrapper_fontconfig)(const FcFontSet*);
@@ -628,7 +752,8 @@ extern FcCache* (*FcDirCacheRescan_dylibloader_wrapper_fontconfig)(const FcChar8
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 FcPattern* (*FcFreeTypeQuery_dylibloader_wrapper_fontconfig)(const FcChar8*, unsigned int, FcBlanks*, int*);
+extern unsigned int (*FcFreeTypeQueryAll_dylibloader_wrapper_fontconfig)(const FcChar8*, unsigned int, FcBlanks*, int*, FcFontSet*);
extern FcFontSet* (*FcFontSetCreate_dylibloader_wrapper_fontconfig)( void);
extern void (*FcFontSetDestroy_dylibloader_wrapper_fontconfig)( FcFontSet*);
extern FcBool (*FcFontSetAdd_dylibloader_wrapper_fontconfig)( FcFontSet*, FcPattern*);
@@ -699,6 +824,7 @@ 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 int (*FcPatternObjectCount_dylibloader_wrapper_fontconfig)(const 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*);
@@ -732,8 +858,18 @@ extern FcRange* (*FcRangeCreateInteger_dylibloader_wrapper_fontconfig)( 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 void (*FcPatternIterStart_dylibloader_wrapper_fontconfig)(const FcPattern*, FcPatternIter*);
+extern FcBool (*FcPatternIterNext_dylibloader_wrapper_fontconfig)(const FcPattern*, FcPatternIter*);
+extern FcBool (*FcPatternIterEqual_dylibloader_wrapper_fontconfig)(const FcPattern*, FcPatternIter*,const FcPattern*, FcPatternIter*);
+extern FcBool (*FcPatternFindIter_dylibloader_wrapper_fontconfig)(const FcPattern*, FcPatternIter*,const char*);
+extern FcBool (*FcPatternIterIsValid_dylibloader_wrapper_fontconfig)(const FcPattern*, FcPatternIter*);
+extern const char* (*FcPatternIterGetObject_dylibloader_wrapper_fontconfig)(const FcPattern*, FcPatternIter*);
+extern int (*FcPatternIterValueCount_dylibloader_wrapper_fontconfig)(const FcPattern*, FcPatternIter*);
+extern FcResult (*FcPatternIterGetValue_dylibloader_wrapper_fontconfig)(const FcPattern*, FcPatternIter*, int, FcValue*, FcValueBinding*);
extern int (*FcWeightFromOpenType_dylibloader_wrapper_fontconfig)( int);
+extern double (*FcWeightFromOpenTypeDouble_dylibloader_wrapper_fontconfig)( double);
extern int (*FcWeightToOpenType_dylibloader_wrapper_fontconfig)( int);
+extern double (*FcWeightToOpenTypeDouble_dylibloader_wrapper_fontconfig)( double);
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*);
diff --git a/platform/linuxbsd/joypad_linux.cpp b/platform/linuxbsd/joypad_linux.cpp
index bc018e366b..4eaf6965c9 100644
--- a/platform/linuxbsd/joypad_linux.cpp
+++ b/platform/linuxbsd/joypad_linux.cpp
@@ -218,8 +218,8 @@ void JoypadLinux::monitor_joypads() {
}
}
closedir(input_directory);
+ usleep(1000000); // 1s
}
- usleep(1000000); // 1s
}
void JoypadLinux::close_joypads() {
diff --git a/platform/linuxbsd/os_linuxbsd.cpp b/platform/linuxbsd/os_linuxbsd.cpp
index 22c5f063c3..d5a75edeea 100644
--- a/platform/linuxbsd/os_linuxbsd.cpp
+++ b/platform/linuxbsd/os_linuxbsd.cpp
@@ -56,10 +56,6 @@
#include <sys/utsname.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" };
@@ -128,6 +124,8 @@ void OS_LinuxBSD::initialize() {
crash_handler.initialize();
OS_Unix::initialize_core();
+
+ system_dir_desktop_cache = get_system_dir(SYSTEM_DIR_DESKTOP);
}
void OS_LinuxBSD::initialize_joypads() {
@@ -583,15 +581,9 @@ Vector<String> OS_LinuxBSD::get_system_fonts() const {
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();
@@ -614,8 +606,6 @@ Vector<String> OS_LinuxBSD::get_system_fonts() const {
}
FcPatternDestroy(pattern);
}
- FcObjectSetDestroy(object_set);
- FcConfigDestroy(config);
for (const String &E : font_names) {
ret.push_back(E);
@@ -626,25 +616,122 @@ Vector<String> OS_LinuxBSD::get_system_fonts() const {
#endif
}
-String OS_LinuxBSD::get_system_font_path(const String &p_font_name, bool p_bold, bool p_italic) const {
+#ifdef FONTCONFIG_ENABLED
+int OS_LinuxBSD::_weight_to_fc(int p_weight) const {
+ if (p_weight < 150) {
+ return FC_WEIGHT_THIN;
+ } else if (p_weight < 250) {
+ return FC_WEIGHT_EXTRALIGHT;
+ } else if (p_weight < 325) {
+ return FC_WEIGHT_LIGHT;
+ } else if (p_weight < 375) {
+ return FC_WEIGHT_DEMILIGHT;
+ } else if (p_weight < 390) {
+ return FC_WEIGHT_BOOK;
+ } else if (p_weight < 450) {
+ return FC_WEIGHT_REGULAR;
+ } else if (p_weight < 550) {
+ return FC_WEIGHT_MEDIUM;
+ } else if (p_weight < 650) {
+ return FC_WEIGHT_DEMIBOLD;
+ } else if (p_weight < 750) {
+ return FC_WEIGHT_BOLD;
+ } else if (p_weight < 850) {
+ return FC_WEIGHT_EXTRABOLD;
+ } else if (p_weight < 925) {
+ return FC_WEIGHT_BLACK;
+ } else {
+ return FC_WEIGHT_EXTRABLACK;
+ }
+}
+
+int OS_LinuxBSD::_stretch_to_fc(int p_stretch) const {
+ if (p_stretch < 56) {
+ return FC_WIDTH_ULTRACONDENSED;
+ } else if (p_stretch < 69) {
+ return FC_WIDTH_EXTRACONDENSED;
+ } else if (p_stretch < 81) {
+ return FC_WIDTH_CONDENSED;
+ } else if (p_stretch < 93) {
+ return FC_WIDTH_SEMICONDENSED;
+ } else if (p_stretch < 106) {
+ return FC_WIDTH_NORMAL;
+ } else if (p_stretch < 137) {
+ return FC_WIDTH_SEMIEXPANDED;
+ } else if (p_stretch < 144) {
+ return FC_WIDTH_EXPANDED;
+ } else if (p_stretch < 162) {
+ return FC_WIDTH_EXTRAEXPANDED;
+ } else {
+ return FC_WIDTH_ULTRAEXPANDED;
+ }
+}
+#endif // FONTCONFIG_ENABLED
+
+Vector<String> OS_LinuxBSD::get_system_font_path_for_text(const String &p_font_name, const String &p_text, const String &p_locale, const String &p_script, int p_weight, int p_stretch, 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.");
+ ERR_FAIL_V_MSG(Vector<String>(), "Unable to load fontconfig, system font support is disabled.");
}
- String ret;
+ Vector<String> ret;
+ FcPattern *pattern = FcPatternCreate();
+ if (pattern) {
+ FcPatternAddString(pattern, FC_FAMILY, reinterpret_cast<const FcChar8 *>(p_font_name.utf8().get_data()));
+ FcPatternAddInteger(pattern, FC_WEIGHT, _weight_to_fc(p_weight));
+ FcPatternAddInteger(pattern, FC_WIDTH, _stretch_to_fc(p_stretch));
+ FcPatternAddInteger(pattern, FC_SLANT, p_italic ? FC_SLANT_ITALIC : FC_SLANT_ROMAN);
+
+ FcCharSet *char_set = FcCharSetCreate();
+ for (int i = 0; i < p_text.size(); i++) {
+ FcCharSetAddChar(char_set, p_text[i]);
+ }
+ FcPatternAddCharSet(pattern, FC_CHARSET, char_set);
- FcConfig *config = FcInitLoadConfigAndFonts();
- ERR_FAIL_COND_V(!config, ret);
+ FcLangSet *lang_set = FcLangSetCreate();
+ FcLangSetAdd(lang_set, reinterpret_cast<const FcChar8 *>(p_locale.utf8().get_data()));
+ FcPatternAddLangSet(pattern, FC_LANG, lang_set);
- FcObjectSet *object_set = FcObjectSetBuild(FC_FAMILY, FC_FILE, nullptr);
- ERR_FAIL_COND_V(!object_set, ret);
+ 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.push_back(String::utf8(file_name));
+ }
+ }
+ FcPatternDestroy(match);
+ }
+ FcPatternDestroy(pattern);
+ FcCharSetDestroy(char_set);
+ FcLangSetDestroy(lang_set);
+ }
+
+ 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, int p_weight, int p_stretch, 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;
FcPattern *pattern = FcPatternCreate();
if (pattern) {
+ bool allow_substitutes = (p_font_name.to_lower() == "sans-serif") || (p_font_name.to_lower() == "serif") || (p_font_name.to_lower() == "monospace") || (p_font_name.to_lower() == "cursive") || (p_font_name.to_lower() == "fantasy");
+
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_WEIGHT, _weight_to_fc(p_weight));
+ FcPatternAddInteger(pattern, FC_WIDTH, _stretch_to_fc(p_stretch));
FcPatternAddInteger(pattern, FC_SLANT, p_italic ? FC_SLANT_ITALIC : FC_SLANT_ROMAN);
FcConfigSubstitute(0, pattern, FcMatchPattern);
@@ -653,6 +740,17 @@ String OS_LinuxBSD::get_system_font_path(const String &p_font_name, bool p_bold,
FcResult result;
FcPattern *match = FcFontMatch(0, pattern, &result);
if (match) {
+ if (!allow_substitutes) {
+ char *family_name = nullptr;
+ if (FcPatternGetString(match, FC_FAMILY, 0, reinterpret_cast<FcChar8 **>(&family_name)) == FcResultMatch) {
+ if (family_name && String::utf8(family_name).to_lower() != p_font_name.to_lower()) {
+ FcPatternDestroy(match);
+ FcPatternDestroy(pattern);
+
+ return String();
+ }
+ }
+ }
char *file_name = nullptr;
if (FcPatternGetString(match, FC_FILE, 0, reinterpret_cast<FcChar8 **>(&file_name)) == FcResultMatch) {
if (file_name) {
@@ -664,8 +762,6 @@ String OS_LinuxBSD::get_system_font_path(const String &p_font_name, bool p_bold,
}
FcPatternDestroy(pattern);
}
- FcObjectSetDestroy(object_set);
- FcConfigDestroy(config);
return ret;
#else
@@ -719,6 +815,10 @@ String OS_LinuxBSD::get_cache_path() const {
}
String OS_LinuxBSD::get_system_dir(SystemDir p_dir, bool p_shared_storage) const {
+ if (p_dir == SYSTEM_DIR_DESKTOP && !system_dir_desktop_cache.is_empty()) {
+ return system_dir_desktop_cache;
+ }
+
String xdgparam;
switch (p_dir) {
@@ -727,31 +827,24 @@ String OS_LinuxBSD::get_system_dir(SystemDir p_dir, bool p_shared_storage) const
} break;
case SYSTEM_DIR_DCIM: {
xdgparam = "PICTURES";
-
} break;
case SYSTEM_DIR_DOCUMENTS: {
xdgparam = "DOCUMENTS";
-
} break;
case SYSTEM_DIR_DOWNLOADS: {
xdgparam = "DOWNLOAD";
-
} break;
case SYSTEM_DIR_MOVIES: {
xdgparam = "VIDEOS";
-
} break;
case SYSTEM_DIR_MUSIC: {
xdgparam = "MUSIC";
-
} break;
case SYSTEM_DIR_PICTURES: {
xdgparam = "PICTURES";
-
} break;
case SYSTEM_DIR_RINGTONES: {
xdgparam = "MUSIC";
-
} break;
}
@@ -994,5 +1087,26 @@ OS_LinuxBSD::OS_LinuxBSD() {
int dylibloader_verbose = 0;
#endif
font_config_initialized = (initialize_fontconfig(dylibloader_verbose) == 0);
+ if (font_config_initialized) {
+ config = FcInitLoadConfigAndFonts();
+ if (!config) {
+ font_config_initialized = false;
+ }
+ object_set = FcObjectSetBuild(FC_FAMILY, FC_FILE, nullptr);
+ if (!object_set) {
+ font_config_initialized = false;
+ }
+ }
+#endif // FONTCONFIG_ENABLED
+}
+
+OS_LinuxBSD::~OS_LinuxBSD() {
+#ifdef FONTCONFIG_ENABLED
+ if (object_set) {
+ FcObjectSetDestroy(object_set);
+ }
+ if (config) {
+ FcConfigDestroy(config);
+ }
#endif // FONTCONFIG_ENABLED
}
diff --git a/platform/linuxbsd/os_linuxbsd.h b/platform/linuxbsd/os_linuxbsd.h
index aea04c1363..bf469af568 100644
--- a/platform/linuxbsd/os_linuxbsd.h
+++ b/platform/linuxbsd/os_linuxbsd.h
@@ -40,11 +40,20 @@
#include "joypad_linux.h"
#include "servers/audio_server.h"
+#ifdef FONTCONFIG_ENABLED
+#include "fontconfig-so_wrap.h"
+#endif
+
class OS_LinuxBSD : public OS_Unix {
virtual void delete_main_loop() override;
#ifdef FONTCONFIG_ENABLED
bool font_config_initialized = false;
+ FcConfig *config = nullptr;
+ FcObjectSet *object_set = nullptr;
+
+ int _weight_to_fc(int p_weight) const;
+ int _stretch_to_fc(int p_stretch) const;
#endif
#ifdef JOYDEV_ENABLED
@@ -72,6 +81,8 @@ class OS_LinuxBSD : public OS_Unix {
Vector<String> lspci_device_filter(Vector<String> vendor_device_id_mapping, String class_suffix, String check_column, String whitelist) const;
Vector<String> lspci_get_device_value(Vector<String> vendor_device_id_mapping, String check_column, String blacklist) const;
+ String system_dir_desktop_cache;
+
protected:
virtual void initialize() override;
virtual void finalize() override;
@@ -92,7 +103,8 @@ 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_system_font_path(const String &p_font_name, int p_weight = 400, int p_stretch = 100, bool p_italic = false) const override;
+ virtual Vector<String> get_system_font_path_for_text(const String &p_font_name, const String &p_text, const String &p_locale = String(), const String &p_script = String(), int p_weight = 400, int p_stretch = 100, bool p_italic = false) const override;
virtual String get_config_path() const override;
virtual String get_data_path() const override;
@@ -117,6 +129,7 @@ public:
virtual Error move_to_trash(const String &p_path) override;
OS_LinuxBSD();
+ ~OS_LinuxBSD();
};
#endif // OS_LINUXBSD_H
diff --git a/platform/linuxbsd/platform_config.h b/platform/linuxbsd/platform_config.h
index 3c05c67444..79e15e2512 100644
--- a/platform/linuxbsd/platform_config.h
+++ b/platform/linuxbsd/platform_config.h
@@ -44,4 +44,4 @@
#endif
#endif
-#define OPENGL_INCLUDE_H "thirdparty/glad/glad/glad.h"
+#define OPENGL_INCLUDE_H "thirdparty/glad/glad/gl.h"
diff --git a/platform/linuxbsd/tts_linux.cpp b/platform/linuxbsd/tts_linux.cpp
index aea1183d3d..8fa708aad6 100644
--- a/platform/linuxbsd/tts_linux.cpp
+++ b/platform/linuxbsd/tts_linux.cpp
@@ -117,13 +117,12 @@ void TTS_Linux::speech_event_callback(size_t p_msg_id, size_t p_client_id, SPDNo
free_spd_voices(voices);
}
PackedInt32Array breaks = TS->string_get_word_breaks(message.text, language);
- int prev = 0;
- for (int i = 0; i < breaks.size(); i++) {
- text += message.text.substr(prev, breaks[i] - prev);
- text += "<mark name=\"" + String::num_int64(breaks[i], 10) + "\"/>";
- prev = breaks[i];
+ for (int i = 0; i < breaks.size(); i += 2) {
+ const int start = breaks[i];
+ const int end = breaks[i + 1];
+ text += message.text.substr(start, end - start + 1);
+ text += "<mark name=\"" + String::num_int64(end, 10) + "\"/>";
}
- text += message.text.substr(prev, -1);
spd_set_synthesis_voice(tts->synth, message.voice.utf8().get_data());
spd_set_volume(tts->synth, message.volume * 2 - 100);
diff --git a/platform/linuxbsd/x11/SCsub b/platform/linuxbsd/x11/SCsub
index 974ad98fb9..8b2e2aabe4 100644
--- a/platform/linuxbsd/x11/SCsub
+++ b/platform/linuxbsd/x11/SCsub
@@ -5,13 +5,21 @@ Import("env")
source_files = [
"display_server_x11.cpp",
"key_mapping_x11.cpp",
+ "dynwrappers/xlib-so_wrap.c",
+ "dynwrappers/xcursor-so_wrap.c",
+ "dynwrappers/xinerama-so_wrap.c",
+ "dynwrappers/xinput2-so_wrap.c",
+ "dynwrappers/xrandr-so_wrap.c",
+ "dynwrappers/xrender-so_wrap.c",
+ "dynwrappers/xext-so_wrap.c",
]
if env["vulkan"]:
source_files.append("vulkan_context_x11.cpp")
if env["opengl3"]:
- source_files.append(["gl_manager_x11.cpp", "detect_prime_x11.cpp"])
+ env.Append(CPPDEFINES=["GLAD_GLX_NO_X11"])
+ source_files.append(["gl_manager_x11.cpp", "detect_prime_x11.cpp", "#thirdparty/glad/glx.c"])
objects = []
diff --git a/platform/linuxbsd/x11/detect_prime_x11.cpp b/platform/linuxbsd/x11/detect_prime_x11.cpp
index 78a10fa2b0..0f756d10e2 100644
--- a/platform/linuxbsd/x11/detect_prime_x11.cpp
+++ b/platform/linuxbsd/x11/detect_prime_x11.cpp
@@ -38,10 +38,10 @@
#include <stdlib.h>
-#include <GL/gl.h>
-#include <GL/glx.h>
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
+#include "thirdparty/glad/glad/gl.h"
+#include "thirdparty/glad/glad/glx.h"
+
+#include "dynwrappers/xlib-so_wrap.h"
#include <cstring>
@@ -77,8 +77,6 @@ void create_context() {
Window x11_window;
GLXContext glx_context;
- GLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribsARB = (GLXCREATECONTEXTATTRIBSARBPROC)glXGetProcAddress((const GLubyte *)"glXCreateContextAttribsARB");
-
static int visual_attribs[] = {
GLX_RENDER_TYPE, GLX_RGBA_BIT,
GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
@@ -90,6 +88,10 @@ void create_context() {
None
};
+ if (gladLoaderLoadGLX(x11_display, XScreenNumberOfScreen(XDefaultScreenOfDisplay(x11_display))) == 0) {
+ print_verbose("Unable to load GLX, GPU detection skipped.");
+ quick_exit(1);
+ }
int fbcount;
GLXFBConfig fbconfig = nullptr;
XVisualInfo *vi = nullptr;
@@ -101,7 +103,7 @@ void create_context() {
GLXFBConfig *fbc = glXChooseFBConfig(x11_display, DefaultScreen(x11_display), visual_attribs, &fbcount);
if (!fbc) {
- exit(1);
+ quick_exit(1);
}
vi = glXGetVisualFromFBConfig(x11_display, fbc[0]);
@@ -122,7 +124,7 @@ void create_context() {
x11_window = XCreateWindow(x11_display, RootWindow(x11_display, vi->screen), 0, 0, 10, 10, 0, vi->depth, InputOutput, vi->visual, valuemask, &swa);
if (!x11_window) {
- exit(1);
+ quick_exit(1);
}
glXMakeCurrent(x11_display, x11_window, glx_context);
@@ -189,8 +191,15 @@ int detect_prime() {
if (i) {
setenv("DRI_PRIME", "1", 1);
}
+
create_context();
+ PFNGLGETSTRINGPROC glGetString = (PFNGLGETSTRINGPROC)glXGetProcAddressARB((GLubyte *)"glGetString");
+ if (!glGetString) {
+ print_verbose("Unable to get glGetString, GPU detection skipped.");
+ quick_exit(1);
+ }
+
const char *vendor = (const char *)glGetString(GL_VENDOR);
const char *renderer = (const char *)glGetString(GL_RENDERER);
diff --git a/platform/linuxbsd/x11/display_server_x11.cpp b/platform/linuxbsd/x11/display_server_x11.cpp
index 2e60ad8f45..57f125a754 100644
--- a/platform/linuxbsd/x11/display_server_x11.cpp
+++ b/platform/linuxbsd/x11/display_server_x11.cpp
@@ -58,11 +58,6 @@
#include <sys/types.h>
#include <unistd.h>
-#include <X11/Xatom.h>
-#include <X11/Xutil.h>
-#include <X11/extensions/Xinerama.h>
-#include <X11/extensions/shape.h>
-
// ICCCM
#define WM_NormalState 1L // window normal state
#define WM_IconicState 3L // window minimized
@@ -1319,7 +1314,10 @@ int64_t DisplayServerX11::window_get_native_handle(HandleType p_handle_type, Win
}
#ifdef GLES3_ENABLED
case OPENGL_CONTEXT: {
- return (int64_t)gl_manager->get_glx_context(p_window);
+ if (gl_manager) {
+ return (int64_t)gl_manager->get_glx_context(p_window);
+ }
+ return 0;
}
#endif
default: {
@@ -1399,8 +1397,8 @@ void DisplayServerX11::window_set_mouse_passthrough(const Vector<Vector2> &p_reg
XRectangle rect;
rect.x = 0;
rect.y = 0;
- rect.width = window_get_real_size(p_window).x;
- rect.height = window_get_real_size(p_window).y;
+ rect.width = window_get_size_with_decorations(p_window).x;
+ rect.height = window_get_size_with_decorations(p_window).y;
XUnionRectWithRegion(&rect, region, region);
} else {
XPoint *points = (XPoint *)memalloc(sizeof(XPoint) * p_region.size());
@@ -1584,7 +1582,7 @@ void DisplayServerX11::_update_size_hints(WindowID p_window) {
xsh->width = wd.size.width;
xsh->height = wd.size.height;
- if (window_mode == WINDOW_MODE_FULLSCREEN) {
+ if (window_mode == WINDOW_MODE_FULLSCREEN || window_mode == WINDOW_MODE_EXCLUSIVE_FULLSCREEN) {
// Do not set any other hints to prevent the window manager from ignoring the fullscreen flags
} else if (window_get_flag(WINDOW_FLAG_RESIZE_DISABLED, p_window)) {
// If resizing is disabled, use the forced size
@@ -1620,6 +1618,40 @@ Point2i DisplayServerX11::window_get_position(WindowID p_window) const {
return wd.position;
}
+Point2i DisplayServerX11::window_get_position_with_decorations(WindowID p_window) const {
+ _THREAD_SAFE_METHOD_
+
+ ERR_FAIL_COND_V(!windows.has(p_window), Size2i());
+ const WindowData &wd = windows[p_window];
+
+ if (wd.fullscreen) {
+ return wd.position;
+ }
+
+ XWindowAttributes xwa;
+ XSync(x11_display, False);
+ XGetWindowAttributes(x11_display, wd.x11_window, &xwa);
+ int x = wd.position.x;
+ int y = wd.position.y;
+ Atom prop = XInternAtom(x11_display, "_NET_FRAME_EXTENTS", True);
+ if (prop != None) {
+ Atom type;
+ int format;
+ unsigned long len;
+ unsigned long remaining;
+ unsigned char *data = nullptr;
+ if (XGetWindowProperty(x11_display, wd.x11_window, prop, 0, 4, False, AnyPropertyType, &type, &format, &len, &remaining, &data) == Success) {
+ if (format == 32 && len == 4 && data) {
+ long *extents = (long *)data;
+ x -= extents[0]; // left
+ y -= extents[2]; // top
+ }
+ XFree(data);
+ }
+ }
+ return Size2i(x, y);
+}
+
void DisplayServerX11::window_set_position(const Point2i &p_position, WindowID p_window) {
_THREAD_SAFE_METHOD_
@@ -1764,12 +1796,16 @@ Size2i DisplayServerX11::window_get_size(WindowID p_window) const {
return wd.size;
}
-Size2i DisplayServerX11::window_get_real_size(WindowID p_window) const {
+Size2i DisplayServerX11::window_get_size_with_decorations(WindowID p_window) const {
_THREAD_SAFE_METHOD_
ERR_FAIL_COND_V(!windows.has(p_window), Size2i());
const WindowData &wd = windows[p_window];
+ if (wd.fullscreen) {
+ return wd.size;
+ }
+
XWindowAttributes xwa;
XSync(x11_display, False);
XGetWindowAttributes(x11_display, wd.x11_window, &xwa);
@@ -1951,7 +1987,7 @@ void DisplayServerX11::_validate_mode_on_map(WindowID p_window) {
// Check if we applied any window modes that didn't take effect while unmapped
const WindowData &wd = windows[p_window];
if (wd.fullscreen && !_window_fullscreen_check(p_window)) {
- _set_wm_fullscreen(p_window, true);
+ _set_wm_fullscreen(p_window, true, wd.exclusive_fullscreen);
} else if (wd.maximized && !_window_maximize_check(p_window, "_NET_WM_STATE")) {
_set_wm_maximized(p_window, true);
} else if (wd.minimized && !_window_minimize_check(p_window)) {
@@ -2026,7 +2062,7 @@ void DisplayServerX11::_set_wm_minimized(WindowID p_window, bool p_enabled) {
wd.minimized = p_enabled;
}
-void DisplayServerX11::_set_wm_fullscreen(WindowID p_window, bool p_enabled) {
+void DisplayServerX11::_set_wm_fullscreen(WindowID p_window, bool p_enabled, bool p_exclusive) {
ERR_FAIL_COND(!windows.has(p_window));
WindowData &wd = windows[p_window];
@@ -2065,7 +2101,14 @@ void DisplayServerX11::_set_wm_fullscreen(WindowID p_window, bool p_enabled) {
// set bypass compositor hint
Atom bypass_compositor = XInternAtom(x11_display, "_NET_WM_BYPASS_COMPOSITOR", False);
- unsigned long compositing_disable_on = p_enabled ? 1 : 0;
+ unsigned long compositing_disable_on = 0; // Use default.
+ if (p_enabled) {
+ if (p_exclusive) {
+ compositing_disable_on = 1; // Force composition OFF to reduce overhead.
+ } else {
+ compositing_disable_on = 2; // Force composition ON to allow popup windows.
+ }
+ }
if (bypass_compositor != None) {
XChangeProperty(x11_display, wd.x11_window, bypass_compositor, XA_CARDINAL, 32, PropModeReplace, (unsigned char *)&compositing_disable_on, 1);
}
@@ -2111,8 +2154,9 @@ void DisplayServerX11::window_set_mode(WindowMode p_mode, WindowID p_window) {
case WINDOW_MODE_FULLSCREEN: {
//Remove full-screen
wd.fullscreen = false;
+ wd.exclusive_fullscreen = false;
- _set_wm_fullscreen(p_window, false);
+ _set_wm_fullscreen(p_window, false, false);
//un-maximize required for always on top
bool on_top = window_get_flag(WINDOW_FLAG_ALWAYS_ON_TOP, p_window);
@@ -2145,7 +2189,13 @@ void DisplayServerX11::window_set_mode(WindowMode p_mode, WindowID p_window) {
}
wd.fullscreen = true;
- _set_wm_fullscreen(p_window, true);
+ if (p_mode == WINDOW_MODE_EXCLUSIVE_FULLSCREEN) {
+ wd.exclusive_fullscreen = true;
+ _set_wm_fullscreen(p_window, true, true);
+ } else {
+ wd.exclusive_fullscreen = false;
+ _set_wm_fullscreen(p_window, true, false);
+ }
} break;
case WINDOW_MODE_MAXIMIZED: {
_set_wm_maximized(p_window, true);
@@ -2160,7 +2210,11 @@ DisplayServer::WindowMode DisplayServerX11::window_get_mode(WindowID p_window) c
const WindowData &wd = windows[p_window];
if (wd.fullscreen) { //if fullscreen, it's not in another mode
- return WINDOW_MODE_FULLSCREEN;
+ if (wd.exclusive_fullscreen) {
+ return WINDOW_MODE_EXCLUSIVE_FULLSCREEN;
+ } else {
+ return WINDOW_MODE_FULLSCREEN;
+ }
}
// Test maximized.
@@ -3931,30 +3985,41 @@ void DisplayServerX11::process_events() {
} else {
DEBUG_LOG_X11("[%u] ButtonRelease window=%lu (%u), button_index=%u \n", frame, event.xbutton.window, window_id, mb->get_button_index());
- if (!wd.focused) {
+ WindowID window_id_other = INVALID_WINDOW_ID;
+ Window wd_other_x11_window;
+ if (wd.focused) {
+ // Handle cases where an unfocused popup is open that needs to receive button-up events.
+ WindowID popup_id = _get_focused_window_or_popup();
+ if (popup_id != INVALID_WINDOW_ID && popup_id != window_id) {
+ window_id_other = popup_id;
+ wd_other_x11_window = windows[popup_id].x11_window;
+ }
+ } else {
// Propagate the event to the focused window,
// because it's received only on the topmost window.
// Note: This is needed for drag & drop to work between windows,
// because the engine expects events to keep being processed
// on the same window dragging started.
for (const KeyValue<WindowID, WindowData> &E : windows) {
- const WindowData &wd_other = E.value;
- WindowID window_id_other = E.key;
- if (wd_other.focused) {
- if (window_id_other != window_id) {
- int x, y;
- Window child;
- XTranslateCoordinates(x11_display, wd.x11_window, wd_other.x11_window, event.xbutton.x, event.xbutton.y, &x, &y, &child);
-
- mb->set_window_id(window_id_other);
- mb->set_position(Vector2(x, y));
- mb->set_global_position(mb->get_position());
- Input::get_singleton()->parse_input_event(mb);
+ if (E.value.focused) {
+ if (E.key != window_id) {
+ window_id_other = E.key;
+ wd_other_x11_window = E.value.x11_window;
}
break;
}
}
}
+
+ if (window_id_other != INVALID_WINDOW_ID) {
+ int x, y;
+ Window child;
+ XTranslateCoordinates(x11_display, wd.x11_window, wd_other_x11_window, event.xbutton.x, event.xbutton.y, &x, &y, &child);
+
+ mb->set_window_id(window_id_other);
+ mb->set_position(Vector2(x, y));
+ mb->set_global_position(mb->get_position());
+ }
}
Input::get_singleton()->parse_input_event(mb);
@@ -4411,7 +4476,7 @@ void DisplayServerX11::window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mo
#if defined(GLES3_ENABLED)
if (gl_manager) {
- gl_manager->set_use_vsync(p_vsync_mode == DisplayServer::VSYNC_ENABLED);
+ gl_manager->set_use_vsync(p_vsync_mode != DisplayServer::VSYNC_DISABLED);
}
#endif
}
@@ -4672,6 +4737,7 @@ DisplayServerX11::WindowID DisplayServerX11::_create_window(WindowMode p_mode, V
if (gl_manager) {
Error err = gl_manager->window_create(id, wd.x11_window, x11_display, p_rect.size.width, p_rect.size.height);
ERR_FAIL_COND_V_MSG(err != OK, INVALID_WINDOW_ID, "Can't create an OpenGL window");
+ window_set_vsync_mode(p_vsync_mode, id);
}
#endif
@@ -4706,6 +4772,46 @@ DisplayServerX11::WindowID DisplayServerX11::_create_window(WindowMode p_mode, V
}
DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, Error &r_error) {
+#ifdef DEBUG_ENABLED
+ int dylibloader_verbose = 1;
+#else
+ int dylibloader_verbose = 0;
+#endif
+ if (initialize_xlib(dylibloader_verbose) != 0) {
+ r_error = ERR_UNAVAILABLE;
+ ERR_FAIL_MSG("Can't load Xlib dynamically.");
+ }
+
+ if (initialize_xcursor(dylibloader_verbose) != 0) {
+ r_error = ERR_UNAVAILABLE;
+ ERR_FAIL_MSG("Can't load XCursor dynamically.");
+ }
+
+ if (initialize_xext(dylibloader_verbose) != 0) {
+ r_error = ERR_UNAVAILABLE;
+ ERR_FAIL_MSG("Can't load Xext dynamically.");
+ }
+
+ if (initialize_xinerama(dylibloader_verbose) != 0) {
+ r_error = ERR_UNAVAILABLE;
+ ERR_FAIL_MSG("Can't load Xinerama dynamically.");
+ }
+
+ if (initialize_xrandr(dylibloader_verbose) != 0) {
+ r_error = ERR_UNAVAILABLE;
+ ERR_FAIL_MSG("Can't load Xrandr dynamically.");
+ }
+
+ if (initialize_xrender(dylibloader_verbose) != 0) {
+ r_error = ERR_UNAVAILABLE;
+ ERR_FAIL_MSG("Can't load Xrender dynamically.");
+ }
+
+ if (initialize_xinput2(dylibloader_verbose) != 0) {
+ r_error = ERR_UNAVAILABLE;
+ ERR_FAIL_MSG("Can't load Xinput2 dynamically.");
+ }
+
Input::get_singleton()->set_event_dispatch_function(_dispatch_input_events);
r_error = OK;
@@ -4906,7 +5012,7 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode
gl_manager = memnew(GLManager_X11(p_resolution, opengl_api_type));
- if (gl_manager->initialize() != OK) {
+ if (gl_manager->initialize(x11_display) != OK) {
memdelete(gl_manager);
gl_manager = nullptr;
r_error = ERR_UNAVAILABLE;
diff --git a/platform/linuxbsd/x11/display_server_x11.h b/platform/linuxbsd/x11/display_server_x11.h
index 4be8c3a534..2578ca06fd 100644
--- a/platform/linuxbsd/x11/display_server_x11.h
+++ b/platform/linuxbsd/x11/display_server_x11.h
@@ -64,12 +64,20 @@
#include "../freedesktop_screensaver.h"
#endif
-#include <X11/Xcursor/Xcursor.h>
+#include <X11/Xatom.h>
#include <X11/Xlib.h>
-#include <X11/extensions/XInput2.h>
-#include <X11/extensions/Xrandr.h>
+#include <X11/Xutil.h>
#include <X11/keysym.h>
+#include "dynwrappers/xlib-so_wrap.h"
+
+#include "dynwrappers/xcursor-so_wrap.h"
+#include "dynwrappers/xext-so_wrap.h"
+#include "dynwrappers/xinerama-so_wrap.h"
+#include "dynwrappers/xinput2-so_wrap.h"
+#include "dynwrappers/xrandr-so_wrap.h"
+#include "dynwrappers/xrender-so_wrap.h"
+
typedef struct _xrr_monitor_info {
Atom name;
Bool primary = false;
@@ -151,6 +159,7 @@ class DisplayServerX11 : public DisplayServer {
//better to guess on the fly, given WM can change it
//WindowMode mode;
bool fullscreen = false; //OS can't exit from this mode
+ bool exclusive_fullscreen = false;
bool on_top = false;
bool borderless = false;
bool resize_disabled = false;
@@ -275,7 +284,7 @@ class DisplayServerX11 : public DisplayServer {
bool _window_minimize_check(WindowID p_window) const;
void _validate_mode_on_map(WindowID p_window);
void _update_size_hints(WindowID p_window);
- void _set_wm_fullscreen(WindowID p_window, bool p_enabled);
+ void _set_wm_fullscreen(WindowID p_window, bool p_enabled, bool p_exclusive);
void _set_wm_maximized(WindowID p_window, bool p_enabled);
void _set_wm_minimized(WindowID p_window, bool p_enabled);
@@ -384,6 +393,7 @@ public:
virtual void window_set_current_screen(int p_screen, WindowID p_window = MAIN_WINDOW_ID) override;
virtual Point2i window_get_position(WindowID p_window = MAIN_WINDOW_ID) const override;
+ virtual Point2i window_get_position_with_decorations(WindowID p_window = MAIN_WINDOW_ID) const override;
virtual void window_set_position(const Point2i &p_position, WindowID p_window = MAIN_WINDOW_ID) override;
virtual void window_set_max_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID) override;
@@ -397,7 +407,7 @@ public:
virtual void window_set_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID) override;
virtual Size2i window_get_size(WindowID p_window = MAIN_WINDOW_ID) const override;
- virtual Size2i window_get_real_size(WindowID p_window = MAIN_WINDOW_ID) const override;
+ virtual Size2i window_get_size_with_decorations(WindowID p_window = MAIN_WINDOW_ID) const override;
virtual void window_set_mode(WindowMode p_mode, WindowID p_window = MAIN_WINDOW_ID) override;
virtual WindowMode window_get_mode(WindowID p_window = MAIN_WINDOW_ID) const override;
diff --git a/platform/linuxbsd/x11/dynwrappers/xcursor-so_wrap.c b/platform/linuxbsd/x11/dynwrappers/xcursor-so_wrap.c
new file mode 100644
index 0000000000..7042a60d47
--- /dev/null
+++ b/platform/linuxbsd/x11/dynwrappers/xcursor-so_wrap.c
@@ -0,0 +1,676 @@
+// 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-12-02 12:48:06
+// flags: ./generate-wrapper.py --include /usr/include/X11/Xcursor/Xcursor.h --sys-include <X11/Xcursor/Xcursor.h> --soname libXcursor.so.1 --init-name xcursor --output-header xcursor-so_wrap.h --output-implementation xcursor-so_wrap.c
+//
+// NOTE: Generated from Xcursor 1.2.0.
+// This has been handpatched to workaround some issues with the generator that
+// will be eventually fixed. In this case, non-existent symbols inherited from
+// libX11, but absent in libXcursor.so.1, were removed.
+#include <stdint.h>
+
+#define XcursorImageCreate XcursorImageCreate_dylibloader_orig_xcursor
+#define XcursorImageDestroy XcursorImageDestroy_dylibloader_orig_xcursor
+#define XcursorImagesCreate XcursorImagesCreate_dylibloader_orig_xcursor
+#define XcursorImagesDestroy XcursorImagesDestroy_dylibloader_orig_xcursor
+#define XcursorImagesSetName XcursorImagesSetName_dylibloader_orig_xcursor
+#define XcursorCursorsCreate XcursorCursorsCreate_dylibloader_orig_xcursor
+#define XcursorCursorsDestroy XcursorCursorsDestroy_dylibloader_orig_xcursor
+#define XcursorAnimateCreate XcursorAnimateCreate_dylibloader_orig_xcursor
+#define XcursorAnimateDestroy XcursorAnimateDestroy_dylibloader_orig_xcursor
+#define XcursorAnimateNext XcursorAnimateNext_dylibloader_orig_xcursor
+#define XcursorCommentCreate XcursorCommentCreate_dylibloader_orig_xcursor
+#define XcursorCommentDestroy XcursorCommentDestroy_dylibloader_orig_xcursor
+#define XcursorCommentsCreate XcursorCommentsCreate_dylibloader_orig_xcursor
+#define XcursorCommentsDestroy XcursorCommentsDestroy_dylibloader_orig_xcursor
+#define XcursorXcFileLoadImage XcursorXcFileLoadImage_dylibloader_orig_xcursor
+#define XcursorXcFileLoadImages XcursorXcFileLoadImages_dylibloader_orig_xcursor
+#define XcursorXcFileLoadAllImages XcursorXcFileLoadAllImages_dylibloader_orig_xcursor
+#define XcursorXcFileLoad XcursorXcFileLoad_dylibloader_orig_xcursor
+#define XcursorXcFileSave XcursorXcFileSave_dylibloader_orig_xcursor
+#define XcursorFileLoadImage XcursorFileLoadImage_dylibloader_orig_xcursor
+#define XcursorFileLoadImages XcursorFileLoadImages_dylibloader_orig_xcursor
+#define XcursorFileLoadAllImages XcursorFileLoadAllImages_dylibloader_orig_xcursor
+#define XcursorFileLoad XcursorFileLoad_dylibloader_orig_xcursor
+#define XcursorFileSaveImages XcursorFileSaveImages_dylibloader_orig_xcursor
+#define XcursorFileSave XcursorFileSave_dylibloader_orig_xcursor
+#define XcursorFilenameLoadImage XcursorFilenameLoadImage_dylibloader_orig_xcursor
+#define XcursorFilenameLoadImages XcursorFilenameLoadImages_dylibloader_orig_xcursor
+#define XcursorFilenameLoadAllImages XcursorFilenameLoadAllImages_dylibloader_orig_xcursor
+#define XcursorFilenameLoad XcursorFilenameLoad_dylibloader_orig_xcursor
+#define XcursorFilenameSaveImages XcursorFilenameSaveImages_dylibloader_orig_xcursor
+#define XcursorFilenameSave XcursorFilenameSave_dylibloader_orig_xcursor
+#define XcursorLibraryLoadImage XcursorLibraryLoadImage_dylibloader_orig_xcursor
+#define XcursorLibraryLoadImages XcursorLibraryLoadImages_dylibloader_orig_xcursor
+#define XcursorLibraryPath XcursorLibraryPath_dylibloader_orig_xcursor
+#define XcursorLibraryShape XcursorLibraryShape_dylibloader_orig_xcursor
+#define XcursorImageLoadCursor XcursorImageLoadCursor_dylibloader_orig_xcursor
+#define XcursorImagesLoadCursors XcursorImagesLoadCursors_dylibloader_orig_xcursor
+#define XcursorImagesLoadCursor XcursorImagesLoadCursor_dylibloader_orig_xcursor
+#define XcursorFilenameLoadCursor XcursorFilenameLoadCursor_dylibloader_orig_xcursor
+#define XcursorFilenameLoadCursors XcursorFilenameLoadCursors_dylibloader_orig_xcursor
+#define XcursorLibraryLoadCursor XcursorLibraryLoadCursor_dylibloader_orig_xcursor
+#define XcursorLibraryLoadCursors XcursorLibraryLoadCursors_dylibloader_orig_xcursor
+#define XcursorShapeLoadImage XcursorShapeLoadImage_dylibloader_orig_xcursor
+#define XcursorShapeLoadImages XcursorShapeLoadImages_dylibloader_orig_xcursor
+#define XcursorShapeLoadCursor XcursorShapeLoadCursor_dylibloader_orig_xcursor
+#define XcursorShapeLoadCursors XcursorShapeLoadCursors_dylibloader_orig_xcursor
+#define XcursorTryShapeCursor XcursorTryShapeCursor_dylibloader_orig_xcursor
+#define XcursorNoticeCreateBitmap XcursorNoticeCreateBitmap_dylibloader_orig_xcursor
+#define XcursorNoticePutBitmap XcursorNoticePutBitmap_dylibloader_orig_xcursor
+#define XcursorTryShapeBitmapCursor XcursorTryShapeBitmapCursor_dylibloader_orig_xcursor
+#define XcursorImageHash XcursorImageHash_dylibloader_orig_xcursor
+#define XcursorSupportsARGB XcursorSupportsARGB_dylibloader_orig_xcursor
+#define XcursorSupportsAnim XcursorSupportsAnim_dylibloader_orig_xcursor
+#define XcursorSetDefaultSize XcursorSetDefaultSize_dylibloader_orig_xcursor
+#define XcursorGetDefaultSize XcursorGetDefaultSize_dylibloader_orig_xcursor
+#define XcursorSetTheme XcursorSetTheme_dylibloader_orig_xcursor
+#define XcursorGetTheme XcursorGetTheme_dylibloader_orig_xcursor
+#define XcursorGetThemeCore XcursorGetThemeCore_dylibloader_orig_xcursor
+#define XcursorSetThemeCore XcursorSetThemeCore_dylibloader_orig_xcursor
+#include <X11/Xcursor/Xcursor.h>
+#undef XcursorImageCreate
+#undef XcursorImageDestroy
+#undef XcursorImagesCreate
+#undef XcursorImagesDestroy
+#undef XcursorImagesSetName
+#undef XcursorCursorsCreate
+#undef XcursorCursorsDestroy
+#undef XcursorAnimateCreate
+#undef XcursorAnimateDestroy
+#undef XcursorAnimateNext
+#undef XcursorCommentCreate
+#undef XcursorCommentDestroy
+#undef XcursorCommentsCreate
+#undef XcursorCommentsDestroy
+#undef XcursorXcFileLoadImage
+#undef XcursorXcFileLoadImages
+#undef XcursorXcFileLoadAllImages
+#undef XcursorXcFileLoad
+#undef XcursorXcFileSave
+#undef XcursorFileLoadImage
+#undef XcursorFileLoadImages
+#undef XcursorFileLoadAllImages
+#undef XcursorFileLoad
+#undef XcursorFileSaveImages
+#undef XcursorFileSave
+#undef XcursorFilenameLoadImage
+#undef XcursorFilenameLoadImages
+#undef XcursorFilenameLoadAllImages
+#undef XcursorFilenameLoad
+#undef XcursorFilenameSaveImages
+#undef XcursorFilenameSave
+#undef XcursorLibraryLoadImage
+#undef XcursorLibraryLoadImages
+#undef XcursorLibraryPath
+#undef XcursorLibraryShape
+#undef XcursorImageLoadCursor
+#undef XcursorImagesLoadCursors
+#undef XcursorImagesLoadCursor
+#undef XcursorFilenameLoadCursor
+#undef XcursorFilenameLoadCursors
+#undef XcursorLibraryLoadCursor
+#undef XcursorLibraryLoadCursors
+#undef XcursorShapeLoadImage
+#undef XcursorShapeLoadImages
+#undef XcursorShapeLoadCursor
+#undef XcursorShapeLoadCursors
+#undef XcursorTryShapeCursor
+#undef XcursorNoticeCreateBitmap
+#undef XcursorNoticePutBitmap
+#undef XcursorTryShapeBitmapCursor
+#undef XcursorImageHash
+#undef XcursorSupportsARGB
+#undef XcursorSupportsAnim
+#undef XcursorSetDefaultSize
+#undef XcursorGetDefaultSize
+#undef XcursorSetTheme
+#undef XcursorGetTheme
+#undef XcursorGetThemeCore
+#undef XcursorSetThemeCore
+#include <dlfcn.h>
+#include <stdio.h>
+XcursorImage* (*XcursorImageCreate_dylibloader_wrapper_xcursor)( int, int);
+void (*XcursorImageDestroy_dylibloader_wrapper_xcursor)( XcursorImage*);
+XcursorImages* (*XcursorImagesCreate_dylibloader_wrapper_xcursor)( int);
+void (*XcursorImagesDestroy_dylibloader_wrapper_xcursor)( XcursorImages*);
+void (*XcursorImagesSetName_dylibloader_wrapper_xcursor)( XcursorImages*,const char*);
+XcursorCursors* (*XcursorCursorsCreate_dylibloader_wrapper_xcursor)( Display*, int);
+void (*XcursorCursorsDestroy_dylibloader_wrapper_xcursor)( XcursorCursors*);
+XcursorAnimate* (*XcursorAnimateCreate_dylibloader_wrapper_xcursor)( XcursorCursors*);
+void (*XcursorAnimateDestroy_dylibloader_wrapper_xcursor)( XcursorAnimate*);
+Cursor (*XcursorAnimateNext_dylibloader_wrapper_xcursor)( XcursorAnimate*);
+XcursorComment* (*XcursorCommentCreate_dylibloader_wrapper_xcursor)( XcursorUInt, int);
+void (*XcursorCommentDestroy_dylibloader_wrapper_xcursor)( XcursorComment*);
+XcursorComments* (*XcursorCommentsCreate_dylibloader_wrapper_xcursor)( int);
+void (*XcursorCommentsDestroy_dylibloader_wrapper_xcursor)( XcursorComments*);
+XcursorImage* (*XcursorXcFileLoadImage_dylibloader_wrapper_xcursor)( XcursorFile*, int);
+XcursorImages* (*XcursorXcFileLoadImages_dylibloader_wrapper_xcursor)( XcursorFile*, int);
+XcursorImages* (*XcursorXcFileLoadAllImages_dylibloader_wrapper_xcursor)( XcursorFile*);
+XcursorBool (*XcursorXcFileLoad_dylibloader_wrapper_xcursor)( XcursorFile*, XcursorComments**, XcursorImages**);
+XcursorBool (*XcursorXcFileSave_dylibloader_wrapper_xcursor)( XcursorFile*,const XcursorComments*,const XcursorImages*);
+XcursorImage* (*XcursorFileLoadImage_dylibloader_wrapper_xcursor)( FILE*, int);
+XcursorImages* (*XcursorFileLoadImages_dylibloader_wrapper_xcursor)( FILE*, int);
+XcursorImages* (*XcursorFileLoadAllImages_dylibloader_wrapper_xcursor)( FILE*);
+XcursorBool (*XcursorFileLoad_dylibloader_wrapper_xcursor)( FILE*, XcursorComments**, XcursorImages**);
+XcursorBool (*XcursorFileSaveImages_dylibloader_wrapper_xcursor)( FILE*,const XcursorImages*);
+XcursorBool (*XcursorFileSave_dylibloader_wrapper_xcursor)( FILE*,const XcursorComments*,const XcursorImages*);
+XcursorImage* (*XcursorFilenameLoadImage_dylibloader_wrapper_xcursor)(const char*, int);
+XcursorImages* (*XcursorFilenameLoadImages_dylibloader_wrapper_xcursor)(const char*, int);
+XcursorImages* (*XcursorFilenameLoadAllImages_dylibloader_wrapper_xcursor)(const char*);
+XcursorBool (*XcursorFilenameLoad_dylibloader_wrapper_xcursor)(const char*, XcursorComments**, XcursorImages**);
+XcursorBool (*XcursorFilenameSaveImages_dylibloader_wrapper_xcursor)(const char*,const XcursorImages*);
+XcursorBool (*XcursorFilenameSave_dylibloader_wrapper_xcursor)(const char*,const XcursorComments*,const XcursorImages*);
+XcursorImage* (*XcursorLibraryLoadImage_dylibloader_wrapper_xcursor)(const char*,const char*, int);
+XcursorImages* (*XcursorLibraryLoadImages_dylibloader_wrapper_xcursor)(const char*,const char*, int);
+const char* (*XcursorLibraryPath_dylibloader_wrapper_xcursor)( void);
+int (*XcursorLibraryShape_dylibloader_wrapper_xcursor)(const char*);
+Cursor (*XcursorImageLoadCursor_dylibloader_wrapper_xcursor)( Display*,const XcursorImage*);
+XcursorCursors* (*XcursorImagesLoadCursors_dylibloader_wrapper_xcursor)( Display*,const XcursorImages*);
+Cursor (*XcursorImagesLoadCursor_dylibloader_wrapper_xcursor)( Display*,const XcursorImages*);
+Cursor (*XcursorFilenameLoadCursor_dylibloader_wrapper_xcursor)( Display*,const char*);
+XcursorCursors* (*XcursorFilenameLoadCursors_dylibloader_wrapper_xcursor)( Display*,const char*);
+Cursor (*XcursorLibraryLoadCursor_dylibloader_wrapper_xcursor)( Display*,const char*);
+XcursorCursors* (*XcursorLibraryLoadCursors_dylibloader_wrapper_xcursor)( Display*,const char*);
+XcursorImage* (*XcursorShapeLoadImage_dylibloader_wrapper_xcursor)( unsigned int,const char*, int);
+XcursorImages* (*XcursorShapeLoadImages_dylibloader_wrapper_xcursor)( unsigned int,const char*, int);
+Cursor (*XcursorShapeLoadCursor_dylibloader_wrapper_xcursor)( Display*, unsigned int);
+XcursorCursors* (*XcursorShapeLoadCursors_dylibloader_wrapper_xcursor)( Display*, unsigned int);
+Cursor (*XcursorTryShapeCursor_dylibloader_wrapper_xcursor)( Display*, Font, Font, unsigned int, unsigned int,const XColor*,const XColor*);
+void (*XcursorNoticeCreateBitmap_dylibloader_wrapper_xcursor)( Display*, Pixmap, unsigned int, unsigned int);
+void (*XcursorNoticePutBitmap_dylibloader_wrapper_xcursor)( Display*, Drawable, XImage*);
+Cursor (*XcursorTryShapeBitmapCursor_dylibloader_wrapper_xcursor)( Display*, Pixmap, Pixmap, XColor*, XColor*, unsigned int, unsigned int);
+void (*XcursorImageHash_dylibloader_wrapper_xcursor)( XImage*, unsigned char [16]);
+XcursorBool (*XcursorSupportsARGB_dylibloader_wrapper_xcursor)( Display*);
+XcursorBool (*XcursorSupportsAnim_dylibloader_wrapper_xcursor)( Display*);
+XcursorBool (*XcursorSetDefaultSize_dylibloader_wrapper_xcursor)( Display*, int);
+int (*XcursorGetDefaultSize_dylibloader_wrapper_xcursor)( Display*);
+XcursorBool (*XcursorSetTheme_dylibloader_wrapper_xcursor)( Display*,const char*);
+char* (*XcursorGetTheme_dylibloader_wrapper_xcursor)( Display*);
+XcursorBool (*XcursorGetThemeCore_dylibloader_wrapper_xcursor)( Display*);
+XcursorBool (*XcursorSetThemeCore_dylibloader_wrapper_xcursor)( Display*, XcursorBool);
+int initialize_xcursor(int verbose) {
+ void *handle;
+ char *error;
+ handle = dlopen("libXcursor.so.1", RTLD_LAZY);
+ if (!handle) {
+ if (verbose) {
+ fprintf(stderr, "%s\n", dlerror());
+ }
+ return(1);
+ }
+ dlerror();
+// XcursorImageCreate
+ *(void **) (&XcursorImageCreate_dylibloader_wrapper_xcursor) = dlsym(handle, "XcursorImageCreate");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XcursorImageDestroy
+ *(void **) (&XcursorImageDestroy_dylibloader_wrapper_xcursor) = dlsym(handle, "XcursorImageDestroy");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XcursorImagesCreate
+ *(void **) (&XcursorImagesCreate_dylibloader_wrapper_xcursor) = dlsym(handle, "XcursorImagesCreate");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XcursorImagesDestroy
+ *(void **) (&XcursorImagesDestroy_dylibloader_wrapper_xcursor) = dlsym(handle, "XcursorImagesDestroy");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XcursorImagesSetName
+ *(void **) (&XcursorImagesSetName_dylibloader_wrapper_xcursor) = dlsym(handle, "XcursorImagesSetName");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XcursorCursorsCreate
+ *(void **) (&XcursorCursorsCreate_dylibloader_wrapper_xcursor) = dlsym(handle, "XcursorCursorsCreate");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XcursorCursorsDestroy
+ *(void **) (&XcursorCursorsDestroy_dylibloader_wrapper_xcursor) = dlsym(handle, "XcursorCursorsDestroy");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XcursorAnimateCreate
+ *(void **) (&XcursorAnimateCreate_dylibloader_wrapper_xcursor) = dlsym(handle, "XcursorAnimateCreate");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XcursorAnimateDestroy
+ *(void **) (&XcursorAnimateDestroy_dylibloader_wrapper_xcursor) = dlsym(handle, "XcursorAnimateDestroy");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XcursorAnimateNext
+ *(void **) (&XcursorAnimateNext_dylibloader_wrapper_xcursor) = dlsym(handle, "XcursorAnimateNext");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XcursorCommentCreate
+ *(void **) (&XcursorCommentCreate_dylibloader_wrapper_xcursor) = dlsym(handle, "XcursorCommentCreate");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XcursorCommentDestroy
+ *(void **) (&XcursorCommentDestroy_dylibloader_wrapper_xcursor) = dlsym(handle, "XcursorCommentDestroy");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XcursorCommentsCreate
+ *(void **) (&XcursorCommentsCreate_dylibloader_wrapper_xcursor) = dlsym(handle, "XcursorCommentsCreate");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XcursorCommentsDestroy
+ *(void **) (&XcursorCommentsDestroy_dylibloader_wrapper_xcursor) = dlsym(handle, "XcursorCommentsDestroy");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XcursorXcFileLoadImage
+ *(void **) (&XcursorXcFileLoadImage_dylibloader_wrapper_xcursor) = dlsym(handle, "XcursorXcFileLoadImage");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XcursorXcFileLoadImages
+ *(void **) (&XcursorXcFileLoadImages_dylibloader_wrapper_xcursor) = dlsym(handle, "XcursorXcFileLoadImages");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XcursorXcFileLoadAllImages
+ *(void **) (&XcursorXcFileLoadAllImages_dylibloader_wrapper_xcursor) = dlsym(handle, "XcursorXcFileLoadAllImages");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XcursorXcFileLoad
+ *(void **) (&XcursorXcFileLoad_dylibloader_wrapper_xcursor) = dlsym(handle, "XcursorXcFileLoad");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XcursorXcFileSave
+ *(void **) (&XcursorXcFileSave_dylibloader_wrapper_xcursor) = dlsym(handle, "XcursorXcFileSave");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XcursorFileLoadImage
+ *(void **) (&XcursorFileLoadImage_dylibloader_wrapper_xcursor) = dlsym(handle, "XcursorFileLoadImage");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XcursorFileLoadImages
+ *(void **) (&XcursorFileLoadImages_dylibloader_wrapper_xcursor) = dlsym(handle, "XcursorFileLoadImages");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XcursorFileLoadAllImages
+ *(void **) (&XcursorFileLoadAllImages_dylibloader_wrapper_xcursor) = dlsym(handle, "XcursorFileLoadAllImages");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XcursorFileLoad
+ *(void **) (&XcursorFileLoad_dylibloader_wrapper_xcursor) = dlsym(handle, "XcursorFileLoad");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XcursorFileSaveImages
+ *(void **) (&XcursorFileSaveImages_dylibloader_wrapper_xcursor) = dlsym(handle, "XcursorFileSaveImages");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XcursorFileSave
+ *(void **) (&XcursorFileSave_dylibloader_wrapper_xcursor) = dlsym(handle, "XcursorFileSave");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XcursorFilenameLoadImage
+ *(void **) (&XcursorFilenameLoadImage_dylibloader_wrapper_xcursor) = dlsym(handle, "XcursorFilenameLoadImage");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XcursorFilenameLoadImages
+ *(void **) (&XcursorFilenameLoadImages_dylibloader_wrapper_xcursor) = dlsym(handle, "XcursorFilenameLoadImages");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XcursorFilenameLoadAllImages
+ *(void **) (&XcursorFilenameLoadAllImages_dylibloader_wrapper_xcursor) = dlsym(handle, "XcursorFilenameLoadAllImages");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XcursorFilenameLoad
+ *(void **) (&XcursorFilenameLoad_dylibloader_wrapper_xcursor) = dlsym(handle, "XcursorFilenameLoad");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XcursorFilenameSaveImages
+ *(void **) (&XcursorFilenameSaveImages_dylibloader_wrapper_xcursor) = dlsym(handle, "XcursorFilenameSaveImages");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XcursorFilenameSave
+ *(void **) (&XcursorFilenameSave_dylibloader_wrapper_xcursor) = dlsym(handle, "XcursorFilenameSave");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XcursorLibraryLoadImage
+ *(void **) (&XcursorLibraryLoadImage_dylibloader_wrapper_xcursor) = dlsym(handle, "XcursorLibraryLoadImage");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XcursorLibraryLoadImages
+ *(void **) (&XcursorLibraryLoadImages_dylibloader_wrapper_xcursor) = dlsym(handle, "XcursorLibraryLoadImages");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XcursorLibraryPath
+ *(void **) (&XcursorLibraryPath_dylibloader_wrapper_xcursor) = dlsym(handle, "XcursorLibraryPath");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XcursorLibraryShape
+ *(void **) (&XcursorLibraryShape_dylibloader_wrapper_xcursor) = dlsym(handle, "XcursorLibraryShape");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XcursorImageLoadCursor
+ *(void **) (&XcursorImageLoadCursor_dylibloader_wrapper_xcursor) = dlsym(handle, "XcursorImageLoadCursor");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XcursorImagesLoadCursors
+ *(void **) (&XcursorImagesLoadCursors_dylibloader_wrapper_xcursor) = dlsym(handle, "XcursorImagesLoadCursors");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XcursorImagesLoadCursor
+ *(void **) (&XcursorImagesLoadCursor_dylibloader_wrapper_xcursor) = dlsym(handle, "XcursorImagesLoadCursor");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XcursorFilenameLoadCursor
+ *(void **) (&XcursorFilenameLoadCursor_dylibloader_wrapper_xcursor) = dlsym(handle, "XcursorFilenameLoadCursor");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XcursorFilenameLoadCursors
+ *(void **) (&XcursorFilenameLoadCursors_dylibloader_wrapper_xcursor) = dlsym(handle, "XcursorFilenameLoadCursors");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XcursorLibraryLoadCursor
+ *(void **) (&XcursorLibraryLoadCursor_dylibloader_wrapper_xcursor) = dlsym(handle, "XcursorLibraryLoadCursor");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XcursorLibraryLoadCursors
+ *(void **) (&XcursorLibraryLoadCursors_dylibloader_wrapper_xcursor) = dlsym(handle, "XcursorLibraryLoadCursors");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XcursorShapeLoadImage
+ *(void **) (&XcursorShapeLoadImage_dylibloader_wrapper_xcursor) = dlsym(handle, "XcursorShapeLoadImage");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XcursorShapeLoadImages
+ *(void **) (&XcursorShapeLoadImages_dylibloader_wrapper_xcursor) = dlsym(handle, "XcursorShapeLoadImages");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XcursorShapeLoadCursor
+ *(void **) (&XcursorShapeLoadCursor_dylibloader_wrapper_xcursor) = dlsym(handle, "XcursorShapeLoadCursor");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XcursorShapeLoadCursors
+ *(void **) (&XcursorShapeLoadCursors_dylibloader_wrapper_xcursor) = dlsym(handle, "XcursorShapeLoadCursors");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XcursorTryShapeCursor
+ *(void **) (&XcursorTryShapeCursor_dylibloader_wrapper_xcursor) = dlsym(handle, "XcursorTryShapeCursor");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XcursorNoticeCreateBitmap
+ *(void **) (&XcursorNoticeCreateBitmap_dylibloader_wrapper_xcursor) = dlsym(handle, "XcursorNoticeCreateBitmap");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XcursorNoticePutBitmap
+ *(void **) (&XcursorNoticePutBitmap_dylibloader_wrapper_xcursor) = dlsym(handle, "XcursorNoticePutBitmap");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XcursorTryShapeBitmapCursor
+ *(void **) (&XcursorTryShapeBitmapCursor_dylibloader_wrapper_xcursor) = dlsym(handle, "XcursorTryShapeBitmapCursor");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XcursorImageHash
+ *(void **) (&XcursorImageHash_dylibloader_wrapper_xcursor) = dlsym(handle, "XcursorImageHash");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XcursorSupportsARGB
+ *(void **) (&XcursorSupportsARGB_dylibloader_wrapper_xcursor) = dlsym(handle, "XcursorSupportsARGB");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XcursorSupportsAnim
+ *(void **) (&XcursorSupportsAnim_dylibloader_wrapper_xcursor) = dlsym(handle, "XcursorSupportsAnim");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XcursorSetDefaultSize
+ *(void **) (&XcursorSetDefaultSize_dylibloader_wrapper_xcursor) = dlsym(handle, "XcursorSetDefaultSize");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XcursorGetDefaultSize
+ *(void **) (&XcursorGetDefaultSize_dylibloader_wrapper_xcursor) = dlsym(handle, "XcursorGetDefaultSize");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XcursorSetTheme
+ *(void **) (&XcursorSetTheme_dylibloader_wrapper_xcursor) = dlsym(handle, "XcursorSetTheme");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XcursorGetTheme
+ *(void **) (&XcursorGetTheme_dylibloader_wrapper_xcursor) = dlsym(handle, "XcursorGetTheme");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XcursorGetThemeCore
+ *(void **) (&XcursorGetThemeCore_dylibloader_wrapper_xcursor) = dlsym(handle, "XcursorGetThemeCore");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XcursorSetThemeCore
+ *(void **) (&XcursorSetThemeCore_dylibloader_wrapper_xcursor) = dlsym(handle, "XcursorSetThemeCore");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+return 0;
+}
diff --git a/platform/linuxbsd/x11/dynwrappers/xcursor-so_wrap.h b/platform/linuxbsd/x11/dynwrappers/xcursor-so_wrap.h
new file mode 100644
index 0000000000..d00fccffda
--- /dev/null
+++ b/platform/linuxbsd/x11/dynwrappers/xcursor-so_wrap.h
@@ -0,0 +1,258 @@
+#ifndef DYLIBLOAD_WRAPPER_XCURSOR
+#define DYLIBLOAD_WRAPPER_XCURSOR
+// 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-12-02 12:48:06
+// flags: ./generate-wrapper.py --include /usr/include/X11/Xcursor/Xcursor.h --sys-include <X11/Xcursor/Xcursor.h> --soname libXcursor.so.1 --init-name xcursor --output-header xcursor-so_wrap.h --output-implementation xcursor-so_wrap.c
+//
+// NOTE: Generated from Xcursor 1.2.0.
+// This has been handpatched to workaround some issues with the generator that
+// will be eventually fixed. In this case, non-existent symbols inherited from
+// libX11, but absent in libXcursor.so.1, were removed.
+#include <stdint.h>
+
+#define XcursorImageCreate XcursorImageCreate_dylibloader_orig_xcursor
+#define XcursorImageDestroy XcursorImageDestroy_dylibloader_orig_xcursor
+#define XcursorImagesCreate XcursorImagesCreate_dylibloader_orig_xcursor
+#define XcursorImagesDestroy XcursorImagesDestroy_dylibloader_orig_xcursor
+#define XcursorImagesSetName XcursorImagesSetName_dylibloader_orig_xcursor
+#define XcursorCursorsCreate XcursorCursorsCreate_dylibloader_orig_xcursor
+#define XcursorCursorsDestroy XcursorCursorsDestroy_dylibloader_orig_xcursor
+#define XcursorAnimateCreate XcursorAnimateCreate_dylibloader_orig_xcursor
+#define XcursorAnimateDestroy XcursorAnimateDestroy_dylibloader_orig_xcursor
+#define XcursorAnimateNext XcursorAnimateNext_dylibloader_orig_xcursor
+#define XcursorCommentCreate XcursorCommentCreate_dylibloader_orig_xcursor
+#define XcursorCommentDestroy XcursorCommentDestroy_dylibloader_orig_xcursor
+#define XcursorCommentsCreate XcursorCommentsCreate_dylibloader_orig_xcursor
+#define XcursorCommentsDestroy XcursorCommentsDestroy_dylibloader_orig_xcursor
+#define XcursorXcFileLoadImage XcursorXcFileLoadImage_dylibloader_orig_xcursor
+#define XcursorXcFileLoadImages XcursorXcFileLoadImages_dylibloader_orig_xcursor
+#define XcursorXcFileLoadAllImages XcursorXcFileLoadAllImages_dylibloader_orig_xcursor
+#define XcursorXcFileLoad XcursorXcFileLoad_dylibloader_orig_xcursor
+#define XcursorXcFileSave XcursorXcFileSave_dylibloader_orig_xcursor
+#define XcursorFileLoadImage XcursorFileLoadImage_dylibloader_orig_xcursor
+#define XcursorFileLoadImages XcursorFileLoadImages_dylibloader_orig_xcursor
+#define XcursorFileLoadAllImages XcursorFileLoadAllImages_dylibloader_orig_xcursor
+#define XcursorFileLoad XcursorFileLoad_dylibloader_orig_xcursor
+#define XcursorFileSaveImages XcursorFileSaveImages_dylibloader_orig_xcursor
+#define XcursorFileSave XcursorFileSave_dylibloader_orig_xcursor
+#define XcursorFilenameLoadImage XcursorFilenameLoadImage_dylibloader_orig_xcursor
+#define XcursorFilenameLoadImages XcursorFilenameLoadImages_dylibloader_orig_xcursor
+#define XcursorFilenameLoadAllImages XcursorFilenameLoadAllImages_dylibloader_orig_xcursor
+#define XcursorFilenameLoad XcursorFilenameLoad_dylibloader_orig_xcursor
+#define XcursorFilenameSaveImages XcursorFilenameSaveImages_dylibloader_orig_xcursor
+#define XcursorFilenameSave XcursorFilenameSave_dylibloader_orig_xcursor
+#define XcursorLibraryLoadImage XcursorLibraryLoadImage_dylibloader_orig_xcursor
+#define XcursorLibraryLoadImages XcursorLibraryLoadImages_dylibloader_orig_xcursor
+#define XcursorLibraryPath XcursorLibraryPath_dylibloader_orig_xcursor
+#define XcursorLibraryShape XcursorLibraryShape_dylibloader_orig_xcursor
+#define XcursorImageLoadCursor XcursorImageLoadCursor_dylibloader_orig_xcursor
+#define XcursorImagesLoadCursors XcursorImagesLoadCursors_dylibloader_orig_xcursor
+#define XcursorImagesLoadCursor XcursorImagesLoadCursor_dylibloader_orig_xcursor
+#define XcursorFilenameLoadCursor XcursorFilenameLoadCursor_dylibloader_orig_xcursor
+#define XcursorFilenameLoadCursors XcursorFilenameLoadCursors_dylibloader_orig_xcursor
+#define XcursorLibraryLoadCursor XcursorLibraryLoadCursor_dylibloader_orig_xcursor
+#define XcursorLibraryLoadCursors XcursorLibraryLoadCursors_dylibloader_orig_xcursor
+#define XcursorShapeLoadImage XcursorShapeLoadImage_dylibloader_orig_xcursor
+#define XcursorShapeLoadImages XcursorShapeLoadImages_dylibloader_orig_xcursor
+#define XcursorShapeLoadCursor XcursorShapeLoadCursor_dylibloader_orig_xcursor
+#define XcursorShapeLoadCursors XcursorShapeLoadCursors_dylibloader_orig_xcursor
+#define XcursorTryShapeCursor XcursorTryShapeCursor_dylibloader_orig_xcursor
+#define XcursorNoticeCreateBitmap XcursorNoticeCreateBitmap_dylibloader_orig_xcursor
+#define XcursorNoticePutBitmap XcursorNoticePutBitmap_dylibloader_orig_xcursor
+#define XcursorTryShapeBitmapCursor XcursorTryShapeBitmapCursor_dylibloader_orig_xcursor
+#define XcursorImageHash XcursorImageHash_dylibloader_orig_xcursor
+#define XcursorSupportsARGB XcursorSupportsARGB_dylibloader_orig_xcursor
+#define XcursorSupportsAnim XcursorSupportsAnim_dylibloader_orig_xcursor
+#define XcursorSetDefaultSize XcursorSetDefaultSize_dylibloader_orig_xcursor
+#define XcursorGetDefaultSize XcursorGetDefaultSize_dylibloader_orig_xcursor
+#define XcursorSetTheme XcursorSetTheme_dylibloader_orig_xcursor
+#define XcursorGetTheme XcursorGetTheme_dylibloader_orig_xcursor
+#define XcursorGetThemeCore XcursorGetThemeCore_dylibloader_orig_xcursor
+#define XcursorSetThemeCore XcursorSetThemeCore_dylibloader_orig_xcursor
+#include <X11/Xcursor/Xcursor.h>
+#undef XcursorImageCreate
+#undef XcursorImageDestroy
+#undef XcursorImagesCreate
+#undef XcursorImagesDestroy
+#undef XcursorImagesSetName
+#undef XcursorCursorsCreate
+#undef XcursorCursorsDestroy
+#undef XcursorAnimateCreate
+#undef XcursorAnimateDestroy
+#undef XcursorAnimateNext
+#undef XcursorCommentCreate
+#undef XcursorCommentDestroy
+#undef XcursorCommentsCreate
+#undef XcursorCommentsDestroy
+#undef XcursorXcFileLoadImage
+#undef XcursorXcFileLoadImages
+#undef XcursorXcFileLoadAllImages
+#undef XcursorXcFileLoad
+#undef XcursorXcFileSave
+#undef XcursorFileLoadImage
+#undef XcursorFileLoadImages
+#undef XcursorFileLoadAllImages
+#undef XcursorFileLoad
+#undef XcursorFileSaveImages
+#undef XcursorFileSave
+#undef XcursorFilenameLoadImage
+#undef XcursorFilenameLoadImages
+#undef XcursorFilenameLoadAllImages
+#undef XcursorFilenameLoad
+#undef XcursorFilenameSaveImages
+#undef XcursorFilenameSave
+#undef XcursorLibraryLoadImage
+#undef XcursorLibraryLoadImages
+#undef XcursorLibraryPath
+#undef XcursorLibraryShape
+#undef XcursorImageLoadCursor
+#undef XcursorImagesLoadCursors
+#undef XcursorImagesLoadCursor
+#undef XcursorFilenameLoadCursor
+#undef XcursorFilenameLoadCursors
+#undef XcursorLibraryLoadCursor
+#undef XcursorLibraryLoadCursors
+#undef XcursorShapeLoadImage
+#undef XcursorShapeLoadImages
+#undef XcursorShapeLoadCursor
+#undef XcursorShapeLoadCursors
+#undef XcursorTryShapeCursor
+#undef XcursorNoticeCreateBitmap
+#undef XcursorNoticePutBitmap
+#undef XcursorTryShapeBitmapCursor
+#undef XcursorImageHash
+#undef XcursorSupportsARGB
+#undef XcursorSupportsAnim
+#undef XcursorSetDefaultSize
+#undef XcursorGetDefaultSize
+#undef XcursorSetTheme
+#undef XcursorGetTheme
+#undef XcursorGetThemeCore
+#undef XcursorSetThemeCore
+#ifdef __cplusplus
+extern "C" {
+#endif
+#define XcursorImageCreate XcursorImageCreate_dylibloader_wrapper_xcursor
+#define XcursorImageDestroy XcursorImageDestroy_dylibloader_wrapper_xcursor
+#define XcursorImagesCreate XcursorImagesCreate_dylibloader_wrapper_xcursor
+#define XcursorImagesDestroy XcursorImagesDestroy_dylibloader_wrapper_xcursor
+#define XcursorImagesSetName XcursorImagesSetName_dylibloader_wrapper_xcursor
+#define XcursorCursorsCreate XcursorCursorsCreate_dylibloader_wrapper_xcursor
+#define XcursorCursorsDestroy XcursorCursorsDestroy_dylibloader_wrapper_xcursor
+#define XcursorAnimateCreate XcursorAnimateCreate_dylibloader_wrapper_xcursor
+#define XcursorAnimateDestroy XcursorAnimateDestroy_dylibloader_wrapper_xcursor
+#define XcursorAnimateNext XcursorAnimateNext_dylibloader_wrapper_xcursor
+#define XcursorCommentCreate XcursorCommentCreate_dylibloader_wrapper_xcursor
+#define XcursorCommentDestroy XcursorCommentDestroy_dylibloader_wrapper_xcursor
+#define XcursorCommentsCreate XcursorCommentsCreate_dylibloader_wrapper_xcursor
+#define XcursorCommentsDestroy XcursorCommentsDestroy_dylibloader_wrapper_xcursor
+#define XcursorXcFileLoadImage XcursorXcFileLoadImage_dylibloader_wrapper_xcursor
+#define XcursorXcFileLoadImages XcursorXcFileLoadImages_dylibloader_wrapper_xcursor
+#define XcursorXcFileLoadAllImages XcursorXcFileLoadAllImages_dylibloader_wrapper_xcursor
+#define XcursorXcFileLoad XcursorXcFileLoad_dylibloader_wrapper_xcursor
+#define XcursorXcFileSave XcursorXcFileSave_dylibloader_wrapper_xcursor
+#define XcursorFileLoadImage XcursorFileLoadImage_dylibloader_wrapper_xcursor
+#define XcursorFileLoadImages XcursorFileLoadImages_dylibloader_wrapper_xcursor
+#define XcursorFileLoadAllImages XcursorFileLoadAllImages_dylibloader_wrapper_xcursor
+#define XcursorFileLoad XcursorFileLoad_dylibloader_wrapper_xcursor
+#define XcursorFileSaveImages XcursorFileSaveImages_dylibloader_wrapper_xcursor
+#define XcursorFileSave XcursorFileSave_dylibloader_wrapper_xcursor
+#define XcursorFilenameLoadImage XcursorFilenameLoadImage_dylibloader_wrapper_xcursor
+#define XcursorFilenameLoadImages XcursorFilenameLoadImages_dylibloader_wrapper_xcursor
+#define XcursorFilenameLoadAllImages XcursorFilenameLoadAllImages_dylibloader_wrapper_xcursor
+#define XcursorFilenameLoad XcursorFilenameLoad_dylibloader_wrapper_xcursor
+#define XcursorFilenameSaveImages XcursorFilenameSaveImages_dylibloader_wrapper_xcursor
+#define XcursorFilenameSave XcursorFilenameSave_dylibloader_wrapper_xcursor
+#define XcursorLibraryLoadImage XcursorLibraryLoadImage_dylibloader_wrapper_xcursor
+#define XcursorLibraryLoadImages XcursorLibraryLoadImages_dylibloader_wrapper_xcursor
+#define XcursorLibraryPath XcursorLibraryPath_dylibloader_wrapper_xcursor
+#define XcursorLibraryShape XcursorLibraryShape_dylibloader_wrapper_xcursor
+#define XcursorImageLoadCursor XcursorImageLoadCursor_dylibloader_wrapper_xcursor
+#define XcursorImagesLoadCursors XcursorImagesLoadCursors_dylibloader_wrapper_xcursor
+#define XcursorImagesLoadCursor XcursorImagesLoadCursor_dylibloader_wrapper_xcursor
+#define XcursorFilenameLoadCursor XcursorFilenameLoadCursor_dylibloader_wrapper_xcursor
+#define XcursorFilenameLoadCursors XcursorFilenameLoadCursors_dylibloader_wrapper_xcursor
+#define XcursorLibraryLoadCursor XcursorLibraryLoadCursor_dylibloader_wrapper_xcursor
+#define XcursorLibraryLoadCursors XcursorLibraryLoadCursors_dylibloader_wrapper_xcursor
+#define XcursorShapeLoadImage XcursorShapeLoadImage_dylibloader_wrapper_xcursor
+#define XcursorShapeLoadImages XcursorShapeLoadImages_dylibloader_wrapper_xcursor
+#define XcursorShapeLoadCursor XcursorShapeLoadCursor_dylibloader_wrapper_xcursor
+#define XcursorShapeLoadCursors XcursorShapeLoadCursors_dylibloader_wrapper_xcursor
+#define XcursorTryShapeCursor XcursorTryShapeCursor_dylibloader_wrapper_xcursor
+#define XcursorNoticeCreateBitmap XcursorNoticeCreateBitmap_dylibloader_wrapper_xcursor
+#define XcursorNoticePutBitmap XcursorNoticePutBitmap_dylibloader_wrapper_xcursor
+#define XcursorTryShapeBitmapCursor XcursorTryShapeBitmapCursor_dylibloader_wrapper_xcursor
+#define XcursorImageHash XcursorImageHash_dylibloader_wrapper_xcursor
+#define XcursorSupportsARGB XcursorSupportsARGB_dylibloader_wrapper_xcursor
+#define XcursorSupportsAnim XcursorSupportsAnim_dylibloader_wrapper_xcursor
+#define XcursorSetDefaultSize XcursorSetDefaultSize_dylibloader_wrapper_xcursor
+#define XcursorGetDefaultSize XcursorGetDefaultSize_dylibloader_wrapper_xcursor
+#define XcursorSetTheme XcursorSetTheme_dylibloader_wrapper_xcursor
+#define XcursorGetTheme XcursorGetTheme_dylibloader_wrapper_xcursor
+#define XcursorGetThemeCore XcursorGetThemeCore_dylibloader_wrapper_xcursor
+#define XcursorSetThemeCore XcursorSetThemeCore_dylibloader_wrapper_xcursor
+extern XcursorImage* (*XcursorImageCreate_dylibloader_wrapper_xcursor)( int, int);
+extern void (*XcursorImageDestroy_dylibloader_wrapper_xcursor)( XcursorImage*);
+extern XcursorImages* (*XcursorImagesCreate_dylibloader_wrapper_xcursor)( int);
+extern void (*XcursorImagesDestroy_dylibloader_wrapper_xcursor)( XcursorImages*);
+extern void (*XcursorImagesSetName_dylibloader_wrapper_xcursor)( XcursorImages*,const char*);
+extern XcursorCursors* (*XcursorCursorsCreate_dylibloader_wrapper_xcursor)( Display*, int);
+extern void (*XcursorCursorsDestroy_dylibloader_wrapper_xcursor)( XcursorCursors*);
+extern XcursorAnimate* (*XcursorAnimateCreate_dylibloader_wrapper_xcursor)( XcursorCursors*);
+extern void (*XcursorAnimateDestroy_dylibloader_wrapper_xcursor)( XcursorAnimate*);
+extern Cursor (*XcursorAnimateNext_dylibloader_wrapper_xcursor)( XcursorAnimate*);
+extern XcursorComment* (*XcursorCommentCreate_dylibloader_wrapper_xcursor)( XcursorUInt, int);
+extern void (*XcursorCommentDestroy_dylibloader_wrapper_xcursor)( XcursorComment*);
+extern XcursorComments* (*XcursorCommentsCreate_dylibloader_wrapper_xcursor)( int);
+extern void (*XcursorCommentsDestroy_dylibloader_wrapper_xcursor)( XcursorComments*);
+extern XcursorImage* (*XcursorXcFileLoadImage_dylibloader_wrapper_xcursor)( XcursorFile*, int);
+extern XcursorImages* (*XcursorXcFileLoadImages_dylibloader_wrapper_xcursor)( XcursorFile*, int);
+extern XcursorImages* (*XcursorXcFileLoadAllImages_dylibloader_wrapper_xcursor)( XcursorFile*);
+extern XcursorBool (*XcursorXcFileLoad_dylibloader_wrapper_xcursor)( XcursorFile*, XcursorComments**, XcursorImages**);
+extern XcursorBool (*XcursorXcFileSave_dylibloader_wrapper_xcursor)( XcursorFile*,const XcursorComments*,const XcursorImages*);
+extern XcursorImage* (*XcursorFileLoadImage_dylibloader_wrapper_xcursor)( FILE*, int);
+extern XcursorImages* (*XcursorFileLoadImages_dylibloader_wrapper_xcursor)( FILE*, int);
+extern XcursorImages* (*XcursorFileLoadAllImages_dylibloader_wrapper_xcursor)( FILE*);
+extern XcursorBool (*XcursorFileLoad_dylibloader_wrapper_xcursor)( FILE*, XcursorComments**, XcursorImages**);
+extern XcursorBool (*XcursorFileSaveImages_dylibloader_wrapper_xcursor)( FILE*,const XcursorImages*);
+extern XcursorBool (*XcursorFileSave_dylibloader_wrapper_xcursor)( FILE*,const XcursorComments*,const XcursorImages*);
+extern XcursorImage* (*XcursorFilenameLoadImage_dylibloader_wrapper_xcursor)(const char*, int);
+extern XcursorImages* (*XcursorFilenameLoadImages_dylibloader_wrapper_xcursor)(const char*, int);
+extern XcursorImages* (*XcursorFilenameLoadAllImages_dylibloader_wrapper_xcursor)(const char*);
+extern XcursorBool (*XcursorFilenameLoad_dylibloader_wrapper_xcursor)(const char*, XcursorComments**, XcursorImages**);
+extern XcursorBool (*XcursorFilenameSaveImages_dylibloader_wrapper_xcursor)(const char*,const XcursorImages*);
+extern XcursorBool (*XcursorFilenameSave_dylibloader_wrapper_xcursor)(const char*,const XcursorComments*,const XcursorImages*);
+extern XcursorImage* (*XcursorLibraryLoadImage_dylibloader_wrapper_xcursor)(const char*,const char*, int);
+extern XcursorImages* (*XcursorLibraryLoadImages_dylibloader_wrapper_xcursor)(const char*,const char*, int);
+extern const char* (*XcursorLibraryPath_dylibloader_wrapper_xcursor)( void);
+extern int (*XcursorLibraryShape_dylibloader_wrapper_xcursor)(const char*);
+extern Cursor (*XcursorImageLoadCursor_dylibloader_wrapper_xcursor)( Display*,const XcursorImage*);
+extern XcursorCursors* (*XcursorImagesLoadCursors_dylibloader_wrapper_xcursor)( Display*,const XcursorImages*);
+extern Cursor (*XcursorImagesLoadCursor_dylibloader_wrapper_xcursor)( Display*,const XcursorImages*);
+extern Cursor (*XcursorFilenameLoadCursor_dylibloader_wrapper_xcursor)( Display*,const char*);
+extern XcursorCursors* (*XcursorFilenameLoadCursors_dylibloader_wrapper_xcursor)( Display*,const char*);
+extern Cursor (*XcursorLibraryLoadCursor_dylibloader_wrapper_xcursor)( Display*,const char*);
+extern XcursorCursors* (*XcursorLibraryLoadCursors_dylibloader_wrapper_xcursor)( Display*,const char*);
+extern XcursorImage* (*XcursorShapeLoadImage_dylibloader_wrapper_xcursor)( unsigned int,const char*, int);
+extern XcursorImages* (*XcursorShapeLoadImages_dylibloader_wrapper_xcursor)( unsigned int,const char*, int);
+extern Cursor (*XcursorShapeLoadCursor_dylibloader_wrapper_xcursor)( Display*, unsigned int);
+extern XcursorCursors* (*XcursorShapeLoadCursors_dylibloader_wrapper_xcursor)( Display*, unsigned int);
+extern Cursor (*XcursorTryShapeCursor_dylibloader_wrapper_xcursor)( Display*, Font, Font, unsigned int, unsigned int,const XColor*,const XColor*);
+extern void (*XcursorNoticeCreateBitmap_dylibloader_wrapper_xcursor)( Display*, Pixmap, unsigned int, unsigned int);
+extern void (*XcursorNoticePutBitmap_dylibloader_wrapper_xcursor)( Display*, Drawable, XImage*);
+extern Cursor (*XcursorTryShapeBitmapCursor_dylibloader_wrapper_xcursor)( Display*, Pixmap, Pixmap, XColor*, XColor*, unsigned int, unsigned int);
+extern void (*XcursorImageHash_dylibloader_wrapper_xcursor)( XImage*, unsigned char [16]);
+extern XcursorBool (*XcursorSupportsARGB_dylibloader_wrapper_xcursor)( Display*);
+extern XcursorBool (*XcursorSupportsAnim_dylibloader_wrapper_xcursor)( Display*);
+extern XcursorBool (*XcursorSetDefaultSize_dylibloader_wrapper_xcursor)( Display*, int);
+extern int (*XcursorGetDefaultSize_dylibloader_wrapper_xcursor)( Display*);
+extern XcursorBool (*XcursorSetTheme_dylibloader_wrapper_xcursor)( Display*,const char*);
+extern char* (*XcursorGetTheme_dylibloader_wrapper_xcursor)( Display*);
+extern XcursorBool (*XcursorGetThemeCore_dylibloader_wrapper_xcursor)( Display*);
+extern XcursorBool (*XcursorSetThemeCore_dylibloader_wrapper_xcursor)( Display*, XcursorBool);
+int initialize_xcursor(int verbose);
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/platform/linuxbsd/x11/dynwrappers/xext-so_wrap.c b/platform/linuxbsd/x11/dynwrappers/xext-so_wrap.c
new file mode 100644
index 0000000000..c8e87a6b85
--- /dev/null
+++ b/platform/linuxbsd/x11/dynwrappers/xext-so_wrap.c
@@ -0,0 +1,154 @@
+// 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-12-02 12:51:55
+// flags: ./generate-wrapper.py --include /usr/include/X11/extensions/Xext.h --sys-include <X11/extensions/Xext.h> --include /usr/include/X11/extensions/shape.h --sys-include <X11/extensions/shape.h> --soname libXext.so.6 --init-name xext --output-header xext-so_wrap.h --output-implementation xext-so_wrap.c
+//
+// NOTE: Generated from Xext 1.3.5.
+// This has been handpatched to workaround some issues with the generator that
+// will be eventually fixed. In this case, non-existent symbols inherited from
+// libX11, but absent in libXext.so.6, were removed and an include needed for
+// proper parsing was added (this had also to be temporarily added to the
+// original header, as dynload-wrapper would complain otherwise)
+#include <stdint.h>
+
+// HANDPATCH: Needed for a successful compilation.
+#include <X11/Xlib.h>
+
+#define XShapeQueryExtension XShapeQueryExtension_dylibloader_orig_xext
+#define XShapeQueryVersion XShapeQueryVersion_dylibloader_orig_xext
+#define XShapeCombineRegion XShapeCombineRegion_dylibloader_orig_xext
+#define XShapeCombineRectangles XShapeCombineRectangles_dylibloader_orig_xext
+#define XShapeCombineMask XShapeCombineMask_dylibloader_orig_xext
+#define XShapeCombineShape XShapeCombineShape_dylibloader_orig_xext
+#define XShapeOffsetShape XShapeOffsetShape_dylibloader_orig_xext
+#define XShapeQueryExtents XShapeQueryExtents_dylibloader_orig_xext
+#define XShapeSelectInput XShapeSelectInput_dylibloader_orig_xext
+#define XShapeInputSelected XShapeInputSelected_dylibloader_orig_xext
+#define XShapeGetRectangles XShapeGetRectangles_dylibloader_orig_xext
+#include <X11/extensions/Xext.h>
+#include <X11/extensions/shape.h>
+#undef XShapeQueryExtension
+#undef XShapeQueryVersion
+#undef XShapeCombineRegion
+#undef XShapeCombineRectangles
+#undef XShapeCombineMask
+#undef XShapeCombineShape
+#undef XShapeOffsetShape
+#undef XShapeQueryExtents
+#undef XShapeSelectInput
+#undef XShapeInputSelected
+#undef XShapeGetRectangles
+#include <dlfcn.h>
+#include <stdio.h>
+int (*XShapeQueryExtension_dylibloader_wrapper_xext)( Display*, int*, int*);
+int (*XShapeQueryVersion_dylibloader_wrapper_xext)( Display*, int*, int*);
+void (*XShapeCombineRegion_dylibloader_wrapper_xext)( Display*, Window, int, int, int, Region, int);
+void (*XShapeCombineRectangles_dylibloader_wrapper_xext)( Display*, Window, int, int, int, XRectangle*, int, int, int);
+void (*XShapeCombineMask_dylibloader_wrapper_xext)( Display*, Window, int, int, int, Pixmap, int);
+void (*XShapeCombineShape_dylibloader_wrapper_xext)( Display*, Window, int, int, int, Window, int, int);
+void (*XShapeOffsetShape_dylibloader_wrapper_xext)( Display*, Window, int, int, int);
+int (*XShapeQueryExtents_dylibloader_wrapper_xext)( Display*, Window, int*, int*, int*, unsigned int*, unsigned int*, int*, int*, int*, unsigned int*, unsigned int*);
+void (*XShapeSelectInput_dylibloader_wrapper_xext)( Display*, Window, unsigned long);
+unsigned long (*XShapeInputSelected_dylibloader_wrapper_xext)( Display*, Window);
+XRectangle* (*XShapeGetRectangles_dylibloader_wrapper_xext)( Display*, Window, int, int*, int*);
+int initialize_xext(int verbose) {
+ void *handle;
+ char *error;
+ handle = dlopen("libXext.so.6", RTLD_LAZY);
+ if (!handle) {
+ if (verbose) {
+ fprintf(stderr, "%s\n", dlerror());
+ }
+ return(1);
+ }
+ dlerror();
+// XShapeQueryExtension
+ *(void **) (&XShapeQueryExtension_dylibloader_wrapper_xext) = dlsym(handle, "XShapeQueryExtension");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XShapeQueryVersion
+ *(void **) (&XShapeQueryVersion_dylibloader_wrapper_xext) = dlsym(handle, "XShapeQueryVersion");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XShapeCombineRegion
+ *(void **) (&XShapeCombineRegion_dylibloader_wrapper_xext) = dlsym(handle, "XShapeCombineRegion");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XShapeCombineRectangles
+ *(void **) (&XShapeCombineRectangles_dylibloader_wrapper_xext) = dlsym(handle, "XShapeCombineRectangles");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XShapeCombineMask
+ *(void **) (&XShapeCombineMask_dylibloader_wrapper_xext) = dlsym(handle, "XShapeCombineMask");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XShapeCombineShape
+ *(void **) (&XShapeCombineShape_dylibloader_wrapper_xext) = dlsym(handle, "XShapeCombineShape");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XShapeOffsetShape
+ *(void **) (&XShapeOffsetShape_dylibloader_wrapper_xext) = dlsym(handle, "XShapeOffsetShape");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XShapeQueryExtents
+ *(void **) (&XShapeQueryExtents_dylibloader_wrapper_xext) = dlsym(handle, "XShapeQueryExtents");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XShapeSelectInput
+ *(void **) (&XShapeSelectInput_dylibloader_wrapper_xext) = dlsym(handle, "XShapeSelectInput");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XShapeInputSelected
+ *(void **) (&XShapeInputSelected_dylibloader_wrapper_xext) = dlsym(handle, "XShapeInputSelected");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XShapeGetRectangles
+ *(void **) (&XShapeGetRectangles_dylibloader_wrapper_xext) = dlsym(handle, "XShapeGetRectangles");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+return 0;
+}
diff --git a/platform/linuxbsd/x11/dynwrappers/xext-so_wrap.h b/platform/linuxbsd/x11/dynwrappers/xext-so_wrap.h
new file mode 100644
index 0000000000..aee92b593e
--- /dev/null
+++ b/platform/linuxbsd/x11/dynwrappers/xext-so_wrap.h
@@ -0,0 +1,72 @@
+#ifndef DYLIBLOAD_WRAPPER_XEXT
+#define DYLIBLOAD_WRAPPER_XEXT
+// 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-12-02 12:51:55
+// flags: ./generate-wrapper.py --include /usr/include/X11/extensions/Xext.h --sys-include <X11/extensions/Xext.h> --include /usr/include/X11/extensions/shape.h --sys-include <X11/extensions/shape.h> --soname libXext.so.6 --init-name xext --output-header xext-so_wrap.h --output-implementation xext-so_wrap.c
+//
+// NOTE: Generated from Xext 1.3.5.
+// This has been handpatched to workaround some issues with the generator that
+// will be eventually fixed. In this case, non-existent symbols inherited from
+// libX11, but absent in libXext.so.6, were removed and an include needed for
+// proper parsing was added (this had also to be temporarily added to the
+// original header, as dynload-wrapper would complain otherwise)
+#include <stdint.h>
+
+// HANDPATCH: Needed for a successful compilation.
+#include <X11/Xlib.h>
+
+#define XShapeQueryExtension XShapeQueryExtension_dylibloader_orig_xext
+#define XShapeQueryVersion XShapeQueryVersion_dylibloader_orig_xext
+#define XShapeCombineRegion XShapeCombineRegion_dylibloader_orig_xext
+#define XShapeCombineRectangles XShapeCombineRectangles_dylibloader_orig_xext
+#define XShapeCombineMask XShapeCombineMask_dylibloader_orig_xext
+#define XShapeCombineShape XShapeCombineShape_dylibloader_orig_xext
+#define XShapeOffsetShape XShapeOffsetShape_dylibloader_orig_xext
+#define XShapeQueryExtents XShapeQueryExtents_dylibloader_orig_xext
+#define XShapeSelectInput XShapeSelectInput_dylibloader_orig_xext
+#define XShapeInputSelected XShapeInputSelected_dylibloader_orig_xext
+#define XShapeGetRectangles XShapeGetRectangles_dylibloader_orig_xext
+#include <X11/extensions/Xext.h>
+#include <X11/extensions/shape.h>
+#undef XShapeQueryExtension
+#undef XShapeQueryVersion
+#undef XShapeCombineRegion
+#undef XShapeCombineRectangles
+#undef XShapeCombineMask
+#undef XShapeCombineShape
+#undef XShapeOffsetShape
+#undef XShapeQueryExtents
+#undef XShapeSelectInput
+#undef XShapeInputSelected
+#undef XShapeGetRectangles
+#ifdef __cplusplus
+extern "C" {
+#endif
+#define XShapeQueryExtension XShapeQueryExtension_dylibloader_wrapper_xext
+#define XShapeQueryVersion XShapeQueryVersion_dylibloader_wrapper_xext
+#define XShapeCombineRegion XShapeCombineRegion_dylibloader_wrapper_xext
+#define XShapeCombineRectangles XShapeCombineRectangles_dylibloader_wrapper_xext
+#define XShapeCombineMask XShapeCombineMask_dylibloader_wrapper_xext
+#define XShapeCombineShape XShapeCombineShape_dylibloader_wrapper_xext
+#define XShapeOffsetShape XShapeOffsetShape_dylibloader_wrapper_xext
+#define XShapeQueryExtents XShapeQueryExtents_dylibloader_wrapper_xext
+#define XShapeSelectInput XShapeSelectInput_dylibloader_wrapper_xext
+#define XShapeInputSelected XShapeInputSelected_dylibloader_wrapper_xext
+#define XShapeGetRectangles XShapeGetRectangles_dylibloader_wrapper_xext
+extern int (*XShapeQueryExtension_dylibloader_wrapper_xext)( Display*, int*, int*);
+extern int (*XShapeQueryVersion_dylibloader_wrapper_xext)( Display*, int*, int*);
+extern void (*XShapeCombineRegion_dylibloader_wrapper_xext)( Display*, Window, int, int, int, Region, int);
+extern void (*XShapeCombineRectangles_dylibloader_wrapper_xext)( Display*, Window, int, int, int, XRectangle*, int, int, int);
+extern void (*XShapeCombineMask_dylibloader_wrapper_xext)( Display*, Window, int, int, int, Pixmap, int);
+extern void (*XShapeCombineShape_dylibloader_wrapper_xext)( Display*, Window, int, int, int, Window, int, int);
+extern void (*XShapeOffsetShape_dylibloader_wrapper_xext)( Display*, Window, int, int, int);
+extern int (*XShapeQueryExtents_dylibloader_wrapper_xext)( Display*, Window, int*, int*, int*, unsigned int*, unsigned int*, int*, int*, int*, unsigned int*, unsigned int*);
+extern void (*XShapeSelectInput_dylibloader_wrapper_xext)( Display*, Window, unsigned long);
+extern unsigned long (*XShapeInputSelected_dylibloader_wrapper_xext)( Display*, Window);
+extern XRectangle* (*XShapeGetRectangles_dylibloader_wrapper_xext)( Display*, Window, int, int*, int*);
+int initialize_xext(int verbose);
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/platform/linuxbsd/x11/dynwrappers/xinerama-so_wrap.c b/platform/linuxbsd/x11/dynwrappers/xinerama-so_wrap.c
new file mode 100644
index 0000000000..85ac80e3f2
--- /dev/null
+++ b/platform/linuxbsd/x11/dynwrappers/xinerama-so_wrap.c
@@ -0,0 +1,71 @@
+// 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-12-02 12:53:11
+// flags: ./generate-wrapper.py --include /usr/include/X11/extensions/Xinerama.h --sys-include <X11/extensions/Xinerama.h> --soname libXinerama.so.1 --init-name xinerama --output-header xinerama-so_wrap.h --output-implementation xinerama-so_wrap.c
+//
+// NOTE: Generated from Xinerama 1.1.4.
+// This has been handpatched to workaround some issues with the generator that
+// will be eventually fixed. In this case, non-existent symbols inherited from
+// libX11, but absent in libXinerama.so.1, were removed.
+#include <stdint.h>
+
+#define XineramaQueryExtension XineramaQueryExtension_dylibloader_orig_xinerama
+#define XineramaQueryVersion XineramaQueryVersion_dylibloader_orig_xinerama
+#define XineramaIsActive XineramaIsActive_dylibloader_orig_xinerama
+#define XineramaQueryScreens XineramaQueryScreens_dylibloader_orig_xinerama
+#include <X11/extensions/Xinerama.h>
+#undef XineramaQueryExtension
+#undef XineramaQueryVersion
+#undef XineramaIsActive
+#undef XineramaQueryScreens
+#include <dlfcn.h>
+#include <stdio.h>
+int (*XineramaQueryExtension_dylibloader_wrapper_xinerama)( Display*, int*, int*);
+int (*XineramaQueryVersion_dylibloader_wrapper_xinerama)( Display*, int*, int*);
+int (*XineramaIsActive_dylibloader_wrapper_xinerama)( Display*);
+XineramaScreenInfo* (*XineramaQueryScreens_dylibloader_wrapper_xinerama)( Display*, int*);
+int initialize_xinerama(int verbose) {
+ void *handle;
+ char *error;
+ handle = dlopen("libXinerama.so.1", RTLD_LAZY);
+ if (!handle) {
+ if (verbose) {
+ fprintf(stderr, "%s\n", dlerror());
+ }
+ return(1);
+ }
+ dlerror();
+// XineramaQueryExtension
+ *(void **) (&XineramaQueryExtension_dylibloader_wrapper_xinerama) = dlsym(handle, "XineramaQueryExtension");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XineramaQueryVersion
+ *(void **) (&XineramaQueryVersion_dylibloader_wrapper_xinerama) = dlsym(handle, "XineramaQueryVersion");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XineramaIsActive
+ *(void **) (&XineramaIsActive_dylibloader_wrapper_xinerama) = dlsym(handle, "XineramaIsActive");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XineramaQueryScreens
+ *(void **) (&XineramaQueryScreens_dylibloader_wrapper_xinerama) = dlsym(handle, "XineramaQueryScreens");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+return 0;
+}
diff --git a/platform/linuxbsd/x11/dynwrappers/xinerama-so_wrap.h b/platform/linuxbsd/x11/dynwrappers/xinerama-so_wrap.h
new file mode 100644
index 0000000000..9139421cd6
--- /dev/null
+++ b/platform/linuxbsd/x11/dynwrappers/xinerama-so_wrap.h
@@ -0,0 +1,38 @@
+#ifndef DYLIBLOAD_WRAPPER_XINERAMA
+#define DYLIBLOAD_WRAPPER_XINERAMA
+// 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-12-02 12:53:11
+// flags: ./generate-wrapper.py --include /usr/include/X11/extensions/Xinerama.h --sys-include <X11/extensions/Xinerama.h> --soname libXinerama.so.1 --init-name xinerama --output-header xinerama-so_wrap.h --output-implementation xinerama-so_wrap.c
+//
+// NOTE: Generated from Xinerama 1.1.4.
+// This has been handpatched to workaround some issues with the generator that
+// will be eventually fixed. In this case, non-existent symbols inherited from
+// libX11, but absent in libXinerama.so.1, were removed.
+#include <stdint.h>
+
+#define XineramaQueryExtension XineramaQueryExtension_dylibloader_orig_xinerama
+#define XineramaQueryVersion XineramaQueryVersion_dylibloader_orig_xinerama
+#define XineramaIsActive XineramaIsActive_dylibloader_orig_xinerama
+#define XineramaQueryScreens XineramaQueryScreens_dylibloader_orig_xinerama
+#include <X11/extensions/Xinerama.h>
+#undef XineramaQueryExtension
+#undef XineramaQueryVersion
+#undef XineramaIsActive
+#undef XineramaQueryScreens
+#ifdef __cplusplus
+extern "C" {
+#endif
+#define XineramaQueryExtension XineramaQueryExtension_dylibloader_wrapper_xinerama
+#define XineramaQueryVersion XineramaQueryVersion_dylibloader_wrapper_xinerama
+#define XineramaIsActive XineramaIsActive_dylibloader_wrapper_xinerama
+#define XineramaQueryScreens XineramaQueryScreens_dylibloader_wrapper_xinerama
+extern int (*XineramaQueryExtension_dylibloader_wrapper_xinerama)( Display*, int*, int*);
+extern int (*XineramaQueryVersion_dylibloader_wrapper_xinerama)( Display*, int*, int*);
+extern int (*XineramaIsActive_dylibloader_wrapper_xinerama)( Display*);
+extern XineramaScreenInfo* (*XineramaQueryScreens_dylibloader_wrapper_xinerama)( Display*, int*);
+int initialize_xinerama(int verbose);
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/platform/linuxbsd/x11/dynwrappers/xinput2-so_wrap.c b/platform/linuxbsd/x11/dynwrappers/xinput2-so_wrap.c
new file mode 100644
index 0000000000..5f16bc6111
--- /dev/null
+++ b/platform/linuxbsd/x11/dynwrappers/xinput2-so_wrap.c
@@ -0,0 +1,401 @@
+// 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-12-02 12:54:10
+// flags: ./generate-wrapper.py --include /usr/include/X11/extensions/XInput2.h --sys-include <X11/extensions/XInput2.h> --soname libXi.so.6 --init-name xinput2 --output-header xinput2-so_wrap.h --output-implementation xinput2-so_wrap.c
+//
+// NOTE: Generated from Xi 1.7.10.
+// This has been handpatched to workaround some issues with the generator that
+// will be eventually fixed. In this case, non-existent symbols inherited from
+// libX11, liXext and libXfixes, but absent in libXi.so.6, were removed.
+#include <stdint.h>
+
+#define XIQueryPointer XIQueryPointer_dylibloader_orig_xinput2
+#define XIWarpPointer XIWarpPointer_dylibloader_orig_xinput2
+#define XIDefineCursor XIDefineCursor_dylibloader_orig_xinput2
+#define XIUndefineCursor XIUndefineCursor_dylibloader_orig_xinput2
+#define XIChangeHierarchy XIChangeHierarchy_dylibloader_orig_xinput2
+#define XISetClientPointer XISetClientPointer_dylibloader_orig_xinput2
+#define XIGetClientPointer XIGetClientPointer_dylibloader_orig_xinput2
+#define XISelectEvents XISelectEvents_dylibloader_orig_xinput2
+#define XIGetSelectedEvents XIGetSelectedEvents_dylibloader_orig_xinput2
+#define XIQueryVersion XIQueryVersion_dylibloader_orig_xinput2
+#define XIQueryDevice XIQueryDevice_dylibloader_orig_xinput2
+#define XISetFocus XISetFocus_dylibloader_orig_xinput2
+#define XIGetFocus XIGetFocus_dylibloader_orig_xinput2
+#define XIGrabDevice XIGrabDevice_dylibloader_orig_xinput2
+#define XIUngrabDevice XIUngrabDevice_dylibloader_orig_xinput2
+#define XIAllowEvents XIAllowEvents_dylibloader_orig_xinput2
+#define XIAllowTouchEvents XIAllowTouchEvents_dylibloader_orig_xinput2
+#define XIGrabButton XIGrabButton_dylibloader_orig_xinput2
+#define XIGrabKeycode XIGrabKeycode_dylibloader_orig_xinput2
+#define XIGrabEnter XIGrabEnter_dylibloader_orig_xinput2
+#define XIGrabFocusIn XIGrabFocusIn_dylibloader_orig_xinput2
+#define XIGrabTouchBegin XIGrabTouchBegin_dylibloader_orig_xinput2
+#define XIUngrabButton XIUngrabButton_dylibloader_orig_xinput2
+#define XIUngrabKeycode XIUngrabKeycode_dylibloader_orig_xinput2
+#define XIUngrabEnter XIUngrabEnter_dylibloader_orig_xinput2
+#define XIUngrabFocusIn XIUngrabFocusIn_dylibloader_orig_xinput2
+#define XIUngrabTouchBegin XIUngrabTouchBegin_dylibloader_orig_xinput2
+#define XIListProperties XIListProperties_dylibloader_orig_xinput2
+#define XIChangeProperty XIChangeProperty_dylibloader_orig_xinput2
+#define XIDeleteProperty XIDeleteProperty_dylibloader_orig_xinput2
+#define XIGetProperty XIGetProperty_dylibloader_orig_xinput2
+#define XIBarrierReleasePointers XIBarrierReleasePointers_dylibloader_orig_xinput2
+#define XIBarrierReleasePointer XIBarrierReleasePointer_dylibloader_orig_xinput2
+#define XIFreeDeviceInfo XIFreeDeviceInfo_dylibloader_orig_xinput2
+#include <X11/extensions/XInput2.h>
+#undef XIQueryPointer
+#undef XIWarpPointer
+#undef XIDefineCursor
+#undef XIUndefineCursor
+#undef XIChangeHierarchy
+#undef XISetClientPointer
+#undef XIGetClientPointer
+#undef XISelectEvents
+#undef XIGetSelectedEvents
+#undef XIQueryVersion
+#undef XIQueryDevice
+#undef XISetFocus
+#undef XIGetFocus
+#undef XIGrabDevice
+#undef XIUngrabDevice
+#undef XIAllowEvents
+#undef XIAllowTouchEvents
+#undef XIGrabButton
+#undef XIGrabKeycode
+#undef XIGrabEnter
+#undef XIGrabFocusIn
+#undef XIGrabTouchBegin
+#undef XIUngrabButton
+#undef XIUngrabKeycode
+#undef XIUngrabEnter
+#undef XIUngrabFocusIn
+#undef XIUngrabTouchBegin
+#undef XIListProperties
+#undef XIChangeProperty
+#undef XIDeleteProperty
+#undef XIGetProperty
+#undef XIBarrierReleasePointers
+#undef XIBarrierReleasePointer
+#undef XIFreeDeviceInfo
+#include <dlfcn.h>
+#include <stdio.h>
+int (*XIQueryPointer_dylibloader_wrapper_xinput2)( Display*, int, Window, Window*, Window*, double*, double*, double*, double*, XIButtonState*, XIModifierState*, XIGroupState*);
+int (*XIWarpPointer_dylibloader_wrapper_xinput2)( Display*, int, Window, Window, double, double, unsigned int, unsigned int, double, double);
+int (*XIDefineCursor_dylibloader_wrapper_xinput2)( Display*, int, Window, Cursor);
+int (*XIUndefineCursor_dylibloader_wrapper_xinput2)( Display*, int, Window);
+int (*XIChangeHierarchy_dylibloader_wrapper_xinput2)( Display*, XIAnyHierarchyChangeInfo*, int);
+int (*XISetClientPointer_dylibloader_wrapper_xinput2)( Display*, Window, int);
+int (*XIGetClientPointer_dylibloader_wrapper_xinput2)( Display*, Window, int*);
+int (*XISelectEvents_dylibloader_wrapper_xinput2)( Display*, Window, XIEventMask*, int);
+XIEventMask* (*XIGetSelectedEvents_dylibloader_wrapper_xinput2)( Display*, Window, int*);
+int (*XIQueryVersion_dylibloader_wrapper_xinput2)( Display*, int*, int*);
+XIDeviceInfo* (*XIQueryDevice_dylibloader_wrapper_xinput2)( Display*, int, int*);
+int (*XISetFocus_dylibloader_wrapper_xinput2)( Display*, int, Window, Time);
+int (*XIGetFocus_dylibloader_wrapper_xinput2)( Display*, int, Window*);
+int (*XIGrabDevice_dylibloader_wrapper_xinput2)( Display*, int, Window, Time, Cursor, int, int, int, XIEventMask*);
+int (*XIUngrabDevice_dylibloader_wrapper_xinput2)( Display*, int, Time);
+int (*XIAllowEvents_dylibloader_wrapper_xinput2)( Display*, int, int, Time);
+int (*XIAllowTouchEvents_dylibloader_wrapper_xinput2)( Display*, int, unsigned int, Window, int);
+int (*XIGrabButton_dylibloader_wrapper_xinput2)( Display*, int, int, Window, Cursor, int, int, int, XIEventMask*, int, XIGrabModifiers*);
+int (*XIGrabKeycode_dylibloader_wrapper_xinput2)( Display*, int, int, Window, int, int, int, XIEventMask*, int, XIGrabModifiers*);
+int (*XIGrabEnter_dylibloader_wrapper_xinput2)( Display*, int, Window, Cursor, int, int, int, XIEventMask*, int, XIGrabModifiers*);
+int (*XIGrabFocusIn_dylibloader_wrapper_xinput2)( Display*, int, Window, int, int, int, XIEventMask*, int, XIGrabModifiers*);
+int (*XIGrabTouchBegin_dylibloader_wrapper_xinput2)( Display*, int, Window, int, XIEventMask*, int, XIGrabModifiers*);
+int (*XIUngrabButton_dylibloader_wrapper_xinput2)( Display*, int, int, Window, int, XIGrabModifiers*);
+int (*XIUngrabKeycode_dylibloader_wrapper_xinput2)( Display*, int, int, Window, int, XIGrabModifiers*);
+int (*XIUngrabEnter_dylibloader_wrapper_xinput2)( Display*, int, Window, int, XIGrabModifiers*);
+int (*XIUngrabFocusIn_dylibloader_wrapper_xinput2)( Display*, int, Window, int, XIGrabModifiers*);
+int (*XIUngrabTouchBegin_dylibloader_wrapper_xinput2)( Display*, int, Window, int, XIGrabModifiers*);
+Atom* (*XIListProperties_dylibloader_wrapper_xinput2)( Display*, int, int*);
+void (*XIChangeProperty_dylibloader_wrapper_xinput2)( Display*, int, Atom, Atom, int, int, unsigned char*, int);
+void (*XIDeleteProperty_dylibloader_wrapper_xinput2)( Display*, int, Atom);
+int (*XIGetProperty_dylibloader_wrapper_xinput2)( Display*, int, Atom, long, long, int, Atom, Atom*, int*, unsigned long*, unsigned long*, unsigned char**);
+void (*XIBarrierReleasePointers_dylibloader_wrapper_xinput2)( Display*, XIBarrierReleasePointerInfo*, int);
+void (*XIBarrierReleasePointer_dylibloader_wrapper_xinput2)( Display*, int, PointerBarrier, BarrierEventID);
+void (*XIFreeDeviceInfo_dylibloader_wrapper_xinput2)( XIDeviceInfo*);
+int initialize_xinput2(int verbose) {
+ void *handle;
+ char *error;
+ handle = dlopen("libXi.so.6", RTLD_LAZY);
+ if (!handle) {
+ if (verbose) {
+ fprintf(stderr, "%s\n", dlerror());
+ }
+ return(1);
+ }
+ dlerror();
+// XIQueryPointer
+ *(void **) (&XIQueryPointer_dylibloader_wrapper_xinput2) = dlsym(handle, "XIQueryPointer");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XIWarpPointer
+ *(void **) (&XIWarpPointer_dylibloader_wrapper_xinput2) = dlsym(handle, "XIWarpPointer");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XIDefineCursor
+ *(void **) (&XIDefineCursor_dylibloader_wrapper_xinput2) = dlsym(handle, "XIDefineCursor");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XIUndefineCursor
+ *(void **) (&XIUndefineCursor_dylibloader_wrapper_xinput2) = dlsym(handle, "XIUndefineCursor");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XIChangeHierarchy
+ *(void **) (&XIChangeHierarchy_dylibloader_wrapper_xinput2) = dlsym(handle, "XIChangeHierarchy");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XISetClientPointer
+ *(void **) (&XISetClientPointer_dylibloader_wrapper_xinput2) = dlsym(handle, "XISetClientPointer");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XIGetClientPointer
+ *(void **) (&XIGetClientPointer_dylibloader_wrapper_xinput2) = dlsym(handle, "XIGetClientPointer");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XISelectEvents
+ *(void **) (&XISelectEvents_dylibloader_wrapper_xinput2) = dlsym(handle, "XISelectEvents");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XIGetSelectedEvents
+ *(void **) (&XIGetSelectedEvents_dylibloader_wrapper_xinput2) = dlsym(handle, "XIGetSelectedEvents");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XIQueryVersion
+ *(void **) (&XIQueryVersion_dylibloader_wrapper_xinput2) = dlsym(handle, "XIQueryVersion");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XIQueryDevice
+ *(void **) (&XIQueryDevice_dylibloader_wrapper_xinput2) = dlsym(handle, "XIQueryDevice");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XISetFocus
+ *(void **) (&XISetFocus_dylibloader_wrapper_xinput2) = dlsym(handle, "XISetFocus");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XIGetFocus
+ *(void **) (&XIGetFocus_dylibloader_wrapper_xinput2) = dlsym(handle, "XIGetFocus");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XIGrabDevice
+ *(void **) (&XIGrabDevice_dylibloader_wrapper_xinput2) = dlsym(handle, "XIGrabDevice");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XIUngrabDevice
+ *(void **) (&XIUngrabDevice_dylibloader_wrapper_xinput2) = dlsym(handle, "XIUngrabDevice");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XIAllowEvents
+ *(void **) (&XIAllowEvents_dylibloader_wrapper_xinput2) = dlsym(handle, "XIAllowEvents");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XIAllowTouchEvents
+ *(void **) (&XIAllowTouchEvents_dylibloader_wrapper_xinput2) = dlsym(handle, "XIAllowTouchEvents");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XIGrabButton
+ *(void **) (&XIGrabButton_dylibloader_wrapper_xinput2) = dlsym(handle, "XIGrabButton");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XIGrabKeycode
+ *(void **) (&XIGrabKeycode_dylibloader_wrapper_xinput2) = dlsym(handle, "XIGrabKeycode");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XIGrabEnter
+ *(void **) (&XIGrabEnter_dylibloader_wrapper_xinput2) = dlsym(handle, "XIGrabEnter");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XIGrabFocusIn
+ *(void **) (&XIGrabFocusIn_dylibloader_wrapper_xinput2) = dlsym(handle, "XIGrabFocusIn");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XIGrabTouchBegin
+ *(void **) (&XIGrabTouchBegin_dylibloader_wrapper_xinput2) = dlsym(handle, "XIGrabTouchBegin");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XIUngrabButton
+ *(void **) (&XIUngrabButton_dylibloader_wrapper_xinput2) = dlsym(handle, "XIUngrabButton");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XIUngrabKeycode
+ *(void **) (&XIUngrabKeycode_dylibloader_wrapper_xinput2) = dlsym(handle, "XIUngrabKeycode");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XIUngrabEnter
+ *(void **) (&XIUngrabEnter_dylibloader_wrapper_xinput2) = dlsym(handle, "XIUngrabEnter");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XIUngrabFocusIn
+ *(void **) (&XIUngrabFocusIn_dylibloader_wrapper_xinput2) = dlsym(handle, "XIUngrabFocusIn");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XIUngrabTouchBegin
+ *(void **) (&XIUngrabTouchBegin_dylibloader_wrapper_xinput2) = dlsym(handle, "XIUngrabTouchBegin");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XIListProperties
+ *(void **) (&XIListProperties_dylibloader_wrapper_xinput2) = dlsym(handle, "XIListProperties");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XIChangeProperty
+ *(void **) (&XIChangeProperty_dylibloader_wrapper_xinput2) = dlsym(handle, "XIChangeProperty");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XIDeleteProperty
+ *(void **) (&XIDeleteProperty_dylibloader_wrapper_xinput2) = dlsym(handle, "XIDeleteProperty");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XIGetProperty
+ *(void **) (&XIGetProperty_dylibloader_wrapper_xinput2) = dlsym(handle, "XIGetProperty");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XIBarrierReleasePointers
+ *(void **) (&XIBarrierReleasePointers_dylibloader_wrapper_xinput2) = dlsym(handle, "XIBarrierReleasePointers");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XIBarrierReleasePointer
+ *(void **) (&XIBarrierReleasePointer_dylibloader_wrapper_xinput2) = dlsym(handle, "XIBarrierReleasePointer");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XIFreeDeviceInfo
+ *(void **) (&XIFreeDeviceInfo_dylibloader_wrapper_xinput2) = dlsym(handle, "XIFreeDeviceInfo");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+return 0;
+}
diff --git a/platform/linuxbsd/x11/dynwrappers/xinput2-so_wrap.h b/platform/linuxbsd/x11/dynwrappers/xinput2-so_wrap.h
new file mode 100644
index 0000000000..ecb7aa5048
--- /dev/null
+++ b/platform/linuxbsd/x11/dynwrappers/xinput2-so_wrap.h
@@ -0,0 +1,158 @@
+#ifndef DYLIBLOAD_WRAPPER_XINPUT2
+#define DYLIBLOAD_WRAPPER_XINPUT2
+// 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-12-02 12:54:10
+// flags: ./generate-wrapper.py --include /usr/include/X11/extensions/XInput2.h --sys-include <X11/extensions/XInput2.h> --soname libXi.so.6 --init-name xinput2 --output-header xinput2-so_wrap.h --output-implementation xinput2-so_wrap.c
+//
+// NOTE: Generated from Xi 1.7.10.
+// This has been handpatched to workaround some issues with the generator that
+// will be eventually fixed. In this case, non-existent symbols inherited from
+// libX11, liXext and libXfixes, but absent in libXi.so.6, were removed.
+#include <stdint.h>
+
+#define XIQueryPointer XIQueryPointer_dylibloader_orig_xinput2
+#define XIWarpPointer XIWarpPointer_dylibloader_orig_xinput2
+#define XIDefineCursor XIDefineCursor_dylibloader_orig_xinput2
+#define XIUndefineCursor XIUndefineCursor_dylibloader_orig_xinput2
+#define XIChangeHierarchy XIChangeHierarchy_dylibloader_orig_xinput2
+#define XISetClientPointer XISetClientPointer_dylibloader_orig_xinput2
+#define XIGetClientPointer XIGetClientPointer_dylibloader_orig_xinput2
+#define XISelectEvents XISelectEvents_dylibloader_orig_xinput2
+#define XIGetSelectedEvents XIGetSelectedEvents_dylibloader_orig_xinput2
+#define XIQueryVersion XIQueryVersion_dylibloader_orig_xinput2
+#define XIQueryDevice XIQueryDevice_dylibloader_orig_xinput2
+#define XISetFocus XISetFocus_dylibloader_orig_xinput2
+#define XIGetFocus XIGetFocus_dylibloader_orig_xinput2
+#define XIGrabDevice XIGrabDevice_dylibloader_orig_xinput2
+#define XIUngrabDevice XIUngrabDevice_dylibloader_orig_xinput2
+#define XIAllowEvents XIAllowEvents_dylibloader_orig_xinput2
+#define XIAllowTouchEvents XIAllowTouchEvents_dylibloader_orig_xinput2
+#define XIGrabButton XIGrabButton_dylibloader_orig_xinput2
+#define XIGrabKeycode XIGrabKeycode_dylibloader_orig_xinput2
+#define XIGrabEnter XIGrabEnter_dylibloader_orig_xinput2
+#define XIGrabFocusIn XIGrabFocusIn_dylibloader_orig_xinput2
+#define XIGrabTouchBegin XIGrabTouchBegin_dylibloader_orig_xinput2
+#define XIUngrabButton XIUngrabButton_dylibloader_orig_xinput2
+#define XIUngrabKeycode XIUngrabKeycode_dylibloader_orig_xinput2
+#define XIUngrabEnter XIUngrabEnter_dylibloader_orig_xinput2
+#define XIUngrabFocusIn XIUngrabFocusIn_dylibloader_orig_xinput2
+#define XIUngrabTouchBegin XIUngrabTouchBegin_dylibloader_orig_xinput2
+#define XIListProperties XIListProperties_dylibloader_orig_xinput2
+#define XIChangeProperty XIChangeProperty_dylibloader_orig_xinput2
+#define XIDeleteProperty XIDeleteProperty_dylibloader_orig_xinput2
+#define XIGetProperty XIGetProperty_dylibloader_orig_xinput2
+#define XIBarrierReleasePointers XIBarrierReleasePointers_dylibloader_orig_xinput2
+#define XIBarrierReleasePointer XIBarrierReleasePointer_dylibloader_orig_xinput2
+#define XIFreeDeviceInfo XIFreeDeviceInfo_dylibloader_orig_xinput2
+#include <X11/extensions/XInput2.h>
+#undef XIQueryPointer
+#undef XIWarpPointer
+#undef XIDefineCursor
+#undef XIUndefineCursor
+#undef XIChangeHierarchy
+#undef XISetClientPointer
+#undef XIGetClientPointer
+#undef XISelectEvents
+#undef XIGetSelectedEvents
+#undef XIQueryVersion
+#undef XIQueryDevice
+#undef XISetFocus
+#undef XIGetFocus
+#undef XIGrabDevice
+#undef XIUngrabDevice
+#undef XIAllowEvents
+#undef XIAllowTouchEvents
+#undef XIGrabButton
+#undef XIGrabKeycode
+#undef XIGrabEnter
+#undef XIGrabFocusIn
+#undef XIGrabTouchBegin
+#undef XIUngrabButton
+#undef XIUngrabKeycode
+#undef XIUngrabEnter
+#undef XIUngrabFocusIn
+#undef XIUngrabTouchBegin
+#undef XIListProperties
+#undef XIChangeProperty
+#undef XIDeleteProperty
+#undef XIGetProperty
+#undef XIBarrierReleasePointers
+#undef XIBarrierReleasePointer
+#undef XIFreeDeviceInfo
+#ifdef __cplusplus
+extern "C" {
+#endif
+#define XIQueryPointer XIQueryPointer_dylibloader_wrapper_xinput2
+#define XIWarpPointer XIWarpPointer_dylibloader_wrapper_xinput2
+#define XIDefineCursor XIDefineCursor_dylibloader_wrapper_xinput2
+#define XIUndefineCursor XIUndefineCursor_dylibloader_wrapper_xinput2
+#define XIChangeHierarchy XIChangeHierarchy_dylibloader_wrapper_xinput2
+#define XISetClientPointer XISetClientPointer_dylibloader_wrapper_xinput2
+#define XIGetClientPointer XIGetClientPointer_dylibloader_wrapper_xinput2
+#define XISelectEvents XISelectEvents_dylibloader_wrapper_xinput2
+#define XIGetSelectedEvents XIGetSelectedEvents_dylibloader_wrapper_xinput2
+#define XIQueryVersion XIQueryVersion_dylibloader_wrapper_xinput2
+#define XIQueryDevice XIQueryDevice_dylibloader_wrapper_xinput2
+#define XISetFocus XISetFocus_dylibloader_wrapper_xinput2
+#define XIGetFocus XIGetFocus_dylibloader_wrapper_xinput2
+#define XIGrabDevice XIGrabDevice_dylibloader_wrapper_xinput2
+#define XIUngrabDevice XIUngrabDevice_dylibloader_wrapper_xinput2
+#define XIAllowEvents XIAllowEvents_dylibloader_wrapper_xinput2
+#define XIAllowTouchEvents XIAllowTouchEvents_dylibloader_wrapper_xinput2
+#define XIGrabButton XIGrabButton_dylibloader_wrapper_xinput2
+#define XIGrabKeycode XIGrabKeycode_dylibloader_wrapper_xinput2
+#define XIGrabEnter XIGrabEnter_dylibloader_wrapper_xinput2
+#define XIGrabFocusIn XIGrabFocusIn_dylibloader_wrapper_xinput2
+#define XIGrabTouchBegin XIGrabTouchBegin_dylibloader_wrapper_xinput2
+#define XIUngrabButton XIUngrabButton_dylibloader_wrapper_xinput2
+#define XIUngrabKeycode XIUngrabKeycode_dylibloader_wrapper_xinput2
+#define XIUngrabEnter XIUngrabEnter_dylibloader_wrapper_xinput2
+#define XIUngrabFocusIn XIUngrabFocusIn_dylibloader_wrapper_xinput2
+#define XIUngrabTouchBegin XIUngrabTouchBegin_dylibloader_wrapper_xinput2
+#define XIListProperties XIListProperties_dylibloader_wrapper_xinput2
+#define XIChangeProperty XIChangeProperty_dylibloader_wrapper_xinput2
+#define XIDeleteProperty XIDeleteProperty_dylibloader_wrapper_xinput2
+#define XIGetProperty XIGetProperty_dylibloader_wrapper_xinput2
+#define XIBarrierReleasePointers XIBarrierReleasePointers_dylibloader_wrapper_xinput2
+#define XIBarrierReleasePointer XIBarrierReleasePointer_dylibloader_wrapper_xinput2
+#define XIFreeDeviceInfo XIFreeDeviceInfo_dylibloader_wrapper_xinput2
+extern int (*XIQueryPointer_dylibloader_wrapper_xinput2)( Display*, int, Window, Window*, Window*, double*, double*, double*, double*, XIButtonState*, XIModifierState*, XIGroupState*);
+extern int (*XIWarpPointer_dylibloader_wrapper_xinput2)( Display*, int, Window, Window, double, double, unsigned int, unsigned int, double, double);
+extern int (*XIDefineCursor_dylibloader_wrapper_xinput2)( Display*, int, Window, Cursor);
+extern int (*XIUndefineCursor_dylibloader_wrapper_xinput2)( Display*, int, Window);
+extern int (*XIChangeHierarchy_dylibloader_wrapper_xinput2)( Display*, XIAnyHierarchyChangeInfo*, int);
+extern int (*XISetClientPointer_dylibloader_wrapper_xinput2)( Display*, Window, int);
+extern int (*XIGetClientPointer_dylibloader_wrapper_xinput2)( Display*, Window, int*);
+extern int (*XISelectEvents_dylibloader_wrapper_xinput2)( Display*, Window, XIEventMask*, int);
+extern XIEventMask* (*XIGetSelectedEvents_dylibloader_wrapper_xinput2)( Display*, Window, int*);
+extern int (*XIQueryVersion_dylibloader_wrapper_xinput2)( Display*, int*, int*);
+extern XIDeviceInfo* (*XIQueryDevice_dylibloader_wrapper_xinput2)( Display*, int, int*);
+extern int (*XISetFocus_dylibloader_wrapper_xinput2)( Display*, int, Window, Time);
+extern int (*XIGetFocus_dylibloader_wrapper_xinput2)( Display*, int, Window*);
+extern int (*XIGrabDevice_dylibloader_wrapper_xinput2)( Display*, int, Window, Time, Cursor, int, int, int, XIEventMask*);
+extern int (*XIUngrabDevice_dylibloader_wrapper_xinput2)( Display*, int, Time);
+extern int (*XIAllowEvents_dylibloader_wrapper_xinput2)( Display*, int, int, Time);
+extern int (*XIAllowTouchEvents_dylibloader_wrapper_xinput2)( Display*, int, unsigned int, Window, int);
+extern int (*XIGrabButton_dylibloader_wrapper_xinput2)( Display*, int, int, Window, Cursor, int, int, int, XIEventMask*, int, XIGrabModifiers*);
+extern int (*XIGrabKeycode_dylibloader_wrapper_xinput2)( Display*, int, int, Window, int, int, int, XIEventMask*, int, XIGrabModifiers*);
+extern int (*XIGrabEnter_dylibloader_wrapper_xinput2)( Display*, int, Window, Cursor, int, int, int, XIEventMask*, int, XIGrabModifiers*);
+extern int (*XIGrabFocusIn_dylibloader_wrapper_xinput2)( Display*, int, Window, int, int, int, XIEventMask*, int, XIGrabModifiers*);
+extern int (*XIGrabTouchBegin_dylibloader_wrapper_xinput2)( Display*, int, Window, int, XIEventMask*, int, XIGrabModifiers*);
+extern int (*XIUngrabButton_dylibloader_wrapper_xinput2)( Display*, int, int, Window, int, XIGrabModifiers*);
+extern int (*XIUngrabKeycode_dylibloader_wrapper_xinput2)( Display*, int, int, Window, int, XIGrabModifiers*);
+extern int (*XIUngrabEnter_dylibloader_wrapper_xinput2)( Display*, int, Window, int, XIGrabModifiers*);
+extern int (*XIUngrabFocusIn_dylibloader_wrapper_xinput2)( Display*, int, Window, int, XIGrabModifiers*);
+extern int (*XIUngrabTouchBegin_dylibloader_wrapper_xinput2)( Display*, int, Window, int, XIGrabModifiers*);
+extern Atom* (*XIListProperties_dylibloader_wrapper_xinput2)( Display*, int, int*);
+extern void (*XIChangeProperty_dylibloader_wrapper_xinput2)( Display*, int, Atom, Atom, int, int, unsigned char*, int);
+extern void (*XIDeleteProperty_dylibloader_wrapper_xinput2)( Display*, int, Atom);
+extern int (*XIGetProperty_dylibloader_wrapper_xinput2)( Display*, int, Atom, long, long, int, Atom, Atom*, int*, unsigned long*, unsigned long*, unsigned char**);
+extern void (*XIBarrierReleasePointers_dylibloader_wrapper_xinput2)( Display*, XIBarrierReleasePointerInfo*, int);
+extern void (*XIBarrierReleasePointer_dylibloader_wrapper_xinput2)( Display*, int, PointerBarrier, BarrierEventID);
+extern void (*XIFreeDeviceInfo_dylibloader_wrapper_xinput2)( XIDeviceInfo*);
+int initialize_xinput2(int verbose);
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/platform/linuxbsd/x11/dynwrappers/xlib-so_wrap.c b/platform/linuxbsd/x11/dynwrappers/xlib-so_wrap.c
new file mode 100644
index 0000000000..12097a2987
--- /dev/null
+++ b/platform/linuxbsd/x11/dynwrappers/xlib-so_wrap.c
@@ -0,0 +1,6664 @@
+// 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-12-02 12:54:53
+// flags: ./generate-wrapper.py --include /usr/include/X11/Xlib.h --include /usr/include/X11/Xutil.h --include /usr/include/X11/XKBlib.h --sys-include <X11/Xlib.h> --sys-include <X11/Xutil.h> --sys-include <X11/XKBlib.h> --soname libX11.so.6 --init-name xlib --omit-prefix XkbGetDeviceIndicatorState --omit-prefix XkbAddSymInterpret --output-header xlib-so_wrap.h --output-implementation xlib-so_wrap.c
+//
+// NOTE: Generated from Xlib 1.6.9.
+// This has been handpatched to workaround some issues with the generator that
+// will be eventually fixed. In this case, the type of the third argument of
+// XIfEvent, XPeekIfEvent and XCheckIfEvent had to be fixed as it wasn't parsed
+// fully (it's a Bool function pointer, but it was just being parsed as an int
+// pointer).
+#include <stdint.h>
+
+#define _Xmblen _Xmblen_dylibloader_orig_xlib
+#define XLoadQueryFont XLoadQueryFont_dylibloader_orig_xlib
+#define XQueryFont XQueryFont_dylibloader_orig_xlib
+#define XGetMotionEvents XGetMotionEvents_dylibloader_orig_xlib
+#define XDeleteModifiermapEntry XDeleteModifiermapEntry_dylibloader_orig_xlib
+#define XGetModifierMapping XGetModifierMapping_dylibloader_orig_xlib
+#define XInsertModifiermapEntry XInsertModifiermapEntry_dylibloader_orig_xlib
+#define XNewModifiermap XNewModifiermap_dylibloader_orig_xlib
+#define XCreateImage XCreateImage_dylibloader_orig_xlib
+#define XInitImage XInitImage_dylibloader_orig_xlib
+#define XGetImage XGetImage_dylibloader_orig_xlib
+#define XGetSubImage XGetSubImage_dylibloader_orig_xlib
+#define XOpenDisplay XOpenDisplay_dylibloader_orig_xlib
+#define XrmInitialize XrmInitialize_dylibloader_orig_xlib
+#define XFetchBytes XFetchBytes_dylibloader_orig_xlib
+#define XFetchBuffer XFetchBuffer_dylibloader_orig_xlib
+#define XGetAtomName XGetAtomName_dylibloader_orig_xlib
+#define XGetAtomNames XGetAtomNames_dylibloader_orig_xlib
+#define XGetDefault XGetDefault_dylibloader_orig_xlib
+#define XDisplayName XDisplayName_dylibloader_orig_xlib
+#define XKeysymToString XKeysymToString_dylibloader_orig_xlib
+#define XSynchronize XSynchronize_dylibloader_orig_xlib
+#define XSetAfterFunction XSetAfterFunction_dylibloader_orig_xlib
+#define XInternAtom XInternAtom_dylibloader_orig_xlib
+#define XInternAtoms XInternAtoms_dylibloader_orig_xlib
+#define XCopyColormapAndFree XCopyColormapAndFree_dylibloader_orig_xlib
+#define XCreateColormap XCreateColormap_dylibloader_orig_xlib
+#define XCreatePixmapCursor XCreatePixmapCursor_dylibloader_orig_xlib
+#define XCreateGlyphCursor XCreateGlyphCursor_dylibloader_orig_xlib
+#define XCreateFontCursor XCreateFontCursor_dylibloader_orig_xlib
+#define XLoadFont XLoadFont_dylibloader_orig_xlib
+#define XCreateGC XCreateGC_dylibloader_orig_xlib
+#define XGContextFromGC XGContextFromGC_dylibloader_orig_xlib
+#define XFlushGC XFlushGC_dylibloader_orig_xlib
+#define XCreatePixmap XCreatePixmap_dylibloader_orig_xlib
+#define XCreateBitmapFromData XCreateBitmapFromData_dylibloader_orig_xlib
+#define XCreatePixmapFromBitmapData XCreatePixmapFromBitmapData_dylibloader_orig_xlib
+#define XCreateSimpleWindow XCreateSimpleWindow_dylibloader_orig_xlib
+#define XGetSelectionOwner XGetSelectionOwner_dylibloader_orig_xlib
+#define XCreateWindow XCreateWindow_dylibloader_orig_xlib
+#define XListInstalledColormaps XListInstalledColormaps_dylibloader_orig_xlib
+#define XListFonts XListFonts_dylibloader_orig_xlib
+#define XListFontsWithInfo XListFontsWithInfo_dylibloader_orig_xlib
+#define XGetFontPath XGetFontPath_dylibloader_orig_xlib
+#define XListExtensions XListExtensions_dylibloader_orig_xlib
+#define XListProperties XListProperties_dylibloader_orig_xlib
+#define XListHosts XListHosts_dylibloader_orig_xlib
+#define XKeycodeToKeysym XKeycodeToKeysym_dylibloader_orig_xlib
+#define XLookupKeysym XLookupKeysym_dylibloader_orig_xlib
+#define XGetKeyboardMapping XGetKeyboardMapping_dylibloader_orig_xlib
+#define XStringToKeysym XStringToKeysym_dylibloader_orig_xlib
+#define XMaxRequestSize XMaxRequestSize_dylibloader_orig_xlib
+#define XExtendedMaxRequestSize XExtendedMaxRequestSize_dylibloader_orig_xlib
+#define XResourceManagerString XResourceManagerString_dylibloader_orig_xlib
+#define XScreenResourceString XScreenResourceString_dylibloader_orig_xlib
+#define XDisplayMotionBufferSize XDisplayMotionBufferSize_dylibloader_orig_xlib
+#define XVisualIDFromVisual XVisualIDFromVisual_dylibloader_orig_xlib
+#define XInitThreads XInitThreads_dylibloader_orig_xlib
+#define XLockDisplay XLockDisplay_dylibloader_orig_xlib
+#define XUnlockDisplay XUnlockDisplay_dylibloader_orig_xlib
+#define XInitExtension XInitExtension_dylibloader_orig_xlib
+#define XAddExtension XAddExtension_dylibloader_orig_xlib
+#define XFindOnExtensionList XFindOnExtensionList_dylibloader_orig_xlib
+#define XEHeadOfExtensionList XEHeadOfExtensionList_dylibloader_orig_xlib
+#define XRootWindow XRootWindow_dylibloader_orig_xlib
+#define XDefaultRootWindow XDefaultRootWindow_dylibloader_orig_xlib
+#define XRootWindowOfScreen XRootWindowOfScreen_dylibloader_orig_xlib
+#define XDefaultVisual XDefaultVisual_dylibloader_orig_xlib
+#define XDefaultVisualOfScreen XDefaultVisualOfScreen_dylibloader_orig_xlib
+#define XDefaultGC XDefaultGC_dylibloader_orig_xlib
+#define XDefaultGCOfScreen XDefaultGCOfScreen_dylibloader_orig_xlib
+#define XBlackPixel XBlackPixel_dylibloader_orig_xlib
+#define XWhitePixel XWhitePixel_dylibloader_orig_xlib
+#define XAllPlanes XAllPlanes_dylibloader_orig_xlib
+#define XBlackPixelOfScreen XBlackPixelOfScreen_dylibloader_orig_xlib
+#define XWhitePixelOfScreen XWhitePixelOfScreen_dylibloader_orig_xlib
+#define XNextRequest XNextRequest_dylibloader_orig_xlib
+#define XLastKnownRequestProcessed XLastKnownRequestProcessed_dylibloader_orig_xlib
+#define XServerVendor XServerVendor_dylibloader_orig_xlib
+#define XDisplayString XDisplayString_dylibloader_orig_xlib
+#define XDefaultColormap XDefaultColormap_dylibloader_orig_xlib
+#define XDefaultColormapOfScreen XDefaultColormapOfScreen_dylibloader_orig_xlib
+#define XDisplayOfScreen XDisplayOfScreen_dylibloader_orig_xlib
+#define XScreenOfDisplay XScreenOfDisplay_dylibloader_orig_xlib
+#define XDefaultScreenOfDisplay XDefaultScreenOfDisplay_dylibloader_orig_xlib
+#define XEventMaskOfScreen XEventMaskOfScreen_dylibloader_orig_xlib
+#define XScreenNumberOfScreen XScreenNumberOfScreen_dylibloader_orig_xlib
+#define XSetErrorHandler XSetErrorHandler_dylibloader_orig_xlib
+#define XSetIOErrorHandler XSetIOErrorHandler_dylibloader_orig_xlib
+#define XListPixmapFormats XListPixmapFormats_dylibloader_orig_xlib
+#define XListDepths XListDepths_dylibloader_orig_xlib
+#define XReconfigureWMWindow XReconfigureWMWindow_dylibloader_orig_xlib
+#define XGetWMProtocols XGetWMProtocols_dylibloader_orig_xlib
+#define XSetWMProtocols XSetWMProtocols_dylibloader_orig_xlib
+#define XIconifyWindow XIconifyWindow_dylibloader_orig_xlib
+#define XWithdrawWindow XWithdrawWindow_dylibloader_orig_xlib
+#define XGetCommand XGetCommand_dylibloader_orig_xlib
+#define XGetWMColormapWindows XGetWMColormapWindows_dylibloader_orig_xlib
+#define XSetWMColormapWindows XSetWMColormapWindows_dylibloader_orig_xlib
+#define XFreeStringList XFreeStringList_dylibloader_orig_xlib
+#define XSetTransientForHint XSetTransientForHint_dylibloader_orig_xlib
+#define XActivateScreenSaver XActivateScreenSaver_dylibloader_orig_xlib
+#define XAddHost XAddHost_dylibloader_orig_xlib
+#define XAddHosts XAddHosts_dylibloader_orig_xlib
+#define XAddToExtensionList XAddToExtensionList_dylibloader_orig_xlib
+#define XAddToSaveSet XAddToSaveSet_dylibloader_orig_xlib
+#define XAllocColor XAllocColor_dylibloader_orig_xlib
+#define XAllocColorCells XAllocColorCells_dylibloader_orig_xlib
+#define XAllocColorPlanes XAllocColorPlanes_dylibloader_orig_xlib
+#define XAllocNamedColor XAllocNamedColor_dylibloader_orig_xlib
+#define XAllowEvents XAllowEvents_dylibloader_orig_xlib
+#define XAutoRepeatOff XAutoRepeatOff_dylibloader_orig_xlib
+#define XAutoRepeatOn XAutoRepeatOn_dylibloader_orig_xlib
+#define XBell XBell_dylibloader_orig_xlib
+#define XBitmapBitOrder XBitmapBitOrder_dylibloader_orig_xlib
+#define XBitmapPad XBitmapPad_dylibloader_orig_xlib
+#define XBitmapUnit XBitmapUnit_dylibloader_orig_xlib
+#define XCellsOfScreen XCellsOfScreen_dylibloader_orig_xlib
+#define XChangeActivePointerGrab XChangeActivePointerGrab_dylibloader_orig_xlib
+#define XChangeGC XChangeGC_dylibloader_orig_xlib
+#define XChangeKeyboardControl XChangeKeyboardControl_dylibloader_orig_xlib
+#define XChangeKeyboardMapping XChangeKeyboardMapping_dylibloader_orig_xlib
+#define XChangePointerControl XChangePointerControl_dylibloader_orig_xlib
+#define XChangeProperty XChangeProperty_dylibloader_orig_xlib
+#define XChangeSaveSet XChangeSaveSet_dylibloader_orig_xlib
+#define XChangeWindowAttributes XChangeWindowAttributes_dylibloader_orig_xlib
+#define XCheckIfEvent XCheckIfEvent_dylibloader_orig_xlib
+#define XCheckMaskEvent XCheckMaskEvent_dylibloader_orig_xlib
+#define XCheckTypedEvent XCheckTypedEvent_dylibloader_orig_xlib
+#define XCheckTypedWindowEvent XCheckTypedWindowEvent_dylibloader_orig_xlib
+#define XCheckWindowEvent XCheckWindowEvent_dylibloader_orig_xlib
+#define XCirculateSubwindows XCirculateSubwindows_dylibloader_orig_xlib
+#define XCirculateSubwindowsDown XCirculateSubwindowsDown_dylibloader_orig_xlib
+#define XCirculateSubwindowsUp XCirculateSubwindowsUp_dylibloader_orig_xlib
+#define XClearArea XClearArea_dylibloader_orig_xlib
+#define XClearWindow XClearWindow_dylibloader_orig_xlib
+#define XCloseDisplay XCloseDisplay_dylibloader_orig_xlib
+#define XConfigureWindow XConfigureWindow_dylibloader_orig_xlib
+#define XConnectionNumber XConnectionNumber_dylibloader_orig_xlib
+#define XConvertSelection XConvertSelection_dylibloader_orig_xlib
+#define XCopyArea XCopyArea_dylibloader_orig_xlib
+#define XCopyGC XCopyGC_dylibloader_orig_xlib
+#define XCopyPlane XCopyPlane_dylibloader_orig_xlib
+#define XDefaultDepth XDefaultDepth_dylibloader_orig_xlib
+#define XDefaultDepthOfScreen XDefaultDepthOfScreen_dylibloader_orig_xlib
+#define XDefaultScreen XDefaultScreen_dylibloader_orig_xlib
+#define XDefineCursor XDefineCursor_dylibloader_orig_xlib
+#define XDeleteProperty XDeleteProperty_dylibloader_orig_xlib
+#define XDestroyWindow XDestroyWindow_dylibloader_orig_xlib
+#define XDestroySubwindows XDestroySubwindows_dylibloader_orig_xlib
+#define XDoesBackingStore XDoesBackingStore_dylibloader_orig_xlib
+#define XDoesSaveUnders XDoesSaveUnders_dylibloader_orig_xlib
+#define XDisableAccessControl XDisableAccessControl_dylibloader_orig_xlib
+#define XDisplayCells XDisplayCells_dylibloader_orig_xlib
+#define XDisplayHeight XDisplayHeight_dylibloader_orig_xlib
+#define XDisplayHeightMM XDisplayHeightMM_dylibloader_orig_xlib
+#define XDisplayKeycodes XDisplayKeycodes_dylibloader_orig_xlib
+#define XDisplayPlanes XDisplayPlanes_dylibloader_orig_xlib
+#define XDisplayWidth XDisplayWidth_dylibloader_orig_xlib
+#define XDisplayWidthMM XDisplayWidthMM_dylibloader_orig_xlib
+#define XDrawArc XDrawArc_dylibloader_orig_xlib
+#define XDrawArcs XDrawArcs_dylibloader_orig_xlib
+#define XDrawImageString XDrawImageString_dylibloader_orig_xlib
+#define XDrawImageString16 XDrawImageString16_dylibloader_orig_xlib
+#define XDrawLine XDrawLine_dylibloader_orig_xlib
+#define XDrawLines XDrawLines_dylibloader_orig_xlib
+#define XDrawPoint XDrawPoint_dylibloader_orig_xlib
+#define XDrawPoints XDrawPoints_dylibloader_orig_xlib
+#define XDrawRectangle XDrawRectangle_dylibloader_orig_xlib
+#define XDrawRectangles XDrawRectangles_dylibloader_orig_xlib
+#define XDrawSegments XDrawSegments_dylibloader_orig_xlib
+#define XDrawString XDrawString_dylibloader_orig_xlib
+#define XDrawString16 XDrawString16_dylibloader_orig_xlib
+#define XDrawText XDrawText_dylibloader_orig_xlib
+#define XDrawText16 XDrawText16_dylibloader_orig_xlib
+#define XEnableAccessControl XEnableAccessControl_dylibloader_orig_xlib
+#define XEventsQueued XEventsQueued_dylibloader_orig_xlib
+#define XFetchName XFetchName_dylibloader_orig_xlib
+#define XFillArc XFillArc_dylibloader_orig_xlib
+#define XFillArcs XFillArcs_dylibloader_orig_xlib
+#define XFillPolygon XFillPolygon_dylibloader_orig_xlib
+#define XFillRectangle XFillRectangle_dylibloader_orig_xlib
+#define XFillRectangles XFillRectangles_dylibloader_orig_xlib
+#define XFlush XFlush_dylibloader_orig_xlib
+#define XForceScreenSaver XForceScreenSaver_dylibloader_orig_xlib
+#define XFree XFree_dylibloader_orig_xlib
+#define XFreeColormap XFreeColormap_dylibloader_orig_xlib
+#define XFreeColors XFreeColors_dylibloader_orig_xlib
+#define XFreeCursor XFreeCursor_dylibloader_orig_xlib
+#define XFreeExtensionList XFreeExtensionList_dylibloader_orig_xlib
+#define XFreeFont XFreeFont_dylibloader_orig_xlib
+#define XFreeFontInfo XFreeFontInfo_dylibloader_orig_xlib
+#define XFreeFontNames XFreeFontNames_dylibloader_orig_xlib
+#define XFreeFontPath XFreeFontPath_dylibloader_orig_xlib
+#define XFreeGC XFreeGC_dylibloader_orig_xlib
+#define XFreeModifiermap XFreeModifiermap_dylibloader_orig_xlib
+#define XFreePixmap XFreePixmap_dylibloader_orig_xlib
+#define XGeometry XGeometry_dylibloader_orig_xlib
+#define XGetErrorDatabaseText XGetErrorDatabaseText_dylibloader_orig_xlib
+#define XGetErrorText XGetErrorText_dylibloader_orig_xlib
+#define XGetFontProperty XGetFontProperty_dylibloader_orig_xlib
+#define XGetGCValues XGetGCValues_dylibloader_orig_xlib
+#define XGetGeometry XGetGeometry_dylibloader_orig_xlib
+#define XGetIconName XGetIconName_dylibloader_orig_xlib
+#define XGetInputFocus XGetInputFocus_dylibloader_orig_xlib
+#define XGetKeyboardControl XGetKeyboardControl_dylibloader_orig_xlib
+#define XGetPointerControl XGetPointerControl_dylibloader_orig_xlib
+#define XGetPointerMapping XGetPointerMapping_dylibloader_orig_xlib
+#define XGetScreenSaver XGetScreenSaver_dylibloader_orig_xlib
+#define XGetTransientForHint XGetTransientForHint_dylibloader_orig_xlib
+#define XGetWindowProperty XGetWindowProperty_dylibloader_orig_xlib
+#define XGetWindowAttributes XGetWindowAttributes_dylibloader_orig_xlib
+#define XGrabButton XGrabButton_dylibloader_orig_xlib
+#define XGrabKey XGrabKey_dylibloader_orig_xlib
+#define XGrabKeyboard XGrabKeyboard_dylibloader_orig_xlib
+#define XGrabPointer XGrabPointer_dylibloader_orig_xlib
+#define XGrabServer XGrabServer_dylibloader_orig_xlib
+#define XHeightMMOfScreen XHeightMMOfScreen_dylibloader_orig_xlib
+#define XHeightOfScreen XHeightOfScreen_dylibloader_orig_xlib
+#define XIfEvent XIfEvent_dylibloader_orig_xlib
+#define XImageByteOrder XImageByteOrder_dylibloader_orig_xlib
+#define XInstallColormap XInstallColormap_dylibloader_orig_xlib
+#define XKeysymToKeycode XKeysymToKeycode_dylibloader_orig_xlib
+#define XKillClient XKillClient_dylibloader_orig_xlib
+#define XLookupColor XLookupColor_dylibloader_orig_xlib
+#define XLowerWindow XLowerWindow_dylibloader_orig_xlib
+#define XMapRaised XMapRaised_dylibloader_orig_xlib
+#define XMapSubwindows XMapSubwindows_dylibloader_orig_xlib
+#define XMapWindow XMapWindow_dylibloader_orig_xlib
+#define XMaskEvent XMaskEvent_dylibloader_orig_xlib
+#define XMaxCmapsOfScreen XMaxCmapsOfScreen_dylibloader_orig_xlib
+#define XMinCmapsOfScreen XMinCmapsOfScreen_dylibloader_orig_xlib
+#define XMoveResizeWindow XMoveResizeWindow_dylibloader_orig_xlib
+#define XMoveWindow XMoveWindow_dylibloader_orig_xlib
+#define XNextEvent XNextEvent_dylibloader_orig_xlib
+#define XNoOp XNoOp_dylibloader_orig_xlib
+#define XParseColor XParseColor_dylibloader_orig_xlib
+#define XParseGeometry XParseGeometry_dylibloader_orig_xlib
+#define XPeekEvent XPeekEvent_dylibloader_orig_xlib
+#define XPeekIfEvent XPeekIfEvent_dylibloader_orig_xlib
+#define XPending XPending_dylibloader_orig_xlib
+#define XPlanesOfScreen XPlanesOfScreen_dylibloader_orig_xlib
+#define XProtocolRevision XProtocolRevision_dylibloader_orig_xlib
+#define XProtocolVersion XProtocolVersion_dylibloader_orig_xlib
+#define XPutBackEvent XPutBackEvent_dylibloader_orig_xlib
+#define XPutImage XPutImage_dylibloader_orig_xlib
+#define XQLength XQLength_dylibloader_orig_xlib
+#define XQueryBestCursor XQueryBestCursor_dylibloader_orig_xlib
+#define XQueryBestSize XQueryBestSize_dylibloader_orig_xlib
+#define XQueryBestStipple XQueryBestStipple_dylibloader_orig_xlib
+#define XQueryBestTile XQueryBestTile_dylibloader_orig_xlib
+#define XQueryColor XQueryColor_dylibloader_orig_xlib
+#define XQueryColors XQueryColors_dylibloader_orig_xlib
+#define XQueryExtension XQueryExtension_dylibloader_orig_xlib
+#define XQueryKeymap XQueryKeymap_dylibloader_orig_xlib
+#define XQueryPointer XQueryPointer_dylibloader_orig_xlib
+#define XQueryTextExtents XQueryTextExtents_dylibloader_orig_xlib
+#define XQueryTextExtents16 XQueryTextExtents16_dylibloader_orig_xlib
+#define XQueryTree XQueryTree_dylibloader_orig_xlib
+#define XRaiseWindow XRaiseWindow_dylibloader_orig_xlib
+#define XReadBitmapFile XReadBitmapFile_dylibloader_orig_xlib
+#define XReadBitmapFileData XReadBitmapFileData_dylibloader_orig_xlib
+#define XRebindKeysym XRebindKeysym_dylibloader_orig_xlib
+#define XRecolorCursor XRecolorCursor_dylibloader_orig_xlib
+#define XRefreshKeyboardMapping XRefreshKeyboardMapping_dylibloader_orig_xlib
+#define XRemoveFromSaveSet XRemoveFromSaveSet_dylibloader_orig_xlib
+#define XRemoveHost XRemoveHost_dylibloader_orig_xlib
+#define XRemoveHosts XRemoveHosts_dylibloader_orig_xlib
+#define XReparentWindow XReparentWindow_dylibloader_orig_xlib
+#define XResetScreenSaver XResetScreenSaver_dylibloader_orig_xlib
+#define XResizeWindow XResizeWindow_dylibloader_orig_xlib
+#define XRestackWindows XRestackWindows_dylibloader_orig_xlib
+#define XRotateBuffers XRotateBuffers_dylibloader_orig_xlib
+#define XRotateWindowProperties XRotateWindowProperties_dylibloader_orig_xlib
+#define XScreenCount XScreenCount_dylibloader_orig_xlib
+#define XSelectInput XSelectInput_dylibloader_orig_xlib
+#define XSendEvent XSendEvent_dylibloader_orig_xlib
+#define XSetAccessControl XSetAccessControl_dylibloader_orig_xlib
+#define XSetArcMode XSetArcMode_dylibloader_orig_xlib
+#define XSetBackground XSetBackground_dylibloader_orig_xlib
+#define XSetClipMask XSetClipMask_dylibloader_orig_xlib
+#define XSetClipOrigin XSetClipOrigin_dylibloader_orig_xlib
+#define XSetClipRectangles XSetClipRectangles_dylibloader_orig_xlib
+#define XSetCloseDownMode XSetCloseDownMode_dylibloader_orig_xlib
+#define XSetCommand XSetCommand_dylibloader_orig_xlib
+#define XSetDashes XSetDashes_dylibloader_orig_xlib
+#define XSetFillRule XSetFillRule_dylibloader_orig_xlib
+#define XSetFillStyle XSetFillStyle_dylibloader_orig_xlib
+#define XSetFont XSetFont_dylibloader_orig_xlib
+#define XSetFontPath XSetFontPath_dylibloader_orig_xlib
+#define XSetForeground XSetForeground_dylibloader_orig_xlib
+#define XSetFunction XSetFunction_dylibloader_orig_xlib
+#define XSetGraphicsExposures XSetGraphicsExposures_dylibloader_orig_xlib
+#define XSetIconName XSetIconName_dylibloader_orig_xlib
+#define XSetInputFocus XSetInputFocus_dylibloader_orig_xlib
+#define XSetLineAttributes XSetLineAttributes_dylibloader_orig_xlib
+#define XSetModifierMapping XSetModifierMapping_dylibloader_orig_xlib
+#define XSetPlaneMask XSetPlaneMask_dylibloader_orig_xlib
+#define XSetPointerMapping XSetPointerMapping_dylibloader_orig_xlib
+#define XSetScreenSaver XSetScreenSaver_dylibloader_orig_xlib
+#define XSetSelectionOwner XSetSelectionOwner_dylibloader_orig_xlib
+#define XSetState XSetState_dylibloader_orig_xlib
+#define XSetStipple XSetStipple_dylibloader_orig_xlib
+#define XSetSubwindowMode XSetSubwindowMode_dylibloader_orig_xlib
+#define XSetTSOrigin XSetTSOrigin_dylibloader_orig_xlib
+#define XSetTile XSetTile_dylibloader_orig_xlib
+#define XSetWindowBackground XSetWindowBackground_dylibloader_orig_xlib
+#define XSetWindowBackgroundPixmap XSetWindowBackgroundPixmap_dylibloader_orig_xlib
+#define XSetWindowBorder XSetWindowBorder_dylibloader_orig_xlib
+#define XSetWindowBorderPixmap XSetWindowBorderPixmap_dylibloader_orig_xlib
+#define XSetWindowBorderWidth XSetWindowBorderWidth_dylibloader_orig_xlib
+#define XSetWindowColormap XSetWindowColormap_dylibloader_orig_xlib
+#define XStoreBuffer XStoreBuffer_dylibloader_orig_xlib
+#define XStoreBytes XStoreBytes_dylibloader_orig_xlib
+#define XStoreColor XStoreColor_dylibloader_orig_xlib
+#define XStoreColors XStoreColors_dylibloader_orig_xlib
+#define XStoreName XStoreName_dylibloader_orig_xlib
+#define XStoreNamedColor XStoreNamedColor_dylibloader_orig_xlib
+#define XSync XSync_dylibloader_orig_xlib
+#define XTextExtents XTextExtents_dylibloader_orig_xlib
+#define XTextExtents16 XTextExtents16_dylibloader_orig_xlib
+#define XTextWidth XTextWidth_dylibloader_orig_xlib
+#define XTextWidth16 XTextWidth16_dylibloader_orig_xlib
+#define XTranslateCoordinates XTranslateCoordinates_dylibloader_orig_xlib
+#define XUndefineCursor XUndefineCursor_dylibloader_orig_xlib
+#define XUngrabButton XUngrabButton_dylibloader_orig_xlib
+#define XUngrabKey XUngrabKey_dylibloader_orig_xlib
+#define XUngrabKeyboard XUngrabKeyboard_dylibloader_orig_xlib
+#define XUngrabPointer XUngrabPointer_dylibloader_orig_xlib
+#define XUngrabServer XUngrabServer_dylibloader_orig_xlib
+#define XUninstallColormap XUninstallColormap_dylibloader_orig_xlib
+#define XUnloadFont XUnloadFont_dylibloader_orig_xlib
+#define XUnmapSubwindows XUnmapSubwindows_dylibloader_orig_xlib
+#define XUnmapWindow XUnmapWindow_dylibloader_orig_xlib
+#define XVendorRelease XVendorRelease_dylibloader_orig_xlib
+#define XWarpPointer XWarpPointer_dylibloader_orig_xlib
+#define XWidthMMOfScreen XWidthMMOfScreen_dylibloader_orig_xlib
+#define XWidthOfScreen XWidthOfScreen_dylibloader_orig_xlib
+#define XWindowEvent XWindowEvent_dylibloader_orig_xlib
+#define XWriteBitmapFile XWriteBitmapFile_dylibloader_orig_xlib
+#define XSupportsLocale XSupportsLocale_dylibloader_orig_xlib
+#define XSetLocaleModifiers XSetLocaleModifiers_dylibloader_orig_xlib
+#define XOpenOM XOpenOM_dylibloader_orig_xlib
+#define XCloseOM XCloseOM_dylibloader_orig_xlib
+#define XSetOMValues XSetOMValues_dylibloader_orig_xlib
+#define XGetOMValues XGetOMValues_dylibloader_orig_xlib
+#define XDisplayOfOM XDisplayOfOM_dylibloader_orig_xlib
+#define XLocaleOfOM XLocaleOfOM_dylibloader_orig_xlib
+#define XCreateOC XCreateOC_dylibloader_orig_xlib
+#define XDestroyOC XDestroyOC_dylibloader_orig_xlib
+#define XOMOfOC XOMOfOC_dylibloader_orig_xlib
+#define XSetOCValues XSetOCValues_dylibloader_orig_xlib
+#define XGetOCValues XGetOCValues_dylibloader_orig_xlib
+#define XCreateFontSet XCreateFontSet_dylibloader_orig_xlib
+#define XFreeFontSet XFreeFontSet_dylibloader_orig_xlib
+#define XFontsOfFontSet XFontsOfFontSet_dylibloader_orig_xlib
+#define XBaseFontNameListOfFontSet XBaseFontNameListOfFontSet_dylibloader_orig_xlib
+#define XLocaleOfFontSet XLocaleOfFontSet_dylibloader_orig_xlib
+#define XContextDependentDrawing XContextDependentDrawing_dylibloader_orig_xlib
+#define XDirectionalDependentDrawing XDirectionalDependentDrawing_dylibloader_orig_xlib
+#define XContextualDrawing XContextualDrawing_dylibloader_orig_xlib
+#define XExtentsOfFontSet XExtentsOfFontSet_dylibloader_orig_xlib
+#define XmbTextEscapement XmbTextEscapement_dylibloader_orig_xlib
+#define XwcTextEscapement XwcTextEscapement_dylibloader_orig_xlib
+#define Xutf8TextEscapement Xutf8TextEscapement_dylibloader_orig_xlib
+#define XmbTextExtents XmbTextExtents_dylibloader_orig_xlib
+#define XwcTextExtents XwcTextExtents_dylibloader_orig_xlib
+#define Xutf8TextExtents Xutf8TextExtents_dylibloader_orig_xlib
+#define XmbTextPerCharExtents XmbTextPerCharExtents_dylibloader_orig_xlib
+#define XwcTextPerCharExtents XwcTextPerCharExtents_dylibloader_orig_xlib
+#define Xutf8TextPerCharExtents Xutf8TextPerCharExtents_dylibloader_orig_xlib
+#define XmbDrawText XmbDrawText_dylibloader_orig_xlib
+#define XwcDrawText XwcDrawText_dylibloader_orig_xlib
+#define Xutf8DrawText Xutf8DrawText_dylibloader_orig_xlib
+#define XmbDrawString XmbDrawString_dylibloader_orig_xlib
+#define XwcDrawString XwcDrawString_dylibloader_orig_xlib
+#define Xutf8DrawString Xutf8DrawString_dylibloader_orig_xlib
+#define XmbDrawImageString XmbDrawImageString_dylibloader_orig_xlib
+#define XwcDrawImageString XwcDrawImageString_dylibloader_orig_xlib
+#define Xutf8DrawImageString Xutf8DrawImageString_dylibloader_orig_xlib
+#define XOpenIM XOpenIM_dylibloader_orig_xlib
+#define XCloseIM XCloseIM_dylibloader_orig_xlib
+#define XGetIMValues XGetIMValues_dylibloader_orig_xlib
+#define XSetIMValues XSetIMValues_dylibloader_orig_xlib
+#define XDisplayOfIM XDisplayOfIM_dylibloader_orig_xlib
+#define XLocaleOfIM XLocaleOfIM_dylibloader_orig_xlib
+#define XCreateIC XCreateIC_dylibloader_orig_xlib
+#define XDestroyIC XDestroyIC_dylibloader_orig_xlib
+#define XSetICFocus XSetICFocus_dylibloader_orig_xlib
+#define XUnsetICFocus XUnsetICFocus_dylibloader_orig_xlib
+#define XwcResetIC XwcResetIC_dylibloader_orig_xlib
+#define XmbResetIC XmbResetIC_dylibloader_orig_xlib
+#define Xutf8ResetIC Xutf8ResetIC_dylibloader_orig_xlib
+#define XSetICValues XSetICValues_dylibloader_orig_xlib
+#define XGetICValues XGetICValues_dylibloader_orig_xlib
+#define XIMOfIC XIMOfIC_dylibloader_orig_xlib
+#define XFilterEvent XFilterEvent_dylibloader_orig_xlib
+#define XmbLookupString XmbLookupString_dylibloader_orig_xlib
+#define XwcLookupString XwcLookupString_dylibloader_orig_xlib
+#define Xutf8LookupString Xutf8LookupString_dylibloader_orig_xlib
+#define XVaCreateNestedList XVaCreateNestedList_dylibloader_orig_xlib
+#define XRegisterIMInstantiateCallback XRegisterIMInstantiateCallback_dylibloader_orig_xlib
+#define XUnregisterIMInstantiateCallback XUnregisterIMInstantiateCallback_dylibloader_orig_xlib
+#define XInternalConnectionNumbers XInternalConnectionNumbers_dylibloader_orig_xlib
+#define XProcessInternalConnection XProcessInternalConnection_dylibloader_orig_xlib
+#define XAddConnectionWatch XAddConnectionWatch_dylibloader_orig_xlib
+#define XRemoveConnectionWatch XRemoveConnectionWatch_dylibloader_orig_xlib
+#define XSetAuthorization XSetAuthorization_dylibloader_orig_xlib
+#define _Xmbtowc _Xmbtowc_dylibloader_orig_xlib
+#define _Xwctomb _Xwctomb_dylibloader_orig_xlib
+#define XGetEventData XGetEventData_dylibloader_orig_xlib
+#define XFreeEventData XFreeEventData_dylibloader_orig_xlib
+#define XAllocClassHint XAllocClassHint_dylibloader_orig_xlib
+#define XAllocIconSize XAllocIconSize_dylibloader_orig_xlib
+#define XAllocSizeHints XAllocSizeHints_dylibloader_orig_xlib
+#define XAllocStandardColormap XAllocStandardColormap_dylibloader_orig_xlib
+#define XAllocWMHints XAllocWMHints_dylibloader_orig_xlib
+#define XClipBox XClipBox_dylibloader_orig_xlib
+#define XCreateRegion XCreateRegion_dylibloader_orig_xlib
+#define XDefaultString XDefaultString_dylibloader_orig_xlib
+#define XDeleteContext XDeleteContext_dylibloader_orig_xlib
+#define XDestroyRegion XDestroyRegion_dylibloader_orig_xlib
+#define XEmptyRegion XEmptyRegion_dylibloader_orig_xlib
+#define XEqualRegion XEqualRegion_dylibloader_orig_xlib
+#define XFindContext XFindContext_dylibloader_orig_xlib
+#define XGetClassHint XGetClassHint_dylibloader_orig_xlib
+#define XGetIconSizes XGetIconSizes_dylibloader_orig_xlib
+#define XGetNormalHints XGetNormalHints_dylibloader_orig_xlib
+#define XGetRGBColormaps XGetRGBColormaps_dylibloader_orig_xlib
+#define XGetSizeHints XGetSizeHints_dylibloader_orig_xlib
+#define XGetStandardColormap XGetStandardColormap_dylibloader_orig_xlib
+#define XGetTextProperty XGetTextProperty_dylibloader_orig_xlib
+#define XGetVisualInfo XGetVisualInfo_dylibloader_orig_xlib
+#define XGetWMClientMachine XGetWMClientMachine_dylibloader_orig_xlib
+#define XGetWMHints XGetWMHints_dylibloader_orig_xlib
+#define XGetWMIconName XGetWMIconName_dylibloader_orig_xlib
+#define XGetWMName XGetWMName_dylibloader_orig_xlib
+#define XGetWMNormalHints XGetWMNormalHints_dylibloader_orig_xlib
+#define XGetWMSizeHints XGetWMSizeHints_dylibloader_orig_xlib
+#define XGetZoomHints XGetZoomHints_dylibloader_orig_xlib
+#define XIntersectRegion XIntersectRegion_dylibloader_orig_xlib
+#define XConvertCase XConvertCase_dylibloader_orig_xlib
+#define XLookupString XLookupString_dylibloader_orig_xlib
+#define XMatchVisualInfo XMatchVisualInfo_dylibloader_orig_xlib
+#define XOffsetRegion XOffsetRegion_dylibloader_orig_xlib
+#define XPointInRegion XPointInRegion_dylibloader_orig_xlib
+#define XPolygonRegion XPolygonRegion_dylibloader_orig_xlib
+#define XRectInRegion XRectInRegion_dylibloader_orig_xlib
+#define XSaveContext XSaveContext_dylibloader_orig_xlib
+#define XSetClassHint XSetClassHint_dylibloader_orig_xlib
+#define XSetIconSizes XSetIconSizes_dylibloader_orig_xlib
+#define XSetNormalHints XSetNormalHints_dylibloader_orig_xlib
+#define XSetRGBColormaps XSetRGBColormaps_dylibloader_orig_xlib
+#define XSetSizeHints XSetSizeHints_dylibloader_orig_xlib
+#define XSetStandardProperties XSetStandardProperties_dylibloader_orig_xlib
+#define XSetTextProperty XSetTextProperty_dylibloader_orig_xlib
+#define XSetWMClientMachine XSetWMClientMachine_dylibloader_orig_xlib
+#define XSetWMHints XSetWMHints_dylibloader_orig_xlib
+#define XSetWMIconName XSetWMIconName_dylibloader_orig_xlib
+#define XSetWMName XSetWMName_dylibloader_orig_xlib
+#define XSetWMNormalHints XSetWMNormalHints_dylibloader_orig_xlib
+#define XSetWMProperties XSetWMProperties_dylibloader_orig_xlib
+#define XmbSetWMProperties XmbSetWMProperties_dylibloader_orig_xlib
+#define Xutf8SetWMProperties Xutf8SetWMProperties_dylibloader_orig_xlib
+#define XSetWMSizeHints XSetWMSizeHints_dylibloader_orig_xlib
+#define XSetRegion XSetRegion_dylibloader_orig_xlib
+#define XSetStandardColormap XSetStandardColormap_dylibloader_orig_xlib
+#define XSetZoomHints XSetZoomHints_dylibloader_orig_xlib
+#define XShrinkRegion XShrinkRegion_dylibloader_orig_xlib
+#define XStringListToTextProperty XStringListToTextProperty_dylibloader_orig_xlib
+#define XSubtractRegion XSubtractRegion_dylibloader_orig_xlib
+#define XmbTextListToTextProperty XmbTextListToTextProperty_dylibloader_orig_xlib
+#define XwcTextListToTextProperty XwcTextListToTextProperty_dylibloader_orig_xlib
+#define Xutf8TextListToTextProperty Xutf8TextListToTextProperty_dylibloader_orig_xlib
+#define XwcFreeStringList XwcFreeStringList_dylibloader_orig_xlib
+#define XTextPropertyToStringList XTextPropertyToStringList_dylibloader_orig_xlib
+#define XmbTextPropertyToTextList XmbTextPropertyToTextList_dylibloader_orig_xlib
+#define XwcTextPropertyToTextList XwcTextPropertyToTextList_dylibloader_orig_xlib
+#define Xutf8TextPropertyToTextList Xutf8TextPropertyToTextList_dylibloader_orig_xlib
+#define XUnionRectWithRegion XUnionRectWithRegion_dylibloader_orig_xlib
+#define XUnionRegion XUnionRegion_dylibloader_orig_xlib
+#define XWMGeometry XWMGeometry_dylibloader_orig_xlib
+#define XXorRegion XXorRegion_dylibloader_orig_xlib
+#define XkbIgnoreExtension XkbIgnoreExtension_dylibloader_orig_xlib
+#define XkbOpenDisplay XkbOpenDisplay_dylibloader_orig_xlib
+#define XkbQueryExtension XkbQueryExtension_dylibloader_orig_xlib
+#define XkbUseExtension XkbUseExtension_dylibloader_orig_xlib
+#define XkbLibraryVersion XkbLibraryVersion_dylibloader_orig_xlib
+#define XkbSetXlibControls XkbSetXlibControls_dylibloader_orig_xlib
+#define XkbGetXlibControls XkbGetXlibControls_dylibloader_orig_xlib
+#define XkbXlibControlsImplemented XkbXlibControlsImplemented_dylibloader_orig_xlib
+#define XkbSetAtomFuncs XkbSetAtomFuncs_dylibloader_orig_xlib
+#define XkbKeycodeToKeysym XkbKeycodeToKeysym_dylibloader_orig_xlib
+#define XkbKeysymToModifiers XkbKeysymToModifiers_dylibloader_orig_xlib
+#define XkbLookupKeySym XkbLookupKeySym_dylibloader_orig_xlib
+#define XkbLookupKeyBinding XkbLookupKeyBinding_dylibloader_orig_xlib
+#define XkbTranslateKeyCode XkbTranslateKeyCode_dylibloader_orig_xlib
+#define XkbTranslateKeySym XkbTranslateKeySym_dylibloader_orig_xlib
+#define XkbSetAutoRepeatRate XkbSetAutoRepeatRate_dylibloader_orig_xlib
+#define XkbGetAutoRepeatRate XkbGetAutoRepeatRate_dylibloader_orig_xlib
+#define XkbChangeEnabledControls XkbChangeEnabledControls_dylibloader_orig_xlib
+#define XkbDeviceBell XkbDeviceBell_dylibloader_orig_xlib
+#define XkbForceDeviceBell XkbForceDeviceBell_dylibloader_orig_xlib
+#define XkbDeviceBellEvent XkbDeviceBellEvent_dylibloader_orig_xlib
+#define XkbBell XkbBell_dylibloader_orig_xlib
+#define XkbForceBell XkbForceBell_dylibloader_orig_xlib
+#define XkbBellEvent XkbBellEvent_dylibloader_orig_xlib
+#define XkbSelectEvents XkbSelectEvents_dylibloader_orig_xlib
+#define XkbSelectEventDetails XkbSelectEventDetails_dylibloader_orig_xlib
+#define XkbNoteMapChanges XkbNoteMapChanges_dylibloader_orig_xlib
+#define XkbNoteNameChanges XkbNoteNameChanges_dylibloader_orig_xlib
+#define XkbGetIndicatorState XkbGetIndicatorState_dylibloader_orig_xlib
+#define XkbGetIndicatorMap XkbGetIndicatorMap_dylibloader_orig_xlib
+#define XkbSetIndicatorMap XkbSetIndicatorMap_dylibloader_orig_xlib
+#define XkbGetNamedIndicator XkbGetNamedIndicator_dylibloader_orig_xlib
+#define XkbGetNamedDeviceIndicator XkbGetNamedDeviceIndicator_dylibloader_orig_xlib
+#define XkbSetNamedIndicator XkbSetNamedIndicator_dylibloader_orig_xlib
+#define XkbSetNamedDeviceIndicator XkbSetNamedDeviceIndicator_dylibloader_orig_xlib
+#define XkbLockModifiers XkbLockModifiers_dylibloader_orig_xlib
+#define XkbLatchModifiers XkbLatchModifiers_dylibloader_orig_xlib
+#define XkbLockGroup XkbLockGroup_dylibloader_orig_xlib
+#define XkbLatchGroup XkbLatchGroup_dylibloader_orig_xlib
+#define XkbSetServerInternalMods XkbSetServerInternalMods_dylibloader_orig_xlib
+#define XkbSetIgnoreLockMods XkbSetIgnoreLockMods_dylibloader_orig_xlib
+#define XkbVirtualModsToReal XkbVirtualModsToReal_dylibloader_orig_xlib
+#define XkbComputeEffectiveMap XkbComputeEffectiveMap_dylibloader_orig_xlib
+#define XkbInitCanonicalKeyTypes XkbInitCanonicalKeyTypes_dylibloader_orig_xlib
+#define XkbAllocKeyboard XkbAllocKeyboard_dylibloader_orig_xlib
+#define XkbFreeKeyboard XkbFreeKeyboard_dylibloader_orig_xlib
+#define XkbAllocClientMap XkbAllocClientMap_dylibloader_orig_xlib
+#define XkbAllocServerMap XkbAllocServerMap_dylibloader_orig_xlib
+#define XkbFreeClientMap XkbFreeClientMap_dylibloader_orig_xlib
+#define XkbFreeServerMap XkbFreeServerMap_dylibloader_orig_xlib
+#define XkbAddKeyType XkbAddKeyType_dylibloader_orig_xlib
+#define XkbAllocIndicatorMaps XkbAllocIndicatorMaps_dylibloader_orig_xlib
+#define XkbFreeIndicatorMaps XkbFreeIndicatorMaps_dylibloader_orig_xlib
+#define XkbGetMap XkbGetMap_dylibloader_orig_xlib
+#define XkbGetUpdatedMap XkbGetUpdatedMap_dylibloader_orig_xlib
+#define XkbGetMapChanges XkbGetMapChanges_dylibloader_orig_xlib
+#define XkbRefreshKeyboardMapping XkbRefreshKeyboardMapping_dylibloader_orig_xlib
+#define XkbGetKeyTypes XkbGetKeyTypes_dylibloader_orig_xlib
+#define XkbGetKeySyms XkbGetKeySyms_dylibloader_orig_xlib
+#define XkbGetKeyActions XkbGetKeyActions_dylibloader_orig_xlib
+#define XkbGetKeyBehaviors XkbGetKeyBehaviors_dylibloader_orig_xlib
+#define XkbGetVirtualMods XkbGetVirtualMods_dylibloader_orig_xlib
+#define XkbGetKeyExplicitComponents XkbGetKeyExplicitComponents_dylibloader_orig_xlib
+#define XkbGetKeyModifierMap XkbGetKeyModifierMap_dylibloader_orig_xlib
+#define XkbGetKeyVirtualModMap XkbGetKeyVirtualModMap_dylibloader_orig_xlib
+#define XkbAllocControls XkbAllocControls_dylibloader_orig_xlib
+#define XkbFreeControls XkbFreeControls_dylibloader_orig_xlib
+#define XkbGetControls XkbGetControls_dylibloader_orig_xlib
+#define XkbSetControls XkbSetControls_dylibloader_orig_xlib
+#define XkbNoteControlsChanges XkbNoteControlsChanges_dylibloader_orig_xlib
+#define XkbAllocCompatMap XkbAllocCompatMap_dylibloader_orig_xlib
+#define XkbFreeCompatMap XkbFreeCompatMap_dylibloader_orig_xlib
+#define XkbGetCompatMap XkbGetCompatMap_dylibloader_orig_xlib
+#define XkbSetCompatMap XkbSetCompatMap_dylibloader_orig_xlib
+#define XkbAllocNames XkbAllocNames_dylibloader_orig_xlib
+#define XkbGetNames XkbGetNames_dylibloader_orig_xlib
+#define XkbSetNames XkbSetNames_dylibloader_orig_xlib
+#define XkbChangeNames XkbChangeNames_dylibloader_orig_xlib
+#define XkbFreeNames XkbFreeNames_dylibloader_orig_xlib
+#define XkbGetState XkbGetState_dylibloader_orig_xlib
+#define XkbSetMap XkbSetMap_dylibloader_orig_xlib
+#define XkbChangeMap XkbChangeMap_dylibloader_orig_xlib
+#define XkbSetDetectableAutoRepeat XkbSetDetectableAutoRepeat_dylibloader_orig_xlib
+#define XkbGetDetectableAutoRepeat XkbGetDetectableAutoRepeat_dylibloader_orig_xlib
+#define XkbSetAutoResetControls XkbSetAutoResetControls_dylibloader_orig_xlib
+#define XkbGetAutoResetControls XkbGetAutoResetControls_dylibloader_orig_xlib
+#define XkbSetPerClientControls XkbSetPerClientControls_dylibloader_orig_xlib
+#define XkbGetPerClientControls XkbGetPerClientControls_dylibloader_orig_xlib
+#define XkbCopyKeyType XkbCopyKeyType_dylibloader_orig_xlib
+#define XkbCopyKeyTypes XkbCopyKeyTypes_dylibloader_orig_xlib
+#define XkbResizeKeyType XkbResizeKeyType_dylibloader_orig_xlib
+#define XkbResizeKeySyms XkbResizeKeySyms_dylibloader_orig_xlib
+#define XkbResizeKeyActions XkbResizeKeyActions_dylibloader_orig_xlib
+#define XkbChangeTypesOfKey XkbChangeTypesOfKey_dylibloader_orig_xlib
+#define XkbChangeKeycodeRange XkbChangeKeycodeRange_dylibloader_orig_xlib
+#define XkbListComponents XkbListComponents_dylibloader_orig_xlib
+#define XkbFreeComponentList XkbFreeComponentList_dylibloader_orig_xlib
+#define XkbGetKeyboard XkbGetKeyboard_dylibloader_orig_xlib
+#define XkbGetKeyboardByName XkbGetKeyboardByName_dylibloader_orig_xlib
+#define XkbKeyTypesForCoreSymbols XkbKeyTypesForCoreSymbols_dylibloader_orig_xlib
+#define XkbApplyCompatMapToKey XkbApplyCompatMapToKey_dylibloader_orig_xlib
+#define XkbUpdateMapFromCore XkbUpdateMapFromCore_dylibloader_orig_xlib
+#define XkbAddDeviceLedInfo XkbAddDeviceLedInfo_dylibloader_orig_xlib
+#define XkbResizeDeviceButtonActions XkbResizeDeviceButtonActions_dylibloader_orig_xlib
+#define XkbAllocDeviceInfo XkbAllocDeviceInfo_dylibloader_orig_xlib
+#define XkbFreeDeviceInfo XkbFreeDeviceInfo_dylibloader_orig_xlib
+#define XkbNoteDeviceChanges XkbNoteDeviceChanges_dylibloader_orig_xlib
+#define XkbGetDeviceInfo XkbGetDeviceInfo_dylibloader_orig_xlib
+#define XkbGetDeviceInfoChanges XkbGetDeviceInfoChanges_dylibloader_orig_xlib
+#define XkbGetDeviceButtonActions XkbGetDeviceButtonActions_dylibloader_orig_xlib
+#define XkbGetDeviceLedInfo XkbGetDeviceLedInfo_dylibloader_orig_xlib
+#define XkbSetDeviceInfo XkbSetDeviceInfo_dylibloader_orig_xlib
+#define XkbChangeDeviceInfo XkbChangeDeviceInfo_dylibloader_orig_xlib
+#define XkbSetDeviceLedInfo XkbSetDeviceLedInfo_dylibloader_orig_xlib
+#define XkbSetDeviceButtonActions XkbSetDeviceButtonActions_dylibloader_orig_xlib
+#define XkbToControl XkbToControl_dylibloader_orig_xlib
+#define XkbSetDebuggingFlags XkbSetDebuggingFlags_dylibloader_orig_xlib
+#define XkbApplyVirtualModChanges XkbApplyVirtualModChanges_dylibloader_orig_xlib
+#define XkbUpdateActionVirtualMods XkbUpdateActionVirtualMods_dylibloader_orig_xlib
+#define XkbUpdateKeyTypeVirtualMods XkbUpdateKeyTypeVirtualMods_dylibloader_orig_xlib
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/XKBlib.h>
+#undef _Xmblen
+#undef XLoadQueryFont
+#undef XQueryFont
+#undef XGetMotionEvents
+#undef XDeleteModifiermapEntry
+#undef XGetModifierMapping
+#undef XInsertModifiermapEntry
+#undef XNewModifiermap
+#undef XCreateImage
+#undef XInitImage
+#undef XGetImage
+#undef XGetSubImage
+#undef XOpenDisplay
+#undef XrmInitialize
+#undef XFetchBytes
+#undef XFetchBuffer
+#undef XGetAtomName
+#undef XGetAtomNames
+#undef XGetDefault
+#undef XDisplayName
+#undef XKeysymToString
+#undef XSynchronize
+#undef XSetAfterFunction
+#undef XInternAtom
+#undef XInternAtoms
+#undef XCopyColormapAndFree
+#undef XCreateColormap
+#undef XCreatePixmapCursor
+#undef XCreateGlyphCursor
+#undef XCreateFontCursor
+#undef XLoadFont
+#undef XCreateGC
+#undef XGContextFromGC
+#undef XFlushGC
+#undef XCreatePixmap
+#undef XCreateBitmapFromData
+#undef XCreatePixmapFromBitmapData
+#undef XCreateSimpleWindow
+#undef XGetSelectionOwner
+#undef XCreateWindow
+#undef XListInstalledColormaps
+#undef XListFonts
+#undef XListFontsWithInfo
+#undef XGetFontPath
+#undef XListExtensions
+#undef XListProperties
+#undef XListHosts
+#undef XKeycodeToKeysym
+#undef XLookupKeysym
+#undef XGetKeyboardMapping
+#undef XStringToKeysym
+#undef XMaxRequestSize
+#undef XExtendedMaxRequestSize
+#undef XResourceManagerString
+#undef XScreenResourceString
+#undef XDisplayMotionBufferSize
+#undef XVisualIDFromVisual
+#undef XInitThreads
+#undef XLockDisplay
+#undef XUnlockDisplay
+#undef XInitExtension
+#undef XAddExtension
+#undef XFindOnExtensionList
+#undef XEHeadOfExtensionList
+#undef XRootWindow
+#undef XDefaultRootWindow
+#undef XRootWindowOfScreen
+#undef XDefaultVisual
+#undef XDefaultVisualOfScreen
+#undef XDefaultGC
+#undef XDefaultGCOfScreen
+#undef XBlackPixel
+#undef XWhitePixel
+#undef XAllPlanes
+#undef XBlackPixelOfScreen
+#undef XWhitePixelOfScreen
+#undef XNextRequest
+#undef XLastKnownRequestProcessed
+#undef XServerVendor
+#undef XDisplayString
+#undef XDefaultColormap
+#undef XDefaultColormapOfScreen
+#undef XDisplayOfScreen
+#undef XScreenOfDisplay
+#undef XDefaultScreenOfDisplay
+#undef XEventMaskOfScreen
+#undef XScreenNumberOfScreen
+#undef XSetErrorHandler
+#undef XSetIOErrorHandler
+#undef XListPixmapFormats
+#undef XListDepths
+#undef XReconfigureWMWindow
+#undef XGetWMProtocols
+#undef XSetWMProtocols
+#undef XIconifyWindow
+#undef XWithdrawWindow
+#undef XGetCommand
+#undef XGetWMColormapWindows
+#undef XSetWMColormapWindows
+#undef XFreeStringList
+#undef XSetTransientForHint
+#undef XActivateScreenSaver
+#undef XAddHost
+#undef XAddHosts
+#undef XAddToExtensionList
+#undef XAddToSaveSet
+#undef XAllocColor
+#undef XAllocColorCells
+#undef XAllocColorPlanes
+#undef XAllocNamedColor
+#undef XAllowEvents
+#undef XAutoRepeatOff
+#undef XAutoRepeatOn
+#undef XBell
+#undef XBitmapBitOrder
+#undef XBitmapPad
+#undef XBitmapUnit
+#undef XCellsOfScreen
+#undef XChangeActivePointerGrab
+#undef XChangeGC
+#undef XChangeKeyboardControl
+#undef XChangeKeyboardMapping
+#undef XChangePointerControl
+#undef XChangeProperty
+#undef XChangeSaveSet
+#undef XChangeWindowAttributes
+#undef XCheckIfEvent
+#undef XCheckMaskEvent
+#undef XCheckTypedEvent
+#undef XCheckTypedWindowEvent
+#undef XCheckWindowEvent
+#undef XCirculateSubwindows
+#undef XCirculateSubwindowsDown
+#undef XCirculateSubwindowsUp
+#undef XClearArea
+#undef XClearWindow
+#undef XCloseDisplay
+#undef XConfigureWindow
+#undef XConnectionNumber
+#undef XConvertSelection
+#undef XCopyArea
+#undef XCopyGC
+#undef XCopyPlane
+#undef XDefaultDepth
+#undef XDefaultDepthOfScreen
+#undef XDefaultScreen
+#undef XDefineCursor
+#undef XDeleteProperty
+#undef XDestroyWindow
+#undef XDestroySubwindows
+#undef XDoesBackingStore
+#undef XDoesSaveUnders
+#undef XDisableAccessControl
+#undef XDisplayCells
+#undef XDisplayHeight
+#undef XDisplayHeightMM
+#undef XDisplayKeycodes
+#undef XDisplayPlanes
+#undef XDisplayWidth
+#undef XDisplayWidthMM
+#undef XDrawArc
+#undef XDrawArcs
+#undef XDrawImageString
+#undef XDrawImageString16
+#undef XDrawLine
+#undef XDrawLines
+#undef XDrawPoint
+#undef XDrawPoints
+#undef XDrawRectangle
+#undef XDrawRectangles
+#undef XDrawSegments
+#undef XDrawString
+#undef XDrawString16
+#undef XDrawText
+#undef XDrawText16
+#undef XEnableAccessControl
+#undef XEventsQueued
+#undef XFetchName
+#undef XFillArc
+#undef XFillArcs
+#undef XFillPolygon
+#undef XFillRectangle
+#undef XFillRectangles
+#undef XFlush
+#undef XForceScreenSaver
+#undef XFree
+#undef XFreeColormap
+#undef XFreeColors
+#undef XFreeCursor
+#undef XFreeExtensionList
+#undef XFreeFont
+#undef XFreeFontInfo
+#undef XFreeFontNames
+#undef XFreeFontPath
+#undef XFreeGC
+#undef XFreeModifiermap
+#undef XFreePixmap
+#undef XGeometry
+#undef XGetErrorDatabaseText
+#undef XGetErrorText
+#undef XGetFontProperty
+#undef XGetGCValues
+#undef XGetGeometry
+#undef XGetIconName
+#undef XGetInputFocus
+#undef XGetKeyboardControl
+#undef XGetPointerControl
+#undef XGetPointerMapping
+#undef XGetScreenSaver
+#undef XGetTransientForHint
+#undef XGetWindowProperty
+#undef XGetWindowAttributes
+#undef XGrabButton
+#undef XGrabKey
+#undef XGrabKeyboard
+#undef XGrabPointer
+#undef XGrabServer
+#undef XHeightMMOfScreen
+#undef XHeightOfScreen
+#undef XIfEvent
+#undef XImageByteOrder
+#undef XInstallColormap
+#undef XKeysymToKeycode
+#undef XKillClient
+#undef XLookupColor
+#undef XLowerWindow
+#undef XMapRaised
+#undef XMapSubwindows
+#undef XMapWindow
+#undef XMaskEvent
+#undef XMaxCmapsOfScreen
+#undef XMinCmapsOfScreen
+#undef XMoveResizeWindow
+#undef XMoveWindow
+#undef XNextEvent
+#undef XNoOp
+#undef XParseColor
+#undef XParseGeometry
+#undef XPeekEvent
+#undef XPeekIfEvent
+#undef XPending
+#undef XPlanesOfScreen
+#undef XProtocolRevision
+#undef XProtocolVersion
+#undef XPutBackEvent
+#undef XPutImage
+#undef XQLength
+#undef XQueryBestCursor
+#undef XQueryBestSize
+#undef XQueryBestStipple
+#undef XQueryBestTile
+#undef XQueryColor
+#undef XQueryColors
+#undef XQueryExtension
+#undef XQueryKeymap
+#undef XQueryPointer
+#undef XQueryTextExtents
+#undef XQueryTextExtents16
+#undef XQueryTree
+#undef XRaiseWindow
+#undef XReadBitmapFile
+#undef XReadBitmapFileData
+#undef XRebindKeysym
+#undef XRecolorCursor
+#undef XRefreshKeyboardMapping
+#undef XRemoveFromSaveSet
+#undef XRemoveHost
+#undef XRemoveHosts
+#undef XReparentWindow
+#undef XResetScreenSaver
+#undef XResizeWindow
+#undef XRestackWindows
+#undef XRotateBuffers
+#undef XRotateWindowProperties
+#undef XScreenCount
+#undef XSelectInput
+#undef XSendEvent
+#undef XSetAccessControl
+#undef XSetArcMode
+#undef XSetBackground
+#undef XSetClipMask
+#undef XSetClipOrigin
+#undef XSetClipRectangles
+#undef XSetCloseDownMode
+#undef XSetCommand
+#undef XSetDashes
+#undef XSetFillRule
+#undef XSetFillStyle
+#undef XSetFont
+#undef XSetFontPath
+#undef XSetForeground
+#undef XSetFunction
+#undef XSetGraphicsExposures
+#undef XSetIconName
+#undef XSetInputFocus
+#undef XSetLineAttributes
+#undef XSetModifierMapping
+#undef XSetPlaneMask
+#undef XSetPointerMapping
+#undef XSetScreenSaver
+#undef XSetSelectionOwner
+#undef XSetState
+#undef XSetStipple
+#undef XSetSubwindowMode
+#undef XSetTSOrigin
+#undef XSetTile
+#undef XSetWindowBackground
+#undef XSetWindowBackgroundPixmap
+#undef XSetWindowBorder
+#undef XSetWindowBorderPixmap
+#undef XSetWindowBorderWidth
+#undef XSetWindowColormap
+#undef XStoreBuffer
+#undef XStoreBytes
+#undef XStoreColor
+#undef XStoreColors
+#undef XStoreName
+#undef XStoreNamedColor
+#undef XSync
+#undef XTextExtents
+#undef XTextExtents16
+#undef XTextWidth
+#undef XTextWidth16
+#undef XTranslateCoordinates
+#undef XUndefineCursor
+#undef XUngrabButton
+#undef XUngrabKey
+#undef XUngrabKeyboard
+#undef XUngrabPointer
+#undef XUngrabServer
+#undef XUninstallColormap
+#undef XUnloadFont
+#undef XUnmapSubwindows
+#undef XUnmapWindow
+#undef XVendorRelease
+#undef XWarpPointer
+#undef XWidthMMOfScreen
+#undef XWidthOfScreen
+#undef XWindowEvent
+#undef XWriteBitmapFile
+#undef XSupportsLocale
+#undef XSetLocaleModifiers
+#undef XOpenOM
+#undef XCloseOM
+#undef XSetOMValues
+#undef XGetOMValues
+#undef XDisplayOfOM
+#undef XLocaleOfOM
+#undef XCreateOC
+#undef XDestroyOC
+#undef XOMOfOC
+#undef XSetOCValues
+#undef XGetOCValues
+#undef XCreateFontSet
+#undef XFreeFontSet
+#undef XFontsOfFontSet
+#undef XBaseFontNameListOfFontSet
+#undef XLocaleOfFontSet
+#undef XContextDependentDrawing
+#undef XDirectionalDependentDrawing
+#undef XContextualDrawing
+#undef XExtentsOfFontSet
+#undef XmbTextEscapement
+#undef XwcTextEscapement
+#undef Xutf8TextEscapement
+#undef XmbTextExtents
+#undef XwcTextExtents
+#undef Xutf8TextExtents
+#undef XmbTextPerCharExtents
+#undef XwcTextPerCharExtents
+#undef Xutf8TextPerCharExtents
+#undef XmbDrawText
+#undef XwcDrawText
+#undef Xutf8DrawText
+#undef XmbDrawString
+#undef XwcDrawString
+#undef Xutf8DrawString
+#undef XmbDrawImageString
+#undef XwcDrawImageString
+#undef Xutf8DrawImageString
+#undef XOpenIM
+#undef XCloseIM
+#undef XGetIMValues
+#undef XSetIMValues
+#undef XDisplayOfIM
+#undef XLocaleOfIM
+#undef XCreateIC
+#undef XDestroyIC
+#undef XSetICFocus
+#undef XUnsetICFocus
+#undef XwcResetIC
+#undef XmbResetIC
+#undef Xutf8ResetIC
+#undef XSetICValues
+#undef XGetICValues
+#undef XIMOfIC
+#undef XFilterEvent
+#undef XmbLookupString
+#undef XwcLookupString
+#undef Xutf8LookupString
+#undef XVaCreateNestedList
+#undef XRegisterIMInstantiateCallback
+#undef XUnregisterIMInstantiateCallback
+#undef XInternalConnectionNumbers
+#undef XProcessInternalConnection
+#undef XAddConnectionWatch
+#undef XRemoveConnectionWatch
+#undef XSetAuthorization
+#undef _Xmbtowc
+#undef _Xwctomb
+#undef XGetEventData
+#undef XFreeEventData
+#undef XAllocClassHint
+#undef XAllocIconSize
+#undef XAllocSizeHints
+#undef XAllocStandardColormap
+#undef XAllocWMHints
+#undef XClipBox
+#undef XCreateRegion
+#undef XDefaultString
+#undef XDeleteContext
+#undef XDestroyRegion
+#undef XEmptyRegion
+#undef XEqualRegion
+#undef XFindContext
+#undef XGetClassHint
+#undef XGetIconSizes
+#undef XGetNormalHints
+#undef XGetRGBColormaps
+#undef XGetSizeHints
+#undef XGetStandardColormap
+#undef XGetTextProperty
+#undef XGetVisualInfo
+#undef XGetWMClientMachine
+#undef XGetWMHints
+#undef XGetWMIconName
+#undef XGetWMName
+#undef XGetWMNormalHints
+#undef XGetWMSizeHints
+#undef XGetZoomHints
+#undef XIntersectRegion
+#undef XConvertCase
+#undef XLookupString
+#undef XMatchVisualInfo
+#undef XOffsetRegion
+#undef XPointInRegion
+#undef XPolygonRegion
+#undef XRectInRegion
+#undef XSaveContext
+#undef XSetClassHint
+#undef XSetIconSizes
+#undef XSetNormalHints
+#undef XSetRGBColormaps
+#undef XSetSizeHints
+#undef XSetStandardProperties
+#undef XSetTextProperty
+#undef XSetWMClientMachine
+#undef XSetWMHints
+#undef XSetWMIconName
+#undef XSetWMName
+#undef XSetWMNormalHints
+#undef XSetWMProperties
+#undef XmbSetWMProperties
+#undef Xutf8SetWMProperties
+#undef XSetWMSizeHints
+#undef XSetRegion
+#undef XSetStandardColormap
+#undef XSetZoomHints
+#undef XShrinkRegion
+#undef XStringListToTextProperty
+#undef XSubtractRegion
+#undef XmbTextListToTextProperty
+#undef XwcTextListToTextProperty
+#undef Xutf8TextListToTextProperty
+#undef XwcFreeStringList
+#undef XTextPropertyToStringList
+#undef XmbTextPropertyToTextList
+#undef XwcTextPropertyToTextList
+#undef Xutf8TextPropertyToTextList
+#undef XUnionRectWithRegion
+#undef XUnionRegion
+#undef XWMGeometry
+#undef XXorRegion
+#undef XkbIgnoreExtension
+#undef XkbOpenDisplay
+#undef XkbQueryExtension
+#undef XkbUseExtension
+#undef XkbLibraryVersion
+#undef XkbSetXlibControls
+#undef XkbGetXlibControls
+#undef XkbXlibControlsImplemented
+#undef XkbSetAtomFuncs
+#undef XkbKeycodeToKeysym
+#undef XkbKeysymToModifiers
+#undef XkbLookupKeySym
+#undef XkbLookupKeyBinding
+#undef XkbTranslateKeyCode
+#undef XkbTranslateKeySym
+#undef XkbSetAutoRepeatRate
+#undef XkbGetAutoRepeatRate
+#undef XkbChangeEnabledControls
+#undef XkbDeviceBell
+#undef XkbForceDeviceBell
+#undef XkbDeviceBellEvent
+#undef XkbBell
+#undef XkbForceBell
+#undef XkbBellEvent
+#undef XkbSelectEvents
+#undef XkbSelectEventDetails
+#undef XkbNoteMapChanges
+#undef XkbNoteNameChanges
+#undef XkbGetIndicatorState
+#undef XkbGetIndicatorMap
+#undef XkbSetIndicatorMap
+#undef XkbGetNamedIndicator
+#undef XkbGetNamedDeviceIndicator
+#undef XkbSetNamedIndicator
+#undef XkbSetNamedDeviceIndicator
+#undef XkbLockModifiers
+#undef XkbLatchModifiers
+#undef XkbLockGroup
+#undef XkbLatchGroup
+#undef XkbSetServerInternalMods
+#undef XkbSetIgnoreLockMods
+#undef XkbVirtualModsToReal
+#undef XkbComputeEffectiveMap
+#undef XkbInitCanonicalKeyTypes
+#undef XkbAllocKeyboard
+#undef XkbFreeKeyboard
+#undef XkbAllocClientMap
+#undef XkbAllocServerMap
+#undef XkbFreeClientMap
+#undef XkbFreeServerMap
+#undef XkbAddKeyType
+#undef XkbAllocIndicatorMaps
+#undef XkbFreeIndicatorMaps
+#undef XkbGetMap
+#undef XkbGetUpdatedMap
+#undef XkbGetMapChanges
+#undef XkbRefreshKeyboardMapping
+#undef XkbGetKeyTypes
+#undef XkbGetKeySyms
+#undef XkbGetKeyActions
+#undef XkbGetKeyBehaviors
+#undef XkbGetVirtualMods
+#undef XkbGetKeyExplicitComponents
+#undef XkbGetKeyModifierMap
+#undef XkbGetKeyVirtualModMap
+#undef XkbAllocControls
+#undef XkbFreeControls
+#undef XkbGetControls
+#undef XkbSetControls
+#undef XkbNoteControlsChanges
+#undef XkbAllocCompatMap
+#undef XkbFreeCompatMap
+#undef XkbGetCompatMap
+#undef XkbSetCompatMap
+#undef XkbAllocNames
+#undef XkbGetNames
+#undef XkbSetNames
+#undef XkbChangeNames
+#undef XkbFreeNames
+#undef XkbGetState
+#undef XkbSetMap
+#undef XkbChangeMap
+#undef XkbSetDetectableAutoRepeat
+#undef XkbGetDetectableAutoRepeat
+#undef XkbSetAutoResetControls
+#undef XkbGetAutoResetControls
+#undef XkbSetPerClientControls
+#undef XkbGetPerClientControls
+#undef XkbCopyKeyType
+#undef XkbCopyKeyTypes
+#undef XkbResizeKeyType
+#undef XkbResizeKeySyms
+#undef XkbResizeKeyActions
+#undef XkbChangeTypesOfKey
+#undef XkbChangeKeycodeRange
+#undef XkbListComponents
+#undef XkbFreeComponentList
+#undef XkbGetKeyboard
+#undef XkbGetKeyboardByName
+#undef XkbKeyTypesForCoreSymbols
+#undef XkbApplyCompatMapToKey
+#undef XkbUpdateMapFromCore
+#undef XkbAddDeviceLedInfo
+#undef XkbResizeDeviceButtonActions
+#undef XkbAllocDeviceInfo
+#undef XkbFreeDeviceInfo
+#undef XkbNoteDeviceChanges
+#undef XkbGetDeviceInfo
+#undef XkbGetDeviceInfoChanges
+#undef XkbGetDeviceButtonActions
+#undef XkbGetDeviceLedInfo
+#undef XkbSetDeviceInfo
+#undef XkbChangeDeviceInfo
+#undef XkbSetDeviceLedInfo
+#undef XkbSetDeviceButtonActions
+#undef XkbToControl
+#undef XkbSetDebuggingFlags
+#undef XkbApplyVirtualModChanges
+#undef XkbUpdateActionVirtualMods
+#undef XkbUpdateKeyTypeVirtualMods
+#include <dlfcn.h>
+#include <stdio.h>
+int (*_Xmblen_dylibloader_wrapper_xlib)( char*, int);
+XFontStruct* (*XLoadQueryFont_dylibloader_wrapper_xlib)( Display*,const char*);
+XFontStruct* (*XQueryFont_dylibloader_wrapper_xlib)( Display*, XID);
+XTimeCoord* (*XGetMotionEvents_dylibloader_wrapper_xlib)( Display*, Window, Time, Time, int*);
+XModifierKeymap* (*XDeleteModifiermapEntry_dylibloader_wrapper_xlib)( XModifierKeymap*, KeyCode, int);
+XModifierKeymap* (*XGetModifierMapping_dylibloader_wrapper_xlib)( Display*);
+XModifierKeymap* (*XInsertModifiermapEntry_dylibloader_wrapper_xlib)( XModifierKeymap*, KeyCode, int);
+XModifierKeymap* (*XNewModifiermap_dylibloader_wrapper_xlib)( int);
+XImage* (*XCreateImage_dylibloader_wrapper_xlib)( Display*, Visual*, unsigned int, int, int, char*, unsigned int, unsigned int, int, int);
+int (*XInitImage_dylibloader_wrapper_xlib)( XImage*);
+XImage* (*XGetImage_dylibloader_wrapper_xlib)( Display*, Drawable, int, int, unsigned int, unsigned int, unsigned long, int);
+XImage* (*XGetSubImage_dylibloader_wrapper_xlib)( Display*, Drawable, int, int, unsigned int, unsigned int, unsigned long, int, XImage*, int, int);
+Display* (*XOpenDisplay_dylibloader_wrapper_xlib)(const char*);
+void (*XrmInitialize_dylibloader_wrapper_xlib)( void);
+char* (*XFetchBytes_dylibloader_wrapper_xlib)( Display*, int*);
+char* (*XFetchBuffer_dylibloader_wrapper_xlib)( Display*, int*, int);
+char* (*XGetAtomName_dylibloader_wrapper_xlib)( Display*, Atom);
+int (*XGetAtomNames_dylibloader_wrapper_xlib)( Display*, Atom*, int, char**);
+char* (*XGetDefault_dylibloader_wrapper_xlib)( Display*,const char*,const char*);
+char* (*XDisplayName_dylibloader_wrapper_xlib)(const char*);
+char* (*XKeysymToString_dylibloader_wrapper_xlib)( KeySym);
+int* (*XSynchronize_dylibloader_wrapper_xlib)( Display*, int);
+int* (*XSetAfterFunction_dylibloader_wrapper_xlib)( Display*, int*);
+Atom (*XInternAtom_dylibloader_wrapper_xlib)( Display*,const char*, int);
+int (*XInternAtoms_dylibloader_wrapper_xlib)( Display*, char**, int, int, Atom*);
+Colormap (*XCopyColormapAndFree_dylibloader_wrapper_xlib)( Display*, Colormap);
+Colormap (*XCreateColormap_dylibloader_wrapper_xlib)( Display*, Window, Visual*, int);
+Cursor (*XCreatePixmapCursor_dylibloader_wrapper_xlib)( Display*, Pixmap, Pixmap, XColor*, XColor*, unsigned int, unsigned int);
+Cursor (*XCreateGlyphCursor_dylibloader_wrapper_xlib)( Display*, Font, Font, unsigned int, unsigned int,const XColor*,const XColor*);
+Cursor (*XCreateFontCursor_dylibloader_wrapper_xlib)( Display*, unsigned int);
+Font (*XLoadFont_dylibloader_wrapper_xlib)( Display*,const char*);
+GC (*XCreateGC_dylibloader_wrapper_xlib)( Display*, Drawable, unsigned long, XGCValues*);
+GContext (*XGContextFromGC_dylibloader_wrapper_xlib)( GC);
+void (*XFlushGC_dylibloader_wrapper_xlib)( Display*, GC);
+Pixmap (*XCreatePixmap_dylibloader_wrapper_xlib)( Display*, Drawable, unsigned int, unsigned int, unsigned int);
+Pixmap (*XCreateBitmapFromData_dylibloader_wrapper_xlib)( Display*, Drawable,const char*, unsigned int, unsigned int);
+Pixmap (*XCreatePixmapFromBitmapData_dylibloader_wrapper_xlib)( Display*, Drawable, char*, unsigned int, unsigned int, unsigned long, unsigned long, unsigned int);
+Window (*XCreateSimpleWindow_dylibloader_wrapper_xlib)( Display*, Window, int, int, unsigned int, unsigned int, unsigned int, unsigned long, unsigned long);
+Window (*XGetSelectionOwner_dylibloader_wrapper_xlib)( Display*, Atom);
+Window (*XCreateWindow_dylibloader_wrapper_xlib)( Display*, Window, int, int, unsigned int, unsigned int, unsigned int, int, unsigned int, Visual*, unsigned long, XSetWindowAttributes*);
+Colormap* (*XListInstalledColormaps_dylibloader_wrapper_xlib)( Display*, Window, int*);
+char** (*XListFonts_dylibloader_wrapper_xlib)( Display*,const char*, int, int*);
+char** (*XListFontsWithInfo_dylibloader_wrapper_xlib)( Display*,const char*, int, int*, XFontStruct**);
+char** (*XGetFontPath_dylibloader_wrapper_xlib)( Display*, int*);
+char** (*XListExtensions_dylibloader_wrapper_xlib)( Display*, int*);
+Atom* (*XListProperties_dylibloader_wrapper_xlib)( Display*, Window, int*);
+XHostAddress* (*XListHosts_dylibloader_wrapper_xlib)( Display*, int*, int*);
+KeySym (*XKeycodeToKeysym_dylibloader_wrapper_xlib)( Display*, KeyCode, int);
+KeySym (*XLookupKeysym_dylibloader_wrapper_xlib)( XKeyEvent*, int);
+KeySym* (*XGetKeyboardMapping_dylibloader_wrapper_xlib)( Display*, KeyCode, int, int*);
+KeySym (*XStringToKeysym_dylibloader_wrapper_xlib)(const char*);
+long (*XMaxRequestSize_dylibloader_wrapper_xlib)( Display*);
+long (*XExtendedMaxRequestSize_dylibloader_wrapper_xlib)( Display*);
+char* (*XResourceManagerString_dylibloader_wrapper_xlib)( Display*);
+char* (*XScreenResourceString_dylibloader_wrapper_xlib)( Screen*);
+unsigned long (*XDisplayMotionBufferSize_dylibloader_wrapper_xlib)( Display*);
+VisualID (*XVisualIDFromVisual_dylibloader_wrapper_xlib)( Visual*);
+int (*XInitThreads_dylibloader_wrapper_xlib)( void);
+void (*XLockDisplay_dylibloader_wrapper_xlib)( Display*);
+void (*XUnlockDisplay_dylibloader_wrapper_xlib)( Display*);
+XExtCodes* (*XInitExtension_dylibloader_wrapper_xlib)( Display*,const char*);
+XExtCodes* (*XAddExtension_dylibloader_wrapper_xlib)( Display*);
+XExtData* (*XFindOnExtensionList_dylibloader_wrapper_xlib)( XExtData**, int);
+XExtData** (*XEHeadOfExtensionList_dylibloader_wrapper_xlib)( XEDataObject);
+Window (*XRootWindow_dylibloader_wrapper_xlib)( Display*, int);
+Window (*XDefaultRootWindow_dylibloader_wrapper_xlib)( Display*);
+Window (*XRootWindowOfScreen_dylibloader_wrapper_xlib)( Screen*);
+Visual* (*XDefaultVisual_dylibloader_wrapper_xlib)( Display*, int);
+Visual* (*XDefaultVisualOfScreen_dylibloader_wrapper_xlib)( Screen*);
+GC (*XDefaultGC_dylibloader_wrapper_xlib)( Display*, int);
+GC (*XDefaultGCOfScreen_dylibloader_wrapper_xlib)( Screen*);
+unsigned long (*XBlackPixel_dylibloader_wrapper_xlib)( Display*, int);
+unsigned long (*XWhitePixel_dylibloader_wrapper_xlib)( Display*, int);
+unsigned long (*XAllPlanes_dylibloader_wrapper_xlib)( void);
+unsigned long (*XBlackPixelOfScreen_dylibloader_wrapper_xlib)( Screen*);
+unsigned long (*XWhitePixelOfScreen_dylibloader_wrapper_xlib)( Screen*);
+unsigned long (*XNextRequest_dylibloader_wrapper_xlib)( Display*);
+unsigned long (*XLastKnownRequestProcessed_dylibloader_wrapper_xlib)( Display*);
+char* (*XServerVendor_dylibloader_wrapper_xlib)( Display*);
+char* (*XDisplayString_dylibloader_wrapper_xlib)( Display*);
+Colormap (*XDefaultColormap_dylibloader_wrapper_xlib)( Display*, int);
+Colormap (*XDefaultColormapOfScreen_dylibloader_wrapper_xlib)( Screen*);
+Display* (*XDisplayOfScreen_dylibloader_wrapper_xlib)( Screen*);
+Screen* (*XScreenOfDisplay_dylibloader_wrapper_xlib)( Display*, int);
+Screen* (*XDefaultScreenOfDisplay_dylibloader_wrapper_xlib)( Display*);
+long (*XEventMaskOfScreen_dylibloader_wrapper_xlib)( Screen*);
+int (*XScreenNumberOfScreen_dylibloader_wrapper_xlib)( Screen*);
+XErrorHandler (*XSetErrorHandler_dylibloader_wrapper_xlib)( XErrorHandler);
+XIOErrorHandler (*XSetIOErrorHandler_dylibloader_wrapper_xlib)( XIOErrorHandler);
+XPixmapFormatValues* (*XListPixmapFormats_dylibloader_wrapper_xlib)( Display*, int*);
+int* (*XListDepths_dylibloader_wrapper_xlib)( Display*, int, int*);
+int (*XReconfigureWMWindow_dylibloader_wrapper_xlib)( Display*, Window, int, unsigned int, XWindowChanges*);
+int (*XGetWMProtocols_dylibloader_wrapper_xlib)( Display*, Window, Atom**, int*);
+int (*XSetWMProtocols_dylibloader_wrapper_xlib)( Display*, Window, Atom*, int);
+int (*XIconifyWindow_dylibloader_wrapper_xlib)( Display*, Window, int);
+int (*XWithdrawWindow_dylibloader_wrapper_xlib)( Display*, Window, int);
+int (*XGetCommand_dylibloader_wrapper_xlib)( Display*, Window, char***, int*);
+int (*XGetWMColormapWindows_dylibloader_wrapper_xlib)( Display*, Window, Window**, int*);
+int (*XSetWMColormapWindows_dylibloader_wrapper_xlib)( Display*, Window, Window*, int);
+void (*XFreeStringList_dylibloader_wrapper_xlib)( char**);
+int (*XSetTransientForHint_dylibloader_wrapper_xlib)( Display*, Window, Window);
+int (*XActivateScreenSaver_dylibloader_wrapper_xlib)( Display*);
+int (*XAddHost_dylibloader_wrapper_xlib)( Display*, XHostAddress*);
+int (*XAddHosts_dylibloader_wrapper_xlib)( Display*, XHostAddress*, int);
+int (*XAddToExtensionList_dylibloader_wrapper_xlib)(struct _XExtData**, XExtData*);
+int (*XAddToSaveSet_dylibloader_wrapper_xlib)( Display*, Window);
+int (*XAllocColor_dylibloader_wrapper_xlib)( Display*, Colormap, XColor*);
+int (*XAllocColorCells_dylibloader_wrapper_xlib)( Display*, Colormap, int, unsigned long*, unsigned int, unsigned long*, unsigned int);
+int (*XAllocColorPlanes_dylibloader_wrapper_xlib)( Display*, Colormap, int, unsigned long*, int, int, int, int, unsigned long*, unsigned long*, unsigned long*);
+int (*XAllocNamedColor_dylibloader_wrapper_xlib)( Display*, Colormap,const char*, XColor*, XColor*);
+int (*XAllowEvents_dylibloader_wrapper_xlib)( Display*, int, Time);
+int (*XAutoRepeatOff_dylibloader_wrapper_xlib)( Display*);
+int (*XAutoRepeatOn_dylibloader_wrapper_xlib)( Display*);
+int (*XBell_dylibloader_wrapper_xlib)( Display*, int);
+int (*XBitmapBitOrder_dylibloader_wrapper_xlib)( Display*);
+int (*XBitmapPad_dylibloader_wrapper_xlib)( Display*);
+int (*XBitmapUnit_dylibloader_wrapper_xlib)( Display*);
+int (*XCellsOfScreen_dylibloader_wrapper_xlib)( Screen*);
+int (*XChangeActivePointerGrab_dylibloader_wrapper_xlib)( Display*, unsigned int, Cursor, Time);
+int (*XChangeGC_dylibloader_wrapper_xlib)( Display*, GC, unsigned long, XGCValues*);
+int (*XChangeKeyboardControl_dylibloader_wrapper_xlib)( Display*, unsigned long, XKeyboardControl*);
+int (*XChangeKeyboardMapping_dylibloader_wrapper_xlib)( Display*, int, int, KeySym*, int);
+int (*XChangePointerControl_dylibloader_wrapper_xlib)( Display*, int, int, int, int, int);
+int (*XChangeProperty_dylibloader_wrapper_xlib)( Display*, Window, Atom, Atom, int, int,const unsigned char*, int);
+int (*XChangeSaveSet_dylibloader_wrapper_xlib)( Display*, Window, int);
+int (*XChangeWindowAttributes_dylibloader_wrapper_xlib)( Display*, Window, unsigned long, XSetWindowAttributes*);
+int (*XCheckIfEvent_dylibloader_wrapper_xlib)( Display*, XEvent*, Bool (*) (Display*, XEvent*, XPointer), XPointer);
+int (*XCheckMaskEvent_dylibloader_wrapper_xlib)( Display*, long, XEvent*);
+int (*XCheckTypedEvent_dylibloader_wrapper_xlib)( Display*, int, XEvent*);
+int (*XCheckTypedWindowEvent_dylibloader_wrapper_xlib)( Display*, Window, int, XEvent*);
+int (*XCheckWindowEvent_dylibloader_wrapper_xlib)( Display*, Window, long, XEvent*);
+int (*XCirculateSubwindows_dylibloader_wrapper_xlib)( Display*, Window, int);
+int (*XCirculateSubwindowsDown_dylibloader_wrapper_xlib)( Display*, Window);
+int (*XCirculateSubwindowsUp_dylibloader_wrapper_xlib)( Display*, Window);
+int (*XClearArea_dylibloader_wrapper_xlib)( Display*, Window, int, int, unsigned int, unsigned int, int);
+int (*XClearWindow_dylibloader_wrapper_xlib)( Display*, Window);
+int (*XCloseDisplay_dylibloader_wrapper_xlib)( Display*);
+int (*XConfigureWindow_dylibloader_wrapper_xlib)( Display*, Window, unsigned int, XWindowChanges*);
+int (*XConnectionNumber_dylibloader_wrapper_xlib)( Display*);
+int (*XConvertSelection_dylibloader_wrapper_xlib)( Display*, Atom, Atom, Atom, Window, Time);
+int (*XCopyArea_dylibloader_wrapper_xlib)( Display*, Drawable, Drawable, GC, int, int, unsigned int, unsigned int, int, int);
+int (*XCopyGC_dylibloader_wrapper_xlib)( Display*, GC, unsigned long, GC);
+int (*XCopyPlane_dylibloader_wrapper_xlib)( Display*, Drawable, Drawable, GC, int, int, unsigned int, unsigned int, int, int, unsigned long);
+int (*XDefaultDepth_dylibloader_wrapper_xlib)( Display*, int);
+int (*XDefaultDepthOfScreen_dylibloader_wrapper_xlib)( Screen*);
+int (*XDefaultScreen_dylibloader_wrapper_xlib)( Display*);
+int (*XDefineCursor_dylibloader_wrapper_xlib)( Display*, Window, Cursor);
+int (*XDeleteProperty_dylibloader_wrapper_xlib)( Display*, Window, Atom);
+int (*XDestroyWindow_dylibloader_wrapper_xlib)( Display*, Window);
+int (*XDestroySubwindows_dylibloader_wrapper_xlib)( Display*, Window);
+int (*XDoesBackingStore_dylibloader_wrapper_xlib)( Screen*);
+int (*XDoesSaveUnders_dylibloader_wrapper_xlib)( Screen*);
+int (*XDisableAccessControl_dylibloader_wrapper_xlib)( Display*);
+int (*XDisplayCells_dylibloader_wrapper_xlib)( Display*, int);
+int (*XDisplayHeight_dylibloader_wrapper_xlib)( Display*, int);
+int (*XDisplayHeightMM_dylibloader_wrapper_xlib)( Display*, int);
+int (*XDisplayKeycodes_dylibloader_wrapper_xlib)( Display*, int*, int*);
+int (*XDisplayPlanes_dylibloader_wrapper_xlib)( Display*, int);
+int (*XDisplayWidth_dylibloader_wrapper_xlib)( Display*, int);
+int (*XDisplayWidthMM_dylibloader_wrapper_xlib)( Display*, int);
+int (*XDrawArc_dylibloader_wrapper_xlib)( Display*, Drawable, GC, int, int, unsigned int, unsigned int, int, int);
+int (*XDrawArcs_dylibloader_wrapper_xlib)( Display*, Drawable, GC, XArc*, int);
+int (*XDrawImageString_dylibloader_wrapper_xlib)( Display*, Drawable, GC, int, int,const char*, int);
+int (*XDrawImageString16_dylibloader_wrapper_xlib)( Display*, Drawable, GC, int, int,const XChar2b*, int);
+int (*XDrawLine_dylibloader_wrapper_xlib)( Display*, Drawable, GC, int, int, int, int);
+int (*XDrawLines_dylibloader_wrapper_xlib)( Display*, Drawable, GC, XPoint*, int, int);
+int (*XDrawPoint_dylibloader_wrapper_xlib)( Display*, Drawable, GC, int, int);
+int (*XDrawPoints_dylibloader_wrapper_xlib)( Display*, Drawable, GC, XPoint*, int, int);
+int (*XDrawRectangle_dylibloader_wrapper_xlib)( Display*, Drawable, GC, int, int, unsigned int, unsigned int);
+int (*XDrawRectangles_dylibloader_wrapper_xlib)( Display*, Drawable, GC, XRectangle*, int);
+int (*XDrawSegments_dylibloader_wrapper_xlib)( Display*, Drawable, GC, XSegment*, int);
+int (*XDrawString_dylibloader_wrapper_xlib)( Display*, Drawable, GC, int, int,const char*, int);
+int (*XDrawString16_dylibloader_wrapper_xlib)( Display*, Drawable, GC, int, int,const XChar2b*, int);
+int (*XDrawText_dylibloader_wrapper_xlib)( Display*, Drawable, GC, int, int, XTextItem*, int);
+int (*XDrawText16_dylibloader_wrapper_xlib)( Display*, Drawable, GC, int, int, XTextItem16*, int);
+int (*XEnableAccessControl_dylibloader_wrapper_xlib)( Display*);
+int (*XEventsQueued_dylibloader_wrapper_xlib)( Display*, int);
+int (*XFetchName_dylibloader_wrapper_xlib)( Display*, Window, char**);
+int (*XFillArc_dylibloader_wrapper_xlib)( Display*, Drawable, GC, int, int, unsigned int, unsigned int, int, int);
+int (*XFillArcs_dylibloader_wrapper_xlib)( Display*, Drawable, GC, XArc*, int);
+int (*XFillPolygon_dylibloader_wrapper_xlib)( Display*, Drawable, GC, XPoint*, int, int, int);
+int (*XFillRectangle_dylibloader_wrapper_xlib)( Display*, Drawable, GC, int, int, unsigned int, unsigned int);
+int (*XFillRectangles_dylibloader_wrapper_xlib)( Display*, Drawable, GC, XRectangle*, int);
+int (*XFlush_dylibloader_wrapper_xlib)( Display*);
+int (*XForceScreenSaver_dylibloader_wrapper_xlib)( Display*, int);
+int (*XFree_dylibloader_wrapper_xlib)( void*);
+int (*XFreeColormap_dylibloader_wrapper_xlib)( Display*, Colormap);
+int (*XFreeColors_dylibloader_wrapper_xlib)( Display*, Colormap, unsigned long*, int, unsigned long);
+int (*XFreeCursor_dylibloader_wrapper_xlib)( Display*, Cursor);
+int (*XFreeExtensionList_dylibloader_wrapper_xlib)( char**);
+int (*XFreeFont_dylibloader_wrapper_xlib)( Display*, XFontStruct*);
+int (*XFreeFontInfo_dylibloader_wrapper_xlib)( char**, XFontStruct*, int);
+int (*XFreeFontNames_dylibloader_wrapper_xlib)( char**);
+int (*XFreeFontPath_dylibloader_wrapper_xlib)( char**);
+int (*XFreeGC_dylibloader_wrapper_xlib)( Display*, GC);
+int (*XFreeModifiermap_dylibloader_wrapper_xlib)( XModifierKeymap*);
+int (*XFreePixmap_dylibloader_wrapper_xlib)( Display*, Pixmap);
+int (*XGeometry_dylibloader_wrapper_xlib)( Display*, int,const char*,const char*, unsigned int, unsigned int, unsigned int, int, int, int*, int*, int*, int*);
+int (*XGetErrorDatabaseText_dylibloader_wrapper_xlib)( Display*,const char*,const char*,const char*, char*, int);
+int (*XGetErrorText_dylibloader_wrapper_xlib)( Display*, int, char*, int);
+int (*XGetFontProperty_dylibloader_wrapper_xlib)( XFontStruct*, Atom, unsigned long*);
+int (*XGetGCValues_dylibloader_wrapper_xlib)( Display*, GC, unsigned long, XGCValues*);
+int (*XGetGeometry_dylibloader_wrapper_xlib)( Display*, Drawable, Window*, int*, int*, unsigned int*, unsigned int*, unsigned int*, unsigned int*);
+int (*XGetIconName_dylibloader_wrapper_xlib)( Display*, Window, char**);
+int (*XGetInputFocus_dylibloader_wrapper_xlib)( Display*, Window*, int*);
+int (*XGetKeyboardControl_dylibloader_wrapper_xlib)( Display*, XKeyboardState*);
+int (*XGetPointerControl_dylibloader_wrapper_xlib)( Display*, int*, int*, int*);
+int (*XGetPointerMapping_dylibloader_wrapper_xlib)( Display*, unsigned char*, int);
+int (*XGetScreenSaver_dylibloader_wrapper_xlib)( Display*, int*, int*, int*, int*);
+int (*XGetTransientForHint_dylibloader_wrapper_xlib)( Display*, Window, Window*);
+int (*XGetWindowProperty_dylibloader_wrapper_xlib)( Display*, Window, Atom, long, long, int, Atom, Atom*, int*, unsigned long*, unsigned long*, unsigned char**);
+int (*XGetWindowAttributes_dylibloader_wrapper_xlib)( Display*, Window, XWindowAttributes*);
+int (*XGrabButton_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, Window, int, unsigned int, int, int, Window, Cursor);
+int (*XGrabKey_dylibloader_wrapper_xlib)( Display*, int, unsigned int, Window, int, int, int);
+int (*XGrabKeyboard_dylibloader_wrapper_xlib)( Display*, Window, int, int, int, Time);
+int (*XGrabPointer_dylibloader_wrapper_xlib)( Display*, Window, int, unsigned int, int, int, Window, Cursor, Time);
+int (*XGrabServer_dylibloader_wrapper_xlib)( Display*);
+int (*XHeightMMOfScreen_dylibloader_wrapper_xlib)( Screen*);
+int (*XHeightOfScreen_dylibloader_wrapper_xlib)( Screen*);
+int (*XIfEvent_dylibloader_wrapper_xlib)( Display*, XEvent*, Bool (*) (Display*, XEvent*, XPointer), XPointer);
+int (*XImageByteOrder_dylibloader_wrapper_xlib)( Display*);
+int (*XInstallColormap_dylibloader_wrapper_xlib)( Display*, Colormap);
+KeyCode (*XKeysymToKeycode_dylibloader_wrapper_xlib)( Display*, KeySym);
+int (*XKillClient_dylibloader_wrapper_xlib)( Display*, XID);
+int (*XLookupColor_dylibloader_wrapper_xlib)( Display*, Colormap,const char*, XColor*, XColor*);
+int (*XLowerWindow_dylibloader_wrapper_xlib)( Display*, Window);
+int (*XMapRaised_dylibloader_wrapper_xlib)( Display*, Window);
+int (*XMapSubwindows_dylibloader_wrapper_xlib)( Display*, Window);
+int (*XMapWindow_dylibloader_wrapper_xlib)( Display*, Window);
+int (*XMaskEvent_dylibloader_wrapper_xlib)( Display*, long, XEvent*);
+int (*XMaxCmapsOfScreen_dylibloader_wrapper_xlib)( Screen*);
+int (*XMinCmapsOfScreen_dylibloader_wrapper_xlib)( Screen*);
+int (*XMoveResizeWindow_dylibloader_wrapper_xlib)( Display*, Window, int, int, unsigned int, unsigned int);
+int (*XMoveWindow_dylibloader_wrapper_xlib)( Display*, Window, int, int);
+int (*XNextEvent_dylibloader_wrapper_xlib)( Display*, XEvent*);
+int (*XNoOp_dylibloader_wrapper_xlib)( Display*);
+int (*XParseColor_dylibloader_wrapper_xlib)( Display*, Colormap,const char*, XColor*);
+int (*XParseGeometry_dylibloader_wrapper_xlib)(const char*, int*, int*, unsigned int*, unsigned int*);
+int (*XPeekEvent_dylibloader_wrapper_xlib)( Display*, XEvent*);
+int (*XPeekIfEvent_dylibloader_wrapper_xlib)( Display*, XEvent*, Bool (*) (Display*, XEvent*, XPointer), XPointer);
+int (*XPending_dylibloader_wrapper_xlib)( Display*);
+int (*XPlanesOfScreen_dylibloader_wrapper_xlib)( Screen*);
+int (*XProtocolRevision_dylibloader_wrapper_xlib)( Display*);
+int (*XProtocolVersion_dylibloader_wrapper_xlib)( Display*);
+int (*XPutBackEvent_dylibloader_wrapper_xlib)( Display*, XEvent*);
+int (*XPutImage_dylibloader_wrapper_xlib)( Display*, Drawable, GC, XImage*, int, int, int, int, unsigned int, unsigned int);
+int (*XQLength_dylibloader_wrapper_xlib)( Display*);
+int (*XQueryBestCursor_dylibloader_wrapper_xlib)( Display*, Drawable, unsigned int, unsigned int, unsigned int*, unsigned int*);
+int (*XQueryBestSize_dylibloader_wrapper_xlib)( Display*, int, Drawable, unsigned int, unsigned int, unsigned int*, unsigned int*);
+int (*XQueryBestStipple_dylibloader_wrapper_xlib)( Display*, Drawable, unsigned int, unsigned int, unsigned int*, unsigned int*);
+int (*XQueryBestTile_dylibloader_wrapper_xlib)( Display*, Drawable, unsigned int, unsigned int, unsigned int*, unsigned int*);
+int (*XQueryColor_dylibloader_wrapper_xlib)( Display*, Colormap, XColor*);
+int (*XQueryColors_dylibloader_wrapper_xlib)( Display*, Colormap, XColor*, int);
+int (*XQueryExtension_dylibloader_wrapper_xlib)( Display*,const char*, int*, int*, int*);
+int (*XQueryKeymap_dylibloader_wrapper_xlib)( Display*, char [32]);
+int (*XQueryPointer_dylibloader_wrapper_xlib)( Display*, Window, Window*, Window*, int*, int*, int*, int*, unsigned int*);
+int (*XQueryTextExtents_dylibloader_wrapper_xlib)( Display*, XID,const char*, int, int*, int*, int*, XCharStruct*);
+int (*XQueryTextExtents16_dylibloader_wrapper_xlib)( Display*, XID,const XChar2b*, int, int*, int*, int*, XCharStruct*);
+int (*XQueryTree_dylibloader_wrapper_xlib)( Display*, Window, Window*, Window*, Window**, unsigned int*);
+int (*XRaiseWindow_dylibloader_wrapper_xlib)( Display*, Window);
+int (*XReadBitmapFile_dylibloader_wrapper_xlib)( Display*, Drawable,const char*, unsigned int*, unsigned int*, Pixmap*, int*, int*);
+int (*XReadBitmapFileData_dylibloader_wrapper_xlib)(const char*, unsigned int*, unsigned int*, unsigned char**, int*, int*);
+int (*XRebindKeysym_dylibloader_wrapper_xlib)( Display*, KeySym, KeySym*, int,const unsigned char*, int);
+int (*XRecolorCursor_dylibloader_wrapper_xlib)( Display*, Cursor, XColor*, XColor*);
+int (*XRefreshKeyboardMapping_dylibloader_wrapper_xlib)( XMappingEvent*);
+int (*XRemoveFromSaveSet_dylibloader_wrapper_xlib)( Display*, Window);
+int (*XRemoveHost_dylibloader_wrapper_xlib)( Display*, XHostAddress*);
+int (*XRemoveHosts_dylibloader_wrapper_xlib)( Display*, XHostAddress*, int);
+int (*XReparentWindow_dylibloader_wrapper_xlib)( Display*, Window, Window, int, int);
+int (*XResetScreenSaver_dylibloader_wrapper_xlib)( Display*);
+int (*XResizeWindow_dylibloader_wrapper_xlib)( Display*, Window, unsigned int, unsigned int);
+int (*XRestackWindows_dylibloader_wrapper_xlib)( Display*, Window*, int);
+int (*XRotateBuffers_dylibloader_wrapper_xlib)( Display*, int);
+int (*XRotateWindowProperties_dylibloader_wrapper_xlib)( Display*, Window, Atom*, int, int);
+int (*XScreenCount_dylibloader_wrapper_xlib)( Display*);
+int (*XSelectInput_dylibloader_wrapper_xlib)( Display*, Window, long);
+int (*XSendEvent_dylibloader_wrapper_xlib)( Display*, Window, int, long, XEvent*);
+int (*XSetAccessControl_dylibloader_wrapper_xlib)( Display*, int);
+int (*XSetArcMode_dylibloader_wrapper_xlib)( Display*, GC, int);
+int (*XSetBackground_dylibloader_wrapper_xlib)( Display*, GC, unsigned long);
+int (*XSetClipMask_dylibloader_wrapper_xlib)( Display*, GC, Pixmap);
+int (*XSetClipOrigin_dylibloader_wrapper_xlib)( Display*, GC, int, int);
+int (*XSetClipRectangles_dylibloader_wrapper_xlib)( Display*, GC, int, int, XRectangle*, int, int);
+int (*XSetCloseDownMode_dylibloader_wrapper_xlib)( Display*, int);
+int (*XSetCommand_dylibloader_wrapper_xlib)( Display*, Window, char**, int);
+int (*XSetDashes_dylibloader_wrapper_xlib)( Display*, GC, int,const char*, int);
+int (*XSetFillRule_dylibloader_wrapper_xlib)( Display*, GC, int);
+int (*XSetFillStyle_dylibloader_wrapper_xlib)( Display*, GC, int);
+int (*XSetFont_dylibloader_wrapper_xlib)( Display*, GC, Font);
+int (*XSetFontPath_dylibloader_wrapper_xlib)( Display*, char**, int);
+int (*XSetForeground_dylibloader_wrapper_xlib)( Display*, GC, unsigned long);
+int (*XSetFunction_dylibloader_wrapper_xlib)( Display*, GC, int);
+int (*XSetGraphicsExposures_dylibloader_wrapper_xlib)( Display*, GC, int);
+int (*XSetIconName_dylibloader_wrapper_xlib)( Display*, Window,const char*);
+int (*XSetInputFocus_dylibloader_wrapper_xlib)( Display*, Window, int, Time);
+int (*XSetLineAttributes_dylibloader_wrapper_xlib)( Display*, GC, unsigned int, int, int, int);
+int (*XSetModifierMapping_dylibloader_wrapper_xlib)( Display*, XModifierKeymap*);
+int (*XSetPlaneMask_dylibloader_wrapper_xlib)( Display*, GC, unsigned long);
+int (*XSetPointerMapping_dylibloader_wrapper_xlib)( Display*,const unsigned char*, int);
+int (*XSetScreenSaver_dylibloader_wrapper_xlib)( Display*, int, int, int, int);
+int (*XSetSelectionOwner_dylibloader_wrapper_xlib)( Display*, Atom, Window, Time);
+int (*XSetState_dylibloader_wrapper_xlib)( Display*, GC, unsigned long, unsigned long, int, unsigned long);
+int (*XSetStipple_dylibloader_wrapper_xlib)( Display*, GC, Pixmap);
+int (*XSetSubwindowMode_dylibloader_wrapper_xlib)( Display*, GC, int);
+int (*XSetTSOrigin_dylibloader_wrapper_xlib)( Display*, GC, int, int);
+int (*XSetTile_dylibloader_wrapper_xlib)( Display*, GC, Pixmap);
+int (*XSetWindowBackground_dylibloader_wrapper_xlib)( Display*, Window, unsigned long);
+int (*XSetWindowBackgroundPixmap_dylibloader_wrapper_xlib)( Display*, Window, Pixmap);
+int (*XSetWindowBorder_dylibloader_wrapper_xlib)( Display*, Window, unsigned long);
+int (*XSetWindowBorderPixmap_dylibloader_wrapper_xlib)( Display*, Window, Pixmap);
+int (*XSetWindowBorderWidth_dylibloader_wrapper_xlib)( Display*, Window, unsigned int);
+int (*XSetWindowColormap_dylibloader_wrapper_xlib)( Display*, Window, Colormap);
+int (*XStoreBuffer_dylibloader_wrapper_xlib)( Display*,const char*, int, int);
+int (*XStoreBytes_dylibloader_wrapper_xlib)( Display*,const char*, int);
+int (*XStoreColor_dylibloader_wrapper_xlib)( Display*, Colormap, XColor*);
+int (*XStoreColors_dylibloader_wrapper_xlib)( Display*, Colormap, XColor*, int);
+int (*XStoreName_dylibloader_wrapper_xlib)( Display*, Window,const char*);
+int (*XStoreNamedColor_dylibloader_wrapper_xlib)( Display*, Colormap,const char*, unsigned long, int);
+int (*XSync_dylibloader_wrapper_xlib)( Display*, int);
+int (*XTextExtents_dylibloader_wrapper_xlib)( XFontStruct*,const char*, int, int*, int*, int*, XCharStruct*);
+int (*XTextExtents16_dylibloader_wrapper_xlib)( XFontStruct*,const XChar2b*, int, int*, int*, int*, XCharStruct*);
+int (*XTextWidth_dylibloader_wrapper_xlib)( XFontStruct*,const char*, int);
+int (*XTextWidth16_dylibloader_wrapper_xlib)( XFontStruct*,const XChar2b*, int);
+int (*XTranslateCoordinates_dylibloader_wrapper_xlib)( Display*, Window, Window, int, int, int*, int*, Window*);
+int (*XUndefineCursor_dylibloader_wrapper_xlib)( Display*, Window);
+int (*XUngrabButton_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, Window);
+int (*XUngrabKey_dylibloader_wrapper_xlib)( Display*, int, unsigned int, Window);
+int (*XUngrabKeyboard_dylibloader_wrapper_xlib)( Display*, Time);
+int (*XUngrabPointer_dylibloader_wrapper_xlib)( Display*, Time);
+int (*XUngrabServer_dylibloader_wrapper_xlib)( Display*);
+int (*XUninstallColormap_dylibloader_wrapper_xlib)( Display*, Colormap);
+int (*XUnloadFont_dylibloader_wrapper_xlib)( Display*, Font);
+int (*XUnmapSubwindows_dylibloader_wrapper_xlib)( Display*, Window);
+int (*XUnmapWindow_dylibloader_wrapper_xlib)( Display*, Window);
+int (*XVendorRelease_dylibloader_wrapper_xlib)( Display*);
+int (*XWarpPointer_dylibloader_wrapper_xlib)( Display*, Window, Window, int, int, unsigned int, unsigned int, int, int);
+int (*XWidthMMOfScreen_dylibloader_wrapper_xlib)( Screen*);
+int (*XWidthOfScreen_dylibloader_wrapper_xlib)( Screen*);
+int (*XWindowEvent_dylibloader_wrapper_xlib)( Display*, Window, long, XEvent*);
+int (*XWriteBitmapFile_dylibloader_wrapper_xlib)( Display*,const char*, Pixmap, unsigned int, unsigned int, int, int);
+int (*XSupportsLocale_dylibloader_wrapper_xlib)( void);
+char* (*XSetLocaleModifiers_dylibloader_wrapper_xlib)(const char*);
+XOM (*XOpenOM_dylibloader_wrapper_xlib)( Display*,struct _XrmHashBucketRec*,const char*,const char*);
+int (*XCloseOM_dylibloader_wrapper_xlib)( XOM);
+char* (*XSetOMValues_dylibloader_wrapper_xlib)( XOM,...);
+char* (*XGetOMValues_dylibloader_wrapper_xlib)( XOM,...);
+Display* (*XDisplayOfOM_dylibloader_wrapper_xlib)( XOM);
+char* (*XLocaleOfOM_dylibloader_wrapper_xlib)( XOM);
+XOC (*XCreateOC_dylibloader_wrapper_xlib)( XOM,...);
+void (*XDestroyOC_dylibloader_wrapper_xlib)( XOC);
+XOM (*XOMOfOC_dylibloader_wrapper_xlib)( XOC);
+char* (*XSetOCValues_dylibloader_wrapper_xlib)( XOC,...);
+char* (*XGetOCValues_dylibloader_wrapper_xlib)( XOC,...);
+XFontSet (*XCreateFontSet_dylibloader_wrapper_xlib)( Display*,const char*, char***, int*, char**);
+void (*XFreeFontSet_dylibloader_wrapper_xlib)( Display*, XFontSet);
+int (*XFontsOfFontSet_dylibloader_wrapper_xlib)( XFontSet, XFontStruct***, char***);
+char* (*XBaseFontNameListOfFontSet_dylibloader_wrapper_xlib)( XFontSet);
+char* (*XLocaleOfFontSet_dylibloader_wrapper_xlib)( XFontSet);
+int (*XContextDependentDrawing_dylibloader_wrapper_xlib)( XFontSet);
+int (*XDirectionalDependentDrawing_dylibloader_wrapper_xlib)( XFontSet);
+int (*XContextualDrawing_dylibloader_wrapper_xlib)( XFontSet);
+XFontSetExtents* (*XExtentsOfFontSet_dylibloader_wrapper_xlib)( XFontSet);
+int (*XmbTextEscapement_dylibloader_wrapper_xlib)( XFontSet,const char*, int);
+int (*XwcTextEscapement_dylibloader_wrapper_xlib)( XFontSet,const wchar_t*, int);
+int (*Xutf8TextEscapement_dylibloader_wrapper_xlib)( XFontSet,const char*, int);
+int (*XmbTextExtents_dylibloader_wrapper_xlib)( XFontSet,const char*, int, XRectangle*, XRectangle*);
+int (*XwcTextExtents_dylibloader_wrapper_xlib)( XFontSet,const wchar_t*, int, XRectangle*, XRectangle*);
+int (*Xutf8TextExtents_dylibloader_wrapper_xlib)( XFontSet,const char*, int, XRectangle*, XRectangle*);
+int (*XmbTextPerCharExtents_dylibloader_wrapper_xlib)( XFontSet,const char*, int, XRectangle*, XRectangle*, int, int*, XRectangle*, XRectangle*);
+int (*XwcTextPerCharExtents_dylibloader_wrapper_xlib)( XFontSet,const wchar_t*, int, XRectangle*, XRectangle*, int, int*, XRectangle*, XRectangle*);
+int (*Xutf8TextPerCharExtents_dylibloader_wrapper_xlib)( XFontSet,const char*, int, XRectangle*, XRectangle*, int, int*, XRectangle*, XRectangle*);
+void (*XmbDrawText_dylibloader_wrapper_xlib)( Display*, Drawable, GC, int, int, XmbTextItem*, int);
+void (*XwcDrawText_dylibloader_wrapper_xlib)( Display*, Drawable, GC, int, int, XwcTextItem*, int);
+void (*Xutf8DrawText_dylibloader_wrapper_xlib)( Display*, Drawable, GC, int, int, XmbTextItem*, int);
+void (*XmbDrawString_dylibloader_wrapper_xlib)( Display*, Drawable, XFontSet, GC, int, int,const char*, int);
+void (*XwcDrawString_dylibloader_wrapper_xlib)( Display*, Drawable, XFontSet, GC, int, int,const wchar_t*, int);
+void (*Xutf8DrawString_dylibloader_wrapper_xlib)( Display*, Drawable, XFontSet, GC, int, int,const char*, int);
+void (*XmbDrawImageString_dylibloader_wrapper_xlib)( Display*, Drawable, XFontSet, GC, int, int,const char*, int);
+void (*XwcDrawImageString_dylibloader_wrapper_xlib)( Display*, Drawable, XFontSet, GC, int, int,const wchar_t*, int);
+void (*Xutf8DrawImageString_dylibloader_wrapper_xlib)( Display*, Drawable, XFontSet, GC, int, int,const char*, int);
+XIM (*XOpenIM_dylibloader_wrapper_xlib)( Display*,struct _XrmHashBucketRec*, char*, char*);
+int (*XCloseIM_dylibloader_wrapper_xlib)( XIM);
+char* (*XGetIMValues_dylibloader_wrapper_xlib)( XIM,...);
+char* (*XSetIMValues_dylibloader_wrapper_xlib)( XIM,...);
+Display* (*XDisplayOfIM_dylibloader_wrapper_xlib)( XIM);
+char* (*XLocaleOfIM_dylibloader_wrapper_xlib)( XIM);
+XIC (*XCreateIC_dylibloader_wrapper_xlib)( XIM,...);
+void (*XDestroyIC_dylibloader_wrapper_xlib)( XIC);
+void (*XSetICFocus_dylibloader_wrapper_xlib)( XIC);
+void (*XUnsetICFocus_dylibloader_wrapper_xlib)( XIC);
+wchar_t* (*XwcResetIC_dylibloader_wrapper_xlib)( XIC);
+char* (*XmbResetIC_dylibloader_wrapper_xlib)( XIC);
+char* (*Xutf8ResetIC_dylibloader_wrapper_xlib)( XIC);
+char* (*XSetICValues_dylibloader_wrapper_xlib)( XIC,...);
+char* (*XGetICValues_dylibloader_wrapper_xlib)( XIC,...);
+XIM (*XIMOfIC_dylibloader_wrapper_xlib)( XIC);
+int (*XFilterEvent_dylibloader_wrapper_xlib)( XEvent*, Window);
+int (*XmbLookupString_dylibloader_wrapper_xlib)( XIC, XKeyPressedEvent*, char*, int, KeySym*, int*);
+int (*XwcLookupString_dylibloader_wrapper_xlib)( XIC, XKeyPressedEvent*, wchar_t*, int, KeySym*, int*);
+int (*Xutf8LookupString_dylibloader_wrapper_xlib)( XIC, XKeyPressedEvent*, char*, int, KeySym*, int*);
+XVaNestedList (*XVaCreateNestedList_dylibloader_wrapper_xlib)( int,...);
+int (*XRegisterIMInstantiateCallback_dylibloader_wrapper_xlib)( Display*,struct _XrmHashBucketRec*, char*, char*, XIDProc, XPointer);
+int (*XUnregisterIMInstantiateCallback_dylibloader_wrapper_xlib)( Display*,struct _XrmHashBucketRec*, char*, char*, XIDProc, XPointer);
+int (*XInternalConnectionNumbers_dylibloader_wrapper_xlib)( Display*, int**, int*);
+void (*XProcessInternalConnection_dylibloader_wrapper_xlib)( Display*, int);
+int (*XAddConnectionWatch_dylibloader_wrapper_xlib)( Display*, XConnectionWatchProc, XPointer);
+void (*XRemoveConnectionWatch_dylibloader_wrapper_xlib)( Display*, XConnectionWatchProc, XPointer);
+void (*XSetAuthorization_dylibloader_wrapper_xlib)( char*, int, char*, int);
+int (*_Xmbtowc_dylibloader_wrapper_xlib)( wchar_t*, char*, int);
+int (*_Xwctomb_dylibloader_wrapper_xlib)( char*, wchar_t);
+int (*XGetEventData_dylibloader_wrapper_xlib)( Display*, XGenericEventCookie*);
+void (*XFreeEventData_dylibloader_wrapper_xlib)( Display*, XGenericEventCookie*);
+XClassHint* (*XAllocClassHint_dylibloader_wrapper_xlib)( void);
+XIconSize* (*XAllocIconSize_dylibloader_wrapper_xlib)( void);
+XSizeHints* (*XAllocSizeHints_dylibloader_wrapper_xlib)( void);
+XStandardColormap* (*XAllocStandardColormap_dylibloader_wrapper_xlib)( void);
+XWMHints* (*XAllocWMHints_dylibloader_wrapper_xlib)( void);
+int (*XClipBox_dylibloader_wrapper_xlib)( Region, XRectangle*);
+Region (*XCreateRegion_dylibloader_wrapper_xlib)( void);
+const char* (*XDefaultString_dylibloader_wrapper_xlib)( void);
+int (*XDeleteContext_dylibloader_wrapper_xlib)( Display*, XID, XContext);
+int (*XDestroyRegion_dylibloader_wrapper_xlib)( Region);
+int (*XEmptyRegion_dylibloader_wrapper_xlib)( Region);
+int (*XEqualRegion_dylibloader_wrapper_xlib)( Region, Region);
+int (*XFindContext_dylibloader_wrapper_xlib)( Display*, XID, XContext, XPointer*);
+int (*XGetClassHint_dylibloader_wrapper_xlib)( Display*, Window, XClassHint*);
+int (*XGetIconSizes_dylibloader_wrapper_xlib)( Display*, Window, XIconSize**, int*);
+int (*XGetNormalHints_dylibloader_wrapper_xlib)( Display*, Window, XSizeHints*);
+int (*XGetRGBColormaps_dylibloader_wrapper_xlib)( Display*, Window, XStandardColormap**, int*, Atom);
+int (*XGetSizeHints_dylibloader_wrapper_xlib)( Display*, Window, XSizeHints*, Atom);
+int (*XGetStandardColormap_dylibloader_wrapper_xlib)( Display*, Window, XStandardColormap*, Atom);
+int (*XGetTextProperty_dylibloader_wrapper_xlib)( Display*, Window, XTextProperty*, Atom);
+XVisualInfo* (*XGetVisualInfo_dylibloader_wrapper_xlib)( Display*, long, XVisualInfo*, int*);
+int (*XGetWMClientMachine_dylibloader_wrapper_xlib)( Display*, Window, XTextProperty*);
+XWMHints* (*XGetWMHints_dylibloader_wrapper_xlib)( Display*, Window);
+int (*XGetWMIconName_dylibloader_wrapper_xlib)( Display*, Window, XTextProperty*);
+int (*XGetWMName_dylibloader_wrapper_xlib)( Display*, Window, XTextProperty*);
+int (*XGetWMNormalHints_dylibloader_wrapper_xlib)( Display*, Window, XSizeHints*, long*);
+int (*XGetWMSizeHints_dylibloader_wrapper_xlib)( Display*, Window, XSizeHints*, long*, Atom);
+int (*XGetZoomHints_dylibloader_wrapper_xlib)( Display*, Window, XSizeHints*);
+int (*XIntersectRegion_dylibloader_wrapper_xlib)( Region, Region, Region);
+void (*XConvertCase_dylibloader_wrapper_xlib)( KeySym, KeySym*, KeySym*);
+int (*XLookupString_dylibloader_wrapper_xlib)( XKeyEvent*, char*, int, KeySym*, XComposeStatus*);
+int (*XMatchVisualInfo_dylibloader_wrapper_xlib)( Display*, int, int, int, XVisualInfo*);
+int (*XOffsetRegion_dylibloader_wrapper_xlib)( Region, int, int);
+int (*XPointInRegion_dylibloader_wrapper_xlib)( Region, int, int);
+Region (*XPolygonRegion_dylibloader_wrapper_xlib)( XPoint*, int, int);
+int (*XRectInRegion_dylibloader_wrapper_xlib)( Region, int, int, unsigned int, unsigned int);
+int (*XSaveContext_dylibloader_wrapper_xlib)( Display*, XID, XContext,const char*);
+int (*XSetClassHint_dylibloader_wrapper_xlib)( Display*, Window, XClassHint*);
+int (*XSetIconSizes_dylibloader_wrapper_xlib)( Display*, Window, XIconSize*, int);
+int (*XSetNormalHints_dylibloader_wrapper_xlib)( Display*, Window, XSizeHints*);
+void (*XSetRGBColormaps_dylibloader_wrapper_xlib)( Display*, Window, XStandardColormap*, int, Atom);
+int (*XSetSizeHints_dylibloader_wrapper_xlib)( Display*, Window, XSizeHints*, Atom);
+int (*XSetStandardProperties_dylibloader_wrapper_xlib)( Display*, Window,const char*,const char*, Pixmap, char**, int, XSizeHints*);
+void (*XSetTextProperty_dylibloader_wrapper_xlib)( Display*, Window, XTextProperty*, Atom);
+void (*XSetWMClientMachine_dylibloader_wrapper_xlib)( Display*, Window, XTextProperty*);
+int (*XSetWMHints_dylibloader_wrapper_xlib)( Display*, Window, XWMHints*);
+void (*XSetWMIconName_dylibloader_wrapper_xlib)( Display*, Window, XTextProperty*);
+void (*XSetWMName_dylibloader_wrapper_xlib)( Display*, Window, XTextProperty*);
+void (*XSetWMNormalHints_dylibloader_wrapper_xlib)( Display*, Window, XSizeHints*);
+void (*XSetWMProperties_dylibloader_wrapper_xlib)( Display*, Window, XTextProperty*, XTextProperty*, char**, int, XSizeHints*, XWMHints*, XClassHint*);
+void (*XmbSetWMProperties_dylibloader_wrapper_xlib)( Display*, Window,const char*,const char*, char**, int, XSizeHints*, XWMHints*, XClassHint*);
+void (*Xutf8SetWMProperties_dylibloader_wrapper_xlib)( Display*, Window,const char*,const char*, char**, int, XSizeHints*, XWMHints*, XClassHint*);
+void (*XSetWMSizeHints_dylibloader_wrapper_xlib)( Display*, Window, XSizeHints*, Atom);
+int (*XSetRegion_dylibloader_wrapper_xlib)( Display*, GC, Region);
+void (*XSetStandardColormap_dylibloader_wrapper_xlib)( Display*, Window, XStandardColormap*, Atom);
+int (*XSetZoomHints_dylibloader_wrapper_xlib)( Display*, Window, XSizeHints*);
+int (*XShrinkRegion_dylibloader_wrapper_xlib)( Region, int, int);
+int (*XStringListToTextProperty_dylibloader_wrapper_xlib)( char**, int, XTextProperty*);
+int (*XSubtractRegion_dylibloader_wrapper_xlib)( Region, Region, Region);
+int (*XmbTextListToTextProperty_dylibloader_wrapper_xlib)( Display*, char**, int, XICCEncodingStyle, XTextProperty*);
+int (*XwcTextListToTextProperty_dylibloader_wrapper_xlib)( Display*, wchar_t**, int, XICCEncodingStyle, XTextProperty*);
+int (*Xutf8TextListToTextProperty_dylibloader_wrapper_xlib)( Display*, char**, int, XICCEncodingStyle, XTextProperty*);
+void (*XwcFreeStringList_dylibloader_wrapper_xlib)( wchar_t**);
+int (*XTextPropertyToStringList_dylibloader_wrapper_xlib)( XTextProperty*, char***, int*);
+int (*XmbTextPropertyToTextList_dylibloader_wrapper_xlib)( Display*,const XTextProperty*, char***, int*);
+int (*XwcTextPropertyToTextList_dylibloader_wrapper_xlib)( Display*,const XTextProperty*, wchar_t***, int*);
+int (*Xutf8TextPropertyToTextList_dylibloader_wrapper_xlib)( Display*,const XTextProperty*, char***, int*);
+int (*XUnionRectWithRegion_dylibloader_wrapper_xlib)( XRectangle*, Region, Region);
+int (*XUnionRegion_dylibloader_wrapper_xlib)( Region, Region, Region);
+int (*XWMGeometry_dylibloader_wrapper_xlib)( Display*, int,const char*,const char*, unsigned int, XSizeHints*, int*, int*, int*, int*, int*);
+int (*XXorRegion_dylibloader_wrapper_xlib)( Region, Region, Region);
+int (*XkbIgnoreExtension_dylibloader_wrapper_xlib)( int);
+Display* (*XkbOpenDisplay_dylibloader_wrapper_xlib)( char*, int*, int*, int*, int*, int*);
+int (*XkbQueryExtension_dylibloader_wrapper_xlib)( Display*, int*, int*, int*, int*, int*);
+int (*XkbUseExtension_dylibloader_wrapper_xlib)( Display*, int*, int*);
+int (*XkbLibraryVersion_dylibloader_wrapper_xlib)( int*, int*);
+unsigned int (*XkbSetXlibControls_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int);
+unsigned int (*XkbGetXlibControls_dylibloader_wrapper_xlib)( Display*);
+unsigned int (*XkbXlibControlsImplemented_dylibloader_wrapper_xlib)( void);
+void (*XkbSetAtomFuncs_dylibloader_wrapper_xlib)( XkbInternAtomFunc, XkbGetAtomNameFunc);
+KeySym (*XkbKeycodeToKeysym_dylibloader_wrapper_xlib)( Display*, KeyCode, int, int);
+unsigned int (*XkbKeysymToModifiers_dylibloader_wrapper_xlib)( Display*, KeySym);
+int (*XkbLookupKeySym_dylibloader_wrapper_xlib)( Display*, KeyCode, unsigned int, unsigned int*, KeySym*);
+int (*XkbLookupKeyBinding_dylibloader_wrapper_xlib)( Display*, KeySym, unsigned int, char*, int, int*);
+int (*XkbTranslateKeyCode_dylibloader_wrapper_xlib)( XkbDescPtr, KeyCode, unsigned int, unsigned int*, KeySym*);
+int (*XkbTranslateKeySym_dylibloader_wrapper_xlib)( Display*, KeySym*, unsigned int, char*, int, int*);
+int (*XkbSetAutoRepeatRate_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, unsigned int);
+int (*XkbGetAutoRepeatRate_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int*, unsigned int*);
+int (*XkbChangeEnabledControls_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, unsigned int);
+int (*XkbDeviceBell_dylibloader_wrapper_xlib)( Display*, Window, int, int, int, int, Atom);
+int (*XkbForceDeviceBell_dylibloader_wrapper_xlib)( Display*, int, int, int, int);
+int (*XkbDeviceBellEvent_dylibloader_wrapper_xlib)( Display*, Window, int, int, int, int, Atom);
+int (*XkbBell_dylibloader_wrapper_xlib)( Display*, Window, int, Atom);
+int (*XkbForceBell_dylibloader_wrapper_xlib)( Display*, int);
+int (*XkbBellEvent_dylibloader_wrapper_xlib)( Display*, Window, int, Atom);
+int (*XkbSelectEvents_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, unsigned int);
+int (*XkbSelectEventDetails_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, unsigned long, unsigned long);
+void (*XkbNoteMapChanges_dylibloader_wrapper_xlib)( XkbMapChangesPtr, XkbMapNotifyEvent*, unsigned int);
+void (*XkbNoteNameChanges_dylibloader_wrapper_xlib)( XkbNameChangesPtr, XkbNamesNotifyEvent*, unsigned int);
+int (*XkbGetIndicatorState_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int*);
+int (*XkbGetIndicatorMap_dylibloader_wrapper_xlib)( Display*, unsigned long, XkbDescPtr);
+int (*XkbSetIndicatorMap_dylibloader_wrapper_xlib)( Display*, unsigned long, XkbDescPtr);
+int (*XkbGetNamedIndicator_dylibloader_wrapper_xlib)( Display*, Atom, int*, int*, XkbIndicatorMapPtr, int*);
+int (*XkbGetNamedDeviceIndicator_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, unsigned int, Atom, int*, int*, XkbIndicatorMapPtr, int*);
+int (*XkbSetNamedIndicator_dylibloader_wrapper_xlib)( Display*, Atom, int, int, int, XkbIndicatorMapPtr);
+int (*XkbSetNamedDeviceIndicator_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, unsigned int, Atom, int, int, int, XkbIndicatorMapPtr);
+int (*XkbLockModifiers_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, unsigned int);
+int (*XkbLatchModifiers_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, unsigned int);
+int (*XkbLockGroup_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int);
+int (*XkbLatchGroup_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int);
+int (*XkbSetServerInternalMods_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int);
+int (*XkbSetIgnoreLockMods_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int);
+int (*XkbVirtualModsToReal_dylibloader_wrapper_xlib)( XkbDescPtr, unsigned int, unsigned int*);
+int (*XkbComputeEffectiveMap_dylibloader_wrapper_xlib)( XkbDescPtr, XkbKeyTypePtr, unsigned char*);
+int (*XkbInitCanonicalKeyTypes_dylibloader_wrapper_xlib)( XkbDescPtr, unsigned int, int);
+XkbDescPtr (*XkbAllocKeyboard_dylibloader_wrapper_xlib)( void);
+void (*XkbFreeKeyboard_dylibloader_wrapper_xlib)( XkbDescPtr, unsigned int, int);
+int (*XkbAllocClientMap_dylibloader_wrapper_xlib)( XkbDescPtr, unsigned int, unsigned int);
+int (*XkbAllocServerMap_dylibloader_wrapper_xlib)( XkbDescPtr, unsigned int, unsigned int);
+void (*XkbFreeClientMap_dylibloader_wrapper_xlib)( XkbDescPtr, unsigned int, int);
+void (*XkbFreeServerMap_dylibloader_wrapper_xlib)( XkbDescPtr, unsigned int, int);
+XkbKeyTypePtr (*XkbAddKeyType_dylibloader_wrapper_xlib)( XkbDescPtr, Atom, int, int, int);
+int (*XkbAllocIndicatorMaps_dylibloader_wrapper_xlib)( XkbDescPtr);
+void (*XkbFreeIndicatorMaps_dylibloader_wrapper_xlib)( XkbDescPtr);
+XkbDescPtr (*XkbGetMap_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int);
+int (*XkbGetUpdatedMap_dylibloader_wrapper_xlib)( Display*, unsigned int, XkbDescPtr);
+int (*XkbGetMapChanges_dylibloader_wrapper_xlib)( Display*, XkbDescPtr, XkbMapChangesPtr);
+int (*XkbRefreshKeyboardMapping_dylibloader_wrapper_xlib)( XkbMapNotifyEvent*);
+int (*XkbGetKeyTypes_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, XkbDescPtr);
+int (*XkbGetKeySyms_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, XkbDescPtr);
+int (*XkbGetKeyActions_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, XkbDescPtr);
+int (*XkbGetKeyBehaviors_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, XkbDescPtr);
+int (*XkbGetVirtualMods_dylibloader_wrapper_xlib)( Display*, unsigned int, XkbDescPtr);
+int (*XkbGetKeyExplicitComponents_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, XkbDescPtr);
+int (*XkbGetKeyModifierMap_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, XkbDescPtr);
+int (*XkbGetKeyVirtualModMap_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, XkbDescPtr);
+int (*XkbAllocControls_dylibloader_wrapper_xlib)( XkbDescPtr, unsigned int);
+void (*XkbFreeControls_dylibloader_wrapper_xlib)( XkbDescPtr, unsigned int, int);
+int (*XkbGetControls_dylibloader_wrapper_xlib)( Display*, unsigned long, XkbDescPtr);
+int (*XkbSetControls_dylibloader_wrapper_xlib)( Display*, unsigned long, XkbDescPtr);
+void (*XkbNoteControlsChanges_dylibloader_wrapper_xlib)( XkbControlsChangesPtr, XkbControlsNotifyEvent*, unsigned int);
+int (*XkbAllocCompatMap_dylibloader_wrapper_xlib)( XkbDescPtr, unsigned int, unsigned int);
+void (*XkbFreeCompatMap_dylibloader_wrapper_xlib)( XkbDescPtr, unsigned int, int);
+int (*XkbGetCompatMap_dylibloader_wrapper_xlib)( Display*, unsigned int, XkbDescPtr);
+int (*XkbSetCompatMap_dylibloader_wrapper_xlib)( Display*, unsigned int, XkbDescPtr, int);
+int (*XkbAllocNames_dylibloader_wrapper_xlib)( XkbDescPtr, unsigned int, int, int);
+int (*XkbGetNames_dylibloader_wrapper_xlib)( Display*, unsigned int, XkbDescPtr);
+int (*XkbSetNames_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, unsigned int, XkbDescPtr);
+int (*XkbChangeNames_dylibloader_wrapper_xlib)( Display*, XkbDescPtr, XkbNameChangesPtr);
+void (*XkbFreeNames_dylibloader_wrapper_xlib)( XkbDescPtr, unsigned int, int);
+int (*XkbGetState_dylibloader_wrapper_xlib)( Display*, unsigned int, XkbStatePtr);
+int (*XkbSetMap_dylibloader_wrapper_xlib)( Display*, unsigned int, XkbDescPtr);
+int (*XkbChangeMap_dylibloader_wrapper_xlib)( Display*, XkbDescPtr, XkbMapChangesPtr);
+int (*XkbSetDetectableAutoRepeat_dylibloader_wrapper_xlib)( Display*, int, int*);
+int (*XkbGetDetectableAutoRepeat_dylibloader_wrapper_xlib)( Display*, int*);
+int (*XkbSetAutoResetControls_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int*, unsigned int*);
+int (*XkbGetAutoResetControls_dylibloader_wrapper_xlib)( Display*, unsigned int*, unsigned int*);
+int (*XkbSetPerClientControls_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int*);
+int (*XkbGetPerClientControls_dylibloader_wrapper_xlib)( Display*, unsigned int*);
+int (*XkbCopyKeyType_dylibloader_wrapper_xlib)( XkbKeyTypePtr, XkbKeyTypePtr);
+int (*XkbCopyKeyTypes_dylibloader_wrapper_xlib)( XkbKeyTypePtr, XkbKeyTypePtr, int);
+int (*XkbResizeKeyType_dylibloader_wrapper_xlib)( XkbDescPtr, int, int, int, int);
+KeySym* (*XkbResizeKeySyms_dylibloader_wrapper_xlib)( XkbDescPtr, int, int);
+XkbAction* (*XkbResizeKeyActions_dylibloader_wrapper_xlib)( XkbDescPtr, int, int);
+int (*XkbChangeTypesOfKey_dylibloader_wrapper_xlib)( XkbDescPtr, int, int, unsigned int, int*, XkbMapChangesPtr);
+int (*XkbChangeKeycodeRange_dylibloader_wrapper_xlib)( XkbDescPtr, int, int, XkbChangesPtr);
+XkbComponentListPtr (*XkbListComponents_dylibloader_wrapper_xlib)( Display*, unsigned int, XkbComponentNamesPtr, int*);
+void (*XkbFreeComponentList_dylibloader_wrapper_xlib)( XkbComponentListPtr);
+XkbDescPtr (*XkbGetKeyboard_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int);
+XkbDescPtr (*XkbGetKeyboardByName_dylibloader_wrapper_xlib)( Display*, unsigned int, XkbComponentNamesPtr, unsigned int, unsigned int, int);
+int (*XkbKeyTypesForCoreSymbols_dylibloader_wrapper_xlib)( XkbDescPtr, int, KeySym*, unsigned int, int*, KeySym*);
+int (*XkbApplyCompatMapToKey_dylibloader_wrapper_xlib)( XkbDescPtr, KeyCode, XkbChangesPtr);
+int (*XkbUpdateMapFromCore_dylibloader_wrapper_xlib)( XkbDescPtr, KeyCode, int, int, KeySym*, XkbChangesPtr);
+XkbDeviceLedInfoPtr (*XkbAddDeviceLedInfo_dylibloader_wrapper_xlib)( XkbDeviceInfoPtr, unsigned int, unsigned int);
+int (*XkbResizeDeviceButtonActions_dylibloader_wrapper_xlib)( XkbDeviceInfoPtr, unsigned int);
+XkbDeviceInfoPtr (*XkbAllocDeviceInfo_dylibloader_wrapper_xlib)( unsigned int, unsigned int, unsigned int);
+void (*XkbFreeDeviceInfo_dylibloader_wrapper_xlib)( XkbDeviceInfoPtr, unsigned int, int);
+void (*XkbNoteDeviceChanges_dylibloader_wrapper_xlib)( XkbDeviceChangesPtr, XkbExtensionDeviceNotifyEvent*, unsigned int);
+XkbDeviceInfoPtr (*XkbGetDeviceInfo_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, unsigned int, unsigned int);
+int (*XkbGetDeviceInfoChanges_dylibloader_wrapper_xlib)( Display*, XkbDeviceInfoPtr, XkbDeviceChangesPtr);
+int (*XkbGetDeviceButtonActions_dylibloader_wrapper_xlib)( Display*, XkbDeviceInfoPtr, int, unsigned int, unsigned int);
+int (*XkbGetDeviceLedInfo_dylibloader_wrapper_xlib)( Display*, XkbDeviceInfoPtr, unsigned int, unsigned int, unsigned int);
+int (*XkbSetDeviceInfo_dylibloader_wrapper_xlib)( Display*, unsigned int, XkbDeviceInfoPtr);
+int (*XkbChangeDeviceInfo_dylibloader_wrapper_xlib)( Display*, XkbDeviceInfoPtr, XkbDeviceChangesPtr);
+int (*XkbSetDeviceLedInfo_dylibloader_wrapper_xlib)( Display*, XkbDeviceInfoPtr, unsigned int, unsigned int, unsigned int);
+int (*XkbSetDeviceButtonActions_dylibloader_wrapper_xlib)( Display*, XkbDeviceInfoPtr, unsigned int, unsigned int);
+char (*XkbToControl_dylibloader_wrapper_xlib)( char);
+int (*XkbSetDebuggingFlags_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, char*, unsigned int, unsigned int, unsigned int*, unsigned int*);
+int (*XkbApplyVirtualModChanges_dylibloader_wrapper_xlib)( XkbDescPtr, unsigned int, XkbChangesPtr);
+int (*XkbUpdateActionVirtualMods_dylibloader_wrapper_xlib)( XkbDescPtr, XkbAction*, unsigned int);
+void (*XkbUpdateKeyTypeVirtualMods_dylibloader_wrapper_xlib)( XkbDescPtr, XkbKeyTypePtr, unsigned int, XkbChangesPtr);
+int initialize_xlib(int verbose) {
+ void *handle;
+ char *error;
+ handle = dlopen("libX11.so.6", RTLD_LAZY);
+ if (!handle) {
+ if (verbose) {
+ fprintf(stderr, "%s\n", dlerror());
+ }
+ return(1);
+ }
+ dlerror();
+// _Xmblen
+ *(void **) (&_Xmblen_dylibloader_wrapper_xlib) = dlsym(handle, "_Xmblen");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XLoadQueryFont
+ *(void **) (&XLoadQueryFont_dylibloader_wrapper_xlib) = dlsym(handle, "XLoadQueryFont");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XQueryFont
+ *(void **) (&XQueryFont_dylibloader_wrapper_xlib) = dlsym(handle, "XQueryFont");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XGetMotionEvents
+ *(void **) (&XGetMotionEvents_dylibloader_wrapper_xlib) = dlsym(handle, "XGetMotionEvents");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XDeleteModifiermapEntry
+ *(void **) (&XDeleteModifiermapEntry_dylibloader_wrapper_xlib) = dlsym(handle, "XDeleteModifiermapEntry");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XGetModifierMapping
+ *(void **) (&XGetModifierMapping_dylibloader_wrapper_xlib) = dlsym(handle, "XGetModifierMapping");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XInsertModifiermapEntry
+ *(void **) (&XInsertModifiermapEntry_dylibloader_wrapper_xlib) = dlsym(handle, "XInsertModifiermapEntry");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XNewModifiermap
+ *(void **) (&XNewModifiermap_dylibloader_wrapper_xlib) = dlsym(handle, "XNewModifiermap");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XCreateImage
+ *(void **) (&XCreateImage_dylibloader_wrapper_xlib) = dlsym(handle, "XCreateImage");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XInitImage
+ *(void **) (&XInitImage_dylibloader_wrapper_xlib) = dlsym(handle, "XInitImage");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XGetImage
+ *(void **) (&XGetImage_dylibloader_wrapper_xlib) = dlsym(handle, "XGetImage");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XGetSubImage
+ *(void **) (&XGetSubImage_dylibloader_wrapper_xlib) = dlsym(handle, "XGetSubImage");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XOpenDisplay
+ *(void **) (&XOpenDisplay_dylibloader_wrapper_xlib) = dlsym(handle, "XOpenDisplay");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XrmInitialize
+ *(void **) (&XrmInitialize_dylibloader_wrapper_xlib) = dlsym(handle, "XrmInitialize");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XFetchBytes
+ *(void **) (&XFetchBytes_dylibloader_wrapper_xlib) = dlsym(handle, "XFetchBytes");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XFetchBuffer
+ *(void **) (&XFetchBuffer_dylibloader_wrapper_xlib) = dlsym(handle, "XFetchBuffer");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XGetAtomName
+ *(void **) (&XGetAtomName_dylibloader_wrapper_xlib) = dlsym(handle, "XGetAtomName");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XGetAtomNames
+ *(void **) (&XGetAtomNames_dylibloader_wrapper_xlib) = dlsym(handle, "XGetAtomNames");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XGetDefault
+ *(void **) (&XGetDefault_dylibloader_wrapper_xlib) = dlsym(handle, "XGetDefault");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XDisplayName
+ *(void **) (&XDisplayName_dylibloader_wrapper_xlib) = dlsym(handle, "XDisplayName");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XKeysymToString
+ *(void **) (&XKeysymToString_dylibloader_wrapper_xlib) = dlsym(handle, "XKeysymToString");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XSynchronize
+ *(void **) (&XSynchronize_dylibloader_wrapper_xlib) = dlsym(handle, "XSynchronize");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XSetAfterFunction
+ *(void **) (&XSetAfterFunction_dylibloader_wrapper_xlib) = dlsym(handle, "XSetAfterFunction");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XInternAtom
+ *(void **) (&XInternAtom_dylibloader_wrapper_xlib) = dlsym(handle, "XInternAtom");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XInternAtoms
+ *(void **) (&XInternAtoms_dylibloader_wrapper_xlib) = dlsym(handle, "XInternAtoms");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XCopyColormapAndFree
+ *(void **) (&XCopyColormapAndFree_dylibloader_wrapper_xlib) = dlsym(handle, "XCopyColormapAndFree");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XCreateColormap
+ *(void **) (&XCreateColormap_dylibloader_wrapper_xlib) = dlsym(handle, "XCreateColormap");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XCreatePixmapCursor
+ *(void **) (&XCreatePixmapCursor_dylibloader_wrapper_xlib) = dlsym(handle, "XCreatePixmapCursor");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XCreateGlyphCursor
+ *(void **) (&XCreateGlyphCursor_dylibloader_wrapper_xlib) = dlsym(handle, "XCreateGlyphCursor");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XCreateFontCursor
+ *(void **) (&XCreateFontCursor_dylibloader_wrapper_xlib) = dlsym(handle, "XCreateFontCursor");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XLoadFont
+ *(void **) (&XLoadFont_dylibloader_wrapper_xlib) = dlsym(handle, "XLoadFont");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XCreateGC
+ *(void **) (&XCreateGC_dylibloader_wrapper_xlib) = dlsym(handle, "XCreateGC");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XGContextFromGC
+ *(void **) (&XGContextFromGC_dylibloader_wrapper_xlib) = dlsym(handle, "XGContextFromGC");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XFlushGC
+ *(void **) (&XFlushGC_dylibloader_wrapper_xlib) = dlsym(handle, "XFlushGC");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XCreatePixmap
+ *(void **) (&XCreatePixmap_dylibloader_wrapper_xlib) = dlsym(handle, "XCreatePixmap");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XCreateBitmapFromData
+ *(void **) (&XCreateBitmapFromData_dylibloader_wrapper_xlib) = dlsym(handle, "XCreateBitmapFromData");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XCreatePixmapFromBitmapData
+ *(void **) (&XCreatePixmapFromBitmapData_dylibloader_wrapper_xlib) = dlsym(handle, "XCreatePixmapFromBitmapData");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XCreateSimpleWindow
+ *(void **) (&XCreateSimpleWindow_dylibloader_wrapper_xlib) = dlsym(handle, "XCreateSimpleWindow");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XGetSelectionOwner
+ *(void **) (&XGetSelectionOwner_dylibloader_wrapper_xlib) = dlsym(handle, "XGetSelectionOwner");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XCreateWindow
+ *(void **) (&XCreateWindow_dylibloader_wrapper_xlib) = dlsym(handle, "XCreateWindow");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XListInstalledColormaps
+ *(void **) (&XListInstalledColormaps_dylibloader_wrapper_xlib) = dlsym(handle, "XListInstalledColormaps");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XListFonts
+ *(void **) (&XListFonts_dylibloader_wrapper_xlib) = dlsym(handle, "XListFonts");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XListFontsWithInfo
+ *(void **) (&XListFontsWithInfo_dylibloader_wrapper_xlib) = dlsym(handle, "XListFontsWithInfo");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XGetFontPath
+ *(void **) (&XGetFontPath_dylibloader_wrapper_xlib) = dlsym(handle, "XGetFontPath");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XListExtensions
+ *(void **) (&XListExtensions_dylibloader_wrapper_xlib) = dlsym(handle, "XListExtensions");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XListProperties
+ *(void **) (&XListProperties_dylibloader_wrapper_xlib) = dlsym(handle, "XListProperties");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XListHosts
+ *(void **) (&XListHosts_dylibloader_wrapper_xlib) = dlsym(handle, "XListHosts");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XKeycodeToKeysym
+ *(void **) (&XKeycodeToKeysym_dylibloader_wrapper_xlib) = dlsym(handle, "XKeycodeToKeysym");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XLookupKeysym
+ *(void **) (&XLookupKeysym_dylibloader_wrapper_xlib) = dlsym(handle, "XLookupKeysym");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XGetKeyboardMapping
+ *(void **) (&XGetKeyboardMapping_dylibloader_wrapper_xlib) = dlsym(handle, "XGetKeyboardMapping");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XStringToKeysym
+ *(void **) (&XStringToKeysym_dylibloader_wrapper_xlib) = dlsym(handle, "XStringToKeysym");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XMaxRequestSize
+ *(void **) (&XMaxRequestSize_dylibloader_wrapper_xlib) = dlsym(handle, "XMaxRequestSize");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XExtendedMaxRequestSize
+ *(void **) (&XExtendedMaxRequestSize_dylibloader_wrapper_xlib) = dlsym(handle, "XExtendedMaxRequestSize");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XResourceManagerString
+ *(void **) (&XResourceManagerString_dylibloader_wrapper_xlib) = dlsym(handle, "XResourceManagerString");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XScreenResourceString
+ *(void **) (&XScreenResourceString_dylibloader_wrapper_xlib) = dlsym(handle, "XScreenResourceString");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XDisplayMotionBufferSize
+ *(void **) (&XDisplayMotionBufferSize_dylibloader_wrapper_xlib) = dlsym(handle, "XDisplayMotionBufferSize");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XVisualIDFromVisual
+ *(void **) (&XVisualIDFromVisual_dylibloader_wrapper_xlib) = dlsym(handle, "XVisualIDFromVisual");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XInitThreads
+ *(void **) (&XInitThreads_dylibloader_wrapper_xlib) = dlsym(handle, "XInitThreads");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XLockDisplay
+ *(void **) (&XLockDisplay_dylibloader_wrapper_xlib) = dlsym(handle, "XLockDisplay");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XUnlockDisplay
+ *(void **) (&XUnlockDisplay_dylibloader_wrapper_xlib) = dlsym(handle, "XUnlockDisplay");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XInitExtension
+ *(void **) (&XInitExtension_dylibloader_wrapper_xlib) = dlsym(handle, "XInitExtension");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XAddExtension
+ *(void **) (&XAddExtension_dylibloader_wrapper_xlib) = dlsym(handle, "XAddExtension");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XFindOnExtensionList
+ *(void **) (&XFindOnExtensionList_dylibloader_wrapper_xlib) = dlsym(handle, "XFindOnExtensionList");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XEHeadOfExtensionList
+ *(void **) (&XEHeadOfExtensionList_dylibloader_wrapper_xlib) = dlsym(handle, "XEHeadOfExtensionList");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRootWindow
+ *(void **) (&XRootWindow_dylibloader_wrapper_xlib) = dlsym(handle, "XRootWindow");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XDefaultRootWindow
+ *(void **) (&XDefaultRootWindow_dylibloader_wrapper_xlib) = dlsym(handle, "XDefaultRootWindow");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRootWindowOfScreen
+ *(void **) (&XRootWindowOfScreen_dylibloader_wrapper_xlib) = dlsym(handle, "XRootWindowOfScreen");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XDefaultVisual
+ *(void **) (&XDefaultVisual_dylibloader_wrapper_xlib) = dlsym(handle, "XDefaultVisual");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XDefaultVisualOfScreen
+ *(void **) (&XDefaultVisualOfScreen_dylibloader_wrapper_xlib) = dlsym(handle, "XDefaultVisualOfScreen");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XDefaultGC
+ *(void **) (&XDefaultGC_dylibloader_wrapper_xlib) = dlsym(handle, "XDefaultGC");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XDefaultGCOfScreen
+ *(void **) (&XDefaultGCOfScreen_dylibloader_wrapper_xlib) = dlsym(handle, "XDefaultGCOfScreen");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XBlackPixel
+ *(void **) (&XBlackPixel_dylibloader_wrapper_xlib) = dlsym(handle, "XBlackPixel");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XWhitePixel
+ *(void **) (&XWhitePixel_dylibloader_wrapper_xlib) = dlsym(handle, "XWhitePixel");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XAllPlanes
+ *(void **) (&XAllPlanes_dylibloader_wrapper_xlib) = dlsym(handle, "XAllPlanes");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XBlackPixelOfScreen
+ *(void **) (&XBlackPixelOfScreen_dylibloader_wrapper_xlib) = dlsym(handle, "XBlackPixelOfScreen");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XWhitePixelOfScreen
+ *(void **) (&XWhitePixelOfScreen_dylibloader_wrapper_xlib) = dlsym(handle, "XWhitePixelOfScreen");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XNextRequest
+ *(void **) (&XNextRequest_dylibloader_wrapper_xlib) = dlsym(handle, "XNextRequest");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XLastKnownRequestProcessed
+ *(void **) (&XLastKnownRequestProcessed_dylibloader_wrapper_xlib) = dlsym(handle, "XLastKnownRequestProcessed");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XServerVendor
+ *(void **) (&XServerVendor_dylibloader_wrapper_xlib) = dlsym(handle, "XServerVendor");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XDisplayString
+ *(void **) (&XDisplayString_dylibloader_wrapper_xlib) = dlsym(handle, "XDisplayString");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XDefaultColormap
+ *(void **) (&XDefaultColormap_dylibloader_wrapper_xlib) = dlsym(handle, "XDefaultColormap");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XDefaultColormapOfScreen
+ *(void **) (&XDefaultColormapOfScreen_dylibloader_wrapper_xlib) = dlsym(handle, "XDefaultColormapOfScreen");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XDisplayOfScreen
+ *(void **) (&XDisplayOfScreen_dylibloader_wrapper_xlib) = dlsym(handle, "XDisplayOfScreen");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XScreenOfDisplay
+ *(void **) (&XScreenOfDisplay_dylibloader_wrapper_xlib) = dlsym(handle, "XScreenOfDisplay");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XDefaultScreenOfDisplay
+ *(void **) (&XDefaultScreenOfDisplay_dylibloader_wrapper_xlib) = dlsym(handle, "XDefaultScreenOfDisplay");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XEventMaskOfScreen
+ *(void **) (&XEventMaskOfScreen_dylibloader_wrapper_xlib) = dlsym(handle, "XEventMaskOfScreen");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XScreenNumberOfScreen
+ *(void **) (&XScreenNumberOfScreen_dylibloader_wrapper_xlib) = dlsym(handle, "XScreenNumberOfScreen");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XSetErrorHandler
+ *(void **) (&XSetErrorHandler_dylibloader_wrapper_xlib) = dlsym(handle, "XSetErrorHandler");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XSetIOErrorHandler
+ *(void **) (&XSetIOErrorHandler_dylibloader_wrapper_xlib) = dlsym(handle, "XSetIOErrorHandler");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XListPixmapFormats
+ *(void **) (&XListPixmapFormats_dylibloader_wrapper_xlib) = dlsym(handle, "XListPixmapFormats");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XListDepths
+ *(void **) (&XListDepths_dylibloader_wrapper_xlib) = dlsym(handle, "XListDepths");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XReconfigureWMWindow
+ *(void **) (&XReconfigureWMWindow_dylibloader_wrapper_xlib) = dlsym(handle, "XReconfigureWMWindow");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XGetWMProtocols
+ *(void **) (&XGetWMProtocols_dylibloader_wrapper_xlib) = dlsym(handle, "XGetWMProtocols");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XSetWMProtocols
+ *(void **) (&XSetWMProtocols_dylibloader_wrapper_xlib) = dlsym(handle, "XSetWMProtocols");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XIconifyWindow
+ *(void **) (&XIconifyWindow_dylibloader_wrapper_xlib) = dlsym(handle, "XIconifyWindow");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XWithdrawWindow
+ *(void **) (&XWithdrawWindow_dylibloader_wrapper_xlib) = dlsym(handle, "XWithdrawWindow");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XGetCommand
+ *(void **) (&XGetCommand_dylibloader_wrapper_xlib) = dlsym(handle, "XGetCommand");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XGetWMColormapWindows
+ *(void **) (&XGetWMColormapWindows_dylibloader_wrapper_xlib) = dlsym(handle, "XGetWMColormapWindows");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XSetWMColormapWindows
+ *(void **) (&XSetWMColormapWindows_dylibloader_wrapper_xlib) = dlsym(handle, "XSetWMColormapWindows");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XFreeStringList
+ *(void **) (&XFreeStringList_dylibloader_wrapper_xlib) = dlsym(handle, "XFreeStringList");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XSetTransientForHint
+ *(void **) (&XSetTransientForHint_dylibloader_wrapper_xlib) = dlsym(handle, "XSetTransientForHint");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XActivateScreenSaver
+ *(void **) (&XActivateScreenSaver_dylibloader_wrapper_xlib) = dlsym(handle, "XActivateScreenSaver");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XAddHost
+ *(void **) (&XAddHost_dylibloader_wrapper_xlib) = dlsym(handle, "XAddHost");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XAddHosts
+ *(void **) (&XAddHosts_dylibloader_wrapper_xlib) = dlsym(handle, "XAddHosts");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XAddToExtensionList
+ *(void **) (&XAddToExtensionList_dylibloader_wrapper_xlib) = dlsym(handle, "XAddToExtensionList");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XAddToSaveSet
+ *(void **) (&XAddToSaveSet_dylibloader_wrapper_xlib) = dlsym(handle, "XAddToSaveSet");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XAllocColor
+ *(void **) (&XAllocColor_dylibloader_wrapper_xlib) = dlsym(handle, "XAllocColor");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XAllocColorCells
+ *(void **) (&XAllocColorCells_dylibloader_wrapper_xlib) = dlsym(handle, "XAllocColorCells");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XAllocColorPlanes
+ *(void **) (&XAllocColorPlanes_dylibloader_wrapper_xlib) = dlsym(handle, "XAllocColorPlanes");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XAllocNamedColor
+ *(void **) (&XAllocNamedColor_dylibloader_wrapper_xlib) = dlsym(handle, "XAllocNamedColor");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XAllowEvents
+ *(void **) (&XAllowEvents_dylibloader_wrapper_xlib) = dlsym(handle, "XAllowEvents");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XAutoRepeatOff
+ *(void **) (&XAutoRepeatOff_dylibloader_wrapper_xlib) = dlsym(handle, "XAutoRepeatOff");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XAutoRepeatOn
+ *(void **) (&XAutoRepeatOn_dylibloader_wrapper_xlib) = dlsym(handle, "XAutoRepeatOn");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XBell
+ *(void **) (&XBell_dylibloader_wrapper_xlib) = dlsym(handle, "XBell");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XBitmapBitOrder
+ *(void **) (&XBitmapBitOrder_dylibloader_wrapper_xlib) = dlsym(handle, "XBitmapBitOrder");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XBitmapPad
+ *(void **) (&XBitmapPad_dylibloader_wrapper_xlib) = dlsym(handle, "XBitmapPad");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XBitmapUnit
+ *(void **) (&XBitmapUnit_dylibloader_wrapper_xlib) = dlsym(handle, "XBitmapUnit");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XCellsOfScreen
+ *(void **) (&XCellsOfScreen_dylibloader_wrapper_xlib) = dlsym(handle, "XCellsOfScreen");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XChangeActivePointerGrab
+ *(void **) (&XChangeActivePointerGrab_dylibloader_wrapper_xlib) = dlsym(handle, "XChangeActivePointerGrab");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XChangeGC
+ *(void **) (&XChangeGC_dylibloader_wrapper_xlib) = dlsym(handle, "XChangeGC");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XChangeKeyboardControl
+ *(void **) (&XChangeKeyboardControl_dylibloader_wrapper_xlib) = dlsym(handle, "XChangeKeyboardControl");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XChangeKeyboardMapping
+ *(void **) (&XChangeKeyboardMapping_dylibloader_wrapper_xlib) = dlsym(handle, "XChangeKeyboardMapping");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XChangePointerControl
+ *(void **) (&XChangePointerControl_dylibloader_wrapper_xlib) = dlsym(handle, "XChangePointerControl");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XChangeProperty
+ *(void **) (&XChangeProperty_dylibloader_wrapper_xlib) = dlsym(handle, "XChangeProperty");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XChangeSaveSet
+ *(void **) (&XChangeSaveSet_dylibloader_wrapper_xlib) = dlsym(handle, "XChangeSaveSet");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XChangeWindowAttributes
+ *(void **) (&XChangeWindowAttributes_dylibloader_wrapper_xlib) = dlsym(handle, "XChangeWindowAttributes");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XCheckIfEvent
+ *(void **) (&XCheckIfEvent_dylibloader_wrapper_xlib) = dlsym(handle, "XCheckIfEvent");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XCheckMaskEvent
+ *(void **) (&XCheckMaskEvent_dylibloader_wrapper_xlib) = dlsym(handle, "XCheckMaskEvent");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XCheckTypedEvent
+ *(void **) (&XCheckTypedEvent_dylibloader_wrapper_xlib) = dlsym(handle, "XCheckTypedEvent");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XCheckTypedWindowEvent
+ *(void **) (&XCheckTypedWindowEvent_dylibloader_wrapper_xlib) = dlsym(handle, "XCheckTypedWindowEvent");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XCheckWindowEvent
+ *(void **) (&XCheckWindowEvent_dylibloader_wrapper_xlib) = dlsym(handle, "XCheckWindowEvent");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XCirculateSubwindows
+ *(void **) (&XCirculateSubwindows_dylibloader_wrapper_xlib) = dlsym(handle, "XCirculateSubwindows");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XCirculateSubwindowsDown
+ *(void **) (&XCirculateSubwindowsDown_dylibloader_wrapper_xlib) = dlsym(handle, "XCirculateSubwindowsDown");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XCirculateSubwindowsUp
+ *(void **) (&XCirculateSubwindowsUp_dylibloader_wrapper_xlib) = dlsym(handle, "XCirculateSubwindowsUp");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XClearArea
+ *(void **) (&XClearArea_dylibloader_wrapper_xlib) = dlsym(handle, "XClearArea");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XClearWindow
+ *(void **) (&XClearWindow_dylibloader_wrapper_xlib) = dlsym(handle, "XClearWindow");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XCloseDisplay
+ *(void **) (&XCloseDisplay_dylibloader_wrapper_xlib) = dlsym(handle, "XCloseDisplay");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XConfigureWindow
+ *(void **) (&XConfigureWindow_dylibloader_wrapper_xlib) = dlsym(handle, "XConfigureWindow");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XConnectionNumber
+ *(void **) (&XConnectionNumber_dylibloader_wrapper_xlib) = dlsym(handle, "XConnectionNumber");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XConvertSelection
+ *(void **) (&XConvertSelection_dylibloader_wrapper_xlib) = dlsym(handle, "XConvertSelection");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XCopyArea
+ *(void **) (&XCopyArea_dylibloader_wrapper_xlib) = dlsym(handle, "XCopyArea");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XCopyGC
+ *(void **) (&XCopyGC_dylibloader_wrapper_xlib) = dlsym(handle, "XCopyGC");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XCopyPlane
+ *(void **) (&XCopyPlane_dylibloader_wrapper_xlib) = dlsym(handle, "XCopyPlane");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XDefaultDepth
+ *(void **) (&XDefaultDepth_dylibloader_wrapper_xlib) = dlsym(handle, "XDefaultDepth");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XDefaultDepthOfScreen
+ *(void **) (&XDefaultDepthOfScreen_dylibloader_wrapper_xlib) = dlsym(handle, "XDefaultDepthOfScreen");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XDefaultScreen
+ *(void **) (&XDefaultScreen_dylibloader_wrapper_xlib) = dlsym(handle, "XDefaultScreen");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XDefineCursor
+ *(void **) (&XDefineCursor_dylibloader_wrapper_xlib) = dlsym(handle, "XDefineCursor");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XDeleteProperty
+ *(void **) (&XDeleteProperty_dylibloader_wrapper_xlib) = dlsym(handle, "XDeleteProperty");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XDestroyWindow
+ *(void **) (&XDestroyWindow_dylibloader_wrapper_xlib) = dlsym(handle, "XDestroyWindow");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XDestroySubwindows
+ *(void **) (&XDestroySubwindows_dylibloader_wrapper_xlib) = dlsym(handle, "XDestroySubwindows");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XDoesBackingStore
+ *(void **) (&XDoesBackingStore_dylibloader_wrapper_xlib) = dlsym(handle, "XDoesBackingStore");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XDoesSaveUnders
+ *(void **) (&XDoesSaveUnders_dylibloader_wrapper_xlib) = dlsym(handle, "XDoesSaveUnders");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XDisableAccessControl
+ *(void **) (&XDisableAccessControl_dylibloader_wrapper_xlib) = dlsym(handle, "XDisableAccessControl");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XDisplayCells
+ *(void **) (&XDisplayCells_dylibloader_wrapper_xlib) = dlsym(handle, "XDisplayCells");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XDisplayHeight
+ *(void **) (&XDisplayHeight_dylibloader_wrapper_xlib) = dlsym(handle, "XDisplayHeight");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XDisplayHeightMM
+ *(void **) (&XDisplayHeightMM_dylibloader_wrapper_xlib) = dlsym(handle, "XDisplayHeightMM");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XDisplayKeycodes
+ *(void **) (&XDisplayKeycodes_dylibloader_wrapper_xlib) = dlsym(handle, "XDisplayKeycodes");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XDisplayPlanes
+ *(void **) (&XDisplayPlanes_dylibloader_wrapper_xlib) = dlsym(handle, "XDisplayPlanes");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XDisplayWidth
+ *(void **) (&XDisplayWidth_dylibloader_wrapper_xlib) = dlsym(handle, "XDisplayWidth");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XDisplayWidthMM
+ *(void **) (&XDisplayWidthMM_dylibloader_wrapper_xlib) = dlsym(handle, "XDisplayWidthMM");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XDrawArc
+ *(void **) (&XDrawArc_dylibloader_wrapper_xlib) = dlsym(handle, "XDrawArc");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XDrawArcs
+ *(void **) (&XDrawArcs_dylibloader_wrapper_xlib) = dlsym(handle, "XDrawArcs");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XDrawImageString
+ *(void **) (&XDrawImageString_dylibloader_wrapper_xlib) = dlsym(handle, "XDrawImageString");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XDrawImageString16
+ *(void **) (&XDrawImageString16_dylibloader_wrapper_xlib) = dlsym(handle, "XDrawImageString16");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XDrawLine
+ *(void **) (&XDrawLine_dylibloader_wrapper_xlib) = dlsym(handle, "XDrawLine");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XDrawLines
+ *(void **) (&XDrawLines_dylibloader_wrapper_xlib) = dlsym(handle, "XDrawLines");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XDrawPoint
+ *(void **) (&XDrawPoint_dylibloader_wrapper_xlib) = dlsym(handle, "XDrawPoint");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XDrawPoints
+ *(void **) (&XDrawPoints_dylibloader_wrapper_xlib) = dlsym(handle, "XDrawPoints");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XDrawRectangle
+ *(void **) (&XDrawRectangle_dylibloader_wrapper_xlib) = dlsym(handle, "XDrawRectangle");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XDrawRectangles
+ *(void **) (&XDrawRectangles_dylibloader_wrapper_xlib) = dlsym(handle, "XDrawRectangles");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XDrawSegments
+ *(void **) (&XDrawSegments_dylibloader_wrapper_xlib) = dlsym(handle, "XDrawSegments");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XDrawString
+ *(void **) (&XDrawString_dylibloader_wrapper_xlib) = dlsym(handle, "XDrawString");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XDrawString16
+ *(void **) (&XDrawString16_dylibloader_wrapper_xlib) = dlsym(handle, "XDrawString16");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XDrawText
+ *(void **) (&XDrawText_dylibloader_wrapper_xlib) = dlsym(handle, "XDrawText");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XDrawText16
+ *(void **) (&XDrawText16_dylibloader_wrapper_xlib) = dlsym(handle, "XDrawText16");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XEnableAccessControl
+ *(void **) (&XEnableAccessControl_dylibloader_wrapper_xlib) = dlsym(handle, "XEnableAccessControl");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XEventsQueued
+ *(void **) (&XEventsQueued_dylibloader_wrapper_xlib) = dlsym(handle, "XEventsQueued");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XFetchName
+ *(void **) (&XFetchName_dylibloader_wrapper_xlib) = dlsym(handle, "XFetchName");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XFillArc
+ *(void **) (&XFillArc_dylibloader_wrapper_xlib) = dlsym(handle, "XFillArc");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XFillArcs
+ *(void **) (&XFillArcs_dylibloader_wrapper_xlib) = dlsym(handle, "XFillArcs");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XFillPolygon
+ *(void **) (&XFillPolygon_dylibloader_wrapper_xlib) = dlsym(handle, "XFillPolygon");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XFillRectangle
+ *(void **) (&XFillRectangle_dylibloader_wrapper_xlib) = dlsym(handle, "XFillRectangle");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XFillRectangles
+ *(void **) (&XFillRectangles_dylibloader_wrapper_xlib) = dlsym(handle, "XFillRectangles");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XFlush
+ *(void **) (&XFlush_dylibloader_wrapper_xlib) = dlsym(handle, "XFlush");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XForceScreenSaver
+ *(void **) (&XForceScreenSaver_dylibloader_wrapper_xlib) = dlsym(handle, "XForceScreenSaver");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XFree
+ *(void **) (&XFree_dylibloader_wrapper_xlib) = dlsym(handle, "XFree");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XFreeColormap
+ *(void **) (&XFreeColormap_dylibloader_wrapper_xlib) = dlsym(handle, "XFreeColormap");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XFreeColors
+ *(void **) (&XFreeColors_dylibloader_wrapper_xlib) = dlsym(handle, "XFreeColors");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XFreeCursor
+ *(void **) (&XFreeCursor_dylibloader_wrapper_xlib) = dlsym(handle, "XFreeCursor");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XFreeExtensionList
+ *(void **) (&XFreeExtensionList_dylibloader_wrapper_xlib) = dlsym(handle, "XFreeExtensionList");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XFreeFont
+ *(void **) (&XFreeFont_dylibloader_wrapper_xlib) = dlsym(handle, "XFreeFont");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XFreeFontInfo
+ *(void **) (&XFreeFontInfo_dylibloader_wrapper_xlib) = dlsym(handle, "XFreeFontInfo");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XFreeFontNames
+ *(void **) (&XFreeFontNames_dylibloader_wrapper_xlib) = dlsym(handle, "XFreeFontNames");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XFreeFontPath
+ *(void **) (&XFreeFontPath_dylibloader_wrapper_xlib) = dlsym(handle, "XFreeFontPath");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XFreeGC
+ *(void **) (&XFreeGC_dylibloader_wrapper_xlib) = dlsym(handle, "XFreeGC");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XFreeModifiermap
+ *(void **) (&XFreeModifiermap_dylibloader_wrapper_xlib) = dlsym(handle, "XFreeModifiermap");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XFreePixmap
+ *(void **) (&XFreePixmap_dylibloader_wrapper_xlib) = dlsym(handle, "XFreePixmap");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XGeometry
+ *(void **) (&XGeometry_dylibloader_wrapper_xlib) = dlsym(handle, "XGeometry");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XGetErrorDatabaseText
+ *(void **) (&XGetErrorDatabaseText_dylibloader_wrapper_xlib) = dlsym(handle, "XGetErrorDatabaseText");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XGetErrorText
+ *(void **) (&XGetErrorText_dylibloader_wrapper_xlib) = dlsym(handle, "XGetErrorText");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XGetFontProperty
+ *(void **) (&XGetFontProperty_dylibloader_wrapper_xlib) = dlsym(handle, "XGetFontProperty");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XGetGCValues
+ *(void **) (&XGetGCValues_dylibloader_wrapper_xlib) = dlsym(handle, "XGetGCValues");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XGetGeometry
+ *(void **) (&XGetGeometry_dylibloader_wrapper_xlib) = dlsym(handle, "XGetGeometry");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XGetIconName
+ *(void **) (&XGetIconName_dylibloader_wrapper_xlib) = dlsym(handle, "XGetIconName");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XGetInputFocus
+ *(void **) (&XGetInputFocus_dylibloader_wrapper_xlib) = dlsym(handle, "XGetInputFocus");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XGetKeyboardControl
+ *(void **) (&XGetKeyboardControl_dylibloader_wrapper_xlib) = dlsym(handle, "XGetKeyboardControl");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XGetPointerControl
+ *(void **) (&XGetPointerControl_dylibloader_wrapper_xlib) = dlsym(handle, "XGetPointerControl");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XGetPointerMapping
+ *(void **) (&XGetPointerMapping_dylibloader_wrapper_xlib) = dlsym(handle, "XGetPointerMapping");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XGetScreenSaver
+ *(void **) (&XGetScreenSaver_dylibloader_wrapper_xlib) = dlsym(handle, "XGetScreenSaver");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XGetTransientForHint
+ *(void **) (&XGetTransientForHint_dylibloader_wrapper_xlib) = dlsym(handle, "XGetTransientForHint");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XGetWindowProperty
+ *(void **) (&XGetWindowProperty_dylibloader_wrapper_xlib) = dlsym(handle, "XGetWindowProperty");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XGetWindowAttributes
+ *(void **) (&XGetWindowAttributes_dylibloader_wrapper_xlib) = dlsym(handle, "XGetWindowAttributes");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XGrabButton
+ *(void **) (&XGrabButton_dylibloader_wrapper_xlib) = dlsym(handle, "XGrabButton");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XGrabKey
+ *(void **) (&XGrabKey_dylibloader_wrapper_xlib) = dlsym(handle, "XGrabKey");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XGrabKeyboard
+ *(void **) (&XGrabKeyboard_dylibloader_wrapper_xlib) = dlsym(handle, "XGrabKeyboard");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XGrabPointer
+ *(void **) (&XGrabPointer_dylibloader_wrapper_xlib) = dlsym(handle, "XGrabPointer");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XGrabServer
+ *(void **) (&XGrabServer_dylibloader_wrapper_xlib) = dlsym(handle, "XGrabServer");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XHeightMMOfScreen
+ *(void **) (&XHeightMMOfScreen_dylibloader_wrapper_xlib) = dlsym(handle, "XHeightMMOfScreen");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XHeightOfScreen
+ *(void **) (&XHeightOfScreen_dylibloader_wrapper_xlib) = dlsym(handle, "XHeightOfScreen");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XIfEvent
+ *(void **) (&XIfEvent_dylibloader_wrapper_xlib) = dlsym(handle, "XIfEvent");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XImageByteOrder
+ *(void **) (&XImageByteOrder_dylibloader_wrapper_xlib) = dlsym(handle, "XImageByteOrder");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XInstallColormap
+ *(void **) (&XInstallColormap_dylibloader_wrapper_xlib) = dlsym(handle, "XInstallColormap");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XKeysymToKeycode
+ *(void **) (&XKeysymToKeycode_dylibloader_wrapper_xlib) = dlsym(handle, "XKeysymToKeycode");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XKillClient
+ *(void **) (&XKillClient_dylibloader_wrapper_xlib) = dlsym(handle, "XKillClient");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XLookupColor
+ *(void **) (&XLookupColor_dylibloader_wrapper_xlib) = dlsym(handle, "XLookupColor");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XLowerWindow
+ *(void **) (&XLowerWindow_dylibloader_wrapper_xlib) = dlsym(handle, "XLowerWindow");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XMapRaised
+ *(void **) (&XMapRaised_dylibloader_wrapper_xlib) = dlsym(handle, "XMapRaised");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XMapSubwindows
+ *(void **) (&XMapSubwindows_dylibloader_wrapper_xlib) = dlsym(handle, "XMapSubwindows");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XMapWindow
+ *(void **) (&XMapWindow_dylibloader_wrapper_xlib) = dlsym(handle, "XMapWindow");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XMaskEvent
+ *(void **) (&XMaskEvent_dylibloader_wrapper_xlib) = dlsym(handle, "XMaskEvent");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XMaxCmapsOfScreen
+ *(void **) (&XMaxCmapsOfScreen_dylibloader_wrapper_xlib) = dlsym(handle, "XMaxCmapsOfScreen");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XMinCmapsOfScreen
+ *(void **) (&XMinCmapsOfScreen_dylibloader_wrapper_xlib) = dlsym(handle, "XMinCmapsOfScreen");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XMoveResizeWindow
+ *(void **) (&XMoveResizeWindow_dylibloader_wrapper_xlib) = dlsym(handle, "XMoveResizeWindow");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XMoveWindow
+ *(void **) (&XMoveWindow_dylibloader_wrapper_xlib) = dlsym(handle, "XMoveWindow");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XNextEvent
+ *(void **) (&XNextEvent_dylibloader_wrapper_xlib) = dlsym(handle, "XNextEvent");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XNoOp
+ *(void **) (&XNoOp_dylibloader_wrapper_xlib) = dlsym(handle, "XNoOp");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XParseColor
+ *(void **) (&XParseColor_dylibloader_wrapper_xlib) = dlsym(handle, "XParseColor");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XParseGeometry
+ *(void **) (&XParseGeometry_dylibloader_wrapper_xlib) = dlsym(handle, "XParseGeometry");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XPeekEvent
+ *(void **) (&XPeekEvent_dylibloader_wrapper_xlib) = dlsym(handle, "XPeekEvent");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XPeekIfEvent
+ *(void **) (&XPeekIfEvent_dylibloader_wrapper_xlib) = dlsym(handle, "XPeekIfEvent");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XPending
+ *(void **) (&XPending_dylibloader_wrapper_xlib) = dlsym(handle, "XPending");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XPlanesOfScreen
+ *(void **) (&XPlanesOfScreen_dylibloader_wrapper_xlib) = dlsym(handle, "XPlanesOfScreen");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XProtocolRevision
+ *(void **) (&XProtocolRevision_dylibloader_wrapper_xlib) = dlsym(handle, "XProtocolRevision");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XProtocolVersion
+ *(void **) (&XProtocolVersion_dylibloader_wrapper_xlib) = dlsym(handle, "XProtocolVersion");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XPutBackEvent
+ *(void **) (&XPutBackEvent_dylibloader_wrapper_xlib) = dlsym(handle, "XPutBackEvent");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XPutImage
+ *(void **) (&XPutImage_dylibloader_wrapper_xlib) = dlsym(handle, "XPutImage");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XQLength
+ *(void **) (&XQLength_dylibloader_wrapper_xlib) = dlsym(handle, "XQLength");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XQueryBestCursor
+ *(void **) (&XQueryBestCursor_dylibloader_wrapper_xlib) = dlsym(handle, "XQueryBestCursor");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XQueryBestSize
+ *(void **) (&XQueryBestSize_dylibloader_wrapper_xlib) = dlsym(handle, "XQueryBestSize");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XQueryBestStipple
+ *(void **) (&XQueryBestStipple_dylibloader_wrapper_xlib) = dlsym(handle, "XQueryBestStipple");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XQueryBestTile
+ *(void **) (&XQueryBestTile_dylibloader_wrapper_xlib) = dlsym(handle, "XQueryBestTile");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XQueryColor
+ *(void **) (&XQueryColor_dylibloader_wrapper_xlib) = dlsym(handle, "XQueryColor");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XQueryColors
+ *(void **) (&XQueryColors_dylibloader_wrapper_xlib) = dlsym(handle, "XQueryColors");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XQueryExtension
+ *(void **) (&XQueryExtension_dylibloader_wrapper_xlib) = dlsym(handle, "XQueryExtension");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XQueryKeymap
+ *(void **) (&XQueryKeymap_dylibloader_wrapper_xlib) = dlsym(handle, "XQueryKeymap");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XQueryPointer
+ *(void **) (&XQueryPointer_dylibloader_wrapper_xlib) = dlsym(handle, "XQueryPointer");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XQueryTextExtents
+ *(void **) (&XQueryTextExtents_dylibloader_wrapper_xlib) = dlsym(handle, "XQueryTextExtents");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XQueryTextExtents16
+ *(void **) (&XQueryTextExtents16_dylibloader_wrapper_xlib) = dlsym(handle, "XQueryTextExtents16");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XQueryTree
+ *(void **) (&XQueryTree_dylibloader_wrapper_xlib) = dlsym(handle, "XQueryTree");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRaiseWindow
+ *(void **) (&XRaiseWindow_dylibloader_wrapper_xlib) = dlsym(handle, "XRaiseWindow");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XReadBitmapFile
+ *(void **) (&XReadBitmapFile_dylibloader_wrapper_xlib) = dlsym(handle, "XReadBitmapFile");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XReadBitmapFileData
+ *(void **) (&XReadBitmapFileData_dylibloader_wrapper_xlib) = dlsym(handle, "XReadBitmapFileData");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRebindKeysym
+ *(void **) (&XRebindKeysym_dylibloader_wrapper_xlib) = dlsym(handle, "XRebindKeysym");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRecolorCursor
+ *(void **) (&XRecolorCursor_dylibloader_wrapper_xlib) = dlsym(handle, "XRecolorCursor");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRefreshKeyboardMapping
+ *(void **) (&XRefreshKeyboardMapping_dylibloader_wrapper_xlib) = dlsym(handle, "XRefreshKeyboardMapping");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRemoveFromSaveSet
+ *(void **) (&XRemoveFromSaveSet_dylibloader_wrapper_xlib) = dlsym(handle, "XRemoveFromSaveSet");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRemoveHost
+ *(void **) (&XRemoveHost_dylibloader_wrapper_xlib) = dlsym(handle, "XRemoveHost");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRemoveHosts
+ *(void **) (&XRemoveHosts_dylibloader_wrapper_xlib) = dlsym(handle, "XRemoveHosts");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XReparentWindow
+ *(void **) (&XReparentWindow_dylibloader_wrapper_xlib) = dlsym(handle, "XReparentWindow");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XResetScreenSaver
+ *(void **) (&XResetScreenSaver_dylibloader_wrapper_xlib) = dlsym(handle, "XResetScreenSaver");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XResizeWindow
+ *(void **) (&XResizeWindow_dylibloader_wrapper_xlib) = dlsym(handle, "XResizeWindow");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRestackWindows
+ *(void **) (&XRestackWindows_dylibloader_wrapper_xlib) = dlsym(handle, "XRestackWindows");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRotateBuffers
+ *(void **) (&XRotateBuffers_dylibloader_wrapper_xlib) = dlsym(handle, "XRotateBuffers");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRotateWindowProperties
+ *(void **) (&XRotateWindowProperties_dylibloader_wrapper_xlib) = dlsym(handle, "XRotateWindowProperties");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XScreenCount
+ *(void **) (&XScreenCount_dylibloader_wrapper_xlib) = dlsym(handle, "XScreenCount");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XSelectInput
+ *(void **) (&XSelectInput_dylibloader_wrapper_xlib) = dlsym(handle, "XSelectInput");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XSendEvent
+ *(void **) (&XSendEvent_dylibloader_wrapper_xlib) = dlsym(handle, "XSendEvent");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XSetAccessControl
+ *(void **) (&XSetAccessControl_dylibloader_wrapper_xlib) = dlsym(handle, "XSetAccessControl");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XSetArcMode
+ *(void **) (&XSetArcMode_dylibloader_wrapper_xlib) = dlsym(handle, "XSetArcMode");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XSetBackground
+ *(void **) (&XSetBackground_dylibloader_wrapper_xlib) = dlsym(handle, "XSetBackground");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XSetClipMask
+ *(void **) (&XSetClipMask_dylibloader_wrapper_xlib) = dlsym(handle, "XSetClipMask");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XSetClipOrigin
+ *(void **) (&XSetClipOrigin_dylibloader_wrapper_xlib) = dlsym(handle, "XSetClipOrigin");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XSetClipRectangles
+ *(void **) (&XSetClipRectangles_dylibloader_wrapper_xlib) = dlsym(handle, "XSetClipRectangles");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XSetCloseDownMode
+ *(void **) (&XSetCloseDownMode_dylibloader_wrapper_xlib) = dlsym(handle, "XSetCloseDownMode");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XSetCommand
+ *(void **) (&XSetCommand_dylibloader_wrapper_xlib) = dlsym(handle, "XSetCommand");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XSetDashes
+ *(void **) (&XSetDashes_dylibloader_wrapper_xlib) = dlsym(handle, "XSetDashes");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XSetFillRule
+ *(void **) (&XSetFillRule_dylibloader_wrapper_xlib) = dlsym(handle, "XSetFillRule");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XSetFillStyle
+ *(void **) (&XSetFillStyle_dylibloader_wrapper_xlib) = dlsym(handle, "XSetFillStyle");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XSetFont
+ *(void **) (&XSetFont_dylibloader_wrapper_xlib) = dlsym(handle, "XSetFont");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XSetFontPath
+ *(void **) (&XSetFontPath_dylibloader_wrapper_xlib) = dlsym(handle, "XSetFontPath");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XSetForeground
+ *(void **) (&XSetForeground_dylibloader_wrapper_xlib) = dlsym(handle, "XSetForeground");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XSetFunction
+ *(void **) (&XSetFunction_dylibloader_wrapper_xlib) = dlsym(handle, "XSetFunction");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XSetGraphicsExposures
+ *(void **) (&XSetGraphicsExposures_dylibloader_wrapper_xlib) = dlsym(handle, "XSetGraphicsExposures");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XSetIconName
+ *(void **) (&XSetIconName_dylibloader_wrapper_xlib) = dlsym(handle, "XSetIconName");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XSetInputFocus
+ *(void **) (&XSetInputFocus_dylibloader_wrapper_xlib) = dlsym(handle, "XSetInputFocus");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XSetLineAttributes
+ *(void **) (&XSetLineAttributes_dylibloader_wrapper_xlib) = dlsym(handle, "XSetLineAttributes");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XSetModifierMapping
+ *(void **) (&XSetModifierMapping_dylibloader_wrapper_xlib) = dlsym(handle, "XSetModifierMapping");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XSetPlaneMask
+ *(void **) (&XSetPlaneMask_dylibloader_wrapper_xlib) = dlsym(handle, "XSetPlaneMask");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XSetPointerMapping
+ *(void **) (&XSetPointerMapping_dylibloader_wrapper_xlib) = dlsym(handle, "XSetPointerMapping");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XSetScreenSaver
+ *(void **) (&XSetScreenSaver_dylibloader_wrapper_xlib) = dlsym(handle, "XSetScreenSaver");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XSetSelectionOwner
+ *(void **) (&XSetSelectionOwner_dylibloader_wrapper_xlib) = dlsym(handle, "XSetSelectionOwner");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XSetState
+ *(void **) (&XSetState_dylibloader_wrapper_xlib) = dlsym(handle, "XSetState");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XSetStipple
+ *(void **) (&XSetStipple_dylibloader_wrapper_xlib) = dlsym(handle, "XSetStipple");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XSetSubwindowMode
+ *(void **) (&XSetSubwindowMode_dylibloader_wrapper_xlib) = dlsym(handle, "XSetSubwindowMode");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XSetTSOrigin
+ *(void **) (&XSetTSOrigin_dylibloader_wrapper_xlib) = dlsym(handle, "XSetTSOrigin");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XSetTile
+ *(void **) (&XSetTile_dylibloader_wrapper_xlib) = dlsym(handle, "XSetTile");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XSetWindowBackground
+ *(void **) (&XSetWindowBackground_dylibloader_wrapper_xlib) = dlsym(handle, "XSetWindowBackground");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XSetWindowBackgroundPixmap
+ *(void **) (&XSetWindowBackgroundPixmap_dylibloader_wrapper_xlib) = dlsym(handle, "XSetWindowBackgroundPixmap");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XSetWindowBorder
+ *(void **) (&XSetWindowBorder_dylibloader_wrapper_xlib) = dlsym(handle, "XSetWindowBorder");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XSetWindowBorderPixmap
+ *(void **) (&XSetWindowBorderPixmap_dylibloader_wrapper_xlib) = dlsym(handle, "XSetWindowBorderPixmap");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XSetWindowBorderWidth
+ *(void **) (&XSetWindowBorderWidth_dylibloader_wrapper_xlib) = dlsym(handle, "XSetWindowBorderWidth");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XSetWindowColormap
+ *(void **) (&XSetWindowColormap_dylibloader_wrapper_xlib) = dlsym(handle, "XSetWindowColormap");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XStoreBuffer
+ *(void **) (&XStoreBuffer_dylibloader_wrapper_xlib) = dlsym(handle, "XStoreBuffer");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XStoreBytes
+ *(void **) (&XStoreBytes_dylibloader_wrapper_xlib) = dlsym(handle, "XStoreBytes");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XStoreColor
+ *(void **) (&XStoreColor_dylibloader_wrapper_xlib) = dlsym(handle, "XStoreColor");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XStoreColors
+ *(void **) (&XStoreColors_dylibloader_wrapper_xlib) = dlsym(handle, "XStoreColors");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XStoreName
+ *(void **) (&XStoreName_dylibloader_wrapper_xlib) = dlsym(handle, "XStoreName");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XStoreNamedColor
+ *(void **) (&XStoreNamedColor_dylibloader_wrapper_xlib) = dlsym(handle, "XStoreNamedColor");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XSync
+ *(void **) (&XSync_dylibloader_wrapper_xlib) = dlsym(handle, "XSync");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XTextExtents
+ *(void **) (&XTextExtents_dylibloader_wrapper_xlib) = dlsym(handle, "XTextExtents");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XTextExtents16
+ *(void **) (&XTextExtents16_dylibloader_wrapper_xlib) = dlsym(handle, "XTextExtents16");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XTextWidth
+ *(void **) (&XTextWidth_dylibloader_wrapper_xlib) = dlsym(handle, "XTextWidth");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XTextWidth16
+ *(void **) (&XTextWidth16_dylibloader_wrapper_xlib) = dlsym(handle, "XTextWidth16");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XTranslateCoordinates
+ *(void **) (&XTranslateCoordinates_dylibloader_wrapper_xlib) = dlsym(handle, "XTranslateCoordinates");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XUndefineCursor
+ *(void **) (&XUndefineCursor_dylibloader_wrapper_xlib) = dlsym(handle, "XUndefineCursor");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XUngrabButton
+ *(void **) (&XUngrabButton_dylibloader_wrapper_xlib) = dlsym(handle, "XUngrabButton");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XUngrabKey
+ *(void **) (&XUngrabKey_dylibloader_wrapper_xlib) = dlsym(handle, "XUngrabKey");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XUngrabKeyboard
+ *(void **) (&XUngrabKeyboard_dylibloader_wrapper_xlib) = dlsym(handle, "XUngrabKeyboard");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XUngrabPointer
+ *(void **) (&XUngrabPointer_dylibloader_wrapper_xlib) = dlsym(handle, "XUngrabPointer");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XUngrabServer
+ *(void **) (&XUngrabServer_dylibloader_wrapper_xlib) = dlsym(handle, "XUngrabServer");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XUninstallColormap
+ *(void **) (&XUninstallColormap_dylibloader_wrapper_xlib) = dlsym(handle, "XUninstallColormap");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XUnloadFont
+ *(void **) (&XUnloadFont_dylibloader_wrapper_xlib) = dlsym(handle, "XUnloadFont");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XUnmapSubwindows
+ *(void **) (&XUnmapSubwindows_dylibloader_wrapper_xlib) = dlsym(handle, "XUnmapSubwindows");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XUnmapWindow
+ *(void **) (&XUnmapWindow_dylibloader_wrapper_xlib) = dlsym(handle, "XUnmapWindow");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XVendorRelease
+ *(void **) (&XVendorRelease_dylibloader_wrapper_xlib) = dlsym(handle, "XVendorRelease");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XWarpPointer
+ *(void **) (&XWarpPointer_dylibloader_wrapper_xlib) = dlsym(handle, "XWarpPointer");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XWidthMMOfScreen
+ *(void **) (&XWidthMMOfScreen_dylibloader_wrapper_xlib) = dlsym(handle, "XWidthMMOfScreen");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XWidthOfScreen
+ *(void **) (&XWidthOfScreen_dylibloader_wrapper_xlib) = dlsym(handle, "XWidthOfScreen");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XWindowEvent
+ *(void **) (&XWindowEvent_dylibloader_wrapper_xlib) = dlsym(handle, "XWindowEvent");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XWriteBitmapFile
+ *(void **) (&XWriteBitmapFile_dylibloader_wrapper_xlib) = dlsym(handle, "XWriteBitmapFile");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XSupportsLocale
+ *(void **) (&XSupportsLocale_dylibloader_wrapper_xlib) = dlsym(handle, "XSupportsLocale");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XSetLocaleModifiers
+ *(void **) (&XSetLocaleModifiers_dylibloader_wrapper_xlib) = dlsym(handle, "XSetLocaleModifiers");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XOpenOM
+ *(void **) (&XOpenOM_dylibloader_wrapper_xlib) = dlsym(handle, "XOpenOM");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XCloseOM
+ *(void **) (&XCloseOM_dylibloader_wrapper_xlib) = dlsym(handle, "XCloseOM");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XSetOMValues
+ *(void **) (&XSetOMValues_dylibloader_wrapper_xlib) = dlsym(handle, "XSetOMValues");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XGetOMValues
+ *(void **) (&XGetOMValues_dylibloader_wrapper_xlib) = dlsym(handle, "XGetOMValues");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XDisplayOfOM
+ *(void **) (&XDisplayOfOM_dylibloader_wrapper_xlib) = dlsym(handle, "XDisplayOfOM");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XLocaleOfOM
+ *(void **) (&XLocaleOfOM_dylibloader_wrapper_xlib) = dlsym(handle, "XLocaleOfOM");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XCreateOC
+ *(void **) (&XCreateOC_dylibloader_wrapper_xlib) = dlsym(handle, "XCreateOC");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XDestroyOC
+ *(void **) (&XDestroyOC_dylibloader_wrapper_xlib) = dlsym(handle, "XDestroyOC");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XOMOfOC
+ *(void **) (&XOMOfOC_dylibloader_wrapper_xlib) = dlsym(handle, "XOMOfOC");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XSetOCValues
+ *(void **) (&XSetOCValues_dylibloader_wrapper_xlib) = dlsym(handle, "XSetOCValues");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XGetOCValues
+ *(void **) (&XGetOCValues_dylibloader_wrapper_xlib) = dlsym(handle, "XGetOCValues");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XCreateFontSet
+ *(void **) (&XCreateFontSet_dylibloader_wrapper_xlib) = dlsym(handle, "XCreateFontSet");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XFreeFontSet
+ *(void **) (&XFreeFontSet_dylibloader_wrapper_xlib) = dlsym(handle, "XFreeFontSet");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XFontsOfFontSet
+ *(void **) (&XFontsOfFontSet_dylibloader_wrapper_xlib) = dlsym(handle, "XFontsOfFontSet");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XBaseFontNameListOfFontSet
+ *(void **) (&XBaseFontNameListOfFontSet_dylibloader_wrapper_xlib) = dlsym(handle, "XBaseFontNameListOfFontSet");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XLocaleOfFontSet
+ *(void **) (&XLocaleOfFontSet_dylibloader_wrapper_xlib) = dlsym(handle, "XLocaleOfFontSet");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XContextDependentDrawing
+ *(void **) (&XContextDependentDrawing_dylibloader_wrapper_xlib) = dlsym(handle, "XContextDependentDrawing");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XDirectionalDependentDrawing
+ *(void **) (&XDirectionalDependentDrawing_dylibloader_wrapper_xlib) = dlsym(handle, "XDirectionalDependentDrawing");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XContextualDrawing
+ *(void **) (&XContextualDrawing_dylibloader_wrapper_xlib) = dlsym(handle, "XContextualDrawing");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XExtentsOfFontSet
+ *(void **) (&XExtentsOfFontSet_dylibloader_wrapper_xlib) = dlsym(handle, "XExtentsOfFontSet");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XmbTextEscapement
+ *(void **) (&XmbTextEscapement_dylibloader_wrapper_xlib) = dlsym(handle, "XmbTextEscapement");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XwcTextEscapement
+ *(void **) (&XwcTextEscapement_dylibloader_wrapper_xlib) = dlsym(handle, "XwcTextEscapement");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// Xutf8TextEscapement
+ *(void **) (&Xutf8TextEscapement_dylibloader_wrapper_xlib) = dlsym(handle, "Xutf8TextEscapement");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XmbTextExtents
+ *(void **) (&XmbTextExtents_dylibloader_wrapper_xlib) = dlsym(handle, "XmbTextExtents");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XwcTextExtents
+ *(void **) (&XwcTextExtents_dylibloader_wrapper_xlib) = dlsym(handle, "XwcTextExtents");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// Xutf8TextExtents
+ *(void **) (&Xutf8TextExtents_dylibloader_wrapper_xlib) = dlsym(handle, "Xutf8TextExtents");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XmbTextPerCharExtents
+ *(void **) (&XmbTextPerCharExtents_dylibloader_wrapper_xlib) = dlsym(handle, "XmbTextPerCharExtents");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XwcTextPerCharExtents
+ *(void **) (&XwcTextPerCharExtents_dylibloader_wrapper_xlib) = dlsym(handle, "XwcTextPerCharExtents");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// Xutf8TextPerCharExtents
+ *(void **) (&Xutf8TextPerCharExtents_dylibloader_wrapper_xlib) = dlsym(handle, "Xutf8TextPerCharExtents");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XmbDrawText
+ *(void **) (&XmbDrawText_dylibloader_wrapper_xlib) = dlsym(handle, "XmbDrawText");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XwcDrawText
+ *(void **) (&XwcDrawText_dylibloader_wrapper_xlib) = dlsym(handle, "XwcDrawText");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// Xutf8DrawText
+ *(void **) (&Xutf8DrawText_dylibloader_wrapper_xlib) = dlsym(handle, "Xutf8DrawText");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XmbDrawString
+ *(void **) (&XmbDrawString_dylibloader_wrapper_xlib) = dlsym(handle, "XmbDrawString");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XwcDrawString
+ *(void **) (&XwcDrawString_dylibloader_wrapper_xlib) = dlsym(handle, "XwcDrawString");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// Xutf8DrawString
+ *(void **) (&Xutf8DrawString_dylibloader_wrapper_xlib) = dlsym(handle, "Xutf8DrawString");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XmbDrawImageString
+ *(void **) (&XmbDrawImageString_dylibloader_wrapper_xlib) = dlsym(handle, "XmbDrawImageString");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XwcDrawImageString
+ *(void **) (&XwcDrawImageString_dylibloader_wrapper_xlib) = dlsym(handle, "XwcDrawImageString");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// Xutf8DrawImageString
+ *(void **) (&Xutf8DrawImageString_dylibloader_wrapper_xlib) = dlsym(handle, "Xutf8DrawImageString");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XOpenIM
+ *(void **) (&XOpenIM_dylibloader_wrapper_xlib) = dlsym(handle, "XOpenIM");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XCloseIM
+ *(void **) (&XCloseIM_dylibloader_wrapper_xlib) = dlsym(handle, "XCloseIM");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XGetIMValues
+ *(void **) (&XGetIMValues_dylibloader_wrapper_xlib) = dlsym(handle, "XGetIMValues");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XSetIMValues
+ *(void **) (&XSetIMValues_dylibloader_wrapper_xlib) = dlsym(handle, "XSetIMValues");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XDisplayOfIM
+ *(void **) (&XDisplayOfIM_dylibloader_wrapper_xlib) = dlsym(handle, "XDisplayOfIM");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XLocaleOfIM
+ *(void **) (&XLocaleOfIM_dylibloader_wrapper_xlib) = dlsym(handle, "XLocaleOfIM");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XCreateIC
+ *(void **) (&XCreateIC_dylibloader_wrapper_xlib) = dlsym(handle, "XCreateIC");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XDestroyIC
+ *(void **) (&XDestroyIC_dylibloader_wrapper_xlib) = dlsym(handle, "XDestroyIC");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XSetICFocus
+ *(void **) (&XSetICFocus_dylibloader_wrapper_xlib) = dlsym(handle, "XSetICFocus");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XUnsetICFocus
+ *(void **) (&XUnsetICFocus_dylibloader_wrapper_xlib) = dlsym(handle, "XUnsetICFocus");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XwcResetIC
+ *(void **) (&XwcResetIC_dylibloader_wrapper_xlib) = dlsym(handle, "XwcResetIC");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XmbResetIC
+ *(void **) (&XmbResetIC_dylibloader_wrapper_xlib) = dlsym(handle, "XmbResetIC");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// Xutf8ResetIC
+ *(void **) (&Xutf8ResetIC_dylibloader_wrapper_xlib) = dlsym(handle, "Xutf8ResetIC");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XSetICValues
+ *(void **) (&XSetICValues_dylibloader_wrapper_xlib) = dlsym(handle, "XSetICValues");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XGetICValues
+ *(void **) (&XGetICValues_dylibloader_wrapper_xlib) = dlsym(handle, "XGetICValues");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XIMOfIC
+ *(void **) (&XIMOfIC_dylibloader_wrapper_xlib) = dlsym(handle, "XIMOfIC");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XFilterEvent
+ *(void **) (&XFilterEvent_dylibloader_wrapper_xlib) = dlsym(handle, "XFilterEvent");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XmbLookupString
+ *(void **) (&XmbLookupString_dylibloader_wrapper_xlib) = dlsym(handle, "XmbLookupString");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XwcLookupString
+ *(void **) (&XwcLookupString_dylibloader_wrapper_xlib) = dlsym(handle, "XwcLookupString");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// Xutf8LookupString
+ *(void **) (&Xutf8LookupString_dylibloader_wrapper_xlib) = dlsym(handle, "Xutf8LookupString");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XVaCreateNestedList
+ *(void **) (&XVaCreateNestedList_dylibloader_wrapper_xlib) = dlsym(handle, "XVaCreateNestedList");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRegisterIMInstantiateCallback
+ *(void **) (&XRegisterIMInstantiateCallback_dylibloader_wrapper_xlib) = dlsym(handle, "XRegisterIMInstantiateCallback");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XUnregisterIMInstantiateCallback
+ *(void **) (&XUnregisterIMInstantiateCallback_dylibloader_wrapper_xlib) = dlsym(handle, "XUnregisterIMInstantiateCallback");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XInternalConnectionNumbers
+ *(void **) (&XInternalConnectionNumbers_dylibloader_wrapper_xlib) = dlsym(handle, "XInternalConnectionNumbers");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XProcessInternalConnection
+ *(void **) (&XProcessInternalConnection_dylibloader_wrapper_xlib) = dlsym(handle, "XProcessInternalConnection");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XAddConnectionWatch
+ *(void **) (&XAddConnectionWatch_dylibloader_wrapper_xlib) = dlsym(handle, "XAddConnectionWatch");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRemoveConnectionWatch
+ *(void **) (&XRemoveConnectionWatch_dylibloader_wrapper_xlib) = dlsym(handle, "XRemoveConnectionWatch");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XSetAuthorization
+ *(void **) (&XSetAuthorization_dylibloader_wrapper_xlib) = dlsym(handle, "XSetAuthorization");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// _Xmbtowc
+ *(void **) (&_Xmbtowc_dylibloader_wrapper_xlib) = dlsym(handle, "_Xmbtowc");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// _Xwctomb
+ *(void **) (&_Xwctomb_dylibloader_wrapper_xlib) = dlsym(handle, "_Xwctomb");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XGetEventData
+ *(void **) (&XGetEventData_dylibloader_wrapper_xlib) = dlsym(handle, "XGetEventData");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XFreeEventData
+ *(void **) (&XFreeEventData_dylibloader_wrapper_xlib) = dlsym(handle, "XFreeEventData");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XAllocClassHint
+ *(void **) (&XAllocClassHint_dylibloader_wrapper_xlib) = dlsym(handle, "XAllocClassHint");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XAllocIconSize
+ *(void **) (&XAllocIconSize_dylibloader_wrapper_xlib) = dlsym(handle, "XAllocIconSize");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XAllocSizeHints
+ *(void **) (&XAllocSizeHints_dylibloader_wrapper_xlib) = dlsym(handle, "XAllocSizeHints");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XAllocStandardColormap
+ *(void **) (&XAllocStandardColormap_dylibloader_wrapper_xlib) = dlsym(handle, "XAllocStandardColormap");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XAllocWMHints
+ *(void **) (&XAllocWMHints_dylibloader_wrapper_xlib) = dlsym(handle, "XAllocWMHints");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XClipBox
+ *(void **) (&XClipBox_dylibloader_wrapper_xlib) = dlsym(handle, "XClipBox");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XCreateRegion
+ *(void **) (&XCreateRegion_dylibloader_wrapper_xlib) = dlsym(handle, "XCreateRegion");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XDefaultString
+ *(void **) (&XDefaultString_dylibloader_wrapper_xlib) = dlsym(handle, "XDefaultString");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XDeleteContext
+ *(void **) (&XDeleteContext_dylibloader_wrapper_xlib) = dlsym(handle, "XDeleteContext");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XDestroyRegion
+ *(void **) (&XDestroyRegion_dylibloader_wrapper_xlib) = dlsym(handle, "XDestroyRegion");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XEmptyRegion
+ *(void **) (&XEmptyRegion_dylibloader_wrapper_xlib) = dlsym(handle, "XEmptyRegion");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XEqualRegion
+ *(void **) (&XEqualRegion_dylibloader_wrapper_xlib) = dlsym(handle, "XEqualRegion");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XFindContext
+ *(void **) (&XFindContext_dylibloader_wrapper_xlib) = dlsym(handle, "XFindContext");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XGetClassHint
+ *(void **) (&XGetClassHint_dylibloader_wrapper_xlib) = dlsym(handle, "XGetClassHint");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XGetIconSizes
+ *(void **) (&XGetIconSizes_dylibloader_wrapper_xlib) = dlsym(handle, "XGetIconSizes");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XGetNormalHints
+ *(void **) (&XGetNormalHints_dylibloader_wrapper_xlib) = dlsym(handle, "XGetNormalHints");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XGetRGBColormaps
+ *(void **) (&XGetRGBColormaps_dylibloader_wrapper_xlib) = dlsym(handle, "XGetRGBColormaps");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XGetSizeHints
+ *(void **) (&XGetSizeHints_dylibloader_wrapper_xlib) = dlsym(handle, "XGetSizeHints");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XGetStandardColormap
+ *(void **) (&XGetStandardColormap_dylibloader_wrapper_xlib) = dlsym(handle, "XGetStandardColormap");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XGetTextProperty
+ *(void **) (&XGetTextProperty_dylibloader_wrapper_xlib) = dlsym(handle, "XGetTextProperty");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XGetVisualInfo
+ *(void **) (&XGetVisualInfo_dylibloader_wrapper_xlib) = dlsym(handle, "XGetVisualInfo");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XGetWMClientMachine
+ *(void **) (&XGetWMClientMachine_dylibloader_wrapper_xlib) = dlsym(handle, "XGetWMClientMachine");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XGetWMHints
+ *(void **) (&XGetWMHints_dylibloader_wrapper_xlib) = dlsym(handle, "XGetWMHints");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XGetWMIconName
+ *(void **) (&XGetWMIconName_dylibloader_wrapper_xlib) = dlsym(handle, "XGetWMIconName");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XGetWMName
+ *(void **) (&XGetWMName_dylibloader_wrapper_xlib) = dlsym(handle, "XGetWMName");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XGetWMNormalHints
+ *(void **) (&XGetWMNormalHints_dylibloader_wrapper_xlib) = dlsym(handle, "XGetWMNormalHints");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XGetWMSizeHints
+ *(void **) (&XGetWMSizeHints_dylibloader_wrapper_xlib) = dlsym(handle, "XGetWMSizeHints");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XGetZoomHints
+ *(void **) (&XGetZoomHints_dylibloader_wrapper_xlib) = dlsym(handle, "XGetZoomHints");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XIntersectRegion
+ *(void **) (&XIntersectRegion_dylibloader_wrapper_xlib) = dlsym(handle, "XIntersectRegion");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XConvertCase
+ *(void **) (&XConvertCase_dylibloader_wrapper_xlib) = dlsym(handle, "XConvertCase");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XLookupString
+ *(void **) (&XLookupString_dylibloader_wrapper_xlib) = dlsym(handle, "XLookupString");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XMatchVisualInfo
+ *(void **) (&XMatchVisualInfo_dylibloader_wrapper_xlib) = dlsym(handle, "XMatchVisualInfo");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XOffsetRegion
+ *(void **) (&XOffsetRegion_dylibloader_wrapper_xlib) = dlsym(handle, "XOffsetRegion");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XPointInRegion
+ *(void **) (&XPointInRegion_dylibloader_wrapper_xlib) = dlsym(handle, "XPointInRegion");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XPolygonRegion
+ *(void **) (&XPolygonRegion_dylibloader_wrapper_xlib) = dlsym(handle, "XPolygonRegion");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRectInRegion
+ *(void **) (&XRectInRegion_dylibloader_wrapper_xlib) = dlsym(handle, "XRectInRegion");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XSaveContext
+ *(void **) (&XSaveContext_dylibloader_wrapper_xlib) = dlsym(handle, "XSaveContext");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XSetClassHint
+ *(void **) (&XSetClassHint_dylibloader_wrapper_xlib) = dlsym(handle, "XSetClassHint");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XSetIconSizes
+ *(void **) (&XSetIconSizes_dylibloader_wrapper_xlib) = dlsym(handle, "XSetIconSizes");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XSetNormalHints
+ *(void **) (&XSetNormalHints_dylibloader_wrapper_xlib) = dlsym(handle, "XSetNormalHints");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XSetRGBColormaps
+ *(void **) (&XSetRGBColormaps_dylibloader_wrapper_xlib) = dlsym(handle, "XSetRGBColormaps");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XSetSizeHints
+ *(void **) (&XSetSizeHints_dylibloader_wrapper_xlib) = dlsym(handle, "XSetSizeHints");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XSetStandardProperties
+ *(void **) (&XSetStandardProperties_dylibloader_wrapper_xlib) = dlsym(handle, "XSetStandardProperties");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XSetTextProperty
+ *(void **) (&XSetTextProperty_dylibloader_wrapper_xlib) = dlsym(handle, "XSetTextProperty");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XSetWMClientMachine
+ *(void **) (&XSetWMClientMachine_dylibloader_wrapper_xlib) = dlsym(handle, "XSetWMClientMachine");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XSetWMHints
+ *(void **) (&XSetWMHints_dylibloader_wrapper_xlib) = dlsym(handle, "XSetWMHints");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XSetWMIconName
+ *(void **) (&XSetWMIconName_dylibloader_wrapper_xlib) = dlsym(handle, "XSetWMIconName");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XSetWMName
+ *(void **) (&XSetWMName_dylibloader_wrapper_xlib) = dlsym(handle, "XSetWMName");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XSetWMNormalHints
+ *(void **) (&XSetWMNormalHints_dylibloader_wrapper_xlib) = dlsym(handle, "XSetWMNormalHints");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XSetWMProperties
+ *(void **) (&XSetWMProperties_dylibloader_wrapper_xlib) = dlsym(handle, "XSetWMProperties");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XmbSetWMProperties
+ *(void **) (&XmbSetWMProperties_dylibloader_wrapper_xlib) = dlsym(handle, "XmbSetWMProperties");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// Xutf8SetWMProperties
+ *(void **) (&Xutf8SetWMProperties_dylibloader_wrapper_xlib) = dlsym(handle, "Xutf8SetWMProperties");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XSetWMSizeHints
+ *(void **) (&XSetWMSizeHints_dylibloader_wrapper_xlib) = dlsym(handle, "XSetWMSizeHints");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XSetRegion
+ *(void **) (&XSetRegion_dylibloader_wrapper_xlib) = dlsym(handle, "XSetRegion");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XSetStandardColormap
+ *(void **) (&XSetStandardColormap_dylibloader_wrapper_xlib) = dlsym(handle, "XSetStandardColormap");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XSetZoomHints
+ *(void **) (&XSetZoomHints_dylibloader_wrapper_xlib) = dlsym(handle, "XSetZoomHints");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XShrinkRegion
+ *(void **) (&XShrinkRegion_dylibloader_wrapper_xlib) = dlsym(handle, "XShrinkRegion");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XStringListToTextProperty
+ *(void **) (&XStringListToTextProperty_dylibloader_wrapper_xlib) = dlsym(handle, "XStringListToTextProperty");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XSubtractRegion
+ *(void **) (&XSubtractRegion_dylibloader_wrapper_xlib) = dlsym(handle, "XSubtractRegion");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XmbTextListToTextProperty
+ *(void **) (&XmbTextListToTextProperty_dylibloader_wrapper_xlib) = dlsym(handle, "XmbTextListToTextProperty");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XwcTextListToTextProperty
+ *(void **) (&XwcTextListToTextProperty_dylibloader_wrapper_xlib) = dlsym(handle, "XwcTextListToTextProperty");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// Xutf8TextListToTextProperty
+ *(void **) (&Xutf8TextListToTextProperty_dylibloader_wrapper_xlib) = dlsym(handle, "Xutf8TextListToTextProperty");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XwcFreeStringList
+ *(void **) (&XwcFreeStringList_dylibloader_wrapper_xlib) = dlsym(handle, "XwcFreeStringList");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XTextPropertyToStringList
+ *(void **) (&XTextPropertyToStringList_dylibloader_wrapper_xlib) = dlsym(handle, "XTextPropertyToStringList");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XmbTextPropertyToTextList
+ *(void **) (&XmbTextPropertyToTextList_dylibloader_wrapper_xlib) = dlsym(handle, "XmbTextPropertyToTextList");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XwcTextPropertyToTextList
+ *(void **) (&XwcTextPropertyToTextList_dylibloader_wrapper_xlib) = dlsym(handle, "XwcTextPropertyToTextList");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// Xutf8TextPropertyToTextList
+ *(void **) (&Xutf8TextPropertyToTextList_dylibloader_wrapper_xlib) = dlsym(handle, "Xutf8TextPropertyToTextList");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XUnionRectWithRegion
+ *(void **) (&XUnionRectWithRegion_dylibloader_wrapper_xlib) = dlsym(handle, "XUnionRectWithRegion");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XUnionRegion
+ *(void **) (&XUnionRegion_dylibloader_wrapper_xlib) = dlsym(handle, "XUnionRegion");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XWMGeometry
+ *(void **) (&XWMGeometry_dylibloader_wrapper_xlib) = dlsym(handle, "XWMGeometry");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XXorRegion
+ *(void **) (&XXorRegion_dylibloader_wrapper_xlib) = dlsym(handle, "XXorRegion");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbIgnoreExtension
+ *(void **) (&XkbIgnoreExtension_dylibloader_wrapper_xlib) = dlsym(handle, "XkbIgnoreExtension");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbOpenDisplay
+ *(void **) (&XkbOpenDisplay_dylibloader_wrapper_xlib) = dlsym(handle, "XkbOpenDisplay");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbQueryExtension
+ *(void **) (&XkbQueryExtension_dylibloader_wrapper_xlib) = dlsym(handle, "XkbQueryExtension");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbUseExtension
+ *(void **) (&XkbUseExtension_dylibloader_wrapper_xlib) = dlsym(handle, "XkbUseExtension");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbLibraryVersion
+ *(void **) (&XkbLibraryVersion_dylibloader_wrapper_xlib) = dlsym(handle, "XkbLibraryVersion");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbSetXlibControls
+ *(void **) (&XkbSetXlibControls_dylibloader_wrapper_xlib) = dlsym(handle, "XkbSetXlibControls");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbGetXlibControls
+ *(void **) (&XkbGetXlibControls_dylibloader_wrapper_xlib) = dlsym(handle, "XkbGetXlibControls");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbXlibControlsImplemented
+ *(void **) (&XkbXlibControlsImplemented_dylibloader_wrapper_xlib) = dlsym(handle, "XkbXlibControlsImplemented");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbSetAtomFuncs
+ *(void **) (&XkbSetAtomFuncs_dylibloader_wrapper_xlib) = dlsym(handle, "XkbSetAtomFuncs");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbKeycodeToKeysym
+ *(void **) (&XkbKeycodeToKeysym_dylibloader_wrapper_xlib) = dlsym(handle, "XkbKeycodeToKeysym");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbKeysymToModifiers
+ *(void **) (&XkbKeysymToModifiers_dylibloader_wrapper_xlib) = dlsym(handle, "XkbKeysymToModifiers");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbLookupKeySym
+ *(void **) (&XkbLookupKeySym_dylibloader_wrapper_xlib) = dlsym(handle, "XkbLookupKeySym");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbLookupKeyBinding
+ *(void **) (&XkbLookupKeyBinding_dylibloader_wrapper_xlib) = dlsym(handle, "XkbLookupKeyBinding");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbTranslateKeyCode
+ *(void **) (&XkbTranslateKeyCode_dylibloader_wrapper_xlib) = dlsym(handle, "XkbTranslateKeyCode");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbTranslateKeySym
+ *(void **) (&XkbTranslateKeySym_dylibloader_wrapper_xlib) = dlsym(handle, "XkbTranslateKeySym");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbSetAutoRepeatRate
+ *(void **) (&XkbSetAutoRepeatRate_dylibloader_wrapper_xlib) = dlsym(handle, "XkbSetAutoRepeatRate");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbGetAutoRepeatRate
+ *(void **) (&XkbGetAutoRepeatRate_dylibloader_wrapper_xlib) = dlsym(handle, "XkbGetAutoRepeatRate");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbChangeEnabledControls
+ *(void **) (&XkbChangeEnabledControls_dylibloader_wrapper_xlib) = dlsym(handle, "XkbChangeEnabledControls");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbDeviceBell
+ *(void **) (&XkbDeviceBell_dylibloader_wrapper_xlib) = dlsym(handle, "XkbDeviceBell");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbForceDeviceBell
+ *(void **) (&XkbForceDeviceBell_dylibloader_wrapper_xlib) = dlsym(handle, "XkbForceDeviceBell");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbDeviceBellEvent
+ *(void **) (&XkbDeviceBellEvent_dylibloader_wrapper_xlib) = dlsym(handle, "XkbDeviceBellEvent");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbBell
+ *(void **) (&XkbBell_dylibloader_wrapper_xlib) = dlsym(handle, "XkbBell");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbForceBell
+ *(void **) (&XkbForceBell_dylibloader_wrapper_xlib) = dlsym(handle, "XkbForceBell");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbBellEvent
+ *(void **) (&XkbBellEvent_dylibloader_wrapper_xlib) = dlsym(handle, "XkbBellEvent");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbSelectEvents
+ *(void **) (&XkbSelectEvents_dylibloader_wrapper_xlib) = dlsym(handle, "XkbSelectEvents");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbSelectEventDetails
+ *(void **) (&XkbSelectEventDetails_dylibloader_wrapper_xlib) = dlsym(handle, "XkbSelectEventDetails");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbNoteMapChanges
+ *(void **) (&XkbNoteMapChanges_dylibloader_wrapper_xlib) = dlsym(handle, "XkbNoteMapChanges");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbNoteNameChanges
+ *(void **) (&XkbNoteNameChanges_dylibloader_wrapper_xlib) = dlsym(handle, "XkbNoteNameChanges");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbGetIndicatorState
+ *(void **) (&XkbGetIndicatorState_dylibloader_wrapper_xlib) = dlsym(handle, "XkbGetIndicatorState");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbGetIndicatorMap
+ *(void **) (&XkbGetIndicatorMap_dylibloader_wrapper_xlib) = dlsym(handle, "XkbGetIndicatorMap");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbSetIndicatorMap
+ *(void **) (&XkbSetIndicatorMap_dylibloader_wrapper_xlib) = dlsym(handle, "XkbSetIndicatorMap");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbGetNamedIndicator
+ *(void **) (&XkbGetNamedIndicator_dylibloader_wrapper_xlib) = dlsym(handle, "XkbGetNamedIndicator");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbGetNamedDeviceIndicator
+ *(void **) (&XkbGetNamedDeviceIndicator_dylibloader_wrapper_xlib) = dlsym(handle, "XkbGetNamedDeviceIndicator");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbSetNamedIndicator
+ *(void **) (&XkbSetNamedIndicator_dylibloader_wrapper_xlib) = dlsym(handle, "XkbSetNamedIndicator");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbSetNamedDeviceIndicator
+ *(void **) (&XkbSetNamedDeviceIndicator_dylibloader_wrapper_xlib) = dlsym(handle, "XkbSetNamedDeviceIndicator");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbLockModifiers
+ *(void **) (&XkbLockModifiers_dylibloader_wrapper_xlib) = dlsym(handle, "XkbLockModifiers");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbLatchModifiers
+ *(void **) (&XkbLatchModifiers_dylibloader_wrapper_xlib) = dlsym(handle, "XkbLatchModifiers");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbLockGroup
+ *(void **) (&XkbLockGroup_dylibloader_wrapper_xlib) = dlsym(handle, "XkbLockGroup");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbLatchGroup
+ *(void **) (&XkbLatchGroup_dylibloader_wrapper_xlib) = dlsym(handle, "XkbLatchGroup");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbSetServerInternalMods
+ *(void **) (&XkbSetServerInternalMods_dylibloader_wrapper_xlib) = dlsym(handle, "XkbSetServerInternalMods");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbSetIgnoreLockMods
+ *(void **) (&XkbSetIgnoreLockMods_dylibloader_wrapper_xlib) = dlsym(handle, "XkbSetIgnoreLockMods");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbVirtualModsToReal
+ *(void **) (&XkbVirtualModsToReal_dylibloader_wrapper_xlib) = dlsym(handle, "XkbVirtualModsToReal");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbComputeEffectiveMap
+ *(void **) (&XkbComputeEffectiveMap_dylibloader_wrapper_xlib) = dlsym(handle, "XkbComputeEffectiveMap");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbInitCanonicalKeyTypes
+ *(void **) (&XkbInitCanonicalKeyTypes_dylibloader_wrapper_xlib) = dlsym(handle, "XkbInitCanonicalKeyTypes");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbAllocKeyboard
+ *(void **) (&XkbAllocKeyboard_dylibloader_wrapper_xlib) = dlsym(handle, "XkbAllocKeyboard");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbFreeKeyboard
+ *(void **) (&XkbFreeKeyboard_dylibloader_wrapper_xlib) = dlsym(handle, "XkbFreeKeyboard");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbAllocClientMap
+ *(void **) (&XkbAllocClientMap_dylibloader_wrapper_xlib) = dlsym(handle, "XkbAllocClientMap");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbAllocServerMap
+ *(void **) (&XkbAllocServerMap_dylibloader_wrapper_xlib) = dlsym(handle, "XkbAllocServerMap");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbFreeClientMap
+ *(void **) (&XkbFreeClientMap_dylibloader_wrapper_xlib) = dlsym(handle, "XkbFreeClientMap");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbFreeServerMap
+ *(void **) (&XkbFreeServerMap_dylibloader_wrapper_xlib) = dlsym(handle, "XkbFreeServerMap");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbAddKeyType
+ *(void **) (&XkbAddKeyType_dylibloader_wrapper_xlib) = dlsym(handle, "XkbAddKeyType");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbAllocIndicatorMaps
+ *(void **) (&XkbAllocIndicatorMaps_dylibloader_wrapper_xlib) = dlsym(handle, "XkbAllocIndicatorMaps");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbFreeIndicatorMaps
+ *(void **) (&XkbFreeIndicatorMaps_dylibloader_wrapper_xlib) = dlsym(handle, "XkbFreeIndicatorMaps");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbGetMap
+ *(void **) (&XkbGetMap_dylibloader_wrapper_xlib) = dlsym(handle, "XkbGetMap");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbGetUpdatedMap
+ *(void **) (&XkbGetUpdatedMap_dylibloader_wrapper_xlib) = dlsym(handle, "XkbGetUpdatedMap");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbGetMapChanges
+ *(void **) (&XkbGetMapChanges_dylibloader_wrapper_xlib) = dlsym(handle, "XkbGetMapChanges");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbRefreshKeyboardMapping
+ *(void **) (&XkbRefreshKeyboardMapping_dylibloader_wrapper_xlib) = dlsym(handle, "XkbRefreshKeyboardMapping");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbGetKeyTypes
+ *(void **) (&XkbGetKeyTypes_dylibloader_wrapper_xlib) = dlsym(handle, "XkbGetKeyTypes");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbGetKeySyms
+ *(void **) (&XkbGetKeySyms_dylibloader_wrapper_xlib) = dlsym(handle, "XkbGetKeySyms");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbGetKeyActions
+ *(void **) (&XkbGetKeyActions_dylibloader_wrapper_xlib) = dlsym(handle, "XkbGetKeyActions");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbGetKeyBehaviors
+ *(void **) (&XkbGetKeyBehaviors_dylibloader_wrapper_xlib) = dlsym(handle, "XkbGetKeyBehaviors");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbGetVirtualMods
+ *(void **) (&XkbGetVirtualMods_dylibloader_wrapper_xlib) = dlsym(handle, "XkbGetVirtualMods");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbGetKeyExplicitComponents
+ *(void **) (&XkbGetKeyExplicitComponents_dylibloader_wrapper_xlib) = dlsym(handle, "XkbGetKeyExplicitComponents");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbGetKeyModifierMap
+ *(void **) (&XkbGetKeyModifierMap_dylibloader_wrapper_xlib) = dlsym(handle, "XkbGetKeyModifierMap");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbGetKeyVirtualModMap
+ *(void **) (&XkbGetKeyVirtualModMap_dylibloader_wrapper_xlib) = dlsym(handle, "XkbGetKeyVirtualModMap");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbAllocControls
+ *(void **) (&XkbAllocControls_dylibloader_wrapper_xlib) = dlsym(handle, "XkbAllocControls");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbFreeControls
+ *(void **) (&XkbFreeControls_dylibloader_wrapper_xlib) = dlsym(handle, "XkbFreeControls");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbGetControls
+ *(void **) (&XkbGetControls_dylibloader_wrapper_xlib) = dlsym(handle, "XkbGetControls");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbSetControls
+ *(void **) (&XkbSetControls_dylibloader_wrapper_xlib) = dlsym(handle, "XkbSetControls");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbNoteControlsChanges
+ *(void **) (&XkbNoteControlsChanges_dylibloader_wrapper_xlib) = dlsym(handle, "XkbNoteControlsChanges");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbAllocCompatMap
+ *(void **) (&XkbAllocCompatMap_dylibloader_wrapper_xlib) = dlsym(handle, "XkbAllocCompatMap");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbFreeCompatMap
+ *(void **) (&XkbFreeCompatMap_dylibloader_wrapper_xlib) = dlsym(handle, "XkbFreeCompatMap");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbGetCompatMap
+ *(void **) (&XkbGetCompatMap_dylibloader_wrapper_xlib) = dlsym(handle, "XkbGetCompatMap");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbSetCompatMap
+ *(void **) (&XkbSetCompatMap_dylibloader_wrapper_xlib) = dlsym(handle, "XkbSetCompatMap");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbAllocNames
+ *(void **) (&XkbAllocNames_dylibloader_wrapper_xlib) = dlsym(handle, "XkbAllocNames");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbGetNames
+ *(void **) (&XkbGetNames_dylibloader_wrapper_xlib) = dlsym(handle, "XkbGetNames");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbSetNames
+ *(void **) (&XkbSetNames_dylibloader_wrapper_xlib) = dlsym(handle, "XkbSetNames");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbChangeNames
+ *(void **) (&XkbChangeNames_dylibloader_wrapper_xlib) = dlsym(handle, "XkbChangeNames");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbFreeNames
+ *(void **) (&XkbFreeNames_dylibloader_wrapper_xlib) = dlsym(handle, "XkbFreeNames");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbGetState
+ *(void **) (&XkbGetState_dylibloader_wrapper_xlib) = dlsym(handle, "XkbGetState");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbSetMap
+ *(void **) (&XkbSetMap_dylibloader_wrapper_xlib) = dlsym(handle, "XkbSetMap");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbChangeMap
+ *(void **) (&XkbChangeMap_dylibloader_wrapper_xlib) = dlsym(handle, "XkbChangeMap");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbSetDetectableAutoRepeat
+ *(void **) (&XkbSetDetectableAutoRepeat_dylibloader_wrapper_xlib) = dlsym(handle, "XkbSetDetectableAutoRepeat");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbGetDetectableAutoRepeat
+ *(void **) (&XkbGetDetectableAutoRepeat_dylibloader_wrapper_xlib) = dlsym(handle, "XkbGetDetectableAutoRepeat");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbSetAutoResetControls
+ *(void **) (&XkbSetAutoResetControls_dylibloader_wrapper_xlib) = dlsym(handle, "XkbSetAutoResetControls");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbGetAutoResetControls
+ *(void **) (&XkbGetAutoResetControls_dylibloader_wrapper_xlib) = dlsym(handle, "XkbGetAutoResetControls");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbSetPerClientControls
+ *(void **) (&XkbSetPerClientControls_dylibloader_wrapper_xlib) = dlsym(handle, "XkbSetPerClientControls");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbGetPerClientControls
+ *(void **) (&XkbGetPerClientControls_dylibloader_wrapper_xlib) = dlsym(handle, "XkbGetPerClientControls");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbCopyKeyType
+ *(void **) (&XkbCopyKeyType_dylibloader_wrapper_xlib) = dlsym(handle, "XkbCopyKeyType");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbCopyKeyTypes
+ *(void **) (&XkbCopyKeyTypes_dylibloader_wrapper_xlib) = dlsym(handle, "XkbCopyKeyTypes");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbResizeKeyType
+ *(void **) (&XkbResizeKeyType_dylibloader_wrapper_xlib) = dlsym(handle, "XkbResizeKeyType");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbResizeKeySyms
+ *(void **) (&XkbResizeKeySyms_dylibloader_wrapper_xlib) = dlsym(handle, "XkbResizeKeySyms");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbResizeKeyActions
+ *(void **) (&XkbResizeKeyActions_dylibloader_wrapper_xlib) = dlsym(handle, "XkbResizeKeyActions");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbChangeTypesOfKey
+ *(void **) (&XkbChangeTypesOfKey_dylibloader_wrapper_xlib) = dlsym(handle, "XkbChangeTypesOfKey");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbChangeKeycodeRange
+ *(void **) (&XkbChangeKeycodeRange_dylibloader_wrapper_xlib) = dlsym(handle, "XkbChangeKeycodeRange");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbListComponents
+ *(void **) (&XkbListComponents_dylibloader_wrapper_xlib) = dlsym(handle, "XkbListComponents");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbFreeComponentList
+ *(void **) (&XkbFreeComponentList_dylibloader_wrapper_xlib) = dlsym(handle, "XkbFreeComponentList");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbGetKeyboard
+ *(void **) (&XkbGetKeyboard_dylibloader_wrapper_xlib) = dlsym(handle, "XkbGetKeyboard");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbGetKeyboardByName
+ *(void **) (&XkbGetKeyboardByName_dylibloader_wrapper_xlib) = dlsym(handle, "XkbGetKeyboardByName");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbKeyTypesForCoreSymbols
+ *(void **) (&XkbKeyTypesForCoreSymbols_dylibloader_wrapper_xlib) = dlsym(handle, "XkbKeyTypesForCoreSymbols");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbApplyCompatMapToKey
+ *(void **) (&XkbApplyCompatMapToKey_dylibloader_wrapper_xlib) = dlsym(handle, "XkbApplyCompatMapToKey");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbUpdateMapFromCore
+ *(void **) (&XkbUpdateMapFromCore_dylibloader_wrapper_xlib) = dlsym(handle, "XkbUpdateMapFromCore");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbAddDeviceLedInfo
+ *(void **) (&XkbAddDeviceLedInfo_dylibloader_wrapper_xlib) = dlsym(handle, "XkbAddDeviceLedInfo");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbResizeDeviceButtonActions
+ *(void **) (&XkbResizeDeviceButtonActions_dylibloader_wrapper_xlib) = dlsym(handle, "XkbResizeDeviceButtonActions");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbAllocDeviceInfo
+ *(void **) (&XkbAllocDeviceInfo_dylibloader_wrapper_xlib) = dlsym(handle, "XkbAllocDeviceInfo");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbFreeDeviceInfo
+ *(void **) (&XkbFreeDeviceInfo_dylibloader_wrapper_xlib) = dlsym(handle, "XkbFreeDeviceInfo");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbNoteDeviceChanges
+ *(void **) (&XkbNoteDeviceChanges_dylibloader_wrapper_xlib) = dlsym(handle, "XkbNoteDeviceChanges");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbGetDeviceInfo
+ *(void **) (&XkbGetDeviceInfo_dylibloader_wrapper_xlib) = dlsym(handle, "XkbGetDeviceInfo");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbGetDeviceInfoChanges
+ *(void **) (&XkbGetDeviceInfoChanges_dylibloader_wrapper_xlib) = dlsym(handle, "XkbGetDeviceInfoChanges");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbGetDeviceButtonActions
+ *(void **) (&XkbGetDeviceButtonActions_dylibloader_wrapper_xlib) = dlsym(handle, "XkbGetDeviceButtonActions");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbGetDeviceLedInfo
+ *(void **) (&XkbGetDeviceLedInfo_dylibloader_wrapper_xlib) = dlsym(handle, "XkbGetDeviceLedInfo");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbSetDeviceInfo
+ *(void **) (&XkbSetDeviceInfo_dylibloader_wrapper_xlib) = dlsym(handle, "XkbSetDeviceInfo");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbChangeDeviceInfo
+ *(void **) (&XkbChangeDeviceInfo_dylibloader_wrapper_xlib) = dlsym(handle, "XkbChangeDeviceInfo");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbSetDeviceLedInfo
+ *(void **) (&XkbSetDeviceLedInfo_dylibloader_wrapper_xlib) = dlsym(handle, "XkbSetDeviceLedInfo");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbSetDeviceButtonActions
+ *(void **) (&XkbSetDeviceButtonActions_dylibloader_wrapper_xlib) = dlsym(handle, "XkbSetDeviceButtonActions");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbToControl
+ *(void **) (&XkbToControl_dylibloader_wrapper_xlib) = dlsym(handle, "XkbToControl");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbSetDebuggingFlags
+ *(void **) (&XkbSetDebuggingFlags_dylibloader_wrapper_xlib) = dlsym(handle, "XkbSetDebuggingFlags");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbApplyVirtualModChanges
+ *(void **) (&XkbApplyVirtualModChanges_dylibloader_wrapper_xlib) = dlsym(handle, "XkbApplyVirtualModChanges");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbUpdateActionVirtualMods
+ *(void **) (&XkbUpdateActionVirtualMods_dylibloader_wrapper_xlib) = dlsym(handle, "XkbUpdateActionVirtualMods");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XkbUpdateKeyTypeVirtualMods
+ *(void **) (&XkbUpdateKeyTypeVirtualMods_dylibloader_wrapper_xlib) = dlsym(handle, "XkbUpdateKeyTypeVirtualMods");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+return 0;
+}
diff --git a/platform/linuxbsd/x11/dynwrappers/xlib-so_wrap.h b/platform/linuxbsd/x11/dynwrappers/xlib-so_wrap.h
new file mode 100644
index 0000000000..47464078e3
--- /dev/null
+++ b/platform/linuxbsd/x11/dynwrappers/xlib-so_wrap.h
@@ -0,0 +1,2439 @@
+#ifndef DYLIBLOAD_WRAPPER_XLIB
+#define DYLIBLOAD_WRAPPER_XLIB
+// 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-12-02 12:54:53
+// flags: ./generate-wrapper.py --include /usr/include/X11/Xlib.h --include /usr/include/X11/Xutil.h --include /usr/include/X11/XKBlib.h --sys-include <X11/Xlib.h> --sys-include <X11/Xutil.h> --sys-include <X11/XKBlib.h> --soname libX11.so.6 --init-name xlib --omit-prefix XkbGetDeviceIndicatorState --omit-prefix XkbAddSymInterpret --output-header xlib-so_wrap.h --output-implementation xlib-so_wrap.c
+//
+// NOTE: Generated from Xlib 1.6.9.
+// This has been handpatched to workaround some issues with the generator that
+// will be eventually fixed. In this case, the type of the third argument of
+// XIfEvent, XPeekIfEvent and XCheckIfEvent had to be fixed as it wasn't parsed
+// fully (it's a Bool function pointer, but it was just being parsed as an int
+// pointer).
+
+#include <stdint.h>
+
+#define _Xmblen _Xmblen_dylibloader_orig_xlib
+#define XLoadQueryFont XLoadQueryFont_dylibloader_orig_xlib
+#define XQueryFont XQueryFont_dylibloader_orig_xlib
+#define XGetMotionEvents XGetMotionEvents_dylibloader_orig_xlib
+#define XDeleteModifiermapEntry XDeleteModifiermapEntry_dylibloader_orig_xlib
+#define XGetModifierMapping XGetModifierMapping_dylibloader_orig_xlib
+#define XInsertModifiermapEntry XInsertModifiermapEntry_dylibloader_orig_xlib
+#define XNewModifiermap XNewModifiermap_dylibloader_orig_xlib
+#define XCreateImage XCreateImage_dylibloader_orig_xlib
+#define XInitImage XInitImage_dylibloader_orig_xlib
+#define XGetImage XGetImage_dylibloader_orig_xlib
+#define XGetSubImage XGetSubImage_dylibloader_orig_xlib
+#define XOpenDisplay XOpenDisplay_dylibloader_orig_xlib
+#define XrmInitialize XrmInitialize_dylibloader_orig_xlib
+#define XFetchBytes XFetchBytes_dylibloader_orig_xlib
+#define XFetchBuffer XFetchBuffer_dylibloader_orig_xlib
+#define XGetAtomName XGetAtomName_dylibloader_orig_xlib
+#define XGetAtomNames XGetAtomNames_dylibloader_orig_xlib
+#define XGetDefault XGetDefault_dylibloader_orig_xlib
+#define XDisplayName XDisplayName_dylibloader_orig_xlib
+#define XKeysymToString XKeysymToString_dylibloader_orig_xlib
+#define XSynchronize XSynchronize_dylibloader_orig_xlib
+#define XSetAfterFunction XSetAfterFunction_dylibloader_orig_xlib
+#define XInternAtom XInternAtom_dylibloader_orig_xlib
+#define XInternAtoms XInternAtoms_dylibloader_orig_xlib
+#define XCopyColormapAndFree XCopyColormapAndFree_dylibloader_orig_xlib
+#define XCreateColormap XCreateColormap_dylibloader_orig_xlib
+#define XCreatePixmapCursor XCreatePixmapCursor_dylibloader_orig_xlib
+#define XCreateGlyphCursor XCreateGlyphCursor_dylibloader_orig_xlib
+#define XCreateFontCursor XCreateFontCursor_dylibloader_orig_xlib
+#define XLoadFont XLoadFont_dylibloader_orig_xlib
+#define XCreateGC XCreateGC_dylibloader_orig_xlib
+#define XGContextFromGC XGContextFromGC_dylibloader_orig_xlib
+#define XFlushGC XFlushGC_dylibloader_orig_xlib
+#define XCreatePixmap XCreatePixmap_dylibloader_orig_xlib
+#define XCreateBitmapFromData XCreateBitmapFromData_dylibloader_orig_xlib
+#define XCreatePixmapFromBitmapData XCreatePixmapFromBitmapData_dylibloader_orig_xlib
+#define XCreateSimpleWindow XCreateSimpleWindow_dylibloader_orig_xlib
+#define XGetSelectionOwner XGetSelectionOwner_dylibloader_orig_xlib
+#define XCreateWindow XCreateWindow_dylibloader_orig_xlib
+#define XListInstalledColormaps XListInstalledColormaps_dylibloader_orig_xlib
+#define XListFonts XListFonts_dylibloader_orig_xlib
+#define XListFontsWithInfo XListFontsWithInfo_dylibloader_orig_xlib
+#define XGetFontPath XGetFontPath_dylibloader_orig_xlib
+#define XListExtensions XListExtensions_dylibloader_orig_xlib
+#define XListProperties XListProperties_dylibloader_orig_xlib
+#define XListHosts XListHosts_dylibloader_orig_xlib
+#define XKeycodeToKeysym XKeycodeToKeysym_dylibloader_orig_xlib
+#define XLookupKeysym XLookupKeysym_dylibloader_orig_xlib
+#define XGetKeyboardMapping XGetKeyboardMapping_dylibloader_orig_xlib
+#define XStringToKeysym XStringToKeysym_dylibloader_orig_xlib
+#define XMaxRequestSize XMaxRequestSize_dylibloader_orig_xlib
+#define XExtendedMaxRequestSize XExtendedMaxRequestSize_dylibloader_orig_xlib
+#define XResourceManagerString XResourceManagerString_dylibloader_orig_xlib
+#define XScreenResourceString XScreenResourceString_dylibloader_orig_xlib
+#define XDisplayMotionBufferSize XDisplayMotionBufferSize_dylibloader_orig_xlib
+#define XVisualIDFromVisual XVisualIDFromVisual_dylibloader_orig_xlib
+#define XInitThreads XInitThreads_dylibloader_orig_xlib
+#define XLockDisplay XLockDisplay_dylibloader_orig_xlib
+#define XUnlockDisplay XUnlockDisplay_dylibloader_orig_xlib
+#define XInitExtension XInitExtension_dylibloader_orig_xlib
+#define XAddExtension XAddExtension_dylibloader_orig_xlib
+#define XFindOnExtensionList XFindOnExtensionList_dylibloader_orig_xlib
+#define XEHeadOfExtensionList XEHeadOfExtensionList_dylibloader_orig_xlib
+#define XRootWindow XRootWindow_dylibloader_orig_xlib
+#define XDefaultRootWindow XDefaultRootWindow_dylibloader_orig_xlib
+#define XRootWindowOfScreen XRootWindowOfScreen_dylibloader_orig_xlib
+#define XDefaultVisual XDefaultVisual_dylibloader_orig_xlib
+#define XDefaultVisualOfScreen XDefaultVisualOfScreen_dylibloader_orig_xlib
+#define XDefaultGC XDefaultGC_dylibloader_orig_xlib
+#define XDefaultGCOfScreen XDefaultGCOfScreen_dylibloader_orig_xlib
+#define XBlackPixel XBlackPixel_dylibloader_orig_xlib
+#define XWhitePixel XWhitePixel_dylibloader_orig_xlib
+#define XAllPlanes XAllPlanes_dylibloader_orig_xlib
+#define XBlackPixelOfScreen XBlackPixelOfScreen_dylibloader_orig_xlib
+#define XWhitePixelOfScreen XWhitePixelOfScreen_dylibloader_orig_xlib
+#define XNextRequest XNextRequest_dylibloader_orig_xlib
+#define XLastKnownRequestProcessed XLastKnownRequestProcessed_dylibloader_orig_xlib
+#define XServerVendor XServerVendor_dylibloader_orig_xlib
+#define XDisplayString XDisplayString_dylibloader_orig_xlib
+#define XDefaultColormap XDefaultColormap_dylibloader_orig_xlib
+#define XDefaultColormapOfScreen XDefaultColormapOfScreen_dylibloader_orig_xlib
+#define XDisplayOfScreen XDisplayOfScreen_dylibloader_orig_xlib
+#define XScreenOfDisplay XScreenOfDisplay_dylibloader_orig_xlib
+#define XDefaultScreenOfDisplay XDefaultScreenOfDisplay_dylibloader_orig_xlib
+#define XEventMaskOfScreen XEventMaskOfScreen_dylibloader_orig_xlib
+#define XScreenNumberOfScreen XScreenNumberOfScreen_dylibloader_orig_xlib
+#define XSetErrorHandler XSetErrorHandler_dylibloader_orig_xlib
+#define XSetIOErrorHandler XSetIOErrorHandler_dylibloader_orig_xlib
+#define XListPixmapFormats XListPixmapFormats_dylibloader_orig_xlib
+#define XListDepths XListDepths_dylibloader_orig_xlib
+#define XReconfigureWMWindow XReconfigureWMWindow_dylibloader_orig_xlib
+#define XGetWMProtocols XGetWMProtocols_dylibloader_orig_xlib
+#define XSetWMProtocols XSetWMProtocols_dylibloader_orig_xlib
+#define XIconifyWindow XIconifyWindow_dylibloader_orig_xlib
+#define XWithdrawWindow XWithdrawWindow_dylibloader_orig_xlib
+#define XGetCommand XGetCommand_dylibloader_orig_xlib
+#define XGetWMColormapWindows XGetWMColormapWindows_dylibloader_orig_xlib
+#define XSetWMColormapWindows XSetWMColormapWindows_dylibloader_orig_xlib
+#define XFreeStringList XFreeStringList_dylibloader_orig_xlib
+#define XSetTransientForHint XSetTransientForHint_dylibloader_orig_xlib
+#define XActivateScreenSaver XActivateScreenSaver_dylibloader_orig_xlib
+#define XAddHost XAddHost_dylibloader_orig_xlib
+#define XAddHosts XAddHosts_dylibloader_orig_xlib
+#define XAddToExtensionList XAddToExtensionList_dylibloader_orig_xlib
+#define XAddToSaveSet XAddToSaveSet_dylibloader_orig_xlib
+#define XAllocColor XAllocColor_dylibloader_orig_xlib
+#define XAllocColorCells XAllocColorCells_dylibloader_orig_xlib
+#define XAllocColorPlanes XAllocColorPlanes_dylibloader_orig_xlib
+#define XAllocNamedColor XAllocNamedColor_dylibloader_orig_xlib
+#define XAllowEvents XAllowEvents_dylibloader_orig_xlib
+#define XAutoRepeatOff XAutoRepeatOff_dylibloader_orig_xlib
+#define XAutoRepeatOn XAutoRepeatOn_dylibloader_orig_xlib
+#define XBell XBell_dylibloader_orig_xlib
+#define XBitmapBitOrder XBitmapBitOrder_dylibloader_orig_xlib
+#define XBitmapPad XBitmapPad_dylibloader_orig_xlib
+#define XBitmapUnit XBitmapUnit_dylibloader_orig_xlib
+#define XCellsOfScreen XCellsOfScreen_dylibloader_orig_xlib
+#define XChangeActivePointerGrab XChangeActivePointerGrab_dylibloader_orig_xlib
+#define XChangeGC XChangeGC_dylibloader_orig_xlib
+#define XChangeKeyboardControl XChangeKeyboardControl_dylibloader_orig_xlib
+#define XChangeKeyboardMapping XChangeKeyboardMapping_dylibloader_orig_xlib
+#define XChangePointerControl XChangePointerControl_dylibloader_orig_xlib
+#define XChangeProperty XChangeProperty_dylibloader_orig_xlib
+#define XChangeSaveSet XChangeSaveSet_dylibloader_orig_xlib
+#define XChangeWindowAttributes XChangeWindowAttributes_dylibloader_orig_xlib
+#define XCheckIfEvent XCheckIfEvent_dylibloader_orig_xlib
+#define XCheckMaskEvent XCheckMaskEvent_dylibloader_orig_xlib
+#define XCheckTypedEvent XCheckTypedEvent_dylibloader_orig_xlib
+#define XCheckTypedWindowEvent XCheckTypedWindowEvent_dylibloader_orig_xlib
+#define XCheckWindowEvent XCheckWindowEvent_dylibloader_orig_xlib
+#define XCirculateSubwindows XCirculateSubwindows_dylibloader_orig_xlib
+#define XCirculateSubwindowsDown XCirculateSubwindowsDown_dylibloader_orig_xlib
+#define XCirculateSubwindowsUp XCirculateSubwindowsUp_dylibloader_orig_xlib
+#define XClearArea XClearArea_dylibloader_orig_xlib
+#define XClearWindow XClearWindow_dylibloader_orig_xlib
+#define XCloseDisplay XCloseDisplay_dylibloader_orig_xlib
+#define XConfigureWindow XConfigureWindow_dylibloader_orig_xlib
+#define XConnectionNumber XConnectionNumber_dylibloader_orig_xlib
+#define XConvertSelection XConvertSelection_dylibloader_orig_xlib
+#define XCopyArea XCopyArea_dylibloader_orig_xlib
+#define XCopyGC XCopyGC_dylibloader_orig_xlib
+#define XCopyPlane XCopyPlane_dylibloader_orig_xlib
+#define XDefaultDepth XDefaultDepth_dylibloader_orig_xlib
+#define XDefaultDepthOfScreen XDefaultDepthOfScreen_dylibloader_orig_xlib
+#define XDefaultScreen XDefaultScreen_dylibloader_orig_xlib
+#define XDefineCursor XDefineCursor_dylibloader_orig_xlib
+#define XDeleteProperty XDeleteProperty_dylibloader_orig_xlib
+#define XDestroyWindow XDestroyWindow_dylibloader_orig_xlib
+#define XDestroySubwindows XDestroySubwindows_dylibloader_orig_xlib
+#define XDoesBackingStore XDoesBackingStore_dylibloader_orig_xlib
+#define XDoesSaveUnders XDoesSaveUnders_dylibloader_orig_xlib
+#define XDisableAccessControl XDisableAccessControl_dylibloader_orig_xlib
+#define XDisplayCells XDisplayCells_dylibloader_orig_xlib
+#define XDisplayHeight XDisplayHeight_dylibloader_orig_xlib
+#define XDisplayHeightMM XDisplayHeightMM_dylibloader_orig_xlib
+#define XDisplayKeycodes XDisplayKeycodes_dylibloader_orig_xlib
+#define XDisplayPlanes XDisplayPlanes_dylibloader_orig_xlib
+#define XDisplayWidth XDisplayWidth_dylibloader_orig_xlib
+#define XDisplayWidthMM XDisplayWidthMM_dylibloader_orig_xlib
+#define XDrawArc XDrawArc_dylibloader_orig_xlib
+#define XDrawArcs XDrawArcs_dylibloader_orig_xlib
+#define XDrawImageString XDrawImageString_dylibloader_orig_xlib
+#define XDrawImageString16 XDrawImageString16_dylibloader_orig_xlib
+#define XDrawLine XDrawLine_dylibloader_orig_xlib
+#define XDrawLines XDrawLines_dylibloader_orig_xlib
+#define XDrawPoint XDrawPoint_dylibloader_orig_xlib
+#define XDrawPoints XDrawPoints_dylibloader_orig_xlib
+#define XDrawRectangle XDrawRectangle_dylibloader_orig_xlib
+#define XDrawRectangles XDrawRectangles_dylibloader_orig_xlib
+#define XDrawSegments XDrawSegments_dylibloader_orig_xlib
+#define XDrawString XDrawString_dylibloader_orig_xlib
+#define XDrawString16 XDrawString16_dylibloader_orig_xlib
+#define XDrawText XDrawText_dylibloader_orig_xlib
+#define XDrawText16 XDrawText16_dylibloader_orig_xlib
+#define XEnableAccessControl XEnableAccessControl_dylibloader_orig_xlib
+#define XEventsQueued XEventsQueued_dylibloader_orig_xlib
+#define XFetchName XFetchName_dylibloader_orig_xlib
+#define XFillArc XFillArc_dylibloader_orig_xlib
+#define XFillArcs XFillArcs_dylibloader_orig_xlib
+#define XFillPolygon XFillPolygon_dylibloader_orig_xlib
+#define XFillRectangle XFillRectangle_dylibloader_orig_xlib
+#define XFillRectangles XFillRectangles_dylibloader_orig_xlib
+#define XFlush XFlush_dylibloader_orig_xlib
+#define XForceScreenSaver XForceScreenSaver_dylibloader_orig_xlib
+#define XFree XFree_dylibloader_orig_xlib
+#define XFreeColormap XFreeColormap_dylibloader_orig_xlib
+#define XFreeColors XFreeColors_dylibloader_orig_xlib
+#define XFreeCursor XFreeCursor_dylibloader_orig_xlib
+#define XFreeExtensionList XFreeExtensionList_dylibloader_orig_xlib
+#define XFreeFont XFreeFont_dylibloader_orig_xlib
+#define XFreeFontInfo XFreeFontInfo_dylibloader_orig_xlib
+#define XFreeFontNames XFreeFontNames_dylibloader_orig_xlib
+#define XFreeFontPath XFreeFontPath_dylibloader_orig_xlib
+#define XFreeGC XFreeGC_dylibloader_orig_xlib
+#define XFreeModifiermap XFreeModifiermap_dylibloader_orig_xlib
+#define XFreePixmap XFreePixmap_dylibloader_orig_xlib
+#define XGeometry XGeometry_dylibloader_orig_xlib
+#define XGetErrorDatabaseText XGetErrorDatabaseText_dylibloader_orig_xlib
+#define XGetErrorText XGetErrorText_dylibloader_orig_xlib
+#define XGetFontProperty XGetFontProperty_dylibloader_orig_xlib
+#define XGetGCValues XGetGCValues_dylibloader_orig_xlib
+#define XGetGeometry XGetGeometry_dylibloader_orig_xlib
+#define XGetIconName XGetIconName_dylibloader_orig_xlib
+#define XGetInputFocus XGetInputFocus_dylibloader_orig_xlib
+#define XGetKeyboardControl XGetKeyboardControl_dylibloader_orig_xlib
+#define XGetPointerControl XGetPointerControl_dylibloader_orig_xlib
+#define XGetPointerMapping XGetPointerMapping_dylibloader_orig_xlib
+#define XGetScreenSaver XGetScreenSaver_dylibloader_orig_xlib
+#define XGetTransientForHint XGetTransientForHint_dylibloader_orig_xlib
+#define XGetWindowProperty XGetWindowProperty_dylibloader_orig_xlib
+#define XGetWindowAttributes XGetWindowAttributes_dylibloader_orig_xlib
+#define XGrabButton XGrabButton_dylibloader_orig_xlib
+#define XGrabKey XGrabKey_dylibloader_orig_xlib
+#define XGrabKeyboard XGrabKeyboard_dylibloader_orig_xlib
+#define XGrabPointer XGrabPointer_dylibloader_orig_xlib
+#define XGrabServer XGrabServer_dylibloader_orig_xlib
+#define XHeightMMOfScreen XHeightMMOfScreen_dylibloader_orig_xlib
+#define XHeightOfScreen XHeightOfScreen_dylibloader_orig_xlib
+#define XIfEvent XIfEvent_dylibloader_orig_xlib
+#define XImageByteOrder XImageByteOrder_dylibloader_orig_xlib
+#define XInstallColormap XInstallColormap_dylibloader_orig_xlib
+#define XKeysymToKeycode XKeysymToKeycode_dylibloader_orig_xlib
+#define XKillClient XKillClient_dylibloader_orig_xlib
+#define XLookupColor XLookupColor_dylibloader_orig_xlib
+#define XLowerWindow XLowerWindow_dylibloader_orig_xlib
+#define XMapRaised XMapRaised_dylibloader_orig_xlib
+#define XMapSubwindows XMapSubwindows_dylibloader_orig_xlib
+#define XMapWindow XMapWindow_dylibloader_orig_xlib
+#define XMaskEvent XMaskEvent_dylibloader_orig_xlib
+#define XMaxCmapsOfScreen XMaxCmapsOfScreen_dylibloader_orig_xlib
+#define XMinCmapsOfScreen XMinCmapsOfScreen_dylibloader_orig_xlib
+#define XMoveResizeWindow XMoveResizeWindow_dylibloader_orig_xlib
+#define XMoveWindow XMoveWindow_dylibloader_orig_xlib
+#define XNextEvent XNextEvent_dylibloader_orig_xlib
+#define XNoOp XNoOp_dylibloader_orig_xlib
+#define XParseColor XParseColor_dylibloader_orig_xlib
+#define XParseGeometry XParseGeometry_dylibloader_orig_xlib
+#define XPeekEvent XPeekEvent_dylibloader_orig_xlib
+#define XPeekIfEvent XPeekIfEvent_dylibloader_orig_xlib
+#define XPending XPending_dylibloader_orig_xlib
+#define XPlanesOfScreen XPlanesOfScreen_dylibloader_orig_xlib
+#define XProtocolRevision XProtocolRevision_dylibloader_orig_xlib
+#define XProtocolVersion XProtocolVersion_dylibloader_orig_xlib
+#define XPutBackEvent XPutBackEvent_dylibloader_orig_xlib
+#define XPutImage XPutImage_dylibloader_orig_xlib
+#define XQLength XQLength_dylibloader_orig_xlib
+#define XQueryBestCursor XQueryBestCursor_dylibloader_orig_xlib
+#define XQueryBestSize XQueryBestSize_dylibloader_orig_xlib
+#define XQueryBestStipple XQueryBestStipple_dylibloader_orig_xlib
+#define XQueryBestTile XQueryBestTile_dylibloader_orig_xlib
+#define XQueryColor XQueryColor_dylibloader_orig_xlib
+#define XQueryColors XQueryColors_dylibloader_orig_xlib
+#define XQueryExtension XQueryExtension_dylibloader_orig_xlib
+#define XQueryKeymap XQueryKeymap_dylibloader_orig_xlib
+#define XQueryPointer XQueryPointer_dylibloader_orig_xlib
+#define XQueryTextExtents XQueryTextExtents_dylibloader_orig_xlib
+#define XQueryTextExtents16 XQueryTextExtents16_dylibloader_orig_xlib
+#define XQueryTree XQueryTree_dylibloader_orig_xlib
+#define XRaiseWindow XRaiseWindow_dylibloader_orig_xlib
+#define XReadBitmapFile XReadBitmapFile_dylibloader_orig_xlib
+#define XReadBitmapFileData XReadBitmapFileData_dylibloader_orig_xlib
+#define XRebindKeysym XRebindKeysym_dylibloader_orig_xlib
+#define XRecolorCursor XRecolorCursor_dylibloader_orig_xlib
+#define XRefreshKeyboardMapping XRefreshKeyboardMapping_dylibloader_orig_xlib
+#define XRemoveFromSaveSet XRemoveFromSaveSet_dylibloader_orig_xlib
+#define XRemoveHost XRemoveHost_dylibloader_orig_xlib
+#define XRemoveHosts XRemoveHosts_dylibloader_orig_xlib
+#define XReparentWindow XReparentWindow_dylibloader_orig_xlib
+#define XResetScreenSaver XResetScreenSaver_dylibloader_orig_xlib
+#define XResizeWindow XResizeWindow_dylibloader_orig_xlib
+#define XRestackWindows XRestackWindows_dylibloader_orig_xlib
+#define XRotateBuffers XRotateBuffers_dylibloader_orig_xlib
+#define XRotateWindowProperties XRotateWindowProperties_dylibloader_orig_xlib
+#define XScreenCount XScreenCount_dylibloader_orig_xlib
+#define XSelectInput XSelectInput_dylibloader_orig_xlib
+#define XSendEvent XSendEvent_dylibloader_orig_xlib
+#define XSetAccessControl XSetAccessControl_dylibloader_orig_xlib
+#define XSetArcMode XSetArcMode_dylibloader_orig_xlib
+#define XSetBackground XSetBackground_dylibloader_orig_xlib
+#define XSetClipMask XSetClipMask_dylibloader_orig_xlib
+#define XSetClipOrigin XSetClipOrigin_dylibloader_orig_xlib
+#define XSetClipRectangles XSetClipRectangles_dylibloader_orig_xlib
+#define XSetCloseDownMode XSetCloseDownMode_dylibloader_orig_xlib
+#define XSetCommand XSetCommand_dylibloader_orig_xlib
+#define XSetDashes XSetDashes_dylibloader_orig_xlib
+#define XSetFillRule XSetFillRule_dylibloader_orig_xlib
+#define XSetFillStyle XSetFillStyle_dylibloader_orig_xlib
+#define XSetFont XSetFont_dylibloader_orig_xlib
+#define XSetFontPath XSetFontPath_dylibloader_orig_xlib
+#define XSetForeground XSetForeground_dylibloader_orig_xlib
+#define XSetFunction XSetFunction_dylibloader_orig_xlib
+#define XSetGraphicsExposures XSetGraphicsExposures_dylibloader_orig_xlib
+#define XSetIconName XSetIconName_dylibloader_orig_xlib
+#define XSetInputFocus XSetInputFocus_dylibloader_orig_xlib
+#define XSetLineAttributes XSetLineAttributes_dylibloader_orig_xlib
+#define XSetModifierMapping XSetModifierMapping_dylibloader_orig_xlib
+#define XSetPlaneMask XSetPlaneMask_dylibloader_orig_xlib
+#define XSetPointerMapping XSetPointerMapping_dylibloader_orig_xlib
+#define XSetScreenSaver XSetScreenSaver_dylibloader_orig_xlib
+#define XSetSelectionOwner XSetSelectionOwner_dylibloader_orig_xlib
+#define XSetState XSetState_dylibloader_orig_xlib
+#define XSetStipple XSetStipple_dylibloader_orig_xlib
+#define XSetSubwindowMode XSetSubwindowMode_dylibloader_orig_xlib
+#define XSetTSOrigin XSetTSOrigin_dylibloader_orig_xlib
+#define XSetTile XSetTile_dylibloader_orig_xlib
+#define XSetWindowBackground XSetWindowBackground_dylibloader_orig_xlib
+#define XSetWindowBackgroundPixmap XSetWindowBackgroundPixmap_dylibloader_orig_xlib
+#define XSetWindowBorder XSetWindowBorder_dylibloader_orig_xlib
+#define XSetWindowBorderPixmap XSetWindowBorderPixmap_dylibloader_orig_xlib
+#define XSetWindowBorderWidth XSetWindowBorderWidth_dylibloader_orig_xlib
+#define XSetWindowColormap XSetWindowColormap_dylibloader_orig_xlib
+#define XStoreBuffer XStoreBuffer_dylibloader_orig_xlib
+#define XStoreBytes XStoreBytes_dylibloader_orig_xlib
+#define XStoreColor XStoreColor_dylibloader_orig_xlib
+#define XStoreColors XStoreColors_dylibloader_orig_xlib
+#define XStoreName XStoreName_dylibloader_orig_xlib
+#define XStoreNamedColor XStoreNamedColor_dylibloader_orig_xlib
+#define XSync XSync_dylibloader_orig_xlib
+#define XTextExtents XTextExtents_dylibloader_orig_xlib
+#define XTextExtents16 XTextExtents16_dylibloader_orig_xlib
+#define XTextWidth XTextWidth_dylibloader_orig_xlib
+#define XTextWidth16 XTextWidth16_dylibloader_orig_xlib
+#define XTranslateCoordinates XTranslateCoordinates_dylibloader_orig_xlib
+#define XUndefineCursor XUndefineCursor_dylibloader_orig_xlib
+#define XUngrabButton XUngrabButton_dylibloader_orig_xlib
+#define XUngrabKey XUngrabKey_dylibloader_orig_xlib
+#define XUngrabKeyboard XUngrabKeyboard_dylibloader_orig_xlib
+#define XUngrabPointer XUngrabPointer_dylibloader_orig_xlib
+#define XUngrabServer XUngrabServer_dylibloader_orig_xlib
+#define XUninstallColormap XUninstallColormap_dylibloader_orig_xlib
+#define XUnloadFont XUnloadFont_dylibloader_orig_xlib
+#define XUnmapSubwindows XUnmapSubwindows_dylibloader_orig_xlib
+#define XUnmapWindow XUnmapWindow_dylibloader_orig_xlib
+#define XVendorRelease XVendorRelease_dylibloader_orig_xlib
+#define XWarpPointer XWarpPointer_dylibloader_orig_xlib
+#define XWidthMMOfScreen XWidthMMOfScreen_dylibloader_orig_xlib
+#define XWidthOfScreen XWidthOfScreen_dylibloader_orig_xlib
+#define XWindowEvent XWindowEvent_dylibloader_orig_xlib
+#define XWriteBitmapFile XWriteBitmapFile_dylibloader_orig_xlib
+#define XSupportsLocale XSupportsLocale_dylibloader_orig_xlib
+#define XSetLocaleModifiers XSetLocaleModifiers_dylibloader_orig_xlib
+#define XOpenOM XOpenOM_dylibloader_orig_xlib
+#define XCloseOM XCloseOM_dylibloader_orig_xlib
+#define XSetOMValues XSetOMValues_dylibloader_orig_xlib
+#define XGetOMValues XGetOMValues_dylibloader_orig_xlib
+#define XDisplayOfOM XDisplayOfOM_dylibloader_orig_xlib
+#define XLocaleOfOM XLocaleOfOM_dylibloader_orig_xlib
+#define XCreateOC XCreateOC_dylibloader_orig_xlib
+#define XDestroyOC XDestroyOC_dylibloader_orig_xlib
+#define XOMOfOC XOMOfOC_dylibloader_orig_xlib
+#define XSetOCValues XSetOCValues_dylibloader_orig_xlib
+#define XGetOCValues XGetOCValues_dylibloader_orig_xlib
+#define XCreateFontSet XCreateFontSet_dylibloader_orig_xlib
+#define XFreeFontSet XFreeFontSet_dylibloader_orig_xlib
+#define XFontsOfFontSet XFontsOfFontSet_dylibloader_orig_xlib
+#define XBaseFontNameListOfFontSet XBaseFontNameListOfFontSet_dylibloader_orig_xlib
+#define XLocaleOfFontSet XLocaleOfFontSet_dylibloader_orig_xlib
+#define XContextDependentDrawing XContextDependentDrawing_dylibloader_orig_xlib
+#define XDirectionalDependentDrawing XDirectionalDependentDrawing_dylibloader_orig_xlib
+#define XContextualDrawing XContextualDrawing_dylibloader_orig_xlib
+#define XExtentsOfFontSet XExtentsOfFontSet_dylibloader_orig_xlib
+#define XmbTextEscapement XmbTextEscapement_dylibloader_orig_xlib
+#define XwcTextEscapement XwcTextEscapement_dylibloader_orig_xlib
+#define Xutf8TextEscapement Xutf8TextEscapement_dylibloader_orig_xlib
+#define XmbTextExtents XmbTextExtents_dylibloader_orig_xlib
+#define XwcTextExtents XwcTextExtents_dylibloader_orig_xlib
+#define Xutf8TextExtents Xutf8TextExtents_dylibloader_orig_xlib
+#define XmbTextPerCharExtents XmbTextPerCharExtents_dylibloader_orig_xlib
+#define XwcTextPerCharExtents XwcTextPerCharExtents_dylibloader_orig_xlib
+#define Xutf8TextPerCharExtents Xutf8TextPerCharExtents_dylibloader_orig_xlib
+#define XmbDrawText XmbDrawText_dylibloader_orig_xlib
+#define XwcDrawText XwcDrawText_dylibloader_orig_xlib
+#define Xutf8DrawText Xutf8DrawText_dylibloader_orig_xlib
+#define XmbDrawString XmbDrawString_dylibloader_orig_xlib
+#define XwcDrawString XwcDrawString_dylibloader_orig_xlib
+#define Xutf8DrawString Xutf8DrawString_dylibloader_orig_xlib
+#define XmbDrawImageString XmbDrawImageString_dylibloader_orig_xlib
+#define XwcDrawImageString XwcDrawImageString_dylibloader_orig_xlib
+#define Xutf8DrawImageString Xutf8DrawImageString_dylibloader_orig_xlib
+#define XOpenIM XOpenIM_dylibloader_orig_xlib
+#define XCloseIM XCloseIM_dylibloader_orig_xlib
+#define XGetIMValues XGetIMValues_dylibloader_orig_xlib
+#define XSetIMValues XSetIMValues_dylibloader_orig_xlib
+#define XDisplayOfIM XDisplayOfIM_dylibloader_orig_xlib
+#define XLocaleOfIM XLocaleOfIM_dylibloader_orig_xlib
+#define XCreateIC XCreateIC_dylibloader_orig_xlib
+#define XDestroyIC XDestroyIC_dylibloader_orig_xlib
+#define XSetICFocus XSetICFocus_dylibloader_orig_xlib
+#define XUnsetICFocus XUnsetICFocus_dylibloader_orig_xlib
+#define XwcResetIC XwcResetIC_dylibloader_orig_xlib
+#define XmbResetIC XmbResetIC_dylibloader_orig_xlib
+#define Xutf8ResetIC Xutf8ResetIC_dylibloader_orig_xlib
+#define XSetICValues XSetICValues_dylibloader_orig_xlib
+#define XGetICValues XGetICValues_dylibloader_orig_xlib
+#define XIMOfIC XIMOfIC_dylibloader_orig_xlib
+#define XFilterEvent XFilterEvent_dylibloader_orig_xlib
+#define XmbLookupString XmbLookupString_dylibloader_orig_xlib
+#define XwcLookupString XwcLookupString_dylibloader_orig_xlib
+#define Xutf8LookupString Xutf8LookupString_dylibloader_orig_xlib
+#define XVaCreateNestedList XVaCreateNestedList_dylibloader_orig_xlib
+#define XRegisterIMInstantiateCallback XRegisterIMInstantiateCallback_dylibloader_orig_xlib
+#define XUnregisterIMInstantiateCallback XUnregisterIMInstantiateCallback_dylibloader_orig_xlib
+#define XInternalConnectionNumbers XInternalConnectionNumbers_dylibloader_orig_xlib
+#define XProcessInternalConnection XProcessInternalConnection_dylibloader_orig_xlib
+#define XAddConnectionWatch XAddConnectionWatch_dylibloader_orig_xlib
+#define XRemoveConnectionWatch XRemoveConnectionWatch_dylibloader_orig_xlib
+#define XSetAuthorization XSetAuthorization_dylibloader_orig_xlib
+#define _Xmbtowc _Xmbtowc_dylibloader_orig_xlib
+#define _Xwctomb _Xwctomb_dylibloader_orig_xlib
+#define XGetEventData XGetEventData_dylibloader_orig_xlib
+#define XFreeEventData XFreeEventData_dylibloader_orig_xlib
+#define XAllocClassHint XAllocClassHint_dylibloader_orig_xlib
+#define XAllocIconSize XAllocIconSize_dylibloader_orig_xlib
+#define XAllocSizeHints XAllocSizeHints_dylibloader_orig_xlib
+#define XAllocStandardColormap XAllocStandardColormap_dylibloader_orig_xlib
+#define XAllocWMHints XAllocWMHints_dylibloader_orig_xlib
+#define XClipBox XClipBox_dylibloader_orig_xlib
+#define XCreateRegion XCreateRegion_dylibloader_orig_xlib
+#define XDefaultString XDefaultString_dylibloader_orig_xlib
+#define XDeleteContext XDeleteContext_dylibloader_orig_xlib
+#define XDestroyRegion XDestroyRegion_dylibloader_orig_xlib
+#define XEmptyRegion XEmptyRegion_dylibloader_orig_xlib
+#define XEqualRegion XEqualRegion_dylibloader_orig_xlib
+#define XFindContext XFindContext_dylibloader_orig_xlib
+#define XGetClassHint XGetClassHint_dylibloader_orig_xlib
+#define XGetIconSizes XGetIconSizes_dylibloader_orig_xlib
+#define XGetNormalHints XGetNormalHints_dylibloader_orig_xlib
+#define XGetRGBColormaps XGetRGBColormaps_dylibloader_orig_xlib
+#define XGetSizeHints XGetSizeHints_dylibloader_orig_xlib
+#define XGetStandardColormap XGetStandardColormap_dylibloader_orig_xlib
+#define XGetTextProperty XGetTextProperty_dylibloader_orig_xlib
+#define XGetVisualInfo XGetVisualInfo_dylibloader_orig_xlib
+#define XGetWMClientMachine XGetWMClientMachine_dylibloader_orig_xlib
+#define XGetWMHints XGetWMHints_dylibloader_orig_xlib
+#define XGetWMIconName XGetWMIconName_dylibloader_orig_xlib
+#define XGetWMName XGetWMName_dylibloader_orig_xlib
+#define XGetWMNormalHints XGetWMNormalHints_dylibloader_orig_xlib
+#define XGetWMSizeHints XGetWMSizeHints_dylibloader_orig_xlib
+#define XGetZoomHints XGetZoomHints_dylibloader_orig_xlib
+#define XIntersectRegion XIntersectRegion_dylibloader_orig_xlib
+#define XConvertCase XConvertCase_dylibloader_orig_xlib
+#define XLookupString XLookupString_dylibloader_orig_xlib
+#define XMatchVisualInfo XMatchVisualInfo_dylibloader_orig_xlib
+#define XOffsetRegion XOffsetRegion_dylibloader_orig_xlib
+#define XPointInRegion XPointInRegion_dylibloader_orig_xlib
+#define XPolygonRegion XPolygonRegion_dylibloader_orig_xlib
+#define XRectInRegion XRectInRegion_dylibloader_orig_xlib
+#define XSaveContext XSaveContext_dylibloader_orig_xlib
+#define XSetClassHint XSetClassHint_dylibloader_orig_xlib
+#define XSetIconSizes XSetIconSizes_dylibloader_orig_xlib
+#define XSetNormalHints XSetNormalHints_dylibloader_orig_xlib
+#define XSetRGBColormaps XSetRGBColormaps_dylibloader_orig_xlib
+#define XSetSizeHints XSetSizeHints_dylibloader_orig_xlib
+#define XSetStandardProperties XSetStandardProperties_dylibloader_orig_xlib
+#define XSetTextProperty XSetTextProperty_dylibloader_orig_xlib
+#define XSetWMClientMachine XSetWMClientMachine_dylibloader_orig_xlib
+#define XSetWMHints XSetWMHints_dylibloader_orig_xlib
+#define XSetWMIconName XSetWMIconName_dylibloader_orig_xlib
+#define XSetWMName XSetWMName_dylibloader_orig_xlib
+#define XSetWMNormalHints XSetWMNormalHints_dylibloader_orig_xlib
+#define XSetWMProperties XSetWMProperties_dylibloader_orig_xlib
+#define XmbSetWMProperties XmbSetWMProperties_dylibloader_orig_xlib
+#define Xutf8SetWMProperties Xutf8SetWMProperties_dylibloader_orig_xlib
+#define XSetWMSizeHints XSetWMSizeHints_dylibloader_orig_xlib
+#define XSetRegion XSetRegion_dylibloader_orig_xlib
+#define XSetStandardColormap XSetStandardColormap_dylibloader_orig_xlib
+#define XSetZoomHints XSetZoomHints_dylibloader_orig_xlib
+#define XShrinkRegion XShrinkRegion_dylibloader_orig_xlib
+#define XStringListToTextProperty XStringListToTextProperty_dylibloader_orig_xlib
+#define XSubtractRegion XSubtractRegion_dylibloader_orig_xlib
+#define XmbTextListToTextProperty XmbTextListToTextProperty_dylibloader_orig_xlib
+#define XwcTextListToTextProperty XwcTextListToTextProperty_dylibloader_orig_xlib
+#define Xutf8TextListToTextProperty Xutf8TextListToTextProperty_dylibloader_orig_xlib
+#define XwcFreeStringList XwcFreeStringList_dylibloader_orig_xlib
+#define XTextPropertyToStringList XTextPropertyToStringList_dylibloader_orig_xlib
+#define XmbTextPropertyToTextList XmbTextPropertyToTextList_dylibloader_orig_xlib
+#define XwcTextPropertyToTextList XwcTextPropertyToTextList_dylibloader_orig_xlib
+#define Xutf8TextPropertyToTextList Xutf8TextPropertyToTextList_dylibloader_orig_xlib
+#define XUnionRectWithRegion XUnionRectWithRegion_dylibloader_orig_xlib
+#define XUnionRegion XUnionRegion_dylibloader_orig_xlib
+#define XWMGeometry XWMGeometry_dylibloader_orig_xlib
+#define XXorRegion XXorRegion_dylibloader_orig_xlib
+#define XkbIgnoreExtension XkbIgnoreExtension_dylibloader_orig_xlib
+#define XkbOpenDisplay XkbOpenDisplay_dylibloader_orig_xlib
+#define XkbQueryExtension XkbQueryExtension_dylibloader_orig_xlib
+#define XkbUseExtension XkbUseExtension_dylibloader_orig_xlib
+#define XkbLibraryVersion XkbLibraryVersion_dylibloader_orig_xlib
+#define XkbSetXlibControls XkbSetXlibControls_dylibloader_orig_xlib
+#define XkbGetXlibControls XkbGetXlibControls_dylibloader_orig_xlib
+#define XkbXlibControlsImplemented XkbXlibControlsImplemented_dylibloader_orig_xlib
+#define XkbSetAtomFuncs XkbSetAtomFuncs_dylibloader_orig_xlib
+#define XkbKeycodeToKeysym XkbKeycodeToKeysym_dylibloader_orig_xlib
+#define XkbKeysymToModifiers XkbKeysymToModifiers_dylibloader_orig_xlib
+#define XkbLookupKeySym XkbLookupKeySym_dylibloader_orig_xlib
+#define XkbLookupKeyBinding XkbLookupKeyBinding_dylibloader_orig_xlib
+#define XkbTranslateKeyCode XkbTranslateKeyCode_dylibloader_orig_xlib
+#define XkbTranslateKeySym XkbTranslateKeySym_dylibloader_orig_xlib
+#define XkbSetAutoRepeatRate XkbSetAutoRepeatRate_dylibloader_orig_xlib
+#define XkbGetAutoRepeatRate XkbGetAutoRepeatRate_dylibloader_orig_xlib
+#define XkbChangeEnabledControls XkbChangeEnabledControls_dylibloader_orig_xlib
+#define XkbDeviceBell XkbDeviceBell_dylibloader_orig_xlib
+#define XkbForceDeviceBell XkbForceDeviceBell_dylibloader_orig_xlib
+#define XkbDeviceBellEvent XkbDeviceBellEvent_dylibloader_orig_xlib
+#define XkbBell XkbBell_dylibloader_orig_xlib
+#define XkbForceBell XkbForceBell_dylibloader_orig_xlib
+#define XkbBellEvent XkbBellEvent_dylibloader_orig_xlib
+#define XkbSelectEvents XkbSelectEvents_dylibloader_orig_xlib
+#define XkbSelectEventDetails XkbSelectEventDetails_dylibloader_orig_xlib
+#define XkbNoteMapChanges XkbNoteMapChanges_dylibloader_orig_xlib
+#define XkbNoteNameChanges XkbNoteNameChanges_dylibloader_orig_xlib
+#define XkbGetIndicatorState XkbGetIndicatorState_dylibloader_orig_xlib
+#define XkbGetIndicatorMap XkbGetIndicatorMap_dylibloader_orig_xlib
+#define XkbSetIndicatorMap XkbSetIndicatorMap_dylibloader_orig_xlib
+#define XkbGetNamedIndicator XkbGetNamedIndicator_dylibloader_orig_xlib
+#define XkbGetNamedDeviceIndicator XkbGetNamedDeviceIndicator_dylibloader_orig_xlib
+#define XkbSetNamedIndicator XkbSetNamedIndicator_dylibloader_orig_xlib
+#define XkbSetNamedDeviceIndicator XkbSetNamedDeviceIndicator_dylibloader_orig_xlib
+#define XkbLockModifiers XkbLockModifiers_dylibloader_orig_xlib
+#define XkbLatchModifiers XkbLatchModifiers_dylibloader_orig_xlib
+#define XkbLockGroup XkbLockGroup_dylibloader_orig_xlib
+#define XkbLatchGroup XkbLatchGroup_dylibloader_orig_xlib
+#define XkbSetServerInternalMods XkbSetServerInternalMods_dylibloader_orig_xlib
+#define XkbSetIgnoreLockMods XkbSetIgnoreLockMods_dylibloader_orig_xlib
+#define XkbVirtualModsToReal XkbVirtualModsToReal_dylibloader_orig_xlib
+#define XkbComputeEffectiveMap XkbComputeEffectiveMap_dylibloader_orig_xlib
+#define XkbInitCanonicalKeyTypes XkbInitCanonicalKeyTypes_dylibloader_orig_xlib
+#define XkbAllocKeyboard XkbAllocKeyboard_dylibloader_orig_xlib
+#define XkbFreeKeyboard XkbFreeKeyboard_dylibloader_orig_xlib
+#define XkbAllocClientMap XkbAllocClientMap_dylibloader_orig_xlib
+#define XkbAllocServerMap XkbAllocServerMap_dylibloader_orig_xlib
+#define XkbFreeClientMap XkbFreeClientMap_dylibloader_orig_xlib
+#define XkbFreeServerMap XkbFreeServerMap_dylibloader_orig_xlib
+#define XkbAddKeyType XkbAddKeyType_dylibloader_orig_xlib
+#define XkbAllocIndicatorMaps XkbAllocIndicatorMaps_dylibloader_orig_xlib
+#define XkbFreeIndicatorMaps XkbFreeIndicatorMaps_dylibloader_orig_xlib
+#define XkbGetMap XkbGetMap_dylibloader_orig_xlib
+#define XkbGetUpdatedMap XkbGetUpdatedMap_dylibloader_orig_xlib
+#define XkbGetMapChanges XkbGetMapChanges_dylibloader_orig_xlib
+#define XkbRefreshKeyboardMapping XkbRefreshKeyboardMapping_dylibloader_orig_xlib
+#define XkbGetKeyTypes XkbGetKeyTypes_dylibloader_orig_xlib
+#define XkbGetKeySyms XkbGetKeySyms_dylibloader_orig_xlib
+#define XkbGetKeyActions XkbGetKeyActions_dylibloader_orig_xlib
+#define XkbGetKeyBehaviors XkbGetKeyBehaviors_dylibloader_orig_xlib
+#define XkbGetVirtualMods XkbGetVirtualMods_dylibloader_orig_xlib
+#define XkbGetKeyExplicitComponents XkbGetKeyExplicitComponents_dylibloader_orig_xlib
+#define XkbGetKeyModifierMap XkbGetKeyModifierMap_dylibloader_orig_xlib
+#define XkbGetKeyVirtualModMap XkbGetKeyVirtualModMap_dylibloader_orig_xlib
+#define XkbAllocControls XkbAllocControls_dylibloader_orig_xlib
+#define XkbFreeControls XkbFreeControls_dylibloader_orig_xlib
+#define XkbGetControls XkbGetControls_dylibloader_orig_xlib
+#define XkbSetControls XkbSetControls_dylibloader_orig_xlib
+#define XkbNoteControlsChanges XkbNoteControlsChanges_dylibloader_orig_xlib
+#define XkbAllocCompatMap XkbAllocCompatMap_dylibloader_orig_xlib
+#define XkbFreeCompatMap XkbFreeCompatMap_dylibloader_orig_xlib
+#define XkbGetCompatMap XkbGetCompatMap_dylibloader_orig_xlib
+#define XkbSetCompatMap XkbSetCompatMap_dylibloader_orig_xlib
+#define XkbAllocNames XkbAllocNames_dylibloader_orig_xlib
+#define XkbGetNames XkbGetNames_dylibloader_orig_xlib
+#define XkbSetNames XkbSetNames_dylibloader_orig_xlib
+#define XkbChangeNames XkbChangeNames_dylibloader_orig_xlib
+#define XkbFreeNames XkbFreeNames_dylibloader_orig_xlib
+#define XkbGetState XkbGetState_dylibloader_orig_xlib
+#define XkbSetMap XkbSetMap_dylibloader_orig_xlib
+#define XkbChangeMap XkbChangeMap_dylibloader_orig_xlib
+#define XkbSetDetectableAutoRepeat XkbSetDetectableAutoRepeat_dylibloader_orig_xlib
+#define XkbGetDetectableAutoRepeat XkbGetDetectableAutoRepeat_dylibloader_orig_xlib
+#define XkbSetAutoResetControls XkbSetAutoResetControls_dylibloader_orig_xlib
+#define XkbGetAutoResetControls XkbGetAutoResetControls_dylibloader_orig_xlib
+#define XkbSetPerClientControls XkbSetPerClientControls_dylibloader_orig_xlib
+#define XkbGetPerClientControls XkbGetPerClientControls_dylibloader_orig_xlib
+#define XkbCopyKeyType XkbCopyKeyType_dylibloader_orig_xlib
+#define XkbCopyKeyTypes XkbCopyKeyTypes_dylibloader_orig_xlib
+#define XkbResizeKeyType XkbResizeKeyType_dylibloader_orig_xlib
+#define XkbResizeKeySyms XkbResizeKeySyms_dylibloader_orig_xlib
+#define XkbResizeKeyActions XkbResizeKeyActions_dylibloader_orig_xlib
+#define XkbChangeTypesOfKey XkbChangeTypesOfKey_dylibloader_orig_xlib
+#define XkbChangeKeycodeRange XkbChangeKeycodeRange_dylibloader_orig_xlib
+#define XkbListComponents XkbListComponents_dylibloader_orig_xlib
+#define XkbFreeComponentList XkbFreeComponentList_dylibloader_orig_xlib
+#define XkbGetKeyboard XkbGetKeyboard_dylibloader_orig_xlib
+#define XkbGetKeyboardByName XkbGetKeyboardByName_dylibloader_orig_xlib
+#define XkbKeyTypesForCoreSymbols XkbKeyTypesForCoreSymbols_dylibloader_orig_xlib
+#define XkbApplyCompatMapToKey XkbApplyCompatMapToKey_dylibloader_orig_xlib
+#define XkbUpdateMapFromCore XkbUpdateMapFromCore_dylibloader_orig_xlib
+#define XkbAddDeviceLedInfo XkbAddDeviceLedInfo_dylibloader_orig_xlib
+#define XkbResizeDeviceButtonActions XkbResizeDeviceButtonActions_dylibloader_orig_xlib
+#define XkbAllocDeviceInfo XkbAllocDeviceInfo_dylibloader_orig_xlib
+#define XkbFreeDeviceInfo XkbFreeDeviceInfo_dylibloader_orig_xlib
+#define XkbNoteDeviceChanges XkbNoteDeviceChanges_dylibloader_orig_xlib
+#define XkbGetDeviceInfo XkbGetDeviceInfo_dylibloader_orig_xlib
+#define XkbGetDeviceInfoChanges XkbGetDeviceInfoChanges_dylibloader_orig_xlib
+#define XkbGetDeviceButtonActions XkbGetDeviceButtonActions_dylibloader_orig_xlib
+#define XkbGetDeviceLedInfo XkbGetDeviceLedInfo_dylibloader_orig_xlib
+#define XkbSetDeviceInfo XkbSetDeviceInfo_dylibloader_orig_xlib
+#define XkbChangeDeviceInfo XkbChangeDeviceInfo_dylibloader_orig_xlib
+#define XkbSetDeviceLedInfo XkbSetDeviceLedInfo_dylibloader_orig_xlib
+#define XkbSetDeviceButtonActions XkbSetDeviceButtonActions_dylibloader_orig_xlib
+#define XkbToControl XkbToControl_dylibloader_orig_xlib
+#define XkbSetDebuggingFlags XkbSetDebuggingFlags_dylibloader_orig_xlib
+#define XkbApplyVirtualModChanges XkbApplyVirtualModChanges_dylibloader_orig_xlib
+#define XkbUpdateActionVirtualMods XkbUpdateActionVirtualMods_dylibloader_orig_xlib
+#define XkbUpdateKeyTypeVirtualMods XkbUpdateKeyTypeVirtualMods_dylibloader_orig_xlib
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/XKBlib.h>
+#undef _Xmblen
+#undef XLoadQueryFont
+#undef XQueryFont
+#undef XGetMotionEvents
+#undef XDeleteModifiermapEntry
+#undef XGetModifierMapping
+#undef XInsertModifiermapEntry
+#undef XNewModifiermap
+#undef XCreateImage
+#undef XInitImage
+#undef XGetImage
+#undef XGetSubImage
+#undef XOpenDisplay
+#undef XrmInitialize
+#undef XFetchBytes
+#undef XFetchBuffer
+#undef XGetAtomName
+#undef XGetAtomNames
+#undef XGetDefault
+#undef XDisplayName
+#undef XKeysymToString
+#undef XSynchronize
+#undef XSetAfterFunction
+#undef XInternAtom
+#undef XInternAtoms
+#undef XCopyColormapAndFree
+#undef XCreateColormap
+#undef XCreatePixmapCursor
+#undef XCreateGlyphCursor
+#undef XCreateFontCursor
+#undef XLoadFont
+#undef XCreateGC
+#undef XGContextFromGC
+#undef XFlushGC
+#undef XCreatePixmap
+#undef XCreateBitmapFromData
+#undef XCreatePixmapFromBitmapData
+#undef XCreateSimpleWindow
+#undef XGetSelectionOwner
+#undef XCreateWindow
+#undef XListInstalledColormaps
+#undef XListFonts
+#undef XListFontsWithInfo
+#undef XGetFontPath
+#undef XListExtensions
+#undef XListProperties
+#undef XListHosts
+#undef XKeycodeToKeysym
+#undef XLookupKeysym
+#undef XGetKeyboardMapping
+#undef XStringToKeysym
+#undef XMaxRequestSize
+#undef XExtendedMaxRequestSize
+#undef XResourceManagerString
+#undef XScreenResourceString
+#undef XDisplayMotionBufferSize
+#undef XVisualIDFromVisual
+#undef XInitThreads
+#undef XLockDisplay
+#undef XUnlockDisplay
+#undef XInitExtension
+#undef XAddExtension
+#undef XFindOnExtensionList
+#undef XEHeadOfExtensionList
+#undef XRootWindow
+#undef XDefaultRootWindow
+#undef XRootWindowOfScreen
+#undef XDefaultVisual
+#undef XDefaultVisualOfScreen
+#undef XDefaultGC
+#undef XDefaultGCOfScreen
+#undef XBlackPixel
+#undef XWhitePixel
+#undef XAllPlanes
+#undef XBlackPixelOfScreen
+#undef XWhitePixelOfScreen
+#undef XNextRequest
+#undef XLastKnownRequestProcessed
+#undef XServerVendor
+#undef XDisplayString
+#undef XDefaultColormap
+#undef XDefaultColormapOfScreen
+#undef XDisplayOfScreen
+#undef XScreenOfDisplay
+#undef XDefaultScreenOfDisplay
+#undef XEventMaskOfScreen
+#undef XScreenNumberOfScreen
+#undef XSetErrorHandler
+#undef XSetIOErrorHandler
+#undef XListPixmapFormats
+#undef XListDepths
+#undef XReconfigureWMWindow
+#undef XGetWMProtocols
+#undef XSetWMProtocols
+#undef XIconifyWindow
+#undef XWithdrawWindow
+#undef XGetCommand
+#undef XGetWMColormapWindows
+#undef XSetWMColormapWindows
+#undef XFreeStringList
+#undef XSetTransientForHint
+#undef XActivateScreenSaver
+#undef XAddHost
+#undef XAddHosts
+#undef XAddToExtensionList
+#undef XAddToSaveSet
+#undef XAllocColor
+#undef XAllocColorCells
+#undef XAllocColorPlanes
+#undef XAllocNamedColor
+#undef XAllowEvents
+#undef XAutoRepeatOff
+#undef XAutoRepeatOn
+#undef XBell
+#undef XBitmapBitOrder
+#undef XBitmapPad
+#undef XBitmapUnit
+#undef XCellsOfScreen
+#undef XChangeActivePointerGrab
+#undef XChangeGC
+#undef XChangeKeyboardControl
+#undef XChangeKeyboardMapping
+#undef XChangePointerControl
+#undef XChangeProperty
+#undef XChangeSaveSet
+#undef XChangeWindowAttributes
+#undef XCheckIfEvent
+#undef XCheckMaskEvent
+#undef XCheckTypedEvent
+#undef XCheckTypedWindowEvent
+#undef XCheckWindowEvent
+#undef XCirculateSubwindows
+#undef XCirculateSubwindowsDown
+#undef XCirculateSubwindowsUp
+#undef XClearArea
+#undef XClearWindow
+#undef XCloseDisplay
+#undef XConfigureWindow
+#undef XConnectionNumber
+#undef XConvertSelection
+#undef XCopyArea
+#undef XCopyGC
+#undef XCopyPlane
+#undef XDefaultDepth
+#undef XDefaultDepthOfScreen
+#undef XDefaultScreen
+#undef XDefineCursor
+#undef XDeleteProperty
+#undef XDestroyWindow
+#undef XDestroySubwindows
+#undef XDoesBackingStore
+#undef XDoesSaveUnders
+#undef XDisableAccessControl
+#undef XDisplayCells
+#undef XDisplayHeight
+#undef XDisplayHeightMM
+#undef XDisplayKeycodes
+#undef XDisplayPlanes
+#undef XDisplayWidth
+#undef XDisplayWidthMM
+#undef XDrawArc
+#undef XDrawArcs
+#undef XDrawImageString
+#undef XDrawImageString16
+#undef XDrawLine
+#undef XDrawLines
+#undef XDrawPoint
+#undef XDrawPoints
+#undef XDrawRectangle
+#undef XDrawRectangles
+#undef XDrawSegments
+#undef XDrawString
+#undef XDrawString16
+#undef XDrawText
+#undef XDrawText16
+#undef XEnableAccessControl
+#undef XEventsQueued
+#undef XFetchName
+#undef XFillArc
+#undef XFillArcs
+#undef XFillPolygon
+#undef XFillRectangle
+#undef XFillRectangles
+#undef XFlush
+#undef XForceScreenSaver
+#undef XFree
+#undef XFreeColormap
+#undef XFreeColors
+#undef XFreeCursor
+#undef XFreeExtensionList
+#undef XFreeFont
+#undef XFreeFontInfo
+#undef XFreeFontNames
+#undef XFreeFontPath
+#undef XFreeGC
+#undef XFreeModifiermap
+#undef XFreePixmap
+#undef XGeometry
+#undef XGetErrorDatabaseText
+#undef XGetErrorText
+#undef XGetFontProperty
+#undef XGetGCValues
+#undef XGetGeometry
+#undef XGetIconName
+#undef XGetInputFocus
+#undef XGetKeyboardControl
+#undef XGetPointerControl
+#undef XGetPointerMapping
+#undef XGetScreenSaver
+#undef XGetTransientForHint
+#undef XGetWindowProperty
+#undef XGetWindowAttributes
+#undef XGrabButton
+#undef XGrabKey
+#undef XGrabKeyboard
+#undef XGrabPointer
+#undef XGrabServer
+#undef XHeightMMOfScreen
+#undef XHeightOfScreen
+#undef XIfEvent
+#undef XImageByteOrder
+#undef XInstallColormap
+#undef XKeysymToKeycode
+#undef XKillClient
+#undef XLookupColor
+#undef XLowerWindow
+#undef XMapRaised
+#undef XMapSubwindows
+#undef XMapWindow
+#undef XMaskEvent
+#undef XMaxCmapsOfScreen
+#undef XMinCmapsOfScreen
+#undef XMoveResizeWindow
+#undef XMoveWindow
+#undef XNextEvent
+#undef XNoOp
+#undef XParseColor
+#undef XParseGeometry
+#undef XPeekEvent
+#undef XPeekIfEvent
+#undef XPending
+#undef XPlanesOfScreen
+#undef XProtocolRevision
+#undef XProtocolVersion
+#undef XPutBackEvent
+#undef XPutImage
+#undef XQLength
+#undef XQueryBestCursor
+#undef XQueryBestSize
+#undef XQueryBestStipple
+#undef XQueryBestTile
+#undef XQueryColor
+#undef XQueryColors
+#undef XQueryExtension
+#undef XQueryKeymap
+#undef XQueryPointer
+#undef XQueryTextExtents
+#undef XQueryTextExtents16
+#undef XQueryTree
+#undef XRaiseWindow
+#undef XReadBitmapFile
+#undef XReadBitmapFileData
+#undef XRebindKeysym
+#undef XRecolorCursor
+#undef XRefreshKeyboardMapping
+#undef XRemoveFromSaveSet
+#undef XRemoveHost
+#undef XRemoveHosts
+#undef XReparentWindow
+#undef XResetScreenSaver
+#undef XResizeWindow
+#undef XRestackWindows
+#undef XRotateBuffers
+#undef XRotateWindowProperties
+#undef XScreenCount
+#undef XSelectInput
+#undef XSendEvent
+#undef XSetAccessControl
+#undef XSetArcMode
+#undef XSetBackground
+#undef XSetClipMask
+#undef XSetClipOrigin
+#undef XSetClipRectangles
+#undef XSetCloseDownMode
+#undef XSetCommand
+#undef XSetDashes
+#undef XSetFillRule
+#undef XSetFillStyle
+#undef XSetFont
+#undef XSetFontPath
+#undef XSetForeground
+#undef XSetFunction
+#undef XSetGraphicsExposures
+#undef XSetIconName
+#undef XSetInputFocus
+#undef XSetLineAttributes
+#undef XSetModifierMapping
+#undef XSetPlaneMask
+#undef XSetPointerMapping
+#undef XSetScreenSaver
+#undef XSetSelectionOwner
+#undef XSetState
+#undef XSetStipple
+#undef XSetSubwindowMode
+#undef XSetTSOrigin
+#undef XSetTile
+#undef XSetWindowBackground
+#undef XSetWindowBackgroundPixmap
+#undef XSetWindowBorder
+#undef XSetWindowBorderPixmap
+#undef XSetWindowBorderWidth
+#undef XSetWindowColormap
+#undef XStoreBuffer
+#undef XStoreBytes
+#undef XStoreColor
+#undef XStoreColors
+#undef XStoreName
+#undef XStoreNamedColor
+#undef XSync
+#undef XTextExtents
+#undef XTextExtents16
+#undef XTextWidth
+#undef XTextWidth16
+#undef XTranslateCoordinates
+#undef XUndefineCursor
+#undef XUngrabButton
+#undef XUngrabKey
+#undef XUngrabKeyboard
+#undef XUngrabPointer
+#undef XUngrabServer
+#undef XUninstallColormap
+#undef XUnloadFont
+#undef XUnmapSubwindows
+#undef XUnmapWindow
+#undef XVendorRelease
+#undef XWarpPointer
+#undef XWidthMMOfScreen
+#undef XWidthOfScreen
+#undef XWindowEvent
+#undef XWriteBitmapFile
+#undef XSupportsLocale
+#undef XSetLocaleModifiers
+#undef XOpenOM
+#undef XCloseOM
+#undef XSetOMValues
+#undef XGetOMValues
+#undef XDisplayOfOM
+#undef XLocaleOfOM
+#undef XCreateOC
+#undef XDestroyOC
+#undef XOMOfOC
+#undef XSetOCValues
+#undef XGetOCValues
+#undef XCreateFontSet
+#undef XFreeFontSet
+#undef XFontsOfFontSet
+#undef XBaseFontNameListOfFontSet
+#undef XLocaleOfFontSet
+#undef XContextDependentDrawing
+#undef XDirectionalDependentDrawing
+#undef XContextualDrawing
+#undef XExtentsOfFontSet
+#undef XmbTextEscapement
+#undef XwcTextEscapement
+#undef Xutf8TextEscapement
+#undef XmbTextExtents
+#undef XwcTextExtents
+#undef Xutf8TextExtents
+#undef XmbTextPerCharExtents
+#undef XwcTextPerCharExtents
+#undef Xutf8TextPerCharExtents
+#undef XmbDrawText
+#undef XwcDrawText
+#undef Xutf8DrawText
+#undef XmbDrawString
+#undef XwcDrawString
+#undef Xutf8DrawString
+#undef XmbDrawImageString
+#undef XwcDrawImageString
+#undef Xutf8DrawImageString
+#undef XOpenIM
+#undef XCloseIM
+#undef XGetIMValues
+#undef XSetIMValues
+#undef XDisplayOfIM
+#undef XLocaleOfIM
+#undef XCreateIC
+#undef XDestroyIC
+#undef XSetICFocus
+#undef XUnsetICFocus
+#undef XwcResetIC
+#undef XmbResetIC
+#undef Xutf8ResetIC
+#undef XSetICValues
+#undef XGetICValues
+#undef XIMOfIC
+#undef XFilterEvent
+#undef XmbLookupString
+#undef XwcLookupString
+#undef Xutf8LookupString
+#undef XVaCreateNestedList
+#undef XRegisterIMInstantiateCallback
+#undef XUnregisterIMInstantiateCallback
+#undef XInternalConnectionNumbers
+#undef XProcessInternalConnection
+#undef XAddConnectionWatch
+#undef XRemoveConnectionWatch
+#undef XSetAuthorization
+#undef _Xmbtowc
+#undef _Xwctomb
+#undef XGetEventData
+#undef XFreeEventData
+#undef XAllocClassHint
+#undef XAllocIconSize
+#undef XAllocSizeHints
+#undef XAllocStandardColormap
+#undef XAllocWMHints
+#undef XClipBox
+#undef XCreateRegion
+#undef XDefaultString
+#undef XDeleteContext
+#undef XDestroyRegion
+#undef XEmptyRegion
+#undef XEqualRegion
+#undef XFindContext
+#undef XGetClassHint
+#undef XGetIconSizes
+#undef XGetNormalHints
+#undef XGetRGBColormaps
+#undef XGetSizeHints
+#undef XGetStandardColormap
+#undef XGetTextProperty
+#undef XGetVisualInfo
+#undef XGetWMClientMachine
+#undef XGetWMHints
+#undef XGetWMIconName
+#undef XGetWMName
+#undef XGetWMNormalHints
+#undef XGetWMSizeHints
+#undef XGetZoomHints
+#undef XIntersectRegion
+#undef XConvertCase
+#undef XLookupString
+#undef XMatchVisualInfo
+#undef XOffsetRegion
+#undef XPointInRegion
+#undef XPolygonRegion
+#undef XRectInRegion
+#undef XSaveContext
+#undef XSetClassHint
+#undef XSetIconSizes
+#undef XSetNormalHints
+#undef XSetRGBColormaps
+#undef XSetSizeHints
+#undef XSetStandardProperties
+#undef XSetTextProperty
+#undef XSetWMClientMachine
+#undef XSetWMHints
+#undef XSetWMIconName
+#undef XSetWMName
+#undef XSetWMNormalHints
+#undef XSetWMProperties
+#undef XmbSetWMProperties
+#undef Xutf8SetWMProperties
+#undef XSetWMSizeHints
+#undef XSetRegion
+#undef XSetStandardColormap
+#undef XSetZoomHints
+#undef XShrinkRegion
+#undef XStringListToTextProperty
+#undef XSubtractRegion
+#undef XmbTextListToTextProperty
+#undef XwcTextListToTextProperty
+#undef Xutf8TextListToTextProperty
+#undef XwcFreeStringList
+#undef XTextPropertyToStringList
+#undef XmbTextPropertyToTextList
+#undef XwcTextPropertyToTextList
+#undef Xutf8TextPropertyToTextList
+#undef XUnionRectWithRegion
+#undef XUnionRegion
+#undef XWMGeometry
+#undef XXorRegion
+#undef XkbIgnoreExtension
+#undef XkbOpenDisplay
+#undef XkbQueryExtension
+#undef XkbUseExtension
+#undef XkbLibraryVersion
+#undef XkbSetXlibControls
+#undef XkbGetXlibControls
+#undef XkbXlibControlsImplemented
+#undef XkbSetAtomFuncs
+#undef XkbKeycodeToKeysym
+#undef XkbKeysymToModifiers
+#undef XkbLookupKeySym
+#undef XkbLookupKeyBinding
+#undef XkbTranslateKeyCode
+#undef XkbTranslateKeySym
+#undef XkbSetAutoRepeatRate
+#undef XkbGetAutoRepeatRate
+#undef XkbChangeEnabledControls
+#undef XkbDeviceBell
+#undef XkbForceDeviceBell
+#undef XkbDeviceBellEvent
+#undef XkbBell
+#undef XkbForceBell
+#undef XkbBellEvent
+#undef XkbSelectEvents
+#undef XkbSelectEventDetails
+#undef XkbNoteMapChanges
+#undef XkbNoteNameChanges
+#undef XkbGetIndicatorState
+#undef XkbGetIndicatorMap
+#undef XkbSetIndicatorMap
+#undef XkbGetNamedIndicator
+#undef XkbGetNamedDeviceIndicator
+#undef XkbSetNamedIndicator
+#undef XkbSetNamedDeviceIndicator
+#undef XkbLockModifiers
+#undef XkbLatchModifiers
+#undef XkbLockGroup
+#undef XkbLatchGroup
+#undef XkbSetServerInternalMods
+#undef XkbSetIgnoreLockMods
+#undef XkbVirtualModsToReal
+#undef XkbComputeEffectiveMap
+#undef XkbInitCanonicalKeyTypes
+#undef XkbAllocKeyboard
+#undef XkbFreeKeyboard
+#undef XkbAllocClientMap
+#undef XkbAllocServerMap
+#undef XkbFreeClientMap
+#undef XkbFreeServerMap
+#undef XkbAddKeyType
+#undef XkbAllocIndicatorMaps
+#undef XkbFreeIndicatorMaps
+#undef XkbGetMap
+#undef XkbGetUpdatedMap
+#undef XkbGetMapChanges
+#undef XkbRefreshKeyboardMapping
+#undef XkbGetKeyTypes
+#undef XkbGetKeySyms
+#undef XkbGetKeyActions
+#undef XkbGetKeyBehaviors
+#undef XkbGetVirtualMods
+#undef XkbGetKeyExplicitComponents
+#undef XkbGetKeyModifierMap
+#undef XkbGetKeyVirtualModMap
+#undef XkbAllocControls
+#undef XkbFreeControls
+#undef XkbGetControls
+#undef XkbSetControls
+#undef XkbNoteControlsChanges
+#undef XkbAllocCompatMap
+#undef XkbFreeCompatMap
+#undef XkbGetCompatMap
+#undef XkbSetCompatMap
+#undef XkbAllocNames
+#undef XkbGetNames
+#undef XkbSetNames
+#undef XkbChangeNames
+#undef XkbFreeNames
+#undef XkbGetState
+#undef XkbSetMap
+#undef XkbChangeMap
+#undef XkbSetDetectableAutoRepeat
+#undef XkbGetDetectableAutoRepeat
+#undef XkbSetAutoResetControls
+#undef XkbGetAutoResetControls
+#undef XkbSetPerClientControls
+#undef XkbGetPerClientControls
+#undef XkbCopyKeyType
+#undef XkbCopyKeyTypes
+#undef XkbResizeKeyType
+#undef XkbResizeKeySyms
+#undef XkbResizeKeyActions
+#undef XkbChangeTypesOfKey
+#undef XkbChangeKeycodeRange
+#undef XkbListComponents
+#undef XkbFreeComponentList
+#undef XkbGetKeyboard
+#undef XkbGetKeyboardByName
+#undef XkbKeyTypesForCoreSymbols
+#undef XkbApplyCompatMapToKey
+#undef XkbUpdateMapFromCore
+#undef XkbAddDeviceLedInfo
+#undef XkbResizeDeviceButtonActions
+#undef XkbAllocDeviceInfo
+#undef XkbFreeDeviceInfo
+#undef XkbNoteDeviceChanges
+#undef XkbGetDeviceInfo
+#undef XkbGetDeviceInfoChanges
+#undef XkbGetDeviceButtonActions
+#undef XkbGetDeviceLedInfo
+#undef XkbSetDeviceInfo
+#undef XkbChangeDeviceInfo
+#undef XkbSetDeviceLedInfo
+#undef XkbSetDeviceButtonActions
+#undef XkbToControl
+#undef XkbSetDebuggingFlags
+#undef XkbApplyVirtualModChanges
+#undef XkbUpdateActionVirtualMods
+#undef XkbUpdateKeyTypeVirtualMods
+#ifdef __cplusplus
+extern "C" {
+#endif
+#define _Xmblen _Xmblen_dylibloader_wrapper_xlib
+#define XLoadQueryFont XLoadQueryFont_dylibloader_wrapper_xlib
+#define XQueryFont XQueryFont_dylibloader_wrapper_xlib
+#define XGetMotionEvents XGetMotionEvents_dylibloader_wrapper_xlib
+#define XDeleteModifiermapEntry XDeleteModifiermapEntry_dylibloader_wrapper_xlib
+#define XGetModifierMapping XGetModifierMapping_dylibloader_wrapper_xlib
+#define XInsertModifiermapEntry XInsertModifiermapEntry_dylibloader_wrapper_xlib
+#define XNewModifiermap XNewModifiermap_dylibloader_wrapper_xlib
+#define XCreateImage XCreateImage_dylibloader_wrapper_xlib
+#define XInitImage XInitImage_dylibloader_wrapper_xlib
+#define XGetImage XGetImage_dylibloader_wrapper_xlib
+#define XGetSubImage XGetSubImage_dylibloader_wrapper_xlib
+#define XOpenDisplay XOpenDisplay_dylibloader_wrapper_xlib
+#define XrmInitialize XrmInitialize_dylibloader_wrapper_xlib
+#define XFetchBytes XFetchBytes_dylibloader_wrapper_xlib
+#define XFetchBuffer XFetchBuffer_dylibloader_wrapper_xlib
+#define XGetAtomName XGetAtomName_dylibloader_wrapper_xlib
+#define XGetAtomNames XGetAtomNames_dylibloader_wrapper_xlib
+#define XGetDefault XGetDefault_dylibloader_wrapper_xlib
+#define XDisplayName XDisplayName_dylibloader_wrapper_xlib
+#define XKeysymToString XKeysymToString_dylibloader_wrapper_xlib
+#define XSynchronize XSynchronize_dylibloader_wrapper_xlib
+#define XSetAfterFunction XSetAfterFunction_dylibloader_wrapper_xlib
+#define XInternAtom XInternAtom_dylibloader_wrapper_xlib
+#define XInternAtoms XInternAtoms_dylibloader_wrapper_xlib
+#define XCopyColormapAndFree XCopyColormapAndFree_dylibloader_wrapper_xlib
+#define XCreateColormap XCreateColormap_dylibloader_wrapper_xlib
+#define XCreatePixmapCursor XCreatePixmapCursor_dylibloader_wrapper_xlib
+#define XCreateGlyphCursor XCreateGlyphCursor_dylibloader_wrapper_xlib
+#define XCreateFontCursor XCreateFontCursor_dylibloader_wrapper_xlib
+#define XLoadFont XLoadFont_dylibloader_wrapper_xlib
+#define XCreateGC XCreateGC_dylibloader_wrapper_xlib
+#define XGContextFromGC XGContextFromGC_dylibloader_wrapper_xlib
+#define XFlushGC XFlushGC_dylibloader_wrapper_xlib
+#define XCreatePixmap XCreatePixmap_dylibloader_wrapper_xlib
+#define XCreateBitmapFromData XCreateBitmapFromData_dylibloader_wrapper_xlib
+#define XCreatePixmapFromBitmapData XCreatePixmapFromBitmapData_dylibloader_wrapper_xlib
+#define XCreateSimpleWindow XCreateSimpleWindow_dylibloader_wrapper_xlib
+#define XGetSelectionOwner XGetSelectionOwner_dylibloader_wrapper_xlib
+#define XCreateWindow XCreateWindow_dylibloader_wrapper_xlib
+#define XListInstalledColormaps XListInstalledColormaps_dylibloader_wrapper_xlib
+#define XListFonts XListFonts_dylibloader_wrapper_xlib
+#define XListFontsWithInfo XListFontsWithInfo_dylibloader_wrapper_xlib
+#define XGetFontPath XGetFontPath_dylibloader_wrapper_xlib
+#define XListExtensions XListExtensions_dylibloader_wrapper_xlib
+#define XListProperties XListProperties_dylibloader_wrapper_xlib
+#define XListHosts XListHosts_dylibloader_wrapper_xlib
+#define XKeycodeToKeysym XKeycodeToKeysym_dylibloader_wrapper_xlib
+#define XLookupKeysym XLookupKeysym_dylibloader_wrapper_xlib
+#define XGetKeyboardMapping XGetKeyboardMapping_dylibloader_wrapper_xlib
+#define XStringToKeysym XStringToKeysym_dylibloader_wrapper_xlib
+#define XMaxRequestSize XMaxRequestSize_dylibloader_wrapper_xlib
+#define XExtendedMaxRequestSize XExtendedMaxRequestSize_dylibloader_wrapper_xlib
+#define XResourceManagerString XResourceManagerString_dylibloader_wrapper_xlib
+#define XScreenResourceString XScreenResourceString_dylibloader_wrapper_xlib
+#define XDisplayMotionBufferSize XDisplayMotionBufferSize_dylibloader_wrapper_xlib
+#define XVisualIDFromVisual XVisualIDFromVisual_dylibloader_wrapper_xlib
+#define XInitThreads XInitThreads_dylibloader_wrapper_xlib
+#define XLockDisplay XLockDisplay_dylibloader_wrapper_xlib
+#define XUnlockDisplay XUnlockDisplay_dylibloader_wrapper_xlib
+#define XInitExtension XInitExtension_dylibloader_wrapper_xlib
+#define XAddExtension XAddExtension_dylibloader_wrapper_xlib
+#define XFindOnExtensionList XFindOnExtensionList_dylibloader_wrapper_xlib
+#define XEHeadOfExtensionList XEHeadOfExtensionList_dylibloader_wrapper_xlib
+#define XRootWindow XRootWindow_dylibloader_wrapper_xlib
+#define XDefaultRootWindow XDefaultRootWindow_dylibloader_wrapper_xlib
+#define XRootWindowOfScreen XRootWindowOfScreen_dylibloader_wrapper_xlib
+#define XDefaultVisual XDefaultVisual_dylibloader_wrapper_xlib
+#define XDefaultVisualOfScreen XDefaultVisualOfScreen_dylibloader_wrapper_xlib
+#define XDefaultGC XDefaultGC_dylibloader_wrapper_xlib
+#define XDefaultGCOfScreen XDefaultGCOfScreen_dylibloader_wrapper_xlib
+#define XBlackPixel XBlackPixel_dylibloader_wrapper_xlib
+#define XWhitePixel XWhitePixel_dylibloader_wrapper_xlib
+#define XAllPlanes XAllPlanes_dylibloader_wrapper_xlib
+#define XBlackPixelOfScreen XBlackPixelOfScreen_dylibloader_wrapper_xlib
+#define XWhitePixelOfScreen XWhitePixelOfScreen_dylibloader_wrapper_xlib
+#define XNextRequest XNextRequest_dylibloader_wrapper_xlib
+#define XLastKnownRequestProcessed XLastKnownRequestProcessed_dylibloader_wrapper_xlib
+#define XServerVendor XServerVendor_dylibloader_wrapper_xlib
+#define XDisplayString XDisplayString_dylibloader_wrapper_xlib
+#define XDefaultColormap XDefaultColormap_dylibloader_wrapper_xlib
+#define XDefaultColormapOfScreen XDefaultColormapOfScreen_dylibloader_wrapper_xlib
+#define XDisplayOfScreen XDisplayOfScreen_dylibloader_wrapper_xlib
+#define XScreenOfDisplay XScreenOfDisplay_dylibloader_wrapper_xlib
+#define XDefaultScreenOfDisplay XDefaultScreenOfDisplay_dylibloader_wrapper_xlib
+#define XEventMaskOfScreen XEventMaskOfScreen_dylibloader_wrapper_xlib
+#define XScreenNumberOfScreen XScreenNumberOfScreen_dylibloader_wrapper_xlib
+#define XSetErrorHandler XSetErrorHandler_dylibloader_wrapper_xlib
+#define XSetIOErrorHandler XSetIOErrorHandler_dylibloader_wrapper_xlib
+#define XListPixmapFormats XListPixmapFormats_dylibloader_wrapper_xlib
+#define XListDepths XListDepths_dylibloader_wrapper_xlib
+#define XReconfigureWMWindow XReconfigureWMWindow_dylibloader_wrapper_xlib
+#define XGetWMProtocols XGetWMProtocols_dylibloader_wrapper_xlib
+#define XSetWMProtocols XSetWMProtocols_dylibloader_wrapper_xlib
+#define XIconifyWindow XIconifyWindow_dylibloader_wrapper_xlib
+#define XWithdrawWindow XWithdrawWindow_dylibloader_wrapper_xlib
+#define XGetCommand XGetCommand_dylibloader_wrapper_xlib
+#define XGetWMColormapWindows XGetWMColormapWindows_dylibloader_wrapper_xlib
+#define XSetWMColormapWindows XSetWMColormapWindows_dylibloader_wrapper_xlib
+#define XFreeStringList XFreeStringList_dylibloader_wrapper_xlib
+#define XSetTransientForHint XSetTransientForHint_dylibloader_wrapper_xlib
+#define XActivateScreenSaver XActivateScreenSaver_dylibloader_wrapper_xlib
+#define XAddHost XAddHost_dylibloader_wrapper_xlib
+#define XAddHosts XAddHosts_dylibloader_wrapper_xlib
+#define XAddToExtensionList XAddToExtensionList_dylibloader_wrapper_xlib
+#define XAddToSaveSet XAddToSaveSet_dylibloader_wrapper_xlib
+#define XAllocColor XAllocColor_dylibloader_wrapper_xlib
+#define XAllocColorCells XAllocColorCells_dylibloader_wrapper_xlib
+#define XAllocColorPlanes XAllocColorPlanes_dylibloader_wrapper_xlib
+#define XAllocNamedColor XAllocNamedColor_dylibloader_wrapper_xlib
+#define XAllowEvents XAllowEvents_dylibloader_wrapper_xlib
+#define XAutoRepeatOff XAutoRepeatOff_dylibloader_wrapper_xlib
+#define XAutoRepeatOn XAutoRepeatOn_dylibloader_wrapper_xlib
+#define XBell XBell_dylibloader_wrapper_xlib
+#define XBitmapBitOrder XBitmapBitOrder_dylibloader_wrapper_xlib
+#define XBitmapPad XBitmapPad_dylibloader_wrapper_xlib
+#define XBitmapUnit XBitmapUnit_dylibloader_wrapper_xlib
+#define XCellsOfScreen XCellsOfScreen_dylibloader_wrapper_xlib
+#define XChangeActivePointerGrab XChangeActivePointerGrab_dylibloader_wrapper_xlib
+#define XChangeGC XChangeGC_dylibloader_wrapper_xlib
+#define XChangeKeyboardControl XChangeKeyboardControl_dylibloader_wrapper_xlib
+#define XChangeKeyboardMapping XChangeKeyboardMapping_dylibloader_wrapper_xlib
+#define XChangePointerControl XChangePointerControl_dylibloader_wrapper_xlib
+#define XChangeProperty XChangeProperty_dylibloader_wrapper_xlib
+#define XChangeSaveSet XChangeSaveSet_dylibloader_wrapper_xlib
+#define XChangeWindowAttributes XChangeWindowAttributes_dylibloader_wrapper_xlib
+#define XCheckIfEvent XCheckIfEvent_dylibloader_wrapper_xlib
+#define XCheckMaskEvent XCheckMaskEvent_dylibloader_wrapper_xlib
+#define XCheckTypedEvent XCheckTypedEvent_dylibloader_wrapper_xlib
+#define XCheckTypedWindowEvent XCheckTypedWindowEvent_dylibloader_wrapper_xlib
+#define XCheckWindowEvent XCheckWindowEvent_dylibloader_wrapper_xlib
+#define XCirculateSubwindows XCirculateSubwindows_dylibloader_wrapper_xlib
+#define XCirculateSubwindowsDown XCirculateSubwindowsDown_dylibloader_wrapper_xlib
+#define XCirculateSubwindowsUp XCirculateSubwindowsUp_dylibloader_wrapper_xlib
+#define XClearArea XClearArea_dylibloader_wrapper_xlib
+#define XClearWindow XClearWindow_dylibloader_wrapper_xlib
+#define XCloseDisplay XCloseDisplay_dylibloader_wrapper_xlib
+#define XConfigureWindow XConfigureWindow_dylibloader_wrapper_xlib
+#define XConnectionNumber XConnectionNumber_dylibloader_wrapper_xlib
+#define XConvertSelection XConvertSelection_dylibloader_wrapper_xlib
+#define XCopyArea XCopyArea_dylibloader_wrapper_xlib
+#define XCopyGC XCopyGC_dylibloader_wrapper_xlib
+#define XCopyPlane XCopyPlane_dylibloader_wrapper_xlib
+#define XDefaultDepth XDefaultDepth_dylibloader_wrapper_xlib
+#define XDefaultDepthOfScreen XDefaultDepthOfScreen_dylibloader_wrapper_xlib
+#define XDefaultScreen XDefaultScreen_dylibloader_wrapper_xlib
+#define XDefineCursor XDefineCursor_dylibloader_wrapper_xlib
+#define XDeleteProperty XDeleteProperty_dylibloader_wrapper_xlib
+#define XDestroyWindow XDestroyWindow_dylibloader_wrapper_xlib
+#define XDestroySubwindows XDestroySubwindows_dylibloader_wrapper_xlib
+#define XDoesBackingStore XDoesBackingStore_dylibloader_wrapper_xlib
+#define XDoesSaveUnders XDoesSaveUnders_dylibloader_wrapper_xlib
+#define XDisableAccessControl XDisableAccessControl_dylibloader_wrapper_xlib
+#define XDisplayCells XDisplayCells_dylibloader_wrapper_xlib
+#define XDisplayHeight XDisplayHeight_dylibloader_wrapper_xlib
+#define XDisplayHeightMM XDisplayHeightMM_dylibloader_wrapper_xlib
+#define XDisplayKeycodes XDisplayKeycodes_dylibloader_wrapper_xlib
+#define XDisplayPlanes XDisplayPlanes_dylibloader_wrapper_xlib
+#define XDisplayWidth XDisplayWidth_dylibloader_wrapper_xlib
+#define XDisplayWidthMM XDisplayWidthMM_dylibloader_wrapper_xlib
+#define XDrawArc XDrawArc_dylibloader_wrapper_xlib
+#define XDrawArcs XDrawArcs_dylibloader_wrapper_xlib
+#define XDrawImageString XDrawImageString_dylibloader_wrapper_xlib
+#define XDrawImageString16 XDrawImageString16_dylibloader_wrapper_xlib
+#define XDrawLine XDrawLine_dylibloader_wrapper_xlib
+#define XDrawLines XDrawLines_dylibloader_wrapper_xlib
+#define XDrawPoint XDrawPoint_dylibloader_wrapper_xlib
+#define XDrawPoints XDrawPoints_dylibloader_wrapper_xlib
+#define XDrawRectangle XDrawRectangle_dylibloader_wrapper_xlib
+#define XDrawRectangles XDrawRectangles_dylibloader_wrapper_xlib
+#define XDrawSegments XDrawSegments_dylibloader_wrapper_xlib
+#define XDrawString XDrawString_dylibloader_wrapper_xlib
+#define XDrawString16 XDrawString16_dylibloader_wrapper_xlib
+#define XDrawText XDrawText_dylibloader_wrapper_xlib
+#define XDrawText16 XDrawText16_dylibloader_wrapper_xlib
+#define XEnableAccessControl XEnableAccessControl_dylibloader_wrapper_xlib
+#define XEventsQueued XEventsQueued_dylibloader_wrapper_xlib
+#define XFetchName XFetchName_dylibloader_wrapper_xlib
+#define XFillArc XFillArc_dylibloader_wrapper_xlib
+#define XFillArcs XFillArcs_dylibloader_wrapper_xlib
+#define XFillPolygon XFillPolygon_dylibloader_wrapper_xlib
+#define XFillRectangle XFillRectangle_dylibloader_wrapper_xlib
+#define XFillRectangles XFillRectangles_dylibloader_wrapper_xlib
+#define XFlush XFlush_dylibloader_wrapper_xlib
+#define XForceScreenSaver XForceScreenSaver_dylibloader_wrapper_xlib
+#define XFree XFree_dylibloader_wrapper_xlib
+#define XFreeColormap XFreeColormap_dylibloader_wrapper_xlib
+#define XFreeColors XFreeColors_dylibloader_wrapper_xlib
+#define XFreeCursor XFreeCursor_dylibloader_wrapper_xlib
+#define XFreeExtensionList XFreeExtensionList_dylibloader_wrapper_xlib
+#define XFreeFont XFreeFont_dylibloader_wrapper_xlib
+#define XFreeFontInfo XFreeFontInfo_dylibloader_wrapper_xlib
+#define XFreeFontNames XFreeFontNames_dylibloader_wrapper_xlib
+#define XFreeFontPath XFreeFontPath_dylibloader_wrapper_xlib
+#define XFreeGC XFreeGC_dylibloader_wrapper_xlib
+#define XFreeModifiermap XFreeModifiermap_dylibloader_wrapper_xlib
+#define XFreePixmap XFreePixmap_dylibloader_wrapper_xlib
+#define XGeometry XGeometry_dylibloader_wrapper_xlib
+#define XGetErrorDatabaseText XGetErrorDatabaseText_dylibloader_wrapper_xlib
+#define XGetErrorText XGetErrorText_dylibloader_wrapper_xlib
+#define XGetFontProperty XGetFontProperty_dylibloader_wrapper_xlib
+#define XGetGCValues XGetGCValues_dylibloader_wrapper_xlib
+#define XGetGeometry XGetGeometry_dylibloader_wrapper_xlib
+#define XGetIconName XGetIconName_dylibloader_wrapper_xlib
+#define XGetInputFocus XGetInputFocus_dylibloader_wrapper_xlib
+#define XGetKeyboardControl XGetKeyboardControl_dylibloader_wrapper_xlib
+#define XGetPointerControl XGetPointerControl_dylibloader_wrapper_xlib
+#define XGetPointerMapping XGetPointerMapping_dylibloader_wrapper_xlib
+#define XGetScreenSaver XGetScreenSaver_dylibloader_wrapper_xlib
+#define XGetTransientForHint XGetTransientForHint_dylibloader_wrapper_xlib
+#define XGetWindowProperty XGetWindowProperty_dylibloader_wrapper_xlib
+#define XGetWindowAttributes XGetWindowAttributes_dylibloader_wrapper_xlib
+#define XGrabButton XGrabButton_dylibloader_wrapper_xlib
+#define XGrabKey XGrabKey_dylibloader_wrapper_xlib
+#define XGrabKeyboard XGrabKeyboard_dylibloader_wrapper_xlib
+#define XGrabPointer XGrabPointer_dylibloader_wrapper_xlib
+#define XGrabServer XGrabServer_dylibloader_wrapper_xlib
+#define XHeightMMOfScreen XHeightMMOfScreen_dylibloader_wrapper_xlib
+#define XHeightOfScreen XHeightOfScreen_dylibloader_wrapper_xlib
+#define XIfEvent XIfEvent_dylibloader_wrapper_xlib
+#define XImageByteOrder XImageByteOrder_dylibloader_wrapper_xlib
+#define XInstallColormap XInstallColormap_dylibloader_wrapper_xlib
+#define XKeysymToKeycode XKeysymToKeycode_dylibloader_wrapper_xlib
+#define XKillClient XKillClient_dylibloader_wrapper_xlib
+#define XLookupColor XLookupColor_dylibloader_wrapper_xlib
+#define XLowerWindow XLowerWindow_dylibloader_wrapper_xlib
+#define XMapRaised XMapRaised_dylibloader_wrapper_xlib
+#define XMapSubwindows XMapSubwindows_dylibloader_wrapper_xlib
+#define XMapWindow XMapWindow_dylibloader_wrapper_xlib
+#define XMaskEvent XMaskEvent_dylibloader_wrapper_xlib
+#define XMaxCmapsOfScreen XMaxCmapsOfScreen_dylibloader_wrapper_xlib
+#define XMinCmapsOfScreen XMinCmapsOfScreen_dylibloader_wrapper_xlib
+#define XMoveResizeWindow XMoveResizeWindow_dylibloader_wrapper_xlib
+#define XMoveWindow XMoveWindow_dylibloader_wrapper_xlib
+#define XNextEvent XNextEvent_dylibloader_wrapper_xlib
+#define XNoOp XNoOp_dylibloader_wrapper_xlib
+#define XParseColor XParseColor_dylibloader_wrapper_xlib
+#define XParseGeometry XParseGeometry_dylibloader_wrapper_xlib
+#define XPeekEvent XPeekEvent_dylibloader_wrapper_xlib
+#define XPeekIfEvent XPeekIfEvent_dylibloader_wrapper_xlib
+#define XPending XPending_dylibloader_wrapper_xlib
+#define XPlanesOfScreen XPlanesOfScreen_dylibloader_wrapper_xlib
+#define XProtocolRevision XProtocolRevision_dylibloader_wrapper_xlib
+#define XProtocolVersion XProtocolVersion_dylibloader_wrapper_xlib
+#define XPutBackEvent XPutBackEvent_dylibloader_wrapper_xlib
+#define XPutImage XPutImage_dylibloader_wrapper_xlib
+#define XQLength XQLength_dylibloader_wrapper_xlib
+#define XQueryBestCursor XQueryBestCursor_dylibloader_wrapper_xlib
+#define XQueryBestSize XQueryBestSize_dylibloader_wrapper_xlib
+#define XQueryBestStipple XQueryBestStipple_dylibloader_wrapper_xlib
+#define XQueryBestTile XQueryBestTile_dylibloader_wrapper_xlib
+#define XQueryColor XQueryColor_dylibloader_wrapper_xlib
+#define XQueryColors XQueryColors_dylibloader_wrapper_xlib
+#define XQueryExtension XQueryExtension_dylibloader_wrapper_xlib
+#define XQueryKeymap XQueryKeymap_dylibloader_wrapper_xlib
+#define XQueryPointer XQueryPointer_dylibloader_wrapper_xlib
+#define XQueryTextExtents XQueryTextExtents_dylibloader_wrapper_xlib
+#define XQueryTextExtents16 XQueryTextExtents16_dylibloader_wrapper_xlib
+#define XQueryTree XQueryTree_dylibloader_wrapper_xlib
+#define XRaiseWindow XRaiseWindow_dylibloader_wrapper_xlib
+#define XReadBitmapFile XReadBitmapFile_dylibloader_wrapper_xlib
+#define XReadBitmapFileData XReadBitmapFileData_dylibloader_wrapper_xlib
+#define XRebindKeysym XRebindKeysym_dylibloader_wrapper_xlib
+#define XRecolorCursor XRecolorCursor_dylibloader_wrapper_xlib
+#define XRefreshKeyboardMapping XRefreshKeyboardMapping_dylibloader_wrapper_xlib
+#define XRemoveFromSaveSet XRemoveFromSaveSet_dylibloader_wrapper_xlib
+#define XRemoveHost XRemoveHost_dylibloader_wrapper_xlib
+#define XRemoveHosts XRemoveHosts_dylibloader_wrapper_xlib
+#define XReparentWindow XReparentWindow_dylibloader_wrapper_xlib
+#define XResetScreenSaver XResetScreenSaver_dylibloader_wrapper_xlib
+#define XResizeWindow XResizeWindow_dylibloader_wrapper_xlib
+#define XRestackWindows XRestackWindows_dylibloader_wrapper_xlib
+#define XRotateBuffers XRotateBuffers_dylibloader_wrapper_xlib
+#define XRotateWindowProperties XRotateWindowProperties_dylibloader_wrapper_xlib
+#define XScreenCount XScreenCount_dylibloader_wrapper_xlib
+#define XSelectInput XSelectInput_dylibloader_wrapper_xlib
+#define XSendEvent XSendEvent_dylibloader_wrapper_xlib
+#define XSetAccessControl XSetAccessControl_dylibloader_wrapper_xlib
+#define XSetArcMode XSetArcMode_dylibloader_wrapper_xlib
+#define XSetBackground XSetBackground_dylibloader_wrapper_xlib
+#define XSetClipMask XSetClipMask_dylibloader_wrapper_xlib
+#define XSetClipOrigin XSetClipOrigin_dylibloader_wrapper_xlib
+#define XSetClipRectangles XSetClipRectangles_dylibloader_wrapper_xlib
+#define XSetCloseDownMode XSetCloseDownMode_dylibloader_wrapper_xlib
+#define XSetCommand XSetCommand_dylibloader_wrapper_xlib
+#define XSetDashes XSetDashes_dylibloader_wrapper_xlib
+#define XSetFillRule XSetFillRule_dylibloader_wrapper_xlib
+#define XSetFillStyle XSetFillStyle_dylibloader_wrapper_xlib
+#define XSetFont XSetFont_dylibloader_wrapper_xlib
+#define XSetFontPath XSetFontPath_dylibloader_wrapper_xlib
+#define XSetForeground XSetForeground_dylibloader_wrapper_xlib
+#define XSetFunction XSetFunction_dylibloader_wrapper_xlib
+#define XSetGraphicsExposures XSetGraphicsExposures_dylibloader_wrapper_xlib
+#define XSetIconName XSetIconName_dylibloader_wrapper_xlib
+#define XSetInputFocus XSetInputFocus_dylibloader_wrapper_xlib
+#define XSetLineAttributes XSetLineAttributes_dylibloader_wrapper_xlib
+#define XSetModifierMapping XSetModifierMapping_dylibloader_wrapper_xlib
+#define XSetPlaneMask XSetPlaneMask_dylibloader_wrapper_xlib
+#define XSetPointerMapping XSetPointerMapping_dylibloader_wrapper_xlib
+#define XSetScreenSaver XSetScreenSaver_dylibloader_wrapper_xlib
+#define XSetSelectionOwner XSetSelectionOwner_dylibloader_wrapper_xlib
+#define XSetState XSetState_dylibloader_wrapper_xlib
+#define XSetStipple XSetStipple_dylibloader_wrapper_xlib
+#define XSetSubwindowMode XSetSubwindowMode_dylibloader_wrapper_xlib
+#define XSetTSOrigin XSetTSOrigin_dylibloader_wrapper_xlib
+#define XSetTile XSetTile_dylibloader_wrapper_xlib
+#define XSetWindowBackground XSetWindowBackground_dylibloader_wrapper_xlib
+#define XSetWindowBackgroundPixmap XSetWindowBackgroundPixmap_dylibloader_wrapper_xlib
+#define XSetWindowBorder XSetWindowBorder_dylibloader_wrapper_xlib
+#define XSetWindowBorderPixmap XSetWindowBorderPixmap_dylibloader_wrapper_xlib
+#define XSetWindowBorderWidth XSetWindowBorderWidth_dylibloader_wrapper_xlib
+#define XSetWindowColormap XSetWindowColormap_dylibloader_wrapper_xlib
+#define XStoreBuffer XStoreBuffer_dylibloader_wrapper_xlib
+#define XStoreBytes XStoreBytes_dylibloader_wrapper_xlib
+#define XStoreColor XStoreColor_dylibloader_wrapper_xlib
+#define XStoreColors XStoreColors_dylibloader_wrapper_xlib
+#define XStoreName XStoreName_dylibloader_wrapper_xlib
+#define XStoreNamedColor XStoreNamedColor_dylibloader_wrapper_xlib
+#define XSync XSync_dylibloader_wrapper_xlib
+#define XTextExtents XTextExtents_dylibloader_wrapper_xlib
+#define XTextExtents16 XTextExtents16_dylibloader_wrapper_xlib
+#define XTextWidth XTextWidth_dylibloader_wrapper_xlib
+#define XTextWidth16 XTextWidth16_dylibloader_wrapper_xlib
+#define XTranslateCoordinates XTranslateCoordinates_dylibloader_wrapper_xlib
+#define XUndefineCursor XUndefineCursor_dylibloader_wrapper_xlib
+#define XUngrabButton XUngrabButton_dylibloader_wrapper_xlib
+#define XUngrabKey XUngrabKey_dylibloader_wrapper_xlib
+#define XUngrabKeyboard XUngrabKeyboard_dylibloader_wrapper_xlib
+#define XUngrabPointer XUngrabPointer_dylibloader_wrapper_xlib
+#define XUngrabServer XUngrabServer_dylibloader_wrapper_xlib
+#define XUninstallColormap XUninstallColormap_dylibloader_wrapper_xlib
+#define XUnloadFont XUnloadFont_dylibloader_wrapper_xlib
+#define XUnmapSubwindows XUnmapSubwindows_dylibloader_wrapper_xlib
+#define XUnmapWindow XUnmapWindow_dylibloader_wrapper_xlib
+#define XVendorRelease XVendorRelease_dylibloader_wrapper_xlib
+#define XWarpPointer XWarpPointer_dylibloader_wrapper_xlib
+#define XWidthMMOfScreen XWidthMMOfScreen_dylibloader_wrapper_xlib
+#define XWidthOfScreen XWidthOfScreen_dylibloader_wrapper_xlib
+#define XWindowEvent XWindowEvent_dylibloader_wrapper_xlib
+#define XWriteBitmapFile XWriteBitmapFile_dylibloader_wrapper_xlib
+#define XSupportsLocale XSupportsLocale_dylibloader_wrapper_xlib
+#define XSetLocaleModifiers XSetLocaleModifiers_dylibloader_wrapper_xlib
+#define XOpenOM XOpenOM_dylibloader_wrapper_xlib
+#define XCloseOM XCloseOM_dylibloader_wrapper_xlib
+#define XSetOMValues XSetOMValues_dylibloader_wrapper_xlib
+#define XGetOMValues XGetOMValues_dylibloader_wrapper_xlib
+#define XDisplayOfOM XDisplayOfOM_dylibloader_wrapper_xlib
+#define XLocaleOfOM XLocaleOfOM_dylibloader_wrapper_xlib
+#define XCreateOC XCreateOC_dylibloader_wrapper_xlib
+#define XDestroyOC XDestroyOC_dylibloader_wrapper_xlib
+#define XOMOfOC XOMOfOC_dylibloader_wrapper_xlib
+#define XSetOCValues XSetOCValues_dylibloader_wrapper_xlib
+#define XGetOCValues XGetOCValues_dylibloader_wrapper_xlib
+#define XCreateFontSet XCreateFontSet_dylibloader_wrapper_xlib
+#define XFreeFontSet XFreeFontSet_dylibloader_wrapper_xlib
+#define XFontsOfFontSet XFontsOfFontSet_dylibloader_wrapper_xlib
+#define XBaseFontNameListOfFontSet XBaseFontNameListOfFontSet_dylibloader_wrapper_xlib
+#define XLocaleOfFontSet XLocaleOfFontSet_dylibloader_wrapper_xlib
+#define XContextDependentDrawing XContextDependentDrawing_dylibloader_wrapper_xlib
+#define XDirectionalDependentDrawing XDirectionalDependentDrawing_dylibloader_wrapper_xlib
+#define XContextualDrawing XContextualDrawing_dylibloader_wrapper_xlib
+#define XExtentsOfFontSet XExtentsOfFontSet_dylibloader_wrapper_xlib
+#define XmbTextEscapement XmbTextEscapement_dylibloader_wrapper_xlib
+#define XwcTextEscapement XwcTextEscapement_dylibloader_wrapper_xlib
+#define Xutf8TextEscapement Xutf8TextEscapement_dylibloader_wrapper_xlib
+#define XmbTextExtents XmbTextExtents_dylibloader_wrapper_xlib
+#define XwcTextExtents XwcTextExtents_dylibloader_wrapper_xlib
+#define Xutf8TextExtents Xutf8TextExtents_dylibloader_wrapper_xlib
+#define XmbTextPerCharExtents XmbTextPerCharExtents_dylibloader_wrapper_xlib
+#define XwcTextPerCharExtents XwcTextPerCharExtents_dylibloader_wrapper_xlib
+#define Xutf8TextPerCharExtents Xutf8TextPerCharExtents_dylibloader_wrapper_xlib
+#define XmbDrawText XmbDrawText_dylibloader_wrapper_xlib
+#define XwcDrawText XwcDrawText_dylibloader_wrapper_xlib
+#define Xutf8DrawText Xutf8DrawText_dylibloader_wrapper_xlib
+#define XmbDrawString XmbDrawString_dylibloader_wrapper_xlib
+#define XwcDrawString XwcDrawString_dylibloader_wrapper_xlib
+#define Xutf8DrawString Xutf8DrawString_dylibloader_wrapper_xlib
+#define XmbDrawImageString XmbDrawImageString_dylibloader_wrapper_xlib
+#define XwcDrawImageString XwcDrawImageString_dylibloader_wrapper_xlib
+#define Xutf8DrawImageString Xutf8DrawImageString_dylibloader_wrapper_xlib
+#define XOpenIM XOpenIM_dylibloader_wrapper_xlib
+#define XCloseIM XCloseIM_dylibloader_wrapper_xlib
+#define XGetIMValues XGetIMValues_dylibloader_wrapper_xlib
+#define XSetIMValues XSetIMValues_dylibloader_wrapper_xlib
+#define XDisplayOfIM XDisplayOfIM_dylibloader_wrapper_xlib
+#define XLocaleOfIM XLocaleOfIM_dylibloader_wrapper_xlib
+#define XCreateIC XCreateIC_dylibloader_wrapper_xlib
+#define XDestroyIC XDestroyIC_dylibloader_wrapper_xlib
+#define XSetICFocus XSetICFocus_dylibloader_wrapper_xlib
+#define XUnsetICFocus XUnsetICFocus_dylibloader_wrapper_xlib
+#define XwcResetIC XwcResetIC_dylibloader_wrapper_xlib
+#define XmbResetIC XmbResetIC_dylibloader_wrapper_xlib
+#define Xutf8ResetIC Xutf8ResetIC_dylibloader_wrapper_xlib
+#define XSetICValues XSetICValues_dylibloader_wrapper_xlib
+#define XGetICValues XGetICValues_dylibloader_wrapper_xlib
+#define XIMOfIC XIMOfIC_dylibloader_wrapper_xlib
+#define XFilterEvent XFilterEvent_dylibloader_wrapper_xlib
+#define XmbLookupString XmbLookupString_dylibloader_wrapper_xlib
+#define XwcLookupString XwcLookupString_dylibloader_wrapper_xlib
+#define Xutf8LookupString Xutf8LookupString_dylibloader_wrapper_xlib
+#define XVaCreateNestedList XVaCreateNestedList_dylibloader_wrapper_xlib
+#define XRegisterIMInstantiateCallback XRegisterIMInstantiateCallback_dylibloader_wrapper_xlib
+#define XUnregisterIMInstantiateCallback XUnregisterIMInstantiateCallback_dylibloader_wrapper_xlib
+#define XInternalConnectionNumbers XInternalConnectionNumbers_dylibloader_wrapper_xlib
+#define XProcessInternalConnection XProcessInternalConnection_dylibloader_wrapper_xlib
+#define XAddConnectionWatch XAddConnectionWatch_dylibloader_wrapper_xlib
+#define XRemoveConnectionWatch XRemoveConnectionWatch_dylibloader_wrapper_xlib
+#define XSetAuthorization XSetAuthorization_dylibloader_wrapper_xlib
+#define _Xmbtowc _Xmbtowc_dylibloader_wrapper_xlib
+#define _Xwctomb _Xwctomb_dylibloader_wrapper_xlib
+#define XGetEventData XGetEventData_dylibloader_wrapper_xlib
+#define XFreeEventData XFreeEventData_dylibloader_wrapper_xlib
+#define XAllocClassHint XAllocClassHint_dylibloader_wrapper_xlib
+#define XAllocIconSize XAllocIconSize_dylibloader_wrapper_xlib
+#define XAllocSizeHints XAllocSizeHints_dylibloader_wrapper_xlib
+#define XAllocStandardColormap XAllocStandardColormap_dylibloader_wrapper_xlib
+#define XAllocWMHints XAllocWMHints_dylibloader_wrapper_xlib
+#define XClipBox XClipBox_dylibloader_wrapper_xlib
+#define XCreateRegion XCreateRegion_dylibloader_wrapper_xlib
+#define XDefaultString XDefaultString_dylibloader_wrapper_xlib
+#define XDeleteContext XDeleteContext_dylibloader_wrapper_xlib
+#define XDestroyRegion XDestroyRegion_dylibloader_wrapper_xlib
+#define XEmptyRegion XEmptyRegion_dylibloader_wrapper_xlib
+#define XEqualRegion XEqualRegion_dylibloader_wrapper_xlib
+#define XFindContext XFindContext_dylibloader_wrapper_xlib
+#define XGetClassHint XGetClassHint_dylibloader_wrapper_xlib
+#define XGetIconSizes XGetIconSizes_dylibloader_wrapper_xlib
+#define XGetNormalHints XGetNormalHints_dylibloader_wrapper_xlib
+#define XGetRGBColormaps XGetRGBColormaps_dylibloader_wrapper_xlib
+#define XGetSizeHints XGetSizeHints_dylibloader_wrapper_xlib
+#define XGetStandardColormap XGetStandardColormap_dylibloader_wrapper_xlib
+#define XGetTextProperty XGetTextProperty_dylibloader_wrapper_xlib
+#define XGetVisualInfo XGetVisualInfo_dylibloader_wrapper_xlib
+#define XGetWMClientMachine XGetWMClientMachine_dylibloader_wrapper_xlib
+#define XGetWMHints XGetWMHints_dylibloader_wrapper_xlib
+#define XGetWMIconName XGetWMIconName_dylibloader_wrapper_xlib
+#define XGetWMName XGetWMName_dylibloader_wrapper_xlib
+#define XGetWMNormalHints XGetWMNormalHints_dylibloader_wrapper_xlib
+#define XGetWMSizeHints XGetWMSizeHints_dylibloader_wrapper_xlib
+#define XGetZoomHints XGetZoomHints_dylibloader_wrapper_xlib
+#define XIntersectRegion XIntersectRegion_dylibloader_wrapper_xlib
+#define XConvertCase XConvertCase_dylibloader_wrapper_xlib
+#define XLookupString XLookupString_dylibloader_wrapper_xlib
+#define XMatchVisualInfo XMatchVisualInfo_dylibloader_wrapper_xlib
+#define XOffsetRegion XOffsetRegion_dylibloader_wrapper_xlib
+#define XPointInRegion XPointInRegion_dylibloader_wrapper_xlib
+#define XPolygonRegion XPolygonRegion_dylibloader_wrapper_xlib
+#define XRectInRegion XRectInRegion_dylibloader_wrapper_xlib
+#define XSaveContext XSaveContext_dylibloader_wrapper_xlib
+#define XSetClassHint XSetClassHint_dylibloader_wrapper_xlib
+#define XSetIconSizes XSetIconSizes_dylibloader_wrapper_xlib
+#define XSetNormalHints XSetNormalHints_dylibloader_wrapper_xlib
+#define XSetRGBColormaps XSetRGBColormaps_dylibloader_wrapper_xlib
+#define XSetSizeHints XSetSizeHints_dylibloader_wrapper_xlib
+#define XSetStandardProperties XSetStandardProperties_dylibloader_wrapper_xlib
+#define XSetTextProperty XSetTextProperty_dylibloader_wrapper_xlib
+#define XSetWMClientMachine XSetWMClientMachine_dylibloader_wrapper_xlib
+#define XSetWMHints XSetWMHints_dylibloader_wrapper_xlib
+#define XSetWMIconName XSetWMIconName_dylibloader_wrapper_xlib
+#define XSetWMName XSetWMName_dylibloader_wrapper_xlib
+#define XSetWMNormalHints XSetWMNormalHints_dylibloader_wrapper_xlib
+#define XSetWMProperties XSetWMProperties_dylibloader_wrapper_xlib
+#define XmbSetWMProperties XmbSetWMProperties_dylibloader_wrapper_xlib
+#define Xutf8SetWMProperties Xutf8SetWMProperties_dylibloader_wrapper_xlib
+#define XSetWMSizeHints XSetWMSizeHints_dylibloader_wrapper_xlib
+#define XSetRegion XSetRegion_dylibloader_wrapper_xlib
+#define XSetStandardColormap XSetStandardColormap_dylibloader_wrapper_xlib
+#define XSetZoomHints XSetZoomHints_dylibloader_wrapper_xlib
+#define XShrinkRegion XShrinkRegion_dylibloader_wrapper_xlib
+#define XStringListToTextProperty XStringListToTextProperty_dylibloader_wrapper_xlib
+#define XSubtractRegion XSubtractRegion_dylibloader_wrapper_xlib
+#define XmbTextListToTextProperty XmbTextListToTextProperty_dylibloader_wrapper_xlib
+#define XwcTextListToTextProperty XwcTextListToTextProperty_dylibloader_wrapper_xlib
+#define Xutf8TextListToTextProperty Xutf8TextListToTextProperty_dylibloader_wrapper_xlib
+#define XwcFreeStringList XwcFreeStringList_dylibloader_wrapper_xlib
+#define XTextPropertyToStringList XTextPropertyToStringList_dylibloader_wrapper_xlib
+#define XmbTextPropertyToTextList XmbTextPropertyToTextList_dylibloader_wrapper_xlib
+#define XwcTextPropertyToTextList XwcTextPropertyToTextList_dylibloader_wrapper_xlib
+#define Xutf8TextPropertyToTextList Xutf8TextPropertyToTextList_dylibloader_wrapper_xlib
+#define XUnionRectWithRegion XUnionRectWithRegion_dylibloader_wrapper_xlib
+#define XUnionRegion XUnionRegion_dylibloader_wrapper_xlib
+#define XWMGeometry XWMGeometry_dylibloader_wrapper_xlib
+#define XXorRegion XXorRegion_dylibloader_wrapper_xlib
+#define XkbIgnoreExtension XkbIgnoreExtension_dylibloader_wrapper_xlib
+#define XkbOpenDisplay XkbOpenDisplay_dylibloader_wrapper_xlib
+#define XkbQueryExtension XkbQueryExtension_dylibloader_wrapper_xlib
+#define XkbUseExtension XkbUseExtension_dylibloader_wrapper_xlib
+#define XkbLibraryVersion XkbLibraryVersion_dylibloader_wrapper_xlib
+#define XkbSetXlibControls XkbSetXlibControls_dylibloader_wrapper_xlib
+#define XkbGetXlibControls XkbGetXlibControls_dylibloader_wrapper_xlib
+#define XkbXlibControlsImplemented XkbXlibControlsImplemented_dylibloader_wrapper_xlib
+#define XkbSetAtomFuncs XkbSetAtomFuncs_dylibloader_wrapper_xlib
+#define XkbKeycodeToKeysym XkbKeycodeToKeysym_dylibloader_wrapper_xlib
+#define XkbKeysymToModifiers XkbKeysymToModifiers_dylibloader_wrapper_xlib
+#define XkbLookupKeySym XkbLookupKeySym_dylibloader_wrapper_xlib
+#define XkbLookupKeyBinding XkbLookupKeyBinding_dylibloader_wrapper_xlib
+#define XkbTranslateKeyCode XkbTranslateKeyCode_dylibloader_wrapper_xlib
+#define XkbTranslateKeySym XkbTranslateKeySym_dylibloader_wrapper_xlib
+#define XkbSetAutoRepeatRate XkbSetAutoRepeatRate_dylibloader_wrapper_xlib
+#define XkbGetAutoRepeatRate XkbGetAutoRepeatRate_dylibloader_wrapper_xlib
+#define XkbChangeEnabledControls XkbChangeEnabledControls_dylibloader_wrapper_xlib
+#define XkbDeviceBell XkbDeviceBell_dylibloader_wrapper_xlib
+#define XkbForceDeviceBell XkbForceDeviceBell_dylibloader_wrapper_xlib
+#define XkbDeviceBellEvent XkbDeviceBellEvent_dylibloader_wrapper_xlib
+#define XkbBell XkbBell_dylibloader_wrapper_xlib
+#define XkbForceBell XkbForceBell_dylibloader_wrapper_xlib
+#define XkbBellEvent XkbBellEvent_dylibloader_wrapper_xlib
+#define XkbSelectEvents XkbSelectEvents_dylibloader_wrapper_xlib
+#define XkbSelectEventDetails XkbSelectEventDetails_dylibloader_wrapper_xlib
+#define XkbNoteMapChanges XkbNoteMapChanges_dylibloader_wrapper_xlib
+#define XkbNoteNameChanges XkbNoteNameChanges_dylibloader_wrapper_xlib
+#define XkbGetIndicatorState XkbGetIndicatorState_dylibloader_wrapper_xlib
+#define XkbGetIndicatorMap XkbGetIndicatorMap_dylibloader_wrapper_xlib
+#define XkbSetIndicatorMap XkbSetIndicatorMap_dylibloader_wrapper_xlib
+#define XkbGetNamedIndicator XkbGetNamedIndicator_dylibloader_wrapper_xlib
+#define XkbGetNamedDeviceIndicator XkbGetNamedDeviceIndicator_dylibloader_wrapper_xlib
+#define XkbSetNamedIndicator XkbSetNamedIndicator_dylibloader_wrapper_xlib
+#define XkbSetNamedDeviceIndicator XkbSetNamedDeviceIndicator_dylibloader_wrapper_xlib
+#define XkbLockModifiers XkbLockModifiers_dylibloader_wrapper_xlib
+#define XkbLatchModifiers XkbLatchModifiers_dylibloader_wrapper_xlib
+#define XkbLockGroup XkbLockGroup_dylibloader_wrapper_xlib
+#define XkbLatchGroup XkbLatchGroup_dylibloader_wrapper_xlib
+#define XkbSetServerInternalMods XkbSetServerInternalMods_dylibloader_wrapper_xlib
+#define XkbSetIgnoreLockMods XkbSetIgnoreLockMods_dylibloader_wrapper_xlib
+#define XkbVirtualModsToReal XkbVirtualModsToReal_dylibloader_wrapper_xlib
+#define XkbComputeEffectiveMap XkbComputeEffectiveMap_dylibloader_wrapper_xlib
+#define XkbInitCanonicalKeyTypes XkbInitCanonicalKeyTypes_dylibloader_wrapper_xlib
+#define XkbAllocKeyboard XkbAllocKeyboard_dylibloader_wrapper_xlib
+#define XkbFreeKeyboard XkbFreeKeyboard_dylibloader_wrapper_xlib
+#define XkbAllocClientMap XkbAllocClientMap_dylibloader_wrapper_xlib
+#define XkbAllocServerMap XkbAllocServerMap_dylibloader_wrapper_xlib
+#define XkbFreeClientMap XkbFreeClientMap_dylibloader_wrapper_xlib
+#define XkbFreeServerMap XkbFreeServerMap_dylibloader_wrapper_xlib
+#define XkbAddKeyType XkbAddKeyType_dylibloader_wrapper_xlib
+#define XkbAllocIndicatorMaps XkbAllocIndicatorMaps_dylibloader_wrapper_xlib
+#define XkbFreeIndicatorMaps XkbFreeIndicatorMaps_dylibloader_wrapper_xlib
+#define XkbGetMap XkbGetMap_dylibloader_wrapper_xlib
+#define XkbGetUpdatedMap XkbGetUpdatedMap_dylibloader_wrapper_xlib
+#define XkbGetMapChanges XkbGetMapChanges_dylibloader_wrapper_xlib
+#define XkbRefreshKeyboardMapping XkbRefreshKeyboardMapping_dylibloader_wrapper_xlib
+#define XkbGetKeyTypes XkbGetKeyTypes_dylibloader_wrapper_xlib
+#define XkbGetKeySyms XkbGetKeySyms_dylibloader_wrapper_xlib
+#define XkbGetKeyActions XkbGetKeyActions_dylibloader_wrapper_xlib
+#define XkbGetKeyBehaviors XkbGetKeyBehaviors_dylibloader_wrapper_xlib
+#define XkbGetVirtualMods XkbGetVirtualMods_dylibloader_wrapper_xlib
+#define XkbGetKeyExplicitComponents XkbGetKeyExplicitComponents_dylibloader_wrapper_xlib
+#define XkbGetKeyModifierMap XkbGetKeyModifierMap_dylibloader_wrapper_xlib
+#define XkbGetKeyVirtualModMap XkbGetKeyVirtualModMap_dylibloader_wrapper_xlib
+#define XkbAllocControls XkbAllocControls_dylibloader_wrapper_xlib
+#define XkbFreeControls XkbFreeControls_dylibloader_wrapper_xlib
+#define XkbGetControls XkbGetControls_dylibloader_wrapper_xlib
+#define XkbSetControls XkbSetControls_dylibloader_wrapper_xlib
+#define XkbNoteControlsChanges XkbNoteControlsChanges_dylibloader_wrapper_xlib
+#define XkbAllocCompatMap XkbAllocCompatMap_dylibloader_wrapper_xlib
+#define XkbFreeCompatMap XkbFreeCompatMap_dylibloader_wrapper_xlib
+#define XkbGetCompatMap XkbGetCompatMap_dylibloader_wrapper_xlib
+#define XkbSetCompatMap XkbSetCompatMap_dylibloader_wrapper_xlib
+#define XkbAllocNames XkbAllocNames_dylibloader_wrapper_xlib
+#define XkbGetNames XkbGetNames_dylibloader_wrapper_xlib
+#define XkbSetNames XkbSetNames_dylibloader_wrapper_xlib
+#define XkbChangeNames XkbChangeNames_dylibloader_wrapper_xlib
+#define XkbFreeNames XkbFreeNames_dylibloader_wrapper_xlib
+#define XkbGetState XkbGetState_dylibloader_wrapper_xlib
+#define XkbSetMap XkbSetMap_dylibloader_wrapper_xlib
+#define XkbChangeMap XkbChangeMap_dylibloader_wrapper_xlib
+#define XkbSetDetectableAutoRepeat XkbSetDetectableAutoRepeat_dylibloader_wrapper_xlib
+#define XkbGetDetectableAutoRepeat XkbGetDetectableAutoRepeat_dylibloader_wrapper_xlib
+#define XkbSetAutoResetControls XkbSetAutoResetControls_dylibloader_wrapper_xlib
+#define XkbGetAutoResetControls XkbGetAutoResetControls_dylibloader_wrapper_xlib
+#define XkbSetPerClientControls XkbSetPerClientControls_dylibloader_wrapper_xlib
+#define XkbGetPerClientControls XkbGetPerClientControls_dylibloader_wrapper_xlib
+#define XkbCopyKeyType XkbCopyKeyType_dylibloader_wrapper_xlib
+#define XkbCopyKeyTypes XkbCopyKeyTypes_dylibloader_wrapper_xlib
+#define XkbResizeKeyType XkbResizeKeyType_dylibloader_wrapper_xlib
+#define XkbResizeKeySyms XkbResizeKeySyms_dylibloader_wrapper_xlib
+#define XkbResizeKeyActions XkbResizeKeyActions_dylibloader_wrapper_xlib
+#define XkbChangeTypesOfKey XkbChangeTypesOfKey_dylibloader_wrapper_xlib
+#define XkbChangeKeycodeRange XkbChangeKeycodeRange_dylibloader_wrapper_xlib
+#define XkbListComponents XkbListComponents_dylibloader_wrapper_xlib
+#define XkbFreeComponentList XkbFreeComponentList_dylibloader_wrapper_xlib
+#define XkbGetKeyboard XkbGetKeyboard_dylibloader_wrapper_xlib
+#define XkbGetKeyboardByName XkbGetKeyboardByName_dylibloader_wrapper_xlib
+#define XkbKeyTypesForCoreSymbols XkbKeyTypesForCoreSymbols_dylibloader_wrapper_xlib
+#define XkbApplyCompatMapToKey XkbApplyCompatMapToKey_dylibloader_wrapper_xlib
+#define XkbUpdateMapFromCore XkbUpdateMapFromCore_dylibloader_wrapper_xlib
+#define XkbAddDeviceLedInfo XkbAddDeviceLedInfo_dylibloader_wrapper_xlib
+#define XkbResizeDeviceButtonActions XkbResizeDeviceButtonActions_dylibloader_wrapper_xlib
+#define XkbAllocDeviceInfo XkbAllocDeviceInfo_dylibloader_wrapper_xlib
+#define XkbFreeDeviceInfo XkbFreeDeviceInfo_dylibloader_wrapper_xlib
+#define XkbNoteDeviceChanges XkbNoteDeviceChanges_dylibloader_wrapper_xlib
+#define XkbGetDeviceInfo XkbGetDeviceInfo_dylibloader_wrapper_xlib
+#define XkbGetDeviceInfoChanges XkbGetDeviceInfoChanges_dylibloader_wrapper_xlib
+#define XkbGetDeviceButtonActions XkbGetDeviceButtonActions_dylibloader_wrapper_xlib
+#define XkbGetDeviceLedInfo XkbGetDeviceLedInfo_dylibloader_wrapper_xlib
+#define XkbSetDeviceInfo XkbSetDeviceInfo_dylibloader_wrapper_xlib
+#define XkbChangeDeviceInfo XkbChangeDeviceInfo_dylibloader_wrapper_xlib
+#define XkbSetDeviceLedInfo XkbSetDeviceLedInfo_dylibloader_wrapper_xlib
+#define XkbSetDeviceButtonActions XkbSetDeviceButtonActions_dylibloader_wrapper_xlib
+#define XkbToControl XkbToControl_dylibloader_wrapper_xlib
+#define XkbSetDebuggingFlags XkbSetDebuggingFlags_dylibloader_wrapper_xlib
+#define XkbApplyVirtualModChanges XkbApplyVirtualModChanges_dylibloader_wrapper_xlib
+#define XkbUpdateActionVirtualMods XkbUpdateActionVirtualMods_dylibloader_wrapper_xlib
+#define XkbUpdateKeyTypeVirtualMods XkbUpdateKeyTypeVirtualMods_dylibloader_wrapper_xlib
+extern int (*_Xmblen_dylibloader_wrapper_xlib)( char*, int);
+extern XFontStruct* (*XLoadQueryFont_dylibloader_wrapper_xlib)( Display*,const char*);
+extern XFontStruct* (*XQueryFont_dylibloader_wrapper_xlib)( Display*, XID);
+extern XTimeCoord* (*XGetMotionEvents_dylibloader_wrapper_xlib)( Display*, Window, Time, Time, int*);
+extern XModifierKeymap* (*XDeleteModifiermapEntry_dylibloader_wrapper_xlib)( XModifierKeymap*, KeyCode, int);
+extern XModifierKeymap* (*XGetModifierMapping_dylibloader_wrapper_xlib)( Display*);
+extern XModifierKeymap* (*XInsertModifiermapEntry_dylibloader_wrapper_xlib)( XModifierKeymap*, KeyCode, int);
+extern XModifierKeymap* (*XNewModifiermap_dylibloader_wrapper_xlib)( int);
+extern XImage* (*XCreateImage_dylibloader_wrapper_xlib)( Display*, Visual*, unsigned int, int, int, char*, unsigned int, unsigned int, int, int);
+extern int (*XInitImage_dylibloader_wrapper_xlib)( XImage*);
+extern XImage* (*XGetImage_dylibloader_wrapper_xlib)( Display*, Drawable, int, int, unsigned int, unsigned int, unsigned long, int);
+extern XImage* (*XGetSubImage_dylibloader_wrapper_xlib)( Display*, Drawable, int, int, unsigned int, unsigned int, unsigned long, int, XImage*, int, int);
+extern Display* (*XOpenDisplay_dylibloader_wrapper_xlib)(const char*);
+extern void (*XrmInitialize_dylibloader_wrapper_xlib)( void);
+extern char* (*XFetchBytes_dylibloader_wrapper_xlib)( Display*, int*);
+extern char* (*XFetchBuffer_dylibloader_wrapper_xlib)( Display*, int*, int);
+extern char* (*XGetAtomName_dylibloader_wrapper_xlib)( Display*, Atom);
+extern int (*XGetAtomNames_dylibloader_wrapper_xlib)( Display*, Atom*, int, char**);
+extern char* (*XGetDefault_dylibloader_wrapper_xlib)( Display*,const char*,const char*);
+extern char* (*XDisplayName_dylibloader_wrapper_xlib)(const char*);
+extern char* (*XKeysymToString_dylibloader_wrapper_xlib)( KeySym);
+extern int* (*XSynchronize_dylibloader_wrapper_xlib)( Display*, int);
+extern int* (*XSetAfterFunction_dylibloader_wrapper_xlib)( Display*, int*);
+extern Atom (*XInternAtom_dylibloader_wrapper_xlib)( Display*,const char*, int);
+extern int (*XInternAtoms_dylibloader_wrapper_xlib)( Display*, char**, int, int, Atom*);
+extern Colormap (*XCopyColormapAndFree_dylibloader_wrapper_xlib)( Display*, Colormap);
+extern Colormap (*XCreateColormap_dylibloader_wrapper_xlib)( Display*, Window, Visual*, int);
+extern Cursor (*XCreatePixmapCursor_dylibloader_wrapper_xlib)( Display*, Pixmap, Pixmap, XColor*, XColor*, unsigned int, unsigned int);
+extern Cursor (*XCreateGlyphCursor_dylibloader_wrapper_xlib)( Display*, Font, Font, unsigned int, unsigned int,const XColor*,const XColor*);
+extern Cursor (*XCreateFontCursor_dylibloader_wrapper_xlib)( Display*, unsigned int);
+extern Font (*XLoadFont_dylibloader_wrapper_xlib)( Display*,const char*);
+extern GC (*XCreateGC_dylibloader_wrapper_xlib)( Display*, Drawable, unsigned long, XGCValues*);
+extern GContext (*XGContextFromGC_dylibloader_wrapper_xlib)( GC);
+extern void (*XFlushGC_dylibloader_wrapper_xlib)( Display*, GC);
+extern Pixmap (*XCreatePixmap_dylibloader_wrapper_xlib)( Display*, Drawable, unsigned int, unsigned int, unsigned int);
+extern Pixmap (*XCreateBitmapFromData_dylibloader_wrapper_xlib)( Display*, Drawable,const char*, unsigned int, unsigned int);
+extern Pixmap (*XCreatePixmapFromBitmapData_dylibloader_wrapper_xlib)( Display*, Drawable, char*, unsigned int, unsigned int, unsigned long, unsigned long, unsigned int);
+extern Window (*XCreateSimpleWindow_dylibloader_wrapper_xlib)( Display*, Window, int, int, unsigned int, unsigned int, unsigned int, unsigned long, unsigned long);
+extern Window (*XGetSelectionOwner_dylibloader_wrapper_xlib)( Display*, Atom);
+extern Window (*XCreateWindow_dylibloader_wrapper_xlib)( Display*, Window, int, int, unsigned int, unsigned int, unsigned int, int, unsigned int, Visual*, unsigned long, XSetWindowAttributes*);
+extern Colormap* (*XListInstalledColormaps_dylibloader_wrapper_xlib)( Display*, Window, int*);
+extern char** (*XListFonts_dylibloader_wrapper_xlib)( Display*,const char*, int, int*);
+extern char** (*XListFontsWithInfo_dylibloader_wrapper_xlib)( Display*,const char*, int, int*, XFontStruct**);
+extern char** (*XGetFontPath_dylibloader_wrapper_xlib)( Display*, int*);
+extern char** (*XListExtensions_dylibloader_wrapper_xlib)( Display*, int*);
+extern Atom* (*XListProperties_dylibloader_wrapper_xlib)( Display*, Window, int*);
+extern XHostAddress* (*XListHosts_dylibloader_wrapper_xlib)( Display*, int*, int*);
+extern KeySym (*XKeycodeToKeysym_dylibloader_wrapper_xlib)( Display*, KeyCode, int);
+extern KeySym (*XLookupKeysym_dylibloader_wrapper_xlib)( XKeyEvent*, int);
+extern KeySym* (*XGetKeyboardMapping_dylibloader_wrapper_xlib)( Display*, KeyCode, int, int*);
+extern KeySym (*XStringToKeysym_dylibloader_wrapper_xlib)(const char*);
+extern long (*XMaxRequestSize_dylibloader_wrapper_xlib)( Display*);
+extern long (*XExtendedMaxRequestSize_dylibloader_wrapper_xlib)( Display*);
+extern char* (*XResourceManagerString_dylibloader_wrapper_xlib)( Display*);
+extern char* (*XScreenResourceString_dylibloader_wrapper_xlib)( Screen*);
+extern unsigned long (*XDisplayMotionBufferSize_dylibloader_wrapper_xlib)( Display*);
+extern VisualID (*XVisualIDFromVisual_dylibloader_wrapper_xlib)( Visual*);
+extern int (*XInitThreads_dylibloader_wrapper_xlib)( void);
+extern void (*XLockDisplay_dylibloader_wrapper_xlib)( Display*);
+extern void (*XUnlockDisplay_dylibloader_wrapper_xlib)( Display*);
+extern XExtCodes* (*XInitExtension_dylibloader_wrapper_xlib)( Display*,const char*);
+extern XExtCodes* (*XAddExtension_dylibloader_wrapper_xlib)( Display*);
+extern XExtData* (*XFindOnExtensionList_dylibloader_wrapper_xlib)( XExtData**, int);
+extern XExtData** (*XEHeadOfExtensionList_dylibloader_wrapper_xlib)( XEDataObject);
+extern Window (*XRootWindow_dylibloader_wrapper_xlib)( Display*, int);
+extern Window (*XDefaultRootWindow_dylibloader_wrapper_xlib)( Display*);
+extern Window (*XRootWindowOfScreen_dylibloader_wrapper_xlib)( Screen*);
+extern Visual* (*XDefaultVisual_dylibloader_wrapper_xlib)( Display*, int);
+extern Visual* (*XDefaultVisualOfScreen_dylibloader_wrapper_xlib)( Screen*);
+extern GC (*XDefaultGC_dylibloader_wrapper_xlib)( Display*, int);
+extern GC (*XDefaultGCOfScreen_dylibloader_wrapper_xlib)( Screen*);
+extern unsigned long (*XBlackPixel_dylibloader_wrapper_xlib)( Display*, int);
+extern unsigned long (*XWhitePixel_dylibloader_wrapper_xlib)( Display*, int);
+extern unsigned long (*XAllPlanes_dylibloader_wrapper_xlib)( void);
+extern unsigned long (*XBlackPixelOfScreen_dylibloader_wrapper_xlib)( Screen*);
+extern unsigned long (*XWhitePixelOfScreen_dylibloader_wrapper_xlib)( Screen*);
+extern unsigned long (*XNextRequest_dylibloader_wrapper_xlib)( Display*);
+extern unsigned long (*XLastKnownRequestProcessed_dylibloader_wrapper_xlib)( Display*);
+extern char* (*XServerVendor_dylibloader_wrapper_xlib)( Display*);
+extern char* (*XDisplayString_dylibloader_wrapper_xlib)( Display*);
+extern Colormap (*XDefaultColormap_dylibloader_wrapper_xlib)( Display*, int);
+extern Colormap (*XDefaultColormapOfScreen_dylibloader_wrapper_xlib)( Screen*);
+extern Display* (*XDisplayOfScreen_dylibloader_wrapper_xlib)( Screen*);
+extern Screen* (*XScreenOfDisplay_dylibloader_wrapper_xlib)( Display*, int);
+extern Screen* (*XDefaultScreenOfDisplay_dylibloader_wrapper_xlib)( Display*);
+extern long (*XEventMaskOfScreen_dylibloader_wrapper_xlib)( Screen*);
+extern int (*XScreenNumberOfScreen_dylibloader_wrapper_xlib)( Screen*);
+extern XErrorHandler (*XSetErrorHandler_dylibloader_wrapper_xlib)( XErrorHandler);
+extern XIOErrorHandler (*XSetIOErrorHandler_dylibloader_wrapper_xlib)( XIOErrorHandler);
+extern XPixmapFormatValues* (*XListPixmapFormats_dylibloader_wrapper_xlib)( Display*, int*);
+extern int* (*XListDepths_dylibloader_wrapper_xlib)( Display*, int, int*);
+extern int (*XReconfigureWMWindow_dylibloader_wrapper_xlib)( Display*, Window, int, unsigned int, XWindowChanges*);
+extern int (*XGetWMProtocols_dylibloader_wrapper_xlib)( Display*, Window, Atom**, int*);
+extern int (*XSetWMProtocols_dylibloader_wrapper_xlib)( Display*, Window, Atom*, int);
+extern int (*XIconifyWindow_dylibloader_wrapper_xlib)( Display*, Window, int);
+extern int (*XWithdrawWindow_dylibloader_wrapper_xlib)( Display*, Window, int);
+extern int (*XGetCommand_dylibloader_wrapper_xlib)( Display*, Window, char***, int*);
+extern int (*XGetWMColormapWindows_dylibloader_wrapper_xlib)( Display*, Window, Window**, int*);
+extern int (*XSetWMColormapWindows_dylibloader_wrapper_xlib)( Display*, Window, Window*, int);
+extern void (*XFreeStringList_dylibloader_wrapper_xlib)( char**);
+extern int (*XSetTransientForHint_dylibloader_wrapper_xlib)( Display*, Window, Window);
+extern int (*XActivateScreenSaver_dylibloader_wrapper_xlib)( Display*);
+extern int (*XAddHost_dylibloader_wrapper_xlib)( Display*, XHostAddress*);
+extern int (*XAddHosts_dylibloader_wrapper_xlib)( Display*, XHostAddress*, int);
+extern int (*XAddToExtensionList_dylibloader_wrapper_xlib)(struct _XExtData**, XExtData*);
+extern int (*XAddToSaveSet_dylibloader_wrapper_xlib)( Display*, Window);
+extern int (*XAllocColor_dylibloader_wrapper_xlib)( Display*, Colormap, XColor*);
+extern int (*XAllocColorCells_dylibloader_wrapper_xlib)( Display*, Colormap, int, unsigned long*, unsigned int, unsigned long*, unsigned int);
+extern int (*XAllocColorPlanes_dylibloader_wrapper_xlib)( Display*, Colormap, int, unsigned long*, int, int, int, int, unsigned long*, unsigned long*, unsigned long*);
+extern int (*XAllocNamedColor_dylibloader_wrapper_xlib)( Display*, Colormap,const char*, XColor*, XColor*);
+extern int (*XAllowEvents_dylibloader_wrapper_xlib)( Display*, int, Time);
+extern int (*XAutoRepeatOff_dylibloader_wrapper_xlib)( Display*);
+extern int (*XAutoRepeatOn_dylibloader_wrapper_xlib)( Display*);
+extern int (*XBell_dylibloader_wrapper_xlib)( Display*, int);
+extern int (*XBitmapBitOrder_dylibloader_wrapper_xlib)( Display*);
+extern int (*XBitmapPad_dylibloader_wrapper_xlib)( Display*);
+extern int (*XBitmapUnit_dylibloader_wrapper_xlib)( Display*);
+extern int (*XCellsOfScreen_dylibloader_wrapper_xlib)( Screen*);
+extern int (*XChangeActivePointerGrab_dylibloader_wrapper_xlib)( Display*, unsigned int, Cursor, Time);
+extern int (*XChangeGC_dylibloader_wrapper_xlib)( Display*, GC, unsigned long, XGCValues*);
+extern int (*XChangeKeyboardControl_dylibloader_wrapper_xlib)( Display*, unsigned long, XKeyboardControl*);
+extern int (*XChangeKeyboardMapping_dylibloader_wrapper_xlib)( Display*, int, int, KeySym*, int);
+extern int (*XChangePointerControl_dylibloader_wrapper_xlib)( Display*, int, int, int, int, int);
+extern int (*XChangeProperty_dylibloader_wrapper_xlib)( Display*, Window, Atom, Atom, int, int,const unsigned char*, int);
+extern int (*XChangeSaveSet_dylibloader_wrapper_xlib)( Display*, Window, int);
+extern int (*XChangeWindowAttributes_dylibloader_wrapper_xlib)( Display*, Window, unsigned long, XSetWindowAttributes*);
+extern int (*XCheckIfEvent_dylibloader_wrapper_xlib)( Display*, XEvent*, Bool (*) (Display*, XEvent*, XPointer), XPointer);
+extern int (*XCheckMaskEvent_dylibloader_wrapper_xlib)( Display*, long, XEvent*);
+extern int (*XCheckTypedEvent_dylibloader_wrapper_xlib)( Display*, int, XEvent*);
+extern int (*XCheckTypedWindowEvent_dylibloader_wrapper_xlib)( Display*, Window, int, XEvent*);
+extern int (*XCheckWindowEvent_dylibloader_wrapper_xlib)( Display*, Window, long, XEvent*);
+extern int (*XCirculateSubwindows_dylibloader_wrapper_xlib)( Display*, Window, int);
+extern int (*XCirculateSubwindowsDown_dylibloader_wrapper_xlib)( Display*, Window);
+extern int (*XCirculateSubwindowsUp_dylibloader_wrapper_xlib)( Display*, Window);
+extern int (*XClearArea_dylibloader_wrapper_xlib)( Display*, Window, int, int, unsigned int, unsigned int, int);
+extern int (*XClearWindow_dylibloader_wrapper_xlib)( Display*, Window);
+extern int (*XCloseDisplay_dylibloader_wrapper_xlib)( Display*);
+extern int (*XConfigureWindow_dylibloader_wrapper_xlib)( Display*, Window, unsigned int, XWindowChanges*);
+extern int (*XConnectionNumber_dylibloader_wrapper_xlib)( Display*);
+extern int (*XConvertSelection_dylibloader_wrapper_xlib)( Display*, Atom, Atom, Atom, Window, Time);
+extern int (*XCopyArea_dylibloader_wrapper_xlib)( Display*, Drawable, Drawable, GC, int, int, unsigned int, unsigned int, int, int);
+extern int (*XCopyGC_dylibloader_wrapper_xlib)( Display*, GC, unsigned long, GC);
+extern int (*XCopyPlane_dylibloader_wrapper_xlib)( Display*, Drawable, Drawable, GC, int, int, unsigned int, unsigned int, int, int, unsigned long);
+extern int (*XDefaultDepth_dylibloader_wrapper_xlib)( Display*, int);
+extern int (*XDefaultDepthOfScreen_dylibloader_wrapper_xlib)( Screen*);
+extern int (*XDefaultScreen_dylibloader_wrapper_xlib)( Display*);
+extern int (*XDefineCursor_dylibloader_wrapper_xlib)( Display*, Window, Cursor);
+extern int (*XDeleteProperty_dylibloader_wrapper_xlib)( Display*, Window, Atom);
+extern int (*XDestroyWindow_dylibloader_wrapper_xlib)( Display*, Window);
+extern int (*XDestroySubwindows_dylibloader_wrapper_xlib)( Display*, Window);
+extern int (*XDoesBackingStore_dylibloader_wrapper_xlib)( Screen*);
+extern int (*XDoesSaveUnders_dylibloader_wrapper_xlib)( Screen*);
+extern int (*XDisableAccessControl_dylibloader_wrapper_xlib)( Display*);
+extern int (*XDisplayCells_dylibloader_wrapper_xlib)( Display*, int);
+extern int (*XDisplayHeight_dylibloader_wrapper_xlib)( Display*, int);
+extern int (*XDisplayHeightMM_dylibloader_wrapper_xlib)( Display*, int);
+extern int (*XDisplayKeycodes_dylibloader_wrapper_xlib)( Display*, int*, int*);
+extern int (*XDisplayPlanes_dylibloader_wrapper_xlib)( Display*, int);
+extern int (*XDisplayWidth_dylibloader_wrapper_xlib)( Display*, int);
+extern int (*XDisplayWidthMM_dylibloader_wrapper_xlib)( Display*, int);
+extern int (*XDrawArc_dylibloader_wrapper_xlib)( Display*, Drawable, GC, int, int, unsigned int, unsigned int, int, int);
+extern int (*XDrawArcs_dylibloader_wrapper_xlib)( Display*, Drawable, GC, XArc*, int);
+extern int (*XDrawImageString_dylibloader_wrapper_xlib)( Display*, Drawable, GC, int, int,const char*, int);
+extern int (*XDrawImageString16_dylibloader_wrapper_xlib)( Display*, Drawable, GC, int, int,const XChar2b*, int);
+extern int (*XDrawLine_dylibloader_wrapper_xlib)( Display*, Drawable, GC, int, int, int, int);
+extern int (*XDrawLines_dylibloader_wrapper_xlib)( Display*, Drawable, GC, XPoint*, int, int);
+extern int (*XDrawPoint_dylibloader_wrapper_xlib)( Display*, Drawable, GC, int, int);
+extern int (*XDrawPoints_dylibloader_wrapper_xlib)( Display*, Drawable, GC, XPoint*, int, int);
+extern int (*XDrawRectangle_dylibloader_wrapper_xlib)( Display*, Drawable, GC, int, int, unsigned int, unsigned int);
+extern int (*XDrawRectangles_dylibloader_wrapper_xlib)( Display*, Drawable, GC, XRectangle*, int);
+extern int (*XDrawSegments_dylibloader_wrapper_xlib)( Display*, Drawable, GC, XSegment*, int);
+extern int (*XDrawString_dylibloader_wrapper_xlib)( Display*, Drawable, GC, int, int,const char*, int);
+extern int (*XDrawString16_dylibloader_wrapper_xlib)( Display*, Drawable, GC, int, int,const XChar2b*, int);
+extern int (*XDrawText_dylibloader_wrapper_xlib)( Display*, Drawable, GC, int, int, XTextItem*, int);
+extern int (*XDrawText16_dylibloader_wrapper_xlib)( Display*, Drawable, GC, int, int, XTextItem16*, int);
+extern int (*XEnableAccessControl_dylibloader_wrapper_xlib)( Display*);
+extern int (*XEventsQueued_dylibloader_wrapper_xlib)( Display*, int);
+extern int (*XFetchName_dylibloader_wrapper_xlib)( Display*, Window, char**);
+extern int (*XFillArc_dylibloader_wrapper_xlib)( Display*, Drawable, GC, int, int, unsigned int, unsigned int, int, int);
+extern int (*XFillArcs_dylibloader_wrapper_xlib)( Display*, Drawable, GC, XArc*, int);
+extern int (*XFillPolygon_dylibloader_wrapper_xlib)( Display*, Drawable, GC, XPoint*, int, int, int);
+extern int (*XFillRectangle_dylibloader_wrapper_xlib)( Display*, Drawable, GC, int, int, unsigned int, unsigned int);
+extern int (*XFillRectangles_dylibloader_wrapper_xlib)( Display*, Drawable, GC, XRectangle*, int);
+extern int (*XFlush_dylibloader_wrapper_xlib)( Display*);
+extern int (*XForceScreenSaver_dylibloader_wrapper_xlib)( Display*, int);
+extern int (*XFree_dylibloader_wrapper_xlib)( void*);
+extern int (*XFreeColormap_dylibloader_wrapper_xlib)( Display*, Colormap);
+extern int (*XFreeColors_dylibloader_wrapper_xlib)( Display*, Colormap, unsigned long*, int, unsigned long);
+extern int (*XFreeCursor_dylibloader_wrapper_xlib)( Display*, Cursor);
+extern int (*XFreeExtensionList_dylibloader_wrapper_xlib)( char**);
+extern int (*XFreeFont_dylibloader_wrapper_xlib)( Display*, XFontStruct*);
+extern int (*XFreeFontInfo_dylibloader_wrapper_xlib)( char**, XFontStruct*, int);
+extern int (*XFreeFontNames_dylibloader_wrapper_xlib)( char**);
+extern int (*XFreeFontPath_dylibloader_wrapper_xlib)( char**);
+extern int (*XFreeGC_dylibloader_wrapper_xlib)( Display*, GC);
+extern int (*XFreeModifiermap_dylibloader_wrapper_xlib)( XModifierKeymap*);
+extern int (*XFreePixmap_dylibloader_wrapper_xlib)( Display*, Pixmap);
+extern int (*XGeometry_dylibloader_wrapper_xlib)( Display*, int,const char*,const char*, unsigned int, unsigned int, unsigned int, int, int, int*, int*, int*, int*);
+extern int (*XGetErrorDatabaseText_dylibloader_wrapper_xlib)( Display*,const char*,const char*,const char*, char*, int);
+extern int (*XGetErrorText_dylibloader_wrapper_xlib)( Display*, int, char*, int);
+extern int (*XGetFontProperty_dylibloader_wrapper_xlib)( XFontStruct*, Atom, unsigned long*);
+extern int (*XGetGCValues_dylibloader_wrapper_xlib)( Display*, GC, unsigned long, XGCValues*);
+extern int (*XGetGeometry_dylibloader_wrapper_xlib)( Display*, Drawable, Window*, int*, int*, unsigned int*, unsigned int*, unsigned int*, unsigned int*);
+extern int (*XGetIconName_dylibloader_wrapper_xlib)( Display*, Window, char**);
+extern int (*XGetInputFocus_dylibloader_wrapper_xlib)( Display*, Window*, int*);
+extern int (*XGetKeyboardControl_dylibloader_wrapper_xlib)( Display*, XKeyboardState*);
+extern int (*XGetPointerControl_dylibloader_wrapper_xlib)( Display*, int*, int*, int*);
+extern int (*XGetPointerMapping_dylibloader_wrapper_xlib)( Display*, unsigned char*, int);
+extern int (*XGetScreenSaver_dylibloader_wrapper_xlib)( Display*, int*, int*, int*, int*);
+extern int (*XGetTransientForHint_dylibloader_wrapper_xlib)( Display*, Window, Window*);
+extern int (*XGetWindowProperty_dylibloader_wrapper_xlib)( Display*, Window, Atom, long, long, int, Atom, Atom*, int*, unsigned long*, unsigned long*, unsigned char**);
+extern int (*XGetWindowAttributes_dylibloader_wrapper_xlib)( Display*, Window, XWindowAttributes*);
+extern int (*XGrabButton_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, Window, int, unsigned int, int, int, Window, Cursor);
+extern int (*XGrabKey_dylibloader_wrapper_xlib)( Display*, int, unsigned int, Window, int, int, int);
+extern int (*XGrabKeyboard_dylibloader_wrapper_xlib)( Display*, Window, int, int, int, Time);
+extern int (*XGrabPointer_dylibloader_wrapper_xlib)( Display*, Window, int, unsigned int, int, int, Window, Cursor, Time);
+extern int (*XGrabServer_dylibloader_wrapper_xlib)( Display*);
+extern int (*XHeightMMOfScreen_dylibloader_wrapper_xlib)( Screen*);
+extern int (*XHeightOfScreen_dylibloader_wrapper_xlib)( Screen*);
+extern int (*XIfEvent_dylibloader_wrapper_xlib)( Display*, XEvent*, Bool (*) (Display*, XEvent*, XPointer), XPointer);
+extern int (*XImageByteOrder_dylibloader_wrapper_xlib)( Display*);
+extern int (*XInstallColormap_dylibloader_wrapper_xlib)( Display*, Colormap);
+extern KeyCode (*XKeysymToKeycode_dylibloader_wrapper_xlib)( Display*, KeySym);
+extern int (*XKillClient_dylibloader_wrapper_xlib)( Display*, XID);
+extern int (*XLookupColor_dylibloader_wrapper_xlib)( Display*, Colormap,const char*, XColor*, XColor*);
+extern int (*XLowerWindow_dylibloader_wrapper_xlib)( Display*, Window);
+extern int (*XMapRaised_dylibloader_wrapper_xlib)( Display*, Window);
+extern int (*XMapSubwindows_dylibloader_wrapper_xlib)( Display*, Window);
+extern int (*XMapWindow_dylibloader_wrapper_xlib)( Display*, Window);
+extern int (*XMaskEvent_dylibloader_wrapper_xlib)( Display*, long, XEvent*);
+extern int (*XMaxCmapsOfScreen_dylibloader_wrapper_xlib)( Screen*);
+extern int (*XMinCmapsOfScreen_dylibloader_wrapper_xlib)( Screen*);
+extern int (*XMoveResizeWindow_dylibloader_wrapper_xlib)( Display*, Window, int, int, unsigned int, unsigned int);
+extern int (*XMoveWindow_dylibloader_wrapper_xlib)( Display*, Window, int, int);
+extern int (*XNextEvent_dylibloader_wrapper_xlib)( Display*, XEvent*);
+extern int (*XNoOp_dylibloader_wrapper_xlib)( Display*);
+extern int (*XParseColor_dylibloader_wrapper_xlib)( Display*, Colormap,const char*, XColor*);
+extern int (*XParseGeometry_dylibloader_wrapper_xlib)(const char*, int*, int*, unsigned int*, unsigned int*);
+extern int (*XPeekEvent_dylibloader_wrapper_xlib)( Display*, XEvent*);
+extern int (*XPeekIfEvent_dylibloader_wrapper_xlib)( Display*, XEvent*, Bool (*) (Display*, XEvent*, XPointer), XPointer);
+extern int (*XPending_dylibloader_wrapper_xlib)( Display*);
+extern int (*XPlanesOfScreen_dylibloader_wrapper_xlib)( Screen*);
+extern int (*XProtocolRevision_dylibloader_wrapper_xlib)( Display*);
+extern int (*XProtocolVersion_dylibloader_wrapper_xlib)( Display*);
+extern int (*XPutBackEvent_dylibloader_wrapper_xlib)( Display*, XEvent*);
+extern int (*XPutImage_dylibloader_wrapper_xlib)( Display*, Drawable, GC, XImage*, int, int, int, int, unsigned int, unsigned int);
+extern int (*XQLength_dylibloader_wrapper_xlib)( Display*);
+extern int (*XQueryBestCursor_dylibloader_wrapper_xlib)( Display*, Drawable, unsigned int, unsigned int, unsigned int*, unsigned int*);
+extern int (*XQueryBestSize_dylibloader_wrapper_xlib)( Display*, int, Drawable, unsigned int, unsigned int, unsigned int*, unsigned int*);
+extern int (*XQueryBestStipple_dylibloader_wrapper_xlib)( Display*, Drawable, unsigned int, unsigned int, unsigned int*, unsigned int*);
+extern int (*XQueryBestTile_dylibloader_wrapper_xlib)( Display*, Drawable, unsigned int, unsigned int, unsigned int*, unsigned int*);
+extern int (*XQueryColor_dylibloader_wrapper_xlib)( Display*, Colormap, XColor*);
+extern int (*XQueryColors_dylibloader_wrapper_xlib)( Display*, Colormap, XColor*, int);
+extern int (*XQueryExtension_dylibloader_wrapper_xlib)( Display*,const char*, int*, int*, int*);
+extern int (*XQueryKeymap_dylibloader_wrapper_xlib)( Display*, char [32]);
+extern int (*XQueryPointer_dylibloader_wrapper_xlib)( Display*, Window, Window*, Window*, int*, int*, int*, int*, unsigned int*);
+extern int (*XQueryTextExtents_dylibloader_wrapper_xlib)( Display*, XID,const char*, int, int*, int*, int*, XCharStruct*);
+extern int (*XQueryTextExtents16_dylibloader_wrapper_xlib)( Display*, XID,const XChar2b*, int, int*, int*, int*, XCharStruct*);
+extern int (*XQueryTree_dylibloader_wrapper_xlib)( Display*, Window, Window*, Window*, Window**, unsigned int*);
+extern int (*XRaiseWindow_dylibloader_wrapper_xlib)( Display*, Window);
+extern int (*XReadBitmapFile_dylibloader_wrapper_xlib)( Display*, Drawable,const char*, unsigned int*, unsigned int*, Pixmap*, int*, int*);
+extern int (*XReadBitmapFileData_dylibloader_wrapper_xlib)(const char*, unsigned int*, unsigned int*, unsigned char**, int*, int*);
+extern int (*XRebindKeysym_dylibloader_wrapper_xlib)( Display*, KeySym, KeySym*, int,const unsigned char*, int);
+extern int (*XRecolorCursor_dylibloader_wrapper_xlib)( Display*, Cursor, XColor*, XColor*);
+extern int (*XRefreshKeyboardMapping_dylibloader_wrapper_xlib)( XMappingEvent*);
+extern int (*XRemoveFromSaveSet_dylibloader_wrapper_xlib)( Display*, Window);
+extern int (*XRemoveHost_dylibloader_wrapper_xlib)( Display*, XHostAddress*);
+extern int (*XRemoveHosts_dylibloader_wrapper_xlib)( Display*, XHostAddress*, int);
+extern int (*XReparentWindow_dylibloader_wrapper_xlib)( Display*, Window, Window, int, int);
+extern int (*XResetScreenSaver_dylibloader_wrapper_xlib)( Display*);
+extern int (*XResizeWindow_dylibloader_wrapper_xlib)( Display*, Window, unsigned int, unsigned int);
+extern int (*XRestackWindows_dylibloader_wrapper_xlib)( Display*, Window*, int);
+extern int (*XRotateBuffers_dylibloader_wrapper_xlib)( Display*, int);
+extern int (*XRotateWindowProperties_dylibloader_wrapper_xlib)( Display*, Window, Atom*, int, int);
+extern int (*XScreenCount_dylibloader_wrapper_xlib)( Display*);
+extern int (*XSelectInput_dylibloader_wrapper_xlib)( Display*, Window, long);
+extern int (*XSendEvent_dylibloader_wrapper_xlib)( Display*, Window, int, long, XEvent*);
+extern int (*XSetAccessControl_dylibloader_wrapper_xlib)( Display*, int);
+extern int (*XSetArcMode_dylibloader_wrapper_xlib)( Display*, GC, int);
+extern int (*XSetBackground_dylibloader_wrapper_xlib)( Display*, GC, unsigned long);
+extern int (*XSetClipMask_dylibloader_wrapper_xlib)( Display*, GC, Pixmap);
+extern int (*XSetClipOrigin_dylibloader_wrapper_xlib)( Display*, GC, int, int);
+extern int (*XSetClipRectangles_dylibloader_wrapper_xlib)( Display*, GC, int, int, XRectangle*, int, int);
+extern int (*XSetCloseDownMode_dylibloader_wrapper_xlib)( Display*, int);
+extern int (*XSetCommand_dylibloader_wrapper_xlib)( Display*, Window, char**, int);
+extern int (*XSetDashes_dylibloader_wrapper_xlib)( Display*, GC, int,const char*, int);
+extern int (*XSetFillRule_dylibloader_wrapper_xlib)( Display*, GC, int);
+extern int (*XSetFillStyle_dylibloader_wrapper_xlib)( Display*, GC, int);
+extern int (*XSetFont_dylibloader_wrapper_xlib)( Display*, GC, Font);
+extern int (*XSetFontPath_dylibloader_wrapper_xlib)( Display*, char**, int);
+extern int (*XSetForeground_dylibloader_wrapper_xlib)( Display*, GC, unsigned long);
+extern int (*XSetFunction_dylibloader_wrapper_xlib)( Display*, GC, int);
+extern int (*XSetGraphicsExposures_dylibloader_wrapper_xlib)( Display*, GC, int);
+extern int (*XSetIconName_dylibloader_wrapper_xlib)( Display*, Window,const char*);
+extern int (*XSetInputFocus_dylibloader_wrapper_xlib)( Display*, Window, int, Time);
+extern int (*XSetLineAttributes_dylibloader_wrapper_xlib)( Display*, GC, unsigned int, int, int, int);
+extern int (*XSetModifierMapping_dylibloader_wrapper_xlib)( Display*, XModifierKeymap*);
+extern int (*XSetPlaneMask_dylibloader_wrapper_xlib)( Display*, GC, unsigned long);
+extern int (*XSetPointerMapping_dylibloader_wrapper_xlib)( Display*,const unsigned char*, int);
+extern int (*XSetScreenSaver_dylibloader_wrapper_xlib)( Display*, int, int, int, int);
+extern int (*XSetSelectionOwner_dylibloader_wrapper_xlib)( Display*, Atom, Window, Time);
+extern int (*XSetState_dylibloader_wrapper_xlib)( Display*, GC, unsigned long, unsigned long, int, unsigned long);
+extern int (*XSetStipple_dylibloader_wrapper_xlib)( Display*, GC, Pixmap);
+extern int (*XSetSubwindowMode_dylibloader_wrapper_xlib)( Display*, GC, int);
+extern int (*XSetTSOrigin_dylibloader_wrapper_xlib)( Display*, GC, int, int);
+extern int (*XSetTile_dylibloader_wrapper_xlib)( Display*, GC, Pixmap);
+extern int (*XSetWindowBackground_dylibloader_wrapper_xlib)( Display*, Window, unsigned long);
+extern int (*XSetWindowBackgroundPixmap_dylibloader_wrapper_xlib)( Display*, Window, Pixmap);
+extern int (*XSetWindowBorder_dylibloader_wrapper_xlib)( Display*, Window, unsigned long);
+extern int (*XSetWindowBorderPixmap_dylibloader_wrapper_xlib)( Display*, Window, Pixmap);
+extern int (*XSetWindowBorderWidth_dylibloader_wrapper_xlib)( Display*, Window, unsigned int);
+extern int (*XSetWindowColormap_dylibloader_wrapper_xlib)( Display*, Window, Colormap);
+extern int (*XStoreBuffer_dylibloader_wrapper_xlib)( Display*,const char*, int, int);
+extern int (*XStoreBytes_dylibloader_wrapper_xlib)( Display*,const char*, int);
+extern int (*XStoreColor_dylibloader_wrapper_xlib)( Display*, Colormap, XColor*);
+extern int (*XStoreColors_dylibloader_wrapper_xlib)( Display*, Colormap, XColor*, int);
+extern int (*XStoreName_dylibloader_wrapper_xlib)( Display*, Window,const char*);
+extern int (*XStoreNamedColor_dylibloader_wrapper_xlib)( Display*, Colormap,const char*, unsigned long, int);
+extern int (*XSync_dylibloader_wrapper_xlib)( Display*, int);
+extern int (*XTextExtents_dylibloader_wrapper_xlib)( XFontStruct*,const char*, int, int*, int*, int*, XCharStruct*);
+extern int (*XTextExtents16_dylibloader_wrapper_xlib)( XFontStruct*,const XChar2b*, int, int*, int*, int*, XCharStruct*);
+extern int (*XTextWidth_dylibloader_wrapper_xlib)( XFontStruct*,const char*, int);
+extern int (*XTextWidth16_dylibloader_wrapper_xlib)( XFontStruct*,const XChar2b*, int);
+extern int (*XTranslateCoordinates_dylibloader_wrapper_xlib)( Display*, Window, Window, int, int, int*, int*, Window*);
+extern int (*XUndefineCursor_dylibloader_wrapper_xlib)( Display*, Window);
+extern int (*XUngrabButton_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, Window);
+extern int (*XUngrabKey_dylibloader_wrapper_xlib)( Display*, int, unsigned int, Window);
+extern int (*XUngrabKeyboard_dylibloader_wrapper_xlib)( Display*, Time);
+extern int (*XUngrabPointer_dylibloader_wrapper_xlib)( Display*, Time);
+extern int (*XUngrabServer_dylibloader_wrapper_xlib)( Display*);
+extern int (*XUninstallColormap_dylibloader_wrapper_xlib)( Display*, Colormap);
+extern int (*XUnloadFont_dylibloader_wrapper_xlib)( Display*, Font);
+extern int (*XUnmapSubwindows_dylibloader_wrapper_xlib)( Display*, Window);
+extern int (*XUnmapWindow_dylibloader_wrapper_xlib)( Display*, Window);
+extern int (*XVendorRelease_dylibloader_wrapper_xlib)( Display*);
+extern int (*XWarpPointer_dylibloader_wrapper_xlib)( Display*, Window, Window, int, int, unsigned int, unsigned int, int, int);
+extern int (*XWidthMMOfScreen_dylibloader_wrapper_xlib)( Screen*);
+extern int (*XWidthOfScreen_dylibloader_wrapper_xlib)( Screen*);
+extern int (*XWindowEvent_dylibloader_wrapper_xlib)( Display*, Window, long, XEvent*);
+extern int (*XWriteBitmapFile_dylibloader_wrapper_xlib)( Display*,const char*, Pixmap, unsigned int, unsigned int, int, int);
+extern int (*XSupportsLocale_dylibloader_wrapper_xlib)( void);
+extern char* (*XSetLocaleModifiers_dylibloader_wrapper_xlib)(const char*);
+extern XOM (*XOpenOM_dylibloader_wrapper_xlib)( Display*,struct _XrmHashBucketRec*,const char*,const char*);
+extern int (*XCloseOM_dylibloader_wrapper_xlib)( XOM);
+extern char* (*XSetOMValues_dylibloader_wrapper_xlib)( XOM,...);
+extern char* (*XGetOMValues_dylibloader_wrapper_xlib)( XOM,...);
+extern Display* (*XDisplayOfOM_dylibloader_wrapper_xlib)( XOM);
+extern char* (*XLocaleOfOM_dylibloader_wrapper_xlib)( XOM);
+extern XOC (*XCreateOC_dylibloader_wrapper_xlib)( XOM,...);
+extern void (*XDestroyOC_dylibloader_wrapper_xlib)( XOC);
+extern XOM (*XOMOfOC_dylibloader_wrapper_xlib)( XOC);
+extern char* (*XSetOCValues_dylibloader_wrapper_xlib)( XOC,...);
+extern char* (*XGetOCValues_dylibloader_wrapper_xlib)( XOC,...);
+extern XFontSet (*XCreateFontSet_dylibloader_wrapper_xlib)( Display*,const char*, char***, int*, char**);
+extern void (*XFreeFontSet_dylibloader_wrapper_xlib)( Display*, XFontSet);
+extern int (*XFontsOfFontSet_dylibloader_wrapper_xlib)( XFontSet, XFontStruct***, char***);
+extern char* (*XBaseFontNameListOfFontSet_dylibloader_wrapper_xlib)( XFontSet);
+extern char* (*XLocaleOfFontSet_dylibloader_wrapper_xlib)( XFontSet);
+extern int (*XContextDependentDrawing_dylibloader_wrapper_xlib)( XFontSet);
+extern int (*XDirectionalDependentDrawing_dylibloader_wrapper_xlib)( XFontSet);
+extern int (*XContextualDrawing_dylibloader_wrapper_xlib)( XFontSet);
+extern XFontSetExtents* (*XExtentsOfFontSet_dylibloader_wrapper_xlib)( XFontSet);
+extern int (*XmbTextEscapement_dylibloader_wrapper_xlib)( XFontSet,const char*, int);
+extern int (*XwcTextEscapement_dylibloader_wrapper_xlib)( XFontSet,const wchar_t*, int);
+extern int (*Xutf8TextEscapement_dylibloader_wrapper_xlib)( XFontSet,const char*, int);
+extern int (*XmbTextExtents_dylibloader_wrapper_xlib)( XFontSet,const char*, int, XRectangle*, XRectangle*);
+extern int (*XwcTextExtents_dylibloader_wrapper_xlib)( XFontSet,const wchar_t*, int, XRectangle*, XRectangle*);
+extern int (*Xutf8TextExtents_dylibloader_wrapper_xlib)( XFontSet,const char*, int, XRectangle*, XRectangle*);
+extern int (*XmbTextPerCharExtents_dylibloader_wrapper_xlib)( XFontSet,const char*, int, XRectangle*, XRectangle*, int, int*, XRectangle*, XRectangle*);
+extern int (*XwcTextPerCharExtents_dylibloader_wrapper_xlib)( XFontSet,const wchar_t*, int, XRectangle*, XRectangle*, int, int*, XRectangle*, XRectangle*);
+extern int (*Xutf8TextPerCharExtents_dylibloader_wrapper_xlib)( XFontSet,const char*, int, XRectangle*, XRectangle*, int, int*, XRectangle*, XRectangle*);
+extern void (*XmbDrawText_dylibloader_wrapper_xlib)( Display*, Drawable, GC, int, int, XmbTextItem*, int);
+extern void (*XwcDrawText_dylibloader_wrapper_xlib)( Display*, Drawable, GC, int, int, XwcTextItem*, int);
+extern void (*Xutf8DrawText_dylibloader_wrapper_xlib)( Display*, Drawable, GC, int, int, XmbTextItem*, int);
+extern void (*XmbDrawString_dylibloader_wrapper_xlib)( Display*, Drawable, XFontSet, GC, int, int,const char*, int);
+extern void (*XwcDrawString_dylibloader_wrapper_xlib)( Display*, Drawable, XFontSet, GC, int, int,const wchar_t*, int);
+extern void (*Xutf8DrawString_dylibloader_wrapper_xlib)( Display*, Drawable, XFontSet, GC, int, int,const char*, int);
+extern void (*XmbDrawImageString_dylibloader_wrapper_xlib)( Display*, Drawable, XFontSet, GC, int, int,const char*, int);
+extern void (*XwcDrawImageString_dylibloader_wrapper_xlib)( Display*, Drawable, XFontSet, GC, int, int,const wchar_t*, int);
+extern void (*Xutf8DrawImageString_dylibloader_wrapper_xlib)( Display*, Drawable, XFontSet, GC, int, int,const char*, int);
+extern XIM (*XOpenIM_dylibloader_wrapper_xlib)( Display*,struct _XrmHashBucketRec*, char*, char*);
+extern int (*XCloseIM_dylibloader_wrapper_xlib)( XIM);
+extern char* (*XGetIMValues_dylibloader_wrapper_xlib)( XIM,...);
+extern char* (*XSetIMValues_dylibloader_wrapper_xlib)( XIM,...);
+extern Display* (*XDisplayOfIM_dylibloader_wrapper_xlib)( XIM);
+extern char* (*XLocaleOfIM_dylibloader_wrapper_xlib)( XIM);
+extern XIC (*XCreateIC_dylibloader_wrapper_xlib)( XIM,...);
+extern void (*XDestroyIC_dylibloader_wrapper_xlib)( XIC);
+extern void (*XSetICFocus_dylibloader_wrapper_xlib)( XIC);
+extern void (*XUnsetICFocus_dylibloader_wrapper_xlib)( XIC);
+extern wchar_t* (*XwcResetIC_dylibloader_wrapper_xlib)( XIC);
+extern char* (*XmbResetIC_dylibloader_wrapper_xlib)( XIC);
+extern char* (*Xutf8ResetIC_dylibloader_wrapper_xlib)( XIC);
+extern char* (*XSetICValues_dylibloader_wrapper_xlib)( XIC,...);
+extern char* (*XGetICValues_dylibloader_wrapper_xlib)( XIC,...);
+extern XIM (*XIMOfIC_dylibloader_wrapper_xlib)( XIC);
+extern int (*XFilterEvent_dylibloader_wrapper_xlib)( XEvent*, Window);
+extern int (*XmbLookupString_dylibloader_wrapper_xlib)( XIC, XKeyPressedEvent*, char*, int, KeySym*, int*);
+extern int (*XwcLookupString_dylibloader_wrapper_xlib)( XIC, XKeyPressedEvent*, wchar_t*, int, KeySym*, int*);
+extern int (*Xutf8LookupString_dylibloader_wrapper_xlib)( XIC, XKeyPressedEvent*, char*, int, KeySym*, int*);
+extern XVaNestedList (*XVaCreateNestedList_dylibloader_wrapper_xlib)( int,...);
+extern int (*XRegisterIMInstantiateCallback_dylibloader_wrapper_xlib)( Display*,struct _XrmHashBucketRec*, char*, char*, XIDProc, XPointer);
+extern int (*XUnregisterIMInstantiateCallback_dylibloader_wrapper_xlib)( Display*,struct _XrmHashBucketRec*, char*, char*, XIDProc, XPointer);
+extern int (*XInternalConnectionNumbers_dylibloader_wrapper_xlib)( Display*, int**, int*);
+extern void (*XProcessInternalConnection_dylibloader_wrapper_xlib)( Display*, int);
+extern int (*XAddConnectionWatch_dylibloader_wrapper_xlib)( Display*, XConnectionWatchProc, XPointer);
+extern void (*XRemoveConnectionWatch_dylibloader_wrapper_xlib)( Display*, XConnectionWatchProc, XPointer);
+extern void (*XSetAuthorization_dylibloader_wrapper_xlib)( char*, int, char*, int);
+extern int (*_Xmbtowc_dylibloader_wrapper_xlib)( wchar_t*, char*, int);
+extern int (*_Xwctomb_dylibloader_wrapper_xlib)( char*, wchar_t);
+extern int (*XGetEventData_dylibloader_wrapper_xlib)( Display*, XGenericEventCookie*);
+extern void (*XFreeEventData_dylibloader_wrapper_xlib)( Display*, XGenericEventCookie*);
+extern XClassHint* (*XAllocClassHint_dylibloader_wrapper_xlib)( void);
+extern XIconSize* (*XAllocIconSize_dylibloader_wrapper_xlib)( void);
+extern XSizeHints* (*XAllocSizeHints_dylibloader_wrapper_xlib)( void);
+extern XStandardColormap* (*XAllocStandardColormap_dylibloader_wrapper_xlib)( void);
+extern XWMHints* (*XAllocWMHints_dylibloader_wrapper_xlib)( void);
+extern int (*XClipBox_dylibloader_wrapper_xlib)( Region, XRectangle*);
+extern Region (*XCreateRegion_dylibloader_wrapper_xlib)( void);
+extern const char* (*XDefaultString_dylibloader_wrapper_xlib)( void);
+extern int (*XDeleteContext_dylibloader_wrapper_xlib)( Display*, XID, XContext);
+extern int (*XDestroyRegion_dylibloader_wrapper_xlib)( Region);
+extern int (*XEmptyRegion_dylibloader_wrapper_xlib)( Region);
+extern int (*XEqualRegion_dylibloader_wrapper_xlib)( Region, Region);
+extern int (*XFindContext_dylibloader_wrapper_xlib)( Display*, XID, XContext, XPointer*);
+extern int (*XGetClassHint_dylibloader_wrapper_xlib)( Display*, Window, XClassHint*);
+extern int (*XGetIconSizes_dylibloader_wrapper_xlib)( Display*, Window, XIconSize**, int*);
+extern int (*XGetNormalHints_dylibloader_wrapper_xlib)( Display*, Window, XSizeHints*);
+extern int (*XGetRGBColormaps_dylibloader_wrapper_xlib)( Display*, Window, XStandardColormap**, int*, Atom);
+extern int (*XGetSizeHints_dylibloader_wrapper_xlib)( Display*, Window, XSizeHints*, Atom);
+extern int (*XGetStandardColormap_dylibloader_wrapper_xlib)( Display*, Window, XStandardColormap*, Atom);
+extern int (*XGetTextProperty_dylibloader_wrapper_xlib)( Display*, Window, XTextProperty*, Atom);
+extern XVisualInfo* (*XGetVisualInfo_dylibloader_wrapper_xlib)( Display*, long, XVisualInfo*, int*);
+extern int (*XGetWMClientMachine_dylibloader_wrapper_xlib)( Display*, Window, XTextProperty*);
+extern XWMHints* (*XGetWMHints_dylibloader_wrapper_xlib)( Display*, Window);
+extern int (*XGetWMIconName_dylibloader_wrapper_xlib)( Display*, Window, XTextProperty*);
+extern int (*XGetWMName_dylibloader_wrapper_xlib)( Display*, Window, XTextProperty*);
+extern int (*XGetWMNormalHints_dylibloader_wrapper_xlib)( Display*, Window, XSizeHints*, long*);
+extern int (*XGetWMSizeHints_dylibloader_wrapper_xlib)( Display*, Window, XSizeHints*, long*, Atom);
+extern int (*XGetZoomHints_dylibloader_wrapper_xlib)( Display*, Window, XSizeHints*);
+extern int (*XIntersectRegion_dylibloader_wrapper_xlib)( Region, Region, Region);
+extern void (*XConvertCase_dylibloader_wrapper_xlib)( KeySym, KeySym*, KeySym*);
+extern int (*XLookupString_dylibloader_wrapper_xlib)( XKeyEvent*, char*, int, KeySym*, XComposeStatus*);
+extern int (*XMatchVisualInfo_dylibloader_wrapper_xlib)( Display*, int, int, int, XVisualInfo*);
+extern int (*XOffsetRegion_dylibloader_wrapper_xlib)( Region, int, int);
+extern int (*XPointInRegion_dylibloader_wrapper_xlib)( Region, int, int);
+extern Region (*XPolygonRegion_dylibloader_wrapper_xlib)( XPoint*, int, int);
+extern int (*XRectInRegion_dylibloader_wrapper_xlib)( Region, int, int, unsigned int, unsigned int);
+extern int (*XSaveContext_dylibloader_wrapper_xlib)( Display*, XID, XContext,const char*);
+extern int (*XSetClassHint_dylibloader_wrapper_xlib)( Display*, Window, XClassHint*);
+extern int (*XSetIconSizes_dylibloader_wrapper_xlib)( Display*, Window, XIconSize*, int);
+extern int (*XSetNormalHints_dylibloader_wrapper_xlib)( Display*, Window, XSizeHints*);
+extern void (*XSetRGBColormaps_dylibloader_wrapper_xlib)( Display*, Window, XStandardColormap*, int, Atom);
+extern int (*XSetSizeHints_dylibloader_wrapper_xlib)( Display*, Window, XSizeHints*, Atom);
+extern int (*XSetStandardProperties_dylibloader_wrapper_xlib)( Display*, Window,const char*,const char*, Pixmap, char**, int, XSizeHints*);
+extern void (*XSetTextProperty_dylibloader_wrapper_xlib)( Display*, Window, XTextProperty*, Atom);
+extern void (*XSetWMClientMachine_dylibloader_wrapper_xlib)( Display*, Window, XTextProperty*);
+extern int (*XSetWMHints_dylibloader_wrapper_xlib)( Display*, Window, XWMHints*);
+extern void (*XSetWMIconName_dylibloader_wrapper_xlib)( Display*, Window, XTextProperty*);
+extern void (*XSetWMName_dylibloader_wrapper_xlib)( Display*, Window, XTextProperty*);
+extern void (*XSetWMNormalHints_dylibloader_wrapper_xlib)( Display*, Window, XSizeHints*);
+extern void (*XSetWMProperties_dylibloader_wrapper_xlib)( Display*, Window, XTextProperty*, XTextProperty*, char**, int, XSizeHints*, XWMHints*, XClassHint*);
+extern void (*XmbSetWMProperties_dylibloader_wrapper_xlib)( Display*, Window,const char*,const char*, char**, int, XSizeHints*, XWMHints*, XClassHint*);
+extern void (*Xutf8SetWMProperties_dylibloader_wrapper_xlib)( Display*, Window,const char*,const char*, char**, int, XSizeHints*, XWMHints*, XClassHint*);
+extern void (*XSetWMSizeHints_dylibloader_wrapper_xlib)( Display*, Window, XSizeHints*, Atom);
+extern int (*XSetRegion_dylibloader_wrapper_xlib)( Display*, GC, Region);
+extern void (*XSetStandardColormap_dylibloader_wrapper_xlib)( Display*, Window, XStandardColormap*, Atom);
+extern int (*XSetZoomHints_dylibloader_wrapper_xlib)( Display*, Window, XSizeHints*);
+extern int (*XShrinkRegion_dylibloader_wrapper_xlib)( Region, int, int);
+extern int (*XStringListToTextProperty_dylibloader_wrapper_xlib)( char**, int, XTextProperty*);
+extern int (*XSubtractRegion_dylibloader_wrapper_xlib)( Region, Region, Region);
+extern int (*XmbTextListToTextProperty_dylibloader_wrapper_xlib)( Display*, char**, int, XICCEncodingStyle, XTextProperty*);
+extern int (*XwcTextListToTextProperty_dylibloader_wrapper_xlib)( Display*, wchar_t**, int, XICCEncodingStyle, XTextProperty*);
+extern int (*Xutf8TextListToTextProperty_dylibloader_wrapper_xlib)( Display*, char**, int, XICCEncodingStyle, XTextProperty*);
+extern void (*XwcFreeStringList_dylibloader_wrapper_xlib)( wchar_t**);
+extern int (*XTextPropertyToStringList_dylibloader_wrapper_xlib)( XTextProperty*, char***, int*);
+extern int (*XmbTextPropertyToTextList_dylibloader_wrapper_xlib)( Display*,const XTextProperty*, char***, int*);
+extern int (*XwcTextPropertyToTextList_dylibloader_wrapper_xlib)( Display*,const XTextProperty*, wchar_t***, int*);
+extern int (*Xutf8TextPropertyToTextList_dylibloader_wrapper_xlib)( Display*,const XTextProperty*, char***, int*);
+extern int (*XUnionRectWithRegion_dylibloader_wrapper_xlib)( XRectangle*, Region, Region);
+extern int (*XUnionRegion_dylibloader_wrapper_xlib)( Region, Region, Region);
+extern int (*XWMGeometry_dylibloader_wrapper_xlib)( Display*, int,const char*,const char*, unsigned int, XSizeHints*, int*, int*, int*, int*, int*);
+extern int (*XXorRegion_dylibloader_wrapper_xlib)( Region, Region, Region);
+extern int (*XkbIgnoreExtension_dylibloader_wrapper_xlib)( int);
+extern Display* (*XkbOpenDisplay_dylibloader_wrapper_xlib)( char*, int*, int*, int*, int*, int*);
+extern int (*XkbQueryExtension_dylibloader_wrapper_xlib)( Display*, int*, int*, int*, int*, int*);
+extern int (*XkbUseExtension_dylibloader_wrapper_xlib)( Display*, int*, int*);
+extern int (*XkbLibraryVersion_dylibloader_wrapper_xlib)( int*, int*);
+extern unsigned int (*XkbSetXlibControls_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int);
+extern unsigned int (*XkbGetXlibControls_dylibloader_wrapper_xlib)( Display*);
+extern unsigned int (*XkbXlibControlsImplemented_dylibloader_wrapper_xlib)( void);
+extern void (*XkbSetAtomFuncs_dylibloader_wrapper_xlib)( XkbInternAtomFunc, XkbGetAtomNameFunc);
+extern KeySym (*XkbKeycodeToKeysym_dylibloader_wrapper_xlib)( Display*, KeyCode, int, int);
+extern unsigned int (*XkbKeysymToModifiers_dylibloader_wrapper_xlib)( Display*, KeySym);
+extern int (*XkbLookupKeySym_dylibloader_wrapper_xlib)( Display*, KeyCode, unsigned int, unsigned int*, KeySym*);
+extern int (*XkbLookupKeyBinding_dylibloader_wrapper_xlib)( Display*, KeySym, unsigned int, char*, int, int*);
+extern int (*XkbTranslateKeyCode_dylibloader_wrapper_xlib)( XkbDescPtr, KeyCode, unsigned int, unsigned int*, KeySym*);
+extern int (*XkbTranslateKeySym_dylibloader_wrapper_xlib)( Display*, KeySym*, unsigned int, char*, int, int*);
+extern int (*XkbSetAutoRepeatRate_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, unsigned int);
+extern int (*XkbGetAutoRepeatRate_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int*, unsigned int*);
+extern int (*XkbChangeEnabledControls_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, unsigned int);
+extern int (*XkbDeviceBell_dylibloader_wrapper_xlib)( Display*, Window, int, int, int, int, Atom);
+extern int (*XkbForceDeviceBell_dylibloader_wrapper_xlib)( Display*, int, int, int, int);
+extern int (*XkbDeviceBellEvent_dylibloader_wrapper_xlib)( Display*, Window, int, int, int, int, Atom);
+extern int (*XkbBell_dylibloader_wrapper_xlib)( Display*, Window, int, Atom);
+extern int (*XkbForceBell_dylibloader_wrapper_xlib)( Display*, int);
+extern int (*XkbBellEvent_dylibloader_wrapper_xlib)( Display*, Window, int, Atom);
+extern int (*XkbSelectEvents_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, unsigned int);
+extern int (*XkbSelectEventDetails_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, unsigned long, unsigned long);
+extern void (*XkbNoteMapChanges_dylibloader_wrapper_xlib)( XkbMapChangesPtr, XkbMapNotifyEvent*, unsigned int);
+extern void (*XkbNoteNameChanges_dylibloader_wrapper_xlib)( XkbNameChangesPtr, XkbNamesNotifyEvent*, unsigned int);
+extern int (*XkbGetIndicatorState_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int*);
+extern int (*XkbGetIndicatorMap_dylibloader_wrapper_xlib)( Display*, unsigned long, XkbDescPtr);
+extern int (*XkbSetIndicatorMap_dylibloader_wrapper_xlib)( Display*, unsigned long, XkbDescPtr);
+extern int (*XkbGetNamedIndicator_dylibloader_wrapper_xlib)( Display*, Atom, int*, int*, XkbIndicatorMapPtr, int*);
+extern int (*XkbGetNamedDeviceIndicator_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, unsigned int, Atom, int*, int*, XkbIndicatorMapPtr, int*);
+extern int (*XkbSetNamedIndicator_dylibloader_wrapper_xlib)( Display*, Atom, int, int, int, XkbIndicatorMapPtr);
+extern int (*XkbSetNamedDeviceIndicator_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, unsigned int, Atom, int, int, int, XkbIndicatorMapPtr);
+extern int (*XkbLockModifiers_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, unsigned int);
+extern int (*XkbLatchModifiers_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, unsigned int);
+extern int (*XkbLockGroup_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int);
+extern int (*XkbLatchGroup_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int);
+extern int (*XkbSetServerInternalMods_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int);
+extern int (*XkbSetIgnoreLockMods_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int);
+extern int (*XkbVirtualModsToReal_dylibloader_wrapper_xlib)( XkbDescPtr, unsigned int, unsigned int*);
+extern int (*XkbComputeEffectiveMap_dylibloader_wrapper_xlib)( XkbDescPtr, XkbKeyTypePtr, unsigned char*);
+extern int (*XkbInitCanonicalKeyTypes_dylibloader_wrapper_xlib)( XkbDescPtr, unsigned int, int);
+extern XkbDescPtr (*XkbAllocKeyboard_dylibloader_wrapper_xlib)( void);
+extern void (*XkbFreeKeyboard_dylibloader_wrapper_xlib)( XkbDescPtr, unsigned int, int);
+extern int (*XkbAllocClientMap_dylibloader_wrapper_xlib)( XkbDescPtr, unsigned int, unsigned int);
+extern int (*XkbAllocServerMap_dylibloader_wrapper_xlib)( XkbDescPtr, unsigned int, unsigned int);
+extern void (*XkbFreeClientMap_dylibloader_wrapper_xlib)( XkbDescPtr, unsigned int, int);
+extern void (*XkbFreeServerMap_dylibloader_wrapper_xlib)( XkbDescPtr, unsigned int, int);
+extern XkbKeyTypePtr (*XkbAddKeyType_dylibloader_wrapper_xlib)( XkbDescPtr, Atom, int, int, int);
+extern int (*XkbAllocIndicatorMaps_dylibloader_wrapper_xlib)( XkbDescPtr);
+extern void (*XkbFreeIndicatorMaps_dylibloader_wrapper_xlib)( XkbDescPtr);
+extern XkbDescPtr (*XkbGetMap_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int);
+extern int (*XkbGetUpdatedMap_dylibloader_wrapper_xlib)( Display*, unsigned int, XkbDescPtr);
+extern int (*XkbGetMapChanges_dylibloader_wrapper_xlib)( Display*, XkbDescPtr, XkbMapChangesPtr);
+extern int (*XkbRefreshKeyboardMapping_dylibloader_wrapper_xlib)( XkbMapNotifyEvent*);
+extern int (*XkbGetKeyTypes_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, XkbDescPtr);
+extern int (*XkbGetKeySyms_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, XkbDescPtr);
+extern int (*XkbGetKeyActions_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, XkbDescPtr);
+extern int (*XkbGetKeyBehaviors_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, XkbDescPtr);
+extern int (*XkbGetVirtualMods_dylibloader_wrapper_xlib)( Display*, unsigned int, XkbDescPtr);
+extern int (*XkbGetKeyExplicitComponents_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, XkbDescPtr);
+extern int (*XkbGetKeyModifierMap_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, XkbDescPtr);
+extern int (*XkbGetKeyVirtualModMap_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, XkbDescPtr);
+extern int (*XkbAllocControls_dylibloader_wrapper_xlib)( XkbDescPtr, unsigned int);
+extern void (*XkbFreeControls_dylibloader_wrapper_xlib)( XkbDescPtr, unsigned int, int);
+extern int (*XkbGetControls_dylibloader_wrapper_xlib)( Display*, unsigned long, XkbDescPtr);
+extern int (*XkbSetControls_dylibloader_wrapper_xlib)( Display*, unsigned long, XkbDescPtr);
+extern void (*XkbNoteControlsChanges_dylibloader_wrapper_xlib)( XkbControlsChangesPtr, XkbControlsNotifyEvent*, unsigned int);
+extern int (*XkbAllocCompatMap_dylibloader_wrapper_xlib)( XkbDescPtr, unsigned int, unsigned int);
+extern void (*XkbFreeCompatMap_dylibloader_wrapper_xlib)( XkbDescPtr, unsigned int, int);
+extern int (*XkbGetCompatMap_dylibloader_wrapper_xlib)( Display*, unsigned int, XkbDescPtr);
+extern int (*XkbSetCompatMap_dylibloader_wrapper_xlib)( Display*, unsigned int, XkbDescPtr, int);
+extern int (*XkbAllocNames_dylibloader_wrapper_xlib)( XkbDescPtr, unsigned int, int, int);
+extern int (*XkbGetNames_dylibloader_wrapper_xlib)( Display*, unsigned int, XkbDescPtr);
+extern int (*XkbSetNames_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, unsigned int, XkbDescPtr);
+extern int (*XkbChangeNames_dylibloader_wrapper_xlib)( Display*, XkbDescPtr, XkbNameChangesPtr);
+extern void (*XkbFreeNames_dylibloader_wrapper_xlib)( XkbDescPtr, unsigned int, int);
+extern int (*XkbGetState_dylibloader_wrapper_xlib)( Display*, unsigned int, XkbStatePtr);
+extern int (*XkbSetMap_dylibloader_wrapper_xlib)( Display*, unsigned int, XkbDescPtr);
+extern int (*XkbChangeMap_dylibloader_wrapper_xlib)( Display*, XkbDescPtr, XkbMapChangesPtr);
+extern int (*XkbSetDetectableAutoRepeat_dylibloader_wrapper_xlib)( Display*, int, int*);
+extern int (*XkbGetDetectableAutoRepeat_dylibloader_wrapper_xlib)( Display*, int*);
+extern int (*XkbSetAutoResetControls_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int*, unsigned int*);
+extern int (*XkbGetAutoResetControls_dylibloader_wrapper_xlib)( Display*, unsigned int*, unsigned int*);
+extern int (*XkbSetPerClientControls_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int*);
+extern int (*XkbGetPerClientControls_dylibloader_wrapper_xlib)( Display*, unsigned int*);
+extern int (*XkbCopyKeyType_dylibloader_wrapper_xlib)( XkbKeyTypePtr, XkbKeyTypePtr);
+extern int (*XkbCopyKeyTypes_dylibloader_wrapper_xlib)( XkbKeyTypePtr, XkbKeyTypePtr, int);
+extern int (*XkbResizeKeyType_dylibloader_wrapper_xlib)( XkbDescPtr, int, int, int, int);
+extern KeySym* (*XkbResizeKeySyms_dylibloader_wrapper_xlib)( XkbDescPtr, int, int);
+extern XkbAction* (*XkbResizeKeyActions_dylibloader_wrapper_xlib)( XkbDescPtr, int, int);
+extern int (*XkbChangeTypesOfKey_dylibloader_wrapper_xlib)( XkbDescPtr, int, int, unsigned int, int*, XkbMapChangesPtr);
+extern int (*XkbChangeKeycodeRange_dylibloader_wrapper_xlib)( XkbDescPtr, int, int, XkbChangesPtr);
+extern XkbComponentListPtr (*XkbListComponents_dylibloader_wrapper_xlib)( Display*, unsigned int, XkbComponentNamesPtr, int*);
+extern void (*XkbFreeComponentList_dylibloader_wrapper_xlib)( XkbComponentListPtr);
+extern XkbDescPtr (*XkbGetKeyboard_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int);
+extern XkbDescPtr (*XkbGetKeyboardByName_dylibloader_wrapper_xlib)( Display*, unsigned int, XkbComponentNamesPtr, unsigned int, unsigned int, int);
+extern int (*XkbKeyTypesForCoreSymbols_dylibloader_wrapper_xlib)( XkbDescPtr, int, KeySym*, unsigned int, int*, KeySym*);
+extern int (*XkbApplyCompatMapToKey_dylibloader_wrapper_xlib)( XkbDescPtr, KeyCode, XkbChangesPtr);
+extern int (*XkbUpdateMapFromCore_dylibloader_wrapper_xlib)( XkbDescPtr, KeyCode, int, int, KeySym*, XkbChangesPtr);
+extern XkbDeviceLedInfoPtr (*XkbAddDeviceLedInfo_dylibloader_wrapper_xlib)( XkbDeviceInfoPtr, unsigned int, unsigned int);
+extern int (*XkbResizeDeviceButtonActions_dylibloader_wrapper_xlib)( XkbDeviceInfoPtr, unsigned int);
+extern XkbDeviceInfoPtr (*XkbAllocDeviceInfo_dylibloader_wrapper_xlib)( unsigned int, unsigned int, unsigned int);
+extern void (*XkbFreeDeviceInfo_dylibloader_wrapper_xlib)( XkbDeviceInfoPtr, unsigned int, int);
+extern void (*XkbNoteDeviceChanges_dylibloader_wrapper_xlib)( XkbDeviceChangesPtr, XkbExtensionDeviceNotifyEvent*, unsigned int);
+extern XkbDeviceInfoPtr (*XkbGetDeviceInfo_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, unsigned int, unsigned int);
+extern int (*XkbGetDeviceInfoChanges_dylibloader_wrapper_xlib)( Display*, XkbDeviceInfoPtr, XkbDeviceChangesPtr);
+extern int (*XkbGetDeviceButtonActions_dylibloader_wrapper_xlib)( Display*, XkbDeviceInfoPtr, int, unsigned int, unsigned int);
+extern int (*XkbGetDeviceLedInfo_dylibloader_wrapper_xlib)( Display*, XkbDeviceInfoPtr, unsigned int, unsigned int, unsigned int);
+extern int (*XkbSetDeviceInfo_dylibloader_wrapper_xlib)( Display*, unsigned int, XkbDeviceInfoPtr);
+extern int (*XkbChangeDeviceInfo_dylibloader_wrapper_xlib)( Display*, XkbDeviceInfoPtr, XkbDeviceChangesPtr);
+extern int (*XkbSetDeviceLedInfo_dylibloader_wrapper_xlib)( Display*, XkbDeviceInfoPtr, unsigned int, unsigned int, unsigned int);
+extern int (*XkbSetDeviceButtonActions_dylibloader_wrapper_xlib)( Display*, XkbDeviceInfoPtr, unsigned int, unsigned int);
+extern char (*XkbToControl_dylibloader_wrapper_xlib)( char);
+extern int (*XkbSetDebuggingFlags_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, char*, unsigned int, unsigned int, unsigned int*, unsigned int*);
+extern int (*XkbApplyVirtualModChanges_dylibloader_wrapper_xlib)( XkbDescPtr, unsigned int, XkbChangesPtr);
+extern int (*XkbUpdateActionVirtualMods_dylibloader_wrapper_xlib)( XkbDescPtr, XkbAction*, unsigned int);
+extern void (*XkbUpdateKeyTypeVirtualMods_dylibloader_wrapper_xlib)( XkbDescPtr, XkbKeyTypePtr, unsigned int, XkbChangesPtr);
+int initialize_xlib(int verbose);
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/platform/linuxbsd/x11/dynwrappers/xrandr-so_wrap.c b/platform/linuxbsd/x11/dynwrappers/xrandr-so_wrap.c
new file mode 100644
index 0000000000..f37f3a9db0
--- /dev/null
+++ b/platform/linuxbsd/x11/dynwrappers/xrandr-so_wrap.c
@@ -0,0 +1,797 @@
+// 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-12-02 12:55:12
+// flags: ./generate-wrapper.py --include /usr/include/X11/extensions/Xrandr.h --sys-include <X11/extensions/Xrandr.h> --soname libXrandr.so.2 --init-name xrandr --output-header xrandr-so_wrap.h --output-implementation xrandr-so_wrap.c
+//
+// NOTE: Generated from Xrandr 1.5.2.
+// This has been handpatched to workaround some issues with the generator that
+// will be eventually fixed. In this case, non-existent symbols inherited from
+// libX11 and libXrender, but absent in libXrandr.so.2, were removed.
+#include <stdint.h>
+
+#define XRRQueryExtension XRRQueryExtension_dylibloader_orig_xrandr
+#define XRRQueryVersion XRRQueryVersion_dylibloader_orig_xrandr
+#define XRRGetScreenInfo XRRGetScreenInfo_dylibloader_orig_xrandr
+#define XRRFreeScreenConfigInfo XRRFreeScreenConfigInfo_dylibloader_orig_xrandr
+#define XRRSetScreenConfig XRRSetScreenConfig_dylibloader_orig_xrandr
+#define XRRSetScreenConfigAndRate XRRSetScreenConfigAndRate_dylibloader_orig_xrandr
+#define XRRConfigRotations XRRConfigRotations_dylibloader_orig_xrandr
+#define XRRConfigTimes XRRConfigTimes_dylibloader_orig_xrandr
+#define XRRConfigSizes XRRConfigSizes_dylibloader_orig_xrandr
+#define XRRConfigRates XRRConfigRates_dylibloader_orig_xrandr
+#define XRRConfigCurrentConfiguration XRRConfigCurrentConfiguration_dylibloader_orig_xrandr
+#define XRRConfigCurrentRate XRRConfigCurrentRate_dylibloader_orig_xrandr
+#define XRRRootToScreen XRRRootToScreen_dylibloader_orig_xrandr
+#define XRRSelectInput XRRSelectInput_dylibloader_orig_xrandr
+#define XRRRotations XRRRotations_dylibloader_orig_xrandr
+#define XRRSizes XRRSizes_dylibloader_orig_xrandr
+#define XRRRates XRRRates_dylibloader_orig_xrandr
+#define XRRTimes XRRTimes_dylibloader_orig_xrandr
+#define XRRGetScreenSizeRange XRRGetScreenSizeRange_dylibloader_orig_xrandr
+#define XRRSetScreenSize XRRSetScreenSize_dylibloader_orig_xrandr
+#define XRRGetScreenResources XRRGetScreenResources_dylibloader_orig_xrandr
+#define XRRFreeScreenResources XRRFreeScreenResources_dylibloader_orig_xrandr
+#define XRRGetOutputInfo XRRGetOutputInfo_dylibloader_orig_xrandr
+#define XRRFreeOutputInfo XRRFreeOutputInfo_dylibloader_orig_xrandr
+#define XRRListOutputProperties XRRListOutputProperties_dylibloader_orig_xrandr
+#define XRRQueryOutputProperty XRRQueryOutputProperty_dylibloader_orig_xrandr
+#define XRRConfigureOutputProperty XRRConfigureOutputProperty_dylibloader_orig_xrandr
+#define XRRChangeOutputProperty XRRChangeOutputProperty_dylibloader_orig_xrandr
+#define XRRDeleteOutputProperty XRRDeleteOutputProperty_dylibloader_orig_xrandr
+#define XRRGetOutputProperty XRRGetOutputProperty_dylibloader_orig_xrandr
+#define XRRAllocModeInfo XRRAllocModeInfo_dylibloader_orig_xrandr
+#define XRRCreateMode XRRCreateMode_dylibloader_orig_xrandr
+#define XRRDestroyMode XRRDestroyMode_dylibloader_orig_xrandr
+#define XRRAddOutputMode XRRAddOutputMode_dylibloader_orig_xrandr
+#define XRRDeleteOutputMode XRRDeleteOutputMode_dylibloader_orig_xrandr
+#define XRRFreeModeInfo XRRFreeModeInfo_dylibloader_orig_xrandr
+#define XRRGetCrtcInfo XRRGetCrtcInfo_dylibloader_orig_xrandr
+#define XRRFreeCrtcInfo XRRFreeCrtcInfo_dylibloader_orig_xrandr
+#define XRRSetCrtcConfig XRRSetCrtcConfig_dylibloader_orig_xrandr
+#define XRRGetCrtcGammaSize XRRGetCrtcGammaSize_dylibloader_orig_xrandr
+#define XRRGetCrtcGamma XRRGetCrtcGamma_dylibloader_orig_xrandr
+#define XRRAllocGamma XRRAllocGamma_dylibloader_orig_xrandr
+#define XRRSetCrtcGamma XRRSetCrtcGamma_dylibloader_orig_xrandr
+#define XRRFreeGamma XRRFreeGamma_dylibloader_orig_xrandr
+#define XRRGetScreenResourcesCurrent XRRGetScreenResourcesCurrent_dylibloader_orig_xrandr
+#define XRRSetCrtcTransform XRRSetCrtcTransform_dylibloader_orig_xrandr
+#define XRRGetCrtcTransform XRRGetCrtcTransform_dylibloader_orig_xrandr
+#define XRRUpdateConfiguration XRRUpdateConfiguration_dylibloader_orig_xrandr
+#define XRRGetPanning XRRGetPanning_dylibloader_orig_xrandr
+#define XRRFreePanning XRRFreePanning_dylibloader_orig_xrandr
+#define XRRSetPanning XRRSetPanning_dylibloader_orig_xrandr
+#define XRRSetOutputPrimary XRRSetOutputPrimary_dylibloader_orig_xrandr
+#define XRRGetOutputPrimary XRRGetOutputPrimary_dylibloader_orig_xrandr
+#define XRRGetProviderResources XRRGetProviderResources_dylibloader_orig_xrandr
+#define XRRFreeProviderResources XRRFreeProviderResources_dylibloader_orig_xrandr
+#define XRRGetProviderInfo XRRGetProviderInfo_dylibloader_orig_xrandr
+#define XRRFreeProviderInfo XRRFreeProviderInfo_dylibloader_orig_xrandr
+#define XRRSetProviderOutputSource XRRSetProviderOutputSource_dylibloader_orig_xrandr
+#define XRRSetProviderOffloadSink XRRSetProviderOffloadSink_dylibloader_orig_xrandr
+#define XRRListProviderProperties XRRListProviderProperties_dylibloader_orig_xrandr
+#define XRRQueryProviderProperty XRRQueryProviderProperty_dylibloader_orig_xrandr
+#define XRRConfigureProviderProperty XRRConfigureProviderProperty_dylibloader_orig_xrandr
+#define XRRChangeProviderProperty XRRChangeProviderProperty_dylibloader_orig_xrandr
+#define XRRDeleteProviderProperty XRRDeleteProviderProperty_dylibloader_orig_xrandr
+#define XRRGetProviderProperty XRRGetProviderProperty_dylibloader_orig_xrandr
+#define XRRAllocateMonitor XRRAllocateMonitor_dylibloader_orig_xrandr
+#define XRRGetMonitors XRRGetMonitors_dylibloader_orig_xrandr
+#define XRRSetMonitor XRRSetMonitor_dylibloader_orig_xrandr
+#define XRRDeleteMonitor XRRDeleteMonitor_dylibloader_orig_xrandr
+#define XRRFreeMonitors XRRFreeMonitors_dylibloader_orig_xrandr
+#include <X11/extensions/Xrandr.h>
+#undef XRRQueryExtension
+#undef XRRQueryVersion
+#undef XRRGetScreenInfo
+#undef XRRFreeScreenConfigInfo
+#undef XRRSetScreenConfig
+#undef XRRSetScreenConfigAndRate
+#undef XRRConfigRotations
+#undef XRRConfigTimes
+#undef XRRConfigSizes
+#undef XRRConfigRates
+#undef XRRConfigCurrentConfiguration
+#undef XRRConfigCurrentRate
+#undef XRRRootToScreen
+#undef XRRSelectInput
+#undef XRRRotations
+#undef XRRSizes
+#undef XRRRates
+#undef XRRTimes
+#undef XRRGetScreenSizeRange
+#undef XRRSetScreenSize
+#undef XRRGetScreenResources
+#undef XRRFreeScreenResources
+#undef XRRGetOutputInfo
+#undef XRRFreeOutputInfo
+#undef XRRListOutputProperties
+#undef XRRQueryOutputProperty
+#undef XRRConfigureOutputProperty
+#undef XRRChangeOutputProperty
+#undef XRRDeleteOutputProperty
+#undef XRRGetOutputProperty
+#undef XRRAllocModeInfo
+#undef XRRCreateMode
+#undef XRRDestroyMode
+#undef XRRAddOutputMode
+#undef XRRDeleteOutputMode
+#undef XRRFreeModeInfo
+#undef XRRGetCrtcInfo
+#undef XRRFreeCrtcInfo
+#undef XRRSetCrtcConfig
+#undef XRRGetCrtcGammaSize
+#undef XRRGetCrtcGamma
+#undef XRRAllocGamma
+#undef XRRSetCrtcGamma
+#undef XRRFreeGamma
+#undef XRRGetScreenResourcesCurrent
+#undef XRRSetCrtcTransform
+#undef XRRGetCrtcTransform
+#undef XRRUpdateConfiguration
+#undef XRRGetPanning
+#undef XRRFreePanning
+#undef XRRSetPanning
+#undef XRRSetOutputPrimary
+#undef XRRGetOutputPrimary
+#undef XRRGetProviderResources
+#undef XRRFreeProviderResources
+#undef XRRGetProviderInfo
+#undef XRRFreeProviderInfo
+#undef XRRSetProviderOutputSource
+#undef XRRSetProviderOffloadSink
+#undef XRRListProviderProperties
+#undef XRRQueryProviderProperty
+#undef XRRConfigureProviderProperty
+#undef XRRChangeProviderProperty
+#undef XRRDeleteProviderProperty
+#undef XRRGetProviderProperty
+#undef XRRAllocateMonitor
+#undef XRRGetMonitors
+#undef XRRSetMonitor
+#undef XRRDeleteMonitor
+#undef XRRFreeMonitors
+#include <dlfcn.h>
+#include <stdio.h>
+int (*XRRQueryExtension_dylibloader_wrapper_xrandr)( Display*, int*, int*);
+int (*XRRQueryVersion_dylibloader_wrapper_xrandr)( Display*, int*, int*);
+XRRScreenConfiguration* (*XRRGetScreenInfo_dylibloader_wrapper_xrandr)( Display*, Window);
+void (*XRRFreeScreenConfigInfo_dylibloader_wrapper_xrandr)( XRRScreenConfiguration*);
+int (*XRRSetScreenConfig_dylibloader_wrapper_xrandr)( Display*, XRRScreenConfiguration*, Drawable, int, Rotation, Time);
+int (*XRRSetScreenConfigAndRate_dylibloader_wrapper_xrandr)( Display*, XRRScreenConfiguration*, Drawable, int, Rotation, short, Time);
+Rotation (*XRRConfigRotations_dylibloader_wrapper_xrandr)( XRRScreenConfiguration*, Rotation*);
+Time (*XRRConfigTimes_dylibloader_wrapper_xrandr)( XRRScreenConfiguration*, Time*);
+XRRScreenSize* (*XRRConfigSizes_dylibloader_wrapper_xrandr)( XRRScreenConfiguration*, int*);
+short* (*XRRConfigRates_dylibloader_wrapper_xrandr)( XRRScreenConfiguration*, int, int*);
+SizeID (*XRRConfigCurrentConfiguration_dylibloader_wrapper_xrandr)( XRRScreenConfiguration*, Rotation*);
+short (*XRRConfigCurrentRate_dylibloader_wrapper_xrandr)( XRRScreenConfiguration*);
+int (*XRRRootToScreen_dylibloader_wrapper_xrandr)( Display*, Window);
+void (*XRRSelectInput_dylibloader_wrapper_xrandr)( Display*, Window, int);
+Rotation (*XRRRotations_dylibloader_wrapper_xrandr)( Display*, int, Rotation*);
+XRRScreenSize* (*XRRSizes_dylibloader_wrapper_xrandr)( Display*, int, int*);
+short* (*XRRRates_dylibloader_wrapper_xrandr)( Display*, int, int, int*);
+Time (*XRRTimes_dylibloader_wrapper_xrandr)( Display*, int, Time*);
+int (*XRRGetScreenSizeRange_dylibloader_wrapper_xrandr)( Display*, Window, int*, int*, int*, int*);
+void (*XRRSetScreenSize_dylibloader_wrapper_xrandr)( Display*, Window, int, int, int, int);
+XRRScreenResources* (*XRRGetScreenResources_dylibloader_wrapper_xrandr)( Display*, Window);
+void (*XRRFreeScreenResources_dylibloader_wrapper_xrandr)( XRRScreenResources*);
+XRROutputInfo* (*XRRGetOutputInfo_dylibloader_wrapper_xrandr)( Display*, XRRScreenResources*, RROutput);
+void (*XRRFreeOutputInfo_dylibloader_wrapper_xrandr)( XRROutputInfo*);
+Atom* (*XRRListOutputProperties_dylibloader_wrapper_xrandr)( Display*, RROutput, int*);
+XRRPropertyInfo* (*XRRQueryOutputProperty_dylibloader_wrapper_xrandr)( Display*, RROutput, Atom);
+void (*XRRConfigureOutputProperty_dylibloader_wrapper_xrandr)( Display*, RROutput, Atom, int, int, int, long*);
+void (*XRRChangeOutputProperty_dylibloader_wrapper_xrandr)( Display*, RROutput, Atom, Atom, int, int,const unsigned char*, int);
+void (*XRRDeleteOutputProperty_dylibloader_wrapper_xrandr)( Display*, RROutput, Atom);
+int (*XRRGetOutputProperty_dylibloader_wrapper_xrandr)( Display*, RROutput, Atom, long, long, int, int, Atom, Atom*, int*, unsigned long*, unsigned long*, unsigned char**);
+XRRModeInfo* (*XRRAllocModeInfo_dylibloader_wrapper_xrandr)(const char*, int);
+RRMode (*XRRCreateMode_dylibloader_wrapper_xrandr)( Display*, Window, XRRModeInfo*);
+void (*XRRDestroyMode_dylibloader_wrapper_xrandr)( Display*, RRMode);
+void (*XRRAddOutputMode_dylibloader_wrapper_xrandr)( Display*, RROutput, RRMode);
+void (*XRRDeleteOutputMode_dylibloader_wrapper_xrandr)( Display*, RROutput, RRMode);
+void (*XRRFreeModeInfo_dylibloader_wrapper_xrandr)( XRRModeInfo*);
+XRRCrtcInfo* (*XRRGetCrtcInfo_dylibloader_wrapper_xrandr)( Display*, XRRScreenResources*, RRCrtc);
+void (*XRRFreeCrtcInfo_dylibloader_wrapper_xrandr)( XRRCrtcInfo*);
+int (*XRRSetCrtcConfig_dylibloader_wrapper_xrandr)( Display*, XRRScreenResources*, RRCrtc, Time, int, int, RRMode, Rotation, RROutput*, int);
+int (*XRRGetCrtcGammaSize_dylibloader_wrapper_xrandr)( Display*, RRCrtc);
+XRRCrtcGamma* (*XRRGetCrtcGamma_dylibloader_wrapper_xrandr)( Display*, RRCrtc);
+XRRCrtcGamma* (*XRRAllocGamma_dylibloader_wrapper_xrandr)( int);
+void (*XRRSetCrtcGamma_dylibloader_wrapper_xrandr)( Display*, RRCrtc, XRRCrtcGamma*);
+void (*XRRFreeGamma_dylibloader_wrapper_xrandr)( XRRCrtcGamma*);
+XRRScreenResources* (*XRRGetScreenResourcesCurrent_dylibloader_wrapper_xrandr)( Display*, Window);
+void (*XRRSetCrtcTransform_dylibloader_wrapper_xrandr)( Display*, RRCrtc, XTransform*,const char*, XFixed*, int);
+int (*XRRGetCrtcTransform_dylibloader_wrapper_xrandr)( Display*, RRCrtc, XRRCrtcTransformAttributes**);
+int (*XRRUpdateConfiguration_dylibloader_wrapper_xrandr)( XEvent*);
+XRRPanning* (*XRRGetPanning_dylibloader_wrapper_xrandr)( Display*, XRRScreenResources*, RRCrtc);
+void (*XRRFreePanning_dylibloader_wrapper_xrandr)( XRRPanning*);
+int (*XRRSetPanning_dylibloader_wrapper_xrandr)( Display*, XRRScreenResources*, RRCrtc, XRRPanning*);
+void (*XRRSetOutputPrimary_dylibloader_wrapper_xrandr)( Display*, Window, RROutput);
+RROutput (*XRRGetOutputPrimary_dylibloader_wrapper_xrandr)( Display*, Window);
+XRRProviderResources* (*XRRGetProviderResources_dylibloader_wrapper_xrandr)( Display*, Window);
+void (*XRRFreeProviderResources_dylibloader_wrapper_xrandr)( XRRProviderResources*);
+XRRProviderInfo* (*XRRGetProviderInfo_dylibloader_wrapper_xrandr)( Display*, XRRScreenResources*, RRProvider);
+void (*XRRFreeProviderInfo_dylibloader_wrapper_xrandr)( XRRProviderInfo*);
+int (*XRRSetProviderOutputSource_dylibloader_wrapper_xrandr)( Display*, XID, XID);
+int (*XRRSetProviderOffloadSink_dylibloader_wrapper_xrandr)( Display*, XID, XID);
+Atom* (*XRRListProviderProperties_dylibloader_wrapper_xrandr)( Display*, RRProvider, int*);
+XRRPropertyInfo* (*XRRQueryProviderProperty_dylibloader_wrapper_xrandr)( Display*, RRProvider, Atom);
+void (*XRRConfigureProviderProperty_dylibloader_wrapper_xrandr)( Display*, RRProvider, Atom, int, int, int, long*);
+void (*XRRChangeProviderProperty_dylibloader_wrapper_xrandr)( Display*, RRProvider, Atom, Atom, int, int,const unsigned char*, int);
+void (*XRRDeleteProviderProperty_dylibloader_wrapper_xrandr)( Display*, RRProvider, Atom);
+int (*XRRGetProviderProperty_dylibloader_wrapper_xrandr)( Display*, RRProvider, Atom, long, long, int, int, Atom, Atom*, int*, unsigned long*, unsigned long*, unsigned char**);
+XRRMonitorInfo* (*XRRAllocateMonitor_dylibloader_wrapper_xrandr)( Display*, int);
+XRRMonitorInfo* (*XRRGetMonitors_dylibloader_wrapper_xrandr)( Display*, Window, int, int*);
+void (*XRRSetMonitor_dylibloader_wrapper_xrandr)( Display*, Window, XRRMonitorInfo*);
+void (*XRRDeleteMonitor_dylibloader_wrapper_xrandr)( Display*, Window, Atom);
+void (*XRRFreeMonitors_dylibloader_wrapper_xrandr)( XRRMonitorInfo*);
+int initialize_xrandr(int verbose) {
+ void *handle;
+ char *error;
+ handle = dlopen("libXrandr.so.2", RTLD_LAZY);
+ if (!handle) {
+ if (verbose) {
+ fprintf(stderr, "%s\n", dlerror());
+ }
+ return(1);
+ }
+ dlerror();
+// XRRQueryExtension
+ *(void **) (&XRRQueryExtension_dylibloader_wrapper_xrandr) = dlsym(handle, "XRRQueryExtension");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRRQueryVersion
+ *(void **) (&XRRQueryVersion_dylibloader_wrapper_xrandr) = dlsym(handle, "XRRQueryVersion");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRRGetScreenInfo
+ *(void **) (&XRRGetScreenInfo_dylibloader_wrapper_xrandr) = dlsym(handle, "XRRGetScreenInfo");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRRFreeScreenConfigInfo
+ *(void **) (&XRRFreeScreenConfigInfo_dylibloader_wrapper_xrandr) = dlsym(handle, "XRRFreeScreenConfigInfo");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRRSetScreenConfig
+ *(void **) (&XRRSetScreenConfig_dylibloader_wrapper_xrandr) = dlsym(handle, "XRRSetScreenConfig");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRRSetScreenConfigAndRate
+ *(void **) (&XRRSetScreenConfigAndRate_dylibloader_wrapper_xrandr) = dlsym(handle, "XRRSetScreenConfigAndRate");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRRConfigRotations
+ *(void **) (&XRRConfigRotations_dylibloader_wrapper_xrandr) = dlsym(handle, "XRRConfigRotations");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRRConfigTimes
+ *(void **) (&XRRConfigTimes_dylibloader_wrapper_xrandr) = dlsym(handle, "XRRConfigTimes");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRRConfigSizes
+ *(void **) (&XRRConfigSizes_dylibloader_wrapper_xrandr) = dlsym(handle, "XRRConfigSizes");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRRConfigRates
+ *(void **) (&XRRConfigRates_dylibloader_wrapper_xrandr) = dlsym(handle, "XRRConfigRates");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRRConfigCurrentConfiguration
+ *(void **) (&XRRConfigCurrentConfiguration_dylibloader_wrapper_xrandr) = dlsym(handle, "XRRConfigCurrentConfiguration");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRRConfigCurrentRate
+ *(void **) (&XRRConfigCurrentRate_dylibloader_wrapper_xrandr) = dlsym(handle, "XRRConfigCurrentRate");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRRRootToScreen
+ *(void **) (&XRRRootToScreen_dylibloader_wrapper_xrandr) = dlsym(handle, "XRRRootToScreen");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRRSelectInput
+ *(void **) (&XRRSelectInput_dylibloader_wrapper_xrandr) = dlsym(handle, "XRRSelectInput");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRRRotations
+ *(void **) (&XRRRotations_dylibloader_wrapper_xrandr) = dlsym(handle, "XRRRotations");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRRSizes
+ *(void **) (&XRRSizes_dylibloader_wrapper_xrandr) = dlsym(handle, "XRRSizes");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRRRates
+ *(void **) (&XRRRates_dylibloader_wrapper_xrandr) = dlsym(handle, "XRRRates");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRRTimes
+ *(void **) (&XRRTimes_dylibloader_wrapper_xrandr) = dlsym(handle, "XRRTimes");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRRGetScreenSizeRange
+ *(void **) (&XRRGetScreenSizeRange_dylibloader_wrapper_xrandr) = dlsym(handle, "XRRGetScreenSizeRange");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRRSetScreenSize
+ *(void **) (&XRRSetScreenSize_dylibloader_wrapper_xrandr) = dlsym(handle, "XRRSetScreenSize");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRRGetScreenResources
+ *(void **) (&XRRGetScreenResources_dylibloader_wrapper_xrandr) = dlsym(handle, "XRRGetScreenResources");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRRFreeScreenResources
+ *(void **) (&XRRFreeScreenResources_dylibloader_wrapper_xrandr) = dlsym(handle, "XRRFreeScreenResources");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRRGetOutputInfo
+ *(void **) (&XRRGetOutputInfo_dylibloader_wrapper_xrandr) = dlsym(handle, "XRRGetOutputInfo");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRRFreeOutputInfo
+ *(void **) (&XRRFreeOutputInfo_dylibloader_wrapper_xrandr) = dlsym(handle, "XRRFreeOutputInfo");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRRListOutputProperties
+ *(void **) (&XRRListOutputProperties_dylibloader_wrapper_xrandr) = dlsym(handle, "XRRListOutputProperties");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRRQueryOutputProperty
+ *(void **) (&XRRQueryOutputProperty_dylibloader_wrapper_xrandr) = dlsym(handle, "XRRQueryOutputProperty");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRRConfigureOutputProperty
+ *(void **) (&XRRConfigureOutputProperty_dylibloader_wrapper_xrandr) = dlsym(handle, "XRRConfigureOutputProperty");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRRChangeOutputProperty
+ *(void **) (&XRRChangeOutputProperty_dylibloader_wrapper_xrandr) = dlsym(handle, "XRRChangeOutputProperty");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRRDeleteOutputProperty
+ *(void **) (&XRRDeleteOutputProperty_dylibloader_wrapper_xrandr) = dlsym(handle, "XRRDeleteOutputProperty");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRRGetOutputProperty
+ *(void **) (&XRRGetOutputProperty_dylibloader_wrapper_xrandr) = dlsym(handle, "XRRGetOutputProperty");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRRAllocModeInfo
+ *(void **) (&XRRAllocModeInfo_dylibloader_wrapper_xrandr) = dlsym(handle, "XRRAllocModeInfo");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRRCreateMode
+ *(void **) (&XRRCreateMode_dylibloader_wrapper_xrandr) = dlsym(handle, "XRRCreateMode");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRRDestroyMode
+ *(void **) (&XRRDestroyMode_dylibloader_wrapper_xrandr) = dlsym(handle, "XRRDestroyMode");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRRAddOutputMode
+ *(void **) (&XRRAddOutputMode_dylibloader_wrapper_xrandr) = dlsym(handle, "XRRAddOutputMode");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRRDeleteOutputMode
+ *(void **) (&XRRDeleteOutputMode_dylibloader_wrapper_xrandr) = dlsym(handle, "XRRDeleteOutputMode");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRRFreeModeInfo
+ *(void **) (&XRRFreeModeInfo_dylibloader_wrapper_xrandr) = dlsym(handle, "XRRFreeModeInfo");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRRGetCrtcInfo
+ *(void **) (&XRRGetCrtcInfo_dylibloader_wrapper_xrandr) = dlsym(handle, "XRRGetCrtcInfo");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRRFreeCrtcInfo
+ *(void **) (&XRRFreeCrtcInfo_dylibloader_wrapper_xrandr) = dlsym(handle, "XRRFreeCrtcInfo");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRRSetCrtcConfig
+ *(void **) (&XRRSetCrtcConfig_dylibloader_wrapper_xrandr) = dlsym(handle, "XRRSetCrtcConfig");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRRGetCrtcGammaSize
+ *(void **) (&XRRGetCrtcGammaSize_dylibloader_wrapper_xrandr) = dlsym(handle, "XRRGetCrtcGammaSize");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRRGetCrtcGamma
+ *(void **) (&XRRGetCrtcGamma_dylibloader_wrapper_xrandr) = dlsym(handle, "XRRGetCrtcGamma");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRRAllocGamma
+ *(void **) (&XRRAllocGamma_dylibloader_wrapper_xrandr) = dlsym(handle, "XRRAllocGamma");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRRSetCrtcGamma
+ *(void **) (&XRRSetCrtcGamma_dylibloader_wrapper_xrandr) = dlsym(handle, "XRRSetCrtcGamma");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRRFreeGamma
+ *(void **) (&XRRFreeGamma_dylibloader_wrapper_xrandr) = dlsym(handle, "XRRFreeGamma");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRRGetScreenResourcesCurrent
+ *(void **) (&XRRGetScreenResourcesCurrent_dylibloader_wrapper_xrandr) = dlsym(handle, "XRRGetScreenResourcesCurrent");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRRSetCrtcTransform
+ *(void **) (&XRRSetCrtcTransform_dylibloader_wrapper_xrandr) = dlsym(handle, "XRRSetCrtcTransform");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRRGetCrtcTransform
+ *(void **) (&XRRGetCrtcTransform_dylibloader_wrapper_xrandr) = dlsym(handle, "XRRGetCrtcTransform");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRRUpdateConfiguration
+ *(void **) (&XRRUpdateConfiguration_dylibloader_wrapper_xrandr) = dlsym(handle, "XRRUpdateConfiguration");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRRGetPanning
+ *(void **) (&XRRGetPanning_dylibloader_wrapper_xrandr) = dlsym(handle, "XRRGetPanning");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRRFreePanning
+ *(void **) (&XRRFreePanning_dylibloader_wrapper_xrandr) = dlsym(handle, "XRRFreePanning");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRRSetPanning
+ *(void **) (&XRRSetPanning_dylibloader_wrapper_xrandr) = dlsym(handle, "XRRSetPanning");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRRSetOutputPrimary
+ *(void **) (&XRRSetOutputPrimary_dylibloader_wrapper_xrandr) = dlsym(handle, "XRRSetOutputPrimary");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRRGetOutputPrimary
+ *(void **) (&XRRGetOutputPrimary_dylibloader_wrapper_xrandr) = dlsym(handle, "XRRGetOutputPrimary");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRRGetProviderResources
+ *(void **) (&XRRGetProviderResources_dylibloader_wrapper_xrandr) = dlsym(handle, "XRRGetProviderResources");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRRFreeProviderResources
+ *(void **) (&XRRFreeProviderResources_dylibloader_wrapper_xrandr) = dlsym(handle, "XRRFreeProviderResources");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRRGetProviderInfo
+ *(void **) (&XRRGetProviderInfo_dylibloader_wrapper_xrandr) = dlsym(handle, "XRRGetProviderInfo");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRRFreeProviderInfo
+ *(void **) (&XRRFreeProviderInfo_dylibloader_wrapper_xrandr) = dlsym(handle, "XRRFreeProviderInfo");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRRSetProviderOutputSource
+ *(void **) (&XRRSetProviderOutputSource_dylibloader_wrapper_xrandr) = dlsym(handle, "XRRSetProviderOutputSource");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRRSetProviderOffloadSink
+ *(void **) (&XRRSetProviderOffloadSink_dylibloader_wrapper_xrandr) = dlsym(handle, "XRRSetProviderOffloadSink");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRRListProviderProperties
+ *(void **) (&XRRListProviderProperties_dylibloader_wrapper_xrandr) = dlsym(handle, "XRRListProviderProperties");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRRQueryProviderProperty
+ *(void **) (&XRRQueryProviderProperty_dylibloader_wrapper_xrandr) = dlsym(handle, "XRRQueryProviderProperty");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRRConfigureProviderProperty
+ *(void **) (&XRRConfigureProviderProperty_dylibloader_wrapper_xrandr) = dlsym(handle, "XRRConfigureProviderProperty");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRRChangeProviderProperty
+ *(void **) (&XRRChangeProviderProperty_dylibloader_wrapper_xrandr) = dlsym(handle, "XRRChangeProviderProperty");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRRDeleteProviderProperty
+ *(void **) (&XRRDeleteProviderProperty_dylibloader_wrapper_xrandr) = dlsym(handle, "XRRDeleteProviderProperty");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRRGetProviderProperty
+ *(void **) (&XRRGetProviderProperty_dylibloader_wrapper_xrandr) = dlsym(handle, "XRRGetProviderProperty");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRRAllocateMonitor
+ *(void **) (&XRRAllocateMonitor_dylibloader_wrapper_xrandr) = dlsym(handle, "XRRAllocateMonitor");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRRGetMonitors
+ *(void **) (&XRRGetMonitors_dylibloader_wrapper_xrandr) = dlsym(handle, "XRRGetMonitors");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRRSetMonitor
+ *(void **) (&XRRSetMonitor_dylibloader_wrapper_xrandr) = dlsym(handle, "XRRSetMonitor");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRRDeleteMonitor
+ *(void **) (&XRRDeleteMonitor_dylibloader_wrapper_xrandr) = dlsym(handle, "XRRDeleteMonitor");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRRFreeMonitors
+ *(void **) (&XRRFreeMonitors_dylibloader_wrapper_xrandr) = dlsym(handle, "XRRFreeMonitors");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+return 0;
+}
diff --git a/platform/linuxbsd/x11/dynwrappers/xrandr-so_wrap.h b/platform/linuxbsd/x11/dynwrappers/xrandr-so_wrap.h
new file mode 100644
index 0000000000..046d4c7de3
--- /dev/null
+++ b/platform/linuxbsd/x11/dynwrappers/xrandr-so_wrap.h
@@ -0,0 +1,302 @@
+#ifndef DYLIBLOAD_WRAPPER_XRANDR
+#define DYLIBLOAD_WRAPPER_XRANDR
+// 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-12-02 12:55:12
+// flags: ./generate-wrapper.py --include /usr/include/X11/extensions/Xrandr.h --sys-include <X11/extensions/Xrandr.h> --soname libXrandr.so.2 --init-name xrandr --output-header xrandr-so_wrap.h --output-implementation xrandr-so_wrap.c
+//
+// NOTE: Generated from Xrandr 1.5.2.
+// This has been handpatched to workaround some issues with the generator that
+// will be eventually fixed. In this case, non-existent symbols inherited from
+// libX11 and libXrender, but absent in libXrandr.so.2, were removed.
+#include <stdint.h>
+
+#define XRRQueryExtension XRRQueryExtension_dylibloader_orig_xrandr
+#define XRRQueryVersion XRRQueryVersion_dylibloader_orig_xrandr
+#define XRRGetScreenInfo XRRGetScreenInfo_dylibloader_orig_xrandr
+#define XRRFreeScreenConfigInfo XRRFreeScreenConfigInfo_dylibloader_orig_xrandr
+#define XRRSetScreenConfig XRRSetScreenConfig_dylibloader_orig_xrandr
+#define XRRSetScreenConfigAndRate XRRSetScreenConfigAndRate_dylibloader_orig_xrandr
+#define XRRConfigRotations XRRConfigRotations_dylibloader_orig_xrandr
+#define XRRConfigTimes XRRConfigTimes_dylibloader_orig_xrandr
+#define XRRConfigSizes XRRConfigSizes_dylibloader_orig_xrandr
+#define XRRConfigRates XRRConfigRates_dylibloader_orig_xrandr
+#define XRRConfigCurrentConfiguration XRRConfigCurrentConfiguration_dylibloader_orig_xrandr
+#define XRRConfigCurrentRate XRRConfigCurrentRate_dylibloader_orig_xrandr
+#define XRRRootToScreen XRRRootToScreen_dylibloader_orig_xrandr
+#define XRRSelectInput XRRSelectInput_dylibloader_orig_xrandr
+#define XRRRotations XRRRotations_dylibloader_orig_xrandr
+#define XRRSizes XRRSizes_dylibloader_orig_xrandr
+#define XRRRates XRRRates_dylibloader_orig_xrandr
+#define XRRTimes XRRTimes_dylibloader_orig_xrandr
+#define XRRGetScreenSizeRange XRRGetScreenSizeRange_dylibloader_orig_xrandr
+#define XRRSetScreenSize XRRSetScreenSize_dylibloader_orig_xrandr
+#define XRRGetScreenResources XRRGetScreenResources_dylibloader_orig_xrandr
+#define XRRFreeScreenResources XRRFreeScreenResources_dylibloader_orig_xrandr
+#define XRRGetOutputInfo XRRGetOutputInfo_dylibloader_orig_xrandr
+#define XRRFreeOutputInfo XRRFreeOutputInfo_dylibloader_orig_xrandr
+#define XRRListOutputProperties XRRListOutputProperties_dylibloader_orig_xrandr
+#define XRRQueryOutputProperty XRRQueryOutputProperty_dylibloader_orig_xrandr
+#define XRRConfigureOutputProperty XRRConfigureOutputProperty_dylibloader_orig_xrandr
+#define XRRChangeOutputProperty XRRChangeOutputProperty_dylibloader_orig_xrandr
+#define XRRDeleteOutputProperty XRRDeleteOutputProperty_dylibloader_orig_xrandr
+#define XRRGetOutputProperty XRRGetOutputProperty_dylibloader_orig_xrandr
+#define XRRAllocModeInfo XRRAllocModeInfo_dylibloader_orig_xrandr
+#define XRRCreateMode XRRCreateMode_dylibloader_orig_xrandr
+#define XRRDestroyMode XRRDestroyMode_dylibloader_orig_xrandr
+#define XRRAddOutputMode XRRAddOutputMode_dylibloader_orig_xrandr
+#define XRRDeleteOutputMode XRRDeleteOutputMode_dylibloader_orig_xrandr
+#define XRRFreeModeInfo XRRFreeModeInfo_dylibloader_orig_xrandr
+#define XRRGetCrtcInfo XRRGetCrtcInfo_dylibloader_orig_xrandr
+#define XRRFreeCrtcInfo XRRFreeCrtcInfo_dylibloader_orig_xrandr
+#define XRRSetCrtcConfig XRRSetCrtcConfig_dylibloader_orig_xrandr
+#define XRRGetCrtcGammaSize XRRGetCrtcGammaSize_dylibloader_orig_xrandr
+#define XRRGetCrtcGamma XRRGetCrtcGamma_dylibloader_orig_xrandr
+#define XRRAllocGamma XRRAllocGamma_dylibloader_orig_xrandr
+#define XRRSetCrtcGamma XRRSetCrtcGamma_dylibloader_orig_xrandr
+#define XRRFreeGamma XRRFreeGamma_dylibloader_orig_xrandr
+#define XRRGetScreenResourcesCurrent XRRGetScreenResourcesCurrent_dylibloader_orig_xrandr
+#define XRRSetCrtcTransform XRRSetCrtcTransform_dylibloader_orig_xrandr
+#define XRRGetCrtcTransform XRRGetCrtcTransform_dylibloader_orig_xrandr
+#define XRRUpdateConfiguration XRRUpdateConfiguration_dylibloader_orig_xrandr
+#define XRRGetPanning XRRGetPanning_dylibloader_orig_xrandr
+#define XRRFreePanning XRRFreePanning_dylibloader_orig_xrandr
+#define XRRSetPanning XRRSetPanning_dylibloader_orig_xrandr
+#define XRRSetOutputPrimary XRRSetOutputPrimary_dylibloader_orig_xrandr
+#define XRRGetOutputPrimary XRRGetOutputPrimary_dylibloader_orig_xrandr
+#define XRRGetProviderResources XRRGetProviderResources_dylibloader_orig_xrandr
+#define XRRFreeProviderResources XRRFreeProviderResources_dylibloader_orig_xrandr
+#define XRRGetProviderInfo XRRGetProviderInfo_dylibloader_orig_xrandr
+#define XRRFreeProviderInfo XRRFreeProviderInfo_dylibloader_orig_xrandr
+#define XRRSetProviderOutputSource XRRSetProviderOutputSource_dylibloader_orig_xrandr
+#define XRRSetProviderOffloadSink XRRSetProviderOffloadSink_dylibloader_orig_xrandr
+#define XRRListProviderProperties XRRListProviderProperties_dylibloader_orig_xrandr
+#define XRRQueryProviderProperty XRRQueryProviderProperty_dylibloader_orig_xrandr
+#define XRRConfigureProviderProperty XRRConfigureProviderProperty_dylibloader_orig_xrandr
+#define XRRChangeProviderProperty XRRChangeProviderProperty_dylibloader_orig_xrandr
+#define XRRDeleteProviderProperty XRRDeleteProviderProperty_dylibloader_orig_xrandr
+#define XRRGetProviderProperty XRRGetProviderProperty_dylibloader_orig_xrandr
+#define XRRAllocateMonitor XRRAllocateMonitor_dylibloader_orig_xrandr
+#define XRRGetMonitors XRRGetMonitors_dylibloader_orig_xrandr
+#define XRRSetMonitor XRRSetMonitor_dylibloader_orig_xrandr
+#define XRRDeleteMonitor XRRDeleteMonitor_dylibloader_orig_xrandr
+#define XRRFreeMonitors XRRFreeMonitors_dylibloader_orig_xrandr
+#include <X11/extensions/Xrandr.h>
+#undef XRRQueryExtension
+#undef XRRQueryVersion
+#undef XRRGetScreenInfo
+#undef XRRFreeScreenConfigInfo
+#undef XRRSetScreenConfig
+#undef XRRSetScreenConfigAndRate
+#undef XRRConfigRotations
+#undef XRRConfigTimes
+#undef XRRConfigSizes
+#undef XRRConfigRates
+#undef XRRConfigCurrentConfiguration
+#undef XRRConfigCurrentRate
+#undef XRRRootToScreen
+#undef XRRSelectInput
+#undef XRRRotations
+#undef XRRSizes
+#undef XRRRates
+#undef XRRTimes
+#undef XRRGetScreenSizeRange
+#undef XRRSetScreenSize
+#undef XRRGetScreenResources
+#undef XRRFreeScreenResources
+#undef XRRGetOutputInfo
+#undef XRRFreeOutputInfo
+#undef XRRListOutputProperties
+#undef XRRQueryOutputProperty
+#undef XRRConfigureOutputProperty
+#undef XRRChangeOutputProperty
+#undef XRRDeleteOutputProperty
+#undef XRRGetOutputProperty
+#undef XRRAllocModeInfo
+#undef XRRCreateMode
+#undef XRRDestroyMode
+#undef XRRAddOutputMode
+#undef XRRDeleteOutputMode
+#undef XRRFreeModeInfo
+#undef XRRGetCrtcInfo
+#undef XRRFreeCrtcInfo
+#undef XRRSetCrtcConfig
+#undef XRRGetCrtcGammaSize
+#undef XRRGetCrtcGamma
+#undef XRRAllocGamma
+#undef XRRSetCrtcGamma
+#undef XRRFreeGamma
+#undef XRRGetScreenResourcesCurrent
+#undef XRRSetCrtcTransform
+#undef XRRGetCrtcTransform
+#undef XRRUpdateConfiguration
+#undef XRRGetPanning
+#undef XRRFreePanning
+#undef XRRSetPanning
+#undef XRRSetOutputPrimary
+#undef XRRGetOutputPrimary
+#undef XRRGetProviderResources
+#undef XRRFreeProviderResources
+#undef XRRGetProviderInfo
+#undef XRRFreeProviderInfo
+#undef XRRSetProviderOutputSource
+#undef XRRSetProviderOffloadSink
+#undef XRRListProviderProperties
+#undef XRRQueryProviderProperty
+#undef XRRConfigureProviderProperty
+#undef XRRChangeProviderProperty
+#undef XRRDeleteProviderProperty
+#undef XRRGetProviderProperty
+#undef XRRAllocateMonitor
+#undef XRRGetMonitors
+#undef XRRSetMonitor
+#undef XRRDeleteMonitor
+#undef XRRFreeMonitors
+#ifdef __cplusplus
+extern "C" {
+#endif
+#define XRRQueryExtension XRRQueryExtension_dylibloader_wrapper_xrandr
+#define XRRQueryVersion XRRQueryVersion_dylibloader_wrapper_xrandr
+#define XRRGetScreenInfo XRRGetScreenInfo_dylibloader_wrapper_xrandr
+#define XRRFreeScreenConfigInfo XRRFreeScreenConfigInfo_dylibloader_wrapper_xrandr
+#define XRRSetScreenConfig XRRSetScreenConfig_dylibloader_wrapper_xrandr
+#define XRRSetScreenConfigAndRate XRRSetScreenConfigAndRate_dylibloader_wrapper_xrandr
+#define XRRConfigRotations XRRConfigRotations_dylibloader_wrapper_xrandr
+#define XRRConfigTimes XRRConfigTimes_dylibloader_wrapper_xrandr
+#define XRRConfigSizes XRRConfigSizes_dylibloader_wrapper_xrandr
+#define XRRConfigRates XRRConfigRates_dylibloader_wrapper_xrandr
+#define XRRConfigCurrentConfiguration XRRConfigCurrentConfiguration_dylibloader_wrapper_xrandr
+#define XRRConfigCurrentRate XRRConfigCurrentRate_dylibloader_wrapper_xrandr
+#define XRRRootToScreen XRRRootToScreen_dylibloader_wrapper_xrandr
+#define XRRSelectInput XRRSelectInput_dylibloader_wrapper_xrandr
+#define XRRRotations XRRRotations_dylibloader_wrapper_xrandr
+#define XRRSizes XRRSizes_dylibloader_wrapper_xrandr
+#define XRRRates XRRRates_dylibloader_wrapper_xrandr
+#define XRRTimes XRRTimes_dylibloader_wrapper_xrandr
+#define XRRGetScreenSizeRange XRRGetScreenSizeRange_dylibloader_wrapper_xrandr
+#define XRRSetScreenSize XRRSetScreenSize_dylibloader_wrapper_xrandr
+#define XRRGetScreenResources XRRGetScreenResources_dylibloader_wrapper_xrandr
+#define XRRFreeScreenResources XRRFreeScreenResources_dylibloader_wrapper_xrandr
+#define XRRGetOutputInfo XRRGetOutputInfo_dylibloader_wrapper_xrandr
+#define XRRFreeOutputInfo XRRFreeOutputInfo_dylibloader_wrapper_xrandr
+#define XRRListOutputProperties XRRListOutputProperties_dylibloader_wrapper_xrandr
+#define XRRQueryOutputProperty XRRQueryOutputProperty_dylibloader_wrapper_xrandr
+#define XRRConfigureOutputProperty XRRConfigureOutputProperty_dylibloader_wrapper_xrandr
+#define XRRChangeOutputProperty XRRChangeOutputProperty_dylibloader_wrapper_xrandr
+#define XRRDeleteOutputProperty XRRDeleteOutputProperty_dylibloader_wrapper_xrandr
+#define XRRGetOutputProperty XRRGetOutputProperty_dylibloader_wrapper_xrandr
+#define XRRAllocModeInfo XRRAllocModeInfo_dylibloader_wrapper_xrandr
+#define XRRCreateMode XRRCreateMode_dylibloader_wrapper_xrandr
+#define XRRDestroyMode XRRDestroyMode_dylibloader_wrapper_xrandr
+#define XRRAddOutputMode XRRAddOutputMode_dylibloader_wrapper_xrandr
+#define XRRDeleteOutputMode XRRDeleteOutputMode_dylibloader_wrapper_xrandr
+#define XRRFreeModeInfo XRRFreeModeInfo_dylibloader_wrapper_xrandr
+#define XRRGetCrtcInfo XRRGetCrtcInfo_dylibloader_wrapper_xrandr
+#define XRRFreeCrtcInfo XRRFreeCrtcInfo_dylibloader_wrapper_xrandr
+#define XRRSetCrtcConfig XRRSetCrtcConfig_dylibloader_wrapper_xrandr
+#define XRRGetCrtcGammaSize XRRGetCrtcGammaSize_dylibloader_wrapper_xrandr
+#define XRRGetCrtcGamma XRRGetCrtcGamma_dylibloader_wrapper_xrandr
+#define XRRAllocGamma XRRAllocGamma_dylibloader_wrapper_xrandr
+#define XRRSetCrtcGamma XRRSetCrtcGamma_dylibloader_wrapper_xrandr
+#define XRRFreeGamma XRRFreeGamma_dylibloader_wrapper_xrandr
+#define XRRGetScreenResourcesCurrent XRRGetScreenResourcesCurrent_dylibloader_wrapper_xrandr
+#define XRRSetCrtcTransform XRRSetCrtcTransform_dylibloader_wrapper_xrandr
+#define XRRGetCrtcTransform XRRGetCrtcTransform_dylibloader_wrapper_xrandr
+#define XRRUpdateConfiguration XRRUpdateConfiguration_dylibloader_wrapper_xrandr
+#define XRRGetPanning XRRGetPanning_dylibloader_wrapper_xrandr
+#define XRRFreePanning XRRFreePanning_dylibloader_wrapper_xrandr
+#define XRRSetPanning XRRSetPanning_dylibloader_wrapper_xrandr
+#define XRRSetOutputPrimary XRRSetOutputPrimary_dylibloader_wrapper_xrandr
+#define XRRGetOutputPrimary XRRGetOutputPrimary_dylibloader_wrapper_xrandr
+#define XRRGetProviderResources XRRGetProviderResources_dylibloader_wrapper_xrandr
+#define XRRFreeProviderResources XRRFreeProviderResources_dylibloader_wrapper_xrandr
+#define XRRGetProviderInfo XRRGetProviderInfo_dylibloader_wrapper_xrandr
+#define XRRFreeProviderInfo XRRFreeProviderInfo_dylibloader_wrapper_xrandr
+#define XRRSetProviderOutputSource XRRSetProviderOutputSource_dylibloader_wrapper_xrandr
+#define XRRSetProviderOffloadSink XRRSetProviderOffloadSink_dylibloader_wrapper_xrandr
+#define XRRListProviderProperties XRRListProviderProperties_dylibloader_wrapper_xrandr
+#define XRRQueryProviderProperty XRRQueryProviderProperty_dylibloader_wrapper_xrandr
+#define XRRConfigureProviderProperty XRRConfigureProviderProperty_dylibloader_wrapper_xrandr
+#define XRRChangeProviderProperty XRRChangeProviderProperty_dylibloader_wrapper_xrandr
+#define XRRDeleteProviderProperty XRRDeleteProviderProperty_dylibloader_wrapper_xrandr
+#define XRRGetProviderProperty XRRGetProviderProperty_dylibloader_wrapper_xrandr
+#define XRRAllocateMonitor XRRAllocateMonitor_dylibloader_wrapper_xrandr
+#define XRRGetMonitors XRRGetMonitors_dylibloader_wrapper_xrandr
+#define XRRSetMonitor XRRSetMonitor_dylibloader_wrapper_xrandr
+#define XRRDeleteMonitor XRRDeleteMonitor_dylibloader_wrapper_xrandr
+#define XRRFreeMonitors XRRFreeMonitors_dylibloader_wrapper_xrandr
+extern int (*XRRQueryExtension_dylibloader_wrapper_xrandr)( Display*, int*, int*);
+extern int (*XRRQueryVersion_dylibloader_wrapper_xrandr)( Display*, int*, int*);
+extern XRRScreenConfiguration* (*XRRGetScreenInfo_dylibloader_wrapper_xrandr)( Display*, Window);
+extern void (*XRRFreeScreenConfigInfo_dylibloader_wrapper_xrandr)( XRRScreenConfiguration*);
+extern int (*XRRSetScreenConfig_dylibloader_wrapper_xrandr)( Display*, XRRScreenConfiguration*, Drawable, int, Rotation, Time);
+extern int (*XRRSetScreenConfigAndRate_dylibloader_wrapper_xrandr)( Display*, XRRScreenConfiguration*, Drawable, int, Rotation, short, Time);
+extern Rotation (*XRRConfigRotations_dylibloader_wrapper_xrandr)( XRRScreenConfiguration*, Rotation*);
+extern Time (*XRRConfigTimes_dylibloader_wrapper_xrandr)( XRRScreenConfiguration*, Time*);
+extern XRRScreenSize* (*XRRConfigSizes_dylibloader_wrapper_xrandr)( XRRScreenConfiguration*, int*);
+extern short* (*XRRConfigRates_dylibloader_wrapper_xrandr)( XRRScreenConfiguration*, int, int*);
+extern SizeID (*XRRConfigCurrentConfiguration_dylibloader_wrapper_xrandr)( XRRScreenConfiguration*, Rotation*);
+extern short (*XRRConfigCurrentRate_dylibloader_wrapper_xrandr)( XRRScreenConfiguration*);
+extern int (*XRRRootToScreen_dylibloader_wrapper_xrandr)( Display*, Window);
+extern void (*XRRSelectInput_dylibloader_wrapper_xrandr)( Display*, Window, int);
+extern Rotation (*XRRRotations_dylibloader_wrapper_xrandr)( Display*, int, Rotation*);
+extern XRRScreenSize* (*XRRSizes_dylibloader_wrapper_xrandr)( Display*, int, int*);
+extern short* (*XRRRates_dylibloader_wrapper_xrandr)( Display*, int, int, int*);
+extern Time (*XRRTimes_dylibloader_wrapper_xrandr)( Display*, int, Time*);
+extern int (*XRRGetScreenSizeRange_dylibloader_wrapper_xrandr)( Display*, Window, int*, int*, int*, int*);
+extern void (*XRRSetScreenSize_dylibloader_wrapper_xrandr)( Display*, Window, int, int, int, int);
+extern XRRScreenResources* (*XRRGetScreenResources_dylibloader_wrapper_xrandr)( Display*, Window);
+extern void (*XRRFreeScreenResources_dylibloader_wrapper_xrandr)( XRRScreenResources*);
+extern XRROutputInfo* (*XRRGetOutputInfo_dylibloader_wrapper_xrandr)( Display*, XRRScreenResources*, RROutput);
+extern void (*XRRFreeOutputInfo_dylibloader_wrapper_xrandr)( XRROutputInfo*);
+extern Atom* (*XRRListOutputProperties_dylibloader_wrapper_xrandr)( Display*, RROutput, int*);
+extern XRRPropertyInfo* (*XRRQueryOutputProperty_dylibloader_wrapper_xrandr)( Display*, RROutput, Atom);
+extern void (*XRRConfigureOutputProperty_dylibloader_wrapper_xrandr)( Display*, RROutput, Atom, int, int, int, long*);
+extern void (*XRRChangeOutputProperty_dylibloader_wrapper_xrandr)( Display*, RROutput, Atom, Atom, int, int,const unsigned char*, int);
+extern void (*XRRDeleteOutputProperty_dylibloader_wrapper_xrandr)( Display*, RROutput, Atom);
+extern int (*XRRGetOutputProperty_dylibloader_wrapper_xrandr)( Display*, RROutput, Atom, long, long, int, int, Atom, Atom*, int*, unsigned long*, unsigned long*, unsigned char**);
+extern XRRModeInfo* (*XRRAllocModeInfo_dylibloader_wrapper_xrandr)(const char*, int);
+extern RRMode (*XRRCreateMode_dylibloader_wrapper_xrandr)( Display*, Window, XRRModeInfo*);
+extern void (*XRRDestroyMode_dylibloader_wrapper_xrandr)( Display*, RRMode);
+extern void (*XRRAddOutputMode_dylibloader_wrapper_xrandr)( Display*, RROutput, RRMode);
+extern void (*XRRDeleteOutputMode_dylibloader_wrapper_xrandr)( Display*, RROutput, RRMode);
+extern void (*XRRFreeModeInfo_dylibloader_wrapper_xrandr)( XRRModeInfo*);
+extern XRRCrtcInfo* (*XRRGetCrtcInfo_dylibloader_wrapper_xrandr)( Display*, XRRScreenResources*, RRCrtc);
+extern void (*XRRFreeCrtcInfo_dylibloader_wrapper_xrandr)( XRRCrtcInfo*);
+extern int (*XRRSetCrtcConfig_dylibloader_wrapper_xrandr)( Display*, XRRScreenResources*, RRCrtc, Time, int, int, RRMode, Rotation, RROutput*, int);
+extern int (*XRRGetCrtcGammaSize_dylibloader_wrapper_xrandr)( Display*, RRCrtc);
+extern XRRCrtcGamma* (*XRRGetCrtcGamma_dylibloader_wrapper_xrandr)( Display*, RRCrtc);
+extern XRRCrtcGamma* (*XRRAllocGamma_dylibloader_wrapper_xrandr)( int);
+extern void (*XRRSetCrtcGamma_dylibloader_wrapper_xrandr)( Display*, RRCrtc, XRRCrtcGamma*);
+extern void (*XRRFreeGamma_dylibloader_wrapper_xrandr)( XRRCrtcGamma*);
+extern XRRScreenResources* (*XRRGetScreenResourcesCurrent_dylibloader_wrapper_xrandr)( Display*, Window);
+extern void (*XRRSetCrtcTransform_dylibloader_wrapper_xrandr)( Display*, RRCrtc, XTransform*,const char*, XFixed*, int);
+extern int (*XRRGetCrtcTransform_dylibloader_wrapper_xrandr)( Display*, RRCrtc, XRRCrtcTransformAttributes**);
+extern int (*XRRUpdateConfiguration_dylibloader_wrapper_xrandr)( XEvent*);
+extern XRRPanning* (*XRRGetPanning_dylibloader_wrapper_xrandr)( Display*, XRRScreenResources*, RRCrtc);
+extern void (*XRRFreePanning_dylibloader_wrapper_xrandr)( XRRPanning*);
+extern int (*XRRSetPanning_dylibloader_wrapper_xrandr)( Display*, XRRScreenResources*, RRCrtc, XRRPanning*);
+extern void (*XRRSetOutputPrimary_dylibloader_wrapper_xrandr)( Display*, Window, RROutput);
+extern RROutput (*XRRGetOutputPrimary_dylibloader_wrapper_xrandr)( Display*, Window);
+extern XRRProviderResources* (*XRRGetProviderResources_dylibloader_wrapper_xrandr)( Display*, Window);
+extern void (*XRRFreeProviderResources_dylibloader_wrapper_xrandr)( XRRProviderResources*);
+extern XRRProviderInfo* (*XRRGetProviderInfo_dylibloader_wrapper_xrandr)( Display*, XRRScreenResources*, RRProvider);
+extern void (*XRRFreeProviderInfo_dylibloader_wrapper_xrandr)( XRRProviderInfo*);
+extern int (*XRRSetProviderOutputSource_dylibloader_wrapper_xrandr)( Display*, XID, XID);
+extern int (*XRRSetProviderOffloadSink_dylibloader_wrapper_xrandr)( Display*, XID, XID);
+extern Atom* (*XRRListProviderProperties_dylibloader_wrapper_xrandr)( Display*, RRProvider, int*);
+extern XRRPropertyInfo* (*XRRQueryProviderProperty_dylibloader_wrapper_xrandr)( Display*, RRProvider, Atom);
+extern void (*XRRConfigureProviderProperty_dylibloader_wrapper_xrandr)( Display*, RRProvider, Atom, int, int, int, long*);
+extern void (*XRRChangeProviderProperty_dylibloader_wrapper_xrandr)( Display*, RRProvider, Atom, Atom, int, int,const unsigned char*, int);
+extern void (*XRRDeleteProviderProperty_dylibloader_wrapper_xrandr)( Display*, RRProvider, Atom);
+extern int (*XRRGetProviderProperty_dylibloader_wrapper_xrandr)( Display*, RRProvider, Atom, long, long, int, int, Atom, Atom*, int*, unsigned long*, unsigned long*, unsigned char**);
+extern XRRMonitorInfo* (*XRRAllocateMonitor_dylibloader_wrapper_xrandr)( Display*, int);
+extern XRRMonitorInfo* (*XRRGetMonitors_dylibloader_wrapper_xrandr)( Display*, Window, int, int*);
+extern void (*XRRSetMonitor_dylibloader_wrapper_xrandr)( Display*, Window, XRRMonitorInfo*);
+extern void (*XRRDeleteMonitor_dylibloader_wrapper_xrandr)( Display*, Window, Atom);
+extern void (*XRRFreeMonitors_dylibloader_wrapper_xrandr)( XRRMonitorInfo*);
+int initialize_xrandr(int verbose);
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/platform/linuxbsd/x11/dynwrappers/xrender-so_wrap.c b/platform/linuxbsd/x11/dynwrappers/xrender-so_wrap.c
new file mode 100644
index 0000000000..2d3847e584
--- /dev/null
+++ b/platform/linuxbsd/x11/dynwrappers/xrender-so_wrap.c
@@ -0,0 +1,511 @@
+// 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-12-02 12:55:28
+// flags: ./generate-wrapper.py --include /usr/include/X11/extensions/Xrender.h --sys-include <X11/extensions/Xrender.h> --soname libXrender.so.1 --init-name xrender --output-header xrender-so_wrap.h --output-implementation xrender-so_wrap.c
+//
+// NOTE: Generated from Xrender 0.9.10.
+// This has been handpatched to workaround some issues with the generator that
+// will be eventually fixed. In this case, non-existent symbols inherited from
+// libX11, but absent in libXrender.so.1, were removed.
+#include <stdint.h>
+
+#define XRenderQueryExtension XRenderQueryExtension_dylibloader_orig_xrender
+#define XRenderQueryVersion XRenderQueryVersion_dylibloader_orig_xrender
+#define XRenderQueryFormats XRenderQueryFormats_dylibloader_orig_xrender
+#define XRenderQuerySubpixelOrder XRenderQuerySubpixelOrder_dylibloader_orig_xrender
+#define XRenderSetSubpixelOrder XRenderSetSubpixelOrder_dylibloader_orig_xrender
+#define XRenderFindVisualFormat XRenderFindVisualFormat_dylibloader_orig_xrender
+#define XRenderFindFormat XRenderFindFormat_dylibloader_orig_xrender
+#define XRenderFindStandardFormat XRenderFindStandardFormat_dylibloader_orig_xrender
+#define XRenderQueryPictIndexValues XRenderQueryPictIndexValues_dylibloader_orig_xrender
+#define XRenderCreatePicture XRenderCreatePicture_dylibloader_orig_xrender
+#define XRenderChangePicture XRenderChangePicture_dylibloader_orig_xrender
+#define XRenderSetPictureClipRectangles XRenderSetPictureClipRectangles_dylibloader_orig_xrender
+#define XRenderSetPictureClipRegion XRenderSetPictureClipRegion_dylibloader_orig_xrender
+#define XRenderSetPictureTransform XRenderSetPictureTransform_dylibloader_orig_xrender
+#define XRenderFreePicture XRenderFreePicture_dylibloader_orig_xrender
+#define XRenderComposite XRenderComposite_dylibloader_orig_xrender
+#define XRenderCreateGlyphSet XRenderCreateGlyphSet_dylibloader_orig_xrender
+#define XRenderReferenceGlyphSet XRenderReferenceGlyphSet_dylibloader_orig_xrender
+#define XRenderFreeGlyphSet XRenderFreeGlyphSet_dylibloader_orig_xrender
+#define XRenderAddGlyphs XRenderAddGlyphs_dylibloader_orig_xrender
+#define XRenderFreeGlyphs XRenderFreeGlyphs_dylibloader_orig_xrender
+#define XRenderCompositeString8 XRenderCompositeString8_dylibloader_orig_xrender
+#define XRenderCompositeString16 XRenderCompositeString16_dylibloader_orig_xrender
+#define XRenderCompositeString32 XRenderCompositeString32_dylibloader_orig_xrender
+#define XRenderCompositeText8 XRenderCompositeText8_dylibloader_orig_xrender
+#define XRenderCompositeText16 XRenderCompositeText16_dylibloader_orig_xrender
+#define XRenderCompositeText32 XRenderCompositeText32_dylibloader_orig_xrender
+#define XRenderFillRectangle XRenderFillRectangle_dylibloader_orig_xrender
+#define XRenderFillRectangles XRenderFillRectangles_dylibloader_orig_xrender
+#define XRenderCompositeTrapezoids XRenderCompositeTrapezoids_dylibloader_orig_xrender
+#define XRenderCompositeTriangles XRenderCompositeTriangles_dylibloader_orig_xrender
+#define XRenderCompositeTriStrip XRenderCompositeTriStrip_dylibloader_orig_xrender
+#define XRenderCompositeTriFan XRenderCompositeTriFan_dylibloader_orig_xrender
+#define XRenderCompositeDoublePoly XRenderCompositeDoublePoly_dylibloader_orig_xrender
+#define XRenderParseColor XRenderParseColor_dylibloader_orig_xrender
+#define XRenderCreateCursor XRenderCreateCursor_dylibloader_orig_xrender
+#define XRenderQueryFilters XRenderQueryFilters_dylibloader_orig_xrender
+#define XRenderSetPictureFilter XRenderSetPictureFilter_dylibloader_orig_xrender
+#define XRenderCreateAnimCursor XRenderCreateAnimCursor_dylibloader_orig_xrender
+#define XRenderAddTraps XRenderAddTraps_dylibloader_orig_xrender
+#define XRenderCreateSolidFill XRenderCreateSolidFill_dylibloader_orig_xrender
+#define XRenderCreateLinearGradient XRenderCreateLinearGradient_dylibloader_orig_xrender
+#define XRenderCreateRadialGradient XRenderCreateRadialGradient_dylibloader_orig_xrender
+#define XRenderCreateConicalGradient XRenderCreateConicalGradient_dylibloader_orig_xrender
+#include <X11/extensions/Xrender.h>
+#undef XRenderQueryExtension
+#undef XRenderQueryVersion
+#undef XRenderQueryFormats
+#undef XRenderQuerySubpixelOrder
+#undef XRenderSetSubpixelOrder
+#undef XRenderFindVisualFormat
+#undef XRenderFindFormat
+#undef XRenderFindStandardFormat
+#undef XRenderQueryPictIndexValues
+#undef XRenderCreatePicture
+#undef XRenderChangePicture
+#undef XRenderSetPictureClipRectangles
+#undef XRenderSetPictureClipRegion
+#undef XRenderSetPictureTransform
+#undef XRenderFreePicture
+#undef XRenderComposite
+#undef XRenderCreateGlyphSet
+#undef XRenderReferenceGlyphSet
+#undef XRenderFreeGlyphSet
+#undef XRenderAddGlyphs
+#undef XRenderFreeGlyphs
+#undef XRenderCompositeString8
+#undef XRenderCompositeString16
+#undef XRenderCompositeString32
+#undef XRenderCompositeText8
+#undef XRenderCompositeText16
+#undef XRenderCompositeText32
+#undef XRenderFillRectangle
+#undef XRenderFillRectangles
+#undef XRenderCompositeTrapezoids
+#undef XRenderCompositeTriangles
+#undef XRenderCompositeTriStrip
+#undef XRenderCompositeTriFan
+#undef XRenderCompositeDoublePoly
+#undef XRenderParseColor
+#undef XRenderCreateCursor
+#undef XRenderQueryFilters
+#undef XRenderSetPictureFilter
+#undef XRenderCreateAnimCursor
+#undef XRenderAddTraps
+#undef XRenderCreateSolidFill
+#undef XRenderCreateLinearGradient
+#undef XRenderCreateRadialGradient
+#undef XRenderCreateConicalGradient
+#include <dlfcn.h>
+#include <stdio.h>
+int (*XRenderQueryExtension_dylibloader_wrapper_xrender)( Display*, int*, int*);
+int (*XRenderQueryVersion_dylibloader_wrapper_xrender)( Display*, int*, int*);
+int (*XRenderQueryFormats_dylibloader_wrapper_xrender)( Display*);
+int (*XRenderQuerySubpixelOrder_dylibloader_wrapper_xrender)( Display*, int);
+int (*XRenderSetSubpixelOrder_dylibloader_wrapper_xrender)( Display*, int, int);
+XRenderPictFormat* (*XRenderFindVisualFormat_dylibloader_wrapper_xrender)( Display*,const Visual*);
+XRenderPictFormat* (*XRenderFindFormat_dylibloader_wrapper_xrender)( Display*, unsigned long,const XRenderPictFormat*, int);
+XRenderPictFormat* (*XRenderFindStandardFormat_dylibloader_wrapper_xrender)( Display*, int);
+XIndexValue* (*XRenderQueryPictIndexValues_dylibloader_wrapper_xrender)( Display*,const XRenderPictFormat*, int*);
+Picture (*XRenderCreatePicture_dylibloader_wrapper_xrender)( Display*, Drawable,const XRenderPictFormat*, unsigned long,const XRenderPictureAttributes*);
+void (*XRenderChangePicture_dylibloader_wrapper_xrender)( Display*, Picture, unsigned long,const XRenderPictureAttributes*);
+void (*XRenderSetPictureClipRectangles_dylibloader_wrapper_xrender)( Display*, Picture, int, int,const XRectangle*, int);
+void (*XRenderSetPictureClipRegion_dylibloader_wrapper_xrender)( Display*, Picture, Region);
+void (*XRenderSetPictureTransform_dylibloader_wrapper_xrender)( Display*, Picture, XTransform*);
+void (*XRenderFreePicture_dylibloader_wrapper_xrender)( Display*, Picture);
+void (*XRenderComposite_dylibloader_wrapper_xrender)( Display*, int, Picture, Picture, Picture, int, int, int, int, int, int, unsigned int, unsigned int);
+GlyphSet (*XRenderCreateGlyphSet_dylibloader_wrapper_xrender)( Display*,const XRenderPictFormat*);
+GlyphSet (*XRenderReferenceGlyphSet_dylibloader_wrapper_xrender)( Display*, GlyphSet);
+void (*XRenderFreeGlyphSet_dylibloader_wrapper_xrender)( Display*, GlyphSet);
+void (*XRenderAddGlyphs_dylibloader_wrapper_xrender)( Display*, GlyphSet,const Glyph*,const XGlyphInfo*, int,const char*, int);
+void (*XRenderFreeGlyphs_dylibloader_wrapper_xrender)( Display*, GlyphSet,const Glyph*, int);
+void (*XRenderCompositeString8_dylibloader_wrapper_xrender)( Display*, int, Picture, Picture,const XRenderPictFormat*, GlyphSet, int, int, int, int,const char*, int);
+void (*XRenderCompositeString16_dylibloader_wrapper_xrender)( Display*, int, Picture, Picture,const XRenderPictFormat*, GlyphSet, int, int, int, int,const unsigned short*, int);
+void (*XRenderCompositeString32_dylibloader_wrapper_xrender)( Display*, int, Picture, Picture,const XRenderPictFormat*, GlyphSet, int, int, int, int,const unsigned int*, int);
+void (*XRenderCompositeText8_dylibloader_wrapper_xrender)( Display*, int, Picture, Picture,const XRenderPictFormat*, int, int, int, int,const XGlyphElt8*, int);
+void (*XRenderCompositeText16_dylibloader_wrapper_xrender)( Display*, int, Picture, Picture,const XRenderPictFormat*, int, int, int, int,const XGlyphElt16*, int);
+void (*XRenderCompositeText32_dylibloader_wrapper_xrender)( Display*, int, Picture, Picture,const XRenderPictFormat*, int, int, int, int,const XGlyphElt32*, int);
+void (*XRenderFillRectangle_dylibloader_wrapper_xrender)( Display*, int, Picture,const XRenderColor*, int, int, unsigned int, unsigned int);
+void (*XRenderFillRectangles_dylibloader_wrapper_xrender)( Display*, int, Picture,const XRenderColor*,const XRectangle*, int);
+void (*XRenderCompositeTrapezoids_dylibloader_wrapper_xrender)( Display*, int, Picture, Picture,const XRenderPictFormat*, int, int,const XTrapezoid*, int);
+void (*XRenderCompositeTriangles_dylibloader_wrapper_xrender)( Display*, int, Picture, Picture,const XRenderPictFormat*, int, int,const XTriangle*, int);
+void (*XRenderCompositeTriStrip_dylibloader_wrapper_xrender)( Display*, int, Picture, Picture,const XRenderPictFormat*, int, int,const XPointFixed*, int);
+void (*XRenderCompositeTriFan_dylibloader_wrapper_xrender)( Display*, int, Picture, Picture,const XRenderPictFormat*, int, int,const XPointFixed*, int);
+void (*XRenderCompositeDoublePoly_dylibloader_wrapper_xrender)( Display*, int, Picture, Picture,const XRenderPictFormat*, int, int, int, int,const XPointDouble*, int, int);
+int (*XRenderParseColor_dylibloader_wrapper_xrender)( Display*, char*, XRenderColor*);
+Cursor (*XRenderCreateCursor_dylibloader_wrapper_xrender)( Display*, Picture, unsigned int, unsigned int);
+XFilters* (*XRenderQueryFilters_dylibloader_wrapper_xrender)( Display*, Drawable);
+void (*XRenderSetPictureFilter_dylibloader_wrapper_xrender)( Display*, Picture,const char*, XFixed*, int);
+Cursor (*XRenderCreateAnimCursor_dylibloader_wrapper_xrender)( Display*, int, XAnimCursor*);
+void (*XRenderAddTraps_dylibloader_wrapper_xrender)( Display*, Picture, int, int,const XTrap*, int);
+Picture (*XRenderCreateSolidFill_dylibloader_wrapper_xrender)( Display*,const XRenderColor*);
+Picture (*XRenderCreateLinearGradient_dylibloader_wrapper_xrender)( Display*,const XLinearGradient*,const XFixed*,const XRenderColor*, int);
+Picture (*XRenderCreateRadialGradient_dylibloader_wrapper_xrender)( Display*,const XRadialGradient*,const XFixed*,const XRenderColor*, int);
+Picture (*XRenderCreateConicalGradient_dylibloader_wrapper_xrender)( Display*,const XConicalGradient*,const XFixed*,const XRenderColor*, int);
+int initialize_xrender(int verbose) {
+ void *handle;
+ char *error;
+ handle = dlopen("libXrender.so.1", RTLD_LAZY);
+ if (!handle) {
+ if (verbose) {
+ fprintf(stderr, "%s\n", dlerror());
+ }
+ return(1);
+ }
+ dlerror();
+// XRenderQueryExtension
+ *(void **) (&XRenderQueryExtension_dylibloader_wrapper_xrender) = dlsym(handle, "XRenderQueryExtension");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRenderQueryVersion
+ *(void **) (&XRenderQueryVersion_dylibloader_wrapper_xrender) = dlsym(handle, "XRenderQueryVersion");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRenderQueryFormats
+ *(void **) (&XRenderQueryFormats_dylibloader_wrapper_xrender) = dlsym(handle, "XRenderQueryFormats");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRenderQuerySubpixelOrder
+ *(void **) (&XRenderQuerySubpixelOrder_dylibloader_wrapper_xrender) = dlsym(handle, "XRenderQuerySubpixelOrder");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRenderSetSubpixelOrder
+ *(void **) (&XRenderSetSubpixelOrder_dylibloader_wrapper_xrender) = dlsym(handle, "XRenderSetSubpixelOrder");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRenderFindVisualFormat
+ *(void **) (&XRenderFindVisualFormat_dylibloader_wrapper_xrender) = dlsym(handle, "XRenderFindVisualFormat");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRenderFindFormat
+ *(void **) (&XRenderFindFormat_dylibloader_wrapper_xrender) = dlsym(handle, "XRenderFindFormat");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRenderFindStandardFormat
+ *(void **) (&XRenderFindStandardFormat_dylibloader_wrapper_xrender) = dlsym(handle, "XRenderFindStandardFormat");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRenderQueryPictIndexValues
+ *(void **) (&XRenderQueryPictIndexValues_dylibloader_wrapper_xrender) = dlsym(handle, "XRenderQueryPictIndexValues");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRenderCreatePicture
+ *(void **) (&XRenderCreatePicture_dylibloader_wrapper_xrender) = dlsym(handle, "XRenderCreatePicture");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRenderChangePicture
+ *(void **) (&XRenderChangePicture_dylibloader_wrapper_xrender) = dlsym(handle, "XRenderChangePicture");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRenderSetPictureClipRectangles
+ *(void **) (&XRenderSetPictureClipRectangles_dylibloader_wrapper_xrender) = dlsym(handle, "XRenderSetPictureClipRectangles");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRenderSetPictureClipRegion
+ *(void **) (&XRenderSetPictureClipRegion_dylibloader_wrapper_xrender) = dlsym(handle, "XRenderSetPictureClipRegion");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRenderSetPictureTransform
+ *(void **) (&XRenderSetPictureTransform_dylibloader_wrapper_xrender) = dlsym(handle, "XRenderSetPictureTransform");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRenderFreePicture
+ *(void **) (&XRenderFreePicture_dylibloader_wrapper_xrender) = dlsym(handle, "XRenderFreePicture");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRenderComposite
+ *(void **) (&XRenderComposite_dylibloader_wrapper_xrender) = dlsym(handle, "XRenderComposite");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRenderCreateGlyphSet
+ *(void **) (&XRenderCreateGlyphSet_dylibloader_wrapper_xrender) = dlsym(handle, "XRenderCreateGlyphSet");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRenderReferenceGlyphSet
+ *(void **) (&XRenderReferenceGlyphSet_dylibloader_wrapper_xrender) = dlsym(handle, "XRenderReferenceGlyphSet");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRenderFreeGlyphSet
+ *(void **) (&XRenderFreeGlyphSet_dylibloader_wrapper_xrender) = dlsym(handle, "XRenderFreeGlyphSet");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRenderAddGlyphs
+ *(void **) (&XRenderAddGlyphs_dylibloader_wrapper_xrender) = dlsym(handle, "XRenderAddGlyphs");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRenderFreeGlyphs
+ *(void **) (&XRenderFreeGlyphs_dylibloader_wrapper_xrender) = dlsym(handle, "XRenderFreeGlyphs");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRenderCompositeString8
+ *(void **) (&XRenderCompositeString8_dylibloader_wrapper_xrender) = dlsym(handle, "XRenderCompositeString8");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRenderCompositeString16
+ *(void **) (&XRenderCompositeString16_dylibloader_wrapper_xrender) = dlsym(handle, "XRenderCompositeString16");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRenderCompositeString32
+ *(void **) (&XRenderCompositeString32_dylibloader_wrapper_xrender) = dlsym(handle, "XRenderCompositeString32");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRenderCompositeText8
+ *(void **) (&XRenderCompositeText8_dylibloader_wrapper_xrender) = dlsym(handle, "XRenderCompositeText8");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRenderCompositeText16
+ *(void **) (&XRenderCompositeText16_dylibloader_wrapper_xrender) = dlsym(handle, "XRenderCompositeText16");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRenderCompositeText32
+ *(void **) (&XRenderCompositeText32_dylibloader_wrapper_xrender) = dlsym(handle, "XRenderCompositeText32");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRenderFillRectangle
+ *(void **) (&XRenderFillRectangle_dylibloader_wrapper_xrender) = dlsym(handle, "XRenderFillRectangle");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRenderFillRectangles
+ *(void **) (&XRenderFillRectangles_dylibloader_wrapper_xrender) = dlsym(handle, "XRenderFillRectangles");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRenderCompositeTrapezoids
+ *(void **) (&XRenderCompositeTrapezoids_dylibloader_wrapper_xrender) = dlsym(handle, "XRenderCompositeTrapezoids");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRenderCompositeTriangles
+ *(void **) (&XRenderCompositeTriangles_dylibloader_wrapper_xrender) = dlsym(handle, "XRenderCompositeTriangles");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRenderCompositeTriStrip
+ *(void **) (&XRenderCompositeTriStrip_dylibloader_wrapper_xrender) = dlsym(handle, "XRenderCompositeTriStrip");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRenderCompositeTriFan
+ *(void **) (&XRenderCompositeTriFan_dylibloader_wrapper_xrender) = dlsym(handle, "XRenderCompositeTriFan");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRenderCompositeDoublePoly
+ *(void **) (&XRenderCompositeDoublePoly_dylibloader_wrapper_xrender) = dlsym(handle, "XRenderCompositeDoublePoly");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRenderParseColor
+ *(void **) (&XRenderParseColor_dylibloader_wrapper_xrender) = dlsym(handle, "XRenderParseColor");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRenderCreateCursor
+ *(void **) (&XRenderCreateCursor_dylibloader_wrapper_xrender) = dlsym(handle, "XRenderCreateCursor");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRenderQueryFilters
+ *(void **) (&XRenderQueryFilters_dylibloader_wrapper_xrender) = dlsym(handle, "XRenderQueryFilters");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRenderSetPictureFilter
+ *(void **) (&XRenderSetPictureFilter_dylibloader_wrapper_xrender) = dlsym(handle, "XRenderSetPictureFilter");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRenderCreateAnimCursor
+ *(void **) (&XRenderCreateAnimCursor_dylibloader_wrapper_xrender) = dlsym(handle, "XRenderCreateAnimCursor");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRenderAddTraps
+ *(void **) (&XRenderAddTraps_dylibloader_wrapper_xrender) = dlsym(handle, "XRenderAddTraps");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRenderCreateSolidFill
+ *(void **) (&XRenderCreateSolidFill_dylibloader_wrapper_xrender) = dlsym(handle, "XRenderCreateSolidFill");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRenderCreateLinearGradient
+ *(void **) (&XRenderCreateLinearGradient_dylibloader_wrapper_xrender) = dlsym(handle, "XRenderCreateLinearGradient");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRenderCreateRadialGradient
+ *(void **) (&XRenderCreateRadialGradient_dylibloader_wrapper_xrender) = dlsym(handle, "XRenderCreateRadialGradient");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// XRenderCreateConicalGradient
+ *(void **) (&XRenderCreateConicalGradient_dylibloader_wrapper_xrender) = dlsym(handle, "XRenderCreateConicalGradient");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+return 0;
+}
diff --git a/platform/linuxbsd/x11/dynwrappers/xrender-so_wrap.h b/platform/linuxbsd/x11/dynwrappers/xrender-so_wrap.h
new file mode 100644
index 0000000000..e873448ec5
--- /dev/null
+++ b/platform/linuxbsd/x11/dynwrappers/xrender-so_wrap.h
@@ -0,0 +1,198 @@
+#ifndef DYLIBLOAD_WRAPPER_XRENDER
+#define DYLIBLOAD_WRAPPER_XRENDER
+// 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-12-02 12:55:28
+// flags: ./generate-wrapper.py --include /usr/include/X11/extensions/Xrender.h --sys-include <X11/extensions/Xrender.h> --soname libXrender.so.1 --init-name xrender --output-header xrender-so_wrap.h --output-implementation xrender-so_wrap.c
+//
+// NOTE: Generated from Xrender 0.9.10.
+// This has been handpatched to workaround some issues with the generator that
+// will be eventually fixed. In this case, non-existent symbols inherited from
+// libX11, but absent in libXrender.so.1, were removed.
+#include <stdint.h>
+
+#define XRenderQueryExtension XRenderQueryExtension_dylibloader_orig_xrender
+#define XRenderQueryVersion XRenderQueryVersion_dylibloader_orig_xrender
+#define XRenderQueryFormats XRenderQueryFormats_dylibloader_orig_xrender
+#define XRenderQuerySubpixelOrder XRenderQuerySubpixelOrder_dylibloader_orig_xrender
+#define XRenderSetSubpixelOrder XRenderSetSubpixelOrder_dylibloader_orig_xrender
+#define XRenderFindVisualFormat XRenderFindVisualFormat_dylibloader_orig_xrender
+#define XRenderFindFormat XRenderFindFormat_dylibloader_orig_xrender
+#define XRenderFindStandardFormat XRenderFindStandardFormat_dylibloader_orig_xrender
+#define XRenderQueryPictIndexValues XRenderQueryPictIndexValues_dylibloader_orig_xrender
+#define XRenderCreatePicture XRenderCreatePicture_dylibloader_orig_xrender
+#define XRenderChangePicture XRenderChangePicture_dylibloader_orig_xrender
+#define XRenderSetPictureClipRectangles XRenderSetPictureClipRectangles_dylibloader_orig_xrender
+#define XRenderSetPictureClipRegion XRenderSetPictureClipRegion_dylibloader_orig_xrender
+#define XRenderSetPictureTransform XRenderSetPictureTransform_dylibloader_orig_xrender
+#define XRenderFreePicture XRenderFreePicture_dylibloader_orig_xrender
+#define XRenderComposite XRenderComposite_dylibloader_orig_xrender
+#define XRenderCreateGlyphSet XRenderCreateGlyphSet_dylibloader_orig_xrender
+#define XRenderReferenceGlyphSet XRenderReferenceGlyphSet_dylibloader_orig_xrender
+#define XRenderFreeGlyphSet XRenderFreeGlyphSet_dylibloader_orig_xrender
+#define XRenderAddGlyphs XRenderAddGlyphs_dylibloader_orig_xrender
+#define XRenderFreeGlyphs XRenderFreeGlyphs_dylibloader_orig_xrender
+#define XRenderCompositeString8 XRenderCompositeString8_dylibloader_orig_xrender
+#define XRenderCompositeString16 XRenderCompositeString16_dylibloader_orig_xrender
+#define XRenderCompositeString32 XRenderCompositeString32_dylibloader_orig_xrender
+#define XRenderCompositeText8 XRenderCompositeText8_dylibloader_orig_xrender
+#define XRenderCompositeText16 XRenderCompositeText16_dylibloader_orig_xrender
+#define XRenderCompositeText32 XRenderCompositeText32_dylibloader_orig_xrender
+#define XRenderFillRectangle XRenderFillRectangle_dylibloader_orig_xrender
+#define XRenderFillRectangles XRenderFillRectangles_dylibloader_orig_xrender
+#define XRenderCompositeTrapezoids XRenderCompositeTrapezoids_dylibloader_orig_xrender
+#define XRenderCompositeTriangles XRenderCompositeTriangles_dylibloader_orig_xrender
+#define XRenderCompositeTriStrip XRenderCompositeTriStrip_dylibloader_orig_xrender
+#define XRenderCompositeTriFan XRenderCompositeTriFan_dylibloader_orig_xrender
+#define XRenderCompositeDoublePoly XRenderCompositeDoublePoly_dylibloader_orig_xrender
+#define XRenderParseColor XRenderParseColor_dylibloader_orig_xrender
+#define XRenderCreateCursor XRenderCreateCursor_dylibloader_orig_xrender
+#define XRenderQueryFilters XRenderQueryFilters_dylibloader_orig_xrender
+#define XRenderSetPictureFilter XRenderSetPictureFilter_dylibloader_orig_xrender
+#define XRenderCreateAnimCursor XRenderCreateAnimCursor_dylibloader_orig_xrender
+#define XRenderAddTraps XRenderAddTraps_dylibloader_orig_xrender
+#define XRenderCreateSolidFill XRenderCreateSolidFill_dylibloader_orig_xrender
+#define XRenderCreateLinearGradient XRenderCreateLinearGradient_dylibloader_orig_xrender
+#define XRenderCreateRadialGradient XRenderCreateRadialGradient_dylibloader_orig_xrender
+#define XRenderCreateConicalGradient XRenderCreateConicalGradient_dylibloader_orig_xrender
+#include <X11/extensions/Xrender.h>
+#undef XRenderQueryExtension
+#undef XRenderQueryVersion
+#undef XRenderQueryFormats
+#undef XRenderQuerySubpixelOrder
+#undef XRenderSetSubpixelOrder
+#undef XRenderFindVisualFormat
+#undef XRenderFindFormat
+#undef XRenderFindStandardFormat
+#undef XRenderQueryPictIndexValues
+#undef XRenderCreatePicture
+#undef XRenderChangePicture
+#undef XRenderSetPictureClipRectangles
+#undef XRenderSetPictureClipRegion
+#undef XRenderSetPictureTransform
+#undef XRenderFreePicture
+#undef XRenderComposite
+#undef XRenderCreateGlyphSet
+#undef XRenderReferenceGlyphSet
+#undef XRenderFreeGlyphSet
+#undef XRenderAddGlyphs
+#undef XRenderFreeGlyphs
+#undef XRenderCompositeString8
+#undef XRenderCompositeString16
+#undef XRenderCompositeString32
+#undef XRenderCompositeText8
+#undef XRenderCompositeText16
+#undef XRenderCompositeText32
+#undef XRenderFillRectangle
+#undef XRenderFillRectangles
+#undef XRenderCompositeTrapezoids
+#undef XRenderCompositeTriangles
+#undef XRenderCompositeTriStrip
+#undef XRenderCompositeTriFan
+#undef XRenderCompositeDoublePoly
+#undef XRenderParseColor
+#undef XRenderCreateCursor
+#undef XRenderQueryFilters
+#undef XRenderSetPictureFilter
+#undef XRenderCreateAnimCursor
+#undef XRenderAddTraps
+#undef XRenderCreateSolidFill
+#undef XRenderCreateLinearGradient
+#undef XRenderCreateRadialGradient
+#undef XRenderCreateConicalGradient
+#ifdef __cplusplus
+extern "C" {
+#endif
+#define XRenderQueryExtension XRenderQueryExtension_dylibloader_wrapper_xrender
+#define XRenderQueryVersion XRenderQueryVersion_dylibloader_wrapper_xrender
+#define XRenderQueryFormats XRenderQueryFormats_dylibloader_wrapper_xrender
+#define XRenderQuerySubpixelOrder XRenderQuerySubpixelOrder_dylibloader_wrapper_xrender
+#define XRenderSetSubpixelOrder XRenderSetSubpixelOrder_dylibloader_wrapper_xrender
+#define XRenderFindVisualFormat XRenderFindVisualFormat_dylibloader_wrapper_xrender
+#define XRenderFindFormat XRenderFindFormat_dylibloader_wrapper_xrender
+#define XRenderFindStandardFormat XRenderFindStandardFormat_dylibloader_wrapper_xrender
+#define XRenderQueryPictIndexValues XRenderQueryPictIndexValues_dylibloader_wrapper_xrender
+#define XRenderCreatePicture XRenderCreatePicture_dylibloader_wrapper_xrender
+#define XRenderChangePicture XRenderChangePicture_dylibloader_wrapper_xrender
+#define XRenderSetPictureClipRectangles XRenderSetPictureClipRectangles_dylibloader_wrapper_xrender
+#define XRenderSetPictureClipRegion XRenderSetPictureClipRegion_dylibloader_wrapper_xrender
+#define XRenderSetPictureTransform XRenderSetPictureTransform_dylibloader_wrapper_xrender
+#define XRenderFreePicture XRenderFreePicture_dylibloader_wrapper_xrender
+#define XRenderComposite XRenderComposite_dylibloader_wrapper_xrender
+#define XRenderCreateGlyphSet XRenderCreateGlyphSet_dylibloader_wrapper_xrender
+#define XRenderReferenceGlyphSet XRenderReferenceGlyphSet_dylibloader_wrapper_xrender
+#define XRenderFreeGlyphSet XRenderFreeGlyphSet_dylibloader_wrapper_xrender
+#define XRenderAddGlyphs XRenderAddGlyphs_dylibloader_wrapper_xrender
+#define XRenderFreeGlyphs XRenderFreeGlyphs_dylibloader_wrapper_xrender
+#define XRenderCompositeString8 XRenderCompositeString8_dylibloader_wrapper_xrender
+#define XRenderCompositeString16 XRenderCompositeString16_dylibloader_wrapper_xrender
+#define XRenderCompositeString32 XRenderCompositeString32_dylibloader_wrapper_xrender
+#define XRenderCompositeText8 XRenderCompositeText8_dylibloader_wrapper_xrender
+#define XRenderCompositeText16 XRenderCompositeText16_dylibloader_wrapper_xrender
+#define XRenderCompositeText32 XRenderCompositeText32_dylibloader_wrapper_xrender
+#define XRenderFillRectangle XRenderFillRectangle_dylibloader_wrapper_xrender
+#define XRenderFillRectangles XRenderFillRectangles_dylibloader_wrapper_xrender
+#define XRenderCompositeTrapezoids XRenderCompositeTrapezoids_dylibloader_wrapper_xrender
+#define XRenderCompositeTriangles XRenderCompositeTriangles_dylibloader_wrapper_xrender
+#define XRenderCompositeTriStrip XRenderCompositeTriStrip_dylibloader_wrapper_xrender
+#define XRenderCompositeTriFan XRenderCompositeTriFan_dylibloader_wrapper_xrender
+#define XRenderCompositeDoublePoly XRenderCompositeDoublePoly_dylibloader_wrapper_xrender
+#define XRenderParseColor XRenderParseColor_dylibloader_wrapper_xrender
+#define XRenderCreateCursor XRenderCreateCursor_dylibloader_wrapper_xrender
+#define XRenderQueryFilters XRenderQueryFilters_dylibloader_wrapper_xrender
+#define XRenderSetPictureFilter XRenderSetPictureFilter_dylibloader_wrapper_xrender
+#define XRenderCreateAnimCursor XRenderCreateAnimCursor_dylibloader_wrapper_xrender
+#define XRenderAddTraps XRenderAddTraps_dylibloader_wrapper_xrender
+#define XRenderCreateSolidFill XRenderCreateSolidFill_dylibloader_wrapper_xrender
+#define XRenderCreateLinearGradient XRenderCreateLinearGradient_dylibloader_wrapper_xrender
+#define XRenderCreateRadialGradient XRenderCreateRadialGradient_dylibloader_wrapper_xrender
+#define XRenderCreateConicalGradient XRenderCreateConicalGradient_dylibloader_wrapper_xrender
+extern int (*XRenderQueryExtension_dylibloader_wrapper_xrender)( Display*, int*, int*);
+extern int (*XRenderQueryVersion_dylibloader_wrapper_xrender)( Display*, int*, int*);
+extern int (*XRenderQueryFormats_dylibloader_wrapper_xrender)( Display*);
+extern int (*XRenderQuerySubpixelOrder_dylibloader_wrapper_xrender)( Display*, int);
+extern int (*XRenderSetSubpixelOrder_dylibloader_wrapper_xrender)( Display*, int, int);
+extern XRenderPictFormat* (*XRenderFindVisualFormat_dylibloader_wrapper_xrender)( Display*,const Visual*);
+extern XRenderPictFormat* (*XRenderFindFormat_dylibloader_wrapper_xrender)( Display*, unsigned long,const XRenderPictFormat*, int);
+extern XRenderPictFormat* (*XRenderFindStandardFormat_dylibloader_wrapper_xrender)( Display*, int);
+extern XIndexValue* (*XRenderQueryPictIndexValues_dylibloader_wrapper_xrender)( Display*,const XRenderPictFormat*, int*);
+extern Picture (*XRenderCreatePicture_dylibloader_wrapper_xrender)( Display*, Drawable,const XRenderPictFormat*, unsigned long,const XRenderPictureAttributes*);
+extern void (*XRenderChangePicture_dylibloader_wrapper_xrender)( Display*, Picture, unsigned long,const XRenderPictureAttributes*);
+extern void (*XRenderSetPictureClipRectangles_dylibloader_wrapper_xrender)( Display*, Picture, int, int,const XRectangle*, int);
+extern void (*XRenderSetPictureClipRegion_dylibloader_wrapper_xrender)( Display*, Picture, Region);
+extern void (*XRenderSetPictureTransform_dylibloader_wrapper_xrender)( Display*, Picture, XTransform*);
+extern void (*XRenderFreePicture_dylibloader_wrapper_xrender)( Display*, Picture);
+extern void (*XRenderComposite_dylibloader_wrapper_xrender)( Display*, int, Picture, Picture, Picture, int, int, int, int, int, int, unsigned int, unsigned int);
+extern GlyphSet (*XRenderCreateGlyphSet_dylibloader_wrapper_xrender)( Display*,const XRenderPictFormat*);
+extern GlyphSet (*XRenderReferenceGlyphSet_dylibloader_wrapper_xrender)( Display*, GlyphSet);
+extern void (*XRenderFreeGlyphSet_dylibloader_wrapper_xrender)( Display*, GlyphSet);
+extern void (*XRenderAddGlyphs_dylibloader_wrapper_xrender)( Display*, GlyphSet,const Glyph*,const XGlyphInfo*, int,const char*, int);
+extern void (*XRenderFreeGlyphs_dylibloader_wrapper_xrender)( Display*, GlyphSet,const Glyph*, int);
+extern void (*XRenderCompositeString8_dylibloader_wrapper_xrender)( Display*, int, Picture, Picture,const XRenderPictFormat*, GlyphSet, int, int, int, int,const char*, int);
+extern void (*XRenderCompositeString16_dylibloader_wrapper_xrender)( Display*, int, Picture, Picture,const XRenderPictFormat*, GlyphSet, int, int, int, int,const unsigned short*, int);
+extern void (*XRenderCompositeString32_dylibloader_wrapper_xrender)( Display*, int, Picture, Picture,const XRenderPictFormat*, GlyphSet, int, int, int, int,const unsigned int*, int);
+extern void (*XRenderCompositeText8_dylibloader_wrapper_xrender)( Display*, int, Picture, Picture,const XRenderPictFormat*, int, int, int, int,const XGlyphElt8*, int);
+extern void (*XRenderCompositeText16_dylibloader_wrapper_xrender)( Display*, int, Picture, Picture,const XRenderPictFormat*, int, int, int, int,const XGlyphElt16*, int);
+extern void (*XRenderCompositeText32_dylibloader_wrapper_xrender)( Display*, int, Picture, Picture,const XRenderPictFormat*, int, int, int, int,const XGlyphElt32*, int);
+extern void (*XRenderFillRectangle_dylibloader_wrapper_xrender)( Display*, int, Picture,const XRenderColor*, int, int, unsigned int, unsigned int);
+extern void (*XRenderFillRectangles_dylibloader_wrapper_xrender)( Display*, int, Picture,const XRenderColor*,const XRectangle*, int);
+extern void (*XRenderCompositeTrapezoids_dylibloader_wrapper_xrender)( Display*, int, Picture, Picture,const XRenderPictFormat*, int, int,const XTrapezoid*, int);
+extern void (*XRenderCompositeTriangles_dylibloader_wrapper_xrender)( Display*, int, Picture, Picture,const XRenderPictFormat*, int, int,const XTriangle*, int);
+extern void (*XRenderCompositeTriStrip_dylibloader_wrapper_xrender)( Display*, int, Picture, Picture,const XRenderPictFormat*, int, int,const XPointFixed*, int);
+extern void (*XRenderCompositeTriFan_dylibloader_wrapper_xrender)( Display*, int, Picture, Picture,const XRenderPictFormat*, int, int,const XPointFixed*, int);
+extern void (*XRenderCompositeDoublePoly_dylibloader_wrapper_xrender)( Display*, int, Picture, Picture,const XRenderPictFormat*, int, int, int, int,const XPointDouble*, int, int);
+extern int (*XRenderParseColor_dylibloader_wrapper_xrender)( Display*, char*, XRenderColor*);
+extern Cursor (*XRenderCreateCursor_dylibloader_wrapper_xrender)( Display*, Picture, unsigned int, unsigned int);
+extern XFilters* (*XRenderQueryFilters_dylibloader_wrapper_xrender)( Display*, Drawable);
+extern void (*XRenderSetPictureFilter_dylibloader_wrapper_xrender)( Display*, Picture,const char*, XFixed*, int);
+extern Cursor (*XRenderCreateAnimCursor_dylibloader_wrapper_xrender)( Display*, int, XAnimCursor*);
+extern void (*XRenderAddTraps_dylibloader_wrapper_xrender)( Display*, Picture, int, int,const XTrap*, int);
+extern Picture (*XRenderCreateSolidFill_dylibloader_wrapper_xrender)( Display*,const XRenderColor*);
+extern Picture (*XRenderCreateLinearGradient_dylibloader_wrapper_xrender)( Display*,const XLinearGradient*,const XFixed*,const XRenderColor*, int);
+extern Picture (*XRenderCreateRadialGradient_dylibloader_wrapper_xrender)( Display*,const XRadialGradient*,const XFixed*,const XRenderColor*, int);
+extern Picture (*XRenderCreateConicalGradient_dylibloader_wrapper_xrender)( Display*,const XConicalGradient*,const XFixed*,const XRenderColor*, int);
+int initialize_xrender(int verbose);
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/platform/linuxbsd/x11/gl_manager_x11.cpp b/platform/linuxbsd/x11/gl_manager_x11.cpp
index 893a22e75e..12846f148d 100644
--- a/platform/linuxbsd/x11/gl_manager_x11.cpp
+++ b/platform/linuxbsd/x11/gl_manager_x11.cpp
@@ -37,9 +37,7 @@
#include <stdlib.h>
#include <unistd.h>
-#define GLX_GLXEXT_PROTOTYPES
-#include <GL/glx.h>
-#include <GL/glxext.h>
+#include "thirdparty/glad/glad/glx.h"
#define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091
#define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092
@@ -323,16 +321,15 @@ void GLManager_X11::swap_buffers() {
glXSwapBuffers(_x_windisp.x11_display, _x_windisp.x11_window);
}
-Error GLManager_X11::initialize() {
+Error GLManager_X11::initialize(Display *p_display) {
+ if (!gladLoaderLoadGLX(p_display, XScreenNumberOfScreen(XDefaultScreenOfDisplay(p_display)))) {
+ return ERR_CANT_CREATE;
+ }
+
return OK;
}
void GLManager_X11::set_use_vsync(bool p_use) {
- static bool setup = false;
- static PFNGLXSWAPINTERVALEXTPROC glXSwapIntervalEXT = nullptr;
- static PFNGLXSWAPINTERVALSGIPROC glXSwapIntervalMESA = nullptr;
- static PFNGLXSWAPINTERVALSGIPROC glXSwapIntervalSGI = nullptr;
-
// force vsync in the editor for now, as a safety measure
bool is_editor = Engine::get_singleton()->is_editor_hint();
if (is_editor) {
@@ -345,25 +342,12 @@ void GLManager_X11::set_use_vsync(bool p_use) {
}
const GLDisplay &disp = get_current_display();
- if (!setup) {
- setup = true;
- String extensions = glXQueryExtensionsString(disp.x11_display, DefaultScreen(disp.x11_display));
- if (extensions.find("GLX_EXT_swap_control") != -1) {
- glXSwapIntervalEXT = (PFNGLXSWAPINTERVALEXTPROC)glXGetProcAddressARB((const GLubyte *)"glXSwapIntervalEXT");
- }
- if (extensions.find("GLX_MESA_swap_control") != -1) {
- glXSwapIntervalMESA = (PFNGLXSWAPINTERVALSGIPROC)glXGetProcAddressARB((const GLubyte *)"glXSwapIntervalMESA");
- }
- if (extensions.find("GLX_SGI_swap_control") != -1) {
- glXSwapIntervalSGI = (PFNGLXSWAPINTERVALSGIPROC)glXGetProcAddressARB((const GLubyte *)"glXSwapIntervalSGI");
- }
- }
int val = p_use ? 1 : 0;
- if (glXSwapIntervalMESA) {
+ if (GLAD_GLX_MESA_swap_control) {
glXSwapIntervalMESA(val);
- } else if (glXSwapIntervalSGI) {
+ } else if (GLAD_GLX_SGI_swap_control) {
glXSwapIntervalSGI(val);
- } else if (glXSwapIntervalEXT) {
+ } else if (GLAD_GLX_EXT_swap_control) {
GLXDrawable drawable = glXGetCurrentDrawable();
glXSwapIntervalEXT(disp.x11_display, drawable, val);
} else {
diff --git a/platform/linuxbsd/x11/gl_manager_x11.h b/platform/linuxbsd/x11/gl_manager_x11.h
index 1594c82801..3ab37b54ac 100644
--- a/platform/linuxbsd/x11/gl_manager_x11.h
+++ b/platform/linuxbsd/x11/gl_manager_x11.h
@@ -37,9 +37,10 @@
#include "core/os/os.h"
#include "core/templates/local_vector.h"
+#include "dynwrappers/xext-so_wrap.h"
+#include "dynwrappers/xlib-so_wrap.h"
+#include "dynwrappers/xrender-so_wrap.h"
#include "servers/display_server.h"
-#include <X11/Xlib.h>
-#include <X11/extensions/Xrender.h>
struct GLManager_X11_Private;
@@ -111,7 +112,7 @@ public:
void window_make_current(DisplayServer::WindowID p_window_id);
- Error initialize();
+ Error initialize(Display *p_display);
void set_use_vsync(bool p_use);
bool is_using_vsync() const;
diff --git a/platform/macos/detect.py b/platform/macos/detect.py
index e73c5322ea..67e4b49b14 100644
--- a/platform/macos/detect.py
+++ b/platform/macos/detect.py
@@ -242,18 +242,24 @@ def configure(env: "Environment"):
if not env["use_volk"]:
env.Append(LINKFLAGS=["-lMoltenVK"])
mvk_found = False
+
+ mkv_list = [get_mvk_sdk_path(), "/opt/homebrew/lib", "/usr/local/homebrew/lib", "/opt/local/lib"]
if env["vulkan_sdk_path"] != "":
- mvk_path = os.path.join(
- os.path.expanduser(env["vulkan_sdk_path"]), "MoltenVK/MoltenVK.xcframework/macos-arm64_x86_64/"
+ mkv_list.insert(0, os.path.expanduser(env["vulkan_sdk_path"]))
+ mkv_list.insert(
+ 0,
+ 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()
+
+ for mvk_path in mkv_list:
if mvk_path and os.path.isfile(os.path.join(mvk_path, "libMoltenVK.a")):
mvk_found = True
+ print("MoltenVK found at: " + mvk_path)
env.Append(LINKFLAGS=["-L" + mvk_path])
+ break
+
if not mvk_found:
print(
"MoltenVK SDK installation directory not found, use 'vulkan_sdk_path' SCons parameter to specify SDK path."
diff --git a/platform/macos/display_server_macos.h b/platform/macos/display_server_macos.h
index 618da6b388..bd26f6e417 100644
--- a/platform/macos/display_server_macos.h
+++ b/platform/macos/display_server_macos.h
@@ -106,6 +106,7 @@ public:
bool layered_window = false;
bool fullscreen = false;
+ bool exclusive_fullscreen = false;
bool on_top = false;
bool borderless = false;
bool resize_disabled = false;
@@ -232,6 +233,7 @@ public:
void popup_close(WindowID p_window);
void set_is_resizing(bool p_is_resizing);
bool get_is_resizing() const;
+ void reparent_check(WindowID p_window);
void window_update(WindowID p_window);
void window_destroy(WindowID p_window);
@@ -353,6 +355,7 @@ public:
virtual void window_set_current_screen(int p_screen, WindowID p_window = MAIN_WINDOW_ID) override;
virtual Point2i window_get_position(WindowID p_window = MAIN_WINDOW_ID) const override;
+ virtual Point2i window_get_position_with_decorations(WindowID p_window = MAIN_WINDOW_ID) const override;
virtual void window_set_position(const Point2i &p_position, WindowID p_window = MAIN_WINDOW_ID) override;
virtual void window_set_transient(WindowID p_window, WindowID p_parent) override;
@@ -366,7 +369,7 @@ public:
virtual void window_set_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID) override;
virtual Size2i window_get_size(WindowID p_window = MAIN_WINDOW_ID) const override;
- virtual Size2i window_get_real_size(WindowID p_window = MAIN_WINDOW_ID) const override;
+ virtual Size2i window_get_size_with_decorations(WindowID p_window = MAIN_WINDOW_ID) const override;
virtual void window_set_mode(WindowMode p_mode, WindowID p_window = MAIN_WINDOW_ID) override;
virtual WindowMode window_get_mode(WindowID p_window = MAIN_WINDOW_ID) const override;
diff --git a/platform/macos/display_server_macos.mm b/platform/macos/display_server_macos.mm
index 8b596379a0..5c979dbf22 100644
--- a/platform/macos/display_server_macos.mm
+++ b/platform/macos/display_server_macos.mm
@@ -166,6 +166,7 @@ DisplayServerMacOS::WindowID DisplayServerMacOS::_create_window(WindowMode p_mod
Error err = gl_manager->window_create(window_id_counter, wd.window_view, p_rect.size.width, p_rect.size.height);
ERR_FAIL_COND_V_MSG(err != OK, INVALID_WINDOW_ID, "Can't create an OpenGL context");
}
+ window_set_vsync_mode(p_vsync_mode, window_id_counter);
#endif
[wd.window_view updateLayerDelegate];
id = window_id_counter++;
@@ -2336,24 +2337,60 @@ void DisplayServerMacOS::window_set_current_screen(int p_screen, WindowID p_wind
}
}
-void DisplayServerMacOS::window_set_exclusive(WindowID p_window, bool p_exclusive) {
- _THREAD_SAFE_METHOD_
+void DisplayServerMacOS::reparent_check(WindowID p_window) {
ERR_FAIL_COND(!windows.has(p_window));
WindowData &wd = windows[p_window];
- if (wd.exclusive != p_exclusive) {
- wd.exclusive = p_exclusive;
- if (wd.transient_parent != INVALID_WINDOW_ID) {
- WindowData &wd_parent = windows[wd.transient_parent];
- if (wd.exclusive) {
- ERR_FAIL_COND_MSG([[wd_parent.window_object childWindows] count] > 0, "Transient parent has another exclusive child.");
+ NSScreen *screen = [wd.window_object screen];
+
+ if (wd.transient_parent != INVALID_WINDOW_ID) {
+ WindowData &wd_parent = windows[wd.transient_parent];
+ NSScreen *parent_screen = [wd_parent.window_object screen];
+
+ if (parent_screen == screen) {
+ if (![[wd_parent.window_object childWindows] containsObject:wd.window_object]) {
+ [wd.window_object setCollectionBehavior:NSWindowCollectionBehaviorFullScreenAuxiliary];
[wd_parent.window_object addChildWindow:wd.window_object ordered:NSWindowAbove];
- } else {
+ }
+ } else {
+ if ([[wd_parent.window_object childWindows] containsObject:wd.window_object]) {
[wd_parent.window_object removeChildWindow:wd.window_object];
+ [wd.window_object setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary];
+ [wd.window_object orderFront:nil];
+ }
+ }
+ }
+
+ for (const WindowID &child : wd.transient_children) {
+ WindowData &wd_child = windows[child];
+ NSScreen *child_screen = [wd_child.window_object screen];
+
+ if (child_screen == screen) {
+ if (![[wd.window_object childWindows] containsObject:wd_child.window_object]) {
+ if (wd_child.fullscreen) {
+ [wd_child.window_object toggleFullScreen:nil];
+ }
+ [wd_child.window_object setCollectionBehavior:NSWindowCollectionBehaviorFullScreenAuxiliary];
+ [wd.window_object addChildWindow:wd_child.window_object ordered:NSWindowAbove];
+ }
+ } else {
+ if ([[wd.window_object childWindows] containsObject:wd_child.window_object]) {
+ [wd.window_object removeChildWindow:wd_child.window_object];
+ [wd_child.window_object setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary];
}
}
}
}
+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];
+ if (wd.exclusive != p_exclusive) {
+ wd.exclusive = p_exclusive;
+ reparent_check(p_window);
+ }
+}
+
Point2i DisplayServerMacOS::window_get_position(WindowID p_window) const {
_THREAD_SAFE_METHOD_
@@ -2377,13 +2414,34 @@ Point2i DisplayServerMacOS::window_get_position(WindowID p_window) const {
return pos;
}
+Point2i DisplayServerMacOS::window_get_position_with_decorations(WindowID p_window) const {
+ _THREAD_SAFE_METHOD_
+
+ ERR_FAIL_COND_V(!windows.has(p_window), Point2i());
+ const WindowData &wd = windows[p_window];
+
+ const NSRect nsrect = [wd.window_object frame];
+ Point2i pos;
+
+ // Return the position of the top-left corner, for OS X the y starts at the bottom.
+ const float scale = screen_get_max_scale();
+ pos.x = nsrect.origin.x;
+ pos.y = (nsrect.origin.y + nsrect.size.height);
+ pos *= scale;
+ pos -= _get_screens_origin();
+ // OS X native y-coordinate relative to _get_screens_origin() is negative,
+ // Godot expects a positive value.
+ pos.y *= -1;
+ return pos;
+}
+
void DisplayServerMacOS::window_set_position(const Point2i &p_position, WindowID p_window) {
_THREAD_SAFE_METHOD_
ERR_FAIL_COND(!windows.has(p_window));
WindowData &wd = windows[p_window];
- if ([wd.window_object isZoomed]) {
+ if (NSEqualRects([wd.window_object frame], [[wd.window_object screen] visibleFrame])) {
return;
}
@@ -2428,11 +2486,10 @@ void DisplayServerMacOS::window_set_transient(WindowID p_window, WindowID p_pare
wd_window.transient_parent = INVALID_WINDOW_ID;
wd_parent.transient_children.erase(p_window);
- [wd_window.window_object setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary];
-
- if (wd_window.exclusive) {
+ if ([[wd_parent.window_object childWindows] containsObject:wd_window.window_object]) {
[wd_parent.window_object removeChildWindow:wd_window.window_object];
}
+ [wd_window.window_object setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary];
} else {
ERR_FAIL_COND(!windows.has(p_parent));
ERR_FAIL_COND_MSG(wd_window.transient_parent != INVALID_WINDOW_ID, "Window already has a transient parent");
@@ -2440,11 +2497,7 @@ void DisplayServerMacOS::window_set_transient(WindowID p_window, WindowID p_pare
wd_window.transient_parent = p_parent;
wd_parent.transient_children.insert(p_window);
- [wd_window.window_object setCollectionBehavior:NSWindowCollectionBehaviorFullScreenAuxiliary];
-
- if (wd_window.exclusive) {
- [wd_parent.window_object addChildWindow:wd_window.window_object ordered:NSWindowAbove];
- }
+ reparent_check(p_window);
}
}
@@ -2511,7 +2564,7 @@ void DisplayServerMacOS::window_set_size(const Size2i p_size, WindowID p_window)
ERR_FAIL_COND(!windows.has(p_window));
WindowData &wd = windows[p_window];
- if ([wd.window_object isZoomed]) {
+ if (NSEqualRects([wd.window_object frame], [[wd.window_object screen] visibleFrame])) {
return;
}
@@ -2541,7 +2594,7 @@ Size2i DisplayServerMacOS::window_get_size(WindowID p_window) const {
return wd.size;
}
-Size2i DisplayServerMacOS::window_get_real_size(WindowID p_window) const {
+Size2i DisplayServerMacOS::window_get_size_with_decorations(WindowID p_window) const {
_THREAD_SAFE_METHOD_
ERR_FAIL_COND_V(!windows.has(p_window), Size2i());
@@ -2584,10 +2637,16 @@ void DisplayServerMacOS::window_set_mode(WindowMode p_mode, WindowID p_window) {
[wd.window_object setContentMaxSize:NSMakeSize(size.x, size.y)];
}
[wd.window_object toggleFullScreen:nil];
+
+ if (old_mode == WINDOW_MODE_EXCLUSIVE_FULLSCREEN) {
+ [NSApp setPresentationOptions:NSApplicationPresentationDefault];
+ }
+
wd.fullscreen = false;
+ wd.exclusive_fullscreen = false;
} break;
case WINDOW_MODE_MAXIMIZED: {
- if ([wd.window_object isZoomed]) {
+ if (NSEqualRects([wd.window_object frame], [[wd.window_object screen] visibleFrame])) {
[wd.window_object zoom:nil];
}
} break;
@@ -2609,10 +2668,18 @@ void DisplayServerMacOS::window_set_mode(WindowMode p_mode, WindowID p_window) {
[wd.window_object setContentMinSize:NSMakeSize(0, 0)];
[wd.window_object setContentMaxSize:NSMakeSize(FLT_MAX, FLT_MAX)];
[wd.window_object toggleFullScreen:nil];
+
wd.fullscreen = true;
+ if (p_mode == WINDOW_MODE_EXCLUSIVE_FULLSCREEN) {
+ const NSUInteger presentationOptions = NSApplicationPresentationHideDock | NSApplicationPresentationHideMenuBar;
+ [NSApp setPresentationOptions:presentationOptions];
+ wd.exclusive_fullscreen = true;
+ } else {
+ wd.exclusive_fullscreen = false;
+ }
} break;
case WINDOW_MODE_MAXIMIZED: {
- if (![wd.window_object isZoomed]) {
+ if (!NSEqualRects([wd.window_object frame], [[wd.window_object screen] visibleFrame])) {
[wd.window_object zoom:nil];
}
} break;
@@ -2626,9 +2693,13 @@ DisplayServer::WindowMode DisplayServerMacOS::window_get_mode(WindowID p_window)
const WindowData &wd = windows[p_window];
if (wd.fullscreen) { // If fullscreen, it's not in another mode.
- return WINDOW_MODE_FULLSCREEN;
+ if (wd.exclusive_fullscreen) {
+ return WINDOW_MODE_EXCLUSIVE_FULLSCREEN;
+ } else {
+ return WINDOW_MODE_FULLSCREEN;
+ }
}
- if ([wd.window_object isZoomed] && !wd.resize_disabled) {
+ if (NSEqualRects([wd.window_object frame], [[wd.window_object screen] visibleFrame])) {
return WINDOW_MODE_MAXIMIZED;
}
if ([wd.window_object respondsToSelector:@selector(isMiniaturized)]) {
@@ -2738,8 +2809,10 @@ void DisplayServerMacOS::window_set_flag(WindowFlags p_flag, bool p_enabled, Win
}
if (p_enabled) {
[wd.window_object setStyleMask:[wd.window_object styleMask] & ~NSWindowStyleMaskResizable];
+ [[wd.window_object standardWindowButton:NSWindowZoomButton] setEnabled:NO];
} else {
[wd.window_object setStyleMask:[wd.window_object styleMask] | NSWindowStyleMaskResizable];
+ [[wd.window_object standardWindowButton:NSWindowZoomButton] setEnabled:YES];
}
} break;
case WINDOW_FLAG_EXTEND_TO_TITLE: {
@@ -2945,7 +3018,10 @@ int64_t DisplayServerMacOS::window_get_native_handle(HandleType p_handle_type, W
}
#ifdef GLES3_ENABLED
case OPENGL_CONTEXT: {
- return (int64_t)gl_manager->get_context(p_window);
+ if (gl_manager) {
+ return (int64_t)gl_manager->get_context(p_window);
+ }
+ return 0;
}
#endif
default: {
@@ -2978,7 +3054,7 @@ void DisplayServerMacOS::window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_
_THREAD_SAFE_METHOD_
#if defined(GLES3_ENABLED)
if (gl_manager) {
- gl_manager->set_use_vsync(p_vsync_mode);
+ gl_manager->set_use_vsync(p_vsync_mode != DisplayServer::VSYNC_DISABLED);
}
#endif
#if defined(VULKAN_ENABLED)
diff --git a/platform/macos/export/export_plugin.cpp b/platform/macos/export/export_plugin.cpp
index de6016cb9b..49c8c7758d 100644
--- a/platform/macos/export/export_plugin.cpp
+++ b/platform/macos/export/export_plugin.cpp
@@ -34,6 +34,7 @@
#include "lipo.h"
#include "macho.h"
+#include "core/io/image_loader.h"
#include "core/string/translation.h"
#include "editor/editor_node.h"
#include "editor/editor_paths.h"
@@ -90,11 +91,14 @@ bool EditorExportPlatformMacOS::get_export_option_visibility(const EditorExportP
return false;
}
} break;
- case 2: { // "altool"
+ case 2: { // "notarytool"
+ // All options are visible.
+ } break;
+ case 3: { // "altool"
// All options are visible.
} break;
default: { // disabled
- if (p_option == "notarization/apple_id_name" || p_option == "notarization/apple_id_password" || p_option == "notarization/apple_team_id" || p_option == "notarization/api_uuid" || p_option == "notarization/api_key") {
+ if (p_option == "notarization/apple_id_name" || p_option == "notarization/apple_id_password" || p_option == "notarization/apple_team_id" || p_option == "notarization/api_uuid" || p_option == "notarization/api_key" || p_option == "notarization/api_key_id") {
return false;
}
} break;
@@ -116,7 +120,8 @@ void EditorExportPlatformMacOS::get_export_options(List<ExportOption> *r_options
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_template/release", PROPERTY_HINT_GLOBAL_FILE, "*.zip"), ""));
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::STRING, "application/icon", PROPERTY_HINT_FILE, "*.png,*.icns"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/icon", PROPERTY_HINT_FILE, "*.icns,*.png,*.webp,*.svg"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "application/icon_interpolation", PROPERTY_HINT_ENUM, "Nearest neighbor,Bilinear,Cubic,Trilinear,Lanczos"), 4));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/bundle_identifier", PROPERTY_HINT_PLACEHOLDER_TEXT, "com.example.game"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/signature"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/app_category", PROPERTY_HINT_ENUM, "Business,Developer-tools,Education,Entertainment,Finance,Games,Action-games,Adventure-games,Arcade-games,Board-games,Card-games,Casino-games,Dice-games,Educational-games,Family-games,Kids-games,Music-games,Puzzle-games,Racing-games,Role-playing-games,Simulation-games,Sports-games,Strategy-games,Trivia-games,Word-games,Graphics-design,Healthcare-fitness,Lifestyle,Medical,Music,News,Photography,Productivity,Reference,Social-networking,Sports,Travel,Utilities,Video,Weather"), "Games"));
@@ -127,9 +132,9 @@ void EditorExportPlatformMacOS::get_export_options(List<ExportOption> *r_options
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "display/high_res"), false));
#ifdef MACOS_ENABLED
- r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "codesign/codesign", PROPERTY_HINT_ENUM, "Disabled,Built-in (ad-hoc only),PyOxidizer rcodesign,Xcode codesign"), 3, true));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "codesign/codesign", PROPERTY_HINT_ENUM, "Disabled,Built-in (ad-hoc only),rcodesign,Xcode codesign"), 3, true));
#else
- r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "codesign/codesign", PROPERTY_HINT_ENUM, "Disabled,Built-in (ad-hoc only),PyOxidizer rcodesign"), 1, true));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "codesign/codesign", PROPERTY_HINT_ENUM, "Disabled,Built-in (ad-hoc only),rcodesign"), 1, true));
#endif
// "codesign" only options:
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "codesign/identity", PROPERTY_HINT_PLACEHOLDER_TEXT, "Type: Name (ID)"), ""));
@@ -163,17 +168,18 @@ void EditorExportPlatformMacOS::get_export_options(List<ExportOption> *r_options
r_options->push_back(ExportOption(PropertyInfo(Variant::PACKED_STRING_ARRAY, "codesign/custom_options"), PackedStringArray()));
#ifdef MACOS_ENABLED
- r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "notarization/notarization", PROPERTY_HINT_ENUM, "Disabled,PyOxidizer rcodesign,Xcode altool"), 0, true));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "notarization/notarization", PROPERTY_HINT_ENUM, "Disabled,rcodesign,Xcode notarytool,Xcode altool (deprecated)"), 0, true));
#else
- r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "notarization/notarization", PROPERTY_HINT_ENUM, "Disabled,PyOxidizer rcodesign"), 0, true));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "notarization/notarization", PROPERTY_HINT_ENUM, "Disabled,rcodesign"), 0, true));
#endif
- // "altool" only options:
+ // "altool" and "notarytool" only options:
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "notarization/apple_id_name", PROPERTY_HINT_PLACEHOLDER_TEXT, "Apple ID email"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "notarization/apple_id_password", PROPERTY_HINT_PASSWORD, "Enable two-factor authentication and provide app-specific password"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "notarization/apple_team_id", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide team ID if your Apple ID belongs to multiple teams"), ""));
- // "altool" and "rcodesign" only options:
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "notarization/api_uuid", PROPERTY_HINT_PLACEHOLDER_TEXT, "App Store Connect issuer ID"), ""));
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "notarization/api_key", PROPERTY_HINT_PLACEHOLDER_TEXT, "App Store Connect API key ID"), ""));
+ // "altool", "notarytool" and "rcodesign" only options:
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "notarization/api_uuid", PROPERTY_HINT_PLACEHOLDER_TEXT, "App Store Connect issuer ID UUID"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "notarization/api_key", PROPERTY_HINT_GLOBAL_FILE, "*.p8"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "notarization/api_key_id", PROPERTY_HINT_PLACEHOLDER_TEXT, "App Store Connect API key ID"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/microphone_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use the microphone"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/microphone_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary()));
@@ -268,7 +274,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 EditorExportPlatformMacOS::_make_icon(const Ref<Image> &p_icon, Vector<uint8_t> &p_data) {
+void EditorExportPlatformMacOS::_make_icon(const Ref<EditorExportPreset> &p_preset, const Ref<Image> &p_icon, Vector<uint8_t> &p_data) {
Ref<ImageTexture> it = memnew(ImageTexture);
Vector<uint8_t> data;
@@ -302,7 +308,7 @@ void EditorExportPlatformMacOS::_make_icon(const Ref<Image> &p_icon, Vector<uint
for (uint64_t i = 0; i < (sizeof(icon_infos) / sizeof(icon_infos[0])); ++i) {
Ref<Image> copy = p_icon; // does this make sense? doesn't this just increase the reference count instead of making a copy? Do we even need a copy?
copy->convert(Image::FORMAT_RGBA8);
- copy->resize(icon_infos[i].size, icon_infos[i].size);
+ copy->resize(icon_infos[i].size, icon_infos[i].size, (Image::Interpolation)(p_preset->get("application/icon_interpolation").operator int()));
if (icon_infos[i].is_png) {
// Encode PNG icon.
@@ -496,7 +502,12 @@ Error EditorExportPlatformMacOS::_notarize(const Ref<EditorExportPreset> &p_pres
args.push_back(p_preset->get("notarization/api_uuid"));
args.push_back("--api-key");
- args.push_back(p_preset->get("notarization/api_key"));
+ args.push_back(p_preset->get("notarization/api_key_id"));
+
+ if (!p_preset->get("notarization/api_key").operator String().is_empty()) {
+ args.push_back("--api-key-path");
+ args.push_back(p_preset->get("notarization/api_key"));
+ }
args.push_back(p_path);
@@ -517,7 +528,7 @@ Error EditorExportPlatformMacOS::_notarize(const Ref<EditorExportPreset> &p_pres
} else {
print_verbose("rcodesign (" + p_path + "):\n" + str);
int next_nl = str.find("\n", rq_offset);
- String request_uuid = (next_nl == -1) ? str.substr(rq_offset + 14, -1) : str.substr(rq_offset + 14, next_nl - rq_offset - 14);
+ String request_uuid = (next_nl == -1) ? str.substr(rq_offset + 23, -1) : str.substr(rq_offset + 23, next_nl - rq_offset - 23);
add_message(EXPORT_MESSAGE_INFO, TTR("Notarization"), vformat(TTR("Notarization request UUID: \"%s\""), request_uuid));
add_message(EXPORT_MESSAGE_INFO, TTR("Notarization"), TTR("The notarization process generally takes less than an hour."));
add_message(EXPORT_MESSAGE_INFO, TTR("Notarization"), "\t" + TTR("You can check progress manually by opening a Terminal and running the following command:"));
@@ -527,7 +538,91 @@ Error EditorExportPlatformMacOS::_notarize(const Ref<EditorExportPreset> &p_pres
}
} break;
#ifdef MACOS_ENABLED
- case 2: { // "altool"
+ case 2: { // "notarytool"
+ print_verbose("using notarytool notarization...");
+
+ if (!FileAccess::exists("/usr/bin/xcrun") && !FileAccess::exists("/bin/xcrun")) {
+ add_message(EXPORT_MESSAGE_ERROR, TTR("Notarization"), TTR("Xcode command line tools are not installed."));
+ return Error::FAILED;
+ }
+
+ List<String> args;
+
+ args.push_back("notarytool");
+ args.push_back("submit");
+
+ args.push_back(p_path);
+
+ if (p_preset->get("notarization/apple_id_name") == "" && p_preset->get("notarization/api_uuid") == "") {
+ add_message(EXPORT_MESSAGE_ERROR, TTR("Notarization"), TTR("Neither Apple ID name nor App Store Connect issuer ID name not specified."));
+ return Error::FAILED;
+ }
+ if (p_preset->get("notarization/apple_id_name") != "" && p_preset->get("notarization/api_uuid") != "") {
+ add_message(EXPORT_MESSAGE_ERROR, TTR("Notarization"), TTR("Both Apple ID name and App Store Connect issuer ID name are specified, only one should be set at the same time."));
+ return Error::FAILED;
+ }
+
+ if (p_preset->get("notarization/apple_id_name") != "") {
+ if (p_preset->get("notarization/apple_id_password") == "") {
+ add_message(EXPORT_MESSAGE_ERROR, TTR("Notarization"), TTR("Apple ID password not specified."));
+ return Error::FAILED;
+ }
+ args.push_back("--apple-id");
+ args.push_back(p_preset->get("notarization/apple_id_name"));
+
+ args.push_back("--password");
+ args.push_back(p_preset->get("notarization/apple_id_password"));
+ } else {
+ if (p_preset->get("notarization/api_key_id") == "") {
+ add_message(EXPORT_MESSAGE_ERROR, TTR("Notarization"), TTR("App Store Connect API key ID not specified."));
+ return Error::FAILED;
+ }
+ args.push_back("--issuer");
+ args.push_back(p_preset->get("notarization/api_uuid"));
+
+ if (!p_preset->get("notarization/api_key").operator String().is_empty()) {
+ args.push_back("--key");
+ args.push_back(p_preset->get("notarization/api_key"));
+ }
+
+ args.push_back("--key-id");
+ args.push_back(p_preset->get("notarization/api_key_id"));
+ }
+
+ args.push_back("--no-progress");
+
+ if (p_preset->get("notarization/apple_team_id")) {
+ args.push_back("--team-id");
+ args.push_back(p_preset->get("notarization/apple_team_id"));
+ }
+
+ String str;
+ int exitcode = 0;
+ Error err = OS::get_singleton()->execute("xcrun", args, &str, &exitcode, true);
+ if (err != OK) {
+ add_message(EXPORT_MESSAGE_WARNING, TTR("Notarization"), TTR("Could not start xcrun executable."));
+ return err;
+ }
+
+ int rq_offset = str.find("id:");
+ if (exitcode != 0 || rq_offset == -1) {
+ print_line("notarytool (" + p_path + "):\n" + str);
+ add_message(EXPORT_MESSAGE_WARNING, TTR("Notarization"), TTR("Notarization failed, see editor log for details."));
+ return Error::FAILED;
+ } else {
+ print_verbose("notarytool (" + p_path + "):\n" + str);
+ int next_nl = str.find("\n", rq_offset);
+ String request_uuid = (next_nl == -1) ? str.substr(rq_offset + 4, -1) : str.substr(rq_offset + 4, next_nl - rq_offset - 4);
+ add_message(EXPORT_MESSAGE_INFO, TTR("Notarization"), vformat(TTR("Notarization request UUID: \"%s\""), request_uuid));
+ add_message(EXPORT_MESSAGE_INFO, TTR("Notarization"), TTR("The notarization process generally takes less than an hour."));
+ add_message(EXPORT_MESSAGE_INFO, TTR("Notarization"), "\t" + TTR("You can check progress manually by opening a Terminal and running the following command:"));
+ add_message(EXPORT_MESSAGE_INFO, TTR("Notarization"), "\t\t\"xcrun notarytool log <request uuid> --issuer <api uuid> --key-id <api key id> --key <api key path>\" or");
+ add_message(EXPORT_MESSAGE_INFO, TTR("Notarization"), "\t\t\"xcrun notarytool log <request uuid> --apple-id <your email> --password <app-specific pwd>>\"");
+ add_message(EXPORT_MESSAGE_INFO, TTR("Notarization"), "\t" + TTR("Run the following command to staple the notarization ticket to the exported application (optional):"));
+ add_message(EXPORT_MESSAGE_INFO, TTR("Notarization"), "\t\t\"xcrun stapler staple <app path>\"");
+ }
+ } break;
+ case 3: { // "altool"
print_verbose("using altool notarization...");
if (!FileAccess::exists("/usr/bin/xcrun") && !FileAccess::exists("/bin/xcrun")) {
@@ -571,7 +666,7 @@ Error EditorExportPlatformMacOS::_notarize(const Ref<EditorExportPreset> &p_pres
args.push_back(p_preset->get("notarization/api_uuid"));
args.push_back("--apiKey");
- args.push_back(p_preset->get("notarization/api_key"));
+ args.push_back(p_preset->get("notarization/api_key_id"));
}
args.push_back("--type");
@@ -593,7 +688,7 @@ Error EditorExportPlatformMacOS::_notarize(const Ref<EditorExportPreset> &p_pres
return err;
}
- int rq_offset = str.find("RequestUUID");
+ int rq_offset = str.find("RequestUUID:");
if (exitcode != 0 || rq_offset == -1) {
print_line("xcrun altool (" + p_path + "):\n" + str);
add_message(EXPORT_MESSAGE_WARNING, TTR("Notarization"), TTR("Notarization failed, see editor log for details."));
@@ -601,7 +696,7 @@ Error EditorExportPlatformMacOS::_notarize(const Ref<EditorExportPreset> &p_pres
} else {
print_verbose("xcrun altool (" + p_path + "):\n" + str);
int next_nl = str.find("\n", rq_offset);
- String request_uuid = (next_nl == -1) ? str.substr(rq_offset + 14, -1) : str.substr(rq_offset + 14, next_nl - rq_offset - 14);
+ String request_uuid = (next_nl == -1) ? str.substr(rq_offset + 13, -1) : str.substr(rq_offset + 13, next_nl - rq_offset - 13);
add_message(EXPORT_MESSAGE_INFO, TTR("Notarization"), vformat(TTR("Notarization request UUID: \"%s\""), request_uuid));
add_message(EXPORT_MESSAGE_INFO, TTR("Notarization"), TTR("The notarization process generally takes less than an hour. When the process is completed, you'll receive an email."));
add_message(EXPORT_MESSAGE_INFO, TTR("Notarization"), "\t" + TTR("You can check progress manually by opening a Terminal and running the following command:"));
@@ -726,7 +821,7 @@ Error EditorExportPlatformMacOS::_code_sign(const Ref<EditorExportPreset> &p_pre
String str;
int exitcode = 0;
- Error err = OS::get_singleton()->execute("codesign", args, &str, nullptr, true);
+ Error err = OS::get_singleton()->execute("codesign", args, &str, &exitcode, true);
if (err != OK) {
add_message(EXPORT_MESSAGE_WARNING, TTR("Code Signing"), TTR("Could not start codesign executable, make sure Xcode command line tools are installed."));
return err;
@@ -1270,9 +1365,9 @@ Error EditorExportPlatformMacOS::export_project(const Ref<EditorExportPreset> &p
} else {
Ref<Image> icon;
icon.instantiate();
- icon->load(iconpath);
- if (!icon->is_empty()) {
- _make_icon(icon, data);
+ err = ImageLoader::load_image(iconpath, icon);
+ if (err == OK && !icon->is_empty()) {
+ _make_icon(p_preset, icon, data);
}
}
}
@@ -1817,7 +1912,7 @@ bool EditorExportPlatformMacOS::has_valid_project_configuration(const Ref<Editor
err += TTR("Notarization: Code signing is required for notarization.") + "\n";
valid = false;
}
- if (notary_tool == 2) {
+ if (notary_tool == 2 || notary_tool == 3) {
if (!FileAccess::exists("/usr/bin/xcrun") && !FileAccess::exists("/bin/xcrun")) {
err += TTR("Notarization: Xcode command line tools are not installed.") + "\n";
valid = false;
@@ -1832,11 +1927,11 @@ bool EditorExportPlatformMacOS::has_valid_project_configuration(const Ref<Editor
if (p_preset->get("notarization/apple_id_name") != "") {
if (p_preset->get("notarization/apple_id_password") == "") {
err += TTR("Notarization: Apple ID password not specified.") + "\n";
+ valid = false;
}
- valid = false;
}
if (p_preset->get("notarization/api_uuid") != "") {
- if (p_preset->get("notarization/api_key") == "") {
+ if (p_preset->get("notarization/api_key_id") == "") {
err += TTR("Notarization: App Store Connect API key ID not specified.") + "\n";
valid = false;
}
@@ -1847,7 +1942,7 @@ bool EditorExportPlatformMacOS::has_valid_project_configuration(const Ref<Editor
err += TTR("Notarization: App Store Connect issuer ID name not specified.") + "\n";
valid = false;
}
- if (p_preset->get("notarization/api_key") == "") {
+ if (p_preset->get("notarization/api_key_id") == "") {
err += TTR("Notarization: App Store Connect API key ID not specified.") + "\n";
valid = false;
}
diff --git a/platform/macos/export/export_plugin.h b/platform/macos/export/export_plugin.h
index b6ad587caa..af7570c394 100644
--- a/platform/macos/export/export_plugin.h
+++ b/platform/macos/export/export_plugin.h
@@ -53,7 +53,7 @@ class EditorExportPlatformMacOS : public EditorExportPlatform {
Ref<ImageTexture> logo;
void _fix_plist(const Ref<EditorExportPreset> &p_preset, Vector<uint8_t> &plist, const String &p_binary);
- void _make_icon(const Ref<Image> &p_icon, Vector<uint8_t> &p_data);
+ void _make_icon(const Ref<EditorExportPreset> &p_preset, const Ref<Image> &p_icon, Vector<uint8_t> &p_data);
Error _notarize(const Ref<EditorExportPreset> &p_preset, const String &p_path);
Error _code_sign(const Ref<EditorExportPreset> &p_preset, const String &p_path, const String &p_ent_path, bool p_warn = true);
diff --git a/platform/macos/export/plist.cpp b/platform/macos/export/plist.cpp
index cad014e65b..c88b6e1077 100644
--- a/platform/macos/export/plist.cpp
+++ b/platform/macos/export/plist.cpp
@@ -30,6 +30,119 @@
#include "plist.h"
+PList::PLNodeType PListNode::get_type() const {
+ return data_type;
+}
+
+Variant PListNode::get_value() const {
+ switch (data_type) {
+ case PList::PL_NODE_TYPE_NIL: {
+ return Variant();
+ } break;
+ case PList::PL_NODE_TYPE_STRING: {
+ return String::utf8(data_string.get_data());
+ } break;
+ case PList::PL_NODE_TYPE_ARRAY: {
+ Array arr;
+ for (const Ref<PListNode> &E : data_array) {
+ arr.push_back(E);
+ }
+ return arr;
+ } break;
+ case PList::PL_NODE_TYPE_DICT: {
+ Dictionary dict;
+ for (const KeyValue<String, Ref<PListNode>> &E : data_dict) {
+ dict[E.key] = E.value;
+ }
+ return dict;
+ } break;
+ case PList::PL_NODE_TYPE_BOOLEAN: {
+ return data_bool;
+ } break;
+ case PList::PL_NODE_TYPE_INTEGER: {
+ return data_int;
+ } break;
+ case PList::PL_NODE_TYPE_REAL: {
+ return data_real;
+ } break;
+ case PList::PL_NODE_TYPE_DATA: {
+ int strlen = data_string.length();
+
+ size_t arr_len = 0;
+ Vector<uint8_t> buf;
+ {
+ buf.resize(strlen / 4 * 3 + 1);
+ uint8_t *w = buf.ptrw();
+
+ ERR_FAIL_COND_V(CryptoCore::b64_decode(&w[0], buf.size(), &arr_len, (unsigned char *)data_string.get_data(), strlen) != OK, Vector<uint8_t>());
+ }
+ buf.resize(arr_len);
+ return buf;
+ } break;
+ case PList::PL_NODE_TYPE_DATE: {
+ return String(data_string.get_data());
+ } break;
+ }
+ return Variant();
+}
+
+Ref<PListNode> PListNode::new_node(const Variant &p_value) {
+ Ref<PListNode> node;
+ node.instantiate();
+
+ switch (p_value.get_type()) {
+ case Variant::NIL: {
+ node->data_type = PList::PL_NODE_TYPE_NIL;
+ } break;
+ case Variant::BOOL: {
+ node->data_type = PList::PL_NODE_TYPE_BOOLEAN;
+ node->data_bool = p_value;
+ } break;
+ case Variant::INT: {
+ node->data_type = PList::PL_NODE_TYPE_INTEGER;
+ node->data_int = p_value;
+ } break;
+ case Variant::FLOAT: {
+ node->data_type = PList::PL_NODE_TYPE_REAL;
+ node->data_real = p_value;
+ } break;
+ case Variant::STRING_NAME:
+ case Variant::STRING: {
+ node->data_type = PList::PL_NODE_TYPE_STRING;
+ node->data_string = p_value.operator String().utf8();
+ } break;
+ case Variant::DICTIONARY: {
+ node->data_type = PList::PL_NODE_TYPE_DICT;
+ Dictionary dict = p_value;
+ const Variant *next = dict.next(nullptr);
+ while (next) {
+ Ref<PListNode> sub_node = dict[*next];
+ ERR_FAIL_COND_V_MSG(sub_node.is_null(), Ref<PListNode>(), "Invalid dictionary element, should be PListNode.");
+ node->data_dict[*next] = sub_node;
+ next = dict.next(next);
+ }
+ } break;
+ case Variant::ARRAY: {
+ node->data_type = PList::PL_NODE_TYPE_ARRAY;
+ Array ar = p_value;
+ for (int i = 0; i < ar.size(); i++) {
+ Ref<PListNode> sub_node = ar[i];
+ ERR_FAIL_COND_V_MSG(sub_node.is_null(), Ref<PListNode>(), "Invalid array element, should be PListNode.");
+ node->data_array.push_back(sub_node);
+ }
+ } break;
+ case Variant::PACKED_BYTE_ARRAY: {
+ node->data_type = PList::PL_NODE_TYPE_DATA;
+ PackedByteArray buf = p_value;
+ node->data_string = CryptoCore::b64_encode_str(buf.ptr(), buf.size()).utf8();
+ } break;
+ default: {
+ ERR_FAIL_V_MSG(Ref<PListNode>(), "Unsupported data type.");
+ } break;
+ }
+ return node;
+}
+
Ref<PListNode> PListNode::new_array() {
Ref<PListNode> node = memnew(PListNode());
ERR_FAIL_COND_V(node.is_null(), Ref<PListNode>());
@@ -65,6 +178,7 @@ Ref<PListNode> PListNode::new_date(const String &p_string) {
ERR_FAIL_COND_V(node.is_null(), Ref<PListNode>());
node->data_type = PList::PLNodeType::PL_NODE_TYPE_DATE;
node->data_string = p_string.utf8();
+ node->data_real = (double)Time::get_singleton()->get_unix_time_from_datetime_string(p_string) - 978307200.0;
return node;
}
@@ -76,7 +190,7 @@ Ref<PListNode> PListNode::new_bool(bool p_bool) {
return node;
}
-Ref<PListNode> PListNode::new_int(int32_t p_int) {
+Ref<PListNode> PListNode::new_int(int64_t p_int) {
Ref<PListNode> node = memnew(PListNode());
ERR_FAIL_COND_V(node.is_null(), Ref<PListNode>());
node->data_type = PList::PLNodeType::PL_NODE_TYPE_INTEGER;
@@ -84,7 +198,7 @@ Ref<PListNode> PListNode::new_int(int32_t p_int) {
return node;
}
-Ref<PListNode> PListNode::new_real(float p_real) {
+Ref<PListNode> PListNode::new_real(double p_real) {
Ref<PListNode> node = memnew(PListNode());
ERR_FAIL_COND_V(node.is_null(), Ref<PListNode>());
node->data_type = PList::PLNodeType::PL_NODE_TYPE_REAL;
@@ -337,6 +451,168 @@ PList::PList(const String &p_string) {
load_string(p_string);
}
+uint64_t PList::read_bplist_var_size_int(Ref<FileAccess> p_file, uint8_t p_size) {
+ uint64_t pos = p_file->get_position();
+ uint64_t ret = 0;
+ switch (p_size) {
+ case 1: {
+ ret = p_file->get_8();
+ } break;
+ case 2: {
+ ret = BSWAP16(p_file->get_16());
+ } break;
+ case 3: {
+ ret = BSWAP32(p_file->get_32() & 0x00FFFFFF);
+ } break;
+ case 4: {
+ ret = BSWAP32(p_file->get_32());
+ } break;
+ case 5: {
+ ret = BSWAP64(p_file->get_64() & 0x000000FFFFFFFFFF);
+ } break;
+ case 6: {
+ ret = BSWAP64(p_file->get_64() & 0x0000FFFFFFFFFFFF);
+ } break;
+ case 7: {
+ ret = BSWAP64(p_file->get_64() & 0x00FFFFFFFFFFFFFF);
+ } break;
+ case 8: {
+ ret = BSWAP64(p_file->get_64());
+ } break;
+ default: {
+ ret = 0;
+ }
+ }
+ p_file->seek(pos + p_size);
+
+ return ret;
+}
+
+Ref<PListNode> PList::read_bplist_obj(Ref<FileAccess> p_file, uint64_t p_offset_idx) {
+ Ref<PListNode> node;
+ node.instantiate();
+
+ uint64_t ot_off = trailer.offset_table_start + p_offset_idx * trailer.offset_size;
+ p_file->seek(ot_off);
+ uint64_t marker_off = read_bplist_var_size_int(p_file, trailer.offset_size);
+ ERR_FAIL_COND_V_MSG(marker_off == 0, Ref<PListNode>(), "Invalid marker size.");
+
+ p_file->seek(marker_off);
+ uint8_t marker = p_file->get_8();
+ uint8_t marker_type = marker & 0xF0;
+ uint64_t marker_size = marker & 0x0F;
+
+ switch (marker_type) {
+ case 0x00: {
+ if (marker_size == 0x00) {
+ node->data_type = PL_NODE_TYPE_NIL;
+ } else if (marker_size == 0x08) {
+ node->data_type = PL_NODE_TYPE_BOOLEAN;
+ node->data_bool = false;
+ } else if (marker_size == 0x09) {
+ node->data_type = PL_NODE_TYPE_BOOLEAN;
+ node->data_bool = true;
+ } else {
+ ERR_FAIL_V_MSG(Ref<PListNode>(), "Invalid nil/bool marker value.");
+ }
+ } break;
+ case 0x10: {
+ node->data_type = PL_NODE_TYPE_INTEGER;
+ node->data_int = static_cast<int64_t>(read_bplist_var_size_int(p_file, pow(2, marker_size)));
+ } break;
+ case 0x20: {
+ node->data_type = PL_NODE_TYPE_REAL;
+ node->data_int = static_cast<int64_t>(read_bplist_var_size_int(p_file, pow(2, marker_size)));
+ } break;
+ case 0x30: {
+ node->data_type = PL_NODE_TYPE_DATE;
+ node->data_int = BSWAP64(p_file->get_64());
+ node->data_string = Time::get_singleton()->get_datetime_string_from_unix_time(node->data_real + 978307200.0).utf8();
+ } break;
+ case 0x40: {
+ if (marker_size == 0x0F) {
+ uint8_t ext = p_file->get_8() & 0xF;
+ marker_size = read_bplist_var_size_int(p_file, pow(2, ext));
+ }
+ node->data_type = PL_NODE_TYPE_DATA;
+ PackedByteArray buf;
+ buf.resize(marker_size + 1);
+ p_file->get_buffer(reinterpret_cast<uint8_t *>(buf.ptrw()), marker_size);
+ node->data_string = CryptoCore::b64_encode_str(buf.ptr(), buf.size()).utf8();
+ } break;
+ case 0x50: {
+ if (marker_size == 0x0F) {
+ uint8_t ext = p_file->get_8() & 0xF;
+ marker_size = read_bplist_var_size_int(p_file, pow(2, ext));
+ }
+ node->data_type = PL_NODE_TYPE_STRING;
+ node->data_string.resize(marker_size + 1);
+ p_file->get_buffer(reinterpret_cast<uint8_t *>(node->data_string.ptrw()), marker_size);
+ } break;
+ case 0x60: {
+ if (marker_size == 0x0F) {
+ uint8_t ext = p_file->get_8() & 0xF;
+ marker_size = read_bplist_var_size_int(p_file, pow(2, ext));
+ }
+ Char16String cs16;
+ cs16.resize(marker_size + 1);
+ for (uint64_t i = 0; i < marker_size; i++) {
+ cs16[i] = BSWAP16(p_file->get_16());
+ }
+ node->data_type = PL_NODE_TYPE_STRING;
+ node->data_string = String::utf16(cs16.ptr(), cs16.length()).utf8();
+ } break;
+ case 0x80: {
+ node->data_type = PL_NODE_TYPE_INTEGER;
+ node->data_int = static_cast<int64_t>(read_bplist_var_size_int(p_file, marker_size + 1));
+ } break;
+ case 0xA0:
+ case 0xC0: {
+ if (marker_size == 0x0F) {
+ uint8_t ext = p_file->get_8() & 0xF;
+ marker_size = read_bplist_var_size_int(p_file, pow(2, ext));
+ }
+ uint64_t pos = p_file->get_position();
+
+ node->data_type = PL_NODE_TYPE_ARRAY;
+ for (uint64_t i = 0; i < marker_size; i++) {
+ p_file->seek(pos + trailer.ref_size * i);
+ uint64_t ref = read_bplist_var_size_int(p_file, trailer.ref_size);
+
+ Ref<PListNode> element = read_bplist_obj(p_file, ref);
+ ERR_FAIL_COND_V(element.is_null(), Ref<PListNode>());
+ node->data_array.push_back(element);
+ }
+ } break;
+ case 0xD0: {
+ if (marker_size == 0x0F) {
+ uint8_t ext = p_file->get_8() & 0xF;
+ marker_size = read_bplist_var_size_int(p_file, pow(2, ext));
+ }
+ uint64_t pos = p_file->get_position();
+
+ node->data_type = PL_NODE_TYPE_DICT;
+ for (uint64_t i = 0; i < marker_size; i++) {
+ p_file->seek(pos + trailer.ref_size * i);
+ uint64_t key_ref = read_bplist_var_size_int(p_file, trailer.ref_size);
+
+ p_file->seek(pos + trailer.ref_size * (i + marker_size));
+ uint64_t obj_ref = read_bplist_var_size_int(p_file, trailer.ref_size);
+
+ Ref<PListNode> element_key = read_bplist_obj(p_file, key_ref);
+ ERR_FAIL_COND_V(element_key.is_null() || element_key->data_type != PL_NODE_TYPE_STRING, Ref<PListNode>());
+ Ref<PListNode> element = read_bplist_obj(p_file, obj_ref);
+ ERR_FAIL_COND_V(element.is_null(), Ref<PListNode>());
+ node->data_dict[String::utf8(element_key->data_string.ptr(), element_key->data_string.length())] = element;
+ }
+ } break;
+ default: {
+ ERR_FAIL_V_MSG(Ref<PListNode>(), "Invalid marker type.");
+ }
+ }
+ return node;
+}
+
bool PList::load_file(const String &p_filename) {
root = Ref<PListNode>();
@@ -349,11 +625,19 @@ bool PList::load_file(const String &p_filename) {
fb->get_buffer(magic, 8);
if (String((const char *)magic, 8) == "bplist00") {
- ERR_FAIL_V_MSG(false, "PList: Binary property lists are not supported.");
+ fb->seek_end(-26);
+ trailer.offset_size = fb->get_8();
+ trailer.ref_size = fb->get_8();
+ trailer.object_num = BSWAP64(fb->get_64());
+ trailer.root_offset_idx = BSWAP64(fb->get_64());
+ trailer.offset_table_start = BSWAP64(fb->get_64());
+ root = read_bplist_obj(fb, trailer.root_offset_idx);
+
+ return root.is_valid();
} else {
// Load text plist.
Error err;
- Vector<uint8_t> array = FileAccess::get_file_as_array(p_filename, &err);
+ Vector<uint8_t> array = FileAccess::get_file_as_bytes(p_filename, &err);
ERR_FAIL_COND_V(err != OK, false);
String ret;
diff --git a/platform/macos/export/plist.h b/platform/macos/export/plist.h
index 97331a3629..d53e88832f 100644
--- a/platform/macos/export/plist.h
+++ b/platform/macos/export/plist.h
@@ -35,6 +35,7 @@
#include "core/crypto/crypto_core.h"
#include "core/io/file_access.h"
+#include "core/os/time.h"
class PListNode;
@@ -55,8 +56,20 @@ public:
};
private:
+ struct PListTrailer {
+ uint8_t offset_size;
+ uint8_t ref_size;
+ uint64_t object_num;
+ uint64_t root_offset_idx;
+ uint64_t offset_table_start;
+ };
+
+ PListTrailer trailer;
Ref<PListNode> root;
+ uint64_t read_bplist_var_size_int(Ref<FileAccess> p_file, uint8_t p_size);
+ Ref<PListNode> read_bplist_obj(Ref<FileAccess> p_file, uint64_t p_offset_idx);
+
public:
PList();
PList(const String &p_string);
@@ -82,19 +95,23 @@ public:
Vector<Ref<PListNode>> data_array;
HashMap<String, Ref<PListNode>> data_dict;
union {
- int32_t data_int;
+ int64_t data_int;
bool data_bool;
- float data_real;
+ double data_real;
};
+ PList::PLNodeType get_type() const;
+ Variant get_value() const;
+
+ static Ref<PListNode> new_node(const Variant &p_value);
static Ref<PListNode> new_array();
static Ref<PListNode> new_dict();
static Ref<PListNode> new_string(const String &p_string);
static Ref<PListNode> new_data(const String &p_string);
static Ref<PListNode> new_date(const String &p_string);
static Ref<PListNode> new_bool(bool p_bool);
- static Ref<PListNode> new_int(int32_t p_int);
- static Ref<PListNode> new_real(float p_real);
+ static Ref<PListNode> new_int(int64_t p_int);
+ static Ref<PListNode> new_real(double p_real);
bool push_subnode(const Ref<PListNode> &p_node, const String &p_key = "");
diff --git a/platform/macos/godot_application_delegate.mm b/platform/macos/godot_application_delegate.mm
index bacdcc2bc4..f1168c685a 100644
--- a/platform/macos/godot_application_delegate.mm
+++ b/platform/macos/godot_application_delegate.mm
@@ -61,7 +61,9 @@
- (void)applicationDidFinishLaunching:(NSNotification *)notice {
NSString *nsappname = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleName"];
- if (nsappname == nil || isatty(STDOUT_FILENO) || isatty(STDIN_FILENO) || isatty(STDERR_FILENO)) {
+ NSString *nsbundleid_env = [NSString stringWithUTF8String:getenv("__CFBundleIdentifier")];
+ NSString *nsbundleid = [[NSBundle mainBundle] bundleIdentifier];
+ if (nsappname == nil || isatty(STDOUT_FILENO) || isatty(STDIN_FILENO) || isatty(STDERR_FILENO) || ![nsbundleid isEqualToString:nsbundleid_env]) {
// If the executable is started from terminal or is not bundled, macOS WindowServer won't register and activate app window correctly (menu and title bar are grayed out and input ignored).
[self performSelector:@selector(forceUnbundledWindowActivationHackStep1) withObject:nil afterDelay:0.02];
}
diff --git a/platform/macos/godot_window_delegate.mm b/platform/macos/godot_window_delegate.mm
index 279fd2a359..27efd3ebb2 100644
--- a/platform/macos/godot_window_delegate.mm
+++ b/platform/macos/godot_window_delegate.mm
@@ -147,7 +147,12 @@
}
DisplayServerMacOS::WindowData &wd = ds->get_window(window_id);
+ if (wd.exclusive_fullscreen) {
+ [NSApp setPresentationOptions:NSApplicationPresentationDefault];
+ }
+
wd.fullscreen = false;
+ wd.exclusive_fullscreen = false;
[(GodotWindow *)wd.window_object setAnimDuration:-1.0f];
@@ -251,6 +256,15 @@
}
}
+- (void)windowDidChangeScreen:(NSNotification *)notification {
+ DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
+ if (!ds || !ds->has_window(window_id)) {
+ return;
+ }
+
+ ds->reparent_check(window_id);
+}
+
- (void)windowDidMove:(NSNotification *)notification {
DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
if (!ds || !ds->has_window(window_id)) {
diff --git a/platform/macos/os_macos.h b/platform/macos/os_macos.h
index 46e7c17ebe..b2734e57cc 100644
--- a/platform/macos/os_macos.h
+++ b/platform/macos/os_macos.h
@@ -57,6 +57,10 @@ class OS_MacOS : public OS_Unix {
List<String> launch_service_args;
+ CGFloat _weight_to_ct(int p_weight) const;
+ CGFloat _stretch_to_ct(int p_stretch) const;
+ String _get_default_fontname(const String &p_font_name) const;
+
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);
@@ -98,7 +102,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_system_font_path(const String &p_font_name, int p_weight = 400, int p_stretch = 100, bool p_italic = false) const override;
+ virtual Vector<String> get_system_font_path_for_text(const String &p_font_name, const String &p_text, const String &p_locale = String(), const String &p_script = String(), int p_weight = 400, int p_stretch = 100, 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;
diff --git a/platform/macos/os_macos.mm b/platform/macos/os_macos.mm
index e620b058d3..fd8ba38808 100644
--- a/platform/macos/os_macos.mm
+++ b/platform/macos/os_macos.mm
@@ -45,16 +45,6 @@
#include <os/log.h>
#include <sys/sysctl.h>
-_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.path_join(p_path.get_file().get_basename()))) {
- return p_path.path_join(p_path.get_file().get_basename());
- } else {
- return p_path;
- }
-}
-
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 modal popup display.
// Do not redraw when rendering is done from the separate thread, it will conflict with the OpenGL context updates.
@@ -162,6 +152,28 @@ void OS_MacOS::alert(const String &p_alert, const String &p_title) {
}
}
+_FORCE_INLINE_ String OS_MacOS::get_framework_executable(const String &p_path) {
+ Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+
+ // Read framework bundle to get executable name.
+ NSURL *url = [NSURL fileURLWithPath:@(p_path.utf8().get_data())];
+ NSBundle *bundle = [NSBundle bundleWithURL:url];
+ if (bundle) {
+ String exe_path = String::utf8([[bundle executablePath] UTF8String]);
+ if (da->file_exists(exe_path)) {
+ return exe_path;
+ }
+ }
+
+ // Try default executable name (invalid framework).
+ if (da->dir_exists(p_path) && da->file_exists(p_path.path_join(p_path.get_file().get_basename()))) {
+ return p_path.path_join(p_path.get_file().get_basename());
+ }
+
+ // Not a framework, try loading as .dylib.
+ return p_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);
@@ -190,14 +202,6 @@ MainLoop *OS_MacOS::get_main_loop() 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()) {
- return get_environment("XDG_CONFIG_HOME");
- } else {
- WARN_PRINT_ONCE("`XDG_CONFIG_HOME` is a relative path. Ignoring its value and falling back to `$HOME/Library/Application Support` or `.` per the XDG Base Directory specification.");
- }
- }
if (has_environment("HOME")) {
return get_environment("HOME").path_join("Library/Application Support");
}
@@ -205,26 +209,10 @@ String OS_MacOS::get_config_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()) {
- return get_environment("XDG_DATA_HOME");
- } else {
- WARN_PRINT_ONCE("`XDG_DATA_HOME` is a relative path. Ignoring its value and falling back to `get_config_path()` per the XDG Base Directory specification.");
- }
- }
return get_config_path();
}
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()) {
- return get_environment("XDG_CACHE_HOME");
- } else {
- WARN_PRINT_ONCE("`XDG_CACHE_HOME` is a relative path. Ignoring its value and falling back to `$HOME/Library/Caches` or `get_config_path()` per the XDG Base Directory specification.");
- }
- }
if (has_environment("HOME")) {
return get_environment("HOME").path_join("Library/Caches");
}
@@ -336,9 +324,7 @@ Vector<String> OS_MacOS::get_system_fonts() const {
return ret;
}
-String OS_MacOS::get_system_font_path(const String &p_font_name, bool p_bold, bool p_italic) const {
- String ret;
-
+String OS_MacOS::_get_default_fontname(const String &p_font_name) const {
String font_name = p_font_name;
if (font_name.to_lower() == "sans-serif") {
font_name = "Helvetica";
@@ -351,21 +337,153 @@ String OS_MacOS::get_system_font_path(const String &p_font_name, bool p_bold, bo
} else if (font_name.to_lower() == "cursive") {
font_name = "Apple Chancery";
};
+ return font_name;
+}
+
+CGFloat OS_MacOS::_weight_to_ct(int p_weight) const {
+ if (p_weight < 150) {
+ return -0.80;
+ } else if (p_weight < 250) {
+ return -0.60;
+ } else if (p_weight < 350) {
+ return -0.40;
+ } else if (p_weight < 450) {
+ return 0.0;
+ } else if (p_weight < 550) {
+ return 0.23;
+ } else if (p_weight < 650) {
+ return 0.30;
+ } else if (p_weight < 750) {
+ return 0.40;
+ } else if (p_weight < 850) {
+ return 0.56;
+ } else if (p_weight < 925) {
+ return 0.62;
+ } else {
+ return 1.00;
+ }
+}
+
+CGFloat OS_MacOS::_stretch_to_ct(int p_stretch) const {
+ if (p_stretch < 56) {
+ return -0.5;
+ } else if (p_stretch < 69) {
+ return -0.37;
+ } else if (p_stretch < 81) {
+ return -0.25;
+ } else if (p_stretch < 93) {
+ return -0.13;
+ } else if (p_stretch < 106) {
+ return 0.0;
+ } else if (p_stretch < 137) {
+ return 0.13;
+ } else if (p_stretch < 144) {
+ return 0.25;
+ } else if (p_stretch < 162) {
+ return 0.37;
+ } else {
+ return 0.5;
+ }
+}
+
+Vector<String> OS_MacOS::get_system_font_path_for_text(const String &p_font_name, const String &p_text, const String &p_locale, const String &p_script, int p_weight, int p_stretch, bool p_italic) const {
+ Vector<String> ret;
+ String font_name = _get_default_fontname(p_font_name);
+
+ CFStringRef name = CFStringCreateWithCString(kCFAllocatorDefault, font_name.utf8().get_data(), kCFStringEncodingUTF8);
+ CTFontSymbolicTraits traits = 0;
+ if (p_weight >= 700) {
+ traits |= kCTFontBoldTrait;
+ }
+ if (p_italic) {
+ traits |= kCTFontItalicTrait;
+ }
+ if (p_stretch < 100) {
+ traits |= kCTFontCondensedTrait;
+ } else if (p_stretch > 100) {
+ traits |= kCTFontExpandedTrait;
+ }
+
+ CFNumberRef sym_traits = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &traits);
+ CFMutableDictionaryRef traits_dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, nullptr, nullptr);
+ CFDictionaryAddValue(traits_dict, kCTFontSymbolicTrait, sym_traits);
+
+ CGFloat weight = _weight_to_ct(p_weight);
+ CFNumberRef font_weight = CFNumberCreate(kCFAllocatorDefault, kCFNumberCGFloatType, &weight);
+ CFDictionaryAddValue(traits_dict, kCTFontWeightTrait, font_weight);
+
+ CGFloat stretch = _stretch_to_ct(p_stretch);
+ CFNumberRef font_stretch = CFNumberCreate(kCFAllocatorDefault, kCFNumberCGFloatType, &stretch);
+ CFDictionaryAddValue(traits_dict, kCTFontWidthTrait, font_stretch);
+
+ CFMutableDictionaryRef attributes = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, nullptr, nullptr);
+ CFDictionaryAddValue(attributes, kCTFontFamilyNameAttribute, name);
+ CFDictionaryAddValue(attributes, kCTFontTraitsAttribute, traits_dict);
+
+ CTFontDescriptorRef font = CTFontDescriptorCreateWithAttributes(attributes);
+ if (font) {
+ CTFontRef family = CTFontCreateWithFontDescriptor(font, 0, nullptr);
+ CFStringRef string = CFStringCreateWithCString(kCFAllocatorDefault, p_text.utf8().get_data(), kCFStringEncodingUTF8);
+ CFRange range = CFRangeMake(0, CFStringGetLength(string));
+ CTFontRef fallback_family = CTFontCreateForString(family, string, range);
+ if (fallback_family) {
+ CTFontDescriptorRef fallback_font = CTFontCopyFontDescriptor(fallback_family);
+ if (fallback_font) {
+ CFURLRef url = (CFURLRef)CTFontDescriptorCopyAttribute(fallback_font, kCTFontURLAttribute);
+ if (url) {
+ NSString *font_path = [NSString stringWithString:[(__bridge NSURL *)url path]];
+ ret.push_back(String::utf8([font_path UTF8String]));
+ CFRelease(url);
+ }
+ CFRelease(fallback_font);
+ }
+ CFRelease(fallback_family);
+ }
+ CFRelease(string);
+ CFRelease(font);
+ }
+
+ CFRelease(attributes);
+ CFRelease(traits_dict);
+ CFRelease(sym_traits);
+ CFRelease(font_stretch);
+ CFRelease(font_weight);
+ CFRelease(name);
+
+ return ret;
+}
+
+String OS_MacOS::get_system_font_path(const String &p_font_name, int p_weight, int p_stretch, bool p_italic) const {
+ String ret;
+ String font_name = _get_default_fontname(p_font_name);
CFStringRef name = CFStringCreateWithCString(kCFAllocatorDefault, font_name.utf8().get_data(), kCFStringEncodingUTF8);
CTFontSymbolicTraits traits = 0;
- if (p_bold) {
+ if (p_weight > 700) {
traits |= kCTFontBoldTrait;
}
if (p_italic) {
traits |= kCTFontItalicTrait;
}
+ if (p_stretch < 100) {
+ traits |= kCTFontCondensedTrait;
+ } else if (p_stretch > 100) {
+ traits |= kCTFontExpandedTrait;
+ }
CFNumberRef sym_traits = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &traits);
CFMutableDictionaryRef traits_dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, nullptr, nullptr);
CFDictionaryAddValue(traits_dict, kCTFontSymbolicTrait, sym_traits);
+ CGFloat weight = _weight_to_ct(p_weight);
+ CFNumberRef font_weight = CFNumberCreate(kCFAllocatorDefault, kCFNumberCGFloatType, &weight);
+ CFDictionaryAddValue(traits_dict, kCTFontWeightTrait, font_weight);
+
+ CGFloat stretch = _stretch_to_ct(p_stretch);
+ CFNumberRef font_stretch = CFNumberCreate(kCFAllocatorDefault, kCFNumberCGFloatType, &stretch);
+ CFDictionaryAddValue(traits_dict, kCTFontWidthTrait, font_stretch);
+
CFMutableDictionaryRef attributes = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, nullptr, nullptr);
CFDictionaryAddValue(attributes, kCTFontFamilyNameAttribute, name);
CFDictionaryAddValue(attributes, kCTFontTraitsAttribute, traits_dict);
@@ -384,6 +502,8 @@ String OS_MacOS::get_system_font_path(const String &p_font_name, bool p_bold, bo
CFRelease(attributes);
CFRelease(traits_dict);
CFRelease(sym_traits);
+ CFRelease(font_stretch);
+ CFRelease(font_weight);
CFRelease(name);
return ret;
diff --git a/platform/macos/platform_config.h b/platform/macos/platform_config.h
index e114606b82..46c46b8803 100644
--- a/platform/macos/platform_config.h
+++ b/platform/macos/platform_config.h
@@ -30,5 +30,5 @@
#include <alloca.h>
-#define OPENGL_INCLUDE_H "thirdparty/glad/glad/glad.h"
+#define OPENGL_INCLUDE_H "thirdparty/glad/glad/gl.h"
#define PTHREAD_RENAME_SELF
diff --git a/platform/web/SCsub b/platform/web/SCsub
index 077024507a..e44e59bfb9 100644
--- a/platform/web/SCsub
+++ b/platform/web/SCsub
@@ -38,15 +38,20 @@ sys_env.AddJSLibraries(
"js/libs/library_godot_webgl2.js",
]
)
+sys_env.AddJSExterns(
+ [
+ "js/libs/library_godot_webgl2.externs.js",
+ ]
+)
if env["javascript_eval"]:
sys_env.AddJSLibraries(["js/libs/library_godot_javascript_singleton.js"])
for lib in sys_env["JS_LIBS"]:
sys_env.Append(LINKFLAGS=["--js-library", lib.abspath])
-for js in env["JS_PRE"]:
+for js in sys_env["JS_PRE"]:
sys_env.Append(LINKFLAGS=["--pre-js", js.abspath])
-for ext in env["JS_EXTERNS"]:
+for ext in sys_env["JS_EXTERNS"]:
sys_env["ENV"]["EMCC_CLOSURE_ARGS"] += " --externs " + ext.abspath
build = []
diff --git a/platform/web/display_server_web.cpp b/platform/web/display_server_web.cpp
index f704124704..d057010c02 100644
--- a/platform/web/display_server_web.cpp
+++ b/platform/web/display_server_web.cpp
@@ -579,8 +579,8 @@ void DisplayServerWeb::touch_callback(int p_type, int p_count) {
}
}
-bool DisplayServerWeb::screen_is_touchscreen(int p_screen) const {
- return godot_js_display_touchscreen_is_available();
+bool DisplayServerWeb::is_touchscreen_available() const {
+ return godot_js_display_touchscreen_is_available() || (Input::get_singleton() && Input::get_singleton()->is_emulating_touch_from_mouse());
}
// Virtual Keyboard
@@ -943,7 +943,11 @@ void DisplayServerWeb::window_set_current_screen(int p_screen, WindowID p_window
}
Point2i DisplayServerWeb::window_get_position(WindowID p_window) const {
- return Point2i(); // TODO Does this need implementation?
+ return Point2i();
+}
+
+Point2i DisplayServerWeb::window_get_position_with_decorations(WindowID p_window) const {
+ return Point2i();
}
void DisplayServerWeb::window_set_position(const Point2i &p_position, WindowID p_window) {
@@ -980,7 +984,7 @@ Size2i DisplayServerWeb::window_get_size(WindowID p_window) const {
return Size2i(size[0], size[1]);
}
-Size2i DisplayServerWeb::window_get_real_size(WindowID p_window) const {
+Size2i DisplayServerWeb::window_get_size_with_decorations(WindowID p_window) const {
return window_get_size(p_window);
}
diff --git a/platform/web/display_server_web.h b/platform/web/display_server_web.h
index 1919736802..fce98ec3d0 100644
--- a/platform/web/display_server_web.h
+++ b/platform/web/display_server_web.h
@@ -143,7 +143,7 @@ public:
virtual Point2i mouse_get_position() const override;
// touch
- virtual bool screen_is_touchscreen(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
+ virtual bool is_touchscreen_available() const override;
// clipboard
virtual void clipboard_set(const String &p_text) override;
@@ -182,6 +182,7 @@ public:
virtual void window_set_current_screen(int p_screen, WindowID p_window = MAIN_WINDOW_ID) override;
virtual Point2i window_get_position(WindowID p_window = MAIN_WINDOW_ID) const override;
+ virtual Point2i window_get_position_with_decorations(WindowID p_window = MAIN_WINDOW_ID) const override;
virtual void window_set_position(const Point2i &p_position, WindowID p_window = MAIN_WINDOW_ID) override;
virtual void window_set_transient(WindowID p_window, WindowID p_parent) override;
@@ -194,7 +195,7 @@ public:
virtual void window_set_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID) override;
virtual Size2i window_get_size(WindowID p_window = MAIN_WINDOW_ID) const override;
- virtual Size2i window_get_real_size(WindowID p_window = MAIN_WINDOW_ID) const override;
+ virtual Size2i window_get_size_with_decorations(WindowID p_window = MAIN_WINDOW_ID) const override;
virtual void window_set_mode(WindowMode p_mode, WindowID p_window = MAIN_WINDOW_ID) override;
virtual WindowMode window_get_mode(WindowID p_window = MAIN_WINDOW_ID) const override;
diff --git a/platform/web/export/export_plugin.cpp b/platform/web/export/export_plugin.cpp
index f59ac54f20..3087b12c40 100644
--- a/platform/web/export/export_plugin.cpp
+++ b/platform/web/export/export_plugin.cpp
@@ -133,7 +133,7 @@ void EditorExportPlatformWeb::_fix_html(Vector<uint8_t> &p_html, const Ref<Edito
config["canvasResizePolicy"] = p_preset->get("html/canvas_resize_policy");
config["experimentalVK"] = p_preset->get("html/experimental_virtual_keyboard");
config["focusCanvas"] = p_preset->get("html/focus_canvas_on_start");
- config["gdnativeLibs"] = libs;
+ config["gdextensionLibs"] = libs;
config["executable"] = p_name;
config["args"] = args;
config["fileSizes"] = p_file_sizes;
diff --git a/platform/web/js/engine/config.js b/platform/web/js/engine/config.js
index 4560f12b49..6a30c253fb 100644
--- a/platform/web/js/engine/config.js
+++ b/platform/web/js/engine/config.js
@@ -127,7 +127,7 @@ const InternalConfig = function (initConfig) { // eslint-disable-line no-unused-
* @ignore
* @type {Array.<string>}
*/
- gdnativeLibs: [],
+ gdextensionLibs: [],
/**
* @ignore
* @type {Array.<string>}
@@ -257,7 +257,7 @@ const InternalConfig = function (initConfig) { // eslint-disable-line no-unused-
this.experimentalVK = parse('experimentalVK', this.experimentalVK);
this.focusCanvas = parse('focusCanvas', this.focusCanvas);
this.serviceWorker = parse('serviceWorker', this.serviceWorker);
- this.gdnativeLibs = parse('gdnativeLibs', this.gdnativeLibs);
+ this.gdextensionLibs = parse('gdextensionLibs', this.gdextensionLibs);
this.fileSizes = parse('fileSizes', this.fileSizes);
this.args = parse('args', this.args);
this.onExecute = parse('onExecute', this.onExecute);
diff --git a/platform/web/js/engine/engine.js b/platform/web/js/engine/engine.js
index 9227aa1f05..fb80bd55e1 100644
--- a/platform/web/js/engine/engine.js
+++ b/platform/web/js/engine/engine.js
@@ -162,9 +162,9 @@ const Engine = (function () {
// Godot configuration.
me.rtenv['initConfig'](config);
- // Preload GDNative libraries.
+ // Preload GDExtension libraries.
const libs = [];
- me.config.gdnativeLibs.forEach(function (lib) {
+ me.config.gdextensionLibs.forEach(function (lib) {
libs.push(me.rtenv['loadDynamicLibrary'](lib, { 'loadAsync': true }));
});
return Promise.all(libs).then(function () {
diff --git a/platform/web/js/engine/features.js b/platform/web/js/engine/features.js
index f91a4eff81..b7c6c9d445 100644
--- a/platform/web/js/engine/features.js
+++ b/platform/web/js/engine/features.js
@@ -76,19 +76,19 @@ const Features = { // eslint-disable-line no-unused-vars
getMissingFeatures: function () {
const missing = [];
if (!Features.isWebGLAvailable(2)) {
- missing.push('WebGL2');
+ missing.push('WebGL2 - Check web browser configuration and hardware support');
}
if (!Features.isFetchAvailable()) {
- missing.push('Fetch');
+ missing.push('Fetch - Check web browser version');
}
if (!Features.isSecureContext()) {
- missing.push('Secure Context');
+ missing.push('Secure Context - Check web server configuration (use HTTPS)');
}
if (!Features.isCrossOriginIsolated()) {
- missing.push('Cross Origin Isolation');
+ missing.push('Cross Origin Isolation - Check web server configuration (send correct headers)');
}
if (!Features.isSharedArrayBufferAvailable()) {
- missing.push('SharedArrayBuffer');
+ missing.push('SharedArrayBuffer - Check web server configuration (send correct headers)');
}
// Audio is normally optional since we have a dummy fallback.
return missing;
diff --git a/platform/web/js/libs/library_godot_webgl2.externs.js b/platform/web/js/libs/library_godot_webgl2.externs.js
new file mode 100644
index 0000000000..18d8d0815a
--- /dev/null
+++ b/platform/web/js/libs/library_godot_webgl2.externs.js
@@ -0,0 +1,36 @@
+
+/**
+ * @constructor OVR_multiview2
+ */
+function OVR_multiview2() {}
+
+/**
+ * @type {number}
+ */
+OVR_multiview2.prototype.FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_OVR;
+
+/**
+ * @type {number}
+ */
+OVR_multiview2.prototype.FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_OVR;
+
+/**
+ * @type {number}
+ */
+OVR_multiview2.prototype.MAX_VIEWS_OVR;
+
+/**
+ * @type {number}
+ */
+OVR_multiview2.prototype.FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_OVR;
+
+/**
+ * @param {number} target
+ * @param {number} attachment
+ * @param {WebGLTexture} texture
+ * @param {number} level
+ * @param {number} baseViewIndex
+ * @param {number} numViews
+ * @return {void}
+ */
+OVR_multiview2.prototype.framebufferTextureMultiviewOVR = function(target, attachment, texture, level, baseViewIndex, numViews) {};
diff --git a/platform/web/js/libs/library_godot_webgl2.js b/platform/web/js/libs/library_godot_webgl2.js
index 365f712be7..ba990b3ee0 100644
--- a/platform/web/js/libs/library_godot_webgl2.js
+++ b/platform/web/js/libs/library_godot_webgl2.js
@@ -37,14 +37,15 @@ const GodotWebGL2 = {
godot_webgl2_glFramebufferTextureMultiviewOVR: function (target, attachment, texture, level, base_view_index, num_views) {
const context = GL.currentContext;
if (typeof context.multiviewExt === 'undefined') {
- const ext = context.GLctx.getExtension('OVR_multiview2');
+ const /** OVR_multiview2 */ ext = context.GLctx.getExtension('OVR_multiview2');
if (!ext) {
console.error('Trying to call glFramebufferTextureMultiviewOVR() without the OVR_multiview2 extension');
return;
}
context.multiviewExt = ext;
}
- context.multiviewExt.framebufferTextureMultiviewOVR(target, attachment, GL.textures[texture], level, base_view_index, num_views);
+ const /** OVR_multiview2 */ ext = context.multiviewExt;
+ ext.framebufferTextureMultiviewOVR(target, attachment, GL.textures[texture], level, base_view_index, num_views);
},
};
diff --git a/platform/windows/console_wrapper_windows.cpp b/platform/windows/console_wrapper_windows.cpp
index 749f51e6e4..258176426b 100644
--- a/platform/windows/console_wrapper_windows.cpp
+++ b/platform/windows/console_wrapper_windows.cpp
@@ -63,7 +63,7 @@ int main(int argc, char *argv[]) {
}
}
- // Enable virtual termial sequences processing.
+ // Enable virtual terminal sequences processing.
HANDLE stdout_handle = GetStdHandle(STD_OUTPUT_HANDLE);
DWORD out_mode = ENABLE_PROCESSED_OUTPUT | ENABLE_VIRTUAL_TERMINAL_PROCESSING;
SetConsoleMode(stdout_handle, out_mode);
diff --git a/platform/windows/crash_handler_windows.cpp b/platform/windows/crash_handler_windows.cpp
index b501ee78db..7ba66750cf 100644
--- a/platform/windows/crash_handler_windows.cpp
+++ b/platform/windows/crash_handler_windows.cpp
@@ -157,7 +157,7 @@ DWORD CrashHandlerException(EXCEPTION_POINTERS *ep) {
return EXCEPTION_CONTINUE_SEARCH;
}
- SymSetOptions(SymGetOptions() | SYMOPT_LOAD_LINES | SYMOPT_UNDNAME);
+ SymSetOptions(SymGetOptions() | SYMOPT_LOAD_LINES | SYMOPT_UNDNAME | SYMOPT_EXACT_SYMBOLS);
EnumProcessModules(process, &module_handles[0], module_handles.size() * sizeof(HMODULE), &cbNeeded);
module_handles.resize(cbNeeded / sizeof(HMODULE));
EnumProcessModules(process, &module_handles[0], module_handles.size() * sizeof(HMODULE), &cbNeeded);
diff --git a/platform/windows/detect.py b/platform/windows/detect.py
index 705e83dace..1b55574b19 100644
--- a/platform/windows/detect.py
+++ b/platform/windows/detect.py
@@ -188,6 +188,7 @@ def get_opts():
BoolVariable("use_llvm", "Use the LLVM compiler", False),
BoolVariable("use_static_cpp", "Link MinGW/MSVC C++ runtime libraries statically", True),
BoolVariable("use_asan", "Use address sanitizer (ASAN)", False),
+ BoolVariable("debug_crt", "Compile with MSVC's debug CRT (/MDd)", False),
]
@@ -339,10 +340,14 @@ def configure_msvc(env, vcvars_msvc_config):
## Compile/link flags
- if env["use_static_cpp"]:
- env.AppendUnique(CCFLAGS=["/MT"])
+ if env["debug_crt"]:
+ # Always use dynamic runtime, static debug CRT breaks thread_local.
+ env.AppendUnique(CCFLAGS=["/MDd"])
else:
- env.AppendUnique(CCFLAGS=["/MD"])
+ if env["use_static_cpp"]:
+ env.AppendUnique(CCFLAGS=["/MT"])
+ else:
+ env.AppendUnique(CCFLAGS=["/MD"])
if env["arch"] == "x86_32":
env["x86_libtheora_opt_vc"] = True
diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp
index 2c8058fdc5..e7864ebac0 100644
--- a/platform/windows/display_server_windows.cpp
+++ b/platform/windows/display_server_windows.cpp
@@ -743,10 +743,16 @@ int64_t DisplayServerWindows::window_get_native_handle(HandleType p_handle_type,
}
#if defined(GLES3_ENABLED)
case WINDOW_VIEW: {
- return (int64_t)gl_manager->get_hdc(p_window);
+ if (gl_manager) {
+ return (int64_t)gl_manager->get_hdc(p_window);
+ }
+ return 0;
}
case OPENGL_CONTEXT: {
- return (int64_t)gl_manager->get_hglrc(p_window);
+ if (gl_manager) {
+ return (int64_t)gl_manager->get_hglrc(p_window);
+ }
+ return 0;
}
#endif
default: {
@@ -903,6 +909,24 @@ Point2i DisplayServerWindows::window_get_position(WindowID p_window) const {
return Point2i(point.x, point.y);
}
+Point2i DisplayServerWindows::window_get_position_with_decorations(WindowID p_window) const {
+ _THREAD_SAFE_METHOD_
+
+ ERR_FAIL_COND_V(!windows.has(p_window), Point2i());
+ const WindowData &wd = windows[p_window];
+
+ if (wd.minimized) {
+ return wd.last_pos;
+ }
+
+ RECT r;
+ if (GetWindowRect(wd.hWnd, &r)) {
+ return Point2i(r.left, r.top);
+ }
+
+ return Point2i();
+}
+
void DisplayServerWindows::_update_real_mouse_position(WindowID p_window) {
ERR_FAIL_COND(!windows.has(p_window));
@@ -1118,7 +1142,7 @@ Size2i DisplayServerWindows::window_get_size(WindowID p_window) const {
return Size2();
}
-Size2i DisplayServerWindows::window_get_real_size(WindowID p_window) const {
+Size2i DisplayServerWindows::window_get_size_with_decorations(WindowID p_window) const {
_THREAD_SAFE_METHOD_
ERR_FAIL_COND_V(!windows.has(p_window), Size2i());
@@ -1886,7 +1910,7 @@ void DisplayServerWindows::set_native_icon(const String &p_filename) {
pos += sizeof(WORD);
f->seek(pos);
- icon_dir = (ICONDIR *)memrealloc(icon_dir, 3 * sizeof(WORD) + icon_dir->idCount * sizeof(ICONDIRENTRY));
+ icon_dir = (ICONDIR *)memrealloc(icon_dir, sizeof(ICONDIR) - sizeof(ICONDIRENTRY) + icon_dir->idCount * sizeof(ICONDIRENTRY));
f->get_buffer((uint8_t *)&icon_dir->idEntries[0], icon_dir->idCount * sizeof(ICONDIRENTRY));
int small_icon_index = -1; // Select 16x16 with largest color count.
@@ -2017,6 +2041,12 @@ void DisplayServerWindows::window_set_vsync_mode(DisplayServer::VSyncMode p_vsyn
context_vulkan->set_vsync_mode(p_window, p_vsync_mode);
}
#endif
+
+#if defined(GLES3_ENABLED)
+ if (gl_manager) {
+ gl_manager->set_use_vsync(p_window, p_vsync_mode != DisplayServer::VSYNC_DISABLED);
+ }
+#endif
}
DisplayServer::VSyncMode DisplayServerWindows::window_get_vsync_mode(WindowID p_window) const {
@@ -2026,6 +2056,13 @@ DisplayServer::VSyncMode DisplayServerWindows::window_get_vsync_mode(WindowID p_
return context_vulkan->get_vsync_mode(p_window);
}
#endif
+
+#if defined(GLES3_ENABLED)
+ if (gl_manager) {
+ return gl_manager->is_using_vsync(p_window) ? DisplayServer::VSYNC_ENABLED : DisplayServer::VSYNC_DISABLED;
+ }
+#endif
+
return DisplayServer::VSYNC_ENABLED;
}
@@ -2395,7 +2432,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
case WM_GETMINMAXINFO: {
if (windows[window_id].resizable && !windows[window_id].fullscreen) {
// Size of window decorations.
- Size2 decor = window_get_real_size(window_id) - window_get_size(window_id);
+ Size2 decor = window_get_size_with_decorations(window_id) - window_get_size(window_id);
MINMAXINFO *min_max_info = (MINMAXINFO *)lParam;
if (windows[window_id].min_size != Size2()) {
@@ -2454,7 +2491,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
window_mouseover_id = INVALID_WINDOW_ID;
_send_window_event(windows[window_id], WINDOW_EVENT_MOUSE_EXIT);
- } else if (window_mouseover_id != INVALID_WINDOW_ID) {
+ } else if (window_mouseover_id != INVALID_WINDOW_ID && windows.has(window_mouseover_id)) {
// This is reached during drag and drop, after dropping in a different window.
// Once-off notification, must call again.
track_mouse_leave_event(windows[window_mouseover_id].hWnd);
@@ -2693,7 +2730,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
// Mouse enter.
if (mouse_mode != MOUSE_MODE_CAPTURED) {
- if (window_mouseover_id != INVALID_WINDOW_ID) {
+ if (window_mouseover_id != INVALID_WINDOW_ID && windows.has(window_mouseover_id)) {
// Leave previous window.
_send_window_event(windows[window_mouseover_id], WINDOW_EVENT_MOUSE_EXIT);
}
@@ -2795,7 +2832,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
}
DisplayServer::WindowID over_id = get_window_at_screen_position(mouse_get_position());
- if (!Rect2(window_get_position(over_id), Point2(windows[over_id].width, windows[over_id].height)).has_point(mouse_get_position())) {
+ if (windows.has(over_id) && !Rect2(window_get_position(over_id), Point2(windows[over_id].width, windows[over_id].height)).has_point(mouse_get_position())) {
// Don't consider the windowborder as part of the window.
over_id = INVALID_WINDOW_ID;
}
@@ -2803,12 +2840,12 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
// Mouse enter.
if (mouse_mode != MOUSE_MODE_CAPTURED) {
- if (window_mouseover_id != INVALID_WINDOW_ID) {
+ if (window_mouseover_id != INVALID_WINDOW_ID && windows.has(window_mouseover_id)) {
// Leave previous window.
_send_window_event(windows[window_mouseover_id], WINDOW_EVENT_MOUSE_EXIT);
}
- if (over_id != INVALID_WINDOW_ID) {
+ if (over_id != INVALID_WINDOW_ID && windows.has(over_id)) {
_send_window_event(windows[over_id], WINDOW_EVENT_MOUSE_ENTER);
}
}
@@ -2891,11 +2928,10 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
old_x = mm->get_position().x;
old_y = mm->get_position().y;
- if (!windows[receiving_window_id].window_has_focus) {
- // In case of unfocused Popups, adjust event position.
- Point2i pos = mm->get_position() - window_get_position(receiving_window_id) + window_get_position(window_id);
- mm->set_position(pos);
- mm->set_global_position(pos);
+ if (receiving_window_id != window_id) {
+ // Adjust event position relative to window distance when event is sent to a different window.
+ mm->set_position(mm->get_position() - window_get_position(receiving_window_id) + window_get_position(window_id));
+ mm->set_global_position(mm->get_position());
}
Input::get_singleton()->parse_input_event(mm);
@@ -3502,7 +3538,7 @@ DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode,
DWORD dwExStyle;
DWORD dwStyle;
- _get_window_style(window_id_counter == MAIN_WINDOW_ID, (p_mode == WINDOW_MODE_FULLSCREEN || p_mode == WINDOW_MODE_EXCLUSIVE_FULLSCREEN), p_mode == WINDOW_MODE_EXCLUSIVE_FULLSCREEN, p_flags & WINDOW_FLAG_BORDERLESS_BIT, !(p_flags & WINDOW_FLAG_RESIZE_DISABLED_BIT), p_mode == WINDOW_MODE_MAXIMIZED, (p_flags & WINDOW_FLAG_NO_FOCUS_BIT), dwStyle, dwExStyle);
+ _get_window_style(window_id_counter == MAIN_WINDOW_ID, (p_mode == WINDOW_MODE_FULLSCREEN || p_mode == WINDOW_MODE_EXCLUSIVE_FULLSCREEN), p_mode == WINDOW_MODE_EXCLUSIVE_FULLSCREEN, p_flags & WINDOW_FLAG_BORDERLESS_BIT, !(p_flags & WINDOW_FLAG_RESIZE_DISABLED_BIT), p_mode == WINDOW_MODE_MAXIMIZED, (p_flags & WINDOW_FLAG_NO_FOCUS_BIT) | (p_flags & WINDOW_FLAG_POPUP), dwStyle, dwExStyle);
RECT WindowRect;
@@ -3595,6 +3631,7 @@ DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode,
windows.erase(id);
ERR_FAIL_V_MSG(INVALID_WINDOW_ID, "Failed to create an OpenGL window.");
}
+ window_set_vsync_mode(p_vsync_mode, id);
}
#endif
@@ -3899,6 +3936,8 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win
WindowID main_window = _create_window(p_mode, p_vsync_mode, 0, Rect2i(window_position, p_resolution));
ERR_FAIL_COND_MSG(main_window == INVALID_WINDOW_ID, "Failed to create main window.");
+ joypad = new JoypadWindows(&windows[MAIN_WINDOW_ID].hWnd);
+
for (int i = 0; i < WINDOW_FLAG_MAX; i++) {
if (p_flags & (1 << i)) {
window_set_flag(WindowFlags(i), true, main_window);
@@ -3938,8 +3977,6 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win
_update_real_mouse_position(MAIN_WINDOW_ID);
- joypad = new JoypadWindows(&windows[MAIN_WINDOW_ID].hWnd);
-
r_error = OK;
static_cast<OS_Windows *>(OS::get_singleton())->set_main_window(windows[MAIN_WINDOW_ID].hWnd);
diff --git a/platform/windows/display_server_windows.h b/platform/windows/display_server_windows.h
index 8ac0086d69..4702bb7765 100644
--- a/platform/windows/display_server_windows.h
+++ b/platform/windows/display_server_windows.h
@@ -555,6 +555,7 @@ public:
virtual void window_set_current_screen(int p_screen, WindowID p_window = MAIN_WINDOW_ID) override;
virtual Point2i window_get_position(WindowID p_window = MAIN_WINDOW_ID) const override;
+ virtual Point2i window_get_position_with_decorations(WindowID p_window = MAIN_WINDOW_ID) const override;
virtual void window_set_position(const Point2i &p_position, WindowID p_window = MAIN_WINDOW_ID) override;
virtual void window_set_transient(WindowID p_window, WindowID p_parent) override;
@@ -568,7 +569,7 @@ public:
virtual void window_set_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID) override;
virtual Size2i window_get_size(WindowID p_window = MAIN_WINDOW_ID) const override;
- virtual Size2i window_get_real_size(WindowID p_window = MAIN_WINDOW_ID) const override; //wtf is this? should probable use proper name
+ virtual Size2i window_get_size_with_decorations(WindowID p_window = MAIN_WINDOW_ID) const override;
virtual void window_set_mode(WindowMode p_mode, WindowID p_window = MAIN_WINDOW_ID) override;
virtual WindowMode window_get_mode(WindowID p_window = MAIN_WINDOW_ID) const override;
diff --git a/platform/windows/export/export_plugin.cpp b/platform/windows/export/export_plugin.cpp
index d15380ac7a..89f56ffd93 100644
--- a/platform/windows/export/export_plugin.cpp
+++ b/platform/windows/export/export_plugin.cpp
@@ -31,7 +31,122 @@
#include "export_plugin.h"
#include "core/config/project_settings.h"
+#include "core/io/image_loader.h"
#include "editor/editor_node.h"
+#include "editor/editor_paths.h"
+
+Error EditorExportPlatformWindows::_process_icon(const Ref<EditorExportPreset> &p_preset, const String &p_src_path, const String &p_dst_path) {
+ static const uint8_t icon_size[] = { 16, 32, 48, 64, 128, 0 /*256*/ };
+
+ struct IconData {
+ Vector<uint8_t> data;
+ uint8_t pal_colors = 0;
+ uint16_t planes = 0;
+ uint16_t bpp = 32;
+ };
+
+ HashMap<uint8_t, IconData> images;
+ Error err;
+
+ if (p_src_path.get_extension() == "ico") {
+ Ref<FileAccess> f = FileAccess::open(p_src_path, FileAccess::READ, &err);
+ if (err != OK) {
+ return err;
+ }
+
+ // Read ICONDIR.
+ f->get_16(); // Reserved.
+ uint16_t icon_type = f->get_16(); // Image type: 1 - ICO.
+ uint16_t icon_count = f->get_16(); // Number of images.
+ ERR_FAIL_COND_V(icon_type != 1, ERR_CANT_OPEN);
+
+ for (uint16_t i = 0; i < icon_count; i++) {
+ // Read ICONDIRENTRY.
+ uint16_t w = f->get_8(); // Width in pixels.
+ uint16_t h = f->get_8(); // Height in pixels.
+ uint8_t pal_colors = f->get_8(); // Number of colors in the palette (0 - no palette).
+ f->get_8(); // Reserved.
+ uint16_t planes = f->get_16(); // Number of color planes.
+ uint16_t bpp = f->get_16(); // Bits per pixel.
+ uint32_t img_size = f->get_32(); // Image data size in bytes.
+ uint32_t img_offset = f->get_32(); // Image data offset.
+ if (w != h) {
+ continue;
+ }
+
+ // Read image data.
+ uint64_t prev_offset = f->get_position();
+ images[w].pal_colors = pal_colors;
+ images[w].planes = planes;
+ images[w].bpp = bpp;
+ images[w].data.resize(img_size);
+ f->seek(img_offset);
+ f->get_buffer(images[w].data.ptrw(), img_size);
+ f->seek(prev_offset);
+ }
+ } else {
+ Ref<Image> src_image;
+ src_image.instantiate();
+ err = ImageLoader::load_image(p_src_path, src_image);
+ ERR_FAIL_COND_V(err != OK || src_image->is_empty(), ERR_CANT_OPEN);
+ for (size_t i = 0; i < sizeof(icon_size) / sizeof(icon_size[0]); ++i) {
+ int size = (icon_size[i] == 0) ? 256 : icon_size[i];
+
+ Ref<Image> res_image = src_image->duplicate();
+ ERR_FAIL_COND_V(res_image.is_null() || res_image->is_empty(), ERR_CANT_OPEN);
+ res_image->resize(size, size, (Image::Interpolation)(p_preset->get("application/icon_interpolation").operator int()));
+ images[icon_size[i]].data = res_image->save_png_to_buffer();
+ }
+ }
+
+ uint16_t valid_icon_count = 0;
+ for (size_t i = 0; i < sizeof(icon_size) / sizeof(icon_size[0]); ++i) {
+ if (images.has(icon_size[i])) {
+ valid_icon_count++;
+ } else {
+ int size = (icon_size[i] == 0) ? 256 : icon_size[i];
+ add_message(EXPORT_MESSAGE_WARNING, TTR("Resources Modification"), vformat(TTR("Icon size \"%d\" is missing."), size));
+ }
+ }
+ ERR_FAIL_COND_V(valid_icon_count == 0, ERR_CANT_OPEN);
+
+ Ref<FileAccess> fw = FileAccess::open(p_dst_path, FileAccess::WRITE, &err);
+ if (err != OK) {
+ return err;
+ }
+
+ // Write ICONDIR.
+ fw->store_16(0); // Reserved.
+ fw->store_16(1); // Image type: 1 - ICO.
+ fw->store_16(valid_icon_count); // Number of images.
+
+ // Write ICONDIRENTRY.
+ uint32_t img_offset = 6 + 16 * valid_icon_count;
+ for (size_t i = 0; i < sizeof(icon_size) / sizeof(icon_size[0]); ++i) {
+ if (images.has(icon_size[i])) {
+ const IconData &di = images[icon_size[i]];
+ fw->store_8(icon_size[i]); // Width in pixels.
+ fw->store_8(icon_size[i]); // Height in pixels.
+ fw->store_8(di.pal_colors); // Number of colors in the palette (0 - no palette).
+ fw->store_8(0); // Reserved.
+ fw->store_16(di.planes); // Number of color planes.
+ fw->store_16(di.bpp); // Bits per pixel.
+ fw->store_32(di.data.size()); // Image data size in bytes.
+ fw->store_32(img_offset); // Image data offset.
+
+ img_offset += di.data.size();
+ }
+ }
+
+ // Write image data.
+ for (size_t i = 0; i < sizeof(icon_size) / sizeof(icon_size[0]); ++i) {
+ if (images.has(icon_size[i])) {
+ const IconData &di = images[icon_size[i]];
+ fw->store_buffer(di.data.ptr(), di.data.size());
+ }
+ }
+ return OK;
+}
Error EditorExportPlatformWindows::sign_shared_object(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path) {
if (p_preset->get("codesign/enable")) {
@@ -110,7 +225,9 @@ void EditorExportPlatformWindows::get_export_options(List<ExportOption> *r_optio
r_options->push_back(ExportOption(PropertyInfo(Variant::PACKED_STRING_ARRAY, "codesign/custom_options"), PackedStringArray()));
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "application/modify_resources"), true));
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/icon", PROPERTY_HINT_FILE, "*.ico"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/icon", PROPERTY_HINT_FILE, "*.ico,*.png,*.webp,*.svg"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/console_wrapper_icon", PROPERTY_HINT_FILE, "*.ico,*.png,*.webp,*.svg"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "application/icon_interpolation", PROPERTY_HINT_ENUM, "Nearest neighbor,Bilinear,Cubic,Trilinear,Lanczos"), 4));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/file_version", PROPERTY_HINT_PLACEHOLDER_TEXT, "1.0.0.0"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/product_version", PROPERTY_HINT_PLACEHOLDER_TEXT, "1.0.0.0"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/company_name", PROPERTY_HINT_PLACEHOLDER_TEXT, "Company Name"), ""));
@@ -120,7 +237,7 @@ void EditorExportPlatformWindows::get_export_options(List<ExportOption> *r_optio
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/trademarks"), ""));
}
-Error EditorExportPlatformWindows::_rcedit_add_data(const Ref<EditorExportPreset> &p_preset, const String &p_path, bool p_set_icon) {
+Error EditorExportPlatformWindows::_rcedit_add_data(const Ref<EditorExportPreset> &p_preset, const String &p_path, bool p_console_icon) {
String rcedit_path = EDITOR_GET("export/windows/rcedit");
if (rcedit_path != String() && !FileAccess::exists(rcedit_path)) {
@@ -147,6 +264,21 @@ Error EditorExportPlatformWindows::_rcedit_add_data(const Ref<EditorExportPreset
#endif
String icon_path = ProjectSettings::get_singleton()->globalize_path(p_preset->get("application/icon"));
+ if (p_console_icon) {
+ String console_icon_path = ProjectSettings::get_singleton()->globalize_path(p_preset->get("application/console_wrapper_icon"));
+ if (!console_icon_path.is_empty() && FileAccess::exists(console_icon_path)) {
+ icon_path = console_icon_path;
+ }
+ }
+
+ String tmp_icon_path = EditorPaths::get_singleton()->get_cache_dir().path_join("_rcedit.ico");
+ if (!icon_path.is_empty()) {
+ if (_process_icon(p_preset, icon_path, tmp_icon_path) != OK) {
+ add_message(EXPORT_MESSAGE_WARNING, TTR("Resources Modification"), vformat(TTR("Invalid icon file \"%s\"."), icon_path));
+ icon_path = String();
+ }
+ }
+
String file_verion = p_preset->get("application/file_version");
String product_version = p_preset->get("application/product_version");
String company_name = p_preset->get("application/company_name");
@@ -158,9 +290,9 @@ Error EditorExportPlatformWindows::_rcedit_add_data(const Ref<EditorExportPreset
List<String> args;
args.push_back(p_path);
- if (!icon_path.is_empty() && p_set_icon) {
+ if (!icon_path.is_empty()) {
args.push_back("--set-icon");
- args.push_back(icon_path);
+ args.push_back(tmp_icon_path);
}
if (!file_verion.is_empty()) {
args.push_back("--set-file-version");
@@ -204,6 +336,11 @@ Error EditorExportPlatformWindows::_rcedit_add_data(const Ref<EditorExportPreset
String str;
Error err = OS::get_singleton()->execute(rcedit_path, args, &str, nullptr, true);
+
+ if (FileAccess::exists(tmp_icon_path)) {
+ DirAccess::remove_file_or_error(tmp_icon_path);
+ }
+
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), or disable \"Application > Modify Resources\" in the export preset."));
return err;
diff --git a/platform/windows/export/export_plugin.h b/platform/windows/export/export_plugin.h
index ec3b60aa76..a9e6d51b9d 100644
--- a/platform/windows/export/export_plugin.h
+++ b/platform/windows/export/export_plugin.h
@@ -38,7 +38,8 @@
#include "platform/windows/logo.gen.h"
class EditorExportPlatformWindows : public EditorExportPlatformPC {
- Error _rcedit_add_data(const Ref<EditorExportPreset> &p_preset, const String &p_path, bool p_set_icon);
+ Error _process_icon(const Ref<EditorExportPreset> &p_preset, const String &p_src_path, const String &p_dst_path);
+ Error _rcedit_add_data(const Ref<EditorExportPreset> &p_preset, const String &p_path, bool p_console_icon);
Error _code_sign(const Ref<EditorExportPreset> &p_preset, const String &p_path);
public:
diff --git a/platform/windows/gl_manager_windows.cpp b/platform/windows/gl_manager_windows.cpp
index 900bca8258..5b39c56ea3 100644
--- a/platform/windows/gl_manager_windows.cpp
+++ b/platform/windows/gl_manager_windows.cpp
@@ -185,6 +185,10 @@ Error GLManager_Windows::_create_context(GLWindow &win, GLDisplay &gl_display) {
return ERR_CANT_CREATE;
}
+ if (!wglSwapIntervalEXT) {
+ wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC)wglGetProcAddress("wglSwapIntervalEXT");
+ }
+
return OK;
}
@@ -293,50 +297,30 @@ void GLManager_Windows::swap_buffers() {
}
Error GLManager_Windows::initialize() {
- wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC)wglGetProcAddress("wglSwapIntervalEXT");
- wglGetSwapIntervalEXT = (PFNWGLGETSWAPINTERVALEXTPROC)wglGetProcAddress("wglGetSwapIntervalEXT");
- //glWrapperInit(wrapper_get_proc_address);
-
return OK;
}
-void GLManager_Windows::set_use_vsync(bool p_use) {
- /*
- static bool setup = false;
- static PFNGLXSWAPINTERVALEXTPROC glXSwapIntervalEXT = nullptr;
- static PFNGLXSWAPINTERVALSGIPROC glXSwapIntervalMESA = nullptr;
- static PFNGLXSWAPINTERVALSGIPROC glXSwapIntervalSGI = nullptr;
-
- if (!setup) {
- setup = true;
- String extensions = glXQueryExtensionsString(x11_display, DefaultScreen(x11_display));
- if (extensions.find("GLX_EXT_swap_control") != -1) {
- glXSwapIntervalEXT = (PFNGLXSWAPINTERVALEXTPROC)glXGetProcAddressARB((const GLubyte *)"glXSwapIntervalEXT");
- }
- if (extensions.find("GLX_MESA_swap_control") != -1) {
- glXSwapIntervalMESA = (PFNGLXSWAPINTERVALSGIPROC)glXGetProcAddressARB((const GLubyte *)"glXSwapIntervalMESA");
- }
- if (extensions.find("GLX_SGI_swap_control") != -1) {
- glXSwapIntervalSGI = (PFNGLXSWAPINTERVALSGIPROC)glXGetProcAddressARB((const GLubyte *)"glXSwapIntervalSGI");
- }
+void GLManager_Windows::set_use_vsync(DisplayServer::WindowID p_window_id, bool p_use) {
+ GLWindow &win = get_window(p_window_id);
+ GLWindow *current = _current_window;
+
+ if (&win != _current_window) {
+ window_make_current(p_window_id);
}
- int val = p_use ? 1 : 0;
- if (glXSwapIntervalMESA) {
- glXSwapIntervalMESA(val);
- } else if (glXSwapIntervalSGI) {
- glXSwapIntervalSGI(val);
- } else if (glXSwapIntervalEXT) {
- GLXDrawable drawable = glXGetCurrentDrawable();
- glXSwapIntervalEXT(x11_display, drawable, val);
- } else {
- return;
+
+ if (wglSwapIntervalEXT) {
+ win.use_vsync = p_use;
+ wglSwapIntervalEXT(p_use ? 1 : 0);
+ }
+
+ if (current != _current_window) {
+ _current_window = current;
+ make_current();
}
- use_vsync = p_use;
- */
}
-bool GLManager_Windows::is_using_vsync() const {
- return use_vsync;
+bool GLManager_Windows::is_using_vsync(DisplayServer::WindowID p_window_id) const {
+ return get_window(p_window_id).use_vsync;
}
HDC GLManager_Windows::get_hdc(DisplayServer::WindowID p_window_id) {
@@ -354,7 +338,6 @@ GLManager_Windows::GLManager_Windows(ContextType p_context_type) {
direct_render = false;
glx_minor = glx_major = 0;
- use_vsync = false;
_current_window = nullptr;
}
diff --git a/platform/windows/gl_manager_windows.h b/platform/windows/gl_manager_windows.h
index c6d5f9f855..94f3ce9860 100644
--- a/platform/windows/gl_manager_windows.h
+++ b/platform/windows/gl_manager_windows.h
@@ -54,6 +54,7 @@ private:
struct GLWindow {
int width = 0;
int height = 0;
+ bool use_vsync = false;
// windows specific
HDC hDC;
@@ -72,8 +73,8 @@ private:
GLWindow *_current_window = nullptr;
- PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT;
- PFNWGLGETSWAPINTERVALEXTPROC wglGetSwapIntervalEXT;
+ PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT = nullptr;
+ PFNWGLGETSWAPINTERVALEXTPROC wglGetSwapIntervalEXT = nullptr;
// funcs
void _internal_set_current_window(GLWindow *p_win);
@@ -86,7 +87,6 @@ private:
bool direct_render;
int glx_minor, glx_major;
- bool use_vsync;
ContextType context_type;
private:
@@ -110,8 +110,8 @@ public:
Error initialize();
- void set_use_vsync(bool p_use);
- bool is_using_vsync() const;
+ void set_use_vsync(DisplayServer::WindowID p_window_id, bool p_use);
+ bool is_using_vsync(DisplayServer::WindowID p_window_id) const;
HDC get_hdc(DisplayServer::WindowID p_window_id);
HGLRC get_hglrc(DisplayServer::WindowID p_window_id);
diff --git a/platform/windows/godot.ico b/platform/windows/godot.ico
index 25830ffdc6..f0bb68225d 100644
--- a/platform/windows/godot.ico
+++ b/platform/windows/godot.ico
Binary files differ
diff --git a/platform/windows/godot_console.ico b/platform/windows/godot_console.ico
new file mode 100644
index 0000000000..1d27e3d6ae
--- /dev/null
+++ b/platform/windows/godot_console.ico
Binary files differ
diff --git a/platform/windows/godot_res_wrap.rc b/platform/windows/godot_res_wrap.rc
index ed93bb1ec3..9dd29afe51 100644
--- a/platform/windows/godot_res_wrap.rc
+++ b/platform/windows/godot_res_wrap.rc
@@ -4,6 +4,8 @@
#define _MKSTR(m_x) _STR(m_x)
#endif
+GODOT_ICON ICON platform/windows/godot_console.ico
+
1 VERSIONINFO
FILEVERSION VERSION_MAJOR,VERSION_MINOR,VERSION_PATCH,0
PRODUCTVERSION VERSION_MAJOR,VERSION_MINOR,VERSION_PATCH,0
diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp
index 08897bb190..f8633d29ac 100644
--- a/platform/windows/os_windows.cpp
+++ b/platform/windows/os_windows.cpp
@@ -43,12 +43,12 @@
#include "platform/windows/display_server_windows.h"
#include "servers/audio_server.h"
#include "servers/rendering/rendering_server_default.h"
+#include "servers/text_server.h"
#include "windows_terminal_logger.h"
#include <avrt.h>
#include <bcrypt.h>
#include <direct.h>
-#include <dwrite.h>
#include <knownfolders.h>
#include <process.h>
#include <regstr.h>
@@ -189,6 +189,27 @@ void OS_Windows::initialize() {
IPUnix::make_default();
main_loop = nullptr;
+
+ CoInitialize(nullptr);
+ HRESULT hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory), reinterpret_cast<IUnknown **>(&dwrite_factory));
+ if (SUCCEEDED(hr)) {
+ hr = dwrite_factory->GetSystemFontCollection(&font_collection, false);
+ if (SUCCEEDED(hr)) {
+ dwrite_init = true;
+ hr = dwrite_factory->QueryInterface(&dwrite_factory2);
+ if (SUCCEEDED(hr)) {
+ hr = dwrite_factory2->GetSystemFontFallback(&system_font_fallback);
+ if (SUCCEEDED(hr)) {
+ dwrite2_init = true;
+ }
+ }
+ }
+ }
+ if (!dwrite_init) {
+ print_verbose("Unable to load IDWriteFactory, system font support is disabled.");
+ } else if (!dwrite2_init) {
+ print_verbose("Unable to load IDWriteFactory2, automatic system font fallback is disabled.");
+ }
}
void OS_Windows::delete_main_loop() {
@@ -203,6 +224,22 @@ void OS_Windows::set_main_loop(MainLoop *p_main_loop) {
}
void OS_Windows::finalize() {
+ if (dwrite_factory2) {
+ dwrite_factory2->Release();
+ dwrite_factory2 = nullptr;
+ }
+ if (font_collection) {
+ font_collection->Release();
+ font_collection = nullptr;
+ }
+ if (system_font_fallback) {
+ system_font_fallback->Release();
+ system_font_fallback = nullptr;
+ }
+ if (dwrite_factory) {
+ dwrite_factory->Release();
+ dwrite_factory = nullptr;
+ }
#ifdef WINMIDI_ENABLED
driver_midi.close();
#endif
@@ -235,7 +272,7 @@ Error OS_Windows::open_dynamic_library(const String p_path, void *&p_library_han
String path = p_path.replace("/", "\\");
if (!FileAccess::exists(path)) {
- //this code exists so gdnative can load .dll files from within the executable path
+ //this code exists so gdextension can load .dll files from within the executable path
path = get_executable_path().get_base_dir().path_join(p_path.get_file());
}
@@ -726,21 +763,17 @@ Error OS_Windows::set_cwd(const String &p_cwd) {
}
Vector<String> OS_Windows::get_system_fonts() const {
+ if (!dwrite_init) {
+ return Vector<String>();
+ }
+
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);
+ HRESULT hr = font_collection->GetFontFamily(i, &family.reference);
ERR_CONTINUE(FAILED(hr) || family.is_null());
ComAutoreleaseRef<IDWriteLocalizedStrings> family_names;
@@ -771,7 +804,98 @@ Vector<String> OS_Windows::get_system_fonts() const {
return ret;
}
-String OS_Windows::get_system_font_path(const String &p_font_name, bool p_bold, bool p_italic) const {
+#if defined(__GNUC__) && !defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
+#endif
+
+class FallbackTextAnalysisSource : public IDWriteTextAnalysisSource {
+ LONG _cRef = 1;
+
+ bool rtl = false;
+ Char16String string;
+ Char16String locale;
+ IDWriteNumberSubstitution *n_sub = nullptr;
+
+public:
+ HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, VOID **ppvInterface) {
+ if (IID_IUnknown == riid) {
+ AddRef();
+ *ppvInterface = (IUnknown *)this;
+ } else if (__uuidof(IMMNotificationClient) == riid) {
+ AddRef();
+ *ppvInterface = (IMMNotificationClient *)this;
+ } else {
+ *ppvInterface = nullptr;
+ return E_NOINTERFACE;
+ }
+ return S_OK;
+ }
+
+ ULONG STDMETHODCALLTYPE AddRef() {
+ return InterlockedIncrement(&_cRef);
+ }
+
+ ULONG STDMETHODCALLTYPE Release() {
+ ULONG ulRef = InterlockedDecrement(&_cRef);
+ if (0 == ulRef) {
+ delete this;
+ }
+ return ulRef;
+ }
+
+ HRESULT STDMETHODCALLTYPE GetTextAtPosition(UINT32 p_text_position, WCHAR const **r_text_string, UINT32 *r_text_length) override {
+ if (p_text_position >= (UINT32)string.length()) {
+ *r_text_string = nullptr;
+ *r_text_length = 0;
+ return S_OK;
+ }
+ *r_text_string = reinterpret_cast<const wchar_t *>(string.get_data()) + p_text_position;
+ *r_text_length = string.length() - p_text_position;
+ return S_OK;
+ }
+
+ HRESULT STDMETHODCALLTYPE GetTextBeforePosition(UINT32 p_text_position, WCHAR const **r_text_string, UINT32 *r_text_length) override {
+ if (p_text_position < 1 || p_text_position >= (UINT32)string.length()) {
+ *r_text_string = nullptr;
+ *r_text_length = 0;
+ return S_OK;
+ }
+ *r_text_string = reinterpret_cast<const wchar_t *>(string.get_data());
+ *r_text_length = p_text_position;
+ return S_OK;
+ }
+
+ DWRITE_READING_DIRECTION STDMETHODCALLTYPE GetParagraphReadingDirection() override {
+ return (rtl) ? DWRITE_READING_DIRECTION_RIGHT_TO_LEFT : DWRITE_READING_DIRECTION_LEFT_TO_RIGHT;
+ }
+
+ HRESULT STDMETHODCALLTYPE GetLocaleName(UINT32 p_text_position, UINT32 *r_text_length, WCHAR const **r_locale_name) override {
+ *r_locale_name = reinterpret_cast<const wchar_t *>(locale.get_data());
+ return S_OK;
+ }
+
+ HRESULT STDMETHODCALLTYPE GetNumberSubstitution(UINT32 p_text_position, UINT32 *r_text_length, IDWriteNumberSubstitution **r_number_substitution) override {
+ *r_number_substitution = n_sub;
+ return S_OK;
+ }
+
+ FallbackTextAnalysisSource(const Char16String &p_text, const Char16String &p_locale, bool p_rtl, IDWriteNumberSubstitution *p_nsub) {
+ _cRef = 1;
+ string = p_text;
+ locale = p_locale;
+ n_sub = p_nsub;
+ rtl = p_rtl;
+ };
+
+ virtual ~FallbackTextAnalysisSource() {}
+};
+
+#if defined(__GNUC__) && !defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+
+String OS_Windows::_get_default_fontname(const String &p_font_name) const {
String font_name = p_font_name;
if (font_name.to_lower() == "sans-serif") {
font_name = "Arial";
@@ -784,19 +908,158 @@ String OS_Windows::get_system_font_path(const String &p_font_name, bool p_bold,
} else if (font_name.to_lower() == "fantasy") {
font_name = "Gabriola";
}
+ return font_name;
+}
- 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());
+DWRITE_FONT_WEIGHT OS_Windows::_weight_to_dw(int p_weight) const {
+ if (p_weight < 150) {
+ return DWRITE_FONT_WEIGHT_THIN;
+ } else if (p_weight < 250) {
+ return DWRITE_FONT_WEIGHT_EXTRA_LIGHT;
+ } else if (p_weight < 325) {
+ return DWRITE_FONT_WEIGHT_LIGHT;
+ } else if (p_weight < 375) {
+ return DWRITE_FONT_WEIGHT_SEMI_LIGHT;
+ } else if (p_weight < 450) {
+ return DWRITE_FONT_WEIGHT_NORMAL;
+ } else if (p_weight < 550) {
+ return DWRITE_FONT_WEIGHT_MEDIUM;
+ } else if (p_weight < 650) {
+ return DWRITE_FONT_WEIGHT_DEMI_BOLD;
+ } else if (p_weight < 750) {
+ return DWRITE_FONT_WEIGHT_BOLD;
+ } else if (p_weight < 850) {
+ return DWRITE_FONT_WEIGHT_EXTRA_BOLD;
+ } else if (p_weight < 925) {
+ return DWRITE_FONT_WEIGHT_BLACK;
+ } else {
+ return DWRITE_FONT_WEIGHT_EXTRA_BLACK;
+ }
+}
- ComAutoreleaseRef<IDWriteFontCollection> font_collection;
- hr = dwrite_factory->GetSystemFontCollection(&font_collection.reference, false);
- ERR_FAIL_COND_V(FAILED(hr) || font_collection.is_null(), String());
+DWRITE_FONT_STRETCH OS_Windows::_stretch_to_dw(int p_stretch) const {
+ if (p_stretch < 56) {
+ return DWRITE_FONT_STRETCH_ULTRA_CONDENSED;
+ } else if (p_stretch < 69) {
+ return DWRITE_FONT_STRETCH_EXTRA_CONDENSED;
+ } else if (p_stretch < 81) {
+ return DWRITE_FONT_STRETCH_CONDENSED;
+ } else if (p_stretch < 93) {
+ return DWRITE_FONT_STRETCH_SEMI_CONDENSED;
+ } else if (p_stretch < 106) {
+ return DWRITE_FONT_STRETCH_NORMAL;
+ } else if (p_stretch < 137) {
+ return DWRITE_FONT_STRETCH_SEMI_EXPANDED;
+ } else if (p_stretch < 144) {
+ return DWRITE_FONT_STRETCH_EXPANDED;
+ } else if (p_stretch < 162) {
+ return DWRITE_FONT_STRETCH_EXTRA_EXPANDED;
+ } else {
+ return DWRITE_FONT_STRETCH_ULTRA_EXPANDED;
+ }
+}
+
+Vector<String> OS_Windows::get_system_font_path_for_text(const String &p_font_name, const String &p_text, const String &p_locale, const String &p_script, int p_weight, int p_stretch, bool p_italic) const {
+ if (!dwrite2_init) {
+ return Vector<String>();
+ }
+
+ String font_name = _get_default_fontname(p_font_name);
+
+ bool rtl = TS->is_locale_right_to_left(p_locale);
+ Char16String text = p_text.utf16();
+ Char16String locale = p_locale.utf16();
+
+ ComAutoreleaseRef<IDWriteNumberSubstitution> number_substitution;
+ HRESULT hr = dwrite_factory->CreateNumberSubstitution(DWRITE_NUMBER_SUBSTITUTION_METHOD_NONE, reinterpret_cast<const wchar_t *>(locale.get_data()), true, &number_substitution.reference);
+ ERR_FAIL_COND_V(FAILED(hr) || number_substitution.is_null(), Vector<String>());
+
+ FallbackTextAnalysisSource fs = FallbackTextAnalysisSource(text, locale, rtl, number_substitution.reference);
+ UINT32 mapped_length = 0;
+ FLOAT scale = 0.0;
+ ComAutoreleaseRef<IDWriteFont> dwrite_font;
+ hr = system_font_fallback->MapCharacters(
+ &fs,
+ 0,
+ (UINT32)text.length(),
+ font_collection,
+ reinterpret_cast<const wchar_t *>(font_name.utf16().get_data()),
+ _weight_to_dw(p_weight),
+ p_italic ? DWRITE_FONT_STYLE_ITALIC : DWRITE_FONT_STYLE_NORMAL,
+ _stretch_to_dw(p_stretch),
+ &mapped_length,
+ &dwrite_font.reference,
+ &scale);
+
+ if (FAILED(hr) || dwrite_font.is_null()) {
+ return Vector<String>();
+ }
+
+ ComAutoreleaseRef<IDWriteFontFace> dwrite_face;
+ hr = dwrite_font->CreateFontFace(&dwrite_face.reference);
+ if (FAILED(hr) || dwrite_face.is_null()) {
+ return Vector<String>();
+ }
+
+ UINT32 number_of_files = 0;
+ hr = dwrite_face->GetFiles(&number_of_files, nullptr);
+ if (FAILED(hr)) {
+ return Vector<String>();
+ }
+ Vector<ComAutoreleaseRef<IDWriteFontFile>> files;
+ files.resize(number_of_files);
+ hr = dwrite_face->GetFiles(&number_of_files, (IDWriteFontFile **)files.ptrw());
+ if (FAILED(hr)) {
+ return Vector<String>();
+ }
+
+ Vector<String> ret;
+ 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;
+ }
+ String fpath = String::utf16((const char16_t *)&file_path[0]);
+
+ WIN32_FIND_DATAW d;
+ HANDLE fnd = FindFirstFileW((LPCWSTR)&file_path[0], &d);
+ if (fnd != INVALID_HANDLE_VALUE) {
+ String fname = String::utf16((const char16_t *)d.cFileName);
+ if (!fname.is_empty()) {
+ fpath = fpath.get_base_dir().path_join(fname);
+ }
+ FindClose(fnd);
+ }
+ ret.push_back(fpath);
+ }
+ return ret;
+}
+
+String OS_Windows::get_system_font_path(const String &p_font_name, int p_weight, int p_stretch, bool p_italic) const {
+ if (!dwrite_init) {
+ return String();
+ }
+
+ String font_name = _get_default_fontname(p_font_name);
UINT32 index = 0;
BOOL exists = false;
- font_collection->FindFamilyName((const WCHAR *)font_name.utf16().get_data(), &index, &exists);
- if (FAILED(hr)) {
+ HRESULT hr = font_collection->FindFamilyName((const WCHAR *)font_name.utf16().get_data(), &index, &exists);
+ if (FAILED(hr) || !exists) {
return String();
}
@@ -807,7 +1070,7 @@ String OS_Windows::get_system_font_path(const String &p_font_name, bool p_bold,
}
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);
+ hr = family->GetFirstMatchingFont(_weight_to_dw(p_weight), _stretch_to_dw(p_stretch), p_italic ? DWRITE_FONT_STYLE_ITALIC : DWRITE_FONT_STYLE_NORMAL, &dwrite_font.reference);
if (FAILED(hr) || dwrite_font.is_null()) {
return String();
}
@@ -849,7 +1112,19 @@ String OS_Windows::get_system_font_path(const String &p_font_name, bool p_bold,
if (FAILED(hr)) {
continue;
}
- return String::utf16((const char16_t *)&file_path[0]);
+ String fpath = String::utf16((const char16_t *)&file_path[0]);
+
+ WIN32_FIND_DATAW d;
+ HANDLE fnd = FindFirstFileW((LPCWSTR)&file_path[0], &d);
+ if (fnd != INVALID_HANDLE_VALUE) {
+ String fname = String::utf16((const char16_t *)d.cFileName);
+ if (!fname.is_empty()) {
+ fpath = fpath.get_base_dir().path_join(fname);
+ }
+ FindClose(fnd);
+ }
+
+ return fpath;
}
return String();
}
@@ -889,8 +1164,11 @@ bool OS_Windows::set_environment(const String &p_var, const String &p_value) con
String OS_Windows::get_stdin_string(bool p_block) {
if (p_block) {
- char buff[1024];
- return fgets(buff, 1024, stdin);
+ WCHAR buff[1024];
+ DWORD count = 0;
+ if (ReadConsoleW(GetStdHandle(STD_INPUT_HANDLE), buff, 1024, &count, nullptr)) {
+ return String::utf16((const char16_t *)buff, count);
+ }
}
return String();
@@ -1061,14 +1339,6 @@ uint64_t OS_Windows::get_embedded_pck_offset() const {
}
String OS_Windows::get_config_path() const {
- // The XDG Base Directory specification technically only applies on Linux/*BSD, but it doesn't hurt to support it on Windows as well.
- if (has_environment("XDG_CONFIG_HOME")) {
- if (get_environment("XDG_CONFIG_HOME").is_absolute_path()) {
- return get_environment("XDG_CONFIG_HOME").replace("\\", "/");
- } else {
- WARN_PRINT_ONCE("`XDG_CONFIG_HOME` is a relative path. Ignoring its value and falling back to `%APPDATA%` or `.` per the XDG Base Directory specification.");
- }
- }
if (has_environment("APPDATA")) {
return get_environment("APPDATA").replace("\\", "/");
}
@@ -1076,29 +1346,13 @@ String OS_Windows::get_config_path() const {
}
String OS_Windows::get_data_path() const {
- // The XDG Base Directory specification technically only applies on Linux/*BSD, but it doesn't hurt to support it on Windows as well.
- if (has_environment("XDG_DATA_HOME")) {
- if (get_environment("XDG_DATA_HOME").is_absolute_path()) {
- return get_environment("XDG_DATA_HOME").replace("\\", "/");
- } else {
- WARN_PRINT_ONCE("`XDG_DATA_HOME` is a relative path. Ignoring its value and falling back to `get_config_path()` per the XDG Base Directory specification.");
- }
- }
return get_config_path();
}
String OS_Windows::get_cache_path() const {
static String cache_path_cache;
if (cache_path_cache.is_empty()) {
- // The XDG Base Directory specification technically only applies on Linux/*BSD, but it doesn't hurt to support it on Windows as well.
- if (has_environment("XDG_CACHE_HOME")) {
- if (get_environment("XDG_CACHE_HOME").is_absolute_path()) {
- cache_path_cache = get_environment("XDG_CACHE_HOME").replace("\\", "/");
- } else {
- WARN_PRINT_ONCE("`XDG_CACHE_HOME` is a relative path. Ignoring its value and falling back to `%LOCALAPPDATA%\\cache`, `%TEMP%` or `get_config_path()` per the XDG Base Directory specification.");
- }
- }
- if (cache_path_cache.is_empty() && has_environment("LOCALAPPDATA")) {
+ if (has_environment("LOCALAPPDATA")) {
cache_path_cache = get_environment("LOCALAPPDATA").replace("\\", "/");
}
if (cache_path_cache.is_empty() && has_environment("TEMP")) {
@@ -1180,7 +1434,7 @@ String OS_Windows::get_unique_id() const {
bool OS_Windows::_check_internal_feature_support(const String &p_feature) {
if (p_feature == "system_fonts") {
- return true;
+ return dwrite_init;
}
if (p_feature == "pc") {
return true;
diff --git a/platform/windows/os_windows.h b/platform/windows/os_windows.h
index 6f89be699a..1db2b5880d 100644
--- a/platform/windows/os_windows.h
+++ b/platform/windows/os_windows.h
@@ -55,6 +55,8 @@
#include <stdio.h>
#define WIN32_LEAN_AND_MEAN
+#include <dwrite.h>
+#include <dwrite_2.h>
#include <windows.h>
#include <windowsx.h>
@@ -79,6 +81,9 @@ public:
_FORCE_INLINE_ bool is_valid() const { return reference != nullptr; }
_FORCE_INLINE_ bool is_null() const { return reference == nullptr; }
ComAutoreleaseRef() {}
+ ComAutoreleaseRef(T *p_ref) {
+ reference = p_ref;
+ }
~ComAutoreleaseRef() {
if (reference != nullptr) {
reference->Release();
@@ -114,6 +119,18 @@ class OS_Windows : public OS {
HWND main_window;
+ IDWriteFactory *dwrite_factory = nullptr;
+ IDWriteFactory2 *dwrite_factory2 = nullptr;
+ IDWriteFontCollection *font_collection = nullptr;
+ IDWriteFontFallback *system_font_fallback = nullptr;
+
+ bool dwrite_init = false;
+ bool dwrite2_init = false;
+
+ String _get_default_fontname(const String &p_font_name) const;
+ DWRITE_FONT_WEIGHT _weight_to_dw(int p_weight) const;
+ DWRITE_FONT_STRETCH _stretch_to_dw(int p_stretch) const;
+
// functions used by main to initialize/deinitialize the OS
protected:
virtual void initialize() override;
@@ -172,7 +189,8 @@ public:
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_system_font_path(const String &p_font_name, int p_weight = 400, int p_stretch = 100, bool p_italic = false) const override;
+ virtual Vector<String> get_system_font_path_for_text(const String &p_font_name, const String &p_text, const String &p_locale = String(), const String &p_script = String(), int p_weight = 400, int p_stretch = 100, bool p_italic = false) const override;
virtual String get_executable_path() const override;
diff --git a/platform/windows/platform_config.h b/platform/windows/platform_config.h
index 8e80f8cacb..7f0042d76f 100644
--- a/platform/windows/platform_config.h
+++ b/platform/windows/platform_config.h
@@ -30,4 +30,4 @@
#include <malloc.h>
-#define OPENGL_INCLUDE_H "thirdparty/glad/glad/glad.h"
+#define OPENGL_INCLUDE_H "thirdparty/glad/glad/gl.h"
diff --git a/platform/windows/platform_windows_builders.py b/platform/windows/platform_windows_builders.py
index 33ca2e8ffa..b522a75a9c 100644
--- a/platform/windows/platform_windows_builders.py
+++ b/platform/windows/platform_windows_builders.py
@@ -4,18 +4,15 @@ All such functions are invoked in a subprocess on Windows to prevent build flaki
"""
import os
+from detect import get_mingw_bin_prefix
from platform_methods import subprocess_main
def make_debug_mingw(target, source, env):
- mingw_prefix = ""
- if env["arch"] == "x86_32":
- mingw_prefix = env["mingw_prefix_32"]
- else:
- mingw_prefix = env["mingw_prefix_64"]
- os.system(mingw_prefix + "objcopy --only-keep-debug {0} {0}.debugsymbols".format(target[0]))
- os.system(mingw_prefix + "strip --strip-debug --strip-unneeded {0}".format(target[0]))
- os.system(mingw_prefix + "objcopy --add-gnu-debuglink={0}.debugsymbols {0}".format(target[0]))
+ mingw_bin_prefix = get_mingw_bin_prefix(env["mingw_prefix"], env["arch"])
+ os.system(mingw_bin_prefix + "objcopy --only-keep-debug {0} {0}.debugsymbols".format(target[0]))
+ os.system(mingw_bin_prefix + "strip --strip-debug --strip-unneeded {0}".format(target[0]))
+ os.system(mingw_bin_prefix + "objcopy --add-gnu-debuglink={0}.debugsymbols {0}".format(target[0]))
if __name__ == "__main__":
diff --git a/scene/2d/audio_stream_player_2d.cpp b/scene/2d/audio_stream_player_2d.cpp
index 9ac3083718..2ded209180 100644
--- a/scene/2d/audio_stream_player_2d.cpp
+++ b/scene/2d/audio_stream_player_2d.cpp
@@ -284,6 +284,9 @@ bool AudioStreamPlayer2D::is_playing() const {
return true;
}
}
+ if (setplay.get() >= 0) {
+ return true; // play() has been called this frame, but no playback exists just yet.
+ }
return false;
}
diff --git a/scene/2d/audio_stream_player_2d.h b/scene/2d/audio_stream_player_2d.h
index 616d7fdb60..5bc9083488 100644
--- a/scene/2d/audio_stream_player_2d.h
+++ b/scene/2d/audio_stream_player_2d.h
@@ -82,7 +82,7 @@ private:
float attenuation = 1.0;
float panning_strength = 1.0f;
- float cached_global_panning_strength = 1.0f;
+ float cached_global_panning_strength = 0.5f;
protected:
void _validate_property(PropertyInfo &p_property) const;
diff --git a/scene/2d/back_buffer_copy.cpp b/scene/2d/back_buffer_copy.cpp
index aa4ae01fd9..9c332123e3 100644
--- a/scene/2d/back_buffer_copy.cpp
+++ b/scene/2d/back_buffer_copy.cpp
@@ -71,12 +71,19 @@ Rect2 BackBufferCopy::get_rect() const {
void BackBufferCopy::set_copy_mode(CopyMode p_mode) {
copy_mode = p_mode;
_update_copy_mode();
+ notify_property_list_changed();
}
BackBufferCopy::CopyMode BackBufferCopy::get_copy_mode() const {
return copy_mode;
}
+void BackBufferCopy::_validate_property(PropertyInfo &p_property) const {
+ if (copy_mode != COPY_MODE_RECT && p_property.name == "rect") {
+ p_property.usage = PROPERTY_USAGE_NO_EDITOR;
+ }
+}
+
void BackBufferCopy::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_rect", "rect"), &BackBufferCopy::set_rect);
ClassDB::bind_method(D_METHOD("get_rect"), &BackBufferCopy::get_rect);
diff --git a/scene/2d/back_buffer_copy.h b/scene/2d/back_buffer_copy.h
index 1f2d5810b0..caacbc83c6 100644
--- a/scene/2d/back_buffer_copy.h
+++ b/scene/2d/back_buffer_copy.h
@@ -51,6 +51,7 @@ private:
protected:
static void _bind_methods();
+ void _validate_property(PropertyInfo &p_property) const;
public:
#ifdef TOOLS_ENABLED
diff --git a/scene/2d/camera_2d.cpp b/scene/2d/camera_2d.cpp
index 4b31bbddac..229625ad6d 100644
--- a/scene/2d/camera_2d.cpp
+++ b/scene/2d/camera_2d.cpp
@@ -39,8 +39,11 @@ void Camera2D::_update_scroll() {
}
if (Engine::get_singleton()->is_editor_hint()) {
- queue_redraw(); //will just be drawn
- return;
+ queue_redraw();
+ // Only set viewport transform when not bound to the main viewport.
+ if (get_viewport() == get_tree()->get_edited_scene_root()->get_viewport()) {
+ return;
+ }
}
if (!viewport) {
diff --git a/scene/2d/canvas_group.cpp b/scene/2d/canvas_group.cpp
index d4182f85a7..0ada703837 100644
--- a/scene/2d/canvas_group.cpp
+++ b/scene/2d/canvas_group.cpp
@@ -47,7 +47,7 @@ void CanvasGroup::set_clear_margin(real_t p_clear_margin) {
ERR_FAIL_COND(p_clear_margin < 0.0);
clear_margin = p_clear_margin;
- RS::get_singleton()->canvas_item_set_canvas_group_mode(get_canvas_item(), RS::CANVAS_GROUP_MODE_TRANSPARENT, clear_margin, true, clear_margin, use_mipmaps);
+ RS::get_singleton()->canvas_item_set_canvas_group_mode(get_canvas_item(), RS::CANVAS_GROUP_MODE_TRANSPARENT, clear_margin, true, fit_margin, use_mipmaps);
queue_redraw();
}
diff --git a/scene/2d/gpu_particles_2d.cpp b/scene/2d/gpu_particles_2d.cpp
index e18f2bd1a1..ccbc080768 100644
--- a/scene/2d/gpu_particles_2d.cpp
+++ b/scene/2d/gpu_particles_2d.cpp
@@ -299,10 +299,6 @@ bool GPUParticles2D::get_interpolate() const {
PackedStringArray GPUParticles2D::get_configuration_warnings() const {
PackedStringArray 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."));
- }
-
if (process_material.is_null()) {
warnings.push_back(RTR("A material to process the particles is not assigned, so no behavior is imprinted."));
} else {
@@ -629,6 +625,8 @@ void GPUParticles2D::_bind_methods() {
ADD_PROPERTY_DEFAULT("emitting", true); // Workaround for doctool in headless mode, as dummy rasterizer always returns false.
ADD_PROPERTY(PropertyInfo(Variant::INT, "amount", PROPERTY_HINT_RANGE, "1,1000000,1,exp"), "set_amount", "get_amount");
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "sub_emitter", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "GPUParticles2D"), "set_sub_emitter", "get_sub_emitter");
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "process_material", PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial,ParticleProcessMaterial"), "set_process_material", "get_process_material");
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture", "get_texture");
ADD_GROUP("Time", "");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "lifetime", PROPERTY_HINT_RANGE, "0.01,600.0,0.01,or_greater,suffix:s"), "set_lifetime", "get_lifetime");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "one_shot"), "set_one_shot", "get_one_shot");
@@ -650,10 +648,6 @@ void GPUParticles2D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "trail_lifetime", PROPERTY_HINT_RANGE, "0.01,10,0.01,or_greater,suffix:s"), "set_trail_lifetime", "get_trail_lifetime");
ADD_PROPERTY(PropertyInfo(Variant::INT, "trail_sections", PROPERTY_HINT_RANGE, "2,128,1"), "set_trail_sections", "get_trail_sections");
ADD_PROPERTY(PropertyInfo(Variant::INT, "trail_section_subdivisions", PROPERTY_HINT_RANGE, "1,1024,1"), "set_trail_section_subdivisions", "get_trail_section_subdivisions");
- ADD_GROUP("Process Material", "process_");
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "process_material", PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial,ParticleProcessMaterial"), "set_process_material", "get_process_material");
- ADD_GROUP("Textures", "");
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture", "get_texture");
BIND_ENUM_CONSTANT(DRAW_ORDER_INDEX);
BIND_ENUM_CONSTANT(DRAW_ORDER_LIFETIME);
diff --git a/scene/2d/gpu_particles_2d.h b/scene/2d/gpu_particles_2d.h
index 7fba174357..94555e0bb0 100644
--- a/scene/2d/gpu_particles_2d.h
+++ b/scene/2d/gpu_particles_2d.h
@@ -64,7 +64,7 @@ private:
#endif
Ref<Material> process_material;
- DrawOrder draw_order;
+ DrawOrder draw_order = DRAW_ORDER_LIFETIME;
Ref<Texture2D> texture;
diff --git a/scene/2d/joint_2d.cpp b/scene/2d/joint_2d.cpp
index 6000508f36..3ec744ff8e 100644
--- a/scene/2d/joint_2d.cpp
+++ b/scene/2d/joint_2d.cpp
@@ -112,7 +112,7 @@ void Joint2D::_update_joint(bool p_only_free) {
ERR_FAIL_COND_MSG(!joint.is_valid(), "Failed to configure the joint.");
- PhysicsServer2D::get_singleton()->get_singleton()->joint_set_param(joint, PhysicsServer2D::JOINT_PARAM_BIAS, bias);
+ PhysicsServer2D::get_singleton()->joint_set_param(joint, PhysicsServer2D::JOINT_PARAM_BIAS, bias);
ba = body_a->get_rid();
bb = body_b->get_rid();
@@ -133,7 +133,13 @@ void Joint2D::set_node_a(const NodePath &p_node_a) {
}
a = p_node_a;
- _update_joint();
+ if (Engine::get_singleton()->is_editor_hint()) {
+ // When in editor, the setter may be called as a result of node rename.
+ // It happens before the node actually changes its name, which triggers false warning.
+ callable_mp(this, &Joint2D::_update_joint).call_deferred();
+ } else {
+ _update_joint();
+ }
}
NodePath Joint2D::get_node_a() const {
@@ -150,7 +156,11 @@ void Joint2D::set_node_b(const NodePath &p_node_b) {
}
b = p_node_b;
- _update_joint();
+ if (Engine::get_singleton()->is_editor_hint()) {
+ callable_mp(this, &Joint2D::_update_joint).call_deferred();
+ } else {
+ _update_joint();
+ }
}
NodePath Joint2D::get_node_b() const {
@@ -178,7 +188,7 @@ void Joint2D::_notification(int p_what) {
void Joint2D::set_bias(real_t p_bias) {
bias = p_bias;
if (joint.is_valid()) {
- PhysicsServer2D::get_singleton()->get_singleton()->joint_set_param(joint, PhysicsServer2D::JOINT_PARAM_BIAS, bias);
+ PhysicsServer2D::get_singleton()->joint_set_param(joint, PhysicsServer2D::JOINT_PARAM_BIAS, bias);
}
}
diff --git a/scene/2d/multimesh_instance_2d.cpp b/scene/2d/multimesh_instance_2d.cpp
index 68d529fd32..fa72fc5b8b 100644
--- a/scene/2d/multimesh_instance_2d.cpp
+++ b/scene/2d/multimesh_instance_2d.cpp
@@ -30,6 +30,7 @@
#include "multimesh_instance_2d.h"
+#include "core/core_string_names.h"
#include "scene/scene_string_names.h"
void MultiMeshInstance2D::_notification(int p_what) {
@@ -60,7 +61,16 @@ void MultiMeshInstance2D::_bind_methods() {
}
void MultiMeshInstance2D::set_multimesh(const Ref<MultiMesh> &p_multimesh) {
+ // Cleanup previous connection if any.
+ if (multimesh.is_valid()) {
+ multimesh->disconnect(CoreStringNames::get_singleton()->changed, callable_mp((CanvasItem *)this, &CanvasItem::queue_redraw));
+ }
multimesh = p_multimesh;
+
+ // Connect to the multimesh so the AABB can update when instance transforms are changed.
+ if (multimesh.is_valid()) {
+ multimesh->connect(CoreStringNames::get_singleton()->changed, callable_mp((CanvasItem *)this, &CanvasItem::queue_redraw));
+ }
queue_redraw();
}
diff --git a/scene/2d/navigation_agent_2d.cpp b/scene/2d/navigation_agent_2d.cpp
index 1a62c9bb6c..62afe0d89b 100644
--- a/scene/2d/navigation_agent_2d.cpp
+++ b/scene/2d/navigation_agent_2d.cpp
@@ -70,6 +70,9 @@ void NavigationAgent2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_navigation_layer_value", "layer_number", "value"), &NavigationAgent2D::set_navigation_layer_value);
ClassDB::bind_method(D_METHOD("get_navigation_layer_value", "layer_number"), &NavigationAgent2D::get_navigation_layer_value);
+ ClassDB::bind_method(D_METHOD("set_path_metadata_flags", "flags"), &NavigationAgent2D::set_path_metadata_flags);
+ ClassDB::bind_method(D_METHOD("get_path_metadata_flags"), &NavigationAgent2D::get_path_metadata_flags);
+
ClassDB::bind_method(D_METHOD("set_navigation_map", "navigation_map"), &NavigationAgent2D::set_navigation_map);
ClassDB::bind_method(D_METHOD("get_navigation_map"), &NavigationAgent2D::get_navigation_map);
@@ -79,8 +82,9 @@ void NavigationAgent2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_next_location"), &NavigationAgent2D::get_next_location);
ClassDB::bind_method(D_METHOD("distance_to_target"), &NavigationAgent2D::distance_to_target);
ClassDB::bind_method(D_METHOD("set_velocity", "velocity"), &NavigationAgent2D::set_velocity);
- ClassDB::bind_method(D_METHOD("get_nav_path"), &NavigationAgent2D::get_nav_path);
- ClassDB::bind_method(D_METHOD("get_nav_path_index"), &NavigationAgent2D::get_nav_path_index);
+ ClassDB::bind_method(D_METHOD("get_current_navigation_result"), &NavigationAgent2D::get_current_navigation_result);
+ ClassDB::bind_method(D_METHOD("get_current_navigation_path"), &NavigationAgent2D::get_current_navigation_path);
+ ClassDB::bind_method(D_METHOD("get_current_navigation_path_index"), &NavigationAgent2D::get_current_navigation_path_index);
ClassDB::bind_method(D_METHOD("is_target_reached"), &NavigationAgent2D::is_target_reached);
ClassDB::bind_method(D_METHOD("is_target_reachable"), &NavigationAgent2D::is_target_reachable);
ClassDB::bind_method(D_METHOD("is_navigation_finished"), &NavigationAgent2D::is_navigation_finished);
@@ -94,6 +98,7 @@ void NavigationAgent2D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "target_desired_distance", PROPERTY_HINT_RANGE, "0.1,100,0.01,suffix:px"), "set_target_desired_distance", "get_target_desired_distance");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "path_max_distance", PROPERTY_HINT_RANGE, "10,100,1,suffix:px"), "set_path_max_distance", "get_path_max_distance");
ADD_PROPERTY(PropertyInfo(Variant::INT, "navigation_layers", PROPERTY_HINT_LAYERS_2D_NAVIGATION), "set_navigation_layers", "get_navigation_layers");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "path_metadata_flags", PROPERTY_HINT_FLAGS, "Include Types,Include RIDs,Include Owners"), "set_path_metadata_flags", "get_path_metadata_flags");
ADD_GROUP("Avoidance", "");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "avoidance_enabled"), "set_avoidance_enabled", "get_avoidance_enabled");
@@ -105,6 +110,8 @@ void NavigationAgent2D::_bind_methods() {
ADD_SIGNAL(MethodInfo("path_changed"));
ADD_SIGNAL(MethodInfo("target_reached"));
+ ADD_SIGNAL(MethodInfo("waypoint_reached", PropertyInfo(Variant::DICTIONARY, "details")));
+ ADD_SIGNAL(MethodInfo("link_reached", PropertyInfo(Variant::DICTIONARY, "details")));
ADD_SIGNAL(MethodInfo("navigation_finished"));
ADD_SIGNAL(MethodInfo("velocity_computed", PropertyInfo(Variant::VECTOR2, "safe_velocity")));
}
@@ -161,7 +168,7 @@ void NavigationAgent2D::_notification(int p_what) {
} break;
case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
- if (agent_parent) {
+ if (agent_parent && target_position_submitted) {
if (avoidance_enabled) {
// agent_position on NavigationServer is avoidance only and has nothing to do with pathfinding
// no point in flooding NavigationServer queue with agent position updates that get send to the void if avoidance is not used
@@ -197,9 +204,9 @@ NavigationAgent2D::~NavigationAgent2D() {
void NavigationAgent2D::set_avoidance_enabled(bool p_enabled) {
avoidance_enabled = p_enabled;
if (avoidance_enabled) {
- NavigationServer2D::get_singleton()->agent_set_callback(agent, this, "_avoidance_done");
+ NavigationServer2D::get_singleton()->agent_set_callback(agent, get_instance_id(), "_avoidance_done");
} else {
- NavigationServer2D::get_singleton()->agent_set_callback(agent, nullptr, "_avoidance_done");
+ NavigationServer2D::get_singleton()->agent_set_callback(agent, ObjectID(), "_avoidance_done");
}
}
@@ -209,7 +216,7 @@ bool NavigationAgent2D::get_avoidance_enabled() const {
void NavigationAgent2D::set_agent_parent(Node *p_agent_parent) {
// remove agent from any avoidance map before changing parent or there will be leftovers on the RVO map
- NavigationServer2D::get_singleton()->agent_set_callback(agent, nullptr, "_avoidance_done");
+ NavigationServer2D::get_singleton()->agent_set_callback(agent, ObjectID(), "_avoidance_done");
if (Object::cast_to<Node2D>(p_agent_parent) != nullptr) {
// place agent on navigation map first or else the RVO agent callback creation fails silently later
agent_parent = Object::cast_to<Node2D>(p_agent_parent);
@@ -256,6 +263,14 @@ bool NavigationAgent2D::get_navigation_layer_value(int p_layer_number) const {
return get_navigation_layers() & (1 << (p_layer_number - 1));
}
+void NavigationAgent2D::set_path_metadata_flags(BitField<NavigationPathQueryParameters2D::PathMetadataFlags> p_path_metadata_flags) {
+ if (path_metadata_flags == p_path_metadata_flags) {
+ return;
+ }
+
+ path_metadata_flags = p_path_metadata_flags;
+}
+
void NavigationAgent2D::set_navigation_map(RID p_navigation_map) {
map_override = p_navigation_map;
NavigationServer2D::get_singleton()->agent_set_map(agent, map_override);
@@ -314,6 +329,7 @@ real_t NavigationAgent2D::get_path_max_distance() {
void NavigationAgent2D::set_target_location(Vector2 p_location) {
target_location = p_location;
+ target_position_submitted = true;
_request_repath();
}
@@ -329,14 +345,10 @@ Vector2 NavigationAgent2D::get_next_location() {
ERR_FAIL_COND_V_MSG(agent_parent == nullptr, Vector2(), "The agent has no parent.");
return agent_parent->get_global_position();
} else {
- return navigation_path[nav_path_index];
+ return navigation_path[navigation_path_index];
}
}
-const Vector<Vector2> &NavigationAgent2D::get_nav_path() const {
- return navigation_result->get_path();
-}
-
real_t NavigationAgent2D::distance_to_target() const {
ERR_FAIL_COND_V_MSG(agent_parent == nullptr, 0.0, "The agent has no parent.");
return agent_parent->get_global_position().distance_to(target_location);
@@ -402,6 +414,9 @@ void NavigationAgent2D::update_navigation() {
if (!agent_parent->is_inside_tree()) {
return;
}
+ if (!target_position_submitted) {
+ return;
+ }
if (update_frame_id == Engine::get_singleton()->get_physics_frames()) {
return;
}
@@ -418,12 +433,12 @@ void NavigationAgent2D::update_navigation() {
reload_path = true;
} else {
// Check if too far from the navigation path
- if (nav_path_index > 0) {
+ if (navigation_path_index > 0) {
const Vector<Vector2> &navigation_path = navigation_result->get_path();
Vector2 segment[2];
- segment[0] = navigation_path[nav_path_index - 1];
- segment[1] = navigation_path[nav_path_index];
+ segment[0] = navigation_path[navigation_path_index - 1];
+ segment[1] = navigation_path[navigation_path_index];
Vector2 p = Geometry2D::get_closest_point_to_segment(origin, segment);
if (origin.distance_to(p) >= path_max_distance) {
// To faraway, reload path
@@ -436,6 +451,7 @@ void NavigationAgent2D::update_navigation() {
navigation_query->set_start_position(origin);
navigation_query->set_target_position(target_location);
navigation_query->set_navigation_layers(navigation_layers);
+ navigation_query->set_metadata_flags(path_metadata_flags);
if (map_override.is_valid()) {
navigation_query->set_map(map_override);
@@ -445,7 +461,7 @@ void NavigationAgent2D::update_navigation() {
NavigationServer2D::get_singleton()->query_path(navigation_query, navigation_result);
navigation_finished = false;
- nav_path_index = 0;
+ navigation_path_index = 0;
emit_signal(SNAME("path_changed"));
}
@@ -457,12 +473,57 @@ void NavigationAgent2D::update_navigation() {
if (navigation_finished == false) {
// Advances to the next far away location.
const Vector<Vector2> &navigation_path = navigation_result->get_path();
- while (origin.distance_to(navigation_path[nav_path_index]) < path_desired_distance) {
- nav_path_index += 1;
- if (nav_path_index == navigation_path.size()) {
+ const Vector<int32_t> &navigation_path_types = navigation_result->get_path_types();
+ const TypedArray<RID> &navigation_path_rids = navigation_result->get_path_rids();
+ const Vector<int64_t> &navigation_path_owners = navigation_result->get_path_owner_ids();
+
+ while (origin.distance_to(navigation_path[navigation_path_index]) < path_desired_distance) {
+ Dictionary details;
+
+ const Vector2 waypoint = navigation_path[navigation_path_index];
+ details[SNAME("location")] = waypoint;
+
+ int waypoint_type = -1;
+ if (path_metadata_flags.has_flag(NavigationPathQueryParameters2D::PathMetadataFlags::PATH_METADATA_INCLUDE_TYPES)) {
+ const NavigationPathQueryResult2D::PathSegmentType type = NavigationPathQueryResult2D::PathSegmentType(navigation_path_types[navigation_path_index]);
+
+ details[SNAME("type")] = type;
+ waypoint_type = type;
+ }
+
+ if (path_metadata_flags.has_flag(NavigationPathQueryParameters2D::PathMetadataFlags::PATH_METADATA_INCLUDE_RIDS)) {
+ details[SNAME("rid")] = navigation_path_rids[navigation_path_index];
+ }
+
+ if (path_metadata_flags.has_flag(NavigationPathQueryParameters2D::PathMetadataFlags::PATH_METADATA_INCLUDE_OWNERS)) {
+ const ObjectID waypoint_owner_id = ObjectID(navigation_path_owners[navigation_path_index]);
+
+ // Get a reference to the owning object.
+ Object *owner = nullptr;
+ if (waypoint_owner_id.is_valid()) {
+ owner = ObjectDB::get_instance(waypoint_owner_id);
+ }
+
+ details[SNAME("owner")] = owner;
+ }
+
+ // Emit a signal for the waypoint
+ emit_signal(SNAME("waypoint_reached"), details);
+
+ // Emit a signal if we've reached a navigation link
+ if (waypoint_type == NavigationPathQueryResult2D::PATH_SEGMENT_TYPE_LINK) {
+ emit_signal(SNAME("link_reached"), details);
+ }
+
+ // Move to the next waypoint on the list
+ navigation_path_index += 1;
+
+ // Check to see if we've finished our route
+ if (navigation_path_index == navigation_path.size()) {
_check_distance_to_target();
- nav_path_index -= 1;
+ navigation_path_index -= 1;
navigation_finished = true;
+ target_position_submitted = false;
emit_signal(SNAME("navigation_finished"));
break;
}
diff --git a/scene/2d/navigation_agent_2d.h b/scene/2d/navigation_agent_2d.h
index 5abd3c0317..439192cce7 100644
--- a/scene/2d/navigation_agent_2d.h
+++ b/scene/2d/navigation_agent_2d.h
@@ -32,10 +32,10 @@
#define NAVIGATION_AGENT_2D_H
#include "scene/main/node.h"
+#include "servers/navigation/navigation_path_query_parameters_2d.h"
+#include "servers/navigation/navigation_path_query_result_2d.h"
class Node2D;
-class NavigationPathQueryParameters2D;
-class NavigationPathQueryResult2D;
class NavigationAgent2D : public Node {
GDCLASS(NavigationAgent2D, Node);
@@ -48,6 +48,7 @@ class NavigationAgent2D : public Node {
bool avoidance_enabled = false;
uint32_t navigation_layers = 1;
+ BitField<NavigationPathQueryParameters2D::PathMetadataFlags> path_metadata_flags = NavigationPathQueryParameters2D::PathMetadataFlags::PATH_METADATA_INCLUDE_ALL;
real_t path_desired_distance = 1.0;
real_t target_desired_distance = 1.0;
@@ -60,9 +61,10 @@ class NavigationAgent2D : public Node {
real_t path_max_distance = 3.0;
Vector2 target_location;
+ bool target_position_submitted = false;
Ref<NavigationPathQueryParameters2D> navigation_query;
Ref<NavigationPathQueryResult2D> navigation_result;
- int nav_path_index = 0;
+ int navigation_path_index = 0;
bool velocity_submitted = false;
Vector2 prev_safe_velocity;
/// The submitted target velocity
@@ -95,6 +97,11 @@ public:
void set_navigation_layer_value(int p_layer_number, bool p_value);
bool get_navigation_layer_value(int p_layer_number) const;
+ void set_path_metadata_flags(BitField<NavigationPathQueryParameters2D::PathMetadataFlags> p_flags);
+ BitField<NavigationPathQueryParameters2D::PathMetadataFlags> get_path_metadata_flags() const {
+ return path_metadata_flags;
+ }
+
void set_navigation_map(RID p_navigation_map);
RID get_navigation_map() const;
@@ -141,10 +148,14 @@ public:
Vector2 get_next_location();
- const Vector<Vector2> &get_nav_path() const;
-
- int get_nav_path_index() const {
- return nav_path_index;
+ Ref<NavigationPathQueryResult2D> get_current_navigation_result() const {
+ return navigation_result;
+ }
+ const Vector<Vector2> &get_current_navigation_path() const {
+ return navigation_result->get_path();
+ }
+ int get_current_navigation_path_index() const {
+ return navigation_path_index;
}
real_t distance_to_target() const;
diff --git a/scene/2d/navigation_link_2d.cpp b/scene/2d/navigation_link_2d.cpp
index 3f7e10eaea..d639e1cc89 100644
--- a/scene/2d/navigation_link_2d.cpp
+++ b/scene/2d/navigation_link_2d.cpp
@@ -279,6 +279,8 @@ PackedStringArray NavigationLink2D::get_configuration_warnings() const {
NavigationLink2D::NavigationLink2D() {
link = NavigationServer2D::get_singleton()->link_create();
+ NavigationServer2D::get_singleton()->link_set_owner_id(link, get_instance_id());
+
set_notify_transform(true);
}
diff --git a/scene/2d/navigation_link_2d.h b/scene/2d/navigation_link_2d.h
index 2a5092216d..9d36f80dd6 100644
--- a/scene/2d/navigation_link_2d.h
+++ b/scene/2d/navigation_link_2d.h
@@ -37,11 +37,11 @@ class NavigationLink2D : public Node2D {
GDCLASS(NavigationLink2D, Node2D);
bool enabled = true;
- RID link = RID();
+ RID link;
bool bidirectional = true;
uint32_t navigation_layers = 1;
- Vector2 end_location = Vector2();
- Vector2 start_location = Vector2();
+ Vector2 end_location;
+ Vector2 start_location;
real_t enter_cost = 0.0;
real_t travel_cost = 1.0;
diff --git a/scene/2d/navigation_region_2d.cpp b/scene/2d/navigation_region_2d.cpp
index 6e8ecb13b1..675ef7c780 100644
--- a/scene/2d/navigation_region_2d.cpp
+++ b/scene/2d/navigation_region_2d.cpp
@@ -31,331 +31,10 @@
#include "navigation_region_2d.h"
#include "core/core_string_names.h"
-#include "core/math/geometry_2d.h"
-#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"
-
-#ifdef TOOLS_ENABLED
-Rect2 NavigationPolygon::_edit_get_rect() const {
- if (rect_cache_dirty) {
- item_rect = Rect2();
- bool first = true;
-
- for (int i = 0; i < outlines.size(); i++) {
- const Vector<Vector2> &outline = outlines[i];
- const int outline_size = outline.size();
- if (outline_size < 3) {
- continue;
- }
- const Vector2 *p = outline.ptr();
- for (int j = 0; j < outline_size; j++) {
- if (first) {
- item_rect = Rect2(p[j], Vector2(0, 0));
- first = false;
- } else {
- item_rect.expand_to(p[j]);
- }
- }
- }
-
- rect_cache_dirty = false;
- }
- return item_rect;
-}
-
-bool NavigationPolygon::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const {
- for (int i = 0; i < outlines.size(); i++) {
- const Vector<Vector2> &outline = outlines[i];
- const int outline_size = outline.size();
- if (outline_size < 3) {
- continue;
- }
- if (Geometry2D::is_point_in_polygon(p_point, Variant(outline))) {
- return true;
- }
- }
- return false;
-}
-#endif
-
-void NavigationPolygon::set_vertices(const Vector<Vector2> &p_vertices) {
- {
- MutexLock lock(navmesh_generation);
- navmesh.unref();
- }
- vertices = p_vertices;
- rect_cache_dirty = true;
-}
-
-Vector<Vector2> NavigationPolygon::get_vertices() const {
- return vertices;
-}
-
-void NavigationPolygon::_set_polygons(const TypedArray<Vector<int32_t>> &p_array) {
- {
- MutexLock lock(navmesh_generation);
- navmesh.unref();
- }
- polygons.resize(p_array.size());
- for (int i = 0; i < p_array.size(); i++) {
- polygons.write[i].indices = p_array[i];
- }
-}
-
-TypedArray<Vector<int32_t>> NavigationPolygon::_get_polygons() const {
- TypedArray<Vector<int32_t>> ret;
- ret.resize(polygons.size());
- for (int i = 0; i < ret.size(); i++) {
- ret[i] = polygons[i].indices;
- }
-
- return ret;
-}
-
-void NavigationPolygon::_set_outlines(const TypedArray<Vector<Vector2>> &p_array) {
- outlines.resize(p_array.size());
- for (int i = 0; i < p_array.size(); i++) {
- outlines.write[i] = p_array[i];
- }
- rect_cache_dirty = true;
-}
-
-TypedArray<Vector<Vector2>> NavigationPolygon::_get_outlines() const {
- TypedArray<Vector<Vector2>> ret;
- ret.resize(outlines.size());
- for (int i = 0; i < ret.size(); i++) {
- ret[i] = outlines[i];
- }
-
- return ret;
-}
-
-void NavigationPolygon::add_polygon(const Vector<int> &p_polygon) {
- Polygon polygon;
- polygon.indices = p_polygon;
- polygons.push_back(polygon);
- {
- MutexLock lock(navmesh_generation);
- navmesh.unref();
- }
-}
-
-void NavigationPolygon::add_outline_at_index(const Vector<Vector2> &p_outline, int p_index) {
- outlines.insert(p_index, p_outline);
- rect_cache_dirty = true;
-}
-
-int NavigationPolygon::get_polygon_count() const {
- return polygons.size();
-}
-
-Vector<int> NavigationPolygon::get_polygon(int p_idx) {
- ERR_FAIL_INDEX_V(p_idx, polygons.size(), Vector<int>());
- return polygons[p_idx].indices;
-}
-
-void NavigationPolygon::clear_polygons() {
- polygons.clear();
- {
- MutexLock lock(navmesh_generation);
- navmesh.unref();
- }
-}
-
-Ref<NavigationMesh> NavigationPolygon::get_mesh() {
- MutexLock lock(navmesh_generation);
-
- if (navmesh.is_null()) {
- navmesh.instantiate();
- Vector<Vector3> verts;
- {
- verts.resize(get_vertices().size());
- Vector3 *w = verts.ptrw();
-
- const Vector2 *r = get_vertices().ptr();
-
- for (int i(0); i < get_vertices().size(); i++) {
- w[i] = Vector3(r[i].x, 0.0, r[i].y);
- }
- }
- navmesh->set_vertices(verts);
-
- for (int i(0); i < get_polygon_count(); i++) {
- navmesh->add_polygon(get_polygon(i));
- }
- }
-
- return navmesh;
-}
-
-void NavigationPolygon::add_outline(const Vector<Vector2> &p_outline) {
- outlines.push_back(p_outline);
- rect_cache_dirty = true;
-}
-
-int NavigationPolygon::get_outline_count() const {
- return outlines.size();
-}
-
-void NavigationPolygon::set_outline(int p_idx, const Vector<Vector2> &p_outline) {
- ERR_FAIL_INDEX(p_idx, outlines.size());
- outlines.write[p_idx] = p_outline;
- rect_cache_dirty = true;
-}
-
-void NavigationPolygon::remove_outline(int p_idx) {
- ERR_FAIL_INDEX(p_idx, outlines.size());
- outlines.remove_at(p_idx);
- rect_cache_dirty = true;
-}
-
-Vector<Vector2> NavigationPolygon::get_outline(int p_idx) const {
- ERR_FAIL_INDEX_V(p_idx, outlines.size(), Vector<Vector2>());
- return outlines[p_idx];
-}
-
-void NavigationPolygon::clear_outlines() {
- outlines.clear();
- rect_cache_dirty = true;
-}
-
-void NavigationPolygon::make_polygons_from_outlines() {
- {
- MutexLock lock(navmesh_generation);
- navmesh.unref();
- }
- List<TPPLPoly> in_poly, out_poly;
-
- Vector2 outside_point(-1e10, -1e10);
-
- for (int i = 0; i < outlines.size(); i++) {
- Vector<Vector2> ol = outlines[i];
- int olsize = ol.size();
- if (olsize < 3) {
- continue;
- }
- const Vector2 *r = ol.ptr();
- for (int j = 0; j < olsize; j++) {
- outside_point.x = MAX(r[j].x, outside_point.x);
- outside_point.y = MAX(r[j].y, outside_point.y);
- }
- }
-
- outside_point += Vector2(0.7239784, 0.819238); //avoid precision issues
-
- for (int i = 0; i < outlines.size(); i++) {
- Vector<Vector2> ol = outlines[i];
- int olsize = ol.size();
- if (olsize < 3) {
- continue;
- }
- const Vector2 *r = ol.ptr();
-
- int interscount = 0;
- //test if this is an outer outline
- for (int k = 0; k < outlines.size(); k++) {
- if (i == k) {
- continue; //no self intersect
- }
-
- Vector<Vector2> ol2 = outlines[k];
- int olsize2 = ol2.size();
- if (olsize2 < 3) {
- continue;
- }
- const Vector2 *r2 = ol2.ptr();
-
- for (int l = 0; l < olsize2; l++) {
- if (Geometry2D::segment_intersects_segment(r[0], outside_point, r2[l], r2[(l + 1) % olsize2], nullptr)) {
- interscount++;
- }
- }
- }
-
- bool outer = (interscount % 2) == 0;
-
- TPPLPoly tp;
- tp.Init(olsize);
- for (int j = 0; j < olsize; j++) {
- tp[j] = r[j];
- }
-
- if (outer) {
- tp.SetOrientation(TPPL_ORIENTATION_CCW);
- } else {
- tp.SetOrientation(TPPL_ORIENTATION_CW);
- tp.SetHole(true);
- }
-
- in_poly.push_back(tp);
- }
-
- TPPLPartition tpart;
- if (tpart.ConvexPartition_HM(&in_poly, &out_poly) == 0) { //failed!
- ERR_PRINT("NavigationPolygon: Convex partition failed!");
- return;
- }
-
- polygons.clear();
- vertices.clear();
-
- HashMap<Vector2, int> points;
- for (List<TPPLPoly>::Element *I = out_poly.front(); I; I = I->next()) {
- TPPLPoly &tp = I->get();
-
- struct Polygon p;
-
- for (int64_t i = 0; i < tp.GetNumPoints(); i++) {
- HashMap<Vector2, int>::Iterator E = points.find(tp[i]);
- if (!E) {
- E = points.insert(tp[i], vertices.size());
- vertices.push_back(tp[i]);
- }
- p.indices.push_back(E->value);
- }
-
- polygons.push_back(p);
- }
-
- emit_signal(CoreStringNames::get_singleton()->changed);
-}
-
-void NavigationPolygon::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_vertices", "vertices"), &NavigationPolygon::set_vertices);
- ClassDB::bind_method(D_METHOD("get_vertices"), &NavigationPolygon::get_vertices);
-
- ClassDB::bind_method(D_METHOD("add_polygon", "polygon"), &NavigationPolygon::add_polygon);
- ClassDB::bind_method(D_METHOD("get_polygon_count"), &NavigationPolygon::get_polygon_count);
- ClassDB::bind_method(D_METHOD("get_polygon", "idx"), &NavigationPolygon::get_polygon);
- ClassDB::bind_method(D_METHOD("clear_polygons"), &NavigationPolygon::clear_polygons);
- ClassDB::bind_method(D_METHOD("get_mesh"), &NavigationPolygon::get_mesh);
-
- ClassDB::bind_method(D_METHOD("add_outline", "outline"), &NavigationPolygon::add_outline);
- ClassDB::bind_method(D_METHOD("add_outline_at_index", "outline", "index"), &NavigationPolygon::add_outline_at_index);
- ClassDB::bind_method(D_METHOD("get_outline_count"), &NavigationPolygon::get_outline_count);
- ClassDB::bind_method(D_METHOD("set_outline", "idx", "outline"), &NavigationPolygon::set_outline);
- ClassDB::bind_method(D_METHOD("get_outline", "idx"), &NavigationPolygon::get_outline);
- ClassDB::bind_method(D_METHOD("remove_outline", "idx"), &NavigationPolygon::remove_outline);
- ClassDB::bind_method(D_METHOD("clear_outlines"), &NavigationPolygon::clear_outlines);
- ClassDB::bind_method(D_METHOD("make_polygons_from_outlines"), &NavigationPolygon::make_polygons_from_outlines);
-
- ClassDB::bind_method(D_METHOD("_set_polygons", "polygons"), &NavigationPolygon::_set_polygons);
- ClassDB::bind_method(D_METHOD("_get_polygons"), &NavigationPolygon::_get_polygons);
-
- ClassDB::bind_method(D_METHOD("_set_outlines", "outlines"), &NavigationPolygon::_set_outlines);
- ClassDB::bind_method(D_METHOD("_get_outlines"), &NavigationPolygon::_get_outlines);
-
- ADD_PROPERTY(PropertyInfo(Variant::PACKED_VECTOR2_ARRAY, "vertices", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "set_vertices", "get_vertices");
- ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "polygons", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_polygons", "_get_polygons");
- ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "outlines", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_outlines", "_get_outlines");
-}
-
-/////////////////////////////
-
void NavigationRegion2D::set_enabled(bool p_enabled) {
if (enabled == p_enabled) {
return;
@@ -458,11 +137,11 @@ RID NavigationRegion2D::get_region_rid() const {
#ifdef TOOLS_ENABLED
Rect2 NavigationRegion2D::_edit_get_rect() const {
- return navpoly.is_valid() ? navpoly->_edit_get_rect() : Rect2();
+ return navigation_polygon.is_valid() ? navigation_polygon->_edit_get_rect() : Rect2();
}
bool NavigationRegion2D::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const {
- return navpoly.is_valid() ? navpoly->_edit_is_selected_on_click(p_point, p_tolerance) : false;
+ return navigation_polygon.is_valid() ? navigation_polygon->_edit_is_selected_on_click(p_point, p_tolerance) : false;
}
#endif
@@ -488,8 +167,8 @@ void NavigationRegion2D::_notification(int p_what) {
case NOTIFICATION_DRAW: {
#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 (is_inside_tree() && (Engine::get_singleton()->is_editor_hint() || NavigationServer3D::get_singleton()->get_debug_enabled()) && navigation_polygon.is_valid()) {
+ Vector<Vector2> verts = navigation_polygon->get_vertices();
if (verts.size() < 3) {
return;
}
@@ -504,9 +183,9 @@ void NavigationRegion2D::_notification(int p_what) {
RandomPCG rand;
- for (int i = 0; i < navpoly->get_polygon_count(); i++) {
+ for (int i = 0; i < navigation_polygon->get_polygon_count(); i++) {
// An array of vertices for this polygon.
- Vector<int> polygon = navpoly->get_polygon(i);
+ Vector<int> polygon = navigation_polygon->get_polygon(i);
Vector<Vector2> vertices;
vertices.resize(polygon.size());
for (int j = 0; j < polygon.size(); j++) {
@@ -547,36 +226,36 @@ void NavigationRegion2D::_notification(int p_what) {
}
}
-void NavigationRegion2D::set_navigation_polygon(const Ref<NavigationPolygon> &p_navpoly) {
- if (p_navpoly == navpoly) {
+void NavigationRegion2D::set_navigation_polygon(const Ref<NavigationPolygon> &p_navigation_polygon) {
+ if (p_navigation_polygon == navigation_polygon) {
return;
}
- if (navpoly.is_valid()) {
- navpoly->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(this, &NavigationRegion2D::_navpoly_changed));
+ if (navigation_polygon.is_valid()) {
+ navigation_polygon->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(this, &NavigationRegion2D::_navigation_polygon_changed));
}
- navpoly = p_navpoly;
- NavigationServer2D::get_singleton()->region_set_navpoly(region, p_navpoly);
+ navigation_polygon = p_navigation_polygon;
+ NavigationServer2D::get_singleton()->region_set_navigation_polygon(region, p_navigation_polygon);
- if (navpoly.is_valid()) {
- navpoly->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &NavigationRegion2D::_navpoly_changed));
+ if (navigation_polygon.is_valid()) {
+ navigation_polygon->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &NavigationRegion2D::_navigation_polygon_changed));
}
- _navpoly_changed();
+ _navigation_polygon_changed();
update_configuration_warnings();
}
Ref<NavigationPolygon> NavigationRegion2D::get_navigation_polygon() const {
- return navpoly;
+ return navigation_polygon;
}
-void NavigationRegion2D::_navpoly_changed() {
+void NavigationRegion2D::_navigation_polygon_changed() {
if (is_inside_tree() && (Engine::get_singleton()->is_editor_hint() || get_tree()->is_debugging_navigation_hint())) {
queue_redraw();
}
- if (navpoly.is_valid()) {
- NavigationServer2D::get_singleton()->region_set_navpoly(region, navpoly);
+ if (navigation_polygon.is_valid()) {
+ NavigationServer2D::get_singleton()->region_set_navigation_polygon(region, navigation_polygon);
}
}
@@ -592,7 +271,7 @@ PackedStringArray NavigationRegion2D::get_configuration_warnings() const {
PackedStringArray warnings = Node2D::get_configuration_warnings();
if (is_visible_in_tree() && is_inside_tree()) {
- if (!navpoly.is_valid()) {
+ if (!navigation_polygon.is_valid()) {
warnings.push_back(RTR("A NavigationMesh resource must be set or created for this node to work. Please set a property or draw a polygon."));
}
}
@@ -601,7 +280,7 @@ PackedStringArray NavigationRegion2D::get_configuration_warnings() const {
}
void NavigationRegion2D::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_navigation_polygon", "navpoly"), &NavigationRegion2D::set_navigation_polygon);
+ ClassDB::bind_method(D_METHOD("set_navigation_polygon", "navigation_polygon"), &NavigationRegion2D::set_navigation_polygon);
ClassDB::bind_method(D_METHOD("get_navigation_polygon"), &NavigationRegion2D::get_navigation_polygon);
ClassDB::bind_method(D_METHOD("set_enabled", "enabled"), &NavigationRegion2D::set_enabled);
@@ -621,18 +300,39 @@ void NavigationRegion2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_travel_cost", "travel_cost"), &NavigationRegion2D::set_travel_cost);
ClassDB::bind_method(D_METHOD("get_travel_cost"), &NavigationRegion2D::get_travel_cost);
- ClassDB::bind_method(D_METHOD("_navpoly_changed"), &NavigationRegion2D::_navpoly_changed);
+ ClassDB::bind_method(D_METHOD("_navigation_polygon_changed"), &NavigationRegion2D::_navigation_polygon_changed);
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "navpoly", PROPERTY_HINT_RESOURCE_TYPE, "NavigationPolygon"), "set_navigation_polygon", "get_navigation_polygon");
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "navigation_polygon", PROPERTY_HINT_RESOURCE_TYPE, "NavigationPolygon"), "set_navigation_polygon", "get_navigation_polygon");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "enabled"), "set_enabled", "is_enabled");
ADD_PROPERTY(PropertyInfo(Variant::INT, "navigation_layers", PROPERTY_HINT_LAYERS_2D_NAVIGATION), "set_navigation_layers", "get_navigation_layers");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "enter_cost"), "set_enter_cost", "get_enter_cost");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "travel_cost"), "set_travel_cost", "get_travel_cost");
}
+#ifndef DISABLE_DEPRECATED
+// Compatibility with earlier 4.0 betas.
+bool NavigationRegion2D::_set(const StringName &p_name, const Variant &p_value) {
+ if (p_name == "navpoly") {
+ set_navigation_polygon(p_value);
+ return true;
+ }
+ return false;
+}
+
+bool NavigationRegion2D::_get(const StringName &p_name, Variant &r_ret) const {
+ if (p_name == "navpoly") {
+ r_ret = get_navigation_polygon();
+ return true;
+ }
+ return false;
+}
+#endif // DISABLE_DEPRECATED
+
NavigationRegion2D::NavigationRegion2D() {
set_notify_transform(true);
+
region = NavigationServer2D::get_singleton()->region_create();
+ NavigationServer2D::get_singleton()->region_set_owner_id(region, get_instance_id());
NavigationServer2D::get_singleton()->region_set_enter_cost(region, get_enter_cost());
NavigationServer2D::get_singleton()->region_set_travel_cost(region, get_travel_cost());
diff --git a/scene/2d/navigation_region_2d.h b/scene/2d/navigation_region_2d.h
index c630e20780..45029fd95f 100644
--- a/scene/2d/navigation_region_2d.h
+++ b/scene/2d/navigation_region_2d.h
@@ -31,65 +31,7 @@
#ifndef NAVIGATION_REGION_2D_H
#define NAVIGATION_REGION_2D_H
-#include "scene/2d/node_2d.h"
-#include "scene/resources/navigation_mesh.h"
-
-class NavigationPolygon : public Resource {
- GDCLASS(NavigationPolygon, Resource);
-
- Vector<Vector2> vertices;
- struct Polygon {
- Vector<int> indices;
- };
- Vector<Polygon> polygons;
- Vector<Vector<Vector2>> outlines;
-
- mutable Rect2 item_rect;
- mutable bool rect_cache_dirty = true;
-
- Mutex navmesh_generation;
- // Navigation mesh
- Ref<NavigationMesh> navmesh;
-
-protected:
- static void _bind_methods();
-
- void _set_polygons(const TypedArray<Vector<int32_t>> &p_array);
- TypedArray<Vector<int32_t>> _get_polygons() const;
-
- void _set_outlines(const TypedArray<Vector<Vector2>> &p_array);
- TypedArray<Vector<Vector2>> _get_outlines() const;
-
-public:
-#ifdef TOOLS_ENABLED
- Rect2 _edit_get_rect() const;
- bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const;
-#endif
-
- void set_vertices(const Vector<Vector2> &p_vertices);
- Vector<Vector2> get_vertices() const;
-
- void add_polygon(const Vector<int> &p_polygon);
- int get_polygon_count() const;
-
- void add_outline(const Vector<Vector2> &p_outline);
- void add_outline_at_index(const Vector<Vector2> &p_outline, int p_index);
- void set_outline(int p_idx, const Vector<Vector2> &p_outline);
- Vector<Vector2> get_outline(int p_idx) const;
- void remove_outline(int p_idx);
- int get_outline_count() const;
-
- void clear_outlines();
- void make_polygons_from_outlines();
-
- Vector<int> get_polygon(int p_idx);
- void clear_polygons();
-
- Ref<NavigationMesh> get_mesh();
-
- NavigationPolygon() {}
- ~NavigationPolygon() {}
-};
+#include "scene/resources/navigation_polygon.h"
class NavigationRegion2D : public Node2D {
GDCLASS(NavigationRegion2D, Node2D);
@@ -99,15 +41,20 @@ class NavigationRegion2D : public Node2D {
uint32_t navigation_layers = 1;
real_t enter_cost = 0.0;
real_t travel_cost = 1.0;
- Ref<NavigationPolygon> navpoly;
+ Ref<NavigationPolygon> navigation_polygon;
- void _navpoly_changed();
+ void _navigation_polygon_changed();
void _map_changed(RID p_RID);
protected:
void _notification(int p_what);
static void _bind_methods();
+#ifndef DISABLE_DEPRECATED
+ bool _set(const StringName &p_name, const Variant &p_value);
+ bool _get(const StringName &p_name, Variant &r_ret) const;
+#endif // DISABLE_DEPRECATED
+
public:
#ifdef TOOLS_ENABLED
virtual Rect2 _edit_get_rect() const override;
@@ -131,7 +78,7 @@ public:
void set_travel_cost(real_t p_travel_cost);
real_t get_travel_cost() const;
- void set_navigation_polygon(const Ref<NavigationPolygon> &p_navpoly);
+ void set_navigation_polygon(const Ref<NavigationPolygon> &p_navigation_polygon);
Ref<NavigationPolygon> get_navigation_polygon() const;
PackedStringArray get_configuration_warnings() const override;
diff --git a/scene/2d/node_2d.cpp b/scene/2d/node_2d.cpp
index 2518069b78..166bc26848 100644
--- a/scene/2d/node_2d.cpp
+++ b/scene/2d/node_2d.cpp
@@ -30,6 +30,8 @@
#include "node_2d.h"
+#include "scene/main/viewport.h"
+
#ifdef TOOLS_ENABLED
Dictionary Node2D::_edit_get_state() const {
Dictionary state;
@@ -147,6 +149,10 @@ void Node2D::set_rotation(real_t p_radians) {
_update_transform();
}
+void Node2D::set_rotation_degrees(real_t p_degrees) {
+ set_rotation(Math::deg_to_rad(p_degrees));
+}
+
void Node2D::set_skew(real_t p_radians) {
if (_xform_dirty) {
const_cast<Node2D *>(this)->_update_xform_values();
@@ -185,6 +191,10 @@ real_t Node2D::get_rotation() const {
return rotation;
}
+real_t Node2D::get_rotation_degrees() const {
+ return Math::rad_to_deg(get_rotation());
+}
+
real_t Node2D::get_skew() const {
if (_xform_dirty) {
const_cast<Node2D *>(this)->_update_xform_values();
@@ -257,6 +267,10 @@ real_t Node2D::get_global_rotation() const {
return get_global_transform().get_rotation();
}
+real_t Node2D::get_global_rotation_degrees() const {
+ return Math::rad_to_deg(get_global_rotation());
+}
+
real_t Node2D::get_global_skew() const {
return get_global_transform().get_skew();
}
@@ -274,6 +288,10 @@ void Node2D::set_global_rotation(const real_t p_radians) {
}
}
+void Node2D::set_global_rotation_degrees(const real_t p_degrees) {
+ set_global_rotation(Math::deg_to_rad(p_degrees));
+}
+
void Node2D::set_global_skew(const real_t p_radians) {
CanvasItem *parent = get_parent_item();
if (parent) {
@@ -326,29 +344,6 @@ void Node2D::set_global_transform(const Transform2D &p_transform) {
}
}
-void Node2D::set_z_index(int p_z) {
- ERR_FAIL_COND(p_z < RS::CANVAS_ITEM_Z_MIN);
- ERR_FAIL_COND(p_z > RS::CANVAS_ITEM_Z_MAX);
- z_index = p_z;
- RS::get_singleton()->canvas_item_set_z_index(get_canvas_item(), z_index);
-}
-
-void Node2D::set_z_as_relative(bool p_enabled) {
- if (z_relative == p_enabled) {
- return;
- }
- z_relative = p_enabled;
- RS::get_singleton()->canvas_item_set_z_as_relative_to_parent(get_canvas_item(), p_enabled);
-}
-
-bool Node2D::is_z_relative() const {
- return z_relative;
-}
-
-int Node2D::get_z_index() const {
- return z_index;
-}
-
Transform2D Node2D::get_relative_transform_to_parent(const Node *p_parent) const {
if (p_parent == this) {
return Transform2D();
@@ -380,23 +375,26 @@ Point2 Node2D::to_global(Point2 p_local) const {
return get_global_transform().xform(p_local);
}
-void Node2D::set_y_sort_enabled(bool p_enabled) {
- y_sort_enabled = p_enabled;
- RS::get_singleton()->canvas_item_set_sort_children_by_y(get_canvas_item(), y_sort_enabled);
-}
-
-bool Node2D::is_y_sort_enabled() const {
- return y_sort_enabled;
+void Node2D::_notification(int p_notification) {
+ switch (p_notification) {
+ case NOTIFICATION_MOVED_IN_PARENT: {
+ if (get_viewport()) {
+ get_viewport()->gui_set_root_order_dirty();
+ }
+ } break;
+ }
}
void Node2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_position", "position"), &Node2D::set_position);
ClassDB::bind_method(D_METHOD("set_rotation", "radians"), &Node2D::set_rotation);
+ ClassDB::bind_method(D_METHOD("set_rotation_degrees", "degrees"), &Node2D::set_rotation_degrees);
ClassDB::bind_method(D_METHOD("set_skew", "radians"), &Node2D::set_skew);
ClassDB::bind_method(D_METHOD("set_scale", "scale"), &Node2D::set_scale);
ClassDB::bind_method(D_METHOD("get_position"), &Node2D::get_position);
ClassDB::bind_method(D_METHOD("get_rotation"), &Node2D::get_rotation);
+ ClassDB::bind_method(D_METHOD("get_rotation_degrees"), &Node2D::get_rotation_degrees);
ClassDB::bind_method(D_METHOD("get_skew"), &Node2D::get_skew);
ClassDB::bind_method(D_METHOD("get_scale"), &Node2D::get_scale);
@@ -410,7 +408,9 @@ void Node2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_global_position", "position"), &Node2D::set_global_position);
ClassDB::bind_method(D_METHOD("get_global_position"), &Node2D::get_global_position);
ClassDB::bind_method(D_METHOD("set_global_rotation", "radians"), &Node2D::set_global_rotation);
+ ClassDB::bind_method(D_METHOD("set_global_rotation_degrees", "degrees"), &Node2D::set_global_rotation_degrees);
ClassDB::bind_method(D_METHOD("get_global_rotation"), &Node2D::get_global_rotation);
+ ClassDB::bind_method(D_METHOD("get_global_rotation_degrees"), &Node2D::get_global_rotation_degrees);
ClassDB::bind_method(D_METHOD("set_global_skew", "radians"), &Node2D::set_global_skew);
ClassDB::bind_method(D_METHOD("get_global_skew"), &Node2D::get_global_skew);
ClassDB::bind_method(D_METHOD("set_global_scale", "scale"), &Node2D::set_global_scale);
@@ -425,32 +425,20 @@ void Node2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("to_local", "global_point"), &Node2D::to_local);
ClassDB::bind_method(D_METHOD("to_global", "local_point"), &Node2D::to_global);
- ClassDB::bind_method(D_METHOD("set_z_index", "z_index"), &Node2D::set_z_index);
- ClassDB::bind_method(D_METHOD("get_z_index"), &Node2D::get_z_index);
-
- ClassDB::bind_method(D_METHOD("set_z_as_relative", "enable"), &Node2D::set_z_as_relative);
- ClassDB::bind_method(D_METHOD("is_z_relative"), &Node2D::is_z_relative);
-
- ClassDB::bind_method(D_METHOD("set_y_sort_enabled", "enabled"), &Node2D::set_y_sort_enabled);
- ClassDB::bind_method(D_METHOD("is_y_sort_enabled"), &Node2D::is_y_sort_enabled);
-
ClassDB::bind_method(D_METHOD("get_relative_transform_to_parent", "parent"), &Node2D::get_relative_transform_to_parent);
ADD_GROUP("Transform", "");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "position", PROPERTY_HINT_RANGE, "-99999,99999,0.001,or_less,or_greater,hide_slider,suffix:px"), "set_position", "get_position");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "rotation", PROPERTY_HINT_RANGE, "-360,360,0.1,or_less,or_greater,radians"), "set_rotation", "get_rotation");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "rotation_degrees", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_rotation_degrees", "get_rotation_degrees");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "scale", PROPERTY_HINT_LINK), "set_scale", "get_scale");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "skew", PROPERTY_HINT_RANGE, "-89.9,89.9,0.1,radians"), "set_skew", "get_skew");
ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM2D, "transform", PROPERTY_HINT_NONE, "suffix:px", PROPERTY_USAGE_NONE), "set_transform", "get_transform");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "global_position", PROPERTY_HINT_NONE, "suffix:px", PROPERTY_USAGE_NONE), "set_global_position", "get_global_position");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "global_rotation", PROPERTY_HINT_NONE, "radians", PROPERTY_USAGE_NONE), "set_global_rotation", "get_global_rotation");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "global_rotation_degrees", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_global_rotation_degrees", "get_global_rotation_degrees");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "global_scale", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_global_scale", "get_global_scale");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "global_skew", PROPERTY_HINT_NONE, "radians", PROPERTY_USAGE_NONE), "set_global_skew", "get_global_skew");
ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM2D, "global_transform", PROPERTY_HINT_NONE, "suffix:px", PROPERTY_USAGE_NONE), "set_global_transform", "get_global_transform");
-
- ADD_GROUP("Ordering", "");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "z_index", PROPERTY_HINT_RANGE, itos(RS::CANVAS_ITEM_Z_MIN) + "," + itos(RS::CANVAS_ITEM_Z_MAX) + ",1"), "set_z_index", "get_z_index");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "z_as_relative"), "set_z_as_relative", "is_z_relative");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "y_sort_enabled"), "set_y_sort_enabled", "is_y_sort_enabled");
}
diff --git a/scene/2d/node_2d.h b/scene/2d/node_2d.h
index 0d8a31e6bb..b066332dcb 100644
--- a/scene/2d/node_2d.h
+++ b/scene/2d/node_2d.h
@@ -40,9 +40,6 @@ class Node2D : public CanvasItem {
real_t rotation = 0.0;
Size2 scale = Vector2(1, 1);
real_t skew = 0.0;
- int z_index = 0;
- bool z_relative = true;
- bool y_sort_enabled = false;
Transform2D transform;
@@ -53,6 +50,7 @@ class Node2D : public CanvasItem {
void _update_xform_values();
protected:
+ void _notification(int p_notification);
static void _bind_methods();
public:
@@ -75,6 +73,7 @@ public:
void set_position(const Point2 &p_pos);
void set_rotation(real_t p_radians);
+ void set_rotation_degrees(real_t p_degrees);
void set_skew(real_t p_radians);
void set_scale(const Size2 &p_scale);
@@ -87,11 +86,13 @@ public:
Point2 get_position() const;
real_t get_rotation() const;
+ real_t get_rotation_degrees() const;
real_t get_skew() const;
Size2 get_scale() const;
Point2 get_global_position() const;
real_t get_global_rotation() const;
+ real_t get_global_rotation_degrees() const;
real_t get_global_skew() const;
Size2 get_global_scale() const;
@@ -99,24 +100,16 @@ public:
void set_global_transform(const Transform2D &p_transform);
void set_global_position(const Point2 &p_pos);
void set_global_rotation(const real_t p_radians);
+ void set_global_rotation_degrees(const real_t p_degrees);
void set_global_skew(const real_t p_radians);
void set_global_scale(const Size2 &p_scale);
- void set_z_index(int p_z);
- int get_z_index() const;
-
void look_at(const Vector2 &p_pos);
real_t get_angle_to(const Vector2 &p_pos) const;
Point2 to_local(Point2 p_global) const;
Point2 to_global(Point2 p_local) const;
- void set_z_as_relative(bool p_enabled);
- bool is_z_relative() const;
-
- virtual void set_y_sort_enabled(bool p_enabled);
- virtual bool is_y_sort_enabled() const;
-
Transform2D get_relative_transform_to_parent(const Node *p_parent) const;
Transform2D get_transform() const override;
diff --git a/scene/2d/path_2d.cpp b/scene/2d/path_2d.cpp
index b5945a4562..823b8d56e3 100644
--- a/scene/2d/path_2d.cpp
+++ b/scene/2d/path_2d.cpp
@@ -106,18 +106,57 @@ void Path2D::_notification(int p_what) {
#else
const real_t line_width = get_tree()->get_debug_paths_width();
#endif
- _cached_draw_pts.resize(curve->get_point_count() * 8);
- int count = 0;
-
- for (int i = 0; i < curve->get_point_count(); i++) {
- for (int j = 0; j < 8; j++) {
- real_t frac = j * (1.0 / 8.0);
- Vector2 p = curve->sample(i, frac);
- _cached_draw_pts.set(count++, p);
+ real_t interval = 10;
+ const real_t length = curve->get_baked_length();
+
+ if (length > CMP_EPSILON) {
+ const int sample_count = int(length / interval) + 2;
+ interval = length / (sample_count - 1); // Recalculate real interval length.
+
+ Vector<Transform2D> frames;
+ frames.resize(sample_count);
+
+ {
+ Transform2D *w = frames.ptrw();
+
+ for (int i = 0; i < sample_count; i++) {
+ w[i] = curve->sample_baked_with_rotation(i * interval, false);
+ }
}
- }
- draw_polyline(_cached_draw_pts, get_tree()->get_debug_paths_color(), line_width, true);
+ const Transform2D *r = frames.ptr();
+ // Draw curve segments
+ {
+ PackedVector2Array v2p;
+ v2p.resize(sample_count);
+ Vector2 *w = v2p.ptrw();
+
+ for (int i = 0; i < sample_count; i++) {
+ w[i] = r[i].get_origin();
+ }
+ draw_polyline(v2p, get_tree()->get_debug_paths_color(), line_width, false);
+ }
+
+ // Draw fish bones
+ {
+ PackedVector2Array v2p;
+ v2p.resize(3);
+ Vector2 *w = v2p.ptrw();
+
+ for (int i = 0; i < sample_count; i++) {
+ const Vector2 p = r[i].get_origin();
+ const Vector2 side = r[i].columns[0];
+ const Vector2 forward = r[i].columns[1];
+
+ // Fish Bone.
+ w[0] = p + (side - forward) * 5;
+ w[1] = p;
+ w[2] = p + (-side - forward) * 5;
+
+ draw_polyline(v2p, get_tree()->get_debug_paths_color(), line_width * 0.5, false);
+ }
+ }
+ }
} break;
}
}
@@ -177,7 +216,7 @@ void PathFollow2D::_update_transform() {
}
if (rotates) {
- Transform2D xform = c->sample_baked_with_rotation(progress, cubic, loop, lookahead);
+ Transform2D xform = c->sample_baked_with_rotation(progress, cubic);
xform.translate_local(v_offset, h_offset);
set_rotation(xform[1].angle());
set_position(xform[2]);
diff --git a/scene/2d/path_2d.h b/scene/2d/path_2d.h
index 5e436fb9f6..935717605a 100644
--- a/scene/2d/path_2d.h
+++ b/scene/2d/path_2d.h
@@ -38,7 +38,6 @@ class Path2D : public Node2D {
GDCLASS(Path2D, Node2D);
Ref<Curve2D> curve;
- Vector<Vector2> _cached_draw_pts;
void _curve_changed();
diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp
index 0f3e6c7529..7f5b5d1ea4 100644
--- a/scene/2d/physics_body_2d.cpp
+++ b/scene/2d/physics_body_2d.cpp
@@ -34,8 +34,8 @@
#include "scene/scene_string_names.h"
void PhysicsBody2D::_bind_methods() {
- ClassDB::bind_method(D_METHOD("move_and_collide", "distance", "test_only", "safe_margin", "recovery_as_collision"), &PhysicsBody2D::_move, DEFVAL(false), DEFVAL(0.08), DEFVAL(false));
- ClassDB::bind_method(D_METHOD("test_move", "from", "distance", "collision", "safe_margin", "recovery_as_collision"), &PhysicsBody2D::test_move, DEFVAL(Variant()), DEFVAL(0.08), DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("move_and_collide", "motion", "test_only", "safe_margin", "recovery_as_collision"), &PhysicsBody2D::_move, DEFVAL(false), DEFVAL(0.08), DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("test_move", "from", "motion", "collision", "safe_margin", "recovery_as_collision"), &PhysicsBody2D::test_move, DEFVAL(Variant()), DEFVAL(0.08), DEFVAL(false));
ClassDB::bind_method(D_METHOD("get_collision_exceptions"), &PhysicsBody2D::get_collision_exceptions);
ClassDB::bind_method(D_METHOD("add_collision_exception_with", "body"), &PhysicsBody2D::add_collision_exception_with);
@@ -54,8 +54,8 @@ PhysicsBody2D::~PhysicsBody2D() {
}
}
-Ref<KinematicCollision2D> PhysicsBody2D::_move(const Vector2 &p_distance, bool p_test_only, real_t p_margin, bool p_recovery_as_collision) {
- PhysicsServer2D::MotionParameters parameters(get_global_transform(), p_distance, p_margin);
+Ref<KinematicCollision2D> PhysicsBody2D::_move(const Vector2 &p_motion, bool p_test_only, real_t p_margin, bool p_recovery_as_collision) {
+ PhysicsServer2D::MotionParameters parameters(get_global_transform(), p_motion, p_margin);
parameters.recovery_as_collision = p_recovery_as_collision;
PhysicsServer2D::MotionResult result;
@@ -128,7 +128,7 @@ bool PhysicsBody2D::move_and_collide(const PhysicsServer2D::MotionParameters &p_
return colliding;
}
-bool PhysicsBody2D::test_move(const Transform2D &p_from, const Vector2 &p_distance, const Ref<KinematicCollision2D> &r_collision, real_t p_margin, bool p_recovery_as_collision) {
+bool PhysicsBody2D::test_move(const Transform2D &p_from, const Vector2 &p_motion, const Ref<KinematicCollision2D> &r_collision, real_t p_margin, bool p_recovery_as_collision) {
ERR_FAIL_COND_V(!is_inside_tree(), false);
PhysicsServer2D::MotionResult *r = nullptr;
@@ -140,7 +140,7 @@ bool PhysicsBody2D::test_move(const Transform2D &p_from, const Vector2 &p_distan
r = &temp_result;
}
- PhysicsServer2D::MotionParameters parameters(p_from, p_distance, p_margin);
+ PhysicsServer2D::MotionParameters parameters(p_from, p_motion, p_margin);
parameters.recovery_as_collision = p_recovery_as_collision;
return PhysicsServer2D::get_singleton()->body_test_motion(get_rid(), parameters, r);
@@ -162,14 +162,14 @@ TypedArray<PhysicsBody2D> PhysicsBody2D::get_collision_exceptions() {
void PhysicsBody2D::add_collision_exception_with(Node *p_node) {
ERR_FAIL_NULL(p_node);
PhysicsBody2D *physics_body = Object::cast_to<PhysicsBody2D>(p_node);
- ERR_FAIL_COND_MSG(!physics_body, "Collision exception only works between two objects of PhysicsBody2D type.");
+ ERR_FAIL_COND_MSG(!physics_body, "Collision exception only works between two nodes that inherit from PhysicsBody2D.");
PhysicsServer2D::get_singleton()->body_add_collision_exception(get_rid(), physics_body->get_rid());
}
void PhysicsBody2D::remove_collision_exception_with(Node *p_node) {
ERR_FAIL_NULL(p_node);
PhysicsBody2D *physics_body = Object::cast_to<PhysicsBody2D>(p_node);
- ERR_FAIL_COND_MSG(!physics_body, "Collision exception only works between two objects of PhysicsBody2D type.");
+ ERR_FAIL_COND_MSG(!physics_body, "Collision exception only works between two nodes that inherit from PhysicsBody2D.");
PhysicsServer2D::get_singleton()->body_remove_collision_exception(get_rid(), physics_body->get_rid());
}
@@ -1761,7 +1761,7 @@ void CharacterBody2D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "floor_max_angle", PROPERTY_HINT_RANGE, "0,180,0.1,radians"), "set_floor_max_angle", "get_floor_max_angle");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "floor_snap_length", PROPERTY_HINT_RANGE, "0,32,0.1,or_greater,suffix:px"), "set_floor_snap_length", "get_floor_snap_length");
- ADD_GROUP("Moving Platform", "platform");
+ ADD_GROUP("Moving Platform", "platform_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "platform_on_leave", PROPERTY_HINT_ENUM, "Add Velocity,Add Upward Velocity,Do Nothing", PROPERTY_USAGE_DEFAULT), "set_platform_on_leave", "get_platform_on_leave");
ADD_PROPERTY(PropertyInfo(Variant::INT, "platform_floor_layers", PROPERTY_HINT_LAYERS_2D_PHYSICS), "set_platform_floor_layers", "get_platform_floor_layers");
ADD_PROPERTY(PropertyInfo(Variant::INT, "platform_wall_layers", PROPERTY_HINT_LAYERS_2D_PHYSICS), "set_platform_wall_layers", "get_platform_wall_layers");
diff --git a/scene/2d/physics_body_2d.h b/scene/2d/physics_body_2d.h
index 932ec1de16..504e1dc333 100644
--- a/scene/2d/physics_body_2d.h
+++ b/scene/2d/physics_body_2d.h
@@ -47,11 +47,11 @@ protected:
Ref<KinematicCollision2D> motion_cache;
- Ref<KinematicCollision2D> _move(const Vector2 &p_distance, bool p_test_only = false, real_t p_margin = 0.08, bool p_recovery_as_collision = false);
+ Ref<KinematicCollision2D> _move(const Vector2 &p_motion, bool p_test_only = false, real_t p_margin = 0.08, bool p_recovery_as_collision = false);
public:
bool move_and_collide(const PhysicsServer2D::MotionParameters &p_parameters, PhysicsServer2D::MotionResult &r_result, bool p_test_only = false, bool p_cancel_sliding = true);
- bool test_move(const Transform2D &p_from, const Vector2 &p_distance, const Ref<KinematicCollision2D> &r_collision = Ref<KinematicCollision2D>(), real_t p_margin = 0.08, bool p_recovery_as_collision = false);
+ bool test_move(const Transform2D &p_from, const Vector2 &p_motion, const Ref<KinematicCollision2D> &r_collision = Ref<KinematicCollision2D>(), real_t p_margin = 0.08, bool p_recovery_as_collision = false);
TypedArray<PhysicsBody2D> get_collision_exceptions();
void add_collision_exception_with(Node *p_node); //must be physicsbody
diff --git a/scene/2d/polygon_2d.cpp b/scene/2d/polygon_2d.cpp
index 5e77902977..e41664b006 100644
--- a/scene/2d/polygon_2d.cpp
+++ b/scene/2d/polygon_2d.cpp
@@ -114,7 +114,7 @@ void Polygon2D::_notification(int p_what) {
ObjectID new_skeleton_id;
- if (skeleton_node) {
+ if (skeleton_node && !invert && bone_weights.size()) {
RS::get_singleton()->canvas_item_attach_skeleton(get_canvas_item(), skeleton_node->get_skeleton());
new_skeleton_id = skeleton_node->get_instance_id();
} else {
@@ -663,5 +663,7 @@ Polygon2D::Polygon2D() {
}
Polygon2D::~Polygon2D() {
+ // This will free the internally-allocated mesh instance, if allocated.
+ RS::get_singleton()->canvas_item_attach_skeleton(get_canvas_item(), RID());
RS::get_singleton()->free(mesh);
}
diff --git a/scene/2d/skeleton_2d.cpp b/scene/2d/skeleton_2d.cpp
index 02d8e20ce8..62787d4488 100644
--- a/scene/2d/skeleton_2d.cpp
+++ b/scene/2d/skeleton_2d.cpp
@@ -213,7 +213,7 @@ void Bone2D::_notification(int p_what) {
}
// Undo scaling
- Transform2D editor_gizmo_trans = Transform2D();
+ Transform2D editor_gizmo_trans;
editor_gizmo_trans.set_scale(Vector2(1, 1) / get_global_scale());
RenderingServer::get_singleton()->canvas_item_set_transform(editor_gizmo_rid, editor_gizmo_trans);
diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp
index 40e8818262..3136752a2e 100644
--- a/scene/2d/tile_map.cpp
+++ b/scene/2d/tile_map.cpp
@@ -358,7 +358,7 @@ TileMap::TerrainConstraint::TerrainConstraint(const TileMap *p_tile_map, const V
terrain = p_terrain;
}
-Vector2i TileMap::transform_coords_layout(Vector2i p_coords, TileSet::TileOffsetAxis p_offset_axis, TileSet::TileLayout p_from_layout, TileSet::TileLayout p_to_layout) {
+Vector2i TileMap::transform_coords_layout(const Vector2i &p_coords, TileSet::TileOffsetAxis p_offset_axis, TileSet::TileLayout p_from_layout, TileSet::TileLayout p_to_layout) {
// Transform to stacked layout.
Vector2i output = p_coords;
if (p_offset_axis == TileSet::TILE_OFFSET_AXIS_VERTICAL) {
@@ -755,6 +755,7 @@ void TileMap::set_y_sort_enabled(bool p_enable) {
_clear_internals();
_recreate_internals();
emit_signal(SNAME("changed"));
+ update_configuration_warnings();
}
Vector2i TileMap::_coords_to_quadrant_coords(int p_layer, const Vector2i &p_coords) const {
@@ -995,9 +996,11 @@ void TileMap::_recompute_rect_cache() {
}
}
+ bool changed = rect_cache != r_total;
+
rect_cache = r_total;
- item_rect_changed();
+ item_rect_changed(changed);
rect_cache_dirty = false;
#endif
@@ -1089,7 +1092,7 @@ void TileMap::_rendering_update_layer(int p_layer) {
/*Transform2D xform;
xform.set_origin(Vector2(0, p_layer));
rs->canvas_item_set_transform(ci, xform);*/
- rs->canvas_item_set_draw_index(ci, p_layer);
+ rs->canvas_item_set_draw_index(ci, p_layer - (int64_t)0x80000000);
layers[p_layer].canvas_item = ci;
}
@@ -1340,7 +1343,7 @@ void TileMap::_rendering_draw_quadrant_debug(TileMapQuadrant *p_quadrant) {
}
}
-void TileMap::draw_tile(RID p_canvas_item, Vector2i p_position, const Ref<TileSet> p_tile_set, int p_atlas_source_id, Vector2i p_atlas_coords, int p_alternative_tile, int p_frame, Color p_modulation, const TileData *p_tile_data_override) {
+void TileMap::draw_tile(RID p_canvas_item, const Vector2i &p_position, const Ref<TileSet> p_tile_set, int p_atlas_source_id, const Vector2i &p_atlas_coords, int p_alternative_tile, int p_frame, Color p_modulation, const TileData *p_tile_data_override) {
ERR_FAIL_COND(!p_tile_set.is_valid());
ERR_FAIL_COND(!p_tile_set->has_source(p_atlas_source_id));
ERR_FAIL_COND(!p_tile_set->get_source(p_atlas_source_id)->has_tile(p_atlas_coords));
@@ -1725,17 +1728,19 @@ void TileMap::_navigation_update_dirty_quadrants(SelfList<TileMapQuadrant>::List
q.navigation_regions[E_cell].resize(tile_set->get_navigation_layers_count());
for (int layer_index = 0; layer_index < tile_set->get_navigation_layers_count(); layer_index++) {
- Ref<NavigationPolygon> navpoly;
- navpoly = tile_data->get_navigation_polygon(layer_index);
+ Ref<NavigationPolygon> navigation_polygon;
+ navigation_polygon = tile_data->get_navigation_polygon(layer_index);
- if (navpoly.is_valid()) {
+ if (navigation_polygon.is_valid()) {
Transform2D tile_transform;
tile_transform.set_origin(map_to_local(E_cell));
RID region = NavigationServer2D::get_singleton()->region_create();
+ NavigationServer2D::get_singleton()->region_set_owner_id(region, get_instance_id());
NavigationServer2D::get_singleton()->region_set_map(region, get_world_2d()->get_navigation_map());
NavigationServer2D::get_singleton()->region_set_transform(region, tilemap_xform * tile_transform);
- NavigationServer2D::get_singleton()->region_set_navpoly(region, navpoly);
+ NavigationServer2D::get_singleton()->region_set_navigation_layers(region, tile_set->get_navigation_layer_layers(layer_index));
+ NavigationServer2D::get_singleton()->region_set_navigation_polygon(region, navigation_polygon);
q.navigation_regions[E_cell].write[layer_index] = region;
}
}
@@ -1859,11 +1864,13 @@ void TileMap::_scenes_update_dirty_quadrants(SelfList<TileMapQuadrant>::List &r_
while (q_list_element) {
TileMapQuadrant &q = *q_list_element->self();
- // Clear the scenes.
- for (const KeyValue<Vector2i, String> &E : q.scenes) {
- Node *node = get_node_or_null(E.value);
- if (node) {
- node->queue_free();
+ // Clear the scenes if instance cache was cleared.
+ if (instantiated_scenes.is_empty()) {
+ for (const KeyValue<Vector2i, String> &E : q.scenes) {
+ Node *node = get_node_or_null(E.value);
+ if (node) {
+ node->queue_free();
+ }
}
}
@@ -1871,6 +1878,15 @@ void TileMap::_scenes_update_dirty_quadrants(SelfList<TileMapQuadrant>::List &r_
// Recreate the scenes.
for (const Vector2i &E_cell : q.cells) {
+ Vector3i cell_coords = Vector3i(q.layer, E_cell.x, E_cell.y);
+ if (instantiated_scenes.has(cell_coords)) {
+ // Skip scene if the instance was cached (to avoid recreating scenes unnecessarily).
+ continue;
+ }
+ if (!Engine::get_singleton()->is_editor_hint()) {
+ instantiated_scenes.insert(cell_coords);
+ }
+
const TileMapCell &c = get_cell(q.layer, E_cell, true);
TileSetSource *source;
@@ -1907,15 +1923,16 @@ void TileMap::_scenes_update_dirty_quadrants(SelfList<TileMapQuadrant>::List &r_
}
void TileMap::_scenes_cleanup_quadrant(TileMapQuadrant *p_quadrant) {
- // Clear the scenes.
- for (const KeyValue<Vector2i, String> &E : p_quadrant->scenes) {
- Node *node = get_node_or_null(E.value);
- if (node) {
- node->queue_free();
+ // Clear the scenes if instance cache was cleared.
+ if (instantiated_scenes.is_empty()) {
+ for (const KeyValue<Vector2i, String> &E : p_quadrant->scenes) {
+ Node *node = get_node_or_null(E.value);
+ if (node) {
+ node->queue_free();
+ }
}
+ p_quadrant->scenes.clear();
}
-
- p_quadrant->scenes.clear();
}
void TileMap::_scenes_draw_quadrant_debug(TileMapQuadrant *p_quadrant) {
@@ -1980,7 +1997,6 @@ void TileMap::set_cell(int p_layer, const Vector2i &p_coords, int p_source_id, c
if ((source_id == TileSet::INVALID_SOURCE || atlas_coords == TileSetSource::INVALID_ATLAS_COORDS || alternative_tile == TileSetSource::INVALID_TILE_ALTERNATIVE) &&
(source_id != TileSet::INVALID_SOURCE || atlas_coords != TileSetSource::INVALID_ATLAS_COORDS || alternative_tile != TileSetSource::INVALID_TILE_ALTERNATIVE)) {
- WARN_PRINT("Setting a cell as empty requires both source_id, atlas_coord and alternative_tile to be set to their respective \"invalid\" values. Values were thus changes accordingly.");
source_id = TileSet::INVALID_SOURCE;
atlas_coords = TileSetSource::INVALID_ATLAS_COORDS;
alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE;
@@ -2171,7 +2187,7 @@ Ref<TileMapPattern> TileMap::get_pattern(int p_layer, TypedArray<Vector2i> p_coo
return output;
}
-Vector2i TileMap::map_pattern(Vector2i p_position_in_tilemap, Vector2i p_coords_in_pattern, Ref<TileMapPattern> p_pattern) {
+Vector2i TileMap::map_pattern(const Vector2i &p_position_in_tilemap, const Vector2i &p_coords_in_pattern, Ref<TileMapPattern> p_pattern) {
ERR_FAIL_COND_V(p_pattern.is_null(), Vector2i());
ERR_FAIL_COND_V(!p_pattern->has_cell(p_coords_in_pattern), Vector2i());
@@ -2195,7 +2211,7 @@ Vector2i TileMap::map_pattern(Vector2i p_position_in_tilemap, Vector2i p_coords_
return output;
}
-void TileMap::set_pattern(int p_layer, Vector2i p_position, const Ref<TileMapPattern> p_pattern) {
+void TileMap::set_pattern(int p_layer, const Vector2i &p_position, const Ref<TileMapPattern> p_pattern) {
ERR_FAIL_INDEX(p_layer, (int)layers.size());
ERR_FAIL_COND(!tile_set.is_valid());
@@ -2206,7 +2222,7 @@ void TileMap::set_pattern(int p_layer, Vector2i p_position, const Ref<TileMapPat
}
}
-TileSet::TerrainsPattern TileMap::_get_best_terrain_pattern_for_constraints(int p_terrain_set, const Vector2i &p_position, RBSet<TerrainConstraint> p_constraints, TileSet::TerrainsPattern p_current_pattern) {
+TileSet::TerrainsPattern TileMap::_get_best_terrain_pattern_for_constraints(int p_terrain_set, const Vector2i &p_position, const RBSet<TerrainConstraint> &p_constraints, TileSet::TerrainsPattern p_current_pattern) {
if (!tile_set.is_valid()) {
return TileSet::TerrainsPattern();
}
@@ -2219,7 +2235,7 @@ TileSet::TerrainsPattern TileMap::_get_best_terrain_pattern_for_constraints(int
// Check the center bit constraint
TerrainConstraint terrain_constraint = TerrainConstraint(this, p_position, terrain_pattern.get_terrain());
- RBSet<TerrainConstraint>::Element *in_set_constraint_element = p_constraints.find(terrain_constraint);
+ const RBSet<TerrainConstraint>::Element *in_set_constraint_element = p_constraints.find(terrain_constraint);
if (in_set_constraint_element) {
if (in_set_constraint_element->get().get_terrain() != terrain_constraint.get_terrain()) {
score += in_set_constraint_element->get().get_priority();
@@ -2266,7 +2282,7 @@ TileSet::TerrainsPattern TileMap::_get_best_terrain_pattern_for_constraints(int
return min_score_pattern;
}
-RBSet<TileMap::TerrainConstraint> TileMap::_get_terrain_constraints_from_added_pattern(Vector2i p_position, int p_terrain_set, TileSet::TerrainsPattern p_terrains_pattern) const {
+RBSet<TileMap::TerrainConstraint> TileMap::_get_terrain_constraints_from_added_pattern(const Vector2i &p_position, int p_terrain_set, TileSet::TerrainsPattern p_terrains_pattern) const {
if (!tile_set.is_valid()) {
return RBSet<TerrainConstraint>();
}
@@ -2374,7 +2390,7 @@ RBSet<TileMap::TerrainConstraint> TileMap::_get_terrain_constraints_from_painted
return constraints;
}
-HashMap<Vector2i, TileSet::TerrainsPattern> TileMap::terrain_fill_constraints(int p_layer, const Vector<Vector2i> &p_to_replace, int p_terrain_set, const RBSet<TerrainConstraint> p_constraints) {
+HashMap<Vector2i, TileSet::TerrainsPattern> TileMap::terrain_fill_constraints(int p_layer, const Vector<Vector2i> &p_to_replace, int p_terrain_set, const RBSet<TerrainConstraint> &p_constraints) {
if (!tile_set.is_valid()) {
return HashMap<Vector2i, TileSet::TerrainsPattern>();
}
@@ -3826,7 +3842,7 @@ void TileMap::set_texture_repeat(CanvasItem::TextureRepeat p_texture_repeat) {
}
}
-TypedArray<Vector2i> TileMap::get_surrounding_tiles(Vector2i coords) {
+TypedArray<Vector2i> TileMap::get_surrounding_cells(const Vector2i &coords) {
if (!tile_set.is_valid()) {
return TypedArray<Vector2i>();
}
@@ -3864,7 +3880,7 @@ TypedArray<Vector2i> TileMap::get_surrounding_tiles(Vector2i coords) {
return around;
}
-void TileMap::draw_cells_outline(Control *p_control, RBSet<Vector2i> p_cells, Color p_color, Transform2D p_transform) {
+void TileMap::draw_cells_outline(Control *p_control, const RBSet<Vector2i> &p_cells, Color p_color, Transform2D p_transform) {
if (!tile_set.is_valid()) {
return;
}
@@ -3889,35 +3905,26 @@ void TileMap::draw_cells_outline(Control *p_control, RBSet<Vector2i> p_cells, Co
DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_BOTTOM_SIDE, 2, 3);
DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_LEFT_SIDE, 3, 0);
DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_TOP_SIDE, 0, 1);
+ } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC) {
+ DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE, 2, 3);
+ DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE, 1, 2);
+ DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE, 0, 1);
+ DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE, 3, 0);
} else {
if (tile_set->get_tile_offset_axis() == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) {
- if (shape == TileSet::TILE_SHAPE_ISOMETRIC) {
- DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE, 3, 4);
- DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE, 2, 3);
- DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE, 0, 1);
- DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE, 5, 0);
- } else {
- DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE, 3, 4);
- DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE, 2, 3);
- DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_LEFT_SIDE, 1, 2);
- DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE, 0, 1);
- DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE, 5, 0);
- DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_RIGHT_SIDE, 4, 5);
- }
+ DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE, 3, 4);
+ DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE, 2, 3);
+ DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_LEFT_SIDE, 1, 2);
+ DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE, 0, 1);
+ DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE, 5, 0);
+ DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_RIGHT_SIDE, 4, 5);
} else {
- if (shape == TileSet::TILE_SHAPE_ISOMETRIC) {
- DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE, 3, 4);
- DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE, 5, 0);
- DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE, 0, 1);
- DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE, 2, 3);
- } else {
- DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE, 3, 4);
- DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_BOTTOM_SIDE, 4, 5);
- DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE, 5, 0);
- DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE, 0, 1);
- DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_TOP_SIDE, 1, 2);
- DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE, 2, 3);
- }
+ DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE, 3, 4);
+ DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_BOTTOM_SIDE, 4, 5);
+ DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE, 5, 0);
+ DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE, 0, 1);
+ DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_TOP_SIDE, 1, 2);
+ DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE, 2, 3);
}
}
}
@@ -3943,6 +3950,22 @@ PackedStringArray TileMap::get_configuration_warnings() const {
}
}
+ if (tile_set.is_valid() && tile_set->get_tile_shape() == TileSet::TILE_SHAPE_ISOMETRIC) {
+ bool warn = !is_y_sort_enabled();
+ if (!warn) {
+ for (int layer = 0; layer < (int)layers.size(); layer++) {
+ if (!layers[layer].y_sort_enabled) {
+ warn = true;
+ break;
+ }
+ }
+ }
+
+ if (warn) {
+ warnings.push_back(RTR("Isometric TileSet will likely not look as intended without Y-sort enabled for the TileMap and all of its layers."));
+ }
+ }
+
return warnings;
}
@@ -4000,7 +4023,7 @@ void TileMap::_bind_methods() {
ClassDB::bind_method(D_METHOD("force_update", "layer"), &TileMap::force_update, DEFVAL(-1));
- ClassDB::bind_method(D_METHOD("get_surrounding_tiles", "coords"), &TileMap::get_surrounding_tiles);
+ ClassDB::bind_method(D_METHOD("get_surrounding_cells", "coords"), &TileMap::get_surrounding_cells);
ClassDB::bind_method(D_METHOD("get_used_cells", "layer"), &TileMap::get_used_cells);
ClassDB::bind_method(D_METHOD("get_used_rect"), &TileMap::get_used_rect);
@@ -4037,7 +4060,9 @@ void TileMap::_bind_methods() {
void TileMap::_tile_set_changed() {
emit_signal(SNAME("changed"));
_tile_set_changed_deferred_update_needed = true;
+ instantiated_scenes.clear();
call_deferred(SNAME("_tile_set_changed_deferred_update"));
+ update_configuration_warnings();
}
void TileMap::_tile_set_changed_deferred_update() {
@@ -4056,5 +4081,9 @@ TileMap::TileMap() {
}
TileMap::~TileMap() {
+ if (tile_set.is_valid()) {
+ tile_set->disconnect("changed", callable_mp(this, &TileMap::_tile_set_changed));
+ }
+
_clear_internals();
}
diff --git a/scene/2d/tile_map.h b/scene/2d/tile_map.h
index 7f3e241871..6f71636e47 100644
--- a/scene/2d/tile_map.h
+++ b/scene/2d/tile_map.h
@@ -115,7 +115,7 @@ public:
class TerrainConstraint {
private:
const TileMap *tile_map;
- Vector2i base_cell_coords = Vector2i();
+ Vector2i base_cell_coords;
int bit = -1;
int terrain = -1;
@@ -155,7 +155,7 @@ public:
priority = p_priority;
}
- int get_priority() {
+ int get_priority() const {
return priority;
}
@@ -236,6 +236,8 @@ private:
void _clear_layer_internals(int p_layer);
void _clear_internals();
+ HashSet<Vector3i> instantiated_scenes;
+
// Rect caching.
void _recompute_rect_cache();
@@ -266,8 +268,8 @@ private:
void _scenes_draw_quadrant_debug(TileMapQuadrant *p_quadrant);
// Terrains.
- TileSet::TerrainsPattern _get_best_terrain_pattern_for_constraints(int p_terrain_set, const Vector2i &p_position, RBSet<TerrainConstraint> p_constraints, TileSet::TerrainsPattern p_current_pattern);
- RBSet<TerrainConstraint> _get_terrain_constraints_from_added_pattern(Vector2i p_position, int p_terrain_set, TileSet::TerrainsPattern p_terrains_pattern) const;
+ TileSet::TerrainsPattern _get_best_terrain_pattern_for_constraints(int p_terrain_set, const Vector2i &p_position, const RBSet<TerrainConstraint> &p_constraints, TileSet::TerrainsPattern p_current_pattern);
+ RBSet<TerrainConstraint> _get_terrain_constraints_from_added_pattern(const Vector2i &p_position, int p_terrain_set, TileSet::TerrainsPattern p_terrains_pattern) const;
RBSet<TerrainConstraint> _get_terrain_constraints_from_painted_cells_list(int p_layer, const RBSet<Vector2i> &p_painted, int p_terrain_set, bool p_ignore_empty_terrains) const;
// Set and get tiles from data arrays.
@@ -289,7 +291,7 @@ protected:
static void _bind_methods();
public:
- static Vector2i transform_coords_layout(Vector2i p_coords, TileSet::TileOffsetAxis p_offset_axis, TileSet::TileLayout p_from_layout, TileSet::TileLayout p_to_layout);
+ static Vector2i transform_coords_layout(const Vector2i &p_coords, TileSet::TileOffsetAxis p_offset_axis, TileSet::TileLayout p_from_layout, TileSet::TileLayout p_to_layout);
enum {
INVALID_CELL = -1
@@ -305,7 +307,7 @@ public:
void set_quadrant_size(int p_size);
int get_quadrant_size() const;
- static void draw_tile(RID p_canvas_item, Vector2i p_position, const Ref<TileSet> p_tile_set, int p_atlas_source_id, Vector2i p_atlas_coords, int p_alternative_tile, int p_frame = -1, Color p_modulation = Color(1.0, 1.0, 1.0, 1.0), const TileData *p_tile_data_override = nullptr);
+ static void draw_tile(RID p_canvas_item, const Vector2i &p_position, const Ref<TileSet> p_tile_set, int p_atlas_source_id, const Vector2i &p_atlas_coords, int p_alternative_tile, int p_frame = -1, Color p_modulation = Color(1.0, 1.0, 1.0, 1.0), const TileData *p_tile_data_override = nullptr);
// Layers management.
int get_layers_count() const;
@@ -348,11 +350,11 @@ public:
// Patterns.
Ref<TileMapPattern> get_pattern(int p_layer, TypedArray<Vector2i> p_coords_array);
- Vector2i map_pattern(Vector2i p_position_in_tilemap, Vector2i p_coords_in_pattern, Ref<TileMapPattern> p_pattern);
- void set_pattern(int p_layer, Vector2i p_position, const Ref<TileMapPattern> p_pattern);
+ Vector2i map_pattern(const Vector2i &p_position_in_tilemap, const Vector2i &p_coords_in_pattern, Ref<TileMapPattern> p_pattern);
+ void set_pattern(int p_layer, const Vector2i &p_position, const Ref<TileMapPattern> p_pattern);
// Terrains.
- HashMap<Vector2i, TileSet::TerrainsPattern> terrain_fill_constraints(int p_layer, const Vector<Vector2i> &p_to_replace, int p_terrain_set, const RBSet<TerrainConstraint> p_constraints); // Not exposed.
+ HashMap<Vector2i, TileSet::TerrainsPattern> terrain_fill_constraints(int p_layer, const Vector<Vector2i> &p_to_replace, int p_terrain_set, const RBSet<TerrainConstraint> &p_constraints); // Not exposed.
HashMap<Vector2i, TileSet::TerrainsPattern> terrain_fill_connect(int p_layer, const Vector<Vector2i> &p_coords_array, int p_terrain_set, int p_terrain, bool p_ignore_empty_terrains = true); // Not exposed.
HashMap<Vector2i, TileSet::TerrainsPattern> terrain_fill_path(int p_layer, const Vector<Vector2i> &p_coords_array, int p_terrain_set, int p_terrain, bool p_ignore_empty_terrains = true); // Not exposed.
HashMap<Vector2i, TileSet::TerrainsPattern> terrain_fill_pattern(int p_layer, const Vector<Vector2i> &p_coords_array, int p_terrain_set, TileSet::TerrainsPattern p_terrains_pattern, bool p_ignore_empty_terrains = true); // Not exposed.
@@ -398,8 +400,8 @@ public:
void force_update(int p_layer = -1);
// Helpers?
- TypedArray<Vector2i> get_surrounding_tiles(Vector2i coords);
- void draw_cells_outline(Control *p_control, RBSet<Vector2i> p_cells, Color p_color, Transform2D p_transform = Transform2D());
+ TypedArray<Vector2i> get_surrounding_cells(const Vector2i &coords);
+ void draw_cells_outline(Control *p_control, const RBSet<Vector2i> &p_cells, Color p_color, Transform2D p_transform = Transform2D());
// Virtual function to modify the TileData at runtime
GDVIRTUAL2R(bool, _use_tile_data_runtime_update, int, Vector2i);
diff --git a/scene/2d/touch_screen_button.cpp b/scene/2d/touch_screen_button.cpp
index a02f322ef1..11b4718802 100644
--- a/scene/2d/touch_screen_button.cpp
+++ b/scene/2d/touch_screen_button.cpp
@@ -100,7 +100,7 @@ void TouchScreenButton::_notification(int p_what) {
if (!is_inside_tree()) {
return;
}
- if (!Engine::get_singleton()->is_editor_hint() && !!DisplayServer::get_singleton()->screen_is_touchscreen(DisplayServer::get_singleton()->window_get_current_screen(get_viewport()->get_window_id())) && visibility == VISIBILITY_TOUCHSCREEN_ONLY) {
+ if (!Engine::get_singleton()->is_editor_hint() && !DisplayServer::get_singleton()->is_touchscreen_available() && visibility == VISIBILITY_TOUCHSCREEN_ONLY) {
return;
}
@@ -137,7 +137,7 @@ void TouchScreenButton::_notification(int p_what) {
} break;
case NOTIFICATION_ENTER_TREE: {
- if (!Engine::get_singleton()->is_editor_hint() && !!DisplayServer::get_singleton()->screen_is_touchscreen(DisplayServer::get_singleton()->window_get_current_screen(get_viewport()->get_window_id())) && visibility == VISIBILITY_TOUCHSCREEN_ONLY) {
+ if (!Engine::get_singleton()->is_editor_hint() && !DisplayServer::get_singleton()->is_touchscreen_available() && visibility == VISIBILITY_TOUCHSCREEN_ONLY) {
return;
}
queue_redraw();
diff --git a/scene/3d/audio_stream_player_3d.cpp b/scene/3d/audio_stream_player_3d.cpp
index b9d95672fe..75e840c24b 100644
--- a/scene/3d/audio_stream_player_3d.cpp
+++ b/scene/3d/audio_stream_player_3d.cpp
@@ -606,6 +606,9 @@ bool AudioStreamPlayer3D::is_playing() const {
return true;
}
}
+ if (setplay.get() >= 0) {
+ return true; // play() has been called this frame, but no playback exists just yet.
+ }
return false;
}
diff --git a/scene/3d/audio_stream_player_3d.h b/scene/3d/audio_stream_player_3d.h
index 913cc9fc00..806b250ba7 100644
--- a/scene/3d/audio_stream_player_3d.h
+++ b/scene/3d/audio_stream_player_3d.h
@@ -117,7 +117,7 @@ private:
float _get_attenuation_db(float p_distance) const;
float panning_strength = 1.0f;
- float cached_global_panning_strength = 1.0f;
+ float cached_global_panning_strength = 0.5f;
protected:
void _validate_property(PropertyInfo &p_property) const;
diff --git a/scene/3d/bone_attachment_3d.cpp b/scene/3d/bone_attachment_3d.cpp
index d8524a7392..9cf10dbef1 100644
--- a/scene/3d/bone_attachment_3d.cpp
+++ b/scene/3d/bone_attachment_3d.cpp
@@ -375,7 +375,7 @@ 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) {
+void BoneAttachment3D::_notify_skeleton_bones_renamed(Node *p_base_scene, Skeleton3D *p_skeleton, Dictionary p_rename_map) {
const Skeleton3D *parent = nullptr;
if (use_external_skeleton) {
if (external_skeleton_node_cache.is_valid()) {
@@ -385,7 +385,7 @@ void BoneAttachment3D::_notify_skeleton_bones_renamed(Node *p_base_scene, Skelet
parent = Object::cast_to<Skeleton3D>(get_parent());
}
if (parent && parent == p_skeleton) {
- StringName bn = p_bone_map->find_profile_bone_name(bone_name);
+ StringName bn = p_rename_map[bone_name];
if (bn) {
set_bone_name(bn);
}
diff --git a/scene/3d/bone_attachment_3d.h b/scene/3d/bone_attachment_3d.h
index 2db6ba6268..81338b30e9 100644
--- a/scene/3d/bone_attachment_3d.h
+++ b/scene/3d/bone_attachment_3d.h
@@ -72,7 +72,7 @@ protected:
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);
+ virtual void _notify_skeleton_bones_renamed(Node *p_base_scene, Skeleton3D *p_skeleton, Dictionary p_rename_map);
#endif // TOOLS_ENABLED
public:
diff --git a/scene/3d/camera_3d.cpp b/scene/3d/camera_3d.cpp
index 304e56326d..2a50575749 100644
--- a/scene/3d/camera_3d.cpp
+++ b/scene/3d/camera_3d.cpp
@@ -112,6 +112,12 @@ void Camera3D::_notification(int p_what) {
if (current || first_camera) {
viewport->_camera_3d_set(this);
}
+
+#ifdef TOOLS_ENABLED
+ if (Engine::get_singleton()->is_editor_hint()) {
+ viewport->connect(SNAME("size_changed"), callable_mp((Node3D *)this, &Camera3D::update_gizmos));
+ }
+#endif
} break;
case NOTIFICATION_TRANSFORM_CHANGED: {
@@ -133,6 +139,11 @@ void Camera3D::_notification(int p_what) {
}
if (viewport) {
+#ifdef TOOLS_ENABLED
+ if (Engine::get_singleton()->is_editor_hint()) {
+ viewport->disconnect(SNAME("size_changed"), callable_mp((Node3D *)this, &Camera3D::update_gizmos));
+ }
+#endif
viewport->_camera_3d_remove(this);
viewport = nullptr;
}
diff --git a/scene/3d/collision_object_3d.cpp b/scene/3d/collision_object_3d.cpp
index ca23fe03a2..66546092f2 100644
--- a/scene/3d/collision_object_3d.cpp
+++ b/scene/3d/collision_object_3d.cpp
@@ -30,6 +30,7 @@
#include "collision_object_3d.h"
+#include "scene/resources/shape_3d.h"
#include "scene/scene_string_names.h"
void CollisionObject3D::_notification(int p_what) {
diff --git a/scene/3d/collision_shape_3d.cpp b/scene/3d/collision_shape_3d.cpp
index ef381641ab..2729dfc369 100644
--- a/scene/3d/collision_shape_3d.cpp
+++ b/scene/3d/collision_shape_3d.cpp
@@ -34,6 +34,7 @@
#include "physics_body_3d.h"
#include "scene/resources/concave_polygon_shape_3d.h"
#include "scene/resources/convex_polygon_shape_3d.h"
+#include "scene/resources/world_boundary_shape_3d.h"
void CollisionShape3D::make_convex_from_siblings() {
Node *p = get_parent();
@@ -125,10 +126,12 @@ PackedStringArray CollisionShape3D::get_configuration_warnings() const {
warnings.push_back(RTR("A shape must be provided for CollisionShape3D to function. Please create a shape resource for it."));
}
- if (shape.is_valid() &&
- Object::cast_to<RigidBody3D>(get_parent()) &&
- Object::cast_to<ConcavePolygonShape3D>(*shape)) {
- warnings.push_back(RTR("ConcavePolygonShape3D doesn't support RigidBody3D in another mode than static."));
+ if (shape.is_valid() && Object::cast_to<RigidBody3D>(get_parent())) {
+ if (Object::cast_to<ConcavePolygonShape3D>(*shape)) {
+ warnings.push_back(RTR("ConcavePolygonShape3D doesn't support RigidBody3D in another mode than static."));
+ } else if (Object::cast_to<WorldBoundaryShape3D>(*shape)) {
+ warnings.push_back(RTR("WorldBoundaryShape3D doesn't support RigidBody3D in another mode than static."));
+ }
}
return warnings;
diff --git a/scene/3d/cpu_particles_3d.cpp b/scene/3d/cpu_particles_3d.cpp
index 7de685b469..5ac8535bb6 100644
--- a/scene/3d/cpu_particles_3d.cpp
+++ b/scene/3d/cpu_particles_3d.cpp
@@ -867,7 +867,7 @@ void CPUParticles3D::_particles_process(double p_delta) {
real_t ring_random_angle = Math::randf() * Math_TAU;
real_t ring_random_radius = Math::randf() * (emission_ring_radius - emission_ring_inner_radius) + emission_ring_inner_radius;
Vector3 axis = emission_ring_axis.normalized();
- Vector3 ortho_axis = Vector3();
+ Vector3 ortho_axis;
if (axis == Vector3(1.0, 0.0, 0.0)) {
ortho_axis = Vector3(0.0, 1.0, 0.0).cross(axis);
} else {
diff --git a/scene/3d/gpu_particles_3d.cpp b/scene/3d/gpu_particles_3d.cpp
index 9d04202c2d..17dfe2610e 100644
--- a/scene/3d/gpu_particles_3d.cpp
+++ b/scene/3d/gpu_particles_3d.cpp
@@ -272,10 +272,6 @@ bool GPUParticles3D::get_interpolate() const {
PackedStringArray GPUParticles3D::get_configuration_warnings() const {
PackedStringArray 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."));
- }
-
bool meshes_found = false;
bool anim_material_found = false;
diff --git a/scene/3d/gpu_particles_3d.h b/scene/3d/gpu_particles_3d.h
index 835d71862a..d1768436e5 100644
--- a/scene/3d/gpu_particles_3d.h
+++ b/scene/3d/gpu_particles_3d.h
@@ -82,7 +82,7 @@ private:
Ref<Material> process_material;
- DrawOrder draw_order;
+ DrawOrder draw_order = DRAW_ORDER_INDEX;
Vector<Ref<Mesh>> draw_passes;
Ref<Skin> skin;
diff --git a/scene/3d/gpu_particles_collision_3d.cpp b/scene/3d/gpu_particles_collision_3d.cpp
index 2c5df48b75..476820b1c4 100644
--- a/scene/3d/gpu_particles_collision_3d.cpp
+++ b/scene/3d/gpu_particles_collision_3d.cpp
@@ -347,7 +347,9 @@ void GPUParticlesCollisionSDF3D::_compute_sdf(ComputeSDFParams *params) {
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(WorkerThreadPool::get_singleton()->get_group_processed_element_count(group_task) * 100 / params->size.z, "Baking SDF");
+ if (bake_step_function) {
+ bake_step_function(WorkerThreadPool::get_singleton()->get_group_processed_element_count(group_task) * 100 / params->size.z, "Baking SDF");
+ }
}
WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task);
}
diff --git a/scene/3d/light_3d.cpp b/scene/3d/light_3d.cpp
index 198dba7811..3f43e718b8 100644
--- a/scene/3d/light_3d.cpp
+++ b/scene/3d/light_3d.cpp
@@ -461,7 +461,7 @@ Light3D::Light3D(RenderingServer::LightType p_type) {
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_BIAS, 0.1);
set_param(PARAM_SHADOW_NORMAL_BIAS, 1.0);
set_param(PARAM_TRANSMITTANCE_BIAS, 0.05);
set_param(PARAM_SHADOW_FADE_START, 1);
@@ -571,8 +571,8 @@ DirectionalLight3D::DirectionalLight3D() :
Light3D(RenderingServer::LIGHT_DIRECTIONAL) {
set_param(PARAM_SHADOW_MAX_DISTANCE, 100);
set_param(PARAM_SHADOW_FADE_START, 0.8);
- // Increase the default shadow bias to better suit most scenes.
- set_param(PARAM_SHADOW_BIAS, 0.1);
+ // Increase the default shadow normal bias to better suit most scenes.
+ set_param(PARAM_SHADOW_NORMAL_BIAS, 2.0);
set_param(PARAM_INTENSITY, 100000.0); // Specified in Lux, approximate mid-day sun.
set_shadow_mode(SHADOW_PARALLEL_4_SPLITS);
blend_splits = false;
@@ -614,8 +614,6 @@ void OmniLight3D::_bind_methods() {
OmniLight3D::OmniLight3D() :
Light3D(RenderingServer::LIGHT_OMNI) {
set_shadow_mode(SHADOW_CUBE);
- // Increase the default shadow biases to better suit most scenes.
- set_param(PARAM_SHADOW_BIAS, 0.2);
}
PackedStringArray SpotLight3D::get_configuration_warnings() const {
@@ -639,3 +637,9 @@ void SpotLight3D::_bind_methods() {
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "spot_angle", PROPERTY_HINT_RANGE, "0,180,0.01,degrees"), "set_param", "get_param", PARAM_SPOT_ANGLE);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "spot_angle_attenuation", PROPERTY_HINT_EXP_EASING, "attenuation"), "set_param", "get_param", PARAM_SPOT_ATTENUATION);
}
+
+SpotLight3D::SpotLight3D() :
+ Light3D(RenderingServer::LIGHT_SPOT) {
+ // Decrease the default shadow bias to better suit most scenes.
+ set_param(PARAM_SHADOW_BIAS, 0.03);
+}
diff --git a/scene/3d/light_3d.h b/scene/3d/light_3d.h
index 84d214030b..d2dfa32aac 100644
--- a/scene/3d/light_3d.h
+++ b/scene/3d/light_3d.h
@@ -233,8 +233,7 @@ protected:
public:
PackedStringArray get_configuration_warnings() const override;
- SpotLight3D() :
- Light3D(RenderingServer::LIGHT_SPOT) {}
+ SpotLight3D();
};
#endif // LIGHT_3D_H
diff --git a/scene/3d/mesh_instance_3d.cpp b/scene/3d/mesh_instance_3d.cpp
index d4f60503c2..c4ec54fa8f 100644
--- a/scene/3d/mesh_instance_3d.cpp
+++ b/scene/3d/mesh_instance_3d.cpp
@@ -33,6 +33,8 @@
#include "collision_shape_3d.h"
#include "core/core_string_names.h"
#include "physics_body_3d.h"
+#include "scene/resources/concave_polygon_shape_3d.h"
+#include "scene/resources/convex_polygon_shape_3d.h"
bool MeshInstance3D::_set(const StringName &p_name, const Variant &p_value) {
//this is not _too_ bad performance wise, really. it only arrives here if the property was not set anywhere else.
@@ -50,6 +52,7 @@ bool MeshInstance3D::_set(const StringName &p_name, const Variant &p_value) {
if (p_name.operator String().begins_with("surface_material_override/")) {
int idx = p_name.operator String().get_slicec('/', 1).to_int();
+
if (idx >= surface_override_materials.size() || idx < 0) {
return false;
}
@@ -224,7 +227,7 @@ Node *MeshInstance3D::create_trimesh_collision_node() {
return nullptr;
}
- Ref<Shape3D> shape = mesh->create_trimesh_shape();
+ Ref<ConcavePolygonShape3D> shape = mesh->create_trimesh_shape();
if (shape.is_null()) {
return nullptr;
}
@@ -254,7 +257,7 @@ Node *MeshInstance3D::create_convex_collision_node(bool p_clean, bool p_simplify
return nullptr;
}
- Ref<Shape3D> shape = mesh->create_convex_shape(p_clean, p_simplify);
+ Ref<ConvexPolygonShape3D> shape = mesh->create_convex_shape(p_clean, p_simplify);
if (shape.is_null()) {
return nullptr;
}
@@ -320,6 +323,11 @@ void MeshInstance3D::_notification(int p_what) {
case NOTIFICATION_ENTER_TREE: {
_resolve_skeleton_path();
} break;
+ case NOTIFICATION_TRANSLATION_CHANGED: {
+ if (mesh.is_valid()) {
+ mesh->notification(NOTIFICATION_TRANSLATION_CHANGED);
+ }
+ } break;
}
}
diff --git a/scene/3d/mesh_instance_3d.h b/scene/3d/mesh_instance_3d.h
index caf7d25616..e1cc5272ea 100644
--- a/scene/3d/mesh_instance_3d.h
+++ b/scene/3d/mesh_instance_3d.h
@@ -57,6 +57,7 @@ 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;
+ bool surface_index_0 = false;
void _notification(int p_what);
static void _bind_methods();
diff --git a/scene/3d/navigation_agent_3d.cpp b/scene/3d/navigation_agent_3d.cpp
index 36350d251e..741f7397ad 100644
--- a/scene/3d/navigation_agent_3d.cpp
+++ b/scene/3d/navigation_agent_3d.cpp
@@ -74,6 +74,9 @@ void NavigationAgent3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_navigation_layer_value", "layer_number", "value"), &NavigationAgent3D::set_navigation_layer_value);
ClassDB::bind_method(D_METHOD("get_navigation_layer_value", "layer_number"), &NavigationAgent3D::get_navigation_layer_value);
+ ClassDB::bind_method(D_METHOD("set_path_metadata_flags", "flags"), &NavigationAgent3D::set_path_metadata_flags);
+ ClassDB::bind_method(D_METHOD("get_path_metadata_flags"), &NavigationAgent3D::get_path_metadata_flags);
+
ClassDB::bind_method(D_METHOD("set_navigation_map", "navigation_map"), &NavigationAgent3D::set_navigation_map);
ClassDB::bind_method(D_METHOD("get_navigation_map"), &NavigationAgent3D::get_navigation_map);
@@ -83,8 +86,9 @@ void NavigationAgent3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_next_location"), &NavigationAgent3D::get_next_location);
ClassDB::bind_method(D_METHOD("distance_to_target"), &NavigationAgent3D::distance_to_target);
ClassDB::bind_method(D_METHOD("set_velocity", "velocity"), &NavigationAgent3D::set_velocity);
- ClassDB::bind_method(D_METHOD("get_nav_path"), &NavigationAgent3D::get_nav_path);
- ClassDB::bind_method(D_METHOD("get_nav_path_index"), &NavigationAgent3D::get_nav_path_index);
+ ClassDB::bind_method(D_METHOD("get_current_navigation_result"), &NavigationAgent3D::get_current_navigation_result);
+ ClassDB::bind_method(D_METHOD("get_current_navigation_path"), &NavigationAgent3D::get_current_navigation_path);
+ ClassDB::bind_method(D_METHOD("get_current_navigation_path_index"), &NavigationAgent3D::get_current_navigation_path_index);
ClassDB::bind_method(D_METHOD("is_target_reached"), &NavigationAgent3D::is_target_reached);
ClassDB::bind_method(D_METHOD("is_target_reachable"), &NavigationAgent3D::is_target_reachable);
ClassDB::bind_method(D_METHOD("is_navigation_finished"), &NavigationAgent3D::is_navigation_finished);
@@ -99,6 +103,7 @@ void NavigationAgent3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "agent_height_offset", PROPERTY_HINT_RANGE, "-100.0,100,0.01,suffix:m"), "set_agent_height_offset", "get_agent_height_offset");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "path_max_distance", PROPERTY_HINT_RANGE, "0.01,100,0.1,suffix:m"), "set_path_max_distance", "get_path_max_distance");
ADD_PROPERTY(PropertyInfo(Variant::INT, "navigation_layers", PROPERTY_HINT_LAYERS_3D_NAVIGATION), "set_navigation_layers", "get_navigation_layers");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "path_metadata_flags", PROPERTY_HINT_FLAGS, "Include Types,Include RIDs,Include Owners"), "set_path_metadata_flags", "get_path_metadata_flags");
ADD_GROUP("Avoidance", "");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "avoidance_enabled"), "set_avoidance_enabled", "get_avoidance_enabled");
@@ -111,6 +116,8 @@ void NavigationAgent3D::_bind_methods() {
ADD_SIGNAL(MethodInfo("path_changed"));
ADD_SIGNAL(MethodInfo("target_reached"));
+ ADD_SIGNAL(MethodInfo("waypoint_reached", PropertyInfo(Variant::DICTIONARY, "details")));
+ ADD_SIGNAL(MethodInfo("link_reached", PropertyInfo(Variant::DICTIONARY, "details")));
ADD_SIGNAL(MethodInfo("navigation_finished"));
ADD_SIGNAL(MethodInfo("velocity_computed", PropertyInfo(Variant::VECTOR3, "safe_velocity")));
}
@@ -167,7 +174,7 @@ void NavigationAgent3D::_notification(int p_what) {
} break;
case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
- if (agent_parent) {
+ if (agent_parent && target_position_submitted) {
if (avoidance_enabled) {
// agent_position on NavigationServer is avoidance only and has nothing to do with pathfinding
// no point in flooding NavigationServer queue with agent position updates that get send to the void if avoidance is not used
@@ -204,9 +211,9 @@ NavigationAgent3D::~NavigationAgent3D() {
void NavigationAgent3D::set_avoidance_enabled(bool p_enabled) {
avoidance_enabled = p_enabled;
if (avoidance_enabled) {
- NavigationServer3D::get_singleton()->agent_set_callback(agent, this, "_avoidance_done");
+ NavigationServer3D::get_singleton()->agent_set_callback(agent, get_instance_id(), "_avoidance_done");
} else {
- NavigationServer3D::get_singleton()->agent_set_callback(agent, nullptr, "_avoidance_done");
+ NavigationServer3D::get_singleton()->agent_set_callback(agent, ObjectID(), "_avoidance_done");
}
}
@@ -216,7 +223,7 @@ bool NavigationAgent3D::get_avoidance_enabled() const {
void NavigationAgent3D::set_agent_parent(Node *p_agent_parent) {
// remove agent from any avoidance map before changing parent or there will be leftovers on the RVO map
- NavigationServer3D::get_singleton()->agent_set_callback(agent, nullptr, "_avoidance_done");
+ NavigationServer3D::get_singleton()->agent_set_callback(agent, ObjectID(), "_avoidance_done");
if (Object::cast_to<Node3D>(p_agent_parent) != nullptr) {
// place agent on navigation map first or else the RVO agent callback creation fails silently later
agent_parent = Object::cast_to<Node3D>(p_agent_parent);
@@ -263,6 +270,14 @@ bool NavigationAgent3D::get_navigation_layer_value(int p_layer_number) const {
return get_navigation_layers() & (1 << (p_layer_number - 1));
}
+void NavigationAgent3D::set_path_metadata_flags(BitField<NavigationPathQueryParameters3D::PathMetadataFlags> p_path_metadata_flags) {
+ if (path_metadata_flags == p_path_metadata_flags) {
+ return;
+ }
+
+ path_metadata_flags = p_path_metadata_flags;
+}
+
void NavigationAgent3D::set_navigation_map(RID p_navigation_map) {
map_override = p_navigation_map;
NavigationServer3D::get_singleton()->agent_set_map(agent, map_override);
@@ -330,6 +345,7 @@ real_t NavigationAgent3D::get_path_max_distance() {
void NavigationAgent3D::set_target_location(Vector3 p_location) {
target_location = p_location;
+ target_position_submitted = true;
_request_repath();
}
@@ -345,14 +361,10 @@ Vector3 NavigationAgent3D::get_next_location() {
ERR_FAIL_COND_V_MSG(agent_parent == nullptr, Vector3(), "The agent has no parent.");
return agent_parent->get_global_transform().origin;
} else {
- return navigation_path[nav_path_index] - Vector3(0, navigation_height_offset, 0);
+ return navigation_path[navigation_path_index] - Vector3(0, navigation_height_offset, 0);
}
}
-const Vector<Vector3> &NavigationAgent3D::get_nav_path() const {
- return navigation_result->get_path();
-}
-
real_t NavigationAgent3D::distance_to_target() const {
ERR_FAIL_COND_V_MSG(agent_parent == nullptr, 0.0, "The agent has no parent.");
return agent_parent->get_global_transform().origin.distance_to(target_location);
@@ -417,6 +429,9 @@ void NavigationAgent3D::update_navigation() {
if (!agent_parent->is_inside_tree()) {
return;
}
+ if (!target_position_submitted) {
+ return;
+ }
if (update_frame_id == Engine::get_singleton()->get_physics_frames()) {
return;
}
@@ -433,12 +448,12 @@ void NavigationAgent3D::update_navigation() {
reload_path = true;
} else {
// Check if too far from the navigation path
- if (nav_path_index > 0) {
+ if (navigation_path_index > 0) {
const Vector<Vector3> &navigation_path = navigation_result->get_path();
Vector3 segment[2];
- segment[0] = navigation_path[nav_path_index - 1];
- segment[1] = navigation_path[nav_path_index];
+ segment[0] = navigation_path[navigation_path_index - 1];
+ segment[1] = navigation_path[navigation_path_index];
segment[0].y -= navigation_height_offset;
segment[1].y -= navigation_height_offset;
Vector3 p = Geometry3D::get_closest_point_to_segment(origin, segment);
@@ -453,6 +468,7 @@ void NavigationAgent3D::update_navigation() {
navigation_query->set_start_position(origin);
navigation_query->set_target_position(target_location);
navigation_query->set_navigation_layers(navigation_layers);
+ navigation_query->set_metadata_flags(path_metadata_flags);
if (map_override.is_valid()) {
navigation_query->set_map(map_override);
@@ -462,7 +478,7 @@ void NavigationAgent3D::update_navigation() {
NavigationServer3D::get_singleton()->query_path(navigation_query, navigation_result);
navigation_finished = false;
- nav_path_index = 0;
+ navigation_path_index = 0;
emit_signal(SNAME("path_changed"));
}
@@ -474,12 +490,57 @@ void NavigationAgent3D::update_navigation() {
if (navigation_finished == false) {
// Advances to the next far away location.
const Vector<Vector3> &navigation_path = navigation_result->get_path();
- while (origin.distance_to(navigation_path[nav_path_index] - Vector3(0, navigation_height_offset, 0)) < path_desired_distance) {
- nav_path_index += 1;
- if (nav_path_index == navigation_path.size()) {
+ const Vector<int32_t> &navigation_path_types = navigation_result->get_path_types();
+ const TypedArray<RID> &navigation_path_rids = navigation_result->get_path_rids();
+ const Vector<int64_t> &navigation_path_owners = navigation_result->get_path_owner_ids();
+
+ while (origin.distance_to(navigation_path[navigation_path_index] - Vector3(0, navigation_height_offset, 0)) < path_desired_distance) {
+ Dictionary details;
+
+ const Vector3 waypoint = navigation_path[navigation_path_index];
+ details[SNAME("location")] = waypoint;
+
+ int waypoint_type = -1;
+ if (path_metadata_flags.has_flag(NavigationPathQueryParameters3D::PathMetadataFlags::PATH_METADATA_INCLUDE_TYPES)) {
+ const NavigationPathQueryResult3D::PathSegmentType type = NavigationPathQueryResult3D::PathSegmentType(navigation_path_types[navigation_path_index]);
+
+ details[SNAME("type")] = type;
+ waypoint_type = type;
+ }
+
+ if (path_metadata_flags.has_flag(NavigationPathQueryParameters3D::PathMetadataFlags::PATH_METADATA_INCLUDE_RIDS)) {
+ details[SNAME("rid")] = navigation_path_rids[navigation_path_index];
+ }
+
+ if (path_metadata_flags.has_flag(NavigationPathQueryParameters3D::PathMetadataFlags::PATH_METADATA_INCLUDE_OWNERS)) {
+ const ObjectID waypoint_owner_id = ObjectID(navigation_path_owners[navigation_path_index]);
+
+ // Get a reference to the owning object.
+ Object *owner = nullptr;
+ if (waypoint_owner_id.is_valid()) {
+ owner = ObjectDB::get_instance(waypoint_owner_id);
+ }
+
+ details[SNAME("owner")] = owner;
+ }
+
+ // Emit a signal for the waypoint
+ emit_signal(SNAME("waypoint_reached"), details);
+
+ // Emit a signal if we've reached a navigation link
+ if (waypoint_type == NavigationPathQueryResult3D::PATH_SEGMENT_TYPE_LINK) {
+ emit_signal(SNAME("link_reached"), details);
+ }
+
+ // Move to the next waypoint on the list
+ navigation_path_index += 1;
+
+ // Check to see if we've finished our route
+ if (navigation_path_index == navigation_path.size()) {
_check_distance_to_target();
- nav_path_index -= 1;
+ navigation_path_index -= 1;
navigation_finished = true;
+ target_position_submitted = false;
emit_signal(SNAME("navigation_finished"));
break;
}
diff --git a/scene/3d/navigation_agent_3d.h b/scene/3d/navigation_agent_3d.h
index 90ceab0242..cda218b538 100644
--- a/scene/3d/navigation_agent_3d.h
+++ b/scene/3d/navigation_agent_3d.h
@@ -32,10 +32,10 @@
#define NAVIGATION_AGENT_3D_H
#include "scene/main/node.h"
+#include "servers/navigation/navigation_path_query_parameters_3d.h"
+#include "servers/navigation/navigation_path_query_result_3d.h"
class Node3D;
-class NavigationPathQueryParameters3D;
-class NavigationPathQueryResult3D;
class NavigationAgent3D : public Node {
GDCLASS(NavigationAgent3D, Node);
@@ -48,6 +48,7 @@ class NavigationAgent3D : public Node {
bool avoidance_enabled = false;
uint32_t navigation_layers = 1;
+ BitField<NavigationPathQueryParameters3D::PathMetadataFlags> path_metadata_flags = NavigationPathQueryParameters3D::PathMetadataFlags::PATH_METADATA_INCLUDE_ALL;
real_t path_desired_distance = 1.0;
real_t target_desired_distance = 1.0;
@@ -62,9 +63,10 @@ class NavigationAgent3D : public Node {
real_t path_max_distance = 3.0;
Vector3 target_location;
+ bool target_position_submitted = false;
Ref<NavigationPathQueryParameters3D> navigation_query;
Ref<NavigationPathQueryResult3D> navigation_result;
- int nav_path_index = 0;
+ int navigation_path_index = 0;
bool velocity_submitted = false;
Vector3 prev_safe_velocity;
/// The submitted target velocity
@@ -97,6 +99,11 @@ public:
void set_navigation_layer_value(int p_layer_number, bool p_value);
bool get_navigation_layer_value(int p_layer_number) const;
+ void set_path_metadata_flags(BitField<NavigationPathQueryParameters3D::PathMetadataFlags> p_flags);
+ BitField<NavigationPathQueryParameters3D::PathMetadataFlags> get_path_metadata_flags() const {
+ return path_metadata_flags;
+ }
+
void set_navigation_map(RID p_navigation_map);
RID get_navigation_map() const;
@@ -153,10 +160,14 @@ public:
Vector3 get_next_location();
- const Vector<Vector3> &get_nav_path() const;
-
- int get_nav_path_index() const {
- return nav_path_index;
+ Ref<NavigationPathQueryResult3D> get_current_navigation_result() const {
+ return navigation_result;
+ }
+ const Vector<Vector3> &get_current_navigation_path() const {
+ return navigation_result->get_path();
+ }
+ int get_current_navigation_path_index() const {
+ return navigation_path_index;
}
real_t distance_to_target() const;
diff --git a/scene/3d/navigation_link_3d.cpp b/scene/3d/navigation_link_3d.cpp
index 78fe4754ea..bee7c7f39b 100644
--- a/scene/3d/navigation_link_3d.cpp
+++ b/scene/3d/navigation_link_3d.cpp
@@ -221,6 +221,8 @@ void NavigationLink3D::_notification(int p_what) {
NavigationLink3D::NavigationLink3D() {
link = NavigationServer3D::get_singleton()->link_create();
+ NavigationServer3D::get_singleton()->link_set_owner_id(link, get_instance_id());
+
set_notify_transform(true);
}
diff --git a/scene/3d/navigation_link_3d.h b/scene/3d/navigation_link_3d.h
index 1fc03546fa..46bc6318b8 100644
--- a/scene/3d/navigation_link_3d.h
+++ b/scene/3d/navigation_link_3d.h
@@ -37,11 +37,11 @@ class NavigationLink3D : public Node3D {
GDCLASS(NavigationLink3D, Node3D);
bool enabled = true;
- RID link = RID();
+ RID link;
bool bidirectional = true;
uint32_t navigation_layers = 1;
- Vector3 end_location = Vector3();
- Vector3 start_location = Vector3();
+ Vector3 end_location;
+ Vector3 start_location;
real_t enter_cost = 0.0;
real_t travel_cost = 1.0;
diff --git a/scene/3d/navigation_region_3d.cpp b/scene/3d/navigation_region_3d.cpp
index 06182d921c..86b78f847e 100644
--- a/scene/3d/navigation_region_3d.cpp
+++ b/scene/3d/navigation_region_3d.cpp
@@ -192,26 +192,26 @@ void NavigationRegion3D::_notification(int p_what) {
}
}
-void NavigationRegion3D::set_navigation_mesh(const Ref<NavigationMesh> &p_navmesh) {
- if (p_navmesh == navmesh) {
+void NavigationRegion3D::set_navigation_mesh(const Ref<NavigationMesh> &p_navigation_mesh) {
+ if (p_navigation_mesh == navigation_mesh) {
return;
}
- if (navmesh.is_valid()) {
- navmesh->disconnect("changed", callable_mp(this, &NavigationRegion3D::_navigation_changed));
+ if (navigation_mesh.is_valid()) {
+ navigation_mesh->disconnect("changed", callable_mp(this, &NavigationRegion3D::_navigation_changed));
}
- navmesh = p_navmesh;
+ navigation_mesh = p_navigation_mesh;
- if (navmesh.is_valid()) {
- navmesh->connect("changed", callable_mp(this, &NavigationRegion3D::_navigation_changed));
+ if (navigation_mesh.is_valid()) {
+ navigation_mesh->connect("changed", callable_mp(this, &NavigationRegion3D::_navigation_changed));
}
- NavigationServer3D::get_singleton()->region_set_navmesh(region, p_navmesh);
+ NavigationServer3D::get_singleton()->region_set_navigation_mesh(region, p_navigation_mesh);
#ifdef DEBUG_ENABLED
if (is_inside_tree() && NavigationServer3D::get_singleton()->get_debug_enabled()) {
- if (navmesh.is_valid()) {
+ if (navigation_mesh.is_valid()) {
_update_debug_mesh();
_update_debug_edge_connections_mesh();
} else {
@@ -232,7 +232,7 @@ void NavigationRegion3D::set_navigation_mesh(const Ref<NavigationMesh> &p_navmes
}
Ref<NavigationMesh> NavigationRegion3D::get_navigation_mesh() const {
- return navmesh;
+ return navigation_mesh;
}
struct BakeThreadsArgs {
@@ -245,7 +245,7 @@ void _bake_navigation_mesh(void *p_user_data) {
if (args->nav_region->get_navigation_mesh().is_valid()) {
Ref<NavigationMesh> nav_mesh = args->nav_region->get_navigation_mesh()->duplicate();
- NavigationServer3D::get_singleton()->region_bake_navmesh(nav_mesh, args->nav_region);
+ NavigationServer3D::get_singleton()->region_bake_navigation_mesh(nav_mesh, args->nav_region);
args->nav_region->call_deferred(SNAME("_bake_finished"), nav_mesh);
memdelete(args);
} else {
@@ -278,7 +278,7 @@ PackedStringArray NavigationRegion3D::get_configuration_warnings() const {
PackedStringArray warnings = Node::get_configuration_warnings();
if (is_visible_in_tree() && is_inside_tree()) {
- if (!navmesh.is_valid()) {
+ if (!navigation_mesh.is_valid()) {
warnings.push_back(RTR("A NavigationMesh resource must be set or created for this node to work."));
}
}
@@ -287,7 +287,7 @@ PackedStringArray NavigationRegion3D::get_configuration_warnings() const {
}
void NavigationRegion3D::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_navigation_mesh", "navmesh"), &NavigationRegion3D::set_navigation_mesh);
+ ClassDB::bind_method(D_METHOD("set_navigation_mesh", "navigation_mesh"), &NavigationRegion3D::set_navigation_mesh);
ClassDB::bind_method(D_METHOD("get_navigation_mesh"), &NavigationRegion3D::get_navigation_mesh);
ClassDB::bind_method(D_METHOD("set_enabled", "enabled"), &NavigationRegion3D::set_enabled);
@@ -308,9 +308,9 @@ void NavigationRegion3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_travel_cost"), &NavigationRegion3D::get_travel_cost);
ClassDB::bind_method(D_METHOD("bake_navigation_mesh", "on_thread"), &NavigationRegion3D::bake_navigation_mesh, DEFVAL(true));
- ClassDB::bind_method(D_METHOD("_bake_finished", "nav_mesh"), &NavigationRegion3D::_bake_finished);
+ ClassDB::bind_method(D_METHOD("_bake_finished", "navigation_mesh"), &NavigationRegion3D::_bake_finished);
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "navmesh", PROPERTY_HINT_RESOURCE_TYPE, "NavigationMesh"), "set_navigation_mesh", "get_navigation_mesh");
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "navigation_mesh", PROPERTY_HINT_RESOURCE_TYPE, "NavigationMesh"), "set_navigation_mesh", "get_navigation_mesh");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "enabled"), "set_enabled", "is_enabled");
ADD_PROPERTY(PropertyInfo(Variant::INT, "navigation_layers", PROPERTY_HINT_LAYERS_3D_NAVIGATION), "set_navigation_layers", "get_navigation_layers");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "enter_cost"), "set_enter_cost", "get_enter_cost");
@@ -320,6 +320,25 @@ void NavigationRegion3D::_bind_methods() {
ADD_SIGNAL(MethodInfo("bake_finished"));
}
+#ifndef DISABLE_DEPRECATED
+// Compatibility with earlier 4.0 betas.
+bool NavigationRegion3D::_set(const StringName &p_name, const Variant &p_value) {
+ if (p_name == "navmesh") {
+ set_navigation_mesh(p_value);
+ return true;
+ }
+ return false;
+}
+
+bool NavigationRegion3D::_get(const StringName &p_name, Variant &r_ret) const {
+ if (p_name == "navmesh") {
+ r_ret = get_navigation_mesh();
+ return true;
+ }
+ return false;
+}
+#endif // DISABLE_DEPRECATED
+
void NavigationRegion3D::_navigation_changed() {
update_gizmos();
update_configuration_warnings();
@@ -339,7 +358,9 @@ void NavigationRegion3D::_navigation_map_changed(RID p_map) {
NavigationRegion3D::NavigationRegion3D() {
set_notify_transform(true);
+
region = NavigationServer3D::get_singleton()->region_create();
+ NavigationServer3D::get_singleton()->region_set_owner_id(region, get_instance_id());
NavigationServer3D::get_singleton()->region_set_enter_cost(region, get_enter_cost());
NavigationServer3D::get_singleton()->region_set_travel_cost(region, get_travel_cost());
@@ -351,8 +372,8 @@ NavigationRegion3D::NavigationRegion3D() {
}
NavigationRegion3D::~NavigationRegion3D() {
- if (navmesh.is_valid()) {
- navmesh->disconnect("changed", callable_mp(this, &NavigationRegion3D::_navigation_changed));
+ if (navigation_mesh.is_valid()) {
+ navigation_mesh->disconnect("changed", callable_mp(this, &NavigationRegion3D::_navigation_changed));
}
NavigationServer3D::get_singleton()->free(region);
@@ -390,7 +411,7 @@ void NavigationRegion3D::_update_debug_mesh() {
return;
}
- if (!navmesh.is_valid()) {
+ if (!navigation_mesh.is_valid()) {
if (debug_instance.is_valid()) {
RS::get_singleton()->instance_set_visible(debug_instance, false);
}
@@ -410,12 +431,12 @@ void NavigationRegion3D::_update_debug_mesh() {
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();
+ Vector<Vector3> vertices = navigation_mesh->get_vertices();
if (vertices.size() == 0) {
return;
}
- int polygon_count = navmesh->get_polygon_count();
+ int polygon_count = navigation_mesh->get_polygon_count();
if (polygon_count == 0) {
return;
}
@@ -448,7 +469,7 @@ void NavigationRegion3D::_update_debug_mesh() {
polygon_color.a = debug_navigation_geometry_face_color.a;
}
- Vector<int> polygon = navmesh->get_polygon(i);
+ Vector<int> polygon = navigation_mesh->get_polygon(i);
face_vertex_array.push_back(vertices[polygon[0]]);
face_vertex_array.push_back(vertices[polygon[1]]);
@@ -526,7 +547,7 @@ void NavigationRegion3D::_update_debug_edge_connections_mesh() {
return;
}
- if (!navmesh.is_valid()) {
+ if (!navigation_mesh.is_valid()) {
if (debug_edge_connections_instance.is_valid()) {
RS::get_singleton()->instance_set_visible(debug_edge_connections_instance, false);
}
diff --git a/scene/3d/navigation_region_3d.h b/scene/3d/navigation_region_3d.h
index 660538d314..811c0885a1 100644
--- a/scene/3d/navigation_region_3d.h
+++ b/scene/3d/navigation_region_3d.h
@@ -42,7 +42,7 @@ class NavigationRegion3D : public Node3D {
uint32_t navigation_layers = 1;
real_t enter_cost = 0.0;
real_t travel_cost = 1.0;
- Ref<NavigationMesh> navmesh;
+ Ref<NavigationMesh> navigation_mesh;
Thread bake_thread;
@@ -64,6 +64,11 @@ protected:
void _notification(int p_what);
static void _bind_methods();
+#ifndef DISABLE_DEPRECATED
+ bool _set(const StringName &p_name, const Variant &p_value);
+ bool _get(const StringName &p_name, Variant &r_ret) const;
+#endif // DISABLE_DEPRECATED
+
public:
void set_enabled(bool p_enabled);
bool is_enabled() const;
@@ -82,13 +87,13 @@ public:
void set_travel_cost(real_t p_travel_cost);
real_t get_travel_cost() const;
- void set_navigation_mesh(const Ref<NavigationMesh> &p_navmesh);
+ void set_navigation_mesh(const Ref<NavigationMesh> &p_navigation_mesh);
Ref<NavigationMesh> get_navigation_mesh() const;
/// Bakes the navigation mesh; once done, automatically
/// sets the new navigation mesh and emits a signal
void bake_navigation_mesh(bool p_on_thread);
- void _bake_finished(Ref<NavigationMesh> p_nav_mesh);
+ void _bake_finished(Ref<NavigationMesh> p_navigation_mesh);
PackedStringArray get_configuration_warnings() const override;
diff --git a/scene/3d/node_3d.cpp b/scene/3d/node_3d.cpp
index 1327bdd6e9..32bbea8ff3 100644
--- a/scene/3d/node_3d.cpp
+++ b/scene/3d/node_3d.cpp
@@ -188,7 +188,7 @@ void Node3D::_notification(int p_what) {
#ifdef TOOLS_ENABLED
if (Engine::get_singleton()->is_editor_hint() && get_tree()->is_node_being_edited(this)) {
- get_tree()->call_group_flags(SceneTree::GROUP_CALL_DEFERRED, SceneStringNames::get_singleton()->_spatial_editor_group, SceneStringNames::get_singleton()->_request_gizmo, this);
+ get_tree()->call_group_flags(SceneTree::GROUP_CALL_DEFERRED, SceneStringNames::get_singleton()->_spatial_editor_group, SNAME("_request_gizmo_for_id"), get_instance_id());
}
#endif
} break;
@@ -251,12 +251,22 @@ Vector3 Node3D::get_global_rotation() const {
return get_global_transform().get_basis().get_euler();
}
+Vector3 Node3D::get_global_rotation_degrees() const {
+ Vector3 radians = get_global_rotation();
+ return Vector3(Math::rad_to_deg(radians.x), Math::rad_to_deg(radians.y), Math::rad_to_deg(radians.z));
+}
+
void Node3D::set_global_rotation(const Vector3 &p_euler_rad) {
Transform3D transform = get_global_transform();
transform.basis = Basis::from_euler(p_euler_rad);
set_global_transform(transform);
}
+void Node3D::set_global_rotation_degrees(const Vector3 &p_euler_degrees) {
+ Vector3 radians(Math::deg_to_rad(p_euler_degrees.x), Math::deg_to_rad(p_euler_degrees.y), Math::deg_to_rad(p_euler_degrees.z));
+ set_global_rotation(radians);
+}
+
void Node3D::set_transform(const Transform3D &p_transform) {
data.local_transform = p_transform;
data.dirty = DIRTY_EULER_ROTATION_AND_SCALE; // Make rot/scale dirty.
@@ -440,6 +450,11 @@ void Node3D::set_rotation(const Vector3 &p_euler_rad) {
}
}
+void Node3D::set_rotation_degrees(const Vector3 &p_euler_degrees) {
+ Vector3 radians(Math::deg_to_rad(p_euler_degrees.x), Math::deg_to_rad(p_euler_degrees.y), Math::deg_to_rad(p_euler_degrees.z));
+ set_rotation(radians);
+}
+
void Node3D::set_scale(const Vector3 &p_scale) {
if (data.dirty & DIRTY_EULER_ROTATION_AND_SCALE) {
// Update rotation only if rotation and scale are dirty, as scale will be overridden.
@@ -467,6 +482,11 @@ Vector3 Node3D::get_rotation() const {
return data.euler_rotation;
}
+Vector3 Node3D::get_rotation_degrees() const {
+ Vector3 radians = get_rotation();
+ return Vector3(Math::rad_to_deg(radians.x), Math::rad_to_deg(radians.y), Math::rad_to_deg(radians.z));
+}
+
Vector3 Node3D::get_scale() const {
if (data.dirty & DIRTY_EULER_ROTATION_AND_SCALE) {
_update_rotation_and_scale();
@@ -482,7 +502,7 @@ void Node3D::update_gizmos() {
}
if (data.gizmos.is_empty()) {
- get_tree()->call_group_flags(SceneTree::GROUP_CALL_DEFERRED, SceneStringNames::get_singleton()->_spatial_editor_group, SceneStringNames::get_singleton()->_request_gizmo, this);
+ get_tree()->call_group_flags(SceneTree::GROUP_CALL_DEFERRED, SceneStringNames::get_singleton()->_spatial_editor_group, SNAME("_request_gizmo_for_id"), get_instance_id());
return;
}
if (data.gizmos_dirty) {
@@ -958,8 +978,10 @@ void Node3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_transform"), &Node3D::get_transform);
ClassDB::bind_method(D_METHOD("set_position", "position"), &Node3D::set_position);
ClassDB::bind_method(D_METHOD("get_position"), &Node3D::get_position);
- ClassDB::bind_method(D_METHOD("set_rotation", "euler"), &Node3D::set_rotation);
+ ClassDB::bind_method(D_METHOD("set_rotation", "euler_radians"), &Node3D::set_rotation);
ClassDB::bind_method(D_METHOD("get_rotation"), &Node3D::get_rotation);
+ ClassDB::bind_method(D_METHOD("set_rotation_degrees", "euler_degrees"), &Node3D::set_rotation_degrees);
+ ClassDB::bind_method(D_METHOD("get_rotation_degrees"), &Node3D::get_rotation_degrees);
ClassDB::bind_method(D_METHOD("set_rotation_order", "order"), &Node3D::set_rotation_order);
ClassDB::bind_method(D_METHOD("get_rotation_order"), &Node3D::get_rotation_order);
ClassDB::bind_method(D_METHOD("set_rotation_edit_mode", "edit_mode"), &Node3D::set_rotation_edit_mode);
@@ -975,8 +997,10 @@ void Node3D::_bind_methods() {
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("set_global_rotation", "euler_radians"), &Node3D::set_global_rotation);
ClassDB::bind_method(D_METHOD("get_global_rotation"), &Node3D::get_global_rotation);
+ ClassDB::bind_method(D_METHOD("set_global_rotation_degrees", "euler_degrees"), &Node3D::set_global_rotation_degrees);
+ ClassDB::bind_method(D_METHOD("get_global_rotation_degrees"), &Node3D::get_global_rotation_degrees);
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);
@@ -1045,6 +1069,7 @@ void Node3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM3D, "global_transform", PROPERTY_HINT_NONE, "suffix:m", PROPERTY_USAGE_NONE), "set_global_transform", "get_global_transform");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "position", PROPERTY_HINT_RANGE, "-99999,99999,0.001,or_greater,or_less,hide_slider,suffix:m", PROPERTY_USAGE_EDITOR), "set_position", "get_position");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "rotation", PROPERTY_HINT_RANGE, "-360,360,0.1,or_less,or_greater,radians", PROPERTY_USAGE_EDITOR), "set_rotation", "get_rotation");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "rotation_degrees", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_rotation_degrees", "get_rotation_degrees");
ADD_PROPERTY(PropertyInfo(Variant::QUATERNION, "quaternion", PROPERTY_HINT_HIDE_QUATERNION_EDIT, "", PROPERTY_USAGE_EDITOR), "set_quaternion", "get_quaternion");
ADD_PROPERTY(PropertyInfo(Variant::BASIS, "basis", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_basis", "get_basis");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "scale", PROPERTY_HINT_LINK, "", PROPERTY_USAGE_EDITOR), "set_scale", "get_scale");
@@ -1054,6 +1079,7 @@ void Node3D::_bind_methods() {
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_PROPERTY(PropertyInfo(Variant::VECTOR3, "global_rotation_degrees", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_global_rotation_degrees", "get_global_rotation_degrees");
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 76c1e3e22c..9558a978fd 100644
--- a/scene/3d/node_3d.h
+++ b/scene/3d/node_3d.h
@@ -172,19 +172,23 @@ public:
void set_rotation_order(EulerOrder p_order);
void set_rotation(const Vector3 &p_euler_rad);
+ void set_rotation_degrees(const Vector3 &p_euler_degrees);
void set_scale(const Vector3 &p_scale);
void set_global_position(const Vector3 &p_position);
void set_global_rotation(const Vector3 &p_euler_rad);
+ void set_global_rotation_degrees(const Vector3 &p_euler_degrees);
Vector3 get_position() const;
EulerOrder get_rotation_order() const;
Vector3 get_rotation() const;
+ Vector3 get_rotation_degrees() const;
Vector3 get_scale() const;
Vector3 get_global_position() const;
Vector3 get_global_rotation() const;
+ Vector3 get_global_rotation_degrees() const;
void set_transform(const Transform3D &p_transform);
void set_basis(const Basis &p_basis);
diff --git a/scene/3d/path_3d.cpp b/scene/3d/path_3d.cpp
index ab4cba86fb..02ab297d8e 100644
--- a/scene/3d/path_3d.cpp
+++ b/scene/3d/path_3d.cpp
@@ -182,125 +182,31 @@ void PathFollow3D::_update_transform(bool p_update_xyz_rot) {
if (bl == 0.0) {
return;
}
- real_t bi = c->get_bake_interval();
- real_t o_next = progress + bi;
- real_t o_prev = progress - bi;
-
- if (loop) {
- o_next = Math::fposmod(o_next, bl);
- o_prev = Math::fposmod(o_prev, bl);
- } else if (rotation_mode == ROTATION_ORIENTED) {
- if (o_next >= bl) {
- o_next = bl;
- }
- if (o_prev <= 0) {
- o_prev = 0;
- }
- }
-
- Vector3 pos = c->sample_baked(progress, cubic);
- Transform3D t = get_transform();
- // Vector3 pos_offset = Vector3(h_offset, v_offset, 0); not used in all cases
- // will be replaced by "Vector3(h_offset, v_offset, 0)" where it was formerly used
-
- if (rotation_mode == ROTATION_ORIENTED) {
- Vector3 forward = c->sample_baked(o_next, cubic) - pos;
-
- // Try with the previous position
- if (forward.length_squared() < CMP_EPSILON2) {
- forward = pos - c->sample_baked(o_prev, cubic);
- }
-
- if (forward.length_squared() < CMP_EPSILON2) {
- forward = Vector3(0, 0, 1);
- } else {
- forward.normalize();
- }
-
- Vector3 up = c->sample_baked_up_vector(progress, true);
- if (o_next < progress) {
- Vector3 up1 = c->sample_baked_up_vector(o_next, true);
- Vector3 axis = up.cross(up1);
-
- if (axis.length_squared() < CMP_EPSILON2) {
- axis = forward;
- } else {
- axis.normalize();
- }
-
- up.rotate(axis, up.angle_to(up1) * 0.5f);
- }
-
- Vector3 scale = t.basis.get_scale();
- Vector3 sideways = up.cross(forward).normalized();
- up = forward.cross(sideways).normalized();
-
- t.basis.set_columns(sideways, up, forward);
- t.basis.scale_local(scale);
-
- t.origin = pos + sideways * h_offset + up * v_offset;
- } else if (rotation_mode != ROTATION_NONE) {
- // perform parallel transport
- //
- // see C. Dougan, The Parallel Transport Frame, Game Programming Gems 2 for example
- // for a discussion about why not Frenet frame.
+ Transform3D t;
+ if (rotation_mode == ROTATION_NONE) {
+ Vector3 pos = c->sample_baked(progress, cubic);
t.origin = pos;
- if (p_update_xyz_rot && prev_offset != progress) { // Only update rotation if some parameter has changed - i.e. not on addition to scene tree.
- real_t sample_distance = bi * 0.01;
- Vector3 t_prev_pos_a = c->sample_baked(prev_offset - sample_distance, cubic);
- Vector3 t_prev_pos_b = c->sample_baked(prev_offset + sample_distance, cubic);
- Vector3 t_cur_pos_a = c->sample_baked(progress - sample_distance, cubic);
- Vector3 t_cur_pos_b = c->sample_baked(progress + sample_distance, cubic);
- Vector3 t_prev = (t_prev_pos_a - t_prev_pos_b).normalized();
- Vector3 t_cur = (t_cur_pos_a - t_cur_pos_b).normalized();
-
- Vector3 axis = t_prev.cross(t_cur);
- real_t dot = t_prev.dot(t_cur);
- real_t angle = Math::acos(CLAMP(dot, -1, 1));
-
- if (likely(!Math::is_zero_approx(angle))) {
- if (rotation_mode == ROTATION_Y) {
- // assuming we're referring to global Y-axis. is this correct?
- axis.x = 0;
- axis.z = 0;
- } else if (rotation_mode == ROTATION_XY) {
- axis.z = 0;
- } else if (rotation_mode == ROTATION_XYZ) {
- // all components are allowed
- }
+ } else {
+ t = c->sample_baked_with_rotation(progress, cubic, false);
+ Vector3 forward = t.basis.get_column(2); // Retain tangent for applying tilt
+ t = PathFollow3D::correct_posture(t, rotation_mode);
- if (likely(!Math::is_zero_approx(axis.length()))) {
- t.rotate_basis(axis.normalized(), angle);
- }
- }
+ // Apply tilt *after* correct_posture
+ if (tilt_enabled) {
+ const real_t tilt = c->sample_baked_tilt(progress);
- // do the additional tilting
- real_t tilt_angle = c->sample_baked_tilt(progress);
- Vector3 tilt_axis = t_cur; // not sure what tilt is supposed to do, is this correct??
-
- if (likely(!Math::is_zero_approx(Math::abs(tilt_angle)))) {
- if (rotation_mode == ROTATION_Y) {
- tilt_axis.x = 0;
- tilt_axis.z = 0;
- } else if (rotation_mode == ROTATION_XY) {
- tilt_axis.z = 0;
- } else if (rotation_mode == ROTATION_XYZ) {
- // all components are allowed
- }
-
- if (likely(!Math::is_zero_approx(tilt_axis.length()))) {
- t.rotate_basis(tilt_axis.normalized(), tilt_angle);
- }
- }
+ const Basis twist(forward, tilt);
+ t.basis = twist * t.basis;
}
-
- t.translate_local(Vector3(h_offset, v_offset, 0));
- } else {
- t.origin = pos + Vector3(h_offset, v_offset, 0);
}
+ Vector3 scale = get_transform().basis.get_scale();
+
+ t.translate_local(Vector3(h_offset, v_offset, 0));
+ t.basis.scale_local(scale);
+
set_transform(t);
}
@@ -358,6 +264,38 @@ PackedStringArray PathFollow3D::get_configuration_warnings() const {
return warnings;
}
+Transform3D PathFollow3D::correct_posture(Transform3D p_transform, PathFollow3D::RotationMode p_rotation_mode) {
+ Transform3D t = p_transform;
+
+ // Modify frame according to rotation mode.
+ if (p_rotation_mode == PathFollow3D::ROTATION_NONE) {
+ // Clear rotation.
+ t.basis = Basis();
+ } else if (p_rotation_mode == PathFollow3D::ROTATION_ORIENTED) {
+ // Y-axis always straight up.
+ Vector3 up(0.0, 1.0, 0.0);
+ Vector3 forward = t.basis.get_column(2);
+
+ t.basis = Basis::looking_at(-forward, up);
+ } else {
+ // Lock some euler axes.
+ Vector3 euler = t.basis.get_euler_normalized(EulerOrder::YXZ);
+ if (p_rotation_mode == PathFollow3D::ROTATION_Y) {
+ // Only Y-axis allowed.
+ euler[0] = 0;
+ euler[2] = 0;
+ } else if (p_rotation_mode == PathFollow3D::ROTATION_XY) {
+ // XY allowed.
+ euler[2] = 0;
+ }
+
+ Basis locked = Basis::from_euler(euler, EulerOrder::YXZ);
+ t.basis = locked;
+ }
+
+ return t;
+}
+
void PathFollow3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_progress", "progress"), &PathFollow3D::set_progress);
ClassDB::bind_method(D_METHOD("get_progress"), &PathFollow3D::get_progress);
@@ -380,6 +318,11 @@ void PathFollow3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_loop", "loop"), &PathFollow3D::set_loop);
ClassDB::bind_method(D_METHOD("has_loop"), &PathFollow3D::has_loop);
+ ClassDB::bind_method(D_METHOD("set_tilt_enabled", "enabled"), &PathFollow3D::set_tilt_enabled);
+ ClassDB::bind_method(D_METHOD("is_tilt_enabled"), &PathFollow3D::is_tilt_enabled);
+
+ ClassDB::bind_static_method("PathFollow3D", D_METHOD("correct_posture", "transform", "rotation_mode"), &PathFollow3D::correct_posture);
+
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "progress", PROPERTY_HINT_RANGE, "0,10000,0.01,or_less,or_greater,suffix:m"), "set_progress", "get_progress");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "progress_ratio", PROPERTY_HINT_RANGE, "0,1,0.0001,or_less,or_greater", PROPERTY_USAGE_EDITOR), "set_progress_ratio", "get_progress_ratio");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "h_offset", PROPERTY_HINT_NONE, "suffix:m"), "set_h_offset", "get_h_offset");
@@ -387,6 +330,7 @@ void PathFollow3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "rotation_mode", PROPERTY_HINT_ENUM, "None,Y,XY,XYZ,Oriented"), "set_rotation_mode", "get_rotation_mode");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "cubic_interp"), "set_cubic_interpolation", "get_cubic_interpolation");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "loop"), "set_loop", "has_loop");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "tilt_enabled"), "set_tilt_enabled", "is_tilt_enabled");
BIND_ENUM_CONSTANT(ROTATION_NONE);
BIND_ENUM_CONSTANT(ROTATION_Y);
@@ -397,7 +341,6 @@ void PathFollow3D::_bind_methods() {
void PathFollow3D::set_progress(real_t p_progress) {
ERR_FAIL_COND(!isfinite(p_progress));
- prev_offset = progress;
progress = p_progress;
if (path) {
@@ -409,8 +352,6 @@ void PathFollow3D::set_progress(real_t p_progress) {
if (!Math::is_zero_approx(p_progress) && Math::is_zero_approx(progress)) {
progress = path_length;
}
- } else {
- progress = CLAMP(progress, 0, path_length);
}
}
@@ -476,3 +417,11 @@ void PathFollow3D::set_loop(bool p_loop) {
bool PathFollow3D::has_loop() const {
return loop;
}
+
+void PathFollow3D::set_tilt_enabled(bool p_enable) {
+ tilt_enabled = p_enable;
+}
+
+bool PathFollow3D::is_tilt_enabled() const {
+ return tilt_enabled;
+}
diff --git a/scene/3d/path_3d.h b/scene/3d/path_3d.h
index b161b12185..9d5f694247 100644
--- a/scene/3d/path_3d.h
+++ b/scene/3d/path_3d.h
@@ -72,14 +72,16 @@ public:
ROTATION_ORIENTED
};
+ static Transform3D correct_posture(Transform3D p_transform, PathFollow3D::RotationMode p_rotation_mode);
+
private:
Path3D *path = nullptr;
- real_t prev_offset = 0.0; // Offset during the last _update_transform.
real_t progress = 0.0;
real_t h_offset = 0.0;
real_t v_offset = 0.0;
bool cubic = true;
bool loop = true;
+ bool tilt_enabled = true;
RotationMode rotation_mode = ROTATION_XYZ;
void _update_transform(bool p_update_xyz_rot = true);
@@ -106,6 +108,9 @@ public:
void set_loop(bool p_loop);
bool has_loop() const;
+ void set_tilt_enabled(bool p_enable);
+ bool is_tilt_enabled() const;
+
void set_rotation_mode(RotationMode p_rotation_mode);
RotationMode get_rotation_mode() const;
diff --git a/scene/3d/physics_body_3d.cpp b/scene/3d/physics_body_3d.cpp
index d9fa37ce74..d29f337fc8 100644
--- a/scene/3d/physics_body_3d.cpp
+++ b/scene/3d/physics_body_3d.cpp
@@ -34,8 +34,8 @@
#include "scene/scene_string_names.h"
void PhysicsBody3D::_bind_methods() {
- ClassDB::bind_method(D_METHOD("move_and_collide", "distance", "test_only", "safe_margin", "recovery_as_collision", "max_collisions"), &PhysicsBody3D::_move, DEFVAL(false), DEFVAL(0.001), DEFVAL(false), DEFVAL(1));
- ClassDB::bind_method(D_METHOD("test_move", "from", "distance", "collision", "safe_margin", "recovery_as_collision", "max_collisions"), &PhysicsBody3D::test_move, DEFVAL(Variant()), DEFVAL(0.001), DEFVAL(false), DEFVAL(1));
+ ClassDB::bind_method(D_METHOD("move_and_collide", "motion", "test_only", "safe_margin", "recovery_as_collision", "max_collisions"), &PhysicsBody3D::_move, DEFVAL(false), DEFVAL(0.001), DEFVAL(false), DEFVAL(1));
+ ClassDB::bind_method(D_METHOD("test_move", "from", "motion", "collision", "safe_margin", "recovery_as_collision", "max_collisions"), &PhysicsBody3D::test_move, DEFVAL(Variant()), DEFVAL(0.001), DEFVAL(false), DEFVAL(1));
ClassDB::bind_method(D_METHOD("set_axis_lock", "axis", "lock"), &PhysicsBody3D::set_axis_lock);
ClassDB::bind_method(D_METHOD("get_axis_lock", "axis"), &PhysicsBody3D::get_axis_lock);
@@ -80,19 +80,19 @@ TypedArray<PhysicsBody3D> PhysicsBody3D::get_collision_exceptions() {
void PhysicsBody3D::add_collision_exception_with(Node *p_node) {
ERR_FAIL_NULL(p_node);
CollisionObject3D *collision_object = Object::cast_to<CollisionObject3D>(p_node);
- ERR_FAIL_COND_MSG(!collision_object, "Collision exception only works between two CollisionObject3Ds.");
+ ERR_FAIL_COND_MSG(!collision_object, "Collision exception only works between two nodes that inherit from CollisionObject3D (such as Area3D or PhysicsBody3D).");
PhysicsServer3D::get_singleton()->body_add_collision_exception(get_rid(), collision_object->get_rid());
}
void PhysicsBody3D::remove_collision_exception_with(Node *p_node) {
ERR_FAIL_NULL(p_node);
CollisionObject3D *collision_object = Object::cast_to<CollisionObject3D>(p_node);
- ERR_FAIL_COND_MSG(!collision_object, "Collision exception only works between two CollisionObject3Ds.");
+ ERR_FAIL_COND_MSG(!collision_object, "Collision exception only works between two nodes that inherit from CollisionObject3D (such as Area3D or PhysicsBody3D).");
PhysicsServer3D::get_singleton()->body_remove_collision_exception(get_rid(), collision_object->get_rid());
}
-Ref<KinematicCollision3D> PhysicsBody3D::_move(const Vector3 &p_distance, bool p_test_only, real_t p_margin, bool p_recovery_as_collision, int p_max_collisions) {
- PhysicsServer3D::MotionParameters parameters(get_global_transform(), p_distance, p_margin);
+Ref<KinematicCollision3D> PhysicsBody3D::_move(const Vector3 &p_motion, bool p_test_only, real_t p_margin, bool p_recovery_as_collision, int p_max_collisions) {
+ PhysicsServer3D::MotionParameters parameters(get_global_transform(), p_motion, p_margin);
parameters.max_collisions = p_max_collisions;
parameters.recovery_as_collision = p_recovery_as_collision;
@@ -169,7 +169,7 @@ bool PhysicsBody3D::move_and_collide(const PhysicsServer3D::MotionParameters &p_
return colliding;
}
-bool PhysicsBody3D::test_move(const Transform3D &p_from, const Vector3 &p_distance, const Ref<KinematicCollision3D> &r_collision, real_t p_margin, bool p_recovery_as_collision, int p_max_collisions) {
+bool PhysicsBody3D::test_move(const Transform3D &p_from, const Vector3 &p_motion, const Ref<KinematicCollision3D> &r_collision, real_t p_margin, bool p_recovery_as_collision, int p_max_collisions) {
ERR_FAIL_COND_V(!is_inside_tree(), false);
PhysicsServer3D::MotionResult *r = nullptr;
@@ -181,7 +181,7 @@ bool PhysicsBody3D::test_move(const Transform3D &p_from, const Vector3 &p_distan
r = &temp_result;
}
- PhysicsServer3D::MotionParameters parameters(p_from, p_distance, p_margin);
+ PhysicsServer3D::MotionParameters parameters(p_from, p_motion, p_margin);
parameters.recovery_as_collision = p_recovery_as_collision;
return PhysicsServer3D::get_singleton()->body_test_motion(get_rid(), parameters, r);
diff --git a/scene/3d/physics_body_3d.h b/scene/3d/physics_body_3d.h
index 4b874b91d9..36b7ce774c 100644
--- a/scene/3d/physics_body_3d.h
+++ b/scene/3d/physics_body_3d.h
@@ -50,11 +50,11 @@ protected:
uint16_t locked_axis = 0;
- Ref<KinematicCollision3D> _move(const Vector3 &p_distance, bool p_test_only = false, real_t p_margin = 0.001, bool p_recovery_as_collision = false, int p_max_collisions = 1);
+ Ref<KinematicCollision3D> _move(const Vector3 &p_motion, bool p_test_only = false, real_t p_margin = 0.001, bool p_recovery_as_collision = false, int p_max_collisions = 1);
public:
bool move_and_collide(const PhysicsServer3D::MotionParameters &p_parameters, PhysicsServer3D::MotionResult &r_result, bool p_test_only = false, bool p_cancel_sliding = true);
- bool test_move(const Transform3D &p_from, const Vector3 &p_distance, const Ref<KinematicCollision3D> &r_collision = Ref<KinematicCollision3D>(), real_t p_margin = 0.001, bool p_recovery_as_collision = false, int p_max_collisions = 1);
+ bool test_move(const Transform3D &p_from, const Vector3 &p_motion, const Ref<KinematicCollision3D> &r_collision = Ref<KinematicCollision3D>(), real_t p_margin = 0.001, bool p_recovery_as_collision = false, int p_max_collisions = 1);
void set_axis_lock(PhysicsServer3D::BodyAxis p_axis, bool p_lock);
bool get_axis_lock(PhysicsServer3D::BodyAxis p_axis) const;
diff --git a/scene/3d/skeleton_3d.cpp b/scene/3d/skeleton_3d.cpp
index a1f962c690..b205c2cde0 100644
--- a/scene/3d/skeleton_3d.cpp
+++ b/scene/3d/skeleton_3d.cpp
@@ -541,7 +541,7 @@ void Skeleton3D::set_bone_name(int p_bone, const String &p_name) {
for (int i = 0; i < bone_size; i++) {
if (i != p_bone) {
- ERR_FAIL_COND(bones[i].name == p_name);
+ ERR_FAIL_COND_MSG(bones[i].name == p_name, "Skeleton3D: '" + get_name() + "', bone name: '" + p_name + "' is already exist.");
}
}
diff --git a/scene/3d/soft_body_3d.cpp b/scene/3d/soft_body_3d.cpp
index 83e3369423..1814baa9e9 100644
--- a/scene/3d/soft_body_3d.cpp
+++ b/scene/3d/soft_body_3d.cpp
@@ -607,14 +607,14 @@ TypedArray<PhysicsBody3D> SoftBody3D::get_collision_exceptions() {
void SoftBody3D::add_collision_exception_with(Node *p_node) {
ERR_FAIL_NULL(p_node);
CollisionObject3D *collision_object = Object::cast_to<CollisionObject3D>(p_node);
- ERR_FAIL_COND_MSG(!collision_object, "Collision exception only works between two CollisionObject3Ds.");
+ ERR_FAIL_COND_MSG(!collision_object, "Collision exception only works between two nodes that inherit from CollisionObject3D (such as Area3D or PhysicsBody3D).");
PhysicsServer3D::get_singleton()->soft_body_add_collision_exception(physics_rid, collision_object->get_rid());
}
void SoftBody3D::remove_collision_exception_with(Node *p_node) {
ERR_FAIL_NULL(p_node);
CollisionObject3D *collision_object = Object::cast_to<CollisionObject3D>(p_node);
- ERR_FAIL_COND_MSG(!collision_object, "Collision exception only works between two CollisionObject3Ds.");
+ ERR_FAIL_COND_MSG(!collision_object, "Collision exception only works between two nodes that inherit from CollisionObject3D (such as Area3D or PhysicsBody3D).");
PhysicsServer3D::get_singleton()->soft_body_remove_collision_exception(physics_rid, collision_object->get_rid());
}
diff --git a/scene/3d/spring_arm_3d.cpp b/scene/3d/spring_arm_3d.cpp
index f855fce318..6d8ce06524 100644
--- a/scene/3d/spring_arm_3d.cpp
+++ b/scene/3d/spring_arm_3d.cpp
@@ -31,6 +31,7 @@
#include "spring_arm_3d.h"
#include "scene/3d/camera_3d.h"
+#include "scene/resources/shape_3d.h"
void SpringArm3D::_notification(int p_what) {
switch (p_what) {
diff --git a/scene/3d/sprite_3d.cpp b/scene/3d/sprite_3d.cpp
index d69953fee5..e488ff3059 100644
--- a/scene/3d/sprite_3d.cpp
+++ b/scene/3d/sprite_3d.cpp
@@ -191,9 +191,7 @@ void SpriteBase3D::draw_texture_rect(Ref<Texture2D> p_texture, Rect2 p_dst_rect,
uint32_t v_normal;
{
- Vector3 n = normal * Vector3(0.5, 0.5, 0.5) + Vector3(0.5, 0.5, 0.5);
-
- Vector2 res = n.octahedron_encode();
+ Vector2 res = normal.octahedron_encode();
uint32_t value = 0;
value |= (uint16_t)CLAMP(res.x * 65535, 0, 65535);
value |= (uint16_t)CLAMP(res.y * 65535, 0, 65535) << 16;
diff --git a/scene/3d/visual_instance_3d.cpp b/scene/3d/visual_instance_3d.cpp
index b5b37bf837..3b21f5c03a 100644
--- a/scene/3d/visual_instance_3d.cpp
+++ b/scene/3d/visual_instance_3d.cpp
@@ -30,6 +30,7 @@
#include "visual_instance_3d.h"
+#include "core/core_string_names.h"
#include "scene/scene_string_names.h"
AABB VisualInstance3D::get_aabb() const {
@@ -101,6 +102,24 @@ bool VisualInstance3D::get_layer_mask_value(int p_layer_number) const {
return layers & (1 << (p_layer_number - 1));
}
+void VisualInstance3D::set_sorting_offset(float p_offset) {
+ sorting_offset = p_offset;
+ RenderingServer::get_singleton()->instance_set_pivot_data(instance, sorting_offset, sorting_use_aabb_center);
+}
+
+float VisualInstance3D::get_sorting_offset() const {
+ return sorting_offset;
+}
+
+void VisualInstance3D::set_sorting_use_aabb_center(bool p_enabled) {
+ sorting_use_aabb_center = p_enabled;
+ RenderingServer::get_singleton()->instance_set_pivot_data(instance, sorting_offset, sorting_use_aabb_center);
+}
+
+bool VisualInstance3D::is_sorting_use_aabb_center() const {
+ return sorting_use_aabb_center;
+}
+
void VisualInstance3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_base", "base"), &VisualInstance3D::set_base);
ClassDB::bind_method(D_METHOD("get_base"), &VisualInstance3D::get_base);
@@ -109,9 +128,17 @@ void VisualInstance3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_layer_mask"), &VisualInstance3D::get_layer_mask);
ClassDB::bind_method(D_METHOD("set_layer_mask_value", "layer_number", "value"), &VisualInstance3D::set_layer_mask_value);
ClassDB::bind_method(D_METHOD("get_layer_mask_value", "layer_number"), &VisualInstance3D::get_layer_mask_value);
+ ClassDB::bind_method(D_METHOD("set_sorting_offset", "offset"), &VisualInstance3D::set_sorting_offset);
+ ClassDB::bind_method(D_METHOD("get_sorting_offset"), &VisualInstance3D::get_sorting_offset);
+ ClassDB::bind_method(D_METHOD("set_sorting_use_aabb_center", "enabled"), &VisualInstance3D::set_sorting_use_aabb_center);
+ ClassDB::bind_method(D_METHOD("is_sorting_use_aabb_center"), &VisualInstance3D::is_sorting_use_aabb_center);
GDVIRTUAL_BIND(_get_aabb);
ADD_PROPERTY(PropertyInfo(Variant::INT, "layers", PROPERTY_HINT_LAYERS_3D_RENDER), "set_layer_mask", "get_layer_mask");
+
+ ADD_GROUP("Sorting", "sorting_");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sorting_offset"), "set_sorting_offset", "get_sorting_offset");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sorting_use_aabb_center"), "set_sorting_use_aabb_center", "is_sorting_use_aabb_center");
}
void VisualInstance3D::set_base(const RID &p_base) {
@@ -134,7 +161,13 @@ VisualInstance3D::~VisualInstance3D() {
}
void GeometryInstance3D::set_material_override(const Ref<Material> &p_material) {
+ if (material_override.is_valid()) {
+ material_override->disconnect(CoreStringNames::get_singleton()->property_list_changed, callable_mp((Object *)this, &Object::notify_property_list_changed));
+ }
material_override = p_material;
+ if (material_override.is_valid()) {
+ material_override->connect(CoreStringNames::get_singleton()->property_list_changed, callable_mp((Object *)this, &Object::notify_property_list_changed));
+ }
RS::get_singleton()->instance_geometry_set_material_override(get_instance(), p_material.is_valid() ? p_material->get_rid() : RID());
}
@@ -331,8 +364,16 @@ Variant GeometryInstance3D::get_instance_shader_parameter(const StringName &p_na
return RS::get_singleton()->instance_geometry_get_shader_parameter(get_instance(), p_name);
}
-void GeometryInstance3D::set_custom_aabb(AABB aabb) {
- RS::get_singleton()->instance_set_custom_aabb(get_instance(), aabb);
+void GeometryInstance3D::set_custom_aabb(AABB p_aabb) {
+ if (p_aabb == custom_aabb) {
+ return;
+ }
+ custom_aabb = p_aabb;
+ RS::get_singleton()->instance_set_custom_aabb(get_instance(), custom_aabb);
+}
+
+AABB GeometryInstance3D::get_custom_aabb() const {
+ return custom_aabb;
}
void GeometryInstance3D::set_lightmap_scale(LightmapScale p_scale) {
@@ -442,6 +483,7 @@ void GeometryInstance3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_ignoring_occlusion_culling"), &GeometryInstance3D::is_ignoring_occlusion_culling);
ClassDB::bind_method(D_METHOD("set_custom_aabb", "aabb"), &GeometryInstance3D::set_custom_aabb);
+ ClassDB::bind_method(D_METHOD("get_custom_aabb"), &GeometryInstance3D::get_custom_aabb);
ClassDB::bind_method(D_METHOD("get_aabb"), &GeometryInstance3D::get_aabb);
@@ -451,6 +493,7 @@ void GeometryInstance3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "transparency", PROPERTY_HINT_RANGE, "0.0,1.0,0.01"), "set_transparency", "get_transparency");
ADD_PROPERTY(PropertyInfo(Variant::INT, "cast_shadow", PROPERTY_HINT_ENUM, "Off,On,Double-Sided,Shadows Only"), "set_cast_shadows_setting", "get_cast_shadows_setting");
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::AABB, "custom_aabb", PROPERTY_HINT_NONE, "suffix:m"), "set_custom_aabb", "get_custom_aabb");
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");
diff --git a/scene/3d/visual_instance_3d.h b/scene/3d/visual_instance_3d.h
index f18bff2ddc..2d107f61d2 100644
--- a/scene/3d/visual_instance_3d.h
+++ b/scene/3d/visual_instance_3d.h
@@ -39,6 +39,8 @@ class VisualInstance3D : public Node3D {
RID base;
RID instance;
uint32_t layers = 1;
+ float sorting_offset = 0.0;
+ bool sorting_use_aabb_center = true;
protected:
void _update_visibility();
@@ -67,6 +69,12 @@ public:
void set_layer_mask_value(int p_layer_number, bool p_enable);
bool get_layer_mask_value(int p_layer_number) const;
+ void set_sorting_offset(float p_offset);
+ float get_sorting_offset() const;
+
+ void set_sorting_use_aabb_center(bool p_enabled);
+ bool is_sorting_use_aabb_center() const;
+
VisualInstance3D();
~VisualInstance3D();
};
@@ -121,6 +129,7 @@ private:
mutable HashMap<StringName, StringName> instance_shader_parameter_property_remap;
float extra_cull_margin = 0.0;
+ AABB custom_aabb;
LightmapScale lightmap_scale = LIGHTMAP_SCALE_1X;
GIMode gi_mode = GI_MODE_STATIC;
bool ignore_occlusion_culling = false;
@@ -177,7 +186,8 @@ public:
void set_instance_shader_parameter(const StringName &p_name, const Variant &p_value);
Variant get_instance_shader_parameter(const StringName &p_name) const;
- void set_custom_aabb(AABB aabb);
+ void set_custom_aabb(AABB p_aabb);
+ AABB get_custom_aabb() const;
void set_ignore_occlusion_culling(bool p_enabled);
bool is_ignoring_occlusion_culling();
diff --git a/scene/3d/xr_nodes.cpp b/scene/3d/xr_nodes.cpp
index ca7d1dfc1d..05fc73306c 100644
--- a/scene/3d/xr_nodes.cpp
+++ b/scene/3d/xr_nodes.cpp
@@ -627,7 +627,9 @@ void XROrigin3D::set_world_scale(real_t p_world_scale) {
xr_server->set_world_scale(p_world_scale);
}
-void XROrigin3D::set_current(bool p_enabled) {
+void XROrigin3D::_set_current(bool p_enabled, bool p_update_others) {
+ // We run this logic even if current already equals p_enabled as we may have set this previously before we entered our tree.
+ // This is then called a second time on NOTIFICATION_ENTER_TREE where we actually process activating this origin node.
current = p_enabled;
if (!is_inside_tree() || Engine::get_singleton()->is_editor_hint()) {
@@ -638,30 +640,38 @@ void XROrigin3D::set_current(bool p_enabled) {
set_notify_local_transform(current);
set_notify_transform(current);
+ // update XRServer with our current position
if (current) {
- for (int i = 0; i < origin_nodes.size(); i++) {
- if (origin_nodes[i] != this) {
- origin_nodes[i]->set_current(false);
- }
- }
-
- // update XRServer with our current position
XRServer *xr_server = XRServer::get_singleton();
ERR_FAIL_NULL(xr_server);
xr_server->set_world_origin(get_global_transform());
- } else {
- bool found = false;
- // We no longer have a current origin so find the first one we can make current
- for (int i = 0; !found && i < origin_nodes.size(); i++) {
- if (origin_nodes[i] != this) {
- origin_nodes[i]->set_current(true);
- found = true;
+ }
+
+ // Check if we need to update our other origin nodes accordingly
+ if (p_update_others) {
+ if (current) {
+ for (int i = 0; i < origin_nodes.size(); i++) {
+ if (origin_nodes[i] != this && origin_nodes[i]->current) {
+ origin_nodes[i]->_set_current(false, false);
+ }
+ }
+ } else {
+ // We no longer have a current origin so find the first one we can make current
+ for (int i = 0; i < origin_nodes.size(); i++) {
+ if (origin_nodes[i] != this) {
+ origin_nodes[i]->_set_current(true, false);
+ return; // we are done.
+ }
}
}
}
}
+void XROrigin3D::set_current(bool p_enabled) {
+ _set_current(p_enabled, true);
+}
+
bool XROrigin3D::is_current() const {
if (Engine::get_singleton()->is_editor_hint()) {
// return as is
diff --git a/scene/3d/xr_nodes.h b/scene/3d/xr_nodes.h
index 990fb61983..ec8e151a08 100644
--- a/scene/3d/xr_nodes.h
+++ b/scene/3d/xr_nodes.h
@@ -183,6 +183,8 @@ private:
bool current = false;
static Vector<XROrigin3D *> origin_nodes; // all origin nodes in tree
+ void _set_current(bool p_enabled, bool p_update_others);
+
protected:
void _notification(int p_what);
static void _bind_methods();
diff --git a/scene/animation/animation_blend_space_1d.cpp b/scene/animation/animation_blend_space_1d.cpp
index f30aea3bdd..4b325ee464 100644
--- a/scene/animation/animation_blend_space_1d.cpp
+++ b/scene/animation/animation_blend_space_1d.cpp
@@ -230,14 +230,14 @@ void AnimationNodeBlendSpace1D::_add_blend_point(int p_index, const Ref<Animatio
}
}
-double AnimationNodeBlendSpace1D::process(double p_time, bool p_seek, bool p_seek_root) {
+double AnimationNodeBlendSpace1D::process(double p_time, bool p_seek, bool p_is_external_seeking) {
if (blend_points_used == 0) {
return 0.0;
}
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, true);
+ return blend_node(blend_points[0].name, blend_points[0].node, p_time, p_seek, p_is_external_seeking, 1.0, FILTER_IGNORE, true);
}
double blend_pos = get_parameter(blend_position);
@@ -307,10 +307,10 @@ double AnimationNodeBlendSpace1D::process(double p_time, bool p_seek, bool p_see
for (int i = 0; i < blend_points_used; i++) {
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);
+ double remaining = blend_node(blend_points[i].name, blend_points[i].node, p_time, p_seek, p_is_external_seeking, 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);
+ } else if (sync) {
+ blend_node(blend_points[i].name, blend_points[i].node, p_time, p_seek, p_is_external_seeking, 0, FILTER_IGNORE, true);
}
}
diff --git a/scene/animation/animation_blend_space_1d.h b/scene/animation/animation_blend_space_1d.h
index 1876ccebc7..30cfe52c8e 100644
--- a/scene/animation/animation_blend_space_1d.h
+++ b/scene/animation/animation_blend_space_1d.h
@@ -98,7 +98,7 @@ public:
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;
+ double process(double p_time, bool p_seek, bool p_is_external_seeking) override;
String get_caption() const override;
Ref<AnimationNode> get_child_by_name(const StringName &p_name) override;
diff --git a/scene/animation/animation_blend_space_2d.cpp b/scene/animation/animation_blend_space_2d.cpp
index 0d8b7ba8f7..4e20429ac9 100644
--- a/scene/animation/animation_blend_space_2d.cpp
+++ b/scene/animation/animation_blend_space_2d.cpp
@@ -432,7 +432,7 @@ void AnimationNodeBlendSpace2D::_blend_triangle(const Vector2 &p_pos, const Vect
r_weights[2] = w;
}
-double AnimationNodeBlendSpace2D::process(double p_time, bool p_seek, bool p_seek_root) {
+double AnimationNodeBlendSpace2D::process(double p_time, bool p_seek, bool p_is_external_seeking) {
_update_triangles();
Vector2 blend_pos = get_parameter(blend_position);
@@ -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, true);
+ double t = blend_node(blend_points[i].name, blend_points[i].node, p_time, p_seek, p_is_external_seeking, blend_weights[j], FILTER_IGNORE, true);
if (first || t < mind) {
mind = t;
first = false;
@@ -512,8 +512,8 @@ double AnimationNodeBlendSpace2D::process(double p_time, bool p_seek, bool p_see
}
}
- if (!found) {
- blend_node(blend_points[i].name, blend_points[i].node, p_time, p_seek, p_seek_root, 0, FILTER_IGNORE, sync);
+ if (sync && !found) {
+ blend_node(blend_points[i].name, blend_points[i].node, p_time, p_seek, p_is_external_seeking, 0, FILTER_IGNORE, true);
}
}
} else {
@@ -538,21 +538,23 @@ 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 = cur_length_internal - blend_node(blend_points[cur_closest].name, blend_points[cur_closest].node, p_time, false, p_seek_root, 0.0, FILTER_IGNORE, true);
+ from = cur_length_internal - blend_node(blend_points[cur_closest].name, blend_points[cur_closest].node, p_time, false, p_is_external_seeking, 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, true);
+ mind = blend_node(blend_points[new_closest].name, blend_points[new_closest].node, from, true, p_is_external_seeking, 1.0, FILTER_IGNORE, true);
cur_length_internal = from + mind;
cur_closest = new_closest;
} else {
- mind = blend_node(blend_points[cur_closest].name, blend_points[cur_closest].node, p_time, p_seek, p_seek_root, 1.0, FILTER_IGNORE, true);
+ mind = blend_node(blend_points[cur_closest].name, blend_points[cur_closest].node, p_time, p_seek, p_is_external_seeking, 1.0, FILTER_IGNORE, true);
}
- for (int i = 0; i < blend_points_used; i++) {
- if (i != cur_closest) {
- blend_node(blend_points[i].name, blend_points[i].node, p_time, p_seek, p_seek_root, 0, FILTER_IGNORE, sync);
+ if (sync) {
+ for (int i = 0; i < blend_points_used; i++) {
+ if (i != cur_closest) {
+ blend_node(blend_points[i].name, blend_points[i].node, p_time, p_seek, p_is_external_seeking, 0, FILTER_IGNORE, true);
+ }
}
}
}
diff --git a/scene/animation/animation_blend_space_2d.h b/scene/animation/animation_blend_space_2d.h
index 250189f202..41854f73a4 100644
--- a/scene/animation/animation_blend_space_2d.h
+++ b/scene/animation/animation_blend_space_2d.h
@@ -128,7 +128,7 @@ public:
void set_y_label(const String &p_label);
String get_y_label() const;
- virtual double process(double p_time, bool p_seek, bool p_seek_root) override;
+ virtual double process(double p_time, bool p_seek, bool p_is_external_seeking) override;
virtual String get_caption() const override;
Vector2 get_closest_point(const Vector2 &p_point);
diff --git a/scene/animation/animation_blend_tree.cpp b/scene/animation/animation_blend_tree.cpp
index 0c91729a6f..26261d6da5 100644
--- a/scene/animation/animation_blend_tree.cpp
+++ b/scene/animation/animation_blend_tree.cpp
@@ -64,7 +64,7 @@ void AnimationNodeAnimation::_validate_property(PropertyInfo &p_property) const
}
}
-double AnimationNodeAnimation::process(double p_time, bool p_seek, bool p_seek_root) {
+double AnimationNodeAnimation::process(double p_time, bool p_seek, bool p_is_external_seeking) {
AnimationPlayer *ap = state->player;
ERR_FAIL_COND_V(!ap, 0);
@@ -87,40 +87,43 @@ double AnimationNodeAnimation::process(double p_time, bool p_seek, bool p_seek_r
double anim_size = (double)anim->get_length();
double step = 0.0;
double prev_time = cur_time;
- int pingponged = 0;
- bool current_backward = signbit(p_time);
+ Animation::LoopedFlag looped_flag = Animation::LOOPED_FLAG_NONE;
+ bool node_backward = play_mode == PLAY_MODE_BACKWARD;
if (p_seek) {
step = p_time - cur_time;
cur_time = p_time;
} else {
p_time *= backward ? -1.0 : 1.0;
- if (!(cur_time == anim_size && !current_backward) && !(cur_time == 0 && current_backward)) {
- cur_time = cur_time + p_time;
- step = p_time;
- }
+ cur_time = cur_time + p_time;
+ step = p_time;
}
if (anim->get_loop_mode() == Animation::LOOP_PINGPONG) {
if (!Math::is_zero_approx(anim_size)) {
- if ((int)Math::floor(abs(cur_time - prev_time) / anim_size) % 2 == 0) {
- if (prev_time >= 0 && cur_time < 0) {
- backward = !backward;
- pingponged = -1;
- }
- if (prev_time <= anim_size && cur_time > anim_size) {
- backward = !backward;
- pingponged = 1;
- }
+ if (prev_time >= 0 && cur_time < 0) {
+ backward = !backward;
+ looped_flag = node_backward ? Animation::LOOPED_FLAG_END : Animation::LOOPED_FLAG_START;
+ }
+ if (prev_time <= anim_size && cur_time > anim_size) {
+ backward = !backward;
+ looped_flag = node_backward ? Animation::LOOPED_FLAG_START : Animation::LOOPED_FLAG_END;
}
cur_time = Math::pingpong(cur_time, anim_size);
}
- } else {
- if (anim->get_loop_mode() == Animation::LOOP_LINEAR) {
- if (!Math::is_zero_approx(anim_size)) {
- cur_time = Math::fposmod(cur_time, anim_size);
+ } else if (anim->get_loop_mode() == Animation::LOOP_LINEAR) {
+ if (!Math::is_zero_approx(anim_size)) {
+ if (prev_time >= 0 && cur_time < 0) {
+ looped_flag = node_backward ? Animation::LOOPED_FLAG_END : Animation::LOOPED_FLAG_START;
}
- } else if (cur_time < 0) {
+ if (prev_time <= anim_size && cur_time > anim_size) {
+ looped_flag = node_backward ? Animation::LOOPED_FLAG_START : Animation::LOOPED_FLAG_END;
+ }
+ cur_time = Math::fposmod(cur_time, anim_size);
+ }
+ backward = false;
+ } else {
+ if (cur_time < 0) {
step += cur_time;
cur_time = 0;
} else if (cur_time > anim_size) {
@@ -128,12 +131,38 @@ double AnimationNodeAnimation::process(double p_time, bool p_seek, bool p_seek_r
cur_time = anim_size;
}
backward = false;
+
+ // If ended, don't progress animation. So set delta to 0.
+ if (p_time > 0) {
+ if (play_mode == PLAY_MODE_FORWARD) {
+ if (prev_time >= anim_size) {
+ step = 0;
+ }
+ } else {
+ if (prev_time <= 0) {
+ step = 0;
+ }
+ }
+ }
+
+ // Emit start & finish signal. Internally, the detections are the same for backward.
+ // We should use call_deferred since the track keys are still being prosessed.
+ if (state->tree) {
+ // AnimationTree uses seek to 0 "internally" to process the first key of the animation, which is used as the start detection.
+ if (p_seek && !p_is_external_seeking && cur_time == 0) {
+ state->tree->call_deferred(SNAME("emit_signal"), "animation_started", animation);
+ }
+ // Finished.
+ if (prev_time < anim_size && cur_time >= anim_size) {
+ state->tree->call_deferred(SNAME("emit_signal"), "animation_finished", animation);
+ }
+ }
}
if (play_mode == PLAY_MODE_FORWARD) {
- blend_animation(animation, cur_time, step, p_seek, p_seek_root, 1.0, pingponged);
+ blend_animation(animation, cur_time, step, p_seek, p_is_external_seeking, 1.0, looped_flag);
} else {
- blend_animation(animation, anim_size - cur_time, -step, p_seek, p_seek_root, 1.0, pingponged);
+ blend_animation(animation, anim_size - cur_time, -step, p_seek, p_is_external_seeking, 1.0, looped_flag);
}
set_parameter(time, cur_time);
@@ -273,7 +302,7 @@ bool AnimationNodeOneShot::has_filter() const {
return true;
}
-double AnimationNodeOneShot::process(double p_time, bool p_seek, bool p_seek_root) {
+double AnimationNodeOneShot::process(double p_time, bool p_seek, bool p_is_external_seeking) {
bool cur_active = get_parameter(active);
bool cur_prev_active = get_parameter(prev_active);
double cur_time = get_parameter(time);
@@ -295,9 +324,7 @@ double AnimationNodeOneShot::process(double p_time, bool p_seek, bool p_seek_roo
set_parameter(time_to_restart, cur_time_to_restart);
}
- if (!cur_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_is_external_seeking, 1.0, FILTER_IGNORE, sync);
}
bool os_seek = p_seek;
@@ -333,12 +360,11 @@ 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_is_external_seeking, 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_is_external_seeking, 1.0 - blend, FILTER_BLEND, sync); // Unlike below, processing this edge is a corner case.
}
-
- double os_rem = blend_input(1, os_seek ? cur_time : p_time, os_seek, p_seek_root, blend, FILTER_PASS, true);
+ double os_rem = blend_input(1, os_seek ? cur_time : p_time, os_seek, p_is_external_seeking, Math::is_zero_approx(blend) ? CMP_EPSILON : blend, FILTER_PASS, true); // Blend values must be more than CMP_EPSILON to process discrete keys in edge.
if (do_start) {
cur_remaining = os_rem;
@@ -420,10 +446,10 @@ bool AnimationNodeAdd2::has_filter() const {
return true;
}
-double AnimationNodeAdd2::process(double p_time, bool p_seek, bool p_seek_root) {
+double AnimationNodeAdd2::process(double p_time, bool p_seek, bool p_is_external_seeking) {
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_is_external_seeking, 1.0, FILTER_IGNORE, sync);
+ blend_input(1, p_time, p_seek, p_is_external_seeking, amount, FILTER_PASS, sync);
return rem0;
}
@@ -454,11 +480,11 @@ bool AnimationNodeAdd3::has_filter() const {
return true;
}
-double AnimationNodeAdd3::process(double p_time, bool p_seek, bool p_seek_root) {
+double AnimationNodeAdd3::process(double p_time, bool p_seek, bool p_is_external_seeking) {
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_is_external_seeking, MAX(0, -amount), FILTER_PASS, sync);
+ double rem0 = blend_input(1, p_time, p_seek, p_is_external_seeking, 1.0, FILTER_IGNORE, sync);
+ blend_input(2, p_time, p_seek, p_is_external_seeking, MAX(0, amount), FILTER_PASS, sync);
return rem0;
}
@@ -486,11 +512,11 @@ String AnimationNodeBlend2::get_caption() const {
return "Blend2";
}
-double AnimationNodeBlend2::process(double p_time, bool p_seek, bool p_seek_root) {
+double AnimationNodeBlend2::process(double p_time, bool p_seek, bool p_is_external_seeking) {
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_is_external_seeking, 1.0 - amount, FILTER_BLEND, sync);
+ double rem1 = blend_input(1, p_time, p_seek, p_is_external_seeking, amount, FILTER_PASS, sync);
return amount > 0.5 ? rem1 : rem0; //hacky but good enough
}
@@ -521,11 +547,11 @@ String AnimationNodeBlend3::get_caption() const {
return "Blend3";
}
-double AnimationNodeBlend3::process(double p_time, bool p_seek, bool p_seek_root) {
+double AnimationNodeBlend3::process(double p_time, bool p_seek, bool p_is_external_seeking) {
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_is_external_seeking, MAX(0, -amount), FILTER_IGNORE, sync);
+ double rem1 = blend_input(1, p_time, p_seek, p_is_external_seeking, 1.0 - ABS(amount), FILTER_IGNORE, sync);
+ double rem2 = blend_input(2, p_time, p_seek, p_is_external_seeking, MAX(0, amount), FILTER_IGNORE, sync);
return amount > 0.5 ? rem2 : (amount < -0.5 ? rem0 : rem1); //hacky but good enough
}
@@ -553,12 +579,12 @@ String AnimationNodeTimeScale::get_caption() const {
return "TimeScale";
}
-double AnimationNodeTimeScale::process(double p_time, bool p_seek, bool p_seek_root) {
+double AnimationNodeTimeScale::process(double p_time, bool p_seek, bool p_is_external_seeking) {
double cur_scale = get_parameter(scale);
if (p_seek) {
- return blend_input(0, p_time, true, p_seek_root, 1.0, FILTER_IGNORE, true);
+ return blend_input(0, p_time, true, p_is_external_seeking, 1.0, FILTER_IGNORE, true);
} else {
- return blend_input(0, p_time * cur_scale, false, p_seek_root, 1.0, FILTER_IGNORE, true);
+ return blend_input(0, p_time * cur_scale, false, p_is_external_seeking, 1.0, FILTER_IGNORE, true);
}
}
@@ -583,16 +609,16 @@ String AnimationNodeTimeSeek::get_caption() const {
return "Seek";
}
-double AnimationNodeTimeSeek::process(double p_time, bool p_seek, bool p_seek_root) {
+double AnimationNodeTimeSeek::process(double p_time, bool p_seek, bool p_is_external_seeking) {
double cur_seek_pos = get_parameter(seek_pos);
if (p_seek) {
- return blend_input(0, p_time, true, p_seek_root, 1.0, FILTER_IGNORE, true);
+ return blend_input(0, p_time, true, p_is_external_seeking, 1.0, FILTER_IGNORE, true);
} else if (cur_seek_pos >= 0) {
double ret = blend_input(0, cur_seek_pos, true, true, 1.0, FILTER_IGNORE, true);
set_parameter(seek_pos, -1.0); //reset
return ret;
} else {
- return blend_input(0, p_time, false, p_seek_root, 1.0, FILTER_IGNORE, true);
+ return blend_input(0, p_time, false, p_is_external_seeking, 1.0, FILTER_IGNORE, true);
}
}
@@ -700,7 +726,7 @@ bool AnimationNodeTransition::is_from_start() const {
return from_start;
}
-double AnimationNodeTransition::process(double p_time, bool p_seek, bool p_seek_root) {
+double AnimationNodeTransition::process(double p_time, bool p_seek, bool p_is_external_seeking) {
int cur_current = get_parameter(current);
int cur_prev = get_parameter(prev);
int cur_prev_current = get_parameter(prev_current);
@@ -726,15 +752,17 @@ 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 != cur_current && i != cur_prev) {
- blend_input(i, p_time, p_seek, p_seek_root, 0, FILTER_IGNORE, sync);
+ if (sync) {
+ for (int i = 0; i < enabled_inputs; i++) {
+ if (i != cur_current && i != cur_prev) {
+ blend_input(i, p_time, p_seek, p_is_external_seeking, 0, FILTER_IGNORE, true);
+ }
}
}
if (cur_prev < 0) { // process current animation, check for transition
- rem = blend_input(cur_current, p_time, p_seek, p_seek_root, 1.0, FILTER_IGNORE, true);
+ rem = blend_input(cur_current, p_time, p_seek, p_is_external_seeking, 1.0, FILTER_IGNORE, true);
if (p_seek) {
cur_time = p_time;
@@ -753,18 +781,19 @@ double AnimationNodeTransition::process(double p_time, bool p_seek, bool p_seek_
blend = xfade_curve->sample(blend);
}
+ // Blend values must be more than CMP_EPSILON to process discrete keys in edge.
+ real_t blend_inv = 1.0 - blend;
if (from_start && !p_seek && switched) { //just switched, seek to start of current
-
- rem = blend_input(cur_current, 0, true, p_seek_root, 1.0 - blend, FILTER_IGNORE, true);
+ rem = blend_input(cur_current, 0, true, p_is_external_seeking, Math::is_zero_approx(blend_inv) ? CMP_EPSILON : blend_inv, FILTER_IGNORE, true);
} else {
- rem = blend_input(cur_current, p_time, p_seek, p_seek_root, 1.0 - blend, FILTER_IGNORE, true);
+ rem = blend_input(cur_current, p_time, p_seek, p_is_external_seeking, Math::is_zero_approx(blend_inv) ? CMP_EPSILON : blend_inv, FILTER_IGNORE, true);
}
if (p_seek) {
- blend_input(cur_prev, p_time, true, p_seek_root, blend, FILTER_IGNORE, true);
+ blend_input(cur_prev, p_time, true, p_is_external_seeking, Math::is_zero_approx(blend) ? CMP_EPSILON : blend, FILTER_IGNORE, true);
cur_time = p_time;
} else {
- blend_input(cur_prev, p_time, false, p_seek_root, blend, FILTER_IGNORE, true);
+ blend_input(cur_prev, p_time, false, p_is_external_seeking, Math::is_zero_approx(blend) ? CMP_EPSILON : blend, FILTER_IGNORE, true);
cur_time += p_time;
cur_prev_xfading -= p_time;
if (cur_prev_xfading < 0) {
@@ -833,8 +862,8 @@ String AnimationNodeOutput::get_caption() const {
return "Output";
}
-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, FILTER_IGNORE, true);
+double AnimationNodeOutput::process(double p_time, bool p_seek, bool p_is_external_seeking) {
+ return blend_input(0, p_time, p_seek, p_is_external_seeking, 1.0, FILTER_IGNORE, true);
}
AnimationNodeOutput::AnimationNodeOutput() {
@@ -1046,9 +1075,9 @@ String AnimationNodeBlendTree::get_caption() const {
return "BlendTree";
}
-double AnimationNodeBlendTree::process(double p_time, bool p_seek, bool p_seek_root) {
+double AnimationNodeBlendTree::process(double p_time, bool p_seek, bool p_is_external_seeking) {
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, FILTER_IGNORE, true);
+ return _blend_node("output", nodes[SceneStringNames::get_singleton()->output].connections, this, output, p_time, p_seek, p_is_external_seeking, 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 1c31718259..52bf67b8f5 100644
--- a/scene/animation/animation_blend_tree.h
+++ b/scene/animation/animation_blend_tree.h
@@ -53,7 +53,7 @@ public:
static Vector<String> (*get_editable_animation_list)();
virtual String get_caption() const override;
- virtual double process(double p_time, bool p_seek, bool p_seek_root) override;
+ virtual double process(double p_time, bool p_seek, bool p_is_external_seeking) override;
void set_animation(const StringName &p_name);
StringName get_animation() const;
@@ -72,7 +72,7 @@ protected:
private:
PlayMode play_mode = PLAY_MODE_FORWARD;
- bool backward = false;
+ bool backward = false; // Only used by pingpong animation.
};
VARIANT_ENUM_CAST(AnimationNodeAnimation::PlayMode)
@@ -148,7 +148,7 @@ public:
MixMode get_mix_mode() const;
virtual bool has_filter() const override;
- virtual double process(double p_time, bool p_seek, bool p_seek_root) override;
+ virtual double process(double p_time, bool p_seek, bool p_is_external_seeking) override;
AnimationNodeOneShot();
};
@@ -170,7 +170,7 @@ public:
virtual String get_caption() const override;
virtual bool has_filter() const override;
- virtual double process(double p_time, bool p_seek, bool p_seek_root) override;
+ virtual double process(double p_time, bool p_seek, bool p_is_external_seeking) override;
AnimationNodeAdd2();
};
@@ -190,7 +190,7 @@ public:
virtual String get_caption() const override;
virtual bool has_filter() const override;
- virtual double process(double p_time, bool p_seek, bool p_seek_root) override;
+ virtual double process(double p_time, bool p_seek, bool p_is_external_seeking) override;
AnimationNodeAdd3();
};
@@ -208,7 +208,7 @@ public:
virtual Variant get_parameter_default_value(const StringName &p_parameter) const override;
virtual String get_caption() const override;
- virtual double process(double p_time, bool p_seek, bool p_seek_root) override;
+ virtual double process(double p_time, bool p_seek, bool p_is_external_seeking) override;
virtual bool has_filter() const override;
AnimationNodeBlend2();
@@ -228,7 +228,7 @@ public:
virtual String get_caption() const override;
- double process(double p_time, bool p_seek, bool p_seek_root) override;
+ double process(double p_time, bool p_seek, bool p_is_external_seeking) override;
AnimationNodeBlend3();
};
@@ -246,7 +246,7 @@ public:
virtual String get_caption() const override;
- double process(double p_time, bool p_seek, bool p_seek_root) override;
+ double process(double p_time, bool p_seek, bool p_is_external_seeking) override;
AnimationNodeTimeScale();
};
@@ -265,7 +265,7 @@ public:
virtual String get_caption() const override;
- double process(double p_time, bool p_seek, bool p_seek_root) override;
+ double process(double p_time, bool p_seek, bool p_is_external_seeking) override;
AnimationNodeTimeSeek();
};
@@ -331,7 +331,7 @@ public:
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;
+ double process(double p_time, bool p_seek, bool p_is_external_seeking) override;
AnimationNodeTransition();
};
@@ -341,7 +341,7 @@ class AnimationNodeOutput : public AnimationNode {
public:
virtual String get_caption() const override;
- virtual double process(double p_time, bool p_seek, bool p_seek_root) override;
+ virtual double process(double p_time, bool p_seek, bool p_is_external_seeking) override;
AnimationNodeOutput();
};
@@ -410,7 +410,7 @@ public:
void get_node_connections(List<NodeConnection> *r_connections) const;
virtual String get_caption() const override;
- virtual double process(double p_time, bool p_seek, bool p_seek_root) override;
+ virtual double process(double p_time, bool p_seek, bool p_is_external_seeking) override;
void get_node_list(List<StringName> *r_list);
diff --git a/scene/animation/animation_node_state_machine.cpp b/scene/animation/animation_node_state_machine.cpp
index 8291df8036..d54740e9b0 100644
--- a/scene/animation/animation_node_state_machine.cpp
+++ b/scene/animation/animation_node_state_machine.cpp
@@ -41,12 +41,12 @@ AnimationNodeStateMachineTransition::SwitchMode AnimationNodeStateMachineTransit
return switch_mode;
}
-void AnimationNodeStateMachineTransition::set_auto_advance(bool p_enable) {
- auto_advance = p_enable;
+void AnimationNodeStateMachineTransition::set_advance_mode(AdvanceMode p_mode) {
+ advance_mode = p_mode;
}
-bool AnimationNodeStateMachineTransition::has_auto_advance() const {
- return auto_advance;
+AnimationNodeStateMachineTransition::AdvanceMode AnimationNodeStateMachineTransition::get_advance_mode() const {
+ return advance_mode;
}
void AnimationNodeStateMachineTransition::set_advance_condition(const StringName &p_condition) {
@@ -107,15 +107,6 @@ Ref<Curve> AnimationNodeStateMachineTransition::get_xfade_curve() const {
return xfade_curve;
}
-void AnimationNodeStateMachineTransition::set_disabled(bool p_disabled) {
- disabled = p_disabled;
- emit_changed();
-}
-
-bool AnimationNodeStateMachineTransition::is_disabled() const {
- return disabled;
-}
-
void AnimationNodeStateMachineTransition::set_priority(int p_priority) {
priority = p_priority;
emit_changed();
@@ -129,8 +120,8 @@ void AnimationNodeStateMachineTransition::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_switch_mode", "mode"), &AnimationNodeStateMachineTransition::set_switch_mode);
ClassDB::bind_method(D_METHOD("get_switch_mode"), &AnimationNodeStateMachineTransition::get_switch_mode);
- ClassDB::bind_method(D_METHOD("set_auto_advance", "auto_advance"), &AnimationNodeStateMachineTransition::set_auto_advance);
- ClassDB::bind_method(D_METHOD("has_auto_advance"), &AnimationNodeStateMachineTransition::has_auto_advance);
+ ClassDB::bind_method(D_METHOD("set_advance_mode", "mode"), &AnimationNodeStateMachineTransition::set_advance_mode);
+ ClassDB::bind_method(D_METHOD("get_advance_mode"), &AnimationNodeStateMachineTransition::get_advance_mode);
ClassDB::bind_method(D_METHOD("set_advance_condition", "name"), &AnimationNodeStateMachineTransition::set_advance_condition);
ClassDB::bind_method(D_METHOD("get_advance_condition"), &AnimationNodeStateMachineTransition::get_advance_condition);
@@ -141,9 +132,6 @@ void AnimationNodeStateMachineTransition::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_xfade_curve", "curve"), &AnimationNodeStateMachineTransition::set_xfade_curve);
ClassDB::bind_method(D_METHOD("get_xfade_curve"), &AnimationNodeStateMachineTransition::get_xfade_curve);
- ClassDB::bind_method(D_METHOD("set_disabled", "disabled"), &AnimationNodeStateMachineTransition::set_disabled);
- ClassDB::bind_method(D_METHOD("is_disabled"), &AnimationNodeStateMachineTransition::is_disabled);
-
ClassDB::bind_method(D_METHOD("set_priority", "priority"), &AnimationNodeStateMachineTransition::set_priority);
ClassDB::bind_method(D_METHOD("get_priority"), &AnimationNodeStateMachineTransition::get_priority);
@@ -155,17 +143,19 @@ void AnimationNodeStateMachineTransition::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "priority", PROPERTY_HINT_RANGE, "0,32,1"), "set_priority", "get_priority");
ADD_GROUP("Switch", "");
ADD_PROPERTY(PropertyInfo(Variant::INT, "switch_mode", PROPERTY_HINT_ENUM, "Immediate,Sync,At End"), "set_switch_mode", "get_switch_mode");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "auto_advance"), "set_auto_advance", "has_auto_advance");
ADD_GROUP("Advance", "advance_");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "advance_mode", PROPERTY_HINT_ENUM, "Disabled,Enabled,Auto"), "set_advance_mode", "get_advance_mode");
ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "advance_condition"), "set_advance_condition", "get_advance_condition");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "advance_expression", PROPERTY_HINT_EXPRESSION, ""), "set_advance_expression", "get_advance_expression");
- ADD_GROUP("Disabling", "");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "disabled"), "set_disabled", "is_disabled");
BIND_ENUM_CONSTANT(SWITCH_MODE_IMMEDIATE);
BIND_ENUM_CONSTANT(SWITCH_MODE_SYNC);
BIND_ENUM_CONSTANT(SWITCH_MODE_AT_END);
+ BIND_ENUM_CONSTANT(ADVANCE_MODE_DISABLED);
+ BIND_ENUM_CONSTANT(ADVANCE_MODE_ENABLED);
+ BIND_ENUM_CONSTANT(ADVANCE_MODE_AUTO);
+
ADD_SIGNAL(MethodInfo("advance_condition_changed"));
}
@@ -234,7 +224,7 @@ bool AnimationNodeStateMachinePlayback::_travel(AnimationNodeStateMachine *p_sta
//build open list
for (int i = 0; i < p_state_machine->transitions.size(); i++) {
- if (p_state_machine->transitions[i].transition->is_disabled()) {
+ if (p_state_machine->transitions[i].transition->get_advance_mode() == AnimationNodeStateMachineTransition::ADVANCE_MODE_DISABLED) {
continue;
}
@@ -279,7 +269,7 @@ bool AnimationNodeStateMachinePlayback::_travel(AnimationNodeStateMachine *p_sta
StringName transition = p_state_machine->transitions[least_cost_transition->get()].local_to;
for (int i = 0; i < p_state_machine->transitions.size(); i++) {
- if (p_state_machine->transitions[i].transition->is_disabled()) {
+ if (p_state_machine->transitions[i].transition->get_advance_mode() == AnimationNodeStateMachineTransition::ADVANCE_MODE_DISABLED) {
continue;
}
@@ -332,11 +322,11 @@ bool AnimationNodeStateMachinePlayback::_travel(AnimationNodeStateMachine *p_sta
return true;
}
-double AnimationNodeStateMachinePlayback::process(AnimationNodeStateMachine *p_state_machine, double p_time, bool p_seek, bool p_seek_root) {
+double AnimationNodeStateMachinePlayback::process(AnimationNodeStateMachine *p_state_machine, double p_time, bool p_seek, bool p_is_external_seeking) {
if (p_time == -1) {
Ref<AnimationNodeStateMachine> anodesm = p_state_machine->states[current].node;
if (anodesm.is_valid()) {
- p_state_machine->blend_node(current, p_state_machine->states[current].node, -1, p_seek, p_seek_root, 0, AnimationNode::FILTER_IGNORE, true);
+ p_state_machine->blend_node(current, p_state_machine->states[current].node, -1, p_seek, p_is_external_seeking, 0, AnimationNode::FILTER_IGNORE, true);
}
playing = false;
return 0;
@@ -379,6 +369,7 @@ double AnimationNodeStateMachinePlayback::process(AnimationNodeStateMachine *p_s
// can't travel, then teleport
path.clear();
current = start_request;
+ play_start = true;
}
start_request = StringName(); //clear start request
}
@@ -405,7 +396,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, true);
+ len_current = p_state_machine->blend_node(current, p_state_machine->states[current].node, 0, true, p_is_external_seeking, 1.0, AnimationNode::FILTER_IGNORE, true);
pos_current = 0;
}
@@ -424,7 +415,7 @@ double AnimationNodeStateMachinePlayback::process(AnimationNodeStateMachine *p_s
fading_pos += p_time;
}
fade_blend = MIN(1.0, fading_pos / fading_time);
- if (fade_blend >= 1.0) {
+ if (fade_blend > 1.0) {
fading_from = StringName();
}
}
@@ -433,10 +424,11 @@ double AnimationNodeStateMachinePlayback::process(AnimationNodeStateMachine *p_s
if (current_curve.is_valid()) {
fade_blend = current_curve->sample(fade_blend);
}
- 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);
+ double rem = p_state_machine->blend_node(current, p_state_machine->states[current].node, p_time, p_seek, p_is_external_seeking, Math::is_zero_approx(fade_blend) ? CMP_EPSILON : fade_blend, AnimationNode::FILTER_IGNORE, true); // Blend values must be more than CMP_EPSILON to process discrete keys in edge.
+ double fade_blend_inv = 1.0 - fade_blend;
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, true);
+ p_state_machine->blend_node(fading_from, p_state_machine->states[fading_from].node, p_time, p_seek, p_is_external_seeking, Math::is_zero_approx(fade_blend_inv) ? CMP_EPSILON : fade_blend_inv, AnimationNode::FILTER_IGNORE, true); // Blend values must be more than CMP_EPSILON to process discrete keys in edge.
}
//guess playback position
@@ -445,19 +437,19 @@ double AnimationNodeStateMachinePlayback::process(AnimationNodeStateMachine *p_s
}
{ //advance and loop check
- float next_pos = len_current - rem;
+ double next_pos = len_current - rem;
end_loop = next_pos < pos_current;
pos_current = next_pos; //looped
}
//find next
StringName next;
- float next_xfade = 0.0;
+ double next_xfade = 0.0;
AnimationNodeStateMachineTransition::SwitchMode switch_mode = AnimationNodeStateMachineTransition::SWITCH_MODE_IMMEDIATE;
if (path.size()) {
for (int i = 0; i < p_state_machine->transitions.size(); i++) {
- if (p_state_machine->transitions[i].transition->is_disabled()) {
+ if (p_state_machine->transitions[i].transition->get_advance_mode() == AnimationNodeStateMachineTransition::ADVANCE_MODE_DISABLED) {
continue;
}
@@ -473,7 +465,7 @@ double AnimationNodeStateMachinePlayback::process(AnimationNodeStateMachine *p_s
int auto_advance_to = -1;
for (int i = 0; i < p_state_machine->transitions.size(); i++) {
- if (p_state_machine->transitions[i].transition->is_disabled()) {
+ if (p_state_machine->transitions[i].transition->get_advance_mode() == AnimationNodeStateMachineTransition::ADVANCE_MODE_DISABLED) {
continue;
}
@@ -541,7 +533,7 @@ double AnimationNodeStateMachinePlayback::process(AnimationNodeStateMachine *p_s
int auto_advance_to = -1;
for (int i = 0; i < prev_state_machine->transitions.size(); i++) {
- if (prev_state_machine->transitions[i].transition->is_disabled()) {
+ if (prev_state_machine->transitions[i].transition->get_advance_mode() == AnimationNodeStateMachineTransition::ADVANCE_MODE_DISABLED) {
continue;
}
@@ -593,19 +585,17 @@ double AnimationNodeStateMachinePlayback::process(AnimationNodeStateMachine *p_s
{ // if the current node is a state machine, update the "playing" variable to false by passing -1 in p_time
Ref<AnimationNodeStateMachine> anodesm = p_state_machine->states[current].node;
if (anodesm.is_valid()) {
- p_state_machine->blend_node(current, p_state_machine->states[current].node, -1, p_seek, p_seek_root, 0, AnimationNode::FILTER_IGNORE, true);
+ p_state_machine->blend_node(current, p_state_machine->states[current].node, -1, p_seek, p_is_external_seeking, 0, AnimationNode::FILTER_IGNORE, true);
}
}
current = next;
+ len_current = p_state_machine->blend_node(current, p_state_machine->states[current].node, 0, true, p_is_external_seeking, CMP_EPSILON, AnimationNode::FILTER_IGNORE, true); // Process next node's first key in here.
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, 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, true);
-
+ p_state_machine->blend_node(current, p_state_machine->states[current].node, pos_current, true, p_is_external_seeking, 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, true);
pos_current = 0;
}
@@ -630,14 +620,14 @@ double AnimationNodeStateMachinePlayback::process(AnimationNodeStateMachine *p_s
}
bool AnimationNodeStateMachinePlayback::_check_advance_condition(const Ref<AnimationNodeStateMachine> state_machine, const Ref<AnimationNodeStateMachineTransition> transition) const {
- if (transition->has_auto_advance()) {
- return true;
+ if (transition->get_advance_mode() != AnimationNodeStateMachineTransition::ADVANCE_MODE_AUTO) {
+ return false;
}
StringName advance_condition_name = transition->get_advance_condition_name();
- if (advance_condition_name != StringName() && bool(state_machine->get_parameter(advance_condition_name))) {
- return true;
+ if (advance_condition_name != StringName() && !bool(state_machine->get_parameter(advance_condition_name))) {
+ return false;
}
if (transition->expression.is_valid()) {
@@ -647,20 +637,18 @@ bool AnimationNodeStateMachinePlayback::_check_advance_condition(const Ref<Anima
NodePath advance_expression_base_node_path = tree_base->get_advance_expression_base_node();
Node *expression_base = tree_base->get_node_or_null(advance_expression_base_node_path);
- WARN_PRINT_ONCE("Animation transition has a valid expression, but no expression base node was set on its AnimationTree.");
-
if (expression_base) {
Ref<Expression> exp = transition->expression;
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;
- }
+ if (exp->has_execute_failed() || !ret) {
+ return false;
}
+ } else {
+ WARN_PRINT_ONCE("Animation transition has a valid expression, but no expression base node was set on its AnimationTree.");
}
}
- return false;
+ return true;
}
void AnimationNodeStateMachinePlayback::_bind_methods() {
@@ -836,7 +824,8 @@ void AnimationNodeStateMachine::rename_node(const StringName &p_name, const Stri
_rename_transitions(p_name, p_new_name);
- emit_signal("tree_changed");
+ emit_changed();
+ emit_signal(SNAME("tree_changed"));
}
void AnimationNodeStateMachine::_rename_transitions(const StringName &p_name, const StringName &p_new_name) {
@@ -879,9 +868,8 @@ void AnimationNodeStateMachine::_rename_transitions(const StringName &p_name, co
transitions.write[i].to = p_new_name;
}
-
- updating_transitions = false;
}
+ updating_transitions = false;
}
void AnimationNodeStateMachine::get_node_list(List<StringName> *r_nodes) const {
@@ -1133,11 +1121,11 @@ Vector2 AnimationNodeStateMachine::get_graph_offset() const {
return graph_offset;
}
-double AnimationNodeStateMachine::process(double p_time, bool p_seek, bool p_seek_root) {
+double AnimationNodeStateMachine::process(double p_time, bool p_seek, bool p_is_external_seeking) {
Ref<AnimationNodeStateMachinePlayback> playback_new = get_parameter(playback);
ERR_FAIL_COND_V(playback_new.is_null(), 0.0);
- return playback_new->process(this, p_time, p_seek, p_seek_root);
+ return playback_new->process(this, p_time, p_seek, p_is_external_seeking);
}
String AnimationNodeStateMachine::get_caption() const {
@@ -1293,6 +1281,7 @@ Vector2 AnimationNodeStateMachine::get_node_position(const StringName &p_name) c
}
void AnimationNodeStateMachine::_tree_changed() {
+ emit_changed();
emit_signal(SNAME("tree_changed"));
}
diff --git a/scene/animation/animation_node_state_machine.h b/scene/animation/animation_node_state_machine.h
index cdb4c7528a..83b5e66491 100644
--- a/scene/animation/animation_node_state_machine.h
+++ b/scene/animation/animation_node_state_machine.h
@@ -44,14 +44,19 @@ public:
SWITCH_MODE_AT_END,
};
+ enum AdvanceMode {
+ ADVANCE_MODE_DISABLED,
+ ADVANCE_MODE_ENABLED,
+ ADVANCE_MODE_AUTO,
+ };
+
private:
SwitchMode switch_mode = SWITCH_MODE_IMMEDIATE;
- bool auto_advance = false;
+ AdvanceMode advance_mode = ADVANCE_MODE_ENABLED;
StringName advance_condition;
StringName advance_condition_name;
float xfade_time = 0.0;
Ref<Curve> xfade_curve;
- bool disabled = false;
int priority = 1;
String advance_expression;
@@ -65,8 +70,8 @@ public:
void set_switch_mode(SwitchMode p_mode);
SwitchMode get_switch_mode() const;
- void set_auto_advance(bool p_enable);
- bool has_auto_advance() const;
+ void set_advance_mode(AdvanceMode p_mode);
+ AdvanceMode get_advance_mode() const;
void set_advance_condition(const StringName &p_condition);
StringName get_advance_condition() const;
@@ -82,9 +87,6 @@ public:
void set_xfade_curve(const Ref<Curve> &p_curve);
Ref<Curve> get_xfade_curve() const;
- void set_disabled(bool p_disabled);
- bool is_disabled() const;
-
void set_priority(int p_priority);
int get_priority() const;
@@ -92,6 +94,7 @@ public:
};
VARIANT_ENUM_CAST(AnimationNodeStateMachineTransition::SwitchMode)
+VARIANT_ENUM_CAST(AnimationNodeStateMachineTransition::AdvanceMode)
class AnimationNodeStateMachine;
@@ -111,8 +114,8 @@ class AnimationNodeStateMachinePlayback : public Resource {
StringName next;
};
- float len_current = 0.0;
- float pos_current = 0.0;
+ double len_current = 0.0;
+ double pos_current = 0.0;
bool end_loop = false;
StringName current;
@@ -133,7 +136,7 @@ class AnimationNodeStateMachinePlayback : public Resource {
bool _travel(AnimationNodeStateMachine *p_state_machine, const StringName &p_travel);
- double process(AnimationNodeStateMachine *p_state_machine, double p_time, bool p_seek, bool p_seek_root);
+ double process(AnimationNodeStateMachine *p_state_machine, double p_time, bool p_seek, bool p_is_external_seeking);
bool _check_advance_condition(const Ref<AnimationNodeStateMachine> p_state_machine, const Ref<AnimationNodeStateMachineTransition> p_transition) const;
@@ -239,7 +242,7 @@ public:
void set_graph_offset(const Vector2 &p_offset);
Vector2 get_graph_offset() const;
- virtual double process(double p_time, bool p_seek, bool p_seek_root) override;
+ virtual double process(double p_time, bool p_seek, bool p_is_external_seeking) override;
virtual String get_caption() const override;
virtual Ref<AnimationNode> get_child_by_name(const StringName &p_name) override;
diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp
index 59930a3fbb..ff20724f89 100644
--- a/scene/animation/animation_player.cpp
+++ b/scene/animation/animation_player.cpp
@@ -468,7 +468,7 @@ Variant AnimationPlayer::_post_process_key_value(const Ref<Animation> &p_anim, i
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) {
+void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double p_prev_time, double p_time, double p_delta, float p_interp, bool p_is_current, bool p_seeked, bool p_started, Animation::LoopedFlag p_looped_flag) {
_ensure_node_caches(p_anim);
ERR_FAIL_COND(p_anim->node_cache.size() != p_anim->animation->get_track_count());
@@ -664,7 +664,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double
}
}
- if (update_mode == Animation::UPDATE_CONTINUOUS || update_mode == Animation::UPDATE_CAPTURE || (p_delta == 0 && update_mode == Animation::UPDATE_DISCRETE)) { //delta == 0 means seek
+ if (update_mode == Animation::UPDATE_CONTINUOUS || update_mode == Animation::UPDATE_CAPTURE) {
Variant value = a->value_track_interpolate(i, p_time);
if (value == Variant()) {
@@ -681,9 +681,23 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double
pa->value_accum = Animation::interpolate_variant(pa->value_accum, value, p_interp);
}
- } else if (p_is_current && p_delta != 0) {
+ } else {
List<int> indices;
- a->value_track_get_key_indices(i, p_time, p_delta, &indices, p_pingponged);
+
+ if (p_seeked) {
+ int found_key = a->track_find_key(i, p_time);
+ if (found_key >= 0) {
+ indices.push_back(found_key);
+ }
+ } else {
+ if (p_started) {
+ int first_key = a->track_find_key(i, p_prev_time, Animation::FIND_MODE_EXACT);
+ if (first_key >= 0) {
+ indices.push_back(first_key);
+ }
+ }
+ a->track_get_key_indices_in_range(i, p_time, p_delta, &indices, p_looped_flag);
+ }
for (int &F : indices) {
Variant value = a->track_get_key_value(i, F);
@@ -734,16 +748,26 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double
if (!nc->node) {
continue;
}
- if (p_delta == 0) {
- continue;
- }
if (!p_is_current) {
break;
}
List<int> indices;
- a->method_track_get_key_indices(i, p_time, p_delta, &indices, p_pingponged);
+ if (p_seeked) {
+ int found_key = a->track_find_key(i, p_time);
+ if (found_key >= 0) {
+ indices.push_back(found_key);
+ }
+ } else {
+ if (p_started) {
+ int first_key = a->track_find_key(i, p_prev_time, Animation::FIND_MODE_EXACT);
+ if (first_key >= 0) {
+ indices.push_back(first_key);
+ }
+ }
+ a->track_get_key_indices_in_range(i, p_time, p_delta, &indices, p_looped_flag);
+ }
for (int &E : indices) {
StringName method = a->method_track_get_name(i, E);
@@ -787,9 +811,6 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double
if (!nc->node) {
continue;
}
- if (p_delta == 0) {
- continue;
- }
if (p_seeked) {
//find whatever should be playing
@@ -833,7 +854,13 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double
} else {
//find stuff to play
List<int> to_play;
- a->track_get_key_indices_in_range(i, p_time, p_delta, &to_play, p_pingponged);
+ if (p_started) {
+ int first_key = a->track_find_key(i, p_prev_time, Animation::FIND_MODE_EXACT);
+ if (first_key >= 0) {
+ to_play.push_back(first_key);
+ }
+ }
+ a->track_get_key_indices_in_range(i, p_time, p_delta, &to_play, p_looped_flag);
if (to_play.size()) {
int idx = to_play.back()->get();
@@ -893,7 +920,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double
continue;
}
- if (p_delta == 0 || p_seeked) {
+ if (p_seeked) {
//seek
int idx = a->track_find_key(i, p_time);
if (idx < 0) {
@@ -928,9 +955,9 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double
break;
}
- if (player->is_playing() || p_seeked) {
- player->play(anim_name);
+ if (player->is_playing()) {
player->seek(at_anim_pos);
+ player->play(anim_name);
nc->animation_playing = true;
playing_caches.insert(nc);
} else {
@@ -940,7 +967,13 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double
} else {
//find stuff to play
List<int> to_play;
- a->track_get_key_indices_in_range(i, p_time, p_delta, &to_play, p_pingponged);
+ if (p_started) {
+ int first_key = a->track_find_key(i, p_prev_time, Animation::FIND_MODE_EXACT);
+ if (first_key >= 0) {
+ to_play.push_back(first_key);
+ }
+ }
+ a->track_get_key_indices_in_range(i, p_time, p_delta, &to_play, p_looped_flag);
if (to_play.size()) {
int idx = to_play.back()->get();
@@ -952,8 +985,8 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double
nc->animation_playing = false;
}
} else {
+ player->seek(0.0);
player->play(anim_name);
- player->seek(0.0, true);
nc->animation_playing = true;
playing_caches.insert(nc);
}
@@ -968,9 +1001,10 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double
void AnimationPlayer::_animation_process_data(PlaybackData &cd, double p_delta, float p_blend, bool p_seeked, bool p_started) {
double delta = p_delta * speed_scale * cd.speed_scale;
double next_pos = cd.pos + delta;
+ bool backwards = signbit(delta); // Negative zero means playing backwards too.
real_t len = cd.from->animation->get_length();
- int pingponged = 0;
+ Animation::LoopedFlag looped_flag = Animation::LOOPED_FLAG_NONE;
switch (cd.from->animation->get_loop_mode()) {
case Animation::LOOP_NONE: {
@@ -979,64 +1013,57 @@ void AnimationPlayer::_animation_process_data(PlaybackData &cd, double p_delta,
} else if (next_pos > len) {
next_pos = len;
}
-
- bool backwards = signbit(delta); // Negative zero means playing backwards too
- delta = next_pos - cd.pos; // Fix delta (after determination of backwards because negative zero is lost here)
-
- if (&cd == &playback.current) {
- if (!backwards && cd.pos <= len && next_pos == len) {
- //playback finished
- end_reached = true;
- end_notify = cd.pos < len; // Notify only if not already at the end
- }
-
- if (backwards && cd.pos >= 0 && next_pos == 0) {
- //playback finished
- end_reached = true;
- end_notify = cd.pos > 0; // Notify only if not already at the beginning
- }
- }
+ delta = next_pos - cd.pos; // Fix delta (after determination of backwards because negative zero is lost here).
} break;
case Animation::LOOP_LINEAR: {
- double looped_next_pos = Math::fposmod(next_pos, (double)len);
- if (looped_next_pos == 0 && next_pos != 0) {
- // Loop multiples of the length to it, rather than 0
- // so state at time=length is previewable in the editor
- next_pos = len;
- } else {
- next_pos = looped_next_pos;
+ if (next_pos < 0 && cd.pos >= 0) {
+ looped_flag = Animation::LOOPED_FLAG_START;
+ }
+ if (next_pos > len && cd.pos <= len) {
+ looped_flag = Animation::LOOPED_FLAG_END;
}
+ next_pos = Math::fposmod(next_pos, (double)len);
} break;
case Animation::LOOP_PINGPONG: {
- if ((int)Math::floor(abs(next_pos - cd.pos) / len) % 2 == 0) {
- if (next_pos < 0 && cd.pos >= 0) {
- cd.speed_scale *= -1.0;
- pingponged = -1;
- }
- if (next_pos > len && cd.pos <= len) {
- cd.speed_scale *= -1.0;
- pingponged = 1;
- }
+ if (next_pos < 0 && cd.pos >= 0) {
+ cd.speed_scale *= -1.0;
+ looped_flag = Animation::LOOPED_FLAG_START;
}
- double looped_next_pos = Math::pingpong(next_pos, (double)len);
- if (looped_next_pos == 0 && next_pos != 0) {
- // Loop multiples of the length to it, rather than 0
- // so state at time=length is previewable in the editor
- next_pos = len;
- } else {
- next_pos = looped_next_pos;
+ if (next_pos > len && cd.pos <= len) {
+ cd.speed_scale *= -1.0;
+ looped_flag = Animation::LOOPED_FLAG_END;
}
+ next_pos = Math::pingpong(next_pos, (double)len);
} break;
default:
break;
}
+ double prev_pos = cd.pos; // The animation may be changed during process, so it is safer that the state is changed before process.
cd.pos = next_pos;
- _animation_process_animation(cd.from, cd.pos, delta, p_blend, &cd == &playback.current, p_seeked, p_started, pingponged);
+ AnimationData *prev_from = cd.from;
+ _animation_process_animation(cd.from, prev_pos, cd.pos, delta, p_blend, &cd == &playback.current, p_seeked, p_started, looped_flag);
+
+ // End detection.
+ if (cd.from->animation->get_loop_mode() == Animation::LOOP_NONE) {
+ if (prev_from != playback.current.from) {
+ return; // Animation has been changed in the process (may be caused by method track), abort process.
+ }
+ if (!backwards && prev_pos <= len && next_pos == len) {
+ // Playback finished.
+ end_reached = true;
+ end_notify = prev_pos < len; // Notify only if not already at the end.
+ }
+ if (backwards && prev_pos >= 0 && next_pos == 0) {
+ // Playback finished.
+ end_reached = true;
+ end_notify = prev_pos > 0; // Notify only if not already at the beginning.
+ }
+ }
}
void AnimationPlayer::_animation_process2(double p_delta, bool p_started) {
@@ -1044,24 +1071,35 @@ void AnimationPlayer::_animation_process2(double p_delta, bool p_started) {
accum_pass++;
- _animation_process_data(c.current, p_delta, 1.0f, c.seeked && p_delta != 0, p_started);
+ bool seeked = c.seeked; // The animation may be changed during process, so it is safer that the state is changed before process.
+
if (p_delta != 0) {
c.seeked = false;
}
- List<Blend>::Element *prev = nullptr;
- for (List<Blend>::Element *E = c.blend.back(); E; E = prev) {
+ float blend = 1.0; // First animation we play at 100% blend
+
+ List<Blend>::Element *next = NULL;
+ for (List<Blend>::Element *E = c.blend.front(); E; E = next) {
Blend &b = E->get();
- float blend = b.blend_left / b.blend_time;
+ // Note: There may be issues if an animation event triggers an animation change while this blend is active,
+ // so it is best to use "deferred" calls instead of "immediate" for animation events that can trigger new animations.
_animation_process_data(b.data, p_delta, blend, false, false);
-
+ blend = 1.0 - b.blend_left / b.blend_time; // This is how much to blend the NEXT animation
b.blend_left -= Math::absf(speed_scale * p_delta);
-
- prev = E->prev();
+ next = E->next();
if (b.blend_left < 0) {
- c.blend.erase(E);
+ // If the blend of this has finished, we need to remove ALL the previous blends
+ List<Blend>::Element *prev;
+ while (E) {
+ prev = E->prev();
+ c.blend.erase(E);
+ E = prev;
+ }
}
}
+
+ _animation_process_data(c.current, p_delta, blend, seeked, p_started);
}
void AnimationPlayer::_animation_update_transforms() {
@@ -1101,8 +1139,6 @@ void AnimationPlayer::_animation_update_transforms() {
}
}
- cache_update_size = 0;
-
for (int i = 0; i < cache_update_prop_size; i++) {
TrackNodeCache::PropertyAnim *pa = cache_update_prop[i];
@@ -1164,29 +1200,35 @@ void AnimationPlayer::_animation_update_transforms() {
}
}
- cache_update_prop_size = 0;
-
for (int i = 0; i < cache_update_bezier_size; i++) {
TrackNodeCache::BezierAnim *ba = cache_update_bezier[i];
ERR_CONTINUE(ba->accum_pass != accum_pass);
ba->object->set_indexed(ba->bezier_property, ba->bezier_accum);
}
-
- cache_update_bezier_size = 0;
}
void AnimationPlayer::_animation_process(double p_delta) {
if (playback.current.from) {
end_reached = false;
end_notify = false;
- _animation_process2(p_delta, playback.started);
+ bool started = playback.started; // The animation may be changed during process, so it is safer that the state is changed before process.
if (playback.started) {
playback.started = false;
}
+ cache_update_size = 0;
+ cache_update_prop_size = 0;
+ cache_update_bezier_size = 0;
+
+ AnimationData *prev_from = playback.current.from;
+ _animation_process2(p_delta, started);
+ if (prev_from != playback.current.from) {
+ return; // Animation has been changed in the process (may be caused by method track), abort process.
+ }
_animation_update_transforms();
+
if (end_reached) {
if (queued.size()) {
String old = playback.assigned;
@@ -1274,23 +1316,6 @@ void AnimationPlayer::_animation_set_cache_update() {
}
void AnimationPlayer::_animation_added(const StringName &p_name, const StringName &p_library) {
- {
- int at_pos = -1;
-
- for (uint32_t i = 0; i < animation_libraries.size(); i++) {
- if (animation_libraries[i].name == p_library) {
- at_pos = i;
- break;
- }
- }
-
- ERR_FAIL_COND(at_pos == -1);
-
- ERR_FAIL_COND(!animation_libraries[at_pos].library->animations.has(p_name));
-
- _ref_anim(animation_libraries[at_pos].library->animations[p_name]);
- }
-
_animation_set_cache_update();
}
@@ -1301,11 +1326,6 @@ void AnimationPlayer::_animation_removed(const StringName &p_name, const StringN
return; // No need to update because not the one from the library being used.
}
- AnimationData animation_data = animation_set[name];
- if (animation_data.animation_library == p_library) {
- _unref_anim(animation_data.animation);
- }
-
_animation_set_cache_update();
// Erase blends if needed
@@ -1401,10 +1421,7 @@ Error AnimationPlayer::add_animation_library(const StringName &p_name, const Ref
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_removed).bind(p_name));
ald.library->connect(SNAME("animation_renamed"), callable_mp(this, &AnimationPlayer::_animation_renamed).bind(p_name));
-
- for (const KeyValue<StringName, Ref<Animation>> &K : ald.library->animations) {
- _ref_anim(K.value);
- }
+ ald.library->connect(SNAME("animation_changed"), callable_mp(this, &AnimationPlayer::_animation_changed));
_animation_set_cache_update();
@@ -1428,27 +1445,16 @@ void AnimationPlayer::remove_animation_library(const StringName &p_name) {
animation_libraries[at_pos].library->disconnect(SNAME("animation_added"), callable_mp(this, &AnimationPlayer::_animation_added));
animation_libraries[at_pos].library->disconnect(SNAME("animation_removed"), callable_mp(this, &AnimationPlayer::_animation_removed));
animation_libraries[at_pos].library->disconnect(SNAME("animation_renamed"), callable_mp(this, &AnimationPlayer::_animation_renamed));
+ animation_libraries[at_pos].library->disconnect(SNAME("animation_changed"), callable_mp(this, &AnimationPlayer::_animation_changed));
stop();
- for (const KeyValue<StringName, Ref<Animation>> &K : animation_libraries[at_pos].library->animations) {
- _unref_anim(K.value);
- }
-
animation_libraries.remove_at(at_pos);
_animation_set_cache_update();
notify_property_list_changed();
}
-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), CONNECT_REFERENCE_COUNTED);
-}
-
-void AnimationPlayer::_unref_anim(const Ref<Animation> &p_anim) {
- Ref<Animation>(p_anim)->disconnect(SceneStringNames::get_singleton()->tracks_changed, callable_mp(this, &AnimationPlayer::_animation_changed));
-}
-
void AnimationPlayer::rename_animation_library(const StringName &p_name, const StringName &p_new_name) {
if (p_name == p_new_name) {
return;
@@ -1646,6 +1652,8 @@ void AnimationPlayer::play(const StringName &p_name, double p_custom_blend, floa
b.data = c.current;
b.blend_time = b.blend_left = blend_time;
c.blend.push_back(b);
+ } else {
+ c.blend.clear();
}
}
@@ -1799,9 +1807,8 @@ double AnimationPlayer::get_current_animation_length() const {
return playback.current.from->animation->get_length();
}
-void AnimationPlayer::_animation_changed() {
+void AnimationPlayer::_animation_changed(const StringName &p_name) {
clear_caches();
- emit_signal(SNAME("caches_cleared"));
if (is_playing()) {
playback.seeked = true; //need to restart stuff, like audio
}
@@ -1840,6 +1847,8 @@ void AnimationPlayer::clear_caches() {
cache_update_size = 0;
cache_update_prop_size = 0;
cache_update_bezier_size = 0;
+
+ emit_signal(SNAME("caches_cleared"));
}
void AnimationPlayer::set_active(bool p_active) {
@@ -2073,7 +2082,7 @@ Ref<AnimatedValuesBackup> AnimationPlayer::apply_reset(bool p_user_initiated) {
old_values->restore();
Ref<EditorUndoRedoManager> &ur = EditorNode::get_undo_redo();
- ur->create_action(TTR("Anim Apply Reset"));
+ ur->create_action(TTR("Animation Apply Reset"));
ur->add_do_method(new_values.ptr(), "restore");
ur->add_undo_method(old_values.ptr(), "restore");
ur->commit_action();
@@ -2158,7 +2167,7 @@ void AnimationPlayer::_bind_methods() {
ClassDB::bind_method(D_METHOD("advance", "delta"), &AnimationPlayer::advance);
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "root_node"), "set_root", "get_root");
- ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "current_animation", PROPERTY_HINT_ENUM, "", PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_ANIMATE_AS_TRIGGER), "set_current_animation", "get_current_animation");
+ ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "current_animation", PROPERTY_HINT_ENUM, "", PROPERTY_USAGE_EDITOR), "set_current_animation", "get_current_animation");
ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "assigned_animation", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_assigned_animation", "get_assigned_animation");
ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "autoplay", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_autoplay", "get_autoplay");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "reset_on_save", PROPERTY_HINT_NONE, ""), "set_reset_on_save_enabled", "is_reset_on_save_enabled");
diff --git a/scene/animation/animation_player.h b/scene/animation/animation_player.h
index 4f32927d25..0b95ee4e9e 100644
--- a/scene/animation/animation_player.h
+++ b/scene/animation/animation_player.h
@@ -268,7 +268,7 @@ private:
NodePath root;
- void _animation_process_animation(AnimationData *p_anim, double p_time, double p_delta, float p_interp, bool p_is_current = true, bool p_seeked = false, bool p_started = false, int p_pingponged = 0);
+ void _animation_process_animation(AnimationData *p_anim, double p_prev_time, double p_time, double p_delta, float p_interp, bool p_is_current = true, bool p_seeked = false, bool p_started = false, Animation::LoopedFlag p_looped_flag = Animation::LOOPED_FLAG_NONE);
void _ensure_node_caches(AnimationData *p_anim, Node *p_root_override = nullptr);
void _animation_process_data(PlaybackData &cd, double p_delta, float p_blend, bool p_seeked, bool p_started);
@@ -291,9 +291,7 @@ private:
return ret;
}
- void _animation_changed();
- void _ref_anim(const Ref<Animation> &p_anim);
- void _unref_anim(const Ref<Animation> &p_anim);
+ void _animation_changed(const StringName &p_name);
void _set_process(bool p_process, bool p_force = false);
diff --git a/scene/animation/animation_tree.cpp b/scene/animation/animation_tree.cpp
index 517908077d..b3408c1509 100644
--- a/scene/animation/animation_tree.cpp
+++ b/scene/animation/animation_tree.cpp
@@ -86,7 +86,7 @@ void AnimationNode::get_child_nodes(List<ChildNode> *r_child_nodes) {
}
}
-void AnimationNode::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) {
+void AnimationNode::blend_animation(const StringName &p_animation, double p_time, double p_delta, bool p_seeked, bool p_is_external_seeking, real_t p_blend, Animation::LoopedFlag p_looped_flag) {
ERR_FAIL_COND(!state);
ERR_FAIL_COND(!state->player->has_animation(p_animation));
@@ -112,19 +112,19 @@ void AnimationNode::blend_animation(const StringName &p_animation, double p_time
anim_state.time = p_time;
anim_state.animation = animation;
anim_state.seeked = p_seeked;
- anim_state.pingponged = p_pingponged;
- anim_state.seek_root = p_seek_root;
+ anim_state.looped_flag = p_looped_flag;
+ anim_state.is_external_seeking = p_is_external_seeking;
state->animation_states.push_back(anim_state);
}
-double AnimationNode::_pre_process(const StringName &p_base_path, AnimationNode *p_parent, State *p_state, double p_time, bool p_seek, bool p_seek_root, const Vector<StringName> &p_connections) {
+double AnimationNode::_pre_process(const StringName &p_base_path, AnimationNode *p_parent, State *p_state, double p_time, bool p_seek, bool p_is_external_seeking, const Vector<StringName> &p_connections) {
base_path = p_base_path;
parent = p_parent;
connections = p_connections;
state = p_state;
- double t = process(p_time, p_seek, p_seek_root);
+ double t = process(p_time, p_seek, p_is_external_seeking);
state = nullptr;
parent = nullptr;
@@ -148,7 +148,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_sync) {
+double AnimationNode::blend_input(int p_input, double p_time, bool p_seek, bool p_is_external_seeking, 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);
@@ -167,7 +167,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_sync, &activity);
+ double ret = _blend_node(node_name, blend_tree->get_node_connection_array(node_name), nullptr, node, p_time, p_seek, p_is_external_seeking, p_blend, p_filter, p_sync, &activity);
Vector<AnimationTree::Activity> *activity_ptr = state->tree->input_activity_map.getptr(base_path);
@@ -178,11 +178,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_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_sub_path, Ref<AnimationNode> p_node, double p_time, bool p_seek, bool p_is_external_seeking, 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_is_external_seeking, 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_sync, 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_is_external_seeking, 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);
@@ -221,7 +221,7 @@ double AnimationNode::_blend_node(const StringName &p_subpath, const Vector<Stri
}
blendw[i] = blendr[i] * p_blend;
- if (blendw[i] > CMP_EPSILON) {
+ if (!Math::is_zero_approx(blendw[i])) {
any_valid = true;
}
}
@@ -236,7 +236,7 @@ double AnimationNode::_blend_node(const StringName &p_subpath, const Vector<Stri
}
blendw[i] = blendr[i] * p_blend;
- if (blendw[i] > CMP_EPSILON) {
+ if (!Math::is_zero_approx(blendw[i])) {
any_valid = true;
}
}
@@ -252,7 +252,7 @@ double AnimationNode::_blend_node(const StringName &p_subpath, const Vector<Stri
blendw[i] = blendr[i]; //not filtered, do not blend
}
- if (blendw[i] > CMP_EPSILON) {
+ if (!Math::is_zero_approx(blendw[i])) {
any_valid = true;
}
}
@@ -263,7 +263,7 @@ double AnimationNode::_blend_node(const StringName &p_subpath, const Vector<Stri
for (int i = 0; i < blend_count; i++) {
//regular blend
blendw[i] = blendr[i] * p_blend;
- if (blendw[i] > CMP_EPSILON) {
+ if (!Math::is_zero_approx(blendw[i])) {
any_valid = true;
}
}
@@ -289,15 +289,12 @@ double AnimationNode::_blend_node(const StringName &p_subpath, const Vector<Stri
new_path = String(parent->base_path) + String(p_subpath) + "/";
}
- // 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.
- // 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.
+ // This process, which depends on p_sync is needed to process sync correctly in the case of
+ // that a synced AnimationNodeSync exists under the un-synced AnimationNodeSync.
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, 0, p_seek, p_is_external_seeking, p_connections);
}
- return p_node->_pre_process(new_path, new_parent, state, p_time, p_seek, p_seek_root, p_connections);
+ return p_node->_pre_process(new_path, new_parent, state, p_time, p_seek, p_is_external_seeking, p_connections);
}
int AnimationNode::get_input_count() const {
@@ -338,9 +335,9 @@ void AnimationNode::remove_input(int p_index) {
emit_changed();
}
-double AnimationNode::process(double p_time, bool p_seek, bool p_seek_root) {
+double AnimationNode::process(double p_time, bool p_seek, bool p_is_external_seeking) {
double ret = 0;
- GDVIRTUAL_CALL(_process, p_time, p_seek, p_seek_root, ret);
+ GDVIRTUAL_CALL(_process, p_time, p_seek, p_is_external_seeking, ret);
return ret;
}
@@ -416,9 +413,9 @@ void AnimationNode::_bind_methods() {
ClassDB::bind_method(D_METHOD("_set_filters", "filters"), &AnimationNode::_set_filters);
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", "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("blend_animation", "animation", "time", "delta", "seeked", "is_external_seeking", "blend", "looped_flag"), &AnimationNode::blend_animation, DEFVAL(Animation::LOOPED_FLAG_NONE));
+ ClassDB::bind_method(D_METHOD("blend_node", "name", "node", "time", "seek", "is_external_seeking", "blend", "filter", "sync"), &AnimationNode::blend_node, DEFVAL(FILTER_IGNORE), DEFVAL(true));
+ ClassDB::bind_method(D_METHOD("blend_input", "input_index", "time", "seek", "is_external_seeking", "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);
@@ -430,12 +427,11 @@ void AnimationNode::_bind_methods() {
GDVIRTUAL_BIND(_get_parameter_list);
GDVIRTUAL_BIND(_get_child_by_name, "name");
GDVIRTUAL_BIND(_get_parameter_default_value, "parameter");
- GDVIRTUAL_BIND(_process, "time", "seek", "seek_root");
+ GDVIRTUAL_BIND(_process, "time", "seek", "is_external_seeking");
GDVIRTUAL_BIND(_get_caption);
GDVIRTUAL_BIND(_has_filter);
ADD_SIGNAL(MethodInfo("removed_from_graph"));
-
ADD_SIGNAL(MethodInfo("tree_changed"));
BIND_ENUM_CONSTANT(FILTER_IGNORE);
@@ -589,6 +585,7 @@ bool AnimationTree::_update_caches(AnimationPlayer *player) {
track_value->object = child;
}
+ track_value->is_discrete = anim->value_track_get_update_mode(i) == Animation::UPDATE_DISCRETE;
track_value->is_using_angle = anim->track_get_interpolation_type(i) == Animation::INTERPOLATION_LINEAR_ANGLE || anim->track_get_interpolation_type(i) == Animation::INTERPOLATION_CUBIC_ANGLE;
track_value->subpath = leftover_path;
@@ -596,6 +593,13 @@ bool AnimationTree::_update_caches(AnimationPlayer *player) {
track = track_value;
+ // If a value track without a key is cached first, the initial value cannot be determined.
+ // It is a corner case, but which may cause problems with blending.
+ ERR_CONTINUE_MSG(anim->track_get_key_count(i) == 0, "AnimationTree: '" + String(E) + "', value track: '" + String(path) + "' must have at least one key to cache for blending.");
+ track_value->init_value = anim->track_get_key_value(i, 0);
+ track_value->init_value.zero();
+
+ // If there is a Reset Animation, it takes precedence by overwriting.
if (has_reset_anim) {
int rt = reset_anim->find_track(path, track_type);
if (rt >= 0 && reset_anim->track_get_key_count(rt) > 0) {
@@ -795,8 +799,18 @@ bool AnimationTree::_update_caches(AnimationPlayer *player) {
}
} else if (track_cache_type == Animation::TYPE_VALUE) {
// If it has at least one angle interpolation, it also uses angle interpolation for blending.
- TrackCacheValue *track_value = memnew(TrackCacheValue);
+ TrackCacheValue *track_value = static_cast<TrackCacheValue *>(track);
+ bool was_discrete = track_value->is_discrete;
+ bool was_using_angle = track_value->is_using_angle;
+ track_value->is_discrete |= anim->value_track_get_update_mode(i) == Animation::UPDATE_DISCRETE;
track_value->is_using_angle |= anim->track_get_interpolation_type(i) == Animation::INTERPOLATION_LINEAR_ANGLE || anim->track_get_interpolation_type(i) == Animation::INTERPOLATION_CUBIC_ANGLE;
+
+ if (was_discrete != track_value->is_discrete) {
+ ERR_PRINT_ED("Value track: " + String(path) + " with different update modes are blended. Blending prioritizes Discrete mode, so other update mode tracks will not be blended.");
+ }
+ if (was_using_angle != track_value->is_using_angle) {
+ WARN_PRINT_ED("Value track: " + String(path) + " with different interpolation types for rotation are blended. Blending prioritizes angle interpolation, so the blending result uses the shortest path referenced to the initial (RESET animation) value.");
+ }
}
track->setup_pass = setup_pass;
@@ -844,7 +858,6 @@ void AnimationTree::_clear_caches() {
memdelete(K.value);
}
playing_caches.clear();
-
track_cache.clear();
cache_valid = false;
}
@@ -868,7 +881,9 @@ void AnimationTree::_process_graph(double p_delta) {
_update_properties(); //if properties need updating, update them
//check all tracks, see if they need modification
- root_motion_transform = Transform3D();
+ root_motion_position = Vector3(0, 0, 0);
+ root_motion_rotation = Quaternion(0, 0, 0, 1);
+ root_motion_scale = Vector3(0, 0, 0);
if (!root.is_valid()) {
ERR_PRINT("AnimationTree: root AnimationNode is not set, disabling playback.");
@@ -955,8 +970,44 @@ void AnimationTree::_process_graph(double p_delta) {
if (!state.valid) {
return; //state is not valid. do nothing.
}
- //apply value/transform/bezier blends to track caches and execute method/audio/animation tracks
+ // Init all value/transform/blend/bezier tracks that track_cache has.
+ {
+ for (const KeyValue<NodePath, TrackCache *> &K : track_cache) {
+ TrackCache *track = K.value;
+
+ switch (track->type) {
+ case Animation::TYPE_POSITION_3D: {
+ TrackCacheTransform *t = static_cast<TrackCacheTransform *>(track);
+ if (track->root_motion) {
+ t->loc = Vector3(0, 0, 0);
+ t->rot = Quaternion(0, 0, 0, 1);
+ t->scale = Vector3(1, 1, 1);
+ } else {
+ t->loc = t->init_loc;
+ t->rot = t->init_rot;
+ t->scale = t->init_scale;
+ }
+ } break;
+ case Animation::TYPE_BLEND_SHAPE: {
+ TrackCacheBlendShape *t = static_cast<TrackCacheBlendShape *>(track);
+ t->value = t->init_value;
+ } break;
+ case Animation::TYPE_VALUE: {
+ TrackCacheValue *t = static_cast<TrackCacheValue *>(track);
+ t->value = t->init_value;
+ } break;
+ case Animation::TYPE_BEZIER: {
+ TrackCacheBezier *t = static_cast<TrackCacheBezier *>(track);
+ t->value = t->init_value;
+ } break;
+ default: {
+ } break;
+ }
+ }
+ }
+
+ // Apply value/transform/blend/bezier blends to track caches and execute method/audio/animation tracks.
{
bool can_call = is_inside_tree() && !Engine::get_singleton()->is_editor_hint();
@@ -966,10 +1017,11 @@ void AnimationTree::_process_graph(double p_delta) {
double delta = as.delta;
real_t weight = as.blend;
bool seeked = as.seeked;
- int pingponged = as.pingponged;
+ Animation::LoopedFlag looped_flag = as.looped_flag;
+ bool is_external_seeking = as.is_external_seeking;
#ifndef _3D_DISABLED
- bool backward = signbit(delta);
- bool calc_root = !seeked || as.seek_root;
+ bool backward = signbit(delta); // This flag is required only for the root motion since it calculates the difference between the previous and current frames.
+ bool calc_root = !seeked || is_external_seeking;
#endif // _3D_DISABLED
for (int i = 0; i < a->get_track_count(); i++) {
@@ -978,37 +1030,31 @@ void AnimationTree::_process_graph(double p_delta) {
}
NodePath path = a->track_get_path(i);
-
- ERR_CONTINUE(!track_cache.has(path));
-
+ if (!track_cache.has(path)) {
+ continue; // No path, but avoid error spamming.
+ }
TrackCache *track = track_cache[path];
+ ERR_CONTINUE(!state.track_map.has(path));
+ int blend_idx = state.track_map[path];
+ ERR_CONTINUE(blend_idx < 0 || blend_idx >= state.track_count);
+ real_t blend = (*as.track_blends)[blend_idx] * weight;
+ if (Math::is_zero_approx(blend)) {
+ continue; // Nothing to blend.
+ }
+
Animation::TrackType ttype = a->track_get_type(i);
if (ttype != Animation::TYPE_POSITION_3D && ttype != Animation::TYPE_ROTATION_3D && ttype != Animation::TYPE_SCALE_3D && track->type != ttype) {
//broken animation, but avoid error spamming
continue;
}
-
track->root_motion = root_motion_track == path;
- ERR_CONTINUE(!state.track_map.has(path));
- int blend_idx = state.track_map[path];
-
- ERR_CONTINUE(blend_idx < 0 || blend_idx >= state.track_count);
-
- real_t blend = (*as.track_blends)[blend_idx] * weight;
-
switch (ttype) {
case Animation::TYPE_POSITION_3D: {
#ifndef _3D_DISABLED
TrackCacheTransform *t = static_cast<TrackCacheTransform *>(track);
if (track->root_motion && calc_root) {
- if (t->process_pass != process_pass) {
- t->process_pass = process_pass;
- t->loc = Vector3(0, 0, 0);
- t->rot = Quaternion(0, 0, 0, 1);
- t->scale = Vector3(0, 0, 0);
- }
double prev_time = time - delta;
if (!backward) {
if (prev_time < 0) {
@@ -1084,12 +1130,6 @@ void AnimationTree::_process_graph(double p_delta) {
prev_time = !backward ? 0 : (double)a->get_length();
} else {
- if (t->process_pass != process_pass) {
- t->process_pass = process_pass;
- t->loc = t->init_loc;
- t->rot = t->init_rot;
- t->scale = t->init_scale;
- }
Vector3 loc;
Error err = a->position_track_interpolate(i, time, &loc);
@@ -1106,12 +1146,6 @@ void AnimationTree::_process_graph(double p_delta) {
#ifndef _3D_DISABLED
TrackCacheTransform *t = static_cast<TrackCacheTransform *>(track);
if (track->root_motion && calc_root) {
- if (t->process_pass != process_pass) {
- t->process_pass = process_pass;
- t->loc = Vector3(0, 0, 0);
- t->rot = Quaternion(0, 0, 0, 1);
- t->scale = Vector3(0, 0, 0);
- }
double prev_time = time - delta;
if (!backward) {
if (prev_time < 0) {
@@ -1186,12 +1220,6 @@ void AnimationTree::_process_graph(double p_delta) {
prev_time = !backward ? 0 : (double)a->get_length();
} else {
- if (t->process_pass != process_pass) {
- t->process_pass = process_pass;
- t->loc = t->init_loc;
- t->rot = t->init_rot;
- t->scale = t->init_scale;
- }
Quaternion rot;
Error err = a->rotation_track_interpolate(i, time, &rot);
@@ -1208,12 +1236,6 @@ void AnimationTree::_process_graph(double p_delta) {
#ifndef _3D_DISABLED
TrackCacheTransform *t = static_cast<TrackCacheTransform *>(track);
if (track->root_motion && calc_root) {
- if (t->process_pass != process_pass) {
- t->process_pass = process_pass;
- t->loc = Vector3(0, 0, 0);
- t->rot = Quaternion(0, 0, 0, 1);
- t->scale = Vector3(0, 0, 0);
- }
double prev_time = time - delta;
if (!backward) {
if (prev_time < 0) {
@@ -1289,12 +1311,6 @@ void AnimationTree::_process_graph(double p_delta) {
prev_time = !backward ? 0 : (double)a->get_length();
} else {
- if (t->process_pass != process_pass) {
- t->process_pass = process_pass;
- t->loc = t->init_loc;
- t->rot = t->init_rot;
- t->scale = t->init_scale;
- }
Vector3 scale;
Error err = a->scale_track_interpolate(i, time, &scale);
@@ -1311,11 +1327,6 @@ void AnimationTree::_process_graph(double p_delta) {
#ifndef _3D_DISABLED
TrackCacheBlendShape *t = static_cast<TrackCacheBlendShape *>(track);
- if (t->process_pass != process_pass) {
- t->process_pass = process_pass;
- t->value = t->init_value;
- }
-
float value;
Error err = a->blend_shape_track_interpolate(i, time, &value);
@@ -1342,15 +1353,6 @@ void AnimationTree::_process_graph(double p_delta) {
continue;
}
- if (t->process_pass != process_pass) {
- t->process_pass = process_pass;
- if (!t->init_value) {
- t->init_value = value;
- t->init_value.zero();
- }
- t->value = t->init_value;
- }
-
// Special case for angle interpolation.
if (t->is_using_angle) {
// For blending consistency, it prevents rotation of more than 180 degrees from init_value.
@@ -1379,12 +1381,8 @@ void AnimationTree::_process_graph(double p_delta) {
}
}
} else {
- if (blend < CMP_EPSILON) {
- continue; //nothing to blend
- }
-
if (seeked) {
- int idx = a->track_find_key(i, time);
+ int idx = a->track_find_key(i, time, is_external_seeking ? Animation::FIND_MODE_NEAREST : Animation::FIND_MODE_EXACT);
if (idx < 0) {
continue;
}
@@ -1393,7 +1391,7 @@ void AnimationTree::_process_graph(double p_delta) {
t->object->set_indexed(t->subpath, value);
} else {
List<int> indices;
- a->value_track_get_key_indices(i, time, delta, &indices, pingponged);
+ a->track_get_key_indices_in_range(i, time, delta, &indices, looped_flag);
for (int &F : indices) {
Variant value = a->track_get_key_value(i, F);
value = _post_process_key_value(a, i, value, t->object);
@@ -1404,13 +1402,10 @@ void AnimationTree::_process_graph(double p_delta) {
} break;
case Animation::TYPE_METHOD: {
- if (blend < CMP_EPSILON) {
- continue; //nothing to blend
- }
TrackCacheMethod *t = static_cast<TrackCacheMethod *>(track);
if (seeked) {
- int idx = a->track_find_key(i, time);
+ int idx = a->track_find_key(i, time, is_external_seeking ? Animation::FIND_MODE_NEAREST : Animation::FIND_MODE_EXACT);
if (idx < 0) {
continue;
}
@@ -1421,7 +1416,7 @@ void AnimationTree::_process_graph(double p_delta) {
}
} else {
List<int> indices;
- a->method_track_get_key_indices(i, time, delta, &indices, pingponged);
+ a->track_get_key_indices_in_range(i, time, delta, &indices, looped_flag);
for (int &F : indices) {
StringName method = a->method_track_get_name(i, F);
Vector<Variant> params = a->method_track_get_params(i, F);
@@ -1437,22 +1432,14 @@ void AnimationTree::_process_graph(double p_delta) {
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;
- t->value = t->init_value;
- }
-
t->value += (bezier - t->init_value) * blend;
} break;
case Animation::TYPE_AUDIO: {
- if (blend < CMP_EPSILON) {
- continue; //nothing to blend
- }
TrackCacheAudio *t = static_cast<TrackCacheAudio *>(track);
if (seeked) {
//find whatever should be playing
- int idx = a->track_find_key(i, time);
+ int idx = a->track_find_key(i, time, is_external_seeking ? Animation::FIND_MODE_NEAREST : Animation::FIND_MODE_EXACT);
if (idx < 0) {
continue;
}
@@ -1492,7 +1479,7 @@ void AnimationTree::_process_graph(double p_delta) {
} else {
//find stuff to play
List<int> to_play;
- a->track_get_key_indices_in_range(i, time, delta, &to_play, pingponged);
+ a->track_get_key_indices_in_range(i, time, delta, &to_play, looped_flag);
if (to_play.size()) {
int idx = to_play.back()->get();
@@ -1555,9 +1542,6 @@ void AnimationTree::_process_graph(double p_delta) {
t->object->call(SNAME("set_volume_db"), db);
} break;
case Animation::TYPE_ANIMATION: {
- if (blend < CMP_EPSILON) {
- continue; //nothing to blend
- }
TrackCacheAnimation *t = static_cast<TrackCacheAnimation *>(track);
AnimationPlayer *player2 = Object::cast_to<AnimationPlayer>(t->object);
@@ -1568,7 +1552,7 @@ void AnimationTree::_process_graph(double p_delta) {
if (seeked) {
//seek
- int idx = a->track_find_key(i, time);
+ int idx = a->track_find_key(i, time, is_external_seeking ? Animation::FIND_MODE_NEAREST : Animation::FIND_MODE_EXACT);
if (idx < 0) {
continue;
}
@@ -1599,8 +1583,8 @@ void AnimationTree::_process_graph(double p_delta) {
}
if (player2->is_playing() || seeked) {
- player2->play(anim_name);
player2->seek(at_anim_pos);
+ player2->play(anim_name);
t->playing = true;
playing_caches.insert(t);
} else {
@@ -1610,7 +1594,7 @@ void AnimationTree::_process_graph(double p_delta) {
} else {
//find stuff to play
List<int> to_play;
- a->track_get_key_indices_in_range(i, time, delta, &to_play, pingponged);
+ a->track_get_key_indices_in_range(i, time, delta, &to_play, looped_flag);
if (to_play.size()) {
int idx = to_play.back()->get();
@@ -1639,9 +1623,6 @@ void AnimationTree::_process_graph(double p_delta) {
// finally, set the tracks
for (const KeyValue<NodePath, TrackCache *> &K : track_cache) {
TrackCache *track = K.value;
- if (track->process_pass != process_pass) {
- continue; //not processed, ignore
- }
switch (track->type) {
case Animation::TYPE_POSITION_3D: {
@@ -1649,11 +1630,9 @@ void AnimationTree::_process_graph(double p_delta) {
TrackCacheTransform *t = static_cast<TrackCacheTransform *>(track);
if (t->root_motion) {
- Transform3D xform;
- xform.origin = t->loc;
- xform.basis.set_quaternion_scale(t->rot, Vector3(1, 1, 1) + t->scale);
-
- root_motion_transform = xform;
+ root_motion_position = t->loc;
+ root_motion_rotation = t->rot;
+ root_motion_scale = t->scale - Vector3(1, 1, 1);
} else if (t->skeleton && t->bone_idx >= 0) {
if (t->loc_used) {
@@ -1691,6 +1670,10 @@ void AnimationTree::_process_graph(double p_delta) {
case Animation::TYPE_VALUE: {
TrackCacheValue *t = static_cast<TrackCacheValue *>(track);
+ if (t->is_discrete) {
+ break; // Don't overwrite the value set by UPDATE_DISCRETE.
+ }
+
if (t->init_value.get_type() == Variant::BOOL) {
t->object->set_indexed(t->subpath, t->value.operator real_t() >= 0.5);
} else {
@@ -1775,7 +1758,7 @@ void AnimationTree::_setup_animation_player() {
AnimationPlayer *new_player = nullptr;
if (!animation_player.is_empty()) {
- new_player = Object::cast_to<AnimationPlayer>(get_node(animation_player));
+ new_player = Object::cast_to<AnimationPlayer>(get_node_or_null(animation_player));
if (new_player && !new_player->is_connected("animation_list_changed", callable_mp(this, &AnimationTree::_animation_player_changed))) {
new_player->connect("animation_list_changed", callable_mp(this, &AnimationTree::_animation_player_changed));
}
@@ -1862,8 +1845,16 @@ NodePath AnimationTree::get_root_motion_track() const {
return root_motion_track;
}
-Transform3D AnimationTree::get_root_motion_transform() const {
- return root_motion_transform;
+Vector3 AnimationTree::get_root_motion_position() const {
+ return root_motion_position;
+}
+
+Quaternion AnimationTree::get_root_motion_rotation() const {
+ return root_motion_rotation;
+}
+
+Vector3 AnimationTree::get_root_motion_scale() const {
+ return root_motion_scale;
}
void AnimationTree::_tree_changed() {
@@ -2021,7 +2012,9 @@ void AnimationTree::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_root_motion_track", "path"), &AnimationTree::set_root_motion_track);
ClassDB::bind_method(D_METHOD("get_root_motion_track"), &AnimationTree::get_root_motion_track);
- ClassDB::bind_method(D_METHOD("get_root_motion_transform"), &AnimationTree::get_root_motion_transform);
+ ClassDB::bind_method(D_METHOD("get_root_motion_position"), &AnimationTree::get_root_motion_position);
+ ClassDB::bind_method(D_METHOD("get_root_motion_rotation"), &AnimationTree::get_root_motion_rotation);
+ ClassDB::bind_method(D_METHOD("get_root_motion_scale"), &AnimationTree::get_root_motion_scale);
ClassDB::bind_method(D_METHOD("_update_properties"), &AnimationTree::_update_properties);
@@ -2043,6 +2036,10 @@ void AnimationTree::_bind_methods() {
BIND_ENUM_CONSTANT(ANIMATION_PROCESS_MANUAL);
ADD_SIGNAL(MethodInfo("animation_player_changed"));
+
+ // Signals from AnimationNodes.
+ ADD_SIGNAL(MethodInfo("animation_started", PropertyInfo(Variant::STRING_NAME, "anim_name")));
+ ADD_SIGNAL(MethodInfo("animation_finished", PropertyInfo(Variant::STRING_NAME, "anim_name")));
}
AnimationTree::AnimationTree() {
diff --git a/scene/animation/animation_tree.h b/scene/animation/animation_tree.h
index 96c1279f82..be0dc1af4e 100644
--- a/scene/animation/animation_tree.h
+++ b/scene/animation/animation_tree.h
@@ -68,8 +68,8 @@ public:
const Vector<real_t> *track_blends = nullptr;
real_t blend = 0.0;
bool seeked = false;
- bool seek_root = false;
- int pingponged = 0;
+ bool is_external_seeking = false;
+ Animation::LoopedFlag looped_flag = Animation::LOOPED_FLAG_NONE;
};
struct State {
@@ -86,7 +86,7 @@ public:
Vector<real_t> blends;
State *state = nullptr;
- double _pre_process(const StringName &p_base_path, AnimationNode *p_parent, State *p_state, double p_time, bool p_seek, bool p_seek_root, const Vector<StringName> &p_connections);
+ double _pre_process(const StringName &p_base_path, AnimationNode *p_parent, State *p_state, double p_time, bool p_seek, bool p_is_external_seeking, const Vector<StringName> &p_connections);
//all this is temporary
StringName base_path;
@@ -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_sync = 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_is_external_seeking, 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_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 blend_animation(const StringName &p_animation, double p_time, double p_delta, bool p_seeked, bool p_is_external_seeking, real_t p_blend, Animation::LoopedFlag p_looped_flag = Animation::LOOPED_FLAG_NONE);
+ double blend_node(const StringName &p_sub_path, Ref<AnimationNode> p_node, double p_time, bool p_seek, bool p_is_external_seeking, 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_is_external_seeking, 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;
@@ -135,7 +135,7 @@ public:
virtual void get_child_nodes(List<ChildNode> *r_child_nodes);
- virtual double process(double p_time, bool p_seek, bool p_seek_root);
+ virtual double process(double p_time, bool p_seek, bool p_is_external_seeking);
virtual String get_caption() const;
int get_input_count() const;
@@ -190,7 +190,6 @@ private:
struct TrackCache {
bool root_motion = false;
uint64_t setup_pass = 0;
- uint64_t process_pass = 0;
Animation::TrackType type = Animation::TrackType::TYPE_ANIMATION;
Object *object = nullptr;
ObjectID object_id;
@@ -233,6 +232,7 @@ private:
Variant init_value;
Variant value;
Vector<StringName> subpath;
+ bool is_discrete = false;
bool is_using_angle = false;
TrackCacheValue() { type = Animation::TYPE_VALUE; }
};
@@ -294,7 +294,9 @@ private:
bool started = true;
NodePath root_motion_track;
- Transform3D root_motion_transform;
+ Vector3 root_motion_position = Vector3(0, 0, 0);
+ Quaternion root_motion_rotation = Quaternion(0, 0, 0, 1);
+ Vector3 root_motion_scale = Vector3(0, 0, 0);
friend class AnimationNode;
bool properties_dirty = true;
@@ -350,7 +352,9 @@ public:
void set_root_motion_track(const NodePath &p_track);
NodePath get_root_motion_track() const;
- Transform3D get_root_motion_transform() const;
+ Vector3 get_root_motion_position() const;
+ Quaternion get_root_motion_rotation() const;
+ Vector3 get_root_motion_scale() const;
real_t get_connection_activity(const StringName &p_path, int p_connection) const;
void advance(double p_time);
diff --git a/scene/animation/root_motion_view.cpp b/scene/animation/root_motion_view.cpp
index 47f08219a9..a6ccb4a576 100644
--- a/scene/animation/root_motion_view.cpp
+++ b/scene/animation/root_motion_view.cpp
@@ -103,7 +103,8 @@ void RootMotionView::_notification(int p_what) {
set_physics_process_internal(false);
}
- transform = tree->get_root_motion_transform();
+ transform.origin = tree->get_root_motion_position();
+ transform.basis = tree->get_root_motion_rotation(); // Scale is meaningless.
}
}
@@ -113,9 +114,8 @@ void RootMotionView::_notification(int p_what) {
first = false;
- transform.orthonormalize(); //don't want scale, too imprecise
-
- accumulated = accumulated * transform;
+ accumulated.origin += transform.origin;
+ accumulated.basis *= transform.basis;
accumulated.origin.x = Math::fposmod(accumulated.origin.x, cell_size);
if (zero_y) {
accumulated.origin.y = 0;
diff --git a/scene/debugger/scene_debugger.cpp b/scene/debugger/scene_debugger.cpp
index b4bdda9ecb..28eedcbe13 100644
--- a/scene/debugger/scene_debugger.cpp
+++ b/scene/debugger/scene_debugger.cpp
@@ -39,87 +39,10 @@
#include "scene/main/window.h"
#include "scene/resources/packed_scene.h"
-Array SceneDebugger::RPCProfilerFrame::serialize() {
- Array arr;
- arr.push_back(infos.size() * 4);
- for (int i = 0; i < infos.size(); ++i) {
- arr.push_back(uint64_t(infos[i].node));
- arr.push_back(infos[i].node_path);
- arr.push_back(infos[i].incoming_rpc);
- arr.push_back(infos[i].outgoing_rpc);
- }
- return arr;
-}
-
-bool SceneDebugger::RPCProfilerFrame::deserialize(const Array &p_arr) {
- ERR_FAIL_COND_V(p_arr.size() < 1, false);
- uint32_t size = p_arr[0];
- ERR_FAIL_COND_V(size % 4, false);
- ERR_FAIL_COND_V((uint32_t)p_arr.size() != size + 1, false);
- infos.resize(size / 4);
- int idx = 1;
- for (uint32_t i = 0; i < size / 4; ++i) {
- infos.write[i].node = uint64_t(p_arr[idx]);
- infos.write[i].node_path = p_arr[idx + 1];
- infos.write[i].incoming_rpc = p_arr[idx + 2];
- infos.write[i].outgoing_rpc = p_arr[idx + 3];
- }
- return true;
-}
-
-class SceneDebugger::RPCProfiler : public EngineProfiler {
- HashMap<ObjectID, RPCNodeInfo> rpc_node_data;
- uint64_t last_profile_time = 0;
-
- void init_node(const ObjectID p_node) {
- if (rpc_node_data.has(p_node)) {
- return;
- }
- rpc_node_data.insert(p_node, RPCNodeInfo());
- rpc_node_data[p_node].node = p_node;
- rpc_node_data[p_node].node_path = Object::cast_to<Node>(ObjectDB::get_instance(p_node))->get_path();
- rpc_node_data[p_node].incoming_rpc = 0;
- rpc_node_data[p_node].outgoing_rpc = 0;
- }
-
-public:
- void toggle(bool p_enable, const Array &p_opts) {
- rpc_node_data.clear();
- }
-
- void add(const Array &p_data) {
- ERR_FAIL_COND(p_data.size() < 2);
- const ObjectID id = p_data[0];
- const String what = p_data[1];
- init_node(id);
- RPCNodeInfo &info = rpc_node_data[id];
- if (what == "rpc_in") {
- info.incoming_rpc++;
- } else if (what == "rpc_out") {
- info.outgoing_rpc++;
- }
- }
-
- void tick(double p_frame_time, double p_process_time, double p_physics_time, double p_physics_frame_time) {
- uint64_t pt = OS::get_singleton()->get_ticks_msec();
- if (pt - last_profile_time > 100) {
- last_profile_time = pt;
- RPCProfilerFrame frame;
- for (const KeyValue<ObjectID, RPCNodeInfo> &E : rpc_node_data) {
- frame.infos.push_back(E.value);
- }
- rpc_node_data.clear();
- EngineDebugger::get_singleton()->send_message("multiplayer:rpc", frame.serialize());
- }
- }
-};
-
SceneDebugger *SceneDebugger::singleton = nullptr;
SceneDebugger::SceneDebugger() {
singleton = this;
- rpc_profiler.instantiate();
- rpc_profiler->bind("rpc");
#ifdef DEBUG_ENABLED
LiveEditor::singleton = memnew(LiveEditor);
EngineDebugger::register_message_capture("scene", EngineDebugger::Capture(nullptr, SceneDebugger::parse_message));
@@ -264,7 +187,7 @@ Error SceneDebugger::parse_message(void *p_user, const String &p_msg, const Arra
ERR_FAIL_COND_V(p_args.size() < 3, ERR_INVALID_DATA);
live_editor->_create_node_func(p_args[0], p_args[1], p_args[2]);
- } else if (p_msg == "live_instance_node") {
+ } else if (p_msg == "live_instantiate_node") {
ERR_FAIL_COND_V(p_args.size() < 3, ERR_INVALID_DATA);
live_editor->_instance_node_func(p_args[0], p_args[1], p_args[2]);
@@ -297,9 +220,35 @@ void SceneDebugger::_save_node(ObjectID id, const String &p_path) {
Node *node = Object::cast_to<Node>(ObjectDB::get_instance(id));
ERR_FAIL_COND(!node);
+#ifdef TOOLS_ENABLED
+ HashMap<const Node *, Node *> duplimap;
+ Node *copy = node->duplicate_from_editor(duplimap);
+#else
+ Node *copy = node->duplicate();
+#endif
+
+ // Handle Unique Nodes.
+ for (int i = 0; i < copy->get_child_count(false); i++) {
+ _set_node_owner_recursive(copy->get_child(i, false), copy);
+ }
+ // Root node cannot ever be unique name in its own Scene!
+ copy->set_unique_name_in_owner(false);
+
Ref<PackedScene> ps = memnew(PackedScene);
- ps->pack(node);
+ ps->pack(copy);
ResourceSaver::save(ps, p_path);
+
+ memdelete(copy);
+}
+
+void SceneDebugger::_set_node_owner_recursive(Node *p_node, Node *p_owner) {
+ if (!p_node->get_owner()) {
+ p_node->set_owner(p_owner);
+ }
+
+ for (int i = 0; i < p_node->get_child_count(false); i++) {
+ _set_node_owner_recursive(p_node->get_child(i, false), p_owner);
+ }
}
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 fe35446aae..34891ef0fd 100644
--- a/scene/debugger/scene_debugger.h
+++ b/scene/debugger/scene_debugger.h
@@ -42,28 +42,9 @@ class Node;
class SceneDebugger {
public:
- // RPC profiler
- struct RPCNodeInfo {
- ObjectID node;
- String node_path;
- int incoming_rpc = 0;
- int outgoing_rpc = 0;
- };
-
- struct RPCProfilerFrame {
- Vector<RPCNodeInfo> infos;
-
- Array serialize();
- bool deserialize(const Array &p_arr);
- };
-
private:
- class RPCProfiler;
-
static SceneDebugger *singleton;
- Ref<RPCProfiler> rpc_profiler;
-
SceneDebugger();
public:
@@ -75,6 +56,7 @@ public:
#ifdef DEBUG_ENABLED
private:
static void _save_node(ObjectID id, const String &p_path);
+ static void _set_node_owner_recursive(Node *p_node, Node *p_owner);
static void _set_object_property(ObjectID p_id, const String &p_property, const Variant &p_value);
static void _send_object_id(ObjectID p_id, int p_max_size = 1 << 20);
diff --git a/scene/gui/base_button.cpp b/scene/gui/base_button.cpp
index ac9034c6fd..9da1fbda1b 100644
--- a/scene/gui/base_button.cpp
+++ b/scene/gui/base_button.cpp
@@ -300,6 +300,7 @@ void BaseButton::set_toggle_mode(bool p_on) {
}
toggle_mode = p_on;
+ update_configuration_warnings();
}
bool BaseButton::is_toggle_mode() const {
@@ -381,6 +382,7 @@ void BaseButton::set_button_group(const Ref<ButtonGroup> &p_group) {
}
queue_redraw(); //checkbox changes to radio if set a buttongroup
+ update_configuration_warnings();
}
Ref<ButtonGroup> BaseButton::get_button_group() const {
@@ -399,6 +401,16 @@ bool BaseButton::is_shortcut_feedback() const {
return shortcut_feedback;
}
+PackedStringArray BaseButton::get_configuration_warnings() const {
+ PackedStringArray warnings = Control::get_configuration_warnings();
+
+ if (get_button_group().is_valid() && !is_toggle_mode()) {
+ warnings.push_back(RTR("ButtonGroup is intended to be used only with buttons that have toggle_mode set to true."));
+ }
+
+ return warnings;
+}
+
void BaseButton::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_pressed", "pressed"), &BaseButton::set_pressed);
ClassDB::bind_method(D_METHOD("is_pressed"), &BaseButton::is_pressed);
diff --git a/scene/gui/base_button.h b/scene/gui/base_button.h
index 3acf535f54..5018aea120 100644
--- a/scene/gui/base_button.h
+++ b/scene/gui/base_button.h
@@ -136,6 +136,8 @@ public:
void set_shortcut_feedback(bool p_feedback);
bool is_shortcut_feedback() const;
+ PackedStringArray get_configuration_warnings() const override;
+
BaseButton();
~BaseButton();
};
diff --git a/scene/gui/button.cpp b/scene/gui/button.cpp
index c2b82e01d1..0e7bc5c306 100644
--- a/scene/gui/button.cpp
+++ b/scene/gui/button.cpp
@@ -231,7 +231,7 @@ void Button::_notification(int p_what) {
_icon = icon;
}
- Rect2 icon_region = Rect2();
+ Rect2 icon_region;
HorizontalAlignment icon_align_rtl_checked = icon_alignment;
HorizontalAlignment align_rtl_checked = alignment;
// Swap icon and text alignment sides if right-to-left layout is set.
diff --git a/scene/gui/code_edit.cpp b/scene/gui/code_edit.cpp
index ea310f5a12..c84438ed5e 100644
--- a/scene/gui/code_edit.cpp
+++ b/scene/gui/code_edit.cpp
@@ -115,7 +115,9 @@ void CodeEdit::_notification(int p_what) {
const Point2 caret_pos = get_caret_draw_pos();
const int total_height = csb->get_minimum_size().y + code_completion_rect.size.height;
- if (caret_pos.y + row_height + total_height > get_size().height) {
+ const bool can_fit_completion_above = (caret_pos.y - row_height > total_height);
+ const bool can_fit_completion_below = (caret_pos.y + row_height + total_height <= get_size().height);
+ if (!can_fit_completion_below && can_fit_completion_above) {
code_completion_rect.position.y = (caret_pos.y - total_height - row_height) + line_spacing;
} else {
code_completion_rect.position.y = caret_pos.y + (line_spacing / 2.0f);
@@ -378,12 +380,13 @@ void CodeEdit::gui_input(const Ref<InputEvent> &p_gui_input) {
}
if (symbol_lookup_on_click_enabled) {
- if (mm->is_command_or_control_pressed() && mm->get_button_mask() == MouseButton::NONE && !is_dragging_cursor()) {
+ if (mm->is_command_or_control_pressed() && mm->get_button_mask() == MouseButton::NONE) {
+ symbol_lookup_pos = get_line_column_at_pos(mpos);
symbol_lookup_new_word = get_word_at_pos(mpos);
if (symbol_lookup_new_word != symbol_lookup_word) {
emit_signal(SNAME("symbol_validate"), symbol_lookup_new_word);
}
- } else {
+ } else if (!mm->is_command_or_control_pressed() || (mm->get_button_mask() != MouseButton::NONE && symbol_lookup_pos != get_line_column_at_pos(mpos))) {
set_symbol_lookup_word_as_valid(false);
}
}
@@ -1425,7 +1428,10 @@ bool CodeEdit::is_line_numbers_zero_padded() const {
}
void CodeEdit::_line_number_draw_callback(int p_line, int p_gutter, const Rect2 &p_region) {
- String fc = TS->format_number(String::num(p_line + 1).lpad(line_number_digits, line_number_padding));
+ String fc = String::num(p_line + 1).lpad(line_number_digits, line_number_padding);
+ if (is_localizing_numeral_system()) {
+ fc = TS->format_number(fc);
+ }
Ref<TextLine> tl;
tl.instantiate();
tl->add_string(fc, font, font_size);
@@ -2075,20 +2081,22 @@ void CodeEdit::confirm_code_completion(bool p_replace) {
}
char32_t last_completion_char_display = display_text[display_text.length() - 1];
+ bool last_char_matches = (last_completion_char == next_char || last_completion_char_display == next_char);
int pre_brace_pair = get_caret_column(i) > 0 ? _get_auto_brace_pair_open_at_pos(caret_line, get_caret_column(i)) : -1;
int post_brace_pair = get_caret_column(i) < get_line(caret_line).length() ? _get_auto_brace_pair_close_at_pos(caret_line, get_caret_column(i)) : -1;
- if (post_brace_pair != -1 && (last_completion_char == next_char || last_completion_char_display == next_char)) {
- remove_text(caret_line, get_caret_column(i), caret_line, get_caret_column(i) + 1);
- adjust_carets_after_edit(i, caret_line, get_caret_column(i), caret_line, get_caret_column(i) + 1);
- }
-
- if (pre_brace_pair != -1 && pre_brace_pair != post_brace_pair && (last_completion_char == next_char || last_completion_char_display == next_char)) {
+ // Strings do not nest like brackets, so ensure we don't add an additional closing pair.
+ if (has_string_delimiter(String::chr(last_completion_char)) && post_brace_pair != -1 && last_char_matches) {
remove_text(caret_line, get_caret_column(i), caret_line, get_caret_column(i) + 1);
adjust_carets_after_edit(i, caret_line, get_caret_column(i), caret_line, get_caret_column(i) + 1);
- } else if (auto_brace_completion_enabled && pre_brace_pair != -1 && post_brace_pair == -1) {
- insert_text_at_caret(auto_brace_completion_pairs[pre_brace_pair].close_key, i);
- set_caret_column(get_caret_column(i) - auto_brace_completion_pairs[pre_brace_pair].close_key.length(), i == 0, i);
+ } else {
+ if (pre_brace_pair != -1 && pre_brace_pair != post_brace_pair && last_char_matches) {
+ remove_text(caret_line, get_caret_column(i), caret_line, get_caret_column(i) + 1);
+ adjust_carets_after_edit(i, caret_line, get_caret_column(i), caret_line, get_caret_column(i) + 1);
+ } else if (auto_brace_completion_enabled && pre_brace_pair != -1) {
+ insert_text_at_caret(auto_brace_completion_pairs[pre_brace_pair].close_key, i);
+ set_caret_column(get_caret_column(i) - auto_brace_completion_pairs[pre_brace_pair].close_key.length(), i == 0, i);
+ }
}
if (pre_brace_pair == -1 && post_brace_pair == -1 && get_caret_column(i) > 0 && get_caret_column(i) < get_line(caret_line).length()) {
diff --git a/scene/gui/code_edit.h b/scene/gui/code_edit.h
index cbbc13480e..e409c7c82b 100644
--- a/scene/gui/code_edit.h
+++ b/scene/gui/code_edit.h
@@ -236,6 +236,7 @@ private:
String symbol_lookup_new_word = "";
String symbol_lookup_word = "";
+ Point2i symbol_lookup_pos;
/* Visual */
Ref<StyleBox> style_normal;
diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp
index 724e5bcaf6..fa4b57d7a7 100644
--- a/scene/gui/color_picker.cpp
+++ b/scene/gui/color_picker.cpp
@@ -959,7 +959,7 @@ void ColorPicker::_sample_draw() {
// Draw both old and new colors for easier comparison (only if spawned from a ColorPickerButton).
const Rect2 rect_old = Rect2(Point2(), Size2(sample->get_size().width * 0.5, sample->get_size().height * 0.95));
- if (display_old_color && old_color.a < 1.0) {
+ if (old_color.a < 1.0) {
sample->draw_texture_rect(get_theme_icon(SNAME("sample_bg"), SNAME("ColorPicker")), rect_old, true);
}
@@ -1088,7 +1088,9 @@ void ColorPicker::_hsv_draw(int p_which, Control *c) {
} else if (p_which == 1) {
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()));
+ c->draw_set_transform(Point2(), -Math_PI / 2, Size2(c->get_size().x, -c->get_size().y));
+ c->draw_texture_rect(hue, Rect2(Point2(), Size2(1, 1)));
+ c->draw_set_transform(Point2(), 0, Size2(1, 1));
int y = c->get_size().y - c->get_size().y * (1.0 - h);
Color col;
col.set_hsv(h, 1, 1);
@@ -1575,8 +1577,7 @@ void ColorPicker::_bind_methods() {
BIND_ENUM_CONSTANT(SHAPE_NONE);
}
-ColorPicker::ColorPicker() :
- BoxContainer(true) {
+ColorPicker::ColorPicker() {
HBoxContainer *hb_edit = memnew(HBoxContainer);
add_child(hb_edit, false, INTERNAL_MODE_FRONT);
hb_edit->set_v_size_flags(SIZE_SHRINK_BEGIN);
diff --git a/scene/gui/color_picker.h b/scene/gui/color_picker.h
index 3208676539..799ca2d202 100644
--- a/scene/gui/color_picker.h
+++ b/scene/gui/color_picker.h
@@ -68,8 +68,8 @@ public:
~ColorPresetButton();
};
-class ColorPicker : public BoxContainer {
- GDCLASS(ColorPicker, BoxContainer);
+class ColorPicker : public VBoxContainer {
+ GDCLASS(ColorPicker, VBoxContainer);
public:
enum ColorModeType {
diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp
index c5cb7157e8..21c7c4ddb4 100644
--- a/scene/gui/control.cpp
+++ b/scene/gui/control.cpp
@@ -220,6 +220,10 @@ PackedStringArray Control::get_configuration_warnings() const {
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\"."));
}
+ if (get_z_index() != 0) {
+ warnings.push_back(RTR("Changing the Z index of a control only affects the drawing order, not the input event handling order."));
+ }
+
return warnings;
}
@@ -253,36 +257,36 @@ bool Control::_set(const StringName &p_name, const Variant &p_value) {
if (p_value.get_type() == Variant::NIL || (p_value.get_type() == Variant::OBJECT && (Object *)p_value == nullptr)) {
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::_notify_theme_override_changed));
+ if (data.theme_icon_override.has(dname)) {
+ data.theme_icon_override[dname]->disconnect("changed", callable_mp(this, &Control::_notify_theme_override_changed));
}
- data.icon_override.erase(dname);
+ data.theme_icon_override.erase(dname);
_notify_theme_override_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::_notify_theme_override_changed));
+ if (data.theme_style_override.has(dname)) {
+ data.theme_style_override[dname]->disconnect("changed", callable_mp(this, &Control::_notify_theme_override_changed));
}
- data.style_override.erase(dname);
+ data.theme_style_override.erase(dname);
_notify_theme_override_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::_notify_theme_override_changed));
+ if (data.theme_font_override.has(dname)) {
+ data.theme_font_override[dname]->disconnect("changed", callable_mp(this, &Control::_notify_theme_override_changed));
}
- data.font_override.erase(dname);
+ data.theme_font_override.erase(dname);
_notify_theme_override_changed();
} else if (name.begins_with("theme_override_font_sizes/")) {
String dname = name.get_slicec('/', 1);
- data.font_size_override.erase(dname);
+ data.theme_font_size_override.erase(dname);
_notify_theme_override_changed();
} else if (name.begins_with("theme_override_colors/")) {
String dname = name.get_slicec('/', 1);
- data.color_override.erase(dname);
+ data.theme_color_override.erase(dname);
_notify_theme_override_changed();
} else if (name.begins_with("theme_override_constants/")) {
String dname = name.get_slicec('/', 1);
- data.constant_override.erase(dname);
+ data.theme_constant_override.erase(dname);
_notify_theme_override_changed();
} else {
return false;
@@ -322,22 +326,22 @@ bool Control::_get(const StringName &p_name, Variant &r_ret) const {
if (sname.begins_with("theme_override_icons/")) {
String name = sname.get_slicec('/', 1);
- r_ret = data.icon_override.has(name) ? Variant(data.icon_override[name]) : Variant();
+ r_ret = data.theme_icon_override.has(name) ? Variant(data.theme_icon_override[name]) : Variant();
} else if (sname.begins_with("theme_override_styles/")) {
String name = sname.get_slicec('/', 1);
- r_ret = data.style_override.has(name) ? Variant(data.style_override[name]) : Variant();
+ r_ret = data.theme_style_override.has(name) ? Variant(data.theme_style_override[name]) : Variant();
} else if (sname.begins_with("theme_override_fonts/")) {
String name = sname.get_slicec('/', 1);
- r_ret = data.font_override.has(name) ? Variant(data.font_override[name]) : Variant();
+ r_ret = data.theme_font_override.has(name) ? Variant(data.theme_font_override[name]) : Variant();
} else if (sname.begins_with("theme_override_font_sizes/")) {
String name = sname.get_slicec('/', 1);
- r_ret = data.font_size_override.has(name) ? Variant(data.font_size_override[name]) : Variant();
+ r_ret = data.theme_font_size_override.has(name) ? Variant(data.theme_font_size_override[name]) : Variant();
} else if (sname.begins_with("theme_override_colors/")) {
String name = sname.get_slicec('/', 1);
- r_ret = data.color_override.has(name) ? Variant(data.color_override[name]) : Variant();
+ r_ret = data.theme_color_override.has(name) ? Variant(data.theme_color_override[name]) : Variant();
} else if (sname.begins_with("theme_override_constants/")) {
String name = sname.get_slicec('/', 1);
- r_ret = data.constant_override.has(name) ? Variant(data.constant_override[name]) : Variant();
+ r_ret = data.theme_constant_override.has(name) ? Variant(data.theme_constant_override[name]) : Variant();
} else {
return false;
}
@@ -346,16 +350,16 @@ bool Control::_get(const StringName &p_name, Variant &r_ret) const {
}
void Control::_get_property_list(List<PropertyInfo> *p_list) const {
- Ref<Theme> theme = ThemeDB::get_singleton()->get_default_theme();
+ Ref<Theme> default_theme = ThemeDB::get_singleton()->get_default_theme();
p_list->push_back(PropertyInfo(Variant::NIL, TTRC("Theme Overrides"), PROPERTY_HINT_NONE, "theme_override_", PROPERTY_USAGE_GROUP));
{
List<StringName> names;
- theme->get_color_list(get_class_name(), &names);
+ default_theme->get_color_list(get_class_name(), &names);
for (const StringName &E : names) {
uint32_t usage = PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_CHECKABLE;
- if (data.color_override.has(E)) {
+ if (data.theme_color_override.has(E)) {
usage |= PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_CHECKED;
}
@@ -364,10 +368,10 @@ void Control::_get_property_list(List<PropertyInfo> *p_list) const {
}
{
List<StringName> names;
- theme->get_constant_list(get_class_name(), &names);
+ default_theme->get_constant_list(get_class_name(), &names);
for (const StringName &E : names) {
uint32_t usage = PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_CHECKABLE;
- if (data.constant_override.has(E)) {
+ if (data.theme_constant_override.has(E)) {
usage |= PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_CHECKED;
}
@@ -376,10 +380,10 @@ void Control::_get_property_list(List<PropertyInfo> *p_list) const {
}
{
List<StringName> names;
- theme->get_font_list(get_class_name(), &names);
+ default_theme->get_font_list(get_class_name(), &names);
for (const StringName &E : names) {
uint32_t usage = PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_CHECKABLE;
- if (data.font_override.has(E)) {
+ if (data.theme_font_override.has(E)) {
usage |= PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_CHECKED;
}
@@ -388,10 +392,10 @@ void Control::_get_property_list(List<PropertyInfo> *p_list) const {
}
{
List<StringName> names;
- theme->get_font_size_list(get_class_name(), &names);
+ default_theme->get_font_size_list(get_class_name(), &names);
for (const StringName &E : names) {
uint32_t usage = PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_CHECKABLE;
- if (data.font_size_override.has(E)) {
+ if (data.theme_font_size_override.has(E)) {
usage |= PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_CHECKED;
}
@@ -400,10 +404,10 @@ void Control::_get_property_list(List<PropertyInfo> *p_list) const {
}
{
List<StringName> names;
- theme->get_icon_list(get_class_name(), &names);
+ default_theme->get_icon_list(get_class_name(), &names);
for (const StringName &E : names) {
uint32_t usage = PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_CHECKABLE;
- if (data.icon_override.has(E)) {
+ if (data.theme_icon_override.has(E)) {
usage |= PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_CHECKED;
}
@@ -412,10 +416,10 @@ void Control::_get_property_list(List<PropertyInfo> *p_list) const {
}
{
List<StringName> names;
- theme->get_stylebox_list(get_class_name(), &names);
+ default_theme->get_stylebox_list(get_class_name(), &names);
for (const StringName &E : names) {
uint32_t usage = PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_CHECKABLE;
- if (data.style_override.has(E)) {
+ if (data.theme_style_override.has(E)) {
usage |= PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_CHECKED;
}
@@ -481,10 +485,10 @@ void Control::_validate_property(PropertyInfo &p_property) const {
}
} else if (Object::cast_to<Container>(parent_node)) {
// If the parent is a container, display only container-related properties.
- if (p_property.name.begins_with("anchor_") || p_property.name.begins_with("offset_") || p_property.name.begins_with("grow_") || p_property.name == "anchors_preset" ||
- p_property.name == "position" || p_property.name == "rotation" || p_property.name == "scale" || p_property.name == "size" || p_property.name == "pivot_offset") {
- p_property.usage ^= PROPERTY_USAGE_EDITOR;
-
+ if (p_property.name.begins_with("anchor_") || p_property.name.begins_with("offset_") || p_property.name.begins_with("grow_") || p_property.name == "anchors_preset") {
+ p_property.usage ^= PROPERTY_USAGE_DEFAULT;
+ } else if (p_property.name == "position" || p_property.name == "rotation" || p_property.name == "scale" || p_property.name == "size" || p_property.name == "pivot_offset") {
+ p_property.usage = PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_READ_ONLY;
} else if (p_property.name == "layout_mode") {
// Set the layout mode to be disabled with the proper value.
p_property.hint_string = "Position,Anchors,Container,Uncontrolled";
@@ -1471,10 +1475,18 @@ void Control::set_rotation(real_t p_radians) {
_notify_transform();
}
+void Control::set_rotation_degrees(real_t p_degrees) {
+ set_rotation(Math::deg_to_rad(p_degrees));
+}
+
real_t Control::get_rotation() const {
return data.rotation;
}
+real_t Control::get_rotation_degrees() const {
+ return Math::rad_to_deg(get_rotation());
+}
+
void Control::set_pivot_offset(const Vector2 &p_pivot) {
if (data.pivot_offset == p_pivot) {
return;
@@ -1559,6 +1571,12 @@ void Control::set_custom_minimum_size(const Size2 &p_custom) {
if (p_custom == data.custom_minimum_size) {
return;
}
+
+ if (isnan(p_custom.x) || isnan(p_custom.y)) {
+ // Prevent infinite loop.
+ return;
+ }
+
data.custom_minimum_size = p_custom;
update_minimum_size();
}
@@ -2377,7 +2395,7 @@ StringName Control::get_theme_type_variation() const {
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);
+ const Ref<Texture2D> *tex = data.theme_icon_override.getptr(p_name);
if (tex) {
return *tex;
}
@@ -2396,7 +2414,7 @@ Ref<Texture2D> Control::get_theme_icon(const StringName &p_name, const StringNam
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);
+ const Ref<StyleBox> *style = data.theme_style_override.getptr(p_name);
if (style) {
return *style;
}
@@ -2415,7 +2433,7 @@ Ref<StyleBox> Control::get_theme_stylebox(const StringName &p_name, const String
Ref<Font> Control::get_theme_font(const StringName &p_name, const StringName &p_theme_type) const {
if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) {
- const Ref<Font> *font = data.font_override.getptr(p_name);
+ const Ref<Font> *font = data.theme_font_override.getptr(p_name);
if (font) {
return *font;
}
@@ -2434,7 +2452,7 @@ Ref<Font> Control::get_theme_font(const StringName &p_name, const StringName &p_
int Control::get_theme_font_size(const StringName &p_name, const StringName &p_theme_type) const {
if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) {
- const int *font_size = data.font_size_override.getptr(p_name);
+ const int *font_size = data.theme_font_size_override.getptr(p_name);
if (font_size && (*font_size) > 0) {
return *font_size;
}
@@ -2453,7 +2471,7 @@ int Control::get_theme_font_size(const StringName &p_name, const StringName &p_t
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);
+ const Color *color = data.theme_color_override.getptr(p_name);
if (color) {
return *color;
}
@@ -2472,7 +2490,7 @@ Color Control::get_theme_color(const StringName &p_name, const StringName &p_the
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);
+ const int *constant = data.theme_constant_override.getptr(p_name);
if (constant) {
return *constant;
}
@@ -2566,123 +2584,123 @@ bool Control::has_theme_constant(const StringName &p_name, const StringName &p_t
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::_notify_theme_override_changed));
+ if (data.theme_icon_override.has(p_name)) {
+ data.theme_icon_override[p_name]->disconnect("changed", callable_mp(this, &Control::_notify_theme_override_changed));
}
- data.icon_override[p_name] = p_icon;
- data.icon_override[p_name]->connect("changed", callable_mp(this, &Control::_notify_theme_override_changed), CONNECT_REFERENCE_COUNTED);
+ data.theme_icon_override[p_name] = p_icon;
+ data.theme_icon_override[p_name]->connect("changed", callable_mp(this, &Control::_notify_theme_override_changed), CONNECT_REFERENCE_COUNTED);
_notify_theme_override_changed();
}
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::_notify_theme_override_changed));
+ if (data.theme_style_override.has(p_name)) {
+ data.theme_style_override[p_name]->disconnect("changed", callable_mp(this, &Control::_notify_theme_override_changed));
}
- data.style_override[p_name] = p_style;
- data.style_override[p_name]->connect("changed", callable_mp(this, &Control::_notify_theme_override_changed), CONNECT_REFERENCE_COUNTED);
+ data.theme_style_override[p_name] = p_style;
+ data.theme_style_override[p_name]->connect("changed", callable_mp(this, &Control::_notify_theme_override_changed), CONNECT_REFERENCE_COUNTED);
_notify_theme_override_changed();
}
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::_notify_theme_override_changed));
+ if (data.theme_font_override.has(p_name)) {
+ data.theme_font_override[p_name]->disconnect("changed", callable_mp(this, &Control::_notify_theme_override_changed));
}
- data.font_override[p_name] = p_font;
- data.font_override[p_name]->connect("changed", callable_mp(this, &Control::_notify_theme_override_changed), CONNECT_REFERENCE_COUNTED);
+ data.theme_font_override[p_name] = p_font;
+ data.theme_font_override[p_name]->connect("changed", callable_mp(this, &Control::_notify_theme_override_changed), CONNECT_REFERENCE_COUNTED);
_notify_theme_override_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;
+ data.theme_font_size_override[p_name] = p_font_size;
_notify_theme_override_changed();
}
void Control::add_theme_color_override(const StringName &p_name, const Color &p_color) {
- data.color_override[p_name] = p_color;
+ data.theme_color_override[p_name] = p_color;
_notify_theme_override_changed();
}
void Control::add_theme_constant_override(const StringName &p_name, int p_constant) {
- data.constant_override[p_name] = p_constant;
+ data.theme_constant_override[p_name] = p_constant;
_notify_theme_override_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::_notify_theme_override_changed));
+ if (data.theme_icon_override.has(p_name)) {
+ data.theme_icon_override[p_name]->disconnect("changed", callable_mp(this, &Control::_notify_theme_override_changed));
}
- data.icon_override.erase(p_name);
+ data.theme_icon_override.erase(p_name);
_notify_theme_override_changed();
}
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::_notify_theme_override_changed));
+ if (data.theme_style_override.has(p_name)) {
+ data.theme_style_override[p_name]->disconnect("changed", callable_mp(this, &Control::_notify_theme_override_changed));
}
- data.style_override.erase(p_name);
+ data.theme_style_override.erase(p_name);
_notify_theme_override_changed();
}
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::_notify_theme_override_changed));
+ if (data.theme_font_override.has(p_name)) {
+ data.theme_font_override[p_name]->disconnect("changed", callable_mp(this, &Control::_notify_theme_override_changed));
}
- data.font_override.erase(p_name);
+ data.theme_font_override.erase(p_name);
_notify_theme_override_changed();
}
void Control::remove_theme_font_size_override(const StringName &p_name) {
- data.font_size_override.erase(p_name);
+ data.theme_font_size_override.erase(p_name);
_notify_theme_override_changed();
}
void Control::remove_theme_color_override(const StringName &p_name) {
- data.color_override.erase(p_name);
+ data.theme_color_override.erase(p_name);
_notify_theme_override_changed();
}
void Control::remove_theme_constant_override(const StringName &p_name) {
- data.constant_override.erase(p_name);
+ data.theme_constant_override.erase(p_name);
_notify_theme_override_changed();
}
bool Control::has_theme_icon_override(const StringName &p_name) const {
- const Ref<Texture2D> *tex = data.icon_override.getptr(p_name);
+ const Ref<Texture2D> *tex = data.theme_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);
+ const Ref<StyleBox> *style = data.theme_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);
+ const Ref<Font> *font = data.theme_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);
+ const int *font_size = data.theme_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);
+ const Color *color = data.theme_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);
+ const int *constant = data.theme_constant_override.getptr(p_name);
return constant != nullptr;
}
@@ -2773,6 +2791,20 @@ bool Control::is_layout_rtl() const {
return data.is_rtl;
}
+void Control::set_localize_numeral_system(bool p_enable) {
+ if (p_enable == data.localize_numeral_system) {
+ return;
+ }
+
+ data.localize_numeral_system = p_enable;
+
+ notification(MainLoop::NOTIFICATION_TRANSLATION_CHANGED);
+}
+
+bool Control::is_localizing_numeral_system() const {
+ return data.localize_numeral_system;
+}
+
void Control::set_auto_translate(bool p_enable) {
if (p_enable == data.auto_translate) {
return;
@@ -2921,7 +2953,7 @@ void Control::_notification(int p_notification) {
queue_redraw();
if (data.RI) {
- get_viewport()->_gui_set_root_order_dirty();
+ get_viewport()->gui_set_root_order_dirty();
}
} break;
@@ -3018,6 +3050,7 @@ void Control::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_global_position", "position", "keep_offsets"), &Control::set_global_position, DEFVAL(false));
ClassDB::bind_method(D_METHOD("_set_global_position", "position"), &Control::_set_global_position);
ClassDB::bind_method(D_METHOD("set_rotation", "radians"), &Control::set_rotation);
+ ClassDB::bind_method(D_METHOD("set_rotation_degrees", "degrees"), &Control::set_rotation_degrees);
ClassDB::bind_method(D_METHOD("set_scale", "scale"), &Control::set_scale);
ClassDB::bind_method(D_METHOD("set_pivot_offset", "pivot_offset"), &Control::set_pivot_offset);
ClassDB::bind_method(D_METHOD("get_begin"), &Control::get_begin);
@@ -3025,6 +3058,7 @@ void Control::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_position"), &Control::get_position);
ClassDB::bind_method(D_METHOD("get_size"), &Control::get_size);
ClassDB::bind_method(D_METHOD("get_rotation"), &Control::get_rotation);
+ ClassDB::bind_method(D_METHOD("get_rotation_degrees"), &Control::get_rotation_degrees);
ClassDB::bind_method(D_METHOD("get_scale"), &Control::get_scale);
ClassDB::bind_method(D_METHOD("get_pivot_offset"), &Control::get_pivot_offset);
ClassDB::bind_method(D_METHOD("get_custom_minimum_size"), &Control::get_custom_minimum_size);
@@ -3154,6 +3188,9 @@ void Control::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_auto_translate", "enable"), &Control::set_auto_translate);
ClassDB::bind_method(D_METHOD("is_auto_translating"), &Control::is_auto_translating);
+ ClassDB::bind_method(D_METHOD("set_localize_numeral_system", "enable"), &Control::set_localize_numeral_system);
+ ClassDB::bind_method(D_METHOD("is_localizing_numeral_system"), &Control::is_localizing_numeral_system);
+
ADD_GROUP("Layout", "");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "clip_contents"), "set_clip_contents", "is_clipping_contents");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "custom_minimum_size", PROPERTY_HINT_NONE, "suffix:px"), "set_custom_minimum_size", "get_custom_minimum_size");
@@ -3190,6 +3227,7 @@ void Control::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "position", PROPERTY_HINT_NONE, "suffix:px", PROPERTY_USAGE_EDITOR), "_set_position", "get_position");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "global_position", PROPERTY_HINT_NONE, "suffix:px", PROPERTY_USAGE_NONE), "_set_global_position", "get_global_position");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "rotation", PROPERTY_HINT_RANGE, "-360,360,0.1,or_less,or_greater,radians"), "set_rotation", "get_rotation");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "rotation_degrees", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_rotation_degrees", "get_rotation_degrees");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "scale"), "set_scale", "get_scale");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "pivot_offset", PROPERTY_HINT_NONE, "suffix:px"), "set_pivot_offset", "get_pivot_offset");
@@ -3198,8 +3236,9 @@ void Control::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "size_flags_vertical", PROPERTY_HINT_FLAGS, "Fill:1,Expand:2,Shrink Center:4,Shrink End:8"), "set_v_size_flags", "get_v_size_flags");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "size_flags_stretch_ratio", PROPERTY_HINT_RANGE, "0,20,0.01,or_greater"), "set_stretch_ratio", "get_stretch_ratio");
- ADD_GROUP("Auto Translate", "");
+ ADD_GROUP("Localization", "");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "auto_translate"), "set_auto_translate", "is_auto_translating");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "localize_numeral_system"), "set_localize_numeral_system", "is_localizing_numeral_system");
ADD_GROUP("Tooltip", "tooltip_");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "tooltip_text", PROPERTY_HINT_MULTILINE_TEXT), "set_tooltip_text", "get_tooltip_text");
@@ -3337,21 +3376,21 @@ Control::~Control() {
memdelete(data.theme_owner);
// Resources need to be disconnected.
- for (KeyValue<StringName, Ref<Texture2D>> &E : data.icon_override) {
+ for (KeyValue<StringName, Ref<Texture2D>> &E : data.theme_icon_override) {
E.value->disconnect("changed", callable_mp(this, &Control::_notify_theme_override_changed));
}
- for (KeyValue<StringName, Ref<StyleBox>> &E : data.style_override) {
+ for (KeyValue<StringName, Ref<StyleBox>> &E : data.theme_style_override) {
E.value->disconnect("changed", callable_mp(this, &Control::_notify_theme_override_changed));
}
- for (KeyValue<StringName, Ref<Font>> &E : data.font_override) {
+ for (KeyValue<StringName, Ref<Font>> &E : data.theme_font_override) {
E.value->disconnect("changed", callable_mp(this, &Control::_notify_theme_override_changed));
}
// Then override maps can be simply cleared.
- data.icon_override.clear();
- data.style_override.clear();
- data.font_override.clear();
- data.font_size_override.clear();
- data.color_override.clear();
- data.constant_override.clear();
+ data.theme_icon_override.clear();
+ data.theme_style_override.clear();
+ data.theme_font_override.clear();
+ data.theme_font_size_override.clear();
+ data.theme_color_override.clear();
+ data.theme_constant_override.clear();
}
diff --git a/scene/gui/control.h b/scene/gui/control.h
index 72e870930d..f82fba3b1b 100644
--- a/scene/gui/control.h
+++ b/scene/gui/control.h
@@ -228,12 +228,12 @@ private:
StringName theme_type_variation;
bool bulk_theme_override = false;
- Theme::ThemeIconMap icon_override;
- Theme::ThemeStyleMap style_override;
- Theme::ThemeFontMap font_override;
- Theme::ThemeFontSizeMap font_size_override;
- Theme::ThemeColorMap color_override;
- Theme::ThemeConstantMap constant_override;
+ Theme::ThemeIconMap theme_icon_override;
+ Theme::ThemeStyleMap theme_style_override;
+ Theme::ThemeFontMap theme_font_override;
+ Theme::ThemeFontSizeMap theme_font_size_override;
+ Theme::ThemeColorMap theme_color_override;
+ Theme::ThemeConstantMap theme_constant_override;
mutable HashMap<StringName, Theme::ThemeIconMap> theme_icon_cache;
mutable HashMap<StringName, Theme::ThemeStyleMap> theme_style_cache;
@@ -249,6 +249,7 @@ private:
bool is_rtl = false;
bool auto_translate = true;
+ bool localize_numeral_system = true;
// Extra properties.
@@ -450,7 +451,9 @@ public:
void set_scale(const Vector2 &p_scale);
Vector2 get_scale() const;
void set_rotation(real_t p_radians);
+ void set_rotation_degrees(real_t p_degrees);
real_t get_rotation() const;
+ real_t get_rotation_degrees() const;
void set_pivot_offset(const Vector2 &p_pivot);
Vector2 get_pivot_offset() const;
@@ -595,6 +598,9 @@ public:
LayoutDirection get_layout_direction() const;
virtual bool is_layout_rtl() const;
+ void set_localize_numeral_system(bool p_enable);
+ bool is_localizing_numeral_system() const;
+
void set_auto_translate(bool p_enable);
bool is_auto_translating() const;
_FORCE_INLINE_ String atr(const String p_string) const {
diff --git a/scene/gui/dialogs.cpp b/scene/gui/dialogs.cpp
index bf4dd3d245..0d265719ec 100644
--- a/scene/gui/dialogs.cpp
+++ b/scene/gui/dialogs.cpp
@@ -377,7 +377,7 @@ void AcceptDialog::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::STRING, "ok_button_text"), "set_ok_button_text", "get_ok_button_text");
- ADD_GROUP("Dialog", "dialog");
+ 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");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "dialog_close_on_escape"), "set_close_on_escape", "get_close_on_escape");
diff --git a/scene/gui/file_dialog.cpp b/scene/gui/file_dialog.cpp
index cade65108c..11a3803b35 100644
--- a/scene/gui/file_dialog.cpp
+++ b/scene/gui/file_dialog.cpp
@@ -632,8 +632,11 @@ void FileDialog::update_file_list() {
files.pop_front();
}
- if (tree->get_root() && tree->get_root()->get_first_child() && tree->get_selected() == nullptr) {
- tree->get_root()->get_first_child()->select(0);
+ if (mode != FILE_MODE_SAVE_FILE) {
+ // Select the first file from list if nothing is selected.
+ if (tree->get_root() && tree->get_root()->get_first_child() && tree->get_selected() == nullptr) {
+ tree->get_root()->get_first_child()->select(0);
+ }
}
}
diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp
index 46b712379d..1c4c8c2574 100644
--- a/scene/gui/graph_edit.cpp
+++ b/scene/gui/graph_edit.cpp
@@ -623,7 +623,7 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) {
//check disconnect
for (const Connection &E : connections) {
if (E.from == gn->get_name() && E.from_port == j) {
- Node *to = get_node(String(E.to));
+ Node *to = get_node(NodePath(E.to));
if (Object::cast_to<GraphNode>(to)) {
connecting_from = E.to;
connecting_index = E.to_port;
@@ -637,7 +637,7 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) {
just_disconnected = true;
emit_signal(SNAME("disconnection_request"), E.from, E.from_port, E.to, E.to_port);
- to = get_node(String(connecting_from)); //maybe it was erased
+ to = get_node(NodePath(connecting_from)); // Maybe it was erased.
if (Object::cast_to<GraphNode>(to)) {
connecting = true;
emit_signal(SNAME("connection_drag_started"), connecting_from, connecting_index, false);
@@ -673,10 +673,10 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) {
if (is_in_input_hotzone(gn, j, click_pos, port_size)) {
if (right_disconnects || valid_right_disconnect_types.has(gn->get_connection_input_type(j))) {
- //check disconnect
+ // Check disconnect.
for (const Connection &E : connections) {
if (E.to == gn->get_name() && E.to_port == j) {
- Node *fr = get_node(String(E.from));
+ Node *fr = get_node(NodePath(E.from));
if (Object::cast_to<GraphNode>(fr)) {
connecting_from = E.from;
connecting_index = E.from_port;
@@ -689,7 +689,7 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) {
if (connecting_type >= 0) {
emit_signal(SNAME("disconnection_request"), E.from, E.from_port, E.to, E.to_port);
- fr = get_node(String(connecting_from)); //maybe it was erased
+ fr = get_node(NodePath(connecting_from)); // Maybe it was erased.
if (Object::cast_to<GraphNode>(fr)) {
connecting = true;
emit_signal(SNAME("connection_drag_started"), connecting_from, connecting_index, true);
@@ -780,26 +780,16 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) {
if (mb.is_valid() && mb->get_button_index() == MouseButton::LEFT && !mb->is_pressed()) {
if (connecting_valid) {
if (connecting && connecting_target) {
- String from = connecting_from;
- int from_port = connecting_index;
- String to = connecting_target_to;
- int to_port = connecting_target_index;
-
- if (!connecting_out) {
- SWAP(from, to);
- SWAP(from_port, to_port);
+ if (connecting_out) {
+ emit_signal(SNAME("connection_request"), connecting_from, connecting_index, connecting_target_to, connecting_target_index);
+ } else {
+ emit_signal(SNAME("connection_request"), connecting_target_to, connecting_target_index, connecting_from, connecting_index);
}
- emit_signal(SNAME("connection_request"), from, from_port, to, to_port);
-
} else if (!just_disconnected) {
- String from = connecting_from;
- int from_port = connecting_index;
- Vector2 ofs = mb->get_position();
-
- if (!connecting_out) {
- emit_signal(SNAME("connection_from_empty"), from, from_port, ofs);
+ if (connecting_out) {
+ emit_signal(SNAME("connection_to_empty"), connecting_from, connecting_index, mb->get_position());
} else {
- emit_signal(SNAME("connection_to_empty"), from, from_port, ofs);
+ emit_signal(SNAME("connection_from_empty"), connecting_from, connecting_index, mb->get_position());
}
}
}
@@ -935,17 +925,12 @@ void GraphEdit::_draw_connection_line(CanvasItem *p_where, const Vector2 &p_from
void GraphEdit::_connections_layer_draw() {
Color activity_color = get_theme_color(SNAME("activity"));
- //draw connections
+ // Draw connections.
List<List<Connection>::Element *> to_erase;
for (List<Connection>::Element *E = connections.front(); E; E = E->next()) {
- NodePath fromnp(E->get().from);
-
- Node *from = get_node(fromnp);
- if (!from) {
- to_erase.push_back(E);
- continue;
- }
+ const Connection &c = E->get();
+ Node *from = get_node(NodePath(c.from));
GraphNode *gfrom = Object::cast_to<GraphNode>(from);
if (!gfrom) {
@@ -953,13 +938,7 @@ void GraphEdit::_connections_layer_draw() {
continue;
}
- NodePath tonp(E->get().to);
- Node *to = get_node(tonp);
- if (!to) {
- to_erase.push_back(E);
- continue;
- }
-
+ Node *to = get_node(NodePath(c.to));
GraphNode *gto = Object::cast_to<GraphNode>(to);
if (!gto) {
@@ -967,21 +946,20 @@ void GraphEdit::_connections_layer_draw() {
continue;
}
- Vector2 frompos = gfrom->get_connection_output_position(E->get().from_port) + gfrom->get_position_offset() * zoom;
- Color color = gfrom->get_connection_output_color(E->get().from_port);
- Vector2 topos = gto->get_connection_input_position(E->get().to_port) + gto->get_position_offset() * zoom;
- Color tocolor = gto->get_connection_input_color(E->get().to_port);
+ Vector2 frompos = gfrom->get_connection_output_position(c.from_port) + gfrom->get_position_offset() * zoom;
+ Color color = gfrom->get_connection_output_color(c.from_port);
+ Vector2 topos = gto->get_connection_input_position(c.to_port) + gto->get_position_offset() * zoom;
+ Color tocolor = gto->get_connection_input_color(c.to_port);
- if (E->get().activity > 0) {
- color = color.lerp(activity_color, E->get().activity);
- tocolor = tocolor.lerp(activity_color, E->get().activity);
+ if (c.activity > 0) {
+ color = color.lerp(activity_color, c.activity);
+ tocolor = tocolor.lerp(activity_color, c.activity);
}
_draw_connection_line(connections_layer, frompos, topos, color, tocolor, lines_thickness, zoom);
}
- while (to_erase.size()) {
- connections.erase(to_erase.front()->get());
- to_erase.pop_front();
+ for (List<Connection>::Element *&E : to_erase) {
+ connections.erase(E);
}
}
@@ -989,7 +967,7 @@ void GraphEdit::_top_layer_draw() {
_update_scroll();
if (connecting) {
- Node *fromn = get_node(connecting_from);
+ Node *fromn = get_node(NodePath(connecting_from));
ERR_FAIL_COND(!fromn);
GraphNode *from = Object::cast_to<GraphNode>(fromn);
ERR_FAIL_COND(!from);
@@ -1087,22 +1065,13 @@ void GraphEdit::_minimap_draw() {
// Draw node connections.
Color activity_color = get_theme_color(SNAME("activity"));
for (const Connection &E : connections) {
- NodePath fromnp(E.from);
-
- Node *from = get_node(fromnp);
- if (!from) {
- continue;
- }
+ Node *from = get_node(NodePath(E.from));
GraphNode *gfrom = Object::cast_to<GraphNode>(from);
if (!gfrom) {
continue;
}
- NodePath tonp(E.to);
- Node *to = get_node(tonp);
- if (!to) {
- continue;
- }
+ Node *to = get_node(NodePath(E.to));
GraphNode *gto = Object::cast_to<GraphNode>(to);
if (!gto) {
continue;
@@ -2406,7 +2375,7 @@ void GraphEdit::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "zoom_step"), "set_zoom_step", "get_zoom_step");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "show_zoom_label"), "set_show_zoom_label", "is_showing_zoom_label");
- ADD_GROUP("Minimap", "minimap");
+ ADD_GROUP("Minimap", "minimap_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "minimap_enabled"), "set_minimap_enabled", "is_minimap_enabled");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "minimap_size", PROPERTY_HINT_NONE, "suffix:px"), "set_minimap_size", "get_minimap_size");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "minimap_opacity"), "set_minimap_opacity", "get_minimap_opacity");
@@ -2428,7 +2397,7 @@ void GraphEdit::_bind_methods() {
ADD_SIGNAL(MethodInfo("begin_node_move"));
ADD_SIGNAL(MethodInfo("end_node_move"));
ADD_SIGNAL(MethodInfo("scroll_offset_changed", PropertyInfo(Variant::VECTOR2, "offset")));
- ADD_SIGNAL(MethodInfo("connection_drag_started", PropertyInfo(Variant::STRING, "from_node"), PropertyInfo(Variant::INT, "from_port"), PropertyInfo(Variant::BOOL, "is_output")));
+ ADD_SIGNAL(MethodInfo("connection_drag_started", PropertyInfo(Variant::STRING_NAME, "from_node"), PropertyInfo(Variant::INT, "from_port"), PropertyInfo(Variant::BOOL, "is_output")));
ADD_SIGNAL(MethodInfo("connection_drag_ended"));
BIND_ENUM_CONSTANT(SCROLL_ZOOMS);
diff --git a/scene/gui/graph_edit.h b/scene/gui/graph_edit.h
index 101087bdbd..eda7ddd824 100644
--- a/scene/gui/graph_edit.h
+++ b/scene/gui/graph_edit.h
@@ -136,14 +136,14 @@ private:
bool arrange_nodes_button_hidden = false;
bool connecting = false;
- String connecting_from;
+ StringName connecting_from;
bool connecting_out = false;
int connecting_index = 0;
int connecting_type = 0;
Color connecting_color;
bool connecting_target = false;
Vector2 connecting_to;
- String connecting_target_to;
+ StringName connecting_target_to;
int connecting_target_index = 0;
bool just_disconnected = false;
bool connecting_valid = false;
diff --git a/scene/gui/graph_node.cpp b/scene/gui/graph_node.cpp
index 5df4c066e4..83c789f3d5 100644
--- a/scene/gui/graph_node.cpp
+++ b/scene/gui/graph_node.cpp
@@ -366,38 +366,46 @@ void GraphNode::_notification(int p_what) {
close_rect = Rect2();
}
- for (const KeyValue<int, Slot> &E : slot_info) {
- if (E.key < 0 || E.key >= cache_y.size()) {
- continue;
- }
- if (!slot_info.has(E.key)) {
- continue;
- }
- const Slot &s = slot_info[E.key];
- // Left port.
- if (s.enable_left) {
- Ref<Texture2D> p = port;
- if (s.custom_slot_left.is_valid()) {
- p = s.custom_slot_left;
+ if (get_child_count() > 0) {
+ for (const KeyValue<int, Slot> &E : slot_info) {
+ if (E.key < 0 || E.key >= cache_y.size()) {
+ continue;
}
- p->draw(get_canvas_item(), icofs + Point2(edgeofs, cache_y[E.key]), s.color_left);
- }
- // Right port.
- if (s.enable_right) {
- Ref<Texture2D> p = port;
- if (s.custom_slot_right.is_valid()) {
- p = s.custom_slot_right;
+ if (!slot_info.has(E.key)) {
+ continue;
+ }
+ const Slot &s = slot_info[E.key];
+ // Left port.
+ if (s.enable_left) {
+ Ref<Texture2D> p = port;
+ if (s.custom_slot_left.is_valid()) {
+ p = s.custom_slot_left;
+ }
+ p->draw(get_canvas_item(), icofs + Point2(edgeofs, cache_y[E.key]), s.color_left);
+ }
+ // Right port.
+ if (s.enable_right) {
+ Ref<Texture2D> p = port;
+ if (s.custom_slot_right.is_valid()) {
+ p = s.custom_slot_right;
+ }
+ p->draw(get_canvas_item(), icofs + Point2(get_size().x - edgeofs, cache_y[E.key]), s.color_right);
}
- p->draw(get_canvas_item(), icofs + Point2(get_size().x - edgeofs, cache_y[E.key]), s.color_right);
- }
- // Draw slot stylebox.
- if (s.draw_stylebox) {
- Control *c = Object::cast_to<Control>(get_child(E.key));
- Rect2 c_rect = c->get_rect();
- c_rect.position.x = sb->get_margin(SIDE_LEFT);
- c_rect.size.width = w;
- draw_style_box(sb_slot, c_rect);
+ // Draw slot stylebox.
+ if (s.draw_stylebox) {
+ Control *c = Object::cast_to<Control>(get_child(E.key));
+ if (!c || !c->is_visible_in_tree()) {
+ continue;
+ }
+ if (c->is_set_as_top_level()) {
+ continue;
+ }
+ Rect2 c_rect = c->get_rect();
+ c_rect.position.x = sb->get_margin(SIDE_LEFT);
+ c_rect.size.width = w;
+ draw_style_box(sb_slot, c_rect);
+ }
}
}
diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp
index 82f089735d..c44feddd38 100644
--- a/scene/gui/item_list.cpp
+++ b/scene/gui/item_list.cpp
@@ -1550,6 +1550,7 @@ bool ItemList::get_allow_reselect() const {
}
void ItemList::set_icon_scale(real_t p_scale) {
+ ERR_FAIL_COND(!Math::is_finite(p_scale));
icon_scale = p_scale;
}
diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp
index 8a77c39487..b8e2c76413 100644
--- a/scene/gui/line_edit.cpp
+++ b/scene/gui/line_edit.cpp
@@ -768,18 +768,18 @@ void LineEdit::_notification(int p_what) {
case NOTIFICATION_WM_WINDOW_FOCUS_IN: {
window_has_focus = true;
- draw_caret = true;
+ _validate_caret_can_draw();
queue_redraw();
} break;
case NOTIFICATION_WM_WINDOW_FOCUS_OUT: {
window_has_focus = false;
- draw_caret = false;
+ _validate_caret_can_draw();
queue_redraw();
} break;
case NOTIFICATION_INTERNAL_PROCESS: {
- if (caret_blinking) {
+ if (caret_blink_enabled && caret_can_draw) {
caret_blink_timer += get_process_delta_time();
if (caret_blink_timer >= caret_blink_interval) {
@@ -790,10 +790,6 @@ void LineEdit::_notification(int p_what) {
} break;
case NOTIFICATION_DRAW: {
- if ((!has_focus() && !(menu && menu->has_focus()) && !caret_force_displayed) || !window_has_focus) {
- draw_caret = false;
- }
-
int width, height;
bool rtl = is_layout_rtl();
@@ -806,7 +802,6 @@ void LineEdit::_notification(int p_what) {
Ref<StyleBox> style = theme_cache.normal;
if (!is_editable()) {
style = theme_cache.read_only;
- draw_caret = false;
}
Ref<Font> font = theme_cache.font;
@@ -827,7 +822,7 @@ void LineEdit::_notification(int p_what) {
case HORIZONTAL_ALIGNMENT_FILL:
case HORIZONTAL_ALIGNMENT_LEFT: {
if (rtl) {
- x_ofs = MAX(style->get_margin(SIDE_LEFT), int(size.width - style->get_margin(SIDE_RIGHT) - (text_width)));
+ x_ofs = MAX(style->get_margin(SIDE_LEFT), int(size.width - Math::ceil(style->get_margin(SIDE_RIGHT) + (text_width))));
} else {
x_ofs = style->get_offset().x;
}
@@ -843,7 +838,7 @@ void LineEdit::_notification(int p_what) {
if (rtl) {
x_ofs = style->get_offset().x;
} else {
- x_ofs = MAX(style->get_margin(SIDE_LEFT), int(size.width - style->get_margin(SIDE_RIGHT) - (text_width)));
+ x_ofs = MAX(style->get_margin(SIDE_LEFT), int(size.width - Math::ceil(style->get_margin(SIDE_RIGHT) + (text_width))));
}
} break;
}
@@ -953,7 +948,7 @@ void LineEdit::_notification(int p_what) {
// Draw carets.
ofs.x = x_ofs + scroll_offset;
- if (draw_caret || drag_caret_force_displayed) {
+ if ((caret_can_draw && draw_caret) || drag_caret_force_displayed) {
// Prevent carets from disappearing at theme scales below 1.0 (if the caret width is 1).
const int caret_width = theme_cache.caret_width * MAX(1, theme_cache.base_scale);
@@ -1063,16 +1058,7 @@ void LineEdit::_notification(int p_what) {
} break;
case NOTIFICATION_FOCUS_ENTER: {
- if (!caret_force_displayed) {
- if (caret_blink_enabled) {
- if (!caret_blinking) {
- caret_blinking = true;
- caret_blink_timer = 0.0;
- }
- } else {
- draw_caret = true;
- }
- }
+ _validate_caret_can_draw();
if (select_all_on_focus) {
if (Input::get_singleton()->is_mouse_button_pressed(MouseButton::LEFT)) {
@@ -1093,9 +1079,7 @@ void LineEdit::_notification(int p_what) {
} break;
case NOTIFICATION_FOCUS_EXIT: {
- if (caret_blink_enabled && !caret_force_displayed) {
- caret_blinking = false;
- }
+ _validate_caret_can_draw();
if (get_viewport()->get_window_id() != DisplayServer::INVALID_WINDOW_ID && DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_IME)) {
DisplayServer::get_singleton()->window_set_ime_position(Point2(), get_viewport()->get_window_id());
@@ -1401,21 +1385,18 @@ bool LineEdit::is_caret_blink_enabled() const {
}
void LineEdit::set_caret_blink_enabled(const bool p_enabled) {
+ if (caret_blink_enabled == p_enabled) {
+ return;
+ }
+
caret_blink_enabled = p_enabled;
set_process_internal(p_enabled);
- if (has_focus() || caret_force_displayed) {
- if (p_enabled) {
- if (!caret_blinking) {
- caret_blinking = true;
- caret_blink_timer = 0.0;
- }
- } else {
- caret_blinking = false;
- }
+ draw_caret = !caret_blink_enabled;
+ if (caret_blink_enabled) {
+ caret_blink_timer = 0.0;
}
-
- draw_caret = true;
+ queue_redraw();
notify_property_list_changed();
}
@@ -1425,8 +1406,13 @@ bool LineEdit::is_caret_force_displayed() const {
}
void LineEdit::set_caret_force_displayed(const bool p_enabled) {
+ if (caret_force_displayed == p_enabled) {
+ return;
+ }
+
caret_force_displayed = p_enabled;
- set_caret_blink_enabled(caret_blink_enabled);
+ _validate_caret_can_draw();
+
queue_redraw();
}
@@ -1442,7 +1428,7 @@ void LineEdit::set_caret_blink_interval(const float p_interval) {
void LineEdit::_reset_caret_blink_timer() {
if (caret_blink_enabled) {
draw_caret = true;
- if (has_focus()) {
+ if (caret_can_draw) {
caret_blink_timer = 0.0;
queue_redraw();
}
@@ -1451,11 +1437,19 @@ void LineEdit::_reset_caret_blink_timer() {
void LineEdit::_toggle_draw_caret() {
draw_caret = !draw_caret;
- if (is_visible_in_tree() && ((has_focus() && window_has_focus) || caret_force_displayed)) {
+ if (is_visible_in_tree() && caret_can_draw) {
queue_redraw();
}
}
+void LineEdit::_validate_caret_can_draw() {
+ if (caret_blink_enabled) {
+ draw_caret = true;
+ caret_blink_timer = 0.0;
+ }
+ caret_can_draw = editable && (window_has_focus || (menu && menu->has_focus())) && (has_focus() || caret_force_displayed);
+}
+
void LineEdit::delete_char() {
if ((text.length() <= 0) || (caret_column == 0)) {
return;
@@ -1846,6 +1840,7 @@ void LineEdit::set_editable(bool p_editable) {
}
editable = p_editable;
+ _validate_caret_can_draw();
update_minimum_size();
queue_redraw();
@@ -2523,6 +2518,8 @@ void LineEdit::_ensure_menu() {
menu->add_child(menu_ctl, false, INTERNAL_MODE_FRONT);
menu->connect("id_pressed", callable_mp(this, &LineEdit::menu_option));
+ menu->connect(SNAME("focus_entered"), callable_mp(this, &LineEdit::_validate_caret_can_draw));
+ menu->connect(SNAME("focus_exited"), callable_mp(this, &LineEdit::_validate_caret_can_draw));
menu_dir->connect("id_pressed", callable_mp(this, &LineEdit::menu_option));
menu_ctl->connect("id_pressed", callable_mp(this, &LineEdit::menu_option));
}
diff --git a/scene/gui/line_edit.h b/scene/gui/line_edit.h
index e0a079b623..79db9dce21 100644
--- a/scene/gui/line_edit.h
+++ b/scene/gui/line_edit.h
@@ -172,7 +172,7 @@ private:
bool draw_caret = true;
float caret_blink_interval = 0.65;
double caret_blink_timer = 0.0;
- bool caret_blinking = false;
+ bool caret_can_draw = false;
bool pending_select_all_on_focus = false;
bool select_all_on_focus = false;
@@ -225,6 +225,7 @@ private:
void _reset_caret_blink_timer();
void _toggle_draw_caret();
+ void _validate_caret_can_draw();
void clear_internal();
diff --git a/scene/gui/link_button.cpp b/scene/gui/link_button.cpp
index 7219e86f52..2c43ca7143 100644
--- a/scene/gui/link_button.cpp
+++ b/scene/gui/link_button.cpp
@@ -108,6 +108,14 @@ String LinkButton::get_language() const {
return language;
}
+void LinkButton::set_uri(const String &p_uri) {
+ uri = p_uri;
+}
+
+String LinkButton::get_uri() const {
+ return uri;
+}
+
void LinkButton::set_underline_mode(UnderlineMode p_underline_mode) {
if (underline_mode == p_underline_mode) {
return;
@@ -121,6 +129,14 @@ LinkButton::UnderlineMode LinkButton::get_underline_mode() const {
return underline_mode;
}
+void LinkButton::pressed() {
+ if (uri.is_empty()) {
+ return;
+ }
+
+ OS::get_singleton()->shell_open(uri);
+}
+
Size2 LinkButton::get_minimum_size() const {
return text_buf->get_size();
}
@@ -245,6 +261,8 @@ void LinkButton::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_text_direction"), &LinkButton::get_text_direction);
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_uri", "uri"), &LinkButton::set_uri);
+ ClassDB::bind_method(D_METHOD("get_uri"), &LinkButton::get_uri);
ClassDB::bind_method(D_METHOD("set_underline_mode", "underline_mode"), &LinkButton::set_underline_mode);
ClassDB::bind_method(D_METHOD("get_underline_mode"), &LinkButton::get_underline_mode);
ClassDB::bind_method(D_METHOD("set_structured_text_bidi_override", "parser"), &LinkButton::set_structured_text_bidi_override);
@@ -258,6 +276,7 @@ void LinkButton::_bind_methods() {
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_PROPERTY(PropertyInfo(Variant::STRING, "uri"), "set_uri", "get_uri");
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");
diff --git a/scene/gui/link_button.h b/scene/gui/link_button.h
index accd848163..c71872fc86 100644
--- a/scene/gui/link_button.h
+++ b/scene/gui/link_button.h
@@ -49,6 +49,7 @@ private:
String xl_text;
Ref<TextLine> text_buf;
UnderlineMode underline_mode = UNDERLINE_MODE_ALWAYS;
+ String uri;
String language;
TextDirection text_direction = TEXT_DIRECTION_AUTO;
@@ -76,6 +77,7 @@ private:
void _shape();
protected:
+ virtual void pressed() override;
virtual Size2 get_minimum_size() const override;
virtual void _update_theme_item_cache() override;
void _notification(int p_what);
@@ -84,6 +86,8 @@ protected:
public:
void set_text(const String &p_text);
String get_text() const;
+ void set_uri(const String &p_uri);
+ String get_uri() const;
void set_structured_text_bidi_override(TextServer::StructuredTextParser p_parser);
TextServer::StructuredTextParser get_structured_text_bidi_override() const;
diff --git a/scene/gui/option_button.cpp b/scene/gui/option_button.cpp
index 0940b4c07b..6d0bbdd6af 100644
--- a/scene/gui/option_button.cpp
+++ b/scene/gui/option_button.cpp
@@ -491,9 +491,9 @@ void OptionButton::show_popup() {
return;
}
- Size2 size = get_size() * get_viewport()->get_canvas_transform().get_scale();
- popup->set_position(get_screen_position() + Size2(0, size.height * get_global_transform().get_scale().y));
- popup->set_size(Size2(size.width, 0));
+ Size2 button_size = get_global_transform_with_canvas().get_scale() * get_size();
+ popup->set_position(get_screen_position() + Size2(0, button_size.height));
+ popup->set_size(Size2i(button_size.width, 0));
// If not triggered by the mouse, start the popup with the checked item (or the first enabled one) focused.
if (current != NONE_SELECTED && !popup->is_item_disabled(current)) {
diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp
index 82f56a56c9..5d8e106e26 100644
--- a/scene/gui/popup_menu.cpp
+++ b/scene/gui/popup_menu.cpp
@@ -221,7 +221,7 @@ void PopupMenu::_activate_submenu(int p_over, bool p_by_keyboard) {
Rect2 safe_area = this_rect;
safe_area.position.y += items[p_over]._ofs_cache + scroll_offset + theme_cache.panel_style->get_offset().height - theme_cache.v_separation / 2;
- safe_area.size.y = items[p_over]._height_cache;
+ safe_area.size.y = items[p_over]._height_cache + theme_cache.v_separation;
DisplayServer::get_singleton()->window_set_popup_safe_rect(submenu_popup->get_window_id(), safe_area);
// Make the position of the parent popup relative to submenu popup.
@@ -558,7 +558,7 @@ void PopupMenu::_draw_items() {
check_ofs += theme_cache.h_separation;
}
- Point2 ofs = Point2();
+ Point2 ofs;
// Loop through all items and draw each.
for (int i = 0; i < items.size(); i++) {
diff --git a/scene/gui/progress_bar.cpp b/scene/gui/progress_bar.cpp
index 8369eaa227..50bcfa6a0c 100644
--- a/scene/gui/progress_bar.cpp
+++ b/scene/gui/progress_bar.cpp
@@ -103,7 +103,12 @@ void ProgressBar::_notification(int p_what) {
}
if (show_percentage) {
- String txt = TS->format_number(itos(int(get_as_ratio() * 100))) + TS->percent_sign();
+ String txt = itos(int(get_as_ratio() * 100));
+ if (is_localizing_numeral_system()) {
+ txt = TS->format_number(txt) + TS->percent_sign();
+ } else {
+ txt += String("%");
+ }
TextLine tl = TextLine(txt, theme_cache.font, theme_cache.font_size);
Vector2 text_pos = (Point2(get_size().width - tl.get_size().x, get_size().height - tl.get_size().y) / 2).round();
diff --git a/scene/gui/range.cpp b/scene/gui/range.cpp
index 27002fad38..00c81c8616 100644
--- a/scene/gui/range.cpp
+++ b/scene/gui/range.cpp
@@ -64,11 +64,6 @@ void Range::_changed_notify(const char *p_what) {
queue_redraw();
}
-void Range::_validate_values() {
- shared->max = MAX(shared->max, shared->min);
- shared->page = CLAMP(shared->page, 0, shared->max - shared->min);
-}
-
void Range::Shared::emit_changed(const char *p_what) {
for (Range *E : owners) {
Range *r = E;
@@ -90,7 +85,7 @@ void Range::set_value(double p_val) {
void Range::set_value_no_signal(double p_val) {
if (shared->step > 0) {
- p_val = Math::round(p_val / shared->step) * shared->step;
+ p_val = Math::round((p_val - shared->min) / shared->step) * shared->step + shared->min;
}
if (_rounded_values) {
@@ -118,8 +113,9 @@ void Range::set_min(double p_min) {
}
shared->min = p_min;
+ shared->max = MAX(shared->max, shared->min);
+ shared->page = CLAMP(shared->page, 0, shared->max - shared->min);
set_value(shared->val);
- _validate_values();
shared->emit_changed("min");
@@ -127,13 +123,14 @@ void Range::set_min(double p_min) {
}
void Range::set_max(double p_max) {
- if (shared->max == p_max) {
+ double max_validated = MAX(p_max, shared->min);
+ if (shared->max == max_validated) {
return;
}
- shared->max = p_max;
+ shared->max = max_validated;
+ shared->page = CLAMP(shared->page, 0, shared->max - shared->min);
set_value(shared->val);
- _validate_values();
shared->emit_changed("max");
}
@@ -148,13 +145,13 @@ void Range::set_step(double p_step) {
}
void Range::set_page(double p_page) {
- if (shared->page == p_page) {
+ double page_validated = CLAMP(p_page, 0, shared->max - shared->min);
+ if (shared->page == page_validated) {
return;
}
- shared->page = p_page;
+ shared->page = page_validated;
set_value(shared->val);
- _validate_values();
shared->emit_changed("page");
}
diff --git a/scene/gui/range.h b/scene/gui/range.h
index f804155dec..5267216f12 100644
--- a/scene/gui/range.h
+++ b/scene/gui/range.h
@@ -59,7 +59,6 @@ class Range : public Control {
void _value_changed_notify();
void _changed_notify(const char *p_what = "");
- void _validate_values();
protected:
virtual void _value_changed(double p_value);
diff --git a/scene/gui/rich_text_effect.cpp b/scene/gui/rich_text_effect.cpp
index 0dece1c287..20d82095a1 100644
--- a/scene/gui/rich_text_effect.cpp
+++ b/scene/gui/rich_text_effect.cpp
@@ -88,6 +88,9 @@ void CharFXTransform::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_glyph_index"), &CharFXTransform::get_glyph_index);
ClassDB::bind_method(D_METHOD("set_glyph_index", "glyph_index"), &CharFXTransform::set_glyph_index);
+ ClassDB::bind_method(D_METHOD("get_relative_index"), &CharFXTransform::get_relative_index);
+ ClassDB::bind_method(D_METHOD("set_relative_index", "relative_index"), &CharFXTransform::set_relative_index);
+
ClassDB::bind_method(D_METHOD("get_glyph_count"), &CharFXTransform::get_glyph_count);
ClassDB::bind_method(D_METHOD("set_glyph_count", "glyph_count"), &CharFXTransform::set_glyph_count);
@@ -107,5 +110,6 @@ void CharFXTransform::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "glyph_index"), "set_glyph_index", "get_glyph_index");
ADD_PROPERTY(PropertyInfo(Variant::INT, "glyph_count"), "set_glyph_count", "get_glyph_count");
ADD_PROPERTY(PropertyInfo(Variant::INT, "glyph_flags"), "set_glyph_flags", "get_glyph_flags");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "relative_index"), "set_relative_index", "get_relative_index");
ADD_PROPERTY(PropertyInfo(Variant::RID, "font"), "set_font", "get_font");
}
diff --git a/scene/gui/rich_text_effect.h b/scene/gui/rich_text_effect.h
index 4532a812ee..886442bc80 100644
--- a/scene/gui/rich_text_effect.h
+++ b/scene/gui/rich_text_effect.h
@@ -52,6 +52,7 @@ public:
uint32_t glyph_index = 0;
uint16_t glyph_flags = 0;
uint8_t glyph_count = 0;
+ int32_t relative_index = 0;
RID font;
CharFXTransform();
@@ -78,12 +79,15 @@ public:
uint32_t get_glyph_index() const { return glyph_index; };
void set_glyph_index(uint32_t p_glyph_index) { glyph_index = p_glyph_index; };
- uint16_t get_glyph_flags() const { return glyph_index; };
+ uint16_t get_glyph_flags() const { return glyph_flags; };
void set_glyph_flags(uint16_t p_glyph_flags) { glyph_flags = p_glyph_flags; };
uint8_t get_glyph_count() const { return glyph_count; };
void set_glyph_count(uint8_t p_glyph_count) { glyph_count = p_glyph_count; };
+ int32_t get_relative_index() const { return relative_index; };
+ void set_relative_index(int32_t p_relative_index) { relative_index = p_relative_index; };
+
RID get_font() const { return font; };
void set_font(RID p_font) { font = p_font; };
diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp
index 7f487175dc..d5c4fd3f07 100644
--- a/scene/gui/rich_text_label.cpp
+++ b/scene/gui/rich_text_label.cpp
@@ -150,7 +150,12 @@ RichTextLabel::Item *RichTextLabel::_get_item_at_pos(RichTextLabel::Item *p_item
return it;
}
} break;
- case ITEM_IMAGE:
+ case ITEM_IMAGE: {
+ offset += 1;
+ if (offset > p_position) {
+ return it;
+ }
+ } break;
case ITEM_TABLE: {
offset += 1;
} break;
@@ -325,7 +330,11 @@ float RichTextLabel::_resize_line(ItemFrame *p_frame, int p_line, const Ref<Font
if (table->columns[i].expand && total_ratio > 0 && remaining_width > 0) {
table->columns[i].width += table->columns[i].expand_ratio * remaining_width / total_ratio;
}
- table->total_width += table->columns[i].width + theme_cache.table_h_separation;
+ if (i != col_count - 1) {
+ table->total_width += table->columns[i].width + theme_cache.table_h_separation;
+ } else {
+ table->total_width += table->columns[i].width;
+ }
}
// Resize to max_width if needed and distribute the remaining space.
@@ -366,6 +375,7 @@ float RichTextLabel::_resize_line(ItemFrame *p_frame, int p_line, const Ref<Font
idx = 0;
table->total_height = 0;
table->rows.clear();
+ table->rows_baseline.clear();
Vector2 offset;
float row_height = 0.0;
@@ -379,13 +389,13 @@ float RichTextLabel::_resize_line(ItemFrame *p_frame, int p_line, const Ref<Font
offset.x += frame->padding.position.x;
float yofs = frame->padding.position.y;
float prev_h = 0;
+ float row_baseline = 0.0;
for (int i = 0; i < (int)frame->lines.size(); i++) {
MutexLock sub_lock(frame->lines[i].text_buf->get_mutex());
frame->lines[i].text_buf->set_width(table->columns[column].width);
table->columns[column].width = MAX(table->columns[column].width, ceil(frame->lines[i].text_buf->get_size().x));
frame->lines[i].offset.y = prev_h;
- frame->lines[i].offset += offset;
float h = frame->lines[i].text_buf->get_size().y + (frame->lines[i].text_buf->get_line_count() - 1) * theme_cache.line_separation;
if (i > 0) {
@@ -399,6 +409,9 @@ float RichTextLabel::_resize_line(ItemFrame *p_frame, int p_line, const Ref<Font
}
yofs += h;
prev_h = frame->lines[i].offset.y + frame->lines[i].text_buf->get_size().y + frame->lines[i].text_buf->get_line_count() * theme_cache.line_separation;
+
+ frame->lines[i].offset += offset;
+ row_baseline = MAX(row_baseline, frame->lines[i].text_buf->get_line_ascent(frame->lines[i].text_buf->get_line_count() - 1));
}
yofs += frame->padding.size.y;
offset.x += table->columns[column].width + theme_cache.table_h_separation + frame->padding.size.x;
@@ -410,11 +423,17 @@ float RichTextLabel::_resize_line(ItemFrame *p_frame, int p_line, const Ref<Font
table->total_height += row_height;
offset.y += row_height;
table->rows.push_back(row_height);
+ table->rows_baseline.push_back(table->total_height - row_height + row_baseline);
row_height = 0;
}
idx++;
}
- l.text_buf->resize_object((uint64_t)it, Size2(table->total_width, table->total_height), table->inline_align);
+ int row_idx = (table->align_to_row < 0) ? table->rows_baseline.size() - 1 : table->align_to_row;
+ if (table->rows_baseline.size() != 0 && row_idx < (int)table->rows_baseline.size() - 1) {
+ l.text_buf->resize_object((uint64_t)it, Size2(table->total_width, table->total_height), table->inline_align, Math::round(table->rows_baseline[row_idx]));
+ } else {
+ l.text_buf->resize_object((uint64_t)it, Size2(table->total_width, table->total_height), table->inline_align);
+ }
} break;
default:
break;
@@ -600,7 +619,11 @@ float RichTextLabel::_shape_line(ItemFrame *p_frame, int p_line, const Ref<Font>
if (table->columns[i].expand && total_ratio > 0 && remaining_width > 0) {
table->columns[i].width += table->columns[i].expand_ratio * remaining_width / total_ratio;
}
- table->total_width += table->columns[i].width + theme_cache.table_h_separation;
+ if (i != col_count - 1) {
+ table->total_width += table->columns[i].width + theme_cache.table_h_separation;
+ } else {
+ table->total_width += table->columns[i].width;
+ }
}
// Resize to max_width if needed and distribute the remaining space.
@@ -641,6 +664,7 @@ float RichTextLabel::_shape_line(ItemFrame *p_frame, int p_line, const Ref<Font>
idx = 0;
table->total_height = 0;
table->rows.clear();
+ table->rows_baseline.clear();
Vector2 offset;
float row_height = 0.0;
@@ -654,6 +678,7 @@ float RichTextLabel::_shape_line(ItemFrame *p_frame, int p_line, const Ref<Font>
offset.x += frame->padding.position.x;
float yofs = frame->padding.position.y;
float prev_h = 0;
+ float row_baseline = 0.0;
for (int i = 0; i < (int)frame->lines.size(); i++) {
MutexLock sub_lock(frame->lines[i].text_buf->get_mutex());
@@ -661,7 +686,6 @@ float RichTextLabel::_shape_line(ItemFrame *p_frame, int p_line, const Ref<Font>
table->columns[column].width = MAX(table->columns[column].width, ceil(frame->lines[i].text_buf->get_size().x));
frame->lines[i].offset.y = prev_h;
- frame->lines[i].offset += offset;
float h = frame->lines[i].text_buf->get_size().y + (frame->lines[i].text_buf->get_line_count() - 1) * theme_cache.line_separation;
if (i > 0) {
@@ -675,6 +699,9 @@ float RichTextLabel::_shape_line(ItemFrame *p_frame, int p_line, const Ref<Font>
}
yofs += h;
prev_h = frame->lines[i].offset.y + frame->lines[i].text_buf->get_size().y + frame->lines[i].text_buf->get_line_count() * theme_cache.line_separation;
+
+ frame->lines[i].offset += offset;
+ row_baseline = MAX(row_baseline, frame->lines[i].text_buf->get_line_ascent(frame->lines[i].text_buf->get_line_count() - 1));
}
yofs += frame->padding.size.y;
offset.x += table->columns[column].width + theme_cache.table_h_separation + frame->padding.size.x;
@@ -687,12 +714,17 @@ float RichTextLabel::_shape_line(ItemFrame *p_frame, int p_line, const Ref<Font>
table->total_height += row_height;
offset.y += row_height;
table->rows.push_back(row_height);
+ table->rows_baseline.push_back(table->total_height - row_height + row_baseline);
row_height = 0;
}
idx++;
}
-
- l.text_buf->add_object((uint64_t)it, Size2(table->total_width, table->total_height), table->inline_align, t_char_count);
+ int row_idx = (table->align_to_row < 0) ? table->rows_baseline.size() - 1 : table->align_to_row;
+ if (table->rows_baseline.size() != 0 && row_idx < (int)table->rows_baseline.size() - 1) {
+ l.text_buf->add_object((uint64_t)it, Size2(table->total_width, table->total_height), table->inline_align, t_char_count, Math::round(table->rows_baseline[row_idx]));
+ } else {
+ l.text_buf->add_object((uint64_t)it, Size2(table->total_width, table->total_height), table->inline_align, t_char_count);
+ }
txt += String::chr(0xfffc).repeat(t_char_count);
} break;
default:
@@ -752,7 +784,10 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
prefix = _prefix;
break;
} else if (list_items[i]->list_type == LIST_NUMBERS) {
- segment = TS->format_number(itos(list_index[i]), _find_language(l.from));
+ segment = itos(list_index[i]);
+ if (is_localizing_numeral_system()) {
+ segment = TS->format_number(segment, _find_language(l.from));
+ }
} else if (list_items[i]->list_type == LIST_LETTERS) {
segment = _letters(list_index[i], list_items[i]->capitalize);
} else if (list_items[i]->list_type == LIST_ROMAN) {
@@ -887,7 +922,7 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
Color odd_row_bg = theme_cache.table_odd_row_bg;
Color even_row_bg = theme_cache.table_even_row_bg;
Color border = theme_cache.table_border;
- int hseparation = theme_cache.table_h_separation;
+ int h_separation = theme_cache.table_h_separation;
int col_count = table->columns.size();
int row_count = table->rows.size();
@@ -905,11 +940,11 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
coff.x = rect.size.width - table->columns[col].width - coff.x;
}
if (row % 2 == 0) {
- draw_rect(Rect2(p_ofs + rect.position + off + coff - frame->padding.position, Size2(table->columns[col].width + hseparation + frame->padding.position.x + frame->padding.size.x, table->rows[row])), (frame->odd_row_bg != Color(0, 0, 0, 0) ? frame->odd_row_bg : odd_row_bg), true);
+ draw_rect(Rect2(p_ofs + rect.position + off + coff - frame->padding.position, Size2(table->columns[col].width + h_separation + frame->padding.position.x + frame->padding.size.x, table->rows[row])), (frame->odd_row_bg != Color(0, 0, 0, 0) ? frame->odd_row_bg : odd_row_bg), true);
} else {
- draw_rect(Rect2(p_ofs + rect.position + off + coff - frame->padding.position, Size2(table->columns[col].width + hseparation + frame->padding.position.x + frame->padding.size.x, table->rows[row])), (frame->even_row_bg != Color(0, 0, 0, 0) ? frame->even_row_bg : even_row_bg), true);
+ draw_rect(Rect2(p_ofs + rect.position + off + coff - frame->padding.position, Size2(table->columns[col].width + h_separation + frame->padding.position.x + frame->padding.size.x, table->rows[row])), (frame->even_row_bg != Color(0, 0, 0, 0) ? frame->even_row_bg : even_row_bg), true);
}
- draw_rect(Rect2(p_ofs + rect.position + off + coff - frame->padding.position, Size2(table->columns[col].width + hseparation + frame->padding.position.x + frame->padding.size.x, table->rows[row])), (frame->border != Color(0, 0, 0, 0) ? frame->border : border), false);
+ draw_rect(Rect2(p_ofs + rect.position + off + coff - frame->padding.position, Size2(table->columns[col].width + h_separation + frame->padding.position.x + frame->padding.size.x, table->rows[row])), (frame->border != Color(0, 0, 0, 0) ? frame->border : border), false);
}
for (int j = 0; j < (int)frame->lines.size(); j++) {
@@ -1002,6 +1037,7 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
if (!custom_effect.is_null()) {
charfx->elapsed_time = item_custom->elapsed_time;
charfx->range = Vector2i(l.char_offset + glyphs[i].start, l.char_offset + glyphs[i].end);
+ charfx->relative_index = l.char_offset + glyphs[i].start - item_fx->char_ofs;
charfx->visibility = txt_visible;
charfx->outline = true;
charfx->font = frid;
@@ -1219,6 +1255,7 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
if (!custom_effect.is_null()) {
charfx->elapsed_time = item_custom->elapsed_time;
charfx->range = Vector2i(l.char_offset + glyphs[i].start, l.char_offset + glyphs[i].end);
+ charfx->relative_index = l.char_offset + glyphs[i].start - item_fx->char_ofs;
charfx->visibility = txt_visible;
charfx->outline = false;
charfx->font = frid;
@@ -1849,10 +1886,6 @@ void RichTextLabel::_notification(int p_what) {
}
Control::CursorShape RichTextLabel::get_cursor_shape(const Point2 &p_pos) const {
- if (!underline_meta) {
- return get_default_cursor_shape();
- }
-
if (selection.click_item) {
return CURSOR_IBEAM;
}
@@ -2686,6 +2719,7 @@ bool RichTextLabel::_validate_line_caches() {
int ctrl_height = get_size().height;
// Update fonts.
+ float old_scroll = vscroll->get_value();
if (main->first_invalid_font_line.load() != (int)main->lines.size()) {
for (int i = main->first_invalid_font_line.load(); i < (int)main->lines.size(); i++) {
_update_line_font(main, i, theme_cache.normal_font, theme_cache.normal_font_size);
@@ -2695,6 +2729,7 @@ bool RichTextLabel::_validate_line_caches() {
}
if (main->first_resized_line.load() == (int)main->lines.size()) {
+ vscroll->set_value(old_scroll);
return true;
}
@@ -2733,6 +2768,8 @@ bool RichTextLabel::_validate_line_caches() {
vscroll->set_page(text_rect.size.height);
if (scroll_follow && scroll_following) {
vscroll->set_value(total_height);
+ } else {
+ vscroll->set_value(old_scroll);
}
updating_scroll = false;
@@ -3034,18 +3071,18 @@ void RichTextLabel::add_newline() {
queue_redraw();
}
-bool RichTextLabel::remove_line(const int p_line) {
+bool RichTextLabel::remove_paragraph(const int p_paragraph) {
_stop_thread();
MutexLock data_lock(data_mutex);
- if (p_line >= (int)current_frame->lines.size() || p_line < 0) {
+ if (p_paragraph >= (int)current_frame->lines.size() || p_paragraph < 0) {
return false;
}
// Remove all subitems with the same line as that provided.
Vector<int> subitem_indices_to_remove;
for (int i = 0; i < current->subitems.size(); i++) {
- if (current->subitems[i]->line == p_line) {
+ if (current->subitems[i]->line == p_paragraph) {
subitem_indices_to_remove.push_back(i);
}
}
@@ -3055,17 +3092,17 @@ bool RichTextLabel::remove_line(const int p_line) {
for (int i = subitem_indices_to_remove.size() - 1; i >= 0; i--) {
int subitem_idx = subitem_indices_to_remove[i];
had_newline = had_newline || current->subitems[subitem_idx]->type == ITEM_NEWLINE;
- _remove_item(current->subitems[subitem_idx], current->subitems[subitem_idx]->line, p_line);
+ _remove_item(current->subitems[subitem_idx], current->subitems[subitem_idx]->line, p_paragraph);
}
if (!had_newline) {
- current_frame->lines.remove_at(p_line);
+ current_frame->lines.remove_at(p_paragraph);
if (current_frame->lines.size() == 0) {
current_frame->lines.resize(1);
}
}
- if (p_line == 0 && current->subitems.size() > 0) {
+ if (p_paragraph == 0 && current->subitems.size() > 0) {
main->lines[0].from = main;
}
@@ -3145,7 +3182,8 @@ void RichTextLabel::push_normal() {
void RichTextLabel::push_bold() {
ERR_FAIL_COND(theme_cache.bold_font.is_null());
- _push_def_font(BOLD_FONT);
+ ItemFont *item_font = _find_font(current);
+ _push_def_font((item_font && item_font->def_font == ITALICS_FONT) ? BOLD_ITALICS_FONT : BOLD_FONT);
}
void RichTextLabel::push_bold_italics() {
@@ -3157,7 +3195,8 @@ void RichTextLabel::push_bold_italics() {
void RichTextLabel::push_italics() {
ERR_FAIL_COND(theme_cache.italics_font.is_null());
- _push_def_font(ITALICS_FONT);
+ ItemFont *item_font = _find_font(current);
+ _push_def_font((item_font && item_font->def_font == BOLD_FONT) ? BOLD_ITALICS_FONT : ITALICS_FONT);
}
void RichTextLabel::push_mono() {
@@ -3293,7 +3332,7 @@ void RichTextLabel::push_hint(const String &p_string) {
_add_item(item, true);
}
-void RichTextLabel::push_table(int p_columns, InlineAlignment p_alignment) {
+void RichTextLabel::push_table(int p_columns, InlineAlignment p_alignment, int p_align_to_row) {
_stop_thread();
MutexLock data_lock(data_mutex);
@@ -3303,6 +3342,7 @@ void RichTextLabel::push_table(int p_columns, InlineAlignment p_alignment) {
item->columns.resize(p_columns);
item->total_width = 0;
item->inline_align = p_alignment;
+ item->align_to_row = p_align_to_row;
for (int i = 0; i < (int)item->columns.size(); i++) {
item->columns[i].expand = false;
item->columns[i].expand_ratio = 1;
@@ -3783,6 +3823,8 @@ void RichTextLabel::append_text(const String &p_bbcode) {
alignment = INLINE_ALIGNMENT_TOP_TO;
} else if (subtag[1] == "center" || subtag[1] == "c") {
alignment = INLINE_ALIGNMENT_CENTER_TO;
+ } else if (subtag[1] == "baseline" || subtag[1] == "l") {
+ alignment = INLINE_ALIGNMENT_BASELINE_TO;
} else if (subtag[1] == "bottom" || subtag[1] == "b") {
alignment = INLINE_ALIGNMENT_BOTTOM_TO;
}
@@ -3804,8 +3846,12 @@ void RichTextLabel::append_text(const String &p_bbcode) {
alignment = INLINE_ALIGNMENT_BOTTOM;
}
}
+ int row = -1;
+ if (subtag.size() > 3) {
+ row = subtag[3].to_int();
+ }
- push_table(columns, (InlineAlignment)alignment);
+ push_table(columns, (InlineAlignment)alignment, row);
pos = brk_end + 1;
tag_stack.push_front("table");
} else if (tag == "cell") {
@@ -3853,6 +3899,15 @@ void RichTextLabel::append_text(const String &p_bbcode) {
Color color2 = Color::from_string(subtag_b[1], fallback_color);
set_cell_row_background_color(color1, color2);
}
+ if (subtag_b.size() == 1) {
+ Color color1 = Color::from_string(subtag_a[1], fallback_color);
+ set_cell_row_background_color(color1, color1);
+ }
+ } else if (subtag_a[0] == "padding") {
+ Vector<String> subtag_b = subtag_a[1].split(",");
+ if (subtag_b.size() == 4) {
+ set_cell_padding(Rect2(subtag_b[0].to_float(), subtag_b[1].to_float(), subtag_b[2].to_float(), subtag_b[3].to_float()));
+ }
}
}
}
@@ -4057,7 +4112,7 @@ void RichTextLabel::append_text(const String &p_bbcode) {
Color color = theme_cache.default_color;
Color outline_color = theme_cache.font_outline_color;
int outline_size = theme_cache.outline_size;
- Rect2 dropcap_margins = Rect2();
+ Rect2 dropcap_margins;
for (int i = 0; i < subtag.size(); i++) {
Vector<String> subtag_a = subtag[i].split("=");
@@ -4515,6 +4570,30 @@ void RichTextLabel::append_text(const String &p_bbcode) {
}
}
+void RichTextLabel::scroll_to_selection() {
+ if (selection.active && selection.from_frame && selection.from_line >= 0 && selection.from_line < (int)selection.from_frame->lines.size()) {
+ // Selected frame paragraph offset.
+ float line_offset = selection.from_frame->lines[selection.from_line].offset.y;
+
+ // Add wrapped line offset.
+ for (int i = 0; i < selection.from_frame->lines[selection.from_line].text_buf->get_line_count(); i++) {
+ Vector2i range = selection.from_frame->lines[selection.from_line].text_buf->get_line_range(i);
+ if (range.x <= selection.from_char && range.y >= selection.from_char) {
+ break;
+ }
+ line_offset += selection.from_frame->lines[selection.from_line].text_buf->get_line_size(i).y + theme_cache.line_separation;
+ }
+
+ // Add nested frame (e.g. table cell) offset.
+ ItemFrame *it = selection.from_frame;
+ while (it->parent_frame != nullptr) {
+ line_offset += it->parent_frame->lines[it->line].offset.y;
+ it = it->parent_frame;
+ }
+ vscroll->set_value(line_offset);
+ }
+}
+
void RichTextLabel::scroll_to_paragraph(int p_paragraph) {
_validate_line_caches();
@@ -4759,7 +4838,7 @@ bool RichTextLabel::search(const String &p_string, bool p_from_selection, bool p
char_idx = p_search_previous ? selection.from_char - 1 : selection.to_char;
if (!(p_search_previous && char_idx < 0) &&
_search_line(selection.from_frame, selection.from_line, p_string, char_idx, p_search_previous)) {
- scroll_to_line(selection.from_frame->line + selection.from_line);
+ scroll_to_selection();
queue_redraw();
return true;
}
@@ -4784,7 +4863,7 @@ bool RichTextLabel::search(const String &p_string, bool p_from_selection, bool p
// Search for next element
if (_search_table(parent_table, parent_element, p_string, p_search_previous)) {
- scroll_to_line(selection.from_frame->line + selection.from_line);
+ scroll_to_selection();
queue_redraw();
return true;
}
@@ -4808,7 +4887,7 @@ bool RichTextLabel::search(const String &p_string, bool p_from_selection, bool p
}
if (_search_line(main, current_line, p_string, char_idx, p_search_previous)) {
- scroll_to_line(current_line);
+ scroll_to_selection();
queue_redraw();
return true;
}
@@ -5236,7 +5315,7 @@ void RichTextLabel::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_text", "text"), &RichTextLabel::set_text);
ClassDB::bind_method(D_METHOD("add_image", "image", "width", "height", "color", "inline_align", "region"), &RichTextLabel::add_image, DEFVAL(0), DEFVAL(0), DEFVAL(Color(1.0, 1.0, 1.0)), DEFVAL(INLINE_ALIGNMENT_CENTER), DEFVAL(Rect2(0, 0, 0, 0)));
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("remove_paragraph", "paragraph"), &RichTextLabel::remove_paragraph);
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_normal"), &RichTextLabel::push_normal);
@@ -5254,7 +5333,7 @@ void RichTextLabel::_bind_methods() {
ClassDB::bind_method(D_METHOD("push_hint", "description"), &RichTextLabel::push_hint);
ClassDB::bind_method(D_METHOD("push_underline"), &RichTextLabel::push_underline);
ClassDB::bind_method(D_METHOD("push_strikethrough"), &RichTextLabel::push_strikethrough);
- ClassDB::bind_method(D_METHOD("push_table", "columns", "inline_align"), &RichTextLabel::push_table, DEFVAL(INLINE_ALIGNMENT_TOP));
+ ClassDB::bind_method(D_METHOD("push_table", "columns", "inline_align", "align_to_row"), &RichTextLabel::push_table, DEFVAL(INLINE_ALIGNMENT_TOP), DEFVAL(-1));
ClassDB::bind_method(D_METHOD("push_dropcap", "string", "font", "size", "dropcap_margins", "color", "outline_size", "outline_color"), &RichTextLabel::push_dropcap, DEFVAL(Rect2()), DEFVAL(Color(1, 1, 1)), DEFVAL(0), DEFVAL(Color(0, 0, 0, 0)));
ClassDB::bind_method(D_METHOD("set_table_column_expand", "column", "expand", "ratio"), &RichTextLabel::set_table_column_expand);
ClassDB::bind_method(D_METHOD("set_cell_row_background_color", "odd_row_bg", "even_row_bg"), &RichTextLabel::set_cell_row_background_color);
@@ -5296,6 +5375,7 @@ void RichTextLabel::_bind_methods() {
ClassDB::bind_method(D_METHOD("scroll_to_line", "line"), &RichTextLabel::scroll_to_line);
ClassDB::bind_method(D_METHOD("scroll_to_paragraph", "paragraph"), &RichTextLabel::scroll_to_paragraph);
+ ClassDB::bind_method(D_METHOD("scroll_to_selection"), &RichTextLabel::scroll_to_selection);
ClassDB::bind_method(D_METHOD("set_tab_size", "spaces"), &RichTextLabel::set_tab_size);
ClassDB::bind_method(D_METHOD("get_tab_size"), &RichTextLabel::get_tab_size);
@@ -5385,7 +5465,7 @@ void RichTextLabel::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shortcut_keys_enabled"), "set_shortcut_keys_enabled", "is_shortcut_keys_enabled");
ADD_GROUP("Markup", "");
- ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "custom_effects", PROPERTY_HINT_ARRAY_TYPE, vformat("%s/%s:%s", Variant::OBJECT, PROPERTY_HINT_RESOURCE_TYPE, "RichTextEffect"), (PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SCRIPT_VARIABLE)), "set_effects", "get_effects");
+ ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "custom_effects", PROPERTY_HINT_ARRAY_TYPE, MAKE_RESOURCE_TYPE_HINT("RichTextEffect"), (PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SCRIPT_VARIABLE)), "set_effects", "get_effects");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "meta_underlined"), "set_meta_underline", "is_meta_underlined");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hint_underlined"), "set_hint_underline", "is_hint_underlined");
@@ -5716,11 +5796,11 @@ Ref<RichTextEffect> RichTextLabel::_get_custom_effect_by_code(String p_bbcode_id
}
Dictionary RichTextLabel::parse_expressions_for_values(Vector<String> p_expressions) {
- Dictionary d = Dictionary();
+ Dictionary d;
for (int i = 0; i < p_expressions.size(); i++) {
String expression = p_expressions[i];
- Array a = Array();
+ Array a;
Vector<String> parts = expression.split("=", true);
String key = parts[0];
if (parts.size() != 2) {
diff --git a/scene/gui/rich_text_label.h b/scene/gui/rich_text_label.h
index d30baaa8d3..a4bc1c8e03 100644
--- a/scene/gui/rich_text_label.h
+++ b/scene/gui/rich_text_label.h
@@ -268,7 +268,9 @@ private:
LocalVector<Column> columns;
LocalVector<float> rows;
+ LocalVector<float> rows_baseline;
+ int align_to_row = -1;
int total_width = 0;
int total_height = 0;
InlineAlignment inline_align = INLINE_ALIGNMENT_TOP;
@@ -571,7 +573,7 @@ public:
void add_text(const String &p_text);
void add_image(const Ref<Texture2D> &p_image, const int p_width = 0, const int p_height = 0, const Color &p_color = Color(1.0, 1.0, 1.0), InlineAlignment p_alignment = INLINE_ALIGNMENT_CENTER, const Rect2 &p_region = Rect2(0, 0, 0, 0));
void add_newline();
- bool remove_line(const int p_line);
+ bool remove_paragraph(const int p_paragraph);
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_def_font(DefaultFont p_def_font);
void _push_def_font_var(DefaultFont p_def_font, const Ref<Font> &p_font, int p_size = -1);
@@ -592,7 +594,7 @@ public:
void push_list(int p_level, ListType p_list, bool p_capitalize);
void push_meta(const Variant &p_meta);
void push_hint(const String &p_string);
- void push_table(int p_columns, InlineAlignment p_alignment = INLINE_ALIGNMENT_TOP);
+ void push_table(int p_columns, InlineAlignment p_alignment = INLINE_ALIGNMENT_TOP, int p_align_to_row = -1);
void push_fade(int p_start_index, int p_length);
void push_shake(int p_strength, float p_rate, bool p_connected);
void push_wave(float p_frequency, float p_amplitude, bool p_connected);
@@ -657,6 +659,8 @@ public:
int get_content_height() const;
int get_content_width() const;
+ void scroll_to_selection();
+
VScrollBar *get_v_scroll_bar() { return vscroll; }
virtual CursorShape get_cursor_shape(const Point2 &p_pos) const override;
diff --git a/scene/gui/scroll_bar.cpp b/scene/gui/scroll_bar.cpp
index 6899178885..a44ddff507 100644
--- a/scene/gui/scroll_bar.cpp
+++ b/scene/gui/scroll_bar.cpp
@@ -550,7 +550,7 @@ void ScrollBar::_drag_node_input(const Ref<InputEvent> &p_input) {
drag_node_accum = Vector2();
last_drag_node_accum = Vector2();
drag_node_from = Vector2(orientation == HORIZONTAL ? get_value() : 0, orientation == VERTICAL ? get_value() : 0);
- drag_node_touching = DisplayServer::get_singleton()->screen_is_touchscreen(DisplayServer::get_singleton()->window_get_current_screen(get_viewport()->get_window_id()));
+ drag_node_touching = DisplayServer::get_singleton()->is_touchscreen_available();
drag_node_touching_deaccel = false;
time_since_motion = 0;
diff --git a/scene/gui/scroll_bar.h b/scene/gui/scroll_bar.h
index 13ca62d7ff..d62acd52af 100644
--- a/scene/gui/scroll_bar.h
+++ b/scene/gui/scroll_bar.h
@@ -72,7 +72,7 @@ class ScrollBar : public Range {
NodePath drag_node_path;
bool drag_node_enabled = true;
- Vector2 drag_node_speed = Vector2();
+ Vector2 drag_node_speed;
Vector2 drag_node_accum;
Vector2 drag_node_from;
Vector2 last_drag_node_accum;
diff --git a/scene/gui/scroll_container.cpp b/scene/gui/scroll_container.cpp
index 531226f938..73d30b7568 100644
--- a/scene/gui/scroll_container.cpp
+++ b/scene/gui/scroll_container.cpp
@@ -164,8 +164,8 @@ void ScrollContainer::gui_input(const Ref<InputEvent> &p_gui_input) {
}
}
- bool screen_is_touchscreen = DisplayServer::get_singleton()->screen_is_touchscreen(DisplayServer::get_singleton()->window_get_current_screen(get_viewport()->get_window_id()));
- if (!screen_is_touchscreen) {
+ bool is_touchscreen_available = DisplayServer::get_singleton()->is_touchscreen_available();
+ if (!is_touchscreen_available) {
return;
}
diff --git a/scene/gui/spin_box.cpp b/scene/gui/spin_box.cpp
index c4000120c8..e15b3b7bd4 100644
--- a/scene/gui/spin_box.cpp
+++ b/scene/gui/spin_box.cpp
@@ -40,7 +40,10 @@ Size2 SpinBox::get_minimum_size() const {
}
void SpinBox::_value_changed(double p_value) {
- String value = TS->format_number(String::num(get_value(), Math::range_step_decimals(get_step())));
+ String value = String::num(get_value(), Math::range_step_decimals(get_step()));
+ if (is_localizing_numeral_system()) {
+ value = TS->format_number(value);
+ }
if (!line_edit->has_focus()) {
if (!prefix.is_empty()) {
diff --git a/scene/gui/split_container.cpp b/scene/gui/split_container.cpp
index 2ca1d6239e..9830b41389 100644
--- a/scene/gui/split_container.cpp
+++ b/scene/gui/split_container.cpp
@@ -71,7 +71,7 @@ void SplitContainerDragger::gui_input(const Ref<InputEvent> &p_event) {
Vector2i in_parent_pos = get_transform().xform(mm->get_position());
if (!sc->vertical && is_layout_rtl()) {
- sc->split_offset = drag_ofs - ((sc->vertical ? in_parent_pos.y : in_parent_pos.x) - drag_from);
+ sc->split_offset = drag_ofs - (in_parent_pos.x - drag_from);
} else {
sc->split_offset = drag_ofs + ((sc->vertical ? in_parent_pos.y : in_parent_pos.x) - drag_from);
}
@@ -194,7 +194,6 @@ void SplitContainer::_compute_middle_sep(bool p_clamp) {
// Clamp the split_offset if requested.
if (p_clamp) {
split_offset -= wished_middle_sep - middle_sep;
- p_clamp = false;
}
}
diff --git a/scene/gui/subviewport_container.cpp b/scene/gui/subviewport_container.cpp
index 3ad84cbc6d..f3d9a22342 100644
--- a/scene/gui/subviewport_container.cpp
+++ b/scene/gui/subviewport_container.cpp
@@ -227,6 +227,18 @@ void SubViewportContainer::unhandled_input(const Ref<InputEvent> &p_event) {
}
}
+void SubViewportContainer::add_child_notify(Node *p_child) {
+ if (Object::cast_to<SubViewport>(p_child)) {
+ queue_redraw();
+ }
+}
+
+void SubViewportContainer::remove_child_notify(Node *p_child) {
+ if (Object::cast_to<SubViewport>(p_child)) {
+ queue_redraw();
+ }
+}
+
PackedStringArray SubViewportContainer::get_configuration_warnings() const {
PackedStringArray warnings = Node::get_configuration_warnings();
diff --git a/scene/gui/subviewport_container.h b/scene/gui/subviewport_container.h
index 63a58b5f07..fdd8fe9486 100644
--- a/scene/gui/subviewport_container.h
+++ b/scene/gui/subviewport_container.h
@@ -44,6 +44,9 @@ protected:
void _notification(int p_what);
static void _bind_methods();
+ virtual void add_child_notify(Node *p_child) override;
+ virtual void remove_child_notify(Node *p_child) override;
+
public:
void set_stretch(bool p_enable);
bool is_stretch_enabled() const;
diff --git a/scene/gui/tab_bar.cpp b/scene/gui/tab_bar.cpp
index cf6681f809..f87829cf71 100644
--- a/scene/gui/tab_bar.cpp
+++ b/scene/gui/tab_bar.cpp
@@ -385,9 +385,6 @@ void TabBar::_notification(int p_what) {
if (tabs[i].disabled) {
sb = theme_cache.tab_disabled_style;
col = theme_cache.font_disabled_color;
- } else if (i == current) {
- sb = theme_cache.tab_selected_style;
- col = theme_cache.font_selected_color;
} else {
sb = theme_cache.tab_unselected_style;
col = theme_cache.font_unselected_color;
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index 56f7281721..6d9e8a90c2 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -680,7 +680,7 @@ void TextEdit::_notification(int p_what) {
}
}
- bool draw_placeholder = text.size() == 1 && text[0].length() == 0;
+ bool draw_placeholder = text.size() == 1 && text[0].is_empty() && ime_text.is_empty();
// Get the highlighted words.
String highlighted_text = get_selected_text(0);
@@ -1108,8 +1108,9 @@ void TextEdit::_notification(int p_what) {
int start = TS->shaped_text_get_range(rid).x;
if (!clipped && !search_text.is_empty()) { // Search highhlight
int search_text_col = _get_column_pos_of_word(search_text, str, search_flags, 0);
+ int search_text_len = search_text.length();
while (search_text_col != -1) {
- Vector<Vector2> sel = TS->shaped_text_get_selection(rid, search_text_col + start, search_text_col + search_text.length() + start);
+ Vector<Vector2> sel = TS->shaped_text_get_selection(rid, search_text_col + start, search_text_col + search_text_len + start);
for (int j = 0; j < sel.size(); j++) {
Rect2 rect = Rect2(sel[j].x + char_margin + ofs_x, ofs_y, sel[j].y - sel[j].x, row_height);
if (rect.position.x + rect.size.x <= xmargin_beg || rect.position.x > xmargin_end) {
@@ -1125,14 +1126,15 @@ void TextEdit::_notification(int p_what) {
draw_rect(rect, search_result_border_color, false);
}
- search_text_col = _get_column_pos_of_word(search_text, str, search_flags, search_text_col + 1);
+ search_text_col = _get_column_pos_of_word(search_text, str, search_flags, search_text_col + search_text_len);
}
}
if (!clipped && highlight_all_occurrences && !only_whitespaces_highlighted && !highlighted_text.is_empty()) { // Highlight
int highlighted_text_col = _get_column_pos_of_word(highlighted_text, str, SEARCH_MATCH_CASE | SEARCH_WHOLE_WORDS, 0);
+ int highlighted_text_len = highlighted_text.length();
while (highlighted_text_col != -1) {
- Vector<Vector2> sel = TS->shaped_text_get_selection(rid, highlighted_text_col + start, highlighted_text_col + highlighted_text.length() + start);
+ Vector<Vector2> sel = TS->shaped_text_get_selection(rid, highlighted_text_col + start, highlighted_text_col + highlighted_text_len + start);
for (int j = 0; j < sel.size(); j++) {
Rect2 rect = Rect2(sel[j].x + char_margin + ofs_x, ofs_y, sel[j].y - sel[j].x, row_height);
if (rect.position.x + rect.size.x <= xmargin_beg || rect.position.x > xmargin_end) {
@@ -1147,15 +1149,16 @@ void TextEdit::_notification(int p_what) {
draw_rect(rect, word_highlighted_color);
}
- highlighted_text_col = _get_column_pos_of_word(highlighted_text, str, SEARCH_MATCH_CASE | SEARCH_WHOLE_WORDS, highlighted_text_col + 1);
+ highlighted_text_col = _get_column_pos_of_word(highlighted_text, str, SEARCH_MATCH_CASE | SEARCH_WHOLE_WORDS, highlighted_text_col + highlighted_text_len);
}
}
if (!clipped && lookup_symbol_word.length() != 0) { // Highlight word
if (is_ascii_char(lookup_symbol_word[0]) || lookup_symbol_word[0] == '_' || lookup_symbol_word[0] == '.') {
- int highlighted_word_col = _get_column_pos_of_word(lookup_symbol_word, str, SEARCH_MATCH_CASE | SEARCH_WHOLE_WORDS, 0);
- while (highlighted_word_col != -1) {
- Vector<Vector2> sel = TS->shaped_text_get_selection(rid, highlighted_word_col + start, highlighted_word_col + lookup_symbol_word.length() + start);
+ int lookup_symbol_word_col = _get_column_pos_of_word(lookup_symbol_word, str, SEARCH_MATCH_CASE | SEARCH_WHOLE_WORDS, 0);
+ int lookup_symbol_word_len = lookup_symbol_word.length();
+ while (lookup_symbol_word_col != -1) {
+ Vector<Vector2> sel = TS->shaped_text_get_selection(rid, lookup_symbol_word_col + start, lookup_symbol_word_col + lookup_symbol_word_len + start);
for (int j = 0; j < sel.size(); j++) {
Rect2 rect = Rect2(sel[j].x + char_margin + ofs_x, ofs_y + (line_spacing / 2), sel[j].y - sel[j].x, row_height);
if (rect.position.x + rect.size.x <= xmargin_beg || rect.position.x > xmargin_end) {
@@ -1172,7 +1175,7 @@ void TextEdit::_notification(int p_what) {
draw_rect(rect, color);
}
- highlighted_word_col = _get_column_pos_of_word(lookup_symbol_word, str, SEARCH_MATCH_CASE | SEARCH_WHOLE_WORDS, highlighted_word_col + 1);
+ lookup_symbol_word_col = _get_column_pos_of_word(lookup_symbol_word, str, SEARCH_MATCH_CASE | SEARCH_WHOLE_WORDS, lookup_symbol_word_col + lookup_symbol_word_len);
}
}
}
@@ -4234,7 +4237,7 @@ Point2i TextEdit::get_line_column_at_pos(const Point2i &p_pos, bool p_allow_out_
if (!p_allow_out_of_bounds) {
return Point2i(-1, -1);
}
- return Point2i(text[row].size(), row);
+ return Point2i(text[row].length(), row);
}
int col = 0;
@@ -7038,8 +7041,8 @@ void TextEdit::_update_selection_mode_word() {
if ((col <= carets[caret_idx].selection.selected_word_origin && line == get_selection_line(caret_idx)) || line < get_selection_line(caret_idx)) {
carets.write[caret_idx].selection.selecting_column = carets[caret_idx].selection.selected_word_end;
select(line, beg, get_selection_line(caret_idx), carets[caret_idx].selection.selected_word_end, caret_idx);
- set_caret_line(get_selection_from_line(caret_idx), false, true, 0, caret_idx);
- set_caret_column(get_selection_from_column(caret_idx), true, caret_idx);
+ set_caret_line(line, false, true, 0, caret_idx);
+ set_caret_column(beg, true, caret_idx);
} else {
carets.write[caret_idx].selection.selecting_column = carets[caret_idx].selection.selected_word_beg;
select(get_selection_line(caret_idx), carets[caret_idx].selection.selected_word_beg, line, end, caret_idx);
diff --git a/scene/gui/texture_button.cpp b/scene/gui/texture_button.cpp
index d9ab1c2c55..ccdf56c1d7 100644
--- a/scene/gui/texture_button.cpp
+++ b/scene/gui/texture_button.cpp
@@ -64,7 +64,7 @@ Size2 TextureButton::get_minimum_size() const {
bool TextureButton::has_point(const Point2 &p_point) const {
if (click_mask.is_valid()) {
Point2 point = p_point;
- Rect2 rect = Rect2();
+ Rect2 rect;
Size2 mask_size = click_mask->get_size();
if (!_position_rect.has_area()) {
@@ -250,11 +250,11 @@ void TextureButton::_notification(int p_what) {
}
void TextureButton::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_normal_texture", "texture"), &TextureButton::set_normal_texture);
- ClassDB::bind_method(D_METHOD("set_pressed_texture", "texture"), &TextureButton::set_pressed_texture);
- ClassDB::bind_method(D_METHOD("set_hover_texture", "texture"), &TextureButton::set_hover_texture);
- ClassDB::bind_method(D_METHOD("set_disabled_texture", "texture"), &TextureButton::set_disabled_texture);
- ClassDB::bind_method(D_METHOD("set_focused_texture", "texture"), &TextureButton::set_focused_texture);
+ ClassDB::bind_method(D_METHOD("set_texture_normal", "texture"), &TextureButton::set_texture_normal);
+ ClassDB::bind_method(D_METHOD("set_texture_pressed", "texture"), &TextureButton::set_texture_pressed);
+ ClassDB::bind_method(D_METHOD("set_texture_hover", "texture"), &TextureButton::set_texture_hover);
+ ClassDB::bind_method(D_METHOD("set_texture_disabled", "texture"), &TextureButton::set_texture_disabled);
+ ClassDB::bind_method(D_METHOD("set_texture_focused", "texture"), &TextureButton::set_texture_focused);
ClassDB::bind_method(D_METHOD("set_click_mask", "mask"), &TextureButton::set_click_mask);
ClassDB::bind_method(D_METHOD("set_ignore_texture_size", "ignore"), &TextureButton::set_ignore_texture_size);
ClassDB::bind_method(D_METHOD("set_stretch_mode", "mode"), &TextureButton::set_stretch_mode);
@@ -263,21 +263,21 @@ void TextureButton::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_flip_v", "enable"), &TextureButton::set_flip_v);
ClassDB::bind_method(D_METHOD("is_flipped_v"), &TextureButton::is_flipped_v);
- ClassDB::bind_method(D_METHOD("get_normal_texture"), &TextureButton::get_normal_texture);
- ClassDB::bind_method(D_METHOD("get_pressed_texture"), &TextureButton::get_pressed_texture);
- ClassDB::bind_method(D_METHOD("get_hover_texture"), &TextureButton::get_hover_texture);
- ClassDB::bind_method(D_METHOD("get_disabled_texture"), &TextureButton::get_disabled_texture);
- ClassDB::bind_method(D_METHOD("get_focused_texture"), &TextureButton::get_focused_texture);
+ ClassDB::bind_method(D_METHOD("get_texture_normal"), &TextureButton::get_texture_normal);
+ ClassDB::bind_method(D_METHOD("get_texture_pressed"), &TextureButton::get_texture_pressed);
+ ClassDB::bind_method(D_METHOD("get_texture_hover"), &TextureButton::get_texture_hover);
+ ClassDB::bind_method(D_METHOD("get_texture_disabled"), &TextureButton::get_texture_disabled);
+ ClassDB::bind_method(D_METHOD("get_texture_focused"), &TextureButton::get_texture_focused);
ClassDB::bind_method(D_METHOD("get_click_mask"), &TextureButton::get_click_mask);
ClassDB::bind_method(D_METHOD("get_ignore_texture_size"), &TextureButton::get_ignore_texture_size);
ClassDB::bind_method(D_METHOD("get_stretch_mode"), &TextureButton::get_stretch_mode);
ADD_GROUP("Textures", "texture_");
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture_normal", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_normal_texture", "get_normal_texture");
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture_pressed", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_pressed_texture", "get_pressed_texture");
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture_hover", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_hover_texture", "get_hover_texture");
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture_disabled", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_disabled_texture", "get_disabled_texture");
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture_focused", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_focused_texture", "get_focused_texture");
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture_normal", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture_normal", "get_texture_normal");
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture_pressed", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture_pressed", "get_texture_pressed");
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture_hover", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture_hover", "get_texture_hover");
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture_disabled", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture_disabled", "get_texture_disabled");
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture_focused", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture_focused", "get_texture_focused");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture_click_mask", PROPERTY_HINT_RESOURCE_TYPE, "BitMap"), "set_click_mask", "get_click_mask");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "ignore_texture_size", PROPERTY_HINT_RESOURCE_TYPE, "bool"), "set_ignore_texture_size", "get_ignore_texture_size");
ADD_PROPERTY(PropertyInfo(Variant::INT, "stretch_mode", PROPERTY_HINT_ENUM, "Scale,Tile,Keep,Keep Centered,Keep Aspect,Keep Aspect Centered,Keep Aspect Covered"), "set_stretch_mode", "get_stretch_mode");
@@ -293,7 +293,7 @@ void TextureButton::_bind_methods() {
BIND_ENUM_CONSTANT(STRETCH_KEEP_ASPECT_COVERED);
}
-void TextureButton::set_normal_texture(const Ref<Texture2D> &p_normal) {
+void TextureButton::set_texture_normal(const Ref<Texture2D> &p_normal) {
if (normal == p_normal) {
return;
}
@@ -303,7 +303,7 @@ void TextureButton::set_normal_texture(const Ref<Texture2D> &p_normal) {
update_minimum_size();
}
-void TextureButton::set_pressed_texture(const Ref<Texture2D> &p_pressed) {
+void TextureButton::set_texture_pressed(const Ref<Texture2D> &p_pressed) {
if (pressed == p_pressed) {
return;
}
@@ -313,7 +313,7 @@ void TextureButton::set_pressed_texture(const Ref<Texture2D> &p_pressed) {
update_minimum_size();
}
-void TextureButton::set_hover_texture(const Ref<Texture2D> &p_hover) {
+void TextureButton::set_texture_hover(const Ref<Texture2D> &p_hover) {
if (hover == p_hover) {
return;
}
@@ -323,7 +323,7 @@ void TextureButton::set_hover_texture(const Ref<Texture2D> &p_hover) {
update_minimum_size();
}
-void TextureButton::set_disabled_texture(const Ref<Texture2D> &p_disabled) {
+void TextureButton::set_texture_disabled(const Ref<Texture2D> &p_disabled) {
if (disabled == p_disabled) {
return;
}
@@ -341,19 +341,19 @@ void TextureButton::set_click_mask(const Ref<BitMap> &p_click_mask) {
update_minimum_size();
}
-Ref<Texture2D> TextureButton::get_normal_texture() const {
+Ref<Texture2D> TextureButton::get_texture_normal() const {
return normal;
}
-Ref<Texture2D> TextureButton::get_pressed_texture() const {
+Ref<Texture2D> TextureButton::get_texture_pressed() const {
return pressed;
}
-Ref<Texture2D> TextureButton::get_hover_texture() const {
+Ref<Texture2D> TextureButton::get_texture_hover() const {
return hover;
}
-Ref<Texture2D> TextureButton::get_disabled_texture() const {
+Ref<Texture2D> TextureButton::get_texture_disabled() const {
return disabled;
}
@@ -361,11 +361,11 @@ Ref<BitMap> TextureButton::get_click_mask() const {
return click_mask;
}
-Ref<Texture2D> TextureButton::get_focused_texture() const {
+Ref<Texture2D> TextureButton::get_texture_focused() const {
return focused;
};
-void TextureButton::set_focused_texture(const Ref<Texture2D> &p_focused) {
+void TextureButton::set_texture_focused(const Ref<Texture2D> &p_focused) {
focused = p_focused;
};
diff --git a/scene/gui/texture_button.h b/scene/gui/texture_button.h
index 9f6f7c1515..4b6d5b5bec 100644
--- a/scene/gui/texture_button.h
+++ b/scene/gui/texture_button.h
@@ -71,18 +71,18 @@ protected:
static void _bind_methods();
public:
- void set_normal_texture(const Ref<Texture2D> &p_normal);
- void set_pressed_texture(const Ref<Texture2D> &p_pressed);
- void set_hover_texture(const Ref<Texture2D> &p_hover);
- void set_disabled_texture(const Ref<Texture2D> &p_disabled);
- void set_focused_texture(const Ref<Texture2D> &p_focused);
+ void set_texture_normal(const Ref<Texture2D> &p_normal);
+ void set_texture_pressed(const Ref<Texture2D> &p_pressed);
+ void set_texture_hover(const Ref<Texture2D> &p_hover);
+ void set_texture_disabled(const Ref<Texture2D> &p_disabled);
+ void set_texture_focused(const Ref<Texture2D> &p_focused);
void set_click_mask(const Ref<BitMap> &p_click_mask);
- Ref<Texture2D> get_normal_texture() const;
- Ref<Texture2D> get_pressed_texture() const;
- Ref<Texture2D> get_hover_texture() const;
- Ref<Texture2D> get_disabled_texture() const;
- Ref<Texture2D> get_focused_texture() const;
+ Ref<Texture2D> get_texture_normal() const;
+ Ref<Texture2D> get_texture_pressed() const;
+ Ref<Texture2D> get_texture_hover() const;
+ Ref<Texture2D> get_texture_disabled() const;
+ Ref<Texture2D> get_texture_focused() const;
Ref<BitMap> get_click_mask() const;
bool get_ignore_texture_size() const;
diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp
index 1c96858da7..79bad44e15 100644
--- a/scene/gui/tree.cpp
+++ b/scene/gui/tree.cpp
@@ -1018,7 +1018,7 @@ void TreeItem::set_as_cursor(int p_column) {
if (tree->select_mode != Tree::SELECT_MULTI) {
return;
}
- if (tree->selected_col == p_column) {
+ if (tree->selected_item == this && tree->selected_col == p_column) {
return;
}
tree->selected_item = this;
@@ -1337,14 +1337,14 @@ Size2 TreeItem::get_minimum_size(int p_column) {
// Icon.
if (cell.mode == CELL_MODE_CHECK) {
- size.width += parent_tree->theme_cache.checked->get_width() + parent_tree->theme_cache.hseparation;
+ size.width += parent_tree->theme_cache.checked->get_width() + parent_tree->theme_cache.h_separation;
}
if (cell.icon.is_valid()) {
Size2i icon_size = cell.get_icon_size();
if (cell.icon_max_w > 0 && icon_size.width > cell.icon_max_w) {
icon_size.width = cell.icon_max_w;
}
- size.width += icon_size.width + parent_tree->theme_cache.hseparation;
+ size.width += icon_size.width + parent_tree->theme_cache.h_separation;
size.height = MAX(size.height, icon_size.height);
}
@@ -1624,8 +1624,8 @@ void Tree::_update_theme_item_cache() {
theme_cache.font_color = get_theme_color(SNAME("font_color"));
theme_cache.font_selected_color = get_theme_color(SNAME("font_selected_color"));
theme_cache.drop_position_color = get_theme_color(SNAME("drop_position_color"));
- theme_cache.hseparation = get_theme_constant(SNAME("h_separation"));
- theme_cache.vseparation = get_theme_constant(SNAME("v_separation"));
+ theme_cache.h_separation = get_theme_constant(SNAME("h_separation"));
+ theme_cache.v_separation = get_theme_constant(SNAME("v_separation"));
theme_cache.item_margin = get_theme_constant(SNAME("item_margin"));
theme_cache.button_margin = get_theme_constant(SNAME("button_margin"));
@@ -1710,7 +1710,7 @@ int Tree::compute_item_height(TreeItem *p_item) const {
height = item_min_height;
}
- height += theme_cache.vseparation;
+ height += theme_cache.v_separation;
return height;
}
@@ -1720,7 +1720,7 @@ int Tree::get_item_height(TreeItem *p_item) const {
return 0;
}
int height = compute_item_height(p_item);
- height += theme_cache.vseparation;
+ height += theme_cache.v_separation;
if (!p_item->collapsed) { /* if not collapsed, check the children */
@@ -1749,7 +1749,7 @@ void Tree::draw_item_rect(TreeItem::Cell &p_cell, const Rect2i &p_rect, const Co
if (p_cell.icon_max_w > 0 && bmsize.width > p_cell.icon_max_w) {
bmsize.width = p_cell.icon_max_w;
}
- w += bmsize.width + theme_cache.hseparation;
+ w += bmsize.width + theme_cache.h_separation;
if (rect.size.width > 0 && (w + ts.width) > rect.size.width) {
ts.width = rect.size.width - w;
}
@@ -1783,8 +1783,8 @@ void Tree::draw_item_rect(TreeItem::Cell &p_cell, const Rect2i &p_rect, const Co
p_cell.text_buf->draw_outline(ci, draw_pos, p_ol_size, p_ol_color);
}
p_cell.text_buf->draw(ci, draw_pos, p_color);
- rect.position.x += ts.width + theme_cache.hseparation;
- rect.size.x -= ts.width + theme_cache.hseparation;
+ rect.position.x += ts.width + theme_cache.h_separation;
+ rect.size.x -= ts.width + theme_cache.h_separation;
}
if (!p_cell.icon.is_null()) {
@@ -1796,8 +1796,8 @@ void Tree::draw_item_rect(TreeItem::Cell &p_cell, const Rect2i &p_rect, const Co
}
p_cell.draw_icon(ci, rect.position + Size2i(0, Math::floor((real_t)(rect.size.y - bmsize.y) / 2)), bmsize, p_icon_color);
- rect.position.x += bmsize.x + theme_cache.hseparation;
- rect.size.x -= bmsize.x + theme_cache.hseparation;
+ rect.position.x += bmsize.x + theme_cache.h_separation;
+ rect.size.x -= bmsize.x + theme_cache.h_separation;
}
if (!rtl) {
@@ -1911,7 +1911,7 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
bool rtl = cache.rtl;
/* Calculate height of the label part */
- label_h += theme_cache.vseparation;
+ label_h += theme_cache.v_separation;
/* Draw label, if height fits */
@@ -1922,7 +1922,7 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
ERR_FAIL_COND_V(theme_cache.font.is_null(), -1);
- int ofs = p_pos.x + ((p_item->disable_folding || hide_folding) ? theme_cache.hseparation : theme_cache.item_margin);
+ int ofs = p_pos.x + ((p_item->disable_folding || hide_folding) ? theme_cache.h_separation : theme_cache.item_margin);
int skip2 = 0;
for (int i = 0; i < columns.size(); i++) {
if (skip2) {
@@ -1940,8 +1940,8 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
continue;
}
} else {
- ofs += theme_cache.hseparation;
- w -= theme_cache.hseparation;
+ ofs += theme_cache.h_separation;
+ w -= theme_cache.h_separation;
}
if (p_item->cells[i].expand_right) {
@@ -1998,8 +1998,8 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
Rect2i item_rect = Rect2i(Point2i(ofs, p_pos.y) - theme_cache.offset + p_draw_ofs, Size2i(w, label_h));
Rect2i cell_rect = item_rect;
if (i != 0) {
- cell_rect.position.x -= theme_cache.hseparation;
- cell_rect.size.x += theme_cache.hseparation;
+ cell_rect.position.x -= theme_cache.h_separation;
+ cell_rect.size.x += theme_cache.h_separation;
}
if (theme_cache.draw_guides) {
@@ -2051,8 +2051,8 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
r.position.x = p_draw_ofs.x;
r.size.x = w + ofs;
} else {
- r.position.x -= theme_cache.hseparation;
- r.size.x += theme_cache.hseparation;
+ r.position.x -= theme_cache.h_separation;
+ r.size.x += theme_cache.h_separation;
}
if (rtl) {
r.position.x = get_size().width - r.position.x - r.size.x;
@@ -2136,7 +2136,7 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
unchecked->draw(ci, check_ofs);
}
- int check_w = checked->get_width() + theme_cache.hseparation;
+ int check_w = checked->get_width() + theme_cache.h_separation;
text_pos.x += check_w;
@@ -2328,7 +2328,7 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
// Draw relationship lines.
if (theme_cache.draw_relationship_lines > 0 && (!hide_root || c->parent != root) && c->is_visible()) {
- int root_ofs = children_pos.x + ((p_item->disable_folding || hide_folding) ? theme_cache.hseparation : theme_cache.item_margin);
+ int root_ofs = children_pos.x + ((p_item->disable_folding || hide_folding) ? theme_cache.h_separation : theme_cache.item_margin);
int parent_ofs = p_pos.x + theme_cache.item_margin;
Point2i root_pos = Point2i(root_ofs, children_pos.y + label_h / 2) - theme_cache.offset + p_draw_ofs;
@@ -2471,6 +2471,8 @@ bool Tree::_is_sibling_branch_selected(TreeItem *p_from) const {
}
void Tree::select_single_item(TreeItem *p_selected, TreeItem *p_current, int p_col, TreeItem *p_prev, bool *r_in_range, bool p_force_deselect) {
+ popup_editor->hide();
+
TreeItem::Cell &selected_cell = p_selected->cells.write[p_col];
bool switched = false;
@@ -2615,7 +2617,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, int
return 0;
}
- int item_h = compute_item_height(p_item) + theme_cache.vseparation;
+ int item_h = compute_item_height(p_item) + theme_cache.v_separation;
bool skip = (p_item == root && hide_root);
@@ -2649,7 +2651,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, int
if (p_item->cells[i].expand_right) {
int plus = 1;
while (i + plus < columns.size() && !p_item->cells[i + plus].editable && p_item->cells[i + plus].mode == TreeItem::CELL_MODE_STRING && p_item->cells[i + plus].text.is_empty() && p_item->cells[i + plus].icon.is_null()) {
- col_width += theme_cache.hseparation;
+ col_width += theme_cache.h_separation;
col_width += get_column_width(i + plus);
plus++;
}
@@ -2669,16 +2671,16 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, int
if (col == -1) {
return -1;
} else if (col == 0) {
- int margin = x_ofs + theme_cache.item_margin; //-theme_cache.hseparation;
+ int margin = x_ofs + theme_cache.item_margin; //-theme_cache.h_separation;
//int lm = theme_cache.panel_style->get_margin(SIDE_LEFT);
col_width -= margin;
limit_w -= margin;
col_ofs += margin;
x -= margin;
} else {
- col_width -= theme_cache.hseparation;
- limit_w -= theme_cache.hseparation;
- x -= theme_cache.hseparation;
+ col_width -= theme_cache.h_separation;
+ limit_w -= theme_cache.h_separation;
+ x -= theme_cache.h_separation;
}
if (!p_item->disable_folding && !hide_folding && !p_item->cells[col].editable && !p_item->cells[col].selectable && p_item->get_first_child()) {
@@ -3671,7 +3673,7 @@ void Tree::gui_input(const Ref<InputEvent> &p_event) {
drag_accum = 0;
//last_drag_accum=0;
drag_from = v_scroll->get_value();
- drag_touching = DisplayServer::get_singleton()->screen_is_touchscreen(DisplayServer::get_singleton()->window_get_current_screen(get_viewport()->get_window_id()));
+ drag_touching = DisplayServer::get_singleton()->is_touchscreen_available();
drag_touching_deaccel = false;
if (drag_touching) {
set_physics_process_internal(true);
@@ -3783,7 +3785,9 @@ bool Tree::edit_selected() {
} else if (c.mode == TreeItem::CELL_MODE_STRING || c.mode == TreeItem::CELL_MODE_RANGE) {
Rect2 popup_rect;
- Vector2 ofs(0, Math::floor((text_editor->get_size().height - rect.size.height) / 2)); // "floor()" centers vertically.
+ int value_editor_height = c.mode == TreeItem::CELL_MODE_RANGE ? value_editor->get_minimum_size().height : 0;
+ // "floor()" centers vertically.
+ Vector2 ofs(0, Math::floor((MAX(text_editor->get_minimum_size().height, rect.size.height - value_editor_height) - rect.size.height) / 2));
Point2i textedpos = get_screen_position() + rect.position - ofs;
cache.text_editor_position = textedpos;
@@ -3799,7 +3803,7 @@ bool Tree::edit_selected() {
text_editor->select_all();
if (c.mode == TreeItem::CELL_MODE_RANGE) {
- popup_rect.size.y += value_editor->get_minimum_size().height;
+ popup_rect.size.y += value_editor_height;
value_editor->show();
updating_value_editor = true;
@@ -4216,7 +4220,9 @@ Tree::SelectMode Tree::get_select_mode() const {
void Tree::deselect_all() {
TreeItem *item = get_next_selected(get_root());
while (item) {
- item->deselect(selected_col);
+ for (int i = 0; i < columns.size(); i++) {
+ item->deselect(i);
+ }
TreeItem *prev_item = item;
item = get_next_selected(get_root());
ERR_FAIL_COND(item == prev_item);
@@ -4338,6 +4344,12 @@ TreeItem *Tree::get_selected() const {
return selected_item;
}
+void Tree::set_selected(TreeItem *p_item, int p_column) {
+ ERR_FAIL_INDEX(p_column, columns.size());
+ ERR_FAIL_COND(!p_item);
+ select_single_item(p_item, get_root(), p_column);
+}
+
int Tree::get_selected_column() const {
return selected_col;
}
@@ -4420,7 +4432,7 @@ int Tree::get_column_minimum_width(int p_column) const {
if (p_column == 0) {
item_size.width += theme_cache.item_margin * depth;
} else {
- item_size.width += theme_cache.hseparation;
+ item_size.width += theme_cache.h_separation;
}
// Check if the item is wider.
@@ -4516,7 +4528,7 @@ int Tree::get_item_offset(TreeItem *p_item) const {
ofs += compute_item_height(it);
if (it != root || !hide_root) {
- ofs += theme_cache.vseparation;
+ ofs += theme_cache.v_separation;
}
if (it->first_child && !it->collapsed) {
@@ -4547,6 +4559,7 @@ void Tree::ensure_cursor_is_visible() {
return; // Nothing under cursor.
}
+ // Note: Code below similar to Tree::scroll_to_item(), in case of bug fix both.
const Size2 area_size = get_size() - theme_cache.panel_style->get_minimum_size();
int y_offset = get_item_offset(selected_item);
@@ -4554,8 +4567,11 @@ void Tree::ensure_cursor_is_visible() {
const int tbh = _get_title_button_height();
y_offset -= tbh;
- const int cell_h = compute_item_height(selected_item) + theme_cache.vseparation;
- const int screen_h = area_size.height - h_scroll->get_combined_minimum_size().height - tbh;
+ const int cell_h = compute_item_height(selected_item) + theme_cache.v_separation;
+ int screen_h = area_size.height - tbh;
+ if (h_scroll->is_visible()) {
+ screen_h -= h_scroll->get_combined_minimum_size().height;
+ }
if (cell_h > screen_h) { // Screen size is too small, maybe it was not resized yet.
v_scroll->set_value(y_offset);
@@ -4706,26 +4722,32 @@ Point2 Tree::get_scroll() const {
void Tree::scroll_to_item(TreeItem *p_item, bool p_center_on_item) {
ERR_FAIL_NULL(p_item);
- if (!is_visible_in_tree() || !p_item->is_visible()) {
- return; // Hack to work around crash in get_item_rect() if Tree is not in tree.
- }
update_scrollbars();
- const real_t tree_height = get_size().y;
- const Rect2 item_rect = get_item_rect(p_item);
- const real_t item_y = item_rect.position.y;
- const real_t item_height = item_rect.size.y + theme_cache.vseparation;
+ // Note: Code below similar to Tree::ensure_cursor_is_visible(), in case of bug fix both.
+ const Size2 area_size = get_size() - theme_cache.panel_style->get_minimum_size();
- if (p_center_on_item) {
- v_scroll->set_value(item_y - (tree_height - item_height) / 2.0f);
- } else {
- if (item_y < v_scroll->get_value()) {
- v_scroll->set_value(item_y);
+ int y_offset = get_item_offset(p_item);
+ if (y_offset != -1) {
+ const int tbh = _get_title_button_height();
+ y_offset -= tbh;
+
+ const int cell_h = compute_item_height(p_item) + theme_cache.v_separation;
+ int screen_h = area_size.height - tbh;
+ if (h_scroll->is_visible()) {
+ screen_h -= h_scroll->get_combined_minimum_size().height;
+ }
+
+ if (p_center_on_item) {
+ v_scroll->set_value(y_offset - (screen_h - cell_h) / 2.0f);
} else {
- const real_t new_position = item_y + item_height - tree_height;
- if (new_position > v_scroll->get_value()) {
- v_scroll->set_value(new_position);
+ if (cell_h > screen_h) { // Screen size is too small, maybe it was not resized yet.
+ v_scroll->set_value(y_offset);
+ } else if (y_offset + cell_h > v_scroll->get_value() + screen_h) {
+ v_scroll->set_value(y_offset - screen_h + cell_h);
+ } else if (y_offset < v_scroll->get_value()) {
+ v_scroll->set_value(y_offset);
}
}
}
@@ -4839,7 +4861,7 @@ TreeItem *Tree::_find_item_at_pos(TreeItem *p_item, const Point2 &p_pos, int &r_
Point2 pos = p_pos;
if ((root != p_item || !hide_root) && p_item->is_visible()) {
- h = compute_item_height(p_item) + theme_cache.vseparation;
+ h = compute_item_height(p_item) + theme_cache.v_separation;
if (pos.y < h) {
if (drop_mode_flags == DROP_MODE_ON_ITEM) {
section = 0;
@@ -5156,6 +5178,7 @@ void Tree::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_root_hidden"), &Tree::is_root_hidden);
ClassDB::bind_method(D_METHOD("get_next_selected", "from"), &Tree::get_next_selected);
ClassDB::bind_method(D_METHOD("get_selected"), &Tree::get_selected);
+ ClassDB::bind_method(D_METHOD("set_selected", "item", "column"), &Tree::set_selected);
ClassDB::bind_method(D_METHOD("get_selected_column"), &Tree::get_selected_column);
ClassDB::bind_method(D_METHOD("get_pressed_button"), &Tree::get_pressed_button);
ClassDB::bind_method(D_METHOD("set_select_mode", "mode"), &Tree::set_select_mode);
@@ -5260,7 +5283,6 @@ Tree::Tree() {
add_child(popup_menu, false, INTERNAL_MODE_FRONT);
popup_editor = memnew(Popup);
- popup_editor->set_wrap_controls(true);
add_child(popup_editor, false, INTERNAL_MODE_FRONT);
popup_editor_vb = memnew(VBoxContainer);
popup_editor->add_child(popup_editor_vb);
@@ -5269,11 +5291,9 @@ Tree::Tree() {
text_editor = memnew(LineEdit);
popup_editor_vb->add_child(text_editor);
text_editor->set_v_size_flags(SIZE_EXPAND_FILL);
- text_editor->set_h_size_flags(SIZE_EXPAND_FILL);
value_editor = memnew(HSlider);
- value_editor->set_v_size_flags(SIZE_EXPAND_FILL);
- value_editor->set_h_size_flags(SIZE_EXPAND_FILL);
popup_editor_vb->add_child(value_editor);
+ value_editor->set_v_size_flags(SIZE_EXPAND_FILL);
value_editor->hide();
h_scroll = memnew(HScrollBar);
diff --git a/scene/gui/tree.h b/scene/gui/tree.h
index f994a5cec1..cdd90fe4c7 100644
--- a/scene/gui/tree.h
+++ b/scene/gui/tree.h
@@ -531,8 +531,8 @@ private:
float base_scale = 1.0;
- int hseparation = 0;
- int vseparation = 0;
+ int h_separation = 0;
+ int v_separation = 0;
int item_margin = 0;
int button_margin = 0;
Point2 offset;
@@ -666,6 +666,7 @@ public:
bool is_root_hidden() const;
TreeItem *get_next_selected(TreeItem *p_item);
TreeItem *get_selected() const;
+ void set_selected(TreeItem *p_item, int p_column = 0);
int get_selected_column() const;
int get_pressed_button() const;
void set_select_mode(SelectMode p_mode);
diff --git a/scene/main/canvas_item.cpp b/scene/main/canvas_item.cpp
index 7bcd4721fc..f3812eb497 100644
--- a/scene/main/canvas_item.cpp
+++ b/scene/main/canvas_item.cpp
@@ -144,7 +144,7 @@ void CanvasItem::_redraw_callback() {
Transform2D CanvasItem::get_global_transform_with_canvas() const {
if (canvas_layer) {
- return canvas_layer->get_transform() * get_global_transform();
+ return canvas_layer->get_final_transform() * get_global_transform();
} else if (is_inside_tree()) {
return get_viewport()->get_canvas_transform() * get_global_transform();
} else {
@@ -450,6 +450,39 @@ void CanvasItem::item_rect_changed(bool p_size_changed) {
emit_signal(SceneStringNames::get_singleton()->item_rect_changed);
}
+void CanvasItem::set_z_index(int p_z) {
+ ERR_FAIL_COND(p_z < RS::CANVAS_ITEM_Z_MIN);
+ ERR_FAIL_COND(p_z > RS::CANVAS_ITEM_Z_MAX);
+ z_index = p_z;
+ RS::get_singleton()->canvas_item_set_z_index(canvas_item, z_index);
+ update_configuration_warnings();
+}
+
+void CanvasItem::set_z_as_relative(bool p_enabled) {
+ if (z_relative == p_enabled) {
+ return;
+ }
+ z_relative = p_enabled;
+ RS::get_singleton()->canvas_item_set_z_as_relative_to_parent(canvas_item, p_enabled);
+}
+
+bool CanvasItem::is_z_relative() const {
+ return z_relative;
+}
+
+int CanvasItem::get_z_index() const {
+ return z_index;
+}
+
+void CanvasItem::set_y_sort_enabled(bool p_enabled) {
+ y_sort_enabled = p_enabled;
+ RS::get_singleton()->canvas_item_set_sort_children_by_y(canvas_item, y_sort_enabled);
+}
+
+bool CanvasItem::is_y_sort_enabled() const {
+ return y_sort_enabled;
+}
+
void CanvasItem::draw_dashed_line(const Point2 &p_from, const Point2 &p_to, const Color &p_color, real_t p_width, real_t p_dash) {
ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal.");
@@ -588,10 +621,10 @@ void CanvasItem::draw_texture_rect_region(const Ref<Texture2D> &p_texture, const
p_texture->draw_rect_region(canvas_item, p_rect, p_src_rect, p_modulate, p_transpose, p_clip_uv);
}
-void CanvasItem::draw_msdf_texture_rect_region(const Ref<Texture2D> &p_texture, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate, double p_outline, double p_pixel_range) {
+void CanvasItem::draw_msdf_texture_rect_region(const Ref<Texture2D> &p_texture, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate, double p_outline, double p_pixel_range, double p_scale) {
ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal.");
ERR_FAIL_COND(p_texture.is_null());
- RenderingServer::get_singleton()->canvas_item_add_msdf_texture_rect_region(canvas_item, p_rect, p_texture->get_rid(), p_src_rect, p_modulate, p_outline, p_pixel_range);
+ RenderingServer::get_singleton()->canvas_item_add_msdf_texture_rect_region(canvas_item, p_rect, p_texture->get_rid(), p_src_rect, p_modulate, p_outline, p_pixel_range, p_scale);
}
void CanvasItem::draw_lcd_texture_rect_region(const Ref<Texture2D> &p_texture, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate) {
@@ -913,9 +946,19 @@ void CanvasItem::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_modulate", "modulate"), &CanvasItem::set_modulate);
ClassDB::bind_method(D_METHOD("get_modulate"), &CanvasItem::get_modulate);
+
ClassDB::bind_method(D_METHOD("set_self_modulate", "self_modulate"), &CanvasItem::set_self_modulate);
ClassDB::bind_method(D_METHOD("get_self_modulate"), &CanvasItem::get_self_modulate);
+ ClassDB::bind_method(D_METHOD("set_z_index", "z_index"), &CanvasItem::set_z_index);
+ ClassDB::bind_method(D_METHOD("get_z_index"), &CanvasItem::get_z_index);
+
+ ClassDB::bind_method(D_METHOD("set_z_as_relative", "enable"), &CanvasItem::set_z_as_relative);
+ ClassDB::bind_method(D_METHOD("is_z_relative"), &CanvasItem::is_z_relative);
+
+ ClassDB::bind_method(D_METHOD("set_y_sort_enabled", "enabled"), &CanvasItem::set_y_sort_enabled);
+ ClassDB::bind_method(D_METHOD("is_y_sort_enabled"), &CanvasItem::is_y_sort_enabled);
+
ClassDB::bind_method(D_METHOD("set_draw_behind_parent", "enable"), &CanvasItem::set_draw_behind_parent);
ClassDB::bind_method(D_METHOD("is_draw_behind_parent_enabled"), &CanvasItem::is_draw_behind_parent_enabled);
@@ -931,7 +974,7 @@ void CanvasItem::_bind_methods() {
ClassDB::bind_method(D_METHOD("draw_texture", "texture", "position", "modulate"), &CanvasItem::draw_texture, DEFVAL(Color(1, 1, 1, 1)));
ClassDB::bind_method(D_METHOD("draw_texture_rect", "texture", "rect", "tile", "modulate", "transpose"), &CanvasItem::draw_texture_rect, DEFVAL(Color(1, 1, 1, 1)), DEFVAL(false));
ClassDB::bind_method(D_METHOD("draw_texture_rect_region", "texture", "rect", "src_rect", "modulate", "transpose", "clip_uv"), &CanvasItem::draw_texture_rect_region, DEFVAL(Color(1, 1, 1, 1)), DEFVAL(false), DEFVAL(true));
- ClassDB::bind_method(D_METHOD("draw_msdf_texture_rect_region", "texture", "rect", "src_rect", "modulate", "outline", "pixel_range"), &CanvasItem::draw_msdf_texture_rect_region, DEFVAL(Color(1, 1, 1, 1)), DEFVAL(0.0), DEFVAL(4.0));
+ ClassDB::bind_method(D_METHOD("draw_msdf_texture_rect_region", "texture", "rect", "src_rect", "modulate", "outline", "pixel_range", "scale"), &CanvasItem::draw_msdf_texture_rect_region, DEFVAL(Color(1, 1, 1, 1)), DEFVAL(0.0), DEFVAL(4.0), DEFVAL(1.0));
ClassDB::bind_method(D_METHOD("draw_lcd_texture_rect_region", "texture", "rect", "src_rect", "modulate"), &CanvasItem::draw_lcd_texture_rect_region, DEFVAL(Color(1, 1, 1, 1)));
ClassDB::bind_method(D_METHOD("draw_style_box", "style_box", "rect"), &CanvasItem::draw_style_box);
ClassDB::bind_method(D_METHOD("draw_primitive", "points", "colors", "uvs", "texture", "width"), &CanvasItem::draw_primitive, DEFVAL(Ref<Texture2D>()), DEFVAL(1.0));
@@ -1005,6 +1048,11 @@ void CanvasItem::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "light_mask", PROPERTY_HINT_LAYERS_2D_RENDER), "set_light_mask", "get_light_mask");
ADD_PROPERTY(PropertyInfo(Variant::INT, "visibility_layer", PROPERTY_HINT_LAYERS_2D_RENDER), "set_visibility_layer", "get_visibility_layer");
+ ADD_GROUP("Ordering", "");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "z_index", PROPERTY_HINT_RANGE, itos(RS::CANVAS_ITEM_Z_MIN) + "," + itos(RS::CANVAS_ITEM_Z_MAX) + ",1"), "set_z_index", "get_z_index");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "z_as_relative"), "set_z_as_relative", "is_z_relative");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "y_sort_enabled"), "set_y_sort_enabled", "is_y_sort_enabled");
+
ADD_GROUP("Texture", "texture_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_filter", PROPERTY_HINT_ENUM, "Inherit,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, "Inherit,Disabled,Enabled,Mirror"), "set_texture_repeat", "get_texture_repeat");
@@ -1051,7 +1099,7 @@ Transform2D CanvasItem::get_canvas_transform() const {
ERR_FAIL_COND_V(!is_inside_tree(), Transform2D());
if (canvas_layer) {
- return canvas_layer->get_transform();
+ return canvas_layer->get_final_transform();
} else if (Object::cast_to<CanvasItem>(get_parent())) {
return Object::cast_to<CanvasItem>(get_parent())->get_canvas_transform();
} else {
@@ -1063,7 +1111,7 @@ Transform2D CanvasItem::get_viewport_transform() const {
ERR_FAIL_COND_V(!is_inside_tree(), Transform2D());
if (canvas_layer) {
- return get_viewport()->get_final_transform() * canvas_layer->get_transform();
+ return get_viewport()->get_final_transform() * canvas_layer->get_final_transform();
} else {
return get_viewport()->get_final_transform() * get_viewport()->get_canvas_transform();
}
diff --git a/scene/main/canvas_item.h b/scene/main/canvas_item.h
index 4e78a175dc..bae03d706a 100644
--- a/scene/main/canvas_item.h
+++ b/scene/main/canvas_item.h
@@ -91,6 +91,10 @@ private:
int light_mask = 1;
uint32_t visibility_layer = 1;
+ int z_index = 0;
+ bool z_relative = true;
+ bool y_sort_enabled = false;
+
Window *window = nullptr;
bool visible = true;
bool parent_visible_in_tree = false;
@@ -230,6 +234,17 @@ public:
void set_visibility_layer_bit(uint32_t p_visibility_layer, bool p_enable);
bool get_visibility_layer_bit(uint32_t p_visibility_layer) const;
+ /* ORDERING */
+
+ void set_z_index(int p_z);
+ int get_z_index() const;
+
+ void set_z_as_relative(bool p_enabled);
+ bool is_z_relative() const;
+
+ virtual void set_y_sort_enabled(bool p_enabled);
+ virtual bool is_y_sort_enabled() const;
+
/* DRAWING API */
void draw_dashed_line(const Point2 &p_from, const Point2 &p_to, const Color &p_color, real_t p_width = 1.0, real_t p_dash = 2.0);
@@ -244,7 +259,7 @@ public:
void draw_texture(const Ref<Texture2D> &p_texture, const Point2 &p_pos, const Color &p_modulate = Color(1, 1, 1, 1));
void draw_texture_rect(const Ref<Texture2D> &p_texture, const Rect2 &p_rect, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false);
void draw_texture_rect_region(const Ref<Texture2D> &p_texture, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, bool p_clip_uv = false);
- void draw_msdf_texture_rect_region(const Ref<Texture2D> &p_texture, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), double p_outline = 0.0, double p_pixel_range = 4.0);
+ void draw_msdf_texture_rect_region(const Ref<Texture2D> &p_texture, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), double p_outline = 0.0, double p_pixel_range = 4.0, double p_scale = 1.0);
void draw_lcd_texture_rect_region(const Ref<Texture2D> &p_texture, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1));
void draw_style_box(const Ref<StyleBox> &p_style_box, const Rect2 &p_rect);
void draw_primitive(const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, Ref<Texture2D> p_texture = Ref<Texture2D>(), real_t p_width = 1);
diff --git a/scene/main/canvas_layer.cpp b/scene/main/canvas_layer.cpp
index be5788739b..97b784e9d0 100644
--- a/scene/main/canvas_layer.cpp
+++ b/scene/main/canvas_layer.cpp
@@ -38,7 +38,7 @@ void CanvasLayer::set_layer(int p_xform) {
layer = p_xform;
if (viewport.is_valid()) {
RenderingServer::get_singleton()->viewport_set_canvas_stacking(viewport, canvas, layer, get_index());
- vp->_gui_set_root_order_dirty();
+ vp->gui_set_root_order_dirty();
}
}
@@ -88,6 +88,18 @@ Transform2D CanvasLayer::get_transform() const {
return transform;
}
+Transform2D CanvasLayer::get_final_transform() const {
+ if (is_following_viewport()) {
+ Transform2D follow;
+ follow.scale(Vector2(get_follow_viewport_scale(), get_follow_viewport_scale()));
+ if (vp) {
+ follow = vp->get_canvas_transform() * follow;
+ }
+ return follow * transform;
+ }
+ return transform;
+}
+
void CanvasLayer::_update_xform() {
transform.set_rotation_and_scale(rot, scale);
transform.set_origin(ofs);
@@ -304,6 +316,7 @@ void CanvasLayer::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_transform", "transform"), &CanvasLayer::set_transform);
ClassDB::bind_method(D_METHOD("get_transform"), &CanvasLayer::get_transform);
+ ClassDB::bind_method(D_METHOD("get_final_transform"), &CanvasLayer::get_final_transform);
ClassDB::bind_method(D_METHOD("set_offset", "offset"), &CanvasLayer::set_offset);
ClassDB::bind_method(D_METHOD("get_offset"), &CanvasLayer::get_offset);
diff --git a/scene/main/canvas_layer.h b/scene/main/canvas_layer.h
index 74b5ebd453..2afc842a50 100644
--- a/scene/main/canvas_layer.h
+++ b/scene/main/canvas_layer.h
@@ -77,6 +77,7 @@ public:
void set_transform(const Transform2D &p_xform);
Transform2D get_transform() const;
+ Transform2D get_final_transform() const;
void set_offset(const Vector2 &p_offset);
Vector2 get_offset() const;
diff --git a/scene/main/http_request.cpp b/scene/main/http_request.cpp
index 2c395ec07d..62f362553f 100644
--- a/scene/main/http_request.cpp
+++ b/scene/main/http_request.cpp
@@ -276,10 +276,10 @@ bool HTTPRequest::_handle_response(bool *ret_value) {
}
if (content_encoding == "gzip") {
decompressor.instantiate();
- decompressor->start_decompression(false, get_download_chunk_size() * 2);
+ decompressor->start_decompression(false, get_download_chunk_size());
} else if (content_encoding == "deflate") {
decompressor.instantiate();
- decompressor->start_decompression(true, get_download_chunk_size() * 2);
+ decompressor->start_decompression(true, get_download_chunk_size());
}
return false;
@@ -390,19 +390,38 @@ bool HTTPRequest::_update_connection() {
return false;
}
- PackedByteArray chunk = client->read_response_body_chunk();
- downloaded.add(chunk.size());
-
- // Decompress chunk if needed.
- if (decompressor.is_valid()) {
- Error err = decompressor->put_data(chunk.ptr(), chunk.size());
- if (err == OK) {
- chunk.resize(decompressor->get_available_bytes());
- err = decompressor->get_data(chunk.ptrw(), chunk.size());
- }
- if (err != OK) {
- _defer_done(RESULT_BODY_DECOMPRESS_FAILED, response_code, response_headers, PackedByteArray());
- return true;
+ PackedByteArray chunk;
+ if (decompressor.is_null()) {
+ // Chunk can be read directly.
+ chunk = client->read_response_body_chunk();
+ downloaded.add(chunk.size());
+ } else {
+ // Chunk is the result of decompression.
+ PackedByteArray compressed = client->read_response_body_chunk();
+ downloaded.add(compressed.size());
+
+ int pos = 0;
+ int left = compressed.size();
+ while (left) {
+ int w = 0;
+ Error err = decompressor->put_partial_data(compressed.ptr() + pos, left, w);
+ if (err == OK) {
+ PackedByteArray dc;
+ dc.resize(decompressor->get_available_bytes());
+ err = decompressor->get_data(dc.ptrw(), dc.size());
+ chunk.append_array(dc);
+ }
+ if (err != OK) {
+ _defer_done(RESULT_BODY_DECOMPRESS_FAILED, response_code, response_headers, PackedByteArray());
+ return true;
+ }
+ // We need this check here because a "zip bomb" could result in a chunk of few kilos decompressing into gigabytes of data.
+ if (body_size_limit >= 0 && final_body_size.get() + chunk.size() > body_size_limit) {
+ _defer_done(RESULT_BODY_SIZE_LIMIT_EXCEEDED, response_code, response_headers, PackedByteArray());
+ return true;
+ }
+ pos += w;
+ left -= w;
}
}
final_body_size.add(chunk.size());
diff --git a/scene/main/multiplayer_api.cpp b/scene/main/multiplayer_api.cpp
index 946929aa89..8b4b98c172 100644
--- a/scene/main/multiplayer_api.cpp
+++ b/scene/main/multiplayer_api.cpp
@@ -39,7 +39,7 @@
#include "core/os/os.h"
#endif
-StringName MultiplayerAPI::default_interface = StringName();
+StringName MultiplayerAPI::default_interface;
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));
diff --git a/scene/main/multiplayer_peer.h b/scene/main/multiplayer_peer.h
index 4b5909538e..fa6b11e5db 100644
--- a/scene/main/multiplayer_peer.h
+++ b/scene/main/multiplayer_peer.h
@@ -112,11 +112,11 @@ protected:
public:
/* PacketPeer extension */
virtual Error get_packet(const uint8_t **r_buffer, int &r_buffer_size) override; ///< buffer is GONE after next get_packet
- GDVIRTUAL2R(Error, _get_packet, GDNativeConstPtr<const uint8_t *>, GDNativePtr<int>);
+ GDVIRTUAL2R(Error, _get_packet, GDExtensionConstPtr<const uint8_t *>, GDExtensionPtr<int>);
GDVIRTUAL0R(PackedByteArray, _get_packet_script); // For GDScript.
virtual Error put_packet(const uint8_t *p_buffer, int p_buffer_size) override;
- GDVIRTUAL2R(Error, _put_packet, GDNativeConstPtr<const uint8_t>, int);
+ GDVIRTUAL2R(Error, _put_packet, GDExtensionConstPtr<const uint8_t>, int);
GDVIRTUAL1R(Error, _put_packet_script, PackedByteArray); // For GDScript.
EXBIND0RC(int, get_available_packet_count);
diff --git a/scene/main/node.cpp b/scene/main/node.cpp
index 304504a82e..680c4cd7e4 100644
--- a/scene/main/node.cpp
+++ b/scene/main/node.cpp
@@ -349,7 +349,7 @@ void Node::move_child(Node *p_child, int p_index) {
}
void Node::_move_child(Node *p_child, int p_index, bool p_ignore_end) {
- ERR_FAIL_COND_MSG(data.blocked > 0, "Parent node is busy setting up children, move_child() failed. Consider using call_deferred(\"move_child\") instead (or \"popup\" if this is from a popup).");
+ ERR_FAIL_COND_MSG(data.blocked > 0, "Parent node is busy setting up children, `move_child()` failed. Consider using `move_child.call_deferred(child, index)` instead (or `popup.call_deferred()` if this is from a popup).");
// Specifying one place beyond the end
// means the same as moving to the last index
@@ -1130,7 +1130,7 @@ void Node::add_child(Node *p_child, bool p_force_readable_name, InternalMode p_i
#ifdef DEBUG_ENABLED
ERR_FAIL_COND_MSG(p_child->is_ancestor_of(this), vformat("Can't add child '%s' to '%s' as it would result in a cyclic dependency since '%s' is already a parent of '%s'.", p_child->get_name(), get_name(), p_child->get_name(), get_name()));
#endif
- ERR_FAIL_COND_MSG(data.blocked > 0, "Parent node is busy setting up children, add_node() failed. Consider using call_deferred(\"add_child\", child) instead.");
+ ERR_FAIL_COND_MSG(data.blocked > 0, "Parent node is busy setting up children, `add_child()` failed. Consider using `add_child.call_deferred(child)` instead.");
_validate_child_name(p_child, p_force_readable_name);
_add_child_nocheck(p_child, p_child->data.name);
@@ -1150,7 +1150,7 @@ void Node::add_sibling(Node *p_sibling, bool p_force_readable_name) {
ERR_FAIL_NULL(p_sibling);
ERR_FAIL_NULL(data.parent);
ERR_FAIL_COND_MSG(p_sibling == this, vformat("Can't add sibling '%s' to itself.", p_sibling->get_name())); // adding to itself!
- ERR_FAIL_COND_MSG(data.blocked > 0, "Parent node is busy setting up children, add_sibling() failed. Consider using call_deferred(\"add_sibling\", sibling) instead.");
+ ERR_FAIL_COND_MSG(data.blocked > 0, "Parent node is busy setting up children, `add_sibling()` failed. Consider using `add_sibling.call_deferred(sibling)` instead.");
InternalMode internal = INTERNAL_MODE_DISABLED;
if (_is_internal_front()) { // The sibling will have the same internal status.
@@ -1165,7 +1165,7 @@ void Node::add_sibling(Node *p_sibling, bool p_force_readable_name) {
void Node::remove_child(Node *p_child) {
ERR_FAIL_NULL(p_child);
- ERR_FAIL_COND_MSG(data.blocked > 0, "Parent node is busy setting up children, remove_node() failed. Consider using call_deferred(\"remove_child\", child) instead.");
+ ERR_FAIL_COND_MSG(data.blocked > 0, "Parent node is busy setting up children, `remove_child()` failed. Consider using `remove_child.call_deferred(child)` instead.");
int child_count = data.children.size();
Node **children = data.children.ptrw();
@@ -1660,7 +1660,7 @@ Node *Node::find_common_parent_with(const Node *p_node) const {
return const_cast<Node *>(common_parent);
}
-NodePath Node::get_path_to(const Node *p_node) const {
+NodePath Node::get_path_to(const Node *p_node, bool p_use_unique_path) const {
ERR_FAIL_NULL_V(p_node, NodePath());
if (this == p_node) {
@@ -1690,20 +1690,58 @@ NodePath Node::get_path_to(const Node *p_node) const {
visited.clear();
Vector<StringName> path;
+ StringName up = String("..");
- n = p_node;
+ if (p_use_unique_path) {
+ n = p_node;
- while (n != common_parent) {
- path.push_back(n->get_name());
- n = n->data.parent;
- }
+ bool is_detected = false;
+ while (n != common_parent) {
+ if (n->is_unique_name_in_owner() && n->get_owner() == get_owner()) {
+ path.push_back(UNIQUE_NODE_PREFIX + String(n->get_name()));
+ is_detected = true;
+ break;
+ }
+ path.push_back(n->get_name());
+ n = n->data.parent;
+ }
- n = this;
- StringName up = String("..");
+ if (!is_detected) {
+ n = this;
- while (n != common_parent) {
- path.push_back(up);
- n = n->data.parent;
+ String detected_name;
+ int up_count = 0;
+ while (n != common_parent) {
+ if (n->is_unique_name_in_owner() && n->get_owner() == get_owner()) {
+ detected_name = n->get_name();
+ up_count = 0;
+ }
+ up_count++;
+ n = n->data.parent;
+ }
+
+ for (int i = 0; i < up_count; i++) {
+ path.push_back(up);
+ }
+
+ if (!detected_name.is_empty()) {
+ path.push_back(UNIQUE_NODE_PREFIX + detected_name);
+ }
+ }
+ } else {
+ n = p_node;
+
+ while (n != common_parent) {
+ path.push_back(n->get_name());
+ n = n->data.parent;
+ }
+
+ n = this;
+
+ while (n != common_parent) {
+ path.push_back(up);
+ n = n->data.parent;
+ }
}
path.reverse();
@@ -1759,11 +1797,11 @@ void Node::add_to_group(const StringName &p_identifier, bool p_persistent) {
}
void Node::remove_from_group(const StringName &p_identifier) {
- ERR_FAIL_COND(!data.grouped.has(p_identifier));
-
HashMap<StringName, GroupData>::Iterator E = data.grouped.find(p_identifier);
- ERR_FAIL_COND(!E);
+ if (!E) {
+ return;
+ }
if (data.tree) {
data.tree->remove_from_group(E->key, this);
@@ -2060,7 +2098,7 @@ Node *Node::_duplicate(int p_flags, HashMap<const Node *, Node *> *r_duplimap) c
nip->set_instance_path(ip->get_instance_path());
node = nip;
- } else if ((p_flags & DUPLICATE_USE_INSTANCING) && !get_scene_file_path().is_empty()) {
+ } else if ((p_flags & DUPLICATE_USE_INSTANTIATION) && !get_scene_file_path().is_empty()) {
Ref<PackedScene> res = ResourceLoader::load(get_scene_file_path());
ERR_FAIL_COND_V(res.is_null(), nullptr);
PackedScene::GenEditState ges = PackedScene::GEN_EDIT_STATE_DISABLED;
@@ -2246,7 +2284,7 @@ Node *Node::duplicate_from_editor(HashMap<const Node *, Node *> &r_duplimap) con
}
Node *Node::duplicate_from_editor(HashMap<const Node *, Node *> &r_duplimap, const HashMap<Ref<Resource>, Ref<Resource>> &p_resource_remap) const {
- Node *dupe = _duplicate(DUPLICATE_SIGNALS | DUPLICATE_GROUPS | DUPLICATE_SCRIPTS | DUPLICATE_USE_INSTANCING | DUPLICATE_FROM_EDITOR, &r_duplimap);
+ Node *dupe = _duplicate(DUPLICATE_SIGNALS | DUPLICATE_GROUPS | DUPLICATE_SCRIPTS | DUPLICATE_USE_INSTANTIATION | DUPLICATE_FROM_EDITOR, &r_duplimap);
// This is used by SceneTreeDock's paste functionality. When pasting to foreign scene, resources are duplicated.
if (!p_resource_remap.is_empty()) {
@@ -2570,10 +2608,6 @@ static void _Node_debug_sn(Object *p_obj) {
}
#endif // DEBUG_ENABLED
-void Node::_print_orphan_nodes() {
- print_orphan_nodes();
-}
-
void Node::print_orphan_nodes() {
#ifdef DEBUG_ENABLED
ObjectDB::debug_objects(_Node_debug_sn);
@@ -2581,10 +2615,14 @@ void Node::print_orphan_nodes() {
}
void Node::queue_free() {
+ // There are users which instantiate multiple scene trees for their games.
+ // Use the node's own tree to handle its deletion when relevant.
if (is_inside_tree()) {
get_tree()->queue_delete(this);
} else {
- SceneTree::get_singleton()->queue_delete(this);
+ SceneTree *tree = SceneTree::get_singleton();
+ ERR_FAIL_NULL_MSG(tree, "Can't queue free a node when no SceneTree is available.");
+ tree->queue_delete(this);
}
}
@@ -2652,7 +2690,7 @@ PackedStringArray Node::get_configuration_warnings() const {
String Node::get_configuration_warnings_as_string() const {
PackedStringArray warnings = get_configuration_warnings();
- String all_warnings = String();
+ String all_warnings;
for (int i = 0; i < warnings.size(); i++) {
if (i > 0) {
all_warnings += "\n\n";
@@ -2741,6 +2779,7 @@ void Node::_bind_methods() {
GLOBAL_DEF("editor/node_naming/name_casing", NAME_CASING_PASCAL_CASE);
ProjectSettings::get_singleton()->set_custom_property_info("editor/node_naming/name_casing", PropertyInfo(Variant::INT, "editor/node_naming/name_casing", PROPERTY_HINT_ENUM, "PascalCase,camelCase,snake_case"));
+ ClassDB::bind_static_method("Node", D_METHOD("print_orphan_nodes"), &Node::print_orphan_nodes);
ClassDB::bind_method(D_METHOD("add_sibling", "sibling", "force_readable_name"), &Node::add_sibling, DEFVAL(false));
ClassDB::bind_method(D_METHOD("set_name", "name"), &Node::set_name);
@@ -2764,7 +2803,7 @@ void Node::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_ancestor_of", "node"), &Node::is_ancestor_of);
ClassDB::bind_method(D_METHOD("is_greater_than", "node"), &Node::is_greater_than);
ClassDB::bind_method(D_METHOD("get_path"), &Node::get_path);
- ClassDB::bind_method(D_METHOD("get_path_to", "node"), &Node::get_path_to);
+ ClassDB::bind_method(D_METHOD("get_path_to", "node", "use_unique_path"), &Node::get_path_to, DEFVAL(false));
ClassDB::bind_method(D_METHOD("add_to_group", "group", "persistent"), &Node::add_to_group, DEFVAL(false));
ClassDB::bind_method(D_METHOD("remove_from_group", "group"), &Node::remove_from_group);
ClassDB::bind_method(D_METHOD("is_in_group", "group"), &Node::is_in_group);
@@ -2798,7 +2837,6 @@ void Node::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_process_mode", "mode"), &Node::set_process_mode);
ClassDB::bind_method(D_METHOD("get_process_mode"), &Node::get_process_mode);
ClassDB::bind_method(D_METHOD("can_process"), &Node::can_process);
- ClassDB::bind_method(D_METHOD("print_orphan_nodes"), &Node::_print_orphan_nodes);
ClassDB::bind_method(D_METHOD("set_display_folded", "fold"), &Node::set_display_folded);
ClassDB::bind_method(D_METHOD("is_displayed_folded"), &Node::is_displayed_folded);
@@ -2812,7 +2850,7 @@ void Node::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_tree"), &Node::get_tree);
ClassDB::bind_method(D_METHOD("create_tween"), &Node::create_tween);
- ClassDB::bind_method(D_METHOD("duplicate", "flags"), &Node::duplicate, DEFVAL(DUPLICATE_USE_INSTANCING | DUPLICATE_SIGNALS | DUPLICATE_GROUPS | DUPLICATE_SCRIPTS));
+ ClassDB::bind_method(D_METHOD("duplicate", "flags"), &Node::duplicate, DEFVAL(DUPLICATE_USE_INSTANTIATION | DUPLICATE_SIGNALS | DUPLICATE_GROUPS | DUPLICATE_SCRIPTS));
ClassDB::bind_method(D_METHOD("replace_by", "node", "keep_groups"), &Node::replace_by, DEFVAL(false));
ClassDB::bind_method(D_METHOD("set_scene_instance_load_placeholder", "load_placeholder"), &Node::set_scene_instance_load_placeholder);
@@ -2918,7 +2956,7 @@ void Node::_bind_methods() {
BIND_ENUM_CONSTANT(DUPLICATE_SIGNALS);
BIND_ENUM_CONSTANT(DUPLICATE_GROUPS);
BIND_ENUM_CONSTANT(DUPLICATE_SCRIPTS);
- BIND_ENUM_CONSTANT(DUPLICATE_USE_INSTANCING);
+ BIND_ENUM_CONSTANT(DUPLICATE_USE_INSTANTIATION);
BIND_ENUM_CONSTANT(INTERNAL_MODE_DISABLED);
BIND_ENUM_CONSTANT(INTERNAL_MODE_FRONT);
diff --git a/scene/main/node.h b/scene/main/node.h
index 4a3ec253b1..574f5063e8 100644
--- a/scene/main/node.h
+++ b/scene/main/node.h
@@ -57,7 +57,7 @@ public:
DUPLICATE_SIGNALS = 1,
DUPLICATE_GROUPS = 2,
DUPLICATE_SCRIPTS = 4,
- DUPLICATE_USE_INSTANCING = 8,
+ DUPLICATE_USE_INSTANTIATION = 8,
#ifdef TOOLS_ENABLED
DUPLICATE_FROM_EDITOR = 16,
#endif
@@ -173,7 +173,6 @@ private:
void _propagate_ready();
void _propagate_exit_tree();
void _propagate_after_exit_tree();
- void _print_orphan_nodes();
void _propagate_process_owner(Node *p_owner, int p_pause_notification, int p_enabled_notification);
void _propagate_groups_dirty();
Array _get_node_and_resource(const NodePath &p_path);
@@ -332,7 +331,7 @@ public:
bool is_greater_than(const Node *p_node) const;
NodePath get_path() const;
- NodePath get_path_to(const Node *p_node) const;
+ NodePath get_path_to(const Node *p_node, bool p_use_unique_path = false) const;
Node *find_common_parent_with(const Node *p_node) const;
void add_to_group(const StringName &p_identifier, bool p_persistent = false);
diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp
index 41eefe0f85..e61cca0a0f 100644
--- a/scene/main/scene_tree.cpp
+++ b/scene/main/scene_tree.cpp
@@ -594,6 +594,12 @@ void SceneTree::finalize() {
timer->release_connections();
}
timers.clear();
+
+ // Cleanup tweens.
+ for (Ref<Tween> &tween : tweens) {
+ tween->clear();
+ }
+ tweens.clear();
}
void SceneTree::quit(int p_exit_code) {
@@ -942,6 +948,9 @@ void SceneTree::_call_input_pause(const StringName &p_group, CallInputType p_cal
}
for (const ObjectID &id : no_context_node_ids) {
+ if (p_viewport->is_input_handled()) {
+ break;
+ }
Node *n = Object::cast_to<Node>(ObjectDB::get_instance(id));
if (n) {
n->_call_shortcut_input(p_input);
@@ -1413,7 +1422,7 @@ SceneTree::SceneTree() {
ProjectSettings::get_singleton()->set_custom_property_info("rendering/anti_aliasing/quality/msaa_3d", PropertyInfo(Variant::INT, "rendering/anti_aliasing/quality/msaa_3d", PROPERTY_HINT_ENUM, String::utf8("Disabled (Fastest),2× (Average),4× (Slow),8× (Slowest)")));
root->set_msaa_3d(Viewport::MSAA(msaa_mode_3d));
- const bool transparent_background = GLOBAL_DEF("rendering/transparent_background", false);
+ const bool transparent_background = GLOBAL_DEF("rendering/viewport/transparent_background", false);
root->set_transparent_background(transparent_background);
const int ssaa_mode = GLOBAL_DEF_BASIC("rendering/anti_aliasing/quality/screen_space_aa", 0);
@@ -1447,7 +1456,7 @@ SceneTree::SceneTree() {
ProjectSettings::get_singleton()->set_custom_property_info("rendering/vrs/texture",
PropertyInfo(Variant::STRING,
"rendering/vrs/texture",
- PROPERTY_HINT_FILE, "*.png"));
+ PROPERTY_HINT_FILE, "*.bmp,*.png,*.tga,*.webp"));
if (vrs_mode == 1 && !vrs_texture_path.is_empty()) {
Ref<Image> vrs_image;
vrs_image.instantiate();
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index 43a2c9473e..afc31ae480 100644
--- a/scene/main/viewport.cpp
+++ b/scene/main/viewport.cpp
@@ -362,6 +362,7 @@ void Viewport::_notification(int p_what) {
current_canvas = find_world_2d()->get_canvas();
RenderingServer::get_singleton()->viewport_attach_canvas(viewport, current_canvas);
+ RenderingServer::get_singleton()->viewport_set_canvas_transform(viewport, current_canvas, canvas_transform);
RenderingServer::get_singleton()->viewport_set_canvas_cull_mask(viewport, canvas_cull_mask);
_update_audio_listener_2d();
#ifndef _3D_DISABLED
@@ -491,6 +492,7 @@ void Viewport::_notification(int p_what) {
} break;
case NOTIFICATION_WM_WINDOW_FOCUS_OUT: {
+ _gui_cancel_tooltip();
_drop_physics_mouseover();
if (gui.mouse_focus && !gui.forced_mouse_focus) {
_drop_mouse_focus();
@@ -640,7 +642,7 @@ void Viewport::_process_picking() {
ObjectID canvas_layer_id;
if (E) {
// A descendant CanvasLayer.
- canvas_layer_transform = E->get_transform();
+ canvas_layer_transform = E->get_final_transform();
canvas_layer_id = E->get_instance_id();
} else {
// This Viewport's builtin canvas.
@@ -1623,7 +1625,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
Control *control = Object::cast_to<Control>(ci);
if (control) {
gui.dragging = true;
- gui.drag_data = control->get_drag_data(control->get_global_transform_with_canvas().affine_inverse().xform(mpos) - gui.drag_accum);
+ gui.drag_data = control->get_drag_data(control->get_global_transform_with_canvas().affine_inverse().xform(mpos - gui.drag_accum));
if (gui.drag_data.get_type() != Variant::NIL) {
gui.mouse_focus = nullptr;
gui.forced_mouse_focus = false;
@@ -1669,6 +1671,9 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
_gui_cancel_tooltip();
if (over) {
+ if (!gui.mouse_over) {
+ _drop_physics_mouseover();
+ }
_gui_call_notification(over, Control::NOTIFICATION_MOUSE_ENTER);
gui.mouse_over = over;
}
@@ -1875,9 +1880,11 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
Ref<InputEventScreenTouch> touch_event = p_event;
if (touch_event.is_valid()) {
Size2 pos = touch_event->get_position();
+ const int touch_index = touch_event->get_index();
if (touch_event->is_pressed()) {
Control *over = gui_find_control(pos);
if (over) {
+ gui.touch_focus[touch_index] = over->get_instance_id();
bool stopped = false;
if (over->can_process()) {
touch_event = touch_event->xformed_by(Transform2D()); // Make a copy.
@@ -1894,17 +1901,25 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
}
return;
}
- } else if (touch_event->get_index() == 0 && gui.last_mouse_focus) {
+ } else {
bool stopped = false;
- if (gui.last_mouse_focus->can_process()) {
+ ObjectID control_id = gui.touch_focus[touch_index];
+ Control *over = control_id.is_valid() ? Object::cast_to<Control>(ObjectDB::get_instance(control_id)) : nullptr;
+ if (over && over->can_process()) {
touch_event = touch_event->xformed_by(Transform2D()); // Make a copy.
- touch_event->set_position(gui.focus_inv_xform.xform(pos));
+ if (over == gui.last_mouse_focus) {
+ pos = gui.focus_inv_xform.xform(pos);
+ } else {
+ pos = over->get_global_transform_with_canvas().affine_inverse().xform(pos);
+ }
+ touch_event->set_position(pos);
- stopped = _gui_call_input(gui.last_mouse_focus, touch_event);
+ stopped = _gui_call_input(over, touch_event);
}
if (stopped) {
set_input_as_handled();
}
+ gui.touch_focus.erase(touch_index);
return;
}
}
@@ -1939,7 +1954,9 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
Ref<InputEventScreenDrag> drag_event = p_event;
if (drag_event.is_valid()) {
- Control *over = gui.mouse_focus;
+ const int drag_event_index = drag_event->get_index();
+ ObjectID control_id = gui.touch_focus[drag_event_index];
+ Control *over = control_id.is_valid() ? Object::cast_to<Control>(ObjectDB::get_instance(control_id)) : nullptr;
if (!over) {
over = gui_find_control(drag_event->get_position());
}
@@ -2092,7 +2109,7 @@ List<Control *>::Element *Viewport::_gui_add_root_control(Control *p_control) {
return gui.roots.push_back(p_control);
}
-void Viewport::_gui_set_root_order_dirty() {
+void Viewport::gui_set_root_order_dirty() {
gui.roots_order_dirty = true;
}
@@ -2660,6 +2677,11 @@ bool Viewport::_sub_windows_forward_input(const Ref<InputEvent> &p_event) {
} else {
gui.subwindow_resize_mode = _sub_window_get_resize_margin(sw.window, mb->get_position());
if (gui.subwindow_resize_mode != SUB_WINDOW_RESIZE_DISABLED) {
+ if (gui.subwindow_focused != sw.window) {
+ // Refocus.
+ _sub_window_grab_focus(sw.window);
+ }
+
gui.subwindow_resize_from_rect = r;
gui.subwindow_drag_from = mb->get_position();
gui.subwindow_drag = SUB_WINDOW_DRAG_RESIZE;
@@ -3039,8 +3061,6 @@ bool Viewport::gui_is_drag_successful() const {
}
void Viewport::set_input_as_handled() {
- _drop_physics_mouseover();
-
if (!handle_input_locally) {
ERR_FAIL_COND(!is_inside_tree());
Viewport *vp = this;
@@ -4159,7 +4179,7 @@ DisplayServer::WindowID SubViewport::get_window_id() const {
}
Transform2D SubViewport::_stretch_transform() {
- Transform2D transform = Transform2D();
+ Transform2D transform;
Size2i view_size_2d_override = _get_size_2d_override();
if (size_2d_override_stretch && view_size_2d_override.width > 0 && view_size_2d_override.height > 0) {
Size2 scale = Size2(_get_size()) / Size2(view_size_2d_override);
@@ -4170,7 +4190,7 @@ Transform2D SubViewport::_stretch_transform() {
}
Transform2D SubViewport::get_screen_transform() const {
- Transform2D container_transform = Transform2D();
+ Transform2D container_transform;
SubViewportContainer *c = Object::cast_to<SubViewportContainer>(get_parent());
if (c) {
if (c->is_stretch_enabled()) {
diff --git a/scene/main/viewport.h b/scene/main/viewport.h
index dc69ec24d8..bc8cd54603 100644
--- a/scene/main/viewport.h
+++ b/scene/main/viewport.h
@@ -354,6 +354,7 @@ private:
bool forced_mouse_focus = false; //used for menu buttons
bool mouse_in_viewport = true;
bool key_event_accepted = false;
+ HashMap<int, ObjectID> touch_focus;
Control *mouse_focus = nullptr;
Control *last_mouse_focus = nullptr;
Control *mouse_click_grabber = nullptr;
@@ -456,8 +457,6 @@ private:
void _update_canvas_items(Node *p_node);
- void _gui_set_root_order_dirty();
-
friend class Window;
void _sub_window_update_order();
@@ -514,6 +513,8 @@ public:
Transform2D get_final_transform() const;
+ void gui_set_root_order_dirty();
+
void set_transparent_background(bool p_enable);
bool has_transparent_background() const;
diff --git a/scene/main/window.cpp b/scene/main/window.cpp
index ebb11ecee8..c71c3e195b 100644
--- a/scene/main/window.cpp
+++ b/scene/main/window.cpp
@@ -40,6 +40,218 @@
#include "scene/theme/theme_db.h"
#include "scene/theme/theme_owner.h"
+// Dynamic properties.
+
+bool Window::_set(const StringName &p_name, const Variant &p_value) {
+ String name = p_name;
+ if (!name.begins_with("theme_override")) {
+ return false;
+ }
+
+ if (p_value.get_type() == Variant::NIL || (p_value.get_type() == Variant::OBJECT && (Object *)p_value == nullptr)) {
+ if (name.begins_with("theme_override_icons/")) {
+ String dname = name.get_slicec('/', 1);
+ if (theme_icon_override.has(dname)) {
+ theme_icon_override[dname]->disconnect("changed", callable_mp(this, &Window::_notify_theme_override_changed));
+ }
+ theme_icon_override.erase(dname);
+ _notify_theme_override_changed();
+ } else if (name.begins_with("theme_override_styles/")) {
+ String dname = name.get_slicec('/', 1);
+ if (theme_style_override.has(dname)) {
+ theme_style_override[dname]->disconnect("changed", callable_mp(this, &Window::_notify_theme_override_changed));
+ }
+ theme_style_override.erase(dname);
+ _notify_theme_override_changed();
+ } else if (name.begins_with("theme_override_fonts/")) {
+ String dname = name.get_slicec('/', 1);
+ if (theme_font_override.has(dname)) {
+ theme_font_override[dname]->disconnect("changed", callable_mp(this, &Window::_notify_theme_override_changed));
+ }
+ theme_font_override.erase(dname);
+ _notify_theme_override_changed();
+ } else if (name.begins_with("theme_override_font_sizes/")) {
+ String dname = name.get_slicec('/', 1);
+ theme_font_size_override.erase(dname);
+ _notify_theme_override_changed();
+ } else if (name.begins_with("theme_override_colors/")) {
+ String dname = name.get_slicec('/', 1);
+ theme_color_override.erase(dname);
+ _notify_theme_override_changed();
+ } else if (name.begins_with("theme_override_constants/")) {
+ String dname = name.get_slicec('/', 1);
+ theme_constant_override.erase(dname);
+ _notify_theme_override_changed();
+ } else {
+ return false;
+ }
+
+ } else {
+ if (name.begins_with("theme_override_icons/")) {
+ String dname = name.get_slicec('/', 1);
+ add_theme_icon_override(dname, p_value);
+ } else if (name.begins_with("theme_override_styles/")) {
+ String dname = name.get_slicec('/', 1);
+ add_theme_style_override(dname, p_value);
+ } else if (name.begins_with("theme_override_fonts/")) {
+ String dname = name.get_slicec('/', 1);
+ add_theme_font_override(dname, p_value);
+ } else if (name.begins_with("theme_override_font_sizes/")) {
+ String dname = name.get_slicec('/', 1);
+ add_theme_font_size_override(dname, p_value);
+ } else if (name.begins_with("theme_override_colors/")) {
+ String dname = name.get_slicec('/', 1);
+ add_theme_color_override(dname, p_value);
+ } else if (name.begins_with("theme_override_constants/")) {
+ String dname = name.get_slicec('/', 1);
+ add_theme_constant_override(dname, p_value);
+ } else {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool Window::_get(const StringName &p_name, Variant &r_ret) const {
+ String sname = p_name;
+ if (!sname.begins_with("theme_override")) {
+ return false;
+ }
+
+ if (sname.begins_with("theme_override_icons/")) {
+ String name = sname.get_slicec('/', 1);
+ r_ret = theme_icon_override.has(name) ? Variant(theme_icon_override[name]) : Variant();
+ } else if (sname.begins_with("theme_override_styles/")) {
+ String name = sname.get_slicec('/', 1);
+ r_ret = theme_style_override.has(name) ? Variant(theme_style_override[name]) : Variant();
+ } else if (sname.begins_with("theme_override_fonts/")) {
+ String name = sname.get_slicec('/', 1);
+ r_ret = theme_font_override.has(name) ? Variant(theme_font_override[name]) : Variant();
+ } else if (sname.begins_with("theme_override_font_sizes/")) {
+ String name = sname.get_slicec('/', 1);
+ r_ret = theme_font_size_override.has(name) ? Variant(theme_font_size_override[name]) : Variant();
+ } else if (sname.begins_with("theme_override_colors/")) {
+ String name = sname.get_slicec('/', 1);
+ r_ret = theme_color_override.has(name) ? Variant(theme_color_override[name]) : Variant();
+ } else if (sname.begins_with("theme_override_constants/")) {
+ String name = sname.get_slicec('/', 1);
+ r_ret = theme_constant_override.has(name) ? Variant(theme_constant_override[name]) : Variant();
+ } else {
+ return false;
+ }
+
+ return true;
+}
+
+void Window::_get_property_list(List<PropertyInfo> *p_list) const {
+ Ref<Theme> default_theme = ThemeDB::get_singleton()->get_default_theme();
+
+ p_list->push_back(PropertyInfo(Variant::NIL, TTRC("Theme Overrides"), PROPERTY_HINT_NONE, "theme_override_", PROPERTY_USAGE_GROUP));
+
+ {
+ List<StringName> names;
+ default_theme->get_color_list(get_class_name(), &names);
+ for (const StringName &E : names) {
+ uint32_t usage = PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_CHECKABLE;
+ if (theme_color_override.has(E)) {
+ usage |= PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_CHECKED;
+ }
+
+ p_list->push_back(PropertyInfo(Variant::COLOR, "theme_override_colors/" + E, PROPERTY_HINT_NONE, "", usage));
+ }
+ }
+ {
+ List<StringName> names;
+ default_theme->get_constant_list(get_class_name(), &names);
+ for (const StringName &E : names) {
+ uint32_t usage = PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_CHECKABLE;
+ if (theme_constant_override.has(E)) {
+ usage |= PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_CHECKED;
+ }
+
+ p_list->push_back(PropertyInfo(Variant::INT, "theme_override_constants/" + E, PROPERTY_HINT_RANGE, "-16384,16384", usage));
+ }
+ }
+ {
+ List<StringName> names;
+ default_theme->get_font_list(get_class_name(), &names);
+ for (const StringName &E : names) {
+ uint32_t usage = PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_CHECKABLE;
+ if (theme_font_override.has(E)) {
+ usage |= PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_CHECKED;
+ }
+
+ p_list->push_back(PropertyInfo(Variant::OBJECT, "theme_override_fonts/" + E, PROPERTY_HINT_RESOURCE_TYPE, "Font", usage));
+ }
+ }
+ {
+ List<StringName> names;
+ default_theme->get_font_size_list(get_class_name(), &names);
+ for (const StringName &E : names) {
+ uint32_t usage = PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_CHECKABLE;
+ if (theme_font_size_override.has(E)) {
+ usage |= PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_CHECKED;
+ }
+
+ p_list->push_back(PropertyInfo(Variant::INT, "theme_override_font_sizes/" + E, PROPERTY_HINT_RANGE, "1,256,1,or_greater,suffix:px", usage));
+ }
+ }
+ {
+ List<StringName> names;
+ default_theme->get_icon_list(get_class_name(), &names);
+ for (const StringName &E : names) {
+ uint32_t usage = PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_CHECKABLE;
+ if (theme_icon_override.has(E)) {
+ usage |= PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_CHECKED;
+ }
+
+ p_list->push_back(PropertyInfo(Variant::OBJECT, "theme_override_icons/" + E, PROPERTY_HINT_RESOURCE_TYPE, "Texture2D", usage));
+ }
+ }
+ {
+ List<StringName> names;
+ default_theme->get_stylebox_list(get_class_name(), &names);
+ for (const StringName &E : names) {
+ uint32_t usage = PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_CHECKABLE;
+ if (theme_style_override.has(E)) {
+ usage |= PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_CHECKED;
+ }
+
+ p_list->push_back(PropertyInfo(Variant::OBJECT, "theme_override_styles/" + E, PROPERTY_HINT_RESOURCE_TYPE, "StyleBox", usage));
+ }
+ }
+}
+
+void Window::_validate_property(PropertyInfo &p_property) const {
+ if (p_property.name == "theme_type_variation") {
+ List<StringName> names;
+
+ // Only the default theme and the project theme are used for the list of options.
+ // This is an imposed limitation to simplify the logic needed to leverage those options.
+ ThemeDB::get_singleton()->get_default_theme()->get_type_variation_list(get_class_name(), &names);
+ if (ThemeDB::get_singleton()->get_project_theme().is_valid()) {
+ ThemeDB::get_singleton()->get_project_theme()->get_type_variation_list(get_class_name(), &names);
+ }
+ names.sort_custom<StringName::AlphCompare>();
+
+ Vector<StringName> unique_names;
+ String hint_string;
+ for (const StringName &E : names) {
+ // Skip duplicate values.
+ if (unique_names.has(E)) {
+ continue;
+ }
+
+ hint_string += String(E) + ",";
+ unique_names.append(E);
+ }
+
+ p_property.hint_string = hint_string;
+ }
+}
+
+//
+
void Window::set_title(const String &p_title) {
title = p_title;
@@ -106,9 +318,16 @@ void Window::reset_size() {
set_size(Size2i());
}
-Size2i Window::get_real_size() const {
+Point2i Window::get_position_with_decorations() const {
+ if (window_id != DisplayServer::INVALID_WINDOW_ID) {
+ return DisplayServer::get_singleton()->window_get_position_with_decorations(window_id);
+ }
+ return position;
+}
+
+Size2i Window::get_size_with_decorations() const {
if (window_id != DisplayServer::INVALID_WINDOW_ID) {
- return DisplayServer::get_singleton()->window_get_real_size(window_id);
+ return DisplayServer::get_singleton()->window_get_size_with_decorations(window_id);
}
return size;
}
@@ -1316,6 +1535,8 @@ void Window::remove_child_notify(Node *p_child) {
}
}
+// Theming.
+
void Window::set_theme_owner_node(Node *p_node) {
theme_owner->set_owner_node(p_node);
}
@@ -1369,6 +1590,12 @@ void Window::_theme_changed() {
}
}
+void Window::_notify_theme_override_changed() {
+ if (!bulk_theme_override && is_inside_tree()) {
+ notification(NOTIFICATION_THEME_CHANGED);
+ }
+}
+
void Window::_invalidate_theme_cache() {
theme_icon_cache.clear();
theme_style_cache.clear();
@@ -1379,6 +1606,9 @@ void Window::_invalidate_theme_cache() {
}
void Window::_update_theme_item_cache() {
+ // Request an update on the next frame to reflect theme changes.
+ // Updating without a delay can cause a lot of lag.
+ child_controls_changed();
}
void Window::set_theme_type_variation(const StringName &p_theme_type) {
@@ -1392,7 +1622,16 @@ StringName Window::get_theme_type_variation() const {
return theme_type_variation;
}
+/// Theme property lookup.
+
Ref<Texture2D> Window::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 == theme_type_variation) {
+ const Ref<Texture2D> *tex = theme_icon_override.getptr(p_name);
+ if (tex) {
+ return *tex;
+ }
+ }
+
if (theme_icon_cache.has(p_theme_type) && theme_icon_cache[p_theme_type].has(p_name)) {
return theme_icon_cache[p_theme_type][p_name];
}
@@ -1405,6 +1644,13 @@ Ref<Texture2D> Window::get_theme_icon(const StringName &p_name, const StringName
}
Ref<StyleBox> Window::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 == theme_type_variation) {
+ const Ref<StyleBox> *style = theme_style_override.getptr(p_name);
+ if (style) {
+ return *style;
+ }
+ }
+
if (theme_style_cache.has(p_theme_type) && theme_style_cache[p_theme_type].has(p_name)) {
return theme_style_cache[p_theme_type][p_name];
}
@@ -1417,6 +1663,13 @@ Ref<StyleBox> Window::get_theme_stylebox(const StringName &p_name, const StringN
}
Ref<Font> Window::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 == theme_type_variation) {
+ const Ref<Font> *font = theme_font_override.getptr(p_name);
+ if (font) {
+ return *font;
+ }
+ }
+
if (theme_font_cache.has(p_theme_type) && theme_font_cache[p_theme_type].has(p_name)) {
return theme_font_cache[p_theme_type][p_name];
}
@@ -1429,6 +1682,13 @@ Ref<Font> Window::get_theme_font(const StringName &p_name, const StringName &p_t
}
int Window::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 == theme_type_variation) {
+ const int *font_size = theme_font_size_override.getptr(p_name);
+ if (font_size && (*font_size) > 0) {
+ return *font_size;
+ }
+ }
+
if (theme_font_size_cache.has(p_theme_type) && theme_font_size_cache[p_theme_type].has(p_name)) {
return theme_font_size_cache[p_theme_type][p_name];
}
@@ -1441,6 +1701,13 @@ int Window::get_theme_font_size(const StringName &p_name, const StringName &p_th
}
Color Window::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 == theme_type_variation) {
+ const Color *color = theme_color_override.getptr(p_name);
+ if (color) {
+ return *color;
+ }
+ }
+
if (theme_color_cache.has(p_theme_type) && theme_color_cache[p_theme_type].has(p_name)) {
return theme_color_cache[p_theme_type][p_name];
}
@@ -1453,6 +1720,13 @@ Color Window::get_theme_color(const StringName &p_name, const StringName &p_them
}
int Window::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 == theme_type_variation) {
+ const int *constant = theme_constant_override.getptr(p_name);
+ if (constant) {
+ return *constant;
+ }
+ }
+
if (theme_constant_cache.has(p_theme_type) && theme_constant_cache[p_theme_type].has(p_name)) {
return theme_constant_cache[p_theme_type][p_name];
}
@@ -1465,41 +1739,204 @@ int Window::get_theme_constant(const StringName &p_name, const StringName &p_the
}
bool Window::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 == theme_type_variation) {
+ if (has_theme_icon_override(p_name)) {
+ return true;
+ }
+ }
+
List<StringName> theme_types;
theme_owner->get_theme_type_dependencies(this, p_theme_type, &theme_types);
return theme_owner->has_theme_item_in_types(Theme::DATA_TYPE_ICON, p_name, theme_types);
}
bool Window::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 == theme_type_variation) {
+ if (has_theme_stylebox_override(p_name)) {
+ return true;
+ }
+ }
+
List<StringName> theme_types;
theme_owner->get_theme_type_dependencies(this, p_theme_type, &theme_types);
return theme_owner->has_theme_item_in_types(Theme::DATA_TYPE_STYLEBOX, p_name, theme_types);
}
bool Window::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 == theme_type_variation) {
+ if (has_theme_font_override(p_name)) {
+ return true;
+ }
+ }
+
List<StringName> theme_types;
theme_owner->get_theme_type_dependencies(this, p_theme_type, &theme_types);
return theme_owner->has_theme_item_in_types(Theme::DATA_TYPE_FONT, p_name, theme_types);
}
bool Window::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 == theme_type_variation) {
+ if (has_theme_font_size_override(p_name)) {
+ return true;
+ }
+ }
+
List<StringName> theme_types;
theme_owner->get_theme_type_dependencies(this, p_theme_type, &theme_types);
return theme_owner->has_theme_item_in_types(Theme::DATA_TYPE_FONT_SIZE, p_name, theme_types);
}
bool Window::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 == theme_type_variation) {
+ if (has_theme_color_override(p_name)) {
+ return true;
+ }
+ }
+
List<StringName> theme_types;
theme_owner->get_theme_type_dependencies(this, p_theme_type, &theme_types);
return theme_owner->has_theme_item_in_types(Theme::DATA_TYPE_COLOR, p_name, theme_types);
}
bool Window::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 == theme_type_variation) {
+ if (has_theme_constant_override(p_name)) {
+ return true;
+ }
+ }
+
List<StringName> theme_types;
theme_owner->get_theme_type_dependencies(this, p_theme_type, &theme_types);
return theme_owner->has_theme_item_in_types(Theme::DATA_TYPE_CONSTANT, p_name, theme_types);
}
+/// Local property overrides.
+
+void Window::add_theme_icon_override(const StringName &p_name, const Ref<Texture2D> &p_icon) {
+ ERR_FAIL_COND(!p_icon.is_valid());
+
+ if (theme_icon_override.has(p_name)) {
+ theme_icon_override[p_name]->disconnect("changed", callable_mp(this, &Window::_notify_theme_override_changed));
+ }
+
+ theme_icon_override[p_name] = p_icon;
+ theme_icon_override[p_name]->connect("changed", callable_mp(this, &Window::_notify_theme_override_changed), CONNECT_REFERENCE_COUNTED);
+ _notify_theme_override_changed();
+}
+
+void Window::add_theme_style_override(const StringName &p_name, const Ref<StyleBox> &p_style) {
+ ERR_FAIL_COND(!p_style.is_valid());
+
+ if (theme_style_override.has(p_name)) {
+ theme_style_override[p_name]->disconnect("changed", callable_mp(this, &Window::_notify_theme_override_changed));
+ }
+
+ theme_style_override[p_name] = p_style;
+ theme_style_override[p_name]->connect("changed", callable_mp(this, &Window::_notify_theme_override_changed), CONNECT_REFERENCE_COUNTED);
+ _notify_theme_override_changed();
+}
+
+void Window::add_theme_font_override(const StringName &p_name, const Ref<Font> &p_font) {
+ ERR_FAIL_COND(!p_font.is_valid());
+
+ if (theme_font_override.has(p_name)) {
+ theme_font_override[p_name]->disconnect("changed", callable_mp(this, &Window::_notify_theme_override_changed));
+ }
+
+ theme_font_override[p_name] = p_font;
+ theme_font_override[p_name]->connect("changed", callable_mp(this, &Window::_notify_theme_override_changed), CONNECT_REFERENCE_COUNTED);
+ _notify_theme_override_changed();
+}
+
+void Window::add_theme_font_size_override(const StringName &p_name, int p_font_size) {
+ theme_font_size_override[p_name] = p_font_size;
+ _notify_theme_override_changed();
+}
+
+void Window::add_theme_color_override(const StringName &p_name, const Color &p_color) {
+ theme_color_override[p_name] = p_color;
+ _notify_theme_override_changed();
+}
+
+void Window::add_theme_constant_override(const StringName &p_name, int p_constant) {
+ theme_constant_override[p_name] = p_constant;
+ _notify_theme_override_changed();
+}
+
+void Window::remove_theme_icon_override(const StringName &p_name) {
+ if (theme_icon_override.has(p_name)) {
+ theme_icon_override[p_name]->disconnect("changed", callable_mp(this, &Window::_notify_theme_override_changed));
+ }
+
+ theme_icon_override.erase(p_name);
+ _notify_theme_override_changed();
+}
+
+void Window::remove_theme_style_override(const StringName &p_name) {
+ if (theme_style_override.has(p_name)) {
+ theme_style_override[p_name]->disconnect("changed", callable_mp(this, &Window::_notify_theme_override_changed));
+ }
+
+ theme_style_override.erase(p_name);
+ _notify_theme_override_changed();
+}
+
+void Window::remove_theme_font_override(const StringName &p_name) {
+ if (theme_font_override.has(p_name)) {
+ theme_font_override[p_name]->disconnect("changed", callable_mp(this, &Window::_notify_theme_override_changed));
+ }
+
+ theme_font_override.erase(p_name);
+ _notify_theme_override_changed();
+}
+
+void Window::remove_theme_font_size_override(const StringName &p_name) {
+ theme_font_size_override.erase(p_name);
+ _notify_theme_override_changed();
+}
+
+void Window::remove_theme_color_override(const StringName &p_name) {
+ theme_color_override.erase(p_name);
+ _notify_theme_override_changed();
+}
+
+void Window::remove_theme_constant_override(const StringName &p_name) {
+ theme_constant_override.erase(p_name);
+ _notify_theme_override_changed();
+}
+
+bool Window::has_theme_icon_override(const StringName &p_name) const {
+ const Ref<Texture2D> *tex = theme_icon_override.getptr(p_name);
+ return tex != nullptr;
+}
+
+bool Window::has_theme_stylebox_override(const StringName &p_name) const {
+ const Ref<StyleBox> *style = theme_style_override.getptr(p_name);
+ return style != nullptr;
+}
+
+bool Window::has_theme_font_override(const StringName &p_name) const {
+ const Ref<Font> *font = theme_font_override.getptr(p_name);
+ return font != nullptr;
+}
+
+bool Window::has_theme_font_size_override(const StringName &p_name) const {
+ const int *font_size = theme_font_size_override.getptr(p_name);
+ return font_size != nullptr;
+}
+
+bool Window::has_theme_color_override(const StringName &p_name) const {
+ const Color *color = theme_color_override.getptr(p_name);
+ return color != nullptr;
+}
+
+bool Window::has_theme_constant_override(const StringName &p_name) const {
+ const int *constant = theme_constant_override.getptr(p_name);
+ return constant != nullptr;
+}
+
+/// Default theme properties.
+
float Window::get_theme_default_base_scale() const {
return theme_owner->get_theme_default_base_scale();
}
@@ -1512,6 +1949,21 @@ int Window::get_theme_default_font_size() const {
return theme_owner->get_theme_default_font_size();
}
+/// Bulk actions.
+
+void Window::begin_bulk_theme_override() {
+ bulk_theme_override = true;
+}
+
+void Window::end_bulk_theme_override() {
+ ERR_FAIL_COND(!bulk_theme_override);
+
+ bulk_theme_override = false;
+ _notify_theme_override_changed();
+}
+
+//
+
Rect2i Window::get_parent_rect() const {
ERR_FAIL_COND_V(!is_inside_tree(), Rect2i());
if (is_embedded()) {
@@ -1604,36 +2056,8 @@ bool Window::is_auto_translating() const {
return auto_translate;
}
-void Window::_validate_property(PropertyInfo &p_property) const {
- if (p_property.name == "theme_type_variation") {
- List<StringName> names;
-
- // Only the default theme and the project theme are used for the list of options.
- // This is an imposed limitation to simplify the logic needed to leverage those options.
- ThemeDB::get_singleton()->get_default_theme()->get_type_variation_list(get_class_name(), &names);
- if (ThemeDB::get_singleton()->get_project_theme().is_valid()) {
- ThemeDB::get_singleton()->get_project_theme()->get_type_variation_list(get_class_name(), &names);
- }
- names.sort_custom<StringName::AlphCompare>();
-
- Vector<StringName> unique_names;
- String hint_string;
- for (const StringName &E : names) {
- // Skip duplicate values.
- if (unique_names.has(E)) {
- continue;
- }
-
- hint_string += String(E) + ",";
- unique_names.append(E);
- }
-
- p_property.hint_string = hint_string;
- }
-}
-
Transform2D Window::get_screen_transform() const {
- Transform2D embedder_transform = Transform2D();
+ Transform2D embedder_transform;
if (_get_embedder()) {
embedder_transform.translate_local(get_position());
embedder_transform = _get_embedder()->get_screen_transform() * embedder_transform;
@@ -1655,7 +2079,8 @@ void Window::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_size"), &Window::get_size);
ClassDB::bind_method(D_METHOD("reset_size"), &Window::reset_size);
- ClassDB::bind_method(D_METHOD("get_real_size"), &Window::get_real_size);
+ ClassDB::bind_method(D_METHOD("get_position_with_decorations"), &Window::get_position_with_decorations);
+ ClassDB::bind_method(D_METHOD("get_size_with_decorations"), &Window::get_size_with_decorations);
ClassDB::bind_method(D_METHOD("set_max_size", "max_size"), &Window::set_max_size);
ClassDB::bind_method(D_METHOD("get_max_size"), &Window::get_max_size);
@@ -1725,6 +2150,23 @@ void Window::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_theme_type_variation", "theme_type"), &Window::set_theme_type_variation);
ClassDB::bind_method(D_METHOD("get_theme_type_variation"), &Window::get_theme_type_variation);
+ ClassDB::bind_method(D_METHOD("begin_bulk_theme_override"), &Window::begin_bulk_theme_override);
+ ClassDB::bind_method(D_METHOD("end_bulk_theme_override"), &Window::end_bulk_theme_override);
+
+ ClassDB::bind_method(D_METHOD("add_theme_icon_override", "name", "texture"), &Window::add_theme_icon_override);
+ ClassDB::bind_method(D_METHOD("add_theme_stylebox_override", "name", "stylebox"), &Window::add_theme_style_override);
+ ClassDB::bind_method(D_METHOD("add_theme_font_override", "name", "font"), &Window::add_theme_font_override);
+ ClassDB::bind_method(D_METHOD("add_theme_font_size_override", "name", "font_size"), &Window::add_theme_font_size_override);
+ ClassDB::bind_method(D_METHOD("add_theme_color_override", "name", "color"), &Window::add_theme_color_override);
+ ClassDB::bind_method(D_METHOD("add_theme_constant_override", "name", "constant"), &Window::add_theme_constant_override);
+
+ ClassDB::bind_method(D_METHOD("remove_theme_icon_override", "name"), &Window::remove_theme_icon_override);
+ ClassDB::bind_method(D_METHOD("remove_theme_stylebox_override", "name"), &Window::remove_theme_style_override);
+ ClassDB::bind_method(D_METHOD("remove_theme_font_override", "name"), &Window::remove_theme_font_override);
+ ClassDB::bind_method(D_METHOD("remove_theme_font_size_override", "name"), &Window::remove_theme_font_size_override);
+ ClassDB::bind_method(D_METHOD("remove_theme_color_override", "name"), &Window::remove_theme_color_override);
+ ClassDB::bind_method(D_METHOD("remove_theme_constant_override", "name"), &Window::remove_theme_constant_override);
+
ClassDB::bind_method(D_METHOD("get_theme_icon", "name", "theme_type"), &Window::get_theme_icon, DEFVAL(""));
ClassDB::bind_method(D_METHOD("get_theme_stylebox", "name", "theme_type"), &Window::get_theme_stylebox, DEFVAL(""));
ClassDB::bind_method(D_METHOD("get_theme_font", "name", "theme_type"), &Window::get_theme_font, DEFVAL(""));
@@ -1732,6 +2174,13 @@ void Window::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_theme_color", "name", "theme_type"), &Window::get_theme_color, DEFVAL(""));
ClassDB::bind_method(D_METHOD("get_theme_constant", "name", "theme_type"), &Window::get_theme_constant, DEFVAL(""));
+ ClassDB::bind_method(D_METHOD("has_theme_icon_override", "name"), &Window::has_theme_icon_override);
+ ClassDB::bind_method(D_METHOD("has_theme_stylebox_override", "name"), &Window::has_theme_stylebox_override);
+ ClassDB::bind_method(D_METHOD("has_theme_font_override", "name"), &Window::has_theme_font_override);
+ ClassDB::bind_method(D_METHOD("has_theme_font_size_override", "name"), &Window::has_theme_font_size_override);
+ ClassDB::bind_method(D_METHOD("has_theme_color_override", "name"), &Window::has_theme_color_override);
+ ClassDB::bind_method(D_METHOD("has_theme_constant_override", "name"), &Window::has_theme_constant_override);
+
ClassDB::bind_method(D_METHOD("has_theme_icon", "name", "theme_type"), &Window::has_theme_icon, DEFVAL(""));
ClassDB::bind_method(D_METHOD("has_theme_stylebox", "name", "theme_type"), &Window::has_theme_stylebox, DEFVAL(""));
ClassDB::bind_method(D_METHOD("has_theme_font", "name", "theme_type"), &Window::has_theme_font, DEFVAL(""));
@@ -1785,13 +2234,13 @@ void Window::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "content_scale_aspect", PROPERTY_HINT_ENUM, "Ignore,Keep,Keep Width,Keep Height,Expand"), "set_content_scale_aspect", "get_content_scale_aspect");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "content_scale_factor"), "set_content_scale_factor", "get_content_scale_factor");
+ ADD_GROUP("Localization", "");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "auto_translate"), "set_auto_translate", "is_auto_translating");
+
ADD_GROUP("Theme", "theme_");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "theme", PROPERTY_HINT_RESOURCE_TYPE, "Theme"), "set_theme", "get_theme");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "theme_type_variation", PROPERTY_HINT_ENUM_SUGGESTION), "set_theme_type_variation", "get_theme_type_variation");
- ADD_GROUP("Auto Translate", "");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "auto_translate"), "set_auto_translate", "is_auto_translating");
-
ADD_SIGNAL(MethodInfo("window_input", PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent")));
ADD_SIGNAL(MethodInfo("files_dropped", PropertyInfo(Variant::PACKED_STRING_ARRAY, "files")));
ADD_SIGNAL(MethodInfo("mouse_entered"));
@@ -1851,4 +2300,23 @@ Window::Window() {
Window::~Window() {
memdelete(theme_owner);
+
+ // Resources need to be disconnected.
+ for (KeyValue<StringName, Ref<Texture2D>> &E : theme_icon_override) {
+ E.value->disconnect("changed", callable_mp(this, &Window::_notify_theme_override_changed));
+ }
+ for (KeyValue<StringName, Ref<StyleBox>> &E : theme_style_override) {
+ E.value->disconnect("changed", callable_mp(this, &Window::_notify_theme_override_changed));
+ }
+ for (KeyValue<StringName, Ref<Font>> &E : theme_font_override) {
+ E.value->disconnect("changed", callable_mp(this, &Window::_notify_theme_override_changed));
+ }
+
+ // Then override maps can be simply cleared.
+ theme_icon_override.clear();
+ theme_style_override.clear();
+ theme_font_override.clear();
+ theme_font_size_override.clear();
+ theme_color_override.clear();
+ theme_constant_override.clear();
}
diff --git a/scene/main/window.h b/scene/main/window.h
index 03597b309a..5024b42587 100644
--- a/scene/main/window.h
+++ b/scene/main/window.h
@@ -140,6 +140,14 @@ private:
Ref<Theme> theme;
StringName theme_type_variation;
+ bool bulk_theme_override = false;
+ Theme::ThemeIconMap theme_icon_override;
+ Theme::ThemeStyleMap theme_style_override;
+ Theme::ThemeFontMap theme_font_override;
+ Theme::ThemeFontSizeMap theme_font_size_override;
+ Theme::ThemeColorMap theme_color_override;
+ Theme::ThemeConstantMap theme_constant_override;
+
mutable HashMap<StringName, Theme::ThemeIconMap> theme_icon_cache;
mutable HashMap<StringName, Theme::ThemeStyleMap> theme_style_cache;
mutable HashMap<StringName, Theme::ThemeFontMap> theme_font_cache;
@@ -148,6 +156,7 @@ private:
mutable HashMap<StringName, Theme::ThemeConstantMap> theme_constant_cache;
void _theme_changed();
+ void _notify_theme_override_changed();
void _invalidate_theme_cache();
Viewport *embedder = nullptr;
@@ -173,6 +182,10 @@ protected:
virtual Size2 _get_contents_minimum_size() const;
static void _bind_methods();
void _notification(int p_what);
+
+ 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 &p_property) const;
virtual void add_child_notify(Node *p_child) override;
@@ -198,7 +211,8 @@ public:
Size2i get_size() const;
void reset_size();
- Size2i get_real_size() const;
+ Point2i get_position_with_decorations() const;
+ Size2i get_size_with_decorations() const;
void set_max_size(const Size2i &p_max_size);
Size2i get_max_size() const;
@@ -270,16 +284,6 @@ public:
void popup_centered(const Size2i &p_minsize = Size2i());
void popup_centered_clamped(const Size2i &p_size = Size2i(), float p_fallback_ratio = 0.75);
- void set_theme_owner_node(Node *p_node);
- Node *get_theme_owner_node() const;
- bool has_theme_owner_node() const;
-
- 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;
-
Size2 get_contents_minimum_size() const;
void grab_focus();
@@ -295,6 +299,35 @@ public:
Rect2i get_usable_parent_rect() const;
+ // Theming.
+
+ void set_theme_owner_node(Node *p_node);
+ Node *get_theme_owner_node() const;
+ bool has_theme_owner_node() const;
+
+ 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();
+
+ void add_theme_icon_override(const StringName &p_name, const Ref<Texture2D> &p_icon);
+ void add_theme_style_override(const StringName &p_name, const Ref<StyleBox> &p_style);
+ void add_theme_font_override(const StringName &p_name, const Ref<Font> &p_font);
+ void add_theme_font_size_override(const StringName &p_name, int p_font_size);
+ void add_theme_color_override(const StringName &p_name, const Color &p_color);
+ void add_theme_constant_override(const StringName &p_name, int p_constant);
+
+ void remove_theme_icon_override(const StringName &p_name);
+ void remove_theme_style_override(const StringName &p_name);
+ void remove_theme_font_override(const StringName &p_name);
+ void remove_theme_font_size_override(const StringName &p_name);
+ void remove_theme_color_override(const StringName &p_name);
+ void remove_theme_constant_override(const StringName &p_name);
+
Ref<Texture2D> get_theme_icon(const StringName &p_name, const StringName &p_theme_type = StringName()) const;
Ref<StyleBox> get_theme_stylebox(const StringName &p_name, const StringName &p_theme_type = StringName()) const;
Ref<Font> get_theme_font(const StringName &p_name, const StringName &p_theme_type = StringName()) const;
@@ -302,6 +335,13 @@ public:
Color get_theme_color(const StringName &p_name, const StringName &p_theme_type = StringName()) const;
int get_theme_constant(const StringName &p_name, const StringName &p_theme_type = StringName()) const;
+ bool has_theme_icon_override(const StringName &p_name) const;
+ bool has_theme_stylebox_override(const StringName &p_name) const;
+ bool has_theme_font_override(const StringName &p_name) const;
+ bool has_theme_font_size_override(const StringName &p_name) const;
+ bool has_theme_color_override(const StringName &p_name) const;
+ bool has_theme_constant_override(const StringName &p_name) const;
+
bool has_theme_icon(const StringName &p_name, const StringName &p_theme_type = StringName()) const;
bool has_theme_stylebox(const StringName &p_name, const StringName &p_theme_type = StringName()) const;
bool has_theme_font(const StringName &p_name, const StringName &p_theme_type = StringName()) const;
@@ -313,6 +353,8 @@ public:
Ref<Font> get_theme_default_font() const;
int get_theme_default_font_size() const;
+ //
+
virtual Transform2D get_screen_transform() const override;
Rect2i get_parent_rect() const;
diff --git a/scene/property_utils.h b/scene/property_utils.h
index 5ada35fdd7..5b0200b491 100644
--- a/scene/property_utils.h
+++ b/scene/property_utils.h
@@ -42,7 +42,7 @@ public:
// Gets the instance/inheritance states of this node, in order of precedence,
// that is, from the topmost (the most able to override values) to the lowermost
- // (Note that in nested instancing the one with the greatest precedence is the furthest
+ // (Note that in nested instantiation, the one with the greatest precedence is the furthest
// in the tree, since every owner found while traversing towards the root gets a chance
// to override property values.)
static Vector<SceneState::PackState> get_node_states_stack(const Node *p_node, const Node *p_owner = nullptr, bool *r_instantiated_by_owner = nullptr);
diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp
index 0f55c7b3b8..4f300cb5d6 100644
--- a/scene/register_scene_types.cpp
+++ b/scene/register_scene_types.cpp
@@ -31,7 +31,7 @@
#include "register_scene_types.h"
#include "core/config/project_settings.h"
-#include "core/extension/native_extension_manager.h"
+#include "core/extension/gdextension_manager.h"
#include "core/object/class_db.h"
#include "core/os/os.h"
#include "scene/2d/animated_sprite_2d.h"
@@ -56,6 +56,7 @@
#include "scene/2d/navigation_agent_2d.h"
#include "scene/2d/navigation_link_2d.h"
#include "scene/2d/navigation_obstacle_2d.h"
+#include "scene/2d/navigation_region_2d.h"
#include "scene/2d/parallax_background.h"
#include "scene/2d/parallax_layer.h"
#include "scene/2d/path_2d.h"
@@ -163,6 +164,7 @@
#include "scene/resources/mesh_data_tool.h"
#include "scene/resources/multimesh.h"
#include "scene/resources/navigation_mesh.h"
+#include "scene/resources/navigation_polygon.h"
#include "scene/resources/packed_scene.h"
#include "scene/resources/particle_process_material.h"
#include "scene/resources/physics_material.h"
@@ -827,14 +829,14 @@ void register_scene_types() {
GDREGISTER_CLASS(ConvexPolygonShape3D);
GDREGISTER_CLASS(ConcavePolygonShape3D);
- ClassDB::register_class<SkeletonModificationStack3D>();
- ClassDB::register_class<SkeletonModification3D>();
- ClassDB::register_class<SkeletonModification3DLookAt>();
- ClassDB::register_class<SkeletonModification3DCCDIK>();
- ClassDB::register_class<SkeletonModification3DFABRIK>();
- ClassDB::register_class<SkeletonModification3DJiggle>();
- ClassDB::register_class<SkeletonModification3DTwoBoneIK>();
- ClassDB::register_class<SkeletonModification3DStackHolder>();
+ GDREGISTER_CLASS(SkeletonModificationStack3D);
+ GDREGISTER_CLASS(SkeletonModification3D);
+ GDREGISTER_CLASS(SkeletonModification3DLookAt);
+ GDREGISTER_CLASS(SkeletonModification3DCCDIK);
+ GDREGISTER_CLASS(SkeletonModification3DFABRIK);
+ GDREGISTER_CLASS(SkeletonModification3DJiggle);
+ GDREGISTER_CLASS(SkeletonModification3DTwoBoneIK);
+ GDREGISTER_CLASS(SkeletonModification3DStackHolder);
OS::get_singleton()->yield(); // may take time to init
#endif // _3D_DISABLED
@@ -960,6 +962,7 @@ void register_scene_types() {
ClassDB::add_compatibility_class("Navigation3D", "Node3D");
ClassDB::add_compatibility_class("Navigation2D", "Node2D");
ClassDB::add_compatibility_class("OpenSimplexNoise", "FastNoiseLite");
+ ClassDB::add_compatibility_class("ProximityGroup", "Node3D");
ClassDB::add_compatibility_class("ToolButton", "Button");
ClassDB::add_compatibility_class("YSort", "Node2D");
// Portal and room occlusion was replaced by raster occlusion (OccluderInstance3D node).
diff --git a/scene/resources/animation.cpp b/scene/resources/animation.cpp
index 1eb78f0160..37407edc33 100644
--- a/scene/resources/animation.cpp
+++ b/scene/resources/animation.cpp
@@ -888,7 +888,6 @@ int Animation::add_track(TrackType p_type, int p_at_pos) {
}
}
emit_changed();
- emit_signal(SceneStringNames::get_singleton()->tracks_changed);
return p_at_pos;
}
@@ -951,7 +950,6 @@ void Animation::remove_track(int p_track) {
memdelete(t);
tracks.remove_at(p_track);
emit_changed();
- emit_signal(SceneStringNames::get_singleton()->tracks_changed);
}
int Animation::get_track_count() const {
@@ -967,7 +965,6 @@ void Animation::track_set_path(int p_track, const NodePath &p_path) {
ERR_FAIL_INDEX(p_track, tracks.size());
tracks[p_track]->path = p_path;
emit_changed();
- emit_signal(SceneStringNames::get_singleton()->tracks_changed);
}
NodePath Animation::track_get_path(int p_track) const {
@@ -1322,7 +1319,7 @@ Error Animation::blend_shape_track_interpolate(int p_track, double p_time, float
}
void Animation::track_remove_key_at_time(int p_track, double p_time) {
- int idx = track_find_key(p_track, p_time, true);
+ int idx = track_find_key(p_track, p_time, FIND_MODE_APPROX);
ERR_FAIL_COND(idx < 0);
track_remove_key(p_track, idx);
}
@@ -1403,7 +1400,7 @@ void Animation::track_remove_key(int p_track, int p_idx) {
emit_changed();
}
-int Animation::track_find_key(int p_track, double p_time, bool p_exact) const {
+int Animation::track_find_key(int p_track, double p_time, FindMode p_find_mode) const {
ERR_FAIL_INDEX_V(p_track, tracks.size(), -1);
Track *t = tracks[p_track];
@@ -1419,7 +1416,7 @@ int Animation::track_find_key(int p_track, double p_time, bool p_exact) const {
uint32_t key_index;
bool fetch_compressed_success = _fetch_compressed<3>(tt->compressed_track, p_time, key, time, key_next, time_next, &key_index);
ERR_FAIL_COND_V(!fetch_compressed_success, -1);
- if (p_exact && time != p_time) {
+ if ((p_find_mode == FIND_MODE_APPROX && !Math::is_equal_approx(time, p_time)) || (p_find_mode == FIND_MODE_EXACT && time != p_time)) {
return -1;
}
return key_index;
@@ -1429,7 +1426,7 @@ int Animation::track_find_key(int p_track, double p_time, bool p_exact) const {
if (k < 0 || k >= tt->positions.size()) {
return -1;
}
- if (tt->positions[k].time != p_time && p_exact) {
+ if ((p_find_mode == FIND_MODE_APPROX && !Math::is_equal_approx(tt->positions[k].time, p_time)) || (p_find_mode == FIND_MODE_EXACT && tt->positions[k].time != p_time)) {
return -1;
}
return k;
@@ -1446,7 +1443,7 @@ int Animation::track_find_key(int p_track, double p_time, bool p_exact) const {
uint32_t key_index;
bool fetch_compressed_success = _fetch_compressed<3>(rt->compressed_track, p_time, key, time, key_next, time_next, &key_index);
ERR_FAIL_COND_V(!fetch_compressed_success, -1);
- if (p_exact && time != p_time) {
+ if ((p_find_mode == FIND_MODE_APPROX && !Math::is_equal_approx(time, p_time)) || (p_find_mode == FIND_MODE_EXACT && time != p_time)) {
return -1;
}
return key_index;
@@ -1456,7 +1453,7 @@ int Animation::track_find_key(int p_track, double p_time, bool p_exact) const {
if (k < 0 || k >= rt->rotations.size()) {
return -1;
}
- if (rt->rotations[k].time != p_time && p_exact) {
+ if ((p_find_mode == FIND_MODE_APPROX && !Math::is_equal_approx(rt->rotations[k].time, p_time)) || (p_find_mode == FIND_MODE_EXACT && rt->rotations[k].time != p_time)) {
return -1;
}
return k;
@@ -1473,7 +1470,7 @@ int Animation::track_find_key(int p_track, double p_time, bool p_exact) const {
uint32_t key_index;
bool fetch_compressed_success = _fetch_compressed<3>(st->compressed_track, p_time, key, time, key_next, time_next, &key_index);
ERR_FAIL_COND_V(!fetch_compressed_success, -1);
- if (p_exact && time != p_time) {
+ if ((p_find_mode == FIND_MODE_APPROX && !Math::is_equal_approx(time, p_time)) || (p_find_mode == FIND_MODE_EXACT && time != p_time)) {
return -1;
}
return key_index;
@@ -1483,7 +1480,7 @@ int Animation::track_find_key(int p_track, double p_time, bool p_exact) const {
if (k < 0 || k >= st->scales.size()) {
return -1;
}
- if (st->scales[k].time != p_time && p_exact) {
+ if ((p_find_mode == FIND_MODE_APPROX && !Math::is_equal_approx(st->scales[k].time, p_time)) || (p_find_mode == FIND_MODE_EXACT && st->scales[k].time != p_time)) {
return -1;
}
return k;
@@ -1500,7 +1497,7 @@ int Animation::track_find_key(int p_track, double p_time, bool p_exact) const {
uint32_t key_index;
bool fetch_compressed_success = _fetch_compressed<1>(bst->compressed_track, p_time, key, time, key_next, time_next, &key_index);
ERR_FAIL_COND_V(!fetch_compressed_success, -1);
- if (p_exact && time != p_time) {
+ if ((p_find_mode == FIND_MODE_APPROX && !Math::is_equal_approx(time, p_time)) || (p_find_mode == FIND_MODE_EXACT && time != p_time)) {
return -1;
}
return key_index;
@@ -1510,7 +1507,7 @@ int Animation::track_find_key(int p_track, double p_time, bool p_exact) const {
if (k < 0 || k >= bst->blend_shapes.size()) {
return -1;
}
- if (bst->blend_shapes[k].time != p_time && p_exact) {
+ if ((p_find_mode == FIND_MODE_APPROX && !Math::is_equal_approx(bst->blend_shapes[k].time, p_time)) || (p_find_mode == FIND_MODE_EXACT && bst->blend_shapes[k].time != p_time)) {
return -1;
}
return k;
@@ -1522,7 +1519,7 @@ int Animation::track_find_key(int p_track, double p_time, bool p_exact) const {
if (k < 0 || k >= vt->values.size()) {
return -1;
}
- if (vt->values[k].time != p_time && p_exact) {
+ if ((p_find_mode == FIND_MODE_APPROX && !Math::is_equal_approx(vt->values[k].time, p_time)) || (p_find_mode == FIND_MODE_EXACT && vt->values[k].time != p_time)) {
return -1;
}
return k;
@@ -1534,7 +1531,7 @@ int Animation::track_find_key(int p_track, double p_time, bool p_exact) const {
if (k < 0 || k >= mt->methods.size()) {
return -1;
}
- if (mt->methods[k].time != p_time && p_exact) {
+ if ((p_find_mode == FIND_MODE_APPROX && !Math::is_equal_approx(mt->methods[k].time, p_time)) || (p_find_mode == FIND_MODE_EXACT && mt->methods[k].time != p_time)) {
return -1;
}
return k;
@@ -1546,7 +1543,7 @@ int Animation::track_find_key(int p_track, double p_time, bool p_exact) const {
if (k < 0 || k >= bt->values.size()) {
return -1;
}
- if (bt->values[k].time != p_time && p_exact) {
+ if ((p_find_mode == FIND_MODE_APPROX && !Math::is_equal_approx(bt->values[k].time, p_time)) || (p_find_mode == FIND_MODE_EXACT && bt->values[k].time != p_time)) {
return -1;
}
return k;
@@ -1558,7 +1555,7 @@ int Animation::track_find_key(int p_track, double p_time, bool p_exact) const {
if (k < 0 || k >= at->values.size()) {
return -1;
}
- if (at->values[k].time != p_time && p_exact) {
+ if ((p_find_mode == FIND_MODE_APPROX && !Math::is_equal_approx(at->values[k].time, p_time)) || (p_find_mode == FIND_MODE_EXACT && at->values[k].time != p_time)) {
return -1;
}
return k;
@@ -1570,7 +1567,7 @@ int Animation::track_find_key(int p_track, double p_time, bool p_exact) const {
if (k < 0 || k >= at->values.size()) {
return -1;
}
- if (at->values[k].time != p_time && p_exact) {
+ if ((p_find_mode == FIND_MODE_APPROX && !Math::is_equal_approx(at->values[k].time, p_time)) || (p_find_mode == FIND_MODE_EXACT && at->values[k].time != p_time)) {
return -1;
}
return k;
@@ -2467,7 +2464,6 @@ T Animation::_interpolate(const Vector<TKey<T>> &p_keys, double p_time, Interpol
ERR_FAIL_COND_V(idx == -2, T());
- bool result = true;
int next = 0;
real_t c = 0.0;
// prepare for all cases of interpolation
@@ -2599,10 +2595,7 @@ T Animation::_interpolate(const Vector<TKey<T>> &p_keys, double p_time, Interpol
}
if (p_ok) {
- *p_ok = result;
- }
- if (!result) {
- return T();
+ *p_ok = true;
}
real_t tr = p_keys[idx].transition;
@@ -2712,111 +2705,11 @@ Variant Animation::value_track_interpolate(int p_track, double p_time) const {
return Variant();
}
-void Animation::_value_track_get_key_indices_in_range(const ValueTrack *vt, double from_time, double to_time, List<int> *p_indices) const {
- if (from_time != length && to_time == length) {
- to_time = length + CMP_EPSILON; //include a little more if at the end
- }
- int to = _find(vt->values, to_time);
-
- if (to >= 0 && from_time == to_time && vt->values[to].time == from_time) {
- //find exact (0 delta), return if found
- p_indices->push_back(to);
- return;
- }
- // can't really send the events == time, will be sent in the next frame.
- // if event>=len then it will probably never be requested by the anim player.
-
- if (to >= 0 && vt->values[to].time >= to_time) {
- to--;
- }
-
- if (to < 0) {
- return; // not bother
- }
-
- int from = _find(vt->values, from_time);
-
- // position in the right first event.+
- if (from < 0 || vt->values[from].time < from_time) {
- from++;
- }
-
- int max = vt->values.size();
-
- for (int i = from; i <= to; i++) {
- ERR_CONTINUE(i < 0 || i >= max); // shouldn't happen
- p_indices->push_back(i);
- }
-}
-
-void Animation::value_track_get_key_indices(int p_track, double p_time, double p_delta, List<int> *p_indices, int p_pingponged) const {
- ERR_FAIL_INDEX(p_track, tracks.size());
- Track *t = tracks[p_track];
- ERR_FAIL_COND(t->type != TYPE_VALUE);
-
- ValueTrack *vt = static_cast<ValueTrack *>(t);
-
- double from_time = p_time - p_delta;
- double to_time = p_time;
-
- if (from_time > to_time) {
- SWAP(from_time, to_time);
- }
-
- switch (loop_mode) {
- case LOOP_NONE: {
- if (from_time < 0) {
- from_time = 0;
- }
- if (from_time > length) {
- from_time = length;
- }
-
- if (to_time < 0) {
- to_time = 0;
- }
- if (to_time > length) {
- to_time = length;
- }
- } break;
- case LOOP_LINEAR: {
- from_time = Math::fposmod(from_time, length);
- to_time = Math::fposmod(to_time, length);
-
- if (from_time > to_time) {
- // handle loop by splitting
- _value_track_get_key_indices_in_range(vt, from_time, length, p_indices);
- _value_track_get_key_indices_in_range(vt, 0, to_time, p_indices);
- return;
- }
- } break;
- case LOOP_PINGPONG: {
- from_time = Math::pingpong(from_time, length);
- to_time = Math::pingpong(to_time, length);
-
- if (p_pingponged == -1) {
- // handle loop by splitting
- _value_track_get_key_indices_in_range(vt, 0, from_time, p_indices);
- _value_track_get_key_indices_in_range(vt, 0, to_time, p_indices);
- return;
- }
- if (p_pingponged == 1) {
- // handle loop by splitting
- _value_track_get_key_indices_in_range(vt, from_time, length, p_indices);
- _value_track_get_key_indices_in_range(vt, to_time, length, p_indices);
- return;
- }
- } break;
- }
-
- _value_track_get_key_indices_in_range(vt, from_time, to_time, p_indices);
-}
-
void Animation::value_track_set_update_mode(int p_track, UpdateMode p_mode) {
ERR_FAIL_INDEX(p_track, tracks.size());
Track *t = tracks[p_track];
ERR_FAIL_COND(t->type != TYPE_VALUE);
- ERR_FAIL_INDEX((int)p_mode, 4);
+ ERR_FAIL_INDEX((int)p_mode, 3);
ValueTrack *vt = static_cast<ValueTrack *>(t);
vt->update_mode = p_mode;
@@ -2833,47 +2726,74 @@ Animation::UpdateMode Animation::value_track_get_update_mode(int p_track) const
}
template <class T>
-void Animation::_track_get_key_indices_in_range(const Vector<T> &p_array, double from_time, double to_time, List<int> *p_indices) const {
- if (from_time != length && to_time == length) {
- to_time = length + CMP_EPSILON; //include a little more if at the end
+void Animation::_track_get_key_indices_in_range(const Vector<T> &p_array, double from_time, double to_time, List<int> *p_indices, bool p_is_backward) const {
+ int len = p_array.size();
+ if (len == 0) {
+ return;
}
- int to = _find(p_array, to_time);
-
- // can't really send the events == time, will be sent in the next frame.
- // if event>=len then it will probably never be requested by the anim player.
+ int from = 0;
+ int to = len - 1;
- if (to >= 0 && p_array[to].time >= to_time) {
- to--;
+ if (!p_is_backward) {
+ while (p_array[from].time < from_time || Math::is_equal_approx(p_array[from].time, from_time)) {
+ from++;
+ if (to < from) {
+ return;
+ }
+ }
+ while (p_array[to].time > to_time && !Math::is_equal_approx(p_array[to].time, to_time)) {
+ to--;
+ if (to < from) {
+ return;
+ }
+ }
+ } else {
+ while (p_array[from].time < from_time && !Math::is_equal_approx(p_array[from].time, from_time)) {
+ from++;
+ if (to < from) {
+ return;
+ }
+ }
+ while (p_array[to].time > to_time || Math::is_equal_approx(p_array[to].time, to_time)) {
+ to--;
+ if (to < from) {
+ return;
+ }
+ }
}
- if (to < 0) {
- return; // not bother
+ if (from == to) {
+ p_indices->push_back(from);
+ return;
}
- int from = _find(p_array, from_time);
-
- // position in the right first event.+
- if (from < 0 || p_array[from].time < from_time) {
- from++;
+ if (!p_is_backward) {
+ for (int i = from; i <= to; i++) {
+ p_indices->push_back(i);
+ }
+ } else {
+ for (int i = to; i >= to; i--) {
+ p_indices->push_back(i);
+ }
}
+}
- int max = p_array.size();
+void Animation::track_get_key_indices_in_range(int p_track, double p_time, double p_delta, List<int> *p_indices, Animation::LoopedFlag p_looped_flag) const {
+ ERR_FAIL_INDEX(p_track, tracks.size());
- for (int i = from; i <= to; i++) {
- ERR_CONTINUE(i < 0 || i >= max); // shouldn't happen
- p_indices->push_back(i);
+ if (p_delta == 0) {
+ return; // Prevent to get key continuously.
}
-}
-void Animation::track_get_key_indices_in_range(int p_track, double p_time, double p_delta, List<int> *p_indices, int p_pingponged) const {
- ERR_FAIL_INDEX(p_track, tracks.size());
const Track *t = tracks[p_track];
double from_time = p_time - p_delta;
double to_time = p_time;
+ bool is_backward = false;
if (from_time > to_time) {
+ is_backward = true;
SWAP(from_time, to_time);
}
@@ -2902,7 +2822,10 @@ void Animation::track_get_key_indices_in_range(int p_track, double p_time, doubl
}
if (from_time > to_time) {
- // handle loop by splitting
+ // Handle loop by splitting.
+ double anim_end = length + CMP_EPSILON;
+ double anim_start = -CMP_EPSILON;
+
switch (t->type) {
case TYPE_POSITION_3D: {
const PositionTrack *tt = static_cast<const PositionTrack *>(t);
@@ -2910,8 +2833,13 @@ void Animation::track_get_key_indices_in_range(int p_track, double p_time, doubl
_get_compressed_key_indices_in_range<3>(tt->compressed_track, from_time, length, p_indices);
_get_compressed_key_indices_in_range<3>(tt->compressed_track, 0, to_time, p_indices);
} else {
- _track_get_key_indices_in_range(tt->positions, from_time, length, p_indices);
- _track_get_key_indices_in_range(tt->positions, 0, to_time, p_indices);
+ if (!is_backward) {
+ _track_get_key_indices_in_range(tt->positions, from_time, anim_end, p_indices, is_backward);
+ _track_get_key_indices_in_range(tt->positions, anim_start, to_time, p_indices, is_backward);
+ } else {
+ _track_get_key_indices_in_range(tt->positions, anim_start, to_time, p_indices, is_backward);
+ _track_get_key_indices_in_range(tt->positions, from_time, anim_end, p_indices, is_backward);
+ }
}
} break;
case TYPE_ROTATION_3D: {
@@ -2920,8 +2848,13 @@ void Animation::track_get_key_indices_in_range(int p_track, double p_time, doubl
_get_compressed_key_indices_in_range<3>(rt->compressed_track, from_time, length, p_indices);
_get_compressed_key_indices_in_range<3>(rt->compressed_track, 0, to_time, p_indices);
} else {
- _track_get_key_indices_in_range(rt->rotations, from_time, length, p_indices);
- _track_get_key_indices_in_range(rt->rotations, 0, to_time, p_indices);
+ if (!is_backward) {
+ _track_get_key_indices_in_range(rt->rotations, from_time, anim_end, p_indices, is_backward);
+ _track_get_key_indices_in_range(rt->rotations, anim_start, to_time, p_indices, is_backward);
+ } else {
+ _track_get_key_indices_in_range(rt->rotations, anim_start, to_time, p_indices, is_backward);
+ _track_get_key_indices_in_range(rt->rotations, from_time, anim_end, p_indices, is_backward);
+ }
}
} break;
case TYPE_SCALE_3D: {
@@ -2930,8 +2863,13 @@ void Animation::track_get_key_indices_in_range(int p_track, double p_time, doubl
_get_compressed_key_indices_in_range<3>(st->compressed_track, from_time, length, p_indices);
_get_compressed_key_indices_in_range<3>(st->compressed_track, 0, to_time, p_indices);
} else {
- _track_get_key_indices_in_range(st->scales, from_time, length, p_indices);
- _track_get_key_indices_in_range(st->scales, 0, to_time, p_indices);
+ if (!is_backward) {
+ _track_get_key_indices_in_range(st->scales, from_time, anim_end, p_indices, is_backward);
+ _track_get_key_indices_in_range(st->scales, anim_start, to_time, p_indices, is_backward);
+ } else {
+ _track_get_key_indices_in_range(st->scales, anim_start, to_time, p_indices, is_backward);
+ _track_get_key_indices_in_range(st->scales, from_time, anim_end, p_indices, is_backward);
+ }
}
} break;
case TYPE_BLEND_SHAPE: {
@@ -2940,38 +2878,83 @@ void Animation::track_get_key_indices_in_range(int p_track, double p_time, doubl
_get_compressed_key_indices_in_range<1>(bst->compressed_track, from_time, length, p_indices);
_get_compressed_key_indices_in_range<1>(bst->compressed_track, 0, to_time, p_indices);
} else {
- _track_get_key_indices_in_range(bst->blend_shapes, from_time, length, p_indices);
- _track_get_key_indices_in_range(bst->blend_shapes, 0, to_time, p_indices);
+ if (!is_backward) {
+ _track_get_key_indices_in_range(bst->blend_shapes, from_time, anim_end, p_indices, is_backward);
+ _track_get_key_indices_in_range(bst->blend_shapes, anim_start, to_time, p_indices, is_backward);
+ } else {
+ _track_get_key_indices_in_range(bst->blend_shapes, anim_start, to_time, p_indices, is_backward);
+ _track_get_key_indices_in_range(bst->blend_shapes, from_time, anim_end, p_indices, is_backward);
+ }
}
} break;
case TYPE_VALUE: {
const ValueTrack *vt = static_cast<const ValueTrack *>(t);
- _track_get_key_indices_in_range(vt->values, from_time, length, p_indices);
- _track_get_key_indices_in_range(vt->values, 0, to_time, p_indices);
+ if (!is_backward) {
+ _track_get_key_indices_in_range(vt->values, from_time, anim_end, p_indices, is_backward);
+ _track_get_key_indices_in_range(vt->values, anim_start, to_time, p_indices, is_backward);
+ } else {
+ _track_get_key_indices_in_range(vt->values, anim_start, to_time, p_indices, is_backward);
+ _track_get_key_indices_in_range(vt->values, from_time, anim_end, p_indices, is_backward);
+ }
} break;
case TYPE_METHOD: {
const MethodTrack *mt = static_cast<const MethodTrack *>(t);
- _track_get_key_indices_in_range(mt->methods, from_time, length, p_indices);
- _track_get_key_indices_in_range(mt->methods, 0, to_time, p_indices);
+ if (!is_backward) {
+ _track_get_key_indices_in_range(mt->methods, from_time, anim_end, p_indices, is_backward);
+ _track_get_key_indices_in_range(mt->methods, anim_start, to_time, p_indices, is_backward);
+ } else {
+ _track_get_key_indices_in_range(mt->methods, anim_start, to_time, p_indices, is_backward);
+ _track_get_key_indices_in_range(mt->methods, from_time, anim_end, p_indices, is_backward);
+ }
} break;
case TYPE_BEZIER: {
const BezierTrack *bz = static_cast<const BezierTrack *>(t);
- _track_get_key_indices_in_range(bz->values, from_time, length, p_indices);
- _track_get_key_indices_in_range(bz->values, 0, to_time, p_indices);
+ if (!is_backward) {
+ _track_get_key_indices_in_range(bz->values, from_time, anim_end, p_indices, is_backward);
+ _track_get_key_indices_in_range(bz->values, anim_start, to_time, p_indices, is_backward);
+ } else {
+ _track_get_key_indices_in_range(bz->values, anim_start, to_time, p_indices, is_backward);
+ _track_get_key_indices_in_range(bz->values, from_time, anim_end, p_indices, is_backward);
+ }
} break;
case TYPE_AUDIO: {
const AudioTrack *ad = static_cast<const AudioTrack *>(t);
- _track_get_key_indices_in_range(ad->values, from_time, length, p_indices);
- _track_get_key_indices_in_range(ad->values, 0, to_time, p_indices);
+ if (!is_backward) {
+ _track_get_key_indices_in_range(ad->values, from_time, anim_end, p_indices, is_backward);
+ _track_get_key_indices_in_range(ad->values, anim_start, to_time, p_indices, is_backward);
+ } else {
+ _track_get_key_indices_in_range(ad->values, anim_start, to_time, p_indices, is_backward);
+ _track_get_key_indices_in_range(ad->values, from_time, anim_end, p_indices, is_backward);
+ }
} break;
case TYPE_ANIMATION: {
const AnimationTrack *an = static_cast<const AnimationTrack *>(t);
- _track_get_key_indices_in_range(an->values, from_time, length, p_indices);
- _track_get_key_indices_in_range(an->values, 0, to_time, p_indices);
+ if (!is_backward) {
+ _track_get_key_indices_in_range(an->values, from_time, anim_end, p_indices, is_backward);
+ _track_get_key_indices_in_range(an->values, anim_start, to_time, p_indices, is_backward);
+ } else {
+ _track_get_key_indices_in_range(an->values, anim_start, to_time, p_indices, is_backward);
+ _track_get_key_indices_in_range(an->values, from_time, anim_end, p_indices, is_backward);
+ }
} break;
}
return;
}
+
+ // Not from_time > to_time but most recent of looping...
+ if (p_looped_flag != Animation::LOOPED_FLAG_NONE) {
+ if (!is_backward && Math::is_equal_approx(from_time, 0)) {
+ int edge = track_find_key(p_track, 0, FIND_MODE_EXACT);
+ if (edge >= 0) {
+ p_indices->push_back(edge);
+ }
+ } else if (is_backward && Math::is_equal_approx(to_time, length)) {
+ int edge = track_find_key(p_track, length, FIND_MODE_EXACT);
+ if (edge >= 0) {
+ p_indices->push_back(edge);
+ }
+ }
+ }
} break;
case LOOP_PINGPONG: {
if (from_time > length || from_time < 0) {
@@ -2981,160 +2964,164 @@ void Animation::track_get_key_indices_in_range(int p_track, double p_time, doubl
to_time = Math::pingpong(to_time, length);
}
- if ((int)Math::floor(abs(p_delta) / length) % 2 == 0) {
- if (p_pingponged == -1) {
- // handle loop by splitting
- switch (t->type) {
- case TYPE_POSITION_3D: {
- const PositionTrack *tt = static_cast<const PositionTrack *>(t);
- if (tt->compressed_track >= 0) {
- _get_compressed_key_indices_in_range<3>(tt->compressed_track, 0, from_time, p_indices);
- _get_compressed_key_indices_in_range<3>(tt->compressed_track, 0, to_time, p_indices);
- } else {
- _track_get_key_indices_in_range(tt->positions, 0, from_time, p_indices);
- _track_get_key_indices_in_range(tt->positions, 0, to_time, p_indices);
- }
- } break;
- case TYPE_ROTATION_3D: {
- const RotationTrack *rt = static_cast<const RotationTrack *>(t);
- if (rt->compressed_track >= 0) {
- _get_compressed_key_indices_in_range<3>(rt->compressed_track, 0, from_time, p_indices);
- _get_compressed_key_indices_in_range<3>(rt->compressed_track, 0, to_time, p_indices);
- } else {
- _track_get_key_indices_in_range(rt->rotations, 0, from_time, p_indices);
- _track_get_key_indices_in_range(rt->rotations, 0, to_time, p_indices);
- }
- } break;
- case TYPE_SCALE_3D: {
- const ScaleTrack *st = static_cast<const ScaleTrack *>(t);
- if (st->compressed_track >= 0) {
- _get_compressed_key_indices_in_range<3>(st->compressed_track, 0, from_time, p_indices);
- _get_compressed_key_indices_in_range<3>(st->compressed_track, 0, to_time, p_indices);
- } else {
- _track_get_key_indices_in_range(st->scales, 0, from_time, p_indices);
- _track_get_key_indices_in_range(st->scales, 0, to_time, p_indices);
- }
- } break;
- case TYPE_BLEND_SHAPE: {
- const BlendShapeTrack *bst = static_cast<const BlendShapeTrack *>(t);
- if (bst->compressed_track >= 0) {
- _get_compressed_key_indices_in_range<1>(bst->compressed_track, 0, from_time, p_indices);
- _get_compressed_key_indices_in_range<1>(bst->compressed_track, 0, to_time, p_indices);
- } else {
- _track_get_key_indices_in_range(bst->blend_shapes, 0, from_time, p_indices);
- _track_get_key_indices_in_range(bst->blend_shapes, 0, to_time, p_indices);
- }
- } break;
- case TYPE_VALUE: {
- const ValueTrack *vt = static_cast<const ValueTrack *>(t);
- _track_get_key_indices_in_range(vt->values, 0, from_time, p_indices);
- _track_get_key_indices_in_range(vt->values, 0, to_time, p_indices);
- } break;
- case TYPE_METHOD: {
- const MethodTrack *mt = static_cast<const MethodTrack *>(t);
- _track_get_key_indices_in_range(mt->methods, 0, from_time, p_indices);
- _track_get_key_indices_in_range(mt->methods, 0, to_time, p_indices);
- } break;
- case TYPE_BEZIER: {
- const BezierTrack *bz = static_cast<const BezierTrack *>(t);
- _track_get_key_indices_in_range(bz->values, 0, from_time, p_indices);
- _track_get_key_indices_in_range(bz->values, 0, to_time, p_indices);
- } break;
- case TYPE_AUDIO: {
- const AudioTrack *ad = static_cast<const AudioTrack *>(t);
- _track_get_key_indices_in_range(ad->values, 0, from_time, p_indices);
- _track_get_key_indices_in_range(ad->values, 0, to_time, p_indices);
- } break;
- case TYPE_ANIMATION: {
- const AnimationTrack *an = static_cast<const AnimationTrack *>(t);
- _track_get_key_indices_in_range(an->values, 0, from_time, p_indices);
- _track_get_key_indices_in_range(an->values, 0, to_time, p_indices);
- } break;
- }
- return;
+ if (p_looped_flag == Animation::LOOPED_FLAG_START) {
+ // Handle loop by splitting.
+ switch (t->type) {
+ case TYPE_POSITION_3D: {
+ const PositionTrack *tt = static_cast<const PositionTrack *>(t);
+ if (tt->compressed_track >= 0) {
+ _get_compressed_key_indices_in_range<3>(tt->compressed_track, 0, from_time, p_indices);
+ _get_compressed_key_indices_in_range<3>(tt->compressed_track, 0, to_time, p_indices);
+ } else {
+ _track_get_key_indices_in_range(tt->positions, 0, from_time, p_indices, true);
+ _track_get_key_indices_in_range(tt->positions, 0, to_time, p_indices, false);
+ }
+ } break;
+ case TYPE_ROTATION_3D: {
+ const RotationTrack *rt = static_cast<const RotationTrack *>(t);
+ if (rt->compressed_track >= 0) {
+ _get_compressed_key_indices_in_range<3>(rt->compressed_track, 0, from_time, p_indices);
+ _get_compressed_key_indices_in_range<3>(rt->compressed_track, 0, to_time, p_indices);
+ } else {
+ _track_get_key_indices_in_range(rt->rotations, 0, from_time, p_indices, true);
+ _track_get_key_indices_in_range(rt->rotations, 0, to_time, p_indices, false);
+ }
+ } break;
+ case TYPE_SCALE_3D: {
+ const ScaleTrack *st = static_cast<const ScaleTrack *>(t);
+ if (st->compressed_track >= 0) {
+ _get_compressed_key_indices_in_range<3>(st->compressed_track, 0, from_time, p_indices);
+ _get_compressed_key_indices_in_range<3>(st->compressed_track, 0, to_time, p_indices);
+ } else {
+ _track_get_key_indices_in_range(st->scales, 0, from_time, p_indices, true);
+ _track_get_key_indices_in_range(st->scales, 0, to_time, p_indices, false);
+ }
+ } break;
+ case TYPE_BLEND_SHAPE: {
+ const BlendShapeTrack *bst = static_cast<const BlendShapeTrack *>(t);
+ if (bst->compressed_track >= 0) {
+ _get_compressed_key_indices_in_range<1>(bst->compressed_track, 0, from_time, p_indices);
+ _get_compressed_key_indices_in_range<1>(bst->compressed_track, 0, to_time, p_indices);
+ } else {
+ _track_get_key_indices_in_range(bst->blend_shapes, 0, from_time, p_indices, true);
+ _track_get_key_indices_in_range(bst->blend_shapes, 0, to_time, p_indices, false);
+ }
+ } break;
+ case TYPE_VALUE: {
+ const ValueTrack *vt = static_cast<const ValueTrack *>(t);
+ _track_get_key_indices_in_range(vt->values, 0, from_time, p_indices, true);
+ _track_get_key_indices_in_range(vt->values, 0, to_time, p_indices, false);
+ } break;
+ case TYPE_METHOD: {
+ const MethodTrack *mt = static_cast<const MethodTrack *>(t);
+ _track_get_key_indices_in_range(mt->methods, 0, from_time, p_indices, true);
+ _track_get_key_indices_in_range(mt->methods, 0, to_time, p_indices, false);
+ } break;
+ case TYPE_BEZIER: {
+ const BezierTrack *bz = static_cast<const BezierTrack *>(t);
+ _track_get_key_indices_in_range(bz->values, 0, from_time, p_indices, true);
+ _track_get_key_indices_in_range(bz->values, 0, to_time, p_indices, false);
+ } break;
+ case TYPE_AUDIO: {
+ const AudioTrack *ad = static_cast<const AudioTrack *>(t);
+ _track_get_key_indices_in_range(ad->values, 0, from_time, p_indices, true);
+ _track_get_key_indices_in_range(ad->values, 0, to_time, p_indices, false);
+ } break;
+ case TYPE_ANIMATION: {
+ const AnimationTrack *an = static_cast<const AnimationTrack *>(t);
+ _track_get_key_indices_in_range(an->values, 0, from_time, p_indices, true);
+ _track_get_key_indices_in_range(an->values, 0, to_time, p_indices, false);
+ } break;
}
- if (p_pingponged == 1) {
- // handle loop by splitting
- switch (t->type) {
- case TYPE_POSITION_3D: {
- const PositionTrack *tt = static_cast<const PositionTrack *>(t);
- if (tt->compressed_track >= 0) {
- _get_compressed_key_indices_in_range<3>(tt->compressed_track, from_time, length, p_indices);
- _get_compressed_key_indices_in_range<3>(tt->compressed_track, to_time, length, p_indices);
- } else {
- _track_get_key_indices_in_range(tt->positions, from_time, length, p_indices);
- _track_get_key_indices_in_range(tt->positions, to_time, length, p_indices);
- }
- } break;
- case TYPE_ROTATION_3D: {
- const RotationTrack *rt = static_cast<const RotationTrack *>(t);
- if (rt->compressed_track >= 0) {
- _get_compressed_key_indices_in_range<3>(rt->compressed_track, from_time, length, p_indices);
- _get_compressed_key_indices_in_range<3>(rt->compressed_track, to_time, length, p_indices);
- } else {
- _track_get_key_indices_in_range(rt->rotations, from_time, length, p_indices);
- _track_get_key_indices_in_range(rt->rotations, to_time, length, p_indices);
- }
- } break;
- case TYPE_SCALE_3D: {
- const ScaleTrack *st = static_cast<const ScaleTrack *>(t);
- if (st->compressed_track >= 0) {
- _get_compressed_key_indices_in_range<3>(st->compressed_track, from_time, length, p_indices);
- _get_compressed_key_indices_in_range<3>(st->compressed_track, to_time, length, p_indices);
- } else {
- _track_get_key_indices_in_range(st->scales, from_time, length, p_indices);
- _track_get_key_indices_in_range(st->scales, to_time, length, p_indices);
- }
- } break;
- case TYPE_BLEND_SHAPE: {
- const BlendShapeTrack *bst = static_cast<const BlendShapeTrack *>(t);
- if (bst->compressed_track >= 0) {
- _get_compressed_key_indices_in_range<1>(bst->compressed_track, from_time, length, p_indices);
- _get_compressed_key_indices_in_range<1>(bst->compressed_track, to_time, length, p_indices);
- } else {
- _track_get_key_indices_in_range(bst->blend_shapes, from_time, length, p_indices);
- _track_get_key_indices_in_range(bst->blend_shapes, to_time, length, p_indices);
- }
- } break;
- case TYPE_VALUE: {
- const ValueTrack *vt = static_cast<const ValueTrack *>(t);
- _track_get_key_indices_in_range(vt->values, from_time, length, p_indices);
- _track_get_key_indices_in_range(vt->values, to_time, length, p_indices);
- } break;
- case TYPE_METHOD: {
- const MethodTrack *mt = static_cast<const MethodTrack *>(t);
- _track_get_key_indices_in_range(mt->methods, from_time, length, p_indices);
- _track_get_key_indices_in_range(mt->methods, to_time, length, p_indices);
- } break;
- case TYPE_BEZIER: {
- const BezierTrack *bz = static_cast<const BezierTrack *>(t);
- _track_get_key_indices_in_range(bz->values, from_time, length, p_indices);
- _track_get_key_indices_in_range(bz->values, to_time, length, p_indices);
- } break;
- case TYPE_AUDIO: {
- const AudioTrack *ad = static_cast<const AudioTrack *>(t);
- _track_get_key_indices_in_range(ad->values, from_time, length, p_indices);
- _track_get_key_indices_in_range(ad->values, to_time, length, p_indices);
- } break;
- case TYPE_ANIMATION: {
- const AnimationTrack *an = static_cast<const AnimationTrack *>(t);
- _track_get_key_indices_in_range(an->values, from_time, length, p_indices);
- _track_get_key_indices_in_range(an->values, to_time, length, p_indices);
- } break;
- }
- return;
+ return;
+ }
+ if (p_looped_flag == Animation::LOOPED_FLAG_END) {
+ // Handle loop by splitting.
+ switch (t->type) {
+ case TYPE_POSITION_3D: {
+ const PositionTrack *tt = static_cast<const PositionTrack *>(t);
+ if (tt->compressed_track >= 0) {
+ _get_compressed_key_indices_in_range<3>(tt->compressed_track, from_time, length, p_indices);
+ _get_compressed_key_indices_in_range<3>(tt->compressed_track, to_time, length, p_indices);
+ } else {
+ _track_get_key_indices_in_range(tt->positions, from_time, length, p_indices, false);
+ _track_get_key_indices_in_range(tt->positions, to_time, length, p_indices, true);
+ }
+ } break;
+ case TYPE_ROTATION_3D: {
+ const RotationTrack *rt = static_cast<const RotationTrack *>(t);
+ if (rt->compressed_track >= 0) {
+ _get_compressed_key_indices_in_range<3>(rt->compressed_track, from_time, length, p_indices);
+ _get_compressed_key_indices_in_range<3>(rt->compressed_track, to_time, length, p_indices);
+ } else {
+ _track_get_key_indices_in_range(rt->rotations, from_time, length, p_indices, false);
+ _track_get_key_indices_in_range(rt->rotations, to_time, length, p_indices, true);
+ }
+ } break;
+ case TYPE_SCALE_3D: {
+ const ScaleTrack *st = static_cast<const ScaleTrack *>(t);
+ if (st->compressed_track >= 0) {
+ _get_compressed_key_indices_in_range<3>(st->compressed_track, from_time, length, p_indices);
+ _get_compressed_key_indices_in_range<3>(st->compressed_track, to_time, length, p_indices);
+ } else {
+ _track_get_key_indices_in_range(st->scales, from_time, length, p_indices, false);
+ _track_get_key_indices_in_range(st->scales, to_time, length, p_indices, true);
+ }
+ } break;
+ case TYPE_BLEND_SHAPE: {
+ const BlendShapeTrack *bst = static_cast<const BlendShapeTrack *>(t);
+ if (bst->compressed_track >= 0) {
+ _get_compressed_key_indices_in_range<1>(bst->compressed_track, from_time, length, p_indices);
+ _get_compressed_key_indices_in_range<1>(bst->compressed_track, to_time, length, p_indices);
+ } else {
+ _track_get_key_indices_in_range(bst->blend_shapes, from_time, length, p_indices, false);
+ _track_get_key_indices_in_range(bst->blend_shapes, to_time, length, p_indices, true);
+ }
+ } break;
+ case TYPE_VALUE: {
+ const ValueTrack *vt = static_cast<const ValueTrack *>(t);
+ _track_get_key_indices_in_range(vt->values, from_time, length, p_indices, false);
+ _track_get_key_indices_in_range(vt->values, to_time, length, p_indices, true);
+ } break;
+ case TYPE_METHOD: {
+ const MethodTrack *mt = static_cast<const MethodTrack *>(t);
+ _track_get_key_indices_in_range(mt->methods, from_time, length, p_indices, false);
+ _track_get_key_indices_in_range(mt->methods, to_time, length, p_indices, true);
+ } break;
+ case TYPE_BEZIER: {
+ const BezierTrack *bz = static_cast<const BezierTrack *>(t);
+ _track_get_key_indices_in_range(bz->values, from_time, length, p_indices, false);
+ _track_get_key_indices_in_range(bz->values, to_time, length, p_indices, true);
+ } break;
+ case TYPE_AUDIO: {
+ const AudioTrack *ad = static_cast<const AudioTrack *>(t);
+ _track_get_key_indices_in_range(ad->values, from_time, length, p_indices, false);
+ _track_get_key_indices_in_range(ad->values, to_time, length, p_indices, true);
+ } break;
+ case TYPE_ANIMATION: {
+ const AnimationTrack *an = static_cast<const AnimationTrack *>(t);
+ _track_get_key_indices_in_range(an->values, from_time, length, p_indices, false);
+ _track_get_key_indices_in_range(an->values, to_time, length, p_indices, true);
+ } break;
}
+ return;
+ }
+
+ // The edge will be pingponged in the next frame and processed there, so let's ignore it now...
+ if (!is_backward && Math::is_equal_approx(to_time, length)) {
+ to_time -= CMP_EPSILON;
+ } else if (is_backward && Math::is_equal_approx(from_time, 0)) {
+ from_time += CMP_EPSILON;
}
} break;
}
-
switch (t->type) {
case TYPE_POSITION_3D: {
const PositionTrack *tt = static_cast<const PositionTrack *>(t);
if (tt->compressed_track >= 0) {
_get_compressed_key_indices_in_range<3>(tt->compressed_track, from_time, to_time - from_time, p_indices);
} else {
- _track_get_key_indices_in_range(tt->positions, from_time, to_time, p_indices);
+ _track_get_key_indices_in_range(tt->positions, from_time, to_time, p_indices, is_backward);
}
} break;
case TYPE_ROTATION_3D: {
@@ -3142,7 +3129,7 @@ void Animation::track_get_key_indices_in_range(int p_track, double p_time, doubl
if (rt->compressed_track >= 0) {
_get_compressed_key_indices_in_range<3>(rt->compressed_track, from_time, to_time - from_time, p_indices);
} else {
- _track_get_key_indices_in_range(rt->rotations, from_time, to_time, p_indices);
+ _track_get_key_indices_in_range(rt->rotations, from_time, to_time, p_indices, is_backward);
}
} break;
case TYPE_SCALE_3D: {
@@ -3150,7 +3137,7 @@ void Animation::track_get_key_indices_in_range(int p_track, double p_time, doubl
if (st->compressed_track >= 0) {
_get_compressed_key_indices_in_range<3>(st->compressed_track, from_time, to_time - from_time, p_indices);
} else {
- _track_get_key_indices_in_range(st->scales, from_time, to_time, p_indices);
+ _track_get_key_indices_in_range(st->scales, from_time, to_time, p_indices, is_backward);
}
} break;
case TYPE_BLEND_SHAPE: {
@@ -3158,136 +3145,32 @@ void Animation::track_get_key_indices_in_range(int p_track, double p_time, doubl
if (bst->compressed_track >= 0) {
_get_compressed_key_indices_in_range<1>(bst->compressed_track, from_time, to_time - from_time, p_indices);
} else {
- _track_get_key_indices_in_range(bst->blend_shapes, from_time, to_time, p_indices);
+ _track_get_key_indices_in_range(bst->blend_shapes, from_time, to_time, p_indices, is_backward);
}
} break;
case TYPE_VALUE: {
const ValueTrack *vt = static_cast<const ValueTrack *>(t);
- _track_get_key_indices_in_range(vt->values, from_time, to_time, p_indices);
+ _track_get_key_indices_in_range(vt->values, from_time, to_time, p_indices, is_backward);
} break;
case TYPE_METHOD: {
const MethodTrack *mt = static_cast<const MethodTrack *>(t);
- _track_get_key_indices_in_range(mt->methods, from_time, to_time, p_indices);
+ _track_get_key_indices_in_range(mt->methods, from_time, to_time, p_indices, is_backward);
} break;
case TYPE_BEZIER: {
const BezierTrack *bz = static_cast<const BezierTrack *>(t);
- _track_get_key_indices_in_range(bz->values, from_time, to_time, p_indices);
+ _track_get_key_indices_in_range(bz->values, from_time, to_time, p_indices, is_backward);
} break;
case TYPE_AUDIO: {
const AudioTrack *ad = static_cast<const AudioTrack *>(t);
- _track_get_key_indices_in_range(ad->values, from_time, to_time, p_indices);
+ _track_get_key_indices_in_range(ad->values, from_time, to_time, p_indices, is_backward);
} break;
case TYPE_ANIMATION: {
const AnimationTrack *an = static_cast<const AnimationTrack *>(t);
- _track_get_key_indices_in_range(an->values, from_time, to_time, p_indices);
+ _track_get_key_indices_in_range(an->values, from_time, to_time, p_indices, is_backward);
} break;
}
}
-void Animation::_method_track_get_key_indices_in_range(const MethodTrack *mt, double from_time, double to_time, List<int> *p_indices) const {
- if (from_time != length && to_time == length) {
- to_time = length + CMP_EPSILON; //include a little more if at the end
- }
-
- int to = _find(mt->methods, to_time);
-
- // can't really send the events == time, will be sent in the next frame.
- // if event>=len then it will probably never be requested by the anim player.
-
- if (to >= 0 && mt->methods[to].time >= to_time) {
- to--;
- }
-
- if (to < 0) {
- return; // not bother
- }
-
- int from = _find(mt->methods, from_time);
-
- // position in the right first event.+
- if (from < 0 || mt->methods[from].time < from_time) {
- from++;
- }
-
- int max = mt->methods.size();
-
- for (int i = from; i <= to; i++) {
- ERR_CONTINUE(i < 0 || i >= max); // shouldn't happen
- p_indices->push_back(i);
- }
-}
-
-void Animation::method_track_get_key_indices(int p_track, double p_time, double p_delta, List<int> *p_indices, int p_pingponged) const {
- ERR_FAIL_INDEX(p_track, tracks.size());
- Track *t = tracks[p_track];
- ERR_FAIL_COND(t->type != TYPE_METHOD);
-
- MethodTrack *mt = static_cast<MethodTrack *>(t);
-
- double from_time = p_time - p_delta;
- double to_time = p_time;
-
- if (from_time > to_time) {
- SWAP(from_time, to_time);
- }
-
- switch (loop_mode) {
- case LOOP_NONE: {
- if (from_time < 0) {
- from_time = 0;
- }
- if (from_time > length) {
- from_time = length;
- }
-
- if (to_time < 0) {
- to_time = 0;
- }
- if (to_time > length) {
- to_time = length;
- }
- } break;
- case LOOP_LINEAR: {
- if (from_time > length || from_time < 0) {
- from_time = Math::fposmod(from_time, length);
- }
- if (to_time > length || to_time < 0) {
- to_time = Math::fposmod(to_time, length);
- }
-
- if (from_time > to_time) {
- // handle loop by splitting
- _method_track_get_key_indices_in_range(mt, from_time, length, p_indices);
- _method_track_get_key_indices_in_range(mt, 0, to_time, p_indices);
- return;
- }
- } break;
- case LOOP_PINGPONG: {
- if (from_time > length || from_time < 0) {
- from_time = Math::pingpong(from_time, length);
- }
- if (to_time > length || to_time < 0) {
- to_time = Math::pingpong(to_time, length);
- }
-
- if (p_pingponged == -1) {
- _method_track_get_key_indices_in_range(mt, 0, from_time, p_indices);
- _method_track_get_key_indices_in_range(mt, 0, to_time, p_indices);
- return;
- }
- if (p_pingponged == 1) {
- _method_track_get_key_indices_in_range(mt, from_time, length, p_indices);
- _method_track_get_key_indices_in_range(mt, to_time, length, p_indices);
- return;
- }
- } break;
- default:
- break;
- }
-
- _method_track_get_key_indices_in_range(mt, from_time, to_time, p_indices);
-}
-
Vector<Variant> Animation::method_track_get_params(int p_track, int p_key_idx) const {
ERR_FAIL_INDEX_V(p_track, tracks.size(), Vector<Variant>());
Track *t = tracks[p_track];
@@ -3834,7 +3717,6 @@ void Animation::track_move_up(int p_track) {
}
emit_changed();
- emit_signal(SceneStringNames::get_singleton()->tracks_changed);
}
void Animation::track_move_down(int p_track) {
@@ -3843,7 +3725,6 @@ void Animation::track_move_down(int p_track) {
}
emit_changed();
- emit_signal(SceneStringNames::get_singleton()->tracks_changed);
}
void Animation::track_move_to(int p_track, int p_to_index) {
@@ -3859,7 +3740,6 @@ void Animation::track_move_to(int p_track, int p_to_index) {
tracks.insert(p_to_index > p_track ? p_to_index - 1 : p_to_index, track);
emit_changed();
- emit_signal(SceneStringNames::get_singleton()->tracks_changed);
}
void Animation::track_swap(int p_track, int p_with_track) {
@@ -3871,7 +3751,6 @@ void Animation::track_swap(int p_track, int p_with_track) {
SWAP(tracks.write[p_track], tracks.write[p_with_track]);
emit_changed();
- emit_signal(SceneStringNames::get_singleton()->tracks_changed);
}
void Animation::set_step(real_t p_step) {
@@ -3939,7 +3818,7 @@ void Animation::_bind_methods() {
ClassDB::bind_method(D_METHOD("track_get_key_count", "track_idx"), &Animation::track_get_key_count);
ClassDB::bind_method(D_METHOD("track_get_key_value", "track_idx", "key_idx"), &Animation::track_get_key_value);
ClassDB::bind_method(D_METHOD("track_get_key_time", "track_idx", "key_idx"), &Animation::track_get_key_time);
- ClassDB::bind_method(D_METHOD("track_find_key", "track_idx", "time", "exact"), &Animation::track_find_key, DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("track_find_key", "track_idx", "time", "find_mode"), &Animation::track_find_key, DEFVAL(FIND_MODE_NEAREST));
ClassDB::bind_method(D_METHOD("track_set_interpolation_type", "track_idx", "interpolation"), &Animation::track_set_interpolation_type);
ClassDB::bind_method(D_METHOD("track_get_interpolation_type", "track_idx"), &Animation::track_get_interpolation_type);
@@ -3952,10 +3831,8 @@ void Animation::_bind_methods() {
ClassDB::bind_method(D_METHOD("value_track_set_update_mode", "track_idx", "mode"), &Animation::value_track_set_update_mode);
ClassDB::bind_method(D_METHOD("value_track_get_update_mode", "track_idx"), &Animation::value_track_get_update_mode);
- ClassDB::bind_method(D_METHOD("value_track_get_key_indices", "track_idx", "time_sec", "delta"), &Animation::_value_track_get_key_indices);
ClassDB::bind_method(D_METHOD("value_track_interpolate", "track_idx", "time_sec"), &Animation::value_track_interpolate);
- ClassDB::bind_method(D_METHOD("method_track_get_key_indices", "track_idx", "time_sec", "delta"), &Animation::_method_track_get_key_indices);
ClassDB::bind_method(D_METHOD("method_track_get_name", "track_idx", "key_idx"), &Animation::method_track_get_name);
ClassDB::bind_method(D_METHOD("method_track_get_params", "track_idx", "key_idx"), &Animation::method_track_get_params);
@@ -4001,8 +3878,6 @@ void Animation::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "loop_mode", PROPERTY_HINT_ENUM, "None,Linear,Ping-Pong"), "set_loop_mode", "get_loop_mode");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "step", PROPERTY_HINT_RANGE, "0,4096,0.001,suffix:s"), "set_step", "get_step");
- ADD_SIGNAL(MethodInfo("tracks_changed"));
-
BIND_ENUM_CONSTANT(TYPE_VALUE);
BIND_ENUM_CONSTANT(TYPE_POSITION_3D);
BIND_ENUM_CONSTANT(TYPE_ROTATION_3D);
@@ -4021,12 +3896,19 @@ void Animation::_bind_methods() {
BIND_ENUM_CONSTANT(UPDATE_CONTINUOUS);
BIND_ENUM_CONSTANT(UPDATE_DISCRETE);
- BIND_ENUM_CONSTANT(UPDATE_TRIGGER);
BIND_ENUM_CONSTANT(UPDATE_CAPTURE);
BIND_ENUM_CONSTANT(LOOP_NONE);
BIND_ENUM_CONSTANT(LOOP_LINEAR);
BIND_ENUM_CONSTANT(LOOP_PINGPONG);
+
+ BIND_ENUM_CONSTANT(LOOPED_FLAG_NONE);
+ BIND_ENUM_CONSTANT(LOOPED_FLAG_END);
+ BIND_ENUM_CONSTANT(LOOPED_FLAG_START);
+
+ BIND_ENUM_CONSTANT(FIND_MODE_NEAREST);
+ BIND_ENUM_CONSTANT(FIND_MODE_APPROX);
+ BIND_ENUM_CONSTANT(FIND_MODE_EXACT);
}
void Animation::clear() {
@@ -4041,7 +3923,6 @@ void Animation::clear() {
compression.pages.clear();
compression.fps = 120;
emit_changed();
- emit_signal(SceneStringNames::get_singleton()->tracks_changed);
}
bool Animation::_float_track_optimize_key(const TKey<float> t0, const TKey<float> t1, const TKey<float> t2, real_t p_allowed_velocity_err, real_t p_allowed_precision_error) {
@@ -4964,7 +4845,7 @@ void Animation::compress(uint32_t p_page_size, uint32_t p_fps, float p_split_tol
if (rollback || best_frame == FRAME_MAX) {
// Commit the page if had to rollback or if no track was found
- print_animc("\tCommiting page..");
+ print_animc("\tCommiting page...");
// The end frame for the page depends entirely on whether its valid or
// no more keys were found.
@@ -6011,7 +5892,8 @@ Variant Animation::interpolate_variant(const Variant &a, const Variant &b, float
}
}
-Animation::Animation() {}
+Animation::Animation() {
+}
Animation::~Animation() {
for (int i = 0; i < tracks.size(); i++) {
diff --git a/scene/resources/animation.h b/scene/resources/animation.h
index 49c8fa4c22..b7d5a683db 100644
--- a/scene/resources/animation.h
+++ b/scene/resources/animation.h
@@ -64,7 +64,6 @@ public:
enum UpdateMode {
UPDATE_CONTINUOUS,
UPDATE_DISCRETE,
- UPDATE_TRIGGER,
UPDATE_CAPTURE,
};
@@ -74,6 +73,18 @@ public:
LOOP_PINGPONG,
};
+ enum LoopedFlag {
+ LOOPED_FLAG_NONE,
+ LOOPED_FLAG_END,
+ LOOPED_FLAG_START,
+ };
+
+ enum FindMode {
+ FIND_MODE_NEAREST,
+ FIND_MODE_APPROX,
+ FIND_MODE_EXACT,
+ };
+
#ifdef TOOLS_ENABLED
enum HandleMode {
HANDLE_MODE_FREE,
@@ -250,15 +261,11 @@ private:
_FORCE_INLINE_ T _interpolate(const Vector<TKey<T>> &p_keys, double p_time, InterpolationType p_interp, bool p_loop_wrap, bool *p_ok, bool p_backward = false) const;
template <class T>
- _FORCE_INLINE_ void _track_get_key_indices_in_range(const Vector<T> &p_array, double from_time, double to_time, List<int> *p_indices) const;
-
- _FORCE_INLINE_ void _value_track_get_key_indices_in_range(const ValueTrack *vt, double from_time, double to_time, List<int> *p_indices) const;
- _FORCE_INLINE_ void _method_track_get_key_indices_in_range(const MethodTrack *mt, double from_time, double to_time, List<int> *p_indices) const;
+ _FORCE_INLINE_ void _track_get_key_indices_in_range(const Vector<T> &p_array, double from_time, double to_time, List<int> *p_indices, bool p_is_backward) const;
double length = 1.0;
real_t step = 0.1;
LoopMode loop_mode = LOOP_NONE;
- int pingponged = 0;
/* Animation compression page format (version 1):
*
@@ -345,27 +352,6 @@ private:
// bind helpers
private:
- Vector<int> _value_track_get_key_indices(int p_track, double p_time, double p_delta) const {
- List<int> idxs;
- value_track_get_key_indices(p_track, p_time, p_delta, &idxs);
- Vector<int> idxr;
-
- for (int &E : idxs) {
- idxr.push_back(E);
- }
- return idxr;
- }
- Vector<int> _method_track_get_key_indices(int p_track, double p_time, double p_delta) const {
- List<int> idxs;
- method_track_get_key_indices(p_track, p_time, p_delta, &idxs);
- Vector<int> idxr;
-
- for (int &E : idxs) {
- idxr.push_back(E);
- }
- return idxr;
- }
-
bool _float_track_optimize_key(const TKey<float> t0, const TKey<float> t1, const TKey<float> t2, real_t p_allowed_velocity_err, real_t p_allowed_precision_error);
bool _vector2_track_optimize_key(const TKey<Vector2> t0, const TKey<Vector2> t1, const TKey<Vector2> t2, real_t p_alowed_velocity_err, real_t p_allowed_angular_error, real_t p_allowed_precision_error);
bool _vector3_track_optimize_key(const TKey<Vector3> t0, const TKey<Vector3> t1, const TKey<Vector3> t2, real_t p_alowed_velocity_err, real_t p_allowed_angular_error, real_t p_allowed_precision_error);
@@ -412,7 +398,7 @@ public:
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);
- int track_find_key(int p_track, double p_time, bool p_exact = false) const;
+ int track_find_key(int p_track, double p_time, FindMode p_find_mode = FIND_MODE_NEAREST) const;
void track_remove_key(int p_track, int p_idx);
void track_remove_key_at_time(int p_track, double p_time);
int track_get_key_count(int p_track) const;
@@ -470,17 +456,15 @@ public:
bool track_get_interpolation_loop_wrap(int p_track) const;
Variant value_track_interpolate(int p_track, double p_time) const;
- void value_track_get_key_indices(int p_track, double p_time, double p_delta, List<int> *p_indices, int p_pingponged = 0) const;
void value_track_set_update_mode(int p_track, UpdateMode p_mode);
UpdateMode value_track_get_update_mode(int p_track) const;
- void method_track_get_key_indices(int p_track, double p_time, double p_delta, List<int> *p_indices, int p_pingponged = 0) const;
Vector<Variant> method_track_get_params(int p_track, int p_key_idx) const;
StringName method_track_get_name(int p_track, int p_key_idx) const;
void copy_track(int p_track, Ref<Animation> p_to_animation);
- void track_get_key_indices_in_range(int p_track, double p_time, double p_delta, List<int> *p_indices, int p_pingponged = 0) const;
+ void track_get_key_indices_in_range(int p_track, double p_time, double p_delta, List<int> *p_indices, Animation::LoopedFlag p_looped_flag = Animation::LOOPED_FLAG_NONE) const;
void set_length(real_t p_length);
real_t get_length() const;
@@ -510,6 +494,8 @@ VARIANT_ENUM_CAST(Animation::TrackType);
VARIANT_ENUM_CAST(Animation::InterpolationType);
VARIANT_ENUM_CAST(Animation::UpdateMode);
VARIANT_ENUM_CAST(Animation::LoopMode);
+VARIANT_ENUM_CAST(Animation::LoopedFlag);
+VARIANT_ENUM_CAST(Animation::FindMode);
#ifdef TOOLS_ENABLED
VARIANT_ENUM_CAST(Animation::HandleMode);
VARIANT_ENUM_CAST(Animation::HandleSetMode);
diff --git a/scene/resources/animation_library.cpp b/scene/resources/animation_library.cpp
index 427d418551..b37bfbae62 100644
--- a/scene/resources/animation_library.cpp
+++ b/scene/resources/animation_library.cpp
@@ -52,11 +52,13 @@ Error AnimationLibrary::add_animation(const StringName &p_name, const Ref<Animat
ERR_FAIL_COND_V(p_animation.is_null(), ERR_INVALID_PARAMETER);
if (animations.has(p_name)) {
+ animations.get(p_name)->disconnect(SNAME("changed"), callable_mp(this, &AnimationLibrary::_animation_changed));
animations.erase(p_name);
emit_signal(SNAME("animation_removed"), p_name);
}
animations.insert(p_name, p_animation);
+ animations.get(p_name)->connect(SNAME("changed"), callable_mp(this, &AnimationLibrary::_animation_changed).bind(p_name));
emit_signal(SNAME("animation_added"), p_name);
notify_property_list_changed();
return OK;
@@ -65,6 +67,7 @@ Error AnimationLibrary::add_animation(const StringName &p_name, const Ref<Animat
void AnimationLibrary::remove_animation(const StringName &p_name) {
ERR_FAIL_COND_MSG(!animations.has(p_name), vformat("Animation not found: %s.", p_name));
+ animations.get(p_name)->disconnect(SNAME("changed"), callable_mp(this, &AnimationLibrary::_animation_changed));
animations.erase(p_name);
emit_signal(SNAME("animation_removed"), p_name);
notify_property_list_changed();
@@ -75,6 +78,8 @@ void AnimationLibrary::rename_animation(const StringName &p_name, const StringNa
ERR_FAIL_COND_MSG(!is_valid_animation_name(p_new_name), "Invalid animation name: '" + String(p_new_name) + "'.");
ERR_FAIL_COND_MSG(animations.has(p_new_name), vformat("Animation name \"%s\" already exists in library.", p_new_name));
+ animations.get(p_name)->disconnect(SNAME("changed"), callable_mp(this, &AnimationLibrary::_animation_changed));
+ animations.get(p_name)->connect(SNAME("changed"), callable_mp(this, &AnimationLibrary::_animation_changed).bind(p_new_name));
animations.insert(p_new_name, animations[p_name]);
animations.erase(p_name);
emit_signal(SNAME("animation_renamed"), p_name, p_new_name);
@@ -100,6 +105,10 @@ TypedArray<StringName> AnimationLibrary::_get_animation_list() const {
return ret;
}
+void AnimationLibrary::_animation_changed(const StringName &p_name) {
+ emit_signal(SNAME("animation_changed"), p_name);
+}
+
void AnimationLibrary::get_animation_list(List<StringName> *p_animations) const {
List<StringName> anims;
@@ -115,6 +124,9 @@ void AnimationLibrary::get_animation_list(List<StringName> *p_animations) const
}
void AnimationLibrary::_set_data(const Dictionary &p_data) {
+ for (KeyValue<StringName, Ref<Animation>> &K : animations) {
+ K.value->disconnect(SNAME("changed"), callable_mp(this, &AnimationLibrary::_animation_changed));
+ }
animations.clear();
List<Variant> keys;
p_data.get_key_list(&keys);
@@ -146,6 +158,7 @@ void AnimationLibrary::_bind_methods() {
ADD_SIGNAL(MethodInfo("animation_added", PropertyInfo(Variant::STRING_NAME, "name")));
ADD_SIGNAL(MethodInfo("animation_removed", PropertyInfo(Variant::STRING_NAME, "name")));
ADD_SIGNAL(MethodInfo("animation_renamed", PropertyInfo(Variant::STRING_NAME, "name"), PropertyInfo(Variant::STRING_NAME, "to_name")));
+ ADD_SIGNAL(MethodInfo("animation_changed", PropertyInfo(Variant::STRING_NAME, "name")));
}
AnimationLibrary::AnimationLibrary() {
}
diff --git a/scene/resources/animation_library.h b/scene/resources/animation_library.h
index d63807b6d7..54bd641b6d 100644
--- a/scene/resources/animation_library.h
+++ b/scene/resources/animation_library.h
@@ -42,6 +42,8 @@ class AnimationLibrary : public Resource {
TypedArray<StringName> _get_animation_list() const;
+ void _animation_changed(const StringName &p_name);
+
friend class AnimationPlayer; //for faster access
HashMap<StringName, Ref<Animation>> animations;
diff --git a/scene/resources/bit_map.cpp b/scene/resources/bit_map.cpp
index 1b06e09bb8..86b806bc4f 100644
--- a/scene/resources/bit_map.cpp
+++ b/scene/resources/bit_map.cpp
@@ -169,7 +169,7 @@ Dictionary BitMap::_get_data() const {
return d;
}
-Vector<Vector2> BitMap::_march_square(const Rect2i &p_rect, const Point2i &p_start) const {
+Vector<Vector<Vector2>> BitMap::_march_square(const Rect2i &p_rect, const Point2i &p_start) const {
int stepx = 0;
int stepy = 0;
int prevx = 0;
@@ -179,9 +179,17 @@ Vector<Vector2> BitMap::_march_square(const Rect2i &p_rect, const Point2i &p_sta
int curx = startx;
int cury = starty;
unsigned int count = 0;
- HashSet<Point2i> case9s;
- HashSet<Point2i> case6s;
+
+ HashMap<Point2i, int> cross_map;
+
Vector<Vector2> _points;
+ int points_size = 0;
+
+ Vector<Vector<Vector2>> ret;
+
+ // Add starting entry at start of return.
+ ret.resize(1);
+
do {
int sv = 0;
{ // Square value
@@ -202,7 +210,7 @@ Vector<Vector2> BitMap::_march_square(const Rect2i &p_rect, const Point2i &p_sta
sv += (p_rect.has_point(bl) && get_bitv(bl)) ? 4 : 0;
Point2i br = Point2i(curx, cury);
sv += (p_rect.has_point(br) && get_bitv(br)) ? 8 : 0;
- ERR_FAIL_COND_V(sv == 0 || sv == 15, Vector<Vector2>());
+ ERR_FAIL_COND_V(sv == 0 || sv == 15, Vector<Vector<Vector2>>());
}
switch (sv) {
@@ -266,70 +274,95 @@ Vector<Vector2> BitMap::_march_square(const Rect2i &p_rect, const Point2i &p_sta
stepy = 0;
break;
case 9:
- /*
+ /* Going DOWN if coming from the LEFT, otherwise go UP.
+ 9
+---+---+
| 1 | |
+---+---+
| | 8 |
+---+---+
- this should normally go UP, but if we already been here, we go down
*/
- if (case9s.has(Point2i(curx, cury))) {
- //found, so we go down, and delete from case9s;
+
+ if (prevx == 1) {
stepx = 0;
stepy = 1;
- case9s.erase(Point2i(curx, cury));
} else {
- //not found, we go up, and add to case9s;
stepx = 0;
stepy = -1;
- case9s.insert(Point2i(curx, cury));
}
break;
case 6:
- /*
+ /* Going RIGHT if coming from BELOW, otherwise go LEFT.
6
+---+---+
| | 2 |
+---+---+
| 4 | |
+---+---+
- this normally go RIGHT, but if it's coming from RIGHT, it should go LEFT
*/
- if (case6s.has(Point2i(curx, cury))) {
- //found, so we go left, and delete from case6s;
- stepx = -1;
+
+ if (prevy == -1) {
+ stepx = 1;
stepy = 0;
- case6s.erase(Point2i(curx, cury));
} else {
- //not found, we go right, and add to case6s;
- stepx = 1;
+ stepx = -1;
stepy = 0;
- case6s.insert(Point2i(curx, cury));
}
break;
default:
ERR_PRINT("this shouldn't happen.");
}
+
+ // Handle crossing points.
+ if (sv == 6 || sv == 9) {
+ const Point2i cur_pos(curx, cury);
+
+ // Find if this point has occurred before.
+ if (HashMap<Point2i, int>::Iterator found = cross_map.find(cur_pos)) {
+ // Add points after the previous crossing to the result.
+ ret.push_back(_points.slice(found->value + 1, points_size));
+
+ // Remove points after crossing point.
+ points_size = found->value + 1;
+
+ // Erase trailing map elements.
+ while (cross_map.last() != found) {
+ cross_map.remove(cross_map.last());
+ }
+
+ cross_map.erase(cur_pos);
+ } else {
+ // Add crossing point to map.
+ cross_map.insert(cur_pos, points_size - 1);
+ }
+ }
+
// Small optimization:
// If the previous direction is same as the current direction,
// then we should modify the last vector to current.
curx += stepx;
cury += stepy;
if (stepx == prevx && stepy == prevy) {
- _points.write[_points.size() - 1].x = (float)(curx - p_rect.position.x);
- _points.write[_points.size() - 1].y = (float)(cury + p_rect.position.y);
+ _points.set(points_size - 1, Vector2(curx, cury) - p_rect.position);
} else {
- _points.push_back(Vector2((float)(curx - p_rect.position.x), (float)(cury + p_rect.position.y)));
+ _points.resize(MAX(points_size + 1, _points.size()));
+ _points.set(points_size, Vector2(curx, cury) - p_rect.position);
+ points_size++;
}
count++;
prevx = stepx;
prevy = stepy;
- ERR_FAIL_COND_V((int)count > width * height, _points);
+ ERR_FAIL_COND_V((int)count > width * height, Vector<Vector<Vector2>>());
} while (curx != startx || cury != starty);
- return _points;
+
+ // Add remaining points to result.
+ _points.resize(points_size);
+
+ ret.set(0, _points);
+
+ return ret;
}
static float perpendicular_distance(const Vector2 &i, const Vector2 &start, const Vector2 &end) {
@@ -442,7 +475,7 @@ static void fill_bits(const BitMap *p_src, Ref<BitMap> &p_map, const Point2i &p_
for (int j = next_j; j <= pos.y + 1; j++) {
if (popped) {
// The next loop over j must start normally.
- next_j = pos.y;
+ next_j = pos.y - 1;
popped = false;
// Skip because an iteration was already executed with current counter values.
continue;
@@ -486,13 +519,10 @@ static void fill_bits(const BitMap *p_src, Ref<BitMap> &p_map, const Point2i &p_
}
}
} while (reenter || popped);
-
- print_verbose("BitMap: Max stack size: " + itos(stack.size()));
}
Vector<Vector<Vector2>> BitMap::clip_opaque_to_polygons(const Rect2i &p_rect, float p_epsilon) const {
Rect2i r = Rect2i(0, 0, width, height).intersection(p_rect);
- print_verbose("BitMap: Rect: " + r);
Point2i from;
Ref<BitMap> fill;
@@ -505,17 +535,16 @@ Vector<Vector<Vector2>> BitMap::clip_opaque_to_polygons(const Rect2i &p_rect, fl
if (!fill->get_bit(j, i) && get_bit(j, i)) {
fill_bits(this, fill, Point2i(j, i), r);
- Vector<Vector2> polygon = _march_square(r, Point2i(j, i));
- print_verbose("BitMap: Pre reduce: " + itos(polygon.size()));
- polygon = reduce(polygon, r, p_epsilon);
- print_verbose("BitMap: Post reduce: " + itos(polygon.size()));
+ for (Vector<Vector2> polygon : _march_square(r, Point2i(j, i))) {
+ polygon = reduce(polygon, r, p_epsilon);
- if (polygon.size() < 3) {
- print_verbose("Invalid polygon, skipped");
- continue;
- }
+ if (polygon.size() < 3) {
+ print_verbose("Invalid polygon, skipped");
+ continue;
+ }
- polygons.push_back(polygon);
+ polygons.push_back(polygon);
+ }
}
}
}
diff --git a/scene/resources/bit_map.h b/scene/resources/bit_map.h
index 291ed8c4d0..0ec5772fd1 100644
--- a/scene/resources/bit_map.h
+++ b/scene/resources/bit_map.h
@@ -46,7 +46,7 @@ class BitMap : public Resource {
int width = 0;
int height = 0;
- Vector<Vector2> _march_square(const Rect2i &p_rect, const Point2i &p_start) const;
+ Vector<Vector<Vector2>> _march_square(const Rect2i &p_rect, const Point2i &p_start) const;
TypedArray<PackedVector2Array> _opaque_to_polygons_bind(const Rect2i &p_rect, float p_epsilon) const;
diff --git a/scene/resources/bone_map.cpp b/scene/resources/bone_map.cpp
index dfaf82f36a..5698e61004 100644
--- a/scene/resources/bone_map.cpp
+++ b/scene/resources/bone_map.cpp
@@ -93,7 +93,7 @@ void BoneMap::set_skeleton_bone_name(StringName p_profile_bone_name, const Strin
}
StringName BoneMap::find_profile_bone_name(StringName p_skeleton_bone_name) const {
- StringName profile_bone_name = StringName();
+ StringName profile_bone_name;
HashMap<StringName, StringName>::ConstIterator E = bone_map.begin();
while (E) {
if (E->value == p_skeleton_bone_name) {
diff --git a/scene/resources/camera_attributes.cpp b/scene/resources/camera_attributes.cpp
index 3c322f32b6..8e4876e01f 100644
--- a/scene/resources/camera_attributes.cpp
+++ b/scene/resources/camera_attributes.cpp
@@ -120,7 +120,7 @@ void CameraAttributes::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_auto_exposure_scale", "exposure_grey"), &CameraAttributes::set_auto_exposure_scale);
ClassDB::bind_method(D_METHOD("get_auto_exposure_scale"), &CameraAttributes::get_auto_exposure_scale);
- ADD_GROUP("Exposure", "exposure");
+ ADD_GROUP("Exposure", "exposure_");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "exposure_sensitivity", PROPERTY_HINT_RANGE, "0.1,32000.0,0.1,suffix:ISO"), "set_exposure_sensitivity", "get_exposure_sensitivity");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "exposure_multiplier", PROPERTY_HINT_RANGE, "0.0,2048.0,0.001"), "set_exposure_multiplier", "get_exposure_multiplier");
@@ -472,7 +472,7 @@ void CameraAttributesPhysical::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "frustum_near", PROPERTY_HINT_RANGE, "0.001,10,0.001,or_greater,exp,suffix:m"), "set_near", "get_near");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "frustum_far", PROPERTY_HINT_RANGE, "0.01,4000,0.01,or_greater,exp,suffix:m"), "set_far", "get_far");
- ADD_GROUP("Exposure", "exposure");
+ ADD_GROUP("Exposure", "exposure_");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "exposure_aperture", PROPERTY_HINT_RANGE, "0.5,64.0,0.01,exp,suffix:f-stop"), "set_aperture", "get_aperture");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "exposure_shutter_speed", PROPERTY_HINT_RANGE, "0.1,8000.0,0.001,suffix:1/s"), "set_shutter_speed", "get_shutter_speed");
diff --git a/scene/resources/curve.cpp b/scene/resources/curve.cpp
index eda9af9dde..be9c0dc725 100644
--- a/scene/resources/curve.cpp
+++ b/scene/resources/curve.cpp
@@ -31,6 +31,7 @@
#include "curve.h"
#include "core/core_string_names.h"
+#include "core/math/math_funcs.h"
const char *Curve::SIGNAL_RANGE_CHANGED = "range_changed";
@@ -340,7 +341,7 @@ real_t Curve::sample_local_nocheck(int p_index, real_t p_local_offset) const {
const Point a = _points[p_index];
const Point b = _points[p_index + 1];
- /* Cubic bezier
+ /* Cubic bézier
*
* ac-----bc
* / \
@@ -773,6 +774,35 @@ void Curve2D::_bake_segment2d(RBMap<real_t, Vector2> &r_bake, real_t p_begin, re
}
}
+void Curve2D::_bake_segment2d_even_length(RBMap<real_t, Vector2> &r_bake, real_t p_begin, real_t p_end, const Vector2 &p_a, const Vector2 &p_out, const Vector2 &p_b, const Vector2 &p_in, int p_depth, int p_max_depth, real_t p_length) const {
+ Vector2 beg = p_a.bezier_interpolate(p_a + p_out, p_b + p_in, p_b, p_begin);
+ Vector2 end = p_a.bezier_interpolate(p_a + p_out, p_b + p_in, p_b, p_end);
+
+ real_t length = beg.distance_to(end);
+
+ if (length > p_length && p_depth < p_max_depth) {
+ real_t mp = (p_begin + p_end) * 0.5;
+ Vector2 mid = p_a.bezier_interpolate(p_a + p_out, p_b + p_in, p_b, mp);
+ r_bake[mp] = mid;
+
+ _bake_segment2d_even_length(r_bake, p_begin, mp, p_a, p_out, p_b, p_in, p_depth + 1, p_max_depth, p_length);
+ _bake_segment2d_even_length(r_bake, mp, p_end, p_a, p_out, p_b, p_in, p_depth + 1, p_max_depth, p_length);
+ }
+}
+
+Vector2 Curve2D::_calculate_tangent(const Vector2 &p_begin, const Vector2 &p_control_1, const Vector2 &p_control_2, const Vector2 &p_end, const real_t p_t) {
+ // Handle corner cases.
+ if (Math::is_zero_approx(p_t - 0.0f) && p_control_1.is_equal_approx(p_begin)) {
+ return (p_end - p_begin).normalized();
+ }
+
+ if (Math::is_zero_approx(p_t - 1.0f) && p_control_2.is_equal_approx(p_end)) {
+ return (p_end - p_begin).normalized();
+ }
+
+ return p_begin.bezier_derivative(p_control_1, p_control_2, p_end, p_t).normalized();
+}
+
void Curve2D::_bake() const {
if (!baked_cache_dirty) {
return;
@@ -784,94 +814,62 @@ void Curve2D::_bake() const {
if (points.size() == 0) {
baked_point_cache.clear();
baked_dist_cache.clear();
+ baked_forward_vector_cache.clear();
return;
}
if (points.size() == 1) {
baked_point_cache.resize(1);
baked_point_cache.set(0, points[0].position);
-
baked_dist_cache.resize(1);
baked_dist_cache.set(0, 0.0);
+ baked_forward_vector_cache.resize(1);
+ baked_forward_vector_cache.set(0, Vector2(0.0, 0.1));
+
return;
}
- Vector2 position = points[0].position;
- real_t dist = 0.0;
-
- List<Vector2> pointlist;
- List<real_t> distlist;
-
- // Start always from origin.
- pointlist.push_back(position);
- distlist.push_back(0.0);
-
- for (int i = 0; i < points.size() - 1; i++) {
- real_t step = 0.1; // at least 10 substeps ought to be enough?
- real_t p = 0.0;
-
- while (p < 1.0) {
- real_t np = p + step;
- if (np > 1.0) {
- np = 1.0;
- }
-
- Vector2 npp = points[i].position.bezier_interpolate(points[i].position + points[i].out, points[i + 1].position + points[i + 1].in, points[i + 1].position, np);
- real_t d = position.distance_to(npp);
-
- if (d > bake_interval) {
- // OK! between P and NP there _has_ to be Something, let's go searching!
-
- int iterations = 10; //lots of detail!
-
- real_t low = p;
- real_t hi = np;
- real_t mid = low + (hi - low) * 0.5;
+ // Tessellate curve to (almost) even length segments
+ {
+ Vector<RBMap<real_t, Vector2>> midpoints = _tessellate_even_length(10, bake_interval);
- for (int j = 0; j < iterations; j++) {
- npp = points[i].position.bezier_interpolate(points[i].position + points[i].out, points[i + 1].position + points[i + 1].in, points[i + 1].position, mid);
- d = position.distance_to(npp);
-
- if (bake_interval < d) {
- hi = mid;
- } else {
- low = mid;
- }
- mid = low + (hi - low) * 0.5;
- }
-
- position = npp;
- p = mid;
- dist += d;
-
- pointlist.push_back(position);
- distlist.push_back(dist);
- } else {
- p = np;
- }
+ int pc = 1;
+ for (int i = 0; i < points.size() - 1; i++) {
+ pc++;
+ pc += midpoints[i].size();
}
- Vector2 npp = points[i + 1].position;
- real_t d = position.distance_to(npp);
-
- position = npp;
- dist += d;
+ baked_point_cache.resize(pc);
+ baked_dist_cache.resize(pc);
+ baked_forward_vector_cache.resize(pc);
- pointlist.push_back(position);
- distlist.push_back(dist);
- }
+ Vector2 *bpw = baked_point_cache.ptrw();
+ Vector2 *bfw = baked_forward_vector_cache.ptrw();
- baked_max_ofs = dist;
+ // Collect positions and sample tilts and tangents for each baked points.
+ bpw[0] = points[0].position;
+ bfw[0] = _calculate_tangent(points[0].position, points[0].position + points[0].out, points[1].position + points[1].in, points[1].position, 0.0);
+ int pidx = 0;
- baked_point_cache.resize(pointlist.size());
- baked_dist_cache.resize(distlist.size());
+ for (int i = 0; i < points.size() - 1; i++) {
+ for (const KeyValue<real_t, Vector2> &E : midpoints[i]) {
+ pidx++;
+ bpw[pidx] = E.value;
+ bfw[pidx] = _calculate_tangent(points[i].position, points[i].position + points[i].out, points[i + 1].position + points[i + 1].in, points[i + 1].position, E.key);
+ }
- Vector2 *w = baked_point_cache.ptrw();
- real_t *wd = baked_dist_cache.ptrw();
+ pidx++;
+ bpw[pidx] = points[i + 1].position;
+ bfw[pidx] = _calculate_tangent(points[i].position, points[i].position + points[i].out, points[i + 1].position + points[i + 1].in, points[i + 1].position, 1.0);
+ }
- for (int i = 0; i < pointlist.size(); i++) {
- w[i] = pointlist[i];
- wd[i] = distlist[i];
+ // Recalculate the baked distances.
+ real_t *bdw = baked_dist_cache.ptrw();
+ bdw[0] = 0.0;
+ for (int i = 0; i < pc - 1; i++) {
+ bdw[i + 1] = bdw[i] + bpw[i].distance_to(bpw[i + 1]);
+ }
+ baked_max_ofs = bdw[pc - 1];
}
}
@@ -883,27 +881,15 @@ real_t Curve2D::get_baked_length() const {
return baked_max_ofs;
}
-Vector2 Curve2D::sample_baked(real_t p_offset, bool p_cubic) const {
- if (baked_cache_dirty) {
- _bake();
- }
+Curve2D::Interval Curve2D::_find_interval(real_t p_offset) const {
+ Interval interval = {
+ -1,
+ 0.0
+ };
+ ERR_FAIL_COND_V_MSG(baked_cache_dirty, interval, "Backed cache is dirty");
- // Validate: Curve may not have baked points.
int pc = baked_point_cache.size();
- ERR_FAIL_COND_V_MSG(pc == 0, Vector2(), "No points in Curve2D.");
-
- if (pc == 1) {
- return baked_point_cache.get(0);
- }
-
- const Vector2 *r = baked_point_cache.ptr();
-
- if (p_offset < 0) {
- return r[0];
- }
- if (p_offset >= baked_max_ofs) {
- return r[pc - 1];
- }
+ ERR_FAIL_COND_V_MSG(pc < 2, interval, "Less than two points in cache");
int start = 0;
int end = pc;
@@ -923,9 +909,27 @@ Vector2 Curve2D::sample_baked(real_t p_offset, bool p_cubic) const {
real_t offset_end = baked_dist_cache[idx + 1];
real_t idx_interval = offset_end - offset_begin;
- ERR_FAIL_COND_V_MSG(p_offset < offset_begin || p_offset > offset_end, Vector2(), "Couldn't find baked segment.");
+ ERR_FAIL_COND_V_MSG(p_offset < offset_begin || p_offset > offset_end, interval, "Offset out of range.");
+
+ interval.idx = idx;
+ if (idx_interval < FLT_EPSILON) {
+ interval.frac = 0.5; // For a very short interval, 0.5 is a reasonable choice.
+ ERR_FAIL_V_MSG(interval, "Zero length interval.");
+ }
+
+ interval.frac = (p_offset - offset_begin) / idx_interval;
+ return interval;
+}
- real_t frac = (p_offset - offset_begin) / idx_interval;
+Vector2 Curve2D::_sample_baked(Interval p_interval, bool p_cubic) const {
+ // Assuming p_interval is valid.
+ ERR_FAIL_INDEX_V_MSG(p_interval.idx, baked_point_cache.size(), Vector2(), "Invalid interval");
+
+ int idx = p_interval.idx;
+ real_t frac = p_interval.frac;
+
+ const Vector2 *r = baked_point_cache.ptr();
+ int pc = baked_point_cache.size();
if (p_cubic) {
Vector2 pre = idx > 0 ? r[idx - 1] : r[idx];
@@ -936,44 +940,70 @@ Vector2 Curve2D::sample_baked(real_t p_offset, bool p_cubic) const {
}
}
-Transform2D Curve2D::sample_baked_with_rotation(real_t p_offset, bool p_cubic, bool p_loop, real_t p_lookahead) const {
- real_t path_length = get_baked_length(); // Ensure baked.
- ERR_FAIL_COND_V_MSG(path_length == 0, Transform2D(), "Length of Curve2D is 0.");
+Transform2D Curve2D::_sample_posture(Interval p_interval) const {
+ // Assuming that p_interval is valid.
+ ERR_FAIL_INDEX_V_MSG(p_interval.idx, baked_point_cache.size(), Transform2D(), "Invalid interval");
- Vector2 pos = sample_baked(p_offset, p_cubic);
+ int idx = p_interval.idx;
+ real_t frac = p_interval.frac;
- real_t ahead = p_offset + p_lookahead;
+ Vector2 forward_begin = baked_forward_vector_cache[idx];
+ Vector2 forward_end = baked_forward_vector_cache[idx + 1];
- if (p_loop && ahead >= path_length) {
- // If our lookahead will loop, we need to check if the path is closed.
- int point_count = get_point_count();
- if (point_count > 0) {
- Vector2 start_point = get_point_position(0);
- Vector2 end_point = get_point_position(point_count - 1);
- if (start_point == end_point) {
- // Since the path is closed we want to 'smooth off'
- // the corner at the start/end.
- // So we wrap the lookahead back round.
- ahead = Math::fmod(ahead, path_length);
- }
- }
+ // Build frames at both ends of the interval, then interpolate.
+ const Vector2 forward = forward_begin.slerp(forward_end, frac).normalized();
+ const Vector2 side = Vector2(-forward.y, forward.x);
+
+ return Transform2D(side, forward, Vector2(0.0, 0.0));
+}
+
+Vector2 Curve2D::sample_baked(real_t p_offset, bool p_cubic) const {
+ if (baked_cache_dirty) {
+ _bake();
}
- Vector2 ahead_pos = sample_baked(ahead, p_cubic);
+ // Validate: Curve may not have baked points.
+ int pc = baked_point_cache.size();
+ ERR_FAIL_COND_V_MSG(pc == 0, Vector2(), "No points in Curve2D.");
- Vector2 tangent_to_curve;
- if (ahead_pos == pos) {
- // This will happen at the end of non-looping or non-closed paths.
- // We'll try a look behind instead, in order to get a meaningful angle.
- tangent_to_curve =
- (pos - sample_baked(p_offset - p_lookahead, p_cubic)).normalized();
- } else {
- tangent_to_curve = (ahead_pos - pos).normalized();
+ if (pc == 1) {
+ return baked_point_cache[0];
}
- Vector2 normal_of_curve = -tangent_to_curve.orthogonal();
+ p_offset = CLAMP(p_offset, 0.0, get_baked_length()); // PathFollower implement wrapping logic.
- return Transform2D(normal_of_curve, tangent_to_curve, pos);
+ Curve2D::Interval interval = _find_interval(p_offset);
+ return _sample_baked(interval, p_cubic);
+}
+
+Transform2D Curve2D::sample_baked_with_rotation(real_t p_offset, bool p_cubic) const {
+ if (baked_cache_dirty) {
+ _bake();
+ }
+
+ // Validate: Curve may not have baked points.
+ const int point_count = baked_point_cache.size();
+ ERR_FAIL_COND_V_MSG(point_count == 0, Transform2D(), "No points in Curve3D.");
+
+ if (point_count == 1) {
+ Transform2D t;
+ t.set_origin(baked_point_cache.get(0));
+ ERR_FAIL_V_MSG(t, "Only 1 point in Curve2D.");
+ }
+
+ p_offset = CLAMP(p_offset, 0.0, get_baked_length()); // PathFollower implement wrapping logic.
+
+ // 0. Find interval for all sampling steps.
+ Curve2D::Interval interval = _find_interval(p_offset);
+
+ // 1. Sample position.
+ Vector2 pos = _sample_baked(interval, p_cubic);
+
+ // 2. Sample rotation frame.
+ Transform2D frame = _sample_posture(interval);
+ frame.set_origin(pos);
+
+ return frame;
}
PackedVector2Array Curve2D::get_baked_points() const {
@@ -1014,10 +1044,11 @@ Vector2 Curve2D::get_closest_point(const Vector2 &p_to_point) const {
real_t nearest_dist = -1.0f;
for (int i = 0; i < pc - 1; i++) {
+ const real_t interval = baked_dist_cache[i + 1] - baked_dist_cache[i];
Vector2 origin = r[i];
- Vector2 direction = (r[i + 1] - origin) / bake_interval;
+ Vector2 direction = (r[i + 1] - origin) / interval;
- real_t d = CLAMP((p_to_point - origin).dot(direction), 0.0f, bake_interval);
+ real_t d = CLAMP((p_to_point - origin).dot(direction), 0.0f, interval);
Vector2 proj = origin + direction * d;
real_t dist = proj.distance_squared_to(p_to_point);
@@ -1053,10 +1084,13 @@ real_t Curve2D::get_closest_offset(const Vector2 &p_to_point) const {
real_t offset = 0.0f;
for (int i = 0; i < pc - 1; i++) {
+ offset = baked_dist_cache[i];
+
+ const real_t interval = baked_dist_cache[i + 1] - baked_dist_cache[i];
Vector2 origin = r[i];
- Vector2 direction = (r[i + 1] - origin) / bake_interval;
+ Vector2 direction = (r[i + 1] - origin) / interval;
- real_t d = CLAMP((p_to_point - origin).dot(direction), 0.0f, bake_interval);
+ real_t d = CLAMP((p_to_point - origin).dot(direction), 0.0f, interval);
Vector2 proj = origin + direction * d;
real_t dist = proj.distance_squared_to(p_to_point);
@@ -1065,8 +1099,6 @@ real_t Curve2D::get_closest_offset(const Vector2 &p_to_point) const {
nearest = offset + d;
nearest_dist = dist;
}
-
- offset += bake_interval;
}
return nearest;
@@ -1146,6 +1178,50 @@ PackedVector2Array Curve2D::tessellate(int p_max_stages, real_t p_tolerance) con
return tess;
}
+Vector<RBMap<real_t, Vector2>> Curve2D::_tessellate_even_length(int p_max_stages, real_t p_length) const {
+ Vector<RBMap<real_t, Vector2>> midpoints;
+ ERR_FAIL_COND_V_MSG(points.size() < 2, midpoints, "Curve must have at least 2 control point");
+
+ midpoints.resize(points.size() - 1);
+
+ for (int i = 0; i < points.size() - 1; i++) {
+ _bake_segment2d_even_length(midpoints.write[i], 0, 1, points[i].position, points[i].out, points[i + 1].position, points[i + 1].in, 0, p_max_stages, p_length);
+ }
+ return midpoints;
+}
+
+PackedVector2Array Curve2D::tessellate_even_length(int p_max_stages, real_t p_length) const {
+ PackedVector2Array tess;
+
+ Vector<RBMap<real_t, Vector2>> midpoints = _tessellate_even_length(p_max_stages, p_length);
+ if (midpoints.size() == 0) {
+ return tess;
+ }
+
+ int pc = 1;
+ for (int i = 0; i < points.size() - 1; i++) {
+ pc++;
+ pc += midpoints[i].size();
+ }
+
+ tess.resize(pc);
+ Vector2 *bpw = tess.ptrw();
+ bpw[0] = points[0].position;
+ int pidx = 0;
+
+ for (int i = 0; i < points.size() - 1; i++) {
+ for (const KeyValue<real_t, Vector2> &E : midpoints[i]) {
+ pidx++;
+ bpw[pidx] = E.value;
+ }
+
+ pidx++;
+ bpw[pidx] = points[i + 1].position;
+ }
+
+ return tess;
+}
+
bool Curve2D::_set(const StringName &p_name, const Variant &p_value) {
Vector<String> components = String(p_name).split("/", true, 2);
if (components.size() >= 2 && components[0].begins_with("point_") && components[0].trim_prefix("point_").is_valid_int()) {
@@ -1223,12 +1299,13 @@ void Curve2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_bake_interval"), &Curve2D::get_bake_interval);
ClassDB::bind_method(D_METHOD("get_baked_length"), &Curve2D::get_baked_length);
- ClassDB::bind_method(D_METHOD("sample_baked", "offset", "cubic"), &Curve2D::sample_baked, DEFVAL(false));
- ClassDB::bind_method(D_METHOD("sample_baked_with_rotation", "offset", "cubic", "loop", "lookahead"), &Curve2D::sample_baked_with_rotation, DEFVAL(false), DEFVAL(true), DEFVAL(4.0));
+ ClassDB::bind_method(D_METHOD("sample_baked", "offset", "cubic"), &Curve2D::sample_baked, DEFVAL(0.0), DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("sample_baked_with_rotation", "offset", "cubic"), &Curve2D::sample_baked_with_rotation, DEFVAL(0.0), DEFVAL(false));
ClassDB::bind_method(D_METHOD("get_baked_points"), &Curve2D::get_baked_points);
ClassDB::bind_method(D_METHOD("get_closest_point", "to_point"), &Curve2D::get_closest_point);
ClassDB::bind_method(D_METHOD("get_closest_offset", "to_point"), &Curve2D::get_closest_offset);
ClassDB::bind_method(D_METHOD("tessellate", "max_stages", "tolerance_degrees"), &Curve2D::tessellate, DEFVAL(5), DEFVAL(4));
+ ClassDB::bind_method(D_METHOD("tessellate_even_length", "max_stages", "tolerance_length"), &Curve2D::tessellate_even_length, DEFVAL(5), DEFVAL(20.0));
ClassDB::bind_method(D_METHOD("_get_data"), &Curve2D::_get_data);
ClassDB::bind_method(D_METHOD("_set_data", "data"), &Curve2D::_set_data);
@@ -1402,6 +1479,35 @@ void Curve3D::_bake_segment3d(RBMap<real_t, Vector3> &r_bake, real_t p_begin, re
}
}
+void Curve3D::_bake_segment3d_even_length(RBMap<real_t, Vector3> &r_bake, real_t p_begin, real_t p_end, const Vector3 &p_a, const Vector3 &p_out, const Vector3 &p_b, const Vector3 &p_in, int p_depth, int p_max_depth, real_t p_length) const {
+ Vector3 beg = p_a.bezier_interpolate(p_a + p_out, p_b + p_in, p_b, p_begin);
+ Vector3 end = p_a.bezier_interpolate(p_a + p_out, p_b + p_in, p_b, p_end);
+
+ real_t length = beg.distance_to(end);
+
+ if (length > p_length && p_depth < p_max_depth) {
+ real_t mp = (p_begin + p_end) * 0.5;
+ Vector3 mid = p_a.bezier_interpolate(p_a + p_out, p_b + p_in, p_b, mp);
+ r_bake[mp] = mid;
+
+ _bake_segment3d_even_length(r_bake, p_begin, mp, p_a, p_out, p_b, p_in, p_depth + 1, p_max_depth, p_length);
+ _bake_segment3d_even_length(r_bake, mp, p_end, p_a, p_out, p_b, p_in, p_depth + 1, p_max_depth, p_length);
+ }
+}
+
+Vector3 Curve3D::_calculate_tangent(const Vector3 &p_begin, const Vector3 &p_control_1, const Vector3 &p_control_2, const Vector3 &p_end, const real_t p_t) {
+ // Handle corner cases.
+ if (Math::is_zero_approx(p_t - 0.0f) && p_control_1.is_equal_approx(p_begin)) {
+ return (p_end - p_begin).normalized();
+ }
+
+ if (Math::is_zero_approx(p_t - 1.0f) && p_control_2.is_equal_approx(p_end)) {
+ return (p_end - p_begin).normalized();
+ }
+
+ return p_begin.bezier_derivative(p_control_1, p_control_2, p_end, p_t).normalized();
+}
+
void Curve3D::_bake() const {
if (!baked_cache_dirty) {
return;
@@ -1413,8 +1519,10 @@ void Curve3D::_bake() const {
if (points.size() == 0) {
baked_point_cache.clear();
baked_tilt_cache.clear();
- baked_up_vector_cache.clear();
baked_dist_cache.clear();
+
+ baked_forward_vector_cache.clear();
+ baked_up_vector_cache.clear();
return;
}
@@ -1425,10 +1533,12 @@ void Curve3D::_bake() const {
baked_tilt_cache.set(0, points[0].tilt);
baked_dist_cache.resize(1);
baked_dist_cache.set(0, 0.0);
+ baked_forward_vector_cache.resize(1);
+ baked_forward_vector_cache.set(0, Vector3(0.0, 0.0, 1.0));
if (up_vector_enabled) {
baked_up_vector_cache.resize(1);
- baked_up_vector_cache.set(0, Vector3(0, 1, 0));
+ baked_up_vector_cache.set(0, Vector3(0.0, 1.0, 0.0));
} else {
baked_up_vector_cache.clear();
}
@@ -1436,136 +1546,135 @@ void Curve3D::_bake() const {
return;
}
- Vector3 position = points[0].position;
- real_t dist = 0.0;
- List<Plane> pointlist;
- List<real_t> distlist;
-
- // Start always from origin.
- pointlist.push_back(Plane(position, points[0].tilt));
- distlist.push_back(0.0);
+ // Step 1: Tessellate curve to (almost) even length segments
+ {
+ Vector<RBMap<real_t, Vector3>> midpoints = _tessellate_even_length(10, bake_interval);
- for (int i = 0; i < points.size() - 1; i++) {
- real_t step = 0.1; // at least 10 substeps ought to be enough?
- real_t p = 0.0;
+ int pc = 1;
+ for (int i = 0; i < points.size() - 1; i++) {
+ pc++;
+ pc += midpoints[i].size();
+ }
- while (p < 1.0) {
- real_t np = p + step;
- if (np > 1.0) {
- np = 1.0;
+ baked_point_cache.resize(pc);
+ baked_tilt_cache.resize(pc);
+ baked_dist_cache.resize(pc);
+ baked_forward_vector_cache.resize(pc);
+
+ Vector3 *bpw = baked_point_cache.ptrw();
+ real_t *btw = baked_tilt_cache.ptrw();
+ Vector3 *bfw = baked_forward_vector_cache.ptrw();
+
+ // Collect positions and sample tilts and tangents for each baked points.
+ bpw[0] = points[0].position;
+ bfw[0] = _calculate_tangent(points[0].position, points[0].position + points[0].out, points[1].position + points[1].in, points[1].position, 0.0);
+ btw[0] = points[0].tilt;
+ int pidx = 0;
+
+ for (int i = 0; i < points.size() - 1; i++) {
+ for (const KeyValue<real_t, Vector3> &E : midpoints[i]) {
+ pidx++;
+ bpw[pidx] = E.value;
+ bfw[pidx] = _calculate_tangent(points[i].position, points[i].position + points[i].out, points[i + 1].position + points[i + 1].in, points[i + 1].position, E.key);
+ btw[pidx] = Math::lerp(points[i].tilt, points[i + 1].tilt, E.key);
}
- Vector3 npp = points[i].position.bezier_interpolate(points[i].position + points[i].out, points[i + 1].position + points[i + 1].in, points[i + 1].position, np);
- real_t d = position.distance_to(npp);
-
- if (d > bake_interval) {
- // OK! between P and NP there _has_ to be Something, let's go searching!
-
- int iterations = 10; //lots of detail!
-
- real_t low = p;
- real_t hi = np;
- real_t mid = low + (hi - low) * 0.5;
-
- for (int j = 0; j < iterations; j++) {
- npp = points[i].position.bezier_interpolate(points[i].position + points[i].out, points[i + 1].position + points[i + 1].in, points[i + 1].position, mid);
- d = position.distance_to(npp);
-
- if (bake_interval < d) {
- hi = mid;
- } else {
- low = mid;
- }
- mid = low + (hi - low) * 0.5;
- }
-
- position = npp;
- p = mid;
- Plane post;
- post.normal = position;
- post.d = Math::lerp(points[i].tilt, points[i + 1].tilt, mid);
- dist += d;
-
- pointlist.push_back(post);
- distlist.push_back(dist);
- } else {
- p = np;
- }
+ pidx++;
+ bpw[pidx] = points[i + 1].position;
+ bfw[pidx] = _calculate_tangent(points[i].position, points[i].position + points[i].out, points[i + 1].position + points[i + 1].in, points[i + 1].position, 1.0);
+ btw[pidx] = points[i + 1].tilt;
}
- Vector3 npp = points[i + 1].position;
- real_t d = position.distance_to(npp);
-
- position = npp;
- Plane post;
- post.normal = position;
- post.d = points[i + 1].tilt;
-
- dist += d;
-
- pointlist.push_back(post);
- distlist.push_back(dist);
+ // Recalculate the baked distances.
+ real_t *bdw = baked_dist_cache.ptrw();
+ bdw[0] = 0.0;
+ for (int i = 0; i < pc - 1; i++) {
+ bdw[i + 1] = bdw[i] + bpw[i].distance_to(bpw[i + 1]);
+ }
+ baked_max_ofs = bdw[pc - 1];
}
- baked_max_ofs = dist;
-
- baked_point_cache.resize(pointlist.size());
- Vector3 *w = baked_point_cache.ptrw();
- int idx = 0;
+ if (!up_vector_enabled) {
+ baked_up_vector_cache.resize(0);
+ return;
+ }
- baked_tilt_cache.resize(pointlist.size());
- real_t *wt = baked_tilt_cache.ptrw();
+ // Step 2: Calculate the up vectors and the whole local reference frame
+ //
+ // See Dougan, Carl. "The parallel transport frame." Game Programming Gems 2 (2001): 215-219.
+ // for an example discussing about why not the Frenet frame.
+ {
+ int point_count = baked_point_cache.size();
- baked_up_vector_cache.resize(up_vector_enabled ? pointlist.size() : 0);
- Vector3 *up_write = baked_up_vector_cache.ptrw();
+ baked_up_vector_cache.resize(point_count);
+ Vector3 *up_write = baked_up_vector_cache.ptrw();
- baked_dist_cache.resize(pointlist.size());
- real_t *wd = baked_dist_cache.ptrw();
+ const Vector3 *forward_ptr = baked_forward_vector_cache.ptr();
+ const Vector3 *points_ptr = baked_point_cache.ptr();
- Vector3 sideways;
- Vector3 up;
- Vector3 forward;
+ Basis frame; // X-right, Y-up, Z-forward.
+ Basis frame_prev;
- Vector3 prev_sideways = Vector3(1, 0, 0);
- Vector3 prev_up = Vector3(0, 1, 0);
- Vector3 prev_forward = Vector3(0, 0, 1);
+ // Set the initial frame based on Y-up rule.
+ {
+ Vector3 forward = forward_ptr[0];
- for (const Plane &E : pointlist) {
- w[idx] = E.normal;
- wt[idx] = E.d;
- wd[idx] = distlist[idx];
+ if (abs(forward.dot(Vector3(0, 1, 0))) > 1.0 - UNIT_EPSILON) {
+ frame_prev = Basis::looking_at(-forward, Vector3(1, 0, 0));
+ } else {
+ frame_prev = Basis::looking_at(-forward, Vector3(0, 1, 0));
+ }
- if (!up_vector_enabled) {
- idx++;
- continue;
+ up_write[0] = frame_prev.get_column(1);
}
- forward = idx > 0 ? (w[idx] - w[idx - 1]).normalized() : prev_forward;
+ // Calculate the Parallel Transport Frame.
+ for (int idx = 1; idx < point_count; idx++) {
+ Vector3 forward = forward_ptr[idx];
- real_t y_dot = prev_up.dot(forward);
+ Basis rotate;
+ rotate.rotate_to_align(frame_prev.get_column(2), forward);
+ frame = rotate * frame_prev;
+ frame.orthonormalize(); // guard against float error accumulation
- if (y_dot > (1.0f - CMP_EPSILON)) {
- sideways = prev_sideways;
- up = -prev_forward;
- } else if (y_dot < -(1.0f - CMP_EPSILON)) {
- sideways = prev_sideways;
- up = prev_forward;
- } else {
- sideways = prev_up.cross(forward).normalized();
- up = forward.cross(sideways).normalized();
+ up_write[idx] = frame.get_column(1);
+ frame_prev = frame;
}
- if (idx == 1) {
- up_write[0] = up;
+ bool is_loop = true;
+ // Loop smoothing only applies when the curve is a loop, which means two ends meet, and share forward directions.
+ {
+ if (!points_ptr[0].is_equal_approx(points_ptr[point_count - 1])) {
+ is_loop = false;
+ }
+
+ real_t dot = forward_ptr[0].dot(forward_ptr[point_count - 1]);
+ if (dot < 1.0 - UNIT_EPSILON) { // Alignment should not be too tight, or it doesn't work for coarse bake interval.
+ is_loop = false;
+ }
}
- up_write[idx] = up;
+ // Twist up vectors, so that they align at two ends of the curve.
+ if (is_loop) {
+ const Vector3 up_start = up_write[0];
+ const Vector3 up_end = up_write[point_count - 1];
- prev_sideways = sideways;
- prev_up = up;
- prev_forward = forward;
+ real_t sign = SIGN(up_end.cross(up_start).dot(forward_ptr[0]));
+ real_t full_angle = Quaternion(up_end, up_start).get_angle();
- idx++;
+ if (abs(full_angle) < CMP_EPSILON) {
+ return;
+ } else {
+ const real_t *dists = baked_dist_cache.ptr();
+ for (int idx = 1; idx < point_count; idx++) {
+ const real_t frac = dists[idx] / baked_max_ofs;
+ const real_t angle = Math::lerp((real_t)0.0, full_angle, frac);
+ Basis twist(forward_ptr[idx] * sign, angle);
+
+ up_write[idx] = twist.xform(up_write[idx]);
+ }
+ }
+ }
}
}
@@ -1577,27 +1686,15 @@ real_t Curve3D::get_baked_length() const {
return baked_max_ofs;
}
-Vector3 Curve3D::sample_baked(real_t p_offset, bool p_cubic) const {
- if (baked_cache_dirty) {
- _bake();
- }
+Curve3D::Interval Curve3D::_find_interval(real_t p_offset) const {
+ Interval interval = {
+ -1,
+ 0.0
+ };
+ ERR_FAIL_COND_V_MSG(baked_cache_dirty, interval, "Backed cache is dirty");
- // Validate: Curve may not have baked points.
int pc = baked_point_cache.size();
- ERR_FAIL_COND_V_MSG(pc == 0, Vector3(), "No points in Curve3D.");
-
- if (pc == 1) {
- return baked_point_cache.get(0);
- }
-
- const Vector3 *r = baked_point_cache.ptr();
-
- if (p_offset < 0) {
- return r[0];
- }
- if (p_offset >= baked_max_ofs) {
- return r[pc - 1];
- }
+ ERR_FAIL_COND_V_MSG(pc < 2, interval, "Less than two points in cache");
int start = 0;
int end = pc;
@@ -1617,9 +1714,27 @@ Vector3 Curve3D::sample_baked(real_t p_offset, bool p_cubic) const {
real_t offset_end = baked_dist_cache[idx + 1];
real_t idx_interval = offset_end - offset_begin;
- ERR_FAIL_COND_V_MSG(p_offset < offset_begin || p_offset > offset_end, Vector3(), "Couldn't find baked segment.");
+ ERR_FAIL_COND_V_MSG(p_offset < offset_begin || p_offset > offset_end, interval, "Offset out of range.");
+
+ interval.idx = idx;
+ if (idx_interval < FLT_EPSILON) {
+ interval.frac = 0.5; // For a very short interval, 0.5 is a reasonable choice.
+ ERR_FAIL_V_MSG(interval, "Zero length interval.");
+ }
+
+ interval.frac = (p_offset - offset_begin) / idx_interval;
+ return interval;
+}
+
+Vector3 Curve3D::_sample_baked(Interval p_interval, bool p_cubic) const {
+ // Assuming p_interval is valid.
+ ERR_FAIL_INDEX_V_MSG(p_interval.idx, baked_point_cache.size(), Vector3(), "Invalid interval");
+
+ int idx = p_interval.idx;
+ real_t frac = p_interval.frac;
- real_t frac = (p_offset - offset_begin) / idx_interval;
+ const Vector3 *r = baked_point_cache.ptr();
+ int pc = baked_point_cache.size();
if (p_cubic) {
Vector3 pre = idx > 0 ? r[idx - 1] : r[idx];
@@ -1630,114 +1745,142 @@ Vector3 Curve3D::sample_baked(real_t p_offset, bool p_cubic) const {
}
}
-real_t Curve3D::sample_baked_tilt(real_t p_offset) const {
- if (baked_cache_dirty) {
- _bake();
- }
+real_t Curve3D::_sample_baked_tilt(Interval p_interval) const {
+ // Assuming that p_interval is valid.
+ ERR_FAIL_INDEX_V_MSG(p_interval.idx, baked_tilt_cache.size(), 0.0, "Invalid interval");
- // Validate: Curve may not have baked tilts.
- int pc = baked_tilt_cache.size();
- ERR_FAIL_COND_V_MSG(pc == 0, 0, "No tilts in Curve3D.");
+ int idx = p_interval.idx;
+ real_t frac = p_interval.frac;
- if (pc == 1) {
- return baked_tilt_cache.get(0);
+ const real_t *r = baked_tilt_cache.ptr();
+
+ return Math::lerp(r[idx], r[idx + 1], frac);
+}
+
+Basis Curve3D::_sample_posture(Interval p_interval, bool p_apply_tilt) const {
+ // Assuming that p_interval is valid.
+ ERR_FAIL_INDEX_V_MSG(p_interval.idx, baked_point_cache.size(), Basis(), "Invalid interval");
+ if (up_vector_enabled) {
+ ERR_FAIL_INDEX_V_MSG(p_interval.idx, baked_up_vector_cache.size(), Basis(), "Invalid interval");
}
- const real_t *r = baked_tilt_cache.ptr();
+ int idx = p_interval.idx;
+ real_t frac = p_interval.frac;
- if (p_offset < 0) {
- return r[0];
+ Vector3 forward_begin = baked_forward_vector_cache[idx];
+ Vector3 forward_end = baked_forward_vector_cache[idx + 1];
+
+ Vector3 up_begin;
+ Vector3 up_end;
+ if (up_vector_enabled) {
+ up_begin = baked_up_vector_cache[idx];
+ up_end = baked_up_vector_cache[idx + 1];
+ } else {
+ up_begin = Vector3(0.0, 1.0, 0.0);
+ up_end = Vector3(0.0, 1.0, 0.0);
}
- if (p_offset >= baked_max_ofs) {
- return r[pc - 1];
+
+ // Build frames at both ends of the interval, then interpolate.
+ const Basis frame_begin = Basis::looking_at(-forward_begin, up_begin);
+ const Basis frame_end = Basis::looking_at(-forward_end, up_end);
+ const Basis frame = frame_begin.slerp(frame_end, frac).orthonormalized();
+
+ if (!p_apply_tilt) {
+ return frame;
}
- int start = 0;
- int end = pc;
- int idx = (end + start) / 2;
- // Binary search to find baked points.
- while (start < idx) {
- real_t offset = baked_dist_cache[idx];
- if (p_offset <= offset) {
- end = idx;
- } else {
- start = idx;
- }
- idx = (end + start) / 2;
+ // Applying tilt.
+ const real_t tilt = _sample_baked_tilt(p_interval);
+ Vector3 forward = frame.get_column(2);
+
+ const Basis twist(forward, tilt);
+ return twist * frame;
+}
+
+Vector3 Curve3D::sample_baked(real_t p_offset, bool p_cubic) const {
+ if (baked_cache_dirty) {
+ _bake();
}
- real_t offset_begin = baked_dist_cache[idx];
- real_t offset_end = baked_dist_cache[idx + 1];
+ // Validate: Curve may not have baked points.
+ int pc = baked_point_cache.size();
+ ERR_FAIL_COND_V_MSG(pc == 0, Vector3(), "No points in Curve3D.");
- real_t idx_interval = offset_end - offset_begin;
- ERR_FAIL_COND_V_MSG(p_offset < offset_begin || p_offset > offset_end, 0, "Couldn't find baked segment.");
+ if (pc == 1) {
+ return baked_point_cache[0];
+ }
- real_t frac = (p_offset - offset_begin) / idx_interval;
+ p_offset = CLAMP(p_offset, 0.0, get_baked_length()); // PathFollower implement wrapping logic.
- return Math::lerp(r[idx], r[idx + 1], (real_t)frac);
+ Curve3D::Interval interval = _find_interval(p_offset);
+ return _sample_baked(interval, p_cubic);
}
-Vector3 Curve3D::sample_baked_up_vector(real_t p_offset, bool p_apply_tilt) const {
+Transform3D Curve3D::sample_baked_with_rotation(real_t p_offset, bool p_cubic, bool p_apply_tilt) const {
if (baked_cache_dirty) {
_bake();
}
- // Validate: Curve may not have baked up vectors.
- int count = baked_up_vector_cache.size();
- ERR_FAIL_COND_V_MSG(count == 0, Vector3(0, 1, 0), "No up vectors in Curve3D.");
+ // Validate: Curve may not have baked points.
+ const int point_count = baked_point_cache.size();
+ ERR_FAIL_COND_V_MSG(point_count == 0, Transform3D(), "No points in Curve3D.");
- if (count == 1) {
- return baked_up_vector_cache.get(0);
+ if (point_count == 1) {
+ Transform3D t;
+ t.origin = baked_point_cache.get(0);
+ ERR_FAIL_V_MSG(t, "Only 1 point in Curve3D.");
}
- const Vector3 *r = baked_up_vector_cache.ptr();
- const Vector3 *rp = baked_point_cache.ptr();
- const real_t *rt = baked_tilt_cache.ptr();
+ p_offset = CLAMP(p_offset, 0.0, get_baked_length()); // PathFollower implement wrapping logic.
- int start = 0;
- int end = count;
- int idx = (end + start) / 2;
- // Binary search to find baked points.
- while (start < idx) {
- real_t offset = baked_dist_cache[idx];
- if (p_offset <= offset) {
- end = idx;
- } else {
- start = idx;
- }
- idx = (end + start) / 2;
- }
+ // 0. Find interval for all sampling steps.
+ Curve3D::Interval interval = _find_interval(p_offset);
- if (idx == count - 1) {
- return p_apply_tilt ? r[idx].rotated((rp[idx] - rp[idx - 1]).normalized(), rt[idx]) : r[idx];
+ // 1. Sample position.
+ Vector3 pos = _sample_baked(interval, p_cubic);
+
+ // 2. Sample rotation frame.
+ Basis frame = _sample_posture(interval, p_apply_tilt);
+
+ return Transform3D(frame, pos);
+}
+
+real_t Curve3D::sample_baked_tilt(real_t p_offset) const {
+ if (baked_cache_dirty) {
+ _bake();
}
- real_t offset_begin = baked_dist_cache[idx];
- real_t offset_end = baked_dist_cache[idx + 1];
+ // Validate: Curve may not have baked tilts.
+ int pc = baked_tilt_cache.size();
+ ERR_FAIL_COND_V_MSG(pc == 0, 0, "No tilts in Curve3D.");
- real_t idx_interval = offset_end - offset_begin;
- ERR_FAIL_COND_V_MSG(p_offset < offset_begin || p_offset > offset_end, Vector3(0, 1, 0), "Couldn't find baked segment.");
+ if (pc == 1) {
+ return baked_tilt_cache.get(0);
+ }
- real_t frac = (p_offset - offset_begin) / idx_interval;
+ p_offset = CLAMP(p_offset, 0.0, get_baked_length()); // PathFollower implement wrapping logic
- Vector3 forward = (rp[idx + 1] - rp[idx]).normalized();
- Vector3 up = r[idx];
- Vector3 up1 = r[idx + 1];
+ Curve3D::Interval interval = _find_interval(p_offset);
+ return _sample_baked_tilt(interval);
+}
- if (p_apply_tilt) {
- up.rotate(forward, rt[idx]);
- up1.rotate(idx + 2 >= count ? forward : (rp[idx + 2] - rp[idx + 1]).normalized(), rt[idx + 1]);
+Vector3 Curve3D::sample_baked_up_vector(real_t p_offset, bool p_apply_tilt) const {
+ if (baked_cache_dirty) {
+ _bake();
}
- Vector3 axis = up.cross(up1);
+ // Validate: Curve may not have baked up vectors.
+ ERR_FAIL_COND_V_MSG(!up_vector_enabled, Vector3(0, 1, 0), "No up vectors in Curve3D.");
- if (axis.length_squared() < CMP_EPSILON2) {
- axis = forward;
- } else {
- axis.normalize();
+ int count = baked_up_vector_cache.size();
+ if (count == 1) {
+ return baked_up_vector_cache.get(0);
}
- return up.rotated(axis, up.angle_to(up1) * frac);
+ p_offset = CLAMP(p_offset, 0.0, get_baked_length()); // PathFollower implement wrapping logic.
+
+ Curve3D::Interval interval = _find_interval(p_offset);
+ return _sample_posture(interval, p_apply_tilt).get_column(1);
}
PackedVector3Array Curve3D::get_baked_points() const {
@@ -1785,10 +1928,11 @@ Vector3 Curve3D::get_closest_point(const Vector3 &p_to_point) const {
real_t nearest_dist = -1.0f;
for (int i = 0; i < pc - 1; i++) {
+ const real_t interval = baked_dist_cache[i + 1] - baked_dist_cache[i];
Vector3 origin = r[i];
- Vector3 direction = (r[i + 1] - origin) / bake_interval;
+ Vector3 direction = (r[i + 1] - origin) / interval;
- real_t d = CLAMP((p_to_point - origin).dot(direction), 0.0f, bake_interval);
+ real_t d = CLAMP((p_to_point - origin).dot(direction), 0.0f, interval);
Vector3 proj = origin + direction * d;
real_t dist = proj.distance_squared_to(p_to_point);
@@ -1821,13 +1965,16 @@ real_t Curve3D::get_closest_offset(const Vector3 &p_to_point) const {
real_t nearest = 0.0f;
real_t nearest_dist = -1.0f;
- real_t offset = 0.0f;
+ real_t offset;
for (int i = 0; i < pc - 1; i++) {
+ offset = baked_dist_cache[i];
+
+ const real_t interval = baked_dist_cache[i + 1] - baked_dist_cache[i];
Vector3 origin = r[i];
- Vector3 direction = (r[i + 1] - origin) / bake_interval;
+ Vector3 direction = (r[i + 1] - origin) / interval;
- real_t d = CLAMP((p_to_point - origin).dot(direction), 0.0f, bake_interval);
+ real_t d = CLAMP((p_to_point - origin).dot(direction), 0.0f, interval);
Vector3 proj = origin + direction * d;
real_t dist = proj.distance_squared_to(p_to_point);
@@ -1836,8 +1983,6 @@ real_t Curve3D::get_closest_offset(const Vector3 &p_to_point) const {
nearest = offset + d;
nearest_dist = dist;
}
-
- offset += bake_interval;
}
return nearest;
@@ -1942,6 +2087,50 @@ PackedVector3Array Curve3D::tessellate(int p_max_stages, real_t p_tolerance) con
return tess;
}
+Vector<RBMap<real_t, Vector3>> Curve3D::_tessellate_even_length(int p_max_stages, real_t p_length) const {
+ Vector<RBMap<real_t, Vector3>> midpoints;
+ ERR_FAIL_COND_V_MSG(points.size() < 2, midpoints, "Curve must have at least 2 control point");
+
+ midpoints.resize(points.size() - 1);
+
+ for (int i = 0; i < points.size() - 1; i++) {
+ _bake_segment3d_even_length(midpoints.write[i], 0, 1, points[i].position, points[i].out, points[i + 1].position, points[i + 1].in, 0, p_max_stages, p_length);
+ }
+ return midpoints;
+}
+
+PackedVector3Array Curve3D::tessellate_even_length(int p_max_stages, real_t p_length) const {
+ PackedVector3Array tess;
+
+ Vector<RBMap<real_t, Vector3>> midpoints = _tessellate_even_length(p_max_stages, p_length);
+ if (midpoints.size() == 0) {
+ return tess;
+ }
+
+ int pc = 1;
+ for (int i = 0; i < points.size() - 1; i++) {
+ pc++;
+ pc += midpoints[i].size();
+ }
+
+ tess.resize(pc);
+ Vector3 *bpw = tess.ptrw();
+ bpw[0] = points[0].position;
+ int pidx = 0;
+
+ for (int i = 0; i < points.size() - 1; i++) {
+ for (const KeyValue<real_t, Vector3> &E : midpoints[i]) {
+ pidx++;
+ bpw[pidx] = E.value;
+ }
+
+ pidx++;
+ bpw[pidx] = points[i + 1].position;
+ }
+
+ return tess;
+}
+
bool Curve3D::_set(const StringName &p_name, const Variant &p_value) {
Vector<String> components = String(p_name).split("/", true, 2);
if (components.size() >= 2 && components[0].begins_with("point_") && components[0].trim_prefix("point_").is_valid_int()) {
@@ -2033,7 +2222,8 @@ void Curve3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_up_vector_enabled"), &Curve3D::is_up_vector_enabled);
ClassDB::bind_method(D_METHOD("get_baked_length"), &Curve3D::get_baked_length);
- ClassDB::bind_method(D_METHOD("sample_baked", "offset", "cubic"), &Curve3D::sample_baked, DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("sample_baked", "offset", "cubic"), &Curve3D::sample_baked, DEFVAL(0.0), DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("sample_baked_with_rotation", "offset", "cubic", "apply_tilt"), &Curve3D::sample_baked_with_rotation, DEFVAL(0.0), DEFVAL(false), DEFVAL(false));
ClassDB::bind_method(D_METHOD("sample_baked_up_vector", "offset", "apply_tilt"), &Curve3D::sample_baked_up_vector, DEFVAL(false));
ClassDB::bind_method(D_METHOD("get_baked_points"), &Curve3D::get_baked_points);
ClassDB::bind_method(D_METHOD("get_baked_tilts"), &Curve3D::get_baked_tilts);
@@ -2041,6 +2231,7 @@ void Curve3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_closest_point", "to_point"), &Curve3D::get_closest_point);
ClassDB::bind_method(D_METHOD("get_closest_offset", "to_point"), &Curve3D::get_closest_offset);
ClassDB::bind_method(D_METHOD("tessellate", "max_stages", "tolerance_degrees"), &Curve3D::tessellate, DEFVAL(5), DEFVAL(4));
+ ClassDB::bind_method(D_METHOD("tessellate_even_length", "max_stages", "tolerance_length"), &Curve3D::tessellate_even_length, DEFVAL(5), DEFVAL(0.2));
ClassDB::bind_method(D_METHOD("_get_data"), &Curve3D::_get_data);
ClassDB::bind_method(D_METHOD("_set_data", "data"), &Curve3D::_set_data);
diff --git a/scene/resources/curve.h b/scene/resources/curve.h
index fa1d35aab1..26608c47cd 100644
--- a/scene/resources/curve.h
+++ b/scene/resources/curve.h
@@ -172,16 +172,27 @@ class Curve2D : public Resource {
mutable bool baked_cache_dirty = false;
mutable PackedVector2Array baked_point_cache;
+ mutable PackedVector2Array baked_forward_vector_cache;
mutable Vector<real_t> baked_dist_cache;
mutable real_t baked_max_ofs = 0.0;
void mark_dirty();
+ static Vector2 _calculate_tangent(const Vector2 &p_begin, const Vector2 &p_control_1, const Vector2 &p_control_2, const Vector2 &p_end, const real_t p_t);
void _bake() const;
real_t bake_interval = 5.0;
+ struct Interval {
+ int idx;
+ real_t frac;
+ };
+ Interval _find_interval(real_t p_offset) const;
+ Vector2 _sample_baked(Interval p_interval, bool p_cubic) const;
+ Transform2D _sample_posture(Interval p_interval) const;
+
void _bake_segment2d(RBMap<real_t, Vector2> &r_bake, real_t p_begin, real_t p_end, const Vector2 &p_a, const Vector2 &p_out, const Vector2 &p_b, const Vector2 &p_in, int p_depth, int p_max_depth, real_t p_tol) const;
+ void _bake_segment2d_even_length(RBMap<real_t, Vector2> &r_bake, real_t p_begin, real_t p_end, const Vector2 &p_a, const Vector2 &p_out, const Vector2 &p_b, const Vector2 &p_in, int p_depth, int p_max_depth, real_t p_length) const;
Dictionary _get_data() const;
void _set_data(const Dictionary &p_data);
@@ -192,6 +203,8 @@ class Curve2D : public Resource {
void _add_point(const Vector2 &p_position, const Vector2 &p_in = Vector2(), const Vector2 &p_out = Vector2(), int p_atpos = -1);
void _remove_point(int p_index);
+ Vector<RBMap<real_t, Vector2>> _tessellate_even_length(int p_max_stages = 5, real_t p_length = 0.2) const;
+
protected:
static void _bind_methods();
@@ -216,12 +229,13 @@ public:
real_t get_baked_length() const;
Vector2 sample_baked(real_t p_offset, bool p_cubic = false) const;
- Transform2D sample_baked_with_rotation(real_t p_offset, bool p_cubic = false, bool p_loop = true, real_t p_lookahead = 4.0) const;
+ Transform2D sample_baked_with_rotation(real_t p_offset, bool p_cubic = false) const;
PackedVector2Array get_baked_points() const; //useful for going through
Vector2 get_closest_point(const Vector2 &p_to_point) const;
real_t get_closest_offset(const Vector2 &p_to_point) const;
PackedVector2Array tessellate(int p_max_stages = 5, real_t p_tolerance = 4) const; //useful for display
+ PackedVector2Array tessellate_even_length(int p_max_stages = 5, real_t p_length = 20.0) const; // Useful for baking.
Curve2D();
};
@@ -238,26 +252,33 @@ class Curve3D : public Resource {
Vector<Point> points;
- struct BakedPoint {
- real_t ofs = 0.0;
- Vector3 point;
- };
-
mutable bool baked_cache_dirty = false;
mutable PackedVector3Array baked_point_cache;
mutable Vector<real_t> baked_tilt_cache;
mutable PackedVector3Array baked_up_vector_cache;
+ mutable PackedVector3Array baked_forward_vector_cache;
mutable Vector<real_t> baked_dist_cache;
mutable real_t baked_max_ofs = 0.0;
void mark_dirty();
+ static Vector3 _calculate_tangent(const Vector3 &p_begin, const Vector3 &p_control_1, const Vector3 &p_control_2, const Vector3 &p_end, const real_t p_t);
void _bake() const;
+ struct Interval {
+ int idx;
+ real_t frac;
+ };
+ Interval _find_interval(real_t p_offset) const;
+ Vector3 _sample_baked(Interval p_interval, bool p_cubic) const;
+ real_t _sample_baked_tilt(Interval p_interval) const;
+ Basis _sample_posture(Interval p_interval, bool p_apply_tilt = false) const;
+
real_t bake_interval = 0.2;
bool up_vector_enabled = true;
void _bake_segment3d(RBMap<real_t, Vector3> &r_bake, real_t p_begin, real_t p_end, const Vector3 &p_a, const Vector3 &p_out, const Vector3 &p_b, const Vector3 &p_in, int p_depth, int p_max_depth, real_t p_tol) const;
+ void _bake_segment3d_even_length(RBMap<real_t, Vector3> &r_bake, real_t p_begin, real_t p_end, const Vector3 &p_a, const Vector3 &p_out, const Vector3 &p_b, const Vector3 &p_in, int p_depth, int p_max_depth, real_t p_length) const;
Dictionary _get_data() const;
void _set_data(const Dictionary &p_data);
@@ -268,6 +289,8 @@ class Curve3D : public Resource {
void _add_point(const Vector3 &p_position, const Vector3 &p_in = Vector3(), const Vector3 &p_out = Vector3(), int p_atpos = -1);
void _remove_point(int p_index);
+ Vector<RBMap<real_t, Vector3>> _tessellate_even_length(int p_max_stages = 5, real_t p_length = 0.2) const;
+
protected:
static void _bind_methods();
@@ -296,15 +319,17 @@ public:
real_t get_baked_length() const;
Vector3 sample_baked(real_t p_offset, bool p_cubic = false) const;
+ Transform3D sample_baked_with_rotation(real_t p_offset, bool p_cubic = false, bool p_apply_tilt = false) const;
real_t sample_baked_tilt(real_t p_offset) const;
Vector3 sample_baked_up_vector(real_t p_offset, bool p_apply_tilt = false) const;
- PackedVector3Array get_baked_points() const; //useful for going through
+ PackedVector3Array get_baked_points() const; // Useful for going through.
Vector<real_t> get_baked_tilts() const; //useful for going through
PackedVector3Array get_baked_up_vectors() const;
Vector3 get_closest_point(const Vector3 &p_to_point) const;
real_t get_closest_offset(const Vector3 &p_to_point) const;
- PackedVector3Array tessellate(int p_max_stages = 5, real_t p_tolerance = 4) const; //useful for display
+ PackedVector3Array tessellate(int p_max_stages = 5, real_t p_tolerance = 4) const; // Useful for display.
+ PackedVector3Array tessellate_even_length(int p_max_stages = 5, real_t p_length = 0.2) const; // Useful for baking.
Curve3D();
};
diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp
index 894936acd7..571ddee763 100644
--- a/scene/resources/default_theme/default_theme.cpp
+++ b/scene/resources/default_theme/default_theme.cpp
@@ -84,7 +84,8 @@ static Ref<ImageTexture> generate_icon(int p_index) {
// with integer scales.
const bool upsample = !Math::is_equal_approx(Math::round(scale), scale);
ImageLoaderSVG img_loader;
- img_loader.create_image_from_string(img, default_theme_icons_sources[p_index], scale, upsample, HashMap<Color, Color>());
+ Error err = img_loader.create_image_from_string(img, default_theme_icons_sources[p_index], scale, upsample, HashMap<Color, Color>());
+ ERR_FAIL_COND_V_MSG(err != OK, Ref<ImageTexture>(), "Failed generating icon, unsupported or invalid SVG data in default theme.");
#endif
return ImageTexture::create_from_image(img);
@@ -99,6 +100,11 @@ static Ref<StyleBox> make_empty_stylebox(float p_margin_left = -1, float p_margi
void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const Ref<Font> &bold_font, const Ref<Font> &bold_italics_font, const Ref<Font> &italics_font, Ref<Texture2D> &default_icon, Ref<StyleBox> &default_style, float p_scale) {
scale = p_scale;
+ // Default theme properties.
+ theme->set_default_font(default_font);
+ theme->set_default_font_size(default_font_size * scale);
+ theme->set_default_base_scale(scale);
+
// Font colors
const Color control_font_color = Color(0.875, 0.875, 0.875);
const Color control_font_low_color = Color(0.7, 0.7, 0.7);
diff --git a/scene/resources/font.cpp b/scene/resources/font.cpp
index 185b6f4bdc..584a7e7eac 100644
--- a/scene/resources/font.cpp
+++ b/scene/resources/font.cpp
@@ -63,6 +63,8 @@ void Font::_bind_methods() {
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_font_weight"), &Font::get_font_weight);
+ ClassDB::bind_method(D_METHOD("get_font_stretch"), &Font::get_font_stretch);
ClassDB::bind_method(D_METHOD("get_spacing", "spacing"), &Font::get_spacing);
ClassDB::bind_method(D_METHOD("get_opentype_features"), &Font::get_opentype_features);
@@ -249,6 +251,14 @@ BitField<TextServer::FontStyle> Font::get_font_style() const {
return TS->font_get_style(_get_rid());
}
+int Font::get_font_weight() const {
+ return TS->font_get_weight(_get_rid());
+}
+
+int Font::get_font_stretch() const {
+ return TS->font_get_stretch(_get_rid());
+}
+
Dictionary Font::get_opentype_features() const {
return Dictionary();
}
@@ -590,6 +600,7 @@ _FORCE_INLINE_ void FontFile::_ensure_rid(int p_cache_index) const {
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_allow_system_fallback(cache[p_cache_index], allow_system_fallback);
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);
@@ -881,6 +892,8 @@ void FontFile::_bind_methods() {
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_font_weight", "weight"), &FontFile::set_font_weight);
+ ClassDB::bind_method(D_METHOD("set_font_stretch", "stretch"), &FontFile::set_font_stretch);
ClassDB::bind_method(D_METHOD("set_antialiasing", "antialiasing"), &FontFile::set_antialiasing);
ClassDB::bind_method(D_METHOD("get_antialiasing"), &FontFile::get_antialiasing);
@@ -900,6 +913,9 @@ void FontFile::_bind_methods() {
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_allow_system_fallback", "allow_system_fallback"), &FontFile::set_allow_system_fallback);
+ ClassDB::bind_method(D_METHOD("is_allow_system_fallback"), &FontFile::is_allow_system_fallback);
+
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);
@@ -1007,16 +1023,20 @@ void FontFile::_bind_methods() {
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, "font_weight", PROPERTY_HINT_RANGE, "100,999,25", PROPERTY_USAGE_STORAGE), "set_font_weight", "get_font_weight");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "font_stretch", PROPERTY_HINT_RANGE, "50,200,25", PROPERTY_USAGE_STORAGE), "set_font_stretch", "get_font_stretch");
+
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, "allow_system_fallback", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_allow_system_fallback", "is_allow_system_fallback");
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");
+ ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "fallbacks", PROPERTY_HINT_ARRAY_TYPE, MAKE_RESOURCE_TYPE_HINT("Font"), PROPERTY_USAGE_STORAGE), "set_fallbacks", "get_fallbacks");
}
bool FontFile::_set(const StringName &p_name, const Variant &p_value) {
@@ -1329,6 +1349,7 @@ void FontFile::reset_state() {
mipmaps = false;
msdf = false;
force_autohinter = false;
+ allow_system_fallback = true;
hinting = TextServer::HINTING_LIGHT;
subpixel_positioning = TextServer::SUBPIXEL_POSITIONING_DISABLED;
msdf_pixel_range = 14;
@@ -1361,6 +1382,7 @@ Error FontFile::load_bitmap_font(const String &p_path) {
mipmaps = false;
msdf = false;
force_autohinter = false;
+ allow_system_fallback = true;
hinting = TextServer::HINTING_NONE;
oversampling = 1.0f;
@@ -1396,6 +1418,9 @@ Error FontFile::load_bitmap_font(const String &p_path) {
case 1: /* info */ {
ERR_FAIL_COND_V_MSG(block_size < 15, ERR_CANT_CREATE, RTR("Invalid BMFont info block size."));
base_size = f->get_16();
+ if (base_size <= 0) {
+ base_size = 16;
+ }
uint8_t flags = f->get_8();
if (flags & (1 << 3)) {
st_flags.set_flag(TextServer::FONT_BOLD);
@@ -1681,7 +1706,6 @@ Error FontFile::load_bitmap_font(const String &p_path) {
if (type == "info") {
if (keys.has("size")) {
base_size = keys["size"].to_int();
- set_fixed_size(base_size);
}
if (keys.has("outline")) {
outline = keys["outline"].to_int();
@@ -1730,6 +1754,7 @@ Error FontFile::load_bitmap_font(const String &p_path) {
encoding = 2;
}
}
+ set_fixed_size(base_size);
} else if (type == "common") {
if (keys.has("lineHeight")) {
height = keys["lineHeight"].to_int();
@@ -1788,7 +1813,10 @@ Error FontFile::load_bitmap_font(const String &p_path) {
ERR_FAIL_V_MSG(ERR_CANT_CREATE, RTR("Unsupported BMFont texture format."));
}
} else {
- if ((ch[0] == 0) && (ch[1] == 0) && (ch[2] == 0) && (ch[3] == 0)) { // RGBA8 color, no outline
+ if ((ch[3] == 0) && (ch[0] == 4) && (ch[1] == 4) && (ch[2] == 4) && img->get_format() == Image::FORMAT_RGBA8) { // might be RGBA8 color, no outline (color part of the image should be sold white, but some apps designed for Godot 3 generate color fonts with this config)
+ outline = 0;
+ set_texture_image(0, Vector2i(base_size, 0), page, img);
+ } else if ((ch[0] == 0) && (ch[1] == 0) && (ch[2] == 0) && (ch[3] == 0)) { // RGBA8 color, no outline
outline = 0;
ERR_FAIL_COND_V_MSG(img->get_format() != Image::FORMAT_RGBA8, ERR_FILE_CANT_READ, RTR("Unsupported BMFont texture format."));
set_texture_image(0, Vector2i(base_size, 0), page, img);
@@ -1931,6 +1959,9 @@ Error FontFile::load_bitmap_font(const String &p_path) {
set_font_name(font_name);
set_font_style(st_flags);
+ if (st_flags & TextServer::FONT_BOLD) {
+ set_font_weight(700);
+ }
set_cache_ascent(0, base_size, ascent);
set_cache_descent(0, base_size, height - ascent);
@@ -1940,7 +1971,7 @@ Error FontFile::load_bitmap_font(const String &p_path) {
Error FontFile::load_dynamic_font(const String &p_path) {
reset_state();
- Vector<uint8_t> font_data = FileAccess::get_file_as_array(p_path);
+ Vector<uint8_t> font_data = FileAccess::get_file_as_bytes(p_path);
set_data(font_data);
return OK;
@@ -1994,6 +2025,16 @@ void FontFile::set_font_style(BitField<TextServer::FontStyle> p_style) {
TS->font_set_style(cache[0], p_style);
}
+void FontFile::set_font_weight(int p_weight) {
+ _ensure_rid(0);
+ TS->font_set_weight(cache[0], p_weight);
+}
+
+void FontFile::set_font_stretch(int p_stretch) {
+ _ensure_rid(0);
+ TS->font_set_stretch(cache[0], p_stretch);
+}
+
void FontFile::set_antialiasing(TextServer::FontAntialiasing p_antialiasing) {
if (antialiasing != p_antialiasing) {
antialiasing = p_antialiasing;
@@ -2084,6 +2125,21 @@ int FontFile::get_fixed_size() const {
return fixed_size;
}
+void FontFile::set_allow_system_fallback(bool p_allow_system_fallback) {
+ if (allow_system_fallback != p_allow_system_fallback) {
+ allow_system_fallback = p_allow_system_fallback;
+ for (int i = 0; i < cache.size(); i++) {
+ _ensure_rid(i);
+ TS->font_set_allow_system_fallback(cache[i], allow_system_fallback);
+ }
+ emit_changed();
+ }
+}
+
+bool FontFile::is_allow_system_fallback() const {
+ return allow_system_fallback;
+}
+
void FontFile::set_force_autohinter(bool p_force_autohinter) {
if (force_autohinter != p_force_autohinter) {
force_autohinter = p_force_autohinter;
@@ -2597,18 +2653,18 @@ void FontVariation::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_spacing", "spacing", "value"), &FontVariation::set_spacing);
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");
+ ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "fallbacks", PROPERTY_HINT_ARRAY_TYPE, MAKE_RESOURCE_TYPE_HINT("Font")), "set_fallbacks", "get_fallbacks");
- ADD_GROUP("Variation", "variation");
+ 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");
- ADD_GROUP("OpenType Features", "opentype");
+ ADD_GROUP("OpenType Features", "opentype_");
ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "opentype_features"), "set_opentype_features", "get_opentype_features");
- ADD_GROUP("Extra Spacing", "spacing");
+ 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);
@@ -2833,6 +2889,9 @@ void SystemFont::_bind_methods() {
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);
+ ClassDB::bind_method(D_METHOD("set_allow_system_fallback", "allow_system_fallback"), &SystemFont::set_allow_system_fallback);
+ ClassDB::bind_method(D_METHOD("is_allow_system_fallback"), &SystemFont::is_allow_system_fallback);
+
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);
@@ -2851,18 +2910,24 @@ void SystemFont::_bind_methods() {
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);
+ ClassDB::bind_method(D_METHOD("get_font_italic"), &SystemFont::get_font_italic);
+ ClassDB::bind_method(D_METHOD("set_font_italic", "italic"), &SystemFont::set_font_italic);
+ ClassDB::bind_method(D_METHOD("set_font_weight", "weight"), &SystemFont::set_font_weight);
+ ClassDB::bind_method(D_METHOD("set_font_stretch", "stretch"), &SystemFont::set_font_stretch);
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, "font_italic"), "set_font_italic", "get_font_italic");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "font_weight", PROPERTY_HINT_RANGE, "100,999,25"), "set_font_weight", "get_font_weight");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "font_stretch", PROPERTY_HINT_RANGE, "50,200,25"), "set_font_stretch", "get_font_stretch");
ADD_PROPERTY(PropertyInfo(Variant::INT, "antialiasing", PROPERTY_HINT_ENUM, "None,Grayscale,LCD Subpixel", PROPERTY_USAGE_STORAGE), "set_antialiasing", "get_antialiasing");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "generate_mipmaps"), "set_generate_mipmaps", "get_generate_mipmaps");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "allow_system_fallback"), "set_allow_system_fallback", "is_allow_system_fallback");
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::BOOL, "multichannel_signed_distance_field"), "set_multichannel_signed_distance_field", "is_multichannel_signed_distance_field");
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");
+ ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "fallbacks", PROPERTY_HINT_ARRAY_TYPE, MAKE_RESOURCE_TYPE_HINT("Font")), "set_fallbacks", "get_fallbacks");
}
void SystemFont::_update_rids() const {
@@ -2893,13 +2958,14 @@ void SystemFont::_update_base_font() {
face_indeces.clear();
ftr_weight = 0;
+ ftr_stretch = 0;
ftr_italic = 0;
for (const String &E : names) {
if (E.is_empty()) {
continue;
}
- String path = OS::get_singleton()->get_system_font_path(E, style & TextServer::FONT_BOLD, style & TextServer::FONT_ITALIC);
+ String path = OS::get_singleton()->get_system_font_path(E, weight, stretch, italic);
if (path.is_empty()) {
continue;
}
@@ -2911,9 +2977,22 @@ void SystemFont::_update_base_font() {
}
// If it's a font collection check all faces to match requested style.
+ int best_score = 0;
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))) {
+ BitField<TextServer::FontStyle> style = file->get_font_style();
+ int font_weight = file->get_font_weight();
+ int font_stretch = file->get_font_stretch();
+ int score = (20 - Math::abs(font_weight - weight) / 50);
+ score += (20 - Math::abs(font_stretch - stretch) / 10);
+ if (bool(style & TextServer::FONT_ITALIC) == italic) {
+ score += 30;
+ }
+ if (score > best_score) {
+ face_indeces.clear();
+ }
+ if (score >= best_score) {
+ best_score = score;
face_indeces.push_back(i);
}
}
@@ -2922,19 +3001,25 @@ void SystemFont::_update_base_font() {
}
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;
+ // If it's a variable font, apply weight, stretch and italic coordinates to match requested style.
+ if (best_score != 50) {
+ Dictionary ftr = file->get_supported_variation_list();
+ if (ftr.has(TS->name_to_tag("width"))) {
+ ftr_stretch = stretch;
+ }
+ if (ftr.has(TS->name_to_tag("weight"))) {
+ ftr_weight = weight;
+ }
+ if (italic && ftr.has(TS->name_to_tag("italic"))) {
+ ftr_italic = 1;
+ }
}
// Apply font rendering settings.
file->set_antialiasing(antialiasing);
file->set_generate_mipmaps(mipmaps);
file->set_force_autohinter(force_autohinter);
+ file->set_allow_system_fallback(allow_system_fallback);
file->set_hinting(hinting);
file->set_subpixel_positioning(subpixel_positioning);
file->set_multichannel_signed_distance_field(msdf);
@@ -2967,11 +3052,15 @@ void SystemFont::reset_state() {
names.clear();
face_indeces.clear();
ftr_weight = 0;
+ ftr_stretch = 0;
ftr_italic = 0;
- style = 0;
+ italic = false;
+ weight = 400;
+ stretch = 100;
antialiasing = TextServer::FONT_ANTIALIASING_GRAY;
mipmaps = false;
force_autohinter = false;
+ allow_system_fallback = true;
hinting = TextServer::HINTING_LIGHT;
subpixel_positioning = TextServer::SUBPIXEL_POSITIONING_DISABLED;
oversampling = 0.f;
@@ -3063,6 +3152,20 @@ bool SystemFont::get_generate_mipmaps() const {
return mipmaps;
}
+void SystemFont::set_allow_system_fallback(bool p_allow_system_fallback) {
+ if (allow_system_fallback != p_allow_system_fallback) {
+ allow_system_fallback = p_allow_system_fallback;
+ if (base_font.is_valid()) {
+ base_font->set_allow_system_fallback(allow_system_fallback);
+ }
+ emit_changed();
+ }
+}
+
+bool SystemFont::is_allow_system_fallback() const {
+ return allow_system_fallback;
+}
+
void SystemFont::set_force_autohinter(bool p_force_autohinter) {
if (force_autohinter != p_force_autohinter) {
force_autohinter = p_force_autohinter;
@@ -3144,15 +3247,37 @@ 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;
+void SystemFont::set_font_italic(bool p_italic) {
+ if (italic != p_italic) {
+ italic = p_italic;
_update_base_font();
}
}
-BitField<TextServer::FontStyle> SystemFont::get_font_style() const {
- return style;
+bool SystemFont::get_font_italic() const {
+ return italic;
+}
+
+void SystemFont::set_font_weight(int p_weight) {
+ if (weight != p_weight) {
+ weight = CLAMP(p_weight, 100, 999);
+ _update_base_font();
+ }
+}
+
+int SystemFont::get_font_weight() const {
+ return weight;
+}
+
+void SystemFont::set_font_stretch(int p_stretch) {
+ if (stretch != p_stretch) {
+ stretch = CLAMP(p_stretch, 50, 200);
+ _update_base_font();
+ }
+}
+
+int SystemFont::get_font_stretch() const {
+ return stretch;
}
int SystemFont::get_spacing(TextServer::SpacingType p_spacing) const {
@@ -3170,6 +3295,9 @@ RID SystemFont::find_variation(const Dictionary &p_variation_coordinates, int p_
if (ftr_weight > 0 && !var.has(TS->name_to_tag("weight"))) {
var[TS->name_to_tag("weight")] = ftr_weight;
}
+ if (ftr_stretch > 0 && !var.has(TS->name_to_tag("width"))) {
+ var[TS->name_to_tag("width")] = ftr_stretch;
+ }
if (ftr_italic > 0 && !var.has(TS->name_to_tag("italic"))) {
var[TS->name_to_tag("italic")] = ftr_italic;
}
@@ -3192,6 +3320,9 @@ RID SystemFont::_get_rid() const {
if (ftr_weight > 0) {
var[TS->name_to_tag("weight")] = ftr_weight;
}
+ if (ftr_stretch > 0) {
+ var[TS->name_to_tag("width")] = ftr_stretch;
+ }
if (ftr_italic > 0) {
var[TS->name_to_tag("italic")] = ftr_italic;
}
diff --git a/scene/resources/font.h b/scene/resources/font.h
index 5cf596b41d..e9f7507652 100644
--- a/scene/resources/font.h
+++ b/scene/resources/font.h
@@ -92,6 +92,8 @@ public:
virtual String get_font_name() const;
virtual String get_font_style_name() const;
virtual BitField<TextServer::FontStyle> get_font_style() const;
+ virtual int get_font_weight() const;
+ virtual int get_font_stretch() const;
virtual int get_spacing(TextServer::SpacingType p_spacing) const { return 0; };
virtual Dictionary get_opentype_features() const;
@@ -148,6 +150,7 @@ class FontFile : public Font {
int msdf_size = 48;
int fixed_size = 0;
bool force_autohinter = false;
+ bool allow_system_fallback = true;
TextServer::Hinting hinting = TextServer::HINTING_LIGHT;
TextServer::SubpixelPositioning subpixel_positioning = TextServer::SUBPIXEL_POSITIONING_AUTO;
real_t oversampling = 0.f;
@@ -191,6 +194,8 @@ public:
virtual void set_font_name(const String &p_name);
virtual void set_font_style_name(const String &p_name);
virtual void set_font_style(BitField<TextServer::FontStyle> p_style);
+ virtual void set_font_weight(int p_weight);
+ virtual void set_font_stretch(int p_stretch);
virtual void set_antialiasing(TextServer::FontAntialiasing p_antialiasing);
virtual TextServer::FontAntialiasing get_antialiasing() const;
@@ -210,6 +215,9 @@ public:
virtual void set_fixed_size(int p_fixed_size);
virtual int get_fixed_size() const;
+ virtual void set_allow_system_fallback(bool p_allow_system_fallback);
+ virtual bool is_allow_system_fallback() const;
+
virtual void set_force_autohinter(bool p_force_autohinter);
virtual bool is_force_autohinter() const;
@@ -389,18 +397,22 @@ class SystemFont : public Font {
GDCLASS(SystemFont, Font);
PackedStringArray names;
- BitField<TextServer::FontStyle> style = 0;
+ bool italic = false;
+ int weight = 400;
+ int stretch = 100;
mutable Ref<Font> theme_font;
Ref<FontFile> base_font;
Vector<int> face_indeces;
int ftr_weight = 0;
+ int ftr_stretch = 0;
int ftr_italic = 0;
TextServer::FontAntialiasing antialiasing = TextServer::FONT_ANTIALIASING_GRAY;
bool mipmaps = false;
bool force_autohinter = false;
+ bool allow_system_fallback = true;
TextServer::Hinting hinting = TextServer::HINTING_LIGHT;
TextServer::SubpixelPositioning subpixel_positioning = TextServer::SUBPIXEL_POSITIONING_AUTO;
real_t oversampling = 0.f;
@@ -423,6 +435,9 @@ public:
virtual void set_generate_mipmaps(bool p_generate_mipmaps);
virtual bool get_generate_mipmaps() const;
+ virtual void set_allow_system_fallback(bool p_allow_system_fallback);
+ virtual bool is_allow_system_fallback() const;
+
virtual void set_force_autohinter(bool p_force_autohinter);
virtual bool is_force_autohinter() const;
@@ -441,8 +456,14 @@ public:
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 void set_font_italic(bool p_italic);
+ virtual bool get_font_italic() const;
+
+ virtual void set_font_weight(int p_weight);
+ virtual int get_font_weight() const override;
+
+ virtual void set_font_stretch(int p_stretch);
+ virtual int get_font_stretch() const override;
virtual int get_spacing(TextServer::SpacingType p_spacing) const override;
diff --git a/scene/resources/importer_mesh.cpp b/scene/resources/importer_mesh.cpp
index cd08103187..b5e02b2f76 100644
--- a/scene/resources/importer_mesh.cpp
+++ b/scene/resources/importer_mesh.cpp
@@ -256,7 +256,7 @@ void ImporterMesh::set_surface_material(int p_surface, const Ref<Material> &p_ma
}
#define VERTEX_SKIN_FUNC(bone_count, vert_idx, read_array, write_array, transform_array, bone_array, weight_array) \
- Vector3 transformed_vert = Vector3(); \
+ Vector3 transformed_vert; \
for (unsigned int weight_idx = 0; weight_idx < bone_count; weight_idx++) { \
int bone_idx = bone_array[vert_idx * bone_count + weight_idx]; \
float w = weight_array[vert_idx * bone_count + weight_idx]; \
@@ -985,10 +985,10 @@ Vector<Ref<Shape3D>> ImporterMesh::convex_decompose(const Mesh::ConvexDecomposit
return ret;
}
-Ref<Shape3D> ImporterMesh::create_trimesh_shape() const {
+Ref<ConcavePolygonShape3D> ImporterMesh::create_trimesh_shape() const {
Vector<Face3> faces = get_faces();
if (faces.size() == 0) {
- return Ref<Shape3D>();
+ return Ref<ConcavePolygonShape3D>();
}
Vector<Vector3> face_points;
diff --git a/scene/resources/importer_mesh.h b/scene/resources/importer_mesh.h
index 088a77edd1..bbd6498fcf 100644
--- a/scene/resources/importer_mesh.h
+++ b/scene/resources/importer_mesh.h
@@ -119,7 +119,7 @@ public:
Vector<Face3> get_faces() const;
Vector<Ref<Shape3D>> convex_decompose(const Mesh::ConvexDecompositionSettings &p_settings) const;
- Ref<Shape3D> create_trimesh_shape() const;
+ Ref<ConcavePolygonShape3D> create_trimesh_shape() const;
Ref<NavigationMesh> create_navigation_mesh();
Error lightmap_unwrap_cached(const Transform3D &p_base_transform, float p_texel_size, const Vector<uint8_t> &p_src_cache, Vector<uint8_t> &r_dst_cache);
diff --git a/scene/resources/label_settings.cpp b/scene/resources/label_settings.cpp
index ef380a68f9..c49620ce27 100644
--- a/scene/resources/label_settings.cpp
+++ b/scene/resources/label_settings.cpp
@@ -66,16 +66,16 @@ void LabelSettings::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "line_spacing", PROPERTY_HINT_NONE, "suffix:px"), "set_line_spacing", "get_line_spacing");
- ADD_GROUP("Font", "font");
+ 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_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_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");
diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp
index 10d193f950..a16d2c2072 100644
--- a/scene/resources/material.cpp
+++ b/scene/resources/material.cpp
@@ -92,18 +92,13 @@ void Material::inspect_native_shader_code() {
RID Material::get_shader_rid() const {
RID ret;
- if (GDVIRTUAL_REQUIRED_CALL(_get_shader_rid, ret)) {
- return ret;
- }
- return RID();
+ GDVIRTUAL_REQUIRED_CALL(_get_shader_rid, ret);
+ return ret;
}
Shader::Mode Material::get_shader_mode() const {
- Shader::Mode ret;
- if (GDVIRTUAL_REQUIRED_CALL(_get_shader_mode, ret)) {
- return ret;
- }
-
- return Shader::MODE_MAX;
+ Shader::Mode ret = Shader::MODE_MAX;
+ GDVIRTUAL_REQUIRED_CALL(_get_shader_mode, ret);
+ return ret;
}
bool Material::_can_do_next_pass() const {
@@ -1257,15 +1252,16 @@ void BaseMaterial3D::_update_shader() {
}
if (distance_fade != DISTANCE_FADE_DISABLED) {
+ // Use the slightly more expensive circular fade (distance to the object) instead of linear
+ // (Z distance), so that the fade is always the same regardless of the camera angle.
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";
-
+ code += " float fade_distance = length((VIEW_MATRIX * MODEL_MATRIX[3]));\n";
} else {
- code += " float fade_distance = -VERTEX.z;\n";
+ code += " float fade_distance = length(VERTEX);\n";
}
// Use interleaved gradient noise, which is fast but still looks good.
code += " const vec3 magic = vec3(0.06711056f, 0.00583715f, 52.9829189f);";
@@ -1279,7 +1275,7 @@ void BaseMaterial3D::_update_shader() {
}
} else {
- code += " ALPHA*=clamp(smoothstep(distance_fade_min,distance_fade_max,-VERTEX.z),0.0,1.0);\n";
+ code += " ALPHA *= clamp(smoothstep(distance_fade_min, distance_fade_max, length(VERTEX)), 0.0, 1.0);\n";
}
}
diff --git a/scene/resources/mesh.cpp b/scene/resources/mesh.cpp
index d1e300e057..af770ddede 100644
--- a/scene/resources/mesh.cpp
+++ b/scene/resources/mesh.cpp
@@ -40,119 +40,83 @@
Mesh::ConvexDecompositionFunc Mesh::convex_decomposition_function = nullptr;
int Mesh::get_surface_count() const {
- int ret;
- if (GDVIRTUAL_REQUIRED_CALL(_get_surface_count, ret)) {
- return ret;
- }
- return 0;
+ int ret = 0;
+ GDVIRTUAL_REQUIRED_CALL(_get_surface_count, ret);
+ return ret;
}
int Mesh::surface_get_array_len(int p_idx) const {
- int ret;
- if (GDVIRTUAL_REQUIRED_CALL(_surface_get_array_len, p_idx, ret)) {
- return ret;
- }
- return 0;
+ int ret = 0;
+ GDVIRTUAL_REQUIRED_CALL(_surface_get_array_len, p_idx, ret);
+ return ret;
}
int Mesh::surface_get_array_index_len(int p_idx) const {
- int ret;
- if (GDVIRTUAL_REQUIRED_CALL(_surface_get_array_index_len, p_idx, ret)) {
- return ret;
- }
- return 0;
+ int ret = 0;
+ GDVIRTUAL_REQUIRED_CALL(_surface_get_array_index_len, p_idx, ret);
+ return ret;
}
Array Mesh::surface_get_arrays(int p_surface) const {
Array ret;
- if (GDVIRTUAL_REQUIRED_CALL(_surface_get_arrays, p_surface, ret)) {
- return ret;
- }
- return Array();
+ GDVIRTUAL_REQUIRED_CALL(_surface_get_arrays, p_surface, ret);
+ return ret;
}
TypedArray<Array> Mesh::surface_get_blend_shape_arrays(int p_surface) const {
TypedArray<Array> ret;
- if (GDVIRTUAL_REQUIRED_CALL(_surface_get_blend_shape_arrays, p_surface, ret)) {
- return ret;
- }
-
- return TypedArray<Array>();
+ GDVIRTUAL_REQUIRED_CALL(_surface_get_blend_shape_arrays, p_surface, ret);
+ return ret;
}
Dictionary Mesh::surface_get_lods(int p_surface) const {
Dictionary ret;
- if (GDVIRTUAL_REQUIRED_CALL(_surface_get_lods, p_surface, ret)) {
- return ret;
- }
-
- return Dictionary();
+ GDVIRTUAL_REQUIRED_CALL(_surface_get_lods, p_surface, ret);
+ return ret;
}
uint32_t Mesh::surface_get_format(int p_idx) const {
- uint32_t ret;
- if (GDVIRTUAL_REQUIRED_CALL(_surface_get_format, p_idx, ret)) {
- return ret;
- }
-
- return 0;
+ uint32_t ret = 0;
+ GDVIRTUAL_REQUIRED_CALL(_surface_get_format, p_idx, ret);
+ return ret;
}
Mesh::PrimitiveType Mesh::surface_get_primitive_type(int p_idx) const {
- uint32_t ret;
- if (GDVIRTUAL_REQUIRED_CALL(_surface_get_primitive_type, p_idx, ret)) {
- return (Mesh::PrimitiveType)ret;
- }
-
- return PRIMITIVE_MAX;
+ uint32_t ret = PRIMITIVE_MAX;
+ GDVIRTUAL_REQUIRED_CALL(_surface_get_primitive_type, p_idx, ret);
+ return (Mesh::PrimitiveType)ret;
}
void Mesh::surface_set_material(int p_idx, const Ref<Material> &p_material) {
- if (GDVIRTUAL_REQUIRED_CALL(_surface_set_material, p_idx, p_material)) {
- return;
- }
+ GDVIRTUAL_REQUIRED_CALL(_surface_set_material, p_idx, p_material);
}
Ref<Material> Mesh::surface_get_material(int p_idx) const {
Ref<Material> ret;
- if (GDVIRTUAL_REQUIRED_CALL(_surface_get_material, p_idx, ret)) {
- return ret;
- }
-
- return Ref<Material>();
+ GDVIRTUAL_REQUIRED_CALL(_surface_get_material, p_idx, ret);
+ return ret;
}
int Mesh::get_blend_shape_count() const {
- int ret;
- if (GDVIRTUAL_REQUIRED_CALL(_get_blend_shape_count, ret)) {
- return ret;
- }
-
- return 0;
+ int ret = 0;
+ GDVIRTUAL_REQUIRED_CALL(_get_blend_shape_count, ret);
+ return ret;
}
StringName Mesh::get_blend_shape_name(int p_index) const {
StringName ret;
- if (GDVIRTUAL_REQUIRED_CALL(_get_blend_shape_name, p_index, ret)) {
- return ret;
- }
-
- return StringName();
+ GDVIRTUAL_REQUIRED_CALL(_get_blend_shape_name, p_index, ret);
+ return ret;
}
void Mesh::set_blend_shape_name(int p_index, const StringName &p_name) {
- if (GDVIRTUAL_REQUIRED_CALL(_set_blend_shape_name, p_index, p_name)) {
- return;
- }
+ GDVIRTUAL_REQUIRED_CALL(_set_blend_shape_name, p_index, p_name);
}
AABB Mesh::get_aabb() const {
AABB ret;
- if (GDVIRTUAL_REQUIRED_CALL(_get_aabb, ret)) {
- return ret;
- }
-
- return AABB();
+ GDVIRTUAL_REQUIRED_CALL(_get_aabb, ret);
+ return ret;
}
Ref<TriangleMesh> Mesh::generate_triangle_mesh() const {
@@ -388,7 +352,7 @@ Vector<Face3> Mesh::get_surface_faces(int p_surface) const {
return Vector<Face3>();
}
-Ref<Shape3D> Mesh::create_convex_shape(bool p_clean, bool p_simplify) const {
+Ref<ConvexPolygonShape3D> Mesh::create_convex_shape(bool p_clean, bool p_simplify) const {
if (p_simplify) {
ConvexDecompositionSettings settings;
settings.max_convex_hulls = 1;
@@ -425,10 +389,10 @@ Ref<Shape3D> Mesh::create_convex_shape(bool p_clean, bool p_simplify) const {
return shape;
}
-Ref<Shape3D> Mesh::create_trimesh_shape() const {
+Ref<ConcavePolygonShape3D> Mesh::create_trimesh_shape() const {
Vector<Face3> faces = get_faces();
if (faces.size() == 0) {
- return Ref<Shape3D>();
+ return Ref<ConcavePolygonShape3D>();
}
Vector<Vector3> face_points;
@@ -1154,7 +1118,19 @@ bool ArrayMesh::_set(const StringName &p_name, const Variant &p_value) {
if (sl == -1) {
return false;
}
- int idx = sname.substr(8, sl - 8).to_int() - 1;
+ int idx = sname.substr(8, sl - 8).to_int();
+
+ // This is a bit of a hack to ensure compatibility with older material
+ // overrides that start indexing at 1.
+ // We assume that idx 0 is always read first, if its not, this won't work.
+ if (idx == 0) {
+ surface_index_0 = true;
+ }
+ if (!surface_index_0) {
+ // This means the file was created when the indexing started at 1, so decrease by one.
+ idx--;
+ }
+
String what = sname.get_slicec('/', 1);
if (what == "material") {
surface_set_material(idx, p_value);
@@ -1527,7 +1503,7 @@ bool ArrayMesh::_get(const StringName &p_name, Variant &r_ret) const {
if (sl == -1) {
return false;
}
- int idx = sname.substr(8, sl - 8).to_int() - 1;
+ int idx = sname.substr(8, sl - 8).to_int();
String what = sname.get_slicec('/', 1);
if (what == "material") {
r_ret = surface_get_material(idx);
@@ -1555,11 +1531,11 @@ void ArrayMesh::_get_property_list(List<PropertyInfo> *p_list) const {
}
for (int i = 0; i < surfaces.size(); i++) {
- p_list->push_back(PropertyInfo(Variant::STRING, "surface_" + itos(i + 1) + "/name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR));
+ p_list->push_back(PropertyInfo(Variant::STRING, "surface_" + itos(i) + "/name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR));
if (surfaces[i].is_2d) {
- p_list->push_back(PropertyInfo(Variant::OBJECT, "surface_" + itos(i + 1) + "/material", PROPERTY_HINT_RESOURCE_TYPE, "CanvasItemMaterial,ShaderMaterial", PROPERTY_USAGE_EDITOR));
+ p_list->push_back(PropertyInfo(Variant::OBJECT, "surface_" + itos(i) + "/material", PROPERTY_HINT_RESOURCE_TYPE, "CanvasItemMaterial,ShaderMaterial", PROPERTY_USAGE_EDITOR));
} else {
- p_list->push_back(PropertyInfo(Variant::OBJECT, "surface_" + itos(i + 1) + "/material", PROPERTY_HINT_RESOURCE_TYPE, "BaseMaterial3D,ShaderMaterial", PROPERTY_USAGE_EDITOR));
+ p_list->push_back(PropertyInfo(Variant::OBJECT, "surface_" + itos(i) + "/material", PROPERTY_HINT_RESOURCE_TYPE, "BaseMaterial3D,ShaderMaterial", PROPERTY_USAGE_EDITOR));
}
}
}
diff --git a/scene/resources/mesh.h b/scene/resources/mesh.h
index 5ed4164117..fabc09a42c 100644
--- a/scene/resources/mesh.h
+++ b/scene/resources/mesh.h
@@ -35,9 +35,12 @@
#include "core/math/face3.h"
#include "core/math/triangle_mesh.h"
#include "scene/resources/material.h"
-#include "scene/resources/shape_3d.h"
#include "servers/rendering_server.h"
+class ConcavePolygonShape3D;
+class ConvexPolygonShape3D;
+class Shape3D;
+
class Mesh : public Resource {
GDCLASS(Mesh, Resource);
@@ -211,8 +214,8 @@ public:
static ConvexDecompositionFunc convex_decomposition_function;
Vector<Ref<Shape3D>> convex_decompose(const ConvexDecompositionSettings &p_settings) const;
- Ref<Shape3D> create_convex_shape(bool p_clean = true, bool p_simplify = false) const;
- Ref<Shape3D> create_trimesh_shape() const;
+ Ref<ConvexPolygonShape3D> create_convex_shape(bool p_clean = true, bool p_simplify = false) const;
+ Ref<ConcavePolygonShape3D> create_trimesh_shape() const;
virtual int get_builtin_bind_pose_count() const;
virtual Transform3D get_builtin_bind_pose(int p_index) const;
@@ -259,6 +262,7 @@ 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;
+ bool surface_index_0 = false;
virtual void reset_state() override;
diff --git a/scene/resources/mesh_library.cpp b/scene/resources/mesh_library.cpp
index 7c78b757c7..858146da96 100644
--- a/scene/resources/mesh_library.cpp
+++ b/scene/resources/mesh_library.cpp
@@ -57,10 +57,18 @@ bool MeshLibrary::_set(const StringName &p_name, const Variant &p_value) {
_set_item_shapes(idx, p_value);
} else if (what == "preview") {
set_item_preview(idx, p_value);
- } else if (what == "navmesh") {
- set_item_navmesh(idx, p_value);
- } else if (what == "navmesh_transform") {
- set_item_navmesh_transform(idx, p_value);
+ } else if (what == "navigation_mesh") {
+ set_item_navigation_mesh(idx, p_value);
+ } else if (what == "navigation_mesh_transform") {
+ set_item_navigation_mesh_transform(idx, p_value);
+#ifndef DISABLE_DEPRECATED
+ } else if (what == "navmesh") { // Renamed in 4.0 beta 9.
+ set_item_navigation_mesh(idx, p_value);
+ } else if (what == "navmesh_transform") { // Renamed in 4.0 beta 9.
+ set_item_navigation_mesh_transform(idx, p_value);
+#endif // DISABLE_DEPRECATED
+ } else if (what == "navigation_layers") {
+ set_item_navigation_layers(idx, p_value);
} else {
return false;
}
@@ -85,10 +93,18 @@ bool MeshLibrary::_get(const StringName &p_name, Variant &r_ret) const {
r_ret = get_item_mesh_transform(idx);
} else if (what == "shapes") {
r_ret = _get_item_shapes(idx);
- } else if (what == "navmesh") {
- r_ret = get_item_navmesh(idx);
- } else if (what == "navmesh_transform") {
- r_ret = get_item_navmesh_transform(idx);
+ } else if (what == "navigation_mesh") {
+ r_ret = get_item_navigation_mesh(idx);
+ } else if (what == "navigation_mesh_transform") {
+ r_ret = get_item_navigation_mesh_transform(idx);
+#ifndef DISABLE_DEPRECATED
+ } else if (what == "navmesh") { // Renamed in 4.0 beta 9.
+ r_ret = get_item_navigation_mesh(idx);
+ } else if (what == "navmesh_transform") { // Renamed in 4.0 beta 9.
+ r_ret = get_item_navigation_mesh_transform(idx);
+#endif // DISABLE_DEPRECATED
+ } else if (what == "navigation_layers") {
+ r_ret = get_item_navigation_layers(idx);
} else if (what == "preview") {
r_ret = get_item_preview(idx);
} else {
@@ -105,8 +121,9 @@ void MeshLibrary::_get_property_list(List<PropertyInfo> *p_list) const {
p_list->push_back(PropertyInfo(Variant::OBJECT, prop_name + PNAME("mesh"), PROPERTY_HINT_RESOURCE_TYPE, "Mesh"));
p_list->push_back(PropertyInfo(Variant::TRANSFORM3D, prop_name + PNAME("mesh_transform"), PROPERTY_HINT_NONE, "suffix:m"));
p_list->push_back(PropertyInfo(Variant::ARRAY, prop_name + PNAME("shapes")));
- p_list->push_back(PropertyInfo(Variant::OBJECT, prop_name + PNAME("navmesh"), PROPERTY_HINT_RESOURCE_TYPE, "NavigationMesh"));
- p_list->push_back(PropertyInfo(Variant::TRANSFORM3D, prop_name + PNAME("navmesh_transform"), PROPERTY_HINT_NONE, "suffix:m"));
+ p_list->push_back(PropertyInfo(Variant::OBJECT, prop_name + PNAME("navigation_mesh"), PROPERTY_HINT_RESOURCE_TYPE, "NavigationMesh"));
+ p_list->push_back(PropertyInfo(Variant::TRANSFORM3D, prop_name + PNAME("navigation_mesh_transform"), PROPERTY_HINT_NONE, "suffix:m"));
+ p_list->push_back(PropertyInfo(Variant::INT, prop_name + PNAME("navigation_layers"), PROPERTY_HINT_LAYERS_3D_NAVIGATION));
p_list->push_back(PropertyInfo(Variant::OBJECT, prop_name + PNAME("preview"), PROPERTY_HINT_RESOURCE_TYPE, "Texture2D", PROPERTY_USAGE_DEFAULT));
}
}
@@ -150,18 +167,27 @@ void MeshLibrary::set_item_shapes(int p_item, const Vector<ShapeData> &p_shapes)
notify_property_list_changed();
}
-void MeshLibrary::set_item_navmesh(int p_item, const Ref<NavigationMesh> &p_navmesh) {
+void MeshLibrary::set_item_navigation_mesh(int p_item, const Ref<NavigationMesh> &p_navigation_mesh) {
ERR_FAIL_COND_MSG(!item_map.has(p_item), "Requested for nonexistent MeshLibrary item '" + itos(p_item) + "'.");
- item_map[p_item].navmesh = p_navmesh;
+ item_map[p_item].navigation_mesh = p_navigation_mesh;
notify_property_list_changed();
notify_change_to_owners();
emit_changed();
notify_property_list_changed();
}
-void MeshLibrary::set_item_navmesh_transform(int p_item, const Transform3D &p_transform) {
+void MeshLibrary::set_item_navigation_mesh_transform(int p_item, const Transform3D &p_transform) {
ERR_FAIL_COND_MSG(!item_map.has(p_item), "Requested for nonexistent MeshLibrary item '" + itos(p_item) + "'.");
- item_map[p_item].navmesh_transform = p_transform;
+ item_map[p_item].navigation_mesh_transform = p_transform;
+ notify_change_to_owners();
+ emit_changed();
+ notify_property_list_changed();
+}
+
+void MeshLibrary::set_item_navigation_layers(int p_item, uint32_t p_navigation_layers) {
+ ERR_FAIL_COND_MSG(!item_map.has(p_item), "Requested for nonexistent MeshLibrary item '" + itos(p_item) + "'.");
+ item_map[p_item].navigation_layers = p_navigation_layers;
+ notify_property_list_changed();
notify_change_to_owners();
emit_changed();
notify_property_list_changed();
@@ -194,14 +220,19 @@ Vector<MeshLibrary::ShapeData> MeshLibrary::get_item_shapes(int p_item) const {
return item_map[p_item].shapes;
}
-Ref<NavigationMesh> MeshLibrary::get_item_navmesh(int p_item) const {
+Ref<NavigationMesh> MeshLibrary::get_item_navigation_mesh(int p_item) const {
ERR_FAIL_COND_V_MSG(!item_map.has(p_item), Ref<NavigationMesh>(), "Requested for nonexistent MeshLibrary item '" + itos(p_item) + "'.");
- return item_map[p_item].navmesh;
+ return item_map[p_item].navigation_mesh;
}
-Transform3D MeshLibrary::get_item_navmesh_transform(int p_item) const {
+Transform3D MeshLibrary::get_item_navigation_mesh_transform(int p_item) const {
ERR_FAIL_COND_V_MSG(!item_map.has(p_item), Transform3D(), "Requested for nonexistent MeshLibrary item '" + itos(p_item) + "'.");
- return item_map[p_item].navmesh_transform;
+ return item_map[p_item].navigation_mesh_transform;
+}
+
+uint32_t MeshLibrary::get_item_navigation_layers(int p_item) const {
+ ERR_FAIL_COND_V_MSG(!item_map.has(p_item), 0, "Requested for nonexistent MeshLibrary item '" + itos(p_item) + "'.");
+ return item_map[p_item].navigation_layers;
}
Ref<Texture2D> MeshLibrary::get_item_preview(int p_item) const {
@@ -314,15 +345,17 @@ void MeshLibrary::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_item_name", "id", "name"), &MeshLibrary::set_item_name);
ClassDB::bind_method(D_METHOD("set_item_mesh", "id", "mesh"), &MeshLibrary::set_item_mesh);
ClassDB::bind_method(D_METHOD("set_item_mesh_transform", "id", "mesh_transform"), &MeshLibrary::set_item_mesh_transform);
- ClassDB::bind_method(D_METHOD("set_item_navmesh", "id", "navmesh"), &MeshLibrary::set_item_navmesh);
- ClassDB::bind_method(D_METHOD("set_item_navmesh_transform", "id", "navmesh"), &MeshLibrary::set_item_navmesh_transform);
+ ClassDB::bind_method(D_METHOD("set_item_navigation_mesh", "id", "navigation_mesh"), &MeshLibrary::set_item_navigation_mesh);
+ ClassDB::bind_method(D_METHOD("set_item_navigation_mesh_transform", "id", "navigation_mesh"), &MeshLibrary::set_item_navigation_mesh_transform);
+ ClassDB::bind_method(D_METHOD("set_item_navigation_layers", "id", "navigation_layers"), &MeshLibrary::set_item_navigation_layers);
ClassDB::bind_method(D_METHOD("set_item_shapes", "id", "shapes"), &MeshLibrary::_set_item_shapes);
ClassDB::bind_method(D_METHOD("set_item_preview", "id", "texture"), &MeshLibrary::set_item_preview);
ClassDB::bind_method(D_METHOD("get_item_name", "id"), &MeshLibrary::get_item_name);
ClassDB::bind_method(D_METHOD("get_item_mesh", "id"), &MeshLibrary::get_item_mesh);
ClassDB::bind_method(D_METHOD("get_item_mesh_transform", "id"), &MeshLibrary::get_item_mesh_transform);
- ClassDB::bind_method(D_METHOD("get_item_navmesh", "id"), &MeshLibrary::get_item_navmesh);
- ClassDB::bind_method(D_METHOD("get_item_navmesh_transform", "id"), &MeshLibrary::get_item_navmesh_transform);
+ ClassDB::bind_method(D_METHOD("get_item_navigation_mesh", "id"), &MeshLibrary::get_item_navigation_mesh);
+ ClassDB::bind_method(D_METHOD("get_item_navigation_mesh_transform", "id"), &MeshLibrary::get_item_navigation_mesh_transform);
+ ClassDB::bind_method(D_METHOD("get_item_navigation_layers", "id"), &MeshLibrary::get_item_navigation_layers);
ClassDB::bind_method(D_METHOD("get_item_shapes", "id"), &MeshLibrary::_get_item_shapes);
ClassDB::bind_method(D_METHOD("get_item_preview", "id"), &MeshLibrary::get_item_preview);
ClassDB::bind_method(D_METHOD("remove_item", "id"), &MeshLibrary::remove_item);
diff --git a/scene/resources/mesh_library.h b/scene/resources/mesh_library.h
index 79acb41c4e..1d5af9e176 100644
--- a/scene/resources/mesh_library.h
+++ b/scene/resources/mesh_library.h
@@ -49,11 +49,12 @@ public:
struct Item {
String name;
Ref<Mesh> mesh;
+ Transform3D mesh_transform;
Vector<ShapeData> shapes;
Ref<Texture2D> preview;
- Transform3D navmesh_transform;
- Transform3D mesh_transform;
- Ref<NavigationMesh> navmesh;
+ Ref<NavigationMesh> navigation_mesh;
+ Transform3D navigation_mesh_transform;
+ uint32_t navigation_layers = 1;
};
RBMap<int, Item> item_map;
@@ -74,15 +75,17 @@ public:
void set_item_name(int p_item, const String &p_name);
void set_item_mesh(int p_item, const Ref<Mesh> &p_mesh);
void set_item_mesh_transform(int p_item, const Transform3D &p_transform);
- void set_item_navmesh(int p_item, const Ref<NavigationMesh> &p_navmesh);
- void set_item_navmesh_transform(int p_item, const Transform3D &p_transform);
+ void set_item_navigation_mesh(int p_item, const Ref<NavigationMesh> &p_navigation_mesh);
+ void set_item_navigation_mesh_transform(int p_item, const Transform3D &p_transform);
+ void set_item_navigation_layers(int p_item, uint32_t p_navigation_layers);
void set_item_shapes(int p_item, const Vector<ShapeData> &p_shapes);
void set_item_preview(int p_item, const Ref<Texture2D> &p_preview);
String get_item_name(int p_item) const;
Ref<Mesh> get_item_mesh(int p_item) const;
Transform3D get_item_mesh_transform(int p_item) const;
- Ref<NavigationMesh> get_item_navmesh(int p_item) const;
- Transform3D get_item_navmesh_transform(int p_item) const;
+ Ref<NavigationMesh> get_item_navigation_mesh(int p_item) const;
+ Transform3D get_item_navigation_mesh_transform(int p_item) const;
+ uint32_t get_item_navigation_layers(int p_item) const;
Vector<ShapeData> get_item_shapes(int p_item) const;
Ref<Texture2D> get_item_preview(int p_item) const;
diff --git a/scene/resources/multimesh.cpp b/scene/resources/multimesh.cpp
index ff4a7a4560..8afb0563b2 100644
--- a/scene/resources/multimesh.cpp
+++ b/scene/resources/multimesh.cpp
@@ -242,6 +242,7 @@ void MultiMesh::set_instance_transform(int p_instance, const Transform3D &p_tran
void MultiMesh::set_instance_transform_2d(int p_instance, const Transform2D &p_transform) {
RenderingServer::get_singleton()->multimesh_instance_set_transform_2d(multimesh, p_instance, p_transform);
+ emit_changed();
}
Transform3D MultiMesh::get_instance_transform(int p_instance) const {
diff --git a/scene/resources/navigation_mesh.cpp b/scene/resources/navigation_mesh.cpp
index de97498674..bf4291869f 100644
--- a/scene/resources/navigation_mesh.cpp
+++ b/scene/resources/navigation_mesh.cpp
@@ -225,13 +225,13 @@ float NavigationMesh::get_edge_max_error() const {
return edge_max_error;
}
-void NavigationMesh::set_verts_per_poly(float p_value) {
+void NavigationMesh::set_vertices_per_polygon(float p_value) {
ERR_FAIL_COND(p_value < 3);
- verts_per_poly = p_value;
+ vertices_per_polygon = p_value;
}
-float NavigationMesh::get_verts_per_poly() const {
- return verts_per_poly;
+float NavigationMesh::get_vertices_per_polygon() const {
+ return vertices_per_polygon;
}
void NavigationMesh::set_detail_sample_distance(float p_value) {
@@ -483,8 +483,8 @@ void NavigationMesh::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_edge_max_error", "edge_max_error"), &NavigationMesh::set_edge_max_error);
ClassDB::bind_method(D_METHOD("get_edge_max_error"), &NavigationMesh::get_edge_max_error);
- ClassDB::bind_method(D_METHOD("set_verts_per_poly", "verts_per_poly"), &NavigationMesh::set_verts_per_poly);
- ClassDB::bind_method(D_METHOD("get_verts_per_poly"), &NavigationMesh::get_verts_per_poly);
+ ClassDB::bind_method(D_METHOD("set_vertices_per_polygon", "vertices_per_polygon"), &NavigationMesh::set_vertices_per_polygon);
+ ClassDB::bind_method(D_METHOD("get_vertices_per_polygon"), &NavigationMesh::get_vertices_per_polygon);
ClassDB::bind_method(D_METHOD("set_detail_sample_distance", "detail_sample_dist"), &NavigationMesh::set_detail_sample_distance);
ClassDB::bind_method(D_METHOD("get_detail_sample_distance"), &NavigationMesh::get_detail_sample_distance);
@@ -527,9 +527,9 @@ void NavigationMesh::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "geometry_parsed_geometry_type", PROPERTY_HINT_ENUM, "Mesh Instances,Static Colliders,Both"), "set_parsed_geometry_type", "get_parsed_geometry_type");
ADD_PROPERTY(PropertyInfo(Variant::INT, "geometry_collision_mask", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_mask", "get_collision_mask");
ADD_PROPERTY_DEFAULT("geometry_collision_mask", 0xFFFFFFFF);
- ADD_PROPERTY(PropertyInfo(Variant::INT, "geometry_source_geometry_mode", PROPERTY_HINT_ENUM, "NavMesh Children,Group With Children,Group Explicit"), "set_source_geometry_mode", "get_source_geometry_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "geometry_source_geometry_mode", PROPERTY_HINT_ENUM, "Root Node Children,Group With Children,Group Explicit"), "set_source_geometry_mode", "get_source_geometry_mode");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "geometry_source_group_name"), "set_source_group_name", "get_source_group_name");
- ADD_PROPERTY_DEFAULT("geometry_source_group_name", StringName("navmesh"));
+ ADD_PROPERTY_DEFAULT("geometry_source_group_name", StringName("navigation_mesh_source_group"));
ADD_GROUP("Cells", "cell_");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "cell_size", PROPERTY_HINT_RANGE, "0.01,500.0,0.01,or_greater,suffix:m"), "set_cell_size", "get_cell_size");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "cell_height", PROPERTY_HINT_RANGE, "0.01,500.0,0.01,or_greater,suffix:m"), "set_cell_height", "get_cell_height");
@@ -544,8 +544,8 @@ void NavigationMesh::_bind_methods() {
ADD_GROUP("Edges", "edge_");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "edge_max_length", PROPERTY_HINT_RANGE, "0.0,50.0,0.01,or_greater,suffix:m"), "set_edge_max_length", "get_edge_max_length");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "edge_max_error", PROPERTY_HINT_RANGE, "0.1,3.0,0.01,or_greater,suffix:m"), "set_edge_max_error", "get_edge_max_error");
- ADD_GROUP("Polygons", "polygon_");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "polygon_verts_per_poly", PROPERTY_HINT_RANGE, "3.0,12.0,1.0,or_greater"), "set_verts_per_poly", "get_verts_per_poly");
+ ADD_GROUP("Polygons", "");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "vertices_per_polygon", PROPERTY_HINT_RANGE, "3.0,12.0,1.0,or_greater"), "set_vertices_per_polygon", "get_vertices_per_polygon");
ADD_GROUP("Details", "detail_");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "detail_sample_distance", PROPERTY_HINT_RANGE, "0.1,16.0,0.01,or_greater,suffix:m"), "set_detail_sample_distance", "get_detail_sample_distance");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "detail_sample_max_error", PROPERTY_HINT_RANGE, "0.0,16.0,0.01,or_greater,suffix:m"), "set_detail_sample_max_error", "get_detail_sample_max_error");
@@ -566,7 +566,7 @@ void NavigationMesh::_bind_methods() {
BIND_ENUM_CONSTANT(PARSED_GEOMETRY_BOTH);
BIND_ENUM_CONSTANT(PARSED_GEOMETRY_MAX);
- BIND_ENUM_CONSTANT(SOURCE_GEOMETRY_NAVMESH_CHILDREN);
+ BIND_ENUM_CONSTANT(SOURCE_GEOMETRY_ROOT_NODE_CHILDREN);
BIND_ENUM_CONSTANT(SOURCE_GEOMETRY_GROUPS_WITH_CHILDREN);
BIND_ENUM_CONSTANT(SOURCE_GEOMETRY_GROUPS_EXPLICIT);
BIND_ENUM_CONSTANT(SOURCE_GEOMETRY_MAX);
@@ -581,7 +581,7 @@ void NavigationMesh::_validate_property(PropertyInfo &p_property) const {
}
if (p_property.name == "geometry_source_group_name") {
- if (source_geometry_mode == SOURCE_GEOMETRY_NAVMESH_CHILDREN) {
+ if (source_geometry_mode == SOURCE_GEOMETRY_ROOT_NODE_CHILDREN) {
p_property.usage = PROPERTY_USAGE_NONE;
return;
}
@@ -590,35 +590,16 @@ void NavigationMesh::_validate_property(PropertyInfo &p_property) const {
#ifndef DISABLE_DEPRECATED
bool NavigationMesh::_set(const StringName &p_name, const Variant &p_value) {
- String prop_name = p_name;
- if (prop_name.find("/") != -1) {
- // Compatibility with pre-3.5 "category/path" property names.
- prop_name = prop_name.replace("/", "_");
- if (prop_name == "sample_partition_type_sample_partition_type") {
- set("sample_partition_type", p_value);
- } else if (prop_name == "filter_filter_walkable_low_height_spans") {
- set("filter_walkable_low_height_spans", p_value);
- } else {
- set(prop_name, p_value);
- }
-
+ if (p_name == "polygon_verts_per_poly") { // Renamed in 4.0 beta 9.
+ set_vertices_per_polygon(p_value);
return true;
}
return false;
}
bool NavigationMesh::_get(const StringName &p_name, Variant &r_ret) const {
- String prop_name = p_name;
- if (prop_name.find("/") != -1) {
- // Compatibility with pre-3.5 "category/path" property names.
- prop_name = prop_name.replace("/", "_");
- if (prop_name == "sample_partition_type_sample_partition_type") {
- r_ret = get("sample_partition_type");
- } else if (prop_name == "filter_filter_walkable_low_height_spans") {
- r_ret = get("filter_walkable_low_height_spans");
- } else {
- r_ret = get(prop_name);
- }
+ if (p_name == "polygon_verts_per_poly") { // Renamed in 4.0 beta 9.
+ r_ret = get_vertices_per_polygon();
return true;
}
return false;
diff --git a/scene/resources/navigation_mesh.h b/scene/resources/navigation_mesh.h
index 5ddbd75dcb..3d072423db 100644
--- a/scene/resources/navigation_mesh.h
+++ b/scene/resources/navigation_mesh.h
@@ -84,7 +84,7 @@ public:
};
enum SourceGeometryMode {
- SOURCE_GEOMETRY_NAVMESH_CHILDREN = 0,
+ SOURCE_GEOMETRY_ROOT_NODE_CHILDREN = 0,
SOURCE_GEOMETRY_GROUPS_WITH_CHILDREN,
SOURCE_GEOMETRY_GROUPS_EXPLICIT,
SOURCE_GEOMETRY_MAX
@@ -101,7 +101,7 @@ protected:
float region_merge_size = 20.0f;
float edge_max_length = 12.0f;
float edge_max_error = 1.3f;
- float verts_per_poly = 6.0f;
+ float vertices_per_polygon = 6.0f;
float detail_sample_distance = 6.0f;
float detail_sample_max_error = 1.0f;
@@ -109,8 +109,8 @@ protected:
ParsedGeometryType parsed_geometry_type = PARSED_GEOMETRY_MESH_INSTANCES;
uint32_t collision_mask = 0xFFFFFFFF;
- SourceGeometryMode source_geometry_mode = SOURCE_GEOMETRY_NAVMESH_CHILDREN;
- StringName source_group_name = "navmesh";
+ SourceGeometryMode source_geometry_mode = SOURCE_GEOMETRY_ROOT_NODE_CHILDREN;
+ StringName source_group_name = "navigation_mesh_source_group";
bool filter_low_hanging_obstacles = false;
bool filter_ledge_spans = false;
@@ -168,8 +168,8 @@ public:
void set_edge_max_error(float p_value);
float get_edge_max_error() const;
- void set_verts_per_poly(float p_value);
- float get_verts_per_poly() const;
+ void set_vertices_per_polygon(float p_value);
+ float get_vertices_per_polygon() const;
void set_detail_sample_distance(float p_value);
float get_detail_sample_distance() const;
diff --git a/scene/resources/navigation_polygon.cpp b/scene/resources/navigation_polygon.cpp
new file mode 100644
index 0000000000..04077e95a7
--- /dev/null
+++ b/scene/resources/navigation_polygon.cpp
@@ -0,0 +1,354 @@
+/*************************************************************************/
+/* navigation_polygon.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 "navigation_polygon.h"
+
+#include "core/core_string_names.h"
+#include "core/math/geometry_2d.h"
+#include "core/os/mutex.h"
+
+#include "thirdparty/misc/polypartition.h"
+
+#ifdef TOOLS_ENABLED
+Rect2 NavigationPolygon::_edit_get_rect() const {
+ if (rect_cache_dirty) {
+ item_rect = Rect2();
+ bool first = true;
+
+ for (int i = 0; i < outlines.size(); i++) {
+ const Vector<Vector2> &outline = outlines[i];
+ const int outline_size = outline.size();
+ if (outline_size < 3) {
+ continue;
+ }
+ const Vector2 *p = outline.ptr();
+ for (int j = 0; j < outline_size; j++) {
+ if (first) {
+ item_rect = Rect2(p[j], Vector2(0, 0));
+ first = false;
+ } else {
+ item_rect.expand_to(p[j]);
+ }
+ }
+ }
+
+ rect_cache_dirty = false;
+ }
+ return item_rect;
+}
+
+bool NavigationPolygon::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const {
+ for (int i = 0; i < outlines.size(); i++) {
+ const Vector<Vector2> &outline = outlines[i];
+ const int outline_size = outline.size();
+ if (outline_size < 3) {
+ continue;
+ }
+ if (Geometry2D::is_point_in_polygon(p_point, Variant(outline))) {
+ return true;
+ }
+ }
+ return false;
+}
+#endif
+
+void NavigationPolygon::set_vertices(const Vector<Vector2> &p_vertices) {
+ {
+ MutexLock lock(navigation_mesh_generation);
+ navigation_mesh.unref();
+ }
+ vertices = p_vertices;
+ rect_cache_dirty = true;
+}
+
+Vector<Vector2> NavigationPolygon::get_vertices() const {
+ return vertices;
+}
+
+void NavigationPolygon::_set_polygons(const TypedArray<Vector<int32_t>> &p_array) {
+ {
+ MutexLock lock(navigation_mesh_generation);
+ navigation_mesh.unref();
+ }
+ polygons.resize(p_array.size());
+ for (int i = 0; i < p_array.size(); i++) {
+ polygons.write[i].indices = p_array[i];
+ }
+}
+
+TypedArray<Vector<int32_t>> NavigationPolygon::_get_polygons() const {
+ TypedArray<Vector<int32_t>> ret;
+ ret.resize(polygons.size());
+ for (int i = 0; i < ret.size(); i++) {
+ ret[i] = polygons[i].indices;
+ }
+
+ return ret;
+}
+
+void NavigationPolygon::_set_outlines(const TypedArray<Vector<Vector2>> &p_array) {
+ outlines.resize(p_array.size());
+ for (int i = 0; i < p_array.size(); i++) {
+ outlines.write[i] = p_array[i];
+ }
+ rect_cache_dirty = true;
+}
+
+TypedArray<Vector<Vector2>> NavigationPolygon::_get_outlines() const {
+ TypedArray<Vector<Vector2>> ret;
+ ret.resize(outlines.size());
+ for (int i = 0; i < ret.size(); i++) {
+ ret[i] = outlines[i];
+ }
+
+ return ret;
+}
+
+void NavigationPolygon::add_polygon(const Vector<int> &p_polygon) {
+ Polygon polygon;
+ polygon.indices = p_polygon;
+ polygons.push_back(polygon);
+ {
+ MutexLock lock(navigation_mesh_generation);
+ navigation_mesh.unref();
+ }
+}
+
+void NavigationPolygon::add_outline_at_index(const Vector<Vector2> &p_outline, int p_index) {
+ outlines.insert(p_index, p_outline);
+ rect_cache_dirty = true;
+}
+
+int NavigationPolygon::get_polygon_count() const {
+ return polygons.size();
+}
+
+Vector<int> NavigationPolygon::get_polygon(int p_idx) {
+ ERR_FAIL_INDEX_V(p_idx, polygons.size(), Vector<int>());
+ return polygons[p_idx].indices;
+}
+
+void NavigationPolygon::clear_polygons() {
+ polygons.clear();
+ {
+ MutexLock lock(navigation_mesh_generation);
+ navigation_mesh.unref();
+ }
+}
+
+Ref<NavigationMesh> NavigationPolygon::get_navigation_mesh() {
+ MutexLock lock(navigation_mesh_generation);
+
+ if (navigation_mesh.is_null()) {
+ navigation_mesh.instantiate();
+ Vector<Vector3> verts;
+ {
+ verts.resize(get_vertices().size());
+ Vector3 *w = verts.ptrw();
+
+ const Vector2 *r = get_vertices().ptr();
+
+ for (int i(0); i < get_vertices().size(); i++) {
+ w[i] = Vector3(r[i].x, 0.0, r[i].y);
+ }
+ }
+ navigation_mesh->set_vertices(verts);
+
+ for (int i(0); i < get_polygon_count(); i++) {
+ navigation_mesh->add_polygon(get_polygon(i));
+ }
+ }
+
+ return navigation_mesh;
+}
+
+void NavigationPolygon::add_outline(const Vector<Vector2> &p_outline) {
+ outlines.push_back(p_outline);
+ rect_cache_dirty = true;
+}
+
+int NavigationPolygon::get_outline_count() const {
+ return outlines.size();
+}
+
+void NavigationPolygon::set_outline(int p_idx, const Vector<Vector2> &p_outline) {
+ ERR_FAIL_INDEX(p_idx, outlines.size());
+ outlines.write[p_idx] = p_outline;
+ rect_cache_dirty = true;
+}
+
+void NavigationPolygon::remove_outline(int p_idx) {
+ ERR_FAIL_INDEX(p_idx, outlines.size());
+ outlines.remove_at(p_idx);
+ rect_cache_dirty = true;
+}
+
+Vector<Vector2> NavigationPolygon::get_outline(int p_idx) const {
+ ERR_FAIL_INDEX_V(p_idx, outlines.size(), Vector<Vector2>());
+ return outlines[p_idx];
+}
+
+void NavigationPolygon::clear_outlines() {
+ outlines.clear();
+ rect_cache_dirty = true;
+}
+
+void NavigationPolygon::make_polygons_from_outlines() {
+ {
+ MutexLock lock(navigation_mesh_generation);
+ navigation_mesh.unref();
+ }
+ List<TPPLPoly> in_poly, out_poly;
+
+ Vector2 outside_point(-1e10, -1e10);
+
+ for (int i = 0; i < outlines.size(); i++) {
+ Vector<Vector2> ol = outlines[i];
+ int olsize = ol.size();
+ if (olsize < 3) {
+ continue;
+ }
+ const Vector2 *r = ol.ptr();
+ for (int j = 0; j < olsize; j++) {
+ outside_point.x = MAX(r[j].x, outside_point.x);
+ outside_point.y = MAX(r[j].y, outside_point.y);
+ }
+ }
+
+ outside_point += Vector2(0.7239784, 0.819238); //avoid precision issues
+
+ for (int i = 0; i < outlines.size(); i++) {
+ Vector<Vector2> ol = outlines[i];
+ int olsize = ol.size();
+ if (olsize < 3) {
+ continue;
+ }
+ const Vector2 *r = ol.ptr();
+
+ int interscount = 0;
+ //test if this is an outer outline
+ for (int k = 0; k < outlines.size(); k++) {
+ if (i == k) {
+ continue; //no self intersect
+ }
+
+ Vector<Vector2> ol2 = outlines[k];
+ int olsize2 = ol2.size();
+ if (olsize2 < 3) {
+ continue;
+ }
+ const Vector2 *r2 = ol2.ptr();
+
+ for (int l = 0; l < olsize2; l++) {
+ if (Geometry2D::segment_intersects_segment(r[0], outside_point, r2[l], r2[(l + 1) % olsize2], nullptr)) {
+ interscount++;
+ }
+ }
+ }
+
+ bool outer = (interscount % 2) == 0;
+
+ TPPLPoly tp;
+ tp.Init(olsize);
+ for (int j = 0; j < olsize; j++) {
+ tp[j] = r[j];
+ }
+
+ if (outer) {
+ tp.SetOrientation(TPPL_ORIENTATION_CCW);
+ } else {
+ tp.SetOrientation(TPPL_ORIENTATION_CW);
+ tp.SetHole(true);
+ }
+
+ in_poly.push_back(tp);
+ }
+
+ TPPLPartition tpart;
+ if (tpart.ConvexPartition_HM(&in_poly, &out_poly) == 0) { //failed!
+ ERR_PRINT("NavigationPolygon: Convex partition failed! Failed to convert outlines to a valid NavigationMesh."
+ "\nNavigationPolygon outlines can not overlap vertices or edges inside same outline or with other outlines or have any intersections."
+ "\nAdd the outmost and largest outline first. To add holes inside this outline add the smaller outlines with opposite winding order.");
+ return;
+ }
+
+ polygons.clear();
+ vertices.clear();
+
+ HashMap<Vector2, int> points;
+ for (List<TPPLPoly>::Element *I = out_poly.front(); I; I = I->next()) {
+ TPPLPoly &tp = I->get();
+
+ struct Polygon p;
+
+ for (int64_t i = 0; i < tp.GetNumPoints(); i++) {
+ HashMap<Vector2, int>::Iterator E = points.find(tp[i]);
+ if (!E) {
+ E = points.insert(tp[i], vertices.size());
+ vertices.push_back(tp[i]);
+ }
+ p.indices.push_back(E->value);
+ }
+
+ polygons.push_back(p);
+ }
+
+ emit_signal(CoreStringNames::get_singleton()->changed);
+}
+
+void NavigationPolygon::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_vertices", "vertices"), &NavigationPolygon::set_vertices);
+ ClassDB::bind_method(D_METHOD("get_vertices"), &NavigationPolygon::get_vertices);
+
+ ClassDB::bind_method(D_METHOD("add_polygon", "polygon"), &NavigationPolygon::add_polygon);
+ ClassDB::bind_method(D_METHOD("get_polygon_count"), &NavigationPolygon::get_polygon_count);
+ ClassDB::bind_method(D_METHOD("get_polygon", "idx"), &NavigationPolygon::get_polygon);
+ ClassDB::bind_method(D_METHOD("clear_polygons"), &NavigationPolygon::clear_polygons);
+ ClassDB::bind_method(D_METHOD("get_navigation_mesh"), &NavigationPolygon::get_navigation_mesh);
+
+ ClassDB::bind_method(D_METHOD("add_outline", "outline"), &NavigationPolygon::add_outline);
+ ClassDB::bind_method(D_METHOD("add_outline_at_index", "outline", "index"), &NavigationPolygon::add_outline_at_index);
+ ClassDB::bind_method(D_METHOD("get_outline_count"), &NavigationPolygon::get_outline_count);
+ ClassDB::bind_method(D_METHOD("set_outline", "idx", "outline"), &NavigationPolygon::set_outline);
+ ClassDB::bind_method(D_METHOD("get_outline", "idx"), &NavigationPolygon::get_outline);
+ ClassDB::bind_method(D_METHOD("remove_outline", "idx"), &NavigationPolygon::remove_outline);
+ ClassDB::bind_method(D_METHOD("clear_outlines"), &NavigationPolygon::clear_outlines);
+ ClassDB::bind_method(D_METHOD("make_polygons_from_outlines"), &NavigationPolygon::make_polygons_from_outlines);
+
+ ClassDB::bind_method(D_METHOD("_set_polygons", "polygons"), &NavigationPolygon::_set_polygons);
+ ClassDB::bind_method(D_METHOD("_get_polygons"), &NavigationPolygon::_get_polygons);
+
+ ClassDB::bind_method(D_METHOD("_set_outlines", "outlines"), &NavigationPolygon::_set_outlines);
+ ClassDB::bind_method(D_METHOD("_get_outlines"), &NavigationPolygon::_get_outlines);
+
+ ADD_PROPERTY(PropertyInfo(Variant::PACKED_VECTOR2_ARRAY, "vertices", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "set_vertices", "get_vertices");
+ ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "polygons", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_polygons", "_get_polygons");
+ ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "outlines", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_outlines", "_get_outlines");
+}
diff --git a/scene/resources/navigation_polygon.h b/scene/resources/navigation_polygon.h
new file mode 100644
index 0000000000..e943cff04e
--- /dev/null
+++ b/scene/resources/navigation_polygon.h
@@ -0,0 +1,94 @@
+/*************************************************************************/
+/* navigation_polygon.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 NAVIGATION_POLYGON_H
+#define NAVIGATION_POLYGON_H
+
+#include "scene/2d/node_2d.h"
+#include "scene/resources/navigation_mesh.h"
+
+class NavigationPolygon : public Resource {
+ GDCLASS(NavigationPolygon, Resource);
+
+ Vector<Vector2> vertices;
+ struct Polygon {
+ Vector<int> indices;
+ };
+ Vector<Polygon> polygons;
+ Vector<Vector<Vector2>> outlines;
+
+ mutable Rect2 item_rect;
+ mutable bool rect_cache_dirty = true;
+
+ Mutex navigation_mesh_generation;
+ // Navigation mesh
+ Ref<NavigationMesh> navigation_mesh;
+
+protected:
+ static void _bind_methods();
+
+ void _set_polygons(const TypedArray<Vector<int32_t>> &p_array);
+ TypedArray<Vector<int32_t>> _get_polygons() const;
+
+ void _set_outlines(const TypedArray<Vector<Vector2>> &p_array);
+ TypedArray<Vector<Vector2>> _get_outlines() const;
+
+public:
+#ifdef TOOLS_ENABLED
+ Rect2 _edit_get_rect() const;
+ bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const;
+#endif
+
+ void set_vertices(const Vector<Vector2> &p_vertices);
+ Vector<Vector2> get_vertices() const;
+
+ void add_polygon(const Vector<int> &p_polygon);
+ int get_polygon_count() const;
+
+ void add_outline(const Vector<Vector2> &p_outline);
+ void add_outline_at_index(const Vector<Vector2> &p_outline, int p_index);
+ void set_outline(int p_idx, const Vector<Vector2> &p_outline);
+ Vector<Vector2> get_outline(int p_idx) const;
+ void remove_outline(int p_idx);
+ int get_outline_count() const;
+
+ void clear_outlines();
+ void make_polygons_from_outlines();
+
+ Vector<int> get_polygon(int p_idx);
+ void clear_polygons();
+
+ Ref<NavigationMesh> get_navigation_mesh();
+
+ NavigationPolygon() {}
+ ~NavigationPolygon() {}
+};
+
+#endif // NAVIGATION_POLYGON_H
diff --git a/scene/resources/packed_scene.cpp b/scene/resources/packed_scene.cpp
index 1c99fa5554..5316b524ba 100644
--- a/scene/resources/packed_scene.cpp
+++ b/scene/resources/packed_scene.cpp
@@ -71,7 +71,7 @@ static Array _sanitize_node_pinned_properties(Node *p_node) {
}
Node *SceneState::instantiate(GenEditState p_edit_state) const {
- // nodes where instancing failed (because something is missing)
+ // Nodes where instantiation failed (because something is missing.)
List<Node *> stray_instances;
#define NODE_FROM_ID(p_name, p_id) \
@@ -122,7 +122,7 @@ Node *SceneState::instantiate(GenEditState p_edit_state) const {
NODE_FROM_ID(nparent, n.parent);
#ifdef DEBUG_ENABLED
if (!nparent && (n.parent & FLAG_ID_IS_PATH)) {
- WARN_PRINT(String("Parent path '" + String(node_paths[n.parent & FLAG_MASK]) + "' for node '" + String(snames[n.name]) + "' has vanished when instancing: '" + get_path() + "'.").ascii().get_data());
+ WARN_PRINT(String("Parent path '" + String(node_paths[n.parent & FLAG_MASK]) + "' for node '" + String(snames[n.name]) + "' has vanished when instantiating: '" + get_path() + "'.").ascii().get_data());
old_parent_path = String(node_paths[n.parent & FLAG_MASK]).trim_prefix("./").replace("/", "@");
nparent = ret_nodes[0];
}
@@ -131,7 +131,7 @@ Node *SceneState::instantiate(GenEditState p_edit_state) const {
} else {
// i == 0 is root node.
ERR_FAIL_COND_V_MSG(n.parent != -1, nullptr, vformat("Invalid scene: root node %s cannot specify a parent node.", snames[n.name]));
- ERR_FAIL_COND_V_MSG(n.type == TYPE_INSTANCED && base_scene_idx < 0, nullptr, vformat("Invalid scene: root node %s in an instance, but there's no base scene.", snames[n.name]));
+ ERR_FAIL_COND_V_MSG(n.type == TYPE_INSTANTIATED && base_scene_idx < 0, nullptr, vformat("Invalid scene: root node %s in an instance, but there's no base scene.", snames[n.name]));
}
Node *node = nullptr;
@@ -169,7 +169,7 @@ Node *SceneState::instantiate(GenEditState p_edit_state) const {
ERR_FAIL_COND_V(!node, nullptr);
}
- } else if (n.type == TYPE_INSTANCED) {
+ } else if (n.type == TYPE_INSTANTIATED) {
//get the node from somewhere, it likely already exists from another instance
if (parent) {
node = parent->_get_child_by_name(snames[n.name]);
@@ -345,7 +345,7 @@ Node *SceneState::instantiate(GenEditState p_edit_state) const {
node->add_to_group(snames[n.groups[j]], true);
}
- if (n.instance >= 0 || n.type != TYPE_INSTANCED || i == 0) {
+ if (n.instance >= 0 || n.type != TYPE_INSTANTIATED || i == 0) {
//if node was not part of instance, must set its name, parenthood and ownership
if (i > 0) {
if (parent) {
@@ -382,7 +382,7 @@ Node *SceneState::instantiate(GenEditState p_edit_state) const {
}
}
- // we only want to deal with pinned flag if instancing as pure main (no instance, no inheriting)
+ // We only want to deal with pinned flag if instantiating as pure main (no instance, no inheriting.)
if (p_edit_state == GEN_EDIT_STATE_MAIN) {
_sanitize_node_pinned_properties(node);
} else {
@@ -450,7 +450,7 @@ Node *SceneState::instantiate(GenEditState p_edit_state) const {
callable = callable.bindp(argptrs, binds.size());
}
- cfrom->connect(snames[c.signal], callable, CONNECT_PERSIST | c.flags);
+ cfrom->connect(snames[c.signal], callable, CONNECT_PERSIST | c.flags | (p_edit_state == GEN_EDIT_STATE_MAIN ? 0 : CONNECT_INHERITED));
}
//Node *s = ret_nodes[0];
@@ -665,7 +665,7 @@ Error SceneState::_parse_node(Node *p_owner, Node *p_node, int p_parent_idx, Has
// Save the right type. If this node was created by an instance
// then flag that the node should not be created but reused
if (states_stack.is_empty() && !is_editable_instance) {
- //this node is not part of an instancing process, so save the type
+ //This node is not part of an instantiation process, so save the type.
if (missing_node != nullptr) {
// It's a missing node (type non existent on load).
nd.type = _nm_get_string(missing_node->get_original_class(), name_map);
@@ -675,7 +675,7 @@ Error SceneState::_parse_node(Node *p_owner, Node *p_node, int p_parent_idx, Has
} else {
// this node is part of an instantiated process, so do not save the type.
// instead, save that it was instantiated
- nd.type = TYPE_INSTANCED;
+ nd.type = TYPE_INSTANTIATED;
}
// determine whether to save this node or not
@@ -1005,6 +1005,37 @@ void SceneState::clear() {
base_scene_idx = -1;
}
+Error SceneState::copy_from(const Ref<SceneState> &p_scene_state) {
+ ERR_FAIL_COND_V(p_scene_state.is_null(), ERR_INVALID_PARAMETER);
+
+ clear();
+
+ for (const StringName &E : p_scene_state->names) {
+ names.append(E);
+ }
+ for (const Variant &E : p_scene_state->variants) {
+ variants.append(E);
+ }
+ for (const SceneState::NodeData &E : p_scene_state->nodes) {
+ nodes.append(E);
+ }
+ for (const SceneState::ConnectionData &E : p_scene_state->connections) {
+ connections.append(E);
+ }
+ for (KeyValue<NodePath, int> &E : p_scene_state->node_path_cache) {
+ node_path_cache.insert(E.key, E.value);
+ }
+ for (const NodePath &E : p_scene_state->node_paths) {
+ node_paths.append(E);
+ }
+ for (const NodePath &E : p_scene_state->editable_instances) {
+ editable_instances.append(E);
+ }
+ base_scene_idx = p_scene_state->base_scene_idx;
+
+ return OK;
+}
+
Ref<SceneState> SceneState::get_base_scene_state() const {
if (base_scene_idx >= 0) {
Ref<PackedScene> ps = variants[base_scene_idx];
@@ -1351,7 +1382,7 @@ int SceneState::get_node_count() const {
StringName SceneState::get_node_type(int p_idx) const {
ERR_FAIL_INDEX_V(p_idx, nodes.size(), StringName());
- if (nodes[p_idx].type == TYPE_INSTANCED) {
+ if (nodes[p_idx].type == TYPE_INSTANTIATED) {
return StringName();
}
return names[nodes[p_idx].type];
@@ -1737,6 +1768,28 @@ void PackedScene::clear() {
state->clear();
}
+void PackedScene::reload_from_file() {
+ String path = get_path();
+ if (!path.is_resource_file()) {
+ return;
+ }
+
+ Ref<PackedScene> s = ResourceLoader::load(ResourceLoader::path_remap(path), get_class(), ResourceFormatLoader::CACHE_MODE_IGNORE);
+ if (!s.is_valid()) {
+ return;
+ }
+
+ // Backup the loaded_state
+ Ref<SceneState> loaded_state = s->get_state();
+ // This assigns a new state to s->state
+ // We do this because of the next step
+ s->recreate_state();
+ // This has a side-effect to clear s->state
+ copy_from(s);
+ // Then, we copy the backed-up loaded_state to state
+ state->copy_from(loaded_state);
+}
+
bool PackedScene::can_instantiate() const {
return state->can_instantiate();
}
diff --git a/scene/resources/packed_scene.h b/scene/resources/packed_scene.h
index c6f82ddd5e..ad1f50cd39 100644
--- a/scene/resources/packed_scene.h
+++ b/scene/resources/packed_scene.h
@@ -108,7 +108,7 @@ protected:
public:
enum {
FLAG_ID_IS_PATH = (1 << 30),
- TYPE_INSTANCED = 0x7FFFFFFF,
+ TYPE_INSTANTIATED = 0x7FFFFFFF,
FLAG_INSTANCE_IS_PLACEHOLDER = (1 << 30),
FLAG_PATH_PROPERTY_IS_NODE = (1 << 30),
FLAG_PROP_NAME_MASK = FLAG_PATH_PROPERTY_IS_NODE - 1,
@@ -143,6 +143,7 @@ public:
String get_path() const;
void clear();
+ Error copy_from(const Ref<SceneState> &p_scene_state);
bool can_instantiate() const;
Node *instantiate(GenEditState p_edit_state) const;
@@ -235,6 +236,8 @@ public:
void recreate_state();
void replace_state(Ref<SceneState> p_by);
+ virtual void reload_from_file() override;
+
virtual void set_path(const String &p_path, bool p_take_over = false) override;
#ifdef TOOLS_ENABLED
virtual void set_last_modified_time(uint64_t p_time) override {
diff --git a/scene/resources/primitive_meshes.cpp b/scene/resources/primitive_meshes.cpp
index eb83a37c7b..54d3676c15 100644
--- a/scene/resources/primitive_meshes.cpp
+++ b/scene/resources/primitive_meshes.cpp
@@ -30,6 +30,7 @@
#include "primitive_meshes.h"
+#include "core/config/project_settings.h"
#include "core/core_string_names.h"
#include "scene/resources/theme.h"
#include "scene/theme/theme_db.h"
@@ -37,6 +38,8 @@
#include "thirdparty/misc/clipper.hpp"
#include "thirdparty/misc/polypartition.h"
+#define PADDING_REF_SIZE 1024.0
+
/**
PrimitiveMesh
*/
@@ -94,6 +97,26 @@ void PrimitiveMesh::_update() const {
}
}
+ if (add_uv2) {
+ // _create_mesh_array should populate our UV2, this is a fallback in case it doesn't.
+ // As we don't know anything about the geometry we only pad the right and bottom edge
+ // of our texture.
+ Vector<Vector2> uv = arr[RS::ARRAY_TEX_UV];
+ Vector<Vector2> uv2 = arr[RS::ARRAY_TEX_UV2];
+
+ if (uv.size() > 0 && uv2.size() == 0) {
+ Vector2 uv2_scale = get_uv2_scale();
+ uv2.resize(uv.size());
+
+ Vector2 *uv2w = uv2.ptrw();
+ for (int i = 0; i < uv.size(); i++) {
+ uv2w[i] = uv[i] * uv2_scale;
+ }
+ }
+
+ arr[RS::ARRAY_TEX_UV2] = uv2;
+ }
+
array_len = pc;
index_array_len = indices.size();
// in with the new
@@ -160,7 +183,12 @@ TypedArray<Array> PrimitiveMesh::surface_get_blend_shape_arrays(int p_surface) c
uint32_t PrimitiveMesh::surface_get_format(int p_idx) const {
ERR_FAIL_INDEX_V(p_idx, 1, 0);
- return RS::ARRAY_FORMAT_VERTEX | RS::ARRAY_FORMAT_NORMAL | RS::ARRAY_FORMAT_TANGENT | RS::ARRAY_FORMAT_TEX_UV | RS::ARRAY_FORMAT_INDEX;
+ uint32_t mesh_format = RS::ARRAY_FORMAT_VERTEX | RS::ARRAY_FORMAT_NORMAL | RS::ARRAY_FORMAT_TANGENT | RS::ARRAY_FORMAT_TEX_UV | RS::ARRAY_FORMAT_INDEX;
+ if (add_uv2) {
+ mesh_format |= RS::ARRAY_FORMAT_TEX_UV2;
+ }
+
+ return mesh_format;
}
Mesh::PrimitiveType PrimitiveMesh::surface_get_primitive_type(int p_idx) const {
@@ -219,9 +247,17 @@ void PrimitiveMesh::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_flip_faces", "flip_faces"), &PrimitiveMesh::set_flip_faces);
ClassDB::bind_method(D_METHOD("get_flip_faces"), &PrimitiveMesh::get_flip_faces);
+ ClassDB::bind_method(D_METHOD("set_add_uv2", "add_uv2"), &PrimitiveMesh::set_add_uv2);
+ ClassDB::bind_method(D_METHOD("get_add_uv2"), &PrimitiveMesh::get_add_uv2);
+
+ ClassDB::bind_method(D_METHOD("set_uv2_padding", "uv2_padding"), &PrimitiveMesh::set_uv2_padding);
+ ClassDB::bind_method(D_METHOD("get_uv2_padding"), &PrimitiveMesh::get_uv2_padding);
+
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material", PROPERTY_HINT_RESOURCE_TYPE, "BaseMaterial3D,ShaderMaterial"), "set_material", "get_material");
ADD_PROPERTY(PropertyInfo(Variant::AABB, "custom_aabb", PROPERTY_HINT_NONE, "suffix:m"), "set_custom_aabb", "get_custom_aabb");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "flip_faces"), "set_flip_faces", "get_flip_faces");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "add_uv2"), "set_add_uv2", "get_add_uv2");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "uv2_padding"), "set_uv2_padding", "get_uv2_padding");
GDVIRTUAL_BIND(_create_mesh_array);
}
@@ -233,7 +269,7 @@ void PrimitiveMesh::set_material(const Ref<Material> &p_material) {
RenderingServer::get_singleton()->mesh_surface_set_material(mesh, 0, material.is_null() ? RID() : material->get_rid());
notify_property_list_changed();
emit_changed();
- };
+ }
}
Ref<Material> PrimitiveMesh::get_material() const {
@@ -263,6 +299,42 @@ bool PrimitiveMesh::get_flip_faces() const {
return flip_faces;
}
+void PrimitiveMesh::set_add_uv2(bool p_enable) {
+ add_uv2 = p_enable;
+ _update_lightmap_size();
+ _request_update();
+}
+
+void PrimitiveMesh::set_uv2_padding(float p_padding) {
+ uv2_padding = p_padding;
+ _update_lightmap_size();
+ _request_update();
+}
+
+Vector2 PrimitiveMesh::get_uv2_scale(Vector2 p_margin_scale) const {
+ Vector2 uv2_scale;
+ Vector2 lightmap_size = get_lightmap_size_hint();
+
+ // Calculate it as a margin, if no lightmap size hint is given we assume "PADDING_REF_SIZE" as our texture size.
+ uv2_scale.x = p_margin_scale.x * uv2_padding / (lightmap_size.x == 0.0 ? PADDING_REF_SIZE : lightmap_size.x);
+ uv2_scale.y = p_margin_scale.y * uv2_padding / (lightmap_size.y == 0.0 ? PADDING_REF_SIZE : lightmap_size.y);
+
+ // Inverse it to turn our margin into a scale
+ uv2_scale = Vector2(1.0, 1.0) - uv2_scale;
+
+ return uv2_scale;
+}
+
+float PrimitiveMesh::get_lightmap_texel_size() const {
+ float texel_size = GLOBAL_GET("rendering/lightmapping/primitive_meshes/texel_size");
+
+ if (texel_size <= 0.0) {
+ texel_size = 0.2;
+ }
+
+ return texel_size;
+}
+
PrimitiveMesh::PrimitiveMesh() {
mesh = RenderingServer::get_singleton()->mesh_create();
}
@@ -275,22 +347,52 @@ PrimitiveMesh::~PrimitiveMesh() {
CapsuleMesh
*/
+void CapsuleMesh::_update_lightmap_size() {
+ if (get_add_uv2()) {
+ // size must have changed, update lightmap size hint
+ Size2i _lightmap_size_hint;
+ float texel_size = get_lightmap_texel_size();
+ float padding = get_uv2_padding();
+
+ float radial_length = radius * Math_PI * 0.5; // circumference of 90 degree bend
+ float vertical_length = radial_length * 2 + (height - 2.0 * radius); // total vertical length
+
+ _lightmap_size_hint.x = MAX(1.0, 4.0 * radial_length / texel_size) + padding;
+ _lightmap_size_hint.y = MAX(1.0, vertical_length / texel_size) + padding;
+
+ set_lightmap_size_hint(_lightmap_size_hint);
+ }
+}
+
void CapsuleMesh::_create_mesh_array(Array &p_arr) const {
- create_mesh_array(p_arr, radius, height, radial_segments, rings);
+ bool _add_uv2 = get_add_uv2();
+ float texel_size = get_lightmap_texel_size();
+ float _uv2_padding = get_uv2_padding() * texel_size;
+
+ create_mesh_array(p_arr, radius, height, radial_segments, rings, _add_uv2, _uv2_padding);
}
-void CapsuleMesh::create_mesh_array(Array &p_arr, const float radius, const float height, const int radial_segments, const int rings) {
+void CapsuleMesh::create_mesh_array(Array &p_arr, const float radius, const float height, const int radial_segments, const int rings, bool p_add_uv2, const float p_uv2_padding) {
int i, j, prevrow, thisrow, point;
float x, y, z, u, v, w;
float onethird = 1.0 / 3.0;
float twothirds = 2.0 / 3.0;
+ // Only used if we calculate UV2
+ float radial_width = 2.0 * radius * Math_PI;
+ float radial_h = radial_width / (radial_width + p_uv2_padding);
+ float radial_length = radius * Math_PI * 0.5; // circumference of 90 degree bend
+ float vertical_length = radial_length * 2 + (height - 2.0 * radius) + p_uv2_padding; // total vertical length
+ float radial_v = radial_length / vertical_length; // v size of top and bottom section
+ float height_v = (height - 2.0 * radius) / vertical_length; // v size of height section
+
// note, this has been aligned with our collision shape but I've left the descriptions as top/middle/bottom
Vector<Vector3> points;
Vector<Vector3> normals;
Vector<float> tangents;
Vector<Vector2> uvs;
+ Vector<Vector2> uv2s;
Vector<int> indices;
point = 0;
@@ -322,6 +424,9 @@ void CapsuleMesh::create_mesh_array(Array &p_arr, const float radius, const floa
normals.push_back(p.normalized());
ADD_TANGENT(-z, 0.0, -x, 1.0)
uvs.push_back(Vector2(u, v * onethird));
+ if (p_add_uv2) {
+ uv2s.push_back(Vector2(u * radial_h, v * radial_v));
+ }
point++;
if (i > 0 && j > 0) {
@@ -332,12 +437,12 @@ void CapsuleMesh::create_mesh_array(Array &p_arr, const float radius, const floa
indices.push_back(prevrow + i);
indices.push_back(thisrow + i);
indices.push_back(thisrow + i - 1);
- };
- };
+ }
+ }
prevrow = thisrow;
thisrow = point;
- };
+ }
/* cylinder */
thisrow = point;
@@ -361,6 +466,9 @@ void CapsuleMesh::create_mesh_array(Array &p_arr, const float radius, const floa
normals.push_back(Vector3(x, 0.0, -z));
ADD_TANGENT(-z, 0.0, -x, 1.0)
uvs.push_back(Vector2(u, onethird + (v * onethird)));
+ if (p_add_uv2) {
+ uv2s.push_back(Vector2(u * radial_h, radial_v + (v * height_v)));
+ }
point++;
if (i > 0 && j > 0) {
@@ -371,12 +479,12 @@ void CapsuleMesh::create_mesh_array(Array &p_arr, const float radius, const floa
indices.push_back(prevrow + i);
indices.push_back(thisrow + i);
indices.push_back(thisrow + i - 1);
- };
- };
+ }
+ }
prevrow = thisrow;
thisrow = point;
- };
+ }
/* bottom hemisphere */
thisrow = point;
@@ -390,17 +498,20 @@ void CapsuleMesh::create_mesh_array(Array &p_arr, const float radius, const floa
y = radius * cos(0.5 * Math_PI * v);
for (i = 0; i <= radial_segments; i++) {
- float u2 = i;
- u2 /= radial_segments;
+ u = i;
+ u /= radial_segments;
- x = -sin(u2 * Math_TAU);
- z = cos(u2 * Math_TAU);
+ x = -sin(u * Math_TAU);
+ z = cos(u * Math_TAU);
Vector3 p = Vector3(x * radius * w, y, -z * radius * w);
points.push_back(p + Vector3(0.0, -0.5 * height + radius, 0.0));
normals.push_back(p.normalized());
ADD_TANGENT(-z, 0.0, -x, 1.0)
- uvs.push_back(Vector2(u2, twothirds + ((v - 1.0) * onethird)));
+ uvs.push_back(Vector2(u, twothirds + ((v - 1.0) * onethird)));
+ if (p_add_uv2) {
+ uv2s.push_back(Vector2(u * radial_h, radial_v + height_v + ((v - 1.0) * radial_v)));
+ }
point++;
if (i > 0 && j > 0) {
@@ -411,17 +522,20 @@ void CapsuleMesh::create_mesh_array(Array &p_arr, const float radius, const floa
indices.push_back(prevrow + i);
indices.push_back(thisrow + i);
indices.push_back(thisrow + i - 1);
- };
- };
+ }
+ }
prevrow = thisrow;
thisrow = point;
- };
+ }
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;
+ if (p_add_uv2) {
+ p_arr[RS::ARRAY_TEX_UV2] = uv2s;
+ }
p_arr[RS::ARRAY_INDEX] = indices;
}
@@ -450,6 +564,7 @@ void CapsuleMesh::set_radius(const float p_radius) {
if (radius > height * 0.5) {
height = radius * 2.0;
}
+ _update_lightmap_size();
_request_update();
}
@@ -462,6 +577,7 @@ void CapsuleMesh::set_height(const float p_height) {
if (radius > height * 0.5) {
radius = height * 0.5;
}
+ _update_lightmap_size();
_request_update();
}
@@ -493,16 +609,53 @@ CapsuleMesh::CapsuleMesh() {}
BoxMesh
*/
+void BoxMesh::_update_lightmap_size() {
+ if (get_add_uv2()) {
+ // size must have changed, update lightmap size hint
+ Size2i _lightmap_size_hint;
+ float texel_size = get_lightmap_texel_size();
+ float padding = get_uv2_padding();
+
+ float width = (size.x + size.z) / texel_size;
+ float length = (size.y + size.y + MAX(size.x, size.z)) / texel_size;
+
+ _lightmap_size_hint.x = MAX(1.0, width) + 2.0 * padding;
+ _lightmap_size_hint.y = MAX(1.0, length) + 3.0 * padding;
+
+ set_lightmap_size_hint(_lightmap_size_hint);
+ }
+}
+
void BoxMesh::_create_mesh_array(Array &p_arr) const {
- BoxMesh::create_mesh_array(p_arr, size, subdivide_w, subdivide_h, subdivide_d);
+ // Note about padding, with our box each face of the box faces a different direction so we want a seam
+ // around every face. We thus add our padding to the right and bottom of each face.
+ // With 3 faces along the width and 2 along the height of the texture we need to adjust our scale
+ // accordingly.
+ bool _add_uv2 = get_add_uv2();
+ float texel_size = get_lightmap_texel_size();
+ float _uv2_padding = get_uv2_padding() * texel_size;
+
+ BoxMesh::create_mesh_array(p_arr, size, subdivide_w, subdivide_h, subdivide_d, _add_uv2, _uv2_padding);
}
-void BoxMesh::create_mesh_array(Array &p_arr, Vector3 size, int subdivide_w, int subdivide_h, int subdivide_d) {
+void BoxMesh::create_mesh_array(Array &p_arr, Vector3 size, int subdivide_w, int subdivide_h, int subdivide_d, bool p_add_uv2, const float p_uv2_padding) {
int i, j, prevrow, thisrow, point;
float x, y, z;
float onethird = 1.0 / 3.0;
float twothirds = 2.0 / 3.0;
+ // Only used if we calculate UV2
+ // TODO this could be improved by changing the order depending on which side is the longest (basically the below works best if size.y is the longest)
+ float total_h = (size.x + size.z + (2.0 * p_uv2_padding));
+ float padding_h = p_uv2_padding / total_h;
+ float width_h = size.x / total_h;
+ float depth_h = size.z / total_h;
+ float total_v = (size.y + size.y + MAX(size.x, size.z) + (3.0 * p_uv2_padding));
+ float padding_v = p_uv2_padding / total_v;
+ float width_v = size.x / total_v;
+ float height_v = size.y / total_v;
+ float depth_v = size.z / total_v;
+
Vector3 start_pos = size * -0.5;
// set our bounding box
@@ -511,6 +664,7 @@ void BoxMesh::create_mesh_array(Array &p_arr, Vector3 size, int subdivide_w, int
Vector<Vector3> normals;
Vector<float> tangents;
Vector<Vector2> uvs;
+ Vector<Vector2> uv2s;
Vector<int> indices;
point = 0;
@@ -525,18 +679,24 @@ void BoxMesh::create_mesh_array(Array &p_arr, Vector3 size, int subdivide_w, int
thisrow = point;
prevrow = 0;
for (j = 0; j <= subdivide_h + 1; j++) {
+ float v = j;
+ float v2 = v / (subdivide_w + 1.0);
+ v /= (2.0 * (subdivide_h + 1.0));
+
x = start_pos.x;
for (i = 0; i <= subdivide_w + 1; i++) {
float u = i;
- float v = j;
+ float u2 = u / (subdivide_w + 1.0);
u /= (3.0 * (subdivide_w + 1.0));
- v /= (2.0 * (subdivide_h + 1.0));
// front
points.push_back(Vector3(x, -y, -start_pos.z)); // double negative on the Z!
normals.push_back(Vector3(0.0, 0.0, 1.0));
ADD_TANGENT(1.0, 0.0, 0.0, 1.0);
uvs.push_back(Vector2(u, v));
+ if (p_add_uv2) {
+ uv2s.push_back(Vector2(u2 * width_h, v2 * height_v));
+ }
point++;
// back
@@ -544,6 +704,9 @@ void BoxMesh::create_mesh_array(Array &p_arr, Vector3 size, int subdivide_w, int
normals.push_back(Vector3(0.0, 0.0, -1.0));
ADD_TANGENT(-1.0, 0.0, 0.0, 1.0);
uvs.push_back(Vector2(twothirds + u, v));
+ if (p_add_uv2) {
+ uv2s.push_back(Vector2(u2 * width_h, height_v + padding_v + (v2 * height_v)));
+ }
point++;
if (i > 0 && j > 0) {
@@ -564,33 +727,39 @@ void BoxMesh::create_mesh_array(Array &p_arr, Vector3 size, int subdivide_w, int
indices.push_back(prevrow + i2 + 1);
indices.push_back(thisrow + i2 + 1);
indices.push_back(thisrow + i2 - 1);
- };
+ }
x += size.x / (subdivide_w + 1.0);
- };
+ }
y += size.y / (subdivide_h + 1.0);
prevrow = thisrow;
thisrow = point;
- };
+ }
// left + right
y = start_pos.y;
thisrow = point;
prevrow = 0;
for (j = 0; j <= (subdivide_h + 1); j++) {
+ float v = j;
+ float v2 = v / (subdivide_h + 1.0);
+ v /= (2.0 * (subdivide_h + 1.0));
+
z = start_pos.z;
for (i = 0; i <= (subdivide_d + 1); i++) {
float u = i;
- float v = j;
+ float u2 = u / (subdivide_d + 1.0);
u /= (3.0 * (subdivide_d + 1.0));
- v /= (2.0 * (subdivide_h + 1.0));
// right
points.push_back(Vector3(-start_pos.x, -y, -z));
normals.push_back(Vector3(1.0, 0.0, 0.0));
ADD_TANGENT(0.0, 0.0, -1.0, 1.0);
uvs.push_back(Vector2(onethird + u, v));
+ if (p_add_uv2) {
+ uv2s.push_back(Vector2(width_h + padding_h + (u2 * depth_h), v2 * height_v));
+ }
point++;
// left
@@ -598,6 +767,9 @@ void BoxMesh::create_mesh_array(Array &p_arr, Vector3 size, int subdivide_w, int
normals.push_back(Vector3(-1.0, 0.0, 0.0));
ADD_TANGENT(0.0, 0.0, 1.0, 1.0);
uvs.push_back(Vector2(u, 0.5 + v));
+ if (p_add_uv2) {
+ uv2s.push_back(Vector2(width_h + padding_h + (u2 * depth_h), height_v + padding_v + (v2 * height_v)));
+ }
point++;
if (i > 0 && j > 0) {
@@ -618,33 +790,39 @@ void BoxMesh::create_mesh_array(Array &p_arr, Vector3 size, int subdivide_w, int
indices.push_back(prevrow + i2 + 1);
indices.push_back(thisrow + i2 + 1);
indices.push_back(thisrow + i2 - 1);
- };
+ }
z += size.z / (subdivide_d + 1.0);
- };
+ }
y += size.y / (subdivide_h + 1.0);
prevrow = thisrow;
thisrow = point;
- };
+ }
// top + bottom
z = start_pos.z;
thisrow = point;
prevrow = 0;
for (j = 0; j <= (subdivide_d + 1); j++) {
+ float v = j;
+ float v2 = v / (subdivide_d + 1.0);
+ v /= (2.0 * (subdivide_d + 1.0));
+
x = start_pos.x;
for (i = 0; i <= (subdivide_w + 1); i++) {
float u = i;
- float v = j;
+ float u2 = u / (subdivide_w + 1.0);
u /= (3.0 * (subdivide_w + 1.0));
- v /= (2.0 * (subdivide_d + 1.0));
// top
points.push_back(Vector3(-x, -start_pos.y, -z));
normals.push_back(Vector3(0.0, 1.0, 0.0));
ADD_TANGENT(-1.0, 0.0, 0.0, 1.0);
uvs.push_back(Vector2(onethird + u, 0.5 + v));
+ if (p_add_uv2) {
+ uv2s.push_back(Vector2(u2 * width_h, ((height_v + padding_v) * 2.0) + (v2 * depth_v)));
+ }
point++;
// bottom
@@ -652,6 +830,9 @@ void BoxMesh::create_mesh_array(Array &p_arr, Vector3 size, int subdivide_w, int
normals.push_back(Vector3(0.0, -1.0, 0.0));
ADD_TANGENT(1.0, 0.0, 0.0, 1.0);
uvs.push_back(Vector2(twothirds + u, 0.5 + v));
+ if (p_add_uv2) {
+ uv2s.push_back(Vector2(width_h + padding_h + (u2 * depth_h), ((height_v + padding_v) * 2.0) + (v2 * width_v)));
+ }
point++;
if (i > 0 && j > 0) {
@@ -672,20 +853,23 @@ void BoxMesh::create_mesh_array(Array &p_arr, Vector3 size, int subdivide_w, int
indices.push_back(prevrow + i2 + 1);
indices.push_back(thisrow + i2 + 1);
indices.push_back(thisrow + i2 - 1);
- };
+ }
x += size.x / (subdivide_w + 1.0);
- };
+ }
z += size.z / (subdivide_d + 1.0);
prevrow = thisrow;
thisrow = point;
- };
+ }
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;
+ if (p_add_uv2) {
+ p_arr[RS::ARRAY_TEX_UV2] = uv2s;
+ }
p_arr[RS::ARRAY_INDEX] = indices;
}
@@ -708,6 +892,7 @@ void BoxMesh::_bind_methods() {
void BoxMesh::set_size(const Vector3 &p_size) {
size = p_size;
+ _update_lightmap_size();
_request_update();
}
@@ -748,18 +933,58 @@ BoxMesh::BoxMesh() {}
CylinderMesh
*/
+void CylinderMesh::_update_lightmap_size() {
+ if (get_add_uv2()) {
+ // size must have changed, update lightmap size hint
+ Size2i _lightmap_size_hint;
+ float texel_size = get_lightmap_texel_size();
+ float padding = get_uv2_padding();
+
+ float top_circumference = top_radius * Math_PI * 2.0;
+ float bottom_circumference = bottom_radius * Math_PI * 2.0;
+
+ float _width = MAX(top_circumference, bottom_circumference) / texel_size + padding;
+ _width = MAX(_width, (((top_radius + bottom_radius) / texel_size) + padding) * 2.0); // this is extremely unlikely to be larger, will only happen if padding is larger then our diameter.
+ _lightmap_size_hint.x = MAX(1.0, _width);
+
+ float _height = ((height + (MAX(top_radius, bottom_radius) * 2.0)) / texel_size) + (2.0 * padding);
+
+ _lightmap_size_hint.y = MAX(1.0, _height);
+
+ set_lightmap_size_hint(_lightmap_size_hint);
+ }
+}
+
void CylinderMesh::_create_mesh_array(Array &p_arr) const {
- create_mesh_array(p_arr, top_radius, bottom_radius, height, radial_segments, rings, cap_top, cap_bottom);
+ bool _add_uv2 = get_add_uv2();
+ float texel_size = get_lightmap_texel_size();
+ float _uv2_padding = get_uv2_padding() * texel_size;
+
+ create_mesh_array(p_arr, top_radius, bottom_radius, height, radial_segments, rings, cap_top, cap_bottom, _add_uv2, _uv2_padding);
}
-void CylinderMesh::create_mesh_array(Array &p_arr, float top_radius, float bottom_radius, float height, int radial_segments, int rings, bool cap_top, bool cap_bottom) {
+void CylinderMesh::create_mesh_array(Array &p_arr, float top_radius, float bottom_radius, float height, int radial_segments, int rings, bool cap_top, bool cap_bottom, bool p_add_uv2, const float p_uv2_padding) {
int i, j, prevrow, thisrow, point;
- float x, y, z, u, v, radius;
+ float x, y, z, u, v, radius, radius_h;
+
+ // Only used if we calculate UV2
+ float top_circumference = top_radius * Math_PI * 2.0;
+ float bottom_circumference = bottom_radius * Math_PI * 2.0;
+ float vertical_length = height + MAX(2.0 * top_radius, 2.0 * bottom_radius) + (2.0 * p_uv2_padding);
+ float height_v = height / vertical_length;
+ float padding_v = p_uv2_padding / vertical_length;
+
+ float horizonal_length = MAX(MAX(2.0 * (top_radius + bottom_radius + p_uv2_padding), top_circumference + p_uv2_padding), bottom_circumference + p_uv2_padding);
+ float center_h = 0.5 * (horizonal_length - p_uv2_padding) / horizonal_length;
+ float top_h = top_circumference / horizonal_length;
+ float bottom_h = bottom_circumference / horizonal_length;
+ float padding_h = p_uv2_padding / horizonal_length;
Vector<Vector3> points;
Vector<Vector3> normals;
Vector<float> tangents;
Vector<Vector2> uvs;
+ Vector<Vector2> uv2s;
Vector<int> indices;
point = 0;
@@ -777,6 +1002,7 @@ void CylinderMesh::create_mesh_array(Array &p_arr, float top_radius, float botto
v /= (rings + 1);
radius = top_radius + ((bottom_radius - top_radius) * v);
+ radius_h = top_h + ((bottom_h - top_h) * v);
y = height * v;
y = (height * 0.5) - y;
@@ -793,6 +1019,9 @@ void CylinderMesh::create_mesh_array(Array &p_arr, float top_radius, float botto
normals.push_back(Vector3(x, side_normal_y, z).normalized());
ADD_TANGENT(z, 0.0, -x, 1.0)
uvs.push_back(Vector2(u, v * 0.5));
+ if (p_add_uv2) {
+ uv2s.push_back(Vector2(center_h + (u - 0.5) * radius_h, v * height_v));
+ }
point++;
if (i > 0 && j > 0) {
@@ -803,14 +1032,20 @@ void CylinderMesh::create_mesh_array(Array &p_arr, float top_radius, float botto
indices.push_back(prevrow + i);
indices.push_back(thisrow + i);
indices.push_back(thisrow + i - 1);
- };
- };
+ }
+ }
prevrow = thisrow;
thisrow = point;
- };
+ }
+
+ // Adjust for bottom section, only used if we calculate UV2s.
+ top_h = top_radius / horizonal_length;
+ float top_v = top_radius / vertical_length;
+ bottom_h = bottom_radius / horizonal_length;
+ float bottom_v = bottom_radius / vertical_length;
- // add top
+ // Add top.
if (cap_top && top_radius > 0.0) {
y = height * 0.5;
@@ -819,6 +1054,9 @@ void CylinderMesh::create_mesh_array(Array &p_arr, float top_radius, float botto
normals.push_back(Vector3(0.0, 1.0, 0.0));
ADD_TANGENT(1.0, 0.0, 0.0, 1.0)
uvs.push_back(Vector2(0.25, 0.75));
+ if (p_add_uv2) {
+ uv2s.push_back(Vector2(top_h, height_v + padding_v + MAX(top_v, bottom_v)));
+ }
point++;
for (i = 0; i <= radial_segments; i++) {
@@ -836,17 +1074,20 @@ void CylinderMesh::create_mesh_array(Array &p_arr, float top_radius, float botto
normals.push_back(Vector3(0.0, 1.0, 0.0));
ADD_TANGENT(1.0, 0.0, 0.0, 1.0)
uvs.push_back(Vector2(u, v));
+ if (p_add_uv2) {
+ uv2s.push_back(Vector2(top_h + (x * top_h), height_v + padding_v + MAX(top_v, bottom_v) + (z * top_v)));
+ }
point++;
if (i > 0) {
indices.push_back(thisrow);
indices.push_back(point - 1);
indices.push_back(point - 2);
- };
- };
- };
+ }
+ }
+ }
- // add bottom
+ // Add bottom.
if (cap_bottom && bottom_radius > 0.0) {
y = height * -0.5;
@@ -855,6 +1096,9 @@ void CylinderMesh::create_mesh_array(Array &p_arr, float top_radius, float botto
normals.push_back(Vector3(0.0, -1.0, 0.0));
ADD_TANGENT(1.0, 0.0, 0.0, 1.0)
uvs.push_back(Vector2(0.75, 0.75));
+ if (p_add_uv2) {
+ uv2s.push_back(Vector2(top_h + top_h + padding_h + bottom_h, height_v + padding_v + MAX(top_v, bottom_v)));
+ }
point++;
for (i = 0; i <= radial_segments; i++) {
@@ -872,20 +1116,26 @@ void CylinderMesh::create_mesh_array(Array &p_arr, float top_radius, float botto
normals.push_back(Vector3(0.0, -1.0, 0.0));
ADD_TANGENT(1.0, 0.0, 0.0, 1.0)
uvs.push_back(Vector2(u, v));
+ if (p_add_uv2) {
+ uv2s.push_back(Vector2(top_h + top_h + padding_h + bottom_h + (x * bottom_h), height_v + padding_v + MAX(top_v, bottom_v) - (z * bottom_v)));
+ }
point++;
if (i > 0) {
indices.push_back(thisrow);
indices.push_back(point - 2);
indices.push_back(point - 1);
- };
- };
- };
+ }
+ }
+ }
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;
+ if (p_add_uv2) {
+ p_arr[RS::ARRAY_TEX_UV2] = uv2s;
+ }
p_arr[RS::ARRAY_INDEX] = indices;
}
@@ -919,6 +1169,7 @@ void CylinderMesh::_bind_methods() {
void CylinderMesh::set_top_radius(const float p_radius) {
top_radius = p_radius;
+ _update_lightmap_size();
_request_update();
}
@@ -928,6 +1179,7 @@ float CylinderMesh::get_top_radius() const {
void CylinderMesh::set_bottom_radius(const float p_radius) {
bottom_radius = p_radius;
+ _update_lightmap_size();
_request_update();
}
@@ -937,6 +1189,7 @@ float CylinderMesh::get_bottom_radius() const {
void CylinderMesh::set_height(const float p_height) {
height = p_height;
+ _update_lightmap_size();
_request_update();
}
@@ -986,10 +1239,26 @@ CylinderMesh::CylinderMesh() {}
PlaneMesh
*/
+void PlaneMesh::_update_lightmap_size() {
+ if (get_add_uv2()) {
+ // size must have changed, update lightmap size hint
+ Size2i _lightmap_size_hint;
+ float texel_size = get_lightmap_texel_size();
+ float padding = get_uv2_padding();
+
+ _lightmap_size_hint.x = MAX(1.0, (size.x / texel_size) + padding);
+ _lightmap_size_hint.y = MAX(1.0, (size.y / texel_size) + padding);
+
+ set_lightmap_size_hint(_lightmap_size_hint);
+ }
+}
+
void PlaneMesh::_create_mesh_array(Array &p_arr) const {
int i, j, prevrow, thisrow, point;
float x, z;
+ // Plane mesh can use default UV2 calculation as implemented in Primitive Mesh
+
Size2 start_pos = size * -0.5;
Vector3 normal = Vector3(0.0, 1.0, 0.0);
@@ -1043,15 +1312,15 @@ void PlaneMesh::_create_mesh_array(Array &p_arr) const {
indices.push_back(prevrow + i);
indices.push_back(thisrow + i);
indices.push_back(thisrow + i - 1);
- };
+ }
x += size.x / (subdivide_w + 1.0);
- };
+ }
z += size.y / (subdivide_d + 1.0);
prevrow = thisrow;
thisrow = point;
- };
+ }
p_arr[RS::ARRAY_VERTEX] = points;
p_arr[RS::ARRAY_NORMAL] = normals;
@@ -1088,6 +1357,7 @@ void PlaneMesh::_bind_methods() {
void PlaneMesh::set_size(const Size2 &p_size) {
size = p_size;
+ _update_lightmap_size();
_request_update();
}
@@ -1137,12 +1407,49 @@ PlaneMesh::PlaneMesh() {}
PrismMesh
*/
+void PrismMesh::_update_lightmap_size() {
+ if (get_add_uv2()) {
+ // size must have changed, update lightmap size hint
+ Size2i _lightmap_size_hint;
+ float texel_size = get_lightmap_texel_size();
+ float padding = get_uv2_padding();
+
+ // left_to_right does not effect the surface area of the prism so we ignore that.
+ // TODO we could combine the two triangles and save some space but we need to re-align the uv1 and adjust the tangent.
+
+ float width = (size.x + size.z) / texel_size;
+ float length = (size.y + size.y + size.z) / texel_size;
+
+ _lightmap_size_hint.x = MAX(1.0, width) + 2.0 * padding;
+ _lightmap_size_hint.y = MAX(1.0, length) + 3.0 * padding;
+
+ set_lightmap_size_hint(_lightmap_size_hint);
+ }
+}
+
void PrismMesh::_create_mesh_array(Array &p_arr) const {
int i, j, prevrow, thisrow, point;
float x, y, z;
float onethird = 1.0 / 3.0;
float twothirds = 2.0 / 3.0;
+ // Only used if we calculate UV2
+ bool _add_uv2 = get_add_uv2();
+ float texel_size = get_lightmap_texel_size();
+ float _uv2_padding = get_uv2_padding() * texel_size;
+
+ float horizontal_total = size.x + size.z + 2.0 * _uv2_padding;
+ float width_h = size.x / horizontal_total;
+ float depth_h = size.z / horizontal_total;
+ float padding_h = _uv2_padding / horizontal_total;
+
+ float vertical_total = (size.y + size.y + size.z) + (3.0 * _uv2_padding);
+ float height_v = size.y / vertical_total;
+ float depth_v = size.z / vertical_total;
+ float padding_v = _uv2_padding / vertical_total;
+
+ // and start building
+
Vector3 start_pos = size * -0.5;
// set our bounding box
@@ -1151,6 +1458,7 @@ void PrismMesh::_create_mesh_array(Array &p_arr) const {
Vector<Vector3> normals;
Vector<float> tangents;
Vector<Vector2> uvs;
+ Vector<Vector2> uv2s;
Vector<int> indices;
point = 0;
@@ -1171,12 +1479,15 @@ void PrismMesh::_create_mesh_array(Array &p_arr) const {
float offset_front = (1.0 - scale) * onethird * left_to_right;
float offset_back = (1.0 - scale) * onethird * (1.0 - left_to_right);
+ float v = j;
+ float v2 = j / (subdivide_h + 1.0);
+ v /= (2.0 * (subdivide_h + 1.0));
+
x = 0.0;
for (i = 0; i <= (subdivide_w + 1); i++) {
float u = i;
- float v = j;
+ float u2 = i / (subdivide_w + 1.0);
u /= (3.0 * (subdivide_w + 1.0));
- v /= (2.0 * (subdivide_h + 1.0));
u *= scale;
@@ -1185,6 +1496,9 @@ void PrismMesh::_create_mesh_array(Array &p_arr) const {
normals.push_back(Vector3(0.0, 0.0, 1.0));
ADD_TANGENT(1.0, 0.0, 0.0, 1.0);
uvs.push_back(Vector2(offset_front + u, v));
+ if (_add_uv2) {
+ uv2s.push_back(Vector2(u2 * scale * width_h, v2 * height_v));
+ }
point++;
/* back */
@@ -1192,6 +1506,9 @@ void PrismMesh::_create_mesh_array(Array &p_arr) const {
normals.push_back(Vector3(0.0, 0.0, -1.0));
ADD_TANGENT(-1.0, 0.0, 0.0, 1.0);
uvs.push_back(Vector2(twothirds + offset_back + u, v));
+ if (_add_uv2) {
+ uv2s.push_back(Vector2(u2 * scale * width_h, height_v + padding_v + v2 * height_v));
+ }
point++;
if (i > 0 && j == 1) {
@@ -1224,15 +1541,15 @@ void PrismMesh::_create_mesh_array(Array &p_arr) const {
indices.push_back(prevrow + i2 + 1);
indices.push_back(thisrow + i2 + 1);
indices.push_back(thisrow + i2 - 1);
- };
+ }
x += scale * size.x / (subdivide_w + 1.0);
- };
+ }
y += size.y / (subdivide_h + 1.0);
prevrow = thisrow;
thisrow = point;
- };
+ }
/* left + right */
Vector3 normal_left, normal_right;
@@ -1246,6 +1563,10 @@ void PrismMesh::_create_mesh_array(Array &p_arr) const {
thisrow = point;
prevrow = 0;
for (j = 0; j <= (subdivide_h + 1); j++) {
+ float v = j;
+ float v2 = j / (subdivide_h + 1.0);
+ v /= (2.0 * (subdivide_h + 1.0));
+
float left, right;
float scale = (y - start_pos.y) / size.y;
@@ -1255,15 +1576,17 @@ void PrismMesh::_create_mesh_array(Array &p_arr) const {
z = start_pos.z;
for (i = 0; i <= (subdivide_d + 1); i++) {
float u = i;
- float v = j;
+ float u2 = u / (subdivide_d + 1.0);
u /= (3.0 * (subdivide_d + 1.0));
- v /= (2.0 * (subdivide_h + 1.0));
/* right */
points.push_back(Vector3(right, -y, -z));
normals.push_back(normal_right);
ADD_TANGENT(0.0, 0.0, -1.0, 1.0);
uvs.push_back(Vector2(onethird + u, v));
+ if (_add_uv2) {
+ uv2s.push_back(Vector2(width_h + padding_h + u2 * depth_h, v2 * height_v));
+ }
point++;
/* left */
@@ -1271,6 +1594,9 @@ void PrismMesh::_create_mesh_array(Array &p_arr) const {
normals.push_back(normal_left);
ADD_TANGENT(0.0, 0.0, 1.0, 1.0);
uvs.push_back(Vector2(u, 0.5 + v));
+ if (_add_uv2) {
+ uv2s.push_back(Vector2(width_h + padding_h + u2 * depth_h, height_v + padding_v + v2 * height_v));
+ }
point++;
if (i > 0 && j > 0) {
@@ -1291,33 +1617,39 @@ void PrismMesh::_create_mesh_array(Array &p_arr) const {
indices.push_back(prevrow + i2 + 1);
indices.push_back(thisrow + i2 + 1);
indices.push_back(thisrow + i2 - 1);
- };
+ }
z += size.z / (subdivide_d + 1.0);
- };
+ }
y += size.y / (subdivide_h + 1.0);
prevrow = thisrow;
thisrow = point;
- };
+ }
/* bottom */
z = start_pos.z;
thisrow = point;
prevrow = 0;
for (j = 0; j <= (subdivide_d + 1); j++) {
+ float v = j;
+ float v2 = v / (subdivide_d + 1.0);
+ v /= (2.0 * (subdivide_d + 1.0));
+
x = start_pos.x;
for (i = 0; i <= (subdivide_w + 1); i++) {
float u = i;
- float v = j;
+ float u2 = u / (subdivide_w + 1.0);
u /= (3.0 * (subdivide_w + 1.0));
- v /= (2.0 * (subdivide_d + 1.0));
/* bottom */
points.push_back(Vector3(x, start_pos.y, -z));
normals.push_back(Vector3(0.0, -1.0, 0.0));
ADD_TANGENT(1.0, 0.0, 0.0, 1.0);
uvs.push_back(Vector2(twothirds + u, 0.5 + v));
+ if (_add_uv2) {
+ uv2s.push_back(Vector2(u2 * width_h, 2.0 * (height_v + padding_v) + v2 * depth_v));
+ }
point++;
if (i > 0 && j > 0) {
@@ -1328,20 +1660,23 @@ void PrismMesh::_create_mesh_array(Array &p_arr) const {
indices.push_back(prevrow + i);
indices.push_back(thisrow + i);
indices.push_back(thisrow + i - 1);
- };
+ }
x += size.x / (subdivide_w + 1.0);
- };
+ }
z += size.z / (subdivide_d + 1.0);
prevrow = thisrow;
thisrow = point;
- };
+ }
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;
+ if (_add_uv2) {
+ p_arr[RS::ARRAY_TEX_UV2] = uv2s;
+ }
p_arr[RS::ARRAY_INDEX] = indices;
}
@@ -1377,6 +1712,7 @@ float PrismMesh::get_left_to_right() const {
void PrismMesh::set_size(const Vector3 &p_size) {
size = p_size;
+ _update_lightmap_size();
_request_update();
}
@@ -1417,22 +1753,50 @@ PrismMesh::PrismMesh() {}
SphereMesh
*/
+void SphereMesh::_update_lightmap_size() {
+ if (get_add_uv2()) {
+ // size must have changed, update lightmap size hint
+ Size2i _lightmap_size_hint;
+ float texel_size = get_lightmap_texel_size();
+ float padding = get_uv2_padding();
+
+ float _width = radius * Math_TAU;
+ _lightmap_size_hint.x = MAX(1.0, (_width / texel_size) + padding);
+ float _height = (is_hemisphere ? 1.0 : 0.5) * height * Math_PI; // note, with hemisphere height is our radius, while with a full sphere it is the diameter..
+ _lightmap_size_hint.y = MAX(1.0, (_height / texel_size) + padding);
+
+ set_lightmap_size_hint(_lightmap_size_hint);
+ }
+}
+
void SphereMesh::_create_mesh_array(Array &p_arr) const {
- create_mesh_array(p_arr, radius, height, radial_segments, rings, is_hemisphere);
+ bool _add_uv2 = get_add_uv2();
+ float texel_size = get_lightmap_texel_size();
+ float _uv2_padding = get_uv2_padding() * texel_size;
+
+ create_mesh_array(p_arr, radius, height, radial_segments, rings, is_hemisphere, _add_uv2, _uv2_padding);
}
-void SphereMesh::create_mesh_array(Array &p_arr, float radius, float height, int radial_segments, int rings, bool is_hemisphere) {
+void SphereMesh::create_mesh_array(Array &p_arr, float radius, float height, int radial_segments, int rings, bool is_hemisphere, bool p_add_uv2, const float p_uv2_padding) {
int i, j, prevrow, thisrow, point;
float x, y, z;
float scale = height * (is_hemisphere ? 1.0 : 0.5);
+ // Only used if we calculate UV2
+ float circumference = radius * Math_TAU;
+ float horizontal_length = circumference + p_uv2_padding;
+ float center_h = 0.5 * circumference / horizontal_length;
+
+ float height_v = scale * Math_PI / ((scale * Math_PI) + p_uv2_padding);
+
// set our bounding box
Vector<Vector3> points;
Vector<Vector3> normals;
Vector<float> tangents;
Vector<Vector2> uvs;
+ Vector<Vector2> uv2s;
Vector<int> indices;
point = 0;
@@ -1467,9 +1831,13 @@ void SphereMesh::create_mesh_array(Array &p_arr, float radius, float height, int
points.push_back(p);
Vector3 normal = Vector3(x * w * scale, radius * (y / scale), z * w * scale);
normals.push_back(normal.normalized());
- };
+ }
ADD_TANGENT(z, 0.0, -x, 1.0)
uvs.push_back(Vector2(u, v));
+ if (p_add_uv2) {
+ float w_h = w * 2.0 * center_h;
+ uv2s.push_back(Vector2(center_h + ((u - 0.5) * w_h), v * height_v));
+ }
point++;
if (i > 0 && j > 0) {
@@ -1480,17 +1848,20 @@ void SphereMesh::create_mesh_array(Array &p_arr, float radius, float height, int
indices.push_back(prevrow + i);
indices.push_back(thisrow + i);
indices.push_back(thisrow + i - 1);
- };
- };
+ }
+ }
prevrow = thisrow;
thisrow = point;
- };
+ }
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;
+ if (p_add_uv2) {
+ p_arr[RS::ARRAY_TEX_UV2] = uv2s;
+ }
p_arr[RS::ARRAY_INDEX] = indices;
}
@@ -1517,6 +1888,7 @@ void SphereMesh::_bind_methods() {
void SphereMesh::set_radius(const float p_radius) {
radius = p_radius;
+ _update_lightmap_size();
_request_update();
}
@@ -1526,6 +1898,7 @@ float SphereMesh::get_radius() const {
void SphereMesh::set_height(const float p_height) {
height = p_height;
+ _update_lightmap_size();
_request_update();
}
@@ -1553,6 +1926,7 @@ int SphereMesh::get_rings() const {
void SphereMesh::set_is_hemisphere(const bool p_is_hemisphere) {
is_hemisphere = p_is_hemisphere;
+ _update_lightmap_size();
_request_update();
}
@@ -1566,6 +1940,31 @@ SphereMesh::SphereMesh() {}
TorusMesh
*/
+void TorusMesh::_update_lightmap_size() {
+ if (get_add_uv2()) {
+ // size must have changed, update lightmap size hint
+ Size2i _lightmap_size_hint;
+ float texel_size = get_lightmap_texel_size();
+ float padding = get_uv2_padding();
+
+ 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;
+
+ float _width = max_radius * Math_TAU;
+ _lightmap_size_hint.x = MAX(1.0, (_width / texel_size) + padding);
+ float _height = radius * Math_TAU;
+ _lightmap_size_hint.y = MAX(1.0, (_height / texel_size) + padding);
+
+ set_lightmap_size_hint(_lightmap_size_hint);
+ }
+}
+
void TorusMesh::_create_mesh_array(Array &p_arr) const {
// set our bounding box
@@ -1573,6 +1972,7 @@ void TorusMesh::_create_mesh_array(Array &p_arr) const {
Vector<Vector3> normals;
Vector<float> tangents;
Vector<Vector2> uvs;
+ Vector<Vector2> uv2s;
Vector<int> indices;
#define ADD_TANGENT(m_x, m_y, m_z, m_d) \
@@ -1592,6 +1992,17 @@ void TorusMesh::_create_mesh_array(Array &p_arr) const {
float radius = (max_radius - min_radius) * 0.5;
+ // Only used if we calculate UV2
+ bool _add_uv2 = get_add_uv2();
+ float texel_size = get_lightmap_texel_size();
+ float _uv2_padding = get_uv2_padding() * texel_size;
+
+ float horizontal_total = max_radius * Math_TAU + _uv2_padding;
+ float max_h = max_radius * Math_TAU / horizontal_total;
+ float delta_h = (max_radius - min_radius) * Math_TAU / horizontal_total;
+
+ float height_v = radius * Math_TAU / (radius * Math_TAU + _uv2_padding);
+
for (int i = 0; i <= rings; i++) {
int prevrow = (i - 1) * (ring_segments + 1);
int thisrow = i * (ring_segments + 1);
@@ -1607,10 +2018,17 @@ void TorusMesh::_create_mesh_array(Array &p_arr) const {
Vector2 normalj = Vector2(-Math::cos(angj), Math::sin(angj));
Vector2 normalk = normalj * radius + Vector2(min_radius + radius, 0);
+ float offset_h = 0.5 * (1.0 - normalj.x) * delta_h;
+ float adj_h = max_h - offset_h;
+ offset_h *= 0.5;
+
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 (_add_uv2) {
+ uv2s.push_back(Vector2(offset_h + inci * adj_h, incj * height_v));
+ }
if (i > 0 && j > 0) {
indices.push_back(thisrow + j - 1);
@@ -1628,6 +2046,9 @@ void TorusMesh::_create_mesh_array(Array &p_arr) const {
p_arr[RS::ARRAY_NORMAL] = normals;
p_arr[RS::ARRAY_TANGENT] = tangents;
p_arr[RS::ARRAY_TEX_UV] = uvs;
+ if (_add_uv2) {
+ p_arr[RS::ARRAY_TEX_UV2] = uv2s;
+ }
p_arr[RS::ARRAY_INDEX] = indices;
}
@@ -1750,6 +2171,24 @@ int TubeTrailMesh::get_section_rings() const {
return section_rings;
}
+void TubeTrailMesh::set_cap_top(bool p_cap_top) {
+ cap_top = p_cap_top;
+ _request_update();
+}
+
+bool TubeTrailMesh::is_cap_top() const {
+ return cap_top;
+}
+
+void TubeTrailMesh::set_cap_bottom(bool p_cap_bottom) {
+ cap_bottom = p_cap_bottom;
+ _request_update();
+}
+
+bool TubeTrailMesh::is_cap_bottom() const {
+ return cap_bottom;
+}
+
void TubeTrailMesh::set_curve(const Ref<Curve> &p_curve) {
if (curve == p_curve) {
return;
@@ -1785,6 +2224,8 @@ Transform3D TubeTrailMesh::get_builtin_bind_pose(int p_index) const {
}
void TubeTrailMesh::_create_mesh_array(Array &p_arr) const {
+ // Seeing use case for TubeTrailMesh, no need to do anything more then default UV2 calculation
+
PackedVector3Array points;
PackedVector3Array normals;
PackedFloat32Array tangents;
@@ -1861,49 +2302,21 @@ void TubeTrailMesh::_create_mesh_array(Array &p_arr) const {
thisrow = point;
}
- // add top
- float scale_pos = 1.0;
- if (curve.is_valid() && curve->get_point_count() > 0) {
- scale_pos = curve->sample_baked(0);
- }
-
- if (scale_pos > CMP_EPSILON) {
- float y = depth * 0.5;
-
- thisrow = point;
- points.push_back(Vector3(0.0, y, 0));
- normals.push_back(Vector3(0.0, 1.0, 0.0));
- ADD_TANGENT(1.0, 0.0, 0.0, 1.0)
- uvs.push_back(Vector2(0.25, 0.75));
- point++;
-
- bone_indices.push_back(0);
- bone_indices.push_back(0);
- bone_indices.push_back(0);
- bone_indices.push_back(0);
-
- bone_weights.push_back(1.0);
- bone_weights.push_back(0);
- bone_weights.push_back(0);
- bone_weights.push_back(0);
-
- float rm = radius * scale_pos;
-
- for (int i = 0; i <= radial_steps; i++) {
- float r = i;
- r /= radial_steps;
-
- float x = sin(r * Math_TAU);
- float z = cos(r * Math_TAU);
+ if (cap_top) {
+ // add top
+ float scale_pos = 1.0;
+ if (curve.is_valid() && curve->get_point_count() > 0) {
+ scale_pos = curve->sample_baked(0);
+ }
- float u = ((x + 1.0) * 0.25);
- float v = 0.5 + ((z + 1.0) * 0.25);
+ if (scale_pos > CMP_EPSILON) {
+ float y = depth * 0.5;
- Vector3 p = Vector3(x * rm, y, z * rm);
- points.push_back(p);
+ thisrow = point;
+ points.push_back(Vector3(0.0, y, 0));
normals.push_back(Vector3(0.0, 1.0, 0.0));
ADD_TANGENT(1.0, 0.0, 0.0, 1.0)
- uvs.push_back(Vector2(u, v));
+ uvs.push_back(Vector2(0.25, 0.75));
point++;
bone_indices.push_back(0);
@@ -1916,57 +2329,59 @@ void TubeTrailMesh::_create_mesh_array(Array &p_arr) const {
bone_weights.push_back(0);
bone_weights.push_back(0);
- if (i > 0) {
- indices.push_back(thisrow);
- indices.push_back(point - 1);
- indices.push_back(point - 2);
- };
- };
- };
+ float rm = radius * scale_pos;
- float scale_neg = 1.0;
- if (curve.is_valid() && curve->get_point_count() > 0) {
- scale_neg = curve->sample_baked(1.0);
- }
+ for (int i = 0; i <= radial_steps; i++) {
+ float r = i;
+ r /= radial_steps;
- // add bottom
- if (scale_neg > CMP_EPSILON) {
- float y = depth * -0.5;
+ float x = sin(r * Math_TAU);
+ float z = cos(r * Math_TAU);
- thisrow = point;
- points.push_back(Vector3(0.0, y, 0.0));
- normals.push_back(Vector3(0.0, -1.0, 0.0));
- ADD_TANGENT(1.0, 0.0, 0.0, 1.0)
- uvs.push_back(Vector2(0.75, 0.75));
- point++;
+ float u = ((x + 1.0) * 0.25);
+ float v = 0.5 + ((z + 1.0) * 0.25);
- bone_indices.push_back(sections);
- bone_indices.push_back(0);
- bone_indices.push_back(0);
- bone_indices.push_back(0);
+ Vector3 p = Vector3(x * rm, y, z * rm);
+ points.push_back(p);
+ normals.push_back(Vector3(0.0, 1.0, 0.0));
+ ADD_TANGENT(1.0, 0.0, 0.0, 1.0)
+ uvs.push_back(Vector2(u, v));
+ point++;
- bone_weights.push_back(1.0);
- bone_weights.push_back(0);
- bone_weights.push_back(0);
- bone_weights.push_back(0);
+ bone_indices.push_back(0);
+ bone_indices.push_back(0);
+ bone_indices.push_back(0);
+ bone_indices.push_back(0);
- float rm = radius * scale_neg;
+ bone_weights.push_back(1.0);
+ bone_weights.push_back(0);
+ bone_weights.push_back(0);
+ bone_weights.push_back(0);
- for (int i = 0; i <= radial_steps; i++) {
- float r = i;
- r /= radial_steps;
+ if (i > 0) {
+ indices.push_back(thisrow);
+ indices.push_back(point - 1);
+ indices.push_back(point - 2);
+ }
+ }
+ }
+ }
- float x = sin(r * Math_TAU);
- float z = cos(r * Math_TAU);
+ if (cap_bottom) {
+ float scale_neg = 1.0;
+ if (curve.is_valid() && curve->get_point_count() > 0) {
+ scale_neg = curve->sample_baked(1.0);
+ }
- float u = 0.5 + ((x + 1.0) * 0.25);
- float v = 1.0 - ((z + 1.0) * 0.25);
+ if (scale_neg > CMP_EPSILON) {
+ // add bottom
+ float y = depth * -0.5;
- Vector3 p = Vector3(x * rm, y, z * rm);
- points.push_back(p);
+ thisrow = point;
+ points.push_back(Vector3(0.0, y, 0.0));
normals.push_back(Vector3(0.0, -1.0, 0.0));
ADD_TANGENT(1.0, 0.0, 0.0, 1.0)
- uvs.push_back(Vector2(u, v));
+ uvs.push_back(Vector2(0.75, 0.75));
point++;
bone_indices.push_back(sections);
@@ -1979,13 +2394,43 @@ void TubeTrailMesh::_create_mesh_array(Array &p_arr) const {
bone_weights.push_back(0);
bone_weights.push_back(0);
- if (i > 0) {
- indices.push_back(thisrow);
- indices.push_back(point - 2);
- indices.push_back(point - 1);
- };
- };
- };
+ float rm = radius * scale_neg;
+
+ for (int i = 0; i <= radial_steps; i++) {
+ float r = i;
+ r /= radial_steps;
+
+ float x = sin(r * Math_TAU);
+ float z = cos(r * Math_TAU);
+
+ float u = 0.5 + ((x + 1.0) * 0.25);
+ float v = 1.0 - ((z + 1.0) * 0.25);
+
+ Vector3 p = Vector3(x * rm, y, z * rm);
+ points.push_back(p);
+ normals.push_back(Vector3(0.0, -1.0, 0.0));
+ ADD_TANGENT(1.0, 0.0, 0.0, 1.0)
+ uvs.push_back(Vector2(u, v));
+ point++;
+
+ bone_indices.push_back(sections);
+ bone_indices.push_back(0);
+ bone_indices.push_back(0);
+ bone_indices.push_back(0);
+
+ bone_weights.push_back(1.0);
+ bone_weights.push_back(0);
+ bone_weights.push_back(0);
+ bone_weights.push_back(0);
+
+ if (i > 0) {
+ indices.push_back(thisrow);
+ indices.push_back(point - 2);
+ indices.push_back(point - 1);
+ }
+ }
+ }
+ }
p_arr[RS::ARRAY_VERTEX] = points;
p_arr[RS::ARRAY_NORMAL] = normals;
@@ -2012,6 +2457,12 @@ void TubeTrailMesh::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_section_rings", "section_rings"), &TubeTrailMesh::set_section_rings);
ClassDB::bind_method(D_METHOD("get_section_rings"), &TubeTrailMesh::get_section_rings);
+ ClassDB::bind_method(D_METHOD("set_cap_top", "cap_top"), &TubeTrailMesh::set_cap_top);
+ ClassDB::bind_method(D_METHOD("is_cap_top"), &TubeTrailMesh::is_cap_top);
+
+ ClassDB::bind_method(D_METHOD("set_cap_bottom", "cap_bottom"), &TubeTrailMesh::set_cap_bottom);
+ ClassDB::bind_method(D_METHOD("is_cap_bottom"), &TubeTrailMesh::is_cap_bottom);
+
ClassDB::bind_method(D_METHOD("set_curve", "curve"), &TubeTrailMesh::set_curve);
ClassDB::bind_method(D_METHOD("get_curve"), &TubeTrailMesh::get_curve);
@@ -2024,13 +2475,16 @@ void TubeTrailMesh::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "section_rings", PROPERTY_HINT_RANGE, "1,128,1"), "set_section_rings", "get_section_rings");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "cap_top"), "set_cap_top", "is_cap_top");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "cap_bottom"), "set_cap_bottom", "is_cap_bottom");
+
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_curve", "get_curve");
}
TubeTrailMesh::TubeTrailMesh() {
}
-// TUBE TRAIL
+// RIBBON TRAIL
void RibbonTrailMesh::set_shape(Shape p_shape) {
shape = p_shape;
@@ -2109,6 +2563,8 @@ Transform3D RibbonTrailMesh::get_builtin_bind_pose(int p_index) const {
}
void RibbonTrailMesh::_create_mesh_array(Array &p_arr) const {
+ // Seeing use case of ribbon trail mesh, no need to implement special UV2 calculation
+
PackedVector3Array points;
PackedVector3Array normals;
PackedFloat32Array tangents;
@@ -2354,13 +2810,7 @@ void TextMesh::_generate_glyph_mesh_data(const GlyphMeshKey &p_key, const Glyph
real_t step = CLAMP(curve_step / (p0 - p3).length(), 0.01, 0.5);
real_t t = step;
while (t < 1.0) {
- real_t omt = (1.0 - t);
- real_t omt2 = omt * omt;
- real_t omt3 = omt2 * omt;
- real_t t2 = t * t;
- real_t t3 = t2 * t;
-
- Vector2 point = p0 * omt3 + p1 * omt2 * t * 3.0 + p2 * omt * t2 * 3.0 + p3 * t3;
+ Vector2 point = p0.bezier_interpolate(p1, p2, p3, t);
Vector2 p = point * pixel_size + origin;
polygon.push_back(ContourPoint(p, false));
t += step;
diff --git a/scene/resources/primitive_meshes.h b/scene/resources/primitive_meshes.h
index ee61f0ac55..5cef042a18 100644
--- a/scene/resources/primitive_meshes.h
+++ b/scene/resources/primitive_meshes.h
@@ -56,6 +56,9 @@ private:
Ref<Material> material;
bool flip_faces = false;
+ bool add_uv2 = false;
+ float uv2_padding = 2.0;
+
// make sure we do an update after we've finished constructing our object
mutable bool pending_request = true;
void _update() const;
@@ -70,6 +73,10 @@ protected:
void _request_update();
GDVIRTUAL0RC(Array, _create_mesh_array)
+ Vector2 get_uv2_scale(Vector2 p_margin_scale = Vector2(1.0, 1.0)) const;
+ float get_lightmap_texel_size() const;
+ virtual void _update_lightmap_size(){};
+
public:
virtual int get_surface_count() const override;
virtual int surface_get_array_len(int p_idx) const override;
@@ -98,6 +105,12 @@ public:
void set_flip_faces(bool p_enable);
bool get_flip_faces() const;
+ void set_add_uv2(bool p_enable);
+ bool get_add_uv2() const { return add_uv2; }
+
+ void set_uv2_padding(float p_padding);
+ float get_uv2_padding() const { return uv2_padding; }
+
PrimitiveMesh();
~PrimitiveMesh();
};
@@ -118,8 +131,10 @@ protected:
static void _bind_methods();
virtual void _create_mesh_array(Array &p_arr) const override;
+ virtual void _update_lightmap_size() override;
+
public:
- static void create_mesh_array(Array &p_arr, float radius, float height, int radial_segments = 64, int rings = 8);
+ static void create_mesh_array(Array &p_arr, float radius, float height, int radial_segments = 64, int rings = 8, bool p_add_uv2 = false, const float p_uv2_padding = 1.0);
void set_radius(const float p_radius);
float get_radius() const;
@@ -152,8 +167,10 @@ protected:
static void _bind_methods();
virtual void _create_mesh_array(Array &p_arr) const override;
+ virtual void _update_lightmap_size() override;
+
public:
- static void create_mesh_array(Array &p_arr, Vector3 size, int subdivide_w = 0, int subdivide_h = 0, int subdivide_d = 0);
+ static void create_mesh_array(Array &p_arr, Vector3 size, int subdivide_w = 0, int subdivide_h = 0, int subdivide_d = 0, bool p_add_uv2 = false, const float p_uv2_padding = 1.0);
void set_size(const Vector3 &p_size);
Vector3 get_size() const;
@@ -190,8 +207,10 @@ protected:
static void _bind_methods();
virtual void _create_mesh_array(Array &p_arr) const override;
+ virtual void _update_lightmap_size() override;
+
public:
- static void create_mesh_array(Array &p_arr, float top_radius, float bottom_radius, float height, int radial_segments = 64, int rings = 4, bool cap_top = true, bool cap_bottom = true);
+ static void create_mesh_array(Array &p_arr, float top_radius, float bottom_radius, float height, int radial_segments = 64, int rings = 4, bool cap_top = true, bool cap_bottom = true, bool p_add_uv2 = false, const float p_uv2_padding = 1.0);
void set_top_radius(const float p_radius);
float get_top_radius() const;
@@ -241,6 +260,8 @@ protected:
static void _bind_methods();
virtual void _create_mesh_array(Array &p_arr) const override;
+ virtual void _update_lightmap_size() override;
+
public:
void set_size(const Size2 &p_size);
Size2 get_size() const;
@@ -292,6 +313,8 @@ protected:
static void _bind_methods();
virtual void _create_mesh_array(Array &p_arr) const override;
+ virtual void _update_lightmap_size() override;
+
public:
void set_left_to_right(const float p_left_to_right);
float get_left_to_right() const;
@@ -328,8 +351,10 @@ protected:
static void _bind_methods();
virtual void _create_mesh_array(Array &p_arr) const override;
+ virtual void _update_lightmap_size() override;
+
public:
- static void create_mesh_array(Array &p_arr, float radius, float height, int radial_segments = 64, int rings = 32, bool is_hemisphere = false);
+ static void create_mesh_array(Array &p_arr, float radius, float height, int radial_segments = 64, int rings = 32, bool is_hemisphere = false, bool p_add_uv2 = false, const float p_uv2_padding = 1.0);
void set_radius(const float p_radius);
float get_radius() const;
@@ -365,6 +390,8 @@ protected:
static void _bind_methods();
virtual void _create_mesh_array(Array &p_arr) const override;
+ virtual void _update_lightmap_size() override;
+
public:
void set_inner_radius(const float p_inner_radius);
float get_inner_radius() const;
@@ -404,6 +431,8 @@ private:
int sections = 5;
float section_length = 0.2;
int section_rings = 3;
+ bool cap_top = true;
+ bool cap_bottom = true;
Ref<Curve> curve;
@@ -429,6 +458,12 @@ public:
void set_section_rings(const int p_section_rings);
int get_section_rings() const;
+ void set_cap_top(bool p_cap_top);
+ bool is_cap_top() const;
+
+ void set_cap_bottom(bool p_cap_bottom);
+ bool is_cap_bottom() const;
+
void set_curve(const Ref<Curve> &p_curve);
Ref<Curve> get_curve() const;
diff --git a/scene/resources/resource_format_text.cpp b/scene/resources/resource_format_text.cpp
index 85b538b1d9..092f672cba 100644
--- a/scene/resources/resource_format_text.cpp
+++ b/scene/resources/resource_format_text.cpp
@@ -144,6 +144,7 @@ Error ResourceLoaderText::_parse_ext_resource(VariantParser::Stream *p_stream, R
}
String id = token.value;
+ Error err = OK;
if (!ignore_resource_parsing) {
if (!ext_resources.has(id)) {
@@ -163,7 +164,7 @@ Error ResourceLoaderText::_parse_ext_resource(VariantParser::Stream *p_stream, R
error = ERR_FILE_MISSING_DEPENDENCIES;
error_text = "[ext_resource] referenced nonexistent resource at: " + path;
_printerr();
- return error;
+ err = error;
} else {
ResourceLoader::notify_dependency_error(local_path, path, type);
}
@@ -175,7 +176,7 @@ Error ResourceLoaderText::_parse_ext_resource(VariantParser::Stream *p_stream, R
error = ERR_FILE_MISSING_DEPENDENCIES;
error_text = "[ext_resource] referenced non-loaded resource at: " + path;
_printerr();
- return error;
+ err = error;
}
} else {
r_res = Ref<Resource>();
@@ -187,7 +188,7 @@ Error ResourceLoaderText::_parse_ext_resource(VariantParser::Stream *p_stream, R
return ERR_PARSE_ERROR;
}
- return OK;
+ return err;
}
Ref<PackedScene> ResourceLoaderText::_parse_node_tag(VariantParser::ResourceParser &parser) {
@@ -217,7 +218,7 @@ Ref<PackedScene> ResourceLoaderText::_parse_node_tag(VariantParser::ResourcePars
if (next_tag.fields.has("type")) {
type = packed_scene->get_state()->add_name(next_tag.fields["type"]);
} else {
- type = SceneState::TYPE_INSTANCED; //no type? assume this was instantiated
+ type = SceneState::TYPE_INSTANTIATED; //no type? assume this was instantiated
}
HashSet<StringName> path_properties;
@@ -256,7 +257,7 @@ Ref<PackedScene> ResourceLoaderText::_parse_node_tag(VariantParser::ResourcePars
if (next_tag.fields.has("owner")) {
owner = packed_scene->get_state()->add_node_path(next_tag.fields["owner"]);
} else {
- if (parent != -1 && !(type == SceneState::TYPE_INSTANCED && instance == -1)) {
+ if (parent != -1 && !(type == SceneState::TYPE_INSTANTIATED && instance == -1)) {
owner = 0; //if no owner, owner is root
}
}
@@ -511,6 +512,7 @@ Error ResourceLoaderText::load() {
if (error) {
_printerr();
+ return error;
}
resource_current++;
@@ -600,9 +602,13 @@ Error ResourceLoaderText::load() {
resource_current++;
int_resources[id] = res; //always assign int resources
- if (do_assign && cache_mode != ResourceFormatLoader::CACHE_MODE_IGNORE) {
- res->set_path(path, cache_mode == ResourceFormatLoader::CACHE_MODE_REPLACE);
- res->set_scene_unique_id(id);
+ if (do_assign) {
+ if (cache_mode == ResourceFormatLoader::CACHE_MODE_IGNORE) {
+ res->set_path(path);
+ } else {
+ res->set_path(path, cache_mode == ResourceFormatLoader::CACHE_MODE_REPLACE);
+ res->set_scene_unique_id(id);
+ }
}
Dictionary missing_resource_properties;
@@ -830,7 +836,8 @@ void ResourceLoaderText::set_translation_remapped(bool p_remapped) {
translation_remapped = p_remapped;
}
-ResourceLoaderText::ResourceLoaderText() {}
+ResourceLoaderText::ResourceLoaderText() :
+ stream(false) {}
void ResourceLoaderText::get_dependencies(Ref<FileAccess> p_f, List<String> *p_dependencies, bool p_add_types) {
open(p_f);
@@ -884,6 +891,7 @@ void ResourceLoaderText::get_dependencies(Ref<FileAccess> p_f, List<String> *p_d
error_text = "Unexpected end of file";
_printerr();
error = ERR_FILE_CORRUPT;
+ return;
}
}
}
@@ -974,15 +982,26 @@ Error ResourceLoaderText::rename_dependencies(Ref<FileAccess> p_f, const String
f->seek(tag_end);
- uint8_t c = f->get_8();
- if (c == '\n' && !f->eof_reached()) {
- // Skip first newline character since we added one
- c = f->get_8();
+ const uint32_t buffer_size = 2048;
+ uint8_t *buffer = (uint8_t *)alloca(buffer_size);
+ uint32_t num_read;
+
+ num_read = f->get_buffer(buffer, buffer_size);
+ ERR_FAIL_COND_V_MSG(num_read == UINT32_MAX, ERR_CANT_CREATE, "Failed to allocate memory for buffer.");
+ ERR_FAIL_COND_V(num_read == 0, ERR_FILE_CORRUPT);
+
+ if (*buffer == '\n') {
+ // Skip first newline character since we added one.
+ if (num_read > 1) {
+ fw->store_buffer(buffer + 1, num_read - 1);
+ }
+ } else {
+ fw->store_buffer(buffer, num_read);
}
while (!f->eof_reached()) {
- fw->store_8(c);
- c = f->get_8();
+ num_read = f->get_buffer(buffer, buffer_size);
+ fw->store_buffer(buffer, num_read);
}
bool all_ok = fw->get_error() == OK;
@@ -1349,7 +1368,7 @@ Error ResourceLoaderText::save_as_binary(const String &p_path) {
wf->seek_end();
- Vector<uint8_t> data = FileAccess::get_file_as_array(temp_file);
+ Vector<uint8_t> data = FileAccess::get_file_as_bytes(temp_file);
wf->store_buffer(data.ptr(), data.size());
{
Ref<DirAccess> dar = DirAccess::open(temp_file.get_base_dir());
diff --git a/scene/resources/shader.cpp b/scene/resources/shader.cpp
index 3a671edeea..48ec084b02 100644
--- a/scene/resources/shader.cpp
+++ b/scene/resources/shader.cpp
@@ -221,7 +221,7 @@ Ref<Resource> ResourceFormatLoaderShader::load(const String &p_path, const Strin
Ref<Shader> shader;
shader.instantiate();
- Vector<uint8_t> buffer = FileAccess::get_file_as_array(p_path);
+ Vector<uint8_t> buffer = FileAccess::get_file_as_bytes(p_path);
String str;
str.parse_utf8((const char *)buffer.ptr(), buffer.size());
diff --git a/scene/resources/shader_include.cpp b/scene/resources/shader_include.cpp
index fe628dd323..a680e66a50 100644
--- a/scene/resources/shader_include.cpp
+++ b/scene/resources/shader_include.cpp
@@ -81,7 +81,7 @@ Ref<Resource> ResourceFormatLoaderShaderInclude::load(const String &p_path, cons
Ref<ShaderInclude> shader_inc;
shader_inc.instantiate();
- Vector<uint8_t> buffer = FileAccess::get_file_as_array(p_path);
+ Vector<uint8_t> buffer = FileAccess::get_file_as_bytes(p_path);
String str;
str.parse_utf8((const char *)buffer.ptr(), buffer.size());
diff --git a/scene/resources/shape_2d.cpp b/scene/resources/shape_2d.cpp
index af84144591..87c6c36ee9 100644
--- a/scene/resources/shape_2d.cpp
+++ b/scene/resources/shape_2d.cpp
@@ -124,5 +124,6 @@ Shape2D::Shape2D(const RID &p_rid) {
}
Shape2D::~Shape2D() {
+ ERR_FAIL_NULL(PhysicsServer2D::get_singleton());
PhysicsServer2D::get_singleton()->free(shape);
}
diff --git a/scene/resources/shape_3d.cpp b/scene/resources/shape_3d.cpp
index 4423c1d7bb..7992ba9fd4 100644
--- a/scene/resources/shape_3d.cpp
+++ b/scene/resources/shape_3d.cpp
@@ -128,5 +128,6 @@ Shape3D::Shape3D(RID p_shape) :
shape(p_shape) {}
Shape3D::~Shape3D() {
+ ERR_FAIL_NULL(PhysicsServer3D::get_singleton());
PhysicsServer3D::get_singleton()->free(shape);
}
diff --git a/scene/resources/skeleton_modification_2d_fabrik.h b/scene/resources/skeleton_modification_2d_fabrik.h
index 4a875d039f..0ca6582965 100644
--- a/scene/resources/skeleton_modification_2d_fabrik.h
+++ b/scene/resources/skeleton_modification_2d_fabrik.h
@@ -68,8 +68,8 @@ private:
float chain_tolarance = 0.01;
int chain_max_iterations = 10;
int chain_iterations = 0;
- Transform2D target_global_pose = Transform2D();
- Transform2D origin_global_pose = Transform2D();
+ Transform2D target_global_pose;
+ Transform2D origin_global_pose;
void fabrik_joint_update_bone2d_cache(int p_joint_idx);
void chain_backwards();
diff --git a/scene/resources/skeleton_modification_3d_fabrik.h b/scene/resources/skeleton_modification_3d_fabrik.h
index e2e490d636..3e3aa5e587 100644
--- a/scene/resources/skeleton_modification_3d_fabrik.h
+++ b/scene/resources/skeleton_modification_3d_fabrik.h
@@ -47,7 +47,7 @@ private:
bool auto_calculate_length = true;
bool use_tip_node = false;
- NodePath tip_node = NodePath();
+ NodePath tip_node;
ObjectID tip_node_cache;
bool use_target_basis = false;
@@ -68,8 +68,8 @@ private:
void update_joint_tip_cache(int p_joint_idx);
int final_joint_idx = 0;
- Transform3D target_global_pose = Transform3D();
- Transform3D origin_global_pose = Transform3D();
+ Transform3D target_global_pose;
+ Transform3D origin_global_pose;
void chain_backwards();
void chain_forwards();
diff --git a/scene/resources/style_box.cpp b/scene/resources/style_box.cpp
index f379f88bed..ea341152e6 100644
--- a/scene/resources/style_box.cpp
+++ b/scene/resources/style_box.cpp
@@ -35,11 +35,9 @@
#include <limits.h>
float StyleBox::get_style_margin(Side p_side) const {
- float ret;
- if (GDVIRTUAL_REQUIRED_CALL(_get_style_margin, p_side, ret)) {
- return ret;
- }
- return 0;
+ float ret = 0;
+ GDVIRTUAL_REQUIRED_CALL(_get_style_margin, p_side, ret);
+ return ret;
}
bool StyleBox::test_mask(const Point2 &p_point, const Rect2 &p_rect) const {
@@ -49,9 +47,7 @@ bool StyleBox::test_mask(const Point2 &p_point, const Rect2 &p_rect) const {
}
void StyleBox::draw(RID p_canvas_item, const Rect2 &p_rect) const {
- if (GDVIRTUAL_REQUIRED_CALL(_draw, p_canvas_item, p_rect)) {
- return;
- }
+ GDVIRTUAL_REQUIRED_CALL(_draw, p_canvas_item, p_rect);
}
void StyleBox::set_default_margin(Side p_side, float p_value) {
diff --git a/scene/resources/syntax_highlighter.cpp b/scene/resources/syntax_highlighter.cpp
index f1eddd8ffc..cb5cb4ef96 100644
--- a/scene/resources/syntax_highlighter.cpp
+++ b/scene/resources/syntax_highlighter.cpp
@@ -336,7 +336,7 @@ Dictionary CodeHighlighter::_get_line_syntax_highlighting_impl(int p_line) {
}
String word = str.substr(j, to - j);
- Color col = Color();
+ Color col;
if (keywords.has(word)) {
col = keywords[word];
} else if (member_keywords.has(word)) {
diff --git a/scene/resources/text_line.cpp b/scene/resources/text_line.cpp
index afab44834d..d094563e6a 100644
--- a/scene/resources/text_line.cpp
+++ b/scene/resources/text_line.cpp
@@ -56,8 +56,8 @@ 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", "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));
+ ClassDB::bind_method(D_METHOD("add_object", "key", "size", "inline_align", "length", "baseline"), &TextLine::add_object, DEFVAL(INLINE_ALIGNMENT_CENTER), DEFVAL(1), DEFVAL(0.0));
+ ClassDB::bind_method(D_METHOD("resize_object", "key", "size", "inline_align", "baseline"), &TextLine::resize_object, DEFVAL(INLINE_ALIGNMENT_CENTER), DEFVAL(0.0));
ClassDB::bind_method(D_METHOD("set_width", "width"), &TextLine::set_width);
ClassDB::bind_method(D_METHOD("get_width"), &TextLine::get_width);
@@ -202,15 +202,15 @@ bool TextLine::add_string(const String &p_text, const Ref<Font> &p_font, int p_f
return res;
}
-bool TextLine::add_object(Variant p_key, const Size2 &p_size, InlineAlignment p_inline_align, int p_length) {
- bool res = TS->shaped_text_add_object(rid, p_key, p_size, p_inline_align, p_length);
+bool TextLine::add_object(Variant p_key, const Size2 &p_size, InlineAlignment p_inline_align, int p_length, float p_baseline) {
+ bool res = TS->shaped_text_add_object(rid, p_key, p_size, p_inline_align, p_length, p_baseline);
dirty = true;
return res;
}
-bool TextLine::resize_object(Variant p_key, const Size2 &p_size, InlineAlignment p_inline_align) {
+bool TextLine::resize_object(Variant p_key, const Size2 &p_size, InlineAlignment p_inline_align, float p_baseline) {
const_cast<TextLine *>(this)->_shape();
- return TS->shaped_text_resize_object(rid, p_key, p_size, p_inline_align);
+ return TS->shaped_text_resize_object(rid, p_key, p_size, p_inline_align, p_baseline);
}
Array TextLine::get_objects() const {
diff --git a/scene/resources/text_line.h b/scene/resources/text_line.h
index e70e82cf2b..801a8a8c11 100644
--- a/scene/resources/text_line.h
+++ b/scene/resources/text_line.h
@@ -76,8 +76,8 @@ public:
bool get_preserve_control() const;
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);
+ bool add_object(Variant p_key, const Size2 &p_size, InlineAlignment p_inline_align = INLINE_ALIGNMENT_CENTER, int p_length = 1, float p_baseline = 0.0);
+ bool resize_object(Variant p_key, const Size2 &p_size, InlineAlignment p_inline_align = INLINE_ALIGNMENT_CENTER, float p_baseline = 0.0);
void set_horizontal_alignment(HorizontalAlignment p_alignment);
HorizontalAlignment get_horizontal_alignment() const;
diff --git a/scene/resources/text_paragraph.cpp b/scene/resources/text_paragraph.cpp
index 59bb24c8b8..d2e85d28e6 100644
--- a/scene/resources/text_paragraph.cpp
+++ b/scene/resources/text_paragraph.cpp
@@ -64,8 +64,8 @@ void TextParagraph::_bind_methods() {
ClassDB::bind_method(D_METHOD("clear_dropcap"), &TextParagraph::clear_dropcap);
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));
+ ClassDB::bind_method(D_METHOD("add_object", "key", "size", "inline_align", "length", "baseline"), &TextParagraph::add_object, DEFVAL(INLINE_ALIGNMENT_CENTER), DEFVAL(1), DEFVAL(0.0));
+ ClassDB::bind_method(D_METHOD("resize_object", "key", "size", "inline_align", "baseline"), &TextParagraph::resize_object, DEFVAL(INLINE_ALIGNMENT_CENTER), DEFVAL(0.0));
ClassDB::bind_method(D_METHOD("set_alignment", "alignment"), &TextParagraph::set_alignment);
ClassDB::bind_method(D_METHOD("get_alignment"), &TextParagraph::get_alignment);
@@ -385,18 +385,18 @@ void TextParagraph::set_bidi_override(const Array &p_override) {
lines_dirty = true;
}
-bool TextParagraph::add_object(Variant p_key, const Size2 &p_size, InlineAlignment p_inline_align, int p_length) {
+bool TextParagraph::add_object(Variant p_key, const Size2 &p_size, InlineAlignment p_inline_align, int p_length, float p_baseline) {
_THREAD_SAFE_METHOD_
- bool res = TS->shaped_text_add_object(rid, p_key, p_size, p_inline_align, p_length);
+ bool res = TS->shaped_text_add_object(rid, p_key, p_size, p_inline_align, p_length, p_baseline);
lines_dirty = true;
return res;
}
-bool TextParagraph::resize_object(Variant p_key, const Size2 &p_size, InlineAlignment p_inline_align) {
+bool TextParagraph::resize_object(Variant p_key, const Size2 &p_size, InlineAlignment p_inline_align, float p_baseline) {
_THREAD_SAFE_METHOD_
- bool res = TS->shaped_text_resize_object(rid, p_key, p_size, p_inline_align);
+ bool res = TS->shaped_text_resize_object(rid, p_key, p_size, p_inline_align, p_baseline);
lines_dirty = true;
return res;
}
diff --git a/scene/resources/text_paragraph.h b/scene/resources/text_paragraph.h
index 0fe82b4364..dced278db4 100644
--- a/scene/resources/text_paragraph.h
+++ b/scene/resources/text_paragraph.h
@@ -95,8 +95,8 @@ public:
void clear_dropcap();
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);
+ bool add_object(Variant p_key, const Size2 &p_size, InlineAlignment p_inline_align = INLINE_ALIGNMENT_CENTER, int p_length = 1, float p_baseline = 0.0);
+ bool resize_object(Variant p_key, const Size2 &p_size, InlineAlignment p_inline_align = INLINE_ALIGNMENT_CENTER, float p_baseline = 0.0);
void set_alignment(HorizontalAlignment p_alignment);
HorizontalAlignment get_alignment() const;
diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp
index a6fb359051..48eaf98aa3 100644
--- a/scene/resources/texture.cpp
+++ b/scene/resources/texture.cpp
@@ -40,19 +40,15 @@
#include "servers/camera/camera_feed.h"
int Texture2D::get_width() const {
- int ret;
- if (GDVIRTUAL_REQUIRED_CALL(_get_width, ret)) {
- return ret;
- }
- return 0;
+ int ret = 0;
+ GDVIRTUAL_REQUIRED_CALL(_get_width, ret);
+ return ret;
}
int Texture2D::get_height() const {
- int ret;
- if (GDVIRTUAL_REQUIRED_CALL(_get_height, ret)) {
- return ret;
- }
- return 0;
+ int ret = 0;
+ GDVIRTUAL_REQUIRED_CALL(_get_height, ret);
+ return ret;
}
Size2 Texture2D::get_size() const {
@@ -64,6 +60,7 @@ bool Texture2D::is_pixel_opaque(int p_x, int p_y) const {
GDVIRTUAL_CALL(_is_pixel_opaque, p_x, p_y, ret);
return ret;
}
+
bool Texture2D::has_alpha() const {
bool ret = true;
GDVIRTUAL_CALL(_has_alpha, ret);
@@ -1091,57 +1088,44 @@ TypedArray<Image> Texture3D::_get_datai() const {
}
Image::Format Texture3D::get_format() const {
- Image::Format ret;
- if (GDVIRTUAL_REQUIRED_CALL(_get_format, ret)) {
- return ret;
- }
- return Image::FORMAT_MAX;
+ Image::Format ret = Image::FORMAT_MAX;
+ GDVIRTUAL_REQUIRED_CALL(_get_format, ret);
+ return ret;
}
int Texture3D::get_width() const {
- int ret;
- if (GDVIRTUAL_REQUIRED_CALL(_get_width, ret)) {
- return ret;
- }
- return 0;
+ int ret = 0;
+ GDVIRTUAL_REQUIRED_CALL(_get_width, ret);
+ return ret;
}
int Texture3D::get_height() const {
- int ret;
- if (GDVIRTUAL_REQUIRED_CALL(_get_height, ret)) {
- return ret;
- }
- return 0;
+ int ret = 0;
+ GDVIRTUAL_REQUIRED_CALL(_get_height, ret);
+ return ret;
}
int Texture3D::get_depth() const {
- int ret;
- if (GDVIRTUAL_REQUIRED_CALL(_get_depth, ret)) {
- return ret;
- }
-
- return 0;
+ int ret = 0;
+ GDVIRTUAL_REQUIRED_CALL(_get_depth, ret);
+ return ret;
}
bool Texture3D::has_mipmaps() const {
- bool ret;
- if (GDVIRTUAL_REQUIRED_CALL(_has_mipmaps, ret)) {
- return ret;
- }
- return false;
+ bool ret = false;
+ GDVIRTUAL_REQUIRED_CALL(_has_mipmaps, ret);
+ return ret;
}
Vector<Ref<Image>> Texture3D::get_data() const {
TypedArray<Image> ret;
- if (GDVIRTUAL_REQUIRED_CALL(_get_data, ret)) {
- Vector<Ref<Image>> data;
- data.resize(ret.size());
- for (int i = 0; i < data.size(); i++) {
- data.write[i] = ret[i];
- }
- return data;
+ GDVIRTUAL_REQUIRED_CALL(_get_data, ret);
+ Vector<Ref<Image>> data;
+ data.resize(ret.size());
+ for (int i = 0; i < data.size(); i++) {
+ data.write[i] = ret[i];
}
- return Vector<Ref<Image>>();
+ return data;
}
void Texture3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_format"), &Texture3D::get_format);
@@ -1607,35 +1591,28 @@ bool AtlasTexture::get_rect_region(const Rect2 &p_rect, const Rect2 &p_src_rect,
return false;
}
- Rect2 rc = region;
-
Rect2 src = p_src_rect;
if (src.size == Size2()) {
- src.size = rc.size;
+ src.size = region.size;
}
Vector2 scale = p_rect.size / src.size;
- src.position += (rc.position - margin.position);
- Rect2 src_c = rc.intersection(src);
- if (src_c.size == Size2()) {
+ src.position += (region.position - margin.position);
+ Rect2 src_clipped = region.intersection(src);
+ if (src_clipped.size == Size2()) {
return false;
}
- Vector2 ofs = (src_c.position - src.position);
+ Vector2 ofs = (src_clipped.position - src.position);
if (scale.x < 0) {
- float mx = (margin.size.width - margin.position.x);
- mx -= margin.position.x;
- ofs.x = -(ofs.x + mx);
+ ofs.x += (src_clipped.size.x - src.size.x);
}
if (scale.y < 0) {
- float my = margin.size.height - margin.position.y;
- my -= margin.position.y;
- ofs.y = -(ofs.y + my);
+ ofs.y += (src_clipped.size.y - src.size.y);
}
- Rect2 dr(p_rect.position + ofs * scale, src_c.size * scale);
- r_rect = dr;
- r_src_rect = src_c;
+ r_rect = Rect2(p_rect.position + ofs * scale, src_clipped.size * scale);
+ r_src_rect = src_clipped;
return true;
}
@@ -2858,60 +2835,45 @@ AnimatedTexture::~AnimatedTexture() {
///////////////////////////////
Image::Format TextureLayered::get_format() const {
- Image::Format ret;
- if (GDVIRTUAL_REQUIRED_CALL(_get_format, ret)) {
- return ret;
- }
- return Image::FORMAT_MAX;
+ Image::Format ret = Image::FORMAT_MAX;
+ GDVIRTUAL_REQUIRED_CALL(_get_format, ret);
+ return ret;
}
TextureLayered::LayeredType TextureLayered::get_layered_type() const {
- uint32_t ret;
- if (GDVIRTUAL_REQUIRED_CALL(_get_layered_type, ret)) {
- return (LayeredType)ret;
- }
- return LAYERED_TYPE_2D_ARRAY;
+ uint32_t ret = LAYERED_TYPE_2D_ARRAY;
+ GDVIRTUAL_REQUIRED_CALL(_get_layered_type, ret);
+ return (LayeredType)ret;
}
int TextureLayered::get_width() const {
- int ret;
- if (GDVIRTUAL_REQUIRED_CALL(_get_width, ret)) {
- return ret;
- }
- return 0;
+ int ret = 0;
+ GDVIRTUAL_REQUIRED_CALL(_get_width, ret);
+ return ret;
}
int TextureLayered::get_height() const {
- int ret;
- if (GDVIRTUAL_REQUIRED_CALL(_get_height, ret)) {
- return ret;
- }
- return 0;
+ int ret = 0;
+ GDVIRTUAL_REQUIRED_CALL(_get_height, ret);
+ return ret;
}
int TextureLayered::get_layers() const {
- int ret;
- if (GDVIRTUAL_REQUIRED_CALL(_get_layers, ret)) {
- return ret;
- }
-
- return 0;
+ int ret = 0;
+ GDVIRTUAL_REQUIRED_CALL(_get_layers, ret);
+ return ret;
}
bool TextureLayered::has_mipmaps() const {
- bool ret;
- if (GDVIRTUAL_REQUIRED_CALL(_has_mipmaps, ret)) {
- return ret;
- }
- return false;
+ bool ret = false;
+ GDVIRTUAL_REQUIRED_CALL(_has_mipmaps, ret);
+ return ret;
}
Ref<Image> TextureLayered::get_layer_data(int p_layer) const {
Ref<Image> ret;
- if (GDVIRTUAL_REQUIRED_CALL(_get_layer_data, p_layer, ret)) {
- return ret;
- }
- return Ref<Image>();
+ GDVIRTUAL_REQUIRED_CALL(_get_layer_data, p_layer, ret);
+ return ret;
}
void TextureLayered::_bind_methods() {
@@ -3424,7 +3386,7 @@ RID PlaceholderTexture2D::get_rid() const {
void PlaceholderTexture2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_size", "size"), &PlaceholderTexture2D::set_size);
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "size", PROPERTY_HINT_NONE, "suffix:px"), "set_size", "get_size");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "size", PROPERTY_HINT_NONE, "suffix:px"), "set_size", "get_size");
}
PlaceholderTexture2D::PlaceholderTexture2D() {
diff --git a/scene/resources/tile_set.cpp b/scene/resources/tile_set.cpp
index 3caf6484d9..0b0461432b 100644
--- a/scene/resources/tile_set.cpp
+++ b/scene/resources/tile_set.cpp
@@ -35,7 +35,6 @@
#include "core/math/geometry_2d.h"
#include "core/templates/local_vector.h"
#include "core/templates/rb_set.h"
-#include "scene/2d/navigation_region_2d.h"
#include "scene/gui/control.h"
#include "scene/resources/convex_polygon_shape_2d.h"
#include "servers/navigation_server_2d.h"
@@ -477,7 +476,7 @@ int TileSet::add_source(Ref<TileSetSource> p_tile_set_source, int p_atlas_source
int new_source_id = p_atlas_source_id_override >= 0 ? p_atlas_source_id_override : next_source_id;
sources[new_source_id] = p_tile_set_source;
- source_ids.append(new_source_id);
+ source_ids.push_back(new_source_id);
source_ids.sort();
p_tile_set_source->set_tile_set(this);
_compute_next_source_id();
@@ -517,7 +516,7 @@ void TileSet::set_source_id(int p_source_id, int p_new_source_id) {
sources.erase(p_source_id);
source_ids.erase(p_source_id);
- source_ids.append(p_new_source_id);
+ source_ids.push_back(p_new_source_id);
source_ids.sort();
_compute_next_source_id();
@@ -1297,7 +1296,7 @@ void TileSet::cleanup_invalid_tile_proxies() {
Vector<int> source_to_remove;
for (const KeyValue<int, int> &E : source_level_proxies) {
if (has_source(E.key)) {
- source_to_remove.append(E.key);
+ source_to_remove.push_back(E.key);
}
}
for (int i = 0; i < source_to_remove.size(); i++) {
@@ -1309,7 +1308,7 @@ void TileSet::cleanup_invalid_tile_proxies() {
for (const KeyValue<Array, Array> &E : coords_level_proxies) {
Array a = E.key;
if (has_source(a[0]) && get_source(a[0])->has_tile(a[1])) {
- coords_to_remove.append(a);
+ coords_to_remove.push_back(a);
}
}
for (int i = 0; i < coords_to_remove.size(); i++) {
@@ -1322,7 +1321,7 @@ void TileSet::cleanup_invalid_tile_proxies() {
for (const KeyValue<Array, Array> &E : alternative_level_proxies) {
Array a = E.key;
if (has_source(a[0]) && get_source(a[0])->has_tile(a[1]) && get_source(a[0])->has_alternative_tile(a[1], a[2])) {
- alternative_to_remove.append(a);
+ alternative_to_remove.push_back(a);
}
}
for (int i = 0; i < alternative_to_remove.size(); i++) {
@@ -1439,16 +1438,18 @@ TileMapCell TileSet::get_random_tile_from_terrains_pattern(int p_terrain_set, Ti
Vector<Vector2> TileSet::get_tile_shape_polygon() {
Vector<Vector2> points;
if (tile_shape == TileSet::TILE_SHAPE_SQUARE) {
- points.append(Vector2(-0.5, -0.5));
- points.append(Vector2(0.5, -0.5));
- points.append(Vector2(0.5, 0.5));
- points.append(Vector2(-0.5, 0.5));
+ points.push_back(Vector2(-0.5, -0.5));
+ points.push_back(Vector2(0.5, -0.5));
+ points.push_back(Vector2(0.5, 0.5));
+ points.push_back(Vector2(-0.5, 0.5));
+ } else if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC) {
+ points.push_back(Vector2(0.0, -0.5));
+ points.push_back(Vector2(-0.5, 0.0));
+ points.push_back(Vector2(0.0, 0.5));
+ points.push_back(Vector2(0.5, 0.0));
} else {
float overlap = 0.0;
switch (tile_shape) {
- case TileSet::TILE_SHAPE_ISOMETRIC:
- overlap = 0.5;
- break;
case TileSet::TILE_SHAPE_HEXAGON:
overlap = 0.25;
break;
@@ -1459,12 +1460,13 @@ Vector<Vector2> TileSet::get_tile_shape_polygon() {
break;
}
- points.append(Vector2(0.0, -0.5));
- points.append(Vector2(-0.5, overlap - 0.5));
- points.append(Vector2(-0.5, 0.5 - overlap));
- points.append(Vector2(0.0, 0.5));
- points.append(Vector2(0.5, 0.5 - overlap));
- points.append(Vector2(0.5, overlap - 0.5));
+ points.push_back(Vector2(0.0, -0.5));
+ points.push_back(Vector2(-0.5, overlap - 0.5));
+ points.push_back(Vector2(-0.5, 0.5 - overlap));
+ points.push_back(Vector2(0.0, 0.5));
+ points.push_back(Vector2(0.5, 0.5 - overlap));
+ points.push_back(Vector2(0.5, overlap - 0.5));
+
if (get_tile_offset_axis() == TileSet::TILE_OFFSET_AXIS_VERTICAL) {
for (int i = 0; i < points.size(); i++) {
points.write[i] = Vector2(points[i].y, points[i].x);
@@ -3789,7 +3791,7 @@ Vector2i TileSetAtlasSource::get_atlas_grid_size() const {
Size2i valid_area = txt->get_size() - margins;
// Compute the number of valid tiles in the tiles atlas
- Size2i grid_size = Size2i();
+ Size2i grid_size;
if (valid_area.x >= texture_region_size.x && valid_area.y >= texture_region_size.y) {
valid_area -= texture_region_size;
grid_size = Size2i(1, 1) + valid_area / (texture_region_size + separation);
@@ -3854,7 +3856,7 @@ bool TileSetAtlasSource::_set(const StringName &p_name, const Variant &p_value)
tiles[coords].alternatives[alternative_id] = memnew(TileData);
tiles[coords].alternatives[alternative_id]->set_tile_set(tile_set);
tiles[coords].alternatives[alternative_id]->set_allow_transform(alternative_id > 0);
- tiles[coords].alternatives_ids.append(alternative_id);
+ tiles[coords].alternatives_ids.push_back(alternative_id);
}
if (components.size() >= 3) {
bool valid;
@@ -4028,11 +4030,11 @@ void TileSetAtlasSource::create_tile(const Vector2i p_atlas_coords, const Vector
tad.alternatives[0]->set_allow_transform(false);
tad.alternatives[0]->connect("changed", callable_mp((Resource *)this, &TileSetAtlasSource::emit_changed));
tad.alternatives[0]->notify_property_list_changed();
- tad.alternatives_ids.append(0);
+ tad.alternatives_ids.push_back(0);
// Create and resize the tile.
tiles.insert(p_atlas_coords, tad);
- tiles_ids.append(p_atlas_coords);
+ tiles_ids.push_back(p_atlas_coords);
tiles_ids.sort();
_create_coords_mapping_cache(p_atlas_coords);
@@ -4343,7 +4345,7 @@ void TileSetAtlasSource::move_tile_in_atlas(Vector2i p_atlas_coords, Vector2i p_
tiles.erase(p_atlas_coords);
tiles_ids.erase(p_atlas_coords);
- tiles_ids.append(new_atlas_coords);
+ tiles_ids.push_back(new_atlas_coords);
tiles_ids.sort();
}
tiles[new_atlas_coords].size_in_atlas = new_size;
@@ -4363,8 +4365,9 @@ int TileSetAtlasSource::create_alternative_tile(const Vector2i p_atlas_coords, i
tiles[p_atlas_coords].alternatives[new_alternative_id] = memnew(TileData);
tiles[p_atlas_coords].alternatives[new_alternative_id]->set_tile_set(tile_set);
tiles[p_atlas_coords].alternatives[new_alternative_id]->set_allow_transform(true);
+ tiles[p_atlas_coords].alternatives[new_alternative_id]->connect("changed", callable_mp((Resource *)this, &TileSetAtlasSource::emit_changed));
tiles[p_atlas_coords].alternatives[new_alternative_id]->notify_property_list_changed();
- tiles[p_atlas_coords].alternatives_ids.append(new_alternative_id);
+ tiles[p_atlas_coords].alternatives_ids.push_back(new_alternative_id);
tiles[p_atlas_coords].alternatives_ids.sort();
_compute_next_alternative_id(p_atlas_coords);
@@ -4394,7 +4397,7 @@ void TileSetAtlasSource::set_alternative_tile_id(const Vector2i p_atlas_coords,
ERR_FAIL_COND_MSG(tiles[p_atlas_coords].alternatives.has(p_new_id), vformat("TileSetAtlasSource has already an alternative with id %d at %s.", p_new_id, String(p_atlas_coords)));
tiles[p_atlas_coords].alternatives[p_new_id] = tiles[p_atlas_coords].alternatives[p_alternative_tile];
- tiles[p_atlas_coords].alternatives_ids.append(p_new_id);
+ tiles[p_atlas_coords].alternatives_ids.push_back(p_new_id);
tiles[p_atlas_coords].alternatives.erase(p_alternative_tile);
tiles[p_atlas_coords].alternatives_ids.erase(p_alternative_tile);
@@ -4682,7 +4685,7 @@ int TileSetScenesCollectionSource::create_scene_tile(Ref<PackedScene> p_packed_s
int new_scene_id = p_id_override >= 0 ? p_id_override : next_scene_id;
scenes[new_scene_id] = SceneData();
- scenes_ids.append(new_scene_id);
+ scenes_ids.push_back(new_scene_id);
scenes_ids.sort();
set_scene_tile_scene(new_scene_id, p_packed_scene);
_compute_next_alternative_id();
@@ -4699,7 +4702,7 @@ void TileSetScenesCollectionSource::set_scene_tile_id(int p_id, int p_new_id) {
scenes[p_new_id] = SceneData();
scenes[p_new_id] = scenes[p_id];
- scenes_ids.append(p_new_id);
+ scenes_ids.push_back(p_new_id);
scenes_ids.sort();
_compute_next_alternative_id();
diff --git a/scene/resources/tile_set.h b/scene/resources/tile_set.h
index 8f175e99a6..88bbbd157a 100644
--- a/scene/resources/tile_set.h
+++ b/scene/resources/tile_set.h
@@ -36,10 +36,10 @@
#include "core/templates/local_vector.h"
#include "core/templates/rb_set.h"
#include "scene/2d/light_occluder_2d.h"
-#include "scene/2d/navigation_region_2d.h"
#include "scene/main/canvas_item.h"
#include "scene/resources/concave_polygon_shape_2d.h"
#include "scene/resources/convex_polygon_shape_2d.h"
+#include "scene/resources/navigation_polygon.h"
#include "scene/resources/packed_scene.h"
#include "scene/resources/physics_material.h"
#include "scene/resources/shape_2d.h"
@@ -785,7 +785,7 @@ private:
bool flip_h = false;
bool flip_v = false;
bool transpose = false;
- Vector2i tex_offset = Vector2i();
+ Vector2i tex_offset;
Ref<Material> material = Ref<Material>();
Color modulate = Color(1.0, 1.0, 1.0, 1.0);
int z_index = 0;
diff --git a/scene/resources/visual_shader.cpp b/scene/resources/visual_shader.cpp
index b30ca3e721..6b8f8097a8 100644
--- a/scene/resources/visual_shader.cpp
+++ b/scene/resources/visual_shader.cpp
@@ -2066,10 +2066,9 @@ Error VisualShader::_write_node(Type type, StringBuilder *p_global_code, StringB
}
if (!node_code.is_empty()) {
- r_code += "\n";
+ r_code += "\n\n";
}
- r_code += "\n"; //
r_processed.insert(p_node);
return OK;
@@ -2366,71 +2365,62 @@ void VisualShader::_update_shader() const {
String global_compute_code;
if (shader_mode == Shader::MODE_PARTICLES) {
- bool has_start = !code_map[TYPE_START].is_empty();
bool has_start_custom = !code_map[TYPE_START_CUSTOM].is_empty();
bool has_process = !code_map[TYPE_PROCESS].is_empty();
bool has_process_custom = !code_map[TYPE_PROCESS_CUSTOM].is_empty();
bool has_collide = !code_map[TYPE_COLLIDE].is_empty();
shader_code += "void start() {\n";
- if (has_start || has_start_custom) {
- shader_code += " uint __seed = __hash(NUMBER + uint(1) + RANDOM_SEED);\n";
- shader_code += " vec3 __diff = TRANSFORM[3].xyz - EMISSION_TRANSFORM[3].xyz;\n";
- shader_code += " float __radians;\n";
- shader_code += " vec3 __vec3_buff1;\n";
- shader_code += " vec3 __vec3_buff2;\n";
- shader_code += " float __scalar_buff1;\n";
- shader_code += " float __scalar_buff2;\n";
- shader_code += " int __scalar_ibuff;\n";
- shader_code += " vec4 __vec4_buff;\n";
- shader_code += " vec3 __ndiff = normalize(__diff);\n\n";
- }
- if (has_start) {
- shader_code += " {\n";
- shader_code += code_map[TYPE_START].replace("\n ", "\n ");
- shader_code += " }\n";
- if (has_start_custom) {
- shader_code += " \n";
- }
- }
+ shader_code += " uint __seed = __hash(NUMBER + uint(1) + RANDOM_SEED);\n";
+ shader_code += "\n";
+ shader_code += " {\n";
+ shader_code += code_map[TYPE_START].replace("\n ", "\n ");
+ shader_code += " }\n";
if (has_start_custom) {
+ shader_code += " \n";
shader_code += " {\n";
shader_code += code_map[TYPE_START_CUSTOM].replace("\n ", "\n ");
shader_code += " }\n";
}
shader_code += "}\n\n";
- shader_code += "void process() {\n";
+
if (has_process || has_process_custom || has_collide) {
+ shader_code += "void process() {\n";
shader_code += " uint __seed = __hash(NUMBER + uint(1) + RANDOM_SEED);\n";
- shader_code += " vec3 __vec3_buff1;\n";
- shader_code += " vec3 __diff = TRANSFORM[3].xyz - EMISSION_TRANSFORM[3].xyz;\n";
- shader_code += " vec3 __ndiff = normalize(__diff);\n\n";
- }
- shader_code += " {\n";
- String tab = " ";
- if (has_collide) {
- shader_code += " if (COLLIDED) {\n\n";
- shader_code += code_map[TYPE_COLLIDE].replace("\n ", "\n ");
+ shader_code += "\n";
+ if (has_process || has_collide) {
+ shader_code += " {\n";
+ }
+ String tab = " ";
+ if (has_collide) {
+ shader_code += " if (COLLIDED) {\n\n";
+ shader_code += code_map[TYPE_COLLIDE].replace("\n ", "\n ");
+ if (has_process) {
+ shader_code += " } else {\n\n";
+ tab += " ";
+ }
+ }
if (has_process) {
- shader_code += " } else {\n\n";
- tab += " ";
+ shader_code += code_map[TYPE_PROCESS].replace("\n ", "\n " + tab);
+ }
+ if (has_collide) {
+ shader_code += " }\n";
+ }
+ if (has_process || has_collide) {
+ shader_code += " }\n";
}
- }
- if (has_process) {
- shader_code += code_map[TYPE_PROCESS].replace("\n ", "\n " + tab);
- }
- if (has_collide) {
- shader_code += " }\n";
- }
- shader_code += " }\n";
- if (has_process_custom) {
- shader_code += " {\n\n";
- shader_code += code_map[TYPE_PROCESS_CUSTOM].replace("\n ", "\n ");
- shader_code += " }\n";
- }
+ if (has_process_custom) {
+ if (has_process || has_collide) {
+ shader_code += " \n";
+ }
+ shader_code += " {\n";
+ shader_code += code_map[TYPE_PROCESS_CUSTOM].replace("\n ", "\n ");
+ shader_code += " }\n";
+ }
- shader_code += "}\n\n";
+ shader_code += "}\n\n";
+ }
global_compute_code += "float __rand_from_seed(inout uint seed) {\n";
global_compute_code += " int k;\n";
@@ -2658,6 +2648,7 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = {
{ 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_SCALAR_INT, "camera_visible_layers", "CAMERA_VISIBLE_LAYERS" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "node_position_view", "NODE_POSITION_VIEW" },
// Node3D, Fragment
@@ -2690,6 +2681,7 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = {
{ 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_SCALAR_INT, "camera_visible_layers", "CAMERA_VISIBLE_LAYERS" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "node_position_view", "NODE_POSITION_VIEW" },
// Node3D, Light
diff --git a/scene/resources/visual_shader_nodes.cpp b/scene/resources/visual_shader_nodes.cpp
index 04637983b5..03abac1b3e 100644
--- a/scene/resources/visual_shader_nodes.cpp
+++ b/scene/resources/visual_shader_nodes.cpp
@@ -3108,9 +3108,9 @@ void VisualShaderNodeUVFunc::set_function(VisualShaderNodeUVFunc::Function p_fun
return;
}
if (p_func == FUNC_PANNING) {
- set_input_port_default_value(2, Vector2()); // offset
+ set_input_port_default_value(2, Vector2(), get_input_port_default_value(2)); // offset
} else { // FUNC_SCALING
- set_input_port_default_value(2, Vector2(0.5, 0.5)); // pivot
+ set_input_port_default_value(2, Vector2(0.5, 0.5), get_input_port_default_value(2)); // pivot
}
func = p_func;
emit_changed();
diff --git a/scene/resources/visual_shader_particle_nodes.cpp b/scene/resources/visual_shader_particle_nodes.cpp
index f125b05a26..d61a343688 100644
--- a/scene/resources/visual_shader_particle_nodes.cpp
+++ b/scene/resources/visual_shader_particle_nodes.cpp
@@ -374,13 +374,13 @@ String VisualShaderNodeParticleMeshEmitter::_generate_code(VisualShader::Type p_
if (is_output_port_connected(p_index)) {
switch (p_port_type) {
case PORT_TYPE_VECTOR_2D: {
- code += vformat(" %s = texelFetch(%s, ivec2(__scalar_ibuff, 0), 0).xy;\n", p_output_vars[p_index], make_unique_id(p_type, p_id, p_texture_name));
+ code += vformat(" %s = texelFetch(%s, ivec2(__scalar_ibuff, 0), 0).xy;\n", p_output_vars[p_index], make_unique_id(p_type, p_id, p_texture_name));
} break;
case PORT_TYPE_VECTOR_3D: {
if (mode_2d) {
- code += vformat(" %s = texelFetch(%s, ivec2(__scalar_ibuff, 0), 0).xy;\n", p_output_vars[p_index], make_unique_id(p_type, p_id, p_texture_name));
+ code += vformat(" %s = texelFetch(%s, ivec2(__scalar_ibuff, 0), 0).xy;\n", p_output_vars[p_index], make_unique_id(p_type, p_id, p_texture_name));
} else {
- code += vformat(" %s = texelFetch(%s, ivec2(__scalar_ibuff, 0), 0).xyz;\n", p_output_vars[p_index], make_unique_id(p_type, p_id, p_texture_name));
+ code += vformat(" %s = texelFetch(%s, ivec2(__scalar_ibuff, 0), 0).xyz;\n", p_output_vars[p_index], make_unique_id(p_type, p_id, p_texture_name));
}
} break;
default:
@@ -392,25 +392,27 @@ String VisualShaderNodeParticleMeshEmitter::_generate_code(VisualShader::Type p_
String VisualShaderNodeParticleMeshEmitter::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) const {
String code;
- code += " __scalar_ibuff = int(__rand_from_seed(__seed) * 65535.0) % " + itos(position_texture->get_width()) + ";\n";
+ code += " {\n";
+ code += " int __scalar_ibuff = int(__rand_from_seed(__seed) * 65535.0) % " + itos(position_texture->get_width()) + ";\n";
code += _generate_code(p_type, p_id, p_output_vars, 0, "mesh_vx", VisualShaderNode::PORT_TYPE_VECTOR_3D);
code += _generate_code(p_type, p_id, p_output_vars, 1, "mesh_nm", VisualShaderNode::PORT_TYPE_VECTOR_3D);
if (is_output_port_connected(2) || is_output_port_connected(3)) {
- code += vformat(" __vec4_buff = texelFetch(%s, ivec2(__scalar_ibuff, 0), 0);\n", make_unique_id(p_type, p_id, "mesh_col"));
+ code += vformat(" vec4 __vec4_buff = texelFetch(%s, ivec2(__scalar_ibuff, 0), 0);\n", make_unique_id(p_type, p_id, "mesh_col"));
if (is_output_port_connected(2)) {
- code += " " + p_output_vars[2] + " = __vec4_buff.rgb;\n";
+ code += " " + p_output_vars[2] + " = __vec4_buff.rgb;\n";
}
if (is_output_port_connected(3)) {
- code += " " + p_output_vars[3] + " = __vec4_buff.a;\n";
+ code += " " + p_output_vars[3] + " = __vec4_buff.a;\n";
}
}
code += _generate_code(p_type, p_id, p_output_vars, 4, "mesh_uv", VisualShaderNode::PORT_TYPE_VECTOR_2D);
code += _generate_code(p_type, p_id, p_output_vars, 5, "mesh_uv2", VisualShaderNode::PORT_TYPE_VECTOR_2D);
+ code += " }\n";
return code;
}
@@ -737,6 +739,8 @@ VisualShaderNodeParticleMeshEmitter::VisualShaderNodeParticleMeshEmitter() {
color_texture.instantiate();
uv_texture.instantiate();
uv2_texture.instantiate();
+
+ simple_decl = false;
}
// VisualShaderNodeParticleMultiplyByAxisAngle
@@ -879,22 +883,26 @@ bool VisualShaderNodeParticleConeVelocity::has_output_port_preview(int p_port) c
String VisualShaderNodeParticleConeVelocity::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) const {
String code;
- code += " __radians = radians(" + (p_input_vars[1].is_empty() ? (String)get_input_port_default_value(1) : p_input_vars[1]) + ");\n";
- code += " __scalar_buff1 = __rand_from_seed_m1_p1(__seed) * __radians;\n";
- code += " __scalar_buff2 = __rand_from_seed_m1_p1(__seed) * __radians;\n";
- code += " __vec3_buff1 = " + (p_input_vars[0].is_empty() ? "vec3" + (String)get_input_port_default_value(0) : p_input_vars[0]) + ";\n";
- code += " __scalar_buff1 += __vec3_buff1.z != 0.0 ? atan(__vec3_buff1.x, __vec3_buff1.z) : sign(__vec3_buff1.x) * (PI / 2.0);\n";
- code += " __scalar_buff2 += __vec3_buff1.z != 0.0 ? atan(__vec3_buff1.y, abs(__vec3_buff1.z)) : (__vec3_buff1.x != 0.0 ? atan(__vec3_buff1.y, abs(__vec3_buff1.x)) : sign(__vec3_buff1.y) * (PI / 2.0));\n";
- code += " __vec3_buff1 = vec3(sin(__scalar_buff1), 0.0, cos(__scalar_buff1));\n";
- code += " __vec3_buff2 = vec3(0.0, sin(__scalar_buff2), cos(__scalar_buff2));\n";
- code += " __vec3_buff2.z = __vec3_buff2.z / max(0.0001, sqrt(abs(__vec3_buff2.z)));\n";
- code += " " + p_output_vars[0] + " = normalize(vec3(__vec3_buff1.x * __vec3_buff2.z, __vec3_buff2.y, __vec3_buff1.z * __vec3_buff2.z));\n";
+ code += " {\n";
+ code += " float __radians = radians(" + (p_input_vars[1].is_empty() ? (String)get_input_port_default_value(1) : p_input_vars[1]) + ");\n";
+ code += " float __scalar_buff1 = __rand_from_seed_m1_p1(__seed) * __radians;\n";
+ code += " float __scalar_buff2 = __rand_from_seed_m1_p1(__seed) * __radians;\n";
+ code += " vec3 __vec3_buff1 = " + (p_input_vars[0].is_empty() ? "vec3" + (String)get_input_port_default_value(0) : p_input_vars[0]) + ";\n";
+ code += " __scalar_buff1 += __vec3_buff1.z != 0.0 ? atan(__vec3_buff1.x, __vec3_buff1.z) : sign(__vec3_buff1.x) * (PI / 2.0);\n";
+ code += " __scalar_buff2 += __vec3_buff1.z != 0.0 ? atan(__vec3_buff1.y, abs(__vec3_buff1.z)) : (__vec3_buff1.x != 0.0 ? atan(__vec3_buff1.y, abs(__vec3_buff1.x)) : sign(__vec3_buff1.y) * (PI / 2.0));\n";
+ code += " __vec3_buff1 = vec3(sin(__scalar_buff1), 0.0, cos(__scalar_buff1));\n";
+ code += " vec3 __vec3_buff2 = vec3(0.0, sin(__scalar_buff2), cos(__scalar_buff2));\n";
+ code += " __vec3_buff2.z = __vec3_buff2.z / max(0.0001, sqrt(abs(__vec3_buff2.z)));\n";
+ code += " " + p_output_vars[0] + " = normalize(vec3(__vec3_buff1.x * __vec3_buff2.z, __vec3_buff2.y, __vec3_buff1.z * __vec3_buff2.z));\n";
+ code += " }\n";
return code;
}
VisualShaderNodeParticleConeVelocity::VisualShaderNodeParticleConeVelocity() {
set_input_port_default_value(0, Vector3(1, 0, 0));
set_input_port_default_value(1, 45.0);
+
+ simple_decl = false;
}
// VisualShaderNodeParticleRandomness
@@ -1086,21 +1094,26 @@ String VisualShaderNodeParticleAccelerator::get_input_port_name(int p_port) cons
String VisualShaderNodeParticleAccelerator::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) const {
String code;
+ code += " {\n";
switch (mode) {
case MODE_LINEAR:
- code += " " + p_output_vars[0] + " = length(VELOCITY) > 0.0 ? " + "normalize(VELOCITY) * " + (p_input_vars[0].is_empty() ? "vec3" + (String)get_input_port_default_value(0) : p_input_vars[0]) + " * mix(1.0, __rand_from_seed(__seed), " + (p_input_vars[1].is_empty() ? (String)get_input_port_default_value(1) : p_input_vars[1]) + ") : vec3(0.0);\n";
+ code += " " + p_output_vars[0] + " = length(VELOCITY) > 0.0 ? " + "normalize(VELOCITY) * " + (p_input_vars[0].is_empty() ? "vec3" + (String)get_input_port_default_value(0) : p_input_vars[0]) + " * mix(1.0, __rand_from_seed(__seed), " + (p_input_vars[1].is_empty() ? (String)get_input_port_default_value(1) : p_input_vars[1]) + ") : vec3(0.0);\n";
break;
case MODE_RADIAL:
- code += " " + p_output_vars[0] + " = length(__diff) > 0.0 ? __ndiff * " + (p_input_vars[0].is_empty() ? "vec3" + (String)get_input_port_default_value(0) : p_input_vars[0]) + " * mix(1.0, __rand_from_seed(__seed), " + (p_input_vars[1].is_empty() ? (String)get_input_port_default_value(1) : p_input_vars[1]) + ") : vec3(0.0);\n";
+ code += " vec3 __diff = TRANSFORM[3].xyz - EMISSION_TRANSFORM[3].xyz;\n";
+ code += " vec3 __ndiff = normalize(__diff);\n\n";
+ code += " " + p_output_vars[0] + " = length(__diff) > 0.0 ? __ndiff * " + (p_input_vars[0].is_empty() ? "vec3" + (String)get_input_port_default_value(0) : p_input_vars[0]) + " * mix(1.0, __rand_from_seed(__seed), " + (p_input_vars[1].is_empty() ? (String)get_input_port_default_value(1) : p_input_vars[1]) + ") : vec3(0.0);\n";
break;
case MODE_TANGENTIAL:
- code += " __vec3_buff1 = cross(__ndiff, normalize(" + (p_input_vars[2].is_empty() ? "vec3" + (String)get_input_port_default_value(2) : p_input_vars[2]) + "));\n";
- code += " " + p_output_vars[0] + " = length(__vec3_buff1) > 0.0 ? normalize(__vec3_buff1) * (" + (p_input_vars[0].is_empty() ? "vec3" + (String)get_input_port_default_value(0) : p_input_vars[0]) + " * mix(1.0, __rand_from_seed(__seed), " + (p_input_vars[1].is_empty() ? (String)get_input_port_default_value(1) : p_input_vars[1]) + ")) : vec3(0.0);\n";
+ code += " vec3 __diff = TRANSFORM[3].xyz - EMISSION_TRANSFORM[3].xyz;\n";
+ code += " vec3 __ndiff = normalize(__diff);\n\n";
+ code += " vec3 __vec3_buff1 = cross(__ndiff, normalize(" + (p_input_vars[2].is_empty() ? "vec3" + (String)get_input_port_default_value(2) : p_input_vars[2]) + "));\n";
+ code += " " + p_output_vars[0] + " = length(__vec3_buff1) > 0.0 ? normalize(__vec3_buff1) * (" + (p_input_vars[0].is_empty() ? "vec3" + (String)get_input_port_default_value(0) : p_input_vars[0]) + " * mix(1.0, __rand_from_seed(__seed), " + (p_input_vars[1].is_empty() ? (String)get_input_port_default_value(1) : p_input_vars[1]) + ")) : vec3(0.0);\n";
break;
default:
break;
}
-
+ code += " }\n";
return code;
}
@@ -1125,6 +1138,8 @@ VisualShaderNodeParticleAccelerator::VisualShaderNodeParticleAccelerator() {
set_input_port_default_value(0, Vector3(1, 1, 1));
set_input_port_default_value(1, 0.0);
set_input_port_default_value(2, Vector3(0, -9.8, 0));
+
+ simple_decl = false;
}
// VisualShaderNodeParticleOutput
diff --git a/scene/scene_string_names.cpp b/scene/scene_string_names.cpp
index a15c03d675..bc7918c662 100644
--- a/scene/scene_string_names.cpp
+++ b/scene/scene_string_names.cpp
@@ -206,8 +206,6 @@ SceneStringNames::SceneStringNames() {
theme_changed = StaticCString::create("theme_changed");
parameters_base_path = "parameters/";
- tracks_changed = "tracks_changed";
-
shader_overrides_group = StaticCString::create("_shader_overrides_group_");
shader_overrides_group_active = StaticCString::create("_shader_overrides_group_active_");
diff --git a/scene/scene_string_names.h b/scene/scene_string_names.h
index 5589ab327f..7ff866cacd 100644
--- a/scene/scene_string_names.h
+++ b/scene/scene_string_names.h
@@ -209,8 +209,6 @@ public:
StringName parameters_base_path;
- StringName tracks_changed;
-
StringName _window_group;
StringName _window_input;
StringName _window_unhandled_input;
diff --git a/scene/theme/theme_db.cpp b/scene/theme/theme_db.cpp
index 1025d40b05..ae64313741 100644
--- a/scene/theme/theme_db.cpp
+++ b/scene/theme/theme_db.cpp
@@ -49,7 +49,7 @@ void ThemeDB::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", 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,*.otf,*.ttf,*.woff,*.woff2,*.fnt,*.font,*.pfb,*.pfm", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED));
TextServer::FontAntialiasing font_antialiasing = (TextServer::FontAntialiasing)(int)GLOBAL_DEF_RST("gui/theme/default_font_antialiasing", 1);
ProjectSettings::get_singleton()->set_custom_property_info("gui/theme/default_font_antialiasing", PropertyInfo(Variant::INT, "gui/theme/default_font_antialiasing", PROPERTY_HINT_ENUM, "None,Grayscale,LCD Subpixel", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED));
@@ -70,7 +70,9 @@ void ThemeDB::initialize_theme() {
Ref<Font> font;
if (!font_path.is_empty()) {
font = ResourceLoader::load(font_path);
- if (!font.is_valid()) {
+ if (font.is_valid()) {
+ set_fallback_font(font);
+ } else {
ERR_PRINT("Error loading custom font '" + font_path + "'");
}
}
@@ -84,9 +86,6 @@ void ThemeDB::initialize_theme() {
Ref<Theme> theme = ResourceLoader::load(theme_path);
if (theme.is_valid()) {
set_project_theme(theme);
- if (font.is_valid()) {
- set_fallback_font(font);
- }
} else {
ERR_PRINT("Error loading custom theme '" + theme_path + "'");
}
diff --git a/scene/theme/theme_owner.cpp b/scene/theme/theme_owner.cpp
index e89aa1b28d..44e0c5d0c8 100644
--- a/scene/theme/theme_owner.cpp
+++ b/scene/theme/theme_owner.cpp
@@ -205,16 +205,7 @@ Variant ThemeOwner::get_theme_item_in_types(Theme::DataType p_data_type, const S
while (owner_node) {
// 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) {
- Ref<Theme> owner_theme;
-
- Control *owner_c = Object::cast_to<Control>(owner_node);
- if (owner_c) {
- owner_theme = owner_c->get_theme();
- }
- Window *owner_w = Object::cast_to<Window>(owner_node);
- if (owner_w) {
- owner_theme = owner_w->get_theme();
- }
+ Ref<Theme> owner_theme = _get_owner_node_theme(owner_node);
if (owner_theme.is_valid() && owner_theme->has_theme_item(p_data_type, p_name, E)) {
return owner_theme->get_theme_item(p_data_type, p_name, E);
@@ -254,16 +245,7 @@ bool ThemeOwner::has_theme_item_in_types(Theme::DataType p_data_type, const Stri
while (owner_node) {
// 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) {
- Ref<Theme> owner_theme;
-
- Control *owner_c = Object::cast_to<Control>(owner_node);
- if (owner_c) {
- owner_theme = owner_c->get_theme();
- }
- Window *owner_w = Object::cast_to<Window>(owner_node);
- if (owner_w) {
- owner_theme = owner_w->get_theme();
- }
+ Ref<Theme> owner_theme = _get_owner_node_theme(owner_node);
if (owner_theme.is_valid() && owner_theme->has_theme_item(p_data_type, p_name, E)) {
return true;
@@ -299,16 +281,7 @@ float ThemeOwner::get_theme_default_base_scale() {
Node *owner_node = get_owner_node();
while (owner_node) {
- Ref<Theme> owner_theme;
-
- Control *owner_c = Object::cast_to<Control>(owner_node);
- if (owner_c) {
- owner_theme = owner_c->get_theme();
- }
- Window *owner_w = Object::cast_to<Window>(owner_node);
- if (owner_w) {
- owner_theme = owner_w->get_theme();
- }
+ Ref<Theme> owner_theme = _get_owner_node_theme(owner_node);
if (owner_theme.is_valid() && owner_theme->has_default_base_scale()) {
return owner_theme->get_default_base_scale();
@@ -338,16 +311,7 @@ Ref<Font> ThemeOwner::get_theme_default_font() {
Node *owner_node = get_owner_node();
while (owner_node) {
- Ref<Theme> owner_theme;
-
- Control *owner_c = Object::cast_to<Control>(owner_node);
- if (owner_c) {
- owner_theme = owner_c->get_theme();
- }
- Window *owner_w = Object::cast_to<Window>(owner_node);
- if (owner_w) {
- owner_theme = owner_w->get_theme();
- }
+ Ref<Theme> owner_theme = _get_owner_node_theme(owner_node);
if (owner_theme.is_valid() && owner_theme->has_default_font()) {
return owner_theme->get_default_font();
@@ -377,16 +341,7 @@ int ThemeOwner::get_theme_default_font_size() {
Node *owner_node = get_owner_node();
while (owner_node) {
- Ref<Theme> owner_theme;
-
- Control *owner_c = Object::cast_to<Control>(owner_node);
- if (owner_c) {
- owner_theme = owner_c->get_theme();
- }
- Window *owner_w = Object::cast_to<Window>(owner_node);
- if (owner_w) {
- owner_theme = owner_w->get_theme();
- }
+ Ref<Theme> owner_theme = _get_owner_node_theme(owner_node);
if (owner_theme.is_valid() && owner_theme->has_default_font_size()) {
return owner_theme->get_default_font_size();
@@ -408,3 +363,17 @@ int ThemeOwner::get_theme_default_font_size() {
}
return ThemeDB::get_singleton()->get_fallback_font_size();
}
+
+Ref<Theme> ThemeOwner::_get_owner_node_theme(Node *p_owner_node) const {
+ const Control *owner_c = Object::cast_to<Control>(p_owner_node);
+ if (owner_c) {
+ return owner_c->get_theme();
+ }
+
+ const Window *owner_w = Object::cast_to<Window>(p_owner_node);
+ if (owner_w) {
+ return owner_w->get_theme();
+ }
+
+ return Ref<Theme>();
+}
diff --git a/scene/theme/theme_owner.h b/scene/theme/theme_owner.h
index 59b72c1627..60d60f525c 100644
--- a/scene/theme/theme_owner.h
+++ b/scene/theme/theme_owner.h
@@ -43,6 +43,7 @@ class ThemeOwner : public Object {
Window *owner_window = nullptr;
Node *_get_next_owner_node(Node *p_from_node) const;
+ Ref<Theme> _get_owner_node_theme(Node *p_owner_node) const;
public:
// Theme owner node.
diff --git a/servers/audio/audio_effect.cpp b/servers/audio/audio_effect.cpp
index ef0e3197e1..870a77806b 100644
--- a/servers/audio/audio_effect.cpp
+++ b/servers/audio/audio_effect.cpp
@@ -31,9 +31,7 @@
#include "audio_effect.h"
void AudioEffectInstance::process(const AudioFrame *p_src_frames, AudioFrame *p_dst_frames, int p_frame_count) {
- if (GDVIRTUAL_REQUIRED_CALL(_process, p_src_frames, p_dst_frames, p_frame_count)) {
- return;
- }
+ GDVIRTUAL_REQUIRED_CALL(_process, p_src_frames, p_dst_frames, p_frame_count);
}
bool AudioEffectInstance::process_silence() const {
bool ret = false;
@@ -50,10 +48,8 @@ void AudioEffectInstance::_bind_methods() {
Ref<AudioEffectInstance> AudioEffect::instantiate() {
Ref<AudioEffectInstance> ret;
- if (GDVIRTUAL_REQUIRED_CALL(_instantiate, ret)) {
- return ret;
- }
- return Ref<AudioEffectInstance>();
+ GDVIRTUAL_REQUIRED_CALL(_instantiate, ret);
+ return ret;
}
void AudioEffect::_bind_methods() {
GDVIRTUAL_BIND(_instantiate);
diff --git a/servers/audio/audio_effect.h b/servers/audio/audio_effect.h
index 653d04595e..93f10c156a 100644
--- a/servers/audio/audio_effect.h
+++ b/servers/audio/audio_effect.h
@@ -41,7 +41,7 @@ class AudioEffectInstance : public RefCounted {
GDCLASS(AudioEffectInstance, RefCounted);
protected:
- GDVIRTUAL3(_process, GDNativeConstPtr<AudioFrame>, GDNativePtr<AudioFrame>, int)
+ GDVIRTUAL3(_process, GDExtensionConstPtr<AudioFrame>, GDExtensionPtr<AudioFrame>, int)
GDVIRTUAL0RC(bool, _process_silence)
static void _bind_methods();
diff --git a/servers/audio/audio_stream.cpp b/servers/audio/audio_stream.cpp
index 33d4c816f2..84c21f7cd6 100644
--- a/servers/audio/audio_stream.cpp
+++ b/servers/audio/audio_stream.cpp
@@ -71,12 +71,9 @@ void AudioStreamPlayback::seek(double p_time) {
}
int AudioStreamPlayback::mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) {
- int ret;
- if (GDVIRTUAL_REQUIRED_CALL(_mix, p_buffer, p_rate_scale, p_frames, ret)) {
- return ret;
- }
-
- return 0;
+ int ret = 0;
+ GDVIRTUAL_REQUIRED_CALL(_mix, p_buffer, p_rate_scale, p_frames, ret);
+ return ret;
}
void AudioStreamPlayback::tag_used_streams() {
@@ -107,20 +104,14 @@ void AudioStreamPlaybackResampled::begin_resample() {
}
int AudioStreamPlaybackResampled::_mix_internal(AudioFrame *p_buffer, int p_frames) {
- int ret;
- if (GDVIRTUAL_REQUIRED_CALL(_mix_resampled, p_buffer, p_frames, ret)) {
- return ret;
- }
-
- return 0;
+ int ret = 0;
+ GDVIRTUAL_REQUIRED_CALL(_mix_resampled, p_buffer, p_frames, ret);
+ return ret;
}
float AudioStreamPlaybackResampled::get_stream_sampling_rate() {
- float ret;
- if (GDVIRTUAL_REQUIRED_CALL(_get_stream_sampling_rate, ret)) {
- return ret;
- }
-
- return 0;
+ float ret = 0;
+ GDVIRTUAL_REQUIRED_CALL(_get_stream_sampling_rate, ret);
+ return ret;
}
void AudioStreamPlaybackResampled::_bind_methods() {
@@ -419,12 +410,12 @@ AudioStreamPlaybackMicrophone::AudioStreamPlaybackMicrophone() {
////////////////////////////////
-void AudioStreamRandomizer::add_stream(int p_index) {
+void AudioStreamRandomizer::add_stream(int p_index, Ref<AudioStream> p_stream, float p_weight) {
if (p_index < 0) {
p_index = audio_stream_pool.size();
}
ERR_FAIL_COND(p_index > audio_stream_pool.size());
- PoolEntry entry{ nullptr, 1.0f };
+ PoolEntry entry{ p_stream, p_weight };
audio_stream_pool.insert(p_index, entry);
emit_signal(SNAME("changed"));
notify_property_list_changed();
@@ -564,8 +555,9 @@ Ref<AudioStreamPlayback> AudioStreamRandomizer::instance_playback_no_repeats() {
}
}
if (local_pool.is_empty()) {
+ // There is only one sound to choose from.
+ // Always play a random sound while allowing repeats (which always plays the same sound).
playback = instance_playback_random();
- WARN_PRINT("Playback stream pool is too small to prevent repeats.");
return playback;
}
@@ -717,7 +709,7 @@ void AudioStreamRandomizer::_get_property_list(List<PropertyInfo> *p_list) const
}
void AudioStreamRandomizer::_bind_methods() {
- ClassDB::bind_method(D_METHOD("add_stream", "index"), &AudioStreamRandomizer::add_stream);
+ ClassDB::bind_method(D_METHOD("add_stream", "index", "stream", "weight"), &AudioStreamRandomizer::add_stream, DEFVAL(1.0));
ClassDB::bind_method(D_METHOD("move_stream", "index_from", "index_to"), &AudioStreamRandomizer::move_stream);
ClassDB::bind_method(D_METHOD("remove_stream", "index"), &AudioStreamRandomizer::remove_stream);
diff --git a/servers/audio/audio_stream.h b/servers/audio/audio_stream.h
index c41475010c..0d3f7bca04 100644
--- a/servers/audio/audio_stream.h
+++ b/servers/audio/audio_stream.h
@@ -53,7 +53,7 @@ protected:
GDVIRTUAL0RC(int, _get_loop_count)
GDVIRTUAL0RC(double, _get_playback_position)
GDVIRTUAL1(_seek, double)
- GDVIRTUAL3R(int, _mix, GDNativePtr<AudioFrame>, float, int)
+ GDVIRTUAL3R(int, _mix, GDExtensionPtr<AudioFrame>, float, int)
GDVIRTUAL0(_tag_used_streams)
public:
virtual void start(double p_from_pos = 0.0);
@@ -91,7 +91,7 @@ protected:
virtual int _mix_internal(AudioFrame *p_buffer, int p_frames);
virtual float get_stream_sampling_rate();
- GDVIRTUAL2R(int, _mix_resampled, GDNativePtr<AudioFrame>, int)
+ GDVIRTUAL2R(int, _mix_resampled, GDExtensionPtr<AudioFrame>, int)
GDVIRTUAL0RC(float, _get_stream_sampling_rate)
static void _bind_methods();
@@ -241,7 +241,7 @@ protected:
void _get_property_list(List<PropertyInfo> *p_list) const;
public:
- void add_stream(int p_index);
+ void add_stream(int p_index, Ref<AudioStream> p_stream, float p_weight = 1.0);
void move_stream(int p_index_from, int p_index_to);
void remove_stream(int p_index);
diff --git a/servers/audio/effects/audio_effect_distortion.cpp b/servers/audio/effects/audio_effect_distortion.cpp
index 95156d8d66..25ca0cfdfe 100644
--- a/servers/audio/effects/audio_effect_distortion.cpp
+++ b/servers/audio/effects/audio_effect_distortion.cpp
@@ -160,10 +160,10 @@ void AudioEffectDistortion::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_post_gain"), &AudioEffectDistortion::get_post_gain);
ADD_PROPERTY(PropertyInfo(Variant::INT, "mode", PROPERTY_HINT_ENUM, "Clip,ATan,LoFi,Overdrive,Wave Shape"), "set_mode", "get_mode");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "pre_gain", PROPERTY_HINT_RANGE, "-60,60,0.01"), "set_pre_gain", "get_pre_gain");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "pre_gain", PROPERTY_HINT_RANGE, "-60,60,0.01,suffix:dB"), "set_pre_gain", "get_pre_gain");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "keep_hf_hz", PROPERTY_HINT_RANGE, "1,20500,1,suffix:Hz"), "set_keep_hf_hz", "get_keep_hf_hz");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "drive", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_drive", "get_drive");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "post_gain", PROPERTY_HINT_RANGE, "-80,24,0.01"), "set_post_gain", "get_post_gain");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "post_gain", PROPERTY_HINT_RANGE, "-80,24,0.01,suffix:dB"), "set_post_gain", "get_post_gain");
BIND_ENUM_CONSTANT(MODE_CLIP);
BIND_ENUM_CONSTANT(MODE_ATAN);
diff --git a/servers/audio_server.cpp b/servers/audio_server.cpp
index e657570f9b..c7d626c159 100644
--- a/servers/audio_server.cpp
+++ b/servers/audio_server.cpp
@@ -449,12 +449,8 @@ void AudioServer::_mix_step() {
case AudioStreamPlaybackListNode::AWAITING_DELETION:
case AudioStreamPlaybackListNode::FADE_OUT_TO_DELETION:
playback_list.erase(playback, [](AudioStreamPlaybackListNode *p) {
- if (p->prev_bus_details) {
- delete p->prev_bus_details;
- }
- if (p->bus_details) {
- delete p->bus_details;
- }
+ delete p->prev_bus_details;
+ delete p->bus_details;
p->stream_playback.unref();
delete p;
});
diff --git a/servers/display_server.cpp b/servers/display_server.cpp
index 52d7f66203..523cc714f0 100644
--- a/servers/display_server.cpp
+++ b/servers/display_server.cpp
@@ -367,8 +367,7 @@ float DisplayServer::screen_get_scale(int p_screen) const {
return 1.0f;
};
-bool DisplayServer::screen_is_touchscreen(int p_screen) const {
- //return false;
+bool DisplayServer::is_touchscreen_available() const {
return Input::get_singleton() && Input::get_singleton()->is_emulating_touch_from_mouse();
}
@@ -618,7 +617,7 @@ void DisplayServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("screen_get_usable_rect", "screen"), &DisplayServer::screen_get_usable_rect, DEFVAL(SCREEN_OF_MAIN_WINDOW));
ClassDB::bind_method(D_METHOD("screen_get_dpi", "screen"), &DisplayServer::screen_get_dpi, DEFVAL(SCREEN_OF_MAIN_WINDOW));
ClassDB::bind_method(D_METHOD("screen_get_scale", "screen"), &DisplayServer::screen_get_scale, DEFVAL(SCREEN_OF_MAIN_WINDOW));
- ClassDB::bind_method(D_METHOD("screen_is_touchscreen", "screen"), &DisplayServer::screen_is_touchscreen, DEFVAL(SCREEN_OF_MAIN_WINDOW));
+ ClassDB::bind_method(D_METHOD("is_touchscreen_available"), &DisplayServer::is_touchscreen_available, DEFVAL(SCREEN_OF_MAIN_WINDOW));
ClassDB::bind_method(D_METHOD("screen_get_max_scale"), &DisplayServer::screen_get_max_scale);
ClassDB::bind_method(D_METHOD("screen_get_refresh_rate", "screen"), &DisplayServer::screen_get_refresh_rate, DEFVAL(SCREEN_OF_MAIN_WINDOW));
@@ -643,6 +642,7 @@ void DisplayServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("window_set_current_screen", "screen", "window_id"), &DisplayServer::window_set_current_screen, DEFVAL(MAIN_WINDOW_ID));
ClassDB::bind_method(D_METHOD("window_get_position", "window_id"), &DisplayServer::window_get_position, DEFVAL(MAIN_WINDOW_ID));
+ ClassDB::bind_method(D_METHOD("window_get_position_with_decorations", "window_id"), &DisplayServer::window_get_position_with_decorations, DEFVAL(MAIN_WINDOW_ID));
ClassDB::bind_method(D_METHOD("window_set_position", "position", "window_id"), &DisplayServer::window_set_position, DEFVAL(MAIN_WINDOW_ID));
ClassDB::bind_method(D_METHOD("window_get_size", "window_id"), &DisplayServer::window_get_size, DEFVAL(MAIN_WINDOW_ID));
@@ -661,7 +661,7 @@ void DisplayServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("window_get_min_size", "window_id"), &DisplayServer::window_get_min_size, DEFVAL(MAIN_WINDOW_ID));
ClassDB::bind_method(D_METHOD("window_set_min_size", "min_size", "window_id"), &DisplayServer::window_set_min_size, DEFVAL(MAIN_WINDOW_ID));
- ClassDB::bind_method(D_METHOD("window_get_real_size", "window_id"), &DisplayServer::window_get_real_size, DEFVAL(MAIN_WINDOW_ID));
+ ClassDB::bind_method(D_METHOD("window_get_size_with_decorations", "window_id"), &DisplayServer::window_get_size_with_decorations, DEFVAL(MAIN_WINDOW_ID));
ClassDB::bind_method(D_METHOD("window_get_mode", "window_id"), &DisplayServer::window_get_mode, DEFVAL(MAIN_WINDOW_ID));
ClassDB::bind_method(D_METHOD("window_set_mode", "mode", "window_id"), &DisplayServer::window_set_mode, DEFVAL(MAIN_WINDOW_ID));
diff --git a/servers/display_server.h b/servers/display_server.h
index a796377f88..4c36b0acb9 100644
--- a/servers/display_server.h
+++ b/servers/display_server.h
@@ -262,7 +262,7 @@ public:
return scale;
}
virtual float screen_get_refresh_rate(int p_screen = SCREEN_OF_MAIN_WINDOW) const = 0;
- virtual bool screen_is_touchscreen(int p_screen = SCREEN_OF_MAIN_WINDOW) const;
+ virtual bool is_touchscreen_available() const;
// Keep the ScreenOrientation enum values in sync with the `display/window/handheld/orientation`
// project setting hint.
@@ -353,6 +353,7 @@ public:
virtual void window_set_current_screen(int p_screen, WindowID p_window = MAIN_WINDOW_ID) = 0;
virtual Point2i window_get_position(WindowID p_window = MAIN_WINDOW_ID) const = 0;
+ virtual Point2i window_get_position_with_decorations(WindowID p_window = MAIN_WINDOW_ID) const = 0;
virtual void window_set_position(const Point2i &p_position, WindowID p_window = MAIN_WINDOW_ID) = 0;
virtual void window_set_transient(WindowID p_window, WindowID p_parent) = 0;
@@ -366,7 +367,7 @@ public:
virtual void window_set_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID) = 0;
virtual Size2i window_get_size(WindowID p_window = MAIN_WINDOW_ID) const = 0;
- virtual Size2i window_get_real_size(WindowID p_window = MAIN_WINDOW_ID) const = 0; // FIXME: Find clearer name for this.
+ virtual Size2i window_get_size_with_decorations(WindowID p_window = MAIN_WINDOW_ID) const = 0;
virtual void window_set_mode(WindowMode p_mode, WindowID p_window = MAIN_WINDOW_ID) = 0;
virtual WindowMode window_get_mode(WindowID p_window = MAIN_WINDOW_ID) const = 0;
diff --git a/servers/display_server_headless.h b/servers/display_server_headless.h
index e1a27b6137..94b5f3c1e9 100644
--- a/servers/display_server_headless.h
+++ b/servers/display_server_headless.h
@@ -90,6 +90,7 @@ public:
void window_set_current_screen(int p_screen, WindowID p_window = MAIN_WINDOW_ID) override {}
Point2i window_get_position(WindowID p_window = MAIN_WINDOW_ID) const override { return Point2i(); }
+ Point2i window_get_position_with_decorations(WindowID p_window = MAIN_WINDOW_ID) const override { return Point2i(); }
void window_set_position(const Point2i &p_position, WindowID p_window = MAIN_WINDOW_ID) override {}
void window_set_transient(WindowID p_window, WindowID p_parent) override {}
@@ -102,7 +103,7 @@ public:
void window_set_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID) override {}
Size2i window_get_size(WindowID p_window = MAIN_WINDOW_ID) const override { return Size2i(); }
- Size2i window_get_real_size(WindowID p_window = MAIN_WINDOW_ID) const override { return Size2i(); }
+ Size2i window_get_size_with_decorations(WindowID p_window = MAIN_WINDOW_ID) const override { return Size2i(); }
void window_set_mode(WindowMode p_mode, WindowID p_window = MAIN_WINDOW_ID) override {}
WindowMode window_get_mode(WindowID p_window = MAIN_WINDOW_ID) const override { return WINDOW_MODE_MINIMIZED; }
diff --git a/servers/extensions/physics_server_2d_extension.h b/servers/extensions/physics_server_2d_extension.h
index 573b51ee12..7a7a3c5cba 100644
--- a/servers/extensions/physics_server_2d_extension.h
+++ b/servers/extensions/physics_server_2d_extension.h
@@ -126,12 +126,12 @@ protected:
static void _bind_methods();
bool is_body_excluded_from_query(const RID &p_body) const;
- GDVIRTUAL7R(bool, _intersect_ray, const Vector2 &, const Vector2 &, uint32_t, bool, bool, bool, GDNativePtr<PhysicsServer2DExtensionRayResult>)
- GDVIRTUAL7R(int, _intersect_point, const Vector2 &, ObjectID, uint32_t, bool, bool, GDNativePtr<PhysicsServer2DExtensionShapeResult>, int)
- GDVIRTUAL9R(int, _intersect_shape, RID, const Transform2D &, const Vector2 &, real_t, uint32_t, bool, bool, GDNativePtr<PhysicsServer2DExtensionShapeResult>, int)
- GDVIRTUAL9R(bool, _cast_motion, RID, const Transform2D &, const Vector2 &, real_t, uint32_t, bool, bool, GDNativePtr<real_t>, GDNativePtr<real_t>)
- GDVIRTUAL10R(bool, _collide_shape, RID, const Transform2D &, const Vector2 &, real_t, uint32_t, bool, bool, GDNativePtr<Vector2>, int, GDNativePtr<int>)
- GDVIRTUAL8R(bool, _rest_info, RID, const Transform2D &, const Vector2 &, real_t, uint32_t, bool, bool, GDNativePtr<PhysicsServer2DExtensionShapeRestInfo>)
+ GDVIRTUAL7R(bool, _intersect_ray, const Vector2 &, const Vector2 &, uint32_t, bool, bool, bool, GDExtensionPtr<PhysicsServer2DExtensionRayResult>)
+ GDVIRTUAL7R(int, _intersect_point, const Vector2 &, ObjectID, uint32_t, bool, bool, GDExtensionPtr<PhysicsServer2DExtensionShapeResult>, int)
+ GDVIRTUAL9R(int, _intersect_shape, RID, const Transform2D &, const Vector2 &, real_t, uint32_t, bool, bool, GDExtensionPtr<PhysicsServer2DExtensionShapeResult>, int)
+ GDVIRTUAL9R(bool, _cast_motion, RID, const Transform2D &, const Vector2 &, real_t, uint32_t, bool, bool, GDExtensionPtr<real_t>, GDExtensionPtr<real_t>)
+ GDVIRTUAL10R(bool, _collide_shape, RID, const Transform2D &, const Vector2 &, real_t, uint32_t, bool, bool, GDExtensionPtr<Vector2>, int, GDExtensionPtr<int>)
+ GDVIRTUAL8R(bool, _rest_info, RID, const Transform2D &, const Vector2 &, real_t, uint32_t, bool, bool, GDExtensionPtr<PhysicsServer2DExtensionShapeRestInfo>)
public:
virtual bool intersect_ray(const RayParameters &p_parameters, RayResult &r_result) override {
@@ -190,9 +190,9 @@ class PhysicsServer2DExtension : public PhysicsServer2D {
protected:
static void _bind_methods();
- GDVIRTUAL9R(bool, _shape_collide, RID, const Transform2D &, const Vector2 &, RID, const Transform2D &, const Vector2 &, GDNativePtr<Vector2>, int, GDNativePtr<int>)
+ GDVIRTUAL9R(bool, _shape_collide, RID, const Transform2D &, const Vector2 &, RID, const Transform2D &, const Vector2 &, GDExtensionPtr<Vector2>, int, GDExtensionPtr<int>)
- GDVIRTUAL8R(bool, _body_collide_shape, RID, int, RID, const Transform2D &, const Vector2 &, GDNativePtr<Vector2>, int, GDNativePtr<int>)
+ GDVIRTUAL8R(bool, _body_collide_shape, RID, int, RID, const Transform2D &, const Vector2 &, GDExtensionPtr<Vector2>, int, GDExtensionPtr<int>)
public:
// The warning is valid, but unavoidable. If the function is not overridden it will error anyway.
@@ -385,7 +385,7 @@ public:
EXBIND1R(PhysicsDirectBodyState2D *, body_get_direct_state, RID)
- GDVIRTUAL7RC(bool, _body_test_motion, RID, const Transform2D &, const Vector2 &, real_t, bool, bool, GDNativePtr<PhysicsServer2DExtensionMotionResult>)
+ GDVIRTUAL7RC(bool, _body_test_motion, RID, const Transform2D &, const Vector2 &, real_t, bool, bool, GDExtensionPtr<PhysicsServer2DExtensionMotionResult>)
thread_local static const HashSet<RID> *exclude_bodies;
thread_local static const HashSet<ObjectID> *exclude_objects;
diff --git a/servers/extensions/physics_server_3d_extension.cpp b/servers/extensions/physics_server_3d_extension.cpp
index 811ff231fc..4ed2bb49d4 100644
--- a/servers/extensions/physics_server_3d_extension.cpp
+++ b/servers/extensions/physics_server_3d_extension.cpp
@@ -400,6 +400,9 @@ void PhysicsServer3DExtension::_bind_methods() {
GDVIRTUAL_BIND(_joint_set_solver_priority, "joint", "priority");
GDVIRTUAL_BIND(_joint_get_solver_priority, "joint");
+ GDVIRTUAL_BIND(_joint_disable_collisions_between_bodies, "joint", "disable");
+ GDVIRTUAL_BIND(_joint_is_disabled_collisions_between_bodies, "joint");
+
GDVIRTUAL_BIND(_free_rid, "rid");
GDVIRTUAL_BIND(_set_active, "active");
diff --git a/servers/extensions/physics_server_3d_extension.h b/servers/extensions/physics_server_3d_extension.h
index 57f2a2d790..a85df0683c 100644
--- a/servers/extensions/physics_server_3d_extension.h
+++ b/servers/extensions/physics_server_3d_extension.h
@@ -128,12 +128,12 @@ protected:
static void _bind_methods();
bool is_body_excluded_from_query(const RID &p_body) const;
- GDVIRTUAL8R(bool, _intersect_ray, const Vector3 &, const Vector3 &, uint32_t, bool, bool, bool, bool, GDNativePtr<PhysicsServer3DExtensionRayResult>)
- GDVIRTUAL6R(int, _intersect_point, const Vector3 &, uint32_t, bool, bool, GDNativePtr<PhysicsServer3DExtensionShapeResult>, int)
- GDVIRTUAL9R(int, _intersect_shape, RID, const Transform3D &, const Vector3 &, real_t, uint32_t, bool, bool, GDNativePtr<PhysicsServer3DExtensionShapeResult>, int)
- GDVIRTUAL10R(bool, _cast_motion, RID, const Transform3D &, const Vector3 &, real_t, uint32_t, bool, bool, GDNativePtr<real_t>, GDNativePtr<real_t>, GDNativePtr<PhysicsServer3DExtensionShapeRestInfo>)
- GDVIRTUAL10R(bool, _collide_shape, RID, const Transform3D &, const Vector3 &, real_t, uint32_t, bool, bool, GDNativePtr<Vector3>, int, GDNativePtr<int>)
- GDVIRTUAL8R(bool, _rest_info, RID, const Transform3D &, const Vector3 &, real_t, uint32_t, bool, bool, GDNativePtr<PhysicsServer3DExtensionShapeRestInfo>)
+ GDVIRTUAL8R(bool, _intersect_ray, const Vector3 &, const Vector3 &, uint32_t, bool, bool, bool, bool, GDExtensionPtr<PhysicsServer3DExtensionRayResult>)
+ GDVIRTUAL6R(int, _intersect_point, const Vector3 &, uint32_t, bool, bool, GDExtensionPtr<PhysicsServer3DExtensionShapeResult>, int)
+ GDVIRTUAL9R(int, _intersect_shape, RID, const Transform3D &, const Vector3 &, real_t, uint32_t, bool, bool, GDExtensionPtr<PhysicsServer3DExtensionShapeResult>, int)
+ GDVIRTUAL10R(bool, _cast_motion, RID, const Transform3D &, const Vector3 &, real_t, uint32_t, bool, bool, GDExtensionPtr<real_t>, GDExtensionPtr<real_t>, GDExtensionPtr<PhysicsServer3DExtensionShapeRestInfo>)
+ GDVIRTUAL10R(bool, _collide_shape, RID, const Transform3D &, const Vector3 &, real_t, uint32_t, bool, bool, GDExtensionPtr<Vector3>, int, GDExtensionPtr<int>)
+ GDVIRTUAL8R(bool, _rest_info, RID, const Transform3D &, const Vector3 &, real_t, uint32_t, bool, bool, GDExtensionPtr<PhysicsServer3DExtensionShapeRestInfo>)
GDVIRTUAL2RC(Vector3, _get_closest_point_to_object_volume, RID, const Vector3 &)
public:
@@ -382,7 +382,7 @@ public:
EXBIND2(body_set_ray_pickable, RID, bool)
- GDVIRTUAL7RC(bool, _body_test_motion, RID, const Transform3D &, const Vector3 &, real_t, int, bool, GDNativePtr<PhysicsServer3DExtensionMotionResult>)
+ GDVIRTUAL7RC(bool, _body_test_motion, RID, const Transform3D &, const Vector3 &, real_t, int, bool, GDExtensionPtr<PhysicsServer3DExtensionMotionResult>)
thread_local static const HashSet<RID> *exclude_bodies;
thread_local static const HashSet<ObjectID> *exclude_objects;
diff --git a/servers/movie_writer/movie_writer.cpp b/servers/movie_writer/movie_writer.cpp
index 0edce4ced6..419943f2d2 100644
--- a/servers/movie_writer/movie_writer.cpp
+++ b/servers/movie_writer/movie_writer.cpp
@@ -52,34 +52,26 @@ MovieWriter *MovieWriter::find_writer_for_file(const String &p_file) {
}
uint32_t MovieWriter::get_audio_mix_rate() const {
- uint32_t ret = 0;
- if (GDVIRTUAL_REQUIRED_CALL(_get_audio_mix_rate, ret)) {
- return ret;
- }
- return 48000;
+ uint32_t ret = 48000;
+ GDVIRTUAL_REQUIRED_CALL(_get_audio_mix_rate, ret);
+ return ret;
}
AudioServer::SpeakerMode MovieWriter::get_audio_speaker_mode() const {
AudioServer::SpeakerMode ret = AudioServer::SPEAKER_MODE_STEREO;
- if (GDVIRTUAL_REQUIRED_CALL(_get_audio_speaker_mode, ret)) {
- return ret;
- }
- return AudioServer::SPEAKER_MODE_STEREO;
+ GDVIRTUAL_REQUIRED_CALL(_get_audio_speaker_mode, ret);
+ return ret;
}
Error MovieWriter::write_begin(const Size2i &p_movie_size, uint32_t p_fps, const String &p_base_path) {
- Error ret = OK;
- if (GDVIRTUAL_REQUIRED_CALL(_write_begin, p_movie_size, p_fps, p_base_path, ret)) {
- return ret;
- }
- return ERR_UNCONFIGURED;
+ Error ret = ERR_UNCONFIGURED;
+ GDVIRTUAL_REQUIRED_CALL(_write_begin, p_movie_size, p_fps, p_base_path, ret);
+ return ret;
}
Error MovieWriter::write_frame(const Ref<Image> &p_image, const int32_t *p_audio_data) {
- Error ret = OK;
- if (GDVIRTUAL_REQUIRED_CALL(_write_frame, p_image, p_audio_data, ret)) {
- return ret;
- }
- return ERR_UNCONFIGURED;
+ Error ret = ERR_UNCONFIGURED;
+ GDVIRTUAL_REQUIRED_CALL(_write_frame, p_image, p_audio_data, ret);
+ return ret;
}
void MovieWriter::write_end() {
@@ -88,18 +80,15 @@ void MovieWriter::write_end() {
bool MovieWriter::handles_file(const String &p_path) const {
bool ret = false;
- if (GDVIRTUAL_REQUIRED_CALL(_handles_file, p_path, ret)) {
- return ret;
- }
- return false;
+ GDVIRTUAL_REQUIRED_CALL(_handles_file, p_path, ret);
+ return ret;
}
void MovieWriter::get_supported_extensions(List<String> *r_extensions) const {
Vector<String> exts;
- if (GDVIRTUAL_REQUIRED_CALL(_get_supported_extensions, exts)) {
- for (int i = 0; i < exts.size(); i++) {
- r_extensions->push_back(exts[i]);
- }
+ GDVIRTUAL_REQUIRED_CALL(_get_supported_extensions, exts);
+ for (int i = 0; i < exts.size(); i++) {
+ r_extensions->push_back(exts[i]);
}
}
diff --git a/servers/movie_writer/movie_writer.h b/servers/movie_writer/movie_writer.h
index 7877a60715..fffc43459d 100644
--- a/servers/movie_writer/movie_writer.h
+++ b/servers/movie_writer/movie_writer.h
@@ -67,7 +67,7 @@ protected:
GDVIRTUAL0RC(Vector<String>, _get_supported_extensions)
GDVIRTUAL3R(Error, _write_begin, const Size2i &, uint32_t, const String &)
- GDVIRTUAL2R(Error, _write_frame, const Ref<Image> &, GDNativeConstPtr<int32_t>)
+ GDVIRTUAL2R(Error, _write_frame, const Ref<Image> &, GDExtensionConstPtr<int32_t>)
GDVIRTUAL0(_write_end)
static void _bind_methods();
diff --git a/servers/navigation/navigation_path_query_parameters_2d.cpp b/servers/navigation/navigation_path_query_parameters_2d.cpp
index 574af90be1..717ada3834 100644
--- a/servers/navigation/navigation_path_query_parameters_2d.cpp
+++ b/servers/navigation/navigation_path_query_parameters_2d.cpp
@@ -105,11 +105,19 @@ Vector2 NavigationPathQueryParameters2D::get_target_position() const {
void NavigationPathQueryParameters2D::set_navigation_layers(uint32_t p_navigation_layers) {
parameters.navigation_layers = p_navigation_layers;
-};
+}
uint32_t NavigationPathQueryParameters2D::get_navigation_layers() const {
return parameters.navigation_layers;
-};
+}
+
+void NavigationPathQueryParameters2D::set_metadata_flags(BitField<NavigationPathQueryParameters2D::PathMetadataFlags> p_flags) {
+ parameters.metadata_flags = (int64_t)p_flags;
+}
+
+BitField<NavigationPathQueryParameters2D::PathMetadataFlags> NavigationPathQueryParameters2D::get_metadata_flags() const {
+ return (int64_t)parameters.metadata_flags;
+}
void NavigationPathQueryParameters2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_pathfinding_algorithm", "pathfinding_algorithm"), &NavigationPathQueryParameters2D::set_pathfinding_algorithm);
@@ -130,15 +138,25 @@ void NavigationPathQueryParameters2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_navigation_layers", "navigation_layers"), &NavigationPathQueryParameters2D::set_navigation_layers);
ClassDB::bind_method(D_METHOD("get_navigation_layers"), &NavigationPathQueryParameters2D::get_navigation_layers);
+ ClassDB::bind_method(D_METHOD("set_metadata_flags", "flags"), &NavigationPathQueryParameters2D::set_metadata_flags);
+ ClassDB::bind_method(D_METHOD("get_metadata_flags"), &NavigationPathQueryParameters2D::get_metadata_flags);
+
ADD_PROPERTY(PropertyInfo(Variant::RID, "map"), "set_map", "get_map");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "start_position"), "set_start_position", "get_start_position");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "target_position"), "set_target_position", "get_target_position");
ADD_PROPERTY(PropertyInfo(Variant::INT, "navigation_layers", PROPERTY_HINT_LAYERS_2D_NAVIGATION), "set_navigation_layers", "get_navigation_layers");
ADD_PROPERTY(PropertyInfo(Variant::INT, "pathfinding_algorithm", PROPERTY_HINT_ENUM, "AStar"), "set_pathfinding_algorithm", "get_pathfinding_algorithm");
ADD_PROPERTY(PropertyInfo(Variant::INT, "path_postprocessing", PROPERTY_HINT_ENUM, "Corridorfunnel,Edgecentered"), "set_path_postprocessing", "get_path_postprocessing");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "metadata_flags", PROPERTY_HINT_FLAGS, "Include Types,Include RIDs,Include Owners"), "set_metadata_flags", "get_metadata_flags");
BIND_ENUM_CONSTANT(PATHFINDING_ALGORITHM_ASTAR);
BIND_ENUM_CONSTANT(PATH_POSTPROCESSING_CORRIDORFUNNEL);
BIND_ENUM_CONSTANT(PATH_POSTPROCESSING_EDGECENTERED);
+
+ BIND_BITFIELD_FLAG(PATH_METADATA_INCLUDE_NONE);
+ BIND_BITFIELD_FLAG(PATH_METADATA_INCLUDE_TYPES);
+ BIND_BITFIELD_FLAG(PATH_METADATA_INCLUDE_RIDS);
+ BIND_BITFIELD_FLAG(PATH_METADATA_INCLUDE_OWNERS);
+ BIND_BITFIELD_FLAG(PATH_METADATA_INCLUDE_ALL);
}
diff --git a/servers/navigation/navigation_path_query_parameters_2d.h b/servers/navigation/navigation_path_query_parameters_2d.h
index c0ef337a27..aeabe1f690 100644
--- a/servers/navigation/navigation_path_query_parameters_2d.h
+++ b/servers/navigation/navigation_path_query_parameters_2d.h
@@ -52,6 +52,14 @@ public:
PATH_POSTPROCESSING_EDGECENTERED,
};
+ enum PathMetadataFlags {
+ PATH_METADATA_INCLUDE_NONE = NavigationUtilities::PathMetadataFlags::PATH_INCLUDE_NONE,
+ PATH_METADATA_INCLUDE_TYPES = NavigationUtilities::PathMetadataFlags::PATH_INCLUDE_TYPES,
+ PATH_METADATA_INCLUDE_RIDS = NavigationUtilities::PathMetadataFlags::PATH_INCLUDE_RIDS,
+ PATH_METADATA_INCLUDE_OWNERS = NavigationUtilities::PathMetadataFlags::PATH_INCLUDE_OWNERS,
+ PATH_METADATA_INCLUDE_ALL = NavigationUtilities::PathMetadataFlags::PATH_INCLUDE_ALL
+ };
+
const NavigationUtilities::PathQueryParameters &get_parameters() const { return parameters; }
void set_pathfinding_algorithm(const PathfindingAlgorithm p_pathfinding_algorithm);
@@ -71,9 +79,13 @@ public:
void set_navigation_layers(uint32_t p_navigation_layers);
uint32_t get_navigation_layers() const;
+
+ void set_metadata_flags(BitField<NavigationPathQueryParameters2D::PathMetadataFlags> p_flags);
+ BitField<NavigationPathQueryParameters2D::PathMetadataFlags> get_metadata_flags() const;
};
VARIANT_ENUM_CAST(NavigationPathQueryParameters2D::PathfindingAlgorithm);
VARIANT_ENUM_CAST(NavigationPathQueryParameters2D::PathPostProcessing);
+VARIANT_BITFIELD_CAST(NavigationPathQueryParameters2D::PathMetadataFlags);
#endif // NAVIGATION_PATH_QUERY_PARAMETERS_2D_H
diff --git a/servers/navigation/navigation_path_query_parameters_3d.cpp b/servers/navigation/navigation_path_query_parameters_3d.cpp
index b09448e82e..180af57af5 100644
--- a/servers/navigation/navigation_path_query_parameters_3d.cpp
+++ b/servers/navigation/navigation_path_query_parameters_3d.cpp
@@ -111,6 +111,14 @@ uint32_t NavigationPathQueryParameters3D::get_navigation_layers() const {
return parameters.navigation_layers;
}
+void NavigationPathQueryParameters3D::set_metadata_flags(BitField<NavigationPathQueryParameters3D::PathMetadataFlags> p_flags) {
+ parameters.metadata_flags = (int64_t)p_flags;
+}
+
+BitField<NavigationPathQueryParameters3D::PathMetadataFlags> NavigationPathQueryParameters3D::get_metadata_flags() const {
+ return (int64_t)parameters.metadata_flags;
+}
+
void NavigationPathQueryParameters3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_pathfinding_algorithm", "pathfinding_algorithm"), &NavigationPathQueryParameters3D::set_pathfinding_algorithm);
ClassDB::bind_method(D_METHOD("get_pathfinding_algorithm"), &NavigationPathQueryParameters3D::get_pathfinding_algorithm);
@@ -130,15 +138,25 @@ void NavigationPathQueryParameters3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_navigation_layers", "navigation_layers"), &NavigationPathQueryParameters3D::set_navigation_layers);
ClassDB::bind_method(D_METHOD("get_navigation_layers"), &NavigationPathQueryParameters3D::get_navigation_layers);
+ ClassDB::bind_method(D_METHOD("set_metadata_flags", "flags"), &NavigationPathQueryParameters3D::set_metadata_flags);
+ ClassDB::bind_method(D_METHOD("get_metadata_flags"), &NavigationPathQueryParameters3D::get_metadata_flags);
+
ADD_PROPERTY(PropertyInfo(Variant::RID, "map"), "set_map", "get_map");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "start_position"), "set_start_position", "get_start_position");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "target_position"), "set_target_position", "get_target_position");
ADD_PROPERTY(PropertyInfo(Variant::INT, "navigation_layers", PROPERTY_HINT_LAYERS_3D_NAVIGATION), "set_navigation_layers", "get_navigation_layers");
ADD_PROPERTY(PropertyInfo(Variant::INT, "pathfinding_algorithm", PROPERTY_HINT_ENUM, "AStar"), "set_pathfinding_algorithm", "get_pathfinding_algorithm");
ADD_PROPERTY(PropertyInfo(Variant::INT, "path_postprocessing", PROPERTY_HINT_ENUM, "Corridorfunnel,Edgecentered"), "set_path_postprocessing", "get_path_postprocessing");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "metadata_flags", PROPERTY_HINT_FLAGS, "Include Types,Include RIDs,Include Owners"), "set_metadata_flags", "get_metadata_flags");
BIND_ENUM_CONSTANT(PATHFINDING_ALGORITHM_ASTAR);
BIND_ENUM_CONSTANT(PATH_POSTPROCESSING_CORRIDORFUNNEL);
BIND_ENUM_CONSTANT(PATH_POSTPROCESSING_EDGECENTERED);
+
+ BIND_BITFIELD_FLAG(PATH_METADATA_INCLUDE_NONE);
+ BIND_BITFIELD_FLAG(PATH_METADATA_INCLUDE_TYPES);
+ BIND_BITFIELD_FLAG(PATH_METADATA_INCLUDE_RIDS);
+ BIND_BITFIELD_FLAG(PATH_METADATA_INCLUDE_OWNERS);
+ BIND_BITFIELD_FLAG(PATH_METADATA_INCLUDE_ALL);
}
diff --git a/servers/navigation/navigation_path_query_parameters_3d.h b/servers/navigation/navigation_path_query_parameters_3d.h
index b4cf02fc79..386c83dece 100644
--- a/servers/navigation/navigation_path_query_parameters_3d.h
+++ b/servers/navigation/navigation_path_query_parameters_3d.h
@@ -52,6 +52,14 @@ public:
PATH_POSTPROCESSING_EDGECENTERED,
};
+ enum PathMetadataFlags {
+ PATH_METADATA_INCLUDE_NONE = NavigationUtilities::PathMetadataFlags::PATH_INCLUDE_NONE,
+ PATH_METADATA_INCLUDE_TYPES = NavigationUtilities::PathMetadataFlags::PATH_INCLUDE_TYPES,
+ PATH_METADATA_INCLUDE_RIDS = NavigationUtilities::PathMetadataFlags::PATH_INCLUDE_RIDS,
+ PATH_METADATA_INCLUDE_OWNERS = NavigationUtilities::PathMetadataFlags::PATH_INCLUDE_OWNERS,
+ PATH_METADATA_INCLUDE_ALL = NavigationUtilities::PathMetadataFlags::PATH_INCLUDE_ALL
+ };
+
const NavigationUtilities::PathQueryParameters &get_parameters() const { return parameters; }
void set_pathfinding_algorithm(const PathfindingAlgorithm p_pathfinding_algorithm);
@@ -71,9 +79,13 @@ public:
void set_navigation_layers(uint32_t p_navigation_layers);
uint32_t get_navigation_layers() const;
+
+ void set_metadata_flags(BitField<NavigationPathQueryParameters3D::PathMetadataFlags> p_flags);
+ BitField<NavigationPathQueryParameters3D::PathMetadataFlags> get_metadata_flags() const;
};
VARIANT_ENUM_CAST(NavigationPathQueryParameters3D::PathfindingAlgorithm);
VARIANT_ENUM_CAST(NavigationPathQueryParameters3D::PathPostProcessing);
+VARIANT_BITFIELD_CAST(NavigationPathQueryParameters3D::PathMetadataFlags);
#endif // NAVIGATION_PATH_QUERY_PARAMETERS_3D_H
diff --git a/servers/navigation/navigation_path_query_result_2d.cpp b/servers/navigation/navigation_path_query_result_2d.cpp
index 8a55451e40..e2764daa9a 100644
--- a/servers/navigation/navigation_path_query_result_2d.cpp
+++ b/servers/navigation/navigation_path_query_result_2d.cpp
@@ -38,15 +38,57 @@ const Vector<Vector2> &NavigationPathQueryResult2D::get_path() const {
return path;
}
+void NavigationPathQueryResult2D::set_path_types(const Vector<int32_t> &p_path_types) {
+ path_types = p_path_types;
+}
+
+const Vector<int32_t> &NavigationPathQueryResult2D::get_path_types() const {
+ return path_types;
+}
+
+void NavigationPathQueryResult2D::set_path_rids(const TypedArray<RID> &p_path_rids) {
+ path_rids = p_path_rids;
+}
+
+TypedArray<RID> NavigationPathQueryResult2D::get_path_rids() const {
+ return path_rids;
+}
+
+void NavigationPathQueryResult2D::set_path_owner_ids(const Vector<int64_t> &p_path_owner_ids) {
+ path_owner_ids = p_path_owner_ids;
+}
+
+const Vector<int64_t> &NavigationPathQueryResult2D::get_path_owner_ids() const {
+ return path_owner_ids;
+}
+
void NavigationPathQueryResult2D::reset() {
path.clear();
+ path_types.clear();
+ path_rids.clear();
+ path_owner_ids.clear();
}
void NavigationPathQueryResult2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_path", "path"), &NavigationPathQueryResult2D::set_path);
ClassDB::bind_method(D_METHOD("get_path"), &NavigationPathQueryResult2D::get_path);
+ ClassDB::bind_method(D_METHOD("set_path_types", "path_types"), &NavigationPathQueryResult2D::set_path_types);
+ ClassDB::bind_method(D_METHOD("get_path_types"), &NavigationPathQueryResult2D::get_path_types);
+
+ ClassDB::bind_method(D_METHOD("set_path_rids", "path_rids"), &NavigationPathQueryResult2D::set_path_rids);
+ ClassDB::bind_method(D_METHOD("get_path_rids"), &NavigationPathQueryResult2D::get_path_rids);
+
+ ClassDB::bind_method(D_METHOD("set_path_owner_ids", "path_owner_ids"), &NavigationPathQueryResult2D::set_path_owner_ids);
+ ClassDB::bind_method(D_METHOD("get_path_owner_ids"), &NavigationPathQueryResult2D::get_path_owner_ids);
+
ClassDB::bind_method(D_METHOD("reset"), &NavigationPathQueryResult2D::reset);
ADD_PROPERTY(PropertyInfo(Variant::PACKED_VECTOR2_ARRAY, "path"), "set_path", "get_path");
+ ADD_PROPERTY(PropertyInfo(Variant::PACKED_INT32_ARRAY, "path_types"), "set_path_types", "get_path_types");
+ ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "path_rids", PROPERTY_HINT_ARRAY_TYPE, "RID"), "set_path_rids", "get_path_rids");
+ ADD_PROPERTY(PropertyInfo(Variant::PACKED_INT64_ARRAY, "path_owner_ids"), "set_path_owner_ids", "get_path_owner_ids");
+
+ BIND_ENUM_CONSTANT(PATH_SEGMENT_TYPE_REGION);
+ BIND_ENUM_CONSTANT(PATH_SEGMENT_TYPE_LINK);
}
diff --git a/servers/navigation/navigation_path_query_result_2d.h b/servers/navigation/navigation_path_query_result_2d.h
index da251ef32d..852a9780ef 100644
--- a/servers/navigation/navigation_path_query_result_2d.h
+++ b/servers/navigation/navigation_path_query_result_2d.h
@@ -38,15 +38,34 @@ class NavigationPathQueryResult2D : public RefCounted {
GDCLASS(NavigationPathQueryResult2D, RefCounted);
Vector<Vector2> path;
+ Vector<int32_t> path_types;
+ TypedArray<RID> path_rids;
+ Vector<int64_t> path_owner_ids;
protected:
static void _bind_methods();
public:
+ enum PathSegmentType {
+ PATH_SEGMENT_TYPE_REGION = 0,
+ PATH_SEGMENT_TYPE_LINK = 1,
+ };
+
void set_path(const Vector<Vector2> &p_path);
const Vector<Vector2> &get_path() const;
+ void set_path_types(const Vector<int32_t> &p_path_types);
+ const Vector<int32_t> &get_path_types() const;
+
+ void set_path_rids(const TypedArray<RID> &p_path_rids);
+ TypedArray<RID> get_path_rids() const;
+
+ void set_path_owner_ids(const Vector<int64_t> &p_path_owner_ids);
+ const Vector<int64_t> &get_path_owner_ids() const;
+
void reset();
};
+VARIANT_ENUM_CAST(NavigationPathQueryResult2D::PathSegmentType);
+
#endif // NAVIGATION_PATH_QUERY_RESULT_2D_H
diff --git a/servers/navigation/navigation_path_query_result_3d.cpp b/servers/navigation/navigation_path_query_result_3d.cpp
index 1e28352995..8218adec18 100644
--- a/servers/navigation/navigation_path_query_result_3d.cpp
+++ b/servers/navigation/navigation_path_query_result_3d.cpp
@@ -38,15 +38,57 @@ const Vector<Vector3> &NavigationPathQueryResult3D::get_path() const {
return path;
}
+void NavigationPathQueryResult3D::set_path_types(const Vector<int32_t> &p_path_types) {
+ path_types = p_path_types;
+}
+
+const Vector<int32_t> &NavigationPathQueryResult3D::get_path_types() const {
+ return path_types;
+}
+
+void NavigationPathQueryResult3D::set_path_rids(const TypedArray<RID> &p_path_rids) {
+ path_rids = p_path_rids;
+}
+
+TypedArray<RID> NavigationPathQueryResult3D::get_path_rids() const {
+ return path_rids;
+}
+
+void NavigationPathQueryResult3D::set_path_owner_ids(const Vector<int64_t> &p_path_owner_ids) {
+ path_owner_ids = p_path_owner_ids;
+}
+
+const Vector<int64_t> &NavigationPathQueryResult3D::get_path_owner_ids() const {
+ return path_owner_ids;
+}
+
void NavigationPathQueryResult3D::reset() {
path.clear();
+ path_types.clear();
+ path_rids.clear();
+ path_owner_ids.clear();
}
void NavigationPathQueryResult3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_path", "path"), &NavigationPathQueryResult3D::set_path);
ClassDB::bind_method(D_METHOD("get_path"), &NavigationPathQueryResult3D::get_path);
+ ClassDB::bind_method(D_METHOD("set_path_types", "path_types"), &NavigationPathQueryResult3D::set_path_types);
+ ClassDB::bind_method(D_METHOD("get_path_types"), &NavigationPathQueryResult3D::get_path_types);
+
+ ClassDB::bind_method(D_METHOD("set_path_rids", "path_rids"), &NavigationPathQueryResult3D::set_path_rids);
+ ClassDB::bind_method(D_METHOD("get_path_rids"), &NavigationPathQueryResult3D::get_path_rids);
+
+ ClassDB::bind_method(D_METHOD("set_path_owner_ids", "path_owner_ids"), &NavigationPathQueryResult3D::set_path_owner_ids);
+ ClassDB::bind_method(D_METHOD("get_path_owner_ids"), &NavigationPathQueryResult3D::get_path_owner_ids);
+
ClassDB::bind_method(D_METHOD("reset"), &NavigationPathQueryResult3D::reset);
ADD_PROPERTY(PropertyInfo(Variant::PACKED_VECTOR3_ARRAY, "path"), "set_path", "get_path");
+ ADD_PROPERTY(PropertyInfo(Variant::PACKED_INT32_ARRAY, "path_types"), "set_path_types", "get_path_types");
+ ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "path_rids", PROPERTY_HINT_ARRAY_TYPE, "RID"), "set_path_rids", "get_path_rids");
+ ADD_PROPERTY(PropertyInfo(Variant::PACKED_INT64_ARRAY, "path_owner_ids"), "set_path_owner_ids", "get_path_owner_ids");
+
+ BIND_ENUM_CONSTANT(PATH_SEGMENT_TYPE_REGION);
+ BIND_ENUM_CONSTANT(PATH_SEGMENT_TYPE_LINK);
}
diff --git a/servers/navigation/navigation_path_query_result_3d.h b/servers/navigation/navigation_path_query_result_3d.h
index fc143ac389..ce34e18dc1 100644
--- a/servers/navigation/navigation_path_query_result_3d.h
+++ b/servers/navigation/navigation_path_query_result_3d.h
@@ -32,21 +32,41 @@
#define NAVIGATION_PATH_QUERY_RESULT_3D_H
#include "core/object/ref_counted.h"
+#include "core/variant/typed_array.h"
#include "servers/navigation/navigation_utilities.h"
class NavigationPathQueryResult3D : public RefCounted {
GDCLASS(NavigationPathQueryResult3D, RefCounted);
Vector<Vector3> path;
+ Vector<int32_t> path_types;
+ TypedArray<RID> path_rids;
+ Vector<int64_t> path_owner_ids;
protected:
static void _bind_methods();
public:
+ enum PathSegmentType {
+ PATH_SEGMENT_TYPE_REGION = 0,
+ PATH_SEGMENT_TYPE_LINK = 1,
+ };
+
void set_path(const Vector<Vector3> &p_path);
const Vector<Vector3> &get_path() const;
+ void set_path_types(const Vector<int32_t> &p_path_types);
+ const Vector<int32_t> &get_path_types() const;
+
+ void set_path_rids(const TypedArray<RID> &p_path_rids);
+ TypedArray<RID> get_path_rids() const;
+
+ void set_path_owner_ids(const Vector<int64_t> &p_path_owner_ids);
+ const Vector<int64_t> &get_path_owner_ids() const;
+
void reset();
};
+VARIANT_ENUM_CAST(NavigationPathQueryResult3D::PathSegmentType);
+
#endif // NAVIGATION_PATH_QUERY_RESULT_3D_H
diff --git a/servers/navigation/navigation_utilities.h b/servers/navigation/navigation_utilities.h
index bedcc16a67..c22a2ed952 100644
--- a/servers/navigation/navigation_utilities.h
+++ b/servers/navigation/navigation_utilities.h
@@ -32,6 +32,7 @@
#define NAVIGATION_UTILITIES_H
#include "core/math/vector3.h"
+#include "core/variant/typed_array.h"
namespace NavigationUtilities {
@@ -44,17 +45,34 @@ enum PathPostProcessing {
PATH_POSTPROCESSING_EDGECENTERED,
};
+enum PathSegmentType {
+ PATH_SEGMENT_TYPE_REGION = 0,
+ PATH_SEGMENT_TYPE_LINK
+};
+
+enum PathMetadataFlags {
+ PATH_INCLUDE_NONE = 0,
+ PATH_INCLUDE_TYPES = 1,
+ PATH_INCLUDE_RIDS = 2,
+ PATH_INCLUDE_OWNERS = 4,
+ PATH_INCLUDE_ALL = PATH_INCLUDE_TYPES | PATH_INCLUDE_RIDS | PATH_INCLUDE_OWNERS
+};
+
struct PathQueryParameters {
PathfindingAlgorithm pathfinding_algorithm = PATHFINDING_ALGORITHM_ASTAR;
PathPostProcessing path_postprocessing = PATH_POSTPROCESSING_CORRIDORFUNNEL;
RID map;
- Vector3 start_position = Vector3();
- Vector3 target_position = Vector3();
+ Vector3 start_position;
+ Vector3 target_position;
uint32_t navigation_layers = 1;
+ BitField<PathMetadataFlags> metadata_flags = PATH_INCLUDE_ALL;
};
struct PathQueryResult {
Vector<Vector3> path;
+ Vector<int32_t> path_types;
+ TypedArray<RID> path_rids;
+ Vector<int64_t> path_owner_ids;
};
} //namespace NavigationUtilities
diff --git a/servers/navigation_server_2d.cpp b/servers/navigation_server_2d.cpp
index 04e5d2f6a1..6fd5f222cf 100644
--- a/servers/navigation_server_2d.cpp
+++ b/servers/navigation_server_2d.cpp
@@ -140,10 +140,6 @@ static Transform3D trf2_to_trf3(const Transform2D &d) {
return Transform3D(b, o);
}
-static Object *obj_to_obj(Object *d) {
- return d;
-}
-
static StringName sn_to_sn(const StringName &d) {
return d;
}
@@ -152,9 +148,13 @@ static Variant var_to_var(const Variant &d) {
return d;
}
+static ObjectID id_to_id(const ObjectID &id) {
+ return id;
+}
+
static Ref<NavigationMesh> poly_to_mesh(Ref<NavigationPolygon> d) {
if (d.is_valid()) {
- return d->get_mesh();
+ return d->get_navigation_mesh();
} else {
return Ref<NavigationMesh>();
}
@@ -250,13 +250,15 @@ void NavigationServer2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("region_get_enter_cost", "region"), &NavigationServer2D::region_get_enter_cost);
ClassDB::bind_method(D_METHOD("region_set_travel_cost", "region", "travel_cost"), &NavigationServer2D::region_set_travel_cost);
ClassDB::bind_method(D_METHOD("region_get_travel_cost", "region"), &NavigationServer2D::region_get_travel_cost);
+ ClassDB::bind_method(D_METHOD("region_set_owner_id", "region", "owner_id"), &NavigationServer2D::region_set_owner_id);
+ ClassDB::bind_method(D_METHOD("region_get_owner_id", "region"), &NavigationServer2D::region_get_owner_id);
ClassDB::bind_method(D_METHOD("region_owns_point", "region", "point"), &NavigationServer2D::region_owns_point);
ClassDB::bind_method(D_METHOD("region_set_map", "region", "map"), &NavigationServer2D::region_set_map);
ClassDB::bind_method(D_METHOD("region_get_map", "region"), &NavigationServer2D::region_get_map);
ClassDB::bind_method(D_METHOD("region_set_navigation_layers", "region", "navigation_layers"), &NavigationServer2D::region_set_navigation_layers);
ClassDB::bind_method(D_METHOD("region_get_navigation_layers", "region"), &NavigationServer2D::region_get_navigation_layers);
ClassDB::bind_method(D_METHOD("region_set_transform", "region", "transform"), &NavigationServer2D::region_set_transform);
- ClassDB::bind_method(D_METHOD("region_set_navpoly", "region", "nav_poly"), &NavigationServer2D::region_set_navpoly);
+ ClassDB::bind_method(D_METHOD("region_set_navigation_polygon", "region", "navigation_polygon"), &NavigationServer2D::region_set_navigation_polygon);
ClassDB::bind_method(D_METHOD("region_get_connections_count", "region"), &NavigationServer2D::region_get_connections_count);
ClassDB::bind_method(D_METHOD("region_get_connection_pathway_start", "region", "connection"), &NavigationServer2D::region_get_connection_pathway_start);
ClassDB::bind_method(D_METHOD("region_get_connection_pathway_end", "region", "connection"), &NavigationServer2D::region_get_connection_pathway_end);
@@ -276,6 +278,8 @@ void NavigationServer2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("link_get_enter_cost", "link"), &NavigationServer2D::link_get_enter_cost);
ClassDB::bind_method(D_METHOD("link_set_travel_cost", "link", "travel_cost"), &NavigationServer2D::link_set_travel_cost);
ClassDB::bind_method(D_METHOD("link_get_travel_cost", "link"), &NavigationServer2D::link_get_travel_cost);
+ ClassDB::bind_method(D_METHOD("link_set_owner_id", "link", "owner_id"), &NavigationServer2D::link_set_owner_id);
+ ClassDB::bind_method(D_METHOD("link_get_owner_id", "link"), &NavigationServer2D::link_get_owner_id);
ClassDB::bind_method(D_METHOD("agent_create"), &NavigationServer2D::agent_create);
ClassDB::bind_method(D_METHOD("agent_set_map", "agent", "map"), &NavigationServer2D::agent_set_map);
@@ -289,7 +293,7 @@ void NavigationServer2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("agent_set_target_velocity", "agent", "target_velocity"), &NavigationServer2D::agent_set_target_velocity);
ClassDB::bind_method(D_METHOD("agent_set_position", "agent", "position"), &NavigationServer2D::agent_set_position);
ClassDB::bind_method(D_METHOD("agent_is_map_changed", "agent"), &NavigationServer2D::agent_is_map_changed);
- ClassDB::bind_method(D_METHOD("agent_set_callback", "agent", "receiver", "method", "userdata"), &NavigationServer2D::agent_set_callback, DEFVAL(Variant()));
+ ClassDB::bind_method(D_METHOD("agent_set_callback", "agent", "object_id", "method", "userdata"), &NavigationServer2D::agent_set_callback, DEFVAL(Variant()));
ClassDB::bind_method(D_METHOD("free_rid", "rid"), &NavigationServer2D::free);
@@ -348,6 +352,8 @@ void FORWARD_2_C(region_set_enter_cost, RID, p_region, real_t, p_enter_cost, rid
real_t FORWARD_1_C(region_get_enter_cost, RID, p_region, rid_to_rid);
void FORWARD_2_C(region_set_travel_cost, RID, p_region, real_t, p_travel_cost, rid_to_rid, real_to_real);
real_t FORWARD_1_C(region_get_travel_cost, RID, p_region, rid_to_rid);
+void FORWARD_2_C(region_set_owner_id, RID, p_region, ObjectID, p_owner_id, rid_to_rid, id_to_id);
+ObjectID FORWARD_1_C(region_get_owner_id, RID, p_region, rid_to_rid);
bool FORWARD_2_C(region_owns_point, RID, p_region, const Vector2 &, p_point, rid_to_rid, v2_to_v3);
void FORWARD_2_C(region_set_map, RID, p_region, RID, p_map, rid_to_rid, rid_to_rid);
@@ -355,8 +361,8 @@ void FORWARD_2_C(region_set_navigation_layers, RID, p_region, uint32_t, p_naviga
uint32_t FORWARD_1_C(region_get_navigation_layers, RID, p_region, rid_to_rid);
void FORWARD_2_C(region_set_transform, RID, p_region, Transform2D, p_transform, rid_to_rid, trf2_to_trf3);
-void NavigationServer2D::region_set_navpoly(RID p_region, Ref<NavigationPolygon> p_nav_mesh) const {
- NavigationServer3D::get_singleton()->region_set_navmesh(p_region, poly_to_mesh(p_nav_mesh));
+void NavigationServer2D::region_set_navigation_polygon(RID p_region, Ref<NavigationPolygon> p_navigation_polygon) const {
+ NavigationServer3D::get_singleton()->region_set_navigation_mesh(p_region, poly_to_mesh(p_navigation_polygon));
}
int FORWARD_1_C(region_get_connections_count, RID, p_region, rid_to_rid);
@@ -379,6 +385,8 @@ void FORWARD_2_C(link_set_enter_cost, RID, p_link, real_t, p_enter_cost, rid_to_
real_t FORWARD_1_C(link_get_enter_cost, RID, p_link, rid_to_rid);
void FORWARD_2_C(link_set_travel_cost, RID, p_link, real_t, p_travel_cost, rid_to_rid, real_to_real);
real_t FORWARD_1_C(link_get_travel_cost, RID, p_link, rid_to_rid);
+void FORWARD_2_C(link_set_owner_id, RID, p_link, ObjectID, p_owner_id, rid_to_rid, id_to_id);
+ObjectID FORWARD_1_C(link_get_owner_id, RID, p_link, rid_to_rid);
RID NavigationServer2D::agent_create() const {
RID agent = NavigationServer3D::get_singleton()->agent_create();
@@ -408,7 +416,7 @@ void FORWARD_2_C(agent_set_ignore_y, RID, p_agent, bool, p_ignore, rid_to_rid, b
bool FORWARD_1_C(agent_is_map_changed, RID, p_agent, rid_to_rid);
-void FORWARD_4_C(agent_set_callback, RID, p_agent, Object *, p_receiver, StringName, p_method, Variant, p_udata, rid_to_rid, obj_to_obj, sn_to_sn, var_to_var);
+void FORWARD_4_C(agent_set_callback, RID, p_agent, ObjectID, p_object_id, StringName, p_method, Variant, p_udata, rid_to_rid, id_to_id, sn_to_sn, var_to_var);
void FORWARD_1_C(free, RID, p_object, rid_to_rid);
@@ -419,4 +427,7 @@ void NavigationServer2D::query_path(const Ref<NavigationPathQueryParameters2D> &
const NavigationUtilities::PathQueryResult _query_result = NavigationServer3D::get_singleton()->_query_path(p_query_parameters->get_parameters());
p_query_result->set_path(vector_v3_to_v2(_query_result.path));
+ p_query_result->set_path_types(_query_result.path_types);
+ p_query_result->set_path_rids(_query_result.path_rids);
+ p_query_result->set_path_owner_ids(_query_result.path_owner_ids);
}
diff --git a/servers/navigation_server_2d.h b/servers/navigation_server_2d.h
index 54cfc6b14e..9b921969c0 100644
--- a/servers/navigation_server_2d.h
+++ b/servers/navigation_server_2d.h
@@ -34,7 +34,7 @@
#include "core/object/class_db.h"
#include "core/templates/rid.h"
-#include "scene/2d/navigation_region_2d.h"
+#include "scene/resources/navigation_polygon.h"
#include "servers/navigation/navigation_path_query_parameters_2d.h"
#include "servers/navigation/navigation_path_query_result_2d.h"
@@ -108,6 +108,10 @@ public:
virtual void region_set_travel_cost(RID p_region, real_t p_travel_cost) const;
virtual real_t region_get_travel_cost(RID p_region) const;
+ /// Set the node which manages this region.
+ virtual void region_set_owner_id(RID p_region, ObjectID p_owner_id) const;
+ virtual ObjectID region_get_owner_id(RID p_region) const;
+
virtual bool region_owns_point(RID p_region, const Vector2 &p_point) const;
/// Set the map of this region.
@@ -122,7 +126,7 @@ public:
virtual void region_set_transform(RID p_region, Transform2D p_transform) const;
/// Set the navigation poly of this region.
- virtual void region_set_navpoly(RID p_region, Ref<NavigationPolygon> p_nav_mesh) const;
+ virtual void region_set_navigation_polygon(RID p_region, Ref<NavigationPolygon> p_navigation_polygon) const;
/// Get a list of a region's connection to other regions.
virtual int region_get_connections_count(RID p_region) const;
@@ -160,6 +164,10 @@ public:
virtual void link_set_travel_cost(RID p_link, real_t p_travel_cost) const;
virtual real_t link_get_travel_cost(RID p_link) const;
+ /// Set the node which manages this link.
+ virtual void link_set_owner_id(RID p_link, ObjectID p_owner_id) const;
+ virtual ObjectID link_get_owner_id(RID p_link) const;
+
/// Creates the agent.
virtual RID agent_create() const;
@@ -218,7 +226,7 @@ public:
virtual bool agent_is_map_changed(RID p_agent) const;
/// Callback called at the end of the RVO process
- virtual void agent_set_callback(RID p_agent, Object *p_receiver, StringName p_method, Variant p_udata = Variant()) const;
+ virtual void agent_set_callback(RID p_agent, ObjectID p_object_id, StringName p_method, Variant p_udata = Variant()) const;
virtual void query_path(const Ref<NavigationPathQueryParameters2D> &p_query_parameters, Ref<NavigationPathQueryResult2D> p_query_result) const;
diff --git a/servers/navigation_server_3d.cpp b/servers/navigation_server_3d.cpp
index cab8816747..6ad07d3053 100644
--- a/servers/navigation_server_3d.cpp
+++ b/servers/navigation_server_3d.cpp
@@ -69,14 +69,16 @@ void NavigationServer3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("region_get_enter_cost", "region"), &NavigationServer3D::region_get_enter_cost);
ClassDB::bind_method(D_METHOD("region_set_travel_cost", "region", "travel_cost"), &NavigationServer3D::region_set_travel_cost);
ClassDB::bind_method(D_METHOD("region_get_travel_cost", "region"), &NavigationServer3D::region_get_travel_cost);
+ ClassDB::bind_method(D_METHOD("region_set_owner_id", "region", "owner_id"), &NavigationServer3D::region_set_owner_id);
+ ClassDB::bind_method(D_METHOD("region_get_owner_id", "region"), &NavigationServer3D::region_get_owner_id);
ClassDB::bind_method(D_METHOD("region_owns_point", "region", "point"), &NavigationServer3D::region_owns_point);
ClassDB::bind_method(D_METHOD("region_set_map", "region", "map"), &NavigationServer3D::region_set_map);
ClassDB::bind_method(D_METHOD("region_get_map", "region"), &NavigationServer3D::region_get_map);
ClassDB::bind_method(D_METHOD("region_set_navigation_layers", "region", "navigation_layers"), &NavigationServer3D::region_set_navigation_layers);
ClassDB::bind_method(D_METHOD("region_get_navigation_layers", "region"), &NavigationServer3D::region_get_navigation_layers);
ClassDB::bind_method(D_METHOD("region_set_transform", "region", "transform"), &NavigationServer3D::region_set_transform);
- ClassDB::bind_method(D_METHOD("region_set_navmesh", "region", "nav_mesh"), &NavigationServer3D::region_set_navmesh);
- ClassDB::bind_method(D_METHOD("region_bake_navmesh", "mesh", "node"), &NavigationServer3D::region_bake_navmesh);
+ ClassDB::bind_method(D_METHOD("region_set_navigation_mesh", "region", "navigation_mesh"), &NavigationServer3D::region_set_navigation_mesh);
+ ClassDB::bind_method(D_METHOD("region_bake_navigation_mesh", "navigation_mesh", "root_node"), &NavigationServer3D::region_bake_navigation_mesh);
ClassDB::bind_method(D_METHOD("region_get_connections_count", "region"), &NavigationServer3D::region_get_connections_count);
ClassDB::bind_method(D_METHOD("region_get_connection_pathway_start", "region", "connection"), &NavigationServer3D::region_get_connection_pathway_start);
ClassDB::bind_method(D_METHOD("region_get_connection_pathway_end", "region", "connection"), &NavigationServer3D::region_get_connection_pathway_end);
@@ -96,6 +98,8 @@ void NavigationServer3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("link_get_enter_cost", "link"), &NavigationServer3D::link_get_enter_cost);
ClassDB::bind_method(D_METHOD("link_set_travel_cost", "link", "travel_cost"), &NavigationServer3D::link_set_travel_cost);
ClassDB::bind_method(D_METHOD("link_get_travel_cost", "link"), &NavigationServer3D::link_get_travel_cost);
+ ClassDB::bind_method(D_METHOD("link_set_owner_id", "link", "owner_id"), &NavigationServer3D::link_set_owner_id);
+ ClassDB::bind_method(D_METHOD("link_get_owner_id", "link"), &NavigationServer3D::link_get_owner_id);
ClassDB::bind_method(D_METHOD("agent_create"), &NavigationServer3D::agent_create);
ClassDB::bind_method(D_METHOD("agent_set_map", "agent", "map"), &NavigationServer3D::agent_set_map);
@@ -109,7 +113,7 @@ void NavigationServer3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("agent_set_target_velocity", "agent", "target_velocity"), &NavigationServer3D::agent_set_target_velocity);
ClassDB::bind_method(D_METHOD("agent_set_position", "agent", "position"), &NavigationServer3D::agent_set_position);
ClassDB::bind_method(D_METHOD("agent_is_map_changed", "agent"), &NavigationServer3D::agent_is_map_changed);
- ClassDB::bind_method(D_METHOD("agent_set_callback", "agent", "receiver", "method", "userdata"), &NavigationServer3D::agent_set_callback, DEFVAL(Variant()));
+ ClassDB::bind_method(D_METHOD("agent_set_callback", "agent", "object_id", "method", "userdata"), &NavigationServer3D::agent_set_callback, DEFVAL(Variant()));
ClassDB::bind_method(D_METHOD("free_rid", "rid"), &NavigationServer3D::free);
@@ -151,7 +155,7 @@ NavigationServer3D::NavigationServer3D() {
debug_navigation_enable_link_connections_xray = GLOBAL_DEF("debug/shapes/navigation/enable_link_connections_xray", true);
if (Engine::get_singleton()->is_editor_hint()) {
- // enable NavigationServer3D when in Editor or else navmesh edge connections are invisible
+ // enable NavigationServer3D when in Editor or else navigation mesh edge connections are invisible
// on runtime tests SceneTree has "Visible Navigation" set and main iteration takes care of this
set_debug_enabled(true);
}
@@ -487,4 +491,7 @@ void NavigationServer3D::query_path(const Ref<NavigationPathQueryParameters3D> &
const NavigationUtilities::PathQueryResult _query_result = _query_path(p_query_parameters->get_parameters());
p_query_result->set_path(_query_result.path);
+ p_query_result->set_path_types(_query_result.path_types);
+ p_query_result->set_path_rids(_query_result.path_rids);
+ p_query_result->set_path_owner_ids(_query_result.path_owner_ids);
}
diff --git a/servers/navigation_server_3d.h b/servers/navigation_server_3d.h
index 0f537383a2..65d6d19073 100644
--- a/servers/navigation_server_3d.h
+++ b/servers/navigation_server_3d.h
@@ -120,6 +120,10 @@ public:
virtual void region_set_travel_cost(RID p_region, real_t p_travel_cost) const = 0;
virtual real_t region_get_travel_cost(RID p_region) const = 0;
+ /// Set the node which manages this region.
+ virtual void region_set_owner_id(RID p_region, ObjectID p_owner_id) const = 0;
+ virtual ObjectID region_get_owner_id(RID p_region) const = 0;
+
virtual bool region_owns_point(RID p_region, const Vector3 &p_point) const = 0;
/// Set the map of this region.
@@ -134,10 +138,10 @@ public:
virtual void region_set_transform(RID p_region, Transform3D p_transform) const = 0;
/// Set the navigation mesh of this region.
- virtual void region_set_navmesh(RID p_region, Ref<NavigationMesh> p_nav_mesh) const = 0;
+ virtual void region_set_navigation_mesh(RID p_region, Ref<NavigationMesh> p_navigation_mesh) const = 0;
/// Bake the navigation mesh.
- virtual void region_bake_navmesh(Ref<NavigationMesh> r_mesh, Node *p_node) const = 0;
+ virtual void region_bake_navigation_mesh(Ref<NavigationMesh> p_navigation_mesh, Node *p_root_node) const = 0;
/// Get a list of a region's connection to other regions.
virtual int region_get_connections_count(RID p_region) const = 0;
@@ -175,6 +179,10 @@ public:
virtual void link_set_travel_cost(RID p_link, real_t p_travel_cost) const = 0;
virtual real_t link_get_travel_cost(RID p_link) const = 0;
+ /// Set the node which manages this link.
+ virtual void link_set_owner_id(RID p_link, ObjectID p_owner_id) const = 0;
+ virtual ObjectID link_get_owner_id(RID p_link) const = 0;
+
/// Creates the agent.
virtual RID agent_create() const = 0;
@@ -233,7 +241,7 @@ public:
virtual bool agent_is_map_changed(RID p_agent) const = 0;
/// Callback called at the end of the RVO process
- virtual void agent_set_callback(RID p_agent, Object *p_receiver, StringName p_method, Variant p_udata = Variant()) const = 0;
+ virtual void agent_set_callback(RID p_agent, ObjectID p_object_id, StringName p_method, Variant p_udata = Variant()) const = 0;
/// Destroy the `RID`
virtual void free(RID p_object) const = 0;
diff --git a/servers/physics_2d/godot_body_pair_2d.cpp b/servers/physics_2d/godot_body_pair_2d.cpp
index 7b7c67bbc2..1684835e76 100644
--- a/servers/physics_2d/godot_body_pair_2d.cpp
+++ b/servers/physics_2d/godot_body_pair_2d.cpp
@@ -161,6 +161,11 @@ void GodotBodyPair2D::_validate_contacts() {
}
}
+// _test_ccd prevents tunneling by slowing down a high velocity body that is about to collide so that next frame it will be at an appropriate location to collide (i.e. slight overlap)
+// Warning: the way velocity is adjusted down to cause a collision means the momentum will be weaker than it should for a bounce!
+// Process: only proceed if body A's motion is high relative to its size.
+// cast forward along motion vector to see if A is going to enter/pass B's collider next frame, only proceed if it does.
+// adjust the velocity of A down so that it will just slightly intersect the collider instead of blowing right past it.
bool GodotBodyPair2D::_test_ccd(real_t p_step, GodotBody2D *p_A, int p_shape_A, const Transform2D &p_xform_A, GodotBody2D *p_B, int p_shape_B, const Transform2D &p_xform_B) {
Vector2 motion = p_A->get_linear_velocity() * p_step;
real_t mlen = motion.length();
@@ -180,24 +185,32 @@ bool GodotBodyPair2D::_test_ccd(real_t p_step, GodotBody2D *p_A, int p_shape_A,
return false;
}
- // Going too fast in that direction.
+ // A is moving fast enough that tunneling might occur. See if it's really about to collide.
// Cast a segment from support in motion normal, in the same direction of motion by motion length.
- // Support is the worst case collision point, so real collision happened before.
+ // Support point will the farthest forward collision point along the movement vector.
+ // i.e. the point that should hit B first if any collision does occur.
+
+ // convert mnormal into body A's local xform because get_support requires (and returns) local coordinates.
int a;
Vector2 s[2];
- p_A->get_shape(p_shape_A)->get_supports(p_xform_A.basis_xform(mnormal).normalized(), s, a);
+ p_A->get_shape(p_shape_A)->get_supports(p_xform_A.basis_xform_inv(mnormal).normalized(), s, a);
Vector2 from = p_xform_A.xform(s[0]);
+ // Back up 10% of the per-frame motion behind the support point and use that as the beginning of our cast.
+ // This should ensure the calculated new velocity will really cause a bit of overlap instead of just getting us very close.
Vector2 to = from + motion;
Transform2D from_inv = p_xform_B.affine_inverse();
- // Start from a little inside the bounding box.
- Vector2 local_from = from_inv.xform(from - mnormal * mlen * 0.1);
+ // Back up 10% of the per-frame motion behind the support point and use that as the beginning of our cast.
+ // At high speeds, this may mean we're actually casting from well behind the body instead of inside it, which is odd. But it still works out.
+ Vector2 local_from = from_inv.xform(from - motion * 0.1);
Vector2 local_to = from_inv.xform(to);
Vector2 rpos, rnorm;
if (!p_B->get_shape(p_shape_B)->intersect_segment(local_from, local_to, rpos, rnorm)) {
+ // there was no hit. Since the segment is the length of per-frame motion, this means the bodies will not
+ // actually collide yet on next frame. We'll probably check again next frame once they're closer.
return false;
}
@@ -215,7 +228,7 @@ bool GodotBodyPair2D::_test_ccd(real_t p_step, GodotBody2D *p_A, int p_shape_A,
// next frame will hit softly or soft enough.
Vector2 hitpos = p_xform_B.xform(rpos);
- real_t newlen = hitpos.distance_to(from) - (max - min) * 0.01;
+ real_t newlen = hitpos.distance_to(from) + (max - min) * 0.01; // adding 1% of body length to the distance between collision and support point should cause body A's support point to arrive just within B's collider next frame.
p_A->set_linear_velocity(mnormal * (newlen / p_step));
return true;
diff --git a/servers/physics_2d/godot_shape_2d.cpp b/servers/physics_2d/godot_shape_2d.cpp
index da414ae233..6823cb32c1 100644
--- a/servers/physics_2d/godot_shape_2d.cpp
+++ b/servers/physics_2d/godot_shape_2d.cpp
@@ -369,8 +369,9 @@ void GodotCapsuleShape2D::get_supports(const Vector2 &p_normal, Vector2 *r_suppo
Vector2 n = p_normal;
real_t d = n.y;
+ real_t h = height * 0.5 - radius; // half-height of the rectangle part
- if (Math::abs(d) < (1.0 - _SEGMENT_IS_VALID_SUPPORT_THRESHOLD)) {
+ if (h > 0 && Math::abs(d) < (1.0 - _SEGMENT_IS_VALID_SUPPORT_THRESHOLD)) {
// make it flat
n.y = 0.0;
n.normalize();
@@ -378,13 +379,10 @@ void GodotCapsuleShape2D::get_supports(const Vector2 &p_normal, Vector2 *r_suppo
r_amount = 2;
r_supports[0] = n;
- r_supports[0].y += height * 0.5 - radius;
+ r_supports[0].y += h;
r_supports[1] = n;
- r_supports[1].y -= height * 0.5 - radius;
-
+ r_supports[1].y -= h;
} else {
- real_t h = height * 0.5 - radius;
-
n *= radius;
n.y += (d > 0) ? h : -h;
r_amount = 1;
diff --git a/servers/physics_2d/godot_step_2d.cpp b/servers/physics_2d/godot_step_2d.cpp
index 46718c8819..b7d79bc0e3 100644
--- a/servers/physics_2d/godot_step_2d.cpp
+++ b/servers/physics_2d/godot_step_2d.cpp
@@ -71,7 +71,7 @@ void GodotStep2D::_populate_island(GodotBody2D *p_body, LocalVector<GodotBody2D
}
}
-void GodotStep2D::_setup_contraint(uint32_t p_constraint_index, void *p_userdata) {
+void GodotStep2D::_setup_constraint(uint32_t p_constraint_index, void *p_userdata) {
GodotConstraint2D *constraint = all_constraints[p_constraint_index];
constraint->setup(delta);
}
@@ -238,8 +238,8 @@ void GodotStep2D::step(GodotSpace2D *p_space, real_t p_delta) {
/* SETUP CONSTRAINTS / PROCESS COLLISIONS */
- uint32_t total_contraint_count = all_constraints.size();
- WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &GodotStep2D::_setup_contraint, nullptr, total_contraint_count, -1, true, SNAME("Physics2DConstraintSetup"));
+ uint32_t total_constraint_count = all_constraints.size();
+ WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &GodotStep2D::_setup_constraint, nullptr, total_constraint_count, -1, true, SNAME("Physics2DConstraintSetup"));
WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task);
{ //profile
diff --git a/servers/physics_2d/godot_step_2d.h b/servers/physics_2d/godot_step_2d.h
index 9f8fdd6ce3..4b3b6fc966 100644
--- a/servers/physics_2d/godot_step_2d.h
+++ b/servers/physics_2d/godot_step_2d.h
@@ -47,7 +47,7 @@ class GodotStep2D {
LocalVector<GodotConstraint2D *> all_constraints;
void _populate_island(GodotBody2D *p_body, LocalVector<GodotBody2D *> &p_body_island, LocalVector<GodotConstraint2D *> &p_constraint_island);
- void _setup_contraint(uint32_t p_constraint_index, void *p_userdata = nullptr);
+ void _setup_constraint(uint32_t p_constraint_index, void *p_userdata = nullptr);
void _pre_solve_island(LocalVector<GodotConstraint2D *> &p_constraint_island) const;
void _solve_island(uint32_t p_island_index, void *p_userdata = nullptr) const;
void _check_suspend(LocalVector<GodotBody2D *> &p_body_island) const;
diff --git a/servers/physics_3d/godot_body_pair_3d.cpp b/servers/physics_3d/godot_body_pair_3d.cpp
index 7e6cc6f834..00b7941292 100644
--- a/servers/physics_3d/godot_body_pair_3d.cpp
+++ b/servers/physics_3d/godot_body_pair_3d.cpp
@@ -161,6 +161,11 @@ void GodotBodyPair3D::validate_contacts() {
}
}
+// _test_ccd prevents tunneling by slowing down a high velocity body that is about to collide so that next frame it will be at an appropriate location to collide (i.e. slight overlap)
+// Warning: the way velocity is adjusted down to cause a collision means the momentum will be weaker than it should for a bounce!
+// Process: only proceed if body A's motion is high relative to its size.
+// cast forward along motion vector to see if A is going to enter/pass B's collider next frame, only proceed if it does.
+// adjust the velocity of A down so that it will just slightly intersect the collider instead of blowing right past it.
bool GodotBodyPair3D::_test_ccd(real_t p_step, GodotBody3D *p_A, int p_shape_A, const Transform3D &p_xform_A, GodotBody3D *p_B, int p_shape_B, const Transform3D &p_xform_B) {
Vector3 motion = p_A->get_linear_velocity() * p_step;
real_t mlen = motion.length();
@@ -177,33 +182,39 @@ bool GodotBodyPair3D::_test_ccd(real_t p_step, GodotBody3D *p_A, int p_shape_A,
// Let's say it should move more than 1/3 the size of the object in that axis.
bool fast_object = mlen > (max - min) * 0.3;
if (!fast_object) {
- return false;
+ return false; // moving slow enough that there's no chance of tunneling.
}
- // Going too fast in that direction.
+ // A is moving fast enough that tunneling might occur. See if it's really about to collide.
// Cast a segment from support in motion normal, in the same direction of motion by motion length.
- // Support is the worst case collision point, so real collision happened before.
- Vector3 s = p_A->get_shape(p_shape_A)->get_support(p_xform_A.basis.xform(mnormal).normalized());
+ // Support point will the farthest forward collision point along the movement vector.
+ // i.e. the point that should hit B first if any collision does occur.
+
+ // convert mnormal into body A's local xform because get_support requires (and returns) local coordinates.
+ Vector3 s = p_A->get_shape(p_shape_A)->get_support(p_xform_A.basis.xform_inv(mnormal).normalized());
Vector3 from = p_xform_A.xform(s);
Vector3 to = from + motion;
Transform3D from_inv = p_xform_B.affine_inverse();
- // Start from a little inside the bounding box.
- Vector3 local_from = from_inv.xform(from - mnormal * mlen * 0.1);
+ // Back up 10% of the per-frame motion behind the support point and use that as the beginning of our cast.
+ // At high speeds, this may mean we're actually casting from well behind the body instead of inside it, which is odd. But it still works out.
+ Vector3 local_from = from_inv.xform(from - motion * 0.1);
Vector3 local_to = from_inv.xform(to);
Vector3 rpos, rnorm;
if (!p_B->get_shape(p_shape_B)->intersect_segment(local_from, local_to, rpos, rnorm, true)) {
+ // there was no hit. Since the segment is the length of per-frame motion, this means the bodies will not
+ // actually collide yet on next frame. We'll probably check again next frame once they're closer.
return false;
}
- // Shorten the linear velocity so it does not hit, but gets close enough,
- // next frame will hit softly or soft enough.
+ // Shorten the linear velocity so it will collide next frame.
Vector3 hitpos = p_xform_B.xform(rpos);
- real_t newlen = hitpos.distance_to(from) - (max - min) * 0.01;
+ real_t newlen = hitpos.distance_to(from) + (max - min) * 0.01; // adding 1% of body length to the distance between collision and support point should cause body A's support point to arrive just within B's collider next frame.
+
p_A->set_linear_velocity((mnormal * newlen) / p_step);
return true;
diff --git a/servers/physics_3d/godot_collision_solver_3d_sat.cpp b/servers/physics_3d/godot_collision_solver_3d_sat.cpp
index 96253cb452..8c78957789 100644
--- a/servers/physics_3d/godot_collision_solver_3d_sat.cpp
+++ b/servers/physics_3d/godot_collision_solver_3d_sat.cpp
@@ -1908,7 +1908,7 @@ static void _collision_cylinder_cylinder(const GodotShape3D *p_a, const Transfor
}
// Cylinder B end caps.
- if (!separator.test_axis(cylinder_A_axis.normalized())) {
+ if (!separator.test_axis(cylinder_B_axis.normalized())) {
return;
}
diff --git a/servers/physics_3d/godot_shape_3d.cpp b/servers/physics_3d/godot_shape_3d.cpp
index 1443cd166b..1a016fbc72 100644
--- a/servers/physics_3d/godot_shape_3d.cpp
+++ b/servers/physics_3d/godot_shape_3d.cpp
@@ -521,8 +521,9 @@ void GodotCapsuleShape3D::get_supports(const Vector3 &p_normal, int p_max, Vecto
Vector3 n = p_normal;
real_t d = n.y;
+ real_t h = height * 0.5 - radius; // half-height of the cylinder part
- if (Math::abs(d) < edge_support_threshold) {
+ if (h > 0 && Math::abs(d) < edge_support_threshold) {
// make it flat
n.y = 0.0;
n.normalize();
@@ -531,13 +532,10 @@ void GodotCapsuleShape3D::get_supports(const Vector3 &p_normal, int p_max, Vecto
r_amount = 2;
r_type = FEATURE_EDGE;
r_supports[0] = n;
- r_supports[0].y += height * 0.5 - radius;
+ r_supports[0].y += h;
r_supports[1] = n;
- r_supports[1].y -= height * 0.5 - radius;
-
+ r_supports[1].y -= h;
} else {
- real_t h = height * 0.5 - radius;
-
n *= radius;
n.y += (d > 0) ? h : -h;
r_amount = 1;
@@ -1998,7 +1996,7 @@ void GodotHeightMapShape3D::_get_cell(const Vector3 &p_point, int &r_x, int &r_y
Vector3 clamped_point(p_point);
clamped_point.x = CLAMP(p_point.x, pos_local.x, pos_local.x + shape_aabb.size.x);
clamped_point.y = CLAMP(p_point.y, pos_local.y, pos_local.y + shape_aabb.size.y);
- clamped_point.z = CLAMP(p_point.z, pos_local.z, pos_local.x + shape_aabb.size.z);
+ clamped_point.z = CLAMP(p_point.z, pos_local.z, pos_local.z + shape_aabb.size.z);
r_x = (clamped_point.x < 0.0) ? (clamped_point.x - 0.5) : (clamped_point.x + 0.5);
r_y = (clamped_point.y < 0.0) ? (clamped_point.y - 0.5) : (clamped_point.y + 0.5);
diff --git a/servers/physics_3d/godot_soft_body_3d.cpp b/servers/physics_3d/godot_soft_body_3d.cpp
index 77110c5fbc..31b6b9e12f 100644
--- a/servers/physics_3d/godot_soft_body_3d.cpp
+++ b/servers/physics_3d/godot_soft_body_3d.cpp
@@ -1011,7 +1011,6 @@ void GodotSoftBody3D::predict_motion(real_t p_delta) {
} break;
case PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE:
case PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE_COMBINE: {
- gravity = Vector3(0, 0, 0);
gravity = area_gravity;
gravity_done = area_gravity_mode == PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE;
} break;
diff --git a/servers/physics_3d/godot_step_3d.cpp b/servers/physics_3d/godot_step_3d.cpp
index bfedcd29c0..634523d0b9 100644
--- a/servers/physics_3d/godot_step_3d.cpp
+++ b/servers/physics_3d/godot_step_3d.cpp
@@ -111,7 +111,7 @@ void GodotStep3D::_populate_island_soft_body(GodotSoftBody3D *p_soft_body, Local
}
}
-void GodotStep3D::_setup_contraint(uint32_t p_constraint_index, void *p_userdata) {
+void GodotStep3D::_setup_constraint(uint32_t p_constraint_index, void *p_userdata) {
GodotConstraint3D *constraint = all_constraints[p_constraint_index];
constraint->setup(delta);
}
@@ -342,8 +342,8 @@ void GodotStep3D::step(GodotSpace3D *p_space, real_t p_delta) {
/* SETUP CONSTRAINTS / PROCESS COLLISIONS */
- uint32_t total_contraint_count = all_constraints.size();
- WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &GodotStep3D::_setup_contraint, nullptr, total_contraint_count, -1, true, SNAME("Physics3DConstraintSetup"));
+ uint32_t total_constraint_count = all_constraints.size();
+ WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &GodotStep3D::_setup_constraint, nullptr, total_constraint_count, -1, true, SNAME("Physics3DConstraintSetup"));
WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task);
{ //profile
diff --git a/servers/physics_3d/godot_step_3d.h b/servers/physics_3d/godot_step_3d.h
index 189487757f..a0854a720c 100644
--- a/servers/physics_3d/godot_step_3d.h
+++ b/servers/physics_3d/godot_step_3d.h
@@ -48,7 +48,7 @@ class GodotStep3D {
void _populate_island(GodotBody3D *p_body, LocalVector<GodotBody3D *> &p_body_island, LocalVector<GodotConstraint3D *> &p_constraint_island);
void _populate_island_soft_body(GodotSoftBody3D *p_soft_body, LocalVector<GodotBody3D *> &p_body_island, LocalVector<GodotConstraint3D *> &p_constraint_island);
- void _setup_contraint(uint32_t p_constraint_index, void *p_userdata = nullptr);
+ void _setup_constraint(uint32_t p_constraint_index, void *p_userdata = nullptr);
void _pre_solve_island(LocalVector<GodotConstraint3D *> &p_constraint_island) const;
void _solve_island(uint32_t p_island_index, void *p_userdata = nullptr);
void _check_suspend(const LocalVector<GodotBody3D *> &p_body_island) const;
diff --git a/servers/physics_server_2d.cpp b/servers/physics_server_2d.cpp
index 21be311637..20f23ae031 100644
--- a/servers/physics_server_2d.cpp
+++ b/servers/physics_server_2d.cpp
@@ -479,8 +479,8 @@ void PhysicsTestMotionParameters2D::set_exclude_bodies(const TypedArray<RID> &p_
}
}
-Array PhysicsTestMotionParameters2D::get_exclude_objects() const {
- Array exclude;
+TypedArray<uint64_t> PhysicsTestMotionParameters2D::get_exclude_objects() const {
+ TypedArray<uint64_t> exclude;
exclude.resize(parameters.exclude_objects.size());
int object_index = 0;
@@ -491,7 +491,7 @@ Array PhysicsTestMotionParameters2D::get_exclude_objects() const {
return exclude;
}
-void PhysicsTestMotionParameters2D::set_exclude_objects(const Array &p_exclude) {
+void PhysicsTestMotionParameters2D::set_exclude_objects(const TypedArray<uint64_t> &p_exclude) {
for (int i = 0; i < p_exclude.size(); ++i) {
ObjectID object_id = p_exclude[i];
ERR_CONTINUE(object_id.is_null());
@@ -765,6 +765,9 @@ void PhysicsServer2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("joint_set_param", "joint", "param", "value"), &PhysicsServer2D::joint_set_param);
ClassDB::bind_method(D_METHOD("joint_get_param", "joint", "param"), &PhysicsServer2D::joint_get_param);
+ ClassDB::bind_method(D_METHOD("joint_disable_collisions_between_bodies", "joint", "disable"), &PhysicsServer2D::joint_disable_collisions_between_bodies);
+ ClassDB::bind_method(D_METHOD("joint_is_disabled_collisions_between_bodies", "joint"), &PhysicsServer2D::joint_is_disabled_collisions_between_bodies);
+
ClassDB::bind_method(D_METHOD("joint_make_pin", "joint", "anchor", "body_a", "body_b"), &PhysicsServer2D::joint_make_pin, DEFVAL(RID()));
ClassDB::bind_method(D_METHOD("joint_make_groove", "joint", "groove1_a", "groove2_a", "anchor_b", "body_a", "body_b"), &PhysicsServer2D::joint_make_groove, DEFVAL(RID()), DEFVAL(RID()));
ClassDB::bind_method(D_METHOD("joint_make_damped_spring", "joint", "anchor_a", "anchor_b", "body_a", "body_b"), &PhysicsServer2D::joint_make_damped_spring, DEFVAL(RID()));
diff --git a/servers/physics_server_2d.h b/servers/physics_server_2d.h
index 95425e72e8..8b4b5ae4de 100644
--- a/servers/physics_server_2d.h
+++ b/servers/physics_server_2d.h
@@ -732,8 +732,8 @@ public:
TypedArray<RID> get_exclude_bodies() const;
void set_exclude_bodies(const TypedArray<RID> &p_exclude);
- Array get_exclude_objects() const;
- void set_exclude_objects(const Array &p_exclude);
+ TypedArray<uint64_t> get_exclude_objects() const;
+ void set_exclude_objects(const TypedArray<uint64_t> &p_exclude);
bool is_recovery_as_collision_enabled() const { return parameters.recovery_as_collision; }
void set_recovery_as_collision_enabled(bool p_enabled) { parameters.recovery_as_collision = p_enabled; }
diff --git a/servers/physics_server_3d.cpp b/servers/physics_server_3d.cpp
index db21e1db06..25912e9aca 100644
--- a/servers/physics_server_3d.cpp
+++ b/servers/physics_server_3d.cpp
@@ -169,25 +169,25 @@ PhysicsDirectBodyState3D::PhysicsDirectBodyState3D() {}
///////////////////////////////////////////////////////
-void PhysicsRayQueryParameters3D::set_exclude(const Vector<RID> &p_exclude) {
+void PhysicsRayQueryParameters3D::set_exclude(const TypedArray<RID> &p_exclude) {
parameters.exclude.clear();
for (int i = 0; i < p_exclude.size(); i++) {
parameters.exclude.insert(p_exclude[i]);
}
}
-Vector<RID> PhysicsRayQueryParameters3D::get_exclude() const {
- Vector<RID> ret;
+TypedArray<RID> PhysicsRayQueryParameters3D::get_exclude() const {
+ TypedArray<RID> ret;
ret.resize(parameters.exclude.size());
int idx = 0;
for (const RID &E : parameters.exclude) {
- ret.write[idx++] = E;
+ ret[idx++] = E;
}
return ret;
}
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_static_method("PhysicsRayQueryParameters3D", D_METHOD("create", "from", "to", "collision_mask", "exclude"), &PhysicsRayQueryParameters3D::create, DEFVAL(UINT32_MAX), DEFVAL(TypedArray<RID>()));
ClassDB::bind_method(D_METHOD("set_from", "from"), &PhysicsRayQueryParameters3D::set_from);
ClassDB::bind_method(D_METHOD("get_from"), &PhysicsRayQueryParameters3D::get_from);
@@ -225,7 +225,7 @@ 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> PhysicsRayQueryParameters3D::create(Vector3 p_from, Vector3 p_to, uint32_t p_mask, const TypedArray<RID> &p_exclude) {
Ref<PhysicsRayQueryParameters3D> params;
params.instantiate();
params->set_from(p_from);
@@ -235,19 +235,19 @@ Ref<PhysicsRayQueryParameters3D> PhysicsRayQueryParameters3D::create(Vector3 p_f
return params;
}
-void PhysicsPointQueryParameters3D::set_exclude(const Vector<RID> &p_exclude) {
+void PhysicsPointQueryParameters3D::set_exclude(const TypedArray<RID> &p_exclude) {
parameters.exclude.clear();
for (int i = 0; i < p_exclude.size(); i++) {
parameters.exclude.insert(p_exclude[i]);
}
}
-Vector<RID> PhysicsPointQueryParameters3D::get_exclude() const {
- Vector<RID> ret;
+TypedArray<RID> PhysicsPointQueryParameters3D::get_exclude() const {
+ TypedArray<RID> ret;
ret.resize(parameters.exclude.size());
int idx = 0;
for (const RID &E : parameters.exclude) {
- ret.write[idx++] = E;
+ ret[idx++] = E;
}
return ret;
}
@@ -290,19 +290,19 @@ void PhysicsShapeQueryParameters3D::set_shape_rid(const RID &p_shape) {
}
}
-void PhysicsShapeQueryParameters3D::set_exclude(const Vector<RID> &p_exclude) {
+void PhysicsShapeQueryParameters3D::set_exclude(const TypedArray<RID> &p_exclude) {
parameters.exclude.clear();
for (int i = 0; i < p_exclude.size(); i++) {
parameters.exclude.insert(p_exclude[i]);
}
}
-Vector<RID> PhysicsShapeQueryParameters3D::get_exclude() const {
- Vector<RID> ret;
+TypedArray<RID> PhysicsShapeQueryParameters3D::get_exclude() const {
+ TypedArray<RID> ret;
ret.resize(parameters.exclude.size());
int idx = 0;
for (const RID &E : parameters.exclude) {
- ret.write[idx++] = E;
+ ret[idx++] = E;
}
return ret;
}
@@ -482,37 +482,37 @@ void PhysicsDirectSpaceState3D::_bind_methods() {
///////////////////////////////
-Vector<RID> PhysicsTestMotionParameters3D::get_exclude_bodies() const {
- Vector<RID> exclude;
+TypedArray<RID> PhysicsTestMotionParameters3D::get_exclude_bodies() const {
+ TypedArray<RID> exclude;
exclude.resize(parameters.exclude_bodies.size());
int body_index = 0;
- for (RID body : parameters.exclude_bodies) {
- exclude.write[body_index++] = body;
+ for (const RID &body : parameters.exclude_bodies) {
+ exclude[body_index++] = body;
}
return exclude;
}
-void PhysicsTestMotionParameters3D::set_exclude_bodies(const Vector<RID> &p_exclude) {
- for (RID body : p_exclude) {
- parameters.exclude_bodies.insert(body);
+void PhysicsTestMotionParameters3D::set_exclude_bodies(const TypedArray<RID> &p_exclude) {
+ for (int i = 0; i < p_exclude.size(); i++) {
+ parameters.exclude_bodies.insert(p_exclude[i]);
}
}
-Array PhysicsTestMotionParameters3D::get_exclude_objects() const {
- Array exclude;
+TypedArray<uint64_t> PhysicsTestMotionParameters3D::get_exclude_objects() const {
+ TypedArray<uint64_t> exclude;
exclude.resize(parameters.exclude_objects.size());
int object_index = 0;
- for (ObjectID object_id : parameters.exclude_objects) {
+ for (const ObjectID &object_id : parameters.exclude_objects) {
exclude[object_index++] = object_id;
}
return exclude;
}
-void PhysicsTestMotionParameters3D::set_exclude_objects(const Array &p_exclude) {
+void PhysicsTestMotionParameters3D::set_exclude_objects(const TypedArray<uint64_t> &p_exclude) {
for (int i = 0; i < p_exclude.size(); ++i) {
ObjectID object_id = p_exclude[i];
ERR_CONTINUE(object_id.is_null());
@@ -943,6 +943,9 @@ void PhysicsServer3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("joint_set_solver_priority", "joint", "priority"), &PhysicsServer3D::joint_set_solver_priority);
ClassDB::bind_method(D_METHOD("joint_get_solver_priority", "joint"), &PhysicsServer3D::joint_get_solver_priority);
+ ClassDB::bind_method(D_METHOD("joint_disable_collisions_between_bodies", "joint", "disable"), &PhysicsServer3D::joint_disable_collisions_between_bodies);
+ ClassDB::bind_method(D_METHOD("joint_is_disabled_collisions_between_bodies", "joint"), &PhysicsServer3D::joint_is_disabled_collisions_between_bodies);
+
ClassDB::bind_method(D_METHOD("joint_make_generic_6dof", "joint", "body_A", "local_ref_A", "body_B", "local_ref_B"), &PhysicsServer3D::joint_make_generic_6dof);
ClassDB::bind_method(D_METHOD("generic_6dof_joint_set_param", "joint", "axis", "param", "value"), &PhysicsServer3D::generic_6dof_joint_set_param);
diff --git a/servers/physics_server_3d.h b/servers/physics_server_3d.h
index 87877ad52d..ca1ff57c99 100644
--- a/servers/physics_server_3d.h
+++ b/servers/physics_server_3d.h
@@ -210,8 +210,8 @@ public:
class PhysicsServer3DRenderingServerHandler : public Object {
GDCLASS(PhysicsServer3DRenderingServerHandler, Object)
protected:
- GDVIRTUAL2(_set_vertex, int, GDNativeConstPtr<void>)
- GDVIRTUAL2(_set_normal, int, GDNativeConstPtr<void>)
+ GDVIRTUAL2(_set_vertex, int, GDExtensionConstPtr<void>)
+ GDVIRTUAL2(_set_normal, int, GDExtensionConstPtr<void>)
GDVIRTUAL1(_set_aabb, const AABB &)
static void _bind_methods();
@@ -822,7 +822,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);
+ static Ref<PhysicsRayQueryParameters3D> create(Vector3 p_from, Vector3 p_to, uint32_t p_mask, const TypedArray<RID> &p_exclude);
const PhysicsDirectSpaceState3D::RayParameters &get_parameters() const { return parameters; }
void set_from(const Vector3 &p_from) { parameters.from = p_from; }
@@ -846,8 +846,8 @@ public:
void set_hit_back_faces(bool p_enable) { parameters.hit_back_faces = p_enable; }
bool is_hit_back_faces_enabled() const { return parameters.hit_back_faces; }
- void set_exclude(const Vector<RID> &p_exclude);
- Vector<RID> get_exclude() const;
+ void set_exclude(const TypedArray<RID> &p_exclude);
+ TypedArray<RID> get_exclude() const;
};
class PhysicsPointQueryParameters3D : public RefCounted {
@@ -873,8 +873,8 @@ public:
void set_collide_with_areas(bool p_enable) { parameters.collide_with_areas = p_enable; }
bool is_collide_with_areas_enabled() const { return parameters.collide_with_areas; }
- void set_exclude(const Vector<RID> &p_exclude);
- Vector<RID> get_exclude() const;
+ void set_exclude(const TypedArray<RID> &p_exclude);
+ TypedArray<RID> get_exclude() const;
};
class PhysicsShapeQueryParameters3D : public RefCounted {
@@ -914,8 +914,8 @@ public:
void set_collide_with_areas(bool p_enable) { parameters.collide_with_areas = p_enable; }
bool is_collide_with_areas_enabled() const { return parameters.collide_with_areas; }
- void set_exclude(const Vector<RID> &p_exclude);
- Vector<RID> get_exclude() const;
+ void set_exclude(const TypedArray<RID> &p_exclude);
+ TypedArray<RID> get_exclude() const;
};
class PhysicsTestMotionParameters3D : public RefCounted {
@@ -944,11 +944,11 @@ public:
bool is_collide_separation_ray_enabled() const { return parameters.collide_separation_ray; }
void set_collide_separation_ray_enabled(bool p_enabled) { parameters.collide_separation_ray = p_enabled; }
- Vector<RID> get_exclude_bodies() const;
- void set_exclude_bodies(const Vector<RID> &p_exclude);
+ TypedArray<RID> get_exclude_bodies() const;
+ void set_exclude_bodies(const TypedArray<RID> &p_exclude);
- Array get_exclude_objects() const;
- void set_exclude_objects(const Array &p_exclude);
+ TypedArray<uint64_t> get_exclude_objects() const;
+ void set_exclude_objects(const TypedArray<uint64_t> &p_exclude);
bool is_recovery_as_collision_enabled() const { return parameters.recovery_as_collision; }
void set_recovery_as_collision_enabled(bool p_enabled) { parameters.recovery_as_collision = p_enabled; }
diff --git a/servers/rendering/dummy/rasterizer_scene_dummy.h b/servers/rendering/dummy/rasterizer_scene_dummy.h
index bc8f7c523b..918f5c1fb7 100644
--- a/servers/rendering/dummy/rasterizer_scene_dummy.h
+++ b/servers/rendering/dummy/rasterizer_scene_dummy.h
@@ -49,6 +49,7 @@ public:
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_pivot_data(float p_sorting_offset, bool p_use_aabb_center) 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 {}
@@ -112,7 +113,6 @@ public:
/* ENVIRONMENT API */
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_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality) override {}
diff --git a/servers/rendering/dummy/storage/light_storage.h b/servers/rendering/dummy/storage/light_storage.h
index 13c342d823..960f5a867a 100644
--- a/servers/rendering/dummy/storage/light_storage.h
+++ b/servers/rendering/dummy/storage/light_storage.h
@@ -135,6 +135,7 @@ public:
virtual bool reflection_probe_instance_needs_redraw(RID p_instance) override { return false; }
virtual bool reflection_probe_instance_has_reflection(RID p_instance) override { return false; }
virtual bool reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas) override { return false; }
+ virtual Ref<RenderSceneBuffers> reflection_probe_atlas_get_render_buffers(RID p_reflection_atlas) override { return Ref<RenderSceneBuffers>(); }
virtual bool reflection_probe_instance_postprocess_step(RID p_instance) override { return true; }
/* LIGHTMAP CAPTURE */
diff --git a/servers/rendering/dummy/storage/mesh_storage.cpp b/servers/rendering/dummy/storage/mesh_storage.cpp
index adf736eee3..52de998835 100644
--- a/servers/rendering/dummy/storage/mesh_storage.cpp
+++ b/servers/rendering/dummy/storage/mesh_storage.cpp
@@ -56,3 +56,10 @@ void MeshStorage::mesh_free(RID p_rid) {
mesh_owner.free(p_rid);
}
+
+void MeshStorage::mesh_clear(RID p_mesh) {
+ DummyMesh *m = mesh_owner.get_or_null(p_mesh);
+ ERR_FAIL_COND(!m);
+
+ m->surfaces.clear();
+}
diff --git a/servers/rendering/dummy/storage/mesh_storage.h b/servers/rendering/dummy/storage/mesh_storage.h
index 4399f4ab66..28fe8cb80d 100644
--- a/servers/rendering/dummy/storage/mesh_storage.h
+++ b/servers/rendering/dummy/storage/mesh_storage.h
@@ -116,7 +116,7 @@ public:
virtual AABB mesh_get_aabb(RID p_mesh, RID p_skeleton = RID()) override { return AABB(); }
virtual void mesh_set_shadow_mesh(RID p_mesh, RID p_shadow_mesh) override {}
- virtual void mesh_clear(RID p_mesh) override {}
+ virtual void mesh_clear(RID p_mesh) override;
/* MESH INSTANCE */
diff --git a/servers/rendering/dummy/storage/particles_storage.h b/servers/rendering/dummy/storage/particles_storage.h
index 7cee55922d..beedff0a76 100644
--- a/servers/rendering/dummy/storage/particles_storage.h
+++ b/servers/rendering/dummy/storage/particles_storage.h
@@ -89,8 +89,6 @@ public:
virtual void particles_add_collision(RID p_particles, RID p_instance) override {}
virtual void particles_remove_collision(RID p_particles, RID p_instance) override {}
- virtual void particles_set_canvas_sdf_collision(RID p_particles, bool p_enable, const Transform2D &p_xform, const Rect2 &p_to_screen, RID p_texture) override {}
-
virtual void update_particles() override {}
/* PARTICLES COLLISION */
@@ -111,7 +109,6 @@ public:
virtual void particles_collision_set_height_field_resolution(RID p_particles_collision, RS::ParticlesCollisionHeightfieldResolution p_resolution) override {}
virtual AABB particles_collision_get_aabb(RID p_particles_collision) const override { return AABB(); }
virtual bool particles_collision_is_heightfield(RID p_particles_collision) const override { return false; }
- virtual RID particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const override { return RID(); }
virtual RID particles_collision_instance_create(RID p_collision) override { return RID(); }
virtual void particles_collision_instance_free(RID p_rid) override {}
diff --git a/servers/rendering/dummy/storage/texture_storage.h b/servers/rendering/dummy/storage/texture_storage.h
index a17d734e10..dd89504f38 100644
--- a/servers/rendering/dummy/storage/texture_storage.h
+++ b/servers/rendering/dummy/storage/texture_storage.h
@@ -80,6 +80,7 @@ public:
virtual void texture_free(RID p_rid) override {
// delete the texture
DummyTexture *texture = texture_owner.get_or_null(p_rid);
+ ERR_FAIL_COND(!texture);
texture_owner.free(p_rid);
memdelete(texture);
};
diff --git a/servers/rendering/renderer_canvas_cull.cpp b/servers/rendering/renderer_canvas_cull.cpp
index 16d382a5f3..6be0419d98 100644
--- a/servers/rendering/renderer_canvas_cull.cpp
+++ b/servers/rendering/renderer_canvas_cull.cpp
@@ -275,12 +275,12 @@ void RendererCanvasCull::_cull_canvas_item(Item *p_canvas_item, const Transform2
if (ci->clip) {
if (p_canvas_clip != nullptr) {
ci->final_clip_rect = p_canvas_clip->final_clip_rect.intersection(global_rect);
- if (ci->final_clip_rect == Rect2()) {
- // Clip rects do not intersect, so don't draw this item.
- return;
- }
} else {
- ci->final_clip_rect = global_rect;
+ ci->final_clip_rect = p_clip_rect.intersection(global_rect);
+ }
+ if (ci->final_clip_rect.size.width < 0.5 || ci->final_clip_rect.size.height < 0.5) {
+ // The clip rect area is 0, so don't draw the item.
+ return;
}
ci->final_clip_rect.position = ci->final_clip_rect.position.round();
ci->final_clip_rect.size = ci->final_clip_rect.size.round();
@@ -1075,18 +1075,36 @@ void RendererCanvasCull::canvas_item_add_polyline(RID p_item, const Vector<Point
void RendererCanvasCull::canvas_item_add_multiline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width) {
ERR_FAIL_COND(p_points.size() < 2);
- Item *canvas_item = canvas_item_owner.get_or_null(p_item);
- ERR_FAIL_COND(!canvas_item);
-
- Item::CommandPolygon *pline = canvas_item->alloc_command<Item::CommandPolygon>();
- ERR_FAIL_COND(!pline);
- if (true || p_width <= 1) {
-#define TODO make thick lines possible
+ // TODO: `canvas_item_add_line`(`multiline`, `polyline`) share logic, should factor out.
+ if (p_width <= 1) {
+ Item *canvas_item = canvas_item_owner.get_or_null(p_item);
+ ERR_FAIL_COND(!canvas_item);
+ Item::CommandPolygon *pline = canvas_item->alloc_command<Item::CommandPolygon>();
+ ERR_FAIL_COND(!pline);
pline->primitive = RS::PRIMITIVE_LINES;
pline->polygon.create(Vector<int>(), p_points, p_colors);
} else {
+ if (p_colors.size() == 1) {
+ Color color = p_colors[0];
+ for (int i = 0; i < p_points.size() >> 1; i++) {
+ Vector2 from = p_points[i * 2 + 0];
+ Vector2 to = p_points[i * 2 + 1];
+
+ canvas_item_add_line(p_item, from, to, color, p_width);
+ }
+ } else if (p_colors.size() == p_points.size() >> 1) {
+ for (int i = 0; i < p_points.size() >> 1; i++) {
+ Color color = p_colors[i];
+ Vector2 from = p_points[i * 2 + 0];
+ Vector2 to = p_points[i * 2 + 1];
+
+ canvas_item_add_line(p_item, from, to, color, p_width);
+ }
+ } else {
+ ERR_FAIL_MSG("Length of p_colors is invalid.");
+ }
}
}
@@ -1167,7 +1185,7 @@ void RendererCanvasCull::canvas_item_add_texture_rect(RID p_item, const Rect2 &p
rect->texture = p_texture;
}
-void RendererCanvasCull::canvas_item_add_msdf_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate, int p_outline_size, float p_px_range) {
+void RendererCanvasCull::canvas_item_add_msdf_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate, int p_outline_size, float p_px_range, float p_scale) {
Item *canvas_item = canvas_item_owner.get_or_null(p_item);
ERR_FAIL_COND(!canvas_item);
@@ -1197,7 +1215,7 @@ void RendererCanvasCull::canvas_item_add_msdf_texture_rect_region(RID p_item, co
rect->flags ^= RendererCanvasRender::CANVAS_RECT_FLIP_V;
rect->source.size.y = -rect->source.size.y;
}
- rect->outline = p_outline_size;
+ rect->outline = (float)p_outline_size / p_scale / 4.0;
rect->px_range = p_px_range;
}
diff --git a/servers/rendering/renderer_canvas_cull.h b/servers/rendering/renderer_canvas_cull.h
index 198e1020f0..808c0acc35 100644
--- a/servers/rendering/renderer_canvas_cull.h
+++ b/servers/rendering/renderer_canvas_cull.h
@@ -228,7 +228,7 @@ public:
void canvas_item_add_circle(RID p_item, const Point2 &p_pos, float p_radius, const Color &p_color);
void canvas_item_add_texture_rect(RID p_item, const Rect2 &p_rect, RID p_texture, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false);
void canvas_item_add_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, bool p_clip_uv = false);
- void canvas_item_add_msdf_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), int p_outline_size = 0, float p_px_range = 1.0);
+ void canvas_item_add_msdf_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), int p_outline_size = 0, float p_px_range = 1.0, float p_scale = 1.0);
void canvas_item_add_lcd_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1));
void canvas_item_add_nine_patch(RID p_item, const Rect2 &p_rect, const Rect2 &p_source, RID p_texture, const Vector2 &p_topleft, const Vector2 &p_bottomright, RS::NinePatchAxisMode p_x_axis_mode = RS::NINE_PATCH_STRETCH, RS::NinePatchAxisMode p_y_axis_mode = RS::NINE_PATCH_STRETCH, bool p_draw_center = true, const Color &p_modulate = Color(1, 1, 1));
void canvas_item_add_primitive(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, RID p_texture, float p_width = 1.0);
diff --git a/servers/rendering/renderer_canvas_render.cpp b/servers/rendering/renderer_canvas_render.cpp
index 623f0c647b..07394b49a3 100644
--- a/servers/rendering/renderer_canvas_render.cpp
+++ b/servers/rendering/renderer_canvas_render.cpp
@@ -32,7 +32,7 @@
#include "servers/rendering/rendering_server_globals.h"
const Rect2 &RendererCanvasRender::Item::get_rect() const {
- if (custom_rect || (!rect_dirty && !update_when_visible)) {
+ if (custom_rect || (!rect_dirty && !update_when_visible && skeleton == RID())) {
return rect;
}
@@ -80,7 +80,7 @@ const Rect2 &RendererCanvasRender::Item::get_rect() const {
} break;
case Item::Command::TYPE_MESH: {
const Item::CommandMesh *mesh = static_cast<const Item::CommandMesh *>(c);
- AABB aabb = RSG::mesh_storage->mesh_get_aabb(mesh->mesh, RID());
+ AABB aabb = RSG::mesh_storage->mesh_get_aabb(mesh->mesh, skeleton);
r = Rect2(aabb.position.x, aabb.position.y, aabb.size.x, aabb.size.y);
diff --git a/servers/rendering/renderer_geometry_instance.cpp b/servers/rendering/renderer_geometry_instance.cpp
index 675659f4c8..f4681916f4 100644
--- a/servers/rendering/renderer_geometry_instance.cpp
+++ b/servers/rendering/renderer_geometry_instance.cpp
@@ -80,6 +80,11 @@ void RenderGeometryInstanceBase::set_transform(const Transform3D &p_transform, c
lod_model_scale = max_scale;
}
+void RenderGeometryInstanceBase::set_pivot_data(float p_sorting_offset, bool p_use_aabb_center) {
+ sorting_offset = p_sorting_offset;
+ use_aabb_center = p_use_aabb_center;
+}
+
void RenderGeometryInstanceBase::set_lod_bias(float p_lod_bias) {
lod_bias = p_lod_bias;
}
diff --git a/servers/rendering/renderer_geometry_instance.h b/servers/rendering/renderer_geometry_instance.h
index fecb9878c2..37fde9e1f6 100644
--- a/servers/rendering/renderer_geometry_instance.h
+++ b/servers/rendering/renderer_geometry_instance.h
@@ -50,6 +50,7 @@ public:
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_pivot_data(float p_sorting_offset, bool p_use_aabb_center) = 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;
@@ -86,11 +87,13 @@ public:
RID mesh_instance;
Transform3D transform;
- bool mirror = false; // move into data?
- AABB transformed_aabb; //needed for LOD
+ bool mirror = false;
+ AABB transformed_aabb;
bool non_uniform_scale = false;
float lod_model_scale = 1.0;
float lod_bias = 0.0;
+ float sorting_offset = 0.0;
+ bool use_aabb_center = true;
uint32_t layer_mask = 1;
@@ -133,6 +136,7 @@ public:
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_pivot_data(float p_sorting_offset, bool p_use_aabb_center) 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;
diff --git a/servers/rendering/renderer_rd/SCsub b/servers/rendering/renderer_rd/SCsub
index 10b83dca11..a27439e931 100644
--- a/servers/rendering/renderer_rd/SCsub
+++ b/servers/rendering/renderer_rd/SCsub
@@ -9,4 +9,5 @@ SConscript("environment/SCsub")
SConscript("forward_clustered/SCsub")
SConscript("forward_mobile/SCsub")
SConscript("shaders/SCsub")
+SConscript("spirv-reflect/SCsub")
SConscript("storage_rd/SCsub")
diff --git a/servers/rendering/renderer_rd/effects/copy_effects.cpp b/servers/rendering/renderer_rd/effects/copy_effects.cpp
index 27f977a80b..9fda54a34d 100644
--- a/servers/rendering/renderer_rd/effects/copy_effects.cpp
+++ b/servers/rendering/renderer_rd/effects/copy_effects.cpp
@@ -56,6 +56,7 @@ CopyEffects::CopyEffects(bool p_prefer_raster_effects) {
blur_modes.push_back("\n#define MODE_GAUSSIAN_GLOW\n"); // BLUR_MODE_GAUSSIAN_GLOW
blur_modes.push_back("\n#define MODE_GAUSSIAN_GLOW\n#define GLOW_USE_AUTO_EXPOSURE\n"); // BLUR_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE
blur_modes.push_back("\n#define MODE_COPY\n"); // BLUR_MODE_COPY
+ blur_modes.push_back("\n#define MODE_SET_COLOR\n"); // BLUR_MODE_SET_COLOR
blur_raster.shader.initialize(blur_modes);
memset(&blur_raster.push_constant, 0, sizeof(BlurRasterPushConstant));
@@ -105,6 +106,7 @@ CopyEffects::CopyEffects(bool p_prefer_raster_effects) {
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_modes.push_back("\n#define MODE_SET_COLOR\n"); // COPY_TO_FB_SET_COLOR
copy_to_fb.shader.initialize(copy_modes);
@@ -508,16 +510,18 @@ void CopyEffects::copy_to_atlas_fb(RID p_source_rd_texture, RID p_dest_framebuff
memset(&copy_to_fb.push_constant, 0, sizeof(CopyToFbPushConstant));
- copy_to_fb.push_constant.use_section = true;
+ copy_to_fb.push_constant.flags |= COPY_TO_FB_FLAG_USE_SECTION;
copy_to_fb.push_constant.section[0] = p_uv_rect.position.x;
copy_to_fb.push_constant.section[1] = p_uv_rect.position.y;
copy_to_fb.push_constant.section[2] = p_uv_rect.size.x;
copy_to_fb.push_constant.section[3] = p_uv_rect.size.y;
if (p_flip_y) {
- copy_to_fb.push_constant.flip_y = true;
+ copy_to_fb.push_constant.flags |= COPY_TO_FB_FLAG_FLIP_Y;
}
+ copy_to_fb.push_constant.luminance_multiplier = 1.0;
+
// setup our uniforms
RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
@@ -535,25 +539,35 @@ void CopyEffects::copy_to_atlas_fb(RID p_source_rd_texture, RID p_dest_framebuff
RD::get_singleton()->draw_list_draw(draw_list, true);
}
-void CopyEffects::copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y, bool p_force_luminance, bool p_alpha_to_zero, bool p_srgb, RID p_secondary, bool p_multiview) {
+void CopyEffects::copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y, bool p_force_luminance, bool p_alpha_to_zero, bool p_srgb, RID p_secondary, bool p_multiview, bool p_alpha_to_one, bool p_linear) {
UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
ERR_FAIL_NULL(uniform_set_cache);
MaterialStorage *material_storage = MaterialStorage::get_singleton();
ERR_FAIL_NULL(material_storage);
memset(&copy_to_fb.push_constant, 0, sizeof(CopyToFbPushConstant));
+ copy_to_fb.push_constant.luminance_multiplier = 1.0;
if (p_flip_y) {
- copy_to_fb.push_constant.flip_y = true;
+ copy_to_fb.push_constant.flags |= COPY_TO_FB_FLAG_FLIP_Y;
}
if (p_force_luminance) {
- copy_to_fb.push_constant.force_luminance = true;
+ copy_to_fb.push_constant.flags |= COPY_TO_FB_FLAG_FORCE_LUMINANCE;
}
if (p_alpha_to_zero) {
- copy_to_fb.push_constant.alpha_to_zero = true;
+ copy_to_fb.push_constant.flags |= COPY_TO_FB_FLAG_ALPHA_TO_ZERO;
}
if (p_srgb) {
- copy_to_fb.push_constant.srgb = true;
+ copy_to_fb.push_constant.flags |= COPY_TO_FB_FLAG_SRGB;
+ }
+ if (p_alpha_to_one) {
+ copy_to_fb.push_constant.flags |= COPY_TO_FB_FLAG_ALPHA_TO_ONE;
+ }
+ if (p_linear) {
+ // Used for copying to a linear buffer. In the mobile renderer we divide the contents of the linear buffer
+ // to allow for a wider effective range.
+ copy_to_fb.push_constant.flags |= COPY_TO_FB_FLAG_LINEAR;
+ copy_to_fb.push_constant.luminance_multiplier = prefer_raster_effects ? 2.0 : 1.0;
}
// setup our uniforms
@@ -608,15 +622,13 @@ void CopyEffects::copy_raster(RID p_source_texture, RID p_dest_framebuffer) {
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[BLUR_MODE_COPY].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_texture), 0);
RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array());
-
- memset(&blur_raster.push_constant, 0, sizeof(BlurRasterPushConstant));
RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur_raster.push_constant, sizeof(BlurRasterPushConstant));
RD::get_singleton()->draw_list_draw(draw_list, true);
RD::get_singleton()->draw_list_end();
}
-void CopyEffects::gaussian_blur(RID p_source_rd_texture, RID p_texture, const Rect2i &p_region, bool p_8bit_dst) {
+void CopyEffects::gaussian_blur(RID p_source_rd_texture, RID p_texture, const Rect2i &p_region, const Size2i &p_size, bool p_8bit_dst) {
ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use the compute version of the gaussian blur with the mobile renderer.");
UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
@@ -628,8 +640,10 @@ void CopyEffects::gaussian_blur(RID p_source_rd_texture, RID p_texture, const Re
copy.push_constant.section[0] = p_region.position.x;
copy.push_constant.section[1] = p_region.position.y;
- copy.push_constant.section[2] = p_region.size.width;
- copy.push_constant.section[3] = p_region.size.height;
+ copy.push_constant.target[0] = p_region.position.x;
+ copy.push_constant.target[1] = p_region.position.y;
+ copy.push_constant.section[2] = p_size.width;
+ copy.push_constant.section[3] = p_size.height;
// setup our uniforms
RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
@@ -641,7 +655,6 @@ void CopyEffects::gaussian_blur(RID p_source_rd_texture, RID p_texture, const Re
RID shader = copy.shader.version_get_shader(copy.shader_version, mode);
ERR_FAIL_COND(shader.is_null());
- //HORIZONTAL
RD::DrawListID compute_list = RD::get_singleton()->compute_list_begin();
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[mode]);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0);
@@ -654,7 +667,44 @@ void CopyEffects::gaussian_blur(RID p_source_rd_texture, RID p_texture, const Re
RD::get_singleton()->compute_list_end();
}
-void CopyEffects::gaussian_glow(RID p_source_rd_texture, RID p_back_texture, const Size2i &p_size, float p_strength, bool p_high_quality, bool p_first_pass, float p_luminance_cap, float p_exposure, float p_bloom, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, RID p_auto_exposure, float p_auto_exposure_scale) {
+void CopyEffects::gaussian_blur_raster(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_region, const Size2i &p_size) {
+ ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use the raster version of the gaussian blur with the clustered renderer.");
+
+ 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 dest_framebuffer = FramebufferCacheRD::get_singleton()->get_cache(p_dest_texture);
+
+ memset(&blur_raster.push_constant, 0, sizeof(BlurRasterPushConstant));
+
+ BlurRasterMode blur_mode = BLUR_MODE_GAUSSIAN_BLUR;
+
+ blur_raster.push_constant.pixel_size[0] = 1.0 / float(p_size.x);
+ blur_raster.push_constant.pixel_size[1] = 1.0 / float(p_size.y);
+
+ // setup our uniforms
+ RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, 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 }));
+
+ RID shader = blur_raster.shader.version_get_shader(blur_raster.shader_version, blur_mode);
+ ERR_FAIL_COND(shader.is_null());
+
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
+ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[blur_mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(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, &blur_raster.push_constant, sizeof(BlurRasterPushConstant));
+
+ RD::get_singleton()->draw_list_draw(draw_list, true);
+ RD::get_singleton()->draw_list_end();
+}
+
+void CopyEffects::gaussian_glow(RID p_source_rd_texture, RID p_back_texture, const Size2i &p_size, float p_strength, bool p_first_pass, float p_luminance_cap, float p_exposure, float p_bloom, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, RID p_auto_exposure, float p_auto_exposure_scale) {
ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use the compute version of the gaussian glow with the mobile renderer.");
UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
@@ -698,14 +748,14 @@ void CopyEffects::gaussian_glow(RID p_source_rd_texture, RID p_back_texture, con
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_auto_exposure), 1);
}
- copy.push_constant.flags = base_flags | (p_first_pass ? COPY_FLAG_GLOW_FIRST_PASS : 0) | (p_high_quality ? COPY_FLAG_HIGH_QUALITY_GLOW : 0);
+ copy.push_constant.flags = base_flags | (p_first_pass ? COPY_FLAG_GLOW_FIRST_PASS : 0);
RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy.push_constant, sizeof(CopyPushConstant));
RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_size.width, p_size.height, 1);
RD::get_singleton()->compute_list_end();
}
-void CopyEffects::gaussian_glow_raster(RID p_source_rd_texture, RID p_half_texture, RID p_dest_texture, float p_luminance_multiplier, const Size2i &p_size, float p_strength, bool p_high_quality, bool p_first_pass, float p_luminance_cap, float p_exposure, float p_bloom, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, RID p_auto_exposure, float p_auto_exposure_scale) {
+void CopyEffects::gaussian_glow_raster(RID p_source_rd_texture, RID p_half_texture, RID p_dest_texture, float p_luminance_multiplier, const Size2i &p_size, float p_strength, bool p_first_pass, float p_luminance_cap, float p_exposure, float p_bloom, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, RID p_auto_exposure, float p_auto_exposure_scale) {
ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use the raster version of the gaussian glow with the clustered renderer.");
UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
@@ -882,6 +932,36 @@ void CopyEffects::set_color(RID p_dest_texture, const Color &p_color, const Rect
RD::get_singleton()->compute_list_end();
}
+void CopyEffects::set_color_raster(RID p_dest_texture, const Color &p_color, const Rect2i &p_region) {
+ ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use the raster version of the set_color shader with the clustered renderer.");
+
+ UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
+ ERR_FAIL_NULL(uniform_set_cache);
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+ ERR_FAIL_NULL(material_storage);
+
+ memset(&copy_to_fb.push_constant, 0, sizeof(CopyToFbPushConstant));
+
+ copy_to_fb.push_constant.set_color[0] = p_color.r;
+ copy_to_fb.push_constant.set_color[1] = p_color.g;
+ copy_to_fb.push_constant.set_color[2] = p_color.b;
+ copy_to_fb.push_constant.set_color[3] = p_color.a;
+
+ RID dest_framebuffer = FramebufferCacheRD::get_singleton()->get_cache(p_dest_texture);
+
+ CopyToFBMode mode = COPY_TO_FB_SET_COLOR;
+
+ RID shader = copy_to_fb.shader.version_get_shader(copy_to_fb.shader_version, mode);
+ ERR_FAIL_COND(shader.is_null());
+
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD, Vector<Color>(), 1.0, 0, p_region);
+ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, copy_to_fb.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(dest_framebuffer)));
+ 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, &copy_to_fb.push_constant, sizeof(CopyToFbPushConstant));
+ RD::get_singleton()->draw_list_draw(draw_list, true);
+ RD::get_singleton()->draw_list_end();
+}
+
void CopyEffects::copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dst_framebuffer, const Rect2 &p_rect, const Vector2 &p_dst_size, float p_z_near, float p_z_far, bool p_dp_flip) {
UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
ERR_FAIL_NULL(uniform_set_cache);
@@ -1075,7 +1155,8 @@ void CopyEffects::cubemap_roughness(RID p_source_rd_texture, RID p_dest_texture,
memset(&roughness.push_constant, 0, sizeof(CubemapRoughnessPushConstant));
roughness.push_constant.face_id = p_face_id > 9 ? 0 : p_face_id;
- roughness.push_constant.roughness = p_roughness * p_roughness; // Shader expects roughness, not perceptual roughness, so multiply before passing in.
+ // Remap to perceptual-roughness^2 to create more detail in lower mips and match the mapping of cubemap_filter.
+ roughness.push_constant.roughness = p_roughness * p_roughness;
roughness.push_constant.sample_count = p_sample_count;
roughness.push_constant.use_direct_write = p_roughness == 0.0;
roughness.push_constant.face_size = p_size;
diff --git a/servers/rendering/renderer_rd/effects/copy_effects.h b/servers/rendering/renderer_rd/effects/copy_effects.h
index 0ddb60ebef..a0904f0b8e 100644
--- a/servers/rendering/renderer_rd/effects/copy_effects.h
+++ b/servers/rendering/renderer_rd/effects/copy_effects.h
@@ -63,6 +63,8 @@ private:
BLUR_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE,
BLUR_MODE_COPY,
+ BLUR_MODE_SET_COLOR,
+
BLUR_MODE_MAX
};
@@ -130,8 +132,7 @@ private:
COPY_FLAG_FLIP_Y = (1 << 5),
COPY_FLAG_FORCE_LUMINANCE = (1 << 6),
COPY_FLAG_ALL_SOURCE = (1 << 7),
- COPY_FLAG_HIGH_QUALITY_GLOW = (1 << 8),
- COPY_FLAG_ALPHA_TO_ONE = (1 << 9),
+ COPY_FLAG_ALPHA_TO_ONE = (1 << 8),
};
struct CopyPushConstant {
@@ -174,19 +175,28 @@ private:
COPY_TO_FB_MULTIVIEW,
COPY_TO_FB_MULTIVIEW_WITH_DEPTH,
+
+ COPY_TO_FB_SET_COLOR,
COPY_TO_FB_MAX,
};
+ enum CopyToFBFlags {
+ COPY_TO_FB_FLAG_FLIP_Y = (1 << 0),
+ COPY_TO_FB_FLAG_USE_SECTION = (1 << 1),
+ COPY_TO_FB_FLAG_FORCE_LUMINANCE = (1 << 2),
+ COPY_TO_FB_FLAG_ALPHA_TO_ZERO = (1 << 3),
+ COPY_TO_FB_FLAG_SRGB = (1 << 4),
+ COPY_TO_FB_FLAG_ALPHA_TO_ONE = (1 << 5),
+ COPY_TO_FB_FLAG_LINEAR = (1 << 6),
+ };
+
struct CopyToFbPushConstant {
float section[4];
float pixel_size[2];
- uint32_t flip_y;
- uint32_t use_section;
+ float luminance_multiplier;
+ uint32_t flags;
- uint32_t force_luminance;
- uint32_t alpha_to_zero;
- uint32_t srgb;
- uint32_t pad;
+ float set_color[4];
};
struct CopyToFb {
@@ -316,18 +326,20 @@ public:
void copy_cubemap_to_panorama(RID p_source_cube, RID p_dest_panorama, const Size2i &p_panorama_size, float p_lod, bool p_is_array);
void copy_depth_to_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y = false);
void copy_depth_to_rect_and_linearize(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y, float p_z_near, float p_z_far);
- void copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y = false, bool p_force_luminance = false, bool p_alpha_to_zero = false, bool p_srgb = false, RID p_secondary = RID(), bool p_multiview = false);
+ void copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y = false, bool p_force_luminance = false, bool p_alpha_to_zero = false, bool p_srgb = false, RID p_secondary = RID(), bool p_multiview = false, bool alpha_to_one = false, bool p_linear = false);
void copy_to_atlas_fb(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_uv_rect, RD::DrawListID p_draw_list, bool p_flip_y = false, bool p_panorama = false);
void copy_raster(RID p_source_texture, RID p_dest_framebuffer);
- void gaussian_blur(RID p_source_rd_texture, RID p_texture, const Rect2i &p_region, bool p_8bit_dst = false);
- void gaussian_glow(RID p_source_rd_texture, RID p_back_texture, const Size2i &p_size, float p_strength = 1.0, bool p_high_quality = false, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_threshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_scale = 1.0);
- void gaussian_glow_raster(RID p_source_rd_texture, RID p_half_texture, RID p_dest_texture, float p_luminance_multiplier, const Size2i &p_size, float p_strength = 1.0, bool p_high_quality = false, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_threshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_scale = 1.0);
+ void gaussian_blur(RID p_source_rd_texture, RID p_texture, const Rect2i &p_region, const Size2i &p_size, bool p_8bit_dst = false);
+ void gaussian_blur_raster(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_region, const Size2i &p_size);
+ void gaussian_glow(RID p_source_rd_texture, RID p_back_texture, const Size2i &p_size, float p_strength = 1.0, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_threshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_scale = 1.0);
+ void gaussian_glow_raster(RID p_source_rd_texture, RID p_half_texture, RID p_dest_texture, float p_luminance_multiplier, const Size2i &p_size, float p_strength = 1.0, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_threshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_scale = 1.0);
void make_mipmap(RID p_source_rd_texture, RID p_dest_texture, const Size2i &p_size);
void make_mipmap_raster(RID p_source_rd_texture, RID p_dest_texture, const Size2i &p_size);
void set_color(RID p_dest_texture, const Color &p_color, const Rect2i &p_region, bool p_8bit_dst = false);
+ void set_color_raster(RID p_dest_texture, const Color &p_color, const Rect2i &p_region);
void copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dst_framebuffer, const Rect2 &p_rect, const Vector2 &p_dst_size, float p_z_near, float p_z_far, bool p_dp_flip);
void cubemap_downsample(RID p_source_cubemap, RID p_dest_cubemap, const Size2i &p_size);
diff --git a/servers/rendering/renderer_rd/effects/resolve.h b/servers/rendering/renderer_rd/effects/resolve.h
index 2a4cd06827..49fba921d5 100644
--- a/servers/rendering/renderer_rd/effects/resolve.h
+++ b/servers/rendering/renderer_rd/effects/resolve.h
@@ -65,8 +65,8 @@ public:
Resolve();
~Resolve();
- void resolve_gi(RID p_source_depth, RID p_source_normal_roughness, RID p_source_voxel_gi, RID p_dest_depth, RID p_dest_normal_roughness, RID p_dest_voxel_gi, Vector2i p_screen_size, int p_samples, uint32_t p_barrier = RD::BARRIER_MASK_ALL);
- void resolve_depth(RID p_source_depth, RID p_dest_depth, Vector2i p_screen_size, int p_samples, uint32_t p_barrier = RD::BARRIER_MASK_ALL);
+ void resolve_gi(RID p_source_depth, RID p_source_normal_roughness, RID p_source_voxel_gi, RID p_dest_depth, RID p_dest_normal_roughness, RID p_dest_voxel_gi, Vector2i p_screen_size, int p_samples, uint32_t p_barrier = RD::BARRIER_MASK_ALL_BARRIERS);
+ void resolve_depth(RID p_source_depth, RID p_dest_depth, Vector2i p_screen_size, int p_samples, uint32_t p_barrier = RD::BARRIER_MASK_ALL_BARRIERS);
};
} // namespace RendererRD
diff --git a/servers/rendering/renderer_rd/effects/ss_effects.cpp b/servers/rendering/renderer_rd/effects/ss_effects.cpp
index 9653382e96..8e43869b4d 100644
--- a/servers/rendering/renderer_rd/effects/ss_effects.cpp
+++ b/servers/rendering/renderer_rd/effects/ss_effects.cpp
@@ -1332,7 +1332,6 @@ void SSEffects::generate_ssao(SSAORenderBuffers &p_ssao_buffers, RID p_normal_bu
for (int pass = 0; pass < blur_passes; pass++) {
int blur_pipeline = SSAO_BLUR_PASS;
if (ssao_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 {
diff --git a/servers/rendering/renderer_rd/effects/ss_effects.h b/servers/rendering/renderer_rd/effects/ss_effects.h
index dfaf3881bb..a04dfc4a74 100644
--- a/servers/rendering/renderer_rd/effects/ss_effects.h
+++ b/servers/rendering/renderer_rd/effects/ss_effects.h
@@ -100,7 +100,7 @@ public:
float sharpness = 0.98;
float normal_rejection = 1.0;
- Size2i full_screen_size = Size2i();
+ Size2i full_screen_size;
};
void ssil_allocate_buffers(SSILRenderBuffers &p_ssil_buffers, const SSILSettings &p_settings, RID p_linear_depth);
@@ -137,7 +137,7 @@ public:
float horizon = 0.06;
float sharpness = 0.98;
- Size2i full_screen_size = Size2i();
+ Size2i full_screen_size;
};
void ssao_allocate_buffers(SSAORenderBuffers &p_ssao_buffers, const SSAOSettings &p_settings, RID p_linear_depth);
diff --git a/servers/rendering/renderer_rd/effects/vrs.cpp b/servers/rendering/renderer_rd/effects/vrs.cpp
index 5ff00aa94c..701d53b41d 100644
--- a/servers/rendering/renderer_rd/effects/vrs.cpp
+++ b/servers/rendering/renderer_rd/effects/vrs.cpp
@@ -92,18 +92,15 @@ void VRS::copy_vrs(RID p_source_rd_texture, RID p_dest_framebuffer, bool p_multi
}
Size2i VRS::get_vrs_texture_size(const Size2i p_base_size) const {
- // 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);
-
- int width = p_base_size.x / texel_size.x;
- if (p_base_size.x % texel_size.x != 0) {
+ int32_t texel_width = RD::get_singleton()->limit_get(RD::LIMIT_VRS_TEXEL_WIDTH);
+ int32_t texel_height = RD::get_singleton()->limit_get(RD::LIMIT_VRS_TEXEL_HEIGHT);
+
+ int width = p_base_size.x / texel_width;
+ if (p_base_size.x % texel_width != 0) {
width++;
}
- int height = p_base_size.y / texel_size.y;
- if (p_base_size.y % texel_size.y != 0) {
+ int height = p_base_size.y / texel_height;
+ if (p_base_size.y % texel_height != 0) {
height++;
}
return Size2i(width, height);
diff --git a/servers/rendering/renderer_rd/environment/fog.cpp b/servers/rendering/renderer_rd/environment/fog.cpp
index 74082906c4..38066b6613 100644
--- a/servers/rendering/renderer_rd/environment/fog.cpp
+++ b/servers/rendering/renderer_rd/environment/fog.cpp
@@ -319,10 +319,6 @@ void Fog::free_fog_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
@@ -366,83 +362,6 @@ void Fog::FogShaderData::set_code(const String &p_code) {
valid = true;
}
-void Fog::FogShaderData::set_default_texture_parameter(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_parameter_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;
}
@@ -451,15 +370,6 @@ 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();
@@ -727,9 +637,9 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
any_uses_time |= shader_data->uses_time;
- Vector3i min = Vector3i();
- Vector3i max = Vector3i();
- Vector3i kernel_size = Vector3i();
+ Vector3i min;
+ Vector3i max;
+ Vector3i kernel_size;
Vector3 position = fog_volume_instance->transform.get_origin();
RS::FogVolumeShape volume_type = RendererRD::Fog::get_singleton()->fog_volume_get_shape(fog_volume);
@@ -789,6 +699,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
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);
+ material->set_as_used();
}
RD::get_singleton()->compute_list_dispatch_threads(compute_list, kernel_size.x, kernel_size.y, kernel_size.z);
diff --git a/servers/rendering/renderer_rd/environment/fog.h b/servers/rendering/renderer_rd/environment/fog.h
index 0ade995758..a5f06a129d 100644
--- a/servers/rendering/renderer_rd/environment/fog.h
+++ b/servers/rendering/renderer_rd/environment/fog.h
@@ -188,27 +188,18 @@ private:
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_parameter(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_parameter_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() {}
diff --git a/servers/rendering/renderer_rd/environment/gi.cpp b/servers/rendering/renderer_rd/environment/gi.cpp
index 550fe27e4c..61b7dd4504 100644
--- a/servers/rendering/renderer_rd/environment/gi.cpp
+++ b/servers/rendering/renderer_rd/environment/gi.cpp
@@ -3496,6 +3496,10 @@ void GI::init(SkyRD *p_sky) {
{
//calculate tables
String defines = "\n#define SDFGI_OCT_SIZE " + itos(SDFGI::LIGHTPROBE_OCT_SIZE) + "\n";
+ if (RendererSceneRenderRD::get_singleton()->is_vrs_supported()) {
+ defines += "\n#define USE_VRS\n";
+ }
+
Vector<String> gi_modes;
gi_modes.push_back("\n#define USE_VOXEL_GI_INSTANCES\n"); // MODE_VOXEL_GI
@@ -4011,7 +4015,7 @@ void GI::process_gi(Ref<RenderSceneBuffersRD> p_render_buffers, const RID *p_nor
u.append_id(rbgi->scene_data_ubo);
uniforms.push_back(u);
}
- {
+ if (RendererSceneRenderRD::get_singleton()->is_vrs_supported()) {
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 19;
diff --git a/servers/rendering/renderer_rd/environment/sky.cpp b/servers/rendering/renderer_rd/environment/sky.cpp
index 0acd48c22a..19546968cd 100644
--- a/servers/rendering/renderer_rd/environment/sky.cpp
+++ b/servers/rendering/renderer_rd/environment/sky.cpp
@@ -32,23 +32,25 @@
#include "core/config/project_settings.h"
#include "core/math/math_defs.h"
#include "servers/rendering/renderer_rd/effects/copy_effects.h"
+#include "servers/rendering/renderer_rd/framebuffer_cache_rd.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/render_scene_buffers_rd.h"
#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
+#include "servers/rendering/renderer_rd/uniform_set_cache_rd.h"
#include "servers/rendering/rendering_server_default.h"
#include "servers/rendering/rendering_server_globals.h"
using namespace RendererRD;
+#define RB_SCOPE_SKY SNAME("sky_buffers")
+#define RB_HALF_TEXTURE SNAME("half_texture")
+#define RB_QUARTER_TEXTURE SNAME("quarter_texture")
+
////////////////////////////////////////////////////////////////////////////////
// SKY SHADER
-void SkyRD::SkyShaderData::set_path_hint(const String &p_path) {
- path = p_path;
-}
-
void SkyRD::SkyShaderData::set_code(const String &p_code) {
//compile
@@ -152,82 +154,6 @@ void SkyRD::SkyShaderData::set_code(const String &p_code) {
valid = true;
}
-void SkyRD::SkyShaderData::set_default_texture_parameter(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 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) {
- 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 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;
- }
-
- 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 SkyRD::SkyShaderData::is_parameter_texture(const StringName &p_param) const {
- if (!uniforms.has(p_param)) {
- return false;
- }
-
- return uniforms[p_param].texture_order >= 0;
-}
-
bool SkyRD::SkyShaderData::is_animated() const {
return false;
}
@@ -236,15 +162,6 @@ bool SkyRD::SkyShaderData::casts_shadows() const {
return false;
}
-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;
- return ShaderLanguage::constant_value_to_variant(default_value, uniform.type, uniform.array_size, uniform.hint);
- }
- return Variant();
-}
-
RS::ShaderNativeSourceCode SkyRD::SkyShaderData::get_native_source_code() const {
RendererSceneRenderRD *scene_singleton = static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton);
@@ -293,18 +210,17 @@ static _FORCE_INLINE_ void store_transform_3x3(const Basis &p_basis, float *p_ar
p_array[11] = 0;
}
-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, 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, const Projection &p_projection, const Basis &p_orientation, const Vector3 &p_position, float p_luminance_multiplier) {
SkyPushConstant sky_push_constant;
memset(&sky_push_constant, 0, sizeof(SkyPushConstant));
- for (uint32_t v = 0; v < p_view_count; v++) {
- // We only need key components of our projection matrix
- sky_push_constant.projections[v][0] = p_projections[v].columns[2][0];
- sky_push_constant.projections[v][1] = p_projections[v].columns[0][0];
- sky_push_constant.projections[v][2] = p_projections[v].columns[2][1];
- sky_push_constant.projections[v][3] = p_projections[v].columns[1][1];
- }
+ // We only need key components of our projection matrix
+ sky_push_constant.projection[0] = p_projection.columns[2][0];
+ sky_push_constant.projection[1] = p_projection.columns[0][0];
+ sky_push_constant.projection[2] = p_projection.columns[2][1];
+ sky_push_constant.projection[3] = p_projection.columns[1][1];
+
sky_push_constant.position[0] = p_position.x;
sky_push_constant.position[1] = p_position.y;
sky_push_constant.position[2] = p_position.z;
@@ -629,28 +545,15 @@ void SkyRD::Sky::free() {
uniform_buffer = RID();
}
- if (half_res_pass.is_valid()) {
- RD::get_singleton()->free(half_res_pass);
- half_res_pass = RID();
- }
-
- if (quarter_res_pass.is_valid()) {
- RD::get_singleton()->free(quarter_res_pass);
- quarter_res_pass = RID();
- }
-
if (material.is_valid()) {
RSG::material_storage->material_free(material);
material = RID();
}
}
-RID SkyRD::Sky::get_textures(SkyTextureSetVersion p_version, RID p_default_shader_rd) {
+RID SkyRD::Sky::get_textures(SkyTextureSetVersion p_version, RID p_default_shader_rd, Ref<RenderSceneBuffersRD> p_render_buffers) {
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])) {
- return texture_uniform_sets[p_version];
- }
Vector<RD::Uniform> uniforms;
{
RD::Uniform u;
@@ -667,17 +570,18 @@ RID SkyRD::Sky::get_textures(SkyTextureSetVersion p_version, RID p_default_shade
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.binding = 1; // half res
- if (half_res_pass.is_valid() && p_version != SKY_TEXTURE_SET_HALF_RES && p_version != SKY_TEXTURE_SET_CUBEMAP_HALF_RES) {
- if (p_version >= SKY_TEXTURE_SET_CUBEMAP) {
+ if (p_version >= SKY_TEXTURE_SET_CUBEMAP) {
+ if (reflection.layers[0].views[1].is_valid() && p_version != SKY_TEXTURE_SET_CUBEMAP_HALF_RES) {
u.append_id(reflection.layers[0].views[1]);
} else {
- u.append_id(half_res_pass);
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK));
}
} else {
- if (p_version < SKY_TEXTURE_SET_CUBEMAP) {
- u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_WHITE));
+ RID half_texture = p_render_buffers->has_texture(RB_SCOPE_SKY, RB_HALF_TEXTURE) ? p_render_buffers->get_texture(RB_SCOPE_SKY, RB_HALF_TEXTURE) : RID();
+ if (half_texture.is_valid() && p_version != SKY_TEXTURE_SET_HALF_RES) {
+ u.append_id(half_texture);
} else {
- u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK));
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_WHITE));
}
}
uniforms.push_back(u);
@@ -686,24 +590,24 @@ RID SkyRD::Sky::get_textures(SkyTextureSetVersion p_version, RID p_default_shade
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.binding = 2; // quarter res
- if (quarter_res_pass.is_valid() && p_version != SKY_TEXTURE_SET_QUARTER_RES && p_version != SKY_TEXTURE_SET_CUBEMAP_QUARTER_RES) {
- if (p_version >= SKY_TEXTURE_SET_CUBEMAP) {
+ if (p_version >= SKY_TEXTURE_SET_CUBEMAP) {
+ if (reflection.layers[0].views[2].is_valid() && p_version != SKY_TEXTURE_SET_CUBEMAP_QUARTER_RES) {
u.append_id(reflection.layers[0].views[2]);
} else {
- u.append_id(quarter_res_pass);
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK));
}
} else {
- if (p_version < SKY_TEXTURE_SET_CUBEMAP) {
- u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_WHITE));
+ RID quarter_texture = p_render_buffers->has_texture(RB_SCOPE_SKY, RB_QUARTER_TEXTURE) ? p_render_buffers->get_texture(RB_SCOPE_SKY, RB_QUARTER_TEXTURE) : RID();
+ if (quarter_texture.is_valid() && p_version != SKY_TEXTURE_SET_QUARTER_RES) {
+ u.append_id(quarter_texture);
} else {
- u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK));
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_WHITE));
}
}
uniforms.push_back(u);
}
- texture_uniform_sets[p_version] = RD::get_singleton()->uniform_set_create(uniforms, p_default_shader_rd, SKY_SET_TEXTURES);
- return texture_uniform_sets[p_version];
+ return UniformSetCacheRD::get_singleton()->get_cache_vec(p_default_shader_rd, SKY_SET_TEXTURES, uniforms);
}
bool SkyRD::Sky::set_radiance_size(int p_radiance_size) {
@@ -1109,11 +1013,17 @@ SkyRD::~SkyRD() {
RD::get_singleton()->free(index_buffer); //array gets freed as dependency
}
-void SkyRD::setup(RID p_env, Ref<RenderSceneBuffersRD> p_render_buffers, const PagedArray<RID> &p_lights, RID p_camera_attributes, const Projection &p_projection, const Transform3D &p_transform, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render) {
+void SkyRD::setup_sky(RID p_env, Ref<RenderSceneBuffersRD> p_render_buffers, const PagedArray<RID> &p_lights, RID p_camera_attributes, uint32_t p_view_count, const Projection *p_view_projections, const Vector3 *p_view_eye_offsets, const Transform3D &p_cam_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.is_null());
+ ERR_FAIL_COND(p_render_buffers.is_null());
+
+ // make sure we support our view count
+ ERR_FAIL_COND(p_view_count == 0);
+ ERR_FAIL_COND(p_view_count > RendererSceneRender::MAX_RENDER_VIEWS);
+
SkyMaterialData *material = nullptr;
Sky *sky = get_sky(RendererSceneRenderRD::get_singleton()->environment_get_sky(p_env));
@@ -1142,31 +1052,14 @@ void SkyRD::setup(RID p_env, Ref<RenderSceneBuffersRD> p_render_buffers, const P
ERR_FAIL_COND(!shader_data);
- // Invalidate supbass buffers if screen size changes
- if (sky->screen_size != p_screen_size) {
- sky->screen_size = p_screen_size;
- sky->screen_size.x = sky->screen_size.x < 4 ? 4 : sky->screen_size.x;
- sky->screen_size.y = sky->screen_size.y < 4 ? 4 : sky->screen_size.y;
- if (shader_data->uses_half_res) {
- if (sky->half_res_pass.is_valid()) {
- RD::get_singleton()->free(sky->half_res_pass);
- sky->half_res_pass = RID();
- }
- invalidate_sky(sky);
- }
- if (shader_data->uses_quarter_res) {
- if (sky->quarter_res_pass.is_valid()) {
- RD::get_singleton()->free(sky->quarter_res_pass);
- sky->quarter_res_pass = RID();
- }
- invalidate_sky(sky);
- }
- }
+ material->set_as_used();
+
+ // Save our screen size, our buffers will already have been cleared
+ sky->screen_size.x = p_screen_size.x < 4 ? 4 : p_screen_size.x;
+ sky->screen_size.y = p_screen_size.y < 4 ? 4 : p_screen_size.y;
- // Create new subpass buffers if necessary
- if ((shader_data->uses_half_res && sky->half_res_pass.is_null()) ||
- (shader_data->uses_quarter_res && sky->quarter_res_pass.is_null()) ||
- sky->radiance.is_null()) {
+ // Trigger updating radiance buffers
+ if (sky->radiance.is_null()) {
invalidate_sky(sky);
update_dirty_skys();
}
@@ -1187,8 +1080,8 @@ void SkyRD::setup(RID p_env, Ref<RenderSceneBuffersRD> p_render_buffers, const P
sky->reflection.dirty = true;
}
- if (!p_transform.origin.is_equal_approx(sky->prev_position) && shader_data->uses_position) {
- sky->prev_position = p_transform.origin;
+ if (!p_cam_transform.origin.is_equal_approx(sky->prev_position) && shader_data->uses_position) {
+ sky->prev_position = p_cam_transform.origin;
sky->reflection.dirty = true;
}
@@ -1316,7 +1209,20 @@ void SkyRD::setup(RID p_env, Ref<RenderSceneBuffersRD> p_render_buffers, const P
}
}
- sky_scene_state.ubo.z_far = p_projection.get_z_far();
+ sky_scene_state.view_count = p_view_count;
+ sky_scene_state.cam_transform = p_cam_transform;
+ sky_scene_state.cam_projection = p_view_projections[0]; // We only use this when rendering a single view
+
+ // Our info in our UBO is only used if we're rendering stereo
+ for (uint32_t i = 0; i < p_view_count; i++) {
+ RendererRD::MaterialStorage::store_camera(p_view_projections[i].inverse(), sky_scene_state.ubo.view_inv_projections[i]);
+ sky_scene_state.ubo.view_eye_offsets[i][0] = p_view_eye_offsets[i].x;
+ sky_scene_state.ubo.view_eye_offsets[i][1] = p_view_eye_offsets[i].y;
+ sky_scene_state.ubo.view_eye_offsets[i][2] = p_view_eye_offsets[i].z;
+ sky_scene_state.ubo.view_eye_offsets[i][3] = 0.0;
+ }
+
+ sky_scene_state.ubo.z_far = p_view_projections[0].get_z_far(); // Should be the same for all projection
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);
@@ -1333,7 +1239,8 @@ void SkyRD::setup(RID p_env, Ref<RenderSceneBuffersRD> p_render_buffers, const P
RD::get_singleton()->buffer_update(sky_scene_state.uniform_buffer, 0, sizeof(SkySceneState::UBO), &sky_scene_state.ubo);
}
-void SkyRD::update(RID p_env, const Projection &p_projection, const Transform3D &p_transform, double p_time, float p_luminance_multiplier) {
+void SkyRD::update_radiance_buffers(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_env, const Vector3 &p_global_pos, double p_time, float p_luminance_multiplier) {
+ ERR_FAIL_COND(p_render_buffers.is_null());
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
ERR_FAIL_COND(p_env.is_null());
@@ -1411,6 +1318,8 @@ void SkyRD::update(RID p_env, const Projection &p_projection, const Transform3D
correction.set_depth_correction(true);
cm = correction * cm;
+ // Note, we ignore environment_get_sky_orientation here as this is applied when we do our lookup in our scene shader.
+
if (shader_data->uses_quarter_res) {
RD::get_singleton()->draw_command_begin_label("Render Sky to Quarter Res Cubemap");
PipelineCacheRD *pipeline = &shader_data->pipelines[SKY_VERSION_CUBEMAP_QUARTER_RES];
@@ -1421,10 +1330,10 @@ void SkyRD::update(RID p_env, const Projection &p_projection, const Transform3D
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(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, p_render_buffers);
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, p_transform.origin, p_luminance_multiplier);
+ _render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[2].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, cm, local_view, p_global_pos, p_luminance_multiplier);
RD::get_singleton()->draw_list_end();
}
RD::get_singleton()->draw_command_end_label();
@@ -1440,10 +1349,10 @@ void SkyRD::update(RID p_env, const Projection &p_projection, const Transform3D
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(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, p_render_buffers);
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, p_transform.origin, p_luminance_multiplier);
+ _render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[1].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, cm, local_view, p_global_pos, p_luminance_multiplier);
RD::get_singleton()->draw_list_end();
}
RD::get_singleton()->draw_command_end_label();
@@ -1455,10 +1364,10 @@ void SkyRD::update(RID p_env, const Projection &p_projection, const Transform3D
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(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, p_render_buffers);
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, p_transform.origin, p_luminance_multiplier);
+ _render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[0].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, cm, local_view, p_global_pos, p_luminance_multiplier);
RD::get_singleton()->draw_list_end();
}
RD::get_singleton()->draw_command_end_label();
@@ -1500,13 +1409,11 @@ void SkyRD::update(RID p_env, const Projection &p_projection, const Transform3D
}
}
-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, float p_luminance_multiplier) {
+void SkyRD::update_res_buffers(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_env, double p_time, float p_luminance_multiplier) {
+ ERR_FAIL_COND(p_render_buffers.is_null());
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
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(RendererSceneRenderRD::get_singleton()->environment_get_sky(p_env));
SkyMaterialData *material = nullptr;
@@ -1539,105 +1446,16 @@ void SkyRD::draw(RID p_env, bool p_can_continue_color, bool p_can_continue_depth
ERR_FAIL_COND(!material);
SkyShaderData *shader_data = material->shader_data;
-
ERR_FAIL_COND(!shader_data);
- Basis sky_transform = RendererSceneRenderRD::get_singleton()->environment_get_sky_orientation(p_env);
- sky_transform.invert();
-
- float custom_fov = RendererSceneRenderRD::get_singleton()->environment_get_sky_custom_fov(p_env);
-
- // Camera
- Projection camera;
- uint32_t view_count = p_view_count;
- const Projection *projections = p_projections;
-
- if (custom_fov) {
- // With custom fov we don't support stereo...
- float near_plane = p_projections[0].get_z_near();
- float far_plane = p_projections[0].get_z_far();
- float aspect = p_projections[0].get_aspect();
-
- camera.set_perspective(custom_fov, aspect, near_plane, far_plane);
-
- view_count = 1;
- projections = &camera;
- }
-
- sky_transform = sky_transform * p_transform.basis;
-
- 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(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));
-
- RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(sky->quarter_res_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, clear_colors);
- _render_sky(draw_list, p_time, sky->quarter_res_framebuffer, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, p_transform.origin, p_luminance_multiplier);
- RD::get_singleton()->draw_list_end();
- }
-
- 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(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));
-
- RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(sky->half_res_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, clear_colors);
- _render_sky(draw_list, p_time, sky->half_res_framebuffer, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, p_transform.origin, p_luminance_multiplier);
- RD::get_singleton()->draw_list_end();
- }
-
- PipelineCacheRD *pipeline = &shader_data->pipelines[view_count > 1 ? SKY_VERSION_BACKGROUND_MULTIVIEW : SKY_VERSION_BACKGROUND];
-
- RID texture_uniform_set;
- if (sky) {
- 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;
- }
-
- RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_fb, RD::INITIAL_ACTION_CONTINUE, p_can_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, p_can_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ);
- _render_sky(draw_list, p_time, p_fb, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, p_transform.origin, p_luminance_multiplier);
- RD::get_singleton()->draw_list_end();
-}
-
-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.is_null());
-
- ERR_FAIL_COND(p_view_count == 0);
- ERR_FAIL_COND(p_view_count > RendererSceneRender::MAX_RENDER_VIEWS);
-
- 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(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::MaterialStorage::SHADER_TYPE_SKY));
- if (!material || !material->shader_data->valid) {
- material = nullptr;
- }
- }
-
- if (!material) {
- sky_material = sky_shader.default_material;
- material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::MaterialStorage::SHADER_TYPE_SKY));
+ if (!shader_data->uses_quarter_res && !shader_data->uses_half_res) {
+ return;
}
- ERR_FAIL_COND(!material);
+ material->set_as_used();
- SkyShaderData *shader_data = material->shader_data;
-
- ERR_FAIL_COND(!shader_data);
+ RENDER_TIMESTAMP("Setup Sky Resolution Buffers");
+ RD::get_singleton()->draw_command_begin_label("Setup Sky Resolution Buffers");
Basis sky_transform = RendererSceneRenderRD::get_singleton()->environment_get_sky_orientation(p_env);
sky_transform.invert();
@@ -1645,58 +1463,65 @@ void SkyRD::update_res_buffers(RID p_env, uint32_t p_view_count, const Projectio
float custom_fov = RendererSceneRenderRD::get_singleton()->environment_get_sky_custom_fov(p_env);
// Camera
- Projection camera;
- uint32_t view_count = p_view_count;
- const Projection *projections = p_projections;
+ Projection projection = sky_scene_state.cam_projection;
- if (custom_fov) {
+ if (custom_fov && sky_scene_state.view_count == 1) {
// With custom fov we don't support stereo...
- float near_plane = p_projections[0].get_z_near();
- float far_plane = p_projections[0].get_z_far();
- float aspect = p_projections[0].get_aspect();
-
- camera.set_perspective(custom_fov, aspect, near_plane, far_plane);
+ float near_plane = projection.get_z_near();
+ float far_plane = projection.get_z_far();
+ float aspect = projection.get_aspect();
- view_count = 1;
- projections = &camera;
+ projection.set_perspective(custom_fov, aspect, near_plane, far_plane);
}
- sky_transform = p_transform.basis * sky_transform;
+ sky_transform = sky_transform * sky_scene_state.cam_transform.basis;
if (shader_data->uses_quarter_res) {
- PipelineCacheRD *pipeline = &shader_data->pipelines[view_count > 1 ? SKY_VERSION_QUARTER_RES_MULTIVIEW : SKY_VERSION_QUARTER_RES];
+ PipelineCacheRD *pipeline = &shader_data->pipelines[sky_scene_state.view_count > 1 ? SKY_VERSION_QUARTER_RES_MULTIVIEW : SKY_VERSION_QUARTER_RES];
+
+ // Grab texture and framebuffer from cache, create if needed...
+ uint32_t usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
+ Size2i quarter_size = sky->screen_size / 4;
+ RID texture = p_render_buffers->create_texture(RB_SCOPE_SKY, RB_QUARTER_TEXTURE, texture_format, usage_bits, RD::TEXTURE_SAMPLES_1, quarter_size);
+ RID framebuffer = FramebufferCacheRD::get_singleton()->get_cache_multiview(sky_scene_state.view_count, texture);
- RID texture_uniform_set = sky->get_textures(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, p_render_buffers);
Vector<Color> clear_colors;
clear_colors.push_back(Color(0.0, 0.0, 0.0));
- RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(sky->quarter_res_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, clear_colors);
- _render_sky(draw_list, p_time, sky->quarter_res_framebuffer, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, p_transform.origin, p_luminance_multiplier);
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, clear_colors);
+ _render_sky(draw_list, p_time, framebuffer, pipeline, material->uniform_set, texture_uniform_set, projection, sky_transform, sky_scene_state.cam_transform.origin, p_luminance_multiplier);
RD::get_singleton()->draw_list_end();
}
if (shader_data->uses_half_res) {
- PipelineCacheRD *pipeline = &shader_data->pipelines[view_count > 1 ? SKY_VERSION_HALF_RES_MULTIVIEW : SKY_VERSION_HALF_RES];
+ PipelineCacheRD *pipeline = &shader_data->pipelines[sky_scene_state.view_count > 1 ? SKY_VERSION_HALF_RES_MULTIVIEW : SKY_VERSION_HALF_RES];
- RID texture_uniform_set = sky->get_textures(SKY_TEXTURE_SET_HALF_RES, sky_shader.default_shader_rd);
+ // Grab texture and framebuffer from cache, create if needed...
+ uint32_t usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
+ Size2i half_size = sky->screen_size / 2;
+ RID texture = p_render_buffers->create_texture(RB_SCOPE_SKY, RB_HALF_TEXTURE, texture_format, usage_bits, RD::TEXTURE_SAMPLES_1, half_size);
+ RID framebuffer = FramebufferCacheRD::get_singleton()->get_cache_multiview(sky_scene_state.view_count, texture);
+
+ RID texture_uniform_set = sky->get_textures(SKY_TEXTURE_SET_HALF_RES, sky_shader.default_shader_rd, p_render_buffers);
Vector<Color> clear_colors;
clear_colors.push_back(Color(0.0, 0.0, 0.0));
- RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(sky->half_res_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, clear_colors);
- _render_sky(draw_list, p_time, sky->half_res_framebuffer, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, p_transform.origin, p_luminance_multiplier);
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, clear_colors);
+ _render_sky(draw_list, p_time, framebuffer, pipeline, material->uniform_set, texture_uniform_set, projection, sky_transform, sky_scene_state.cam_transform.origin, p_luminance_multiplier);
RD::get_singleton()->draw_list_end();
}
+
+ RD::get_singleton()->draw_command_end_label(); // Setup Sky resolution buffers
}
-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) {
+void SkyRD::draw_sky(RD::DrawListID p_draw_list, Ref<RenderSceneBuffersRD> p_render_buffers, RID p_env, RID p_fb, double p_time, float p_luminance_multiplier) {
+ ERR_FAIL_COND(p_render_buffers.is_null());
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
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(RendererSceneRenderRD::get_singleton()->environment_get_sky(p_env));
SkyMaterialData *material = nullptr;
@@ -1729,43 +1554,39 @@ void SkyRD::draw(RD::DrawListID p_draw_list, RID p_env, RID p_fb, uint32_t p_vie
ERR_FAIL_COND(!material);
SkyShaderData *shader_data = material->shader_data;
-
ERR_FAIL_COND(!shader_data);
+ material->set_as_used();
+
Basis sky_transform = RendererSceneRenderRD::get_singleton()->environment_get_sky_orientation(p_env);
sky_transform.invert();
float custom_fov = RendererSceneRenderRD::get_singleton()->environment_get_sky_custom_fov(p_env);
// Camera
- Projection camera;
- uint32_t view_count = p_view_count;
- const Projection *projections = p_projections;
+ Projection projection = sky_scene_state.cam_projection;
- if (custom_fov) {
+ if (custom_fov && sky_scene_state.view_count == 1) {
// With custom fov we don't support stereo...
- float near_plane = p_projections[0].get_z_near();
- float far_plane = p_projections[0].get_z_far();
- float aspect = p_projections[0].get_aspect();
+ float near_plane = projection.get_z_near();
+ float far_plane = projection.get_z_far();
+ float aspect = projection.get_aspect();
- camera.set_perspective(custom_fov, aspect, near_plane, far_plane);
-
- view_count = 1;
- projections = &camera;
+ projection.set_perspective(custom_fov, aspect, near_plane, far_plane);
}
- sky_transform = p_transform.basis * sky_transform;
+ sky_transform = sky_transform * sky_scene_state.cam_transform.basis;
- PipelineCacheRD *pipeline = &shader_data->pipelines[view_count > 1 ? SKY_VERSION_BACKGROUND_MULTIVIEW : SKY_VERSION_BACKGROUND];
+ PipelineCacheRD *pipeline = &shader_data->pipelines[sky_scene_state.view_count > 1 ? SKY_VERSION_BACKGROUND_MULTIVIEW : SKY_VERSION_BACKGROUND];
RID texture_uniform_set;
if (sky) {
- texture_uniform_set = sky->get_textures(SKY_TEXTURE_SET_BACKGROUND, sky_shader.default_shader_rd);
+ texture_uniform_set = sky->get_textures(SKY_TEXTURE_SET_BACKGROUND, sky_shader.default_shader_rd, p_render_buffers);
} else {
texture_uniform_set = sky_scene_state.fog_only_texture_uniform_set;
}
- _render_sky(p_draw_list, p_time, p_fb, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, p_transform.origin, p_luminance_multiplier);
+ _render_sky(p_draw_list, p_time, p_fb, pipeline, material->uniform_set, texture_uniform_set, projection, sky_transform, sky_scene_state.cam_transform.origin, p_luminance_multiplier);
}
void SkyRD::invalidate_sky(Sky *p_sky) {
@@ -1780,9 +1601,11 @@ void SkyRD::update_dirty_skys() {
Sky *sky = dirty_sky_list;
while (sky) {
- bool texture_set_dirty = false;
//update sky configuration if texture is missing
+ // TODO See if we can move this into `update_radiance_buffers` and remove our dirty_sky logic.
+ // As this is basically a duplicate of the logic in reflection probes we could move this logic
+ // into RenderSceneBuffersRD and use that from both places.
if (sky->radiance.is_null()) {
int mipmaps = Image::get_image_required_mipmaps(sky->radiance_size, sky->radiance_size, Image::FORMAT_RGBAH) + 1;
@@ -1825,47 +1648,6 @@ void SkyRD::update_dirty_skys() {
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;
- }
-
- // Create subpass buffers if they haven't been created already
- if (sky->half_res_pass.is_null() && !RD::get_singleton()->texture_is_valid(sky->half_res_pass) && sky->screen_size.x >= 4 && sky->screen_size.y >= 4) {
- RD::TextureFormat tformat;
- tformat.format = texture_format;
- tformat.width = sky->screen_size.x / 2;
- tformat.height = sky->screen_size.y / 2;
- tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
- tformat.texture_type = RD::TEXTURE_TYPE_2D;
-
- sky->half_res_pass = RD::get_singleton()->texture_create(tformat, RD::TextureView());
- Vector<RID> texs;
- texs.push_back(sky->half_res_pass);
- sky->half_res_framebuffer = RD::get_singleton()->framebuffer_create(texs);
- texture_set_dirty = true;
- }
-
- if (sky->quarter_res_pass.is_null() && !RD::get_singleton()->texture_is_valid(sky->quarter_res_pass) && sky->screen_size.x >= 4 && sky->screen_size.y >= 4) {
- RD::TextureFormat tformat;
- tformat.format = texture_format;
- tformat.width = sky->screen_size.x / 4;
- tformat.height = sky->screen_size.y / 4;
- tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
- tformat.texture_type = RD::TEXTURE_TYPE_2D;
-
- sky->quarter_res_pass = RD::get_singleton()->texture_create(tformat, RD::TextureView());
- Vector<RID> texs;
- texs.push_back(sky->quarter_res_pass);
- sky->quarter_res_framebuffer = RD::get_singleton()->framebuffer_create(texs);
- texture_set_dirty = true;
- }
-
- if (texture_set_dirty) {
- for (int i = 0; i < SKY_TEXTURE_SET_MAX; i++) {
- if (sky->texture_uniform_sets[i].is_valid() && RD::get_singleton()->uniform_set_is_valid(sky->texture_uniform_sets[i])) {
- RD::get_singleton()->free(sky->texture_uniform_sets[i]);
- sky->texture_uniform_sets[i] = RID();
- }
- }
}
sky->reflection.dirty = true;
diff --git a/servers/rendering/renderer_rd/environment/sky.h b/servers/rendering/renderer_rd/environment/sky.h
index 45c4f9bda7..6e0ebb5f8e 100644
--- a/servers/rendering/renderer_rd/environment/sky.h
+++ b/servers/rendering/renderer_rd/environment/sky.h
@@ -99,11 +99,11 @@ private:
struct SkyPushConstant {
float orientation[12]; // 48 - 48
- float projections[RendererSceneRender::MAX_RENDER_VIEWS][4]; // 2 x 16 - 80
- float position[3]; // 12 - 92
- float time; // 4 - 96
- float pad[3]; // 12 - 108
- float luminance_multiplier; // 4 - 112
+ float projection[4]; // 16 - 64
+ float position[3]; // 12 - 76
+ float time; // 4 - 80
+ float pad[3]; // 12 - 92
+ float luminance_multiplier; // 4 - 96
// 128 is the max size of a push constant. We can replace "pad" but we can't add any more.
};
@@ -112,15 +112,12 @@ private:
RID version;
PipelineCacheRD pipelines[SKY_VERSION_MAX];
- 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;
bool uses_position = false;
@@ -129,46 +126,47 @@ 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_parameter(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_parameter_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;
SkyShaderData() {}
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 Projection *p_projections, const Basis &p_orientation, 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, const Projection &p_projection, const Basis &p_orientation, const Vector3 &p_position, float p_luminance_multiplier);
public:
struct SkySceneState {
struct UBO {
- uint32_t volumetric_fog_enabled; // 4 - 4
- float volumetric_fog_inv_length; // 4 - 8
- float volumetric_fog_detail_spread; // 4 - 12
- float volumetric_fog_sky_affect; // 4 - 16
-
- uint32_t fog_enabled; // 4 - 20
- float fog_sky_affect; // 4 - 24
- float fog_density; // 4 - 28
- float fog_sun_scatter; // 4 - 32
-
- float fog_light_color[3]; // 12 - 44
- float fog_aerial_perspective; // 4 - 48
-
- float z_far; // 4 - 52
- uint32_t directional_light_count; // 4 - 56
- uint32_t pad1; // 4 - 60
- uint32_t pad2; // 4 - 64
+ float view_inv_projections[RendererSceneRender::MAX_RENDER_VIEWS][16]; // 2 x 64 - 128
+ float view_eye_offsets[RendererSceneRender::MAX_RENDER_VIEWS][4]; // 2 x 16 - 160
+
+ uint32_t volumetric_fog_enabled; // 4 - 164
+ float volumetric_fog_inv_length; // 4 - 168
+ float volumetric_fog_detail_spread; // 4 - 172
+ float volumetric_fog_sky_affect; // 4 - 176
+
+ uint32_t fog_enabled; // 4 - 180
+ float fog_sky_affect; // 4 - 184
+ float fog_density; // 4 - 188
+ float fog_sun_scatter; // 4 - 192
+
+ float fog_light_color[3]; // 12 - 204
+ float fog_aerial_perspective; // 4 - 208
+
+ float z_far; // 4 - 212
+ uint32_t directional_light_count; // 4 - 216
+ uint32_t pad1; // 4 - 220
+ uint32_t pad2; // 4 - 224
};
UBO ubo;
+ uint32_t view_count = 1;
+ Transform3D cam_transform;
+ Projection cam_projection;
+
SkyDirectionalLightData *directional_lights = nullptr;
SkyDirectionalLightData *last_frame_directional_lights = nullptr;
uint32_t max_directional_lights;
@@ -247,13 +245,10 @@ public:
struct Sky {
RID radiance;
- RID half_res_pass;
- RID half_res_framebuffer;
RID quarter_res_pass;
RID quarter_res_framebuffer;
Size2i screen_size;
- RID texture_uniform_sets[SKY_TEXTURE_SET_MAX];
RID uniform_set;
RID material;
@@ -276,7 +271,7 @@ public:
void free();
- RID get_textures(SkyTextureSetVersion p_version, RID p_default_shader_rd);
+ RID get_textures(SkyTextureSetVersion p_version, RID p_default_shader_rd, Ref<RenderSceneBuffersRD> p_render_buffers);
bool set_radiance_size(int p_radiance_size);
bool set_mode(RS::SkyMode p_mode);
bool set_material(RID p_material);
@@ -300,11 +295,10 @@ public:
void set_texture_format(RD::DataFormat p_texture_format);
~SkyRD();
- void setup(RID p_env, Ref<RenderSceneBuffersRD> p_render_buffers, const PagedArray<RID> &p_lights, RID p_camera_attributes, 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, float p_luminance_multiplier = 1.0); // 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 setup_sky(RID p_env, Ref<RenderSceneBuffersRD> p_render_buffers, const PagedArray<RID> &p_lights, RID p_camera_attributes, uint32_t p_view_count, const Projection *p_view_projections, const Vector3 *p_view_eye_offsets, const Transform3D &p_cam_transform, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render);
+ void update_radiance_buffers(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_env, const Vector3 &p_global_pos, double p_time, float p_luminance_multiplier = 1.0);
+ void update_res_buffers(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_env, double p_time, float p_luminance_multiplier = 1.0);
+ void draw_sky(RD::DrawListID p_draw_list, Ref<RenderSceneBuffersRD> p_render_buffers, RID p_env, RID p_fb, double p_time, float p_luminance_multiplier = 1.0);
void invalidate_sky(Sky *p_sky);
void update_dirty_skys();
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 0e4a223f69..5b465fb45c 100644
--- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
+++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
@@ -348,6 +348,7 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p
#endif
material_uniform_set = surf->material_uniform_set;
shader = surf->shader;
+ surf->material->set_as_used();
#ifdef DEBUG_ENABLED
}
#endif
@@ -830,8 +831,18 @@ void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, con
for (int i = 0; i < (int)p_render_data->instances->size(); i++) {
GeometryInstanceForwardClustered *inst = static_cast<GeometryInstanceForwardClustered *>((*p_render_data->instances)[i]);
- Vector3 support_min = inst->transformed_aabb.get_support(-near_plane.normal);
- inst->depth = near_plane.distance_to(support_min);
+ Vector3 center = inst->transform.origin;
+ if (p_render_data->scene_data->cam_orthogonal) {
+ if (inst->use_aabb_center) {
+ center = inst->transformed_aabb.get_support(-near_plane.normal);
+ }
+ inst->depth = near_plane.distance_to(center) - inst->sorting_offset;
+ } else {
+ if (inst->use_aabb_center) {
+ center = inst->transformed_aabb.position + (inst->transformed_aabb.size * 0.5);
+ }
+ inst->depth = p_render_data->scene_data->cam_transform.origin.distance_to(center) - inst->sorting_offset;
+ }
uint32_t depth_layer = CLAMP(int(inst->depth * 16 / z_max), 0, 15);
uint32_t flags = inst->base_flags; //fill flags if appropriate
@@ -1151,6 +1162,7 @@ void RenderForwardClustered::_update_volumetric_fog(Ref<RenderSceneBuffersRD> p_
ERR_FAIL_COND(p_render_buffers.is_null());
Ref<RenderBufferDataForwardClustered> rb_data = p_render_buffers->get_custom_data(RB_SCOPE_FORWARD_CLUSTERED);
+ ERR_FAIL_COND(rb_data.is_null());
ERR_FAIL_COND(!p_render_buffers->has_custom_data(RB_SCOPE_GI));
Ref<RendererRD::GI::RenderBuffersGI> rbgi = p_render_buffers->get_custom_data(RB_SCOPE_GI);
@@ -1321,7 +1333,9 @@ void RenderForwardClustered::_pre_opaque_render(RenderDataRD *p_render_data, boo
Ref<RenderSceneBuffersRD> rb = p_render_data->render_buffers;
Ref<RenderBufferDataForwardClustered> rb_data;
- if (rb.is_valid()) {
+ if (rb.is_valid() && rb->has_custom_data(RB_SCOPE_FORWARD_CLUSTERED)) {
+ // Our forward clustered custom data buffer will only be available when we're rendering our normal view.
+ // This will not be available when rendering reflection probes.
rb_data = rb->get_custom_data(RB_SCOPE_FORWARD_CLUSTERED);
}
@@ -1446,7 +1460,7 @@ void RenderForwardClustered::_pre_opaque_render(RenderDataRD *p_render_data, boo
}
//full barrier here, we need raster, transfer and compute and it depends from the previous work
- RD::get_singleton()->barrier(RD::BARRIER_MASK_ALL, RD::BARRIER_MASK_ALL);
+ RD::get_singleton()->barrier(RD::BARRIER_MASK_ALL_BARRIERS, RD::BARRIER_MASK_ALL_BARRIERS);
if (current_cluster_builder) {
current_cluster_builder->begin(p_render_data->scene_data->cam_transform, p_render_data->scene_data->cam_projection, !p_render_data->reflection_probe.is_valid());
@@ -1474,7 +1488,7 @@ void RenderForwardClustered::_pre_opaque_render(RenderDataRD *p_render_data, boo
current_cluster_builder->bake_cluster();
}
- if (rb.is_valid()) {
+ if (rb_data.is_valid()) {
bool directional_shadows = RendererRD::LightStorage::get_singleton()->has_directional_shadows(directional_light_count);
_update_volumetric_fog(rb, p_render_data->environment, p_render_data->scene_data->cam_projection, p_render_data->scene_data->cam_transform, p_render_data->scene_data->prev_cam_transform.affine_inverse(), p_render_data->shadow_atlas, directional_light_count, directional_shadows, positional_light_count, p_render_data->voxel_gi_count, *p_render_data->fog_volumes);
}
@@ -1540,7 +1554,11 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
Ref<RenderBufferDataForwardClustered> rb_data;
if (p_render_data && p_render_data->render_buffers.is_valid()) {
rb = p_render_data->render_buffers;
- rb_data = rb->get_custom_data(RB_SCOPE_FORWARD_CLUSTERED);
+ if (rb->has_custom_data(RB_SCOPE_FORWARD_CLUSTERED)) {
+ // Our forward clustered custom data buffer will only be available when we're rendering our normal view.
+ // This will not be available when rendering reflection probes.
+ rb_data = rb->get_custom_data(RB_SCOPE_FORWARD_CLUSTERED);
+ }
}
static const int texture_multisamples[RS::VIEWPORT_MSAA_MAX] = { 1, 2, 4, 8 };
@@ -1559,32 +1577,32 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
}
// obtain cluster builder
- if (rb_data.is_valid()) {
- current_cluster_builder = rb_data->cluster_builder;
- } else if (light_storage->owns_reflection_probe_instance(p_render_data->reflection_probe)) {
+ if (light_storage->owns_reflection_probe_instance(p_render_data->reflection_probe)) {
current_cluster_builder = light_storage->reflection_probe_instance_get_cluster_builder(p_render_data->reflection_probe, &cluster_builder_shared);
if (p_render_data->camera_attributes.is_valid()) {
light_storage->reflection_probe_set_baked_exposure(light_storage->reflection_probe_instance_get_probe(p_render_data->reflection_probe), RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_render_data->camera_attributes));
}
- } else {
- ERR_PRINT("No render buffer nor reflection atlas, bug"); //should never happen, will crash
- current_cluster_builder = nullptr;
- }
+ } else if (rb_data.is_valid()) {
+ current_cluster_builder = rb_data->cluster_builder;
- p_render_data->voxel_gi_count = 0;
+ p_render_data->voxel_gi_count = 0;
- if (rb.is_valid()) {
- if (rb->has_custom_data(RB_SCOPE_SDFGI)) {
- Ref<RendererRD::GI::SDFGI> sdfgi = rb->get_custom_data(RB_SCOPE_SDFGI);
- if (sdfgi.is_valid()) {
- sdfgi->update_cascades();
- sdfgi->pre_process_gi(p_render_data->scene_data->cam_transform, p_render_data);
- sdfgi->update_light();
+ if (rb.is_valid()) {
+ if (rb->has_custom_data(RB_SCOPE_SDFGI)) {
+ Ref<RendererRD::GI::SDFGI> sdfgi = rb->get_custom_data(RB_SCOPE_SDFGI);
+ if (sdfgi.is_valid()) {
+ sdfgi->update_cascades();
+ sdfgi->pre_process_gi(p_render_data->scene_data->cam_transform, p_render_data);
+ sdfgi->update_light();
+ }
}
- }
- gi.setup_voxel_gi_instances(p_render_data, p_render_data->render_buffers, p_render_data->scene_data->cam_transform, *p_render_data->voxel_gi_instances, p_render_data->voxel_gi_count);
+ gi.setup_voxel_gi_instances(p_render_data, p_render_data->render_buffers, p_render_data->scene_data->cam_transform, *p_render_data->voxel_gi_instances, p_render_data->voxel_gi_count);
+ }
+ } else {
+ ERR_PRINT("No render buffer nor reflection atlas, bug"); //should never happen, will crash
+ current_cluster_builder = nullptr;
}
if (current_cluster_builder != nullptr) {
@@ -1622,10 +1640,24 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
bool using_ssr = false;
bool using_sdfgi = false;
bool using_voxelgi = false;
- bool reverse_cull = false;
+ bool reverse_cull = p_render_data->scene_data->cam_transform.basis.determinant() < 0;
bool using_ssil = p_render_data->environment.is_valid() && environment_get_ssil_enabled(p_render_data->environment);
- if (rb.is_valid()) {
+ if (p_render_data->reflection_probe.is_valid()) {
+ uint32_t resolution = light_storage->reflection_probe_instance_get_resolution(p_render_data->reflection_probe);
+ screen_size.x = resolution;
+ screen_size.y = resolution;
+
+ color_framebuffer = light_storage->reflection_probe_instance_get_framebuffer(p_render_data->reflection_probe, p_render_data->reflection_probe_pass);
+ color_only_framebuffer = color_framebuffer;
+ depth_framebuffer = light_storage->reflection_probe_instance_get_depth_framebuffer(p_render_data->reflection_probe, p_render_data->reflection_probe_pass);
+
+ if (light_storage->reflection_probe_is_interior(light_storage->reflection_probe_instance_get_probe(p_render_data->reflection_probe))) {
+ p_render_data->environment = RID(); //no environment on interiors
+ }
+
+ reverse_cull = true; // for some reason our views are inverted
+ } else if (rb.is_valid()) {
screen_size = rb->get_internal_size();
if (rb->get_use_taa() || get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_MOTION_VECTORS) {
@@ -1677,20 +1709,6 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
color_framebuffer = rb_data->get_color_pass_fb(color_pass_flags);
color_only_framebuffer = rb_data->get_color_only_fb();
- } else if (p_render_data->reflection_probe.is_valid()) {
- uint32_t resolution = light_storage->reflection_probe_instance_get_resolution(p_render_data->reflection_probe);
- screen_size.x = resolution;
- screen_size.y = resolution;
-
- color_framebuffer = light_storage->reflection_probe_instance_get_framebuffer(p_render_data->reflection_probe, p_render_data->reflection_probe_pass);
- color_only_framebuffer = color_framebuffer;
- depth_framebuffer = light_storage->reflection_probe_instance_get_depth_framebuffer(p_render_data->reflection_probe, p_render_data->reflection_probe_pass);
-
- if (light_storage->reflection_probe_is_interior(light_storage->reflection_probe_instance_get_probe(p_render_data->reflection_probe))) {
- p_render_data->environment = RID(); //no environment on interiors
- }
-
- reverse_cull = true; // for some reason our views are inverted
} else {
ERR_FAIL(); //bug?
}
@@ -1765,6 +1783,10 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
draw_sky = true;
} break;
case RS::ENV_BG_CANVAS: {
+ if (rb.is_valid()) {
+ RID texture = RendererRD::TextureStorage::get_singleton()->render_target_get_rd_texture(rb->get_render_target());
+ copy_effects->copy_to_fb_rect(texture, color_only_framebuffer, Rect2i(), false, false, false, false, RID(), false, false, true);
+ }
keep_color = true;
} break;
case RS::ENV_BG_KEEP: {
@@ -1775,29 +1797,40 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
default: {
}
}
+
// setup sky if used for ambient, reflections, or background
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");
- Projection projection = p_render_data->scene_data->cam_projection;
+
+ // Setup our sky render information for this frame/viewport
if (p_render_data->reflection_probe.is_valid()) {
+ Vector3 eye_offset;
Projection correction;
correction.set_depth_correction(true);
- projection = correction * p_render_data->scene_data->cam_projection;
- }
+ Projection projection = correction * p_render_data->scene_data->cam_projection;
- sky.setup(p_render_data->environment, rb, *p_render_data->lights, p_render_data->camera_attributes, projection, p_render_data->scene_data->cam_transform, screen_size, this);
+ sky.setup_sky(p_render_data->environment, rb, *p_render_data->lights, p_render_data->camera_attributes, 1, &projection, &eye_offset, p_render_data->scene_data->cam_transform, screen_size, this);
+ } else {
+ sky.setup_sky(p_render_data->environment, rb, *p_render_data->lights, p_render_data->camera_attributes, p_render_data->scene_data->view_count, p_render_data->scene_data->view_projection, p_render_data->scene_data->view_eye_offset, p_render_data->scene_data->cam_transform, screen_size, this);
+ }
sky_energy_multiplier *= bg_energy_multiplier;
RID sky_rid = environment_get_sky(p_render_data->environment);
if (sky_rid.is_valid()) {
- sky.update(p_render_data->environment, projection, p_render_data->scene_data->cam_transform, time, sky_energy_multiplier);
+ sky.update_radiance_buffers(rb, p_render_data->environment, p_render_data->scene_data->cam_transform.origin, time, sky_energy_multiplier);
radiance_texture = sky.sky_get_radiance_texture_rd(sky_rid);
} else {
// do not try to draw sky if invalid
draw_sky = false;
}
+
+ if (draw_sky || draw_sky_fog_only) {
+ // update sky half/quarter res buffers (if required)
+ sky.update_res_buffers(rb, p_render_data->environment, time, sky_energy_multiplier);
+ }
+
RD::get_singleton()->draw_command_end_label();
}
} else {
@@ -1947,15 +1980,11 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
RENDER_TIMESTAMP("Render Sky");
RD::get_singleton()->draw_command_begin_label("Draw Sky");
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(color_only_framebuffer, RD::INITIAL_ACTION_CONTINUE, can_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, can_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ);
- if (p_render_data->reflection_probe.is_valid()) {
- Projection correction;
- correction.set_depth_correction(true);
- Projection projection = correction * p_render_data->scene_data->cam_projection;
- sky.draw(p_render_data->environment, can_continue_color, can_continue_depth, color_only_framebuffer, 1, &projection, p_render_data->scene_data->cam_transform, time, sky_energy_multiplier);
- } else {
- sky.draw(p_render_data->environment, can_continue_color, can_continue_depth, color_only_framebuffer, p_render_data->scene_data->view_count, p_render_data->scene_data->view_projection, p_render_data->scene_data->cam_transform, time, sky_energy_multiplier);
- }
+ sky.draw_sky(draw_list, rb, p_render_data->environment, color_only_framebuffer, time, sky_energy_multiplier);
+
+ RD::get_singleton()->draw_list_end();
RD::get_singleton()->draw_command_end_label();
}
@@ -2032,7 +2061,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
RD::get_singleton()->draw_command_begin_label("Resolve");
- if (rb.is_valid() && rb->get_msaa_3d() != RS::VIEWPORT_MSAA_DISABLED) {
+ if (rb_data.is_valid() && rb->get_msaa_3d() != RS::VIEWPORT_MSAA_DISABLED) {
for (uint32_t v = 0; v < rb->get_view_count(); v++) {
RD::get_singleton()->texture_resolve_multisample(rb_data->get_color_msaa(v), rb->get_internal_texture(v));
resolve_effects->resolve_depth(rb_data->get_depth_msaa(v), rb->get_depth_texture(v), rb->get_internal_size(), texture_multisamples[rb->get_msaa_3d()]);
@@ -2051,12 +2080,12 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
}
RD::get_singleton()->draw_command_end_label();
- if (rb.is_valid() && taa && rb->get_use_taa()) {
+ if (rb_data.is_valid() && taa && rb->get_use_taa()) {
RENDER_TIMESTAMP("TAA")
taa->process(rb, _render_buffers_get_color_format(), p_render_data->scene_data->z_near, p_render_data->scene_data->z_far);
}
- if (rb.is_valid()) {
+ if (rb_data.is_valid()) {
_debug_draw_cluster(rb);
RENDER_TIMESTAMP("Tonemap");
@@ -2064,7 +2093,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
_render_buffers_post_process_and_tonemap(p_render_data);
}
- if (rb.is_valid()) {
+ if (rb_data.is_valid()) {
_render_buffers_debug_draw(rb, p_render_data->shadow_atlas, p_render_data->occluder_debug_tex);
if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_SDFGI && rb->has_custom_data(RB_SCOPE_SDFGI)) {
@@ -2311,6 +2340,8 @@ void RenderForwardClustered::_render_shadow_append(RID p_framebuffer, const Page
scene_data.lod_distance_multiplier = p_lod_distance_multiplier;
scene_data.dual_paraboloid_side = p_use_dp_flip ? -1 : 1;
scene_data.opaque_prepass_threshold = 0.1f;
+ scene_data.time = time;
+ scene_data.time_step = time_step;
RenderDataRD render_data;
render_data.scene_data = &scene_data;
@@ -2401,6 +2432,8 @@ void RenderForwardClustered::_render_particle_collider_heightfield(RID p_fb, con
scene_data.z_far = p_cam_projection.get_z_far();
scene_data.dual_paraboloid_side = 0;
scene_data.opaque_prepass_threshold = 0.0;
+ scene_data.time = time;
+ scene_data.time_step = time_step;
RenderDataRD render_data;
render_data.scene_data = &scene_data;
@@ -2443,6 +2476,8 @@ void RenderForwardClustered::_render_material(const Transform3D &p_cam_transform
scene_data.material_uv2_mode = false;
scene_data.opaque_prepass_threshold = 0.0f;
scene_data.emissive_exposure_normalization = p_exposure_normalization;
+ scene_data.time = time;
+ scene_data.time_step = time_step;
RenderDataRD render_data;
render_data.scene_data = &scene_data;
@@ -2848,7 +2883,11 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
Ref<RenderBufferDataForwardClustered> rb_data;
if (p_render_data && p_render_data->render_buffers.is_valid()) {
rb = p_render_data->render_buffers;
- rb_data = rb->get_custom_data(RB_SCOPE_FORWARD_CLUSTERED);
+ if (rb->has_custom_data(RB_SCOPE_FORWARD_CLUSTERED)) {
+ // Our forward clustered custom data buffer will only be available when we're rendering our normal view.
+ // This will not be available when rendering reflection probes.
+ rb_data = rb->get_custom_data(RB_SCOPE_FORWARD_CLUSTERED);
+ }
}
//default render buffer and scene state uniform set
@@ -3083,7 +3122,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
RD::Uniform u;
u.binding = 19;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- RID vfog = RID();
+ RID vfog;
if (rb_data.is_valid() && rb->has_custom_data(RB_SCOPE_FOG)) {
Ref<RendererRD::Fog::VolumetricFog> fog = rb->get_custom_data(RB_SCOPE_FOG);
vfog = fog->fog_map;
@@ -3281,6 +3320,99 @@ void RenderForwardClustered::sub_surface_scattering_set_scale(float p_scale, flo
RenderForwardClustered *RenderForwardClustered::singleton = nullptr;
+void RenderForwardClustered::sdfgi_update(const Ref<RenderSceneBuffers> &p_render_buffers, RID p_environment, const Vector3 &p_world_position) {
+ Ref<RenderSceneBuffersRD> rb = p_render_buffers;
+ ERR_FAIL_COND(rb.is_null());
+ Ref<RendererRD::GI::SDFGI> sdfgi;
+ if (rb->has_custom_data(RB_SCOPE_SDFGI)) {
+ sdfgi = rb->get_custom_data(RB_SCOPE_SDFGI);
+ }
+
+ bool needs_sdfgi = p_environment.is_valid() && environment_get_sdfgi_enabled(p_environment);
+
+ if (!needs_sdfgi) {
+ if (sdfgi.is_valid()) {
+ // delete it
+ sdfgi.unref();
+ rb->set_custom_data(RB_SCOPE_SDFGI, sdfgi);
+ }
+ return;
+ }
+
+ 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 (sdfgi.is_valid() && (sdfgi->num_cascades != environment_get_sdfgi_cascades(p_environment) || sdfgi->min_cell_size != environment_get_sdfgi_min_cell_size(p_environment) || requested_history_size != sdfgi->history_size || sdfgi->uses_occlusion != environment_get_sdfgi_use_occlusion(p_environment) || sdfgi->y_scale_mode != environment_get_sdfgi_y_scale(p_environment))) {
+ //configuration changed, erase
+ sdfgi.unref();
+ rb->set_custom_data(RB_SCOPE_SDFGI, sdfgi);
+ }
+
+ if (sdfgi.is_null()) {
+ // re-create
+ sdfgi = gi.create_sdfgi(p_environment, p_world_position, requested_history_size);
+ rb->set_custom_data(RB_SCOPE_SDFGI, sdfgi);
+ } else {
+ //check for updates
+ sdfgi->update(p_environment, p_world_position);
+ }
+}
+
+int RenderForwardClustered::sdfgi_get_pending_region_count(const Ref<RenderSceneBuffers> &p_render_buffers) const {
+ Ref<RenderSceneBuffersRD> rb = p_render_buffers;
+ ERR_FAIL_COND_V(rb.is_null(), 0);
+
+ if (!rb->has_custom_data(RB_SCOPE_SDFGI)) {
+ return 0;
+ }
+ Ref<RendererRD::GI::SDFGI> sdfgi = rb->get_custom_data(RB_SCOPE_SDFGI);
+
+ int dirty_count = 0;
+ for (uint32_t i = 0; i < sdfgi->cascades.size(); i++) {
+ const RendererRD::GI::SDFGI::Cascade &c = sdfgi->cascades[i];
+
+ if (c.dirty_regions == RendererRD::GI::SDFGI::Cascade::DIRTY_ALL) {
+ dirty_count++;
+ } else {
+ for (int j = 0; j < 3; j++) {
+ if (c.dirty_regions[j] != 0) {
+ dirty_count++;
+ }
+ }
+ }
+ }
+
+ return dirty_count;
+}
+
+AABB RenderForwardClustered::sdfgi_get_pending_region_bounds(const Ref<RenderSceneBuffers> &p_render_buffers, int p_region) const {
+ AABB bounds;
+ Vector3i from;
+ Vector3i size;
+
+ Ref<RenderSceneBuffersRD> rb = p_render_buffers;
+ ERR_FAIL_COND_V(rb.is_null(), AABB());
+ Ref<RendererRD::GI::SDFGI> sdfgi = rb->get_custom_data(RB_SCOPE_SDFGI);
+ ERR_FAIL_COND_V(sdfgi.is_null(), AABB());
+
+ int c = sdfgi->get_pending_region_data(p_region, from, size, bounds);
+ ERR_FAIL_COND_V(c == -1, AABB());
+ return bounds;
+}
+
+uint32_t RenderForwardClustered::sdfgi_get_pending_region_cascade(const Ref<RenderSceneBuffers> &p_render_buffers, int p_region) const {
+ AABB bounds;
+ Vector3i from;
+ Vector3i size;
+
+ Ref<RenderSceneBuffersRD> rb = p_render_buffers;
+ ERR_FAIL_COND_V(rb.is_null(), -1);
+ Ref<RendererRD::GI::SDFGI> sdfgi = rb->get_custom_data(RB_SCOPE_SDFGI);
+ ERR_FAIL_COND_V(sdfgi.is_null(), -1);
+
+ return sdfgi->get_pending_region_data(p_region, from, size, bounds);
+}
+
void RenderForwardClustered::GeometryInstanceForwardClustered::_mark_dirty() {
if (dirty_list_element.in_list()) {
return;
@@ -3368,6 +3500,7 @@ void RenderForwardClustered::_geometry_instance_add_surface_with_material(Geomet
sdcache->flags = flags;
sdcache->shader = p_material->shader_data;
+ sdcache->material = p_material;
sdcache->material_uniform_set = p_material->uniform_set;
sdcache->surface = mesh_storage->mesh_get_surface(p_mesh, p_surface);
sdcache->primitive = mesh_storage->mesh_surface_get_primitive(sdcache->surface);
@@ -3586,6 +3719,10 @@ void RenderForwardClustered::_geometry_instance_update(RenderGeometryInstance *p
}
ginstance->transforms_uniform_set = particles_storage->particles_get_instance_buffer_uniform_set(ginstance->data->base, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET);
+ if (particles_storage->particles_get_frame_counter(ginstance->data->base) == 0) {
+ // Particles haven't been cleared or updated, update once now to ensure they are ready to render.
+ particles_storage->update_particles();
+ }
} else if (ginstance->data->base_type == RS::INSTANCE_MESH) {
if (mesh_storage->skeleton_is_valid(ginstance->data->skeleton)) {
ginstance->transforms_uniform_set = mesh_storage->skeleton_get_3d_uniform_set(ginstance->data->skeleton, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET);
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 670eb93e20..3399382b56 100644
--- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h
+++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h
@@ -210,10 +210,10 @@ class RenderForwardClustered : public RendererSceneRenderRD {
float screen_mesh_lod_threshold = 0.0;
RD::FramebufferFormatID framebuffer_format = 0;
uint32_t element_offset = 0;
- uint32_t barrier = RD::BARRIER_MASK_ALL;
+ uint32_t barrier = RD::BARRIER_MASK_ALL_BARRIERS;
bool use_directional_soft_shadow = false;
- RenderListParameters(GeometryInstanceSurfaceDataCache **p_elements, RenderElementInfo *p_element_info, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, uint32_t p_color_pass_flags, bool p_no_gi, bool p_use_directional_soft_shadows, RID p_render_pass_uniform_set, bool p_force_wireframe = false, const Vector2 &p_uv_offset = Vector2(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, uint32_t p_view_count = 1, uint32_t p_element_offset = 0, uint32_t p_barrier = RD::BARRIER_MASK_ALL) {
+ RenderListParameters(GeometryInstanceSurfaceDataCache **p_elements, RenderElementInfo *p_element_info, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, uint32_t p_color_pass_flags, bool p_no_gi, bool p_use_directional_soft_shadows, RID p_render_pass_uniform_set, bool p_force_wireframe = false, const Vector2 &p_uv_offset = Vector2(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, uint32_t p_view_count = 1, uint32_t p_element_offset = 0, uint32_t p_barrier = RD::BARRIER_MASK_ALL_BARRIERS) {
elements = p_elements;
element_info = p_element_info;
element_count = p_element_count;
@@ -441,6 +441,7 @@ class RenderForwardClustered : public RendererSceneRenderRD {
void *surface = nullptr;
RID material_uniform_set;
SceneShaderForwardClustered::ShaderData *shader = nullptr;
+ SceneShaderForwardClustered::MaterialData *material = nullptr;
void *surface_shadow = nullptr;
RID material_uniform_set_shadow;
@@ -596,7 +597,7 @@ class RenderForwardClustered : public RendererSceneRenderRD {
void _render_shadow_begin();
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, RenderingMethod::RenderInfo *p_render_info = nullptr);
void _render_shadow_process();
- void _render_shadow_end(uint32_t p_barrier = RD::BARRIER_MASK_ALL);
+ void _render_shadow_end(uint32_t p_barrier = RD::BARRIER_MASK_ALL_BARRIERS);
/* Render Scene */
void _process_ssao(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_environment, RID p_normal_buffer, const Projection &p_projection);
@@ -649,6 +650,16 @@ public:
_update_render_base_uniform_set();
}
+ /* SDFGI UPDATE */
+
+ virtual void sdfgi_update(const Ref<RenderSceneBuffers> &p_render_buffers, RID p_environment, const Vector3 &p_world_position) override;
+ virtual int sdfgi_get_pending_region_count(const Ref<RenderSceneBuffers> &p_render_buffers) const override;
+ virtual AABB sdfgi_get_pending_region_bounds(const Ref<RenderSceneBuffers> &p_render_buffers, int p_region) const override;
+ virtual uint32_t sdfgi_get_pending_region_cascade(const Ref<RenderSceneBuffers> &p_render_buffers, int p_region) const override;
+ RID sdfgi_get_ubo() const { return gi.sdfgi_ubo; }
+
+ /* GEOMETRY INSTANCE */
+
virtual RenderGeometryInstance *geometry_instance_create(RID p_base) override;
virtual void geometry_instance_free(RenderGeometryInstance *p_geometry_instance) override;
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 c1b23af82f..914ca25899 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,10 +37,6 @@
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
@@ -115,6 +111,9 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
actions.usage_flag_pointers["ALPHA"] = &uses_alpha;
actions.usage_flag_pointers["ALPHA_SCISSOR_THRESHOLD"] = &uses_alpha_clip;
+ // Use alpha clip pipeline for alpha hash/dither.
+ // This prevents sorting issues inherent to alpha blending and allows such materials to cast shadows.
+ actions.usage_flag_pointers["ALPHA_HASH_SCALE"] = &uses_alpha_clip;
actions.render_mode_flags["depth_prepass_alpha"] = &uses_depth_pre_pass;
actions.usage_flag_pointers["SSS_STRENGTH"] = &uses_sss;
@@ -151,6 +150,8 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
depth_test = DepthTest(depth_testi);
cull_mode = Cull(cull_modei);
uses_screen_texture_mipmaps = gen_code.uses_screen_texture_mipmaps;
+ uses_vertex_time = gen_code.uses_vertex_time;
+ uses_fragment_time = gen_code.uses_fragment_time;
#if 0
print_line("**compiling shader:");
@@ -255,6 +256,7 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
depth_stencil_state.depth_compare_operator = RD::COMPARE_OP_LESS_OR_EQUAL;
depth_stencil_state.enable_depth_write = depth_draw != DEPTH_DRAW_DISABLED ? true : false;
}
+ bool depth_pre_pass_enabled = bool(GLOBAL_GET("rendering/driver/depth_prepass/enable"));
for (int i = 0; i < CULL_VARIANT_MAX; i++) {
RD::PolygonCullMode cull_mode_rd_table[CULL_VARIANT_MAX][3] = {
@@ -306,8 +308,16 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
continue;
}
- RD::PipelineColorBlendState blend_state;
RD::PipelineDepthStencilState depth_stencil = depth_stencil_state;
+ if (depth_pre_pass_enabled && casts_shadows()) {
+ // We already have a depth from the depth pre-pass, there is no need to write it again.
+ // In addition we can use COMPARE_OP_EQUAL instead of COMPARE_OP_LESS_OR_EQUAL.
+ // This way we can use the early depth test to discard transparent fragments before the fragment shader even starts.
+ depth_stencil.depth_compare_operator = RD::COMPARE_OP_EQUAL;
+ depth_stencil.enable_depth_write = false;
+ }
+
+ RD::PipelineColorBlendState blend_state;
RD::PipelineMultisampleState multisample_state;
int shader_flags = 0;
@@ -375,102 +385,16 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
valid = true;
}
-void SceneShaderForwardClustered::ShaderData::set_default_texture_parameter(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 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) {
- if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_LOCAL ||
- E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_SCREEN_TEXTURE ||
- E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE ||
- E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_DEPTH_TEXTURE) {
- // Don't expose any of these.
- 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 SceneShaderForwardClustered::ShaderData::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 SceneShaderForwardClustered::ShaderData::is_parameter_texture(const StringName &p_param) const {
- if (!uniforms.has(p_param)) {
- return false;
- }
-
- return uniforms[p_param].texture_order >= 0;
-}
-
bool SceneShaderForwardClustered::ShaderData::is_animated() const {
- return false;
+ return (uses_fragment_time && uses_discard) || (uses_vertex_time && uses_vertex);
}
bool SceneShaderForwardClustered::ShaderData::casts_shadows() const {
- return false;
-}
+ bool has_read_screen_alpha = uses_screen_texture || uses_depth_texture || uses_normal_texture;
+ bool has_base_alpha = (uses_alpha && !uses_alpha_clip) || has_read_screen_alpha;
+ bool has_alpha = has_base_alpha || uses_blend_alpha;
-Variant SceneShaderForwardClustered::ShaderData::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();
+ return !has_alpha || (uses_depth_pre_pass && !(depth_draw == DEPTH_DRAW_DISABLED || depth_test == DEPTH_TEST_DISABLED));
}
RS::ShaderNativeSourceCode SceneShaderForwardClustered::ShaderData::get_native_source_code() const {
@@ -700,6 +624,7 @@ void SceneShaderForwardClustered::init(const String p_defines) {
actions.renames["NODE_POSITION_WORLD"] = "read_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["CAMERA_VISIBLE_LAYERS"] = "scene_data.camera_visible_layers";
actions.renames["NODE_POSITION_VIEW"] = "(read_model_matrix * scene_data.view_matrix)[3].xyz";
actions.renames["VIEW_INDEX"] = "ViewIndex";
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 a9a9fa94de..51e4dd44d5 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
@@ -139,19 +139,15 @@ public:
PipelineCacheRD pipelines[CULL_VARIANT_MAX][RS::PRIMITIVE_MAX][PIPELINE_VERSION_MAX];
PipelineCacheRD color_pipelines[CULL_VARIANT_MAX][RS::PRIMITIVE_MAX][PIPELINE_COLOR_PASS_FLAG_COUNT];
- String path;
-
- HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms;
Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms;
Vector<uint32_t> ubo_offsets;
uint32_t ubo_size = 0;
String code;
- HashMap<StringName, HashMap<int, RID>> default_texture_params;
- DepthDraw depth_draw;
- DepthTest depth_test;
+ DepthDraw depth_draw = DEPTH_DRAW_OPAQUE;
+ DepthTest depth_test = DEPTH_TEST_ENABLED;
bool uses_point_size = false;
bool uses_alpha = false;
@@ -172,6 +168,8 @@ public:
bool uses_depth_texture = false;
bool uses_normal_texture = false;
bool uses_time = false;
+ bool uses_vertex_time = false;
+ bool uses_fragment_time = false;
bool writes_modelview_or_projection = false;
bool uses_world_coordinates = false;
bool uses_screen_texture_mipmaps = false;
@@ -181,15 +179,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_parameter(const StringName &p_name, RID p_texture, int p_index);
- 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_parameter_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;
SelfList<ShaderData> shader_list_element;
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 898521ca4d..53bcb1c038 100644
--- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
+++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
@@ -70,17 +70,17 @@ void RenderForwardMobile::ForwardIDStorageMobile::map_forward_id(RendererRD::For
void RenderForwardMobile::ForwardIDStorageMobile::fill_push_constant_instance_indices(GeometryInstanceForwardMobile::PushConstant *p_push_constant, uint32_t &spec_constants, const GeometryInstanceForwardMobile *p_instance) {
// first zero out our indices
- p_push_constant->omni_lights[0] = 0xFFFF;
- p_push_constant->omni_lights[1] = 0xFFFF;
+ p_push_constant->omni_lights[0] = 0xFFFFFFFF;
+ p_push_constant->omni_lights[1] = 0xFFFFFFFF;
- p_push_constant->spot_lights[0] = 0xFFFF;
- p_push_constant->spot_lights[1] = 0xFFFF;
+ p_push_constant->spot_lights[0] = 0xFFFFFFFF;
+ p_push_constant->spot_lights[1] = 0xFFFFFFFF;
- p_push_constant->decals[0] = 0xFFFF;
- p_push_constant->decals[1] = 0xFFFF;
+ p_push_constant->decals[0] = 0xFFFFFFFF;
+ p_push_constant->decals[1] = 0xFFFFFFFF;
- p_push_constant->reflection_probes[0] = 0xFFFF;
- p_push_constant->reflection_probes[1] = 0xFFFF;
+ p_push_constant->reflection_probes[0] = 0xFFFFFFFF;
+ p_push_constant->reflection_probes[1] = 0xFFFFFFFF;
if (p_instance->omni_light_count == 0) {
spec_constants |= 1 << SPEC_CONSTANT_DISABLE_OMNI_LIGHTS;
@@ -154,8 +154,8 @@ void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RenderSceneBu
render_buffers->create_texture(RB_SCOPE_MOBILE, RB_TEX_COLOR_MSAA, format, usage_bits, texture_samples);
- 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;
usage_bits = RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT;
+ format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D24_UNORM_S8_UINT, usage_bits) ? RD::DATA_FORMAT_D24_UNORM_S8_UINT : RD::DATA_FORMAT_D32_SFLOAT_S8_UINT;
render_buffers->create_texture(RB_SCOPE_MOBILE, RB_TEX_DEPTH_MSAA, format, usage_bits, texture_samples);
}
@@ -361,7 +361,11 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_
Ref<RenderSceneBuffersRD> rb;
if (p_render_data && p_render_data->render_buffers.is_valid()) {
rb = p_render_data->render_buffers;
- rb_data = rb->get_custom_data(RB_SCOPE_MOBILE);
+ if (rb->has_custom_data(RB_SCOPE_MOBILE)) {
+ // Our forward mobile custom data buffer will only be available when we're rendering our normal view.
+ // This will not be available when rendering reflection probes.
+ rb_data = rb->get_custom_data(RB_SCOPE_MOBILE);
+ }
}
// default render buffer and scene state uniform set
@@ -612,7 +616,7 @@ void RenderForwardMobile::_pre_opaque_render(RenderDataRD *p_render_data) {
}
//full barrier here, we need raster, transfer and compute and it depends from the previous work
- RD::get_singleton()->barrier(RD::BARRIER_MASK_ALL, RD::BARRIER_MASK_ALL);
+ RD::get_singleton()->barrier(RD::BARRIER_MASK_ALL_BARRIERS, RD::BARRIER_MASK_ALL_BARRIERS);
bool using_shadows = true;
@@ -640,7 +644,11 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
Ref<RenderBufferDataForwardMobile> rb_data;
if (p_render_data->render_buffers.is_valid()) {
rb = p_render_data->render_buffers;
- rb_data = rb->get_custom_data(RB_SCOPE_MOBILE);
+ if (rb->has_custom_data(RB_SCOPE_MOBILE)) {
+ // Our forward mobile custom data buffer will only be available when we're rendering our normal view.
+ // This will not be available when rendering reflection probes.
+ rb_data = rb->get_custom_data(RB_SCOPE_MOBILE);
+ }
}
RENDER_TIMESTAMP("Prepare 3D Scene");
@@ -673,7 +681,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
Size2i screen_size;
RID framebuffer;
- bool reverse_cull = false;
+ bool reverse_cull = p_render_data->scene_data->cam_transform.basis.determinant() < 0;
bool using_subpass_transparent = true;
bool using_subpass_post_process = true;
@@ -689,7 +697,21 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_VISIBLE][RS::VIEWPORT_RENDER_INFO_OBJECTS_IN_FRAME] = p_render_data->instances->size();
}
- if (rb_data.is_valid()) {
+ if (p_render_data->reflection_probe.is_valid()) {
+ uint32_t resolution = light_storage->reflection_probe_instance_get_resolution(p_render_data->reflection_probe);
+ screen_size.x = resolution;
+ screen_size.y = resolution;
+
+ framebuffer = light_storage->reflection_probe_instance_get_framebuffer(p_render_data->reflection_probe, p_render_data->reflection_probe_pass);
+
+ if (light_storage->reflection_probe_is_interior(light_storage->reflection_probe_instance_get_probe(p_render_data->reflection_probe))) {
+ p_render_data->environment = RID(); //no environment on interiors
+ }
+
+ reverse_cull = true;
+ using_subpass_transparent = true; // we ignore our screen/depth texture here
+ using_subpass_post_process = false; // not applicable at all for reflection probes.
+ } else if (rb_data.is_valid()) {
// setup rendering to render buffer
screen_size = p_render_data->render_buffers->get_internal_size();
@@ -717,20 +739,6 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
// only opaque and sky as subpasses
framebuffer = rb_data->get_color_fbs(RenderBufferDataForwardMobile::FB_CONFIG_TWO_SUBPASSES);
}
- } else if (p_render_data->reflection_probe.is_valid()) {
- uint32_t resolution = light_storage->reflection_probe_instance_get_resolution(p_render_data->reflection_probe);
- screen_size.x = resolution;
- screen_size.y = resolution;
-
- framebuffer = light_storage->reflection_probe_instance_get_framebuffer(p_render_data->reflection_probe, p_render_data->reflection_probe_pass);
-
- if (light_storage->reflection_probe_is_interior(light_storage->reflection_probe_instance_get_probe(p_render_data->reflection_probe))) {
- p_render_data->environment = RID(); //no environment on interiors
- }
-
- reverse_cull = true;
- using_subpass_transparent = true; // we ignore our screen/depth texture here
- using_subpass_post_process = false; // not applicable at all for reflection probes.
} else {
ERR_FAIL(); //bug?
}
@@ -796,6 +804,11 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
draw_sky = true;
} break;
case RS::ENV_BG_CANVAS: {
+ if (rb_data.is_valid()) {
+ RID dest_framebuffer = rb_data->get_color_fbs(RenderBufferDataForwardMobile::FB_CONFIG_ONE_PASS);
+ RID texture = RendererRD::TextureStorage::get_singleton()->render_target_get_rd_texture(rb->get_render_target());
+ copy_effects->copy_to_fb_rect(texture, dest_framebuffer, Rect2i(), false, false, false, false, RID(), false, false, true);
+ }
keep_color = true;
} break;
case RS::ENV_BG_KEEP: {
@@ -806,55 +819,45 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
default: {
}
}
+
// setup sky if used for ambient, reflections, or background
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");
- Projection projection = p_render_data->scene_data->cam_projection;
+
+ // Setup our sky render information for this frame/viewport
if (p_render_data->reflection_probe.is_valid()) {
+ Vector3 eye_offset;
Projection correction;
correction.set_depth_correction(true);
- projection = correction * p_render_data->scene_data->cam_projection;
- }
+ Projection projection = correction * p_render_data->scene_data->cam_projection;
- sky.setup(p_render_data->environment, p_render_data->render_buffers, *p_render_data->lights, p_render_data->camera_attributes, projection, p_render_data->scene_data->cam_transform, screen_size, this);
+ sky.setup_sky(p_render_data->environment, p_render_data->render_buffers, *p_render_data->lights, p_render_data->camera_attributes, 1, &projection, &eye_offset, p_render_data->scene_data->cam_transform, screen_size, this);
+ } else {
+ sky.setup_sky(p_render_data->environment, p_render_data->render_buffers, *p_render_data->lights, p_render_data->camera_attributes, p_render_data->scene_data->view_count, p_render_data->scene_data->view_projection, p_render_data->scene_data->view_eye_offset, p_render_data->scene_data->cam_transform, screen_size, this);
+ }
sky_energy_multiplier *= bg_energy_multiplier;
RID sky_rid = environment_get_sky(p_render_data->environment);
if (sky_rid.is_valid()) {
- sky.update(p_render_data->environment, projection, p_render_data->scene_data->cam_transform, time, sky_energy_multiplier);
+ sky.update_radiance_buffers(rb, p_render_data->environment, p_render_data->scene_data->cam_transform.origin, time, sky_energy_multiplier);
radiance_texture = sky.sky_get_radiance_texture_rd(sky_rid);
} else {
// do not try to draw sky if invalid
draw_sky = false;
}
+
+ if (draw_sky || draw_sky_fog_only) {
+ // update sky half/quarter res buffers (if required)
+ sky.update_res_buffers(rb, p_render_data->environment, time, sky_energy_multiplier);
+ }
RD::get_singleton()->draw_command_end_label(); // Setup Sky
}
} else {
clear_color = p_default_bg_color;
}
- // update sky buffers (if required)
- if (draw_sky || draw_sky_fog_only) {
- // !BAS! @TODO See if we can limit doing some things double and maybe even move this into _pre_opaque_render
- // and change Forward Clustered in the same way as we have here (but without using subpasses)
- RENDER_TIMESTAMP("Setup Sky Resolution Buffers");
-
- RD::get_singleton()->draw_command_begin_label("Setup Sky Resolution Buffers");
-
- if (p_render_data->reflection_probe.is_valid()) {
- Projection correction;
- correction.set_depth_correction(true);
- Projection projection = correction * p_render_data->scene_data->cam_projection;
- sky.update_res_buffers(p_render_data->environment, 1, &projection, p_render_data->scene_data->cam_transform, time, sky_energy_multiplier);
- } else {
- sky.update_res_buffers(p_render_data->environment, p_render_data->scene_data->view_count, p_render_data->scene_data->view_projection, p_render_data->scene_data->cam_transform, time, sky_energy_multiplier);
- }
-
- RD::get_singleton()->draw_command_end_label(); // Setup Sky resolution buffers
- }
-
_pre_opaque_render(p_render_data);
uint32_t spec_constant_base_flags = 0;
@@ -939,16 +942,11 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
if (draw_sky || draw_sky_fog_only) {
RD::get_singleton()->draw_command_begin_label("Draw Sky Subpass");
+ // Note, sky.setup should have been called up above and setup stuff we need.
+
RD::DrawListID draw_list = RD::get_singleton()->draw_list_switch_to_next_pass();
- if (p_render_data->reflection_probe.is_valid()) {
- Projection correction;
- correction.set_depth_correction(true);
- Projection projection = correction * p_render_data->scene_data->cam_projection;
- sky.draw(draw_list, p_render_data->environment, framebuffer, 1, &projection, p_render_data->scene_data->cam_transform, time, sky_energy_multiplier);
- } else {
- sky.draw(draw_list, p_render_data->environment, framebuffer, p_render_data->scene_data->view_count, p_render_data->scene_data->view_projection, p_render_data->scene_data->cam_transform, time, sky_energy_multiplier);
- }
+ sky.draw_sky(draw_list, rb, p_render_data->environment, framebuffer, time, sky_energy_multiplier);
RD::get_singleton()->draw_command_end_label(); // Draw Sky Subpass
@@ -960,7 +958,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
if (!using_subpass_transparent) {
// We're done with our subpasses so end our container pass
- RD::get_singleton()->draw_list_end(RD::BARRIER_MASK_ALL);
+ RD::get_singleton()->draw_list_end(RD::BARRIER_MASK_ALL_BARRIERS);
RD::get_singleton()->draw_command_end_label(); // Render 3D Pass / Render Reflection Probe Pass
}
@@ -1012,11 +1010,13 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
RD::get_singleton()->draw_command_end_label(); // Render 3D Pass / Render Reflection Probe Pass
- RD::get_singleton()->draw_list_end(RD::BARRIER_MASK_ALL);
+ RD::get_singleton()->draw_list_end(RD::BARRIER_MASK_ALL_BARRIERS);
} else {
RENDER_TIMESTAMP("Render Transparent");
- framebuffer = rb_data->get_color_fbs(RenderBufferDataForwardMobile::FB_CONFIG_ONE_PASS);
+ if (rb_data.is_valid()) {
+ framebuffer = rb_data->get_color_fbs(RenderBufferDataForwardMobile::FB_CONFIG_ONE_PASS);
+ }
// this may be needed if we re-introduced steps that change info, not sure which do so in the previous implementation
// _setup_environment(p_render_data, p_render_data->reflection_probe.is_valid(), screen_size, !p_render_data->reflection_probe.is_valid(), p_default_bg_color, false);
@@ -1032,12 +1032,12 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
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);
+ RD::get_singleton()->draw_list_end(RD::BARRIER_MASK_ALL_BARRIERS);
} else {
//single threaded
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, 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);
_render_list(draw_list, fb_format, &render_list_params, 0, render_list_params.element_count);
- RD::get_singleton()->draw_list_end(RD::BARRIER_MASK_ALL);
+ RD::get_singleton()->draw_list_end(RD::BARRIER_MASK_ALL_BARRIERS);
}
RD::get_singleton()->draw_command_end_label(); // Render Transparent Subpass
@@ -1269,6 +1269,8 @@ void RenderForwardMobile::_render_shadow_append(RID p_framebuffer, const PagedAr
scene_data.lod_distance_multiplier = p_lod_distance_multiplier;
scene_data.dual_paraboloid_side = p_use_dp_flip ? -1 : 1;
scene_data.opaque_prepass_threshold = 0.1;
+ scene_data.time = time;
+ scene_data.time_step = time_step;
RenderDataRD render_data;
render_data.scene_data = &scene_data;
@@ -1361,6 +1363,8 @@ void RenderForwardMobile::_render_material(const Transform3D &p_cam_transform, c
scene_data.material_uv2_mode = false;
scene_data.opaque_prepass_threshold = 0.0f;
scene_data.emissive_exposure_normalization = p_exposure_normalization;
+ scene_data.time = time;
+ scene_data.time_step = time_step;
RenderDataRD render_data;
render_data.scene_data = &scene_data;
@@ -1484,6 +1488,8 @@ void RenderForwardMobile::_render_particle_collider_heightfield(RID p_fb, const
scene_data.z_far = p_cam_projection.get_z_far();
scene_data.dual_paraboloid_side = 0;
scene_data.opaque_prepass_threshold = 0.0;
+ scene_data.time = time;
+ scene_data.time_step = time_step;
RenderDataRD render_data;
render_data.scene_data = &scene_data;
@@ -1746,8 +1752,18 @@ void RenderForwardMobile::_fill_render_list(RenderListType p_render_list, const
for (int i = 0; i < (int)p_render_data->instances->size(); i++) {
GeometryInstanceForwardMobile *inst = static_cast<GeometryInstanceForwardMobile *>((*p_render_data->instances)[i]);
- Vector3 support_min = inst->transformed_aabb.get_support(-near_plane.normal);
- inst->depth = near_plane.distance_to(support_min);
+ Vector3 center = inst->transform.origin;
+ if (p_render_data->scene_data->cam_orthogonal) {
+ if (inst->use_aabb_center) {
+ center = inst->transformed_aabb.get_support(-near_plane.normal);
+ }
+ inst->depth = near_plane.distance_to(center) - inst->sorting_offset;
+ } else {
+ if (inst->use_aabb_center) {
+ center = inst->transformed_aabb.position + (inst->transformed_aabb.size * 0.5);
+ }
+ inst->depth = p_render_data->scene_data->cam_transform.origin.distance_to(center) - inst->sorting_offset;
+ }
uint32_t depth_layer = CLAMP(int(inst->depth * 16 / z_max), 0, 15);
uint32_t flags = inst->base_flags; //fill flags if appropriate
@@ -2081,6 +2097,7 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr
#endif
material_uniform_set = surf->material_uniform_set;
shader = surf->shader;
+ surf->material->set_as_used();
#ifdef DEBUG_ENABLED
}
#endif
@@ -2396,6 +2413,7 @@ void RenderForwardMobile::_geometry_instance_add_surface_with_material(GeometryI
sdcache->flags = flags;
sdcache->shader = p_material->shader_data;
+ sdcache->material = p_material;
sdcache->material_uniform_set = p_material->uniform_set;
sdcache->surface = mesh_storage->mesh_get_surface(p_mesh, p_surface);
sdcache->primitive = mesh_storage->mesh_surface_get_primitive(sdcache->surface);
@@ -2613,6 +2631,10 @@ void RenderForwardMobile::_geometry_instance_update(RenderGeometryInstance *p_ge
}
ginstance->transforms_uniform_set = particles_storage->particles_get_instance_buffer_uniform_set(ginstance->data->base, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET);
+ if (particles_storage->particles_get_frame_counter(ginstance->data->base) == 0) {
+ // Particles haven't been cleared or updated, update once now to ensure they are ready to render.
+ particles_storage->update_particles();
+ }
} else if (ginstance->data->base_type == RS::INSTANCE_MESH) {
if (mesh_storage->skeleton_is_valid(ginstance->data->skeleton)) {
ginstance->transforms_uniform_set = mesh_storage->skeleton_get_3d_uniform_set(ginstance->data->skeleton, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET);
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 ce64d805b7..7ed6061def 100644
--- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h
+++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h
@@ -168,10 +168,10 @@ private:
float screen_mesh_lod_threshold = 0.0;
RD::FramebufferFormatID framebuffer_format = 0;
uint32_t element_offset = 0;
- uint32_t barrier = RD::BARRIER_MASK_ALL;
+ uint32_t barrier = RD::BARRIER_MASK_ALL_BARRIERS;
uint32_t subpass = 0;
- RenderListParameters(GeometryInstanceSurfaceDataCache **p_elements, RenderElementInfo *p_element_info, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, RID p_render_pass_uniform_set, uint32_t p_spec_constant_base_flags = 0, bool p_force_wireframe = false, const Vector2 &p_uv_offset = Vector2(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, uint32_t p_view_count = 1, uint32_t p_element_offset = 0, uint32_t p_barrier = RD::BARRIER_MASK_ALL) {
+ RenderListParameters(GeometryInstanceSurfaceDataCache **p_elements, RenderElementInfo *p_element_info, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, RID p_render_pass_uniform_set, uint32_t p_spec_constant_base_flags = 0, bool p_force_wireframe = false, const Vector2 &p_uv_offset = Vector2(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, uint32_t p_view_count = 1, uint32_t p_element_offset = 0, uint32_t p_barrier = RD::BARRIER_MASK_ALL_BARRIERS) {
elements = p_elements;
element_info = p_element_info;
element_count = p_element_count;
@@ -196,7 +196,7 @@ private:
void _render_shadow_begin();
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, RenderingMethod::RenderInfo *p_render_info = nullptr);
void _render_shadow_process();
- void _render_shadow_end(uint32_t p_barrier = RD::BARRIER_MASK_ALL);
+ void _render_shadow_end(uint32_t p_barrier = RD::BARRIER_MASK_ALL_BARRIERS);
/* Render Scene */
@@ -440,6 +440,7 @@ protected:
void *surface = nullptr;
RID material_uniform_set;
SceneShaderForwardMobile::ShaderData *shader = nullptr;
+ SceneShaderForwardMobile::MaterialData *material = nullptr;
void *surface_shadow = nullptr;
RID material_uniform_set_shadow;
@@ -554,6 +555,15 @@ public:
virtual RID reflection_probe_create_framebuffer(RID p_color, RID p_depth) override;
+ /* SDFGI UPDATE */
+
+ virtual void sdfgi_update(const Ref<RenderSceneBuffers> &p_render_buffers, RID p_environment, const Vector3 &p_world_position) override {}
+ virtual int sdfgi_get_pending_region_count(const Ref<RenderSceneBuffers> &p_render_buffers) const override { return 0; }
+ virtual AABB sdfgi_get_pending_region_bounds(const Ref<RenderSceneBuffers> &p_render_buffers, int p_region) const override { return AABB(); }
+ virtual uint32_t sdfgi_get_pending_region_cascade(const Ref<RenderSceneBuffers> &p_render_buffers, int p_region) const override { return 0; }
+
+ /* GEOMETRY INSTANCE */
+
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);
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 02bd30d32d..224bb34189 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,10 +39,6 @@ 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
@@ -116,6 +112,9 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) {
actions.usage_flag_pointers["ALPHA"] = &uses_alpha;
actions.usage_flag_pointers["ALPHA_SCISSOR_THRESHOLD"] = &uses_alpha_clip;
+ // Use alpha clip pipeline for alpha hash/dither.
+ // This prevents sorting issues inherent to alpha blending and allows such materials to cast shadows.
+ actions.usage_flag_pointers["ALPHA_HASH_SCALE"] = &uses_alpha_clip;
actions.render_mode_flags["depth_prepass_alpha"] = &uses_depth_pre_pass;
// actions.usage_flag_pointers["SSS_STRENGTH"] = &uses_sss;
@@ -150,6 +149,8 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) {
depth_draw = DepthDraw(depth_drawi);
depth_test = DepthTest(depth_testi);
+ uses_vertex_time = gen_code.uses_vertex_time;
+ uses_fragment_time = gen_code.uses_fragment_time;
#if 0
print_line("**compiling shader:");
@@ -331,101 +332,16 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) {
valid = true;
}
-void SceneShaderForwardMobile::ShaderData::set_default_texture_parameter(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 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) {
- if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_LOCAL ||
- E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_SCREEN_TEXTURE ||
- E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE ||
- E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_DEPTH_TEXTURE) {
- 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 SceneShaderForwardMobile::ShaderData::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 SceneShaderForwardMobile::ShaderData::is_parameter_texture(const StringName &p_param) const {
- if (!uniforms.has(p_param)) {
- return false;
- }
-
- return uniforms[p_param].texture_order >= 0;
-}
-
bool SceneShaderForwardMobile::ShaderData::is_animated() const {
- return false;
+ return (uses_fragment_time && uses_discard) || (uses_vertex_time && uses_vertex);
}
bool SceneShaderForwardMobile::ShaderData::casts_shadows() const {
- return false;
-}
+ bool has_read_screen_alpha = uses_screen_texture || uses_depth_texture || uses_normal_texture;
+ bool has_base_alpha = (uses_alpha && !uses_alpha_clip) || has_read_screen_alpha;
+ bool has_alpha = has_base_alpha || uses_blend_alpha;
-Variant SceneShaderForwardMobile::ShaderData::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();
+ return !has_alpha || (uses_depth_pre_pass && !(depth_draw == DEPTH_DRAW_DISABLED || depth_test == DEPTH_TEST_DISABLED));
}
RS::ShaderNativeSourceCode SceneShaderForwardMobile::ShaderData::get_native_source_code() const {
@@ -600,6 +516,7 @@ void SceneShaderForwardMobile::init(const String p_defines) {
actions.renames["NODE_POSITION_WORLD"] = "read_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["CAMERA_VISIBLE_LAYERS"] = "scene_data.camera_visible_layers";
actions.renames["NODE_POSITION_VIEW"] = "(read_model_matrix * scene_data.view_matrix)[3].xyz";
actions.renames["VIEW_INDEX"] = "ViewIndex";
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 f67665a02f..18a897a9e9 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
@@ -100,16 +100,12 @@ public:
uint32_t vertex_input_mask = 0;
PipelineCacheRD pipelines[CULL_VARIANT_MAX][RS::PRIMITIVE_MAX][SHADER_VERSION_MAX];
- String path;
-
- HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms;
Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms;
Vector<uint32_t> ubo_offsets;
uint32_t ubo_size = 0;
String code;
- HashMap<StringName, HashMap<int, RID>> default_texture_params;
DepthDraw depth_draw;
DepthTest depth_test;
@@ -132,6 +128,8 @@ public:
bool uses_depth_texture = false;
bool uses_normal_texture = false;
bool uses_time = false;
+ bool uses_vertex_time = false;
+ bool uses_fragment_time = false;
bool writes_modelview_or_projection = false;
bool uses_world_coordinates = false;
@@ -139,16 +137,8 @@ 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_parameter(const StringName &p_name, RID p_texture, int p_index);
- 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_parameter_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;
SelfList<ShaderData> shader_list_element;
diff --git a/servers/rendering/renderer_rd/framebuffer_cache_rd.h b/servers/rendering/renderer_rd/framebuffer_cache_rd.h
index f50d6baa30..8cf25cf44a 100644
--- a/servers/rendering/renderer_rd/framebuffer_cache_rd.h
+++ b/servers/rendering/renderer_rd/framebuffer_cache_rd.h
@@ -254,11 +254,11 @@ public:
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());
+ h = hash_murmur3_one_32(p_textures.size(), h);
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());
+ h = hash_murmur3_one_32(p_passes.size(), h);
for (int i = 0; i < p_passes.size(); i++) {
h = _hash_pass(p_passes[i], h);
}
diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
index 7e0070f8b7..96690ceac1 100644
--- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
@@ -398,7 +398,7 @@ void RendererCanvasRenderRD::_bind_canvas_texture(RD::DrawListID p_draw_list, RI
r_last_texture = p_texture;
}
-void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_render_target, const Item *p_item, RD::FramebufferFormatID p_framebuffer_format, const Transform2D &p_canvas_transform_inverse, Item *&current_clip, Light *p_lights, PipelineVariants *p_pipeline_variants) {
+void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_render_target, const Item *p_item, RD::FramebufferFormatID p_framebuffer_format, const Transform2D &p_canvas_transform_inverse, Item *&current_clip, Light *p_lights, PipelineVariants *p_pipeline_variants, bool &r_sdf_used) {
//create an empty push constant
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton();
@@ -790,13 +790,12 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend
ERR_BREAK(particles_storage->particles_get_mode(pt->particles) != RS::PARTICLES_MODE_2D);
particles_storage->particles_request_process(pt->particles);
- if (particles_storage->particles_is_inactive(pt->particles)) {
+ if (particles_storage->particles_is_inactive(pt->particles) || particles_storage->particles_get_frame_counter(pt->particles) == 0) {
break;
}
RenderingServerDefault::redraw_request(); // active particles means redraw request
- bool local_coords = true;
int dpc = particles_storage->particles_get_draw_passes(pt->particles);
if (dpc == 0) {
break; //nothing to draw
@@ -818,12 +817,7 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend
if (particles_storage->particles_has_collision(pt->particles) && texture_storage->render_target_is_sdf_enabled(p_render_target)) {
//pass collision information
- Transform2D xform;
- if (local_coords) {
- xform = p_item->final_transform;
- } else {
- xform = p_canvas_transform_inverse;
- }
+ Transform2D xform = p_item->final_transform;
RID sdf_texture = texture_storage->render_target_get_sdf_texture(p_render_target);
@@ -839,6 +833,9 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend
} else {
particles_storage->particles_set_canvas_sdf_collision(pt->particles, false, Transform2D(), Rect2(), RID());
}
+
+ // Signal that SDF texture needs to be updated.
+ r_sdf_used |= particles_storage->particles_has_collision(pt->particles);
}
if (mesh.is_null()) {
@@ -1051,7 +1048,7 @@ RID RendererCanvasRenderRD::_create_base_uniform_set(RID p_to_render_target, boo
return uniform_set;
}
-void RendererCanvasRenderRD::_render_items(RID p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights, bool p_to_backbuffer) {
+void RendererCanvasRenderRD::_render_items(RID p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights, bool &r_sdf_used, bool p_to_backbuffer) {
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
@@ -1139,6 +1136,7 @@ void RendererCanvasRenderRD::_render_items(RID p_to_render_target, int p_item_co
// Update uniform set.
if (material_data->uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(material_data->uniform_set)) { // Material may not have a uniform set.
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, material_data->uniform_set, MATERIAL_UNIFORM_SET);
+ material_data->set_as_used();
}
} else {
pipeline_variants = &shader.pipeline_variants;
@@ -1148,7 +1146,7 @@ void RendererCanvasRenderRD::_render_items(RID p_to_render_target, int p_item_co
}
}
- _render_item(draw_list, p_to_render_target, ci, fb_format, canvas_transform_inverse, current_clip, p_lights, pipeline_variants);
+ _render_item(draw_list, p_to_render_target, ci, fb_format, canvas_transform_inverse, current_clip, p_lights, pipeline_variants, r_sdf_used);
prev_material = material;
}
@@ -1446,7 +1444,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
update_skeletons = false;
}
- _render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list);
+ _render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list, r_sdf_used);
item_count = 0;
if (ci->canvas_group_owner->canvas_group->mode != RS::CANVAS_GROUP_MODE_TRANSPARENT) {
@@ -1478,7 +1476,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
update_skeletons = false;
}
- _render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list, true);
+ _render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list, r_sdf_used, true);
item_count = 0;
if (ci->canvas_group->blur_mipmaps) {
@@ -1497,7 +1495,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
update_skeletons = false;
}
- _render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list);
+ _render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list, r_sdf_used);
item_count = 0;
texture_storage->render_target_copy_to_back_buffer(p_to_render_target, back_buffer_rect, backbuffer_gen_mipmaps);
@@ -1523,7 +1521,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
update_skeletons = false;
}
- _render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list);
+ _render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list, r_sdf_used, false);
//then reset
item_count = 0;
}
@@ -2004,10 +2002,6 @@ 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
@@ -2219,86 +2213,6 @@ void RendererCanvasRenderRD::CanvasShaderData::set_code(const String &p_code) {
valid = true;
}
-void RendererCanvasRenderRD::CanvasShaderData::set_default_texture_parameter(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 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) {
- if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_LOCAL ||
- E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_SCREEN_TEXTURE ||
- E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE ||
- E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_DEPTH_TEXTURE) {
- // Don't expose any of these.
- 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 RendererCanvasRenderRD::CanvasShaderData::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 RendererCanvasRenderRD::CanvasShaderData::is_parameter_texture(const StringName &p_param) const {
- if (!uniforms.has(p_param)) {
- return false;
- }
-
- return uniforms[p_param].texture_order >= 0;
-}
-
bool RendererCanvasRenderRD::CanvasShaderData::is_animated() const {
return false;
}
@@ -2307,15 +2221,6 @@ bool RendererCanvasRenderRD::CanvasShaderData::casts_shadows() const {
return false;
}
-Variant RendererCanvasRenderRD::CanvasShaderData::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 RendererCanvasRenderRD::CanvasShaderData::get_native_source_code() const {
RendererCanvasRenderRD *canvas_singleton = static_cast<RendererCanvasRenderRD *>(RendererCanvasRender::singleton);
return canvas_singleton->shader.canvas_shader.version_get_native_source_code(version);
@@ -2681,16 +2586,6 @@ RendererCanvasRenderRD::RendererCanvasRenderRD() {
primitive_arrays.index_array[3] = shader.quad_index_array = RD::get_singleton()->index_array_create(shader.quad_index_buffer, 0, 6);
}
- { //default skeleton buffer
-
- shader.default_skeleton_uniform_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(SkeletonUniform));
- SkeletonUniform su;
- _update_transform_2d_to_mat4(Transform2D(), su.skeleton_inverse);
- _update_transform_2d_to_mat4(Transform2D(), su.skeleton_transform);
- RD::get_singleton()->buffer_update(shader.default_skeleton_uniform_buffer, 0, sizeof(SkeletonUniform), &su);
-
- shader.default_skeleton_texture_buffer = RD::get_singleton()->texture_buffer_create(32, RD::DATA_FORMAT_R32G32B32A32_SFLOAT);
- }
{
//default shadow texture to keep uniform set happy
RD::TextureFormat tf;
@@ -2834,8 +2729,6 @@ RendererCanvasRenderRD::~RendererCanvasRenderRD() {
memdelete_arr(state.light_uniforms);
RD::get_singleton()->free(state.lights_uniform_buffer);
- RD::get_singleton()->free(shader.default_skeleton_uniform_buffer);
- RD::get_singleton()->free(shader.default_skeleton_texture_buffer);
}
//shadow rendering
diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h
index d1f3c9ec6a..f809c7f046 100644
--- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h
+++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h
@@ -144,10 +144,6 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
RID quad_index_array;
PipelineVariants pipeline_variants;
- // default_skeleton uniform set
- RID default_skeleton_uniform_buffer;
- RID default_skeleton_texture_buffer;
-
ShaderCompiler compiler;
} shader;
@@ -164,16 +160,13 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
bool valid = false;
RID version;
PipelineVariants pipeline_variants;
- String path;
- HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms;
Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms;
Vector<uint32_t> ubo_offsets;
uint32_t ubo_size = 0;
String code;
- HashMap<StringName, HashMap<int, RID>> default_texture_params;
bool uses_screen_texture = false;
bool uses_screen_texture_mipmaps = false;
@@ -181,15 +174,8 @@ 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_parameter(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_parameter_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;
CanvasShaderData() {}
@@ -409,11 +395,6 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
uint32_t lights[4];
};
- struct SkeletonUniform {
- float skeleton_transform[16];
- float skeleton_inverse[16];
- };
-
Item *items[MAX_RENDER_ITEMS];
bool using_directional_lights = false;
@@ -430,8 +411,8 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
RID _create_base_uniform_set(RID p_to_render_target, bool p_backbuffer);
inline void _bind_canvas_texture(RD::DrawListID p_draw_list, RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, RID &r_last_texture, PushConstant &push_constant, Size2 &r_texpixel_size); //recursive, so regular inline used instead.
- void _render_item(RenderingDevice::DrawListID p_draw_list, RID p_render_target, const Item *p_item, RenderingDevice::FramebufferFormatID p_framebuffer_format, const Transform2D &p_canvas_transform_inverse, Item *&current_clip, Light *p_lights, PipelineVariants *p_pipeline_variants);
- void _render_items(RID p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights, bool p_to_backbuffer = false);
+ void _render_item(RenderingDevice::DrawListID p_draw_list, RID p_render_target, const Item *p_item, RenderingDevice::FramebufferFormatID p_framebuffer_format, const Transform2D &p_canvas_transform_inverse, Item *&current_clip, Light *p_lights, PipelineVariants *p_pipeline_variants, bool &r_sdf_used);
+ void _render_items(RID p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights, bool &r_sdf_used, bool p_to_backbuffer = false);
_FORCE_INLINE_ void _update_transform_2d_to_mat2x4(const Transform2D &p_transform, float *p_mat2x4);
_FORCE_INLINE_ void _update_transform_2d_to_mat2x3(const Transform2D &p_transform, float *p_mat2x3);
diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp
index 3289bfb0ea..f488fd63fe 100644
--- a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp
@@ -174,13 +174,19 @@ void RendererCompositorRD::set_boot_image(const Ref<Image> &p_image, const Color
texture_storage->texture_2d_initialize(texture, p_image);
RID rd_texture = texture_storage->texture_get_rd_texture(texture);
+ RD::SamplerState sampler_state;
+ sampler_state.min_filter = p_use_filter ? RD::SAMPLER_FILTER_LINEAR : RD::SAMPLER_FILTER_NEAREST;
+ sampler_state.mag_filter = p_use_filter ? RD::SAMPLER_FILTER_LINEAR : RD::SAMPLER_FILTER_NEAREST;
+ sampler_state.max_lod = 0;
+ RID sampler = RD::get_singleton()->sampler_create(sampler_state);
+
RID uset;
{
Vector<RD::Uniform> uniforms;
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
u.binding = 0;
- u.append_id(blit.sampler);
+ u.append_id(sampler);
u.append_id(rd_texture);
uniforms.push_back(u);
uset = RD::get_singleton()->uniform_set_create(uniforms, blit.shader.version_get_shader(blit.shader_version, BLIT_MODE_NORMAL), 0);
@@ -241,6 +247,7 @@ void RendererCompositorRD::set_boot_image(const Ref<Image> &p_image, const Color
RD::get_singleton()->swap_buffers();
texture_storage->texture_free(texture);
+ RD::get_singleton()->free(sampler);
}
RendererCompositorRD *RendererCompositorRD::singleton = nullptr;
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
index 75fe84f46b..1242c11bea 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
@@ -51,99 +51,6 @@ void get_vogel_disk(float *r_kernel, int p_sample_count) {
}
}
-void RendererSceneRenderRD::sdfgi_update(const Ref<RenderSceneBuffers> &p_render_buffers, RID p_environment, const Vector3 &p_world_position) {
- Ref<RenderSceneBuffersRD> rb = p_render_buffers;
- ERR_FAIL_COND(rb.is_null());
- Ref<RendererRD::GI::SDFGI> sdfgi;
- if (rb->has_custom_data(RB_SCOPE_SDFGI)) {
- sdfgi = rb->get_custom_data(RB_SCOPE_SDFGI);
- }
-
- bool needs_sdfgi = p_environment.is_valid() && environment_get_sdfgi_enabled(p_environment);
-
- if (!needs_sdfgi) {
- if (sdfgi.is_valid()) {
- // delete it
- sdfgi.unref();
- rb->set_custom_data(RB_SCOPE_SDFGI, sdfgi);
- }
- return;
- }
-
- 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 (sdfgi.is_valid() && (sdfgi->num_cascades != environment_get_sdfgi_cascades(p_environment) || sdfgi->min_cell_size != environment_get_sdfgi_min_cell_size(p_environment) || requested_history_size != sdfgi->history_size || sdfgi->uses_occlusion != environment_get_sdfgi_use_occlusion(p_environment) || sdfgi->y_scale_mode != environment_get_sdfgi_y_scale(p_environment))) {
- //configuration changed, erase
- sdfgi.unref();
- rb->set_custom_data(RB_SCOPE_SDFGI, sdfgi);
- }
-
- if (sdfgi.is_null()) {
- // re-create
- sdfgi = gi.create_sdfgi(p_environment, p_world_position, requested_history_size);
- rb->set_custom_data(RB_SCOPE_SDFGI, sdfgi);
- } else {
- //check for updates
- sdfgi->update(p_environment, p_world_position);
- }
-}
-
-int RendererSceneRenderRD::sdfgi_get_pending_region_count(const Ref<RenderSceneBuffers> &p_render_buffers) const {
- Ref<RenderSceneBuffersRD> rb = p_render_buffers;
- ERR_FAIL_COND_V(rb.is_null(), 0);
-
- if (!rb->has_custom_data(RB_SCOPE_SDFGI)) {
- return 0;
- }
- Ref<RendererRD::GI::SDFGI> sdfgi = rb->get_custom_data(RB_SCOPE_SDFGI);
-
- int dirty_count = 0;
- for (uint32_t i = 0; i < sdfgi->cascades.size(); i++) {
- const RendererRD::GI::SDFGI::Cascade &c = sdfgi->cascades[i];
-
- if (c.dirty_regions == RendererRD::GI::SDFGI::Cascade::DIRTY_ALL) {
- dirty_count++;
- } else {
- for (int j = 0; j < 3; j++) {
- if (c.dirty_regions[j] != 0) {
- dirty_count++;
- }
- }
- }
- }
-
- return dirty_count;
-}
-
-AABB RendererSceneRenderRD::sdfgi_get_pending_region_bounds(const Ref<RenderSceneBuffers> &p_render_buffers, int p_region) const {
- AABB bounds;
- Vector3i from;
- Vector3i size;
-
- Ref<RenderSceneBuffersRD> rb = p_render_buffers;
- ERR_FAIL_COND_V(rb.is_null(), AABB());
- Ref<RendererRD::GI::SDFGI> sdfgi = rb->get_custom_data(RB_SCOPE_SDFGI);
- ERR_FAIL_COND_V(sdfgi.is_null(), AABB());
-
- int c = sdfgi->get_pending_region_data(p_region, from, size, bounds);
- ERR_FAIL_COND_V(c == -1, AABB());
- return bounds;
-}
-
-uint32_t RendererSceneRenderRD::sdfgi_get_pending_region_cascade(const Ref<RenderSceneBuffers> &p_render_buffers, int p_region) const {
- AABB bounds;
- Vector3i from;
- Vector3i size;
-
- Ref<RenderSceneBuffersRD> rb = p_render_buffers;
- ERR_FAIL_COND_V(rb.is_null(), -1);
- Ref<RendererRD::GI::SDFGI> sdfgi = rb->get_custom_data(RB_SCOPE_SDFGI);
- ERR_FAIL_COND_V(sdfgi.is_null(), -1);
-
- return sdfgi->get_pending_region_data(p_region, from, size, bounds);
-}
-
RID RendererSceneRenderRD::sky_allocate() {
return sky.allocate_sky_rid();
}
@@ -171,10 +78,6 @@ void RendererSceneRenderRD::environment_glow_set_use_bicubic_upscale(bool p_enab
glow_bicubic_upscale = p_enable;
}
-void RendererSceneRenderRD::environment_glow_set_use_high_quality(bool p_enable) {
- glow_high_quality = p_enable;
-}
-
void RendererSceneRenderRD::environment_set_volumetric_fog_volume_size(int p_size, int p_depth) {
volumetric_fog_size = p_size;
volumetric_fog_depth = p_depth;
@@ -599,20 +502,20 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
RID source = rb->get_internal_texture(l);
RID dest = rb->get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_BLUR_1, l, i);
if (can_use_storage) {
- copy_effects->gaussian_glow(source, dest, vp_size, 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, auto_exposure_scale);
+ copy_effects->gaussian_glow(source, dest, vp_size, environment_get_glow_strength(p_render_data->environment), 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, auto_exposure_scale);
} else {
RID half = rb->get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_HALF_BLUR, 0, i); // we can reuse this for each view
- copy_effects->gaussian_glow_raster(source, half, dest, luminance_multiplier, vp_size, 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, auto_exposure_scale);
+ copy_effects->gaussian_glow_raster(source, half, dest, luminance_multiplier, vp_size, environment_get_glow_strength(p_render_data->environment), 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, auto_exposure_scale);
}
} else {
RID source = rb->get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_BLUR_1, l, i - 1);
RID dest = rb->get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_BLUR_1, l, i);
if (can_use_storage) {
- copy_effects->gaussian_glow(source, dest, vp_size, environment_get_glow_strength(p_render_data->environment), glow_high_quality);
+ copy_effects->gaussian_glow(source, dest, vp_size, environment_get_glow_strength(p_render_data->environment));
} else {
RID half = rb->get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_HALF_BLUR, 0, i); // we can reuse this for each view
- copy_effects->gaussian_glow_raster(source, half, dest, luminance_multiplier, vp_size, environment_get_glow_strength(p_render_data->environment), glow_high_quality);
+ copy_effects->gaussian_glow_raster(source, half, dest, luminance_multiplier, vp_size, environment_get_glow_strength(p_render_data->environment));
}
}
}
@@ -1006,10 +909,20 @@ bool RendererSceneRenderRD::is_using_radiance_cubemap_array() const {
}
void RendererSceneRenderRD::_update_vrs(Ref<RenderSceneBuffersRD> p_render_buffers) {
- if (p_render_buffers.is_valid() && vrs) {
+ if (p_render_buffers.is_null()) {
+ return;
+ }
+
+ RID render_target = p_render_buffers->get_render_target();
+ if (render_target.is_null()) {
+ // must be rendering reflection probes
+ return;
+ }
+
+ if (vrs) {
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
- RS::ViewportVRSMode vrs_mode = texture_storage->render_target_get_vrs_mode(p_render_buffers->get_render_target());
+ RS::ViewportVRSMode vrs_mode = texture_storage->render_target_get_vrs_mode(render_target);
if (vrs_mode != RS::VIEWPORT_VRS_DISABLED) {
RID vrs_texture = p_render_buffers->get_texture(RB_SCOPE_VRS, RB_TEXTURE);
@@ -1078,6 +991,7 @@ void RendererSceneRenderRD::render_scene(const Ref<RenderSceneBuffers> &p_render
scene_data.cam_transform = p_camera_data->main_transform;
scene_data.cam_projection = p_camera_data->main_projection;
scene_data.cam_orthogonal = p_camera_data->is_orthogonal;
+ scene_data.camera_visible_layers = p_camera_data->visible_layers;
scene_data.taa_jitter = p_camera_data->taa_jitter;
scene_data.view_count = p_camera_data->view_count;
@@ -1160,7 +1074,7 @@ void RendererSceneRenderRD::render_scene(const Ref<RenderSceneBuffers> &p_render
}
Color clear_color;
- if (p_render_buffers.is_valid()) {
+ if (p_render_buffers.is_valid() && p_reflection_probe.is_null()) {
clear_color = texture_storage->render_target_get_clear_request_color(rb->get_render_target());
} else {
clear_color = RSG::texture_storage->get_default_clear_color();
@@ -1400,7 +1314,6 @@ void RendererSceneRenderRD::init() {
screen_space_roughness_limiter_amount = GLOBAL_GET("rendering/anti_aliasing/screen_space_roughness_limiter/amount");
screen_space_roughness_limiter_limit = GLOBAL_GET("rendering/anti_aliasing/screen_space_roughness_limiter/limit");
glow_bicubic_upscale = int(GLOBAL_GET("rendering/environment/glow/upscale_mode")) > 0;
- glow_high_quality = GLOBAL_GET("rendering/environment/glow/use_high_quality");
directional_penumbra_shadow_kernel = memnew_arr(float, 128);
directional_soft_shadow_kernel = memnew_arr(float, 128);
@@ -1418,10 +1331,13 @@ void RendererSceneRenderRD::init() {
cull_argument.set_page_pool(&cull_argument_pool);
bool can_use_storage = _render_buffers_can_be_storage();
+ bool can_use_vrs = is_vrs_supported();
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_vrs) {
+ vrs = memnew(RendererRD::VRS);
+ }
if (can_use_storage) {
fsr = memnew(RendererRD::FSR);
}
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.h b/servers/rendering/renderer_rd/renderer_scene_render_rd.h
index 2312603829..704cb37c91 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_rd.h
+++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.h
@@ -114,7 +114,6 @@ protected:
/* ENVIRONMENT */
bool glow_bicubic_upscale = false;
- bool glow_high_quality = false;
bool use_physical_light_units = false;
@@ -218,14 +217,6 @@ public:
RendererRD::SkyRD *get_sky() { return &sky; }
- /* SDFGI UPDATE */
-
- virtual void sdfgi_update(const Ref<RenderSceneBuffers> &p_render_buffers, RID p_environment, const Vector3 &p_world_position) override;
- virtual int sdfgi_get_pending_region_count(const Ref<RenderSceneBuffers> &p_render_buffers) const override;
- virtual AABB sdfgi_get_pending_region_bounds(const Ref<RenderSceneBuffers> &p_render_buffers, int p_region) const override;
- virtual uint32_t sdfgi_get_pending_region_cascade(const Ref<RenderSceneBuffers> &p_render_buffers, int p_region) const override;
- RID sdfgi_get_ubo() const { return gi.sdfgi_ubo; }
-
/* SKY API */
virtual RID sky_allocate() override;
@@ -239,7 +230,6 @@ public:
/* ENVIRONMENT API */
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_volumetric_fog_volume_size(int p_size, int p_depth) override;
virtual void environment_set_volumetric_fog_filter_active(bool p_enable) override;
diff --git a/servers/rendering/renderer_rd/shaders/canvas.glsl b/servers/rendering/renderer_rd/shaders/canvas.glsl
index 8593e6b265..eb5f68849e 100644
--- a/servers/rendering/renderer_rd/shaders/canvas.glsl
+++ b/servers/rendering/renderer_rd/shaders/canvas.glsl
@@ -191,48 +191,6 @@ void main() {
uv += 1e-5;
}
-#ifdef USE_ATTRIBUTES
-#if 0
- if (bool(draw_data.flags & FLAGS_USE_SKELETON) && bone_weights != vec4(0.0)) { //must be a valid bone
- //skeleton transform
- ivec4 bone_indicesi = ivec4(bone_indices);
-
- uvec2 tex_ofs = bone_indicesi.x * 2;
-
- mat2x4 m;
- m = mat2x4(
- texelFetch(skeleton_buffer, tex_ofs + 0),
- texelFetch(skeleton_buffer, tex_ofs + 1)) *
- bone_weights.x;
-
- tex_ofs = bone_indicesi.y * 2;
-
- m += mat2x4(
- texelFetch(skeleton_buffer, tex_ofs + 0),
- texelFetch(skeleton_buffer, tex_ofs + 1)) *
- bone_weights.y;
-
- tex_ofs = bone_indicesi.z * 2;
-
- m += mat2x4(
- texelFetch(skeleton_buffer, tex_ofs + 0),
- texelFetch(skeleton_buffer, tex_ofs + 1)) *
- bone_weights.z;
-
- tex_ofs = bone_indicesi.w * 2;
-
- m += mat2x4(
- texelFetch(skeleton_buffer, tex_ofs + 0),
- texelFetch(skeleton_buffer, tex_ofs + 1)) *
- bone_weights.w;
-
- mat4 bone_matrix = skeleton_data.skeleton_transform * transpose(mat4(m[0], m[1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0))) * skeleton_data.skeleton_transform_inverse;
-
- //outvec = bone_matrix * outvec;
- }
-#endif
-#endif
-
vertex = (canvas_data.canvas_transform * vec4(vertex, 0.0, 1.0)).xy;
vertex_interp = vertex;
diff --git a/servers/rendering/renderer_rd/shaders/effects/blur_raster.glsl b/servers/rendering/renderer_rd/shaders/effects/blur_raster.glsl
index cb06250cf2..31aabbe9d2 100644
--- a/servers/rendering/renderer_rd/shaders/effects/blur_raster.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/blur_raster.glsl
@@ -53,30 +53,31 @@ void main() {
#ifdef MODE_GAUSSIAN_BLUR
- // Simpler blur uses SIGMA2 for the gaussian kernel for a stronger effect
-
- // note, for blur blur.luminance_multiplier is irrelavant, we would be multiplying and then dividing by this amount.
-
- if (bool(blur.flags & FLAG_HORIZONTAL)) {
- vec2 pix_size = blur.pixel_size;
- pix_size *= 0.5; //reading from larger buffer, so use more samples
- vec4 color = texture(source_color, uv_interp + vec2(0.0, 0.0) * pix_size) * 0.214607;
- color += texture(source_color, uv_interp + vec2(1.0, 0.0) * pix_size) * 0.189879;
- color += texture(source_color, uv_interp + vec2(2.0, 0.0) * pix_size) * 0.131514;
- color += texture(source_color, uv_interp + vec2(3.0, 0.0) * pix_size) * 0.071303;
- color += texture(source_color, uv_interp + vec2(-1.0, 0.0) * pix_size) * 0.189879;
- color += texture(source_color, uv_interp + vec2(-2.0, 0.0) * pix_size) * 0.131514;
- color += texture(source_color, uv_interp + vec2(-3.0, 0.0) * pix_size) * 0.071303;
- frag_color = color;
- } else {
- vec2 pix_size = blur.pixel_size;
- vec4 color = texture(source_color, uv_interp + vec2(0.0, 0.0) * pix_size) * 0.38774;
- color += texture(source_color, uv_interp + vec2(0.0, 1.0) * pix_size) * 0.24477;
- color += texture(source_color, uv_interp + vec2(0.0, 2.0) * pix_size) * 0.06136;
- color += texture(source_color, uv_interp + vec2(0.0, -1.0) * pix_size) * 0.24477;
- color += texture(source_color, uv_interp + vec2(0.0, -2.0) * pix_size) * 0.06136;
- frag_color = color;
- }
+ // For Gaussian Blur we use 13 taps in a single pass instead of 12 taps over 2 passes.
+ // This minimizes the number of times we change framebuffers which is very important for mobile.
+ // Source: http://www.iryoku.com/next-generation-post-processing-in-call-of-duty-advanced-warfare
+ vec4 A = texture(source_color, uv_interp + blur.pixel_size * vec2(-1.0, -1.0));
+ vec4 B = texture(source_color, uv_interp + blur.pixel_size * vec2(0.0, -1.0));
+ vec4 C = texture(source_color, uv_interp + blur.pixel_size * vec2(1.0, -1.0));
+ vec4 D = texture(source_color, uv_interp + blur.pixel_size * vec2(-0.5, -0.5));
+ vec4 E = texture(source_color, uv_interp + blur.pixel_size * vec2(0.5, -0.5));
+ vec4 F = texture(source_color, uv_interp + blur.pixel_size * vec2(-1.0, 0.0));
+ vec4 G = texture(source_color, uv_interp);
+ vec4 H = texture(source_color, uv_interp + blur.pixel_size * vec2(1.0, 0.0));
+ vec4 I = texture(source_color, uv_interp + blur.pixel_size * vec2(-0.5, 0.5));
+ vec4 J = texture(source_color, uv_interp + blur.pixel_size * vec2(0.5, 0.5));
+ vec4 K = texture(source_color, uv_interp + blur.pixel_size * vec2(-1.0, 1.0));
+ vec4 L = texture(source_color, uv_interp + blur.pixel_size * vec2(0.0, 1.0));
+ vec4 M = texture(source_color, uv_interp + blur.pixel_size * vec2(1.0, 1.0));
+
+ float base_weight = 0.5 / 4.0;
+ float lesser_weight = 0.125 / 4.0;
+
+ frag_color = (D + E + I + J) * base_weight;
+ frag_color += (A + B + G + F) * lesser_weight;
+ frag_color += (B + C + H + G) * lesser_weight;
+ frag_color += (F + G + L + K) * lesser_weight;
+ frag_color += (G + H + M + L) * lesser_weight;
#endif
#ifdef MODE_GAUSSIAN_GLOW
diff --git a/servers/rendering/renderer_rd/shaders/effects/copy.glsl b/servers/rendering/renderer_rd/shaders/effects/copy.glsl
index bfe329b8ec..3a82861057 100644
--- a/servers/rendering/renderer_rd/shaders/effects/copy.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/copy.glsl
@@ -14,8 +14,7 @@ layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
#define FLAG_FLIP_Y (1 << 5)
#define FLAG_FORCE_LUMINANCE (1 << 6)
#define FLAG_COPY_ALL_SOURCE (1 << 7)
-#define FLAG_HIGH_QUALITY_GLOW (1 << 8)
-#define FLAG_ALPHA_TO_ONE (1 << 9)
+#define FLAG_ALPHA_TO_ONE (1 << 8)
layout(push_constant, std430) uniform Params {
ivec4 section;
@@ -93,25 +92,14 @@ void main() {
#ifdef MODE_GAUSSIAN_BLUR
// First pass copy texture into 16x16 local memory for every 8x8 thread block
- vec2 quad_center_uv = clamp(vec2(gl_GlobalInvocationID.xy + gl_LocalInvocationID.xy - 3.5) / params.section.zw, vec2(0.5 / params.section.zw), vec2(1.0 - 1.5 / params.section.zw));
+ vec2 quad_center_uv = clamp(vec2(params.section.xy + gl_GlobalInvocationID.xy + gl_LocalInvocationID.xy - 3.5) / params.section.zw, vec2(0.5 / params.section.zw), vec2(1.0 - 1.5 / params.section.zw));
uint dest_index = gl_LocalInvocationID.x * 2 + gl_LocalInvocationID.y * 2 * 16;
-#ifdef MODE_GLOW
- if (bool(params.flags & FLAG_HIGH_QUALITY_GLOW)) {
- vec2 quad_offset_uv = clamp((vec2(gl_GlobalInvocationID.xy + gl_LocalInvocationID.xy - 3.0)) / params.section.zw, vec2(0.5 / params.section.zw), vec2(1.0 - 1.5 / params.section.zw));
-
- local_cache[dest_index] = (textureLod(source_color, quad_center_uv, 0) + textureLod(source_color, quad_offset_uv, 0)) * 0.5;
- local_cache[dest_index + 1] = (textureLod(source_color, quad_center_uv + vec2(1.0 / params.section.z, 0.0), 0) + textureLod(source_color, quad_offset_uv + vec2(1.0 / params.section.z, 0.0), 0)) * 0.5;
- local_cache[dest_index + 16] = (textureLod(source_color, quad_center_uv + vec2(0.0, 1.0 / params.section.w), 0) + textureLod(source_color, quad_offset_uv + vec2(0.0, 1.0 / params.section.w), 0)) * 0.5;
- local_cache[dest_index + 16 + 1] = (textureLod(source_color, quad_center_uv + vec2(1.0 / params.section.zw), 0) + textureLod(source_color, quad_offset_uv + vec2(1.0 / params.section.zw), 0)) * 0.5;
- } else
-#endif
- {
- local_cache[dest_index] = textureLod(source_color, quad_center_uv, 0);
- local_cache[dest_index + 1] = textureLod(source_color, quad_center_uv + vec2(1.0 / params.section.z, 0.0), 0);
- local_cache[dest_index + 16] = textureLod(source_color, quad_center_uv + vec2(0.0, 1.0 / params.section.w), 0);
- local_cache[dest_index + 16 + 1] = textureLod(source_color, quad_center_uv + vec2(1.0 / params.section.zw), 0);
- }
+ local_cache[dest_index] = textureLod(source_color, quad_center_uv, 0);
+ local_cache[dest_index + 1] = textureLod(source_color, quad_center_uv + vec2(1.0 / params.section.z, 0.0), 0);
+ local_cache[dest_index + 16] = textureLod(source_color, quad_center_uv + vec2(0.0, 1.0 / params.section.w), 0);
+ local_cache[dest_index + 16 + 1] = textureLod(source_color, quad_center_uv + vec2(1.0 / params.section.zw), 0);
+
#ifdef MODE_GLOW
if (bool(params.flags & FLAG_GLOW_FIRST_PASS)) {
// Tonemap initial samples to reduce weight of fireflies: https://graphicrants.blogspot.com/2013/12/tone-mapping.html
@@ -194,10 +182,10 @@ void main() {
color = min(color * feedback, vec4(params.glow_luminance_cap));
}
-#endif
+#endif // MODE_GLOW
imageStore(dest_buffer, pos + params.target, color);
-#endif
+#endif // MODE_GAUSSIAN_BLUR
#ifdef MODE_SIMPLE_COPY
@@ -227,7 +215,7 @@ void main() {
imageStore(dest_buffer, pos + params.target, color);
-#endif
+#endif // MODE_SIMPLE_COPY
#ifdef MODE_SIMPLE_COPY_DEPTH
@@ -239,7 +227,7 @@ void main() {
imageStore(dest_buffer, pos + params.target, vec4(color.r));
-#endif
+#endif // MODE_SIMPLE_COPY_DEPTH
#ifdef MODE_LINEARIZE_DEPTH_COPY
@@ -253,7 +241,7 @@ void main() {
}
imageStore(dest_buffer, pos + params.target, color);
-#endif
+#endif // MODE_LINEARIZE_DEPTH_COPY
#if defined(MODE_CUBEMAP_TO_PANORAMA) || defined(MODE_CUBEMAP_ARRAY_TO_PANORAMA)
@@ -276,7 +264,7 @@ void main() {
vec4 color = textureLod(source_color, vec4(normal, params.camera_z_far), 0.0); //the biggest the lod the least the acne
#endif
imageStore(dest_buffer, pos + params.target, color);
-#endif
+#endif // defined(MODE_CUBEMAP_TO_PANORAMA) || defined(MODE_CUBEMAP_ARRAY_TO_PANORAMA)
#ifdef MODE_SET_COLOR
imageStore(dest_buffer, pos + params.target, params.set_color);
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 1c17eabb56..6137224162 100644
--- a/servers/rendering/renderer_rd/shaders/effects/copy_to_fb.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/copy_to_fb.glsl
@@ -13,6 +13,14 @@
#endif // has_VK_KHR_multiview
#endif //MULTIVIEW
+#define FLAG_FLIP_Y (1 << 0)
+#define FLAG_USE_SECTION (1 << 1)
+#define FLAG_FORCE_LUMINANCE (1 << 2)
+#define FLAG_ALPHA_TO_ZERO (1 << 3)
+#define FLAG_SRGB (1 << 4)
+#define FLAG_ALPHA_TO_ONE (1 << 5)
+#define FLAG_LINEAR (1 << 6)
+
#ifdef MULTIVIEW
layout(location = 0) out vec3 uv_interp;
#else
@@ -22,11 +30,10 @@ layout(location = 0) out vec2 uv_interp;
layout(push_constant, std430) uniform Params {
vec4 section;
vec2 pixel_size;
- bool flip_y;
- bool use_section;
+ float luminance_multiplier;
+ uint flags;
- bool force_luminance;
- uint pad[3];
+ vec4 color;
}
params;
@@ -37,13 +44,13 @@ void main() {
uv_interp.z = ViewIndex;
#endif
vec2 vpos = uv_interp.xy;
- if (params.use_section) {
+ if (bool(params.flags & FLAG_USE_SECTION)) {
vpos = params.section.xy + vpos * params.section.zw;
}
gl_Position = vec4(vpos * 2.0 - 1.0, 0.0, 1.0);
- if (params.flip_y) {
+ if (bool(params.flags & FLAG_FLIP_Y)) {
uv_interp.y = 1.0 - uv_interp.y;
}
}
@@ -63,19 +70,25 @@ void main() {
#endif // has_VK_KHR_multiview
#endif //MULTIVIEW
+#define FLAG_FLIP_Y (1 << 0)
+#define FLAG_USE_SECTION (1 << 1)
+#define FLAG_FORCE_LUMINANCE (1 << 2)
+#define FLAG_ALPHA_TO_ZERO (1 << 3)
+#define FLAG_SRGB (1 << 4)
+#define FLAG_ALPHA_TO_ONE (1 << 5)
+#define FLAG_LINEAR (1 << 6)
+
layout(push_constant, std430) uniform Params {
vec4 section;
vec2 pixel_size;
- bool flip_y;
- bool use_section;
+ float luminance_multiplier;
+ uint flags;
- bool force_luminance;
- bool alpha_to_zero;
- bool srgb;
- uint pad;
+ vec4 color;
}
params;
+#ifndef MODE_SET_COLOR
#ifdef MULTIVIEW
layout(location = 0) in vec3 uv_interp;
#else
@@ -94,6 +107,7 @@ layout(set = 0, binding = 0) uniform sampler2D source_color;
layout(set = 1, binding = 0) uniform sampler2D source_color2;
#endif /* MODE_TWO_SOURCES */
#endif /* MULTIVIEW */
+#endif /* !SET_COLOR */
layout(location = 0) out vec4 frag_color;
@@ -104,7 +118,15 @@ vec3 linear_to_srgb(vec3 color) {
return mix((vec3(1.0f) + a) * pow(color.rgb, vec3(1.0f / 2.4f)) - a, 12.92f * color.rgb, lessThan(color.rgb, vec3(0.0031308f)));
}
+vec3 srgb_to_linear(vec3 color) {
+ return mix(pow((color.rgb + vec3(0.055)) * (1.0 / (1.0 + 0.055)), vec3(2.4)), color.rgb * (1.0 / 12.92), lessThan(color.rgb, vec3(0.04045)));
+}
+
void main() {
+#ifdef MODE_SET_COLOR
+ frag_color = params.color;
+#else
+
#ifdef MULTIVIEW
vec3 uv = uv_interp;
#else
@@ -155,15 +177,22 @@ void main() {
#endif /* MODE_TWO_SOURCES */
#endif /* MULTIVIEW */
- if (params.force_luminance) {
+ if (bool(params.flags & FLAG_FORCE_LUMINANCE)) {
color.rgb = vec3(max(max(color.r, color.g), color.b));
}
- if (params.alpha_to_zero) {
+ if (bool(params.flags & FLAG_ALPHA_TO_ZERO)) {
color.rgb *= color.a;
}
- if (params.srgb) {
+ if (bool(params.flags & FLAG_SRGB)) {
color.rgb = linear_to_srgb(color.rgb);
}
+ if (bool(params.flags & FLAG_ALPHA_TO_ONE)) {
+ color.a = 1.0;
+ }
+ if (bool(params.flags & FLAG_LINEAR)) {
+ color.rgb = srgb_to_linear(color.rgb);
+ }
- frag_color = color;
+ frag_color = color / params.luminance_multiplier;
+#endif // MODE_SET_COLOR
}
diff --git a/servers/rendering/renderer_rd/shaders/effects/cubemap_roughness_inc.glsl b/servers/rendering/renderer_rd/shaders/effects/cubemap_roughness_inc.glsl
index 1bee428a6f..c0597fe3f3 100644
--- a/servers/rendering/renderer_rd/shaders/effects/cubemap_roughness_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/cubemap_roughness_inc.glsl
@@ -70,17 +70,6 @@ float DistributionGGX(float NdotH, float roughness4) {
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 radicalInverse_VdC(uint bits) {
bits = (bits << 16u) | (bits >> 16u);
bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);
diff --git a/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection.glsl b/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection.glsl
index 9d8294a7da..631d1968b0 100644
--- a/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection.glsl
@@ -66,6 +66,19 @@ void main() {
vec4 normal_roughness = imageLoad(source_normal_roughness, ssC);
vec3 normal = normal_roughness.xyz * 2.0 - 1.0;
+ float roughness = normal_roughness.w;
+
+ // The roughness cutoff of 0.6 is chosen to match the roughness fadeout from GH-69828.
+ if (roughness > 0.6) {
+ // Do not compute SSR for rough materials to improve performance at the cost of
+ // subtle artifacting.
+#ifdef MODE_ROUGH
+ imageStore(blur_radius_image, ssC, vec4(0.0));
+#endif
+ imageStore(ssr_image, ssC, vec4(0.0));
+ return;
+ }
+
normal = normalize(normal);
normal.y = -normal.y; //because this code reads flipped
@@ -81,8 +94,6 @@ void main() {
imageStore(ssr_image, ssC, vec4(0.0));
return;
}
- //ray_dir = normalize(view_dir - normal * dot(normal,view_dir) * 2.0);
- //ray_dir = normalize(vec3(1.0, 1.0, -1.0));
////////////////
@@ -212,6 +223,9 @@ void main() {
float grad = (steps_taken + 1.0) / float(params.num_steps);
float initial_fade = params.curve_fade_in == 0.0 ? 1.0 : pow(clamp(grad, 0.0, 1.0), params.curve_fade_in);
float fade = pow(clamp(1.0 - grad, 0.0, 1.0), params.distance_fade) * initial_fade;
+ // This is an ad-hoc term to fade out the SSR as roughness increases. Values used
+ // are meant to match the visual appearance of a ReflectionProbe.
+ float roughness_fade = smoothstep(0.4, 0.7, 1.0 - normal_roughness.w);
final_pos = pos;
vec4 final_color;
@@ -220,7 +234,6 @@ void main() {
// if roughness is enabled, do screen space cone tracing
float blur_radius = 0.0;
- float roughness = normal_roughness.w;
if (roughness > 0.001) {
float cone_angle = min(roughness, 0.999) * M_PI * 0.5;
@@ -246,7 +259,7 @@ void main() {
#endif // MODE_ROUGH
- final_color = vec4(imageLoad(source_diffuse, ivec2(final_pos - 0.5)).rgb, fade * margin_blend);
+ final_color = vec4(imageLoad(source_diffuse, ivec2(final_pos - 0.5)).rgb, fade * margin_blend * roughness_fade);
// Schlick term.
float metallic = texelFetch(source_metallic, ssC << 1, 0).w;
diff --git a/servers/rendering/renderer_rd/shaders/effects/vrs.glsl b/servers/rendering/renderer_rd/shaders/effects/vrs.glsl
index 5ef83c0b44..b450bb9fe9 100644
--- a/servers/rendering/renderer_rd/shaders/effects/vrs.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/vrs.glsl
@@ -63,10 +63,18 @@ void main() {
#ifdef MULTIVIEW
vec4 color = textureLod(source_color, uv, 0.0);
+ frag_color = uint(color.r * 255.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);
+ // for user supplied VRS map we do a color mapping
+ color.r *= 3.0;
+ frag_color = int(color.r) << 2;
+
+ color.g *= 3.0;
+ frag_color += int(color.g);
+
+ // note 1x4, 4x1, 1x8, 8x1, 2x8 and 8x2 are not supported
+ // 4x8, 8x4 and 8x8 are only available on some GPUs
+#endif /* MULTIVIEW */
}
diff --git a/servers/rendering/renderer_rd/shaders/environment/gi.glsl b/servers/rendering/renderer_rd/shaders/environment/gi.glsl
index ab927df678..459c4dcb1d 100644
--- a/servers/rendering/renderer_rd/shaders/environment/gi.glsl
+++ b/servers/rendering/renderer_rd/shaders/environment/gi.glsl
@@ -108,7 +108,9 @@ layout(set = 0, binding = 18, std140) uniform SceneData {
}
scene_data;
+#ifdef USE_VRS
layout(r8ui, set = 0, binding = 19) uniform restrict readonly uimage2D vrs_buffer;
+#endif
layout(push_constant, std430) uniform Params {
uint max_voxel_gi_instances;
@@ -661,6 +663,7 @@ void main() {
ivec2 pos = ivec2(gl_GlobalInvocationID.xy);
uint vrs_x, vrs_y;
+#ifdef USE_VRS
if (sc_use_vrs) {
ivec2 vrs_pos;
@@ -684,6 +687,7 @@ void main() {
return;
}
}
+#endif
if (sc_half_res) {
pos <<= 1;
@@ -708,6 +712,7 @@ void main() {
imageStore(ambient_buffer, pos, ambient_light);
imageStore(reflection_buffer, pos, reflection_light);
+#ifdef USE_VRS
if (sc_use_vrs) {
if (vrs_x > 1) {
imageStore(ambient_buffer, pos + ivec2(1, 0), ambient_light);
@@ -766,4 +771,5 @@ void main() {
imageStore(reflection_buffer, pos + ivec2(3, 3), reflection_light);
}
}
+#endif
}
diff --git a/servers/rendering/renderer_rd/shaders/environment/sky.glsl b/servers/rendering/renderer_rd/shaders/environment/sky.glsl
index d523461600..bf974a3fd5 100644
--- a/servers/rendering/renderer_rd/shaders/environment/sky.glsl
+++ b/servers/rendering/renderer_rd/shaders/environment/sky.glsl
@@ -14,7 +14,7 @@ layout(location = 0) out vec2 uv_interp;
layout(push_constant, std430) uniform Params {
mat3 orientation;
- vec4 projections[MAX_VIEWS];
+ vec4 projection; // only applicable if not multiview
vec3 position;
float time;
vec3 pad;
@@ -54,7 +54,7 @@ layout(location = 0) in vec2 uv_interp;
layout(push_constant, std430) uniform Params {
mat3 orientation;
- vec4 projections[MAX_VIEWS];
+ vec4 projection; // only applicable if not multiview
vec3 position;
float time;
vec3 pad;
@@ -82,7 +82,10 @@ layout(set = 0, binding = 1, std430) restrict readonly buffer GlobalShaderUnifor
}
global_shader_uniforms;
-layout(set = 0, binding = 2, std140) uniform SceneData {
+layout(set = 0, binding = 2, std140) uniform SkySceneData {
+ mat4 view_inv_projections[2];
+ vec4 view_eye_offsets[2];
+
bool volumetric_fog_enabled; // 4 - 4
float volumetric_fog_inv_length; // 4 - 8
float volumetric_fog_detail_spread; // 4 - 12
@@ -101,7 +104,7 @@ layout(set = 0, binding = 2, std140) uniform SceneData {
uint pad1; // 4 - 60
uint pad2; // 4 - 64
}
-scene_data;
+sky_scene_data;
struct DirectionalLightData {
vec4 direction_energy;
@@ -124,6 +127,9 @@ layout(set = 2, binding = 0) uniform textureCube radiance;
#ifdef USE_CUBEMAP_PASS
layout(set = 2, binding = 1) uniform textureCube half_res;
layout(set = 2, binding = 2) uniform textureCube quarter_res;
+#elif defined(USE_MULTIVIEW)
+layout(set = 2, binding = 1) uniform texture2DArray half_res;
+layout(set = 2, binding = 2) uniform texture2DArray quarter_res;
#else
layout(set = 2, binding = 1) uniform texture2D half_res;
layout(set = 2, binding = 2) uniform texture2D quarter_res;
@@ -169,15 +175,15 @@ vec4 volumetric_fog_process(vec2 screen_uv) {
}
vec4 fog_process(vec3 view, vec3 sky_color) {
- vec3 fog_color = mix(scene_data.fog_light_color, sky_color, scene_data.fog_aerial_perspective);
+ vec3 fog_color = mix(sky_scene_data.fog_light_color, sky_color, sky_scene_data.fog_aerial_perspective);
- if (scene_data.fog_sun_scatter > 0.001) {
+ if (sky_scene_data.fog_sun_scatter > 0.001) {
vec4 sun_scatter = vec4(0.0);
float sun_total = 0.0;
- for (uint i = 0; i < scene_data.directional_light_count; i++) {
+ for (uint i = 0; i < sky_scene_data.directional_light_count; i++) {
vec3 light_color = directional_lights.data[i].color_size.xyz * directional_lights.data[i].direction_energy.w;
float light_amount = pow(max(dot(view, directional_lights.data[i].direction_energy.xyz), 0.0), 8.0);
- fog_color += light_color * light_amount * scene_data.fog_sun_scatter;
+ fog_color += light_color * light_amount * sky_scene_data.fog_sun_scatter;
}
}
@@ -186,9 +192,17 @@ vec4 fog_process(vec3 view, vec3 sky_color) {
void main() {
vec3 cube_normal;
+#ifdef USE_MULTIVIEW
+ // In multiview our projection matrices will contain positional and rotational offsets that we need to properly unproject.
+ vec4 unproject = vec4(uv_interp.x, -uv_interp.y, 1.0, 1.0);
+ vec4 unprojected = sky_scene_data.view_inv_projections[ViewIndex] * unproject;
+ cube_normal = unprojected.xyz / unprojected.w;
+ cube_normal += sky_scene_data.view_eye_offsets[ViewIndex].xyz;
+#else
cube_normal.z = -1.0;
- cube_normal.x = (cube_normal.z * (-uv_interp.x - params.projections[ViewIndex].x)) / params.projections[ViewIndex].y;
- cube_normal.y = -(cube_normal.z * (-uv_interp.y - params.projections[ViewIndex].z)) / params.projections[ViewIndex].w;
+ cube_normal.x = (cube_normal.z * (-uv_interp.x - params.projection.x)) / params.projection.y;
+ cube_normal.y = -(cube_normal.z * (-uv_interp.y - params.projection.z)) / params.projection.w;
+#endif
cube_normal = mat3(params.orientation) * cube_normal;
cube_normal = normalize(cube_normal);
@@ -209,20 +223,33 @@ void main() {
vec4 custom_fog = vec4(0.0);
#ifdef USE_CUBEMAP_PASS
+
#ifdef USES_HALF_RES_COLOR
half_res_color = texture(samplerCube(half_res, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), cube_normal) / params.luminance_multiplier;
#endif
#ifdef USES_QUARTER_RES_COLOR
quarter_res_color = texture(samplerCube(quarter_res, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), cube_normal) / params.luminance_multiplier;
#endif
+
#else
+
#ifdef USES_HALF_RES_COLOR
+#ifdef USE_MULTIVIEW
+ half_res_color = textureLod(sampler2DArray(half_res, material_samplers[SAMPLER_LINEAR_CLAMP]), vec3(uv, ViewIndex), 0.0) / params.luminance_multiplier;
+#else
half_res_color = textureLod(sampler2D(half_res, material_samplers[SAMPLER_LINEAR_CLAMP]), uv, 0.0) / params.luminance_multiplier;
-#endif
+#endif // USE_MULTIVIEW
+#endif // USES_HALF_RES_COLOR
+
#ifdef USES_QUARTER_RES_COLOR
+#ifdef USE_MULTIVIEW
+ quarter_res_color = textureLod(sampler2DArray(quarter_res, material_samplers[SAMPLER_LINEAR_CLAMP]), vec3(uv, ViewIndex), 0.0) / params.luminance_multiplier;
+#else
quarter_res_color = textureLod(sampler2D(quarter_res, material_samplers[SAMPLER_LINEAR_CLAMP]), uv, 0.0) / params.luminance_multiplier;
-#endif
-#endif
+#endif // USE_MULTIVIEW
+#endif // USES_QUARTER_RES_COLOR
+
+#endif //USE_CUBEMAP_PASS
{
@@ -236,14 +263,14 @@ void main() {
#if !defined(DISABLE_FOG) && !defined(USE_CUBEMAP_PASS)
// Draw "fixed" fog before volumetric fog to ensure volumetric fog can appear in front of the sky.
- if (scene_data.fog_enabled) {
+ if (sky_scene_data.fog_enabled) {
vec4 fog = fog_process(cube_normal, frag_color.rgb);
- frag_color.rgb = mix(frag_color.rgb, fog.rgb, fog.a * scene_data.fog_sky_affect);
+ frag_color.rgb = mix(frag_color.rgb, fog.rgb, fog.a * sky_scene_data.fog_sky_affect);
}
- if (scene_data.volumetric_fog_enabled) {
+ if (sky_scene_data.volumetric_fog_enabled) {
vec4 fog = volumetric_fog_process(uv);
- frag_color.rgb = mix(frag_color.rgb, fog.rgb, fog.a * scene_data.volumetric_fog_sky_affect);
+ frag_color.rgb = mix(frag_color.rgb, fog.rgb, fog.a * sky_scene_data.volumetric_fog_sky_affect);
}
if (custom_fog.a > 0.0) {
diff --git a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl
index 0bdf0e50aa..be53a7ae49 100644
--- a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl
+++ b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl
@@ -62,7 +62,7 @@ vec3 oct_to_vec3(vec2 e) {
vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));
float t = max(-v.z, 0.0);
v.xy += t * -sign(v.xy);
- return v;
+ return normalize(v);
}
/* Varyings */
@@ -826,7 +826,8 @@ void fragment_shader(in SceneData scene_data) {
// alpha hash can be used in unison with alpha antialiasing
#ifdef ALPHA_HASH_USED
- if (alpha < compute_alpha_hash_threshold(vertex, alpha_hash_scale)) {
+ vec3 object_pos = (inverse(read_model_matrix) * inv_view_matrix * vec4(vertex, 1.0)).xyz;
+ if (alpha < compute_alpha_hash_threshold(object_pos, alpha_hash_scale)) {
discard;
}
#endif // ALPHA_HASH_USED
@@ -1083,12 +1084,13 @@ void fragment_shader(in SceneData scene_data) {
#ifdef USE_RADIANCE_CUBEMAP_ARRAY
float lod, blend;
- blend = modf(roughness * MAX_ROUGHNESS_LOD, lod);
+
+ blend = modf(sqrt(roughness) * MAX_ROUGHNESS_LOD, lod);
specular_light = texture(samplerCubeArray(radiance_cubemap, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), vec4(ref_vec, lod)).rgb;
specular_light = mix(specular_light, texture(samplerCubeArray(radiance_cubemap, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), vec4(ref_vec, lod + 1)).rgb, blend);
#else
- specular_light = textureLod(samplerCube(radiance_cubemap, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), ref_vec, roughness * MAX_ROUGHNESS_LOD).rgb;
+ specular_light = textureLod(samplerCube(radiance_cubemap, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), ref_vec, sqrt(roughness) * MAX_ROUGHNESS_LOD).rgb;
#endif //USE_RADIANCE_CUBEMAP_ARRAY
specular_light *= scene_data.IBL_exposure_normalization;
@@ -1136,7 +1138,7 @@ void fragment_shader(in SceneData scene_data) {
ref_vec = mix(ref_vec, n, clearcoat_roughness * clearcoat_roughness);
float horizon = min(1.0 + dot(ref_vec, normal), 1.0);
ref_vec = scene_data.radiance_inverse_xform * ref_vec;
- float roughness_lod = mix(0.001, 0.1, clearcoat_roughness) * MAX_ROUGHNESS_LOD;
+ float roughness_lod = mix(0.001, 0.1, sqrt(clearcoat_roughness)) * MAX_ROUGHNESS_LOD;
#ifdef USE_RADIANCE_CUBEMAP_ARRAY
float lod, blend;
@@ -1483,7 +1485,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 * clamp(50.0 * f0.g, 0.0, 1.0);
+ specular_light *= env.x * f0 + env.y * clamp(50.0 * f0.g, metallic, 1.0);
#endif
}
diff --git a/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl
index 9aeaa6d978..b45c68db5a 100644
--- a/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl
+++ b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl
@@ -63,7 +63,7 @@ vec3 oct_to_vec3(vec2 e) {
vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));
float t = max(-v.z, 0.0);
v.xy += t * -sign(v.xy);
- return v;
+ return normalize(v);
}
/* Varyings */
@@ -779,7 +779,8 @@ void main() {
// alpha hash can be used in unison with alpha antialiasing
#ifdef ALPHA_HASH_USED
- if (alpha < compute_alpha_hash_threshold(vertex, alpha_hash_scale)) {
+ vec3 object_pos = (inverse(read_model_matrix) * inv_view_matrix * vec4(vertex, 1.0)).xyz;
+ if (alpha < compute_alpha_hash_threshold(object_pos, alpha_hash_scale)) {
discard;
}
#endif // ALPHA_HASH_USED
@@ -986,12 +987,12 @@ void main() {
#ifdef USE_RADIANCE_CUBEMAP_ARRAY
float lod, blend;
- blend = modf(roughness * MAX_ROUGHNESS_LOD, lod);
+ blend = modf(sqrt(roughness) * MAX_ROUGHNESS_LOD, lod);
specular_light = texture(samplerCubeArray(radiance_cubemap, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), vec4(ref_vec, lod)).rgb;
specular_light = mix(specular_light, texture(samplerCubeArray(radiance_cubemap, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), vec4(ref_vec, lod + 1)).rgb, blend);
#else // USE_RADIANCE_CUBEMAP_ARRAY
- specular_light = textureLod(samplerCube(radiance_cubemap, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), ref_vec, roughness * MAX_ROUGHNESS_LOD).rgb;
+ specular_light = textureLod(samplerCube(radiance_cubemap, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), ref_vec, sqrt(roughness) * MAX_ROUGHNESS_LOD).rgb;
#endif //USE_RADIANCE_CUBEMAP_ARRAY
specular_light *= sc_luminance_multiplier;
@@ -1041,7 +1042,7 @@ void main() {
float horizon = min(1.0 + dot(ref_vec, normal), 1.0);
ref_vec = scene_data.radiance_inverse_xform * ref_vec;
- float roughness_lod = mix(0.001, 0.1, clearcoat_roughness) * MAX_ROUGHNESS_LOD;
+ float roughness_lod = mix(0.001, 0.1, sqrt(clearcoat_roughness)) * MAX_ROUGHNESS_LOD;
#ifdef USE_RADIANCE_CUBEMAP_ARRAY
float lod, blend;
@@ -1204,7 +1205,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, metallic, 1.0);
#endif
}
diff --git a/servers/rendering/renderer_rd/shaders/particles.glsl b/servers/rendering/renderer_rd/shaders/particles.glsl
index 9f6aa7adc0..a609076e2c 100644
--- a/servers/rendering/renderer_rd/shaders/particles.glsl
+++ b/servers/rendering/renderer_rd/shaders/particles.glsl
@@ -243,8 +243,14 @@ void main() {
if (params.trail_size > 1) {
if (params.trail_pass) {
+ if (particle >= params.total_particles * (params.trail_size - 1)) {
+ return;
+ }
particle += (particle / (params.trail_size - 1)) + 1;
} else {
+ if (particle >= params.total_particles) {
+ return;
+ }
particle *= params.trail_size;
}
}
@@ -298,12 +304,17 @@ void main() {
PARTICLE.flags = PARTICLE_FLAG_TRAILED | ((frame_history.data[0].frame & PARTICLE_FRAME_MASK) << PARTICLE_FRAME_SHIFT); //mark it as trailed, save in which frame it will start
PARTICLE.xform = particles.data[src_idx].xform;
}
-
+ if (!bool(particles.data[src_idx].flags & PARTICLE_FLAG_ACTIVE)) {
+ // Disable the entire trail if the parent is no longer active.
+ PARTICLE.flags = 0;
+ return;
+ }
if (bool(PARTICLE.flags & PARTICLE_FLAG_TRAILED) && ((PARTICLE.flags >> PARTICLE_FRAME_SHIFT) == (FRAME.frame & PARTICLE_FRAME_MASK))) { //check this is trailed and see if it should start now
// we just assume that this is the first frame of the particle, the rest is deterministic
PARTICLE.flags = PARTICLE_FLAG_ACTIVE | (particles.data[src_idx].flags & (PARTICLE_FRAME_MASK << PARTICLE_FRAME_SHIFT));
return; //- this appears like it should be correct, but it seems not to be.. wonder why.
}
+
} else {
PARTICLE.flags &= ~PARTICLE_FLAG_STARTED;
}
diff --git a/servers/rendering/renderer_rd/shaders/scene_data_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_data_inc.glsl
index 048257e9ef..b57ee18521 100644
--- a/servers/rendering/renderer_rd/shaders/scene_data_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_data_inc.glsl
@@ -63,7 +63,7 @@ struct SceneData {
float IBL_exposure_normalization;
bool pancake_shadows;
- uint pad1;
+ uint camera_visible_layers;
uint pad2;
uint pad3;
};
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_aa_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_aa_inc.glsl
index 97c913d489..71510ee06a 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_aa_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_aa_inc.glsl
@@ -11,7 +11,8 @@ float hash_3d(vec3 p) {
float compute_alpha_hash_threshold(vec3 pos, float hash_scale) {
vec3 dx = dFdx(pos);
- vec3 dy = dFdx(pos);
+ vec3 dy = dFdy(pos);
+
float delta_max_sqr = max(length(dx), length(dy));
float pix_scale = 1.0 / (hash_scale * delta_max_sqr);
@@ -32,9 +33,9 @@ float compute_alpha_hash_threshold(vec3 pos, float hash_scale) {
1.0 - ((1.0 - a_interp) * (1.0 - a_interp) / (2.0 * min_lerp * (1.0 - min_lerp))));
float alpha_hash_threshold =
- (lerp_factor < (1.0 - min_lerp)) ? ((lerp_factor < min_lerp) ? cases.x : cases.y) : cases.z;
+ (a_interp < (1.0 - min_lerp)) ? ((a_interp < min_lerp) ? cases.x : cases.y) : cases.z;
- return clamp(alpha_hash_threshold, 0.0, 1.0);
+ return clamp(alpha_hash_threshold, 0.00001, 1.0);
}
#endif // ALPHA_HASH_USED
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 2fba1351f7..b30b0c8169 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl
@@ -134,7 +134,8 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float atte
#endif
#if defined(LIGHT_RIM_USED)
- float rim_light = pow(max(0.0, 1.0 - cNdotV), max(0.0, (1.0 - roughness) * 16.0));
+ // Epsilon min to prevent pow(0, 0) singularity which results in undefined behavior.
+ float rim_light = pow(max(1e-4, 1.0 - cNdotV), max(0.0, (1.0 - roughness) * 16.0));
diffuse_light += rim_light * rim * mix(vec3(1.0), albedo, rim_tint) * light_color;
#endif
@@ -202,7 +203,7 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float atte
float cLdotH5 = SchlickFresnel(cLdotH);
// 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);
+ float f90 = clamp(dot(f0, vec3(50.0 * 0.33)), metallic, 1.0);
vec3 F = f0 + (f90 - f0) * cLdotH5;
vec3 specular_brdf_NL = cNdotL * D * F * G;
diff --git a/servers/rendering/renderer_rd/shaders/skeleton.glsl b/servers/rendering/renderer_rd/shaders/skeleton.glsl
index 75bea9300b..f5b233cca0 100644
--- a/servers/rendering/renderer_rd/shaders/skeleton.glsl
+++ b/servers/rendering/renderer_rd/shaders/skeleton.glsl
@@ -63,7 +63,7 @@ vec3 oct_to_vec3(vec2 oct) {
vec3 v = vec3(oct.xy, 1.0 - abs(oct.x) - abs(oct.y));
float t = max(-v.z, 0.0);
v.xy += t * -sign(v.xy);
- return v;
+ return normalize(v);
}
vec3 decode_uint_oct_to_norm(uint base) {
@@ -143,8 +143,8 @@ void main() {
uint skin_offset = params.skin_stride * index;
uvec2 bones = uvec2(src_bone_weights.data[skin_offset + 0], src_bone_weights.data[skin_offset + 1]);
- uvec2 bones_01 = uvec2(bones.x & 0xFFFF, bones.x >> 16) * 3; //pre-add xform offset
- uvec2 bones_23 = uvec2(bones.y & 0xFFFF, bones.y >> 16) * 3;
+ uvec2 bones_01 = uvec2(bones.x & 0xFFFF, bones.x >> 16) * 2; //pre-add xform offset
+ uvec2 bones_23 = uvec2(bones.y & 0xFFFF, bones.y >> 16) * 2;
skin_offset += params.skin_weight_offset;
@@ -161,6 +161,13 @@ void main() {
//reverse order because its transposed
vertex = (vec4(vertex, 0.0, 1.0) * m).xy;
}
+
+ uint dst_offset = index * params.vertex_stride;
+
+ uvec2 uvertex = floatBitsToUint(vertex);
+ dst_vertices.data[dst_offset + 0] = uvertex.x;
+ dst_vertices.data[dst_offset + 1] = uvertex.y;
+
#else
vec3 vertex;
vec3 normal;
diff --git a/drivers/spirv-reflect/SCsub b/servers/rendering/renderer_rd/spirv-reflect/SCsub
index 1e7b3de0e6..4c27e5bef7 100644
--- a/drivers/spirv-reflect/SCsub
+++ b/servers/rendering/renderer_rd/spirv-reflect/SCsub
@@ -14,4 +14,4 @@ thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources]
env_thirdparty = env.Clone()
env_thirdparty.disable_warnings()
-env_thirdparty.add_source_files(env.drivers_sources, thirdparty_sources)
+env_thirdparty.add_source_files(env.servers_sources, thirdparty_sources)
diff --git a/servers/rendering/renderer_rd/storage_rd/light_storage.cpp b/servers/rendering/renderer_rd/storage_rd/light_storage.cpp
index c83473ef07..637aff9aac 100644
--- a/servers/rendering/renderer_rd/storage_rd/light_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/light_storage.cpp
@@ -653,6 +653,14 @@ void LightStorage::update_light_buffers(RenderDataRD *p_render_data, const Paged
if (light_data.shadow_opacity > 0.001) {
RS::LightDirectionalShadowMode smode = light->directional_shadow_mode;
+ light_data.soft_shadow_scale = light->param[RS::LIGHT_PARAM_SHADOW_BLUR];
+ light_data.softshadow_angle = angular_diameter;
+ light_data.bake_mode = light->bake_mode;
+
+ if (angular_diameter <= 0.0) {
+ light_data.soft_shadow_scale *= RendererSceneRenderRD::get_singleton()->directional_shadow_quality_radius_get(); // Only use quality radius for PCF
+ }
+
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->directional_blend_splits;
for (int j = 0; j < 4; j++) {
@@ -669,7 +677,7 @@ void LightStorage::update_light_buffers(RenderDataRD *p_render_data, const Paged
Projection shadow_mtx = rectm * bias * matrix * modelview;
light_data.shadow_split_offsets[j] = split;
- float bias_scale = light_instance->shadow_transform[j].bias_scale;
+ float bias_scale = light_instance->shadow_transform[j].bias_scale * light_data.soft_shadow_scale;
light_data.shadow_bias[j] = light->param[RS::LIGHT_PARAM_SHADOW_BIAS] / 100.0 * bias_scale;
light_data.shadow_normal_bias[j] = light->param[RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS] * light_instance->shadow_transform[j].shadow_texel_size;
light_data.shadow_transmittance_bias[j] = light->param[RS::LIGHT_PARAM_TRANSMITTANCE_BIAS] * bias_scale;
@@ -702,14 +710,6 @@ void LightStorage::update_light_buffers(RenderDataRD *p_render_data, const Paged
float fade_start = light->param[RS::LIGHT_PARAM_SHADOW_FADE_START];
light_data.fade_from = -light_data.shadow_split_offsets[3] * MIN(fade_start, 0.999); //using 1.0 would break smoothstep
light_data.fade_to = -light_data.shadow_split_offsets[3];
-
- light_data.soft_shadow_scale = light->param[RS::LIGHT_PARAM_SHADOW_BLUR];
- light_data.softshadow_angle = angular_diameter;
- light_data.bake_mode = light->bake_mode;
-
- if (angular_diameter <= 0.0) {
- light_data.soft_shadow_scale *= RendererSceneRenderRD::get_singleton()->directional_shadow_quality_radius_get(); // Only use quality radius for PCF
- }
}
r_directional_light_count++;
@@ -978,6 +978,7 @@ void LightStorage::update_light_buffers(RenderDataRD *p_render_data, const Paged
light_data.soft_shadow_size = 0.0;
light_data.soft_shadow_scale *= RendererSceneRenderRD::get_singleton()->shadows_quality_radius_get(); // Only use quality radius for PCF
}
+ light_data.shadow_bias *= light_data.soft_shadow_scale;
}
} else {
light_data.shadow_opacity = 0.0;
@@ -1314,6 +1315,10 @@ void LightStorage::reflection_atlas_set_size(RID p_ref_atlas, int p_reflection_s
ra->reflections.clear();
}
+
+ if (ra->render_buffers.is_valid()) {
+ ra->render_buffers->cleanup();
+ }
}
int LightStorage::reflection_atlas_get_size(RID p_ref_atlas) const {
@@ -1359,6 +1364,9 @@ void LightStorage::reflection_probe_release_atlas_index(RID p_instance) {
ERR_FAIL_COND(!atlas);
ERR_FAIL_INDEX(rpi->atlas_index, atlas->reflections.size());
atlas->reflections.write[rpi->atlas_index].owner = RID();
+
+ // TODO investigate if this is enough? shouldn't we be freeing our textures and framebuffers?
+
rpi->atlas_index = -1;
rpi->atlas = RID();
}
@@ -1397,6 +1405,10 @@ bool LightStorage::reflection_probe_instance_begin_render(RID p_instance, RID p_
ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance);
ERR_FAIL_COND_V(!rpi, false);
+ if (atlas->render_buffers.is_null()) {
+ atlas->render_buffers.instantiate();
+ }
+
RD::get_singleton()->draw_command_begin_label("Reflection probe render");
if (LightStorage::get_singleton()->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS && atlas->reflection.is_valid() && atlas->size != 256) {
@@ -1454,6 +1466,9 @@ bool LightStorage::reflection_probe_instance_begin_render(RID p_instance, RID p_
Vector<RID> fb;
fb.push_back(atlas->depth_buffer);
atlas->depth_fb = RD::get_singleton()->framebuffer_create(fb);
+
+ atlas->render_buffers->cleanup();
+ atlas->render_buffers->configure_for_reflections(Size2i(atlas->size, atlas->size));
}
if (rpi->atlas_index == -1) {
@@ -1493,6 +1508,13 @@ bool LightStorage::reflection_probe_instance_begin_render(RID p_instance, RID p_
return true;
}
+Ref<RenderSceneBuffers> LightStorage::reflection_probe_atlas_get_render_buffers(RID p_reflection_atlas) {
+ ReflectionAtlas *atlas = reflection_atlas_owner.get_or_null(p_reflection_atlas);
+ ERR_FAIL_COND_V(!atlas, Ref<RenderSceneBuffersRD>());
+
+ return atlas->render_buffers;
+}
+
bool LightStorage::reflection_probe_instance_postprocess_step(RID p_instance) {
ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance);
ERR_FAIL_COND_V(!rpi, false);
@@ -1725,13 +1747,13 @@ void LightStorage::lightmap_set_textures(RID p_lightmap, RID p_light, bool p_use
//erase lightmap users
if (lm->light_texture.is_valid()) {
- TextureStorage::Texture *t = texture_storage->get_singleton()->get_texture(lm->light_texture);
+ TextureStorage::Texture *t = texture_storage->get_texture(lm->light_texture);
if (t) {
t->lightmap_users.erase(p_lightmap);
}
}
- TextureStorage::Texture *t = texture_storage->get_singleton()->get_texture(p_light);
+ TextureStorage::Texture *t = texture_storage->get_texture(p_light);
lm->light_texture = p_light;
lm->uses_spherical_harmonics = p_uses_spherical_haromics;
diff --git a/servers/rendering/renderer_rd/storage_rd/light_storage.h b/servers/rendering/renderer_rd/storage_rd/light_storage.h
index 79006ad982..d31924eeb0 100644
--- a/servers/rendering/renderer_rd/storage_rd/light_storage.h
+++ b/servers/rendering/renderer_rd/storage_rd/light_storage.h
@@ -38,6 +38,7 @@
#include "servers/rendering/renderer_rd/cluster_builder_rd.h"
#include "servers/rendering/renderer_rd/environment/sky.h"
#include "servers/rendering/renderer_rd/storage_rd/forward_id_storage.h"
+#include "servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h"
#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
#include "servers/rendering/storage/light_storage.h"
#include "servers/rendering/storage/utilities.h"
@@ -256,6 +257,8 @@ private:
Vector<Reflection> reflections;
+ Ref<RenderSceneBuffersRD> render_buffers; // Further render buffers used.
+
ClusterBuilderRD *cluster_builder = nullptr; // only used if cluster builder is supported by the renderer.
};
@@ -846,6 +849,7 @@ public:
virtual bool reflection_probe_instance_needs_redraw(RID p_instance) override;
virtual bool reflection_probe_instance_has_reflection(RID p_instance) override;
virtual bool reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas) override;
+ virtual Ref<RenderSceneBuffers> reflection_probe_atlas_get_render_buffers(RID p_reflection_atlas) override;
virtual bool reflection_probe_instance_postprocess_step(RID p_instance) override;
uint32_t reflection_probe_instance_get_resolution(RID p_instance);
diff --git a/servers/rendering/renderer_rd/storage_rd/material_storage.cpp b/servers/rendering/renderer_rd/storage_rd/material_storage.cpp
index 6703d8e7d0..709e4b449f 100644
--- a/servers/rendering/renderer_rd/storage_rd/material_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/material_storage.cpp
@@ -928,6 +928,104 @@ _FORCE_INLINE_ static void _fill_std140_ubo_empty(ShaderLanguage::DataType type,
}
///////////////////////////////////////////////////////////////////////////
+// MaterialStorage::ShaderData
+
+void MaterialStorage::ShaderData::set_path_hint(const String &p_hint) {
+ path = p_hint;
+}
+
+void MaterialStorage::ShaderData::set_default_texture_parameter(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;
+ }
+}
+
+Variant MaterialStorage::ShaderData::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();
+}
+
+void MaterialStorage::ShaderData::get_shader_uniform_list(List<PropertyInfo> *p_param_list) const {
+ SortArray<Pair<StringName, int>, ShaderLanguage::UniformOrderComparator> sorter;
+ LocalVector<Pair<StringName, int>> filtered_uniforms;
+
+ for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
+ if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_LOCAL) {
+ continue;
+ }
+ if (E.value.texture_order >= 0) {
+ filtered_uniforms.push_back(Pair<StringName, int>(E.key, E.value.texture_order + 100000));
+ } else {
+ filtered_uniforms.push_back(Pair<StringName, int>(E.key, E.value.order));
+ }
+ }
+ int uniform_count = filtered_uniforms.size();
+ sorter.sort(filtered_uniforms.ptr(), uniform_count);
+
+ String last_group;
+ for (int i = 0; i < uniform_count; i++) {
+ const StringName &uniform_name = filtered_uniforms[i].first;
+ const ShaderLanguage::ShaderNode::Uniform &uniform = uniforms[uniform_name];
+
+ String group = uniform.group;
+ if (!uniform.subgroup.is_empty()) {
+ group += "::" + uniform.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(uniform);
+ pi.name = uniform_name;
+ p_param_list->push_back(pi);
+ }
+}
+
+void MaterialStorage::ShaderData::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 MaterialStorage::ShaderData::is_parameter_texture(const StringName &p_param) const {
+ if (!uniforms.has(p_param)) {
+ return false;
+ }
+
+ return uniforms[p_param].texture_order >= 0;
+}
+
+///////////////////////////////////////////////////////////////////////////
// MaterialStorage::MaterialData
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) {
@@ -1221,6 +1319,10 @@ void MaterialStorage::MaterialData::update_textures(const HashMap<StringName, Va
roughness_detect_texture = tex;
roughness_channel = RS::TextureDetectRoughnessChannel(p_texture_uniforms[i].hint - ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_R);
}
+ if (tex->render_target) {
+ tex->render_target->was_used = true;
+ render_target_cache.push_back(tex->render_target);
+ }
#endif
}
if (rd_texture.is_null()) {
@@ -1307,6 +1409,7 @@ bool MaterialStorage::MaterialData::update_parameters_uniform_set(const HashMap<
if ((uint32_t)texture_cache.size() != tex_uniform_count || p_textures_dirty) {
texture_cache.resize(tex_uniform_count);
+ render_target_cache.clear();
p_textures_dirty = true;
//clear previous uniform set
@@ -1367,6 +1470,12 @@ bool MaterialStorage::MaterialData::update_parameters_uniform_set(const HashMap<
return true;
}
+void MaterialStorage::MaterialData::set_as_used() {
+ for (int i = 0; i < render_target_cache.size(); i++) {
+ render_target_cache[i]->was_used = true;
+ }
+}
+
///////////////////////////////////////////////////////////////////////////
// MaterialStorage
diff --git a/servers/rendering/renderer_rd/storage_rd/material_storage.h b/servers/rendering/renderer_rd/storage_rd/material_storage.h
index fb25e56ed3..989a0f7b45 100644
--- a/servers/rendering/renderer_rd/storage_rd/material_storage.h
+++ b/servers/rendering/renderer_rd/storage_rd/material_storage.h
@@ -31,6 +31,8 @@
#ifndef MATERIAL_STORAGE_RD_H
#define MATERIAL_STORAGE_RD_H
+#include "texture_storage.h"
+
#include "core/math/projection.h"
#include "core/templates/local_vector.h"
#include "core/templates/rid_owner.h"
@@ -54,24 +56,30 @@ public:
};
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_parameter(const StringName &p_name, RID p_texture, int p_index) = 0;
- virtual void get_shader_uniform_list(List<PropertyInfo> *p_param_list) const = 0;
+ String path;
+ HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms;
+ HashMap<StringName, HashMap<int, RID>> default_texture_params;
- virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const = 0;
- virtual bool is_parameter_texture(const StringName &p_param) const = 0;
+ virtual void set_path_hint(const String &p_hint);
+ virtual void set_default_texture_parameter(const StringName &p_name, RID p_texture, int p_index);
+ virtual Variant get_default_parameter(const StringName &p_parameter) 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_parameter_texture(const StringName &p_param) const;
+
+ virtual void set_code(const String &p_Code) = 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() {}
};
struct MaterialData {
+ Vector<RendererRD::TextureStorage::RenderTarget *> render_target_cache;
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);
+ void set_as_used();
virtual void set_render_priority(int p_priority) = 0;
virtual void set_next_pass(RID p_pass) = 0;
@@ -79,7 +87,7 @@ public:
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, bool p_use_linear_color, uint32_t p_barrier = RD::BARRIER_MASK_ALL);
+ 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, bool p_use_linear_color, uint32_t p_barrier = RD::BARRIER_MASK_ALL_BARRIERS);
void free_parameters_uniform_set(RID p_uniform_set);
private:
diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp
index 1e74d31383..35fa3931f8 100644
--- a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp
@@ -434,20 +434,8 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface)
}
if (mesh->surface_count == 0) {
- mesh->bone_aabbs = p_surface.bone_aabbs;
mesh->aabb = p_surface.aabb;
} else {
- if (mesh->bone_aabbs.size() < p_surface.bone_aabbs.size()) {
- // ArrayMesh::_surface_set_data only allocates bone_aabbs up to max_bone
- // Each surface may affect different numbers of bones.
- mesh->bone_aabbs.resize(p_surface.bone_aabbs.size());
- }
- for (int i = 0; i < p_surface.bone_aabbs.size(); i++) {
- const AABB &bone = p_surface.bone_aabbs[i];
- if (bone.has_volume()) {
- mesh->bone_aabbs.write[i].merge_with(bone);
- }
- }
mesh->aabb.merge_with(p_surface.aabb);
}
@@ -616,7 +604,7 @@ AABB MeshStorage::mesh_get_aabb(RID p_mesh, RID p_skeleton) {
Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton);
- if (!skeleton || skeleton->size == 0) {
+ if (!skeleton || skeleton->size == 0 || mesh->skeleton_aabb_version == skeleton->version) {
return mesh->aabb;
}
@@ -708,6 +696,9 @@ AABB MeshStorage::mesh_get_aabb(RID p_mesh, RID p_skeleton) {
}
}
+ mesh->aabb = aabb;
+
+ mesh->skeleton_aabb_version = skeleton->version;
return aabb;
}
@@ -1841,7 +1832,7 @@ void MeshStorage::_update_dirty_multimeshes() {
RD::get_singleton()->buffer_update(multimesh->buffer, buffer_offset * sizeof(float) + offset, MIN(region_size, size - offset), &data[region_start_index], RD::BARRIER_MASK_NO_BARRIER);
}
}
- RD::get_singleton()->barrier(RD::BARRIER_MASK_NO_BARRIER, RD::BARRIER_MASK_ALL);
+ RD::get_singleton()->barrier(RD::BARRIER_MASK_NO_BARRIER, RD::BARRIER_MASK_ALL_BARRIERS);
}
memcpy(multimesh->previous_data_cache_dirty_regions, multimesh->data_cache_dirty_regions, data_cache_dirty_region_count * sizeof(bool));
diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.h b/servers/rendering/renderer_rd/storage_rd/mesh_storage.h
index 6a7400631d..a8feddc3b9 100644
--- a/servers/rendering/renderer_rd/storage_rd/mesh_storage.h
+++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.h
@@ -138,12 +138,11 @@ private:
Surface **surfaces = nullptr;
uint32_t surface_count = 0;
- Vector<AABB> bone_aabbs;
-
bool has_bone_weights = false;
AABB aabb;
AABB custom_aabb;
+ uint64_t skeleton_aabb_version = 0;
Vector<RID> material_cache;
@@ -664,7 +663,6 @@ public:
virtual void skeleton_allocate_data(RID p_skeleton, int p_bones, bool p_2d_skeleton = false) override;
virtual void skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform) override;
- void skeleton_set_world_transform(RID p_skeleton, bool p_enable, const Transform3D &p_world_transform);
virtual int skeleton_get_bone_count(RID p_skeleton) const override;
virtual void skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform3D &p_transform) override;
virtual Transform3D skeleton_bone_get_transform(RID p_skeleton, int p_bone) const override;
diff --git a/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp
index 854976692e..708455706b 100644
--- a/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp
@@ -810,6 +810,15 @@ void ParticlesStorage::_particles_process(Particles *p_particles, double p_delta
//2D collision
Transform2D xform = p_particles->sdf_collision_transform; //will use dotproduct manually so invert beforehand
+
+ if (!p_particles->use_local_coords) {
+ Transform2D emission;
+ emission.columns[0] = Vector2(p_particles->emission_transform.basis.get_column(0).x, p_particles->emission_transform.basis.get_column(0).y);
+ emission.columns[1] = Vector2(p_particles->emission_transform.basis.get_column(1).x, p_particles->emission_transform.basis.get_column(1).y);
+ emission.set_origin(Vector2(p_particles->emission_transform.origin.x, p_particles->emission_transform.origin.y));
+ xform = xform * emission.affine_inverse();
+ }
+
Transform2D revert = xform.affine_inverse();
frame_params.collider_count = 1;
frame_params.colliders[0].transform[0] = xform.columns[0][0];
@@ -1027,6 +1036,7 @@ void ParticlesStorage::_particles_process(Particles *p_particles, double p_delta
uniforms.push_back(u);
}
p_particles->collision_textures_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, particles_shader.default_shader_rd, 2);
+ p_particles->collision_heightmap_texture = collision_heightmap_texture;
}
}
@@ -1106,6 +1116,7 @@ void ParticlesStorage::_particles_process(Particles *p_particles, double p_delta
if (m->uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(m->uniform_set)) {
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, m->uniform_set, 3);
+ m->set_as_used();
}
RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(ParticlesShader::PushConstant));
@@ -1404,6 +1415,7 @@ void ParticlesStorage::update_particles() {
}
bool zero_time_scale = Engine::get_singleton()->get_time_scale() <= 0.0;
+ bool updated = false;
if (particles->clear && particles->pre_process_time > 0.0) {
double frame_time;
@@ -1418,6 +1430,7 @@ void ParticlesStorage::update_particles() {
while (todo >= 0) {
_particles_process(particles, frame_time);
todo -= frame_time;
+ updated = true;
}
}
@@ -1439,9 +1452,10 @@ void ParticlesStorage::update_particles() {
}
double todo = particles->frame_remainder + delta;
- while (todo >= frame_time) {
+ while (todo >= frame_time || (particles->clear && !updated)) {
_particles_process(particles, frame_time);
todo -= decr;
+ updated = true;
}
particles->frame_remainder = todo;
@@ -1449,14 +1463,16 @@ void ParticlesStorage::update_particles() {
} else {
if (zero_time_scale) {
_particles_process(particles, 0.0);
+ updated = true;
} else {
_particles_process(particles, RendererCompositorRD::singleton->get_frame_delta_time());
+ updated = true;
}
}
//copy particles to instance buffer
- if (particles->draw_order != RS::PARTICLES_DRAW_ORDER_VIEW_DEPTH && particles->transform_align != RS::PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD && particles->transform_align != RS::PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD_Y_TO_VELOCITY) {
+ if (updated && particles->draw_order != RS::PARTICLES_DRAW_ORDER_VIEW_DEPTH && particles->transform_align != RS::PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD && particles->transform_align != RS::PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD_Y_TO_VELOCITY) {
//does not need view dependent operation, do copy here
ParticlesShader::CopyPushConstant copy_push_constant;
@@ -1533,9 +1549,6 @@ 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
@@ -1601,83 +1614,6 @@ void ParticlesStorage::ParticlesShaderData::set_code(const String &p_code) {
valid = true;
}
-void ParticlesStorage::ParticlesShaderData::set_default_texture_parameter(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 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) {
- 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 ParticlesStorage::ParticlesShaderData::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 ParticlesStorage::ParticlesShaderData::is_parameter_texture(const StringName &p_param) const {
- if (!uniforms.has(p_param)) {
- return false;
- }
-
- return uniforms[p_param].texture_order >= 0;
-}
-
bool ParticlesStorage::ParticlesShaderData::is_animated() const {
return false;
}
@@ -1686,15 +1622,6 @@ bool ParticlesStorage::ParticlesShaderData::casts_shadows() const {
return false;
}
-Variant ParticlesStorage::ParticlesShaderData::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 ParticlesStorage::ParticlesShaderData::get_native_source_code() const {
return ParticlesStorage::get_singleton()->particles_shader.shader.version_get_native_source_code(version);
}
diff --git a/servers/rendering/renderer_rd/storage_rd/particles_storage.h b/servers/rendering/renderer_rd/storage_rd/particles_storage.h
index a9cc98abb9..0701dc95dd 100644
--- a/servers/rendering/renderer_rd/storage_rd/particles_storage.h
+++ b/servers/rendering/renderer_rd/storage_rd/particles_storage.h
@@ -54,8 +54,7 @@ private:
float velocity[3];
uint32_t active;
float color[4];
- float custom[3];
- float lifetime;
+ float custom[4];
};
struct ParticlesFrameParams {
@@ -127,9 +126,6 @@ private:
Collider colliders[MAX_COLLIDERS];
};
- struct ParticleEmissionBufferData {
- };
-
struct ParticleEmissionBuffer {
struct Data {
float xform[16];
@@ -317,15 +313,12 @@ private:
RID version;
bool uses_collision = false;
- 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;
RID pipeline;
@@ -335,14 +328,8 @@ 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_parameter(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_parameter_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;
ParticlesShaderData() {}
@@ -412,7 +399,7 @@ public:
bool owns_particles(RID p_rid) { return particles_owner.owns(p_rid); }
virtual RID particles_allocate() override;
- virtual void particles_initialize(RID p_particles_collision) override;
+ virtual void particles_initialize(RID p_rid) override;
virtual void particles_free(RID p_rid) override;
virtual void particles_set_mode(RID p_particles, RS::ParticlesMode p_mode) override;
@@ -468,6 +455,12 @@ public:
return particles->mode;
}
+ _FORCE_INLINE_ uint32_t particles_get_frame_counter(RID p_particles) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND_V(!particles, false);
+ return particles->frame_counter;
+ }
+
_FORCE_INLINE_ uint32_t particles_get_amount(RID p_particles, uint32_t &r_trail_divisor) {
Particles *particles = particles_owner.get_or_null(p_particles);
ERR_FAIL_COND_V(!particles, 0);
@@ -498,9 +491,8 @@ public:
_FORCE_INLINE_ RID particles_get_instance_buffer_uniform_set(RID p_particles, RID p_shader, uint32_t p_set) {
Particles *particles = particles_owner.get_or_null(p_particles);
ERR_FAIL_COND_V(!particles, RID());
- if (particles->particles_transforms_buffer_uniform_set.is_null()) {
+ if (particles->particles_transforms_buffer_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(particles->particles_transforms_buffer_uniform_set)) {
_particles_update_buffers(particles);
-
Vector<RD::Uniform> uniforms;
{
@@ -519,7 +511,7 @@ public:
virtual void particles_add_collision(RID p_particles, RID p_particles_collision_instance) override;
virtual void particles_remove_collision(RID p_particles, RID p_particles_collision_instance) override;
- virtual void particles_set_canvas_sdf_collision(RID p_particles, bool p_enable, const Transform2D &p_xform, const Rect2 &p_to_screen, RID p_texture) override;
+ void particles_set_canvas_sdf_collision(RID p_particles, bool p_enable, const Transform2D &p_xform, const Rect2 &p_to_screen, RID p_texture);
virtual void update_particles() override;
@@ -546,7 +538,7 @@ public:
virtual AABB particles_collision_get_aabb(RID p_particles_collision) const override;
Vector3 particles_collision_get_extents(RID p_particles_collision) const;
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;
+ RID particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const;
Dependency *particles_collision_get_dependency(RID p_particles) const;
diff --git a/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.cpp b/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.cpp
index 0c2092f03e..12ba29a0b8 100644
--- a/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.cpp
@@ -202,6 +202,30 @@ void RenderSceneBuffersRD::configure(RID p_render_target, const Size2i p_interna
vrs_texture = create_texture(RB_SCOPE_VRS, RB_TEXTURE, RD::DATA_FORMAT_R8_UINT, usage_bits, RD::TEXTURE_SAMPLES_1, vrs->get_vrs_texture_size(internal_size));
}
+ // (re-)configure any named buffers
+ for (KeyValue<StringName, Ref<RenderBufferCustomDataRD>> &E : data_buffers) {
+ E.value->configure(this);
+ }
+}
+
+void RenderSceneBuffersRD::configure_for_reflections(const Size2i p_reflection_size) {
+ // For now our render buffers for reflections are only used for effects/environment (Sky/Fog/Etc)
+ // Possibly at some point move our entire reflection atlas buffer management into this class
+
+ target_size = p_reflection_size;
+ internal_size = p_reflection_size;
+ render_target = RID();
+ fsr_sharpness = 0.0;
+ msaa_3d = RS::VIEWPORT_MSAA_DISABLED;
+ screen_space_aa = RS::VIEWPORT_SCREEN_SPACE_AA_DISABLED;
+ use_taa = false;
+ use_debanding = false;
+ view_count = 1;
+
+ // cleanout any old buffers we had.
+ cleanup();
+
+ // (re-)configure any named buffers
for (KeyValue<StringName, Ref<RenderBufferCustomDataRD>> &E : data_buffers) {
E.value->configure(this);
}
diff --git a/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h b/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h
index 6907f69b93..4b82f70e1a 100644
--- a/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h
+++ b/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h
@@ -140,6 +140,7 @@ public:
void cleanup();
virtual void configure(RID p_render_target, const Size2i p_internal_size, const Size2i p_target_size, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa_3d, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) override;
+ void configure_for_reflections(const Size2i p_reflection_size);
virtual void set_fsr_sharpness(float p_fsr_sharpness) override;
virtual void set_texture_mipmap_bias(float p_texture_mipmap_bias) override;
virtual void set_use_debanding(bool p_use_debanding) override;
diff --git a/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.cpp b/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.cpp
index 7dd790d1da..9b3d5a2d29 100644
--- a/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.cpp
@@ -88,6 +88,7 @@ void RenderSceneDataRD::update_ubo(RID p_uniform_buffer, RS::ViewportDebugDraw p
RendererRD::MaterialStorage::store_soft_shadow_kernel(render_scene_render->directional_soft_shadow_kernel_get(), ubo.directional_soft_shadow_kernel);
RendererRD::MaterialStorage::store_soft_shadow_kernel(render_scene_render->penumbra_shadow_kernel_get(), ubo.penumbra_shadow_kernel);
RendererRD::MaterialStorage::store_soft_shadow_kernel(render_scene_render->soft_shadow_kernel_get(), ubo.soft_shadow_kernel);
+ ubo.camera_visible_layers = camera_visible_layers;
ubo.viewport_size[0] = p_screen_size.x;
ubo.viewport_size[1] = p_screen_size.y;
diff --git a/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.h b/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.h
index 9c031acc1e..5ea4991e8e 100644
--- a/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.h
+++ b/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.h
@@ -45,6 +45,7 @@ public:
Transform3D cam_transform;
Projection cam_projection;
Vector2 taa_jitter;
+ uint32_t camera_visible_layers;
bool cam_orthogonal = false;
// For stereo rendering
@@ -142,7 +143,7 @@ private:
float IBL_exposure_normalization; // Adjusts for baked exposure.
uint32_t pancake_shadows;
- uint32_t pad1;
+ uint32_t camera_visible_layers;
uint32_t pad2;
uint32_t pad3;
};
diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
index 077fde58b8..6a4359faf3 100644
--- a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
@@ -419,11 +419,12 @@ TextureStorage::TextureStorage() {
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_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT;
- if (RD::get_singleton()->has_feature(RD::SUPPORTS_ATTACHMENT_VRS)) {
- tformat.usage_bits |= RD::TEXTURE_USAGE_VRS_ATTACHMENT_BIT;
- }
+ tformat.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT | RD::TEXTURE_USAGE_VRS_ATTACHMENT_BIT;
tformat.texture_type = RD::TEXTURE_TYPE_2D;
+ if (!RD::get_singleton()->has_feature(RD::SUPPORTS_ATTACHMENT_VRS)) {
+ tformat.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT;
+ tformat.format = RD::DATA_FORMAT_R8_UNORM;
+ }
Vector<uint8_t> pv;
pv.resize(4 * 4);
@@ -560,6 +561,7 @@ void TextureStorage::canvas_texture_set_texture_filter(RID p_canvas_texture, RS:
void TextureStorage::canvas_texture_set_texture_repeat(RID p_canvas_texture, RS::CanvasItemTextureRepeat p_repeat) {
CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture);
ERR_FAIL_NULL(ct);
+
ct->texture_repeat = p_repeat;
ct->clear_sets();
}
@@ -580,6 +582,9 @@ bool TextureStorage::canvas_texture_get_uniform_set(RID p_texture, RS::CanvasIte
}
ct = t->canvas_texture;
+ if (t->render_target) {
+ t->render_target->was_used = true;
+ }
} else {
ct = canvas_texture_owner.get_or_null(p_texture);
}
@@ -610,6 +615,9 @@ bool TextureStorage::canvas_texture_get_uniform_set(RID p_texture, RS::CanvasIte
} else {
u.append_id(t->rd_texture);
ct->size_cache = Size2i(t->width_2d, t->height_2d);
+ if (t->render_target) {
+ t->render_target->was_used = true;
+ }
}
uniforms.push_back(u);
}
@@ -625,6 +633,9 @@ bool TextureStorage::canvas_texture_get_uniform_set(RID p_texture, RS::CanvasIte
} else {
u.append_id(t->rd_texture);
ct->use_normal_cache = true;
+ if (t->render_target) {
+ t->render_target->was_used = true;
+ }
}
uniforms.push_back(u);
}
@@ -640,6 +651,9 @@ bool TextureStorage::canvas_texture_get_uniform_set(RID p_texture, RS::CanvasIte
} else {
u.append_id(t->rd_texture);
ct->use_specular_cache = true;
+ if (t->render_target) {
+ t->render_target->was_used = true;
+ }
}
uniforms.push_back(u);
}
@@ -1763,6 +1777,46 @@ Ref<Image> TextureStorage::_validate_texture_format(const Ref<Image> &p_image, T
r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO;
r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
} break;
+ case Image::FORMAT_ASTC_4x4:
+ case Image::FORMAT_ASTC_4x4_HDR: {
+ if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_ASTC_4x4_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
+ r_format.format = RD::DATA_FORMAT_ASTC_4x4_UNORM_BLOCK;
+ if (p_image->get_format() == Image::FORMAT_ASTC_4x4) {
+ r_format.format_srgb = RD::DATA_FORMAT_ASTC_4x4_SRGB_BLOCK;
+ }
+ } else {
+ //not supported, reconvert
+ r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
+ r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB;
+ image->decompress();
+ image->convert(Image::FORMAT_RGBA8);
+ }
+ r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
+ r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
+ r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B;
+ r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A;
+
+ } break; // astc 4x4
+ case Image::FORMAT_ASTC_8x8:
+ case Image::FORMAT_ASTC_8x8_HDR: {
+ if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_ASTC_8x8_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
+ r_format.format = RD::DATA_FORMAT_ASTC_8x8_UNORM_BLOCK;
+ if (p_image->get_format() == Image::FORMAT_ASTC_8x8) {
+ r_format.format_srgb = RD::DATA_FORMAT_ASTC_8x8_SRGB_BLOCK;
+ }
+ } else {
+ //not supported, reconvert
+ r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
+ r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB;
+ image->decompress();
+ image->convert(Image::FORMAT_RGBA8);
+ }
+ r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
+ r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
+ r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B;
+ r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A;
+
+ } break; // astc 8x8
default: {
}
@@ -2397,6 +2451,10 @@ void TextureStorage::_clear_render_target(RenderTarget *rt) {
rt->color = RID();
rt->color_multisample = RID();
+ if (rt->texture.is_valid()) {
+ Texture *tex = get_texture(rt->texture);
+ tex->render_target = nullptr;
+ }
}
void TextureStorage::_update_render_target(RenderTarget *rt) {
@@ -2477,6 +2535,7 @@ void TextureStorage::_update_render_target(RenderTarget *rt) {
tex->rd_texture = RID();
tex->rd_texture_srgb = RID();
+ tex->render_target = rt;
//create shared textures to the color buffer,
//so transparent can be supported
@@ -3119,9 +3178,11 @@ void TextureStorage::render_target_copy_to_back_buffer(RID p_render_target, cons
// TODO figure out stereo support here
- //single texture copy for backbuffer
- //RD::get_singleton()->texture_copy(rt->color, rt->backbuffer_mipmap0, Vector3(region.position.x, region.position.y, 0), Vector3(region.position.x, region.position.y, 0), Vector3(region.size.x, region.size.y, 1), 0, 0, 0, 0, true);
- copy_effects->copy_to_rect(rt->color, rt->backbuffer_mipmap0, region, false, false, false, true, true);
+ if (RendererSceneRenderRD::get_singleton()->_render_buffers_can_be_storage()) {
+ copy_effects->copy_to_rect(rt->color, rt->backbuffer_mipmap0, region, false, false, false, true, true);
+ } else {
+ copy_effects->copy_to_fb_rect(rt->color, rt->backbuffer_fb, region, false, false, false, false, RID(), false, true);
+ }
if (!p_gen_mipmaps) {
return;
@@ -3130,14 +3191,22 @@ void TextureStorage::render_target_copy_to_back_buffer(RID p_render_target, cons
//then mipmap blur
RID prev_texture = rt->color; //use color, not backbuffer, as bb has mipmaps.
+ Size2i texture_size = rt->size;
+
for (int i = 0; i < rt->backbuffer_mipmaps.size(); i++) {
region.position.x >>= 1;
region.position.y >>= 1;
region.size.x = MAX(1, region.size.x >> 1);
region.size.y = MAX(1, region.size.y >> 1);
+ texture_size.x = MAX(1, texture_size.x >> 1);
+ texture_size.y = MAX(1, texture_size.y >> 1);
RID mipmap = rt->backbuffer_mipmaps[i];
- copy_effects->gaussian_blur(prev_texture, mipmap, region, true);
+ if (RendererSceneRenderRD::get_singleton()->_render_buffers_can_be_storage()) {
+ copy_effects->gaussian_blur(prev_texture, mipmap, region, texture_size, true);
+ } else {
+ copy_effects->gaussian_blur_raster(prev_texture, mipmap, region, texture_size);
+ }
prev_texture = mipmap;
}
RD::get_singleton()->draw_command_end_label();
@@ -3165,7 +3234,11 @@ void TextureStorage::render_target_clear_back_buffer(RID p_render_target, const
}
//single texture copy for backbuffer
- copy_effects->set_color(rt->backbuffer_mipmap0, p_color, region, true);
+ if (RendererSceneRenderRD::get_singleton()->_render_buffers_can_be_storage()) {
+ copy_effects->set_color(rt->backbuffer_mipmap0, p_color, region, true);
+ } else {
+ copy_effects->set_color_raster(rt->backbuffer_mipmap0, p_color, region);
+ }
}
void TextureStorage::render_target_gen_back_buffer_mipmaps(RID p_render_target, const Rect2i &p_region) {
@@ -3191,15 +3264,23 @@ void TextureStorage::render_target_gen_back_buffer_mipmaps(RID p_render_target,
RD::get_singleton()->draw_command_begin_label("Gaussian Blur Mipmaps2");
//then mipmap blur
RID prev_texture = rt->backbuffer_mipmap0;
+ Size2i texture_size = rt->size;
for (int i = 0; i < rt->backbuffer_mipmaps.size(); i++) {
region.position.x >>= 1;
region.position.y >>= 1;
region.size.x = MAX(1, region.size.x >> 1);
region.size.y = MAX(1, region.size.y >> 1);
+ texture_size.x = MAX(1, texture_size.x >> 1);
+ texture_size.y = MAX(1, texture_size.y >> 1);
RID mipmap = rt->backbuffer_mipmaps[i];
- copy_effects->gaussian_blur(prev_texture, mipmap, region, true);
+
+ if (RendererSceneRenderRD::get_singleton()->_render_buffers_can_be_storage()) {
+ copy_effects->gaussian_blur(prev_texture, mipmap, region, texture_size, true);
+ } else {
+ copy_effects->gaussian_blur_raster(prev_texture, mipmap, region, texture_size);
+ }
prev_texture = mipmap;
}
RD::get_singleton()->draw_command_end_label();
diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.h b/servers/rendering/renderer_rd/storage_rd/texture_storage.h
index f4737eb63d..0c70d3f938 100644
--- a/servers/rendering/renderer_rd/storage_rd/texture_storage.h
+++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.h
@@ -108,6 +108,8 @@ private:
/* Texture API */
+ struct RenderTarget;
+
class Texture {
public:
TextureType type;
@@ -141,6 +143,7 @@ private:
Vector<BufferSlice3D> buffer_slices_3d;
uint32_t buffer_size_3d = 0;
+ RenderTarget *render_target = nullptr;
bool is_render_target;
bool is_proxy;
diff --git a/servers/rendering/renderer_scene_cull.cpp b/servers/rendering/renderer_scene_cull.cpp
index 348f6e4695..675e81c62a 100644
--- a/servers/rendering/renderer_scene_cull.cpp
+++ b/servers/rendering/renderer_scene_cull.cpp
@@ -646,6 +646,7 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) {
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_pivot_data(instance->sorting_offset, instance->use_aabb_center);
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);
@@ -844,6 +845,20 @@ void RendererSceneCull::instance_set_layer_mask(RID p_instance, uint32_t p_mask)
}
}
+void RendererSceneCull::instance_set_pivot_data(RID p_instance, float p_sorting_offset, bool p_use_aabb_center) {
+ Instance *instance = instance_owner.get_or_null(p_instance);
+ ERR_FAIL_COND(!instance);
+
+ instance->sorting_offset = p_sorting_offset;
+ instance->use_aabb_center = p_use_aabb_center;
+
+ if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) {
+ InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);
+ ERR_FAIL_NULL(geom->geometry_instance);
+ geom->geometry_instance->set_pivot_data(p_sorting_offset, p_use_aabb_center);
+ }
+}
+
void RendererSceneCull::instance_geometry_set_transparency(RID p_instance, float p_transparency) {
Instance *instance = instance_owner.get_or_null(p_instance);
ERR_FAIL_COND(!instance);
@@ -2512,7 +2527,7 @@ void RendererSceneCull::render_camera(const Ref<RenderSceneBuffers> &p_render_bu
} break;
}
- camera_data.set_camera(transform, projection, is_orthogonal, vaspect, jitter);
+ camera_data.set_camera(transform, projection, is_orthogonal, vaspect, jitter, camera->visible_layers);
} else {
// Setup our camera for our XR interface.
// We can support multiple views here each with their own camera
@@ -2520,7 +2535,7 @@ void RendererSceneCull::render_camera(const Ref<RenderSceneBuffers> &p_render_bu
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");
+ ERR_FAIL_COND_MSG(view_count == 0 || view_count > RendererSceneRender::MAX_RENDER_VIEWS, "Requested view count is not supported");
float aspect = p_viewport_size.width / (float)p_viewport_size.height;
@@ -2534,7 +2549,7 @@ void RendererSceneCull::render_camera(const Ref<RenderSceneBuffers> &p_render_bu
}
if (view_count == 1) {
- camera_data.set_camera(transforms[0], projections[0], false, camera->vaspect, jitter);
+ camera_data.set_camera(transforms[0], projections[0], false, camera->vaspect, jitter, camera->visible_layers);
} else if (view_count == 2) {
camera_data.set_multiview_camera(view_count, transforms, projections, false, camera->vaspect);
} else {
@@ -2930,7 +2945,7 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c
scene_render->set_scene_pass(render_pass);
- if (p_render_buffers.is_valid()) {
+ if (p_render_buffers.is_valid() && p_reflection_probe.is_null()) {
//no rendering code here, this is only to set up what needs to be done, request regions, etc.
scene_render->sdfgi_update(p_render_buffers, p_environment, p_camera_data->main_transform.origin); //update conditions for SDFGI (whether its used or not)
}
@@ -3012,7 +3027,7 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c
{ //sdfgi
cull.sdfgi.region_count = 0;
- if (p_render_buffers.is_valid()) {
+ if (p_render_buffers.is_valid() && p_reflection_probe.is_null()) {
cull.sdfgi.cascade_light_count = 0;
uint32_t prev_cascade = 0xFFFFFFFF;
@@ -3214,6 +3229,8 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c
//render SDFGI
{
+ // Q: Should this whole block be skipped if we're rendering our reflection probe?
+
sdfgi_update_data.update_static = false;
if (cull.sdfgi.region_count > 0) {
@@ -3239,7 +3256,7 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c
}
}
- if (p_render_buffers.is_valid()) {
+ if (p_render_buffers.is_valid() && p_reflection_probe.is_null()) {
sdfgi_update_data.directional_lights = &directional_lights;
sdfgi_update_data.positional_light_instances = scenario->dynamic_lights.ptr();
sdfgi_update_data.positional_light_count = scenario->dynamic_lights.size();
@@ -3319,7 +3336,7 @@ void RendererSceneCull::render_empty_scene(const Ref<RenderSceneBuffers> &p_rend
RendererSceneRender::CameraData camera_data;
camera_data.set_camera(Transform3D(), Projection(), true, false);
- 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);
+ 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>(), environment, RID(), p_shadow_atlas, RID(), scenario->reflection_atlas, RID(), 0, 0, nullptr, 0, nullptr, 0, nullptr);
#endif
}
@@ -3392,7 +3409,7 @@ bool RendererSceneCull::_render_reflection_probe_step(Instance *p_instance, int
RendererSceneRender::CameraData camera_data;
camera_data.set_camera(xform, cm, false, false);
- Ref<RenderSceneBuffers> render_buffers;
+ Ref<RenderSceneBuffers> render_buffers = RSG::light_storage->reflection_probe_atlas_get_render_buffers(scenario->reflection_atlas);
_render_scene(&camera_data, render_buffers, environment, RID(), RSG::light_storage->reflection_probe_get_cull_mask(p_instance->base), p_instance->scenario->self, RID(), shadow_atlas, reflection_probe->instance, p_step, mesh_lod_threshold, use_shadows);
} else {
diff --git a/servers/rendering/renderer_scene_cull.h b/servers/rendering/renderer_scene_cull.h
index d085b84a8c..106871edfd 100644
--- a/servers/rendering/renderer_scene_cull.h
+++ b/servers/rendering/renderer_scene_cull.h
@@ -459,6 +459,10 @@ public:
float extra_margin;
ObjectID object_id;
+ // sorting
+ float sorting_offset = 0.0;
+ bool use_aabb_center = true;
+
Vector<Color> lightmap_target_sh; //target is used for incrementally changing the SH over time, this avoids pops in some corner cases and when going interior <-> exterior
uint64_t last_frame_pass;
@@ -476,6 +480,7 @@ public:
Instance *instance = (Instance *)tracker->userdata;
switch (p_notification) {
case Dependency::DEPENDENCY_CHANGED_SKELETON_DATA:
+ case Dependency::DEPENDENCY_CHANGED_SKELETON_BONES:
case Dependency::DEPENDENCY_CHANGED_AABB: {
singleton->_instance_queue_update(instance, true, false);
@@ -491,8 +496,7 @@ public:
case Dependency::DEPENDENCY_CHANGED_REFLECTION_PROBE: {
singleton->_instance_queue_update(instance, true, true);
} break;
- case Dependency::DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES:
- case Dependency::DEPENDENCY_CHANGED_SKELETON_BONES: {
+ case Dependency::DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES: {
//ignored
} break;
case Dependency::DEPENDENCY_CHANGED_LIGHT_SOFT_SHADOW_AND_PROJECTOR: {
@@ -933,6 +937,7 @@ public:
virtual void instance_set_base(RID p_instance, RID p_base);
virtual void instance_set_scenario(RID p_instance, RID p_scenario);
virtual void instance_set_layer_mask(RID p_instance, uint32_t p_mask);
+ virtual void instance_set_pivot_data(RID p_instance, float p_sorting_offset, bool p_use_aabb_center);
virtual void instance_set_transform(RID p_instance, const Transform3D &p_transform);
virtual void instance_attach_object_instance_id(RID p_instance, ObjectID p_id);
virtual void instance_set_blend_shape_weight(RID p_instance, int p_shape, float p_weight);
@@ -1173,7 +1178,6 @@ public:
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)
diff --git a/servers/rendering/renderer_scene_render.cpp b/servers/rendering/renderer_scene_render.cpp
index f085168df3..3c069f6e2e 100644
--- a/servers/rendering/renderer_scene_render.cpp
+++ b/servers/rendering/renderer_scene_render.cpp
@@ -33,7 +33,7 @@
/////////////////////////////////////////////////////////////////////////////
// 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) {
+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, const uint32_t p_visible_layers) {
view_count = 1;
is_orthogonal = p_is_orthogonal;
vaspect = p_vaspect;
@@ -41,6 +41,7 @@ void RendererSceneRender::CameraData::set_camera(const Transform3D p_transform,
main_transform = p_transform;
main_projection = p_projection;
+ visible_layers = p_visible_layers;
view_offset[0] = Transform3D();
view_projection[0] = p_projection;
taa_jitter = p_taa_jitter;
@@ -49,6 +50,7 @@ void RendererSceneRender::CameraData::set_camera(const Transform3D p_transform,
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");
+ visible_layers = 0xFFFFFFFF;
view_count = p_view_count;
is_orthogonal = p_is_orthogonal;
vaspect = p_vaspect;
diff --git a/servers/rendering/renderer_scene_render.h b/servers/rendering/renderer_scene_render.h
index a8df897077..71f0a78ef3 100644
--- a/servers/rendering/renderer_scene_render.h
+++ b/servers/rendering/renderer_scene_render.h
@@ -162,7 +162,6 @@ public:
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);
@@ -268,6 +267,7 @@ public:
// flags
uint32_t view_count;
bool is_orthogonal;
+ uint32_t visible_layers;
bool vaspect;
// Main/center projection
@@ -278,7 +278,7 @@ public:
Projection view_projection[RendererSceneRender::MAX_RENDER_VIEWS];
Vector2 taa_jitter;
- 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_camera(const Transform3D p_transform, const Projection p_projection, bool p_is_orthogonal, bool p_vaspect, const Vector2 &p_taa_jitter = Vector2(), uint32_t p_visible_layers = 0xFFFFFFFF);
void set_multiview_camera(uint32_t p_view_count, const Transform3D *p_transforms, const Projection *p_projections, bool p_is_orthogonal, bool p_vaspect);
};
diff --git a/servers/rendering/renderer_viewport.cpp b/servers/rendering/renderer_viewport.cpp
index 2836889de5..8cec531393 100644
--- a/servers/rendering/renderer_viewport.cpp
+++ b/servers/rendering/renderer_viewport.cpp
@@ -550,6 +550,9 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) {
if (!can_draw_3d) {
RSG::scene->render_empty_scene(p_viewport->render_buffers, p_viewport->scenario, p_viewport->shadow_atlas);
} else {
+ // There may be an outstanding clear request if a clear was requested, but no 2D elements were drawn.
+ // Clear now otherwise we copy over garbage from the render target.
+ RSG::texture_storage->render_target_do_clear_request(p_viewport->render_target);
_draw_3d(p_viewport);
}
}
diff --git a/servers/rendering/rendering_device.cpp b/servers/rendering/rendering_device.cpp
index bb4c41df52..28408ddb8e 100644
--- a/servers/rendering/rendering_device.cpp
+++ b/servers/rendering/rendering_device.cpp
@@ -32,8 +32,18 @@
#include "rendering_device_binds.h"
+#include "thirdparty/spirv-reflect/spirv_reflect.h"
+
RenderingDevice *RenderingDevice::singleton = nullptr;
+const char *RenderingDevice::shader_stage_names[RenderingDevice::SHADER_STAGE_MAX] = {
+ "Vertex",
+ "Fragment",
+ "TesselationControl",
+ "TesselationEvaluation",
+ "Compute",
+};
+
RenderingDevice *RenderingDevice::get_singleton() {
return singleton;
}
@@ -170,10 +180,16 @@ RenderingDevice::VertexFormatID RenderingDevice::_vertex_format_create(const Typ
return vertex_format_create(descriptions);
}
-RID RenderingDevice::_vertex_array_create(uint32_t p_vertex_count, VertexFormatID p_vertex_format, const TypedArray<RID> &p_src_buffers) {
+RID RenderingDevice::_vertex_array_create(uint32_t p_vertex_count, VertexFormatID p_vertex_format, const TypedArray<RID> &p_src_buffers, const Vector<int64_t> &p_offsets) {
Vector<RID> buffers = Variant(p_src_buffers);
- return vertex_array_create(p_vertex_count, p_vertex_format, buffers);
+ Vector<uint64_t> offsets;
+ offsets.resize(p_offsets.size());
+ for (int i = 0; i < p_offsets.size(); i++) {
+ offsets.write[i] = p_offsets[i];
+ }
+
+ return vertex_array_create(p_vertex_count, p_vertex_format, buffers, offsets);
}
Ref<RDShaderSPIRV> RenderingDevice::_shader_compile_spirv_from_source(const Ref<RDShaderSource> &p_source, bool p_allow_cache) {
@@ -246,7 +262,7 @@ RID RenderingDevice::_uniform_set_create(const TypedArray<RDUniform> &p_uniforms
return uniform_set_create(uniforms, p_shader, p_shader_set);
}
-Error RenderingDevice::_buffer_update(RID p_buffer, uint32_t p_offset, uint32_t p_size, const Vector<uint8_t> &p_data, uint32_t p_post_barrier) {
+Error RenderingDevice::_buffer_update(RID p_buffer, uint32_t p_offset, uint32_t p_size, const Vector<uint8_t> &p_data, BitField<BarrierMask> p_post_barrier) {
return buffer_update(p_buffer, p_offset, p_size, p_data.ptr(), p_post_barrier);
}
@@ -280,7 +296,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) {
+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, BitField<PipelineDynamicStateFlags> 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()) {
rasterization_state = p_rasterization_state->base;
@@ -362,12 +378,329 @@ void RenderingDevice::_compute_list_set_push_constant(ComputeListID p_list, cons
compute_list_set_push_constant(p_list, p_data.ptr(), p_data_size);
}
+Error RenderingDevice::_reflect_spirv(const Vector<ShaderStageSPIRVData> &p_spirv, SpirvReflectionData &r_reflection_data) {
+ r_reflection_data = {};
+
+ for (int i = 0; i < p_spirv.size(); i++) {
+ ShaderStage stage = p_spirv[i].shader_stage;
+ ShaderStage stage_flag = (ShaderStage)(1 << p_spirv[i].shader_stage);
+
+ if (p_spirv[i].shader_stage == SHADER_STAGE_COMPUTE) {
+ r_reflection_data.is_compute = true;
+ ERR_FAIL_COND_V_MSG(p_spirv.size() != 1, FAILED,
+ "Compute shaders can only receive one stage, dedicated to compute.");
+ }
+ ERR_FAIL_COND_V_MSG(r_reflection_data.stages_mask.has_flag(stage_flag), FAILED,
+ "Stage " + String(shader_stage_names[p_spirv[i].shader_stage]) + " submitted more than once.");
+
+ {
+ SpvReflectShaderModule module;
+ const uint8_t *spirv = p_spirv[i].spir_v.ptr();
+ SpvReflectResult result = spvReflectCreateShaderModule(p_spirv[i].spir_v.size(), spirv, &module);
+ ERR_FAIL_COND_V_MSG(result != SPV_REFLECT_RESULT_SUCCESS, FAILED,
+ "Reflection of SPIR-V shader stage '" + String(shader_stage_names[p_spirv[i].shader_stage]) + "' failed parsing shader.");
+
+ if (r_reflection_data.is_compute) {
+ r_reflection_data.compute_local_size[0] = module.entry_points->local_size.x;
+ r_reflection_data.compute_local_size[1] = module.entry_points->local_size.y;
+ r_reflection_data.compute_local_size[2] = module.entry_points->local_size.z;
+ }
+ uint32_t binding_count = 0;
+ result = spvReflectEnumerateDescriptorBindings(&module, &binding_count, nullptr);
+ ERR_FAIL_COND_V_MSG(result != SPV_REFLECT_RESULT_SUCCESS, FAILED,
+ "Reflection of SPIR-V shader stage '" + String(shader_stage_names[p_spirv[i].shader_stage]) + "' failed enumerating descriptor bindings.");
+
+ if (binding_count > 0) {
+ // Parse bindings.
+
+ Vector<SpvReflectDescriptorBinding *> bindings;
+ bindings.resize(binding_count);
+ result = spvReflectEnumerateDescriptorBindings(&module, &binding_count, bindings.ptrw());
+
+ ERR_FAIL_COND_V_MSG(result != SPV_REFLECT_RESULT_SUCCESS, FAILED,
+ "Reflection of SPIR-V shader stage '" + String(shader_stage_names[p_spirv[i].shader_stage]) + "' failed getting descriptor bindings.");
+
+ for (uint32_t j = 0; j < binding_count; j++) {
+ const SpvReflectDescriptorBinding &binding = *bindings[j];
+
+ SpirvReflectionData::Uniform info{};
+
+ 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: {
+ info.type = UNIFORM_TYPE_SAMPLER;
+ need_array_dimensions = true;
+ } break;
+ case SPV_REFLECT_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: {
+ info.type = UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
+ need_array_dimensions = true;
+ } break;
+ case SPV_REFLECT_DESCRIPTOR_TYPE_SAMPLED_IMAGE: {
+ info.type = UNIFORM_TYPE_TEXTURE;
+ need_array_dimensions = true;
+ } break;
+ 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;
+ need_array_dimensions = true;
+ } break;
+ 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;
+ need_block_size = true;
+ } break;
+ 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.");
+ continue;
+ } break;
+ case SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: {
+ ERR_PRINT("Dynamic storage buffer not supported.");
+ continue;
+ } break;
+ case SPV_REFLECT_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: {
+ info.type = UNIFORM_TYPE_INPUT_ATTACHMENT;
+ need_array_dimensions = true;
+ } break;
+ case SPV_REFLECT_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR: {
+ ERR_PRINT("Acceleration structure not supported.");
+ continue;
+ } break;
+ }
+
+ if (need_array_dimensions) {
+ if (binding.array.dims_count == 0) {
+ info.length = 1;
+ } else {
+ for (uint32_t k = 0; k < binding.array.dims_count; k++) {
+ if (k == 0) {
+ info.length = binding.array.dims[0];
+ } else {
+ info.length *= binding.array.dims[k];
+ }
+ }
+ }
+
+ } else if (need_block_size) {
+ info.length = binding.block.size;
+ } else {
+ info.length = 0;
+ }
+
+ 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;
+ }
+
+ info.binding = binding.binding;
+ uint32_t set = binding.set;
+
+ ERR_FAIL_COND_V_MSG(set >= MAX_UNIFORM_SETS, FAILED,
+ "On shader stage '" + String(shader_stage_names[stage]) + "', uniform '" + binding.name + "' uses a set (" + itos(set) + ") index larger than what is supported (" + itos(MAX_UNIFORM_SETS) + ").");
+
+ if (set < (uint32_t)r_reflection_data.uniforms.size()) {
+ // Check if this already exists.
+ bool exists = false;
+ for (int k = 0; k < r_reflection_data.uniforms[set].size(); k++) {
+ if (r_reflection_data.uniforms[set][k].binding == (uint32_t)info.binding) {
+ // Already exists, verify that it's the same type.
+ ERR_FAIL_COND_V_MSG(r_reflection_data.uniforms[set][k].type != info.type, FAILED,
+ "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 type.");
+
+ // Also, verify that it's the same size.
+ ERR_FAIL_COND_V_MSG(r_reflection_data.uniforms[set][k].length != info.length, FAILED,
+ "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(r_reflection_data.uniforms[set][k].writable != info.writable, FAILED,
+ "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.
+ r_reflection_data.uniforms.write[set].write[k].stages_mask.set_flag(stage_flag);
+ exists = true;
+ break;
+ }
+ }
+
+ if (exists) {
+ continue; // Merged.
+ }
+ }
+
+ info.stages_mask.set_flag(stage_flag);
+
+ if (set >= (uint32_t)r_reflection_data.uniforms.size()) {
+ r_reflection_data.uniforms.resize(set + 1);
+ }
+
+ r_reflection_data.uniforms.write[set].push_back(info);
+ }
+ }
+
+ {
+ // Specialization constants.
+
+ uint32_t sc_count = 0;
+ result = spvReflectEnumerateSpecializationConstants(&module, &sc_count, nullptr);
+ ERR_FAIL_COND_V_MSG(result != SPV_REFLECT_RESULT_SUCCESS, FAILED,
+ "Reflection of SPIR-V shader stage '" + String(shader_stage_names[p_spirv[i].shader_stage]) + "' failed enumerating specialization constants.");
+
+ if (sc_count) {
+ Vector<SpvReflectSpecializationConstant *> spec_constants;
+ spec_constants.resize(sc_count);
+
+ result = spvReflectEnumerateSpecializationConstants(&module, &sc_count, spec_constants.ptrw());
+ ERR_FAIL_COND_V_MSG(result != SPV_REFLECT_RESULT_SUCCESS, FAILED,
+ "Reflection of SPIR-V shader stage '" + String(shader_stage_names[p_spirv[i].shader_stage]) + "' failed obtaining specialization constants.");
+
+ for (uint32_t j = 0; j < sc_count; j++) {
+ int32_t existing = -1;
+ SpirvReflectionData::SpecializationConstant sconst{};
+ SpvReflectSpecializationConstant *spc = spec_constants[j];
+
+ sconst.constant_id = spc->constant_id;
+ sconst.int_value = 0; // Clear previous value JIC.
+ switch (spc->constant_type) {
+ case SPV_REFLECT_SPECIALIZATION_CONSTANT_BOOL: {
+ sconst.type = PIPELINE_SPECIALIZATION_CONSTANT_TYPE_BOOL;
+ sconst.bool_value = spc->default_value.int_bool_value != 0;
+ } break;
+ case SPV_REFLECT_SPECIALIZATION_CONSTANT_INT: {
+ sconst.type = PIPELINE_SPECIALIZATION_CONSTANT_TYPE_INT;
+ sconst.int_value = spc->default_value.int_bool_value;
+ } break;
+ case SPV_REFLECT_SPECIALIZATION_CONSTANT_FLOAT: {
+ sconst.type = PIPELINE_SPECIALIZATION_CONSTANT_TYPE_FLOAT;
+ sconst.float_value = spc->default_value.float_value;
+ } break;
+ }
+ sconst.stages_mask.set_flag(stage_flag);
+
+ for (int k = 0; k < r_reflection_data.specialization_constants.size(); k++) {
+ if (r_reflection_data.specialization_constants[k].constant_id == sconst.constant_id) {
+ ERR_FAIL_COND_V_MSG(r_reflection_data.specialization_constants[k].type != sconst.type, FAILED, "More than one specialization constant used for id (" + itos(sconst.constant_id) + "), but their types differ.");
+ ERR_FAIL_COND_V_MSG(r_reflection_data.specialization_constants[k].int_value != sconst.int_value, FAILED, "More than one specialization constant used for id (" + itos(sconst.constant_id) + "), but their default values differ.");
+ existing = k;
+ break;
+ }
+ }
+
+ if (existing > 0) {
+ r_reflection_data.specialization_constants.write[existing].stages_mask.set_flag(stage_flag);
+ } else {
+ r_reflection_data.specialization_constants.push_back(sconst);
+ }
+ }
+ }
+ }
+
+ if (stage == SHADER_STAGE_VERTEX) {
+ uint32_t iv_count = 0;
+ result = spvReflectEnumerateInputVariables(&module, &iv_count, nullptr);
+ ERR_FAIL_COND_V_MSG(result != SPV_REFLECT_RESULT_SUCCESS, FAILED,
+ "Reflection of SPIR-V shader stage '" + String(shader_stage_names[p_spirv[i].shader_stage]) + "' failed enumerating input variables.");
+
+ if (iv_count) {
+ Vector<SpvReflectInterfaceVariable *> input_vars;
+ input_vars.resize(iv_count);
+
+ result = spvReflectEnumerateInputVariables(&module, &iv_count, input_vars.ptrw());
+ ERR_FAIL_COND_V_MSG(result != SPV_REFLECT_RESULT_SUCCESS, FAILED,
+ "Reflection of SPIR-V shader stage '" + String(shader_stage_names[p_spirv[i].shader_stage]) + "' failed obtaining input variables.");
+
+ for (uint32_t j = 0; j < iv_count; j++) {
+ if (input_vars[j] && input_vars[j]->decoration_flags == 0) { // Regular input.
+ r_reflection_data.vertex_input_mask |= (1 << uint32_t(input_vars[j]->location));
+ }
+ }
+ }
+ }
+
+ if (stage == SHADER_STAGE_FRAGMENT) {
+ uint32_t ov_count = 0;
+ result = spvReflectEnumerateOutputVariables(&module, &ov_count, nullptr);
+ ERR_FAIL_COND_V_MSG(result != SPV_REFLECT_RESULT_SUCCESS, FAILED,
+ "Reflection of SPIR-V shader stage '" + String(shader_stage_names[p_spirv[i].shader_stage]) + "' failed enumerating output variables.");
+
+ if (ov_count) {
+ Vector<SpvReflectInterfaceVariable *> output_vars;
+ output_vars.resize(ov_count);
+
+ result = spvReflectEnumerateOutputVariables(&module, &ov_count, output_vars.ptrw());
+ ERR_FAIL_COND_V_MSG(result != SPV_REFLECT_RESULT_SUCCESS, FAILED,
+ "Reflection of SPIR-V shader stage '" + String(shader_stage_names[p_spirv[i].shader_stage]) + "' failed obtaining output variables.");
+
+ for (uint32_t j = 0; j < ov_count; j++) {
+ const SpvReflectInterfaceVariable *refvar = output_vars[j];
+ if (refvar != nullptr && refvar->built_in != SpvBuiltInFragDepth) {
+ r_reflection_data.fragment_output_mask |= 1 << refvar->location;
+ }
+ }
+ }
+ }
+
+ uint32_t pc_count = 0;
+ result = spvReflectEnumeratePushConstantBlocks(&module, &pc_count, nullptr);
+ ERR_FAIL_COND_V_MSG(result != SPV_REFLECT_RESULT_SUCCESS, FAILED,
+ "Reflection of SPIR-V shader stage '" + String(shader_stage_names[p_spirv[i].shader_stage]) + "' failed enumerating push constants.");
+
+ if (pc_count) {
+ ERR_FAIL_COND_V_MSG(pc_count > 1, FAILED,
+ "Reflection of SPIR-V shader stage '" + String(shader_stage_names[p_spirv[i].shader_stage]) + "': Only one push constant is supported, which should be the same across shader stages.");
+
+ Vector<SpvReflectBlockVariable *> pconstants;
+ pconstants.resize(pc_count);
+ result = spvReflectEnumeratePushConstantBlocks(&module, &pc_count, pconstants.ptrw());
+ ERR_FAIL_COND_V_MSG(result != SPV_REFLECT_RESULT_SUCCESS, FAILED,
+ "Reflection of SPIR-V shader stage '" + String(shader_stage_names[p_spirv[i].shader_stage]) + "' failed obtaining push constants.");
+#if 0
+ if (pconstants[0] == nullptr) {
+ Ref<FileAccess> f = FileAccess::open("res://popo.spv", FileAccess::WRITE);
+ f->store_buffer((const uint8_t *)&SpirV[0], SpirV.size() * sizeof(uint32_t));
+ }
+#endif
+
+ ERR_FAIL_COND_V_MSG(r_reflection_data.push_constant_size && r_reflection_data.push_constant_size != pconstants[0]->size, FAILED,
+ "Reflection of SPIR-V shader stage '" + String(shader_stage_names[p_spirv[i].shader_stage]) + "': Push constant block must be the same across shader stages.");
+
+ r_reflection_data.push_constant_size = pconstants[0]->size;
+ r_reflection_data.push_constant_stages_mask.set_flag(stage_flag);
+
+ //print_line("Stage: " + String(shader_stage_names[stage]) + " push constant of size=" + itos(push_constant.push_constant_size));
+ }
+
+ // Destroy the reflection data when no longer required.
+ spvReflectDestroyShaderModule(&module);
+ }
+
+ r_reflection_data.stages_mask.set_flag(stage_flag);
+ }
+
+ return OK;
+}
+
void RenderingDevice::_bind_methods() {
ClassDB::bind_method(D_METHOD("texture_create", "format", "view", "data"), &RenderingDevice::_texture_create, DEFVAL(Array()));
ClassDB::bind_method(D_METHOD("texture_create_shared", "view", "with_texture"), &RenderingDevice::_texture_create_shared);
ClassDB::bind_method(D_METHOD("texture_create_shared_from_slice", "view", "with_texture", "layer", "mipmap", "mipmaps", "slice_type"), &RenderingDevice::_texture_create_shared_from_slice, DEFVAL(1), DEFVAL(TEXTURE_SLICE_2D));
- ClassDB::bind_method(D_METHOD("texture_update", "texture", "layer", "data", "post_barrier"), &RenderingDevice::texture_update, DEFVAL(BARRIER_MASK_ALL));
+ ClassDB::bind_method(D_METHOD("texture_update", "texture", "layer", "data", "post_barrier"), &RenderingDevice::texture_update, DEFVAL(BARRIER_MASK_ALL_BARRIERS));
ClassDB::bind_method(D_METHOD("texture_get_data", "texture", "layer"), &RenderingDevice::texture_get_data);
ClassDB::bind_method(D_METHOD("texture_is_format_supported_for_usage", "format", "usage_flags"), &RenderingDevice::texture_is_format_supported_for_usage);
@@ -375,9 +708,9 @@ void RenderingDevice::_bind_methods() {
ClassDB::bind_method(D_METHOD("texture_is_shared", "texture"), &RenderingDevice::texture_is_shared);
ClassDB::bind_method(D_METHOD("texture_is_valid", "texture"), &RenderingDevice::texture_is_valid);
- ClassDB::bind_method(D_METHOD("texture_copy", "from_texture", "to_texture", "from_pos", "to_pos", "size", "src_mipmap", "dst_mipmap", "src_layer", "dst_layer", "post_barrier"), &RenderingDevice::texture_copy, DEFVAL(BARRIER_MASK_ALL));
- ClassDB::bind_method(D_METHOD("texture_clear", "texture", "color", "base_mipmap", "mipmap_count", "base_layer", "layer_count", "post_barrier"), &RenderingDevice::texture_clear, DEFVAL(BARRIER_MASK_ALL));
- ClassDB::bind_method(D_METHOD("texture_resolve_multisample", "from_texture", "to_texture", "post_barrier"), &RenderingDevice::texture_resolve_multisample, DEFVAL(BARRIER_MASK_ALL));
+ ClassDB::bind_method(D_METHOD("texture_copy", "from_texture", "to_texture", "from_pos", "to_pos", "size", "src_mipmap", "dst_mipmap", "src_layer", "dst_layer", "post_barrier"), &RenderingDevice::texture_copy, DEFVAL(BARRIER_MASK_ALL_BARRIERS));
+ ClassDB::bind_method(D_METHOD("texture_clear", "texture", "color", "base_mipmap", "mipmap_count", "base_layer", "layer_count", "post_barrier"), &RenderingDevice::texture_clear, DEFVAL(BARRIER_MASK_ALL_BARRIERS));
+ ClassDB::bind_method(D_METHOD("texture_resolve_multisample", "from_texture", "to_texture", "post_barrier"), &RenderingDevice::texture_resolve_multisample, DEFVAL(BARRIER_MASK_ALL_BARRIERS));
ClassDB::bind_method(D_METHOD("framebuffer_format_create", "attachments", "view_count"), &RenderingDevice::_framebuffer_format_create, DEFVAL(1));
ClassDB::bind_method(D_METHOD("framebuffer_format_create_multipass", "attachments", "passes", "view_count"), &RenderingDevice::_framebuffer_format_create_multipass, DEFVAL(1));
@@ -393,7 +726,7 @@ void RenderingDevice::_bind_methods() {
ClassDB::bind_method(D_METHOD("vertex_buffer_create", "size_bytes", "data", "use_as_storage"), &RenderingDevice::vertex_buffer_create, DEFVAL(Vector<uint8_t>()), DEFVAL(false));
ClassDB::bind_method(D_METHOD("vertex_format_create", "vertex_descriptions"), &RenderingDevice::_vertex_format_create);
- ClassDB::bind_method(D_METHOD("vertex_array_create", "vertex_count", "vertex_format", "src_buffers"), &RenderingDevice::_vertex_array_create);
+ ClassDB::bind_method(D_METHOD("vertex_array_create", "vertex_count", "vertex_format", "src_buffers", "offsets"), &RenderingDevice::_vertex_array_create, DEFVAL(Vector<int64_t>()));
ClassDB::bind_method(D_METHOD("index_buffer_create", "size_indices", "format", "data", "use_restart_indices"), &RenderingDevice::index_buffer_create, DEFVAL(Vector<uint8_t>()), DEFVAL(false));
ClassDB::bind_method(D_METHOD("index_array_create", "index_buffer", "index_offset", "index_count"), &RenderingDevice::index_array_create);
@@ -411,8 +744,8 @@ void RenderingDevice::_bind_methods() {
ClassDB::bind_method(D_METHOD("uniform_set_create", "uniforms", "shader", "shader_set"), &RenderingDevice::_uniform_set_create);
ClassDB::bind_method(D_METHOD("uniform_set_is_valid", "uniform_set"), &RenderingDevice::uniform_set_is_valid);
- ClassDB::bind_method(D_METHOD("buffer_update", "buffer", "offset", "size_bytes", "data", "post_barrier"), &RenderingDevice::_buffer_update, DEFVAL(BARRIER_MASK_ALL));
- ClassDB::bind_method(D_METHOD("buffer_clear", "buffer", "offset", "size_bytes", "post_barrier"), &RenderingDevice::buffer_clear, DEFVAL(BARRIER_MASK_ALL));
+ ClassDB::bind_method(D_METHOD("buffer_update", "buffer", "offset", "size_bytes", "data", "post_barrier"), &RenderingDevice::_buffer_update, DEFVAL(BARRIER_MASK_ALL_BARRIERS));
+ ClassDB::bind_method(D_METHOD("buffer_clear", "buffer", "offset", "size_bytes", "post_barrier"), &RenderingDevice::buffer_clear, DEFVAL(BARRIER_MASK_ALL_BARRIERS));
ClassDB::bind_method(D_METHOD("buffer_get_data", "buffer"), &RenderingDevice::buffer_get_data);
ClassDB::bind_method(D_METHOD("render_pipeline_create", "shader", "framebuffer_format", "vertex_format", "primitive", "rasterization_state", "multisample_state", "stencil_state", "color_blend_state", "dynamic_state_flags", "for_render_pass", "specialization_constants"), &RenderingDevice::_render_pipeline_create, DEFVAL(0), DEFVAL(0), DEFVAL(TypedArray<RDPipelineSpecializationConstant>()));
@@ -445,7 +778,7 @@ void RenderingDevice::_bind_methods() {
ClassDB::bind_method(D_METHOD("draw_list_switch_to_next_pass"), &RenderingDevice::draw_list_switch_to_next_pass);
ClassDB::bind_method(D_METHOD("draw_list_switch_to_next_pass_split", "splits"), &RenderingDevice::_draw_list_switch_to_next_pass_split);
- ClassDB::bind_method(D_METHOD("draw_list_end", "post_barrier"), &RenderingDevice::draw_list_end, DEFVAL(BARRIER_MASK_ALL));
+ ClassDB::bind_method(D_METHOD("draw_list_end", "post_barrier"), &RenderingDevice::draw_list_end, DEFVAL(BARRIER_MASK_ALL_BARRIERS));
ClassDB::bind_method(D_METHOD("compute_list_begin", "allow_draw_overlap"), &RenderingDevice::compute_list_begin, DEFVAL(false));
ClassDB::bind_method(D_METHOD("compute_list_bind_compute_pipeline", "compute_list", "compute_pipeline"), &RenderingDevice::compute_list_bind_compute_pipeline);
@@ -453,7 +786,7 @@ void RenderingDevice::_bind_methods() {
ClassDB::bind_method(D_METHOD("compute_list_bind_uniform_set", "compute_list", "uniform_set", "set_index"), &RenderingDevice::compute_list_bind_uniform_set);
ClassDB::bind_method(D_METHOD("compute_list_dispatch", "compute_list", "x_groups", "y_groups", "z_groups"), &RenderingDevice::compute_list_dispatch);
ClassDB::bind_method(D_METHOD("compute_list_add_barrier", "compute_list"), &RenderingDevice::compute_list_add_barrier);
- ClassDB::bind_method(D_METHOD("compute_list_end", "post_barrier"), &RenderingDevice::compute_list_end, DEFVAL(BARRIER_MASK_ALL));
+ ClassDB::bind_method(D_METHOD("compute_list_end", "post_barrier"), &RenderingDevice::compute_list_end, DEFVAL(BARRIER_MASK_ALL_BARRIERS));
ClassDB::bind_method(D_METHOD("free_rid", "rid"), &RenderingDevice::free);
@@ -469,7 +802,7 @@ void RenderingDevice::_bind_methods() {
ClassDB::bind_method(D_METHOD("submit"), &RenderingDevice::submit);
ClassDB::bind_method(D_METHOD("sync"), &RenderingDevice::sync);
- ClassDB::bind_method(D_METHOD("barrier", "from", "to"), &RenderingDevice::barrier, DEFVAL(BARRIER_MASK_ALL), DEFVAL(BARRIER_MASK_ALL));
+ ClassDB::bind_method(D_METHOD("barrier", "from", "to"), &RenderingDevice::barrier, DEFVAL(BARRIER_MASK_ALL_BARRIERS), DEFVAL(BARRIER_MASK_ALL_BARRIERS));
ClassDB::bind_method(D_METHOD("full_barrier"), &RenderingDevice::full_barrier);
ClassDB::bind_method(D_METHOD("create_local_device"), &RenderingDevice::create_local_device);
@@ -488,12 +821,6 @@ void RenderingDevice::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_driver_resource", "resource", "rid", "index"), &RenderingDevice::get_driver_resource);
- BIND_CONSTANT(BARRIER_MASK_RASTER);
- BIND_CONSTANT(BARRIER_MASK_COMPUTE);
- BIND_CONSTANT(BARRIER_MASK_TRANSFER);
- BIND_CONSTANT(BARRIER_MASK_ALL);
- BIND_CONSTANT(BARRIER_MASK_NO_BARRIER);
-
BIND_ENUM_CONSTANT(DEVICE_TYPE_OTHER);
BIND_ENUM_CONSTANT(DEVICE_TYPE_INTEGRATED_GPU);
BIND_ENUM_CONSTANT(DEVICE_TYPE_DISCRETE_GPU);
@@ -735,6 +1062,12 @@ void RenderingDevice::_bind_methods() {
BIND_ENUM_CONSTANT(DATA_FORMAT_G16_B16_R16_3PLANE_444_UNORM);
BIND_ENUM_CONSTANT(DATA_FORMAT_MAX);
+ BIND_BITFIELD_FLAG(BARRIER_MASK_RASTER);
+ BIND_BITFIELD_FLAG(BARRIER_MASK_COMPUTE);
+ BIND_BITFIELD_FLAG(BARRIER_MASK_TRANSFER);
+ BIND_BITFIELD_FLAG(BARRIER_MASK_ALL_BARRIERS);
+ BIND_BITFIELD_FLAG(BARRIER_MASK_NO_BARRIER);
+
BIND_ENUM_CONSTANT(TEXTURE_TYPE_1D);
BIND_ENUM_CONSTANT(TEXTURE_TYPE_2D);
BIND_ENUM_CONSTANT(TEXTURE_TYPE_3D);
@@ -753,16 +1086,16 @@ void RenderingDevice::_bind_methods() {
BIND_ENUM_CONSTANT(TEXTURE_SAMPLES_64);
BIND_ENUM_CONSTANT(TEXTURE_SAMPLES_MAX);
- BIND_ENUM_CONSTANT(TEXTURE_USAGE_SAMPLING_BIT);
- BIND_ENUM_CONSTANT(TEXTURE_USAGE_COLOR_ATTACHMENT_BIT);
- BIND_ENUM_CONSTANT(TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT);
- BIND_ENUM_CONSTANT(TEXTURE_USAGE_STORAGE_BIT);
- BIND_ENUM_CONSTANT(TEXTURE_USAGE_STORAGE_ATOMIC_BIT);
- BIND_ENUM_CONSTANT(TEXTURE_USAGE_CPU_READ_BIT);
- BIND_ENUM_CONSTANT(TEXTURE_USAGE_CAN_UPDATE_BIT);
- BIND_ENUM_CONSTANT(TEXTURE_USAGE_CAN_COPY_FROM_BIT);
- BIND_ENUM_CONSTANT(TEXTURE_USAGE_CAN_COPY_TO_BIT);
- BIND_ENUM_CONSTANT(TEXTURE_USAGE_INPUT_ATTACHMENT_BIT);
+ BIND_BITFIELD_FLAG(TEXTURE_USAGE_SAMPLING_BIT);
+ BIND_BITFIELD_FLAG(TEXTURE_USAGE_COLOR_ATTACHMENT_BIT);
+ BIND_BITFIELD_FLAG(TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT);
+ BIND_BITFIELD_FLAG(TEXTURE_USAGE_STORAGE_BIT);
+ BIND_BITFIELD_FLAG(TEXTURE_USAGE_STORAGE_ATOMIC_BIT);
+ BIND_BITFIELD_FLAG(TEXTURE_USAGE_CPU_READ_BIT);
+ BIND_BITFIELD_FLAG(TEXTURE_USAGE_CAN_UPDATE_BIT);
+ BIND_BITFIELD_FLAG(TEXTURE_USAGE_CAN_COPY_FROM_BIT);
+ BIND_BITFIELD_FLAG(TEXTURE_USAGE_CAN_COPY_TO_BIT);
+ BIND_BITFIELD_FLAG(TEXTURE_USAGE_INPUT_ATTACHMENT_BIT);
BIND_ENUM_CONSTANT(TEXTURE_SWIZZLE_IDENTITY);
BIND_ENUM_CONSTANT(TEXTURE_SWIZZLE_ZERO);
@@ -800,7 +1133,7 @@ void RenderingDevice::_bind_methods() {
BIND_ENUM_CONSTANT(INDEX_BUFFER_FORMAT_UINT16);
BIND_ENUM_CONSTANT(INDEX_BUFFER_FORMAT_UINT32);
- BIND_ENUM_CONSTANT(STORAGE_BUFFER_USAGE_DISPATCH_INDIRECT);
+ BIND_BITFIELD_FLAG(STORAGE_BUFFER_USAGE_DISPATCH_INDIRECT);
BIND_ENUM_CONSTANT(UNIFORM_TYPE_SAMPLER); //for sampling only (sampler GLSL type)
BIND_ENUM_CONSTANT(UNIFORM_TYPE_SAMPLER_WITH_TEXTURE); // for sampling only); but includes a texture); (samplerXX GLSL type)); first a sampler then a texture
@@ -900,13 +1233,13 @@ void RenderingDevice::_bind_methods() {
BIND_ENUM_CONSTANT(BLEND_OP_MAXIMUM);
BIND_ENUM_CONSTANT(BLEND_OP_MAX);
- BIND_ENUM_CONSTANT(DYNAMIC_STATE_LINE_WIDTH);
- BIND_ENUM_CONSTANT(DYNAMIC_STATE_DEPTH_BIAS);
- BIND_ENUM_CONSTANT(DYNAMIC_STATE_BLEND_CONSTANTS);
- BIND_ENUM_CONSTANT(DYNAMIC_STATE_DEPTH_BOUNDS);
- BIND_ENUM_CONSTANT(DYNAMIC_STATE_STENCIL_COMPARE_MASK);
- BIND_ENUM_CONSTANT(DYNAMIC_STATE_STENCIL_WRITE_MASK);
- BIND_ENUM_CONSTANT(DYNAMIC_STATE_STENCIL_REFERENCE);
+ BIND_BITFIELD_FLAG(DYNAMIC_STATE_LINE_WIDTH);
+ BIND_BITFIELD_FLAG(DYNAMIC_STATE_DEPTH_BIAS);
+ BIND_BITFIELD_FLAG(DYNAMIC_STATE_BLEND_CONSTANTS);
+ BIND_BITFIELD_FLAG(DYNAMIC_STATE_DEPTH_BOUNDS);
+ BIND_BITFIELD_FLAG(DYNAMIC_STATE_STENCIL_COMPARE_MASK);
+ BIND_BITFIELD_FLAG(DYNAMIC_STATE_STENCIL_WRITE_MASK);
+ BIND_BITFIELD_FLAG(DYNAMIC_STATE_STENCIL_REFERENCE);
BIND_ENUM_CONSTANT(INITIAL_ACTION_CLEAR); //start rendering and clear the framebuffer (supply params)
BIND_ENUM_CONSTANT(INITIAL_ACTION_CLEAR_REGION); //start rendering and clear the framebuffer (supply params)
diff --git a/servers/rendering/rendering_device.h b/servers/rendering/rendering_device.h
index d0b85d8220..0adc78894a 100644
--- a/servers/rendering/rendering_device.h
+++ b/servers/rendering/rendering_device.h
@@ -396,8 +396,8 @@ public:
BARRIER_MASK_RASTER = 1,
BARRIER_MASK_COMPUTE = 2,
BARRIER_MASK_TRANSFER = 4,
+ BARRIER_MASK_ALL_BARRIERS = BARRIER_MASK_RASTER | BARRIER_MASK_COMPUTE | BARRIER_MASK_TRANSFER, // 7
BARRIER_MASK_NO_BARRIER = 8,
- BARRIER_MASK_ALL = BARRIER_MASK_RASTER | BARRIER_MASK_COMPUTE | BARRIER_MASK_TRANSFER
};
/*****************/
@@ -532,17 +532,17 @@ public:
virtual RID texture_create_shared_from_slice(const TextureView &p_view, RID p_with_texture, uint32_t p_layer, uint32_t p_mipmap, uint32_t p_mipmaps = 1, TextureSliceType p_slice_type = TEXTURE_SLICE_2D) = 0;
- virtual Error texture_update(RID p_texture, uint32_t p_layer, const Vector<uint8_t> &p_data, uint32_t p_post_barrier = BARRIER_MASK_ALL) = 0;
+ virtual Error texture_update(RID p_texture, uint32_t p_layer, const Vector<uint8_t> &p_data, BitField<BarrierMask> p_post_barrier = BARRIER_MASK_ALL_BARRIERS) = 0;
virtual Vector<uint8_t> texture_get_data(RID p_texture, uint32_t p_layer) = 0; // CPU textures will return immediately, while GPU textures will most likely force a flush
- virtual bool texture_is_format_supported_for_usage(DataFormat p_format, uint32_t p_usage) const = 0;
+ virtual bool texture_is_format_supported_for_usage(DataFormat p_format, BitField<RenderingDevice::TextureUsageBits> p_usage) const = 0;
virtual bool texture_is_shared(RID p_texture) = 0;
virtual bool texture_is_valid(RID p_texture) = 0;
virtual Size2i texture_size(RID p_texture) = 0;
- virtual Error texture_copy(RID p_from_texture, RID p_to_texture, const Vector3 &p_from, const Vector3 &p_to, const Vector3 &p_size, uint32_t p_src_mipmap, uint32_t p_dst_mipmap, uint32_t p_src_layer, uint32_t p_dst_layer, uint32_t p_post_barrier = BARRIER_MASK_ALL) = 0;
- virtual Error texture_clear(RID p_texture, const Color &p_color, uint32_t p_base_mipmap, uint32_t p_mipmaps, uint32_t p_base_layer, uint32_t p_layers, uint32_t p_post_barrier = BARRIER_MASK_ALL) = 0;
- virtual Error texture_resolve_multisample(RID p_from_texture, RID p_to_texture, uint32_t p_post_barrier = BARRIER_MASK_ALL) = 0;
+ virtual Error texture_copy(RID p_from_texture, RID p_to_texture, const Vector3 &p_from, const Vector3 &p_to, const Vector3 &p_size, uint32_t p_src_mipmap, uint32_t p_dst_mipmap, uint32_t p_src_layer, uint32_t p_dst_layer, BitField<BarrierMask> p_post_barrier = BARRIER_MASK_ALL_BARRIERS) = 0;
+ virtual Error texture_clear(RID p_texture, const Color &p_color, uint32_t p_base_mipmap, uint32_t p_mipmaps, uint32_t p_base_layer, uint32_t p_layers, BitField<BarrierMask> p_post_barrier = BARRIER_MASK_ALL_BARRIERS) = 0;
+ virtual Error texture_resolve_multisample(RID p_from_texture, RID p_to_texture, BitField<BarrierMask> p_post_barrier = BARRIER_MASK_ALL_BARRIERS) = 0;
/*********************/
/**** FRAMEBUFFER ****/
@@ -683,7 +683,7 @@ public:
// This ID is warranted to be unique for the same formats, does not need to be freed
virtual VertexFormatID vertex_format_create(const Vector<VertexAttribute> &p_vertex_formats) = 0;
- virtual RID vertex_array_create(uint32_t p_vertex_count, VertexFormatID p_vertex_format, const Vector<RID> &p_src_buffers) = 0;
+ virtual RID vertex_array_create(uint32_t p_vertex_count, VertexFormatID p_vertex_format, const Vector<RID> &p_src_buffers, const Vector<uint64_t> &p_offsets = Vector<uint64_t>()) = 0;
enum IndexBufferFormat {
INDEX_BUFFER_FORMAT_UINT16,
@@ -749,11 +749,11 @@ public:
};
enum StorageBufferUsage {
- STORAGE_BUFFER_USAGE_DISPATCH_INDIRECT = 1
+ STORAGE_BUFFER_USAGE_DISPATCH_INDIRECT = 1,
};
virtual RID uniform_buffer_create(uint32_t p_size_bytes, const Vector<uint8_t> &p_data = Vector<uint8_t>()) = 0;
- virtual RID storage_buffer_create(uint32_t p_size, const Vector<uint8_t> &p_data = Vector<uint8_t>(), uint32_t p_usage = 0) = 0;
+ virtual RID storage_buffer_create(uint32_t p_size, const Vector<uint8_t> &p_data = Vector<uint8_t>(), BitField<StorageBufferUsage> p_usage = 0) = 0;
virtual RID texture_buffer_create(uint32_t p_size_elements, DataFormat p_format, const Vector<uint8_t> &p_data = Vector<uint8_t>()) = 0;
struct Uniform {
@@ -826,8 +826,8 @@ public:
virtual bool uniform_set_is_valid(RID p_uniform_set) = 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;
+ virtual Error buffer_update(RID p_buffer, uint32_t p_offset, uint32_t p_size, const void *p_data, BitField<BarrierMask> p_post_barrier = BARRIER_MASK_ALL_BARRIERS) = 0;
+ virtual Error buffer_clear(RID p_buffer, uint32_t p_offset, uint32_t p_size, BitField<BarrierMask> p_post_barrier = BARRIER_MASK_ALL_BARRIERS) = 0;
virtual Vector<uint8_t> buffer_get_data(RID p_buffer) = 0; //this causes stall, only use to retrieve large buffers for saving
/******************************************/
@@ -1112,7 +1112,7 @@ public:
};
virtual bool render_pipeline_is_valid(RID p_pipeline) = 0;
- virtual RID render_pipeline_create(RID p_shader, FramebufferFormatID p_framebuffer_format, VertexFormatID p_vertex_format, RenderPrimitive p_render_primitive, const PipelineRasterizationState &p_rasterization_state, const PipelineMultisampleState &p_multisample_state, const PipelineDepthStencilState &p_depth_stencil_state, const PipelineColorBlendState &p_blend_state, int p_dynamic_state_flags = 0, uint32_t p_for_render_pass = 0, const Vector<PipelineSpecializationConstant> &p_specialization_constants = Vector<PipelineSpecializationConstant>()) = 0;
+ virtual RID render_pipeline_create(RID p_shader, FramebufferFormatID p_framebuffer_format, VertexFormatID p_vertex_format, RenderPrimitive p_render_primitive, const PipelineRasterizationState &p_rasterization_state, const PipelineMultisampleState &p_multisample_state, const PipelineDepthStencilState &p_depth_stencil_state, const PipelineColorBlendState &p_blend_state, BitField<PipelineDynamicStateFlags> p_dynamic_state_flags = 0, uint32_t p_for_render_pass = 0, const Vector<PipelineSpecializationConstant> &p_specialization_constants = Vector<PipelineSpecializationConstant>()) = 0;
/**************************/
/**** COMPUTE PIPELINE ****/
@@ -1173,7 +1173,7 @@ public:
virtual DrawListID draw_list_switch_to_next_pass() = 0;
virtual Error draw_list_switch_to_next_pass_split(uint32_t p_splits, DrawListID *r_split_ids) = 0;
- virtual void draw_list_end(uint32_t p_post_barrier = BARRIER_MASK_ALL) = 0;
+ virtual void draw_list_end(BitField<BarrierMask> p_post_barrier = BARRIER_MASK_ALL_BARRIERS) = 0;
/***********************/
/**** COMPUTE LISTS ****/
@@ -1190,9 +1190,9 @@ public:
virtual void compute_list_dispatch_indirect(ComputeListID p_list, RID p_buffer, uint32_t p_offset) = 0;
virtual void compute_list_add_barrier(ComputeListID p_list) = 0;
- virtual void compute_list_end(uint32_t p_post_barrier = BARRIER_MASK_ALL) = 0;
+ virtual void compute_list_end(BitField<BarrierMask> p_post_barrier = BARRIER_MASK_ALL_BARRIERS) = 0;
- virtual void barrier(uint32_t p_from = BARRIER_MASK_ALL, uint32_t p_to = BARRIER_MASK_ALL) = 0;
+ virtual void barrier(BitField<BarrierMask> p_from = BARRIER_MASK_ALL_BARRIERS, BitField<BarrierMask> p_to = BARRIER_MASK_ALL_BARRIERS) = 0;
virtual void full_barrier() = 0;
/***************/
@@ -1257,6 +1257,8 @@ public:
LIMIT_SUBGROUP_SIZE,
LIMIT_SUBGROUP_IN_SHADERS, // Set flags using SHADER_STAGE_VERTEX_BIT, SHADER_STAGE_FRAGMENT_BIT, etc.
LIMIT_SUBGROUP_OPERATIONS,
+ LIMIT_VRS_TEXEL_WIDTH,
+ LIMIT_VRS_TEXEL_HEIGHT,
};
virtual uint64_t limit_get(Limit p_limit) const = 0;
@@ -1299,6 +1301,10 @@ public:
RenderingDevice();
protected:
+ static const char *shader_stage_names[RenderingDevice::SHADER_STAGE_MAX];
+
+ static const uint32_t MAX_UNIFORM_SETS = 16;
+
//binders to script API
RID _texture_create(const Ref<RDTextureFormat> &p_format, const Ref<RDTextureView> &p_view, const TypedArray<PackedByteArray> &p_data = Array());
RID _texture_create_shared(const Ref<RDTextureView> &p_view, RID p_with_texture);
@@ -1310,7 +1316,7 @@ protected:
RID _framebuffer_create_multipass(const TypedArray<RID> &p_textures, const TypedArray<RDFramebufferPass> &p_passes, FramebufferFormatID p_format_check = INVALID_ID, uint32_t p_view_count = 1);
RID _sampler_create(const Ref<RDSamplerState> &p_state);
VertexFormatID _vertex_format_create(const TypedArray<RDVertexAttribute> &p_vertex_formats);
- RID _vertex_array_create(uint32_t p_vertex_count, VertexFormatID p_vertex_format, const TypedArray<RID> &p_src_buffers);
+ RID _vertex_array_create(uint32_t p_vertex_count, VertexFormatID p_vertex_format, const TypedArray<RID> &p_src_buffers, const Vector<int64_t> &p_offsets = Vector<int64_t>());
Ref<RDShaderSPIRV> _shader_compile_spirv_from_source(const Ref<RDShaderSource> &p_source, bool p_allow_cache = true);
Vector<uint8_t> _shader_compile_binary_from_spirv(const Ref<RDShaderSPIRV> &p_bytecode, const String &p_shader_name = "");
@@ -1318,15 +1324,48 @@ protected:
RID _uniform_set_create(const TypedArray<RDUniform> &p_uniforms, RID p_shader, uint32_t p_shader_set);
- Error _buffer_update(RID p_buffer, uint32_t p_offset, uint32_t p_size, const Vector<uint8_t> &p_data, uint32_t p_post_barrier = BARRIER_MASK_ALL);
+ Error _buffer_update(RID p_buffer, uint32_t p_offset, uint32_t p_size, const Vector<uint8_t> &p_data, BitField<BarrierMask> p_post_barrier = BARRIER_MASK_ALL_BARRIERS);
- RID _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);
+ RID _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, BitField<PipelineDynamicStateFlags> p_dynamic_state_flags, uint32_t p_for_render_pass, const TypedArray<RDPipelineSpecializationConstant> &p_specialization_constants);
RID _compute_pipeline_create(RID p_shader, const TypedArray<RDPipelineSpecializationConstant> &p_specialization_constants);
Vector<int64_t> _draw_list_begin_split(RID p_framebuffer, uint32_t p_splits, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2(), const TypedArray<RID> &p_storage_textures = TypedArray<RID>());
void _draw_list_set_push_constant(DrawListID p_list, const Vector<uint8_t> &p_data, uint32_t p_data_size);
void _compute_list_set_push_constant(ComputeListID p_list, const Vector<uint8_t> &p_data, uint32_t p_data_size);
Vector<int64_t> _draw_list_switch_to_next_pass_split(uint32_t p_splits);
+
+ struct SpirvReflectionData {
+ BitField<ShaderStage> stages_mask;
+ uint32_t vertex_input_mask;
+ uint32_t fragment_output_mask;
+ bool is_compute;
+ uint32_t compute_local_size[3];
+ uint32_t push_constant_size;
+ BitField<ShaderStage> push_constant_stages_mask;
+
+ struct Uniform {
+ UniformType type;
+ uint32_t binding;
+ BitField<ShaderStage> stages_mask;
+ uint32_t length; // Size of arrays (in total elements), or ubos (in bytes * total elements).
+ bool writable;
+ };
+ Vector<Vector<Uniform>> uniforms;
+
+ struct SpecializationConstant {
+ PipelineSpecializationConstantType type;
+ uint32_t constant_id;
+ union {
+ uint32_t int_value;
+ float float_value;
+ bool bool_value;
+ };
+ BitField<ShaderStage> stages_mask;
+ };
+ Vector<SpecializationConstant> specialization_constants;
+ };
+
+ Error _reflect_spirv(const Vector<ShaderStageSPIRVData> &p_spirv, SpirvReflectionData &r_reflection_data);
};
VARIANT_ENUM_CAST(RenderingDevice::DeviceType)
@@ -1335,9 +1374,10 @@ VARIANT_ENUM_CAST(RenderingDevice::ShaderStage)
VARIANT_ENUM_CAST(RenderingDevice::ShaderLanguage)
VARIANT_ENUM_CAST(RenderingDevice::CompareOperator)
VARIANT_ENUM_CAST(RenderingDevice::DataFormat)
+VARIANT_BITFIELD_CAST(RenderingDevice::BarrierMask);
VARIANT_ENUM_CAST(RenderingDevice::TextureType)
VARIANT_ENUM_CAST(RenderingDevice::TextureSamples)
-VARIANT_ENUM_CAST(RenderingDevice::TextureUsageBits)
+VARIANT_BITFIELD_CAST(RenderingDevice::TextureUsageBits)
VARIANT_ENUM_CAST(RenderingDevice::TextureSwizzle)
VARIANT_ENUM_CAST(RenderingDevice::TextureSliceType)
VARIANT_ENUM_CAST(RenderingDevice::SamplerFilter)
@@ -1345,7 +1385,7 @@ VARIANT_ENUM_CAST(RenderingDevice::SamplerRepeatMode)
VARIANT_ENUM_CAST(RenderingDevice::SamplerBorderColor)
VARIANT_ENUM_CAST(RenderingDevice::VertexFrequency)
VARIANT_ENUM_CAST(RenderingDevice::IndexBufferFormat)
-VARIANT_ENUM_CAST(RenderingDevice::StorageBufferUsage)
+VARIANT_BITFIELD_CAST(RenderingDevice::StorageBufferUsage)
VARIANT_ENUM_CAST(RenderingDevice::UniformType)
VARIANT_ENUM_CAST(RenderingDevice::RenderPrimitive)
VARIANT_ENUM_CAST(RenderingDevice::PolygonCullMode)
@@ -1354,7 +1394,7 @@ VARIANT_ENUM_CAST(RenderingDevice::StencilOperation)
VARIANT_ENUM_CAST(RenderingDevice::LogicOperation)
VARIANT_ENUM_CAST(RenderingDevice::BlendFactor)
VARIANT_ENUM_CAST(RenderingDevice::BlendOperation)
-VARIANT_ENUM_CAST(RenderingDevice::PipelineDynamicStateFlags)
+VARIANT_BITFIELD_CAST(RenderingDevice::PipelineDynamicStateFlags)
VARIANT_ENUM_CAST(RenderingDevice::PipelineSpecializationConstantType)
VARIANT_ENUM_CAST(RenderingDevice::InitialAction)
VARIANT_ENUM_CAST(RenderingDevice::FinalAction)
diff --git a/servers/rendering/rendering_device_binds.h b/servers/rendering/rendering_device_binds.h
index c710bd0a10..dbff305794 100644
--- a/servers/rendering/rendering_device_binds.h
+++ b/servers/rendering/rendering_device_binds.h
@@ -66,7 +66,7 @@ public:
RD_SETGET(uint32_t, mipmaps)
RD_SETGET(RD::TextureType, texture_type)
RD_SETGET(RD::TextureSamples, samples)
- RD_SETGET(uint32_t, usage_bits)
+ RD_SETGET(BitField<RenderingDevice::TextureUsageBits>, usage_bits)
void add_shareable_format(RD::DataFormat p_format) { base.shareable_formats.push_back(p_format); }
void remove_shareable_format(RD::DataFormat p_format) { base.shareable_formats.erase(p_format); }
diff --git a/servers/rendering/rendering_method.h b/servers/rendering/rendering_method.h
index c4d9e25ecd..e3f29b51d5 100644
--- a/servers/rendering/rendering_method.h
+++ b/servers/rendering/rendering_method.h
@@ -72,6 +72,7 @@ public:
virtual void instance_set_base(RID p_instance, RID p_base) = 0;
virtual void instance_set_scenario(RID p_instance, RID p_scenario) = 0;
virtual void instance_set_layer_mask(RID p_instance, uint32_t p_mask) = 0;
+ virtual void instance_set_pivot_data(RID p_instance, float p_sorting_offset, bool p_use_aabb_center) = 0;
virtual void instance_set_transform(RID p_instance, const Transform3D &p_transform) = 0;
virtual void instance_attach_object_instance_id(RID p_instance, ObjectID p_id) = 0;
virtual void instance_set_blend_shape_weight(RID p_instance, int p_shape, float p_weight) = 0;
@@ -203,7 +204,6 @@ public:
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
diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h
index b77b95bb62..3f5b135d2a 100644
--- a/servers/rendering/rendering_server_default.h
+++ b/servers/rendering/rendering_server_default.h
@@ -698,7 +698,6 @@ public:
FUNC13(environment_set_glow, RID, bool, Vector<float>, float, float, float, float, EnvironmentGlowBlendMode, float, float, float, float, RID)
FUNC1(environment_glow_set_use_bicubic_upscale, bool)
- FUNC1(environment_glow_set_use_high_quality, bool)
FUNC4(environment_set_tonemap, RID, EnvironmentToneMapper, float, float)
@@ -763,6 +762,7 @@ public:
FUNC2(instance_set_base, RID, RID)
FUNC2(instance_set_scenario, RID, RID)
FUNC2(instance_set_layer_mask, RID, uint32_t)
+ FUNC3(instance_set_pivot_data, RID, float, bool)
FUNC2(instance_set_transform, RID, const Transform3D &)
FUNC2(instance_attach_object_instance_id, RID, ObjectID)
FUNC3(instance_set_blend_shape_weight, RID, int, float)
@@ -851,7 +851,7 @@ public:
FUNC4(canvas_item_add_circle, RID, const Point2 &, float, const Color &)
FUNC6(canvas_item_add_texture_rect, RID, const Rect2 &, RID, bool, const Color &, bool)
FUNC7(canvas_item_add_texture_rect_region, RID, const Rect2 &, RID, const Rect2 &, const Color &, bool, bool)
- FUNC7(canvas_item_add_msdf_texture_rect_region, RID, const Rect2 &, RID, const Rect2 &, const Color &, int, float)
+ FUNC8(canvas_item_add_msdf_texture_rect_region, RID, const Rect2 &, RID, const Rect2 &, const Color &, int, float, float)
FUNC5(canvas_item_add_lcd_texture_rect_region, RID, const Rect2 &, RID, const Rect2 &, const Color &)
FUNC10(canvas_item_add_nine_patch, RID, const Rect2 &, const Rect2 &, RID, const Vector2 &, const Vector2 &, NinePatchAxisMode, NinePatchAxisMode, bool, const Color &)
FUNC6(canvas_item_add_primitive, RID, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID, float)
diff --git a/servers/rendering/shader_compiler.cpp b/servers/rendering/shader_compiler.cpp
index fc644fcae6..00b6a8c44c 100644
--- a/servers/rendering/shader_compiler.cpp
+++ b/servers/rendering/shader_compiler.cpp
@@ -134,6 +134,8 @@ static String _interpstr(SL::DataInterpolation p_interp) {
return "flat ";
case SL::INTERPOLATION_SMOOTH:
return "";
+ case SL::INTERPOLATION_DEFAULT:
+ return "";
}
return "";
}
@@ -667,6 +669,9 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
fragment_varyings.insert(varying_name);
continue;
}
+ if (varying.type < SL::TYPE_INT) {
+ continue; // Ignore boolean types to prevent crashing (if varying is just declared).
+ }
String vcode;
String interp_mode = _interpstr(varying.interpolation);
@@ -1141,8 +1146,18 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
case SL::OP_STRUCT:
case SL::OP_CONSTRUCT: {
ERR_FAIL_COND_V(onode->arguments[0]->type != SL::Node::TYPE_VARIABLE, String());
-
- SL::VariableNode *vnode = (SL::VariableNode *)onode->arguments[0];
+ const SL::VariableNode *vnode = static_cast<const SL::VariableNode *>(onode->arguments[0]);
+ const SL::FunctionNode *func = nullptr;
+ const bool is_internal_func = internal_functions.has(vnode->name);
+
+ if (!is_internal_func) {
+ for (int i = 0; i < shader->functions.size(); i++) {
+ if (shader->functions[i].name == vnode->name) {
+ func = shader->functions[i].function;
+ break;
+ }
+ }
+ }
bool is_texture_func = false;
bool is_screen_texture = false;
@@ -1156,7 +1171,7 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
used_flag_pointers.insert(vnode->name);
}
- if (internal_functions.has(vnode->name)) {
+ if (is_internal_func) {
code += vnode->name;
is_texture_func = texture_functions.has(vnode->name);
} else if (p_default_actions.renames.has(vnode->name)) {
@@ -1172,6 +1187,44 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
if (i > 1) {
code += ", ";
}
+
+ bool is_out_qualifier = false;
+ if (is_internal_func) {
+ is_out_qualifier = SL::is_builtin_func_out_parameter(vnode->name, i - 1);
+ } else if (func != nullptr) {
+ const SL::ArgumentQualifier qualifier = func->arguments[i - 1].qualifier;
+ is_out_qualifier = qualifier == SL::ARGUMENT_QUALIFIER_OUT || qualifier == SL::ARGUMENT_QUALIFIER_INOUT;
+ }
+
+ if (is_out_qualifier) {
+ StringName name;
+ bool found = false;
+ {
+ const SL::Node *node = onode->arguments[i];
+
+ bool done = false;
+ do {
+ switch (node->type) {
+ case SL::Node::TYPE_VARIABLE: {
+ name = static_cast<const SL::VariableNode *>(node)->name;
+ done = true;
+ found = true;
+ } break;
+ case SL::Node::TYPE_MEMBER: {
+ node = static_cast<const SL::MemberNode *>(node)->owner;
+ } break;
+ default: {
+ done = true;
+ } break;
+ }
+ } while (!done);
+ }
+
+ if (found && p_actions.write_flag_pointers.has(name)) {
+ *p_actions.write_flag_pointers[name] = true;
+ }
+ }
+
String node_code = _dump_node_code(onode->arguments[i], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
if (!RS::get_singleton()->is_low_end() && is_texture_func && i == 1) {
//need to map from texture to sampler in order to sample when using Vulkan GLSL
@@ -1239,7 +1292,7 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
}
code += ")";
if (is_screen_texture && actions.apply_luminance_multiplier) {
- code = "(" + code + " / vec4(vec3(sc_luminance_multiplier), 1.0))";
+ code = "(" + code + " * vec4(vec3(sc_luminance_multiplier), 1.0))";
}
} break;
case SL::OP_INDEX: {
diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp
index 14c09c1512..8c732b3d5a 100644
--- a/servers/rendering/shader_language.cpp
+++ b/servers/rendering/shader_language.cpp
@@ -989,6 +989,18 @@ String ShaderLanguage::get_precision_name(DataPrecision p_type) {
return "";
}
+String ShaderLanguage::get_interpolation_name(DataInterpolation p_interpolation) {
+ switch (p_interpolation) {
+ case INTERPOLATION_FLAT:
+ return "flat";
+ case INTERPOLATION_SMOOTH:
+ return "smooth";
+ default:
+ break;
+ }
+ return "";
+}
+
String ShaderLanguage::get_datatype_name(DataType p_type) {
switch (p_type) {
case TYPE_VOID:
@@ -3645,7 +3657,7 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C
switch (p_type) {
case ShaderLanguage::TYPE_BOOL:
if (array_size > 0) {
- PackedInt32Array array = PackedInt32Array();
+ PackedInt32Array array;
for (int i = 0; i < array_size; i++) {
array.push_back(p_value[i].boolean);
}
@@ -3658,7 +3670,7 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C
array_size *= 2;
if (array_size > 0) {
- PackedInt32Array array = PackedInt32Array();
+ PackedInt32Array array;
for (int i = 0; i < array_size; i++) {
array.push_back(p_value[i].boolean);
}
@@ -3671,7 +3683,7 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C
array_size *= 3;
if (array_size > 0) {
- PackedInt32Array array = PackedInt32Array();
+ PackedInt32Array array;
for (int i = 0; i < array_size; i++) {
array.push_back(p_value[i].boolean);
}
@@ -3684,7 +3696,7 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C
array_size *= 4;
if (array_size > 0) {
- PackedInt32Array array = PackedInt32Array();
+ PackedInt32Array array;
for (int i = 0; i < array_size; i++) {
array.push_back(p_value[i].boolean);
}
@@ -3695,7 +3707,7 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C
break;
case ShaderLanguage::TYPE_INT:
if (array_size > 0) {
- PackedInt32Array array = PackedInt32Array();
+ PackedInt32Array array;
for (int i = 0; i < array_size; i++) {
array.push_back(p_value[i].sint);
}
@@ -3708,7 +3720,7 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C
if (array_size > 0) {
array_size *= 2;
- PackedInt32Array array = PackedInt32Array();
+ PackedInt32Array array;
for (int i = 0; i < array_size; i++) {
array.push_back(p_value[i].sint);
}
@@ -3721,7 +3733,7 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C
if (array_size > 0) {
array_size *= 3;
- PackedInt32Array array = PackedInt32Array();
+ PackedInt32Array array;
for (int i = 0; i < array_size; i++) {
array.push_back(p_value[i].sint);
}
@@ -3734,7 +3746,7 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C
if (array_size > 0) {
array_size *= 4;
- PackedInt32Array array = PackedInt32Array();
+ PackedInt32Array array;
for (int i = 0; i < array_size; i++) {
array.push_back(p_value[i].sint);
}
@@ -3745,7 +3757,7 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C
break;
case ShaderLanguage::TYPE_UINT:
if (array_size > 0) {
- PackedInt32Array array = PackedInt32Array();
+ PackedInt32Array array;
for (int i = 0; i < array_size; i++) {
array.push_back(p_value[i].uint);
}
@@ -3758,7 +3770,7 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C
if (array_size > 0) {
array_size *= 2;
- PackedInt32Array array = PackedInt32Array();
+ PackedInt32Array array;
for (int i = 0; i < array_size; i++) {
array.push_back(p_value[i].uint);
}
@@ -3771,7 +3783,7 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C
if (array_size > 0) {
array_size *= 3;
- PackedInt32Array array = PackedInt32Array();
+ PackedInt32Array array;
for (int i = 0; i < array_size; i++) {
array.push_back(p_value[i].uint);
}
@@ -3784,7 +3796,7 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C
if (array_size > 0) {
array_size *= 4;
- PackedInt32Array array = PackedInt32Array();
+ PackedInt32Array array;
for (int i = 0; i < array_size; i++) {
array.push_back(p_value[i].uint);
}
@@ -3795,7 +3807,7 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C
break;
case ShaderLanguage::TYPE_FLOAT:
if (array_size > 0) {
- PackedFloat32Array array = PackedFloat32Array();
+ PackedFloat32Array array;
for (int i = 0; i < array_size; i++) {
array.push_back(p_value[i].real);
}
@@ -3808,7 +3820,7 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C
if (array_size > 0) {
array_size *= 2;
- PackedVector2Array array = PackedVector2Array();
+ PackedVector2Array array;
for (int i = 0; i < array_size; i += 2) {
array.push_back(Vector2(p_value[i].real, p_value[i + 1].real));
}
@@ -3822,13 +3834,13 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C
array_size *= 3;
if (p_hint == ShaderLanguage::ShaderNode::Uniform::HINT_SOURCE_COLOR) {
- PackedColorArray array = PackedColorArray();
+ PackedColorArray array;
for (int i = 0; i < array_size; i += 3) {
array.push_back(Color(p_value[i].real, p_value[i + 1].real, p_value[i + 2].real));
}
value = Variant(array);
} else {
- PackedVector3Array array = PackedVector3Array();
+ PackedVector3Array array;
for (int i = 0; i < array_size; i += 3) {
array.push_back(Vector3(p_value[i].real, p_value[i + 1].real, p_value[i + 2].real));
}
@@ -3847,13 +3859,13 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C
array_size *= 4;
if (p_hint == ShaderLanguage::ShaderNode::Uniform::HINT_SOURCE_COLOR) {
- PackedColorArray array = PackedColorArray();
+ PackedColorArray array;
for (int i = 0; i < array_size; i += 4) {
array.push_back(Color(p_value[i].real, p_value[i + 1].real, p_value[i + 2].real, p_value[i + 3].real));
}
value = Variant(array);
} else {
- PackedFloat32Array array = PackedFloat32Array();
+ PackedFloat32Array array;
for (int i = 0; i < array_size; i += 4) {
array.push_back(p_value[i].real);
array.push_back(p_value[i + 1].real);
@@ -3874,7 +3886,7 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C
if (array_size > 0) {
array_size *= 4;
- PackedFloat32Array array = PackedFloat32Array();
+ PackedFloat32Array array;
for (int i = 0; i < array_size; i += 4) {
array.push_back(p_value[i].real);
array.push_back(p_value[i + 1].real);
@@ -3890,7 +3902,7 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C
if (array_size > 0) {
array_size *= 9;
- PackedFloat32Array array = PackedFloat32Array();
+ PackedFloat32Array array;
for (int i = 0; i < array_size; i += 9) {
for (int j = 0; j < 9; j++) {
array.push_back(p_value[i + j].real);
@@ -3916,7 +3928,7 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C
if (array_size > 0) {
array_size *= 16;
- PackedFloat32Array array = PackedFloat32Array();
+ PackedFloat32Array array;
for (int i = 0; i < array_size; i += 16) {
for (int j = 0; j < 16; j++) {
array.push_back(p_value[i + j].real);
@@ -4110,43 +4122,41 @@ PropertyInfo ShaderLanguage::uniform_to_property_info(const ShaderNode::Uniform
case ShaderLanguage::TYPE_USAMPLER2D: {
if (p_uniform.array_size > 0) {
pi.type = Variant::ARRAY;
+ pi.hint = PROPERTY_HINT_ARRAY_TYPE;
+ pi.hint_string = MAKE_RESOURCE_TYPE_HINT("Texture2D");
} else {
pi.type = Variant::OBJECT;
+ pi.hint = PROPERTY_HINT_RESOURCE_TYPE;
+ pi.hint_string = "Texture2D";
}
- pi.hint = PROPERTY_HINT_RESOURCE_TYPE;
- pi.hint_string = "Texture2D";
} break;
case ShaderLanguage::TYPE_SAMPLER2DARRAY:
case ShaderLanguage::TYPE_ISAMPLER2DARRAY:
- case ShaderLanguage::TYPE_USAMPLER2DARRAY: {
+ case ShaderLanguage::TYPE_USAMPLER2DARRAY:
+ case ShaderLanguage::TYPE_SAMPLERCUBE:
+ case ShaderLanguage::TYPE_SAMPLERCUBEARRAY: {
if (p_uniform.array_size > 0) {
pi.type = Variant::ARRAY;
+ pi.hint = PROPERTY_HINT_ARRAY_TYPE;
+ pi.hint_string = MAKE_RESOURCE_TYPE_HINT("TextureLayered");
} else {
pi.type = Variant::OBJECT;
+ pi.hint = PROPERTY_HINT_RESOURCE_TYPE;
+ pi.hint_string = "TextureLayered";
}
- pi.hint = PROPERTY_HINT_RESOURCE_TYPE;
- pi.hint_string = "TextureLayered";
} break;
case ShaderLanguage::TYPE_SAMPLER3D:
case ShaderLanguage::TYPE_ISAMPLER3D:
case ShaderLanguage::TYPE_USAMPLER3D: {
if (p_uniform.array_size > 0) {
pi.type = Variant::ARRAY;
+ pi.hint = PROPERTY_HINT_ARRAY_TYPE;
+ pi.hint_string = MAKE_RESOURCE_TYPE_HINT("Texture3D");
} else {
pi.type = Variant::OBJECT;
+ pi.hint = PROPERTY_HINT_RESOURCE_TYPE;
+ pi.hint_string = "Texture3D";
}
- pi.hint = PROPERTY_HINT_RESOURCE_TYPE;
- pi.hint_string = "Texture3D";
- } break;
- case ShaderLanguage::TYPE_SAMPLERCUBE:
- case ShaderLanguage::TYPE_SAMPLERCUBEARRAY: {
- if (p_uniform.array_size > 0) {
- pi.type = Variant::ARRAY;
- } else {
- pi.type = Variant::OBJECT;
- }
- pi.hint = PROPERTY_HINT_RESOURCE_TYPE;
- pi.hint_string = "TextureLayered";
} break;
case ShaderLanguage::TYPE_STRUCT: {
// FIXME: Implement this.
@@ -4309,8 +4319,18 @@ ShaderLanguage::DataType ShaderLanguage::get_scalar_type(DataType p_type) {
TYPE_INT,
TYPE_UINT,
TYPE_FLOAT,
+ TYPE_INT,
+ TYPE_UINT,
+ TYPE_FLOAT,
+ TYPE_INT,
+ TYPE_UINT,
+ TYPE_FLOAT,
+ TYPE_FLOAT,
+ TYPE_VOID,
};
+ static_assert(sizeof(scalar_types) / sizeof(*scalar_types) == TYPE_MAX);
+
return scalar_types[p_type];
}
@@ -4340,8 +4360,18 @@ int ShaderLanguage::get_cardinality(DataType p_type) {
1,
1,
1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
};
+ static_assert(sizeof(cardinality_table) / sizeof(*cardinality_table) == TYPE_MAX);
+
return cardinality_table[p_type];
}
@@ -4399,13 +4429,17 @@ bool ShaderLanguage::_is_operator_assign(Operator p_op) const {
}
bool ShaderLanguage::_validate_varying_assign(ShaderNode::Varying &p_varying, String *r_message) {
- if (current_function != String("vertex") && current_function != String("fragment")) {
+ if (current_function != "vertex" && current_function != "fragment") {
*r_message = vformat(RTR("Varying may not be assigned in the '%s' function."), current_function);
return false;
}
switch (p_varying.stage) {
case ShaderNode::Varying::STAGE_UNKNOWN: // first assign
if (current_function == varying_function_names.vertex) {
+ if (p_varying.type < TYPE_INT) {
+ *r_message = vformat(RTR("Varying with '%s' data type may only be assigned in the 'fragment' function."), get_datatype_name(p_varying.type));
+ return false;
+ }
p_varying.stage = ShaderNode::Varying::STAGE_VERTEX;
} else if (current_function == varying_function_names.fragment) {
p_varying.stage = ShaderNode::Varying::STAGE_FRAGMENT;
@@ -5205,7 +5239,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
if (shader->varyings.has(varname)) {
switch (shader->varyings[varname].stage) {
case ShaderNode::Varying::STAGE_UNKNOWN: {
- _set_error(vformat(RTR("Varying '%s' must be assigned in the vertex or fragment function first."), varname));
+ _set_error(vformat(RTR("Varying '%s' must be assigned in the 'vertex' or 'fragment' function first."), varname));
return nullptr;
}
case ShaderNode::Varying::STAGE_VERTEX_TO_FRAGMENT_LIGHT:
@@ -5389,6 +5423,16 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
}
} else {
switch (var.stage) {
+ case ShaderNode::Varying::STAGE_UNKNOWN: {
+ if (var.type < TYPE_INT) {
+ if (current_function == varying_function_names.vertex) {
+ _set_error(vformat(RTR("Varying with '%s' data type may only be used in the 'fragment' function."), get_datatype_name(var.type)));
+ } else {
+ _set_error(vformat(RTR("Varying '%s' must be assigned in the 'fragment' function first."), identifier));
+ }
+ return nullptr;
+ }
+ } break;
case ShaderNode::Varying::STAGE_VERTEX:
if (current_function == varying_function_names.fragment || current_function == varying_function_names.light) {
var.stage = ShaderNode::Varying::STAGE_VERTEX_TO_FRAGMENT_LIGHT;
@@ -7570,7 +7614,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
return ERR_BUG;
}
- if (b && b->parent_function && p_function_info.main_function) {
+ if (b->parent_function && p_function_info.main_function) {
_set_error(vformat(RTR("Using '%s' in the '%s' processor function is incorrect."), "return", b->parent_function->name));
return ERR_PARSE_ERROR;
}
@@ -8170,25 +8214,27 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f
};
[[fallthrough]];
case TK_INSTANCE: {
+ if (tk.type == TK_INSTANCE) {
#ifdef DEBUG_ENABLED
- keyword_completion_context = CF_UNIFORM_KEYWORD;
- if (_lookup_next(next)) {
- if (next.type == TK_UNIFORM) {
- keyword_completion_context ^= CF_UNIFORM_KEYWORD;
+ keyword_completion_context = CF_UNIFORM_KEYWORD;
+ if (_lookup_next(next)) {
+ if (next.type == TK_UNIFORM) {
+ keyword_completion_context ^= CF_UNIFORM_KEYWORD;
+ }
}
- }
#endif // DEBUG_ENABLED
- if (String(shader_type_identifier) != "spatial") {
- _set_error(vformat(RTR("Uniform instances are not yet implemented for '%s' shaders."), shader_type_identifier));
- return ERR_PARSE_ERROR;
- }
- if (uniform_scope == ShaderNode::Uniform::SCOPE_LOCAL) {
- tk = _get_token();
- if (tk.type != TK_UNIFORM) {
- _set_expected_after_error("uniform", "instance");
+ if (String(shader_type_identifier) != "spatial") {
+ _set_error(vformat(RTR("Uniform instances are not yet implemented for '%s' shaders."), shader_type_identifier));
return ERR_PARSE_ERROR;
}
- uniform_scope = ShaderNode::Uniform::SCOPE_INSTANCE;
+ if (uniform_scope == ShaderNode::Uniform::SCOPE_LOCAL) {
+ tk = _get_token();
+ if (tk.type != TK_UNIFORM) {
+ _set_expected_after_error("uniform", "instance");
+ return ERR_PARSE_ERROR;
+ }
+ uniform_scope = ShaderNode::Uniform::SCOPE_INSTANCE;
+ }
}
};
[[fallthrough]];
@@ -8205,7 +8251,7 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f
}
}
DataPrecision precision = PRECISION_DEFAULT;
- DataInterpolation interpolation = INTERPOLATION_SMOOTH;
+ DataInterpolation interpolation = INTERPOLATION_DEFAULT;
DataType type;
StringName name;
int array_size = 0;
@@ -8314,6 +8360,11 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f
return ERR_PARSE_ERROR;
}
+ if (!is_uniform && interpolation != INTERPOLATION_DEFAULT && type < TYPE_INT) {
+ _set_error(vformat(RTR("Interpolation modifier '%s' cannot be used with boolean types."), get_interpolation_name(interpolation)));
+ return ERR_PARSE_ERROR;
+ }
+
if (!is_uniform && type > TYPE_MAT4) {
_set_error(RTR("Invalid data type for varying."));
return ERR_PARSE_ERROR;
@@ -8858,7 +8909,7 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f
_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()) {
+ } else if (current_uniform_group_name.is_empty()) {
_set_error(RTR("Group needs to be opened before."));
return ERR_PARSE_ERROR;
} else {
@@ -9717,6 +9768,25 @@ String ShaderLanguage::get_shader_type(const String &p_code) {
return String();
}
+bool ShaderLanguage::is_builtin_func_out_parameter(const String &p_name, int p_param) {
+ int i = 0;
+ while (builtin_func_out_args[i].name) {
+ if (p_name == builtin_func_out_args[i].name) {
+ for (int j = 0; j < BuiltinFuncOutArgs::MAX_ARGS; j++) {
+ int arg = builtin_func_out_args[i].arguments[j];
+ if (arg == p_param) {
+ return true;
+ }
+ if (arg < 0) {
+ return false;
+ }
+ }
+ }
+ i++;
+ }
+ return false;
+}
+
#ifdef DEBUG_ENABLED
void ShaderLanguage::_check_warning_accums() {
for (const KeyValue<ShaderWarning::Code, HashMap<StringName, HashMap<StringName, Usage>> *> &E : warnings_check_map2) {
diff --git a/servers/rendering/shader_language.h b/servers/rendering/shader_language.h
index 1e302f5805..d34114589f 100644
--- a/servers/rendering/shader_language.h
+++ b/servers/rendering/shader_language.h
@@ -247,6 +247,7 @@ public:
enum DataInterpolation {
INTERPOLATION_FLAT,
INTERPOLATION_SMOOTH,
+ INTERPOLATION_DEFAULT,
};
enum Operator {
@@ -720,6 +721,12 @@ public:
Node(TYPE_SHADER) {}
};
+ struct UniformOrderComparator {
+ _FORCE_INLINE_ bool operator()(const Pair<StringName, int> &A, const Pair<StringName, int> &B) const {
+ return A.second < B.second;
+ }
+ };
+
struct Expression {
bool is_op;
union {
@@ -768,6 +775,7 @@ public:
static bool is_token_arg_qual(TokenType p_type);
static DataPrecision get_token_precision(TokenType p_type);
static String get_precision_name(DataPrecision p_type);
+ static String get_interpolation_name(DataInterpolation p_interpolation);
static String get_datatype_name(DataType p_type);
static String get_uniform_hint_name(ShaderNode::Uniform::Hint p_hint);
static String get_texture_filter_name(TextureFilter p_filter);
@@ -1119,6 +1127,7 @@ public:
void clear();
static String get_shader_type(const String &p_code);
+ static bool is_builtin_func_out_parameter(const String &p_name, int p_param);
struct ShaderCompileInfo {
HashMap<StringName, FunctionInfo> functions;
diff --git a/servers/rendering/shader_types.cpp b/servers/rendering/shader_types.cpp
index 5e1da7c15d..86dd6a8b7e 100644
--- a/servers/rendering/shader_types.cpp
+++ b/servers/rendering/shader_types.cpp
@@ -100,6 +100,7 @@ ShaderTypes::ShaderTypes() {
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["CAMERA_VISIBLE_LAYERS"] = ShaderLanguage::TYPE_UINT;
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);
@@ -147,6 +148,7 @@ ShaderTypes::ShaderTypes() {
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["CAMERA_VISIBLE_LAYERS"] = ShaderLanguage::TYPE_UINT;
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);
diff --git a/servers/rendering/storage/environment_storage.cpp b/servers/rendering/storage/environment_storage.cpp
index 9b1842f1d9..78ce4eb4d0 100644
--- a/servers/rendering/storage/environment_storage.cpp
+++ b/servers/rendering/storage/environment_storage.cpp
@@ -283,7 +283,7 @@ void RendererEnvironmentStorage::environment_set_volumetric_fog(RID p_env, bool
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_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;
diff --git a/servers/rendering/storage/environment_storage.h b/servers/rendering/storage/environment_storage.h
index 17bde94902..dea9487af6 100644
--- a/servers/rendering/storage/environment_storage.h
+++ b/servers/rendering/storage/environment_storage.h
@@ -98,7 +98,7 @@ private:
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();
+ RID glow_map;
// SSR
bool ssr_enabled = false;
@@ -143,7 +143,7 @@ private:
float adjustments_contrast = 1.0f;
float adjustments_saturation = 1.0f;
bool use_1d_color_correction = false;
- RID color_correction = RID();
+ RID color_correction;
};
mutable RID_Owner<Environment, true> environment_owner;
diff --git a/servers/rendering/storage/light_storage.h b/servers/rendering/storage/light_storage.h
index df5b893cd5..ea3b4d4c44 100644
--- a/servers/rendering/storage/light_storage.h
+++ b/servers/rendering/storage/light_storage.h
@@ -31,6 +31,7 @@
#ifndef LIGHT_STORAGE_H
#define LIGHT_STORAGE_H
+#include "render_scene_buffers.h"
#include "servers/rendering_server.h"
class RendererLightStorage {
@@ -142,6 +143,7 @@ public:
virtual bool reflection_probe_instance_needs_redraw(RID p_instance) = 0;
virtual bool reflection_probe_instance_has_reflection(RID p_instance) = 0;
virtual bool reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas) = 0;
+ virtual Ref<RenderSceneBuffers> reflection_probe_atlas_get_render_buffers(RID p_reflection_atlas) = 0;
virtual bool reflection_probe_instance_postprocess_step(RID p_instance) = 0;
/* LIGHTMAP */
diff --git a/servers/rendering/storage/particles_storage.h b/servers/rendering/storage/particles_storage.h
index ee4b8679b3..5ef54346f2 100644
--- a/servers/rendering/storage/particles_storage.h
+++ b/servers/rendering/storage/particles_storage.h
@@ -94,8 +94,6 @@ public:
virtual void particles_add_collision(RID p_particles, RID p_particles_collision_instance) = 0;
virtual void particles_remove_collision(RID p_particles, RID p_particles_collision_instance) = 0;
- virtual void particles_set_canvas_sdf_collision(RID p_particles, bool p_enable, const Transform2D &p_xform, const Rect2 &p_to_screen, RID p_texture) = 0;
-
virtual void update_particles() = 0;
/* PARTICLES COLLISION */
@@ -116,7 +114,6 @@ public:
virtual void particles_collision_set_height_field_resolution(RID p_particles_collision, RS::ParticlesCollisionHeightfieldResolution p_resolution) = 0; //for SDF and vector field
virtual AABB particles_collision_get_aabb(RID p_particles_collision) const = 0;
virtual bool particles_collision_is_heightfield(RID p_particles_collision) const = 0;
- virtual RID particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const = 0;
//used from 2D and 3D
virtual RID particles_collision_instance_create(RID p_collision) = 0;
diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp
index 7691bede07..de3bd8d3e0 100644
--- a/servers/rendering_server.cpp
+++ b/servers/rendering_server.cpp
@@ -625,7 +625,7 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint
const int *src = indices.ptr();
for (int i = 0; i < p_index_array_len; i++) {
- if (p_vertex_array_len < (1 << 16) && p_vertex_array_len > 0) {
+ if (p_vertex_array_len <= (1 << 16) && p_vertex_array_len > 0) {
uint16_t v = src[i];
memcpy(&iw[i * 2], &v, 2);
@@ -835,10 +835,10 @@ void RenderingServer::mesh_surface_make_offsets_from_format(uint32_t p_format, i
break;
}
/* determine whether using 16 or 32 bits indices */
- if (p_vertex_len >= (1 << 16) || p_vertex_len == 0) {
- elem_size = 4;
- } else {
+ if (p_vertex_len <= (1 << 16) && p_vertex_len > 0) {
elem_size = 2;
+ } else {
+ elem_size = 4;
}
r_offsets[i] = elem_size;
continue;
@@ -1280,7 +1280,7 @@ Array RenderingServer::_get_array_from_surface(uint32_t p_format, Vector<uint8_t
Vector<int> arr;
arr.resize(p_index_len);
- if (p_vertex_len < (1 << 16)) {
+ if (p_vertex_len <= (1 << 16)) {
int *w = arr.ptrw();
for (int j = 0; j < p_index_len; j++) {
@@ -1476,7 +1476,11 @@ RenderingDevice *RenderingServer::get_rendering_device() const {
}
RenderingDevice *RenderingServer::create_local_rendering_device() const {
- return RenderingDevice::get_singleton()->create_local_device();
+ RenderingDevice *device = RenderingDevice::get_singleton();
+ if (!device) {
+ return nullptr;
+ }
+ return device->create_local_device();
}
static Vector<Ref<Image>> _get_imgvec(const TypedArray<Image> &p_layers) {
@@ -2349,7 +2353,6 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("environment_set_volumetric_fog", "env", "enable", "density", "albedo", "emission", "emission_energy", "anisotropy", "length", "p_detail_spread", "gi_inject", "temporal_reprojection", "temporal_reprojection_amount", "ambient_inject", "sky_affect"), &RenderingServer::environment_set_volumetric_fog);
ClassDB::bind_method(D_METHOD("environment_glow_set_use_bicubic_upscale", "enable"), &RenderingServer::environment_glow_set_use_bicubic_upscale);
- ClassDB::bind_method(D_METHOD("environment_glow_set_use_high_quality", "enable"), &RenderingServer::environment_glow_set_use_high_quality);
ClassDB::bind_method(D_METHOD("environment_set_ssr_roughness_quality", "quality"), &RenderingServer::environment_set_ssr_roughness_quality);
ClassDB::bind_method(D_METHOD("environment_set_ssao_quality", "quality", "half_size", "adaptive_target", "blur_passes", "fadeout_from", "fadeout_to"), &RenderingServer::environment_set_ssao_quality);
ClassDB::bind_method(D_METHOD("environment_set_ssil_quality", "quality", "half_size", "adaptive_target", "blur_passes", "fadeout_from", "fadeout_to"), &RenderingServer::environment_set_ssil_quality);
@@ -2477,6 +2480,7 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("instance_set_base", "instance", "base"), &RenderingServer::instance_set_base);
ClassDB::bind_method(D_METHOD("instance_set_scenario", "instance", "scenario"), &RenderingServer::instance_set_scenario);
ClassDB::bind_method(D_METHOD("instance_set_layer_mask", "instance", "mask"), &RenderingServer::instance_set_layer_mask);
+ ClassDB::bind_method(D_METHOD("instance_set_pivot_data", "instance", "sorting_offset", "use_aabb_center"), &RenderingServer::instance_set_pivot_data);
ClassDB::bind_method(D_METHOD("instance_set_transform", "instance", "transform"), &RenderingServer::instance_set_transform);
ClassDB::bind_method(D_METHOD("instance_attach_object_instance_id", "instance", "id"), &RenderingServer::instance_attach_object_instance_id);
ClassDB::bind_method(D_METHOD("instance_set_blend_shape_weight", "instance", "shape", "weight"), &RenderingServer::instance_set_blend_shape_weight);
@@ -2593,7 +2597,7 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("canvas_item_add_rect", "item", "rect", "color"), &RenderingServer::canvas_item_add_rect);
ClassDB::bind_method(D_METHOD("canvas_item_add_circle", "item", "pos", "radius", "color"), &RenderingServer::canvas_item_add_circle);
ClassDB::bind_method(D_METHOD("canvas_item_add_texture_rect", "item", "rect", "texture", "tile", "modulate", "transpose"), &RenderingServer::canvas_item_add_texture_rect, DEFVAL(false), DEFVAL(Color(1, 1, 1)), DEFVAL(false));
- ClassDB::bind_method(D_METHOD("canvas_item_add_msdf_texture_rect_region", "item", "rect", "texture", "src_rect", "modulate", "outline_size", "px_range"), &RenderingServer::canvas_item_add_msdf_texture_rect_region, DEFVAL(Color(1, 1, 1)), DEFVAL(0), DEFVAL(1.0));
+ ClassDB::bind_method(D_METHOD("canvas_item_add_msdf_texture_rect_region", "item", "rect", "texture", "src_rect", "modulate", "outline_size", "px_range", "scale"), &RenderingServer::canvas_item_add_msdf_texture_rect_region, DEFVAL(Color(1, 1, 1)), DEFVAL(0), DEFVAL(1.0), DEFVAL(1.0));
ClassDB::bind_method(D_METHOD("canvas_item_add_lcd_texture_rect_region", "item", "rect", "texture", "src_rect", "modulate"), &RenderingServer::canvas_item_add_lcd_texture_rect_region);
ClassDB::bind_method(D_METHOD("canvas_item_add_texture_rect_region", "item", "rect", "texture", "src_rect", "modulate", "transpose", "clip_uv"), &RenderingServer::canvas_item_add_texture_rect_region, DEFVAL(Color(1, 1, 1)), DEFVAL(false), DEFVAL(true));
ClassDB::bind_method(D_METHOD("canvas_item_add_nine_patch", "item", "rect", "source", "texture", "topleft", "bottomright", "x_axis_mode", "y_axis_mode", "draw_center", "modulate"), &RenderingServer::canvas_item_add_nine_patch, DEFVAL(NINE_PATCH_STRETCH), DEFVAL(NINE_PATCH_STRETCH), DEFVAL(true), DEFVAL(Color(1, 1, 1)));
@@ -2850,8 +2854,12 @@ void RenderingServer::init() {
GLOBAL_DEF_RST("rendering/textures/vram_compression/import_etc2", true);
GLOBAL_DEF("rendering/textures/lossless_compression/force_png", false);
- GLOBAL_DEF("rendering/textures/lossless_compression/webp_compression_level", 2);
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/textures/lossless_compression/webp_compression_level", PropertyInfo(Variant::INT, "rendering/textures/lossless_compression/webp_compression_level", PROPERTY_HINT_RANGE, "0,9,1"));
+
+ GLOBAL_DEF("rendering/textures/webp_compression/compression_method", 2);
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/textures/webp_compression/compression_method", PropertyInfo(Variant::INT, "rendering/textures/webp_compression/compression_method", PROPERTY_HINT_RANGE, "0,6,1"));
+
+ GLOBAL_DEF("rendering/textures/webp_compression/lossless_compression_factor", 25);
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/textures/webp_compression/lossless_compression_factor", PropertyInfo(Variant::FLOAT, "rendering/textures/webp_compression/lossless_compression_factor", PROPERTY_HINT_RANGE, "0,100,1"));
GLOBAL_DEF("rendering/limits/time/time_rollover_secs", 3600);
ProjectSettings::get_singleton()->set_custom_property_info("rendering/limits/time/time_rollover_secs", PropertyInfo(Variant::FLOAT, "rendering/limits/time/time_rollover_secs", PROPERTY_HINT_RANGE, "0,10000,1,or_greater"));
@@ -2979,7 +2987,6 @@ void RenderingServer::init() {
GLOBAL_DEF("rendering/environment/glow/upscale_mode", 1);
ProjectSettings::get_singleton()->set_custom_property_info("rendering/environment/glow/upscale_mode", PropertyInfo(Variant::INT, "rendering/environment/glow/upscale_mode", PROPERTY_HINT_ENUM, "Linear (Fast),Bicubic (Slow)"));
GLOBAL_DEF("rendering/environment/glow/upscale_mode.mobile", 0);
- GLOBAL_DEF("rendering/environment/glow/use_high_quality", false);
GLOBAL_DEF("rendering/environment/screen_space_reflection/roughness_quality", 1);
ProjectSettings::get_singleton()->set_custom_property_info("rendering/environment/screen_space_reflection/roughness_quality", PropertyInfo(Variant::INT, "rendering/environment/screen_space_reflection/roughness_quality", PROPERTY_HINT_ENUM, "Disabled (Fastest),Low (Fast),Medium (Average),High (Slow)"));
diff --git a/servers/rendering_server.h b/servers/rendering_server.h
index 1d364dfcff..f3d95e07cb 100644
--- a/servers/rendering_server.h
+++ b/servers/rendering_server.h
@@ -1038,7 +1038,6 @@ public:
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, 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;
enum EnvironmentToneMapper {
ENV_TONE_MAPPER_LINEAR,
@@ -1210,6 +1209,7 @@ public:
virtual void instance_set_base(RID p_instance, RID p_base) = 0;
virtual void instance_set_scenario(RID p_instance, RID p_scenario) = 0;
virtual void instance_set_layer_mask(RID p_instance, uint32_t p_mask) = 0;
+ virtual void instance_set_pivot_data(RID p_instance, float p_sorting_offset, bool p_use_aabb_center) = 0;
virtual void instance_set_transform(RID p_instance, const Transform3D &p_transform) = 0;
virtual void instance_attach_object_instance_id(RID p_instance, ObjectID p_id) = 0;
virtual void instance_set_blend_shape_weight(RID p_instance, int p_shape, float p_weight) = 0;
@@ -1340,7 +1340,7 @@ public:
virtual void canvas_item_add_circle(RID p_item, const Point2 &p_pos, float p_radius, const Color &p_color) = 0;
virtual void canvas_item_add_texture_rect(RID p_item, const Rect2 &p_rect, RID p_texture, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false) = 0;
virtual void canvas_item_add_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, bool p_clip_uv = false) = 0;
- virtual void canvas_item_add_msdf_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), int p_outline_size = 0, float p_px_range = 1.0) = 0;
+ virtual void canvas_item_add_msdf_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), int p_outline_size = 0, float p_px_range = 1.0, float p_scale = 1.0) = 0;
virtual void canvas_item_add_lcd_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1)) = 0;
virtual void canvas_item_add_nine_patch(RID p_item, const Rect2 &p_rect, const Rect2 &p_source, RID p_texture, const Vector2 &p_topleft, const Vector2 &p_bottomright, NinePatchAxisMode p_x_axis_mode = NINE_PATCH_STRETCH, NinePatchAxisMode p_y_axis_mode = NINE_PATCH_STRETCH, bool p_draw_center = true, const Color &p_modulate = Color(1, 1, 1)) = 0;
virtual void canvas_item_add_primitive(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, RID p_texture, float p_width = 1.0) = 0;
diff --git a/servers/text/text_server_extension.cpp b/servers/text/text_server_extension.cpp
index dd4cb5accb..4baa1db9bf 100644
--- a/servers/text/text_server_extension.cpp
+++ b/servers/text/text_server_extension.cpp
@@ -69,6 +69,12 @@ void TextServerExtension::_bind_methods() {
GDVIRTUAL_BIND(_font_set_style_name, "font_rid", "name_style");
GDVIRTUAL_BIND(_font_get_style_name, "font_rid");
+ GDVIRTUAL_BIND(_font_set_weight, "font_rid", "weight");
+ GDVIRTUAL_BIND(_font_get_weight, "font_rid");
+
+ GDVIRTUAL_BIND(_font_set_stretch, "font_rid", "stretch");
+ GDVIRTUAL_BIND(_font_get_stretch, "font_rid");
+
GDVIRTUAL_BIND(_font_set_antialiasing, "font_rid", "antialiasing");
GDVIRTUAL_BIND(_font_get_antialiasing, "font_rid");
@@ -87,6 +93,9 @@ void TextServerExtension::_bind_methods() {
GDVIRTUAL_BIND(_font_set_fixed_size, "font_rid", "fixed_size");
GDVIRTUAL_BIND(_font_get_fixed_size, "font_rid");
+ GDVIRTUAL_BIND(_font_set_allow_system_fallback, "font_rid", "allow_system_fallback");
+ GDVIRTUAL_BIND(_font_is_allow_system_fallback, "font_rid");
+
GDVIRTUAL_BIND(_font_set_force_autohinter, "font_rid", "force_autohinter");
GDVIRTUAL_BIND(_font_is_force_autohinter, "font_rid");
@@ -231,8 +240,8 @@ void TextServerExtension::_bind_methods() {
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");
+ GDVIRTUAL_BIND(_shaped_text_add_object, "shaped", "key", "size", "inline_align", "length", "baseline");
+ GDVIRTUAL_BIND(_shaped_text_resize_object, "shaped", "key", "size", "inline_align", "baseline");
GDVIRTUAL_BIND(_shaped_get_span_count, "shaped");
GDVIRTUAL_BIND(_shaped_get_span_meta, "shaped", "index");
@@ -299,7 +308,7 @@ void TextServerExtension::_bind_methods() {
GDVIRTUAL_BIND(_strip_diacritics, "string");
GDVIRTUAL_BIND(_is_valid_identifier, "string");
- GDVIRTUAL_BIND(_string_get_word_breaks, "string", "language");
+ GDVIRTUAL_BIND(_string_get_word_breaks, "string", "language", "chars_per_line");
GDVIRTUAL_BIND(_is_confusable, "string", "dict");
GDVIRTUAL_BIND(_spoof_check, "string");
@@ -308,6 +317,8 @@ void TextServerExtension::_bind_methods() {
GDVIRTUAL_BIND(_string_to_lower, "string", "language");
GDVIRTUAL_BIND(_parse_structured_text, "parser_type", "args", "text");
+
+ GDVIRTUAL_BIND(_cleanup);
}
bool TextServerExtension::has_feature(Feature p_feature) const {
@@ -434,6 +445,26 @@ String TextServerExtension::font_get_style_name(const RID &p_font_rid) const {
return ret;
}
+void TextServerExtension::font_set_weight(const RID &p_font_rid, int64_t p_weight) {
+ GDVIRTUAL_CALL(_font_set_weight, p_font_rid, p_weight);
+}
+
+int64_t TextServerExtension::font_get_weight(const RID &p_font_rid) const {
+ int64_t ret = 400;
+ GDVIRTUAL_CALL(_font_get_weight, p_font_rid, ret);
+ return ret;
+}
+
+void TextServerExtension::font_set_stretch(const RID &p_font_rid, int64_t p_stretch) {
+ GDVIRTUAL_CALL(_font_set_stretch, p_font_rid, p_stretch);
+}
+
+int64_t TextServerExtension::font_get_stretch(const RID &p_font_rid) const {
+ int64_t ret = 100;
+ GDVIRTUAL_CALL(_font_get_stretch, p_font_rid, ret);
+ return ret;
+}
+
void TextServerExtension::font_set_name(const RID &p_font_rid, const String &p_name) {
GDVIRTUAL_CALL(_font_set_name, p_font_rid, p_name);
}
@@ -504,6 +535,16 @@ int64_t TextServerExtension::font_get_fixed_size(const RID &p_font_rid) const {
return ret;
}
+void TextServerExtension::font_set_allow_system_fallback(const RID &p_font_rid, bool p_allow_system_fallback) {
+ GDVIRTUAL_CALL(_font_set_allow_system_fallback, p_font_rid, p_allow_system_fallback);
+}
+
+bool TextServerExtension::font_is_allow_system_fallback(const RID &p_font_rid) const {
+ bool ret = false;
+ GDVIRTUAL_CALL(_font_is_allow_system_fallback, p_font_rid, ret);
+ return ret;
+}
+
void TextServerExtension::font_set_force_autohinter(const RID &p_font_rid, bool p_force_autohinter) {
GDVIRTUAL_CALL(_font_set_force_autohinter, p_font_rid, p_force_autohinter);
}
@@ -1000,15 +1041,15 @@ bool TextServerExtension::shaped_text_add_string(const RID &p_shaped, const Stri
return ret;
}
-bool TextServerExtension::shaped_text_add_object(const RID &p_shaped, const Variant &p_key, const Size2 &p_size, InlineAlignment p_inline_align, int64_t p_length) {
+bool TextServerExtension::shaped_text_add_object(const RID &p_shaped, const Variant &p_key, const Size2 &p_size, InlineAlignment p_inline_align, int64_t p_length, float p_baseline) {
bool ret = false;
- GDVIRTUAL_CALL(_shaped_text_add_object, p_shaped, p_key, p_size, p_inline_align, p_length, ret);
+ GDVIRTUAL_CALL(_shaped_text_add_object, p_shaped, p_key, p_size, p_inline_align, p_length, p_baseline, ret);
return ret;
}
-bool TextServerExtension::shaped_text_resize_object(const RID &p_shaped, const Variant &p_key, const Size2 &p_size, InlineAlignment p_inline_align) {
+bool TextServerExtension::shaped_text_resize_object(const RID &p_shaped, const Variant &p_key, const Size2 &p_size, InlineAlignment p_inline_align, float p_baseline) {
bool ret = false;
- GDVIRTUAL_CALL(_shaped_text_resize_object, p_shaped, p_key, p_size, p_inline_align, ret);
+ GDVIRTUAL_CALL(_shaped_text_resize_object, p_shaped, p_key, p_size, p_inline_align, p_baseline, ret);
return ret;
}
@@ -1077,13 +1118,13 @@ bool TextServerExtension::shaped_text_is_ready(const RID &p_shaped) const {
}
const Glyph *TextServerExtension::shaped_text_get_glyphs(const RID &p_shaped) const {
- GDNativeConstPtr<const Glyph> ret;
+ GDExtensionConstPtr<const Glyph> ret;
GDVIRTUAL_CALL(_shaped_text_get_glyphs, p_shaped, ret);
return ret;
}
const Glyph *TextServerExtension::shaped_text_sort_logical(const RID &p_shaped) {
- GDNativeConstPtr<const Glyph> ret;
+ GDExtensionConstPtr<const Glyph> ret;
GDVIRTUAL_CALL(_shaped_text_sort_logical, p_shaped, ret);
return ret;
}
@@ -1137,7 +1178,7 @@ int64_t TextServerExtension::shaped_text_get_ellipsis_pos(const RID &p_shaped) c
}
const Glyph *TextServerExtension::shaped_text_get_ellipsis_glyphs(const RID &p_shaped) const {
- GDNativeConstPtr<const Glyph> ret;
+ GDExtensionConstPtr<const Glyph> ret;
GDVIRTUAL_CALL(_shaped_text_get_ellipsis_glyphs, p_shaped, ret);
return ret;
}
@@ -1338,9 +1379,9 @@ TypedArray<Vector2i> TextServerExtension::parse_structured_text(StructuredTextPa
return ret;
}
-PackedInt32Array TextServerExtension::string_get_word_breaks(const String &p_string, const String &p_language) const {
+PackedInt32Array TextServerExtension::string_get_word_breaks(const String &p_string, const String &p_language, int p_chars_per_line) const {
PackedInt32Array ret;
- GDVIRTUAL_CALL(_string_get_word_breaks, p_string, p_language, ret);
+ GDVIRTUAL_CALL(_string_get_word_breaks, p_string, p_language, p_chars_per_line, ret);
return ret;
}
@@ -1360,6 +1401,10 @@ bool TextServerExtension::spoof_check(const String &p_string) const {
return TextServer::spoof_check(p_string);
}
+void TextServerExtension::cleanup() {
+ GDVIRTUAL_CALL(_cleanup);
+}
+
TextServerExtension::TextServerExtension() {
//NOP
}
diff --git a/servers/text/text_server_extension.h b/servers/text/text_server_extension.h
index 992b708045..551e4e9087 100644
--- a/servers/text/text_server_extension.h
+++ b/servers/text/text_server_extension.h
@@ -84,7 +84,7 @@ public:
virtual void font_set_data(const RID &p_font_rid, const PackedByteArray &p_data) override;
virtual void font_set_data_ptr(const RID &p_font_rid, const uint8_t *p_data_ptr, int64_t p_data_size) override;
GDVIRTUAL2(_font_set_data, RID, const PackedByteArray &);
- GDVIRTUAL3(_font_set_data_ptr, RID, GDNativeConstPtr<const uint8_t>, int64_t);
+ GDVIRTUAL3(_font_set_data_ptr, RID, GDExtensionConstPtr<const uint8_t>, int64_t);
virtual void font_set_face_index(const RID &p_font_rid, int64_t p_index) override;
virtual int64_t font_get_face_index(const RID &p_font_rid) const override;
@@ -109,6 +109,16 @@ public:
GDVIRTUAL2(_font_set_style_name, RID, const String &);
GDVIRTUAL1RC(String, _font_get_style_name, RID);
+ virtual void font_set_weight(const RID &p_font_rid, int64_t p_weight) override;
+ virtual int64_t font_get_weight(const RID &p_font_rid) const override;
+ GDVIRTUAL2(_font_set_weight, RID, int);
+ GDVIRTUAL1RC(int64_t, _font_get_weight, RID);
+
+ virtual void font_set_stretch(const RID &p_font_rid, int64_t p_stretch) override;
+ virtual int64_t font_get_stretch(const RID &p_font_rid) const override;
+ GDVIRTUAL2(_font_set_stretch, RID, int);
+ GDVIRTUAL1RC(int64_t, _font_get_stretch, RID);
+
virtual void font_set_antialiasing(const RID &p_font_rid, TextServer::FontAntialiasing p_antialiasing) override;
virtual TextServer::FontAntialiasing font_get_antialiasing(const RID &p_font_rid) const override;
GDVIRTUAL2(_font_set_antialiasing, RID, TextServer::FontAntialiasing);
@@ -154,6 +164,11 @@ public:
GDVIRTUAL2(_font_set_transform, RID, Transform2D);
GDVIRTUAL1RC(Transform2D, _font_get_transform, RID);
+ virtual void font_set_allow_system_fallback(const RID &p_font_rid, bool p_allow_system_fallback) override;
+ virtual bool font_is_allow_system_fallback(const RID &p_font_rid) const override;
+ GDVIRTUAL2(_font_set_allow_system_fallback, RID, bool);
+ GDVIRTUAL1RC(bool, _font_is_allow_system_fallback, RID);
+
virtual void font_set_force_autohinter(const RID &p_font_rid, bool p_force_autohinter) override;
virtual bool font_is_force_autohinter(const RID &p_font_rid) const override;
GDVIRTUAL2(_font_set_force_autohinter, RID, bool);
@@ -380,11 +395,11 @@ public:
GDVIRTUAL2RC(int64_t, _shaped_text_get_spacing, RID, SpacingType);
virtual bool shaped_text_add_string(const RID &p_shaped, const String &p_text, const TypedArray<RID> &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;
+ 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, float p_baseline = 0.0) 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, float p_baseline = 0.0) override;
GDVIRTUAL7R(bool, _shaped_text_add_string, RID, const String &, const TypedArray<RID> &, int64_t, const Dictionary &, const String &, const Variant &);
- GDVIRTUAL5R(bool, _shaped_text_add_object, RID, const Variant &, const Size2 &, InlineAlignment, int64_t);
- GDVIRTUAL4R(bool, _shaped_text_resize_object, RID, const Variant &, const Size2 &, InlineAlignment);
+ GDVIRTUAL6R(bool, _shaped_text_add_object, RID, const Variant &, const Size2 &, InlineAlignment, int64_t, float);
+ GDVIRTUAL5R(bool, _shaped_text_resize_object, RID, const Variant &, const Size2 &, InlineAlignment, float);
virtual int64_t shaped_get_span_count(const RID &p_shaped) const override;
virtual Variant shaped_get_span_meta(const RID &p_shaped, int64_t p_index) const override;
@@ -416,8 +431,8 @@ public:
virtual const Glyph *shaped_text_get_glyphs(const RID &p_shaped) const override;
virtual const Glyph *shaped_text_sort_logical(const RID &p_shaped) override;
virtual int64_t shaped_text_get_glyph_count(const RID &p_shaped) const override;
- GDVIRTUAL1RC(GDNativeConstPtr<const Glyph>, _shaped_text_get_glyphs, RID);
- GDVIRTUAL1R(GDNativeConstPtr<const Glyph>, _shaped_text_sort_logical, RID);
+ GDVIRTUAL1RC(GDExtensionConstPtr<const Glyph>, _shaped_text_get_glyphs, RID);
+ GDVIRTUAL1R(GDExtensionConstPtr<const Glyph>, _shaped_text_sort_logical, RID);
GDVIRTUAL1RC(int64_t, _shaped_text_get_glyph_count, RID);
virtual Vector2i shaped_text_get_range(const RID &p_shaped) const override;
@@ -436,7 +451,7 @@ public:
virtual int64_t shaped_text_get_ellipsis_glyph_count(const RID &p_shaped) const override;
GDVIRTUAL1RC(int64_t, _shaped_text_get_trim_pos, RID);
GDVIRTUAL1RC(int64_t, _shaped_text_get_ellipsis_pos, RID);
- GDVIRTUAL1RC(GDNativeConstPtr<const Glyph>, _shaped_text_get_ellipsis_glyphs, RID);
+ GDVIRTUAL1RC(GDExtensionConstPtr<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, BitField<TextServer::TextOverrunFlag> p_trim_flags) override;
@@ -465,7 +480,7 @@ public:
virtual CaretInfo shaped_text_get_carets(const RID &p_shaped, int64_t p_position) const override;
virtual Vector<Vector2> shaped_text_get_selection(const RID &p_shaped, int64_t p_start, int64_t p_end) const override;
- GDVIRTUAL3C(_shaped_text_get_carets, RID, int64_t, GDNativePtr<CaretInfo>);
+ GDVIRTUAL3C(_shaped_text_get_carets, RID, int64_t, GDExtensionPtr<CaretInfo>);
GDVIRTUAL3RC(Vector<Vector2>, _shaped_text_get_selection, RID, int64_t, int64_t);
virtual int64_t shaped_text_hit_test_grapheme(const RID &p_shaped, double p_coords) const override;
@@ -495,8 +510,8 @@ public:
virtual String strip_diacritics(const String &p_string) const override;
GDVIRTUAL1RC(String, _strip_diacritics, const String &);
- 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 PackedInt32Array string_get_word_breaks(const String &p_string, const String &p_language = "", int p_chars_per_line = 0) const override;
+ GDVIRTUAL3RC(PackedInt32Array, _string_get_word_breaks, const String &, const String &, int);
virtual bool is_valid_identifier(const String &p_string) const override;
GDVIRTUAL1RC(bool, _is_valid_identifier, const String &);
@@ -514,6 +529,9 @@ public:
GDVIRTUAL2RC(int64_t, _is_confusable, const String &, const PackedStringArray &);
GDVIRTUAL1RC(bool, _spoof_check, const String &);
+ virtual void cleanup() override;
+ GDVIRTUAL0(_cleanup);
+
TextServerExtension();
~TextServerExtension();
};
diff --git a/servers/text_server.cpp b/servers/text_server.cpp
index dfeb5cb70c..c0f235fe50 100644
--- a/servers/text_server.cpp
+++ b/servers/text_server.cpp
@@ -223,6 +223,12 @@ void TextServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("font_set_style_name", "font_rid", "name"), &TextServer::font_set_style_name);
ClassDB::bind_method(D_METHOD("font_get_style_name", "font_rid"), &TextServer::font_get_style_name);
+ ClassDB::bind_method(D_METHOD("font_set_weight", "font_rid", "weight"), &TextServer::font_set_weight);
+ ClassDB::bind_method(D_METHOD("font_get_weight", "font_rid"), &TextServer::font_get_weight);
+
+ ClassDB::bind_method(D_METHOD("font_set_stretch", "font_rid", "weight"), &TextServer::font_set_stretch);
+ ClassDB::bind_method(D_METHOD("font_get_stretch", "font_rid"), &TextServer::font_get_stretch);
+
ClassDB::bind_method(D_METHOD("font_set_antialiasing", "font_rid", "antialiasing"), &TextServer::font_set_antialiasing);
ClassDB::bind_method(D_METHOD("font_get_antialiasing", "font_rid"), &TextServer::font_get_antialiasing);
@@ -241,6 +247,9 @@ void TextServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("font_set_fixed_size", "font_rid", "fixed_size"), &TextServer::font_set_fixed_size);
ClassDB::bind_method(D_METHOD("font_get_fixed_size", "font_rid"), &TextServer::font_get_fixed_size);
+ ClassDB::bind_method(D_METHOD("font_set_allow_system_fallback", "font_rid", "allow_system_fallback"), &TextServer::font_set_allow_system_fallback);
+ ClassDB::bind_method(D_METHOD("font_is_allow_system_fallback", "font_rid"), &TextServer::font_is_allow_system_fallback);
+
ClassDB::bind_method(D_METHOD("font_set_force_autohinter", "font_rid", "force_autohinter"), &TextServer::font_set_force_autohinter);
ClassDB::bind_method(D_METHOD("font_is_force_autohinter", "font_rid"), &TextServer::font_is_force_autohinter);
@@ -385,8 +394,8 @@ void TextServer::_bind_methods() {
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));
+ ClassDB::bind_method(D_METHOD("shaped_text_add_object", "shaped", "key", "size", "inline_align", "length", "baseline"), &TextServer::shaped_text_add_object, DEFVAL(INLINE_ALIGNMENT_CENTER), DEFVAL(1), DEFVAL(0.0));
+ ClassDB::bind_method(D_METHOD("shaped_text_resize_object", "shaped", "key", "size", "inline_align", "baseline"), &TextServer::shaped_text_resize_object, DEFVAL(INLINE_ALIGNMENT_CENTER), DEFVAL(0.0));
ClassDB::bind_method(D_METHOD("shaped_get_span_count", "shaped"), &TextServer::shaped_get_span_count);
ClassDB::bind_method(D_METHOD("shaped_get_span_meta", "shaped", "index"), &TextServer::shaped_get_span_meta);
@@ -445,7 +454,7 @@ void TextServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("parse_number", "number", "language"), &TextServer::parse_number, DEFVAL(""));
ClassDB::bind_method(D_METHOD("percent_sign", "language"), &TextServer::percent_sign, DEFVAL(""));
- ClassDB::bind_method(D_METHOD("string_get_word_breaks", "string", "language"), &TextServer::string_get_word_breaks, DEFVAL(""));
+ ClassDB::bind_method(D_METHOD("string_get_word_breaks", "string", "language", "chars_per_line"), &TextServer::string_get_word_breaks, DEFVAL(""), DEFVAL(0));
ClassDB::bind_method(D_METHOD("is_confusable", "string", "dict"), &TextServer::is_confusable);
ClassDB::bind_method(D_METHOD("spoof_check", "string"), &TextServer::spoof_check);
diff --git a/servers/text_server.h b/servers/text_server.h
index a4e6080fd0..0d94f45b79 100644
--- a/servers/text_server.h
+++ b/servers/text_server.h
@@ -250,6 +250,12 @@ public:
virtual void font_set_style_name(const RID &p_font_rid, const String &p_name) = 0;
virtual String font_get_style_name(const RID &p_font_rid) const = 0;
+ virtual void font_set_weight(const RID &p_font_rid, int64_t p_weight) = 0;
+ virtual int64_t font_get_weight(const RID &p_font_rid) const = 0;
+
+ virtual void font_set_stretch(const RID &p_font_rid, int64_t p_stretch) = 0;
+ virtual int64_t font_get_stretch(const RID &p_font_rid) const = 0;
+
virtual void font_set_antialiasing(const RID &p_font_rid, FontAntialiasing p_antialiasing) = 0;
virtual FontAntialiasing font_get_antialiasing(const RID &p_font_rid) const = 0;
@@ -268,6 +274,9 @@ public:
virtual void font_set_fixed_size(const RID &p_font_rid, int64_t p_fixed_size) = 0;
virtual int64_t font_get_fixed_size(const RID &p_font_rid) const = 0;
+ virtual void font_set_allow_system_fallback(const RID &p_font_rid, bool p_allow_system_fallback) = 0;
+ virtual bool font_is_allow_system_fallback(const RID &p_font_rid) const = 0;
+
virtual void font_set_force_autohinter(const RID &p_font_rid, bool p_force_autohinter) = 0;
virtual bool font_is_force_autohinter(const RID &p_font_rid) const = 0;
@@ -411,8 +420,8 @@ public:
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 TypedArray<RID> &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;
+ 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, float p_baseline = 0.0) = 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, float p_baseline = 0.0) = 0;
virtual int64_t shaped_get_span_count(const RID &p_shaped) const = 0;
virtual Variant shaped_get_span_meta(const RID &p_shaped, int64_t p_index) const = 0;
@@ -484,7 +493,7 @@ public:
virtual String percent_sign(const String &p_language = "") const = 0;
// String functions.
- virtual PackedInt32Array string_get_word_breaks(const String &p_string, const String &p_language = "") const = 0;
+ virtual PackedInt32Array string_get_word_breaks(const String &p_string, const String &p_language = "", int p_chars_per_line = 0) const = 0;
virtual int64_t is_confusable(const String &p_string, const PackedStringArray &p_dict) const { return -1; };
virtual bool spoof_check(const String &p_string) const { return false; };
@@ -498,6 +507,8 @@ public:
TypedArray<Vector2i> parse_structured_text(StructuredTextParser p_parser_type, const Array &p_args, const String &p_text) const;
+ virtual void cleanup() {}
+
TextServer();
~TextServer();
};
diff --git a/servers/xr/xr_interface.cpp b/servers/xr/xr_interface.cpp
index 4d58d24405..ec4ae98397 100644
--- a/servers/xr/xr_interface.cpp
+++ b/servers/xr/xr_interface.cpp
@@ -167,11 +167,12 @@ 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.
+ int32_t texel_width = RD::get_singleton()->limit_get(RD::LIMIT_VRS_TEXEL_WIDTH);
+ int32_t texel_height = RD::get_singleton()->limit_get(RD::LIMIT_VRS_TEXEL_HEIGHT);
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));
+ Size2 vrs_size = Size2(round(0.5 + target_size.x / texel_width), round(0.5 + target_size.y / texel_height));
real_t radius = vrs_size.length() * 0.5;
Size2 vrs_sizei = vrs_size;
@@ -179,6 +180,8 @@ RID XRInterface::get_vrs_texture() {
const uint8_t densities[] = {
0, // 1x1
1, // 1x2
+ // 2, // 1x4 - not supported
+ // 3, // 1x8 - not supported
// 4, // 2x1
5, // 2x2
6, // 2x4
diff --git a/servers/xr/xr_interface.h b/servers/xr/xr_interface.h
index 86d328d41c..2960074dd2 100644
--- a/servers/xr/xr_interface.h
+++ b/servers/xr/xr_interface.h
@@ -138,8 +138,6 @@ public:
virtual bool start_passthrough() { return false; }
virtual void stop_passthrough() {}
- virtual void notification(int p_what){};
-
XRInterface();
~XRInterface();
diff --git a/servers/xr/xr_interface_extension.cpp b/servers/xr/xr_interface_extension.cpp
index 89752b3017..2142ecd262 100644
--- a/servers/xr/xr_interface_extension.cpp
+++ b/servers/xr/xr_interface_extension.cpp
@@ -58,8 +58,6 @@ void XRInterfaceExtension::_bind_methods() {
GDVIRTUAL_BIND(_post_draw_viewport, "render_target", "screen_rect");
GDVIRTUAL_BIND(_end_frame);
- GDVIRTUAL_BIND(_notification, "what");
-
/** input and output **/
GDVIRTUAL_BIND(_get_suggested_tracker_names);
@@ -309,10 +307,6 @@ void XRInterfaceExtension::end_frame() {
GDVIRTUAL_CALL(_end_frame);
}
-void XRInterfaceExtension::notification(int p_what) {
- GDVIRTUAL_CALL(_notification, p_what);
-}
-
RID XRInterfaceExtension::get_render_target_texture(RID p_render_target) {
// In due time this will need to be enhance to return the correct INTERNAL RID for the chosen rendering engine.
// So once a GLES driver is implemented we'll return that and the implemented plugin needs to handle this correctly too.
diff --git a/servers/xr/xr_interface_extension.h b/servers/xr/xr_interface_extension.h
index 2235b57cb3..123626864d 100644
--- a/servers/xr/xr_interface_extension.h
+++ b/servers/xr/xr_interface_extension.h
@@ -123,7 +123,6 @@ public:
virtual bool pre_draw_viewport(RID p_render_target) override;
virtual Vector<BlitToScreen> post_draw_viewport(RID p_render_target, const Rect2 &p_screen_rect) override;
virtual void end_frame() override;
- virtual void notification(int p_what) override;
GDVIRTUAL0(_process);
GDVIRTUAL0(_pre_render);
@@ -131,8 +130,6 @@ public:
GDVIRTUAL2(_post_draw_viewport, RID, const Rect2 &);
GDVIRTUAL0(_end_frame);
- GDVIRTUAL1(_notification, int);
-
/* access to some internals we need */
RID get_render_target_texture(RID p_render_target);
// RID get_render_target_depth(RID p_render_target);
diff --git a/tests/core/config/test_project_settings.h b/tests/core/config/test_project_settings.h
new file mode 100644
index 0000000000..c99ba76a24
--- /dev/null
+++ b/tests/core/config/test_project_settings.h
@@ -0,0 +1,102 @@
+/*************************************************************************/
+/* test_project_settings.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_PROJECT_SETTINGS_H
+#define TEST_PROJECT_SETTINGS_H
+
+#include "core/config/project_settings.h"
+#include "core/variant/variant.h"
+#include "tests/test_macros.h"
+
+namespace TestProjectSettings {
+
+TEST_CASE("[ProjectSettings] Get existing setting") {
+ CHECK(ProjectSettings::get_singleton()->has_setting("application/config/name"));
+
+ Variant variant = ProjectSettings::get_singleton()->get_setting("application/config/name");
+ CHECK_EQ(variant.get_type(), Variant::STRING);
+
+ String name = variant;
+ CHECK_EQ(name, "GDScript Integration Test Suite");
+}
+
+TEST_CASE("[ProjectSettings] Default value is ignored if setting exists") {
+ CHECK(ProjectSettings::get_singleton()->has_setting("application/config/name"));
+
+ Variant variant = ProjectSettings::get_singleton()->get_setting("application/config/name", "SomeDefaultValue");
+ CHECK_EQ(variant.get_type(), Variant::STRING);
+
+ String name = variant;
+ CHECK_EQ(name, "GDScript Integration Test Suite");
+}
+
+TEST_CASE("[ProjectSettings] Non existing setting is null") {
+ CHECK_FALSE(ProjectSettings::get_singleton()->has_setting("not_existing_setting"));
+
+ Variant variant = ProjectSettings::get_singleton()->get_setting("not_existing_setting");
+ CHECK_EQ(variant.get_type(), Variant::NIL);
+}
+
+TEST_CASE("[ProjectSettings] Non existing setting should return default value") {
+ CHECK_FALSE(ProjectSettings::get_singleton()->has_setting("not_existing_setting"));
+
+ Variant variant = ProjectSettings::get_singleton()->get_setting("not_existing_setting");
+ CHECK_EQ(variant.get_type(), Variant::NIL);
+
+ variant = ProjectSettings::get_singleton()->get_setting("not_existing_setting", "my_nice_default_value");
+ CHECK_EQ(variant.get_type(), Variant::STRING);
+
+ String name = variant;
+ CHECK_EQ(name, "my_nice_default_value");
+
+ CHECK_FALSE(ProjectSettings::get_singleton()->has_setting("not_existing_setting"));
+}
+
+TEST_CASE("[ProjectSettings] Set value should be returned when retrieved") {
+ CHECK_FALSE(ProjectSettings::get_singleton()->has_setting("my_custom_setting"));
+
+ Variant variant = ProjectSettings::get_singleton()->get_setting("my_custom_setting");
+ CHECK_EQ(variant.get_type(), Variant::NIL);
+
+ ProjectSettings::get_singleton()->set_setting("my_custom_setting", true);
+ CHECK(ProjectSettings::get_singleton()->has_setting("my_custom_setting"));
+
+ variant = ProjectSettings::get_singleton()->get_setting("my_custom_setting");
+ CHECK_EQ(variant.get_type(), Variant::BOOL);
+
+ bool value = variant;
+ CHECK_EQ(true, value);
+
+ CHECK(ProjectSettings::get_singleton()->has_setting("my_custom_setting"));
+}
+
+} // namespace TestProjectSettings
+
+#endif // TEST_PROJECT_SETTINGS_H
diff --git a/tests/core/math/test_math_funcs.h b/tests/core/math/test_math_funcs.h
index c468e73b74..c9d14bbd21 100644
--- a/tests/core/math/test_math_funcs.h
+++ b/tests/core/math/test_math_funcs.h
@@ -88,290 +88,280 @@ TEST_CASE("[Math] Power of two functions") {
CHECK(nearest_shift(65535) == 16);
}
-TEST_CASE("[Math] abs") {
- // int
- CHECK(Math::abs(-1) == 1);
- CHECK(Math::abs(0) == 0);
- CHECK(Math::abs(1) == 1);
-
- // double
- CHECK(Math::abs(-0.1) == 0.1);
- CHECK(Math::abs(0.0) == 0.0);
- CHECK(Math::abs(0.1) == 0.1);
-
- // float
- CHECK(Math::abs(-0.1f) == 0.1f);
- CHECK(Math::abs(0.0f) == 0.0f);
- CHECK(Math::abs(0.1f) == 0.1f);
-}
-
-TEST_CASE("[Math] round/floor/ceil") {
- CHECK(Math::round(1.5) == 2.0);
- CHECK(Math::round(1.6) == 2.0);
- CHECK(Math::round(-1.5) == -2.0);
- CHECK(Math::round(-1.1) == -1.0);
-
- CHECK(Math::floor(1.5) == 1.0);
- CHECK(Math::floor(-1.5) == -2.0);
-
- CHECK(Math::ceil(1.5) == 2.0);
- CHECK(Math::ceil(-1.9) == -1.0);
-}
-
-TEST_CASE("[Math] sin/cos/tan") {
- CHECK(Math::sin(-0.1) == doctest::Approx(-0.0998334166));
- CHECK(Math::sin(0.1) == doctest::Approx(0.0998334166));
- CHECK(Math::sin(0.5) == doctest::Approx(0.4794255386));
- CHECK(Math::sin(1.0) == doctest::Approx(0.8414709848));
- CHECK(Math::sin(1.5) == doctest::Approx(0.9974949866));
- CHECK(Math::sin(450.0) == doctest::Approx(-0.683283725));
-
- CHECK(Math::cos(-0.1) == doctest::Approx(0.99500416530));
- CHECK(Math::cos(0.1) == doctest::Approx(0.9950041653));
- CHECK(Math::cos(0.5) == doctest::Approx(0.8775825619));
- CHECK(Math::cos(1.0) == doctest::Approx(0.5403023059));
- CHECK(Math::cos(1.5) == doctest::Approx(0.0707372017));
- CHECK(Math::cos(450.0) == doctest::Approx(-0.7301529642));
-
- CHECK(Math::tan(-0.1) == doctest::Approx(-0.1003346721));
- CHECK(Math::tan(0.1) == doctest::Approx(0.1003346721));
- CHECK(Math::tan(0.5) == doctest::Approx(0.5463024898));
- CHECK(Math::tan(1.0) == doctest::Approx(1.5574077247));
- CHECK(Math::tan(1.5) == doctest::Approx(14.1014199472));
- CHECK(Math::tan(450.0) == doctest::Approx(0.9358090134));
-}
-
-TEST_CASE("[Math] sinh/cosh/tanh") {
- CHECK(Math::sinh(-0.1) == doctest::Approx(-0.10016675));
- CHECK(Math::sinh(0.1) == doctest::Approx(0.10016675));
- CHECK(Math::sinh(0.5) == doctest::Approx(0.5210953055));
- CHECK(Math::sinh(1.0) == doctest::Approx(1.1752011936));
- CHECK(Math::sinh(1.5) == doctest::Approx(2.1292794551));
-
- CHECK(Math::cosh(-0.1) == doctest::Approx(1.0050041681));
- CHECK(Math::cosh(0.1) == doctest::Approx(1.0050041681));
- CHECK(Math::cosh(0.5) == doctest::Approx(1.1276259652));
- CHECK(Math::cosh(1.0) == doctest::Approx(1.5430806348));
- CHECK(Math::cosh(1.5) == doctest::Approx(2.3524096152));
-
- CHECK(Math::tanh(-0.1) == doctest::Approx(-0.0996679946));
- CHECK(Math::tanh(0.1) == doctest::Approx(0.0996679946));
- CHECK(Math::tanh(0.5) == doctest::Approx(0.4621171573));
- CHECK(Math::tanh(1.0) == doctest::Approx(0.761594156));
- CHECK(Math::tanh(1.5) == doctest::Approx(0.9051482536));
- CHECK(Math::tanh(450.0) == doctest::Approx(1.0));
-}
-
-TEST_CASE("[Math] asin/acos/atan") {
- CHECK(Math::asin(-0.1) == doctest::Approx(-0.1001674212));
- CHECK(Math::asin(0.1) == doctest::Approx(0.1001674212));
- CHECK(Math::asin(0.5) == doctest::Approx(0.5235987756));
- CHECK(Math::asin(1.0) == doctest::Approx(1.5707963268));
- CHECK(Math::is_nan(Math::asin(1.5)));
- CHECK(Math::is_nan(Math::asin(450.0)));
-
- CHECK(Math::acos(-0.1) == doctest::Approx(1.670963748));
- CHECK(Math::acos(0.1) == doctest::Approx(1.4706289056));
- CHECK(Math::acos(0.5) == doctest::Approx(1.0471975512));
- CHECK(Math::acos(1.0) == doctest::Approx(0.0));
- CHECK(Math::is_nan(Math::acos(1.5)));
- CHECK(Math::is_nan(Math::acos(450.0)));
-
- CHECK(Math::atan(-0.1) == doctest::Approx(-0.0996686525));
- CHECK(Math::atan(0.1) == doctest::Approx(0.0996686525));
- CHECK(Math::atan(0.5) == doctest::Approx(0.463647609));
- CHECK(Math::atan(1.0) == doctest::Approx(0.7853981634));
- CHECK(Math::atan(1.5) == doctest::Approx(0.9827937232));
- CHECK(Math::atan(450.0) == doctest::Approx(1.5685741082));
-}
-
-TEST_CASE("[Math] sinc/sincn/atan2") {
- CHECK(Math::sinc(-0.1) == doctest::Approx(0.9983341665));
- CHECK(Math::sinc(0.1) == doctest::Approx(0.9983341665));
- CHECK(Math::sinc(0.5) == doctest::Approx(0.9588510772));
- CHECK(Math::sinc(1.0) == doctest::Approx(0.8414709848));
- CHECK(Math::sinc(1.5) == doctest::Approx(0.6649966577));
- CHECK(Math::sinc(450.0) == doctest::Approx(-0.0015184083));
-
- CHECK(Math::sincn(-0.1) == doctest::Approx(0.9836316431));
- CHECK(Math::sincn(0.1) == doctest::Approx(0.9836316431));
- CHECK(Math::sincn(0.5) == doctest::Approx(0.6366197724));
- CHECK(Math::sincn(1.0) == doctest::Approx(0.0));
- CHECK(Math::sincn(1.5) == doctest::Approx(-0.2122065908));
- CHECK(Math::sincn(450.0) == doctest::Approx(0.0));
-
- CHECK(Math::atan2(-0.1, 0.5) == doctest::Approx(-0.1973955598));
- CHECK(Math::atan2(0.1, -0.5) == doctest::Approx(2.9441970937));
- CHECK(Math::atan2(0.5, 1.5) == doctest::Approx(0.3217505544));
- CHECK(Math::atan2(1.0, 2.5) == doctest::Approx(0.3805063771));
- CHECK(Math::atan2(1.5, 1.0) == doctest::Approx(0.9827937232));
- CHECK(Math::atan2(450.0, 1.0) == doctest::Approx(1.5685741082));
-}
-
-TEST_CASE("[Math] pow/log/log2/exp/sqrt") {
- CHECK(Math::pow(-0.1, 2.0) == doctest::Approx(0.01));
- CHECK(Math::pow(0.1, 2.5) == doctest::Approx(0.0031622777));
- CHECK(Math::pow(0.5, 0.5) == doctest::Approx(0.7071067812));
- CHECK(Math::pow(1.0, 1.0) == doctest::Approx(1.0));
- CHECK(Math::pow(1.5, -1.0) == doctest::Approx(0.6666666667));
- CHECK(Math::pow(450.0, -2.0) == doctest::Approx(0.0000049383));
- CHECK(Math::pow(450.0, 0.0) == doctest::Approx(1.0));
-
- CHECK(Math::is_nan(Math::log(-0.1)));
- CHECK(Math::log(0.1) == doctest::Approx(-2.302585093));
- CHECK(Math::log(0.5) == doctest::Approx(-0.6931471806));
- CHECK(Math::log(1.0) == doctest::Approx(0.0));
- CHECK(Math::log(1.5) == doctest::Approx(0.4054651081));
- CHECK(Math::log(450.0) == doctest::Approx(6.1092475828));
-
- CHECK(Math::is_nan(Math::log2(-0.1)));
- CHECK(Math::log2(0.1) == doctest::Approx(-3.3219280949));
- CHECK(Math::log2(0.5) == doctest::Approx(-1.0));
- CHECK(Math::log2(1.0) == doctest::Approx(0.0));
- CHECK(Math::log2(1.5) == doctest::Approx(0.5849625007));
- CHECK(Math::log2(450.0) == doctest::Approx(8.8137811912));
-
- CHECK(Math::exp(-0.1) == doctest::Approx(0.904837418));
- CHECK(Math::exp(0.1) == doctest::Approx(1.1051709181));
- CHECK(Math::exp(0.5) == doctest::Approx(1.6487212707));
- CHECK(Math::exp(1.0) == doctest::Approx(2.7182818285));
- CHECK(Math::exp(1.5) == doctest::Approx(4.4816890703));
-
- CHECK(Math::is_nan(Math::sqrt(-0.1)));
- CHECK(Math::sqrt(0.1) == doctest::Approx(0.316228));
- CHECK(Math::sqrt(0.5) == doctest::Approx(0.707107));
- CHECK(Math::sqrt(1.0) == doctest::Approx(1.0));
- CHECK(Math::sqrt(1.5) == doctest::Approx(1.224745));
-}
-
-TEST_CASE("[Math] is_nan/is_inf") {
- CHECK(!Math::is_nan(0.0));
- CHECK(Math::is_nan(NAN));
-
- CHECK(!Math::is_inf(0.0));
- CHECK(Math::is_inf(INFINITY));
-}
-
-TEST_CASE("[Math] linear_to_db") {
- CHECK(Math::linear_to_db(1.0) == doctest::Approx(0.0));
- CHECK(Math::linear_to_db(20.0) == doctest::Approx(26.0206));
- CHECK(Math::is_inf(Math::linear_to_db(0.0)));
- CHECK(Math::is_nan(Math::linear_to_db(-20.0)));
-}
-
-TEST_CASE("[Math] db_to_linear") {
- CHECK(Math::db_to_linear(0.0) == doctest::Approx(1.0));
- CHECK(Math::db_to_linear(1.0) == doctest::Approx(1.122018));
- CHECK(Math::db_to_linear(20.0) == doctest::Approx(10.0));
- CHECK(Math::db_to_linear(-20.0) == doctest::Approx(0.1));
-}
-
-TEST_CASE("[Math] step_decimals") {
- CHECK(Math::step_decimals(-0.5) == 1);
- CHECK(Math::step_decimals(0) == 0);
- CHECK(Math::step_decimals(1) == 0);
- CHECK(Math::step_decimals(0.1) == 1);
- CHECK(Math::step_decimals(0.01) == 2);
- CHECK(Math::step_decimals(0.001) == 3);
- CHECK(Math::step_decimals(0.0001) == 4);
- CHECK(Math::step_decimals(0.00001) == 5);
- CHECK(Math::step_decimals(0.000001) == 6);
- CHECK(Math::step_decimals(0.0000001) == 7);
- CHECK(Math::step_decimals(0.00000001) == 8);
- CHECK(Math::step_decimals(0.000000001) == 9);
+TEST_CASE_TEMPLATE("[Math] abs", T, int, float, double) {
+ CHECK(Math::abs((T)-1) == (T)1);
+ CHECK(Math::abs((T)0) == (T)0);
+ CHECK(Math::abs((T)1) == (T)1);
+ CHECK(Math::abs((T)0.1) == (T)0.1);
+}
+
+TEST_CASE_TEMPLATE("[Math] round/floor/ceil", T, float, double) {
+ CHECK(Math::round((T)1.5) == (T)2.0);
+ CHECK(Math::round((T)1.6) == (T)2.0);
+ CHECK(Math::round((T)-1.5) == (T)-2.0);
+ CHECK(Math::round((T)-1.1) == (T)-1.0);
+
+ CHECK(Math::floor((T)1.5) == (T)1.0);
+ CHECK(Math::floor((T)-1.5) == (T)-2.0);
+
+ CHECK(Math::ceil((T)1.5) == (T)2.0);
+ CHECK(Math::ceil((T)-1.9) == (T)-1.0);
+}
+
+TEST_CASE_TEMPLATE("[Math] sin/cos/tan", T, float, double) {
+ CHECK(Math::sin((T)-0.1) == doctest::Approx((T)-0.0998334166));
+ CHECK(Math::sin((T)0.1) == doctest::Approx((T)0.0998334166));
+ CHECK(Math::sin((T)0.5) == doctest::Approx((T)0.4794255386));
+ CHECK(Math::sin((T)1.0) == doctest::Approx((T)0.8414709848));
+ CHECK(Math::sin((T)1.5) == doctest::Approx((T)0.9974949866));
+ CHECK(Math::sin((T)450.0) == doctest::Approx((T)-0.683283725));
+
+ CHECK(Math::cos((T)-0.1) == doctest::Approx((T)0.99500416530));
+ CHECK(Math::cos((T)0.1) == doctest::Approx((T)0.9950041653));
+ CHECK(Math::cos((T)0.5) == doctest::Approx((T)0.8775825619));
+ CHECK(Math::cos((T)1.0) == doctest::Approx((T)0.5403023059));
+ CHECK(Math::cos((T)1.5) == doctest::Approx((T)0.0707372017));
+ CHECK(Math::cos((T)450.0) == doctest::Approx((T)-0.7301529642));
+
+ CHECK(Math::tan((T)-0.1) == doctest::Approx((T)-0.1003346721));
+ CHECK(Math::tan((T)0.1) == doctest::Approx((T)0.1003346721));
+ CHECK(Math::tan((T)0.5) == doctest::Approx((T)0.5463024898));
+ CHECK(Math::tan((T)1.0) == doctest::Approx((T)1.5574077247));
+ CHECK(Math::tan((T)1.5) == doctest::Approx((T)14.1014199472));
+ CHECK(Math::tan((T)450.0) == doctest::Approx((T)0.9358090134));
+}
+
+TEST_CASE_TEMPLATE("[Math] sinh/cosh/tanh", T, float, double) {
+ CHECK(Math::sinh((T)-0.1) == doctest::Approx((T)-0.10016675));
+ CHECK(Math::sinh((T)0.1) == doctest::Approx((T)0.10016675));
+ CHECK(Math::sinh((T)0.5) == doctest::Approx((T)0.5210953055));
+ CHECK(Math::sinh((T)1.0) == doctest::Approx((T)1.1752011936));
+ CHECK(Math::sinh((T)1.5) == doctest::Approx((T)2.1292794551));
+
+ CHECK(Math::cosh((T)-0.1) == doctest::Approx((T)1.0050041681));
+ CHECK(Math::cosh((T)0.1) == doctest::Approx((T)1.0050041681));
+ CHECK(Math::cosh((T)0.5) == doctest::Approx((T)1.1276259652));
+ CHECK(Math::cosh((T)1.0) == doctest::Approx((T)1.5430806348));
+ CHECK(Math::cosh((T)1.5) == doctest::Approx((T)2.3524096152));
+
+ CHECK(Math::tanh((T)-0.1) == doctest::Approx((T)-0.0996679946));
+ CHECK(Math::tanh((T)0.1) == doctest::Approx((T)0.0996679946));
+ CHECK(Math::tanh((T)0.5) == doctest::Approx((T)0.4621171573));
+ CHECK(Math::tanh((T)1.0) == doctest::Approx((T)0.761594156));
+ CHECK(Math::tanh((T)1.5) == doctest::Approx((T)0.9051482536));
+ CHECK(Math::tanh((T)450.0) == doctest::Approx((T)1.0));
+}
+
+TEST_CASE_TEMPLATE("[Math] asin/acos/atan", T, float, double) {
+ CHECK(Math::asin((T)-0.1) == doctest::Approx((T)-0.1001674212));
+ CHECK(Math::asin((T)0.1) == doctest::Approx((T)0.1001674212));
+ CHECK(Math::asin((T)0.5) == doctest::Approx((T)0.5235987756));
+ CHECK(Math::asin((T)1.0) == doctest::Approx((T)1.5707963268));
+ CHECK(Math::is_nan(Math::asin((T)1.5)));
+ CHECK(Math::is_nan(Math::asin((T)450.0)));
+
+ CHECK(Math::acos((T)-0.1) == doctest::Approx((T)1.670963748));
+ CHECK(Math::acos((T)0.1) == doctest::Approx((T)1.4706289056));
+ CHECK(Math::acos((T)0.5) == doctest::Approx((T)1.0471975512));
+ CHECK(Math::acos((T)1.0) == doctest::Approx((T)0.0));
+ CHECK(Math::is_nan(Math::acos((T)1.5)));
+ CHECK(Math::is_nan(Math::acos((T)450.0)));
+
+ CHECK(Math::atan((T)-0.1) == doctest::Approx((T)-0.0996686525));
+ CHECK(Math::atan((T)0.1) == doctest::Approx((T)0.0996686525));
+ CHECK(Math::atan((T)0.5) == doctest::Approx((T)0.463647609));
+ CHECK(Math::atan((T)1.0) == doctest::Approx((T)0.7853981634));
+ CHECK(Math::atan((T)1.5) == doctest::Approx((T)0.9827937232));
+ CHECK(Math::atan((T)450.0) == doctest::Approx((T)1.5685741082));
+}
+
+TEST_CASE_TEMPLATE("[Math] sinc/sincn/atan2", T, float, double) {
+ CHECK(Math::sinc((T)-0.1) == doctest::Approx((T)0.9983341665));
+ CHECK(Math::sinc((T)0.1) == doctest::Approx((T)0.9983341665));
+ CHECK(Math::sinc((T)0.5) == doctest::Approx((T)0.9588510772));
+ CHECK(Math::sinc((T)1.0) == doctest::Approx((T)0.8414709848));
+ CHECK(Math::sinc((T)1.5) == doctest::Approx((T)0.6649966577));
+ CHECK(Math::sinc((T)450.0) == doctest::Approx((T)-0.0015184083));
+
+ CHECK(Math::sincn((T)-0.1) == doctest::Approx((T)0.9836316431));
+ CHECK(Math::sincn((T)0.1) == doctest::Approx((T)0.9836316431));
+ CHECK(Math::sincn((T)0.5) == doctest::Approx((T)0.6366197724));
+ CHECK(Math::sincn((T)1.0) == doctest::Approx((T)0.0));
+ CHECK(Math::sincn((T)1.5) == doctest::Approx((T)-0.2122065908));
+ CHECK(Math::sincn((T)450.0) == doctest::Approx((T)0.0));
+
+ CHECK(Math::atan2((T)-0.1, (T)0.5) == doctest::Approx((T)-0.1973955598));
+ CHECK(Math::atan2((T)0.1, (T)-0.5) == doctest::Approx((T)2.9441970937));
+ CHECK(Math::atan2((T)0.5, (T)1.5) == doctest::Approx((T)0.3217505544));
+ CHECK(Math::atan2((T)1.0, (T)2.5) == doctest::Approx((T)0.3805063771));
+ CHECK(Math::atan2((T)1.5, (T)1.0) == doctest::Approx((T)0.9827937232));
+ CHECK(Math::atan2((T)450.0, (T)1.0) == doctest::Approx((T)1.5685741082));
+}
+
+TEST_CASE_TEMPLATE("[Math] pow/log/log2/exp/sqrt", T, float, double) {
+ CHECK(Math::pow((T)-0.1, (T)2.0) == doctest::Approx((T)0.01));
+ CHECK(Math::pow((T)0.1, (T)2.5) == doctest::Approx((T)0.0031622777));
+ CHECK(Math::pow((T)0.5, (T)0.5) == doctest::Approx((T)0.7071067812));
+ CHECK(Math::pow((T)1.0, (T)1.0) == doctest::Approx((T)1.0));
+ CHECK(Math::pow((T)1.5, (T)-1.0) == doctest::Approx((T)0.6666666667));
+ CHECK(Math::pow((T)450.0, (T)-2.0) == doctest::Approx((T)0.0000049383));
+ CHECK(Math::pow((T)450.0, (T)0.0) == doctest::Approx((T)1.0));
+
+ CHECK(Math::is_nan(Math::log((T)-0.1)));
+ CHECK(Math::log((T)0.1) == doctest::Approx((T)-2.302585093));
+ CHECK(Math::log((T)0.5) == doctest::Approx((T)-0.6931471806));
+ CHECK(Math::log((T)1.0) == doctest::Approx((T)0.0));
+ CHECK(Math::log((T)1.5) == doctest::Approx((T)0.4054651081));
+ CHECK(Math::log((T)450.0) == doctest::Approx((T)6.1092475828));
+
+ CHECK(Math::is_nan(Math::log2((T)-0.1)));
+ CHECK(Math::log2((T)0.1) == doctest::Approx((T)-3.3219280949));
+ CHECK(Math::log2((T)0.5) == doctest::Approx((T)-1.0));
+ CHECK(Math::log2((T)1.0) == doctest::Approx((T)0.0));
+ CHECK(Math::log2((T)1.5) == doctest::Approx((T)0.5849625007));
+ CHECK(Math::log2((T)450.0) == doctest::Approx((T)8.8137811912));
+
+ CHECK(Math::exp((T)-0.1) == doctest::Approx((T)0.904837418));
+ CHECK(Math::exp((T)0.1) == doctest::Approx((T)1.1051709181));
+ CHECK(Math::exp((T)0.5) == doctest::Approx((T)1.6487212707));
+ CHECK(Math::exp((T)1.0) == doctest::Approx((T)2.7182818285));
+ CHECK(Math::exp((T)1.5) == doctest::Approx((T)4.4816890703));
+
+ CHECK(Math::is_nan(Math::sqrt((T)-0.1)));
+ CHECK(Math::sqrt((T)0.1) == doctest::Approx((T)0.316228));
+ CHECK(Math::sqrt((T)0.5) == doctest::Approx((T)0.707107));
+ CHECK(Math::sqrt((T)1.0) == doctest::Approx((T)1.0));
+ CHECK(Math::sqrt((T)1.5) == doctest::Approx((T)1.224745));
+}
+
+TEST_CASE_TEMPLATE("[Math] is_nan/is_inf", T, float, double) {
+ CHECK(!Math::is_nan((T)0.0));
+ CHECK(Math::is_nan((T)NAN));
+
+ CHECK(!Math::is_inf((T)0.0));
+ CHECK(Math::is_inf((T)INFINITY));
+}
+
+TEST_CASE_TEMPLATE("[Math] linear_to_db", T, float, double) {
+ CHECK(Math::linear_to_db((T)1.0) == doctest::Approx((T)0.0));
+ CHECK(Math::linear_to_db((T)20.0) == doctest::Approx((T)26.0206));
+ CHECK(Math::is_inf(Math::linear_to_db((T)0.0)));
+ CHECK(Math::is_nan(Math::linear_to_db((T)-20.0)));
+}
+
+TEST_CASE_TEMPLATE("[Math] db_to_linear", T, float, double) {
+ CHECK(Math::db_to_linear((T)0.0) == doctest::Approx((T)1.0));
+ CHECK(Math::db_to_linear((T)1.0) == doctest::Approx((T)1.122018));
+ CHECK(Math::db_to_linear((T)20.0) == doctest::Approx((T)10.0));
+ CHECK(Math::db_to_linear((T)-20.0) == doctest::Approx((T)0.1));
+}
+
+TEST_CASE_TEMPLATE("[Math] step_decimals", T, float, double) {
+ CHECK(Math::step_decimals((T)-0.5) == 1);
+ CHECK(Math::step_decimals((T)0) == 0);
+ CHECK(Math::step_decimals((T)1) == 0);
+ CHECK(Math::step_decimals((T)0.1) == 1);
+ CHECK(Math::step_decimals((T)0.01) == 2);
+ CHECK(Math::step_decimals((T)0.001) == 3);
+ CHECK(Math::step_decimals((T)0.0001) == 4);
+ CHECK(Math::step_decimals((T)0.00001) == 5);
+ CHECK(Math::step_decimals((T)0.000001) == 6);
+ CHECK(Math::step_decimals((T)0.0000001) == 7);
+ CHECK(Math::step_decimals((T)0.00000001) == 8);
+ CHECK(Math::step_decimals((T)0.000000001) == 9);
// Too many decimals to handle.
- CHECK(Math::step_decimals(0.0000000001) == 0);
+ CHECK(Math::step_decimals((T)0.0000000001) == 0);
}
-TEST_CASE("[Math] range_step_decimals") {
- CHECK(Math::range_step_decimals(0.000000001) == 9);
+TEST_CASE_TEMPLATE("[Math] range_step_decimals", T, float, double) {
+ CHECK(Math::range_step_decimals((T)0.000000001) == 9);
// Too many decimals to handle.
- CHECK(Math::range_step_decimals(0.0000000001) == 0);
+ CHECK(Math::range_step_decimals((T)0.0000000001) == 0);
// Should be treated as a step of 0 for use by the editor.
- CHECK(Math::range_step_decimals(0.0) == 16);
- CHECK(Math::range_step_decimals(-0.5) == 16);
+ CHECK(Math::range_step_decimals((T)0.0) == 16);
+ CHECK(Math::range_step_decimals((T)-0.5) == 16);
}
-TEST_CASE("[Math] lerp") {
- CHECK(Math::lerp(2.0, 5.0, -0.1) == doctest::Approx(1.7));
- CHECK(Math::lerp(2.0, 5.0, 0.0) == doctest::Approx(2.0));
- CHECK(Math::lerp(2.0, 5.0, 0.1) == doctest::Approx(2.3));
- CHECK(Math::lerp(2.0, 5.0, 1.0) == doctest::Approx(5.0));
- CHECK(Math::lerp(2.0, 5.0, 2.0) == doctest::Approx(8.0));
+TEST_CASE_TEMPLATE("[Math] lerp", T, float, double) {
+ CHECK(Math::lerp((T)2.0, (T)5.0, (T)-0.1) == doctest::Approx((T)1.7));
+ CHECK(Math::lerp((T)2.0, (T)5.0, (T)0.0) == doctest::Approx((T)2.0));
+ CHECK(Math::lerp((T)2.0, (T)5.0, (T)0.1) == doctest::Approx((T)2.3));
+ CHECK(Math::lerp((T)2.0, (T)5.0, (T)1.0) == doctest::Approx((T)5.0));
+ CHECK(Math::lerp((T)2.0, (T)5.0, (T)2.0) == doctest::Approx((T)8.0));
- CHECK(Math::lerp(-2.0, -5.0, -0.1) == doctest::Approx(-1.7));
- CHECK(Math::lerp(-2.0, -5.0, 0.0) == doctest::Approx(-2.0));
- CHECK(Math::lerp(-2.0, -5.0, 0.1) == doctest::Approx(-2.3));
- CHECK(Math::lerp(-2.0, -5.0, 1.0) == doctest::Approx(-5.0));
- CHECK(Math::lerp(-2.0, -5.0, 2.0) == doctest::Approx(-8.0));
+ CHECK(Math::lerp((T)-2.0, (T)-5.0, (T)-0.1) == doctest::Approx((T)-1.7));
+ CHECK(Math::lerp((T)-2.0, (T)-5.0, (T)0.0) == doctest::Approx((T)-2.0));
+ CHECK(Math::lerp((T)-2.0, (T)-5.0, (T)0.1) == doctest::Approx((T)-2.3));
+ CHECK(Math::lerp((T)-2.0, (T)-5.0, (T)1.0) == doctest::Approx((T)-5.0));
+ CHECK(Math::lerp((T)-2.0, (T)-5.0, (T)2.0) == doctest::Approx((T)-8.0));
}
-TEST_CASE("[Math] inverse_lerp") {
- CHECK(Math::inverse_lerp(2.0, 5.0, 1.7) == doctest::Approx(-0.1));
- CHECK(Math::inverse_lerp(2.0, 5.0, 2.0) == doctest::Approx(0.0));
- CHECK(Math::inverse_lerp(2.0, 5.0, 2.3) == doctest::Approx(0.1));
- CHECK(Math::inverse_lerp(2.0, 5.0, 5.0) == doctest::Approx(1.0));
- CHECK(Math::inverse_lerp(2.0, 5.0, 8.0) == doctest::Approx(2.0));
+TEST_CASE_TEMPLATE("[Math] inverse_lerp", T, float, double) {
+ CHECK(Math::inverse_lerp((T)2.0, (T)5.0, (T)1.7) == doctest::Approx((T)-0.1));
+ CHECK(Math::inverse_lerp((T)2.0, (T)5.0, (T)2.0) == doctest::Approx((T)0.0));
+ CHECK(Math::inverse_lerp((T)2.0, (T)5.0, (T)2.3) == doctest::Approx((T)0.1));
+ CHECK(Math::inverse_lerp((T)2.0, (T)5.0, (T)5.0) == doctest::Approx((T)1.0));
+ CHECK(Math::inverse_lerp((T)2.0, (T)5.0, (T)8.0) == doctest::Approx((T)2.0));
- CHECK(Math::inverse_lerp(-2.0, -5.0, -1.7) == doctest::Approx(-0.1));
- CHECK(Math::inverse_lerp(-2.0, -5.0, -2.0) == doctest::Approx(0.0));
- CHECK(Math::inverse_lerp(-2.0, -5.0, -2.3) == doctest::Approx(0.1));
- CHECK(Math::inverse_lerp(-2.0, -5.0, -5.0) == doctest::Approx(1.0));
- CHECK(Math::inverse_lerp(-2.0, -5.0, -8.0) == doctest::Approx(2.0));
+ CHECK(Math::inverse_lerp((T)-2.0, (T)-5.0, (T)-1.7) == doctest::Approx((T)-0.1));
+ CHECK(Math::inverse_lerp((T)-2.0, (T)-5.0, (T)-2.0) == doctest::Approx((T)0.0));
+ CHECK(Math::inverse_lerp((T)-2.0, (T)-5.0, (T)-2.3) == doctest::Approx((T)0.1));
+ CHECK(Math::inverse_lerp((T)-2.0, (T)-5.0, (T)-5.0) == doctest::Approx((T)1.0));
+ CHECK(Math::inverse_lerp((T)-2.0, (T)-5.0, (T)-8.0) == doctest::Approx((T)2.0));
}
-TEST_CASE("[Math] remap") {
- CHECK(Math::remap(50.0, 100.0, 200.0, 0.0, 1000.0) == doctest::Approx(-500.0));
- CHECK(Math::remap(100.0, 100.0, 200.0, 0.0, 1000.0) == doctest::Approx(0.0));
- CHECK(Math::remap(200.0, 100.0, 200.0, 0.0, 1000.0) == doctest::Approx(1000.0));
- CHECK(Math::remap(250.0, 100.0, 200.0, 0.0, 1000.0) == doctest::Approx(1500.0));
+TEST_CASE_TEMPLATE("[Math] remap", T, float, double) {
+ CHECK(Math::remap((T)50.0, (T)100.0, (T)200.0, (T)0.0, (T)1000.0) == doctest::Approx((T)-500.0));
+ CHECK(Math::remap((T)100.0, (T)100.0, (T)200.0, (T)0.0, (T)1000.0) == doctest::Approx((T)0.0));
+ CHECK(Math::remap((T)200.0, (T)100.0, (T)200.0, (T)0.0, (T)1000.0) == doctest::Approx((T)1000.0));
+ CHECK(Math::remap((T)250.0, (T)100.0, (T)200.0, (T)0.0, (T)1000.0) == doctest::Approx((T)1500.0));
- CHECK(Math::remap(-50.0, -100.0, -200.0, 0.0, 1000.0) == doctest::Approx(-500.0));
- CHECK(Math::remap(-100.0, -100.0, -200.0, 0.0, 1000.0) == doctest::Approx(0.0));
- CHECK(Math::remap(-200.0, -100.0, -200.0, 0.0, 1000.0) == doctest::Approx(1000.0));
- CHECK(Math::remap(-250.0, -100.0, -200.0, 0.0, 1000.0) == doctest::Approx(1500.0));
+ CHECK(Math::remap((T)-50.0, (T)-100.0, (T)-200.0, (T)0.0, (T)1000.0) == doctest::Approx((T)-500.0));
+ CHECK(Math::remap((T)-100.0, (T)-100.0, (T)-200.0, (T)0.0, (T)1000.0) == doctest::Approx((T)0.0));
+ CHECK(Math::remap((T)-200.0, (T)-100.0, (T)-200.0, (T)0.0, (T)1000.0) == doctest::Approx((T)1000.0));
+ CHECK(Math::remap((T)-250.0, (T)-100.0, (T)-200.0, (T)0.0, (T)1000.0) == doctest::Approx((T)1500.0));
- CHECK(Math::remap(-50.0, -100.0, -200.0, 0.0, -1000.0) == doctest::Approx(500.0));
- CHECK(Math::remap(-100.0, -100.0, -200.0, 0.0, -1000.0) == doctest::Approx(0.0));
- CHECK(Math::remap(-200.0, -100.0, -200.0, 0.0, -1000.0) == doctest::Approx(-1000.0));
- CHECK(Math::remap(-250.0, -100.0, -200.0, 0.0, -1000.0) == doctest::Approx(-1500.0));
+ CHECK(Math::remap((T)-50.0, (T)-100.0, (T)-200.0, (T)0.0, (T)-1000.0) == doctest::Approx((T)500.0));
+ CHECK(Math::remap((T)-100.0, (T)-100.0, (T)-200.0, (T)0.0, (T)-1000.0) == doctest::Approx((T)0.0));
+ CHECK(Math::remap((T)-200.0, (T)-100.0, (T)-200.0, (T)0.0, (T)-1000.0) == doctest::Approx((T)-1000.0));
+ CHECK(Math::remap((T)-250.0, (T)-100.0, (T)-200.0, (T)0.0, (T)-1000.0) == doctest::Approx((T)-1500.0));
}
-TEST_CASE("[Math] lerp_angle") {
+TEST_CASE_TEMPLATE("[Math] lerp_angle", T, float, double) {
// Counter-clockwise rotation.
- CHECK(Math::lerp_angle(0.24 * Math_TAU, 0.75 * Math_TAU, 0.5) == doctest::Approx(-0.005 * Math_TAU));
+ CHECK(Math::lerp_angle((T)0.24 * Math_TAU, 0.75 * Math_TAU, 0.5) == doctest::Approx((T)-0.005 * Math_TAU));
// Counter-clockwise rotation.
- CHECK(Math::lerp_angle(0.25 * Math_TAU, 0.75 * Math_TAU, 0.5) == doctest::Approx(0.0));
+ CHECK(Math::lerp_angle((T)0.25 * Math_TAU, 0.75 * Math_TAU, 0.5) == doctest::Approx((T)0.0));
// Clockwise rotation.
- CHECK(Math::lerp_angle(0.26 * Math_TAU, 0.75 * Math_TAU, 0.5) == doctest::Approx(0.505 * Math_TAU));
+ CHECK(Math::lerp_angle((T)0.26 * Math_TAU, 0.75 * Math_TAU, 0.5) == doctest::Approx((T)0.505 * Math_TAU));
- CHECK(Math::lerp_angle(-0.25 * Math_TAU, 1.25 * Math_TAU, 0.5) == doctest::Approx(-0.5 * Math_TAU));
- CHECK(Math::lerp_angle(0.72 * Math_TAU, 1.44 * Math_TAU, 0.96) == doctest::Approx(0.4512 * Math_TAU));
- CHECK(Math::lerp_angle(0.72 * Math_TAU, 1.44 * Math_TAU, 1.04) == doctest::Approx(0.4288 * Math_TAU));
+ CHECK(Math::lerp_angle((T)-0.25 * Math_TAU, 1.25 * Math_TAU, 0.5) == doctest::Approx((T)-0.5 * Math_TAU));
+ CHECK(Math::lerp_angle((T)0.72 * Math_TAU, 1.44 * Math_TAU, 0.96) == doctest::Approx((T)0.4512 * Math_TAU));
+ CHECK(Math::lerp_angle((T)0.72 * Math_TAU, 1.44 * Math_TAU, 1.04) == doctest::Approx((T)0.4288 * Math_TAU));
// Initial and final angles are effectively identical, so the value returned
// should always be the same regardless of the `weight` parameter.
- CHECK(Math::lerp_angle(-4 * Math_TAU, 4 * Math_TAU, -1.0) == doctest::Approx(-4.0 * Math_TAU));
- CHECK(Math::lerp_angle(-4 * Math_TAU, 4 * Math_TAU, 0.0) == doctest::Approx(-4.0 * Math_TAU));
- CHECK(Math::lerp_angle(-4 * Math_TAU, 4 * Math_TAU, 0.5) == doctest::Approx(-4.0 * Math_TAU));
- CHECK(Math::lerp_angle(-4 * Math_TAU, 4 * Math_TAU, 1.0) == doctest::Approx(-4.0 * Math_TAU));
- CHECK(Math::lerp_angle(-4 * Math_TAU, 4 * Math_TAU, 500.0) == doctest::Approx(-4.0 * Math_TAU));
+ CHECK(Math::lerp_angle((T)-4 * Math_TAU, 4 * Math_TAU, -1.0) == doctest::Approx((T)-4.0 * Math_TAU));
+ CHECK(Math::lerp_angle((T)-4 * Math_TAU, 4 * Math_TAU, 0.0) == doctest::Approx((T)-4.0 * Math_TAU));
+ CHECK(Math::lerp_angle((T)-4 * Math_TAU, 4 * Math_TAU, 0.5) == doctest::Approx((T)-4.0 * Math_TAU));
+ CHECK(Math::lerp_angle((T)-4 * Math_TAU, 4 * Math_TAU, 1.0) == doctest::Approx((T)-4.0 * Math_TAU));
+ CHECK(Math::lerp_angle((T)-4 * Math_TAU, 4 * Math_TAU, 500.0) == doctest::Approx((T)-4.0 * Math_TAU));
}
-TEST_CASE("[Math] move_toward") {
- CHECK(Math::move_toward(2.0, 5.0, -1.0) == doctest::Approx(1.0));
- CHECK(Math::move_toward(2.0, 5.0, 2.5) == doctest::Approx(4.5));
- CHECK(Math::move_toward(2.0, 5.0, 4.0) == doctest::Approx(5.0));
- CHECK(Math::move_toward(-2.0, -5.0, -1.0) == doctest::Approx(-1.0));
- CHECK(Math::move_toward(-2.0, -5.0, 2.5) == doctest::Approx(-4.5));
- CHECK(Math::move_toward(-2.0, -5.0, 4.0) == doctest::Approx(-5.0));
+TEST_CASE_TEMPLATE("[Math] move_toward", T, float, double) {
+ CHECK(Math::move_toward(2.0, 5.0, -1.0) == doctest::Approx((T)1.0));
+ CHECK(Math::move_toward(2.0, 5.0, 2.5) == doctest::Approx((T)4.5));
+ CHECK(Math::move_toward(2.0, 5.0, 4.0) == doctest::Approx((T)5.0));
+ CHECK(Math::move_toward(-2.0, -5.0, -1.0) == doctest::Approx((T)-1.0));
+ CHECK(Math::move_toward(-2.0, -5.0, 2.5) == doctest::Approx((T)-4.5));
+ CHECK(Math::move_toward(-2.0, -5.0, 4.0) == doctest::Approx((T)-5.0));
}
-TEST_CASE("[Math] smoothstep") {
- CHECK(Math::smoothstep(0.0, 2.0, -5.0) == doctest::Approx(0.0));
- CHECK(Math::smoothstep(0.0, 2.0, 0.5) == doctest::Approx(0.15625));
- CHECK(Math::smoothstep(0.0, 2.0, 1.0) == doctest::Approx(0.5));
- CHECK(Math::smoothstep(0.0, 2.0, 2.0) == doctest::Approx(1.0));
+TEST_CASE_TEMPLATE("[Math] smoothstep", T, float, double) {
+ CHECK(Math::smoothstep((T)0.0, (T)2.0, (T)-5.0) == doctest::Approx((T)0.0));
+ CHECK(Math::smoothstep((T)0.0, (T)2.0, (T)0.5) == doctest::Approx((T)0.15625));
+ CHECK(Math::smoothstep((T)0.0, (T)2.0, (T)1.0) == doctest::Approx((T)0.5));
+ CHECK(Math::smoothstep((T)0.0, (T)2.0, (T)2.0) == doctest::Approx((T)1.0));
}
TEST_CASE("[Math] ease") {
@@ -429,34 +419,34 @@ TEST_CASE("[Math] larger_prime") {
ERR_PRINT_ON;
}
-TEST_CASE("[Math] fmod") {
- CHECK(Math::fmod(-2.0, 0.3) == doctest::Approx(-0.2));
- CHECK(Math::fmod(0.0, 0.3) == doctest::Approx(0.0));
- CHECK(Math::fmod(2.0, 0.3) == doctest::Approx(0.2));
+TEST_CASE_TEMPLATE("[Math] fmod", T, float, double) {
+ CHECK(Math::fmod((T)-2.0, (T)0.3) == doctest::Approx((T)-0.2));
+ CHECK(Math::fmod((T)0.0, (T)0.3) == doctest::Approx((T)0.0));
+ CHECK(Math::fmod((T)2.0, (T)0.3) == doctest::Approx((T)0.2));
- CHECK(Math::fmod(-2.0, -0.3) == doctest::Approx(-0.2));
- CHECK(Math::fmod(0.0, -0.3) == doctest::Approx(0.0));
- CHECK(Math::fmod(2.0, -0.3) == doctest::Approx(0.2));
+ CHECK(Math::fmod((T)-2.0, (T)-0.3) == doctest::Approx((T)-0.2));
+ CHECK(Math::fmod((T)0.0, (T)-0.3) == doctest::Approx((T)0.0));
+ CHECK(Math::fmod((T)2.0, (T)-0.3) == doctest::Approx((T)0.2));
}
-TEST_CASE("[Math] fposmod") {
- CHECK(Math::fposmod(-2.0, 0.3) == doctest::Approx(0.1));
- CHECK(Math::fposmod(0.0, 0.3) == doctest::Approx(0.0));
- CHECK(Math::fposmod(2.0, 0.3) == doctest::Approx(0.2));
+TEST_CASE_TEMPLATE("[Math] fposmod", T, float, double) {
+ CHECK(Math::fposmod((T)-2.0, (T)0.3) == doctest::Approx((T)0.1));
+ CHECK(Math::fposmod((T)0.0, (T)0.3) == doctest::Approx((T)0.0));
+ CHECK(Math::fposmod((T)2.0, (T)0.3) == doctest::Approx((T)0.2));
- CHECK(Math::fposmod(-2.0, -0.3) == doctest::Approx(-0.2));
- CHECK(Math::fposmod(0.0, -0.3) == doctest::Approx(0.0));
- CHECK(Math::fposmod(2.0, -0.3) == doctest::Approx(-0.1));
+ CHECK(Math::fposmod((T)-2.0, (T)-0.3) == doctest::Approx((T)-0.2));
+ CHECK(Math::fposmod((T)0.0, (T)-0.3) == doctest::Approx((T)0.0));
+ CHECK(Math::fposmod((T)2.0, (T)-0.3) == doctest::Approx((T)-0.1));
}
-TEST_CASE("[Math] fposmodp") {
- CHECK(Math::fposmodp(-2.0, 0.3) == doctest::Approx(0.1));
- CHECK(Math::fposmodp(0.0, 0.3) == doctest::Approx(0.0));
- CHECK(Math::fposmodp(2.0, 0.3) == doctest::Approx(0.2));
+TEST_CASE_TEMPLATE("[Math] fposmodp", T, float, double) {
+ CHECK(Math::fposmodp((T)-2.0, (T)0.3) == doctest::Approx((T)0.1));
+ CHECK(Math::fposmodp((T)0.0, (T)0.3) == doctest::Approx((T)0.0));
+ CHECK(Math::fposmodp((T)2.0, (T)0.3) == doctest::Approx((T)0.2));
- CHECK(Math::fposmodp(-2.0, -0.3) == doctest::Approx(-0.5));
- CHECK(Math::fposmodp(0.0, -0.3) == doctest::Approx(0.0));
- CHECK(Math::fposmodp(2.0, -0.3) == doctest::Approx(0.2));
+ CHECK(Math::fposmodp((T)-2.0, (T)-0.3) == doctest::Approx((T)-0.5));
+ CHECK(Math::fposmodp((T)0.0, (T)-0.3) == doctest::Approx((T)0.0));
+ CHECK(Math::fposmodp((T)2.0, (T)-0.3) == doctest::Approx((T)0.2));
}
TEST_CASE("[Math] posmod") {
@@ -475,80 +465,83 @@ TEST_CASE("[Math] wrapi") {
CHECK(Math::wrapi(300'000'000'000, -20, 160) == 120);
}
-TEST_CASE("[Math] wrapf") {
- CHECK(Math::wrapf(-30.0, -20.0, 160.0) == doctest::Approx(150.0));
- CHECK(Math::wrapf(30.0, -2.0, 160.0) == doctest::Approx(30.0));
- CHECK(Math::wrapf(300.0, -20.0, 160.0) == doctest::Approx(120.0));
- CHECK(Math::wrapf(300'000'000'000.0, -20.0, 160.0) == doctest::Approx(120.0));
+TEST_CASE_TEMPLATE("[Math] wrapf", T, float, double) {
+ CHECK(Math::wrapf((T)-30.0, (T)-20.0, (T)160.0) == doctest::Approx((T)150.0));
+ CHECK(Math::wrapf((T)30.0, (T)-2.0, (T)160.0) == doctest::Approx((T)30.0));
+ CHECK(Math::wrapf((T)300.0, (T)-20.0, (T)160.0) == doctest::Approx((T)120.0));
+
+ CHECK(Math::wrapf(300'000'000'000.0, -20.0, 160.0) == doctest::Approx((T)120.0));
+ // float's precision is too low for 300'000'000'000.0, so we reduce it by a factor of 1000.
+ CHECK(Math::wrapf((float)300'000'000.0, (float)-20.0, (float)160.0) == doctest::Approx((T)128.0));
}
-TEST_CASE("[Math] fract") {
- CHECK(Math::fract(1.0) == doctest::Approx(0.0));
- CHECK(Math::fract(77.8) == doctest::Approx(0.8));
- CHECK(Math::fract(-10.1) == doctest::Approx(0.9));
+TEST_CASE_TEMPLATE("[Math] fract", T, float, double) {
+ CHECK(Math::fract((T)1.0) == doctest::Approx((T)0.0));
+ CHECK(Math::fract((T)77.8) == doctest::Approx((T)0.8));
+ CHECK(Math::fract((T)-10.1) == doctest::Approx((T)0.9));
}
-TEST_CASE("[Math] pingpong") {
- CHECK(Math::pingpong(0.0, 0.0) == doctest::Approx(0.0));
- CHECK(Math::pingpong(1.0, 1.0) == doctest::Approx(1.0));
- CHECK(Math::pingpong(0.5, 2.0) == doctest::Approx(0.5));
- CHECK(Math::pingpong(3.5, 2.0) == doctest::Approx(0.5));
- CHECK(Math::pingpong(11.5, 2.0) == doctest::Approx(0.5));
- CHECK(Math::pingpong(-2.5, 2.0) == doctest::Approx(1.5));
+TEST_CASE_TEMPLATE("[Math] pingpong", T, float, double) {
+ CHECK(Math::pingpong((T)0.0, (T)0.0) == doctest::Approx((T)0.0));
+ CHECK(Math::pingpong((T)1.0, (T)1.0) == doctest::Approx((T)1.0));
+ CHECK(Math::pingpong((T)0.5, (T)2.0) == doctest::Approx((T)0.5));
+ CHECK(Math::pingpong((T)3.5, (T)2.0) == doctest::Approx((T)0.5));
+ CHECK(Math::pingpong((T)11.5, (T)2.0) == doctest::Approx((T)0.5));
+ CHECK(Math::pingpong((T)-2.5, (T)2.0) == doctest::Approx((T)1.5));
}
-TEST_CASE("[Math] deg_to_rad/rad_to_deg") {
- CHECK(Math::deg_to_rad(180.0) == doctest::Approx(Math_PI));
- CHECK(Math::deg_to_rad(-27.0) == doctest::Approx(-0.471239));
+TEST_CASE_TEMPLATE("[Math] deg_to_rad/rad_to_deg", T, float, double) {
+ CHECK(Math::deg_to_rad((T)180.0) == doctest::Approx((T)Math_PI));
+ CHECK(Math::deg_to_rad((T)-27.0) == doctest::Approx((T)-0.471239));
- CHECK(Math::rad_to_deg(Math_PI) == doctest::Approx(180.0));
- CHECK(Math::rad_to_deg(-1.5) == doctest::Approx(-85.94366927));
+ CHECK(Math::rad_to_deg((T)Math_PI) == doctest::Approx((T)180.0));
+ CHECK(Math::rad_to_deg((T)-1.5) == doctest::Approx((T)-85.94366927));
}
-TEST_CASE("[Math] cubic_interpolate") {
- CHECK(Math::cubic_interpolate(0.2, 0.8, 0.0, 1.0, 0.0) == doctest::Approx(0.2));
- CHECK(Math::cubic_interpolate(0.2, 0.8, 0.0, 1.0, 0.25) == doctest::Approx(0.33125));
- CHECK(Math::cubic_interpolate(0.2, 0.8, 0.0, 1.0, 0.5) == doctest::Approx(0.5));
- CHECK(Math::cubic_interpolate(0.2, 0.8, 0.0, 1.0, 0.75) == doctest::Approx(0.66875));
- CHECK(Math::cubic_interpolate(0.2, 0.8, 0.0, 1.0, 1.0) == doctest::Approx(0.8));
+TEST_CASE_TEMPLATE("[Math] cubic_interpolate", T, float, double) {
+ CHECK(Math::cubic_interpolate((T)0.2, (T)0.8, (T)0.0, (T)1.0, (T)0.0) == doctest::Approx((T)0.2));
+ CHECK(Math::cubic_interpolate((T)0.2, (T)0.8, (T)0.0, (T)1.0, (T)0.25) == doctest::Approx((T)0.33125));
+ CHECK(Math::cubic_interpolate((T)0.2, (T)0.8, (T)0.0, (T)1.0, (T)0.5) == doctest::Approx((T)0.5));
+ CHECK(Math::cubic_interpolate((T)0.2, (T)0.8, (T)0.0, (T)1.0, (T)0.75) == doctest::Approx((T)0.66875));
+ CHECK(Math::cubic_interpolate((T)0.2, (T)0.8, (T)0.0, (T)1.0, (T)1.0) == doctest::Approx((T)0.8));
- CHECK(Math::cubic_interpolate(20.2, 30.1, -100.0, 32.0, -50.0) == doctest::Approx(-6662732.3));
- CHECK(Math::cubic_interpolate(20.2, 30.1, -100.0, 32.0, -5.0) == doctest::Approx(-9356.3));
- CHECK(Math::cubic_interpolate(20.2, 30.1, -100.0, 32.0, 0.0) == doctest::Approx(20.2));
- CHECK(Math::cubic_interpolate(20.2, 30.1, -100.0, 32.0, 1.0) == doctest::Approx(30.1));
- CHECK(Math::cubic_interpolate(20.2, 30.1, -100.0, 32.0, 4.0) == doctest::Approx(1853.2));
+ CHECK(Math::cubic_interpolate((T)20.2, (T)30.1, (T)-100.0, (T)32.0, (T)-50.0) == doctest::Approx((T)-6662732.3));
+ CHECK(Math::cubic_interpolate((T)20.2, (T)30.1, (T)-100.0, (T)32.0, (T)-5.0) == doctest::Approx((T)-9356.3));
+ CHECK(Math::cubic_interpolate((T)20.2, (T)30.1, (T)-100.0, (T)32.0, (T)0.0) == doctest::Approx((T)20.2));
+ CHECK(Math::cubic_interpolate((T)20.2, (T)30.1, (T)-100.0, (T)32.0, (T)1.0) == doctest::Approx((T)30.1));
+ CHECK(Math::cubic_interpolate((T)20.2, (T)30.1, (T)-100.0, (T)32.0, (T)4.0) == doctest::Approx((T)1853.2));
}
-TEST_CASE("[Math] cubic_interpolate_angle") {
- CHECK(Math::cubic_interpolate_angle(Math_PI * (1.0 / 6.0), Math_PI * (5.0 / 6.0), 0.0, Math_PI, 0.0) == doctest::Approx(Math_PI * (1.0 / 6.0)));
- CHECK(Math::cubic_interpolate_angle(Math_PI * (1.0 / 6.0), Math_PI * (5.0 / 6.0), 0.0, Math_PI, 0.25) == doctest::Approx(0.973566));
- CHECK(Math::cubic_interpolate_angle(Math_PI * (1.0 / 6.0), Math_PI * (5.0 / 6.0), 0.0, Math_PI, 0.5) == doctest::Approx(Math_PI / 2.0));
- CHECK(Math::cubic_interpolate_angle(Math_PI * (1.0 / 6.0), Math_PI * (5.0 / 6.0), 0.0, Math_PI, 0.75) == doctest::Approx(2.16803));
- CHECK(Math::cubic_interpolate_angle(Math_PI * (1.0 / 6.0), Math_PI * (5.0 / 6.0), 0.0, Math_PI, 1.0) == doctest::Approx(Math_PI * (5.0 / 6.0)));
+TEST_CASE_TEMPLATE("[Math] cubic_interpolate_angle", T, float, double) {
+ CHECK(Math::cubic_interpolate_angle((T)(Math_PI * (1.0 / 6.0)), (T)(Math_PI * (5.0 / 6.0)), (T)0.0, (T)Math_PI, (T)0.0) == doctest::Approx((T)Math_PI * (1.0 / 6.0)));
+ CHECK(Math::cubic_interpolate_angle((T)(Math_PI * (1.0 / 6.0)), (T)(Math_PI * (5.0 / 6.0)), (T)0.0, (T)Math_PI, (T)0.25) == doctest::Approx((T)0.973566));
+ CHECK(Math::cubic_interpolate_angle((T)(Math_PI * (1.0 / 6.0)), (T)(Math_PI * (5.0 / 6.0)), (T)0.0, (T)Math_PI, (T)0.5) == doctest::Approx((T)Math_PI / 2.0));
+ CHECK(Math::cubic_interpolate_angle((T)(Math_PI * (1.0 / 6.0)), (T)(Math_PI * (5.0 / 6.0)), (T)0.0, (T)Math_PI, (T)0.75) == doctest::Approx((T)2.16803));
+ CHECK(Math::cubic_interpolate_angle((T)(Math_PI * (1.0 / 6.0)), (T)(Math_PI * (5.0 / 6.0)), (T)0.0, (T)Math_PI, (T)1.0) == doctest::Approx((T)Math_PI * (5.0 / 6.0)));
}
-TEST_CASE("[Math] cubic_interpolate_in_time") {
- CHECK(Math::cubic_interpolate_in_time(0.2, 0.8, 0.0, 1.0, 0.0, 0.5, 0.0, 1.0) == doctest::Approx(0.0));
- CHECK(Math::cubic_interpolate_in_time(0.2, 0.8, 0.0, 1.0, 0.25, 0.5, 0.0, 1.0) == doctest::Approx(0.1625));
- CHECK(Math::cubic_interpolate_in_time(0.2, 0.8, 0.0, 1.0, 0.5, 0.5, 0.0, 1.0) == doctest::Approx(0.4));
- CHECK(Math::cubic_interpolate_in_time(0.2, 0.8, 0.0, 1.0, 0.75, 0.5, 0.0, 1.0) == doctest::Approx(0.6375));
- CHECK(Math::cubic_interpolate_in_time(0.2, 0.8, 0.0, 1.0, 1.0, 0.5, 0.0, 1.0) == doctest::Approx(0.8));
+TEST_CASE_TEMPLATE("[Math] cubic_interpolate_in_time", T, float, double) {
+ CHECK(Math::cubic_interpolate_in_time((T)0.2, (T)0.8, (T)0.0, (T)1.0, (T)0.0, (T)0.5, (T)0.0, (T)1.0) == doctest::Approx((T)0.0));
+ CHECK(Math::cubic_interpolate_in_time((T)0.2, (T)0.8, (T)0.0, (T)1.0, (T)0.25, (T)0.5, (T)0.0, (T)1.0) == doctest::Approx((T)0.1625));
+ CHECK(Math::cubic_interpolate_in_time((T)0.2, (T)0.8, (T)0.0, (T)1.0, (T)0.5, (T)0.5, (T)0.0, (T)1.0) == doctest::Approx((T)0.4));
+ CHECK(Math::cubic_interpolate_in_time((T)0.2, (T)0.8, (T)0.0, (T)1.0, (T)0.75, (T)0.5, (T)0.0, (T)1.0) == doctest::Approx((T)0.6375));
+ CHECK(Math::cubic_interpolate_in_time((T)0.2, (T)0.8, (T)0.0, (T)1.0, (T)1.0, (T)0.5, (T)0.0, (T)1.0) == doctest::Approx((T)0.8));
}
-TEST_CASE("[Math] cubic_interpolate_angle_in_time") {
- CHECK(Math::cubic_interpolate_angle_in_time(Math_PI * (1.0 / 6.0), Math_PI * (5.0 / 6.0), 0.0, Math_PI, 0.0, 0.5, 0.0, 1.0) == doctest::Approx(0.0));
- CHECK(Math::cubic_interpolate_angle_in_time(Math_PI * (1.0 / 6.0), Math_PI * (5.0 / 6.0), 0.0, Math_PI, 0.25, 0.5, 0.0, 1.0) == doctest::Approx(0.494964));
- CHECK(Math::cubic_interpolate_angle_in_time(Math_PI * (1.0 / 6.0), Math_PI * (5.0 / 6.0), 0.0, Math_PI, 0.5, 0.5, 0.0, 1.0) == doctest::Approx(1.27627));
- CHECK(Math::cubic_interpolate_angle_in_time(Math_PI * (1.0 / 6.0), Math_PI * (5.0 / 6.0), 0.0, Math_PI, 0.75, 0.5, 0.0, 1.0) == doctest::Approx(2.07394));
- CHECK(Math::cubic_interpolate_angle_in_time(Math_PI * (1.0 / 6.0), Math_PI * (5.0 / 6.0), 0.0, Math_PI, 1.0, 0.5, 0.0, 1.0) == doctest::Approx(Math_PI * (5.0 / 6.0)));
+TEST_CASE_TEMPLATE("[Math] cubic_interpolate_angle_in_time", T, float, double) {
+ CHECK(Math::cubic_interpolate_angle_in_time((T)(Math_PI * (1.0 / 6.0)), (T)(Math_PI * (5.0 / 6.0)), (T)0.0, (T)Math_PI, (T)0.0, (T)0.5, (T)0.0, (T)1.0) == doctest::Approx((T)0.0));
+ CHECK(Math::cubic_interpolate_angle_in_time((T)(Math_PI * (1.0 / 6.0)), (T)(Math_PI * (5.0 / 6.0)), (T)0.0, (T)Math_PI, (T)0.25, (T)0.5, (T)0.0, (T)1.0) == doctest::Approx((T)0.494964));
+ CHECK(Math::cubic_interpolate_angle_in_time((T)(Math_PI * (1.0 / 6.0)), (T)(Math_PI * (5.0 / 6.0)), (T)0.0, (T)Math_PI, (T)0.5, (T)0.5, (T)0.0, (T)1.0) == doctest::Approx((T)1.27627));
+ CHECK(Math::cubic_interpolate_angle_in_time((T)(Math_PI * (1.0 / 6.0)), (T)(Math_PI * (5.0 / 6.0)), (T)0.0, (T)Math_PI, (T)0.75, (T)0.5, (T)0.0, (T)1.0) == doctest::Approx((T)2.07394));
+ CHECK(Math::cubic_interpolate_angle_in_time((T)(Math_PI * (1.0 / 6.0)), (T)(Math_PI * (5.0 / 6.0)), (T)0.0, (T)Math_PI, (T)1.0, (T)0.5, (T)0.0, (T)1.0) == doctest::Approx((T)Math_PI * (5.0 / 6.0)));
}
-TEST_CASE("[Math] bezier_interpolate") {
- CHECK(Math::bezier_interpolate(0.0, 0.2, 0.8, 1.0, 0.0) == doctest::Approx(0.0));
- CHECK(Math::bezier_interpolate(0.0, 0.2, 0.8, 1.0, 0.25) == doctest::Approx(0.2125));
- CHECK(Math::bezier_interpolate(0.0, 0.2, 0.8, 1.0, 0.5) == doctest::Approx(0.5));
- CHECK(Math::bezier_interpolate(0.0, 0.2, 0.8, 1.0, 0.75) == doctest::Approx(0.7875));
- CHECK(Math::bezier_interpolate(0.0, 0.2, 0.8, 1.0, 1.0) == doctest::Approx(1.0));
+TEST_CASE_TEMPLATE("[Math] bezier_interpolate", T, float, double) {
+ CHECK(Math::bezier_interpolate((T)0.0, (T)0.2, (T)0.8, (T)1.0, (T)0.0) == doctest::Approx((T)0.0));
+ CHECK(Math::bezier_interpolate((T)0.0, (T)0.2, (T)0.8, (T)1.0, (T)0.25) == doctest::Approx((T)0.2125));
+ CHECK(Math::bezier_interpolate((T)0.0, (T)0.2, (T)0.8, (T)1.0, (T)0.5) == doctest::Approx((T)0.5));
+ CHECK(Math::bezier_interpolate((T)0.0, (T)0.2, (T)0.8, (T)1.0, (T)0.75) == doctest::Approx((T)0.7875));
+ CHECK(Math::bezier_interpolate((T)0.0, (T)0.2, (T)0.8, (T)1.0, (T)1.0) == doctest::Approx((T)1.0));
}
} // namespace TestMath
diff --git a/tests/core/math/test_vector2i.h b/tests/core/math/test_vector2i.h
index c7a0dccdcc..9ee844ffa8 100644
--- a/tests/core/math/test_vector2i.h
+++ b/tests/core/math/test_vector2i.h
@@ -131,12 +131,16 @@ TEST_CASE("[Vector2i] Other methods") {
"Vector2i aspect should work as expected.");
CHECK_MESSAGE(
- Vector2i(1, 2) == vector.min(Vector2i(3, 2)),
+ vector.min(Vector2i(3, 2)) == Vector2i(1, 2),
"Vector2i min should return expected value.");
CHECK_MESSAGE(
- Vector2i(5, 3) == vector.max(Vector2i(5, 2)),
+ vector.max(Vector2i(5, 2)) == Vector2i(5, 3),
"Vector2i max should return expected value.");
+
+ CHECK_MESSAGE(
+ vector.snapped(Vector2i(4, 2)) == Vector2i(0, 4),
+ "Vector2i snapped should work as expected.");
}
TEST_CASE("[Vector2i] Abs and sign methods") {
diff --git a/tests/core/math/test_vector3i.h b/tests/core/math/test_vector3i.h
index 56578f99eb..45240bd2ff 100644
--- a/tests/core/math/test_vector3i.h
+++ b/tests/core/math/test_vector3i.h
@@ -127,6 +127,14 @@ TEST_CASE("[Vector3i] Operators") {
"Vector3i constructed from Vector3 should work as expected.");
}
+TEST_CASE("[Vector3i] Other methods") {
+ const Vector3i vector = Vector3i(1, 3, -7);
+
+ CHECK_MESSAGE(
+ vector.snapped(Vector3i(4, 2, 5)) == Vector3i(0, 4, -5),
+ "Vector3i snapped should work as expected.");
+}
+
TEST_CASE("[Vector3i] Abs and sign methods") {
const Vector3i vector1 = Vector3i(1, 3, 5);
const Vector3i vector2 = Vector3i(1, -3, -5);
diff --git a/tests/core/math/test_vector4i.h b/tests/core/math/test_vector4i.h
index 30d38607dd..8a9522f9cc 100644
--- a/tests/core/math/test_vector4i.h
+++ b/tests/core/math/test_vector4i.h
@@ -130,6 +130,14 @@ TEST_CASE("[Vector4i] Operators") {
"Vector4i constructed from Vector4 should work as expected.");
}
+TEST_CASE("[Vector3i] Other methods") {
+ const Vector4i vector = Vector4i(1, 3, -7, 13);
+
+ CHECK_MESSAGE(
+ vector.snapped(Vector4i(4, 2, 5, 8)) == Vector4i(0, 4, -5, 16),
+ "Vector4i snapped 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);
diff --git a/tests/core/os/test_os.h b/tests/core/os/test_os.h
index c46da5e156..086f0b9b0c 100644
--- a/tests/core/os/test_os.h
+++ b/tests/core/os/test_os.h
@@ -97,14 +97,14 @@ TEST_CASE("[OS] Feature tags") {
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.");
+ !OS::get_singleton()->has_feature("template"),
+ "The binary does not have the \"template\" feature tag.");
CHECK_MESSAGE(
- OS::get_singleton()->has_feature("debug"),
- "The binary has the \"debug\" feature tag.");
+ !OS::get_singleton()->has_feature("template_debug"),
+ "The binary does not have the \"template_debug\" feature tag.");
CHECK_MESSAGE(
- !OS::get_singleton()->has_feature("release"),
- "The binary does not have the \"release\" feature tag.");
+ !OS::get_singleton()->has_feature("template_release"),
+ "The binary does not have the \"template_release\" feature tag.");
}
TEST_CASE("[OS] Process ID") {
diff --git a/tests/core/string/test_string.h b/tests/core/string/test_string.h
index 7e4e3aa9f0..659d451d76 100644
--- a/tests/core/string/test_string.h
+++ b/tests/core/string/test_string.h
@@ -226,6 +226,12 @@ TEST_CASE("[String] Comparisons (equal)") {
CHECK(s == U"Test Compare");
CHECK(s == L"Test Compare");
CHECK(s == String("Test Compare"));
+
+ CharString empty = "";
+ CharString cs = "Test Compare";
+ CHECK(!(empty == cs));
+ CHECK(!(cs == empty));
+ CHECK(cs == CharString("Test Compare"));
}
TEST_CASE("[String] Comparisons (not equal)") {
@@ -516,21 +522,22 @@ TEST_CASE("[String] Splitting") {
s = "1.2;2.3 4.5";
const double slices_d[3] = { 1.2, 2.3, 4.5 };
- Vector<float> f;
- f = s.split_floats(";");
- CHECK(f.size() == 2);
- for (int i = 0; i < f.size(); i++) {
- CHECK(ABS(f[i] - slices_d[i]) <= 0.00001);
+ Vector<double> d_arr;
+ d_arr = s.split_floats(";");
+ CHECK(d_arr.size() == 2);
+ for (int i = 0; i < d_arr.size(); i++) {
+ CHECK(ABS(d_arr[i] - slices_d[i]) <= 0.00001);
}
Vector<String> keys;
keys.push_back(";");
keys.push_back(" ");
- f = s.split_floats_mk(keys);
- CHECK(f.size() == 3);
- for (int i = 0; i < f.size(); i++) {
- CHECK(ABS(f[i] - slices_d[i]) <= 0.00001);
+ Vector<float> f_arr;
+ f_arr = s.split_floats_mk(keys);
+ CHECK(f_arr.size() == 3);
+ for (int i = 0; i < f_arr.size(); i++) {
+ CHECK(ABS(f_arr[i] - slices_d[i]) <= 0.00001);
}
s = "1;2 4";
diff --git a/tests/core/variant/test_dictionary.h b/tests/core/variant/test_dictionary.h
index c98434d42c..0c87f11ed7 100644
--- a/tests/core/variant/test_dictionary.h
+++ b/tests/core/variant/test_dictionary.h
@@ -64,6 +64,19 @@ TEST_CASE("[Dictionary] Assignment using bracket notation ([])") {
map["World!"] = 4;
CHECK(int(map["World!"]) == 4);
+ map[StringName("HelloName")] = 6;
+ CHECK(int(map[StringName("HelloName")]) == 6);
+ // Check that StringName key is converted to String.
+ CHECK(int(map.find_key(6).get_type()) == Variant::STRING);
+ map[StringName("HelloName")] = 7;
+ CHECK(int(map[StringName("HelloName")]) == 7);
+
+ // Test String and StringName are equivalent.
+ map[StringName("Hello")] = 8;
+ CHECK(int(map["Hello"]) == 8);
+ map["Hello"] = 9;
+ CHECK(int(map[StringName("Hello")]) == 9);
+
// Test non-string keys, since keys can be of any Variant type.
map[12345] = -5;
CHECK(int(map[12345]) == -5);
diff --git a/tests/python_build/fixtures/gles3/vertex_fragment_expected_full.glsl b/tests/python_build/fixtures/gles3/vertex_fragment_expected_full.glsl
index 7bf56e73cd..58ddd08cdd 100644
--- a/tests/python_build/fixtures/gles3/vertex_fragment_expected_full.glsl
+++ b/tests/python_build/fixtures/gles3/vertex_fragment_expected_full.glsl
@@ -18,7 +18,7 @@ public:
DISABLE_LIGHTING=1,
};
- _FORCE_INLINE_ void version_bind_shader(RID p_version,ShaderVariant p_variant,uint64_t p_specialization=0) { _version_bind_shader(p_version,p_variant,p_specialization); }
+ _FORCE_INLINE_ bool version_bind_shader(RID p_version,ShaderVariant p_variant,uint64_t p_specialization=0) { return _version_bind_shader(p_version,p_variant,p_specialization); }
protected:
@@ -35,13 +35,14 @@ protected:
{"DISABLE_LIGHTING",false},
};
+ static const Feedback* _feedbacks=nullptr;
static const char _vertex_code[]={
10,112,114,101,99,105,115,105,111,110,32,104,105,103,104,112,32,102,108,111,97,116,59,10,112,114,101,99,105,115,105,111,110,32,104,105,103,104,112,32,105,110,116,59,10,10,108,97,121,111,117,116,40,108,111,99,97,116,105,111,110,32,61,32,48,41,32,105,110,32,104,105,103,104,112,32,118,101,99,51,32,118,101,114,116,101,120,59,10,10,111,117,116,32,104,105,103,104,112,32,118,101,99,52,32,112,111,115,105,116,105,111,110,95,105,110,116,101,114,112,59,10,10,118,111,105,100,32,109,97,105,110,40,41,32,123,10,9,112,111,115,105,116,105,111,110,95,105,110,116,101,114,112,32,61,32,118,101,99,52,40,118,101,114,116,101,120,46,120,44,49,44,48,44,49,41,59,10,125,10,10, 0};
static const char _fragment_code[]={
10,112,114,101,99,105,115,105,111,110,32,104,105,103,104,112,32,102,108,111,97,116,59,10,112,114,101,99,105,115,105,111,110,32,104,105,103,104,112,32,105,110,116,59,10,10,105,110,32,104,105,103,104,112,32,118,101,99,52,32,112,111,115,105,116,105,111,110,95,105,110,116,101,114,112,59,10,10,118,111,105,100,32,109,97,105,110,40,41,32,123,10,9,104,105,103,104,112,32,102,108,111,97,116,32,100,101,112,116,104,32,61,32,40,40,112,111,115,105,116,105,111,110,95,105,110,116,101,114,112,46,122,32,47,32,112,111,115,105,116,105,111,110,95,105,110,116,101,114,112,46,119,41,32,43,32,49,46,48,41,59,10,9,102,114,97,103,95,99,111,108,111,114,32,61,32,118,101,99,52,40,100,101,112,116,104,41,59,10,125,10, 0};
- _setup(_vertex_code,_fragment_code,"VertexFragmentShaderGLES3",0,_uniform_strings,0,_ubo_pairs,0,_texunit_pairs,1,_spec_pairs,1,_variant_defines);
+ _setup(_vertex_code,_fragment_code,"VertexFragmentShaderGLES3",0,_uniform_strings,0,_ubo_pairs,0,_feedbacks,0,_texunit_pairs,1,_spec_pairs,1,_variant_defines);
}
};
diff --git a/tests/python_build/fixtures/gles3/vertex_fragment_expected_parts.json b/tests/python_build/fixtures/gles3/vertex_fragment_expected_parts.json
index eaeb5981c0..5ac8092ad0 100644
--- a/tests/python_build/fixtures/gles3/vertex_fragment_expected_parts.json
+++ b/tests/python_build/fixtures/gles3/vertex_fragment_expected_parts.json
@@ -31,6 +31,7 @@
"texunit_names": [],
"ubos": [],
"ubo_names": [],
+ "feedbacks": [],
"vertex_included_files": [],
"fragment_included_files": [],
"reading": "fragment",
diff --git a/tests/scene/test_arraymesh.h b/tests/scene/test_arraymesh.h
index fc23adcd06..a11916fbd0 100644
--- a/tests/scene/test_arraymesh.h
+++ b/tests/scene/test_arraymesh.h
@@ -82,7 +82,9 @@ TEST_CASE("[SceneTree][ArrayMesh] Adding and modifying blendshapes.") {
cylinder->create_mesh_array(cylinder_array, 3.f, 3.f, 5.f);
mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, cylinder_array);
+ ERR_PRINT_OFF
mesh->add_blend_shape(name_a);
+ ERR_PRINT_ON
CHECK(mesh->get_blend_shape_count() == 0);
}
@@ -121,7 +123,9 @@ TEST_CASE("[SceneTree][ArrayMesh] Adding and modifying blendshapes.") {
cylinder->create_mesh_array(cylinder_array, 3.f, 3.f, 5.f);
mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, cylinder_array);
+ ERR_PRINT_OFF
mesh->clear_blend_shapes();
+ ERR_PRINT_ON
CHECK(mesh->get_blend_shape_count() == 2);
}
diff --git a/tests/scene/test_bit_map.h b/tests/scene/test_bit_map.h
index aca7e5fe22..a8ee7505ec 100644
--- a/tests/scene/test_bit_map.h
+++ b/tests/scene/test_bit_map.h
@@ -49,6 +49,8 @@ TEST_CASE("[BitMap] Create bit map") {
CHECK(bit_map.get_size() == Size2i(256, 512));
CHECK_MESSAGE(bit_map.get_true_bit_count() == 0, "This will go through the entire bitmask inside of bitmap, thus hopefully checking if the bitmask was correctly set up.");
+ ERR_PRINT_OFF
+
dim = Size2i(0, 256);
bit_map.create(dim);
CHECK_MESSAGE(bit_map.get_size() == Size2i(256, 512), "We should still have the same dimensions as before, because the new dimension is invalid.");
@@ -60,6 +62,8 @@ TEST_CASE("[BitMap] Create bit map") {
dim = Size2i(46341, 46341);
bit_map.create(dim);
CHECK_MESSAGE(bit_map.get_size() == Size2i(256, 512), "We should still have the same dimensions as before, because the new dimension is too large (46341*46341=2147488281).");
+
+ ERR_PRINT_ON
}
TEST_CASE("[BitMap] Create bit map from image alpha") {
@@ -67,6 +71,8 @@ TEST_CASE("[BitMap] Create bit map from image alpha") {
BitMap bit_map{};
bit_map.create(dim);
+ ERR_PRINT_OFF
+
const Ref<Image> null_img = nullptr;
bit_map.create_from_image_alpha(null_img);
CHECK_MESSAGE(bit_map.get_size() == Size2i(256, 256), "Bitmap should have its old values because bitmap creation from a nullptr should fail.");
@@ -80,6 +86,8 @@ TEST_CASE("[BitMap] Create bit map from image alpha") {
bit_map.create_from_image_alpha(wrong_format_img);
CHECK_MESSAGE(bit_map.get_size() == Size2i(256, 256), "Bitmap should have its old values because converting from a compressed image should fail.");
+ ERR_PRINT_ON
+
Ref<Image> img = Image::create_empty(3, 3, false, Image::Format::FORMAT_RGBA8);
img->set_pixel(0, 0, Color(0, 0, 0, 0));
img->set_pixel(0, 1, Color(0, 0, 0, 0.09f));
@@ -105,6 +113,8 @@ TEST_CASE("[BitMap] Set bit") {
BitMap bit_map{};
// Setting a point before a bit map is created should not crash, because there are checks to see if we are out of bounds.
+ ERR_PRINT_OFF
+
bit_map.set_bitv(Point2i(128, 128), true);
bit_map.create(dim);
@@ -120,12 +130,16 @@ TEST_CASE("[BitMap] Set bit") {
bit_map.create(dim);
bit_map.set_bitv(Point2i(512, 512), true);
CHECK_MESSAGE(bit_map.get_true_bit_count() == 0, "Nothing should change as we were trying to edit a bit outside of the correct range.");
+
+ ERR_PRINT_ON
}
TEST_CASE("[BitMap] Get bit") {
const Size2i dim{ 256, 256 };
BitMap bit_map{};
+ ERR_PRINT_OFF
+
CHECK_MESSAGE(bit_map.get_bitv(Point2i(128, 128)) == false, "Trying to access a bit outside of the BitMap's range should always return false");
bit_map.create(dim);
@@ -140,6 +154,8 @@ TEST_CASE("[BitMap] Get bit") {
CHECK(bit_map.get_bitv(Point2i(255, 255)) == true);
CHECK(bit_map.get_bitv(Point2i(256, 256)) == false);
CHECK(bit_map.get_bitv(Point2i(257, 257)) == false);
+
+ ERR_PRINT_ON
}
TEST_CASE("[BitMap] Set bit rect") {
@@ -158,6 +174,9 @@ TEST_CASE("[BitMap] Set bit rect") {
reset_bit_map(bit_map);
// Checking out of bounds handling.
+
+ ERR_PRINT_OFF
+
bit_map.set_bit_rect(Rect2i{ 128, 128, 256, 256 }, true);
CHECK(bit_map.get_true_bit_count() == 16384);
@@ -170,6 +189,8 @@ TEST_CASE("[BitMap] Set bit rect") {
bit_map.set_bit_rect(Rect2i{ -128, -128, 512, 512 }, true);
CHECK(bit_map.get_true_bit_count() == 65536);
+
+ ERR_PRINT_ON
}
TEST_CASE("[BitMap] Get true bit count") {
@@ -197,7 +218,9 @@ TEST_CASE("[BitMap] Get size") {
bit_map.create(dim);
CHECK(bit_map.get_size() == Size2i(256, 256));
+ ERR_PRINT_OFF
bit_map.create(Size2i(-1, 0));
+ ERR_PRINT_ON
CHECK_MESSAGE(bit_map.get_size() == Size2i(256, 256), "Invalid size should not be accepted by create");
bit_map.create(Size2i(256, 128));
@@ -219,7 +242,9 @@ TEST_CASE("[BitMap] Resize") {
CHECK_MESSAGE(bit_map.get_true_bit_count() == 50, "There should be 25 bits in the top left corner, and 25 bits in the bottom right corner");
bit_map.create(dim);
+ ERR_PRINT_OFF
bit_map.resize(Size2i(-1, 128));
+ ERR_PRINT_ON
CHECK_MESSAGE(bit_map.get_size() == Size2i(128, 128), "When an invalid size is given the bit map will keep its size");
bit_map.create(dim);
@@ -234,7 +259,9 @@ TEST_CASE("[BitMap] Resize") {
TEST_CASE("[BitMap] Grow and shrink mask") {
const Size2i dim{ 256, 256 };
BitMap bit_map{};
+ ERR_PRINT_OFF
bit_map.grow_mask(100, Rect2i(0, 0, 128, 128)); // Check if method does not crash when working with an uninitialized bit map.
+ ERR_PRINT_ON
CHECK_MESSAGE(bit_map.get_size() == Size2i(0, 0), "Size should still be equal to 0x0");
bit_map.create(dim);
@@ -331,7 +358,9 @@ TEST_CASE("[BitMap] Blit") {
Ref<BitMap> blit_bit_map{};
// Testing null reference to blit bit map.
+ ERR_PRINT_OFF
bit_map.blit(blit_pos, blit_bit_map);
+ ERR_PRINT_ON
blit_bit_map.instantiate();
@@ -378,7 +407,9 @@ TEST_CASE("[BitMap] Convert to image") {
BitMap bit_map{};
Ref<Image> img;
+ ERR_PRINT_OFF
img = bit_map.convert_to_image();
+ ERR_PRINT_ON
CHECK_MESSAGE(img.is_valid(), "We should receive a valid Image Object even if BitMap is not created yet");
CHECK_MESSAGE(img->get_format() == Image::FORMAT_L8, "We should receive a valid Image Object even if BitMap is not created yet");
CHECK_MESSAGE(img->get_size() == (Size2i(0, 0)), "Image should have no width or height, because BitMap has not yet been created");
@@ -392,7 +423,7 @@ TEST_CASE("[BitMap] Convert to image") {
bit_map.set_bit_rect(Rect2i(0, 0, 128, 128), true);
img = bit_map.convert_to_image();
CHECK_MESSAGE(img->get_pixel(0, 0).is_equal_approx(Color(1, 1, 1)), "BitMap's top-left quadrant is all 1's, so Image should be white");
- CHECK_MESSAGE(img->get_pixel(256, 256).is_equal_approx(Color(0, 0, 0)), "All other quadrants were 0's, so these should be black");
+ CHECK_MESSAGE(img->get_pixel(255, 255).is_equal_approx(Color(0, 0, 0)), "All other quadrants were 0's, so these should be black");
}
TEST_CASE("[BitMap] Clip to polygon") {
@@ -400,7 +431,9 @@ TEST_CASE("[BitMap] Clip to polygon") {
BitMap bit_map{};
Vector<Vector<Vector2>> polygons;
+ ERR_PRINT_OFF
polygons = bit_map.clip_opaque_to_polygons(Rect2i(0, 0, 128, 128));
+ ERR_PRINT_ON
CHECK_MESSAGE(polygons.size() == 0, "We should have no polygons, because the BitMap was not initialized");
bit_map.create(dim);
@@ -434,6 +467,37 @@ TEST_CASE("[BitMap] Clip to polygon") {
polygons = bit_map.clip_opaque_to_polygons(Rect2i(0, 0, 128, 128));
CHECK_MESSAGE(polygons.size() == 1, "We should have exactly 1 polygon");
CHECK_MESSAGE(polygons[0].size() == 6, "The polygon should have exactly 6 points");
+
+ reset_bit_map(bit_map);
+ bit_map.set_bit_rect(Rect2i(0, 0, 64, 64), true);
+ bit_map.set_bit_rect(Rect2i(64, 64, 64, 64), true);
+ bit_map.set_bit_rect(Rect2i(192, 128, 64, 64), true);
+ bit_map.set_bit_rect(Rect2i(128, 192, 64, 64), true);
+ polygons = bit_map.clip_opaque_to_polygons(Rect2i(0, 0, 256, 256));
+ CHECK_MESSAGE(polygons.size() == 4, "We should have exactly 4 polygons");
+ CHECK_MESSAGE(polygons[0].size() == 4, "The polygon should have exactly 4 points");
+ CHECK_MESSAGE(polygons[1].size() == 4, "The polygon should have exactly 4 points");
+ CHECK_MESSAGE(polygons[2].size() == 4, "The polygon should have exactly 4 points");
+ CHECK_MESSAGE(polygons[3].size() == 4, "The polygon should have exactly 4 points");
+
+ reset_bit_map(bit_map);
+ bit_map.set_bit(0, 0, true);
+ bit_map.set_bit(2, 0, true);
+ bit_map.set_bit_rect(Rect2i(1, 1, 1, 2), true);
+ polygons = bit_map.clip_opaque_to_polygons(Rect2i(0, 0, 3, 3));
+ CHECK_MESSAGE(polygons.size() == 3, "We should have exactly 3 polygons");
+ CHECK_MESSAGE(polygons[0].size() == 4, "The polygon should have exactly 4 points");
+ CHECK_MESSAGE(polygons[1].size() == 4, "The polygon should have exactly 4 points");
+ CHECK_MESSAGE(polygons[2].size() == 4, "The polygon should have exactly 4 points");
+
+ reset_bit_map(bit_map);
+ bit_map.set_bit_rect(Rect2i(0, 0, 2, 1), true);
+ bit_map.set_bit_rect(Rect2i(0, 2, 3, 1), true);
+ bit_map.set_bit(0, 1, true);
+ bit_map.set_bit(2, 1, true);
+ polygons = bit_map.clip_opaque_to_polygons(Rect2i(0, 0, 4, 4));
+ CHECK_MESSAGE(polygons.size() == 1, "We should have exactly 1 polygon");
+ CHECK_MESSAGE(polygons[0].size() == 6, "The polygon should have exactly 6 points");
}
} // namespace TestBitmap
diff --git a/tests/scene/test_code_edit.h b/tests/scene/test_code_edit.h
index 3940bdb37a..fa31a3a461 100644
--- a/tests/scene/test_code_edit.h
+++ b/tests/scene/test_code_edit.h
@@ -2871,6 +2871,89 @@ TEST_CASE("[SceneTree][CodeEdit] completion") {
CHECK(code_edit->get_text() == "\'\'\'");
}
+ SUBCASE("[CodeEdit] autocomplete with brace completion") {
+ code_edit->set_auto_brace_completion_enabled(true);
+ CHECK(code_edit->is_auto_brace_completion_enabled());
+
+ code_edit->insert_text_at_caret("(te)");
+ code_edit->set_caret_column(3);
+
+ // Full completion.
+ code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_FUNCTION, "test()", "test()");
+ code_edit->update_code_completion_options();
+ code_edit->confirm_code_completion();
+ CHECK(code_edit->get_line(0) == "(test())");
+ CHECK(code_edit->get_caret_column() == 7);
+ code_edit->undo();
+
+ // With "arg".
+ code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_FUNCTION, "test(", "test(");
+ code_edit->update_code_completion_options();
+ code_edit->confirm_code_completion();
+ CHECK(code_edit->get_line(0) == "(test())");
+ CHECK(code_edit->get_caret_column() == 6);
+ code_edit->undo();
+
+ // brace completion disbaled
+ code_edit->set_auto_brace_completion_enabled(false);
+
+ // Full completion.
+ code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_FUNCTION, "test()", "test()");
+ code_edit->update_code_completion_options();
+ code_edit->confirm_code_completion();
+ CHECK(code_edit->get_line(0) == "(test())");
+ CHECK(code_edit->get_caret_column() == 7);
+ code_edit->undo();
+
+ // With "arg".
+ code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_FUNCTION, "test(", "test(");
+ code_edit->update_code_completion_options();
+ code_edit->confirm_code_completion();
+ CHECK(code_edit->get_line(0) == "(test()");
+ CHECK(code_edit->get_caret_column() == 6);
+
+ // String
+ code_edit->set_auto_brace_completion_enabled(true);
+ code_edit->clear();
+ code_edit->insert_text_at_caret("\"\"");
+ code_edit->set_caret_column(1);
+
+ // Full completion.
+ code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_NODE_PATH, "\"test\"", "\"test\"");
+ code_edit->update_code_completion_options();
+ code_edit->confirm_code_completion();
+ CHECK(code_edit->get_line(0) == "\"test\"");
+ CHECK(code_edit->get_caret_column() == 6);
+ code_edit->undo();
+
+ // With "arg".
+ code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_NODE_PATH, "\"test", "\"test");
+ code_edit->update_code_completion_options();
+ code_edit->confirm_code_completion();
+ CHECK(code_edit->get_line(0) == "\"\"test\"\"");
+ CHECK(code_edit->get_caret_column() == 7);
+ code_edit->undo();
+
+ // brace completion disbaled
+ code_edit->set_auto_brace_completion_enabled(false);
+
+ // Full completion.
+ code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_NODE_PATH, "\"test\"", "\"test\"");
+ code_edit->update_code_completion_options();
+ code_edit->confirm_code_completion();
+ CHECK(code_edit->get_line(0) == "\"test\"");
+ CHECK(code_edit->get_caret_column() == 6);
+ code_edit->undo();
+
+ // With "arg".
+ code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_NODE_PATH, "\"test", "\"test");
+ code_edit->update_code_completion_options();
+ code_edit->confirm_code_completion();
+ CHECK(code_edit->get_line(0) == "\"\"test\"");
+ CHECK(code_edit->get_caret_column() == 7);
+ code_edit->undo();
+ }
+
SUBCASE("[CodeEdit] autocomplete") {
code_edit->set_code_completion_enabled(true);
CHECK(code_edit->is_code_completion_enabled());
@@ -3027,7 +3110,7 @@ TEST_CASE("[SceneTree][CodeEdit] completion") {
CHECK(code_edit->get_code_completion_selected_index() == 0);
Point2 caret_pos = code_edit->get_caret_draw_pos();
- caret_pos.y -= code_edit->get_line_height();
+ caret_pos.y += code_edit->get_line_height();
SEND_GUI_MOUSE_BUTTON_EVENT(code_edit, caret_pos, MouseButton::WHEEL_DOWN, MouseButton::NONE, Key::NONE);
CHECK(code_edit->get_code_completion_selected_index() == 1);
@@ -3035,6 +3118,7 @@ TEST_CASE("[SceneTree][CodeEdit] completion") {
CHECK(code_edit->get_code_completion_selected_index() == 0);
/* Single click selects. */
+ caret_pos.y += code_edit->get_line_height() * 2;
SEND_GUI_MOUSE_BUTTON_EVENT(code_edit, caret_pos, MouseButton::LEFT, MouseButton::MASK_LEFT, Key::NONE);
CHECK(code_edit->get_code_completion_selected_index() == 2);
diff --git a/tests/scene/test_curve.h b/tests/scene/test_curve.h
index 36ec0c0a4d..4f95568b4a 100644
--- a/tests/scene/test_curve.h
+++ b/tests/scene/test_curve.h
@@ -31,6 +31,7 @@
#ifndef TEST_CURVE_H
#define TEST_CURVE_H
+#include "core/math/math_funcs.h"
#include "scene/resources/curve.h"
#include "tests/test_macros.h"
@@ -229,7 +230,7 @@ TEST_CASE("[Curve2D] Linear sampling should return exact value") {
for (int i = 0; i < len; i++) {
Vector2 pos = curve->sample_baked(i);
- CHECK_MESSAGE(pos.x == i, "sample_baked should return exact value");
+ CHECK_MESSAGE(Math::is_equal_approx(pos.x, i), "sample_baked should return exact value");
}
}
@@ -239,13 +240,14 @@ TEST_CASE("[Curve3D] Linear sampling should return exact value") {
curve->add_point(Vector3(0, 0, 0));
curve->add_point(Vector3(len, 0, 0));
-
+ ERR_PRINT_OFF
real_t baked_length = curve->get_baked_length();
+ ERR_PRINT_ON
CHECK(len == baked_length);
for (int i = 0; i < len; i++) {
Vector3 pos = curve->sample_baked(i);
- CHECK_MESSAGE(pos.x == i, "sample_baked should return exact value");
+ CHECK_MESSAGE(Math::is_equal_approx(pos.x, i), "sample_baked should return exact value");
}
}
diff --git a/tests/scene/test_text_edit.h b/tests/scene/test_text_edit.h
index 5dad7d06e1..6d1c2f4f2e 100644
--- a/tests/scene/test_text_edit.h
+++ b/tests/scene/test_text_edit.h
@@ -3261,8 +3261,8 @@ TEST_CASE("[SceneTree][TextEdit] mouse") {
CHECK(text_edit->get_line_column_at_pos(Point2i(end_pos.x - 100, end_pos.y - 100), false) == Point2i(90, 0));
CHECK(text_edit->get_line_column_at_pos(Point2i(end_pos.x - 100, end_pos.y)) == Point2i(90, 0));
- CHECK(text_edit->get_line_column_at_pos(Point2i(end_pos.x, end_pos.y + 100)) == Point2i(141, 0));
- CHECK(text_edit->get_line_column_at_pos(Point2i(end_pos.x - 100, end_pos.y + 100)) == Point2i(141, 0));
+ CHECK(text_edit->get_line_column_at_pos(Point2i(end_pos.x, end_pos.y + 100)) == Point2i(140, 0));
+ CHECK(text_edit->get_line_column_at_pos(Point2i(end_pos.x - 100, end_pos.y + 100)) == Point2i(140, 0));
CHECK(text_edit->get_line_column_at_pos(Point2i(end_pos.x, end_pos.y - 100)) == Point2i(104, 0));
CHECK(text_edit->get_line_column_at_pos(Point2i(end_pos.x - 100, end_pos.y - 100)) == Point2i(90, 0));
diff --git a/tests/scene/test_visual_shader.h b/tests/scene/test_visual_shader.h
new file mode 100644
index 0000000000..457f9ad6ac
--- /dev/null
+++ b/tests/scene/test_visual_shader.h
@@ -0,0 +1,151 @@
+/*************************************************************************/
+/* test_visual_shader.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_VISUAL_SHADER_H
+#define TEST_VISUAL_SHADER_H
+
+#include "scene/resources/visual_shader.h"
+
+#include "tests/test_macros.h"
+
+namespace TestVisualArray {
+
+TEST_CASE("[SceneTree][VisualShader] Object creation and parameter") {
+ Ref<VisualShader> vs = memnew(VisualShader);
+ CHECK(vs.is_valid());
+
+ CHECK(vs->get_mode() == Shader::MODE_SPATIAL);
+
+ for (int i = 1; i < Shader::MODE_MAX; i++) {
+ vs->set_mode((Shader::Mode)i);
+ CHECK(vs->get_mode() == i);
+ }
+}
+
+TEST_CASE("[SceneTree][VisualShader] Testing VisualShaderNodes") {
+ SUBCASE("Testing Node Creation") {
+ Ref<VisualShader> vs = memnew(VisualShader);
+ CHECK(vs.is_valid());
+
+ for (int i = 0; i < VisualShader::TYPE_MAX; i++) {
+ Ref<VisualShaderNode> vsn = memnew(VisualShaderNodeInput);
+ CHECK(vsn.is_valid());
+ vs->add_node(VisualShader::Type(i), vsn, Vector2(1, 10), i + 2);
+ CHECK(vs->get_node(VisualShader::Type(i), i + 2) == vsn);
+ }
+
+ ERR_PRINT_OFF;
+
+ // Testing for Invalid entries.
+ Ref<VisualShaderNode> vsn5 = memnew(VisualShaderNodeInput);
+ Ref<VisualShaderNode> vsn6 = memnew(VisualShaderNodeInput);
+ CHECK(vsn6.is_valid());
+ CHECK(vsn5.is_valid());
+
+ vs->add_node(VisualShader::TYPE_SKY, vsn5, Vector2(1, 10), 0);
+ CHECK_FALSE(vs->get_node(VisualShader::TYPE_SKY, 0) == vsn6);
+ vs->add_node(VisualShader::TYPE_MAX, vsn6, Vector2(1, 10), 7);
+ CHECK_FALSE(vs->get_node(VisualShader::TYPE_SKY, 7) == vsn6);
+
+ ERR_PRINT_ON;
+ }
+
+ SUBCASE("Testing VisualShaderNode position getter and setter") {
+ Ref<VisualShader> vs = memnew(VisualShader);
+ CHECK(vs.is_valid());
+
+ Ref<VisualShaderNode> vsn1 = memnew(VisualShaderNodeInput);
+ CHECK(vsn1.is_valid());
+ vs->add_node(VisualShader::TYPE_COLLIDE, vsn1, Vector2(0, 0), 3);
+ CHECK(vs->get_node_position(VisualShader::TYPE_COLLIDE, 3) == Vector2(0, 0));
+ vs->set_node_position(VisualShader::TYPE_COLLIDE, 3, Vector2(1, 1));
+ CHECK(vs->get_node_position(VisualShader::TYPE_COLLIDE, 3) == Vector2(1, 1));
+
+ Ref<VisualShaderNode> vsn2 = memnew(VisualShaderNodeInput);
+ CHECK(vsn2.is_valid());
+ vs->add_node(VisualShader::TYPE_FOG, vsn2, Vector2(1, 2), 4);
+ CHECK(vs->get_node_position(VisualShader::TYPE_FOG, 4) == Vector2(1, 2));
+ vs->set_node_position(VisualShader::TYPE_FOG, 4, Vector2(2, 2));
+ CHECK(vs->get_node_position(VisualShader::TYPE_FOG, 4) == Vector2(2, 2));
+ }
+
+ SUBCASE("Testing VisualShaderNode ID") {
+ Ref<VisualShader> vs = memnew(VisualShader);
+ CHECK(vs.is_valid());
+
+ for (int i = 0; i < VisualShader::TYPE_MAX; i++) {
+ Ref<VisualShaderNode> vsn = memnew(VisualShaderNodeInput);
+ CHECK(vsn.is_valid());
+ vs->add_node(VisualShader::Type(i), vsn, Vector2(1, 10), i + 2);
+ CHECK(vs->get_valid_node_id(VisualShader::Type(i)) - 1 == i + 2);
+ }
+ }
+
+ SUBCASE("Testing remove and replace VisualShaderNode") {
+ Ref<VisualShader> vs = memnew(VisualShader);
+ CHECK(vs.is_valid());
+
+ ERR_PRINT_OFF;
+
+ for (int i = 0; i < VisualShader::TYPE_MAX; i++) {
+ Ref<VisualShaderNode> vsn = memnew(VisualShaderNodeInput);
+ CHECK(vsn.is_valid());
+ vs->add_node(VisualShader::Type(i), vsn, Vector2(1, 10), i + 2);
+ CHECK(vs->get_node(VisualShader::Type(i), i + 2) == vsn);
+ vs->remove_node(VisualShader::Type(i), i + 2);
+ CHECK_FALSE(vs->get_node(VisualShader::Type(i), i + 2) == vsn);
+ }
+
+ ERR_PRINT_ON;
+ }
+}
+
+TEST_CASE("[SceneTree][VisualShader] Testing Varyings") {
+ Ref<VisualShader> vs = memnew(VisualShader);
+
+ vs->add_varying("Test1", VisualShader::VARYING_MODE_FRAG_TO_LIGHT, VisualShader::VARYING_TYPE_TRANSFORM);
+ CHECK(vs->has_varying("Test1") == true);
+
+ vs->add_varying("Test2", VisualShader::VARYING_MODE_VERTEX_TO_FRAG_LIGHT, VisualShader::VARYING_TYPE_VECTOR_2D);
+ CHECK(vs->has_varying("Test2"));
+
+ CHECK_FALSE(vs->has_varying("Does_not_exits"));
+ ERR_PRINT_OFF;
+ vs->add_varying("Test3", VisualShader::VARYING_MODE_MAX, VisualShader::VARYING_TYPE_INT);
+ CHECK_FALSE(vs->has_varying("Test3"));
+
+ vs->add_varying("Test4", VisualShader::VARYING_MODE_FRAG_TO_LIGHT, VisualShader::VARYING_TYPE_MAX);
+ CHECK_FALSE(vs->has_varying("Test4"));
+ ERR_PRINT_ON;
+}
+
+} //namespace TestVisualArray
+
+#endif // TEST_VISUAL_SHADER_H
diff --git a/tests/servers/test_text_server.h b/tests/servers/test_text_server.h
index 9ebd0f34b4..b3c120e0ba 100644
--- a/tests/servers/test_text_server.h
+++ b/tests/servers/test_text_server.h
@@ -68,8 +68,10 @@ TEST_SUITE("[TextServer]") {
RID font1 = ts->create_font();
ts->font_set_data_ptr(font1, _font_NotoSans_Regular, _font_NotoSans_Regular_size);
+ ts->font_set_allow_system_fallback(font1, false);
RID font2 = ts->create_font();
ts->font_set_data_ptr(font2, _font_NotoSansThaiUI_Regular, _font_NotoSansThaiUI_Regular_size);
+ ts->font_set_allow_system_fallback(font2, false);
Array font;
font.push_back(font1);
@@ -591,12 +593,18 @@ TEST_SUITE("[TextServer]") {
String text1 = U"linguistically similar and effectively form";
// 14^ 22^ 26^ 38^
PackedInt32Array breaks = ts->string_get_word_breaks(text1, "en");
- CHECK(breaks.size() == 4);
- if (breaks.size() == 4) {
- CHECK(breaks[0] == 14);
- CHECK(breaks[1] == 22);
- CHECK(breaks[2] == 26);
- CHECK(breaks[3] == 38);
+ CHECK(breaks.size() == 10);
+ if (breaks.size() == 10) {
+ CHECK(breaks[0] == 0);
+ CHECK(breaks[1] == 14);
+ CHECK(breaks[2] == 15);
+ CHECK(breaks[3] == 22);
+ CHECK(breaks[4] == 23);
+ CHECK(breaks[5] == 26);
+ CHECK(breaks[6] == 27);
+ CHECK(breaks[7] == 38);
+ CHECK(breaks[8] == 39);
+ CHECK(breaks[9] == 43);
}
}
@@ -606,16 +614,26 @@ TEST_SUITE("[TextServer]") {
// 3^ 7^ 13^ 16^ 20^ 25^ 29^ 32^
PackedInt32Array breaks = ts->string_get_word_breaks(text2, "th");
- CHECK(breaks.size() == 8);
- if (breaks.size() == 8) {
- CHECK(breaks[0] == 3);
- CHECK(breaks[1] == 7);
- CHECK(breaks[2] == 13);
- CHECK(breaks[3] == 16);
- CHECK(breaks[4] == 20);
- CHECK(breaks[5] == 25);
- CHECK(breaks[6] == 29);
- CHECK(breaks[7] == 32);
+ CHECK(breaks.size() == 18);
+ if (breaks.size() == 18) {
+ CHECK(breaks[0] == 0);
+ CHECK(breaks[1] == 4);
+ CHECK(breaks[2] == 4);
+ CHECK(breaks[3] == 8);
+ CHECK(breaks[4] == 8);
+ CHECK(breaks[5] == 14);
+ CHECK(breaks[6] == 14);
+ CHECK(breaks[7] == 17);
+ CHECK(breaks[8] == 17);
+ CHECK(breaks[9] == 21);
+ CHECK(breaks[10] == 21);
+ CHECK(breaks[11] == 26);
+ CHECK(breaks[12] == 26);
+ CHECK(breaks[13] == 30);
+ CHECK(breaks[14] == 30);
+ CHECK(breaks[15] == 33);
+ CHECK(breaks[16] == 33);
+ CHECK(breaks[17] == 42);
}
}
}
diff --git a/tests/test_main.cpp b/tests/test_main.cpp
index d58c19ac32..f51d7c8e4d 100644
--- a/tests/test_main.cpp
+++ b/tests/test_main.cpp
@@ -30,6 +30,7 @@
#include "test_main.h"
+#include "tests/core/config/test_project_settings.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"
@@ -97,6 +98,7 @@
#include "tests/scene/test_sprite_frames.h"
#include "tests/scene/test_text_edit.h"
#include "tests/scene/test_theme.h"
+#include "tests/scene/test_visual_shader.h"
#include "tests/servers/test_text_server.h"
#include "tests/test_validate_testing.h"
diff --git a/thirdparty/README.md b/thirdparty/README.md
index 383ee3197b..017dabe9e5 100644
--- a/thirdparty/README.md
+++ b/thirdparty/README.md
@@ -20,7 +20,7 @@ Files extracted from upstream source:
## basis_universal
- Upstream: https://github.com/BinomialLLC/basis_universal
-- Version: git (1531cfaf9ed5232248a0a45736686a849ca3befc, 2022)
+- Version: git (a91e94c8495d7f470d3df326a364d49324cfd4a3, 2022)
- License: Apache 2.0
Files extracted from upstream source:
@@ -44,14 +44,14 @@ Files extracted from upstream source:
## certs
- Upstream: Mozilla, via https://github.com/bagder/ca-bundle
-- Version: git (7f33e7eb8472dbcf31fdcf50cd216c89a282825d, 2022)
+- Version: git (b2f7415648411b6fd7c298c6c92d6552f0165f60, 2022)
- License: MPL 2.0
## cvtt
- Upstream: https://github.com/elasota/ConvectionKernels
-- Version: git (dc2dbbe0ae2cf2be06ef56d1021e2222a56c7fe2, 2021)
+- Version: git (350416daa4e98f1c17ffc273b134d0120a2ef230, 2022)
- License: MIT
Files extracted from upstream source:
@@ -74,7 +74,7 @@ Files extracted from upstream source:
## embree
- Upstream: https://github.com/embree/embree
-- Version: 3.13.1 (12b99393438a4cc9e478e33459eed78bec6233fd, 2021)
+- Version: 3.13.5 (698442324ccddd11725fb8875275dc1384f7fb40, 2022)
- License: Apache 2.0
Files extracted from upstream:
@@ -173,6 +173,23 @@ comments. Apply the patches in the `patches/` folder when syncing on newer upstr
commits.
+## glad
+
+- Upstream: https://github.com/Dav1dde/glad
+- Version: 2.0.2 (f237a2bfcec0d9b82b90ec9af4af265c40de7183, 2022)
+- License: CC0 1.0 and Apache 2.0
+
+Files extracted from upstream source:
+- `LICENSE`
+
+Files generated from [upstream web instance](https://gen.glad.sh/):
+- `KHR/khrplatform.h`
+- `gl.c`
+- `glad/gl.h`
+- `glx.c`
+- `glad/glx.h`
+
+
## glslang
- Upstream: https://github.com/KhronosGroup/glslang
@@ -200,8 +217,8 @@ Files extracted from upstream source:
## graphite
- Upstream: https://github.com/silnrsi/graphite
-- Version: 1.3.14 (80c52493ef42e6fe605a69dcddd2a691cd8a1380, 2021)
-- License: MPL-2.0
+- Version: 1.3.14 (27572742003b93dc53dc02c01c237b72c6c25f54, 2022)
+- License: MIT
Files extracted from upstream source:
@@ -213,7 +230,7 @@ Files extracted from upstream source:
## harfbuzz
- Upstream: https://github.com/harfbuzz/harfbuzz
-- Version: 5.3.1 (970321db7bddbe8c579b73751fc655a924ea3ce6, 2022)
+- Version: 6.0.0 (afcae83a064843d71d47624bc162e121cc56c08b, 2022)
- License: MIT
Files extracted from upstream source:
@@ -290,18 +307,15 @@ Files extracted from upstream source:
## libtheora
- Upstream: https://www.theora.org
-- Version: 1.1.1 (2010)
+- Version: git (7180717276af1ebc7da15c83162d6c5d6203aabf, 2020)
- License: BSD-3-Clause
Files extracted from upstream source:
-- all .c, .h in lib/
+- all .c, .h in lib/, except arm/ and c64x/ folders
- all .h files in include/theora/ as theora/
- COPYING and LICENSE
-Upstream patches included in the `patches` directory have been applied
-on top of the 1.1.1 source (not included in any stable release yet).
-
## libvorbis
@@ -331,7 +345,7 @@ Files extracted from upstream source:
## mbedtls
- Upstream: https://github.com/Mbed-TLS/mbedtls
-- Version: 2.18.1 (dd79db10014d85b26d11fe57218431f2e5ede6f2, 2022)
+- Version: 2.18.2 (89f040a5c938985c5f30728baed21e49d0846a53, 2022)
- License: Apache 2.0
File extracted from upstream release tarball:
@@ -341,12 +355,10 @@ File extracted from upstream release tarball:
- The `LICENSE` file.
- Applied the patch in `patches/1453.diff` (upstream PR:
https://github.com/ARMmbed/mbedtls/pull/1453).
+ Applied the patch in `patches/windows-arm64-hardclock.diff`
- Added 2 files `godot_core_mbedtls_platform.c` and `godot_core_mbedtls_config.h`
providing configuration for light bundling with core.
-Some changes have been made in order to fix Windows on ARM build errors.
-They are marked with `// -- GODOT start --` and `// -- GODOT end --`
-
## meshoptimizer
@@ -384,7 +396,7 @@ to solve some MSVC warnings. See the patches in the `patches` directory.
## miniupnpc
- Upstream: https://github.com/miniupnp/miniupnp
-- Version: 2.2.3 (2df8120326ed4246e049a7a6de707539604cd514, 2021)
+- Version: 2.2.4 (7d1d8bc3868b08ad003bad235eee57562b95b76d, 2022)
- License: BSD-3-Clause
Files extracted from upstream source:
@@ -534,7 +546,7 @@ Patch files are provided in `oidn/patches/`.
## openxr
- Upstream: https://github.com/KhronosGroup/OpenXR-SDK
-- Version: 1.0.25 (c16a18c99740ea5dd251e3af117e0e5aea4ceaa9, 2022)
+- Version: 1.0.26 (e2da9ce83a4388c9622da328bf48548471261290, 2022)
- License: Apache 2.0
Files extracted from upstream source:
@@ -577,7 +589,7 @@ in 10.40, it can be found in the `patches` folder.
## recastnavigation
- Upstream: https://github.com/recastnavigation/recastnavigation
-- Version: git (5a870d427e47abd4a8e4ce58a95582ec049434d5, 2022)
+- Version: git (4fef0446609b23d6ac180ed822817571525528a1, 2022)
- License: zlib
Files extracted from upstream source:
@@ -654,7 +666,7 @@ instead of `miniz.h` as an external dependency.
## thorvg
- Upstream: https://github.com/Samsung/thorvg
-- Version: 0.8.2 (496796f1e5e85bd5fbba36dae987edb1b3945592, 2022)
+- Version: 0.8.3 (a0fcf51f80a75f63a066df085f60cdaf715188b6, 2022)
- License: MIT
Files extracted from upstream source:
diff --git a/thirdparty/basis_universal/encoder/basisu_comp.cpp b/thirdparty/basis_universal/encoder/basisu_comp.cpp
index 166a1c4fe0..41eae2b78a 100644
--- a/thirdparty/basis_universal/encoder/basisu_comp.cpp
+++ b/thirdparty/basis_universal/encoder/basisu_comp.cpp
@@ -1501,7 +1501,8 @@ namespace basisu
if (m_params.m_compute_stats)
{
- printf("Slice: %u\n", slice_index);
+ if (m_params.m_print_stats)
+ printf("Slice: %u\n", slice_index);
image_stats& s = m_stats[slice_index];
@@ -1511,81 +1512,100 @@ namespace basisu
// ---- .basis stats
em.calc(m_slice_images[slice_index], m_decoded_output_textures_unpacked[slice_index], 0, 3);
- em.print(".basis RGB Avg: ");
+ if (m_params.m_print_stats)
+ em.print(".basis RGB Avg: ");
s.m_basis_rgb_avg_psnr = em.m_psnr;
em.calc(m_slice_images[slice_index], m_decoded_output_textures_unpacked[slice_index], 0, 4);
- em.print(".basis RGBA Avg: ");
+ if (m_params.m_print_stats)
+ em.print(".basis RGBA Avg: ");
s.m_basis_rgba_avg_psnr = em.m_psnr;
em.calc(m_slice_images[slice_index], m_decoded_output_textures_unpacked[slice_index], 0, 1);
- em.print(".basis R Avg: ");
+ if (m_params.m_print_stats)
+ em.print(".basis R Avg: ");
em.calc(m_slice_images[slice_index], m_decoded_output_textures_unpacked[slice_index], 1, 1);
- em.print(".basis G Avg: ");
+ if (m_params.m_print_stats)
+ em.print(".basis G Avg: ");
em.calc(m_slice_images[slice_index], m_decoded_output_textures_unpacked[slice_index], 2, 1);
- em.print(".basis B Avg: ");
+ if (m_params.m_print_stats)
+ em.print(".basis B Avg: ");
if (m_params.m_uastc)
{
em.calc(m_slice_images[slice_index], m_decoded_output_textures_unpacked[slice_index], 3, 1);
- em.print(".basis A Avg: ");
+ if (m_params.m_print_stats)
+ em.print(".basis A Avg: ");
s.m_basis_a_avg_psnr = em.m_psnr;
}
em.calc(m_slice_images[slice_index], m_decoded_output_textures_unpacked[slice_index], 0, 0);
- em.print(".basis 709 Luma: ");
+ if (m_params.m_print_stats)
+ em.print(".basis 709 Luma: ");
s.m_basis_luma_709_psnr = static_cast<float>(em.m_psnr);
s.m_basis_luma_709_ssim = static_cast<float>(em.m_ssim);
em.calc(m_slice_images[slice_index], m_decoded_output_textures_unpacked[slice_index], 0, 0, true, true);
- em.print(".basis 601 Luma: ");
+ if (m_params.m_print_stats)
+ em.print(".basis 601 Luma: ");
s.m_basis_luma_601_psnr = static_cast<float>(em.m_psnr);
if (m_slice_descs.size() == 1)
{
const uint32_t output_size = comp_size ? (uint32_t)comp_size : (uint32_t)comp_data.size();
- debug_printf(".basis RGB PSNR per bit/texel*10000: %3.3f\n", 10000.0f * s.m_basis_rgb_avg_psnr / ((output_size * 8.0f) / (slice_desc.m_orig_width * slice_desc.m_orig_height)));
- debug_printf(".basis Luma 709 PSNR per bit/texel*10000: %3.3f\n", 10000.0f * s.m_basis_luma_709_psnr / ((output_size * 8.0f) / (slice_desc.m_orig_width * slice_desc.m_orig_height)));
+ if (m_params.m_print_stats)
+ {
+ debug_printf(".basis RGB PSNR per bit/texel*10000: %3.3f\n", 10000.0f * s.m_basis_rgb_avg_psnr / ((output_size * 8.0f) / (slice_desc.m_orig_width * slice_desc.m_orig_height)));
+ debug_printf(".basis Luma 709 PSNR per bit/texel*10000: %3.3f\n", 10000.0f * s.m_basis_luma_709_psnr / ((output_size * 8.0f) / (slice_desc.m_orig_width * slice_desc.m_orig_height)));
+ }
}
if (m_decoded_output_textures_unpacked_bc7[slice_index].get_width())
{
// ---- BC7 stats
em.calc(m_slice_images[slice_index], m_decoded_output_textures_unpacked_bc7[slice_index], 0, 3);
- em.print("BC7 RGB Avg: ");
+ if (m_params.m_print_stats)
+ em.print("BC7 RGB Avg: ");
s.m_bc7_rgb_avg_psnr = em.m_psnr;
em.calc(m_slice_images[slice_index], m_decoded_output_textures_unpacked_bc7[slice_index], 0, 4);
- em.print("BC7 RGBA Avg: ");
+ if (m_params.m_print_stats)
+ em.print("BC7 RGBA Avg: ");
s.m_bc7_rgba_avg_psnr = em.m_psnr;
em.calc(m_slice_images[slice_index], m_decoded_output_textures_unpacked_bc7[slice_index], 0, 1);
- em.print("BC7 R Avg: ");
+ if (m_params.m_print_stats)
+ em.print("BC7 R Avg: ");
em.calc(m_slice_images[slice_index], m_decoded_output_textures_unpacked_bc7[slice_index], 1, 1);
- em.print("BC7 G Avg: ");
+ if (m_params.m_print_stats)
+ em.print("BC7 G Avg: ");
em.calc(m_slice_images[slice_index], m_decoded_output_textures_unpacked_bc7[slice_index], 2, 1);
- em.print("BC7 B Avg: ");
+ if (m_params.m_print_stats)
+ em.print("BC7 B Avg: ");
if (m_params.m_uastc)
{
em.calc(m_slice_images[slice_index], m_decoded_output_textures_unpacked_bc7[slice_index], 3, 1);
- em.print("BC7 A Avg: ");
+ if (m_params.m_print_stats)
+ em.print("BC7 A Avg: ");
s.m_bc7_a_avg_psnr = em.m_psnr;
}
em.calc(m_slice_images[slice_index], m_decoded_output_textures_unpacked_bc7[slice_index], 0, 0);
- em.print("BC7 709 Luma: ");
+ if (m_params.m_print_stats)
+ em.print("BC7 709 Luma: ");
s.m_bc7_luma_709_psnr = static_cast<float>(em.m_psnr);
s.m_bc7_luma_709_ssim = static_cast<float>(em.m_ssim);
em.calc(m_slice_images[slice_index], m_decoded_output_textures_unpacked_bc7[slice_index], 0, 0, true, true);
- em.print("BC7 601 Luma: ");
+ if (m_params.m_print_stats)
+ em.print("BC7 601 Luma: ");
s.m_bc7_luma_601_psnr = static_cast<float>(em.m_psnr);
}
@@ -1593,16 +1613,19 @@ namespace basisu
{
// ---- Nearly best possible ETC1S stats
em.calc(m_slice_images[slice_index], m_best_etc1s_images_unpacked[slice_index], 0, 3);
- em.print("Unquantized ETC1S RGB Avg: ");
+ if (m_params.m_print_stats)
+ em.print("Unquantized ETC1S RGB Avg: ");
s.m_best_etc1s_rgb_avg_psnr = static_cast<float>(em.m_psnr);
em.calc(m_slice_images[slice_index], m_best_etc1s_images_unpacked[slice_index], 0, 0);
- em.print("Unquantized ETC1S 709 Luma: ");
+ if (m_params.m_print_stats)
+ em.print("Unquantized ETC1S 709 Luma: ");
s.m_best_etc1s_luma_709_psnr = static_cast<float>(em.m_psnr);
s.m_best_etc1s_luma_709_ssim = static_cast<float>(em.m_ssim);
em.calc(m_slice_images[slice_index], m_best_etc1s_images_unpacked[slice_index], 0, 0, true, true);
- em.print("Unquantized ETC1S 601 Luma: ");
+ if (m_params.m_print_stats)
+ em.print("Unquantized ETC1S 601 Luma: ");
s.m_best_etc1s_luma_601_psnr = static_cast<float>(em.m_psnr);
}
}
@@ -2311,6 +2334,8 @@ namespace basisu
}
comp_params.m_compute_stats = (pStats != nullptr);
+ comp_params.m_print_stats = (flags_and_quality & cFlagPrintStats) != 0;
+ comp_params.m_status_output = (flags_and_quality & cFlagPrintStatus) != 0;
// Create the compressor, initialize it, and process the input
basis_compressor comp;
@@ -2328,6 +2353,11 @@ namespace basisu
return nullptr;
}
+ if ((pStats) && (comp.get_opencl_failed()))
+ {
+ pStats->m_opencl_failed = true;
+ }
+
// Get the output file data and return it to the caller
void* pFile_data = nullptr;
const uint8_vec* pFile_data_vec = comp_params.m_create_ktx2_file ? &comp.get_output_ktx2_file() : &comp.get_output_basis_file();
@@ -2388,4 +2418,108 @@ namespace basisu
free(p);
}
+ bool basis_benchmark_etc1s_opencl(bool* pOpenCL_failed)
+ {
+ if (pOpenCL_failed)
+ *pOpenCL_failed = false;
+
+ if (!opencl_is_available())
+ {
+ error_printf("basis_benchmark_etc1s_opencl: OpenCL support must be enabled first!\n");
+ return false;
+ }
+
+ const uint32_t W = 1024, H = 1024;
+ basisu::vector<image> images;
+ image& img = images.enlarge(1)->resize(W, H);
+
+ const uint32_t NUM_RAND_LETTERS = 6000;// 40000;
+
+ rand r;
+ r.seed(200);
+
+ for (uint32_t i = 0; i < NUM_RAND_LETTERS; i++)
+ {
+ uint32_t x = r.irand(0, W - 1), y = r.irand(0, H - 1);
+ uint32_t sx = r.irand(1, 4), sy = r.irand(1, 4);
+ color_rgba c(r.byte(), r.byte(), r.byte(), 255);
+
+ img.debug_text(x, y, sx, sy, c, nullptr, false, "%c", static_cast<char>(r.irand(32, 127)));
+ }
+
+ //save_png("test.png", img);
+
+ image_stats stats;
+
+ uint32_t flags_and_quality = cFlagSRGB | cFlagThreaded | 255;
+ size_t comp_size = 0;
+
+ double best_cpu_time = 1e+9f, best_gpu_time = 1e+9f;
+
+ const uint32_t TIMES_TO_ENCODE = 2;
+ interval_timer tm;
+
+ for (uint32_t i = 0; i < TIMES_TO_ENCODE; i++)
+ {
+ tm.start();
+ void* pComp_data = basis_compress(
+ images,
+ flags_and_quality, 1.0f,
+ &comp_size,
+ &stats);
+ double cpu_time = tm.get_elapsed_secs();
+ if (!pComp_data)
+ {
+ error_printf("basis_benchmark_etc1s_opencl: basis_compress() failed (CPU)!\n");
+ return false;
+ }
+
+ best_cpu_time = minimum(best_cpu_time, cpu_time);
+
+ basis_free_data(pComp_data);
+ }
+
+ printf("Best CPU time: %3.3f\n", best_cpu_time);
+
+ for (uint32_t i = 0; i < TIMES_TO_ENCODE; i++)
+ {
+ tm.start();
+ void* pComp_data = basis_compress(
+ images,
+ flags_and_quality | cFlagUseOpenCL, 1.0f,
+ &comp_size,
+ &stats);
+
+ if (stats.m_opencl_failed)
+ {
+ error_printf("basis_benchmark_etc1s_opencl: OpenCL failed!\n");
+
+ basis_free_data(pComp_data);
+
+ if (pOpenCL_failed)
+ *pOpenCL_failed = true;
+
+ return false;
+ }
+
+ double gpu_time = tm.get_elapsed_secs();
+ if (!pComp_data)
+ {
+ error_printf("basis_benchmark_etc1s_opencl: basis_compress() failed (GPU)!\n");
+ return false;
+ }
+
+ best_gpu_time = minimum(best_gpu_time, gpu_time);
+
+ basis_free_data(pComp_data);
+ }
+
+ printf("Best GPU time: %3.3f\n", best_gpu_time);
+
+ return best_gpu_time < best_cpu_time;
+ }
+
} // namespace basisu
+
+
+
diff --git a/thirdparty/basis_universal/encoder/basisu_comp.h b/thirdparty/basis_universal/encoder/basisu_comp.h
index aa5ea6fec3..b6c9fef9e2 100644
--- a/thirdparty/basis_universal/encoder/basisu_comp.h
+++ b/thirdparty/basis_universal/encoder/basisu_comp.h
@@ -92,6 +92,8 @@ namespace basisu
m_best_etc1s_luma_709_psnr = 0.0f;
m_best_etc1s_luma_601_psnr = 0.0f;
m_best_etc1s_luma_709_ssim = 0.0f;
+
+ m_opencl_failed = false;
}
std::string m_filename;
@@ -119,6 +121,8 @@ namespace basisu
float m_best_etc1s_luma_709_psnr;
float m_best_etc1s_luma_601_psnr;
float m_best_etc1s_luma_709_ssim;
+
+ bool m_opencl_failed;
};
template<bool def>
@@ -255,6 +259,7 @@ namespace basisu
m_write_output_basis_files.clear();
m_compression_level.clear();
m_compute_stats.clear();
+ m_print_stats.clear();
m_check_for_alpha.clear();
m_force_alpha.clear();
m_multithreading.clear();
@@ -373,6 +378,9 @@ namespace basisu
// Compute and display image metrics
bool_param<false> m_compute_stats;
+
+ // Print stats to stdout, if m_compute_stats is true.
+ bool_param<true> m_print_stats;
// Check to see if any input image has an alpha channel, if so then the output basis file will have alpha channels
bool_param<true> m_check_for_alpha;
@@ -583,11 +591,16 @@ namespace basisu
cFlagYFlip = 1 << 16, // flip source image on Y axis before compression
cFlagUASTC = 1 << 17, // use UASTC compression vs. ETC1S
- cFlagUASTCRDO = 1 << 18 // use RDO postprocessing when generating UASTC files (must set uastc_rdo_quality to the quality scalar)
+ cFlagUASTCRDO = 1 << 18, // use RDO postprocessing when generating UASTC files (must set uastc_rdo_quality to the quality scalar)
+
+ cFlagPrintStats = 1 << 19, // print image stats to stdout
+ cFlagPrintStatus = 1 << 20 // print status to stdout
};
// This function accepts an array of source images.
// If more than one image is provided, it's assumed the images form a mipmap pyramid and automatic mipmap generation is disabled.
+ // Returns a pointer to the compressed .basis or .ktx2 file data. *pSize is the size of the compressed data. The returned block must be freed using basis_free_data().
+ // basisu_encoder_init() MUST be called first!
void* basis_compress(
const basisu::vector<image> &source_images,
uint32_t flags_and_quality, float uastc_rdo_quality,
@@ -604,6 +617,12 @@ namespace basisu
// Frees the dynamically allocated file data returned by basis_compress().
void basis_free_data(void* p);
+ // Runs a short benchmark using synthetic image data to time OpenCL encoding vs. CPU encoding, with multithreading enabled.
+ // Returns true if opencl is worth using on this system, otherwise false.
+ // If pOpenCL_failed is not null, it will be set to true if OpenCL encoding failed *on this particular machine/driver/BasisU version* and the encoder falled back to CPU encoding.
+ // basisu_encoder_init() MUST be called first. If OpenCL support wasn't enabled this always returns false.
+ bool basis_benchmark_etc1s_opencl(bool *pOpenCL_failed = nullptr);
+
// Parallel compression API
struct parallel_results
{
diff --git a/thirdparty/basis_universal/encoder/basisu_enc.cpp b/thirdparty/basis_universal/encoder/basisu_enc.cpp
index b427215ee3..c431ceaf12 100644
--- a/thirdparty/basis_universal/encoder/basisu_enc.cpp
+++ b/thirdparty/basis_universal/encoder/basisu_enc.cpp
@@ -187,6 +187,8 @@ namespace basisu
opencl_init(opencl_force_serialization);
}
+ interval_timer::init(); // make sure interval_timer globals are initialized from main thread to avoid TSAN reports
+
g_library_initialized = true;
}
@@ -227,7 +229,7 @@ namespace basisu
{
QueryPerformanceFrequency(reinterpret_cast<LARGE_INTEGER*>(pTicks));
}
-#elif defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__)
+#elif defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__EMSCRIPTEN__)
#include <sys/time.h>
inline void query_counter(timer_ticks* pTicks)
{
diff --git a/thirdparty/basis_universal/encoder/basisu_frontend.cpp b/thirdparty/basis_universal/encoder/basisu_frontend.cpp
index 00210e6679..1f30a33c70 100644
--- a/thirdparty/basis_universal/encoder/basisu_frontend.cpp
+++ b/thirdparty/basis_universal/encoder/basisu_frontend.cpp
@@ -2328,8 +2328,6 @@ namespace basisu
m_optimized_cluster_selectors.resize(total_selector_clusters);
- uint32_t total_clusters_processed = 0;
-
// For each selector codebook entry, and for each of the 4x4 selectors, determine which selector minimizes the error across all the blocks that use that quantized selector.
const uint32_t N = 256;
for (uint32_t cluster_index_iter = 0; cluster_index_iter < total_selector_clusters; cluster_index_iter += N)
@@ -2338,7 +2336,7 @@ namespace basisu
const uint32_t last_index = minimum<uint32_t>((uint32_t)total_selector_clusters, cluster_index_iter + N);
#ifndef __EMSCRIPTEN__
- m_params.m_pJob_pool->add_job([this, first_index, last_index, &total_clusters_processed, &total_selector_clusters] {
+ m_params.m_pJob_pool->add_job([this, first_index, last_index] {
#endif
for (uint32_t cluster_index = first_index; cluster_index < last_index; cluster_index++)
diff --git a/thirdparty/basis_universal/transcoder/basisu_transcoder.cpp b/thirdparty/basis_universal/transcoder/basisu_transcoder.cpp
index 630731900f..3aeba0ee7a 100644
--- a/thirdparty/basis_universal/transcoder/basisu_transcoder.cpp
+++ b/thirdparty/basis_universal/transcoder/basisu_transcoder.cpp
@@ -16867,7 +16867,7 @@ namespace basist
{
m_format = basist::basis_tex_format::cETC1S;
- // 3.10.2: "Whether the image has 1 or 2 slices can be determined from the DFD’s sample count."
+ // 3.10.2: "Whether the image has 1 or 2 slices can be determined from the DFD's sample count."
// If m_has_alpha is true it may be 2-channel RRRG or 4-channel RGBA, but we let the caller deal with that.
m_has_alpha = (m_header.m_dfd_byte_length == 60);
diff --git a/thirdparty/certs/ca-certificates.crt b/thirdparty/certs/ca-certificates.crt
index 036f630d5b..5ed6adf574 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: Tue Jul 19 14:20:01 2022 GMT
+## Certificate data from Mozilla as of: Fri Oct 21 16:14:43 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: 9bf3799611fb58197f61d45e71ce3dc19f30e7dd73731915872ce5108a7bb066
+## SHA256: 3ff8bd209b5f2e739b9f2b96eacb694a774114685b02978257824f37ff528f71
##
@@ -3458,3 +3458,49 @@ zPUwHQYDVR0OBBYEFP+CMXI++cRmbK04ntGwUYilkMz1MA4GA1UdDwEB/wQEAwIBBjAKBggqhkjO
PQQDAwNpADBmAjEA5gVYaWHlLcoNy/EZCL3W/VGSGn5jVASQkZo1kTmZ+gepZpO6yGjUij/67W4W
Aie3AjEA3VoXK3YdZUKWpqxdinlW2Iob35reX8dQj7FbcQwm32pAAOwzkSFxvmjkI6TZraE3
-----END CERTIFICATE-----
+
+Security Communication RootCA3
+==============================
+-----BEGIN CERTIFICATE-----
+MIIFfzCCA2egAwIBAgIJAOF8N0D9G/5nMA0GCSqGSIb3DQEBDAUAMF0xCzAJBgNVBAYTAkpQMSUw
+IwYDVQQKExxTRUNPTSBUcnVzdCBTeXN0ZW1zIENPLixMVEQuMScwJQYDVQQDEx5TZWN1cml0eSBD
+b21tdW5pY2F0aW9uIFJvb3RDQTMwHhcNMTYwNjE2MDYxNzE2WhcNMzgwMTE4MDYxNzE2WjBdMQsw
+CQYDVQQGEwJKUDElMCMGA1UEChMcU0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEnMCUGA1UE
+AxMeU2VjdXJpdHkgQ29tbXVuaWNhdGlvbiBSb290Q0EzMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A
+MIICCgKCAgEA48lySfcw3gl8qUCBWNO0Ot26YQ+TUG5pPDXC7ltzkBtnTCHsXzW7OT4rCmDvu20r
+hvtxosis5FaU+cmvsXLUIKx00rgVrVH+hXShuRD+BYD5UpOzQD11EKzAlrenfna84xtSGc4RHwsE
+NPXY9Wk8d/Nk9A2qhd7gCVAEF5aEt8iKvE1y/By7z/MGTfmfZPd+pmaGNXHIEYBMwXFAWB6+oHP2
+/D5Q4eAvJj1+XCO1eXDe+uDRpdYMQXF79+qMHIjH7Iv10S9VlkZ8WjtYO/u62C21Jdp6Ts9EriGm
+npjKIG58u4iFW/vAEGK78vknR+/RiTlDxN/e4UG/VHMgly1s2vPUB6PmudhvrvyMGS7TZ2crldtY
+XLVqAvO4g160a75BflcJdURQVc1aEWEhCmHCqYj9E7wtiS/NYeCVvsq1e+F7NGcLH7YMx3weGVPK
+p7FKFSBWFHA9K4IsD50VHUeAR/94mQ4xr28+j+2GaR57GIgUssL8gjMunEst+3A7caoreyYn8xrC
+3PsXuKHqy6C0rtOUfnrQq8PsOC0RLoi/1D+tEjtCrI8Cbn3M0V9hvqG8OmpI6iZVIhZdXw3/JzOf
+GAN0iltSIEdrRU0id4xVJ/CvHozJgyJUt5rQT9nO/NkuHJYosQLTA70lUhw0Zk8jq/R3gpYd0Vcw
+CBEF/VfR2ccCAwEAAaNCMEAwHQYDVR0OBBYEFGQUfPxYchamCik0FW8qy7z8r6irMA4GA1UdDwEB
+/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBDAUAA4ICAQDcAiMI4u8hOscNtybS
+YpOnpSNyByCCYN8Y11StaSWSntkUz5m5UoHPrmyKO1o5yGwBQ8IibQLwYs1OY0PAFNr0Y/Dq9HHu
+Tofjcan0yVflLl8cebsjqodEV+m9NU1Bu0soo5iyG9kLFwfl9+qd9XbXv8S2gVj/yP9kaWJ5rW4O
+H3/uHWnlt3Jxs/6lATWUVCvAUm2PVcTJ0rjLyjQIUYWg9by0F1jqClx6vWPGOi//lkkZhOpn2ASx
+YfQAW0q3nHE3GYV5v4GwxxMOdnE+OoAGrgYWp421wsTL/0ClXI2lyTrtcoHKXJg80jQDdwj98ClZ
+XSEIx2C/pHF7uNkegr4Jr2VvKKu/S7XuPghHJ6APbw+LP6yVGPO5DtxnVW5inkYO0QR4ynKudtml
++LLfiAlhi+8kTtFZP1rUPcmTPCtk9YENFpb3ksP+MW/oKjJ0DvRMmEoYDjBU1cXrvMUVnuiZIesn
+KwkK2/HmcBhWuwzkvvnoEKQTkrgc4NtnHVMDpCKn3F2SEDzq//wbEBrD2NCcnWXL0CsnMQMeNuE9
+dnUM/0Umud1RvCPHX9jYhxBAEg09ODfnRDwYwFMJZI//1ZqmfHAuc1Uh6N//g7kdPjIe1qZ9LPFm
+6Vwdp6POXiUyK+OVrCoHzrQoeIY8LaadTdJ0MN1kURXbg4NR16/9M51NZg==
+-----END CERTIFICATE-----
+
+Security Communication ECC RootCA1
+==================================
+-----BEGIN CERTIFICATE-----
+MIICODCCAb6gAwIBAgIJANZdm7N4gS7rMAoGCCqGSM49BAMDMGExCzAJBgNVBAYTAkpQMSUwIwYD
+VQQKExxTRUNPTSBUcnVzdCBTeXN0ZW1zIENPLixMVEQuMSswKQYDVQQDEyJTZWN1cml0eSBDb21t
+dW5pY2F0aW9uIEVDQyBSb290Q0ExMB4XDTE2MDYxNjA1MTUyOFoXDTM4MDExODA1MTUyOFowYTEL
+MAkGA1UEBhMCSlAxJTAjBgNVBAoTHFNFQ09NIFRydXN0IFN5c3RlbXMgQ08uLExURC4xKzApBgNV
+BAMTIlNlY3VyaXR5IENvbW11bmljYXRpb24gRUNDIFJvb3RDQTEwdjAQBgcqhkjOPQIBBgUrgQQA
+IgNiAASkpW9gAwPDvTH00xecK4R1rOX9PVdu12O/5gSJko6BnOPpR27KkBLIE+CnnfdldB9sELLo
+5OnvbYUymUSxXv3MdhDYW72ixvnWQuRXdtyQwjWpS4g8EkdtXP9JTxpKULGjQjBAMB0GA1UdDgQW
+BBSGHOf+LaVKiwj+KBH6vqNm+GBZLzAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAK
+BggqhkjOPQQDAwNoADBlAjAVXUI9/Lbu9zuxNuie9sRGKEkz0FhDKmMpzE2xtHqiuQ04pV1IKv3L
+snNdo4gIxwwCMQDAqy0Obe0YottT6SXbVQjgUMzfRGEWgqtJsLKB7HOHeLRMsmIbEvoWTSVLY70e
+N9k=
+-----END CERTIFICATE-----
diff --git a/thirdparty/cvtt/ConvectionKernels_BC67.cpp b/thirdparty/cvtt/ConvectionKernels_BC67.cpp
index 791859b232..021d658c08 100644
--- a/thirdparty/cvtt/ConvectionKernels_BC67.cpp
+++ b/thirdparty/cvtt/ConvectionKernels_BC67.cpp
@@ -726,10 +726,10 @@ namespace cvtt
if (carry)
{
uint32_t bitMask = (1 << carry) - 1;
- for (int i = 0; i < 4; i++)
+ for (int i = 0; i < entriesRemaining; i++)
{
m_vector[i] >>= carry;
- if (i != 3)
+ if (i != entriesRemaining - 1)
m_vector[i] |= (m_vector[i + 1] & bitMask) << (32 - carry);
}
}
@@ -3058,14 +3058,11 @@ void cvtt::Internal::BC6HComputer::SignExtendSingle(int &v, int bits)
void cvtt::Internal::BC6HComputer::UnpackOne(PixelBlockF16 &output, const uint8_t *pBC, bool isSigned)
{
- UnpackingVector pv;
- pv.Init(pBC);
-
int numModeBits = 2;
- int modeBits = pv.Unpack(2);
+ int modeBits = pBC[0] & 0x3;
if (modeBits != 0 && modeBits != 1)
{
- modeBits |= pv.Unpack(3) << 2;
+ modeBits = pBC[0] & 0x1f;
numModeBits += 3;
}
@@ -3102,6 +3099,9 @@ void cvtt::Internal::BC6HComputer::UnpackOne(PixelBlockF16 &output, const uint8_
for (int ch = 0; ch < 3; ch++)
eps[subset][epi][ch] = 0;
+ UnpackingVector pv;
+ pv.Init(pBC);
+
{
uint32_t header[3];
uint16_t codedEPs[2][2][3];
diff --git a/thirdparty/embree/common/algorithms/parallel_for.h b/thirdparty/embree/common/algorithms/parallel_for.h
index 645681ac63..6d411e4852 100644
--- a/thirdparty/embree/common/algorithms/parallel_for.h
+++ b/thirdparty/embree/common/algorithms/parallel_for.h
@@ -26,7 +26,6 @@ namespace embree
abort();
// -- GODOT end --
}
-
#elif defined(TASKING_TBB)
#if TBB_INTERFACE_VERSION >= 12002
tbb::task_group_context context;
diff --git a/thirdparty/embree/common/algorithms/parallel_for_for.h b/thirdparty/embree/common/algorithms/parallel_for_for.h
index 92c37a4a38..7838ef11b3 100644
--- a/thirdparty/embree/common/algorithms/parallel_for_for.h
+++ b/thirdparty/embree/common/algorithms/parallel_for_for.h
@@ -30,15 +30,20 @@ namespace embree
template<typename ArrayArray>
__forceinline ParallelForForState (ArrayArray& array2, const size_t minStepSize) {
init(array2,minStepSize);
+ }
+
+ template<typename SizeFunc>
+ __forceinline ParallelForForState (const size_t numArrays, const SizeFunc& getSize, const size_t minStepSize) {
+ init(numArrays,getSize,minStepSize);
}
- template<typename ArrayArray>
- __forceinline void init ( ArrayArray& array2, const size_t minStepSize )
+ template<typename SizeFunc>
+ __forceinline void init ( const size_t numArrays, const SizeFunc& getSize, const size_t minStepSize )
{
/* first calculate total number of elements */
size_t N = 0;
- for (size_t i=0; i<array2.size(); i++) {
- N += array2[i] ? array2[i]->size() : 0;
+ for (size_t i=0; i<numArrays; i++) {
+ N += getSize(i);
}
this->N = N;
@@ -54,8 +59,8 @@ namespace embree
size_t k0 = (++taskIndex)*N/taskCount;
for (size_t i=0, k=0; taskIndex < taskCount; i++)
{
- assert(i<array2.size());
- size_t j=0, M = array2[i] ? array2[i]->size() : 0;
+ assert(i<numArrays);
+ size_t j=0, M = getSize(i);
while (j<M && k+M-j >= k0 && taskIndex < taskCount) {
assert(taskIndex<taskCount);
i0[taskIndex] = i;
@@ -67,6 +72,12 @@ namespace embree
}
}
+ template<typename ArrayArray>
+ __forceinline void init ( ArrayArray& array2, const size_t minStepSize )
+ {
+ init(array2.size(),[&](size_t i) { return array2[i] ? array2[i]->size() : 0; },minStepSize);
+ }
+
__forceinline size_t size() const {
return N;
}
diff --git a/thirdparty/embree/common/algorithms/parallel_for_for_prefix_sum.h b/thirdparty/embree/common/algorithms/parallel_for_for_prefix_sum.h
index b15b44a991..8c3f4aace7 100644
--- a/thirdparty/embree/common/algorithms/parallel_for_for_prefix_sum.h
+++ b/thirdparty/embree/common/algorithms/parallel_for_for_prefix_sum.h
@@ -17,15 +17,20 @@ namespace embree
__forceinline ParallelForForPrefixSumState (ArrayArray& array2, const size_t minStepSize)
: ParallelForForState(array2,minStepSize) {}
+ template<typename SizeFunc>
+ __forceinline ParallelForForPrefixSumState (size_t numArrays, const SizeFunc& getSize, const size_t minStepSize)
+ : ParallelForForState(numArrays,getSize,minStepSize) {}
+
ParallelPrefixSumState<Value> prefix_state;
};
- template<typename ArrayArray, typename Index, typename Value, typename Func, typename Reduction>
- __forceinline Value parallel_for_for_prefix_sum0( ParallelForForPrefixSumState<Value>& state, ArrayArray& array2, Index minStepSize,
- const Value& identity, const Func& func, const Reduction& reduction)
+ template<typename SizeFunc, typename Index, typename Value, typename Func, typename Reduction>
+ __forceinline Value parallel_for_for_prefix_sum0_( ParallelForForPrefixSumState<Value>& state, Index minStepSize,
+ const SizeFunc& getSize, const Value& identity, const Func& func, const Reduction& reduction)
{
/* calculate number of tasks to use */
const size_t taskCount = state.taskCount;
+
/* perform parallel prefix sum */
parallel_for(taskCount, [&](const size_t taskIndex)
{
@@ -38,9 +43,9 @@ namespace embree
size_t k=k0;
Value N=identity;
for (size_t i=i0; k<k1; i++) {
- const size_t size = array2[i] ? array2[i]->size() : 0;
+ const size_t size = getSize(i);
const size_t r0 = j0, r1 = min(size,r0+k1-k);
- if (r1 > r0) N = reduction(N, func(array2[i],range<Index>((Index)r0,(Index)r1),(Index)k,(Index)i));
+ if (r1 > r0) N = reduction(N, func((Index)i,range<Index>((Index)r0,(Index)r1),(Index)k));
k+=r1-r0; j0 = 0;
}
state.prefix_state.counts[taskIndex] = N;
@@ -58,9 +63,10 @@ namespace embree
return sum;
}
- template<typename ArrayArray, typename Index, typename Value, typename Func, typename Reduction>
- __forceinline Value parallel_for_for_prefix_sum1( ParallelForForPrefixSumState<Value>& state, ArrayArray& array2, Index minStepSize,
- const Value& identity, const Func& func, const Reduction& reduction)
+ template<typename SizeFunc, typename Index, typename Value, typename Func, typename Reduction>
+ __forceinline Value parallel_for_for_prefix_sum1_( ParallelForForPrefixSumState<Value>& state, Index minStepSize,
+ const SizeFunc& getSize,
+ const Value& identity, const Func& func, const Reduction& reduction)
{
/* calculate number of tasks to use */
const size_t taskCount = state.taskCount;
@@ -76,9 +82,9 @@ namespace embree
size_t k=k0;
Value N=identity;
for (size_t i=i0; k<k1; i++) {
- const size_t size = array2[i] ? array2[i]->size() : 0;
+ const size_t size = getSize(i);
const size_t r0 = j0, r1 = min(size,r0+k1-k);
- if (r1 > r0) N = reduction(N, func(array2[i],range<Index>((Index)r0,(Index)r1),(Index)k,(Index)i,reduction(state.prefix_state.sums[taskIndex],N)));
+ if (r1 > r0) N = reduction(N, func((Index)i,range<Index>((Index)r0,(Index)r1),(Index)k,reduction(state.prefix_state.sums[taskIndex],N)));
k+=r1-r0; j0 = 0;
}
state.prefix_state.counts[taskIndex] = N;
@@ -96,6 +102,30 @@ namespace embree
return sum;
}
+ template<typename ArrayArray, typename Index, typename Value, typename Func, typename Reduction>
+ __forceinline Value parallel_for_for_prefix_sum0( ParallelForForPrefixSumState<Value>& state,
+ ArrayArray& array2, Index minStepSize,
+ const Value& identity, const Func& func, const Reduction& reduction)
+ {
+ return parallel_for_for_prefix_sum0_(state,minStepSize,
+ [&](Index i) { return array2[i] ? array2[i]->size() : 0; },
+ identity,
+ [&](Index i, const range<Index>& r, Index k) { return func(array2[i], r, k, i); },
+ reduction);
+ }
+
+ template<typename ArrayArray, typename Index, typename Value, typename Func, typename Reduction>
+ __forceinline Value parallel_for_for_prefix_sum1( ParallelForForPrefixSumState<Value>& state,
+ ArrayArray& array2, Index minStepSize,
+ const Value& identity, const Func& func, const Reduction& reduction)
+ {
+ return parallel_for_for_prefix_sum1_(state,minStepSize,
+ [&](Index i) { return array2[i] ? array2[i]->size() : 0; },
+ identity,
+ [&](Index i, const range<Index>& r, Index k, const Value& base) { return func(array2[i], r, k, i, base); },
+ reduction);
+ }
+
template<typename ArrayArray, typename Value, typename Func, typename Reduction>
__forceinline Value parallel_for_for_prefix_sum0( ParallelForForPrefixSumState<Value>& state, ArrayArray& array2,
const Value& identity, const Func& func, const Reduction& reduction)
diff --git a/thirdparty/embree/common/algorithms/parallel_reduce.h b/thirdparty/embree/common/algorithms/parallel_reduce.h
index 8271372ea4..cd0078f2e6 100644
--- a/thirdparty/embree/common/algorithms/parallel_reduce.h
+++ b/thirdparty/embree/common/algorithms/parallel_reduce.h
@@ -26,7 +26,7 @@ namespace embree
const Index threadCount = (Index) TaskScheduler::threadCount();
taskCount = min(taskCount,threadCount,maxTasks);
- /* parallel invokation of all tasks */
+ /* parallel invocation of all tasks */
dynamic_large_stack_array(Value,values,taskCount,8192); // consumes at most 8192 bytes on the stack
parallel_for(taskCount, [&](const Index taskIndex) {
const Index k0 = first+(taskIndex+0)*(last-first)/taskCount;
diff --git a/thirdparty/embree/common/math/bbox.h b/thirdparty/embree/common/math/bbox.h
index bc43155358..e4eb3df9a4 100644
--- a/thirdparty/embree/common/math/bbox.h
+++ b/thirdparty/embree/common/math/bbox.h
@@ -77,7 +77,7 @@ namespace embree
return lower > upper;
}
-#if defined(__SSE__)
+#if defined(__SSE__) || defined(__ARM_NEON)
template<> __forceinline bool BBox<Vec3fa>::empty() const {
return !all(le_mask(lower,upper));
}
@@ -196,11 +196,11 @@ namespace embree
}
template<> __inline bool subset( const BBox<Vec3fa>& a, const BBox<Vec3fa>& b ) {
- return all(ge_mask(a.lower,b.lower)) & all(le_mask(a.upper,b.upper));
+ return all(ge_mask(a.lower,b.lower)) && all(le_mask(a.upper,b.upper));
}
template<> __inline bool subset( const BBox<Vec3fx>& a, const BBox<Vec3fx>& b ) {
- return all(ge_mask(a.lower,b.lower)) & all(le_mask(a.upper,b.upper));
+ return all(ge_mask(a.lower,b.lower)) && all(le_mask(a.upper,b.upper));
}
/*! blending */
@@ -228,11 +228,11 @@ namespace embree
/// SSE / AVX / MIC specializations
////////////////////////////////////////////////////////////////////////////////
-#if defined __SSE__
+#if defined (__SSE__) || defined(__ARM_NEON)
#include "../simd/sse.h"
#endif
-#if defined __AVX__
+#if defined (__AVX__)
#include "../simd/avx.h"
#endif
diff --git a/thirdparty/embree/common/math/color.h b/thirdparty/embree/common/math/color.h
index 529584ea16..e62e4ad2a4 100644
--- a/thirdparty/embree/common/math/color.h
+++ b/thirdparty/embree/common/math/color.h
@@ -152,21 +152,38 @@ namespace embree
}
__forceinline const Color rcp ( const Color& a )
{
+#if defined(__aarch64__)
+ __m128 reciprocal = _mm_rcp_ps(a.m128);
+ reciprocal = vmulq_f32(vrecpsq_f32(a.m128, reciprocal), reciprocal);
+ reciprocal = vmulq_f32(vrecpsq_f32(a.m128, reciprocal), reciprocal);
+ return (const Color)reciprocal;
+#else
#if defined(__AVX512VL__)
const Color r = _mm_rcp14_ps(a.m128);
#else
const Color r = _mm_rcp_ps(a.m128);
#endif
- return _mm_sub_ps(_mm_add_ps(r, r), _mm_mul_ps(_mm_mul_ps(r, r), a));
+ return _mm_add_ps(r,_mm_mul_ps(r, _mm_sub_ps(_mm_set1_ps(1.0f), _mm_mul_ps(a, r)))); // computes r + r * (1 - a * r)
+
+#endif //defined(__aarch64__)
}
__forceinline const Color rsqrt( const Color& a )
{
+#if defined(__aarch64__)
+ __m128 r = _mm_rsqrt_ps(a.m128);
+ r = vmulq_f32(r, vrsqrtsq_f32(vmulq_f32(a.m128, r), r));
+ r = vmulq_f32(r, vrsqrtsq_f32(vmulq_f32(a.m128, r), r));
+ return r;
+#else
+
#if defined(__AVX512VL__)
__m128 r = _mm_rsqrt14_ps(a.m128);
#else
__m128 r = _mm_rsqrt_ps(a.m128);
#endif
return _mm_add_ps(_mm_mul_ps(_mm_set1_ps(1.5f),r), _mm_mul_ps(_mm_mul_ps(_mm_mul_ps(a, _mm_set1_ps(-0.5f)), r), _mm_mul_ps(r, r)));
+
+#endif //defined(__aarch64__)
}
__forceinline const Color sqrt ( const Color& a ) { return _mm_sqrt_ps(a.m128); }
diff --git a/thirdparty/embree/common/math/constants.cpp b/thirdparty/embree/common/math/constants.cpp
index 03919ae20c..f51c642bfc 100644
--- a/thirdparty/embree/common/math/constants.cpp
+++ b/thirdparty/embree/common/math/constants.cpp
@@ -5,23 +5,4 @@
namespace embree
{
- TrueTy True;
- FalseTy False;
- ZeroTy zero;
- OneTy one;
- NegInfTy neg_inf;
- PosInfTy inf;
- PosInfTy pos_inf;
- NaNTy nan;
- UlpTy ulp;
- PiTy pi;
- OneOverPiTy one_over_pi;
- TwoPiTy two_pi;
- OneOverTwoPiTy one_over_two_pi;
- FourPiTy four_pi;
- OneOverFourPiTy one_over_four_pi;
- StepTy step;
- ReverseStepTy reverse_step;
- EmptyTy empty;
- UndefinedTy undefined;
}
diff --git a/thirdparty/embree/common/math/constants.h b/thirdparty/embree/common/math/constants.h
index 578473a8ab..07a1a868ba 100644
--- a/thirdparty/embree/common/math/constants.h
+++ b/thirdparty/embree/common/math/constants.h
@@ -24,13 +24,13 @@ namespace embree
__forceinline operator bool( ) const { return true; }
};
- extern MAYBE_UNUSED TrueTy True;
+ const constexpr TrueTy True = TrueTy();
struct FalseTy {
__forceinline operator bool( ) const { return false; }
};
- extern MAYBE_UNUSED FalseTy False;
+ const constexpr FalseTy False = FalseTy();
struct ZeroTy
{
@@ -48,7 +48,7 @@ namespace embree
__forceinline operator unsigned char ( ) const { return 0; }
};
- extern MAYBE_UNUSED ZeroTy zero;
+ const constexpr ZeroTy zero = ZeroTy();
struct OneTy
{
@@ -66,7 +66,7 @@ namespace embree
__forceinline operator unsigned char ( ) const { return 1; }
};
- extern MAYBE_UNUSED OneTy one;
+ const constexpr OneTy one = OneTy();
struct NegInfTy
{
@@ -85,7 +85,7 @@ namespace embree
};
- extern MAYBE_UNUSED NegInfTy neg_inf;
+ const constexpr NegInfTy neg_inf = NegInfTy();
struct PosInfTy
{
@@ -103,8 +103,8 @@ namespace embree
__forceinline operator unsigned char ( ) const { return std::numeric_limits<unsigned char>::max(); }
};
- extern MAYBE_UNUSED PosInfTy inf;
- extern MAYBE_UNUSED PosInfTy pos_inf;
+ const constexpr PosInfTy inf = PosInfTy();
+ const constexpr PosInfTy pos_inf = PosInfTy();
struct NaNTy
{
@@ -112,15 +112,15 @@ namespace embree
__forceinline operator float ( ) const { return std::numeric_limits<float>::quiet_NaN(); }
};
- extern MAYBE_UNUSED NaNTy nan;
+ const constexpr NaNTy nan = NaNTy();
struct UlpTy
{
__forceinline operator double( ) const { return std::numeric_limits<double>::epsilon(); }
__forceinline operator float ( ) const { return std::numeric_limits<float>::epsilon(); }
};
-
- extern MAYBE_UNUSED UlpTy ulp;
+
+ const constexpr UlpTy ulp = UlpTy();
struct PiTy
{
@@ -128,7 +128,7 @@ namespace embree
__forceinline operator float ( ) const { return float(M_PI); }
};
- extern MAYBE_UNUSED PiTy pi;
+ const constexpr PiTy pi = PiTy();
struct OneOverPiTy
{
@@ -136,7 +136,7 @@ namespace embree
__forceinline operator float ( ) const { return float(M_1_PI); }
};
- extern MAYBE_UNUSED OneOverPiTy one_over_pi;
+ const constexpr OneOverPiTy one_over_pi = OneOverPiTy();
struct TwoPiTy
{
@@ -144,7 +144,7 @@ namespace embree
__forceinline operator float ( ) const { return float(2.0*M_PI); }
};
- extern MAYBE_UNUSED TwoPiTy two_pi;
+ const constexpr TwoPiTy two_pi = TwoPiTy();
struct OneOverTwoPiTy
{
@@ -152,7 +152,7 @@ namespace embree
__forceinline operator float ( ) const { return float(0.5*M_1_PI); }
};
- extern MAYBE_UNUSED OneOverTwoPiTy one_over_two_pi;
+ const constexpr OneOverTwoPiTy one_over_two_pi = OneOverTwoPiTy();
struct FourPiTy
{
@@ -160,7 +160,7 @@ namespace embree
__forceinline operator float ( ) const { return float(4.0*M_PI); }
};
- extern MAYBE_UNUSED FourPiTy four_pi;
+ const constexpr FourPiTy four_pi = FourPiTy();
struct OneOverFourPiTy
{
@@ -168,30 +168,42 @@ namespace embree
__forceinline operator float ( ) const { return float(0.25*M_1_PI); }
};
- extern MAYBE_UNUSED OneOverFourPiTy one_over_four_pi;
+ const constexpr OneOverFourPiTy one_over_four_pi = OneOverFourPiTy();
struct StepTy {
+ __forceinline operator double ( ) const { return 0; }
+ __forceinline operator float ( ) const { return 0; }
+ __forceinline operator long long( ) const { return 0; }
+ __forceinline operator unsigned long long( ) const { return 0; }
+ __forceinline operator long ( ) const { return 0; }
+ __forceinline operator unsigned long ( ) const { return 0; }
+ __forceinline operator int ( ) const { return 0; }
+ __forceinline operator unsigned int ( ) const { return 0; }
+ __forceinline operator short ( ) const { return 0; }
+ __forceinline operator unsigned short ( ) const { return 0; }
+ __forceinline operator char ( ) const { return 0; }
+ __forceinline operator unsigned char ( ) const { return 0; }
};
- extern MAYBE_UNUSED StepTy step;
+ const constexpr StepTy step = StepTy();
struct ReverseStepTy {
};
- extern MAYBE_UNUSED ReverseStepTy reverse_step;
+ const constexpr ReverseStepTy reverse_step = ReverseStepTy();
struct EmptyTy {
};
- extern MAYBE_UNUSED EmptyTy empty;
+ const constexpr EmptyTy empty = EmptyTy();
struct FullTy {
};
- extern MAYBE_UNUSED FullTy full;
+ const constexpr FullTy full = FullTy();
struct UndefinedTy {
};
- extern MAYBE_UNUSED UndefinedTy undefined;
+ const constexpr UndefinedTy undefined = UndefinedTy();
}
diff --git a/thirdparty/embree/common/math/math.h b/thirdparty/embree/common/math/math.h
index 4bc54c1a6a..7930c17727 100644
--- a/thirdparty/embree/common/math/math.h
+++ b/thirdparty/embree/common/math/math.h
@@ -53,6 +53,16 @@ namespace embree
__forceinline float rcp ( const float x )
{
+#if defined(__aarch64__)
+ // Move scalar to vector register and do rcp.
+ __m128 a;
+ a[0] = x;
+ float32x4_t reciprocal = vrecpeq_f32(a);
+ reciprocal = vmulq_f32(vrecpsq_f32(a, reciprocal), reciprocal);
+ reciprocal = vmulq_f32(vrecpsq_f32(a, reciprocal), reciprocal);
+ return reciprocal[0];
+#else
+
const __m128 a = _mm_set_ss(x);
#if defined(__AVX512VL__)
@@ -66,30 +76,71 @@ namespace embree
#else
return _mm_cvtss_f32(_mm_mul_ss(r,_mm_sub_ss(_mm_set_ss(2.0f), _mm_mul_ss(r, a))));
#endif
+
+#endif //defined(__aarch64__)
}
__forceinline float signmsk ( const float x ) {
+#if defined(__aarch64__)
+ // FP and Neon shares same vector register in arm64
+ __m128 a;
+ __m128i b;
+ a[0] = x;
+ b[0] = 0x80000000;
+ a = _mm_and_ps(a, vreinterpretq_f32_s32(b));
+ return a[0];
+#else
return _mm_cvtss_f32(_mm_and_ps(_mm_set_ss(x),_mm_castsi128_ps(_mm_set1_epi32(0x80000000))));
+#endif
}
__forceinline float xorf( const float x, const float y ) {
+#if defined(__aarch64__)
+ // FP and Neon shares same vector register in arm64
+ __m128 a;
+ __m128 b;
+ a[0] = x;
+ b[0] = y;
+ a = _mm_xor_ps(a, b);
+ return a[0];
+#else
return _mm_cvtss_f32(_mm_xor_ps(_mm_set_ss(x),_mm_set_ss(y)));
+#endif
}
__forceinline float andf( const float x, const unsigned y ) {
+#if defined(__aarch64__)
+ // FP and Neon shares same vector register in arm64
+ __m128 a;
+ __m128i b;
+ a[0] = x;
+ b[0] = y;
+ a = _mm_and_ps(a, vreinterpretq_f32_s32(b));
+ return a[0];
+#else
return _mm_cvtss_f32(_mm_and_ps(_mm_set_ss(x),_mm_castsi128_ps(_mm_set1_epi32(y))));
+#endif
}
__forceinline float rsqrt( const float x )
{
+#if defined(__aarch64__)
+ // FP and Neon shares same vector register in arm64
+ __m128 a;
+ a[0] = x;
+ __m128 value = _mm_rsqrt_ps(a);
+ value = vmulq_f32(value, vrsqrtsq_f32(vmulq_f32(a, value), value));
+ value = vmulq_f32(value, vrsqrtsq_f32(vmulq_f32(a, value), value));
+ return value[0];
+#else
+
const __m128 a = _mm_set_ss(x);
#if defined(__AVX512VL__)
__m128 r = _mm_rsqrt14_ss(_mm_set_ss(0.0f),a);
#else
__m128 r = _mm_rsqrt_ss(a);
#endif
- r = _mm_add_ss(_mm_mul_ss(_mm_set_ss(1.5f), r), _mm_mul_ss(_mm_mul_ss(_mm_mul_ss(a, _mm_set_ss(-0.5f)), r), _mm_mul_ss(r, r)));
-#if defined(__ARM_NEON)
- r = _mm_add_ss(_mm_mul_ss(_mm_set_ss(1.5f), r), _mm_mul_ss(_mm_mul_ss(_mm_mul_ss(a, _mm_set_ss(-0.5f)), r), _mm_mul_ss(r, r)));
+ const __m128 c = _mm_add_ss(_mm_mul_ss(_mm_set_ss(1.5f), r),
+ _mm_mul_ss(_mm_mul_ss(_mm_mul_ss(a, _mm_set_ss(-0.5f)), r), _mm_mul_ss(r, r)));
+ return _mm_cvtss_f32(c);
#endif
- return _mm_cvtss_f32(r);
}
#if defined(__WIN32__) && defined(_MSC_VER) && (_MSC_VER <= 1700)
@@ -146,7 +197,17 @@ namespace embree
__forceinline double floor( const double x ) { return ::floor (x); }
__forceinline double ceil ( const double x ) { return ::ceil (x); }
-#if defined(__SSE4_1__)
+#if defined(__aarch64__)
+ __forceinline float mini(float a, float b) {
+ // FP and Neon shares same vector register in arm64
+ __m128 x;
+ __m128 y;
+ x[0] = a;
+ y[0] = b;
+ x = _mm_min_ps(x, y);
+ return x[0];
+ }
+#elif defined(__SSE4_1__)
__forceinline float mini(float a, float b) {
const __m128i ai = _mm_castps_si128(_mm_set_ss(a));
const __m128i bi = _mm_castps_si128(_mm_set_ss(b));
@@ -155,7 +216,17 @@ namespace embree
}
#endif
-#if defined(__SSE4_1__)
+#if defined(__aarch64__)
+ __forceinline float maxi(float a, float b) {
+ // FP and Neon shares same vector register in arm64
+ __m128 x;
+ __m128 y;
+ x[0] = a;
+ y[0] = b;
+ x = _mm_max_ps(x, y);
+ return x[0];
+ }
+#elif defined(__SSE4_1__)
__forceinline float maxi(float a, float b) {
const __m128i ai = _mm_castps_si128(_mm_set_ss(a));
const __m128i bi = _mm_castps_si128(_mm_set_ss(b));
@@ -172,9 +243,12 @@ namespace embree
__forceinline int64_t min(int64_t a, int64_t b) { return a<b ? a:b; }
__forceinline float min(float a, float b) { return a<b ? a:b; }
__forceinline double min(double a, double b) { return a<b ? a:b; }
-#if defined(__64BIT__)
+#if defined(__64BIT__) || defined(__EMSCRIPTEN__)
__forceinline size_t min(size_t a, size_t b) { return a<b ? a:b; }
#endif
+#if defined(__EMSCRIPTEN__)
+ __forceinline long min(long a, long b) { return a<b ? a:b; }
+#endif
template<typename T> __forceinline T min(const T& a, const T& b, const T& c) { return min(min(a,b),c); }
template<typename T> __forceinline T min(const T& a, const T& b, const T& c, const T& d) { return min(min(a,b),min(c,d)); }
@@ -189,9 +263,12 @@ namespace embree
__forceinline int64_t max(int64_t a, int64_t b) { return a<b ? b:a; }
__forceinline float max(float a, float b) { return a<b ? b:a; }
__forceinline double max(double a, double b) { return a<b ? b:a; }
-#if defined(__64BIT__)
+#if defined(__64BIT__) || defined(__EMSCRIPTEN__)
__forceinline size_t max(size_t a, size_t b) { return a<b ? b:a; }
#endif
+#if defined(__EMSCRIPTEN__)
+ __forceinline long max(long a, long b) { return a<b ? b:a; }
+#endif
template<typename T> __forceinline T max(const T& a, const T& b, const T& c) { return max(max(a,b),c); }
template<typename T> __forceinline T max(const T& a, const T& b, const T& c, const T& d) { return max(max(a,b),max(c,d)); }
@@ -231,6 +308,15 @@ namespace embree
__forceinline float msub ( const float a, const float b, const float c) { return _mm_cvtss_f32(_mm_fmsub_ss(_mm_set_ss(a),_mm_set_ss(b),_mm_set_ss(c))); }
__forceinline float nmadd ( const float a, const float b, const float c) { return _mm_cvtss_f32(_mm_fnmadd_ss(_mm_set_ss(a),_mm_set_ss(b),_mm_set_ss(c))); }
__forceinline float nmsub ( const float a, const float b, const float c) { return _mm_cvtss_f32(_mm_fnmsub_ss(_mm_set_ss(a),_mm_set_ss(b),_mm_set_ss(c))); }
+
+#elif defined (__aarch64__) && defined(__clang__)
+#pragma clang fp contract(fast)
+__forceinline float madd ( const float a, const float b, const float c) { return a*b + c; }
+__forceinline float msub ( const float a, const float b, const float c) { return a*b - c; }
+__forceinline float nmadd ( const float a, const float b, const float c) { return c - a*b; }
+__forceinline float nmsub ( const float a, const float b, const float c) { return -(c + a*b); }
+#pragma clang fp contract(on)
+
#else
__forceinline float madd ( const float a, const float b, const float c) { return a*b+c; }
__forceinline float msub ( const float a, const float b, const float c) { return a*b-c; }
@@ -326,7 +412,7 @@ namespace embree
return x | (y << 1) | (z << 2);
}
-#if defined(__AVX2__)
+#if defined(__AVX2__) && !defined(__aarch64__)
template<>
__forceinline unsigned int bitInterleave(const unsigned int &xi, const unsigned int& yi, const unsigned int& zi)
diff --git a/thirdparty/embree/common/math/quaternion.h b/thirdparty/embree/common/math/quaternion.h
index 080800efcd..78efccda72 100644
--- a/thirdparty/embree/common/math/quaternion.h
+++ b/thirdparty/embree/common/math/quaternion.h
@@ -242,13 +242,17 @@ namespace embree
T cosTheta = dot(q0, q1_);
QuaternionT<T> q1 = select(cosTheta < 0.f, -q1_, q1_);
cosTheta = select(cosTheta < 0.f, -cosTheta, cosTheta);
- if (unlikely(all(cosTheta > 0.9995f))) {
- return normalize(lerp(q0, q1, t));
- }
+
+ // spherical linear interpolation
const T phi = t * fastapprox::acos(cosTheta);
T sinPhi, cosPhi;
fastapprox::sincos(phi, sinPhi, cosPhi);
QuaternionT<T> qperp = sinPhi * normalize(msub(cosTheta, q0, q1));
- return msub(cosPhi, q0, qperp);
+ QuaternionT<T> qslerp = msub(cosPhi, q0, qperp);
+
+ // regular linear interpolation as fallback
+ QuaternionT<T> qlerp = normalize(lerp(q0, q1, t));
+
+ return select(cosTheta > 0.9995f, qlerp, qslerp);
}
}
diff --git a/thirdparty/embree/common/math/transcendental.h b/thirdparty/embree/common/math/transcendental.h
index fd16c26e81..daf9dd96d2 100644
--- a/thirdparty/embree/common/math/transcendental.h
+++ b/thirdparty/embree/common/math/transcendental.h
@@ -27,7 +27,7 @@ __forceinline T sin(const T &v)
// Reduced range version of x
auto x = v - kReal * piOverTwoVec;
auto kMod4 = k & 3;
- auto sinUseCos = (kMod4 == 1 | kMod4 == 3);
+ auto sinUseCos = (kMod4 == 1) | (kMod4 == 3);
auto flipSign = (kMod4 > 1);
// These coefficients are from sollya with fpminimax(sin(x)/x, [|0, 2,
@@ -76,8 +76,8 @@ __forceinline T cos(const T &v)
auto x = v - kReal * piOverTwoVec;
auto kMod4 = k & 3;
- auto cosUseCos = (kMod4 == 0 | kMod4 == 2);
- auto flipSign = (kMod4 == 1 | kMod4 == 2);
+ auto cosUseCos = (kMod4 == 0) | (kMod4 == 2);
+ auto flipSign = (kMod4 == 1) | (kMod4 == 2);
const float sinC2 = -0.16666667163372039794921875;
const float sinC4 = +8.333347737789154052734375e-3;
diff --git a/thirdparty/embree/common/math/vec2.h b/thirdparty/embree/common/math/vec2.h
index d62aef51f3..f6d98ffa0d 100644
--- a/thirdparty/embree/common/math/vec2.h
+++ b/thirdparty/embree/common/math/vec2.h
@@ -144,7 +144,7 @@ namespace embree
}
////////////////////////////////////////////////////////////////////////////////
- /// Euclidian Space Operators
+ /// Euclidean Space Operators
////////////////////////////////////////////////////////////////////////////////
template<typename T> __forceinline T dot ( const Vec2<T>& a, const Vec2<T>& b ) { return madd(a.x,b.x,a.y*b.y); }
@@ -205,11 +205,11 @@ namespace embree
#include "vec2fa.h"
-#if defined __SSE__
+#if defined(__SSE__) || defined(__ARM_NEON)
#include "../simd/sse.h"
#endif
-#if defined __AVX__
+#if defined(__AVX__)
#include "../simd/avx.h"
#endif
@@ -221,7 +221,7 @@ namespace embree
{
template<> __forceinline Vec2<float>::Vec2(const Vec2fa& a) : x(a.x), y(a.y) {}
-#if defined(__SSE__)
+#if defined(__SSE__) || defined(__ARM_NEON)
template<> __forceinline Vec2<vfloat4>::Vec2(const Vec2fa& a) : x(a.x), y(a.y) {}
#endif
diff --git a/thirdparty/embree/common/math/vec2fa.h b/thirdparty/embree/common/math/vec2fa.h
index a51fb68fd0..4f222894c2 100644
--- a/thirdparty/embree/common/math/vec2fa.h
+++ b/thirdparty/embree/common/math/vec2fa.h
@@ -97,6 +97,12 @@ namespace embree
__forceinline Vec2fa rcp ( const Vec2fa& a )
{
+#if defined(__aarch64__)
+ __m128 reciprocal = _mm_rcp_ps(a.m128);
+ reciprocal = vmulq_f32(vrecpsq_f32(a.m128, reciprocal), reciprocal);
+ reciprocal = vmulq_f32(vrecpsq_f32(a.m128, reciprocal), reciprocal);
+ return (const Vec2fa)reciprocal;
+#else
#if defined(__AVX512VL__)
const Vec2fa r = _mm_rcp14_ps(a.m128);
#else
@@ -104,13 +110,15 @@ namespace embree
#endif
#if defined(__AVX2__)
- const Vec2fa res = _mm_mul_ps(r,_mm_fnmadd_ps(r, a, vfloat4(2.0f)));
+ const Vec2fa h_n = _mm_fnmadd_ps(a, r, vfloat4(1.0)); // First, compute 1 - a * r (which will be very close to 0)
+ const Vec2fa res = _mm_fmadd_ps(r, h_n, r); // Then compute r + r * h_n
#else
- const Vec2fa res = _mm_mul_ps(r,_mm_sub_ps(vfloat4(2.0f), _mm_mul_ps(r, a)));
- //return _mm_sub_ps(_mm_add_ps(r, r), _mm_mul_ps(_mm_mul_ps(r, r), a));
+ const Vec2fa h_n = _mm_sub_ps(vfloat4(1.0f), _mm_mul_ps(a, r)); // First, compute 1 - a * r (which will be very close to 0)
+ const Vec2fa res = _mm_add_ps(r,_mm_mul_ps(r, h_n)); // Then compute r + r * h_n
#endif
return res;
+#endif //defined(__aarch64__)
}
__forceinline Vec2fa sqrt ( const Vec2fa& a ) { return _mm_sqrt_ps(a.m128); }
@@ -118,12 +126,21 @@ namespace embree
__forceinline Vec2fa rsqrt( const Vec2fa& a )
{
+#if defined(__aarch64__)
+ __m128 r = _mm_rsqrt_ps(a.m128);
+ r = vmulq_f32(r, vrsqrtsq_f32(vmulq_f32(a.m128, r), r));
+ r = vmulq_f32(r, vrsqrtsq_f32(vmulq_f32(a.m128, r), r));
+ return r;
+#else
+
#if defined(__AVX512VL__)
__m128 r = _mm_rsqrt14_ps(a.m128);
#else
__m128 r = _mm_rsqrt_ps(a.m128);
#endif
return _mm_add_ps(_mm_mul_ps(_mm_set1_ps(1.5f),r), _mm_mul_ps(_mm_mul_ps(_mm_mul_ps(a, _mm_set1_ps(-0.5f)), r), _mm_mul_ps(r, r)));
+
+#endif
}
__forceinline Vec2fa zero_fix(const Vec2fa& a) {
@@ -156,7 +173,7 @@ namespace embree
__forceinline Vec2fa min( const Vec2fa& a, const Vec2fa& b ) { return _mm_min_ps(a.m128,b.m128); }
__forceinline Vec2fa max( const Vec2fa& a, const Vec2fa& b ) { return _mm_max_ps(a.m128,b.m128); }
-#if defined(__SSE4_1__)
+#if defined(__aarch64__) || defined(__SSE4_1__)
__forceinline Vec2fa mini(const Vec2fa& a, const Vec2fa& b) {
const vint4 ai = _mm_castps_si128(a);
const vint4 bi = _mm_castps_si128(b);
@@ -165,7 +182,7 @@ namespace embree
}
#endif
-#if defined(__SSE4_1__)
+#if defined(__aarch64__) || defined(__SSE4_1__)
__forceinline Vec2fa maxi(const Vec2fa& a, const Vec2fa& b) {
const vint4 ai = _mm_castps_si128(a);
const vint4 bi = _mm_castps_si128(b);
@@ -227,7 +244,7 @@ namespace embree
__forceinline bool operator !=( const Vec2fa& a, const Vec2fa& b ) { return (_mm_movemask_ps(_mm_cmpneq_ps(a.m128, b.m128)) & 3) != 0; }
////////////////////////////////////////////////////////////////////////////////
- /// Euclidian Space Operators
+ /// Euclidean Space Operators
////////////////////////////////////////////////////////////////////////////////
#if defined(__SSE4_1__)
diff --git a/thirdparty/embree/common/math/vec3.h b/thirdparty/embree/common/math/vec3.h
index ce94eff327..254f6c4011 100644
--- a/thirdparty/embree/common/math/vec3.h
+++ b/thirdparty/embree/common/math/vec3.h
@@ -197,7 +197,7 @@ namespace embree
template<typename T> __forceinline Vec3<bool> ge_mask( const Vec3<T>& a, const Vec3<T>& b ) { return Vec3<bool>(a.x>=b.x,a.y>=b.y,a.z>=b.z); }
////////////////////////////////////////////////////////////////////////////////
- /// Euclidian Space Operators
+ /// Euclidean Space Operators
////////////////////////////////////////////////////////////////////////////////
template<typename T> __forceinline T sqr ( const Vec3<T>& a ) { return dot(a,a); }
@@ -207,7 +207,6 @@ namespace embree
template<typename T> __forceinline Vec3<T> normalize( const Vec3<T>& a ) { return a*rsqrt(sqr(a)); }
template<typename T> __forceinline T distance ( const Vec3<T>& a, const Vec3<T>& b ) { return length(a-b); }
template<typename T> __forceinline Vec3<T> cross ( const Vec3<T>& a, const Vec3<T>& b ) { return Vec3<T>(msub(a.y,b.z,a.z*b.y), msub(a.z,b.x,a.x*b.z), msub(a.x,b.y,a.y*b.x)); }
-
template<typename T> __forceinline Vec3<T> stable_triangle_normal( const Vec3<T>& a, const Vec3<T>& b, const Vec3<T>& c )
{
const T ab_x = a.z*b.y, ab_y = a.x*b.z, ab_z = a.y*b.x;
@@ -266,11 +265,11 @@ namespace embree
/// SSE / AVX / MIC specializations
////////////////////////////////////////////////////////////////////////////////
-#if defined __SSE__
+#if defined(__SSE__) || defined(__ARM_NEON)
#include "../simd/sse.h"
#endif
-#if defined __AVX__
+#if defined(__AVX__)
#include "../simd/avx.h"
#endif
@@ -291,14 +290,14 @@ namespace embree
template<> __forceinline Vec3<vfloat4>::Vec3(const Vec3fa& a) {
x = a.x; y = a.y; z = a.z;
}
-#elif defined(__SSE__)
+#elif defined(__SSE__) || defined(__ARM_NEON)
template<>
__forceinline Vec3<vfloat4>::Vec3(const Vec3fa& a) {
const vfloat4 v = vfloat4(a.m128); x = shuffle<0,0,0,0>(v); y = shuffle<1,1,1,1>(v); z = shuffle<2,2,2,2>(v);
}
#endif
-#if defined(__SSE__)
+#if defined(__SSE__) || defined(__ARM_NEON)
template<>
__forceinline Vec3<vfloat4> broadcast<vfloat4,vfloat4>(const Vec3<vfloat4>& a, const size_t k) {
return Vec3<vfloat4>(vfloat4::broadcast(&a.x[k]), vfloat4::broadcast(&a.y[k]), vfloat4::broadcast(&a.z[k]));
diff --git a/thirdparty/embree/common/math/vec3fa.h b/thirdparty/embree/common/math/vec3fa.h
index 586039741d..8564cf6d10 100644
--- a/thirdparty/embree/common/math/vec3fa.h
+++ b/thirdparty/embree/common/math/vec3fa.h
@@ -55,7 +55,13 @@ namespace embree
////////////////////////////////////////////////////////////////////////////////
static __forceinline Vec3fa load( const void* const a ) {
+#if defined(__aarch64__)
+ __m128 t = _mm_load_ps((float*)a);
+ t[3] = 0.0f;
+ return Vec3fa(t);
+#else
return Vec3fa(_mm_and_ps(_mm_load_ps((float*)a),_mm_castsi128_ps(_mm_set_epi32(0, -1, -1, -1))));
+#endif
}
static __forceinline Vec3fa loadu( const void* const a ) {
@@ -89,12 +95,20 @@ namespace embree
__forceinline Vec3fa operator +( const Vec3fa& a ) { return a; }
__forceinline Vec3fa operator -( const Vec3fa& a ) {
+#if defined(__aarch64__)
+ return vnegq_f32(a.m128);
+#else
const __m128 mask = _mm_castsi128_ps(_mm_set1_epi32(0x80000000));
return _mm_xor_ps(a.m128, mask);
+#endif
}
__forceinline Vec3fa abs ( const Vec3fa& a ) {
+#if defined(__aarch64__)
+ return _mm_abs_ps(a.m128);
+#else
const __m128 mask = _mm_castsi128_ps(_mm_set1_epi32(0x7fffffff));
return _mm_and_ps(a.m128, mask);
+#endif
}
__forceinline Vec3fa sign ( const Vec3fa& a ) {
return blendv_ps(Vec3fa(one).m128, (-Vec3fa(one)).m128, _mm_cmplt_ps (a.m128,Vec3fa(zero).m128));
@@ -102,6 +116,10 @@ namespace embree
__forceinline Vec3fa rcp ( const Vec3fa& a )
{
+#if defined(__aarch64__)
+ return vdivq_f32(vdupq_n_f32(1.0f),a.m128);
+#else
+
#if defined(__AVX512VL__)
const Vec3fa r = _mm_rcp14_ps(a.m128);
#else
@@ -109,13 +127,15 @@ namespace embree
#endif
#if defined(__AVX2__)
- const Vec3fa res = _mm_mul_ps(r.m128,_mm_fnmadd_ps(r.m128, a.m128, vfloat4(2.0f)));
+ const Vec3fa h_n = _mm_fnmadd_ps(a.m128, r.m128, vfloat4(1.0)); // First, compute 1 - a * r (which will be very close to 0)
+ const Vec3fa res = _mm_fmadd_ps(r.m128, h_n.m128, r.m128); // Then compute r + r * h_n
#else
- const Vec3fa res = _mm_mul_ps(r.m128,_mm_sub_ps(vfloat4(2.0f), _mm_mul_ps(r.m128, a.m128)));
- //return _mm_sub_ps(_mm_add_ps(r, r), _mm_mul_ps(_mm_mul_ps(r, r), a));
+ const Vec3fa h_n = _mm_sub_ps(vfloat4(1.0f), _mm_mul_ps(a.m128, r.m128)); // First, compute 1 - a * r (which will be very close to 0)
+ const Vec3fa res = _mm_add_ps(r.m128,_mm_mul_ps(r.m128, h_n.m128)); // Then compute r + r * h_n
#endif
return res;
+#endif //defined(__aarch64__)
}
__forceinline Vec3fa sqrt ( const Vec3fa& a ) { return _mm_sqrt_ps(a.m128); }
@@ -123,12 +143,20 @@ namespace embree
__forceinline Vec3fa rsqrt( const Vec3fa& a )
{
+#if defined(__aarch64__)
+ __m128 r = _mm_rsqrt_ps(a.m128);
+ r = vmulq_f32(r, vrsqrtsq_f32(vmulq_f32(a.m128, r), r));
+ r = vmulq_f32(r, vrsqrtsq_f32(vmulq_f32(a.m128, r), r));
+ return r;
+#else
+
#if defined(__AVX512VL__)
__m128 r = _mm_rsqrt14_ps(a.m128);
#else
__m128 r = _mm_rsqrt_ps(a.m128);
#endif
return _mm_add_ps(_mm_mul_ps(_mm_set1_ps(1.5f),r), _mm_mul_ps(_mm_mul_ps(_mm_mul_ps(a.m128, _mm_set1_ps(-0.5f)), r), _mm_mul_ps(r, r)));
+#endif
}
__forceinline Vec3fa zero_fix(const Vec3fa& a) {
@@ -161,7 +189,7 @@ namespace embree
__forceinline Vec3fa min( const Vec3fa& a, const Vec3fa& b ) { return _mm_min_ps(a.m128,b.m128); }
__forceinline Vec3fa max( const Vec3fa& a, const Vec3fa& b ) { return _mm_max_ps(a.m128,b.m128); }
-#if defined(__SSE4_1__)
+#if defined(__aarch64__) || defined(__SSE4_1__)
__forceinline Vec3fa mini(const Vec3fa& a, const Vec3fa& b) {
const vint4 ai = _mm_castps_si128(a.m128);
const vint4 bi = _mm_castps_si128(b.m128);
@@ -170,7 +198,7 @@ namespace embree
}
#endif
-#if defined(__SSE4_1__)
+#if defined(__aarch64__) || defined(__SSE4_1__)
__forceinline Vec3fa maxi(const Vec3fa& a, const Vec3fa& b) {
const vint4 ai = _mm_castps_si128(a.m128);
const vint4 bi = _mm_castps_si128(b.m128);
@@ -187,16 +215,16 @@ namespace embree
/// Ternary Operators
////////////////////////////////////////////////////////////////////////////////
-#if defined(__AVX2__)
+#if defined(__AVX2__) || defined(__ARM_NEON)
__forceinline Vec3fa madd ( const Vec3fa& a, const Vec3fa& b, const Vec3fa& c) { return _mm_fmadd_ps(a.m128,b.m128,c.m128); }
__forceinline Vec3fa msub ( const Vec3fa& a, const Vec3fa& b, const Vec3fa& c) { return _mm_fmsub_ps(a.m128,b.m128,c.m128); }
__forceinline Vec3fa nmadd ( const Vec3fa& a, const Vec3fa& b, const Vec3fa& c) { return _mm_fnmadd_ps(a.m128,b.m128,c.m128); }
__forceinline Vec3fa nmsub ( const Vec3fa& a, const Vec3fa& b, const Vec3fa& c) { return _mm_fnmsub_ps(a.m128,b.m128,c.m128); }
#else
__forceinline Vec3fa madd ( const Vec3fa& a, const Vec3fa& b, const Vec3fa& c) { return a*b+c; }
- __forceinline Vec3fa msub ( const Vec3fa& a, const Vec3fa& b, const Vec3fa& c) { return a*b-c; }
__forceinline Vec3fa nmadd ( const Vec3fa& a, const Vec3fa& b, const Vec3fa& c) { return -a*b+c;}
__forceinline Vec3fa nmsub ( const Vec3fa& a, const Vec3fa& b, const Vec3fa& c) { return -a*b-c; }
+ __forceinline Vec3fa msub ( const Vec3fa& a, const Vec3fa& b, const Vec3fa& c) { return a*b-c; }
#endif
__forceinline Vec3fa madd ( const float a, const Vec3fa& b, const Vec3fa& c) { return madd(Vec3fa(a),b,c); }
@@ -218,8 +246,26 @@ namespace embree
////////////////////////////////////////////////////////////////////////////////
/// Reductions
////////////////////////////////////////////////////////////////////////////////
+#if defined(__aarch64__)
+ __forceinline float reduce_add(const Vec3fa& v) {
+ float32x4_t t = v.m128;
+ t[3] = 0.0f;
+ return vaddvq_f32(t);
+ }
- __forceinline float reduce_add(const Vec3fa& v) {
+ __forceinline float reduce_mul(const Vec3fa& v) { return v.x*v.y*v.z; }
+ __forceinline float reduce_min(const Vec3fa& v) {
+ float32x4_t t = v.m128;
+ t[3] = t[2];
+ return vminvq_f32(t);
+ }
+ __forceinline float reduce_max(const Vec3fa& v) {
+ float32x4_t t = v.m128;
+ t[3] = t[2];
+ return vmaxvq_f32(t);
+ }
+#else
+ __forceinline float reduce_add(const Vec3fa& v) {
const vfloat4 a(v.m128);
const vfloat4 b = shuffle<1>(a);
const vfloat4 c = shuffle<2>(a);
@@ -229,6 +275,7 @@ namespace embree
__forceinline float reduce_mul(const Vec3fa& v) { return v.x*v.y*v.z; }
__forceinline float reduce_min(const Vec3fa& v) { return min(v.x,v.y,v.z); }
__forceinline float reduce_max(const Vec3fa& v) { return max(v.x,v.y,v.z); }
+#endif
////////////////////////////////////////////////////////////////////////////////
/// Comparison Operators
@@ -241,8 +288,13 @@ namespace embree
__forceinline Vec3ba neq_mask(const Vec3fa& a, const Vec3fa& b ) { return _mm_cmpneq_ps(a.m128, b.m128); }
__forceinline Vec3ba lt_mask( const Vec3fa& a, const Vec3fa& b ) { return _mm_cmplt_ps (a.m128, b.m128); }
__forceinline Vec3ba le_mask( const Vec3fa& a, const Vec3fa& b ) { return _mm_cmple_ps (a.m128, b.m128); }
- __forceinline Vec3ba gt_mask( const Vec3fa& a, const Vec3fa& b ) { return _mm_cmpnle_ps(a.m128, b.m128); }
- __forceinline Vec3ba ge_mask( const Vec3fa& a, const Vec3fa& b ) { return _mm_cmpnlt_ps(a.m128, b.m128); }
+ #if defined(__aarch64__)
+ __forceinline Vec3ba gt_mask( const Vec3fa& a, const Vec3fa& b ) { return _mm_cmpgt_ps (a.m128, b.m128); }
+ __forceinline Vec3ba ge_mask( const Vec3fa& a, const Vec3fa& b ) { return _mm_cmpge_ps (a.m128, b.m128); }
+#else
+ __forceinline Vec3ba gt_mask(const Vec3fa& a, const Vec3fa& b) { return _mm_cmpnle_ps(a.m128, b.m128); }
+ __forceinline Vec3ba ge_mask(const Vec3fa& a, const Vec3fa& b) { return _mm_cmpnlt_ps(a.m128, b.m128); }
+#endif
__forceinline bool isvalid ( const Vec3fa& v ) {
return all(gt_mask(v,Vec3fa(-FLT_LARGE)) & lt_mask(v,Vec3fa(+FLT_LARGE)));
@@ -261,7 +313,7 @@ namespace embree
}
////////////////////////////////////////////////////////////////////////////////
- /// Euclidian Space Operators
+ /// Euclidean Space Operators
////////////////////////////////////////////////////////////////////////////////
#if defined(__SSE4_1__)
@@ -335,7 +387,11 @@ namespace embree
/// Rounding Functions
////////////////////////////////////////////////////////////////////////////////
-#if defined (__SSE4_1__)
+#if defined(__aarch64__)
+ __forceinline Vec3fa floor(const Vec3fa& a) { return vrndmq_f32(a.m128); }
+ __forceinline Vec3fa ceil (const Vec3fa& a) { return vrndpq_f32(a.m128); }
+ __forceinline Vec3fa trunc(const Vec3fa& a) { return vrndq_f32(a.m128); }
+#elif defined (__SSE4_1__)
__forceinline Vec3fa trunc( const Vec3fa& a ) { return _mm_round_ps(a.m128, _MM_FROUND_TO_NEAREST_INT); }
__forceinline Vec3fa floor( const Vec3fa& a ) { return _mm_round_ps(a.m128, _MM_FROUND_TO_NEG_INF ); }
__forceinline Vec3fa ceil ( const Vec3fa& a ) { return _mm_round_ps(a.m128, _MM_FROUND_TO_POS_INF ); }
@@ -393,8 +449,10 @@ namespace embree
__forceinline Vec3fx( const Vec3fa& other, const int a1) { m128 = other.m128; a = a1; }
__forceinline Vec3fx( const Vec3fa& other, const unsigned a1) { m128 = other.m128; u = a1; }
- __forceinline Vec3fx( const Vec3fa& other, const float w1) {
-#if defined (__SSE4_1__)
+ __forceinline Vec3fx( const Vec3fa& other, const float w1) {
+#if defined (__aarch64__)
+ m128 = other.m128; m128[3] = w1;
+#elif defined (__SSE4_1__)
m128 = _mm_insert_ps(other.m128, _mm_set_ss(w1),3 << 4);
#else
const vint4 mask(-1,-1,-1,0);
@@ -526,7 +584,7 @@ namespace embree
__forceinline Vec3fx min( const Vec3fx& a, const Vec3fx& b ) { return _mm_min_ps(a.m128,b.m128); }
__forceinline Vec3fx max( const Vec3fx& a, const Vec3fx& b ) { return _mm_max_ps(a.m128,b.m128); }
-#if defined(__SSE4_1__)
+#if defined(__SSE4_1__) || defined(__aarch64__)
__forceinline Vec3fx mini(const Vec3fx& a, const Vec3fx& b) {
const vint4 ai = _mm_castps_si128(a.m128);
const vint4 bi = _mm_castps_si128(b.m128);
@@ -535,7 +593,7 @@ namespace embree
}
#endif
-#if defined(__SSE4_1__)
+#if defined(__SSE4_1__) || defined(__aarch64__)
__forceinline Vec3fx maxi(const Vec3fx& a, const Vec3fx& b) {
const vint4 ai = _mm_castps_si128(a.m128);
const vint4 bi = _mm_castps_si128(b.m128);
@@ -626,7 +684,7 @@ namespace embree
}
////////////////////////////////////////////////////////////////////////////////
- /// Euclidian Space Operators
+ /// Euclidean Space Operators
////////////////////////////////////////////////////////////////////////////////
#if defined(__SSE4_1__)
diff --git a/thirdparty/embree/common/math/vec3ia.h b/thirdparty/embree/common/math/vec3ia.h
index 694804c40d..d4cc3125cd 100644
--- a/thirdparty/embree/common/math/vec3ia.h
+++ b/thirdparty/embree/common/math/vec3ia.h
@@ -65,7 +65,9 @@ namespace embree
__forceinline Vec3ia operator +( const Vec3ia& a ) { return a; }
__forceinline Vec3ia operator -( const Vec3ia& a ) { return _mm_sub_epi32(_mm_setzero_si128(), a.m128); }
-#if defined(__SSSE3__)
+#if (defined(__aarch64__))
+ __forceinline Vec3ia abs ( const Vec3ia& a ) { return vabsq_s32(a.m128); }
+#elif defined(__SSSE3__)
__forceinline Vec3ia abs ( const Vec3ia& a ) { return _mm_abs_epi32(a.m128); }
#endif
@@ -81,7 +83,7 @@ namespace embree
__forceinline Vec3ia operator -( const Vec3ia& a, const int b ) { return a-Vec3ia(b); }
__forceinline Vec3ia operator -( const int a, const Vec3ia& b ) { return Vec3ia(a)-b; }
-#if defined(__SSE4_1__)
+#if defined(__aarch64__) || defined(__SSE4_1__)
__forceinline Vec3ia operator *( const Vec3ia& a, const Vec3ia& b ) { return _mm_mullo_epi32(a.m128, b.m128); }
__forceinline Vec3ia operator *( const Vec3ia& a, const int b ) { return a * Vec3ia(b); }
__forceinline Vec3ia operator *( const int a, const Vec3ia& b ) { return Vec3ia(a) * b; }
@@ -116,7 +118,7 @@ namespace embree
__forceinline Vec3ia& operator -=( Vec3ia& a, const Vec3ia& b ) { return a = a - b; }
__forceinline Vec3ia& operator -=( Vec3ia& a, const int& b ) { return a = a - b; }
-#if defined(__SSE4_1__)
+#if defined(__aarch64__) || defined(__SSE4_1__)
__forceinline Vec3ia& operator *=( Vec3ia& a, const Vec3ia& b ) { return a = a * b; }
__forceinline Vec3ia& operator *=( Vec3ia& a, const int& b ) { return a = a * b; }
#endif
@@ -127,18 +129,38 @@ namespace embree
__forceinline Vec3ia& operator |=( Vec3ia& a, const Vec3ia& b ) { return a = a | b; }
__forceinline Vec3ia& operator |=( Vec3ia& a, const int& b ) { return a = a | b; }
+#if !defined(__ARM_NEON)
__forceinline Vec3ia& operator <<=( Vec3ia& a, const int& b ) { return a = a << b; }
__forceinline Vec3ia& operator >>=( Vec3ia& a, const int& b ) { return a = a >> b; }
+#endif
////////////////////////////////////////////////////////////////////////////////
- /// Reductions
+ /// Select
////////////////////////////////////////////////////////////////////////////////
+ __forceinline Vec3ia select( const Vec3ba& m, const Vec3ia& t, const Vec3ia& f ) {
+#if defined(__aarch64__) || defined(__SSE4_1__)
+ return _mm_castps_si128(_mm_blendv_ps(_mm_castsi128_ps(f), _mm_castsi128_ps(t), m));
+#else
+ return _mm_or_si128(_mm_and_si128(_mm_castps_si128(m), t), _mm_andnot_si128(_mm_castps_si128(m), f));
+#endif
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Reductions
+ ////////////////////////////////////////////////////////////////////////////////
+#if defined(__aarch64__)
+ __forceinline int reduce_add(const Vec3ia& v) { return vaddvq_s32(select(Vec3ba(1,1,1),v,Vec3ia(0))); }
+ __forceinline int reduce_mul(const Vec3ia& v) { return v.x*v.y*v.z; }
+ __forceinline int reduce_min(const Vec3ia& v) { return vminvq_s32(select(Vec3ba(1,1,1),v,Vec3ia(0x7FFFFFFF))); }
+ __forceinline int reduce_max(const Vec3ia& v) { return vmaxvq_s32(select(Vec3ba(1,1,1),v,Vec3ia(0x80000000))); }
+#else
__forceinline int reduce_add(const Vec3ia& v) { return v.x+v.y+v.z; }
__forceinline int reduce_mul(const Vec3ia& v) { return v.x*v.y*v.z; }
__forceinline int reduce_min(const Vec3ia& v) { return min(v.x,v.y,v.z); }
__forceinline int reduce_max(const Vec3ia& v) { return max(v.x,v.y,v.z); }
-
+#endif
+
////////////////////////////////////////////////////////////////////////////////
/// Comparison Operators
////////////////////////////////////////////////////////////////////////////////
@@ -156,19 +178,7 @@ namespace embree
__forceinline Vec3ba lt_mask( const Vec3ia& a, const Vec3ia& b ) { return _mm_castsi128_ps(_mm_cmplt_epi32 (a.m128, b.m128)); }
__forceinline Vec3ba gt_mask( const Vec3ia& a, const Vec3ia& b ) { return _mm_castsi128_ps(_mm_cmpgt_epi32 (a.m128, b.m128)); }
- ////////////////////////////////////////////////////////////////////////////////
- /// Select
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline Vec3ia select( const Vec3ba& m, const Vec3ia& t, const Vec3ia& f ) {
-#if defined(__SSE4_1__)
- return _mm_castps_si128(_mm_blendv_ps(_mm_castsi128_ps(f), _mm_castsi128_ps(t), m));
-#else
- return _mm_or_si128(_mm_and_si128(_mm_castps_si128(m), t), _mm_andnot_si128(_mm_castps_si128(m), f));
-#endif
- }
-
-#if defined(__SSE4_1__)
+#if defined(__aarch64__) || defined(__SSE4_1__)
__forceinline Vec3ia min( const Vec3ia& a, const Vec3ia& b ) { return _mm_min_epi32(a.m128,b.m128); }
__forceinline Vec3ia max( const Vec3ia& a, const Vec3ia& b ) { return _mm_max_epi32(a.m128,b.m128); }
#else
diff --git a/thirdparty/embree/common/math/vec4.h b/thirdparty/embree/common/math/vec4.h
index 0ed107928a..10c53f47b4 100644
--- a/thirdparty/embree/common/math/vec4.h
+++ b/thirdparty/embree/common/math/vec4.h
@@ -149,7 +149,7 @@ namespace embree
}
////////////////////////////////////////////////////////////////////////////////
- /// Euclidian Space Operators
+ /// Euclidean Space Operators
////////////////////////////////////////////////////////////////////////////////
template<typename T> __forceinline T dot ( const Vec4<T>& a, const Vec4<T>& b ) { return madd(a.x,b.x,madd(a.y,b.y,madd(a.z,b.z,a.w*b.w))); }
@@ -205,7 +205,7 @@ namespace embree
/// SSE / AVX / MIC specializations
////////////////////////////////////////////////////////////////////////////////
-#if defined __SSE__
+#if defined(__SSE__) || defined(__ARM_NEON)
#include "../simd/sse.h"
#endif
@@ -225,7 +225,7 @@ namespace embree
template<> __forceinline Vec4<vfloat4>::Vec4( const Vec3fx& a ) {
x = a.x; y = a.y; z = a.z; w = a.w;
}
-#elif defined(__SSE__)
+#elif defined(__SSE__) || defined(__ARM_NEON)
template<> __forceinline Vec4<vfloat4>::Vec4( const Vec3fx& a ) {
const vfloat4 v = vfloat4(a.m128); x = shuffle<0,0,0,0>(v); y = shuffle<1,1,1,1>(v); z = shuffle<2,2,2,2>(v); w = shuffle<3,3,3,3>(v);
}
diff --git a/thirdparty/embree/common/simd/arm/avx2neon.h b/thirdparty/embree/common/simd/arm/avx2neon.h
new file mode 100644
index 0000000000..dd321d3d64
--- /dev/null
+++ b/thirdparty/embree/common/simd/arm/avx2neon.h
@@ -0,0 +1,1196 @@
+#pragma once
+
+#if !defined(__aarch64__)
+#error "avx2neon is only supported for AARCH64"
+#endif
+
+#include "sse2neon.h"
+
+#define AVX2NEON_ABI static inline __attribute__((always_inline))
+
+
+struct __m256 {
+ __m128 lo,hi;
+ __m256() {}
+};
+
+
+
+
+struct __m256i {
+ __m128i lo,hi;
+ explicit __m256i(const __m256 a) : lo(__m128i(a.lo)),hi(__m128i(a.hi)) {}
+ operator __m256() const {__m256 res; res.lo = __m128(lo);res.hi = __m128(hi); return res;}
+ __m256i() {}
+};
+
+
+
+
+struct __m256d {
+ float64x2_t lo,hi;
+ __m256d() {}
+ __m256d(const __m256& a) : lo(float64x2_t(a.lo)),hi(float64x2_t(a.hi)) {}
+ __m256d(const __m256i& a) : lo(float64x2_t(a.lo)),hi(float64x2_t(a.hi)) {}
+};
+
+#define UNARY_AVX_OP(type,func,basic_func) AVX2NEON_ABI type func(const type& a) {type res;res.lo=basic_func(a.lo);res.hi=basic_func(a.hi);return res;}
+
+
+#define BINARY_AVX_OP(type,func,basic_func) AVX2NEON_ABI type func(const type& a,const type& b) {type res;res.lo=basic_func(a.lo,b.lo);res.hi=basic_func(a.hi,b.hi);return res;}
+#define BINARY_AVX_OP_CAST(type,func,basic_func,bdst,bsrc) AVX2NEON_ABI type func(const type& a,const type& b) {type res;res.lo=bdst(basic_func(bsrc(a.lo),bsrc(b.lo)));res.hi=bdst(basic_func(bsrc(a.hi),bsrc(b.hi)));return res;}
+
+#define TERNARY_AVX_OP(type,func,basic_func) AVX2NEON_ABI type func(const type& a,const type& b,const type& c) {type res;res.lo=basic_func(a.lo,b.lo,c.lo);res.hi=basic_func(a.hi,b.hi,c.hi);return res;}
+
+
+#define CAST_SIMD_TYPE(to,name,from,basic_dst) AVX2NEON_ABI to name(const from& a) { to res; res.lo = basic_dst(a.lo); res.hi=basic_dst(a.hi); return res;}
+
+
+
+#define _mm_stream_load_si128 _mm_load_si128
+#define _mm256_stream_load_si256 _mm256_load_si256
+
+
+AVX2NEON_ABI
+__m128i _mm_blend_epi32 (__m128i a, __m128i b, const int imm8)
+{
+ __m128 af = _mm_castsi128_ps(a);
+ __m128 bf = _mm_castsi128_ps(b);
+ __m128 blendf = _mm_blend_ps(af, bf, imm8);
+ return _mm_castps_si128(blendf);
+}
+
+AVX2NEON_ABI
+int _mm_movemask_popcnt(__m128 a)
+{
+ return __builtin_popcount(_mm_movemask_ps(a));
+}
+
+AVX2NEON_ABI
+__m128 _mm_maskload_ps (float const * mem_addr, __m128i mask)
+{
+ float32x4_t res;
+ uint32x4_t mask_u32 = vreinterpretq_u32_m128i(mask);
+ for (int i=0;i<4;i++) {
+ if (mask_u32[i] & 0x80000000) res[i] = mem_addr[i]; else res[i] = 0;
+ }
+ return vreinterpretq_m128_f32(res);
+}
+
+AVX2NEON_ABI
+void _mm_maskstore_ps (float * mem_addr, __m128i mask, __m128 a)
+{
+ float32x4_t a_f32 = vreinterpretq_f32_m128(a);
+ uint32x4_t mask_u32 = vreinterpretq_u32_m128i(mask);
+ for (int i=0;i<4;i++) {
+ if (mask_u32[i] & 0x80000000) mem_addr[i] = a_f32[i];
+ }
+}
+
+AVX2NEON_ABI
+void _mm_maskstore_epi32 (int * mem_addr, __m128i mask, __m128i a)
+{
+ uint32x4_t mask_u32 = vreinterpretq_u32_m128i(mask);
+ int32x4_t a_s32 = vreinterpretq_s32_m128i(a);
+ for (int i=0;i<4;i++) {
+ if (mask_u32[i] & 0x80000000) mem_addr[i] = a_s32[i];
+ }
+}
+
+
+#define _mm_fmadd_ss _mm_fmadd_ps
+#define _mm_fmsub_ss _mm_fmsub_ps
+#define _mm_fnmsub_ss _mm_fnmsub_ps
+#define _mm_fnmadd_ss _mm_fnmadd_ps
+
+template<int code>
+AVX2NEON_ABI float32x4_t dpps_neon(const float32x4_t& a,const float32x4_t& b)
+{
+ float v;
+ v = 0;
+ v += (code & 0x10) ? a[0]*b[0] : 0;
+ v += (code & 0x20) ? a[1]*b[1] : 0;
+ v += (code & 0x40) ? a[2]*b[2] : 0;
+ v += (code & 0x80) ? a[3]*b[3] : 0;
+ float32x4_t res;
+ res[0] = (code & 0x1) ? v : 0;
+ res[1] = (code & 0x2) ? v : 0;
+ res[2] = (code & 0x4) ? v : 0;
+ res[3] = (code & 0x8) ? v : 0;
+ return res;
+}
+
+template<>
+inline float32x4_t dpps_neon<0x7f>(const float32x4_t& a,const float32x4_t& b)
+{
+ float v;
+ float32x4_t m = _mm_mul_ps(a,b);
+ m[3] = 0;
+ v = vaddvq_f32(m);
+ return _mm_set1_ps(v);
+}
+
+template<>
+inline float32x4_t dpps_neon<0xff>(const float32x4_t& a,const float32x4_t& b)
+{
+ float v;
+ float32x4_t m = _mm_mul_ps(a,b);
+ v = vaddvq_f32(m);
+ return _mm_set1_ps(v);
+}
+
+#define _mm_dp_ps(a,b,c) dpps_neon<c>((a),(b))
+
+
+AVX2NEON_ABI
+__m128 _mm_permutevar_ps (__m128 a, __m128i b)
+{
+ uint32x4_t b_u32 = vreinterpretq_u32_m128i(b);
+ float32x4_t x;
+ for (int i=0;i<4;i++)
+ {
+ x[i] = a[b_u32[i]];
+ }
+ return vreinterpretq_m128_f32(x);
+}
+
+AVX2NEON_ABI
+__m256i _mm256_setzero_si256()
+{
+ __m256i res;
+ res.lo = res.hi = vdupq_n_s32(0);
+ return res;
+}
+
+AVX2NEON_ABI
+__m256 _mm256_setzero_ps()
+{
+ __m256 res;
+ res.lo = res.hi = vdupq_n_f32(0.0f);
+ return res;
+}
+
+AVX2NEON_ABI
+__m256i _mm256_undefined_si256()
+{
+ return _mm256_setzero_si256();
+}
+
+AVX2NEON_ABI
+__m256 _mm256_undefined_ps()
+{
+ return _mm256_setzero_ps();
+}
+
+CAST_SIMD_TYPE(__m256d, _mm256_castps_pd, __m256, float64x2_t)
+CAST_SIMD_TYPE(__m256i, _mm256_castps_si256, __m256, __m128i)
+CAST_SIMD_TYPE(__m256, _mm256_castsi256_ps, __m256i, __m128)
+CAST_SIMD_TYPE(__m256, _mm256_castpd_ps , __m256d, __m128)
+CAST_SIMD_TYPE(__m256d, _mm256_castsi256_pd, __m256i, float64x2_t)
+CAST_SIMD_TYPE(__m256i, _mm256_castpd_si256, __m256d, __m128i)
+
+
+
+
+AVX2NEON_ABI
+__m128 _mm256_castps256_ps128 (__m256 a)
+{
+ return a.lo;
+}
+
+AVX2NEON_ABI
+__m256i _mm256_castsi128_si256 (__m128i a)
+{
+ __m256i res;
+ res.lo = a ;
+ res.hi = vdupq_n_s32(0);
+ return res;
+}
+
+AVX2NEON_ABI
+__m128i _mm256_castsi256_si128 (__m256i a)
+{
+ return a.lo;
+}
+
+AVX2NEON_ABI
+__m256 _mm256_castps128_ps256 (__m128 a)
+{
+ __m256 res;
+ res.lo = a;
+ res.hi = vdupq_n_f32(0);
+ return res;
+}
+
+
+AVX2NEON_ABI
+__m256 _mm256_broadcast_ss (float const * mem_addr)
+{
+ __m256 res;
+ res.lo = res.hi = vdupq_n_f32(*mem_addr);
+ return res;
+}
+
+
+AVX2NEON_ABI
+__m256i _mm256_set_epi32 (int e7, int e6, int e5, int e4, int e3, int e2, int e1, int e0)
+{
+ __m256i res;
+ res.lo = _mm_set_epi32(e3,e2,e1,e0);
+ res.hi = _mm_set_epi32(e7,e6,e5,e4);
+ return res;
+
+}
+
+AVX2NEON_ABI
+__m256i _mm256_set1_epi32 (int a)
+{
+ __m256i res;
+ res.lo = res.hi = vdupq_n_s32(a);
+ return res;
+}
+AVX2NEON_ABI
+__m256i _mm256_set1_epi8 (int a)
+{
+ __m256i res;
+ res.lo = res.hi = vdupq_n_s8(a);
+ return res;
+}
+AVX2NEON_ABI
+__m256i _mm256_set1_epi16 (int a)
+{
+ __m256i res;
+ res.lo = res.hi = vdupq_n_s16(a);
+ return res;
+}
+
+
+
+
+AVX2NEON_ABI
+int _mm256_movemask_ps(const __m256& v)
+{
+ return (_mm_movemask_ps(v.hi) << 4) | _mm_movemask_ps(v.lo);
+}
+
+template<int imm8>
+AVX2NEON_ABI
+__m256 __mm256_permute_ps (const __m256& a)
+{
+ __m256 res;
+ res.lo = _mm_shuffle_ps(a.lo,a.lo,imm8);
+ res.hi = _mm_shuffle_ps(a.hi,a.hi,imm8);
+ return res;
+
+}
+
+#define _mm256_permute_ps(a,c) __mm256_permute_ps<c>(a)
+
+
+template<int imm8>
+AVX2NEON_ABI
+__m256 __mm256_shuffle_ps (const __m256 a,const __m256& b)
+{
+ __m256 res;
+ res.lo = _mm_shuffle_ps(a.lo,b.lo,imm8);
+ res.hi = _mm_shuffle_ps(a.hi,b.hi,imm8);
+ return res;
+
+}
+
+template<int imm8>
+AVX2NEON_ABI
+__m256i __mm256_shuffle_epi32 (const __m256i a)
+{
+ __m256i res;
+ res.lo = _mm_shuffle_epi32(a.lo,imm8);
+ res.hi = _mm_shuffle_epi32(a.hi,imm8);
+ return res;
+
+}
+
+template<int imm8>
+AVX2NEON_ABI
+__m256i __mm256_srli_si256 (__m256i a)
+{
+ __m256i res;
+ res.lo = _mm_srli_si128(a.lo,imm8);
+ res.hi = _mm_srli_si128(a.hi,imm8);
+ return res;
+}
+
+template<int imm8>
+AVX2NEON_ABI
+__m256i __mm256_slli_si256 (__m256i a)
+{
+ __m256i res;
+ res.lo = _mm_slli_si128(a.lo,imm8);
+ res.hi = _mm_slli_si128(a.hi,imm8);
+ return res;
+}
+
+
+#define _mm256_srli_si256(a,b) __mm256_srli_si256<b>(a)
+#define _mm256_slli_si256(a,b) __mm256_slli_si256<b>(a)
+
+
+
+#define _mm256_shuffle_ps(a,b,c) __mm256_shuffle_ps<c>(a,b)
+#define _mm256_shuffle_epi32(a,c) __mm256_shuffle_epi32<c>(a)
+
+
+AVX2NEON_ABI
+__m256i _mm256_set1_epi64x (long long a)
+{
+ __m256i res;
+ int64x2_t t = vdupq_n_s64(a);
+ res.lo = res.hi = __m128i(t);
+ return res;
+}
+
+
+AVX2NEON_ABI
+__m256 _mm256_permute2f128_ps (__m256 a, __m256 b, int imm8)
+{
+ __m256 res;
+ __m128 tmp;
+ switch (imm8 & 0x7)
+ {
+ case 0: tmp = a.lo; break;
+ case 1: tmp = a.hi; break;
+ case 2: tmp = b.lo; break;
+ case 3: tmp = b.hi; break;
+ }
+ if (imm8 & 0x8)
+ tmp = _mm_setzero_ps();
+
+
+
+ res.lo = tmp;
+ imm8 >>= 4;
+
+ switch (imm8 & 0x7)
+ {
+ case 0: tmp = a.lo; break;
+ case 1: tmp = a.hi; break;
+ case 2: tmp = b.lo; break;
+ case 3: tmp = b.hi; break;
+ }
+ if (imm8 & 0x8)
+ tmp = _mm_setzero_ps();
+
+ res.hi = tmp;
+
+ return res;
+}
+
+AVX2NEON_ABI
+__m256 _mm256_moveldup_ps (__m256 a)
+{
+ __m256 res;
+ res.lo = _mm_moveldup_ps(a.lo);
+ res.hi = _mm_moveldup_ps(a.hi);
+ return res;
+}
+
+AVX2NEON_ABI
+__m256 _mm256_movehdup_ps (__m256 a)
+{
+ __m256 res;
+ res.lo = _mm_movehdup_ps(a.lo);
+ res.hi = _mm_movehdup_ps(a.hi);
+ return res;
+}
+
+AVX2NEON_ABI
+__m256 _mm256_insertf128_ps (__m256 a, __m128 b, int imm8)
+{
+ __m256 res = a;
+ if (imm8 & 1) res.hi = b;
+ else res.lo = b;
+ return res;
+}
+
+
+AVX2NEON_ABI
+__m128 _mm256_extractf128_ps (__m256 a, const int imm8)
+{
+ if (imm8 & 1) return a.hi;
+ return a.lo;
+}
+
+
+AVX2NEON_ABI
+__m256d _mm256_movedup_pd (__m256d a)
+{
+ __m256d res;
+ res.lo = _mm_movedup_pd(a.lo);
+ res.hi = _mm_movedup_pd(a.hi);
+ return res;
+}
+
+AVX2NEON_ABI
+__m256i _mm256_abs_epi32(__m256i a)
+{
+ __m256i res;
+ res.lo = vabsq_s32(a.lo);
+ res.hi = vabsq_s32(a.hi);
+ return res;
+}
+
+UNARY_AVX_OP(__m256,_mm256_sqrt_ps,_mm_sqrt_ps)
+UNARY_AVX_OP(__m256,_mm256_rsqrt_ps,_mm_rsqrt_ps)
+UNARY_AVX_OP(__m256,_mm256_rcp_ps,_mm_rcp_ps)
+UNARY_AVX_OP(__m256,_mm256_floor_ps,vrndmq_f32)
+UNARY_AVX_OP(__m256,_mm256_ceil_ps,vrndpq_f32)
+UNARY_AVX_OP(__m256i,_mm256_abs_epi16,_mm_abs_epi16)
+
+
+BINARY_AVX_OP(__m256i,_mm256_add_epi8,_mm_add_epi8)
+BINARY_AVX_OP(__m256i,_mm256_adds_epi8,_mm_adds_epi8)
+
+BINARY_AVX_OP(__m256i,_mm256_hadd_epi32,_mm_hadd_epi32)
+BINARY_AVX_OP(__m256i,_mm256_add_epi32,_mm_add_epi32)
+BINARY_AVX_OP(__m256i,_mm256_sub_epi32,_mm_sub_epi32)
+BINARY_AVX_OP(__m256i,_mm256_mullo_epi32,_mm_mullo_epi32)
+
+BINARY_AVX_OP(__m256i,_mm256_min_epi32,_mm_min_epi32)
+BINARY_AVX_OP(__m256i,_mm256_max_epi32,_mm_max_epi32)
+BINARY_AVX_OP(__m256i,_mm256_min_epi16,_mm_min_epi16)
+BINARY_AVX_OP(__m256i,_mm256_max_epi16,_mm_max_epi16)
+BINARY_AVX_OP(__m256i,_mm256_min_epi8,_mm_min_epi8)
+BINARY_AVX_OP(__m256i,_mm256_max_epi8,_mm_max_epi8)
+BINARY_AVX_OP(__m256i,_mm256_min_epu16,_mm_min_epu16)
+BINARY_AVX_OP(__m256i,_mm256_max_epu16,_mm_max_epu16)
+BINARY_AVX_OP(__m256i,_mm256_min_epu8,_mm_min_epu8)
+BINARY_AVX_OP(__m256i,_mm256_max_epu8,_mm_max_epu8)
+BINARY_AVX_OP(__m256i,_mm256_sign_epi16,_mm_sign_epi16)
+
+
+BINARY_AVX_OP_CAST(__m256i,_mm256_min_epu32,vminq_u32,__m128i,uint32x4_t)
+BINARY_AVX_OP_CAST(__m256i,_mm256_max_epu32,vmaxq_u32,__m128i,uint32x4_t)
+
+BINARY_AVX_OP(__m256,_mm256_min_ps,_mm_min_ps)
+BINARY_AVX_OP(__m256,_mm256_max_ps,_mm_max_ps)
+
+BINARY_AVX_OP(__m256,_mm256_add_ps,_mm_add_ps)
+BINARY_AVX_OP(__m256,_mm256_mul_ps,_mm_mul_ps)
+BINARY_AVX_OP(__m256,_mm256_sub_ps,_mm_sub_ps)
+BINARY_AVX_OP(__m256,_mm256_div_ps,_mm_div_ps)
+
+BINARY_AVX_OP(__m256,_mm256_and_ps,_mm_and_ps)
+BINARY_AVX_OP(__m256,_mm256_andnot_ps,_mm_andnot_ps)
+BINARY_AVX_OP(__m256,_mm256_or_ps,_mm_or_ps)
+BINARY_AVX_OP(__m256,_mm256_xor_ps,_mm_xor_ps)
+
+BINARY_AVX_OP_CAST(__m256d,_mm256_and_pd,vandq_s64,float64x2_t,int64x2_t)
+BINARY_AVX_OP_CAST(__m256d,_mm256_or_pd,vorrq_s64,float64x2_t,int64x2_t)
+BINARY_AVX_OP_CAST(__m256d,_mm256_xor_pd,veorq_s64,float64x2_t,int64x2_t)
+
+
+
+BINARY_AVX_OP(__m256i,_mm256_and_si256,_mm_and_si128)
+BINARY_AVX_OP(__m256i,_mm256_andnot_si256,_mm_andnot_si128)
+BINARY_AVX_OP(__m256i,_mm256_or_si256,_mm_or_si128)
+BINARY_AVX_OP(__m256i,_mm256_xor_si256,_mm_xor_si128)
+
+
+BINARY_AVX_OP(__m256,_mm256_unpackhi_ps,_mm_unpackhi_ps)
+BINARY_AVX_OP(__m256,_mm256_unpacklo_ps,_mm_unpacklo_ps)
+TERNARY_AVX_OP(__m256,_mm256_blendv_ps,_mm_blendv_ps)
+TERNARY_AVX_OP(__m256i,_mm256_blendv_epi8,_mm_blendv_epi8)
+
+
+TERNARY_AVX_OP(__m256,_mm256_fmadd_ps,_mm_fmadd_ps)
+TERNARY_AVX_OP(__m256,_mm256_fnmadd_ps,_mm_fnmadd_ps)
+TERNARY_AVX_OP(__m256,_mm256_fmsub_ps,_mm_fmsub_ps)
+TERNARY_AVX_OP(__m256,_mm256_fnmsub_ps,_mm_fnmsub_ps)
+
+
+
+BINARY_AVX_OP(__m256i,_mm256_packs_epi32,_mm_packs_epi32)
+BINARY_AVX_OP(__m256i,_mm256_packs_epi16,_mm_packs_epi16)
+BINARY_AVX_OP(__m256i,_mm256_packus_epi32,_mm_packus_epi32)
+BINARY_AVX_OP(__m256i,_mm256_packus_epi16,_mm_packus_epi16)
+
+
+BINARY_AVX_OP(__m256i,_mm256_unpackhi_epi64,_mm_unpackhi_epi64)
+BINARY_AVX_OP(__m256i,_mm256_unpackhi_epi32,_mm_unpackhi_epi32)
+BINARY_AVX_OP(__m256i,_mm256_unpackhi_epi16,_mm_unpackhi_epi16)
+BINARY_AVX_OP(__m256i,_mm256_unpackhi_epi8,_mm_unpackhi_epi8)
+
+BINARY_AVX_OP(__m256i,_mm256_unpacklo_epi64,_mm_unpacklo_epi64)
+BINARY_AVX_OP(__m256i,_mm256_unpacklo_epi32,_mm_unpacklo_epi32)
+BINARY_AVX_OP(__m256i,_mm256_unpacklo_epi16,_mm_unpacklo_epi16)
+BINARY_AVX_OP(__m256i,_mm256_unpacklo_epi8,_mm_unpacklo_epi8)
+
+BINARY_AVX_OP(__m256i,_mm256_mulhrs_epi16,_mm_mulhrs_epi16)
+BINARY_AVX_OP(__m256i,_mm256_mulhi_epu16,_mm_mulhi_epu16)
+BINARY_AVX_OP(__m256i,_mm256_mulhi_epi16,_mm_mulhi_epi16)
+//BINARY_AVX_OP(__m256i,_mm256_mullo_epu16,_mm_mullo_epu16)
+BINARY_AVX_OP(__m256i,_mm256_mullo_epi16,_mm_mullo_epi16)
+
+BINARY_AVX_OP(__m256i,_mm256_subs_epu16,_mm_subs_epu16)
+BINARY_AVX_OP(__m256i,_mm256_adds_epu16,_mm_adds_epu16)
+BINARY_AVX_OP(__m256i,_mm256_subs_epi16,_mm_subs_epi16)
+BINARY_AVX_OP(__m256i,_mm256_adds_epi16,_mm_adds_epi16)
+BINARY_AVX_OP(__m256i,_mm256_sub_epi16,_mm_sub_epi16)
+BINARY_AVX_OP(__m256i,_mm256_add_epi16,_mm_add_epi16)
+BINARY_AVX_OP(__m256i,_mm256_sub_epi8,_mm_sub_epi8)
+
+
+BINARY_AVX_OP(__m256i,_mm256_hadd_epi16,_mm_hadd_epi16)
+BINARY_AVX_OP(__m256i,_mm256_hadds_epi16,_mm_hadds_epi16)
+
+
+
+
+BINARY_AVX_OP(__m256i,_mm256_cmpeq_epi32,_mm_cmpeq_epi32)
+BINARY_AVX_OP(__m256i,_mm256_cmpgt_epi32,_mm_cmpgt_epi32)
+
+BINARY_AVX_OP(__m256i,_mm256_cmpeq_epi8,_mm_cmpeq_epi8)
+BINARY_AVX_OP(__m256i,_mm256_cmpgt_epi8,_mm_cmpgt_epi8)
+
+BINARY_AVX_OP(__m256i,_mm256_cmpeq_epi16,_mm_cmpeq_epi16)
+BINARY_AVX_OP(__m256i,_mm256_cmpgt_epi16,_mm_cmpgt_epi16)
+
+
+BINARY_AVX_OP(__m256i,_mm256_shuffle_epi8,_mm_shuffle_epi8)
+
+
+BINARY_AVX_OP(__m256,_mm256_cmpeq_ps,_mm_cmpeq_ps)
+BINARY_AVX_OP(__m256,_mm256_cmpneq_ps,_mm_cmpneq_ps)
+BINARY_AVX_OP(__m256,_mm256_cmpnlt_ps,_mm_cmpnlt_ps)
+BINARY_AVX_OP(__m256,_mm256_cmpngt_ps,_mm_cmpngt_ps)
+BINARY_AVX_OP(__m256,_mm256_cmpge_ps,_mm_cmpge_ps)
+BINARY_AVX_OP(__m256,_mm256_cmpnge_ps,_mm_cmpnge_ps)
+BINARY_AVX_OP(__m256,_mm256_cmplt_ps,_mm_cmplt_ps)
+BINARY_AVX_OP(__m256,_mm256_cmple_ps,_mm_cmple_ps)
+BINARY_AVX_OP(__m256,_mm256_cmpgt_ps,_mm_cmpgt_ps)
+BINARY_AVX_OP(__m256,_mm256_cmpnle_ps,_mm_cmpnle_ps)
+
+
+AVX2NEON_ABI
+__m256i _mm256_cvtps_epi32 (__m256 a)
+{
+ __m256i res;
+ res.lo = _mm_cvtps_epi32(a.lo);
+ res.hi = _mm_cvtps_epi32(a.hi);
+ return res;
+
+}
+
+AVX2NEON_ABI
+__m256i _mm256_cvttps_epi32 (__m256 a)
+{
+ __m256i res;
+ res.lo = _mm_cvttps_epi32(a.lo);
+ res.hi = _mm_cvttps_epi32(a.hi);
+ return res;
+
+}
+
+AVX2NEON_ABI
+__m256 _mm256_loadu_ps (float const * mem_addr)
+{
+ __m256 res;
+ res.lo = *(__m128 *)(mem_addr + 0);
+ res.hi = *(__m128 *)(mem_addr + 4);
+ return res;
+}
+#define _mm256_load_ps _mm256_loadu_ps
+
+
+AVX2NEON_ABI
+int _mm256_testz_ps (const __m256& a, const __m256& b)
+{
+ __m256 t = a;
+ if (&a != &b)
+ t = _mm256_and_ps(a,b);
+
+ int32x4_t l = vshrq_n_s32(vreinterpretq_s32_m128(t.lo),31);
+ int32x4_t h = vshrq_n_s32(vreinterpretq_s32_m128(t.hi),31);
+ return vaddvq_s32(vaddq_s32(l,h)) == 0;
+}
+
+
+AVX2NEON_ABI
+__m256i _mm256_set_epi64x (int64_t e3, int64_t e2, int64_t e1, int64_t e0)
+{
+ __m256i res;
+ int64x2_t t0 = {e0,e1};
+ int64x2_t t1 = {e2,e3};
+ res.lo = __m128i(t0);
+ res.hi = __m128i(t1);
+ return res;
+}
+AVX2NEON_ABI
+__m256i _mm256_setr_epi64x (int64_t e0, int64_t e1, int64_t e2, int64_t e3)
+{
+ __m256i res;
+ int64x2_t t0 = {e0,e1};
+ int64x2_t t1 = {e2,e3};
+ res.lo = __m128i(t0);
+ res.hi = __m128i(t1);
+ return res;
+}
+
+
+
+AVX2NEON_ABI
+__m256i _mm256_set_epi8 (char e31, char e30, char e29, char e28, char e27, char e26, char e25, char e24, char e23, char e22, char e21, char e20, char e19, char e18, char e17, char e16, char e15, char e14, char e13, char e12, char e11, char e10, char e9, char e8, char e7, char e6, char e5, char e4, char e3, char e2, char e1, char e0)
+{
+ int8x16_t lo = {e0,e1,e2,e3,e4,e5,e6,e7,e8,e9,e10,e11,e12,e13,e14,e15};
+ int8x16_t hi = {e16,e17,e18,e19,e20,e21,e22,e23,e24,e25,e26,e27,e28,e29,e30,e31};
+ __m256i res;
+ res.lo = lo; res.hi = hi;
+ return res;
+}
+
+AVX2NEON_ABI
+__m256i _mm256_setr_epi8 (char e0, char e1, char e2, char e3, char e4, char e5, char e6, char e7, char e8, char e9, char e10, char e11, char e12, char e13, char e14, char e15, char e16, char e17, char e18, char e19, char e20, char e21, char e22, char e23, char e24, char e25, char e26, char e27, char e28, char e29, char e30, char e31)
+{
+ int8x16_t lo = {e0,e1,e2,e3,e4,e5,e6,e7,e8,e9,e10,e11,e12,e13,e14,e15};
+ int8x16_t hi = {e16,e17,e18,e19,e20,e21,e22,e23,e24,e25,e26,e27,e28,e29,e30,e31};
+ __m256i res;
+ res.lo = lo; res.hi = hi;
+ return res;
+}
+
+
+AVX2NEON_ABI
+__m256i _mm256_set_epi16 (short e15, short e14, short e13, short e12, short e11, short e10, short e9, short e8, short e7, short e6, short e5, short e4, short e3, short e2, short e1, short e0)
+{
+ int16x8_t lo = {e0,e1,e2,e3,e4,e5,e6,e7};
+ int16x8_t hi = {e8,e9,e10,e11,e12,e13,e14,e15};
+ __m256i res;
+ res.lo = lo; res.hi = hi;
+ return res;
+}
+
+AVX2NEON_ABI
+__m256i _mm256_setr_epi16 (short e0, short e1, short e2, short e3, short e4, short e5, short e6, short e7, short e8, short e9, short e10, short e11, short e12, short e13, short e14, short e15)
+{
+ int16x8_t lo = {e0,e1,e2,e3,e4,e5,e6,e7};
+ int16x8_t hi = {e8,e9,e10,e11,e12,e13,e14,e15};
+ __m256i res;
+ res.lo = lo; res.hi = hi;
+ return res;
+}
+
+
+
+
+AVX2NEON_ABI
+int _mm256_movemask_epi8(const __m256i& a)
+{
+ return (_mm_movemask_epi8(a.hi) << 16) | _mm_movemask_epi8(a.lo);
+}
+
+
+AVX2NEON_ABI
+int _mm256_testz_si256(const __m256i& a,const __m256i& b)
+{
+ uint32x4_t lo = vandq_u32(a.lo,b.lo);
+ uint32x4_t hi = vandq_u32(a.hi,b.hi);
+
+ return (vaddvq_u32(lo) + vaddvq_u32(hi)) == 0;
+}
+
+AVX2NEON_ABI
+__m256d _mm256_setzero_pd ()
+{
+ __m256d res;
+ res.lo = res.hi = vdupq_n_f64(0);
+ return res;
+}
+
+AVX2NEON_ABI
+int _mm256_movemask_pd (__m256d a)
+{
+ return (_mm_movemask_pd(a.hi) << 2) | _mm_movemask_pd(a.lo);
+}
+
+AVX2NEON_ABI
+__m256i _mm256_cmpeq_epi64 (__m256i a, __m256i b)
+{
+ __m256i res;
+ res.lo = _mm_cmpeq_epi64(a.lo, b.lo);
+ res.hi = _mm_cmpeq_epi64(a.hi, b.hi);
+ return res;
+}
+
+AVX2NEON_ABI
+__m256d _mm256_cmpeq_pd (__m256d a, __m256d b)
+{
+ __m256d res;
+ res.lo = _mm_cmpeq_pd(a.lo, b.lo);
+ res.hi = _mm_cmpeq_pd(a.hi, b.hi);
+ return res;
+}
+
+
+AVX2NEON_ABI
+int _mm256_testz_pd (const __m256d& a, const __m256d& b)
+{
+ __m256d t = a;
+
+ if (&a != &b)
+ t = _mm256_and_pd(a,b);
+
+ return _mm256_movemask_pd(t) == 0;
+}
+
+AVX2NEON_ABI
+__m256d _mm256_blendv_pd (__m256d a, __m256d b, __m256d mask)
+{
+ __m256d res;
+ res.lo = _mm_blendv_pd(a.lo, b.lo, mask.lo);
+ res.hi = _mm_blendv_pd(a.hi, b.hi, mask.hi);
+ return res;
+}
+
+template<int imm8>
+AVX2NEON_ABI
+__m256 __mm256_dp_ps (__m256 a, __m256 b)
+{
+ __m256 res;
+ res.lo = _mm_dp_ps(a.lo, b.lo, imm8);
+ res.hi = _mm_dp_ps(a.hi, b.hi, imm8);
+ return res;
+}
+
+#define _mm256_dp_ps(a,b,c) __mm256_dp_ps<c>(a,b)
+
+AVX2NEON_ABI
+double _mm256_permute4x64_pd_select(__m256d a, const int imm8)
+{
+ switch (imm8 & 3) {
+ case 0:
+ return ((float64x2_t)a.lo)[0];
+ case 1:
+ return ((float64x2_t)a.lo)[1];
+ case 2:
+ return ((float64x2_t)a.hi)[0];
+ case 3:
+ return ((float64x2_t)a.hi)[1];
+ }
+ __builtin_unreachable();
+ return 0;
+}
+
+AVX2NEON_ABI
+__m256d _mm256_permute4x64_pd (__m256d a, const int imm8)
+{
+ float64x2_t lo,hi;
+ lo[0] = _mm256_permute4x64_pd_select(a,imm8 >> 0);
+ lo[1] = _mm256_permute4x64_pd_select(a,imm8 >> 2);
+ hi[0] = _mm256_permute4x64_pd_select(a,imm8 >> 4);
+ hi[1] = _mm256_permute4x64_pd_select(a,imm8 >> 6);
+
+ __m256d res;
+ res.lo = lo; res.hi = hi;
+ return res;
+}
+
+AVX2NEON_ABI
+__m256i _mm256_insertf128_si256 (__m256i a, __m128i b, int imm8)
+{
+ return __m256i(_mm256_insertf128_ps((__m256)a,(__m128)b,imm8));
+}
+
+
+AVX2NEON_ABI
+__m256i _mm256_loadu_si256 (__m256i const * mem_addr)
+{
+ __m256i res;
+ res.lo = *(__m128i *)((int32_t *)mem_addr + 0);
+ res.hi = *(__m128i *)((int32_t *)mem_addr + 4);
+ return res;
+}
+
+#define _mm256_load_si256 _mm256_loadu_si256
+
+AVX2NEON_ABI
+void _mm256_storeu_ps (float * mem_addr, __m256 a)
+{
+ *(__m128 *)(mem_addr + 0) = a.lo;
+ *(__m128 *)(mem_addr + 4) = a.hi;
+}
+
+#define _mm256_store_ps _mm256_storeu_ps
+#define _mm256_stream_ps _mm256_storeu_ps
+
+
+AVX2NEON_ABI
+void _mm256_storeu_si256 (__m256i * mem_addr, __m256i a)
+{
+ *(__m128i *)((int32_t *)mem_addr + 0) = a.lo;
+ *(__m128i *)((int32_t *)mem_addr + 4) = a.hi;
+}
+
+#define _mm256_store_si256 _mm256_storeu_si256
+
+
+
+AVX2NEON_ABI
+__m256i _mm256_permute4x64_epi64 (const __m256i a, const int imm8)
+{
+ uint8x16x2_t tbl = {a.lo, a.hi};
+
+ uint8_t sz = sizeof(uint64_t);
+ uint8_t u64[4] = {
+ (uint8_t)(((imm8 >> 0) & 0x3) * sz),
+ (uint8_t)(((imm8 >> 2) & 0x3) * sz),
+ (uint8_t)(((imm8 >> 4) & 0x3) * sz),
+ (uint8_t)(((imm8 >> 6) & 0x3) * sz),
+ };
+
+ uint8x16_t idx_lo = {
+ // lo[0] bytes
+ (uint8_t)(u64[0]+0), (uint8_t)(u64[0]+1), (uint8_t)(u64[0]+2), (uint8_t)(u64[0]+3),
+ (uint8_t)(u64[0]+4), (uint8_t)(u64[0]+5), (uint8_t)(u64[0]+6), (uint8_t)(u64[0]+7),
+
+ // lo[1] bytes
+ (uint8_t)(u64[1]+0), (uint8_t)(u64[1]+1), (uint8_t)(u64[1]+2), (uint8_t)(u64[1]+3),
+ (uint8_t)(u64[1]+4), (uint8_t)(u64[1]+5), (uint8_t)(u64[1]+6), (uint8_t)(u64[1]+7),
+ };
+ uint8x16_t idx_hi = {
+ // hi[0] bytes
+ (uint8_t)(u64[2]+0), (uint8_t)(u64[2]+1), (uint8_t)(u64[2]+2), (uint8_t)(u64[2]+3),
+ (uint8_t)(u64[2]+4), (uint8_t)(u64[2]+5), (uint8_t)(u64[2]+6), (uint8_t)(u64[2]+7),
+
+ // hi[1] bytes
+ (uint8_t)(u64[3]+0), (uint8_t)(u64[3]+1), (uint8_t)(u64[3]+2), (uint8_t)(u64[3]+3),
+ (uint8_t)(u64[3]+4), (uint8_t)(u64[3]+5), (uint8_t)(u64[3]+6), (uint8_t)(u64[3]+7),
+ };
+
+ uint8x16_t lo = vqtbl2q_u8(tbl, idx_lo);
+ uint8x16_t hi = vqtbl2q_u8(tbl, idx_hi);
+
+ __m256i res;
+ res.lo = lo; res.hi = hi;
+ return res;
+}
+
+
+AVX2NEON_ABI
+__m256i _mm256_permute2x128_si256(const __m256i a,const __m256i b, const int imm8)
+{
+ return __m256i(_mm256_permute2f128_ps(__m256(a),__m256(b),imm8));
+}
+
+
+
+AVX2NEON_ABI
+__m256 _mm256_maskload_ps (float const * mem_addr, __m256i mask)
+{
+ __m256 res;
+ res.lo = _mm_maskload_ps(mem_addr,mask.lo);
+ res.hi = _mm_maskload_ps(mem_addr + 4,mask.hi);
+ return res;
+}
+
+
+AVX2NEON_ABI
+__m256i _mm256_cvtepu8_epi32 (__m128i a)
+{
+ uint8x16_t a_u8 = vreinterpretq_u8_m128i(a); // xxxx xxxx xxxx xxxx HHGG FFEE DDCC BBAA
+ uint16x8_t u16x8 = vmovl_u8(vget_low_u8(a_u8)); // 00HH 00GG 00FF 00EE 00DD 00CC 00BB 00AA
+ uint32x4_t lo = vmovl_u16(vget_low_u16(u16x8)); // 0000 00DD 0000 00CC 0000 00BB 0000 00AA
+ uint32x4_t hi = vmovl_high_u16(u16x8); // 0000 00HH 0000 00GG 0000 00FF 0000 00EE
+
+ __m256i res;
+ res.lo = lo; res.hi = hi;
+ return res;
+}
+
+
+AVX2NEON_ABI
+__m256i _mm256_cvtepi8_epi32 (__m128i a)
+{
+ int8x16_t a_s8 = vreinterpretq_s8_m128i(a); // xxxx xxxx xxxx xxxx HHGG FFEE DDCC BBAA
+ int16x8_t s16x8 = vmovl_s8(vget_low_s8(a_s8)); // ssHH ssGG ssFF ssEE ssDD ssCC ssBB ssAA
+ int32x4_t lo = vmovl_s16(vget_low_s16(s16x8)); // ssss ssDD ssss ssCC ssss ssBB ssss ssAA
+ int32x4_t hi = vmovl_high_s16(s16x8); // ssss ssHH ssss ssGG ssss ssFF ssss ssEE
+
+ __m256i res;
+ res.lo = lo; res.hi = hi;
+ return res;
+}
+
+
+AVX2NEON_ABI
+__m256i _mm256_cvtepi16_epi32 (__m128i a)
+{
+ int16x8_t a_s16 = vreinterpretq_s16_m128i(a); // HHHH GGGG FFFF EEEE DDDD CCCC BBBB AAAA
+ int32x4_t lo = vmovl_s16(vget_low_s16(a_s16)); // ssss DDDD ssss CCCC ssss BBBB ssss AAAA
+ int32x4_t hi = vmovl_high_s16(a_s16); // ssss HHHH ssss GGGG ssss FFFF ssss EEEE
+
+ __m256i res;
+ res.lo = lo; res.hi = hi;
+ return res;
+}
+
+
+
+AVX2NEON_ABI
+void _mm256_maskstore_epi32 (int* mem_addr, __m256i mask, __m256i a)
+{
+ _mm_maskstore_epi32(mem_addr,mask.lo,a.lo);
+ _mm_maskstore_epi32(mem_addr + 4,mask.hi,a.hi);
+}
+
+AVX2NEON_ABI
+__m256i _mm256_slli_epi64 (__m256i a, int imm8)
+{
+ __m256i res;
+ res.lo = _mm_slli_epi64(a.lo,imm8);
+ res.hi = _mm_slli_epi64(a.hi,imm8);
+ return res;
+}
+
+AVX2NEON_ABI
+__m256i _mm256_slli_epi32 (__m256i a, int imm8)
+{
+ __m256i res;
+ res.lo = _mm_slli_epi32(a.lo,imm8);
+ res.hi = _mm_slli_epi32(a.hi,imm8);
+ return res;
+}
+
+
+AVX2NEON_ABI
+__m256i __mm256_slli_epi16 (__m256i a, int imm8)
+{
+ __m256i res;
+ res.lo = _mm_slli_epi16(a.lo,imm8);
+ res.hi = _mm_slli_epi16(a.hi,imm8);
+ return res;
+}
+
+
+AVX2NEON_ABI
+__m256i _mm256_srli_epi32 (__m256i a, int imm8)
+{
+ __m256i res;
+ res.lo = _mm_srli_epi32(a.lo,imm8);
+ res.hi = _mm_srli_epi32(a.hi,imm8);
+ return res;
+}
+
+AVX2NEON_ABI
+__m256i __mm256_srli_epi16 (__m256i a, int imm8)
+{
+ __m256i res;
+ res.lo = _mm_srli_epi16(a.lo,imm8);
+ res.hi = _mm_srli_epi16(a.hi,imm8);
+ return res;
+}
+
+AVX2NEON_ABI
+__m256i _mm256_cvtepu16_epi32(__m128i a)
+{
+ __m256i res;
+ res.lo = vmovl_u16(vget_low_u16(a));
+ res.hi = vmovl_high_u16(a);
+ return res;
+}
+
+AVX2NEON_ABI
+__m256i _mm256_cvtepu8_epi16(__m128i a)
+{
+ __m256i res;
+ res.lo = vmovl_u8(vget_low_u8(a));
+ res.hi = vmovl_high_u8(a);
+ return res;
+}
+
+
+AVX2NEON_ABI
+__m256i _mm256_srai_epi32 (__m256i a, int imm8)
+{
+ __m256i res;
+ res.lo = _mm_srai_epi32(a.lo,imm8);
+ res.hi = _mm_srai_epi32(a.hi,imm8);
+ return res;
+}
+
+AVX2NEON_ABI
+__m256i _mm256_srai_epi16 (__m256i a, int imm8)
+{
+ __m256i res;
+ res.lo = _mm_srai_epi16(a.lo,imm8);
+ res.hi = _mm_srai_epi16(a.hi,imm8);
+ return res;
+}
+
+
+AVX2NEON_ABI
+__m256i _mm256_sllv_epi32 (__m256i a, __m256i count)
+{
+ __m256i res;
+ res.lo = vshlq_s32(a.lo,count.lo);
+ res.hi = vshlq_s32(a.hi,count.hi);
+ return res;
+
+}
+
+
+AVX2NEON_ABI
+__m256i _mm256_srav_epi32 (__m256i a, __m256i count)
+{
+ __m256i res;
+ res.lo = vshlq_s32(a.lo,vnegq_s32(count.lo));
+ res.hi = vshlq_s32(a.hi,vnegq_s32(count.hi));
+ return res;
+
+}
+
+AVX2NEON_ABI
+__m256i _mm256_srlv_epi32 (__m256i a, __m256i count)
+{
+ __m256i res;
+ res.lo = __m128i(vshlq_u32(uint32x4_t(a.lo),vnegq_s32(count.lo)));
+ res.hi = __m128i(vshlq_u32(uint32x4_t(a.hi),vnegq_s32(count.hi)));
+ return res;
+
+}
+
+
+AVX2NEON_ABI
+__m256i _mm256_permute2f128_si256 (__m256i a, __m256i b, int imm8)
+{
+ return __m256i(_mm256_permute2f128_ps(__m256(a),__m256(b),imm8));
+}
+
+
+AVX2NEON_ABI
+__m128i _mm256_extractf128_si256 (__m256i a, const int imm8)
+{
+ if (imm8 & 1) return a.hi;
+ return a.lo;
+}
+
+AVX2NEON_ABI
+__m256 _mm256_set1_ps(float x)
+{
+ __m256 res;
+ res.lo = res.hi = vdupq_n_f32(x);
+ return res;
+}
+
+AVX2NEON_ABI
+__m256 _mm256_set_ps (float e7, float e6, float e5, float e4, float e3, float e2, float e1, float e0)
+{
+ __m256 res;
+ res.lo = _mm_set_ps(e3,e2,e1,e0);
+ res.hi = _mm_set_ps(e7,e6,e5,e4);
+ return res;
+}
+
+AVX2NEON_ABI
+__m256 _mm256_broadcast_ps (__m128 const * mem_addr)
+{
+ __m256 res;
+ res.lo = res.hi = *mem_addr;
+ return res;
+}
+
+AVX2NEON_ABI
+__m256 _mm256_cvtepi32_ps (__m256i a)
+{
+ __m256 res;
+ res.lo = _mm_cvtepi32_ps(a.lo);
+ res.hi = _mm_cvtepi32_ps(a.hi);
+ return res;
+}
+AVX2NEON_ABI
+void _mm256_maskstore_ps (float * mem_addr, __m256i mask, __m256 a)
+{
+ uint32x4_t mask_lo = mask.lo;
+ uint32x4_t mask_hi = mask.hi;
+ float32x4_t a_lo = a.lo;
+ float32x4_t a_hi = a.hi;
+
+ for (int i=0;i<4;i++) {
+ if (mask_lo[i] & 0x80000000) mem_addr[i] = a_lo[i];
+ if (mask_hi[i] & 0x80000000) mem_addr[i+4] = a_hi[i];
+ }
+}
+
+AVX2NEON_ABI
+__m256d _mm256_andnot_pd (__m256d a, __m256d b)
+{
+ __m256d res;
+ res.lo = float64x2_t(_mm_andnot_ps(__m128(a.lo),__m128(b.lo)));
+ res.hi = float64x2_t(_mm_andnot_ps(__m128(a.hi),__m128(b.hi)));
+ return res;
+}
+
+AVX2NEON_ABI
+__m256 _mm256_blend_ps (__m256 a, __m256 b, const int imm8)
+{
+ __m256 res;
+ res.lo = _mm_blend_ps(a.lo,b.lo,imm8 & 0xf);
+ res.hi = _mm_blend_ps(a.hi,b.hi,imm8 >> 4);
+ return res;
+
+}
+
+
+AVX2NEON_ABI
+__m256i _mm256_blend_epi32 (__m256i a, __m256i b, const int imm8)
+{
+ return __m256i(_mm256_blend_ps(__m256(a),__m256(b),imm8));
+
+}
+
+AVX2NEON_ABI
+__m256i _mm256_blend_epi16 (__m256i a, __m256i b, const int imm8)
+{
+ __m256i res;
+ res.lo = _mm_blend_epi16(a.lo,b.lo,imm8);
+ res.hi = _mm_blend_epi16(a.hi,b.hi,imm8);
+ return res;
+}
+
+
+
+AVX2NEON_ABI
+__m256i _mm256_i32gather_epi32 (int const* base_addr, __m256i vindex, const int scale)
+{
+ int32x4_t vindex_lo = vindex.lo;
+ int32x4_t vindex_hi = vindex.hi;
+ int32x4_t lo,hi;
+ for (int i=0;i<4;i++)
+ {
+ lo[i] = *(int32_t *)((char *) base_addr + (vindex_lo[i]*scale));
+ hi[i] = *(int32_t *)((char *) base_addr + (vindex_hi[i]*scale));
+ }
+
+ __m256i res;
+ res.lo = lo; res.hi = hi;
+ return res;
+}
+
+
+AVX2NEON_ABI
+__m256i _mm256_mask_i32gather_epi32 (__m256i src, int const* base_addr, __m256i vindex, __m256i mask, const int scale)
+{
+ uint32x4_t mask_lo = mask.lo;
+ uint32x4_t mask_hi = mask.hi;
+ int32x4_t vindex_lo = vindex.lo;
+ int32x4_t vindex_hi = vindex.hi;
+ int32x4_t lo,hi;
+ lo = hi = _mm_setzero_si128();
+ for (int i=0;i<4;i++)
+ {
+ if (mask_lo[i] >> 31) lo[i] = *(int32_t *)((char *) base_addr + (vindex_lo[i]*scale));
+ if (mask_hi[i] >> 31) hi[i] = *(int32_t *)((char *) base_addr + (vindex_hi[i]*scale));
+ }
+
+ __m256i res;
+ res.lo = lo; res.hi = hi;
+ return res;
+}
diff --git a/thirdparty/embree/common/simd/arm/emulation.h b/thirdparty/embree/common/simd/arm/emulation.h
index 1c3875fb27..4327298019 100644
--- a/thirdparty/embree/common/simd/arm/emulation.h
+++ b/thirdparty/embree/common/simd/arm/emulation.h
@@ -11,33 +11,28 @@
#include "sse2neon.h"
-__forceinline __m128 _mm_fmsub_ps(__m128 a, __m128 b, __m128 c) {
- __m128 neg_c = vreinterpretq_m128_f32(vnegq_f32(vreinterpretq_f32_m128(c)));
- return _mm_fmadd_ps(a, b, neg_c);
-}
-
-__forceinline __m128 _mm_fnmadd_ps(__m128 a, __m128 b, __m128 c) {
-#if defined(__aarch64__)
- return vreinterpretq_m128_f32(vfmsq_f32(vreinterpretq_f32_m128(c),
- vreinterpretq_f32_m128(b),
- vreinterpretq_f32_m128(a)));
-#else
- return _mm_sub_ps(c, _mm_mul_ps(a, b));
-#endif
-}
+__forceinline __m128 _mm_abs_ps(__m128 a) { return vabsq_f32(a); }
+
+__forceinline __m128 _mm_fmadd_ps (__m128 a, __m128 b, __m128 c) { return vfmaq_f32(c, a, b); }
+__forceinline __m128 _mm_fnmadd_ps(__m128 a, __m128 b, __m128 c) { return vfmsq_f32(c, a, b); }
+__forceinline __m128 _mm_fnmsub_ps(__m128 a, __m128 b, __m128 c) { return vnegq_f32(vfmaq_f32(c, a, b)); }
+__forceinline __m128 _mm_fmsub_ps (__m128 a, __m128 b, __m128 c) { return vnegq_f32(vfmsq_f32(c, a, b)); }
-__forceinline __m128 _mm_fnmsub_ps(__m128 a, __m128 b, __m128 c) {
- return vreinterpretq_m128_f32(vnegq_f32(vreinterpretq_f32_m128(_mm_fmadd_ps(a,b,c))));
+__forceinline __m128 _mm_broadcast_ss (float const * mem_addr)
+{
+ return vdupq_n_f32(*mem_addr);
}
+// AVX2 emulation leverages Intel FMA defs above. Include after them.
+#include "avx2neon.h"
/* Dummy defines for floating point control */
#define _MM_MASK_MASK 0x1f80
#define _MM_MASK_DIV_ZERO 0x200
-#define _MM_FLUSH_ZERO_ON 0x8000
+// #define _MM_FLUSH_ZERO_ON 0x8000
#define _MM_MASK_DENORM 0x100
#define _MM_SET_EXCEPTION_MASK(x)
-#define _MM_SET_FLUSH_ZERO_MODE(x)
+// #define _MM_SET_FLUSH_ZERO_MODE(x)
__forceinline int _mm_getcsr()
{
@@ -48,3 +43,43 @@ __forceinline void _mm_mfence()
{
__sync_synchronize();
}
+
+__forceinline __m128i _mm_load4epu8_epi32(__m128i *ptr)
+{
+ uint8x8_t t0 = vld1_u8((uint8_t*)ptr);
+ uint16x8_t t1 = vmovl_u8(t0);
+ uint32x4_t t2 = vmovl_u16(vget_low_u16(t1));
+ return vreinterpretq_s32_u32(t2);
+}
+
+__forceinline __m128i _mm_load4epu16_epi32(__m128i *ptr)
+{
+ uint16x8_t t0 = vld1q_u16((uint16_t*)ptr);
+ uint32x4_t t1 = vmovl_u16(vget_low_u16(t0));
+ return vreinterpretq_s32_u32(t1);
+}
+
+__forceinline __m128i _mm_load4epi8_f32(__m128i *ptr)
+{
+ int8x8_t t0 = vld1_s8((int8_t*)ptr);
+ int16x8_t t1 = vmovl_s8(t0);
+ int32x4_t t2 = vmovl_s16(vget_low_s16(t1));
+ float32x4_t t3 = vcvtq_f32_s32(t2);
+ return vreinterpretq_s32_f32(t3);
+}
+
+__forceinline __m128i _mm_load4epu8_f32(__m128i *ptr)
+{
+ uint8x8_t t0 = vld1_u8((uint8_t*)ptr);
+ uint16x8_t t1 = vmovl_u8(t0);
+ uint32x4_t t2 = vmovl_u16(vget_low_u16(t1));
+ return vreinterpretq_s32_u32(t2);
+}
+
+__forceinline __m128i _mm_load4epi16_f32(__m128i *ptr)
+{
+ int16x8_t t0 = vld1q_s16((int16_t*)ptr);
+ int32x4_t t1 = vmovl_s16(vget_low_s16(t0));
+ float32x4_t t2 = vcvtq_f32_s32(t1);
+ return vreinterpretq_s32_f32(t2);
+}
diff --git a/thirdparty/embree/common/simd/arm/sse2neon.h b/thirdparty/embree/common/simd/arm/sse2neon.h
index 7eb25cf2c5..43416662d7 100644
--- a/thirdparty/embree/common/simd/arm/sse2neon.h
+++ b/thirdparty/embree/common/simd/arm/sse2neon.h
@@ -52,7 +52,7 @@
/* Enable precise implementation of math operations
* This would slow down the computation a bit, but gives consistent result with
- * x86 SSE2. (e.g. would solve a hole or NaN pixel in the rendering result)
+ * x86 SSE. (e.g. would solve a hole or NaN pixel in the rendering result)
*/
/* _mm_min_ps and _mm_max_ps */
#ifndef SSE2NEON_PRECISE_MINMAX
@@ -66,36 +66,29 @@
#ifndef SSE2NEON_PRECISE_SQRT
#define SSE2NEON_PRECISE_SQRT (0)
#endif
-#ifndef SSE2NEON_PRECISE_RSQRT
-#define SSE2NEON_PRECISE_RSQRT (0)
+/* _mm_dp_pd */
+#ifndef SSE2NEON_PRECISE_DP
+#define SSE2NEON_PRECISE_DP (0)
#endif
+/* compiler specific definitions */
#if defined(__GNUC__) || defined(__clang__)
#pragma push_macro("FORCE_INLINE")
#pragma push_macro("ALIGN_STRUCT")
#define FORCE_INLINE static inline __attribute__((always_inline))
#define ALIGN_STRUCT(x) __attribute__((aligned(x)))
-#ifndef likely
-#define likely(x) __builtin_expect(!!(x), 1)
-#endif
-#ifndef unlikely
-#define unlikely(x) __builtin_expect(!!(x), 0)
-#endif
-#else
-#error "Macro name collisions may happen with unsupported compiler."
-#ifdef FORCE_INLINE
-#undef FORCE_INLINE
-#endif
+#define _sse2neon_likely(x) __builtin_expect(!!(x), 1)
+#define _sse2neon_unlikely(x) __builtin_expect(!!(x), 0)
+#else /* non-GNU / non-clang compilers */
+#warning "Macro name collisions may happen with unsupported compiler."
+#ifndef FORCE_INLINE
#define FORCE_INLINE static inline
+#endif
#ifndef ALIGN_STRUCT
#define ALIGN_STRUCT(x) __declspec(align(x))
#endif
-#endif
-#ifndef likely
-#define likely(x) (x)
-#endif
-#ifndef unlikely
-#define unlikely(x) (x)
+#define _sse2neon_likely(x) (x)
+#define _sse2neon_unlikely(x) (x)
#endif
#include <stdint.h>
@@ -155,6 +148,14 @@
* argument "a" of mm_shuffle_ps that will be places in fp1 of result.
* fp0 is the same for fp0 of result.
*/
+#if defined(__aarch64__)
+#define _MN_SHUFFLE(fp3,fp2,fp1,fp0) ( (uint8x16_t){ (((fp3)*4)+0), (((fp3)*4)+1), (((fp3)*4)+2), (((fp3)*4)+3), (((fp2)*4)+0), (((fp2)*4)+1), (((fp2)*4)+\
+2), (((fp2)*4)+3), (((fp1)*4)+0), (((fp1)*4)+1), (((fp1)*4)+2), (((fp1)*4)+3), (((fp0)*4)+0), (((fp0)*4)+1), (((fp0)*4)+2), (((fp0)*4)+3) } )
+#define _MF_SHUFFLE(fp3,fp2,fp1,fp0) ( (uint8x16_t){ (((fp3)*4)+0), (((fp3)*4)+1), (((fp3)*4)+2), (((fp3)*4)+3), (((fp2)*4)+0), (((fp2)*4)+1), (((fp2)*4)+\
+2), (((fp2)*4)+3), (((fp1)*4)+16+0), (((fp1)*4)+16+1), (((fp1)*4)+16+2), (((fp1)*4)+16+3), (((fp0)*4)+16+0), (((fp0)*4)+16+1), (((fp0)*4)+16+2), (((fp0)*\
+4)+16+3) } )
+#endif
+
#define _MM_SHUFFLE(fp3, fp2, fp1, fp0) \
(((fp3) << 6) | ((fp2) << 4) | ((fp1) << 2) | ((fp0)))
@@ -169,6 +170,14 @@
#define _MM_ROUND_DOWN 0x2000
#define _MM_ROUND_UP 0x4000
#define _MM_ROUND_TOWARD_ZERO 0x6000
+/* Flush zero mode macros. */
+#define _MM_FLUSH_ZERO_MASK 0x8000
+#define _MM_FLUSH_ZERO_ON 0x8000
+#define _MM_FLUSH_ZERO_OFF 0x0000
+/* Denormals are zeros mode macros. */
+#define _MM_DENORMALS_ZERO_MASK 0x0040
+#define _MM_DENORMALS_ZERO_ON 0x0040
+#define _MM_DENORMALS_ZERO_OFF 0x0000
/* indicate immediate constant argument in a given range */
#define __constrange(a, b) const
@@ -189,7 +198,10 @@ typedef float64x2_t __m128d; /* 128-bit vector containing 2 doubles */
#else
typedef float32x4_t __m128d;
#endif
-typedef int64x2_t __m128i; /* 128-bit vector containing integers */
+// Note: upstream sse2neon declares __m128i as int64x2_t. However, there's
+// many places within embree that assume __m128i can be indexed as a
+// 4 element u32.
+typedef int32x4_t __m128i; /* 128-bit vector containing integers */
/* type-safe casting between types */
@@ -221,28 +233,28 @@ typedef int64x2_t __m128i; /* 128-bit vector containing integers */
#define vreinterpretq_s32_m128(x) vreinterpretq_s32_f32(x)
#define vreinterpretq_s64_m128(x) vreinterpretq_s64_f32(x)
-#define vreinterpretq_m128i_s8(x) vreinterpretq_s64_s8(x)
-#define vreinterpretq_m128i_s16(x) vreinterpretq_s64_s16(x)
-#define vreinterpretq_m128i_s32(x) vreinterpretq_s64_s32(x)
-#define vreinterpretq_m128i_s64(x) (x)
+#define vreinterpretq_m128i_s8(x) vreinterpretq_s32_s8(x)
+#define vreinterpretq_m128i_s16(x) vreinterpretq_s32_s16(x)
+#define vreinterpretq_m128i_s32(x) (x)
+#define vreinterpretq_m128i_s64(x) vreinterpretq_s32_s64(x)
-#define vreinterpretq_m128i_u8(x) vreinterpretq_s64_u8(x)
-#define vreinterpretq_m128i_u16(x) vreinterpretq_s64_u16(x)
-#define vreinterpretq_m128i_u32(x) vreinterpretq_s64_u32(x)
-#define vreinterpretq_m128i_u64(x) vreinterpretq_s64_u64(x)
+#define vreinterpretq_m128i_u8(x) vreinterpretq_s32_u8(x)
+#define vreinterpretq_m128i_u16(x) vreinterpretq_s32_u16(x)
+#define vreinterpretq_m128i_u32(x) vreinterpretq_s32_u32(x)
+#define vreinterpretq_m128i_u64(x) vreinterpretq_s32_u64(x)
-#define vreinterpretq_f32_m128i(x) vreinterpretq_f32_s64(x)
-#define vreinterpretq_f64_m128i(x) vreinterpretq_f64_s64(x)
+#define vreinterpretq_f32_m128i(x) vreinterpretq_f32_s32(x)
+#define vreinterpretq_f64_m128i(x) vreinterpretq_f64_s32(x)
-#define vreinterpretq_s8_m128i(x) vreinterpretq_s8_s64(x)
-#define vreinterpretq_s16_m128i(x) vreinterpretq_s16_s64(x)
-#define vreinterpretq_s32_m128i(x) vreinterpretq_s32_s64(x)
-#define vreinterpretq_s64_m128i(x) (x)
+#define vreinterpretq_s8_m128i(x) vreinterpretq_s8_s32(x)
+#define vreinterpretq_s16_m128i(x) vreinterpretq_s16_s32(x)
+#define vreinterpretq_s32_m128i(x) (x)
+#define vreinterpretq_s64_m128i(x) vreinterpretq_s64_s32(x)
-#define vreinterpretq_u8_m128i(x) vreinterpretq_u8_s64(x)
-#define vreinterpretq_u16_m128i(x) vreinterpretq_u16_s64(x)
-#define vreinterpretq_u32_m128i(x) vreinterpretq_u32_s64(x)
-#define vreinterpretq_u64_m128i(x) vreinterpretq_u64_s64(x)
+#define vreinterpretq_u8_m128i(x) vreinterpretq_u8_s32(x)
+#define vreinterpretq_u16_m128i(x) vreinterpretq_u16_s32(x)
+#define vreinterpretq_u32_m128i(x) vreinterpretq_u32_s32(x)
+#define vreinterpretq_u64_m128i(x) vreinterpretq_u64_s32(x)
#define vreinterpret_m64_s8(x) vreinterpret_s64_s8(x)
#define vreinterpret_m64_s16(x) vreinterpret_s64_s16(x)
@@ -281,6 +293,7 @@ typedef int64x2_t __m128i; /* 128-bit vector containing integers */
#define vreinterpretq_s64_m128d(x) vreinterpretq_s64_f64(x)
+#define vreinterpretq_u32_m128d(x) vreinterpretq_u32_f64(x)
#define vreinterpretq_u64_m128d(x) vreinterpretq_u64_f64(x)
#define vreinterpretq_f64_m128d(x) (x)
@@ -303,10 +316,10 @@ typedef int64x2_t __m128i; /* 128-bit vector containing integers */
#endif
// A struct is defined in this header file called 'SIMDVec' which can be used
-// by applications which attempt to access the contents of an _m128 struct
+// by applications which attempt to access the contents of an __m128 struct
// directly. It is important to note that accessing the __m128 struct directly
// is bad coding practice by Microsoft: @see:
-// https://msdn.microsoft.com/en-us/library/ayeb3ayc.aspx
+// https://docs.microsoft.com/en-us/cpp/cpp/m128
//
// However, some legacy source code may try to access the contents of an __m128
// struct directly so the developer can use the SIMDVec as an alias for it. Any
@@ -342,13 +355,48 @@ typedef union ALIGN_STRUCT(16) SIMDVec {
#define vreinterpretq_nth_u32_m128i(x, n) (((SIMDVec *) &x)->m128_u32[n])
#define vreinterpretq_nth_u8_m128i(x, n) (((SIMDVec *) &x)->m128_u8[n])
+/* SSE macros */
+#define _MM_GET_FLUSH_ZERO_MODE _sse2neon_mm_get_flush_zero_mode
+#define _MM_SET_FLUSH_ZERO_MODE _sse2neon_mm_set_flush_zero_mode
+#define _MM_GET_DENORMALS_ZERO_MODE _sse2neon_mm_get_denormals_zero_mode
+#define _MM_SET_DENORMALS_ZERO_MODE _sse2neon_mm_set_denormals_zero_mode
+
+// Function declaration
+// SSE
+FORCE_INLINE unsigned int _MM_GET_ROUNDING_MODE();
+FORCE_INLINE __m128 _mm_move_ss(__m128, __m128);
+FORCE_INLINE __m128 _mm_or_ps(__m128, __m128);
+FORCE_INLINE __m128 _mm_set_ps1(float);
+FORCE_INLINE __m128 _mm_setzero_ps(void);
+// SSE2
+FORCE_INLINE __m128i _mm_and_si128(__m128i, __m128i);
+FORCE_INLINE __m128i _mm_castps_si128(__m128);
+FORCE_INLINE __m128i _mm_cmpeq_epi32(__m128i, __m128i);
+FORCE_INLINE __m128i _mm_cvtps_epi32(__m128);
+FORCE_INLINE __m128d _mm_move_sd(__m128d, __m128d);
+FORCE_INLINE __m128i _mm_or_si128(__m128i, __m128i);
+FORCE_INLINE __m128i _mm_set_epi32(int, int, int, int);
+FORCE_INLINE __m128i _mm_set_epi64x(int64_t, int64_t);
+FORCE_INLINE __m128d _mm_set_pd(double, double);
+FORCE_INLINE __m128i _mm_set1_epi32(int);
+FORCE_INLINE __m128i _mm_setzero_si128();
+// SSE4.1
+FORCE_INLINE __m128d _mm_ceil_pd(__m128d);
+FORCE_INLINE __m128 _mm_ceil_ps(__m128);
+FORCE_INLINE __m128d _mm_floor_pd(__m128d);
+FORCE_INLINE __m128 _mm_floor_ps(__m128);
+FORCE_INLINE __m128d _mm_round_pd(__m128d, int);
+FORCE_INLINE __m128 _mm_round_ps(__m128, int);
+// SSE4.2
+FORCE_INLINE uint32_t _mm_crc32_u8(uint32_t, uint8_t);
+
/* Backwards compatibility for compilers with lack of specific type support */
// Older gcc does not define vld1q_u8_x4 type
-#if defined(__GNUC__) && !defined(__clang__) && \
- ((__GNUC__ == 10 && (__GNUC_MINOR__ <= 1)) || \
- (__GNUC__ == 9 && (__GNUC_MINOR__ <= 3)) || \
- (__GNUC__ == 8 && (__GNUC_MINOR__ <= 4)) || __GNUC__ <= 7)
+#if defined(__GNUC__) && !defined(__clang__) && \
+ ((__GNUC__ <= 10 && defined(__arm__)) || \
+ (__GNUC__ == 10 && __GNUC_MINOR__ < 3 && defined(__aarch64__)) || \
+ (__GNUC__ <= 9 && defined(__aarch64__)))
FORCE_INLINE uint8x16x4_t _sse2neon_vld1q_u8_x4(const uint8_t *p)
{
uint8x16x4_t ret;
@@ -443,8 +491,6 @@ FORCE_INLINE uint8x16x4_t _sse2neon_vld1q_u8_x4(const uint8_t *p)
+------+------+------+------+------+------+-------------+
*/
-/* Set/get methods */
-
/* Constants for use with _mm_prefetch. */
enum _mm_hint {
_MM_HINT_NTA = 0, /* load data to L1 and L2 cache, mark it as NTA */
@@ -457,1098 +503,1568 @@ enum _mm_hint {
_MM_HINT_ET2 = 7 /* exclusive version of _MM_HINT_T2 */
};
-// Loads one cache line of data from address p to a location closer to the
-// processor. https://msdn.microsoft.com/en-us/library/84szxsww(v=vs.100).aspx
-FORCE_INLINE void _mm_prefetch(const void *p, int i)
+// The bit field mapping to the FPCR(floating-point control register)
+typedef struct {
+ uint16_t res0;
+ uint8_t res1 : 6;
+ uint8_t bit22 : 1;
+ uint8_t bit23 : 1;
+ uint8_t bit24 : 1;
+ uint8_t res2 : 7;
+#if defined(__aarch64__)
+ uint32_t res3;
+#endif
+} fpcr_bitfield;
+
+// Takes the upper 64 bits of a and places it in the low end of the result
+// Takes the lower 64 bits of b and places it into the high end of the result.
+FORCE_INLINE __m128 _mm_shuffle_ps_1032(__m128 a, __m128 b)
{
- (void) i;
- __builtin_prefetch(p);
+ float32x2_t a32 = vget_high_f32(vreinterpretq_f32_m128(a));
+ float32x2_t b10 = vget_low_f32(vreinterpretq_f32_m128(b));
+ return vreinterpretq_m128_f32(vcombine_f32(a32, b10));
}
-// Pause the processor. This is typically used in spin-wait loops and depending
-// on the x86 processor typical values are in the 40-100 cycle range. The
-// 'yield' instruction isn't a good fit beacuse it's effectively a nop on most
-// Arm cores. Experience with several databases has shown has shown an 'isb' is
-// a reasonable approximation.
-FORCE_INLINE void _mm_pause()
+// takes the lower two 32-bit values from a and swaps them and places in high
+// end of result takes the higher two 32 bit values from b and swaps them and
+// places in low end of result.
+FORCE_INLINE __m128 _mm_shuffle_ps_2301(__m128 a, __m128 b)
{
- __asm__ __volatile__("isb\n");
+ float32x2_t a01 = vrev64_f32(vget_low_f32(vreinterpretq_f32_m128(a)));
+ float32x2_t b23 = vrev64_f32(vget_high_f32(vreinterpretq_f32_m128(b)));
+ return vreinterpretq_m128_f32(vcombine_f32(a01, b23));
}
-// Copy the lower single-precision (32-bit) floating-point element of a to dst.
-//
-// dst[31:0] := a[31:0]
-//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtss_f32
-FORCE_INLINE float _mm_cvtss_f32(__m128 a)
+FORCE_INLINE __m128 _mm_shuffle_ps_0321(__m128 a, __m128 b)
{
- return vgetq_lane_f32(vreinterpretq_f32_m128(a), 0);
+ float32x2_t a21 = vget_high_f32(
+ vextq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(a), 3));
+ float32x2_t b03 = vget_low_f32(
+ vextq_f32(vreinterpretq_f32_m128(b), vreinterpretq_f32_m128(b), 3));
+ return vreinterpretq_m128_f32(vcombine_f32(a21, b03));
}
-// Convert the lower single-precision (32-bit) floating-point element in b to a
-// double-precision (64-bit) floating-point element, store the result in the
-// lower element of dst, and copy the upper element from a to the upper element
-// of dst.
+FORCE_INLINE __m128 _mm_shuffle_ps_2103(__m128 a, __m128 b)
+{
+ float32x2_t a03 = vget_low_f32(
+ vextq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(a), 3));
+ float32x2_t b21 = vget_high_f32(
+ vextq_f32(vreinterpretq_f32_m128(b), vreinterpretq_f32_m128(b), 3));
+ return vreinterpretq_m128_f32(vcombine_f32(a03, b21));
+}
+
+FORCE_INLINE __m128 _mm_shuffle_ps_1010(__m128 a, __m128 b)
+{
+ float32x2_t a10 = vget_low_f32(vreinterpretq_f32_m128(a));
+ float32x2_t b10 = vget_low_f32(vreinterpretq_f32_m128(b));
+ return vreinterpretq_m128_f32(vcombine_f32(a10, b10));
+}
+
+FORCE_INLINE __m128 _mm_shuffle_ps_1001(__m128 a, __m128 b)
+{
+ float32x2_t a01 = vrev64_f32(vget_low_f32(vreinterpretq_f32_m128(a)));
+ float32x2_t b10 = vget_low_f32(vreinterpretq_f32_m128(b));
+ return vreinterpretq_m128_f32(vcombine_f32(a01, b10));
+}
+
+FORCE_INLINE __m128 _mm_shuffle_ps_0101(__m128 a, __m128 b)
+{
+ float32x2_t a01 = vrev64_f32(vget_low_f32(vreinterpretq_f32_m128(a)));
+ float32x2_t b01 = vrev64_f32(vget_low_f32(vreinterpretq_f32_m128(b)));
+ return vreinterpretq_m128_f32(vcombine_f32(a01, b01));
+}
+
+// keeps the low 64 bits of b in the low and puts the high 64 bits of a in the
+// high
+FORCE_INLINE __m128 _mm_shuffle_ps_3210(__m128 a, __m128 b)
+{
+ float32x2_t a10 = vget_low_f32(vreinterpretq_f32_m128(a));
+ float32x2_t b32 = vget_high_f32(vreinterpretq_f32_m128(b));
+ return vreinterpretq_m128_f32(vcombine_f32(a10, b32));
+}
+
+FORCE_INLINE __m128 _mm_shuffle_ps_0011(__m128 a, __m128 b)
+{
+ float32x2_t a11 = vdup_lane_f32(vget_low_f32(vreinterpretq_f32_m128(a)), 1);
+ float32x2_t b00 = vdup_lane_f32(vget_low_f32(vreinterpretq_f32_m128(b)), 0);
+ return vreinterpretq_m128_f32(vcombine_f32(a11, b00));
+}
+
+FORCE_INLINE __m128 _mm_shuffle_ps_0022(__m128 a, __m128 b)
+{
+ float32x2_t a22 =
+ vdup_lane_f32(vget_high_f32(vreinterpretq_f32_m128(a)), 0);
+ float32x2_t b00 = vdup_lane_f32(vget_low_f32(vreinterpretq_f32_m128(b)), 0);
+ return vreinterpretq_m128_f32(vcombine_f32(a22, b00));
+}
+
+FORCE_INLINE __m128 _mm_shuffle_ps_2200(__m128 a, __m128 b)
+{
+ float32x2_t a00 = vdup_lane_f32(vget_low_f32(vreinterpretq_f32_m128(a)), 0);
+ float32x2_t b22 =
+ vdup_lane_f32(vget_high_f32(vreinterpretq_f32_m128(b)), 0);
+ return vreinterpretq_m128_f32(vcombine_f32(a00, b22));
+}
+
+FORCE_INLINE __m128 _mm_shuffle_ps_3202(__m128 a, __m128 b)
+{
+ float32_t a0 = vgetq_lane_f32(vreinterpretq_f32_m128(a), 0);
+ float32x2_t a22 =
+ vdup_lane_f32(vget_high_f32(vreinterpretq_f32_m128(a)), 0);
+ float32x2_t a02 = vset_lane_f32(a0, a22, 1); /* TODO: use vzip ?*/
+ float32x2_t b32 = vget_high_f32(vreinterpretq_f32_m128(b));
+ return vreinterpretq_m128_f32(vcombine_f32(a02, b32));
+}
+
+FORCE_INLINE __m128 _mm_shuffle_ps_1133(__m128 a, __m128 b)
+{
+ float32x2_t a33 =
+ vdup_lane_f32(vget_high_f32(vreinterpretq_f32_m128(a)), 1);
+ float32x2_t b11 = vdup_lane_f32(vget_low_f32(vreinterpretq_f32_m128(b)), 1);
+ return vreinterpretq_m128_f32(vcombine_f32(a33, b11));
+}
+
+FORCE_INLINE __m128 _mm_shuffle_ps_2010(__m128 a, __m128 b)
+{
+ float32x2_t a10 = vget_low_f32(vreinterpretq_f32_m128(a));
+ float32_t b2 = vgetq_lane_f32(vreinterpretq_f32_m128(b), 2);
+ float32x2_t b00 = vdup_lane_f32(vget_low_f32(vreinterpretq_f32_m128(b)), 0);
+ float32x2_t b20 = vset_lane_f32(b2, b00, 1);
+ return vreinterpretq_m128_f32(vcombine_f32(a10, b20));
+}
+
+FORCE_INLINE __m128 _mm_shuffle_ps_2001(__m128 a, __m128 b)
+{
+ float32x2_t a01 = vrev64_f32(vget_low_f32(vreinterpretq_f32_m128(a)));
+ float32_t b2 = vgetq_lane_f32(b, 2);
+ float32x2_t b00 = vdup_lane_f32(vget_low_f32(vreinterpretq_f32_m128(b)), 0);
+ float32x2_t b20 = vset_lane_f32(b2, b00, 1);
+ return vreinterpretq_m128_f32(vcombine_f32(a01, b20));
+}
+
+FORCE_INLINE __m128 _mm_shuffle_ps_2032(__m128 a, __m128 b)
+{
+ float32x2_t a32 = vget_high_f32(vreinterpretq_f32_m128(a));
+ float32_t b2 = vgetq_lane_f32(b, 2);
+ float32x2_t b00 = vdup_lane_f32(vget_low_f32(vreinterpretq_f32_m128(b)), 0);
+ float32x2_t b20 = vset_lane_f32(b2, b00, 1);
+ return vreinterpretq_m128_f32(vcombine_f32(a32, b20));
+}
+
+// Kahan summation for accurate summation of floating-point numbers.
+// http://blog.zachbjornson.com/2019/08/11/fast-float-summation.html
+FORCE_INLINE void _sse2neon_kadd_f32(float *sum, float *c, float y)
+{
+ y -= *c;
+ float t = *sum + y;
+ *c = (t - *sum) - y;
+ *sum = t;
+}
+
+#if defined(__ARM_FEATURE_CRYPTO)
+// Wraps vmull_p64
+FORCE_INLINE uint64x2_t _sse2neon_vmull_p64(uint64x1_t _a, uint64x1_t _b)
+{
+ poly64_t a = vget_lane_p64(vreinterpret_p64_u64(_a), 0);
+ poly64_t b = vget_lane_p64(vreinterpret_p64_u64(_b), 0);
+ return vreinterpretq_u64_p128(vmull_p64(a, b));
+}
+#else // ARMv7 polyfill
+// ARMv7/some A64 lacks vmull_p64, but it has vmull_p8.
//
-// dst[63:0] := Convert_FP32_To_FP64(b[31:0])
-// dst[127:64] := a[127:64]
+// vmull_p8 calculates 8 8-bit->16-bit polynomial multiplies, but we need a
+// 64-bit->128-bit polynomial multiply.
//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtss_sd
-FORCE_INLINE __m128d _mm_cvtss_sd(__m128d a, __m128 b)
+// It needs some work and is somewhat slow, but it is still faster than all
+// known scalar methods.
+//
+// Algorithm adapted to C from
+// https://www.workofard.com/2017/07/ghash-for-low-end-cores/, which is adapted
+// from "Fast Software Polynomial Multiplication on ARM Processors Using the
+// NEON Engine" by Danilo Camara, Conrado Gouvea, Julio Lopez and Ricardo Dahab
+// (https://hal.inria.fr/hal-01506572)
+static uint64x2_t _sse2neon_vmull_p64(uint64x1_t _a, uint64x1_t _b)
{
- double d = (double) vgetq_lane_f32(vreinterpretq_f32_m128(b), 0);
+ poly8x8_t a = vreinterpret_p8_u64(_a);
+ poly8x8_t b = vreinterpret_p8_u64(_b);
+
+ // Masks
+ uint8x16_t k48_32 = vcombine_u8(vcreate_u8(0x0000ffffffffffff),
+ vcreate_u8(0x00000000ffffffff));
+ uint8x16_t k16_00 = vcombine_u8(vcreate_u8(0x000000000000ffff),
+ vcreate_u8(0x0000000000000000));
+
+ // Do the multiplies, rotating with vext to get all combinations
+ uint8x16_t d = vreinterpretq_u8_p16(vmull_p8(a, b)); // D = A0 * B0
+ uint8x16_t e =
+ vreinterpretq_u8_p16(vmull_p8(a, vext_p8(b, b, 1))); // E = A0 * B1
+ uint8x16_t f =
+ vreinterpretq_u8_p16(vmull_p8(vext_p8(a, a, 1), b)); // F = A1 * B0
+ uint8x16_t g =
+ vreinterpretq_u8_p16(vmull_p8(a, vext_p8(b, b, 2))); // G = A0 * B2
+ uint8x16_t h =
+ vreinterpretq_u8_p16(vmull_p8(vext_p8(a, a, 2), b)); // H = A2 * B0
+ uint8x16_t i =
+ vreinterpretq_u8_p16(vmull_p8(a, vext_p8(b, b, 3))); // I = A0 * B3
+ uint8x16_t j =
+ vreinterpretq_u8_p16(vmull_p8(vext_p8(a, a, 3), b)); // J = A3 * B0
+ uint8x16_t k =
+ vreinterpretq_u8_p16(vmull_p8(a, vext_p8(b, b, 4))); // L = A0 * B4
+
+ // Add cross products
+ uint8x16_t l = veorq_u8(e, f); // L = E + F
+ uint8x16_t m = veorq_u8(g, h); // M = G + H
+ uint8x16_t n = veorq_u8(i, j); // N = I + J
+
+ // Interleave. Using vzip1 and vzip2 prevents Clang from emitting TBL
+ // instructions.
#if defined(__aarch64__)
- return vreinterpretq_m128d_f64(
- vsetq_lane_f64(d, vreinterpretq_f64_m128d(a), 0));
+ uint8x16_t lm_p0 = vreinterpretq_u8_u64(
+ vzip1q_u64(vreinterpretq_u64_u8(l), vreinterpretq_u64_u8(m)));
+ uint8x16_t lm_p1 = vreinterpretq_u8_u64(
+ vzip2q_u64(vreinterpretq_u64_u8(l), vreinterpretq_u64_u8(m)));
+ uint8x16_t nk_p0 = vreinterpretq_u8_u64(
+ vzip1q_u64(vreinterpretq_u64_u8(n), vreinterpretq_u64_u8(k)));
+ uint8x16_t nk_p1 = vreinterpretq_u8_u64(
+ vzip2q_u64(vreinterpretq_u64_u8(n), vreinterpretq_u64_u8(k)));
#else
- return vreinterpretq_m128d_s64(
- vsetq_lane_s64(*(int64_t *) &d, vreinterpretq_s64_m128d(a), 0));
+ uint8x16_t lm_p0 = vcombine_u8(vget_low_u8(l), vget_low_u8(m));
+ uint8x16_t lm_p1 = vcombine_u8(vget_high_u8(l), vget_high_u8(m));
+ uint8x16_t nk_p0 = vcombine_u8(vget_low_u8(n), vget_low_u8(k));
+ uint8x16_t nk_p1 = vcombine_u8(vget_high_u8(n), vget_high_u8(k));
#endif
-}
+ // t0 = (L) (P0 + P1) << 8
+ // t1 = (M) (P2 + P3) << 16
+ uint8x16_t t0t1_tmp = veorq_u8(lm_p0, lm_p1);
+ uint8x16_t t0t1_h = vandq_u8(lm_p1, k48_32);
+ uint8x16_t t0t1_l = veorq_u8(t0t1_tmp, t0t1_h);
-// Convert the lower single-precision (32-bit) floating-point element in a to a
-// 32-bit integer, and store the result in dst.
-//
-// dst[31:0] := Convert_FP32_To_Int32(a[31:0])
-//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtss_si32
-#define _mm_cvtss_si32(a) _mm_cvt_ss2si(a)
+ // t2 = (N) (P4 + P5) << 24
+ // t3 = (K) (P6 + P7) << 32
+ uint8x16_t t2t3_tmp = veorq_u8(nk_p0, nk_p1);
+ uint8x16_t t2t3_h = vandq_u8(nk_p1, k16_00);
+ uint8x16_t t2t3_l = veorq_u8(t2t3_tmp, t2t3_h);
-// Convert the lower single-precision (32-bit) floating-point element in a to a
-// 64-bit integer, and store the result in dst.
-//
-// dst[63:0] := Convert_FP32_To_Int64(a[31:0])
-//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtss_si64
-FORCE_INLINE int _mm_cvtss_si64(__m128 a)
-{
+ // De-interleave
#if defined(__aarch64__)
- return vgetq_lane_s64(
- vreinterpretq_s64_s32(vcvtnq_s32_f32(vreinterpretq_f32_m128(a))), 0);
+ uint8x16_t t0 = vreinterpretq_u8_u64(
+ vuzp1q_u64(vreinterpretq_u64_u8(t0t1_l), vreinterpretq_u64_u8(t0t1_h)));
+ uint8x16_t t1 = vreinterpretq_u8_u64(
+ vuzp2q_u64(vreinterpretq_u64_u8(t0t1_l), vreinterpretq_u64_u8(t0t1_h)));
+ uint8x16_t t2 = vreinterpretq_u8_u64(
+ vuzp1q_u64(vreinterpretq_u64_u8(t2t3_l), vreinterpretq_u64_u8(t2t3_h)));
+ uint8x16_t t3 = vreinterpretq_u8_u64(
+ vuzp2q_u64(vreinterpretq_u64_u8(t2t3_l), vreinterpretq_u64_u8(t2t3_h)));
#else
- float32_t data = vgetq_lane_f32(vreinterpretq_f32_m128(a), 0);
- float32_t diff = data - floor(data);
- if (diff > 0.5)
- return (int64_t) ceil(data);
- if (unlikely(diff == 0.5)) {
- int64_t f = (int64_t) floor(data);
- int64_t c = (int64_t) ceil(data);
- return c & 1 ? f : c;
- }
- return (int64_t) floor(data);
+ uint8x16_t t1 = vcombine_u8(vget_high_u8(t0t1_l), vget_high_u8(t0t1_h));
+ uint8x16_t t0 = vcombine_u8(vget_low_u8(t0t1_l), vget_low_u8(t0t1_h));
+ uint8x16_t t3 = vcombine_u8(vget_high_u8(t2t3_l), vget_high_u8(t2t3_h));
+ uint8x16_t t2 = vcombine_u8(vget_low_u8(t2t3_l), vget_low_u8(t2t3_h));
#endif
+ // Shift the cross products
+ uint8x16_t t0_shift = vextq_u8(t0, t0, 15); // t0 << 8
+ uint8x16_t t1_shift = vextq_u8(t1, t1, 14); // t1 << 16
+ uint8x16_t t2_shift = vextq_u8(t2, t2, 13); // t2 << 24
+ uint8x16_t t3_shift = vextq_u8(t3, t3, 12); // t3 << 32
+
+ // Accumulate the products
+ uint8x16_t cross1 = veorq_u8(t0_shift, t1_shift);
+ uint8x16_t cross2 = veorq_u8(t2_shift, t3_shift);
+ uint8x16_t mix = veorq_u8(d, cross1);
+ uint8x16_t r = veorq_u8(mix, cross2);
+ return vreinterpretq_u64_u8(r);
}
+#endif // ARMv7 polyfill
-// Convert packed single-precision (32-bit) floating-point elements in a to
-// packed 32-bit integers with truncation, and store the results in dst.
-//
-// FOR j := 0 to 1
-// i := 32*j
-// dst[i+31:i] := Convert_FP32_To_Int32_Truncate(a[i+31:i])
-// ENDFOR
-//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtt_ps2pi
-FORCE_INLINE __m64 _mm_cvtt_ps2pi(__m128 a)
+// C equivalent:
+// __m128i _mm_shuffle_epi32_default(__m128i a,
+// __constrange(0, 255) int imm) {
+// __m128i ret;
+// ret[0] = a[imm & 0x3]; ret[1] = a[(imm >> 2) & 0x3];
+// ret[2] = a[(imm >> 4) & 0x03]; ret[3] = a[(imm >> 6) & 0x03];
+// return ret;
+// }
+#define _mm_shuffle_epi32_default(a, imm) \
+ __extension__({ \
+ int32x4_t ret; \
+ ret = vmovq_n_s32( \
+ vgetq_lane_s32(vreinterpretq_s32_m128i(a), (imm) & (0x3))); \
+ ret = vsetq_lane_s32( \
+ vgetq_lane_s32(vreinterpretq_s32_m128i(a), ((imm) >> 2) & 0x3), \
+ ret, 1); \
+ ret = vsetq_lane_s32( \
+ vgetq_lane_s32(vreinterpretq_s32_m128i(a), ((imm) >> 4) & 0x3), \
+ ret, 2); \
+ ret = vsetq_lane_s32( \
+ vgetq_lane_s32(vreinterpretq_s32_m128i(a), ((imm) >> 6) & 0x3), \
+ ret, 3); \
+ vreinterpretq_m128i_s32(ret); \
+ })
+
+// Takes the upper 64 bits of a and places it in the low end of the result
+// Takes the lower 64 bits of a and places it into the high end of the result.
+FORCE_INLINE __m128i _mm_shuffle_epi_1032(__m128i a)
{
- return vreinterpret_m64_s32(
- vget_low_s32(vcvtq_s32_f32(vreinterpretq_f32_m128(a))));
+ int32x2_t a32 = vget_high_s32(vreinterpretq_s32_m128i(a));
+ int32x2_t a10 = vget_low_s32(vreinterpretq_s32_m128i(a));
+ return vreinterpretq_m128i_s32(vcombine_s32(a32, a10));
}
-// Convert the lower single-precision (32-bit) floating-point element in a to a
-// 32-bit integer with truncation, and store the result in dst.
-//
-// dst[31:0] := Convert_FP32_To_Int32_Truncate(a[31:0])
-//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtt_ss2si
-FORCE_INLINE int _mm_cvtt_ss2si(__m128 a)
+// takes the lower two 32-bit values from a and swaps them and places in low end
+// of result takes the higher two 32 bit values from a and swaps them and places
+// in high end of result.
+FORCE_INLINE __m128i _mm_shuffle_epi_2301(__m128i a)
{
- return vgetq_lane_s32(vcvtq_s32_f32(vreinterpretq_f32_m128(a)), 0);
+ int32x2_t a01 = vrev64_s32(vget_low_s32(vreinterpretq_s32_m128i(a)));
+ int32x2_t a23 = vrev64_s32(vget_high_s32(vreinterpretq_s32_m128i(a)));
+ return vreinterpretq_m128i_s32(vcombine_s32(a01, a23));
}
-// Convert packed single-precision (32-bit) floating-point elements in a to
-// packed 32-bit integers with truncation, and store the results in dst.
-//
-// FOR j := 0 to 1
-// i := 32*j
-// dst[i+31:i] := Convert_FP32_To_Int32_Truncate(a[i+31:i])
-// ENDFOR
-//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvttps_pi32
-#define _mm_cvttps_pi32(a) _mm_cvtt_ps2pi(a)
+// rotates the least significant 32 bits into the most significant 32 bits, and
+// shifts the rest down
+FORCE_INLINE __m128i _mm_shuffle_epi_0321(__m128i a)
+{
+ return vreinterpretq_m128i_s32(
+ vextq_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(a), 1));
+}
-// Convert the lower single-precision (32-bit) floating-point element in a to a
-// 32-bit integer with truncation, and store the result in dst.
-//
-// dst[31:0] := Convert_FP32_To_Int32_Truncate(a[31:0])
-//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvttss_si32
-#define _mm_cvttss_si32(a) _mm_cvtt_ss2si(a)
+// rotates the most significant 32 bits into the least significant 32 bits, and
+// shifts the rest up
+FORCE_INLINE __m128i _mm_shuffle_epi_2103(__m128i a)
+{
+ return vreinterpretq_m128i_s32(
+ vextq_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(a), 3));
+}
-// Convert the lower single-precision (32-bit) floating-point element in a to a
-// 64-bit integer with truncation, and store the result in dst.
-//
-// dst[63:0] := Convert_FP32_To_Int64_Truncate(a[31:0])
-//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvttss_si64
-FORCE_INLINE int64_t _mm_cvttss_si64(__m128 a)
+// gets the lower 64 bits of a, and places it in the upper 64 bits
+// gets the lower 64 bits of a and places it in the lower 64 bits
+FORCE_INLINE __m128i _mm_shuffle_epi_1010(__m128i a)
{
- return vgetq_lane_s64(
- vmovl_s32(vget_low_s32(vcvtq_s32_f32(vreinterpretq_f32_m128(a)))), 0);
+ int32x2_t a10 = vget_low_s32(vreinterpretq_s32_m128i(a));
+ return vreinterpretq_m128i_s32(vcombine_s32(a10, a10));
}
-// Sets the 128-bit value to zero
-// https://msdn.microsoft.com/en-us/library/vstudio/ys7dw0kh(v=vs.100).aspx
-FORCE_INLINE __m128i _mm_setzero_si128(void)
+// gets the lower 64 bits of a, swaps the 0 and 1 elements, and places it in the
+// lower 64 bits gets the lower 64 bits of a, and places it in the upper 64 bits
+FORCE_INLINE __m128i _mm_shuffle_epi_1001(__m128i a)
{
- return vreinterpretq_m128i_s32(vdupq_n_s32(0));
+ int32x2_t a01 = vrev64_s32(vget_low_s32(vreinterpretq_s32_m128i(a)));
+ int32x2_t a10 = vget_low_s32(vreinterpretq_s32_m128i(a));
+ return vreinterpretq_m128i_s32(vcombine_s32(a01, a10));
}
-// Clears the four single-precision, floating-point values.
-// https://msdn.microsoft.com/en-us/library/vstudio/tk1t2tbz(v=vs.100).aspx
-FORCE_INLINE __m128 _mm_setzero_ps(void)
+// gets the lower 64 bits of a, swaps the 0 and 1 elements and places it in the
+// upper 64 bits gets the lower 64 bits of a, swaps the 0 and 1 elements, and
+// places it in the lower 64 bits
+FORCE_INLINE __m128i _mm_shuffle_epi_0101(__m128i a)
{
- return vreinterpretq_m128_f32(vdupq_n_f32(0));
+ int32x2_t a01 = vrev64_s32(vget_low_s32(vreinterpretq_s32_m128i(a)));
+ return vreinterpretq_m128i_s32(vcombine_s32(a01, a01));
}
-// Return vector of type __m128d with all elements set to zero.
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_setzero_pd
-FORCE_INLINE __m128d _mm_setzero_pd(void)
+FORCE_INLINE __m128i _mm_shuffle_epi_2211(__m128i a)
{
+ int32x2_t a11 = vdup_lane_s32(vget_low_s32(vreinterpretq_s32_m128i(a)), 1);
+ int32x2_t a22 = vdup_lane_s32(vget_high_s32(vreinterpretq_s32_m128i(a)), 0);
+ return vreinterpretq_m128i_s32(vcombine_s32(a11, a22));
+}
+
+FORCE_INLINE __m128i _mm_shuffle_epi_0122(__m128i a)
+{
+ int32x2_t a22 = vdup_lane_s32(vget_high_s32(vreinterpretq_s32_m128i(a)), 0);
+ int32x2_t a01 = vrev64_s32(vget_low_s32(vreinterpretq_s32_m128i(a)));
+ return vreinterpretq_m128i_s32(vcombine_s32(a22, a01));
+}
+
+FORCE_INLINE __m128i _mm_shuffle_epi_3332(__m128i a)
+{
+ int32x2_t a32 = vget_high_s32(vreinterpretq_s32_m128i(a));
+ int32x2_t a33 = vdup_lane_s32(vget_high_s32(vreinterpretq_s32_m128i(a)), 1);
+ return vreinterpretq_m128i_s32(vcombine_s32(a32, a33));
+}
+
+// FORCE_INLINE __m128i _mm_shuffle_epi32_splat(__m128i a, __constrange(0,255)
+// int imm)
#if defined(__aarch64__)
- return vreinterpretq_m128d_f64(vdupq_n_f64(0));
+#define _mm_shuffle_epi32_splat(a, imm) \
+ __extension__({ \
+ vreinterpretq_m128i_s32( \
+ vdupq_laneq_s32(vreinterpretq_s32_m128i(a), (imm))); \
+ })
#else
- return vreinterpretq_m128d_f32(vdupq_n_f32(0));
+#define _mm_shuffle_epi32_splat(a, imm) \
+ __extension__({ \
+ vreinterpretq_m128i_s32( \
+ vdupq_n_s32(vgetq_lane_s32(vreinterpretq_s32_m128i(a), (imm)))); \
+ })
#endif
-}
-// Sets the four single-precision, floating-point values to w.
+// NEON does not support a general purpose permute intrinsic
+// Selects four specific single-precision, floating-point values from a and b,
+// based on the mask i.
//
-// r0 := r1 := r2 := r3 := w
+// C equivalent:
+// __m128 _mm_shuffle_ps_default(__m128 a, __m128 b,
+// __constrange(0, 255) int imm) {
+// __m128 ret;
+// ret[0] = a[imm & 0x3]; ret[1] = a[(imm >> 2) & 0x3];
+// ret[2] = b[(imm >> 4) & 0x03]; ret[3] = b[(imm >> 6) & 0x03];
+// return ret;
+// }
//
-// https://msdn.microsoft.com/en-us/library/vstudio/2x1se8ha(v=vs.100).aspx
-FORCE_INLINE __m128 _mm_set1_ps(float _w)
+// https://msdn.microsoft.com/en-us/library/vstudio/5f0858x0(v=vs.100).aspx
+#define _mm_shuffle_ps_default(a, b, imm) \
+ __extension__({ \
+ float32x4_t ret; \
+ ret = vmovq_n_f32( \
+ vgetq_lane_f32(vreinterpretq_f32_m128(a), (imm) & (0x3))); \
+ ret = vsetq_lane_f32( \
+ vgetq_lane_f32(vreinterpretq_f32_m128(a), ((imm) >> 2) & 0x3), \
+ ret, 1); \
+ ret = vsetq_lane_f32( \
+ vgetq_lane_f32(vreinterpretq_f32_m128(b), ((imm) >> 4) & 0x3), \
+ ret, 2); \
+ ret = vsetq_lane_f32( \
+ vgetq_lane_f32(vreinterpretq_f32_m128(b), ((imm) >> 6) & 0x3), \
+ ret, 3); \
+ vreinterpretq_m128_f32(ret); \
+ })
+
+// Shuffles the lower 4 signed or unsigned 16-bit integers in a as specified
+// by imm.
+// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/y41dkk37(v=vs.100)
+// FORCE_INLINE __m128i _mm_shufflelo_epi16_function(__m128i a,
+// __constrange(0,255) int
+// imm)
+#define _mm_shufflelo_epi16_function(a, imm) \
+ __extension__({ \
+ int16x8_t ret = vreinterpretq_s16_m128i(a); \
+ int16x4_t lowBits = vget_low_s16(ret); \
+ ret = vsetq_lane_s16(vget_lane_s16(lowBits, (imm) & (0x3)), ret, 0); \
+ ret = vsetq_lane_s16(vget_lane_s16(lowBits, ((imm) >> 2) & 0x3), ret, \
+ 1); \
+ ret = vsetq_lane_s16(vget_lane_s16(lowBits, ((imm) >> 4) & 0x3), ret, \
+ 2); \
+ ret = vsetq_lane_s16(vget_lane_s16(lowBits, ((imm) >> 6) & 0x3), ret, \
+ 3); \
+ vreinterpretq_m128i_s16(ret); \
+ })
+
+// Shuffles the upper 4 signed or unsigned 16-bit integers in a as specified
+// by imm.
+// https://msdn.microsoft.com/en-us/library/13ywktbs(v=vs.100).aspx
+// FORCE_INLINE __m128i _mm_shufflehi_epi16_function(__m128i a,
+// __constrange(0,255) int
+// imm)
+#define _mm_shufflehi_epi16_function(a, imm) \
+ __extension__({ \
+ int16x8_t ret = vreinterpretq_s16_m128i(a); \
+ int16x4_t highBits = vget_high_s16(ret); \
+ ret = vsetq_lane_s16(vget_lane_s16(highBits, (imm) & (0x3)), ret, 4); \
+ ret = vsetq_lane_s16(vget_lane_s16(highBits, ((imm) >> 2) & 0x3), ret, \
+ 5); \
+ ret = vsetq_lane_s16(vget_lane_s16(highBits, ((imm) >> 4) & 0x3), ret, \
+ 6); \
+ ret = vsetq_lane_s16(vget_lane_s16(highBits, ((imm) >> 6) & 0x3), ret, \
+ 7); \
+ vreinterpretq_m128i_s16(ret); \
+ })
+
+/* SSE */
+
+// Adds the four single-precision, floating-point values of a and b.
+//
+// r0 := a0 + b0
+// r1 := a1 + b1
+// r2 := a2 + b2
+// r3 := a3 + b3
+//
+// https://msdn.microsoft.com/en-us/library/vstudio/c9848chc(v=vs.100).aspx
+FORCE_INLINE __m128 _mm_add_ps(__m128 a, __m128 b)
{
- return vreinterpretq_m128_f32(vdupq_n_f32(_w));
+ return vreinterpretq_m128_f32(
+ vaddq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b)));
}
-// Sets the four single-precision, floating-point values to w.
-// https://msdn.microsoft.com/en-us/library/vstudio/2x1se8ha(v=vs.100).aspx
-FORCE_INLINE __m128 _mm_set_ps1(float _w)
+// adds the scalar single-precision floating point values of a and b.
+// https://msdn.microsoft.com/en-us/library/be94x2y6(v=vs.100).aspx
+FORCE_INLINE __m128 _mm_add_ss(__m128 a, __m128 b)
{
- return vreinterpretq_m128_f32(vdupq_n_f32(_w));
+ float32_t b0 = vgetq_lane_f32(vreinterpretq_f32_m128(b), 0);
+ float32x4_t value = vsetq_lane_f32(b0, vdupq_n_f32(0), 0);
+ // the upper values in the result must be the remnants of <a>.
+ return vreinterpretq_m128_f32(vaddq_f32(a, value));
}
-// Sets the four single-precision, floating-point values to the four inputs.
-// https://msdn.microsoft.com/en-us/library/vstudio/afh0zf75(v=vs.100).aspx
-FORCE_INLINE __m128 _mm_set_ps(float w, float z, float y, float x)
+// Computes the bitwise AND of the four single-precision, floating-point values
+// of a and b.
+//
+// r0 := a0 & b0
+// r1 := a1 & b1
+// r2 := a2 & b2
+// r3 := a3 & b3
+//
+// https://msdn.microsoft.com/en-us/library/vstudio/73ck1xc5(v=vs.100).aspx
+FORCE_INLINE __m128 _mm_and_ps(__m128 a, __m128 b)
{
- float ALIGN_STRUCT(16) data[4] = {x, y, z, w};
- return vreinterpretq_m128_f32(vld1q_f32(data));
+ return vreinterpretq_m128_s32(
+ vandq_s32(vreinterpretq_s32_m128(a), vreinterpretq_s32_m128(b)));
}
-// Copy single-precision (32-bit) floating-point element a to the lower element
-// of dst, and zero the upper 3 elements.
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_set_ss
-FORCE_INLINE __m128 _mm_set_ss(float a)
+// Computes the bitwise AND-NOT of the four single-precision, floating-point
+// values of a and b.
+//
+// r0 := ~a0 & b0
+// r1 := ~a1 & b1
+// r2 := ~a2 & b2
+// r3 := ~a3 & b3
+//
+// https://msdn.microsoft.com/en-us/library/vstudio/68h7wd02(v=vs.100).aspx
+FORCE_INLINE __m128 _mm_andnot_ps(__m128 a, __m128 b)
{
- float ALIGN_STRUCT(16) data[4] = {a, 0, 0, 0};
- return vreinterpretq_m128_f32(vld1q_f32(data));
+ return vreinterpretq_m128_s32(
+ vbicq_s32(vreinterpretq_s32_m128(b),
+ vreinterpretq_s32_m128(a))); // *NOTE* argument swap
}
-// Sets the four single-precision, floating-point values to the four inputs in
-// reverse order.
-// https://msdn.microsoft.com/en-us/library/vstudio/d2172ct3(v=vs.100).aspx
-FORCE_INLINE __m128 _mm_setr_ps(float w, float z, float y, float x)
+// Average packed unsigned 16-bit integers in a and b, and store the results in
+// dst.
+//
+// FOR j := 0 to 3
+// i := j*16
+// dst[i+15:i] := (a[i+15:i] + b[i+15:i] + 1) >> 1
+// ENDFOR
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_avg_pu16
+FORCE_INLINE __m64 _mm_avg_pu16(__m64 a, __m64 b)
{
- float ALIGN_STRUCT(16) data[4] = {w, z, y, x};
- return vreinterpretq_m128_f32(vld1q_f32(data));
+ return vreinterpret_m64_u16(
+ vrhadd_u16(vreinterpret_u16_m64(a), vreinterpret_u16_m64(b)));
}
-// Sets the 8 signed 16-bit integer values in reverse order.
+// Average packed unsigned 8-bit integers in a and b, and store the results in
+// dst.
//
-// Return Value
-// r0 := w0
-// r1 := w1
-// ...
-// r7 := w7
-FORCE_INLINE __m128i _mm_setr_epi16(short w0,
- short w1,
- short w2,
- short w3,
- short w4,
- short w5,
- short w6,
- short w7)
+// FOR j := 0 to 7
+// i := j*8
+// dst[i+7:i] := (a[i+7:i] + b[i+7:i] + 1) >> 1
+// ENDFOR
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_avg_pu8
+FORCE_INLINE __m64 _mm_avg_pu8(__m64 a, __m64 b)
{
- int16_t ALIGN_STRUCT(16) data[8] = {w0, w1, w2, w3, w4, w5, w6, w7};
- return vreinterpretq_m128i_s16(vld1q_s16((int16_t *) data));
+ return vreinterpret_m64_u8(
+ vrhadd_u8(vreinterpret_u8_m64(a), vreinterpret_u8_m64(b)));
}
-// Sets the 4 signed 32-bit integer values in reverse order
-// https://technet.microsoft.com/en-us/library/security/27yb3ee5(v=vs.90).aspx
-FORCE_INLINE __m128i _mm_setr_epi32(int i3, int i2, int i1, int i0)
+// Compares for equality.
+// https://msdn.microsoft.com/en-us/library/vstudio/36aectz5(v=vs.100).aspx
+FORCE_INLINE __m128 _mm_cmpeq_ps(__m128 a, __m128 b)
{
- int32_t ALIGN_STRUCT(16) data[4] = {i3, i2, i1, i0};
- return vreinterpretq_m128i_s32(vld1q_s32(data));
+ return vreinterpretq_m128_u32(
+ vceqq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b)));
}
-// Set packed 64-bit integers in dst with the supplied values in reverse order.
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_setr_epi64
-FORCE_INLINE __m128i _mm_setr_epi64(__m64 e1, __m64 e0)
+// Compares for equality.
+// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/k423z28e(v=vs.100)
+FORCE_INLINE __m128 _mm_cmpeq_ss(__m128 a, __m128 b)
{
- return vreinterpretq_m128i_s64(vcombine_s64(e1, e0));
+ return _mm_move_ss(a, _mm_cmpeq_ps(a, b));
}
-// Sets the 16 signed 8-bit integer values to b.
+// Compares for greater than or equal.
+// https://msdn.microsoft.com/en-us/library/vstudio/fs813y2t(v=vs.100).aspx
+FORCE_INLINE __m128 _mm_cmpge_ps(__m128 a, __m128 b)
+{
+ return vreinterpretq_m128_u32(
+ vcgeq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b)));
+}
+
+// Compares for greater than or equal.
+// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/kesh3ddc(v=vs.100)
+FORCE_INLINE __m128 _mm_cmpge_ss(__m128 a, __m128 b)
+{
+ return _mm_move_ss(a, _mm_cmpge_ps(a, b));
+}
+
+// Compares for greater than.
//
-// r0 := b
-// r1 := b
-// ...
-// r15 := b
+// r0 := (a0 > b0) ? 0xffffffff : 0x0
+// r1 := (a1 > b1) ? 0xffffffff : 0x0
+// r2 := (a2 > b2) ? 0xffffffff : 0x0
+// r3 := (a3 > b3) ? 0xffffffff : 0x0
//
-// https://msdn.microsoft.com/en-us/library/6e14xhyf(v=vs.100).aspx
-FORCE_INLINE __m128i _mm_set1_epi8(signed char w)
+// https://msdn.microsoft.com/en-us/library/vstudio/11dy102s(v=vs.100).aspx
+FORCE_INLINE __m128 _mm_cmpgt_ps(__m128 a, __m128 b)
{
- return vreinterpretq_m128i_s8(vdupq_n_s8(w));
+ return vreinterpretq_m128_u32(
+ vcgtq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b)));
}
-// Broadcast double-precision (64-bit) floating-point value a to all elements of
-// dst.
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_set1_pd
-FORCE_INLINE __m128d _mm_set1_pd(double d)
+// Compares for greater than.
+// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/1xyyyy9e(v=vs.100)
+FORCE_INLINE __m128 _mm_cmpgt_ss(__m128 a, __m128 b)
{
-#if defined(__aarch64__)
- return vreinterpretq_m128d_f64(vdupq_n_f64(d));
-#else
- return vreinterpretq_m128d_s64(vdupq_n_s64(*(int64_t *) &d));
-#endif
+ return _mm_move_ss(a, _mm_cmpgt_ps(a, b));
}
-// Sets the 8 signed 16-bit integer values to w.
+// Compares for less than or equal.
//
-// r0 := w
-// r1 := w
-// ...
-// r7 := w
+// r0 := (a0 <= b0) ? 0xffffffff : 0x0
+// r1 := (a1 <= b1) ? 0xffffffff : 0x0
+// r2 := (a2 <= b2) ? 0xffffffff : 0x0
+// r3 := (a3 <= b3) ? 0xffffffff : 0x0
//
-// https://msdn.microsoft.com/en-us/library/k0ya3x0e(v=vs.90).aspx
-FORCE_INLINE __m128i _mm_set1_epi16(short w)
+// https://msdn.microsoft.com/en-us/library/vstudio/1s75w83z(v=vs.100).aspx
+FORCE_INLINE __m128 _mm_cmple_ps(__m128 a, __m128 b)
{
- return vreinterpretq_m128i_s16(vdupq_n_s16(w));
+ return vreinterpretq_m128_u32(
+ vcleq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b)));
}
-// Sets the 16 signed 8-bit integer values.
-// https://msdn.microsoft.com/en-us/library/x0cx8zd3(v=vs.90).aspx
-FORCE_INLINE __m128i _mm_set_epi8(signed char b15,
- signed char b14,
- signed char b13,
- signed char b12,
- signed char b11,
- signed char b10,
- signed char b9,
- signed char b8,
- signed char b7,
- signed char b6,
- signed char b5,
- signed char b4,
- signed char b3,
- signed char b2,
- signed char b1,
- signed char b0)
+// Compares for less than or equal.
+// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/a7x0hbhw(v=vs.100)
+FORCE_INLINE __m128 _mm_cmple_ss(__m128 a, __m128 b)
{
- int8_t ALIGN_STRUCT(16)
- data[16] = {(int8_t) b0, (int8_t) b1, (int8_t) b2, (int8_t) b3,
- (int8_t) b4, (int8_t) b5, (int8_t) b6, (int8_t) b7,
- (int8_t) b8, (int8_t) b9, (int8_t) b10, (int8_t) b11,
- (int8_t) b12, (int8_t) b13, (int8_t) b14, (int8_t) b15};
- return (__m128i) vld1q_s8(data);
+ return _mm_move_ss(a, _mm_cmple_ps(a, b));
}
-// Sets the 8 signed 16-bit integer values.
-// https://msdn.microsoft.com/en-au/library/3e0fek84(v=vs.90).aspx
-FORCE_INLINE __m128i _mm_set_epi16(short i7,
- short i6,
- short i5,
- short i4,
- short i3,
- short i2,
- short i1,
- short i0)
+// Compares for less than
+// https://msdn.microsoft.com/en-us/library/vstudio/f330yhc8(v=vs.100).aspx
+FORCE_INLINE __m128 _mm_cmplt_ps(__m128 a, __m128 b)
{
- int16_t ALIGN_STRUCT(16) data[8] = {i0, i1, i2, i3, i4, i5, i6, i7};
- return vreinterpretq_m128i_s16(vld1q_s16(data));
+ return vreinterpretq_m128_u32(
+ vcltq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b)));
}
-// Sets the 16 signed 8-bit integer values in reverse order.
-// https://msdn.microsoft.com/en-us/library/2khb9c7k(v=vs.90).aspx
-FORCE_INLINE __m128i _mm_setr_epi8(signed char b0,
- signed char b1,
- signed char b2,
- signed char b3,
- signed char b4,
- signed char b5,
- signed char b6,
- signed char b7,
- signed char b8,
- signed char b9,
- signed char b10,
- signed char b11,
- signed char b12,
- signed char b13,
- signed char b14,
- signed char b15)
+// Compares for less than
+// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/fy94wye7(v=vs.100)
+FORCE_INLINE __m128 _mm_cmplt_ss(__m128 a, __m128 b)
{
- int8_t ALIGN_STRUCT(16)
- data[16] = {(int8_t) b0, (int8_t) b1, (int8_t) b2, (int8_t) b3,
- (int8_t) b4, (int8_t) b5, (int8_t) b6, (int8_t) b7,
- (int8_t) b8, (int8_t) b9, (int8_t) b10, (int8_t) b11,
- (int8_t) b12, (int8_t) b13, (int8_t) b14, (int8_t) b15};
- return (__m128i) vld1q_s8(data);
+ return _mm_move_ss(a, _mm_cmplt_ps(a, b));
}
-// Sets the 4 signed 32-bit integer values to i.
-//
-// r0 := i
-// r1 := i
-// r2 := i
-// r3 := I
-//
-// https://msdn.microsoft.com/en-us/library/vstudio/h4xscxat(v=vs.100).aspx
-FORCE_INLINE __m128i _mm_set1_epi32(int _i)
+// Compares for inequality.
+// https://msdn.microsoft.com/en-us/library/sf44thbx(v=vs.100).aspx
+FORCE_INLINE __m128 _mm_cmpneq_ps(__m128 a, __m128 b)
{
- return vreinterpretq_m128i_s32(vdupq_n_s32(_i));
+ return vreinterpretq_m128_u32(vmvnq_u32(
+ vceqq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b))));
}
-// Sets the 2 signed 64-bit integer values to i.
-// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/whtfzhzk(v=vs.100)
-FORCE_INLINE __m128i _mm_set1_epi64(__m64 _i)
+// Compares for inequality.
+// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/ekya8fh4(v=vs.100)
+FORCE_INLINE __m128 _mm_cmpneq_ss(__m128 a, __m128 b)
{
- return vreinterpretq_m128i_s64(vdupq_n_s64((int64_t) _i));
+ return _mm_move_ss(a, _mm_cmpneq_ps(a, b));
}
-// Sets the 2 signed 64-bit integer values to i.
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_set1_epi64x
-FORCE_INLINE __m128i _mm_set1_epi64x(int64_t _i)
+// Compares for not greater than or equal.
+// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/wsexys62(v=vs.100)
+FORCE_INLINE __m128 _mm_cmpnge_ps(__m128 a, __m128 b)
{
- return vreinterpretq_m128i_s64(vdupq_n_s64(_i));
+ return vreinterpretq_m128_u32(vmvnq_u32(
+ vcgeq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b))));
}
-// Sets the 4 signed 32-bit integer values.
-// https://msdn.microsoft.com/en-us/library/vstudio/019beekt(v=vs.100).aspx
-FORCE_INLINE __m128i _mm_set_epi32(int i3, int i2, int i1, int i0)
+// Compares for not greater than or equal.
+// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/fk2y80s8(v=vs.100)
+FORCE_INLINE __m128 _mm_cmpnge_ss(__m128 a, __m128 b)
{
- int32_t ALIGN_STRUCT(16) data[4] = {i0, i1, i2, i3};
- return vreinterpretq_m128i_s32(vld1q_s32(data));
+ return _mm_move_ss(a, _mm_cmpnge_ps(a, b));
}
-// Returns the __m128i structure with its two 64-bit integer values
-// initialized to the values of the two 64-bit integers passed in.
-// https://msdn.microsoft.com/en-us/library/dk2sdw0h(v=vs.120).aspx
-FORCE_INLINE __m128i _mm_set_epi64x(int64_t i1, int64_t i2)
+// Compares for not greater than.
+// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/d0xh7w0s(v=vs.100)
+FORCE_INLINE __m128 _mm_cmpngt_ps(__m128 a, __m128 b)
{
- return vreinterpretq_m128i_s64(
- vcombine_s64(vcreate_s64(i2), vcreate_s64(i1)));
+ return vreinterpretq_m128_u32(vmvnq_u32(
+ vcgtq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b))));
}
-// Returns the __m128i structure with its two 64-bit integer values
-// initialized to the values of the two 64-bit integers passed in.
-// https://msdn.microsoft.com/en-us/library/dk2sdw0h(v=vs.120).aspx
-FORCE_INLINE __m128i _mm_set_epi64(__m64 i1, __m64 i2)
+// Compares for not greater than.
+// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/z7x9ydwh(v=vs.100)
+FORCE_INLINE __m128 _mm_cmpngt_ss(__m128 a, __m128 b)
{
- return _mm_set_epi64x((int64_t) i1, (int64_t) i2);
+ return _mm_move_ss(a, _mm_cmpngt_ps(a, b));
}
-// Set packed double-precision (64-bit) floating-point elements in dst with the
-// supplied values.
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_set_pd
-FORCE_INLINE __m128d _mm_set_pd(double e1, double e0)
+// Compares for not less than or equal.
+// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/6a330kxw(v=vs.100)
+FORCE_INLINE __m128 _mm_cmpnle_ps(__m128 a, __m128 b)
{
- double ALIGN_STRUCT(16) data[2] = {e0, e1};
-#if defined(__aarch64__)
- return vreinterpretq_m128d_f64(vld1q_f64((float64_t *) data));
-#else
- return vreinterpretq_m128d_f32(vld1q_f32((float32_t *) data));
-#endif
+ return vreinterpretq_m128_u32(vmvnq_u32(
+ vcleq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b))));
}
-// Set packed double-precision (64-bit) floating-point elements in dst with the
-// supplied values in reverse order.
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_setr_pd
-FORCE_INLINE __m128d _mm_setr_pd(double e1, double e0)
+// Compares for not less than or equal.
+// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/z7x9ydwh(v=vs.100)
+FORCE_INLINE __m128 _mm_cmpnle_ss(__m128 a, __m128 b)
{
- return _mm_set_pd(e0, e1);
+ return _mm_move_ss(a, _mm_cmpnle_ps(a, b));
}
-// Copy double-precision (64-bit) floating-point element a to the lower element
-// of dst, and zero the upper element.
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_set_sd
-FORCE_INLINE __m128d _mm_set_sd(double a)
+// Compares for not less than.
+// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/4686bbdw(v=vs.100)
+FORCE_INLINE __m128 _mm_cmpnlt_ps(__m128 a, __m128 b)
{
- return _mm_set_pd(0, a);
+ return vreinterpretq_m128_u32(vmvnq_u32(
+ vcltq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b))));
}
-// Broadcast double-precision (64-bit) floating-point value a to all elements of
-// dst.
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_set_pd1
-#define _mm_set_pd1 _mm_set1_pd
+// Compares for not less than.
+// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/56b9z2wf(v=vs.100)
+FORCE_INLINE __m128 _mm_cmpnlt_ss(__m128 a, __m128 b)
+{
+ return _mm_move_ss(a, _mm_cmpnlt_ps(a, b));
+}
-// Stores four single-precision, floating-point values.
-// https://msdn.microsoft.com/en-us/library/vstudio/s3h4ay6y(v=vs.100).aspx
-FORCE_INLINE void _mm_store_ps(float *p, __m128 a)
+// Compares the four 32-bit floats in a and b to check if any values are NaN.
+// Ordered compare between each value returns true for "orderable" and false for
+// "not orderable" (NaN).
+// https://msdn.microsoft.com/en-us/library/vstudio/0h9w00fx(v=vs.100).aspx see
+// also:
+// http://stackoverflow.com/questions/8627331/what-does-ordered-unordered-comparison-mean
+// http://stackoverflow.com/questions/29349621/neon-isnanval-intrinsics
+FORCE_INLINE __m128 _mm_cmpord_ps(__m128 a, __m128 b)
{
- vst1q_f32(p, vreinterpretq_f32_m128(a));
+ // Note: NEON does not have ordered compare builtin
+ // Need to compare a eq a and b eq b to check for NaN
+ // Do AND of results to get final
+ uint32x4_t ceqaa =
+ vceqq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(a));
+ uint32x4_t ceqbb =
+ vceqq_f32(vreinterpretq_f32_m128(b), vreinterpretq_f32_m128(b));
+ return vreinterpretq_m128_u32(vandq_u32(ceqaa, ceqbb));
}
-// Store the lower single-precision (32-bit) floating-point element from a into
-// 4 contiguous elements in memory. mem_addr must be aligned on a 16-byte
-// boundary or a general-protection exception may be generated.
-//
-// MEM[mem_addr+31:mem_addr] := a[31:0]
-// MEM[mem_addr+63:mem_addr+32] := a[31:0]
-// MEM[mem_addr+95:mem_addr+64] := a[31:0]
-// MEM[mem_addr+127:mem_addr+96] := a[31:0]
-//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_store_ps1
-FORCE_INLINE void _mm_store_ps1(float *p, __m128 a)
+// Compares for ordered.
+// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/343t62da(v=vs.100)
+FORCE_INLINE __m128 _mm_cmpord_ss(__m128 a, __m128 b)
{
- float32_t a0 = vgetq_lane_f32(vreinterpretq_f32_m128(a), 0);
- vst1q_f32(p, vdupq_n_f32(a0));
+ return _mm_move_ss(a, _mm_cmpord_ps(a, b));
}
-// Store the lower single-precision (32-bit) floating-point element from a into
-// 4 contiguous elements in memory. mem_addr must be aligned on a 16-byte
-// boundary or a general-protection exception may be generated.
-//
-// MEM[mem_addr+31:mem_addr] := a[31:0]
-// MEM[mem_addr+63:mem_addr+32] := a[31:0]
-// MEM[mem_addr+95:mem_addr+64] := a[31:0]
-// MEM[mem_addr+127:mem_addr+96] := a[31:0]
-//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_store1_ps
-#define _mm_store1_ps _mm_store_ps1
+// Compares for unordered.
+// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/khy6fk1t(v=vs.100)
+FORCE_INLINE __m128 _mm_cmpunord_ps(__m128 a, __m128 b)
+{
+ uint32x4_t f32a =
+ vceqq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(a));
+ uint32x4_t f32b =
+ vceqq_f32(vreinterpretq_f32_m128(b), vreinterpretq_f32_m128(b));
+ return vreinterpretq_m128_u32(vmvnq_u32(vandq_u32(f32a, f32b)));
+}
-// Store 4 single-precision (32-bit) floating-point elements from a into memory
-// in reverse order. mem_addr must be aligned on a 16-byte boundary or a
-// general-protection exception may be generated.
-//
-// MEM[mem_addr+31:mem_addr] := a[127:96]
-// MEM[mem_addr+63:mem_addr+32] := a[95:64]
-// MEM[mem_addr+95:mem_addr+64] := a[63:32]
-// MEM[mem_addr+127:mem_addr+96] := a[31:0]
-//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_storer_ps
-FORCE_INLINE void _mm_storer_ps(float *p, __m128 a)
+// Compares for unordered.
+// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/2as2387b(v=vs.100)
+FORCE_INLINE __m128 _mm_cmpunord_ss(__m128 a, __m128 b)
{
- float32x4_t tmp = vrev64q_f32(vreinterpretq_f32_m128(a));
- float32x4_t rev = vextq_f32(tmp, tmp, 2);
- vst1q_f32(p, rev);
+ return _mm_move_ss(a, _mm_cmpunord_ps(a, b));
}
-// Stores four single-precision, floating-point values.
-// https://msdn.microsoft.com/en-us/library/44e30x22(v=vs.100).aspx
-FORCE_INLINE void _mm_storeu_ps(float *p, __m128 a)
+// Compares the lower single-precision floating point scalar values of a and b
+// using an equality operation. :
+// https://msdn.microsoft.com/en-us/library/93yx2h2b(v=vs.100).aspx
+FORCE_INLINE int _mm_comieq_ss(__m128 a, __m128 b)
{
- vst1q_f32(p, vreinterpretq_f32_m128(a));
+ uint32x4_t a_eq_b =
+ vceqq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b));
+ return vgetq_lane_u32(a_eq_b, 0) & 0x1;
}
-// Stores four 32-bit integer values as (as a __m128i value) at the address p.
-// https://msdn.microsoft.com/en-us/library/vstudio/edk11s13(v=vs.100).aspx
-FORCE_INLINE void _mm_store_si128(__m128i *p, __m128i a)
+// Compares the lower single-precision floating point scalar values of a and b
+// using a greater than or equal operation. :
+// https://msdn.microsoft.com/en-us/library/8t80des6(v=vs.100).aspx
+FORCE_INLINE int _mm_comige_ss(__m128 a, __m128 b)
{
- vst1q_s32((int32_t *) p, vreinterpretq_s32_m128i(a));
+ uint32x4_t a_ge_b =
+ vcgeq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b));
+ return vgetq_lane_u32(a_ge_b, 0) & 0x1;
}
-// Stores four 32-bit integer values as (as a __m128i value) at the address p.
-// https://msdn.microsoft.com/en-us/library/vstudio/edk11s13(v=vs.100).aspx
-FORCE_INLINE void _mm_storeu_si128(__m128i *p, __m128i a)
+// Compares the lower single-precision floating point scalar values of a and b
+// using a greater than operation. :
+// https://msdn.microsoft.com/en-us/library/b0738e0t(v=vs.100).aspx
+FORCE_INLINE int _mm_comigt_ss(__m128 a, __m128 b)
{
- vst1q_s32((int32_t *) p, vreinterpretq_s32_m128i(a));
+ uint32x4_t a_gt_b =
+ vcgtq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b));
+ return vgetq_lane_u32(a_gt_b, 0) & 0x1;
}
-// Stores the lower single - precision, floating - point value.
-// https://msdn.microsoft.com/en-us/library/tzz10fbx(v=vs.100).aspx
-FORCE_INLINE void _mm_store_ss(float *p, __m128 a)
+// Compares the lower single-precision floating point scalar values of a and b
+// using a less than or equal operation. :
+// https://msdn.microsoft.com/en-us/library/1w4t7c57(v=vs.90).aspx
+FORCE_INLINE int _mm_comile_ss(__m128 a, __m128 b)
{
- vst1q_lane_f32(p, vreinterpretq_f32_m128(a), 0);
+ uint32x4_t a_le_b =
+ vcleq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b));
+ return vgetq_lane_u32(a_le_b, 0) & 0x1;
}
-// Store 128-bits (composed of 2 packed double-precision (64-bit) floating-point
-// elements) from a into memory. mem_addr must be aligned on a 16-byte boundary
-// or a general-protection exception may be generated.
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_store_pd
-FORCE_INLINE void _mm_store_pd(double *mem_addr, __m128d a)
+// Compares the lower single-precision floating point scalar values of a and b
+// using a less than operation. :
+// https://msdn.microsoft.com/en-us/library/2kwe606b(v=vs.90).aspx Important
+// note!! The documentation on MSDN is incorrect! If either of the values is a
+// NAN the docs say you will get a one, but in fact, it will return a zero!!
+FORCE_INLINE int _mm_comilt_ss(__m128 a, __m128 b)
{
-#if defined(__aarch64__)
- vst1q_f64((float64_t *) mem_addr, vreinterpretq_f64_m128d(a));
-#else
- vst1q_f32((float32_t *) mem_addr, vreinterpretq_f32_m128d(a));
-#endif
+ uint32x4_t a_lt_b =
+ vcltq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b));
+ return vgetq_lane_u32(a_lt_b, 0) & 0x1;
}
-// Store the upper double-precision (64-bit) floating-point element from a into
-// memory.
+// Compares the lower single-precision floating point scalar values of a and b
+// using an inequality operation. :
+// https://msdn.microsoft.com/en-us/library/bafh5e0a(v=vs.90).aspx
+FORCE_INLINE int _mm_comineq_ss(__m128 a, __m128 b)
+{
+ return !_mm_comieq_ss(a, b);
+}
+
+// Convert packed signed 32-bit integers in b to packed single-precision
+// (32-bit) floating-point elements, store the results in the lower 2 elements
+// of dst, and copy the upper 2 packed elements from a to the upper elements of
+// dst.
//
-// MEM[mem_addr+63:mem_addr] := a[127:64]
+// dst[31:0] := Convert_Int32_To_FP32(b[31:0])
+// dst[63:32] := Convert_Int32_To_FP32(b[63:32])
+// dst[95:64] := a[95:64]
+// dst[127:96] := a[127:96]
//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_storeh_pd
-FORCE_INLINE void _mm_storeh_pd(double *mem_addr, __m128d a)
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvt_pi2ps
+FORCE_INLINE __m128 _mm_cvt_pi2ps(__m128 a, __m64 b)
{
-#if defined(__aarch64__)
- vst1_f64((float64_t *) mem_addr, vget_high_f64(vreinterpretq_f64_m128d(a)));
-#else
- vst1_f32((float32_t *) mem_addr, vget_high_f32(vreinterpretq_f32_m128d(a)));
-#endif
+ return vreinterpretq_m128_f32(
+ vcombine_f32(vcvt_f32_s32(vreinterpret_s32_m64(b)),
+ vget_high_f32(vreinterpretq_f32_m128(a))));
}
-// Store the lower double-precision (64-bit) floating-point element from a into
-// memory.
+// Convert packed single-precision (32-bit) floating-point elements in a to
+// packed 32-bit integers, and store the results in dst.
//
-// MEM[mem_addr+63:mem_addr] := a[63:0]
+// FOR j := 0 to 1
+// i := 32*j
+// dst[i+31:i] := Convert_FP32_To_Int32(a[i+31:i])
+// ENDFOR
//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_storel_pd
-FORCE_INLINE void _mm_storel_pd(double *mem_addr, __m128d a)
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvt_ps2pi
+FORCE_INLINE __m64 _mm_cvt_ps2pi(__m128 a)
{
#if defined(__aarch64__)
- vst1_f64((float64_t *) mem_addr, vget_low_f64(vreinterpretq_f64_m128d(a)));
+ return vreinterpret_m64_s32(
+ vget_low_s32(vcvtnq_s32_f32(vrndiq_f32(vreinterpretq_f32_m128(a)))));
#else
- vst1_f32((float32_t *) mem_addr, vget_low_f32(vreinterpretq_f32_m128d(a)));
+ return vreinterpret_m64_s32(vcvt_s32_f32(vget_low_f32(
+ vreinterpretq_f32_m128(_mm_round_ps(a, _MM_FROUND_CUR_DIRECTION)))));
#endif
}
-// Store 2 double-precision (64-bit) floating-point elements from a into memory
-// in reverse order. mem_addr must be aligned on a 16-byte boundary or a
-// general-protection exception may be generated.
+// Convert the signed 32-bit integer b to a single-precision (32-bit)
+// floating-point element, store the result in the lower element of dst, and
+// copy the upper 3 packed elements from a to the upper elements of dst.
//
-// MEM[mem_addr+63:mem_addr] := a[127:64]
-// MEM[mem_addr+127:mem_addr+64] := a[63:0]
+// dst[31:0] := Convert_Int32_To_FP32(b[31:0])
+// dst[127:32] := a[127:32]
//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_storer_pd
-FORCE_INLINE void _mm_storer_pd(double *mem_addr, __m128d a)
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvt_si2ss
+FORCE_INLINE __m128 _mm_cvt_si2ss(__m128 a, int b)
{
- float32x4_t f = vreinterpretq_f32_m128d(a);
- _mm_store_pd(mem_addr, vreinterpretq_m128d_f32(vextq_f32(f, f, 2)));
+ return vreinterpretq_m128_f32(
+ vsetq_lane_f32((float) b, vreinterpretq_f32_m128(a), 0));
}
-// Store the lower double-precision (64-bit) floating-point element from a into
-// 2 contiguous elements in memory. mem_addr must be aligned on a 16-byte
-// boundary or a general-protection exception may be generated.
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_store_pd1
-FORCE_INLINE void _mm_store_pd1(double *mem_addr, __m128d a)
+// Convert the lower single-precision (32-bit) floating-point element in a to a
+// 32-bit integer, and store the result in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvt_ss2si
+FORCE_INLINE int _mm_cvt_ss2si(__m128 a)
{
#if defined(__aarch64__)
- float64x1_t a_low = vget_low_f64(vreinterpretq_f64_m128d(a));
- vst1q_f64((float64_t *) mem_addr,
- vreinterpretq_f64_m128d(vcombine_f64(a_low, a_low)));
+ return vgetq_lane_s32(vcvtnq_s32_f32(vrndiq_f32(vreinterpretq_f32_m128(a))),
+ 0);
#else
- float32x2_t a_low = vget_low_f32(vreinterpretq_f32_m128d(a));
- vst1q_f32((float32_t *) mem_addr,
- vreinterpretq_f32_m128d(vcombine_f32(a_low, a_low)));
+ float32_t data = vgetq_lane_f32(
+ vreinterpretq_f32_m128(_mm_round_ps(a, _MM_FROUND_CUR_DIRECTION)), 0);
+ return (int32_t) data;
#endif
}
-// Store the lower double-precision (64-bit) floating-point element from a into
-// 2 contiguous elements in memory. mem_addr must be aligned on a 16-byte
-// boundary or a general-protection exception may be generated.
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#expand=9,526,5601&text=_mm_store1_pd
-#define _mm_store1_pd _mm_store_pd1
-
-// Store 128-bits (composed of 2 packed double-precision (64-bit) floating-point
-// elements) from a into memory. mem_addr does not need to be aligned on any
-// particular boundary.
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_storeu_pd
-FORCE_INLINE void _mm_storeu_pd(double *mem_addr, __m128d a)
+// Convert packed 16-bit integers in a to packed single-precision (32-bit)
+// floating-point elements, and store the results in dst.
+//
+// FOR j := 0 to 3
+// i := j*16
+// m := j*32
+// dst[m+31:m] := Convert_Int16_To_FP32(a[i+15:i])
+// ENDFOR
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtpi16_ps
+FORCE_INLINE __m128 _mm_cvtpi16_ps(__m64 a)
{
- _mm_store_pd(mem_addr, a);
+ return vreinterpretq_m128_f32(
+ vcvtq_f32_s32(vmovl_s16(vreinterpret_s16_m64(a))));
}
-// Reads the lower 64 bits of b and stores them into the lower 64 bits of a.
-// https://msdn.microsoft.com/en-us/library/hhwf428f%28v=vs.90%29.aspx
-FORCE_INLINE void _mm_storel_epi64(__m128i *a, __m128i b)
+// Convert packed 32-bit integers in b to packed single-precision (32-bit)
+// floating-point elements, store the results in the lower 2 elements of dst,
+// and copy the upper 2 packed elements from a to the upper elements of dst.
+//
+// dst[31:0] := Convert_Int32_To_FP32(b[31:0])
+// dst[63:32] := Convert_Int32_To_FP32(b[63:32])
+// dst[95:64] := a[95:64]
+// dst[127:96] := a[127:96]
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtpi32_ps
+FORCE_INLINE __m128 _mm_cvtpi32_ps(__m128 a, __m64 b)
{
- uint64x1_t hi = vget_high_u64(vreinterpretq_u64_m128i(*a));
- uint64x1_t lo = vget_low_u64(vreinterpretq_u64_m128i(b));
- *a = vreinterpretq_m128i_u64(vcombine_u64(lo, hi));
+ return vreinterpretq_m128_f32(
+ vcombine_f32(vcvt_f32_s32(vreinterpret_s32_m64(b)),
+ vget_high_f32(vreinterpretq_f32_m128(a))));
}
-// Stores the lower two single-precision floating point values of a to the
-// address p.
+// Convert packed signed 32-bit integers in a to packed single-precision
+// (32-bit) floating-point elements, store the results in the lower 2 elements
+// of dst, then covert the packed signed 32-bit integers in b to
+// single-precision (32-bit) floating-point element, and store the results in
+// the upper 2 elements of dst.
//
-// *p0 := a0
-// *p1 := a1
+// dst[31:0] := Convert_Int32_To_FP32(a[31:0])
+// dst[63:32] := Convert_Int32_To_FP32(a[63:32])
+// dst[95:64] := Convert_Int32_To_FP32(b[31:0])
+// dst[127:96] := Convert_Int32_To_FP32(b[63:32])
//
-// https://msdn.microsoft.com/en-us/library/h54t98ks(v=vs.90).aspx
-FORCE_INLINE void _mm_storel_pi(__m64 *p, __m128 a)
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtpi32x2_ps
+FORCE_INLINE __m128 _mm_cvtpi32x2_ps(__m64 a, __m64 b)
{
- *p = vreinterpret_m64_f32(vget_low_f32(a));
+ return vreinterpretq_m128_f32(vcvtq_f32_s32(
+ vcombine_s32(vreinterpret_s32_m64(a), vreinterpret_s32_m64(b))));
}
-// Stores the upper two single-precision, floating-point values of a to the
-// address p.
+// Convert the lower packed 8-bit integers in a to packed single-precision
+// (32-bit) floating-point elements, and store the results in dst.
//
-// *p0 := a2
-// *p1 := a3
+// FOR j := 0 to 3
+// i := j*8
+// m := j*32
+// dst[m+31:m] := Convert_Int8_To_FP32(a[i+7:i])
+// ENDFOR
//
-// https://msdn.microsoft.com/en-us/library/a7525fs8(v%3dvs.90).aspx
-FORCE_INLINE void _mm_storeh_pi(__m64 *p, __m128 a)
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtpi8_ps
+FORCE_INLINE __m128 _mm_cvtpi8_ps(__m64 a)
{
- *p = vreinterpret_m64_f32(vget_high_f32(a));
+ return vreinterpretq_m128_f32(vcvtq_f32_s32(
+ vmovl_s16(vget_low_s16(vmovl_s8(vreinterpret_s8_m64(a))))));
}
-// Loads a single single-precision, floating-point value, copying it into all
-// four words
-// https://msdn.microsoft.com/en-us/library/vstudio/5cdkf716(v=vs.100).aspx
-FORCE_INLINE __m128 _mm_load1_ps(const float *p)
+// Convert packed single-precision (32-bit) floating-point elements in a to
+// packed 16-bit integers, and store the results in dst. Note: this intrinsic
+// will generate 0x7FFF, rather than 0x8000, for input values between 0x7FFF and
+// 0x7FFFFFFF.
+//
+// FOR j := 0 to 3
+// i := 16*j
+// k := 32*j
+// IF a[k+31:k] >= FP32(0x7FFF) && a[k+31:k] <= FP32(0x7FFFFFFF)
+// dst[i+15:i] := 0x7FFF
+// ELSE
+// dst[i+15:i] := Convert_FP32_To_Int16(a[k+31:k])
+// FI
+// ENDFOR
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtps_pi16
+FORCE_INLINE __m64 _mm_cvtps_pi16(__m128 a)
{
- return vreinterpretq_m128_f32(vld1q_dup_f32(p));
+ const __m128 i16Min = _mm_set_ps1((float) INT16_MIN);
+ const __m128 i16Max = _mm_set_ps1((float) INT16_MAX);
+ const __m128 i32Max = _mm_set_ps1((float) INT32_MAX);
+ const __m128i maxMask = _mm_castps_si128(
+ _mm_and_ps(_mm_cmpge_ps(a, i16Max), _mm_cmple_ps(a, i32Max)));
+ const __m128i betweenMask = _mm_castps_si128(
+ _mm_and_ps(_mm_cmpgt_ps(a, i16Min), _mm_cmplt_ps(a, i16Max)));
+ const __m128i minMask = _mm_cmpeq_epi32(_mm_or_si128(maxMask, betweenMask),
+ _mm_setzero_si128());
+ __m128i max = _mm_and_si128(maxMask, _mm_set1_epi32(INT16_MAX));
+ __m128i min = _mm_and_si128(minMask, _mm_set1_epi32(INT16_MIN));
+ __m128i cvt = _mm_and_si128(betweenMask, _mm_cvtps_epi32(a));
+ __m128i res32 = _mm_or_si128(_mm_or_si128(max, min), cvt);
+ return vreinterpret_m64_s16(vmovn_s32(vreinterpretq_s32_m128i(res32)));
}
-// Load a single-precision (32-bit) floating-point element from memory into all
-// elements of dst.
+// Convert packed single-precision (32-bit) floating-point elements in a to
+// packed 32-bit integers, and store the results in dst.
//
-// dst[31:0] := MEM[mem_addr+31:mem_addr]
-// dst[63:32] := MEM[mem_addr+31:mem_addr]
-// dst[95:64] := MEM[mem_addr+31:mem_addr]
-// dst[127:96] := MEM[mem_addr+31:mem_addr]
+// FOR j := 0 to 1
+// i := 32*j
+// dst[i+31:i] := Convert_FP32_To_Int32(a[i+31:i])
+// ENDFOR
//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_load_ps1
-#define _mm_load_ps1 _mm_load1_ps
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtps_pi32
+#define _mm_cvtps_pi32(a) _mm_cvt_ps2pi(a)
-// Sets the lower two single-precision, floating-point values with 64
-// bits of data loaded from the address p; the upper two values are passed
-// through from a.
+// Convert packed single-precision (32-bit) floating-point elements in a to
+// packed 8-bit integers, and store the results in lower 4 elements of dst.
+// Note: this intrinsic will generate 0x7F, rather than 0x80, for input values
+// between 0x7F and 0x7FFFFFFF.
//
-// Return Value
-// r0 := *p0
-// r1 := *p1
-// r2 := a2
-// r3 := a3
+// FOR j := 0 to 3
+// i := 8*j
+// k := 32*j
+// IF a[k+31:k] >= FP32(0x7F) && a[k+31:k] <= FP32(0x7FFFFFFF)
+// dst[i+7:i] := 0x7F
+// ELSE
+// dst[i+7:i] := Convert_FP32_To_Int8(a[k+31:k])
+// FI
+// ENDFOR
//
-// https://msdn.microsoft.com/en-us/library/s57cyak2(v=vs.100).aspx
-FORCE_INLINE __m128 _mm_loadl_pi(__m128 a, __m64 const *p)
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtps_pi8
+FORCE_INLINE __m64 _mm_cvtps_pi8(__m128 a)
+{
+ const __m128 i8Min = _mm_set_ps1((float) INT8_MIN);
+ const __m128 i8Max = _mm_set_ps1((float) INT8_MAX);
+ const __m128 i32Max = _mm_set_ps1((float) INT32_MAX);
+ const __m128i maxMask = _mm_castps_si128(
+ _mm_and_ps(_mm_cmpge_ps(a, i8Max), _mm_cmple_ps(a, i32Max)));
+ const __m128i betweenMask = _mm_castps_si128(
+ _mm_and_ps(_mm_cmpgt_ps(a, i8Min), _mm_cmplt_ps(a, i8Max)));
+ const __m128i minMask = _mm_cmpeq_epi32(_mm_or_si128(maxMask, betweenMask),
+ _mm_setzero_si128());
+ __m128i max = _mm_and_si128(maxMask, _mm_set1_epi32(INT8_MAX));
+ __m128i min = _mm_and_si128(minMask, _mm_set1_epi32(INT8_MIN));
+ __m128i cvt = _mm_and_si128(betweenMask, _mm_cvtps_epi32(a));
+ __m128i res32 = _mm_or_si128(_mm_or_si128(max, min), cvt);
+ int16x4_t res16 = vmovn_s32(vreinterpretq_s32_m128i(res32));
+ int8x8_t res8 = vmovn_s16(vcombine_s16(res16, res16));
+ uint32_t bitMask[2] = {0xFFFFFFFF, 0};
+ int8x8_t mask = vreinterpret_s8_u32(vld1_u32(bitMask));
+
+ return vreinterpret_m64_s8(vorr_s8(vand_s8(mask, res8), vdup_n_s8(0)));
+}
+
+// Convert packed unsigned 16-bit integers in a to packed single-precision
+// (32-bit) floating-point elements, and store the results in dst.
+//
+// FOR j := 0 to 3
+// i := j*16
+// m := j*32
+// dst[m+31:m] := Convert_UInt16_To_FP32(a[i+15:i])
+// ENDFOR
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtpu16_ps
+FORCE_INLINE __m128 _mm_cvtpu16_ps(__m64 a)
{
return vreinterpretq_m128_f32(
- vcombine_f32(vld1_f32((const float32_t *) p), vget_high_f32(a)));
+ vcvtq_f32_u32(vmovl_u16(vreinterpret_u16_m64(a))));
}
-// Load 4 single-precision (32-bit) floating-point elements from memory into dst
-// in reverse order. mem_addr must be aligned on a 16-byte boundary or a
-// general-protection exception may be generated.
+// Convert the lower packed unsigned 8-bit integers in a to packed
+// single-precision (32-bit) floating-point elements, and store the results in
+// dst.
//
-// dst[31:0] := MEM[mem_addr+127:mem_addr+96]
-// dst[63:32] := MEM[mem_addr+95:mem_addr+64]
-// dst[95:64] := MEM[mem_addr+63:mem_addr+32]
-// dst[127:96] := MEM[mem_addr+31:mem_addr]
+// FOR j := 0 to 3
+// i := j*8
+// m := j*32
+// dst[m+31:m] := Convert_UInt8_To_FP32(a[i+7:i])
+// ENDFOR
//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_loadr_ps
-FORCE_INLINE __m128 _mm_loadr_ps(const float *p)
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtpu8_ps
+FORCE_INLINE __m128 _mm_cvtpu8_ps(__m64 a)
{
- float32x4_t v = vrev64q_f32(vld1q_f32(p));
- return vreinterpretq_m128_f32(vextq_f32(v, v, 2));
+ return vreinterpretq_m128_f32(vcvtq_f32_u32(
+ vmovl_u16(vget_low_u16(vmovl_u8(vreinterpret_u8_m64(a))))));
}
-// Sets the upper two single-precision, floating-point values with 64
-// bits of data loaded from the address p; the lower two values are passed
-// through from a.
+// Convert the signed 32-bit integer b to a single-precision (32-bit)
+// floating-point element, store the result in the lower element of dst, and
+// copy the upper 3 packed elements from a to the upper elements of dst.
//
-// r0 := a0
-// r1 := a1
-// r2 := *p0
-// r3 := *p1
+// dst[31:0] := Convert_Int32_To_FP32(b[31:0])
+// dst[127:32] := a[127:32]
//
-// https://msdn.microsoft.com/en-us/library/w92wta0x(v%3dvs.100).aspx
-FORCE_INLINE __m128 _mm_loadh_pi(__m128 a, __m64 const *p)
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtsi32_ss
+#define _mm_cvtsi32_ss(a, b) _mm_cvt_si2ss(a, b)
+
+// Convert the signed 64-bit integer b to a single-precision (32-bit)
+// floating-point element, store the result in the lower element of dst, and
+// copy the upper 3 packed elements from a to the upper elements of dst.
+//
+// dst[31:0] := Convert_Int64_To_FP32(b[63:0])
+// dst[127:32] := a[127:32]
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtsi64_ss
+FORCE_INLINE __m128 _mm_cvtsi64_ss(__m128 a, int64_t b)
{
return vreinterpretq_m128_f32(
- vcombine_f32(vget_low_f32(a), vld1_f32((const float32_t *) p)));
+ vsetq_lane_f32((float) b, vreinterpretq_f32_m128(a), 0));
}
-// Loads four single-precision, floating-point values.
-// https://msdn.microsoft.com/en-us/library/vstudio/zzd50xxt(v=vs.100).aspx
-FORCE_INLINE __m128 _mm_load_ps(const float *p)
+// Copy the lower single-precision (32-bit) floating-point element of a to dst.
+//
+// dst[31:0] := a[31:0]
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtss_f32
+FORCE_INLINE float _mm_cvtss_f32(__m128 a)
{
- return vreinterpretq_m128_f32(vld1q_f32(p));
+ return vgetq_lane_f32(vreinterpretq_f32_m128(a), 0);
}
-// Loads four single-precision, floating-point values.
-// https://msdn.microsoft.com/en-us/library/x1b16s7z%28v=vs.90%29.aspx
-FORCE_INLINE __m128 _mm_loadu_ps(const float *p)
+// Convert the lower single-precision (32-bit) floating-point element in a to a
+// 32-bit integer, and store the result in dst.
+//
+// dst[31:0] := Convert_FP32_To_Int32(a[31:0])
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtss_si32
+#define _mm_cvtss_si32(a) _mm_cvt_ss2si(a)
+
+// Convert the lower single-precision (32-bit) floating-point element in a to a
+// 64-bit integer, and store the result in dst.
+//
+// dst[63:0] := Convert_FP32_To_Int64(a[31:0])
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtss_si64
+FORCE_INLINE int64_t _mm_cvtss_si64(__m128 a)
{
- // for neon, alignment doesn't matter, so _mm_load_ps and _mm_loadu_ps are
- // equivalent for neon
- return vreinterpretq_m128_f32(vld1q_f32(p));
+#if defined(__aarch64__)
+ return (int64_t) vgetq_lane_f32(vrndiq_f32(vreinterpretq_f32_m128(a)), 0);
+#else
+ float32_t data = vgetq_lane_f32(
+ vreinterpretq_f32_m128(_mm_round_ps(a, _MM_FROUND_CUR_DIRECTION)), 0);
+ return (int64_t) data;
+#endif
}
-// Load unaligned 16-bit integer from memory into the first element of dst.
+// Convert packed single-precision (32-bit) floating-point elements in a to
+// packed 32-bit integers with truncation, and store the results in dst.
//
-// dst[15:0] := MEM[mem_addr+15:mem_addr]
-// dst[MAX:16] := 0
+// FOR j := 0 to 1
+// i := 32*j
+// dst[i+31:i] := Convert_FP32_To_Int32_Truncate(a[i+31:i])
+// ENDFOR
//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_loadu_si16
-FORCE_INLINE __m128i _mm_loadu_si16(const void *p)
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtt_ps2pi
+FORCE_INLINE __m64 _mm_cvtt_ps2pi(__m128 a)
{
- return vreinterpretq_m128i_s16(
- vsetq_lane_s16(*(const int16_t *) p, vdupq_n_s16(0), 0));
+ return vreinterpret_m64_s32(
+ vget_low_s32(vcvtq_s32_f32(vreinterpretq_f32_m128(a))));
}
-// Load unaligned 64-bit integer from memory into the first element of dst.
+// Convert the lower single-precision (32-bit) floating-point element in a to a
+// 32-bit integer with truncation, and store the result in dst.
//
-// dst[63:0] := MEM[mem_addr+63:mem_addr]
-// dst[MAX:64] := 0
+// dst[31:0] := Convert_FP32_To_Int32_Truncate(a[31:0])
//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_loadu_si64
-FORCE_INLINE __m128i _mm_loadu_si64(const void *p)
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtt_ss2si
+FORCE_INLINE int _mm_cvtt_ss2si(__m128 a)
{
- return vreinterpretq_m128i_s64(
- vcombine_s64(vld1_s64((const int64_t *) p), vdup_n_s64(0)));
+ return vgetq_lane_s32(vcvtq_s32_f32(vreinterpretq_f32_m128(a)), 0);
}
-// Load a double-precision (64-bit) floating-point element from memory into the
-// lower of dst, and zero the upper element. mem_addr does not need to be
-// aligned on any particular boundary.
+// Convert packed single-precision (32-bit) floating-point elements in a to
+// packed 32-bit integers with truncation, and store the results in dst.
//
-// dst[63:0] := MEM[mem_addr+63:mem_addr]
-// dst[127:64] := 0
+// FOR j := 0 to 1
+// i := 32*j
+// dst[i+31:i] := Convert_FP32_To_Int32_Truncate(a[i+31:i])
+// ENDFOR
//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_load_sd
-FORCE_INLINE __m128d _mm_load_sd(const double *p)
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvttps_pi32
+#define _mm_cvttps_pi32(a) _mm_cvtt_ps2pi(a)
+
+// Convert the lower single-precision (32-bit) floating-point element in a to a
+// 32-bit integer with truncation, and store the result in dst.
+//
+// dst[31:0] := Convert_FP32_To_Int32_Truncate(a[31:0])
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvttss_si32
+#define _mm_cvttss_si32(a) _mm_cvtt_ss2si(a)
+
+// Convert the lower single-precision (32-bit) floating-point element in a to a
+// 64-bit integer with truncation, and store the result in dst.
+//
+// dst[63:0] := Convert_FP32_To_Int64_Truncate(a[31:0])
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvttss_si64
+FORCE_INLINE int64_t _mm_cvttss_si64(__m128 a)
{
-#if defined(__aarch64__)
- return vreinterpretq_m128d_f64(vsetq_lane_f64(*p, vdupq_n_f64(0), 0));
-#else
- const float *fp = (const float *) p;
- float ALIGN_STRUCT(16) data[4] = {fp[0], fp[1], 0, 0};
- return vreinterpretq_m128d_f32(vld1q_f32(data));
-#endif
+ return (int64_t) vgetq_lane_f32(vreinterpretq_f32_m128(a), 0);
}
-// Loads two double-precision from 16-byte aligned memory, floating-point
-// values.
+// Divides the four single-precision, floating-point values of a and b.
//
-// dst[127:0] := MEM[mem_addr+127:mem_addr]
+// r0 := a0 / b0
+// r1 := a1 / b1
+// r2 := a2 / b2
+// r3 := a3 / b3
//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_load_pd
-FORCE_INLINE __m128d _mm_load_pd(const double *p)
+// https://msdn.microsoft.com/en-us/library/edaw8147(v=vs.100).aspx
+FORCE_INLINE __m128 _mm_div_ps(__m128 a, __m128 b)
{
-#if defined(__aarch64__)
- return vreinterpretq_m128d_f64(vld1q_f64(p));
+#if defined(__aarch64__) && !SSE2NEON_PRECISE_DIV
+ return vreinterpretq_m128_f32(
+ vdivq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b)));
#else
- const float *fp = (const float *) p;
- float ALIGN_STRUCT(16) data[4] = {fp[0], fp[1], fp[2], fp[3]};
- return vreinterpretq_m128d_f32(vld1q_f32(data));
+ float32x4_t recip = vrecpeq_f32(vreinterpretq_f32_m128(b));
+ recip = vmulq_f32(recip, vrecpsq_f32(recip, vreinterpretq_f32_m128(b)));
+#if SSE2NEON_PRECISE_DIV
+ // Additional Netwon-Raphson iteration for accuracy
+ recip = vmulq_f32(recip, vrecpsq_f32(recip, vreinterpretq_f32_m128(b)));
+#endif
+ return vreinterpretq_m128_f32(vmulq_f32(vreinterpretq_f32_m128(a), recip));
#endif
}
-// Loads two double-precision from unaligned memory, floating-point values.
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_loadu_pd
-FORCE_INLINE __m128d _mm_loadu_pd(const double *p)
+// Divides the scalar single-precision floating point value of a by b.
+// https://msdn.microsoft.com/en-us/library/4y73xa49(v=vs.100).aspx
+FORCE_INLINE __m128 _mm_div_ss(__m128 a, __m128 b)
{
- return _mm_load_pd(p);
+ float32_t value =
+ vgetq_lane_f32(vreinterpretq_f32_m128(_mm_div_ps(a, b)), 0);
+ return vreinterpretq_m128_f32(
+ vsetq_lane_f32(value, vreinterpretq_f32_m128(a), 0));
}
-// Loads an single - precision, floating - point value into the low word and
-// clears the upper three words.
-// https://msdn.microsoft.com/en-us/library/548bb9h4%28v=vs.90%29.aspx
-FORCE_INLINE __m128 _mm_load_ss(const float *p)
-{
- return vreinterpretq_m128_f32(vsetq_lane_f32(*p, vdupq_n_f32(0), 0));
-}
+// Extract a 16-bit integer from a, selected with imm8, and store the result in
+// the lower element of dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_extract_pi16
+#define _mm_extract_pi16(a, imm) \
+ (int32_t) vget_lane_u16(vreinterpret_u16_m64(a), (imm))
-// Load 64-bit integer from memory into the first element of dst.
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_loadl_epi64
-FORCE_INLINE __m128i _mm_loadl_epi64(__m128i const *p)
+// Free aligned memory that was allocated with _mm_malloc.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_free
+FORCE_INLINE void _mm_free(void *addr)
{
- /* Load the lower 64 bits of the value pointed to by p into the
- * lower 64 bits of the result, zeroing the upper 64 bits of the result.
- */
- return vreinterpretq_m128i_s32(
- vcombine_s32(vld1_s32((int32_t const *) p), vcreate_s32(0)));
+ free(addr);
}
-// Load a double-precision (64-bit) floating-point element from memory into the
-// lower element of dst, and copy the upper element from a to dst. mem_addr does
-// not need to be aligned on any particular boundary.
-//
-// dst[63:0] := MEM[mem_addr+63:mem_addr]
-// dst[127:64] := a[127:64]
-//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_loadl_pd
-FORCE_INLINE __m128d _mm_loadl_pd(__m128d a, const double *p)
+// Macro: Get the flush zero bits from the MXCSR control and status register.
+// The flush zero may contain any of the following flags: _MM_FLUSH_ZERO_ON or
+// _MM_FLUSH_ZERO_OFF
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_MM_GET_FLUSH_ZERO_MODE
+FORCE_INLINE unsigned int _sse2neon_mm_get_flush_zero_mode()
{
+ union {
+ fpcr_bitfield field;
#if defined(__aarch64__)
- return vreinterpretq_m128d_f64(
- vcombine_f64(vld1_f64(p), vget_high_f64(vreinterpretq_f64_m128d(a))));
+ uint64_t value;
#else
- return vreinterpretq_m128d_f32(
- vcombine_f32(vld1_f32((const float *) p),
- vget_high_f32(vreinterpretq_f32_m128d(a))));
+ uint32_t value;
#endif
-}
+ } r;
-// Load 2 double-precision (64-bit) floating-point elements from memory into dst
-// in reverse order. mem_addr must be aligned on a 16-byte boundary or a
-// general-protection exception may be generated.
-//
-// dst[63:0] := MEM[mem_addr+127:mem_addr+64]
-// dst[127:64] := MEM[mem_addr+63:mem_addr]
-//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_loadr_pd
-FORCE_INLINE __m128d _mm_loadr_pd(const double *p)
-{
#if defined(__aarch64__)
- float64x2_t v = vld1q_f64(p);
- return vreinterpretq_m128d_f64(vextq_f64(v, v, 1));
+ asm volatile("mrs %0, FPCR" : "=r"(r.value)); /* read */
#else
- int64x2_t v = vld1q_s64((const int64_t *) p);
- return vreinterpretq_m128d_s64(vextq_s64(v, v, 1));
+ asm volatile("vmrs %0, FPSCR" : "=r"(r.value)); /* read */
#endif
+
+ return r.field.bit24 ? _MM_FLUSH_ZERO_ON : _MM_FLUSH_ZERO_OFF;
}
-// Sets the low word to the single-precision, floating-point value of b
-// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/35hdzazd(v=vs.100)
-FORCE_INLINE __m128 _mm_move_ss(__m128 a, __m128 b)
+// Macro: Get the rounding mode bits from the MXCSR control and status register.
+// The rounding mode may contain any of the following flags: _MM_ROUND_NEAREST,
+// _MM_ROUND_DOWN, _MM_ROUND_UP, _MM_ROUND_TOWARD_ZERO
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_MM_GET_ROUNDING_MODE
+FORCE_INLINE unsigned int _MM_GET_ROUNDING_MODE()
{
- return vreinterpretq_m128_f32(
- vsetq_lane_f32(vgetq_lane_f32(vreinterpretq_f32_m128(b), 0),
- vreinterpretq_f32_m128(a), 0));
+ union {
+ fpcr_bitfield field;
+#if defined(__aarch64__)
+ uint64_t value;
+#else
+ uint32_t value;
+#endif
+ } r;
+
+#if defined(__aarch64__)
+ asm volatile("mrs %0, FPCR" : "=r"(r.value)); /* read */
+#else
+ asm volatile("vmrs %0, FPSCR" : "=r"(r.value)); /* read */
+#endif
+
+ if (r.field.bit22) {
+ return r.field.bit23 ? _MM_ROUND_TOWARD_ZERO : _MM_ROUND_UP;
+ } else {
+ return r.field.bit23 ? _MM_ROUND_DOWN : _MM_ROUND_NEAREST;
+ }
}
-// Move the lower double-precision (64-bit) floating-point element from b to the
-// lower element of dst, and copy the upper element from a to the upper element
-// of dst.
-//
-// dst[63:0] := b[63:0]
-// dst[127:64] := a[127:64]
-//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_move_sd
-FORCE_INLINE __m128d _mm_move_sd(__m128d a, __m128d b)
+// Copy a to dst, and insert the 16-bit integer i into dst at the location
+// specified by imm8.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_insert_pi16
+#define _mm_insert_pi16(a, b, imm) \
+ __extension__({ \
+ vreinterpret_m64_s16( \
+ vset_lane_s16((b), vreinterpret_s16_m64(a), (imm))); \
+ })
+
+// Loads four single-precision, floating-point values.
+// https://msdn.microsoft.com/en-us/library/vstudio/zzd50xxt(v=vs.100).aspx
+FORCE_INLINE __m128 _mm_load_ps(const float *p)
{
- return vreinterpretq_m128d_f32(
- vcombine_f32(vget_low_f32(vreinterpretq_f32_m128d(b)),
- vget_high_f32(vreinterpretq_f32_m128d(a))));
+ return vreinterpretq_m128_f32(vld1q_f32(p));
}
-// Copy the lower 64-bit integer in a to the lower element of dst, and zero the
-// upper element.
+// Load a single-precision (32-bit) floating-point element from memory into all
+// elements of dst.
//
-// dst[63:0] := a[63:0]
-// dst[127:64] := 0
+// dst[31:0] := MEM[mem_addr+31:mem_addr]
+// dst[63:32] := MEM[mem_addr+31:mem_addr]
+// dst[95:64] := MEM[mem_addr+31:mem_addr]
+// dst[127:96] := MEM[mem_addr+31:mem_addr]
//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_move_epi64
-FORCE_INLINE __m128i _mm_move_epi64(__m128i a)
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_load_ps1
+#define _mm_load_ps1 _mm_load1_ps
+
+// Loads an single - precision, floating - point value into the low word and
+// clears the upper three words.
+// https://msdn.microsoft.com/en-us/library/548bb9h4%28v=vs.90%29.aspx
+FORCE_INLINE __m128 _mm_load_ss(const float *p)
{
- return vreinterpretq_m128i_s64(
- vsetq_lane_s64(0, vreinterpretq_s64_m128i(a), 1));
+ return vreinterpretq_m128_f32(vsetq_lane_f32(*p, vdupq_n_f32(0), 0));
}
-// Return vector of type __m128 with undefined elements.
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_undefined_ps
-FORCE_INLINE __m128 _mm_undefined_ps(void)
+// Loads a single single-precision, floating-point value, copying it into all
+// four words
+// https://msdn.microsoft.com/en-us/library/vstudio/5cdkf716(v=vs.100).aspx
+FORCE_INLINE __m128 _mm_load1_ps(const float *p)
{
-#if defined(__GNUC__) || defined(__clang__)
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wuninitialized"
-#endif
- __m128 a;
- return a;
-#if defined(__GNUC__) || defined(__clang__)
-#pragma GCC diagnostic pop
-#endif
+ return vreinterpretq_m128_f32(vld1q_dup_f32(p));
}
-/* Logic/Binary operations */
-
-// Computes the bitwise AND-NOT of the four single-precision, floating-point
-// values of a and b.
+// Sets the upper two single-precision, floating-point values with 64
+// bits of data loaded from the address p; the lower two values are passed
+// through from a.
//
-// r0 := ~a0 & b0
-// r1 := ~a1 & b1
-// r2 := ~a2 & b2
-// r3 := ~a3 & b3
+// r0 := a0
+// r1 := a1
+// r2 := *p0
+// r3 := *p1
//
-// https://msdn.microsoft.com/en-us/library/vstudio/68h7wd02(v=vs.100).aspx
-FORCE_INLINE __m128 _mm_andnot_ps(__m128 a, __m128 b)
+// https://msdn.microsoft.com/en-us/library/w92wta0x(v%3dvs.100).aspx
+FORCE_INLINE __m128 _mm_loadh_pi(__m128 a, __m64 const *p)
{
- return vreinterpretq_m128_s32(
- vbicq_s32(vreinterpretq_s32_m128(b),
- vreinterpretq_s32_m128(a))); // *NOTE* argument swap
+ return vreinterpretq_m128_f32(
+ vcombine_f32(vget_low_f32(a), vld1_f32((const float32_t *) p)));
}
-// Compute the bitwise NOT of packed double-precision (64-bit) floating-point
-// elements in a and then AND with b, and store the results in dst.
+// Sets the lower two single-precision, floating-point values with 64
+// bits of data loaded from the address p; the upper two values are passed
+// through from a.
//
-// FOR j := 0 to 1
-// i := j*64
-// dst[i+63:i] := ((NOT a[i+63:i]) AND b[i+63:i])
-// ENDFOR
+// Return Value
+// r0 := *p0
+// r1 := *p1
+// r2 := a2
+// r3 := a3
//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_andnot_pd
-FORCE_INLINE __m128d _mm_andnot_pd(__m128d a, __m128d b)
+// https://msdn.microsoft.com/en-us/library/s57cyak2(v=vs.100).aspx
+FORCE_INLINE __m128 _mm_loadl_pi(__m128 a, __m64 const *p)
{
- // *NOTE* argument swap
- return vreinterpretq_m128d_s64(
- vbicq_s64(vreinterpretq_s64_m128d(b), vreinterpretq_s64_m128d(a)));
+ return vreinterpretq_m128_f32(
+ vcombine_f32(vld1_f32((const float32_t *) p), vget_high_f32(a)));
}
-// Computes the bitwise AND of the 128-bit value in b and the bitwise NOT of the
-// 128-bit value in a.
+// Load 4 single-precision (32-bit) floating-point elements from memory into dst
+// in reverse order. mem_addr must be aligned on a 16-byte boundary or a
+// general-protection exception may be generated.
//
-// r := (~a) & b
+// dst[31:0] := MEM[mem_addr+127:mem_addr+96]
+// dst[63:32] := MEM[mem_addr+95:mem_addr+64]
+// dst[95:64] := MEM[mem_addr+63:mem_addr+32]
+// dst[127:96] := MEM[mem_addr+31:mem_addr]
//
-// https://msdn.microsoft.com/en-us/library/vstudio/1beaceh8(v=vs.100).aspx
-FORCE_INLINE __m128i _mm_andnot_si128(__m128i a, __m128i b)
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_loadr_ps
+FORCE_INLINE __m128 _mm_loadr_ps(const float *p)
{
- return vreinterpretq_m128i_s32(
- vbicq_s32(vreinterpretq_s32_m128i(b),
- vreinterpretq_s32_m128i(a))); // *NOTE* argument swap
+ float32x4_t v = vrev64q_f32(vld1q_f32(p));
+ return vreinterpretq_m128_f32(vextq_f32(v, v, 2));
}
-// Computes the bitwise AND of the 128-bit value in a and the 128-bit value in
-// b.
-//
-// r := a & b
-//
-// https://msdn.microsoft.com/en-us/library/vstudio/6d1txsa8(v=vs.100).aspx
-FORCE_INLINE __m128i _mm_and_si128(__m128i a, __m128i b)
+// Loads four single-precision, floating-point values.
+// https://msdn.microsoft.com/en-us/library/x1b16s7z%28v=vs.90%29.aspx
+FORCE_INLINE __m128 _mm_loadu_ps(const float *p)
{
- return vreinterpretq_m128i_s32(
- vandq_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(b)));
+ // for neon, alignment doesn't matter, so _mm_load_ps and _mm_loadu_ps are
+ // equivalent for neon
+ return vreinterpretq_m128_f32(vld1q_f32(p));
}
-// Computes the bitwise AND of the four single-precision, floating-point values
-// of a and b.
+// Load unaligned 16-bit integer from memory into the first element of dst.
//
-// r0 := a0 & b0
-// r1 := a1 & b1
-// r2 := a2 & b2
-// r3 := a3 & b3
+// dst[15:0] := MEM[mem_addr+15:mem_addr]
+// dst[MAX:16] := 0
//
-// https://msdn.microsoft.com/en-us/library/vstudio/73ck1xc5(v=vs.100).aspx
-FORCE_INLINE __m128 _mm_and_ps(__m128 a, __m128 b)
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_loadu_si16
+FORCE_INLINE __m128i _mm_loadu_si16(const void *p)
{
- return vreinterpretq_m128_s32(
- vandq_s32(vreinterpretq_s32_m128(a), vreinterpretq_s32_m128(b)));
+ return vreinterpretq_m128i_s16(
+ vsetq_lane_s16(*(const int16_t *) p, vdupq_n_s16(0), 0));
}
-// Compute the bitwise AND of packed double-precision (64-bit) floating-point
-// elements in a and b, and store the results in dst.
+// Load unaligned 64-bit integer from memory into the first element of dst.
//
-// FOR j := 0 to 1
-// i := j*64
-// dst[i+63:i] := a[i+63:i] AND b[i+63:i]
-// ENDFOR
+// dst[63:0] := MEM[mem_addr+63:mem_addr]
+// dst[MAX:64] := 0
//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_and_pd
-FORCE_INLINE __m128d _mm_and_pd(__m128d a, __m128d b)
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_loadu_si64
+FORCE_INLINE __m128i _mm_loadu_si64(const void *p)
{
- return vreinterpretq_m128d_s64(
- vandq_s64(vreinterpretq_s64_m128d(a), vreinterpretq_s64_m128d(b)));
+ return vreinterpretq_m128i_s64(
+ vcombine_s64(vld1_s64((const int64_t *) p), vdup_n_s64(0)));
}
-// Computes the bitwise OR of the four single-precision, floating-point values
-// of a and b.
-// https://msdn.microsoft.com/en-us/library/vstudio/7ctdsyy0(v=vs.100).aspx
-FORCE_INLINE __m128 _mm_or_ps(__m128 a, __m128 b)
+// Allocate aligned blocks of memory.
+// https://software.intel.com/en-us/
+// cpp-compiler-developer-guide-and-reference-allocating-and-freeing-aligned-memory-blocks
+FORCE_INLINE void *_mm_malloc(size_t size, size_t align)
{
- return vreinterpretq_m128_s32(
- vorrq_s32(vreinterpretq_s32_m128(a), vreinterpretq_s32_m128(b)));
+ void *ptr;
+ if (align == 1)
+ return malloc(size);
+ if (align == 2 || (sizeof(void *) == 8 && align == 4))
+ align = sizeof(void *);
+ if (!posix_memalign(&ptr, align, size))
+ return ptr;
+ return NULL;
}
-// Computes bitwise EXOR (exclusive-or) of the four single-precision,
-// floating-point values of a and b.
-// https://msdn.microsoft.com/en-us/library/ss6k3wk8(v=vs.100).aspx
-FORCE_INLINE __m128 _mm_xor_ps(__m128 a, __m128 b)
+// Conditionally store 8-bit integer elements from a into memory using mask
+// (elements are not stored when the highest bit is not set in the corresponding
+// element) and a non-temporal memory hint.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskmove_si64
+FORCE_INLINE void _mm_maskmove_si64(__m64 a, __m64 mask, char *mem_addr)
{
- return vreinterpretq_m128_s32(
- veorq_s32(vreinterpretq_s32_m128(a), vreinterpretq_s32_m128(b)));
+ int8x8_t shr_mask = vshr_n_s8(vreinterpret_s8_m64(mask), 7);
+ __m128 b = _mm_load_ps((const float *) mem_addr);
+ int8x8_t masked =
+ vbsl_s8(vreinterpret_u8_s8(shr_mask), vreinterpret_s8_m64(a),
+ vreinterpret_s8_u64(vget_low_u64(vreinterpretq_u64_m128(b))));
+ vst1_s8((int8_t *) mem_addr, masked);
}
-// Compute the bitwise XOR of packed double-precision (64-bit) floating-point
-// elements in a and b, and store the results in dst.
+// Conditionally store 8-bit integer elements from a into memory using mask
+// (elements are not stored when the highest bit is not set in the corresponding
+// element) and a non-temporal memory hint.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_m_maskmovq
+#define _m_maskmovq(a, mask, mem_addr) _mm_maskmove_si64(a, mask, mem_addr)
+
+// Compare packed signed 16-bit integers in a and b, and store packed maximum
+// values in dst.
//
-// FOR j := 0 to 1
-// i := j*64
-// dst[i+63:i] := a[i+63:i] XOR b[i+63:i]
+// FOR j := 0 to 3
+// i := j*16
+// dst[i+15:i] := MAX(a[i+15:i], b[i+15:i])
// ENDFOR
//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_xor_pd
-FORCE_INLINE __m128d _mm_xor_pd(__m128d a, __m128d b)
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_max_pi16
+FORCE_INLINE __m64 _mm_max_pi16(__m64 a, __m64 b)
{
- return vreinterpretq_m128d_s64(
- veorq_s64(vreinterpretq_s64_m128d(a), vreinterpretq_s64_m128d(b)));
+ return vreinterpret_m64_s16(
+ vmax_s16(vreinterpret_s16_m64(a), vreinterpret_s16_m64(b)));
}
-// Compute the bitwise OR of packed double-precision (64-bit) floating-point
-// elements in a and b, and store the results in dst.
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=mm_or_pd
-FORCE_INLINE __m128d _mm_or_pd(__m128d a, __m128d b)
+// Computes the maximums of the four single-precision, floating-point values of
+// a and b.
+// https://msdn.microsoft.com/en-us/library/vstudio/ff5d607a(v=vs.100).aspx
+FORCE_INLINE __m128 _mm_max_ps(__m128 a, __m128 b)
{
- return vreinterpretq_m128d_s64(
- vorrq_s64(vreinterpretq_s64_m128d(a), vreinterpretq_s64_m128d(b)));
+#if SSE2NEON_PRECISE_MINMAX
+ float32x4_t _a = vreinterpretq_f32_m128(a);
+ float32x4_t _b = vreinterpretq_f32_m128(b);
+ return vbslq_f32(vcltq_f32(_b, _a), _a, _b);
+#else
+ return vreinterpretq_m128_f32(
+ vmaxq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b)));
+#endif
}
-// Computes the bitwise OR of the 128-bit value in a and the 128-bit value in b.
+// Compare packed unsigned 8-bit integers in a and b, and store packed maximum
+// values in dst.
//
-// r := a | b
+// FOR j := 0 to 7
+// i := j*8
+// dst[i+7:i] := MAX(a[i+7:i], b[i+7:i])
+// ENDFOR
//
-// https://msdn.microsoft.com/en-us/library/vstudio/ew8ty0db(v=vs.100).aspx
-FORCE_INLINE __m128i _mm_or_si128(__m128i a, __m128i b)
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_max_pu8
+FORCE_INLINE __m64 _mm_max_pu8(__m64 a, __m64 b)
{
- return vreinterpretq_m128i_s32(
- vorrq_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(b)));
+ return vreinterpret_m64_u8(
+ vmax_u8(vreinterpret_u8_m64(a), vreinterpret_u8_m64(b)));
}
-// Computes the bitwise XOR of the 128-bit value in a and the 128-bit value in
-// b. https://msdn.microsoft.com/en-us/library/fzt08www(v=vs.100).aspx
-FORCE_INLINE __m128i _mm_xor_si128(__m128i a, __m128i b)
+// Computes the maximum of the two lower scalar single-precision floating point
+// values of a and b.
+// https://msdn.microsoft.com/en-us/library/s6db5esz(v=vs.100).aspx
+FORCE_INLINE __m128 _mm_max_ss(__m128 a, __m128 b)
{
- return vreinterpretq_m128i_s32(
- veorq_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(b)));
+ float32_t value = vgetq_lane_f32(_mm_max_ps(a, b), 0);
+ return vreinterpretq_m128_f32(
+ vsetq_lane_f32(value, vreinterpretq_f32_m128(a), 0));
}
-// Duplicate the low double-precision (64-bit) floating-point element from a,
-// and store the results in dst.
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_movedup_pd
-FORCE_INLINE __m128d _mm_movedup_pd(__m128d a)
+// Compare packed signed 16-bit integers in a and b, and store packed minimum
+// values in dst.
+//
+// FOR j := 0 to 3
+// i := j*16
+// dst[i+15:i] := MIN(a[i+15:i], b[i+15:i])
+// ENDFOR
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_min_pi16
+FORCE_INLINE __m64 _mm_min_pi16(__m64 a, __m64 b)
{
-#if (__aarch64__)
- return vreinterpretq_m128d_f64(
- vdupq_laneq_f64(vreinterpretq_f64_m128d(a), 0));
-#else
- return vreinterpretq_m128d_u64(
- vdupq_n_u64(vgetq_lane_u64(vreinterpretq_u64_m128d(a), 0)));
-#endif
+ return vreinterpret_m64_s16(
+ vmin_s16(vreinterpret_s16_m64(a), vreinterpret_s16_m64(b)));
}
-// Duplicate odd-indexed single-precision (32-bit) floating-point elements
-// from a, and store the results in dst.
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_movehdup_ps
-FORCE_INLINE __m128 _mm_movehdup_ps(__m128 a)
+// Computes the minima of the four single-precision, floating-point values of a
+// and b.
+// https://msdn.microsoft.com/en-us/library/vstudio/wh13kadz(v=vs.100).aspx
+FORCE_INLINE __m128 _mm_min_ps(__m128 a, __m128 b)
{
-#if __has_builtin(__builtin_shufflevector)
- return vreinterpretq_m128_f32(__builtin_shufflevector(
- vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(a), 1, 1, 3, 3));
+#if SSE2NEON_PRECISE_MINMAX
+ float32x4_t _a = vreinterpretq_f32_m128(a);
+ float32x4_t _b = vreinterpretq_f32_m128(b);
+ return vbslq_f32(vcltq_f32(_a, _b), _a, _b);
#else
- float32_t a1 = vgetq_lane_f32(vreinterpretq_f32_m128(a), 1);
- float32_t a3 = vgetq_lane_f32(vreinterpretq_f32_m128(a), 3);
- float ALIGN_STRUCT(16) data[4] = {a1, a1, a3, a3};
- return vreinterpretq_m128_f32(vld1q_f32(data));
+ return vreinterpretq_m128_f32(
+ vminq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b)));
#endif
}
-// Duplicate even-indexed single-precision (32-bit) floating-point elements
-// from a, and store the results in dst.
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_moveldup_ps
-FORCE_INLINE __m128 _mm_moveldup_ps(__m128 a)
+// Compare packed unsigned 8-bit integers in a and b, and store packed minimum
+// values in dst.
+//
+// FOR j := 0 to 7
+// i := j*8
+// dst[i+7:i] := MIN(a[i+7:i], b[i+7:i])
+// ENDFOR
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_min_pu8
+FORCE_INLINE __m64 _mm_min_pu8(__m64 a, __m64 b)
{
-#if __has_builtin(__builtin_shufflevector)
- return vreinterpretq_m128_f32(__builtin_shufflevector(
- vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(a), 0, 0, 2, 2));
-#else
- float32_t a0 = vgetq_lane_f32(vreinterpretq_f32_m128(a), 0);
- float32_t a2 = vgetq_lane_f32(vreinterpretq_f32_m128(a), 2);
- float ALIGN_STRUCT(16) data[4] = {a0, a0, a2, a2};
- return vreinterpretq_m128_f32(vld1q_f32(data));
-#endif
+ return vreinterpret_m64_u8(
+ vmin_u8(vreinterpret_u8_m64(a), vreinterpret_u8_m64(b)));
+}
+
+// Computes the minimum of the two lower scalar single-precision floating point
+// values of a and b.
+// https://msdn.microsoft.com/en-us/library/0a9y7xaa(v=vs.100).aspx
+FORCE_INLINE __m128 _mm_min_ss(__m128 a, __m128 b)
+{
+ float32_t value = vgetq_lane_f32(_mm_min_ps(a, b), 0);
+ return vreinterpretq_m128_f32(
+ vsetq_lane_f32(value, vreinterpretq_f32_m128(a), 0));
+}
+
+// Sets the low word to the single-precision, floating-point value of b
+// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/35hdzazd(v=vs.100)
+FORCE_INLINE __m128 _mm_move_ss(__m128 a, __m128 b)
+{
+ return vreinterpretq_m128_f32(
+ vsetq_lane_f32(vgetq_lane_f32(vreinterpretq_f32_m128(b), 0),
+ vreinterpretq_f32_m128(a), 0));
}
// Moves the upper two values of B into the lower two values of A.
@@ -1577,315 +2093,419 @@ FORCE_INLINE __m128 _mm_movelh_ps(__m128 __A, __m128 __B)
return vreinterpretq_m128_f32(vcombine_f32(a10, b10));
}
-// Compute the absolute value of packed signed 32-bit integers in a, and store
-// the unsigned results in dst.
-//
-// FOR j := 0 to 3
-// i := j*32
-// dst[i+31:i] := ABS(a[i+31:i])
-// ENDFOR
-//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_abs_epi32
-FORCE_INLINE __m128i _mm_abs_epi32(__m128i a)
+// Create mask from the most significant bit of each 8-bit element in a, and
+// store the result in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_movemask_pi8
+FORCE_INLINE int _mm_movemask_pi8(__m64 a)
{
- return vreinterpretq_m128i_s32(vabsq_s32(vreinterpretq_s32_m128i(a)));
+ uint8x8_t input = vreinterpret_u8_m64(a);
+#if defined(__aarch64__)
+ static const int8x8_t shift = {0, 1, 2, 3, 4, 5, 6, 7};
+ uint8x8_t tmp = vshr_n_u8(input, 7);
+ return vaddv_u8(vshl_u8(tmp, shift));
+#else
+ // Refer the implementation of `_mm_movemask_epi8`
+ uint16x4_t high_bits = vreinterpret_u16_u8(vshr_n_u8(input, 7));
+ uint32x2_t paired16 =
+ vreinterpret_u32_u16(vsra_n_u16(high_bits, high_bits, 7));
+ uint8x8_t paired32 =
+ vreinterpret_u8_u32(vsra_n_u32(paired16, paired16, 14));
+ return vget_lane_u8(paired32, 0) | ((int) vget_lane_u8(paired32, 4) << 4);
+#endif
}
-// Compute the absolute value of packed signed 16-bit integers in a, and store
-// the unsigned results in dst.
-//
-// FOR j := 0 to 7
-// i := j*16
-// dst[i+15:i] := ABS(a[i+15:i])
-// ENDFOR
-//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_abs_epi16
-FORCE_INLINE __m128i _mm_abs_epi16(__m128i a)
+// NEON does not provide this method
+// Creates a 4-bit mask from the most significant bits of the four
+// single-precision, floating-point values.
+// https://msdn.microsoft.com/en-us/library/vstudio/4490ys29(v=vs.100).aspx
+FORCE_INLINE int _mm_movemask_ps(__m128 a)
{
- return vreinterpretq_m128i_s16(vabsq_s16(vreinterpretq_s16_m128i(a)));
+ uint32x4_t input = vreinterpretq_u32_m128(a);
+#if defined(__aarch64__)
+ static const int32x4_t shift = {0, 1, 2, 3};
+ uint32x4_t tmp = vshrq_n_u32(input, 31);
+ return vaddvq_u32(vshlq_u32(tmp, shift));
+#else
+ // Uses the exact same method as _mm_movemask_epi8, see that for details.
+ // Shift out everything but the sign bits with a 32-bit unsigned shift
+ // right.
+ uint64x2_t high_bits = vreinterpretq_u64_u32(vshrq_n_u32(input, 31));
+ // Merge the two pairs together with a 64-bit unsigned shift right + add.
+ uint8x16_t paired =
+ vreinterpretq_u8_u64(vsraq_n_u64(high_bits, high_bits, 31));
+ // Extract the result.
+ return vgetq_lane_u8(paired, 0) | (vgetq_lane_u8(paired, 8) << 2);
+#endif
}
-// Compute the absolute value of packed signed 8-bit integers in a, and store
-// the unsigned results in dst.
+// Multiplies the four single-precision, floating-point values of a and b.
//
-// FOR j := 0 to 15
-// i := j*8
-// dst[i+7:i] := ABS(a[i+7:i])
-// ENDFOR
+// r0 := a0 * b0
+// r1 := a1 * b1
+// r2 := a2 * b2
+// r3 := a3 * b3
//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_abs_epi8
-FORCE_INLINE __m128i _mm_abs_epi8(__m128i a)
+// https://msdn.microsoft.com/en-us/library/vstudio/22kbk6t9(v=vs.100).aspx
+FORCE_INLINE __m128 _mm_mul_ps(__m128 a, __m128 b)
{
- return vreinterpretq_m128i_s8(vabsq_s8(vreinterpretq_s8_m128i(a)));
+ return vreinterpretq_m128_f32(
+ vmulq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b)));
}
-// Compute the absolute value of packed signed 32-bit integers in a, and store
-// the unsigned results in dst.
+// Multiply the lower single-precision (32-bit) floating-point element in a and
+// b, store the result in the lower element of dst, and copy the upper 3 packed
+// elements from a to the upper elements of dst.
//
-// FOR j := 0 to 1
-// i := j*32
-// dst[i+31:i] := ABS(a[i+31:i])
-// ENDFOR
+// dst[31:0] := a[31:0] * b[31:0]
+// dst[127:32] := a[127:32]
//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_abs_pi32
-FORCE_INLINE __m64 _mm_abs_pi32(__m64 a)
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mul_ss
+FORCE_INLINE __m128 _mm_mul_ss(__m128 a, __m128 b)
{
- return vreinterpret_m64_s32(vabs_s32(vreinterpret_s32_m64(a)));
+ return _mm_move_ss(a, _mm_mul_ps(a, b));
}
-// Compute the absolute value of packed signed 16-bit integers in a, and store
-// the unsigned results in dst.
-//
-// FOR j := 0 to 3
-// i := j*16
-// dst[i+15:i] := ABS(a[i+15:i])
-// ENDFOR
-//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_abs_pi16
-FORCE_INLINE __m64 _mm_abs_pi16(__m64 a)
+// Multiply the packed unsigned 16-bit integers in a and b, producing
+// intermediate 32-bit integers, and store the high 16 bits of the intermediate
+// integers in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mulhi_pu16
+FORCE_INLINE __m64 _mm_mulhi_pu16(__m64 a, __m64 b)
{
- return vreinterpret_m64_s16(vabs_s16(vreinterpret_s16_m64(a)));
+ return vreinterpret_m64_u16(vshrn_n_u32(
+ vmull_u16(vreinterpret_u16_m64(a), vreinterpret_u16_m64(b)), 16));
}
-// Compute the absolute value of packed signed 8-bit integers in a, and store
-// the unsigned results in dst.
+// Computes the bitwise OR of the four single-precision, floating-point values
+// of a and b.
+// https://msdn.microsoft.com/en-us/library/vstudio/7ctdsyy0(v=vs.100).aspx
+FORCE_INLINE __m128 _mm_or_ps(__m128 a, __m128 b)
+{
+ return vreinterpretq_m128_s32(
+ vorrq_s32(vreinterpretq_s32_m128(a), vreinterpretq_s32_m128(b)));
+}
+
+// Average packed unsigned 8-bit integers in a and b, and store the results in
+// dst.
//
// FOR j := 0 to 7
// i := j*8
-// dst[i+7:i] := ABS(a[i+7:i])
+// dst[i+7:i] := (a[i+7:i] + b[i+7:i] + 1) >> 1
// ENDFOR
//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_abs_pi8
-FORCE_INLINE __m64 _mm_abs_pi8(__m64 a)
-{
- return vreinterpret_m64_s8(vabs_s8(vreinterpret_s8_m64(a)));
-}
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_m_pavgb
+#define _m_pavgb(a, b) _mm_avg_pu8(a, b)
-// Concatenate 16-byte blocks in a and b into a 32-byte temporary result, shift
-// the result right by imm8 bytes, and store the low 16 bytes in dst.
+// Average packed unsigned 16-bit integers in a and b, and store the results in
+// dst.
//
-// tmp[255:0] := ((a[127:0] << 128)[255:0] OR b[127:0]) >> (imm8*8)
-// dst[127:0] := tmp[127:0]
+// FOR j := 0 to 3
+// i := j*16
+// dst[i+15:i] := (a[i+15:i] + b[i+15:i] + 1) >> 1
+// ENDFOR
//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_alignr_epi8
-#define _mm_alignr_epi8(a, b, imm) \
- __extension__({ \
- __m128i ret; \
- if (unlikely((imm) >= 32)) { \
- ret = _mm_setzero_si128(); \
- } else { \
- uint8x16_t tmp_low, tmp_high; \
- if (imm >= 16) { \
- const int idx = imm - 16; \
- tmp_low = vreinterpretq_u8_m128i(a); \
- tmp_high = vdupq_n_u8(0); \
- ret = \
- vreinterpretq_m128i_u8(vextq_u8(tmp_low, tmp_high, idx)); \
- } else { \
- const int idx = imm; \
- tmp_low = vreinterpretq_u8_m128i(b); \
- tmp_high = vreinterpretq_u8_m128i(a); \
- ret = \
- vreinterpretq_m128i_u8(vextq_u8(tmp_low, tmp_high, idx)); \
- } \
- } \
- ret; \
- })
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_m_pavgw
+#define _m_pavgw(a, b) _mm_avg_pu16(a, b)
-// Concatenate 8-byte blocks in a and b into a 16-byte temporary result, shift
-// the result right by imm8 bytes, and store the low 8 bytes in dst.
-//
-// tmp[127:0] := ((a[63:0] << 64)[127:0] OR b[63:0]) >> (imm8*8)
-// dst[63:0] := tmp[63:0]
-//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_alignr_pi8
-#define _mm_alignr_pi8(a, b, imm) \
- __extension__({ \
- __m64 ret; \
- if (unlikely((imm) >= 16)) { \
- ret = vreinterpret_m64_s8(vdup_n_s8(0)); \
- } else { \
- uint8x8_t tmp_low, tmp_high; \
- if (imm >= 8) { \
- const int idx = imm - 8; \
- tmp_low = vreinterpret_u8_m64(a); \
- tmp_high = vdup_n_u8(0); \
- ret = vreinterpret_m64_u8(vext_u8(tmp_low, tmp_high, idx)); \
- } else { \
- const int idx = imm; \
- tmp_low = vreinterpret_u8_m64(b); \
- tmp_high = vreinterpret_u8_m64(a); \
- ret = vreinterpret_m64_u8(vext_u8(tmp_low, tmp_high, idx)); \
- } \
- } \
- ret; \
- })
+// Extract a 16-bit integer from a, selected with imm8, and store the result in
+// the lower element of dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_m_pextrw
+#define _m_pextrw(a, imm) _mm_extract_pi16(a, imm)
-// Takes the upper 64 bits of a and places it in the low end of the result
-// Takes the lower 64 bits of b and places it into the high end of the result.
-FORCE_INLINE __m128 _mm_shuffle_ps_1032(__m128 a, __m128 b)
-{
- float32x2_t a32 = vget_high_f32(vreinterpretq_f32_m128(a));
- float32x2_t b10 = vget_low_f32(vreinterpretq_f32_m128(b));
- return vreinterpretq_m128_f32(vcombine_f32(a32, b10));
-}
+// Copy a to dst, and insert the 16-bit integer i into dst at the location
+// specified by imm8.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=m_pinsrw
+#define _m_pinsrw(a, i, imm) _mm_insert_pi16(a, i, imm)
-// takes the lower two 32-bit values from a and swaps them and places in high
-// end of result takes the higher two 32 bit values from b and swaps them and
-// places in low end of result.
-FORCE_INLINE __m128 _mm_shuffle_ps_2301(__m128 a, __m128 b)
+// Compare packed signed 16-bit integers in a and b, and store packed maximum
+// values in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_m_pmaxsw
+#define _m_pmaxsw(a, b) _mm_max_pi16(a, b)
+
+// Compare packed unsigned 8-bit integers in a and b, and store packed maximum
+// values in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_m_pmaxub
+#define _m_pmaxub(a, b) _mm_max_pu8(a, b)
+
+// Compare packed signed 16-bit integers in a and b, and store packed minimum
+// values in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_m_pminsw
+#define _m_pminsw(a, b) _mm_min_pi16(a, b)
+
+// Compare packed unsigned 8-bit integers in a and b, and store packed minimum
+// values in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_m_pminub
+#define _m_pminub(a, b) _mm_min_pu8(a, b)
+
+// Create mask from the most significant bit of each 8-bit element in a, and
+// store the result in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_m_pmovmskb
+#define _m_pmovmskb(a) _mm_movemask_pi8(a)
+
+// Multiply the packed unsigned 16-bit integers in a and b, producing
+// intermediate 32-bit integers, and store the high 16 bits of the intermediate
+// integers in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_m_pmulhuw
+#define _m_pmulhuw(a, b) _mm_mulhi_pu16(a, b)
+
+// Loads one cache line of data from address p to a location closer to the
+// processor. https://msdn.microsoft.com/en-us/library/84szxsww(v=vs.100).aspx
+FORCE_INLINE void _mm_prefetch(const void *p, int i)
{
- float32x2_t a01 = vrev64_f32(vget_low_f32(vreinterpretq_f32_m128(a)));
- float32x2_t b23 = vrev64_f32(vget_high_f32(vreinterpretq_f32_m128(b)));
- return vreinterpretq_m128_f32(vcombine_f32(a01, b23));
+ (void) i;
+ __builtin_prefetch(p);
}
-FORCE_INLINE __m128 _mm_shuffle_ps_0321(__m128 a, __m128 b)
+// Compute the absolute differences of packed unsigned 8-bit integers in a and
+// b, then horizontally sum each consecutive 8 differences to produce four
+// unsigned 16-bit integers, and pack these unsigned 16-bit integers in the low
+// 16 bits of dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=m_psadbw
+#define _m_psadbw(a, b) _mm_sad_pu8(a, b)
+
+// Shuffle 16-bit integers in a using the control in imm8, and store the results
+// in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_m_pshufw
+#define _m_pshufw(a, imm) _mm_shuffle_pi16(a, imm)
+
+// Compute the approximate reciprocal of packed single-precision (32-bit)
+// floating-point elements in a, and store the results in dst. The maximum
+// relative error for this approximation is less than 1.5*2^-12.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_rcp_ps
+FORCE_INLINE __m128 _mm_rcp_ps(__m128 in)
{
- float32x2_t a21 = vget_high_f32(
- vextq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(a), 3));
- float32x2_t b03 = vget_low_f32(
- vextq_f32(vreinterpretq_f32_m128(b), vreinterpretq_f32_m128(b), 3));
- return vreinterpretq_m128_f32(vcombine_f32(a21, b03));
+ float32x4_t recip = vrecpeq_f32(vreinterpretq_f32_m128(in));
+ recip = vmulq_f32(recip, vrecpsq_f32(recip, vreinterpretq_f32_m128(in)));
+#if SSE2NEON_PRECISE_DIV
+ // Additional Netwon-Raphson iteration for accuracy
+ recip = vmulq_f32(recip, vrecpsq_f32(recip, vreinterpretq_f32_m128(in)));
+#endif
+ return vreinterpretq_m128_f32(recip);
}
-FORCE_INLINE __m128 _mm_shuffle_ps_2103(__m128 a, __m128 b)
+// Compute the approximate reciprocal of the lower single-precision (32-bit)
+// floating-point element in a, store the result in the lower element of dst,
+// and copy the upper 3 packed elements from a to the upper elements of dst. The
+// maximum relative error for this approximation is less than 1.5*2^-12.
+//
+// dst[31:0] := (1.0 / a[31:0])
+// dst[127:32] := a[127:32]
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_rcp_ss
+FORCE_INLINE __m128 _mm_rcp_ss(__m128 a)
{
- float32x2_t a03 = vget_low_f32(
- vextq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(a), 3));
- float32x2_t b21 = vget_high_f32(
- vextq_f32(vreinterpretq_f32_m128(b), vreinterpretq_f32_m128(b), 3));
- return vreinterpretq_m128_f32(vcombine_f32(a03, b21));
+ return _mm_move_ss(a, _mm_rcp_ps(a));
}
-FORCE_INLINE __m128 _mm_shuffle_ps_1010(__m128 a, __m128 b)
+// Computes the approximations of the reciprocal square roots of the four
+// single-precision floating point values of in.
+// The current precision is 1% error.
+// https://msdn.microsoft.com/en-us/library/22hfsh53(v=vs.100).aspx
+FORCE_INLINE __m128 _mm_rsqrt_ps(__m128 in)
{
- float32x2_t a10 = vget_low_f32(vreinterpretq_f32_m128(a));
- float32x2_t b10 = vget_low_f32(vreinterpretq_f32_m128(b));
- return vreinterpretq_m128_f32(vcombine_f32(a10, b10));
+ float32x4_t out = vrsqrteq_f32(vreinterpretq_f32_m128(in));
+#if SSE2NEON_PRECISE_SQRT
+ // Additional Netwon-Raphson iteration for accuracy
+ out = vmulq_f32(
+ out, vrsqrtsq_f32(vmulq_f32(vreinterpretq_f32_m128(in), out), out));
+ out = vmulq_f32(
+ out, vrsqrtsq_f32(vmulq_f32(vreinterpretq_f32_m128(in), out), out));
+#endif
+ return vreinterpretq_m128_f32(out);
}
-FORCE_INLINE __m128 _mm_shuffle_ps_1001(__m128 a, __m128 b)
+// Compute the approximate reciprocal square root of the lower single-precision
+// (32-bit) floating-point element in a, store the result in the lower element
+// of dst, and copy the upper 3 packed elements from a to the upper elements of
+// dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_rsqrt_ss
+FORCE_INLINE __m128 _mm_rsqrt_ss(__m128 in)
{
- float32x2_t a01 = vrev64_f32(vget_low_f32(vreinterpretq_f32_m128(a)));
- float32x2_t b10 = vget_low_f32(vreinterpretq_f32_m128(b));
- return vreinterpretq_m128_f32(vcombine_f32(a01, b10));
+ return vsetq_lane_f32(vgetq_lane_f32(_mm_rsqrt_ps(in), 0), in, 0);
}
-FORCE_INLINE __m128 _mm_shuffle_ps_0101(__m128 a, __m128 b)
+// Compute the absolute differences of packed unsigned 8-bit integers in a and
+// b, then horizontally sum each consecutive 8 differences to produce four
+// unsigned 16-bit integers, and pack these unsigned 16-bit integers in the low
+// 16 bits of dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_sad_pu8
+FORCE_INLINE __m64 _mm_sad_pu8(__m64 a, __m64 b)
{
- float32x2_t a01 = vrev64_f32(vget_low_f32(vreinterpretq_f32_m128(a)));
- float32x2_t b01 = vrev64_f32(vget_low_f32(vreinterpretq_f32_m128(b)));
- return vreinterpretq_m128_f32(vcombine_f32(a01, b01));
+ uint64x1_t t = vpaddl_u32(vpaddl_u16(
+ vpaddl_u8(vabd_u8(vreinterpret_u8_m64(a), vreinterpret_u8_m64(b)))));
+ return vreinterpret_m64_u16(
+ vset_lane_u16(vget_lane_u64(t, 0), vdup_n_u16(0), 0));
}
-// keeps the low 64 bits of b in the low and puts the high 64 bits of a in the
-// high
-FORCE_INLINE __m128 _mm_shuffle_ps_3210(__m128 a, __m128 b)
+// Macro: Set the flush zero bits of the MXCSR control and status register to
+// the value in unsigned 32-bit integer a. The flush zero may contain any of the
+// following flags: _MM_FLUSH_ZERO_ON or _MM_FLUSH_ZERO_OFF
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_MM_SET_FLUSH_ZERO_MODE
+FORCE_INLINE void _sse2neon_mm_set_flush_zero_mode(unsigned int flag)
{
- float32x2_t a10 = vget_low_f32(vreinterpretq_f32_m128(a));
- float32x2_t b32 = vget_high_f32(vreinterpretq_f32_m128(b));
- return vreinterpretq_m128_f32(vcombine_f32(a10, b32));
+ // AArch32 Advanced SIMD arithmetic always uses the Flush-to-zero setting,
+ // regardless of the value of the FZ bit.
+ union {
+ fpcr_bitfield field;
+#if defined(__aarch64__)
+ uint64_t value;
+#else
+ uint32_t value;
+#endif
+ } r;
+
+#if defined(__aarch64__)
+ asm volatile("mrs %0, FPCR" : "=r"(r.value)); /* read */
+#else
+ asm volatile("vmrs %0, FPSCR" : "=r"(r.value)); /* read */
+#endif
+
+ r.field.bit24 = (flag & _MM_FLUSH_ZERO_MASK) == _MM_FLUSH_ZERO_ON;
+
+#if defined(__aarch64__)
+ asm volatile("msr FPCR, %0" ::"r"(r)); /* write */
+#else
+ asm volatile("vmsr FPSCR, %0" ::"r"(r)); /* write */
+#endif
}
-FORCE_INLINE __m128 _mm_shuffle_ps_0011(__m128 a, __m128 b)
+// Sets the four single-precision, floating-point values to the four inputs.
+// https://msdn.microsoft.com/en-us/library/vstudio/afh0zf75(v=vs.100).aspx
+FORCE_INLINE __m128 _mm_set_ps(float w, float z, float y, float x)
{
- float32x2_t a11 = vdup_lane_f32(vget_low_f32(vreinterpretq_f32_m128(a)), 1);
- float32x2_t b00 = vdup_lane_f32(vget_low_f32(vreinterpretq_f32_m128(b)), 0);
- return vreinterpretq_m128_f32(vcombine_f32(a11, b00));
+ float ALIGN_STRUCT(16) data[4] = {x, y, z, w};
+ return vreinterpretq_m128_f32(vld1q_f32(data));
}
-FORCE_INLINE __m128 _mm_shuffle_ps_0022(__m128 a, __m128 b)
+// Sets the four single-precision, floating-point values to w.
+// https://msdn.microsoft.com/en-us/library/vstudio/2x1se8ha(v=vs.100).aspx
+FORCE_INLINE __m128 _mm_set_ps1(float _w)
{
- float32x2_t a22 =
- vdup_lane_f32(vget_high_f32(vreinterpretq_f32_m128(a)), 0);
- float32x2_t b00 = vdup_lane_f32(vget_low_f32(vreinterpretq_f32_m128(b)), 0);
- return vreinterpretq_m128_f32(vcombine_f32(a22, b00));
+ return vreinterpretq_m128_f32(vdupq_n_f32(_w));
}
-FORCE_INLINE __m128 _mm_shuffle_ps_2200(__m128 a, __m128 b)
+// Macro: Set the rounding mode bits of the MXCSR control and status register to
+// the value in unsigned 32-bit integer a. The rounding mode may contain any of
+// the following flags: _MM_ROUND_NEAREST, _MM_ROUND_DOWN, _MM_ROUND_UP,
+// _MM_ROUND_TOWARD_ZERO
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_MM_SET_ROUNDING_MODE
+FORCE_INLINE void _MM_SET_ROUNDING_MODE(int rounding)
{
- float32x2_t a00 = vdup_lane_f32(vget_low_f32(vreinterpretq_f32_m128(a)), 0);
- float32x2_t b22 =
- vdup_lane_f32(vget_high_f32(vreinterpretq_f32_m128(b)), 0);
- return vreinterpretq_m128_f32(vcombine_f32(a00, b22));
+ union {
+ fpcr_bitfield field;
+#if defined(__aarch64__)
+ uint64_t value;
+#else
+ uint32_t value;
+#endif
+ } r;
+
+#if defined(__aarch64__)
+ asm volatile("mrs %0, FPCR" : "=r"(r.value)); /* read */
+#else
+ asm volatile("vmrs %0, FPSCR" : "=r"(r.value)); /* read */
+#endif
+
+ switch (rounding) {
+ case _MM_ROUND_TOWARD_ZERO:
+ r.field.bit22 = 1;
+ r.field.bit23 = 1;
+ break;
+ case _MM_ROUND_DOWN:
+ r.field.bit22 = 0;
+ r.field.bit23 = 1;
+ break;
+ case _MM_ROUND_UP:
+ r.field.bit22 = 1;
+ r.field.bit23 = 0;
+ break;
+ default: //_MM_ROUND_NEAREST
+ r.field.bit22 = 0;
+ r.field.bit23 = 0;
+ }
+
+#if defined(__aarch64__)
+ asm volatile("msr FPCR, %0" ::"r"(r)); /* write */
+#else
+ asm volatile("vmsr FPSCR, %0" ::"r"(r)); /* write */
+#endif
}
-FORCE_INLINE __m128 _mm_shuffle_ps_3202(__m128 a, __m128 b)
+// Copy single-precision (32-bit) floating-point element a to the lower element
+// of dst, and zero the upper 3 elements.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_set_ss
+FORCE_INLINE __m128 _mm_set_ss(float a)
{
- float32_t a0 = vgetq_lane_f32(vreinterpretq_f32_m128(a), 0);
- float32x2_t a22 =
- vdup_lane_f32(vget_high_f32(vreinterpretq_f32_m128(a)), 0);
- float32x2_t a02 = vset_lane_f32(a0, a22, 1); /* TODO: use vzip ?*/
- float32x2_t b32 = vget_high_f32(vreinterpretq_f32_m128(b));
- return vreinterpretq_m128_f32(vcombine_f32(a02, b32));
+ float ALIGN_STRUCT(16) data[4] = {a, 0, 0, 0};
+ return vreinterpretq_m128_f32(vld1q_f32(data));
}
-FORCE_INLINE __m128 _mm_shuffle_ps_1133(__m128 a, __m128 b)
+// Sets the four single-precision, floating-point values to w.
+//
+// r0 := r1 := r2 := r3 := w
+//
+// https://msdn.microsoft.com/en-us/library/vstudio/2x1se8ha(v=vs.100).aspx
+FORCE_INLINE __m128 _mm_set1_ps(float _w)
{
- float32x2_t a33 =
- vdup_lane_f32(vget_high_f32(vreinterpretq_f32_m128(a)), 1);
- float32x2_t b11 = vdup_lane_f32(vget_low_f32(vreinterpretq_f32_m128(b)), 1);
- return vreinterpretq_m128_f32(vcombine_f32(a33, b11));
+ return vreinterpretq_m128_f32(vdupq_n_f32(_w));
}
-FORCE_INLINE __m128 _mm_shuffle_ps_2010(__m128 a, __m128 b)
+FORCE_INLINE void _mm_setcsr(unsigned int a)
{
- float32x2_t a10 = vget_low_f32(vreinterpretq_f32_m128(a));
- float32_t b2 = vgetq_lane_f32(vreinterpretq_f32_m128(b), 2);
- float32x2_t b00 = vdup_lane_f32(vget_low_f32(vreinterpretq_f32_m128(b)), 0);
- float32x2_t b20 = vset_lane_f32(b2, b00, 1);
- return vreinterpretq_m128_f32(vcombine_f32(a10, b20));
+ _MM_SET_ROUNDING_MODE(a);
}
-FORCE_INLINE __m128 _mm_shuffle_ps_2001(__m128 a, __m128 b)
+// Sets the four single-precision, floating-point values to the four inputs in
+// reverse order.
+// https://msdn.microsoft.com/en-us/library/vstudio/d2172ct3(v=vs.100).aspx
+FORCE_INLINE __m128 _mm_setr_ps(float w, float z, float y, float x)
{
- float32x2_t a01 = vrev64_f32(vget_low_f32(vreinterpretq_f32_m128(a)));
- float32_t b2 = vgetq_lane_f32(b, 2);
- float32x2_t b00 = vdup_lane_f32(vget_low_f32(vreinterpretq_f32_m128(b)), 0);
- float32x2_t b20 = vset_lane_f32(b2, b00, 1);
- return vreinterpretq_m128_f32(vcombine_f32(a01, b20));
+ float ALIGN_STRUCT(16) data[4] = {w, z, y, x};
+ return vreinterpretq_m128_f32(vld1q_f32(data));
}
-FORCE_INLINE __m128 _mm_shuffle_ps_2032(__m128 a, __m128 b)
+// Clears the four single-precision, floating-point values.
+// https://msdn.microsoft.com/en-us/library/vstudio/tk1t2tbz(v=vs.100).aspx
+FORCE_INLINE __m128 _mm_setzero_ps(void)
{
- float32x2_t a32 = vget_high_f32(vreinterpretq_f32_m128(a));
- float32_t b2 = vgetq_lane_f32(b, 2);
- float32x2_t b00 = vdup_lane_f32(vget_low_f32(vreinterpretq_f32_m128(b)), 0);
- float32x2_t b20 = vset_lane_f32(b2, b00, 1);
- return vreinterpretq_m128_f32(vcombine_f32(a32, b20));
+ return vreinterpretq_m128_f32(vdupq_n_f32(0));
}
-// NEON does not support a general purpose permute intrinsic
-// Selects four specific single-precision, floating-point values from a and b,
-// based on the mask i.
-//
-// C equivalent:
-// __m128 _mm_shuffle_ps_default(__m128 a, __m128 b,
-// __constrange(0, 255) int imm) {
-// __m128 ret;
-// ret[0] = a[imm & 0x3]; ret[1] = a[(imm >> 2) & 0x3];
-// ret[2] = b[(imm >> 4) & 0x03]; ret[3] = b[(imm >> 6) & 0x03];
-// return ret;
-// }
-//
-// https://msdn.microsoft.com/en-us/library/vstudio/5f0858x0(v=vs.100).aspx
-#define _mm_shuffle_ps_default(a, b, imm) \
+// Shuffle 16-bit integers in a using the control in imm8, and store the results
+// in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_shuffle_pi16
+#if __has_builtin(__builtin_shufflevector)
+#define _mm_shuffle_pi16(a, imm) \
__extension__({ \
- float32x4_t ret; \
- ret = vmovq_n_f32( \
- vgetq_lane_f32(vreinterpretq_f32_m128(a), (imm) & (0x3))); \
- ret = vsetq_lane_f32( \
- vgetq_lane_f32(vreinterpretq_f32_m128(a), ((imm) >> 2) & 0x3), \
- ret, 1); \
- ret = vsetq_lane_f32( \
- vgetq_lane_f32(vreinterpretq_f32_m128(b), ((imm) >> 4) & 0x3), \
- ret, 2); \
- ret = vsetq_lane_f32( \
- vgetq_lane_f32(vreinterpretq_f32_m128(b), ((imm) >> 6) & 0x3), \
- ret, 3); \
- vreinterpretq_m128_f32(ret); \
+ vreinterpret_m64_s16(__builtin_shufflevector( \
+ vreinterpret_s16_m64(a), vreinterpret_s16_m64(a), (imm & 0x3), \
+ ((imm >> 2) & 0x3), ((imm >> 4) & 0x3), ((imm >> 6) & 0x3))); \
})
+#else
+#define _mm_shuffle_pi16(a, imm) \
+ __extension__({ \
+ int16x4_t ret; \
+ ret = \
+ vmov_n_s16(vget_lane_s16(vreinterpret_s16_m64(a), (imm) & (0x3))); \
+ ret = vset_lane_s16( \
+ vget_lane_s16(vreinterpret_s16_m64(a), ((imm) >> 2) & 0x3), ret, \
+ 1); \
+ ret = vset_lane_s16( \
+ vget_lane_s16(vreinterpret_s16_m64(a), ((imm) >> 4) & 0x3), ret, \
+ 2); \
+ ret = vset_lane_s16( \
+ vget_lane_s16(vreinterpret_s16_m64(a), ((imm) >> 6) & 0x3), ret, \
+ 3); \
+ vreinterpret_m64_s16(ret); \
+ })
+#endif
+
+// Guarantees that every preceding store is globally visible before any
+// subsequent store.
+// https://msdn.microsoft.com/en-us/library/5h2w73d1%28v=vs.90%29.aspx
+FORCE_INLINE void _mm_sfence(void)
+{
+ __sync_synchronize();
+}
// FORCE_INLINE __m128 _mm_shuffle_ps(__m128 a, __m128 b, __constrange(0,255)
// int imm)
@@ -1963,1876 +2583,1721 @@ FORCE_INLINE __m128 _mm_shuffle_ps_2032(__m128 a, __m128 b)
})
#endif
-// Takes the upper 64 bits of a and places it in the low end of the result
-// Takes the lower 64 bits of a and places it into the high end of the result.
-FORCE_INLINE __m128i _mm_shuffle_epi_1032(__m128i a)
+// Computes the approximations of square roots of the four single-precision,
+// floating-point values of a. First computes reciprocal square roots and then
+// reciprocals of the four values.
+//
+// r0 := sqrt(a0)
+// r1 := sqrt(a1)
+// r2 := sqrt(a2)
+// r3 := sqrt(a3)
+//
+// https://msdn.microsoft.com/en-us/library/vstudio/8z67bwwk(v=vs.100).aspx
+FORCE_INLINE __m128 _mm_sqrt_ps(__m128 in)
{
- int32x2_t a32 = vget_high_s32(vreinterpretq_s32_m128i(a));
- int32x2_t a10 = vget_low_s32(vreinterpretq_s32_m128i(a));
- return vreinterpretq_m128i_s32(vcombine_s32(a32, a10));
+#if SSE2NEON_PRECISE_SQRT
+ float32x4_t recip = vrsqrteq_f32(vreinterpretq_f32_m128(in));
+
+ // Test for vrsqrteq_f32(0) -> positive infinity case.
+ // Change to zero, so that s * 1/sqrt(s) result is zero too.
+ const uint32x4_t pos_inf = vdupq_n_u32(0x7F800000);
+ const uint32x4_t div_by_zero =
+ vceqq_u32(pos_inf, vreinterpretq_u32_f32(recip));
+ recip = vreinterpretq_f32_u32(
+ vandq_u32(vmvnq_u32(div_by_zero), vreinterpretq_u32_f32(recip)));
+
+ // Additional Netwon-Raphson iteration for accuracy
+ recip = vmulq_f32(
+ vrsqrtsq_f32(vmulq_f32(recip, recip), vreinterpretq_f32_m128(in)),
+ recip);
+ recip = vmulq_f32(
+ vrsqrtsq_f32(vmulq_f32(recip, recip), vreinterpretq_f32_m128(in)),
+ recip);
+
+ // sqrt(s) = s * 1/sqrt(s)
+ return vreinterpretq_m128_f32(vmulq_f32(vreinterpretq_f32_m128(in), recip));
+#elif defined(__aarch64__)
+ return vreinterpretq_m128_f32(vsqrtq_f32(vreinterpretq_f32_m128(in)));
+#else
+ float32x4_t recipsq = vrsqrteq_f32(vreinterpretq_f32_m128(in));
+ float32x4_t sq = vrecpeq_f32(recipsq);
+ return vreinterpretq_m128_f32(sq);
+#endif
}
-// takes the lower two 32-bit values from a and swaps them and places in low end
-// of result takes the higher two 32 bit values from a and swaps them and places
-// in high end of result.
-FORCE_INLINE __m128i _mm_shuffle_epi_2301(__m128i a)
+// Computes the approximation of the square root of the scalar single-precision
+// floating point value of in.
+// https://msdn.microsoft.com/en-us/library/ahfsc22d(v=vs.100).aspx
+FORCE_INLINE __m128 _mm_sqrt_ss(__m128 in)
{
- int32x2_t a01 = vrev64_s32(vget_low_s32(vreinterpretq_s32_m128i(a)));
- int32x2_t a23 = vrev64_s32(vget_high_s32(vreinterpretq_s32_m128i(a)));
- return vreinterpretq_m128i_s32(vcombine_s32(a01, a23));
+ float32_t value =
+ vgetq_lane_f32(vreinterpretq_f32_m128(_mm_sqrt_ps(in)), 0);
+ return vreinterpretq_m128_f32(
+ vsetq_lane_f32(value, vreinterpretq_f32_m128(in), 0));
}
-// rotates the least significant 32 bits into the most signficant 32 bits, and
-// shifts the rest down
-FORCE_INLINE __m128i _mm_shuffle_epi_0321(__m128i a)
+// Stores four single-precision, floating-point values.
+// https://msdn.microsoft.com/en-us/library/vstudio/s3h4ay6y(v=vs.100).aspx
+FORCE_INLINE void _mm_store_ps(float *p, __m128 a)
{
- return vreinterpretq_m128i_s32(
- vextq_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(a), 1));
+ vst1q_f32(p, vreinterpretq_f32_m128(a));
}
-// rotates the most significant 32 bits into the least signficant 32 bits, and
-// shifts the rest up
-FORCE_INLINE __m128i _mm_shuffle_epi_2103(__m128i a)
+// Store the lower single-precision (32-bit) floating-point element from a into
+// 4 contiguous elements in memory. mem_addr must be aligned on a 16-byte
+// boundary or a general-protection exception may be generated.
+//
+// MEM[mem_addr+31:mem_addr] := a[31:0]
+// MEM[mem_addr+63:mem_addr+32] := a[31:0]
+// MEM[mem_addr+95:mem_addr+64] := a[31:0]
+// MEM[mem_addr+127:mem_addr+96] := a[31:0]
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_store_ps1
+FORCE_INLINE void _mm_store_ps1(float *p, __m128 a)
{
- return vreinterpretq_m128i_s32(
- vextq_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(a), 3));
+ float32_t a0 = vgetq_lane_f32(vreinterpretq_f32_m128(a), 0);
+ vst1q_f32(p, vdupq_n_f32(a0));
}
-// gets the lower 64 bits of a, and places it in the upper 64 bits
-// gets the lower 64 bits of a and places it in the lower 64 bits
-FORCE_INLINE __m128i _mm_shuffle_epi_1010(__m128i a)
+// Stores the lower single - precision, floating - point value.
+// https://msdn.microsoft.com/en-us/library/tzz10fbx(v=vs.100).aspx
+FORCE_INLINE void _mm_store_ss(float *p, __m128 a)
{
- int32x2_t a10 = vget_low_s32(vreinterpretq_s32_m128i(a));
- return vreinterpretq_m128i_s32(vcombine_s32(a10, a10));
+ vst1q_lane_f32(p, vreinterpretq_f32_m128(a), 0);
}
-// gets the lower 64 bits of a, swaps the 0 and 1 elements, and places it in the
-// lower 64 bits gets the lower 64 bits of a, and places it in the upper 64 bits
-FORCE_INLINE __m128i _mm_shuffle_epi_1001(__m128i a)
+// Store the lower single-precision (32-bit) floating-point element from a into
+// 4 contiguous elements in memory. mem_addr must be aligned on a 16-byte
+// boundary or a general-protection exception may be generated.
+//
+// MEM[mem_addr+31:mem_addr] := a[31:0]
+// MEM[mem_addr+63:mem_addr+32] := a[31:0]
+// MEM[mem_addr+95:mem_addr+64] := a[31:0]
+// MEM[mem_addr+127:mem_addr+96] := a[31:0]
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_store1_ps
+#define _mm_store1_ps _mm_store_ps1
+
+// Stores the upper two single-precision, floating-point values of a to the
+// address p.
+//
+// *p0 := a2
+// *p1 := a3
+//
+// https://msdn.microsoft.com/en-us/library/a7525fs8(v%3dvs.90).aspx
+FORCE_INLINE void _mm_storeh_pi(__m64 *p, __m128 a)
{
- int32x2_t a01 = vrev64_s32(vget_low_s32(vreinterpretq_s32_m128i(a)));
- int32x2_t a10 = vget_low_s32(vreinterpretq_s32_m128i(a));
- return vreinterpretq_m128i_s32(vcombine_s32(a01, a10));
+ *p = vreinterpret_m64_f32(vget_high_f32(a));
}
-// gets the lower 64 bits of a, swaps the 0 and 1 elements and places it in the
-// upper 64 bits gets the lower 64 bits of a, swaps the 0 and 1 elements, and
-// places it in the lower 64 bits
-FORCE_INLINE __m128i _mm_shuffle_epi_0101(__m128i a)
+// Stores the lower two single-precision floating point values of a to the
+// address p.
+//
+// *p0 := a0
+// *p1 := a1
+//
+// https://msdn.microsoft.com/en-us/library/h54t98ks(v=vs.90).aspx
+FORCE_INLINE void _mm_storel_pi(__m64 *p, __m128 a)
{
- int32x2_t a01 = vrev64_s32(vget_low_s32(vreinterpretq_s32_m128i(a)));
- return vreinterpretq_m128i_s32(vcombine_s32(a01, a01));
+ *p = vreinterpret_m64_f32(vget_low_f32(a));
}
-FORCE_INLINE __m128i _mm_shuffle_epi_2211(__m128i a)
+// Store 4 single-precision (32-bit) floating-point elements from a into memory
+// in reverse order. mem_addr must be aligned on a 16-byte boundary or a
+// general-protection exception may be generated.
+//
+// MEM[mem_addr+31:mem_addr] := a[127:96]
+// MEM[mem_addr+63:mem_addr+32] := a[95:64]
+// MEM[mem_addr+95:mem_addr+64] := a[63:32]
+// MEM[mem_addr+127:mem_addr+96] := a[31:0]
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_storer_ps
+FORCE_INLINE void _mm_storer_ps(float *p, __m128 a)
{
- int32x2_t a11 = vdup_lane_s32(vget_low_s32(vreinterpretq_s32_m128i(a)), 1);
- int32x2_t a22 = vdup_lane_s32(vget_high_s32(vreinterpretq_s32_m128i(a)), 0);
- return vreinterpretq_m128i_s32(vcombine_s32(a11, a22));
+ float32x4_t tmp = vrev64q_f32(vreinterpretq_f32_m128(a));
+ float32x4_t rev = vextq_f32(tmp, tmp, 2);
+ vst1q_f32(p, rev);
}
-FORCE_INLINE __m128i _mm_shuffle_epi_0122(__m128i a)
+// Stores four single-precision, floating-point values.
+// https://msdn.microsoft.com/en-us/library/44e30x22(v=vs.100).aspx
+FORCE_INLINE void _mm_storeu_ps(float *p, __m128 a)
{
- int32x2_t a22 = vdup_lane_s32(vget_high_s32(vreinterpretq_s32_m128i(a)), 0);
- int32x2_t a01 = vrev64_s32(vget_low_s32(vreinterpretq_s32_m128i(a)));
- return vreinterpretq_m128i_s32(vcombine_s32(a22, a01));
+ vst1q_f32(p, vreinterpretq_f32_m128(a));
}
-FORCE_INLINE __m128i _mm_shuffle_epi_3332(__m128i a)
+// Stores 16-bits of integer data a at the address p.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_storeu_si16
+FORCE_INLINE void _mm_storeu_si16(void *p, __m128i a)
{
- int32x2_t a32 = vget_high_s32(vreinterpretq_s32_m128i(a));
- int32x2_t a33 = vdup_lane_s32(vget_high_s32(vreinterpretq_s32_m128i(a)), 1);
- return vreinterpretq_m128i_s32(vcombine_s32(a32, a33));
+ vst1q_lane_s16((int16_t *) p, vreinterpretq_s16_m128i(a), 0);
}
-// Shuffle packed 8-bit integers in a according to shuffle control mask in the
-// corresponding 8-bit element of b, and store the results in dst.
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_shuffle_epi8
-FORCE_INLINE __m128i _mm_shuffle_epi8(__m128i a, __m128i b)
+// Stores 64-bits of integer data a at the address p.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_storeu_si64
+FORCE_INLINE void _mm_storeu_si64(void *p, __m128i a)
{
- int8x16_t tbl = vreinterpretq_s8_m128i(a); // input a
- uint8x16_t idx = vreinterpretq_u8_m128i(b); // input b
- uint8x16_t idx_masked =
- vandq_u8(idx, vdupq_n_u8(0x8F)); // avoid using meaningless bits
-#if defined(__aarch64__)
- return vreinterpretq_m128i_s8(vqtbl1q_s8(tbl, idx_masked));
-#elif defined(__GNUC__)
- int8x16_t ret;
- // %e and %f represent the even and odd D registers
- // respectively.
- __asm__ __volatile__(
- "vtbl.8 %e[ret], {%e[tbl], %f[tbl]}, %e[idx]\n"
- "vtbl.8 %f[ret], {%e[tbl], %f[tbl]}, %f[idx]\n"
- : [ret] "=&w"(ret)
- : [tbl] "w"(tbl), [idx] "w"(idx_masked));
- return vreinterpretq_m128i_s8(ret);
-#else
- // use this line if testing on aarch64
- int8x8x2_t a_split = {vget_low_s8(tbl), vget_high_s8(tbl)};
- return vreinterpretq_m128i_s8(
- vcombine_s8(vtbl2_s8(a_split, vget_low_u8(idx_masked)),
- vtbl2_s8(a_split, vget_high_u8(idx_masked))));
-#endif
+ vst1q_lane_s64((int64_t *) p, vreinterpretq_s64_m128i(a), 0);
}
-// C equivalent:
-// __m128i _mm_shuffle_epi32_default(__m128i a,
-// __constrange(0, 255) int imm) {
-// __m128i ret;
-// ret[0] = a[imm & 0x3]; ret[1] = a[(imm >> 2) & 0x3];
-// ret[2] = a[(imm >> 4) & 0x03]; ret[3] = a[(imm >> 6) & 0x03];
-// return ret;
-// }
-#define _mm_shuffle_epi32_default(a, imm) \
- __extension__({ \
- int32x4_t ret; \
- ret = vmovq_n_s32( \
- vgetq_lane_s32(vreinterpretq_s32_m128i(a), (imm) & (0x3))); \
- ret = vsetq_lane_s32( \
- vgetq_lane_s32(vreinterpretq_s32_m128i(a), ((imm) >> 2) & 0x3), \
- ret, 1); \
- ret = vsetq_lane_s32( \
- vgetq_lane_s32(vreinterpretq_s32_m128i(a), ((imm) >> 4) & 0x3), \
- ret, 2); \
- ret = vsetq_lane_s32( \
- vgetq_lane_s32(vreinterpretq_s32_m128i(a), ((imm) >> 6) & 0x3), \
- ret, 3); \
- vreinterpretq_m128i_s32(ret); \
- })
+// Store 64-bits of integer data from a into memory using a non-temporal memory
+// hint.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_stream_pi
+FORCE_INLINE void _mm_stream_pi(__m64 *p, __m64 a)
+{
+ vst1_s64((int64_t *) p, vreinterpret_s64_m64(a));
+}
-// FORCE_INLINE __m128i _mm_shuffle_epi32_splat(__m128i a, __constrange(0,255)
-// int imm)
-#if defined(__aarch64__)
-#define _mm_shuffle_epi32_splat(a, imm) \
- __extension__({ \
- vreinterpretq_m128i_s32( \
- vdupq_laneq_s32(vreinterpretq_s32_m128i(a), (imm))); \
- })
+// Store 128-bits (composed of 4 packed single-precision (32-bit) floating-
+// point elements) from a into memory using a non-temporal memory hint.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_stream_ps
+FORCE_INLINE void _mm_stream_ps(float *p, __m128 a)
+{
+#if __has_builtin(__builtin_nontemporal_store)
+ __builtin_nontemporal_store(a, (float32x4_t *) p);
#else
-#define _mm_shuffle_epi32_splat(a, imm) \
- __extension__({ \
- vreinterpretq_m128i_s32( \
- vdupq_n_s32(vgetq_lane_s32(vreinterpretq_s32_m128i(a), (imm)))); \
- })
+ vst1q_f32(p, vreinterpretq_f32_m128(a));
#endif
+}
-// Shuffles the 4 signed or unsigned 32-bit integers in a as specified by imm.
-// https://msdn.microsoft.com/en-us/library/56f67xbk%28v=vs.90%29.aspx
-// FORCE_INLINE __m128i _mm_shuffle_epi32(__m128i a,
-// __constrange(0,255) int imm)
-#if __has_builtin(__builtin_shufflevector)
-#define _mm_shuffle_epi32(a, imm) \
- __extension__({ \
- int32x4_t _input = vreinterpretq_s32_m128i(a); \
- int32x4_t _shuf = __builtin_shufflevector( \
- _input, _input, (imm) & (0x3), ((imm) >> 2) & 0x3, \
- ((imm) >> 4) & 0x3, ((imm) >> 6) & 0x3); \
- vreinterpretq_m128i_s32(_shuf); \
- })
-#else // generic
-#define _mm_shuffle_epi32(a, imm) \
- __extension__({ \
- __m128i ret; \
- switch (imm) { \
- case _MM_SHUFFLE(1, 0, 3, 2): \
- ret = _mm_shuffle_epi_1032((a)); \
- break; \
- case _MM_SHUFFLE(2, 3, 0, 1): \
- ret = _mm_shuffle_epi_2301((a)); \
- break; \
- case _MM_SHUFFLE(0, 3, 2, 1): \
- ret = _mm_shuffle_epi_0321((a)); \
- break; \
- case _MM_SHUFFLE(2, 1, 0, 3): \
- ret = _mm_shuffle_epi_2103((a)); \
- break; \
- case _MM_SHUFFLE(1, 0, 1, 0): \
- ret = _mm_shuffle_epi_1010((a)); \
- break; \
- case _MM_SHUFFLE(1, 0, 0, 1): \
- ret = _mm_shuffle_epi_1001((a)); \
- break; \
- case _MM_SHUFFLE(0, 1, 0, 1): \
- ret = _mm_shuffle_epi_0101((a)); \
- break; \
- case _MM_SHUFFLE(2, 2, 1, 1): \
- ret = _mm_shuffle_epi_2211((a)); \
- break; \
- case _MM_SHUFFLE(0, 1, 2, 2): \
- ret = _mm_shuffle_epi_0122((a)); \
- break; \
- case _MM_SHUFFLE(3, 3, 3, 2): \
- ret = _mm_shuffle_epi_3332((a)); \
- break; \
- case _MM_SHUFFLE(0, 0, 0, 0): \
- ret = _mm_shuffle_epi32_splat((a), 0); \
- break; \
- case _MM_SHUFFLE(1, 1, 1, 1): \
- ret = _mm_shuffle_epi32_splat((a), 1); \
- break; \
- case _MM_SHUFFLE(2, 2, 2, 2): \
- ret = _mm_shuffle_epi32_splat((a), 2); \
- break; \
- case _MM_SHUFFLE(3, 3, 3, 3): \
- ret = _mm_shuffle_epi32_splat((a), 3); \
- break; \
- default: \
- ret = _mm_shuffle_epi32_default((a), (imm)); \
- break; \
- } \
- ret; \
- })
-#endif
+// Subtracts the four single-precision, floating-point values of a and b.
+//
+// r0 := a0 - b0
+// r1 := a1 - b1
+// r2 := a2 - b2
+// r3 := a3 - b3
+//
+// https://msdn.microsoft.com/en-us/library/vstudio/1zad2k61(v=vs.100).aspx
+FORCE_INLINE __m128 _mm_sub_ps(__m128 a, __m128 b)
+{
+ return vreinterpretq_m128_f32(
+ vsubq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b)));
+}
-// Shuffles the lower 4 signed or unsigned 16-bit integers in a as specified
-// by imm.
-// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/y41dkk37(v=vs.100)
-// FORCE_INLINE __m128i _mm_shufflelo_epi16_function(__m128i a,
-// __constrange(0,255) int
-// imm)
-#define _mm_shufflelo_epi16_function(a, imm) \
- __extension__({ \
- int16x8_t ret = vreinterpretq_s16_m128i(a); \
- int16x4_t lowBits = vget_low_s16(ret); \
- ret = vsetq_lane_s16(vget_lane_s16(lowBits, (imm) & (0x3)), ret, 0); \
- ret = vsetq_lane_s16(vget_lane_s16(lowBits, ((imm) >> 2) & 0x3), ret, \
- 1); \
- ret = vsetq_lane_s16(vget_lane_s16(lowBits, ((imm) >> 4) & 0x3), ret, \
- 2); \
- ret = vsetq_lane_s16(vget_lane_s16(lowBits, ((imm) >> 6) & 0x3), ret, \
- 3); \
- vreinterpretq_m128i_s16(ret); \
- })
+// Subtract the lower single-precision (32-bit) floating-point element in b from
+// the lower single-precision (32-bit) floating-point element in a, store the
+// result in the lower element of dst, and copy the upper 3 packed elements from
+// a to the upper elements of dst.
+//
+// dst[31:0] := a[31:0] - b[31:0]
+// dst[127:32] := a[127:32]
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_sub_ss
+FORCE_INLINE __m128 _mm_sub_ss(__m128 a, __m128 b)
+{
+ return _mm_move_ss(a, _mm_sub_ps(a, b));
+}
-// FORCE_INLINE __m128i _mm_shufflelo_epi16(__m128i a,
-// __constrange(0,255) int imm)
-#if __has_builtin(__builtin_shufflevector)
-#define _mm_shufflelo_epi16(a, imm) \
- __extension__({ \
- int16x8_t _input = vreinterpretq_s16_m128i(a); \
- int16x8_t _shuf = __builtin_shufflevector( \
- _input, _input, ((imm) & (0x3)), (((imm) >> 2) & 0x3), \
- (((imm) >> 4) & 0x3), (((imm) >> 6) & 0x3), 4, 5, 6, 7); \
- vreinterpretq_m128i_s16(_shuf); \
- })
-#else // generic
-#define _mm_shufflelo_epi16(a, imm) _mm_shufflelo_epi16_function((a), (imm))
-#endif
+// Macro: Transpose the 4x4 matrix formed by the 4 rows of single-precision
+// (32-bit) floating-point elements in row0, row1, row2, and row3, and store the
+// transposed matrix in these vectors (row0 now contains column 0, etc.).
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=MM_TRANSPOSE4_PS
+#define _MM_TRANSPOSE4_PS(row0, row1, row2, row3) \
+ do { \
+ float32x4x2_t ROW01 = vtrnq_f32(row0, row1); \
+ float32x4x2_t ROW23 = vtrnq_f32(row2, row3); \
+ row0 = vcombine_f32(vget_low_f32(ROW01.val[0]), \
+ vget_low_f32(ROW23.val[0])); \
+ row1 = vcombine_f32(vget_low_f32(ROW01.val[1]), \
+ vget_low_f32(ROW23.val[1])); \
+ row2 = vcombine_f32(vget_high_f32(ROW01.val[0]), \
+ vget_high_f32(ROW23.val[0])); \
+ row3 = vcombine_f32(vget_high_f32(ROW01.val[1]), \
+ vget_high_f32(ROW23.val[1])); \
+ } while (0)
-// Shuffles the upper 4 signed or unsigned 16-bit integers in a as specified
-// by imm.
-// https://msdn.microsoft.com/en-us/library/13ywktbs(v=vs.100).aspx
-// FORCE_INLINE __m128i _mm_shufflehi_epi16_function(__m128i a,
-// __constrange(0,255) int
-// imm)
-#define _mm_shufflehi_epi16_function(a, imm) \
- __extension__({ \
- int16x8_t ret = vreinterpretq_s16_m128i(a); \
- int16x4_t highBits = vget_high_s16(ret); \
- ret = vsetq_lane_s16(vget_lane_s16(highBits, (imm) & (0x3)), ret, 4); \
- ret = vsetq_lane_s16(vget_lane_s16(highBits, ((imm) >> 2) & 0x3), ret, \
- 5); \
- ret = vsetq_lane_s16(vget_lane_s16(highBits, ((imm) >> 4) & 0x3), ret, \
- 6); \
- ret = vsetq_lane_s16(vget_lane_s16(highBits, ((imm) >> 6) & 0x3), ret, \
- 7); \
- vreinterpretq_m128i_s16(ret); \
- })
+// according to the documentation, these intrinsics behave the same as the
+// non-'u' versions. We'll just alias them here.
+#define _mm_ucomieq_ss _mm_comieq_ss
+#define _mm_ucomige_ss _mm_comige_ss
+#define _mm_ucomigt_ss _mm_comigt_ss
+#define _mm_ucomile_ss _mm_comile_ss
+#define _mm_ucomilt_ss _mm_comilt_ss
+#define _mm_ucomineq_ss _mm_comineq_ss
-// FORCE_INLINE __m128i _mm_shufflehi_epi16(__m128i a,
-// __constrange(0,255) int imm)
-#if __has_builtin(__builtin_shufflevector)
-#define _mm_shufflehi_epi16(a, imm) \
- __extension__({ \
- int16x8_t _input = vreinterpretq_s16_m128i(a); \
- int16x8_t _shuf = __builtin_shufflevector( \
- _input, _input, 0, 1, 2, 3, ((imm) & (0x3)) + 4, \
- (((imm) >> 2) & 0x3) + 4, (((imm) >> 4) & 0x3) + 4, \
- (((imm) >> 6) & 0x3) + 4); \
- vreinterpretq_m128i_s16(_shuf); \
- })
-#else // generic
-#define _mm_shufflehi_epi16(a, imm) _mm_shufflehi_epi16_function((a), (imm))
+// Return vector of type __m128i with undefined elements.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=mm_undefined_si128
+FORCE_INLINE __m128i _mm_undefined_si128(void)
+{
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wuninitialized"
#endif
+ __m128i a;
+ return a;
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+}
-// Shuffle double-precision (64-bit) floating-point elements using the control
-// in imm8, and store the results in dst.
+// Return vector of type __m128 with undefined elements.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_undefined_ps
+FORCE_INLINE __m128 _mm_undefined_ps(void)
+{
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wuninitialized"
+#endif
+ __m128 a;
+ return a;
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+}
+
+// Selects and interleaves the upper two single-precision, floating-point values
+// from a and b.
//
-// dst[63:0] := (imm8[0] == 0) ? a[63:0] : a[127:64]
-// dst[127:64] := (imm8[1] == 0) ? b[63:0] : b[127:64]
+// r0 := a2
+// r1 := b2
+// r2 := a3
+// r3 := b3
//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_shuffle_pd
-#if __has_builtin(__builtin_shufflevector)
-#define _mm_shuffle_pd(a, b, imm8) \
- vreinterpretq_m128d_s64(__builtin_shufflevector( \
- vreinterpretq_s64_m128d(a), vreinterpretq_s64_m128d(b), imm8 & 0x1, \
- ((imm8 & 0x2) >> 1) + 2))
+// https://msdn.microsoft.com/en-us/library/skccxx7d%28v=vs.90%29.aspx
+FORCE_INLINE __m128 _mm_unpackhi_ps(__m128 a, __m128 b)
+{
+#if defined(__aarch64__)
+ return vreinterpretq_m128_f32(
+ vzip2q_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b)));
#else
-#define _mm_shuffle_pd(a, b, imm8) \
- _mm_castsi128_pd(_mm_set_epi64x( \
- vgetq_lane_s64(vreinterpretq_s64_m128d(b), (imm8 & 0x2) >> 1), \
- vgetq_lane_s64(vreinterpretq_s64_m128d(a), imm8 & 0x1)))
+ float32x2_t a1 = vget_high_f32(vreinterpretq_f32_m128(a));
+ float32x2_t b1 = vget_high_f32(vreinterpretq_f32_m128(b));
+ float32x2x2_t result = vzip_f32(a1, b1);
+ return vreinterpretq_m128_f32(vcombine_f32(result.val[0], result.val[1]));
#endif
+}
-// Blend packed 16-bit integers from a and b using control mask imm8, and store
-// the results in dst.
+// Selects and interleaves the lower two single-precision, floating-point values
+// from a and b.
//
-// FOR j := 0 to 7
-// i := j*16
-// IF imm8[j]
-// dst[i+15:i] := b[i+15:i]
-// ELSE
-// dst[i+15:i] := a[i+15:i]
-// FI
-// ENDFOR
-// FORCE_INLINE __m128i _mm_blend_epi16(__m128i a, __m128i b,
-// __constrange(0,255) int imm)
-#define _mm_blend_epi16(a, b, imm) \
- __extension__({ \
- const uint16_t _mask[8] = {((imm) & (1 << 0)) ? 0xFFFF : 0x0000, \
- ((imm) & (1 << 1)) ? 0xFFFF : 0x0000, \
- ((imm) & (1 << 2)) ? 0xFFFF : 0x0000, \
- ((imm) & (1 << 3)) ? 0xFFFF : 0x0000, \
- ((imm) & (1 << 4)) ? 0xFFFF : 0x0000, \
- ((imm) & (1 << 5)) ? 0xFFFF : 0x0000, \
- ((imm) & (1 << 6)) ? 0xFFFF : 0x0000, \
- ((imm) & (1 << 7)) ? 0xFFFF : 0x0000}; \
- uint16x8_t _mask_vec = vld1q_u16(_mask); \
- uint16x8_t _a = vreinterpretq_u16_m128i(a); \
- uint16x8_t _b = vreinterpretq_u16_m128i(b); \
- vreinterpretq_m128i_u16(vbslq_u16(_mask_vec, _b, _a)); \
- })
-
-// Blend packed 8-bit integers from a and b using mask, and store the results in
-// dst.
+// r0 := a0
+// r1 := b0
+// r2 := a1
+// r3 := b1
//
-// FOR j := 0 to 15
-// i := j*8
-// IF mask[i+7]
-// dst[i+7:i] := b[i+7:i]
-// ELSE
-// dst[i+7:i] := a[i+7:i]
-// FI
-// ENDFOR
-FORCE_INLINE __m128i _mm_blendv_epi8(__m128i _a, __m128i _b, __m128i _mask)
+// https://msdn.microsoft.com/en-us/library/25st103b%28v=vs.90%29.aspx
+FORCE_INLINE __m128 _mm_unpacklo_ps(__m128 a, __m128 b)
{
- // Use a signed shift right to create a mask with the sign bit
- uint8x16_t mask =
- vreinterpretq_u8_s8(vshrq_n_s8(vreinterpretq_s8_m128i(_mask), 7));
- uint8x16_t a = vreinterpretq_u8_m128i(_a);
- uint8x16_t b = vreinterpretq_u8_m128i(_b);
- return vreinterpretq_m128i_u8(vbslq_u8(mask, b, a));
+#if defined(__aarch64__)
+ return vreinterpretq_m128_f32(
+ vzip1q_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b)));
+#else
+ float32x2_t a1 = vget_low_f32(vreinterpretq_f32_m128(a));
+ float32x2_t b1 = vget_low_f32(vreinterpretq_f32_m128(b));
+ float32x2x2_t result = vzip_f32(a1, b1);
+ return vreinterpretq_m128_f32(vcombine_f32(result.val[0], result.val[1]));
+#endif
}
-/* Shifts */
+// Computes bitwise EXOR (exclusive-or) of the four single-precision,
+// floating-point values of a and b.
+// https://msdn.microsoft.com/en-us/library/ss6k3wk8(v=vs.100).aspx
+FORCE_INLINE __m128 _mm_xor_ps(__m128 a, __m128 b)
+{
+ return vreinterpretq_m128_s32(
+ veorq_s32(vreinterpretq_s32_m128(a), vreinterpretq_s32_m128(b)));
+}
+/* SSE2 */
-// Shift packed 16-bit integers in a right by imm while shifting in sign
-// bits, and store the results in dst.
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_srai_epi16
-FORCE_INLINE __m128i _mm_srai_epi16(__m128i a, int imm)
+// Adds the 8 signed or unsigned 16-bit integers in a to the 8 signed or
+// unsigned 16-bit integers in b.
+// https://msdn.microsoft.com/en-us/library/fceha5k4(v=vs.100).aspx
+FORCE_INLINE __m128i _mm_add_epi16(__m128i a, __m128i b)
{
- const int count = (imm & ~15) ? 15 : imm;
- return (__m128i) vshlq_s16((int16x8_t) a, vdupq_n_s16(-count));
+ return vreinterpretq_m128i_s16(
+ vaddq_s16(vreinterpretq_s16_m128i(a), vreinterpretq_s16_m128i(b)));
}
-// Shifts the 8 signed or unsigned 16-bit integers in a left by count bits while
-// shifting in zeros.
+// Adds the 4 signed or unsigned 32-bit integers in a to the 4 signed or
+// unsigned 32-bit integers in b.
//
-// r0 := a0 << count
-// r1 := a1 << count
-// ...
-// r7 := a7 << count
+// r0 := a0 + b0
+// r1 := a1 + b1
+// r2 := a2 + b2
+// r3 := a3 + b3
//
-// https://msdn.microsoft.com/en-us/library/es73bcsy(v=vs.90).aspx
-#define _mm_slli_epi16(a, imm) \
- __extension__({ \
- __m128i ret; \
- if (unlikely((imm)) <= 0) { \
- ret = a; \
- } \
- if (unlikely((imm) > 15)) { \
- ret = _mm_setzero_si128(); \
- } else { \
- ret = vreinterpretq_m128i_s16( \
- vshlq_n_s16(vreinterpretq_s16_m128i(a), (imm))); \
- } \
- ret; \
- })
-
-// Shifts the 4 signed or unsigned 32-bit integers in a left by count bits while
-// shifting in zeros. :
-// https://msdn.microsoft.com/en-us/library/z2k3bbtb%28v=vs.90%29.aspx
-// FORCE_INLINE __m128i _mm_slli_epi32(__m128i a, __constrange(0,255) int imm)
-FORCE_INLINE __m128i _mm_slli_epi32(__m128i a, int imm)
+// https://msdn.microsoft.com/en-us/library/vstudio/09xs4fkk(v=vs.100).aspx
+FORCE_INLINE __m128i _mm_add_epi32(__m128i a, __m128i b)
{
- if (unlikely(imm <= 0)) /* TODO: add constant range macro: [0, 255] */
- return a;
- if (unlikely(imm > 31))
- return _mm_setzero_si128();
return vreinterpretq_m128i_s32(
- vshlq_s32(vreinterpretq_s32_m128i(a), vdupq_n_s32(imm)));
+ vaddq_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(b)));
}
-// Shift packed 64-bit integers in a left by imm8 while shifting in zeros, and
-// store the results in dst.
-FORCE_INLINE __m128i _mm_slli_epi64(__m128i a, int imm)
+// Adds the 4 signed or unsigned 64-bit integers in a to the 4 signed or
+// unsigned 32-bit integers in b.
+// https://msdn.microsoft.com/en-us/library/vstudio/09xs4fkk(v=vs.100).aspx
+FORCE_INLINE __m128i _mm_add_epi64(__m128i a, __m128i b)
{
- if (unlikely(imm <= 0)) /* TODO: add constant range macro: [0, 255] */
- return a;
- if (unlikely(imm > 63))
- return _mm_setzero_si128();
return vreinterpretq_m128i_s64(
- vshlq_s64(vreinterpretq_s64_m128i(a), vdupq_n_s64(imm)));
+ vaddq_s64(vreinterpretq_s64_m128i(a), vreinterpretq_s64_m128i(b)));
}
-// Shift packed 16-bit integers in a right by imm8 while shifting in zeros, and
+// Adds the 16 signed or unsigned 8-bit integers in a to the 16 signed or
+// unsigned 8-bit integers in b.
+// https://technet.microsoft.com/en-us/subscriptions/yc7tcyzs(v=vs.90)
+FORCE_INLINE __m128i _mm_add_epi8(__m128i a, __m128i b)
+{
+ return vreinterpretq_m128i_s8(
+ vaddq_s8(vreinterpretq_s8_m128i(a), vreinterpretq_s8_m128i(b)));
+}
+
+// Add packed double-precision (64-bit) floating-point elements in a and b, and
// store the results in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_add_pd
+FORCE_INLINE __m128d _mm_add_pd(__m128d a, __m128d b)
+{
+#if defined(__aarch64__)
+ return vreinterpretq_m128d_f64(
+ vaddq_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(b)));
+#else
+ double *da = (double *) &a;
+ double *db = (double *) &b;
+ double c[2];
+ c[0] = da[0] + db[0];
+ c[1] = da[1] + db[1];
+ return vld1q_f32((float32_t *) c);
+#endif
+}
+
+// Add the lower double-precision (64-bit) floating-point element in a and b,
+// store the result in the lower element of dst, and copy the upper element from
+// a to the upper element of dst.
//
-// FOR j := 0 to 7
-// i := j*16
-// IF imm8[7:0] > 15
-// dst[i+15:i] := 0
-// ELSE
-// dst[i+15:i] := ZeroExtend16(a[i+15:i] >> imm8[7:0])
-// FI
-// ENDFOR
+// dst[63:0] := a[63:0] + b[63:0]
+// dst[127:64] := a[127:64]
//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_srli_epi16
-#define _mm_srli_epi16(a, imm) \
- __extension__({ \
- __m128i ret; \
- if (unlikely(imm) == 0) { \
- ret = a; \
- } \
- if (likely(0 < (imm) && (imm) < 16)) { \
- ret = vreinterpretq_m128i_u16( \
- vshlq_u16(vreinterpretq_u16_m128i(a), vdupq_n_s16(-imm))); \
- } else { \
- ret = _mm_setzero_si128(); \
- } \
- ret; \
- })
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_add_sd
+FORCE_INLINE __m128d _mm_add_sd(__m128d a, __m128d b)
+{
+#if defined(__aarch64__)
+ return _mm_move_sd(a, _mm_add_pd(a, b));
+#else
+ double *da = (double *) &a;
+ double *db = (double *) &b;
+ double c[2];
+ c[0] = da[0] + db[0];
+ c[1] = da[1];
+ return vld1q_f32((float32_t *) c);
+#endif
+}
-// Shift packed 32-bit integers in a right by imm8 while shifting in zeros, and
-// store the results in dst.
+// Add 64-bit integers a and b, and store the result in dst.
//
-// FOR j := 0 to 3
-// i := j*32
-// IF imm8[7:0] > 31
-// dst[i+31:i] := 0
-// ELSE
-// dst[i+31:i] := ZeroExtend32(a[i+31:i] >> imm8[7:0])
-// FI
-// ENDFOR
+// dst[63:0] := a[63:0] + b[63:0]
//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_srli_epi32
-// FORCE_INLINE __m128i _mm_srli_epi32(__m128i a, __constrange(0,255) int imm)
-#define _mm_srli_epi32(a, imm) \
- __extension__({ \
- __m128i ret; \
- if (unlikely((imm) == 0)) { \
- ret = a; \
- } \
- if (likely(0 < (imm) && (imm) < 32)) { \
- ret = vreinterpretq_m128i_u32( \
- vshlq_u32(vreinterpretq_u32_m128i(a), vdupq_n_s32(-imm))); \
- } else { \
- ret = _mm_setzero_si128(); \
- } \
- ret; \
- })
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_add_si64
+FORCE_INLINE __m64 _mm_add_si64(__m64 a, __m64 b)
+{
+ return vreinterpret_m64_s64(
+ vadd_s64(vreinterpret_s64_m64(a), vreinterpret_s64_m64(b)));
+}
-// Shift packed 64-bit integers in a right by imm8 while shifting in zeros, and
-// store the results in dst.
+// Adds the 8 signed 16-bit integers in a to the 8 signed 16-bit integers in b
+// and saturates.
//
-// FOR j := 0 to 1
-// i := j*64
-// IF imm8[7:0] > 63
-// dst[i+63:i] := 0
-// ELSE
-// dst[i+63:i] := ZeroExtend64(a[i+63:i] >> imm8[7:0])
-// FI
-// ENDFOR
+// r0 := SignedSaturate(a0 + b0)
+// r1 := SignedSaturate(a1 + b1)
+// ...
+// r7 := SignedSaturate(a7 + b7)
//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_srli_epi64
-#define _mm_srli_epi64(a, imm) \
- __extension__({ \
- __m128i ret; \
- if (unlikely((imm) == 0)) { \
- ret = a; \
- } \
- if (likely(0 < (imm) && (imm) < 64)) { \
- ret = vreinterpretq_m128i_u64( \
- vshlq_u64(vreinterpretq_u64_m128i(a), vdupq_n_s64(-imm))); \
- } else { \
- ret = _mm_setzero_si128(); \
- } \
- ret; \
- })
+// https://msdn.microsoft.com/en-us/library/1a306ef8(v=vs.100).aspx
+FORCE_INLINE __m128i _mm_adds_epi16(__m128i a, __m128i b)
+{
+ return vreinterpretq_m128i_s16(
+ vqaddq_s16(vreinterpretq_s16_m128i(a), vreinterpretq_s16_m128i(b)));
+}
-// Shift packed 32-bit integers in a right by imm8 while shifting in sign bits,
-// and store the results in dst.
+// Add packed signed 8-bit integers in a and b using saturation, and store the
+// results in dst.
//
-// FOR j := 0 to 3
-// i := j*32
-// IF imm8[7:0] > 31
-// dst[i+31:i] := (a[i+31] ? 0xFFFFFFFF : 0x0)
-// ELSE
-// dst[i+31:i] := SignExtend32(a[i+31:i] >> imm8[7:0])
-// FI
+// FOR j := 0 to 15
+// i := j*8
+// dst[i+7:i] := Saturate8( a[i+7:i] + b[i+7:i] )
// ENDFOR
//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_srai_epi32
-// FORCE_INLINE __m128i _mm_srai_epi32(__m128i a, __constrange(0,255) int imm)
-#define _mm_srai_epi32(a, imm) \
- __extension__({ \
- __m128i ret; \
- if (unlikely((imm) == 0)) { \
- ret = a; \
- } \
- if (likely(0 < (imm) && (imm) < 32)) { \
- ret = vreinterpretq_m128i_s32( \
- vshlq_s32(vreinterpretq_s32_m128i(a), vdupq_n_s32(-imm))); \
- } else { \
- ret = vreinterpretq_m128i_s32( \
- vshrq_n_s32(vreinterpretq_s32_m128i(a), 31)); \
- } \
- ret; \
- })
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_adds_epi8
+FORCE_INLINE __m128i _mm_adds_epi8(__m128i a, __m128i b)
+{
+ return vreinterpretq_m128i_s8(
+ vqaddq_s8(vreinterpretq_s8_m128i(a), vreinterpretq_s8_m128i(b)));
+}
-// Shifts the 128 - bit value in a right by imm bytes while shifting in
-// zeros.imm must be an immediate.
-//
-// r := srl(a, imm*8)
-//
-// https://msdn.microsoft.com/en-us/library/305w28yz(v=vs.100).aspx
-// FORCE_INLINE _mm_srli_si128(__m128i a, __constrange(0,255) int imm)
-#define _mm_srli_si128(a, imm) \
- __extension__({ \
- __m128i ret; \
- if (unlikely((imm) <= 0)) { \
- ret = a; \
- } \
- if (unlikely((imm) > 15)) { \
- ret = _mm_setzero_si128(); \
- } else { \
- ret = vreinterpretq_m128i_s8( \
- vextq_s8(vreinterpretq_s8_m128i(a), vdupq_n_s8(0), (imm))); \
- } \
- ret; \
- })
+// Add packed unsigned 16-bit integers in a and b using saturation, and store
+// the results in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_adds_epu16
+FORCE_INLINE __m128i _mm_adds_epu16(__m128i a, __m128i b)
+{
+ return vreinterpretq_m128i_u16(
+ vqaddq_u16(vreinterpretq_u16_m128i(a), vreinterpretq_u16_m128i(b)));
+}
-// Shifts the 128-bit value in a left by imm bytes while shifting in zeros. imm
-// must be an immediate.
-//
-// r := a << (imm * 8)
-//
-// https://msdn.microsoft.com/en-us/library/34d3k2kt(v=vs.100).aspx
-// FORCE_INLINE __m128i _mm_slli_si128(__m128i a, __constrange(0,255) int imm)
-#define _mm_slli_si128(a, imm) \
- __extension__({ \
- __m128i ret; \
- if (unlikely((imm) <= 0)) { \
- ret = a; \
- } \
- if (unlikely((imm) > 15)) { \
- ret = _mm_setzero_si128(); \
- } else { \
- ret = vreinterpretq_m128i_s8(vextq_s8( \
- vdupq_n_s8(0), vreinterpretq_s8_m128i(a), 16 - (imm))); \
- } \
- ret; \
- })
+// Adds the 16 unsigned 8-bit integers in a to the 16 unsigned 8-bit integers in
+// b and saturates..
+// https://msdn.microsoft.com/en-us/library/9hahyddy(v=vs.100).aspx
+FORCE_INLINE __m128i _mm_adds_epu8(__m128i a, __m128i b)
+{
+ return vreinterpretq_m128i_u8(
+ vqaddq_u8(vreinterpretq_u8_m128i(a), vreinterpretq_u8_m128i(b)));
+}
-// Shifts the 8 signed or unsigned 16-bit integers in a left by count bits while
-// shifting in zeros.
+// Compute the bitwise AND of packed double-precision (64-bit) floating-point
+// elements in a and b, and store the results in dst.
//
-// r0 := a0 << count
-// r1 := a1 << count
-// ...
-// r7 := a7 << count
+// FOR j := 0 to 1
+// i := j*64
+// dst[i+63:i] := a[i+63:i] AND b[i+63:i]
+// ENDFOR
//
-// https://msdn.microsoft.com/en-us/library/c79w388h(v%3dvs.90).aspx
-FORCE_INLINE __m128i _mm_sll_epi16(__m128i a, __m128i count)
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_and_pd
+FORCE_INLINE __m128d _mm_and_pd(__m128d a, __m128d b)
{
- uint64_t c = vreinterpretq_nth_u64_m128i(count, 0);
- if (unlikely(c > 15))
- return _mm_setzero_si128();
-
- int16x8_t vc = vdupq_n_s16((int16_t) c);
- return vreinterpretq_m128i_s16(vshlq_s16(vreinterpretq_s16_m128i(a), vc));
+ return vreinterpretq_m128d_s64(
+ vandq_s64(vreinterpretq_s64_m128d(a), vreinterpretq_s64_m128d(b)));
}
-// Shifts the 4 signed or unsigned 32-bit integers in a left by count bits while
-// shifting in zeros.
+// Computes the bitwise AND of the 128-bit value in a and the 128-bit value in
+// b.
//
-// r0 := a0 << count
-// r1 := a1 << count
-// r2 := a2 << count
-// r3 := a3 << count
+// r := a & b
//
-// https://msdn.microsoft.com/en-us/library/6fe5a6s9(v%3dvs.90).aspx
-FORCE_INLINE __m128i _mm_sll_epi32(__m128i a, __m128i count)
+// https://msdn.microsoft.com/en-us/library/vstudio/6d1txsa8(v=vs.100).aspx
+FORCE_INLINE __m128i _mm_and_si128(__m128i a, __m128i b)
{
- uint64_t c = vreinterpretq_nth_u64_m128i(count, 0);
- if (unlikely(c > 31))
- return _mm_setzero_si128();
-
- int32x4_t vc = vdupq_n_s32((int32_t) c);
- return vreinterpretq_m128i_s32(vshlq_s32(vreinterpretq_s32_m128i(a), vc));
+ return vreinterpretq_m128i_s32(
+ vandq_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(b)));
}
-// Shifts the 2 signed or unsigned 64-bit integers in a left by count bits while
-// shifting in zeros.
+// Compute the bitwise NOT of packed double-precision (64-bit) floating-point
+// elements in a and then AND with b, and store the results in dst.
//
-// r0 := a0 << count
-// r1 := a1 << count
+// FOR j := 0 to 1
+// i := j*64
+// dst[i+63:i] := ((NOT a[i+63:i]) AND b[i+63:i])
+// ENDFOR
//
-// https://msdn.microsoft.com/en-us/library/6ta9dffd(v%3dvs.90).aspx
-FORCE_INLINE __m128i _mm_sll_epi64(__m128i a, __m128i count)
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_andnot_pd
+FORCE_INLINE __m128d _mm_andnot_pd(__m128d a, __m128d b)
{
- uint64_t c = vreinterpretq_nth_u64_m128i(count, 0);
- if (unlikely(c > 63))
- return _mm_setzero_si128();
-
- int64x2_t vc = vdupq_n_s64((int64_t) c);
- return vreinterpretq_m128i_s64(vshlq_s64(vreinterpretq_s64_m128i(a), vc));
+ // *NOTE* argument swap
+ return vreinterpretq_m128d_s64(
+ vbicq_s64(vreinterpretq_s64_m128d(b), vreinterpretq_s64_m128d(a)));
}
-// Shifts the 8 signed or unsigned 16-bit integers in a right by count bits
-// while shifting in zeros.
+// Computes the bitwise AND of the 128-bit value in b and the bitwise NOT of the
+// 128-bit value in a.
//
-// r0 := srl(a0, count)
-// r1 := srl(a1, count)
-// ...
-// r7 := srl(a7, count)
+// r := (~a) & b
//
-// https://msdn.microsoft.com/en-us/library/wd5ax830(v%3dvs.90).aspx
-FORCE_INLINE __m128i _mm_srl_epi16(__m128i a, __m128i count)
+// https://msdn.microsoft.com/en-us/library/vstudio/1beaceh8(v=vs.100).aspx
+FORCE_INLINE __m128i _mm_andnot_si128(__m128i a, __m128i b)
{
- uint64_t c = vreinterpretq_nth_u64_m128i(count, 0);
- if (unlikely(c > 15))
- return _mm_setzero_si128();
-
- int16x8_t vc = vdupq_n_s16(-(int16_t) c);
- return vreinterpretq_m128i_u16(vshlq_u16(vreinterpretq_u16_m128i(a), vc));
+ return vreinterpretq_m128i_s32(
+ vbicq_s32(vreinterpretq_s32_m128i(b),
+ vreinterpretq_s32_m128i(a))); // *NOTE* argument swap
}
-// Shifts the 4 signed or unsigned 32-bit integers in a right by count bits
-// while shifting in zeros.
+// Computes the average of the 8 unsigned 16-bit integers in a and the 8
+// unsigned 16-bit integers in b and rounds.
//
-// r0 := srl(a0, count)
-// r1 := srl(a1, count)
-// r2 := srl(a2, count)
-// r3 := srl(a3, count)
+// r0 := (a0 + b0) / 2
+// r1 := (a1 + b1) / 2
+// ...
+// r7 := (a7 + b7) / 2
//
-// https://msdn.microsoft.com/en-us/library/a9cbttf4(v%3dvs.90).aspx
-FORCE_INLINE __m128i _mm_srl_epi32(__m128i a, __m128i count)
+// https://msdn.microsoft.com/en-us/library/vstudio/y13ca3c8(v=vs.90).aspx
+FORCE_INLINE __m128i _mm_avg_epu16(__m128i a, __m128i b)
{
- uint64_t c = vreinterpretq_nth_u64_m128i(count, 0);
- if (unlikely(c > 31))
- return _mm_setzero_si128();
-
- int32x4_t vc = vdupq_n_s32(-(int32_t) c);
- return vreinterpretq_m128i_u32(vshlq_u32(vreinterpretq_u32_m128i(a), vc));
+ return (__m128i) vrhaddq_u16(vreinterpretq_u16_m128i(a),
+ vreinterpretq_u16_m128i(b));
}
-// Shifts the 2 signed or unsigned 64-bit integers in a right by count bits
-// while shifting in zeros.
+// Computes the average of the 16 unsigned 8-bit integers in a and the 16
+// unsigned 8-bit integers in b and rounds.
//
-// r0 := srl(a0, count)
-// r1 := srl(a1, count)
+// r0 := (a0 + b0) / 2
+// r1 := (a1 + b1) / 2
+// ...
+// r15 := (a15 + b15) / 2
//
-// https://msdn.microsoft.com/en-us/library/yf6cf9k8(v%3dvs.90).aspx
-FORCE_INLINE __m128i _mm_srl_epi64(__m128i a, __m128i count)
+// https://msdn.microsoft.com/en-us/library/vstudio/8zwh554a(v%3dvs.90).aspx
+FORCE_INLINE __m128i _mm_avg_epu8(__m128i a, __m128i b)
{
- uint64_t c = vreinterpretq_nth_u64_m128i(count, 0);
- if (unlikely(c > 63))
- return _mm_setzero_si128();
-
- int64x2_t vc = vdupq_n_s64(-(int64_t) c);
- return vreinterpretq_m128i_u64(vshlq_u64(vreinterpretq_u64_m128i(a), vc));
+ return vreinterpretq_m128i_u8(
+ vrhaddq_u8(vreinterpretq_u8_m128i(a), vreinterpretq_u8_m128i(b)));
}
-// NEON does not provide a version of this function.
-// Creates a 16-bit mask from the most significant bits of the 16 signed or
-// unsigned 8-bit integers in a and zero extends the upper bits.
-// https://msdn.microsoft.com/en-us/library/vstudio/s090c8fk(v=vs.100).aspx
-FORCE_INLINE int _mm_movemask_epi8(__m128i a)
-{
- // Use increasingly wide shifts+adds to collect the sign bits
- // together.
- // Since the widening shifts would be rather confusing to follow in little
- // endian, everything will be illustrated in big endian order instead. This
- // has a different result - the bits would actually be reversed on a big
- // endian machine.
-
- // Starting input (only half the elements are shown):
- // 89 ff 1d c0 00 10 99 33
- uint8x16_t input = vreinterpretq_u8_m128i(a);
-
- // Shift out everything but the sign bits with an unsigned shift right.
- //
- // Bytes of the vector::
- // 89 ff 1d c0 00 10 99 33
- // \ \ \ \ \ \ \ \ high_bits = (uint16x4_t)(input >> 7)
- // | | | | | | | |
- // 01 01 00 01 00 00 01 00
- //
- // Bits of first important lane(s):
- // 10001001 (89)
- // \______
- // |
- // 00000001 (01)
- uint16x8_t high_bits = vreinterpretq_u16_u8(vshrq_n_u8(input, 7));
-
- // Merge the even lanes together with a 16-bit unsigned shift right + add.
- // 'xx' represents garbage data which will be ignored in the final result.
- // In the important bytes, the add functions like a binary OR.
- //
- // 01 01 00 01 00 00 01 00
- // \_ | \_ | \_ | \_ | paired16 = (uint32x4_t)(input + (input >> 7))
- // \| \| \| \|
- // xx 03 xx 01 xx 00 xx 02
- //
- // 00000001 00000001 (01 01)
- // \_______ |
- // \|
- // xxxxxxxx xxxxxx11 (xx 03)
- uint32x4_t paired16 =
- vreinterpretq_u32_u16(vsraq_n_u16(high_bits, high_bits, 7));
+// Shift a left by imm8 bytes while shifting in zeros, and store the results in
+// dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_bslli_si128
+#define _mm_bslli_si128(a, imm) _mm_slli_si128(a, imm)
- // Repeat with a wider 32-bit shift + add.
- // xx 03 xx 01 xx 00 xx 02
- // \____ | \____ | paired32 = (uint64x1_t)(paired16 + (paired16 >>
- // 14))
- // \| \|
- // xx xx xx 0d xx xx xx 02
- //
- // 00000011 00000001 (03 01)
- // \\_____ ||
- // '----.\||
- // xxxxxxxx xxxx1101 (xx 0d)
- uint64x2_t paired32 =
- vreinterpretq_u64_u32(vsraq_n_u32(paired16, paired16, 14));
+// Shift a right by imm8 bytes while shifting in zeros, and store the results in
+// dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_bsrli_si128
+#define _mm_bsrli_si128(a, imm) _mm_srli_si128(a, imm)
- // Last, an even wider 64-bit shift + add to get our result in the low 8 bit
- // lanes. xx xx xx 0d xx xx xx 02
- // \_________ | paired64 = (uint8x8_t)(paired32 + (paired32 >>
- // 28))
- // \|
- // xx xx xx xx xx xx xx d2
- //
- // 00001101 00000010 (0d 02)
- // \ \___ | |
- // '---. \| |
- // xxxxxxxx 11010010 (xx d2)
- uint8x16_t paired64 =
- vreinterpretq_u8_u64(vsraq_n_u64(paired32, paired32, 28));
+// Cast vector of type __m128d to type __m128. This intrinsic is only used for
+// compilation and does not generate any instructions, thus it has zero latency.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_castpd_ps
+FORCE_INLINE __m128 _mm_castpd_ps(__m128d a)
+{
+ return vreinterpretq_m128_s64(vreinterpretq_s64_m128d(a));
+}
- // Extract the low 8 bits from each 64-bit lane with 2 8-bit extracts.
- // xx xx xx xx xx xx xx d2
- // || return paired64[0]
- // d2
- // Note: Little endian would return the correct value 4b (01001011) instead.
- return vgetq_lane_u8(paired64, 0) | ((int) vgetq_lane_u8(paired64, 8) << 8);
+// Cast vector of type __m128d to type __m128i. This intrinsic is only used for
+// compilation and does not generate any instructions, thus it has zero latency.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_castpd_si128
+FORCE_INLINE __m128i _mm_castpd_si128(__m128d a)
+{
+ return vreinterpretq_m128i_s64(vreinterpretq_s64_m128d(a));
}
-// Copy the lower 64-bit integer in a to dst.
-//
-// dst[63:0] := a[63:0]
-//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_movepi64_pi64
-FORCE_INLINE __m64 _mm_movepi64_pi64(__m128i a)
+// Cast vector of type __m128 to type __m128d. This intrinsic is only used for
+// compilation and does not generate any instructions, thus it has zero latency.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_castps_pd
+FORCE_INLINE __m128d _mm_castps_pd(__m128 a)
{
- return vreinterpret_m64_s64(vget_low_s64(vreinterpretq_s64_m128i(a)));
+ return vreinterpretq_m128d_s32(vreinterpretq_s32_m128(a));
}
-// Copy the 64-bit integer a to the lower element of dst, and zero the upper
-// element.
-//
-// dst[63:0] := a[63:0]
-// dst[127:64] := 0
-//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_movpi64_epi64
-FORCE_INLINE __m128i _mm_movpi64_epi64(__m64 a)
+// Applies a type cast to reinterpret four 32-bit floating point values passed
+// in as a 128-bit parameter as packed 32-bit integers.
+// https://msdn.microsoft.com/en-us/library/bb514099.aspx
+FORCE_INLINE __m128i _mm_castps_si128(__m128 a)
{
- return vreinterpretq_m128i_s64(
- vcombine_s64(vreinterpret_s64_m64(a), vdup_n_s64(0)));
+ return vreinterpretq_m128i_s32(vreinterpretq_s32_m128(a));
}
-// NEON does not provide this method
-// Creates a 4-bit mask from the most significant bits of the four
-// single-precision, floating-point values.
-// https://msdn.microsoft.com/en-us/library/vstudio/4490ys29(v=vs.100).aspx
-FORCE_INLINE int _mm_movemask_ps(__m128 a)
+// Cast vector of type __m128i to type __m128d. This intrinsic is only used for
+// compilation and does not generate any instructions, thus it has zero latency.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_castsi128_pd
+FORCE_INLINE __m128d _mm_castsi128_pd(__m128i a)
{
- uint32x4_t input = vreinterpretq_u32_m128(a);
#if defined(__aarch64__)
- static const int32x4_t shift = {0, 1, 2, 3};
- uint32x4_t tmp = vshrq_n_u32(input, 31);
- return vaddvq_u32(vshlq_u32(tmp, shift));
+ return vreinterpretq_m128d_f64(vreinterpretq_f64_m128i(a));
#else
- // Uses the exact same method as _mm_movemask_epi8, see that for details.
- // Shift out everything but the sign bits with a 32-bit unsigned shift
- // right.
- uint64x2_t high_bits = vreinterpretq_u64_u32(vshrq_n_u32(input, 31));
- // Merge the two pairs together with a 64-bit unsigned shift right + add.
- uint8x16_t paired =
- vreinterpretq_u8_u64(vsraq_n_u64(high_bits, high_bits, 31));
- // Extract the result.
- return vgetq_lane_u8(paired, 0) | (vgetq_lane_u8(paired, 8) << 2);
+ return vreinterpretq_m128d_f32(vreinterpretq_f32_m128i(a));
#endif
}
-// Compute the bitwise NOT of a and then AND with a 128-bit vector containing
-// all 1's, and return 1 if the result is zero, otherwise return 0.
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_test_all_ones
-FORCE_INLINE int _mm_test_all_ones(__m128i a)
+// Applies a type cast to reinterpret four 32-bit integers passed in as a
+// 128-bit parameter as packed 32-bit floating point values.
+// https://msdn.microsoft.com/en-us/library/bb514029.aspx
+FORCE_INLINE __m128 _mm_castsi128_ps(__m128i a)
{
- return (uint64_t)(vgetq_lane_s64(a, 0) & vgetq_lane_s64(a, 1)) ==
- ~(uint64_t) 0;
+ return vreinterpretq_m128_s32(vreinterpretq_s32_m128i(a));
}
-// Compute the bitwise AND of 128 bits (representing integer data) in a and
-// mask, and return 1 if the result is zero, otherwise return 0.
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_test_all_zeros
-FORCE_INLINE int _mm_test_all_zeros(__m128i a, __m128i mask)
+// Cache line containing p is flushed and invalidated from all caches in the
+// coherency domain. :
+// https://msdn.microsoft.com/en-us/library/ba08y07y(v=vs.100).aspx
+FORCE_INLINE void _mm_clflush(void const *p)
{
- int64x2_t a_and_mask =
- vandq_s64(vreinterpretq_s64_m128i(a), vreinterpretq_s64_m128i(mask));
- return (vgetq_lane_s64(a_and_mask, 0) | vgetq_lane_s64(a_and_mask, 1)) ? 0
- : 1;
+ (void) p;
+ // no corollary for Neon?
}
-/* Math operations */
+// Compares the 8 signed or unsigned 16-bit integers in a and the 8 signed or
+// unsigned 16-bit integers in b for equality.
+// https://msdn.microsoft.com/en-us/library/2ay060te(v=vs.100).aspx
+FORCE_INLINE __m128i _mm_cmpeq_epi16(__m128i a, __m128i b)
+{
+ return vreinterpretq_m128i_u16(
+ vceqq_s16(vreinterpretq_s16_m128i(a), vreinterpretq_s16_m128i(b)));
+}
-// Subtracts the four single-precision, floating-point values of a and b.
-//
-// r0 := a0 - b0
-// r1 := a1 - b1
-// r2 := a2 - b2
-// r3 := a3 - b3
-//
-// https://msdn.microsoft.com/en-us/library/vstudio/1zad2k61(v=vs.100).aspx
-FORCE_INLINE __m128 _mm_sub_ps(__m128 a, __m128 b)
+// Compare packed 32-bit integers in a and b for equality, and store the results
+// in dst
+FORCE_INLINE __m128i _mm_cmpeq_epi32(__m128i a, __m128i b)
{
- return vreinterpretq_m128_f32(
- vsubq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b)));
+ return vreinterpretq_m128i_u32(
+ vceqq_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(b)));
}
-// Subtract the lower single-precision (32-bit) floating-point element in b from
-// the lower single-precision (32-bit) floating-point element in a, store the
-// result in the lower element of dst, and copy the upper 3 packed elements from
-// a to the upper elements of dst.
-//
-// dst[31:0] := a[31:0] - b[31:0]
-// dst[127:32] := a[127:32]
-//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_sub_ss
-FORCE_INLINE __m128 _mm_sub_ss(__m128 a, __m128 b)
+// Compares the 16 signed or unsigned 8-bit integers in a and the 16 signed or
+// unsigned 8-bit integers in b for equality.
+// https://msdn.microsoft.com/en-us/library/windows/desktop/bz5xk21a(v=vs.90).aspx
+FORCE_INLINE __m128i _mm_cmpeq_epi8(__m128i a, __m128i b)
{
- return _mm_move_ss(a, _mm_sub_ps(a, b));
+ return vreinterpretq_m128i_u8(
+ vceqq_s8(vreinterpretq_s8_m128i(a), vreinterpretq_s8_m128i(b)));
}
-// Subtract 2 packed 64-bit integers in b from 2 packed 64-bit integers in a,
-// and store the results in dst.
-// r0 := a0 - b0
-// r1 := a1 - b1
-FORCE_INLINE __m128i _mm_sub_epi64(__m128i a, __m128i b)
+// Compare packed double-precision (64-bit) floating-point elements in a and b
+// for equality, and store the results in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmpeq_pd
+FORCE_INLINE __m128d _mm_cmpeq_pd(__m128d a, __m128d b)
{
- return vreinterpretq_m128i_s64(
- vsubq_s64(vreinterpretq_s64_m128i(a), vreinterpretq_s64_m128i(b)));
+#if defined(__aarch64__)
+ return vreinterpretq_m128d_u64(
+ vceqq_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(b)));
+#else
+ // (a == b) -> (a_lo == b_lo) && (a_hi == b_hi)
+ uint32x4_t cmp =
+ vceqq_u32(vreinterpretq_u32_m128d(a), vreinterpretq_u32_m128d(b));
+ uint32x4_t swapped = vrev64q_u32(cmp);
+ return vreinterpretq_m128d_u32(vandq_u32(cmp, swapped));
+#endif
}
-// Subtracts the 4 signed or unsigned 32-bit integers of b from the 4 signed or
-// unsigned 32-bit integers of a.
-//
-// r0 := a0 - b0
-// r1 := a1 - b1
-// r2 := a2 - b2
-// r3 := a3 - b3
-//
-// https://msdn.microsoft.com/en-us/library/vstudio/fhh866h0(v=vs.100).aspx
-FORCE_INLINE __m128i _mm_sub_epi32(__m128i a, __m128i b)
+// Compare the lower double-precision (64-bit) floating-point elements in a and
+// b for equality, store the result in the lower element of dst, and copy the
+// upper element from a to the upper element of dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmpeq_sd
+FORCE_INLINE __m128d _mm_cmpeq_sd(__m128d a, __m128d b)
{
- return vreinterpretq_m128i_s32(
- vsubq_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(b)));
+ return _mm_move_sd(a, _mm_cmpeq_pd(a, b));
}
-// Subtract packed 16-bit integers in b from packed 16-bit integers in a, and
-// store the results in dst.
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_sub_epi16
-FORCE_INLINE __m128i _mm_sub_epi16(__m128i a, __m128i b)
+// Compare packed double-precision (64-bit) floating-point elements in a and b
+// for greater-than-or-equal, and store the results in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmpge_pd
+FORCE_INLINE __m128d _mm_cmpge_pd(__m128d a, __m128d b)
{
- return vreinterpretq_m128i_s16(
- vsubq_s16(vreinterpretq_s16_m128i(a), vreinterpretq_s16_m128i(b)));
+#if defined(__aarch64__)
+ return vreinterpretq_m128d_u64(
+ vcgeq_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(b)));
+#else
+ uint64_t a0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(a));
+ uint64_t a1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(a));
+ uint64_t b0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(b));
+ uint64_t b1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(b));
+ uint64_t d[2];
+ d[0] = (*(double *) &a0) >= (*(double *) &b0) ? ~UINT64_C(0) : UINT64_C(0);
+ d[1] = (*(double *) &a1) >= (*(double *) &b1) ? ~UINT64_C(0) : UINT64_C(0);
+
+ return vreinterpretq_m128d_u64(vld1q_u64(d));
+#endif
}
-// Subtract packed 8-bit integers in b from packed 8-bit integers in a, and
-// store the results in dst.
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_sub_epi8
-FORCE_INLINE __m128i _mm_sub_epi8(__m128i a, __m128i b)
+// Compare the lower double-precision (64-bit) floating-point elements in a and
+// b for greater-than-or-equal, store the result in the lower element of dst,
+// and copy the upper element from a to the upper element of dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmpge_sd
+FORCE_INLINE __m128d _mm_cmpge_sd(__m128d a, __m128d b)
{
- return vreinterpretq_m128i_s8(
- vsubq_s8(vreinterpretq_s8_m128i(a), vreinterpretq_s8_m128i(b)));
+#if defined(__aarch64__)
+ return _mm_move_sd(a, _mm_cmpge_pd(a, b));
+#else
+ // expand "_mm_cmpge_pd()" to reduce unnecessary operations
+ uint64_t a0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(a));
+ uint64_t a1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(a));
+ uint64_t b0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(b));
+ uint64_t d[2];
+ d[0] = (*(double *) &a0) >= (*(double *) &b0) ? ~UINT64_C(0) : UINT64_C(0);
+ d[1] = a1;
+
+ return vreinterpretq_m128d_u64(vld1q_u64(d));
+#endif
}
-// Subtract 64-bit integer b from 64-bit integer a, and store the result in dst.
+// Compares the 8 signed 16-bit integers in a and the 8 signed 16-bit integers
+// in b for greater than.
//
-// dst[63:0] := a[63:0] - b[63:0]
+// r0 := (a0 > b0) ? 0xffff : 0x0
+// r1 := (a1 > b1) ? 0xffff : 0x0
+// ...
+// r7 := (a7 > b7) ? 0xffff : 0x0
//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_sub_si64
-FORCE_INLINE __m64 _mm_sub_si64(__m64 a, __m64 b)
+// https://technet.microsoft.com/en-us/library/xd43yfsa(v=vs.100).aspx
+FORCE_INLINE __m128i _mm_cmpgt_epi16(__m128i a, __m128i b)
{
- return vreinterpret_m64_s64(
- vsub_s64(vreinterpret_s64_m64(a), vreinterpret_s64_m64(b)));
+ return vreinterpretq_m128i_u16(
+ vcgtq_s16(vreinterpretq_s16_m128i(a), vreinterpretq_s16_m128i(b)));
}
-// Subtracts the 8 unsigned 16-bit integers of bfrom the 8 unsigned 16-bit
-// integers of a and saturates..
-// https://technet.microsoft.com/en-us/subscriptions/index/f44y0s19(v=vs.90).aspx
-FORCE_INLINE __m128i _mm_subs_epu16(__m128i a, __m128i b)
+// Compares the 4 signed 32-bit integers in a and the 4 signed 32-bit integers
+// in b for greater than.
+// https://msdn.microsoft.com/en-us/library/vstudio/1s9f2z0y(v=vs.100).aspx
+FORCE_INLINE __m128i _mm_cmpgt_epi32(__m128i a, __m128i b)
{
- return vreinterpretq_m128i_u16(
- vqsubq_u16(vreinterpretq_u16_m128i(a), vreinterpretq_u16_m128i(b)));
+ return vreinterpretq_m128i_u32(
+ vcgtq_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(b)));
}
-// Subtracts the 16 unsigned 8-bit integers of b from the 16 unsigned 8-bit
-// integers of a and saturates.
+// Compares the 16 signed 8-bit integers in a and the 16 signed 8-bit integers
+// in b for greater than.
//
-// r0 := UnsignedSaturate(a0 - b0)
-// r1 := UnsignedSaturate(a1 - b1)
+// r0 := (a0 > b0) ? 0xff : 0x0
+// r1 := (a1 > b1) ? 0xff : 0x0
// ...
-// r15 := UnsignedSaturate(a15 - b15)
+// r15 := (a15 > b15) ? 0xff : 0x0
//
-// https://technet.microsoft.com/en-us/subscriptions/yadkxc18(v=vs.90)
-FORCE_INLINE __m128i _mm_subs_epu8(__m128i a, __m128i b)
+// https://msdn.microsoft.com/zh-tw/library/wf45zt2b(v=vs.100).aspx
+FORCE_INLINE __m128i _mm_cmpgt_epi8(__m128i a, __m128i b)
{
return vreinterpretq_m128i_u8(
- vqsubq_u8(vreinterpretq_u8_m128i(a), vreinterpretq_u8_m128i(b)));
+ vcgtq_s8(vreinterpretq_s8_m128i(a), vreinterpretq_s8_m128i(b)));
}
-// Subtracts the 16 signed 8-bit integers of b from the 16 signed 8-bit integers
-// of a and saturates.
-//
-// r0 := SignedSaturate(a0 - b0)
-// r1 := SignedSaturate(a1 - b1)
-// ...
-// r15 := SignedSaturate(a15 - b15)
-//
-// https://technet.microsoft.com/en-us/subscriptions/by7kzks1(v=vs.90)
-FORCE_INLINE __m128i _mm_subs_epi8(__m128i a, __m128i b)
+// Compare packed double-precision (64-bit) floating-point elements in a and b
+// for greater-than, and store the results in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmpgt_pd
+FORCE_INLINE __m128d _mm_cmpgt_pd(__m128d a, __m128d b)
{
- return vreinterpretq_m128i_s8(
- vqsubq_s8(vreinterpretq_s8_m128i(a), vreinterpretq_s8_m128i(b)));
+#if defined(__aarch64__)
+ return vreinterpretq_m128d_u64(
+ vcgtq_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(b)));
+#else
+ uint64_t a0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(a));
+ uint64_t a1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(a));
+ uint64_t b0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(b));
+ uint64_t b1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(b));
+ uint64_t d[2];
+ d[0] = (*(double *) &a0) > (*(double *) &b0) ? ~UINT64_C(0) : UINT64_C(0);
+ d[1] = (*(double *) &a1) > (*(double *) &b1) ? ~UINT64_C(0) : UINT64_C(0);
+
+ return vreinterpretq_m128d_u64(vld1q_u64(d));
+#endif
}
-// Subtracts the 8 signed 16-bit integers of b from the 8 signed 16-bit integers
-// of a and saturates.
-//
-// r0 := SignedSaturate(a0 - b0)
-// r1 := SignedSaturate(a1 - b1)
-// ...
-// r7 := SignedSaturate(a7 - b7)
-//
-// https://technet.microsoft.com/en-us/subscriptions/3247z5b8(v=vs.90)
-FORCE_INLINE __m128i _mm_subs_epi16(__m128i a, __m128i b)
+// Compare the lower double-precision (64-bit) floating-point elements in a and
+// b for greater-than, store the result in the lower element of dst, and copy
+// the upper element from a to the upper element of dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmpgt_sd
+FORCE_INLINE __m128d _mm_cmpgt_sd(__m128d a, __m128d b)
{
- return vreinterpretq_m128i_s16(
- vqsubq_s16(vreinterpretq_s16_m128i(a), vreinterpretq_s16_m128i(b)));
+#if defined(__aarch64__)
+ return _mm_move_sd(a, _mm_cmpgt_pd(a, b));
+#else
+ // expand "_mm_cmpge_pd()" to reduce unnecessary operations
+ uint64_t a0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(a));
+ uint64_t a1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(a));
+ uint64_t b0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(b));
+ uint64_t d[2];
+ d[0] = (*(double *) &a0) > (*(double *) &b0) ? ~UINT64_C(0) : UINT64_C(0);
+ d[1] = a1;
+
+ return vreinterpretq_m128d_u64(vld1q_u64(d));
+#endif
}
-// Subtract packed double-precision (64-bit) floating-point elements in b from
-// packed double-precision (64-bit) floating-point elements in a, and store the
-// results in dst.
-//
-// FOR j := 0 to 1
-// i := j*64
-// dst[i+63:i] := a[i+63:i] - b[i+63:i]
-// ENDFOR
-//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=mm_sub_pd
-FORCE_INLINE __m128d _mm_sub_pd(__m128d a, __m128d b)
+// Compare packed double-precision (64-bit) floating-point elements in a and b
+// for less-than-or-equal, and store the results in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmple_pd
+FORCE_INLINE __m128d _mm_cmple_pd(__m128d a, __m128d b)
{
#if defined(__aarch64__)
- return vreinterpretq_m128d_f64(
- vsubq_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(b)));
+ return vreinterpretq_m128d_u64(
+ vcleq_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(b)));
#else
- double *da = (double *) &a;
- double *db = (double *) &b;
- double c[2];
- c[0] = da[0] - db[0];
- c[1] = da[1] - db[1];
- return vld1q_f32((float32_t *) c);
+ uint64_t a0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(a));
+ uint64_t a1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(a));
+ uint64_t b0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(b));
+ uint64_t b1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(b));
+ uint64_t d[2];
+ d[0] = (*(double *) &a0) <= (*(double *) &b0) ? ~UINT64_C(0) : UINT64_C(0);
+ d[1] = (*(double *) &a1) <= (*(double *) &b1) ? ~UINT64_C(0) : UINT64_C(0);
+
+ return vreinterpretq_m128d_u64(vld1q_u64(d));
#endif
}
-// Subtract the lower double-precision (64-bit) floating-point element in b from
-// the lower double-precision (64-bit) floating-point element in a, store the
-// result in the lower element of dst, and copy the upper element from a to the
-// upper element of dst.
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_sub_sd
-FORCE_INLINE __m128d _mm_sub_sd(__m128d a, __m128d b)
+// Compare the lower double-precision (64-bit) floating-point elements in a and
+// b for less-than-or-equal, store the result in the lower element of dst, and
+// copy the upper element from a to the upper element of dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmple_sd
+FORCE_INLINE __m128d _mm_cmple_sd(__m128d a, __m128d b)
{
- return _mm_move_sd(a, _mm_sub_pd(a, b));
+#if defined(__aarch64__)
+ return _mm_move_sd(a, _mm_cmple_pd(a, b));
+#else
+ // expand "_mm_cmpge_pd()" to reduce unnecessary operations
+ uint64_t a0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(a));
+ uint64_t a1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(a));
+ uint64_t b0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(b));
+ uint64_t d[2];
+ d[0] = (*(double *) &a0) <= (*(double *) &b0) ? ~UINT64_C(0) : UINT64_C(0);
+ d[1] = a1;
+
+ return vreinterpretq_m128d_u64(vld1q_u64(d));
+#endif
}
-// Add packed unsigned 16-bit integers in a and b using saturation, and store
-// the results in dst.
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_adds_epu16
-FORCE_INLINE __m128i _mm_adds_epu16(__m128i a, __m128i b)
+// Compares the 8 signed 16-bit integers in a and the 8 signed 16-bit integers
+// in b for less than.
+//
+// r0 := (a0 < b0) ? 0xffff : 0x0
+// r1 := (a1 < b1) ? 0xffff : 0x0
+// ...
+// r7 := (a7 < b7) ? 0xffff : 0x0
+//
+// https://technet.microsoft.com/en-us/library/t863edb2(v=vs.100).aspx
+FORCE_INLINE __m128i _mm_cmplt_epi16(__m128i a, __m128i b)
{
return vreinterpretq_m128i_u16(
- vqaddq_u16(vreinterpretq_u16_m128i(a), vreinterpretq_u16_m128i(b)));
+ vcltq_s16(vreinterpretq_s16_m128i(a), vreinterpretq_s16_m128i(b)));
}
-// Negate packed 8-bit integers in a when the corresponding signed
-// 8-bit integer in b is negative, and store the results in dst.
-// Element in dst are zeroed out when the corresponding element
-// in b is zero.
-//
-// for i in 0..15
-// if b[i] < 0
-// r[i] := -a[i]
-// else if b[i] == 0
-// r[i] := 0
-// else
-// r[i] := a[i]
-// fi
-// done
-FORCE_INLINE __m128i _mm_sign_epi8(__m128i _a, __m128i _b)
+
+// Compares the 4 signed 32-bit integers in a and the 4 signed 32-bit integers
+// in b for less than.
+// https://msdn.microsoft.com/en-us/library/vstudio/4ak0bf5d(v=vs.100).aspx
+FORCE_INLINE __m128i _mm_cmplt_epi32(__m128i a, __m128i b)
{
- int8x16_t a = vreinterpretq_s8_m128i(_a);
- int8x16_t b = vreinterpretq_s8_m128i(_b);
+ return vreinterpretq_m128i_u32(
+ vcltq_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(b)));
+}
- // signed shift right: faster than vclt
- // (b < 0) ? 0xFF : 0
- uint8x16_t ltMask = vreinterpretq_u8_s8(vshrq_n_s8(b, 7));
+// Compares the 16 signed 8-bit integers in a and the 16 signed 8-bit integers
+// in b for lesser than.
+// https://msdn.microsoft.com/en-us/library/windows/desktop/9s46csht(v=vs.90).aspx
+FORCE_INLINE __m128i _mm_cmplt_epi8(__m128i a, __m128i b)
+{
+ return vreinterpretq_m128i_u8(
+ vcltq_s8(vreinterpretq_s8_m128i(a), vreinterpretq_s8_m128i(b)));
+}
- // (b == 0) ? 0xFF : 0
+// Compare packed double-precision (64-bit) floating-point elements in a and b
+// for less-than, and store the results in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmplt_pd
+FORCE_INLINE __m128d _mm_cmplt_pd(__m128d a, __m128d b)
+{
#if defined(__aarch64__)
- int8x16_t zeroMask = vreinterpretq_s8_u8(vceqzq_s8(b));
+ return vreinterpretq_m128d_u64(
+ vcltq_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(b)));
#else
- int8x16_t zeroMask = vreinterpretq_s8_u8(vceqq_s8(b, vdupq_n_s8(0)));
+ uint64_t a0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(a));
+ uint64_t a1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(a));
+ uint64_t b0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(b));
+ uint64_t b1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(b));
+ uint64_t d[2];
+ d[0] = (*(double *) &a0) < (*(double *) &b0) ? ~UINT64_C(0) : UINT64_C(0);
+ d[1] = (*(double *) &a1) < (*(double *) &b1) ? ~UINT64_C(0) : UINT64_C(0);
+
+ return vreinterpretq_m128d_u64(vld1q_u64(d));
#endif
-
- // bitwise select either a or nagative 'a' (vnegq_s8(a) return nagative 'a')
- // based on ltMask
- int8x16_t masked = vbslq_s8(ltMask, vnegq_s8(a), a);
- // res = masked & (~zeroMask)
- int8x16_t res = vbicq_s8(masked, zeroMask);
-
- return vreinterpretq_m128i_s8(res);
}
-// Negate packed 16-bit integers in a when the corresponding signed
-// 16-bit integer in b is negative, and store the results in dst.
-// Element in dst are zeroed out when the corresponding element
-// in b is zero.
-//
-// for i in 0..7
-// if b[i] < 0
-// r[i] := -a[i]
-// else if b[i] == 0
-// r[i] := 0
-// else
-// r[i] := a[i]
-// fi
-// done
-FORCE_INLINE __m128i _mm_sign_epi16(__m128i _a, __m128i _b)
+// Compare the lower double-precision (64-bit) floating-point elements in a and
+// b for less-than, store the result in the lower element of dst, and copy the
+// upper element from a to the upper element of dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmplt_sd
+FORCE_INLINE __m128d _mm_cmplt_sd(__m128d a, __m128d b)
{
- int16x8_t a = vreinterpretq_s16_m128i(_a);
- int16x8_t b = vreinterpretq_s16_m128i(_b);
-
- // signed shift right: faster than vclt
- // (b < 0) ? 0xFFFF : 0
- uint16x8_t ltMask = vreinterpretq_u16_s16(vshrq_n_s16(b, 15));
- // (b == 0) ? 0xFFFF : 0
#if defined(__aarch64__)
- int16x8_t zeroMask = vreinterpretq_s16_u16(vceqzq_s16(b));
+ return _mm_move_sd(a, _mm_cmplt_pd(a, b));
#else
- int16x8_t zeroMask = vreinterpretq_s16_u16(vceqq_s16(b, vdupq_n_s16(0)));
+ uint64_t a0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(a));
+ uint64_t a1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(a));
+ uint64_t b0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(b));
+ uint64_t d[2];
+ d[0] = (*(double *) &a0) < (*(double *) &b0) ? ~UINT64_C(0) : UINT64_C(0);
+ d[1] = a1;
+
+ return vreinterpretq_m128d_u64(vld1q_u64(d));
#endif
-
- // bitwise select either a or negative 'a' (vnegq_s16(a) equals to negative
- // 'a') based on ltMask
- int16x8_t masked = vbslq_s16(ltMask, vnegq_s16(a), a);
- // res = masked & (~zeroMask)
- int16x8_t res = vbicq_s16(masked, zeroMask);
- return vreinterpretq_m128i_s16(res);
}
-// Negate packed 32-bit integers in a when the corresponding signed
-// 32-bit integer in b is negative, and store the results in dst.
-// Element in dst are zeroed out when the corresponding element
-// in b is zero.
-//
-// for i in 0..3
-// if b[i] < 0
-// r[i] := -a[i]
-// else if b[i] == 0
-// r[i] := 0
-// else
-// r[i] := a[i]
-// fi
-// done
-FORCE_INLINE __m128i _mm_sign_epi32(__m128i _a, __m128i _b)
+// Compare packed double-precision (64-bit) floating-point elements in a and b
+// for not-equal, and store the results in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmpneq_pd
+FORCE_INLINE __m128d _mm_cmpneq_pd(__m128d a, __m128d b)
{
- int32x4_t a = vreinterpretq_s32_m128i(_a);
- int32x4_t b = vreinterpretq_s32_m128i(_b);
-
- // signed shift right: faster than vclt
- // (b < 0) ? 0xFFFFFFFF : 0
- uint32x4_t ltMask = vreinterpretq_u32_s32(vshrq_n_s32(b, 31));
-
- // (b == 0) ? 0xFFFFFFFF : 0
#if defined(__aarch64__)
- int32x4_t zeroMask = vreinterpretq_s32_u32(vceqzq_s32(b));
+ return vreinterpretq_m128d_s32(vmvnq_s32(vreinterpretq_s32_u64(
+ vceqq_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(b)))));
#else
- int32x4_t zeroMask = vreinterpretq_s32_u32(vceqq_s32(b, vdupq_n_s32(0)));
+ // (a == b) -> (a_lo == b_lo) && (a_hi == b_hi)
+ uint32x4_t cmp =
+ vceqq_u32(vreinterpretq_u32_m128d(a), vreinterpretq_u32_m128d(b));
+ uint32x4_t swapped = vrev64q_u32(cmp);
+ return vreinterpretq_m128d_u32(vmvnq_u32(vandq_u32(cmp, swapped)));
#endif
-
- // bitwise select either a or negative 'a' (vnegq_s32(a) equals to negative
- // 'a') based on ltMask
- int32x4_t masked = vbslq_s32(ltMask, vnegq_s32(a), a);
- // res = masked & (~zeroMask)
- int32x4_t res = vbicq_s32(masked, zeroMask);
- return vreinterpretq_m128i_s32(res);
}
-// Negate packed 16-bit integers in a when the corresponding signed 16-bit
-// integer in b is negative, and store the results in dst. Element in dst are
-// zeroed out when the corresponding element in b is zero.
-//
-// FOR j := 0 to 3
-// i := j*16
-// IF b[i+15:i] < 0
-// dst[i+15:i] := -(a[i+15:i])
-// ELSE IF b[i+15:i] == 0
-// dst[i+15:i] := 0
-// ELSE
-// dst[i+15:i] := a[i+15:i]
-// FI
-// ENDFOR
-//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_sign_pi16
-FORCE_INLINE __m64 _mm_sign_pi16(__m64 _a, __m64 _b)
+// Compare the lower double-precision (64-bit) floating-point elements in a and
+// b for not-equal, store the result in the lower element of dst, and copy the
+// upper element from a to the upper element of dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmpneq_sd
+FORCE_INLINE __m128d _mm_cmpneq_sd(__m128d a, __m128d b)
{
- int16x4_t a = vreinterpret_s16_m64(_a);
- int16x4_t b = vreinterpret_s16_m64(_b);
-
- // signed shift right: faster than vclt
- // (b < 0) ? 0xFFFF : 0
- uint16x4_t ltMask = vreinterpret_u16_s16(vshr_n_s16(b, 15));
+ return _mm_move_sd(a, _mm_cmpneq_pd(a, b));
+}
- // (b == 0) ? 0xFFFF : 0
+// Compare packed double-precision (64-bit) floating-point elements in a and b
+// for not-greater-than-or-equal, and store the results in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmpnge_pd
+FORCE_INLINE __m128d _mm_cmpnge_pd(__m128d a, __m128d b)
+{
#if defined(__aarch64__)
- int16x4_t zeroMask = vreinterpret_s16_u16(vceqz_s16(b));
+ return vreinterpretq_m128d_u64(veorq_u64(
+ vcgeq_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(b)),
+ vdupq_n_u64(UINT64_MAX)));
#else
- int16x4_t zeroMask = vreinterpret_s16_u16(vceq_s16(b, vdup_n_s16(0)));
+ uint64_t a0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(a));
+ uint64_t a1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(a));
+ uint64_t b0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(b));
+ uint64_t b1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(b));
+ uint64_t d[2];
+ d[0] =
+ !((*(double *) &a0) >= (*(double *) &b0)) ? ~UINT64_C(0) : UINT64_C(0);
+ d[1] =
+ !((*(double *) &a1) >= (*(double *) &b1)) ? ~UINT64_C(0) : UINT64_C(0);
+
+ return vreinterpretq_m128d_u64(vld1q_u64(d));
#endif
-
- // bitwise select either a or nagative 'a' (vneg_s16(a) return nagative 'a')
- // based on ltMask
- int16x4_t masked = vbsl_s16(ltMask, vneg_s16(a), a);
- // res = masked & (~zeroMask)
- int16x4_t res = vbic_s16(masked, zeroMask);
-
- return vreinterpret_m64_s16(res);
}
-// Negate packed 32-bit integers in a when the corresponding signed 32-bit
-// integer in b is negative, and store the results in dst. Element in dst are
-// zeroed out when the corresponding element in b is zero.
-//
-// FOR j := 0 to 1
-// i := j*32
-// IF b[i+31:i] < 0
-// dst[i+31:i] := -(a[i+31:i])
-// ELSE IF b[i+31:i] == 0
-// dst[i+31:i] := 0
-// ELSE
-// dst[i+31:i] := a[i+31:i]
-// FI
-// ENDFOR
-//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_sign_pi32
-FORCE_INLINE __m64 _mm_sign_pi32(__m64 _a, __m64 _b)
+// Compare the lower double-precision (64-bit) floating-point elements in a and
+// b for not-greater-than-or-equal, store the result in the lower element of
+// dst, and copy the upper element from a to the upper element of dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmpnge_sd
+FORCE_INLINE __m128d _mm_cmpnge_sd(__m128d a, __m128d b)
{
- int32x2_t a = vreinterpret_s32_m64(_a);
- int32x2_t b = vreinterpret_s32_m64(_b);
-
- // signed shift right: faster than vclt
- // (b < 0) ? 0xFFFFFFFF : 0
- uint32x2_t ltMask = vreinterpret_u32_s32(vshr_n_s32(b, 31));
+ return _mm_move_sd(a, _mm_cmpnge_pd(a, b));
+}
- // (b == 0) ? 0xFFFFFFFF : 0
+// Compare packed double-precision (64-bit) floating-point elements in a and b
+// for not-greater-than, and store the results in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_cmpngt_pd
+FORCE_INLINE __m128d _mm_cmpngt_pd(__m128d a, __m128d b)
+{
#if defined(__aarch64__)
- int32x2_t zeroMask = vreinterpret_s32_u32(vceqz_s32(b));
+ return vreinterpretq_m128d_u64(veorq_u64(
+ vcgtq_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(b)),
+ vdupq_n_u64(UINT64_MAX)));
#else
- int32x2_t zeroMask = vreinterpret_s32_u32(vceq_s32(b, vdup_n_s32(0)));
+ uint64_t a0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(a));
+ uint64_t a1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(a));
+ uint64_t b0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(b));
+ uint64_t b1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(b));
+ uint64_t d[2];
+ d[0] =
+ !((*(double *) &a0) > (*(double *) &b0)) ? ~UINT64_C(0) : UINT64_C(0);
+ d[1] =
+ !((*(double *) &a1) > (*(double *) &b1)) ? ~UINT64_C(0) : UINT64_C(0);
+
+ return vreinterpretq_m128d_u64(vld1q_u64(d));
#endif
-
- // bitwise select either a or nagative 'a' (vneg_s32(a) return nagative 'a')
- // based on ltMask
- int32x2_t masked = vbsl_s32(ltMask, vneg_s32(a), a);
- // res = masked & (~zeroMask)
- int32x2_t res = vbic_s32(masked, zeroMask);
-
- return vreinterpret_m64_s32(res);
}
-// Negate packed 8-bit integers in a when the corresponding signed 8-bit integer
-// in b is negative, and store the results in dst. Element in dst are zeroed out
-// when the corresponding element in b is zero.
-//
-// FOR j := 0 to 7
-// i := j*8
-// IF b[i+7:i] < 0
-// dst[i+7:i] := -(a[i+7:i])
-// ELSE IF b[i+7:i] == 0
-// dst[i+7:i] := 0
-// ELSE
-// dst[i+7:i] := a[i+7:i]
-// FI
-// ENDFOR
-//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_sign_pi8
-FORCE_INLINE __m64 _mm_sign_pi8(__m64 _a, __m64 _b)
+// Compare the lower double-precision (64-bit) floating-point elements in a and
+// b for not-greater-than, store the result in the lower element of dst, and
+// copy the upper element from a to the upper element of dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmpngt_sd
+FORCE_INLINE __m128d _mm_cmpngt_sd(__m128d a, __m128d b)
{
- int8x8_t a = vreinterpret_s8_m64(_a);
- int8x8_t b = vreinterpret_s8_m64(_b);
-
- // signed shift right: faster than vclt
- // (b < 0) ? 0xFF : 0
- uint8x8_t ltMask = vreinterpret_u8_s8(vshr_n_s8(b, 7));
+ return _mm_move_sd(a, _mm_cmpngt_pd(a, b));
+}
- // (b == 0) ? 0xFF : 0
+// Compare packed double-precision (64-bit) floating-point elements in a and b
+// for not-less-than-or-equal, and store the results in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmpnle_pd
+FORCE_INLINE __m128d _mm_cmpnle_pd(__m128d a, __m128d b)
+{
#if defined(__aarch64__)
- int8x8_t zeroMask = vreinterpret_s8_u8(vceqz_s8(b));
+ return vreinterpretq_m128d_u64(veorq_u64(
+ vcleq_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(b)),
+ vdupq_n_u64(UINT64_MAX)));
#else
- int8x8_t zeroMask = vreinterpret_s8_u8(vceq_s8(b, vdup_n_s8(0)));
+ uint64_t a0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(a));
+ uint64_t a1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(a));
+ uint64_t b0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(b));
+ uint64_t b1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(b));
+ uint64_t d[2];
+ d[0] =
+ !((*(double *) &a0) <= (*(double *) &b0)) ? ~UINT64_C(0) : UINT64_C(0);
+ d[1] =
+ !((*(double *) &a1) <= (*(double *) &b1)) ? ~UINT64_C(0) : UINT64_C(0);
+
+ return vreinterpretq_m128d_u64(vld1q_u64(d));
#endif
-
- // bitwise select either a or nagative 'a' (vneg_s8(a) return nagative 'a')
- // based on ltMask
- int8x8_t masked = vbsl_s8(ltMask, vneg_s8(a), a);
- // res = masked & (~zeroMask)
- int8x8_t res = vbic_s8(masked, zeroMask);
-
- return vreinterpret_m64_s8(res);
}
-// Average packed unsigned 16-bit integers in a and b, and store the results in
-// dst.
-//
-// FOR j := 0 to 3
-// i := j*16
-// dst[i+15:i] := (a[i+15:i] + b[i+15:i] + 1) >> 1
-// ENDFOR
-//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_avg_pu16
-FORCE_INLINE __m64 _mm_avg_pu16(__m64 a, __m64 b)
+// Compare the lower double-precision (64-bit) floating-point elements in a and
+// b for not-less-than-or-equal, store the result in the lower element of dst,
+// and copy the upper element from a to the upper element of dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmpnle_sd
+FORCE_INLINE __m128d _mm_cmpnle_sd(__m128d a, __m128d b)
{
- return vreinterpret_m64_u16(
- vrhadd_u16(vreinterpret_u16_m64(a), vreinterpret_u16_m64(b)));
+ return _mm_move_sd(a, _mm_cmpnle_pd(a, b));
}
-// Average packed unsigned 8-bit integers in a and b, and store the results in
-// dst.
-//
-// FOR j := 0 to 7
-// i := j*8
-// dst[i+7:i] := (a[i+7:i] + b[i+7:i] + 1) >> 1
-// ENDFOR
-//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_avg_pu8
-FORCE_INLINE __m64 _mm_avg_pu8(__m64 a, __m64 b)
+// Compare packed double-precision (64-bit) floating-point elements in a and b
+// for not-less-than, and store the results in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmpnlt_pd
+FORCE_INLINE __m128d _mm_cmpnlt_pd(__m128d a, __m128d b)
{
- return vreinterpret_m64_u8(
- vrhadd_u8(vreinterpret_u8_m64(a), vreinterpret_u8_m64(b)));
+#if defined(__aarch64__)
+ return vreinterpretq_m128d_u64(veorq_u64(
+ vcltq_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(b)),
+ vdupq_n_u64(UINT64_MAX)));
+#else
+ uint64_t a0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(a));
+ uint64_t a1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(a));
+ uint64_t b0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(b));
+ uint64_t b1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(b));
+ uint64_t d[2];
+ d[0] =
+ !((*(double *) &a0) < (*(double *) &b0)) ? ~UINT64_C(0) : UINT64_C(0);
+ d[1] =
+ !((*(double *) &a1) < (*(double *) &b1)) ? ~UINT64_C(0) : UINT64_C(0);
+
+ return vreinterpretq_m128d_u64(vld1q_u64(d));
+#endif
}
-// Average packed unsigned 8-bit integers in a and b, and store the results in
-// dst.
-//
-// FOR j := 0 to 7
-// i := j*8
-// dst[i+7:i] := (a[i+7:i] + b[i+7:i] + 1) >> 1
-// ENDFOR
-//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_m_pavgb
-#define _m_pavgb(a, b) _mm_avg_pu8(a, b)
-
-// Average packed unsigned 16-bit integers in a and b, and store the results in
-// dst.
-//
-// FOR j := 0 to 3
-// i := j*16
-// dst[i+15:i] := (a[i+15:i] + b[i+15:i] + 1) >> 1
-// ENDFOR
-//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_m_pavgw
-#define _m_pavgw(a, b) _mm_avg_pu16(a, b)
-
-// Extract a 16-bit integer from a, selected with imm8, and store the result in
-// the lower element of dst.
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_m_pextrw
-#define _m_pextrw(a, imm) _mm_extract_pi16(a, imm)
-
-// Copy a to dst, and insert the 16-bit integer i into dst at the location
-// specified by imm8.
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=m_pinsrw
-#define _m_pinsrw(a, i, imm) _mm_insert_pi16(a, i, imm)
-
-// Compare packed signed 16-bit integers in a and b, and store packed maximum
-// values in dst.
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_m_pmaxsw
-#define _m_pmaxsw(a, b) _mm_max_pi16(a, b)
-
-// Compare packed unsigned 8-bit integers in a and b, and store packed maximum
-// values in dst.
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_m_pmaxub
-#define _m_pmaxub(a, b) _mm_max_pu8(a, b)
-
-// Compare packed signed 16-bit integers in a and b, and store packed minimum
-// values in dst.
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_m_pminsw
-#define _m_pminsw(a, b) _mm_min_pi16(a, b)
-
-// Compare packed unsigned 8-bit integers in a and b, and store packed minimum
-// values in dst.
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_m_pminub
-#define _m_pminub(a, b) _mm_min_pu8(a, b)
-
-// Computes the average of the 16 unsigned 8-bit integers in a and the 16
-// unsigned 8-bit integers in b and rounds.
-//
-// r0 := (a0 + b0) / 2
-// r1 := (a1 + b1) / 2
-// ...
-// r15 := (a15 + b15) / 2
-//
-// https://msdn.microsoft.com/en-us/library/vstudio/8zwh554a(v%3dvs.90).aspx
-FORCE_INLINE __m128i _mm_avg_epu8(__m128i a, __m128i b)
+// Compare the lower double-precision (64-bit) floating-point elements in a and
+// b for not-less-than, store the result in the lower element of dst, and copy
+// the upper element from a to the upper element of dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmpnlt_sd
+FORCE_INLINE __m128d _mm_cmpnlt_sd(__m128d a, __m128d b)
{
- return vreinterpretq_m128i_u8(
- vrhaddq_u8(vreinterpretq_u8_m128i(a), vreinterpretq_u8_m128i(b)));
+ return _mm_move_sd(a, _mm_cmpnlt_pd(a, b));
}
-// Computes the average of the 8 unsigned 16-bit integers in a and the 8
-// unsigned 16-bit integers in b and rounds.
-//
-// r0 := (a0 + b0) / 2
-// r1 := (a1 + b1) / 2
-// ...
-// r7 := (a7 + b7) / 2
-//
-// https://msdn.microsoft.com/en-us/library/vstudio/y13ca3c8(v=vs.90).aspx
-FORCE_INLINE __m128i _mm_avg_epu16(__m128i a, __m128i b)
+// Compare packed double-precision (64-bit) floating-point elements in a and b
+// to see if neither is NaN, and store the results in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmpord_pd
+FORCE_INLINE __m128d _mm_cmpord_pd(__m128d a, __m128d b)
{
- return (__m128i) vrhaddq_u16(vreinterpretq_u16_m128i(a),
- vreinterpretq_u16_m128i(b));
+#if defined(__aarch64__)
+ // Excluding NaNs, any two floating point numbers can be compared.
+ uint64x2_t not_nan_a =
+ vceqq_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(a));
+ uint64x2_t not_nan_b =
+ vceqq_f64(vreinterpretq_f64_m128d(b), vreinterpretq_f64_m128d(b));
+ return vreinterpretq_m128d_u64(vandq_u64(not_nan_a, not_nan_b));
+#else
+ uint64_t a0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(a));
+ uint64_t a1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(a));
+ uint64_t b0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(b));
+ uint64_t b1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(b));
+ uint64_t d[2];
+ d[0] = ((*(double *) &a0) == (*(double *) &a0) &&
+ (*(double *) &b0) == (*(double *) &b0))
+ ? ~UINT64_C(0)
+ : UINT64_C(0);
+ d[1] = ((*(double *) &a1) == (*(double *) &a1) &&
+ (*(double *) &b1) == (*(double *) &b1))
+ ? ~UINT64_C(0)
+ : UINT64_C(0);
+
+ return vreinterpretq_m128d_u64(vld1q_u64(d));
+#endif
}
-// Adds the four single-precision, floating-point values of a and b.
-//
-// r0 := a0 + b0
-// r1 := a1 + b1
-// r2 := a2 + b2
-// r3 := a3 + b3
-//
-// https://msdn.microsoft.com/en-us/library/vstudio/c9848chc(v=vs.100).aspx
-FORCE_INLINE __m128 _mm_add_ps(__m128 a, __m128 b)
+// Compare the lower double-precision (64-bit) floating-point elements in a and
+// b to see if neither is NaN, store the result in the lower element of dst, and
+// copy the upper element from a to the upper element of dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmpord_sd
+FORCE_INLINE __m128d _mm_cmpord_sd(__m128d a, __m128d b)
{
- return vreinterpretq_m128_f32(
- vaddq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b)));
+#if defined(__aarch64__)
+ return _mm_move_sd(a, _mm_cmpord_pd(a, b));
+#else
+ uint64_t a0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(a));
+ uint64_t b0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(b));
+ uint64_t a1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(a));
+ uint64_t d[2];
+ d[0] = ((*(double *) &a0) == (*(double *) &a0) &&
+ (*(double *) &b0) == (*(double *) &b0))
+ ? ~UINT64_C(0)
+ : UINT64_C(0);
+ d[1] = a1;
+
+ return vreinterpretq_m128d_u64(vld1q_u64(d));
+#endif
}
-// Add packed double-precision (64-bit) floating-point elements in a and b, and
-// store the results in dst.
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_add_pd
-FORCE_INLINE __m128d _mm_add_pd(__m128d a, __m128d b)
+// Compare packed double-precision (64-bit) floating-point elements in a and b
+// to see if either is NaN, and store the results in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmpunord_pd
+FORCE_INLINE __m128d _mm_cmpunord_pd(__m128d a, __m128d b)
{
#if defined(__aarch64__)
- return vreinterpretq_m128d_f64(
- vaddq_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(b)));
+ // Two NaNs are not equal in comparison operation.
+ uint64x2_t not_nan_a =
+ vceqq_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(a));
+ uint64x2_t not_nan_b =
+ vceqq_f64(vreinterpretq_f64_m128d(b), vreinterpretq_f64_m128d(b));
+ return vreinterpretq_m128d_s32(
+ vmvnq_s32(vreinterpretq_s32_u64(vandq_u64(not_nan_a, not_nan_b))));
#else
- double *da = (double *) &a;
- double *db = (double *) &b;
- double c[2];
- c[0] = da[0] + db[0];
- c[1] = da[1] + db[1];
- return vld1q_f32((float32_t *) c);
+ uint64_t a0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(a));
+ uint64_t a1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(a));
+ uint64_t b0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(b));
+ uint64_t b1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(b));
+ uint64_t d[2];
+ d[0] = ((*(double *) &a0) == (*(double *) &a0) &&
+ (*(double *) &b0) == (*(double *) &b0))
+ ? UINT64_C(0)
+ : ~UINT64_C(0);
+ d[1] = ((*(double *) &a1) == (*(double *) &a1) &&
+ (*(double *) &b1) == (*(double *) &b1))
+ ? UINT64_C(0)
+ : ~UINT64_C(0);
+
+ return vreinterpretq_m128d_u64(vld1q_u64(d));
#endif
}
-// Add the lower double-precision (64-bit) floating-point element in a and b,
-// store the result in the lower element of dst, and copy the upper element from
-// a to the upper element of dst.
-//
-// dst[63:0] := a[63:0] + b[63:0]
-// dst[127:64] := a[127:64]
-//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_add_sd
-FORCE_INLINE __m128d _mm_add_sd(__m128d a, __m128d b)
+// Compare the lower double-precision (64-bit) floating-point elements in a and
+// b to see if either is NaN, store the result in the lower element of dst, and
+// copy the upper element from a to the upper element of dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmpunord_sd
+FORCE_INLINE __m128d _mm_cmpunord_sd(__m128d a, __m128d b)
{
#if defined(__aarch64__)
- return _mm_move_sd(a, _mm_add_pd(a, b));
+ return _mm_move_sd(a, _mm_cmpunord_pd(a, b));
#else
- double *da = (double *) &a;
- double *db = (double *) &b;
- double c[2];
- c[0] = da[0] + db[0];
- c[1] = da[1];
- return vld1q_f32((float32_t *) c);
+ uint64_t a0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(a));
+ uint64_t b0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(b));
+ uint64_t a1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(a));
+ uint64_t d[2];
+ d[0] = ((*(double *) &a0) == (*(double *) &a0) &&
+ (*(double *) &b0) == (*(double *) &b0))
+ ? UINT64_C(0)
+ : ~UINT64_C(0);
+ d[1] = a1;
+
+ return vreinterpretq_m128d_u64(vld1q_u64(d));
#endif
}
-// Add 64-bit integers a and b, and store the result in dst.
-//
-// dst[63:0] := a[63:0] + b[63:0]
-//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_add_si64
-FORCE_INLINE __m64 _mm_add_si64(__m64 a, __m64 b)
+// Compare the lower double-precision (64-bit) floating-point element in a and b
+// for greater-than-or-equal, and return the boolean result (0 or 1).
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_comige_sd
+FORCE_INLINE int _mm_comige_sd(__m128d a, __m128d b)
{
- return vreinterpret_m64_s64(
- vadd_s64(vreinterpret_s64_m64(a), vreinterpret_s64_m64(b)));
-}
+#if defined(__aarch64__)
+ return vgetq_lane_u64(vcgeq_f64(a, b), 0) & 0x1;
+#else
+ uint64_t a0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(a));
+ uint64_t b0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(b));
-// adds the scalar single-precision floating point values of a and b.
-// https://msdn.microsoft.com/en-us/library/be94x2y6(v=vs.100).aspx
-FORCE_INLINE __m128 _mm_add_ss(__m128 a, __m128 b)
-{
- float32_t b0 = vgetq_lane_f32(vreinterpretq_f32_m128(b), 0);
- float32x4_t value = vsetq_lane_f32(b0, vdupq_n_f32(0), 0);
- // the upper values in the result must be the remnants of <a>.
- return vreinterpretq_m128_f32(vaddq_f32(a, value));
+ return (*(double *) &a0 >= *(double *) &b0);
+#endif
}
-// Adds the 4 signed or unsigned 64-bit integers in a to the 4 signed or
-// unsigned 32-bit integers in b.
-// https://msdn.microsoft.com/en-us/library/vstudio/09xs4fkk(v=vs.100).aspx
-FORCE_INLINE __m128i _mm_add_epi64(__m128i a, __m128i b)
+// Compare the lower double-precision (64-bit) floating-point element in a and b
+// for greater-than, and return the boolean result (0 or 1).
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_comigt_sd
+FORCE_INLINE int _mm_comigt_sd(__m128d a, __m128d b)
{
- return vreinterpretq_m128i_s64(
- vaddq_s64(vreinterpretq_s64_m128i(a), vreinterpretq_s64_m128i(b)));
+#if defined(__aarch64__)
+ return vgetq_lane_u64(vcgtq_f64(a, b), 0) & 0x1;
+#else
+ uint64_t a0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(a));
+ uint64_t b0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(b));
+
+ return (*(double *) &a0 > *(double *) &b0);
+#endif
}
-// Adds the 4 signed or unsigned 32-bit integers in a to the 4 signed or
-// unsigned 32-bit integers in b.
-//
-// r0 := a0 + b0
-// r1 := a1 + b1
-// r2 := a2 + b2
-// r3 := a3 + b3
-//
-// https://msdn.microsoft.com/en-us/library/vstudio/09xs4fkk(v=vs.100).aspx
-FORCE_INLINE __m128i _mm_add_epi32(__m128i a, __m128i b)
+// Compare the lower double-precision (64-bit) floating-point element in a and b
+// for less-than-or-equal, and return the boolean result (0 or 1).
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_comile_sd
+FORCE_INLINE int _mm_comile_sd(__m128d a, __m128d b)
{
- return vreinterpretq_m128i_s32(
- vaddq_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(b)));
+#if defined(__aarch64__)
+ return vgetq_lane_u64(vcleq_f64(a, b), 0) & 0x1;
+#else
+ uint64_t a0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(a));
+ uint64_t b0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(b));
+
+ return (*(double *) &a0 <= *(double *) &b0);
+#endif
}
-// Adds the 8 signed or unsigned 16-bit integers in a to the 8 signed or
-// unsigned 16-bit integers in b.
-// https://msdn.microsoft.com/en-us/library/fceha5k4(v=vs.100).aspx
-FORCE_INLINE __m128i _mm_add_epi16(__m128i a, __m128i b)
+// Compare the lower double-precision (64-bit) floating-point element in a and b
+// for less-than, and return the boolean result (0 or 1).
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_comilt_sd
+FORCE_INLINE int _mm_comilt_sd(__m128d a, __m128d b)
{
- return vreinterpretq_m128i_s16(
- vaddq_s16(vreinterpretq_s16_m128i(a), vreinterpretq_s16_m128i(b)));
+#if defined(__aarch64__)
+ return vgetq_lane_u64(vcltq_f64(a, b), 0) & 0x1;
+#else
+ uint64_t a0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(a));
+ uint64_t b0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(b));
+
+ return (*(double *) &a0 < *(double *) &b0);
+#endif
}
-// Adds the 16 signed or unsigned 8-bit integers in a to the 16 signed or
-// unsigned 8-bit integers in b.
-// https://technet.microsoft.com/en-us/subscriptions/yc7tcyzs(v=vs.90)
-FORCE_INLINE __m128i _mm_add_epi8(__m128i a, __m128i b)
+// Compare the lower double-precision (64-bit) floating-point element in a and b
+// for equality, and return the boolean result (0 or 1).
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_comieq_sd
+FORCE_INLINE int _mm_comieq_sd(__m128d a, __m128d b)
{
- return vreinterpretq_m128i_s8(
- vaddq_s8(vreinterpretq_s8_m128i(a), vreinterpretq_s8_m128i(b)));
+#if defined(__aarch64__)
+ return vgetq_lane_u64(vceqq_f64(a, b), 0) & 0x1;
+#else
+ uint32x4_t a_not_nan =
+ vceqq_u32(vreinterpretq_u32_m128d(a), vreinterpretq_u32_m128d(a));
+ uint32x4_t b_not_nan =
+ vceqq_u32(vreinterpretq_u32_m128d(b), vreinterpretq_u32_m128d(b));
+ uint32x4_t a_and_b_not_nan = vandq_u32(a_not_nan, b_not_nan);
+ uint32x4_t a_eq_b =
+ vceqq_u32(vreinterpretq_u32_m128d(a), vreinterpretq_u32_m128d(b));
+ uint64x2_t and_results = vandq_u64(vreinterpretq_u64_u32(a_and_b_not_nan),
+ vreinterpretq_u64_u32(a_eq_b));
+ return vgetq_lane_u64(and_results, 0) & 0x1;
+#endif
}
-// Adds the 8 signed 16-bit integers in a to the 8 signed 16-bit integers in b
-// and saturates.
-//
-// r0 := SignedSaturate(a0 + b0)
-// r1 := SignedSaturate(a1 + b1)
-// ...
-// r7 := SignedSaturate(a7 + b7)
-//
-// https://msdn.microsoft.com/en-us/library/1a306ef8(v=vs.100).aspx
-FORCE_INLINE __m128i _mm_adds_epi16(__m128i a, __m128i b)
+// Compare the lower double-precision (64-bit) floating-point element in a and b
+// for not-equal, and return the boolean result (0 or 1).
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_comineq_sd
+FORCE_INLINE int _mm_comineq_sd(__m128d a, __m128d b)
{
- return vreinterpretq_m128i_s16(
- vqaddq_s16(vreinterpretq_s16_m128i(a), vreinterpretq_s16_m128i(b)));
+ return !_mm_comieq_sd(a, b);
}
-// Add packed signed 8-bit integers in a and b using saturation, and store the
-// results in dst.
+// Convert packed signed 32-bit integers in a to packed double-precision
+// (64-bit) floating-point elements, and store the results in dst.
//
-// FOR j := 0 to 15
-// i := j*8
-// dst[i+7:i] := Saturate8( a[i+7:i] + b[i+7:i] )
+// FOR j := 0 to 1
+// i := j*32
+// m := j*64
+// dst[m+63:m] := Convert_Int32_To_FP64(a[i+31:i])
// ENDFOR
//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_adds_epi8
-FORCE_INLINE __m128i _mm_adds_epi8(__m128i a, __m128i b)
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtepi32_pd
+FORCE_INLINE __m128d _mm_cvtepi32_pd(__m128i a)
{
- return vreinterpretq_m128i_s8(
- vqaddq_s8(vreinterpretq_s8_m128i(a), vreinterpretq_s8_m128i(b)));
+#if defined(__aarch64__)
+ return vreinterpretq_m128d_f64(
+ vcvtq_f64_s64(vmovl_s32(vget_low_s32(vreinterpretq_s32_m128i(a)))));
+#else
+ double a0 = (double) vgetq_lane_s32(vreinterpretq_s32_m128i(a), 0);
+ double a1 = (double) vgetq_lane_s32(vreinterpretq_s32_m128i(a), 1);
+ return _mm_set_pd(a1, a0);
+#endif
}
-// Adds the 16 unsigned 8-bit integers in a to the 16 unsigned 8-bit integers in
-// b and saturates..
-// https://msdn.microsoft.com/en-us/library/9hahyddy(v=vs.100).aspx
-FORCE_INLINE __m128i _mm_adds_epu8(__m128i a, __m128i b)
+// Converts the four signed 32-bit integer values of a to single-precision,
+// floating-point values
+// https://msdn.microsoft.com/en-us/library/vstudio/36bwxcx5(v=vs.100).aspx
+FORCE_INLINE __m128 _mm_cvtepi32_ps(__m128i a)
{
- return vreinterpretq_m128i_u8(
- vqaddq_u8(vreinterpretq_u8_m128i(a), vreinterpretq_u8_m128i(b)));
+ return vreinterpretq_m128_f32(vcvtq_f32_s32(vreinterpretq_s32_m128i(a)));
}
-// Multiplies the 8 signed or unsigned 16-bit integers from a by the 8 signed or
-// unsigned 16-bit integers from b.
+// Convert packed double-precision (64-bit) floating-point elements in a to
+// packed 32-bit integers, and store the results in dst.
//
-// r0 := (a0 * b0)[15:0]
-// r1 := (a1 * b1)[15:0]
-// ...
-// r7 := (a7 * b7)[15:0]
+// FOR j := 0 to 1
+// i := 32*j
+// k := 64*j
+// dst[i+31:i] := Convert_FP64_To_Int32(a[k+63:k])
+// ENDFOR
//
-// https://msdn.microsoft.com/en-us/library/vstudio/9ks1472s(v=vs.100).aspx
-FORCE_INLINE __m128i _mm_mullo_epi16(__m128i a, __m128i b)
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtpd_epi32
+FORCE_INLINE __m128i _mm_cvtpd_epi32(__m128d a)
{
- return vreinterpretq_m128i_s16(
- vmulq_s16(vreinterpretq_s16_m128i(a), vreinterpretq_s16_m128i(b)));
+ __m128d rnd = _mm_round_pd(a, _MM_FROUND_CUR_DIRECTION);
+ double d0 = ((double *) &rnd)[0];
+ double d1 = ((double *) &rnd)[1];
+ return _mm_set_epi32(0, 0, (int32_t) d1, (int32_t) d0);
}
-// Multiplies the 4 signed or unsigned 32-bit integers from a by the 4 signed or
-// unsigned 32-bit integers from b.
-// https://msdn.microsoft.com/en-us/library/vstudio/bb531409(v=vs.100).aspx
-FORCE_INLINE __m128i _mm_mullo_epi32(__m128i a, __m128i b)
+// Convert packed double-precision (64-bit) floating-point elements in a to
+// packed 32-bit integers, and store the results in dst.
+//
+// FOR j := 0 to 1
+// i := 32*j
+// k := 64*j
+// dst[i+31:i] := Convert_FP64_To_Int32(a[k+63:k])
+// ENDFOR
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtpd_pi32
+FORCE_INLINE __m64 _mm_cvtpd_pi32(__m128d a)
{
- return vreinterpretq_m128i_s32(
- vmulq_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(b)));
+ __m128d rnd = _mm_round_pd(a, _MM_FROUND_CUR_DIRECTION);
+ double d0 = ((double *) &rnd)[0];
+ double d1 = ((double *) &rnd)[1];
+ int32_t ALIGN_STRUCT(16) data[2] = {(int32_t) d0, (int32_t) d1};
+ return vreinterpret_m64_s32(vld1_s32(data));
}
-// Multiply the packed unsigned 16-bit integers in a and b, producing
-// intermediate 32-bit integers, and store the high 16 bits of the intermediate
-// integers in dst.
+// Convert packed double-precision (64-bit) floating-point elements in a to
+// packed single-precision (32-bit) floating-point elements, and store the
+// results in dst.
//
-// FOR j := 0 to 3
-// i := j*16
-// tmp[31:0] := a[i+15:i] * b[i+15:i]
-// dst[i+15:i] := tmp[31:16]
+// FOR j := 0 to 1
+// i := 32*j
+// k := 64*j
+// dst[i+31:i] := Convert_FP64_To_FP32(a[k+64:k])
// ENDFOR
+// dst[127:64] := 0
//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_m_pmulhuw
-#define _m_pmulhuw(a, b) _mm_mulhi_pu16(a, b)
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtpd_ps
+FORCE_INLINE __m128 _mm_cvtpd_ps(__m128d a)
+{
+#if defined(__aarch64__)
+ float32x2_t tmp = vcvt_f32_f64(vreinterpretq_f64_m128d(a));
+ return vreinterpretq_m128_f32(vcombine_f32(tmp, vdup_n_f32(0)));
+#else
+ float a0 = (float) ((double *) &a)[0];
+ float a1 = (float) ((double *) &a)[1];
+ return _mm_set_ps(0, 0, a1, a0);
+#endif
+}
-// Multiplies the four single-precision, floating-point values of a and b.
+// Convert packed signed 32-bit integers in a to packed double-precision
+// (64-bit) floating-point elements, and store the results in dst.
//
-// r0 := a0 * b0
-// r1 := a1 * b1
-// r2 := a2 * b2
-// r3 := a3 * b3
+// FOR j := 0 to 1
+// i := j*32
+// m := j*64
+// dst[m+63:m] := Convert_Int32_To_FP64(a[i+31:i])
+// ENDFOR
//
-// https://msdn.microsoft.com/en-us/library/vstudio/22kbk6t9(v=vs.100).aspx
-FORCE_INLINE __m128 _mm_mul_ps(__m128 a, __m128 b)
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtpi32_pd
+FORCE_INLINE __m128d _mm_cvtpi32_pd(__m64 a)
{
- return vreinterpretq_m128_f32(
- vmulq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b)));
+#if defined(__aarch64__)
+ return vreinterpretq_m128d_f64(
+ vcvtq_f64_s64(vmovl_s32(vreinterpret_s32_m64(a))));
+#else
+ double a0 = (double) vget_lane_s32(vreinterpret_s32_m64(a), 0);
+ double a1 = (double) vget_lane_s32(vreinterpret_s32_m64(a), 1);
+ return _mm_set_pd(a1, a0);
+#endif
}
-// Multiply packed double-precision (64-bit) floating-point elements in a and b,
-// and store the results in dst.
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mul_pd
-FORCE_INLINE __m128d _mm_mul_pd(__m128d a, __m128d b)
+// Converts the four single-precision, floating-point values of a to signed
+// 32-bit integer values.
+//
+// r0 := (int) a0
+// r1 := (int) a1
+// r2 := (int) a2
+// r3 := (int) a3
+//
+// https://msdn.microsoft.com/en-us/library/vstudio/xdc42k5e(v=vs.100).aspx
+// *NOTE*. The default rounding mode on SSE is 'round to even', which ARMv7-A
+// does not support! It is supported on ARMv8-A however.
+FORCE_INLINE __m128i _mm_cvtps_epi32(__m128 a)
{
#if defined(__aarch64__)
- return vreinterpretq_m128d_f64(
- vmulq_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(b)));
+ switch (_MM_GET_ROUNDING_MODE()) {
+ case _MM_ROUND_NEAREST:
+ return vreinterpretq_m128i_s32(vcvtnq_s32_f32(a));
+ case _MM_ROUND_DOWN:
+ return vreinterpretq_m128i_s32(vcvtmq_s32_f32(a));
+ case _MM_ROUND_UP:
+ return vreinterpretq_m128i_s32(vcvtpq_s32_f32(a));
+ default: // _MM_ROUND_TOWARD_ZERO
+ return vreinterpretq_m128i_s32(vcvtq_s32_f32(a));
+ }
#else
- double *da = (double *) &a;
- double *db = (double *) &b;
- double c[2];
- c[0] = da[0] * db[0];
- c[1] = da[1] * db[1];
- return vld1q_f32((float32_t *) c);
+ float *f = (float *) &a;
+ switch (_MM_GET_ROUNDING_MODE()) {
+ case _MM_ROUND_NEAREST: {
+ uint32x4_t signmask = vdupq_n_u32(0x80000000);
+ float32x4_t half = vbslq_f32(signmask, vreinterpretq_f32_m128(a),
+ vdupq_n_f32(0.5f)); /* +/- 0.5 */
+ int32x4_t r_normal = vcvtq_s32_f32(vaddq_f32(
+ vreinterpretq_f32_m128(a), half)); /* round to integer: [a + 0.5]*/
+ int32x4_t r_trunc = vcvtq_s32_f32(
+ vreinterpretq_f32_m128(a)); /* truncate to integer: [a] */
+ int32x4_t plusone = vreinterpretq_s32_u32(vshrq_n_u32(
+ vreinterpretq_u32_s32(vnegq_s32(r_trunc)), 31)); /* 1 or 0 */
+ int32x4_t r_even = vbicq_s32(vaddq_s32(r_trunc, plusone),
+ vdupq_n_s32(1)); /* ([a] + {0,1}) & ~1 */
+ float32x4_t delta = vsubq_f32(
+ vreinterpretq_f32_m128(a),
+ vcvtq_f32_s32(r_trunc)); /* compute delta: delta = (a - [a]) */
+ uint32x4_t is_delta_half =
+ vceqq_f32(delta, half); /* delta == +/- 0.5 */
+ return vreinterpretq_m128i_s32(
+ vbslq_s32(is_delta_half, r_even, r_normal));
+ }
+ case _MM_ROUND_DOWN:
+ return _mm_set_epi32(floorf(f[3]), floorf(f[2]), floorf(f[1]),
+ floorf(f[0]));
+ case _MM_ROUND_UP:
+ return _mm_set_epi32(ceilf(f[3]), ceilf(f[2]), ceilf(f[1]),
+ ceilf(f[0]));
+ default: // _MM_ROUND_TOWARD_ZERO
+ return _mm_set_epi32((int32_t) f[3], (int32_t) f[2], (int32_t) f[1],
+ (int32_t) f[0]);
+ }
#endif
}
-// Multiply the lower double-precision (64-bit) floating-point element in a and
-// b, store the result in the lower element of dst, and copy the upper element
-// from a to the upper element of dst.
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=mm_mul_sd
-FORCE_INLINE __m128d _mm_mul_sd(__m128d a, __m128d b)
+// Convert packed single-precision (32-bit) floating-point elements in a to
+// packed double-precision (64-bit) floating-point elements, and store the
+// results in dst.
+//
+// FOR j := 0 to 1
+// i := 64*j
+// k := 32*j
+// dst[i+63:i] := Convert_FP32_To_FP64(a[k+31:k])
+// ENDFOR
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtps_pd
+FORCE_INLINE __m128d _mm_cvtps_pd(__m128 a)
{
- return _mm_move_sd(a, _mm_mul_pd(a, b));
+#if defined(__aarch64__)
+ return vreinterpretq_m128d_f64(
+ vcvt_f64_f32(vget_low_f32(vreinterpretq_f32_m128(a))));
+#else
+ double a0 = (double) vgetq_lane_f32(vreinterpretq_f32_m128(a), 0);
+ double a1 = (double) vgetq_lane_f32(vreinterpretq_f32_m128(a), 1);
+ return _mm_set_pd(a1, a0);
+#endif
}
-// Multiply the lower single-precision (32-bit) floating-point element in a and
-// b, store the result in the lower element of dst, and copy the upper 3 packed
-// elements from a to the upper elements of dst.
+// Copy the lower double-precision (64-bit) floating-point element of a to dst.
//
-// dst[31:0] := a[31:0] * b[31:0]
-// dst[127:32] := a[127:32]
+// dst[63:0] := a[63:0]
//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mul_ss
-FORCE_INLINE __m128 _mm_mul_ss(__m128 a, __m128 b)
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtsd_f64
+FORCE_INLINE double _mm_cvtsd_f64(__m128d a)
{
- return _mm_move_ss(a, _mm_mul_ps(a, b));
+#if defined(__aarch64__)
+ return (double) vgetq_lane_f64(vreinterpretq_f64_m128d(a), 0);
+#else
+ return ((double *) &a)[0];
+#endif
}
-// Multiply the low unsigned 32-bit integers from each packed 64-bit element in
-// a and b, and store the unsigned 64-bit results in dst.
+// Convert the lower double-precision (64-bit) floating-point element in a to a
+// 32-bit integer, and store the result in dst.
//
-// r0 := (a0 & 0xFFFFFFFF) * (b0 & 0xFFFFFFFF)
-// r1 := (a2 & 0xFFFFFFFF) * (b2 & 0xFFFFFFFF)
-FORCE_INLINE __m128i _mm_mul_epu32(__m128i a, __m128i b)
+// dst[31:0] := Convert_FP64_To_Int32(a[63:0])
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtsd_si32
+FORCE_INLINE int32_t _mm_cvtsd_si32(__m128d a)
{
- // vmull_u32 upcasts instead of masking, so we downcast.
- uint32x2_t a_lo = vmovn_u64(vreinterpretq_u64_m128i(a));
- uint32x2_t b_lo = vmovn_u64(vreinterpretq_u64_m128i(b));
- return vreinterpretq_m128i_u64(vmull_u32(a_lo, b_lo));
+#if defined(__aarch64__)
+ return (int32_t) vgetq_lane_f64(vrndiq_f64(vreinterpretq_f64_m128d(a)), 0);
+#else
+ __m128d rnd = _mm_round_pd(a, _MM_FROUND_CUR_DIRECTION);
+ double ret = ((double *) &rnd)[0];
+ return (int32_t) ret;
+#endif
}
-// Multiply the low unsigned 32-bit integers from a and b, and store the
-// unsigned 64-bit result in dst.
+// Convert the lower double-precision (64-bit) floating-point element in a to a
+// 64-bit integer, and store the result in dst.
//
-// dst[63:0] := a[31:0] * b[31:0]
+// dst[63:0] := Convert_FP64_To_Int64(a[63:0])
//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mul_su32
-FORCE_INLINE __m64 _mm_mul_su32(__m64 a, __m64 b)
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtsd_si64
+FORCE_INLINE int64_t _mm_cvtsd_si64(__m128d a)
{
- return vreinterpret_m64_u64(vget_low_u64(
- vmull_u32(vreinterpret_u32_m64(a), vreinterpret_u32_m64(b))));
+#if defined(__aarch64__)
+ return (int64_t) vgetq_lane_f64(vrndiq_f64(vreinterpretq_f64_m128d(a)), 0);
+#else
+ __m128d rnd = _mm_round_pd(a, _MM_FROUND_CUR_DIRECTION);
+ double ret = ((double *) &rnd)[0];
+ return (int64_t) ret;
+#endif
}
-// Multiply the low signed 32-bit integers from each packed 64-bit element in
-// a and b, and store the signed 64-bit results in dst.
+// Convert the lower double-precision (64-bit) floating-point element in a to a
+// 64-bit integer, and store the result in dst.
//
-// r0 := (int64_t)(int32_t)a0 * (int64_t)(int32_t)b0
-// r1 := (int64_t)(int32_t)a2 * (int64_t)(int32_t)b2
-FORCE_INLINE __m128i _mm_mul_epi32(__m128i a, __m128i b)
+// dst[63:0] := Convert_FP64_To_Int64(a[63:0])
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtsd_si64x
+#define _mm_cvtsd_si64x _mm_cvtsd_si64
+
+// Convert the lower double-precision (64-bit) floating-point element in b to a
+// single-precision (32-bit) floating-point element, store the result in the
+// lower element of dst, and copy the upper 3 packed elements from a to the
+// upper elements of dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtsd_ss
+FORCE_INLINE __m128 _mm_cvtsd_ss(__m128 a, __m128d b)
{
- // vmull_s32 upcasts instead of masking, so we downcast.
- int32x2_t a_lo = vmovn_s64(vreinterpretq_s64_m128i(a));
- int32x2_t b_lo = vmovn_s64(vreinterpretq_s64_m128i(b));
- return vreinterpretq_m128i_s64(vmull_s32(a_lo, b_lo));
+#if defined(__aarch64__)
+ return vreinterpretq_m128_f32(vsetq_lane_f32(
+ vget_lane_f32(vcvt_f32_f64(vreinterpretq_f64_m128d(b)), 0),
+ vreinterpretq_f32_m128(a), 0));
+#else
+ return vreinterpretq_m128_f32(vsetq_lane_f32((float) ((double *) &b)[0],
+ vreinterpretq_f32_m128(a), 0));
+#endif
}
-// Multiplies the 8 signed 16-bit integers from a by the 8 signed 16-bit
-// integers from b.
+// Copy the lower 32-bit integer in a to dst.
//
-// r0 := (a0 * b0) + (a1 * b1)
-// r1 := (a2 * b2) + (a3 * b3)
-// r2 := (a4 * b4) + (a5 * b5)
-// r3 := (a6 * b6) + (a7 * b7)
-// https://msdn.microsoft.com/en-us/library/yht36sa6(v=vs.90).aspx
-FORCE_INLINE __m128i _mm_madd_epi16(__m128i a, __m128i b)
+// dst[31:0] := a[31:0]
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtsi128_si32
+FORCE_INLINE int _mm_cvtsi128_si32(__m128i a)
{
- int32x4_t low = vmull_s16(vget_low_s16(vreinterpretq_s16_m128i(a)),
- vget_low_s16(vreinterpretq_s16_m128i(b)));
- int32x4_t high = vmull_s16(vget_high_s16(vreinterpretq_s16_m128i(a)),
- vget_high_s16(vreinterpretq_s16_m128i(b)));
-
- int32x2_t low_sum = vpadd_s32(vget_low_s32(low), vget_high_s32(low));
- int32x2_t high_sum = vpadd_s32(vget_low_s32(high), vget_high_s32(high));
-
- return vreinterpretq_m128i_s32(vcombine_s32(low_sum, high_sum));
+ return vgetq_lane_s32(vreinterpretq_s32_m128i(a), 0);
}
-// Multiply packed signed 16-bit integers in a and b, producing intermediate
-// signed 32-bit integers. Shift right by 15 bits while rounding up, and store
-// the packed 16-bit integers in dst.
+// Copy the lower 64-bit integer in a to dst.
//
-// r0 := Round(((int32_t)a0 * (int32_t)b0) >> 15)
-// r1 := Round(((int32_t)a1 * (int32_t)b1) >> 15)
-// r2 := Round(((int32_t)a2 * (int32_t)b2) >> 15)
-// ...
-// r7 := Round(((int32_t)a7 * (int32_t)b7) >> 15)
-FORCE_INLINE __m128i _mm_mulhrs_epi16(__m128i a, __m128i b)
+// dst[63:0] := a[63:0]
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtsi128_si64
+FORCE_INLINE int64_t _mm_cvtsi128_si64(__m128i a)
{
- // Has issues due to saturation
- // return vreinterpretq_m128i_s16(vqrdmulhq_s16(a, b));
-
- // Multiply
- int32x4_t mul_lo = vmull_s16(vget_low_s16(vreinterpretq_s16_m128i(a)),
- vget_low_s16(vreinterpretq_s16_m128i(b)));
- int32x4_t mul_hi = vmull_s16(vget_high_s16(vreinterpretq_s16_m128i(a)),
- vget_high_s16(vreinterpretq_s16_m128i(b)));
-
- // Rounding narrowing shift right
- // narrow = (int16_t)((mul + 16384) >> 15);
- int16x4_t narrow_lo = vrshrn_n_s32(mul_lo, 15);
- int16x4_t narrow_hi = vrshrn_n_s32(mul_hi, 15);
-
- // Join together
- return vreinterpretq_m128i_s16(vcombine_s16(narrow_lo, narrow_hi));
+ return vgetq_lane_s64(vreinterpretq_s64_m128i(a), 0);
}
-// Vertically multiply each unsigned 8-bit integer from a with the corresponding
-// signed 8-bit integer from b, producing intermediate signed 16-bit integers.
-// Horizontally add adjacent pairs of intermediate signed 16-bit integers,
-// and pack the saturated results in dst.
-//
-// FOR j := 0 to 7
-// i := j*16
-// dst[i+15:i] := Saturate_To_Int16( a[i+15:i+8]*b[i+15:i+8] +
-// a[i+7:i]*b[i+7:i] )
-// ENDFOR
-FORCE_INLINE __m128i _mm_maddubs_epi16(__m128i _a, __m128i _b)
+// Copy the lower 64-bit integer in a to dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtsi128_si64x
+#define _mm_cvtsi128_si64x(a) _mm_cvtsi128_si64(a)
+
+// Convert the signed 32-bit integer b to a double-precision (64-bit)
+// floating-point element, store the result in the lower element of dst, and
+// copy the upper element from a to the upper element of dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtsi32_sd
+FORCE_INLINE __m128d _mm_cvtsi32_sd(__m128d a, int32_t b)
{
#if defined(__aarch64__)
- uint8x16_t a = vreinterpretq_u8_m128i(_a);
- int8x16_t b = vreinterpretq_s8_m128i(_b);
- int16x8_t tl = vmulq_s16(vreinterpretq_s16_u16(vmovl_u8(vget_low_u8(a))),
- vmovl_s8(vget_low_s8(b)));
- int16x8_t th = vmulq_s16(vreinterpretq_s16_u16(vmovl_u8(vget_high_u8(a))),
- vmovl_s8(vget_high_s8(b)));
- return vreinterpretq_m128i_s16(
- vqaddq_s16(vuzp1q_s16(tl, th), vuzp2q_s16(tl, th)));
+ return vreinterpretq_m128d_f64(
+ vsetq_lane_f64((double) b, vreinterpretq_f64_m128d(a), 0));
#else
- // This would be much simpler if x86 would choose to zero extend OR sign
- // extend, not both. This could probably be optimized better.
- uint16x8_t a = vreinterpretq_u16_m128i(_a);
- int16x8_t b = vreinterpretq_s16_m128i(_b);
-
- // Zero extend a
- int16x8_t a_odd = vreinterpretq_s16_u16(vshrq_n_u16(a, 8));
- int16x8_t a_even = vreinterpretq_s16_u16(vbicq_u16(a, vdupq_n_u16(0xff00)));
-
- // Sign extend by shifting left then shifting right.
- int16x8_t b_even = vshrq_n_s16(vshlq_n_s16(b, 8), 8);
- int16x8_t b_odd = vshrq_n_s16(b, 8);
-
- // multiply
- int16x8_t prod1 = vmulq_s16(a_even, b_even);
- int16x8_t prod2 = vmulq_s16(a_odd, b_odd);
-
- // saturated add
- return vreinterpretq_m128i_s16(vqaddq_s16(prod1, prod2));
+ double bf = (double) b;
+ return vreinterpretq_m128d_s64(
+ vsetq_lane_s64(*(int64_t *) &bf, vreinterpretq_s64_m128d(a), 0));
#endif
}
-// Computes the fused multiple add product of 32-bit floating point numbers.
+// Copy the lower 64-bit integer in a to dst.
//
-// Return Value
-// Multiplies A and B, and adds C to the temporary result before returning it.
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_fmadd
-FORCE_INLINE __m128 _mm_fmadd_ps(__m128 a, __m128 b, __m128 c)
+// dst[63:0] := a[63:0]
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtsi128_si64x
+#define _mm_cvtsi128_si64x(a) _mm_cvtsi128_si64(a)
+
+// Moves 32-bit integer a to the least significant 32 bits of an __m128 object,
+// zero extending the upper bits.
+//
+// r0 := a
+// r1 := 0x0
+// r2 := 0x0
+// r3 := 0x0
+//
+// https://msdn.microsoft.com/en-us/library/ct3539ha%28v=vs.90%29.aspx
+FORCE_INLINE __m128i _mm_cvtsi32_si128(int a)
+{
+ return vreinterpretq_m128i_s32(vsetq_lane_s32(a, vdupq_n_s32(0), 0));
+}
+
+// Convert the signed 64-bit integer b to a double-precision (64-bit)
+// floating-point element, store the result in the lower element of dst, and
+// copy the upper element from a to the upper element of dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtsi64_sd
+FORCE_INLINE __m128d _mm_cvtsi64_sd(__m128d a, int64_t b)
{
#if defined(__aarch64__)
- return vreinterpretq_m128_f32(vfmaq_f32(vreinterpretq_f32_m128(c),
- vreinterpretq_f32_m128(b),
- vreinterpretq_f32_m128(a)));
+ return vreinterpretq_m128d_f64(
+ vsetq_lane_f64((double) b, vreinterpretq_f64_m128d(a), 0));
#else
- return _mm_add_ps(_mm_mul_ps(a, b), c);
+ double bf = (double) b;
+ return vreinterpretq_m128d_s64(
+ vsetq_lane_s64(*(int64_t *) &bf, vreinterpretq_s64_m128d(a), 0));
#endif
}
-// Alternatively add and subtract packed single-precision (32-bit)
-// floating-point elements in a to/from packed elements in b, and store the
-// results in dst.
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=addsub_ps
-FORCE_INLINE __m128 _mm_addsub_ps(__m128 a, __m128 b)
+// Moves 64-bit integer a to the least significant 64 bits of an __m128 object,
+// zero extending the upper bits.
+//
+// r0 := a
+// r1 := 0x0
+FORCE_INLINE __m128i _mm_cvtsi64_si128(int64_t a)
{
- __m128 mask = {-1.0f, 1.0f, -1.0f, 1.0f};
- return _mm_fmadd_ps(b, mask, a);
+ return vreinterpretq_m128i_s64(vsetq_lane_s64(a, vdupq_n_s64(0), 0));
}
-// Horizontally add adjacent pairs of double-precision (64-bit) floating-point
-// elements in a and b, and pack the results in dst.
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_hadd_pd
-FORCE_INLINE __m128d _mm_hadd_pd(__m128d a, __m128d b)
+// Copy 64-bit integer a to the lower element of dst, and zero the upper
+// element.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtsi64x_si128
+#define _mm_cvtsi64x_si128(a) _mm_cvtsi64_si128(a)
+
+// Convert the signed 64-bit integer b to a double-precision (64-bit)
+// floating-point element, store the result in the lower element of dst, and
+// copy the upper element from a to the upper element of dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtsi64x_sd
+#define _mm_cvtsi64x_sd(a, b) _mm_cvtsi64_sd(a, b)
+
+// Convert the lower single-precision (32-bit) floating-point element in b to a
+// double-precision (64-bit) floating-point element, store the result in the
+// lower element of dst, and copy the upper element from a to the upper element
+// of dst.
+//
+// dst[63:0] := Convert_FP32_To_FP64(b[31:0])
+// dst[127:64] := a[127:64]
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtss_sd
+FORCE_INLINE __m128d _mm_cvtss_sd(__m128d a, __m128 b)
{
+ double d = (double) vgetq_lane_f32(vreinterpretq_f32_m128(b), 0);
#if defined(__aarch64__)
return vreinterpretq_m128d_f64(
- vpaddq_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(b)));
+ vsetq_lane_f64(d, vreinterpretq_f64_m128d(a), 0));
#else
- double *da = (double *) &a;
- double *db = (double *) &b;
- double c[] = {da[0] + da[1], db[0] + db[1]};
- return vreinterpretq_m128d_u64(vld1q_u64((uint64_t *) c));
+ return vreinterpretq_m128d_s64(
+ vsetq_lane_s64(*(int64_t *) &d, vreinterpretq_s64_m128d(a), 0));
#endif
}
-// Compute the absolute differences of packed unsigned 8-bit integers in a and
-// b, then horizontally sum each consecutive 8 differences to produce two
-// unsigned 16-bit integers, and pack these unsigned 16-bit integers in the low
-// 16 bits of 64-bit elements in dst.
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_sad_epu8
-FORCE_INLINE __m128i _mm_sad_epu8(__m128i a, __m128i b)
+// Convert packed double-precision (64-bit) floating-point elements in a to
+// packed 32-bit integers with truncation, and store the results in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvttpd_epi32
+FORCE_INLINE __m128i _mm_cvttpd_epi32(__m128d a)
{
- uint16x8_t t = vpaddlq_u8(vabdq_u8((uint8x16_t) a, (uint8x16_t) b));
- uint16_t r0 = t[0] + t[1] + t[2] + t[3];
- uint16_t r4 = t[4] + t[5] + t[6] + t[7];
- uint16x8_t r = vsetq_lane_u16(r0, vdupq_n_u16(0), 0);
- return (__m128i) vsetq_lane_u16(r4, r, 4);
+ double a0 = ((double *) &a)[0];
+ double a1 = ((double *) &a)[1];
+ return _mm_set_epi32(0, 0, (int32_t) a1, (int32_t) a0);
}
-// Compute the absolute differences of packed unsigned 8-bit integers in a and
-// b, then horizontally sum each consecutive 8 differences to produce four
-// unsigned 16-bit integers, and pack these unsigned 16-bit integers in the low
-// 16 bits of dst.
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_sad_pu8
-FORCE_INLINE __m64 _mm_sad_pu8(__m64 a, __m64 b)
+// Convert packed double-precision (64-bit) floating-point elements in a to
+// packed 32-bit integers with truncation, and store the results in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvttpd_pi32
+FORCE_INLINE __m64 _mm_cvttpd_pi32(__m128d a)
{
- uint16x4_t t =
- vpaddl_u8(vabd_u8(vreinterpret_u8_m64(a), vreinterpret_u8_m64(b)));
- uint16_t r0 = t[0] + t[1] + t[2] + t[3];
- return vreinterpret_m64_u16(vset_lane_u16(r0, vdup_n_u16(0), 0));
+ double a0 = ((double *) &a)[0];
+ double a1 = ((double *) &a)[1];
+ int32_t ALIGN_STRUCT(16) data[2] = {(int32_t) a0, (int32_t) a1};
+ return vreinterpret_m64_s32(vld1_s32(data));
}
-// Compute the absolute differences of packed unsigned 8-bit integers in a and
-// b, then horizontally sum each consecutive 8 differences to produce four
-// unsigned 16-bit integers, and pack these unsigned 16-bit integers in the low
-// 16 bits of dst.
+// Converts the four single-precision, floating-point values of a to signed
+// 32-bit integer values using truncate.
+// https://msdn.microsoft.com/en-us/library/vstudio/1h005y6x(v=vs.100).aspx
+FORCE_INLINE __m128i _mm_cvttps_epi32(__m128 a)
+{
+ return vreinterpretq_m128i_s32(vcvtq_s32_f32(vreinterpretq_f32_m128(a)));
+}
+
+// Convert the lower double-precision (64-bit) floating-point element in a to a
+// 32-bit integer with truncation, and store the result in dst.
//
-// FOR j := 0 to 7
-// i := j*8
-// tmp[i+7:i] := ABS(a[i+7:i] - b[i+7:i])
-// ENDFOR
-// dst[15:0] := tmp[7:0] + tmp[15:8] + tmp[23:16] + tmp[31:24] + tmp[39:32] +
-// tmp[47:40] + tmp[55:48] + tmp[63:56] dst[63:16] := 0
+// dst[63:0] := Convert_FP64_To_Int32_Truncate(a[63:0])
//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_m_psadbw
-#define _m_psadbw(a, b) _mm_sad_pu8(a, b)
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvttsd_si32
+FORCE_INLINE int32_t _mm_cvttsd_si32(__m128d a)
+{
+ double ret = *((double *) &a);
+ return (int32_t) ret;
+}
-// Divides the four single-precision, floating-point values of a and b.
+// Convert the lower double-precision (64-bit) floating-point element in a to a
+// 64-bit integer with truncation, and store the result in dst.
//
-// r0 := a0 / b0
-// r1 := a1 / b1
-// r2 := a2 / b2
-// r3 := a3 / b3
+// dst[63:0] := Convert_FP64_To_Int64_Truncate(a[63:0])
//
-// https://msdn.microsoft.com/en-us/library/edaw8147(v=vs.100).aspx
-FORCE_INLINE __m128 _mm_div_ps(__m128 a, __m128 b)
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvttsd_si64
+FORCE_INLINE int64_t _mm_cvttsd_si64(__m128d a)
{
-#if defined(__aarch64__) && !SSE2NEON_PRECISE_DIV
- return vreinterpretq_m128_f32(
- vdivq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b)));
+#if defined(__aarch64__)
+ return vgetq_lane_s64(vcvtq_s64_f64(vreinterpretq_f64_m128d(a)), 0);
#else
- float32x4_t recip = vrecpeq_f32(vreinterpretq_f32_m128(b));
- recip = vmulq_f32(recip, vrecpsq_f32(recip, vreinterpretq_f32_m128(b)));
-#if SSE2NEON_PRECISE_DIV
- // Additional Netwon-Raphson iteration for accuracy
- recip = vmulq_f32(recip, vrecpsq_f32(recip, vreinterpretq_f32_m128(b)));
-#endif
- return vreinterpretq_m128_f32(vmulq_f32(vreinterpretq_f32_m128(a), recip));
+ double ret = *((double *) &a);
+ return (int64_t) ret;
#endif
}
-// Divides the scalar single-precision floating point value of a by b.
-// https://msdn.microsoft.com/en-us/library/4y73xa49(v=vs.100).aspx
-FORCE_INLINE __m128 _mm_div_ss(__m128 a, __m128 b)
-{
- float32_t value =
- vgetq_lane_f32(vreinterpretq_f32_m128(_mm_div_ps(a, b)), 0);
- return vreinterpretq_m128_f32(
- vsetq_lane_f32(value, vreinterpretq_f32_m128(a), 0));
-}
+// Convert the lower double-precision (64-bit) floating-point element in a to a
+// 64-bit integer with truncation, and store the result in dst.
+//
+// dst[63:0] := Convert_FP64_To_Int64_Truncate(a[63:0])
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvttsd_si64x
+#define _mm_cvttsd_si64x(a) _mm_cvttsd_si64(a)
// Divide packed double-precision (64-bit) floating-point elements in a by
// packed elements in b, and store the results in dst.
@@ -3875,266 +4340,230 @@ FORCE_INLINE __m128d _mm_div_sd(__m128d a, __m128d b)
#endif
}
-// Compute the approximate reciprocal of packed single-precision (32-bit)
-// floating-point elements in a, and store the results in dst. The maximum
-// relative error for this approximation is less than 1.5*2^-12.
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_rcp_ps
-FORCE_INLINE __m128 _mm_rcp_ps(__m128 in)
+// Extracts the selected signed or unsigned 16-bit integer from a and zero
+// extends.
+// https://msdn.microsoft.com/en-us/library/6dceta0c(v=vs.100).aspx
+// FORCE_INLINE int _mm_extract_epi16(__m128i a, __constrange(0,8) int imm)
+#define _mm_extract_epi16(a, imm) \
+ vgetq_lane_u16(vreinterpretq_u16_m128i(a), (imm))
+
+// Inserts the least significant 16 bits of b into the selected 16-bit integer
+// of a.
+// https://msdn.microsoft.com/en-us/library/kaze8hz1%28v=vs.100%29.aspx
+// FORCE_INLINE __m128i _mm_insert_epi16(__m128i a, int b,
+// __constrange(0,8) int imm)
+#define _mm_insert_epi16(a, b, imm) \
+ __extension__({ \
+ vreinterpretq_m128i_s16( \
+ vsetq_lane_s16((b), vreinterpretq_s16_m128i(a), (imm))); \
+ })
+
+// Loads two double-precision from 16-byte aligned memory, floating-point
+// values.
+//
+// dst[127:0] := MEM[mem_addr+127:mem_addr]
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_load_pd
+FORCE_INLINE __m128d _mm_load_pd(const double *p)
{
- float32x4_t recip = vrecpeq_f32(vreinterpretq_f32_m128(in));
- recip = vmulq_f32(recip, vrecpsq_f32(recip, vreinterpretq_f32_m128(in)));
-#if SSE2NEON_PRECISE_DIV
- // Additional Netwon-Raphson iteration for accuracy
- recip = vmulq_f32(recip, vrecpsq_f32(recip, vreinterpretq_f32_m128(in)));
+#if defined(__aarch64__)
+ return vreinterpretq_m128d_f64(vld1q_f64(p));
+#else
+ const float *fp = (const float *) p;
+ float ALIGN_STRUCT(16) data[4] = {fp[0], fp[1], fp[2], fp[3]};
+ return vreinterpretq_m128d_f32(vld1q_f32(data));
#endif
- return vreinterpretq_m128_f32(recip);
}
-// Compute the approximate reciprocal of the lower single-precision (32-bit)
-// floating-point element in a, store the result in the lower element of dst,
-// and copy the upper 3 packed elements from a to the upper elements of dst. The
-// maximum relative error for this approximation is less than 1.5*2^-12.
+// Load a double-precision (64-bit) floating-point element from memory into both
+// elements of dst.
//
-// dst[31:0] := (1.0 / a[31:0])
-// dst[127:32] := a[127:32]
+// dst[63:0] := MEM[mem_addr+63:mem_addr]
+// dst[127:64] := MEM[mem_addr+63:mem_addr]
//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_rcp_ss
-FORCE_INLINE __m128 _mm_rcp_ss(__m128 a)
-{
- return _mm_move_ss(a, _mm_rcp_ps(a));
-}
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_load_pd1
+#define _mm_load_pd1 _mm_load1_pd
-// Computes the approximations of square roots of the four single-precision,
-// floating-point values of a. First computes reciprocal square roots and then
-// reciprocals of the four values.
+// Load a double-precision (64-bit) floating-point element from memory into the
+// lower of dst, and zero the upper element. mem_addr does not need to be
+// aligned on any particular boundary.
//
-// r0 := sqrt(a0)
-// r1 := sqrt(a1)
-// r2 := sqrt(a2)
-// r3 := sqrt(a3)
+// dst[63:0] := MEM[mem_addr+63:mem_addr]
+// dst[127:64] := 0
//
-// https://msdn.microsoft.com/en-us/library/vstudio/8z67bwwk(v=vs.100).aspx
-FORCE_INLINE __m128 _mm_sqrt_ps(__m128 in)
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_load_sd
+FORCE_INLINE __m128d _mm_load_sd(const double *p)
{
-#if SSE2NEON_PRECISE_SQRT
- float32x4_t recip = vrsqrteq_f32(vreinterpretq_f32_m128(in));
-
- // Test for vrsqrteq_f32(0) -> positive infinity case.
- // Change to zero, so that s * 1/sqrt(s) result is zero too.
- const uint32x4_t pos_inf = vdupq_n_u32(0x7F800000);
- const uint32x4_t div_by_zero =
- vceqq_u32(pos_inf, vreinterpretq_u32_f32(recip));
- recip = vreinterpretq_f32_u32(
- vandq_u32(vmvnq_u32(div_by_zero), vreinterpretq_u32_f32(recip)));
-
- // Additional Netwon-Raphson iteration for accuracy
- recip = vmulq_f32(
- vrsqrtsq_f32(vmulq_f32(recip, recip), vreinterpretq_f32_m128(in)),
- recip);
- recip = vmulq_f32(
- vrsqrtsq_f32(vmulq_f32(recip, recip), vreinterpretq_f32_m128(in)),
- recip);
-
- // sqrt(s) = s * 1/sqrt(s)
- return vreinterpretq_m128_f32(vmulq_f32(vreinterpretq_f32_m128(in), recip));
-#elif defined(__aarch64__)
- return vreinterpretq_m128_f32(vsqrtq_f32(vreinterpretq_f32_m128(in)));
+#if defined(__aarch64__)
+ return vreinterpretq_m128d_f64(vsetq_lane_f64(*p, vdupq_n_f64(0), 0));
#else
- float32x4_t recipsq = vrsqrteq_f32(vreinterpretq_f32_m128(in));
- float32x4_t sq = vrecpeq_f32(recipsq);
- return vreinterpretq_m128_f32(sq);
+ const float *fp = (const float *) p;
+ float ALIGN_STRUCT(16) data[4] = {fp[0], fp[1], 0, 0};
+ return vreinterpretq_m128d_f32(vld1q_f32(data));
#endif
}
-// Computes the approximation of the square root of the scalar single-precision
-// floating point value of in.
-// https://msdn.microsoft.com/en-us/library/ahfsc22d(v=vs.100).aspx
-FORCE_INLINE __m128 _mm_sqrt_ss(__m128 in)
+// Loads 128-bit value. :
+// https://msdn.microsoft.com/en-us/library/atzzad1h(v=vs.80).aspx
+FORCE_INLINE __m128i _mm_load_si128(const __m128i *p)
{
- float32_t value =
- vgetq_lane_f32(vreinterpretq_f32_m128(_mm_sqrt_ps(in)), 0);
- return vreinterpretq_m128_f32(
- vsetq_lane_f32(value, vreinterpretq_f32_m128(in), 0));
+ return vreinterpretq_m128i_s32(vld1q_s32((const int32_t *) p));
}
-// Computes the approximations of the reciprocal square roots of the four
-// single-precision floating point values of in.
-// https://msdn.microsoft.com/en-us/library/22hfsh53(v=vs.100).aspx
-FORCE_INLINE __m128 _mm_rsqrt_ps(__m128 in)
+// Load a double-precision (64-bit) floating-point element from memory into both
+// elements of dst.
+//
+// dst[63:0] := MEM[mem_addr+63:mem_addr]
+// dst[127:64] := MEM[mem_addr+63:mem_addr]
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_load1_pd
+FORCE_INLINE __m128d _mm_load1_pd(const double *p)
{
- float32x4_t out = vrsqrteq_f32(vreinterpretq_f32_m128(in));
-#if SSE2NEON_PRECISE_RSQRT
- // Additional Netwon-Raphson iteration for accuracy
- out = vmulq_f32(
- out, vrsqrtsq_f32(vmulq_f32(vreinterpretq_f32_m128(in), out), out));
- out = vmulq_f32(
- out, vrsqrtsq_f32(vmulq_f32(vreinterpretq_f32_m128(in), out), out));
+#if defined(__aarch64__)
+ return vreinterpretq_m128d_f64(vld1q_dup_f64(p));
+#else
+ return vreinterpretq_m128d_s64(vdupq_n_s64(*(const int64_t *) p));
#endif
- return vreinterpretq_m128_f32(out);
}
-// Compute the approximate reciprocal square root of the lower single-precision
-// (32-bit) floating-point element in a, store the result in the lower element
-// of dst, and copy the upper 3 packed elements from a to the upper elements of
-// dst.
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_rsqrt_ss
-FORCE_INLINE __m128 _mm_rsqrt_ss(__m128 in)
+// Load a double-precision (64-bit) floating-point element from memory into the
+// upper element of dst, and copy the lower element from a to dst. mem_addr does
+// not need to be aligned on any particular boundary.
+//
+// dst[63:0] := a[63:0]
+// dst[127:64] := MEM[mem_addr+63:mem_addr]
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_loadh_pd
+FORCE_INLINE __m128d _mm_loadh_pd(__m128d a, const double *p)
{
- return vsetq_lane_f32(vgetq_lane_f32(_mm_rsqrt_ps(in), 0), in, 0);
+#if defined(__aarch64__)
+ return vreinterpretq_m128d_f64(
+ vcombine_f64(vget_low_f64(vreinterpretq_f64_m128d(a)), vld1_f64(p)));
+#else
+ return vreinterpretq_m128d_f32(vcombine_f32(
+ vget_low_f32(vreinterpretq_f32_m128d(a)), vld1_f32((const float *) p)));
+#endif
}
-// Compare packed signed 16-bit integers in a and b, and store packed maximum
-// values in dst.
-//
-// FOR j := 0 to 3
-// i := j*16
-// dst[i+15:i] := MAX(a[i+15:i], b[i+15:i])
-// ENDFOR
-//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_max_pi16
-FORCE_INLINE __m64 _mm_max_pi16(__m64 a, __m64 b)
+// Load 64-bit integer from memory into the first element of dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_loadl_epi64
+FORCE_INLINE __m128i _mm_loadl_epi64(__m128i const *p)
{
- return vreinterpret_m64_s16(
- vmax_s16(vreinterpret_s16_m64(a), vreinterpret_s16_m64(b)));
+ /* Load the lower 64 bits of the value pointed to by p into the
+ * lower 64 bits of the result, zeroing the upper 64 bits of the result.
+ */
+ return vreinterpretq_m128i_s32(
+ vcombine_s32(vld1_s32((int32_t const *) p), vcreate_s32(0)));
}
-// Compare packed signed 16-bit integers in a and b, and store packed maximum
-// values in dst.
+// Load a double-precision (64-bit) floating-point element from memory into the
+// lower element of dst, and copy the upper element from a to dst. mem_addr does
+// not need to be aligned on any particular boundary.
//
-// FOR j := 0 to 3
-// i := j*16
-// dst[i+15:i] := MAX(a[i+15:i], b[i+15:i])
-// ENDFOR
+// dst[63:0] := MEM[mem_addr+63:mem_addr]
+// dst[127:64] := a[127:64]
//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_max_pi16
-#define _m_pmaxsw(a, b) _mm_max_pi16(a, b)
-
-// Computes the maximums of the four single-precision, floating-point values of
-// a and b.
-// https://msdn.microsoft.com/en-us/library/vstudio/ff5d607a(v=vs.100).aspx
-FORCE_INLINE __m128 _mm_max_ps(__m128 a, __m128 b)
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_loadl_pd
+FORCE_INLINE __m128d _mm_loadl_pd(__m128d a, const double *p)
{
-#if SSE2NEON_PRECISE_MINMAX
- float32x4_t _a = vreinterpretq_f32_m128(a);
- float32x4_t _b = vreinterpretq_f32_m128(b);
- return vbslq_f32(vcltq_f32(_b, _a), _a, _b);
+#if defined(__aarch64__)
+ return vreinterpretq_m128d_f64(
+ vcombine_f64(vld1_f64(p), vget_high_f64(vreinterpretq_f64_m128d(a))));
#else
- return vreinterpretq_m128_f32(
- vmaxq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b)));
+ return vreinterpretq_m128d_f32(
+ vcombine_f32(vld1_f32((const float *) p),
+ vget_high_f32(vreinterpretq_f32_m128d(a))));
#endif
}
-// Compare packed unsigned 8-bit integers in a and b, and store packed maximum
-// values in dst.
+// Load 2 double-precision (64-bit) floating-point elements from memory into dst
+// in reverse order. mem_addr must be aligned on a 16-byte boundary or a
+// general-protection exception may be generated.
//
-// FOR j := 0 to 7
-// i := j*8
-// dst[i+7:i] := MAX(a[i+7:i], b[i+7:i])
-// ENDFOR
+// dst[63:0] := MEM[mem_addr+127:mem_addr+64]
+// dst[127:64] := MEM[mem_addr+63:mem_addr]
//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_max_pu8
-FORCE_INLINE __m64 _mm_max_pu8(__m64 a, __m64 b)
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_loadr_pd
+FORCE_INLINE __m128d _mm_loadr_pd(const double *p)
{
- return vreinterpret_m64_u8(
- vmax_u8(vreinterpret_u8_m64(a), vreinterpret_u8_m64(b)));
+#if defined(__aarch64__)
+ float64x2_t v = vld1q_f64(p);
+ return vreinterpretq_m128d_f64(vextq_f64(v, v, 1));
+#else
+ int64x2_t v = vld1q_s64((const int64_t *) p);
+ return vreinterpretq_m128d_s64(vextq_s64(v, v, 1));
+#endif
}
-// Compare packed unsigned 8-bit integers in a and b, and store packed maximum
-// values in dst.
-//
-// FOR j := 0 to 7
-// i := j*8
-// dst[i+7:i] := MAX(a[i+7:i], b[i+7:i])
-// ENDFOR
-//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_max_pu8
-#define _m_pmaxub(a, b) _mm_max_pu8(a, b)
-
-// Compare packed signed 16-bit integers in a and b, and store packed minimum
-// values in dst.
-//
-// FOR j := 0 to 3
-// i := j*16
-// dst[i+15:i] := MIN(a[i+15:i], b[i+15:i])
-// ENDFOR
-//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_min_pi16
-FORCE_INLINE __m64 _mm_min_pi16(__m64 a, __m64 b)
+// Loads two double-precision from unaligned memory, floating-point values.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_loadu_pd
+FORCE_INLINE __m128d _mm_loadu_pd(const double *p)
{
- return vreinterpret_m64_s16(
- vmin_s16(vreinterpret_s16_m64(a), vreinterpret_s16_m64(b)));
+ return _mm_load_pd(p);
}
-// Compare packed signed 16-bit integers in a and b, and store packed minimum
-// values in dst.
-//
-// FOR j := 0 to 3
-// i := j*16
-// dst[i+15:i] := MIN(a[i+15:i], b[i+15:i])
-// ENDFOR
-//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_min_pi16
-#define _m_pminsw(a, b) _mm_min_pi16(a, b)
-
-// Computes the minima of the four single-precision, floating-point values of a
-// and b.
-// https://msdn.microsoft.com/en-us/library/vstudio/wh13kadz(v=vs.100).aspx
-FORCE_INLINE __m128 _mm_min_ps(__m128 a, __m128 b)
+// Loads 128-bit value. :
+// https://msdn.microsoft.com/zh-cn/library/f4k12ae8(v=vs.90).aspx
+FORCE_INLINE __m128i _mm_loadu_si128(const __m128i *p)
{
-#if SSE2NEON_PRECISE_MINMAX
- float32x4_t _a = vreinterpretq_f32_m128(a);
- float32x4_t _b = vreinterpretq_f32_m128(b);
- return vbslq_f32(vcltq_f32(_a, _b), _a, _b);
-#else
- return vreinterpretq_m128_f32(
- vminq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b)));
-#endif
+ return vreinterpretq_m128i_s32(vld1q_s32((const int32_t *) p));
}
-// Compare packed unsigned 8-bit integers in a and b, and store packed minimum
-// values in dst.
+// Load unaligned 32-bit integer from memory into the first element of dst.
//
-// FOR j := 0 to 7
-// i := j*8
-// dst[i+7:i] := MIN(a[i+7:i], b[i+7:i])
-// ENDFOR
+// dst[31:0] := MEM[mem_addr+31:mem_addr]
+// dst[MAX:32] := 0
//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_min_pu8
-FORCE_INLINE __m64 _mm_min_pu8(__m64 a, __m64 b)
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_loadu_si32
+FORCE_INLINE __m128i _mm_loadu_si32(const void *p)
{
- return vreinterpret_m64_u8(
- vmin_u8(vreinterpret_u8_m64(a), vreinterpret_u8_m64(b)));
+ return vreinterpretq_m128i_s32(
+ vsetq_lane_s32(*(const int32_t *) p, vdupq_n_s32(0), 0));
}
-// Compare packed unsigned 8-bit integers in a and b, and store packed minimum
-// values in dst.
-//
-// FOR j := 0 to 7
-// i := j*8
-// dst[i+7:i] := MIN(a[i+7:i], b[i+7:i])
-// ENDFOR
+// Multiplies the 8 signed 16-bit integers from a by the 8 signed 16-bit
+// integers from b.
//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_min_pu8
-#define _m_pminub(a, b) _mm_min_pu8(a, b)
+// r0 := (a0 * b0) + (a1 * b1)
+// r1 := (a2 * b2) + (a3 * b3)
+// r2 := (a4 * b4) + (a5 * b5)
+// r3 := (a6 * b6) + (a7 * b7)
+// https://msdn.microsoft.com/en-us/library/yht36sa6(v=vs.90).aspx
+FORCE_INLINE __m128i _mm_madd_epi16(__m128i a, __m128i b)
+{
+ int32x4_t low = vmull_s16(vget_low_s16(vreinterpretq_s16_m128i(a)),
+ vget_low_s16(vreinterpretq_s16_m128i(b)));
+ int32x4_t high = vmull_s16(vget_high_s16(vreinterpretq_s16_m128i(a)),
+ vget_high_s16(vreinterpretq_s16_m128i(b)));
-// Computes the maximum of the two lower scalar single-precision floating point
-// values of a and b.
-// https://msdn.microsoft.com/en-us/library/s6db5esz(v=vs.100).aspx
-FORCE_INLINE __m128 _mm_max_ss(__m128 a, __m128 b)
+ int32x2_t low_sum = vpadd_s32(vget_low_s32(low), vget_high_s32(low));
+ int32x2_t high_sum = vpadd_s32(vget_low_s32(high), vget_high_s32(high));
+
+ return vreinterpretq_m128i_s32(vcombine_s32(low_sum, high_sum));
+}
+
+// Conditionally store 8-bit integer elements from a into memory using mask
+// (elements are not stored when the highest bit is not set in the corresponding
+// element) and a non-temporal memory hint. mem_addr does not need to be aligned
+// on any particular boundary.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskmoveu_si128
+FORCE_INLINE void _mm_maskmoveu_si128(__m128i a, __m128i mask, char *mem_addr)
{
- float32_t value = vgetq_lane_f32(_mm_max_ps(a, b), 0);
- return vreinterpretq_m128_f32(
- vsetq_lane_f32(value, vreinterpretq_f32_m128(a), 0));
+ int8x16_t shr_mask = vshrq_n_s8(vreinterpretq_s8_m128i(mask), 7);
+ __m128 b = _mm_load_ps((const float *) mem_addr);
+ int8x16_t masked =
+ vbslq_s8(vreinterpretq_u8_s8(shr_mask), vreinterpretq_s8_m128i(a),
+ vreinterpretq_s8_m128(b));
+ vst1q_s8((int8_t *) mem_addr, masked);
}
-// Computes the minimum of the two lower scalar single-precision floating point
-// values of a and b.
-// https://msdn.microsoft.com/en-us/library/0a9y7xaa(v=vs.100).aspx
-FORCE_INLINE __m128 _mm_min_ss(__m128 a, __m128 b)
+// Computes the pairwise maxima of the 8 signed 16-bit integers from a and the 8
+// signed 16-bit integers from b.
+// https://msdn.microsoft.com/en-us/LIBRary/3x060h7c(v=vs.100).aspx
+FORCE_INLINE __m128i _mm_max_epi16(__m128i a, __m128i b)
{
- float32_t value = vgetq_lane_f32(_mm_min_ps(a, b), 0);
- return vreinterpretq_m128_f32(
- vsetq_lane_f32(value, vreinterpretq_f32_m128(a), 0));
+ return vreinterpretq_m128i_s16(
+ vmaxq_s16(vreinterpretq_s16_m128i(a), vreinterpretq_s16_m128i(b)));
}
// Computes the pairwise maxima of the 16 unsigned 8-bit integers from a and the
@@ -4146,13 +4575,41 @@ FORCE_INLINE __m128i _mm_max_epu8(__m128i a, __m128i b)
vmaxq_u8(vreinterpretq_u8_m128i(a), vreinterpretq_u8_m128i(b)));
}
-// Computes the pairwise minima of the 16 unsigned 8-bit integers from a and the
-// 16 unsigned 8-bit integers from b.
-// https://msdn.microsoft.com/ko-kr/library/17k8cf58(v=vs.100).aspxx
-FORCE_INLINE __m128i _mm_min_epu8(__m128i a, __m128i b)
+// Compare packed double-precision (64-bit) floating-point elements in a and b,
+// and store packed maximum values in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_max_pd
+FORCE_INLINE __m128d _mm_max_pd(__m128d a, __m128d b)
{
- return vreinterpretq_m128i_u8(
- vminq_u8(vreinterpretq_u8_m128i(a), vreinterpretq_u8_m128i(b)));
+#if defined(__aarch64__)
+ return vreinterpretq_m128d_f64(
+ vmaxq_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(b)));
+#else
+ uint64_t a0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(a));
+ uint64_t a1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(a));
+ uint64_t b0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(b));
+ uint64_t b1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(b));
+ uint64_t d[2];
+ d[0] = (*(double *) &a0) > (*(double *) &b0) ? a0 : b0;
+ d[1] = (*(double *) &a1) > (*(double *) &b1) ? a1 : b1;
+
+ return vreinterpretq_m128d_u64(vld1q_u64(d));
+#endif
+}
+
+// Compare the lower double-precision (64-bit) floating-point elements in a and
+// b, store the maximum value in the lower element of dst, and copy the upper
+// element from a to the upper element of dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_max_sd
+FORCE_INLINE __m128d _mm_max_sd(__m128d a, __m128d b)
+{
+#if defined(__aarch64__)
+ return _mm_move_sd(a, _mm_max_pd(a, b));
+#else
+ double *da = (double *) &a;
+ double *db = (double *) &b;
+ double c[2] = {fmax(da[0], db[0]), da[1]};
+ return vld1q_f32((float32_t *) c);
+#endif
}
// Computes the pairwise minima of the 8 signed 16-bit integers from a and the 8
@@ -4164,110 +4621,246 @@ FORCE_INLINE __m128i _mm_min_epi16(__m128i a, __m128i b)
vminq_s16(vreinterpretq_s16_m128i(a), vreinterpretq_s16_m128i(b)));
}
-// Compare packed signed 8-bit integers in a and b, and store packed maximum
-// values in dst.
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_max_epi8
-FORCE_INLINE __m128i _mm_max_epi8(__m128i a, __m128i b)
+// Computes the pairwise minima of the 16 unsigned 8-bit integers from a and the
+// 16 unsigned 8-bit integers from b.
+// https://msdn.microsoft.com/ko-kr/library/17k8cf58(v=vs.100).aspxx
+FORCE_INLINE __m128i _mm_min_epu8(__m128i a, __m128i b)
{
- return vreinterpretq_m128i_s8(
- vmaxq_s8(vreinterpretq_s8_m128i(a), vreinterpretq_s8_m128i(b)));
+ return vreinterpretq_m128i_u8(
+ vminq_u8(vreinterpretq_u8_m128i(a), vreinterpretq_u8_m128i(b)));
}
-// Compare packed unsigned 16-bit integers in a and b, and store packed maximum
-// values in dst.
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_max_epu16
-FORCE_INLINE __m128i _mm_max_epu16(__m128i a, __m128i b)
+// Compare packed double-precision (64-bit) floating-point elements in a and b,
+// and store packed minimum values in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_min_pd
+FORCE_INLINE __m128d _mm_min_pd(__m128d a, __m128d b)
{
- return vreinterpretq_m128i_u16(
- vmaxq_u16(vreinterpretq_u16_m128i(a), vreinterpretq_u16_m128i(b)));
+#if defined(__aarch64__)
+ return vreinterpretq_m128d_f64(
+ vminq_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(b)));
+#else
+ uint64_t a0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(a));
+ uint64_t a1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(a));
+ uint64_t b0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(b));
+ uint64_t b1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(b));
+ uint64_t d[2];
+ d[0] = (*(double *) &a0) < (*(double *) &b0) ? a0 : b0;
+ d[1] = (*(double *) &a1) < (*(double *) &b1) ? a1 : b1;
+ return vreinterpretq_m128d_u64(vld1q_u64(d));
+#endif
}
-// Compare packed signed 8-bit integers in a and b, and store packed minimum
-// values in dst.
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_min_epi8
-FORCE_INLINE __m128i _mm_min_epi8(__m128i a, __m128i b)
+// Compare the lower double-precision (64-bit) floating-point elements in a and
+// b, store the minimum value in the lower element of dst, and copy the upper
+// element from a to the upper element of dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_min_sd
+FORCE_INLINE __m128d _mm_min_sd(__m128d a, __m128d b)
{
- return vreinterpretq_m128i_s8(
- vminq_s8(vreinterpretq_s8_m128i(a), vreinterpretq_s8_m128i(b)));
+#if defined(__aarch64__)
+ return _mm_move_sd(a, _mm_min_pd(a, b));
+#else
+ double *da = (double *) &a;
+ double *db = (double *) &b;
+ double c[2] = {fmin(da[0], db[0]), da[1]};
+ return vld1q_f32((float32_t *) c);
+#endif
}
-// Compare packed unsigned 16-bit integers in a and b, and store packed minimum
-// values in dst.
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_min_epu16
-FORCE_INLINE __m128i _mm_min_epu16(__m128i a, __m128i b)
+// Copy the lower 64-bit integer in a to the lower element of dst, and zero the
+// upper element.
+//
+// dst[63:0] := a[63:0]
+// dst[127:64] := 0
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_move_epi64
+FORCE_INLINE __m128i _mm_move_epi64(__m128i a)
{
- return vreinterpretq_m128i_u16(
- vminq_u16(vreinterpretq_u16_m128i(a), vreinterpretq_u16_m128i(b)));
+ return vreinterpretq_m128i_s64(
+ vsetq_lane_s64(0, vreinterpretq_s64_m128i(a), 1));
}
-// Computes the pairwise maxima of the 8 signed 16-bit integers from a and the 8
-// signed 16-bit integers from b.
-// https://msdn.microsoft.com/en-us/LIBRary/3x060h7c(v=vs.100).aspx
-FORCE_INLINE __m128i _mm_max_epi16(__m128i a, __m128i b)
+// Move the lower double-precision (64-bit) floating-point element from b to the
+// lower element of dst, and copy the upper element from a to the upper element
+// of dst.
+//
+// dst[63:0] := b[63:0]
+// dst[127:64] := a[127:64]
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_move_sd
+FORCE_INLINE __m128d _mm_move_sd(__m128d a, __m128d b)
{
- return vreinterpretq_m128i_s16(
- vmaxq_s16(vreinterpretq_s16_m128i(a), vreinterpretq_s16_m128i(b)));
+ return vreinterpretq_m128d_f32(
+ vcombine_f32(vget_low_f32(vreinterpretq_f32_m128d(b)),
+ vget_high_f32(vreinterpretq_f32_m128d(a))));
}
-// epi versions of min/max
-// Computes the pariwise maximums of the four signed 32-bit integer values of a
-// and b.
+// NEON does not provide a version of this function.
+// Creates a 16-bit mask from the most significant bits of the 16 signed or
+// unsigned 8-bit integers in a and zero extends the upper bits.
+// https://msdn.microsoft.com/en-us/library/vstudio/s090c8fk(v=vs.100).aspx
+FORCE_INLINE int _mm_movemask_epi8(__m128i a)
+{
+ // Use increasingly wide shifts+adds to collect the sign bits
+ // together.
+ // Since the widening shifts would be rather confusing to follow in little
+ // endian, everything will be illustrated in big endian order instead. This
+ // has a different result - the bits would actually be reversed on a big
+ // endian machine.
+
+ // Starting input (only half the elements are shown):
+ // 89 ff 1d c0 00 10 99 33
+ uint8x16_t input = vreinterpretq_u8_m128i(a);
+
+ // Shift out everything but the sign bits with an unsigned shift right.
+ //
+ // Bytes of the vector::
+ // 89 ff 1d c0 00 10 99 33
+ // \ \ \ \ \ \ \ \ high_bits = (uint16x4_t)(input >> 7)
+ // | | | | | | | |
+ // 01 01 00 01 00 00 01 00
+ //
+ // Bits of first important lane(s):
+ // 10001001 (89)
+ // \______
+ // |
+ // 00000001 (01)
+ uint16x8_t high_bits = vreinterpretq_u16_u8(vshrq_n_u8(input, 7));
+
+ // Merge the even lanes together with a 16-bit unsigned shift right + add.
+ // 'xx' represents garbage data which will be ignored in the final result.
+ // In the important bytes, the add functions like a binary OR.
+ //
+ // 01 01 00 01 00 00 01 00
+ // \_ | \_ | \_ | \_ | paired16 = (uint32x4_t)(input + (input >> 7))
+ // \| \| \| \|
+ // xx 03 xx 01 xx 00 xx 02
+ //
+ // 00000001 00000001 (01 01)
+ // \_______ |
+ // \|
+ // xxxxxxxx xxxxxx11 (xx 03)
+ uint32x4_t paired16 =
+ vreinterpretq_u32_u16(vsraq_n_u16(high_bits, high_bits, 7));
+
+ // Repeat with a wider 32-bit shift + add.
+ // xx 03 xx 01 xx 00 xx 02
+ // \____ | \____ | paired32 = (uint64x1_t)(paired16 + (paired16 >>
+ // 14))
+ // \| \|
+ // xx xx xx 0d xx xx xx 02
+ //
+ // 00000011 00000001 (03 01)
+ // \\_____ ||
+ // '----.\||
+ // xxxxxxxx xxxx1101 (xx 0d)
+ uint64x2_t paired32 =
+ vreinterpretq_u64_u32(vsraq_n_u32(paired16, paired16, 14));
+
+ // Last, an even wider 64-bit shift + add to get our result in the low 8 bit
+ // lanes. xx xx xx 0d xx xx xx 02
+ // \_________ | paired64 = (uint8x8_t)(paired32 + (paired32 >>
+ // 28))
+ // \|
+ // xx xx xx xx xx xx xx d2
+ //
+ // 00001101 00000010 (0d 02)
+ // \ \___ | |
+ // '---. \| |
+ // xxxxxxxx 11010010 (xx d2)
+ uint8x16_t paired64 =
+ vreinterpretq_u8_u64(vsraq_n_u64(paired32, paired32, 28));
+
+ // Extract the low 8 bits from each 64-bit lane with 2 8-bit extracts.
+ // xx xx xx xx xx xx xx d2
+ // || return paired64[0]
+ // d2
+ // Note: Little endian would return the correct value 4b (01001011) instead.
+ return vgetq_lane_u8(paired64, 0) | ((int) vgetq_lane_u8(paired64, 8) << 8);
+}
+
+// Set each bit of mask dst based on the most significant bit of the
+// corresponding packed double-precision (64-bit) floating-point element in a.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_movemask_pd
+FORCE_INLINE int _mm_movemask_pd(__m128d a)
+{
+ uint64x2_t input = vreinterpretq_u64_m128d(a);
+ uint64x2_t high_bits = vshrq_n_u64(input, 63);
+ return vgetq_lane_u64(high_bits, 0) | (vgetq_lane_u64(high_bits, 1) << 1);
+}
+
+// Copy the lower 64-bit integer in a to dst.
//
-// A 128-bit parameter that can be defined with the following equations:
-// r0 := (a0 > b0) ? a0 : b0
-// r1 := (a1 > b1) ? a1 : b1
-// r2 := (a2 > b2) ? a2 : b2
-// r3 := (a3 > b3) ? a3 : b3
+// dst[63:0] := a[63:0]
//
-// https://msdn.microsoft.com/en-us/library/vstudio/bb514055(v=vs.100).aspx
-FORCE_INLINE __m128i _mm_max_epi32(__m128i a, __m128i b)
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_movepi64_pi64
+FORCE_INLINE __m64 _mm_movepi64_pi64(__m128i a)
{
- return vreinterpretq_m128i_s32(
- vmaxq_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(b)));
+ return vreinterpret_m64_s64(vget_low_s64(vreinterpretq_s64_m128i(a)));
}
-// Computes the pariwise minima of the four signed 32-bit integer values of a
-// and b.
+// Copy the 64-bit integer a to the lower element of dst, and zero the upper
+// element.
//
-// A 128-bit parameter that can be defined with the following equations:
-// r0 := (a0 < b0) ? a0 : b0
-// r1 := (a1 < b1) ? a1 : b1
-// r2 := (a2 < b2) ? a2 : b2
-// r3 := (a3 < b3) ? a3 : b3
+// dst[63:0] := a[63:0]
+// dst[127:64] := 0
//
-// https://msdn.microsoft.com/en-us/library/vstudio/bb531476(v=vs.100).aspx
-FORCE_INLINE __m128i _mm_min_epi32(__m128i a, __m128i b)
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_movpi64_epi64
+FORCE_INLINE __m128i _mm_movpi64_epi64(__m64 a)
{
- return vreinterpretq_m128i_s32(
- vminq_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(b)));
+ return vreinterpretq_m128i_s64(
+ vcombine_s64(vreinterpret_s64_m64(a), vdup_n_s64(0)));
}
-// Compare packed unsigned 32-bit integers in a and b, and store packed maximum
-// values in dst.
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_max_epu32
-FORCE_INLINE __m128i _mm_max_epu32(__m128i a, __m128i b)
+// Multiply the low unsigned 32-bit integers from each packed 64-bit element in
+// a and b, and store the unsigned 64-bit results in dst.
+//
+// r0 := (a0 & 0xFFFFFFFF) * (b0 & 0xFFFFFFFF)
+// r1 := (a2 & 0xFFFFFFFF) * (b2 & 0xFFFFFFFF)
+FORCE_INLINE __m128i _mm_mul_epu32(__m128i a, __m128i b)
{
- return vreinterpretq_m128i_u32(
- vmaxq_u32(vreinterpretq_u32_m128i(a), vreinterpretq_u32_m128i(b)));
+ // vmull_u32 upcasts instead of masking, so we downcast.
+ uint32x2_t a_lo = vmovn_u64(vreinterpretq_u64_m128i(a));
+ uint32x2_t b_lo = vmovn_u64(vreinterpretq_u64_m128i(b));
+ return vreinterpretq_m128i_u64(vmull_u32(a_lo, b_lo));
}
-// Compare packed unsigned 32-bit integers in a and b, and store packed minimum
-// values in dst.
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_max_epu32
-FORCE_INLINE __m128i _mm_min_epu32(__m128i a, __m128i b)
+// Multiply packed double-precision (64-bit) floating-point elements in a and b,
+// and store the results in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mul_pd
+FORCE_INLINE __m128d _mm_mul_pd(__m128d a, __m128d b)
{
- return vreinterpretq_m128i_u32(
- vminq_u32(vreinterpretq_u32_m128i(a), vreinterpretq_u32_m128i(b)));
+#if defined(__aarch64__)
+ return vreinterpretq_m128d_f64(
+ vmulq_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(b)));
+#else
+ double *da = (double *) &a;
+ double *db = (double *) &b;
+ double c[2];
+ c[0] = da[0] * db[0];
+ c[1] = da[1] * db[1];
+ return vld1q_f32((float32_t *) c);
+#endif
}
-// Multiply the packed unsigned 16-bit integers in a and b, producing
-// intermediate 32-bit integers, and store the high 16 bits of the intermediate
-// integers in dst.
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mulhi_pu16
-FORCE_INLINE __m64 _mm_mulhi_pu16(__m64 a, __m64 b)
+// Multiply the lower double-precision (64-bit) floating-point element in a and
+// b, store the result in the lower element of dst, and copy the upper element
+// from a to the upper element of dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=mm_mul_sd
+FORCE_INLINE __m128d _mm_mul_sd(__m128d a, __m128d b)
{
- return vreinterpret_m64_u16(vshrn_n_u32(
- vmull_u16(vreinterpret_u16_m64(a), vreinterpret_u16_m64(b)), 16));
+ return _mm_move_sd(a, _mm_mul_pd(a, b));
+}
+
+// Multiply the low unsigned 32-bit integers from a and b, and store the
+// unsigned 64-bit result in dst.
+//
+// dst[63:0] := a[31:0] * b[31:0]
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mul_su32
+FORCE_INLINE __m64 _mm_mul_su32(__m64 a, __m64 b)
+{
+ return vreinterpret_m64_u64(vget_low_u64(
+ vmull_u32(vreinterpret_u32_m64(a), vreinterpret_u32_m64(b))));
}
// Multiplies the 8 signed 16-bit integers from a by the 8 signed 16-bit
@@ -4321,1341 +4914,2413 @@ FORCE_INLINE __m128i _mm_mulhi_epu16(__m128i a, __m128i b)
#endif
}
-// Computes pairwise add of each argument as single-precision, floating-point
-// values a and b.
-// https://msdn.microsoft.com/en-us/library/yd9wecaa.aspx
-FORCE_INLINE __m128 _mm_hadd_ps(__m128 a, __m128 b)
+// Multiplies the 8 signed or unsigned 16-bit integers from a by the 8 signed or
+// unsigned 16-bit integers from b.
+//
+// r0 := (a0 * b0)[15:0]
+// r1 := (a1 * b1)[15:0]
+// ...
+// r7 := (a7 * b7)[15:0]
+//
+// https://msdn.microsoft.com/en-us/library/vstudio/9ks1472s(v=vs.100).aspx
+FORCE_INLINE __m128i _mm_mullo_epi16(__m128i a, __m128i b)
{
-#if defined(__aarch64__)
- return vreinterpretq_m128_f32(
- vpaddq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b)));
-#else
- float32x2_t a10 = vget_low_f32(vreinterpretq_f32_m128(a));
- float32x2_t a32 = vget_high_f32(vreinterpretq_f32_m128(a));
- float32x2_t b10 = vget_low_f32(vreinterpretq_f32_m128(b));
- float32x2_t b32 = vget_high_f32(vreinterpretq_f32_m128(b));
- return vreinterpretq_m128_f32(
- vcombine_f32(vpadd_f32(a10, a32), vpadd_f32(b10, b32)));
-#endif
+ return vreinterpretq_m128i_s16(
+ vmulq_s16(vreinterpretq_s16_m128i(a), vreinterpretq_s16_m128i(b)));
}
-// Computes pairwise add of each argument as a 16-bit signed or unsigned integer
-// values a and b.
-FORCE_INLINE __m128i _mm_hadd_epi16(__m128i _a, __m128i _b)
+// Compute the bitwise OR of packed double-precision (64-bit) floating-point
+// elements in a and b, and store the results in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=mm_or_pd
+FORCE_INLINE __m128d _mm_or_pd(__m128d a, __m128d b)
{
- int16x8_t a = vreinterpretq_s16_m128i(_a);
- int16x8_t b = vreinterpretq_s16_m128i(_b);
-#if defined(__aarch64__)
- return vreinterpretq_m128i_s16(vpaddq_s16(a, b));
-#else
- return vreinterpretq_m128i_s16(
- vcombine_s16(vpadd_s16(vget_low_s16(a), vget_high_s16(a)),
- vpadd_s16(vget_low_s16(b), vget_high_s16(b))));
-#endif
+ return vreinterpretq_m128d_s64(
+ vorrq_s64(vreinterpretq_s64_m128d(a), vreinterpretq_s64_m128d(b)));
}
-// Horizontally substract adjacent pairs of single-precision (32-bit)
-// floating-point elements in a and b, and pack the results in dst.
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_hsub_ps
-FORCE_INLINE __m128 _mm_hsub_ps(__m128 _a, __m128 _b)
+// Computes the bitwise OR of the 128-bit value in a and the 128-bit value in b.
+//
+// r := a | b
+//
+// https://msdn.microsoft.com/en-us/library/vstudio/ew8ty0db(v=vs.100).aspx
+FORCE_INLINE __m128i _mm_or_si128(__m128i a, __m128i b)
{
-#if defined(__aarch64__)
- return vreinterpretq_m128_f32(vsubq_f32(
- vuzp1q_f32(vreinterpretq_f32_m128(_a), vreinterpretq_f32_m128(_b)),
- vuzp2q_f32(vreinterpretq_f32_m128(_a), vreinterpretq_f32_m128(_b))));
-#else
- float32x4x2_t c =
- vuzpq_f32(vreinterpretq_f32_m128(_a), vreinterpretq_f32_m128(_b));
- return vreinterpretq_m128_f32(vsubq_f32(c.val[0], c.val[1]));
-#endif
+ return vreinterpretq_m128i_s32(
+ vorrq_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(b)));
}
-// Horizontally add adjacent pairs of 16-bit integers in a and b, and pack the
-// signed 16-bit results in dst.
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_hadd_pi16
-FORCE_INLINE __m64 _mm_hadd_pi16(__m64 a, __m64 b)
+// Packs the 16 signed 16-bit integers from a and b into 8-bit integers and
+// saturates.
+// https://msdn.microsoft.com/en-us/library/k4y4f7w5%28v=vs.90%29.aspx
+FORCE_INLINE __m128i _mm_packs_epi16(__m128i a, __m128i b)
{
- return vreinterpret_m64_s16(
- vpadd_s16(vreinterpret_s16_m64(a), vreinterpret_s16_m64(b)));
+ return vreinterpretq_m128i_s8(
+ vcombine_s8(vqmovn_s16(vreinterpretq_s16_m128i(a)),
+ vqmovn_s16(vreinterpretq_s16_m128i(b))));
}
-// Horizontally add adjacent pairs of 32-bit integers in a and b, and pack the
-// signed 32-bit results in dst.
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_hadd_pi32
-FORCE_INLINE __m64 _mm_hadd_pi32(__m64 a, __m64 b)
+// Packs the 8 signed 32-bit integers from a and b into signed 16-bit integers
+// and saturates.
+//
+// r0 := SignedSaturate(a0)
+// r1 := SignedSaturate(a1)
+// r2 := SignedSaturate(a2)
+// r3 := SignedSaturate(a3)
+// r4 := SignedSaturate(b0)
+// r5 := SignedSaturate(b1)
+// r6 := SignedSaturate(b2)
+// r7 := SignedSaturate(b3)
+//
+// https://msdn.microsoft.com/en-us/library/393t56f9%28v=vs.90%29.aspx
+FORCE_INLINE __m128i _mm_packs_epi32(__m128i a, __m128i b)
{
- return vreinterpret_m64_s32(
- vpadd_s32(vreinterpret_s32_m64(a), vreinterpret_s32_m64(b)));
+ return vreinterpretq_m128i_s16(
+ vcombine_s16(vqmovn_s32(vreinterpretq_s32_m128i(a)),
+ vqmovn_s32(vreinterpretq_s32_m128i(b))));
}
-// Computes pairwise difference of each argument as a 16-bit signed or unsigned
-// integer values a and b.
-FORCE_INLINE __m128i _mm_hsub_epi16(__m128i _a, __m128i _b)
+// Packs the 16 signed 16 - bit integers from a and b into 8 - bit unsigned
+// integers and saturates.
+//
+// r0 := UnsignedSaturate(a0)
+// r1 := UnsignedSaturate(a1)
+// ...
+// r7 := UnsignedSaturate(a7)
+// r8 := UnsignedSaturate(b0)
+// r9 := UnsignedSaturate(b1)
+// ...
+// r15 := UnsignedSaturate(b7)
+//
+// https://msdn.microsoft.com/en-us/library/07ad1wx4(v=vs.100).aspx
+FORCE_INLINE __m128i _mm_packus_epi16(const __m128i a, const __m128i b)
{
- int32x4_t a = vreinterpretq_s32_m128i(_a);
- int32x4_t b = vreinterpretq_s32_m128i(_b);
- // Interleave using vshrn/vmovn
- // [a0|a2|a4|a6|b0|b2|b4|b6]
- // [a1|a3|a5|a7|b1|b3|b5|b7]
- int16x8_t ab0246 = vcombine_s16(vmovn_s32(a), vmovn_s32(b));
- int16x8_t ab1357 = vcombine_s16(vshrn_n_s32(a, 16), vshrn_n_s32(b, 16));
- // Subtract
- return vreinterpretq_m128i_s16(vsubq_s16(ab0246, ab1357));
+ return vreinterpretq_m128i_u8(
+ vcombine_u8(vqmovun_s16(vreinterpretq_s16_m128i(a)),
+ vqmovun_s16(vreinterpretq_s16_m128i(b))));
}
-// Computes saturated pairwise sub of each argument as a 16-bit signed
-// integer values a and b.
-FORCE_INLINE __m128i _mm_hadds_epi16(__m128i _a, __m128i _b)
+// Pause the processor. This is typically used in spin-wait loops and depending
+// on the x86 processor typical values are in the 40-100 cycle range. The
+// 'yield' instruction isn't a good fit beacuse it's effectively a nop on most
+// Arm cores. Experience with several databases has shown has shown an 'isb' is
+// a reasonable approximation.
+FORCE_INLINE void _mm_pause()
{
-#if defined(__aarch64__)
- int16x8_t a = vreinterpretq_s16_m128i(_a);
- int16x8_t b = vreinterpretq_s16_m128i(_b);
- return vreinterpretq_s64_s16(
- vqaddq_s16(vuzp1q_s16(a, b), vuzp2q_s16(a, b)));
-#else
- int32x4_t a = vreinterpretq_s32_m128i(_a);
- int32x4_t b = vreinterpretq_s32_m128i(_b);
- // Interleave using vshrn/vmovn
- // [a0|a2|a4|a6|b0|b2|b4|b6]
- // [a1|a3|a5|a7|b1|b3|b5|b7]
- int16x8_t ab0246 = vcombine_s16(vmovn_s32(a), vmovn_s32(b));
- int16x8_t ab1357 = vcombine_s16(vshrn_n_s32(a, 16), vshrn_n_s32(b, 16));
- // Saturated add
- return vreinterpretq_m128i_s16(vqaddq_s16(ab0246, ab1357));
-#endif
+ __asm__ __volatile__("isb\n");
}
-// Computes saturated pairwise difference of each argument as a 16-bit signed
-// integer values a and b.
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_hsubs_epi16
-FORCE_INLINE __m128i _mm_hsubs_epi16(__m128i _a, __m128i _b)
+// Compute the absolute differences of packed unsigned 8-bit integers in a and
+// b, then horizontally sum each consecutive 8 differences to produce two
+// unsigned 16-bit integers, and pack these unsigned 16-bit integers in the low
+// 16 bits of 64-bit elements in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_sad_epu8
+FORCE_INLINE __m128i _mm_sad_epu8(__m128i a, __m128i b)
{
-#if defined(__aarch64__)
- int16x8_t a = vreinterpretq_s16_m128i(_a);
- int16x8_t b = vreinterpretq_s16_m128i(_b);
- return vreinterpretq_s64_s16(
- vqsubq_s16(vuzp1q_s16(a, b), vuzp2q_s16(a, b)));
-#else
- int32x4_t a = vreinterpretq_s32_m128i(_a);
- int32x4_t b = vreinterpretq_s32_m128i(_b);
- // Interleave using vshrn/vmovn
- // [a0|a2|a4|a6|b0|b2|b4|b6]
- // [a1|a3|a5|a7|b1|b3|b5|b7]
- int16x8_t ab0246 = vcombine_s16(vmovn_s32(a), vmovn_s32(b));
- int16x8_t ab1357 = vcombine_s16(vshrn_n_s32(a, 16), vshrn_n_s32(b, 16));
- // Saturated subtract
- return vreinterpretq_m128i_s16(vqsubq_s16(ab0246, ab1357));
-#endif
+ uint16x8_t t = vpaddlq_u8(vabdq_u8((uint8x16_t) a, (uint8x16_t) b));
+ return vreinterpretq_m128i_u64(vpaddlq_u32(vpaddlq_u16(t)));
}
-// Computes pairwise add of each argument as a 32-bit signed or unsigned integer
-// values a and b.
-FORCE_INLINE __m128i _mm_hadd_epi32(__m128i _a, __m128i _b)
+// Sets the 8 signed 16-bit integer values.
+// https://msdn.microsoft.com/en-au/library/3e0fek84(v=vs.90).aspx
+FORCE_INLINE __m128i _mm_set_epi16(short i7,
+ short i6,
+ short i5,
+ short i4,
+ short i3,
+ short i2,
+ short i1,
+ short i0)
{
- int32x4_t a = vreinterpretq_s32_m128i(_a);
- int32x4_t b = vreinterpretq_s32_m128i(_b);
- return vreinterpretq_m128i_s32(
- vcombine_s32(vpadd_s32(vget_low_s32(a), vget_high_s32(a)),
- vpadd_s32(vget_low_s32(b), vget_high_s32(b))));
+ int16_t ALIGN_STRUCT(16) data[8] = {i0, i1, i2, i3, i4, i5, i6, i7};
+ return vreinterpretq_m128i_s16(vld1q_s16(data));
}
-// Computes pairwise difference of each argument as a 32-bit signed or unsigned
-// integer values a and b.
-FORCE_INLINE __m128i _mm_hsub_epi32(__m128i _a, __m128i _b)
+// Sets the 4 signed 32-bit integer values.
+// https://msdn.microsoft.com/en-us/library/vstudio/019beekt(v=vs.100).aspx
+FORCE_INLINE __m128i _mm_set_epi32(int i3, int i2, int i1, int i0)
{
- int64x2_t a = vreinterpretq_s64_m128i(_a);
- int64x2_t b = vreinterpretq_s64_m128i(_b);
- // Interleave using vshrn/vmovn
- // [a0|a2|b0|b2]
- // [a1|a2|b1|b3]
- int32x4_t ab02 = vcombine_s32(vmovn_s64(a), vmovn_s64(b));
- int32x4_t ab13 = vcombine_s32(vshrn_n_s64(a, 32), vshrn_n_s64(b, 32));
- // Subtract
- return vreinterpretq_m128i_s32(vsubq_s32(ab02, ab13));
+ int32_t ALIGN_STRUCT(16) data[4] = {i0, i1, i2, i3};
+ return vreinterpretq_m128i_s32(vld1q_s32(data));
}
-// Kahan summation for accurate summation of floating-point numbers.
-// http://blog.zachbjornson.com/2019/08/11/fast-float-summation.html
-FORCE_INLINE void _sse2neon_kadd_f32(float *sum, float *c, float y)
+// Returns the __m128i structure with its two 64-bit integer values
+// initialized to the values of the two 64-bit integers passed in.
+// https://msdn.microsoft.com/en-us/library/dk2sdw0h(v=vs.120).aspx
+FORCE_INLINE __m128i _mm_set_epi64(__m64 i1, __m64 i2)
{
- y -= *c;
- float t = *sum + y;
- *c = (t - *sum) - y;
- *sum = t;
+ return _mm_set_epi64x((int64_t) i1, (int64_t) i2);
}
-// Conditionally multiply the packed single-precision (32-bit) floating-point
-// elements in a and b using the high 4 bits in imm8, sum the four products,
-// and conditionally store the sum in dst using the low 4 bits of imm.
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_dp_ps
-FORCE_INLINE __m128 _mm_dp_ps(__m128 a, __m128 b, const int imm)
+// Returns the __m128i structure with its two 64-bit integer values
+// initialized to the values of the two 64-bit integers passed in.
+// https://msdn.microsoft.com/en-us/library/dk2sdw0h(v=vs.120).aspx
+FORCE_INLINE __m128i _mm_set_epi64x(int64_t i1, int64_t i2)
{
-#if defined(__aarch64__)
- /* shortcuts */
- if (imm == 0xFF) {
- return _mm_set1_ps(vaddvq_f32(_mm_mul_ps(a, b)));
- }
- if (imm == 0x7F) {
- float32x4_t m = _mm_mul_ps(a, b);
- m[3] = 0;
- return _mm_set1_ps(vaddvq_f32(m));
- }
-#endif
-
- float s = 0, c = 0;
- float32x4_t f32a = vreinterpretq_f32_m128(a);
- float32x4_t f32b = vreinterpretq_f32_m128(b);
-
- /* To improve the accuracy of floating-point summation, Kahan algorithm
- * is used for each operation.
- */
- if (imm & (1 << 4))
- _sse2neon_kadd_f32(&s, &c, f32a[0] * f32b[0]);
- if (imm & (1 << 5))
- _sse2neon_kadd_f32(&s, &c, f32a[1] * f32b[1]);
- if (imm & (1 << 6))
- _sse2neon_kadd_f32(&s, &c, f32a[2] * f32b[2]);
- if (imm & (1 << 7))
- _sse2neon_kadd_f32(&s, &c, f32a[3] * f32b[3]);
- s += c;
-
- float32x4_t res = {
- (imm & 0x1) ? s : 0,
- (imm & 0x2) ? s : 0,
- (imm & 0x4) ? s : 0,
- (imm & 0x8) ? s : 0,
- };
- return vreinterpretq_m128_f32(res);
+ return vreinterpretq_m128i_s64(
+ vcombine_s64(vcreate_s64(i2), vcreate_s64(i1)));
}
-/* Compare operations */
+// Sets the 16 signed 8-bit integer values.
+// https://msdn.microsoft.com/en-us/library/x0cx8zd3(v=vs.90).aspx
+FORCE_INLINE __m128i _mm_set_epi8(signed char b15,
+ signed char b14,
+ signed char b13,
+ signed char b12,
+ signed char b11,
+ signed char b10,
+ signed char b9,
+ signed char b8,
+ signed char b7,
+ signed char b6,
+ signed char b5,
+ signed char b4,
+ signed char b3,
+ signed char b2,
+ signed char b1,
+ signed char b0)
+{
+ int8_t ALIGN_STRUCT(16)
+ data[16] = {(int8_t) b0, (int8_t) b1, (int8_t) b2, (int8_t) b3,
+ (int8_t) b4, (int8_t) b5, (int8_t) b6, (int8_t) b7,
+ (int8_t) b8, (int8_t) b9, (int8_t) b10, (int8_t) b11,
+ (int8_t) b12, (int8_t) b13, (int8_t) b14, (int8_t) b15};
+ return (__m128i) vld1q_s8(data);
+}
-// Compares for less than
-// https://msdn.microsoft.com/en-us/library/vstudio/f330yhc8(v=vs.100).aspx
-FORCE_INLINE __m128 _mm_cmplt_ps(__m128 a, __m128 b)
+// Set packed double-precision (64-bit) floating-point elements in dst with the
+// supplied values.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_set_pd
+FORCE_INLINE __m128d _mm_set_pd(double e1, double e0)
{
- return vreinterpretq_m128_u32(
- vcltq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b)));
+ double ALIGN_STRUCT(16) data[2] = {e0, e1};
+#if defined(__aarch64__)
+ return vreinterpretq_m128d_f64(vld1q_f64((float64_t *) data));
+#else
+ return vreinterpretq_m128d_f32(vld1q_f32((float32_t *) data));
+#endif
}
-// Compares for less than
-// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/fy94wye7(v=vs.100)
-FORCE_INLINE __m128 _mm_cmplt_ss(__m128 a, __m128 b)
+// Broadcast double-precision (64-bit) floating-point value a to all elements of
+// dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_set_pd1
+#define _mm_set_pd1 _mm_set1_pd
+
+// Copy double-precision (64-bit) floating-point element a to the lower element
+// of dst, and zero the upper element.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_set_sd
+FORCE_INLINE __m128d _mm_set_sd(double a)
{
- return _mm_move_ss(a, _mm_cmplt_ps(a, b));
+ return _mm_set_pd(0, a);
}
-// Compares for greater than.
+// Sets the 8 signed 16-bit integer values to w.
//
-// r0 := (a0 > b0) ? 0xffffffff : 0x0
-// r1 := (a1 > b1) ? 0xffffffff : 0x0
-// r2 := (a2 > b2) ? 0xffffffff : 0x0
-// r3 := (a3 > b3) ? 0xffffffff : 0x0
+// r0 := w
+// r1 := w
+// ...
+// r7 := w
//
-// https://msdn.microsoft.com/en-us/library/vstudio/11dy102s(v=vs.100).aspx
-FORCE_INLINE __m128 _mm_cmpgt_ps(__m128 a, __m128 b)
+// https://msdn.microsoft.com/en-us/library/k0ya3x0e(v=vs.90).aspx
+FORCE_INLINE __m128i _mm_set1_epi16(short w)
{
- return vreinterpretq_m128_u32(
- vcgtq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b)));
+ return vreinterpretq_m128i_s16(vdupq_n_s16(w));
}
-// Compares for greater than.
-// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/1xyyyy9e(v=vs.100)
-FORCE_INLINE __m128 _mm_cmpgt_ss(__m128 a, __m128 b)
+// Sets the 4 signed 32-bit integer values to i.
+//
+// r0 := i
+// r1 := i
+// r2 := i
+// r3 := I
+//
+// https://msdn.microsoft.com/en-us/library/vstudio/h4xscxat(v=vs.100).aspx
+FORCE_INLINE __m128i _mm_set1_epi32(int _i)
{
- return _mm_move_ss(a, _mm_cmpgt_ps(a, b));
+ return vreinterpretq_m128i_s32(vdupq_n_s32(_i));
}
-// Compares for greater than or equal.
-// https://msdn.microsoft.com/en-us/library/vstudio/fs813y2t(v=vs.100).aspx
-FORCE_INLINE __m128 _mm_cmpge_ps(__m128 a, __m128 b)
+// Sets the 2 signed 64-bit integer values to i.
+// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/whtfzhzk(v=vs.100)
+FORCE_INLINE __m128i _mm_set1_epi64(__m64 _i)
{
- return vreinterpretq_m128_u32(
- vcgeq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b)));
+ return vreinterpretq_m128i_s64(vdupq_n_s64((int64_t) _i));
}
-// Compares for greater than or equal.
-// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/kesh3ddc(v=vs.100)
-FORCE_INLINE __m128 _mm_cmpge_ss(__m128 a, __m128 b)
+// Sets the 2 signed 64-bit integer values to i.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_set1_epi64x
+FORCE_INLINE __m128i _mm_set1_epi64x(int64_t _i)
{
- return _mm_move_ss(a, _mm_cmpge_ps(a, b));
+ return vreinterpretq_m128i_s64(vdupq_n_s64(_i));
}
-// Compares for less than or equal.
+// Sets the 16 signed 8-bit integer values to b.
//
-// r0 := (a0 <= b0) ? 0xffffffff : 0x0
-// r1 := (a1 <= b1) ? 0xffffffff : 0x0
-// r2 := (a2 <= b2) ? 0xffffffff : 0x0
-// r3 := (a3 <= b3) ? 0xffffffff : 0x0
+// r0 := b
+// r1 := b
+// ...
+// r15 := b
//
-// https://msdn.microsoft.com/en-us/library/vstudio/1s75w83z(v=vs.100).aspx
-FORCE_INLINE __m128 _mm_cmple_ps(__m128 a, __m128 b)
+// https://msdn.microsoft.com/en-us/library/6e14xhyf(v=vs.100).aspx
+FORCE_INLINE __m128i _mm_set1_epi8(signed char w)
{
- return vreinterpretq_m128_u32(
- vcleq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b)));
+ return vreinterpretq_m128i_s8(vdupq_n_s8(w));
}
-// Compares for less than or equal.
-// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/a7x0hbhw(v=vs.100)
-FORCE_INLINE __m128 _mm_cmple_ss(__m128 a, __m128 b)
+// Broadcast double-precision (64-bit) floating-point value a to all elements of
+// dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_set1_pd
+FORCE_INLINE __m128d _mm_set1_pd(double d)
{
- return _mm_move_ss(a, _mm_cmple_ps(a, b));
+#if defined(__aarch64__)
+ return vreinterpretq_m128d_f64(vdupq_n_f64(d));
+#else
+ return vreinterpretq_m128d_s64(vdupq_n_s64(*(int64_t *) &d));
+#endif
}
-// Compares for equality.
-// https://msdn.microsoft.com/en-us/library/vstudio/36aectz5(v=vs.100).aspx
-FORCE_INLINE __m128 _mm_cmpeq_ps(__m128 a, __m128 b)
+// Sets the 8 signed 16-bit integer values in reverse order.
+//
+// Return Value
+// r0 := w0
+// r1 := w1
+// ...
+// r7 := w7
+FORCE_INLINE __m128i _mm_setr_epi16(short w0,
+ short w1,
+ short w2,
+ short w3,
+ short w4,
+ short w5,
+ short w6,
+ short w7)
{
- return vreinterpretq_m128_u32(
- vceqq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b)));
+ int16_t ALIGN_STRUCT(16) data[8] = {w0, w1, w2, w3, w4, w5, w6, w7};
+ return vreinterpretq_m128i_s16(vld1q_s16((int16_t *) data));
}
-// Compares for equality.
-// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/k423z28e(v=vs.100)
-FORCE_INLINE __m128 _mm_cmpeq_ss(__m128 a, __m128 b)
+// Sets the 4 signed 32-bit integer values in reverse order
+// https://technet.microsoft.com/en-us/library/security/27yb3ee5(v=vs.90).aspx
+FORCE_INLINE __m128i _mm_setr_epi32(int i3, int i2, int i1, int i0)
{
- return _mm_move_ss(a, _mm_cmpeq_ps(a, b));
+ int32_t ALIGN_STRUCT(16) data[4] = {i3, i2, i1, i0};
+ return vreinterpretq_m128i_s32(vld1q_s32(data));
}
-// Compares for inequality.
-// https://msdn.microsoft.com/en-us/library/sf44thbx(v=vs.100).aspx
-FORCE_INLINE __m128 _mm_cmpneq_ps(__m128 a, __m128 b)
+// Set packed 64-bit integers in dst with the supplied values in reverse order.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_setr_epi64
+FORCE_INLINE __m128i _mm_setr_epi64(__m64 e1, __m64 e0)
{
- return vreinterpretq_m128_u32(vmvnq_u32(
- vceqq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b))));
+ return vreinterpretq_m128i_s64(vcombine_s64(e1, e0));
}
-// Compares for inequality.
-// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/ekya8fh4(v=vs.100)
-FORCE_INLINE __m128 _mm_cmpneq_ss(__m128 a, __m128 b)
+// Sets the 16 signed 8-bit integer values in reverse order.
+// https://msdn.microsoft.com/en-us/library/2khb9c7k(v=vs.90).aspx
+FORCE_INLINE __m128i _mm_setr_epi8(signed char b0,
+ signed char b1,
+ signed char b2,
+ signed char b3,
+ signed char b4,
+ signed char b5,
+ signed char b6,
+ signed char b7,
+ signed char b8,
+ signed char b9,
+ signed char b10,
+ signed char b11,
+ signed char b12,
+ signed char b13,
+ signed char b14,
+ signed char b15)
{
- return _mm_move_ss(a, _mm_cmpneq_ps(a, b));
+ int8_t ALIGN_STRUCT(16)
+ data[16] = {(int8_t) b0, (int8_t) b1, (int8_t) b2, (int8_t) b3,
+ (int8_t) b4, (int8_t) b5, (int8_t) b6, (int8_t) b7,
+ (int8_t) b8, (int8_t) b9, (int8_t) b10, (int8_t) b11,
+ (int8_t) b12, (int8_t) b13, (int8_t) b14, (int8_t) b15};
+ return (__m128i) vld1q_s8(data);
}
-// Compares for not greater than or equal.
-// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/wsexys62(v=vs.100)
-FORCE_INLINE __m128 _mm_cmpnge_ps(__m128 a, __m128 b)
+// Set packed double-precision (64-bit) floating-point elements in dst with the
+// supplied values in reverse order.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_setr_pd
+FORCE_INLINE __m128d _mm_setr_pd(double e1, double e0)
{
- return _mm_cmplt_ps(a, b);
+ return _mm_set_pd(e0, e1);
}
-// Compares for not greater than or equal.
-// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/fk2y80s8(v=vs.100)
-FORCE_INLINE __m128 _mm_cmpnge_ss(__m128 a, __m128 b)
+// Return vector of type __m128d with all elements set to zero.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_setzero_pd
+FORCE_INLINE __m128d _mm_setzero_pd(void)
{
- return _mm_cmplt_ss(a, b);
+#if defined(__aarch64__)
+ return vreinterpretq_m128d_f64(vdupq_n_f64(0));
+#else
+ return vreinterpretq_m128d_f32(vdupq_n_f32(0));
+#endif
}
-// Compares for not greater than.
-// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/d0xh7w0s(v=vs.100)
-FORCE_INLINE __m128 _mm_cmpngt_ps(__m128 a, __m128 b)
+// Sets the 128-bit value to zero
+// https://msdn.microsoft.com/en-us/library/vstudio/ys7dw0kh(v=vs.100).aspx
+FORCE_INLINE __m128i _mm_setzero_si128(void)
{
- return _mm_cmple_ps(a, b);
+ return vreinterpretq_m128i_s32(vdupq_n_s32(0));
}
-// Compares for not greater than.
-// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/z7x9ydwh(v=vs.100)
-FORCE_INLINE __m128 _mm_cmpngt_ss(__m128 a, __m128 b)
+// Shuffles the 4 signed or unsigned 32-bit integers in a as specified by imm.
+// https://msdn.microsoft.com/en-us/library/56f67xbk%28v=vs.90%29.aspx
+// FORCE_INLINE __m128i _mm_shuffle_epi32(__m128i a,
+// __constrange(0,255) int imm)
+#if __has_builtin(__builtin_shufflevector)
+#define _mm_shuffle_epi32(a, imm) \
+ __extension__({ \
+ int32x4_t _input = vreinterpretq_s32_m128i(a); \
+ int32x4_t _shuf = __builtin_shufflevector( \
+ _input, _input, (imm) & (0x3), ((imm) >> 2) & 0x3, \
+ ((imm) >> 4) & 0x3, ((imm) >> 6) & 0x3); \
+ vreinterpretq_m128i_s32(_shuf); \
+ })
+#else // generic
+#define _mm_shuffle_epi32(a, imm) \
+ __extension__({ \
+ __m128i ret; \
+ switch (imm) { \
+ case _MM_SHUFFLE(1, 0, 3, 2): \
+ ret = _mm_shuffle_epi_1032((a)); \
+ break; \
+ case _MM_SHUFFLE(2, 3, 0, 1): \
+ ret = _mm_shuffle_epi_2301((a)); \
+ break; \
+ case _MM_SHUFFLE(0, 3, 2, 1): \
+ ret = _mm_shuffle_epi_0321((a)); \
+ break; \
+ case _MM_SHUFFLE(2, 1, 0, 3): \
+ ret = _mm_shuffle_epi_2103((a)); \
+ break; \
+ case _MM_SHUFFLE(1, 0, 1, 0): \
+ ret = _mm_shuffle_epi_1010((a)); \
+ break; \
+ case _MM_SHUFFLE(1, 0, 0, 1): \
+ ret = _mm_shuffle_epi_1001((a)); \
+ break; \
+ case _MM_SHUFFLE(0, 1, 0, 1): \
+ ret = _mm_shuffle_epi_0101((a)); \
+ break; \
+ case _MM_SHUFFLE(2, 2, 1, 1): \
+ ret = _mm_shuffle_epi_2211((a)); \
+ break; \
+ case _MM_SHUFFLE(0, 1, 2, 2): \
+ ret = _mm_shuffle_epi_0122((a)); \
+ break; \
+ case _MM_SHUFFLE(3, 3, 3, 2): \
+ ret = _mm_shuffle_epi_3332((a)); \
+ break; \
+ case _MM_SHUFFLE(0, 0, 0, 0): \
+ ret = _mm_shuffle_epi32_splat((a), 0); \
+ break; \
+ case _MM_SHUFFLE(1, 1, 1, 1): \
+ ret = _mm_shuffle_epi32_splat((a), 1); \
+ break; \
+ case _MM_SHUFFLE(2, 2, 2, 2): \
+ ret = _mm_shuffle_epi32_splat((a), 2); \
+ break; \
+ case _MM_SHUFFLE(3, 3, 3, 3): \
+ ret = _mm_shuffle_epi32_splat((a), 3); \
+ break; \
+ default: \
+ ret = _mm_shuffle_epi32_default((a), (imm)); \
+ break; \
+ } \
+ ret; \
+ })
+#endif
+
+// Shuffle double-precision (64-bit) floating-point elements using the control
+// in imm8, and store the results in dst.
+//
+// dst[63:0] := (imm8[0] == 0) ? a[63:0] : a[127:64]
+// dst[127:64] := (imm8[1] == 0) ? b[63:0] : b[127:64]
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_shuffle_pd
+#if __has_builtin(__builtin_shufflevector)
+#define _mm_shuffle_pd(a, b, imm8) \
+ vreinterpretq_m128d_s64(__builtin_shufflevector( \
+ vreinterpretq_s64_m128d(a), vreinterpretq_s64_m128d(b), imm8 & 0x1, \
+ ((imm8 & 0x2) >> 1) + 2))
+#else
+#define _mm_shuffle_pd(a, b, imm8) \
+ _mm_castsi128_pd(_mm_set_epi64x( \
+ vgetq_lane_s64(vreinterpretq_s64_m128d(b), (imm8 & 0x2) >> 1), \
+ vgetq_lane_s64(vreinterpretq_s64_m128d(a), imm8 & 0x1)))
+#endif
+
+// FORCE_INLINE __m128i _mm_shufflehi_epi16(__m128i a,
+// __constrange(0,255) int imm)
+#if __has_builtin(__builtin_shufflevector)
+#define _mm_shufflehi_epi16(a, imm) \
+ __extension__({ \
+ int16x8_t _input = vreinterpretq_s16_m128i(a); \
+ int16x8_t _shuf = __builtin_shufflevector( \
+ _input, _input, 0, 1, 2, 3, ((imm) & (0x3)) + 4, \
+ (((imm) >> 2) & 0x3) + 4, (((imm) >> 4) & 0x3) + 4, \
+ (((imm) >> 6) & 0x3) + 4); \
+ vreinterpretq_m128i_s16(_shuf); \
+ })
+#else // generic
+#define _mm_shufflehi_epi16(a, imm) _mm_shufflehi_epi16_function((a), (imm))
+#endif
+
+// FORCE_INLINE __m128i _mm_shufflelo_epi16(__m128i a,
+// __constrange(0,255) int imm)
+#if __has_builtin(__builtin_shufflevector)
+#define _mm_shufflelo_epi16(a, imm) \
+ __extension__({ \
+ int16x8_t _input = vreinterpretq_s16_m128i(a); \
+ int16x8_t _shuf = __builtin_shufflevector( \
+ _input, _input, ((imm) & (0x3)), (((imm) >> 2) & 0x3), \
+ (((imm) >> 4) & 0x3), (((imm) >> 6) & 0x3), 4, 5, 6, 7); \
+ vreinterpretq_m128i_s16(_shuf); \
+ })
+#else // generic
+#define _mm_shufflelo_epi16(a, imm) _mm_shufflelo_epi16_function((a), (imm))
+#endif
+
+// Shift packed 16-bit integers in a left by count while shifting in zeros, and
+// store the results in dst.
+//
+// FOR j := 0 to 7
+// i := j*16
+// IF count[63:0] > 15
+// dst[i+15:i] := 0
+// ELSE
+// dst[i+15:i] := ZeroExtend16(a[i+15:i] << count[63:0])
+// FI
+// ENDFOR
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_sll_epi16
+FORCE_INLINE __m128i _mm_sll_epi16(__m128i a, __m128i count)
{
- return _mm_cmple_ss(a, b);
+ uint64_t c = vreinterpretq_nth_u64_m128i(count, 0);
+ if (_sse2neon_unlikely(c & ~15))
+ return _mm_setzero_si128();
+
+ int16x8_t vc = vdupq_n_s16((int16_t) c);
+ return vreinterpretq_m128i_s16(vshlq_s16(vreinterpretq_s16_m128i(a), vc));
}
-// Compares for not less than or equal.
-// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/6a330kxw(v=vs.100)
-FORCE_INLINE __m128 _mm_cmpnle_ps(__m128 a, __m128 b)
+// Shift packed 32-bit integers in a left by count while shifting in zeros, and
+// store the results in dst.
+//
+// FOR j := 0 to 3
+// i := j*32
+// IF count[63:0] > 31
+// dst[i+31:i] := 0
+// ELSE
+// dst[i+31:i] := ZeroExtend32(a[i+31:i] << count[63:0])
+// FI
+// ENDFOR
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_sll_epi32
+FORCE_INLINE __m128i _mm_sll_epi32(__m128i a, __m128i count)
{
- return _mm_cmpgt_ps(a, b);
+ uint64_t c = vreinterpretq_nth_u64_m128i(count, 0);
+ if (_sse2neon_unlikely(c & ~31))
+ return _mm_setzero_si128();
+
+ int32x4_t vc = vdupq_n_s32((int32_t) c);
+ return vreinterpretq_m128i_s32(vshlq_s32(vreinterpretq_s32_m128i(a), vc));
}
-// Compares for not less than or equal.
-// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/z7x9ydwh(v=vs.100)
-FORCE_INLINE __m128 _mm_cmpnle_ss(__m128 a, __m128 b)
+// Shift packed 64-bit integers in a left by count while shifting in zeros, and
+// store the results in dst.
+//
+// FOR j := 0 to 1
+// i := j*64
+// IF count[63:0] > 63
+// dst[i+63:i] := 0
+// ELSE
+// dst[i+63:i] := ZeroExtend64(a[i+63:i] << count[63:0])
+// FI
+// ENDFOR
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_sll_epi64
+FORCE_INLINE __m128i _mm_sll_epi64(__m128i a, __m128i count)
{
- return _mm_cmpgt_ss(a, b);
+ uint64_t c = vreinterpretq_nth_u64_m128i(count, 0);
+ if (_sse2neon_unlikely(c & ~63))
+ return _mm_setzero_si128();
+
+ int64x2_t vc = vdupq_n_s64((int64_t) c);
+ return vreinterpretq_m128i_s64(vshlq_s64(vreinterpretq_s64_m128i(a), vc));
}
-// Compares for not less than.
-// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/4686bbdw(v=vs.100)
-FORCE_INLINE __m128 _mm_cmpnlt_ps(__m128 a, __m128 b)
+// Shift packed 16-bit integers in a left by imm8 while shifting in zeros, and
+// store the results in dst.
+//
+// FOR j := 0 to 7
+// i := j*16
+// IF imm8[7:0] > 15
+// dst[i+15:i] := 0
+// ELSE
+// dst[i+15:i] := ZeroExtend16(a[i+15:i] << imm8[7:0])
+// FI
+// ENDFOR
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_slli_epi16
+FORCE_INLINE __m128i _mm_slli_epi16(__m128i a, int imm)
{
- return _mm_cmpge_ps(a, b);
+ if (_sse2neon_unlikely(imm & ~15))
+ return _mm_setzero_si128();
+ return vreinterpretq_m128i_s16(
+ vshlq_s16(vreinterpretq_s16_m128i(a), vdupq_n_s16(imm)));
}
-// Compares for not less than.
-// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/56b9z2wf(v=vs.100)
-FORCE_INLINE __m128 _mm_cmpnlt_ss(__m128 a, __m128 b)
+// Shift packed 32-bit integers in a left by imm8 while shifting in zeros, and
+// store the results in dst.
+//
+// FOR j := 0 to 3
+// i := j*32
+// IF imm8[7:0] > 31
+// dst[i+31:i] := 0
+// ELSE
+// dst[i+31:i] := ZeroExtend32(a[i+31:i] << imm8[7:0])
+// FI
+// ENDFOR
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_slli_epi32
+FORCE_INLINE __m128i _mm_slli_epi32(__m128i a, int imm)
{
- return _mm_cmpge_ss(a, b);
+ if (_sse2neon_unlikely(imm & ~31))
+ return _mm_setzero_si128();
+ return vreinterpretq_m128i_s32(
+ vshlq_s32(vreinterpretq_s32_m128i(a), vdupq_n_s32(imm)));
}
-// Compares the 16 signed or unsigned 8-bit integers in a and the 16 signed or
-// unsigned 8-bit integers in b for equality.
-// https://msdn.microsoft.com/en-us/library/windows/desktop/bz5xk21a(v=vs.90).aspx
-FORCE_INLINE __m128i _mm_cmpeq_epi8(__m128i a, __m128i b)
+// Shift packed 64-bit integers in a left by imm8 while shifting in zeros, and
+// store the results in dst.
+//
+// FOR j := 0 to 1
+// i := j*64
+// IF imm8[7:0] > 63
+// dst[i+63:i] := 0
+// ELSE
+// dst[i+63:i] := ZeroExtend64(a[i+63:i] << imm8[7:0])
+// FI
+// ENDFOR
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_slli_epi64
+FORCE_INLINE __m128i _mm_slli_epi64(__m128i a, int imm)
+{
+ if (_sse2neon_unlikely(imm & ~63))
+ return _mm_setzero_si128();
+ return vreinterpretq_m128i_s64(
+ vshlq_s64(vreinterpretq_s64_m128i(a), vdupq_n_s64(imm)));
+}
+
+// Shift a left by imm8 bytes while shifting in zeros, and store the results in
+// dst.
+//
+// tmp := imm8[7:0]
+// IF tmp > 15
+// tmp := 16
+// FI
+// dst[127:0] := a[127:0] << (tmp*8)
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_slli_si128
+FORCE_INLINE __m128i _mm_slli_si128(__m128i a, int imm)
{
+ if (_sse2neon_unlikely(imm & ~15))
+ return _mm_setzero_si128();
+ uint8x16_t tmp[2] = {vdupq_n_u8(0), vreinterpretq_u8_m128i(a)};
return vreinterpretq_m128i_u8(
- vceqq_s8(vreinterpretq_s8_m128i(a), vreinterpretq_s8_m128i(b)));
+ vld1q_u8(((uint8_t const *) tmp) + (16 - imm)));
}
-// Compare packed double-precision (64-bit) floating-point elements in a and b
-// for equality, and store the results in dst.
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmpeq_pd
-FORCE_INLINE __m128d _mm_cmpeq_pd(__m128d a, __m128d b)
+// Compute the square root of packed double-precision (64-bit) floating-point
+// elements in a, and store the results in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_sqrt_pd
+FORCE_INLINE __m128d _mm_sqrt_pd(__m128d a)
{
#if defined(__aarch64__)
- return vreinterpretq_m128d_u64(
- vceqq_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(b)));
+ return vreinterpretq_m128d_f64(vsqrtq_f64(vreinterpretq_f64_m128d(a)));
#else
- // (a == b) -> (a_lo == b_lo) && (a_hi == b_hi)
- uint32x4_t cmp =
- vceqq_u32(vreinterpretq_u32_m128d(a), vreinterpretq_u32_m128d(b));
- uint32x4_t swapped = vrev64q_u32(cmp);
- return vreinterpretq_m128d_u32(vandq_u32(cmp, swapped));
+ double a0 = sqrt(((double *) &a)[0]);
+ double a1 = sqrt(((double *) &a)[1]);
+ return _mm_set_pd(a1, a0);
#endif
}
-// Compares the 8 signed or unsigned 16-bit integers in a and the 8 signed or
-// unsigned 16-bit integers in b for equality.
-// https://msdn.microsoft.com/en-us/library/2ay060te(v=vs.100).aspx
-FORCE_INLINE __m128i _mm_cmpeq_epi16(__m128i a, __m128i b)
+// Compute the square root of the lower double-precision (64-bit) floating-point
+// element in b, store the result in the lower element of dst, and copy the
+// upper element from a to the upper element of dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_sqrt_sd
+FORCE_INLINE __m128d _mm_sqrt_sd(__m128d a, __m128d b)
{
- return vreinterpretq_m128i_u16(
- vceqq_s16(vreinterpretq_s16_m128i(a), vreinterpretq_s16_m128i(b)));
+#if defined(__aarch64__)
+ return _mm_move_sd(a, _mm_sqrt_pd(b));
+#else
+ return _mm_set_pd(((double *) &a)[1], sqrt(((double *) &b)[0]));
+#endif
}
-// Compare packed 32-bit integers in a and b for equality, and store the results
-// in dst
-FORCE_INLINE __m128i _mm_cmpeq_epi32(__m128i a, __m128i b)
+// Shift packed 16-bit integers in a right by count while shifting in sign bits,
+// and store the results in dst.
+//
+// FOR j := 0 to 7
+// i := j*16
+// IF count[63:0] > 15
+// dst[i+15:i] := (a[i+15] ? 0xFFFF : 0x0)
+// ELSE
+// dst[i+15:i] := SignExtend16(a[i+15:i] >> count[63:0])
+// FI
+// ENDFOR
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_sra_epi16
+FORCE_INLINE __m128i _mm_sra_epi16(__m128i a, __m128i count)
{
- return vreinterpretq_m128i_u32(
- vceqq_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(b)));
+ int64_t c = (int64_t) vget_low_s64((int64x2_t) count);
+ if (_sse2neon_unlikely(c & ~15))
+ return _mm_cmplt_epi16(a, _mm_setzero_si128());
+ return vreinterpretq_m128i_s16(vshlq_s16((int16x8_t) a, vdupq_n_s16(-c)));
}
-// Compare packed 64-bit integers in a and b for equality, and store the results
-// in dst
-FORCE_INLINE __m128i _mm_cmpeq_epi64(__m128i a, __m128i b)
+// Shift packed 32-bit integers in a right by count while shifting in sign bits,
+// and store the results in dst.
+//
+// FOR j := 0 to 3
+// i := j*32
+// IF count[63:0] > 31
+// dst[i+31:i] := (a[i+31] ? 0xFFFFFFFF : 0x0)
+// ELSE
+// dst[i+31:i] := SignExtend32(a[i+31:i] >> count[63:0])
+// FI
+// ENDFOR
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_sra_epi32
+FORCE_INLINE __m128i _mm_sra_epi32(__m128i a, __m128i count)
{
-#if defined(__aarch64__)
- return vreinterpretq_m128i_u64(
- vceqq_u64(vreinterpretq_u64_m128i(a), vreinterpretq_u64_m128i(b)));
-#else
- // ARMv7 lacks vceqq_u64
- // (a == b) -> (a_lo == b_lo) && (a_hi == b_hi)
- uint32x4_t cmp =
- vceqq_u32(vreinterpretq_u32_m128i(a), vreinterpretq_u32_m128i(b));
- uint32x4_t swapped = vrev64q_u32(cmp);
- return vreinterpretq_m128i_u32(vandq_u32(cmp, swapped));
-#endif
+ int64_t c = (int64_t) vget_low_s64((int64x2_t) count);
+ if (_sse2neon_unlikely(c & ~31))
+ return _mm_cmplt_epi32(a, _mm_setzero_si128());
+ return vreinterpretq_m128i_s32(vshlq_s32((int32x4_t) a, vdupq_n_s32(-c)));
}
-// Compares the 16 signed 8-bit integers in a and the 16 signed 8-bit integers
-// in b for lesser than.
-// https://msdn.microsoft.com/en-us/library/windows/desktop/9s46csht(v=vs.90).aspx
-FORCE_INLINE __m128i _mm_cmplt_epi8(__m128i a, __m128i b)
+// Shift packed 16-bit integers in a right by imm8 while shifting in sign
+// bits, and store the results in dst.
+//
+// FOR j := 0 to 7
+// i := j*16
+// IF imm8[7:0] > 15
+// dst[i+15:i] := (a[i+15] ? 0xFFFF : 0x0)
+// ELSE
+// dst[i+15:i] := SignExtend16(a[i+15:i] >> imm8[7:0])
+// FI
+// ENDFOR
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_srai_epi16
+FORCE_INLINE __m128i _mm_srai_epi16(__m128i a, int imm)
{
- return vreinterpretq_m128i_u8(
- vcltq_s8(vreinterpretq_s8_m128i(a), vreinterpretq_s8_m128i(b)));
+ const int count = (imm & ~15) ? 15 : imm;
+ return (__m128i) vshlq_s16((int16x8_t) a, vdupq_n_s16(-count));
}
-// Compares the 16 signed 8-bit integers in a and the 16 signed 8-bit integers
-// in b for greater than.
+// Shift packed 32-bit integers in a right by imm8 while shifting in sign bits,
+// and store the results in dst.
//
-// r0 := (a0 > b0) ? 0xff : 0x0
-// r1 := (a1 > b1) ? 0xff : 0x0
-// ...
-// r15 := (a15 > b15) ? 0xff : 0x0
+// FOR j := 0 to 3
+// i := j*32
+// IF imm8[7:0] > 31
+// dst[i+31:i] := (a[i+31] ? 0xFFFFFFFF : 0x0)
+// ELSE
+// dst[i+31:i] := SignExtend32(a[i+31:i] >> imm8[7:0])
+// FI
+// ENDFOR
//
-// https://msdn.microsoft.com/zh-tw/library/wf45zt2b(v=vs.100).aspx
-FORCE_INLINE __m128i _mm_cmpgt_epi8(__m128i a, __m128i b)
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_srai_epi32
+// FORCE_INLINE __m128i _mm_srai_epi32(__m128i a, __constrange(0,255) int imm)
+#define _mm_srai_epi32(a, imm) \
+ __extension__({ \
+ __m128i ret; \
+ if (_sse2neon_unlikely((imm) == 0)) { \
+ ret = a; \
+ } else if (_sse2neon_likely(0 < (imm) && (imm) < 32)) { \
+ ret = vreinterpretq_m128i_s32( \
+ vshlq_s32(vreinterpretq_s32_m128i(a), vdupq_n_s32(-imm))); \
+ } else { \
+ ret = vreinterpretq_m128i_s32( \
+ vshrq_n_s32(vreinterpretq_s32_m128i(a), 31)); \
+ } \
+ ret; \
+ })
+
+// Shift packed 16-bit integers in a right by count while shifting in zeros, and
+// store the results in dst.
+//
+// FOR j := 0 to 7
+// i := j*16
+// IF count[63:0] > 15
+// dst[i+15:i] := 0
+// ELSE
+// dst[i+15:i] := ZeroExtend16(a[i+15:i] >> count[63:0])
+// FI
+// ENDFOR
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_srl_epi16
+FORCE_INLINE __m128i _mm_srl_epi16(__m128i a, __m128i count)
{
- return vreinterpretq_m128i_u8(
- vcgtq_s8(vreinterpretq_s8_m128i(a), vreinterpretq_s8_m128i(b)));
+ uint64_t c = vreinterpretq_nth_u64_m128i(count, 0);
+ if (_sse2neon_unlikely(c & ~15))
+ return _mm_setzero_si128();
+
+ int16x8_t vc = vdupq_n_s16(-(int16_t) c);
+ return vreinterpretq_m128i_u16(vshlq_u16(vreinterpretq_u16_m128i(a), vc));
}
-// Compares the 8 signed 16-bit integers in a and the 8 signed 16-bit integers
-// in b for less than.
+// Shift packed 32-bit integers in a right by count while shifting in zeros, and
+// store the results in dst.
//
-// r0 := (a0 < b0) ? 0xffff : 0x0
-// r1 := (a1 < b1) ? 0xffff : 0x0
-// ...
-// r7 := (a7 < b7) ? 0xffff : 0x0
+// FOR j := 0 to 3
+// i := j*32
+// IF count[63:0] > 31
+// dst[i+31:i] := 0
+// ELSE
+// dst[i+31:i] := ZeroExtend32(a[i+31:i] >> count[63:0])
+// FI
+// ENDFOR
//
-// https://technet.microsoft.com/en-us/library/t863edb2(v=vs.100).aspx
-FORCE_INLINE __m128i _mm_cmplt_epi16(__m128i a, __m128i b)
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_srl_epi32
+FORCE_INLINE __m128i _mm_srl_epi32(__m128i a, __m128i count)
{
- return vreinterpretq_m128i_u16(
- vcltq_s16(vreinterpretq_s16_m128i(a), vreinterpretq_s16_m128i(b)));
+ uint64_t c = vreinterpretq_nth_u64_m128i(count, 0);
+ if (_sse2neon_unlikely(c & ~31))
+ return _mm_setzero_si128();
+
+ int32x4_t vc = vdupq_n_s32(-(int32_t) c);
+ return vreinterpretq_m128i_u32(vshlq_u32(vreinterpretq_u32_m128i(a), vc));
}
-// Compares the 8 signed 16-bit integers in a and the 8 signed 16-bit integers
-// in b for greater than.
+// Shift packed 64-bit integers in a right by count while shifting in zeros, and
+// store the results in dst.
//
-// r0 := (a0 > b0) ? 0xffff : 0x0
-// r1 := (a1 > b1) ? 0xffff : 0x0
-// ...
-// r7 := (a7 > b7) ? 0xffff : 0x0
+// FOR j := 0 to 1
+// i := j*64
+// IF count[63:0] > 63
+// dst[i+63:i] := 0
+// ELSE
+// dst[i+63:i] := ZeroExtend64(a[i+63:i] >> count[63:0])
+// FI
+// ENDFOR
//
-// https://technet.microsoft.com/en-us/library/xd43yfsa(v=vs.100).aspx
-FORCE_INLINE __m128i _mm_cmpgt_epi16(__m128i a, __m128i b)
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_srl_epi64
+FORCE_INLINE __m128i _mm_srl_epi64(__m128i a, __m128i count)
{
- return vreinterpretq_m128i_u16(
- vcgtq_s16(vreinterpretq_s16_m128i(a), vreinterpretq_s16_m128i(b)));
+ uint64_t c = vreinterpretq_nth_u64_m128i(count, 0);
+ if (_sse2neon_unlikely(c & ~63))
+ return _mm_setzero_si128();
+
+ int64x2_t vc = vdupq_n_s64(-(int64_t) c);
+ return vreinterpretq_m128i_u64(vshlq_u64(vreinterpretq_u64_m128i(a), vc));
}
+// Shift packed 16-bit integers in a right by imm8 while shifting in zeros, and
+// store the results in dst.
+//
+// FOR j := 0 to 7
+// i := j*16
+// IF imm8[7:0] > 15
+// dst[i+15:i] := 0
+// ELSE
+// dst[i+15:i] := ZeroExtend16(a[i+15:i] >> imm8[7:0])
+// FI
+// ENDFOR
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_srli_epi16
+#define _mm_srli_epi16(a, imm) \
+ __extension__({ \
+ __m128i ret; \
+ if (_sse2neon_unlikely(imm & ~15)) { \
+ ret = _mm_setzero_si128(); \
+ } else { \
+ ret = vreinterpretq_m128i_u16( \
+ vshlq_u16(vreinterpretq_u16_m128i(a), vdupq_n_s16(-imm))); \
+ } \
+ ret; \
+ })
+
+// Shift packed 32-bit integers in a right by imm8 while shifting in zeros, and
+// store the results in dst.
+//
+// FOR j := 0 to 3
+// i := j*32
+// IF imm8[7:0] > 31
+// dst[i+31:i] := 0
+// ELSE
+// dst[i+31:i] := ZeroExtend32(a[i+31:i] >> imm8[7:0])
+// FI
+// ENDFOR
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_srli_epi32
+// FORCE_INLINE __m128i _mm_srli_epi32(__m128i a, __constrange(0,255) int imm)
+#define _mm_srli_epi32(a, imm) \
+ __extension__({ \
+ __m128i ret; \
+ if (_sse2neon_unlikely(imm & ~31)) { \
+ ret = _mm_setzero_si128(); \
+ } else { \
+ ret = vreinterpretq_m128i_u32( \
+ vshlq_u32(vreinterpretq_u32_m128i(a), vdupq_n_s32(-imm))); \
+ } \
+ ret; \
+ })
-// Compares the 4 signed 32-bit integers in a and the 4 signed 32-bit integers
-// in b for less than.
-// https://msdn.microsoft.com/en-us/library/vstudio/4ak0bf5d(v=vs.100).aspx
-FORCE_INLINE __m128i _mm_cmplt_epi32(__m128i a, __m128i b)
+// Shift packed 64-bit integers in a right by imm8 while shifting in zeros, and
+// store the results in dst.
+//
+// FOR j := 0 to 1
+// i := j*64
+// IF imm8[7:0] > 63
+// dst[i+63:i] := 0
+// ELSE
+// dst[i+63:i] := ZeroExtend64(a[i+63:i] >> imm8[7:0])
+// FI
+// ENDFOR
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_srli_epi64
+#define _mm_srli_epi64(a, imm) \
+ __extension__({ \
+ __m128i ret; \
+ if (_sse2neon_unlikely(imm & ~63)) { \
+ ret = _mm_setzero_si128(); \
+ } else { \
+ ret = vreinterpretq_m128i_u64( \
+ vshlq_u64(vreinterpretq_u64_m128i(a), vdupq_n_s64(-imm))); \
+ } \
+ ret; \
+ })
+
+// Shift a right by imm8 bytes while shifting in zeros, and store the results in
+// dst.
+//
+// tmp := imm8[7:0]
+// IF tmp > 15
+// tmp := 16
+// FI
+// dst[127:0] := a[127:0] >> (tmp*8)
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_srli_si128
+FORCE_INLINE __m128i _mm_srli_si128(__m128i a, int imm)
{
- return vreinterpretq_m128i_u32(
- vcltq_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(b)));
+ if (_sse2neon_unlikely(imm & ~15))
+ return _mm_setzero_si128();
+ uint8x16_t tmp[2] = {vreinterpretq_u8_m128i(a), vdupq_n_u8(0)};
+ return vreinterpretq_m128i_u8(vld1q_u8(((uint8_t const *) tmp) + imm));
}
-// Compares the 4 signed 32-bit integers in a and the 4 signed 32-bit integers
-// in b for greater than.
-// https://msdn.microsoft.com/en-us/library/vstudio/1s9f2z0y(v=vs.100).aspx
-FORCE_INLINE __m128i _mm_cmpgt_epi32(__m128i a, __m128i b)
+// Store 128-bits (composed of 2 packed double-precision (64-bit) floating-point
+// elements) from a into memory. mem_addr must be aligned on a 16-byte boundary
+// or a general-protection exception may be generated.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_store_pd
+FORCE_INLINE void _mm_store_pd(double *mem_addr, __m128d a)
{
- return vreinterpretq_m128i_u32(
- vcgtq_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(b)));
+#if defined(__aarch64__)
+ vst1q_f64((float64_t *) mem_addr, vreinterpretq_f64_m128d(a));
+#else
+ vst1q_f32((float32_t *) mem_addr, vreinterpretq_f32_m128d(a));
+#endif
}
-// Compares the 2 signed 64-bit integers in a and the 2 signed 64-bit integers
-// in b for greater than.
-FORCE_INLINE __m128i _mm_cmpgt_epi64(__m128i a, __m128i b)
+// Store the lower double-precision (64-bit) floating-point element from a into
+// 2 contiguous elements in memory. mem_addr must be aligned on a 16-byte
+// boundary or a general-protection exception may be generated.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_store_pd1
+FORCE_INLINE void _mm_store_pd1(double *mem_addr, __m128d a)
{
#if defined(__aarch64__)
- return vreinterpretq_m128i_u64(
- vcgtq_s64(vreinterpretq_s64_m128i(a), vreinterpretq_s64_m128i(b)));
+ float64x1_t a_low = vget_low_f64(vreinterpretq_f64_m128d(a));
+ vst1q_f64((float64_t *) mem_addr,
+ vreinterpretq_f64_m128d(vcombine_f64(a_low, a_low)));
#else
- // ARMv7 lacks vcgtq_s64.
- // This is based off of Clang's SSE2 polyfill:
- // (a > b) -> ((a_hi > b_hi) || (a_lo > b_lo && a_hi == b_hi))
-
- // Mask the sign bit out since we need a signed AND an unsigned comparison
- // and it is ugly to try and split them.
- int32x4_t mask = vreinterpretq_s32_s64(vdupq_n_s64(0x80000000ull));
- int32x4_t a_mask = veorq_s32(vreinterpretq_s32_m128i(a), mask);
- int32x4_t b_mask = veorq_s32(vreinterpretq_s32_m128i(b), mask);
- // Check if a > b
- int64x2_t greater = vreinterpretq_s64_u32(vcgtq_s32(a_mask, b_mask));
- // Copy upper mask to lower mask
- // a_hi > b_hi
- int64x2_t gt_hi = vshrq_n_s64(greater, 63);
- // Copy lower mask to upper mask
- // a_lo > b_lo
- int64x2_t gt_lo = vsliq_n_s64(greater, greater, 32);
- // Compare for equality
- int64x2_t equal = vreinterpretq_s64_u32(vceqq_s32(a_mask, b_mask));
- // Copy upper mask to lower mask
- // a_hi == b_hi
- int64x2_t eq_hi = vshrq_n_s64(equal, 63);
- // a_hi > b_hi || (a_lo > b_lo && a_hi == b_hi)
- int64x2_t ret = vorrq_s64(gt_hi, vandq_s64(gt_lo, eq_hi));
- return vreinterpretq_m128i_s64(ret);
+ float32x2_t a_low = vget_low_f32(vreinterpretq_f32_m128d(a));
+ vst1q_f32((float32_t *) mem_addr,
+ vreinterpretq_f32_m128d(vcombine_f32(a_low, a_low)));
#endif
}
-// Compares the four 32-bit floats in a and b to check if any values are NaN.
-// Ordered compare between each value returns true for "orderable" and false for
-// "not orderable" (NaN).
-// https://msdn.microsoft.com/en-us/library/vstudio/0h9w00fx(v=vs.100).aspx see
-// also:
-// http://stackoverflow.com/questions/8627331/what-does-ordered-unordered-comparison-mean
-// http://stackoverflow.com/questions/29349621/neon-isnanval-intrinsics
-FORCE_INLINE __m128 _mm_cmpord_ps(__m128 a, __m128 b)
+// Store the lower double-precision (64-bit) floating-point element from a into
+// memory. mem_addr does not need to be aligned on any particular boundary.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=mm_store_sd
+FORCE_INLINE void _mm_store_sd(double *mem_addr, __m128d a)
{
- // Note: NEON does not have ordered compare builtin
- // Need to compare a eq a and b eq b to check for NaN
- // Do AND of results to get final
- uint32x4_t ceqaa =
- vceqq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(a));
- uint32x4_t ceqbb =
- vceqq_f32(vreinterpretq_f32_m128(b), vreinterpretq_f32_m128(b));
- return vreinterpretq_m128_u32(vandq_u32(ceqaa, ceqbb));
+#if defined(__aarch64__)
+ vst1_f64((float64_t *) mem_addr, vget_low_f64(vreinterpretq_f64_m128d(a)));
+#else
+ vst1_u64((uint64_t *) mem_addr, vget_low_u64(vreinterpretq_u64_m128d(a)));
+#endif
}
-// Compares for ordered.
-// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/343t62da(v=vs.100)
-FORCE_INLINE __m128 _mm_cmpord_ss(__m128 a, __m128 b)
+// Stores four 32-bit integer values as (as a __m128i value) at the address p.
+// https://msdn.microsoft.com/en-us/library/vstudio/edk11s13(v=vs.100).aspx
+FORCE_INLINE void _mm_store_si128(__m128i *p, __m128i a)
{
- return _mm_move_ss(a, _mm_cmpord_ps(a, b));
+ vst1q_s32((int32_t *) p, vreinterpretq_s32_m128i(a));
}
-// Compares for unordered.
-// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/khy6fk1t(v=vs.100)
-FORCE_INLINE __m128 _mm_cmpunord_ps(__m128 a, __m128 b)
+// Store the lower double-precision (64-bit) floating-point element from a into
+// 2 contiguous elements in memory. mem_addr must be aligned on a 16-byte
+// boundary or a general-protection exception may be generated.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#expand=9,526,5601&text=_mm_store1_pd
+#define _mm_store1_pd _mm_store_pd1
+
+// Store the upper double-precision (64-bit) floating-point element from a into
+// memory.
+//
+// MEM[mem_addr+63:mem_addr] := a[127:64]
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_storeh_pd
+FORCE_INLINE void _mm_storeh_pd(double *mem_addr, __m128d a)
{
- uint32x4_t f32a =
- vceqq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(a));
- uint32x4_t f32b =
- vceqq_f32(vreinterpretq_f32_m128(b), vreinterpretq_f32_m128(b));
- return vreinterpretq_m128_u32(vmvnq_u32(vandq_u32(f32a, f32b)));
+#if defined(__aarch64__)
+ vst1_f64((float64_t *) mem_addr, vget_high_f64(vreinterpretq_f64_m128d(a)));
+#else
+ vst1_f32((float32_t *) mem_addr, vget_high_f32(vreinterpretq_f32_m128d(a)));
+#endif
}
-// Compares for unordered.
-// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/2as2387b(v=vs.100)
-FORCE_INLINE __m128 _mm_cmpunord_ss(__m128 a, __m128 b)
+// Reads the lower 64 bits of b and stores them into the lower 64 bits of a.
+// https://msdn.microsoft.com/en-us/library/hhwf428f%28v=vs.90%29.aspx
+FORCE_INLINE void _mm_storel_epi64(__m128i *a, __m128i b)
{
- return _mm_move_ss(a, _mm_cmpunord_ps(a, b));
+ uint64x1_t hi = vget_high_u64(vreinterpretq_u64_m128i(*a));
+ uint64x1_t lo = vget_low_u64(vreinterpretq_u64_m128i(b));
+ *a = vreinterpretq_m128i_u64(vcombine_u64(lo, hi));
}
-// Compares the lower single-precision floating point scalar values of a and b
-// using a less than operation. :
-// https://msdn.microsoft.com/en-us/library/2kwe606b(v=vs.90).aspx Important
-// note!! The documentation on MSDN is incorrect! If either of the values is a
-// NAN the docs say you will get a one, but in fact, it will return a zero!!
-FORCE_INLINE int _mm_comilt_ss(__m128 a, __m128 b)
+// Store the lower double-precision (64-bit) floating-point element from a into
+// memory.
+//
+// MEM[mem_addr+63:mem_addr] := a[63:0]
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_storel_pd
+FORCE_INLINE void _mm_storel_pd(double *mem_addr, __m128d a)
{
- uint32x4_t a_not_nan =
- vceqq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(a));
- uint32x4_t b_not_nan =
- vceqq_f32(vreinterpretq_f32_m128(b), vreinterpretq_f32_m128(b));
- uint32x4_t a_and_b_not_nan = vandq_u32(a_not_nan, b_not_nan);
- uint32x4_t a_lt_b =
- vcltq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b));
- return (vgetq_lane_u32(vandq_u32(a_and_b_not_nan, a_lt_b), 0) != 0) ? 1 : 0;
+#if defined(__aarch64__)
+ vst1_f64((float64_t *) mem_addr, vget_low_f64(vreinterpretq_f64_m128d(a)));
+#else
+ vst1_f32((float32_t *) mem_addr, vget_low_f32(vreinterpretq_f32_m128d(a)));
+#endif
}
-// Compares the lower single-precision floating point scalar values of a and b
-// using a greater than operation. :
-// https://msdn.microsoft.com/en-us/library/b0738e0t(v=vs.100).aspx
-FORCE_INLINE int _mm_comigt_ss(__m128 a, __m128 b)
+// Store 2 double-precision (64-bit) floating-point elements from a into memory
+// in reverse order. mem_addr must be aligned on a 16-byte boundary or a
+// general-protection exception may be generated.
+//
+// MEM[mem_addr+63:mem_addr] := a[127:64]
+// MEM[mem_addr+127:mem_addr+64] := a[63:0]
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_storer_pd
+FORCE_INLINE void _mm_storer_pd(double *mem_addr, __m128d a)
{
- // return vgetq_lane_u32(vcgtq_f32(vreinterpretq_f32_m128(a),
- // vreinterpretq_f32_m128(b)), 0);
- uint32x4_t a_not_nan =
- vceqq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(a));
- uint32x4_t b_not_nan =
- vceqq_f32(vreinterpretq_f32_m128(b), vreinterpretq_f32_m128(b));
- uint32x4_t a_and_b_not_nan = vandq_u32(a_not_nan, b_not_nan);
- uint32x4_t a_gt_b =
- vcgtq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b));
- return (vgetq_lane_u32(vandq_u32(a_and_b_not_nan, a_gt_b), 0) != 0) ? 1 : 0;
+ float32x4_t f = vreinterpretq_f32_m128d(a);
+ _mm_store_pd(mem_addr, vreinterpretq_m128d_f32(vextq_f32(f, f, 2)));
}
-// Compares the lower single-precision floating point scalar values of a and b
-// using a less than or equal operation. :
-// https://msdn.microsoft.com/en-us/library/1w4t7c57(v=vs.90).aspx
-FORCE_INLINE int _mm_comile_ss(__m128 a, __m128 b)
+// Store 128-bits (composed of 2 packed double-precision (64-bit) floating-point
+// elements) from a into memory. mem_addr does not need to be aligned on any
+// particular boundary.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_storeu_pd
+FORCE_INLINE void _mm_storeu_pd(double *mem_addr, __m128d a)
{
- // return vgetq_lane_u32(vcleq_f32(vreinterpretq_f32_m128(a),
- // vreinterpretq_f32_m128(b)), 0);
- uint32x4_t a_not_nan =
- vceqq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(a));
- uint32x4_t b_not_nan =
- vceqq_f32(vreinterpretq_f32_m128(b), vreinterpretq_f32_m128(b));
- uint32x4_t a_and_b_not_nan = vandq_u32(a_not_nan, b_not_nan);
- uint32x4_t a_le_b =
- vcleq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b));
- return (vgetq_lane_u32(vandq_u32(a_and_b_not_nan, a_le_b), 0) != 0) ? 1 : 0;
+ _mm_store_pd(mem_addr, a);
}
-// Compares the lower single-precision floating point scalar values of a and b
-// using a greater than or equal operation. :
-// https://msdn.microsoft.com/en-us/library/8t80des6(v=vs.100).aspx
-FORCE_INLINE int _mm_comige_ss(__m128 a, __m128 b)
+// Stores 128-bits of integer data a at the address p.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_storeu_si128
+FORCE_INLINE void _mm_storeu_si128(__m128i *p, __m128i a)
{
- // return vgetq_lane_u32(vcgeq_f32(vreinterpretq_f32_m128(a),
- // vreinterpretq_f32_m128(b)), 0);
- uint32x4_t a_not_nan =
- vceqq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(a));
- uint32x4_t b_not_nan =
- vceqq_f32(vreinterpretq_f32_m128(b), vreinterpretq_f32_m128(b));
- uint32x4_t a_and_b_not_nan = vandq_u32(a_not_nan, b_not_nan);
- uint32x4_t a_ge_b =
- vcgeq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b));
- return (vgetq_lane_u32(vandq_u32(a_and_b_not_nan, a_ge_b), 0) != 0) ? 1 : 0;
+ vst1q_s32((int32_t *) p, vreinterpretq_s32_m128i(a));
}
-// Compares the lower single-precision floating point scalar values of a and b
-// using an equality operation. :
-// https://msdn.microsoft.com/en-us/library/93yx2h2b(v=vs.100).aspx
-FORCE_INLINE int _mm_comieq_ss(__m128 a, __m128 b)
+// Stores 32-bits of integer data a at the address p.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_storeu_si32
+FORCE_INLINE void _mm_storeu_si32(void *p, __m128i a)
{
- // return vgetq_lane_u32(vceqq_f32(vreinterpretq_f32_m128(a),
- // vreinterpretq_f32_m128(b)), 0);
- uint32x4_t a_not_nan =
- vceqq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(a));
- uint32x4_t b_not_nan =
- vceqq_f32(vreinterpretq_f32_m128(b), vreinterpretq_f32_m128(b));
- uint32x4_t a_and_b_not_nan = vandq_u32(a_not_nan, b_not_nan);
- uint32x4_t a_eq_b =
- vceqq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b));
- return (vgetq_lane_u32(vandq_u32(a_and_b_not_nan, a_eq_b), 0) != 0) ? 1 : 0;
+ vst1q_lane_s32((int32_t *) p, vreinterpretq_s32_m128i(a), 0);
}
-// Compares the lower single-precision floating point scalar values of a and b
-// using an inequality operation. :
-// https://msdn.microsoft.com/en-us/library/bafh5e0a(v=vs.90).aspx
-FORCE_INLINE int _mm_comineq_ss(__m128 a, __m128 b)
+// Store 128-bits (composed of 2 packed double-precision (64-bit) floating-point
+// elements) from a into memory using a non-temporal memory hint. mem_addr must
+// be aligned on a 16-byte boundary or a general-protection exception may be
+// generated.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_stream_pd
+FORCE_INLINE void _mm_stream_pd(double *p, __m128d a)
{
- // return !vgetq_lane_u32(vceqq_f32(vreinterpretq_f32_m128(a),
- // vreinterpretq_f32_m128(b)), 0);
- uint32x4_t a_not_nan =
- vceqq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(a));
- uint32x4_t b_not_nan =
- vceqq_f32(vreinterpretq_f32_m128(b), vreinterpretq_f32_m128(b));
- uint32x4_t a_or_b_nan = vmvnq_u32(vandq_u32(a_not_nan, b_not_nan));
- uint32x4_t a_neq_b = vmvnq_u32(
- vceqq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b)));
- return (vgetq_lane_u32(vorrq_u32(a_or_b_nan, a_neq_b), 0) != 0) ? 1 : 0;
+#if __has_builtin(__builtin_nontemporal_store)
+ __builtin_nontemporal_store(a, (float32x4_t *) p);
+#elif defined(__aarch64__)
+ vst1q_f64(p, vreinterpretq_f64_m128d(a));
+#else
+ vst1q_s64((int64_t *) p, vreinterpretq_s64_m128d(a));
+#endif
}
-// according to the documentation, these intrinsics behave the same as the
-// non-'u' versions. We'll just alias them here.
-#define _mm_ucomieq_ss _mm_comieq_ss
-#define _mm_ucomige_ss _mm_comige_ss
-#define _mm_ucomigt_ss _mm_comigt_ss
-#define _mm_ucomile_ss _mm_comile_ss
-#define _mm_ucomilt_ss _mm_comilt_ss
-#define _mm_ucomineq_ss _mm_comineq_ss
+// Stores the data in a to the address p without polluting the caches. If the
+// cache line containing address p is already in the cache, the cache will be
+// updated.
+// https://msdn.microsoft.com/en-us/library/ba08y07y%28v=vs.90%29.aspx
+FORCE_INLINE void _mm_stream_si128(__m128i *p, __m128i a)
+{
+#if __has_builtin(__builtin_nontemporal_store)
+ __builtin_nontemporal_store(a, p);
+#else
+ vst1q_s64((int64_t *) p, vreinterpretq_s64_m128i(a));
+#endif
+}
-/* Conversions */
+// Store 32-bit integer a into memory using a non-temporal hint to minimize
+// cache pollution. If the cache line containing address mem_addr is already in
+// the cache, the cache will be updated.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_stream_si32
+FORCE_INLINE void _mm_stream_si32(int *p, int a)
+{
+ vst1q_lane_s32((int32_t *) p, vdupq_n_s32(a), 0);
+}
-// Convert packed signed 32-bit integers in b to packed single-precision
-// (32-bit) floating-point elements, store the results in the lower 2 elements
-// of dst, and copy the upper 2 packed elements from a to the upper elements of
-// dst.
+// Subtract packed 16-bit integers in b from packed 16-bit integers in a, and
+// store the results in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_sub_epi16
+FORCE_INLINE __m128i _mm_sub_epi16(__m128i a, __m128i b)
+{
+ return vreinterpretq_m128i_s16(
+ vsubq_s16(vreinterpretq_s16_m128i(a), vreinterpretq_s16_m128i(b)));
+}
+
+// Subtracts the 4 signed or unsigned 32-bit integers of b from the 4 signed or
+// unsigned 32-bit integers of a.
//
-// dst[31:0] := Convert_Int32_To_FP32(b[31:0])
-// dst[63:32] := Convert_Int32_To_FP32(b[63:32])
-// dst[95:64] := a[95:64]
-// dst[127:96] := a[127:96]
+// r0 := a0 - b0
+// r1 := a1 - b1
+// r2 := a2 - b2
+// r3 := a3 - b3
//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvt_pi2ps
-FORCE_INLINE __m128 _mm_cvt_pi2ps(__m128 a, __m64 b)
+// https://msdn.microsoft.com/en-us/library/vstudio/fhh866h0(v=vs.100).aspx
+FORCE_INLINE __m128i _mm_sub_epi32(__m128i a, __m128i b)
{
- return vreinterpretq_m128_f32(
- vcombine_f32(vcvt_f32_s32(vreinterpret_s32_m64(b)),
- vget_high_f32(vreinterpretq_f32_m128(a))));
+ return vreinterpretq_m128i_s32(
+ vsubq_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(b)));
}
-// Convert the signed 32-bit integer b to a single-precision (32-bit)
-// floating-point element, store the result in the lower element of dst, and
-// copy the upper 3 packed elements from a to the upper elements of dst.
+// Subtract 2 packed 64-bit integers in b from 2 packed 64-bit integers in a,
+// and store the results in dst.
+// r0 := a0 - b0
+// r1 := a1 - b1
+FORCE_INLINE __m128i _mm_sub_epi64(__m128i a, __m128i b)
+{
+ return vreinterpretq_m128i_s64(
+ vsubq_s64(vreinterpretq_s64_m128i(a), vreinterpretq_s64_m128i(b)));
+}
+
+// Subtract packed 8-bit integers in b from packed 8-bit integers in a, and
+// store the results in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_sub_epi8
+FORCE_INLINE __m128i _mm_sub_epi8(__m128i a, __m128i b)
+{
+ return vreinterpretq_m128i_s8(
+ vsubq_s8(vreinterpretq_s8_m128i(a), vreinterpretq_s8_m128i(b)));
+}
+
+// Subtract packed double-precision (64-bit) floating-point elements in b from
+// packed double-precision (64-bit) floating-point elements in a, and store the
+// results in dst.
//
-// dst[31:0] := Convert_Int32_To_FP32(b[31:0])
-// dst[127:32] := a[127:32]
+// FOR j := 0 to 1
+// i := j*64
+// dst[i+63:i] := a[i+63:i] - b[i+63:i]
+// ENDFOR
//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvt_si2ss
-FORCE_INLINE __m128 _mm_cvt_si2ss(__m128 a, int b)
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=mm_sub_pd
+FORCE_INLINE __m128d _mm_sub_pd(__m128d a, __m128d b)
{
- return vreinterpretq_m128_f32(
- vsetq_lane_f32((float) b, vreinterpretq_f32_m128(a), 0));
+#if defined(__aarch64__)
+ return vreinterpretq_m128d_f64(
+ vsubq_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(b)));
+#else
+ double *da = (double *) &a;
+ double *db = (double *) &b;
+ double c[2];
+ c[0] = da[0] - db[0];
+ c[1] = da[1] - db[1];
+ return vld1q_f32((float32_t *) c);
+#endif
}
-// Convert the signed 32-bit integer b to a single-precision (32-bit)
-// floating-point element, store the result in the lower element of dst, and
-// copy the upper 3 packed elements from a to the upper elements of dst.
+// Subtract the lower double-precision (64-bit) floating-point element in b from
+// the lower double-precision (64-bit) floating-point element in a, store the
+// result in the lower element of dst, and copy the upper element from a to the
+// upper element of dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_sub_sd
+FORCE_INLINE __m128d _mm_sub_sd(__m128d a, __m128d b)
+{
+ return _mm_move_sd(a, _mm_sub_pd(a, b));
+}
+
+// Subtract 64-bit integer b from 64-bit integer a, and store the result in dst.
//
-// dst[31:0] := Convert_Int32_To_FP32(b[31:0])
-// dst[127:32] := a[127:32]
+// dst[63:0] := a[63:0] - b[63:0]
//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtsi32_ss
-#define _mm_cvtsi32_ss(a, b) _mm_cvt_si2ss(a, b)
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_sub_si64
+FORCE_INLINE __m64 _mm_sub_si64(__m64 a, __m64 b)
+{
+ return vreinterpret_m64_s64(
+ vsub_s64(vreinterpret_s64_m64(a), vreinterpret_s64_m64(b)));
+}
-// Convert the signed 64-bit integer b to a single-precision (32-bit)
-// floating-point element, store the result in the lower element of dst, and
-// copy the upper 3 packed elements from a to the upper elements of dst.
+// Subtracts the 8 signed 16-bit integers of b from the 8 signed 16-bit integers
+// of a and saturates.
//
-// dst[31:0] := Convert_Int64_To_FP32(b[63:0])
-// dst[127:32] := a[127:32]
+// r0 := SignedSaturate(a0 - b0)
+// r1 := SignedSaturate(a1 - b1)
+// ...
+// r7 := SignedSaturate(a7 - b7)
//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtsi64_ss
-FORCE_INLINE __m128 _mm_cvtsi64_ss(__m128 a, int64_t b)
+// https://technet.microsoft.com/en-us/subscriptions/3247z5b8(v=vs.90)
+FORCE_INLINE __m128i _mm_subs_epi16(__m128i a, __m128i b)
{
- return vreinterpretq_m128_f32(
- vsetq_lane_f32((float) b, vreinterpretq_f32_m128(a), 0));
+ return vreinterpretq_m128i_s16(
+ vqsubq_s16(vreinterpretq_s16_m128i(a), vreinterpretq_s16_m128i(b)));
}
-// Convert the lower single-precision (32-bit) floating-point element in a to a
-// 32-bit integer, and store the result in dst.
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvt_ss2si
-FORCE_INLINE int _mm_cvt_ss2si(__m128 a)
+// Subtracts the 16 signed 8-bit integers of b from the 16 signed 8-bit integers
+// of a and saturates.
+//
+// r0 := SignedSaturate(a0 - b0)
+// r1 := SignedSaturate(a1 - b1)
+// ...
+// r15 := SignedSaturate(a15 - b15)
+//
+// https://technet.microsoft.com/en-us/subscriptions/by7kzks1(v=vs.90)
+FORCE_INLINE __m128i _mm_subs_epi8(__m128i a, __m128i b)
{
-#if defined(__aarch64__)
- return vgetq_lane_s32(vcvtnq_s32_f32(vreinterpretq_f32_m128(a)), 0);
-#else
- float32_t data = vgetq_lane_f32(vreinterpretq_f32_m128(a), 0);
- float32_t diff = data - floor(data);
- if (diff > 0.5)
- return (int32_t) ceil(data);
- if (unlikely(diff == 0.5)) {
- int32_t f = (int32_t) floor(data);
- int32_t c = (int32_t) ceil(data);
- return c & 1 ? f : c;
- }
- return (int32_t) floor(data);
-#endif
+ return vreinterpretq_m128i_s8(
+ vqsubq_s8(vreinterpretq_s8_m128i(a), vreinterpretq_s8_m128i(b)));
}
-// Convert packed 16-bit integers in a to packed single-precision (32-bit)
-// floating-point elements, and store the results in dst.
+// Subtracts the 8 unsigned 16-bit integers of bfrom the 8 unsigned 16-bit
+// integers of a and saturates..
+// https://technet.microsoft.com/en-us/subscriptions/index/f44y0s19(v=vs.90).aspx
+FORCE_INLINE __m128i _mm_subs_epu16(__m128i a, __m128i b)
+{
+ return vreinterpretq_m128i_u16(
+ vqsubq_u16(vreinterpretq_u16_m128i(a), vreinterpretq_u16_m128i(b)));
+}
+
+// Subtracts the 16 unsigned 8-bit integers of b from the 16 unsigned 8-bit
+// integers of a and saturates.
//
-// FOR j := 0 to 3
-// i := j*16
-// m := j*32
-// dst[m+31:m] := Convert_Int16_To_FP32(a[i+15:i])
-// ENDFOR
+// r0 := UnsignedSaturate(a0 - b0)
+// r1 := UnsignedSaturate(a1 - b1)
+// ...
+// r15 := UnsignedSaturate(a15 - b15)
//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtpi16_ps
-FORCE_INLINE __m128 _mm_cvtpi16_ps(__m64 a)
+// https://technet.microsoft.com/en-us/subscriptions/yadkxc18(v=vs.90)
+FORCE_INLINE __m128i _mm_subs_epu8(__m128i a, __m128i b)
{
- return vreinterpretq_m128_f32(
- vcvtq_f32_s32(vmovl_s16(vreinterpret_s16_m64(a))));
+ return vreinterpretq_m128i_u8(
+ vqsubq_u8(vreinterpretq_u8_m128i(a), vreinterpretq_u8_m128i(b)));
}
-// Convert packed 32-bit integers in b to packed single-precision (32-bit)
-// floating-point elements, store the results in the lower 2 elements of dst,
-// and copy the upper 2 packed elements from a to the upper elements of dst.
+#define _mm_ucomieq_sd _mm_comieq_sd
+#define _mm_ucomige_sd _mm_comige_sd
+#define _mm_ucomigt_sd _mm_comigt_sd
+#define _mm_ucomile_sd _mm_comile_sd
+#define _mm_ucomilt_sd _mm_comilt_sd
+#define _mm_ucomineq_sd _mm_comineq_sd
+
+// Return vector of type __m128d with undefined elements.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_undefined_pd
+FORCE_INLINE __m128d _mm_undefined_pd(void)
+{
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wuninitialized"
+#endif
+ __m128d a;
+ return a;
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+}
+
+// Interleaves the upper 4 signed or unsigned 16-bit integers in a with the
+// upper 4 signed or unsigned 16-bit integers in b.
//
-// dst[31:0] := Convert_Int32_To_FP32(b[31:0])
-// dst[63:32] := Convert_Int32_To_FP32(b[63:32])
-// dst[95:64] := a[95:64]
-// dst[127:96] := a[127:96]
+// r0 := a4
+// r1 := b4
+// r2 := a5
+// r3 := b5
+// r4 := a6
+// r5 := b6
+// r6 := a7
+// r7 := b7
//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtpi32_ps
-FORCE_INLINE __m128 _mm_cvtpi32_ps(__m128 a, __m64 b)
+// https://msdn.microsoft.com/en-us/library/03196cz7(v=vs.100).aspx
+FORCE_INLINE __m128i _mm_unpackhi_epi16(__m128i a, __m128i b)
{
- return vreinterpretq_m128_f32(
- vcombine_f32(vcvt_f32_s32(vreinterpret_s32_m64(b)),
- vget_high_f32(vreinterpretq_f32_m128(a))));
+#if defined(__aarch64__)
+ return vreinterpretq_m128i_s16(
+ vzip2q_s16(vreinterpretq_s16_m128i(a), vreinterpretq_s16_m128i(b)));
+#else
+ int16x4_t a1 = vget_high_s16(vreinterpretq_s16_m128i(a));
+ int16x4_t b1 = vget_high_s16(vreinterpretq_s16_m128i(b));
+ int16x4x2_t result = vzip_s16(a1, b1);
+ return vreinterpretq_m128i_s16(vcombine_s16(result.val[0], result.val[1]));
+#endif
}
-// Convert packed signed 32-bit integers in a to packed single-precision
-// (32-bit) floating-point elements, store the results in the lower 2 elements
-// of dst, then covert the packed signed 32-bit integers in b to
-// single-precision (32-bit) floating-point element, and store the results in
-// the upper 2 elements of dst.
+// Interleaves the upper 2 signed or unsigned 32-bit integers in a with the
+// upper 2 signed or unsigned 32-bit integers in b.
+// https://msdn.microsoft.com/en-us/library/65sa7cbs(v=vs.100).aspx
+FORCE_INLINE __m128i _mm_unpackhi_epi32(__m128i a, __m128i b)
+{
+#if defined(__aarch64__)
+ return vreinterpretq_m128i_s32(
+ vzip2q_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(b)));
+#else
+ int32x2_t a1 = vget_high_s32(vreinterpretq_s32_m128i(a));
+ int32x2_t b1 = vget_high_s32(vreinterpretq_s32_m128i(b));
+ int32x2x2_t result = vzip_s32(a1, b1);
+ return vreinterpretq_m128i_s32(vcombine_s32(result.val[0], result.val[1]));
+#endif
+}
+
+// Interleaves the upper signed or unsigned 64-bit integer in a with the
+// upper signed or unsigned 64-bit integer in b.
//
-// dst[31:0] := Convert_Int32_To_FP32(a[31:0])
-// dst[63:32] := Convert_Int32_To_FP32(a[63:32])
-// dst[95:64] := Convert_Int32_To_FP32(b[31:0])
-// dst[127:96] := Convert_Int32_To_FP32(b[63:32])
+// r0 := a1
+// r1 := b1
+FORCE_INLINE __m128i _mm_unpackhi_epi64(__m128i a, __m128i b)
+{
+ int64x1_t a_h = vget_high_s64(vreinterpretq_s64_m128i(a));
+ int64x1_t b_h = vget_high_s64(vreinterpretq_s64_m128i(b));
+ return vreinterpretq_m128i_s64(vcombine_s64(a_h, b_h));
+}
+
+// Interleaves the upper 8 signed or unsigned 8-bit integers in a with the upper
+// 8 signed or unsigned 8-bit integers in b.
//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtpi32x2_ps
-FORCE_INLINE __m128 _mm_cvtpi32x2_ps(__m64 a, __m64 b)
+// r0 := a8
+// r1 := b8
+// r2 := a9
+// r3 := b9
+// ...
+// r14 := a15
+// r15 := b15
+//
+// https://msdn.microsoft.com/en-us/library/t5h7783k(v=vs.100).aspx
+FORCE_INLINE __m128i _mm_unpackhi_epi8(__m128i a, __m128i b)
{
- return vreinterpretq_m128_f32(vcvtq_f32_s32(
- vcombine_s32(vreinterpret_s32_m64(a), vreinterpret_s32_m64(b))));
+#if defined(__aarch64__)
+ return vreinterpretq_m128i_s8(
+ vzip2q_s8(vreinterpretq_s8_m128i(a), vreinterpretq_s8_m128i(b)));
+#else
+ int8x8_t a1 =
+ vreinterpret_s8_s16(vget_high_s16(vreinterpretq_s16_m128i(a)));
+ int8x8_t b1 =
+ vreinterpret_s8_s16(vget_high_s16(vreinterpretq_s16_m128i(b)));
+ int8x8x2_t result = vzip_s8(a1, b1);
+ return vreinterpretq_m128i_s8(vcombine_s8(result.val[0], result.val[1]));
+#endif
}
-// Convert the lower packed 8-bit integers in a to packed single-precision
-// (32-bit) floating-point elements, and store the results in dst.
+// Unpack and interleave double-precision (64-bit) floating-point elements from
+// the high half of a and b, and store the results in dst.
//
-// FOR j := 0 to 3
-// i := j*8
-// m := j*32
-// dst[m+31:m] := Convert_Int8_To_FP32(a[i+7:i])
-// ENDFOR
+// DEFINE INTERLEAVE_HIGH_QWORDS(src1[127:0], src2[127:0]) {
+// dst[63:0] := src1[127:64]
+// dst[127:64] := src2[127:64]
+// RETURN dst[127:0]
+// }
+// dst[127:0] := INTERLEAVE_HIGH_QWORDS(a[127:0], b[127:0])
//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtpi8_ps
-FORCE_INLINE __m128 _mm_cvtpi8_ps(__m64 a)
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_unpackhi_pd
+FORCE_INLINE __m128d _mm_unpackhi_pd(__m128d a, __m128d b)
{
- return vreinterpretq_m128_f32(vcvtq_f32_s32(
- vmovl_s16(vget_low_s16(vmovl_s8(vreinterpret_s8_m64(a))))));
+#if defined(__aarch64__)
+ return vreinterpretq_m128d_f64(
+ vzip2q_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(b)));
+#else
+ return vreinterpretq_m128d_s64(
+ vcombine_s64(vget_high_s64(vreinterpretq_s64_m128d(a)),
+ vget_high_s64(vreinterpretq_s64_m128d(b))));
+#endif
}
-// Convert packed unsigned 16-bit integers in a to packed single-precision
-// (32-bit) floating-point elements, and store the results in dst.
+// Interleaves the lower 4 signed or unsigned 16-bit integers in a with the
+// lower 4 signed or unsigned 16-bit integers in b.
//
-// FOR j := 0 to 3
-// i := j*16
-// m := j*32
-// dst[m+31:m] := Convert_UInt16_To_FP32(a[i+15:i])
-// ENDFOR
+// r0 := a0
+// r1 := b0
+// r2 := a1
+// r3 := b1
+// r4 := a2
+// r5 := b2
+// r6 := a3
+// r7 := b3
//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtpu16_ps
-FORCE_INLINE __m128 _mm_cvtpu16_ps(__m64 a)
+// https://msdn.microsoft.com/en-us/library/btxb17bw%28v=vs.90%29.aspx
+FORCE_INLINE __m128i _mm_unpacklo_epi16(__m128i a, __m128i b)
{
- return vreinterpretq_m128_f32(
- vcvtq_f32_u32(vmovl_u16(vreinterpret_u16_m64(a))));
+#if defined(__aarch64__)
+ return vreinterpretq_m128i_s16(
+ vzip1q_s16(vreinterpretq_s16_m128i(a), vreinterpretq_s16_m128i(b)));
+#else
+ int16x4_t a1 = vget_low_s16(vreinterpretq_s16_m128i(a));
+ int16x4_t b1 = vget_low_s16(vreinterpretq_s16_m128i(b));
+ int16x4x2_t result = vzip_s16(a1, b1);
+ return vreinterpretq_m128i_s16(vcombine_s16(result.val[0], result.val[1]));
+#endif
}
-// Convert the lower packed unsigned 8-bit integers in a to packed
-// single-precision (32-bit) floating-point elements, and store the results in
-// dst.
+// Interleaves the lower 2 signed or unsigned 32 - bit integers in a with the
+// lower 2 signed or unsigned 32 - bit integers in b.
//
-// FOR j := 0 to 3
-// i := j*8
-// m := j*32
-// dst[m+31:m] := Convert_UInt8_To_FP32(a[i+7:i])
-// ENDFOR
+// r0 := a0
+// r1 := b0
+// r2 := a1
+// r3 := b1
//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtpu8_ps
-FORCE_INLINE __m128 _mm_cvtpu8_ps(__m64 a)
+// https://msdn.microsoft.com/en-us/library/x8atst9d(v=vs.100).aspx
+FORCE_INLINE __m128i _mm_unpacklo_epi32(__m128i a, __m128i b)
{
- return vreinterpretq_m128_f32(vcvtq_f32_u32(
- vmovl_u16(vget_low_u16(vmovl_u8(vreinterpret_u8_m64(a))))));
+#if defined(__aarch64__)
+ return vreinterpretq_m128i_s32(
+ vzip1q_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(b)));
+#else
+ int32x2_t a1 = vget_low_s32(vreinterpretq_s32_m128i(a));
+ int32x2_t b1 = vget_low_s32(vreinterpretq_s32_m128i(b));
+ int32x2x2_t result = vzip_s32(a1, b1);
+ return vreinterpretq_m128i_s32(vcombine_s32(result.val[0], result.val[1]));
+#endif
}
-// Converts the four single-precision, floating-point values of a to signed
-// 32-bit integer values using truncate.
-// https://msdn.microsoft.com/en-us/library/vstudio/1h005y6x(v=vs.100).aspx
-FORCE_INLINE __m128i _mm_cvttps_epi32(__m128 a)
+FORCE_INLINE __m128i _mm_unpacklo_epi64(__m128i a, __m128i b)
{
- return vreinterpretq_m128i_s32(vcvtq_s32_f32(vreinterpretq_f32_m128(a)));
+ int64x1_t a_l = vget_low_s64(vreinterpretq_s64_m128i(a));
+ int64x1_t b_l = vget_low_s64(vreinterpretq_s64_m128i(b));
+ return vreinterpretq_m128i_s64(vcombine_s64(a_l, b_l));
}
-// Convert the lower double-precision (64-bit) floating-point element in a to a
-// 64-bit integer with truncation, and store the result in dst.
+// Interleaves the lower 8 signed or unsigned 8-bit integers in a with the lower
+// 8 signed or unsigned 8-bit integers in b.
//
-// dst[63:0] := Convert_FP64_To_Int64_Truncate(a[63:0])
+// r0 := a0
+// r1 := b0
+// r2 := a1
+// r3 := b1
+// ...
+// r14 := a7
+// r15 := b7
//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvttsd_si64
-FORCE_INLINE int64_t _mm_cvttsd_si64(__m128d a)
+// https://msdn.microsoft.com/en-us/library/xf7k860c%28v=vs.90%29.aspx
+FORCE_INLINE __m128i _mm_unpacklo_epi8(__m128i a, __m128i b)
{
#if defined(__aarch64__)
- return vgetq_lane_s64(vcvtq_s64_f64(vreinterpretq_f64_m128d(a)), 0);
+ return vreinterpretq_m128i_s8(
+ vzip1q_s8(vreinterpretq_s8_m128i(a), vreinterpretq_s8_m128i(b)));
#else
- double ret = *((double *) &a);
- return (int64_t) ret;
+ int8x8_t a1 = vreinterpret_s8_s16(vget_low_s16(vreinterpretq_s16_m128i(a)));
+ int8x8_t b1 = vreinterpret_s8_s16(vget_low_s16(vreinterpretq_s16_m128i(b)));
+ int8x8x2_t result = vzip_s8(a1, b1);
+ return vreinterpretq_m128i_s8(vcombine_s8(result.val[0], result.val[1]));
#endif
}
-// Convert the lower double-precision (64-bit) floating-point element in a to a
-// 64-bit integer with truncation, and store the result in dst.
+// Unpack and interleave double-precision (64-bit) floating-point elements from
+// the low half of a and b, and store the results in dst.
//
-// dst[63:0] := Convert_FP64_To_Int64_Truncate(a[63:0])
+// DEFINE INTERLEAVE_QWORDS(src1[127:0], src2[127:0]) {
+// dst[63:0] := src1[63:0]
+// dst[127:64] := src2[63:0]
+// RETURN dst[127:0]
+// }
+// dst[127:0] := INTERLEAVE_QWORDS(a[127:0], b[127:0])
//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvttsd_si64x
-#define _mm_cvttsd_si64x(a) _mm_cvttsd_si64(a)
-
-// Converts the four signed 32-bit integer values of a to single-precision,
-// floating-point values
-// https://msdn.microsoft.com/en-us/library/vstudio/36bwxcx5(v=vs.100).aspx
-FORCE_INLINE __m128 _mm_cvtepi32_ps(__m128i a)
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_unpacklo_pd
+FORCE_INLINE __m128d _mm_unpacklo_pd(__m128d a, __m128d b)
{
- return vreinterpretq_m128_f32(vcvtq_f32_s32(vreinterpretq_s32_m128i(a)));
+#if defined(__aarch64__)
+ return vreinterpretq_m128d_f64(
+ vzip1q_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(b)));
+#else
+ return vreinterpretq_m128d_s64(
+ vcombine_s64(vget_low_s64(vreinterpretq_s64_m128d(a)),
+ vget_low_s64(vreinterpretq_s64_m128d(b))));
+#endif
}
-// Converts the four unsigned 8-bit integers in the lower 16 bits to four
-// unsigned 32-bit integers.
-FORCE_INLINE __m128i _mm_cvtepu8_epi16(__m128i a)
+// Compute the bitwise XOR of packed double-precision (64-bit) floating-point
+// elements in a and b, and store the results in dst.
+//
+// FOR j := 0 to 1
+// i := j*64
+// dst[i+63:i] := a[i+63:i] XOR b[i+63:i]
+// ENDFOR
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_xor_pd
+FORCE_INLINE __m128d _mm_xor_pd(__m128d a, __m128d b)
{
- uint8x16_t u8x16 = vreinterpretq_u8_m128i(a); /* xxxx xxxx xxxx DCBA */
- uint16x8_t u16x8 = vmovl_u8(vget_low_u8(u8x16)); /* 0x0x 0x0x 0D0C 0B0A */
- return vreinterpretq_m128i_u16(u16x8);
+ return vreinterpretq_m128d_s64(
+ veorq_s64(vreinterpretq_s64_m128d(a), vreinterpretq_s64_m128d(b)));
}
-// Converts the four unsigned 8-bit integers in the lower 32 bits to four
-// unsigned 32-bit integers.
-// https://msdn.microsoft.com/en-us/library/bb531467%28v=vs.100%29.aspx
-FORCE_INLINE __m128i _mm_cvtepu8_epi32(__m128i a)
+// Computes the bitwise XOR of the 128-bit value in a and the 128-bit value in
+// b. https://msdn.microsoft.com/en-us/library/fzt08www(v=vs.100).aspx
+FORCE_INLINE __m128i _mm_xor_si128(__m128i a, __m128i b)
{
- uint8x16_t u8x16 = vreinterpretq_u8_m128i(a); /* xxxx xxxx xxxx DCBA */
- uint16x8_t u16x8 = vmovl_u8(vget_low_u8(u8x16)); /* 0x0x 0x0x 0D0C 0B0A */
- uint32x4_t u32x4 = vmovl_u16(vget_low_u16(u16x8)); /* 000D 000C 000B 000A */
- return vreinterpretq_m128i_u32(u32x4);
+ return vreinterpretq_m128i_s32(
+ veorq_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(b)));
}
-// Converts the two unsigned 8-bit integers in the lower 16 bits to two
-// unsigned 64-bit integers.
-FORCE_INLINE __m128i _mm_cvtepu8_epi64(__m128i a)
+/* SSE3 */
+
+// Alternatively add and subtract packed double-precision (64-bit)
+// floating-point elements in a to/from packed elements in b, and store the
+// results in dst.
+//
+// FOR j := 0 to 1
+// i := j*64
+// IF ((j & 1) == 0)
+// dst[i+63:i] := a[i+63:i] - b[i+63:i]
+// ELSE
+// dst[i+63:i] := a[i+63:i] + b[i+63:i]
+// FI
+// ENDFOR
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_addsub_pd
+FORCE_INLINE __m128d _mm_addsub_pd(__m128d a, __m128d b)
{
- uint8x16_t u8x16 = vreinterpretq_u8_m128i(a); /* xxxx xxxx xxxx xxBA */
- uint16x8_t u16x8 = vmovl_u8(vget_low_u8(u8x16)); /* 0x0x 0x0x 0x0x 0B0A */
- uint32x4_t u32x4 = vmovl_u16(vget_low_u16(u16x8)); /* 000x 000x 000B 000A */
- uint64x2_t u64x2 = vmovl_u32(vget_low_u32(u32x4)); /* 0000 000B 0000 000A */
- return vreinterpretq_m128i_u64(u64x2);
+ __m128d mask = _mm_set_pd(1.0f, -1.0f);
+#if defined(__aarch64__)
+ return vreinterpretq_m128d_f64(vfmaq_f64(vreinterpretq_f64_m128d(a),
+ vreinterpretq_f64_m128d(b),
+ vreinterpretq_f64_m128d(mask)));
+#else
+ return _mm_add_pd(_mm_mul_pd(b, mask), a);
+#endif
}
-// Converts the four unsigned 8-bit integers in the lower 16 bits to four
-// unsigned 32-bit integers.
-FORCE_INLINE __m128i _mm_cvtepi8_epi16(__m128i a)
+// Alternatively add and subtract packed single-precision (32-bit)
+// floating-point elements in a to/from packed elements in b, and store the
+// results in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=addsub_ps
+FORCE_INLINE __m128 _mm_addsub_ps(__m128 a, __m128 b)
{
- int8x16_t s8x16 = vreinterpretq_s8_m128i(a); /* xxxx xxxx xxxx DCBA */
- int16x8_t s16x8 = vmovl_s8(vget_low_s8(s8x16)); /* 0x0x 0x0x 0D0C 0B0A */
- return vreinterpretq_m128i_s16(s16x8);
+ __m128 mask = {-1.0f, 1.0f, -1.0f, 1.0f};
+#if defined(__aarch64__) || defined(__ARM_FEATURE_FMA) /* VFPv4+ */
+ return vreinterpretq_m128_f32(vfmaq_f32(vreinterpretq_f32_m128(a),
+ vreinterpretq_f32_m128(mask),
+ vreinterpretq_f32_m128(b)));
+#else
+ return _mm_add_ps(_mm_mul_ps(b, mask), a);
+#endif
}
-// Converts the four unsigned 8-bit integers in the lower 32 bits to four
-// unsigned 32-bit integers.
-FORCE_INLINE __m128i _mm_cvtepi8_epi32(__m128i a)
+// Horizontally add adjacent pairs of double-precision (64-bit) floating-point
+// elements in a and b, and pack the results in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_hadd_pd
+FORCE_INLINE __m128d _mm_hadd_pd(__m128d a, __m128d b)
{
- int8x16_t s8x16 = vreinterpretq_s8_m128i(a); /* xxxx xxxx xxxx DCBA */
- int16x8_t s16x8 = vmovl_s8(vget_low_s8(s8x16)); /* 0x0x 0x0x 0D0C 0B0A */
- int32x4_t s32x4 = vmovl_s16(vget_low_s16(s16x8)); /* 000D 000C 000B 000A */
- return vreinterpretq_m128i_s32(s32x4);
+#if defined(__aarch64__)
+ return vreinterpretq_m128d_f64(
+ vpaddq_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(b)));
+#else
+ double *da = (double *) &a;
+ double *db = (double *) &b;
+ double c[] = {da[0] + da[1], db[0] + db[1]};
+ return vreinterpretq_m128d_u64(vld1q_u64((uint64_t *) c));
+#endif
}
-// Converts the two signed 8-bit integers in the lower 32 bits to four
-// signed 64-bit integers.
-FORCE_INLINE __m128i _mm_cvtepi8_epi64(__m128i a)
+// Computes pairwise add of each argument as single-precision, floating-point
+// values a and b.
+// https://msdn.microsoft.com/en-us/library/yd9wecaa.aspx
+FORCE_INLINE __m128 _mm_hadd_ps(__m128 a, __m128 b)
{
- int8x16_t s8x16 = vreinterpretq_s8_m128i(a); /* xxxx xxxx xxxx xxBA */
- int16x8_t s16x8 = vmovl_s8(vget_low_s8(s8x16)); /* 0x0x 0x0x 0x0x 0B0A */
- int32x4_t s32x4 = vmovl_s16(vget_low_s16(s16x8)); /* 000x 000x 000B 000A */
- int64x2_t s64x2 = vmovl_s32(vget_low_s32(s32x4)); /* 0000 000B 0000 000A */
- return vreinterpretq_m128i_s64(s64x2);
+#if defined(__aarch64__)
+ return vreinterpretq_m128_f32(
+ vpaddq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b)));
+#else
+ float32x2_t a10 = vget_low_f32(vreinterpretq_f32_m128(a));
+ float32x2_t a32 = vget_high_f32(vreinterpretq_f32_m128(a));
+ float32x2_t b10 = vget_low_f32(vreinterpretq_f32_m128(b));
+ float32x2_t b32 = vget_high_f32(vreinterpretq_f32_m128(b));
+ return vreinterpretq_m128_f32(
+ vcombine_f32(vpadd_f32(a10, a32), vpadd_f32(b10, b32)));
+#endif
}
-// Converts the four signed 16-bit integers in the lower 64 bits to four signed
-// 32-bit integers.
-FORCE_INLINE __m128i _mm_cvtepi16_epi32(__m128i a)
+// Horizontally subtract adjacent pairs of double-precision (64-bit)
+// floating-point elements in a and b, and pack the results in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_hsub_pd
+FORCE_INLINE __m128d _mm_hsub_pd(__m128d _a, __m128d _b)
{
- return vreinterpretq_m128i_s32(
- vmovl_s16(vget_low_s16(vreinterpretq_s16_m128i(a))));
+#if defined(__aarch64__)
+ return vreinterpretq_m128d_f64(vsubq_f64(
+ vuzp1q_f64(vreinterpretq_f64_m128d(_a), vreinterpretq_f64_m128d(_b)),
+ vuzp2q_f64(vreinterpretq_f64_m128d(_a), vreinterpretq_f64_m128d(_b))));
+#else
+ double *da = (double *) &_a;
+ double *db = (double *) &_b;
+ double c[] = {da[0] - da[1], db[0] - db[1]};
+ return vreinterpretq_m128d_u64(vld1q_u64((uint64_t *) c));
+#endif
}
-// Converts the two signed 16-bit integers in the lower 32 bits two signed
-// 32-bit integers.
-FORCE_INLINE __m128i _mm_cvtepi16_epi64(__m128i a)
+// Horizontally substract adjacent pairs of single-precision (32-bit)
+// floating-point elements in a and b, and pack the results in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_hsub_ps
+FORCE_INLINE __m128 _mm_hsub_ps(__m128 _a, __m128 _b)
{
- int16x8_t s16x8 = vreinterpretq_s16_m128i(a); /* xxxx xxxx xxxx 0B0A */
- int32x4_t s32x4 = vmovl_s16(vget_low_s16(s16x8)); /* 000x 000x 000B 000A */
- int64x2_t s64x2 = vmovl_s32(vget_low_s32(s32x4)); /* 0000 000B 0000 000A */
- return vreinterpretq_m128i_s64(s64x2);
+#if defined(__aarch64__)
+ return vreinterpretq_m128_f32(vsubq_f32(
+ vuzp1q_f32(vreinterpretq_f32_m128(_a), vreinterpretq_f32_m128(_b)),
+ vuzp2q_f32(vreinterpretq_f32_m128(_a), vreinterpretq_f32_m128(_b))));
+#else
+ float32x4x2_t c =
+ vuzpq_f32(vreinterpretq_f32_m128(_a), vreinterpretq_f32_m128(_b));
+ return vreinterpretq_m128_f32(vsubq_f32(c.val[0], c.val[1]));
+#endif
}
-// Converts the four unsigned 16-bit integers in the lower 64 bits to four
-// unsigned 32-bit integers.
-FORCE_INLINE __m128i _mm_cvtepu16_epi32(__m128i a)
+// Load 128-bits of integer data from unaligned memory into dst. This intrinsic
+// may perform better than _mm_loadu_si128 when the data crosses a cache line
+// boundary.
+//
+// dst[127:0] := MEM[mem_addr+127:mem_addr]
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_lddqu_si128
+#define _mm_lddqu_si128 _mm_loadu_si128
+
+// Load a double-precision (64-bit) floating-point element from memory into both
+// elements of dst.
+//
+// dst[63:0] := MEM[mem_addr+63:mem_addr]
+// dst[127:64] := MEM[mem_addr+63:mem_addr]
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_loaddup_pd
+#define _mm_loaddup_pd _mm_load1_pd
+
+// Duplicate the low double-precision (64-bit) floating-point element from a,
+// and store the results in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_movedup_pd
+FORCE_INLINE __m128d _mm_movedup_pd(__m128d a)
{
- return vreinterpretq_m128i_u32(
- vmovl_u16(vget_low_u16(vreinterpretq_u16_m128i(a))));
+#if (__aarch64__)
+ return vreinterpretq_m128d_f64(
+ vdupq_laneq_f64(vreinterpretq_f64_m128d(a), 0));
+#else
+ return vreinterpretq_m128d_u64(
+ vdupq_n_u64(vgetq_lane_u64(vreinterpretq_u64_m128d(a), 0)));
+#endif
}
-// Converts the two unsigned 16-bit integers in the lower 32 bits to two
-// unsigned 64-bit integers.
-FORCE_INLINE __m128i _mm_cvtepu16_epi64(__m128i a)
+// Duplicate odd-indexed single-precision (32-bit) floating-point elements
+// from a, and store the results in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_movehdup_ps
+FORCE_INLINE __m128 _mm_movehdup_ps(__m128 a)
{
- uint16x8_t u16x8 = vreinterpretq_u16_m128i(a); /* xxxx xxxx xxxx 0B0A */
- uint32x4_t u32x4 = vmovl_u16(vget_low_u16(u16x8)); /* 000x 000x 000B 000A */
- uint64x2_t u64x2 = vmovl_u32(vget_low_u32(u32x4)); /* 0000 000B 0000 000A */
- return vreinterpretq_m128i_u64(u64x2);
+#if __has_builtin(__builtin_shufflevector)
+ return vreinterpretq_m128_f32(__builtin_shufflevector(
+ vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(a), 1, 1, 3, 3));
+#else
+ float32_t a1 = vgetq_lane_f32(vreinterpretq_f32_m128(a), 1);
+ float32_t a3 = vgetq_lane_f32(vreinterpretq_f32_m128(a), 3);
+ float ALIGN_STRUCT(16) data[4] = {a1, a1, a3, a3};
+ return vreinterpretq_m128_f32(vld1q_f32(data));
+#endif
}
-// Converts the two unsigned 32-bit integers in the lower 64 bits to two
-// unsigned 64-bit integers.
-FORCE_INLINE __m128i _mm_cvtepu32_epi64(__m128i a)
+// Duplicate even-indexed single-precision (32-bit) floating-point elements
+// from a, and store the results in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_moveldup_ps
+FORCE_INLINE __m128 _mm_moveldup_ps(__m128 a)
{
- return vreinterpretq_m128i_u64(
- vmovl_u32(vget_low_u32(vreinterpretq_u32_m128i(a))));
+#if __has_builtin(__builtin_shufflevector)
+ return vreinterpretq_m128_f32(__builtin_shufflevector(
+ vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(a), 0, 0, 2, 2));
+#else
+ float32_t a0 = vgetq_lane_f32(vreinterpretq_f32_m128(a), 0);
+ float32_t a2 = vgetq_lane_f32(vreinterpretq_f32_m128(a), 2);
+ float ALIGN_STRUCT(16) data[4] = {a0, a0, a2, a2};
+ return vreinterpretq_m128_f32(vld1q_f32(data));
+#endif
}
-// Converts the two signed 32-bit integers in the lower 64 bits to two signed
-// 64-bit integers.
-FORCE_INLINE __m128i _mm_cvtepi32_epi64(__m128i a)
+/* SSSE3 */
+
+// Compute the absolute value of packed signed 16-bit integers in a, and store
+// the unsigned results in dst.
+//
+// FOR j := 0 to 7
+// i := j*16
+// dst[i+15:i] := ABS(a[i+15:i])
+// ENDFOR
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_abs_epi16
+FORCE_INLINE __m128i _mm_abs_epi16(__m128i a)
{
- return vreinterpretq_m128i_s64(
- vmovl_s32(vget_low_s32(vreinterpretq_s32_m128i(a))));
+ return vreinterpretq_m128i_s16(vabsq_s16(vreinterpretq_s16_m128i(a)));
}
-// Converts the four single-precision, floating-point values of a to signed
-// 32-bit integer values.
+// Compute the absolute value of packed signed 32-bit integers in a, and store
+// the unsigned results in dst.
//
-// r0 := (int) a0
-// r1 := (int) a1
-// r2 := (int) a2
-// r3 := (int) a3
+// FOR j := 0 to 3
+// i := j*32
+// dst[i+31:i] := ABS(a[i+31:i])
+// ENDFOR
//
-// https://msdn.microsoft.com/en-us/library/vstudio/xdc42k5e(v=vs.100).aspx
-// *NOTE*. The default rounding mode on SSE is 'round to even', which ARMv7-A
-// does not support! It is supported on ARMv8-A however.
-FORCE_INLINE __m128i _mm_cvtps_epi32(__m128 a)
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_abs_epi32
+FORCE_INLINE __m128i _mm_abs_epi32(__m128i a)
{
-#if defined(__aarch64__)
- return vreinterpretq_m128i_s32(vcvtnq_s32_f32(a));
-#else
- uint32x4_t signmask = vdupq_n_u32(0x80000000);
- float32x4_t half = vbslq_f32(signmask, vreinterpretq_f32_m128(a),
- vdupq_n_f32(0.5f)); /* +/- 0.5 */
- int32x4_t r_normal = vcvtq_s32_f32(vaddq_f32(
- vreinterpretq_f32_m128(a), half)); /* round to integer: [a + 0.5]*/
- int32x4_t r_trunc =
- vcvtq_s32_f32(vreinterpretq_f32_m128(a)); /* truncate to integer: [a] */
- int32x4_t plusone = vreinterpretq_s32_u32(vshrq_n_u32(
- vreinterpretq_u32_s32(vnegq_s32(r_trunc)), 31)); /* 1 or 0 */
- int32x4_t r_even = vbicq_s32(vaddq_s32(r_trunc, plusone),
- vdupq_n_s32(1)); /* ([a] + {0,1}) & ~1 */
- float32x4_t delta = vsubq_f32(
- vreinterpretq_f32_m128(a),
- vcvtq_f32_s32(r_trunc)); /* compute delta: delta = (a - [a]) */
- uint32x4_t is_delta_half = vceqq_f32(delta, half); /* delta == +/- 0.5 */
- return vreinterpretq_m128i_s32(vbslq_s32(is_delta_half, r_even, r_normal));
-#endif
+ return vreinterpretq_m128i_s32(vabsq_s32(vreinterpretq_s32_m128i(a)));
}
-// Convert packed single-precision (32-bit) floating-point elements in a to
-// packed 16-bit integers, and store the results in dst. Note: this intrinsic
-// will generate 0x7FFF, rather than 0x8000, for input values between 0x7FFF and
-// 0x7FFFFFFF.
+// Compute the absolute value of packed signed 8-bit integers in a, and store
+// the unsigned results in dst.
//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtps_pi16
-FORCE_INLINE __m64 _mm_cvtps_pi16(__m128 a)
+// FOR j := 0 to 15
+// i := j*8
+// dst[i+7:i] := ABS(a[i+7:i])
+// ENDFOR
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_abs_epi8
+FORCE_INLINE __m128i _mm_abs_epi8(__m128i a)
{
- return vreinterpret_m64_s16(
- vmovn_s32(vreinterpretq_s32_m128i(_mm_cvtps_epi32(a))));
+ return vreinterpretq_m128i_s8(vabsq_s8(vreinterpretq_s8_m128i(a)));
}
-// Copy the lower 32-bit integer in a to dst.
+// Compute the absolute value of packed signed 16-bit integers in a, and store
+// the unsigned results in dst.
//
-// dst[31:0] := a[31:0]
+// FOR j := 0 to 3
+// i := j*16
+// dst[i+15:i] := ABS(a[i+15:i])
+// ENDFOR
//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtsi128_si32
-FORCE_INLINE int _mm_cvtsi128_si32(__m128i a)
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_abs_pi16
+FORCE_INLINE __m64 _mm_abs_pi16(__m64 a)
{
- return vgetq_lane_s32(vreinterpretq_s32_m128i(a), 0);
+ return vreinterpret_m64_s16(vabs_s16(vreinterpret_s16_m64(a)));
}
-// Copy the lower 64-bit integer in a to dst.
+// Compute the absolute value of packed signed 32-bit integers in a, and store
+// the unsigned results in dst.
//
-// dst[63:0] := a[63:0]
+// FOR j := 0 to 1
+// i := j*32
+// dst[i+31:i] := ABS(a[i+31:i])
+// ENDFOR
//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtsi128_si64
-FORCE_INLINE int64_t _mm_cvtsi128_si64(__m128i a)
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_abs_pi32
+FORCE_INLINE __m64 _mm_abs_pi32(__m64 a)
{
- return vgetq_lane_s64(vreinterpretq_s64_m128i(a), 0);
+ return vreinterpret_m64_s32(vabs_s32(vreinterpret_s32_m64(a)));
}
-// Copy the lower 64-bit integer in a to dst.
+// Compute the absolute value of packed signed 8-bit integers in a, and store
+// the unsigned results in dst.
//
-// dst[63:0] := a[63:0]
+// FOR j := 0 to 7
+// i := j*8
+// dst[i+7:i] := ABS(a[i+7:i])
+// ENDFOR
//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtsi128_si64x
-#define _mm_cvtsi128_si64x(a) _mm_cvtsi128_si64(a)
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_abs_pi8
+FORCE_INLINE __m64 _mm_abs_pi8(__m64 a)
+{
+ return vreinterpret_m64_s8(vabs_s8(vreinterpret_s8_m64(a)));
+}
-// Moves 32-bit integer a to the least significant 32 bits of an __m128 object,
-// zero extending the upper bits.
+// Concatenate 16-byte blocks in a and b into a 32-byte temporary result, shift
+// the result right by imm8 bytes, and store the low 16 bytes in dst.
//
-// r0 := a
-// r1 := 0x0
-// r2 := 0x0
-// r3 := 0x0
+// tmp[255:0] := ((a[127:0] << 128)[255:0] OR b[127:0]) >> (imm8*8)
+// dst[127:0] := tmp[127:0]
//
-// https://msdn.microsoft.com/en-us/library/ct3539ha%28v=vs.90%29.aspx
-FORCE_INLINE __m128i _mm_cvtsi32_si128(int a)
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_alignr_epi8
+FORCE_INLINE __m128i _mm_alignr_epi8(__m128i a, __m128i b, int imm)
{
- return vreinterpretq_m128i_s32(vsetq_lane_s32(a, vdupq_n_s32(0), 0));
+ if (_sse2neon_unlikely(imm & ~31))
+ return _mm_setzero_si128();
+ int idx;
+ uint8x16_t tmp[2];
+ if (imm >= 16) {
+ idx = imm - 16;
+ tmp[0] = vreinterpretq_u8_m128i(a);
+ tmp[1] = vdupq_n_u8(0);
+ } else {
+ idx = imm;
+ tmp[0] = vreinterpretq_u8_m128i(b);
+ tmp[1] = vreinterpretq_u8_m128i(a);
+ }
+ return vreinterpretq_m128i_u8(vld1q_u8(((uint8_t const *) tmp) + idx));
}
-// Moves 64-bit integer a to the least significant 64 bits of an __m128 object,
-// zero extending the upper bits.
+// Concatenate 8-byte blocks in a and b into a 16-byte temporary result, shift
+// the result right by imm8 bytes, and store the low 8 bytes in dst.
//
-// r0 := a
-// r1 := 0x0
-FORCE_INLINE __m128i _mm_cvtsi64_si128(int64_t a)
+// tmp[127:0] := ((a[63:0] << 64)[127:0] OR b[63:0]) >> (imm8*8)
+// dst[63:0] := tmp[63:0]
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_alignr_pi8
+#define _mm_alignr_pi8(a, b, imm) \
+ __extension__({ \
+ __m64 ret; \
+ if (_sse2neon_unlikely((imm) >= 16)) { \
+ ret = vreinterpret_m64_s8(vdup_n_s8(0)); \
+ } else { \
+ uint8x8_t tmp_low, tmp_high; \
+ if (imm >= 8) { \
+ const int idx = imm - 8; \
+ tmp_low = vreinterpret_u8_m64(a); \
+ tmp_high = vdup_n_u8(0); \
+ ret = vreinterpret_m64_u8(vext_u8(tmp_low, tmp_high, idx)); \
+ } else { \
+ const int idx = imm; \
+ tmp_low = vreinterpret_u8_m64(b); \
+ tmp_high = vreinterpret_u8_m64(a); \
+ ret = vreinterpret_m64_u8(vext_u8(tmp_low, tmp_high, idx)); \
+ } \
+ } \
+ ret; \
+ })
+
+// Computes pairwise add of each argument as a 16-bit signed or unsigned integer
+// values a and b.
+FORCE_INLINE __m128i _mm_hadd_epi16(__m128i _a, __m128i _b)
{
- return vreinterpretq_m128i_s64(vsetq_lane_s64(a, vdupq_n_s64(0), 0));
+ int16x8_t a = vreinterpretq_s16_m128i(_a);
+ int16x8_t b = vreinterpretq_s16_m128i(_b);
+#if defined(__aarch64__)
+ return vreinterpretq_m128i_s16(vpaddq_s16(a, b));
+#else
+ return vreinterpretq_m128i_s16(
+ vcombine_s16(vpadd_s16(vget_low_s16(a), vget_high_s16(a)),
+ vpadd_s16(vget_low_s16(b), vget_high_s16(b))));
+#endif
}
-// Cast vector of type __m128 to type __m128d. This intrinsic is only used for
-// compilation and does not generate any instructions, thus it has zero latency.
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_castps_pd
-FORCE_INLINE __m128d _mm_castps_pd(__m128 a)
+// Computes pairwise add of each argument as a 32-bit signed or unsigned integer
+// values a and b.
+FORCE_INLINE __m128i _mm_hadd_epi32(__m128i _a, __m128i _b)
{
- return vreinterpretq_m128d_s32(vreinterpretq_s32_m128(a));
+ int32x4_t a = vreinterpretq_s32_m128i(_a);
+ int32x4_t b = vreinterpretq_s32_m128i(_b);
+ return vreinterpretq_m128i_s32(
+ vcombine_s32(vpadd_s32(vget_low_s32(a), vget_high_s32(a)),
+ vpadd_s32(vget_low_s32(b), vget_high_s32(b))));
}
-// Applies a type cast to reinterpret four 32-bit floating point values passed
-// in as a 128-bit parameter as packed 32-bit integers.
-// https://msdn.microsoft.com/en-us/library/bb514099.aspx
-FORCE_INLINE __m128i _mm_castps_si128(__m128 a)
+// Horizontally add adjacent pairs of 16-bit integers in a and b, and pack the
+// signed 16-bit results in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_hadd_pi16
+FORCE_INLINE __m64 _mm_hadd_pi16(__m64 a, __m64 b)
{
- return vreinterpretq_m128i_s32(vreinterpretq_s32_m128(a));
+ return vreinterpret_m64_s16(
+ vpadd_s16(vreinterpret_s16_m64(a), vreinterpret_s16_m64(b)));
}
-// Cast vector of type __m128i to type __m128d. This intrinsic is only used for
-// compilation and does not generate any instructions, thus it has zero latency.
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_castsi128_pd
-FORCE_INLINE __m128d _mm_castsi128_pd(__m128i a)
+// Horizontally add adjacent pairs of 32-bit integers in a and b, and pack the
+// signed 32-bit results in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_hadd_pi32
+FORCE_INLINE __m64 _mm_hadd_pi32(__m64 a, __m64 b)
+{
+ return vreinterpret_m64_s32(
+ vpadd_s32(vreinterpret_s32_m64(a), vreinterpret_s32_m64(b)));
+}
+
+// Computes saturated pairwise sub of each argument as a 16-bit signed
+// integer values a and b.
+FORCE_INLINE __m128i _mm_hadds_epi16(__m128i _a, __m128i _b)
{
#if defined(__aarch64__)
- return vreinterpretq_m128d_f64(vreinterpretq_f64_m128i(a));
+ int16x8_t a = vreinterpretq_s16_m128i(_a);
+ int16x8_t b = vreinterpretq_s16_m128i(_b);
+ return vreinterpretq_s64_s16(
+ vqaddq_s16(vuzp1q_s16(a, b), vuzp2q_s16(a, b)));
#else
- return vreinterpretq_m128d_f32(vreinterpretq_f32_m128i(a));
+ int32x4_t a = vreinterpretq_s32_m128i(_a);
+ int32x4_t b = vreinterpretq_s32_m128i(_b);
+ // Interleave using vshrn/vmovn
+ // [a0|a2|a4|a6|b0|b2|b4|b6]
+ // [a1|a3|a5|a7|b1|b3|b5|b7]
+ int16x8_t ab0246 = vcombine_s16(vmovn_s32(a), vmovn_s32(b));
+ int16x8_t ab1357 = vcombine_s16(vshrn_n_s32(a, 16), vshrn_n_s32(b, 16));
+ // Saturated add
+ return vreinterpretq_m128i_s16(vqaddq_s16(ab0246, ab1357));
#endif
}
-// Applies a type cast to reinterpret four 32-bit integers passed in as a
-// 128-bit parameter as packed 32-bit floating point values.
-// https://msdn.microsoft.com/en-us/library/bb514029.aspx
-FORCE_INLINE __m128 _mm_castsi128_ps(__m128i a)
+// Horizontally add adjacent pairs of signed 16-bit integers in a and b using
+// saturation, and pack the signed 16-bit results in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_hadds_pi16
+FORCE_INLINE __m64 _mm_hadds_pi16(__m64 _a, __m64 _b)
{
- return vreinterpretq_m128_s32(vreinterpretq_s32_m128i(a));
+ int16x4_t a = vreinterpret_s16_m64(_a);
+ int16x4_t b = vreinterpret_s16_m64(_b);
+#if defined(__aarch64__)
+ return vreinterpret_s64_s16(vqadd_s16(vuzp1_s16(a, b), vuzp2_s16(a, b)));
+#else
+ int16x4x2_t res = vuzp_s16(a, b);
+ return vreinterpret_s64_s16(vqadd_s16(res.val[0], res.val[1]));
+#endif
}
-// Loads 128-bit value. :
-// https://msdn.microsoft.com/en-us/library/atzzad1h(v=vs.80).aspx
-FORCE_INLINE __m128i _mm_load_si128(const __m128i *p)
+// Computes pairwise difference of each argument as a 16-bit signed or unsigned
+// integer values a and b.
+FORCE_INLINE __m128i _mm_hsub_epi16(__m128i _a, __m128i _b)
{
- return vreinterpretq_m128i_s32(vld1q_s32((const int32_t *) p));
+ int32x4_t a = vreinterpretq_s32_m128i(_a);
+ int32x4_t b = vreinterpretq_s32_m128i(_b);
+ // Interleave using vshrn/vmovn
+ // [a0|a2|a4|a6|b0|b2|b4|b6]
+ // [a1|a3|a5|a7|b1|b3|b5|b7]
+ int16x8_t ab0246 = vcombine_s16(vmovn_s32(a), vmovn_s32(b));
+ int16x8_t ab1357 = vcombine_s16(vshrn_n_s32(a, 16), vshrn_n_s32(b, 16));
+ // Subtract
+ return vreinterpretq_m128i_s16(vsubq_s16(ab0246, ab1357));
}
-// Load a double-precision (64-bit) floating-point element from memory into both
-// elements of dst.
-//
-// dst[63:0] := MEM[mem_addr+63:mem_addr]
-// dst[127:64] := MEM[mem_addr+63:mem_addr]
-//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_load1_pd
-FORCE_INLINE __m128d _mm_load1_pd(const double *p)
+// Computes pairwise difference of each argument as a 32-bit signed or unsigned
+// integer values a and b.
+FORCE_INLINE __m128i _mm_hsub_epi32(__m128i _a, __m128i _b)
+{
+ int64x2_t a = vreinterpretq_s64_m128i(_a);
+ int64x2_t b = vreinterpretq_s64_m128i(_b);
+ // Interleave using vshrn/vmovn
+ // [a0|a2|b0|b2]
+ // [a1|a2|b1|b3]
+ int32x4_t ab02 = vcombine_s32(vmovn_s64(a), vmovn_s64(b));
+ int32x4_t ab13 = vcombine_s32(vshrn_n_s64(a, 32), vshrn_n_s64(b, 32));
+ // Subtract
+ return vreinterpretq_m128i_s32(vsubq_s32(ab02, ab13));
+}
+
+// Horizontally subtract adjacent pairs of 16-bit integers in a and b, and pack
+// the signed 16-bit results in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_hsub_pi16
+FORCE_INLINE __m64 _mm_hsub_pi16(__m64 _a, __m64 _b)
+{
+ int32x4_t ab =
+ vcombine_s32(vreinterpret_s32_m64(_a), vreinterpret_s32_m64(_b));
+
+ int16x4_t ab_low_bits = vmovn_s32(ab);
+ int16x4_t ab_high_bits = vshrn_n_s32(ab, 16);
+
+ return vreinterpret_m64_s16(vsub_s16(ab_low_bits, ab_high_bits));
+}
+
+// Horizontally subtract adjacent pairs of 32-bit integers in a and b, and pack
+// the signed 32-bit results in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=mm_hsub_pi32
+FORCE_INLINE __m64 _mm_hsub_pi32(__m64 _a, __m64 _b)
{
#if defined(__aarch64__)
- return vreinterpretq_m128d_f64(vld1q_dup_f64(p));
+ int32x2_t a = vreinterpret_s32_m64(_a);
+ int32x2_t b = vreinterpret_s32_m64(_b);
+ return vreinterpret_m64_s32(vsub_s32(vtrn1_s32(a, b), vtrn2_s32(a, b)));
#else
- return vreinterpretq_m128d_s64(vdupq_n_s64(*(const int64_t *) p));
+ int32x2x2_t trn_ab =
+ vtrn_s32(vreinterpret_s32_m64(_a), vreinterpret_s32_m64(_b));
+ return vreinterpret_m64_s32(vsub_s32(trn_ab.val[0], trn_ab.val[1]));
#endif
}
-// Load a double-precision (64-bit) floating-point element from memory into both
-// elements of dst.
-//
-// dst[63:0] := MEM[mem_addr+63:mem_addr]
-// dst[127:64] := MEM[mem_addr+63:mem_addr]
-//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_load_pd1
-#define _mm_load_pd1 _mm_load1_pd
+// Computes saturated pairwise difference of each argument as a 16-bit signed
+// integer values a and b.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_hsubs_epi16
+FORCE_INLINE __m128i _mm_hsubs_epi16(__m128i _a, __m128i _b)
+{
+#if defined(__aarch64__)
+ int16x8_t a = vreinterpretq_s16_m128i(_a);
+ int16x8_t b = vreinterpretq_s16_m128i(_b);
+ return vreinterpretq_s64_s16(
+ vqsubq_s16(vuzp1q_s16(a, b), vuzp2q_s16(a, b)));
+#else
+ int32x4_t a = vreinterpretq_s32_m128i(_a);
+ int32x4_t b = vreinterpretq_s32_m128i(_b);
+ // Interleave using vshrn/vmovn
+ // [a0|a2|a4|a6|b0|b2|b4|b6]
+ // [a1|a3|a5|a7|b1|b3|b5|b7]
+ int16x8_t ab0246 = vcombine_s16(vmovn_s32(a), vmovn_s32(b));
+ int16x8_t ab1357 = vcombine_s16(vshrn_n_s32(a, 16), vshrn_n_s32(b, 16));
+ // Saturated subtract
+ return vreinterpretq_m128i_s16(vqsubq_s16(ab0246, ab1357));
+#endif
+}
-// Load a double-precision (64-bit) floating-point element from memory into the
-// upper element of dst, and copy the lower element from a to dst. mem_addr does
-// not need to be aligned on any particular boundary.
-//
-// dst[63:0] := a[63:0]
-// dst[127:64] := MEM[mem_addr+63:mem_addr]
-//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_loadh_pd
-FORCE_INLINE __m128d _mm_loadh_pd(__m128d a, const double *p)
+// Horizontally subtract adjacent pairs of signed 16-bit integers in a and b
+// using saturation, and pack the signed 16-bit results in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_hsubs_pi16
+FORCE_INLINE __m64 _mm_hsubs_pi16(__m64 _a, __m64 _b)
{
+ int16x4_t a = vreinterpret_s16_m64(_a);
+ int16x4_t b = vreinterpret_s16_m64(_b);
#if defined(__aarch64__)
- return vreinterpretq_m128d_f64(
- vcombine_f64(vget_low_f64(vreinterpretq_f64_m128d(a)), vld1_f64(p)));
+ return vreinterpret_s64_s16(vqsub_s16(vuzp1_s16(a, b), vuzp2_s16(a, b)));
#else
- return vreinterpretq_m128d_f32(vcombine_f32(
- vget_low_f32(vreinterpretq_f32_m128d(a)), vld1_f32((const float *) p)));
+ int16x4x2_t res = vuzp_s16(a, b);
+ return vreinterpret_s64_s16(vqsub_s16(res.val[0], res.val[1]));
#endif
}
-// Load a double-precision (64-bit) floating-point element from memory into both
-// elements of dst.
-//
-// dst[63:0] := MEM[mem_addr+63:mem_addr]
-// dst[127:64] := MEM[mem_addr+63:mem_addr]
+// Vertically multiply each unsigned 8-bit integer from a with the corresponding
+// signed 8-bit integer from b, producing intermediate signed 16-bit integers.
+// Horizontally add adjacent pairs of intermediate signed 16-bit integers,
+// and pack the saturated results in dst.
//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_load_pd1
-#define _mm_load_pd1 _mm_load1_pd
+// FOR j := 0 to 7
+// i := j*16
+// dst[i+15:i] := Saturate_To_Int16( a[i+15:i+8]*b[i+15:i+8] +
+// a[i+7:i]*b[i+7:i] )
+// ENDFOR
+FORCE_INLINE __m128i _mm_maddubs_epi16(__m128i _a, __m128i _b)
+{
+#if defined(__aarch64__)
+ uint8x16_t a = vreinterpretq_u8_m128i(_a);
+ int8x16_t b = vreinterpretq_s8_m128i(_b);
+ int16x8_t tl = vmulq_s16(vreinterpretq_s16_u16(vmovl_u8(vget_low_u8(a))),
+ vmovl_s8(vget_low_s8(b)));
+ int16x8_t th = vmulq_s16(vreinterpretq_s16_u16(vmovl_u8(vget_high_u8(a))),
+ vmovl_s8(vget_high_s8(b)));
+ return vreinterpretq_m128i_s16(
+ vqaddq_s16(vuzp1q_s16(tl, th), vuzp2q_s16(tl, th)));
+#else
+ // This would be much simpler if x86 would choose to zero extend OR sign
+ // extend, not both. This could probably be optimized better.
+ uint16x8_t a = vreinterpretq_u16_m128i(_a);
+ int16x8_t b = vreinterpretq_s16_m128i(_b);
-// Load a double-precision (64-bit) floating-point element from memory into both
-// elements of dst.
-//
-// dst[63:0] := MEM[mem_addr+63:mem_addr]
-// dst[127:64] := MEM[mem_addr+63:mem_addr]
-//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_loaddup_pd
-#define _mm_loaddup_pd _mm_load1_pd
+ // Zero extend a
+ int16x8_t a_odd = vreinterpretq_s16_u16(vshrq_n_u16(a, 8));
+ int16x8_t a_even = vreinterpretq_s16_u16(vbicq_u16(a, vdupq_n_u16(0xff00)));
-// Loads 128-bit value. :
-// https://msdn.microsoft.com/zh-cn/library/f4k12ae8(v=vs.90).aspx
-FORCE_INLINE __m128i _mm_loadu_si128(const __m128i *p)
+ // Sign extend by shifting left then shifting right.
+ int16x8_t b_even = vshrq_n_s16(vshlq_n_s16(b, 8), 8);
+ int16x8_t b_odd = vshrq_n_s16(b, 8);
+
+ // multiply
+ int16x8_t prod1 = vmulq_s16(a_even, b_even);
+ int16x8_t prod2 = vmulq_s16(a_odd, b_odd);
+
+ // saturated add
+ return vreinterpretq_m128i_s16(vqaddq_s16(prod1, prod2));
+#endif
+}
+
+// Vertically multiply each unsigned 8-bit integer from a with the corresponding
+// signed 8-bit integer from b, producing intermediate signed 16-bit integers.
+// Horizontally add adjacent pairs of intermediate signed 16-bit integers, and
+// pack the saturated results in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maddubs_pi16
+FORCE_INLINE __m64 _mm_maddubs_pi16(__m64 _a, __m64 _b)
{
- return vreinterpretq_m128i_s32(vld1q_s32((const int32_t *) p));
+ uint16x4_t a = vreinterpret_u16_m64(_a);
+ int16x4_t b = vreinterpret_s16_m64(_b);
+
+ // Zero extend a
+ int16x4_t a_odd = vreinterpret_s16_u16(vshr_n_u16(a, 8));
+ int16x4_t a_even = vreinterpret_s16_u16(vand_u16(a, vdup_n_u16(0xff)));
+
+ // Sign extend by shifting left then shifting right.
+ int16x4_t b_even = vshr_n_s16(vshl_n_s16(b, 8), 8);
+ int16x4_t b_odd = vshr_n_s16(b, 8);
+
+ // multiply
+ int16x4_t prod1 = vmul_s16(a_even, b_even);
+ int16x4_t prod2 = vmul_s16(a_odd, b_odd);
+
+ // saturated add
+ return vreinterpret_m64_s16(vqadd_s16(prod1, prod2));
}
-// Load unaligned 32-bit integer from memory into the first element of dst.
-//
-// dst[31:0] := MEM[mem_addr+31:mem_addr]
-// dst[MAX:32] := 0
+// Multiply packed signed 16-bit integers in a and b, producing intermediate
+// signed 32-bit integers. Shift right by 15 bits while rounding up, and store
+// the packed 16-bit integers in dst.
//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_loadu_si32
-FORCE_INLINE __m128i _mm_loadu_si32(const void *p)
+// r0 := Round(((int32_t)a0 * (int32_t)b0) >> 15)
+// r1 := Round(((int32_t)a1 * (int32_t)b1) >> 15)
+// r2 := Round(((int32_t)a2 * (int32_t)b2) >> 15)
+// ...
+// r7 := Round(((int32_t)a7 * (int32_t)b7) >> 15)
+FORCE_INLINE __m128i _mm_mulhrs_epi16(__m128i a, __m128i b)
{
- return vreinterpretq_m128i_s32(
- vsetq_lane_s32(*(const int32_t *) p, vdupq_n_s32(0), 0));
+ // Has issues due to saturation
+ // return vreinterpretq_m128i_s16(vqrdmulhq_s16(a, b));
+
+ // Multiply
+ int32x4_t mul_lo = vmull_s16(vget_low_s16(vreinterpretq_s16_m128i(a)),
+ vget_low_s16(vreinterpretq_s16_m128i(b)));
+ int32x4_t mul_hi = vmull_s16(vget_high_s16(vreinterpretq_s16_m128i(a)),
+ vget_high_s16(vreinterpretq_s16_m128i(b)));
+
+ // Rounding narrowing shift right
+ // narrow = (int16_t)((mul + 16384) >> 15);
+ int16x4_t narrow_lo = vrshrn_n_s32(mul_lo, 15);
+ int16x4_t narrow_hi = vrshrn_n_s32(mul_hi, 15);
+
+ // Join together
+ return vreinterpretq_m128i_s16(vcombine_s16(narrow_lo, narrow_hi));
}
-// Convert packed double-precision (64-bit) floating-point elements in a to
-// packed single-precision (32-bit) floating-point elements, and store the
-// results in dst.
+// Multiply packed signed 16-bit integers in a and b, producing intermediate
+// signed 32-bit integers. Truncate each intermediate integer to the 18 most
+// significant bits, round by adding 1, and store bits [16:1] to dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mulhrs_pi16
+FORCE_INLINE __m64 _mm_mulhrs_pi16(__m64 a, __m64 b)
+{
+ int32x4_t mul_extend =
+ vmull_s16((vreinterpret_s16_m64(a)), (vreinterpret_s16_m64(b)));
+
+ // Rounding narrowing shift right
+ return vreinterpret_m64_s16(vrshrn_n_s32(mul_extend, 15));
+}
+
+// Shuffle packed 8-bit integers in a according to shuffle control mask in the
+// corresponding 8-bit element of b, and store the results in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_shuffle_epi8
+FORCE_INLINE __m128i _mm_shuffle_epi8(__m128i a, __m128i b)
+{
+ int8x16_t tbl = vreinterpretq_s8_m128i(a); // input a
+ uint8x16_t idx = vreinterpretq_u8_m128i(b); // input b
+ uint8x16_t idx_masked =
+ vandq_u8(idx, vdupq_n_u8(0x8F)); // avoid using meaningless bits
+#if defined(__aarch64__)
+ return vreinterpretq_m128i_s8(vqtbl1q_s8(tbl, idx_masked));
+#elif defined(__GNUC__)
+ int8x16_t ret;
+ // %e and %f represent the even and odd D registers
+ // respectively.
+ __asm__ __volatile__(
+ "vtbl.8 %e[ret], {%e[tbl], %f[tbl]}, %e[idx]\n"
+ "vtbl.8 %f[ret], {%e[tbl], %f[tbl]}, %f[idx]\n"
+ : [ret] "=&w"(ret)
+ : [tbl] "w"(tbl), [idx] "w"(idx_masked));
+ return vreinterpretq_m128i_s8(ret);
+#else
+ // use this line if testing on aarch64
+ int8x8x2_t a_split = {vget_low_s8(tbl), vget_high_s8(tbl)};
+ return vreinterpretq_m128i_s8(
+ vcombine_s8(vtbl2_s8(a_split, vget_low_u8(idx_masked)),
+ vtbl2_s8(a_split, vget_high_u8(idx_masked))));
+#endif
+}
+
+// Shuffle packed 8-bit integers in a according to shuffle control mask in the
+// corresponding 8-bit element of b, and store the results in dst.
//
-// FOR j := 0 to 1
-// i := 32*j
-// k := 64*j
-// dst[i+31:i] := Convert_FP64_To_FP32(a[k+64:k])
+// FOR j := 0 to 7
+// i := j*8
+// IF b[i+7] == 1
+// dst[i+7:i] := 0
+// ELSE
+// index[2:0] := b[i+2:i]
+// dst[i+7:i] := a[index*8+7:index*8]
+// FI
// ENDFOR
-// dst[127:64] := 0
//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtpd_ps
-FORCE_INLINE __m128 _mm_cvtpd_ps(__m128d a)
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_shuffle_pi8
+FORCE_INLINE __m64 _mm_shuffle_pi8(__m64 a, __m64 b)
+{
+ const int8x8_t controlMask =
+ vand_s8(vreinterpret_s8_m64(b), vdup_n_s8((int8_t)(0x1 << 7 | 0x07)));
+ int8x8_t res = vtbl1_s8(vreinterpret_s8_m64(a), controlMask);
+ return vreinterpret_m64_s8(res);
+}
+
+// Negate packed 16-bit integers in a when the corresponding signed
+// 16-bit integer in b is negative, and store the results in dst.
+// Element in dst are zeroed out when the corresponding element
+// in b is zero.
+//
+// for i in 0..7
+// if b[i] < 0
+// r[i] := -a[i]
+// else if b[i] == 0
+// r[i] := 0
+// else
+// r[i] := a[i]
+// fi
+// done
+FORCE_INLINE __m128i _mm_sign_epi16(__m128i _a, __m128i _b)
{
+ int16x8_t a = vreinterpretq_s16_m128i(_a);
+ int16x8_t b = vreinterpretq_s16_m128i(_b);
+
+ // signed shift right: faster than vclt
+ // (b < 0) ? 0xFFFF : 0
+ uint16x8_t ltMask = vreinterpretq_u16_s16(vshrq_n_s16(b, 15));
+ // (b == 0) ? 0xFFFF : 0
#if defined(__aarch64__)
- float32x2_t tmp = vcvt_f32_f64(vreinterpretq_f64_m128d(a));
- return vreinterpretq_m128_f32(vcombine_f32(tmp, vdup_n_f32(0)));
+ int16x8_t zeroMask = vreinterpretq_s16_u16(vceqzq_s16(b));
#else
- float a0 = (float) ((double *) &a)[0];
- float a1 = (float) ((double *) &a)[1];
- return _mm_set_ps(0, 0, a1, a0);
+ int16x8_t zeroMask = vreinterpretq_s16_u16(vceqq_s16(b, vdupq_n_s16(0)));
#endif
+
+ // bitwise select either a or negative 'a' (vnegq_s16(a) equals to negative
+ // 'a') based on ltMask
+ int16x8_t masked = vbslq_s16(ltMask, vnegq_s16(a), a);
+ // res = masked & (~zeroMask)
+ int16x8_t res = vbicq_s16(masked, zeroMask);
+ return vreinterpretq_m128i_s16(res);
}
-// Copy the lower double-precision (64-bit) floating-point element of a to dst.
+// Negate packed 32-bit integers in a when the corresponding signed
+// 32-bit integer in b is negative, and store the results in dst.
+// Element in dst are zeroed out when the corresponding element
+// in b is zero.
//
-// dst[63:0] := a[63:0]
+// for i in 0..3
+// if b[i] < 0
+// r[i] := -a[i]
+// else if b[i] == 0
+// r[i] := 0
+// else
+// r[i] := a[i]
+// fi
+// done
+FORCE_INLINE __m128i _mm_sign_epi32(__m128i _a, __m128i _b)
+{
+ int32x4_t a = vreinterpretq_s32_m128i(_a);
+ int32x4_t b = vreinterpretq_s32_m128i(_b);
+
+ // signed shift right: faster than vclt
+ // (b < 0) ? 0xFFFFFFFF : 0
+ uint32x4_t ltMask = vreinterpretq_u32_s32(vshrq_n_s32(b, 31));
+
+ // (b == 0) ? 0xFFFFFFFF : 0
+#if defined(__aarch64__)
+ int32x4_t zeroMask = vreinterpretq_s32_u32(vceqzq_s32(b));
+#else
+ int32x4_t zeroMask = vreinterpretq_s32_u32(vceqq_s32(b, vdupq_n_s32(0)));
+#endif
+
+ // bitwise select either a or negative 'a' (vnegq_s32(a) equals to negative
+ // 'a') based on ltMask
+ int32x4_t masked = vbslq_s32(ltMask, vnegq_s32(a), a);
+ // res = masked & (~zeroMask)
+ int32x4_t res = vbicq_s32(masked, zeroMask);
+ return vreinterpretq_m128i_s32(res);
+}
+
+// Negate packed 8-bit integers in a when the corresponding signed
+// 8-bit integer in b is negative, and store the results in dst.
+// Element in dst are zeroed out when the corresponding element
+// in b is zero.
//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtsd_f64
-FORCE_INLINE double _mm_cvtsd_f64(__m128d a)
+// for i in 0..15
+// if b[i] < 0
+// r[i] := -a[i]
+// else if b[i] == 0
+// r[i] := 0
+// else
+// r[i] := a[i]
+// fi
+// done
+FORCE_INLINE __m128i _mm_sign_epi8(__m128i _a, __m128i _b)
{
+ int8x16_t a = vreinterpretq_s8_m128i(_a);
+ int8x16_t b = vreinterpretq_s8_m128i(_b);
+
+ // signed shift right: faster than vclt
+ // (b < 0) ? 0xFF : 0
+ uint8x16_t ltMask = vreinterpretq_u8_s8(vshrq_n_s8(b, 7));
+
+ // (b == 0) ? 0xFF : 0
#if defined(__aarch64__)
- return (double) vgetq_lane_f64(vreinterpretq_f64_m128d(a), 0);
+ int8x16_t zeroMask = vreinterpretq_s8_u8(vceqzq_s8(b));
#else
- return ((double *) &a)[0];
+ int8x16_t zeroMask = vreinterpretq_s8_u8(vceqq_s8(b, vdupq_n_s8(0)));
#endif
+
+ // bitwise select either a or nagative 'a' (vnegq_s8(a) return nagative 'a')
+ // based on ltMask
+ int8x16_t masked = vbslq_s8(ltMask, vnegq_s8(a), a);
+ // res = masked & (~zeroMask)
+ int8x16_t res = vbicq_s8(masked, zeroMask);
+
+ return vreinterpretq_m128i_s8(res);
}
-// Convert packed single-precision (32-bit) floating-point elements in a to
-// packed double-precision (64-bit) floating-point elements, and store the
-// results in dst.
+// Negate packed 16-bit integers in a when the corresponding signed 16-bit
+// integer in b is negative, and store the results in dst. Element in dst are
+// zeroed out when the corresponding element in b is zero.
//
-// FOR j := 0 to 1
-// i := 64*j
-// k := 32*j
-// dst[i+63:i] := Convert_FP32_To_FP64(a[k+31:k])
+// FOR j := 0 to 3
+// i := j*16
+// IF b[i+15:i] < 0
+// dst[i+15:i] := -(a[i+15:i])
+// ELSE IF b[i+15:i] == 0
+// dst[i+15:i] := 0
+// ELSE
+// dst[i+15:i] := a[i+15:i]
+// FI
// ENDFOR
//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtps_pd
-FORCE_INLINE __m128d _mm_cvtps_pd(__m128 a)
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_sign_pi16
+FORCE_INLINE __m64 _mm_sign_pi16(__m64 _a, __m64 _b)
{
+ int16x4_t a = vreinterpret_s16_m64(_a);
+ int16x4_t b = vreinterpret_s16_m64(_b);
+
+ // signed shift right: faster than vclt
+ // (b < 0) ? 0xFFFF : 0
+ uint16x4_t ltMask = vreinterpret_u16_s16(vshr_n_s16(b, 15));
+
+ // (b == 0) ? 0xFFFF : 0
#if defined(__aarch64__)
- return vreinterpretq_m128d_f64(
- vcvt_f64_f32(vget_low_f32(vreinterpretq_f32_m128(a))));
+ int16x4_t zeroMask = vreinterpret_s16_u16(vceqz_s16(b));
#else
- double a0 = (double) vgetq_lane_f32(vreinterpretq_f32_m128(a), 0);
- double a1 = (double) vgetq_lane_f32(vreinterpretq_f32_m128(a), 1);
- return _mm_set_pd(a1, a0);
+ int16x4_t zeroMask = vreinterpret_s16_u16(vceq_s16(b, vdup_n_s16(0)));
#endif
-}
-// Cast vector of type __m128d to type __m128i. This intrinsic is only used for
-// compilation and does not generate any instructions, thus it has zero latency.
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_castpd_si128
-FORCE_INLINE __m128i _mm_castpd_si128(__m128d a)
-{
- return vreinterpretq_m128i_s64(vreinterpretq_s64_m128d(a));
+ // bitwise select either a or nagative 'a' (vneg_s16(a) return nagative 'a')
+ // based on ltMask
+ int16x4_t masked = vbsl_s16(ltMask, vneg_s16(a), a);
+ // res = masked & (~zeroMask)
+ int16x4_t res = vbic_s16(masked, zeroMask);
+
+ return vreinterpret_m64_s16(res);
}
-// Cast vector of type __m128d to type __m128. This intrinsic is only used for
-// compilation and does not generate any instructions, thus it has zero latency.
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_castpd_ps
-FORCE_INLINE __m128 _mm_castpd_ps(__m128d a)
+// Negate packed 32-bit integers in a when the corresponding signed 32-bit
+// integer in b is negative, and store the results in dst. Element in dst are
+// zeroed out when the corresponding element in b is zero.
+//
+// FOR j := 0 to 1
+// i := j*32
+// IF b[i+31:i] < 0
+// dst[i+31:i] := -(a[i+31:i])
+// ELSE IF b[i+31:i] == 0
+// dst[i+31:i] := 0
+// ELSE
+// dst[i+31:i] := a[i+31:i]
+// FI
+// ENDFOR
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_sign_pi32
+FORCE_INLINE __m64 _mm_sign_pi32(__m64 _a, __m64 _b)
{
- return vreinterpretq_m128_s64(vreinterpretq_s64_m128d(a));
+ int32x2_t a = vreinterpret_s32_m64(_a);
+ int32x2_t b = vreinterpret_s32_m64(_b);
+
+ // signed shift right: faster than vclt
+ // (b < 0) ? 0xFFFFFFFF : 0
+ uint32x2_t ltMask = vreinterpret_u32_s32(vshr_n_s32(b, 31));
+
+ // (b == 0) ? 0xFFFFFFFF : 0
+#if defined(__aarch64__)
+ int32x2_t zeroMask = vreinterpret_s32_u32(vceqz_s32(b));
+#else
+ int32x2_t zeroMask = vreinterpret_s32_u32(vceq_s32(b, vdup_n_s32(0)));
+#endif
+
+ // bitwise select either a or nagative 'a' (vneg_s32(a) return nagative 'a')
+ // based on ltMask
+ int32x2_t masked = vbsl_s32(ltMask, vneg_s32(a), a);
+ // res = masked & (~zeroMask)
+ int32x2_t res = vbic_s32(masked, zeroMask);
+
+ return vreinterpret_m64_s32(res);
}
-// Blend packed single-precision (32-bit) floating-point elements from a and b
-// using mask, and store the results in dst.
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_blendv_ps
-FORCE_INLINE __m128 _mm_blendv_ps(__m128 _a, __m128 _b, __m128 _mask)
+// Negate packed 8-bit integers in a when the corresponding signed 8-bit integer
+// in b is negative, and store the results in dst. Element in dst are zeroed out
+// when the corresponding element in b is zero.
+//
+// FOR j := 0 to 7
+// i := j*8
+// IF b[i+7:i] < 0
+// dst[i+7:i] := -(a[i+7:i])
+// ELSE IF b[i+7:i] == 0
+// dst[i+7:i] := 0
+// ELSE
+// dst[i+7:i] := a[i+7:i]
+// FI
+// ENDFOR
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_sign_pi8
+FORCE_INLINE __m64 _mm_sign_pi8(__m64 _a, __m64 _b)
{
- // Use a signed shift right to create a mask with the sign bit
- uint32x4_t mask =
- vreinterpretq_u32_s32(vshrq_n_s32(vreinterpretq_s32_m128(_mask), 31));
- float32x4_t a = vreinterpretq_f32_m128(_a);
- float32x4_t b = vreinterpretq_f32_m128(_b);
- return vreinterpretq_m128_f32(vbslq_f32(mask, b, a));
+ int8x8_t a = vreinterpret_s8_m64(_a);
+ int8x8_t b = vreinterpret_s8_m64(_b);
+
+ // signed shift right: faster than vclt
+ // (b < 0) ? 0xFF : 0
+ uint8x8_t ltMask = vreinterpret_u8_s8(vshr_n_s8(b, 7));
+
+ // (b == 0) ? 0xFF : 0
+#if defined(__aarch64__)
+ int8x8_t zeroMask = vreinterpret_s8_u8(vceqz_s8(b));
+#else
+ int8x8_t zeroMask = vreinterpret_s8_u8(vceq_s8(b, vdup_n_s8(0)));
+#endif
+
+ // bitwise select either a or nagative 'a' (vneg_s8(a) return nagative 'a')
+ // based on ltMask
+ int8x8_t masked = vbsl_s8(ltMask, vneg_s8(a), a);
+ // res = masked & (~zeroMask)
+ int8x8_t res = vbic_s8(masked, zeroMask);
+
+ return vreinterpret_m64_s8(res);
}
+/* SSE4.1 */
+
+// Blend packed 16-bit integers from a and b using control mask imm8, and store
+// the results in dst.
+//
+// FOR j := 0 to 7
+// i := j*16
+// IF imm8[j]
+// dst[i+15:i] := b[i+15:i]
+// ELSE
+// dst[i+15:i] := a[i+15:i]
+// FI
+// ENDFOR
+// FORCE_INLINE __m128i _mm_blend_epi16(__m128i a, __m128i b,
+// __constrange(0,255) int imm)
+#define _mm_blend_epi16(a, b, imm) \
+ __extension__({ \
+ const uint16_t ones = 0xffff; \
+ const uint16_t zeros = 0x0000; \
+ const uint16_t _mask[8] = {((imm) & (1 << 0)) ? ones : zeros, \
+ ((imm) & (1 << 1)) ? ones : zeros, \
+ ((imm) & (1 << 2)) ? ones : zeros, \
+ ((imm) & (1 << 3)) ? ones : zeros, \
+ ((imm) & (1 << 4)) ? ones : zeros, \
+ ((imm) & (1 << 5)) ? ones : zeros, \
+ ((imm) & (1 << 6)) ? ones : zeros, \
+ ((imm) & (1 << 7)) ? ones : zeros}; \
+ uint16x8_t _mask_vec = vld1q_u16(_mask); \
+ uint16x8_t _a = vreinterpretq_u16_m128i(a); \
+ uint16x8_t _b = vreinterpretq_u16_m128i(b); \
+ vreinterpretq_m128i_u16(vbslq_u16(_mask_vec, _b, _a)); \
+ })
+
+// Blend packed double-precision (64-bit) floating-point elements from a and b
+// using control mask imm8, and store the results in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_blend_pd
+#define _mm_blend_pd(a, b, imm) \
+ __extension__({ \
+ const uint64_t _mask[2] = { \
+ ((imm) & (1 << 0)) ? ~UINT64_C(0) : UINT64_C(0), \
+ ((imm) & (1 << 1)) ? ~UINT64_C(0) : UINT64_C(0)}; \
+ uint64x2_t _mask_vec = vld1q_u64(_mask); \
+ uint64x2_t _a = vreinterpretq_u64_m128d(a); \
+ uint64x2_t _b = vreinterpretq_u64_m128d(b); \
+ vreinterpretq_m128d_u64(vbslq_u64(_mask_vec, _b, _a)); \
+ })
+
// Blend packed single-precision (32-bit) floating-point elements from a and b
// using mask, and store the results in dst.
// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_blend_ps
@@ -5672,6 +7337,27 @@ FORCE_INLINE __m128 _mm_blend_ps(__m128 _a, __m128 _b, const char imm8)
return vreinterpretq_m128_f32(vbslq_f32(mask, b, a));
}
+// Blend packed 8-bit integers from a and b using mask, and store the results in
+// dst.
+//
+// FOR j := 0 to 15
+// i := j*8
+// IF mask[i+7]
+// dst[i+7:i] := b[i+7:i]
+// ELSE
+// dst[i+7:i] := a[i+7:i]
+// FI
+// ENDFOR
+FORCE_INLINE __m128i _mm_blendv_epi8(__m128i _a, __m128i _b, __m128i _mask)
+{
+ // Use a signed shift right to create a mask with the sign bit
+ uint8x16_t mask =
+ vreinterpretq_u8_s8(vshrq_n_s8(vreinterpretq_s8_m128i(_mask), 7));
+ uint8x16_t a = vreinterpretq_u8_m128i(_a);
+ uint8x16_t b = vreinterpretq_u8_m128i(_b);
+ return vreinterpretq_m128i_u8(vbslq_u8(mask, b, a));
+}
+
// Blend packed double-precision (64-bit) floating-point elements from a and b
// using mask, and store the results in dst.
// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_blendv_pd
@@ -5690,154 +7376,55 @@ FORCE_INLINE __m128d _mm_blendv_pd(__m128d _a, __m128d _b, __m128d _mask)
#endif
}
-typedef struct {
- uint16_t res0;
- uint8_t res1 : 6;
- uint8_t bit22 : 1;
- uint8_t bit23 : 1;
- uint8_t res2;
-#if defined(__aarch64__)
- uint32_t res3;
-#endif
-} fpcr_bitfield;
-
-// Macro: Set the rounding mode bits of the MXCSR control and status register to
-// the value in unsigned 32-bit integer a. The rounding mode may contain any of
-// the following flags: _MM_ROUND_NEAREST, _MM_ROUND_DOWN, _MM_ROUND_UP,
-// _MM_ROUND_TOWARD_ZERO
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_MM_SET_ROUNDING_MODE
-FORCE_INLINE void _MM_SET_ROUNDING_MODE(int rounding)
-{
- union {
- fpcr_bitfield field;
-#if defined(__aarch64__)
- uint64_t value;
-#else
- uint32_t value;
-#endif
- } r;
-
-#if defined(__aarch64__)
- asm volatile("mrs %0, FPCR" : "=r"(r.value)); /* read */
-#else
- asm volatile("vmrs %0, FPSCR" : "=r"(r.value)); /* read */
-#endif
-
- switch (rounding) {
- case _MM_ROUND_TOWARD_ZERO:
- r.field.bit22 = 1;
- r.field.bit23 = 1;
- break;
- case _MM_ROUND_DOWN:
- r.field.bit22 = 0;
- r.field.bit23 = 1;
- break;
- case _MM_ROUND_UP:
- r.field.bit22 = 1;
- r.field.bit23 = 0;
- break;
- default: //_MM_ROUND_NEAREST
- r.field.bit22 = 0;
- r.field.bit23 = 0;
- }
-
-#if defined(__aarch64__)
- asm volatile("msr FPCR, %0" ::"r"(r)); /* write */
-#else
- asm volatile("vmsr FPSCR, %0" ::"r"(r)); /* write */
-#endif
-}
-
-FORCE_INLINE void _mm_setcsr(unsigned int a)
+// Blend packed single-precision (32-bit) floating-point elements from a and b
+// using mask, and store the results in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_blendv_ps
+FORCE_INLINE __m128 _mm_blendv_ps(__m128 _a, __m128 _b, __m128 _mask)
{
- _MM_SET_ROUNDING_MODE(a);
+ // Use a signed shift right to create a mask with the sign bit
+ uint32x4_t mask =
+ vreinterpretq_u32_s32(vshrq_n_s32(vreinterpretq_s32_m128(_mask), 31));
+ float32x4_t a = vreinterpretq_f32_m128(_a);
+ float32x4_t b = vreinterpretq_f32_m128(_b);
+ return vreinterpretq_m128_f32(vbslq_f32(mask, b, a));
}
-// Round the packed single-precision (32-bit) floating-point elements in a using
-// the rounding parameter, and store the results as packed single-precision
+// Round the packed double-precision (64-bit) floating-point elements in a up
+// to an integer value, and store the results as packed double-precision
// floating-point elements in dst.
-// software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_round_ps
-FORCE_INLINE __m128 _mm_round_ps(__m128 a, int rounding)
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_ceil_pd
+FORCE_INLINE __m128d _mm_ceil_pd(__m128d a)
{
#if defined(__aarch64__)
- switch (rounding) {
- case (_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC):
- return vreinterpretq_m128_f32(vrndnq_f32(vreinterpretq_f32_m128(a)));
- case (_MM_FROUND_TO_NEG_INF | _MM_FROUND_NO_EXC):
- return vreinterpretq_m128_f32(vrndmq_f32(vreinterpretq_f32_m128(a)));
- case (_MM_FROUND_TO_POS_INF | _MM_FROUND_NO_EXC):
- return vreinterpretq_m128_f32(vrndpq_f32(vreinterpretq_f32_m128(a)));
- case (_MM_FROUND_TO_ZERO | _MM_FROUND_NO_EXC):
- return vreinterpretq_m128_f32(vrndq_f32(vreinterpretq_f32_m128(a)));
- default: //_MM_FROUND_CUR_DIRECTION
- return vreinterpretq_m128_f32(vrndiq_f32(vreinterpretq_f32_m128(a)));
- }
+ return vreinterpretq_m128d_f64(vrndpq_f64(vreinterpretq_f64_m128d(a)));
#else
- float *v_float = (float *) &a;
- __m128 zero, neg_inf, pos_inf;
-
- switch (rounding) {
- case (_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC):
- return _mm_cvtepi32_ps(_mm_cvtps_epi32(a));
- case (_MM_FROUND_TO_NEG_INF | _MM_FROUND_NO_EXC):
- return (__m128){floorf(v_float[0]), floorf(v_float[1]),
- floorf(v_float[2]), floorf(v_float[3])};
- case (_MM_FROUND_TO_POS_INF | _MM_FROUND_NO_EXC):
- return (__m128){ceilf(v_float[0]), ceilf(v_float[1]), ceilf(v_float[2]),
- ceilf(v_float[3])};
- case (_MM_FROUND_TO_ZERO | _MM_FROUND_NO_EXC):
- zero = _mm_set_ps(0.0f, 0.0f, 0.0f, 0.0f);
- neg_inf = _mm_set_ps(floorf(v_float[0]), floorf(v_float[1]),
- floorf(v_float[2]), floorf(v_float[3]));
- pos_inf = _mm_set_ps(ceilf(v_float[0]), ceilf(v_float[1]),
- ceilf(v_float[2]), ceilf(v_float[3]));
- return _mm_blendv_ps(pos_inf, neg_inf, _mm_cmple_ps(a, zero));
- default: //_MM_FROUND_CUR_DIRECTION
- return (__m128){roundf(v_float[0]), roundf(v_float[1]),
- roundf(v_float[2]), roundf(v_float[3])};
- }
+ double *f = (double *) &a;
+ return _mm_set_pd(ceil(f[1]), ceil(f[0]));
#endif
}
-// Convert packed single-precision (32-bit) floating-point elements in a to
-// packed 32-bit integers, and store the results in dst.
-//
-// FOR j := 0 to 1
-// i := 32*j
-// dst[i+31:i] := Convert_FP32_To_Int32(a[i+31:i])
-// ENDFOR
-//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvt_ps2pi
-FORCE_INLINE __m64 _mm_cvt_ps2pi(__m128 a)
+// Round the packed single-precision (32-bit) floating-point elements in a up to
+// an integer value, and store the results as packed single-precision
+// floating-point elements in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_ceil_ps
+FORCE_INLINE __m128 _mm_ceil_ps(__m128 a)
{
#if defined(__aarch64__)
- return vreinterpret_m64_s32(
- vget_low_s32(vcvtnq_s32_f32(vreinterpretq_f32_m128(a))));
+ return vreinterpretq_m128_f32(vrndpq_f32(vreinterpretq_f32_m128(a)));
#else
- return vreinterpret_m64_s32(
- vcvt_s32_f32(vget_low_f32(vreinterpretq_f32_m128(
- _mm_round_ps(a, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC)))));
+ float *f = (float *) &a;
+ return _mm_set_ps(ceilf(f[3]), ceilf(f[2]), ceilf(f[1]), ceilf(f[0]));
#endif
}
-// Convert packed single-precision (32-bit) floating-point elements in a to
-// packed 32-bit integers, and store the results in dst.
-//
-// FOR j := 0 to 1
-// i := 32*j
-// dst[i+31:i] := Convert_FP32_To_Int32(a[i+31:i])
-// ENDFOR
-//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtps_pi32
-#define _mm_cvtps_pi32(a) _mm_cvt_ps2pi(a)
-
-// Round the packed single-precision (32-bit) floating-point elements in a up to
-// an integer value, and store the results as packed single-precision
-// floating-point elements in dst.
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_ceil_ps
-FORCE_INLINE __m128 _mm_ceil_ps(__m128 a)
+// Round the lower double-precision (64-bit) floating-point element in b up to
+// an integer value, store the result as a double-precision floating-point
+// element in the lower element of dst, and copy the upper element from a to the
+// upper element of dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_ceil_sd
+FORCE_INLINE __m128d _mm_ceil_sd(__m128d a, __m128d b)
{
- return _mm_round_ps(a, _MM_FROUND_TO_POS_INF | _MM_FROUND_NO_EXC);
+ return _mm_move_sd(a, _mm_ceil_pd(b));
}
// Round the lower single-precision (32-bit) floating-point element in b up to
@@ -5851,396 +7438,442 @@ FORCE_INLINE __m128 _mm_ceil_ps(__m128 a)
// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_ceil_ss
FORCE_INLINE __m128 _mm_ceil_ss(__m128 a, __m128 b)
{
- return _mm_move_ss(
- a, _mm_round_ps(b, _MM_FROUND_TO_POS_INF | _MM_FROUND_NO_EXC));
+ return _mm_move_ss(a, _mm_ceil_ps(b));
}
-// Round the packed single-precision (32-bit) floating-point elements in a down
-// to an integer value, and store the results as packed single-precision
-// floating-point elements in dst.
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_floor_ps
-FORCE_INLINE __m128 _mm_floor_ps(__m128 a)
+// Compare packed 64-bit integers in a and b for equality, and store the results
+// in dst
+FORCE_INLINE __m128i _mm_cmpeq_epi64(__m128i a, __m128i b)
{
- return _mm_round_ps(a, _MM_FROUND_TO_NEG_INF | _MM_FROUND_NO_EXC);
+#if defined(__aarch64__)
+ return vreinterpretq_m128i_u64(
+ vceqq_u64(vreinterpretq_u64_m128i(a), vreinterpretq_u64_m128i(b)));
+#else
+ // ARMv7 lacks vceqq_u64
+ // (a == b) -> (a_lo == b_lo) && (a_hi == b_hi)
+ uint32x4_t cmp =
+ vceqq_u32(vreinterpretq_u32_m128i(a), vreinterpretq_u32_m128i(b));
+ uint32x4_t swapped = vrev64q_u32(cmp);
+ return vreinterpretq_m128i_u32(vandq_u32(cmp, swapped));
+#endif
}
-// Round the lower single-precision (32-bit) floating-point element in b down to
-// an integer value, store the result as a single-precision floating-point
-// element in the lower element of dst, and copy the upper 3 packed elements
-// from a to the upper elements of dst.
-//
-// dst[31:0] := FLOOR(b[31:0])
-// dst[127:32] := a[127:32]
-//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_floor_ss
-FORCE_INLINE __m128 _mm_floor_ss(__m128 a, __m128 b)
+// Converts the four signed 16-bit integers in the lower 64 bits to four signed
+// 32-bit integers.
+FORCE_INLINE __m128i _mm_cvtepi16_epi32(__m128i a)
{
- return _mm_move_ss(
- a, _mm_round_ps(b, _MM_FROUND_TO_NEG_INF | _MM_FROUND_NO_EXC));
+ return vreinterpretq_m128i_s32(
+ vmovl_s16(vget_low_s16(vreinterpretq_s16_m128i(a))));
}
-// Load 128-bits of integer data from unaligned memory into dst. This intrinsic
-// may perform better than _mm_loadu_si128 when the data crosses a cache line
-// boundary.
-//
-// dst[127:0] := MEM[mem_addr+127:mem_addr]
-//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_lddqu_si128
-#define _mm_lddqu_si128 _mm_loadu_si128
+// Converts the two signed 16-bit integers in the lower 32 bits two signed
+// 32-bit integers.
+FORCE_INLINE __m128i _mm_cvtepi16_epi64(__m128i a)
+{
+ int16x8_t s16x8 = vreinterpretq_s16_m128i(a); /* xxxx xxxx xxxx 0B0A */
+ int32x4_t s32x4 = vmovl_s16(vget_low_s16(s16x8)); /* 000x 000x 000B 000A */
+ int64x2_t s64x2 = vmovl_s32(vget_low_s32(s32x4)); /* 0000 000B 0000 000A */
+ return vreinterpretq_m128i_s64(s64x2);
+}
-/* Miscellaneous Operations */
+// Converts the two signed 32-bit integers in the lower 64 bits to two signed
+// 64-bit integers.
+FORCE_INLINE __m128i _mm_cvtepi32_epi64(__m128i a)
+{
+ return vreinterpretq_m128i_s64(
+ vmovl_s32(vget_low_s32(vreinterpretq_s32_m128i(a))));
+}
-// Shifts the 8 signed 16-bit integers in a right by count bits while shifting
-// in the sign bit.
-//
-// r0 := a0 >> count
-// r1 := a1 >> count
-// ...
-// r7 := a7 >> count
-//
-// https://msdn.microsoft.com/en-us/library/3c9997dk(v%3dvs.90).aspx
-FORCE_INLINE __m128i _mm_sra_epi16(__m128i a, __m128i count)
+// Converts the four unsigned 8-bit integers in the lower 16 bits to four
+// unsigned 32-bit integers.
+FORCE_INLINE __m128i _mm_cvtepi8_epi16(__m128i a)
{
- int64_t c = (int64_t) vget_low_s64((int64x2_t) count);
- if (unlikely(c > 15))
- return _mm_cmplt_epi16(a, _mm_setzero_si128());
- return vreinterpretq_m128i_s16(vshlq_s16((int16x8_t) a, vdupq_n_s16(-c)));
+ int8x16_t s8x16 = vreinterpretq_s8_m128i(a); /* xxxx xxxx xxxx DCBA */
+ int16x8_t s16x8 = vmovl_s8(vget_low_s8(s8x16)); /* 0x0x 0x0x 0D0C 0B0A */
+ return vreinterpretq_m128i_s16(s16x8);
}
-// Shifts the 4 signed 32-bit integers in a right by count bits while shifting
-// in the sign bit.
-//
-// r0 := a0 >> count
-// r1 := a1 >> count
-// r2 := a2 >> count
-// r3 := a3 >> count
-//
-// https://msdn.microsoft.com/en-us/library/ce40009e(v%3dvs.100).aspx
-FORCE_INLINE __m128i _mm_sra_epi32(__m128i a, __m128i count)
+// Converts the four unsigned 8-bit integers in the lower 32 bits to four
+// unsigned 32-bit integers.
+FORCE_INLINE __m128i _mm_cvtepi8_epi32(__m128i a)
{
- int64_t c = (int64_t) vget_low_s64((int64x2_t) count);
- if (unlikely(c > 31))
- return _mm_cmplt_epi32(a, _mm_setzero_si128());
- return vreinterpretq_m128i_s32(vshlq_s32((int32x4_t) a, vdupq_n_s32(-c)));
+ int8x16_t s8x16 = vreinterpretq_s8_m128i(a); /* xxxx xxxx xxxx DCBA */
+ int16x8_t s16x8 = vmovl_s8(vget_low_s8(s8x16)); /* 0x0x 0x0x 0D0C 0B0A */
+ int32x4_t s32x4 = vmovl_s16(vget_low_s16(s16x8)); /* 000D 000C 000B 000A */
+ return vreinterpretq_m128i_s32(s32x4);
}
-// Packs the 16 signed 16-bit integers from a and b into 8-bit integers and
-// saturates.
-// https://msdn.microsoft.com/en-us/library/k4y4f7w5%28v=vs.90%29.aspx
-FORCE_INLINE __m128i _mm_packs_epi16(__m128i a, __m128i b)
+// Converts the two signed 8-bit integers in the lower 32 bits to four
+// signed 64-bit integers.
+FORCE_INLINE __m128i _mm_cvtepi8_epi64(__m128i a)
{
- return vreinterpretq_m128i_s8(
- vcombine_s8(vqmovn_s16(vreinterpretq_s16_m128i(a)),
- vqmovn_s16(vreinterpretq_s16_m128i(b))));
+ int8x16_t s8x16 = vreinterpretq_s8_m128i(a); /* xxxx xxxx xxxx xxBA */
+ int16x8_t s16x8 = vmovl_s8(vget_low_s8(s8x16)); /* 0x0x 0x0x 0x0x 0B0A */
+ int32x4_t s32x4 = vmovl_s16(vget_low_s16(s16x8)); /* 000x 000x 000B 000A */
+ int64x2_t s64x2 = vmovl_s32(vget_low_s32(s32x4)); /* 0000 000B 0000 000A */
+ return vreinterpretq_m128i_s64(s64x2);
}
-// Packs the 16 signed 16 - bit integers from a and b into 8 - bit unsigned
-// integers and saturates.
-//
-// r0 := UnsignedSaturate(a0)
-// r1 := UnsignedSaturate(a1)
-// ...
-// r7 := UnsignedSaturate(a7)
-// r8 := UnsignedSaturate(b0)
-// r9 := UnsignedSaturate(b1)
-// ...
-// r15 := UnsignedSaturate(b7)
-//
-// https://msdn.microsoft.com/en-us/library/07ad1wx4(v=vs.100).aspx
-FORCE_INLINE __m128i _mm_packus_epi16(const __m128i a, const __m128i b)
+// Converts the four unsigned 16-bit integers in the lower 64 bits to four
+// unsigned 32-bit integers.
+FORCE_INLINE __m128i _mm_cvtepu16_epi32(__m128i a)
{
- return vreinterpretq_m128i_u8(
- vcombine_u8(vqmovun_s16(vreinterpretq_s16_m128i(a)),
- vqmovun_s16(vreinterpretq_s16_m128i(b))));
+ return vreinterpretq_m128i_u32(
+ vmovl_u16(vget_low_u16(vreinterpretq_u16_m128i(a))));
}
-// Packs the 8 signed 32-bit integers from a and b into signed 16-bit integers
-// and saturates.
-//
-// r0 := SignedSaturate(a0)
-// r1 := SignedSaturate(a1)
-// r2 := SignedSaturate(a2)
-// r3 := SignedSaturate(a3)
-// r4 := SignedSaturate(b0)
-// r5 := SignedSaturate(b1)
-// r6 := SignedSaturate(b2)
-// r7 := SignedSaturate(b3)
-//
-// https://msdn.microsoft.com/en-us/library/393t56f9%28v=vs.90%29.aspx
-FORCE_INLINE __m128i _mm_packs_epi32(__m128i a, __m128i b)
+// Converts the two unsigned 16-bit integers in the lower 32 bits to two
+// unsigned 64-bit integers.
+FORCE_INLINE __m128i _mm_cvtepu16_epi64(__m128i a)
{
- return vreinterpretq_m128i_s16(
- vcombine_s16(vqmovn_s32(vreinterpretq_s32_m128i(a)),
- vqmovn_s32(vreinterpretq_s32_m128i(b))));
+ uint16x8_t u16x8 = vreinterpretq_u16_m128i(a); /* xxxx xxxx xxxx 0B0A */
+ uint32x4_t u32x4 = vmovl_u16(vget_low_u16(u16x8)); /* 000x 000x 000B 000A */
+ uint64x2_t u64x2 = vmovl_u32(vget_low_u32(u32x4)); /* 0000 000B 0000 000A */
+ return vreinterpretq_m128i_u64(u64x2);
}
-// Packs the 8 unsigned 32-bit integers from a and b into unsigned 16-bit
-// integers and saturates.
-//
-// r0 := UnsignedSaturate(a0)
-// r1 := UnsignedSaturate(a1)
-// r2 := UnsignedSaturate(a2)
-// r3 := UnsignedSaturate(a3)
-// r4 := UnsignedSaturate(b0)
-// r5 := UnsignedSaturate(b1)
-// r6 := UnsignedSaturate(b2)
-// r7 := UnsignedSaturate(b3)
-FORCE_INLINE __m128i _mm_packus_epi32(__m128i a, __m128i b)
+// Converts the two unsigned 32-bit integers in the lower 64 bits to two
+// unsigned 64-bit integers.
+FORCE_INLINE __m128i _mm_cvtepu32_epi64(__m128i a)
{
- return vreinterpretq_m128i_u16(
- vcombine_u16(vqmovun_s32(vreinterpretq_s32_m128i(a)),
- vqmovun_s32(vreinterpretq_s32_m128i(b))));
+ return vreinterpretq_m128i_u64(
+ vmovl_u32(vget_low_u32(vreinterpretq_u32_m128i(a))));
}
-// Interleaves the lower 8 signed or unsigned 8-bit integers in a with the lower
-// 8 signed or unsigned 8-bit integers in b.
-//
-// r0 := a0
-// r1 := b0
-// r2 := a1
-// r3 := b1
-// ...
-// r14 := a7
-// r15 := b7
-//
-// https://msdn.microsoft.com/en-us/library/xf7k860c%28v=vs.90%29.aspx
-FORCE_INLINE __m128i _mm_unpacklo_epi8(__m128i a, __m128i b)
+// Zero extend packed unsigned 8-bit integers in a to packed 16-bit integers,
+// and store the results in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtepu8_epi16
+FORCE_INLINE __m128i _mm_cvtepu8_epi16(__m128i a)
{
-#if defined(__aarch64__)
- return vreinterpretq_m128i_s8(
- vzip1q_s8(vreinterpretq_s8_m128i(a), vreinterpretq_s8_m128i(b)));
-#else
- int8x8_t a1 = vreinterpret_s8_s16(vget_low_s16(vreinterpretq_s16_m128i(a)));
- int8x8_t b1 = vreinterpret_s8_s16(vget_low_s16(vreinterpretq_s16_m128i(b)));
- int8x8x2_t result = vzip_s8(a1, b1);
- return vreinterpretq_m128i_s8(vcombine_s8(result.val[0], result.val[1]));
-#endif
+ uint8x16_t u8x16 = vreinterpretq_u8_m128i(a); /* xxxx xxxx HGFE DCBA */
+ uint16x8_t u16x8 = vmovl_u8(vget_low_u8(u8x16)); /* 0H0G 0F0E 0D0C 0B0A */
+ return vreinterpretq_m128i_u16(u16x8);
}
-// Interleaves the lower 4 signed or unsigned 16-bit integers in a with the
-// lower 4 signed or unsigned 16-bit integers in b.
-//
-// r0 := a0
-// r1 := b0
-// r2 := a1
-// r3 := b1
-// r4 := a2
-// r5 := b2
-// r6 := a3
-// r7 := b3
-//
-// https://msdn.microsoft.com/en-us/library/btxb17bw%28v=vs.90%29.aspx
-FORCE_INLINE __m128i _mm_unpacklo_epi16(__m128i a, __m128i b)
+// Converts the four unsigned 8-bit integers in the lower 32 bits to four
+// unsigned 32-bit integers.
+// https://msdn.microsoft.com/en-us/library/bb531467%28v=vs.100%29.aspx
+FORCE_INLINE __m128i _mm_cvtepu8_epi32(__m128i a)
{
-#if defined(__aarch64__)
- return vreinterpretq_m128i_s16(
- vzip1q_s16(vreinterpretq_s16_m128i(a), vreinterpretq_s16_m128i(b)));
-#else
- int16x4_t a1 = vget_low_s16(vreinterpretq_s16_m128i(a));
- int16x4_t b1 = vget_low_s16(vreinterpretq_s16_m128i(b));
- int16x4x2_t result = vzip_s16(a1, b1);
- return vreinterpretq_m128i_s16(vcombine_s16(result.val[0], result.val[1]));
-#endif
+ uint8x16_t u8x16 = vreinterpretq_u8_m128i(a); /* xxxx xxxx xxxx DCBA */
+ uint16x8_t u16x8 = vmovl_u8(vget_low_u8(u8x16)); /* 0x0x 0x0x 0D0C 0B0A */
+ uint32x4_t u32x4 = vmovl_u16(vget_low_u16(u16x8)); /* 000D 000C 000B 000A */
+ return vreinterpretq_m128i_u32(u32x4);
}
-// Interleaves the lower 2 signed or unsigned 32 - bit integers in a with the
-// lower 2 signed or unsigned 32 - bit integers in b.
-//
-// r0 := a0
-// r1 := b0
-// r2 := a1
-// r3 := b1
-//
-// https://msdn.microsoft.com/en-us/library/x8atst9d(v=vs.100).aspx
-FORCE_INLINE __m128i _mm_unpacklo_epi32(__m128i a, __m128i b)
+// Converts the two unsigned 8-bit integers in the lower 16 bits to two
+// unsigned 64-bit integers.
+FORCE_INLINE __m128i _mm_cvtepu8_epi64(__m128i a)
+{
+ uint8x16_t u8x16 = vreinterpretq_u8_m128i(a); /* xxxx xxxx xxxx xxBA */
+ uint16x8_t u16x8 = vmovl_u8(vget_low_u8(u8x16)); /* 0x0x 0x0x 0x0x 0B0A */
+ uint32x4_t u32x4 = vmovl_u16(vget_low_u16(u16x8)); /* 000x 000x 000B 000A */
+ uint64x2_t u64x2 = vmovl_u32(vget_low_u32(u32x4)); /* 0000 000B 0000 000A */
+ return vreinterpretq_m128i_u64(u64x2);
+}
+
+// Conditionally multiply the packed double-precision (64-bit) floating-point
+// elements in a and b using the high 4 bits in imm8, sum the four products, and
+// conditionally store the sum in dst using the low 4 bits of imm8.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_dp_pd
+FORCE_INLINE __m128d _mm_dp_pd(__m128d a, __m128d b, const int imm)
{
+ // Generate mask value from constant immediate bit value
+ const int64_t bit0Mask = imm & 0x01 ? UINT64_MAX : 0;
+ const int64_t bit1Mask = imm & 0x02 ? UINT64_MAX : 0;
+#if !SSE2NEON_PRECISE_DP
+ const int64_t bit4Mask = imm & 0x10 ? UINT64_MAX : 0;
+ const int64_t bit5Mask = imm & 0x20 ? UINT64_MAX : 0;
+#endif
+ // Conditional multiplication
+#if !SSE2NEON_PRECISE_DP
+ __m128d mul = _mm_mul_pd(a, b);
+ const __m128d mulMask =
+ _mm_castsi128_pd(_mm_set_epi64x(bit5Mask, bit4Mask));
+ __m128d tmp = _mm_and_pd(mul, mulMask);
+#else
#if defined(__aarch64__)
- return vreinterpretq_m128i_s32(
- vzip1q_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(b)));
+ double d0 = (imm & 0x10) ? vgetq_lane_f64(vreinterpretq_f64_m128d(a), 0) *
+ vgetq_lane_f64(vreinterpretq_f64_m128d(b), 0)
+ : 0;
+ double d1 = (imm & 0x20) ? vgetq_lane_f64(vreinterpretq_f64_m128d(a), 1) *
+ vgetq_lane_f64(vreinterpretq_f64_m128d(b), 1)
+ : 0;
#else
- int32x2_t a1 = vget_low_s32(vreinterpretq_s32_m128i(a));
- int32x2_t b1 = vget_low_s32(vreinterpretq_s32_m128i(b));
- int32x2x2_t result = vzip_s32(a1, b1);
- return vreinterpretq_m128i_s32(vcombine_s32(result.val[0], result.val[1]));
+ double d0 = (imm & 0x10) ? ((double *) &a)[0] * ((double *) &b)[0] : 0;
+ double d1 = (imm & 0x20) ? ((double *) &a)[1] * ((double *) &b)[1] : 0;
+#endif
+ __m128d tmp = _mm_set_pd(d1, d0);
#endif
+ // Sum the products
+#if defined(__aarch64__)
+ double sum = vpaddd_f64(vreinterpretq_f64_m128d(tmp));
+#else
+ double sum = *((double *) &tmp) + *(((double *) &tmp) + 1);
+#endif
+ // Conditionally store the sum
+ const __m128d sumMask =
+ _mm_castsi128_pd(_mm_set_epi64x(bit1Mask, bit0Mask));
+ __m128d res = _mm_and_pd(_mm_set_pd1(sum), sumMask);
+ return res;
}
-FORCE_INLINE __m128i _mm_unpacklo_epi64(__m128i a, __m128i b)
+// Conditionally multiply the packed single-precision (32-bit) floating-point
+// elements in a and b using the high 4 bits in imm8, sum the four products,
+// and conditionally store the sum in dst using the low 4 bits of imm.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_dp_ps
+FORCE_INLINE __m128 _mm_dp_ps(__m128 a, __m128 b, const int imm)
{
- int64x1_t a_l = vget_low_s64(vreinterpretq_s64_m128i(a));
- int64x1_t b_l = vget_low_s64(vreinterpretq_s64_m128i(b));
- return vreinterpretq_m128i_s64(vcombine_s64(a_l, b_l));
+#if defined(__aarch64__)
+ /* shortcuts */
+ if (imm == 0xFF) {
+ return _mm_set1_ps(vaddvq_f32(_mm_mul_ps(a, b)));
+ }
+ if (imm == 0x7F) {
+ float32x4_t m = _mm_mul_ps(a, b);
+ m[3] = 0;
+ return _mm_set1_ps(vaddvq_f32(m));
+ }
+#endif
+
+ float s = 0, c = 0;
+ float32x4_t f32a = vreinterpretq_f32_m128(a);
+ float32x4_t f32b = vreinterpretq_f32_m128(b);
+
+ /* To improve the accuracy of floating-point summation, Kahan algorithm
+ * is used for each operation.
+ */
+ if (imm & (1 << 4))
+ _sse2neon_kadd_f32(&s, &c, f32a[0] * f32b[0]);
+ if (imm & (1 << 5))
+ _sse2neon_kadd_f32(&s, &c, f32a[1] * f32b[1]);
+ if (imm & (1 << 6))
+ _sse2neon_kadd_f32(&s, &c, f32a[2] * f32b[2]);
+ if (imm & (1 << 7))
+ _sse2neon_kadd_f32(&s, &c, f32a[3] * f32b[3]);
+ s += c;
+
+ float32x4_t res = {
+ (imm & 0x1) ? s : 0,
+ (imm & 0x2) ? s : 0,
+ (imm & 0x4) ? s : 0,
+ (imm & 0x8) ? s : 0,
+ };
+ return vreinterpretq_m128_f32(res);
}
-// Selects and interleaves the lower two single-precision, floating-point values
-// from a and b.
-//
-// r0 := a0
-// r1 := b0
-// r2 := a1
-// r3 := b1
-//
-// https://msdn.microsoft.com/en-us/library/25st103b%28v=vs.90%29.aspx
-FORCE_INLINE __m128 _mm_unpacklo_ps(__m128 a, __m128 b)
+// Extracts the selected signed or unsigned 32-bit integer from a and zero
+// extends.
+// FORCE_INLINE int _mm_extract_epi32(__m128i a, __constrange(0,4) int imm)
+#define _mm_extract_epi32(a, imm) \
+ vgetq_lane_s32(vreinterpretq_s32_m128i(a), (imm))
+
+// Extracts the selected signed or unsigned 64-bit integer from a and zero
+// extends.
+// FORCE_INLINE __int64 _mm_extract_epi64(__m128i a, __constrange(0,2) int imm)
+#define _mm_extract_epi64(a, imm) \
+ vgetq_lane_s64(vreinterpretq_s64_m128i(a), (imm))
+
+// Extracts the selected signed or unsigned 8-bit integer from a and zero
+// extends.
+// FORCE_INLINE int _mm_extract_epi8(__m128i a, __constrange(0,16) int imm)
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_extract_epi8
+#define _mm_extract_epi8(a, imm) vgetq_lane_u8(vreinterpretq_u8_m128i(a), (imm))
+
+// Extracts the selected single-precision (32-bit) floating-point from a.
+// FORCE_INLINE int _mm_extract_ps(__m128 a, __constrange(0,4) int imm)
+#define _mm_extract_ps(a, imm) vgetq_lane_s32(vreinterpretq_s32_m128(a), (imm))
+
+// Round the packed double-precision (64-bit) floating-point elements in a down
+// to an integer value, and store the results as packed double-precision
+// floating-point elements in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_floor_pd
+FORCE_INLINE __m128d _mm_floor_pd(__m128d a)
{
#if defined(__aarch64__)
- return vreinterpretq_m128_f32(
- vzip1q_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b)));
+ return vreinterpretq_m128d_f64(vrndmq_f64(vreinterpretq_f64_m128d(a)));
#else
- float32x2_t a1 = vget_low_f32(vreinterpretq_f32_m128(a));
- float32x2_t b1 = vget_low_f32(vreinterpretq_f32_m128(b));
- float32x2x2_t result = vzip_f32(a1, b1);
- return vreinterpretq_m128_f32(vcombine_f32(result.val[0], result.val[1]));
+ double *f = (double *) &a;
+ return _mm_set_pd(floor(f[1]), floor(f[0]));
#endif
}
-// Unpack and interleave double-precision (64-bit) floating-point elements from
-// the low half of a and b, and store the results in dst.
-//
-// DEFINE INTERLEAVE_QWORDS(src1[127:0], src2[127:0]) {
-// dst[63:0] := src1[63:0]
-// dst[127:64] := src2[63:0]
-// RETURN dst[127:0]
-// }
-// dst[127:0] := INTERLEAVE_QWORDS(a[127:0], b[127:0])
-//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_unpacklo_pd
-FORCE_INLINE __m128d _mm_unpacklo_pd(__m128d a, __m128d b)
+// Round the packed single-precision (32-bit) floating-point elements in a down
+// to an integer value, and store the results as packed single-precision
+// floating-point elements in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_floor_ps
+FORCE_INLINE __m128 _mm_floor_ps(__m128 a)
{
#if defined(__aarch64__)
- return vreinterpretq_m128d_f64(
- vzip1q_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(b)));
+ return vreinterpretq_m128_f32(vrndmq_f32(vreinterpretq_f32_m128(a)));
#else
- return vreinterpretq_m128d_s64(
- vcombine_s64(vget_low_s64(vreinterpretq_s64_m128d(a)),
- vget_low_s64(vreinterpretq_s64_m128d(b))));
+ float *f = (float *) &a;
+ return _mm_set_ps(floorf(f[3]), floorf(f[2]), floorf(f[1]), floorf(f[0]));
#endif
}
-// Unpack and interleave double-precision (64-bit) floating-point elements from
-// the high half of a and b, and store the results in dst.
-//
-// DEFINE INTERLEAVE_HIGH_QWORDS(src1[127:0], src2[127:0]) {
-// dst[63:0] := src1[127:64]
-// dst[127:64] := src2[127:64]
-// RETURN dst[127:0]
-// }
-// dst[127:0] := INTERLEAVE_HIGH_QWORDS(a[127:0], b[127:0])
-//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_unpackhi_pd
-FORCE_INLINE __m128d _mm_unpackhi_pd(__m128d a, __m128d b)
+// Round the lower double-precision (64-bit) floating-point element in b down to
+// an integer value, store the result as a double-precision floating-point
+// element in the lower element of dst, and copy the upper element from a to the
+// upper element of dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_floor_sd
+FORCE_INLINE __m128d _mm_floor_sd(__m128d a, __m128d b)
{
-#if defined(__aarch64__)
- return vreinterpretq_m128d_f64(
- vzip2q_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(b)));
-#else
- return vreinterpretq_m128d_s64(
- vcombine_s64(vget_high_s64(vreinterpretq_s64_m128d(a)),
- vget_high_s64(vreinterpretq_s64_m128d(b))));
-#endif
+ return _mm_move_sd(a, _mm_floor_pd(b));
}
-// Selects and interleaves the upper two single-precision, floating-point values
-// from a and b.
+// Round the lower single-precision (32-bit) floating-point element in b down to
+// an integer value, store the result as a single-precision floating-point
+// element in the lower element of dst, and copy the upper 3 packed elements
+// from a to the upper elements of dst.
//
-// r0 := a2
-// r1 := b2
-// r2 := a3
-// r3 := b3
+// dst[31:0] := FLOOR(b[31:0])
+// dst[127:32] := a[127:32]
//
-// https://msdn.microsoft.com/en-us/library/skccxx7d%28v=vs.90%29.aspx
-FORCE_INLINE __m128 _mm_unpackhi_ps(__m128 a, __m128 b)
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_floor_ss
+FORCE_INLINE __m128 _mm_floor_ss(__m128 a, __m128 b)
{
-#if defined(__aarch64__)
- return vreinterpretq_m128_f32(
- vzip2q_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b)));
-#else
- float32x2_t a1 = vget_high_f32(vreinterpretq_f32_m128(a));
- float32x2_t b1 = vget_high_f32(vreinterpretq_f32_m128(b));
- float32x2x2_t result = vzip_f32(a1, b1);
- return vreinterpretq_m128_f32(vcombine_f32(result.val[0], result.val[1]));
-#endif
+ return _mm_move_ss(a, _mm_floor_ps(b));
}
-// Interleaves the upper 8 signed or unsigned 8-bit integers in a with the upper
-// 8 signed or unsigned 8-bit integers in b.
+// Inserts the least significant 32 bits of b into the selected 32-bit integer
+// of a.
+// FORCE_INLINE __m128i _mm_insert_epi32(__m128i a, int b,
+// __constrange(0,4) int imm)
+#define _mm_insert_epi32(a, b, imm) \
+ __extension__({ \
+ vreinterpretq_m128i_s32( \
+ vsetq_lane_s32((b), vreinterpretq_s32_m128i(a), (imm))); \
+ })
+
+// Inserts the least significant 64 bits of b into the selected 64-bit integer
+// of a.
+// FORCE_INLINE __m128i _mm_insert_epi64(__m128i a, __int64 b,
+// __constrange(0,2) int imm)
+#define _mm_insert_epi64(a, b, imm) \
+ __extension__({ \
+ vreinterpretq_m128i_s64( \
+ vsetq_lane_s64((b), vreinterpretq_s64_m128i(a), (imm))); \
+ })
+
+// Inserts the least significant 8 bits of b into the selected 8-bit integer
+// of a.
+// FORCE_INLINE __m128i _mm_insert_epi8(__m128i a, int b,
+// __constrange(0,16) int imm)
+#define _mm_insert_epi8(a, b, imm) \
+ __extension__({ \
+ vreinterpretq_m128i_s8( \
+ vsetq_lane_s8((b), vreinterpretq_s8_m128i(a), (imm))); \
+ })
+
+// Copy a to tmp, then insert a single-precision (32-bit) floating-point
+// element from b into tmp using the control in imm8. Store tmp to dst using
+// the mask in imm8 (elements are zeroed out when the corresponding bit is set).
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=insert_ps
+#define _mm_insert_ps(a, b, imm8) \
+ __extension__({ \
+ float32x4_t tmp1 = \
+ vsetq_lane_f32(vgetq_lane_f32(b, (imm8 >> 6) & 0x3), \
+ vreinterpretq_f32_m128(a), 0); \
+ float32x4_t tmp2 = \
+ vsetq_lane_f32(vgetq_lane_f32(tmp1, 0), vreinterpretq_f32_m128(a), \
+ ((imm8 >> 4) & 0x3)); \
+ const uint32_t data[4] = {((imm8) & (1 << 0)) ? UINT32_MAX : 0, \
+ ((imm8) & (1 << 1)) ? UINT32_MAX : 0, \
+ ((imm8) & (1 << 2)) ? UINT32_MAX : 0, \
+ ((imm8) & (1 << 3)) ? UINT32_MAX : 0}; \
+ uint32x4_t mask = vld1q_u32(data); \
+ float32x4_t all_zeros = vdupq_n_f32(0); \
+ \
+ vreinterpretq_m128_f32( \
+ vbslq_f32(mask, all_zeros, vreinterpretq_f32_m128(tmp2))); \
+ })
+
+// epi versions of min/max
+// Computes the pariwise maximums of the four signed 32-bit integer values of a
+// and b.
//
-// r0 := a8
-// r1 := b8
-// r2 := a9
-// r3 := b9
-// ...
-// r14 := a15
-// r15 := b15
+// A 128-bit parameter that can be defined with the following equations:
+// r0 := (a0 > b0) ? a0 : b0
+// r1 := (a1 > b1) ? a1 : b1
+// r2 := (a2 > b2) ? a2 : b2
+// r3 := (a3 > b3) ? a3 : b3
//
-// https://msdn.microsoft.com/en-us/library/t5h7783k(v=vs.100).aspx
-FORCE_INLINE __m128i _mm_unpackhi_epi8(__m128i a, __m128i b)
+// https://msdn.microsoft.com/en-us/library/vstudio/bb514055(v=vs.100).aspx
+FORCE_INLINE __m128i _mm_max_epi32(__m128i a, __m128i b)
+{
+ return vreinterpretq_m128i_s32(
+ vmaxq_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(b)));
+}
+
+// Compare packed signed 8-bit integers in a and b, and store packed maximum
+// values in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_max_epi8
+FORCE_INLINE __m128i _mm_max_epi8(__m128i a, __m128i b)
{
-#if defined(__aarch64__)
return vreinterpretq_m128i_s8(
- vzip2q_s8(vreinterpretq_s8_m128i(a), vreinterpretq_s8_m128i(b)));
-#else
- int8x8_t a1 =
- vreinterpret_s8_s16(vget_high_s16(vreinterpretq_s16_m128i(a)));
- int8x8_t b1 =
- vreinterpret_s8_s16(vget_high_s16(vreinterpretq_s16_m128i(b)));
- int8x8x2_t result = vzip_s8(a1, b1);
- return vreinterpretq_m128i_s8(vcombine_s8(result.val[0], result.val[1]));
-#endif
+ vmaxq_s8(vreinterpretq_s8_m128i(a), vreinterpretq_s8_m128i(b)));
}
-// Interleaves the upper 4 signed or unsigned 16-bit integers in a with the
-// upper 4 signed or unsigned 16-bit integers in b.
+// Compare packed unsigned 16-bit integers in a and b, and store packed maximum
+// values in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_max_epu16
+FORCE_INLINE __m128i _mm_max_epu16(__m128i a, __m128i b)
+{
+ return vreinterpretq_m128i_u16(
+ vmaxq_u16(vreinterpretq_u16_m128i(a), vreinterpretq_u16_m128i(b)));
+}
+
+// Compare packed unsigned 32-bit integers in a and b, and store packed maximum
+// values in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_max_epu32
+FORCE_INLINE __m128i _mm_max_epu32(__m128i a, __m128i b)
+{
+ return vreinterpretq_m128i_u32(
+ vmaxq_u32(vreinterpretq_u32_m128i(a), vreinterpretq_u32_m128i(b)));
+}
+
+// Computes the pariwise minima of the four signed 32-bit integer values of a
+// and b.
//
-// r0 := a4
-// r1 := b4
-// r2 := a5
-// r3 := b5
-// r4 := a6
-// r5 := b6
-// r6 := a7
-// r7 := b7
+// A 128-bit parameter that can be defined with the following equations:
+// r0 := (a0 < b0) ? a0 : b0
+// r1 := (a1 < b1) ? a1 : b1
+// r2 := (a2 < b2) ? a2 : b2
+// r3 := (a3 < b3) ? a3 : b3
//
-// https://msdn.microsoft.com/en-us/library/03196cz7(v=vs.100).aspx
-FORCE_INLINE __m128i _mm_unpackhi_epi16(__m128i a, __m128i b)
+// https://msdn.microsoft.com/en-us/library/vstudio/bb531476(v=vs.100).aspx
+FORCE_INLINE __m128i _mm_min_epi32(__m128i a, __m128i b)
{
-#if defined(__aarch64__)
- return vreinterpretq_m128i_s16(
- vzip2q_s16(vreinterpretq_s16_m128i(a), vreinterpretq_s16_m128i(b)));
-#else
- int16x4_t a1 = vget_high_s16(vreinterpretq_s16_m128i(a));
- int16x4_t b1 = vget_high_s16(vreinterpretq_s16_m128i(b));
- int16x4x2_t result = vzip_s16(a1, b1);
- return vreinterpretq_m128i_s16(vcombine_s16(result.val[0], result.val[1]));
-#endif
+ return vreinterpretq_m128i_s32(
+ vminq_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(b)));
}
-// Interleaves the upper 2 signed or unsigned 32-bit integers in a with the
-// upper 2 signed or unsigned 32-bit integers in b.
-// https://msdn.microsoft.com/en-us/library/65sa7cbs(v=vs.100).aspx
-FORCE_INLINE __m128i _mm_unpackhi_epi32(__m128i a, __m128i b)
+// Compare packed signed 8-bit integers in a and b, and store packed minimum
+// values in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_min_epi8
+FORCE_INLINE __m128i _mm_min_epi8(__m128i a, __m128i b)
{
-#if defined(__aarch64__)
- return vreinterpretq_m128i_s32(
- vzip2q_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(b)));
-#else
- int32x2_t a1 = vget_high_s32(vreinterpretq_s32_m128i(a));
- int32x2_t b1 = vget_high_s32(vreinterpretq_s32_m128i(b));
- int32x2x2_t result = vzip_s32(a1, b1);
- return vreinterpretq_m128i_s32(vcombine_s32(result.val[0], result.val[1]));
-#endif
+ return vreinterpretq_m128i_s8(
+ vminq_s8(vreinterpretq_s8_m128i(a), vreinterpretq_s8_m128i(b)));
}
-// Interleaves the upper signed or unsigned 64-bit integer in a with the
-// upper signed or unsigned 64-bit integer in b.
-//
-// r0 := a1
-// r1 := b1
-FORCE_INLINE __m128i _mm_unpackhi_epi64(__m128i a, __m128i b)
+// Compare packed unsigned 16-bit integers in a and b, and store packed minimum
+// values in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_min_epu16
+FORCE_INLINE __m128i _mm_min_epu16(__m128i a, __m128i b)
{
- int64x1_t a_h = vget_high_s64(vreinterpretq_s64_m128i(a));
- int64x1_t b_h = vget_high_s64(vreinterpretq_s64_m128i(b));
- return vreinterpretq_m128i_s64(vcombine_s64(a_h, b_h));
+ return vreinterpretq_m128i_u16(
+ vminq_u16(vreinterpretq_u16_m128i(a), vreinterpretq_u16_m128i(b)));
+}
+
+// Compare packed unsigned 32-bit integers in a and b, and store packed minimum
+// values in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_max_epu32
+FORCE_INLINE __m128i _mm_min_epu32(__m128i a, __m128i b)
+{
+ return vreinterpretq_m128i_u32(
+ vminq_u32(vreinterpretq_u32_m128i(a), vreinterpretq_u32_m128i(b)));
}
// Horizontally compute the minimum amongst the packed unsigned 16-bit integers
@@ -6296,6 +7929,339 @@ FORCE_INLINE __m128i _mm_minpos_epu16(__m128i a)
return dst;
}
+// Compute the sum of absolute differences (SADs) of quadruplets of unsigned
+// 8-bit integers in a compared to those in b, and store the 16-bit results in
+// dst. Eight SADs are performed using one quadruplet from b and eight
+// quadruplets from a. One quadruplet is selected from b starting at on the
+// offset specified in imm8. Eight quadruplets are formed from sequential 8-bit
+// integers selected from a starting at the offset specified in imm8.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mpsadbw_epu8
+FORCE_INLINE __m128i _mm_mpsadbw_epu8(__m128i a, __m128i b, const int imm)
+{
+ uint8x16_t _a, _b;
+
+ switch (imm & 0x4) {
+ case 0:
+ // do nothing
+ _a = vreinterpretq_u8_m128i(a);
+ break;
+ case 4:
+ _a = vreinterpretq_u8_u32(vextq_u32(vreinterpretq_u32_m128i(a),
+ vreinterpretq_u32_m128i(a), 1));
+ break;
+ default:
+#if defined(__GNUC__) || defined(__clang__)
+ __builtin_unreachable();
+#endif
+ break;
+ }
+
+ switch (imm & 0x3) {
+ case 0:
+ _b = vreinterpretq_u8_u32(
+ vdupq_n_u32(vgetq_lane_u32(vreinterpretq_u32_m128i(b), 0)));
+ break;
+ case 1:
+ _b = vreinterpretq_u8_u32(
+ vdupq_n_u32(vgetq_lane_u32(vreinterpretq_u32_m128i(b), 1)));
+ break;
+ case 2:
+ _b = vreinterpretq_u8_u32(
+ vdupq_n_u32(vgetq_lane_u32(vreinterpretq_u32_m128i(b), 2)));
+ break;
+ case 3:
+ _b = vreinterpretq_u8_u32(
+ vdupq_n_u32(vgetq_lane_u32(vreinterpretq_u32_m128i(b), 3)));
+ break;
+ default:
+#if defined(__GNUC__) || defined(__clang__)
+ __builtin_unreachable();
+#endif
+ break;
+ }
+
+ int16x8_t c04, c15, c26, c37;
+ uint8x8_t low_b = vget_low_u8(_b);
+ c04 = vabsq_s16(vreinterpretq_s16_u16(vsubl_u8(vget_low_u8(_a), low_b)));
+ _a = vextq_u8(_a, _a, 1);
+ c15 = vabsq_s16(vreinterpretq_s16_u16(vsubl_u8(vget_low_u8(_a), low_b)));
+ _a = vextq_u8(_a, _a, 1);
+ c26 = vabsq_s16(vreinterpretq_s16_u16(vsubl_u8(vget_low_u8(_a), low_b)));
+ _a = vextq_u8(_a, _a, 1);
+ c37 = vabsq_s16(vreinterpretq_s16_u16(vsubl_u8(vget_low_u8(_a), low_b)));
+#if defined(__aarch64__)
+ // |0|4|2|6|
+ c04 = vpaddq_s16(c04, c26);
+ // |1|5|3|7|
+ c15 = vpaddq_s16(c15, c37);
+
+ int32x4_t trn1_c =
+ vtrn1q_s32(vreinterpretq_s32_s16(c04), vreinterpretq_s32_s16(c15));
+ int32x4_t trn2_c =
+ vtrn2q_s32(vreinterpretq_s32_s16(c04), vreinterpretq_s32_s16(c15));
+ return vreinterpretq_m128i_s16(vpaddq_s16(vreinterpretq_s16_s32(trn1_c),
+ vreinterpretq_s16_s32(trn2_c)));
+#else
+ int16x4_t c01, c23, c45, c67;
+ c01 = vpadd_s16(vget_low_s16(c04), vget_low_s16(c15));
+ c23 = vpadd_s16(vget_low_s16(c26), vget_low_s16(c37));
+ c45 = vpadd_s16(vget_high_s16(c04), vget_high_s16(c15));
+ c67 = vpadd_s16(vget_high_s16(c26), vget_high_s16(c37));
+
+ return vreinterpretq_m128i_s16(
+ vcombine_s16(vpadd_s16(c01, c23), vpadd_s16(c45, c67)));
+#endif
+}
+
+// Multiply the low signed 32-bit integers from each packed 64-bit element in
+// a and b, and store the signed 64-bit results in dst.
+//
+// r0 := (int64_t)(int32_t)a0 * (int64_t)(int32_t)b0
+// r1 := (int64_t)(int32_t)a2 * (int64_t)(int32_t)b2
+FORCE_INLINE __m128i _mm_mul_epi32(__m128i a, __m128i b)
+{
+ // vmull_s32 upcasts instead of masking, so we downcast.
+ int32x2_t a_lo = vmovn_s64(vreinterpretq_s64_m128i(a));
+ int32x2_t b_lo = vmovn_s64(vreinterpretq_s64_m128i(b));
+ return vreinterpretq_m128i_s64(vmull_s32(a_lo, b_lo));
+}
+
+// Multiplies the 4 signed or unsigned 32-bit integers from a by the 4 signed or
+// unsigned 32-bit integers from b.
+// https://msdn.microsoft.com/en-us/library/vstudio/bb531409(v=vs.100).aspx
+FORCE_INLINE __m128i _mm_mullo_epi32(__m128i a, __m128i b)
+{
+ return vreinterpretq_m128i_s32(
+ vmulq_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(b)));
+}
+
+// Packs the 8 unsigned 32-bit integers from a and b into unsigned 16-bit
+// integers and saturates.
+//
+// r0 := UnsignedSaturate(a0)
+// r1 := UnsignedSaturate(a1)
+// r2 := UnsignedSaturate(a2)
+// r3 := UnsignedSaturate(a3)
+// r4 := UnsignedSaturate(b0)
+// r5 := UnsignedSaturate(b1)
+// r6 := UnsignedSaturate(b2)
+// r7 := UnsignedSaturate(b3)
+FORCE_INLINE __m128i _mm_packus_epi32(__m128i a, __m128i b)
+{
+ return vreinterpretq_m128i_u16(
+ vcombine_u16(vqmovun_s32(vreinterpretq_s32_m128i(a)),
+ vqmovun_s32(vreinterpretq_s32_m128i(b))));
+}
+
+// Round the packed double-precision (64-bit) floating-point elements in a using
+// the rounding parameter, and store the results as packed double-precision
+// floating-point elements in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_round_pd
+FORCE_INLINE __m128d _mm_round_pd(__m128d a, int rounding)
+{
+#if defined(__aarch64__)
+ switch (rounding) {
+ case (_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC):
+ return vreinterpretq_m128d_f64(vrndnq_f64(vreinterpretq_f64_m128d(a)));
+ case (_MM_FROUND_TO_NEG_INF | _MM_FROUND_NO_EXC):
+ return _mm_floor_pd(a);
+ case (_MM_FROUND_TO_POS_INF | _MM_FROUND_NO_EXC):
+ return _mm_ceil_pd(a);
+ case (_MM_FROUND_TO_ZERO | _MM_FROUND_NO_EXC):
+ return vreinterpretq_m128d_f64(vrndq_f64(vreinterpretq_f64_m128d(a)));
+ default: //_MM_FROUND_CUR_DIRECTION
+ return vreinterpretq_m128d_f64(vrndiq_f64(vreinterpretq_f64_m128d(a)));
+ }
+#else
+ double *v_double = (double *) &a;
+
+ if (rounding == (_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC) ||
+ (rounding == _MM_FROUND_CUR_DIRECTION &&
+ _MM_GET_ROUNDING_MODE() == _MM_ROUND_NEAREST)) {
+ double res[2], tmp;
+ for (int i = 0; i < 2; i++) {
+ tmp = (v_double[i] < 0) ? -v_double[i] : v_double[i];
+ double roundDown = floor(tmp); // Round down value
+ double roundUp = ceil(tmp); // Round up value
+ double diffDown = tmp - roundDown;
+ double diffUp = roundUp - tmp;
+ if (diffDown < diffUp) {
+ /* If it's closer to the round down value, then use it */
+ res[i] = roundDown;
+ } else if (diffDown > diffUp) {
+ /* If it's closer to the round up value, then use it */
+ res[i] = roundUp;
+ } else {
+ /* If it's equidistant between round up and round down value,
+ * pick the one which is an even number */
+ double half = roundDown / 2;
+ if (half != floor(half)) {
+ /* If the round down value is odd, return the round up value
+ */
+ res[i] = roundUp;
+ } else {
+ /* If the round up value is odd, return the round down value
+ */
+ res[i] = roundDown;
+ }
+ }
+ res[i] = (v_double[i] < 0) ? -res[i] : res[i];
+ }
+ return _mm_set_pd(res[1], res[0]);
+ } else if (rounding == (_MM_FROUND_TO_NEG_INF | _MM_FROUND_NO_EXC) ||
+ (rounding == _MM_FROUND_CUR_DIRECTION &&
+ _MM_GET_ROUNDING_MODE() == _MM_ROUND_DOWN)) {
+ return _mm_floor_pd(a);
+ } else if (rounding == (_MM_FROUND_TO_POS_INF | _MM_FROUND_NO_EXC) ||
+ (rounding == _MM_FROUND_CUR_DIRECTION &&
+ _MM_GET_ROUNDING_MODE() == _MM_ROUND_UP)) {
+ return _mm_ceil_pd(a);
+ }
+ return _mm_set_pd(v_double[1] > 0 ? floor(v_double[1]) : ceil(v_double[1]),
+ v_double[0] > 0 ? floor(v_double[0]) : ceil(v_double[0]));
+#endif
+}
+
+// Round the packed single-precision (32-bit) floating-point elements in a using
+// the rounding parameter, and store the results as packed single-precision
+// floating-point elements in dst.
+// software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_round_ps
+FORCE_INLINE __m128 _mm_round_ps(__m128 a, int rounding)
+{
+#if defined(__aarch64__)
+ switch (rounding) {
+ case (_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC):
+ return vreinterpretq_m128_f32(vrndnq_f32(vreinterpretq_f32_m128(a)));
+ case (_MM_FROUND_TO_NEG_INF | _MM_FROUND_NO_EXC):
+ return _mm_floor_ps(a);
+ case (_MM_FROUND_TO_POS_INF | _MM_FROUND_NO_EXC):
+ return _mm_ceil_ps(a);
+ case (_MM_FROUND_TO_ZERO | _MM_FROUND_NO_EXC):
+ return vreinterpretq_m128_f32(vrndq_f32(vreinterpretq_f32_m128(a)));
+ default: //_MM_FROUND_CUR_DIRECTION
+ return vreinterpretq_m128_f32(vrndiq_f32(vreinterpretq_f32_m128(a)));
+ }
+#else
+ float *v_float = (float *) &a;
+
+ if (rounding == (_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC) ||
+ (rounding == _MM_FROUND_CUR_DIRECTION &&
+ _MM_GET_ROUNDING_MODE() == _MM_ROUND_NEAREST)) {
+ uint32x4_t signmask = vdupq_n_u32(0x80000000);
+ float32x4_t half = vbslq_f32(signmask, vreinterpretq_f32_m128(a),
+ vdupq_n_f32(0.5f)); /* +/- 0.5 */
+ int32x4_t r_normal = vcvtq_s32_f32(vaddq_f32(
+ vreinterpretq_f32_m128(a), half)); /* round to integer: [a + 0.5]*/
+ int32x4_t r_trunc = vcvtq_s32_f32(
+ vreinterpretq_f32_m128(a)); /* truncate to integer: [a] */
+ int32x4_t plusone = vreinterpretq_s32_u32(vshrq_n_u32(
+ vreinterpretq_u32_s32(vnegq_s32(r_trunc)), 31)); /* 1 or 0 */
+ int32x4_t r_even = vbicq_s32(vaddq_s32(r_trunc, plusone),
+ vdupq_n_s32(1)); /* ([a] + {0,1}) & ~1 */
+ float32x4_t delta = vsubq_f32(
+ vreinterpretq_f32_m128(a),
+ vcvtq_f32_s32(r_trunc)); /* compute delta: delta = (a - [a]) */
+ uint32x4_t is_delta_half =
+ vceqq_f32(delta, half); /* delta == +/- 0.5 */
+ return vreinterpretq_m128_f32(
+ vcvtq_f32_s32(vbslq_s32(is_delta_half, r_even, r_normal)));
+ } else if (rounding == (_MM_FROUND_TO_NEG_INF | _MM_FROUND_NO_EXC) ||
+ (rounding == _MM_FROUND_CUR_DIRECTION &&
+ _MM_GET_ROUNDING_MODE() == _MM_ROUND_DOWN)) {
+ return _mm_floor_ps(a);
+ } else if (rounding == (_MM_FROUND_TO_POS_INF | _MM_FROUND_NO_EXC) ||
+ (rounding == _MM_FROUND_CUR_DIRECTION &&
+ _MM_GET_ROUNDING_MODE() == _MM_ROUND_UP)) {
+ return _mm_ceil_ps(a);
+ }
+ return _mm_set_ps(v_float[3] > 0 ? floorf(v_float[3]) : ceilf(v_float[3]),
+ v_float[2] > 0 ? floorf(v_float[2]) : ceilf(v_float[2]),
+ v_float[1] > 0 ? floorf(v_float[1]) : ceilf(v_float[1]),
+ v_float[0] > 0 ? floorf(v_float[0]) : ceilf(v_float[0]));
+#endif
+}
+
+// Round the lower double-precision (64-bit) floating-point element in b using
+// the rounding parameter, store the result as a double-precision floating-point
+// element in the lower element of dst, and copy the upper element from a to the
+// upper element of dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_round_sd
+FORCE_INLINE __m128d _mm_round_sd(__m128d a, __m128d b, int rounding)
+{
+ return _mm_move_sd(a, _mm_round_pd(b, rounding));
+}
+
+// Round the lower single-precision (32-bit) floating-point element in b using
+// the rounding parameter, store the result as a single-precision floating-point
+// element in the lower element of dst, and copy the upper 3 packed elements
+// from a to the upper elements of dst. Rounding is done according to the
+// rounding[3:0] parameter, which can be one of:
+// (_MM_FROUND_TO_NEAREST_INT |_MM_FROUND_NO_EXC) // round to nearest, and
+// suppress exceptions
+// (_MM_FROUND_TO_NEG_INF |_MM_FROUND_NO_EXC) // round down, and
+// suppress exceptions
+// (_MM_FROUND_TO_POS_INF |_MM_FROUND_NO_EXC) // round up, and suppress
+// exceptions
+// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress
+// exceptions _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see
+// _MM_SET_ROUNDING_MODE
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_round_ss
+FORCE_INLINE __m128 _mm_round_ss(__m128 a, __m128 b, int rounding)
+{
+ return _mm_move_ss(a, _mm_round_ps(b, rounding));
+}
+
+// Load 128-bits of integer data from memory into dst using a non-temporal
+// memory hint. mem_addr must be aligned on a 16-byte boundary or a
+// general-protection exception may be generated.
+//
+// dst[127:0] := MEM[mem_addr+127:mem_addr]
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_stream_load_si128
+FORCE_INLINE __m128i _mm_stream_load_si128(__m128i *p)
+{
+#if __has_builtin(__builtin_nontemporal_store)
+ return __builtin_nontemporal_load(p);
+#else
+ return vreinterpretq_m128i_s64(vld1q_s64((int64_t *) p));
+#endif
+}
+
+// Compute the bitwise NOT of a and then AND with a 128-bit vector containing
+// all 1's, and return 1 if the result is zero, otherwise return 0.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_test_all_ones
+FORCE_INLINE int _mm_test_all_ones(__m128i a)
+{
+ return (uint64_t)(vgetq_lane_s64(a, 0) & vgetq_lane_s64(a, 1)) ==
+ ~(uint64_t) 0;
+}
+
+// Compute the bitwise AND of 128 bits (representing integer data) in a and
+// mask, and return 1 if the result is zero, otherwise return 0.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_test_all_zeros
+FORCE_INLINE int _mm_test_all_zeros(__m128i a, __m128i mask)
+{
+ int64x2_t a_and_mask =
+ vandq_s64(vreinterpretq_s64_m128i(a), vreinterpretq_s64_m128i(mask));
+ return !(vgetq_lane_s64(a_and_mask, 0) | vgetq_lane_s64(a_and_mask, 1));
+}
+
+// Compute the bitwise AND of 128 bits (representing integer data) in a and
+// mask, and set ZF to 1 if the result is zero, otherwise set ZF to 0. Compute
+// the bitwise NOT of a and then AND with mask, and set CF to 1 if the result is
+// zero, otherwise set CF to 0. Return 1 if both the ZF and CF values are zero,
+// otherwise return 0.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=mm_test_mix_ones_zero
+FORCE_INLINE int _mm_test_mix_ones_zeros(__m128i a, __m128i mask)
+{
+ uint64x2_t zf =
+ vandq_u64(vreinterpretq_u64_m128i(mask), vreinterpretq_u64_m128i(a));
+ uint64x2_t cf =
+ vbicq_u64(vreinterpretq_u64_m128i(mask), vreinterpretq_u64_m128i(a));
+ uint64x2_t result = vandq_u64(zf, cf);
+ return !(vgetq_lane_u64(result, 0) | vgetq_lane_u64(result, 1));
+}
+
// Compute the bitwise AND of 128 bits (representing integer data) in a and b,
// and set ZF to 1 if the result is zero, otherwise set ZF to 0. Compute the
// bitwise NOT of a and then AND with b, and set CF to 1 if the result is zero,
@@ -6312,6 +8278,14 @@ FORCE_INLINE int _mm_testc_si128(__m128i a, __m128i b)
// Compute the bitwise AND of 128 bits (representing integer data) in a and b,
// and set ZF to 1 if the result is zero, otherwise set ZF to 0. Compute the
// bitwise NOT of a and then AND with b, and set CF to 1 if the result is zero,
+// otherwise set CF to 0. Return 1 if both the ZF and CF values are zero,
+// otherwise return 0.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_testnzc_si128
+#define _mm_testnzc_si128(a, b) _mm_test_mix_ones_zeros(a, b)
+
+// Compute the bitwise AND of 128 bits (representing integer data) in a and b,
+// and set ZF to 1 if the result is zero, otherwise set ZF to 0. Compute the
+// bitwise NOT of a and then AND with b, and set CF to 1 if the result is zero,
// otherwise set CF to 0. Return the ZF value.
// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_testz_si128
FORCE_INLINE int _mm_testz_si128(__m128i a, __m128i b)
@@ -6321,299 +8295,93 @@ FORCE_INLINE int _mm_testz_si128(__m128i a, __m128i b)
return !(vgetq_lane_s64(s64, 0) | vgetq_lane_s64(s64, 1));
}
-// Extracts the selected signed or unsigned 8-bit integer from a and zero
-// extends.
-// FORCE_INLINE int _mm_extract_epi8(__m128i a, __constrange(0,16) int imm)
-#define _mm_extract_epi8(a, imm) vgetq_lane_u8(vreinterpretq_u8_m128i(a), (imm))
-
-// Inserts the least significant 8 bits of b into the selected 8-bit integer
-// of a.
-// FORCE_INLINE __m128i _mm_insert_epi8(__m128i a, int b,
-// __constrange(0,16) int imm)
-#define _mm_insert_epi8(a, b, imm) \
- __extension__({ \
- vreinterpretq_m128i_s8( \
- vsetq_lane_s8((b), vreinterpretq_s8_m128i(a), (imm))); \
- })
-
-// Extracts the selected signed or unsigned 16-bit integer from a and zero
-// extends.
-// https://msdn.microsoft.com/en-us/library/6dceta0c(v=vs.100).aspx
-// FORCE_INLINE int _mm_extract_epi16(__m128i a, __constrange(0,8) int imm)
-#define _mm_extract_epi16(a, imm) \
- vgetq_lane_u16(vreinterpretq_u16_m128i(a), (imm))
-
-// Inserts the least significant 16 bits of b into the selected 16-bit integer
-// of a.
-// https://msdn.microsoft.com/en-us/library/kaze8hz1%28v=vs.100%29.aspx
-// FORCE_INLINE __m128i _mm_insert_epi16(__m128i a, int b,
-// __constrange(0,8) int imm)
-#define _mm_insert_epi16(a, b, imm) \
- __extension__({ \
- vreinterpretq_m128i_s16( \
- vsetq_lane_s16((b), vreinterpretq_s16_m128i(a), (imm))); \
- })
-
-// Copy a to dst, and insert the 16-bit integer i into dst at the location
-// specified by imm8.
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_insert_pi16
-#define _mm_insert_pi16(a, b, imm) \
- __extension__({ \
- vreinterpret_m64_s16( \
- vset_lane_s16((b), vreinterpret_s16_m64(a), (imm))); \
- })
-
-// Extracts the selected signed or unsigned 32-bit integer from a and zero
-// extends.
-// FORCE_INLINE int _mm_extract_epi32(__m128i a, __constrange(0,4) int imm)
-#define _mm_extract_epi32(a, imm) \
- vgetq_lane_s32(vreinterpretq_s32_m128i(a), (imm))
-
-// Extracts the selected single-precision (32-bit) floating-point from a.
-// FORCE_INLINE int _mm_extract_ps(__m128 a, __constrange(0,4) int imm)
-#define _mm_extract_ps(a, imm) vgetq_lane_s32(vreinterpretq_s32_m128(a), (imm))
-
-// Inserts the least significant 32 bits of b into the selected 32-bit integer
-// of a.
-// FORCE_INLINE __m128i _mm_insert_epi32(__m128i a, int b,
-// __constrange(0,4) int imm)
-#define _mm_insert_epi32(a, b, imm) \
- __extension__({ \
- vreinterpretq_m128i_s32( \
- vsetq_lane_s32((b), vreinterpretq_s32_m128i(a), (imm))); \
- })
-
-// Extracts the selected signed or unsigned 64-bit integer from a and zero
-// extends.
-// FORCE_INLINE __int64 _mm_extract_epi64(__m128i a, __constrange(0,2) int imm)
-#define _mm_extract_epi64(a, imm) \
- vgetq_lane_s64(vreinterpretq_s64_m128i(a), (imm))
-
-// Inserts the least significant 64 bits of b into the selected 64-bit integer
-// of a.
-// FORCE_INLINE __m128i _mm_insert_epi64(__m128i a, __int64 b,
-// __constrange(0,2) int imm)
-#define _mm_insert_epi64(a, b, imm) \
- __extension__({ \
- vreinterpretq_m128i_s64( \
- vsetq_lane_s64((b), vreinterpretq_s64_m128i(a), (imm))); \
- })
+/* SSE4.2 */
-// Count the number of bits set to 1 in unsigned 32-bit integer a, and
-// return that count in dst.
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_popcnt_u32
-FORCE_INLINE int _mm_popcnt_u32(unsigned int a)
+// Compares the 2 signed 64-bit integers in a and the 2 signed 64-bit integers
+// in b for greater than.
+FORCE_INLINE __m128i _mm_cmpgt_epi64(__m128i a, __m128i b)
{
#if defined(__aarch64__)
-#if __has_builtin(__builtin_popcount)
- return __builtin_popcount(a);
+ return vreinterpretq_m128i_u64(
+ vcgtq_s64(vreinterpretq_s64_m128i(a), vreinterpretq_s64_m128i(b)));
#else
- return (int) vaddlv_u8(vcnt_u8(vcreate_u8((uint64_t) a)));
-#endif
-#else
- uint32_t count = 0;
- uint8x8_t input_val, count8x8_val;
- uint16x4_t count16x4_val;
- uint32x2_t count32x2_val;
-
- input_val = vld1_u8((uint8_t *) &a);
- count8x8_val = vcnt_u8(input_val);
- count16x4_val = vpaddl_u8(count8x8_val);
- count32x2_val = vpaddl_u16(count16x4_val);
-
- vst1_u32(&count, count32x2_val);
- return count;
+ return vreinterpretq_m128i_s64(vshrq_n_s64(
+ vqsubq_s64(vreinterpretq_s64_m128i(b), vreinterpretq_s64_m128i(a)),
+ 63));
#endif
}
-// Count the number of bits set to 1 in unsigned 64-bit integer a, and
-// return that count in dst.
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_popcnt_u64
-FORCE_INLINE int64_t _mm_popcnt_u64(uint64_t a)
+// Starting with the initial value in crc, accumulates a CRC32 value for
+// unsigned 16-bit integer v.
+// https://msdn.microsoft.com/en-us/library/bb531411(v=vs.100)
+FORCE_INLINE uint32_t _mm_crc32_u16(uint32_t crc, uint16_t v)
{
-#if defined(__aarch64__)
-#if __has_builtin(__builtin_popcountll)
- return __builtin_popcountll(a);
-#else
- return (int64_t) vaddlv_u8(vcnt_u8(vcreate_u8(a)));
-#endif
+#if defined(__aarch64__) && defined(__ARM_FEATURE_CRC32)
+ __asm__ __volatile__("crc32ch %w[c], %w[c], %w[v]\n\t"
+ : [c] "+r"(crc)
+ : [v] "r"(v));
#else
- uint64_t count = 0;
- uint8x8_t input_val, count8x8_val;
- uint16x4_t count16x4_val;
- uint32x2_t count32x2_val;
- uint64x1_t count64x1_val;
-
- input_val = vld1_u8((uint8_t *) &a);
- count8x8_val = vcnt_u8(input_val);
- count16x4_val = vpaddl_u8(count8x8_val);
- count32x2_val = vpaddl_u16(count16x4_val);
- count64x1_val = vpaddl_u32(count32x2_val);
- vst1_u64(&count, count64x1_val);
- return count;
+ crc = _mm_crc32_u8(crc, v & 0xff);
+ crc = _mm_crc32_u8(crc, (v >> 8) & 0xff);
#endif
+ return crc;
}
-// Macro: Transpose the 4x4 matrix formed by the 4 rows of single-precision
-// (32-bit) floating-point elements in row0, row1, row2, and row3, and store the
-// transposed matrix in these vectors (row0 now contains column 0, etc.).
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=MM_TRANSPOSE4_PS
-#define _MM_TRANSPOSE4_PS(row0, row1, row2, row3) \
- do { \
- float32x4x2_t ROW01 = vtrnq_f32(row0, row1); \
- float32x4x2_t ROW23 = vtrnq_f32(row2, row3); \
- row0 = vcombine_f32(vget_low_f32(ROW01.val[0]), \
- vget_low_f32(ROW23.val[0])); \
- row1 = vcombine_f32(vget_low_f32(ROW01.val[1]), \
- vget_low_f32(ROW23.val[1])); \
- row2 = vcombine_f32(vget_high_f32(ROW01.val[0]), \
- vget_high_f32(ROW23.val[0])); \
- row3 = vcombine_f32(vget_high_f32(ROW01.val[1]), \
- vget_high_f32(ROW23.val[1])); \
- } while (0)
-
-/* Crypto Extensions */
-
-#if defined(__ARM_FEATURE_CRYPTO)
-// Wraps vmull_p64
-FORCE_INLINE uint64x2_t _sse2neon_vmull_p64(uint64x1_t _a, uint64x1_t _b)
-{
- poly64_t a = vget_lane_p64(vreinterpret_p64_u64(_a), 0);
- poly64_t b = vget_lane_p64(vreinterpret_p64_u64(_b), 0);
- return vreinterpretq_u64_p128(vmull_p64(a, b));
-}
-#else // ARMv7 polyfill
-// ARMv7/some A64 lacks vmull_p64, but it has vmull_p8.
-//
-// vmull_p8 calculates 8 8-bit->16-bit polynomial multiplies, but we need a
-// 64-bit->128-bit polynomial multiply.
-//
-// It needs some work and is somewhat slow, but it is still faster than all
-// known scalar methods.
-//
-// Algorithm adapted to C from
-// https://www.workofard.com/2017/07/ghash-for-low-end-cores/, which is adapted
-// from "Fast Software Polynomial Multiplication on ARM Processors Using the
-// NEON Engine" by Danilo Camara, Conrado Gouvea, Julio Lopez and Ricardo Dahab
-// (https://hal.inria.fr/hal-01506572)
-static uint64x2_t _sse2neon_vmull_p64(uint64x1_t _a, uint64x1_t _b)
+// Starting with the initial value in crc, accumulates a CRC32 value for
+// unsigned 32-bit integer v.
+// https://msdn.microsoft.com/en-us/library/bb531394(v=vs.100)
+FORCE_INLINE uint32_t _mm_crc32_u32(uint32_t crc, uint32_t v)
{
- poly8x8_t a = vreinterpret_p8_u64(_a);
- poly8x8_t b = vreinterpret_p8_u64(_b);
-
- // Masks
- uint8x16_t k48_32 = vcombine_u8(vcreate_u8(0x0000ffffffffffff),
- vcreate_u8(0x00000000ffffffff));
- uint8x16_t k16_00 = vcombine_u8(vcreate_u8(0x000000000000ffff),
- vcreate_u8(0x0000000000000000));
-
- // Do the multiplies, rotating with vext to get all combinations
- uint8x16_t d = vreinterpretq_u8_p16(vmull_p8(a, b)); // D = A0 * B0
- uint8x16_t e =
- vreinterpretq_u8_p16(vmull_p8(a, vext_p8(b, b, 1))); // E = A0 * B1
- uint8x16_t f =
- vreinterpretq_u8_p16(vmull_p8(vext_p8(a, a, 1), b)); // F = A1 * B0
- uint8x16_t g =
- vreinterpretq_u8_p16(vmull_p8(a, vext_p8(b, b, 2))); // G = A0 * B2
- uint8x16_t h =
- vreinterpretq_u8_p16(vmull_p8(vext_p8(a, a, 2), b)); // H = A2 * B0
- uint8x16_t i =
- vreinterpretq_u8_p16(vmull_p8(a, vext_p8(b, b, 3))); // I = A0 * B3
- uint8x16_t j =
- vreinterpretq_u8_p16(vmull_p8(vext_p8(a, a, 3), b)); // J = A3 * B0
- uint8x16_t k =
- vreinterpretq_u8_p16(vmull_p8(a, vext_p8(b, b, 4))); // L = A0 * B4
-
- // Add cross products
- uint8x16_t l = veorq_u8(e, f); // L = E + F
- uint8x16_t m = veorq_u8(g, h); // M = G + H
- uint8x16_t n = veorq_u8(i, j); // N = I + J
-
- // Interleave. Using vzip1 and vzip2 prevents Clang from emitting TBL
- // instructions.
-#if defined(__aarch64__)
- uint8x16_t lm_p0 = vreinterpretq_u8_u64(
- vzip1q_u64(vreinterpretq_u64_u8(l), vreinterpretq_u64_u8(m)));
- uint8x16_t lm_p1 = vreinterpretq_u8_u64(
- vzip2q_u64(vreinterpretq_u64_u8(l), vreinterpretq_u64_u8(m)));
- uint8x16_t nk_p0 = vreinterpretq_u8_u64(
- vzip1q_u64(vreinterpretq_u64_u8(n), vreinterpretq_u64_u8(k)));
- uint8x16_t nk_p1 = vreinterpretq_u8_u64(
- vzip2q_u64(vreinterpretq_u64_u8(n), vreinterpretq_u64_u8(k)));
+#if defined(__aarch64__) && defined(__ARM_FEATURE_CRC32)
+ __asm__ __volatile__("crc32cw %w[c], %w[c], %w[v]\n\t"
+ : [c] "+r"(crc)
+ : [v] "r"(v));
#else
- uint8x16_t lm_p0 = vcombine_u8(vget_low_u8(l), vget_low_u8(m));
- uint8x16_t lm_p1 = vcombine_u8(vget_high_u8(l), vget_high_u8(m));
- uint8x16_t nk_p0 = vcombine_u8(vget_low_u8(n), vget_low_u8(k));
- uint8x16_t nk_p1 = vcombine_u8(vget_high_u8(n), vget_high_u8(k));
+ crc = _mm_crc32_u16(crc, v & 0xffff);
+ crc = _mm_crc32_u16(crc, (v >> 16) & 0xffff);
#endif
- // t0 = (L) (P0 + P1) << 8
- // t1 = (M) (P2 + P3) << 16
- uint8x16_t t0t1_tmp = veorq_u8(lm_p0, lm_p1);
- uint8x16_t t0t1_h = vandq_u8(lm_p1, k48_32);
- uint8x16_t t0t1_l = veorq_u8(t0t1_tmp, t0t1_h);
-
- // t2 = (N) (P4 + P5) << 24
- // t3 = (K) (P6 + P7) << 32
- uint8x16_t t2t3_tmp = veorq_u8(nk_p0, nk_p1);
- uint8x16_t t2t3_h = vandq_u8(nk_p1, k16_00);
- uint8x16_t t2t3_l = veorq_u8(t2t3_tmp, t2t3_h);
+ return crc;
+}
- // De-interleave
-#if defined(__aarch64__)
- uint8x16_t t0 = vreinterpretq_u8_u64(
- vuzp1q_u64(vreinterpretq_u64_u8(t0t1_l), vreinterpretq_u64_u8(t0t1_h)));
- uint8x16_t t1 = vreinterpretq_u8_u64(
- vuzp2q_u64(vreinterpretq_u64_u8(t0t1_l), vreinterpretq_u64_u8(t0t1_h)));
- uint8x16_t t2 = vreinterpretq_u8_u64(
- vuzp1q_u64(vreinterpretq_u64_u8(t2t3_l), vreinterpretq_u64_u8(t2t3_h)));
- uint8x16_t t3 = vreinterpretq_u8_u64(
- vuzp2q_u64(vreinterpretq_u64_u8(t2t3_l), vreinterpretq_u64_u8(t2t3_h)));
+// Starting with the initial value in crc, accumulates a CRC32 value for
+// unsigned 64-bit integer v.
+// https://msdn.microsoft.com/en-us/library/bb514033(v=vs.100)
+FORCE_INLINE uint64_t _mm_crc32_u64(uint64_t crc, uint64_t v)
+{
+#if defined(__aarch64__) && defined(__ARM_FEATURE_CRC32)
+ __asm__ __volatile__("crc32cx %w[c], %w[c], %x[v]\n\t"
+ : [c] "+r"(crc)
+ : [v] "r"(v));
#else
- uint8x16_t t1 = vcombine_u8(vget_high_u8(t0t1_l), vget_high_u8(t0t1_h));
- uint8x16_t t0 = vcombine_u8(vget_low_u8(t0t1_l), vget_low_u8(t0t1_h));
- uint8x16_t t3 = vcombine_u8(vget_high_u8(t2t3_l), vget_high_u8(t2t3_h));
- uint8x16_t t2 = vcombine_u8(vget_low_u8(t2t3_l), vget_low_u8(t2t3_h));
+ crc = _mm_crc32_u32((uint32_t)(crc), v & 0xffffffff);
+ crc = _mm_crc32_u32((uint32_t)(crc), (v >> 32) & 0xffffffff);
#endif
- // Shift the cross products
- uint8x16_t t0_shift = vextq_u8(t0, t0, 15); // t0 << 8
- uint8x16_t t1_shift = vextq_u8(t1, t1, 14); // t1 << 16
- uint8x16_t t2_shift = vextq_u8(t2, t2, 13); // t2 << 24
- uint8x16_t t3_shift = vextq_u8(t3, t3, 12); // t3 << 32
-
- // Accumulate the products
- uint8x16_t cross1 = veorq_u8(t0_shift, t1_shift);
- uint8x16_t cross2 = veorq_u8(t2_shift, t3_shift);
- uint8x16_t mix = veorq_u8(d, cross1);
- uint8x16_t r = veorq_u8(mix, cross2);
- return vreinterpretq_u64_u8(r);
+ return crc;
}
-#endif // ARMv7 polyfill
-// Perform a carry-less multiplication of two 64-bit integers, selected from a
-// and b according to imm8, and store the results in dst.
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_clmulepi64_si128
-FORCE_INLINE __m128i _mm_clmulepi64_si128(__m128i _a, __m128i _b, const int imm)
+// Starting with the initial value in crc, accumulates a CRC32 value for
+// unsigned 8-bit integer v.
+// https://msdn.microsoft.com/en-us/library/bb514036(v=vs.100)
+FORCE_INLINE uint32_t _mm_crc32_u8(uint32_t crc, uint8_t v)
{
- uint64x2_t a = vreinterpretq_u64_m128i(_a);
- uint64x2_t b = vreinterpretq_u64_m128i(_b);
- switch (imm & 0x11) {
- case 0x00:
- return vreinterpretq_m128i_u64(
- _sse2neon_vmull_p64(vget_low_u64(a), vget_low_u64(b)));
- case 0x01:
- return vreinterpretq_m128i_u64(
- _sse2neon_vmull_p64(vget_high_u64(a), vget_low_u64(b)));
- case 0x10:
- return vreinterpretq_m128i_u64(
- _sse2neon_vmull_p64(vget_low_u64(a), vget_high_u64(b)));
- case 0x11:
- return vreinterpretq_m128i_u64(
- _sse2neon_vmull_p64(vget_high_u64(a), vget_high_u64(b)));
- default:
- abort();
+#if defined(__aarch64__) && defined(__ARM_FEATURE_CRC32)
+ __asm__ __volatile__("crc32cb %w[c], %w[c], %w[v]\n\t"
+ : [c] "+r"(crc)
+ : [v] "r"(v));
+#else
+ crc ^= v;
+ for (int bit = 0; bit < 8; bit++) {
+ if (crc & 1)
+ crc = (crc >> 1) ^ UINT32_C(0x82f63b78);
+ else
+ crc = (crc >> 1);
}
+#endif
+ return crc;
}
+/* AES */
+
#if !defined(__ARM_FEATURE_CRYPTO)
/* clang-format off */
#define SSE2NEON_AES_DATA(w) \
@@ -6752,22 +8520,22 @@ FORCE_INLINE __m128i _mm_aesenclast_si128(__m128i a, __m128i RoundKey)
{
/* FIXME: optimized for NEON */
uint8_t v[4][4] = {
- [0] = {SSE2NEON_sbox[vreinterpretq_nth_u8_m128i(a, 0)],
- SSE2NEON_sbox[vreinterpretq_nth_u8_m128i(a, 5)],
- SSE2NEON_sbox[vreinterpretq_nth_u8_m128i(a, 10)],
- SSE2NEON_sbox[vreinterpretq_nth_u8_m128i(a, 15)]},
- [1] = {SSE2NEON_sbox[vreinterpretq_nth_u8_m128i(a, 4)],
- SSE2NEON_sbox[vreinterpretq_nth_u8_m128i(a, 9)],
- SSE2NEON_sbox[vreinterpretq_nth_u8_m128i(a, 14)],
- SSE2NEON_sbox[vreinterpretq_nth_u8_m128i(a, 3)]},
- [2] = {SSE2NEON_sbox[vreinterpretq_nth_u8_m128i(a, 8)],
- SSE2NEON_sbox[vreinterpretq_nth_u8_m128i(a, 13)],
- SSE2NEON_sbox[vreinterpretq_nth_u8_m128i(a, 2)],
- SSE2NEON_sbox[vreinterpretq_nth_u8_m128i(a, 7)]},
- [3] = {SSE2NEON_sbox[vreinterpretq_nth_u8_m128i(a, 12)],
- SSE2NEON_sbox[vreinterpretq_nth_u8_m128i(a, 1)],
- SSE2NEON_sbox[vreinterpretq_nth_u8_m128i(a, 6)],
- SSE2NEON_sbox[vreinterpretq_nth_u8_m128i(a, 11)]},
+ {SSE2NEON_sbox[vreinterpretq_nth_u8_m128i(a, 0)],
+ SSE2NEON_sbox[vreinterpretq_nth_u8_m128i(a, 5)],
+ SSE2NEON_sbox[vreinterpretq_nth_u8_m128i(a, 10)],
+ SSE2NEON_sbox[vreinterpretq_nth_u8_m128i(a, 15)]},
+ {SSE2NEON_sbox[vreinterpretq_nth_u8_m128i(a, 4)],
+ SSE2NEON_sbox[vreinterpretq_nth_u8_m128i(a, 9)],
+ SSE2NEON_sbox[vreinterpretq_nth_u8_m128i(a, 14)],
+ SSE2NEON_sbox[vreinterpretq_nth_u8_m128i(a, 3)]},
+ {SSE2NEON_sbox[vreinterpretq_nth_u8_m128i(a, 8)],
+ SSE2NEON_sbox[vreinterpretq_nth_u8_m128i(a, 13)],
+ SSE2NEON_sbox[vreinterpretq_nth_u8_m128i(a, 2)],
+ SSE2NEON_sbox[vreinterpretq_nth_u8_m128i(a, 7)]},
+ {SSE2NEON_sbox[vreinterpretq_nth_u8_m128i(a, 12)],
+ SSE2NEON_sbox[vreinterpretq_nth_u8_m128i(a, 1)],
+ SSE2NEON_sbox[vreinterpretq_nth_u8_m128i(a, 6)],
+ SSE2NEON_sbox[vreinterpretq_nth_u8_m128i(a, 11)]},
};
for (int i = 0; i < 16; i++)
vreinterpretq_nth_u8_m128i(a, i) =
@@ -6833,155 +8601,134 @@ FORCE_INLINE __m128i _mm_aeskeygenassist_si128(__m128i a, const int rcon)
}
#endif
-/* Streaming Extensions */
+/* Others */
-// Guarantees that every preceding store is globally visible before any
-// subsequent store.
-// https://msdn.microsoft.com/en-us/library/5h2w73d1%28v=vs.90%29.aspx
-FORCE_INLINE void _mm_sfence(void)
+// Perform a carry-less multiplication of two 64-bit integers, selected from a
+// and b according to imm8, and store the results in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_clmulepi64_si128
+FORCE_INLINE __m128i _mm_clmulepi64_si128(__m128i _a, __m128i _b, const int imm)
{
- __sync_synchronize();
+ uint64x2_t a = vreinterpretq_u64_m128i(_a);
+ uint64x2_t b = vreinterpretq_u64_m128i(_b);
+ switch (imm & 0x11) {
+ case 0x00:
+ return vreinterpretq_m128i_u64(
+ _sse2neon_vmull_p64(vget_low_u64(a), vget_low_u64(b)));
+ case 0x01:
+ return vreinterpretq_m128i_u64(
+ _sse2neon_vmull_p64(vget_high_u64(a), vget_low_u64(b)));
+ case 0x10:
+ return vreinterpretq_m128i_u64(
+ _sse2neon_vmull_p64(vget_low_u64(a), vget_high_u64(b)));
+ case 0x11:
+ return vreinterpretq_m128i_u64(
+ _sse2neon_vmull_p64(vget_high_u64(a), vget_high_u64(b)));
+ default:
+ abort();
+ }
}
-// Store 128-bits (composed of 4 packed single-precision (32-bit) floating-
-// point elements) from a into memory using a non-temporal memory hint.
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_stream_ps
-FORCE_INLINE void _mm_stream_ps(float *p, __m128 a)
+FORCE_INLINE unsigned int _sse2neon_mm_get_denormals_zero_mode()
{
-#if __has_builtin(__builtin_nontemporal_store)
- __builtin_nontemporal_store(a, (float32x4_t *) p);
+ union {
+ fpcr_bitfield field;
+#if defined(__aarch64__)
+ uint64_t value;
#else
- vst1q_f32(p, vreinterpretq_f32_m128(a));
+ uint32_t value;
#endif
-}
+ } r;
-// Stores the data in a to the address p without polluting the caches. If the
-// cache line containing address p is already in the cache, the cache will be
-// updated.
-// https://msdn.microsoft.com/en-us/library/ba08y07y%28v=vs.90%29.aspx
-FORCE_INLINE void _mm_stream_si128(__m128i *p, __m128i a)
-{
-#if __has_builtin(__builtin_nontemporal_store)
- __builtin_nontemporal_store(a, p);
+#if defined(__aarch64__)
+ asm volatile("mrs %0, FPCR" : "=r"(r.value)); /* read */
#else
- vst1q_s64((int64_t *) p, vreinterpretq_s64_m128i(a));
+ asm volatile("vmrs %0, FPSCR" : "=r"(r.value)); /* read */
#endif
+
+ return r.field.bit24 ? _MM_DENORMALS_ZERO_ON : _MM_DENORMALS_ZERO_OFF;
}
-// Load 128-bits of integer data from memory into dst using a non-temporal
-// memory hint. mem_addr must be aligned on a 16-byte boundary or a
-// general-protection exception may be generated.
-//
-// dst[127:0] := MEM[mem_addr+127:mem_addr]
-//
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_stream_load_si128
-FORCE_INLINE __m128i _mm_stream_load_si128(__m128i *p)
+// Count the number of bits set to 1 in unsigned 32-bit integer a, and
+// return that count in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_popcnt_u32
+FORCE_INLINE int _mm_popcnt_u32(unsigned int a)
{
-#if __has_builtin(__builtin_nontemporal_store)
- return __builtin_nontemporal_load(p);
+#if defined(__aarch64__)
+#if __has_builtin(__builtin_popcount)
+ return __builtin_popcount(a);
#else
- return vreinterpretq_m128i_s64(vld1q_s64((int64_t *) p));
+ return (int) vaddlv_u8(vcnt_u8(vcreate_u8((uint64_t) a)));
#endif
-}
-
-// Cache line containing p is flushed and invalidated from all caches in the
-// coherency domain. :
-// https://msdn.microsoft.com/en-us/library/ba08y07y(v=vs.100).aspx
-FORCE_INLINE void _mm_clflush(void const *p)
-{
- (void) p;
- // no corollary for Neon?
-}
+#else
+ uint32_t count = 0;
+ uint8x8_t input_val, count8x8_val;
+ uint16x4_t count16x4_val;
+ uint32x2_t count32x2_val;
-// Allocate aligned blocks of memory.
-// https://software.intel.com/en-us/
-// cpp-compiler-developer-guide-and-reference-allocating-and-freeing-aligned-memory-blocks
-FORCE_INLINE void *_mm_malloc(size_t size, size_t align)
-{
- void *ptr;
- if (align == 1)
- return malloc(size);
- if (align == 2 || (sizeof(void *) == 8 && align == 4))
- align = sizeof(void *);
- if (!posix_memalign(&ptr, align, size))
- return ptr;
- return NULL;
-}
+ input_val = vld1_u8((uint8_t *) &a);
+ count8x8_val = vcnt_u8(input_val);
+ count16x4_val = vpaddl_u8(count8x8_val);
+ count32x2_val = vpaddl_u16(count16x4_val);
-// Free aligned memory that was allocated with _mm_malloc.
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_free
-FORCE_INLINE void _mm_free(void *addr)
-{
- free(addr);
+ vst1_u32(&count, count32x2_val);
+ return count;
+#endif
}
-// Starting with the initial value in crc, accumulates a CRC32 value for
-// unsigned 8-bit integer v.
-// https://msdn.microsoft.com/en-us/library/bb514036(v=vs.100)
-FORCE_INLINE uint32_t _mm_crc32_u8(uint32_t crc, uint8_t v)
+// Count the number of bits set to 1 in unsigned 64-bit integer a, and
+// return that count in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_popcnt_u64
+FORCE_INLINE int64_t _mm_popcnt_u64(uint64_t a)
{
-#if defined(__aarch64__) && defined(__ARM_FEATURE_CRC32)
- __asm__ __volatile__("crc32cb %w[c], %w[c], %w[v]\n\t"
- : [c] "+r"(crc)
- : [v] "r"(v));
+#if defined(__aarch64__)
+#if __has_builtin(__builtin_popcountll)
+ return __builtin_popcountll(a);
#else
- crc ^= v;
- for (int bit = 0; bit < 8; bit++) {
- if (crc & 1)
- crc = (crc >> 1) ^ UINT32_C(0x82f63b78);
- else
- crc = (crc >> 1);
- }
+ return (int64_t) vaddlv_u8(vcnt_u8(vcreate_u8(a)));
+#endif
+#else
+ uint64_t count = 0;
+ uint8x8_t input_val, count8x8_val;
+ uint16x4_t count16x4_val;
+ uint32x2_t count32x2_val;
+ uint64x1_t count64x1_val;
+
+ input_val = vld1_u8((uint8_t *) &a);
+ count8x8_val = vcnt_u8(input_val);
+ count16x4_val = vpaddl_u8(count8x8_val);
+ count32x2_val = vpaddl_u16(count16x4_val);
+ count64x1_val = vpaddl_u32(count32x2_val);
+ vst1_u64(&count, count64x1_val);
+ return count;
#endif
- return crc;
}
-// Starting with the initial value in crc, accumulates a CRC32 value for
-// unsigned 16-bit integer v.
-// https://msdn.microsoft.com/en-us/library/bb531411(v=vs.100)
-FORCE_INLINE uint32_t _mm_crc32_u16(uint32_t crc, uint16_t v)
+FORCE_INLINE void _sse2neon_mm_set_denormals_zero_mode(unsigned int flag)
{
-#if defined(__aarch64__) && defined(__ARM_FEATURE_CRC32)
- __asm__ __volatile__("crc32ch %w[c], %w[c], %w[v]\n\t"
- : [c] "+r"(crc)
- : [v] "r"(v));
+ // AArch32 Advanced SIMD arithmetic always uses the Flush-to-zero setting,
+ // regardless of the value of the FZ bit.
+ union {
+ fpcr_bitfield field;
+#if defined(__aarch64__)
+ uint64_t value;
#else
- crc = _mm_crc32_u8(crc, v & 0xff);
- crc = _mm_crc32_u8(crc, (v >> 8) & 0xff);
+ uint32_t value;
#endif
- return crc;
-}
+ } r;
-// Starting with the initial value in crc, accumulates a CRC32 value for
-// unsigned 32-bit integer v.
-// https://msdn.microsoft.com/en-us/library/bb531394(v=vs.100)
-FORCE_INLINE uint32_t _mm_crc32_u32(uint32_t crc, uint32_t v)
-{
-#if defined(__aarch64__) && defined(__ARM_FEATURE_CRC32)
- __asm__ __volatile__("crc32cw %w[c], %w[c], %w[v]\n\t"
- : [c] "+r"(crc)
- : [v] "r"(v));
+#if defined(__aarch64__)
+ asm volatile("mrs %0, FPCR" : "=r"(r.value)); /* read */
#else
- crc = _mm_crc32_u16(crc, v & 0xffff);
- crc = _mm_crc32_u16(crc, (v >> 16) & 0xffff);
+ asm volatile("vmrs %0, FPSCR" : "=r"(r.value)); /* read */
#endif
- return crc;
-}
-// Starting with the initial value in crc, accumulates a CRC32 value for
-// unsigned 64-bit integer v.
-// https://msdn.microsoft.com/en-us/library/bb514033(v=vs.100)
-FORCE_INLINE uint64_t _mm_crc32_u64(uint64_t crc, uint64_t v)
-{
-#if defined(__aarch64__) && defined(__ARM_FEATURE_CRC32)
- __asm__ __volatile__("crc32cx %w[c], %w[c], %x[v]\n\t"
- : [c] "+r"(crc)
- : [v] "r"(v));
+ r.field.bit24 = (flag & _MM_DENORMALS_ZERO_MASK) == _MM_DENORMALS_ZERO_ON;
+
+#if defined(__aarch64__)
+ asm volatile("msr FPCR, %0" ::"r"(r)); /* write */
#else
- crc = _mm_crc32_u32((uint32_t)(crc), v & 0xffffffff);
- crc = _mm_crc32_u32((uint32_t)(crc), (v >> 32) & 0xffffffff);
+ asm volatile("vmsr FPSCR, %0" ::"r"(r)); /* write */
#endif
- return crc;
}
#if defined(__GNUC__) || defined(__clang__)
@@ -6993,4 +8740,4 @@ FORCE_INLINE uint64_t _mm_crc32_u64(uint64_t crc, uint64_t v)
#pragma GCC pop_options
#endif
-#endif
+#endif \ No newline at end of file
diff --git a/thirdparty/embree/common/simd/simd.h b/thirdparty/embree/common/simd/simd.h
index 195506b530..34e37b08b1 100644
--- a/thirdparty/embree/common/simd/simd.h
+++ b/thirdparty/embree/common/simd/simd.h
@@ -6,7 +6,7 @@
#include "../math/math.h"
/* include SSE wrapper classes */
-#if defined(__SSE__)
+#if defined(__SSE__) || defined(__ARM_NEON)
# include "sse.h"
#endif
diff --git a/thirdparty/embree/common/simd/sse.h b/thirdparty/embree/common/simd/sse.h
index 1465fb4fb0..04d90533dd 100644
--- a/thirdparty/embree/common/simd/sse.h
+++ b/thirdparty/embree/common/simd/sse.h
@@ -11,7 +11,7 @@
namespace embree
{
-#if defined(__SSE4_1__)
+#if defined(__aarch64__) || defined(__SSE4_1__)
__forceinline __m128 blendv_ps(__m128 f, __m128 t, __m128 mask) {
return _mm_blendv_ps(f,t,mask);
}
diff --git a/thirdparty/embree/common/simd/vboold4_avx.h b/thirdparty/embree/common/simd/vboold4_avx.h
index 7db0d1c5c1..450bd7a4eb 100644
--- a/thirdparty/embree/common/simd/vboold4_avx.h
+++ b/thirdparty/embree/common/simd/vboold4_avx.h
@@ -62,7 +62,11 @@ namespace embree
////////////////////////////////////////////////////////////////////////////////
__forceinline vboold(FalseTy) : v(_mm256_setzero_pd()) {}
+#if !defined(__aarch64__)
__forceinline vboold(TrueTy) : v(_mm256_cmp_pd(_mm256_setzero_pd(), _mm256_setzero_pd(), _CMP_EQ_OQ)) {}
+#else
+ __forceinline vboold(TrueTy) : v(_mm256_cmpeq_pd(_mm256_setzero_pd(), _mm256_setzero_pd())) {}
+#endif
////////////////////////////////////////////////////////////////////////////////
/// Array Access
@@ -107,9 +111,10 @@ namespace embree
/// Movement/Shifting/Shuffling Functions
////////////////////////////////////////////////////////////////////////////////
+#if !defined(__aarch64__)
__forceinline vboold4 unpacklo(const vboold4& a, const vboold4& b) { return _mm256_unpacklo_pd(a, b); }
__forceinline vboold4 unpackhi(const vboold4& a, const vboold4& b) { return _mm256_unpackhi_pd(a, b); }
-
+#endif
#if defined(__AVX2__)
template<int i0, int i1, int i2, int i3>
diff --git a/thirdparty/embree/common/simd/vboolf16_avx512.h b/thirdparty/embree/common/simd/vboolf16_avx512.h
index 19841dcea8..86b718f025 100644
--- a/thirdparty/embree/common/simd/vboolf16_avx512.h
+++ b/thirdparty/embree/common/simd/vboolf16_avx512.h
@@ -116,7 +116,7 @@ namespace embree
__forceinline size_t popcnt (const vboolf16& a) { return popcnt(a.v); }
////////////////////////////////////////////////////////////////////////////////
- /// Convertion Operations
+ /// Conversion Operations
////////////////////////////////////////////////////////////////////////////////
__forceinline unsigned int toInt (const vboolf16& a) { return mm512_mask2int(a); }
diff --git a/thirdparty/embree/common/simd/vboolf4_sse2.h b/thirdparty/embree/common/simd/vboolf4_sse2.h
index fa84b1b6ee..9e0fdf5c6f 100644
--- a/thirdparty/embree/common/simd/vboolf4_sse2.h
+++ b/thirdparty/embree/common/simd/vboolf4_sse2.h
@@ -36,9 +36,11 @@ namespace embree
__forceinline vboolf(__m128 input) : v(input) {}
__forceinline operator const __m128&() const { return v; }
+ #if !defined(__EMSCRIPTEN__)
__forceinline operator const __m128i() const { return _mm_castps_si128(v); }
__forceinline operator const __m128d() const { return _mm_castps_pd(v); }
-
+ #endif
+
__forceinline vboolf(bool a)
: v(mm_lookupmask_ps[(size_t(a) << 3) | (size_t(a) << 2) | (size_t(a) << 1) | size_t(a)]) {}
__forceinline vboolf(bool a, bool b)
@@ -100,7 +102,7 @@ namespace embree
__forceinline vboolf4 operator ==(const vboolf4& a, const vboolf4& b) { return _mm_castsi128_ps(_mm_cmpeq_epi32(a, b)); }
__forceinline vboolf4 select(const vboolf4& m, const vboolf4& t, const vboolf4& f) {
-#if defined(__SSE4_1__)
+#if defined(__aarch64__) || defined(__SSE4_1__)
return _mm_blendv_ps(f, t, m);
#else
return _mm_or_ps(_mm_and_ps(m, t), _mm_andnot_ps(m, f));
@@ -114,6 +116,17 @@ namespace embree
__forceinline vboolf4 unpacklo(const vboolf4& a, const vboolf4& b) { return _mm_unpacklo_ps(a, b); }
__forceinline vboolf4 unpackhi(const vboolf4& a, const vboolf4& b) { return _mm_unpackhi_ps(a, b); }
+#if defined(__aarch64__)
+ template<int i0, int i1, int i2, int i3>
+ __forceinline vboolf4 shuffle(const vboolf4& v) {
+ return vreinterpretq_f32_u8(vqtbl1q_u8( vreinterpretq_u8_s32(v), _MN_SHUFFLE(i0, i1, i2, i3)));
+ }
+
+ template<int i0, int i1, int i2, int i3>
+ __forceinline vboolf4 shuffle(const vboolf4& a, const vboolf4& b) {
+ return vreinterpretq_f32_u8(vqtbl2q_u8( (uint8x16x2_t){(uint8x16_t)a.v, (uint8x16_t)b.v}, _MF_SHUFFLE(i0, i1, i2, i3)));
+ }
+#else
template<int i0, int i1, int i2, int i3>
__forceinline vboolf4 shuffle(const vboolf4& v) {
return _mm_castsi128_ps(_mm_shuffle_epi32(v, _MM_SHUFFLE(i3, i2, i1, i0)));
@@ -123,6 +136,7 @@ namespace embree
__forceinline vboolf4 shuffle(const vboolf4& a, const vboolf4& b) {
return _mm_shuffle_ps(a, b, _MM_SHUFFLE(i3, i2, i1, i0));
}
+#endif
template<int i0>
__forceinline vboolf4 shuffle(const vboolf4& v) {
@@ -135,7 +149,7 @@ namespace embree
template<> __forceinline vboolf4 shuffle<0, 1, 0, 1>(const vboolf4& v) { return _mm_castpd_ps(_mm_movedup_pd(v)); }
#endif
-#if defined(__SSE4_1__)
+#if defined(__SSE4_1__) && !defined(__aarch64__)
template<int dst, int src, int clr> __forceinline vboolf4 insert(const vboolf4& a, const vboolf4& b) { return _mm_insert_ps(a, b, (dst << 4) | (src << 6) | clr); }
template<int dst, int src> __forceinline vboolf4 insert(const vboolf4& a, const vboolf4& b) { return insert<dst, src, 0>(a, b); }
template<int dst> __forceinline vboolf4 insert(const vboolf4& a, const bool b) { return insert<dst, 0>(a, vboolf4(b)); }
@@ -157,7 +171,9 @@ namespace embree
__forceinline bool none(const vboolf4& valid, const vboolf4& b) { return none(valid & b); }
__forceinline size_t movemask(const vboolf4& a) { return _mm_movemask_ps(a); }
-#if defined(__SSE4_2__)
+#if defined(__aarch64__)
+ __forceinline size_t popcnt(const vboolf4& a) { return vaddvq_s32(vandq_u32(vreinterpretq_u32_f32(a.v),_mm_set1_epi32(1))); }
+#elif defined(__SSE4_2__)
__forceinline size_t popcnt(const vboolf4& a) { return popcnt((size_t)_mm_movemask_ps(a)); }
#else
__forceinline size_t popcnt(const vboolf4& a) { return bool(a[0])+bool(a[1])+bool(a[2])+bool(a[3]); }
diff --git a/thirdparty/embree/common/simd/vboolf8_avx.h b/thirdparty/embree/common/simd/vboolf8_avx.h
index ba77cc3c5e..18cede19c6 100644
--- a/thirdparty/embree/common/simd/vboolf8_avx.h
+++ b/thirdparty/embree/common/simd/vboolf8_avx.h
@@ -76,7 +76,7 @@ namespace embree
////////////////////////////////////////////////////////////////////////////////
__forceinline vboolf(FalseTy) : v(_mm256_setzero_ps()) {}
- __forceinline vboolf(TrueTy) : v(_mm256_cmp_ps(_mm256_setzero_ps(), _mm256_setzero_ps(), _CMP_EQ_OQ)) {}
+ __forceinline vboolf(TrueTy) : v(_mm256_castsi256_ps(_mm256_set1_epi32(0xFFFFFFFF))) {}
////////////////////////////////////////////////////////////////////////////////
/// Array Access
diff --git a/thirdparty/embree/common/simd/vdouble4_avx.h b/thirdparty/embree/common/simd/vdouble4_avx.h
index 55326de7dd..208bb7ac99 100644
--- a/thirdparty/embree/common/simd/vdouble4_avx.h
+++ b/thirdparty/embree/common/simd/vdouble4_avx.h
@@ -189,13 +189,20 @@ namespace embree
__forceinline vboold4 operator >=(const vdouble4& a, const vdouble4& b) { return _mm256_cmp_pd_mask(a, b, _MM_CMPINT_GE); }
__forceinline vboold4 operator > (const vdouble4& a, const vdouble4& b) { return _mm256_cmp_pd_mask(a, b, _MM_CMPINT_GT); }
__forceinline vboold4 operator <=(const vdouble4& a, const vdouble4& b) { return _mm256_cmp_pd_mask(a, b, _MM_CMPINT_LE); }
-#else
+#elif !defined(__aarch64__)
__forceinline vboold4 operator ==(const vdouble4& a, const vdouble4& b) { return _mm256_cmp_pd(a, b, _CMP_EQ_OQ); }
__forceinline vboold4 operator !=(const vdouble4& a, const vdouble4& b) { return _mm256_cmp_pd(a, b, _CMP_NEQ_UQ); }
__forceinline vboold4 operator < (const vdouble4& a, const vdouble4& b) { return _mm256_cmp_pd(a, b, _CMP_LT_OS); }
__forceinline vboold4 operator >=(const vdouble4& a, const vdouble4& b) { return _mm256_cmp_pd(a, b, _CMP_NLT_US); }
__forceinline vboold4 operator > (const vdouble4& a, const vdouble4& b) { return _mm256_cmp_pd(a, b, _CMP_NLE_US); }
__forceinline vboold4 operator <=(const vdouble4& a, const vdouble4& b) { return _mm256_cmp_pd(a, b, _CMP_LE_OS); }
+#else
+ __forceinline vboold4 operator ==(const vdouble4& a, const vdouble4& b) { return _mm256_cmpeq_pd(a, b); }
+ __forceinline vboold4 operator !=(const vdouble4& a, const vdouble4& b) { return _mm256_cmpneq_pd(a, b); }
+ __forceinline vboold4 operator < (const vdouble4& a, const vdouble4& b) { return _mm256_cmplt_pd(a, b); }
+ __forceinline vboold4 operator >=(const vdouble4& a, const vdouble4& b) { return _mm256_cmpnlt_pd(a, b); }
+ __forceinline vboold4 operator > (const vdouble4& a, const vdouble4& b) { return _mm256_cmpnle_pd(a, b); }
+ __forceinline vboold4 operator <=(const vdouble4& a, const vdouble4& b) { return _mm256_cmple_pd(a, b); }
#endif
__forceinline vboold4 operator ==(const vdouble4& a, double b) { return a == vdouble4(b); }
diff --git a/thirdparty/embree/common/simd/vfloat16_avx512.h b/thirdparty/embree/common/simd/vfloat16_avx512.h
index 9f1e2459c4..75c471cc0c 100644
--- a/thirdparty/embree/common/simd/vfloat16_avx512.h
+++ b/thirdparty/embree/common/simd/vfloat16_avx512.h
@@ -177,9 +177,10 @@ namespace embree
__forceinline vfloat16 abs (const vfloat16& a) { return _mm512_castsi512_ps(_mm512_and_epi32(_mm512_castps_si512(a),_mm512_set1_epi32(0x7FFFFFFF))); }
__forceinline vfloat16 signmsk(const vfloat16& a) { return _mm512_castsi512_ps(_mm512_and_epi32(_mm512_castps_si512(a),_mm512_set1_epi32(0x80000000))); }
- __forceinline vfloat16 rcp(const vfloat16& a) {
+ __forceinline vfloat16 rcp(const vfloat16& a)
+ {
const vfloat16 r = _mm512_rcp14_ps(a);
- return _mm512_mul_ps(r, _mm512_fnmadd_ps(r, a, vfloat16(2.0f)));
+ return _mm512_fmadd_ps(r, _mm512_fnmadd_ps(a, r, vfloat16(1.0)), r); // computes r + r * (1 - a*r)
}
__forceinline vfloat16 sqr (const vfloat16& a) { return _mm512_mul_ps(a,a); }
diff --git a/thirdparty/embree/common/simd/vfloat4_sse2.h b/thirdparty/embree/common/simd/vfloat4_sse2.h
index 5215bf9730..6d7e11fe72 100644
--- a/thirdparty/embree/common/simd/vfloat4_sse2.h
+++ b/thirdparty/embree/common/simd/vfloat4_sse2.h
@@ -42,6 +42,11 @@ namespace embree
__forceinline vfloat(float a, float b, float c, float d) : v(_mm_set_ps(d, c, b, a)) {}
__forceinline explicit vfloat(const vint4& a) : v(_mm_cvtepi32_ps(a)) {}
+#if defined(__aarch64__)
+ __forceinline explicit vfloat(const vuint4& x) {
+ v = vcvtq_f32_u32(vreinterpretq_u32_s32(x.v));
+ }
+#else
__forceinline explicit vfloat(const vuint4& x) {
const __m128i a = _mm_and_si128(x,_mm_set1_epi32(0x7FFFFFFF));
const __m128i b = _mm_and_si128(_mm_srai_epi32(x,31),_mm_set1_epi32(0x4F000000)); //0x4F000000 = 2^31
@@ -49,7 +54,7 @@ namespace embree
const __m128 bf = _mm_castsi128_ps(b);
v = _mm_add_ps(af,bf);
}
-
+#endif
////////////////////////////////////////////////////////////////////////////////
/// Constants
////////////////////////////////////////////////////////////////////////////////
@@ -107,7 +112,11 @@ namespace embree
#endif
}
-#if defined(__SSE4_1__)
+#if defined(__aarch64__)
+ static __forceinline vfloat4 load(const char* ptr) {
+ return __m128(_mm_load4epi8_f32(((__m128i*)ptr)));
+ }
+#elif defined(__SSE4_1__)
static __forceinline vfloat4 load(const char* ptr) {
return _mm_cvtepi32_ps(_mm_cvtepi8_epi32(_mm_loadu_si128((__m128i*)ptr)));
}
@@ -117,7 +126,11 @@ namespace embree
}
#endif
-#if defined(__SSE4_1__)
+#if defined(__aarch64__)
+ static __forceinline vfloat4 load(const unsigned char* ptr) {
+ return __m128(_mm_load4epu8_f32(((__m128i*)ptr)));
+ }
+#elif defined(__SSE4_1__)
static __forceinline vfloat4 load(const unsigned char* ptr) {
return _mm_cvtepi32_ps(_mm_cvtepu8_epi32(_mm_loadu_si128((__m128i*)ptr)));
}
@@ -128,7 +141,11 @@ namespace embree
}
#endif
-#if defined(__SSE4_1__)
+#if defined(__aarch64__)
+ static __forceinline vfloat4 load(const short* ptr) {
+ return __m128(_mm_load4epi16_f32(((__m128i*)ptr)));
+ }
+#elif defined(__SSE4_1__)
static __forceinline vfloat4 load(const short* ptr) {
return _mm_cvtepi32_ps(_mm_cvtepi16_epi32(_mm_loadu_si128((__m128i*)ptr)));
}
@@ -145,15 +162,19 @@ namespace embree
static __forceinline void store_nt(void* ptr, const vfloat4& v)
{
#if defined (__SSE4_1__)
+#if defined(__aarch64__)
_mm_stream_ps((float*)ptr,v);
#else
+ _mm_stream_ps((float*)ptr,v);
+#endif
+#else
_mm_store_ps((float*)ptr,v);
#endif
}
template<int scale = 4>
static __forceinline vfloat4 gather(const float* ptr, const vint4& index) {
-#if defined(__AVX2__)
+#if defined(__AVX2__) && !defined(__aarch64__)
return _mm_i32gather_ps(ptr, index, scale);
#else
return vfloat4(
@@ -169,7 +190,7 @@ namespace embree
vfloat4 r = zero;
#if defined(__AVX512VL__)
return _mm_mmask_i32gather_ps(r, mask, index, ptr, scale);
-#elif defined(__AVX2__)
+#elif defined(__AVX2__) && !defined(__aarch64__)
return _mm_mask_i32gather_ps(r, ptr, index, mask, scale);
#else
if (likely(mask[0])) r[0] = *(float*)(((char*)ptr)+scale*index[0]);
@@ -223,8 +244,8 @@ namespace embree
friend __forceinline vfloat4 select(const vboolf4& m, const vfloat4& t, const vfloat4& f) {
#if defined(__AVX512VL__)
return _mm_mask_blend_ps(m, f, t);
-#elif defined(__SSE4_1__)
- return _mm_blendv_ps(f, t, m);
+#elif defined(__SSE4_1__) || (defined(__aarch64__))
+ return _mm_blendv_ps(f, t, m);
#else
return _mm_or_ps(_mm_and_ps(m, t), _mm_andnot_ps(m, f));
#endif
@@ -256,18 +277,34 @@ namespace embree
__forceinline vfloat4 toFloat(const vint4& a) { return vfloat4(a); }
__forceinline vfloat4 operator +(const vfloat4& a) { return a; }
+#if defined(__aarch64__)
+ __forceinline vfloat4 operator -(const vfloat4& a) {
+ return vnegq_f32(a);
+ }
+#else
__forceinline vfloat4 operator -(const vfloat4& a) { return _mm_xor_ps(a, _mm_castsi128_ps(_mm_set1_epi32(0x80000000))); }
+#endif
+#if defined(__aarch64__)
+ __forceinline vfloat4 abs(const vfloat4& a) { return _mm_abs_ps(a); }
+#else
__forceinline vfloat4 abs(const vfloat4& a) { return _mm_and_ps(a, _mm_castsi128_ps(_mm_set1_epi32(0x7fffffff))); }
+#endif
+
#if defined(__AVX512VL__)
__forceinline vfloat4 sign(const vfloat4& a) { return _mm_mask_blend_ps(_mm_cmp_ps_mask(a, vfloat4(zero), _CMP_LT_OQ), vfloat4(one), -vfloat4(one)); }
#else
__forceinline vfloat4 sign(const vfloat4& a) { return blendv_ps(vfloat4(one), -vfloat4(one), _mm_cmplt_ps(a, vfloat4(zero))); }
#endif
+
__forceinline vfloat4 signmsk(const vfloat4& a) { return _mm_and_ps(a,_mm_castsi128_ps(_mm_set1_epi32(0x80000000))); }
-
+
__forceinline vfloat4 rcp(const vfloat4& a)
{
+#if defined(__aarch64__)
+ return vfloat4(vdivq_f32(vdupq_n_f32(1.0f),a.v));
+#else
+
#if defined(__AVX512VL__)
const vfloat4 r = _mm_rcp14_ps(a);
#else
@@ -275,30 +312,39 @@ namespace embree
#endif
#if defined(__AVX2__)
- return _mm_mul_ps(r,_mm_fnmadd_ps(r, a, vfloat4(2.0f)));
+ return _mm_fmadd_ps(r, _mm_fnmadd_ps(a, r, vfloat4(1.0f)), r); // computes r + r * (1 - a * r)
#else
- return _mm_mul_ps(r,_mm_sub_ps(vfloat4(2.0f), _mm_mul_ps(r, a)));
+ return _mm_add_ps(r,_mm_mul_ps(r, _mm_sub_ps(vfloat4(1.0f), _mm_mul_ps(a, r)))); // computes r + r * (1 - a * r)
#endif
+
+#endif //defined(__aarch64__)
}
__forceinline vfloat4 sqr (const vfloat4& a) { return _mm_mul_ps(a,a); }
__forceinline vfloat4 sqrt(const vfloat4& a) { return _mm_sqrt_ps(a); }
__forceinline vfloat4 rsqrt(const vfloat4& a)
{
+#if defined(__aarch64__)
+ vfloat4 r = _mm_rsqrt_ps(a);
+ r = vmulq_f32(r, vrsqrtsq_f32(vmulq_f32(a, r), r));
+ r = vmulq_f32(r, vrsqrtsq_f32(vmulq_f32(a, r), r));
+ r = vmulq_f32(r, vrsqrtsq_f32(vmulq_f32(a, r), r));
+ return r;
+#else
+
#if defined(__AVX512VL__)
vfloat4 r = _mm_rsqrt14_ps(a);
#else
vfloat4 r = _mm_rsqrt_ps(a);
#endif
-#if defined(__ARM_NEON)
- r = _mm_fmadd_ps(_mm_set1_ps(1.5f), r, _mm_mul_ps(_mm_mul_ps(_mm_mul_ps(a, _mm_set1_ps(-0.5f)), r), _mm_mul_ps(r, r)));
- r = _mm_fmadd_ps(_mm_set1_ps(1.5f), r, _mm_mul_ps(_mm_mul_ps(_mm_mul_ps(a, _mm_set1_ps(-0.5f)), r), _mm_mul_ps(r, r)));
-#elif defined(__AVX2__)
+#if defined(__AVX2__)
r = _mm_fmadd_ps(_mm_set1_ps(1.5f), r, _mm_mul_ps(_mm_mul_ps(_mm_mul_ps(a, _mm_set1_ps(-0.5f)), r), _mm_mul_ps(r, r)));
#else
r = _mm_add_ps(_mm_mul_ps(_mm_set1_ps(1.5f), r), _mm_mul_ps(_mm_mul_ps(_mm_mul_ps(a, _mm_set1_ps(-0.5f)), r), _mm_mul_ps(r, r)));
#endif
+
+#endif
return r;
}
@@ -344,7 +390,8 @@ namespace embree
__forceinline vfloat4 max(const vfloat4& a, float b) { return _mm_max_ps(a,vfloat4(b)); }
__forceinline vfloat4 max(float a, const vfloat4& b) { return _mm_max_ps(vfloat4(a),b); }
-#if defined(__SSE4_1__)
+#if defined(__SSE4_1__) || defined(__aarch64__)
+
__forceinline vfloat4 mini(const vfloat4& a, const vfloat4& b) {
const vint4 ai = _mm_castps_si128(a);
const vint4 bi = _mm_castps_si128(b);
@@ -393,9 +440,10 @@ namespace embree
__forceinline vfloat4 nmsub(const vfloat4& a, const vfloat4& b, const vfloat4& c) { return _mm_fnmsub_ps(a,b,c); }
#else
__forceinline vfloat4 madd (const vfloat4& a, const vfloat4& b, const vfloat4& c) { return a*b+c; }
- __forceinline vfloat4 msub (const vfloat4& a, const vfloat4& b, const vfloat4& c) { return a*b-c; }
__forceinline vfloat4 nmadd(const vfloat4& a, const vfloat4& b, const vfloat4& c) { return -a*b+c;}
__forceinline vfloat4 nmsub(const vfloat4& a, const vfloat4& b, const vfloat4& c) { return -a*b-c; }
+ __forceinline vfloat4 msub (const vfloat4& a, const vfloat4& b, const vfloat4& c) { return a*b-c; }
+
#endif
////////////////////////////////////////////////////////////////////////////////
@@ -429,8 +477,13 @@ namespace embree
__forceinline vboolf4 operator ==(const vfloat4& a, const vfloat4& b) { return _mm_cmpeq_ps (a, b); }
__forceinline vboolf4 operator !=(const vfloat4& a, const vfloat4& b) { return _mm_cmpneq_ps(a, b); }
__forceinline vboolf4 operator < (const vfloat4& a, const vfloat4& b) { return _mm_cmplt_ps (a, b); }
+#if defined(__aarch64__)
+ __forceinline vboolf4 operator >=(const vfloat4& a, const vfloat4& b) { return _mm_cmpge_ps (a, b); }
+ __forceinline vboolf4 operator > (const vfloat4& a, const vfloat4& b) { return _mm_cmpgt_ps (a, b); }
+#else
__forceinline vboolf4 operator >=(const vfloat4& a, const vfloat4& b) { return _mm_cmpnlt_ps(a, b); }
__forceinline vboolf4 operator > (const vfloat4& a, const vfloat4& b) { return _mm_cmpnle_ps(a, b); }
+#endif
__forceinline vboolf4 operator <=(const vfloat4& a, const vfloat4& b) { return _mm_cmple_ps (a, b); }
#endif
@@ -484,7 +537,7 @@ namespace embree
return select(vboolf4(mask), t, f);
#endif
}
-
+
__forceinline vfloat4 lerp(const vfloat4& a, const vfloat4& b, const vfloat4& t) {
return madd(t,b-a,a);
}
@@ -506,10 +559,10 @@ namespace embree
////////////////////////////////////////////////////////////////////////////////
#if defined(__aarch64__)
- __forceinline vfloat4 floor(const vfloat4& a) { return vrndmq_f32(a.v); }
- __forceinline vfloat4 ceil (const vfloat4& a) { return vrndpq_f32(a.v); }
- __forceinline vfloat4 trunc(const vfloat4& a) { return vrndq_f32(a.v); }
- __forceinline vfloat4 round(const vfloat4& a) { return vrndnq_f32(a.v); }
+ __forceinline vfloat4 floor(const vfloat4& a) { return vrndmq_f32(a.v); } // towards -inf
+ __forceinline vfloat4 ceil (const vfloat4& a) { return vrndpq_f32(a.v); } // toward +inf
+ __forceinline vfloat4 trunc(const vfloat4& a) { return vrndq_f32(a.v); } // towards 0
+ __forceinline vfloat4 round(const vfloat4& a) { return vrndnq_f32(a.v); } // to nearest, ties to even. NOTE(LTE): arm clang uses vrndnq, old gcc uses vrndqn?
#elif defined (__SSE4_1__)
__forceinline vfloat4 floor(const vfloat4& a) { return _mm_round_ps(a, _MM_FROUND_TO_NEG_INF ); }
__forceinline vfloat4 ceil (const vfloat4& a) { return _mm_round_ps(a, _MM_FROUND_TO_POS_INF ); }
@@ -524,7 +577,9 @@ namespace embree
__forceinline vfloat4 frac(const vfloat4& a) { return a-floor(a); }
__forceinline vint4 floori(const vfloat4& a) {
-#if defined(__SSE4_1__)
+#if defined(__aarch64__)
+ return vcvtq_s32_f32(floor(a));
+#elif defined(__SSE4_1__)
return vint4(floor(a));
#else
return vint4(a-vfloat4(0.5f));
@@ -538,6 +593,16 @@ namespace embree
__forceinline vfloat4 unpacklo(const vfloat4& a, const vfloat4& b) { return _mm_unpacklo_ps(a, b); }
__forceinline vfloat4 unpackhi(const vfloat4& a, const vfloat4& b) { return _mm_unpackhi_ps(a, b); }
+#if defined(__aarch64__)
+ template<int i0, int i1, int i2, int i3>
+ __forceinline vfloat4 shuffle(const vfloat4& v) {
+ return vreinterpretq_f32_u8(vqtbl1q_u8( (uint8x16_t)v.v, _MN_SHUFFLE(i0, i1, i2, i3)));
+ }
+ template<int i0, int i1, int i2, int i3>
+ __forceinline vfloat4 shuffle(const vfloat4& a, const vfloat4& b) {
+ return vreinterpretq_f32_u8(vqtbl2q_u8( (uint8x16x2_t){(uint8x16_t)a.v, (uint8x16_t)b.v}, _MF_SHUFFLE(i0, i1, i2, i3)));
+ }
+#else
template<int i0, int i1, int i2, int i3>
__forceinline vfloat4 shuffle(const vfloat4& v) {
return _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(v), _MM_SHUFFLE(i3, i2, i1, i0)));
@@ -547,8 +612,9 @@ namespace embree
__forceinline vfloat4 shuffle(const vfloat4& a, const vfloat4& b) {
return _mm_shuffle_ps(a, b, _MM_SHUFFLE(i3, i2, i1, i0));
}
+#endif
-#if defined(__SSE3__)
+#if defined(__SSE3__) && !defined(__aarch64__)
template<> __forceinline vfloat4 shuffle<0, 0, 2, 2>(const vfloat4& v) { return _mm_moveldup_ps(v); }
template<> __forceinline vfloat4 shuffle<1, 1, 3, 3>(const vfloat4& v) { return _mm_movehdup_ps(v); }
template<> __forceinline vfloat4 shuffle<0, 1, 0, 1>(const vfloat4& v) { return _mm_castpd_ps(_mm_movedup_pd(_mm_castps_pd(v))); }
@@ -559,10 +625,14 @@ namespace embree
return shuffle<i,i,i,i>(v);
}
+#if defined(__aarch64__)
+ template<int i> __forceinline float extract(const vfloat4& a) { return a[i]; }
+#else
template<int i> __forceinline float extract (const vfloat4& a) { return _mm_cvtss_f32(shuffle<i>(a)); }
template<> __forceinline float extract<0>(const vfloat4& a) { return _mm_cvtss_f32(a); }
+#endif
-#if defined (__SSE4_1__)
+#if defined (__SSE4_1__) && !defined(__aarch64__)
template<int dst, int src, int clr> __forceinline vfloat4 insert(const vfloat4& a, const vfloat4& b) { return _mm_insert_ps(a, b, (dst << 4) | (src << 6) | clr); }
template<int dst, int src> __forceinline vfloat4 insert(const vfloat4& a, const vfloat4& b) { return insert<dst, src, 0>(a, b); }
template<int dst> __forceinline vfloat4 insert(const vfloat4& a, const float b) { return insert<dst, 0>(a, _mm_set_ss(b)); }
@@ -664,14 +734,25 @@ namespace embree
////////////////////////////////////////////////////////////////////////////////
/// Reductions
////////////////////////////////////////////////////////////////////////////////
-
+#if defined(__aarch64__)
+ __forceinline vfloat4 vreduce_min(const vfloat4& v) { float h = vminvq_f32(v); return vdupq_n_f32(h); }
+ __forceinline vfloat4 vreduce_max(const vfloat4& v) { float h = vmaxvq_f32(v); return vdupq_n_f32(h); }
+ __forceinline vfloat4 vreduce_add(const vfloat4& v) { float h = vaddvq_f32(v); return vdupq_n_f32(h); }
+#else
__forceinline vfloat4 vreduce_min(const vfloat4& v) { vfloat4 h = min(shuffle<1,0,3,2>(v),v); return min(shuffle<2,3,0,1>(h),h); }
__forceinline vfloat4 vreduce_max(const vfloat4& v) { vfloat4 h = max(shuffle<1,0,3,2>(v),v); return max(shuffle<2,3,0,1>(h),h); }
__forceinline vfloat4 vreduce_add(const vfloat4& v) { vfloat4 h = shuffle<1,0,3,2>(v) + v ; return shuffle<2,3,0,1>(h) + h ; }
+#endif
+#if defined(__aarch64__)
+ __forceinline float reduce_min(const vfloat4& v) { return vminvq_f32(v); }
+ __forceinline float reduce_max(const vfloat4& v) { return vmaxvq_f32(v); }
+ __forceinline float reduce_add(const vfloat4& v) { return vaddvq_f32(v); }
+#else
__forceinline float reduce_min(const vfloat4& v) { return _mm_cvtss_f32(vreduce_min(v)); }
__forceinline float reduce_max(const vfloat4& v) { return _mm_cvtss_f32(vreduce_max(v)); }
__forceinline float reduce_add(const vfloat4& v) { return _mm_cvtss_f32(vreduce_add(v)); }
+#endif
__forceinline size_t select_min(const vboolf4& valid, const vfloat4& v)
{
@@ -687,7 +768,7 @@ namespace embree
}
////////////////////////////////////////////////////////////////////////////////
- /// Euclidian Space Operators
+ /// Euclidean Space Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline float dot(const vfloat4& a, const vfloat4& b) {
diff --git a/thirdparty/embree/common/simd/vfloat8_avx.h b/thirdparty/embree/common/simd/vfloat8_avx.h
index 13446454e8..b09d5e641d 100644
--- a/thirdparty/embree/common/simd/vfloat8_avx.h
+++ b/thirdparty/embree/common/simd/vfloat8_avx.h
@@ -107,11 +107,11 @@ namespace embree
static __forceinline void store (const vboolf8& mask, void* ptr, const vfloat8& v) { _mm256_mask_store_ps ((float*)ptr,mask,v); }
static __forceinline void storeu(const vboolf8& mask, void* ptr, const vfloat8& v) { _mm256_mask_storeu_ps((float*)ptr,mask,v); }
#else
- static __forceinline vfloat8 load (const vboolf8& mask, const void* ptr) { return _mm256_maskload_ps((float*)ptr,(__m256i)mask); }
- static __forceinline vfloat8 loadu(const vboolf8& mask, const void* ptr) { return _mm256_maskload_ps((float*)ptr,(__m256i)mask); }
+ static __forceinline vfloat8 load (const vboolf8& mask, const void* ptr) { return _mm256_maskload_ps((float*)ptr,_mm256_castps_si256(mask.v)); }
+ static __forceinline vfloat8 loadu(const vboolf8& mask, const void* ptr) { return _mm256_maskload_ps((float*)ptr,_mm256_castps_si256(mask.v)); }
- static __forceinline void store (const vboolf8& mask, void* ptr, const vfloat8& v) { _mm256_maskstore_ps((float*)ptr,(__m256i)mask,v); }
- static __forceinline void storeu(const vboolf8& mask, void* ptr, const vfloat8& v) { _mm256_maskstore_ps((float*)ptr,(__m256i)mask,v); }
+ static __forceinline void store (const vboolf8& mask, void* ptr, const vfloat8& v) { _mm256_maskstore_ps((float*)ptr,_mm256_castps_si256(mask.v),v); }
+ static __forceinline void storeu(const vboolf8& mask, void* ptr, const vfloat8& v) { _mm256_maskstore_ps((float*)ptr,_mm256_castps_si256(mask.v),v); }
#endif
#if defined(__AVX2__)
@@ -126,7 +126,7 @@ namespace embree
template<int scale = 4>
static __forceinline vfloat8 gather(const float* ptr, const vint8& index) {
-#if defined(__AVX2__)
+#if defined(__AVX2__) && !defined(__aarch64__)
return _mm256_i32gather_ps(ptr, index ,scale);
#else
return vfloat8(
@@ -146,7 +146,7 @@ namespace embree
vfloat8 r = zero;
#if defined(__AVX512VL__)
return _mm256_mmask_i32gather_ps(r, mask, index, ptr, scale);
-#elif defined(__AVX2__)
+#elif defined(__AVX2__) && !defined(__aarch64__)
return _mm256_mask_i32gather_ps(r, ptr, index, mask, scale);
#else
if (likely(mask[0])) r[0] = *(float*)(((char*)ptr)+scale*index[0]);
@@ -215,20 +215,52 @@ namespace embree
__forceinline vfloat8 toFloat(const vint8& a) { return vfloat8(a); }
__forceinline vfloat8 operator +(const vfloat8& a) { return a; }
+#if !defined(__aarch64__)
__forceinline vfloat8 operator -(const vfloat8& a) {
const __m256 mask = _mm256_castsi256_ps(_mm256_set1_epi32(0x80000000));
return _mm256_xor_ps(a, mask);
}
+#else
+ __forceinline vfloat8 operator -(const vfloat8& a) {
+ __m256 res;
+ res.lo = vnegq_f32(a.v.lo);
+ res.hi = vnegq_f32(a.v.hi);
+ return res;
+}
+#endif
+
+#if !defined(__aarch64__)
__forceinline vfloat8 abs(const vfloat8& a) {
const __m256 mask = _mm256_castsi256_ps(_mm256_set1_epi32(0x7fffffff));
return _mm256_and_ps(a, mask);
}
+#else
+__forceinline vfloat8 abs(const vfloat8& a) {
+ __m256 res;
+ res.lo = vabsq_f32(a.v.lo);
+ res.hi = vabsq_f32(a.v.hi);
+ return res;
+}
+#endif
+
+#if !defined(__aarch64__)
__forceinline vfloat8 sign (const vfloat8& a) { return _mm256_blendv_ps(vfloat8(one), -vfloat8(one), _mm256_cmp_ps(a, vfloat8(zero), _CMP_NGE_UQ)); }
+#else
+ __forceinline vfloat8 sign (const vfloat8& a) { return _mm256_blendv_ps(vfloat8(one), -vfloat8(one), _mm256_cmplt_ps(a, vfloat8(zero))); }
+#endif
__forceinline vfloat8 signmsk(const vfloat8& a) { return _mm256_and_ps(a,_mm256_castsi256_ps(_mm256_set1_epi32(0x80000000))); }
static __forceinline vfloat8 rcp(const vfloat8& a)
{
+#if defined(__aarch64__)
+ vfloat8 ret;
+ const float32x4_t one = vdupq_n_f32(1.0f);
+ ret.v.lo = vdivq_f32(one, a.v.lo);
+ ret.v.hi = vdivq_f32(one, a.v.hi);
+ return ret;
+#endif
+
#if defined(__AVX512VL__)
const vfloat8 r = _mm256_rcp14_ps(a);
#else
@@ -236,9 +268,12 @@ namespace embree
#endif
#if defined(__AVX2__)
- return _mm256_mul_ps(r, _mm256_fnmadd_ps(r, a, vfloat8(2.0f)));
+ // First, compute 1 - a * r (which will be very close to 0)
+ const vfloat8 h_n = _mm256_fnmadd_ps(a, r, vfloat8(1.0f));
+ // Then compute r + r * h_n
+ return _mm256_fmadd_ps(r, h_n, r);
#else
- return _mm256_mul_ps(r, _mm256_sub_ps(vfloat8(2.0f), _mm256_mul_ps(r, a)));
+ return _mm256_add_ps(r,_mm256_mul_ps(r, _mm256_sub_ps(vfloat8(1.0f), _mm256_mul_ps(a, r)))); // computes r + r * (1 - a * r)
#endif
}
__forceinline vfloat8 sqr (const vfloat8& a) { return _mm256_mul_ps(a,a); }
@@ -384,7 +419,7 @@ namespace embree
static __forceinline vfloat8 select(const vboolf8& m, const vfloat8& t, const vfloat8& f) {
return _mm256_mask_blend_ps(m, f, t);
}
-#else
+#elif !defined(__aarch64__)
static __forceinline vboolf8 operator ==(const vfloat8& a, const vfloat8& b) { return _mm256_cmp_ps(a, b, _CMP_EQ_OQ); }
static __forceinline vboolf8 operator !=(const vfloat8& a, const vfloat8& b) { return _mm256_cmp_ps(a, b, _CMP_NEQ_UQ); }
static __forceinline vboolf8 operator < (const vfloat8& a, const vfloat8& b) { return _mm256_cmp_ps(a, b, _CMP_LT_OS); }
@@ -395,6 +430,18 @@ namespace embree
static __forceinline vfloat8 select(const vboolf8& m, const vfloat8& t, const vfloat8& f) {
return _mm256_blendv_ps(f, t, m);
}
+#else
+ static __forceinline vboolf8 operator ==(const vfloat8& a, const vfloat8& b) { return _mm256_cmpeq_ps(a, b); }
+ static __forceinline vboolf8 operator !=(const vfloat8& a, const vfloat8& b) { return _mm256_cmpneq_ps(a, b); }
+ static __forceinline vboolf8 operator < (const vfloat8& a, const vfloat8& b) { return _mm256_cmplt_ps(a, b); }
+ static __forceinline vboolf8 operator >=(const vfloat8& a, const vfloat8& b) { return _mm256_cmpge_ps(a, b); }
+ static __forceinline vboolf8 operator > (const vfloat8& a, const vfloat8& b) { return _mm256_cmpgt_ps(a, b); }
+ static __forceinline vboolf8 operator <=(const vfloat8& a, const vfloat8& b) { return _mm256_cmple_ps(a, b); }
+
+ static __forceinline vfloat8 select(const vboolf8& m, const vfloat8& t, const vfloat8& f) {
+ return _mm256_blendv_ps(f, t, m);
+ }
+
#endif
template<int mask>
@@ -463,10 +510,17 @@ namespace embree
/// Rounding Functions
////////////////////////////////////////////////////////////////////////////////
+#if !defined(__aarch64__)
__forceinline vfloat8 floor(const vfloat8& a) { return _mm256_round_ps(a, _MM_FROUND_TO_NEG_INF ); }
__forceinline vfloat8 ceil (const vfloat8& a) { return _mm256_round_ps(a, _MM_FROUND_TO_POS_INF ); }
__forceinline vfloat8 trunc(const vfloat8& a) { return _mm256_round_ps(a, _MM_FROUND_TO_ZERO ); }
__forceinline vfloat8 round(const vfloat8& a) { return _mm256_round_ps(a, _MM_FROUND_TO_NEAREST_INT); }
+#else
+ __forceinline vfloat8 floor(const vfloat8& a) { return _mm256_floor_ps(a); }
+ __forceinline vfloat8 ceil (const vfloat8& a) { return _mm256_ceil_ps(a); }
+#endif
+
+
__forceinline vfloat8 frac (const vfloat8& a) { return a-floor(a); }
////////////////////////////////////////////////////////////////////////////////
@@ -501,9 +555,11 @@ namespace embree
return _mm256_shuffle_ps(a, b, _MM_SHUFFLE(i3, i2, i1, i0));
}
+#if !defined(__aarch64__)
template<> __forceinline vfloat8 shuffle<0, 0, 2, 2>(const vfloat8& v) { return _mm256_moveldup_ps(v); }
template<> __forceinline vfloat8 shuffle<1, 1, 3, 3>(const vfloat8& v) { return _mm256_movehdup_ps(v); }
template<> __forceinline vfloat8 shuffle<0, 1, 0, 1>(const vfloat8& v) { return _mm256_castpd_ps(_mm256_movedup_pd(_mm256_castps_pd(v))); }
+#endif
__forceinline vfloat8 broadcast(const float* ptr) { return _mm256_broadcast_ss(ptr); }
template<size_t i> __forceinline vfloat8 insert4(const vfloat8& a, const vfloat4& b) { return _mm256_insertf128_ps(a, b, i); }
@@ -512,7 +568,7 @@ namespace embree
__forceinline float toScalar(const vfloat8& v) { return _mm_cvtss_f32(_mm256_castps256_ps128(v)); }
-#if defined (__AVX2__)
+#if defined (__AVX2__) && !defined(__aarch64__)
static __forceinline vfloat8 permute(const vfloat8& a, const __m256i& index) {
return _mm256_permutevar8x32_ps(a, index);
}
@@ -609,7 +665,7 @@ namespace embree
////////////////////////////////////////////////////////////////////////////////
/// Reductions
////////////////////////////////////////////////////////////////////////////////
-
+#if !defined(__aarch64__)
__forceinline vfloat8 vreduce_min2(const vfloat8& v) { return min(v,shuffle<1,0,3,2>(v)); }
__forceinline vfloat8 vreduce_min4(const vfloat8& v) { vfloat8 v1 = vreduce_min2(v); return min(v1,shuffle<2,3,0,1>(v1)); }
__forceinline vfloat8 vreduce_min (const vfloat8& v) { vfloat8 v1 = vreduce_min4(v); return min(v1,shuffle4<1,0>(v1)); }
@@ -625,7 +681,14 @@ namespace embree
__forceinline float reduce_min(const vfloat8& v) { return toScalar(vreduce_min(v)); }
__forceinline float reduce_max(const vfloat8& v) { return toScalar(vreduce_max(v)); }
__forceinline float reduce_add(const vfloat8& v) { return toScalar(vreduce_add(v)); }
+#else
+ __forceinline float reduce_min(const vfloat8& v) { return vminvq_f32(_mm_min_ps(v.v.lo,v.v.hi)); }
+ __forceinline float reduce_max(const vfloat8& v) { return vmaxvq_f32(_mm_max_ps(v.v.lo,v.v.hi)); }
+ __forceinline vfloat8 vreduce_min(const vfloat8& v) { return vfloat8(reduce_min(v)); }
+ __forceinline vfloat8 vreduce_max(const vfloat8& v) { return vfloat8(reduce_max(v)); }
+ __forceinline float reduce_add(const vfloat8& v) { return vaddvq_f32(_mm_add_ps(v.v.lo,v.v.hi)); }
+#endif
__forceinline size_t select_min(const vboolf8& valid, const vfloat8& v)
{
const vfloat8 a = select(valid,v,vfloat8(pos_inf));
@@ -642,7 +705,7 @@ namespace embree
////////////////////////////////////////////////////////////////////////////////
- /// Euclidian Space Operators (pairs of Vec3fa's)
+ /// Euclidean Space Operators (pairs of Vec3fa's)
////////////////////////////////////////////////////////////////////////////////
//__forceinline vfloat8 dot(const vfloat8& a, const vfloat8& b) {
diff --git a/thirdparty/embree/common/simd/vint4_sse2.h b/thirdparty/embree/common/simd/vint4_sse2.h
index 9814d5c71c..eea03a771e 100644
--- a/thirdparty/embree/common/simd/vint4_sse2.h
+++ b/thirdparty/embree/common/simd/vint4_sse2.h
@@ -106,7 +106,14 @@ namespace embree
#endif
-#if defined(__SSE4_1__)
+#if defined(__aarch64__)
+ static __forceinline vint4 load(const unsigned char* ptr) {
+ return _mm_load4epu8_epi32(((__m128i*)ptr));
+ }
+ static __forceinline vint4 loadu(const unsigned char* ptr) {
+ return _mm_load4epu8_epi32(((__m128i*)ptr));
+ }
+#elif defined(__SSE4_1__)
static __forceinline vint4 load(const unsigned char* ptr) {
return _mm_cvtepu8_epi32(_mm_loadl_epi64((__m128i*)ptr));
}
@@ -127,7 +134,9 @@ namespace embree
#endif
static __forceinline vint4 load(const unsigned short* ptr) {
-#if defined (__SSE4_1__)
+#if defined(__aarch64__)
+ return __m128i(vmovl_u16(vld1_u16(ptr)));
+#elif defined (__SSE4_1__)
return _mm_cvtepu16_epi32(_mm_loadu_si128((__m128i*)ptr));
#else
return vint4(ptr[0],ptr[1],ptr[2],ptr[3]);
@@ -135,7 +144,12 @@ namespace embree
}
static __forceinline void store(unsigned char* ptr, const vint4& v) {
-#if defined(__SSE4_1__)
+#if defined(__aarch64__)
+ int32x4_t x = v;
+ uint16x4_t y = vqmovn_u32(uint32x4_t(x));
+ uint8x8_t z = vqmovn_u16(vcombine_u16(y, y));
+ vst1_lane_u32((uint32_t *)ptr,uint32x2_t(z), 0);
+#elif defined(__SSE4_1__)
__m128i x = v;
x = _mm_packus_epi32(x, x);
x = _mm_packus_epi16(x, x);
@@ -147,20 +161,26 @@ namespace embree
}
static __forceinline void store(unsigned short* ptr, const vint4& v) {
+#if defined(__aarch64__)
+ uint32x4_t x = uint32x4_t(v.v);
+ uint16x4_t y = vqmovn_u32(x);
+ vst1_u16(ptr, y);
+#else
for (size_t i=0;i<4;i++)
ptr[i] = (unsigned short)v[i];
+#endif
}
static __forceinline vint4 load_nt(void* ptr) {
-#if defined(__SSE4_1__)
- return _mm_stream_load_si128((__m128i*)ptr);
+#if defined(__aarch64__) || defined(__SSE4_1__)
+ return _mm_stream_load_si128((__m128i*)ptr);
#else
return _mm_load_si128((__m128i*)ptr);
#endif
}
static __forceinline void store_nt(void* ptr, const vint4& v) {
-#if defined(__SSE4_1__)
+#if !defined(__aarch64__) && defined(__SSE4_1__)
_mm_stream_ps((float*)ptr, _mm_castsi128_ps(v));
#else
_mm_store_si128((__m128i*)ptr,v);
@@ -169,7 +189,7 @@ namespace embree
template<int scale = 4>
static __forceinline vint4 gather(const int* ptr, const vint4& index) {
-#if defined(__AVX2__)
+#if defined(__AVX2__) && !defined(__aarch64__)
return _mm_i32gather_epi32(ptr, index, scale);
#else
return vint4(
@@ -185,7 +205,7 @@ namespace embree
vint4 r = zero;
#if defined(__AVX512VL__)
return _mm_mmask_i32gather_epi32(r, mask, index, ptr, scale);
-#elif defined(__AVX2__)
+#elif defined(__AVX2__) && !defined(__aarch64__)
return _mm_mask_i32gather_epi32(r, ptr, index, mask, scale);
#else
if (likely(mask[0])) r[0] = *(int*)(((char*)ptr)+scale*index[0]);
@@ -222,7 +242,7 @@ namespace embree
#endif
}
-#if defined(__x86_64__)
+#if defined(__x86_64__) || defined(__aarch64__)
static __forceinline vint4 broadcast64(long long a) { return _mm_set1_epi64x(a); }
#endif
@@ -236,6 +256,8 @@ namespace embree
friend __forceinline vint4 select(const vboolf4& m, const vint4& t, const vint4& f) {
#if defined(__AVX512VL__)
return _mm_mask_blend_epi32(m, (__m128i)f, (__m128i)t);
+#elif defined(__aarch64__)
+ return _mm_castps_si128(_mm_blendv_ps((__m128)f.v,(__m128) t.v, (__m128)m.v));
#elif defined(__SSE4_1__)
return _mm_castps_si128(_mm_blendv_ps(_mm_castsi128_ps(f), _mm_castsi128_ps(t), m));
#else
@@ -256,7 +278,9 @@ namespace embree
__forceinline vint4 operator +(const vint4& a) { return a; }
__forceinline vint4 operator -(const vint4& a) { return _mm_sub_epi32(_mm_setzero_si128(), a); }
-#if defined(__SSSE3__)
+#if defined(__aarch64__)
+ __forceinline vint4 abs(const vint4& a) { return vabsq_s32(a.v); }
+#elif defined(__SSSE3__)
__forceinline vint4 abs(const vint4& a) { return _mm_abs_epi32(a); }
#endif
@@ -272,7 +296,7 @@ namespace embree
__forceinline vint4 operator -(const vint4& a, int b) { return a - vint4(b); }
__forceinline vint4 operator -(int a, const vint4& b) { return vint4(a) - b; }
-#if defined(__SSE4_1__)
+#if (defined(__aarch64__)) || defined(__SSE4_1__)
__forceinline vint4 operator *(const vint4& a, const vint4& b) { return _mm_mullo_epi32(a, b); }
#else
__forceinline vint4 operator *(const vint4& a, const vint4& b) { return vint4(a[0]*b[0],a[1]*b[1],a[2]*b[2],a[3]*b[3]); }
@@ -292,8 +316,8 @@ namespace embree
__forceinline vint4 operator ^(const vint4& a, int b) { return a ^ vint4(b); }
__forceinline vint4 operator ^(int a, const vint4& b) { return vint4(a) ^ b; }
- __forceinline vint4 operator <<(const vint4& a, int n) { return _mm_slli_epi32(a, n); }
- __forceinline vint4 operator >>(const vint4& a, int n) { return _mm_srai_epi32(a, n); }
+ __forceinline vint4 operator <<(const vint4& a, const int n) { return _mm_slli_epi32(a, n); }
+ __forceinline vint4 operator >>(const vint4& a, const int n) { return _mm_srai_epi32(a, n); }
__forceinline vint4 sll (const vint4& a, int b) { return _mm_slli_epi32(a, b); }
__forceinline vint4 sra (const vint4& a, int b) { return _mm_srai_epi32(a, b); }
@@ -309,7 +333,7 @@ namespace embree
__forceinline vint4& operator -=(vint4& a, const vint4& b) { return a = a - b; }
__forceinline vint4& operator -=(vint4& a, int b) { return a = a - b; }
-#if defined(__SSE4_1__)
+#if (defined(__aarch64__)) || defined(__SSE4_1__)
__forceinline vint4& operator *=(vint4& a, const vint4& b) { return a = a * b; }
__forceinline vint4& operator *=(vint4& a, int b) { return a = a * b; }
#endif
@@ -393,7 +417,7 @@ namespace embree
#endif
}
-#if defined(__SSE4_1__)
+#if defined(__aarch64__) || defined(__SSE4_1__)
__forceinline vint4 min(const vint4& a, const vint4& b) { return _mm_min_epi32(a, b); }
__forceinline vint4 max(const vint4& a, const vint4& b) { return _mm_max_epi32(a, b); }
@@ -417,6 +441,16 @@ namespace embree
__forceinline vint4 unpacklo(const vint4& a, const vint4& b) { return _mm_castps_si128(_mm_unpacklo_ps(_mm_castsi128_ps(a), _mm_castsi128_ps(b))); }
__forceinline vint4 unpackhi(const vint4& a, const vint4& b) { return _mm_castps_si128(_mm_unpackhi_ps(_mm_castsi128_ps(a), _mm_castsi128_ps(b))); }
+#if defined(__aarch64__)
+ template<int i0, int i1, int i2, int i3>
+ __forceinline vint4 shuffle(const vint4& v) {
+ return vreinterpretq_s32_u8(vqtbl1q_u8( (uint8x16_t)v.v, _MN_SHUFFLE(i0, i1, i2, i3)));
+ }
+ template<int i0, int i1, int i2, int i3>
+ __forceinline vint4 shuffle(const vint4& a, const vint4& b) {
+ return vreinterpretq_s32_u8(vqtbl2q_u8( (uint8x16x2_t){(uint8x16_t)a.v, (uint8x16_t)b.v}, _MF_SHUFFLE(i0, i1, i2, i3)));
+ }
+#else
template<int i0, int i1, int i2, int i3>
__forceinline vint4 shuffle(const vint4& v) {
return _mm_shuffle_epi32(v, _MM_SHUFFLE(i3, i2, i1, i0));
@@ -426,7 +460,7 @@ namespace embree
__forceinline vint4 shuffle(const vint4& a, const vint4& b) {
return _mm_castps_si128(_mm_shuffle_ps(_mm_castsi128_ps(a), _mm_castsi128_ps(b), _MM_SHUFFLE(i3, i2, i1, i0)));
}
-
+#endif
#if defined(__SSE3__)
template<> __forceinline vint4 shuffle<0, 0, 2, 2>(const vint4& v) { return _mm_castps_si128(_mm_moveldup_ps(_mm_castsi128_ps(v))); }
template<> __forceinline vint4 shuffle<1, 1, 3, 3>(const vint4& v) { return _mm_castps_si128(_mm_movehdup_ps(_mm_castsi128_ps(v))); }
@@ -438,7 +472,7 @@ namespace embree
return shuffle<i,i,i,i>(v);
}
-#if defined(__SSE4_1__)
+#if defined(__SSE4_1__) && !defined(__aarch64__)
template<int src> __forceinline int extract(const vint4& b) { return _mm_extract_epi32(b, src); }
template<int dst> __forceinline vint4 insert(const vint4& a, const int b) { return _mm_insert_epi32(a, b, dst); }
#else
@@ -446,18 +480,27 @@ namespace embree
template<int dst> __forceinline vint4 insert(const vint4& a, int b) { vint4 c = a; c[dst&3] = b; return c; }
#endif
-
template<> __forceinline int extract<0>(const vint4& b) { return _mm_cvtsi128_si32(b); }
-
+
__forceinline int toScalar(const vint4& v) { return _mm_cvtsi128_si32(v); }
-
- __forceinline size_t toSizeT(const vint4& v) {
+
+#if defined(__aarch64__)
+ __forceinline size_t toSizeT(const vint4& v) {
+ uint64x2_t x = uint64x2_t(v.v);
+ return x[0];
+ }
+#else
+__forceinline size_t toSizeT(const vint4& v) {
#if defined(__WIN32__) && !defined(__X86_64__) // win32 workaround
return toScalar(v);
+#elif defined(__ARM_NEON)
+ // FIXME(LTE): Do we need a swap(i.e. use lane 1)?
+ return vgetq_lane_u64(*(reinterpret_cast<const uint64x2_t *>(&v)), 0);
#else
return _mm_cvtsi128_si64(v);
#endif
}
+#endif
#if defined(__AVX512VL__)
@@ -475,7 +518,17 @@ namespace embree
/// Reductions
////////////////////////////////////////////////////////////////////////////////
-#if defined(__SSE4_1__)
+#if defined(__aarch64__) || defined(__SSE4_1__)
+
+#if defined(__aarch64__)
+ __forceinline vint4 vreduce_min(const vint4& v) { int h = vminvq_s32(v); return vdupq_n_s32(h); }
+ __forceinline vint4 vreduce_max(const vint4& v) { int h = vmaxvq_s32(v); return vdupq_n_s32(h); }
+ __forceinline vint4 vreduce_add(const vint4& v) { int h = vaddvq_s32(v); return vdupq_n_s32(h); }
+
+ __forceinline int reduce_min(const vint4& v) { return vminvq_s32(v); }
+ __forceinline int reduce_max(const vint4& v) { return vmaxvq_s32(v); }
+ __forceinline int reduce_add(const vint4& v) { return vaddvq_s32(v); }
+#else
__forceinline vint4 vreduce_min(const vint4& v) { vint4 h = min(shuffle<1,0,3,2>(v),v); return min(shuffle<2,3,0,1>(h),h); }
__forceinline vint4 vreduce_max(const vint4& v) { vint4 h = max(shuffle<1,0,3,2>(v),v); return max(shuffle<2,3,0,1>(h),h); }
__forceinline vint4 vreduce_add(const vint4& v) { vint4 h = shuffle<1,0,3,2>(v) + v ; return shuffle<2,3,0,1>(h) + h ; }
@@ -483,6 +536,7 @@ namespace embree
__forceinline int reduce_min(const vint4& v) { return toScalar(vreduce_min(v)); }
__forceinline int reduce_max(const vint4& v) { return toScalar(vreduce_max(v)); }
__forceinline int reduce_add(const vint4& v) { return toScalar(vreduce_add(v)); }
+#endif
__forceinline size_t select_min(const vint4& v) { return bsf(movemask(v == vreduce_min(v))); }
__forceinline size_t select_max(const vint4& v) { return bsf(movemask(v == vreduce_max(v))); }
@@ -502,7 +556,7 @@ namespace embree
/// Sorting networks
////////////////////////////////////////////////////////////////////////////////
-#if defined(__SSE4_1__)
+#if (defined(__aarch64__)) || defined(__SSE4_1__)
__forceinline vint4 usort_ascending(const vint4& v)
{
diff --git a/thirdparty/embree/common/simd/vint8_avx.h b/thirdparty/embree/common/simd/vint8_avx.h
index f43e9a8c22..48f5a9b203 100644
--- a/thirdparty/embree/common/simd/vint8_avx.h
+++ b/thirdparty/embree/common/simd/vint8_avx.h
@@ -79,8 +79,8 @@ namespace embree
static __forceinline void store (void* ptr, const vint8& f) { _mm256_store_ps((float*)ptr,_mm256_castsi256_ps(f)); }
static __forceinline void storeu(void* ptr, const vint8& f) { _mm256_storeu_ps((float*)ptr,_mm256_castsi256_ps(f)); }
- static __forceinline void store (const vboolf8& mask, void* ptr, const vint8& f) { _mm256_maskstore_ps((float*)ptr,(__m256i)mask,_mm256_castsi256_ps(f)); }
- static __forceinline void storeu(const vboolf8& mask, void* ptr, const vint8& f) { _mm256_maskstore_ps((float*)ptr,(__m256i)mask,_mm256_castsi256_ps(f)); }
+ static __forceinline void store (const vboolf8& mask, void* ptr, const vint8& f) { _mm256_maskstore_ps((float*)ptr,_mm256_castps_si256(mask.v),_mm256_castsi256_ps(f)); }
+ static __forceinline void storeu(const vboolf8& mask, void* ptr, const vint8& f) { _mm256_maskstore_ps((float*)ptr,_mm256_castps_si256(mask.v),_mm256_castsi256_ps(f)); }
static __forceinline void store_nt(void* ptr, const vint8& v) {
_mm256_stream_ps((float*)ptr,_mm256_castsi256_ps(v));
diff --git a/thirdparty/embree/common/simd/vint8_avx2.h b/thirdparty/embree/common/simd/vint8_avx2.h
index e04737ffbe..d48efac3f4 100644
--- a/thirdparty/embree/common/simd/vint8_avx2.h
+++ b/thirdparty/embree/common/simd/vint8_avx2.h
@@ -393,6 +393,7 @@ namespace embree
__forceinline int toScalar(const vint8& v) { return _mm_cvtsi128_si32(_mm256_castsi256_si128(v)); }
+#if !defined(__aarch64__)
__forceinline vint8 permute(const vint8& v, const __m256i& index) {
return _mm256_permutevar8x32_epi32(v, index);
}
@@ -410,6 +411,9 @@ namespace embree
#endif
}
+#endif
+
+
////////////////////////////////////////////////////////////////////////////////
/// Reductions
////////////////////////////////////////////////////////////////////////////////
diff --git a/thirdparty/embree/common/simd/vuint4_sse2.h b/thirdparty/embree/common/simd/vuint4_sse2.h
index 0601b9ab80..f7817da6be 100644
--- a/thirdparty/embree/common/simd/vuint4_sse2.h
+++ b/thirdparty/embree/common/simd/vuint4_sse2.h
@@ -95,7 +95,14 @@ namespace embree
static __forceinline void storeu(const vboolf4& mask, void* ptr, const vuint4& i) { storeu(ptr,select(mask,i,loadu(ptr))); }
#endif
-#if defined(__SSE4_1__)
+#if defined(__aarch64__)
+ static __forceinline vuint4 load(const unsigned char* ptr) {
+ return _mm_load4epu8_epi32(((__m128i*)ptr));
+ }
+ static __forceinline vuint4 loadu(const unsigned char* ptr) {
+ return _mm_load4epu8_epi32(((__m128i*)ptr));
+ }
+#elif defined(__SSE4_1__)
static __forceinline vuint4 load(const unsigned char* ptr) {
return _mm_cvtepu8_epi32(_mm_loadl_epi64((__m128i*)ptr));
}
@@ -107,7 +114,9 @@ namespace embree
#endif
static __forceinline vuint4 load(const unsigned short* ptr) {
-#if defined (__SSE4_1__)
+#if defined(__aarch64__)
+ return _mm_load4epu16_epi32(((__m128i*)ptr));
+#elif defined (__SSE4_1__)
return _mm_cvtepu16_epi32(_mm_loadu_si128((__m128i*)ptr));
#else
return vuint4(ptr[0],ptr[1],ptr[2],ptr[3]);
@@ -115,7 +124,7 @@ namespace embree
}
static __forceinline vuint4 load_nt(void* ptr) {
-#if defined(__SSE4_1__)
+#if (defined(__aarch64__)) || defined(__SSE4_1__)
return _mm_stream_load_si128((__m128i*)ptr);
#else
return _mm_load_si128((__m128i*)ptr);
@@ -123,8 +132,8 @@ namespace embree
}
static __forceinline void store_nt(void* ptr, const vuint4& v) {
-#if defined(__SSE4_1__)
- _mm_stream_ps((float*)ptr,_mm_castsi128_ps(v));
+#if !defined(__aarch64__) && defined(__SSE4_1__)
+ _mm_stream_ps((float*)ptr, _mm_castsi128_ps(v));
#else
_mm_store_si128((__m128i*)ptr,v);
#endif
@@ -132,7 +141,7 @@ namespace embree
template<int scale = 4>
static __forceinline vuint4 gather(const unsigned int* ptr, const vint4& index) {
-#if defined(__AVX2__)
+#if defined(__AVX2__) && !defined(__aarch64__)
return _mm_i32gather_epi32((const int*)ptr, index, scale);
#else
return vuint4(
@@ -148,7 +157,7 @@ namespace embree
vuint4 r = zero;
#if defined(__AVX512VL__)
return _mm_mmask_i32gather_epi32(r, mask, index, ptr, scale);
-#elif defined(__AVX2__)
+#elif defined(__AVX2__) && !defined(__aarch64__)
return _mm_mask_i32gather_epi32(r, (const int*)ptr, index, mask, scale);
#else
if (likely(mask[0])) r[0] = *(unsigned int*)(((char*)ptr)+scale*index[0]);
@@ -344,6 +353,16 @@ namespace embree
__forceinline vuint4 unpacklo(const vuint4& a, const vuint4& b) { return _mm_castps_si128(_mm_unpacklo_ps(_mm_castsi128_ps(a), _mm_castsi128_ps(b))); }
__forceinline vuint4 unpackhi(const vuint4& a, const vuint4& b) { return _mm_castps_si128(_mm_unpackhi_ps(_mm_castsi128_ps(a), _mm_castsi128_ps(b))); }
+#if defined(__aarch64__)
+ template<int i0, int i1, int i2, int i3>
+ __forceinline vuint4 shuffle(const vuint4& v) {
+ return vreinterpretq_s32_u8(vqtbl1q_u8( (uint8x16_t)v.v, _MN_SHUFFLE(i0, i1, i2, i3)));
+ }
+ template<int i0, int i1, int i2, int i3>
+ __forceinline vuint4 shuffle(const vuint4& a, const vuint4& b) {
+ return vreinterpretq_s32_u8(vqtbl2q_u8( (uint8x16x2_t){(uint8x16_t)a.v, (uint8x16_t)b.v}, _MF_SHUFFLE(i0, i1, i2, i3)));
+ }
+#else
template<int i0, int i1, int i2, int i3>
__forceinline vuint4 shuffle(const vuint4& v) {
return _mm_shuffle_epi32(v, _MM_SHUFFLE(i3, i2, i1, i0));
@@ -353,7 +372,7 @@ namespace embree
__forceinline vuint4 shuffle(const vuint4& a, const vuint4& b) {
return _mm_castps_si128(_mm_shuffle_ps(_mm_castsi128_ps(a), _mm_castsi128_ps(b), _MM_SHUFFLE(i3, i2, i1, i0)));
}
-
+#endif
#if defined(__SSE3__)
template<> __forceinline vuint4 shuffle<0, 0, 2, 2>(const vuint4& v) { return _mm_castps_si128(_mm_moveldup_ps(_mm_castsi128_ps(v))); }
template<> __forceinline vuint4 shuffle<1, 1, 3, 3>(const vuint4& v) { return _mm_castps_si128(_mm_movehdup_ps(_mm_castsi128_ps(v))); }
@@ -365,7 +384,7 @@ namespace embree
return shuffle<i,i,i,i>(v);
}
-#if defined(__SSE4_1__)
+#if defined(__SSE4_1__) && !defined(__aarch64__)
template<int src> __forceinline unsigned int extract(const vuint4& b) { return _mm_extract_epi32(b, src); }
template<int dst> __forceinline vuint4 insert(const vuint4& a, const unsigned b) { return _mm_insert_epi32(a, b, dst); }
#else
@@ -373,7 +392,6 @@ namespace embree
template<int dst> __forceinline vuint4 insert(const vuint4& a, const unsigned b) { vuint4 c = a; c[dst&3] = b; return c; }
#endif
-
template<> __forceinline unsigned int extract<0>(const vuint4& b) { return _mm_cvtsi128_si32(b); }
__forceinline unsigned int toScalar(const vuint4& v) { return _mm_cvtsi128_si32(v); }
diff --git a/thirdparty/embree/common/simd/vuint8_avx.h b/thirdparty/embree/common/simd/vuint8_avx.h
index 589cd9d731..cb8b5158c1 100644
--- a/thirdparty/embree/common/simd/vuint8_avx.h
+++ b/thirdparty/embree/common/simd/vuint8_avx.h
@@ -77,8 +77,8 @@ namespace embree
static __forceinline void store (void* ptr, const vuint8& f) { _mm256_store_ps((float*)ptr,_mm256_castsi256_ps(f)); }
static __forceinline void storeu(void* ptr, const vuint8& f) { _mm256_storeu_ps((float*)ptr,_mm256_castsi256_ps(f)); }
- static __forceinline void store (const vboolf8& mask, void* ptr, const vuint8& f) { _mm256_maskstore_ps((float*)ptr,(__m256i)mask,_mm256_castsi256_ps(f)); }
- static __forceinline void storeu(const vboolf8& mask, void* ptr, const vuint8& f) { _mm256_maskstore_ps((float*)ptr,(__m256i)mask,_mm256_castsi256_ps(f)); }
+ static __forceinline void store (const vboolf8& mask, void* ptr, const vuint8& f) { _mm256_maskstore_ps((float*)ptr,_mm256_castps_si256(mask.v),_mm256_castsi256_ps(f)); }
+ static __forceinline void storeu(const vboolf8& mask, void* ptr, const vuint8& f) { _mm256_maskstore_ps((float*)ptr,_mm256_castps_si256(mask.v),_mm256_castsi256_ps(f)); }
static __forceinline void store_nt(void* ptr, const vuint8& v) {
_mm256_stream_ps((float*)ptr,_mm256_castsi256_ps(v));
diff --git a/thirdparty/embree/common/simd/vuint8_avx2.h b/thirdparty/embree/common/simd/vuint8_avx2.h
index 17b994522f..959143724b 100644
--- a/thirdparty/embree/common/simd/vuint8_avx2.h
+++ b/thirdparty/embree/common/simd/vuint8_avx2.h
@@ -385,6 +385,7 @@ namespace embree
__forceinline int toScalar(const vuint8& v) { return _mm_cvtsi128_si32(_mm256_castsi256_si128(v)); }
+#if !defined(__aarch64__)
__forceinline vuint8 permute(const vuint8& v, const __m256i& index) {
return _mm256_permutevar8x32_epi32(v, index);
}
@@ -401,6 +402,7 @@ namespace embree
return _mm256_alignr_epi8(a, b, 4*i);
#endif
}
+#endif // !defined(__aarch64__)
////////////////////////////////////////////////////////////////////////////////
/// Reductions
diff --git a/thirdparty/embree/common/simd/wasm/emulation.h b/thirdparty/embree/common/simd/wasm/emulation.h
new file mode 100644
index 0000000000..778ab4ae6a
--- /dev/null
+++ b/thirdparty/embree/common/simd/wasm/emulation.h
@@ -0,0 +1,13 @@
+// Copyright 2009-2020 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+// According to https://emscripten.org/docs/porting/simd.html, _MM_SET_EXCEPTION_MASK and
+// _mm_setcsr are unavailable in WebAssembly.
+
+#define _MM_SET_EXCEPTION_MASK(x)
+
+__forceinline void _mm_setcsr(unsigned int)
+{
+}
diff --git a/thirdparty/embree/common/sys/array.h b/thirdparty/embree/common/sys/array.h
index dd9190c52a..e96939b63d 100644
--- a/thirdparty/embree/common/sys/array.h
+++ b/thirdparty/embree/common/sys/array.h
@@ -59,8 +59,8 @@ namespace embree
/********************** Iterators ****************************/
- __forceinline T* begin() const { return items; };
- __forceinline T* end () const { return items+M; };
+ __forceinline T* begin() const { return (T*)items; };
+ __forceinline T* end () const { return (T*)items+M; };
/********************** Capacity ****************************/
@@ -101,8 +101,8 @@ namespace embree
__forceinline T& at(size_t i) { assert(i < M); return items[i]; }
__forceinline const T& at(size_t i) const { assert(i < M); return items[i]; }
- __forceinline T& front() const { assert(M > 0); return items[0]; };
- __forceinline T& back () const { assert(M > 0); return items[M-1]; };
+ __forceinline T& front() { assert(M > 0); return items[0]; };
+ __forceinline T& back () { assert(M > 0); return items[M-1]; };
__forceinline T* data() { return items; };
__forceinline const T* data() const { return items; };
@@ -139,7 +139,7 @@ namespace embree
__forceinline Ty& operator[](const unsigned i) { assert(i<N); return data[i]; }
__forceinline const Ty& operator[](const unsigned i) const { assert(i<N); return data[i]; }
-#if defined(__64BIT__)
+#if defined(__64BIT__) || defined(__EMSCRIPTEN__)
__forceinline Ty& operator[](const size_t i) { assert(i<N); return data[i]; }
__forceinline const Ty& operator[](const size_t i) const { assert(i<N); return data[i]; }
#endif
@@ -196,7 +196,7 @@ namespace embree
__forceinline Ty& operator[](const int i) { assert(i>=0 && i<max_total_elements); resize(i+1); return data[i]; }
__forceinline Ty& operator[](const unsigned i) { assert(i<max_total_elements); resize(i+1); return data[i]; }
-#if defined(__64BIT__)
+#if defined(__64BIT__) || defined(__EMSCRIPTEN__)
__forceinline Ty& operator[](const size_t i) { assert(i<max_total_elements); resize(i+1); return data[i]; }
#endif
diff --git a/thirdparty/embree/common/sys/barrier.h b/thirdparty/embree/common/sys/barrier.h
index 37fc036291..c56513a2ed 100644
--- a/thirdparty/embree/common/sys/barrier.h
+++ b/thirdparty/embree/common/sys/barrier.h
@@ -24,7 +24,7 @@ namespace embree
BarrierSys& operator= (const BarrierSys& other) DELETED; // do not implement
public:
- /*! intializes the barrier with some number of threads */
+ /*! initializes the barrier with some number of threads */
void init(size_t count);
/*! lets calling thread wait in barrier */
@@ -94,7 +94,7 @@ namespace embree
LinearBarrierActive& operator= (const LinearBarrierActive& other) DELETED; // do not implement
public:
- /*! intializes the barrier with some number of threads */
+ /*! initializes the barrier with some number of threads */
void init(size_t threadCount);
/*! thread with threadIndex waits in the barrier */
diff --git a/thirdparty/embree/common/sys/intrinsics.h b/thirdparty/embree/common/sys/intrinsics.h
index ed8dd7d40a..2c2f6eccda 100644
--- a/thirdparty/embree/common/sys/intrinsics.h
+++ b/thirdparty/embree/common/sys/intrinsics.h
@@ -13,6 +13,9 @@
#include "../simd/arm/emulation.h"
#else
#include <immintrin.h>
+#if defined(__EMSCRIPTEN__)
+#include "../simd/wasm/emulation.h"
+#endif
#endif
#if defined(__BMI__) && defined(__GNUC__) && !defined(__INTEL_COMPILER)
@@ -24,24 +27,26 @@
#endif
#endif
-#if defined(__LZCNT__)
+#if defined(__aarch64__)
#if !defined(_lzcnt_u32)
- #define _lzcnt_u32 __lzcnt32
+ #define _lzcnt_u32 __builtin_clz
#endif
- #if !defined(_lzcnt_u64)
- #define _lzcnt_u64 __lzcnt64
+#else
+ #if defined(__LZCNT__)
+ #if !defined(_lzcnt_u32)
+ #define _lzcnt_u32 __lzcnt32
+ #endif
+ #if !defined(_lzcnt_u64)
+ #define _lzcnt_u64 __lzcnt64
+ #endif
#endif
#endif
#if defined(__WIN32__)
-// -- GODOT start --
-#if !defined(NOMINMAX)
-// -- GODOT end --
-#define NOMINMAX
-// -- GODOT start --
-#endif
-#include "windows.h"
-// -- GODOT end --
+# if !defined(NOMINMAX)
+# define NOMINMAX
+# endif
+# include <windows.h>
#endif
/* normally defined in pmmintrin.h, but we always need this */
@@ -69,7 +74,7 @@ namespace embree
}
__forceinline int bsf(int v) {
-#if defined(__AVX2__)
+#if defined(__AVX2__) && !defined(__aarch64__)
return _tzcnt_u32(v);
#else
unsigned long r = 0; _BitScanForward(&r,v); return r;
@@ -77,7 +82,7 @@ namespace embree
}
__forceinline unsigned bsf(unsigned v) {
-#if defined(__AVX2__)
+#if defined(__AVX2__) && !defined(__aarch64__)
return _tzcnt_u32(v);
#else
unsigned long r = 0; _BitScanForward(&r,v); return r;
@@ -118,7 +123,7 @@ namespace embree
#endif
__forceinline int bsr(int v) {
-#if defined(__AVX2__)
+#if defined(__AVX2__) && !defined(__aarch64__)
return 31 - _lzcnt_u32(v);
#else
unsigned long r = 0; _BitScanReverse(&r,v); return r;
@@ -126,7 +131,7 @@ namespace embree
}
__forceinline unsigned bsr(unsigned v) {
-#if defined(__AVX2__)
+#if defined(__AVX2__) && !defined(__aarch64__)
return 31 - _lzcnt_u32(v);
#else
unsigned long r = 0; _BitScanReverse(&r,v); return r;
@@ -145,7 +150,7 @@ namespace embree
__forceinline int lzcnt(const int x)
{
-#if defined(__AVX2__)
+#if defined(__AVX2__) && !defined(__aarch64__)
return _lzcnt_u32(x);
#else
if (unlikely(x == 0)) return 32;
@@ -214,15 +219,26 @@ namespace embree
#elif defined(__X86_ASM__)
__forceinline void __cpuid(int out[4], int op) {
- asm volatile ("cpuid" : "=a"(out[0]), "=b"(out[1]), "=c"(out[2]), "=d"(out[3]) : "a"(op));
+#if defined(__ARM_NEON)
+ if (op == 0) { // Get CPU name
+ out[0] = 0x41524d20;
+ out[1] = 0x41524d20;
+ out[2] = 0x41524d20;
+ out[3] = 0x41524d20;
+ }
+#else
+ asm volatile ("cpuid" : "=a"(out[0]), "=b"(out[1]), "=c"(out[2]), "=d"(out[3]) : "a"(op));
+#endif
}
-
+
+#if !defined(__ARM_NEON)
__forceinline void __cpuid_count(int out[4], int op1, int op2) {
asm volatile ("cpuid" : "=a"(out[0]), "=b"(out[1]), "=c"(out[2]), "=d"(out[3]) : "a"(op1), "c"(op2));
}
-
#endif
-
+
+#endif
+
__forceinline uint64_t read_tsc() {
#if defined(__X86_ASM__)
uint32_t high,low;
@@ -235,30 +251,38 @@ namespace embree
}
__forceinline int bsf(int v) {
-#if defined(__AVX2__)
+#if defined(__ARM_NEON)
+ return __builtin_ctz(v);
+#else
+#if defined(__AVX2__)
return _tzcnt_u32(v);
#elif defined(__X86_ASM__)
int r = 0; asm ("bsf %1,%0" : "=r"(r) : "r"(v)); return r;
#else
return __builtin_ctz(v);
#endif
+#endif
}
#if defined(__64BIT__)
__forceinline unsigned bsf(unsigned v)
{
-#if defined(__AVX2__)
+#if defined(__ARM_NEON)
+ return __builtin_ctz(v);
+#else
+#if defined(__AVX2__)
return _tzcnt_u32(v);
#elif defined(__X86_ASM__)
unsigned r = 0; asm ("bsf %1,%0" : "=r"(r) : "r"(v)); return r;
#else
return __builtin_ctz(v);
#endif
+#endif
}
#endif
__forceinline size_t bsf(size_t v) {
-#if defined(__AVX2__)
+#if defined(__AVX2__) && !defined(__aarch64__)
#if defined(__X86_64__)
return _tzcnt_u64(v);
#else
@@ -295,7 +319,7 @@ namespace embree
}
__forceinline int bsr(int v) {
-#if defined(__AVX2__)
+#if defined(__AVX2__) && !defined(__aarch64__)
return 31 - _lzcnt_u32(v);
#elif defined(__X86_ASM__)
int r = 0; asm ("bsr %1,%0" : "=r"(r) : "r"(v)); return r;
@@ -304,7 +328,7 @@ namespace embree
#endif
}
-#if defined(__64BIT__)
+#if defined(__64BIT__) || defined(__EMSCRIPTEN__)
__forceinline unsigned bsr(unsigned v) {
#if defined(__AVX2__)
return 31 - _lzcnt_u32(v);
@@ -317,7 +341,7 @@ namespace embree
#endif
__forceinline size_t bsr(size_t v) {
-#if defined(__AVX2__)
+#if defined(__AVX2__) && !defined(__aarch64__)
#if defined(__X86_64__)
return 63 - _lzcnt_u64(v);
#else
@@ -332,7 +356,7 @@ namespace embree
__forceinline int lzcnt(const int x)
{
-#if defined(__AVX2__)
+#if defined(__AVX2__) && !defined(__aarch64__)
return _lzcnt_u32(x);
#else
if (unlikely(x == 0)) return 32;
@@ -341,18 +365,18 @@ namespace embree
}
__forceinline size_t blsr(size_t v) {
-#if defined(__AVX2__)
-#if defined(__INTEL_COMPILER)
+#if defined(__AVX2__) && !defined(__aarch64__)
+ #if defined(__INTEL_COMPILER)
return _blsr_u64(v);
+ #else
+ #if defined(__X86_64__)
+ return __blsr_u64(v);
+ #else
+ return __blsr_u32(v);
+ #endif
+ #endif
#else
-#if defined(__X86_64__)
- return __blsr_u64(v);
-#else
- return __blsr_u32(v);
-#endif
-#endif
-#else
- return v & (v-1);
+ return v & (v-1);
#endif
}
@@ -368,7 +392,7 @@ namespace embree
#if defined(__X86_ASM__)
int r = 0; asm ("bts %1,%0" : "=r"(r) : "r"(i), "0"(v) : "flags"); return r;
#else
- return (v | (v << i));
+ return (v | (1 << i));
#endif
}
@@ -376,7 +400,7 @@ namespace embree
#if defined(__X86_ASM__)
int r = 0; asm ("btr %1,%0" : "=r"(r) : "r"(i), "0"(v) : "flags"); return r;
#else
- return (v & ~(v << i));
+ return (v & ~(1 << i));
#endif
}
@@ -392,7 +416,7 @@ namespace embree
#if defined(__X86_ASM__)
size_t r = 0; asm ("bts %1,%0" : "=r"(r) : "r"(i), "0"(v) : "flags"); return r;
#else
- return (v | (v << i));
+ return (v | (1 << i));
#endif
}
@@ -400,7 +424,7 @@ namespace embree
#if defined(__X86_ASM__)
size_t r = 0; asm ("btr %1,%0" : "=r"(r) : "r"(i), "0"(v) : "flags"); return r;
#else
- return (v & ~(v << i));
+ return (v & ~(1 << i));
#endif
}
@@ -435,8 +459,8 @@ namespace embree
#endif
#endif
-#if defined(__SSE4_2__)
-
+#if defined(__SSE4_2__) || defined(__ARM_NEON)
+
__forceinline int popcnt(int in) {
return _mm_popcnt_u32(in);
}
@@ -483,14 +507,14 @@ namespace embree
#endif
}
- __forceinline void prefetchL1EX(const void* ptr) {
- prefetchEX(ptr);
+ __forceinline void prefetchL1EX(const void* ptr) {
+ prefetchEX(ptr);
}
-
- __forceinline void prefetchL2EX(const void* ptr) {
- prefetchEX(ptr);
+
+ __forceinline void prefetchL2EX(const void* ptr) {
+ prefetchEX(ptr);
}
-#if defined(__AVX2__)
+#if defined(__AVX2__) && !defined(__aarch64__)
__forceinline unsigned int pext(unsigned int a, unsigned int b) { return _pext_u32(a, b); }
__forceinline unsigned int pdep(unsigned int a, unsigned int b) { return _pdep_u32(a, b); }
#if defined(__X86_64__)
diff --git a/thirdparty/embree/common/sys/mutex.cpp b/thirdparty/embree/common/sys/mutex.cpp
index 789feaf2d8..8212deaa49 100644
--- a/thirdparty/embree/common/sys/mutex.cpp
+++ b/thirdparty/embree/common/sys/mutex.cpp
@@ -36,6 +36,7 @@ namespace embree
MAYBE_UNUSED bool ok = pthread_mutex_destroy((pthread_mutex_t*)mutex) == 0;
assert(ok);
delete (pthread_mutex_t*)mutex;
+ mutex = nullptr;
}
void MutexSys::lock()
diff --git a/thirdparty/embree/common/sys/mutex.h b/thirdparty/embree/common/sys/mutex.h
index 4cb3626d92..26af6c582c 100644
--- a/thirdparty/embree/common/sys/mutex.h
+++ b/thirdparty/embree/common/sys/mutex.h
@@ -7,6 +7,7 @@
#include "intrinsics.h"
#include "atomic.h"
+#define CPU_CACHELINE_SIZE 64
namespace embree
{
/*! system mutex */
@@ -83,6 +84,11 @@ namespace embree
atomic<bool> flag;
};
+ class PaddedSpinLock : public SpinLock
+ {
+ private:
+ char padding[CPU_CACHELINE_SIZE - sizeof(SpinLock)];
+ };
/*! safe mutex lock and unlock helper */
template<typename Mutex> class Lock {
public:
diff --git a/thirdparty/embree/common/sys/platform.h b/thirdparty/embree/common/sys/platform.h
index 3e386c4944..728bf6ed7d 100644
--- a/thirdparty/embree/common/sys/platform.h
+++ b/thirdparty/embree/common/sys/platform.h
@@ -92,16 +92,19 @@
////////////////////////////////////////////////////////////////////////////////
#ifdef __WIN32__
-#define dll_export __declspec(dllexport)
-#define dll_import __declspec(dllimport)
+# if defined(EMBREE_STATIC_LIB)
+# define dll_export
+# define dll_import
+# else
+# define dll_export __declspec(dllexport)
+# define dll_import __declspec(dllimport)
+# endif
#else
-#define dll_export __attribute__ ((visibility ("default")))
-#define dll_import
+# define dll_export __attribute__ ((visibility ("default")))
+# define dll_import
#endif
-// -- GODOT start --
#if defined(__WIN32__) && !defined(__MINGW32__)
-// -- GODOT end --
#if !defined(__noinline)
#define __noinline __declspec(noinline)
#endif
@@ -151,9 +154,7 @@
#define DELETED = delete
#endif
-// -- GODOT start --
#if !defined(likely)
-// -- GODOT end --
#if defined(_MSC_VER) && !defined(__INTEL_COMPILER)
#define likely(expr) (expr)
#define unlikely(expr) (expr)
@@ -161,9 +162,7 @@
#define likely(expr) __builtin_expect((bool)(expr),true )
#define unlikely(expr) __builtin_expect((bool)(expr),false)
#endif
-// -- GODOT start --
#endif
-// -- GODOT end --
////////////////////////////////////////////////////////////////////////////////
/// Error handling and debugging
@@ -252,6 +251,7 @@ __forceinline std::string toString(long long value) {
#pragma warning(disable:4800) // forcing value to bool 'true' or 'false' (performance warning)
//#pragma warning(disable:4267) // '=' : conversion from 'size_t' to 'unsigned long', possible loss of data
#pragma warning(disable:4244) // 'argument' : conversion from 'ssize_t' to 'unsigned int', possible loss of data
+#pragma warning(disable:4267) // conversion from 'size_t' to 'const int', possible loss of data
//#pragma warning(disable:4355) // 'this' : used in base member initializer list
//#pragma warning(disable:391 ) // '<=' : signed / unsigned mismatch
//#pragma warning(disable:4018) // '<' : signed / unsigned mismatch
diff --git a/thirdparty/embree/common/sys/sysinfo.cpp b/thirdparty/embree/common/sys/sysinfo.cpp
index f1a59e511e..7f7a009a1e 100644
--- a/thirdparty/embree/common/sys/sysinfo.cpp
+++ b/thirdparty/embree/common/sys/sysinfo.cpp
@@ -21,7 +21,11 @@ namespace embree
std::string getPlatformName()
{
-#if defined(__LINUX__) && !defined(__64BIT__)
+#if defined(__ANDROID__) && !defined(__64BIT__)
+ return "Android (32bit)";
+#elif defined(__ANDROID__) && defined(__64BIT__)
+ return "Android (64bit)";
+#elif defined(__LINUX__) && !defined(__64BIT__)
return "Linux (32bit)";
#elif defined(__LINUX__) && defined(__64BIT__)
return "Linux (64bit)";
@@ -248,9 +252,7 @@ namespace embree
#if defined(__X86_ASM__)
__noinline int64_t get_xcr0()
{
-// -- GODOT start --
-#if defined (__WIN32__) && !defined (__MINGW32__)
-// -- GODOT end --
+#if defined (__WIN32__) && !defined (__MINGW32__) && defined(_XCR_XFEATURE_ENABLED_MASK)
int64_t xcr0 = 0; // int64_t is workaround for compiler bug under VS2013, Win32
xcr0 = _xgetbv(0);
return xcr0;
@@ -337,9 +339,24 @@ namespace embree
if (cpuid_leaf_7[ECX] & CPU_FEATURE_BIT_AVX512VBMI) cpu_features |= CPU_FEATURE_AVX512VBMI;
return cpu_features;
-#elif defined(__ARM_NEON)
- /* emulated features with sse2neon */
- return CPU_FEATURE_SSE|CPU_FEATURE_SSE2|CPU_FEATURE_XMM_ENABLED;
+
+#elif defined(__ARM_NEON) || defined(__EMSCRIPTEN__)
+
+ int cpu_features = CPU_FEATURE_NEON|CPU_FEATURE_SSE|CPU_FEATURE_SSE2;
+ cpu_features |= CPU_FEATURE_SSE3|CPU_FEATURE_SSSE3|CPU_FEATURE_SSE42;
+ cpu_features |= CPU_FEATURE_XMM_ENABLED;
+ cpu_features |= CPU_FEATURE_YMM_ENABLED;
+ cpu_features |= CPU_FEATURE_SSE41 | CPU_FEATURE_RDRAND | CPU_FEATURE_F16C;
+ cpu_features |= CPU_FEATURE_POPCNT;
+ cpu_features |= CPU_FEATURE_AVX;
+ cpu_features |= CPU_FEATURE_AVX2;
+ cpu_features |= CPU_FEATURE_FMA3;
+ cpu_features |= CPU_FEATURE_LZCNT;
+ cpu_features |= CPU_FEATURE_BMI1;
+ cpu_features |= CPU_FEATURE_BMI2;
+ cpu_features |= CPU_FEATURE_NEON_2X;
+ return cpu_features;
+
#else
/* Unknown CPU. */
return 0;
@@ -376,6 +393,8 @@ namespace embree
if (features & CPU_FEATURE_AVX512VL) str += "AVX512VL ";
if (features & CPU_FEATURE_AVX512IFMA) str += "AVX512IFMA ";
if (features & CPU_FEATURE_AVX512VBMI) str += "AVX512VBMI ";
+ if (features & CPU_FEATURE_NEON) str += "NEON ";
+ if (features & CPU_FEATURE_NEON_2X) str += "2xNEON ";
return str;
}
@@ -390,6 +409,9 @@ namespace embree
if (isa == AVX) return "AVX";
if (isa == AVX2) return "AVX2";
if (isa == AVX512) return "AVX512";
+
+ if (isa == NEON) return "NEON";
+ if (isa == NEON_2X) return "2xNEON";
return "UNKNOWN";
}
@@ -410,6 +432,9 @@ namespace embree
if (hasISA(features,AVXI)) v += "AVXI ";
if (hasISA(features,AVX2)) v += "AVX2 ";
if (hasISA(features,AVX512)) v += "AVX512 ";
+
+ if (hasISA(features,NEON)) v += "NEON ";
+ if (hasISA(features,NEON_2X)) v += "2xNEON ";
return v;
}
}
@@ -613,6 +638,16 @@ namespace embree
#include <sys/time.h>
#include <pthread.h>
+#if defined(__EMSCRIPTEN__)
+#include <emscripten.h>
+
+// -- GODOT start --
+extern "C" {
+extern int godot_js_os_hw_concurrency_get();
+}
+// -- GODOT end --
+#endif
+
namespace embree
{
unsigned int getNumberOfLogicalThreads()
@@ -620,12 +655,13 @@ namespace embree
static int nThreads = -1;
if (nThreads != -1) return nThreads;
-// -- GODOT start --
-// #if defined(__MACOSX__)
#if defined(__MACOSX__) || defined(__ANDROID__)
-// -- GODOT end --
nThreads = sysconf(_SC_NPROCESSORS_ONLN); // does not work in Linux LXC container
assert(nThreads);
+#elif defined(__EMSCRIPTEN__)
+ // -- GODOT start --
+ nThreads = godot_js_os_hw_concurrency_get();
+ // -- GODOT end --
#else
cpu_set_t set;
if (pthread_getaffinity_np(pthread_self(), sizeof(set), &set) == 0)
diff --git a/thirdparty/embree/common/sys/sysinfo.h b/thirdparty/embree/common/sys/sysinfo.h
index 72351d12e4..cefd39a0f6 100644
--- a/thirdparty/embree/common/sys/sysinfo.h
+++ b/thirdparty/embree/common/sys/sysinfo.h
@@ -55,7 +55,12 @@
# define isa sse
# define ISA SSE
# define ISA_STR "SSE"
-#else
+#elif defined(__ARM_NEON)
+// NOTE(LTE): Use sse2 for `isa` for the compatibility at the moment.
+#define isa sse2
+#define ISA NEON
+#define ISA_STR "NEON"
+#else
#error Unknown ISA
#endif
@@ -133,7 +138,9 @@ namespace embree
static const int CPU_FEATURE_XMM_ENABLED = 1 << 25;
static const int CPU_FEATURE_YMM_ENABLED = 1 << 26;
static const int CPU_FEATURE_ZMM_ENABLED = 1 << 27;
-
+ static const int CPU_FEATURE_NEON = 1 << 28;
+ static const int CPU_FEATURE_NEON_2X = 1 << 29;
+
/*! get CPU features */
int getCPUFeatures();
@@ -154,6 +161,8 @@ namespace embree
static const int AVXI = AVX | CPU_FEATURE_F16C | CPU_FEATURE_RDRAND;
static const int AVX2 = AVXI | CPU_FEATURE_AVX2 | CPU_FEATURE_FMA3 | CPU_FEATURE_BMI1 | CPU_FEATURE_BMI2 | CPU_FEATURE_LZCNT;
static const int AVX512 = AVX2 | CPU_FEATURE_AVX512F | CPU_FEATURE_AVX512DQ | CPU_FEATURE_AVX512CD | CPU_FEATURE_AVX512BW | CPU_FEATURE_AVX512VL | CPU_FEATURE_ZMM_ENABLED;
+ static const int NEON = CPU_FEATURE_NEON | CPU_FEATURE_SSE | CPU_FEATURE_SSE2;
+ static const int NEON_2X = CPU_FEATURE_NEON_2X | AVX2;
/*! converts ISA bitvector into a string */
std::string stringOfISA(int features);
diff --git a/thirdparty/embree/common/sys/thread.cpp b/thirdparty/embree/common/sys/thread.cpp
index f4014be89b..530c3c7810 100644
--- a/thirdparty/embree/common/sys/thread.cpp
+++ b/thirdparty/embree/common/sys/thread.cpp
@@ -10,6 +10,9 @@
#include "../simd/arm/emulation.h"
#else
#include <xmmintrin.h>
+#if defined(__EMSCRIPTEN__)
+#include "../simd/wasm/emulation.h"
+#endif
#endif
#if defined(PTHREADS_WIN32)
@@ -158,9 +161,7 @@ namespace embree
/// Linux Platform
////////////////////////////////////////////////////////////////////////////////
-// -- GODOT start --
#if defined(__LINUX__) && !defined(__ANDROID__)
-// -- GODOT end --
#include <fstream>
#include <sstream>
@@ -219,6 +220,8 @@ namespace embree
/* find correct thread to affinitize to */
cpu_set_t set;
+ CPU_ZERO(&set);
+
if (pthread_getaffinity_np(pthread_self(), sizeof(set), &set) == 0)
{
for (int i=0, j=0; i<CPU_SETSIZE; i++)
@@ -241,7 +244,8 @@ namespace embree
{
cpu_set_t cset;
CPU_ZERO(&cset);
- size_t threadID = mapThreadID(affinity);
+ //size_t threadID = mapThreadID(affinity); // this is not working properly in LXC containers when some processors are disabled
+ size_t threadID = affinity;
CPU_SET(threadID, &cset);
pthread_setaffinity_np(pthread_self(), sizeof(cset), &cset);
@@ -249,7 +253,6 @@ namespace embree
}
#endif
-// -- GODOT start --
////////////////////////////////////////////////////////////////////////////////
/// Android Platform
////////////////////////////////////////////////////////////////////////////////
@@ -269,7 +272,6 @@ namespace embree
}
}
#endif
-// -- GODOT end --
////////////////////////////////////////////////////////////////////////////////
/// FreeBSD Platform
@@ -294,6 +296,21 @@ namespace embree
#endif
////////////////////////////////////////////////////////////////////////////////
+/// WebAssembly Platform
+////////////////////////////////////////////////////////////////////////////////
+
+#if defined(__EMSCRIPTEN__)
+namespace embree
+{
+ /*! set affinity of the calling thread */
+ void setAffinity(ssize_t affinity)
+ {
+ // Setting thread affinity is not supported in WASM.
+ }
+}
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
/// MacOSX Platform
////////////////////////////////////////////////////////////////////////////////
@@ -379,9 +396,7 @@ namespace embree
pthread_attr_destroy(&attr);
/* set affinity */
-// -- GODOT start --
#if defined(__LINUX__) && !defined(__ANDROID__)
-// -- GODOT end --
if (threadID >= 0) {
cpu_set_t cset;
CPU_ZERO(&cset);
@@ -396,7 +411,6 @@ namespace embree
CPU_SET(threadID, &cset);
pthread_setaffinity_np(*tid, sizeof(cset), &cset);
}
-// -- GODOT start --
#elif defined(__ANDROID__)
if (threadID >= 0) {
cpu_set_t cset;
@@ -405,7 +419,6 @@ namespace embree
sched_setaffinity(pthread_gettid_np(*tid), sizeof(cset), &cset);
}
#endif
-// -- GODOT end --
return thread_t(tid);
}
@@ -424,14 +437,12 @@ namespace embree
/*! destroy a hardware thread by its handle */
void destroyThread(thread_t tid) {
-// -- GODOT start --
#if defined(__ANDROID__)
- FATAL("Can't destroy threads on Android.");
+ FATAL("Can't destroy threads on Android."); // pthread_cancel not implemented.
#else
pthread_cancel(*(pthread_t*)tid);
delete (pthread_t*)tid;
#endif
-// -- GODOT end --
}
/*! creates thread local storage */
diff --git a/thirdparty/embree/common/sys/vector.h b/thirdparty/embree/common/sys/vector.h
index f832626789..d05e1deb18 100644
--- a/thirdparty/embree/common/sys/vector.h
+++ b/thirdparty/embree/common/sys/vector.h
@@ -127,14 +127,15 @@ namespace embree
{
assert(!empty());
size_active--;
- alloc.destroy(&items[size_active]);
+ items[size_active].~T();
}
__forceinline void clear()
{
/* destroy elements */
- for (size_t i=0; i<size_active; i++)
- alloc.destroy(&items[i]);
+ for (size_t i=0; i<size_active; i++){
+ items[i].~T();
+ }
/* free memory */
alloc.deallocate(items,size_alloced);
@@ -178,8 +179,9 @@ namespace embree
/* destroy elements */
if (new_active < size_active)
{
- for (size_t i=new_active; i<size_active; i++)
- alloc.destroy(&items[i]);
+ for (size_t i=new_active; i<size_active; i++){
+ items[i].~T();
+ }
size_active = new_active;
}
@@ -195,7 +197,7 @@ namespace embree
items = alloc.allocate(new_alloced);
for (size_t i=0; i<size_active; i++) {
::new (&items[i]) T(std::move(old_items[i]));
- alloc.destroy(&old_items[i]);
+ old_items[i].~T();
}
for (size_t i=size_active; i<new_active; i++) {
diff --git a/thirdparty/embree/common/tasking/taskschedulerinternal.h b/thirdparty/embree/common/tasking/taskschedulerinternal.h
index 8fa6bb12fa..6cc2495195 100644
--- a/thirdparty/embree/common/tasking/taskschedulerinternal.h
+++ b/thirdparty/embree/common/tasking/taskschedulerinternal.h
@@ -143,7 +143,7 @@ namespace embree
/* allocate new task on right side of stack */
size_t oldStackPtr = stackPtr;
TaskFunction* func = new (alloc(sizeof(ClosureTaskFunction<Closure>))) ClosureTaskFunction<Closure>(closure);
- new (&tasks[right]) Task(func,thread.task,oldStackPtr,size);
+ new (&(tasks[right.load()])) Task(func,thread.task,oldStackPtr,size);
right++;
/* also move left pointer */
diff --git a/thirdparty/embree/common/tasking/taskschedulertbb.h b/thirdparty/embree/common/tasking/taskschedulertbb.h
index 35bd49849f..042ba7bc4c 100644
--- a/thirdparty/embree/common/tasking/taskschedulertbb.h
+++ b/thirdparty/embree/common/tasking/taskschedulertbb.h
@@ -11,14 +11,8 @@
#include "../sys/condition.h"
#include "../sys/ref.h"
-#if defined(__WIN32__)
-// -- GODOT start --
-#if !defined(NOMINMAX)
-// -- GODOT end --
+#if defined(__WIN32__) && !defined(NOMINMAX)
# define NOMINMAX
-// -- GODOT start --
-#endif
-// -- GODOT end --
#endif
// We need to define these to avoid implicit linkage against
diff --git a/thirdparty/embree/include/embree3/rtcore_common.h b/thirdparty/embree/include/embree3/rtcore_common.h
index 4857e1e05e..894628e47c 100644
--- a/thirdparty/embree/include/embree3/rtcore_common.h
+++ b/thirdparty/embree/include/embree3/rtcore_common.h
@@ -19,9 +19,7 @@ typedef int ssize_t;
#endif
#endif
-// -- GODOT start --
-#if defined(_WIN32) && defined(_MSC_VER)
-// -- GODOT end --
+#if defined(_WIN32) && !defined(__MINGW32__)
# define RTC_ALIGN(...) __declspec(align(__VA_ARGS__))
#else
# define RTC_ALIGN(...) __attribute__((aligned(__VA_ARGS__)))
diff --git a/thirdparty/embree/include/embree3/rtcore_config.h b/thirdparty/embree/include/embree3/rtcore_config.h
index 62b7b6f4dc..0b399ef040 100644
--- a/thirdparty/embree/include/embree3/rtcore_config.h
+++ b/thirdparty/embree/include/embree3/rtcore_config.h
@@ -1,4 +1,3 @@
-
// Copyright 2009-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
@@ -6,23 +5,25 @@
#define RTC_VERSION_MAJOR 3
#define RTC_VERSION_MINOR 13
-#define RTC_VERSION_PATCH 1
-#define RTC_VERSION 31301
-#define RTC_VERSION_STRING "3.13.1"
+#define RTC_VERSION_PATCH 5
+#define RTC_VERSION 31305
+#define RTC_VERSION_STRING "3.13.5"
#define RTC_MAX_INSTANCE_LEVEL_COUNT 1
#define EMBREE_MIN_WIDTH 0
#define RTC_MIN_WIDTH EMBREE_MIN_WIDTH
-#define EMBREE_STATIC_LIB
-/* #undef EMBREE_API_NAMESPACE */
+#if !defined(EMBREE_STATIC_LIB)
+# define EMBREE_STATIC_LIB
+#endif
+/* #undef EMBREE_API_NAMESPACE*/
#if defined(EMBREE_API_NAMESPACE)
# define RTC_NAMESPACE
-# define RTC_NAMESPACE_BEGIN namespace {
+# define RTC_NAMESPACE_BEGIN namespace {
# define RTC_NAMESPACE_END }
-# define RTC_NAMESPACE_USE using namespace ;
+# define RTC_NAMESPACE_USE using namespace;
# define RTC_API_EXTERN_C
# undef EMBREE_API_NAMESPACE
#else
diff --git a/thirdparty/embree/include/embree3/rtcore_quaternion.h b/thirdparty/embree/include/embree3/rtcore_quaternion.h
index 6489fa3467..bd5fe1d89a 100644
--- a/thirdparty/embree/include/embree3/rtcore_quaternion.h
+++ b/thirdparty/embree/include/embree3/rtcore_quaternion.h
@@ -8,7 +8,7 @@
RTC_NAMESPACE_BEGIN
/*
- * Structure for transformation respresentation as a matrix decomposition using
+ * Structure for transformation representation as a matrix decomposition using
* a quaternion
*/
struct RTC_ALIGN(16) RTCQuaternionDecomposition
diff --git a/thirdparty/embree/include/embree3/rtcore_scene.h b/thirdparty/embree/include/embree3/rtcore_scene.h
index 5878a3d402..34d87a2ce4 100644
--- a/thirdparty/embree/include/embree3/rtcore_scene.h
+++ b/thirdparty/embree/include/embree3/rtcore_scene.h
@@ -47,9 +47,12 @@ RTC_API void rtcAttachGeometryByID(RTCScene scene, RTCGeometry geometry, unsigne
/* Detaches the geometry from the scene. */
RTC_API void rtcDetachGeometry(RTCScene scene, unsigned int geomID);
-/* Gets a geometry handle from the scene. */
+/* Gets a geometry handle from the scene. This function is not thread safe and should get used during rendering. */
RTC_API RTCGeometry rtcGetGeometry(RTCScene scene, unsigned int geomID);
+/* Gets a geometry handle from the scene. This function is thread safe and should NOT get used during rendering. */
+RTC_API RTCGeometry rtcGetGeometryThreadSafe(RTCScene scene, unsigned int geomID);
+
/* Commits the scene. */
RTC_API void rtcCommitScene(RTCScene scene);
diff --git a/thirdparty/embree/kernels/builders/bvh_builder_morton.h b/thirdparty/embree/kernels/builders/bvh_builder_morton.h
index 8f21e3254f..cba32ca73c 100644
--- a/thirdparty/embree/kernels/builders/bvh_builder_morton.h
+++ b/thirdparty/embree/kernels/builders/bvh_builder_morton.h
@@ -411,7 +411,7 @@ namespace embree
ReductionTy bounds[MAX_BRANCHING_FACTOR];
if (current.size() > singleThreadThreshold)
{
- /*! parallel_for is faster than spawing sub-tasks */
+ /*! parallel_for is faster than spawning sub-tasks */
parallel_for(size_t(0), numChildren, [&] (const range<size_t>& r) {
for (size_t i=r.begin(); i<r.end(); i++) {
bounds[i] = recurse(depth+1,children[i],nullptr,true);
diff --git a/thirdparty/embree/kernels/builders/bvh_builder_msmblur.h b/thirdparty/embree/kernels/builders/bvh_builder_msmblur.h
index f9a08d65cd..6e73c0d250 100644
--- a/thirdparty/embree/kernels/builders/bvh_builder_msmblur.h
+++ b/thirdparty/embree/kernels/builders/bvh_builder_msmblur.h
@@ -374,7 +374,7 @@ namespace embree
const size_t begin = set.begin();
const size_t end = set.end();
- const size_t center = (begin + end)/2;
+ const size_t center = (begin + end + 1) / 2;
PrimInfoMB linfo = empty;
for (size_t i=begin; i<center; i++)
@@ -594,7 +594,7 @@ namespace embree
/* spawn tasks */
if (unlikely(current.size() > cfg.singleThreadThreshold))
{
- /*! parallel_for is faster than spawing sub-tasks */
+ /*! parallel_for is faster than spawning sub-tasks */
parallel_for(size_t(0), children.size(), [&] (const range<size_t>& r) {
for (size_t i=r.begin(); i<r.end(); i++) {
values[i] = recurse(children[i],nullptr,true);
diff --git a/thirdparty/embree/kernels/builders/bvh_builder_sah.h b/thirdparty/embree/kernels/builders/bvh_builder_sah.h
index fff4bf2a35..24c5faf8be 100644
--- a/thirdparty/embree/kernels/builders/bvh_builder_sah.h
+++ b/thirdparty/embree/kernels/builders/bvh_builder_sah.h
@@ -298,7 +298,7 @@ namespace embree
/* spawn tasks */
if (current.size() > cfg.singleThreadThreshold)
{
- /*! parallel_for is faster than spawing sub-tasks */
+ /*! parallel_for is faster than spawning sub-tasks */
parallel_for(size_t(0), numChildren, [&] (const range<size_t>& r) { // FIXME: no range here
for (size_t i=r.begin(); i<r.end(); i++) {
values[i] = recurse(children[i],nullptr,true);
diff --git a/thirdparty/embree/kernels/builders/heuristic_binning.h b/thirdparty/embree/kernels/builders/heuristic_binning.h
index ee29d09ac9..41be6183b8 100644
--- a/thirdparty/embree/kernels/builders/heuristic_binning.h
+++ b/thirdparty/embree/kernels/builders/heuristic_binning.h
@@ -57,14 +57,12 @@ namespace embree
__forceinline Vec3ia bin(const Vec3fa& p) const
{
const vint4 i = floori((vfloat4(p)-ofs)*scale);
-#if 1
assert(i[0] >= 0 && (size_t)i[0] < num);
assert(i[1] >= 0 && (size_t)i[1] < num);
assert(i[2] >= 0 && (size_t)i[2] < num);
- return Vec3ia(i);
-#else
+
+ // we clamp to handle corner cases that could calculate out of bounds bin
return Vec3ia(clamp(i,vint4(0),vint4(num-1)));
-#endif
}
/*! faster but unsafe binning */
diff --git a/thirdparty/embree/kernels/builders/heuristic_openmerge_array.h b/thirdparty/embree/kernels/builders/heuristic_openmerge_array.h
index 4249d16ea1..354e283557 100644
--- a/thirdparty/embree/kernels/builders/heuristic_openmerge_array.h
+++ b/thirdparty/embree/kernels/builders/heuristic_openmerge_array.h
@@ -275,7 +275,7 @@ namespace embree
openNodesBasedOnExtend(set);
#endif
- /* disable opening when unsufficient space for opening a node available */
+ /* disable opening when insufficient space for opening a node available */
if (set.ext_range_size() < max_open_size-1)
set.set_ext_range(set.end()); /* disable opening */
}
diff --git a/thirdparty/embree/kernels/builders/heuristic_spatial.h b/thirdparty/embree/kernels/builders/heuristic_spatial.h
index a6939ba258..8b3499ac8d 100644
--- a/thirdparty/embree/kernels/builders/heuristic_spatial.h
+++ b/thirdparty/embree/kernels/builders/heuristic_spatial.h
@@ -159,27 +159,25 @@ namespace embree
assert(binID < BINS);
bounds [binID][dim].extend(b);
}
-
- /*! bins an array of triangles */
- template<typename SplitPrimitive>
- __forceinline void bin(const SplitPrimitive& splitPrimitive, const PrimRef* prims, size_t N, const SpatialBinMapping<BINS>& mapping)
+
+ /*! bins an array of primitives */
+ template<typename PrimitiveSplitterFactory>
+ __forceinline void bin2(const PrimitiveSplitterFactory& splitterFactory, const PrimRef* source, size_t begin, size_t end, const SpatialBinMapping<BINS>& mapping)
{
- for (size_t i=0; i<N; i++)
+ for (size_t i=begin; i<end; i++)
{
- const PrimRef prim = prims[i];
+ const PrimRef& prim = source[i];
unsigned splits = prim.geomID() >> (32-RESERVED_NUM_SPATIAL_SPLITS_GEOMID_BITS);
-
- if (unlikely(splits == 1))
+
+ if (unlikely(splits <= 1))
{
const vint4 bin = mapping.bin(center(prim.bounds()));
for (size_t dim=0; dim<3; dim++)
{
assert(bin[dim] >= (int)0 && bin[dim] < (int)BINS);
- numBegin[bin[dim]][dim]++;
- numEnd [bin[dim]][dim]++;
- bounds [bin[dim]][dim].extend(prim.bounds());
+ add(dim,bin[dim],bin[dim],bin[dim],prim.bounds());
}
- }
+ }
else
{
const vint4 bin0 = mapping.bin(prim.bounds().lower);
@@ -187,89 +185,44 @@ namespace embree
for (size_t dim=0; dim<3; dim++)
{
+ if (unlikely(mapping.invalid(dim)))
+ continue;
+
size_t bin;
- PrimRef rest = prim;
size_t l = bin0[dim];
size_t r = bin1[dim];
-
+
// same bin optimization
if (likely(l == r))
{
- numBegin[l][dim]++;
- numEnd [l][dim]++;
- bounds [l][dim].extend(prim.bounds());
+ add(dim,l,l,l,prim.bounds());
continue;
}
-
- for (bin=(size_t)bin0[dim]; bin<(size_t)bin1[dim]; bin++)
+ size_t bin_start = bin0[dim];
+ size_t bin_end = bin1[dim];
+ BBox3fa rest = prim.bounds();
+
+ /* assure that split position always overlaps the primitive bounds */
+ while (bin_start < bin_end && mapping.pos(bin_start+1,dim) <= rest.lower[dim]) bin_start++;
+ while (bin_start < bin_end && mapping.pos(bin_end ,dim) >= rest.upper[dim]) bin_end--;
+
+ const auto splitter = splitterFactory(prim);
+ for (bin=bin_start; bin<bin_end; bin++)
{
const float pos = mapping.pos(bin+1,dim);
+ BBox3fa left,right;
+ splitter(rest,dim,pos,left,right);
- PrimRef left,right;
- splitPrimitive(rest,(int)dim,pos,left,right);
- if (unlikely(left.bounds().empty())) l++;
- bounds[bin][dim].extend(left.bounds());
+ if (unlikely(left.empty())) l++;
+ extend(dim,bin,left);
rest = right;
}
- if (unlikely(rest.bounds().empty())) r--;
- numBegin[l][dim]++;
- numEnd [r][dim]++;
- bounds [bin][dim].extend(rest.bounds());
+ if (unlikely(rest.empty())) r--;
+ add(dim,l,r,bin,rest);
}
- }
+ }
}
}
-
- /*! bins a range of primitives inside an array */
- template<typename SplitPrimitive>
- void bin(const SplitPrimitive& splitPrimitive, const PrimRef* prims, size_t begin, size_t end, const SpatialBinMapping<BINS>& mapping) {
- bin(splitPrimitive,prims+begin,end-begin,mapping);
- }
-
- /*! bins an array of primitives */
- template<typename PrimitiveSplitterFactory>
- __forceinline void bin2(const PrimitiveSplitterFactory& splitterFactory, const PrimRef* source, size_t begin, size_t end, const SpatialBinMapping<BINS>& mapping)
- {
- for (size_t i=begin; i<end; i++)
- {
- const PrimRef &prim = source[i];
- const vint4 bin0 = mapping.bin(prim.bounds().lower);
- const vint4 bin1 = mapping.bin(prim.bounds().upper);
-
- for (size_t dim=0; dim<3; dim++)
- {
- if (unlikely(mapping.invalid(dim)))
- continue;
-
- size_t bin;
- size_t l = bin0[dim];
- size_t r = bin1[dim];
-
- // same bin optimization
- if (likely(l == r))
- {
- add(dim,l,l,l,prim.bounds());
- continue;
- }
- const size_t bin_start = bin0[dim];
- const size_t bin_end = bin1[dim];
- BBox3fa rest = prim.bounds();
- const auto splitter = splitterFactory(prim);
- for (bin=bin_start; bin<bin_end; bin++)
- {
- const float pos = mapping.pos(bin+1,dim);
- BBox3fa left,right;
- splitter(rest,dim,pos,left,right);
- if (unlikely(left.empty())) l++;
- extend(dim,bin,left);
- rest = right;
- }
- if (unlikely(rest.empty())) r--;
- add(dim,l,r,bin,rest);
- }
- }
- }
-
/*! bins an array of primitives */
diff --git a/thirdparty/embree/kernels/builders/heuristic_spatial_array.h b/thirdparty/embree/kernels/builders/heuristic_spatial_array.h
index 60d235f48d..2584c19bda 100644
--- a/thirdparty/embree/kernels/builders/heuristic_spatial_array.h
+++ b/thirdparty/embree/kernels/builders/heuristic_spatial_array.h
@@ -241,7 +241,7 @@ namespace embree
SpatialBinner binner(empty);
const SpatialBinMapping<SPATIAL_BINS> mapping(set);
binner.bin2(splitterFactory,prims0,set.begin(),set.end(),mapping);
- /* todo: best spatial split not exeeding the extended range does not provide any benefit ?*/
+ /* todo: best spatial split not exceeding the extended range does not provide any benefit ?*/
return binner.best(mapping,logBlockSize); //,set.ext_size());
}
@@ -256,7 +256,7 @@ namespace embree
binner.bin2(splitterFactory,prims0,r.begin(),r.end(),_mapping);
return binner; },
[&] (const SpatialBinner& b0, const SpatialBinner& b1) -> SpatialBinner { return SpatialBinner::reduce(b0,b1); });
- /* todo: best spatial split not exeeding the extended range does not provide any benefit ?*/
+ /* todo: best spatial split not exceeding the extended range does not provide any benefit ?*/
return binner.best(mapping,logBlockSize); //,set.ext_size());
}
@@ -286,6 +286,7 @@ namespace embree
//int bin0 = split.mapping.bin(prims0[i].lower)[split.dim];
//int bin1 = split.mapping.bin(prims0[i].upper)[split.dim];
//if (unlikely(bin0 < split.pos && bin1 >= split.pos))
+
if (unlikely(prims0[i].lower[split.dim] < fpos && prims0[i].upper[split.dim] > fpos))
{
assert(splits > 1);
@@ -384,8 +385,8 @@ namespace embree
new (&lset) PrimInfoExtRange(begin,center,center,local_left);
new (&rset) PrimInfoExtRange(center,end,end,local_right);
- assert(area(lset.geomBounds) >= 0.0f);
- assert(area(rset.geomBounds) >= 0.0f);
+ assert(!lset.geomBounds.empty() && area(lset.geomBounds) >= 0.0f);
+ assert(!rset.geomBounds.empty() && area(rset.geomBounds) >= 0.0f);
return std::pair<size_t,size_t>(left_weight,right_weight);
}
@@ -410,7 +411,7 @@ namespace embree
begin,end,local_left,local_right,
[&] (const PrimRef& ref) {
const Vec3fa c = ref.bounds().center();
- return any(((vint4)mapping.bin(c) < vSplitPos) & vSplitMask);
+ return any(((vint4)mapping.bin(c) < vSplitPos) & vSplitMask);
},
[] (PrimInfo& pinfo,const PrimRef& ref) { pinfo.add_center2(ref,ref.lower.u >> (32-RESERVED_NUM_SPATIAL_SPLITS_GEOMID_BITS)); });
@@ -419,8 +420,8 @@ namespace embree
new (&lset) PrimInfoExtRange(begin,center,center,local_left);
new (&rset) PrimInfoExtRange(center,end,end,local_right);
- assert(area(lset.geomBounds) >= 0.0f);
- assert(area(rset.geomBounds) >= 0.0f);
+ assert(!lset.geomBounds.empty() && area(lset.geomBounds) >= 0.0f);
+ assert(!rset.geomBounds.empty() && area(rset.geomBounds) >= 0.0f);
return std::pair<size_t,size_t>(left_weight,right_weight);
}
diff --git a/thirdparty/embree/kernels/builders/primrefgen.cpp b/thirdparty/embree/kernels/builders/primrefgen.cpp
index d279dc4993..e2d7c27bd8 100644
--- a/thirdparty/embree/kernels/builders/primrefgen.cpp
+++ b/thirdparty/embree/kernels/builders/primrefgen.cpp
@@ -184,9 +184,7 @@ namespace embree
// special variants for grid meshes
-// -- GODOT start --
#if defined(EMBREE_GEOMETRY_GRID)
-// -- GODOT end --
PrimInfo createPrimRefArrayGrids(Scene* scene, mvector<PrimRef>& prims, mvector<SubGridBuildData>& sgrids)
{
PrimInfo pinfo(empty);
@@ -296,9 +294,7 @@ namespace embree
return pinfo;
}
-// -- GODOT start --
#endif
-// -- GODOT end --
// ====================================================================================================
// ====================================================================================================
diff --git a/thirdparty/embree/kernels/builders/primrefgen_presplit.h b/thirdparty/embree/kernels/builders/primrefgen_presplit.h
index 8cd251ddd2..aa2026a85e 100644
--- a/thirdparty/embree/kernels/builders/primrefgen_presplit.h
+++ b/thirdparty/embree/kernels/builders/primrefgen_presplit.h
@@ -266,7 +266,7 @@ namespace embree
/* anything to split ? */
if (center < numPrimitives)
{
- const size_t numPrimitivesToSplit = numPrimitives - center;
+ size_t numPrimitivesToSplit = numPrimitives - center;
assert(presplitItem[center].priority >= 1.0f);
/* sort presplit items in ascending order */
@@ -279,8 +279,8 @@ namespace embree
});
);
- unsigned int *const primOffset0 = (unsigned int*)tmp_presplitItem;
- unsigned int *const primOffset1 = (unsigned int*)tmp_presplitItem + numPrimitivesToSplit;
+ unsigned int* primOffset0 = (unsigned int*)tmp_presplitItem;
+ unsigned int* primOffset1 = (unsigned int*)tmp_presplitItem + numPrimitivesToSplit;
/* compute actual number of sub-primitives generated within the [center;numPrimitives-1] range */
const size_t totalNumSubPrims = parallel_reduce( size_t(center), numPrimitives, size_t(MIN_STEP_SIZE), size_t(0), [&](const range<size_t>& t) -> size_t {
@@ -317,11 +317,16 @@ namespace embree
sum += numSubPrims;
}
new_center++;
+
+ primOffset0 += new_center - center;
+ numPrimitivesToSplit -= new_center - center;
center = new_center;
+ assert(numPrimitivesToSplit == (numPrimitives - center));
}
/* parallel prefix sum to compute offsets for storing sub-primitives */
const unsigned int offset = parallel_prefix_sum(primOffset0,primOffset1,numPrimitivesToSplit,(unsigned int)0,std::plus<unsigned int>());
+ assert(numPrimitives+offset <= alloc_numPrimitives);
/* iterate over range, and split primitives into sub primitives and append them to prims array */
parallel_for( size_t(center), numPrimitives, size_t(MIN_STEP_SIZE), [&](const range<size_t>& rn) -> void {
@@ -338,7 +343,7 @@ namespace embree
unsigned int numSubPrims = 0;
splitPrimitive(Splitter,prims[primrefID],geomID,primID,split_levels,grid_base,grid_scale,grid_extend,subPrims,numSubPrims);
const size_t newID = numPrimitives + primOffset1[j-center];
- assert(newID+numSubPrims <= alloc_numPrimitives);
+ assert(newID+numSubPrims-1 <= alloc_numPrimitives);
prims[primrefID] = subPrims[0];
for (size_t i=1;i<numSubPrims;i++)
prims[newID+i-1] = subPrims[i];
diff --git a/thirdparty/embree/kernels/builders/splitter.h b/thirdparty/embree/kernels/builders/splitter.h
index f7720bd284..da89d0b178 100644
--- a/thirdparty/embree/kernels/builders/splitter.h
+++ b/thirdparty/embree/kernels/builders/splitter.h
@@ -128,28 +128,30 @@ namespace embree
const unsigned int mask = 0xFFFFFFFF >> RESERVED_NUM_SPATIAL_SPLITS_GEOMID_BITS;
const QuadMesh* mesh = (const QuadMesh*) scene->get(prim.geomID() & mask );
QuadMesh::Quad quad = mesh->quad(prim.primID());
- v[0] = mesh->vertex(quad.v[0]);
- v[1] = mesh->vertex(quad.v[1]);
- v[2] = mesh->vertex(quad.v[2]);
- v[3] = mesh->vertex(quad.v[3]);
- v[4] = mesh->vertex(quad.v[0]);
- inv_length[0] = Vec3fa(1.0f) / (v[1]-v[0]);
- inv_length[1] = Vec3fa(1.0f) / (v[2]-v[1]);
- inv_length[2] = Vec3fa(1.0f) / (v[3]-v[2]);
- inv_length[3] = Vec3fa(1.0f) / (v[0]-v[3]);
+ v[0] = mesh->vertex(quad.v[1]);
+ v[1] = mesh->vertex(quad.v[2]);
+ v[2] = mesh->vertex(quad.v[3]);
+ v[3] = mesh->vertex(quad.v[0]);
+ v[4] = mesh->vertex(quad.v[1]);
+ v[5] = mesh->vertex(quad.v[3]);
+ inv_length[0] = Vec3fa(1.0f) / (v[1] - v[0]);
+ inv_length[1] = Vec3fa(1.0f) / (v[2] - v[1]);
+ inv_length[2] = Vec3fa(1.0f) / (v[3] - v[2]);
+ inv_length[3] = Vec3fa(1.0f) / (v[4] - v[3]);
+ inv_length[4] = Vec3fa(1.0f) / (v[5] - v[4]);
}
__forceinline void operator() (const PrimRef& prim, const size_t dim, const float pos, PrimRef& left_o, PrimRef& right_o) const {
- splitPolygon<4>(prim,dim,pos,v,left_o,right_o);
+ splitPolygon<5>(prim,dim,pos,v,left_o,right_o);
}
__forceinline void operator() (const BBox3fa& prim, const size_t dim, const float pos, BBox3fa& left_o, BBox3fa& right_o) const {
- splitPolygon<4>(prim,dim,pos,v,inv_length,left_o,right_o);
+ splitPolygon<5>(prim,dim,pos,v,inv_length,left_o,right_o);
}
private:
- Vec3fa v[5];
- Vec3fa inv_length[4];
+ Vec3fa v[6];
+ Vec3fa inv_length[5];
};
struct QuadSplitterFactory
diff --git a/thirdparty/embree/kernels/bvh/bvh.cpp b/thirdparty/embree/kernels/bvh/bvh.cpp
index a84295f0da..f6cf626465 100644
--- a/thirdparty/embree/kernels/bvh/bvh.cpp
+++ b/thirdparty/embree/kernels/bvh/bvh.cpp
@@ -183,7 +183,7 @@ namespace embree
template class BVHN<8>;
#endif
-#if !defined(__AVX__) || !defined(EMBREE_TARGET_SSE2) && !defined(EMBREE_TARGET_SSE42)
+#if !defined(__AVX__) || !defined(EMBREE_TARGET_SSE2) && !defined(EMBREE_TARGET_SSE42) || defined(__aarch64__)
template class BVHN<4>;
#endif
}
diff --git a/thirdparty/embree/kernels/bvh/bvh_intersector_hybrid.cpp b/thirdparty/embree/kernels/bvh/bvh_intersector_hybrid.cpp
index 6e9a5a538e..1d393fd06b 100644
--- a/thirdparty/embree/kernels/bvh/bvh_intersector_hybrid.cpp
+++ b/thirdparty/embree/kernels/bvh/bvh_intersector_hybrid.cpp
@@ -230,7 +230,7 @@ namespace embree
continue;
/* switch to single ray traversal */
-#if (!defined(__WIN32__) || defined(__X86_64__)) && defined(__SSE4_2__)
+#if (!defined(__WIN32__) || defined(__X86_64__)) && ((defined(__aarch64__)) || defined(__SSE4_2__))
#if FORCE_SINGLE_MODE == 0
if (single)
#endif
@@ -676,7 +676,7 @@ namespace embree
continue;
/* switch to single ray traversal */
-#if (!defined(__WIN32__) || defined(__X86_64__)) && defined(__SSE4_2__)
+#if (!defined(__WIN32__) || defined(__X86_64__)) && ((defined(__aarch64__)) || defined(__SSE4_2__))
#if FORCE_SINGLE_MODE == 0
if (single)
#endif
diff --git a/thirdparty/embree/kernels/bvh/bvh_intersector_stream.h b/thirdparty/embree/kernels/bvh/bvh_intersector_stream.h
index 717f559677..c7e040fadb 100644
--- a/thirdparty/embree/kernels/bvh/bvh_intersector_stream.h
+++ b/thirdparty/embree/kernels/bvh/bvh_intersector_stream.h
@@ -170,12 +170,23 @@ namespace embree
TravRayKStream<K,robust> &p = packets[rayID / K];
const size_t i = rayID % K;
const vint<N> bitmask(shiftTable[rayID]);
+
+#if defined (__aarch64__)
+ const vfloat<N> tNearX = madd(bminX, p.rdir.x[i], p.neg_org_rdir.x[i]);
+ const vfloat<N> tNearY = madd(bminY, p.rdir.y[i], p.neg_org_rdir.y[i]);
+ const vfloat<N> tNearZ = madd(bminZ, p.rdir.z[i], p.neg_org_rdir.z[i]);
+ const vfloat<N> tFarX = madd(bmaxX, p.rdir.x[i], p.neg_org_rdir.x[i]);
+ const vfloat<N> tFarY = madd(bmaxY, p.rdir.y[i], p.neg_org_rdir.y[i]);
+ const vfloat<N> tFarZ = madd(bmaxZ, p.rdir.z[i], p.neg_org_rdir.z[i]);
+#else
const vfloat<N> tNearX = msub(bminX, p.rdir.x[i], p.org_rdir.x[i]);
const vfloat<N> tNearY = msub(bminY, p.rdir.y[i], p.org_rdir.y[i]);
const vfloat<N> tNearZ = msub(bminZ, p.rdir.z[i], p.org_rdir.z[i]);
const vfloat<N> tFarX = msub(bmaxX, p.rdir.x[i], p.org_rdir.x[i]);
const vfloat<N> tFarY = msub(bmaxY, p.rdir.y[i], p.org_rdir.y[i]);
const vfloat<N> tFarZ = msub(bmaxZ, p.rdir.z[i], p.org_rdir.z[i]);
+#endif
+
const vfloat<N> tNear = maxi(tNearX, tNearY, tNearZ, vfloat<N>(p.tnear[i]));
const vfloat<N> tFar = mini(tFarX , tFarY , tFarZ, vfloat<N>(p.tfar[i]));
diff --git a/thirdparty/embree/kernels/bvh/bvh_node_aabb.h b/thirdparty/embree/kernels/bvh/bvh_node_aabb.h
index 57530692bc..3fd9fc7d18 100644
--- a/thirdparty/embree/kernels/bvh/bvh_node_aabb.h
+++ b/thirdparty/embree/kernels/bvh/bvh_node_aabb.h
@@ -46,6 +46,14 @@ namespace embree
template<typename BuildRecord>
__forceinline NodeRef operator() (const BuildRecord& precord, const BuildRecord* crecords, NodeRef ref, NodeRef* children, const size_t num) const
{
+#if defined(DEBUG)
+ // check that empty children are only at the end of the child list
+ bool emptyChild = false;
+ for (size_t i=0; i<num; i++) {
+ emptyChild |= (children[i] == NodeRef::emptyNode);
+ assert(emptyChild == (children[i] == NodeRef::emptyNode));
+ }
+#endif
AABBNode_t* node = ref.getAABBNode();
for (size_t i=0; i<num; i++) node->setRef(i,children[i]);
return ref;
@@ -60,6 +68,14 @@ namespace embree
template<typename BuildRecord>
__forceinline NodeRef operator() (const BuildRecord& precord, const BuildRecord* crecords, NodeRef ref, NodeRef* children, const size_t num) const
{
+#if defined(DEBUG)
+ // check that empty children are only at the end of the child list
+ bool emptyChild = false;
+ for (size_t i=0; i<num; i++) {
+ emptyChild |= (children[i] == NodeRef::emptyNode);
+ assert(emptyChild == (children[i] == NodeRef::emptyNode));
+ }
+#endif
AABBNode_t* node = ref.getAABBNode();
for (size_t i=0; i<num; i++) node->setRef(i,children[i]);
diff --git a/thirdparty/embree/kernels/bvh/bvh_node_aabb_mb.h b/thirdparty/embree/kernels/bvh/bvh_node_aabb_mb.h
index c4cea7d8ba..001f526c25 100644
--- a/thirdparty/embree/kernels/bvh/bvh_node_aabb_mb.h
+++ b/thirdparty/embree/kernels/bvh/bvh_node_aabb_mb.h
@@ -31,6 +31,14 @@ namespace embree
template<typename BuildRecord>
__forceinline NodeRecordMB operator() (const BuildRecord& precord, const BuildRecord* crecords, NodeRef ref, NodeRecordMB* children, const size_t num) const
{
+#if defined(DEBUG)
+ // check that empty children are only at the end of the child list
+ bool emptyChild = false;
+ for (size_t i=0; i<num; i++) {
+ emptyChild |= (children[i].ref == NodeRef::emptyNode);
+ assert(emptyChild == (children[i].ref == NodeRef::emptyNode));
+ }
+#endif
AABBNodeMB_t* node = ref.getAABBNodeMB();
LBBox3fa bounds = empty;
diff --git a/thirdparty/embree/kernels/bvh/bvh_node_aabb_mb4d.h b/thirdparty/embree/kernels/bvh/bvh_node_aabb_mb4d.h
index 46a81d7581..3b966fd054 100644
--- a/thirdparty/embree/kernels/bvh/bvh_node_aabb_mb4d.h
+++ b/thirdparty/embree/kernels/bvh/bvh_node_aabb_mb4d.h
@@ -41,6 +41,14 @@ namespace embree
template<typename BuildRecord>
__forceinline void operator() (const BuildRecord&, const BuildRecord*, NodeRef ref, NodeRecordMB4D* children, const size_t num) const
{
+#if defined(DEBUG)
+ // check that empty children are only at the end of the child list
+ bool emptyChild = false;
+ for (size_t i=0; i<num; i++) {
+ emptyChild |= (children[i].ref == NodeRef::emptyNode);
+ assert(emptyChild == (children[i].ref == NodeRef::emptyNode));
+ }
+#endif
if (likely(ref.isAABBNodeMB())) {
for (size_t i=0; i<num; i++)
ref.getAABBNodeMB()->set(i, children[i]);
diff --git a/thirdparty/embree/kernels/bvh/bvh_node_qaabb.h b/thirdparty/embree/kernels/bvh/bvh_node_qaabb.h
index 2afc8c98e7..99671ddc5a 100644
--- a/thirdparty/embree/kernels/bvh/bvh_node_qaabb.h
+++ b/thirdparty/embree/kernels/bvh/bvh_node_qaabb.h
@@ -190,6 +190,14 @@ namespace embree
template<typename BuildRecord>
__forceinline NodeRef operator() (const BuildRecord& precord, const BuildRecord* crecords, NodeRef ref, NodeRef* children, const size_t num) const
{
+#if defined(DEBUG)
+ // check that empty children are only at the end of the child list
+ bool emptyChild = false;
+ for (size_t i=0; i<num; i++) {
+ emptyChild |= (children[i] == NodeRef::emptyNode);
+ assert(emptyChild == (children[i] == NodeRef::emptyNode));
+ }
+#endif
QuantizedNode_t* node = ref.quantizedNode();
for (size_t i=0; i<num; i++) node->setRef(i,children[i]);
return ref;
diff --git a/thirdparty/embree/kernels/bvh/bvh_statistics.cpp b/thirdparty/embree/kernels/bvh/bvh_statistics.cpp
index d857ff7d95..57f75bfd7e 100644
--- a/thirdparty/embree/kernels/bvh/bvh_statistics.cpp
+++ b/thirdparty/embree/kernels/bvh/bvh_statistics.cpp
@@ -162,7 +162,7 @@ namespace embree
template class BVHNStatistics<8>;
#endif
-#if !defined(__AVX__) || !defined(EMBREE_TARGET_SSE2) && !defined(EMBREE_TARGET_SSE42)
+#if !defined(__AVX__) || (!defined(EMBREE_TARGET_SSE2) && !defined(EMBREE_TARGET_SSE42)) || defined(__aarch64__)
template class BVHNStatistics<4>;
#endif
}
diff --git a/thirdparty/embree/kernels/bvh/node_intersector1.h b/thirdparty/embree/kernels/bvh/node_intersector1.h
index 1ec4fc63fc..17641fa888 100644
--- a/thirdparty/embree/kernels/bvh/node_intersector1.h
+++ b/thirdparty/embree/kernels/bvh/node_intersector1.h
@@ -5,6 +5,15 @@
#include "node_intersector.h"
+#if defined(__AVX2__)
+#define __FMA_X4__
+#endif
+
+#if defined(__aarch64__)
+#define __FMA_X4__
+#endif
+
+
namespace embree
{
namespace isa
@@ -29,9 +38,15 @@ namespace embree
org = Vec3vf<N>(ray_org.x,ray_org.y,ray_org.z);
dir = Vec3vf<N>(ray_dir.x,ray_dir.y,ray_dir.z);
rdir = Vec3vf<N>(ray_rdir.x,ray_rdir.y,ray_rdir.z);
-#if defined(__AVX2__) || defined(__ARM_NEON)
+#if defined(__FMA_X4__)
const Vec3fa ray_org_rdir = ray_org*ray_rdir;
+#if !defined(__aarch64__)
org_rdir = Vec3vf<N>(ray_org_rdir.x,ray_org_rdir.y,ray_org_rdir.z);
+#else
+ //for aarch64, we do not have msub equal instruction, so we negeate orig and use madd
+ //x86 will use msub
+ neg_org_rdir = Vec3vf<N>(-ray_org_rdir.x,-ray_org_rdir.y,-ray_org_rdir.z);
+#endif
#endif
nearX = ray_rdir.x >= 0.0f ? 0*sizeof(vfloat<N>) : 1*sizeof(vfloat<N>);
nearY = ray_rdir.y >= 0.0f ? 2*sizeof(vfloat<N>) : 3*sizeof(vfloat<N>);
@@ -49,8 +64,12 @@ namespace embree
org = Vec3vf<N>(ray_org.x[k], ray_org.y[k], ray_org.z[k]);
dir = Vec3vf<N>(ray_dir.x[k], ray_dir.y[k], ray_dir.z[k]);
rdir = Vec3vf<N>(ray_rdir.x[k], ray_rdir.y[k], ray_rdir.z[k]);
-#if defined(__AVX2__) || defined(__ARM_NEON)
- org_rdir = org*rdir;
+#if defined(__FMA_X4__)
+#if !defined(__aarch64__)
+ org_rdir = org*rdir;
+#else
+ neg_org_rdir = -(org*rdir);
+#endif
#endif
nearX = nearXYZ.x[k];
nearY = nearXYZ.y[k];
@@ -62,8 +81,14 @@ namespace embree
Vec3fa org_xyz, dir_xyz;
Vec3vf<N> org, dir, rdir;
-#if defined(__AVX2__) || defined(__ARM_NEON)
+#if defined(__FMA_X4__)
+#if !defined(__aarch64__)
Vec3vf<N> org_rdir;
+#else
+ //aarch64 version are keeping negation of the org_rdir and use madd
+ //x86 uses msub
+ Vec3vf<N> neg_org_rdir;
+#endif
#endif
size_t nearX, nearY, nearZ;
size_t farX, farY, farZ;
@@ -404,13 +429,22 @@ namespace embree
template<>
__forceinline size_t intersectNode<4>(const typename BVH4::AABBNode* node, const TravRay<4,false>& ray, vfloat4& dist)
{
-#if defined(__AVX2__) || defined(__ARM_NEON)
+#if defined(__FMA_X4__)
+#if defined(__aarch64__)
+ const vfloat4 tNearX = madd(vfloat4::load((float*)((const char*)&node->lower_x+ray.nearX)), ray.rdir.x, ray.neg_org_rdir.x);
+ const vfloat4 tNearY = madd(vfloat4::load((float*)((const char*)&node->lower_x+ray.nearY)), ray.rdir.y, ray.neg_org_rdir.y);
+ const vfloat4 tNearZ = madd(vfloat4::load((float*)((const char*)&node->lower_x+ray.nearZ)), ray.rdir.z, ray.neg_org_rdir.z);
+ const vfloat4 tFarX = madd(vfloat4::load((float*)((const char*)&node->lower_x+ray.farX )), ray.rdir.x, ray.neg_org_rdir.x);
+ const vfloat4 tFarY = madd(vfloat4::load((float*)((const char*)&node->lower_x+ray.farY )), ray.rdir.y, ray.neg_org_rdir.y);
+ const vfloat4 tFarZ = madd(vfloat4::load((float*)((const char*)&node->lower_x+ray.farZ )), ray.rdir.z, ray.neg_org_rdir.z);
+#else
const vfloat4 tNearX = msub(vfloat4::load((float*)((const char*)&node->lower_x+ray.nearX)), ray.rdir.x, ray.org_rdir.x);
const vfloat4 tNearY = msub(vfloat4::load((float*)((const char*)&node->lower_x+ray.nearY)), ray.rdir.y, ray.org_rdir.y);
const vfloat4 tNearZ = msub(vfloat4::load((float*)((const char*)&node->lower_x+ray.nearZ)), ray.rdir.z, ray.org_rdir.z);
const vfloat4 tFarX = msub(vfloat4::load((float*)((const char*)&node->lower_x+ray.farX )), ray.rdir.x, ray.org_rdir.x);
const vfloat4 tFarY = msub(vfloat4::load((float*)((const char*)&node->lower_x+ray.farY )), ray.rdir.y, ray.org_rdir.y);
const vfloat4 tFarZ = msub(vfloat4::load((float*)((const char*)&node->lower_x+ray.farZ )), ray.rdir.z, ray.org_rdir.z);
+#endif
#else
const vfloat4 tNearX = (vfloat4::load((float*)((const char*)&node->lower_x+ray.nearX)) - ray.org.x) * ray.rdir.x;
const vfloat4 tNearY = (vfloat4::load((float*)((const char*)&node->lower_x+ray.nearY)) - ray.org.y) * ray.rdir.y;
@@ -450,13 +484,23 @@ namespace embree
template<>
__forceinline size_t intersectNode<8>(const typename BVH8::AABBNode* node, const TravRay<8,false>& ray, vfloat8& dist)
{
-#if defined(__AVX2__) || defined(__ARM_NEON)
+#if defined(__AVX2__)
+#if defined(__aarch64__)
+ const vfloat8 tNearX = madd(vfloat8::load((float*)((const char*)&node->lower_x+ray.nearX)), ray.rdir.x, ray.neg_org_rdir.x);
+ const vfloat8 tNearY = madd(vfloat8::load((float*)((const char*)&node->lower_x+ray.nearY)), ray.rdir.y, ray.neg_org_rdir.y);
+ const vfloat8 tNearZ = madd(vfloat8::load((float*)((const char*)&node->lower_x+ray.nearZ)), ray.rdir.z, ray.neg_org_rdir.z);
+ const vfloat8 tFarX = madd(vfloat8::load((float*)((const char*)&node->lower_x+ray.farX )), ray.rdir.x, ray.neg_org_rdir.x);
+ const vfloat8 tFarY = madd(vfloat8::load((float*)((const char*)&node->lower_x+ray.farY )), ray.rdir.y, ray.neg_org_rdir.y);
+ const vfloat8 tFarZ = madd(vfloat8::load((float*)((const char*)&node->lower_x+ray.farZ )), ray.rdir.z, ray.neg_org_rdir.z);
+#else
const vfloat8 tNearX = msub(vfloat8::load((float*)((const char*)&node->lower_x+ray.nearX)), ray.rdir.x, ray.org_rdir.x);
const vfloat8 tNearY = msub(vfloat8::load((float*)((const char*)&node->lower_x+ray.nearY)), ray.rdir.y, ray.org_rdir.y);
const vfloat8 tNearZ = msub(vfloat8::load((float*)((const char*)&node->lower_x+ray.nearZ)), ray.rdir.z, ray.org_rdir.z);
const vfloat8 tFarX = msub(vfloat8::load((float*)((const char*)&node->lower_x+ray.farX )), ray.rdir.x, ray.org_rdir.x);
const vfloat8 tFarY = msub(vfloat8::load((float*)((const char*)&node->lower_x+ray.farY )), ray.rdir.y, ray.org_rdir.y);
const vfloat8 tFarZ = msub(vfloat8::load((float*)((const char*)&node->lower_x+ray.farZ )), ray.rdir.z, ray.org_rdir.z);
+#endif
+
#else
const vfloat8 tNearX = (vfloat8::load((float*)((const char*)&node->lower_x+ray.nearX)) - ray.org.x) * ray.rdir.x;
const vfloat8 tNearY = (vfloat8::load((float*)((const char*)&node->lower_x+ray.nearY)) - ray.org.y) * ray.rdir.y;
@@ -522,13 +566,22 @@ namespace embree
const vfloat<N>* pFarX = (const vfloat<N>*)((const char*)&node->lower_x+ray.farX);
const vfloat<N>* pFarY = (const vfloat<N>*)((const char*)&node->lower_x+ray.farY);
const vfloat<N>* pFarZ = (const vfloat<N>*)((const char*)&node->lower_x+ray.farZ);
-#if defined(__AVX2__) || defined(__ARM_NEON)
+#if defined(__FMA_X4__)
+#if defined(__aarch64__)
+ const vfloat<N> tNearX = madd(madd(time,pNearX[6],vfloat<N>(pNearX[0])), ray.rdir.x, ray.neg_org_rdir.x);
+ const vfloat<N> tNearY = madd(madd(time,pNearY[6],vfloat<N>(pNearY[0])), ray.rdir.y, ray.neg_org_rdir.y);
+ const vfloat<N> tNearZ = madd(madd(time,pNearZ[6],vfloat<N>(pNearZ[0])), ray.rdir.z, ray.neg_org_rdir.z);
+ const vfloat<N> tFarX = madd(madd(time,pFarX [6],vfloat<N>(pFarX [0])), ray.rdir.x, ray.neg_org_rdir.x);
+ const vfloat<N> tFarY = madd(madd(time,pFarY [6],vfloat<N>(pFarY [0])), ray.rdir.y, ray.neg_org_rdir.y);
+ const vfloat<N> tFarZ = madd(madd(time,pFarZ [6],vfloat<N>(pFarZ [0])), ray.rdir.z, ray.neg_org_rdir.z);
+#else
const vfloat<N> tNearX = msub(madd(time,pNearX[6],vfloat<N>(pNearX[0])), ray.rdir.x, ray.org_rdir.x);
const vfloat<N> tNearY = msub(madd(time,pNearY[6],vfloat<N>(pNearY[0])), ray.rdir.y, ray.org_rdir.y);
const vfloat<N> tNearZ = msub(madd(time,pNearZ[6],vfloat<N>(pNearZ[0])), ray.rdir.z, ray.org_rdir.z);
const vfloat<N> tFarX = msub(madd(time,pFarX [6],vfloat<N>(pFarX [0])), ray.rdir.x, ray.org_rdir.x);
const vfloat<N> tFarY = msub(madd(time,pFarY [6],vfloat<N>(pFarY [0])), ray.rdir.y, ray.org_rdir.y);
const vfloat<N> tFarZ = msub(madd(time,pFarZ [6],vfloat<N>(pFarZ [0])), ray.rdir.z, ray.org_rdir.z);
+#endif
#else
const vfloat<N> tNearX = (madd(time,pNearX[6],vfloat<N>(pNearX[0])) - ray.org.x) * ray.rdir.x;
const vfloat<N> tNearY = (madd(time,pNearY[6],vfloat<N>(pNearY[0])) - ray.org.y) * ray.rdir.y;
@@ -537,7 +590,7 @@ namespace embree
const vfloat<N> tFarY = (madd(time,pFarY [6],vfloat<N>(pFarY [0])) - ray.org.y) * ray.rdir.y;
const vfloat<N> tFarZ = (madd(time,pFarZ [6],vfloat<N>(pFarZ [0])) - ray.org.z) * ray.rdir.z;
#endif
-#if defined(__AVX2__) && !defined(__AVX512F__) // HSW
+#if defined(__FMA_X4__) && !defined(__AVX512F__) // HSW
const vfloat<N> tNear = maxi(tNearX,tNearY,tNearZ,ray.tnear);
const vfloat<N> tFar = mini(tFarX ,tFarY ,tFarZ ,ray.tfar);
const vbool<N> vmask = asInt(tNear) > asInt(tFar);
@@ -598,13 +651,22 @@ namespace embree
const vfloat<N>* pFarX = (const vfloat<N>*)((const char*)&node->lower_x+ray.farX);
const vfloat<N>* pFarY = (const vfloat<N>*)((const char*)&node->lower_x+ray.farY);
const vfloat<N>* pFarZ = (const vfloat<N>*)((const char*)&node->lower_x+ray.farZ);
-#if defined (__AVX2__) || defined(__ARM_NEON)
+#if defined (__FMA_X4__)
+#if defined(__aarch64__)
+ const vfloat<N> tNearX = madd(madd(time,pNearX[6],vfloat<N>(pNearX[0])), ray.rdir.x, ray.neg_org_rdir.x);
+ const vfloat<N> tNearY = madd(madd(time,pNearY[6],vfloat<N>(pNearY[0])), ray.rdir.y, ray.neg_org_rdir.y);
+ const vfloat<N> tNearZ = madd(madd(time,pNearZ[6],vfloat<N>(pNearZ[0])), ray.rdir.z, ray.neg_org_rdir.z);
+ const vfloat<N> tFarX = madd(madd(time,pFarX [6],vfloat<N>(pFarX [0])), ray.rdir.x, ray.neg_org_rdir.x);
+ const vfloat<N> tFarY = madd(madd(time,pFarY [6],vfloat<N>(pFarY [0])), ray.rdir.y, ray.neg_org_rdir.y);
+ const vfloat<N> tFarZ = madd(madd(time,pFarZ [6],vfloat<N>(pFarZ [0])), ray.rdir.z, ray.neg_org_rdir.z);
+#else
const vfloat<N> tNearX = msub(madd(time,pNearX[6],vfloat<N>(pNearX[0])), ray.rdir.x, ray.org_rdir.x);
const vfloat<N> tNearY = msub(madd(time,pNearY[6],vfloat<N>(pNearY[0])), ray.rdir.y, ray.org_rdir.y);
const vfloat<N> tNearZ = msub(madd(time,pNearZ[6],vfloat<N>(pNearZ[0])), ray.rdir.z, ray.org_rdir.z);
const vfloat<N> tFarX = msub(madd(time,pFarX [6],vfloat<N>(pFarX [0])), ray.rdir.x, ray.org_rdir.x);
const vfloat<N> tFarY = msub(madd(time,pFarY [6],vfloat<N>(pFarY [0])), ray.rdir.y, ray.org_rdir.y);
const vfloat<N> tFarZ = msub(madd(time,pFarZ [6],vfloat<N>(pFarZ [0])), ray.rdir.z, ray.org_rdir.z);
+#endif
#else
const vfloat<N> tNearX = (madd(time,pNearX[6],vfloat<N>(pNearX[0])) - ray.org.x) * ray.rdir.x;
const vfloat<N> tNearY = (madd(time,pNearY[6],vfloat<N>(pNearY[0])) - ray.org.y) * ray.rdir.y;
@@ -613,7 +675,7 @@ namespace embree
const vfloat<N> tFarY = (madd(time,pFarY [6],vfloat<N>(pFarY [0])) - ray.org.y) * ray.rdir.y;
const vfloat<N> tFarZ = (madd(time,pFarZ [6],vfloat<N>(pFarZ [0])) - ray.org.z) * ray.rdir.z;
#endif
-#if defined(__AVX2__) && !defined(__AVX512F__)
+#if defined(__FMA_X4__) && !defined(__AVX512F__)
const vfloat<N> tNear = maxi(maxi(tNearX,tNearY),maxi(tNearZ,ray.tnear));
const vfloat<N> tFar = mini(mini(tFarX ,tFarY ),mini(tFarZ ,ray.tfar ));
#else
@@ -687,13 +749,22 @@ namespace embree
const vfloat4 lower_z = madd(node->dequantize<4>(ray.nearZ >> 2),scale_z,start_z);
const vfloat4 upper_z = madd(node->dequantize<4>(ray.farZ >> 2),scale_z,start_z);
-#if defined(__AVX2__) || defined(__ARM_NEON)
+#if defined(__FMA_X4__)
+#if defined(__aarch64__)
+ const vfloat4 tNearX = madd(lower_x, ray.rdir.x, ray.neg_org_rdir.x);
+ const vfloat4 tNearY = madd(lower_y, ray.rdir.y, ray.neg_org_rdir.y);
+ const vfloat4 tNearZ = madd(lower_z, ray.rdir.z, ray.neg_org_rdir.z);
+ const vfloat4 tFarX = madd(upper_x, ray.rdir.x, ray.neg_org_rdir.x);
+ const vfloat4 tFarY = madd(upper_y, ray.rdir.y, ray.neg_org_rdir.y);
+ const vfloat4 tFarZ = madd(upper_z, ray.rdir.z, ray.neg_org_rdir.z);
+#else
const vfloat4 tNearX = msub(lower_x, ray.rdir.x, ray.org_rdir.x);
const vfloat4 tNearY = msub(lower_y, ray.rdir.y, ray.org_rdir.y);
const vfloat4 tNearZ = msub(lower_z, ray.rdir.z, ray.org_rdir.z);
const vfloat4 tFarX = msub(upper_x, ray.rdir.x, ray.org_rdir.x);
const vfloat4 tFarY = msub(upper_y, ray.rdir.y, ray.org_rdir.y);
const vfloat4 tFarZ = msub(upper_z, ray.rdir.z, ray.org_rdir.z);
+#endif
#else
const vfloat4 tNearX = (lower_x - ray.org.x) * ray.rdir.x;
const vfloat4 tNearY = (lower_y - ray.org.y) * ray.rdir.y;
@@ -703,7 +774,7 @@ namespace embree
const vfloat4 tFarZ = (upper_z - ray.org.z) * ray.rdir.z;
#endif
-#if defined(__SSE4_1__) && !defined(__AVX512F__) // up to HSW
+#if defined(__aarch64__) || defined(__SSE4_1__) && !defined(__AVX512F__) // up to HSW
const vfloat4 tNear = maxi(tNearX,tNearY,tNearZ,ray.tnear);
const vfloat4 tFar = mini(tFarX ,tFarY ,tFarZ ,ray.tfar);
const vbool4 vmask = asInt(tNear) > asInt(tFar);
@@ -775,13 +846,22 @@ namespace embree
const vfloat8 lower_z = madd(node->dequantize<8>(ray.nearZ >> 2),scale_z,start_z);
const vfloat8 upper_z = madd(node->dequantize<8>(ray.farZ >> 2),scale_z,start_z);
-#if defined(__AVX2__) || defined(__ARM_NEON)
+#if defined(__AVX2__)
+#if defined(__aarch64__)
+ const vfloat8 tNearX = madd(lower_x, ray.rdir.x, ray.neg_org_rdir.x);
+ const vfloat8 tNearY = madd(lower_y, ray.rdir.y, ray.neg_org_rdir.y);
+ const vfloat8 tNearZ = madd(lower_z, ray.rdir.z, ray.neg_org_rdir.z);
+ const vfloat8 tFarX = madd(upper_x, ray.rdir.x, ray.neg_org_rdir.x);
+ const vfloat8 tFarY = madd(upper_y, ray.rdir.y, ray.neg_org_rdir.y);
+ const vfloat8 tFarZ = madd(upper_z, ray.rdir.z, ray.neg_org_rdir.z);
+#else
const vfloat8 tNearX = msub(lower_x, ray.rdir.x, ray.org_rdir.x);
const vfloat8 tNearY = msub(lower_y, ray.rdir.y, ray.org_rdir.y);
const vfloat8 tNearZ = msub(lower_z, ray.rdir.z, ray.org_rdir.z);
const vfloat8 tFarX = msub(upper_x, ray.rdir.x, ray.org_rdir.x);
const vfloat8 tFarY = msub(upper_y, ray.rdir.y, ray.org_rdir.y);
const vfloat8 tFarZ = msub(upper_z, ray.rdir.z, ray.org_rdir.z);
+#endif
#else
const vfloat8 tNearX = (lower_x - ray.org.x) * ray.rdir.x;
const vfloat8 tNearY = (lower_y - ray.org.y) * ray.rdir.y;
@@ -857,13 +937,22 @@ namespace embree
const vfloat<N> upper_y = node->dequantizeUpperY(time);
const vfloat<N> lower_z = node->dequantizeLowerZ(time);
const vfloat<N> upper_z = node->dequantizeUpperZ(time);
-#if defined(__AVX2__) || defined(__ARM_NEON)
+#if defined(__FMA_X4__)
+#if defined(__aarch64__)
+ const vfloat<N> tNearX = madd(lower_x, ray.rdir.x, ray.neg_org_rdir.x);
+ const vfloat<N> tNearY = madd(lower_y, ray.rdir.y, ray.neg_org_rdir.y);
+ const vfloat<N> tNearZ = madd(lower_z, ray.rdir.z, ray.neg_org_rdir.z);
+ const vfloat<N> tFarX = madd(upper_x, ray.rdir.x, ray.neg_org_rdir.x);
+ const vfloat<N> tFarY = madd(upper_y, ray.rdir.y, ray.neg_org_rdir.y);
+ const vfloat<N> tFarZ = madd(upper_z, ray.rdir.z, ray.neg_org_rdir.z);
+#else
const vfloat<N> tNearX = msub(lower_x, ray.rdir.x, ray.org_rdir.x);
const vfloat<N> tNearY = msub(lower_y, ray.rdir.y, ray.org_rdir.y);
const vfloat<N> tNearZ = msub(lower_z, ray.rdir.z, ray.org_rdir.z);
const vfloat<N> tFarX = msub(upper_x, ray.rdir.x, ray.org_rdir.x);
const vfloat<N> tFarY = msub(upper_y, ray.rdir.y, ray.org_rdir.y);
const vfloat<N> tFarZ = msub(upper_z, ray.rdir.z, ray.org_rdir.z);
+#endif
#else
const vfloat<N> tNearX = (lower_x - ray.org.x) * ray.rdir.x;
const vfloat<N> tNearY = (lower_y - ray.org.y) * ray.rdir.y;
diff --git a/thirdparty/embree/kernels/bvh/node_intersector_frustum.h b/thirdparty/embree/kernels/bvh/node_intersector_frustum.h
index 1f7215e5df..cad4e6de2d 100644
--- a/thirdparty/embree/kernels/bvh/node_intersector_frustum.h
+++ b/thirdparty/embree/kernels/bvh/node_intersector_frustum.h
@@ -75,9 +75,13 @@ namespace embree
min_rdir = select(pos_rdir, reduced_min_rdir, reduced_max_rdir);
max_rdir = select(pos_rdir, reduced_max_rdir, reduced_min_rdir);
+#if defined (__aarch64__)
+ neg_min_org_rdir = -(min_rdir * select(pos_rdir, reduced_max_org, reduced_min_org));
+ neg_max_org_rdir = -(max_rdir * select(pos_rdir, reduced_min_org, reduced_max_org));
+#else
min_org_rdir = min_rdir * select(pos_rdir, reduced_max_org, reduced_min_org);
max_org_rdir = max_rdir * select(pos_rdir, reduced_min_org, reduced_max_org);
-
+#endif
min_dist = reduced_min_dist;
max_dist = reduced_max_dist;
@@ -95,9 +99,13 @@ namespace embree
Vec3fa min_rdir;
Vec3fa max_rdir;
+#if defined (__aarch64__)
+ Vec3fa neg_min_org_rdir;
+ Vec3fa neg_max_org_rdir;
+#else
Vec3fa min_org_rdir;
Vec3fa max_org_rdir;
-
+#endif
float min_dist;
float max_dist;
};
@@ -191,13 +199,21 @@ namespace embree
const vfloat<N> bmaxY = *(const vfloat<N>*)((const char*)&node->lower_x + frustum.nf.farY);
const vfloat<N> bmaxZ = *(const vfloat<N>*)((const char*)&node->lower_x + frustum.nf.farZ);
+#if defined (__aarch64__)
+ const vfloat<N> fminX = madd(bminX, vfloat<N>(frustum.min_rdir.x), vfloat<N>(frustum.neg_min_org_rdir.x));
+ const vfloat<N> fminY = madd(bminY, vfloat<N>(frustum.min_rdir.y), vfloat<N>(frustum.neg_min_org_rdir.y));
+ const vfloat<N> fminZ = madd(bminZ, vfloat<N>(frustum.min_rdir.z), vfloat<N>(frustum.neg_min_org_rdir.z));
+ const vfloat<N> fmaxX = madd(bmaxX, vfloat<N>(frustum.max_rdir.x), vfloat<N>(frustum.neg_max_org_rdir.x));
+ const vfloat<N> fmaxY = madd(bmaxY, vfloat<N>(frustum.max_rdir.y), vfloat<N>(frustum.neg_max_org_rdir.y));
+ const vfloat<N> fmaxZ = madd(bmaxZ, vfloat<N>(frustum.max_rdir.z), vfloat<N>(frustum.neg_max_org_rdir.z));
+#else
const vfloat<N> fminX = msub(bminX, vfloat<N>(frustum.min_rdir.x), vfloat<N>(frustum.min_org_rdir.x));
const vfloat<N> fminY = msub(bminY, vfloat<N>(frustum.min_rdir.y), vfloat<N>(frustum.min_org_rdir.y));
const vfloat<N> fminZ = msub(bminZ, vfloat<N>(frustum.min_rdir.z), vfloat<N>(frustum.min_org_rdir.z));
const vfloat<N> fmaxX = msub(bmaxX, vfloat<N>(frustum.max_rdir.x), vfloat<N>(frustum.max_org_rdir.x));
const vfloat<N> fmaxY = msub(bmaxY, vfloat<N>(frustum.max_rdir.y), vfloat<N>(frustum.max_org_rdir.y));
const vfloat<N> fmaxZ = msub(bmaxZ, vfloat<N>(frustum.max_rdir.z), vfloat<N>(frustum.max_org_rdir.z));
-
+#endif
const vfloat<N> fmin = maxi(fminX, fminY, fminZ, vfloat<N>(frustum.min_dist));
dist = fmin;
const vfloat<N> fmax = mini(fmaxX, fmaxY, fmaxZ, vfloat<N>(frustum.max_dist));
diff --git a/thirdparty/embree/kernels/bvh/node_intersector_packet.h b/thirdparty/embree/kernels/bvh/node_intersector_packet.h
index d5498fc5db..4deacd620d 100644
--- a/thirdparty/embree/kernels/bvh/node_intersector_packet.h
+++ b/thirdparty/embree/kernels/bvh/node_intersector_packet.h
@@ -39,7 +39,9 @@ namespace embree
org = ray_org;
dir = ray_dir;
rdir = rcp_safe(ray_dir);
-#if defined(__AVX2__) || defined(__ARM_NEON)
+#if defined(__aarch64__)
+ neg_org_rdir = -(org * rdir);
+#elif defined(__AVX2__)
org_rdir = org * rdir;
#endif
@@ -55,7 +57,9 @@ namespace embree
Vec3vf<K> org;
Vec3vf<K> dir;
Vec3vf<K> rdir;
-#if defined(__AVX2__) || defined(__ARM_NEON)
+#if defined(__aarch64__)
+ Vec3vf<K> neg_org_rdir;
+#elif defined(__AVX2__)
Vec3vf<K> org_rdir;
#endif
Vec3vi<K> nearXYZ;
@@ -119,7 +123,14 @@ namespace embree
const TravRayKFast<K>& ray, vfloat<K>& dist)
{
- #if defined(__AVX2__) || defined(__ARM_NEON)
+#if defined(__aarch64__)
+ const vfloat<K> lclipMinX = madd(node->lower_x[i], ray.rdir.x, ray.neg_org_rdir.x);
+ const vfloat<K> lclipMinY = madd(node->lower_y[i], ray.rdir.y, ray.neg_org_rdir.y);
+ const vfloat<K> lclipMinZ = madd(node->lower_z[i], ray.rdir.z, ray.neg_org_rdir.z);
+ const vfloat<K> lclipMaxX = madd(node->upper_x[i], ray.rdir.x, ray.neg_org_rdir.x);
+ const vfloat<K> lclipMaxY = madd(node->upper_y[i], ray.rdir.y, ray.neg_org_rdir.y);
+ const vfloat<K> lclipMaxZ = madd(node->upper_z[i], ray.rdir.z, ray.neg_org_rdir.z);
+#elif defined(__AVX2__)
const vfloat<K> lclipMinX = msub(node->lower_x[i], ray.rdir.x, ray.org_rdir.x);
const vfloat<K> lclipMinY = msub(node->lower_y[i], ray.rdir.y, ray.org_rdir.y);
const vfloat<K> lclipMinZ = msub(node->lower_z[i], ray.rdir.z, ray.org_rdir.z);
@@ -199,7 +210,14 @@ namespace embree
const vfloat<K> vupper_y = madd(time, vfloat<K>(node->upper_dy[i]), vfloat<K>(node->upper_y[i]));
const vfloat<K> vupper_z = madd(time, vfloat<K>(node->upper_dz[i]), vfloat<K>(node->upper_z[i]));
-#if defined(__AVX2__) || defined(__ARM_NEON)
+#if defined(__aarch64__)
+ const vfloat<K> lclipMinX = madd(vlower_x, ray.rdir.x, ray.neg_org_rdir.x);
+ const vfloat<K> lclipMinY = madd(vlower_y, ray.rdir.y, ray.neg_org_rdir.y);
+ const vfloat<K> lclipMinZ = madd(vlower_z, ray.rdir.z, ray.neg_org_rdir.z);
+ const vfloat<K> lclipMaxX = madd(vupper_x, ray.rdir.x, ray.neg_org_rdir.x);
+ const vfloat<K> lclipMaxY = madd(vupper_y, ray.rdir.y, ray.neg_org_rdir.y);
+ const vfloat<K> lclipMaxZ = madd(vupper_z, ray.rdir.z, ray.neg_org_rdir.z);
+#elif defined(__AVX2__)
const vfloat<K> lclipMinX = msub(vlower_x, ray.rdir.x, ray.org_rdir.x);
const vfloat<K> lclipMinY = msub(vlower_y, ray.rdir.y, ray.org_rdir.y);
const vfloat<K> lclipMinZ = msub(vlower_z, ray.rdir.z, ray.org_rdir.z);
@@ -302,7 +320,14 @@ namespace embree
const vfloat<K> vupper_y = madd(time, vfloat<K>(node->upper_dy[i]), vfloat<K>(node->upper_y[i]));
const vfloat<K> vupper_z = madd(time, vfloat<K>(node->upper_dz[i]), vfloat<K>(node->upper_z[i]));
-#if defined(__AVX2__) || defined(__ARM_NEON)
+#if defined(__aarch64__)
+ const vfloat<K> lclipMinX = madd(vlower_x, ray.rdir.x, ray.neg_org_rdir.x);
+ const vfloat<K> lclipMinY = madd(vlower_y, ray.rdir.y, ray.neg_org_rdir.y);
+ const vfloat<K> lclipMinZ = madd(vlower_z, ray.rdir.z, ray.neg_org_rdir.z);
+ const vfloat<K> lclipMaxX = madd(vupper_x, ray.rdir.x, ray.neg_org_rdir.x);
+ const vfloat<K> lclipMaxY = madd(vupper_y, ray.rdir.y, ray.neg_org_rdir.y);
+ const vfloat<K> lclipMaxZ = madd(vupper_z, ray.rdir.z, ray.neg_org_rdir.z);
+#elif defined(__AVX2__)
const vfloat<K> lclipMinX = msub(vlower_x, ray.rdir.x, ray.org_rdir.x);
const vfloat<K> lclipMinY = msub(vlower_y, ray.rdir.y, ray.org_rdir.y);
const vfloat<K> lclipMinZ = msub(vlower_z, ray.rdir.z, ray.org_rdir.z);
@@ -464,7 +489,14 @@ namespace embree
const vfloat<N> lower_z = node->dequantizeLowerZ();
const vfloat<N> upper_z = node->dequantizeUpperZ();
- #if defined(__AVX2__) || defined(__ARM_NEON)
+ #if defined(__aarch64__)
+ const vfloat<K> lclipMinX = madd(lower_x[i], ray.rdir.x, ray.neg_org_rdir.x);
+ const vfloat<K> lclipMinY = madd(lower_y[i], ray.rdir.y, ray.neg_org_rdir.y);
+ const vfloat<K> lclipMinZ = madd(lower_z[i], ray.rdir.z, ray.neg_org_rdir.z);
+ const vfloat<K> lclipMaxX = madd(upper_x[i], ray.rdir.x, ray.neg_org_rdir.x);
+ const vfloat<K> lclipMaxY = madd(upper_y[i], ray.rdir.y, ray.neg_org_rdir.y);
+ const vfloat<K> lclipMaxZ = madd(upper_z[i], ray.rdir.z, ray.neg_org_rdir.z);
+ #elif defined(__AVX2__)
const vfloat<K> lclipMinX = msub(lower_x[i], ray.rdir.x, ray.org_rdir.x);
const vfloat<K> lclipMinY = msub(lower_y[i], ray.rdir.y, ray.org_rdir.y);
const vfloat<K> lclipMinZ = msub(lower_z[i], ray.rdir.z, ray.org_rdir.z);
@@ -549,7 +581,14 @@ namespace embree
const vfloat<K> lower_z = node->template dequantizeLowerZ<K>(i,time);
const vfloat<K> upper_z = node->template dequantizeUpperZ<K>(i,time);
-#if defined(__AVX2__) || defined(__ARM_NEON)
+#if defined(__aarch64__)
+ const vfloat<K> lclipMinX = madd(lower_x, ray.rdir.x, ray.neg_org_rdir.x);
+ const vfloat<K> lclipMinY = madd(lower_y, ray.rdir.y, ray.neg_org_rdir.y);
+ const vfloat<K> lclipMinZ = madd(lower_z, ray.rdir.z, ray.neg_org_rdir.z);
+ const vfloat<K> lclipMaxX = madd(upper_x, ray.rdir.x, ray.neg_org_rdir.x);
+ const vfloat<K> lclipMaxY = madd(upper_y, ray.rdir.y, ray.neg_org_rdir.y);
+ const vfloat<K> lclipMaxZ = madd(upper_z, ray.rdir.z, ray.neg_org_rdir.z);
+#elif defined(__AVX2__)
const vfloat<K> lclipMinX = msub(lower_x, ray.rdir.x, ray.org_rdir.x);
const vfloat<K> lclipMinY = msub(lower_y, ray.rdir.y, ray.org_rdir.y);
const vfloat<K> lclipMinZ = msub(lower_z, ray.rdir.z, ray.org_rdir.z);
diff --git a/thirdparty/embree/kernels/bvh/node_intersector_packet_stream.h b/thirdparty/embree/kernels/bvh/node_intersector_packet_stream.h
index 55b2c27231..943fd7043f 100644
--- a/thirdparty/embree/kernels/bvh/node_intersector_packet_stream.h
+++ b/thirdparty/embree/kernels/bvh/node_intersector_packet_stream.h
@@ -32,11 +32,19 @@ namespace embree
__forceinline void init(const Vec3vf<K>& ray_org, const Vec3vf<K>& ray_dir)
{
rdir = rcp_safe(ray_dir);
+#if defined(__aarch64__)
+ neg_org_rdir = -(ray_org * rdir);
+#else
org_rdir = ray_org * rdir;
+#endif
}
Vec3vf<K> rdir;
+#if defined(__aarch64__)
+ Vec3vf<K> neg_org_rdir;
+#else
Vec3vf<K> org_rdir;
+#endif
vfloat<K> tnear;
vfloat<K> tfar;
};
@@ -87,12 +95,21 @@ namespace embree
const vfloat<N> bmaxY = vfloat<N>(*(const vfloat<N>*)((const char*)&node->lower_x + nf.farY));
const vfloat<N> bmaxZ = vfloat<N>(*(const vfloat<N>*)((const char*)&node->lower_x + nf.farZ));
+#if defined (__aarch64__)
+ const vfloat<N> rminX = madd(bminX, vfloat<N>(ray.rdir.x[k]), vfloat<N>(ray.neg_org_rdir.x[k]));
+ const vfloat<N> rminY = madd(bminY, vfloat<N>(ray.rdir.y[k]), vfloat<N>(ray.neg_org_rdir.y[k]));
+ const vfloat<N> rminZ = madd(bminZ, vfloat<N>(ray.rdir.z[k]), vfloat<N>(ray.neg_org_rdir.z[k]));
+ const vfloat<N> rmaxX = madd(bmaxX, vfloat<N>(ray.rdir.x[k]), vfloat<N>(ray.neg_org_rdir.x[k]));
+ const vfloat<N> rmaxY = madd(bmaxY, vfloat<N>(ray.rdir.y[k]), vfloat<N>(ray.neg_org_rdir.y[k]));
+ const vfloat<N> rmaxZ = madd(bmaxZ, vfloat<N>(ray.rdir.z[k]), vfloat<N>(ray.neg_org_rdir.z[k]));
+#else
const vfloat<N> rminX = msub(bminX, vfloat<N>(ray.rdir.x[k]), vfloat<N>(ray.org_rdir.x[k]));
const vfloat<N> rminY = msub(bminY, vfloat<N>(ray.rdir.y[k]), vfloat<N>(ray.org_rdir.y[k]));
const vfloat<N> rminZ = msub(bminZ, vfloat<N>(ray.rdir.z[k]), vfloat<N>(ray.org_rdir.z[k]));
const vfloat<N> rmaxX = msub(bmaxX, vfloat<N>(ray.rdir.x[k]), vfloat<N>(ray.org_rdir.x[k]));
const vfloat<N> rmaxY = msub(bmaxY, vfloat<N>(ray.rdir.y[k]), vfloat<N>(ray.org_rdir.y[k]));
const vfloat<N> rmaxZ = msub(bmaxZ, vfloat<N>(ray.rdir.z[k]), vfloat<N>(ray.org_rdir.z[k]));
+#endif
const vfloat<N> rmin = maxi(rminX, rminY, rminZ, vfloat<N>(ray.tnear[k]));
const vfloat<N> rmax = mini(rmaxX, rmaxY, rmaxZ, vfloat<N>(ray.tfar[k]));
@@ -113,12 +130,21 @@ namespace embree
const vfloat<K> bmaxY = *(const float*)(ptr + nf.farY);
const vfloat<K> bmaxZ = *(const float*)(ptr + nf.farZ);
+#if defined (__aarch64__)
+ const vfloat<K> rminX = madd(bminX, ray.rdir.x, ray.neg_org_rdir.x);
+ const vfloat<K> rminY = madd(bminY, ray.rdir.y, ray.neg_org_rdir.y);
+ const vfloat<K> rminZ = madd(bminZ, ray.rdir.z, ray.neg_org_rdir.z);
+ const vfloat<K> rmaxX = madd(bmaxX, ray.rdir.x, ray.neg_org_rdir.x);
+ const vfloat<K> rmaxY = madd(bmaxY, ray.rdir.y, ray.neg_org_rdir.y);
+ const vfloat<K> rmaxZ = madd(bmaxZ, ray.rdir.z, ray.neg_org_rdir.z);
+#else
const vfloat<K> rminX = msub(bminX, ray.rdir.x, ray.org_rdir.x);
const vfloat<K> rminY = msub(bminY, ray.rdir.y, ray.org_rdir.y);
const vfloat<K> rminZ = msub(bminZ, ray.rdir.z, ray.org_rdir.z);
const vfloat<K> rmaxX = msub(bmaxX, ray.rdir.x, ray.org_rdir.x);
const vfloat<K> rmaxY = msub(bmaxY, ray.rdir.y, ray.org_rdir.y);
const vfloat<K> rmaxZ = msub(bmaxZ, ray.rdir.z, ray.org_rdir.z);
+#endif
const vfloat<K> rmin = maxi(rminX, rminY, rminZ, ray.tnear);
const vfloat<K> rmax = mini(rmaxX, rmaxY, rmaxZ, ray.tfar);
diff --git a/thirdparty/embree/kernels/common/accel.h b/thirdparty/embree/kernels/common/accel.h
index cc4ea1805b..d24326ce92 100644
--- a/thirdparty/embree/kernels/common/accel.h
+++ b/thirdparty/embree/kernels/common/accel.h
@@ -332,7 +332,7 @@ namespace embree
intersectorN.intersect(this,rayN,N,context);
}
-#if defined(__SSE__)
+#if defined(__SSE__) || defined(__ARM_NEON)
__forceinline void intersect(const vbool4& valid, RayHitK<4>& ray, IntersectContext* context) {
const vint<4> mask = valid.mask32();
intersect4(&mask,(RTCRayHit4&)ray,context);
@@ -388,7 +388,7 @@ namespace embree
intersectorN.occluded(this,rayN,N,context);
}
-#if defined(__SSE__)
+#if defined(__SSE__) || defined(__ARM_NEON)
__forceinline void occluded(const vbool4& valid, RayK<4>& ray, IntersectContext* context) {
const vint<4> mask = valid.mask32();
occluded4(&mask,(RTCRay4&)ray,context);
diff --git a/thirdparty/embree/kernels/common/acceln.cpp b/thirdparty/embree/kernels/common/acceln.cpp
index 32a27c560a..111c62083d 100644
--- a/thirdparty/embree/kernels/common/acceln.cpp
+++ b/thirdparty/embree/kernels/common/acceln.cpp
@@ -97,7 +97,7 @@ namespace embree
for (size_t i=0; i<This->accels.size(); i++) {
if (This->accels[i]->isEmpty()) continue;
This->accels[i]->intersectors.occluded4(valid,ray,context);
-#if defined(__SSE2__)
+#if defined(__SSE2__) || defined(__ARM_NEON)
vbool4 valid0 = asBool(((vint4*)valid)[0]);
vbool4 hit0 = ((vfloat4*)ray.tfar)[0] >= vfloat4(zero);
if (unlikely(none(valid0 & hit0))) break;
@@ -111,7 +111,7 @@ namespace embree
for (size_t i=0; i<This->accels.size(); i++) {
if (This->accels[i]->isEmpty()) continue;
This->accels[i]->intersectors.occluded8(valid,ray,context);
-#if defined(__SSE2__) // FIXME: use higher ISA
+#if defined(__SSE2__) || defined(__ARM_NEON) // FIXME: use higher ISA
vbool4 valid0 = asBool(((vint4*)valid)[0]);
vbool4 hit0 = ((vfloat4*)ray.tfar)[0] >= vfloat4(zero);
vbool4 valid1 = asBool(((vint4*)valid)[1]);
@@ -127,7 +127,7 @@ namespace embree
for (size_t i=0; i<This->accels.size(); i++) {
if (This->accels[i]->isEmpty()) continue;
This->accels[i]->intersectors.occluded16(valid,ray,context);
-#if defined(__SSE2__) // FIXME: use higher ISA
+#if defined(__SSE2__) || defined(__ARM_NEON) // FIXME: use higher ISA
vbool4 valid0 = asBool(((vint4*)valid)[0]);
vbool4 hit0 = ((vfloat4*)ray.tfar)[0] >= vfloat4(zero);
vbool4 valid1 = asBool(((vint4*)valid)[1]);
diff --git a/thirdparty/embree/kernels/common/accelset.h b/thirdparty/embree/kernels/common/accelset.h
index 90b184a07b..1b67120c97 100644
--- a/thirdparty/embree/kernels/common/accelset.h
+++ b/thirdparty/embree/kernels/common/accelset.h
@@ -14,21 +14,14 @@ namespace embree
struct IntersectFunctionNArguments;
struct OccludedFunctionNArguments;
- typedef void (*ReportIntersectionFunc) (IntersectFunctionNArguments* args, const RTCFilterFunctionNArguments* filter_args);
- typedef void (*ReportOcclusionFunc) (OccludedFunctionNArguments* args, const RTCFilterFunctionNArguments* filter_args);
-
struct IntersectFunctionNArguments : public RTCIntersectFunctionNArguments
{
- IntersectContext* internal_context;
Geometry* geometry;
- ReportIntersectionFunc report;
};
struct OccludedFunctionNArguments : public RTCOccludedFunctionNArguments
{
- IntersectContext* internal_context;
Geometry* geometry;
- ReportOcclusionFunc report;
};
/*! Base class for set of acceleration structures. */
@@ -145,7 +138,7 @@ namespace embree
public:
/*! Intersects a single ray with the scene. */
- __forceinline void intersect (RayHit& ray, unsigned int geomID, unsigned int primID, IntersectContext* context, ReportIntersectionFunc report)
+ __forceinline void intersect (RayHit& ray, unsigned int geomID, unsigned int primID, IntersectContext* context)
{
assert(primID < size());
assert(intersectorN.intersect);
@@ -159,15 +152,13 @@ namespace embree
args.N = 1;
args.geomID = geomID;
args.primID = primID;
- args.internal_context = context;
args.geometry = this;
- args.report = report;
intersectorN.intersect(&args);
}
/*! Tests if single ray is occluded by the scene. */
- __forceinline void occluded (Ray& ray, unsigned int geomID, unsigned int primID, IntersectContext* context, ReportOcclusionFunc report)
+ __forceinline void occluded (Ray& ray, unsigned int geomID, unsigned int primID, IntersectContext* context)
{
assert(primID < size());
assert(intersectorN.occluded);
@@ -181,16 +172,14 @@ namespace embree
args.N = 1;
args.geomID = geomID;
args.primID = primID;
- args.internal_context = context;
args.geometry = this;
- args.report = report;
intersectorN.occluded(&args);
}
/*! Intersects a packet of K rays with the scene. */
template<int K>
- __forceinline void intersect (const vbool<K>& valid, RayHitK<K>& ray, unsigned int geomID, unsigned int primID, IntersectContext* context, ReportIntersectionFunc report)
+ __forceinline void intersect (const vbool<K>& valid, RayHitK<K>& ray, unsigned int geomID, unsigned int primID, IntersectContext* context)
{
assert(primID < size());
assert(intersectorN.intersect);
@@ -204,16 +193,14 @@ namespace embree
args.N = K;
args.geomID = geomID;
args.primID = primID;
- args.internal_context = context;
args.geometry = this;
- args.report = report;
intersectorN.intersect(&args);
}
/*! Tests if a packet of K rays is occluded by the scene. */
template<int K>
- __forceinline void occluded (const vbool<K>& valid, RayK<K>& ray, unsigned int geomID, unsigned int primID, IntersectContext* context, ReportOcclusionFunc report)
+ __forceinline void occluded (const vbool<K>& valid, RayK<K>& ray, unsigned int geomID, unsigned int primID, IntersectContext* context)
{
assert(primID < size());
assert(intersectorN.occluded);
@@ -227,9 +214,7 @@ namespace embree
args.N = K;
args.geomID = geomID;
args.primID = primID;
- args.internal_context = context;
args.geometry = this;
- args.report = report;
intersectorN.occluded(&args);
}
diff --git a/thirdparty/embree/kernels/common/alloc.cpp b/thirdparty/embree/kernels/common/alloc.cpp
index 1a0e1aeed3..38a76225f4 100644
--- a/thirdparty/embree/kernels/common/alloc.cpp
+++ b/thirdparty/embree/kernels/common/alloc.cpp
@@ -3,6 +3,9 @@
#include "alloc.h"
#include "../../common/sys/thread.h"
+#if defined(APPLE) && defined(__aarch64__)
+#include "../../common/sys/barrier.h"
+#endif
namespace embree
{
diff --git a/thirdparty/embree/kernels/common/alloc.h b/thirdparty/embree/kernels/common/alloc.h
index 4458e35c24..12769df2c8 100644
--- a/thirdparty/embree/kernels/common/alloc.h
+++ b/thirdparty/embree/kernels/common/alloc.h
@@ -8,6 +8,10 @@
#include "scene.h"
#include "primref.h"
+#if defined(APPLE) && defined(__aarch64__)
+#include <mutex>
+#endif
+
namespace embree
{
class FastAllocator
@@ -26,7 +30,7 @@ namespace embree
public:
struct ThreadLocal2;
- enum AllocationType { ALIGNED_MALLOC, OS_MALLOC, SHARED, ANY_TYPE };
+ enum AllocationType { ALIGNED_MALLOC, EMBREE_OS_MALLOC, SHARED, ANY_TYPE };
/*! Per thread structure holding the current memory block. */
struct __aligned(64) ThreadLocal
@@ -132,7 +136,11 @@ namespace embree
{
assert(alloc_i);
if (alloc.load() == alloc_i) return;
+#if defined(APPLE) && defined(__aarch64__)
+ std::scoped_lock lock(mutex);
+#else
Lock<SpinLock> lock(mutex);
+#endif
//if (alloc.load() == alloc_i) return; // not required as only one thread calls bind
if (alloc.load()) {
alloc.load()->bytesUsed += alloc0.getUsedBytes() + alloc1.getUsedBytes();
@@ -150,7 +158,11 @@ namespace embree
{
assert(alloc_i);
if (alloc.load() != alloc_i) return;
+#if defined(APPLE) && defined(__aarch64__)
+ std::scoped_lock lock(mutex);
+#else
Lock<SpinLock> lock(mutex);
+#endif
if (alloc.load() != alloc_i) return; // required as a different thread calls unbind
alloc.load()->bytesUsed += alloc0.getUsedBytes() + alloc1.getUsedBytes();
alloc.load()->bytesFree += alloc0.getFreeBytes() + alloc1.getFreeBytes();
@@ -161,7 +173,11 @@ namespace embree
}
public:
+#if defined(APPLE) && defined(__aarch64__)
+ std::mutex mutex;
+#else
SpinLock mutex; //!< required as unbind is called from other threads
+#endif
std::atomic<FastAllocator*> alloc; //!< parent allocator
ThreadLocal alloc0;
ThreadLocal alloc1;
@@ -169,7 +185,7 @@ namespace embree
FastAllocator (Device* device, bool osAllocation)
: device(device), slotMask(0), usedBlocks(nullptr), freeBlocks(nullptr), use_single_mode(false), defaultBlockSize(PAGE_SIZE), estimatedSize(0),
- growSize(PAGE_SIZE), maxGrowSize(maxAllocationSize), log2_grow_size_scale(0), bytesUsed(0), bytesFree(0), bytesWasted(0), atype(osAllocation ? OS_MALLOC : ALIGNED_MALLOC),
+ growSize(PAGE_SIZE), maxGrowSize(maxAllocationSize), log2_grow_size_scale(0), bytesUsed(0), bytesFree(0), bytesWasted(0), atype(osAllocation ? EMBREE_OS_MALLOC : ALIGNED_MALLOC),
primrefarray(device,0)
{
for (size_t i=0; i<MAX_THREAD_USED_BLOCK_SLOTS; i++)
@@ -206,7 +222,7 @@ namespace embree
void setOSallocation(bool flag)
{
- atype = flag ? OS_MALLOC : ALIGNED_MALLOC;
+ atype = flag ? EMBREE_OS_MALLOC : ALIGNED_MALLOC;
}
private:
@@ -217,7 +233,11 @@ namespace embree
ThreadLocal2* alloc = thread_local_allocator2;
if (alloc == nullptr) {
thread_local_allocator2 = alloc = new ThreadLocal2;
+#if defined(APPLE) && defined(__aarch64__)
+ std::scoped_lock lock(s_thread_local_allocators_lock);
+#else
Lock<SpinLock> lock(s_thread_local_allocators_lock);
+#endif
s_thread_local_allocators.push_back(make_unique(alloc));
}
return alloc;
@@ -227,7 +247,11 @@ namespace embree
__forceinline void join(ThreadLocal2* alloc)
{
+#if defined(APPLE) && defined(__aarch64__)
+ std::scoped_lock lock(s_thread_local_allocators_lock);
+#else
Lock<SpinLock> lock(thread_local_allocators_lock);
+#endif
thread_local_allocators.push_back(alloc);
}
@@ -492,7 +516,11 @@ namespace embree
/* parallel block creation in case of no freeBlocks, avoids single global mutex */
if (likely(freeBlocks.load() == nullptr))
{
+#if defined(APPLE) && defined(__aarch64__)
+ std::scoped_lock lock(slotMutex[slot]);
+#else
Lock<SpinLock> lock(slotMutex[slot]);
+#endif
if (myUsedBlocks == threadUsedBlocks[slot]) {
const size_t alignedBytes = (bytes+(align-1)) & ~(align-1);
const size_t allocSize = max(min(growSize,maxGrowSize),alignedBytes);
@@ -505,7 +533,11 @@ namespace embree
/* if this fails allocate new block */
{
- Lock<SpinLock> lock(mutex);
+#if defined(APPLE) && defined(__aarch64__)
+ std::scoped_lock lock(mutex);
+#else
+ Lock<SpinLock> lock(mutex);
+#endif
if (myUsedBlocks == threadUsedBlocks[slot])
{
if (freeBlocks.load() != nullptr) {
@@ -527,7 +559,11 @@ namespace embree
/*! add new block */
void addBlock(void* ptr, ssize_t bytes)
{
+#if defined(APPLE) && defined(__aarch64__)
+ std::scoped_lock lock(mutex);
+#else
Lock<SpinLock> lock(mutex);
+#endif
const size_t sizeof_Header = offsetof(Block,data[0]);
void* aptr = (void*) ((((size_t)ptr)+maxAlignment-1) & ~(maxAlignment-1));
size_t ofs = (size_t) aptr - (size_t) ptr;
@@ -613,8 +649,8 @@ namespace embree
bytesWasted(alloc->bytesWasted),
stat_all(alloc,ANY_TYPE),
stat_malloc(alloc,ALIGNED_MALLOC),
- stat_4K(alloc,OS_MALLOC,false),
- stat_2M(alloc,OS_MALLOC,true),
+ stat_4K(alloc,EMBREE_OS_MALLOC,false),
+ stat_2M(alloc,EMBREE_OS_MALLOC,true),
stat_shared(alloc,SHARED) {}
AllStatistics (size_t bytesUsed,
@@ -707,7 +743,7 @@ namespace embree
/* We avoid using os_malloc for small blocks as this could
* cause a risk of fragmenting the virtual address space and
* reach the limit of vm.max_map_count = 65k under Linux. */
- if (atype == OS_MALLOC && bytesAllocate < maxAllocationSize)
+ if (atype == EMBREE_OS_MALLOC && bytesAllocate < maxAllocationSize)
atype = ALIGNED_MALLOC;
/* we need to additionally allocate some header */
@@ -716,7 +752,7 @@ namespace embree
bytesReserve = sizeof_Header+bytesReserve;
/* consume full 4k pages with using os_malloc */
- if (atype == OS_MALLOC) {
+ if (atype == EMBREE_OS_MALLOC) {
bytesAllocate = ((bytesAllocate+PAGE_SIZE-1) & ~(PAGE_SIZE-1));
bytesReserve = ((bytesReserve +PAGE_SIZE-1) & ~(PAGE_SIZE-1));
}
@@ -748,11 +784,11 @@ namespace embree
return new (ptr) Block(ALIGNED_MALLOC,bytesAllocate-sizeof_Header,bytesAllocate-sizeof_Header,next,alignment);
}
}
- else if (atype == OS_MALLOC)
+ else if (atype == EMBREE_OS_MALLOC)
{
if (device) device->memoryMonitor(bytesAllocate,false);
bool huge_pages; ptr = os_malloc(bytesReserve,huge_pages);
- return new (ptr) Block(OS_MALLOC,bytesAllocate-sizeof_Header,bytesReserve-sizeof_Header,next,0,huge_pages);
+ return new (ptr) Block(EMBREE_OS_MALLOC,bytesAllocate-sizeof_Header,bytesReserve-sizeof_Header,next,0,huge_pages);
}
else
assert(false);
@@ -796,7 +832,7 @@ namespace embree
if (device) device->memoryMonitor(-sizeof_Alloced,true);
}
- else if (atype == OS_MALLOC) {
+ else if (atype == EMBREE_OS_MALLOC) {
size_t sizeof_This = sizeof_Header+reserveEnd;
os_free(this,sizeof_This,huge_pages);
if (device) device->memoryMonitor(-sizeof_Alloced,true);
@@ -857,7 +893,7 @@ namespace embree
bool hasType(AllocationType atype_i, bool huge_pages_i) const
{
if (atype_i == ANY_TYPE ) return true;
- else if (atype == OS_MALLOC) return atype_i == atype && huge_pages_i == huge_pages;
+ else if (atype == EMBREE_OS_MALLOC) return atype_i == atype && huge_pages_i == huge_pages;
else return atype_i == atype;
}
@@ -906,7 +942,7 @@ namespace embree
void print_block() const
{
if (atype == ALIGNED_MALLOC) std::cout << "A";
- else if (atype == OS_MALLOC) std::cout << "O";
+ else if (atype == EMBREE_OS_MALLOC) std::cout << "O";
else if (atype == SHARED) std::cout << "S";
if (huge_pages) std::cout << "H";
size_t bytesUsed = getBlockUsedBytes();
@@ -936,7 +972,11 @@ namespace embree
std::atomic<Block*> freeBlocks;
std::atomic<Block*> threadBlocks[MAX_THREAD_USED_BLOCK_SLOTS];
- SpinLock slotMutex[MAX_THREAD_USED_BLOCK_SLOTS];
+#if defined(APPLE) && defined(__aarch64__)
+ std::mutex slotMutex[MAX_THREAD_USED_BLOCK_SLOTS];
+#else
+ PaddedSpinLock slotMutex[MAX_THREAD_USED_BLOCK_SLOTS];
+#endif
bool use_single_mode;
size_t defaultBlockSize;
@@ -950,7 +990,11 @@ namespace embree
static __thread ThreadLocal2* thread_local_allocator2;
static SpinLock s_thread_local_allocators_lock;
static std::vector<std::unique_ptr<ThreadLocal2>> s_thread_local_allocators;
+#if defined(APPLE) && defined(__aarch64__)
+ std::mutex thread_local_allocators_lock;
+#else
SpinLock thread_local_allocators_lock;
+#endif
std::vector<ThreadLocal2*> thread_local_allocators;
AllocationType atype;
mvector<PrimRef> primrefarray; //!< primrefarray used to allocate nodes
diff --git a/thirdparty/embree/kernels/common/device.cpp b/thirdparty/embree/kernels/common/device.cpp
index 068e0c2983..833ec65139 100644
--- a/thirdparty/embree/kernels/common/device.cpp
+++ b/thirdparty/embree/kernels/common/device.cpp
@@ -66,7 +66,11 @@ namespace embree
case CPU::CORE1: frequency_level = FREQUENCY_SIMD128; break;
case CPU::XEON_PHI_KNIGHTS_MILL : frequency_level = FREQUENCY_SIMD512; break;
case CPU::XEON_PHI_KNIGHTS_LANDING: frequency_level = FREQUENCY_SIMD512; break;
+#if defined(__APPLE__)
+ case CPU::ARM: frequency_level = FREQUENCY_SIMD256; break; // Apple M1 supports high throughput for SIMD4
+#else
case CPU::ARM: frequency_level = FREQUENCY_SIMD128; break;
+#endif
}
/* initialize global state */
diff --git a/thirdparty/embree/kernels/common/geometry.h b/thirdparty/embree/kernels/common/geometry.h
index 2f9f2e7c94..593990f5b1 100644
--- a/thirdparty/embree/kernels/common/geometry.h
+++ b/thirdparty/embree/kernels/common/geometry.h
@@ -91,7 +91,7 @@ namespace embree
size_t numFilterFunctions; //!< number of geometries with filter functions enabled
size_t numTriangles; //!< number of enabled triangles
- size_t numMBTriangles; //!< number of enabled motion blured triangles
+ size_t numMBTriangles; //!< number of enabled motion blurred triangles
size_t numQuads; //!< number of enabled quads
size_t numMBQuads; //!< number of enabled motion blurred quads
size_t numBezierCurves; //!< number of enabled curves
@@ -99,7 +99,7 @@ namespace embree
size_t numLineSegments; //!< number of enabled line segments
size_t numMBLineSegments; //!< number of enabled line motion blurred segments
size_t numSubdivPatches; //!< number of enabled subdivision patches
- size_t numMBSubdivPatches; //!< number of enabled motion blured subdivision patches
+ size_t numMBSubdivPatches; //!< number of enabled motion blurred subdivision patches
size_t numUserGeometries; //!< number of enabled user geometries
size_t numMBUserGeometries; //!< number of enabled motion blurred user geometries
size_t numInstancesCheap; //!< number of enabled cheap instances
diff --git a/thirdparty/embree/kernels/common/isa.h b/thirdparty/embree/kernels/common/isa.h
index ae6556336c..9e1132e1a0 100644
--- a/thirdparty/embree/kernels/common/isa.h
+++ b/thirdparty/embree/kernels/common/isa.h
@@ -44,7 +44,7 @@ namespace embree
#define SELECT_SYMBOL_DEFAULT(features,intersector) \
intersector = isa::intersector;
-#if defined(__SSE__)
+#if defined(__SSE__) || defined(__ARM_NEON)
#if !defined(EMBREE_TARGET_SIMD4)
#define EMBREE_TARGET_SIMD4
#endif
diff --git a/thirdparty/embree/kernels/common/ray.h b/thirdparty/embree/kernels/common/ray.h
index 7b951cc1e8..3c8ee3989c 100644
--- a/thirdparty/embree/kernels/common/ray.h
+++ b/thirdparty/embree/kernels/common/ray.h
@@ -6,7 +6,7 @@
#include "default.h"
#include "instance_stack.h"
-// FIXME: if ray gets seperated into ray* and hit, uload4 needs to be adjusted
+// FIXME: if ray gets separated into ray* and hit, uload4 needs to be adjusted
namespace embree
{
diff --git a/thirdparty/embree/kernels/common/rtcore.cpp b/thirdparty/embree/kernels/common/rtcore.cpp
index 94b3819e42..a6ea55bfc4 100644
--- a/thirdparty/embree/kernels/common/rtcore.cpp
+++ b/thirdparty/embree/kernels/common/rtcore.cpp
@@ -7,6 +7,7 @@
#include "device.h"
#include "scene.h"
#include "context.h"
+#include "../geometry/filter.h"
#include "../../include/embree3/rtcore_ray.h"
using namespace embree;
@@ -482,7 +483,7 @@ RTC_NAMESPACE_BEGIN;
IntersectContext context(scene,user_context);
#if !defined(EMBREE_RAY_PACKETS)
- Ray4* ray4 = (Ray4*) rayhit;
+ RayHit4* ray4 = (RayHit4*) rayhit;
for (size_t i=0; i<4; i++) {
if (!valid[i]) continue;
RayHit ray1; ray4->get(i,ray1);
@@ -513,7 +514,7 @@ RTC_NAMESPACE_BEGIN;
IntersectContext context(scene,user_context);
#if !defined(EMBREE_RAY_PACKETS)
- Ray8* ray8 = (Ray8*) rayhit;
+ RayHit8* ray8 = (RayHit8*) rayhit;
for (size_t i=0; i<8; i++) {
if (!valid[i]) continue;
RayHit ray1; ray8->get(i,ray1);
@@ -546,7 +547,7 @@ RTC_NAMESPACE_BEGIN;
IntersectContext context(scene,user_context);
#if !defined(EMBREE_RAY_PACKETS)
- Ray16* ray16 = (Ray16*) rayhit;
+ RayHit16* ray16 = (RayHit16*) rayhit;
for (size_t i=0; i<16; i++) {
if (!valid[i]) continue;
RayHit ray1; ray16->get(i,ray1);
@@ -1097,13 +1098,13 @@ RTC_NAMESPACE_BEGIN;
RTC_API void rtcFilterIntersection(const struct RTCIntersectFunctionNArguments* const args_i, const struct RTCFilterFunctionNArguments* filter_args)
{
IntersectFunctionNArguments* args = (IntersectFunctionNArguments*) args_i;
- args->report(args,filter_args);
+ isa::reportIntersection1(args, filter_args);
}
RTC_API void rtcFilterOcclusion(const struct RTCOccludedFunctionNArguments* const args_i, const struct RTCFilterFunctionNArguments* filter_args)
{
OccludedFunctionNArguments* args = (OccludedFunctionNArguments*) args_i;
- args->report(args,filter_args);
+ isa::reportOcclusion1(args,filter_args);
}
RTC_API RTCGeometry rtcNewGeometry (RTCDevice hdevice, RTCGeometryType type)
@@ -1763,4 +1764,19 @@ RTC_NAMESPACE_BEGIN;
return nullptr;
}
+ RTC_API RTCGeometry rtcGetGeometryThreadSafe (RTCScene hscene, unsigned int geomID)
+ {
+ Scene* scene = (Scene*) hscene;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcGetGeometryThreadSafe);
+#if defined(DEBUG)
+ RTC_VERIFY_HANDLE(hscene);
+ RTC_VERIFY_GEOMID(geomID);
+#endif
+ Ref<Geometry> geom = scene->get_locked(geomID);
+ return (RTCGeometry) geom.ptr;
+ RTC_CATCH_END2(scene);
+ return nullptr;
+ }
+
RTC_NAMESPACE_END
diff --git a/thirdparty/embree/kernels/common/rtcore.h b/thirdparty/embree/kernels/common/rtcore.h
index f8aad7c7cb..ac58a84d6f 100644
--- a/thirdparty/embree/kernels/common/rtcore.h
+++ b/thirdparty/embree/kernels/common/rtcore.h
@@ -26,56 +26,59 @@ namespace embree
/*! Macros used in the rtcore API implementation */
// -- GODOT start --
-// #define RTC_CATCH_BEGIN try {
#define RTC_CATCH_BEGIN
-
-// #define RTC_CATCH_END(device) \
-// } catch (std::bad_alloc&) { \
-// Device::process_error(device,RTC_ERROR_OUT_OF_MEMORY,"out of memory"); \
-// } catch (rtcore_error& e) { \
-// Device::process_error(device,e.error,e.what()); \
-// } catch (std::exception& e) { \
-// Device::process_error(device,RTC_ERROR_UNKNOWN,e.what()); \
-// } catch (...) { \
-// Device::process_error(device,RTC_ERROR_UNKNOWN,"unknown exception caught"); \
-// }
#define RTC_CATCH_END(device)
-
-// #define RTC_CATCH_END2(scene) \
-// } catch (std::bad_alloc&) { \
-// Device* device = scene ? scene->device : nullptr; \
-// Device::process_error(device,RTC_ERROR_OUT_OF_MEMORY,"out of memory"); \
-// } catch (rtcore_error& e) { \
-// Device* device = scene ? scene->device : nullptr; \
-// Device::process_error(device,e.error,e.what()); \
-// } catch (std::exception& e) { \
-// Device* device = scene ? scene->device : nullptr; \
-// Device::process_error(device,RTC_ERROR_UNKNOWN,e.what()); \
-// } catch (...) { \
-// Device* device = scene ? scene->device : nullptr; \
-// Device::process_error(device,RTC_ERROR_UNKNOWN,"unknown exception caught"); \
-// }
#define RTC_CATCH_END2(scene)
-
-// #define RTC_CATCH_END2_FALSE(scene) \
-// } catch (std::bad_alloc&) { \
-// Device* device = scene ? scene->device : nullptr; \
-// Device::process_error(device,RTC_ERROR_OUT_OF_MEMORY,"out of memory"); \
-// return false; \
-// } catch (rtcore_error& e) { \
-// Device* device = scene ? scene->device : nullptr; \
-// Device::process_error(device,e.error,e.what()); \
-// return false; \
-// } catch (std::exception& e) { \
-// Device* device = scene ? scene->device : nullptr; \
-// Device::process_error(device,RTC_ERROR_UNKNOWN,e.what()); \
-// return false; \
-// } catch (...) { \
-// Device* device = scene ? scene->device : nullptr; \
-// Device::process_error(device,RTC_ERROR_UNKNOWN,"unknown exception caught"); \
-// return false; \
-// }
#define RTC_CATCH_END2_FALSE(scene) return false;
+
+#if 0
+#define RTC_CATCH_BEGIN try {
+
+#define RTC_CATCH_END(device) \
+ } catch (std::bad_alloc&) { \
+ Device::process_error(device,RTC_ERROR_OUT_OF_MEMORY,"out of memory"); \
+ } catch (rtcore_error& e) { \
+ Device::process_error(device,e.error,e.what()); \
+ } catch (std::exception& e) { \
+ Device::process_error(device,RTC_ERROR_UNKNOWN,e.what()); \
+ } catch (...) { \
+ Device::process_error(device,RTC_ERROR_UNKNOWN,"unknown exception caught"); \
+ }
+
+#define RTC_CATCH_END2(scene) \
+ } catch (std::bad_alloc&) { \
+ Device* device = scene ? scene->device : nullptr; \
+ Device::process_error(device,RTC_ERROR_OUT_OF_MEMORY,"out of memory"); \
+ } catch (rtcore_error& e) { \
+ Device* device = scene ? scene->device : nullptr; \
+ Device::process_error(device,e.error,e.what()); \
+ } catch (std::exception& e) { \
+ Device* device = scene ? scene->device : nullptr; \
+ Device::process_error(device,RTC_ERROR_UNKNOWN,e.what()); \
+ } catch (...) { \
+ Device* device = scene ? scene->device : nullptr; \
+ Device::process_error(device,RTC_ERROR_UNKNOWN,"unknown exception caught"); \
+ }
+
+#define RTC_CATCH_END2_FALSE(scene) \
+ } catch (std::bad_alloc&) { \
+ Device* device = scene ? scene->device : nullptr; \
+ Device::process_error(device,RTC_ERROR_OUT_OF_MEMORY,"out of memory"); \
+ return false; \
+ } catch (rtcore_error& e) { \
+ Device* device = scene ? scene->device : nullptr; \
+ Device::process_error(device,e.error,e.what()); \
+ return false; \
+ } catch (std::exception& e) { \
+ Device* device = scene ? scene->device : nullptr; \
+ Device::process_error(device,RTC_ERROR_UNKNOWN,e.what()); \
+ return false; \
+ } catch (...) { \
+ Device* device = scene ? scene->device : nullptr; \
+ Device::process_error(device,RTC_ERROR_UNKNOWN,"unknown exception caught"); \
+ return false; \
+ }
+#endif
// -- GODOT end --
#define RTC_VERIFY_HANDLE(handle) \
@@ -103,39 +106,35 @@ namespace embree
#define RTC_TRACE(x)
#endif
-// -- GODOT begin --
-// /*! used to throw embree API errors */
-// struct rtcore_error : public std::exception
-// {
-// __forceinline rtcore_error(RTCError error, const std::string& str)
-// : error(error), str(str) {}
-//
-// ~rtcore_error() throw() {}
-//
-// const char* what () const throw () {
-// return str.c_str();
-// }
-//
-// RTCError error;
-// std::string str;
-// };
-// -- GODOT end --
+// -- GODOT start --
+#if 0
+ /*! used to throw embree API errors */
+ struct rtcore_error : public std::exception
+ {
+ __forceinline rtcore_error(RTCError error, const std::string& str)
+ : error(error), str(str) {}
+
+ ~rtcore_error() throw() {}
+
+ const char* what () const throw () {
+ return str.c_str();
+ }
+
+ RTCError error;
+ std::string str;
+ };
+#endif
#if defined(DEBUG) // only report file and line in debug mode
- // -- GODOT begin --
- // #define throw_RTCError(error,str) \
- // throw rtcore_error(error,std::string(__FILE__) + " (" + toString(__LINE__) + "): " + std::string(str));
#define throw_RTCError(error,str) \
printf("%s (%d): %s", __FILE__, __LINE__, std::string(str).c_str()), abort();
- // -- GODOT end --
+ // throw rtcore_error(error,std::string(__FILE__) + " (" + toString(__LINE__) + "): " + std::string(str));
#else
- // -- GODOT begin --
- // #define throw_RTCError(error,str) \
- // throw rtcore_error(error,str);
#define throw_RTCError(error,str) \
abort();
- // -- GODOT end --
+ // throw rtcore_error(error,str);
#endif
+// -- GODOT end --
#define RTC_BUILD_ARGUMENTS_HAS(settings,member) \
(settings.byteSize > (offsetof(RTCBuildArguments,member)+sizeof(settings.member)))
diff --git a/thirdparty/embree/kernels/common/rtcore_builder.cpp b/thirdparty/embree/kernels/common/rtcore_builder.cpp
index 1f1b6f6ddf..29e3bdca20 100644
--- a/thirdparty/embree/kernels/common/rtcore_builder.cpp
+++ b/thirdparty/embree/kernels/common/rtcore_builder.cpp
@@ -371,7 +371,7 @@ RTC_NAMESPACE_BEGIN
bvh->allocator.init_estimate(arguments->primitiveCount*sizeof(BBox3fa));
bvh->allocator.reset();
- /* switch between differnet builders based on quality level */
+ /* switch between different builders based on quality level */
if (arguments->buildQuality == RTC_BUILD_QUALITY_LOW)
return rtcBuildBVHMorton(arguments);
else if (arguments->buildQuality == RTC_BUILD_QUALITY_MEDIUM)
diff --git a/thirdparty/embree/kernels/common/scene.cpp b/thirdparty/embree/kernels/common/scene.cpp
index 408d7eae6f..65d31d0f81 100644
--- a/thirdparty/embree/kernels/common/scene.cpp
+++ b/thirdparty/embree/kernels/common/scene.cpp
@@ -629,9 +629,7 @@ namespace embree
if (geometry == null)
throw_RTCError(RTC_ERROR_INVALID_OPERATION,"invalid geometry");
- if (geometry->isEnabled()) {
- setModified ();
- }
+ setModified ();
accels_deleteGeometry(unsigned(geomID));
id_pool.deallocate((unsigned)geomID);
geometries[geomID] = null;
diff --git a/thirdparty/embree/kernels/common/scene_curves.h b/thirdparty/embree/kernels/common/scene_curves.h
index a5a39e42d4..a1ea45d3c7 100644
--- a/thirdparty/embree/kernels/common/scene_curves.h
+++ b/thirdparty/embree/kernels/common/scene_curves.h
@@ -452,6 +452,10 @@ namespace embree
const Vec3fa n1 = normal(index+1,itime);
if (!isvalid(n0) || !isvalid(n1))
return false;
+
+ const BBox3fa b = getOrientedCurveScaledRadius(i,itime).accurateBounds();
+ if (!isvalid(b))
+ return false;
}
}
@@ -612,6 +616,10 @@ namespace embree
const Vec3fa dn1 = dnormal(index+1,itime);
if (!isvalid(dn0) || !isvalid(dn1))
return false;
+
+ const BBox3fa b = getOrientedCurveScaledRadius(i,itime).accurateBounds();
+ if (!isvalid(b))
+ return false;
}
}
diff --git a/thirdparty/embree/kernels/common/state.cpp b/thirdparty/embree/kernels/common/state.cpp
index 01c862da0c..db6b803041 100644
--- a/thirdparty/embree/kernels/common/state.cpp
+++ b/thirdparty/embree/kernels/common/state.cpp
@@ -144,7 +144,20 @@ namespace embree
}
bool State::checkISASupport() {
+#if defined(__ARM_NEON)
+ /*
+ * NEON CPU type is a mixture of NEON and SSE2
+ */
+
+ bool hasSSE2 = (getCPUFeatures() & enabled_cpu_features) & CPU_FEATURE_SSE2;
+
+ /* this will be true when explicitly initialize Device with `isa=neon` config */
+ bool hasNEON = (getCPUFeatures() & enabled_cpu_features) & CPU_FEATURE_NEON;
+
+ return hasSSE2 || hasNEON;
+#else
return (getCPUFeatures() & enabled_cpu_features) == enabled_cpu_features;
+#endif
}
void State::verify()
@@ -157,8 +170,10 @@ namespace embree
* functions */
#if defined(DEBUG)
#if defined(EMBREE_TARGET_SSE2)
+#if !defined(__ARM_NEON)
assert(sse2::getISA() <= SSE2);
#endif
+#endif
#if defined(EMBREE_TARGET_SSE42)
assert(sse42::getISA() <= SSE42);
#endif
diff --git a/thirdparty/embree/kernels/config.h b/thirdparty/embree/kernels/config.h
index 2bf7e93587..84ac27d103 100644
--- a/thirdparty/embree/kernels/config.h
+++ b/thirdparty/embree/kernels/config.h
@@ -1,5 +1,4 @@
-
-// Copyright 2009-2020 Intel Corporation
+// Copyright 2009-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
/* #undef EMBREE_RAY_MASK */
@@ -20,6 +19,7 @@
/* #undef EMBREE_COMPACT_POLYS */
#define EMBREE_CURVE_SELF_INTERSECTION_AVOIDANCE_FACTOR 2.0
+#define EMBREE_DISC_POINT_SELF_INTERSECTION_AVOIDANCE
#if defined(EMBREE_GEOMETRY_TRIANGLE)
#define IF_ENABLED_TRIS(x) x
diff --git a/thirdparty/embree/kernels/geometry/curve_intersector_oriented.h b/thirdparty/embree/kernels/geometry/curve_intersector_oriented.h
index 3d8900c2aa..75532f5ae0 100644
--- a/thirdparty/embree/kernels/geometry/curve_intersector_oriented.h
+++ b/thirdparty/embree/kernels/geometry/curve_intersector_oriented.h
@@ -225,7 +225,7 @@ namespace embree
/* exit if convergence cannot get proven, but terminate if we are very small */
if (unlikely(!subset(K,x) && !very_small)) return false;
- /* solve using newton raphson iteration of convergence is guarenteed */
+ /* solve using newton raphson iteration of convergence is guaranteed */
solve_newton_raphson_loop(cu,cv,c1,dfdu,dfdv,rcp_J);
return true;
}
diff --git a/thirdparty/embree/kernels/geometry/curve_intersector_sweep.h b/thirdparty/embree/kernels/geometry/curve_intersector_sweep.h
index 2d4abd73ac..ed827d583f 100644
--- a/thirdparty/embree/kernels/geometry/curve_intersector_sweep.h
+++ b/thirdparty/embree/kernels/geometry/curve_intersector_sweep.h
@@ -60,7 +60,7 @@ namespace embree
const Vec3fa dir = ray.dir;
const float length_ray_dir = length(dir);
- /* error of curve evaluations is propertional to largest coordinate */
+ /* error of curve evaluations is proportional to largest coordinate */
const BBox3ff box = curve.bounds();
const float P_err = 16.0f*float(ulp)*reduce_max(max(abs(box.lower),abs(box.upper)));
diff --git a/thirdparty/embree/kernels/geometry/disc_intersector.h b/thirdparty/embree/kernels/geometry/disc_intersector.h
index 816c066899..ec6fa9c4f3 100644
--- a/thirdparty/embree/kernels/geometry/disc_intersector.h
+++ b/thirdparty/embree/kernels/geometry/disc_intersector.h
@@ -68,15 +68,15 @@ namespace embree
const Vec3vf<M> center = v0.xyz();
const vfloat<M> radius = v0.w;
+ /* compute ray distance projC0 to hit point with ray oriented plane */
const Vec3vf<M> c0 = center - ray_org;
const vfloat<M> projC0 = dot(c0, ray_dir) * rd2;
valid &= (vfloat<M>(ray.tnear()) <= projC0) & (projC0 <= vfloat<M>(ray.tfar));
- if (EMBREE_CURVE_SELF_INTERSECTION_AVOIDANCE_FACTOR != 0.0f)
- valid &= projC0 > float(EMBREE_CURVE_SELF_INTERSECTION_AVOIDANCE_FACTOR) * radius * pre.depth_scale; // ignore self intersections
if (unlikely(none(valid)))
return false;
-
+
+ /* check if hit point lies inside disc */
const Vec3vf<M> perp = c0 - projC0 * ray_dir;
const vfloat<M> l2 = dot(perp, perp);
const vfloat<M> r2 = radius * radius;
@@ -84,6 +84,15 @@ namespace embree
if (unlikely(none(valid)))
return false;
+ /* We reject hits where the ray origin lies inside the ray
+ * oriented disc to avoid self intersections. */
+#if defined(EMBREE_DISC_POINT_SELF_INTERSECTION_AVOIDANCE)
+ const vfloat<M> m2 = dot(c0, c0);
+ valid &= (m2 > r2);
+ if (unlikely(none(valid)))
+ return false;
+#endif
+
DiscIntersectorHitM<M> hit(zero, zero, projC0, -ray_dir);
return epilog(valid, hit);
}
@@ -152,15 +161,15 @@ namespace embree
const Vec3vf<M> center = v0.xyz();
const vfloat<M> radius = v0.w;
+ /* compute ray distance projC0 to hit point with ray oriented plane */
const Vec3vf<M> c0 = center - ray_org;
const vfloat<M> projC0 = dot(c0, ray_dir) * rd2;
valid &= (vfloat<M>(ray.tnear()[k]) <= projC0) & (projC0 <= vfloat<M>(ray.tfar[k]));
- if (EMBREE_CURVE_SELF_INTERSECTION_AVOIDANCE_FACTOR != 0.0f)
- valid &= projC0 > float(EMBREE_CURVE_SELF_INTERSECTION_AVOIDANCE_FACTOR) * radius * pre.depth_scale[k]; // ignore self intersections
if (unlikely(none(valid)))
return false;
+ /* check if hit point lies inside disc */
const Vec3vf<M> perp = c0 - projC0 * ray_dir;
const vfloat<M> l2 = dot(perp, perp);
const vfloat<M> r2 = radius * radius;
@@ -168,6 +177,15 @@ namespace embree
if (unlikely(none(valid)))
return false;
+ /* We reject hits where the ray origin lies inside the ray
+ * oriented disc to avoid self intersections. */
+#if defined(EMBREE_DISC_POINT_SELF_INTERSECTION_AVOIDANCE)
+ const vfloat<M> m2 = dot(c0, c0);
+ valid &= (m2 > r2);
+ if (unlikely(none(valid)))
+ return false;
+#endif
+
DiscIntersectorHitM<M> hit(zero, zero, projC0, -ray_dir);
return epilog(valid, hit);
}
diff --git a/thirdparty/embree/kernels/geometry/filter.h b/thirdparty/embree/kernels/geometry/filter.h
index 3b4d924ea7..d64320bf78 100644
--- a/thirdparty/embree/kernels/geometry/filter.h
+++ b/thirdparty/embree/kernels/geometry/filter.h
@@ -51,20 +51,11 @@ namespace embree
__forceinline void reportIntersection1(IntersectFunctionNArguments* args, const RTCFilterFunctionNArguments* filter_args)
{
#if defined(EMBREE_FILTER_FUNCTION)
- IntersectContext* MAYBE_UNUSED context = args->internal_context;
- const Geometry* const geometry = args->geometry;
- if (geometry->intersectionFilterN) {
- assert(context->scene->hasGeometryFilterFunction());
- geometry->intersectionFilterN(filter_args);
- }
+ if (args->geometry->intersectionFilterN)
+ args->geometry->intersectionFilterN(filter_args);
- //if (args->valid[0] == 0)
- // return;
-
- if (context->user->filter) {
- assert(context->scene->hasContextFilterFunction());
- context->user->filter(filter_args);
- }
+ if (args->context->filter)
+ args->context->filter(filter_args);
#endif
}
@@ -105,20 +96,11 @@ namespace embree
__forceinline void reportOcclusion1(OccludedFunctionNArguments* args, const RTCFilterFunctionNArguments* filter_args)
{
#if defined(EMBREE_FILTER_FUNCTION)
- IntersectContext* MAYBE_UNUSED context = args->internal_context;
- const Geometry* const geometry = args->geometry;
- if (geometry->occlusionFilterN) {
- assert(context->scene->hasGeometryFilterFunction());
- geometry->occlusionFilterN(filter_args);
- }
-
- //if (args->valid[0] == 0)
- // return false;
+ if (args->geometry->occlusionFilterN)
+ args->geometry->occlusionFilterN(filter_args);
- if (context->user->filter) {
- assert(context->scene->hasContextFilterFunction());
- context->user->filter(filter_args);
- }
+ if (args->context->filter)
+ args->context->filter(filter_args);
#endif
}
diff --git a/thirdparty/embree/kernels/geometry/object_intersector.h b/thirdparty/embree/kernels/geometry/object_intersector.h
index 11ceb2f7fe..e4ad01852f 100644
--- a/thirdparty/embree/kernels/geometry/object_intersector.h
+++ b/thirdparty/embree/kernels/geometry/object_intersector.h
@@ -32,7 +32,7 @@ namespace embree
return;
#endif
- accel->intersect(ray,prim.geomID(),prim.primID(),context,reportIntersection1);
+ accel->intersect(ray,prim.geomID(),prim.primID(),context);
}
static __forceinline bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& prim)
@@ -44,7 +44,7 @@ namespace embree
return false;
#endif
- accel->occluded(ray,prim.geomID(),prim.primID(),context,&reportOcclusion1);
+ accel->occluded(ray,prim.geomID(),prim.primID(),context);
return ray.tfar < 0.0f;
}
@@ -89,7 +89,7 @@ namespace embree
valid &= (ray.mask & accel->mask) != 0;
if (none(valid)) return;
#endif
- accel->intersect(valid,ray,prim.geomID(),prim.primID(),context,&reportIntersection1);
+ accel->intersect(valid,ray,prim.geomID(),prim.primID(),context);
}
static __forceinline vbool<K> occluded(const vbool<K>& valid_i, const Precalculations& pre, RayK<K>& ray, IntersectContext* context, const Primitive& prim)
@@ -102,7 +102,7 @@ namespace embree
valid &= (ray.mask & accel->mask) != 0;
if (none(valid)) return false;
#endif
- accel->occluded(valid,ray,prim.geomID(),prim.primID(),context,&reportOcclusion1);
+ accel->occluded(valid,ray,prim.geomID(),prim.primID(),context);
return ray.tfar < 0.0f;
}
diff --git a/thirdparty/embree/kernels/geometry/quadv.h b/thirdparty/embree/kernels/geometry/quadv.h
index 2137356ff2..514e519b0c 100644
--- a/thirdparty/embree/kernels/geometry/quadv.h
+++ b/thirdparty/embree/kernels/geometry/quadv.h
@@ -152,7 +152,7 @@ namespace embree
Vec3vf<M> v0; // 1st vertex of the quads
Vec3vf<M> v1; // 2nd vertex of the quads
Vec3vf<M> v2; // 3rd vertex of the quads
- Vec3vf<M> v3; // 4rd vertex of the quads
+ Vec3vf<M> v3; // 4th vertex of the quads
private:
vuint<M> geomIDs; // geometry ID
vuint<M> primIDs; // primitive ID
diff --git a/thirdparty/embree/kernels/geometry/roundline_intersector.h b/thirdparty/embree/kernels/geometry/roundline_intersector.h
index 0e9393442b..764ff93fec 100644
--- a/thirdparty/embree/kernels/geometry/roundline_intersector.h
+++ b/thirdparty/embree/kernels/geometry/roundline_intersector.h
@@ -19,7 +19,7 @@
For multiple connected round linear curve segments this construction
yield a proper shape when viewed from the outside. Using the
- following CSG we can also handle the interiour in most common cases:
+ following CSG we can also handle the interior in most common cases:
round_linear_curve(pl,rl,p0,r0,p1,r1,pr,rr) =
cone_sphere(p0,r0,p1,r1) - cone(pl,rl,p0,r0) - cone(p1,r1,pr,rr)
@@ -431,7 +431,7 @@ namespace embree
Ng' = (h-u*dP) - (w0+u*dw)*dw/dP^2*dP
Inserting the definition of w0 and dw and refactoring
- yield a furhter scaled Ng'':
+ yield a further scaled Ng'':
Ng'' = (dP^2 - dr^2) (h-q) - (r0+u*dr)*dr*dP
diff --git a/thirdparty/embree/kernels/geometry/subgrid_intersector.h b/thirdparty/embree/kernels/geometry/subgrid_intersector.h
index ad5fee2e4e..e241073812 100644
--- a/thirdparty/embree/kernels/geometry/subgrid_intersector.h
+++ b/thirdparty/embree/kernels/geometry/subgrid_intersector.h
@@ -264,8 +264,8 @@ namespace embree
const Vec3vf<K> p2 = vtx[i*4+2];
const Vec3vf<K> p3 = vtx[i*4+3];
STAT3(shadow.trav_prims,1,popcnt(valid0),K);
- if (pre.intersectK(valid0,ray,p0,p1,p2,p3,g,subgrid,i,OccludedKEpilogM<4,K,filter>(valid0,ray,context,subgrid.geomID(),subgrid.primID(),i)))
- break;
+ pre.intersectK(valid0,ray,p0,p1,p2,p3,g,subgrid,i,OccludedKEpilogM<4,K,filter>(valid0,ray,context,subgrid.geomID(),subgrid.primID(),i));
+ if (none(valid0)) break;
}
return !valid0;
}
@@ -408,10 +408,8 @@ namespace embree
const Vec3vf<K> p2 = vtx[i*4+2];
const Vec3vf<K> p3 = vtx[i*4+3];
STAT3(shadow.trav_prims,1,popcnt(valid0),K);
- //if (pre.intersectK(valid0,ray,p0,p1,p2,p3,g,subgrid,i,OccludedKEpilogM<4,K,filter>(valid0,ray,context,subgrid.geomID(),subgrid.primID(),i)))
- if (pre.occludedK(valid0,ray,p0,p1,p2,p3,g,subgrid,i,OccludedKEpilogM<4,K,filter>(valid0,ray,context,subgrid.geomID(),subgrid.primID(),i)))
-
- break;
+ pre.occludedK(valid0,ray,p0,p1,p2,p3,g,subgrid,i,OccludedKEpilogM<4,K,filter>(valid0,ray,context,subgrid.geomID(),subgrid.primID(),i));
+ if (none(valid0)) break;
}
return !valid0;
}
diff --git a/thirdparty/embree/kernels/hash.h b/thirdparty/embree/kernels/hash.h
index 470e15f03e..39d50e2354 100644
--- a/thirdparty/embree/kernels/hash.h
+++ b/thirdparty/embree/kernels/hash.h
@@ -1,5 +1,4 @@
-
-// Copyright 2009-2020 Intel Corporation
+// Copyright 2009-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
-#define RTC_HASH "12b99393438a4cc9e478e33459eed78bec6233fd"
+#define RTC_HASH "698442324ccddd11725fb8875275dc1384f7fb40"
diff --git a/thirdparty/embree/kernels/subdiv/bezier_patch.h b/thirdparty/embree/kernels/subdiv/bezier_patch.h
index 2ff03902a7..0a2aef321f 100644
--- a/thirdparty/embree/kernels/subdiv/bezier_patch.h
+++ b/thirdparty/embree/kernels/subdiv/bezier_patch.h
@@ -94,7 +94,7 @@ namespace embree
matrix[0][1] = computeRightEdgeBezierControlPoint(source.v,1,1);
matrix[0][2] = computeLeftEdgeBezierControlPoint(source.v,1,2);
- /* compute buttom edge control points */
+ /* compute bottom edge control points */
matrix[3][1] = computeRightEdgeBezierControlPoint(source.v,2,1);
matrix[3][2] = computeLeftEdgeBezierControlPoint(source.v,2,2);
diff --git a/thirdparty/embree/kernels/subdiv/catmullclark_ring.h b/thirdparty/embree/kernels/subdiv/catmullclark_ring.h
index e5ad5dadfe..eab91d9ee6 100644
--- a/thirdparty/embree/kernels/subdiv/catmullclark_ring.h
+++ b/thirdparty/embree/kernels/subdiv/catmullclark_ring.h
@@ -388,7 +388,7 @@ namespace embree
return (Vertex_t)(n*n*vtx+4.0f*E+F) / ((n+5.0f)*n);
}
- /* gets limit tangent in the direction of egde vtx -> ring[0] */
+ /* gets limit tangent in the direction of edge vtx -> ring[0] */
__forceinline Vertex getLimitTangent() const
{
if (unlikely(std::isinf(vertex_crease_weight)))
@@ -429,7 +429,7 @@ namespace embree
return sigma * (alpha + beta);
}
- /* gets limit tangent in the direction of egde vtx -> ring[edge_valence-2] */
+ /* gets limit tangent in the direction of edge vtx -> ring[edge_valence-2] */
__forceinline Vertex getSecondLimitTangent() const
{
if (unlikely(std::isinf(vertex_crease_weight)))
@@ -763,7 +763,7 @@ namespace embree
}
- /* gets limit tangent in the direction of egde vtx -> ring[0] */
+ /* gets limit tangent in the direction of edge vtx -> ring[0] */
__forceinline Vertex getLimitTangent() const
{
CatmullClark1Ring cc_vtx;
@@ -779,7 +779,7 @@ namespace embree
return 2.0f * cc_vtx.getLimitTangent();
}
- /* gets limit tangent in the direction of egde vtx -> ring[edge_valence-2] */
+ /* gets limit tangent in the direction of edge vtx -> ring[edge_valence-2] */
__forceinline Vertex getSecondLimitTangent() const
{
CatmullClark1Ring cc_vtx;
diff --git a/thirdparty/embree/kernels/subdiv/catmullrom_curve.h b/thirdparty/embree/kernels/subdiv/catmullrom_curve.h
index 74fc4c1230..9532287d98 100644
--- a/thirdparty/embree/kernels/subdiv/catmullrom_curve.h
+++ b/thirdparty/embree/kernels/subdiv/catmullrom_curve.h
@@ -8,7 +8,7 @@
/*
- Implements Catmul Rom curves with control points p0, p1, p2, p3. At
+ Implements Catmull-Rom curves with control points p0, p1, p2, p3. At
t=0 the curve goes through p1, with tangent (p2-p0)/3, and for t=1
the curve goes through p2 with tangent (p3-p2)/2.
@@ -91,11 +91,11 @@ namespace embree
: v0(v0), v1(v1), v2(v2), v3(v3) {}
__forceinline Vertex begin() const {
- return madd(1.0f/6.0f,v0,madd(2.0f/3.0f,v1,1.0f/6.0f*v2));
+ return v1;
}
__forceinline Vertex end() const {
- return madd(1.0f/6.0f,v1,madd(2.0f/3.0f,v2,1.0f/6.0f*v3));
+ return v2;
}
__forceinline Vertex center() const {
diff --git a/thirdparty/embree/kernels/subdiv/linear_bezier_patch.h b/thirdparty/embree/kernels/subdiv/linear_bezier_patch.h
index f8e8a25f35..dcdb101d7c 100644
--- a/thirdparty/embree/kernels/subdiv/linear_bezier_patch.h
+++ b/thirdparty/embree/kernels/subdiv/linear_bezier_patch.h
@@ -81,29 +81,29 @@ namespace embree
{
SourceCurve<Vec3ff> vcurve = center;
SourceCurve<Vec3fa> ncurve = normal;
-
+
/* here we construct a patch which follows the curve l(t) =
* p(t) +/- r(t)*normalize(cross(n(t),dp(t))) */
const Vec3ff p0 = vcurve.eval(0.0f);
const Vec3ff dp0 = vcurve.eval_du(0.0f);
- const Vec3ff ddp0 = vcurve.eval_dudu(0.0f);
+ //const Vec3ff ddp0 = vcurve.eval_dudu(0.0f); // ddp0 is assumed to be 0
const Vec3fa n0 = ncurve.eval(0.0f);
const Vec3fa dn0 = ncurve.eval_du(0.0f);
const Vec3ff p1 = vcurve.eval(1.0f);
const Vec3ff dp1 = vcurve.eval_du(1.0f);
- const Vec3ff ddp1 = vcurve.eval_dudu(1.0f);
+ //const Vec3ff ddp1 = vcurve.eval_dudu(1.0f); // ddp1 is assumed to be 0
const Vec3fa n1 = ncurve.eval(1.0f);
const Vec3fa dn1 = ncurve.eval_du(1.0f);
const Vec3fa bt0 = cross(n0,dp0);
- const Vec3fa dbt0 = cross(dn0,dp0) + cross(n0,ddp0);
+ const Vec3fa dbt0 = cross(dn0,dp0);// + cross(n0,ddp0);
const Vec3fa bt1 = cross(n1,dp1);
- const Vec3fa dbt1 = cross(dn1,dp1) + cross(n1,ddp1);
+ const Vec3fa dbt1 = cross(dn1,dp1);// + cross(n1,ddp1);
const Vec3fa k0 = normalize(bt0);
const Vec3fa dk0 = dnormalize(bt0,dbt0);
diff --git a/thirdparty/embree/patches/emscripten-nthreads.patch b/thirdparty/embree/patches/emscripten-nthreads.patch
new file mode 100644
index 0000000000..e42f203475
--- /dev/null
+++ b/thirdparty/embree/patches/emscripten-nthreads.patch
@@ -0,0 +1,42 @@
+diff --git a/thirdparty/embree/common/sys/sysinfo.cpp b/thirdparty/embree/common/sys/sysinfo.cpp
+index c98f61fa53..7f7a009a1e 100644
+--- a/thirdparty/embree/common/sys/sysinfo.cpp
++++ b/thirdparty/embree/common/sys/sysinfo.cpp
+@@ -640,6 +640,12 @@ namespace embree
+
+ #if defined(__EMSCRIPTEN__)
+ #include <emscripten.h>
++
++// -- GODOT start --
++extern "C" {
++extern int godot_js_os_hw_concurrency_get();
++}
++// -- GODOT end --
+ #endif
+
+ namespace embree
+@@ -653,21 +659,9 @@ namespace embree
+ nThreads = sysconf(_SC_NPROCESSORS_ONLN); // does not work in Linux LXC container
+ assert(nThreads);
+ #elif defined(__EMSCRIPTEN__)
+- // WebAssembly supports pthreads, but not pthread_getaffinity_np. Get the number of logical
+- // threads from the browser or Node.js using JavaScript.
+- nThreads = MAIN_THREAD_EM_ASM_INT({
+- const isBrowser = typeof window !== 'undefined';
+- const isNode = typeof process !== 'undefined' && process.versions != null &&
+- process.versions.node != null;
+- if (isBrowser) {
+- // Return 1 if the browser does not expose hardwareConcurrency.
+- return window.navigator.hardwareConcurrency || 1;
+- } else if (isNode) {
+- return require('os').cpus().length;
+- } else {
+- return 1;
+- }
+- });
++ // -- GODOT start --
++ nThreads = godot_js_os_hw_concurrency_get();
++ // -- GODOT end --
+ #else
+ cpu_set_t set;
+ if (pthread_getaffinity_np(pthread_self(), sizeof(set), &set) == 0)
diff --git a/thirdparty/embree/patches/godot-changes-android.patch b/thirdparty/embree/patches/godot-changes-android.patch
deleted file mode 100644
index a27f924bde..0000000000
--- a/thirdparty/embree/patches/godot-changes-android.patch
+++ /dev/null
@@ -1,103 +0,0 @@
-diff --git a/thirdparty/embree/common/sys/sysinfo.cpp b/thirdparty/embree/common/sys/sysinfo.cpp
-index ba97dc227b..1679599608 100644
---- a/thirdparty/embree/common/sys/sysinfo.cpp
-+++ b/thirdparty/embree/common/sys/sysinfo.cpp
-@@ -618,7 +618,10 @@ namespace embree
- static int nThreads = -1;
- if (nThreads != -1) return nThreads;
-
--#if defined(__MACOSX__)
-+// -- GODOT start --
-+// #if defined(__MACOSX__)
-+#if defined(__MACOSX__) || defined(__ANDROID__)
-+// -- GODOT end --
- nThreads = sysconf(_SC_NPROCESSORS_ONLN); // does not work in Linux LXC container
- assert(nThreads);
- #else
-diff --git a/thirdparty/embree/common/sys/thread.cpp b/thirdparty/embree/common/sys/thread.cpp
-index a7827e18f7..f4014be89b 100644
---- a/thirdparty/embree/common/sys/thread.cpp
-+++ b/thirdparty/embree/common/sys/thread.cpp
-@@ -158,7 +158,9 @@ namespace embree
- /// Linux Platform
- ////////////////////////////////////////////////////////////////////////////////
-
--#if defined(__LINUX__)
-+// -- GODOT start --
-+#if defined(__LINUX__) && !defined(__ANDROID__)
-+// -- GODOT end --
-
- #include <fstream>
- #include <sstream>
-@@ -247,6 +249,28 @@ namespace embree
- }
- #endif
-
-+// -- GODOT start --
-+////////////////////////////////////////////////////////////////////////////////
-+/// Android Platform
-+////////////////////////////////////////////////////////////////////////////////
-+
-+#if defined(__ANDROID__)
-+
-+namespace embree
-+{
-+ /*! set affinity of the calling thread */
-+ void setAffinity(ssize_t affinity)
-+ {
-+ cpu_set_t cset;
-+ CPU_ZERO(&cset);
-+ CPU_SET(affinity, &cset);
-+
-+ sched_setaffinity(0, sizeof(cset), &cset);
-+ }
-+}
-+#endif
-+// -- GODOT end --
-+
- ////////////////////////////////////////////////////////////////////////////////
- /// FreeBSD Platform
- ////////////////////////////////////////////////////////////////////////////////
-@@ -355,7 +379,9 @@ namespace embree
- pthread_attr_destroy(&attr);
-
- /* set affinity */
--#if defined(__LINUX__)
-+// -- GODOT start --
-+#if defined(__LINUX__) && !defined(__ANDROID__)
-+// -- GODOT end --
- if (threadID >= 0) {
- cpu_set_t cset;
- CPU_ZERO(&cset);
-@@ -370,7 +396,16 @@ namespace embree
- CPU_SET(threadID, &cset);
- pthread_setaffinity_np(*tid, sizeof(cset), &cset);
- }
-+// -- GODOT start --
-+#elif defined(__ANDROID__)
-+ if (threadID >= 0) {
-+ cpu_set_t cset;
-+ CPU_ZERO(&cset);
-+ CPU_SET(threadID, &cset);
-+ sched_setaffinity(pthread_gettid_np(*tid), sizeof(cset), &cset);
-+ }
- #endif
-+// -- GODOT end --
-
- return thread_t(tid);
- }
-@@ -389,8 +424,14 @@ namespace embree
-
- /*! destroy a hardware thread by its handle */
- void destroyThread(thread_t tid) {
-+// -- GODOT start --
-+#if defined(__ANDROID__)
-+ FATAL("Can't destroy threads on Android.");
-+#else
- pthread_cancel(*(pthread_t*)tid);
- delete (pthread_t*)tid;
-+#endif
-+// -- GODOT end --
- }
-
- /*! creates thread local storage */
diff --git a/thirdparty/embree/patches/godot-changes-misc.patch b/thirdparty/embree/patches/godot-changes-misc.patch
deleted file mode 100644
index 8bf0d9fa97..0000000000
--- a/thirdparty/embree/patches/godot-changes-misc.patch
+++ /dev/null
@@ -1,105 +0,0 @@
-diff --git a/thirdparty/embree/common/sys/intrinsics.h b/thirdparty/embree/common/sys/intrinsics.h
-index 79729c87ab..ed8dd7d40a 100644
---- a/thirdparty/embree/common/sys/intrinsics.h
-+++ b/thirdparty/embree/common/sys/intrinsics.h
-@@ -34,8 +34,14 @@
- #endif
-
- #if defined(__WIN32__)
--# define NOMINMAX
--# include <windows.h>
-+// -- GODOT start --
-+#if !defined(NOMINMAX)
-+// -- GODOT end --
-+#define NOMINMAX
-+// -- GODOT start --
-+#endif
-+#include "windows.h"
-+// -- GODOT end --
- #endif
-
- /* normally defined in pmmintrin.h, but we always need this */
-diff --git a/thirdparty/embree/common/sys/platform.h b/thirdparty/embree/common/sys/platform.h
-index 3fc5e99b8d..697e07bb86 100644
---- a/thirdparty/embree/common/sys/platform.h
-+++ b/thirdparty/embree/common/sys/platform.h
-@@ -99,7 +99,9 @@
- #define dll_import
- #endif
-
--#ifdef __WIN32__
-+// -- GODOT start --
-+#if defined(__WIN32__) && !defined(__MINGW32__)
-+// -- GODOT end --
- #if !defined(__noinline)
- #define __noinline __declspec(noinline)
- #endif
-@@ -149,6 +151,9 @@
- #define DELETED = delete
- #endif
-
-+// -- GODOT start --
-+#if !defined(likely)
-+// -- GODOT end --
- #if defined(_MSC_VER) && !defined(__INTEL_COMPILER)
- #define likely(expr) (expr)
- #define unlikely(expr) (expr)
-@@ -156,6 +161,9 @@
- #define likely(expr) __builtin_expect((bool)(expr),true )
- #define unlikely(expr) __builtin_expect((bool)(expr),false)
- #endif
-+// -- GODOT start --
-+#endif
-+// -- GODOT end --
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Error handling and debugging
-diff --git a/thirdparty/embree/common/sys/sysinfo.cpp b/thirdparty/embree/common/sys/sysinfo.cpp
-index ba97dc227b..f1a59e511e 100644
---- a/thirdparty/embree/common/sys/sysinfo.cpp
-+++ b/thirdparty/embree/common/sys/sysinfo.cpp
-@@ -248,7 +248,9 @@ namespace embree
- #if defined(__X86_ASM__)
- __noinline int64_t get_xcr0()
- {
--#if defined (__WIN32__)
-+// -- GODOT start --
-+#if defined (__WIN32__) && !defined (__MINGW32__)
-+// -- GODOT end --
- int64_t xcr0 = 0; // int64_t is workaround for compiler bug under VS2013, Win32
- xcr0 = _xgetbv(0);
- return xcr0;
-diff --git a/thirdparty/embree/include/embree3/rtcore_common.h b/thirdparty/embree/include/embree3/rtcore_common.h
-index 9c14b28745..4857e1e05e 100644
---- a/thirdparty/embree/include/embree3/rtcore_common.h
-+++ b/thirdparty/embree/include/embree3/rtcore_common.h
-@@ -19,7 +19,9 @@ typedef int ssize_t;
- #endif
- #endif
-
--#ifdef _WIN32
-+// -- GODOT start --
-+#if defined(_WIN32) && defined(_MSC_VER)
-+// -- GODOT end --
- # define RTC_ALIGN(...) __declspec(align(__VA_ARGS__))
- #else
- # define RTC_ALIGN(...) __attribute__((aligned(__VA_ARGS__)))
-diff --git a/thirdparty/embree/common/tasking/taskschedulertbb.h b/thirdparty/embree/common/tasking/taskschedulertbb.h
-index 3fd15816e9..35bd49849f 100644
---- a/thirdparty/embree/common/tasking/taskschedulertbb.h
-+++ b/thirdparty/embree/common/tasking/taskschedulertbb.h
-@@ -12,7 +12,13 @@
- #include "../sys/ref.h"
-
- #if defined(__WIN32__)
-+// -- GODOT start --
-+#if !defined(NOMINMAX)
-+// -- GODOT end --
- # define NOMINMAX
-+// -- GODOT start --
-+#endif
-+// -- GODOT end --
- #endif
-
- // We need to define these to avoid implicit linkage against
- \ No newline at end of file
diff --git a/thirdparty/embree/patches/godot-changes-noexcept.patch b/thirdparty/embree/patches/godot-changes-noexcept.patch
index 598a7f2ddc..84169c36e4 100644
--- a/thirdparty/embree/patches/godot-changes-noexcept.patch
+++ b/thirdparty/embree/patches/godot-changes-noexcept.patch
@@ -1,5 +1,5 @@
diff --git a/thirdparty/embree/common/algorithms/parallel_for.h b/thirdparty/embree/common/algorithms/parallel_for.h
-index f052d8b468..645681ac63 100644
+index f2969a88f1..6d411e4852 100644
--- a/thirdparty/embree/common/algorithms/parallel_for.h
+++ b/thirdparty/embree/common/algorithms/parallel_for.h
@@ -21,7 +21,10 @@ namespace embree
@@ -12,9 +12,9 @@ index f052d8b468..645681ac63 100644
+ abort();
+ // -- GODOT end --
}
-
#elif defined(TASKING_TBB)
-@@ -31,13 +34,19 @@ namespace embree
+ #if TBB_INTERFACE_VERSION >= 12002
+@@ -30,13 +33,19 @@ namespace embree
func(i);
},context);
if (context.is_group_execution_cancelled())
@@ -36,7 +36,7 @@ index f052d8b468..645681ac63 100644
#endif
#elif defined(TASKING_PPL)
-@@ -57,7 +66,10 @@ namespace embree
+@@ -56,7 +65,10 @@ namespace embree
#if defined(TASKING_INTERNAL)
TaskScheduler::spawn(first,last,minStepSize,func);
if (!TaskScheduler::wait())
@@ -48,7 +48,7 @@ index f052d8b468..645681ac63 100644
#elif defined(TASKING_TBB)
#if TBB_INTERFACE_VERSION >= 12002
-@@ -66,13 +78,19 @@ namespace embree
+@@ -65,13 +77,19 @@ namespace embree
func(range<Index>(r.begin(),r.end()));
},context);
if (context.is_group_execution_cancelled())
@@ -70,7 +70,7 @@ index f052d8b468..645681ac63 100644
#endif
#elif defined(TASKING_PPL)
-@@ -104,13 +122,19 @@ namespace embree
+@@ -103,13 +121,19 @@ namespace embree
func(i);
},tbb::simple_partitioner(),context);
if (context.is_group_execution_cancelled())
@@ -92,7 +92,7 @@ index f052d8b468..645681ac63 100644
#endif
}
-@@ -125,13 +149,19 @@ namespace embree
+@@ -124,13 +148,19 @@ namespace embree
func(i);
},ap,context);
if (context.is_group_execution_cancelled())
@@ -115,7 +115,7 @@ index f052d8b468..645681ac63 100644
}
diff --git a/thirdparty/embree/common/algorithms/parallel_reduce.h b/thirdparty/embree/common/algorithms/parallel_reduce.h
-index f42ae2ec50..8271372ea4 100644
+index 1a94aad8c4..cd0078f2e6 100644
--- a/thirdparty/embree/common/algorithms/parallel_reduce.h
+++ b/thirdparty/embree/common/algorithms/parallel_reduce.h
@@ -58,15 +58,19 @@ namespace embree
@@ -247,10 +247,10 @@ index 1bc30fe9a5..abdd269069 100644
/* hint for transparent huge pages (THP) */
diff --git a/thirdparty/embree/common/sys/platform.h b/thirdparty/embree/common/sys/platform.h
-index 8a6d9fa0a9..697e07bb86 100644
+index be3ec36436..728bf6ed7d 100644
--- a/thirdparty/embree/common/sys/platform.h
+++ b/thirdparty/embree/common/sys/platform.h
-@@ -179,11 +179,19 @@
+@@ -178,11 +178,19 @@
#define PRINT4(x,y,z,w) embree_cout << STRING(x) << " = " << (x) << ", " << STRING(y) << " = " << (y) << ", " << STRING(z) << " = " << (z) << ", " << STRING(w) << " = " << (w) << embree_endl
#if defined(DEBUG) // only report file and line in debug mode
@@ -351,7 +351,7 @@ index dca835a716..ad438588a3 100644
bool TaskScheduler::steal_from_other_threads(Thread& thread)
diff --git a/thirdparty/embree/common/tasking/taskschedulerinternal.h b/thirdparty/embree/common/tasking/taskschedulerinternal.h
-index c766a0bb6a..8fa6bb12fa 100644
+index 61a0e57c5b..6cc2495195 100644
--- a/thirdparty/embree/common/tasking/taskschedulerinternal.h
+++ b/thirdparty/embree/common/tasking/taskschedulerinternal.h
@@ -123,7 +123,10 @@ namespace embree
@@ -391,7 +391,7 @@ index c766a0bb6a..8fa6bb12fa 100644
/*! steals a task from a different thread */
bool steal_from_other_threads(Thread& thread);
diff --git a/thirdparty/embree/kernels/bvh/bvh_statistics.cpp b/thirdparty/embree/kernels/bvh/bvh_statistics.cpp
-index d8da78eed7..d857ff7d95 100644
+index 40f9043736..57f75bfd7e 100644
--- a/thirdparty/embree/kernels/bvh/bvh_statistics.cpp
+++ b/thirdparty/embree/kernels/bvh/bvh_statistics.cpp
@@ -150,7 +150,10 @@ namespace embree
@@ -407,10 +407,10 @@ index d8da78eed7..d857ff7d95 100644
return s;
}
diff --git a/thirdparty/embree/kernels/common/rtcore.cpp b/thirdparty/embree/kernels/common/rtcore.cpp
-index 74e9fb335c..94b3819e42 100644
+index 95a94319ec..a6ea55bfc4 100644
--- a/thirdparty/embree/kernels/common/rtcore.cpp
+++ b/thirdparty/embree/kernels/common/rtcore.cpp
-@@ -197,7 +197,10 @@ RTC_NAMESPACE_BEGIN;
+@@ -198,7 +198,10 @@ RTC_NAMESPACE_BEGIN;
if (quality != RTC_BUILD_QUALITY_LOW &&
quality != RTC_BUILD_QUALITY_MEDIUM &&
quality != RTC_BUILD_QUALITY_HIGH)
@@ -422,7 +422,7 @@ index 74e9fb335c..94b3819e42 100644
scene->setBuildQuality(quality);
RTC_CATCH_END2(scene);
}
-@@ -1350,7 +1353,10 @@ RTC_NAMESPACE_BEGIN;
+@@ -1351,7 +1354,10 @@ RTC_NAMESPACE_BEGIN;
quality != RTC_BUILD_QUALITY_MEDIUM &&
quality != RTC_BUILD_QUALITY_HIGH &&
quality != RTC_BUILD_QUALITY_REFIT)
@@ -435,172 +435,67 @@ index 74e9fb335c..94b3819e42 100644
RTC_CATCH_END2(geometry);
}
diff --git a/thirdparty/embree/kernels/common/rtcore.h b/thirdparty/embree/kernels/common/rtcore.h
-index 4e4b24e9c2..373e49a689 100644
+index 4e4b24e9c2..ac58a84d6f 100644
--- a/thirdparty/embree/kernels/common/rtcore.h
+++ b/thirdparty/embree/kernels/common/rtcore.h
-@@ -25,52 +25,58 @@ namespace embree
+@@ -25,6 +25,13 @@ namespace embree
#endif
/*! Macros used in the rtcore API implementation */
--#define RTC_CATCH_BEGIN try {
+// -- GODOT start --
-+// #define RTC_CATCH_BEGIN try {
+#define RTC_CATCH_BEGIN
-
--#define RTC_CATCH_END(device) \
-- } catch (std::bad_alloc&) { \
-- Device::process_error(device,RTC_ERROR_OUT_OF_MEMORY,"out of memory"); \
-- } catch (rtcore_error& e) { \
-- Device::process_error(device,e.error,e.what()); \
-- } catch (std::exception& e) { \
-- Device::process_error(device,RTC_ERROR_UNKNOWN,e.what()); \
-- } catch (...) { \
-- Device::process_error(device,RTC_ERROR_UNKNOWN,"unknown exception caught"); \
-- }
-+// #define RTC_CATCH_END(device) \
-+// } catch (std::bad_alloc&) { \
-+// Device::process_error(device,RTC_ERROR_OUT_OF_MEMORY,"out of memory"); \
-+// } catch (rtcore_error& e) { \
-+// Device::process_error(device,e.error,e.what()); \
-+// } catch (std::exception& e) { \
-+// Device::process_error(device,RTC_ERROR_UNKNOWN,e.what()); \
-+// } catch (...) { \
-+// Device::process_error(device,RTC_ERROR_UNKNOWN,"unknown exception caught"); \
-+// }
+#define RTC_CATCH_END(device)
-
--#define RTC_CATCH_END2(scene) \
-- } catch (std::bad_alloc&) { \
-- Device* device = scene ? scene->device : nullptr; \
-- Device::process_error(device,RTC_ERROR_OUT_OF_MEMORY,"out of memory"); \
-- } catch (rtcore_error& e) { \
-- Device* device = scene ? scene->device : nullptr; \
-- Device::process_error(device,e.error,e.what()); \
-- } catch (std::exception& e) { \
-- Device* device = scene ? scene->device : nullptr; \
-- Device::process_error(device,RTC_ERROR_UNKNOWN,e.what()); \
-- } catch (...) { \
-- Device* device = scene ? scene->device : nullptr; \
-- Device::process_error(device,RTC_ERROR_UNKNOWN,"unknown exception caught"); \
-- }
-+// #define RTC_CATCH_END2(scene) \
-+// } catch (std::bad_alloc&) { \
-+// Device* device = scene ? scene->device : nullptr; \
-+// Device::process_error(device,RTC_ERROR_OUT_OF_MEMORY,"out of memory"); \
-+// } catch (rtcore_error& e) { \
-+// Device* device = scene ? scene->device : nullptr; \
-+// Device::process_error(device,e.error,e.what()); \
-+// } catch (std::exception& e) { \
-+// Device* device = scene ? scene->device : nullptr; \
-+// Device::process_error(device,RTC_ERROR_UNKNOWN,e.what()); \
-+// } catch (...) { \
-+// Device* device = scene ? scene->device : nullptr; \
-+// Device::process_error(device,RTC_ERROR_UNKNOWN,"unknown exception caught"); \
-+// }
+#define RTC_CATCH_END2(scene)
-
--#define RTC_CATCH_END2_FALSE(scene) \
-- } catch (std::bad_alloc&) { \
-- Device* device = scene ? scene->device : nullptr; \
-- Device::process_error(device,RTC_ERROR_OUT_OF_MEMORY,"out of memory"); \
-- return false; \
-- } catch (rtcore_error& e) { \
-- Device* device = scene ? scene->device : nullptr; \
-- Device::process_error(device,e.error,e.what()); \
-- return false; \
-- } catch (std::exception& e) { \
-- Device* device = scene ? scene->device : nullptr; \
-- Device::process_error(device,RTC_ERROR_UNKNOWN,e.what()); \
-- return false; \
-- } catch (...) { \
-- Device* device = scene ? scene->device : nullptr; \
-- Device::process_error(device,RTC_ERROR_UNKNOWN,"unknown exception caught"); \
-- return false; \
-- }
-+// #define RTC_CATCH_END2_FALSE(scene) \
-+// } catch (std::bad_alloc&) { \
-+// Device* device = scene ? scene->device : nullptr; \
-+// Device::process_error(device,RTC_ERROR_OUT_OF_MEMORY,"out of memory"); \
-+// return false; \
-+// } catch (rtcore_error& e) { \
-+// Device* device = scene ? scene->device : nullptr; \
-+// Device::process_error(device,e.error,e.what()); \
-+// return false; \
-+// } catch (std::exception& e) { \
-+// Device* device = scene ? scene->device : nullptr; \
-+// Device::process_error(device,RTC_ERROR_UNKNOWN,e.what()); \
-+// return false; \
-+// } catch (...) { \
-+// Device* device = scene ? scene->device : nullptr; \
-+// Device::process_error(device,RTC_ERROR_UNKNOWN,"unknown exception caught"); \
-+// return false; \
-+// }
+#define RTC_CATCH_END2_FALSE(scene) return false;
++
++#if 0
+ #define RTC_CATCH_BEGIN try {
+
+ #define RTC_CATCH_END(device) \
+@@ -71,6 +78,8 @@ namespace embree
+ Device::process_error(device,RTC_ERROR_UNKNOWN,"unknown exception caught"); \
+ return false; \
+ }
++#endif
+// -- GODOT end --
#define RTC_VERIFY_HANDLE(handle) \
if (handle == nullptr) { \
-@@ -97,28 +103,38 @@ namespace embree
+@@ -97,6 +106,8 @@ namespace embree
#define RTC_TRACE(x)
#endif
-- /*! used to throw embree API errors */
-- struct rtcore_error : public std::exception
-- {
-- __forceinline rtcore_error(RTCError error, const std::string& str)
-- : error(error), str(str) {}
--
-- ~rtcore_error() throw() {}
--
-- const char* what () const throw () {
-- return str.c_str();
-- }
--
-- RTCError error;
-- std::string str;
-- };
-+// -- GODOT begin --
-+// /*! used to throw embree API errors */
-+// struct rtcore_error : public std::exception
-+// {
-+// __forceinline rtcore_error(RTCError error, const std::string& str)
-+// : error(error), str(str) {}
-+//
-+// ~rtcore_error() throw() {}
-+//
-+// const char* what () const throw () {
-+// return str.c_str();
-+// }
-+//
-+// RTCError error;
-+// std::string str;
-+// };
-+// -- GODOT end --
++// -- GODOT start --
++#if 0
+ /*! used to throw embree API errors */
+ struct rtcore_error : public std::exception
+ {
+@@ -112,14 +123,18 @@ namespace embree
+ RTCError error;
+ std::string str;
+ };
++#endif
#if defined(DEBUG) // only report file and line in debug mode
-+ // -- GODOT begin --
-+ // #define throw_RTCError(error,str) \
-+ // throw rtcore_error(error,std::string(__FILE__) + " (" + toString(__LINE__) + "): " + std::string(str));
#define throw_RTCError(error,str) \
- throw rtcore_error(error,std::string(__FILE__) + " (" + toString(__LINE__) + "): " + std::string(str));
+ printf("%s (%d): %s", __FILE__, __LINE__, std::string(str).c_str()), abort();
-+ // -- GODOT end --
++ // throw rtcore_error(error,std::string(__FILE__) + " (" + toString(__LINE__) + "): " + std::string(str));
#else
-+ // -- GODOT begin --
-+ // #define throw_RTCError(error,str) \
-+ // throw rtcore_error(error,str);
#define throw_RTCError(error,str) \
- throw rtcore_error(error,str);
+ abort();
-+ // -- GODOT end --
++ // throw rtcore_error(error,str);
#endif
++// -- GODOT end --
#define RTC_BUILD_ARGUMENTS_HAS(settings,member) \
+ (settings.byteSize > (offsetof(RTCBuildArguments,member)+sizeof(settings.member)))
diff --git a/thirdparty/embree/kernels/common/scene.cpp b/thirdparty/embree/kernels/common/scene.cpp
-index 0149055f2c..408d7eae6f 100644
+index ad1916c54e..65d31d0f81 100644
--- a/thirdparty/embree/kernels/common/scene.cpp
+++ b/thirdparty/embree/kernels/common/scene.cpp
-@@ -792,16 +792,18 @@ namespace embree
+@@ -790,16 +790,18 @@ namespace embree
}
/* initiate build */
diff --git a/thirdparty/embree/patches/godot-changes-ubsan.patch b/thirdparty/embree/patches/godot-changes-ubsan.patch
deleted file mode 100644
index 1336246f0d..0000000000
--- a/thirdparty/embree/patches/godot-changes-ubsan.patch
+++ /dev/null
@@ -1,24 +0,0 @@
-diff --git a/thirdparty/embree/kernels/builders/primrefgen.cpp b/thirdparty/embree/kernels/builders/primrefgen.cpp
-index bb4fc81dfe..d279dc4993 100644
---- a/thirdparty/embree/kernels/builders/primrefgen.cpp
-+++ b/thirdparty/embree/kernels/builders/primrefgen.cpp
-@@ -184,6 +184,9 @@ namespace embree
-
- // special variants for grid meshes
-
-+// -- GODOT start --
-+#if defined(EMBREE_GEOMETRY_GRID)
-+// -- GODOT end --
- PrimInfo createPrimRefArrayGrids(Scene* scene, mvector<PrimRef>& prims, mvector<SubGridBuildData>& sgrids)
- {
- PrimInfo pinfo(empty);
-@@ -293,6 +296,9 @@ namespace embree
-
- return pinfo;
- }
-+// -- GODOT start --
-+#endif
-+// -- GODOT end --
-
- // ====================================================================================================
- // ====================================================================================================
diff --git a/thirdparty/glad/LICENSE b/thirdparty/glad/LICENSE
index b6e2ca25b0..4965a6bffc 100644
--- a/thirdparty/glad/LICENSE
+++ b/thirdparty/glad/LICENSE
@@ -1,20 +1,63 @@
-The MIT License (MIT)
-
-Copyright (c) 2013-2018 David Herberth
-
-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.
+The glad source code:
+
+ The MIT License (MIT)
+
+ Copyright (c) 2013-2022 David Herberth
+
+ 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.
+
+
+The Khronos Specifications:
+
+ Copyright (c) 2013-2020 The Khronos Group Inc.
+
+ 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.
+
+
+The EGL Specification and various headers:
+
+ Copyright (c) 2007-2016 The Khronos Group Inc.
+
+ Permission is hereby granted, free of charge, to any person obtaining a
+ copy of this software and/or associated documentation files (the
+ "Materials"), to deal in the Materials without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Materials, and to
+ permit persons to whom the Materials are 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 Materials.
+
+ THE MATERIALS ARE 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
+ MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
diff --git a/thirdparty/glad/gl.c b/thirdparty/glad/gl.c
new file mode 100644
index 0000000000..6be716284c
--- /dev/null
+++ b/thirdparty/glad/gl.c
@@ -0,0 +1,1995 @@
+/**
+ * SPDX-License-Identifier: (WTFPL OR CC0-1.0) AND Apache-2.0
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <glad/gl.h>
+
+#ifndef GLAD_IMPL_UTIL_C_
+#define GLAD_IMPL_UTIL_C_
+
+#ifdef _MSC_VER
+#define GLAD_IMPL_UTIL_SSCANF sscanf_s
+#else
+#define GLAD_IMPL_UTIL_SSCANF sscanf
+#endif
+
+#endif /* GLAD_IMPL_UTIL_C_ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+
+int GLAD_GL_VERSION_1_0 = 0;
+int GLAD_GL_VERSION_1_1 = 0;
+int GLAD_GL_VERSION_1_2 = 0;
+int GLAD_GL_VERSION_1_3 = 0;
+int GLAD_GL_VERSION_1_4 = 0;
+int GLAD_GL_VERSION_1_5 = 0;
+int GLAD_GL_VERSION_2_0 = 0;
+int GLAD_GL_VERSION_2_1 = 0;
+int GLAD_GL_VERSION_3_0 = 0;
+int GLAD_GL_VERSION_3_1 = 0;
+int GLAD_GL_VERSION_3_2 = 0;
+int GLAD_GL_VERSION_3_3 = 0;
+int GLAD_GL_ARB_debug_output = 0;
+int GLAD_GL_ARB_framebuffer_object = 0;
+int GLAD_GL_EXT_framebuffer_blit = 0;
+int GLAD_GL_EXT_framebuffer_multisample = 0;
+int GLAD_GL_EXT_framebuffer_object = 0;
+int GLAD_GL_OVR_multiview = 0;
+int GLAD_GL_OVR_multiview2 = 0;
+
+
+
+PFNGLACCUMPROC glad_glAccum = NULL;
+PFNGLACTIVETEXTUREPROC glad_glActiveTexture = NULL;
+PFNGLALPHAFUNCPROC glad_glAlphaFunc = NULL;
+PFNGLARETEXTURESRESIDENTPROC glad_glAreTexturesResident = NULL;
+PFNGLARRAYELEMENTPROC glad_glArrayElement = NULL;
+PFNGLATTACHSHADERPROC glad_glAttachShader = NULL;
+PFNGLBEGINPROC glad_glBegin = NULL;
+PFNGLBEGINCONDITIONALRENDERPROC glad_glBeginConditionalRender = NULL;
+PFNGLBEGINQUERYPROC glad_glBeginQuery = NULL;
+PFNGLBEGINTRANSFORMFEEDBACKPROC glad_glBeginTransformFeedback = NULL;
+PFNGLBINDATTRIBLOCATIONPROC glad_glBindAttribLocation = NULL;
+PFNGLBINDBUFFERPROC glad_glBindBuffer = NULL;
+PFNGLBINDBUFFERBASEPROC glad_glBindBufferBase = NULL;
+PFNGLBINDBUFFERRANGEPROC glad_glBindBufferRange = NULL;
+PFNGLBINDFRAGDATALOCATIONPROC glad_glBindFragDataLocation = NULL;
+PFNGLBINDFRAGDATALOCATIONINDEXEDPROC glad_glBindFragDataLocationIndexed = NULL;
+PFNGLBINDFRAMEBUFFERPROC glad_glBindFramebuffer = NULL;
+PFNGLBINDFRAMEBUFFEREXTPROC glad_glBindFramebufferEXT = NULL;
+PFNGLBINDRENDERBUFFERPROC glad_glBindRenderbuffer = NULL;
+PFNGLBINDRENDERBUFFEREXTPROC glad_glBindRenderbufferEXT = NULL;
+PFNGLBINDSAMPLERPROC glad_glBindSampler = NULL;
+PFNGLBINDTEXTUREPROC glad_glBindTexture = NULL;
+PFNGLBINDVERTEXARRAYPROC glad_glBindVertexArray = NULL;
+PFNGLBITMAPPROC glad_glBitmap = NULL;
+PFNGLBLENDCOLORPROC glad_glBlendColor = NULL;
+PFNGLBLENDEQUATIONPROC glad_glBlendEquation = NULL;
+PFNGLBLENDEQUATIONSEPARATEPROC glad_glBlendEquationSeparate = NULL;
+PFNGLBLENDFUNCPROC glad_glBlendFunc = NULL;
+PFNGLBLENDFUNCSEPARATEPROC glad_glBlendFuncSeparate = NULL;
+PFNGLBLITFRAMEBUFFERPROC glad_glBlitFramebuffer = NULL;
+PFNGLBLITFRAMEBUFFEREXTPROC glad_glBlitFramebufferEXT = NULL;
+PFNGLBUFFERDATAPROC glad_glBufferData = NULL;
+PFNGLBUFFERSUBDATAPROC glad_glBufferSubData = NULL;
+PFNGLCALLLISTPROC glad_glCallList = NULL;
+PFNGLCALLLISTSPROC glad_glCallLists = NULL;
+PFNGLCHECKFRAMEBUFFERSTATUSPROC glad_glCheckFramebufferStatus = NULL;
+PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC glad_glCheckFramebufferStatusEXT = NULL;
+PFNGLCLAMPCOLORPROC glad_glClampColor = NULL;
+PFNGLCLEARPROC glad_glClear = NULL;
+PFNGLCLEARACCUMPROC glad_glClearAccum = NULL;
+PFNGLCLEARBUFFERFIPROC glad_glClearBufferfi = NULL;
+PFNGLCLEARBUFFERFVPROC glad_glClearBufferfv = NULL;
+PFNGLCLEARBUFFERIVPROC glad_glClearBufferiv = NULL;
+PFNGLCLEARBUFFERUIVPROC glad_glClearBufferuiv = NULL;
+PFNGLCLEARCOLORPROC glad_glClearColor = NULL;
+PFNGLCLEARDEPTHPROC glad_glClearDepth = NULL;
+PFNGLCLEARINDEXPROC glad_glClearIndex = NULL;
+PFNGLCLEARSTENCILPROC glad_glClearStencil = NULL;
+PFNGLCLIENTACTIVETEXTUREPROC glad_glClientActiveTexture = NULL;
+PFNGLCLIENTWAITSYNCPROC glad_glClientWaitSync = NULL;
+PFNGLCLIPPLANEPROC glad_glClipPlane = NULL;
+PFNGLCOLOR3BPROC glad_glColor3b = NULL;
+PFNGLCOLOR3BVPROC glad_glColor3bv = NULL;
+PFNGLCOLOR3DPROC glad_glColor3d = NULL;
+PFNGLCOLOR3DVPROC glad_glColor3dv = NULL;
+PFNGLCOLOR3FPROC glad_glColor3f = NULL;
+PFNGLCOLOR3FVPROC glad_glColor3fv = NULL;
+PFNGLCOLOR3IPROC glad_glColor3i = NULL;
+PFNGLCOLOR3IVPROC glad_glColor3iv = NULL;
+PFNGLCOLOR3SPROC glad_glColor3s = NULL;
+PFNGLCOLOR3SVPROC glad_glColor3sv = NULL;
+PFNGLCOLOR3UBPROC glad_glColor3ub = NULL;
+PFNGLCOLOR3UBVPROC glad_glColor3ubv = NULL;
+PFNGLCOLOR3UIPROC glad_glColor3ui = NULL;
+PFNGLCOLOR3UIVPROC glad_glColor3uiv = NULL;
+PFNGLCOLOR3USPROC glad_glColor3us = NULL;
+PFNGLCOLOR3USVPROC glad_glColor3usv = NULL;
+PFNGLCOLOR4BPROC glad_glColor4b = NULL;
+PFNGLCOLOR4BVPROC glad_glColor4bv = NULL;
+PFNGLCOLOR4DPROC glad_glColor4d = NULL;
+PFNGLCOLOR4DVPROC glad_glColor4dv = NULL;
+PFNGLCOLOR4FPROC glad_glColor4f = NULL;
+PFNGLCOLOR4FVPROC glad_glColor4fv = NULL;
+PFNGLCOLOR4IPROC glad_glColor4i = NULL;
+PFNGLCOLOR4IVPROC glad_glColor4iv = NULL;
+PFNGLCOLOR4SPROC glad_glColor4s = NULL;
+PFNGLCOLOR4SVPROC glad_glColor4sv = NULL;
+PFNGLCOLOR4UBPROC glad_glColor4ub = NULL;
+PFNGLCOLOR4UBVPROC glad_glColor4ubv = NULL;
+PFNGLCOLOR4UIPROC glad_glColor4ui = NULL;
+PFNGLCOLOR4UIVPROC glad_glColor4uiv = NULL;
+PFNGLCOLOR4USPROC glad_glColor4us = NULL;
+PFNGLCOLOR4USVPROC glad_glColor4usv = NULL;
+PFNGLCOLORMASKPROC glad_glColorMask = NULL;
+PFNGLCOLORMASKIPROC glad_glColorMaski = NULL;
+PFNGLCOLORMATERIALPROC glad_glColorMaterial = NULL;
+PFNGLCOLORP3UIPROC glad_glColorP3ui = NULL;
+PFNGLCOLORP3UIVPROC glad_glColorP3uiv = NULL;
+PFNGLCOLORP4UIPROC glad_glColorP4ui = NULL;
+PFNGLCOLORP4UIVPROC glad_glColorP4uiv = NULL;
+PFNGLCOLORPOINTERPROC glad_glColorPointer = NULL;
+PFNGLCOMPILESHADERPROC glad_glCompileShader = NULL;
+PFNGLCOMPRESSEDTEXIMAGE1DPROC glad_glCompressedTexImage1D = NULL;
+PFNGLCOMPRESSEDTEXIMAGE2DPROC glad_glCompressedTexImage2D = NULL;
+PFNGLCOMPRESSEDTEXIMAGE3DPROC glad_glCompressedTexImage3D = NULL;
+PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC glad_glCompressedTexSubImage1D = NULL;
+PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC glad_glCompressedTexSubImage2D = NULL;
+PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC glad_glCompressedTexSubImage3D = NULL;
+PFNGLCOPYBUFFERSUBDATAPROC glad_glCopyBufferSubData = NULL;
+PFNGLCOPYPIXELSPROC glad_glCopyPixels = NULL;
+PFNGLCOPYTEXIMAGE1DPROC glad_glCopyTexImage1D = NULL;
+PFNGLCOPYTEXIMAGE2DPROC glad_glCopyTexImage2D = NULL;
+PFNGLCOPYTEXSUBIMAGE1DPROC glad_glCopyTexSubImage1D = NULL;
+PFNGLCOPYTEXSUBIMAGE2DPROC glad_glCopyTexSubImage2D = NULL;
+PFNGLCOPYTEXSUBIMAGE3DPROC glad_glCopyTexSubImage3D = NULL;
+PFNGLCREATEPROGRAMPROC glad_glCreateProgram = NULL;
+PFNGLCREATESHADERPROC glad_glCreateShader = NULL;
+PFNGLCULLFACEPROC glad_glCullFace = NULL;
+PFNGLDEBUGMESSAGECALLBACKARBPROC glad_glDebugMessageCallbackARB = NULL;
+PFNGLDEBUGMESSAGECONTROLARBPROC glad_glDebugMessageControlARB = NULL;
+PFNGLDEBUGMESSAGEINSERTARBPROC glad_glDebugMessageInsertARB = NULL;
+PFNGLDELETEBUFFERSPROC glad_glDeleteBuffers = NULL;
+PFNGLDELETEFRAMEBUFFERSPROC glad_glDeleteFramebuffers = NULL;
+PFNGLDELETEFRAMEBUFFERSEXTPROC glad_glDeleteFramebuffersEXT = NULL;
+PFNGLDELETELISTSPROC glad_glDeleteLists = NULL;
+PFNGLDELETEPROGRAMPROC glad_glDeleteProgram = NULL;
+PFNGLDELETEQUERIESPROC glad_glDeleteQueries = NULL;
+PFNGLDELETERENDERBUFFERSPROC glad_glDeleteRenderbuffers = NULL;
+PFNGLDELETERENDERBUFFERSEXTPROC glad_glDeleteRenderbuffersEXT = NULL;
+PFNGLDELETESAMPLERSPROC glad_glDeleteSamplers = NULL;
+PFNGLDELETESHADERPROC glad_glDeleteShader = NULL;
+PFNGLDELETESYNCPROC glad_glDeleteSync = NULL;
+PFNGLDELETETEXTURESPROC glad_glDeleteTextures = NULL;
+PFNGLDELETEVERTEXARRAYSPROC glad_glDeleteVertexArrays = NULL;
+PFNGLDEPTHFUNCPROC glad_glDepthFunc = NULL;
+PFNGLDEPTHMASKPROC glad_glDepthMask = NULL;
+PFNGLDEPTHRANGEPROC glad_glDepthRange = NULL;
+PFNGLDETACHSHADERPROC glad_glDetachShader = NULL;
+PFNGLDISABLEPROC glad_glDisable = NULL;
+PFNGLDISABLECLIENTSTATEPROC glad_glDisableClientState = NULL;
+PFNGLDISABLEVERTEXATTRIBARRAYPROC glad_glDisableVertexAttribArray = NULL;
+PFNGLDISABLEIPROC glad_glDisablei = NULL;
+PFNGLDRAWARRAYSPROC glad_glDrawArrays = NULL;
+PFNGLDRAWARRAYSINSTANCEDPROC glad_glDrawArraysInstanced = NULL;
+PFNGLDRAWBUFFERPROC glad_glDrawBuffer = NULL;
+PFNGLDRAWBUFFERSPROC glad_glDrawBuffers = NULL;
+PFNGLDRAWELEMENTSPROC glad_glDrawElements = NULL;
+PFNGLDRAWELEMENTSBASEVERTEXPROC glad_glDrawElementsBaseVertex = NULL;
+PFNGLDRAWELEMENTSINSTANCEDPROC glad_glDrawElementsInstanced = NULL;
+PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC glad_glDrawElementsInstancedBaseVertex = NULL;
+PFNGLDRAWPIXELSPROC glad_glDrawPixels = NULL;
+PFNGLDRAWRANGEELEMENTSPROC glad_glDrawRangeElements = NULL;
+PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC glad_glDrawRangeElementsBaseVertex = NULL;
+PFNGLEDGEFLAGPROC glad_glEdgeFlag = NULL;
+PFNGLEDGEFLAGPOINTERPROC glad_glEdgeFlagPointer = NULL;
+PFNGLEDGEFLAGVPROC glad_glEdgeFlagv = NULL;
+PFNGLENABLEPROC glad_glEnable = NULL;
+PFNGLENABLECLIENTSTATEPROC glad_glEnableClientState = NULL;
+PFNGLENABLEVERTEXATTRIBARRAYPROC glad_glEnableVertexAttribArray = NULL;
+PFNGLENABLEIPROC glad_glEnablei = NULL;
+PFNGLENDPROC glad_glEnd = NULL;
+PFNGLENDCONDITIONALRENDERPROC glad_glEndConditionalRender = NULL;
+PFNGLENDLISTPROC glad_glEndList = NULL;
+PFNGLENDQUERYPROC glad_glEndQuery = NULL;
+PFNGLENDTRANSFORMFEEDBACKPROC glad_glEndTransformFeedback = NULL;
+PFNGLEVALCOORD1DPROC glad_glEvalCoord1d = NULL;
+PFNGLEVALCOORD1DVPROC glad_glEvalCoord1dv = NULL;
+PFNGLEVALCOORD1FPROC glad_glEvalCoord1f = NULL;
+PFNGLEVALCOORD1FVPROC glad_glEvalCoord1fv = NULL;
+PFNGLEVALCOORD2DPROC glad_glEvalCoord2d = NULL;
+PFNGLEVALCOORD2DVPROC glad_glEvalCoord2dv = NULL;
+PFNGLEVALCOORD2FPROC glad_glEvalCoord2f = NULL;
+PFNGLEVALCOORD2FVPROC glad_glEvalCoord2fv = NULL;
+PFNGLEVALMESH1PROC glad_glEvalMesh1 = NULL;
+PFNGLEVALMESH2PROC glad_glEvalMesh2 = NULL;
+PFNGLEVALPOINT1PROC glad_glEvalPoint1 = NULL;
+PFNGLEVALPOINT2PROC glad_glEvalPoint2 = NULL;
+PFNGLFEEDBACKBUFFERPROC glad_glFeedbackBuffer = NULL;
+PFNGLFENCESYNCPROC glad_glFenceSync = NULL;
+PFNGLFINISHPROC glad_glFinish = NULL;
+PFNGLFLUSHPROC glad_glFlush = NULL;
+PFNGLFLUSHMAPPEDBUFFERRANGEPROC glad_glFlushMappedBufferRange = NULL;
+PFNGLFOGCOORDPOINTERPROC glad_glFogCoordPointer = NULL;
+PFNGLFOGCOORDDPROC glad_glFogCoordd = NULL;
+PFNGLFOGCOORDDVPROC glad_glFogCoorddv = NULL;
+PFNGLFOGCOORDFPROC glad_glFogCoordf = NULL;
+PFNGLFOGCOORDFVPROC glad_glFogCoordfv = NULL;
+PFNGLFOGFPROC glad_glFogf = NULL;
+PFNGLFOGFVPROC glad_glFogfv = NULL;
+PFNGLFOGIPROC glad_glFogi = NULL;
+PFNGLFOGIVPROC glad_glFogiv = NULL;
+PFNGLFRAMEBUFFERRENDERBUFFERPROC glad_glFramebufferRenderbuffer = NULL;
+PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glad_glFramebufferRenderbufferEXT = NULL;
+PFNGLFRAMEBUFFERTEXTUREPROC glad_glFramebufferTexture = NULL;
+PFNGLFRAMEBUFFERTEXTURE1DPROC glad_glFramebufferTexture1D = NULL;
+PFNGLFRAMEBUFFERTEXTURE1DEXTPROC glad_glFramebufferTexture1DEXT = NULL;
+PFNGLFRAMEBUFFERTEXTURE2DPROC glad_glFramebufferTexture2D = NULL;
+PFNGLFRAMEBUFFERTEXTURE2DEXTPROC glad_glFramebufferTexture2DEXT = NULL;
+PFNGLFRAMEBUFFERTEXTURE3DPROC glad_glFramebufferTexture3D = NULL;
+PFNGLFRAMEBUFFERTEXTURE3DEXTPROC glad_glFramebufferTexture3DEXT = NULL;
+PFNGLFRAMEBUFFERTEXTURELAYERPROC glad_glFramebufferTextureLayer = NULL;
+PFNGLFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC glad_glFramebufferTextureMultiviewOVR = NULL;
+PFNGLFRONTFACEPROC glad_glFrontFace = NULL;
+PFNGLFRUSTUMPROC glad_glFrustum = NULL;
+PFNGLGENBUFFERSPROC glad_glGenBuffers = NULL;
+PFNGLGENFRAMEBUFFERSPROC glad_glGenFramebuffers = NULL;
+PFNGLGENFRAMEBUFFERSEXTPROC glad_glGenFramebuffersEXT = NULL;
+PFNGLGENLISTSPROC glad_glGenLists = NULL;
+PFNGLGENQUERIESPROC glad_glGenQueries = NULL;
+PFNGLGENRENDERBUFFERSPROC glad_glGenRenderbuffers = NULL;
+PFNGLGENRENDERBUFFERSEXTPROC glad_glGenRenderbuffersEXT = NULL;
+PFNGLGENSAMPLERSPROC glad_glGenSamplers = NULL;
+PFNGLGENTEXTURESPROC glad_glGenTextures = NULL;
+PFNGLGENVERTEXARRAYSPROC glad_glGenVertexArrays = NULL;
+PFNGLGENERATEMIPMAPPROC glad_glGenerateMipmap = NULL;
+PFNGLGENERATEMIPMAPEXTPROC glad_glGenerateMipmapEXT = NULL;
+PFNGLGETACTIVEATTRIBPROC glad_glGetActiveAttrib = NULL;
+PFNGLGETACTIVEUNIFORMPROC glad_glGetActiveUniform = NULL;
+PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC glad_glGetActiveUniformBlockName = NULL;
+PFNGLGETACTIVEUNIFORMBLOCKIVPROC glad_glGetActiveUniformBlockiv = NULL;
+PFNGLGETACTIVEUNIFORMNAMEPROC glad_glGetActiveUniformName = NULL;
+PFNGLGETACTIVEUNIFORMSIVPROC glad_glGetActiveUniformsiv = NULL;
+PFNGLGETATTACHEDSHADERSPROC glad_glGetAttachedShaders = NULL;
+PFNGLGETATTRIBLOCATIONPROC glad_glGetAttribLocation = NULL;
+PFNGLGETBOOLEANI_VPROC glad_glGetBooleani_v = NULL;
+PFNGLGETBOOLEANVPROC glad_glGetBooleanv = NULL;
+PFNGLGETBUFFERPARAMETERI64VPROC glad_glGetBufferParameteri64v = NULL;
+PFNGLGETBUFFERPARAMETERIVPROC glad_glGetBufferParameteriv = NULL;
+PFNGLGETBUFFERPOINTERVPROC glad_glGetBufferPointerv = NULL;
+PFNGLGETBUFFERSUBDATAPROC glad_glGetBufferSubData = NULL;
+PFNGLGETCLIPPLANEPROC glad_glGetClipPlane = NULL;
+PFNGLGETCOMPRESSEDTEXIMAGEPROC glad_glGetCompressedTexImage = NULL;
+PFNGLGETDEBUGMESSAGELOGARBPROC glad_glGetDebugMessageLogARB = NULL;
+PFNGLGETDOUBLEVPROC glad_glGetDoublev = NULL;
+PFNGLGETERRORPROC glad_glGetError = NULL;
+PFNGLGETFLOATVPROC glad_glGetFloatv = NULL;
+PFNGLGETFRAGDATAINDEXPROC glad_glGetFragDataIndex = NULL;
+PFNGLGETFRAGDATALOCATIONPROC glad_glGetFragDataLocation = NULL;
+PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC glad_glGetFramebufferAttachmentParameteriv = NULL;
+PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC glad_glGetFramebufferAttachmentParameterivEXT = NULL;
+PFNGLGETINTEGER64I_VPROC glad_glGetInteger64i_v = NULL;
+PFNGLGETINTEGER64VPROC glad_glGetInteger64v = NULL;
+PFNGLGETINTEGERI_VPROC glad_glGetIntegeri_v = NULL;
+PFNGLGETINTEGERVPROC glad_glGetIntegerv = NULL;
+PFNGLGETLIGHTFVPROC glad_glGetLightfv = NULL;
+PFNGLGETLIGHTIVPROC glad_glGetLightiv = NULL;
+PFNGLGETMAPDVPROC glad_glGetMapdv = NULL;
+PFNGLGETMAPFVPROC glad_glGetMapfv = NULL;
+PFNGLGETMAPIVPROC glad_glGetMapiv = NULL;
+PFNGLGETMATERIALFVPROC glad_glGetMaterialfv = NULL;
+PFNGLGETMATERIALIVPROC glad_glGetMaterialiv = NULL;
+PFNGLGETMULTISAMPLEFVPROC glad_glGetMultisamplefv = NULL;
+PFNGLGETPIXELMAPFVPROC glad_glGetPixelMapfv = NULL;
+PFNGLGETPIXELMAPUIVPROC glad_glGetPixelMapuiv = NULL;
+PFNGLGETPIXELMAPUSVPROC glad_glGetPixelMapusv = NULL;
+PFNGLGETPOINTERVPROC glad_glGetPointerv = NULL;
+PFNGLGETPOLYGONSTIPPLEPROC glad_glGetPolygonStipple = NULL;
+PFNGLGETPROGRAMINFOLOGPROC glad_glGetProgramInfoLog = NULL;
+PFNGLGETPROGRAMIVPROC glad_glGetProgramiv = NULL;
+PFNGLGETQUERYOBJECTI64VPROC glad_glGetQueryObjecti64v = NULL;
+PFNGLGETQUERYOBJECTIVPROC glad_glGetQueryObjectiv = NULL;
+PFNGLGETQUERYOBJECTUI64VPROC glad_glGetQueryObjectui64v = NULL;
+PFNGLGETQUERYOBJECTUIVPROC glad_glGetQueryObjectuiv = NULL;
+PFNGLGETQUERYIVPROC glad_glGetQueryiv = NULL;
+PFNGLGETRENDERBUFFERPARAMETERIVPROC glad_glGetRenderbufferParameteriv = NULL;
+PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC glad_glGetRenderbufferParameterivEXT = NULL;
+PFNGLGETSAMPLERPARAMETERIIVPROC glad_glGetSamplerParameterIiv = NULL;
+PFNGLGETSAMPLERPARAMETERIUIVPROC glad_glGetSamplerParameterIuiv = NULL;
+PFNGLGETSAMPLERPARAMETERFVPROC glad_glGetSamplerParameterfv = NULL;
+PFNGLGETSAMPLERPARAMETERIVPROC glad_glGetSamplerParameteriv = NULL;
+PFNGLGETSHADERINFOLOGPROC glad_glGetShaderInfoLog = NULL;
+PFNGLGETSHADERSOURCEPROC glad_glGetShaderSource = NULL;
+PFNGLGETSHADERIVPROC glad_glGetShaderiv = NULL;
+PFNGLGETSTRINGPROC glad_glGetString = NULL;
+PFNGLGETSTRINGIPROC glad_glGetStringi = NULL;
+PFNGLGETSYNCIVPROC glad_glGetSynciv = NULL;
+PFNGLGETTEXENVFVPROC glad_glGetTexEnvfv = NULL;
+PFNGLGETTEXENVIVPROC glad_glGetTexEnviv = NULL;
+PFNGLGETTEXGENDVPROC glad_glGetTexGendv = NULL;
+PFNGLGETTEXGENFVPROC glad_glGetTexGenfv = NULL;
+PFNGLGETTEXGENIVPROC glad_glGetTexGeniv = NULL;
+PFNGLGETTEXIMAGEPROC glad_glGetTexImage = NULL;
+PFNGLGETTEXLEVELPARAMETERFVPROC glad_glGetTexLevelParameterfv = NULL;
+PFNGLGETTEXLEVELPARAMETERIVPROC glad_glGetTexLevelParameteriv = NULL;
+PFNGLGETTEXPARAMETERIIVPROC glad_glGetTexParameterIiv = NULL;
+PFNGLGETTEXPARAMETERIUIVPROC glad_glGetTexParameterIuiv = NULL;
+PFNGLGETTEXPARAMETERFVPROC glad_glGetTexParameterfv = NULL;
+PFNGLGETTEXPARAMETERIVPROC glad_glGetTexParameteriv = NULL;
+PFNGLGETTRANSFORMFEEDBACKVARYINGPROC glad_glGetTransformFeedbackVarying = NULL;
+PFNGLGETUNIFORMBLOCKINDEXPROC glad_glGetUniformBlockIndex = NULL;
+PFNGLGETUNIFORMINDICESPROC glad_glGetUniformIndices = NULL;
+PFNGLGETUNIFORMLOCATIONPROC glad_glGetUniformLocation = NULL;
+PFNGLGETUNIFORMFVPROC glad_glGetUniformfv = NULL;
+PFNGLGETUNIFORMIVPROC glad_glGetUniformiv = NULL;
+PFNGLGETUNIFORMUIVPROC glad_glGetUniformuiv = NULL;
+PFNGLGETVERTEXATTRIBIIVPROC glad_glGetVertexAttribIiv = NULL;
+PFNGLGETVERTEXATTRIBIUIVPROC glad_glGetVertexAttribIuiv = NULL;
+PFNGLGETVERTEXATTRIBPOINTERVPROC glad_glGetVertexAttribPointerv = NULL;
+PFNGLGETVERTEXATTRIBDVPROC glad_glGetVertexAttribdv = NULL;
+PFNGLGETVERTEXATTRIBFVPROC glad_glGetVertexAttribfv = NULL;
+PFNGLGETVERTEXATTRIBIVPROC glad_glGetVertexAttribiv = NULL;
+PFNGLHINTPROC glad_glHint = NULL;
+PFNGLINDEXMASKPROC glad_glIndexMask = NULL;
+PFNGLINDEXPOINTERPROC glad_glIndexPointer = NULL;
+PFNGLINDEXDPROC glad_glIndexd = NULL;
+PFNGLINDEXDVPROC glad_glIndexdv = NULL;
+PFNGLINDEXFPROC glad_glIndexf = NULL;
+PFNGLINDEXFVPROC glad_glIndexfv = NULL;
+PFNGLINDEXIPROC glad_glIndexi = NULL;
+PFNGLINDEXIVPROC glad_glIndexiv = NULL;
+PFNGLINDEXSPROC glad_glIndexs = NULL;
+PFNGLINDEXSVPROC glad_glIndexsv = NULL;
+PFNGLINDEXUBPROC glad_glIndexub = NULL;
+PFNGLINDEXUBVPROC glad_glIndexubv = NULL;
+PFNGLINITNAMESPROC glad_glInitNames = NULL;
+PFNGLINTERLEAVEDARRAYSPROC glad_glInterleavedArrays = NULL;
+PFNGLISBUFFERPROC glad_glIsBuffer = NULL;
+PFNGLISENABLEDPROC glad_glIsEnabled = NULL;
+PFNGLISENABLEDIPROC glad_glIsEnabledi = NULL;
+PFNGLISFRAMEBUFFERPROC glad_glIsFramebuffer = NULL;
+PFNGLISFRAMEBUFFEREXTPROC glad_glIsFramebufferEXT = NULL;
+PFNGLISLISTPROC glad_glIsList = NULL;
+PFNGLISPROGRAMPROC glad_glIsProgram = NULL;
+PFNGLISQUERYPROC glad_glIsQuery = NULL;
+PFNGLISRENDERBUFFERPROC glad_glIsRenderbuffer = NULL;
+PFNGLISRENDERBUFFEREXTPROC glad_glIsRenderbufferEXT = NULL;
+PFNGLISSAMPLERPROC glad_glIsSampler = NULL;
+PFNGLISSHADERPROC glad_glIsShader = NULL;
+PFNGLISSYNCPROC glad_glIsSync = NULL;
+PFNGLISTEXTUREPROC glad_glIsTexture = NULL;
+PFNGLISVERTEXARRAYPROC glad_glIsVertexArray = NULL;
+PFNGLLIGHTMODELFPROC glad_glLightModelf = NULL;
+PFNGLLIGHTMODELFVPROC glad_glLightModelfv = NULL;
+PFNGLLIGHTMODELIPROC glad_glLightModeli = NULL;
+PFNGLLIGHTMODELIVPROC glad_glLightModeliv = NULL;
+PFNGLLIGHTFPROC glad_glLightf = NULL;
+PFNGLLIGHTFVPROC glad_glLightfv = NULL;
+PFNGLLIGHTIPROC glad_glLighti = NULL;
+PFNGLLIGHTIVPROC glad_glLightiv = NULL;
+PFNGLLINESTIPPLEPROC glad_glLineStipple = NULL;
+PFNGLLINEWIDTHPROC glad_glLineWidth = NULL;
+PFNGLLINKPROGRAMPROC glad_glLinkProgram = NULL;
+PFNGLLISTBASEPROC glad_glListBase = NULL;
+PFNGLLOADIDENTITYPROC glad_glLoadIdentity = NULL;
+PFNGLLOADMATRIXDPROC glad_glLoadMatrixd = NULL;
+PFNGLLOADMATRIXFPROC glad_glLoadMatrixf = NULL;
+PFNGLLOADNAMEPROC glad_glLoadName = NULL;
+PFNGLLOADTRANSPOSEMATRIXDPROC glad_glLoadTransposeMatrixd = NULL;
+PFNGLLOADTRANSPOSEMATRIXFPROC glad_glLoadTransposeMatrixf = NULL;
+PFNGLLOGICOPPROC glad_glLogicOp = NULL;
+PFNGLMAP1DPROC glad_glMap1d = NULL;
+PFNGLMAP1FPROC glad_glMap1f = NULL;
+PFNGLMAP2DPROC glad_glMap2d = NULL;
+PFNGLMAP2FPROC glad_glMap2f = NULL;
+PFNGLMAPBUFFERPROC glad_glMapBuffer = NULL;
+PFNGLMAPBUFFERRANGEPROC glad_glMapBufferRange = NULL;
+PFNGLMAPGRID1DPROC glad_glMapGrid1d = NULL;
+PFNGLMAPGRID1FPROC glad_glMapGrid1f = NULL;
+PFNGLMAPGRID2DPROC glad_glMapGrid2d = NULL;
+PFNGLMAPGRID2FPROC glad_glMapGrid2f = NULL;
+PFNGLMATERIALFPROC glad_glMaterialf = NULL;
+PFNGLMATERIALFVPROC glad_glMaterialfv = NULL;
+PFNGLMATERIALIPROC glad_glMateriali = NULL;
+PFNGLMATERIALIVPROC glad_glMaterialiv = NULL;
+PFNGLMATRIXMODEPROC glad_glMatrixMode = NULL;
+PFNGLMULTMATRIXDPROC glad_glMultMatrixd = NULL;
+PFNGLMULTMATRIXFPROC glad_glMultMatrixf = NULL;
+PFNGLMULTTRANSPOSEMATRIXDPROC glad_glMultTransposeMatrixd = NULL;
+PFNGLMULTTRANSPOSEMATRIXFPROC glad_glMultTransposeMatrixf = NULL;
+PFNGLMULTIDRAWARRAYSPROC glad_glMultiDrawArrays = NULL;
+PFNGLMULTIDRAWELEMENTSPROC glad_glMultiDrawElements = NULL;
+PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC glad_glMultiDrawElementsBaseVertex = NULL;
+PFNGLMULTITEXCOORD1DPROC glad_glMultiTexCoord1d = NULL;
+PFNGLMULTITEXCOORD1DVPROC glad_glMultiTexCoord1dv = NULL;
+PFNGLMULTITEXCOORD1FPROC glad_glMultiTexCoord1f = NULL;
+PFNGLMULTITEXCOORD1FVPROC glad_glMultiTexCoord1fv = NULL;
+PFNGLMULTITEXCOORD1IPROC glad_glMultiTexCoord1i = NULL;
+PFNGLMULTITEXCOORD1IVPROC glad_glMultiTexCoord1iv = NULL;
+PFNGLMULTITEXCOORD1SPROC glad_glMultiTexCoord1s = NULL;
+PFNGLMULTITEXCOORD1SVPROC glad_glMultiTexCoord1sv = NULL;
+PFNGLMULTITEXCOORD2DPROC glad_glMultiTexCoord2d = NULL;
+PFNGLMULTITEXCOORD2DVPROC glad_glMultiTexCoord2dv = NULL;
+PFNGLMULTITEXCOORD2FPROC glad_glMultiTexCoord2f = NULL;
+PFNGLMULTITEXCOORD2FVPROC glad_glMultiTexCoord2fv = NULL;
+PFNGLMULTITEXCOORD2IPROC glad_glMultiTexCoord2i = NULL;
+PFNGLMULTITEXCOORD2IVPROC glad_glMultiTexCoord2iv = NULL;
+PFNGLMULTITEXCOORD2SPROC glad_glMultiTexCoord2s = NULL;
+PFNGLMULTITEXCOORD2SVPROC glad_glMultiTexCoord2sv = NULL;
+PFNGLMULTITEXCOORD3DPROC glad_glMultiTexCoord3d = NULL;
+PFNGLMULTITEXCOORD3DVPROC glad_glMultiTexCoord3dv = NULL;
+PFNGLMULTITEXCOORD3FPROC glad_glMultiTexCoord3f = NULL;
+PFNGLMULTITEXCOORD3FVPROC glad_glMultiTexCoord3fv = NULL;
+PFNGLMULTITEXCOORD3IPROC glad_glMultiTexCoord3i = NULL;
+PFNGLMULTITEXCOORD3IVPROC glad_glMultiTexCoord3iv = NULL;
+PFNGLMULTITEXCOORD3SPROC glad_glMultiTexCoord3s = NULL;
+PFNGLMULTITEXCOORD3SVPROC glad_glMultiTexCoord3sv = NULL;
+PFNGLMULTITEXCOORD4DPROC glad_glMultiTexCoord4d = NULL;
+PFNGLMULTITEXCOORD4DVPROC glad_glMultiTexCoord4dv = NULL;
+PFNGLMULTITEXCOORD4FPROC glad_glMultiTexCoord4f = NULL;
+PFNGLMULTITEXCOORD4FVPROC glad_glMultiTexCoord4fv = NULL;
+PFNGLMULTITEXCOORD4IPROC glad_glMultiTexCoord4i = NULL;
+PFNGLMULTITEXCOORD4IVPROC glad_glMultiTexCoord4iv = NULL;
+PFNGLMULTITEXCOORD4SPROC glad_glMultiTexCoord4s = NULL;
+PFNGLMULTITEXCOORD4SVPROC glad_glMultiTexCoord4sv = NULL;
+PFNGLMULTITEXCOORDP1UIPROC glad_glMultiTexCoordP1ui = NULL;
+PFNGLMULTITEXCOORDP1UIVPROC glad_glMultiTexCoordP1uiv = NULL;
+PFNGLMULTITEXCOORDP2UIPROC glad_glMultiTexCoordP2ui = NULL;
+PFNGLMULTITEXCOORDP2UIVPROC glad_glMultiTexCoordP2uiv = NULL;
+PFNGLMULTITEXCOORDP3UIPROC glad_glMultiTexCoordP3ui = NULL;
+PFNGLMULTITEXCOORDP3UIVPROC glad_glMultiTexCoordP3uiv = NULL;
+PFNGLMULTITEXCOORDP4UIPROC glad_glMultiTexCoordP4ui = NULL;
+PFNGLMULTITEXCOORDP4UIVPROC glad_glMultiTexCoordP4uiv = NULL;
+PFNGLNEWLISTPROC glad_glNewList = NULL;
+PFNGLNORMAL3BPROC glad_glNormal3b = NULL;
+PFNGLNORMAL3BVPROC glad_glNormal3bv = NULL;
+PFNGLNORMAL3DPROC glad_glNormal3d = NULL;
+PFNGLNORMAL3DVPROC glad_glNormal3dv = NULL;
+PFNGLNORMAL3FPROC glad_glNormal3f = NULL;
+PFNGLNORMAL3FVPROC glad_glNormal3fv = NULL;
+PFNGLNORMAL3IPROC glad_glNormal3i = NULL;
+PFNGLNORMAL3IVPROC glad_glNormal3iv = NULL;
+PFNGLNORMAL3SPROC glad_glNormal3s = NULL;
+PFNGLNORMAL3SVPROC glad_glNormal3sv = NULL;
+PFNGLNORMALP3UIPROC glad_glNormalP3ui = NULL;
+PFNGLNORMALP3UIVPROC glad_glNormalP3uiv = NULL;
+PFNGLNORMALPOINTERPROC glad_glNormalPointer = NULL;
+PFNGLORTHOPROC glad_glOrtho = NULL;
+PFNGLPASSTHROUGHPROC glad_glPassThrough = NULL;
+PFNGLPIXELMAPFVPROC glad_glPixelMapfv = NULL;
+PFNGLPIXELMAPUIVPROC glad_glPixelMapuiv = NULL;
+PFNGLPIXELMAPUSVPROC glad_glPixelMapusv = NULL;
+PFNGLPIXELSTOREFPROC glad_glPixelStoref = NULL;
+PFNGLPIXELSTOREIPROC glad_glPixelStorei = NULL;
+PFNGLPIXELTRANSFERFPROC glad_glPixelTransferf = NULL;
+PFNGLPIXELTRANSFERIPROC glad_glPixelTransferi = NULL;
+PFNGLPIXELZOOMPROC glad_glPixelZoom = NULL;
+PFNGLPOINTPARAMETERFPROC glad_glPointParameterf = NULL;
+PFNGLPOINTPARAMETERFVPROC glad_glPointParameterfv = NULL;
+PFNGLPOINTPARAMETERIPROC glad_glPointParameteri = NULL;
+PFNGLPOINTPARAMETERIVPROC glad_glPointParameteriv = NULL;
+PFNGLPOINTSIZEPROC glad_glPointSize = NULL;
+PFNGLPOLYGONMODEPROC glad_glPolygonMode = NULL;
+PFNGLPOLYGONOFFSETPROC glad_glPolygonOffset = NULL;
+PFNGLPOLYGONSTIPPLEPROC glad_glPolygonStipple = NULL;
+PFNGLPOPATTRIBPROC glad_glPopAttrib = NULL;
+PFNGLPOPCLIENTATTRIBPROC glad_glPopClientAttrib = NULL;
+PFNGLPOPMATRIXPROC glad_glPopMatrix = NULL;
+PFNGLPOPNAMEPROC glad_glPopName = NULL;
+PFNGLPRIMITIVERESTARTINDEXPROC glad_glPrimitiveRestartIndex = NULL;
+PFNGLPRIORITIZETEXTURESPROC glad_glPrioritizeTextures = NULL;
+PFNGLPROVOKINGVERTEXPROC glad_glProvokingVertex = NULL;
+PFNGLPUSHATTRIBPROC glad_glPushAttrib = NULL;
+PFNGLPUSHCLIENTATTRIBPROC glad_glPushClientAttrib = NULL;
+PFNGLPUSHMATRIXPROC glad_glPushMatrix = NULL;
+PFNGLPUSHNAMEPROC glad_glPushName = NULL;
+PFNGLQUERYCOUNTERPROC glad_glQueryCounter = NULL;
+PFNGLRASTERPOS2DPROC glad_glRasterPos2d = NULL;
+PFNGLRASTERPOS2DVPROC glad_glRasterPos2dv = NULL;
+PFNGLRASTERPOS2FPROC glad_glRasterPos2f = NULL;
+PFNGLRASTERPOS2FVPROC glad_glRasterPos2fv = NULL;
+PFNGLRASTERPOS2IPROC glad_glRasterPos2i = NULL;
+PFNGLRASTERPOS2IVPROC glad_glRasterPos2iv = NULL;
+PFNGLRASTERPOS2SPROC glad_glRasterPos2s = NULL;
+PFNGLRASTERPOS2SVPROC glad_glRasterPos2sv = NULL;
+PFNGLRASTERPOS3DPROC glad_glRasterPos3d = NULL;
+PFNGLRASTERPOS3DVPROC glad_glRasterPos3dv = NULL;
+PFNGLRASTERPOS3FPROC glad_glRasterPos3f = NULL;
+PFNGLRASTERPOS3FVPROC glad_glRasterPos3fv = NULL;
+PFNGLRASTERPOS3IPROC glad_glRasterPos3i = NULL;
+PFNGLRASTERPOS3IVPROC glad_glRasterPos3iv = NULL;
+PFNGLRASTERPOS3SPROC glad_glRasterPos3s = NULL;
+PFNGLRASTERPOS3SVPROC glad_glRasterPos3sv = NULL;
+PFNGLRASTERPOS4DPROC glad_glRasterPos4d = NULL;
+PFNGLRASTERPOS4DVPROC glad_glRasterPos4dv = NULL;
+PFNGLRASTERPOS4FPROC glad_glRasterPos4f = NULL;
+PFNGLRASTERPOS4FVPROC glad_glRasterPos4fv = NULL;
+PFNGLRASTERPOS4IPROC glad_glRasterPos4i = NULL;
+PFNGLRASTERPOS4IVPROC glad_glRasterPos4iv = NULL;
+PFNGLRASTERPOS4SPROC glad_glRasterPos4s = NULL;
+PFNGLRASTERPOS4SVPROC glad_glRasterPos4sv = NULL;
+PFNGLREADBUFFERPROC glad_glReadBuffer = NULL;
+PFNGLREADPIXELSPROC glad_glReadPixels = NULL;
+PFNGLRECTDPROC glad_glRectd = NULL;
+PFNGLRECTDVPROC glad_glRectdv = NULL;
+PFNGLRECTFPROC glad_glRectf = NULL;
+PFNGLRECTFVPROC glad_glRectfv = NULL;
+PFNGLRECTIPROC glad_glRecti = NULL;
+PFNGLRECTIVPROC glad_glRectiv = NULL;
+PFNGLRECTSPROC glad_glRects = NULL;
+PFNGLRECTSVPROC glad_glRectsv = NULL;
+PFNGLRENDERMODEPROC glad_glRenderMode = NULL;
+PFNGLRENDERBUFFERSTORAGEPROC glad_glRenderbufferStorage = NULL;
+PFNGLRENDERBUFFERSTORAGEEXTPROC glad_glRenderbufferStorageEXT = NULL;
+PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC glad_glRenderbufferStorageMultisample = NULL;
+PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC glad_glRenderbufferStorageMultisampleEXT = NULL;
+PFNGLROTATEDPROC glad_glRotated = NULL;
+PFNGLROTATEFPROC glad_glRotatef = NULL;
+PFNGLSAMPLECOVERAGEPROC glad_glSampleCoverage = NULL;
+PFNGLSAMPLEMASKIPROC glad_glSampleMaski = NULL;
+PFNGLSAMPLERPARAMETERIIVPROC glad_glSamplerParameterIiv = NULL;
+PFNGLSAMPLERPARAMETERIUIVPROC glad_glSamplerParameterIuiv = NULL;
+PFNGLSAMPLERPARAMETERFPROC glad_glSamplerParameterf = NULL;
+PFNGLSAMPLERPARAMETERFVPROC glad_glSamplerParameterfv = NULL;
+PFNGLSAMPLERPARAMETERIPROC glad_glSamplerParameteri = NULL;
+PFNGLSAMPLERPARAMETERIVPROC glad_glSamplerParameteriv = NULL;
+PFNGLSCALEDPROC glad_glScaled = NULL;
+PFNGLSCALEFPROC glad_glScalef = NULL;
+PFNGLSCISSORPROC glad_glScissor = NULL;
+PFNGLSECONDARYCOLOR3BPROC glad_glSecondaryColor3b = NULL;
+PFNGLSECONDARYCOLOR3BVPROC glad_glSecondaryColor3bv = NULL;
+PFNGLSECONDARYCOLOR3DPROC glad_glSecondaryColor3d = NULL;
+PFNGLSECONDARYCOLOR3DVPROC glad_glSecondaryColor3dv = NULL;
+PFNGLSECONDARYCOLOR3FPROC glad_glSecondaryColor3f = NULL;
+PFNGLSECONDARYCOLOR3FVPROC glad_glSecondaryColor3fv = NULL;
+PFNGLSECONDARYCOLOR3IPROC glad_glSecondaryColor3i = NULL;
+PFNGLSECONDARYCOLOR3IVPROC glad_glSecondaryColor3iv = NULL;
+PFNGLSECONDARYCOLOR3SPROC glad_glSecondaryColor3s = NULL;
+PFNGLSECONDARYCOLOR3SVPROC glad_glSecondaryColor3sv = NULL;
+PFNGLSECONDARYCOLOR3UBPROC glad_glSecondaryColor3ub = NULL;
+PFNGLSECONDARYCOLOR3UBVPROC glad_glSecondaryColor3ubv = NULL;
+PFNGLSECONDARYCOLOR3UIPROC glad_glSecondaryColor3ui = NULL;
+PFNGLSECONDARYCOLOR3UIVPROC glad_glSecondaryColor3uiv = NULL;
+PFNGLSECONDARYCOLOR3USPROC glad_glSecondaryColor3us = NULL;
+PFNGLSECONDARYCOLOR3USVPROC glad_glSecondaryColor3usv = NULL;
+PFNGLSECONDARYCOLORP3UIPROC glad_glSecondaryColorP3ui = NULL;
+PFNGLSECONDARYCOLORP3UIVPROC glad_glSecondaryColorP3uiv = NULL;
+PFNGLSECONDARYCOLORPOINTERPROC glad_glSecondaryColorPointer = NULL;
+PFNGLSELECTBUFFERPROC glad_glSelectBuffer = NULL;
+PFNGLSHADEMODELPROC glad_glShadeModel = NULL;
+PFNGLSHADERSOURCEPROC glad_glShaderSource = NULL;
+PFNGLSTENCILFUNCPROC glad_glStencilFunc = NULL;
+PFNGLSTENCILFUNCSEPARATEPROC glad_glStencilFuncSeparate = NULL;
+PFNGLSTENCILMASKPROC glad_glStencilMask = NULL;
+PFNGLSTENCILMASKSEPARATEPROC glad_glStencilMaskSeparate = NULL;
+PFNGLSTENCILOPPROC glad_glStencilOp = NULL;
+PFNGLSTENCILOPSEPARATEPROC glad_glStencilOpSeparate = NULL;
+PFNGLTEXBUFFERPROC glad_glTexBuffer = NULL;
+PFNGLTEXCOORD1DPROC glad_glTexCoord1d = NULL;
+PFNGLTEXCOORD1DVPROC glad_glTexCoord1dv = NULL;
+PFNGLTEXCOORD1FPROC glad_glTexCoord1f = NULL;
+PFNGLTEXCOORD1FVPROC glad_glTexCoord1fv = NULL;
+PFNGLTEXCOORD1IPROC glad_glTexCoord1i = NULL;
+PFNGLTEXCOORD1IVPROC glad_glTexCoord1iv = NULL;
+PFNGLTEXCOORD1SPROC glad_glTexCoord1s = NULL;
+PFNGLTEXCOORD1SVPROC glad_glTexCoord1sv = NULL;
+PFNGLTEXCOORD2DPROC glad_glTexCoord2d = NULL;
+PFNGLTEXCOORD2DVPROC glad_glTexCoord2dv = NULL;
+PFNGLTEXCOORD2FPROC glad_glTexCoord2f = NULL;
+PFNGLTEXCOORD2FVPROC glad_glTexCoord2fv = NULL;
+PFNGLTEXCOORD2IPROC glad_glTexCoord2i = NULL;
+PFNGLTEXCOORD2IVPROC glad_glTexCoord2iv = NULL;
+PFNGLTEXCOORD2SPROC glad_glTexCoord2s = NULL;
+PFNGLTEXCOORD2SVPROC glad_glTexCoord2sv = NULL;
+PFNGLTEXCOORD3DPROC glad_glTexCoord3d = NULL;
+PFNGLTEXCOORD3DVPROC glad_glTexCoord3dv = NULL;
+PFNGLTEXCOORD3FPROC glad_glTexCoord3f = NULL;
+PFNGLTEXCOORD3FVPROC glad_glTexCoord3fv = NULL;
+PFNGLTEXCOORD3IPROC glad_glTexCoord3i = NULL;
+PFNGLTEXCOORD3IVPROC glad_glTexCoord3iv = NULL;
+PFNGLTEXCOORD3SPROC glad_glTexCoord3s = NULL;
+PFNGLTEXCOORD3SVPROC glad_glTexCoord3sv = NULL;
+PFNGLTEXCOORD4DPROC glad_glTexCoord4d = NULL;
+PFNGLTEXCOORD4DVPROC glad_glTexCoord4dv = NULL;
+PFNGLTEXCOORD4FPROC glad_glTexCoord4f = NULL;
+PFNGLTEXCOORD4FVPROC glad_glTexCoord4fv = NULL;
+PFNGLTEXCOORD4IPROC glad_glTexCoord4i = NULL;
+PFNGLTEXCOORD4IVPROC glad_glTexCoord4iv = NULL;
+PFNGLTEXCOORD4SPROC glad_glTexCoord4s = NULL;
+PFNGLTEXCOORD4SVPROC glad_glTexCoord4sv = NULL;
+PFNGLTEXCOORDP1UIPROC glad_glTexCoordP1ui = NULL;
+PFNGLTEXCOORDP1UIVPROC glad_glTexCoordP1uiv = NULL;
+PFNGLTEXCOORDP2UIPROC glad_glTexCoordP2ui = NULL;
+PFNGLTEXCOORDP2UIVPROC glad_glTexCoordP2uiv = NULL;
+PFNGLTEXCOORDP3UIPROC glad_glTexCoordP3ui = NULL;
+PFNGLTEXCOORDP3UIVPROC glad_glTexCoordP3uiv = NULL;
+PFNGLTEXCOORDP4UIPROC glad_glTexCoordP4ui = NULL;
+PFNGLTEXCOORDP4UIVPROC glad_glTexCoordP4uiv = NULL;
+PFNGLTEXCOORDPOINTERPROC glad_glTexCoordPointer = NULL;
+PFNGLTEXENVFPROC glad_glTexEnvf = NULL;
+PFNGLTEXENVFVPROC glad_glTexEnvfv = NULL;
+PFNGLTEXENVIPROC glad_glTexEnvi = NULL;
+PFNGLTEXENVIVPROC glad_glTexEnviv = NULL;
+PFNGLTEXGENDPROC glad_glTexGend = NULL;
+PFNGLTEXGENDVPROC glad_glTexGendv = NULL;
+PFNGLTEXGENFPROC glad_glTexGenf = NULL;
+PFNGLTEXGENFVPROC glad_glTexGenfv = NULL;
+PFNGLTEXGENIPROC glad_glTexGeni = NULL;
+PFNGLTEXGENIVPROC glad_glTexGeniv = NULL;
+PFNGLTEXIMAGE1DPROC glad_glTexImage1D = NULL;
+PFNGLTEXIMAGE2DPROC glad_glTexImage2D = NULL;
+PFNGLTEXIMAGE2DMULTISAMPLEPROC glad_glTexImage2DMultisample = NULL;
+PFNGLTEXIMAGE3DPROC glad_glTexImage3D = NULL;
+PFNGLTEXIMAGE3DMULTISAMPLEPROC glad_glTexImage3DMultisample = NULL;
+PFNGLTEXPARAMETERIIVPROC glad_glTexParameterIiv = NULL;
+PFNGLTEXPARAMETERIUIVPROC glad_glTexParameterIuiv = NULL;
+PFNGLTEXPARAMETERFPROC glad_glTexParameterf = NULL;
+PFNGLTEXPARAMETERFVPROC glad_glTexParameterfv = NULL;
+PFNGLTEXPARAMETERIPROC glad_glTexParameteri = NULL;
+PFNGLTEXPARAMETERIVPROC glad_glTexParameteriv = NULL;
+PFNGLTEXSUBIMAGE1DPROC glad_glTexSubImage1D = NULL;
+PFNGLTEXSUBIMAGE2DPROC glad_glTexSubImage2D = NULL;
+PFNGLTEXSUBIMAGE3DPROC glad_glTexSubImage3D = NULL;
+PFNGLTRANSFORMFEEDBACKVARYINGSPROC glad_glTransformFeedbackVaryings = NULL;
+PFNGLTRANSLATEDPROC glad_glTranslated = NULL;
+PFNGLTRANSLATEFPROC glad_glTranslatef = NULL;
+PFNGLUNIFORM1FPROC glad_glUniform1f = NULL;
+PFNGLUNIFORM1FVPROC glad_glUniform1fv = NULL;
+PFNGLUNIFORM1IPROC glad_glUniform1i = NULL;
+PFNGLUNIFORM1IVPROC glad_glUniform1iv = NULL;
+PFNGLUNIFORM1UIPROC glad_glUniform1ui = NULL;
+PFNGLUNIFORM1UIVPROC glad_glUniform1uiv = NULL;
+PFNGLUNIFORM2FPROC glad_glUniform2f = NULL;
+PFNGLUNIFORM2FVPROC glad_glUniform2fv = NULL;
+PFNGLUNIFORM2IPROC glad_glUniform2i = NULL;
+PFNGLUNIFORM2IVPROC glad_glUniform2iv = NULL;
+PFNGLUNIFORM2UIPROC glad_glUniform2ui = NULL;
+PFNGLUNIFORM2UIVPROC glad_glUniform2uiv = NULL;
+PFNGLUNIFORM3FPROC glad_glUniform3f = NULL;
+PFNGLUNIFORM3FVPROC glad_glUniform3fv = NULL;
+PFNGLUNIFORM3IPROC glad_glUniform3i = NULL;
+PFNGLUNIFORM3IVPROC glad_glUniform3iv = NULL;
+PFNGLUNIFORM3UIPROC glad_glUniform3ui = NULL;
+PFNGLUNIFORM3UIVPROC glad_glUniform3uiv = NULL;
+PFNGLUNIFORM4FPROC glad_glUniform4f = NULL;
+PFNGLUNIFORM4FVPROC glad_glUniform4fv = NULL;
+PFNGLUNIFORM4IPROC glad_glUniform4i = NULL;
+PFNGLUNIFORM4IVPROC glad_glUniform4iv = NULL;
+PFNGLUNIFORM4UIPROC glad_glUniform4ui = NULL;
+PFNGLUNIFORM4UIVPROC glad_glUniform4uiv = NULL;
+PFNGLUNIFORMBLOCKBINDINGPROC glad_glUniformBlockBinding = NULL;
+PFNGLUNIFORMMATRIX2FVPROC glad_glUniformMatrix2fv = NULL;
+PFNGLUNIFORMMATRIX2X3FVPROC glad_glUniformMatrix2x3fv = NULL;
+PFNGLUNIFORMMATRIX2X4FVPROC glad_glUniformMatrix2x4fv = NULL;
+PFNGLUNIFORMMATRIX3FVPROC glad_glUniformMatrix3fv = NULL;
+PFNGLUNIFORMMATRIX3X2FVPROC glad_glUniformMatrix3x2fv = NULL;
+PFNGLUNIFORMMATRIX3X4FVPROC glad_glUniformMatrix3x4fv = NULL;
+PFNGLUNIFORMMATRIX4FVPROC glad_glUniformMatrix4fv = NULL;
+PFNGLUNIFORMMATRIX4X2FVPROC glad_glUniformMatrix4x2fv = NULL;
+PFNGLUNIFORMMATRIX4X3FVPROC glad_glUniformMatrix4x3fv = NULL;
+PFNGLUNMAPBUFFERPROC glad_glUnmapBuffer = NULL;
+PFNGLUSEPROGRAMPROC glad_glUseProgram = NULL;
+PFNGLVALIDATEPROGRAMPROC glad_glValidateProgram = NULL;
+PFNGLVERTEX2DPROC glad_glVertex2d = NULL;
+PFNGLVERTEX2DVPROC glad_glVertex2dv = NULL;
+PFNGLVERTEX2FPROC glad_glVertex2f = NULL;
+PFNGLVERTEX2FVPROC glad_glVertex2fv = NULL;
+PFNGLVERTEX2IPROC glad_glVertex2i = NULL;
+PFNGLVERTEX2IVPROC glad_glVertex2iv = NULL;
+PFNGLVERTEX2SPROC glad_glVertex2s = NULL;
+PFNGLVERTEX2SVPROC glad_glVertex2sv = NULL;
+PFNGLVERTEX3DPROC glad_glVertex3d = NULL;
+PFNGLVERTEX3DVPROC glad_glVertex3dv = NULL;
+PFNGLVERTEX3FPROC glad_glVertex3f = NULL;
+PFNGLVERTEX3FVPROC glad_glVertex3fv = NULL;
+PFNGLVERTEX3IPROC glad_glVertex3i = NULL;
+PFNGLVERTEX3IVPROC glad_glVertex3iv = NULL;
+PFNGLVERTEX3SPROC glad_glVertex3s = NULL;
+PFNGLVERTEX3SVPROC glad_glVertex3sv = NULL;
+PFNGLVERTEX4DPROC glad_glVertex4d = NULL;
+PFNGLVERTEX4DVPROC glad_glVertex4dv = NULL;
+PFNGLVERTEX4FPROC glad_glVertex4f = NULL;
+PFNGLVERTEX4FVPROC glad_glVertex4fv = NULL;
+PFNGLVERTEX4IPROC glad_glVertex4i = NULL;
+PFNGLVERTEX4IVPROC glad_glVertex4iv = NULL;
+PFNGLVERTEX4SPROC glad_glVertex4s = NULL;
+PFNGLVERTEX4SVPROC glad_glVertex4sv = NULL;
+PFNGLVERTEXATTRIB1DPROC glad_glVertexAttrib1d = NULL;
+PFNGLVERTEXATTRIB1DVPROC glad_glVertexAttrib1dv = NULL;
+PFNGLVERTEXATTRIB1FPROC glad_glVertexAttrib1f = NULL;
+PFNGLVERTEXATTRIB1FVPROC glad_glVertexAttrib1fv = NULL;
+PFNGLVERTEXATTRIB1SPROC glad_glVertexAttrib1s = NULL;
+PFNGLVERTEXATTRIB1SVPROC glad_glVertexAttrib1sv = NULL;
+PFNGLVERTEXATTRIB2DPROC glad_glVertexAttrib2d = NULL;
+PFNGLVERTEXATTRIB2DVPROC glad_glVertexAttrib2dv = NULL;
+PFNGLVERTEXATTRIB2FPROC glad_glVertexAttrib2f = NULL;
+PFNGLVERTEXATTRIB2FVPROC glad_glVertexAttrib2fv = NULL;
+PFNGLVERTEXATTRIB2SPROC glad_glVertexAttrib2s = NULL;
+PFNGLVERTEXATTRIB2SVPROC glad_glVertexAttrib2sv = NULL;
+PFNGLVERTEXATTRIB3DPROC glad_glVertexAttrib3d = NULL;
+PFNGLVERTEXATTRIB3DVPROC glad_glVertexAttrib3dv = NULL;
+PFNGLVERTEXATTRIB3FPROC glad_glVertexAttrib3f = NULL;
+PFNGLVERTEXATTRIB3FVPROC glad_glVertexAttrib3fv = NULL;
+PFNGLVERTEXATTRIB3SPROC glad_glVertexAttrib3s = NULL;
+PFNGLVERTEXATTRIB3SVPROC glad_glVertexAttrib3sv = NULL;
+PFNGLVERTEXATTRIB4NBVPROC glad_glVertexAttrib4Nbv = NULL;
+PFNGLVERTEXATTRIB4NIVPROC glad_glVertexAttrib4Niv = NULL;
+PFNGLVERTEXATTRIB4NSVPROC glad_glVertexAttrib4Nsv = NULL;
+PFNGLVERTEXATTRIB4NUBPROC glad_glVertexAttrib4Nub = NULL;
+PFNGLVERTEXATTRIB4NUBVPROC glad_glVertexAttrib4Nubv = NULL;
+PFNGLVERTEXATTRIB4NUIVPROC glad_glVertexAttrib4Nuiv = NULL;
+PFNGLVERTEXATTRIB4NUSVPROC glad_glVertexAttrib4Nusv = NULL;
+PFNGLVERTEXATTRIB4BVPROC glad_glVertexAttrib4bv = NULL;
+PFNGLVERTEXATTRIB4DPROC glad_glVertexAttrib4d = NULL;
+PFNGLVERTEXATTRIB4DVPROC glad_glVertexAttrib4dv = NULL;
+PFNGLVERTEXATTRIB4FPROC glad_glVertexAttrib4f = NULL;
+PFNGLVERTEXATTRIB4FVPROC glad_glVertexAttrib4fv = NULL;
+PFNGLVERTEXATTRIB4IVPROC glad_glVertexAttrib4iv = NULL;
+PFNGLVERTEXATTRIB4SPROC glad_glVertexAttrib4s = NULL;
+PFNGLVERTEXATTRIB4SVPROC glad_glVertexAttrib4sv = NULL;
+PFNGLVERTEXATTRIB4UBVPROC glad_glVertexAttrib4ubv = NULL;
+PFNGLVERTEXATTRIB4UIVPROC glad_glVertexAttrib4uiv = NULL;
+PFNGLVERTEXATTRIB4USVPROC glad_glVertexAttrib4usv = NULL;
+PFNGLVERTEXATTRIBDIVISORPROC glad_glVertexAttribDivisor = NULL;
+PFNGLVERTEXATTRIBI1IPROC glad_glVertexAttribI1i = NULL;
+PFNGLVERTEXATTRIBI1IVPROC glad_glVertexAttribI1iv = NULL;
+PFNGLVERTEXATTRIBI1UIPROC glad_glVertexAttribI1ui = NULL;
+PFNGLVERTEXATTRIBI1UIVPROC glad_glVertexAttribI1uiv = NULL;
+PFNGLVERTEXATTRIBI2IPROC glad_glVertexAttribI2i = NULL;
+PFNGLVERTEXATTRIBI2IVPROC glad_glVertexAttribI2iv = NULL;
+PFNGLVERTEXATTRIBI2UIPROC glad_glVertexAttribI2ui = NULL;
+PFNGLVERTEXATTRIBI2UIVPROC glad_glVertexAttribI2uiv = NULL;
+PFNGLVERTEXATTRIBI3IPROC glad_glVertexAttribI3i = NULL;
+PFNGLVERTEXATTRIBI3IVPROC glad_glVertexAttribI3iv = NULL;
+PFNGLVERTEXATTRIBI3UIPROC glad_glVertexAttribI3ui = NULL;
+PFNGLVERTEXATTRIBI3UIVPROC glad_glVertexAttribI3uiv = NULL;
+PFNGLVERTEXATTRIBI4BVPROC glad_glVertexAttribI4bv = NULL;
+PFNGLVERTEXATTRIBI4IPROC glad_glVertexAttribI4i = NULL;
+PFNGLVERTEXATTRIBI4IVPROC glad_glVertexAttribI4iv = NULL;
+PFNGLVERTEXATTRIBI4SVPROC glad_glVertexAttribI4sv = NULL;
+PFNGLVERTEXATTRIBI4UBVPROC glad_glVertexAttribI4ubv = NULL;
+PFNGLVERTEXATTRIBI4UIPROC glad_glVertexAttribI4ui = NULL;
+PFNGLVERTEXATTRIBI4UIVPROC glad_glVertexAttribI4uiv = NULL;
+PFNGLVERTEXATTRIBI4USVPROC glad_glVertexAttribI4usv = NULL;
+PFNGLVERTEXATTRIBIPOINTERPROC glad_glVertexAttribIPointer = NULL;
+PFNGLVERTEXATTRIBP1UIPROC glad_glVertexAttribP1ui = NULL;
+PFNGLVERTEXATTRIBP1UIVPROC glad_glVertexAttribP1uiv = NULL;
+PFNGLVERTEXATTRIBP2UIPROC glad_glVertexAttribP2ui = NULL;
+PFNGLVERTEXATTRIBP2UIVPROC glad_glVertexAttribP2uiv = NULL;
+PFNGLVERTEXATTRIBP3UIPROC glad_glVertexAttribP3ui = NULL;
+PFNGLVERTEXATTRIBP3UIVPROC glad_glVertexAttribP3uiv = NULL;
+PFNGLVERTEXATTRIBP4UIPROC glad_glVertexAttribP4ui = NULL;
+PFNGLVERTEXATTRIBP4UIVPROC glad_glVertexAttribP4uiv = NULL;
+PFNGLVERTEXATTRIBPOINTERPROC glad_glVertexAttribPointer = NULL;
+PFNGLVERTEXP2UIPROC glad_glVertexP2ui = NULL;
+PFNGLVERTEXP2UIVPROC glad_glVertexP2uiv = NULL;
+PFNGLVERTEXP3UIPROC glad_glVertexP3ui = NULL;
+PFNGLVERTEXP3UIVPROC glad_glVertexP3uiv = NULL;
+PFNGLVERTEXP4UIPROC glad_glVertexP4ui = NULL;
+PFNGLVERTEXP4UIVPROC glad_glVertexP4uiv = NULL;
+PFNGLVERTEXPOINTERPROC glad_glVertexPointer = NULL;
+PFNGLVIEWPORTPROC glad_glViewport = NULL;
+PFNGLWAITSYNCPROC glad_glWaitSync = NULL;
+PFNGLWINDOWPOS2DPROC glad_glWindowPos2d = NULL;
+PFNGLWINDOWPOS2DVPROC glad_glWindowPos2dv = NULL;
+PFNGLWINDOWPOS2FPROC glad_glWindowPos2f = NULL;
+PFNGLWINDOWPOS2FVPROC glad_glWindowPos2fv = NULL;
+PFNGLWINDOWPOS2IPROC glad_glWindowPos2i = NULL;
+PFNGLWINDOWPOS2IVPROC glad_glWindowPos2iv = NULL;
+PFNGLWINDOWPOS2SPROC glad_glWindowPos2s = NULL;
+PFNGLWINDOWPOS2SVPROC glad_glWindowPos2sv = NULL;
+PFNGLWINDOWPOS3DPROC glad_glWindowPos3d = NULL;
+PFNGLWINDOWPOS3DVPROC glad_glWindowPos3dv = NULL;
+PFNGLWINDOWPOS3FPROC glad_glWindowPos3f = NULL;
+PFNGLWINDOWPOS3FVPROC glad_glWindowPos3fv = NULL;
+PFNGLWINDOWPOS3IPROC glad_glWindowPos3i = NULL;
+PFNGLWINDOWPOS3IVPROC glad_glWindowPos3iv = NULL;
+PFNGLWINDOWPOS3SPROC glad_glWindowPos3s = NULL;
+PFNGLWINDOWPOS3SVPROC glad_glWindowPos3sv = NULL;
+
+
+static void glad_gl_load_GL_VERSION_1_0( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_VERSION_1_0) return;
+ glad_glAccum = (PFNGLACCUMPROC) load(userptr, "glAccum");
+ glad_glAlphaFunc = (PFNGLALPHAFUNCPROC) load(userptr, "glAlphaFunc");
+ glad_glBegin = (PFNGLBEGINPROC) load(userptr, "glBegin");
+ glad_glBitmap = (PFNGLBITMAPPROC) load(userptr, "glBitmap");
+ glad_glBlendFunc = (PFNGLBLENDFUNCPROC) load(userptr, "glBlendFunc");
+ glad_glCallList = (PFNGLCALLLISTPROC) load(userptr, "glCallList");
+ glad_glCallLists = (PFNGLCALLLISTSPROC) load(userptr, "glCallLists");
+ glad_glClear = (PFNGLCLEARPROC) load(userptr, "glClear");
+ glad_glClearAccum = (PFNGLCLEARACCUMPROC) load(userptr, "glClearAccum");
+ glad_glClearColor = (PFNGLCLEARCOLORPROC) load(userptr, "glClearColor");
+ glad_glClearDepth = (PFNGLCLEARDEPTHPROC) load(userptr, "glClearDepth");
+ glad_glClearIndex = (PFNGLCLEARINDEXPROC) load(userptr, "glClearIndex");
+ glad_glClearStencil = (PFNGLCLEARSTENCILPROC) load(userptr, "glClearStencil");
+ glad_glClipPlane = (PFNGLCLIPPLANEPROC) load(userptr, "glClipPlane");
+ glad_glColor3b = (PFNGLCOLOR3BPROC) load(userptr, "glColor3b");
+ glad_glColor3bv = (PFNGLCOLOR3BVPROC) load(userptr, "glColor3bv");
+ glad_glColor3d = (PFNGLCOLOR3DPROC) load(userptr, "glColor3d");
+ glad_glColor3dv = (PFNGLCOLOR3DVPROC) load(userptr, "glColor3dv");
+ glad_glColor3f = (PFNGLCOLOR3FPROC) load(userptr, "glColor3f");
+ glad_glColor3fv = (PFNGLCOLOR3FVPROC) load(userptr, "glColor3fv");
+ glad_glColor3i = (PFNGLCOLOR3IPROC) load(userptr, "glColor3i");
+ glad_glColor3iv = (PFNGLCOLOR3IVPROC) load(userptr, "glColor3iv");
+ glad_glColor3s = (PFNGLCOLOR3SPROC) load(userptr, "glColor3s");
+ glad_glColor3sv = (PFNGLCOLOR3SVPROC) load(userptr, "glColor3sv");
+ glad_glColor3ub = (PFNGLCOLOR3UBPROC) load(userptr, "glColor3ub");
+ glad_glColor3ubv = (PFNGLCOLOR3UBVPROC) load(userptr, "glColor3ubv");
+ glad_glColor3ui = (PFNGLCOLOR3UIPROC) load(userptr, "glColor3ui");
+ glad_glColor3uiv = (PFNGLCOLOR3UIVPROC) load(userptr, "glColor3uiv");
+ glad_glColor3us = (PFNGLCOLOR3USPROC) load(userptr, "glColor3us");
+ glad_glColor3usv = (PFNGLCOLOR3USVPROC) load(userptr, "glColor3usv");
+ glad_glColor4b = (PFNGLCOLOR4BPROC) load(userptr, "glColor4b");
+ glad_glColor4bv = (PFNGLCOLOR4BVPROC) load(userptr, "glColor4bv");
+ glad_glColor4d = (PFNGLCOLOR4DPROC) load(userptr, "glColor4d");
+ glad_glColor4dv = (PFNGLCOLOR4DVPROC) load(userptr, "glColor4dv");
+ glad_glColor4f = (PFNGLCOLOR4FPROC) load(userptr, "glColor4f");
+ glad_glColor4fv = (PFNGLCOLOR4FVPROC) load(userptr, "glColor4fv");
+ glad_glColor4i = (PFNGLCOLOR4IPROC) load(userptr, "glColor4i");
+ glad_glColor4iv = (PFNGLCOLOR4IVPROC) load(userptr, "glColor4iv");
+ glad_glColor4s = (PFNGLCOLOR4SPROC) load(userptr, "glColor4s");
+ glad_glColor4sv = (PFNGLCOLOR4SVPROC) load(userptr, "glColor4sv");
+ glad_glColor4ub = (PFNGLCOLOR4UBPROC) load(userptr, "glColor4ub");
+ glad_glColor4ubv = (PFNGLCOLOR4UBVPROC) load(userptr, "glColor4ubv");
+ glad_glColor4ui = (PFNGLCOLOR4UIPROC) load(userptr, "glColor4ui");
+ glad_glColor4uiv = (PFNGLCOLOR4UIVPROC) load(userptr, "glColor4uiv");
+ glad_glColor4us = (PFNGLCOLOR4USPROC) load(userptr, "glColor4us");
+ glad_glColor4usv = (PFNGLCOLOR4USVPROC) load(userptr, "glColor4usv");
+ glad_glColorMask = (PFNGLCOLORMASKPROC) load(userptr, "glColorMask");
+ glad_glColorMaterial = (PFNGLCOLORMATERIALPROC) load(userptr, "glColorMaterial");
+ glad_glCopyPixels = (PFNGLCOPYPIXELSPROC) load(userptr, "glCopyPixels");
+ glad_glCullFace = (PFNGLCULLFACEPROC) load(userptr, "glCullFace");
+ glad_glDeleteLists = (PFNGLDELETELISTSPROC) load(userptr, "glDeleteLists");
+ glad_glDepthFunc = (PFNGLDEPTHFUNCPROC) load(userptr, "glDepthFunc");
+ glad_glDepthMask = (PFNGLDEPTHMASKPROC) load(userptr, "glDepthMask");
+ glad_glDepthRange = (PFNGLDEPTHRANGEPROC) load(userptr, "glDepthRange");
+ glad_glDisable = (PFNGLDISABLEPROC) load(userptr, "glDisable");
+ glad_glDrawBuffer = (PFNGLDRAWBUFFERPROC) load(userptr, "glDrawBuffer");
+ glad_glDrawPixels = (PFNGLDRAWPIXELSPROC) load(userptr, "glDrawPixels");
+ glad_glEdgeFlag = (PFNGLEDGEFLAGPROC) load(userptr, "glEdgeFlag");
+ glad_glEdgeFlagv = (PFNGLEDGEFLAGVPROC) load(userptr, "glEdgeFlagv");
+ glad_glEnable = (PFNGLENABLEPROC) load(userptr, "glEnable");
+ glad_glEnd = (PFNGLENDPROC) load(userptr, "glEnd");
+ glad_glEndList = (PFNGLENDLISTPROC) load(userptr, "glEndList");
+ glad_glEvalCoord1d = (PFNGLEVALCOORD1DPROC) load(userptr, "glEvalCoord1d");
+ glad_glEvalCoord1dv = (PFNGLEVALCOORD1DVPROC) load(userptr, "glEvalCoord1dv");
+ glad_glEvalCoord1f = (PFNGLEVALCOORD1FPROC) load(userptr, "glEvalCoord1f");
+ glad_glEvalCoord1fv = (PFNGLEVALCOORD1FVPROC) load(userptr, "glEvalCoord1fv");
+ glad_glEvalCoord2d = (PFNGLEVALCOORD2DPROC) load(userptr, "glEvalCoord2d");
+ glad_glEvalCoord2dv = (PFNGLEVALCOORD2DVPROC) load(userptr, "glEvalCoord2dv");
+ glad_glEvalCoord2f = (PFNGLEVALCOORD2FPROC) load(userptr, "glEvalCoord2f");
+ glad_glEvalCoord2fv = (PFNGLEVALCOORD2FVPROC) load(userptr, "glEvalCoord2fv");
+ glad_glEvalMesh1 = (PFNGLEVALMESH1PROC) load(userptr, "glEvalMesh1");
+ glad_glEvalMesh2 = (PFNGLEVALMESH2PROC) load(userptr, "glEvalMesh2");
+ glad_glEvalPoint1 = (PFNGLEVALPOINT1PROC) load(userptr, "glEvalPoint1");
+ glad_glEvalPoint2 = (PFNGLEVALPOINT2PROC) load(userptr, "glEvalPoint2");
+ glad_glFeedbackBuffer = (PFNGLFEEDBACKBUFFERPROC) load(userptr, "glFeedbackBuffer");
+ glad_glFinish = (PFNGLFINISHPROC) load(userptr, "glFinish");
+ glad_glFlush = (PFNGLFLUSHPROC) load(userptr, "glFlush");
+ glad_glFogf = (PFNGLFOGFPROC) load(userptr, "glFogf");
+ glad_glFogfv = (PFNGLFOGFVPROC) load(userptr, "glFogfv");
+ glad_glFogi = (PFNGLFOGIPROC) load(userptr, "glFogi");
+ glad_glFogiv = (PFNGLFOGIVPROC) load(userptr, "glFogiv");
+ glad_glFrontFace = (PFNGLFRONTFACEPROC) load(userptr, "glFrontFace");
+ glad_glFrustum = (PFNGLFRUSTUMPROC) load(userptr, "glFrustum");
+ glad_glGenLists = (PFNGLGENLISTSPROC) load(userptr, "glGenLists");
+ glad_glGetBooleanv = (PFNGLGETBOOLEANVPROC) load(userptr, "glGetBooleanv");
+ glad_glGetClipPlane = (PFNGLGETCLIPPLANEPROC) load(userptr, "glGetClipPlane");
+ glad_glGetDoublev = (PFNGLGETDOUBLEVPROC) load(userptr, "glGetDoublev");
+ glad_glGetError = (PFNGLGETERRORPROC) load(userptr, "glGetError");
+ glad_glGetFloatv = (PFNGLGETFLOATVPROC) load(userptr, "glGetFloatv");
+ glad_glGetIntegerv = (PFNGLGETINTEGERVPROC) load(userptr, "glGetIntegerv");
+ glad_glGetLightfv = (PFNGLGETLIGHTFVPROC) load(userptr, "glGetLightfv");
+ glad_glGetLightiv = (PFNGLGETLIGHTIVPROC) load(userptr, "glGetLightiv");
+ glad_glGetMapdv = (PFNGLGETMAPDVPROC) load(userptr, "glGetMapdv");
+ glad_glGetMapfv = (PFNGLGETMAPFVPROC) load(userptr, "glGetMapfv");
+ glad_glGetMapiv = (PFNGLGETMAPIVPROC) load(userptr, "glGetMapiv");
+ glad_glGetMaterialfv = (PFNGLGETMATERIALFVPROC) load(userptr, "glGetMaterialfv");
+ glad_glGetMaterialiv = (PFNGLGETMATERIALIVPROC) load(userptr, "glGetMaterialiv");
+ glad_glGetPixelMapfv = (PFNGLGETPIXELMAPFVPROC) load(userptr, "glGetPixelMapfv");
+ glad_glGetPixelMapuiv = (PFNGLGETPIXELMAPUIVPROC) load(userptr, "glGetPixelMapuiv");
+ glad_glGetPixelMapusv = (PFNGLGETPIXELMAPUSVPROC) load(userptr, "glGetPixelMapusv");
+ glad_glGetPolygonStipple = (PFNGLGETPOLYGONSTIPPLEPROC) load(userptr, "glGetPolygonStipple");
+ glad_glGetString = (PFNGLGETSTRINGPROC) load(userptr, "glGetString");
+ glad_glGetTexEnvfv = (PFNGLGETTEXENVFVPROC) load(userptr, "glGetTexEnvfv");
+ glad_glGetTexEnviv = (PFNGLGETTEXENVIVPROC) load(userptr, "glGetTexEnviv");
+ glad_glGetTexGendv = (PFNGLGETTEXGENDVPROC) load(userptr, "glGetTexGendv");
+ glad_glGetTexGenfv = (PFNGLGETTEXGENFVPROC) load(userptr, "glGetTexGenfv");
+ glad_glGetTexGeniv = (PFNGLGETTEXGENIVPROC) load(userptr, "glGetTexGeniv");
+ glad_glGetTexImage = (PFNGLGETTEXIMAGEPROC) load(userptr, "glGetTexImage");
+ glad_glGetTexLevelParameterfv = (PFNGLGETTEXLEVELPARAMETERFVPROC) load(userptr, "glGetTexLevelParameterfv");
+ glad_glGetTexLevelParameteriv = (PFNGLGETTEXLEVELPARAMETERIVPROC) load(userptr, "glGetTexLevelParameteriv");
+ glad_glGetTexParameterfv = (PFNGLGETTEXPARAMETERFVPROC) load(userptr, "glGetTexParameterfv");
+ glad_glGetTexParameteriv = (PFNGLGETTEXPARAMETERIVPROC) load(userptr, "glGetTexParameteriv");
+ glad_glHint = (PFNGLHINTPROC) load(userptr, "glHint");
+ glad_glIndexMask = (PFNGLINDEXMASKPROC) load(userptr, "glIndexMask");
+ glad_glIndexd = (PFNGLINDEXDPROC) load(userptr, "glIndexd");
+ glad_glIndexdv = (PFNGLINDEXDVPROC) load(userptr, "glIndexdv");
+ glad_glIndexf = (PFNGLINDEXFPROC) load(userptr, "glIndexf");
+ glad_glIndexfv = (PFNGLINDEXFVPROC) load(userptr, "glIndexfv");
+ glad_glIndexi = (PFNGLINDEXIPROC) load(userptr, "glIndexi");
+ glad_glIndexiv = (PFNGLINDEXIVPROC) load(userptr, "glIndexiv");
+ glad_glIndexs = (PFNGLINDEXSPROC) load(userptr, "glIndexs");
+ glad_glIndexsv = (PFNGLINDEXSVPROC) load(userptr, "glIndexsv");
+ glad_glInitNames = (PFNGLINITNAMESPROC) load(userptr, "glInitNames");
+ glad_glIsEnabled = (PFNGLISENABLEDPROC) load(userptr, "glIsEnabled");
+ glad_glIsList = (PFNGLISLISTPROC) load(userptr, "glIsList");
+ glad_glLightModelf = (PFNGLLIGHTMODELFPROC) load(userptr, "glLightModelf");
+ glad_glLightModelfv = (PFNGLLIGHTMODELFVPROC) load(userptr, "glLightModelfv");
+ glad_glLightModeli = (PFNGLLIGHTMODELIPROC) load(userptr, "glLightModeli");
+ glad_glLightModeliv = (PFNGLLIGHTMODELIVPROC) load(userptr, "glLightModeliv");
+ glad_glLightf = (PFNGLLIGHTFPROC) load(userptr, "glLightf");
+ glad_glLightfv = (PFNGLLIGHTFVPROC) load(userptr, "glLightfv");
+ glad_glLighti = (PFNGLLIGHTIPROC) load(userptr, "glLighti");
+ glad_glLightiv = (PFNGLLIGHTIVPROC) load(userptr, "glLightiv");
+ glad_glLineStipple = (PFNGLLINESTIPPLEPROC) load(userptr, "glLineStipple");
+ glad_glLineWidth = (PFNGLLINEWIDTHPROC) load(userptr, "glLineWidth");
+ glad_glListBase = (PFNGLLISTBASEPROC) load(userptr, "glListBase");
+ glad_glLoadIdentity = (PFNGLLOADIDENTITYPROC) load(userptr, "glLoadIdentity");
+ glad_glLoadMatrixd = (PFNGLLOADMATRIXDPROC) load(userptr, "glLoadMatrixd");
+ glad_glLoadMatrixf = (PFNGLLOADMATRIXFPROC) load(userptr, "glLoadMatrixf");
+ glad_glLoadName = (PFNGLLOADNAMEPROC) load(userptr, "glLoadName");
+ glad_glLogicOp = (PFNGLLOGICOPPROC) load(userptr, "glLogicOp");
+ glad_glMap1d = (PFNGLMAP1DPROC) load(userptr, "glMap1d");
+ glad_glMap1f = (PFNGLMAP1FPROC) load(userptr, "glMap1f");
+ glad_glMap2d = (PFNGLMAP2DPROC) load(userptr, "glMap2d");
+ glad_glMap2f = (PFNGLMAP2FPROC) load(userptr, "glMap2f");
+ glad_glMapGrid1d = (PFNGLMAPGRID1DPROC) load(userptr, "glMapGrid1d");
+ glad_glMapGrid1f = (PFNGLMAPGRID1FPROC) load(userptr, "glMapGrid1f");
+ glad_glMapGrid2d = (PFNGLMAPGRID2DPROC) load(userptr, "glMapGrid2d");
+ glad_glMapGrid2f = (PFNGLMAPGRID2FPROC) load(userptr, "glMapGrid2f");
+ glad_glMaterialf = (PFNGLMATERIALFPROC) load(userptr, "glMaterialf");
+ glad_glMaterialfv = (PFNGLMATERIALFVPROC) load(userptr, "glMaterialfv");
+ glad_glMateriali = (PFNGLMATERIALIPROC) load(userptr, "glMateriali");
+ glad_glMaterialiv = (PFNGLMATERIALIVPROC) load(userptr, "glMaterialiv");
+ glad_glMatrixMode = (PFNGLMATRIXMODEPROC) load(userptr, "glMatrixMode");
+ glad_glMultMatrixd = (PFNGLMULTMATRIXDPROC) load(userptr, "glMultMatrixd");
+ glad_glMultMatrixf = (PFNGLMULTMATRIXFPROC) load(userptr, "glMultMatrixf");
+ glad_glNewList = (PFNGLNEWLISTPROC) load(userptr, "glNewList");
+ glad_glNormal3b = (PFNGLNORMAL3BPROC) load(userptr, "glNormal3b");
+ glad_glNormal3bv = (PFNGLNORMAL3BVPROC) load(userptr, "glNormal3bv");
+ glad_glNormal3d = (PFNGLNORMAL3DPROC) load(userptr, "glNormal3d");
+ glad_glNormal3dv = (PFNGLNORMAL3DVPROC) load(userptr, "glNormal3dv");
+ glad_glNormal3f = (PFNGLNORMAL3FPROC) load(userptr, "glNormal3f");
+ glad_glNormal3fv = (PFNGLNORMAL3FVPROC) load(userptr, "glNormal3fv");
+ glad_glNormal3i = (PFNGLNORMAL3IPROC) load(userptr, "glNormal3i");
+ glad_glNormal3iv = (PFNGLNORMAL3IVPROC) load(userptr, "glNormal3iv");
+ glad_glNormal3s = (PFNGLNORMAL3SPROC) load(userptr, "glNormal3s");
+ glad_glNormal3sv = (PFNGLNORMAL3SVPROC) load(userptr, "glNormal3sv");
+ glad_glOrtho = (PFNGLORTHOPROC) load(userptr, "glOrtho");
+ glad_glPassThrough = (PFNGLPASSTHROUGHPROC) load(userptr, "glPassThrough");
+ glad_glPixelMapfv = (PFNGLPIXELMAPFVPROC) load(userptr, "glPixelMapfv");
+ glad_glPixelMapuiv = (PFNGLPIXELMAPUIVPROC) load(userptr, "glPixelMapuiv");
+ glad_glPixelMapusv = (PFNGLPIXELMAPUSVPROC) load(userptr, "glPixelMapusv");
+ glad_glPixelStoref = (PFNGLPIXELSTOREFPROC) load(userptr, "glPixelStoref");
+ glad_glPixelStorei = (PFNGLPIXELSTOREIPROC) load(userptr, "glPixelStorei");
+ glad_glPixelTransferf = (PFNGLPIXELTRANSFERFPROC) load(userptr, "glPixelTransferf");
+ glad_glPixelTransferi = (PFNGLPIXELTRANSFERIPROC) load(userptr, "glPixelTransferi");
+ glad_glPixelZoom = (PFNGLPIXELZOOMPROC) load(userptr, "glPixelZoom");
+ glad_glPointSize = (PFNGLPOINTSIZEPROC) load(userptr, "glPointSize");
+ glad_glPolygonMode = (PFNGLPOLYGONMODEPROC) load(userptr, "glPolygonMode");
+ glad_glPolygonStipple = (PFNGLPOLYGONSTIPPLEPROC) load(userptr, "glPolygonStipple");
+ glad_glPopAttrib = (PFNGLPOPATTRIBPROC) load(userptr, "glPopAttrib");
+ glad_glPopMatrix = (PFNGLPOPMATRIXPROC) load(userptr, "glPopMatrix");
+ glad_glPopName = (PFNGLPOPNAMEPROC) load(userptr, "glPopName");
+ glad_glPushAttrib = (PFNGLPUSHATTRIBPROC) load(userptr, "glPushAttrib");
+ glad_glPushMatrix = (PFNGLPUSHMATRIXPROC) load(userptr, "glPushMatrix");
+ glad_glPushName = (PFNGLPUSHNAMEPROC) load(userptr, "glPushName");
+ glad_glRasterPos2d = (PFNGLRASTERPOS2DPROC) load(userptr, "glRasterPos2d");
+ glad_glRasterPos2dv = (PFNGLRASTERPOS2DVPROC) load(userptr, "glRasterPos2dv");
+ glad_glRasterPos2f = (PFNGLRASTERPOS2FPROC) load(userptr, "glRasterPos2f");
+ glad_glRasterPos2fv = (PFNGLRASTERPOS2FVPROC) load(userptr, "glRasterPos2fv");
+ glad_glRasterPos2i = (PFNGLRASTERPOS2IPROC) load(userptr, "glRasterPos2i");
+ glad_glRasterPos2iv = (PFNGLRASTERPOS2IVPROC) load(userptr, "glRasterPos2iv");
+ glad_glRasterPos2s = (PFNGLRASTERPOS2SPROC) load(userptr, "glRasterPos2s");
+ glad_glRasterPos2sv = (PFNGLRASTERPOS2SVPROC) load(userptr, "glRasterPos2sv");
+ glad_glRasterPos3d = (PFNGLRASTERPOS3DPROC) load(userptr, "glRasterPos3d");
+ glad_glRasterPos3dv = (PFNGLRASTERPOS3DVPROC) load(userptr, "glRasterPos3dv");
+ glad_glRasterPos3f = (PFNGLRASTERPOS3FPROC) load(userptr, "glRasterPos3f");
+ glad_glRasterPos3fv = (PFNGLRASTERPOS3FVPROC) load(userptr, "glRasterPos3fv");
+ glad_glRasterPos3i = (PFNGLRASTERPOS3IPROC) load(userptr, "glRasterPos3i");
+ glad_glRasterPos3iv = (PFNGLRASTERPOS3IVPROC) load(userptr, "glRasterPos3iv");
+ glad_glRasterPos3s = (PFNGLRASTERPOS3SPROC) load(userptr, "glRasterPos3s");
+ glad_glRasterPos3sv = (PFNGLRASTERPOS3SVPROC) load(userptr, "glRasterPos3sv");
+ glad_glRasterPos4d = (PFNGLRASTERPOS4DPROC) load(userptr, "glRasterPos4d");
+ glad_glRasterPos4dv = (PFNGLRASTERPOS4DVPROC) load(userptr, "glRasterPos4dv");
+ glad_glRasterPos4f = (PFNGLRASTERPOS4FPROC) load(userptr, "glRasterPos4f");
+ glad_glRasterPos4fv = (PFNGLRASTERPOS4FVPROC) load(userptr, "glRasterPos4fv");
+ glad_glRasterPos4i = (PFNGLRASTERPOS4IPROC) load(userptr, "glRasterPos4i");
+ glad_glRasterPos4iv = (PFNGLRASTERPOS4IVPROC) load(userptr, "glRasterPos4iv");
+ glad_glRasterPos4s = (PFNGLRASTERPOS4SPROC) load(userptr, "glRasterPos4s");
+ glad_glRasterPos4sv = (PFNGLRASTERPOS4SVPROC) load(userptr, "glRasterPos4sv");
+ glad_glReadBuffer = (PFNGLREADBUFFERPROC) load(userptr, "glReadBuffer");
+ glad_glReadPixels = (PFNGLREADPIXELSPROC) load(userptr, "glReadPixels");
+ glad_glRectd = (PFNGLRECTDPROC) load(userptr, "glRectd");
+ glad_glRectdv = (PFNGLRECTDVPROC) load(userptr, "glRectdv");
+ glad_glRectf = (PFNGLRECTFPROC) load(userptr, "glRectf");
+ glad_glRectfv = (PFNGLRECTFVPROC) load(userptr, "glRectfv");
+ glad_glRecti = (PFNGLRECTIPROC) load(userptr, "glRecti");
+ glad_glRectiv = (PFNGLRECTIVPROC) load(userptr, "glRectiv");
+ glad_glRects = (PFNGLRECTSPROC) load(userptr, "glRects");
+ glad_glRectsv = (PFNGLRECTSVPROC) load(userptr, "glRectsv");
+ glad_glRenderMode = (PFNGLRENDERMODEPROC) load(userptr, "glRenderMode");
+ glad_glRotated = (PFNGLROTATEDPROC) load(userptr, "glRotated");
+ glad_glRotatef = (PFNGLROTATEFPROC) load(userptr, "glRotatef");
+ glad_glScaled = (PFNGLSCALEDPROC) load(userptr, "glScaled");
+ glad_glScalef = (PFNGLSCALEFPROC) load(userptr, "glScalef");
+ glad_glScissor = (PFNGLSCISSORPROC) load(userptr, "glScissor");
+ glad_glSelectBuffer = (PFNGLSELECTBUFFERPROC) load(userptr, "glSelectBuffer");
+ glad_glShadeModel = (PFNGLSHADEMODELPROC) load(userptr, "glShadeModel");
+ glad_glStencilFunc = (PFNGLSTENCILFUNCPROC) load(userptr, "glStencilFunc");
+ glad_glStencilMask = (PFNGLSTENCILMASKPROC) load(userptr, "glStencilMask");
+ glad_glStencilOp = (PFNGLSTENCILOPPROC) load(userptr, "glStencilOp");
+ glad_glTexCoord1d = (PFNGLTEXCOORD1DPROC) load(userptr, "glTexCoord1d");
+ glad_glTexCoord1dv = (PFNGLTEXCOORD1DVPROC) load(userptr, "glTexCoord1dv");
+ glad_glTexCoord1f = (PFNGLTEXCOORD1FPROC) load(userptr, "glTexCoord1f");
+ glad_glTexCoord1fv = (PFNGLTEXCOORD1FVPROC) load(userptr, "glTexCoord1fv");
+ glad_glTexCoord1i = (PFNGLTEXCOORD1IPROC) load(userptr, "glTexCoord1i");
+ glad_glTexCoord1iv = (PFNGLTEXCOORD1IVPROC) load(userptr, "glTexCoord1iv");
+ glad_glTexCoord1s = (PFNGLTEXCOORD1SPROC) load(userptr, "glTexCoord1s");
+ glad_glTexCoord1sv = (PFNGLTEXCOORD1SVPROC) load(userptr, "glTexCoord1sv");
+ glad_glTexCoord2d = (PFNGLTEXCOORD2DPROC) load(userptr, "glTexCoord2d");
+ glad_glTexCoord2dv = (PFNGLTEXCOORD2DVPROC) load(userptr, "glTexCoord2dv");
+ glad_glTexCoord2f = (PFNGLTEXCOORD2FPROC) load(userptr, "glTexCoord2f");
+ glad_glTexCoord2fv = (PFNGLTEXCOORD2FVPROC) load(userptr, "glTexCoord2fv");
+ glad_glTexCoord2i = (PFNGLTEXCOORD2IPROC) load(userptr, "glTexCoord2i");
+ glad_glTexCoord2iv = (PFNGLTEXCOORD2IVPROC) load(userptr, "glTexCoord2iv");
+ glad_glTexCoord2s = (PFNGLTEXCOORD2SPROC) load(userptr, "glTexCoord2s");
+ glad_glTexCoord2sv = (PFNGLTEXCOORD2SVPROC) load(userptr, "glTexCoord2sv");
+ glad_glTexCoord3d = (PFNGLTEXCOORD3DPROC) load(userptr, "glTexCoord3d");
+ glad_glTexCoord3dv = (PFNGLTEXCOORD3DVPROC) load(userptr, "glTexCoord3dv");
+ glad_glTexCoord3f = (PFNGLTEXCOORD3FPROC) load(userptr, "glTexCoord3f");
+ glad_glTexCoord3fv = (PFNGLTEXCOORD3FVPROC) load(userptr, "glTexCoord3fv");
+ glad_glTexCoord3i = (PFNGLTEXCOORD3IPROC) load(userptr, "glTexCoord3i");
+ glad_glTexCoord3iv = (PFNGLTEXCOORD3IVPROC) load(userptr, "glTexCoord3iv");
+ glad_glTexCoord3s = (PFNGLTEXCOORD3SPROC) load(userptr, "glTexCoord3s");
+ glad_glTexCoord3sv = (PFNGLTEXCOORD3SVPROC) load(userptr, "glTexCoord3sv");
+ glad_glTexCoord4d = (PFNGLTEXCOORD4DPROC) load(userptr, "glTexCoord4d");
+ glad_glTexCoord4dv = (PFNGLTEXCOORD4DVPROC) load(userptr, "glTexCoord4dv");
+ glad_glTexCoord4f = (PFNGLTEXCOORD4FPROC) load(userptr, "glTexCoord4f");
+ glad_glTexCoord4fv = (PFNGLTEXCOORD4FVPROC) load(userptr, "glTexCoord4fv");
+ glad_glTexCoord4i = (PFNGLTEXCOORD4IPROC) load(userptr, "glTexCoord4i");
+ glad_glTexCoord4iv = (PFNGLTEXCOORD4IVPROC) load(userptr, "glTexCoord4iv");
+ glad_glTexCoord4s = (PFNGLTEXCOORD4SPROC) load(userptr, "glTexCoord4s");
+ glad_glTexCoord4sv = (PFNGLTEXCOORD4SVPROC) load(userptr, "glTexCoord4sv");
+ glad_glTexEnvf = (PFNGLTEXENVFPROC) load(userptr, "glTexEnvf");
+ glad_glTexEnvfv = (PFNGLTEXENVFVPROC) load(userptr, "glTexEnvfv");
+ glad_glTexEnvi = (PFNGLTEXENVIPROC) load(userptr, "glTexEnvi");
+ glad_glTexEnviv = (PFNGLTEXENVIVPROC) load(userptr, "glTexEnviv");
+ glad_glTexGend = (PFNGLTEXGENDPROC) load(userptr, "glTexGend");
+ glad_glTexGendv = (PFNGLTEXGENDVPROC) load(userptr, "glTexGendv");
+ glad_glTexGenf = (PFNGLTEXGENFPROC) load(userptr, "glTexGenf");
+ glad_glTexGenfv = (PFNGLTEXGENFVPROC) load(userptr, "glTexGenfv");
+ glad_glTexGeni = (PFNGLTEXGENIPROC) load(userptr, "glTexGeni");
+ glad_glTexGeniv = (PFNGLTEXGENIVPROC) load(userptr, "glTexGeniv");
+ glad_glTexImage1D = (PFNGLTEXIMAGE1DPROC) load(userptr, "glTexImage1D");
+ glad_glTexImage2D = (PFNGLTEXIMAGE2DPROC) load(userptr, "glTexImage2D");
+ glad_glTexParameterf = (PFNGLTEXPARAMETERFPROC) load(userptr, "glTexParameterf");
+ glad_glTexParameterfv = (PFNGLTEXPARAMETERFVPROC) load(userptr, "glTexParameterfv");
+ glad_glTexParameteri = (PFNGLTEXPARAMETERIPROC) load(userptr, "glTexParameteri");
+ glad_glTexParameteriv = (PFNGLTEXPARAMETERIVPROC) load(userptr, "glTexParameteriv");
+ glad_glTranslated = (PFNGLTRANSLATEDPROC) load(userptr, "glTranslated");
+ glad_glTranslatef = (PFNGLTRANSLATEFPROC) load(userptr, "glTranslatef");
+ glad_glVertex2d = (PFNGLVERTEX2DPROC) load(userptr, "glVertex2d");
+ glad_glVertex2dv = (PFNGLVERTEX2DVPROC) load(userptr, "glVertex2dv");
+ glad_glVertex2f = (PFNGLVERTEX2FPROC) load(userptr, "glVertex2f");
+ glad_glVertex2fv = (PFNGLVERTEX2FVPROC) load(userptr, "glVertex2fv");
+ glad_glVertex2i = (PFNGLVERTEX2IPROC) load(userptr, "glVertex2i");
+ glad_glVertex2iv = (PFNGLVERTEX2IVPROC) load(userptr, "glVertex2iv");
+ glad_glVertex2s = (PFNGLVERTEX2SPROC) load(userptr, "glVertex2s");
+ glad_glVertex2sv = (PFNGLVERTEX2SVPROC) load(userptr, "glVertex2sv");
+ glad_glVertex3d = (PFNGLVERTEX3DPROC) load(userptr, "glVertex3d");
+ glad_glVertex3dv = (PFNGLVERTEX3DVPROC) load(userptr, "glVertex3dv");
+ glad_glVertex3f = (PFNGLVERTEX3FPROC) load(userptr, "glVertex3f");
+ glad_glVertex3fv = (PFNGLVERTEX3FVPROC) load(userptr, "glVertex3fv");
+ glad_glVertex3i = (PFNGLVERTEX3IPROC) load(userptr, "glVertex3i");
+ glad_glVertex3iv = (PFNGLVERTEX3IVPROC) load(userptr, "glVertex3iv");
+ glad_glVertex3s = (PFNGLVERTEX3SPROC) load(userptr, "glVertex3s");
+ glad_glVertex3sv = (PFNGLVERTEX3SVPROC) load(userptr, "glVertex3sv");
+ glad_glVertex4d = (PFNGLVERTEX4DPROC) load(userptr, "glVertex4d");
+ glad_glVertex4dv = (PFNGLVERTEX4DVPROC) load(userptr, "glVertex4dv");
+ glad_glVertex4f = (PFNGLVERTEX4FPROC) load(userptr, "glVertex4f");
+ glad_glVertex4fv = (PFNGLVERTEX4FVPROC) load(userptr, "glVertex4fv");
+ glad_glVertex4i = (PFNGLVERTEX4IPROC) load(userptr, "glVertex4i");
+ glad_glVertex4iv = (PFNGLVERTEX4IVPROC) load(userptr, "glVertex4iv");
+ glad_glVertex4s = (PFNGLVERTEX4SPROC) load(userptr, "glVertex4s");
+ glad_glVertex4sv = (PFNGLVERTEX4SVPROC) load(userptr, "glVertex4sv");
+ glad_glViewport = (PFNGLVIEWPORTPROC) load(userptr, "glViewport");
+}
+static void glad_gl_load_GL_VERSION_1_1( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_VERSION_1_1) return;
+ glad_glAreTexturesResident = (PFNGLARETEXTURESRESIDENTPROC) load(userptr, "glAreTexturesResident");
+ glad_glArrayElement = (PFNGLARRAYELEMENTPROC) load(userptr, "glArrayElement");
+ glad_glBindTexture = (PFNGLBINDTEXTUREPROC) load(userptr, "glBindTexture");
+ glad_glColorPointer = (PFNGLCOLORPOINTERPROC) load(userptr, "glColorPointer");
+ glad_glCopyTexImage1D = (PFNGLCOPYTEXIMAGE1DPROC) load(userptr, "glCopyTexImage1D");
+ glad_glCopyTexImage2D = (PFNGLCOPYTEXIMAGE2DPROC) load(userptr, "glCopyTexImage2D");
+ glad_glCopyTexSubImage1D = (PFNGLCOPYTEXSUBIMAGE1DPROC) load(userptr, "glCopyTexSubImage1D");
+ glad_glCopyTexSubImage2D = (PFNGLCOPYTEXSUBIMAGE2DPROC) load(userptr, "glCopyTexSubImage2D");
+ glad_glDeleteTextures = (PFNGLDELETETEXTURESPROC) load(userptr, "glDeleteTextures");
+ glad_glDisableClientState = (PFNGLDISABLECLIENTSTATEPROC) load(userptr, "glDisableClientState");
+ glad_glDrawArrays = (PFNGLDRAWARRAYSPROC) load(userptr, "glDrawArrays");
+ glad_glDrawElements = (PFNGLDRAWELEMENTSPROC) load(userptr, "glDrawElements");
+ glad_glEdgeFlagPointer = (PFNGLEDGEFLAGPOINTERPROC) load(userptr, "glEdgeFlagPointer");
+ glad_glEnableClientState = (PFNGLENABLECLIENTSTATEPROC) load(userptr, "glEnableClientState");
+ glad_glGenTextures = (PFNGLGENTEXTURESPROC) load(userptr, "glGenTextures");
+ glad_glGetPointerv = (PFNGLGETPOINTERVPROC) load(userptr, "glGetPointerv");
+ glad_glIndexPointer = (PFNGLINDEXPOINTERPROC) load(userptr, "glIndexPointer");
+ glad_glIndexub = (PFNGLINDEXUBPROC) load(userptr, "glIndexub");
+ glad_glIndexubv = (PFNGLINDEXUBVPROC) load(userptr, "glIndexubv");
+ glad_glInterleavedArrays = (PFNGLINTERLEAVEDARRAYSPROC) load(userptr, "glInterleavedArrays");
+ glad_glIsTexture = (PFNGLISTEXTUREPROC) load(userptr, "glIsTexture");
+ glad_glNormalPointer = (PFNGLNORMALPOINTERPROC) load(userptr, "glNormalPointer");
+ glad_glPolygonOffset = (PFNGLPOLYGONOFFSETPROC) load(userptr, "glPolygonOffset");
+ glad_glPopClientAttrib = (PFNGLPOPCLIENTATTRIBPROC) load(userptr, "glPopClientAttrib");
+ glad_glPrioritizeTextures = (PFNGLPRIORITIZETEXTURESPROC) load(userptr, "glPrioritizeTextures");
+ glad_glPushClientAttrib = (PFNGLPUSHCLIENTATTRIBPROC) load(userptr, "glPushClientAttrib");
+ glad_glTexCoordPointer = (PFNGLTEXCOORDPOINTERPROC) load(userptr, "glTexCoordPointer");
+ glad_glTexSubImage1D = (PFNGLTEXSUBIMAGE1DPROC) load(userptr, "glTexSubImage1D");
+ glad_glTexSubImage2D = (PFNGLTEXSUBIMAGE2DPROC) load(userptr, "glTexSubImage2D");
+ glad_glVertexPointer = (PFNGLVERTEXPOINTERPROC) load(userptr, "glVertexPointer");
+}
+static void glad_gl_load_GL_VERSION_1_2( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_VERSION_1_2) return;
+ glad_glCopyTexSubImage3D = (PFNGLCOPYTEXSUBIMAGE3DPROC) load(userptr, "glCopyTexSubImage3D");
+ glad_glDrawRangeElements = (PFNGLDRAWRANGEELEMENTSPROC) load(userptr, "glDrawRangeElements");
+ glad_glTexImage3D = (PFNGLTEXIMAGE3DPROC) load(userptr, "glTexImage3D");
+ glad_glTexSubImage3D = (PFNGLTEXSUBIMAGE3DPROC) load(userptr, "glTexSubImage3D");
+}
+static void glad_gl_load_GL_VERSION_1_3( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_VERSION_1_3) return;
+ glad_glActiveTexture = (PFNGLACTIVETEXTUREPROC) load(userptr, "glActiveTexture");
+ glad_glClientActiveTexture = (PFNGLCLIENTACTIVETEXTUREPROC) load(userptr, "glClientActiveTexture");
+ glad_glCompressedTexImage1D = (PFNGLCOMPRESSEDTEXIMAGE1DPROC) load(userptr, "glCompressedTexImage1D");
+ glad_glCompressedTexImage2D = (PFNGLCOMPRESSEDTEXIMAGE2DPROC) load(userptr, "glCompressedTexImage2D");
+ glad_glCompressedTexImage3D = (PFNGLCOMPRESSEDTEXIMAGE3DPROC) load(userptr, "glCompressedTexImage3D");
+ glad_glCompressedTexSubImage1D = (PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC) load(userptr, "glCompressedTexSubImage1D");
+ glad_glCompressedTexSubImage2D = (PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC) load(userptr, "glCompressedTexSubImage2D");
+ glad_glCompressedTexSubImage3D = (PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC) load(userptr, "glCompressedTexSubImage3D");
+ glad_glGetCompressedTexImage = (PFNGLGETCOMPRESSEDTEXIMAGEPROC) load(userptr, "glGetCompressedTexImage");
+ glad_glLoadTransposeMatrixd = (PFNGLLOADTRANSPOSEMATRIXDPROC) load(userptr, "glLoadTransposeMatrixd");
+ glad_glLoadTransposeMatrixf = (PFNGLLOADTRANSPOSEMATRIXFPROC) load(userptr, "glLoadTransposeMatrixf");
+ glad_glMultTransposeMatrixd = (PFNGLMULTTRANSPOSEMATRIXDPROC) load(userptr, "glMultTransposeMatrixd");
+ glad_glMultTransposeMatrixf = (PFNGLMULTTRANSPOSEMATRIXFPROC) load(userptr, "glMultTransposeMatrixf");
+ glad_glMultiTexCoord1d = (PFNGLMULTITEXCOORD1DPROC) load(userptr, "glMultiTexCoord1d");
+ glad_glMultiTexCoord1dv = (PFNGLMULTITEXCOORD1DVPROC) load(userptr, "glMultiTexCoord1dv");
+ glad_glMultiTexCoord1f = (PFNGLMULTITEXCOORD1FPROC) load(userptr, "glMultiTexCoord1f");
+ glad_glMultiTexCoord1fv = (PFNGLMULTITEXCOORD1FVPROC) load(userptr, "glMultiTexCoord1fv");
+ glad_glMultiTexCoord1i = (PFNGLMULTITEXCOORD1IPROC) load(userptr, "glMultiTexCoord1i");
+ glad_glMultiTexCoord1iv = (PFNGLMULTITEXCOORD1IVPROC) load(userptr, "glMultiTexCoord1iv");
+ glad_glMultiTexCoord1s = (PFNGLMULTITEXCOORD1SPROC) load(userptr, "glMultiTexCoord1s");
+ glad_glMultiTexCoord1sv = (PFNGLMULTITEXCOORD1SVPROC) load(userptr, "glMultiTexCoord1sv");
+ glad_glMultiTexCoord2d = (PFNGLMULTITEXCOORD2DPROC) load(userptr, "glMultiTexCoord2d");
+ glad_glMultiTexCoord2dv = (PFNGLMULTITEXCOORD2DVPROC) load(userptr, "glMultiTexCoord2dv");
+ glad_glMultiTexCoord2f = (PFNGLMULTITEXCOORD2FPROC) load(userptr, "glMultiTexCoord2f");
+ glad_glMultiTexCoord2fv = (PFNGLMULTITEXCOORD2FVPROC) load(userptr, "glMultiTexCoord2fv");
+ glad_glMultiTexCoord2i = (PFNGLMULTITEXCOORD2IPROC) load(userptr, "glMultiTexCoord2i");
+ glad_glMultiTexCoord2iv = (PFNGLMULTITEXCOORD2IVPROC) load(userptr, "glMultiTexCoord2iv");
+ glad_glMultiTexCoord2s = (PFNGLMULTITEXCOORD2SPROC) load(userptr, "glMultiTexCoord2s");
+ glad_glMultiTexCoord2sv = (PFNGLMULTITEXCOORD2SVPROC) load(userptr, "glMultiTexCoord2sv");
+ glad_glMultiTexCoord3d = (PFNGLMULTITEXCOORD3DPROC) load(userptr, "glMultiTexCoord3d");
+ glad_glMultiTexCoord3dv = (PFNGLMULTITEXCOORD3DVPROC) load(userptr, "glMultiTexCoord3dv");
+ glad_glMultiTexCoord3f = (PFNGLMULTITEXCOORD3FPROC) load(userptr, "glMultiTexCoord3f");
+ glad_glMultiTexCoord3fv = (PFNGLMULTITEXCOORD3FVPROC) load(userptr, "glMultiTexCoord3fv");
+ glad_glMultiTexCoord3i = (PFNGLMULTITEXCOORD3IPROC) load(userptr, "glMultiTexCoord3i");
+ glad_glMultiTexCoord3iv = (PFNGLMULTITEXCOORD3IVPROC) load(userptr, "glMultiTexCoord3iv");
+ glad_glMultiTexCoord3s = (PFNGLMULTITEXCOORD3SPROC) load(userptr, "glMultiTexCoord3s");
+ glad_glMultiTexCoord3sv = (PFNGLMULTITEXCOORD3SVPROC) load(userptr, "glMultiTexCoord3sv");
+ glad_glMultiTexCoord4d = (PFNGLMULTITEXCOORD4DPROC) load(userptr, "glMultiTexCoord4d");
+ glad_glMultiTexCoord4dv = (PFNGLMULTITEXCOORD4DVPROC) load(userptr, "glMultiTexCoord4dv");
+ glad_glMultiTexCoord4f = (PFNGLMULTITEXCOORD4FPROC) load(userptr, "glMultiTexCoord4f");
+ glad_glMultiTexCoord4fv = (PFNGLMULTITEXCOORD4FVPROC) load(userptr, "glMultiTexCoord4fv");
+ glad_glMultiTexCoord4i = (PFNGLMULTITEXCOORD4IPROC) load(userptr, "glMultiTexCoord4i");
+ glad_glMultiTexCoord4iv = (PFNGLMULTITEXCOORD4IVPROC) load(userptr, "glMultiTexCoord4iv");
+ glad_glMultiTexCoord4s = (PFNGLMULTITEXCOORD4SPROC) load(userptr, "glMultiTexCoord4s");
+ glad_glMultiTexCoord4sv = (PFNGLMULTITEXCOORD4SVPROC) load(userptr, "glMultiTexCoord4sv");
+ glad_glSampleCoverage = (PFNGLSAMPLECOVERAGEPROC) load(userptr, "glSampleCoverage");
+}
+static void glad_gl_load_GL_VERSION_1_4( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_VERSION_1_4) return;
+ glad_glBlendColor = (PFNGLBLENDCOLORPROC) load(userptr, "glBlendColor");
+ glad_glBlendEquation = (PFNGLBLENDEQUATIONPROC) load(userptr, "glBlendEquation");
+ glad_glBlendFuncSeparate = (PFNGLBLENDFUNCSEPARATEPROC) load(userptr, "glBlendFuncSeparate");
+ glad_glFogCoordPointer = (PFNGLFOGCOORDPOINTERPROC) load(userptr, "glFogCoordPointer");
+ glad_glFogCoordd = (PFNGLFOGCOORDDPROC) load(userptr, "glFogCoordd");
+ glad_glFogCoorddv = (PFNGLFOGCOORDDVPROC) load(userptr, "glFogCoorddv");
+ glad_glFogCoordf = (PFNGLFOGCOORDFPROC) load(userptr, "glFogCoordf");
+ glad_glFogCoordfv = (PFNGLFOGCOORDFVPROC) load(userptr, "glFogCoordfv");
+ glad_glMultiDrawArrays = (PFNGLMULTIDRAWARRAYSPROC) load(userptr, "glMultiDrawArrays");
+ glad_glMultiDrawElements = (PFNGLMULTIDRAWELEMENTSPROC) load(userptr, "glMultiDrawElements");
+ glad_glPointParameterf = (PFNGLPOINTPARAMETERFPROC) load(userptr, "glPointParameterf");
+ glad_glPointParameterfv = (PFNGLPOINTPARAMETERFVPROC) load(userptr, "glPointParameterfv");
+ glad_glPointParameteri = (PFNGLPOINTPARAMETERIPROC) load(userptr, "glPointParameteri");
+ glad_glPointParameteriv = (PFNGLPOINTPARAMETERIVPROC) load(userptr, "glPointParameteriv");
+ glad_glSecondaryColor3b = (PFNGLSECONDARYCOLOR3BPROC) load(userptr, "glSecondaryColor3b");
+ glad_glSecondaryColor3bv = (PFNGLSECONDARYCOLOR3BVPROC) load(userptr, "glSecondaryColor3bv");
+ glad_glSecondaryColor3d = (PFNGLSECONDARYCOLOR3DPROC) load(userptr, "glSecondaryColor3d");
+ glad_glSecondaryColor3dv = (PFNGLSECONDARYCOLOR3DVPROC) load(userptr, "glSecondaryColor3dv");
+ glad_glSecondaryColor3f = (PFNGLSECONDARYCOLOR3FPROC) load(userptr, "glSecondaryColor3f");
+ glad_glSecondaryColor3fv = (PFNGLSECONDARYCOLOR3FVPROC) load(userptr, "glSecondaryColor3fv");
+ glad_glSecondaryColor3i = (PFNGLSECONDARYCOLOR3IPROC) load(userptr, "glSecondaryColor3i");
+ glad_glSecondaryColor3iv = (PFNGLSECONDARYCOLOR3IVPROC) load(userptr, "glSecondaryColor3iv");
+ glad_glSecondaryColor3s = (PFNGLSECONDARYCOLOR3SPROC) load(userptr, "glSecondaryColor3s");
+ glad_glSecondaryColor3sv = (PFNGLSECONDARYCOLOR3SVPROC) load(userptr, "glSecondaryColor3sv");
+ glad_glSecondaryColor3ub = (PFNGLSECONDARYCOLOR3UBPROC) load(userptr, "glSecondaryColor3ub");
+ glad_glSecondaryColor3ubv = (PFNGLSECONDARYCOLOR3UBVPROC) load(userptr, "glSecondaryColor3ubv");
+ glad_glSecondaryColor3ui = (PFNGLSECONDARYCOLOR3UIPROC) load(userptr, "glSecondaryColor3ui");
+ glad_glSecondaryColor3uiv = (PFNGLSECONDARYCOLOR3UIVPROC) load(userptr, "glSecondaryColor3uiv");
+ glad_glSecondaryColor3us = (PFNGLSECONDARYCOLOR3USPROC) load(userptr, "glSecondaryColor3us");
+ glad_glSecondaryColor3usv = (PFNGLSECONDARYCOLOR3USVPROC) load(userptr, "glSecondaryColor3usv");
+ glad_glSecondaryColorPointer = (PFNGLSECONDARYCOLORPOINTERPROC) load(userptr, "glSecondaryColorPointer");
+ glad_glWindowPos2d = (PFNGLWINDOWPOS2DPROC) load(userptr, "glWindowPos2d");
+ glad_glWindowPos2dv = (PFNGLWINDOWPOS2DVPROC) load(userptr, "glWindowPos2dv");
+ glad_glWindowPos2f = (PFNGLWINDOWPOS2FPROC) load(userptr, "glWindowPos2f");
+ glad_glWindowPos2fv = (PFNGLWINDOWPOS2FVPROC) load(userptr, "glWindowPos2fv");
+ glad_glWindowPos2i = (PFNGLWINDOWPOS2IPROC) load(userptr, "glWindowPos2i");
+ glad_glWindowPos2iv = (PFNGLWINDOWPOS2IVPROC) load(userptr, "glWindowPos2iv");
+ glad_glWindowPos2s = (PFNGLWINDOWPOS2SPROC) load(userptr, "glWindowPos2s");
+ glad_glWindowPos2sv = (PFNGLWINDOWPOS2SVPROC) load(userptr, "glWindowPos2sv");
+ glad_glWindowPos3d = (PFNGLWINDOWPOS3DPROC) load(userptr, "glWindowPos3d");
+ glad_glWindowPos3dv = (PFNGLWINDOWPOS3DVPROC) load(userptr, "glWindowPos3dv");
+ glad_glWindowPos3f = (PFNGLWINDOWPOS3FPROC) load(userptr, "glWindowPos3f");
+ glad_glWindowPos3fv = (PFNGLWINDOWPOS3FVPROC) load(userptr, "glWindowPos3fv");
+ glad_glWindowPos3i = (PFNGLWINDOWPOS3IPROC) load(userptr, "glWindowPos3i");
+ glad_glWindowPos3iv = (PFNGLWINDOWPOS3IVPROC) load(userptr, "glWindowPos3iv");
+ glad_glWindowPos3s = (PFNGLWINDOWPOS3SPROC) load(userptr, "glWindowPos3s");
+ glad_glWindowPos3sv = (PFNGLWINDOWPOS3SVPROC) load(userptr, "glWindowPos3sv");
+}
+static void glad_gl_load_GL_VERSION_1_5( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_VERSION_1_5) return;
+ glad_glBeginQuery = (PFNGLBEGINQUERYPROC) load(userptr, "glBeginQuery");
+ glad_glBindBuffer = (PFNGLBINDBUFFERPROC) load(userptr, "glBindBuffer");
+ glad_glBufferData = (PFNGLBUFFERDATAPROC) load(userptr, "glBufferData");
+ glad_glBufferSubData = (PFNGLBUFFERSUBDATAPROC) load(userptr, "glBufferSubData");
+ glad_glDeleteBuffers = (PFNGLDELETEBUFFERSPROC) load(userptr, "glDeleteBuffers");
+ glad_glDeleteQueries = (PFNGLDELETEQUERIESPROC) load(userptr, "glDeleteQueries");
+ glad_glEndQuery = (PFNGLENDQUERYPROC) load(userptr, "glEndQuery");
+ glad_glGenBuffers = (PFNGLGENBUFFERSPROC) load(userptr, "glGenBuffers");
+ glad_glGenQueries = (PFNGLGENQUERIESPROC) load(userptr, "glGenQueries");
+ glad_glGetBufferParameteriv = (PFNGLGETBUFFERPARAMETERIVPROC) load(userptr, "glGetBufferParameteriv");
+ glad_glGetBufferPointerv = (PFNGLGETBUFFERPOINTERVPROC) load(userptr, "glGetBufferPointerv");
+ glad_glGetBufferSubData = (PFNGLGETBUFFERSUBDATAPROC) load(userptr, "glGetBufferSubData");
+ glad_glGetQueryObjectiv = (PFNGLGETQUERYOBJECTIVPROC) load(userptr, "glGetQueryObjectiv");
+ glad_glGetQueryObjectuiv = (PFNGLGETQUERYOBJECTUIVPROC) load(userptr, "glGetQueryObjectuiv");
+ glad_glGetQueryiv = (PFNGLGETQUERYIVPROC) load(userptr, "glGetQueryiv");
+ glad_glIsBuffer = (PFNGLISBUFFERPROC) load(userptr, "glIsBuffer");
+ glad_glIsQuery = (PFNGLISQUERYPROC) load(userptr, "glIsQuery");
+ glad_glMapBuffer = (PFNGLMAPBUFFERPROC) load(userptr, "glMapBuffer");
+ glad_glUnmapBuffer = (PFNGLUNMAPBUFFERPROC) load(userptr, "glUnmapBuffer");
+}
+static void glad_gl_load_GL_VERSION_2_0( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_VERSION_2_0) return;
+ glad_glAttachShader = (PFNGLATTACHSHADERPROC) load(userptr, "glAttachShader");
+ glad_glBindAttribLocation = (PFNGLBINDATTRIBLOCATIONPROC) load(userptr, "glBindAttribLocation");
+ glad_glBlendEquationSeparate = (PFNGLBLENDEQUATIONSEPARATEPROC) load(userptr, "glBlendEquationSeparate");
+ glad_glCompileShader = (PFNGLCOMPILESHADERPROC) load(userptr, "glCompileShader");
+ glad_glCreateProgram = (PFNGLCREATEPROGRAMPROC) load(userptr, "glCreateProgram");
+ glad_glCreateShader = (PFNGLCREATESHADERPROC) load(userptr, "glCreateShader");
+ glad_glDeleteProgram = (PFNGLDELETEPROGRAMPROC) load(userptr, "glDeleteProgram");
+ glad_glDeleteShader = (PFNGLDELETESHADERPROC) load(userptr, "glDeleteShader");
+ glad_glDetachShader = (PFNGLDETACHSHADERPROC) load(userptr, "glDetachShader");
+ glad_glDisableVertexAttribArray = (PFNGLDISABLEVERTEXATTRIBARRAYPROC) load(userptr, "glDisableVertexAttribArray");
+ glad_glDrawBuffers = (PFNGLDRAWBUFFERSPROC) load(userptr, "glDrawBuffers");
+ glad_glEnableVertexAttribArray = (PFNGLENABLEVERTEXATTRIBARRAYPROC) load(userptr, "glEnableVertexAttribArray");
+ glad_glGetActiveAttrib = (PFNGLGETACTIVEATTRIBPROC) load(userptr, "glGetActiveAttrib");
+ glad_glGetActiveUniform = (PFNGLGETACTIVEUNIFORMPROC) load(userptr, "glGetActiveUniform");
+ glad_glGetAttachedShaders = (PFNGLGETATTACHEDSHADERSPROC) load(userptr, "glGetAttachedShaders");
+ glad_glGetAttribLocation = (PFNGLGETATTRIBLOCATIONPROC) load(userptr, "glGetAttribLocation");
+ glad_glGetProgramInfoLog = (PFNGLGETPROGRAMINFOLOGPROC) load(userptr, "glGetProgramInfoLog");
+ glad_glGetProgramiv = (PFNGLGETPROGRAMIVPROC) load(userptr, "glGetProgramiv");
+ glad_glGetShaderInfoLog = (PFNGLGETSHADERINFOLOGPROC) load(userptr, "glGetShaderInfoLog");
+ glad_glGetShaderSource = (PFNGLGETSHADERSOURCEPROC) load(userptr, "glGetShaderSource");
+ glad_glGetShaderiv = (PFNGLGETSHADERIVPROC) load(userptr, "glGetShaderiv");
+ glad_glGetUniformLocation = (PFNGLGETUNIFORMLOCATIONPROC) load(userptr, "glGetUniformLocation");
+ glad_glGetUniformfv = (PFNGLGETUNIFORMFVPROC) load(userptr, "glGetUniformfv");
+ glad_glGetUniformiv = (PFNGLGETUNIFORMIVPROC) load(userptr, "glGetUniformiv");
+ glad_glGetVertexAttribPointerv = (PFNGLGETVERTEXATTRIBPOINTERVPROC) load(userptr, "glGetVertexAttribPointerv");
+ glad_glGetVertexAttribdv = (PFNGLGETVERTEXATTRIBDVPROC) load(userptr, "glGetVertexAttribdv");
+ glad_glGetVertexAttribfv = (PFNGLGETVERTEXATTRIBFVPROC) load(userptr, "glGetVertexAttribfv");
+ glad_glGetVertexAttribiv = (PFNGLGETVERTEXATTRIBIVPROC) load(userptr, "glGetVertexAttribiv");
+ glad_glIsProgram = (PFNGLISPROGRAMPROC) load(userptr, "glIsProgram");
+ glad_glIsShader = (PFNGLISSHADERPROC) load(userptr, "glIsShader");
+ glad_glLinkProgram = (PFNGLLINKPROGRAMPROC) load(userptr, "glLinkProgram");
+ glad_glShaderSource = (PFNGLSHADERSOURCEPROC) load(userptr, "glShaderSource");
+ glad_glStencilFuncSeparate = (PFNGLSTENCILFUNCSEPARATEPROC) load(userptr, "glStencilFuncSeparate");
+ glad_glStencilMaskSeparate = (PFNGLSTENCILMASKSEPARATEPROC) load(userptr, "glStencilMaskSeparate");
+ glad_glStencilOpSeparate = (PFNGLSTENCILOPSEPARATEPROC) load(userptr, "glStencilOpSeparate");
+ glad_glUniform1f = (PFNGLUNIFORM1FPROC) load(userptr, "glUniform1f");
+ glad_glUniform1fv = (PFNGLUNIFORM1FVPROC) load(userptr, "glUniform1fv");
+ glad_glUniform1i = (PFNGLUNIFORM1IPROC) load(userptr, "glUniform1i");
+ glad_glUniform1iv = (PFNGLUNIFORM1IVPROC) load(userptr, "glUniform1iv");
+ glad_glUniform2f = (PFNGLUNIFORM2FPROC) load(userptr, "glUniform2f");
+ glad_glUniform2fv = (PFNGLUNIFORM2FVPROC) load(userptr, "glUniform2fv");
+ glad_glUniform2i = (PFNGLUNIFORM2IPROC) load(userptr, "glUniform2i");
+ glad_glUniform2iv = (PFNGLUNIFORM2IVPROC) load(userptr, "glUniform2iv");
+ glad_glUniform3f = (PFNGLUNIFORM3FPROC) load(userptr, "glUniform3f");
+ glad_glUniform3fv = (PFNGLUNIFORM3FVPROC) load(userptr, "glUniform3fv");
+ glad_glUniform3i = (PFNGLUNIFORM3IPROC) load(userptr, "glUniform3i");
+ glad_glUniform3iv = (PFNGLUNIFORM3IVPROC) load(userptr, "glUniform3iv");
+ glad_glUniform4f = (PFNGLUNIFORM4FPROC) load(userptr, "glUniform4f");
+ glad_glUniform4fv = (PFNGLUNIFORM4FVPROC) load(userptr, "glUniform4fv");
+ glad_glUniform4i = (PFNGLUNIFORM4IPROC) load(userptr, "glUniform4i");
+ glad_glUniform4iv = (PFNGLUNIFORM4IVPROC) load(userptr, "glUniform4iv");
+ glad_glUniformMatrix2fv = (PFNGLUNIFORMMATRIX2FVPROC) load(userptr, "glUniformMatrix2fv");
+ glad_glUniformMatrix3fv = (PFNGLUNIFORMMATRIX3FVPROC) load(userptr, "glUniformMatrix3fv");
+ glad_glUniformMatrix4fv = (PFNGLUNIFORMMATRIX4FVPROC) load(userptr, "glUniformMatrix4fv");
+ glad_glUseProgram = (PFNGLUSEPROGRAMPROC) load(userptr, "glUseProgram");
+ glad_glValidateProgram = (PFNGLVALIDATEPROGRAMPROC) load(userptr, "glValidateProgram");
+ glad_glVertexAttrib1d = (PFNGLVERTEXATTRIB1DPROC) load(userptr, "glVertexAttrib1d");
+ glad_glVertexAttrib1dv = (PFNGLVERTEXATTRIB1DVPROC) load(userptr, "glVertexAttrib1dv");
+ glad_glVertexAttrib1f = (PFNGLVERTEXATTRIB1FPROC) load(userptr, "glVertexAttrib1f");
+ glad_glVertexAttrib1fv = (PFNGLVERTEXATTRIB1FVPROC) load(userptr, "glVertexAttrib1fv");
+ glad_glVertexAttrib1s = (PFNGLVERTEXATTRIB1SPROC) load(userptr, "glVertexAttrib1s");
+ glad_glVertexAttrib1sv = (PFNGLVERTEXATTRIB1SVPROC) load(userptr, "glVertexAttrib1sv");
+ glad_glVertexAttrib2d = (PFNGLVERTEXATTRIB2DPROC) load(userptr, "glVertexAttrib2d");
+ glad_glVertexAttrib2dv = (PFNGLVERTEXATTRIB2DVPROC) load(userptr, "glVertexAttrib2dv");
+ glad_glVertexAttrib2f = (PFNGLVERTEXATTRIB2FPROC) load(userptr, "glVertexAttrib2f");
+ glad_glVertexAttrib2fv = (PFNGLVERTEXATTRIB2FVPROC) load(userptr, "glVertexAttrib2fv");
+ glad_glVertexAttrib2s = (PFNGLVERTEXATTRIB2SPROC) load(userptr, "glVertexAttrib2s");
+ glad_glVertexAttrib2sv = (PFNGLVERTEXATTRIB2SVPROC) load(userptr, "glVertexAttrib2sv");
+ glad_glVertexAttrib3d = (PFNGLVERTEXATTRIB3DPROC) load(userptr, "glVertexAttrib3d");
+ glad_glVertexAttrib3dv = (PFNGLVERTEXATTRIB3DVPROC) load(userptr, "glVertexAttrib3dv");
+ glad_glVertexAttrib3f = (PFNGLVERTEXATTRIB3FPROC) load(userptr, "glVertexAttrib3f");
+ glad_glVertexAttrib3fv = (PFNGLVERTEXATTRIB3FVPROC) load(userptr, "glVertexAttrib3fv");
+ glad_glVertexAttrib3s = (PFNGLVERTEXATTRIB3SPROC) load(userptr, "glVertexAttrib3s");
+ glad_glVertexAttrib3sv = (PFNGLVERTEXATTRIB3SVPROC) load(userptr, "glVertexAttrib3sv");
+ glad_glVertexAttrib4Nbv = (PFNGLVERTEXATTRIB4NBVPROC) load(userptr, "glVertexAttrib4Nbv");
+ glad_glVertexAttrib4Niv = (PFNGLVERTEXATTRIB4NIVPROC) load(userptr, "glVertexAttrib4Niv");
+ glad_glVertexAttrib4Nsv = (PFNGLVERTEXATTRIB4NSVPROC) load(userptr, "glVertexAttrib4Nsv");
+ glad_glVertexAttrib4Nub = (PFNGLVERTEXATTRIB4NUBPROC) load(userptr, "glVertexAttrib4Nub");
+ glad_glVertexAttrib4Nubv = (PFNGLVERTEXATTRIB4NUBVPROC) load(userptr, "glVertexAttrib4Nubv");
+ glad_glVertexAttrib4Nuiv = (PFNGLVERTEXATTRIB4NUIVPROC) load(userptr, "glVertexAttrib4Nuiv");
+ glad_glVertexAttrib4Nusv = (PFNGLVERTEXATTRIB4NUSVPROC) load(userptr, "glVertexAttrib4Nusv");
+ glad_glVertexAttrib4bv = (PFNGLVERTEXATTRIB4BVPROC) load(userptr, "glVertexAttrib4bv");
+ glad_glVertexAttrib4d = (PFNGLVERTEXATTRIB4DPROC) load(userptr, "glVertexAttrib4d");
+ glad_glVertexAttrib4dv = (PFNGLVERTEXATTRIB4DVPROC) load(userptr, "glVertexAttrib4dv");
+ glad_glVertexAttrib4f = (PFNGLVERTEXATTRIB4FPROC) load(userptr, "glVertexAttrib4f");
+ glad_glVertexAttrib4fv = (PFNGLVERTEXATTRIB4FVPROC) load(userptr, "glVertexAttrib4fv");
+ glad_glVertexAttrib4iv = (PFNGLVERTEXATTRIB4IVPROC) load(userptr, "glVertexAttrib4iv");
+ glad_glVertexAttrib4s = (PFNGLVERTEXATTRIB4SPROC) load(userptr, "glVertexAttrib4s");
+ glad_glVertexAttrib4sv = (PFNGLVERTEXATTRIB4SVPROC) load(userptr, "glVertexAttrib4sv");
+ glad_glVertexAttrib4ubv = (PFNGLVERTEXATTRIB4UBVPROC) load(userptr, "glVertexAttrib4ubv");
+ glad_glVertexAttrib4uiv = (PFNGLVERTEXATTRIB4UIVPROC) load(userptr, "glVertexAttrib4uiv");
+ glad_glVertexAttrib4usv = (PFNGLVERTEXATTRIB4USVPROC) load(userptr, "glVertexAttrib4usv");
+ glad_glVertexAttribPointer = (PFNGLVERTEXATTRIBPOINTERPROC) load(userptr, "glVertexAttribPointer");
+}
+static void glad_gl_load_GL_VERSION_2_1( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_VERSION_2_1) return;
+ glad_glUniformMatrix2x3fv = (PFNGLUNIFORMMATRIX2X3FVPROC) load(userptr, "glUniformMatrix2x3fv");
+ glad_glUniformMatrix2x4fv = (PFNGLUNIFORMMATRIX2X4FVPROC) load(userptr, "glUniformMatrix2x4fv");
+ glad_glUniformMatrix3x2fv = (PFNGLUNIFORMMATRIX3X2FVPROC) load(userptr, "glUniformMatrix3x2fv");
+ glad_glUniformMatrix3x4fv = (PFNGLUNIFORMMATRIX3X4FVPROC) load(userptr, "glUniformMatrix3x4fv");
+ glad_glUniformMatrix4x2fv = (PFNGLUNIFORMMATRIX4X2FVPROC) load(userptr, "glUniformMatrix4x2fv");
+ glad_glUniformMatrix4x3fv = (PFNGLUNIFORMMATRIX4X3FVPROC) load(userptr, "glUniformMatrix4x3fv");
+}
+static void glad_gl_load_GL_VERSION_3_0( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_VERSION_3_0) return;
+ glad_glBeginConditionalRender = (PFNGLBEGINCONDITIONALRENDERPROC) load(userptr, "glBeginConditionalRender");
+ glad_glBeginTransformFeedback = (PFNGLBEGINTRANSFORMFEEDBACKPROC) load(userptr, "glBeginTransformFeedback");
+ glad_glBindBufferBase = (PFNGLBINDBUFFERBASEPROC) load(userptr, "glBindBufferBase");
+ glad_glBindBufferRange = (PFNGLBINDBUFFERRANGEPROC) load(userptr, "glBindBufferRange");
+ glad_glBindFragDataLocation = (PFNGLBINDFRAGDATALOCATIONPROC) load(userptr, "glBindFragDataLocation");
+ glad_glBindFramebuffer = (PFNGLBINDFRAMEBUFFERPROC) load(userptr, "glBindFramebuffer");
+ glad_glBindRenderbuffer = (PFNGLBINDRENDERBUFFERPROC) load(userptr, "glBindRenderbuffer");
+ glad_glBindVertexArray = (PFNGLBINDVERTEXARRAYPROC) load(userptr, "glBindVertexArray");
+ glad_glBlitFramebuffer = (PFNGLBLITFRAMEBUFFERPROC) load(userptr, "glBlitFramebuffer");
+ glad_glCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSPROC) load(userptr, "glCheckFramebufferStatus");
+ glad_glClampColor = (PFNGLCLAMPCOLORPROC) load(userptr, "glClampColor");
+ glad_glClearBufferfi = (PFNGLCLEARBUFFERFIPROC) load(userptr, "glClearBufferfi");
+ glad_glClearBufferfv = (PFNGLCLEARBUFFERFVPROC) load(userptr, "glClearBufferfv");
+ glad_glClearBufferiv = (PFNGLCLEARBUFFERIVPROC) load(userptr, "glClearBufferiv");
+ glad_glClearBufferuiv = (PFNGLCLEARBUFFERUIVPROC) load(userptr, "glClearBufferuiv");
+ glad_glColorMaski = (PFNGLCOLORMASKIPROC) load(userptr, "glColorMaski");
+ glad_glDeleteFramebuffers = (PFNGLDELETEFRAMEBUFFERSPROC) load(userptr, "glDeleteFramebuffers");
+ glad_glDeleteRenderbuffers = (PFNGLDELETERENDERBUFFERSPROC) load(userptr, "glDeleteRenderbuffers");
+ glad_glDeleteVertexArrays = (PFNGLDELETEVERTEXARRAYSPROC) load(userptr, "glDeleteVertexArrays");
+ glad_glDisablei = (PFNGLDISABLEIPROC) load(userptr, "glDisablei");
+ glad_glEnablei = (PFNGLENABLEIPROC) load(userptr, "glEnablei");
+ glad_glEndConditionalRender = (PFNGLENDCONDITIONALRENDERPROC) load(userptr, "glEndConditionalRender");
+ glad_glEndTransformFeedback = (PFNGLENDTRANSFORMFEEDBACKPROC) load(userptr, "glEndTransformFeedback");
+ glad_glFlushMappedBufferRange = (PFNGLFLUSHMAPPEDBUFFERRANGEPROC) load(userptr, "glFlushMappedBufferRange");
+ glad_glFramebufferRenderbuffer = (PFNGLFRAMEBUFFERRENDERBUFFERPROC) load(userptr, "glFramebufferRenderbuffer");
+ glad_glFramebufferTexture1D = (PFNGLFRAMEBUFFERTEXTURE1DPROC) load(userptr, "glFramebufferTexture1D");
+ glad_glFramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DPROC) load(userptr, "glFramebufferTexture2D");
+ glad_glFramebufferTexture3D = (PFNGLFRAMEBUFFERTEXTURE3DPROC) load(userptr, "glFramebufferTexture3D");
+ glad_glFramebufferTextureLayer = (PFNGLFRAMEBUFFERTEXTURELAYERPROC) load(userptr, "glFramebufferTextureLayer");
+ glad_glGenFramebuffers = (PFNGLGENFRAMEBUFFERSPROC) load(userptr, "glGenFramebuffers");
+ glad_glGenRenderbuffers = (PFNGLGENRENDERBUFFERSPROC) load(userptr, "glGenRenderbuffers");
+ glad_glGenVertexArrays = (PFNGLGENVERTEXARRAYSPROC) load(userptr, "glGenVertexArrays");
+ glad_glGenerateMipmap = (PFNGLGENERATEMIPMAPPROC) load(userptr, "glGenerateMipmap");
+ glad_glGetBooleani_v = (PFNGLGETBOOLEANI_VPROC) load(userptr, "glGetBooleani_v");
+ glad_glGetFragDataLocation = (PFNGLGETFRAGDATALOCATIONPROC) load(userptr, "glGetFragDataLocation");
+ glad_glGetFramebufferAttachmentParameteriv = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC) load(userptr, "glGetFramebufferAttachmentParameteriv");
+ glad_glGetIntegeri_v = (PFNGLGETINTEGERI_VPROC) load(userptr, "glGetIntegeri_v");
+ glad_glGetRenderbufferParameteriv = (PFNGLGETRENDERBUFFERPARAMETERIVPROC) load(userptr, "glGetRenderbufferParameteriv");
+ glad_glGetStringi = (PFNGLGETSTRINGIPROC) load(userptr, "glGetStringi");
+ glad_glGetTexParameterIiv = (PFNGLGETTEXPARAMETERIIVPROC) load(userptr, "glGetTexParameterIiv");
+ glad_glGetTexParameterIuiv = (PFNGLGETTEXPARAMETERIUIVPROC) load(userptr, "glGetTexParameterIuiv");
+ glad_glGetTransformFeedbackVarying = (PFNGLGETTRANSFORMFEEDBACKVARYINGPROC) load(userptr, "glGetTransformFeedbackVarying");
+ glad_glGetUniformuiv = (PFNGLGETUNIFORMUIVPROC) load(userptr, "glGetUniformuiv");
+ glad_glGetVertexAttribIiv = (PFNGLGETVERTEXATTRIBIIVPROC) load(userptr, "glGetVertexAttribIiv");
+ glad_glGetVertexAttribIuiv = (PFNGLGETVERTEXATTRIBIUIVPROC) load(userptr, "glGetVertexAttribIuiv");
+ glad_glIsEnabledi = (PFNGLISENABLEDIPROC) load(userptr, "glIsEnabledi");
+ glad_glIsFramebuffer = (PFNGLISFRAMEBUFFERPROC) load(userptr, "glIsFramebuffer");
+ glad_glIsRenderbuffer = (PFNGLISRENDERBUFFERPROC) load(userptr, "glIsRenderbuffer");
+ glad_glIsVertexArray = (PFNGLISVERTEXARRAYPROC) load(userptr, "glIsVertexArray");
+ glad_glMapBufferRange = (PFNGLMAPBUFFERRANGEPROC) load(userptr, "glMapBufferRange");
+ glad_glRenderbufferStorage = (PFNGLRENDERBUFFERSTORAGEPROC) load(userptr, "glRenderbufferStorage");
+ glad_glRenderbufferStorageMultisample = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC) load(userptr, "glRenderbufferStorageMultisample");
+ glad_glTexParameterIiv = (PFNGLTEXPARAMETERIIVPROC) load(userptr, "glTexParameterIiv");
+ glad_glTexParameterIuiv = (PFNGLTEXPARAMETERIUIVPROC) load(userptr, "glTexParameterIuiv");
+ glad_glTransformFeedbackVaryings = (PFNGLTRANSFORMFEEDBACKVARYINGSPROC) load(userptr, "glTransformFeedbackVaryings");
+ glad_glUniform1ui = (PFNGLUNIFORM1UIPROC) load(userptr, "glUniform1ui");
+ glad_glUniform1uiv = (PFNGLUNIFORM1UIVPROC) load(userptr, "glUniform1uiv");
+ glad_glUniform2ui = (PFNGLUNIFORM2UIPROC) load(userptr, "glUniform2ui");
+ glad_glUniform2uiv = (PFNGLUNIFORM2UIVPROC) load(userptr, "glUniform2uiv");
+ glad_glUniform3ui = (PFNGLUNIFORM3UIPROC) load(userptr, "glUniform3ui");
+ glad_glUniform3uiv = (PFNGLUNIFORM3UIVPROC) load(userptr, "glUniform3uiv");
+ glad_glUniform4ui = (PFNGLUNIFORM4UIPROC) load(userptr, "glUniform4ui");
+ glad_glUniform4uiv = (PFNGLUNIFORM4UIVPROC) load(userptr, "glUniform4uiv");
+ glad_glVertexAttribI1i = (PFNGLVERTEXATTRIBI1IPROC) load(userptr, "glVertexAttribI1i");
+ glad_glVertexAttribI1iv = (PFNGLVERTEXATTRIBI1IVPROC) load(userptr, "glVertexAttribI1iv");
+ glad_glVertexAttribI1ui = (PFNGLVERTEXATTRIBI1UIPROC) load(userptr, "glVertexAttribI1ui");
+ glad_glVertexAttribI1uiv = (PFNGLVERTEXATTRIBI1UIVPROC) load(userptr, "glVertexAttribI1uiv");
+ glad_glVertexAttribI2i = (PFNGLVERTEXATTRIBI2IPROC) load(userptr, "glVertexAttribI2i");
+ glad_glVertexAttribI2iv = (PFNGLVERTEXATTRIBI2IVPROC) load(userptr, "glVertexAttribI2iv");
+ glad_glVertexAttribI2ui = (PFNGLVERTEXATTRIBI2UIPROC) load(userptr, "glVertexAttribI2ui");
+ glad_glVertexAttribI2uiv = (PFNGLVERTEXATTRIBI2UIVPROC) load(userptr, "glVertexAttribI2uiv");
+ glad_glVertexAttribI3i = (PFNGLVERTEXATTRIBI3IPROC) load(userptr, "glVertexAttribI3i");
+ glad_glVertexAttribI3iv = (PFNGLVERTEXATTRIBI3IVPROC) load(userptr, "glVertexAttribI3iv");
+ glad_glVertexAttribI3ui = (PFNGLVERTEXATTRIBI3UIPROC) load(userptr, "glVertexAttribI3ui");
+ glad_glVertexAttribI3uiv = (PFNGLVERTEXATTRIBI3UIVPROC) load(userptr, "glVertexAttribI3uiv");
+ glad_glVertexAttribI4bv = (PFNGLVERTEXATTRIBI4BVPROC) load(userptr, "glVertexAttribI4bv");
+ glad_glVertexAttribI4i = (PFNGLVERTEXATTRIBI4IPROC) load(userptr, "glVertexAttribI4i");
+ glad_glVertexAttribI4iv = (PFNGLVERTEXATTRIBI4IVPROC) load(userptr, "glVertexAttribI4iv");
+ glad_glVertexAttribI4sv = (PFNGLVERTEXATTRIBI4SVPROC) load(userptr, "glVertexAttribI4sv");
+ glad_glVertexAttribI4ubv = (PFNGLVERTEXATTRIBI4UBVPROC) load(userptr, "glVertexAttribI4ubv");
+ glad_glVertexAttribI4ui = (PFNGLVERTEXATTRIBI4UIPROC) load(userptr, "glVertexAttribI4ui");
+ glad_glVertexAttribI4uiv = (PFNGLVERTEXATTRIBI4UIVPROC) load(userptr, "glVertexAttribI4uiv");
+ glad_glVertexAttribI4usv = (PFNGLVERTEXATTRIBI4USVPROC) load(userptr, "glVertexAttribI4usv");
+ glad_glVertexAttribIPointer = (PFNGLVERTEXATTRIBIPOINTERPROC) load(userptr, "glVertexAttribIPointer");
+}
+static void glad_gl_load_GL_VERSION_3_1( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_VERSION_3_1) return;
+ glad_glBindBufferBase = (PFNGLBINDBUFFERBASEPROC) load(userptr, "glBindBufferBase");
+ glad_glBindBufferRange = (PFNGLBINDBUFFERRANGEPROC) load(userptr, "glBindBufferRange");
+ glad_glCopyBufferSubData = (PFNGLCOPYBUFFERSUBDATAPROC) load(userptr, "glCopyBufferSubData");
+ glad_glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDPROC) load(userptr, "glDrawArraysInstanced");
+ glad_glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDPROC) load(userptr, "glDrawElementsInstanced");
+ glad_glGetActiveUniformBlockName = (PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC) load(userptr, "glGetActiveUniformBlockName");
+ glad_glGetActiveUniformBlockiv = (PFNGLGETACTIVEUNIFORMBLOCKIVPROC) load(userptr, "glGetActiveUniformBlockiv");
+ glad_glGetActiveUniformName = (PFNGLGETACTIVEUNIFORMNAMEPROC) load(userptr, "glGetActiveUniformName");
+ glad_glGetActiveUniformsiv = (PFNGLGETACTIVEUNIFORMSIVPROC) load(userptr, "glGetActiveUniformsiv");
+ glad_glGetIntegeri_v = (PFNGLGETINTEGERI_VPROC) load(userptr, "glGetIntegeri_v");
+ glad_glGetUniformBlockIndex = (PFNGLGETUNIFORMBLOCKINDEXPROC) load(userptr, "glGetUniformBlockIndex");
+ glad_glGetUniformIndices = (PFNGLGETUNIFORMINDICESPROC) load(userptr, "glGetUniformIndices");
+ glad_glPrimitiveRestartIndex = (PFNGLPRIMITIVERESTARTINDEXPROC) load(userptr, "glPrimitiveRestartIndex");
+ glad_glTexBuffer = (PFNGLTEXBUFFERPROC) load(userptr, "glTexBuffer");
+ glad_glUniformBlockBinding = (PFNGLUNIFORMBLOCKBINDINGPROC) load(userptr, "glUniformBlockBinding");
+}
+static void glad_gl_load_GL_VERSION_3_2( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_VERSION_3_2) return;
+ glad_glClientWaitSync = (PFNGLCLIENTWAITSYNCPROC) load(userptr, "glClientWaitSync");
+ glad_glDeleteSync = (PFNGLDELETESYNCPROC) load(userptr, "glDeleteSync");
+ glad_glDrawElementsBaseVertex = (PFNGLDRAWELEMENTSBASEVERTEXPROC) load(userptr, "glDrawElementsBaseVertex");
+ glad_glDrawElementsInstancedBaseVertex = (PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC) load(userptr, "glDrawElementsInstancedBaseVertex");
+ glad_glDrawRangeElementsBaseVertex = (PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC) load(userptr, "glDrawRangeElementsBaseVertex");
+ glad_glFenceSync = (PFNGLFENCESYNCPROC) load(userptr, "glFenceSync");
+ glad_glFramebufferTexture = (PFNGLFRAMEBUFFERTEXTUREPROC) load(userptr, "glFramebufferTexture");
+ glad_glGetBufferParameteri64v = (PFNGLGETBUFFERPARAMETERI64VPROC) load(userptr, "glGetBufferParameteri64v");
+ glad_glGetInteger64i_v = (PFNGLGETINTEGER64I_VPROC) load(userptr, "glGetInteger64i_v");
+ glad_glGetInteger64v = (PFNGLGETINTEGER64VPROC) load(userptr, "glGetInteger64v");
+ glad_glGetMultisamplefv = (PFNGLGETMULTISAMPLEFVPROC) load(userptr, "glGetMultisamplefv");
+ glad_glGetSynciv = (PFNGLGETSYNCIVPROC) load(userptr, "glGetSynciv");
+ glad_glIsSync = (PFNGLISSYNCPROC) load(userptr, "glIsSync");
+ glad_glMultiDrawElementsBaseVertex = (PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC) load(userptr, "glMultiDrawElementsBaseVertex");
+ glad_glProvokingVertex = (PFNGLPROVOKINGVERTEXPROC) load(userptr, "glProvokingVertex");
+ glad_glSampleMaski = (PFNGLSAMPLEMASKIPROC) load(userptr, "glSampleMaski");
+ glad_glTexImage2DMultisample = (PFNGLTEXIMAGE2DMULTISAMPLEPROC) load(userptr, "glTexImage2DMultisample");
+ glad_glTexImage3DMultisample = (PFNGLTEXIMAGE3DMULTISAMPLEPROC) load(userptr, "glTexImage3DMultisample");
+ glad_glWaitSync = (PFNGLWAITSYNCPROC) load(userptr, "glWaitSync");
+}
+static void glad_gl_load_GL_VERSION_3_3( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_VERSION_3_3) return;
+ glad_glBindFragDataLocationIndexed = (PFNGLBINDFRAGDATALOCATIONINDEXEDPROC) load(userptr, "glBindFragDataLocationIndexed");
+ glad_glBindSampler = (PFNGLBINDSAMPLERPROC) load(userptr, "glBindSampler");
+ glad_glColorP3ui = (PFNGLCOLORP3UIPROC) load(userptr, "glColorP3ui");
+ glad_glColorP3uiv = (PFNGLCOLORP3UIVPROC) load(userptr, "glColorP3uiv");
+ glad_glColorP4ui = (PFNGLCOLORP4UIPROC) load(userptr, "glColorP4ui");
+ glad_glColorP4uiv = (PFNGLCOLORP4UIVPROC) load(userptr, "glColorP4uiv");
+ glad_glDeleteSamplers = (PFNGLDELETESAMPLERSPROC) load(userptr, "glDeleteSamplers");
+ glad_glGenSamplers = (PFNGLGENSAMPLERSPROC) load(userptr, "glGenSamplers");
+ glad_glGetFragDataIndex = (PFNGLGETFRAGDATAINDEXPROC) load(userptr, "glGetFragDataIndex");
+ glad_glGetQueryObjecti64v = (PFNGLGETQUERYOBJECTI64VPROC) load(userptr, "glGetQueryObjecti64v");
+ glad_glGetQueryObjectui64v = (PFNGLGETQUERYOBJECTUI64VPROC) load(userptr, "glGetQueryObjectui64v");
+ glad_glGetSamplerParameterIiv = (PFNGLGETSAMPLERPARAMETERIIVPROC) load(userptr, "glGetSamplerParameterIiv");
+ glad_glGetSamplerParameterIuiv = (PFNGLGETSAMPLERPARAMETERIUIVPROC) load(userptr, "glGetSamplerParameterIuiv");
+ glad_glGetSamplerParameterfv = (PFNGLGETSAMPLERPARAMETERFVPROC) load(userptr, "glGetSamplerParameterfv");
+ glad_glGetSamplerParameteriv = (PFNGLGETSAMPLERPARAMETERIVPROC) load(userptr, "glGetSamplerParameteriv");
+ glad_glIsSampler = (PFNGLISSAMPLERPROC) load(userptr, "glIsSampler");
+ glad_glMultiTexCoordP1ui = (PFNGLMULTITEXCOORDP1UIPROC) load(userptr, "glMultiTexCoordP1ui");
+ glad_glMultiTexCoordP1uiv = (PFNGLMULTITEXCOORDP1UIVPROC) load(userptr, "glMultiTexCoordP1uiv");
+ glad_glMultiTexCoordP2ui = (PFNGLMULTITEXCOORDP2UIPROC) load(userptr, "glMultiTexCoordP2ui");
+ glad_glMultiTexCoordP2uiv = (PFNGLMULTITEXCOORDP2UIVPROC) load(userptr, "glMultiTexCoordP2uiv");
+ glad_glMultiTexCoordP3ui = (PFNGLMULTITEXCOORDP3UIPROC) load(userptr, "glMultiTexCoordP3ui");
+ glad_glMultiTexCoordP3uiv = (PFNGLMULTITEXCOORDP3UIVPROC) load(userptr, "glMultiTexCoordP3uiv");
+ glad_glMultiTexCoordP4ui = (PFNGLMULTITEXCOORDP4UIPROC) load(userptr, "glMultiTexCoordP4ui");
+ glad_glMultiTexCoordP4uiv = (PFNGLMULTITEXCOORDP4UIVPROC) load(userptr, "glMultiTexCoordP4uiv");
+ glad_glNormalP3ui = (PFNGLNORMALP3UIPROC) load(userptr, "glNormalP3ui");
+ glad_glNormalP3uiv = (PFNGLNORMALP3UIVPROC) load(userptr, "glNormalP3uiv");
+ glad_glQueryCounter = (PFNGLQUERYCOUNTERPROC) load(userptr, "glQueryCounter");
+ glad_glSamplerParameterIiv = (PFNGLSAMPLERPARAMETERIIVPROC) load(userptr, "glSamplerParameterIiv");
+ glad_glSamplerParameterIuiv = (PFNGLSAMPLERPARAMETERIUIVPROC) load(userptr, "glSamplerParameterIuiv");
+ glad_glSamplerParameterf = (PFNGLSAMPLERPARAMETERFPROC) load(userptr, "glSamplerParameterf");
+ glad_glSamplerParameterfv = (PFNGLSAMPLERPARAMETERFVPROC) load(userptr, "glSamplerParameterfv");
+ glad_glSamplerParameteri = (PFNGLSAMPLERPARAMETERIPROC) load(userptr, "glSamplerParameteri");
+ glad_glSamplerParameteriv = (PFNGLSAMPLERPARAMETERIVPROC) load(userptr, "glSamplerParameteriv");
+ glad_glSecondaryColorP3ui = (PFNGLSECONDARYCOLORP3UIPROC) load(userptr, "glSecondaryColorP3ui");
+ glad_glSecondaryColorP3uiv = (PFNGLSECONDARYCOLORP3UIVPROC) load(userptr, "glSecondaryColorP3uiv");
+ glad_glTexCoordP1ui = (PFNGLTEXCOORDP1UIPROC) load(userptr, "glTexCoordP1ui");
+ glad_glTexCoordP1uiv = (PFNGLTEXCOORDP1UIVPROC) load(userptr, "glTexCoordP1uiv");
+ glad_glTexCoordP2ui = (PFNGLTEXCOORDP2UIPROC) load(userptr, "glTexCoordP2ui");
+ glad_glTexCoordP2uiv = (PFNGLTEXCOORDP2UIVPROC) load(userptr, "glTexCoordP2uiv");
+ glad_glTexCoordP3ui = (PFNGLTEXCOORDP3UIPROC) load(userptr, "glTexCoordP3ui");
+ glad_glTexCoordP3uiv = (PFNGLTEXCOORDP3UIVPROC) load(userptr, "glTexCoordP3uiv");
+ glad_glTexCoordP4ui = (PFNGLTEXCOORDP4UIPROC) load(userptr, "glTexCoordP4ui");
+ glad_glTexCoordP4uiv = (PFNGLTEXCOORDP4UIVPROC) load(userptr, "glTexCoordP4uiv");
+ glad_glVertexAttribDivisor = (PFNGLVERTEXATTRIBDIVISORPROC) load(userptr, "glVertexAttribDivisor");
+ glad_glVertexAttribP1ui = (PFNGLVERTEXATTRIBP1UIPROC) load(userptr, "glVertexAttribP1ui");
+ glad_glVertexAttribP1uiv = (PFNGLVERTEXATTRIBP1UIVPROC) load(userptr, "glVertexAttribP1uiv");
+ glad_glVertexAttribP2ui = (PFNGLVERTEXATTRIBP2UIPROC) load(userptr, "glVertexAttribP2ui");
+ glad_glVertexAttribP2uiv = (PFNGLVERTEXATTRIBP2UIVPROC) load(userptr, "glVertexAttribP2uiv");
+ glad_glVertexAttribP3ui = (PFNGLVERTEXATTRIBP3UIPROC) load(userptr, "glVertexAttribP3ui");
+ glad_glVertexAttribP3uiv = (PFNGLVERTEXATTRIBP3UIVPROC) load(userptr, "glVertexAttribP3uiv");
+ glad_glVertexAttribP4ui = (PFNGLVERTEXATTRIBP4UIPROC) load(userptr, "glVertexAttribP4ui");
+ glad_glVertexAttribP4uiv = (PFNGLVERTEXATTRIBP4UIVPROC) load(userptr, "glVertexAttribP4uiv");
+ glad_glVertexP2ui = (PFNGLVERTEXP2UIPROC) load(userptr, "glVertexP2ui");
+ glad_glVertexP2uiv = (PFNGLVERTEXP2UIVPROC) load(userptr, "glVertexP2uiv");
+ glad_glVertexP3ui = (PFNGLVERTEXP3UIPROC) load(userptr, "glVertexP3ui");
+ glad_glVertexP3uiv = (PFNGLVERTEXP3UIVPROC) load(userptr, "glVertexP3uiv");
+ glad_glVertexP4ui = (PFNGLVERTEXP4UIPROC) load(userptr, "glVertexP4ui");
+ glad_glVertexP4uiv = (PFNGLVERTEXP4UIVPROC) load(userptr, "glVertexP4uiv");
+}
+static void glad_gl_load_GL_ARB_debug_output( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_ARB_debug_output) return;
+ glad_glDebugMessageCallbackARB = (PFNGLDEBUGMESSAGECALLBACKARBPROC) load(userptr, "glDebugMessageCallbackARB");
+ glad_glDebugMessageControlARB = (PFNGLDEBUGMESSAGECONTROLARBPROC) load(userptr, "glDebugMessageControlARB");
+ glad_glDebugMessageInsertARB = (PFNGLDEBUGMESSAGEINSERTARBPROC) load(userptr, "glDebugMessageInsertARB");
+ glad_glGetDebugMessageLogARB = (PFNGLGETDEBUGMESSAGELOGARBPROC) load(userptr, "glGetDebugMessageLogARB");
+}
+static void glad_gl_load_GL_ARB_framebuffer_object( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_ARB_framebuffer_object) return;
+ glad_glBindFramebuffer = (PFNGLBINDFRAMEBUFFERPROC) load(userptr, "glBindFramebuffer");
+ glad_glBindRenderbuffer = (PFNGLBINDRENDERBUFFERPROC) load(userptr, "glBindRenderbuffer");
+ glad_glBlitFramebuffer = (PFNGLBLITFRAMEBUFFERPROC) load(userptr, "glBlitFramebuffer");
+ glad_glCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSPROC) load(userptr, "glCheckFramebufferStatus");
+ glad_glDeleteFramebuffers = (PFNGLDELETEFRAMEBUFFERSPROC) load(userptr, "glDeleteFramebuffers");
+ glad_glDeleteRenderbuffers = (PFNGLDELETERENDERBUFFERSPROC) load(userptr, "glDeleteRenderbuffers");
+ glad_glFramebufferRenderbuffer = (PFNGLFRAMEBUFFERRENDERBUFFERPROC) load(userptr, "glFramebufferRenderbuffer");
+ glad_glFramebufferTexture1D = (PFNGLFRAMEBUFFERTEXTURE1DPROC) load(userptr, "glFramebufferTexture1D");
+ glad_glFramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DPROC) load(userptr, "glFramebufferTexture2D");
+ glad_glFramebufferTexture3D = (PFNGLFRAMEBUFFERTEXTURE3DPROC) load(userptr, "glFramebufferTexture3D");
+ glad_glFramebufferTextureLayer = (PFNGLFRAMEBUFFERTEXTURELAYERPROC) load(userptr, "glFramebufferTextureLayer");
+ glad_glGenFramebuffers = (PFNGLGENFRAMEBUFFERSPROC) load(userptr, "glGenFramebuffers");
+ glad_glGenRenderbuffers = (PFNGLGENRENDERBUFFERSPROC) load(userptr, "glGenRenderbuffers");
+ glad_glGenerateMipmap = (PFNGLGENERATEMIPMAPPROC) load(userptr, "glGenerateMipmap");
+ glad_glGetFramebufferAttachmentParameteriv = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC) load(userptr, "glGetFramebufferAttachmentParameteriv");
+ glad_glGetRenderbufferParameteriv = (PFNGLGETRENDERBUFFERPARAMETERIVPROC) load(userptr, "glGetRenderbufferParameteriv");
+ glad_glIsFramebuffer = (PFNGLISFRAMEBUFFERPROC) load(userptr, "glIsFramebuffer");
+ glad_glIsRenderbuffer = (PFNGLISRENDERBUFFERPROC) load(userptr, "glIsRenderbuffer");
+ glad_glRenderbufferStorage = (PFNGLRENDERBUFFERSTORAGEPROC) load(userptr, "glRenderbufferStorage");
+ glad_glRenderbufferStorageMultisample = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC) load(userptr, "glRenderbufferStorageMultisample");
+}
+static void glad_gl_load_GL_EXT_framebuffer_blit( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_EXT_framebuffer_blit) return;
+ glad_glBlitFramebufferEXT = (PFNGLBLITFRAMEBUFFEREXTPROC) load(userptr, "glBlitFramebufferEXT");
+}
+static void glad_gl_load_GL_EXT_framebuffer_multisample( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_EXT_framebuffer_multisample) return;
+ glad_glRenderbufferStorageMultisampleEXT = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) load(userptr, "glRenderbufferStorageMultisampleEXT");
+}
+static void glad_gl_load_GL_EXT_framebuffer_object( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_EXT_framebuffer_object) return;
+ glad_glBindFramebufferEXT = (PFNGLBINDFRAMEBUFFEREXTPROC) load(userptr, "glBindFramebufferEXT");
+ glad_glBindRenderbufferEXT = (PFNGLBINDRENDERBUFFEREXTPROC) load(userptr, "glBindRenderbufferEXT");
+ glad_glCheckFramebufferStatusEXT = (PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC) load(userptr, "glCheckFramebufferStatusEXT");
+ glad_glDeleteFramebuffersEXT = (PFNGLDELETEFRAMEBUFFERSEXTPROC) load(userptr, "glDeleteFramebuffersEXT");
+ glad_glDeleteRenderbuffersEXT = (PFNGLDELETERENDERBUFFERSEXTPROC) load(userptr, "glDeleteRenderbuffersEXT");
+ glad_glFramebufferRenderbufferEXT = (PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC) load(userptr, "glFramebufferRenderbufferEXT");
+ glad_glFramebufferTexture1DEXT = (PFNGLFRAMEBUFFERTEXTURE1DEXTPROC) load(userptr, "glFramebufferTexture1DEXT");
+ glad_glFramebufferTexture2DEXT = (PFNGLFRAMEBUFFERTEXTURE2DEXTPROC) load(userptr, "glFramebufferTexture2DEXT");
+ glad_glFramebufferTexture3DEXT = (PFNGLFRAMEBUFFERTEXTURE3DEXTPROC) load(userptr, "glFramebufferTexture3DEXT");
+ glad_glGenFramebuffersEXT = (PFNGLGENFRAMEBUFFERSEXTPROC) load(userptr, "glGenFramebuffersEXT");
+ glad_glGenRenderbuffersEXT = (PFNGLGENRENDERBUFFERSEXTPROC) load(userptr, "glGenRenderbuffersEXT");
+ glad_glGenerateMipmapEXT = (PFNGLGENERATEMIPMAPEXTPROC) load(userptr, "glGenerateMipmapEXT");
+ glad_glGetFramebufferAttachmentParameterivEXT = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC) load(userptr, "glGetFramebufferAttachmentParameterivEXT");
+ glad_glGetRenderbufferParameterivEXT = (PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC) load(userptr, "glGetRenderbufferParameterivEXT");
+ glad_glIsFramebufferEXT = (PFNGLISFRAMEBUFFEREXTPROC) load(userptr, "glIsFramebufferEXT");
+ glad_glIsRenderbufferEXT = (PFNGLISRENDERBUFFEREXTPROC) load(userptr, "glIsRenderbufferEXT");
+ glad_glRenderbufferStorageEXT = (PFNGLRENDERBUFFERSTORAGEEXTPROC) load(userptr, "glRenderbufferStorageEXT");
+}
+static void glad_gl_load_GL_OVR_multiview( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_OVR_multiview) return;
+ glad_glFramebufferTextureMultiviewOVR = (PFNGLFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC) load(userptr, "glFramebufferTextureMultiviewOVR");
+}
+
+
+
+#if defined(GL_ES_VERSION_3_0) || defined(GL_VERSION_3_0)
+#define GLAD_GL_IS_SOME_NEW_VERSION 1
+#else
+#define GLAD_GL_IS_SOME_NEW_VERSION 0
+#endif
+
+static int glad_gl_get_extensions( int version, const char **out_exts, unsigned int *out_num_exts_i, char ***out_exts_i) {
+#if GLAD_GL_IS_SOME_NEW_VERSION
+ if(GLAD_VERSION_MAJOR(version) < 3) {
+#else
+ GLAD_UNUSED(version);
+ GLAD_UNUSED(out_num_exts_i);
+ GLAD_UNUSED(out_exts_i);
+#endif
+ if (glad_glGetString == NULL) {
+ return 0;
+ }
+ *out_exts = (const char *)glad_glGetString(GL_EXTENSIONS);
+#if GLAD_GL_IS_SOME_NEW_VERSION
+ } else {
+ unsigned int index = 0;
+ unsigned int num_exts_i = 0;
+ char **exts_i = NULL;
+ if (glad_glGetStringi == NULL || glad_glGetIntegerv == NULL) {
+ return 0;
+ }
+ glad_glGetIntegerv(GL_NUM_EXTENSIONS, (int*) &num_exts_i);
+ if (num_exts_i > 0) {
+ exts_i = (char **) malloc(num_exts_i * (sizeof *exts_i));
+ }
+ if (exts_i == NULL) {
+ return 0;
+ }
+ for(index = 0; index < num_exts_i; index++) {
+ const char *gl_str_tmp = (const char*) glad_glGetStringi(GL_EXTENSIONS, index);
+ size_t len = strlen(gl_str_tmp) + 1;
+
+ char *local_str = (char*) malloc(len * sizeof(char));
+ if(local_str != NULL) {
+ memcpy(local_str, gl_str_tmp, len * sizeof(char));
+ }
+
+ exts_i[index] = local_str;
+ }
+
+ *out_num_exts_i = num_exts_i;
+ *out_exts_i = exts_i;
+ }
+#endif
+ return 1;
+}
+static void glad_gl_free_extensions(char **exts_i, unsigned int num_exts_i) {
+ if (exts_i != NULL) {
+ unsigned int index;
+ for(index = 0; index < num_exts_i; index++) {
+ free((void *) (exts_i[index]));
+ }
+ free((void *)exts_i);
+ exts_i = NULL;
+ }
+}
+static int glad_gl_has_extension(int version, const char *exts, unsigned int num_exts_i, char **exts_i, const char *ext) {
+ if(GLAD_VERSION_MAJOR(version) < 3 || !GLAD_GL_IS_SOME_NEW_VERSION) {
+ const char *extensions;
+ const char *loc;
+ const char *terminator;
+ extensions = exts;
+ if(extensions == NULL || ext == NULL) {
+ return 0;
+ }
+ while(1) {
+ loc = strstr(extensions, ext);
+ if(loc == NULL) {
+ return 0;
+ }
+ terminator = loc + strlen(ext);
+ if((loc == extensions || *(loc - 1) == ' ') &&
+ (*terminator == ' ' || *terminator == '\0')) {
+ return 1;
+ }
+ extensions = terminator;
+ }
+ } else {
+ unsigned int index;
+ for(index = 0; index < num_exts_i; index++) {
+ const char *e = exts_i[index];
+ if(strcmp(e, ext) == 0) {
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+static GLADapiproc glad_gl_get_proc_from_userptr(void *userptr, const char* name) {
+ return (GLAD_GNUC_EXTENSION (GLADapiproc (*)(const char *name)) userptr)(name);
+}
+
+static int glad_gl_find_extensions_gl( int version) {
+ const char *exts = NULL;
+ unsigned int num_exts_i = 0;
+ char **exts_i = NULL;
+ if (!glad_gl_get_extensions(version, &exts, &num_exts_i, &exts_i)) return 0;
+
+ GLAD_GL_ARB_debug_output = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_debug_output");
+ GLAD_GL_ARB_framebuffer_object = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_framebuffer_object");
+ GLAD_GL_EXT_framebuffer_blit = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_framebuffer_blit");
+ GLAD_GL_EXT_framebuffer_multisample = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_framebuffer_multisample");
+ GLAD_GL_EXT_framebuffer_object = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_framebuffer_object");
+ GLAD_GL_OVR_multiview = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OVR_multiview");
+ GLAD_GL_OVR_multiview2 = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OVR_multiview2");
+
+ glad_gl_free_extensions(exts_i, num_exts_i);
+
+ return 1;
+}
+
+static int glad_gl_find_core_gl(void) {
+ int i;
+ const char* version;
+ const char* prefixes[] = {
+ "OpenGL ES-CM ",
+ "OpenGL ES-CL ",
+ "OpenGL ES ",
+ "OpenGL SC ",
+ NULL
+ };
+ int major = 0;
+ int minor = 0;
+ version = (const char*) glad_glGetString(GL_VERSION);
+ if (!version) return 0;
+ for (i = 0; prefixes[i]; i++) {
+ const size_t length = strlen(prefixes[i]);
+ if (strncmp(version, prefixes[i], length) == 0) {
+ version += length;
+ break;
+ }
+ }
+
+ GLAD_IMPL_UTIL_SSCANF(version, "%d.%d", &major, &minor);
+
+ GLAD_GL_VERSION_1_0 = (major == 1 && minor >= 0) || major > 1;
+ GLAD_GL_VERSION_1_1 = (major == 1 && minor >= 1) || major > 1;
+ GLAD_GL_VERSION_1_2 = (major == 1 && minor >= 2) || major > 1;
+ GLAD_GL_VERSION_1_3 = (major == 1 && minor >= 3) || major > 1;
+ GLAD_GL_VERSION_1_4 = (major == 1 && minor >= 4) || major > 1;
+ GLAD_GL_VERSION_1_5 = (major == 1 && minor >= 5) || major > 1;
+ GLAD_GL_VERSION_2_0 = (major == 2 && minor >= 0) || major > 2;
+ GLAD_GL_VERSION_2_1 = (major == 2 && minor >= 1) || major > 2;
+ GLAD_GL_VERSION_3_0 = (major == 3 && minor >= 0) || major > 3;
+ GLAD_GL_VERSION_3_1 = (major == 3 && minor >= 1) || major > 3;
+ GLAD_GL_VERSION_3_2 = (major == 3 && minor >= 2) || major > 3;
+ GLAD_GL_VERSION_3_3 = (major == 3 && minor >= 3) || major > 3;
+
+ return GLAD_MAKE_VERSION(major, minor);
+}
+
+int gladLoadGLUserPtr( GLADuserptrloadfunc load, void *userptr) {
+ int version;
+
+ glad_glGetString = (PFNGLGETSTRINGPROC) load(userptr, "glGetString");
+ if(glad_glGetString == NULL) return 0;
+ if(glad_glGetString(GL_VERSION) == NULL) return 0;
+ version = glad_gl_find_core_gl();
+
+ glad_gl_load_GL_VERSION_1_0(load, userptr);
+ glad_gl_load_GL_VERSION_1_1(load, userptr);
+ glad_gl_load_GL_VERSION_1_2(load, userptr);
+ glad_gl_load_GL_VERSION_1_3(load, userptr);
+ glad_gl_load_GL_VERSION_1_4(load, userptr);
+ glad_gl_load_GL_VERSION_1_5(load, userptr);
+ glad_gl_load_GL_VERSION_2_0(load, userptr);
+ glad_gl_load_GL_VERSION_2_1(load, userptr);
+ glad_gl_load_GL_VERSION_3_0(load, userptr);
+ glad_gl_load_GL_VERSION_3_1(load, userptr);
+ glad_gl_load_GL_VERSION_3_2(load, userptr);
+ glad_gl_load_GL_VERSION_3_3(load, userptr);
+
+ if (!glad_gl_find_extensions_gl(version)) return 0;
+ glad_gl_load_GL_ARB_debug_output(load, userptr);
+ glad_gl_load_GL_ARB_framebuffer_object(load, userptr);
+ glad_gl_load_GL_EXT_framebuffer_blit(load, userptr);
+ glad_gl_load_GL_EXT_framebuffer_multisample(load, userptr);
+ glad_gl_load_GL_EXT_framebuffer_object(load, userptr);
+ glad_gl_load_GL_OVR_multiview(load, userptr);
+
+
+
+ return version;
+}
+
+
+int gladLoadGL( GLADloadfunc load) {
+ return gladLoadGLUserPtr( glad_gl_get_proc_from_userptr, GLAD_GNUC_EXTENSION (void*) load);
+}
+
+
+
+
+
+#ifdef GLAD_GL
+
+#ifndef GLAD_LOADER_LIBRARY_C_
+#define GLAD_LOADER_LIBRARY_C_
+
+#include <stddef.h>
+#include <stdlib.h>
+
+#if GLAD_PLATFORM_WIN32
+#include <windows.h>
+#else
+#include <dlfcn.h>
+#endif
+
+
+static void* glad_get_dlopen_handle(const char *lib_names[], int length) {
+ void *handle = NULL;
+ int i;
+
+ for (i = 0; i < length; ++i) {
+#if GLAD_PLATFORM_WIN32
+ #if GLAD_PLATFORM_UWP
+ size_t buffer_size = (strlen(lib_names[i]) + 1) * sizeof(WCHAR);
+ LPWSTR buffer = (LPWSTR) malloc(buffer_size);
+ if (buffer != NULL) {
+ int ret = MultiByteToWideChar(CP_ACP, 0, lib_names[i], -1, buffer, buffer_size);
+ if (ret != 0) {
+ handle = (void*) LoadPackagedLibrary(buffer, 0);
+ }
+ free((void*) buffer);
+ }
+ #else
+ handle = (void*) LoadLibraryA(lib_names[i]);
+ #endif
+#else
+ handle = dlopen(lib_names[i], RTLD_LAZY | RTLD_LOCAL);
+#endif
+ if (handle != NULL) {
+ return handle;
+ }
+ }
+
+ return NULL;
+}
+
+static void glad_close_dlopen_handle(void* handle) {
+ if (handle != NULL) {
+#if GLAD_PLATFORM_WIN32
+ FreeLibrary((HMODULE) handle);
+#else
+ dlclose(handle);
+#endif
+ }
+}
+
+static GLADapiproc glad_dlsym_handle(void* handle, const char *name) {
+ if (handle == NULL) {
+ return NULL;
+ }
+
+#if GLAD_PLATFORM_WIN32
+ return (GLADapiproc) GetProcAddress((HMODULE) handle, name);
+#else
+ return GLAD_GNUC_EXTENSION (GLADapiproc) dlsym(handle, name);
+#endif
+}
+
+#endif /* GLAD_LOADER_LIBRARY_C_ */
+
+typedef void* (GLAD_API_PTR *GLADglprocaddrfunc)(const char*);
+struct _glad_gl_userptr {
+ void *handle;
+ GLADglprocaddrfunc gl_get_proc_address_ptr;
+};
+
+static GLADapiproc glad_gl_get_proc(void *vuserptr, const char *name) {
+ struct _glad_gl_userptr userptr = *(struct _glad_gl_userptr*) vuserptr;
+ GLADapiproc result = NULL;
+
+ if(userptr.gl_get_proc_address_ptr != NULL) {
+ result = GLAD_GNUC_EXTENSION (GLADapiproc) userptr.gl_get_proc_address_ptr(name);
+ }
+ if(result == NULL) {
+ result = glad_dlsym_handle(userptr.handle, name);
+ }
+
+ return result;
+}
+
+static void* _glad_GL_loader_handle = NULL;
+
+static void* glad_gl_dlopen_handle(void) {
+#if GLAD_PLATFORM_APPLE
+ static const char *NAMES[] = {
+ "../Frameworks/OpenGL.framework/OpenGL",
+ "/Library/Frameworks/OpenGL.framework/OpenGL",
+ "/System/Library/Frameworks/OpenGL.framework/OpenGL",
+ "/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL"
+ };
+#elif GLAD_PLATFORM_WIN32
+ static const char *NAMES[] = {"opengl32.dll"};
+#else
+ static const char *NAMES[] = {
+ #if defined(__CYGWIN__)
+ "libGL-1.so",
+ #endif
+ "libGL.so.1",
+ "libGL.so"
+ };
+#endif
+
+ if (_glad_GL_loader_handle == NULL) {
+ _glad_GL_loader_handle = glad_get_dlopen_handle(NAMES, sizeof(NAMES) / sizeof(NAMES[0]));
+ }
+
+ return _glad_GL_loader_handle;
+}
+
+static struct _glad_gl_userptr glad_gl_build_userptr(void *handle) {
+ struct _glad_gl_userptr userptr;
+
+ userptr.handle = handle;
+#if GLAD_PLATFORM_APPLE || defined(__HAIKU__)
+ userptr.gl_get_proc_address_ptr = NULL;
+#elif GLAD_PLATFORM_WIN32
+ userptr.gl_get_proc_address_ptr =
+ (GLADglprocaddrfunc) glad_dlsym_handle(handle, "wglGetProcAddress");
+#else
+ userptr.gl_get_proc_address_ptr =
+ (GLADglprocaddrfunc) glad_dlsym_handle(handle, "glXGetProcAddressARB");
+#endif
+
+ return userptr;
+}
+
+int gladLoaderLoadGL(void) {
+ int version = 0;
+ void *handle;
+ int did_load = 0;
+ struct _glad_gl_userptr userptr;
+
+ did_load = _glad_GL_loader_handle == NULL;
+ handle = glad_gl_dlopen_handle();
+ if (handle) {
+ userptr = glad_gl_build_userptr(handle);
+
+ version = gladLoadGLUserPtr(glad_gl_get_proc, &userptr);
+
+ if (did_load) {
+ gladLoaderUnloadGL();
+ }
+ }
+
+ return version;
+}
+
+
+
+void gladLoaderUnloadGL(void) {
+ if (_glad_GL_loader_handle != NULL) {
+ glad_close_dlopen_handle(_glad_GL_loader_handle);
+ _glad_GL_loader_handle = NULL;
+ }
+}
+
+#endif /* GLAD_GL */
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/thirdparty/glad/glad.c b/thirdparty/glad/glad.c
deleted file mode 100644
index 4b20178ef7..0000000000
--- a/thirdparty/glad/glad.c
+++ /dev/null
@@ -1,1951 +0,0 @@
-/*
-
- OpenGL loader generated by glad 0.1.36 on Sun Sep 4 15:50:32 2022.
-
- Language/Generator: C/C++
- Specification: gl
- APIs: gl=3.3
- Profile: compatibility
- Extensions:
- GL_ARB_debug_output,
- GL_ARB_framebuffer_object,
- GL_EXT_framebuffer_blit,
- GL_EXT_framebuffer_multisample,
- GL_EXT_framebuffer_object,
- GL_OVR_multiview,
- GL_OVR_multiview2
- Loader: True
- Local files: False
- Omit khrplatform: False
- Reproducible: False
-
- Commandline:
- --profile="compatibility" --api="gl=3.3" --generator="c" --spec="gl" --extensions="GL_ARB_debug_output,GL_ARB_framebuffer_object,GL_EXT_framebuffer_blit,GL_EXT_framebuffer_multisample,GL_EXT_framebuffer_object,GL_OVR_multiview,GL_OVR_multiview2"
- Online:
- https://glad.dav1d.de/#profile=compatibility&language=c&specification=gl&loader=on&api=gl%3D3.3&extensions=GL_ARB_debug_output&extensions=GL_ARB_framebuffer_object&extensions=GL_EXT_framebuffer_blit&extensions=GL_EXT_framebuffer_multisample&extensions=GL_EXT_framebuffer_object&extensions=GL_OVR_multiview&extensions=GL_OVR_multiview2
-*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <glad/glad.h>
-
-static void* get_proc(const char *namez);
-
-#if defined(_WIN32) || defined(__CYGWIN__)
-#ifndef _WINDOWS_
-#undef APIENTRY
-#endif
-#include <windows.h>
-static HMODULE libGL;
-
-typedef void* (APIENTRYP PFNWGLGETPROCADDRESSPROC_PRIVATE)(const char*);
-static PFNWGLGETPROCADDRESSPROC_PRIVATE gladGetProcAddressPtr;
-
-#ifdef _MSC_VER
-#ifdef __has_include
- #if __has_include(<winapifamily.h>)
- #define HAVE_WINAPIFAMILY 1
- #endif
-#elif _MSC_VER >= 1700 && !_USING_V110_SDK71_
- #define HAVE_WINAPIFAMILY 1
-#endif
-#endif
-
-#ifdef HAVE_WINAPIFAMILY
- #include <winapifamily.h>
- #if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)
- #define IS_UWP 1
- #endif
-#endif
-
-static
-int open_gl(void) {
-#ifndef IS_UWP
- libGL = LoadLibraryW(L"opengl32.dll");
- if(libGL != NULL) {
- void (* tmp)(void);
- tmp = (void(*)(void)) GetProcAddress(libGL, "wglGetProcAddress");
- gladGetProcAddressPtr = (PFNWGLGETPROCADDRESSPROC_PRIVATE) tmp;
- return gladGetProcAddressPtr != NULL;
- }
-#endif
-
- return 0;
-}
-
-static
-void close_gl(void) {
- if(libGL != NULL) {
- FreeLibrary((HMODULE) libGL);
- libGL = NULL;
- }
-}
-#else
-#include <dlfcn.h>
-static void* libGL;
-
-#if !defined(__APPLE__) && !defined(__HAIKU__)
-typedef void* (APIENTRYP PFNGLXGETPROCADDRESSPROC_PRIVATE)(const char*);
-static PFNGLXGETPROCADDRESSPROC_PRIVATE gladGetProcAddressPtr;
-#endif
-
-static
-int open_gl(void) {
-#ifdef __APPLE__
- static const char *NAMES[] = {
- "../Frameworks/OpenGL.framework/OpenGL",
- "/Library/Frameworks/OpenGL.framework/OpenGL",
- "/System/Library/Frameworks/OpenGL.framework/OpenGL",
- "/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL"
- };
-#else
- static const char *NAMES[] = {"libGL.so.1", "libGL.so"};
-#endif
-
- unsigned int index = 0;
- for(index = 0; index < (sizeof(NAMES) / sizeof(NAMES[0])); index++) {
- libGL = dlopen(NAMES[index], RTLD_NOW | RTLD_GLOBAL);
-
- if(libGL != NULL) {
-#if defined(__APPLE__) || defined(__HAIKU__)
- return 1;
-#else
- gladGetProcAddressPtr = (PFNGLXGETPROCADDRESSPROC_PRIVATE)dlsym(libGL,
- "glXGetProcAddressARB");
- return gladGetProcAddressPtr != NULL;
-#endif
- }
- }
-
- return 0;
-}
-
-static
-void close_gl(void) {
- if(libGL != NULL) {
- dlclose(libGL);
- libGL = NULL;
- }
-}
-#endif
-
-static
-void* get_proc(const char *namez) {
- void* result = NULL;
- if(libGL == NULL) return NULL;
-
-#if !defined(__APPLE__) && !defined(__HAIKU__)
- if(gladGetProcAddressPtr != NULL) {
- result = gladGetProcAddressPtr(namez);
- }
-#endif
- if(result == NULL) {
-#if defined(_WIN32) || defined(__CYGWIN__)
- result = (void*)GetProcAddress((HMODULE) libGL, namez);
-#else
- result = dlsym(libGL, namez);
-#endif
- }
-
- return result;
-}
-
-int gladLoadGL(void) {
- int status = 0;
-
- if(open_gl()) {
- status = gladLoadGLLoader(&get_proc);
- close_gl();
- }
-
- return status;
-}
-
-struct gladGLversionStruct GLVersion = { 0, 0 };
-
-#if defined(GL_ES_VERSION_3_0) || defined(GL_VERSION_3_0)
-#define _GLAD_IS_SOME_NEW_VERSION 1
-#endif
-
-static int max_loaded_major;
-static int max_loaded_minor;
-
-static const char *exts = NULL;
-static int num_exts_i = 0;
-static char **exts_i = NULL;
-
-static int get_exts(void) {
-#ifdef _GLAD_IS_SOME_NEW_VERSION
- if(max_loaded_major < 3) {
-#endif
- exts = (const char *)glGetString(GL_EXTENSIONS);
-#ifdef _GLAD_IS_SOME_NEW_VERSION
- } else {
- unsigned int index;
-
- num_exts_i = 0;
- glGetIntegerv(GL_NUM_EXTENSIONS, &num_exts_i);
- if (num_exts_i > 0) {
- exts_i = (char **)malloc((size_t)num_exts_i * (sizeof *exts_i));
- }
-
- if (exts_i == NULL) {
- return 0;
- }
-
- for(index = 0; index < (unsigned)num_exts_i; index++) {
- const char *gl_str_tmp = (const char*)glGetStringi(GL_EXTENSIONS, index);
- size_t len = strlen(gl_str_tmp);
-
- char *local_str = (char*)malloc((len+1) * sizeof(char));
- if(local_str != NULL) {
- memcpy(local_str, gl_str_tmp, (len+1) * sizeof(char));
- }
- exts_i[index] = local_str;
- }
- }
-#endif
- return 1;
-}
-
-static void free_exts(void) {
- if (exts_i != NULL) {
- int index;
- for(index = 0; index < num_exts_i; index++) {
- free((char *)exts_i[index]);
- }
- free((void *)exts_i);
- exts_i = NULL;
- }
-}
-
-static int has_ext(const char *ext) {
-#ifdef _GLAD_IS_SOME_NEW_VERSION
- if(max_loaded_major < 3) {
-#endif
- const char *extensions;
- const char *loc;
- const char *terminator;
- extensions = exts;
- if(extensions == NULL || ext == NULL) {
- return 0;
- }
-
- while(1) {
- loc = strstr(extensions, ext);
- if(loc == NULL) {
- return 0;
- }
-
- terminator = loc + strlen(ext);
- if((loc == extensions || *(loc - 1) == ' ') &&
- (*terminator == ' ' || *terminator == '\0')) {
- return 1;
- }
- extensions = terminator;
- }
-#ifdef _GLAD_IS_SOME_NEW_VERSION
- } else {
- int index;
- if(exts_i == NULL) return 0;
- for(index = 0; index < num_exts_i; index++) {
- const char *e = exts_i[index];
-
- if(exts_i[index] != NULL && strcmp(e, ext) == 0) {
- return 1;
- }
- }
- }
-#endif
-
- return 0;
-}
-int GLAD_GL_VERSION_1_0 = 0;
-int GLAD_GL_VERSION_1_1 = 0;
-int GLAD_GL_VERSION_1_2 = 0;
-int GLAD_GL_VERSION_1_3 = 0;
-int GLAD_GL_VERSION_1_4 = 0;
-int GLAD_GL_VERSION_1_5 = 0;
-int GLAD_GL_VERSION_2_0 = 0;
-int GLAD_GL_VERSION_2_1 = 0;
-int GLAD_GL_VERSION_3_0 = 0;
-int GLAD_GL_VERSION_3_1 = 0;
-int GLAD_GL_VERSION_3_2 = 0;
-int GLAD_GL_VERSION_3_3 = 0;
-PFNGLACCUMPROC glad_glAccum = NULL;
-PFNGLACTIVETEXTUREPROC glad_glActiveTexture = NULL;
-PFNGLALPHAFUNCPROC glad_glAlphaFunc = NULL;
-PFNGLARETEXTURESRESIDENTPROC glad_glAreTexturesResident = NULL;
-PFNGLARRAYELEMENTPROC glad_glArrayElement = NULL;
-PFNGLATTACHSHADERPROC glad_glAttachShader = NULL;
-PFNGLBEGINPROC glad_glBegin = NULL;
-PFNGLBEGINCONDITIONALRENDERPROC glad_glBeginConditionalRender = NULL;
-PFNGLBEGINQUERYPROC glad_glBeginQuery = NULL;
-PFNGLBEGINTRANSFORMFEEDBACKPROC glad_glBeginTransformFeedback = NULL;
-PFNGLBINDATTRIBLOCATIONPROC glad_glBindAttribLocation = NULL;
-PFNGLBINDBUFFERPROC glad_glBindBuffer = NULL;
-PFNGLBINDBUFFERBASEPROC glad_glBindBufferBase = NULL;
-PFNGLBINDBUFFERRANGEPROC glad_glBindBufferRange = NULL;
-PFNGLBINDFRAGDATALOCATIONPROC glad_glBindFragDataLocation = NULL;
-PFNGLBINDFRAGDATALOCATIONINDEXEDPROC glad_glBindFragDataLocationIndexed = NULL;
-PFNGLBINDFRAMEBUFFERPROC glad_glBindFramebuffer = NULL;
-PFNGLBINDRENDERBUFFERPROC glad_glBindRenderbuffer = NULL;
-PFNGLBINDSAMPLERPROC glad_glBindSampler = NULL;
-PFNGLBINDTEXTUREPROC glad_glBindTexture = NULL;
-PFNGLBINDVERTEXARRAYPROC glad_glBindVertexArray = NULL;
-PFNGLBITMAPPROC glad_glBitmap = NULL;
-PFNGLBLENDCOLORPROC glad_glBlendColor = NULL;
-PFNGLBLENDEQUATIONPROC glad_glBlendEquation = NULL;
-PFNGLBLENDEQUATIONSEPARATEPROC glad_glBlendEquationSeparate = NULL;
-PFNGLBLENDFUNCPROC glad_glBlendFunc = NULL;
-PFNGLBLENDFUNCSEPARATEPROC glad_glBlendFuncSeparate = NULL;
-PFNGLBLITFRAMEBUFFERPROC glad_glBlitFramebuffer = NULL;
-PFNGLBUFFERDATAPROC glad_glBufferData = NULL;
-PFNGLBUFFERSUBDATAPROC glad_glBufferSubData = NULL;
-PFNGLCALLLISTPROC glad_glCallList = NULL;
-PFNGLCALLLISTSPROC glad_glCallLists = NULL;
-PFNGLCHECKFRAMEBUFFERSTATUSPROC glad_glCheckFramebufferStatus = NULL;
-PFNGLCLAMPCOLORPROC glad_glClampColor = NULL;
-PFNGLCLEARPROC glad_glClear = NULL;
-PFNGLCLEARACCUMPROC glad_glClearAccum = NULL;
-PFNGLCLEARBUFFERFIPROC glad_glClearBufferfi = NULL;
-PFNGLCLEARBUFFERFVPROC glad_glClearBufferfv = NULL;
-PFNGLCLEARBUFFERIVPROC glad_glClearBufferiv = NULL;
-PFNGLCLEARBUFFERUIVPROC glad_glClearBufferuiv = NULL;
-PFNGLCLEARCOLORPROC glad_glClearColor = NULL;
-PFNGLCLEARDEPTHPROC glad_glClearDepth = NULL;
-PFNGLCLEARINDEXPROC glad_glClearIndex = NULL;
-PFNGLCLEARSTENCILPROC glad_glClearStencil = NULL;
-PFNGLCLIENTACTIVETEXTUREPROC glad_glClientActiveTexture = NULL;
-PFNGLCLIENTWAITSYNCPROC glad_glClientWaitSync = NULL;
-PFNGLCLIPPLANEPROC glad_glClipPlane = NULL;
-PFNGLCOLOR3BPROC glad_glColor3b = NULL;
-PFNGLCOLOR3BVPROC glad_glColor3bv = NULL;
-PFNGLCOLOR3DPROC glad_glColor3d = NULL;
-PFNGLCOLOR3DVPROC glad_glColor3dv = NULL;
-PFNGLCOLOR3FPROC glad_glColor3f = NULL;
-PFNGLCOLOR3FVPROC glad_glColor3fv = NULL;
-PFNGLCOLOR3IPROC glad_glColor3i = NULL;
-PFNGLCOLOR3IVPROC glad_glColor3iv = NULL;
-PFNGLCOLOR3SPROC glad_glColor3s = NULL;
-PFNGLCOLOR3SVPROC glad_glColor3sv = NULL;
-PFNGLCOLOR3UBPROC glad_glColor3ub = NULL;
-PFNGLCOLOR3UBVPROC glad_glColor3ubv = NULL;
-PFNGLCOLOR3UIPROC glad_glColor3ui = NULL;
-PFNGLCOLOR3UIVPROC glad_glColor3uiv = NULL;
-PFNGLCOLOR3USPROC glad_glColor3us = NULL;
-PFNGLCOLOR3USVPROC glad_glColor3usv = NULL;
-PFNGLCOLOR4BPROC glad_glColor4b = NULL;
-PFNGLCOLOR4BVPROC glad_glColor4bv = NULL;
-PFNGLCOLOR4DPROC glad_glColor4d = NULL;
-PFNGLCOLOR4DVPROC glad_glColor4dv = NULL;
-PFNGLCOLOR4FPROC glad_glColor4f = NULL;
-PFNGLCOLOR4FVPROC glad_glColor4fv = NULL;
-PFNGLCOLOR4IPROC glad_glColor4i = NULL;
-PFNGLCOLOR4IVPROC glad_glColor4iv = NULL;
-PFNGLCOLOR4SPROC glad_glColor4s = NULL;
-PFNGLCOLOR4SVPROC glad_glColor4sv = NULL;
-PFNGLCOLOR4UBPROC glad_glColor4ub = NULL;
-PFNGLCOLOR4UBVPROC glad_glColor4ubv = NULL;
-PFNGLCOLOR4UIPROC glad_glColor4ui = NULL;
-PFNGLCOLOR4UIVPROC glad_glColor4uiv = NULL;
-PFNGLCOLOR4USPROC glad_glColor4us = NULL;
-PFNGLCOLOR4USVPROC glad_glColor4usv = NULL;
-PFNGLCOLORMASKPROC glad_glColorMask = NULL;
-PFNGLCOLORMASKIPROC glad_glColorMaski = NULL;
-PFNGLCOLORMATERIALPROC glad_glColorMaterial = NULL;
-PFNGLCOLORP3UIPROC glad_glColorP3ui = NULL;
-PFNGLCOLORP3UIVPROC glad_glColorP3uiv = NULL;
-PFNGLCOLORP4UIPROC glad_glColorP4ui = NULL;
-PFNGLCOLORP4UIVPROC glad_glColorP4uiv = NULL;
-PFNGLCOLORPOINTERPROC glad_glColorPointer = NULL;
-PFNGLCOMPILESHADERPROC glad_glCompileShader = NULL;
-PFNGLCOMPRESSEDTEXIMAGE1DPROC glad_glCompressedTexImage1D = NULL;
-PFNGLCOMPRESSEDTEXIMAGE2DPROC glad_glCompressedTexImage2D = NULL;
-PFNGLCOMPRESSEDTEXIMAGE3DPROC glad_glCompressedTexImage3D = NULL;
-PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC glad_glCompressedTexSubImage1D = NULL;
-PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC glad_glCompressedTexSubImage2D = NULL;
-PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC glad_glCompressedTexSubImage3D = NULL;
-PFNGLCOPYBUFFERSUBDATAPROC glad_glCopyBufferSubData = NULL;
-PFNGLCOPYPIXELSPROC glad_glCopyPixels = NULL;
-PFNGLCOPYTEXIMAGE1DPROC glad_glCopyTexImage1D = NULL;
-PFNGLCOPYTEXIMAGE2DPROC glad_glCopyTexImage2D = NULL;
-PFNGLCOPYTEXSUBIMAGE1DPROC glad_glCopyTexSubImage1D = NULL;
-PFNGLCOPYTEXSUBIMAGE2DPROC glad_glCopyTexSubImage2D = NULL;
-PFNGLCOPYTEXSUBIMAGE3DPROC glad_glCopyTexSubImage3D = NULL;
-PFNGLCREATEPROGRAMPROC glad_glCreateProgram = NULL;
-PFNGLCREATESHADERPROC glad_glCreateShader = NULL;
-PFNGLCULLFACEPROC glad_glCullFace = NULL;
-PFNGLDELETEBUFFERSPROC glad_glDeleteBuffers = NULL;
-PFNGLDELETEFRAMEBUFFERSPROC glad_glDeleteFramebuffers = NULL;
-PFNGLDELETELISTSPROC glad_glDeleteLists = NULL;
-PFNGLDELETEPROGRAMPROC glad_glDeleteProgram = NULL;
-PFNGLDELETEQUERIESPROC glad_glDeleteQueries = NULL;
-PFNGLDELETERENDERBUFFERSPROC glad_glDeleteRenderbuffers = NULL;
-PFNGLDELETESAMPLERSPROC glad_glDeleteSamplers = NULL;
-PFNGLDELETESHADERPROC glad_glDeleteShader = NULL;
-PFNGLDELETESYNCPROC glad_glDeleteSync = NULL;
-PFNGLDELETETEXTURESPROC glad_glDeleteTextures = NULL;
-PFNGLDELETEVERTEXARRAYSPROC glad_glDeleteVertexArrays = NULL;
-PFNGLDEPTHFUNCPROC glad_glDepthFunc = NULL;
-PFNGLDEPTHMASKPROC glad_glDepthMask = NULL;
-PFNGLDEPTHRANGEPROC glad_glDepthRange = NULL;
-PFNGLDETACHSHADERPROC glad_glDetachShader = NULL;
-PFNGLDISABLEPROC glad_glDisable = NULL;
-PFNGLDISABLECLIENTSTATEPROC glad_glDisableClientState = NULL;
-PFNGLDISABLEVERTEXATTRIBARRAYPROC glad_glDisableVertexAttribArray = NULL;
-PFNGLDISABLEIPROC glad_glDisablei = NULL;
-PFNGLDRAWARRAYSPROC glad_glDrawArrays = NULL;
-PFNGLDRAWARRAYSINSTANCEDPROC glad_glDrawArraysInstanced = NULL;
-PFNGLDRAWBUFFERPROC glad_glDrawBuffer = NULL;
-PFNGLDRAWBUFFERSPROC glad_glDrawBuffers = NULL;
-PFNGLDRAWELEMENTSPROC glad_glDrawElements = NULL;
-PFNGLDRAWELEMENTSBASEVERTEXPROC glad_glDrawElementsBaseVertex = NULL;
-PFNGLDRAWELEMENTSINSTANCEDPROC glad_glDrawElementsInstanced = NULL;
-PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC glad_glDrawElementsInstancedBaseVertex = NULL;
-PFNGLDRAWPIXELSPROC glad_glDrawPixels = NULL;
-PFNGLDRAWRANGEELEMENTSPROC glad_glDrawRangeElements = NULL;
-PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC glad_glDrawRangeElementsBaseVertex = NULL;
-PFNGLEDGEFLAGPROC glad_glEdgeFlag = NULL;
-PFNGLEDGEFLAGPOINTERPROC glad_glEdgeFlagPointer = NULL;
-PFNGLEDGEFLAGVPROC glad_glEdgeFlagv = NULL;
-PFNGLENABLEPROC glad_glEnable = NULL;
-PFNGLENABLECLIENTSTATEPROC glad_glEnableClientState = NULL;
-PFNGLENABLEVERTEXATTRIBARRAYPROC glad_glEnableVertexAttribArray = NULL;
-PFNGLENABLEIPROC glad_glEnablei = NULL;
-PFNGLENDPROC glad_glEnd = NULL;
-PFNGLENDCONDITIONALRENDERPROC glad_glEndConditionalRender = NULL;
-PFNGLENDLISTPROC glad_glEndList = NULL;
-PFNGLENDQUERYPROC glad_glEndQuery = NULL;
-PFNGLENDTRANSFORMFEEDBACKPROC glad_glEndTransformFeedback = NULL;
-PFNGLEVALCOORD1DPROC glad_glEvalCoord1d = NULL;
-PFNGLEVALCOORD1DVPROC glad_glEvalCoord1dv = NULL;
-PFNGLEVALCOORD1FPROC glad_glEvalCoord1f = NULL;
-PFNGLEVALCOORD1FVPROC glad_glEvalCoord1fv = NULL;
-PFNGLEVALCOORD2DPROC glad_glEvalCoord2d = NULL;
-PFNGLEVALCOORD2DVPROC glad_glEvalCoord2dv = NULL;
-PFNGLEVALCOORD2FPROC glad_glEvalCoord2f = NULL;
-PFNGLEVALCOORD2FVPROC glad_glEvalCoord2fv = NULL;
-PFNGLEVALMESH1PROC glad_glEvalMesh1 = NULL;
-PFNGLEVALMESH2PROC glad_glEvalMesh2 = NULL;
-PFNGLEVALPOINT1PROC glad_glEvalPoint1 = NULL;
-PFNGLEVALPOINT2PROC glad_glEvalPoint2 = NULL;
-PFNGLFEEDBACKBUFFERPROC glad_glFeedbackBuffer = NULL;
-PFNGLFENCESYNCPROC glad_glFenceSync = NULL;
-PFNGLFINISHPROC glad_glFinish = NULL;
-PFNGLFLUSHPROC glad_glFlush = NULL;
-PFNGLFLUSHMAPPEDBUFFERRANGEPROC glad_glFlushMappedBufferRange = NULL;
-PFNGLFOGCOORDPOINTERPROC glad_glFogCoordPointer = NULL;
-PFNGLFOGCOORDDPROC glad_glFogCoordd = NULL;
-PFNGLFOGCOORDDVPROC glad_glFogCoorddv = NULL;
-PFNGLFOGCOORDFPROC glad_glFogCoordf = NULL;
-PFNGLFOGCOORDFVPROC glad_glFogCoordfv = NULL;
-PFNGLFOGFPROC glad_glFogf = NULL;
-PFNGLFOGFVPROC glad_glFogfv = NULL;
-PFNGLFOGIPROC glad_glFogi = NULL;
-PFNGLFOGIVPROC glad_glFogiv = NULL;
-PFNGLFRAMEBUFFERRENDERBUFFERPROC glad_glFramebufferRenderbuffer = NULL;
-PFNGLFRAMEBUFFERTEXTUREPROC glad_glFramebufferTexture = NULL;
-PFNGLFRAMEBUFFERTEXTURE1DPROC glad_glFramebufferTexture1D = NULL;
-PFNGLFRAMEBUFFERTEXTURE2DPROC glad_glFramebufferTexture2D = NULL;
-PFNGLFRAMEBUFFERTEXTURE3DPROC glad_glFramebufferTexture3D = NULL;
-PFNGLFRAMEBUFFERTEXTURELAYERPROC glad_glFramebufferTextureLayer = NULL;
-PFNGLFRONTFACEPROC glad_glFrontFace = NULL;
-PFNGLFRUSTUMPROC glad_glFrustum = NULL;
-PFNGLGENBUFFERSPROC glad_glGenBuffers = NULL;
-PFNGLGENFRAMEBUFFERSPROC glad_glGenFramebuffers = NULL;
-PFNGLGENLISTSPROC glad_glGenLists = NULL;
-PFNGLGENQUERIESPROC glad_glGenQueries = NULL;
-PFNGLGENRENDERBUFFERSPROC glad_glGenRenderbuffers = NULL;
-PFNGLGENSAMPLERSPROC glad_glGenSamplers = NULL;
-PFNGLGENTEXTURESPROC glad_glGenTextures = NULL;
-PFNGLGENVERTEXARRAYSPROC glad_glGenVertexArrays = NULL;
-PFNGLGENERATEMIPMAPPROC glad_glGenerateMipmap = NULL;
-PFNGLGETACTIVEATTRIBPROC glad_glGetActiveAttrib = NULL;
-PFNGLGETACTIVEUNIFORMPROC glad_glGetActiveUniform = NULL;
-PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC glad_glGetActiveUniformBlockName = NULL;
-PFNGLGETACTIVEUNIFORMBLOCKIVPROC glad_glGetActiveUniformBlockiv = NULL;
-PFNGLGETACTIVEUNIFORMNAMEPROC glad_glGetActiveUniformName = NULL;
-PFNGLGETACTIVEUNIFORMSIVPROC glad_glGetActiveUniformsiv = NULL;
-PFNGLGETATTACHEDSHADERSPROC glad_glGetAttachedShaders = NULL;
-PFNGLGETATTRIBLOCATIONPROC glad_glGetAttribLocation = NULL;
-PFNGLGETBOOLEANI_VPROC glad_glGetBooleani_v = NULL;
-PFNGLGETBOOLEANVPROC glad_glGetBooleanv = NULL;
-PFNGLGETBUFFERPARAMETERI64VPROC glad_glGetBufferParameteri64v = NULL;
-PFNGLGETBUFFERPARAMETERIVPROC glad_glGetBufferParameteriv = NULL;
-PFNGLGETBUFFERPOINTERVPROC glad_glGetBufferPointerv = NULL;
-PFNGLGETBUFFERSUBDATAPROC glad_glGetBufferSubData = NULL;
-PFNGLGETCLIPPLANEPROC glad_glGetClipPlane = NULL;
-PFNGLGETCOMPRESSEDTEXIMAGEPROC glad_glGetCompressedTexImage = NULL;
-PFNGLGETDOUBLEVPROC glad_glGetDoublev = NULL;
-PFNGLGETERRORPROC glad_glGetError = NULL;
-PFNGLGETFLOATVPROC glad_glGetFloatv = NULL;
-PFNGLGETFRAGDATAINDEXPROC glad_glGetFragDataIndex = NULL;
-PFNGLGETFRAGDATALOCATIONPROC glad_glGetFragDataLocation = NULL;
-PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC glad_glGetFramebufferAttachmentParameteriv = NULL;
-PFNGLGETINTEGER64I_VPROC glad_glGetInteger64i_v = NULL;
-PFNGLGETINTEGER64VPROC glad_glGetInteger64v = NULL;
-PFNGLGETINTEGERI_VPROC glad_glGetIntegeri_v = NULL;
-PFNGLGETINTEGERVPROC glad_glGetIntegerv = NULL;
-PFNGLGETLIGHTFVPROC glad_glGetLightfv = NULL;
-PFNGLGETLIGHTIVPROC glad_glGetLightiv = NULL;
-PFNGLGETMAPDVPROC glad_glGetMapdv = NULL;
-PFNGLGETMAPFVPROC glad_glGetMapfv = NULL;
-PFNGLGETMAPIVPROC glad_glGetMapiv = NULL;
-PFNGLGETMATERIALFVPROC glad_glGetMaterialfv = NULL;
-PFNGLGETMATERIALIVPROC glad_glGetMaterialiv = NULL;
-PFNGLGETMULTISAMPLEFVPROC glad_glGetMultisamplefv = NULL;
-PFNGLGETPIXELMAPFVPROC glad_glGetPixelMapfv = NULL;
-PFNGLGETPIXELMAPUIVPROC glad_glGetPixelMapuiv = NULL;
-PFNGLGETPIXELMAPUSVPROC glad_glGetPixelMapusv = NULL;
-PFNGLGETPOINTERVPROC glad_glGetPointerv = NULL;
-PFNGLGETPOLYGONSTIPPLEPROC glad_glGetPolygonStipple = NULL;
-PFNGLGETPROGRAMINFOLOGPROC glad_glGetProgramInfoLog = NULL;
-PFNGLGETPROGRAMIVPROC glad_glGetProgramiv = NULL;
-PFNGLGETQUERYOBJECTI64VPROC glad_glGetQueryObjecti64v = NULL;
-PFNGLGETQUERYOBJECTIVPROC glad_glGetQueryObjectiv = NULL;
-PFNGLGETQUERYOBJECTUI64VPROC glad_glGetQueryObjectui64v = NULL;
-PFNGLGETQUERYOBJECTUIVPROC glad_glGetQueryObjectuiv = NULL;
-PFNGLGETQUERYIVPROC glad_glGetQueryiv = NULL;
-PFNGLGETRENDERBUFFERPARAMETERIVPROC glad_glGetRenderbufferParameteriv = NULL;
-PFNGLGETSAMPLERPARAMETERIIVPROC glad_glGetSamplerParameterIiv = NULL;
-PFNGLGETSAMPLERPARAMETERIUIVPROC glad_glGetSamplerParameterIuiv = NULL;
-PFNGLGETSAMPLERPARAMETERFVPROC glad_glGetSamplerParameterfv = NULL;
-PFNGLGETSAMPLERPARAMETERIVPROC glad_glGetSamplerParameteriv = NULL;
-PFNGLGETSHADERINFOLOGPROC glad_glGetShaderInfoLog = NULL;
-PFNGLGETSHADERSOURCEPROC glad_glGetShaderSource = NULL;
-PFNGLGETSHADERIVPROC glad_glGetShaderiv = NULL;
-PFNGLGETSTRINGPROC glad_glGetString = NULL;
-PFNGLGETSTRINGIPROC glad_glGetStringi = NULL;
-PFNGLGETSYNCIVPROC glad_glGetSynciv = NULL;
-PFNGLGETTEXENVFVPROC glad_glGetTexEnvfv = NULL;
-PFNGLGETTEXENVIVPROC glad_glGetTexEnviv = NULL;
-PFNGLGETTEXGENDVPROC glad_glGetTexGendv = NULL;
-PFNGLGETTEXGENFVPROC glad_glGetTexGenfv = NULL;
-PFNGLGETTEXGENIVPROC glad_glGetTexGeniv = NULL;
-PFNGLGETTEXIMAGEPROC glad_glGetTexImage = NULL;
-PFNGLGETTEXLEVELPARAMETERFVPROC glad_glGetTexLevelParameterfv = NULL;
-PFNGLGETTEXLEVELPARAMETERIVPROC glad_glGetTexLevelParameteriv = NULL;
-PFNGLGETTEXPARAMETERIIVPROC glad_glGetTexParameterIiv = NULL;
-PFNGLGETTEXPARAMETERIUIVPROC glad_glGetTexParameterIuiv = NULL;
-PFNGLGETTEXPARAMETERFVPROC glad_glGetTexParameterfv = NULL;
-PFNGLGETTEXPARAMETERIVPROC glad_glGetTexParameteriv = NULL;
-PFNGLGETTRANSFORMFEEDBACKVARYINGPROC glad_glGetTransformFeedbackVarying = NULL;
-PFNGLGETUNIFORMBLOCKINDEXPROC glad_glGetUniformBlockIndex = NULL;
-PFNGLGETUNIFORMINDICESPROC glad_glGetUniformIndices = NULL;
-PFNGLGETUNIFORMLOCATIONPROC glad_glGetUniformLocation = NULL;
-PFNGLGETUNIFORMFVPROC glad_glGetUniformfv = NULL;
-PFNGLGETUNIFORMIVPROC glad_glGetUniformiv = NULL;
-PFNGLGETUNIFORMUIVPROC glad_glGetUniformuiv = NULL;
-PFNGLGETVERTEXATTRIBIIVPROC glad_glGetVertexAttribIiv = NULL;
-PFNGLGETVERTEXATTRIBIUIVPROC glad_glGetVertexAttribIuiv = NULL;
-PFNGLGETVERTEXATTRIBPOINTERVPROC glad_glGetVertexAttribPointerv = NULL;
-PFNGLGETVERTEXATTRIBDVPROC glad_glGetVertexAttribdv = NULL;
-PFNGLGETVERTEXATTRIBFVPROC glad_glGetVertexAttribfv = NULL;
-PFNGLGETVERTEXATTRIBIVPROC glad_glGetVertexAttribiv = NULL;
-PFNGLHINTPROC glad_glHint = NULL;
-PFNGLINDEXMASKPROC glad_glIndexMask = NULL;
-PFNGLINDEXPOINTERPROC glad_glIndexPointer = NULL;
-PFNGLINDEXDPROC glad_glIndexd = NULL;
-PFNGLINDEXDVPROC glad_glIndexdv = NULL;
-PFNGLINDEXFPROC glad_glIndexf = NULL;
-PFNGLINDEXFVPROC glad_glIndexfv = NULL;
-PFNGLINDEXIPROC glad_glIndexi = NULL;
-PFNGLINDEXIVPROC glad_glIndexiv = NULL;
-PFNGLINDEXSPROC glad_glIndexs = NULL;
-PFNGLINDEXSVPROC glad_glIndexsv = NULL;
-PFNGLINDEXUBPROC glad_glIndexub = NULL;
-PFNGLINDEXUBVPROC glad_glIndexubv = NULL;
-PFNGLINITNAMESPROC glad_glInitNames = NULL;
-PFNGLINTERLEAVEDARRAYSPROC glad_glInterleavedArrays = NULL;
-PFNGLISBUFFERPROC glad_glIsBuffer = NULL;
-PFNGLISENABLEDPROC glad_glIsEnabled = NULL;
-PFNGLISENABLEDIPROC glad_glIsEnabledi = NULL;
-PFNGLISFRAMEBUFFERPROC glad_glIsFramebuffer = NULL;
-PFNGLISLISTPROC glad_glIsList = NULL;
-PFNGLISPROGRAMPROC glad_glIsProgram = NULL;
-PFNGLISQUERYPROC glad_glIsQuery = NULL;
-PFNGLISRENDERBUFFERPROC glad_glIsRenderbuffer = NULL;
-PFNGLISSAMPLERPROC glad_glIsSampler = NULL;
-PFNGLISSHADERPROC glad_glIsShader = NULL;
-PFNGLISSYNCPROC glad_glIsSync = NULL;
-PFNGLISTEXTUREPROC glad_glIsTexture = NULL;
-PFNGLISVERTEXARRAYPROC glad_glIsVertexArray = NULL;
-PFNGLLIGHTMODELFPROC glad_glLightModelf = NULL;
-PFNGLLIGHTMODELFVPROC glad_glLightModelfv = NULL;
-PFNGLLIGHTMODELIPROC glad_glLightModeli = NULL;
-PFNGLLIGHTMODELIVPROC glad_glLightModeliv = NULL;
-PFNGLLIGHTFPROC glad_glLightf = NULL;
-PFNGLLIGHTFVPROC glad_glLightfv = NULL;
-PFNGLLIGHTIPROC glad_glLighti = NULL;
-PFNGLLIGHTIVPROC glad_glLightiv = NULL;
-PFNGLLINESTIPPLEPROC glad_glLineStipple = NULL;
-PFNGLLINEWIDTHPROC glad_glLineWidth = NULL;
-PFNGLLINKPROGRAMPROC glad_glLinkProgram = NULL;
-PFNGLLISTBASEPROC glad_glListBase = NULL;
-PFNGLLOADIDENTITYPROC glad_glLoadIdentity = NULL;
-PFNGLLOADMATRIXDPROC glad_glLoadMatrixd = NULL;
-PFNGLLOADMATRIXFPROC glad_glLoadMatrixf = NULL;
-PFNGLLOADNAMEPROC glad_glLoadName = NULL;
-PFNGLLOADTRANSPOSEMATRIXDPROC glad_glLoadTransposeMatrixd = NULL;
-PFNGLLOADTRANSPOSEMATRIXFPROC glad_glLoadTransposeMatrixf = NULL;
-PFNGLLOGICOPPROC glad_glLogicOp = NULL;
-PFNGLMAP1DPROC glad_glMap1d = NULL;
-PFNGLMAP1FPROC glad_glMap1f = NULL;
-PFNGLMAP2DPROC glad_glMap2d = NULL;
-PFNGLMAP2FPROC glad_glMap2f = NULL;
-PFNGLMAPBUFFERPROC glad_glMapBuffer = NULL;
-PFNGLMAPBUFFERRANGEPROC glad_glMapBufferRange = NULL;
-PFNGLMAPGRID1DPROC glad_glMapGrid1d = NULL;
-PFNGLMAPGRID1FPROC glad_glMapGrid1f = NULL;
-PFNGLMAPGRID2DPROC glad_glMapGrid2d = NULL;
-PFNGLMAPGRID2FPROC glad_glMapGrid2f = NULL;
-PFNGLMATERIALFPROC glad_glMaterialf = NULL;
-PFNGLMATERIALFVPROC glad_glMaterialfv = NULL;
-PFNGLMATERIALIPROC glad_glMateriali = NULL;
-PFNGLMATERIALIVPROC glad_glMaterialiv = NULL;
-PFNGLMATRIXMODEPROC glad_glMatrixMode = NULL;
-PFNGLMULTMATRIXDPROC glad_glMultMatrixd = NULL;
-PFNGLMULTMATRIXFPROC glad_glMultMatrixf = NULL;
-PFNGLMULTTRANSPOSEMATRIXDPROC glad_glMultTransposeMatrixd = NULL;
-PFNGLMULTTRANSPOSEMATRIXFPROC glad_glMultTransposeMatrixf = NULL;
-PFNGLMULTIDRAWARRAYSPROC glad_glMultiDrawArrays = NULL;
-PFNGLMULTIDRAWELEMENTSPROC glad_glMultiDrawElements = NULL;
-PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC glad_glMultiDrawElementsBaseVertex = NULL;
-PFNGLMULTITEXCOORD1DPROC glad_glMultiTexCoord1d = NULL;
-PFNGLMULTITEXCOORD1DVPROC glad_glMultiTexCoord1dv = NULL;
-PFNGLMULTITEXCOORD1FPROC glad_glMultiTexCoord1f = NULL;
-PFNGLMULTITEXCOORD1FVPROC glad_glMultiTexCoord1fv = NULL;
-PFNGLMULTITEXCOORD1IPROC glad_glMultiTexCoord1i = NULL;
-PFNGLMULTITEXCOORD1IVPROC glad_glMultiTexCoord1iv = NULL;
-PFNGLMULTITEXCOORD1SPROC glad_glMultiTexCoord1s = NULL;
-PFNGLMULTITEXCOORD1SVPROC glad_glMultiTexCoord1sv = NULL;
-PFNGLMULTITEXCOORD2DPROC glad_glMultiTexCoord2d = NULL;
-PFNGLMULTITEXCOORD2DVPROC glad_glMultiTexCoord2dv = NULL;
-PFNGLMULTITEXCOORD2FPROC glad_glMultiTexCoord2f = NULL;
-PFNGLMULTITEXCOORD2FVPROC glad_glMultiTexCoord2fv = NULL;
-PFNGLMULTITEXCOORD2IPROC glad_glMultiTexCoord2i = NULL;
-PFNGLMULTITEXCOORD2IVPROC glad_glMultiTexCoord2iv = NULL;
-PFNGLMULTITEXCOORD2SPROC glad_glMultiTexCoord2s = NULL;
-PFNGLMULTITEXCOORD2SVPROC glad_glMultiTexCoord2sv = NULL;
-PFNGLMULTITEXCOORD3DPROC glad_glMultiTexCoord3d = NULL;
-PFNGLMULTITEXCOORD3DVPROC glad_glMultiTexCoord3dv = NULL;
-PFNGLMULTITEXCOORD3FPROC glad_glMultiTexCoord3f = NULL;
-PFNGLMULTITEXCOORD3FVPROC glad_glMultiTexCoord3fv = NULL;
-PFNGLMULTITEXCOORD3IPROC glad_glMultiTexCoord3i = NULL;
-PFNGLMULTITEXCOORD3IVPROC glad_glMultiTexCoord3iv = NULL;
-PFNGLMULTITEXCOORD3SPROC glad_glMultiTexCoord3s = NULL;
-PFNGLMULTITEXCOORD3SVPROC glad_glMultiTexCoord3sv = NULL;
-PFNGLMULTITEXCOORD4DPROC glad_glMultiTexCoord4d = NULL;
-PFNGLMULTITEXCOORD4DVPROC glad_glMultiTexCoord4dv = NULL;
-PFNGLMULTITEXCOORD4FPROC glad_glMultiTexCoord4f = NULL;
-PFNGLMULTITEXCOORD4FVPROC glad_glMultiTexCoord4fv = NULL;
-PFNGLMULTITEXCOORD4IPROC glad_glMultiTexCoord4i = NULL;
-PFNGLMULTITEXCOORD4IVPROC glad_glMultiTexCoord4iv = NULL;
-PFNGLMULTITEXCOORD4SPROC glad_glMultiTexCoord4s = NULL;
-PFNGLMULTITEXCOORD4SVPROC glad_glMultiTexCoord4sv = NULL;
-PFNGLMULTITEXCOORDP1UIPROC glad_glMultiTexCoordP1ui = NULL;
-PFNGLMULTITEXCOORDP1UIVPROC glad_glMultiTexCoordP1uiv = NULL;
-PFNGLMULTITEXCOORDP2UIPROC glad_glMultiTexCoordP2ui = NULL;
-PFNGLMULTITEXCOORDP2UIVPROC glad_glMultiTexCoordP2uiv = NULL;
-PFNGLMULTITEXCOORDP3UIPROC glad_glMultiTexCoordP3ui = NULL;
-PFNGLMULTITEXCOORDP3UIVPROC glad_glMultiTexCoordP3uiv = NULL;
-PFNGLMULTITEXCOORDP4UIPROC glad_glMultiTexCoordP4ui = NULL;
-PFNGLMULTITEXCOORDP4UIVPROC glad_glMultiTexCoordP4uiv = NULL;
-PFNGLNEWLISTPROC glad_glNewList = NULL;
-PFNGLNORMAL3BPROC glad_glNormal3b = NULL;
-PFNGLNORMAL3BVPROC glad_glNormal3bv = NULL;
-PFNGLNORMAL3DPROC glad_glNormal3d = NULL;
-PFNGLNORMAL3DVPROC glad_glNormal3dv = NULL;
-PFNGLNORMAL3FPROC glad_glNormal3f = NULL;
-PFNGLNORMAL3FVPROC glad_glNormal3fv = NULL;
-PFNGLNORMAL3IPROC glad_glNormal3i = NULL;
-PFNGLNORMAL3IVPROC glad_glNormal3iv = NULL;
-PFNGLNORMAL3SPROC glad_glNormal3s = NULL;
-PFNGLNORMAL3SVPROC glad_glNormal3sv = NULL;
-PFNGLNORMALP3UIPROC glad_glNormalP3ui = NULL;
-PFNGLNORMALP3UIVPROC glad_glNormalP3uiv = NULL;
-PFNGLNORMALPOINTERPROC glad_glNormalPointer = NULL;
-PFNGLORTHOPROC glad_glOrtho = NULL;
-PFNGLPASSTHROUGHPROC glad_glPassThrough = NULL;
-PFNGLPIXELMAPFVPROC glad_glPixelMapfv = NULL;
-PFNGLPIXELMAPUIVPROC glad_glPixelMapuiv = NULL;
-PFNGLPIXELMAPUSVPROC glad_glPixelMapusv = NULL;
-PFNGLPIXELSTOREFPROC glad_glPixelStoref = NULL;
-PFNGLPIXELSTOREIPROC glad_glPixelStorei = NULL;
-PFNGLPIXELTRANSFERFPROC glad_glPixelTransferf = NULL;
-PFNGLPIXELTRANSFERIPROC glad_glPixelTransferi = NULL;
-PFNGLPIXELZOOMPROC glad_glPixelZoom = NULL;
-PFNGLPOINTPARAMETERFPROC glad_glPointParameterf = NULL;
-PFNGLPOINTPARAMETERFVPROC glad_glPointParameterfv = NULL;
-PFNGLPOINTPARAMETERIPROC glad_glPointParameteri = NULL;
-PFNGLPOINTPARAMETERIVPROC glad_glPointParameteriv = NULL;
-PFNGLPOINTSIZEPROC glad_glPointSize = NULL;
-PFNGLPOLYGONMODEPROC glad_glPolygonMode = NULL;
-PFNGLPOLYGONOFFSETPROC glad_glPolygonOffset = NULL;
-PFNGLPOLYGONSTIPPLEPROC glad_glPolygonStipple = NULL;
-PFNGLPOPATTRIBPROC glad_glPopAttrib = NULL;
-PFNGLPOPCLIENTATTRIBPROC glad_glPopClientAttrib = NULL;
-PFNGLPOPMATRIXPROC glad_glPopMatrix = NULL;
-PFNGLPOPNAMEPROC glad_glPopName = NULL;
-PFNGLPRIMITIVERESTARTINDEXPROC glad_glPrimitiveRestartIndex = NULL;
-PFNGLPRIORITIZETEXTURESPROC glad_glPrioritizeTextures = NULL;
-PFNGLPROVOKINGVERTEXPROC glad_glProvokingVertex = NULL;
-PFNGLPUSHATTRIBPROC glad_glPushAttrib = NULL;
-PFNGLPUSHCLIENTATTRIBPROC glad_glPushClientAttrib = NULL;
-PFNGLPUSHMATRIXPROC glad_glPushMatrix = NULL;
-PFNGLPUSHNAMEPROC glad_glPushName = NULL;
-PFNGLQUERYCOUNTERPROC glad_glQueryCounter = NULL;
-PFNGLRASTERPOS2DPROC glad_glRasterPos2d = NULL;
-PFNGLRASTERPOS2DVPROC glad_glRasterPos2dv = NULL;
-PFNGLRASTERPOS2FPROC glad_glRasterPos2f = NULL;
-PFNGLRASTERPOS2FVPROC glad_glRasterPos2fv = NULL;
-PFNGLRASTERPOS2IPROC glad_glRasterPos2i = NULL;
-PFNGLRASTERPOS2IVPROC glad_glRasterPos2iv = NULL;
-PFNGLRASTERPOS2SPROC glad_glRasterPos2s = NULL;
-PFNGLRASTERPOS2SVPROC glad_glRasterPos2sv = NULL;
-PFNGLRASTERPOS3DPROC glad_glRasterPos3d = NULL;
-PFNGLRASTERPOS3DVPROC glad_glRasterPos3dv = NULL;
-PFNGLRASTERPOS3FPROC glad_glRasterPos3f = NULL;
-PFNGLRASTERPOS3FVPROC glad_glRasterPos3fv = NULL;
-PFNGLRASTERPOS3IPROC glad_glRasterPos3i = NULL;
-PFNGLRASTERPOS3IVPROC glad_glRasterPos3iv = NULL;
-PFNGLRASTERPOS3SPROC glad_glRasterPos3s = NULL;
-PFNGLRASTERPOS3SVPROC glad_glRasterPos3sv = NULL;
-PFNGLRASTERPOS4DPROC glad_glRasterPos4d = NULL;
-PFNGLRASTERPOS4DVPROC glad_glRasterPos4dv = NULL;
-PFNGLRASTERPOS4FPROC glad_glRasterPos4f = NULL;
-PFNGLRASTERPOS4FVPROC glad_glRasterPos4fv = NULL;
-PFNGLRASTERPOS4IPROC glad_glRasterPos4i = NULL;
-PFNGLRASTERPOS4IVPROC glad_glRasterPos4iv = NULL;
-PFNGLRASTERPOS4SPROC glad_glRasterPos4s = NULL;
-PFNGLRASTERPOS4SVPROC glad_glRasterPos4sv = NULL;
-PFNGLREADBUFFERPROC glad_glReadBuffer = NULL;
-PFNGLREADPIXELSPROC glad_glReadPixels = NULL;
-PFNGLRECTDPROC glad_glRectd = NULL;
-PFNGLRECTDVPROC glad_glRectdv = NULL;
-PFNGLRECTFPROC glad_glRectf = NULL;
-PFNGLRECTFVPROC glad_glRectfv = NULL;
-PFNGLRECTIPROC glad_glRecti = NULL;
-PFNGLRECTIVPROC glad_glRectiv = NULL;
-PFNGLRECTSPROC glad_glRects = NULL;
-PFNGLRECTSVPROC glad_glRectsv = NULL;
-PFNGLRENDERMODEPROC glad_glRenderMode = NULL;
-PFNGLRENDERBUFFERSTORAGEPROC glad_glRenderbufferStorage = NULL;
-PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC glad_glRenderbufferStorageMultisample = NULL;
-PFNGLROTATEDPROC glad_glRotated = NULL;
-PFNGLROTATEFPROC glad_glRotatef = NULL;
-PFNGLSAMPLECOVERAGEPROC glad_glSampleCoverage = NULL;
-PFNGLSAMPLEMASKIPROC glad_glSampleMaski = NULL;
-PFNGLSAMPLERPARAMETERIIVPROC glad_glSamplerParameterIiv = NULL;
-PFNGLSAMPLERPARAMETERIUIVPROC glad_glSamplerParameterIuiv = NULL;
-PFNGLSAMPLERPARAMETERFPROC glad_glSamplerParameterf = NULL;
-PFNGLSAMPLERPARAMETERFVPROC glad_glSamplerParameterfv = NULL;
-PFNGLSAMPLERPARAMETERIPROC glad_glSamplerParameteri = NULL;
-PFNGLSAMPLERPARAMETERIVPROC glad_glSamplerParameteriv = NULL;
-PFNGLSCALEDPROC glad_glScaled = NULL;
-PFNGLSCALEFPROC glad_glScalef = NULL;
-PFNGLSCISSORPROC glad_glScissor = NULL;
-PFNGLSECONDARYCOLOR3BPROC glad_glSecondaryColor3b = NULL;
-PFNGLSECONDARYCOLOR3BVPROC glad_glSecondaryColor3bv = NULL;
-PFNGLSECONDARYCOLOR3DPROC glad_glSecondaryColor3d = NULL;
-PFNGLSECONDARYCOLOR3DVPROC glad_glSecondaryColor3dv = NULL;
-PFNGLSECONDARYCOLOR3FPROC glad_glSecondaryColor3f = NULL;
-PFNGLSECONDARYCOLOR3FVPROC glad_glSecondaryColor3fv = NULL;
-PFNGLSECONDARYCOLOR3IPROC glad_glSecondaryColor3i = NULL;
-PFNGLSECONDARYCOLOR3IVPROC glad_glSecondaryColor3iv = NULL;
-PFNGLSECONDARYCOLOR3SPROC glad_glSecondaryColor3s = NULL;
-PFNGLSECONDARYCOLOR3SVPROC glad_glSecondaryColor3sv = NULL;
-PFNGLSECONDARYCOLOR3UBPROC glad_glSecondaryColor3ub = NULL;
-PFNGLSECONDARYCOLOR3UBVPROC glad_glSecondaryColor3ubv = NULL;
-PFNGLSECONDARYCOLOR3UIPROC glad_glSecondaryColor3ui = NULL;
-PFNGLSECONDARYCOLOR3UIVPROC glad_glSecondaryColor3uiv = NULL;
-PFNGLSECONDARYCOLOR3USPROC glad_glSecondaryColor3us = NULL;
-PFNGLSECONDARYCOLOR3USVPROC glad_glSecondaryColor3usv = NULL;
-PFNGLSECONDARYCOLORP3UIPROC glad_glSecondaryColorP3ui = NULL;
-PFNGLSECONDARYCOLORP3UIVPROC glad_glSecondaryColorP3uiv = NULL;
-PFNGLSECONDARYCOLORPOINTERPROC glad_glSecondaryColorPointer = NULL;
-PFNGLSELECTBUFFERPROC glad_glSelectBuffer = NULL;
-PFNGLSHADEMODELPROC glad_glShadeModel = NULL;
-PFNGLSHADERSOURCEPROC glad_glShaderSource = NULL;
-PFNGLSTENCILFUNCPROC glad_glStencilFunc = NULL;
-PFNGLSTENCILFUNCSEPARATEPROC glad_glStencilFuncSeparate = NULL;
-PFNGLSTENCILMASKPROC glad_glStencilMask = NULL;
-PFNGLSTENCILMASKSEPARATEPROC glad_glStencilMaskSeparate = NULL;
-PFNGLSTENCILOPPROC glad_glStencilOp = NULL;
-PFNGLSTENCILOPSEPARATEPROC glad_glStencilOpSeparate = NULL;
-PFNGLTEXBUFFERPROC glad_glTexBuffer = NULL;
-PFNGLTEXCOORD1DPROC glad_glTexCoord1d = NULL;
-PFNGLTEXCOORD1DVPROC glad_glTexCoord1dv = NULL;
-PFNGLTEXCOORD1FPROC glad_glTexCoord1f = NULL;
-PFNGLTEXCOORD1FVPROC glad_glTexCoord1fv = NULL;
-PFNGLTEXCOORD1IPROC glad_glTexCoord1i = NULL;
-PFNGLTEXCOORD1IVPROC glad_glTexCoord1iv = NULL;
-PFNGLTEXCOORD1SPROC glad_glTexCoord1s = NULL;
-PFNGLTEXCOORD1SVPROC glad_glTexCoord1sv = NULL;
-PFNGLTEXCOORD2DPROC glad_glTexCoord2d = NULL;
-PFNGLTEXCOORD2DVPROC glad_glTexCoord2dv = NULL;
-PFNGLTEXCOORD2FPROC glad_glTexCoord2f = NULL;
-PFNGLTEXCOORD2FVPROC glad_glTexCoord2fv = NULL;
-PFNGLTEXCOORD2IPROC glad_glTexCoord2i = NULL;
-PFNGLTEXCOORD2IVPROC glad_glTexCoord2iv = NULL;
-PFNGLTEXCOORD2SPROC glad_glTexCoord2s = NULL;
-PFNGLTEXCOORD2SVPROC glad_glTexCoord2sv = NULL;
-PFNGLTEXCOORD3DPROC glad_glTexCoord3d = NULL;
-PFNGLTEXCOORD3DVPROC glad_glTexCoord3dv = NULL;
-PFNGLTEXCOORD3FPROC glad_glTexCoord3f = NULL;
-PFNGLTEXCOORD3FVPROC glad_glTexCoord3fv = NULL;
-PFNGLTEXCOORD3IPROC glad_glTexCoord3i = NULL;
-PFNGLTEXCOORD3IVPROC glad_glTexCoord3iv = NULL;
-PFNGLTEXCOORD3SPROC glad_glTexCoord3s = NULL;
-PFNGLTEXCOORD3SVPROC glad_glTexCoord3sv = NULL;
-PFNGLTEXCOORD4DPROC glad_glTexCoord4d = NULL;
-PFNGLTEXCOORD4DVPROC glad_glTexCoord4dv = NULL;
-PFNGLTEXCOORD4FPROC glad_glTexCoord4f = NULL;
-PFNGLTEXCOORD4FVPROC glad_glTexCoord4fv = NULL;
-PFNGLTEXCOORD4IPROC glad_glTexCoord4i = NULL;
-PFNGLTEXCOORD4IVPROC glad_glTexCoord4iv = NULL;
-PFNGLTEXCOORD4SPROC glad_glTexCoord4s = NULL;
-PFNGLTEXCOORD4SVPROC glad_glTexCoord4sv = NULL;
-PFNGLTEXCOORDP1UIPROC glad_glTexCoordP1ui = NULL;
-PFNGLTEXCOORDP1UIVPROC glad_glTexCoordP1uiv = NULL;
-PFNGLTEXCOORDP2UIPROC glad_glTexCoordP2ui = NULL;
-PFNGLTEXCOORDP2UIVPROC glad_glTexCoordP2uiv = NULL;
-PFNGLTEXCOORDP3UIPROC glad_glTexCoordP3ui = NULL;
-PFNGLTEXCOORDP3UIVPROC glad_glTexCoordP3uiv = NULL;
-PFNGLTEXCOORDP4UIPROC glad_glTexCoordP4ui = NULL;
-PFNGLTEXCOORDP4UIVPROC glad_glTexCoordP4uiv = NULL;
-PFNGLTEXCOORDPOINTERPROC glad_glTexCoordPointer = NULL;
-PFNGLTEXENVFPROC glad_glTexEnvf = NULL;
-PFNGLTEXENVFVPROC glad_glTexEnvfv = NULL;
-PFNGLTEXENVIPROC glad_glTexEnvi = NULL;
-PFNGLTEXENVIVPROC glad_glTexEnviv = NULL;
-PFNGLTEXGENDPROC glad_glTexGend = NULL;
-PFNGLTEXGENDVPROC glad_glTexGendv = NULL;
-PFNGLTEXGENFPROC glad_glTexGenf = NULL;
-PFNGLTEXGENFVPROC glad_glTexGenfv = NULL;
-PFNGLTEXGENIPROC glad_glTexGeni = NULL;
-PFNGLTEXGENIVPROC glad_glTexGeniv = NULL;
-PFNGLTEXIMAGE1DPROC glad_glTexImage1D = NULL;
-PFNGLTEXIMAGE2DPROC glad_glTexImage2D = NULL;
-PFNGLTEXIMAGE2DMULTISAMPLEPROC glad_glTexImage2DMultisample = NULL;
-PFNGLTEXIMAGE3DPROC glad_glTexImage3D = NULL;
-PFNGLTEXIMAGE3DMULTISAMPLEPROC glad_glTexImage3DMultisample = NULL;
-PFNGLTEXPARAMETERIIVPROC glad_glTexParameterIiv = NULL;
-PFNGLTEXPARAMETERIUIVPROC glad_glTexParameterIuiv = NULL;
-PFNGLTEXPARAMETERFPROC glad_glTexParameterf = NULL;
-PFNGLTEXPARAMETERFVPROC glad_glTexParameterfv = NULL;
-PFNGLTEXPARAMETERIPROC glad_glTexParameteri = NULL;
-PFNGLTEXPARAMETERIVPROC glad_glTexParameteriv = NULL;
-PFNGLTEXSUBIMAGE1DPROC glad_glTexSubImage1D = NULL;
-PFNGLTEXSUBIMAGE2DPROC glad_glTexSubImage2D = NULL;
-PFNGLTEXSUBIMAGE3DPROC glad_glTexSubImage3D = NULL;
-PFNGLTRANSFORMFEEDBACKVARYINGSPROC glad_glTransformFeedbackVaryings = NULL;
-PFNGLTRANSLATEDPROC glad_glTranslated = NULL;
-PFNGLTRANSLATEFPROC glad_glTranslatef = NULL;
-PFNGLUNIFORM1FPROC glad_glUniform1f = NULL;
-PFNGLUNIFORM1FVPROC glad_glUniform1fv = NULL;
-PFNGLUNIFORM1IPROC glad_glUniform1i = NULL;
-PFNGLUNIFORM1IVPROC glad_glUniform1iv = NULL;
-PFNGLUNIFORM1UIPROC glad_glUniform1ui = NULL;
-PFNGLUNIFORM1UIVPROC glad_glUniform1uiv = NULL;
-PFNGLUNIFORM2FPROC glad_glUniform2f = NULL;
-PFNGLUNIFORM2FVPROC glad_glUniform2fv = NULL;
-PFNGLUNIFORM2IPROC glad_glUniform2i = NULL;
-PFNGLUNIFORM2IVPROC glad_glUniform2iv = NULL;
-PFNGLUNIFORM2UIPROC glad_glUniform2ui = NULL;
-PFNGLUNIFORM2UIVPROC glad_glUniform2uiv = NULL;
-PFNGLUNIFORM3FPROC glad_glUniform3f = NULL;
-PFNGLUNIFORM3FVPROC glad_glUniform3fv = NULL;
-PFNGLUNIFORM3IPROC glad_glUniform3i = NULL;
-PFNGLUNIFORM3IVPROC glad_glUniform3iv = NULL;
-PFNGLUNIFORM3UIPROC glad_glUniform3ui = NULL;
-PFNGLUNIFORM3UIVPROC glad_glUniform3uiv = NULL;
-PFNGLUNIFORM4FPROC glad_glUniform4f = NULL;
-PFNGLUNIFORM4FVPROC glad_glUniform4fv = NULL;
-PFNGLUNIFORM4IPROC glad_glUniform4i = NULL;
-PFNGLUNIFORM4IVPROC glad_glUniform4iv = NULL;
-PFNGLUNIFORM4UIPROC glad_glUniform4ui = NULL;
-PFNGLUNIFORM4UIVPROC glad_glUniform4uiv = NULL;
-PFNGLUNIFORMBLOCKBINDINGPROC glad_glUniformBlockBinding = NULL;
-PFNGLUNIFORMMATRIX2FVPROC glad_glUniformMatrix2fv = NULL;
-PFNGLUNIFORMMATRIX2X3FVPROC glad_glUniformMatrix2x3fv = NULL;
-PFNGLUNIFORMMATRIX2X4FVPROC glad_glUniformMatrix2x4fv = NULL;
-PFNGLUNIFORMMATRIX3FVPROC glad_glUniformMatrix3fv = NULL;
-PFNGLUNIFORMMATRIX3X2FVPROC glad_glUniformMatrix3x2fv = NULL;
-PFNGLUNIFORMMATRIX3X4FVPROC glad_glUniformMatrix3x4fv = NULL;
-PFNGLUNIFORMMATRIX4FVPROC glad_glUniformMatrix4fv = NULL;
-PFNGLUNIFORMMATRIX4X2FVPROC glad_glUniformMatrix4x2fv = NULL;
-PFNGLUNIFORMMATRIX4X3FVPROC glad_glUniformMatrix4x3fv = NULL;
-PFNGLUNMAPBUFFERPROC glad_glUnmapBuffer = NULL;
-PFNGLUSEPROGRAMPROC glad_glUseProgram = NULL;
-PFNGLVALIDATEPROGRAMPROC glad_glValidateProgram = NULL;
-PFNGLVERTEX2DPROC glad_glVertex2d = NULL;
-PFNGLVERTEX2DVPROC glad_glVertex2dv = NULL;
-PFNGLVERTEX2FPROC glad_glVertex2f = NULL;
-PFNGLVERTEX2FVPROC glad_glVertex2fv = NULL;
-PFNGLVERTEX2IPROC glad_glVertex2i = NULL;
-PFNGLVERTEX2IVPROC glad_glVertex2iv = NULL;
-PFNGLVERTEX2SPROC glad_glVertex2s = NULL;
-PFNGLVERTEX2SVPROC glad_glVertex2sv = NULL;
-PFNGLVERTEX3DPROC glad_glVertex3d = NULL;
-PFNGLVERTEX3DVPROC glad_glVertex3dv = NULL;
-PFNGLVERTEX3FPROC glad_glVertex3f = NULL;
-PFNGLVERTEX3FVPROC glad_glVertex3fv = NULL;
-PFNGLVERTEX3IPROC glad_glVertex3i = NULL;
-PFNGLVERTEX3IVPROC glad_glVertex3iv = NULL;
-PFNGLVERTEX3SPROC glad_glVertex3s = NULL;
-PFNGLVERTEX3SVPROC glad_glVertex3sv = NULL;
-PFNGLVERTEX4DPROC glad_glVertex4d = NULL;
-PFNGLVERTEX4DVPROC glad_glVertex4dv = NULL;
-PFNGLVERTEX4FPROC glad_glVertex4f = NULL;
-PFNGLVERTEX4FVPROC glad_glVertex4fv = NULL;
-PFNGLVERTEX4IPROC glad_glVertex4i = NULL;
-PFNGLVERTEX4IVPROC glad_glVertex4iv = NULL;
-PFNGLVERTEX4SPROC glad_glVertex4s = NULL;
-PFNGLVERTEX4SVPROC glad_glVertex4sv = NULL;
-PFNGLVERTEXATTRIB1DPROC glad_glVertexAttrib1d = NULL;
-PFNGLVERTEXATTRIB1DVPROC glad_glVertexAttrib1dv = NULL;
-PFNGLVERTEXATTRIB1FPROC glad_glVertexAttrib1f = NULL;
-PFNGLVERTEXATTRIB1FVPROC glad_glVertexAttrib1fv = NULL;
-PFNGLVERTEXATTRIB1SPROC glad_glVertexAttrib1s = NULL;
-PFNGLVERTEXATTRIB1SVPROC glad_glVertexAttrib1sv = NULL;
-PFNGLVERTEXATTRIB2DPROC glad_glVertexAttrib2d = NULL;
-PFNGLVERTEXATTRIB2DVPROC glad_glVertexAttrib2dv = NULL;
-PFNGLVERTEXATTRIB2FPROC glad_glVertexAttrib2f = NULL;
-PFNGLVERTEXATTRIB2FVPROC glad_glVertexAttrib2fv = NULL;
-PFNGLVERTEXATTRIB2SPROC glad_glVertexAttrib2s = NULL;
-PFNGLVERTEXATTRIB2SVPROC glad_glVertexAttrib2sv = NULL;
-PFNGLVERTEXATTRIB3DPROC glad_glVertexAttrib3d = NULL;
-PFNGLVERTEXATTRIB3DVPROC glad_glVertexAttrib3dv = NULL;
-PFNGLVERTEXATTRIB3FPROC glad_glVertexAttrib3f = NULL;
-PFNGLVERTEXATTRIB3FVPROC glad_glVertexAttrib3fv = NULL;
-PFNGLVERTEXATTRIB3SPROC glad_glVertexAttrib3s = NULL;
-PFNGLVERTEXATTRIB3SVPROC glad_glVertexAttrib3sv = NULL;
-PFNGLVERTEXATTRIB4NBVPROC glad_glVertexAttrib4Nbv = NULL;
-PFNGLVERTEXATTRIB4NIVPROC glad_glVertexAttrib4Niv = NULL;
-PFNGLVERTEXATTRIB4NSVPROC glad_glVertexAttrib4Nsv = NULL;
-PFNGLVERTEXATTRIB4NUBPROC glad_glVertexAttrib4Nub = NULL;
-PFNGLVERTEXATTRIB4NUBVPROC glad_glVertexAttrib4Nubv = NULL;
-PFNGLVERTEXATTRIB4NUIVPROC glad_glVertexAttrib4Nuiv = NULL;
-PFNGLVERTEXATTRIB4NUSVPROC glad_glVertexAttrib4Nusv = NULL;
-PFNGLVERTEXATTRIB4BVPROC glad_glVertexAttrib4bv = NULL;
-PFNGLVERTEXATTRIB4DPROC glad_glVertexAttrib4d = NULL;
-PFNGLVERTEXATTRIB4DVPROC glad_glVertexAttrib4dv = NULL;
-PFNGLVERTEXATTRIB4FPROC glad_glVertexAttrib4f = NULL;
-PFNGLVERTEXATTRIB4FVPROC glad_glVertexAttrib4fv = NULL;
-PFNGLVERTEXATTRIB4IVPROC glad_glVertexAttrib4iv = NULL;
-PFNGLVERTEXATTRIB4SPROC glad_glVertexAttrib4s = NULL;
-PFNGLVERTEXATTRIB4SVPROC glad_glVertexAttrib4sv = NULL;
-PFNGLVERTEXATTRIB4UBVPROC glad_glVertexAttrib4ubv = NULL;
-PFNGLVERTEXATTRIB4UIVPROC glad_glVertexAttrib4uiv = NULL;
-PFNGLVERTEXATTRIB4USVPROC glad_glVertexAttrib4usv = NULL;
-PFNGLVERTEXATTRIBDIVISORPROC glad_glVertexAttribDivisor = NULL;
-PFNGLVERTEXATTRIBI1IPROC glad_glVertexAttribI1i = NULL;
-PFNGLVERTEXATTRIBI1IVPROC glad_glVertexAttribI1iv = NULL;
-PFNGLVERTEXATTRIBI1UIPROC glad_glVertexAttribI1ui = NULL;
-PFNGLVERTEXATTRIBI1UIVPROC glad_glVertexAttribI1uiv = NULL;
-PFNGLVERTEXATTRIBI2IPROC glad_glVertexAttribI2i = NULL;
-PFNGLVERTEXATTRIBI2IVPROC glad_glVertexAttribI2iv = NULL;
-PFNGLVERTEXATTRIBI2UIPROC glad_glVertexAttribI2ui = NULL;
-PFNGLVERTEXATTRIBI2UIVPROC glad_glVertexAttribI2uiv = NULL;
-PFNGLVERTEXATTRIBI3IPROC glad_glVertexAttribI3i = NULL;
-PFNGLVERTEXATTRIBI3IVPROC glad_glVertexAttribI3iv = NULL;
-PFNGLVERTEXATTRIBI3UIPROC glad_glVertexAttribI3ui = NULL;
-PFNGLVERTEXATTRIBI3UIVPROC glad_glVertexAttribI3uiv = NULL;
-PFNGLVERTEXATTRIBI4BVPROC glad_glVertexAttribI4bv = NULL;
-PFNGLVERTEXATTRIBI4IPROC glad_glVertexAttribI4i = NULL;
-PFNGLVERTEXATTRIBI4IVPROC glad_glVertexAttribI4iv = NULL;
-PFNGLVERTEXATTRIBI4SVPROC glad_glVertexAttribI4sv = NULL;
-PFNGLVERTEXATTRIBI4UBVPROC glad_glVertexAttribI4ubv = NULL;
-PFNGLVERTEXATTRIBI4UIPROC glad_glVertexAttribI4ui = NULL;
-PFNGLVERTEXATTRIBI4UIVPROC glad_glVertexAttribI4uiv = NULL;
-PFNGLVERTEXATTRIBI4USVPROC glad_glVertexAttribI4usv = NULL;
-PFNGLVERTEXATTRIBIPOINTERPROC glad_glVertexAttribIPointer = NULL;
-PFNGLVERTEXATTRIBP1UIPROC glad_glVertexAttribP1ui = NULL;
-PFNGLVERTEXATTRIBP1UIVPROC glad_glVertexAttribP1uiv = NULL;
-PFNGLVERTEXATTRIBP2UIPROC glad_glVertexAttribP2ui = NULL;
-PFNGLVERTEXATTRIBP2UIVPROC glad_glVertexAttribP2uiv = NULL;
-PFNGLVERTEXATTRIBP3UIPROC glad_glVertexAttribP3ui = NULL;
-PFNGLVERTEXATTRIBP3UIVPROC glad_glVertexAttribP3uiv = NULL;
-PFNGLVERTEXATTRIBP4UIPROC glad_glVertexAttribP4ui = NULL;
-PFNGLVERTEXATTRIBP4UIVPROC glad_glVertexAttribP4uiv = NULL;
-PFNGLVERTEXATTRIBPOINTERPROC glad_glVertexAttribPointer = NULL;
-PFNGLVERTEXP2UIPROC glad_glVertexP2ui = NULL;
-PFNGLVERTEXP2UIVPROC glad_glVertexP2uiv = NULL;
-PFNGLVERTEXP3UIPROC glad_glVertexP3ui = NULL;
-PFNGLVERTEXP3UIVPROC glad_glVertexP3uiv = NULL;
-PFNGLVERTEXP4UIPROC glad_glVertexP4ui = NULL;
-PFNGLVERTEXP4UIVPROC glad_glVertexP4uiv = NULL;
-PFNGLVERTEXPOINTERPROC glad_glVertexPointer = NULL;
-PFNGLVIEWPORTPROC glad_glViewport = NULL;
-PFNGLWAITSYNCPROC glad_glWaitSync = NULL;
-PFNGLWINDOWPOS2DPROC glad_glWindowPos2d = NULL;
-PFNGLWINDOWPOS2DVPROC glad_glWindowPos2dv = NULL;
-PFNGLWINDOWPOS2FPROC glad_glWindowPos2f = NULL;
-PFNGLWINDOWPOS2FVPROC glad_glWindowPos2fv = NULL;
-PFNGLWINDOWPOS2IPROC glad_glWindowPos2i = NULL;
-PFNGLWINDOWPOS2IVPROC glad_glWindowPos2iv = NULL;
-PFNGLWINDOWPOS2SPROC glad_glWindowPos2s = NULL;
-PFNGLWINDOWPOS2SVPROC glad_glWindowPos2sv = NULL;
-PFNGLWINDOWPOS3DPROC glad_glWindowPos3d = NULL;
-PFNGLWINDOWPOS3DVPROC glad_glWindowPos3dv = NULL;
-PFNGLWINDOWPOS3FPROC glad_glWindowPos3f = NULL;
-PFNGLWINDOWPOS3FVPROC glad_glWindowPos3fv = NULL;
-PFNGLWINDOWPOS3IPROC glad_glWindowPos3i = NULL;
-PFNGLWINDOWPOS3IVPROC glad_glWindowPos3iv = NULL;
-PFNGLWINDOWPOS3SPROC glad_glWindowPos3s = NULL;
-PFNGLWINDOWPOS3SVPROC glad_glWindowPos3sv = NULL;
-int GLAD_GL_ARB_debug_output = 0;
-int GLAD_GL_ARB_framebuffer_object = 0;
-int GLAD_GL_EXT_framebuffer_blit = 0;
-int GLAD_GL_EXT_framebuffer_multisample = 0;
-int GLAD_GL_EXT_framebuffer_object = 0;
-int GLAD_GL_OVR_multiview = 0;
-int GLAD_GL_OVR_multiview2 = 0;
-PFNGLDEBUGMESSAGECONTROLARBPROC glad_glDebugMessageControlARB = NULL;
-PFNGLDEBUGMESSAGEINSERTARBPROC glad_glDebugMessageInsertARB = NULL;
-PFNGLDEBUGMESSAGECALLBACKARBPROC glad_glDebugMessageCallbackARB = NULL;
-PFNGLGETDEBUGMESSAGELOGARBPROC glad_glGetDebugMessageLogARB = NULL;
-PFNGLBLITFRAMEBUFFEREXTPROC glad_glBlitFramebufferEXT = NULL;
-PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC glad_glRenderbufferStorageMultisampleEXT = NULL;
-PFNGLISRENDERBUFFEREXTPROC glad_glIsRenderbufferEXT = NULL;
-PFNGLBINDRENDERBUFFEREXTPROC glad_glBindRenderbufferEXT = NULL;
-PFNGLDELETERENDERBUFFERSEXTPROC glad_glDeleteRenderbuffersEXT = NULL;
-PFNGLGENRENDERBUFFERSEXTPROC glad_glGenRenderbuffersEXT = NULL;
-PFNGLRENDERBUFFERSTORAGEEXTPROC glad_glRenderbufferStorageEXT = NULL;
-PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC glad_glGetRenderbufferParameterivEXT = NULL;
-PFNGLISFRAMEBUFFEREXTPROC glad_glIsFramebufferEXT = NULL;
-PFNGLBINDFRAMEBUFFEREXTPROC glad_glBindFramebufferEXT = NULL;
-PFNGLDELETEFRAMEBUFFERSEXTPROC glad_glDeleteFramebuffersEXT = NULL;
-PFNGLGENFRAMEBUFFERSEXTPROC glad_glGenFramebuffersEXT = NULL;
-PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC glad_glCheckFramebufferStatusEXT = NULL;
-PFNGLFRAMEBUFFERTEXTURE1DEXTPROC glad_glFramebufferTexture1DEXT = NULL;
-PFNGLFRAMEBUFFERTEXTURE2DEXTPROC glad_glFramebufferTexture2DEXT = NULL;
-PFNGLFRAMEBUFFERTEXTURE3DEXTPROC glad_glFramebufferTexture3DEXT = NULL;
-PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glad_glFramebufferRenderbufferEXT = NULL;
-PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC glad_glGetFramebufferAttachmentParameterivEXT = NULL;
-PFNGLGENERATEMIPMAPEXTPROC glad_glGenerateMipmapEXT = NULL;
-PFNGLFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC glad_glFramebufferTextureMultiviewOVR = NULL;
-static void load_GL_VERSION_1_0(GLADloadproc load) {
- if(!GLAD_GL_VERSION_1_0) return;
- glad_glCullFace = (PFNGLCULLFACEPROC)load("glCullFace");
- glad_glFrontFace = (PFNGLFRONTFACEPROC)load("glFrontFace");
- glad_glHint = (PFNGLHINTPROC)load("glHint");
- glad_glLineWidth = (PFNGLLINEWIDTHPROC)load("glLineWidth");
- glad_glPointSize = (PFNGLPOINTSIZEPROC)load("glPointSize");
- glad_glPolygonMode = (PFNGLPOLYGONMODEPROC)load("glPolygonMode");
- glad_glScissor = (PFNGLSCISSORPROC)load("glScissor");
- glad_glTexParameterf = (PFNGLTEXPARAMETERFPROC)load("glTexParameterf");
- glad_glTexParameterfv = (PFNGLTEXPARAMETERFVPROC)load("glTexParameterfv");
- glad_glTexParameteri = (PFNGLTEXPARAMETERIPROC)load("glTexParameteri");
- glad_glTexParameteriv = (PFNGLTEXPARAMETERIVPROC)load("glTexParameteriv");
- glad_glTexImage1D = (PFNGLTEXIMAGE1DPROC)load("glTexImage1D");
- glad_glTexImage2D = (PFNGLTEXIMAGE2DPROC)load("glTexImage2D");
- glad_glDrawBuffer = (PFNGLDRAWBUFFERPROC)load("glDrawBuffer");
- glad_glClear = (PFNGLCLEARPROC)load("glClear");
- glad_glClearColor = (PFNGLCLEARCOLORPROC)load("glClearColor");
- glad_glClearStencil = (PFNGLCLEARSTENCILPROC)load("glClearStencil");
- glad_glClearDepth = (PFNGLCLEARDEPTHPROC)load("glClearDepth");
- glad_glStencilMask = (PFNGLSTENCILMASKPROC)load("glStencilMask");
- glad_glColorMask = (PFNGLCOLORMASKPROC)load("glColorMask");
- glad_glDepthMask = (PFNGLDEPTHMASKPROC)load("glDepthMask");
- glad_glDisable = (PFNGLDISABLEPROC)load("glDisable");
- glad_glEnable = (PFNGLENABLEPROC)load("glEnable");
- glad_glFinish = (PFNGLFINISHPROC)load("glFinish");
- glad_glFlush = (PFNGLFLUSHPROC)load("glFlush");
- glad_glBlendFunc = (PFNGLBLENDFUNCPROC)load("glBlendFunc");
- glad_glLogicOp = (PFNGLLOGICOPPROC)load("glLogicOp");
- glad_glStencilFunc = (PFNGLSTENCILFUNCPROC)load("glStencilFunc");
- glad_glStencilOp = (PFNGLSTENCILOPPROC)load("glStencilOp");
- glad_glDepthFunc = (PFNGLDEPTHFUNCPROC)load("glDepthFunc");
- glad_glPixelStoref = (PFNGLPIXELSTOREFPROC)load("glPixelStoref");
- glad_glPixelStorei = (PFNGLPIXELSTOREIPROC)load("glPixelStorei");
- glad_glReadBuffer = (PFNGLREADBUFFERPROC)load("glReadBuffer");
- glad_glReadPixels = (PFNGLREADPIXELSPROC)load("glReadPixels");
- glad_glGetBooleanv = (PFNGLGETBOOLEANVPROC)load("glGetBooleanv");
- glad_glGetDoublev = (PFNGLGETDOUBLEVPROC)load("glGetDoublev");
- glad_glGetError = (PFNGLGETERRORPROC)load("glGetError");
- glad_glGetFloatv = (PFNGLGETFLOATVPROC)load("glGetFloatv");
- glad_glGetIntegerv = (PFNGLGETINTEGERVPROC)load("glGetIntegerv");
- glad_glGetString = (PFNGLGETSTRINGPROC)load("glGetString");
- glad_glGetTexImage = (PFNGLGETTEXIMAGEPROC)load("glGetTexImage");
- glad_glGetTexParameterfv = (PFNGLGETTEXPARAMETERFVPROC)load("glGetTexParameterfv");
- glad_glGetTexParameteriv = (PFNGLGETTEXPARAMETERIVPROC)load("glGetTexParameteriv");
- glad_glGetTexLevelParameterfv = (PFNGLGETTEXLEVELPARAMETERFVPROC)load("glGetTexLevelParameterfv");
- glad_glGetTexLevelParameteriv = (PFNGLGETTEXLEVELPARAMETERIVPROC)load("glGetTexLevelParameteriv");
- glad_glIsEnabled = (PFNGLISENABLEDPROC)load("glIsEnabled");
- glad_glDepthRange = (PFNGLDEPTHRANGEPROC)load("glDepthRange");
- glad_glViewport = (PFNGLVIEWPORTPROC)load("glViewport");
- glad_glNewList = (PFNGLNEWLISTPROC)load("glNewList");
- glad_glEndList = (PFNGLENDLISTPROC)load("glEndList");
- glad_glCallList = (PFNGLCALLLISTPROC)load("glCallList");
- glad_glCallLists = (PFNGLCALLLISTSPROC)load("glCallLists");
- glad_glDeleteLists = (PFNGLDELETELISTSPROC)load("glDeleteLists");
- glad_glGenLists = (PFNGLGENLISTSPROC)load("glGenLists");
- glad_glListBase = (PFNGLLISTBASEPROC)load("glListBase");
- glad_glBegin = (PFNGLBEGINPROC)load("glBegin");
- glad_glBitmap = (PFNGLBITMAPPROC)load("glBitmap");
- glad_glColor3b = (PFNGLCOLOR3BPROC)load("glColor3b");
- glad_glColor3bv = (PFNGLCOLOR3BVPROC)load("glColor3bv");
- glad_glColor3d = (PFNGLCOLOR3DPROC)load("glColor3d");
- glad_glColor3dv = (PFNGLCOLOR3DVPROC)load("glColor3dv");
- glad_glColor3f = (PFNGLCOLOR3FPROC)load("glColor3f");
- glad_glColor3fv = (PFNGLCOLOR3FVPROC)load("glColor3fv");
- glad_glColor3i = (PFNGLCOLOR3IPROC)load("glColor3i");
- glad_glColor3iv = (PFNGLCOLOR3IVPROC)load("glColor3iv");
- glad_glColor3s = (PFNGLCOLOR3SPROC)load("glColor3s");
- glad_glColor3sv = (PFNGLCOLOR3SVPROC)load("glColor3sv");
- glad_glColor3ub = (PFNGLCOLOR3UBPROC)load("glColor3ub");
- glad_glColor3ubv = (PFNGLCOLOR3UBVPROC)load("glColor3ubv");
- glad_glColor3ui = (PFNGLCOLOR3UIPROC)load("glColor3ui");
- glad_glColor3uiv = (PFNGLCOLOR3UIVPROC)load("glColor3uiv");
- glad_glColor3us = (PFNGLCOLOR3USPROC)load("glColor3us");
- glad_glColor3usv = (PFNGLCOLOR3USVPROC)load("glColor3usv");
- glad_glColor4b = (PFNGLCOLOR4BPROC)load("glColor4b");
- glad_glColor4bv = (PFNGLCOLOR4BVPROC)load("glColor4bv");
- glad_glColor4d = (PFNGLCOLOR4DPROC)load("glColor4d");
- glad_glColor4dv = (PFNGLCOLOR4DVPROC)load("glColor4dv");
- glad_glColor4f = (PFNGLCOLOR4FPROC)load("glColor4f");
- glad_glColor4fv = (PFNGLCOLOR4FVPROC)load("glColor4fv");
- glad_glColor4i = (PFNGLCOLOR4IPROC)load("glColor4i");
- glad_glColor4iv = (PFNGLCOLOR4IVPROC)load("glColor4iv");
- glad_glColor4s = (PFNGLCOLOR4SPROC)load("glColor4s");
- glad_glColor4sv = (PFNGLCOLOR4SVPROC)load("glColor4sv");
- glad_glColor4ub = (PFNGLCOLOR4UBPROC)load("glColor4ub");
- glad_glColor4ubv = (PFNGLCOLOR4UBVPROC)load("glColor4ubv");
- glad_glColor4ui = (PFNGLCOLOR4UIPROC)load("glColor4ui");
- glad_glColor4uiv = (PFNGLCOLOR4UIVPROC)load("glColor4uiv");
- glad_glColor4us = (PFNGLCOLOR4USPROC)load("glColor4us");
- glad_glColor4usv = (PFNGLCOLOR4USVPROC)load("glColor4usv");
- glad_glEdgeFlag = (PFNGLEDGEFLAGPROC)load("glEdgeFlag");
- glad_glEdgeFlagv = (PFNGLEDGEFLAGVPROC)load("glEdgeFlagv");
- glad_glEnd = (PFNGLENDPROC)load("glEnd");
- glad_glIndexd = (PFNGLINDEXDPROC)load("glIndexd");
- glad_glIndexdv = (PFNGLINDEXDVPROC)load("glIndexdv");
- glad_glIndexf = (PFNGLINDEXFPROC)load("glIndexf");
- glad_glIndexfv = (PFNGLINDEXFVPROC)load("glIndexfv");
- glad_glIndexi = (PFNGLINDEXIPROC)load("glIndexi");
- glad_glIndexiv = (PFNGLINDEXIVPROC)load("glIndexiv");
- glad_glIndexs = (PFNGLINDEXSPROC)load("glIndexs");
- glad_glIndexsv = (PFNGLINDEXSVPROC)load("glIndexsv");
- glad_glNormal3b = (PFNGLNORMAL3BPROC)load("glNormal3b");
- glad_glNormal3bv = (PFNGLNORMAL3BVPROC)load("glNormal3bv");
- glad_glNormal3d = (PFNGLNORMAL3DPROC)load("glNormal3d");
- glad_glNormal3dv = (PFNGLNORMAL3DVPROC)load("glNormal3dv");
- glad_glNormal3f = (PFNGLNORMAL3FPROC)load("glNormal3f");
- glad_glNormal3fv = (PFNGLNORMAL3FVPROC)load("glNormal3fv");
- glad_glNormal3i = (PFNGLNORMAL3IPROC)load("glNormal3i");
- glad_glNormal3iv = (PFNGLNORMAL3IVPROC)load("glNormal3iv");
- glad_glNormal3s = (PFNGLNORMAL3SPROC)load("glNormal3s");
- glad_glNormal3sv = (PFNGLNORMAL3SVPROC)load("glNormal3sv");
- glad_glRasterPos2d = (PFNGLRASTERPOS2DPROC)load("glRasterPos2d");
- glad_glRasterPos2dv = (PFNGLRASTERPOS2DVPROC)load("glRasterPos2dv");
- glad_glRasterPos2f = (PFNGLRASTERPOS2FPROC)load("glRasterPos2f");
- glad_glRasterPos2fv = (PFNGLRASTERPOS2FVPROC)load("glRasterPos2fv");
- glad_glRasterPos2i = (PFNGLRASTERPOS2IPROC)load("glRasterPos2i");
- glad_glRasterPos2iv = (PFNGLRASTERPOS2IVPROC)load("glRasterPos2iv");
- glad_glRasterPos2s = (PFNGLRASTERPOS2SPROC)load("glRasterPos2s");
- glad_glRasterPos2sv = (PFNGLRASTERPOS2SVPROC)load("glRasterPos2sv");
- glad_glRasterPos3d = (PFNGLRASTERPOS3DPROC)load("glRasterPos3d");
- glad_glRasterPos3dv = (PFNGLRASTERPOS3DVPROC)load("glRasterPos3dv");
- glad_glRasterPos3f = (PFNGLRASTERPOS3FPROC)load("glRasterPos3f");
- glad_glRasterPos3fv = (PFNGLRASTERPOS3FVPROC)load("glRasterPos3fv");
- glad_glRasterPos3i = (PFNGLRASTERPOS3IPROC)load("glRasterPos3i");
- glad_glRasterPos3iv = (PFNGLRASTERPOS3IVPROC)load("glRasterPos3iv");
- glad_glRasterPos3s = (PFNGLRASTERPOS3SPROC)load("glRasterPos3s");
- glad_glRasterPos3sv = (PFNGLRASTERPOS3SVPROC)load("glRasterPos3sv");
- glad_glRasterPos4d = (PFNGLRASTERPOS4DPROC)load("glRasterPos4d");
- glad_glRasterPos4dv = (PFNGLRASTERPOS4DVPROC)load("glRasterPos4dv");
- glad_glRasterPos4f = (PFNGLRASTERPOS4FPROC)load("glRasterPos4f");
- glad_glRasterPos4fv = (PFNGLRASTERPOS4FVPROC)load("glRasterPos4fv");
- glad_glRasterPos4i = (PFNGLRASTERPOS4IPROC)load("glRasterPos4i");
- glad_glRasterPos4iv = (PFNGLRASTERPOS4IVPROC)load("glRasterPos4iv");
- glad_glRasterPos4s = (PFNGLRASTERPOS4SPROC)load("glRasterPos4s");
- glad_glRasterPos4sv = (PFNGLRASTERPOS4SVPROC)load("glRasterPos4sv");
- glad_glRectd = (PFNGLRECTDPROC)load("glRectd");
- glad_glRectdv = (PFNGLRECTDVPROC)load("glRectdv");
- glad_glRectf = (PFNGLRECTFPROC)load("glRectf");
- glad_glRectfv = (PFNGLRECTFVPROC)load("glRectfv");
- glad_glRecti = (PFNGLRECTIPROC)load("glRecti");
- glad_glRectiv = (PFNGLRECTIVPROC)load("glRectiv");
- glad_glRects = (PFNGLRECTSPROC)load("glRects");
- glad_glRectsv = (PFNGLRECTSVPROC)load("glRectsv");
- glad_glTexCoord1d = (PFNGLTEXCOORD1DPROC)load("glTexCoord1d");
- glad_glTexCoord1dv = (PFNGLTEXCOORD1DVPROC)load("glTexCoord1dv");
- glad_glTexCoord1f = (PFNGLTEXCOORD1FPROC)load("glTexCoord1f");
- glad_glTexCoord1fv = (PFNGLTEXCOORD1FVPROC)load("glTexCoord1fv");
- glad_glTexCoord1i = (PFNGLTEXCOORD1IPROC)load("glTexCoord1i");
- glad_glTexCoord1iv = (PFNGLTEXCOORD1IVPROC)load("glTexCoord1iv");
- glad_glTexCoord1s = (PFNGLTEXCOORD1SPROC)load("glTexCoord1s");
- glad_glTexCoord1sv = (PFNGLTEXCOORD1SVPROC)load("glTexCoord1sv");
- glad_glTexCoord2d = (PFNGLTEXCOORD2DPROC)load("glTexCoord2d");
- glad_glTexCoord2dv = (PFNGLTEXCOORD2DVPROC)load("glTexCoord2dv");
- glad_glTexCoord2f = (PFNGLTEXCOORD2FPROC)load("glTexCoord2f");
- glad_glTexCoord2fv = (PFNGLTEXCOORD2FVPROC)load("glTexCoord2fv");
- glad_glTexCoord2i = (PFNGLTEXCOORD2IPROC)load("glTexCoord2i");
- glad_glTexCoord2iv = (PFNGLTEXCOORD2IVPROC)load("glTexCoord2iv");
- glad_glTexCoord2s = (PFNGLTEXCOORD2SPROC)load("glTexCoord2s");
- glad_glTexCoord2sv = (PFNGLTEXCOORD2SVPROC)load("glTexCoord2sv");
- glad_glTexCoord3d = (PFNGLTEXCOORD3DPROC)load("glTexCoord3d");
- glad_glTexCoord3dv = (PFNGLTEXCOORD3DVPROC)load("glTexCoord3dv");
- glad_glTexCoord3f = (PFNGLTEXCOORD3FPROC)load("glTexCoord3f");
- glad_glTexCoord3fv = (PFNGLTEXCOORD3FVPROC)load("glTexCoord3fv");
- glad_glTexCoord3i = (PFNGLTEXCOORD3IPROC)load("glTexCoord3i");
- glad_glTexCoord3iv = (PFNGLTEXCOORD3IVPROC)load("glTexCoord3iv");
- glad_glTexCoord3s = (PFNGLTEXCOORD3SPROC)load("glTexCoord3s");
- glad_glTexCoord3sv = (PFNGLTEXCOORD3SVPROC)load("glTexCoord3sv");
- glad_glTexCoord4d = (PFNGLTEXCOORD4DPROC)load("glTexCoord4d");
- glad_glTexCoord4dv = (PFNGLTEXCOORD4DVPROC)load("glTexCoord4dv");
- glad_glTexCoord4f = (PFNGLTEXCOORD4FPROC)load("glTexCoord4f");
- glad_glTexCoord4fv = (PFNGLTEXCOORD4FVPROC)load("glTexCoord4fv");
- glad_glTexCoord4i = (PFNGLTEXCOORD4IPROC)load("glTexCoord4i");
- glad_glTexCoord4iv = (PFNGLTEXCOORD4IVPROC)load("glTexCoord4iv");
- glad_glTexCoord4s = (PFNGLTEXCOORD4SPROC)load("glTexCoord4s");
- glad_glTexCoord4sv = (PFNGLTEXCOORD4SVPROC)load("glTexCoord4sv");
- glad_glVertex2d = (PFNGLVERTEX2DPROC)load("glVertex2d");
- glad_glVertex2dv = (PFNGLVERTEX2DVPROC)load("glVertex2dv");
- glad_glVertex2f = (PFNGLVERTEX2FPROC)load("glVertex2f");
- glad_glVertex2fv = (PFNGLVERTEX2FVPROC)load("glVertex2fv");
- glad_glVertex2i = (PFNGLVERTEX2IPROC)load("glVertex2i");
- glad_glVertex2iv = (PFNGLVERTEX2IVPROC)load("glVertex2iv");
- glad_glVertex2s = (PFNGLVERTEX2SPROC)load("glVertex2s");
- glad_glVertex2sv = (PFNGLVERTEX2SVPROC)load("glVertex2sv");
- glad_glVertex3d = (PFNGLVERTEX3DPROC)load("glVertex3d");
- glad_glVertex3dv = (PFNGLVERTEX3DVPROC)load("glVertex3dv");
- glad_glVertex3f = (PFNGLVERTEX3FPROC)load("glVertex3f");
- glad_glVertex3fv = (PFNGLVERTEX3FVPROC)load("glVertex3fv");
- glad_glVertex3i = (PFNGLVERTEX3IPROC)load("glVertex3i");
- glad_glVertex3iv = (PFNGLVERTEX3IVPROC)load("glVertex3iv");
- glad_glVertex3s = (PFNGLVERTEX3SPROC)load("glVertex3s");
- glad_glVertex3sv = (PFNGLVERTEX3SVPROC)load("glVertex3sv");
- glad_glVertex4d = (PFNGLVERTEX4DPROC)load("glVertex4d");
- glad_glVertex4dv = (PFNGLVERTEX4DVPROC)load("glVertex4dv");
- glad_glVertex4f = (PFNGLVERTEX4FPROC)load("glVertex4f");
- glad_glVertex4fv = (PFNGLVERTEX4FVPROC)load("glVertex4fv");
- glad_glVertex4i = (PFNGLVERTEX4IPROC)load("glVertex4i");
- glad_glVertex4iv = (PFNGLVERTEX4IVPROC)load("glVertex4iv");
- glad_glVertex4s = (PFNGLVERTEX4SPROC)load("glVertex4s");
- glad_glVertex4sv = (PFNGLVERTEX4SVPROC)load("glVertex4sv");
- glad_glClipPlane = (PFNGLCLIPPLANEPROC)load("glClipPlane");
- glad_glColorMaterial = (PFNGLCOLORMATERIALPROC)load("glColorMaterial");
- glad_glFogf = (PFNGLFOGFPROC)load("glFogf");
- glad_glFogfv = (PFNGLFOGFVPROC)load("glFogfv");
- glad_glFogi = (PFNGLFOGIPROC)load("glFogi");
- glad_glFogiv = (PFNGLFOGIVPROC)load("glFogiv");
- glad_glLightf = (PFNGLLIGHTFPROC)load("glLightf");
- glad_glLightfv = (PFNGLLIGHTFVPROC)load("glLightfv");
- glad_glLighti = (PFNGLLIGHTIPROC)load("glLighti");
- glad_glLightiv = (PFNGLLIGHTIVPROC)load("glLightiv");
- glad_glLightModelf = (PFNGLLIGHTMODELFPROC)load("glLightModelf");
- glad_glLightModelfv = (PFNGLLIGHTMODELFVPROC)load("glLightModelfv");
- glad_glLightModeli = (PFNGLLIGHTMODELIPROC)load("glLightModeli");
- glad_glLightModeliv = (PFNGLLIGHTMODELIVPROC)load("glLightModeliv");
- glad_glLineStipple = (PFNGLLINESTIPPLEPROC)load("glLineStipple");
- glad_glMaterialf = (PFNGLMATERIALFPROC)load("glMaterialf");
- glad_glMaterialfv = (PFNGLMATERIALFVPROC)load("glMaterialfv");
- glad_glMateriali = (PFNGLMATERIALIPROC)load("glMateriali");
- glad_glMaterialiv = (PFNGLMATERIALIVPROC)load("glMaterialiv");
- glad_glPolygonStipple = (PFNGLPOLYGONSTIPPLEPROC)load("glPolygonStipple");
- glad_glShadeModel = (PFNGLSHADEMODELPROC)load("glShadeModel");
- glad_glTexEnvf = (PFNGLTEXENVFPROC)load("glTexEnvf");
- glad_glTexEnvfv = (PFNGLTEXENVFVPROC)load("glTexEnvfv");
- glad_glTexEnvi = (PFNGLTEXENVIPROC)load("glTexEnvi");
- glad_glTexEnviv = (PFNGLTEXENVIVPROC)load("glTexEnviv");
- glad_glTexGend = (PFNGLTEXGENDPROC)load("glTexGend");
- glad_glTexGendv = (PFNGLTEXGENDVPROC)load("glTexGendv");
- glad_glTexGenf = (PFNGLTEXGENFPROC)load("glTexGenf");
- glad_glTexGenfv = (PFNGLTEXGENFVPROC)load("glTexGenfv");
- glad_glTexGeni = (PFNGLTEXGENIPROC)load("glTexGeni");
- glad_glTexGeniv = (PFNGLTEXGENIVPROC)load("glTexGeniv");
- glad_glFeedbackBuffer = (PFNGLFEEDBACKBUFFERPROC)load("glFeedbackBuffer");
- glad_glSelectBuffer = (PFNGLSELECTBUFFERPROC)load("glSelectBuffer");
- glad_glRenderMode = (PFNGLRENDERMODEPROC)load("glRenderMode");
- glad_glInitNames = (PFNGLINITNAMESPROC)load("glInitNames");
- glad_glLoadName = (PFNGLLOADNAMEPROC)load("glLoadName");
- glad_glPassThrough = (PFNGLPASSTHROUGHPROC)load("glPassThrough");
- glad_glPopName = (PFNGLPOPNAMEPROC)load("glPopName");
- glad_glPushName = (PFNGLPUSHNAMEPROC)load("glPushName");
- glad_glClearAccum = (PFNGLCLEARACCUMPROC)load("glClearAccum");
- glad_glClearIndex = (PFNGLCLEARINDEXPROC)load("glClearIndex");
- glad_glIndexMask = (PFNGLINDEXMASKPROC)load("glIndexMask");
- glad_glAccum = (PFNGLACCUMPROC)load("glAccum");
- glad_glPopAttrib = (PFNGLPOPATTRIBPROC)load("glPopAttrib");
- glad_glPushAttrib = (PFNGLPUSHATTRIBPROC)load("glPushAttrib");
- glad_glMap1d = (PFNGLMAP1DPROC)load("glMap1d");
- glad_glMap1f = (PFNGLMAP1FPROC)load("glMap1f");
- glad_glMap2d = (PFNGLMAP2DPROC)load("glMap2d");
- glad_glMap2f = (PFNGLMAP2FPROC)load("glMap2f");
- glad_glMapGrid1d = (PFNGLMAPGRID1DPROC)load("glMapGrid1d");
- glad_glMapGrid1f = (PFNGLMAPGRID1FPROC)load("glMapGrid1f");
- glad_glMapGrid2d = (PFNGLMAPGRID2DPROC)load("glMapGrid2d");
- glad_glMapGrid2f = (PFNGLMAPGRID2FPROC)load("glMapGrid2f");
- glad_glEvalCoord1d = (PFNGLEVALCOORD1DPROC)load("glEvalCoord1d");
- glad_glEvalCoord1dv = (PFNGLEVALCOORD1DVPROC)load("glEvalCoord1dv");
- glad_glEvalCoord1f = (PFNGLEVALCOORD1FPROC)load("glEvalCoord1f");
- glad_glEvalCoord1fv = (PFNGLEVALCOORD1FVPROC)load("glEvalCoord1fv");
- glad_glEvalCoord2d = (PFNGLEVALCOORD2DPROC)load("glEvalCoord2d");
- glad_glEvalCoord2dv = (PFNGLEVALCOORD2DVPROC)load("glEvalCoord2dv");
- glad_glEvalCoord2f = (PFNGLEVALCOORD2FPROC)load("glEvalCoord2f");
- glad_glEvalCoord2fv = (PFNGLEVALCOORD2FVPROC)load("glEvalCoord2fv");
- glad_glEvalMesh1 = (PFNGLEVALMESH1PROC)load("glEvalMesh1");
- glad_glEvalPoint1 = (PFNGLEVALPOINT1PROC)load("glEvalPoint1");
- glad_glEvalMesh2 = (PFNGLEVALMESH2PROC)load("glEvalMesh2");
- glad_glEvalPoint2 = (PFNGLEVALPOINT2PROC)load("glEvalPoint2");
- glad_glAlphaFunc = (PFNGLALPHAFUNCPROC)load("glAlphaFunc");
- glad_glPixelZoom = (PFNGLPIXELZOOMPROC)load("glPixelZoom");
- glad_glPixelTransferf = (PFNGLPIXELTRANSFERFPROC)load("glPixelTransferf");
- glad_glPixelTransferi = (PFNGLPIXELTRANSFERIPROC)load("glPixelTransferi");
- glad_glPixelMapfv = (PFNGLPIXELMAPFVPROC)load("glPixelMapfv");
- glad_glPixelMapuiv = (PFNGLPIXELMAPUIVPROC)load("glPixelMapuiv");
- glad_glPixelMapusv = (PFNGLPIXELMAPUSVPROC)load("glPixelMapusv");
- glad_glCopyPixels = (PFNGLCOPYPIXELSPROC)load("glCopyPixels");
- glad_glDrawPixels = (PFNGLDRAWPIXELSPROC)load("glDrawPixels");
- glad_glGetClipPlane = (PFNGLGETCLIPPLANEPROC)load("glGetClipPlane");
- glad_glGetLightfv = (PFNGLGETLIGHTFVPROC)load("glGetLightfv");
- glad_glGetLightiv = (PFNGLGETLIGHTIVPROC)load("glGetLightiv");
- glad_glGetMapdv = (PFNGLGETMAPDVPROC)load("glGetMapdv");
- glad_glGetMapfv = (PFNGLGETMAPFVPROC)load("glGetMapfv");
- glad_glGetMapiv = (PFNGLGETMAPIVPROC)load("glGetMapiv");
- glad_glGetMaterialfv = (PFNGLGETMATERIALFVPROC)load("glGetMaterialfv");
- glad_glGetMaterialiv = (PFNGLGETMATERIALIVPROC)load("glGetMaterialiv");
- glad_glGetPixelMapfv = (PFNGLGETPIXELMAPFVPROC)load("glGetPixelMapfv");
- glad_glGetPixelMapuiv = (PFNGLGETPIXELMAPUIVPROC)load("glGetPixelMapuiv");
- glad_glGetPixelMapusv = (PFNGLGETPIXELMAPUSVPROC)load("glGetPixelMapusv");
- glad_glGetPolygonStipple = (PFNGLGETPOLYGONSTIPPLEPROC)load("glGetPolygonStipple");
- glad_glGetTexEnvfv = (PFNGLGETTEXENVFVPROC)load("glGetTexEnvfv");
- glad_glGetTexEnviv = (PFNGLGETTEXENVIVPROC)load("glGetTexEnviv");
- glad_glGetTexGendv = (PFNGLGETTEXGENDVPROC)load("glGetTexGendv");
- glad_glGetTexGenfv = (PFNGLGETTEXGENFVPROC)load("glGetTexGenfv");
- glad_glGetTexGeniv = (PFNGLGETTEXGENIVPROC)load("glGetTexGeniv");
- glad_glIsList = (PFNGLISLISTPROC)load("glIsList");
- glad_glFrustum = (PFNGLFRUSTUMPROC)load("glFrustum");
- glad_glLoadIdentity = (PFNGLLOADIDENTITYPROC)load("glLoadIdentity");
- glad_glLoadMatrixf = (PFNGLLOADMATRIXFPROC)load("glLoadMatrixf");
- glad_glLoadMatrixd = (PFNGLLOADMATRIXDPROC)load("glLoadMatrixd");
- glad_glMatrixMode = (PFNGLMATRIXMODEPROC)load("glMatrixMode");
- glad_glMultMatrixf = (PFNGLMULTMATRIXFPROC)load("glMultMatrixf");
- glad_glMultMatrixd = (PFNGLMULTMATRIXDPROC)load("glMultMatrixd");
- glad_glOrtho = (PFNGLORTHOPROC)load("glOrtho");
- glad_glPopMatrix = (PFNGLPOPMATRIXPROC)load("glPopMatrix");
- glad_glPushMatrix = (PFNGLPUSHMATRIXPROC)load("glPushMatrix");
- glad_glRotated = (PFNGLROTATEDPROC)load("glRotated");
- glad_glRotatef = (PFNGLROTATEFPROC)load("glRotatef");
- glad_glScaled = (PFNGLSCALEDPROC)load("glScaled");
- glad_glScalef = (PFNGLSCALEFPROC)load("glScalef");
- glad_glTranslated = (PFNGLTRANSLATEDPROC)load("glTranslated");
- glad_glTranslatef = (PFNGLTRANSLATEFPROC)load("glTranslatef");
-}
-static void load_GL_VERSION_1_1(GLADloadproc load) {
- if(!GLAD_GL_VERSION_1_1) return;
- glad_glDrawArrays = (PFNGLDRAWARRAYSPROC)load("glDrawArrays");
- glad_glDrawElements = (PFNGLDRAWELEMENTSPROC)load("glDrawElements");
- glad_glGetPointerv = (PFNGLGETPOINTERVPROC)load("glGetPointerv");
- glad_glPolygonOffset = (PFNGLPOLYGONOFFSETPROC)load("glPolygonOffset");
- glad_glCopyTexImage1D = (PFNGLCOPYTEXIMAGE1DPROC)load("glCopyTexImage1D");
- glad_glCopyTexImage2D = (PFNGLCOPYTEXIMAGE2DPROC)load("glCopyTexImage2D");
- glad_glCopyTexSubImage1D = (PFNGLCOPYTEXSUBIMAGE1DPROC)load("glCopyTexSubImage1D");
- glad_glCopyTexSubImage2D = (PFNGLCOPYTEXSUBIMAGE2DPROC)load("glCopyTexSubImage2D");
- glad_glTexSubImage1D = (PFNGLTEXSUBIMAGE1DPROC)load("glTexSubImage1D");
- glad_glTexSubImage2D = (PFNGLTEXSUBIMAGE2DPROC)load("glTexSubImage2D");
- glad_glBindTexture = (PFNGLBINDTEXTUREPROC)load("glBindTexture");
- glad_glDeleteTextures = (PFNGLDELETETEXTURESPROC)load("glDeleteTextures");
- glad_glGenTextures = (PFNGLGENTEXTURESPROC)load("glGenTextures");
- glad_glIsTexture = (PFNGLISTEXTUREPROC)load("glIsTexture");
- glad_glArrayElement = (PFNGLARRAYELEMENTPROC)load("glArrayElement");
- glad_glColorPointer = (PFNGLCOLORPOINTERPROC)load("glColorPointer");
- glad_glDisableClientState = (PFNGLDISABLECLIENTSTATEPROC)load("glDisableClientState");
- glad_glEdgeFlagPointer = (PFNGLEDGEFLAGPOINTERPROC)load("glEdgeFlagPointer");
- glad_glEnableClientState = (PFNGLENABLECLIENTSTATEPROC)load("glEnableClientState");
- glad_glIndexPointer = (PFNGLINDEXPOINTERPROC)load("glIndexPointer");
- glad_glInterleavedArrays = (PFNGLINTERLEAVEDARRAYSPROC)load("glInterleavedArrays");
- glad_glNormalPointer = (PFNGLNORMALPOINTERPROC)load("glNormalPointer");
- glad_glTexCoordPointer = (PFNGLTEXCOORDPOINTERPROC)load("glTexCoordPointer");
- glad_glVertexPointer = (PFNGLVERTEXPOINTERPROC)load("glVertexPointer");
- glad_glAreTexturesResident = (PFNGLARETEXTURESRESIDENTPROC)load("glAreTexturesResident");
- glad_glPrioritizeTextures = (PFNGLPRIORITIZETEXTURESPROC)load("glPrioritizeTextures");
- glad_glIndexub = (PFNGLINDEXUBPROC)load("glIndexub");
- glad_glIndexubv = (PFNGLINDEXUBVPROC)load("glIndexubv");
- glad_glPopClientAttrib = (PFNGLPOPCLIENTATTRIBPROC)load("glPopClientAttrib");
- glad_glPushClientAttrib = (PFNGLPUSHCLIENTATTRIBPROC)load("glPushClientAttrib");
-}
-static void load_GL_VERSION_1_2(GLADloadproc load) {
- if(!GLAD_GL_VERSION_1_2) return;
- glad_glDrawRangeElements = (PFNGLDRAWRANGEELEMENTSPROC)load("glDrawRangeElements");
- glad_glTexImage3D = (PFNGLTEXIMAGE3DPROC)load("glTexImage3D");
- glad_glTexSubImage3D = (PFNGLTEXSUBIMAGE3DPROC)load("glTexSubImage3D");
- glad_glCopyTexSubImage3D = (PFNGLCOPYTEXSUBIMAGE3DPROC)load("glCopyTexSubImage3D");
-}
-static void load_GL_VERSION_1_3(GLADloadproc load) {
- if(!GLAD_GL_VERSION_1_3) return;
- glad_glActiveTexture = (PFNGLACTIVETEXTUREPROC)load("glActiveTexture");
- glad_glSampleCoverage = (PFNGLSAMPLECOVERAGEPROC)load("glSampleCoverage");
- glad_glCompressedTexImage3D = (PFNGLCOMPRESSEDTEXIMAGE3DPROC)load("glCompressedTexImage3D");
- glad_glCompressedTexImage2D = (PFNGLCOMPRESSEDTEXIMAGE2DPROC)load("glCompressedTexImage2D");
- glad_glCompressedTexImage1D = (PFNGLCOMPRESSEDTEXIMAGE1DPROC)load("glCompressedTexImage1D");
- glad_glCompressedTexSubImage3D = (PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC)load("glCompressedTexSubImage3D");
- glad_glCompressedTexSubImage2D = (PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC)load("glCompressedTexSubImage2D");
- glad_glCompressedTexSubImage1D = (PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC)load("glCompressedTexSubImage1D");
- glad_glGetCompressedTexImage = (PFNGLGETCOMPRESSEDTEXIMAGEPROC)load("glGetCompressedTexImage");
- glad_glClientActiveTexture = (PFNGLCLIENTACTIVETEXTUREPROC)load("glClientActiveTexture");
- glad_glMultiTexCoord1d = (PFNGLMULTITEXCOORD1DPROC)load("glMultiTexCoord1d");
- glad_glMultiTexCoord1dv = (PFNGLMULTITEXCOORD1DVPROC)load("glMultiTexCoord1dv");
- glad_glMultiTexCoord1f = (PFNGLMULTITEXCOORD1FPROC)load("glMultiTexCoord1f");
- glad_glMultiTexCoord1fv = (PFNGLMULTITEXCOORD1FVPROC)load("glMultiTexCoord1fv");
- glad_glMultiTexCoord1i = (PFNGLMULTITEXCOORD1IPROC)load("glMultiTexCoord1i");
- glad_glMultiTexCoord1iv = (PFNGLMULTITEXCOORD1IVPROC)load("glMultiTexCoord1iv");
- glad_glMultiTexCoord1s = (PFNGLMULTITEXCOORD1SPROC)load("glMultiTexCoord1s");
- glad_glMultiTexCoord1sv = (PFNGLMULTITEXCOORD1SVPROC)load("glMultiTexCoord1sv");
- glad_glMultiTexCoord2d = (PFNGLMULTITEXCOORD2DPROC)load("glMultiTexCoord2d");
- glad_glMultiTexCoord2dv = (PFNGLMULTITEXCOORD2DVPROC)load("glMultiTexCoord2dv");
- glad_glMultiTexCoord2f = (PFNGLMULTITEXCOORD2FPROC)load("glMultiTexCoord2f");
- glad_glMultiTexCoord2fv = (PFNGLMULTITEXCOORD2FVPROC)load("glMultiTexCoord2fv");
- glad_glMultiTexCoord2i = (PFNGLMULTITEXCOORD2IPROC)load("glMultiTexCoord2i");
- glad_glMultiTexCoord2iv = (PFNGLMULTITEXCOORD2IVPROC)load("glMultiTexCoord2iv");
- glad_glMultiTexCoord2s = (PFNGLMULTITEXCOORD2SPROC)load("glMultiTexCoord2s");
- glad_glMultiTexCoord2sv = (PFNGLMULTITEXCOORD2SVPROC)load("glMultiTexCoord2sv");
- glad_glMultiTexCoord3d = (PFNGLMULTITEXCOORD3DPROC)load("glMultiTexCoord3d");
- glad_glMultiTexCoord3dv = (PFNGLMULTITEXCOORD3DVPROC)load("glMultiTexCoord3dv");
- glad_glMultiTexCoord3f = (PFNGLMULTITEXCOORD3FPROC)load("glMultiTexCoord3f");
- glad_glMultiTexCoord3fv = (PFNGLMULTITEXCOORD3FVPROC)load("glMultiTexCoord3fv");
- glad_glMultiTexCoord3i = (PFNGLMULTITEXCOORD3IPROC)load("glMultiTexCoord3i");
- glad_glMultiTexCoord3iv = (PFNGLMULTITEXCOORD3IVPROC)load("glMultiTexCoord3iv");
- glad_glMultiTexCoord3s = (PFNGLMULTITEXCOORD3SPROC)load("glMultiTexCoord3s");
- glad_glMultiTexCoord3sv = (PFNGLMULTITEXCOORD3SVPROC)load("glMultiTexCoord3sv");
- glad_glMultiTexCoord4d = (PFNGLMULTITEXCOORD4DPROC)load("glMultiTexCoord4d");
- glad_glMultiTexCoord4dv = (PFNGLMULTITEXCOORD4DVPROC)load("glMultiTexCoord4dv");
- glad_glMultiTexCoord4f = (PFNGLMULTITEXCOORD4FPROC)load("glMultiTexCoord4f");
- glad_glMultiTexCoord4fv = (PFNGLMULTITEXCOORD4FVPROC)load("glMultiTexCoord4fv");
- glad_glMultiTexCoord4i = (PFNGLMULTITEXCOORD4IPROC)load("glMultiTexCoord4i");
- glad_glMultiTexCoord4iv = (PFNGLMULTITEXCOORD4IVPROC)load("glMultiTexCoord4iv");
- glad_glMultiTexCoord4s = (PFNGLMULTITEXCOORD4SPROC)load("glMultiTexCoord4s");
- glad_glMultiTexCoord4sv = (PFNGLMULTITEXCOORD4SVPROC)load("glMultiTexCoord4sv");
- glad_glLoadTransposeMatrixf = (PFNGLLOADTRANSPOSEMATRIXFPROC)load("glLoadTransposeMatrixf");
- glad_glLoadTransposeMatrixd = (PFNGLLOADTRANSPOSEMATRIXDPROC)load("glLoadTransposeMatrixd");
- glad_glMultTransposeMatrixf = (PFNGLMULTTRANSPOSEMATRIXFPROC)load("glMultTransposeMatrixf");
- glad_glMultTransposeMatrixd = (PFNGLMULTTRANSPOSEMATRIXDPROC)load("glMultTransposeMatrixd");
-}
-static void load_GL_VERSION_1_4(GLADloadproc load) {
- if(!GLAD_GL_VERSION_1_4) return;
- glad_glBlendFuncSeparate = (PFNGLBLENDFUNCSEPARATEPROC)load("glBlendFuncSeparate");
- glad_glMultiDrawArrays = (PFNGLMULTIDRAWARRAYSPROC)load("glMultiDrawArrays");
- glad_glMultiDrawElements = (PFNGLMULTIDRAWELEMENTSPROC)load("glMultiDrawElements");
- glad_glPointParameterf = (PFNGLPOINTPARAMETERFPROC)load("glPointParameterf");
- glad_glPointParameterfv = (PFNGLPOINTPARAMETERFVPROC)load("glPointParameterfv");
- glad_glPointParameteri = (PFNGLPOINTPARAMETERIPROC)load("glPointParameteri");
- glad_glPointParameteriv = (PFNGLPOINTPARAMETERIVPROC)load("glPointParameteriv");
- glad_glFogCoordf = (PFNGLFOGCOORDFPROC)load("glFogCoordf");
- glad_glFogCoordfv = (PFNGLFOGCOORDFVPROC)load("glFogCoordfv");
- glad_glFogCoordd = (PFNGLFOGCOORDDPROC)load("glFogCoordd");
- glad_glFogCoorddv = (PFNGLFOGCOORDDVPROC)load("glFogCoorddv");
- glad_glFogCoordPointer = (PFNGLFOGCOORDPOINTERPROC)load("glFogCoordPointer");
- glad_glSecondaryColor3b = (PFNGLSECONDARYCOLOR3BPROC)load("glSecondaryColor3b");
- glad_glSecondaryColor3bv = (PFNGLSECONDARYCOLOR3BVPROC)load("glSecondaryColor3bv");
- glad_glSecondaryColor3d = (PFNGLSECONDARYCOLOR3DPROC)load("glSecondaryColor3d");
- glad_glSecondaryColor3dv = (PFNGLSECONDARYCOLOR3DVPROC)load("glSecondaryColor3dv");
- glad_glSecondaryColor3f = (PFNGLSECONDARYCOLOR3FPROC)load("glSecondaryColor3f");
- glad_glSecondaryColor3fv = (PFNGLSECONDARYCOLOR3FVPROC)load("glSecondaryColor3fv");
- glad_glSecondaryColor3i = (PFNGLSECONDARYCOLOR3IPROC)load("glSecondaryColor3i");
- glad_glSecondaryColor3iv = (PFNGLSECONDARYCOLOR3IVPROC)load("glSecondaryColor3iv");
- glad_glSecondaryColor3s = (PFNGLSECONDARYCOLOR3SPROC)load("glSecondaryColor3s");
- glad_glSecondaryColor3sv = (PFNGLSECONDARYCOLOR3SVPROC)load("glSecondaryColor3sv");
- glad_glSecondaryColor3ub = (PFNGLSECONDARYCOLOR3UBPROC)load("glSecondaryColor3ub");
- glad_glSecondaryColor3ubv = (PFNGLSECONDARYCOLOR3UBVPROC)load("glSecondaryColor3ubv");
- glad_glSecondaryColor3ui = (PFNGLSECONDARYCOLOR3UIPROC)load("glSecondaryColor3ui");
- glad_glSecondaryColor3uiv = (PFNGLSECONDARYCOLOR3UIVPROC)load("glSecondaryColor3uiv");
- glad_glSecondaryColor3us = (PFNGLSECONDARYCOLOR3USPROC)load("glSecondaryColor3us");
- glad_glSecondaryColor3usv = (PFNGLSECONDARYCOLOR3USVPROC)load("glSecondaryColor3usv");
- glad_glSecondaryColorPointer = (PFNGLSECONDARYCOLORPOINTERPROC)load("glSecondaryColorPointer");
- glad_glWindowPos2d = (PFNGLWINDOWPOS2DPROC)load("glWindowPos2d");
- glad_glWindowPos2dv = (PFNGLWINDOWPOS2DVPROC)load("glWindowPos2dv");
- glad_glWindowPos2f = (PFNGLWINDOWPOS2FPROC)load("glWindowPos2f");
- glad_glWindowPos2fv = (PFNGLWINDOWPOS2FVPROC)load("glWindowPos2fv");
- glad_glWindowPos2i = (PFNGLWINDOWPOS2IPROC)load("glWindowPos2i");
- glad_glWindowPos2iv = (PFNGLWINDOWPOS2IVPROC)load("glWindowPos2iv");
- glad_glWindowPos2s = (PFNGLWINDOWPOS2SPROC)load("glWindowPos2s");
- glad_glWindowPos2sv = (PFNGLWINDOWPOS2SVPROC)load("glWindowPos2sv");
- glad_glWindowPos3d = (PFNGLWINDOWPOS3DPROC)load("glWindowPos3d");
- glad_glWindowPos3dv = (PFNGLWINDOWPOS3DVPROC)load("glWindowPos3dv");
- glad_glWindowPos3f = (PFNGLWINDOWPOS3FPROC)load("glWindowPos3f");
- glad_glWindowPos3fv = (PFNGLWINDOWPOS3FVPROC)load("glWindowPos3fv");
- glad_glWindowPos3i = (PFNGLWINDOWPOS3IPROC)load("glWindowPos3i");
- glad_glWindowPos3iv = (PFNGLWINDOWPOS3IVPROC)load("glWindowPos3iv");
- glad_glWindowPos3s = (PFNGLWINDOWPOS3SPROC)load("glWindowPos3s");
- glad_glWindowPos3sv = (PFNGLWINDOWPOS3SVPROC)load("glWindowPos3sv");
- glad_glBlendColor = (PFNGLBLENDCOLORPROC)load("glBlendColor");
- glad_glBlendEquation = (PFNGLBLENDEQUATIONPROC)load("glBlendEquation");
-}
-static void load_GL_VERSION_1_5(GLADloadproc load) {
- if(!GLAD_GL_VERSION_1_5) return;
- glad_glGenQueries = (PFNGLGENQUERIESPROC)load("glGenQueries");
- glad_glDeleteQueries = (PFNGLDELETEQUERIESPROC)load("glDeleteQueries");
- glad_glIsQuery = (PFNGLISQUERYPROC)load("glIsQuery");
- glad_glBeginQuery = (PFNGLBEGINQUERYPROC)load("glBeginQuery");
- glad_glEndQuery = (PFNGLENDQUERYPROC)load("glEndQuery");
- glad_glGetQueryiv = (PFNGLGETQUERYIVPROC)load("glGetQueryiv");
- glad_glGetQueryObjectiv = (PFNGLGETQUERYOBJECTIVPROC)load("glGetQueryObjectiv");
- glad_glGetQueryObjectuiv = (PFNGLGETQUERYOBJECTUIVPROC)load("glGetQueryObjectuiv");
- glad_glBindBuffer = (PFNGLBINDBUFFERPROC)load("glBindBuffer");
- glad_glDeleteBuffers = (PFNGLDELETEBUFFERSPROC)load("glDeleteBuffers");
- glad_glGenBuffers = (PFNGLGENBUFFERSPROC)load("glGenBuffers");
- glad_glIsBuffer = (PFNGLISBUFFERPROC)load("glIsBuffer");
- glad_glBufferData = (PFNGLBUFFERDATAPROC)load("glBufferData");
- glad_glBufferSubData = (PFNGLBUFFERSUBDATAPROC)load("glBufferSubData");
- glad_glGetBufferSubData = (PFNGLGETBUFFERSUBDATAPROC)load("glGetBufferSubData");
- glad_glMapBuffer = (PFNGLMAPBUFFERPROC)load("glMapBuffer");
- glad_glUnmapBuffer = (PFNGLUNMAPBUFFERPROC)load("glUnmapBuffer");
- glad_glGetBufferParameteriv = (PFNGLGETBUFFERPARAMETERIVPROC)load("glGetBufferParameteriv");
- glad_glGetBufferPointerv = (PFNGLGETBUFFERPOINTERVPROC)load("glGetBufferPointerv");
-}
-static void load_GL_VERSION_2_0(GLADloadproc load) {
- if(!GLAD_GL_VERSION_2_0) return;
- glad_glBlendEquationSeparate = (PFNGLBLENDEQUATIONSEPARATEPROC)load("glBlendEquationSeparate");
- glad_glDrawBuffers = (PFNGLDRAWBUFFERSPROC)load("glDrawBuffers");
- glad_glStencilOpSeparate = (PFNGLSTENCILOPSEPARATEPROC)load("glStencilOpSeparate");
- glad_glStencilFuncSeparate = (PFNGLSTENCILFUNCSEPARATEPROC)load("glStencilFuncSeparate");
- glad_glStencilMaskSeparate = (PFNGLSTENCILMASKSEPARATEPROC)load("glStencilMaskSeparate");
- glad_glAttachShader = (PFNGLATTACHSHADERPROC)load("glAttachShader");
- glad_glBindAttribLocation = (PFNGLBINDATTRIBLOCATIONPROC)load("glBindAttribLocation");
- glad_glCompileShader = (PFNGLCOMPILESHADERPROC)load("glCompileShader");
- glad_glCreateProgram = (PFNGLCREATEPROGRAMPROC)load("glCreateProgram");
- glad_glCreateShader = (PFNGLCREATESHADERPROC)load("glCreateShader");
- glad_glDeleteProgram = (PFNGLDELETEPROGRAMPROC)load("glDeleteProgram");
- glad_glDeleteShader = (PFNGLDELETESHADERPROC)load("glDeleteShader");
- glad_glDetachShader = (PFNGLDETACHSHADERPROC)load("glDetachShader");
- glad_glDisableVertexAttribArray = (PFNGLDISABLEVERTEXATTRIBARRAYPROC)load("glDisableVertexAttribArray");
- glad_glEnableVertexAttribArray = (PFNGLENABLEVERTEXATTRIBARRAYPROC)load("glEnableVertexAttribArray");
- glad_glGetActiveAttrib = (PFNGLGETACTIVEATTRIBPROC)load("glGetActiveAttrib");
- glad_glGetActiveUniform = (PFNGLGETACTIVEUNIFORMPROC)load("glGetActiveUniform");
- glad_glGetAttachedShaders = (PFNGLGETATTACHEDSHADERSPROC)load("glGetAttachedShaders");
- glad_glGetAttribLocation = (PFNGLGETATTRIBLOCATIONPROC)load("glGetAttribLocation");
- glad_glGetProgramiv = (PFNGLGETPROGRAMIVPROC)load("glGetProgramiv");
- glad_glGetProgramInfoLog = (PFNGLGETPROGRAMINFOLOGPROC)load("glGetProgramInfoLog");
- glad_glGetShaderiv = (PFNGLGETSHADERIVPROC)load("glGetShaderiv");
- glad_glGetShaderInfoLog = (PFNGLGETSHADERINFOLOGPROC)load("glGetShaderInfoLog");
- glad_glGetShaderSource = (PFNGLGETSHADERSOURCEPROC)load("glGetShaderSource");
- glad_glGetUniformLocation = (PFNGLGETUNIFORMLOCATIONPROC)load("glGetUniformLocation");
- glad_glGetUniformfv = (PFNGLGETUNIFORMFVPROC)load("glGetUniformfv");
- glad_glGetUniformiv = (PFNGLGETUNIFORMIVPROC)load("glGetUniformiv");
- glad_glGetVertexAttribdv = (PFNGLGETVERTEXATTRIBDVPROC)load("glGetVertexAttribdv");
- glad_glGetVertexAttribfv = (PFNGLGETVERTEXATTRIBFVPROC)load("glGetVertexAttribfv");
- glad_glGetVertexAttribiv = (PFNGLGETVERTEXATTRIBIVPROC)load("glGetVertexAttribiv");
- glad_glGetVertexAttribPointerv = (PFNGLGETVERTEXATTRIBPOINTERVPROC)load("glGetVertexAttribPointerv");
- glad_glIsProgram = (PFNGLISPROGRAMPROC)load("glIsProgram");
- glad_glIsShader = (PFNGLISSHADERPROC)load("glIsShader");
- glad_glLinkProgram = (PFNGLLINKPROGRAMPROC)load("glLinkProgram");
- glad_glShaderSource = (PFNGLSHADERSOURCEPROC)load("glShaderSource");
- glad_glUseProgram = (PFNGLUSEPROGRAMPROC)load("glUseProgram");
- glad_glUniform1f = (PFNGLUNIFORM1FPROC)load("glUniform1f");
- glad_glUniform2f = (PFNGLUNIFORM2FPROC)load("glUniform2f");
- glad_glUniform3f = (PFNGLUNIFORM3FPROC)load("glUniform3f");
- glad_glUniform4f = (PFNGLUNIFORM4FPROC)load("glUniform4f");
- glad_glUniform1i = (PFNGLUNIFORM1IPROC)load("glUniform1i");
- glad_glUniform2i = (PFNGLUNIFORM2IPROC)load("glUniform2i");
- glad_glUniform3i = (PFNGLUNIFORM3IPROC)load("glUniform3i");
- glad_glUniform4i = (PFNGLUNIFORM4IPROC)load("glUniform4i");
- glad_glUniform1fv = (PFNGLUNIFORM1FVPROC)load("glUniform1fv");
- glad_glUniform2fv = (PFNGLUNIFORM2FVPROC)load("glUniform2fv");
- glad_glUniform3fv = (PFNGLUNIFORM3FVPROC)load("glUniform3fv");
- glad_glUniform4fv = (PFNGLUNIFORM4FVPROC)load("glUniform4fv");
- glad_glUniform1iv = (PFNGLUNIFORM1IVPROC)load("glUniform1iv");
- glad_glUniform2iv = (PFNGLUNIFORM2IVPROC)load("glUniform2iv");
- glad_glUniform3iv = (PFNGLUNIFORM3IVPROC)load("glUniform3iv");
- glad_glUniform4iv = (PFNGLUNIFORM4IVPROC)load("glUniform4iv");
- glad_glUniformMatrix2fv = (PFNGLUNIFORMMATRIX2FVPROC)load("glUniformMatrix2fv");
- glad_glUniformMatrix3fv = (PFNGLUNIFORMMATRIX3FVPROC)load("glUniformMatrix3fv");
- glad_glUniformMatrix4fv = (PFNGLUNIFORMMATRIX4FVPROC)load("glUniformMatrix4fv");
- glad_glValidateProgram = (PFNGLVALIDATEPROGRAMPROC)load("glValidateProgram");
- glad_glVertexAttrib1d = (PFNGLVERTEXATTRIB1DPROC)load("glVertexAttrib1d");
- glad_glVertexAttrib1dv = (PFNGLVERTEXATTRIB1DVPROC)load("glVertexAttrib1dv");
- glad_glVertexAttrib1f = (PFNGLVERTEXATTRIB1FPROC)load("glVertexAttrib1f");
- glad_glVertexAttrib1fv = (PFNGLVERTEXATTRIB1FVPROC)load("glVertexAttrib1fv");
- glad_glVertexAttrib1s = (PFNGLVERTEXATTRIB1SPROC)load("glVertexAttrib1s");
- glad_glVertexAttrib1sv = (PFNGLVERTEXATTRIB1SVPROC)load("glVertexAttrib1sv");
- glad_glVertexAttrib2d = (PFNGLVERTEXATTRIB2DPROC)load("glVertexAttrib2d");
- glad_glVertexAttrib2dv = (PFNGLVERTEXATTRIB2DVPROC)load("glVertexAttrib2dv");
- glad_glVertexAttrib2f = (PFNGLVERTEXATTRIB2FPROC)load("glVertexAttrib2f");
- glad_glVertexAttrib2fv = (PFNGLVERTEXATTRIB2FVPROC)load("glVertexAttrib2fv");
- glad_glVertexAttrib2s = (PFNGLVERTEXATTRIB2SPROC)load("glVertexAttrib2s");
- glad_glVertexAttrib2sv = (PFNGLVERTEXATTRIB2SVPROC)load("glVertexAttrib2sv");
- glad_glVertexAttrib3d = (PFNGLVERTEXATTRIB3DPROC)load("glVertexAttrib3d");
- glad_glVertexAttrib3dv = (PFNGLVERTEXATTRIB3DVPROC)load("glVertexAttrib3dv");
- glad_glVertexAttrib3f = (PFNGLVERTEXATTRIB3FPROC)load("glVertexAttrib3f");
- glad_glVertexAttrib3fv = (PFNGLVERTEXATTRIB3FVPROC)load("glVertexAttrib3fv");
- glad_glVertexAttrib3s = (PFNGLVERTEXATTRIB3SPROC)load("glVertexAttrib3s");
- glad_glVertexAttrib3sv = (PFNGLVERTEXATTRIB3SVPROC)load("glVertexAttrib3sv");
- glad_glVertexAttrib4Nbv = (PFNGLVERTEXATTRIB4NBVPROC)load("glVertexAttrib4Nbv");
- glad_glVertexAttrib4Niv = (PFNGLVERTEXATTRIB4NIVPROC)load("glVertexAttrib4Niv");
- glad_glVertexAttrib4Nsv = (PFNGLVERTEXATTRIB4NSVPROC)load("glVertexAttrib4Nsv");
- glad_glVertexAttrib4Nub = (PFNGLVERTEXATTRIB4NUBPROC)load("glVertexAttrib4Nub");
- glad_glVertexAttrib4Nubv = (PFNGLVERTEXATTRIB4NUBVPROC)load("glVertexAttrib4Nubv");
- glad_glVertexAttrib4Nuiv = (PFNGLVERTEXATTRIB4NUIVPROC)load("glVertexAttrib4Nuiv");
- glad_glVertexAttrib4Nusv = (PFNGLVERTEXATTRIB4NUSVPROC)load("glVertexAttrib4Nusv");
- glad_glVertexAttrib4bv = (PFNGLVERTEXATTRIB4BVPROC)load("glVertexAttrib4bv");
- glad_glVertexAttrib4d = (PFNGLVERTEXATTRIB4DPROC)load("glVertexAttrib4d");
- glad_glVertexAttrib4dv = (PFNGLVERTEXATTRIB4DVPROC)load("glVertexAttrib4dv");
- glad_glVertexAttrib4f = (PFNGLVERTEXATTRIB4FPROC)load("glVertexAttrib4f");
- glad_glVertexAttrib4fv = (PFNGLVERTEXATTRIB4FVPROC)load("glVertexAttrib4fv");
- glad_glVertexAttrib4iv = (PFNGLVERTEXATTRIB4IVPROC)load("glVertexAttrib4iv");
- glad_glVertexAttrib4s = (PFNGLVERTEXATTRIB4SPROC)load("glVertexAttrib4s");
- glad_glVertexAttrib4sv = (PFNGLVERTEXATTRIB4SVPROC)load("glVertexAttrib4sv");
- glad_glVertexAttrib4ubv = (PFNGLVERTEXATTRIB4UBVPROC)load("glVertexAttrib4ubv");
- glad_glVertexAttrib4uiv = (PFNGLVERTEXATTRIB4UIVPROC)load("glVertexAttrib4uiv");
- glad_glVertexAttrib4usv = (PFNGLVERTEXATTRIB4USVPROC)load("glVertexAttrib4usv");
- glad_glVertexAttribPointer = (PFNGLVERTEXATTRIBPOINTERPROC)load("glVertexAttribPointer");
-}
-static void load_GL_VERSION_2_1(GLADloadproc load) {
- if(!GLAD_GL_VERSION_2_1) return;
- glad_glUniformMatrix2x3fv = (PFNGLUNIFORMMATRIX2X3FVPROC)load("glUniformMatrix2x3fv");
- glad_glUniformMatrix3x2fv = (PFNGLUNIFORMMATRIX3X2FVPROC)load("glUniformMatrix3x2fv");
- glad_glUniformMatrix2x4fv = (PFNGLUNIFORMMATRIX2X4FVPROC)load("glUniformMatrix2x4fv");
- glad_glUniformMatrix4x2fv = (PFNGLUNIFORMMATRIX4X2FVPROC)load("glUniformMatrix4x2fv");
- glad_glUniformMatrix3x4fv = (PFNGLUNIFORMMATRIX3X4FVPROC)load("glUniformMatrix3x4fv");
- glad_glUniformMatrix4x3fv = (PFNGLUNIFORMMATRIX4X3FVPROC)load("glUniformMatrix4x3fv");
-}
-static void load_GL_VERSION_3_0(GLADloadproc load) {
- if(!GLAD_GL_VERSION_3_0) return;
- glad_glColorMaski = (PFNGLCOLORMASKIPROC)load("glColorMaski");
- glad_glGetBooleani_v = (PFNGLGETBOOLEANI_VPROC)load("glGetBooleani_v");
- glad_glGetIntegeri_v = (PFNGLGETINTEGERI_VPROC)load("glGetIntegeri_v");
- glad_glEnablei = (PFNGLENABLEIPROC)load("glEnablei");
- glad_glDisablei = (PFNGLDISABLEIPROC)load("glDisablei");
- glad_glIsEnabledi = (PFNGLISENABLEDIPROC)load("glIsEnabledi");
- glad_glBeginTransformFeedback = (PFNGLBEGINTRANSFORMFEEDBACKPROC)load("glBeginTransformFeedback");
- glad_glEndTransformFeedback = (PFNGLENDTRANSFORMFEEDBACKPROC)load("glEndTransformFeedback");
- glad_glBindBufferRange = (PFNGLBINDBUFFERRANGEPROC)load("glBindBufferRange");
- glad_glBindBufferBase = (PFNGLBINDBUFFERBASEPROC)load("glBindBufferBase");
- glad_glTransformFeedbackVaryings = (PFNGLTRANSFORMFEEDBACKVARYINGSPROC)load("glTransformFeedbackVaryings");
- glad_glGetTransformFeedbackVarying = (PFNGLGETTRANSFORMFEEDBACKVARYINGPROC)load("glGetTransformFeedbackVarying");
- glad_glClampColor = (PFNGLCLAMPCOLORPROC)load("glClampColor");
- glad_glBeginConditionalRender = (PFNGLBEGINCONDITIONALRENDERPROC)load("glBeginConditionalRender");
- glad_glEndConditionalRender = (PFNGLENDCONDITIONALRENDERPROC)load("glEndConditionalRender");
- glad_glVertexAttribIPointer = (PFNGLVERTEXATTRIBIPOINTERPROC)load("glVertexAttribIPointer");
- glad_glGetVertexAttribIiv = (PFNGLGETVERTEXATTRIBIIVPROC)load("glGetVertexAttribIiv");
- glad_glGetVertexAttribIuiv = (PFNGLGETVERTEXATTRIBIUIVPROC)load("glGetVertexAttribIuiv");
- glad_glVertexAttribI1i = (PFNGLVERTEXATTRIBI1IPROC)load("glVertexAttribI1i");
- glad_glVertexAttribI2i = (PFNGLVERTEXATTRIBI2IPROC)load("glVertexAttribI2i");
- glad_glVertexAttribI3i = (PFNGLVERTEXATTRIBI3IPROC)load("glVertexAttribI3i");
- glad_glVertexAttribI4i = (PFNGLVERTEXATTRIBI4IPROC)load("glVertexAttribI4i");
- glad_glVertexAttribI1ui = (PFNGLVERTEXATTRIBI1UIPROC)load("glVertexAttribI1ui");
- glad_glVertexAttribI2ui = (PFNGLVERTEXATTRIBI2UIPROC)load("glVertexAttribI2ui");
- glad_glVertexAttribI3ui = (PFNGLVERTEXATTRIBI3UIPROC)load("glVertexAttribI3ui");
- glad_glVertexAttribI4ui = (PFNGLVERTEXATTRIBI4UIPROC)load("glVertexAttribI4ui");
- glad_glVertexAttribI1iv = (PFNGLVERTEXATTRIBI1IVPROC)load("glVertexAttribI1iv");
- glad_glVertexAttribI2iv = (PFNGLVERTEXATTRIBI2IVPROC)load("glVertexAttribI2iv");
- glad_glVertexAttribI3iv = (PFNGLVERTEXATTRIBI3IVPROC)load("glVertexAttribI3iv");
- glad_glVertexAttribI4iv = (PFNGLVERTEXATTRIBI4IVPROC)load("glVertexAttribI4iv");
- glad_glVertexAttribI1uiv = (PFNGLVERTEXATTRIBI1UIVPROC)load("glVertexAttribI1uiv");
- glad_glVertexAttribI2uiv = (PFNGLVERTEXATTRIBI2UIVPROC)load("glVertexAttribI2uiv");
- glad_glVertexAttribI3uiv = (PFNGLVERTEXATTRIBI3UIVPROC)load("glVertexAttribI3uiv");
- glad_glVertexAttribI4uiv = (PFNGLVERTEXATTRIBI4UIVPROC)load("glVertexAttribI4uiv");
- glad_glVertexAttribI4bv = (PFNGLVERTEXATTRIBI4BVPROC)load("glVertexAttribI4bv");
- glad_glVertexAttribI4sv = (PFNGLVERTEXATTRIBI4SVPROC)load("glVertexAttribI4sv");
- glad_glVertexAttribI4ubv = (PFNGLVERTEXATTRIBI4UBVPROC)load("glVertexAttribI4ubv");
- glad_glVertexAttribI4usv = (PFNGLVERTEXATTRIBI4USVPROC)load("glVertexAttribI4usv");
- glad_glGetUniformuiv = (PFNGLGETUNIFORMUIVPROC)load("glGetUniformuiv");
- glad_glBindFragDataLocation = (PFNGLBINDFRAGDATALOCATIONPROC)load("glBindFragDataLocation");
- glad_glGetFragDataLocation = (PFNGLGETFRAGDATALOCATIONPROC)load("glGetFragDataLocation");
- glad_glUniform1ui = (PFNGLUNIFORM1UIPROC)load("glUniform1ui");
- glad_glUniform2ui = (PFNGLUNIFORM2UIPROC)load("glUniform2ui");
- glad_glUniform3ui = (PFNGLUNIFORM3UIPROC)load("glUniform3ui");
- glad_glUniform4ui = (PFNGLUNIFORM4UIPROC)load("glUniform4ui");
- glad_glUniform1uiv = (PFNGLUNIFORM1UIVPROC)load("glUniform1uiv");
- glad_glUniform2uiv = (PFNGLUNIFORM2UIVPROC)load("glUniform2uiv");
- glad_glUniform3uiv = (PFNGLUNIFORM3UIVPROC)load("glUniform3uiv");
- glad_glUniform4uiv = (PFNGLUNIFORM4UIVPROC)load("glUniform4uiv");
- glad_glTexParameterIiv = (PFNGLTEXPARAMETERIIVPROC)load("glTexParameterIiv");
- glad_glTexParameterIuiv = (PFNGLTEXPARAMETERIUIVPROC)load("glTexParameterIuiv");
- glad_glGetTexParameterIiv = (PFNGLGETTEXPARAMETERIIVPROC)load("glGetTexParameterIiv");
- glad_glGetTexParameterIuiv = (PFNGLGETTEXPARAMETERIUIVPROC)load("glGetTexParameterIuiv");
- glad_glClearBufferiv = (PFNGLCLEARBUFFERIVPROC)load("glClearBufferiv");
- glad_glClearBufferuiv = (PFNGLCLEARBUFFERUIVPROC)load("glClearBufferuiv");
- glad_glClearBufferfv = (PFNGLCLEARBUFFERFVPROC)load("glClearBufferfv");
- glad_glClearBufferfi = (PFNGLCLEARBUFFERFIPROC)load("glClearBufferfi");
- glad_glGetStringi = (PFNGLGETSTRINGIPROC)load("glGetStringi");
- glad_glIsRenderbuffer = (PFNGLISRENDERBUFFERPROC)load("glIsRenderbuffer");
- glad_glBindRenderbuffer = (PFNGLBINDRENDERBUFFERPROC)load("glBindRenderbuffer");
- glad_glDeleteRenderbuffers = (PFNGLDELETERENDERBUFFERSPROC)load("glDeleteRenderbuffers");
- glad_glGenRenderbuffers = (PFNGLGENRENDERBUFFERSPROC)load("glGenRenderbuffers");
- glad_glRenderbufferStorage = (PFNGLRENDERBUFFERSTORAGEPROC)load("glRenderbufferStorage");
- glad_glGetRenderbufferParameteriv = (PFNGLGETRENDERBUFFERPARAMETERIVPROC)load("glGetRenderbufferParameteriv");
- glad_glIsFramebuffer = (PFNGLISFRAMEBUFFERPROC)load("glIsFramebuffer");
- glad_glBindFramebuffer = (PFNGLBINDFRAMEBUFFERPROC)load("glBindFramebuffer");
- glad_glDeleteFramebuffers = (PFNGLDELETEFRAMEBUFFERSPROC)load("glDeleteFramebuffers");
- glad_glGenFramebuffers = (PFNGLGENFRAMEBUFFERSPROC)load("glGenFramebuffers");
- glad_glCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSPROC)load("glCheckFramebufferStatus");
- glad_glFramebufferTexture1D = (PFNGLFRAMEBUFFERTEXTURE1DPROC)load("glFramebufferTexture1D");
- glad_glFramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DPROC)load("glFramebufferTexture2D");
- glad_glFramebufferTexture3D = (PFNGLFRAMEBUFFERTEXTURE3DPROC)load("glFramebufferTexture3D");
- glad_glFramebufferRenderbuffer = (PFNGLFRAMEBUFFERRENDERBUFFERPROC)load("glFramebufferRenderbuffer");
- glad_glGetFramebufferAttachmentParameteriv = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC)load("glGetFramebufferAttachmentParameteriv");
- glad_glGenerateMipmap = (PFNGLGENERATEMIPMAPPROC)load("glGenerateMipmap");
- glad_glBlitFramebuffer = (PFNGLBLITFRAMEBUFFERPROC)load("glBlitFramebuffer");
- glad_glRenderbufferStorageMultisample = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC)load("glRenderbufferStorageMultisample");
- glad_glFramebufferTextureLayer = (PFNGLFRAMEBUFFERTEXTURELAYERPROC)load("glFramebufferTextureLayer");
- glad_glMapBufferRange = (PFNGLMAPBUFFERRANGEPROC)load("glMapBufferRange");
- glad_glFlushMappedBufferRange = (PFNGLFLUSHMAPPEDBUFFERRANGEPROC)load("glFlushMappedBufferRange");
- glad_glBindVertexArray = (PFNGLBINDVERTEXARRAYPROC)load("glBindVertexArray");
- glad_glDeleteVertexArrays = (PFNGLDELETEVERTEXARRAYSPROC)load("glDeleteVertexArrays");
- glad_glGenVertexArrays = (PFNGLGENVERTEXARRAYSPROC)load("glGenVertexArrays");
- glad_glIsVertexArray = (PFNGLISVERTEXARRAYPROC)load("glIsVertexArray");
-}
-static void load_GL_VERSION_3_1(GLADloadproc load) {
- if(!GLAD_GL_VERSION_3_1) return;
- glad_glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDPROC)load("glDrawArraysInstanced");
- glad_glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDPROC)load("glDrawElementsInstanced");
- glad_glTexBuffer = (PFNGLTEXBUFFERPROC)load("glTexBuffer");
- glad_glPrimitiveRestartIndex = (PFNGLPRIMITIVERESTARTINDEXPROC)load("glPrimitiveRestartIndex");
- glad_glCopyBufferSubData = (PFNGLCOPYBUFFERSUBDATAPROC)load("glCopyBufferSubData");
- glad_glGetUniformIndices = (PFNGLGETUNIFORMINDICESPROC)load("glGetUniformIndices");
- glad_glGetActiveUniformsiv = (PFNGLGETACTIVEUNIFORMSIVPROC)load("glGetActiveUniformsiv");
- glad_glGetActiveUniformName = (PFNGLGETACTIVEUNIFORMNAMEPROC)load("glGetActiveUniformName");
- glad_glGetUniformBlockIndex = (PFNGLGETUNIFORMBLOCKINDEXPROC)load("glGetUniformBlockIndex");
- glad_glGetActiveUniformBlockiv = (PFNGLGETACTIVEUNIFORMBLOCKIVPROC)load("glGetActiveUniformBlockiv");
- glad_glGetActiveUniformBlockName = (PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC)load("glGetActiveUniformBlockName");
- glad_glUniformBlockBinding = (PFNGLUNIFORMBLOCKBINDINGPROC)load("glUniformBlockBinding");
- glad_glBindBufferRange = (PFNGLBINDBUFFERRANGEPROC)load("glBindBufferRange");
- glad_glBindBufferBase = (PFNGLBINDBUFFERBASEPROC)load("glBindBufferBase");
- glad_glGetIntegeri_v = (PFNGLGETINTEGERI_VPROC)load("glGetIntegeri_v");
-}
-static void load_GL_VERSION_3_2(GLADloadproc load) {
- if(!GLAD_GL_VERSION_3_2) return;
- glad_glDrawElementsBaseVertex = (PFNGLDRAWELEMENTSBASEVERTEXPROC)load("glDrawElementsBaseVertex");
- glad_glDrawRangeElementsBaseVertex = (PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC)load("glDrawRangeElementsBaseVertex");
- glad_glDrawElementsInstancedBaseVertex = (PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC)load("glDrawElementsInstancedBaseVertex");
- glad_glMultiDrawElementsBaseVertex = (PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC)load("glMultiDrawElementsBaseVertex");
- glad_glProvokingVertex = (PFNGLPROVOKINGVERTEXPROC)load("glProvokingVertex");
- glad_glFenceSync = (PFNGLFENCESYNCPROC)load("glFenceSync");
- glad_glIsSync = (PFNGLISSYNCPROC)load("glIsSync");
- glad_glDeleteSync = (PFNGLDELETESYNCPROC)load("glDeleteSync");
- glad_glClientWaitSync = (PFNGLCLIENTWAITSYNCPROC)load("glClientWaitSync");
- glad_glWaitSync = (PFNGLWAITSYNCPROC)load("glWaitSync");
- glad_glGetInteger64v = (PFNGLGETINTEGER64VPROC)load("glGetInteger64v");
- glad_glGetSynciv = (PFNGLGETSYNCIVPROC)load("glGetSynciv");
- glad_glGetInteger64i_v = (PFNGLGETINTEGER64I_VPROC)load("glGetInteger64i_v");
- glad_glGetBufferParameteri64v = (PFNGLGETBUFFERPARAMETERI64VPROC)load("glGetBufferParameteri64v");
- glad_glFramebufferTexture = (PFNGLFRAMEBUFFERTEXTUREPROC)load("glFramebufferTexture");
- glad_glTexImage2DMultisample = (PFNGLTEXIMAGE2DMULTISAMPLEPROC)load("glTexImage2DMultisample");
- glad_glTexImage3DMultisample = (PFNGLTEXIMAGE3DMULTISAMPLEPROC)load("glTexImage3DMultisample");
- glad_glGetMultisamplefv = (PFNGLGETMULTISAMPLEFVPROC)load("glGetMultisamplefv");
- glad_glSampleMaski = (PFNGLSAMPLEMASKIPROC)load("glSampleMaski");
-}
-static void load_GL_VERSION_3_3(GLADloadproc load) {
- if(!GLAD_GL_VERSION_3_3) return;
- glad_glBindFragDataLocationIndexed = (PFNGLBINDFRAGDATALOCATIONINDEXEDPROC)load("glBindFragDataLocationIndexed");
- glad_glGetFragDataIndex = (PFNGLGETFRAGDATAINDEXPROC)load("glGetFragDataIndex");
- glad_glGenSamplers = (PFNGLGENSAMPLERSPROC)load("glGenSamplers");
- glad_glDeleteSamplers = (PFNGLDELETESAMPLERSPROC)load("glDeleteSamplers");
- glad_glIsSampler = (PFNGLISSAMPLERPROC)load("glIsSampler");
- glad_glBindSampler = (PFNGLBINDSAMPLERPROC)load("glBindSampler");
- glad_glSamplerParameteri = (PFNGLSAMPLERPARAMETERIPROC)load("glSamplerParameteri");
- glad_glSamplerParameteriv = (PFNGLSAMPLERPARAMETERIVPROC)load("glSamplerParameteriv");
- glad_glSamplerParameterf = (PFNGLSAMPLERPARAMETERFPROC)load("glSamplerParameterf");
- glad_glSamplerParameterfv = (PFNGLSAMPLERPARAMETERFVPROC)load("glSamplerParameterfv");
- glad_glSamplerParameterIiv = (PFNGLSAMPLERPARAMETERIIVPROC)load("glSamplerParameterIiv");
- glad_glSamplerParameterIuiv = (PFNGLSAMPLERPARAMETERIUIVPROC)load("glSamplerParameterIuiv");
- glad_glGetSamplerParameteriv = (PFNGLGETSAMPLERPARAMETERIVPROC)load("glGetSamplerParameteriv");
- glad_glGetSamplerParameterIiv = (PFNGLGETSAMPLERPARAMETERIIVPROC)load("glGetSamplerParameterIiv");
- glad_glGetSamplerParameterfv = (PFNGLGETSAMPLERPARAMETERFVPROC)load("glGetSamplerParameterfv");
- glad_glGetSamplerParameterIuiv = (PFNGLGETSAMPLERPARAMETERIUIVPROC)load("glGetSamplerParameterIuiv");
- glad_glQueryCounter = (PFNGLQUERYCOUNTERPROC)load("glQueryCounter");
- glad_glGetQueryObjecti64v = (PFNGLGETQUERYOBJECTI64VPROC)load("glGetQueryObjecti64v");
- glad_glGetQueryObjectui64v = (PFNGLGETQUERYOBJECTUI64VPROC)load("glGetQueryObjectui64v");
- glad_glVertexAttribDivisor = (PFNGLVERTEXATTRIBDIVISORPROC)load("glVertexAttribDivisor");
- glad_glVertexAttribP1ui = (PFNGLVERTEXATTRIBP1UIPROC)load("glVertexAttribP1ui");
- glad_glVertexAttribP1uiv = (PFNGLVERTEXATTRIBP1UIVPROC)load("glVertexAttribP1uiv");
- glad_glVertexAttribP2ui = (PFNGLVERTEXATTRIBP2UIPROC)load("glVertexAttribP2ui");
- glad_glVertexAttribP2uiv = (PFNGLVERTEXATTRIBP2UIVPROC)load("glVertexAttribP2uiv");
- glad_glVertexAttribP3ui = (PFNGLVERTEXATTRIBP3UIPROC)load("glVertexAttribP3ui");
- glad_glVertexAttribP3uiv = (PFNGLVERTEXATTRIBP3UIVPROC)load("glVertexAttribP3uiv");
- glad_glVertexAttribP4ui = (PFNGLVERTEXATTRIBP4UIPROC)load("glVertexAttribP4ui");
- glad_glVertexAttribP4uiv = (PFNGLVERTEXATTRIBP4UIVPROC)load("glVertexAttribP4uiv");
- glad_glVertexP2ui = (PFNGLVERTEXP2UIPROC)load("glVertexP2ui");
- glad_glVertexP2uiv = (PFNGLVERTEXP2UIVPROC)load("glVertexP2uiv");
- glad_glVertexP3ui = (PFNGLVERTEXP3UIPROC)load("glVertexP3ui");
- glad_glVertexP3uiv = (PFNGLVERTEXP3UIVPROC)load("glVertexP3uiv");
- glad_glVertexP4ui = (PFNGLVERTEXP4UIPROC)load("glVertexP4ui");
- glad_glVertexP4uiv = (PFNGLVERTEXP4UIVPROC)load("glVertexP4uiv");
- glad_glTexCoordP1ui = (PFNGLTEXCOORDP1UIPROC)load("glTexCoordP1ui");
- glad_glTexCoordP1uiv = (PFNGLTEXCOORDP1UIVPROC)load("glTexCoordP1uiv");
- glad_glTexCoordP2ui = (PFNGLTEXCOORDP2UIPROC)load("glTexCoordP2ui");
- glad_glTexCoordP2uiv = (PFNGLTEXCOORDP2UIVPROC)load("glTexCoordP2uiv");
- glad_glTexCoordP3ui = (PFNGLTEXCOORDP3UIPROC)load("glTexCoordP3ui");
- glad_glTexCoordP3uiv = (PFNGLTEXCOORDP3UIVPROC)load("glTexCoordP3uiv");
- glad_glTexCoordP4ui = (PFNGLTEXCOORDP4UIPROC)load("glTexCoordP4ui");
- glad_glTexCoordP4uiv = (PFNGLTEXCOORDP4UIVPROC)load("glTexCoordP4uiv");
- glad_glMultiTexCoordP1ui = (PFNGLMULTITEXCOORDP1UIPROC)load("glMultiTexCoordP1ui");
- glad_glMultiTexCoordP1uiv = (PFNGLMULTITEXCOORDP1UIVPROC)load("glMultiTexCoordP1uiv");
- glad_glMultiTexCoordP2ui = (PFNGLMULTITEXCOORDP2UIPROC)load("glMultiTexCoordP2ui");
- glad_glMultiTexCoordP2uiv = (PFNGLMULTITEXCOORDP2UIVPROC)load("glMultiTexCoordP2uiv");
- glad_glMultiTexCoordP3ui = (PFNGLMULTITEXCOORDP3UIPROC)load("glMultiTexCoordP3ui");
- glad_glMultiTexCoordP3uiv = (PFNGLMULTITEXCOORDP3UIVPROC)load("glMultiTexCoordP3uiv");
- glad_glMultiTexCoordP4ui = (PFNGLMULTITEXCOORDP4UIPROC)load("glMultiTexCoordP4ui");
- glad_glMultiTexCoordP4uiv = (PFNGLMULTITEXCOORDP4UIVPROC)load("glMultiTexCoordP4uiv");
- glad_glNormalP3ui = (PFNGLNORMALP3UIPROC)load("glNormalP3ui");
- glad_glNormalP3uiv = (PFNGLNORMALP3UIVPROC)load("glNormalP3uiv");
- glad_glColorP3ui = (PFNGLCOLORP3UIPROC)load("glColorP3ui");
- glad_glColorP3uiv = (PFNGLCOLORP3UIVPROC)load("glColorP3uiv");
- glad_glColorP4ui = (PFNGLCOLORP4UIPROC)load("glColorP4ui");
- glad_glColorP4uiv = (PFNGLCOLORP4UIVPROC)load("glColorP4uiv");
- glad_glSecondaryColorP3ui = (PFNGLSECONDARYCOLORP3UIPROC)load("glSecondaryColorP3ui");
- glad_glSecondaryColorP3uiv = (PFNGLSECONDARYCOLORP3UIVPROC)load("glSecondaryColorP3uiv");
-}
-static void load_GL_ARB_debug_output(GLADloadproc load) {
- if(!GLAD_GL_ARB_debug_output) return;
- glad_glDebugMessageControlARB = (PFNGLDEBUGMESSAGECONTROLARBPROC)load("glDebugMessageControlARB");
- glad_glDebugMessageInsertARB = (PFNGLDEBUGMESSAGEINSERTARBPROC)load("glDebugMessageInsertARB");
- glad_glDebugMessageCallbackARB = (PFNGLDEBUGMESSAGECALLBACKARBPROC)load("glDebugMessageCallbackARB");
- glad_glGetDebugMessageLogARB = (PFNGLGETDEBUGMESSAGELOGARBPROC)load("glGetDebugMessageLogARB");
-}
-static void load_GL_ARB_framebuffer_object(GLADloadproc load) {
- if(!GLAD_GL_ARB_framebuffer_object) return;
- glad_glIsRenderbuffer = (PFNGLISRENDERBUFFERPROC)load("glIsRenderbuffer");
- glad_glBindRenderbuffer = (PFNGLBINDRENDERBUFFERPROC)load("glBindRenderbuffer");
- glad_glDeleteRenderbuffers = (PFNGLDELETERENDERBUFFERSPROC)load("glDeleteRenderbuffers");
- glad_glGenRenderbuffers = (PFNGLGENRENDERBUFFERSPROC)load("glGenRenderbuffers");
- glad_glRenderbufferStorage = (PFNGLRENDERBUFFERSTORAGEPROC)load("glRenderbufferStorage");
- glad_glGetRenderbufferParameteriv = (PFNGLGETRENDERBUFFERPARAMETERIVPROC)load("glGetRenderbufferParameteriv");
- glad_glIsFramebuffer = (PFNGLISFRAMEBUFFERPROC)load("glIsFramebuffer");
- glad_glBindFramebuffer = (PFNGLBINDFRAMEBUFFERPROC)load("glBindFramebuffer");
- glad_glDeleteFramebuffers = (PFNGLDELETEFRAMEBUFFERSPROC)load("glDeleteFramebuffers");
- glad_glGenFramebuffers = (PFNGLGENFRAMEBUFFERSPROC)load("glGenFramebuffers");
- glad_glCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSPROC)load("glCheckFramebufferStatus");
- glad_glFramebufferTexture1D = (PFNGLFRAMEBUFFERTEXTURE1DPROC)load("glFramebufferTexture1D");
- glad_glFramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DPROC)load("glFramebufferTexture2D");
- glad_glFramebufferTexture3D = (PFNGLFRAMEBUFFERTEXTURE3DPROC)load("glFramebufferTexture3D");
- glad_glFramebufferRenderbuffer = (PFNGLFRAMEBUFFERRENDERBUFFERPROC)load("glFramebufferRenderbuffer");
- glad_glGetFramebufferAttachmentParameteriv = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC)load("glGetFramebufferAttachmentParameteriv");
- glad_glGenerateMipmap = (PFNGLGENERATEMIPMAPPROC)load("glGenerateMipmap");
- glad_glBlitFramebuffer = (PFNGLBLITFRAMEBUFFERPROC)load("glBlitFramebuffer");
- glad_glRenderbufferStorageMultisample = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC)load("glRenderbufferStorageMultisample");
- glad_glFramebufferTextureLayer = (PFNGLFRAMEBUFFERTEXTURELAYERPROC)load("glFramebufferTextureLayer");
-}
-static void load_GL_EXT_framebuffer_blit(GLADloadproc load) {
- if(!GLAD_GL_EXT_framebuffer_blit) return;
- glad_glBlitFramebufferEXT = (PFNGLBLITFRAMEBUFFEREXTPROC)load("glBlitFramebufferEXT");
-}
-static void load_GL_EXT_framebuffer_multisample(GLADloadproc load) {
- if(!GLAD_GL_EXT_framebuffer_multisample) return;
- glad_glRenderbufferStorageMultisampleEXT = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC)load("glRenderbufferStorageMultisampleEXT");
-}
-static void load_GL_EXT_framebuffer_object(GLADloadproc load) {
- if(!GLAD_GL_EXT_framebuffer_object) return;
- glad_glIsRenderbufferEXT = (PFNGLISRENDERBUFFEREXTPROC)load("glIsRenderbufferEXT");
- glad_glBindRenderbufferEXT = (PFNGLBINDRENDERBUFFEREXTPROC)load("glBindRenderbufferEXT");
- glad_glDeleteRenderbuffersEXT = (PFNGLDELETERENDERBUFFERSEXTPROC)load("glDeleteRenderbuffersEXT");
- glad_glGenRenderbuffersEXT = (PFNGLGENRENDERBUFFERSEXTPROC)load("glGenRenderbuffersEXT");
- glad_glRenderbufferStorageEXT = (PFNGLRENDERBUFFERSTORAGEEXTPROC)load("glRenderbufferStorageEXT");
- glad_glGetRenderbufferParameterivEXT = (PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC)load("glGetRenderbufferParameterivEXT");
- glad_glIsFramebufferEXT = (PFNGLISFRAMEBUFFEREXTPROC)load("glIsFramebufferEXT");
- glad_glBindFramebufferEXT = (PFNGLBINDFRAMEBUFFEREXTPROC)load("glBindFramebufferEXT");
- glad_glDeleteFramebuffersEXT = (PFNGLDELETEFRAMEBUFFERSEXTPROC)load("glDeleteFramebuffersEXT");
- glad_glGenFramebuffersEXT = (PFNGLGENFRAMEBUFFERSEXTPROC)load("glGenFramebuffersEXT");
- glad_glCheckFramebufferStatusEXT = (PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC)load("glCheckFramebufferStatusEXT");
- glad_glFramebufferTexture1DEXT = (PFNGLFRAMEBUFFERTEXTURE1DEXTPROC)load("glFramebufferTexture1DEXT");
- glad_glFramebufferTexture2DEXT = (PFNGLFRAMEBUFFERTEXTURE2DEXTPROC)load("glFramebufferTexture2DEXT");
- glad_glFramebufferTexture3DEXT = (PFNGLFRAMEBUFFERTEXTURE3DEXTPROC)load("glFramebufferTexture3DEXT");
- glad_glFramebufferRenderbufferEXT = (PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC)load("glFramebufferRenderbufferEXT");
- glad_glGetFramebufferAttachmentParameterivEXT = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC)load("glGetFramebufferAttachmentParameterivEXT");
- glad_glGenerateMipmapEXT = (PFNGLGENERATEMIPMAPEXTPROC)load("glGenerateMipmapEXT");
-}
-static void load_GL_OVR_multiview(GLADloadproc load) {
- if(!GLAD_GL_OVR_multiview) return;
- glad_glFramebufferTextureMultiviewOVR = (PFNGLFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC)load("glFramebufferTextureMultiviewOVR");
-}
-static int find_extensionsGL(void) {
- if (!get_exts()) return 0;
- GLAD_GL_ARB_debug_output = has_ext("GL_ARB_debug_output");
- GLAD_GL_ARB_framebuffer_object = has_ext("GL_ARB_framebuffer_object");
- GLAD_GL_EXT_framebuffer_blit = has_ext("GL_EXT_framebuffer_blit");
- GLAD_GL_EXT_framebuffer_multisample = has_ext("GL_EXT_framebuffer_multisample");
- GLAD_GL_EXT_framebuffer_object = has_ext("GL_EXT_framebuffer_object");
- GLAD_GL_OVR_multiview = has_ext("GL_OVR_multiview");
- GLAD_GL_OVR_multiview2 = has_ext("GL_OVR_multiview2");
- free_exts();
- return 1;
-}
-
-static void find_coreGL(void) {
-
- /* Thank you @elmindreda
- * https://github.com/elmindreda/greg/blob/master/templates/greg.c.in#L176
- * https://github.com/glfw/glfw/blob/master/src/context.c#L36
- */
- int i, major, minor;
-
- const char* version;
- const char* prefixes[] = {
- "OpenGL ES-CM ",
- "OpenGL ES-CL ",
- "OpenGL ES ",
- NULL
- };
-
- version = (const char*) glGetString(GL_VERSION);
- if (!version) return;
-
- for (i = 0; prefixes[i]; i++) {
- const size_t length = strlen(prefixes[i]);
- if (strncmp(version, prefixes[i], length) == 0) {
- version += length;
- break;
- }
- }
-
-/* PR #18 */
-#ifdef _MSC_VER
- sscanf_s(version, "%d.%d", &major, &minor);
-#else
- sscanf(version, "%d.%d", &major, &minor);
-#endif
-
- GLVersion.major = major; GLVersion.minor = minor;
- max_loaded_major = major; max_loaded_minor = minor;
- GLAD_GL_VERSION_1_0 = (major == 1 && minor >= 0) || major > 1;
- GLAD_GL_VERSION_1_1 = (major == 1 && minor >= 1) || major > 1;
- GLAD_GL_VERSION_1_2 = (major == 1 && minor >= 2) || major > 1;
- GLAD_GL_VERSION_1_3 = (major == 1 && minor >= 3) || major > 1;
- GLAD_GL_VERSION_1_4 = (major == 1 && minor >= 4) || major > 1;
- GLAD_GL_VERSION_1_5 = (major == 1 && minor >= 5) || major > 1;
- GLAD_GL_VERSION_2_0 = (major == 2 && minor >= 0) || major > 2;
- GLAD_GL_VERSION_2_1 = (major == 2 && minor >= 1) || major > 2;
- GLAD_GL_VERSION_3_0 = (major == 3 && minor >= 0) || major > 3;
- GLAD_GL_VERSION_3_1 = (major == 3 && minor >= 1) || major > 3;
- GLAD_GL_VERSION_3_2 = (major == 3 && minor >= 2) || major > 3;
- GLAD_GL_VERSION_3_3 = (major == 3 && minor >= 3) || major > 3;
- if (GLVersion.major > 3 || (GLVersion.major >= 3 && GLVersion.minor >= 3)) {
- max_loaded_major = 3;
- max_loaded_minor = 3;
- }
-}
-
-int gladLoadGLLoader(GLADloadproc load) {
- GLVersion.major = 0; GLVersion.minor = 0;
- glGetString = (PFNGLGETSTRINGPROC)load("glGetString");
- if(glGetString == NULL) return 0;
- if(glGetString(GL_VERSION) == NULL) return 0;
- find_coreGL();
- load_GL_VERSION_1_0(load);
- load_GL_VERSION_1_1(load);
- load_GL_VERSION_1_2(load);
- load_GL_VERSION_1_3(load);
- load_GL_VERSION_1_4(load);
- load_GL_VERSION_1_5(load);
- load_GL_VERSION_2_0(load);
- load_GL_VERSION_2_1(load);
- load_GL_VERSION_3_0(load);
- load_GL_VERSION_3_1(load);
- load_GL_VERSION_3_2(load);
- load_GL_VERSION_3_3(load);
-
- if (!find_extensionsGL()) return 0;
- load_GL_ARB_debug_output(load);
- load_GL_ARB_framebuffer_object(load);
- load_GL_EXT_framebuffer_blit(load);
- load_GL_EXT_framebuffer_multisample(load);
- load_GL_EXT_framebuffer_object(load);
- load_GL_OVR_multiview(load);
- return GLVersion.major != 0 || GLVersion.minor != 0;
-}
-
diff --git a/thirdparty/glad/glad/gl.h b/thirdparty/glad/glad/gl.h
new file mode 100644
index 0000000000..9836296226
--- /dev/null
+++ b/thirdparty/glad/glad/gl.h
@@ -0,0 +1,3884 @@
+/**
+ * Loader generated by glad 2.0.2 on Mon Nov 7 12:17:15 2022
+ *
+ * SPDX-License-Identifier: (WTFPL OR CC0-1.0) AND Apache-2.0
+ *
+ * Generator: C/C++
+ * Specification: gl
+ * Extensions: 7
+ *
+ * APIs:
+ * - gl:compatibility=3.3
+ *
+ * Options:
+ * - ALIAS = False
+ * - DEBUG = False
+ * - HEADER_ONLY = False
+ * - LOADER = True
+ * - MX = False
+ * - ON_DEMAND = False
+ *
+ * Commandline:
+ * --api='gl:compatibility=3.3' --extensions='GL_ARB_debug_output,GL_ARB_framebuffer_object,GL_EXT_framebuffer_blit,GL_EXT_framebuffer_multisample,GL_EXT_framebuffer_object,GL_OVR_multiview,GL_OVR_multiview2' c --loader
+ *
+ * Online:
+ * http://glad.sh/#api=gl%3Acompatibility%3D3.3&extensions=GL_ARB_debug_output%2CGL_ARB_framebuffer_object%2CGL_EXT_framebuffer_blit%2CGL_EXT_framebuffer_multisample%2CGL_EXT_framebuffer_object%2CGL_OVR_multiview%2CGL_OVR_multiview2&generator=c&options=LOADER
+ *
+ */
+
+#ifndef GLAD_GL_H_
+#define GLAD_GL_H_
+
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wreserved-id-macro"
+#endif
+#ifdef __gl_h_
+ #error OpenGL (gl.h) header already included (API: gl), remove previous include!
+#endif
+#define __gl_h_ 1
+#ifdef __gl3_h_
+ #error OpenGL (gl3.h) header already included (API: gl), remove previous include!
+#endif
+#define __gl3_h_ 1
+#ifdef __glext_h_
+ #error OpenGL (glext.h) header already included (API: gl), remove previous include!
+#endif
+#define __glext_h_ 1
+#ifdef __gl3ext_h_
+ #error OpenGL (gl3ext.h) header already included (API: gl), remove previous include!
+#endif
+#define __gl3ext_h_ 1
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+
+#define GLAD_GL
+#define GLAD_OPTION_GL_LOADER
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef GLAD_PLATFORM_H_
+#define GLAD_PLATFORM_H_
+
+#ifndef GLAD_PLATFORM_WIN32
+ #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) || defined(__MINGW32__)
+ #define GLAD_PLATFORM_WIN32 1
+ #else
+ #define GLAD_PLATFORM_WIN32 0
+ #endif
+#endif
+
+#ifndef GLAD_PLATFORM_APPLE
+ #ifdef __APPLE__
+ #define GLAD_PLATFORM_APPLE 1
+ #else
+ #define GLAD_PLATFORM_APPLE 0
+ #endif
+#endif
+
+#ifndef GLAD_PLATFORM_EMSCRIPTEN
+ #ifdef __EMSCRIPTEN__
+ #define GLAD_PLATFORM_EMSCRIPTEN 1
+ #else
+ #define GLAD_PLATFORM_EMSCRIPTEN 0
+ #endif
+#endif
+
+#ifndef GLAD_PLATFORM_UWP
+ #if defined(_MSC_VER) && !defined(GLAD_INTERNAL_HAVE_WINAPIFAMILY)
+ #ifdef __has_include
+ #if __has_include(<winapifamily.h>)
+ #define GLAD_INTERNAL_HAVE_WINAPIFAMILY 1
+ #endif
+ #elif _MSC_VER >= 1700 && !_USING_V110_SDK71_
+ #define GLAD_INTERNAL_HAVE_WINAPIFAMILY 1
+ #endif
+ #endif
+
+ #ifdef GLAD_INTERNAL_HAVE_WINAPIFAMILY
+ #include <winapifamily.h>
+ #if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)
+ #define GLAD_PLATFORM_UWP 1
+ #endif
+ #endif
+
+ #ifndef GLAD_PLATFORM_UWP
+ #define GLAD_PLATFORM_UWP 0
+ #endif
+#endif
+
+#ifdef __GNUC__
+ #define GLAD_GNUC_EXTENSION __extension__
+#else
+ #define GLAD_GNUC_EXTENSION
+#endif
+
+#define GLAD_UNUSED(x) (void)(x)
+
+#ifndef GLAD_API_CALL
+ #if defined(GLAD_API_CALL_EXPORT)
+ #if GLAD_PLATFORM_WIN32 || defined(__CYGWIN__)
+ #if defined(GLAD_API_CALL_EXPORT_BUILD)
+ #if defined(__GNUC__)
+ #define GLAD_API_CALL __attribute__ ((dllexport)) extern
+ #else
+ #define GLAD_API_CALL __declspec(dllexport) extern
+ #endif
+ #else
+ #if defined(__GNUC__)
+ #define GLAD_API_CALL __attribute__ ((dllimport)) extern
+ #else
+ #define GLAD_API_CALL __declspec(dllimport) extern
+ #endif
+ #endif
+ #elif defined(__GNUC__) && defined(GLAD_API_CALL_EXPORT_BUILD)
+ #define GLAD_API_CALL __attribute__ ((visibility ("default"))) extern
+ #else
+ #define GLAD_API_CALL extern
+ #endif
+ #else
+ #define GLAD_API_CALL extern
+ #endif
+#endif
+
+#ifdef APIENTRY
+ #define GLAD_API_PTR APIENTRY
+#elif GLAD_PLATFORM_WIN32
+ #define GLAD_API_PTR __stdcall
+#else
+ #define GLAD_API_PTR
+#endif
+
+#ifndef GLAPI
+#define GLAPI GLAD_API_CALL
+#endif
+
+#ifndef GLAPIENTRY
+#define GLAPIENTRY GLAD_API_PTR
+#endif
+
+#define GLAD_MAKE_VERSION(major, minor) (major * 10000 + minor)
+#define GLAD_VERSION_MAJOR(version) (version / 10000)
+#define GLAD_VERSION_MINOR(version) (version % 10000)
+
+#define GLAD_GENERATOR_VERSION "2.0.2"
+
+typedef void (*GLADapiproc)(void);
+
+typedef GLADapiproc (*GLADloadfunc)(const char *name);
+typedef GLADapiproc (*GLADuserptrloadfunc)(void *userptr, const char *name);
+
+typedef void (*GLADprecallback)(const char *name, GLADapiproc apiproc, int len_args, ...);
+typedef void (*GLADpostcallback)(void *ret, const char *name, GLADapiproc apiproc, int len_args, ...);
+
+#endif /* GLAD_PLATFORM_H_ */
+
+#define GL_2D 0x0600
+#define GL_2_BYTES 0x1407
+#define GL_3D 0x0601
+#define GL_3D_COLOR 0x0602
+#define GL_3D_COLOR_TEXTURE 0x0603
+#define GL_3_BYTES 0x1408
+#define GL_4D_COLOR_TEXTURE 0x0604
+#define GL_4_BYTES 0x1409
+#define GL_ACCUM 0x0100
+#define GL_ACCUM_ALPHA_BITS 0x0D5B
+#define GL_ACCUM_BLUE_BITS 0x0D5A
+#define GL_ACCUM_BUFFER_BIT 0x00000200
+#define GL_ACCUM_CLEAR_VALUE 0x0B80
+#define GL_ACCUM_GREEN_BITS 0x0D59
+#define GL_ACCUM_RED_BITS 0x0D58
+#define GL_ACTIVE_ATTRIBUTES 0x8B89
+#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A
+#define GL_ACTIVE_TEXTURE 0x84E0
+#define GL_ACTIVE_UNIFORMS 0x8B86
+#define GL_ACTIVE_UNIFORM_BLOCKS 0x8A36
+#define GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH 0x8A35
+#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87
+#define GL_ADD 0x0104
+#define GL_ADD_SIGNED 0x8574
+#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E
+#define GL_ALIASED_POINT_SIZE_RANGE 0x846D
+#define GL_ALL_ATTRIB_BITS 0xFFFFFFFF
+#define GL_ALPHA 0x1906
+#define GL_ALPHA12 0x803D
+#define GL_ALPHA16 0x803E
+#define GL_ALPHA4 0x803B
+#define GL_ALPHA8 0x803C
+#define GL_ALPHA_BIAS 0x0D1D
+#define GL_ALPHA_BITS 0x0D55
+#define GL_ALPHA_INTEGER 0x8D97
+#define GL_ALPHA_SCALE 0x0D1C
+#define GL_ALPHA_TEST 0x0BC0
+#define GL_ALPHA_TEST_FUNC 0x0BC1
+#define GL_ALPHA_TEST_REF 0x0BC2
+#define GL_ALREADY_SIGNALED 0x911A
+#define GL_ALWAYS 0x0207
+#define GL_AMBIENT 0x1200
+#define GL_AMBIENT_AND_DIFFUSE 0x1602
+#define GL_AND 0x1501
+#define GL_AND_INVERTED 0x1504
+#define GL_AND_REVERSE 0x1502
+#define GL_ANY_SAMPLES_PASSED 0x8C2F
+#define GL_ARRAY_BUFFER 0x8892
+#define GL_ARRAY_BUFFER_BINDING 0x8894
+#define GL_ATTACHED_SHADERS 0x8B85
+#define GL_ATTRIB_STACK_DEPTH 0x0BB0
+#define GL_AUTO_NORMAL 0x0D80
+#define GL_AUX0 0x0409
+#define GL_AUX1 0x040A
+#define GL_AUX2 0x040B
+#define GL_AUX3 0x040C
+#define GL_AUX_BUFFERS 0x0C00
+#define GL_BACK 0x0405
+#define GL_BACK_LEFT 0x0402
+#define GL_BACK_RIGHT 0x0403
+#define GL_BGR 0x80E0
+#define GL_BGRA 0x80E1
+#define GL_BGRA_INTEGER 0x8D9B
+#define GL_BGR_INTEGER 0x8D9A
+#define GL_BITMAP 0x1A00
+#define GL_BITMAP_TOKEN 0x0704
+#define GL_BLEND 0x0BE2
+#define GL_BLEND_COLOR 0x8005
+#define GL_BLEND_DST 0x0BE0
+#define GL_BLEND_DST_ALPHA 0x80CA
+#define GL_BLEND_DST_RGB 0x80C8
+#define GL_BLEND_EQUATION 0x8009
+#define GL_BLEND_EQUATION_ALPHA 0x883D
+#define GL_BLEND_EQUATION_RGB 0x8009
+#define GL_BLEND_SRC 0x0BE1
+#define GL_BLEND_SRC_ALPHA 0x80CB
+#define GL_BLEND_SRC_RGB 0x80C9
+#define GL_BLUE 0x1905
+#define GL_BLUE_BIAS 0x0D1B
+#define GL_BLUE_BITS 0x0D54
+#define GL_BLUE_INTEGER 0x8D96
+#define GL_BLUE_SCALE 0x0D1A
+#define GL_BOOL 0x8B56
+#define GL_BOOL_VEC2 0x8B57
+#define GL_BOOL_VEC3 0x8B58
+#define GL_BOOL_VEC4 0x8B59
+#define GL_BUFFER_ACCESS 0x88BB
+#define GL_BUFFER_ACCESS_FLAGS 0x911F
+#define GL_BUFFER_MAPPED 0x88BC
+#define GL_BUFFER_MAP_LENGTH 0x9120
+#define GL_BUFFER_MAP_OFFSET 0x9121
+#define GL_BUFFER_MAP_POINTER 0x88BD
+#define GL_BUFFER_SIZE 0x8764
+#define GL_BUFFER_USAGE 0x8765
+#define GL_BYTE 0x1400
+#define GL_C3F_V3F 0x2A24
+#define GL_C4F_N3F_V3F 0x2A26
+#define GL_C4UB_V2F 0x2A22
+#define GL_C4UB_V3F 0x2A23
+#define GL_CCW 0x0901
+#define GL_CLAMP 0x2900
+#define GL_CLAMP_FRAGMENT_COLOR 0x891B
+#define GL_CLAMP_READ_COLOR 0x891C
+#define GL_CLAMP_TO_BORDER 0x812D
+#define GL_CLAMP_TO_EDGE 0x812F
+#define GL_CLAMP_VERTEX_COLOR 0x891A
+#define GL_CLEAR 0x1500
+#define GL_CLIENT_ACTIVE_TEXTURE 0x84E1
+#define GL_CLIENT_ALL_ATTRIB_BITS 0xFFFFFFFF
+#define GL_CLIENT_ATTRIB_STACK_DEPTH 0x0BB1
+#define GL_CLIENT_PIXEL_STORE_BIT 0x00000001
+#define GL_CLIENT_VERTEX_ARRAY_BIT 0x00000002
+#define GL_CLIP_DISTANCE0 0x3000
+#define GL_CLIP_DISTANCE1 0x3001
+#define GL_CLIP_DISTANCE2 0x3002
+#define GL_CLIP_DISTANCE3 0x3003
+#define GL_CLIP_DISTANCE4 0x3004
+#define GL_CLIP_DISTANCE5 0x3005
+#define GL_CLIP_DISTANCE6 0x3006
+#define GL_CLIP_DISTANCE7 0x3007
+#define GL_CLIP_PLANE0 0x3000
+#define GL_CLIP_PLANE1 0x3001
+#define GL_CLIP_PLANE2 0x3002
+#define GL_CLIP_PLANE3 0x3003
+#define GL_CLIP_PLANE4 0x3004
+#define GL_CLIP_PLANE5 0x3005
+#define GL_COEFF 0x0A00
+#define GL_COLOR 0x1800
+#define GL_COLOR_ARRAY 0x8076
+#define GL_COLOR_ARRAY_BUFFER_BINDING 0x8898
+#define GL_COLOR_ARRAY_POINTER 0x8090
+#define GL_COLOR_ARRAY_SIZE 0x8081
+#define GL_COLOR_ARRAY_STRIDE 0x8083
+#define GL_COLOR_ARRAY_TYPE 0x8082
+#define GL_COLOR_ATTACHMENT0 0x8CE0
+#define GL_COLOR_ATTACHMENT0_EXT 0x8CE0
+#define GL_COLOR_ATTACHMENT1 0x8CE1
+#define GL_COLOR_ATTACHMENT10 0x8CEA
+#define GL_COLOR_ATTACHMENT10_EXT 0x8CEA
+#define GL_COLOR_ATTACHMENT11 0x8CEB
+#define GL_COLOR_ATTACHMENT11_EXT 0x8CEB
+#define GL_COLOR_ATTACHMENT12 0x8CEC
+#define GL_COLOR_ATTACHMENT12_EXT 0x8CEC
+#define GL_COLOR_ATTACHMENT13 0x8CED
+#define GL_COLOR_ATTACHMENT13_EXT 0x8CED
+#define GL_COLOR_ATTACHMENT14 0x8CEE
+#define GL_COLOR_ATTACHMENT14_EXT 0x8CEE
+#define GL_COLOR_ATTACHMENT15 0x8CEF
+#define GL_COLOR_ATTACHMENT15_EXT 0x8CEF
+#define GL_COLOR_ATTACHMENT16 0x8CF0
+#define GL_COLOR_ATTACHMENT17 0x8CF1
+#define GL_COLOR_ATTACHMENT18 0x8CF2
+#define GL_COLOR_ATTACHMENT19 0x8CF3
+#define GL_COLOR_ATTACHMENT1_EXT 0x8CE1
+#define GL_COLOR_ATTACHMENT2 0x8CE2
+#define GL_COLOR_ATTACHMENT20 0x8CF4
+#define GL_COLOR_ATTACHMENT21 0x8CF5
+#define GL_COLOR_ATTACHMENT22 0x8CF6
+#define GL_COLOR_ATTACHMENT23 0x8CF7
+#define GL_COLOR_ATTACHMENT24 0x8CF8
+#define GL_COLOR_ATTACHMENT25 0x8CF9
+#define GL_COLOR_ATTACHMENT26 0x8CFA
+#define GL_COLOR_ATTACHMENT27 0x8CFB
+#define GL_COLOR_ATTACHMENT28 0x8CFC
+#define GL_COLOR_ATTACHMENT29 0x8CFD
+#define GL_COLOR_ATTACHMENT2_EXT 0x8CE2
+#define GL_COLOR_ATTACHMENT3 0x8CE3
+#define GL_COLOR_ATTACHMENT30 0x8CFE
+#define GL_COLOR_ATTACHMENT31 0x8CFF
+#define GL_COLOR_ATTACHMENT3_EXT 0x8CE3
+#define GL_COLOR_ATTACHMENT4 0x8CE4
+#define GL_COLOR_ATTACHMENT4_EXT 0x8CE4
+#define GL_COLOR_ATTACHMENT5 0x8CE5
+#define GL_COLOR_ATTACHMENT5_EXT 0x8CE5
+#define GL_COLOR_ATTACHMENT6 0x8CE6
+#define GL_COLOR_ATTACHMENT6_EXT 0x8CE6
+#define GL_COLOR_ATTACHMENT7 0x8CE7
+#define GL_COLOR_ATTACHMENT7_EXT 0x8CE7
+#define GL_COLOR_ATTACHMENT8 0x8CE8
+#define GL_COLOR_ATTACHMENT8_EXT 0x8CE8
+#define GL_COLOR_ATTACHMENT9 0x8CE9
+#define GL_COLOR_ATTACHMENT9_EXT 0x8CE9
+#define GL_COLOR_BUFFER_BIT 0x00004000
+#define GL_COLOR_CLEAR_VALUE 0x0C22
+#define GL_COLOR_INDEX 0x1900
+#define GL_COLOR_INDEXES 0x1603
+#define GL_COLOR_LOGIC_OP 0x0BF2
+#define GL_COLOR_MATERIAL 0x0B57
+#define GL_COLOR_MATERIAL_FACE 0x0B55
+#define GL_COLOR_MATERIAL_PARAMETER 0x0B56
+#define GL_COLOR_SUM 0x8458
+#define GL_COLOR_WRITEMASK 0x0C23
+#define GL_COMBINE 0x8570
+#define GL_COMBINE_ALPHA 0x8572
+#define GL_COMBINE_RGB 0x8571
+#define GL_COMPARE_REF_TO_TEXTURE 0x884E
+#define GL_COMPARE_R_TO_TEXTURE 0x884E
+#define GL_COMPILE 0x1300
+#define GL_COMPILE_AND_EXECUTE 0x1301
+#define GL_COMPILE_STATUS 0x8B81
+#define GL_COMPRESSED_ALPHA 0x84E9
+#define GL_COMPRESSED_INTENSITY 0x84EC
+#define GL_COMPRESSED_LUMINANCE 0x84EA
+#define GL_COMPRESSED_LUMINANCE_ALPHA 0x84EB
+#define GL_COMPRESSED_RED 0x8225
+#define GL_COMPRESSED_RED_RGTC1 0x8DBB
+#define GL_COMPRESSED_RG 0x8226
+#define GL_COMPRESSED_RGB 0x84ED
+#define GL_COMPRESSED_RGBA 0x84EE
+#define GL_COMPRESSED_RG_RGTC2 0x8DBD
+#define GL_COMPRESSED_SIGNED_RED_RGTC1 0x8DBC
+#define GL_COMPRESSED_SIGNED_RG_RGTC2 0x8DBE
+#define GL_COMPRESSED_SLUMINANCE 0x8C4A
+#define GL_COMPRESSED_SLUMINANCE_ALPHA 0x8C4B
+#define GL_COMPRESSED_SRGB 0x8C48
+#define GL_COMPRESSED_SRGB_ALPHA 0x8C49
+#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3
+#define GL_CONDITION_SATISFIED 0x911C
+#define GL_CONSTANT 0x8576
+#define GL_CONSTANT_ALPHA 0x8003
+#define GL_CONSTANT_ATTENUATION 0x1207
+#define GL_CONSTANT_COLOR 0x8001
+#define GL_CONTEXT_COMPATIBILITY_PROFILE_BIT 0x00000002
+#define GL_CONTEXT_CORE_PROFILE_BIT 0x00000001
+#define GL_CONTEXT_FLAGS 0x821E
+#define GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT 0x00000001
+#define GL_CONTEXT_PROFILE_MASK 0x9126
+#define GL_COORD_REPLACE 0x8862
+#define GL_COPY 0x1503
+#define GL_COPY_INVERTED 0x150C
+#define GL_COPY_PIXEL_TOKEN 0x0706
+#define GL_COPY_READ_BUFFER 0x8F36
+#define GL_COPY_WRITE_BUFFER 0x8F37
+#define GL_CULL_FACE 0x0B44
+#define GL_CULL_FACE_MODE 0x0B45
+#define GL_CURRENT_BIT 0x00000001
+#define GL_CURRENT_COLOR 0x0B00
+#define GL_CURRENT_FOG_COORD 0x8453
+#define GL_CURRENT_FOG_COORDINATE 0x8453
+#define GL_CURRENT_INDEX 0x0B01
+#define GL_CURRENT_NORMAL 0x0B02
+#define GL_CURRENT_PROGRAM 0x8B8D
+#define GL_CURRENT_QUERY 0x8865
+#define GL_CURRENT_RASTER_COLOR 0x0B04
+#define GL_CURRENT_RASTER_DISTANCE 0x0B09
+#define GL_CURRENT_RASTER_INDEX 0x0B05
+#define GL_CURRENT_RASTER_POSITION 0x0B07
+#define GL_CURRENT_RASTER_POSITION_VALID 0x0B08
+#define GL_CURRENT_RASTER_SECONDARY_COLOR 0x845F
+#define GL_CURRENT_RASTER_TEXTURE_COORDS 0x0B06
+#define GL_CURRENT_SECONDARY_COLOR 0x8459
+#define GL_CURRENT_TEXTURE_COORDS 0x0B03
+#define GL_CURRENT_VERTEX_ATTRIB 0x8626
+#define GL_CW 0x0900
+#define GL_DEBUG_CALLBACK_FUNCTION_ARB 0x8244
+#define GL_DEBUG_CALLBACK_USER_PARAM_ARB 0x8245
+#define GL_DEBUG_LOGGED_MESSAGES_ARB 0x9145
+#define GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_ARB 0x8243
+#define GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB 0x8242
+#define GL_DEBUG_SEVERITY_HIGH_ARB 0x9146
+#define GL_DEBUG_SEVERITY_LOW_ARB 0x9148
+#define GL_DEBUG_SEVERITY_MEDIUM_ARB 0x9147
+#define GL_DEBUG_SOURCE_API_ARB 0x8246
+#define GL_DEBUG_SOURCE_APPLICATION_ARB 0x824A
+#define GL_DEBUG_SOURCE_OTHER_ARB 0x824B
+#define GL_DEBUG_SOURCE_SHADER_COMPILER_ARB 0x8248
+#define GL_DEBUG_SOURCE_THIRD_PARTY_ARB 0x8249
+#define GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB 0x8247
+#define GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB 0x824D
+#define GL_DEBUG_TYPE_ERROR_ARB 0x824C
+#define GL_DEBUG_TYPE_OTHER_ARB 0x8251
+#define GL_DEBUG_TYPE_PERFORMANCE_ARB 0x8250
+#define GL_DEBUG_TYPE_PORTABILITY_ARB 0x824F
+#define GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB 0x824E
+#define GL_DECAL 0x2101
+#define GL_DECR 0x1E03
+#define GL_DECR_WRAP 0x8508
+#define GL_DELETE_STATUS 0x8B80
+#define GL_DEPTH 0x1801
+#define GL_DEPTH24_STENCIL8 0x88F0
+#define GL_DEPTH32F_STENCIL8 0x8CAD
+#define GL_DEPTH_ATTACHMENT 0x8D00
+#define GL_DEPTH_ATTACHMENT_EXT 0x8D00
+#define GL_DEPTH_BIAS 0x0D1F
+#define GL_DEPTH_BITS 0x0D56
+#define GL_DEPTH_BUFFER_BIT 0x00000100
+#define GL_DEPTH_CLAMP 0x864F
+#define GL_DEPTH_CLEAR_VALUE 0x0B73
+#define GL_DEPTH_COMPONENT 0x1902
+#define GL_DEPTH_COMPONENT16 0x81A5
+#define GL_DEPTH_COMPONENT24 0x81A6
+#define GL_DEPTH_COMPONENT32 0x81A7
+#define GL_DEPTH_COMPONENT32F 0x8CAC
+#define GL_DEPTH_FUNC 0x0B74
+#define GL_DEPTH_RANGE 0x0B70
+#define GL_DEPTH_SCALE 0x0D1E
+#define GL_DEPTH_STENCIL 0x84F9
+#define GL_DEPTH_STENCIL_ATTACHMENT 0x821A
+#define GL_DEPTH_TEST 0x0B71
+#define GL_DEPTH_TEXTURE_MODE 0x884B
+#define GL_DEPTH_WRITEMASK 0x0B72
+#define GL_DIFFUSE 0x1201
+#define GL_DITHER 0x0BD0
+#define GL_DOMAIN 0x0A02
+#define GL_DONT_CARE 0x1100
+#define GL_DOT3_RGB 0x86AE
+#define GL_DOT3_RGBA 0x86AF
+#define GL_DOUBLE 0x140A
+#define GL_DOUBLEBUFFER 0x0C32
+#define GL_DRAW_BUFFER 0x0C01
+#define GL_DRAW_BUFFER0 0x8825
+#define GL_DRAW_BUFFER1 0x8826
+#define GL_DRAW_BUFFER10 0x882F
+#define GL_DRAW_BUFFER11 0x8830
+#define GL_DRAW_BUFFER12 0x8831
+#define GL_DRAW_BUFFER13 0x8832
+#define GL_DRAW_BUFFER14 0x8833
+#define GL_DRAW_BUFFER15 0x8834
+#define GL_DRAW_BUFFER2 0x8827
+#define GL_DRAW_BUFFER3 0x8828
+#define GL_DRAW_BUFFER4 0x8829
+#define GL_DRAW_BUFFER5 0x882A
+#define GL_DRAW_BUFFER6 0x882B
+#define GL_DRAW_BUFFER7 0x882C
+#define GL_DRAW_BUFFER8 0x882D
+#define GL_DRAW_BUFFER9 0x882E
+#define GL_DRAW_FRAMEBUFFER 0x8CA9
+#define GL_DRAW_FRAMEBUFFER_BINDING 0x8CA6
+#define GL_DRAW_FRAMEBUFFER_BINDING_EXT 0x8CA6
+#define GL_DRAW_FRAMEBUFFER_EXT 0x8CA9
+#define GL_DRAW_PIXEL_TOKEN 0x0705
+#define GL_DST_ALPHA 0x0304
+#define GL_DST_COLOR 0x0306
+#define GL_DYNAMIC_COPY 0x88EA
+#define GL_DYNAMIC_DRAW 0x88E8
+#define GL_DYNAMIC_READ 0x88E9
+#define GL_EDGE_FLAG 0x0B43
+#define GL_EDGE_FLAG_ARRAY 0x8079
+#define GL_EDGE_FLAG_ARRAY_BUFFER_BINDING 0x889B
+#define GL_EDGE_FLAG_ARRAY_POINTER 0x8093
+#define GL_EDGE_FLAG_ARRAY_STRIDE 0x808C
+#define GL_ELEMENT_ARRAY_BUFFER 0x8893
+#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895
+#define GL_EMISSION 0x1600
+#define GL_ENABLE_BIT 0x00002000
+#define GL_EQUAL 0x0202
+#define GL_EQUIV 0x1509
+#define GL_EVAL_BIT 0x00010000
+#define GL_EXP 0x0800
+#define GL_EXP2 0x0801
+#define GL_EXTENSIONS 0x1F03
+#define GL_EYE_LINEAR 0x2400
+#define GL_EYE_PLANE 0x2502
+#define GL_FALSE 0
+#define GL_FASTEST 0x1101
+#define GL_FEEDBACK 0x1C01
+#define GL_FEEDBACK_BUFFER_POINTER 0x0DF0
+#define GL_FEEDBACK_BUFFER_SIZE 0x0DF1
+#define GL_FEEDBACK_BUFFER_TYPE 0x0DF2
+#define GL_FILL 0x1B02
+#define GL_FIRST_VERTEX_CONVENTION 0x8E4D
+#define GL_FIXED_ONLY 0x891D
+#define GL_FLAT 0x1D00
+#define GL_FLOAT 0x1406
+#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV 0x8DAD
+#define GL_FLOAT_MAT2 0x8B5A
+#define GL_FLOAT_MAT2x3 0x8B65
+#define GL_FLOAT_MAT2x4 0x8B66
+#define GL_FLOAT_MAT3 0x8B5B
+#define GL_FLOAT_MAT3x2 0x8B67
+#define GL_FLOAT_MAT3x4 0x8B68
+#define GL_FLOAT_MAT4 0x8B5C
+#define GL_FLOAT_MAT4x2 0x8B69
+#define GL_FLOAT_MAT4x3 0x8B6A
+#define GL_FLOAT_VEC2 0x8B50
+#define GL_FLOAT_VEC3 0x8B51
+#define GL_FLOAT_VEC4 0x8B52
+#define GL_FOG 0x0B60
+#define GL_FOG_BIT 0x00000080
+#define GL_FOG_COLOR 0x0B66
+#define GL_FOG_COORD 0x8451
+#define GL_FOG_COORDINATE 0x8451
+#define GL_FOG_COORDINATE_ARRAY 0x8457
+#define GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING 0x889D
+#define GL_FOG_COORDINATE_ARRAY_POINTER 0x8456
+#define GL_FOG_COORDINATE_ARRAY_STRIDE 0x8455
+#define GL_FOG_COORDINATE_ARRAY_TYPE 0x8454
+#define GL_FOG_COORDINATE_SOURCE 0x8450
+#define GL_FOG_COORD_ARRAY 0x8457
+#define GL_FOG_COORD_ARRAY_BUFFER_BINDING 0x889D
+#define GL_FOG_COORD_ARRAY_POINTER 0x8456
+#define GL_FOG_COORD_ARRAY_STRIDE 0x8455
+#define GL_FOG_COORD_ARRAY_TYPE 0x8454
+#define GL_FOG_COORD_SRC 0x8450
+#define GL_FOG_DENSITY 0x0B62
+#define GL_FOG_END 0x0B64
+#define GL_FOG_HINT 0x0C54
+#define GL_FOG_INDEX 0x0B61
+#define GL_FOG_MODE 0x0B65
+#define GL_FOG_START 0x0B63
+#define GL_FRAGMENT_DEPTH 0x8452
+#define GL_FRAGMENT_SHADER 0x8B30
+#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT 0x8B8B
+#define GL_FRAMEBUFFER 0x8D40
+#define GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE 0x8215
+#define GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE 0x8214
+#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING 0x8210
+#define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE 0x8211
+#define GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE 0x8216
+#define GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE 0x8213
+#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED 0x8DA7
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT 0x8CD1
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT 0x8CD0
+#define GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE 0x8212
+#define GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE 0x8217
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT 0x8CD4
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_OVR 0x9632
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT 0x8CD3
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER 0x8CD4
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT 0x8CD2
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_OVR 0x9630
+#define GL_FRAMEBUFFER_BINDING 0x8CA6
+#define GL_FRAMEBUFFER_BINDING_EXT 0x8CA6
+#define GL_FRAMEBUFFER_COMPLETE 0x8CD5
+#define GL_FRAMEBUFFER_COMPLETE_EXT 0x8CD5
+#define GL_FRAMEBUFFER_DEFAULT 0x8218
+#define GL_FRAMEBUFFER_EXT 0x8D40
+#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6
+#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT 0x8CD6
+#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT 0x8CD9
+#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER 0x8CDB
+#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT 0x8CDB
+#define GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT 0x8CDA
+#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS 0x8DA8
+#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7
+#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT 0x8CD7
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 0x8D56
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT 0x8D56
+#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER 0x8CDC
+#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT 0x8CDC
+#define GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_OVR 0x9633
+#define GL_FRAMEBUFFER_SRGB 0x8DB9
+#define GL_FRAMEBUFFER_UNDEFINED 0x8219
+#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD
+#define GL_FRAMEBUFFER_UNSUPPORTED_EXT 0x8CDD
+#define GL_FRONT 0x0404
+#define GL_FRONT_AND_BACK 0x0408
+#define GL_FRONT_FACE 0x0B46
+#define GL_FRONT_LEFT 0x0400
+#define GL_FRONT_RIGHT 0x0401
+#define GL_FUNC_ADD 0x8006
+#define GL_FUNC_REVERSE_SUBTRACT 0x800B
+#define GL_FUNC_SUBTRACT 0x800A
+#define GL_GENERATE_MIPMAP 0x8191
+#define GL_GENERATE_MIPMAP_HINT 0x8192
+#define GL_GEOMETRY_INPUT_TYPE 0x8917
+#define GL_GEOMETRY_OUTPUT_TYPE 0x8918
+#define GL_GEOMETRY_SHADER 0x8DD9
+#define GL_GEOMETRY_VERTICES_OUT 0x8916
+#define GL_GEQUAL 0x0206
+#define GL_GREATER 0x0204
+#define GL_GREEN 0x1904
+#define GL_GREEN_BIAS 0x0D19
+#define GL_GREEN_BITS 0x0D53
+#define GL_GREEN_INTEGER 0x8D95
+#define GL_GREEN_SCALE 0x0D18
+#define GL_HALF_FLOAT 0x140B
+#define GL_HINT_BIT 0x00008000
+#define GL_INCR 0x1E02
+#define GL_INCR_WRAP 0x8507
+#define GL_INDEX 0x8222
+#define GL_INDEX_ARRAY 0x8077
+#define GL_INDEX_ARRAY_BUFFER_BINDING 0x8899
+#define GL_INDEX_ARRAY_POINTER 0x8091
+#define GL_INDEX_ARRAY_STRIDE 0x8086
+#define GL_INDEX_ARRAY_TYPE 0x8085
+#define GL_INDEX_BITS 0x0D51
+#define GL_INDEX_CLEAR_VALUE 0x0C20
+#define GL_INDEX_LOGIC_OP 0x0BF1
+#define GL_INDEX_MODE 0x0C30
+#define GL_INDEX_OFFSET 0x0D13
+#define GL_INDEX_SHIFT 0x0D12
+#define GL_INDEX_WRITEMASK 0x0C21
+#define GL_INFO_LOG_LENGTH 0x8B84
+#define GL_INT 0x1404
+#define GL_INTENSITY 0x8049
+#define GL_INTENSITY12 0x804C
+#define GL_INTENSITY16 0x804D
+#define GL_INTENSITY4 0x804A
+#define GL_INTENSITY8 0x804B
+#define GL_INTERLEAVED_ATTRIBS 0x8C8C
+#define GL_INTERPOLATE 0x8575
+#define GL_INT_2_10_10_10_REV 0x8D9F
+#define GL_INT_SAMPLER_1D 0x8DC9
+#define GL_INT_SAMPLER_1D_ARRAY 0x8DCE
+#define GL_INT_SAMPLER_2D 0x8DCA
+#define GL_INT_SAMPLER_2D_ARRAY 0x8DCF
+#define GL_INT_SAMPLER_2D_MULTISAMPLE 0x9109
+#define GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910C
+#define GL_INT_SAMPLER_2D_RECT 0x8DCD
+#define GL_INT_SAMPLER_3D 0x8DCB
+#define GL_INT_SAMPLER_BUFFER 0x8DD0
+#define GL_INT_SAMPLER_CUBE 0x8DCC
+#define GL_INT_VEC2 0x8B53
+#define GL_INT_VEC3 0x8B54
+#define GL_INT_VEC4 0x8B55
+#define GL_INVALID_ENUM 0x0500
+#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506
+#define GL_INVALID_FRAMEBUFFER_OPERATION_EXT 0x0506
+#define GL_INVALID_INDEX 0xFFFFFFFF
+#define GL_INVALID_OPERATION 0x0502
+#define GL_INVALID_VALUE 0x0501
+#define GL_INVERT 0x150A
+#define GL_KEEP 0x1E00
+#define GL_LAST_VERTEX_CONVENTION 0x8E4E
+#define GL_LEFT 0x0406
+#define GL_LEQUAL 0x0203
+#define GL_LESS 0x0201
+#define GL_LIGHT0 0x4000
+#define GL_LIGHT1 0x4001
+#define GL_LIGHT2 0x4002
+#define GL_LIGHT3 0x4003
+#define GL_LIGHT4 0x4004
+#define GL_LIGHT5 0x4005
+#define GL_LIGHT6 0x4006
+#define GL_LIGHT7 0x4007
+#define GL_LIGHTING 0x0B50
+#define GL_LIGHTING_BIT 0x00000040
+#define GL_LIGHT_MODEL_AMBIENT 0x0B53
+#define GL_LIGHT_MODEL_COLOR_CONTROL 0x81F8
+#define GL_LIGHT_MODEL_LOCAL_VIEWER 0x0B51
+#define GL_LIGHT_MODEL_TWO_SIDE 0x0B52
+#define GL_LINE 0x1B01
+#define GL_LINEAR 0x2601
+#define GL_LINEAR_ATTENUATION 0x1208
+#define GL_LINEAR_MIPMAP_LINEAR 0x2703
+#define GL_LINEAR_MIPMAP_NEAREST 0x2701
+#define GL_LINES 0x0001
+#define GL_LINES_ADJACENCY 0x000A
+#define GL_LINE_BIT 0x00000004
+#define GL_LINE_LOOP 0x0002
+#define GL_LINE_RESET_TOKEN 0x0707
+#define GL_LINE_SMOOTH 0x0B20
+#define GL_LINE_SMOOTH_HINT 0x0C52
+#define GL_LINE_STIPPLE 0x0B24
+#define GL_LINE_STIPPLE_PATTERN 0x0B25
+#define GL_LINE_STIPPLE_REPEAT 0x0B26
+#define GL_LINE_STRIP 0x0003
+#define GL_LINE_STRIP_ADJACENCY 0x000B
+#define GL_LINE_TOKEN 0x0702
+#define GL_LINE_WIDTH 0x0B21
+#define GL_LINE_WIDTH_GRANULARITY 0x0B23
+#define GL_LINE_WIDTH_RANGE 0x0B22
+#define GL_LINK_STATUS 0x8B82
+#define GL_LIST_BASE 0x0B32
+#define GL_LIST_BIT 0x00020000
+#define GL_LIST_INDEX 0x0B33
+#define GL_LIST_MODE 0x0B30
+#define GL_LOAD 0x0101
+#define GL_LOGIC_OP 0x0BF1
+#define GL_LOGIC_OP_MODE 0x0BF0
+#define GL_LOWER_LEFT 0x8CA1
+#define GL_LUMINANCE 0x1909
+#define GL_LUMINANCE12 0x8041
+#define GL_LUMINANCE12_ALPHA12 0x8047
+#define GL_LUMINANCE12_ALPHA4 0x8046
+#define GL_LUMINANCE16 0x8042
+#define GL_LUMINANCE16_ALPHA16 0x8048
+#define GL_LUMINANCE4 0x803F
+#define GL_LUMINANCE4_ALPHA4 0x8043
+#define GL_LUMINANCE6_ALPHA2 0x8044
+#define GL_LUMINANCE8 0x8040
+#define GL_LUMINANCE8_ALPHA8 0x8045
+#define GL_LUMINANCE_ALPHA 0x190A
+#define GL_MAJOR_VERSION 0x821B
+#define GL_MAP1_COLOR_4 0x0D90
+#define GL_MAP1_GRID_DOMAIN 0x0DD0
+#define GL_MAP1_GRID_SEGMENTS 0x0DD1
+#define GL_MAP1_INDEX 0x0D91
+#define GL_MAP1_NORMAL 0x0D92
+#define GL_MAP1_TEXTURE_COORD_1 0x0D93
+#define GL_MAP1_TEXTURE_COORD_2 0x0D94
+#define GL_MAP1_TEXTURE_COORD_3 0x0D95
+#define GL_MAP1_TEXTURE_COORD_4 0x0D96
+#define GL_MAP1_VERTEX_3 0x0D97
+#define GL_MAP1_VERTEX_4 0x0D98
+#define GL_MAP2_COLOR_4 0x0DB0
+#define GL_MAP2_GRID_DOMAIN 0x0DD2
+#define GL_MAP2_GRID_SEGMENTS 0x0DD3
+#define GL_MAP2_INDEX 0x0DB1
+#define GL_MAP2_NORMAL 0x0DB2
+#define GL_MAP2_TEXTURE_COORD_1 0x0DB3
+#define GL_MAP2_TEXTURE_COORD_2 0x0DB4
+#define GL_MAP2_TEXTURE_COORD_3 0x0DB5
+#define GL_MAP2_TEXTURE_COORD_4 0x0DB6
+#define GL_MAP2_VERTEX_3 0x0DB7
+#define GL_MAP2_VERTEX_4 0x0DB8
+#define GL_MAP_COLOR 0x0D10
+#define GL_MAP_FLUSH_EXPLICIT_BIT 0x0010
+#define GL_MAP_INVALIDATE_BUFFER_BIT 0x0008
+#define GL_MAP_INVALIDATE_RANGE_BIT 0x0004
+#define GL_MAP_READ_BIT 0x0001
+#define GL_MAP_STENCIL 0x0D11
+#define GL_MAP_UNSYNCHRONIZED_BIT 0x0020
+#define GL_MAP_WRITE_BIT 0x0002
+#define GL_MATRIX_MODE 0x0BA0
+#define GL_MAX 0x8008
+#define GL_MAX_3D_TEXTURE_SIZE 0x8073
+#define GL_MAX_ARRAY_TEXTURE_LAYERS 0x88FF
+#define GL_MAX_ATTRIB_STACK_DEPTH 0x0D35
+#define GL_MAX_CLIENT_ATTRIB_STACK_DEPTH 0x0D3B
+#define GL_MAX_CLIP_DISTANCES 0x0D32
+#define GL_MAX_CLIP_PLANES 0x0D32
+#define GL_MAX_COLOR_ATTACHMENTS 0x8CDF
+#define GL_MAX_COLOR_ATTACHMENTS_EXT 0x8CDF
+#define GL_MAX_COLOR_TEXTURE_SAMPLES 0x910E
+#define GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS 0x8A33
+#define GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS 0x8A32
+#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D
+#define GL_MAX_COMBINED_UNIFORM_BLOCKS 0x8A2E
+#define GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS 0x8A31
+#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C
+#define GL_MAX_DEBUG_LOGGED_MESSAGES_ARB 0x9144
+#define GL_MAX_DEBUG_MESSAGE_LENGTH_ARB 0x9143
+#define GL_MAX_DEPTH_TEXTURE_SAMPLES 0x910F
+#define GL_MAX_DRAW_BUFFERS 0x8824
+#define GL_MAX_DUAL_SOURCE_DRAW_BUFFERS 0x88FC
+#define GL_MAX_ELEMENTS_INDICES 0x80E9
+#define GL_MAX_ELEMENTS_VERTICES 0x80E8
+#define GL_MAX_EVAL_ORDER 0x0D30
+#define GL_MAX_FRAGMENT_INPUT_COMPONENTS 0x9125
+#define GL_MAX_FRAGMENT_UNIFORM_BLOCKS 0x8A2D
+#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS 0x8B49
+#define GL_MAX_GEOMETRY_INPUT_COMPONENTS 0x9123
+#define GL_MAX_GEOMETRY_OUTPUT_COMPONENTS 0x9124
+#define GL_MAX_GEOMETRY_OUTPUT_VERTICES 0x8DE0
+#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS 0x8C29
+#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS 0x8DE1
+#define GL_MAX_GEOMETRY_UNIFORM_BLOCKS 0x8A2C
+#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS 0x8DDF
+#define GL_MAX_INTEGER_SAMPLES 0x9110
+#define GL_MAX_LIGHTS 0x0D31
+#define GL_MAX_LIST_NESTING 0x0B31
+#define GL_MAX_MODELVIEW_STACK_DEPTH 0x0D36
+#define GL_MAX_NAME_STACK_DEPTH 0x0D37
+#define GL_MAX_PIXEL_MAP_TABLE 0x0D34
+#define GL_MAX_PROGRAM_TEXEL_OFFSET 0x8905
+#define GL_MAX_PROJECTION_STACK_DEPTH 0x0D38
+#define GL_MAX_RECTANGLE_TEXTURE_SIZE 0x84F8
+#define GL_MAX_RENDERBUFFER_SIZE 0x84E8
+#define GL_MAX_RENDERBUFFER_SIZE_EXT 0x84E8
+#define GL_MAX_SAMPLES 0x8D57
+#define GL_MAX_SAMPLES_EXT 0x8D57
+#define GL_MAX_SAMPLE_MASK_WORDS 0x8E59
+#define GL_MAX_SERVER_WAIT_TIMEOUT 0x9111
+#define GL_MAX_TEXTURE_BUFFER_SIZE 0x8C2B
+#define GL_MAX_TEXTURE_COORDS 0x8871
+#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872
+#define GL_MAX_TEXTURE_LOD_BIAS 0x84FD
+#define GL_MAX_TEXTURE_SIZE 0x0D33
+#define GL_MAX_TEXTURE_STACK_DEPTH 0x0D39
+#define GL_MAX_TEXTURE_UNITS 0x84E2
+#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS 0x8C8A
+#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS 0x8C8B
+#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS 0x8C80
+#define GL_MAX_UNIFORM_BLOCK_SIZE 0x8A30
+#define GL_MAX_UNIFORM_BUFFER_BINDINGS 0x8A2F
+#define GL_MAX_VARYING_COMPONENTS 0x8B4B
+#define GL_MAX_VARYING_FLOATS 0x8B4B
+#define GL_MAX_VERTEX_ATTRIBS 0x8869
+#define GL_MAX_VERTEX_OUTPUT_COMPONENTS 0x9122
+#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C
+#define GL_MAX_VERTEX_UNIFORM_BLOCKS 0x8A2B
+#define GL_MAX_VERTEX_UNIFORM_COMPONENTS 0x8B4A
+#define GL_MAX_VIEWPORT_DIMS 0x0D3A
+#define GL_MAX_VIEWS_OVR 0x9631
+#define GL_MIN 0x8007
+#define GL_MINOR_VERSION 0x821C
+#define GL_MIN_PROGRAM_TEXEL_OFFSET 0x8904
+#define GL_MIRRORED_REPEAT 0x8370
+#define GL_MODELVIEW 0x1700
+#define GL_MODELVIEW_MATRIX 0x0BA6
+#define GL_MODELVIEW_STACK_DEPTH 0x0BA3
+#define GL_MODULATE 0x2100
+#define GL_MULT 0x0103
+#define GL_MULTISAMPLE 0x809D
+#define GL_MULTISAMPLE_BIT 0x20000000
+#define GL_N3F_V3F 0x2A25
+#define GL_NAME_STACK_DEPTH 0x0D70
+#define GL_NAND 0x150E
+#define GL_NEAREST 0x2600
+#define GL_NEAREST_MIPMAP_LINEAR 0x2702
+#define GL_NEAREST_MIPMAP_NEAREST 0x2700
+#define GL_NEVER 0x0200
+#define GL_NICEST 0x1102
+#define GL_NONE 0
+#define GL_NOOP 0x1505
+#define GL_NOR 0x1508
+#define GL_NORMALIZE 0x0BA1
+#define GL_NORMAL_ARRAY 0x8075
+#define GL_NORMAL_ARRAY_BUFFER_BINDING 0x8897
+#define GL_NORMAL_ARRAY_POINTER 0x808F
+#define GL_NORMAL_ARRAY_STRIDE 0x807F
+#define GL_NORMAL_ARRAY_TYPE 0x807E
+#define GL_NORMAL_MAP 0x8511
+#define GL_NOTEQUAL 0x0205
+#define GL_NO_ERROR 0
+#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2
+#define GL_NUM_EXTENSIONS 0x821D
+#define GL_OBJECT_LINEAR 0x2401
+#define GL_OBJECT_PLANE 0x2501
+#define GL_OBJECT_TYPE 0x9112
+#define GL_ONE 1
+#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004
+#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002
+#define GL_ONE_MINUS_DST_ALPHA 0x0305
+#define GL_ONE_MINUS_DST_COLOR 0x0307
+#define GL_ONE_MINUS_SRC1_ALPHA 0x88FB
+#define GL_ONE_MINUS_SRC1_COLOR 0x88FA
+#define GL_ONE_MINUS_SRC_ALPHA 0x0303
+#define GL_ONE_MINUS_SRC_COLOR 0x0301
+#define GL_OPERAND0_ALPHA 0x8598
+#define GL_OPERAND0_RGB 0x8590
+#define GL_OPERAND1_ALPHA 0x8599
+#define GL_OPERAND1_RGB 0x8591
+#define GL_OPERAND2_ALPHA 0x859A
+#define GL_OPERAND2_RGB 0x8592
+#define GL_OR 0x1507
+#define GL_ORDER 0x0A01
+#define GL_OR_INVERTED 0x150D
+#define GL_OR_REVERSE 0x150B
+#define GL_OUT_OF_MEMORY 0x0505
+#define GL_PACK_ALIGNMENT 0x0D05
+#define GL_PACK_IMAGE_HEIGHT 0x806C
+#define GL_PACK_LSB_FIRST 0x0D01
+#define GL_PACK_ROW_LENGTH 0x0D02
+#define GL_PACK_SKIP_IMAGES 0x806B
+#define GL_PACK_SKIP_PIXELS 0x0D04
+#define GL_PACK_SKIP_ROWS 0x0D03
+#define GL_PACK_SWAP_BYTES 0x0D00
+#define GL_PASS_THROUGH_TOKEN 0x0700
+#define GL_PERSPECTIVE_CORRECTION_HINT 0x0C50
+#define GL_PIXEL_MAP_A_TO_A 0x0C79
+#define GL_PIXEL_MAP_A_TO_A_SIZE 0x0CB9
+#define GL_PIXEL_MAP_B_TO_B 0x0C78
+#define GL_PIXEL_MAP_B_TO_B_SIZE 0x0CB8
+#define GL_PIXEL_MAP_G_TO_G 0x0C77
+#define GL_PIXEL_MAP_G_TO_G_SIZE 0x0CB7
+#define GL_PIXEL_MAP_I_TO_A 0x0C75
+#define GL_PIXEL_MAP_I_TO_A_SIZE 0x0CB5
+#define GL_PIXEL_MAP_I_TO_B 0x0C74
+#define GL_PIXEL_MAP_I_TO_B_SIZE 0x0CB4
+#define GL_PIXEL_MAP_I_TO_G 0x0C73
+#define GL_PIXEL_MAP_I_TO_G_SIZE 0x0CB3
+#define GL_PIXEL_MAP_I_TO_I 0x0C70
+#define GL_PIXEL_MAP_I_TO_I_SIZE 0x0CB0
+#define GL_PIXEL_MAP_I_TO_R 0x0C72
+#define GL_PIXEL_MAP_I_TO_R_SIZE 0x0CB2
+#define GL_PIXEL_MAP_R_TO_R 0x0C76
+#define GL_PIXEL_MAP_R_TO_R_SIZE 0x0CB6
+#define GL_PIXEL_MAP_S_TO_S 0x0C71
+#define GL_PIXEL_MAP_S_TO_S_SIZE 0x0CB1
+#define GL_PIXEL_MODE_BIT 0x00000020
+#define GL_PIXEL_PACK_BUFFER 0x88EB
+#define GL_PIXEL_PACK_BUFFER_BINDING 0x88ED
+#define GL_PIXEL_UNPACK_BUFFER 0x88EC
+#define GL_PIXEL_UNPACK_BUFFER_BINDING 0x88EF
+#define GL_POINT 0x1B00
+#define GL_POINTS 0x0000
+#define GL_POINT_BIT 0x00000002
+#define GL_POINT_DISTANCE_ATTENUATION 0x8129
+#define GL_POINT_FADE_THRESHOLD_SIZE 0x8128
+#define GL_POINT_SIZE 0x0B11
+#define GL_POINT_SIZE_GRANULARITY 0x0B13
+#define GL_POINT_SIZE_MAX 0x8127
+#define GL_POINT_SIZE_MIN 0x8126
+#define GL_POINT_SIZE_RANGE 0x0B12
+#define GL_POINT_SMOOTH 0x0B10
+#define GL_POINT_SMOOTH_HINT 0x0C51
+#define GL_POINT_SPRITE 0x8861
+#define GL_POINT_SPRITE_COORD_ORIGIN 0x8CA0
+#define GL_POINT_TOKEN 0x0701
+#define GL_POLYGON 0x0009
+#define GL_POLYGON_BIT 0x00000008
+#define GL_POLYGON_MODE 0x0B40
+#define GL_POLYGON_OFFSET_FACTOR 0x8038
+#define GL_POLYGON_OFFSET_FILL 0x8037
+#define GL_POLYGON_OFFSET_LINE 0x2A02
+#define GL_POLYGON_OFFSET_POINT 0x2A01
+#define GL_POLYGON_OFFSET_UNITS 0x2A00
+#define GL_POLYGON_SMOOTH 0x0B41
+#define GL_POLYGON_SMOOTH_HINT 0x0C53
+#define GL_POLYGON_STIPPLE 0x0B42
+#define GL_POLYGON_STIPPLE_BIT 0x00000010
+#define GL_POLYGON_TOKEN 0x0703
+#define GL_POSITION 0x1203
+#define GL_PREVIOUS 0x8578
+#define GL_PRIMARY_COLOR 0x8577
+#define GL_PRIMITIVES_GENERATED 0x8C87
+#define GL_PRIMITIVE_RESTART 0x8F9D
+#define GL_PRIMITIVE_RESTART_INDEX 0x8F9E
+#define GL_PROGRAM_POINT_SIZE 0x8642
+#define GL_PROJECTION 0x1701
+#define GL_PROJECTION_MATRIX 0x0BA7
+#define GL_PROJECTION_STACK_DEPTH 0x0BA4
+#define GL_PROVOKING_VERTEX 0x8E4F
+#define GL_PROXY_TEXTURE_1D 0x8063
+#define GL_PROXY_TEXTURE_1D_ARRAY 0x8C19
+#define GL_PROXY_TEXTURE_2D 0x8064
+#define GL_PROXY_TEXTURE_2D_ARRAY 0x8C1B
+#define GL_PROXY_TEXTURE_2D_MULTISAMPLE 0x9101
+#define GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9103
+#define GL_PROXY_TEXTURE_3D 0x8070
+#define GL_PROXY_TEXTURE_CUBE_MAP 0x851B
+#define GL_PROXY_TEXTURE_RECTANGLE 0x84F7
+#define GL_Q 0x2003
+#define GL_QUADRATIC_ATTENUATION 0x1209
+#define GL_QUADS 0x0007
+#define GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION 0x8E4C
+#define GL_QUAD_STRIP 0x0008
+#define GL_QUERY_BY_REGION_NO_WAIT 0x8E16
+#define GL_QUERY_BY_REGION_WAIT 0x8E15
+#define GL_QUERY_COUNTER_BITS 0x8864
+#define GL_QUERY_NO_WAIT 0x8E14
+#define GL_QUERY_RESULT 0x8866
+#define GL_QUERY_RESULT_AVAILABLE 0x8867
+#define GL_QUERY_WAIT 0x8E13
+#define GL_R 0x2002
+#define GL_R11F_G11F_B10F 0x8C3A
+#define GL_R16 0x822A
+#define GL_R16F 0x822D
+#define GL_R16I 0x8233
+#define GL_R16UI 0x8234
+#define GL_R16_SNORM 0x8F98
+#define GL_R32F 0x822E
+#define GL_R32I 0x8235
+#define GL_R32UI 0x8236
+#define GL_R3_G3_B2 0x2A10
+#define GL_R8 0x8229
+#define GL_R8I 0x8231
+#define GL_R8UI 0x8232
+#define GL_R8_SNORM 0x8F94
+#define GL_RASTERIZER_DISCARD 0x8C89
+#define GL_READ_BUFFER 0x0C02
+#define GL_READ_FRAMEBUFFER 0x8CA8
+#define GL_READ_FRAMEBUFFER_BINDING 0x8CAA
+#define GL_READ_FRAMEBUFFER_BINDING_EXT 0x8CAA
+#define GL_READ_FRAMEBUFFER_EXT 0x8CA8
+#define GL_READ_ONLY 0x88B8
+#define GL_READ_WRITE 0x88BA
+#define GL_RED 0x1903
+#define GL_RED_BIAS 0x0D15
+#define GL_RED_BITS 0x0D52
+#define GL_RED_INTEGER 0x8D94
+#define GL_RED_SCALE 0x0D14
+#define GL_REFLECTION_MAP 0x8512
+#define GL_RENDER 0x1C00
+#define GL_RENDERBUFFER 0x8D41
+#define GL_RENDERBUFFER_ALPHA_SIZE 0x8D53
+#define GL_RENDERBUFFER_ALPHA_SIZE_EXT 0x8D53
+#define GL_RENDERBUFFER_BINDING 0x8CA7
+#define GL_RENDERBUFFER_BINDING_EXT 0x8CA7
+#define GL_RENDERBUFFER_BLUE_SIZE 0x8D52
+#define GL_RENDERBUFFER_BLUE_SIZE_EXT 0x8D52
+#define GL_RENDERBUFFER_DEPTH_SIZE 0x8D54
+#define GL_RENDERBUFFER_DEPTH_SIZE_EXT 0x8D54
+#define GL_RENDERBUFFER_EXT 0x8D41
+#define GL_RENDERBUFFER_GREEN_SIZE 0x8D51
+#define GL_RENDERBUFFER_GREEN_SIZE_EXT 0x8D51
+#define GL_RENDERBUFFER_HEIGHT 0x8D43
+#define GL_RENDERBUFFER_HEIGHT_EXT 0x8D43
+#define GL_RENDERBUFFER_INTERNAL_FORMAT 0x8D44
+#define GL_RENDERBUFFER_INTERNAL_FORMAT_EXT 0x8D44
+#define GL_RENDERBUFFER_RED_SIZE 0x8D50
+#define GL_RENDERBUFFER_RED_SIZE_EXT 0x8D50
+#define GL_RENDERBUFFER_SAMPLES 0x8CAB
+#define GL_RENDERBUFFER_SAMPLES_EXT 0x8CAB
+#define GL_RENDERBUFFER_STENCIL_SIZE 0x8D55
+#define GL_RENDERBUFFER_STENCIL_SIZE_EXT 0x8D55
+#define GL_RENDERBUFFER_WIDTH 0x8D42
+#define GL_RENDERBUFFER_WIDTH_EXT 0x8D42
+#define GL_RENDERER 0x1F01
+#define GL_RENDER_MODE 0x0C40
+#define GL_REPEAT 0x2901
+#define GL_REPLACE 0x1E01
+#define GL_RESCALE_NORMAL 0x803A
+#define GL_RETURN 0x0102
+#define GL_RG 0x8227
+#define GL_RG16 0x822C
+#define GL_RG16F 0x822F
+#define GL_RG16I 0x8239
+#define GL_RG16UI 0x823A
+#define GL_RG16_SNORM 0x8F99
+#define GL_RG32F 0x8230
+#define GL_RG32I 0x823B
+#define GL_RG32UI 0x823C
+#define GL_RG8 0x822B
+#define GL_RG8I 0x8237
+#define GL_RG8UI 0x8238
+#define GL_RG8_SNORM 0x8F95
+#define GL_RGB 0x1907
+#define GL_RGB10 0x8052
+#define GL_RGB10_A2 0x8059
+#define GL_RGB10_A2UI 0x906F
+#define GL_RGB12 0x8053
+#define GL_RGB16 0x8054
+#define GL_RGB16F 0x881B
+#define GL_RGB16I 0x8D89
+#define GL_RGB16UI 0x8D77
+#define GL_RGB16_SNORM 0x8F9A
+#define GL_RGB32F 0x8815
+#define GL_RGB32I 0x8D83
+#define GL_RGB32UI 0x8D71
+#define GL_RGB4 0x804F
+#define GL_RGB5 0x8050
+#define GL_RGB5_A1 0x8057
+#define GL_RGB8 0x8051
+#define GL_RGB8I 0x8D8F
+#define GL_RGB8UI 0x8D7D
+#define GL_RGB8_SNORM 0x8F96
+#define GL_RGB9_E5 0x8C3D
+#define GL_RGBA 0x1908
+#define GL_RGBA12 0x805A
+#define GL_RGBA16 0x805B
+#define GL_RGBA16F 0x881A
+#define GL_RGBA16I 0x8D88
+#define GL_RGBA16UI 0x8D76
+#define GL_RGBA16_SNORM 0x8F9B
+#define GL_RGBA2 0x8055
+#define GL_RGBA32F 0x8814
+#define GL_RGBA32I 0x8D82
+#define GL_RGBA32UI 0x8D70
+#define GL_RGBA4 0x8056
+#define GL_RGBA8 0x8058
+#define GL_RGBA8I 0x8D8E
+#define GL_RGBA8UI 0x8D7C
+#define GL_RGBA8_SNORM 0x8F97
+#define GL_RGBA_INTEGER 0x8D99
+#define GL_RGBA_MODE 0x0C31
+#define GL_RGB_INTEGER 0x8D98
+#define GL_RGB_SCALE 0x8573
+#define GL_RG_INTEGER 0x8228
+#define GL_RIGHT 0x0407
+#define GL_S 0x2000
+#define GL_SAMPLER_1D 0x8B5D
+#define GL_SAMPLER_1D_ARRAY 0x8DC0
+#define GL_SAMPLER_1D_ARRAY_SHADOW 0x8DC3
+#define GL_SAMPLER_1D_SHADOW 0x8B61
+#define GL_SAMPLER_2D 0x8B5E
+#define GL_SAMPLER_2D_ARRAY 0x8DC1
+#define GL_SAMPLER_2D_ARRAY_SHADOW 0x8DC4
+#define GL_SAMPLER_2D_MULTISAMPLE 0x9108
+#define GL_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910B
+#define GL_SAMPLER_2D_RECT 0x8B63
+#define GL_SAMPLER_2D_RECT_SHADOW 0x8B64
+#define GL_SAMPLER_2D_SHADOW 0x8B62
+#define GL_SAMPLER_3D 0x8B5F
+#define GL_SAMPLER_BINDING 0x8919
+#define GL_SAMPLER_BUFFER 0x8DC2
+#define GL_SAMPLER_CUBE 0x8B60
+#define GL_SAMPLER_CUBE_SHADOW 0x8DC5
+#define GL_SAMPLES 0x80A9
+#define GL_SAMPLES_PASSED 0x8914
+#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E
+#define GL_SAMPLE_ALPHA_TO_ONE 0x809F
+#define GL_SAMPLE_BUFFERS 0x80A8
+#define GL_SAMPLE_COVERAGE 0x80A0
+#define GL_SAMPLE_COVERAGE_INVERT 0x80AB
+#define GL_SAMPLE_COVERAGE_VALUE 0x80AA
+#define GL_SAMPLE_MASK 0x8E51
+#define GL_SAMPLE_MASK_VALUE 0x8E52
+#define GL_SAMPLE_POSITION 0x8E50
+#define GL_SCISSOR_BIT 0x00080000
+#define GL_SCISSOR_BOX 0x0C10
+#define GL_SCISSOR_TEST 0x0C11
+#define GL_SECONDARY_COLOR_ARRAY 0x845E
+#define GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING 0x889C
+#define GL_SECONDARY_COLOR_ARRAY_POINTER 0x845D
+#define GL_SECONDARY_COLOR_ARRAY_SIZE 0x845A
+#define GL_SECONDARY_COLOR_ARRAY_STRIDE 0x845C
+#define GL_SECONDARY_COLOR_ARRAY_TYPE 0x845B
+#define GL_SELECT 0x1C02
+#define GL_SELECTION_BUFFER_POINTER 0x0DF3
+#define GL_SELECTION_BUFFER_SIZE 0x0DF4
+#define GL_SEPARATE_ATTRIBS 0x8C8D
+#define GL_SEPARATE_SPECULAR_COLOR 0x81FA
+#define GL_SET 0x150F
+#define GL_SHADER_SOURCE_LENGTH 0x8B88
+#define GL_SHADER_TYPE 0x8B4F
+#define GL_SHADE_MODEL 0x0B54
+#define GL_SHADING_LANGUAGE_VERSION 0x8B8C
+#define GL_SHININESS 0x1601
+#define GL_SHORT 0x1402
+#define GL_SIGNALED 0x9119
+#define GL_SIGNED_NORMALIZED 0x8F9C
+#define GL_SINGLE_COLOR 0x81F9
+#define GL_SLUMINANCE 0x8C46
+#define GL_SLUMINANCE8 0x8C47
+#define GL_SLUMINANCE8_ALPHA8 0x8C45
+#define GL_SLUMINANCE_ALPHA 0x8C44
+#define GL_SMOOTH 0x1D01
+#define GL_SMOOTH_LINE_WIDTH_GRANULARITY 0x0B23
+#define GL_SMOOTH_LINE_WIDTH_RANGE 0x0B22
+#define GL_SMOOTH_POINT_SIZE_GRANULARITY 0x0B13
+#define GL_SMOOTH_POINT_SIZE_RANGE 0x0B12
+#define GL_SOURCE0_ALPHA 0x8588
+#define GL_SOURCE0_RGB 0x8580
+#define GL_SOURCE1_ALPHA 0x8589
+#define GL_SOURCE1_RGB 0x8581
+#define GL_SOURCE2_ALPHA 0x858A
+#define GL_SOURCE2_RGB 0x8582
+#define GL_SPECULAR 0x1202
+#define GL_SPHERE_MAP 0x2402
+#define GL_SPOT_CUTOFF 0x1206
+#define GL_SPOT_DIRECTION 0x1204
+#define GL_SPOT_EXPONENT 0x1205
+#define GL_SRC0_ALPHA 0x8588
+#define GL_SRC0_RGB 0x8580
+#define GL_SRC1_ALPHA 0x8589
+#define GL_SRC1_COLOR 0x88F9
+#define GL_SRC1_RGB 0x8581
+#define GL_SRC2_ALPHA 0x858A
+#define GL_SRC2_RGB 0x8582
+#define GL_SRC_ALPHA 0x0302
+#define GL_SRC_ALPHA_SATURATE 0x0308
+#define GL_SRC_COLOR 0x0300
+#define GL_SRGB 0x8C40
+#define GL_SRGB8 0x8C41
+#define GL_SRGB8_ALPHA8 0x8C43
+#define GL_SRGB_ALPHA 0x8C42
+#define GL_STACK_OVERFLOW 0x0503
+#define GL_STACK_UNDERFLOW 0x0504
+#define GL_STATIC_COPY 0x88E6
+#define GL_STATIC_DRAW 0x88E4
+#define GL_STATIC_READ 0x88E5
+#define GL_STENCIL 0x1802
+#define GL_STENCIL_ATTACHMENT 0x8D20
+#define GL_STENCIL_ATTACHMENT_EXT 0x8D20
+#define GL_STENCIL_BACK_FAIL 0x8801
+#define GL_STENCIL_BACK_FUNC 0x8800
+#define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802
+#define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803
+#define GL_STENCIL_BACK_REF 0x8CA3
+#define GL_STENCIL_BACK_VALUE_MASK 0x8CA4
+#define GL_STENCIL_BACK_WRITEMASK 0x8CA5
+#define GL_STENCIL_BITS 0x0D57
+#define GL_STENCIL_BUFFER_BIT 0x00000400
+#define GL_STENCIL_CLEAR_VALUE 0x0B91
+#define GL_STENCIL_FAIL 0x0B94
+#define GL_STENCIL_FUNC 0x0B92
+#define GL_STENCIL_INDEX 0x1901
+#define GL_STENCIL_INDEX1 0x8D46
+#define GL_STENCIL_INDEX16 0x8D49
+#define GL_STENCIL_INDEX16_EXT 0x8D49
+#define GL_STENCIL_INDEX1_EXT 0x8D46
+#define GL_STENCIL_INDEX4 0x8D47
+#define GL_STENCIL_INDEX4_EXT 0x8D47
+#define GL_STENCIL_INDEX8 0x8D48
+#define GL_STENCIL_INDEX8_EXT 0x8D48
+#define GL_STENCIL_PASS_DEPTH_FAIL 0x0B95
+#define GL_STENCIL_PASS_DEPTH_PASS 0x0B96
+#define GL_STENCIL_REF 0x0B97
+#define GL_STENCIL_TEST 0x0B90
+#define GL_STENCIL_VALUE_MASK 0x0B93
+#define GL_STENCIL_WRITEMASK 0x0B98
+#define GL_STEREO 0x0C33
+#define GL_STREAM_COPY 0x88E2
+#define GL_STREAM_DRAW 0x88E0
+#define GL_STREAM_READ 0x88E1
+#define GL_SUBPIXEL_BITS 0x0D50
+#define GL_SUBTRACT 0x84E7
+#define GL_SYNC_CONDITION 0x9113
+#define GL_SYNC_FENCE 0x9116
+#define GL_SYNC_FLAGS 0x9115
+#define GL_SYNC_FLUSH_COMMANDS_BIT 0x00000001
+#define GL_SYNC_GPU_COMMANDS_COMPLETE 0x9117
+#define GL_SYNC_STATUS 0x9114
+#define GL_T 0x2001
+#define GL_T2F_C3F_V3F 0x2A2A
+#define GL_T2F_C4F_N3F_V3F 0x2A2C
+#define GL_T2F_C4UB_V3F 0x2A29
+#define GL_T2F_N3F_V3F 0x2A2B
+#define GL_T2F_V3F 0x2A27
+#define GL_T4F_C4F_N3F_V4F 0x2A2D
+#define GL_T4F_V4F 0x2A28
+#define GL_TEXTURE 0x1702
+#define GL_TEXTURE0 0x84C0
+#define GL_TEXTURE1 0x84C1
+#define GL_TEXTURE10 0x84CA
+#define GL_TEXTURE11 0x84CB
+#define GL_TEXTURE12 0x84CC
+#define GL_TEXTURE13 0x84CD
+#define GL_TEXTURE14 0x84CE
+#define GL_TEXTURE15 0x84CF
+#define GL_TEXTURE16 0x84D0
+#define GL_TEXTURE17 0x84D1
+#define GL_TEXTURE18 0x84D2
+#define GL_TEXTURE19 0x84D3
+#define GL_TEXTURE2 0x84C2
+#define GL_TEXTURE20 0x84D4
+#define GL_TEXTURE21 0x84D5
+#define GL_TEXTURE22 0x84D6
+#define GL_TEXTURE23 0x84D7
+#define GL_TEXTURE24 0x84D8
+#define GL_TEXTURE25 0x84D9
+#define GL_TEXTURE26 0x84DA
+#define GL_TEXTURE27 0x84DB
+#define GL_TEXTURE28 0x84DC
+#define GL_TEXTURE29 0x84DD
+#define GL_TEXTURE3 0x84C3
+#define GL_TEXTURE30 0x84DE
+#define GL_TEXTURE31 0x84DF
+#define GL_TEXTURE4 0x84C4
+#define GL_TEXTURE5 0x84C5
+#define GL_TEXTURE6 0x84C6
+#define GL_TEXTURE7 0x84C7
+#define GL_TEXTURE8 0x84C8
+#define GL_TEXTURE9 0x84C9
+#define GL_TEXTURE_1D 0x0DE0
+#define GL_TEXTURE_1D_ARRAY 0x8C18
+#define GL_TEXTURE_2D 0x0DE1
+#define GL_TEXTURE_2D_ARRAY 0x8C1A
+#define GL_TEXTURE_2D_MULTISAMPLE 0x9100
+#define GL_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9102
+#define GL_TEXTURE_3D 0x806F
+#define GL_TEXTURE_ALPHA_SIZE 0x805F
+#define GL_TEXTURE_ALPHA_TYPE 0x8C13
+#define GL_TEXTURE_BASE_LEVEL 0x813C
+#define GL_TEXTURE_BINDING_1D 0x8068
+#define GL_TEXTURE_BINDING_1D_ARRAY 0x8C1C
+#define GL_TEXTURE_BINDING_2D 0x8069
+#define GL_TEXTURE_BINDING_2D_ARRAY 0x8C1D
+#define GL_TEXTURE_BINDING_2D_MULTISAMPLE 0x9104
+#define GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY 0x9105
+#define GL_TEXTURE_BINDING_3D 0x806A
+#define GL_TEXTURE_BINDING_BUFFER 0x8C2C
+#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514
+#define GL_TEXTURE_BINDING_RECTANGLE 0x84F6
+#define GL_TEXTURE_BIT 0x00040000
+#define GL_TEXTURE_BLUE_SIZE 0x805E
+#define GL_TEXTURE_BLUE_TYPE 0x8C12
+#define GL_TEXTURE_BORDER 0x1005
+#define GL_TEXTURE_BORDER_COLOR 0x1004
+#define GL_TEXTURE_BUFFER 0x8C2A
+#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING 0x8C2D
+#define GL_TEXTURE_COMPARE_FUNC 0x884D
+#define GL_TEXTURE_COMPARE_MODE 0x884C
+#define GL_TEXTURE_COMPONENTS 0x1003
+#define GL_TEXTURE_COMPRESSED 0x86A1
+#define GL_TEXTURE_COMPRESSED_IMAGE_SIZE 0x86A0
+#define GL_TEXTURE_COMPRESSION_HINT 0x84EF
+#define GL_TEXTURE_COORD_ARRAY 0x8078
+#define GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING 0x889A
+#define GL_TEXTURE_COORD_ARRAY_POINTER 0x8092
+#define GL_TEXTURE_COORD_ARRAY_SIZE 0x8088
+#define GL_TEXTURE_COORD_ARRAY_STRIDE 0x808A
+#define GL_TEXTURE_COORD_ARRAY_TYPE 0x8089
+#define GL_TEXTURE_CUBE_MAP 0x8513
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519
+#define GL_TEXTURE_CUBE_MAP_SEAMLESS 0x884F
+#define GL_TEXTURE_DEPTH 0x8071
+#define GL_TEXTURE_DEPTH_SIZE 0x884A
+#define GL_TEXTURE_DEPTH_TYPE 0x8C16
+#define GL_TEXTURE_ENV 0x2300
+#define GL_TEXTURE_ENV_COLOR 0x2201
+#define GL_TEXTURE_ENV_MODE 0x2200
+#define GL_TEXTURE_FILTER_CONTROL 0x8500
+#define GL_TEXTURE_FIXED_SAMPLE_LOCATIONS 0x9107
+#define GL_TEXTURE_GEN_MODE 0x2500
+#define GL_TEXTURE_GEN_Q 0x0C63
+#define GL_TEXTURE_GEN_R 0x0C62
+#define GL_TEXTURE_GEN_S 0x0C60
+#define GL_TEXTURE_GEN_T 0x0C61
+#define GL_TEXTURE_GREEN_SIZE 0x805D
+#define GL_TEXTURE_GREEN_TYPE 0x8C11
+#define GL_TEXTURE_HEIGHT 0x1001
+#define GL_TEXTURE_INTENSITY_SIZE 0x8061
+#define GL_TEXTURE_INTENSITY_TYPE 0x8C15
+#define GL_TEXTURE_INTERNAL_FORMAT 0x1003
+#define GL_TEXTURE_LOD_BIAS 0x8501
+#define GL_TEXTURE_LUMINANCE_SIZE 0x8060
+#define GL_TEXTURE_LUMINANCE_TYPE 0x8C14
+#define GL_TEXTURE_MAG_FILTER 0x2800
+#define GL_TEXTURE_MATRIX 0x0BA8
+#define GL_TEXTURE_MAX_LEVEL 0x813D
+#define GL_TEXTURE_MAX_LOD 0x813B
+#define GL_TEXTURE_MIN_FILTER 0x2801
+#define GL_TEXTURE_MIN_LOD 0x813A
+#define GL_TEXTURE_PRIORITY 0x8066
+#define GL_TEXTURE_RECTANGLE 0x84F5
+#define GL_TEXTURE_RED_SIZE 0x805C
+#define GL_TEXTURE_RED_TYPE 0x8C10
+#define GL_TEXTURE_RESIDENT 0x8067
+#define GL_TEXTURE_SAMPLES 0x9106
+#define GL_TEXTURE_SHARED_SIZE 0x8C3F
+#define GL_TEXTURE_STACK_DEPTH 0x0BA5
+#define GL_TEXTURE_STENCIL_SIZE 0x88F1
+#define GL_TEXTURE_SWIZZLE_A 0x8E45
+#define GL_TEXTURE_SWIZZLE_B 0x8E44
+#define GL_TEXTURE_SWIZZLE_G 0x8E43
+#define GL_TEXTURE_SWIZZLE_R 0x8E42
+#define GL_TEXTURE_SWIZZLE_RGBA 0x8E46
+#define GL_TEXTURE_WIDTH 0x1000
+#define GL_TEXTURE_WRAP_R 0x8072
+#define GL_TEXTURE_WRAP_S 0x2802
+#define GL_TEXTURE_WRAP_T 0x2803
+#define GL_TIMEOUT_EXPIRED 0x911B
+#define GL_TIMEOUT_IGNORED 0xFFFFFFFFFFFFFFFF
+#define GL_TIMESTAMP 0x8E28
+#define GL_TIME_ELAPSED 0x88BF
+#define GL_TRANSFORM_BIT 0x00001000
+#define GL_TRANSFORM_FEEDBACK_BUFFER 0x8C8E
+#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING 0x8C8F
+#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE 0x8C7F
+#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE 0x8C85
+#define GL_TRANSFORM_FEEDBACK_BUFFER_START 0x8C84
+#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN 0x8C88
+#define GL_TRANSFORM_FEEDBACK_VARYINGS 0x8C83
+#define GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH 0x8C76
+#define GL_TRANSPOSE_COLOR_MATRIX 0x84E6
+#define GL_TRANSPOSE_MODELVIEW_MATRIX 0x84E3
+#define GL_TRANSPOSE_PROJECTION_MATRIX 0x84E4
+#define GL_TRANSPOSE_TEXTURE_MATRIX 0x84E5
+#define GL_TRIANGLES 0x0004
+#define GL_TRIANGLES_ADJACENCY 0x000C
+#define GL_TRIANGLE_FAN 0x0006
+#define GL_TRIANGLE_STRIP 0x0005
+#define GL_TRIANGLE_STRIP_ADJACENCY 0x000D
+#define GL_TRUE 1
+#define GL_UNIFORM_ARRAY_STRIDE 0x8A3C
+#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS 0x8A42
+#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES 0x8A43
+#define GL_UNIFORM_BLOCK_BINDING 0x8A3F
+#define GL_UNIFORM_BLOCK_DATA_SIZE 0x8A40
+#define GL_UNIFORM_BLOCK_INDEX 0x8A3A
+#define GL_UNIFORM_BLOCK_NAME_LENGTH 0x8A41
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER 0x8A46
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER 0x8A45
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER 0x8A44
+#define GL_UNIFORM_BUFFER 0x8A11
+#define GL_UNIFORM_BUFFER_BINDING 0x8A28
+#define GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT 0x8A34
+#define GL_UNIFORM_BUFFER_SIZE 0x8A2A
+#define GL_UNIFORM_BUFFER_START 0x8A29
+#define GL_UNIFORM_IS_ROW_MAJOR 0x8A3E
+#define GL_UNIFORM_MATRIX_STRIDE 0x8A3D
+#define GL_UNIFORM_NAME_LENGTH 0x8A39
+#define GL_UNIFORM_OFFSET 0x8A3B
+#define GL_UNIFORM_SIZE 0x8A38
+#define GL_UNIFORM_TYPE 0x8A37
+#define GL_UNPACK_ALIGNMENT 0x0CF5
+#define GL_UNPACK_IMAGE_HEIGHT 0x806E
+#define GL_UNPACK_LSB_FIRST 0x0CF1
+#define GL_UNPACK_ROW_LENGTH 0x0CF2
+#define GL_UNPACK_SKIP_IMAGES 0x806D
+#define GL_UNPACK_SKIP_PIXELS 0x0CF4
+#define GL_UNPACK_SKIP_ROWS 0x0CF3
+#define GL_UNPACK_SWAP_BYTES 0x0CF0
+#define GL_UNSIGNALED 0x9118
+#define GL_UNSIGNED_BYTE 0x1401
+#define GL_UNSIGNED_BYTE_2_3_3_REV 0x8362
+#define GL_UNSIGNED_BYTE_3_3_2 0x8032
+#define GL_UNSIGNED_INT 0x1405
+#define GL_UNSIGNED_INT_10F_11F_11F_REV 0x8C3B
+#define GL_UNSIGNED_INT_10_10_10_2 0x8036
+#define GL_UNSIGNED_INT_24_8 0x84FA
+#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368
+#define GL_UNSIGNED_INT_5_9_9_9_REV 0x8C3E
+#define GL_UNSIGNED_INT_8_8_8_8 0x8035
+#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367
+#define GL_UNSIGNED_INT_SAMPLER_1D 0x8DD1
+#define GL_UNSIGNED_INT_SAMPLER_1D_ARRAY 0x8DD6
+#define GL_UNSIGNED_INT_SAMPLER_2D 0x8DD2
+#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY 0x8DD7
+#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE 0x910A
+#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910D
+#define GL_UNSIGNED_INT_SAMPLER_2D_RECT 0x8DD5
+#define GL_UNSIGNED_INT_SAMPLER_3D 0x8DD3
+#define GL_UNSIGNED_INT_SAMPLER_BUFFER 0x8DD8
+#define GL_UNSIGNED_INT_SAMPLER_CUBE 0x8DD4
+#define GL_UNSIGNED_INT_VEC2 0x8DC6
+#define GL_UNSIGNED_INT_VEC3 0x8DC7
+#define GL_UNSIGNED_INT_VEC4 0x8DC8
+#define GL_UNSIGNED_NORMALIZED 0x8C17
+#define GL_UNSIGNED_SHORT 0x1403
+#define GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366
+#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033
+#define GL_UNSIGNED_SHORT_4_4_4_4_REV 0x8365
+#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034
+#define GL_UNSIGNED_SHORT_5_6_5 0x8363
+#define GL_UNSIGNED_SHORT_5_6_5_REV 0x8364
+#define GL_UPPER_LEFT 0x8CA2
+#define GL_V2F 0x2A20
+#define GL_V3F 0x2A21
+#define GL_VALIDATE_STATUS 0x8B83
+#define GL_VENDOR 0x1F00
+#define GL_VERSION 0x1F02
+#define GL_VERTEX_ARRAY 0x8074
+#define GL_VERTEX_ARRAY_BINDING 0x85B5
+#define GL_VERTEX_ARRAY_BUFFER_BINDING 0x8896
+#define GL_VERTEX_ARRAY_POINTER 0x808E
+#define GL_VERTEX_ARRAY_SIZE 0x807A
+#define GL_VERTEX_ARRAY_STRIDE 0x807C
+#define GL_VERTEX_ARRAY_TYPE 0x807B
+#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F
+#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR 0x88FE
+#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622
+#define GL_VERTEX_ATTRIB_ARRAY_INTEGER 0x88FD
+#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A
+#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645
+#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623
+#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624
+#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625
+#define GL_VERTEX_PROGRAM_POINT_SIZE 0x8642
+#define GL_VERTEX_PROGRAM_TWO_SIDE 0x8643
+#define GL_VERTEX_SHADER 0x8B31
+#define GL_VIEWPORT 0x0BA2
+#define GL_VIEWPORT_BIT 0x00000800
+#define GL_WAIT_FAILED 0x911D
+#define GL_WEIGHT_ARRAY_BUFFER_BINDING 0x889E
+#define GL_WRITE_ONLY 0x88B9
+#define GL_XOR 0x1506
+#define GL_ZERO 0
+#define GL_ZOOM_X 0x0D16
+#define GL_ZOOM_Y 0x0D17
+
+
+#include <KHR/khrplatform.h>
+typedef unsigned int GLenum;
+typedef unsigned char GLboolean;
+typedef unsigned int GLbitfield;
+typedef void GLvoid;
+typedef khronos_int8_t GLbyte;
+typedef khronos_uint8_t GLubyte;
+typedef khronos_int16_t GLshort;
+typedef khronos_uint16_t GLushort;
+typedef int GLint;
+typedef unsigned int GLuint;
+typedef khronos_int32_t GLclampx;
+typedef int GLsizei;
+typedef khronos_float_t GLfloat;
+typedef khronos_float_t GLclampf;
+typedef double GLdouble;
+typedef double GLclampd;
+typedef void *GLeglClientBufferEXT;
+typedef void *GLeglImageOES;
+typedef char GLchar;
+typedef char GLcharARB;
+#ifdef __APPLE__
+typedef void *GLhandleARB;
+#else
+typedef unsigned int GLhandleARB;
+#endif
+typedef khronos_uint16_t GLhalf;
+typedef khronos_uint16_t GLhalfARB;
+typedef khronos_int32_t GLfixed;
+#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ > 1060)
+typedef khronos_intptr_t GLintptr;
+#else
+typedef khronos_intptr_t GLintptr;
+#endif
+#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ > 1060)
+typedef khronos_intptr_t GLintptrARB;
+#else
+typedef khronos_intptr_t GLintptrARB;
+#endif
+#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ > 1060)
+typedef khronos_ssize_t GLsizeiptr;
+#else
+typedef khronos_ssize_t GLsizeiptr;
+#endif
+#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ > 1060)
+typedef khronos_ssize_t GLsizeiptrARB;
+#else
+typedef khronos_ssize_t GLsizeiptrARB;
+#endif
+typedef khronos_int64_t GLint64;
+typedef khronos_int64_t GLint64EXT;
+typedef khronos_uint64_t GLuint64;
+typedef khronos_uint64_t GLuint64EXT;
+typedef struct __GLsync *GLsync;
+struct _cl_context;
+struct _cl_event;
+typedef void (GLAD_API_PTR *GLDEBUGPROC)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam);
+typedef void (GLAD_API_PTR *GLDEBUGPROCARB)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam);
+typedef void (GLAD_API_PTR *GLDEBUGPROCKHR)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam);
+typedef void (GLAD_API_PTR *GLDEBUGPROCAMD)(GLuint id,GLenum category,GLenum severity,GLsizei length,const GLchar *message,void *userParam);
+typedef unsigned short GLhalfNV;
+typedef GLintptr GLvdpauSurfaceNV;
+typedef void (GLAD_API_PTR *GLVULKANPROCNV)(void);
+
+
+#define GL_VERSION_1_0 1
+GLAD_API_CALL int GLAD_GL_VERSION_1_0;
+#define GL_VERSION_1_1 1
+GLAD_API_CALL int GLAD_GL_VERSION_1_1;
+#define GL_VERSION_1_2 1
+GLAD_API_CALL int GLAD_GL_VERSION_1_2;
+#define GL_VERSION_1_3 1
+GLAD_API_CALL int GLAD_GL_VERSION_1_3;
+#define GL_VERSION_1_4 1
+GLAD_API_CALL int GLAD_GL_VERSION_1_4;
+#define GL_VERSION_1_5 1
+GLAD_API_CALL int GLAD_GL_VERSION_1_5;
+#define GL_VERSION_2_0 1
+GLAD_API_CALL int GLAD_GL_VERSION_2_0;
+#define GL_VERSION_2_1 1
+GLAD_API_CALL int GLAD_GL_VERSION_2_1;
+#define GL_VERSION_3_0 1
+GLAD_API_CALL int GLAD_GL_VERSION_3_0;
+#define GL_VERSION_3_1 1
+GLAD_API_CALL int GLAD_GL_VERSION_3_1;
+#define GL_VERSION_3_2 1
+GLAD_API_CALL int GLAD_GL_VERSION_3_2;
+#define GL_VERSION_3_3 1
+GLAD_API_CALL int GLAD_GL_VERSION_3_3;
+#define GL_ARB_debug_output 1
+GLAD_API_CALL int GLAD_GL_ARB_debug_output;
+#define GL_ARB_framebuffer_object 1
+GLAD_API_CALL int GLAD_GL_ARB_framebuffer_object;
+#define GL_EXT_framebuffer_blit 1
+GLAD_API_CALL int GLAD_GL_EXT_framebuffer_blit;
+#define GL_EXT_framebuffer_multisample 1
+GLAD_API_CALL int GLAD_GL_EXT_framebuffer_multisample;
+#define GL_EXT_framebuffer_object 1
+GLAD_API_CALL int GLAD_GL_EXT_framebuffer_object;
+#define GL_OVR_multiview 1
+GLAD_API_CALL int GLAD_GL_OVR_multiview;
+#define GL_OVR_multiview2 1
+GLAD_API_CALL int GLAD_GL_OVR_multiview2;
+
+
+typedef void (GLAD_API_PTR *PFNGLACCUMPROC)(GLenum op, GLfloat value);
+typedef void (GLAD_API_PTR *PFNGLACTIVETEXTUREPROC)(GLenum texture);
+typedef void (GLAD_API_PTR *PFNGLALPHAFUNCPROC)(GLenum func, GLfloat ref);
+typedef GLboolean (GLAD_API_PTR *PFNGLARETEXTURESRESIDENTPROC)(GLsizei n, const GLuint * textures, GLboolean * residences);
+typedef void (GLAD_API_PTR *PFNGLARRAYELEMENTPROC)(GLint i);
+typedef void (GLAD_API_PTR *PFNGLATTACHSHADERPROC)(GLuint program, GLuint shader);
+typedef void (GLAD_API_PTR *PFNGLBEGINPROC)(GLenum mode);
+typedef void (GLAD_API_PTR *PFNGLBEGINCONDITIONALRENDERPROC)(GLuint id, GLenum mode);
+typedef void (GLAD_API_PTR *PFNGLBEGINQUERYPROC)(GLenum target, GLuint id);
+typedef void (GLAD_API_PTR *PFNGLBEGINTRANSFORMFEEDBACKPROC)(GLenum primitiveMode);
+typedef void (GLAD_API_PTR *PFNGLBINDATTRIBLOCATIONPROC)(GLuint program, GLuint index, const GLchar * name);
+typedef void (GLAD_API_PTR *PFNGLBINDBUFFERPROC)(GLenum target, GLuint buffer);
+typedef void (GLAD_API_PTR *PFNGLBINDBUFFERBASEPROC)(GLenum target, GLuint index, GLuint buffer);
+typedef void (GLAD_API_PTR *PFNGLBINDBUFFERRANGEPROC)(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
+typedef void (GLAD_API_PTR *PFNGLBINDFRAGDATALOCATIONPROC)(GLuint program, GLuint color, const GLchar * name);
+typedef void (GLAD_API_PTR *PFNGLBINDFRAGDATALOCATIONINDEXEDPROC)(GLuint program, GLuint colorNumber, GLuint index, const GLchar * name);
+typedef void (GLAD_API_PTR *PFNGLBINDFRAMEBUFFERPROC)(GLenum target, GLuint framebuffer);
+typedef void (GLAD_API_PTR *PFNGLBINDFRAMEBUFFEREXTPROC)(GLenum target, GLuint framebuffer);
+typedef void (GLAD_API_PTR *PFNGLBINDRENDERBUFFERPROC)(GLenum target, GLuint renderbuffer);
+typedef void (GLAD_API_PTR *PFNGLBINDRENDERBUFFEREXTPROC)(GLenum target, GLuint renderbuffer);
+typedef void (GLAD_API_PTR *PFNGLBINDSAMPLERPROC)(GLuint unit, GLuint sampler);
+typedef void (GLAD_API_PTR *PFNGLBINDTEXTUREPROC)(GLenum target, GLuint texture);
+typedef void (GLAD_API_PTR *PFNGLBINDVERTEXARRAYPROC)(GLuint array);
+typedef void (GLAD_API_PTR *PFNGLBITMAPPROC)(GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, const GLubyte * bitmap);
+typedef void (GLAD_API_PTR *PFNGLBLENDCOLORPROC)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+typedef void (GLAD_API_PTR *PFNGLBLENDEQUATIONPROC)(GLenum mode);
+typedef void (GLAD_API_PTR *PFNGLBLENDEQUATIONSEPARATEPROC)(GLenum modeRGB, GLenum modeAlpha);
+typedef void (GLAD_API_PTR *PFNGLBLENDFUNCPROC)(GLenum sfactor, GLenum dfactor);
+typedef void (GLAD_API_PTR *PFNGLBLENDFUNCSEPARATEPROC)(GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
+typedef void (GLAD_API_PTR *PFNGLBLITFRAMEBUFFERPROC)(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+typedef void (GLAD_API_PTR *PFNGLBLITFRAMEBUFFEREXTPROC)(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+typedef void (GLAD_API_PTR *PFNGLBUFFERDATAPROC)(GLenum target, GLsizeiptr size, const void * data, GLenum usage);
+typedef void (GLAD_API_PTR *PFNGLBUFFERSUBDATAPROC)(GLenum target, GLintptr offset, GLsizeiptr size, const void * data);
+typedef void (GLAD_API_PTR *PFNGLCALLLISTPROC)(GLuint list);
+typedef void (GLAD_API_PTR *PFNGLCALLLISTSPROC)(GLsizei n, GLenum type, const void * lists);
+typedef GLenum (GLAD_API_PTR *PFNGLCHECKFRAMEBUFFERSTATUSPROC)(GLenum target);
+typedef GLenum (GLAD_API_PTR *PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC)(GLenum target);
+typedef void (GLAD_API_PTR *PFNGLCLAMPCOLORPROC)(GLenum target, GLenum clamp);
+typedef void (GLAD_API_PTR *PFNGLCLEARPROC)(GLbitfield mask);
+typedef void (GLAD_API_PTR *PFNGLCLEARACCUMPROC)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+typedef void (GLAD_API_PTR *PFNGLCLEARBUFFERFIPROC)(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil);
+typedef void (GLAD_API_PTR *PFNGLCLEARBUFFERFVPROC)(GLenum buffer, GLint drawbuffer, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLCLEARBUFFERIVPROC)(GLenum buffer, GLint drawbuffer, const GLint * value);
+typedef void (GLAD_API_PTR *PFNGLCLEARBUFFERUIVPROC)(GLenum buffer, GLint drawbuffer, const GLuint * value);
+typedef void (GLAD_API_PTR *PFNGLCLEARCOLORPROC)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+typedef void (GLAD_API_PTR *PFNGLCLEARDEPTHPROC)(GLdouble depth);
+typedef void (GLAD_API_PTR *PFNGLCLEARINDEXPROC)(GLfloat c);
+typedef void (GLAD_API_PTR *PFNGLCLEARSTENCILPROC)(GLint s);
+typedef void (GLAD_API_PTR *PFNGLCLIENTACTIVETEXTUREPROC)(GLenum texture);
+typedef GLenum (GLAD_API_PTR *PFNGLCLIENTWAITSYNCPROC)(GLsync sync, GLbitfield flags, GLuint64 timeout);
+typedef void (GLAD_API_PTR *PFNGLCLIPPLANEPROC)(GLenum plane, const GLdouble * equation);
+typedef void (GLAD_API_PTR *PFNGLCOLOR3BPROC)(GLbyte red, GLbyte green, GLbyte blue);
+typedef void (GLAD_API_PTR *PFNGLCOLOR3BVPROC)(const GLbyte * v);
+typedef void (GLAD_API_PTR *PFNGLCOLOR3DPROC)(GLdouble red, GLdouble green, GLdouble blue);
+typedef void (GLAD_API_PTR *PFNGLCOLOR3DVPROC)(const GLdouble * v);
+typedef void (GLAD_API_PTR *PFNGLCOLOR3FPROC)(GLfloat red, GLfloat green, GLfloat blue);
+typedef void (GLAD_API_PTR *PFNGLCOLOR3FVPROC)(const GLfloat * v);
+typedef void (GLAD_API_PTR *PFNGLCOLOR3IPROC)(GLint red, GLint green, GLint blue);
+typedef void (GLAD_API_PTR *PFNGLCOLOR3IVPROC)(const GLint * v);
+typedef void (GLAD_API_PTR *PFNGLCOLOR3SPROC)(GLshort red, GLshort green, GLshort blue);
+typedef void (GLAD_API_PTR *PFNGLCOLOR3SVPROC)(const GLshort * v);
+typedef void (GLAD_API_PTR *PFNGLCOLOR3UBPROC)(GLubyte red, GLubyte green, GLubyte blue);
+typedef void (GLAD_API_PTR *PFNGLCOLOR3UBVPROC)(const GLubyte * v);
+typedef void (GLAD_API_PTR *PFNGLCOLOR3UIPROC)(GLuint red, GLuint green, GLuint blue);
+typedef void (GLAD_API_PTR *PFNGLCOLOR3UIVPROC)(const GLuint * v);
+typedef void (GLAD_API_PTR *PFNGLCOLOR3USPROC)(GLushort red, GLushort green, GLushort blue);
+typedef void (GLAD_API_PTR *PFNGLCOLOR3USVPROC)(const GLushort * v);
+typedef void (GLAD_API_PTR *PFNGLCOLOR4BPROC)(GLbyte red, GLbyte green, GLbyte blue, GLbyte alpha);
+typedef void (GLAD_API_PTR *PFNGLCOLOR4BVPROC)(const GLbyte * v);
+typedef void (GLAD_API_PTR *PFNGLCOLOR4DPROC)(GLdouble red, GLdouble green, GLdouble blue, GLdouble alpha);
+typedef void (GLAD_API_PTR *PFNGLCOLOR4DVPROC)(const GLdouble * v);
+typedef void (GLAD_API_PTR *PFNGLCOLOR4FPROC)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+typedef void (GLAD_API_PTR *PFNGLCOLOR4FVPROC)(const GLfloat * v);
+typedef void (GLAD_API_PTR *PFNGLCOLOR4IPROC)(GLint red, GLint green, GLint blue, GLint alpha);
+typedef void (GLAD_API_PTR *PFNGLCOLOR4IVPROC)(const GLint * v);
+typedef void (GLAD_API_PTR *PFNGLCOLOR4SPROC)(GLshort red, GLshort green, GLshort blue, GLshort alpha);
+typedef void (GLAD_API_PTR *PFNGLCOLOR4SVPROC)(const GLshort * v);
+typedef void (GLAD_API_PTR *PFNGLCOLOR4UBPROC)(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha);
+typedef void (GLAD_API_PTR *PFNGLCOLOR4UBVPROC)(const GLubyte * v);
+typedef void (GLAD_API_PTR *PFNGLCOLOR4UIPROC)(GLuint red, GLuint green, GLuint blue, GLuint alpha);
+typedef void (GLAD_API_PTR *PFNGLCOLOR4UIVPROC)(const GLuint * v);
+typedef void (GLAD_API_PTR *PFNGLCOLOR4USPROC)(GLushort red, GLushort green, GLushort blue, GLushort alpha);
+typedef void (GLAD_API_PTR *PFNGLCOLOR4USVPROC)(const GLushort * v);
+typedef void (GLAD_API_PTR *PFNGLCOLORMASKPROC)(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
+typedef void (GLAD_API_PTR *PFNGLCOLORMASKIPROC)(GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a);
+typedef void (GLAD_API_PTR *PFNGLCOLORMATERIALPROC)(GLenum face, GLenum mode);
+typedef void (GLAD_API_PTR *PFNGLCOLORP3UIPROC)(GLenum type, GLuint color);
+typedef void (GLAD_API_PTR *PFNGLCOLORP3UIVPROC)(GLenum type, const GLuint * color);
+typedef void (GLAD_API_PTR *PFNGLCOLORP4UIPROC)(GLenum type, GLuint color);
+typedef void (GLAD_API_PTR *PFNGLCOLORP4UIVPROC)(GLenum type, const GLuint * color);
+typedef void (GLAD_API_PTR *PFNGLCOLORPOINTERPROC)(GLint size, GLenum type, GLsizei stride, const void * pointer);
+typedef void (GLAD_API_PTR *PFNGLCOMPILESHADERPROC)(GLuint shader);
+typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXIMAGE1DPROC)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void * data);
+typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXIMAGE2DPROC)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void * data);
+typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXIMAGE3DPROC)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void * data);
+typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC)(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void * data);
+typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void * data);
+typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void * data);
+typedef void (GLAD_API_PTR *PFNGLCOPYBUFFERSUBDATAPROC)(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
+typedef void (GLAD_API_PTR *PFNGLCOPYPIXELSPROC)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type);
+typedef void (GLAD_API_PTR *PFNGLCOPYTEXIMAGE1DPROC)(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border);
+typedef void (GLAD_API_PTR *PFNGLCOPYTEXIMAGE2DPROC)(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+typedef void (GLAD_API_PTR *PFNGLCOPYTEXSUBIMAGE1DPROC)(GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width);
+typedef void (GLAD_API_PTR *PFNGLCOPYTEXSUBIMAGE2DPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GLAD_API_PTR *PFNGLCOPYTEXSUBIMAGE3DPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef GLuint (GLAD_API_PTR *PFNGLCREATEPROGRAMPROC)(void);
+typedef GLuint (GLAD_API_PTR *PFNGLCREATESHADERPROC)(GLenum type);
+typedef void (GLAD_API_PTR *PFNGLCULLFACEPROC)(GLenum mode);
+typedef void (GLAD_API_PTR *PFNGLDEBUGMESSAGECALLBACKARBPROC)(GLDEBUGPROCARB callback, const void * userParam);
+typedef void (GLAD_API_PTR *PFNGLDEBUGMESSAGECONTROLARBPROC)(GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint * ids, GLboolean enabled);
+typedef void (GLAD_API_PTR *PFNGLDEBUGMESSAGEINSERTARBPROC)(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar * buf);
+typedef void (GLAD_API_PTR *PFNGLDELETEBUFFERSPROC)(GLsizei n, const GLuint * buffers);
+typedef void (GLAD_API_PTR *PFNGLDELETEFRAMEBUFFERSPROC)(GLsizei n, const GLuint * framebuffers);
+typedef void (GLAD_API_PTR *PFNGLDELETEFRAMEBUFFERSEXTPROC)(GLsizei n, const GLuint * framebuffers);
+typedef void (GLAD_API_PTR *PFNGLDELETELISTSPROC)(GLuint list, GLsizei range);
+typedef void (GLAD_API_PTR *PFNGLDELETEPROGRAMPROC)(GLuint program);
+typedef void (GLAD_API_PTR *PFNGLDELETEQUERIESPROC)(GLsizei n, const GLuint * ids);
+typedef void (GLAD_API_PTR *PFNGLDELETERENDERBUFFERSPROC)(GLsizei n, const GLuint * renderbuffers);
+typedef void (GLAD_API_PTR *PFNGLDELETERENDERBUFFERSEXTPROC)(GLsizei n, const GLuint * renderbuffers);
+typedef void (GLAD_API_PTR *PFNGLDELETESAMPLERSPROC)(GLsizei count, const GLuint * samplers);
+typedef void (GLAD_API_PTR *PFNGLDELETESHADERPROC)(GLuint shader);
+typedef void (GLAD_API_PTR *PFNGLDELETESYNCPROC)(GLsync sync);
+typedef void (GLAD_API_PTR *PFNGLDELETETEXTURESPROC)(GLsizei n, const GLuint * textures);
+typedef void (GLAD_API_PTR *PFNGLDELETEVERTEXARRAYSPROC)(GLsizei n, const GLuint * arrays);
+typedef void (GLAD_API_PTR *PFNGLDEPTHFUNCPROC)(GLenum func);
+typedef void (GLAD_API_PTR *PFNGLDEPTHMASKPROC)(GLboolean flag);
+typedef void (GLAD_API_PTR *PFNGLDEPTHRANGEPROC)(GLdouble n, GLdouble f);
+typedef void (GLAD_API_PTR *PFNGLDETACHSHADERPROC)(GLuint program, GLuint shader);
+typedef void (GLAD_API_PTR *PFNGLDISABLEPROC)(GLenum cap);
+typedef void (GLAD_API_PTR *PFNGLDISABLECLIENTSTATEPROC)(GLenum array);
+typedef void (GLAD_API_PTR *PFNGLDISABLEVERTEXATTRIBARRAYPROC)(GLuint index);
+typedef void (GLAD_API_PTR *PFNGLDISABLEIPROC)(GLenum target, GLuint index);
+typedef void (GLAD_API_PTR *PFNGLDRAWARRAYSPROC)(GLenum mode, GLint first, GLsizei count);
+typedef void (GLAD_API_PTR *PFNGLDRAWARRAYSINSTANCEDPROC)(GLenum mode, GLint first, GLsizei count, GLsizei instancecount);
+typedef void (GLAD_API_PTR *PFNGLDRAWBUFFERPROC)(GLenum buf);
+typedef void (GLAD_API_PTR *PFNGLDRAWBUFFERSPROC)(GLsizei n, const GLenum * bufs);
+typedef void (GLAD_API_PTR *PFNGLDRAWELEMENTSPROC)(GLenum mode, GLsizei count, GLenum type, const void * indices);
+typedef void (GLAD_API_PTR *PFNGLDRAWELEMENTSBASEVERTEXPROC)(GLenum mode, GLsizei count, GLenum type, const void * indices, GLint basevertex);
+typedef void (GLAD_API_PTR *PFNGLDRAWELEMENTSINSTANCEDPROC)(GLenum mode, GLsizei count, GLenum type, const void * indices, GLsizei instancecount);
+typedef void (GLAD_API_PTR *PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC)(GLenum mode, GLsizei count, GLenum type, const void * indices, GLsizei instancecount, GLint basevertex);
+typedef void (GLAD_API_PTR *PFNGLDRAWPIXELSPROC)(GLsizei width, GLsizei height, GLenum format, GLenum type, const void * pixels);
+typedef void (GLAD_API_PTR *PFNGLDRAWRANGEELEMENTSPROC)(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void * indices);
+typedef void (GLAD_API_PTR *PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC)(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void * indices, GLint basevertex);
+typedef void (GLAD_API_PTR *PFNGLEDGEFLAGPROC)(GLboolean flag);
+typedef void (GLAD_API_PTR *PFNGLEDGEFLAGPOINTERPROC)(GLsizei stride, const void * pointer);
+typedef void (GLAD_API_PTR *PFNGLEDGEFLAGVPROC)(const GLboolean * flag);
+typedef void (GLAD_API_PTR *PFNGLENABLEPROC)(GLenum cap);
+typedef void (GLAD_API_PTR *PFNGLENABLECLIENTSTATEPROC)(GLenum array);
+typedef void (GLAD_API_PTR *PFNGLENABLEVERTEXATTRIBARRAYPROC)(GLuint index);
+typedef void (GLAD_API_PTR *PFNGLENABLEIPROC)(GLenum target, GLuint index);
+typedef void (GLAD_API_PTR *PFNGLENDPROC)(void);
+typedef void (GLAD_API_PTR *PFNGLENDCONDITIONALRENDERPROC)(void);
+typedef void (GLAD_API_PTR *PFNGLENDLISTPROC)(void);
+typedef void (GLAD_API_PTR *PFNGLENDQUERYPROC)(GLenum target);
+typedef void (GLAD_API_PTR *PFNGLENDTRANSFORMFEEDBACKPROC)(void);
+typedef void (GLAD_API_PTR *PFNGLEVALCOORD1DPROC)(GLdouble u);
+typedef void (GLAD_API_PTR *PFNGLEVALCOORD1DVPROC)(const GLdouble * u);
+typedef void (GLAD_API_PTR *PFNGLEVALCOORD1FPROC)(GLfloat u);
+typedef void (GLAD_API_PTR *PFNGLEVALCOORD1FVPROC)(const GLfloat * u);
+typedef void (GLAD_API_PTR *PFNGLEVALCOORD2DPROC)(GLdouble u, GLdouble v);
+typedef void (GLAD_API_PTR *PFNGLEVALCOORD2DVPROC)(const GLdouble * u);
+typedef void (GLAD_API_PTR *PFNGLEVALCOORD2FPROC)(GLfloat u, GLfloat v);
+typedef void (GLAD_API_PTR *PFNGLEVALCOORD2FVPROC)(const GLfloat * u);
+typedef void (GLAD_API_PTR *PFNGLEVALMESH1PROC)(GLenum mode, GLint i1, GLint i2);
+typedef void (GLAD_API_PTR *PFNGLEVALMESH2PROC)(GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2);
+typedef void (GLAD_API_PTR *PFNGLEVALPOINT1PROC)(GLint i);
+typedef void (GLAD_API_PTR *PFNGLEVALPOINT2PROC)(GLint i, GLint j);
+typedef void (GLAD_API_PTR *PFNGLFEEDBACKBUFFERPROC)(GLsizei size, GLenum type, GLfloat * buffer);
+typedef GLsync (GLAD_API_PTR *PFNGLFENCESYNCPROC)(GLenum condition, GLbitfield flags);
+typedef void (GLAD_API_PTR *PFNGLFINISHPROC)(void);
+typedef void (GLAD_API_PTR *PFNGLFLUSHPROC)(void);
+typedef void (GLAD_API_PTR *PFNGLFLUSHMAPPEDBUFFERRANGEPROC)(GLenum target, GLintptr offset, GLsizeiptr length);
+typedef void (GLAD_API_PTR *PFNGLFOGCOORDPOINTERPROC)(GLenum type, GLsizei stride, const void * pointer);
+typedef void (GLAD_API_PTR *PFNGLFOGCOORDDPROC)(GLdouble coord);
+typedef void (GLAD_API_PTR *PFNGLFOGCOORDDVPROC)(const GLdouble * coord);
+typedef void (GLAD_API_PTR *PFNGLFOGCOORDFPROC)(GLfloat coord);
+typedef void (GLAD_API_PTR *PFNGLFOGCOORDFVPROC)(const GLfloat * coord);
+typedef void (GLAD_API_PTR *PFNGLFOGFPROC)(GLenum pname, GLfloat param);
+typedef void (GLAD_API_PTR *PFNGLFOGFVPROC)(GLenum pname, const GLfloat * params);
+typedef void (GLAD_API_PTR *PFNGLFOGIPROC)(GLenum pname, GLint param);
+typedef void (GLAD_API_PTR *PFNGLFOGIVPROC)(GLenum pname, const GLint * params);
+typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERRENDERBUFFERPROC)(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC)(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERTEXTUREPROC)(GLenum target, GLenum attachment, GLuint texture, GLint level);
+typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERTEXTURE1DPROC)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERTEXTURE1DEXTPROC)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERTEXTURE2DPROC)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERTEXTURE2DEXTPROC)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERTEXTURE3DPROC)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
+typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERTEXTURE3DEXTPROC)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
+typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERTEXTURELAYERPROC)(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
+typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC)(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint baseViewIndex, GLsizei numViews);
+typedef void (GLAD_API_PTR *PFNGLFRONTFACEPROC)(GLenum mode);
+typedef void (GLAD_API_PTR *PFNGLFRUSTUMPROC)(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);
+typedef void (GLAD_API_PTR *PFNGLGENBUFFERSPROC)(GLsizei n, GLuint * buffers);
+typedef void (GLAD_API_PTR *PFNGLGENFRAMEBUFFERSPROC)(GLsizei n, GLuint * framebuffers);
+typedef void (GLAD_API_PTR *PFNGLGENFRAMEBUFFERSEXTPROC)(GLsizei n, GLuint * framebuffers);
+typedef GLuint (GLAD_API_PTR *PFNGLGENLISTSPROC)(GLsizei range);
+typedef void (GLAD_API_PTR *PFNGLGENQUERIESPROC)(GLsizei n, GLuint * ids);
+typedef void (GLAD_API_PTR *PFNGLGENRENDERBUFFERSPROC)(GLsizei n, GLuint * renderbuffers);
+typedef void (GLAD_API_PTR *PFNGLGENRENDERBUFFERSEXTPROC)(GLsizei n, GLuint * renderbuffers);
+typedef void (GLAD_API_PTR *PFNGLGENSAMPLERSPROC)(GLsizei count, GLuint * samplers);
+typedef void (GLAD_API_PTR *PFNGLGENTEXTURESPROC)(GLsizei n, GLuint * textures);
+typedef void (GLAD_API_PTR *PFNGLGENVERTEXARRAYSPROC)(GLsizei n, GLuint * arrays);
+typedef void (GLAD_API_PTR *PFNGLGENERATEMIPMAPPROC)(GLenum target);
+typedef void (GLAD_API_PTR *PFNGLGENERATEMIPMAPEXTPROC)(GLenum target);
+typedef void (GLAD_API_PTR *PFNGLGETACTIVEATTRIBPROC)(GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLint * size, GLenum * type, GLchar * name);
+typedef void (GLAD_API_PTR *PFNGLGETACTIVEUNIFORMPROC)(GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLint * size, GLenum * type, GLchar * name);
+typedef void (GLAD_API_PTR *PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC)(GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei * length, GLchar * uniformBlockName);
+typedef void (GLAD_API_PTR *PFNGLGETACTIVEUNIFORMBLOCKIVPROC)(GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETACTIVEUNIFORMNAMEPROC)(GLuint program, GLuint uniformIndex, GLsizei bufSize, GLsizei * length, GLchar * uniformName);
+typedef void (GLAD_API_PTR *PFNGLGETACTIVEUNIFORMSIVPROC)(GLuint program, GLsizei uniformCount, const GLuint * uniformIndices, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETATTACHEDSHADERSPROC)(GLuint program, GLsizei maxCount, GLsizei * count, GLuint * shaders);
+typedef GLint (GLAD_API_PTR *PFNGLGETATTRIBLOCATIONPROC)(GLuint program, const GLchar * name);
+typedef void (GLAD_API_PTR *PFNGLGETBOOLEANI_VPROC)(GLenum target, GLuint index, GLboolean * data);
+typedef void (GLAD_API_PTR *PFNGLGETBOOLEANVPROC)(GLenum pname, GLboolean * data);
+typedef void (GLAD_API_PTR *PFNGLGETBUFFERPARAMETERI64VPROC)(GLenum target, GLenum pname, GLint64 * params);
+typedef void (GLAD_API_PTR *PFNGLGETBUFFERPARAMETERIVPROC)(GLenum target, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETBUFFERPOINTERVPROC)(GLenum target, GLenum pname, void ** params);
+typedef void (GLAD_API_PTR *PFNGLGETBUFFERSUBDATAPROC)(GLenum target, GLintptr offset, GLsizeiptr size, void * data);
+typedef void (GLAD_API_PTR *PFNGLGETCLIPPLANEPROC)(GLenum plane, GLdouble * equation);
+typedef void (GLAD_API_PTR *PFNGLGETCOMPRESSEDTEXIMAGEPROC)(GLenum target, GLint level, void * img);
+typedef GLuint (GLAD_API_PTR *PFNGLGETDEBUGMESSAGELOGARBPROC)(GLuint count, GLsizei bufSize, GLenum * sources, GLenum * types, GLuint * ids, GLenum * severities, GLsizei * lengths, GLchar * messageLog);
+typedef void (GLAD_API_PTR *PFNGLGETDOUBLEVPROC)(GLenum pname, GLdouble * data);
+typedef GLenum (GLAD_API_PTR *PFNGLGETERRORPROC)(void);
+typedef void (GLAD_API_PTR *PFNGLGETFLOATVPROC)(GLenum pname, GLfloat * data);
+typedef GLint (GLAD_API_PTR *PFNGLGETFRAGDATAINDEXPROC)(GLuint program, const GLchar * name);
+typedef GLint (GLAD_API_PTR *PFNGLGETFRAGDATALOCATIONPROC)(GLuint program, const GLchar * name);
+typedef void (GLAD_API_PTR *PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC)(GLenum target, GLenum attachment, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC)(GLenum target, GLenum attachment, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETINTEGER64I_VPROC)(GLenum target, GLuint index, GLint64 * data);
+typedef void (GLAD_API_PTR *PFNGLGETINTEGER64VPROC)(GLenum pname, GLint64 * data);
+typedef void (GLAD_API_PTR *PFNGLGETINTEGERI_VPROC)(GLenum target, GLuint index, GLint * data);
+typedef void (GLAD_API_PTR *PFNGLGETINTEGERVPROC)(GLenum pname, GLint * data);
+typedef void (GLAD_API_PTR *PFNGLGETLIGHTFVPROC)(GLenum light, GLenum pname, GLfloat * params);
+typedef void (GLAD_API_PTR *PFNGLGETLIGHTIVPROC)(GLenum light, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETMAPDVPROC)(GLenum target, GLenum query, GLdouble * v);
+typedef void (GLAD_API_PTR *PFNGLGETMAPFVPROC)(GLenum target, GLenum query, GLfloat * v);
+typedef void (GLAD_API_PTR *PFNGLGETMAPIVPROC)(GLenum target, GLenum query, GLint * v);
+typedef void (GLAD_API_PTR *PFNGLGETMATERIALFVPROC)(GLenum face, GLenum pname, GLfloat * params);
+typedef void (GLAD_API_PTR *PFNGLGETMATERIALIVPROC)(GLenum face, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETMULTISAMPLEFVPROC)(GLenum pname, GLuint index, GLfloat * val);
+typedef void (GLAD_API_PTR *PFNGLGETPIXELMAPFVPROC)(GLenum map, GLfloat * values);
+typedef void (GLAD_API_PTR *PFNGLGETPIXELMAPUIVPROC)(GLenum map, GLuint * values);
+typedef void (GLAD_API_PTR *PFNGLGETPIXELMAPUSVPROC)(GLenum map, GLushort * values);
+typedef void (GLAD_API_PTR *PFNGLGETPOINTERVPROC)(GLenum pname, void ** params);
+typedef void (GLAD_API_PTR *PFNGLGETPOLYGONSTIPPLEPROC)(GLubyte * mask);
+typedef void (GLAD_API_PTR *PFNGLGETPROGRAMINFOLOGPROC)(GLuint program, GLsizei bufSize, GLsizei * length, GLchar * infoLog);
+typedef void (GLAD_API_PTR *PFNGLGETPROGRAMIVPROC)(GLuint program, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETQUERYOBJECTI64VPROC)(GLuint id, GLenum pname, GLint64 * params);
+typedef void (GLAD_API_PTR *PFNGLGETQUERYOBJECTIVPROC)(GLuint id, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETQUERYOBJECTUI64VPROC)(GLuint id, GLenum pname, GLuint64 * params);
+typedef void (GLAD_API_PTR *PFNGLGETQUERYOBJECTUIVPROC)(GLuint id, GLenum pname, GLuint * params);
+typedef void (GLAD_API_PTR *PFNGLGETQUERYIVPROC)(GLenum target, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETRENDERBUFFERPARAMETERIVPROC)(GLenum target, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC)(GLenum target, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETSAMPLERPARAMETERIIVPROC)(GLuint sampler, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETSAMPLERPARAMETERIUIVPROC)(GLuint sampler, GLenum pname, GLuint * params);
+typedef void (GLAD_API_PTR *PFNGLGETSAMPLERPARAMETERFVPROC)(GLuint sampler, GLenum pname, GLfloat * params);
+typedef void (GLAD_API_PTR *PFNGLGETSAMPLERPARAMETERIVPROC)(GLuint sampler, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETSHADERINFOLOGPROC)(GLuint shader, GLsizei bufSize, GLsizei * length, GLchar * infoLog);
+typedef void (GLAD_API_PTR *PFNGLGETSHADERSOURCEPROC)(GLuint shader, GLsizei bufSize, GLsizei * length, GLchar * source);
+typedef void (GLAD_API_PTR *PFNGLGETSHADERIVPROC)(GLuint shader, GLenum pname, GLint * params);
+typedef const GLubyte * (GLAD_API_PTR *PFNGLGETSTRINGPROC)(GLenum name);
+typedef const GLubyte * (GLAD_API_PTR *PFNGLGETSTRINGIPROC)(GLenum name, GLuint index);
+typedef void (GLAD_API_PTR *PFNGLGETSYNCIVPROC)(GLsync sync, GLenum pname, GLsizei count, GLsizei * length, GLint * values);
+typedef void (GLAD_API_PTR *PFNGLGETTEXENVFVPROC)(GLenum target, GLenum pname, GLfloat * params);
+typedef void (GLAD_API_PTR *PFNGLGETTEXENVIVPROC)(GLenum target, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETTEXGENDVPROC)(GLenum coord, GLenum pname, GLdouble * params);
+typedef void (GLAD_API_PTR *PFNGLGETTEXGENFVPROC)(GLenum coord, GLenum pname, GLfloat * params);
+typedef void (GLAD_API_PTR *PFNGLGETTEXGENIVPROC)(GLenum coord, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETTEXIMAGEPROC)(GLenum target, GLint level, GLenum format, GLenum type, void * pixels);
+typedef void (GLAD_API_PTR *PFNGLGETTEXLEVELPARAMETERFVPROC)(GLenum target, GLint level, GLenum pname, GLfloat * params);
+typedef void (GLAD_API_PTR *PFNGLGETTEXLEVELPARAMETERIVPROC)(GLenum target, GLint level, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETTEXPARAMETERIIVPROC)(GLenum target, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETTEXPARAMETERIUIVPROC)(GLenum target, GLenum pname, GLuint * params);
+typedef void (GLAD_API_PTR *PFNGLGETTEXPARAMETERFVPROC)(GLenum target, GLenum pname, GLfloat * params);
+typedef void (GLAD_API_PTR *PFNGLGETTEXPARAMETERIVPROC)(GLenum target, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETTRANSFORMFEEDBACKVARYINGPROC)(GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLsizei * size, GLenum * type, GLchar * name);
+typedef GLuint (GLAD_API_PTR *PFNGLGETUNIFORMBLOCKINDEXPROC)(GLuint program, const GLchar * uniformBlockName);
+typedef void (GLAD_API_PTR *PFNGLGETUNIFORMINDICESPROC)(GLuint program, GLsizei uniformCount, const GLchar *const* uniformNames, GLuint * uniformIndices);
+typedef GLint (GLAD_API_PTR *PFNGLGETUNIFORMLOCATIONPROC)(GLuint program, const GLchar * name);
+typedef void (GLAD_API_PTR *PFNGLGETUNIFORMFVPROC)(GLuint program, GLint location, GLfloat * params);
+typedef void (GLAD_API_PTR *PFNGLGETUNIFORMIVPROC)(GLuint program, GLint location, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETUNIFORMUIVPROC)(GLuint program, GLint location, GLuint * params);
+typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBIIVPROC)(GLuint index, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBIUIVPROC)(GLuint index, GLenum pname, GLuint * params);
+typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBPOINTERVPROC)(GLuint index, GLenum pname, void ** pointer);
+typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBDVPROC)(GLuint index, GLenum pname, GLdouble * params);
+typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBFVPROC)(GLuint index, GLenum pname, GLfloat * params);
+typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBIVPROC)(GLuint index, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLHINTPROC)(GLenum target, GLenum mode);
+typedef void (GLAD_API_PTR *PFNGLINDEXMASKPROC)(GLuint mask);
+typedef void (GLAD_API_PTR *PFNGLINDEXPOINTERPROC)(GLenum type, GLsizei stride, const void * pointer);
+typedef void (GLAD_API_PTR *PFNGLINDEXDPROC)(GLdouble c);
+typedef void (GLAD_API_PTR *PFNGLINDEXDVPROC)(const GLdouble * c);
+typedef void (GLAD_API_PTR *PFNGLINDEXFPROC)(GLfloat c);
+typedef void (GLAD_API_PTR *PFNGLINDEXFVPROC)(const GLfloat * c);
+typedef void (GLAD_API_PTR *PFNGLINDEXIPROC)(GLint c);
+typedef void (GLAD_API_PTR *PFNGLINDEXIVPROC)(const GLint * c);
+typedef void (GLAD_API_PTR *PFNGLINDEXSPROC)(GLshort c);
+typedef void (GLAD_API_PTR *PFNGLINDEXSVPROC)(const GLshort * c);
+typedef void (GLAD_API_PTR *PFNGLINDEXUBPROC)(GLubyte c);
+typedef void (GLAD_API_PTR *PFNGLINDEXUBVPROC)(const GLubyte * c);
+typedef void (GLAD_API_PTR *PFNGLINITNAMESPROC)(void);
+typedef void (GLAD_API_PTR *PFNGLINTERLEAVEDARRAYSPROC)(GLenum format, GLsizei stride, const void * pointer);
+typedef GLboolean (GLAD_API_PTR *PFNGLISBUFFERPROC)(GLuint buffer);
+typedef GLboolean (GLAD_API_PTR *PFNGLISENABLEDPROC)(GLenum cap);
+typedef GLboolean (GLAD_API_PTR *PFNGLISENABLEDIPROC)(GLenum target, GLuint index);
+typedef GLboolean (GLAD_API_PTR *PFNGLISFRAMEBUFFERPROC)(GLuint framebuffer);
+typedef GLboolean (GLAD_API_PTR *PFNGLISFRAMEBUFFEREXTPROC)(GLuint framebuffer);
+typedef GLboolean (GLAD_API_PTR *PFNGLISLISTPROC)(GLuint list);
+typedef GLboolean (GLAD_API_PTR *PFNGLISPROGRAMPROC)(GLuint program);
+typedef GLboolean (GLAD_API_PTR *PFNGLISQUERYPROC)(GLuint id);
+typedef GLboolean (GLAD_API_PTR *PFNGLISRENDERBUFFERPROC)(GLuint renderbuffer);
+typedef GLboolean (GLAD_API_PTR *PFNGLISRENDERBUFFEREXTPROC)(GLuint renderbuffer);
+typedef GLboolean (GLAD_API_PTR *PFNGLISSAMPLERPROC)(GLuint sampler);
+typedef GLboolean (GLAD_API_PTR *PFNGLISSHADERPROC)(GLuint shader);
+typedef GLboolean (GLAD_API_PTR *PFNGLISSYNCPROC)(GLsync sync);
+typedef GLboolean (GLAD_API_PTR *PFNGLISTEXTUREPROC)(GLuint texture);
+typedef GLboolean (GLAD_API_PTR *PFNGLISVERTEXARRAYPROC)(GLuint array);
+typedef void (GLAD_API_PTR *PFNGLLIGHTMODELFPROC)(GLenum pname, GLfloat param);
+typedef void (GLAD_API_PTR *PFNGLLIGHTMODELFVPROC)(GLenum pname, const GLfloat * params);
+typedef void (GLAD_API_PTR *PFNGLLIGHTMODELIPROC)(GLenum pname, GLint param);
+typedef void (GLAD_API_PTR *PFNGLLIGHTMODELIVPROC)(GLenum pname, const GLint * params);
+typedef void (GLAD_API_PTR *PFNGLLIGHTFPROC)(GLenum light, GLenum pname, GLfloat param);
+typedef void (GLAD_API_PTR *PFNGLLIGHTFVPROC)(GLenum light, GLenum pname, const GLfloat * params);
+typedef void (GLAD_API_PTR *PFNGLLIGHTIPROC)(GLenum light, GLenum pname, GLint param);
+typedef void (GLAD_API_PTR *PFNGLLIGHTIVPROC)(GLenum light, GLenum pname, const GLint * params);
+typedef void (GLAD_API_PTR *PFNGLLINESTIPPLEPROC)(GLint factor, GLushort pattern);
+typedef void (GLAD_API_PTR *PFNGLLINEWIDTHPROC)(GLfloat width);
+typedef void (GLAD_API_PTR *PFNGLLINKPROGRAMPROC)(GLuint program);
+typedef void (GLAD_API_PTR *PFNGLLISTBASEPROC)(GLuint base);
+typedef void (GLAD_API_PTR *PFNGLLOADIDENTITYPROC)(void);
+typedef void (GLAD_API_PTR *PFNGLLOADMATRIXDPROC)(const GLdouble * m);
+typedef void (GLAD_API_PTR *PFNGLLOADMATRIXFPROC)(const GLfloat * m);
+typedef void (GLAD_API_PTR *PFNGLLOADNAMEPROC)(GLuint name);
+typedef void (GLAD_API_PTR *PFNGLLOADTRANSPOSEMATRIXDPROC)(const GLdouble * m);
+typedef void (GLAD_API_PTR *PFNGLLOADTRANSPOSEMATRIXFPROC)(const GLfloat * m);
+typedef void (GLAD_API_PTR *PFNGLLOGICOPPROC)(GLenum opcode);
+typedef void (GLAD_API_PTR *PFNGLMAP1DPROC)(GLenum target, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble * points);
+typedef void (GLAD_API_PTR *PFNGLMAP1FPROC)(GLenum target, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat * points);
+typedef void (GLAD_API_PTR *PFNGLMAP2DPROC)(GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble * points);
+typedef void (GLAD_API_PTR *PFNGLMAP2FPROC)(GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat * points);
+typedef void * (GLAD_API_PTR *PFNGLMAPBUFFERPROC)(GLenum target, GLenum access);
+typedef void * (GLAD_API_PTR *PFNGLMAPBUFFERRANGEPROC)(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
+typedef void (GLAD_API_PTR *PFNGLMAPGRID1DPROC)(GLint un, GLdouble u1, GLdouble u2);
+typedef void (GLAD_API_PTR *PFNGLMAPGRID1FPROC)(GLint un, GLfloat u1, GLfloat u2);
+typedef void (GLAD_API_PTR *PFNGLMAPGRID2DPROC)(GLint un, GLdouble u1, GLdouble u2, GLint vn, GLdouble v1, GLdouble v2);
+typedef void (GLAD_API_PTR *PFNGLMAPGRID2FPROC)(GLint un, GLfloat u1, GLfloat u2, GLint vn, GLfloat v1, GLfloat v2);
+typedef void (GLAD_API_PTR *PFNGLMATERIALFPROC)(GLenum face, GLenum pname, GLfloat param);
+typedef void (GLAD_API_PTR *PFNGLMATERIALFVPROC)(GLenum face, GLenum pname, const GLfloat * params);
+typedef void (GLAD_API_PTR *PFNGLMATERIALIPROC)(GLenum face, GLenum pname, GLint param);
+typedef void (GLAD_API_PTR *PFNGLMATERIALIVPROC)(GLenum face, GLenum pname, const GLint * params);
+typedef void (GLAD_API_PTR *PFNGLMATRIXMODEPROC)(GLenum mode);
+typedef void (GLAD_API_PTR *PFNGLMULTMATRIXDPROC)(const GLdouble * m);
+typedef void (GLAD_API_PTR *PFNGLMULTMATRIXFPROC)(const GLfloat * m);
+typedef void (GLAD_API_PTR *PFNGLMULTTRANSPOSEMATRIXDPROC)(const GLdouble * m);
+typedef void (GLAD_API_PTR *PFNGLMULTTRANSPOSEMATRIXFPROC)(const GLfloat * m);
+typedef void (GLAD_API_PTR *PFNGLMULTIDRAWARRAYSPROC)(GLenum mode, const GLint * first, const GLsizei * count, GLsizei drawcount);
+typedef void (GLAD_API_PTR *PFNGLMULTIDRAWELEMENTSPROC)(GLenum mode, const GLsizei * count, GLenum type, const void *const* indices, GLsizei drawcount);
+typedef void (GLAD_API_PTR *PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC)(GLenum mode, const GLsizei * count, GLenum type, const void *const* indices, GLsizei drawcount, const GLint * basevertex);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD1DPROC)(GLenum target, GLdouble s);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD1DVPROC)(GLenum target, const GLdouble * v);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD1FPROC)(GLenum target, GLfloat s);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD1FVPROC)(GLenum target, const GLfloat * v);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD1IPROC)(GLenum target, GLint s);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD1IVPROC)(GLenum target, const GLint * v);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD1SPROC)(GLenum target, GLshort s);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD1SVPROC)(GLenum target, const GLshort * v);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD2DPROC)(GLenum target, GLdouble s, GLdouble t);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD2DVPROC)(GLenum target, const GLdouble * v);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD2FPROC)(GLenum target, GLfloat s, GLfloat t);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD2FVPROC)(GLenum target, const GLfloat * v);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD2IPROC)(GLenum target, GLint s, GLint t);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD2IVPROC)(GLenum target, const GLint * v);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD2SPROC)(GLenum target, GLshort s, GLshort t);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD2SVPROC)(GLenum target, const GLshort * v);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD3DPROC)(GLenum target, GLdouble s, GLdouble t, GLdouble r);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD3DVPROC)(GLenum target, const GLdouble * v);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD3FPROC)(GLenum target, GLfloat s, GLfloat t, GLfloat r);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD3FVPROC)(GLenum target, const GLfloat * v);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD3IPROC)(GLenum target, GLint s, GLint t, GLint r);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD3IVPROC)(GLenum target, const GLint * v);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD3SPROC)(GLenum target, GLshort s, GLshort t, GLshort r);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD3SVPROC)(GLenum target, const GLshort * v);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD4DPROC)(GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD4DVPROC)(GLenum target, const GLdouble * v);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD4FPROC)(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD4FVPROC)(GLenum target, const GLfloat * v);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD4IPROC)(GLenum target, GLint s, GLint t, GLint r, GLint q);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD4IVPROC)(GLenum target, const GLint * v);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD4SPROC)(GLenum target, GLshort s, GLshort t, GLshort r, GLshort q);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD4SVPROC)(GLenum target, const GLshort * v);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORDP1UIPROC)(GLenum texture, GLenum type, GLuint coords);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORDP1UIVPROC)(GLenum texture, GLenum type, const GLuint * coords);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORDP2UIPROC)(GLenum texture, GLenum type, GLuint coords);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORDP2UIVPROC)(GLenum texture, GLenum type, const GLuint * coords);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORDP3UIPROC)(GLenum texture, GLenum type, GLuint coords);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORDP3UIVPROC)(GLenum texture, GLenum type, const GLuint * coords);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORDP4UIPROC)(GLenum texture, GLenum type, GLuint coords);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORDP4UIVPROC)(GLenum texture, GLenum type, const GLuint * coords);
+typedef void (GLAD_API_PTR *PFNGLNEWLISTPROC)(GLuint list, GLenum mode);
+typedef void (GLAD_API_PTR *PFNGLNORMAL3BPROC)(GLbyte nx, GLbyte ny, GLbyte nz);
+typedef void (GLAD_API_PTR *PFNGLNORMAL3BVPROC)(const GLbyte * v);
+typedef void (GLAD_API_PTR *PFNGLNORMAL3DPROC)(GLdouble nx, GLdouble ny, GLdouble nz);
+typedef void (GLAD_API_PTR *PFNGLNORMAL3DVPROC)(const GLdouble * v);
+typedef void (GLAD_API_PTR *PFNGLNORMAL3FPROC)(GLfloat nx, GLfloat ny, GLfloat nz);
+typedef void (GLAD_API_PTR *PFNGLNORMAL3FVPROC)(const GLfloat * v);
+typedef void (GLAD_API_PTR *PFNGLNORMAL3IPROC)(GLint nx, GLint ny, GLint nz);
+typedef void (GLAD_API_PTR *PFNGLNORMAL3IVPROC)(const GLint * v);
+typedef void (GLAD_API_PTR *PFNGLNORMAL3SPROC)(GLshort nx, GLshort ny, GLshort nz);
+typedef void (GLAD_API_PTR *PFNGLNORMAL3SVPROC)(const GLshort * v);
+typedef void (GLAD_API_PTR *PFNGLNORMALP3UIPROC)(GLenum type, GLuint coords);
+typedef void (GLAD_API_PTR *PFNGLNORMALP3UIVPROC)(GLenum type, const GLuint * coords);
+typedef void (GLAD_API_PTR *PFNGLNORMALPOINTERPROC)(GLenum type, GLsizei stride, const void * pointer);
+typedef void (GLAD_API_PTR *PFNGLORTHOPROC)(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);
+typedef void (GLAD_API_PTR *PFNGLPASSTHROUGHPROC)(GLfloat token);
+typedef void (GLAD_API_PTR *PFNGLPIXELMAPFVPROC)(GLenum map, GLsizei mapsize, const GLfloat * values);
+typedef void (GLAD_API_PTR *PFNGLPIXELMAPUIVPROC)(GLenum map, GLsizei mapsize, const GLuint * values);
+typedef void (GLAD_API_PTR *PFNGLPIXELMAPUSVPROC)(GLenum map, GLsizei mapsize, const GLushort * values);
+typedef void (GLAD_API_PTR *PFNGLPIXELSTOREFPROC)(GLenum pname, GLfloat param);
+typedef void (GLAD_API_PTR *PFNGLPIXELSTOREIPROC)(GLenum pname, GLint param);
+typedef void (GLAD_API_PTR *PFNGLPIXELTRANSFERFPROC)(GLenum pname, GLfloat param);
+typedef void (GLAD_API_PTR *PFNGLPIXELTRANSFERIPROC)(GLenum pname, GLint param);
+typedef void (GLAD_API_PTR *PFNGLPIXELZOOMPROC)(GLfloat xfactor, GLfloat yfactor);
+typedef void (GLAD_API_PTR *PFNGLPOINTPARAMETERFPROC)(GLenum pname, GLfloat param);
+typedef void (GLAD_API_PTR *PFNGLPOINTPARAMETERFVPROC)(GLenum pname, const GLfloat * params);
+typedef void (GLAD_API_PTR *PFNGLPOINTPARAMETERIPROC)(GLenum pname, GLint param);
+typedef void (GLAD_API_PTR *PFNGLPOINTPARAMETERIVPROC)(GLenum pname, const GLint * params);
+typedef void (GLAD_API_PTR *PFNGLPOINTSIZEPROC)(GLfloat size);
+typedef void (GLAD_API_PTR *PFNGLPOLYGONMODEPROC)(GLenum face, GLenum mode);
+typedef void (GLAD_API_PTR *PFNGLPOLYGONOFFSETPROC)(GLfloat factor, GLfloat units);
+typedef void (GLAD_API_PTR *PFNGLPOLYGONSTIPPLEPROC)(const GLubyte * mask);
+typedef void (GLAD_API_PTR *PFNGLPOPATTRIBPROC)(void);
+typedef void (GLAD_API_PTR *PFNGLPOPCLIENTATTRIBPROC)(void);
+typedef void (GLAD_API_PTR *PFNGLPOPMATRIXPROC)(void);
+typedef void (GLAD_API_PTR *PFNGLPOPNAMEPROC)(void);
+typedef void (GLAD_API_PTR *PFNGLPRIMITIVERESTARTINDEXPROC)(GLuint index);
+typedef void (GLAD_API_PTR *PFNGLPRIORITIZETEXTURESPROC)(GLsizei n, const GLuint * textures, const GLfloat * priorities);
+typedef void (GLAD_API_PTR *PFNGLPROVOKINGVERTEXPROC)(GLenum mode);
+typedef void (GLAD_API_PTR *PFNGLPUSHATTRIBPROC)(GLbitfield mask);
+typedef void (GLAD_API_PTR *PFNGLPUSHCLIENTATTRIBPROC)(GLbitfield mask);
+typedef void (GLAD_API_PTR *PFNGLPUSHMATRIXPROC)(void);
+typedef void (GLAD_API_PTR *PFNGLPUSHNAMEPROC)(GLuint name);
+typedef void (GLAD_API_PTR *PFNGLQUERYCOUNTERPROC)(GLuint id, GLenum target);
+typedef void (GLAD_API_PTR *PFNGLRASTERPOS2DPROC)(GLdouble x, GLdouble y);
+typedef void (GLAD_API_PTR *PFNGLRASTERPOS2DVPROC)(const GLdouble * v);
+typedef void (GLAD_API_PTR *PFNGLRASTERPOS2FPROC)(GLfloat x, GLfloat y);
+typedef void (GLAD_API_PTR *PFNGLRASTERPOS2FVPROC)(const GLfloat * v);
+typedef void (GLAD_API_PTR *PFNGLRASTERPOS2IPROC)(GLint x, GLint y);
+typedef void (GLAD_API_PTR *PFNGLRASTERPOS2IVPROC)(const GLint * v);
+typedef void (GLAD_API_PTR *PFNGLRASTERPOS2SPROC)(GLshort x, GLshort y);
+typedef void (GLAD_API_PTR *PFNGLRASTERPOS2SVPROC)(const GLshort * v);
+typedef void (GLAD_API_PTR *PFNGLRASTERPOS3DPROC)(GLdouble x, GLdouble y, GLdouble z);
+typedef void (GLAD_API_PTR *PFNGLRASTERPOS3DVPROC)(const GLdouble * v);
+typedef void (GLAD_API_PTR *PFNGLRASTERPOS3FPROC)(GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAD_API_PTR *PFNGLRASTERPOS3FVPROC)(const GLfloat * v);
+typedef void (GLAD_API_PTR *PFNGLRASTERPOS3IPROC)(GLint x, GLint y, GLint z);
+typedef void (GLAD_API_PTR *PFNGLRASTERPOS3IVPROC)(const GLint * v);
+typedef void (GLAD_API_PTR *PFNGLRASTERPOS3SPROC)(GLshort x, GLshort y, GLshort z);
+typedef void (GLAD_API_PTR *PFNGLRASTERPOS3SVPROC)(const GLshort * v);
+typedef void (GLAD_API_PTR *PFNGLRASTERPOS4DPROC)(GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (GLAD_API_PTR *PFNGLRASTERPOS4DVPROC)(const GLdouble * v);
+typedef void (GLAD_API_PTR *PFNGLRASTERPOS4FPROC)(GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (GLAD_API_PTR *PFNGLRASTERPOS4FVPROC)(const GLfloat * v);
+typedef void (GLAD_API_PTR *PFNGLRASTERPOS4IPROC)(GLint x, GLint y, GLint z, GLint w);
+typedef void (GLAD_API_PTR *PFNGLRASTERPOS4IVPROC)(const GLint * v);
+typedef void (GLAD_API_PTR *PFNGLRASTERPOS4SPROC)(GLshort x, GLshort y, GLshort z, GLshort w);
+typedef void (GLAD_API_PTR *PFNGLRASTERPOS4SVPROC)(const GLshort * v);
+typedef void (GLAD_API_PTR *PFNGLREADBUFFERPROC)(GLenum src);
+typedef void (GLAD_API_PTR *PFNGLREADPIXELSPROC)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void * pixels);
+typedef void (GLAD_API_PTR *PFNGLRECTDPROC)(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2);
+typedef void (GLAD_API_PTR *PFNGLRECTDVPROC)(const GLdouble * v1, const GLdouble * v2);
+typedef void (GLAD_API_PTR *PFNGLRECTFPROC)(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2);
+typedef void (GLAD_API_PTR *PFNGLRECTFVPROC)(const GLfloat * v1, const GLfloat * v2);
+typedef void (GLAD_API_PTR *PFNGLRECTIPROC)(GLint x1, GLint y1, GLint x2, GLint y2);
+typedef void (GLAD_API_PTR *PFNGLRECTIVPROC)(const GLint * v1, const GLint * v2);
+typedef void (GLAD_API_PTR *PFNGLRECTSPROC)(GLshort x1, GLshort y1, GLshort x2, GLshort y2);
+typedef void (GLAD_API_PTR *PFNGLRECTSVPROC)(const GLshort * v1, const GLshort * v2);
+typedef GLint (GLAD_API_PTR *PFNGLRENDERMODEPROC)(GLenum mode);
+typedef void (GLAD_API_PTR *PFNGLRENDERBUFFERSTORAGEPROC)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GLAD_API_PTR *PFNGLRENDERBUFFERSTORAGEEXTPROC)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GLAD_API_PTR *PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GLAD_API_PTR *PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GLAD_API_PTR *PFNGLROTATEDPROC)(GLdouble angle, GLdouble x, GLdouble y, GLdouble z);
+typedef void (GLAD_API_PTR *PFNGLROTATEFPROC)(GLfloat angle, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAD_API_PTR *PFNGLSAMPLECOVERAGEPROC)(GLfloat value, GLboolean invert);
+typedef void (GLAD_API_PTR *PFNGLSAMPLEMASKIPROC)(GLuint maskNumber, GLbitfield mask);
+typedef void (GLAD_API_PTR *PFNGLSAMPLERPARAMETERIIVPROC)(GLuint sampler, GLenum pname, const GLint * param);
+typedef void (GLAD_API_PTR *PFNGLSAMPLERPARAMETERIUIVPROC)(GLuint sampler, GLenum pname, const GLuint * param);
+typedef void (GLAD_API_PTR *PFNGLSAMPLERPARAMETERFPROC)(GLuint sampler, GLenum pname, GLfloat param);
+typedef void (GLAD_API_PTR *PFNGLSAMPLERPARAMETERFVPROC)(GLuint sampler, GLenum pname, const GLfloat * param);
+typedef void (GLAD_API_PTR *PFNGLSAMPLERPARAMETERIPROC)(GLuint sampler, GLenum pname, GLint param);
+typedef void (GLAD_API_PTR *PFNGLSAMPLERPARAMETERIVPROC)(GLuint sampler, GLenum pname, const GLint * param);
+typedef void (GLAD_API_PTR *PFNGLSCALEDPROC)(GLdouble x, GLdouble y, GLdouble z);
+typedef void (GLAD_API_PTR *PFNGLSCALEFPROC)(GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAD_API_PTR *PFNGLSCISSORPROC)(GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLOR3BPROC)(GLbyte red, GLbyte green, GLbyte blue);
+typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLOR3BVPROC)(const GLbyte * v);
+typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLOR3DPROC)(GLdouble red, GLdouble green, GLdouble blue);
+typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLOR3DVPROC)(const GLdouble * v);
+typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLOR3FPROC)(GLfloat red, GLfloat green, GLfloat blue);
+typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLOR3FVPROC)(const GLfloat * v);
+typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLOR3IPROC)(GLint red, GLint green, GLint blue);
+typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLOR3IVPROC)(const GLint * v);
+typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLOR3SPROC)(GLshort red, GLshort green, GLshort blue);
+typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLOR3SVPROC)(const GLshort * v);
+typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLOR3UBPROC)(GLubyte red, GLubyte green, GLubyte blue);
+typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLOR3UBVPROC)(const GLubyte * v);
+typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLOR3UIPROC)(GLuint red, GLuint green, GLuint blue);
+typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLOR3UIVPROC)(const GLuint * v);
+typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLOR3USPROC)(GLushort red, GLushort green, GLushort blue);
+typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLOR3USVPROC)(const GLushort * v);
+typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLORP3UIPROC)(GLenum type, GLuint color);
+typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLORP3UIVPROC)(GLenum type, const GLuint * color);
+typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLORPOINTERPROC)(GLint size, GLenum type, GLsizei stride, const void * pointer);
+typedef void (GLAD_API_PTR *PFNGLSELECTBUFFERPROC)(GLsizei size, GLuint * buffer);
+typedef void (GLAD_API_PTR *PFNGLSHADEMODELPROC)(GLenum mode);
+typedef void (GLAD_API_PTR *PFNGLSHADERSOURCEPROC)(GLuint shader, GLsizei count, const GLchar *const* string, const GLint * length);
+typedef void (GLAD_API_PTR *PFNGLSTENCILFUNCPROC)(GLenum func, GLint ref, GLuint mask);
+typedef void (GLAD_API_PTR *PFNGLSTENCILFUNCSEPARATEPROC)(GLenum face, GLenum func, GLint ref, GLuint mask);
+typedef void (GLAD_API_PTR *PFNGLSTENCILMASKPROC)(GLuint mask);
+typedef void (GLAD_API_PTR *PFNGLSTENCILMASKSEPARATEPROC)(GLenum face, GLuint mask);
+typedef void (GLAD_API_PTR *PFNGLSTENCILOPPROC)(GLenum fail, GLenum zfail, GLenum zpass);
+typedef void (GLAD_API_PTR *PFNGLSTENCILOPSEPARATEPROC)(GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);
+typedef void (GLAD_API_PTR *PFNGLTEXBUFFERPROC)(GLenum target, GLenum internalformat, GLuint buffer);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD1DPROC)(GLdouble s);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD1DVPROC)(const GLdouble * v);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD1FPROC)(GLfloat s);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD1FVPROC)(const GLfloat * v);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD1IPROC)(GLint s);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD1IVPROC)(const GLint * v);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD1SPROC)(GLshort s);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD1SVPROC)(const GLshort * v);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD2DPROC)(GLdouble s, GLdouble t);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD2DVPROC)(const GLdouble * v);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD2FPROC)(GLfloat s, GLfloat t);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD2FVPROC)(const GLfloat * v);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD2IPROC)(GLint s, GLint t);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD2IVPROC)(const GLint * v);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD2SPROC)(GLshort s, GLshort t);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD2SVPROC)(const GLshort * v);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD3DPROC)(GLdouble s, GLdouble t, GLdouble r);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD3DVPROC)(const GLdouble * v);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD3FPROC)(GLfloat s, GLfloat t, GLfloat r);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD3FVPROC)(const GLfloat * v);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD3IPROC)(GLint s, GLint t, GLint r);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD3IVPROC)(const GLint * v);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD3SPROC)(GLshort s, GLshort t, GLshort r);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD3SVPROC)(const GLshort * v);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD4DPROC)(GLdouble s, GLdouble t, GLdouble r, GLdouble q);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD4DVPROC)(const GLdouble * v);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD4FPROC)(GLfloat s, GLfloat t, GLfloat r, GLfloat q);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD4FVPROC)(const GLfloat * v);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD4IPROC)(GLint s, GLint t, GLint r, GLint q);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD4IVPROC)(const GLint * v);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD4SPROC)(GLshort s, GLshort t, GLshort r, GLshort q);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD4SVPROC)(const GLshort * v);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORDP1UIPROC)(GLenum type, GLuint coords);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORDP1UIVPROC)(GLenum type, const GLuint * coords);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORDP2UIPROC)(GLenum type, GLuint coords);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORDP2UIVPROC)(GLenum type, const GLuint * coords);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORDP3UIPROC)(GLenum type, GLuint coords);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORDP3UIVPROC)(GLenum type, const GLuint * coords);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORDP4UIPROC)(GLenum type, GLuint coords);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORDP4UIVPROC)(GLenum type, const GLuint * coords);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORDPOINTERPROC)(GLint size, GLenum type, GLsizei stride, const void * pointer);
+typedef void (GLAD_API_PTR *PFNGLTEXENVFPROC)(GLenum target, GLenum pname, GLfloat param);
+typedef void (GLAD_API_PTR *PFNGLTEXENVFVPROC)(GLenum target, GLenum pname, const GLfloat * params);
+typedef void (GLAD_API_PTR *PFNGLTEXENVIPROC)(GLenum target, GLenum pname, GLint param);
+typedef void (GLAD_API_PTR *PFNGLTEXENVIVPROC)(GLenum target, GLenum pname, const GLint * params);
+typedef void (GLAD_API_PTR *PFNGLTEXGENDPROC)(GLenum coord, GLenum pname, GLdouble param);
+typedef void (GLAD_API_PTR *PFNGLTEXGENDVPROC)(GLenum coord, GLenum pname, const GLdouble * params);
+typedef void (GLAD_API_PTR *PFNGLTEXGENFPROC)(GLenum coord, GLenum pname, GLfloat param);
+typedef void (GLAD_API_PTR *PFNGLTEXGENFVPROC)(GLenum coord, GLenum pname, const GLfloat * params);
+typedef void (GLAD_API_PTR *PFNGLTEXGENIPROC)(GLenum coord, GLenum pname, GLint param);
+typedef void (GLAD_API_PTR *PFNGLTEXGENIVPROC)(GLenum coord, GLenum pname, const GLint * params);
+typedef void (GLAD_API_PTR *PFNGLTEXIMAGE1DPROC)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const void * pixels);
+typedef void (GLAD_API_PTR *PFNGLTEXIMAGE2DPROC)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void * pixels);
+typedef void (GLAD_API_PTR *PFNGLTEXIMAGE2DMULTISAMPLEPROC)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations);
+typedef void (GLAD_API_PTR *PFNGLTEXIMAGE3DPROC)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void * pixels);
+typedef void (GLAD_API_PTR *PFNGLTEXIMAGE3DMULTISAMPLEPROC)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations);
+typedef void (GLAD_API_PTR *PFNGLTEXPARAMETERIIVPROC)(GLenum target, GLenum pname, const GLint * params);
+typedef void (GLAD_API_PTR *PFNGLTEXPARAMETERIUIVPROC)(GLenum target, GLenum pname, const GLuint * params);
+typedef void (GLAD_API_PTR *PFNGLTEXPARAMETERFPROC)(GLenum target, GLenum pname, GLfloat param);
+typedef void (GLAD_API_PTR *PFNGLTEXPARAMETERFVPROC)(GLenum target, GLenum pname, const GLfloat * params);
+typedef void (GLAD_API_PTR *PFNGLTEXPARAMETERIPROC)(GLenum target, GLenum pname, GLint param);
+typedef void (GLAD_API_PTR *PFNGLTEXPARAMETERIVPROC)(GLenum target, GLenum pname, const GLint * params);
+typedef void (GLAD_API_PTR *PFNGLTEXSUBIMAGE1DPROC)(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void * pixels);
+typedef void (GLAD_API_PTR *PFNGLTEXSUBIMAGE2DPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void * pixels);
+typedef void (GLAD_API_PTR *PFNGLTEXSUBIMAGE3DPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void * pixels);
+typedef void (GLAD_API_PTR *PFNGLTRANSFORMFEEDBACKVARYINGSPROC)(GLuint program, GLsizei count, const GLchar *const* varyings, GLenum bufferMode);
+typedef void (GLAD_API_PTR *PFNGLTRANSLATEDPROC)(GLdouble x, GLdouble y, GLdouble z);
+typedef void (GLAD_API_PTR *PFNGLTRANSLATEFPROC)(GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM1FPROC)(GLint location, GLfloat v0);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM1FVPROC)(GLint location, GLsizei count, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM1IPROC)(GLint location, GLint v0);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM1IVPROC)(GLint location, GLsizei count, const GLint * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM1UIPROC)(GLint location, GLuint v0);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM1UIVPROC)(GLint location, GLsizei count, const GLuint * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM2FPROC)(GLint location, GLfloat v0, GLfloat v1);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM2FVPROC)(GLint location, GLsizei count, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM2IPROC)(GLint location, GLint v0, GLint v1);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM2IVPROC)(GLint location, GLsizei count, const GLint * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM2UIPROC)(GLint location, GLuint v0, GLuint v1);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM2UIVPROC)(GLint location, GLsizei count, const GLuint * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM3FPROC)(GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM3FVPROC)(GLint location, GLsizei count, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM3IPROC)(GLint location, GLint v0, GLint v1, GLint v2);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM3IVPROC)(GLint location, GLsizei count, const GLint * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM3UIPROC)(GLint location, GLuint v0, GLuint v1, GLuint v2);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM3UIVPROC)(GLint location, GLsizei count, const GLuint * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM4FPROC)(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM4FVPROC)(GLint location, GLsizei count, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM4IPROC)(GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM4IVPROC)(GLint location, GLsizei count, const GLint * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM4UIPROC)(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM4UIVPROC)(GLint location, GLsizei count, const GLuint * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORMBLOCKBINDINGPROC)(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding);
+typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX2FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX2X3FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX2X4FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX3FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX3X2FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX3X4FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX4FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX4X2FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX4X3FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
+typedef GLboolean (GLAD_API_PTR *PFNGLUNMAPBUFFERPROC)(GLenum target);
+typedef void (GLAD_API_PTR *PFNGLUSEPROGRAMPROC)(GLuint program);
+typedef void (GLAD_API_PTR *PFNGLVALIDATEPROGRAMPROC)(GLuint program);
+typedef void (GLAD_API_PTR *PFNGLVERTEX2DPROC)(GLdouble x, GLdouble y);
+typedef void (GLAD_API_PTR *PFNGLVERTEX2DVPROC)(const GLdouble * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEX2FPROC)(GLfloat x, GLfloat y);
+typedef void (GLAD_API_PTR *PFNGLVERTEX2FVPROC)(const GLfloat * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEX2IPROC)(GLint x, GLint y);
+typedef void (GLAD_API_PTR *PFNGLVERTEX2IVPROC)(const GLint * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEX2SPROC)(GLshort x, GLshort y);
+typedef void (GLAD_API_PTR *PFNGLVERTEX2SVPROC)(const GLshort * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEX3DPROC)(GLdouble x, GLdouble y, GLdouble z);
+typedef void (GLAD_API_PTR *PFNGLVERTEX3DVPROC)(const GLdouble * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEX3FPROC)(GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAD_API_PTR *PFNGLVERTEX3FVPROC)(const GLfloat * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEX3IPROC)(GLint x, GLint y, GLint z);
+typedef void (GLAD_API_PTR *PFNGLVERTEX3IVPROC)(const GLint * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEX3SPROC)(GLshort x, GLshort y, GLshort z);
+typedef void (GLAD_API_PTR *PFNGLVERTEX3SVPROC)(const GLshort * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEX4DPROC)(GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (GLAD_API_PTR *PFNGLVERTEX4DVPROC)(const GLdouble * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEX4FPROC)(GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (GLAD_API_PTR *PFNGLVERTEX4FVPROC)(const GLfloat * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEX4IPROC)(GLint x, GLint y, GLint z, GLint w);
+typedef void (GLAD_API_PTR *PFNGLVERTEX4IVPROC)(const GLint * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEX4SPROC)(GLshort x, GLshort y, GLshort z, GLshort w);
+typedef void (GLAD_API_PTR *PFNGLVERTEX4SVPROC)(const GLshort * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1DPROC)(GLuint index, GLdouble x);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1DVPROC)(GLuint index, const GLdouble * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1FPROC)(GLuint index, GLfloat x);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1FVPROC)(GLuint index, const GLfloat * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1SPROC)(GLuint index, GLshort x);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1SVPROC)(GLuint index, const GLshort * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2DPROC)(GLuint index, GLdouble x, GLdouble y);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2DVPROC)(GLuint index, const GLdouble * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2FPROC)(GLuint index, GLfloat x, GLfloat y);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2FVPROC)(GLuint index, const GLfloat * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2SPROC)(GLuint index, GLshort x, GLshort y);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2SVPROC)(GLuint index, const GLshort * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3DPROC)(GLuint index, GLdouble x, GLdouble y, GLdouble z);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3DVPROC)(GLuint index, const GLdouble * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3FPROC)(GLuint index, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3FVPROC)(GLuint index, const GLfloat * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3SPROC)(GLuint index, GLshort x, GLshort y, GLshort z);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3SVPROC)(GLuint index, const GLshort * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4NBVPROC)(GLuint index, const GLbyte * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4NIVPROC)(GLuint index, const GLint * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4NSVPROC)(GLuint index, const GLshort * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4NUBPROC)(GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4NUBVPROC)(GLuint index, const GLubyte * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4NUIVPROC)(GLuint index, const GLuint * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4NUSVPROC)(GLuint index, const GLushort * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4BVPROC)(GLuint index, const GLbyte * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4DPROC)(GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4DVPROC)(GLuint index, const GLdouble * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4FPROC)(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4FVPROC)(GLuint index, const GLfloat * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4IVPROC)(GLuint index, const GLint * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4SPROC)(GLuint index, GLshort x, GLshort y, GLshort z, GLshort w);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4SVPROC)(GLuint index, const GLshort * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4UBVPROC)(GLuint index, const GLubyte * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4UIVPROC)(GLuint index, const GLuint * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4USVPROC)(GLuint index, const GLushort * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBDIVISORPROC)(GLuint index, GLuint divisor);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI1IPROC)(GLuint index, GLint x);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI1IVPROC)(GLuint index, const GLint * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI1UIPROC)(GLuint index, GLuint x);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI1UIVPROC)(GLuint index, const GLuint * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI2IPROC)(GLuint index, GLint x, GLint y);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI2IVPROC)(GLuint index, const GLint * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI2UIPROC)(GLuint index, GLuint x, GLuint y);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI2UIVPROC)(GLuint index, const GLuint * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI3IPROC)(GLuint index, GLint x, GLint y, GLint z);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI3IVPROC)(GLuint index, const GLint * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI3UIPROC)(GLuint index, GLuint x, GLuint y, GLuint z);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI3UIVPROC)(GLuint index, const GLuint * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4BVPROC)(GLuint index, const GLbyte * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4IPROC)(GLuint index, GLint x, GLint y, GLint z, GLint w);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4IVPROC)(GLuint index, const GLint * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4SVPROC)(GLuint index, const GLshort * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4UBVPROC)(GLuint index, const GLubyte * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4UIPROC)(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4UIVPROC)(GLuint index, const GLuint * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4USVPROC)(GLuint index, const GLushort * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBIPOINTERPROC)(GLuint index, GLint size, GLenum type, GLsizei stride, const void * pointer);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBP1UIPROC)(GLuint index, GLenum type, GLboolean normalized, GLuint value);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBP1UIVPROC)(GLuint index, GLenum type, GLboolean normalized, const GLuint * value);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBP2UIPROC)(GLuint index, GLenum type, GLboolean normalized, GLuint value);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBP2UIVPROC)(GLuint index, GLenum type, GLboolean normalized, const GLuint * value);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBP3UIPROC)(GLuint index, GLenum type, GLboolean normalized, GLuint value);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBP3UIVPROC)(GLuint index, GLenum type, GLboolean normalized, const GLuint * value);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBP4UIPROC)(GLuint index, GLenum type, GLboolean normalized, GLuint value);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBP4UIVPROC)(GLuint index, GLenum type, GLboolean normalized, const GLuint * value);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBPOINTERPROC)(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void * pointer);
+typedef void (GLAD_API_PTR *PFNGLVERTEXP2UIPROC)(GLenum type, GLuint value);
+typedef void (GLAD_API_PTR *PFNGLVERTEXP2UIVPROC)(GLenum type, const GLuint * value);
+typedef void (GLAD_API_PTR *PFNGLVERTEXP3UIPROC)(GLenum type, GLuint value);
+typedef void (GLAD_API_PTR *PFNGLVERTEXP3UIVPROC)(GLenum type, const GLuint * value);
+typedef void (GLAD_API_PTR *PFNGLVERTEXP4UIPROC)(GLenum type, GLuint value);
+typedef void (GLAD_API_PTR *PFNGLVERTEXP4UIVPROC)(GLenum type, const GLuint * value);
+typedef void (GLAD_API_PTR *PFNGLVERTEXPOINTERPROC)(GLint size, GLenum type, GLsizei stride, const void * pointer);
+typedef void (GLAD_API_PTR *PFNGLVIEWPORTPROC)(GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GLAD_API_PTR *PFNGLWAITSYNCPROC)(GLsync sync, GLbitfield flags, GLuint64 timeout);
+typedef void (GLAD_API_PTR *PFNGLWINDOWPOS2DPROC)(GLdouble x, GLdouble y);
+typedef void (GLAD_API_PTR *PFNGLWINDOWPOS2DVPROC)(const GLdouble * v);
+typedef void (GLAD_API_PTR *PFNGLWINDOWPOS2FPROC)(GLfloat x, GLfloat y);
+typedef void (GLAD_API_PTR *PFNGLWINDOWPOS2FVPROC)(const GLfloat * v);
+typedef void (GLAD_API_PTR *PFNGLWINDOWPOS2IPROC)(GLint x, GLint y);
+typedef void (GLAD_API_PTR *PFNGLWINDOWPOS2IVPROC)(const GLint * v);
+typedef void (GLAD_API_PTR *PFNGLWINDOWPOS2SPROC)(GLshort x, GLshort y);
+typedef void (GLAD_API_PTR *PFNGLWINDOWPOS2SVPROC)(const GLshort * v);
+typedef void (GLAD_API_PTR *PFNGLWINDOWPOS3DPROC)(GLdouble x, GLdouble y, GLdouble z);
+typedef void (GLAD_API_PTR *PFNGLWINDOWPOS3DVPROC)(const GLdouble * v);
+typedef void (GLAD_API_PTR *PFNGLWINDOWPOS3FPROC)(GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAD_API_PTR *PFNGLWINDOWPOS3FVPROC)(const GLfloat * v);
+typedef void (GLAD_API_PTR *PFNGLWINDOWPOS3IPROC)(GLint x, GLint y, GLint z);
+typedef void (GLAD_API_PTR *PFNGLWINDOWPOS3IVPROC)(const GLint * v);
+typedef void (GLAD_API_PTR *PFNGLWINDOWPOS3SPROC)(GLshort x, GLshort y, GLshort z);
+typedef void (GLAD_API_PTR *PFNGLWINDOWPOS3SVPROC)(const GLshort * v);
+
+GLAD_API_CALL PFNGLACCUMPROC glad_glAccum;
+#define glAccum glad_glAccum
+GLAD_API_CALL PFNGLACTIVETEXTUREPROC glad_glActiveTexture;
+#define glActiveTexture glad_glActiveTexture
+GLAD_API_CALL PFNGLALPHAFUNCPROC glad_glAlphaFunc;
+#define glAlphaFunc glad_glAlphaFunc
+GLAD_API_CALL PFNGLARETEXTURESRESIDENTPROC glad_glAreTexturesResident;
+#define glAreTexturesResident glad_glAreTexturesResident
+GLAD_API_CALL PFNGLARRAYELEMENTPROC glad_glArrayElement;
+#define glArrayElement glad_glArrayElement
+GLAD_API_CALL PFNGLATTACHSHADERPROC glad_glAttachShader;
+#define glAttachShader glad_glAttachShader
+GLAD_API_CALL PFNGLBEGINPROC glad_glBegin;
+#define glBegin glad_glBegin
+GLAD_API_CALL PFNGLBEGINCONDITIONALRENDERPROC glad_glBeginConditionalRender;
+#define glBeginConditionalRender glad_glBeginConditionalRender
+GLAD_API_CALL PFNGLBEGINQUERYPROC glad_glBeginQuery;
+#define glBeginQuery glad_glBeginQuery
+GLAD_API_CALL PFNGLBEGINTRANSFORMFEEDBACKPROC glad_glBeginTransformFeedback;
+#define glBeginTransformFeedback glad_glBeginTransformFeedback
+GLAD_API_CALL PFNGLBINDATTRIBLOCATIONPROC glad_glBindAttribLocation;
+#define glBindAttribLocation glad_glBindAttribLocation
+GLAD_API_CALL PFNGLBINDBUFFERPROC glad_glBindBuffer;
+#define glBindBuffer glad_glBindBuffer
+GLAD_API_CALL PFNGLBINDBUFFERBASEPROC glad_glBindBufferBase;
+#define glBindBufferBase glad_glBindBufferBase
+GLAD_API_CALL PFNGLBINDBUFFERRANGEPROC glad_glBindBufferRange;
+#define glBindBufferRange glad_glBindBufferRange
+GLAD_API_CALL PFNGLBINDFRAGDATALOCATIONPROC glad_glBindFragDataLocation;
+#define glBindFragDataLocation glad_glBindFragDataLocation
+GLAD_API_CALL PFNGLBINDFRAGDATALOCATIONINDEXEDPROC glad_glBindFragDataLocationIndexed;
+#define glBindFragDataLocationIndexed glad_glBindFragDataLocationIndexed
+GLAD_API_CALL PFNGLBINDFRAMEBUFFERPROC glad_glBindFramebuffer;
+#define glBindFramebuffer glad_glBindFramebuffer
+GLAD_API_CALL PFNGLBINDFRAMEBUFFEREXTPROC glad_glBindFramebufferEXT;
+#define glBindFramebufferEXT glad_glBindFramebufferEXT
+GLAD_API_CALL PFNGLBINDRENDERBUFFERPROC glad_glBindRenderbuffer;
+#define glBindRenderbuffer glad_glBindRenderbuffer
+GLAD_API_CALL PFNGLBINDRENDERBUFFEREXTPROC glad_glBindRenderbufferEXT;
+#define glBindRenderbufferEXT glad_glBindRenderbufferEXT
+GLAD_API_CALL PFNGLBINDSAMPLERPROC glad_glBindSampler;
+#define glBindSampler glad_glBindSampler
+GLAD_API_CALL PFNGLBINDTEXTUREPROC glad_glBindTexture;
+#define glBindTexture glad_glBindTexture
+GLAD_API_CALL PFNGLBINDVERTEXARRAYPROC glad_glBindVertexArray;
+#define glBindVertexArray glad_glBindVertexArray
+GLAD_API_CALL PFNGLBITMAPPROC glad_glBitmap;
+#define glBitmap glad_glBitmap
+GLAD_API_CALL PFNGLBLENDCOLORPROC glad_glBlendColor;
+#define glBlendColor glad_glBlendColor
+GLAD_API_CALL PFNGLBLENDEQUATIONPROC glad_glBlendEquation;
+#define glBlendEquation glad_glBlendEquation
+GLAD_API_CALL PFNGLBLENDEQUATIONSEPARATEPROC glad_glBlendEquationSeparate;
+#define glBlendEquationSeparate glad_glBlendEquationSeparate
+GLAD_API_CALL PFNGLBLENDFUNCPROC glad_glBlendFunc;
+#define glBlendFunc glad_glBlendFunc
+GLAD_API_CALL PFNGLBLENDFUNCSEPARATEPROC glad_glBlendFuncSeparate;
+#define glBlendFuncSeparate glad_glBlendFuncSeparate
+GLAD_API_CALL PFNGLBLITFRAMEBUFFERPROC glad_glBlitFramebuffer;
+#define glBlitFramebuffer glad_glBlitFramebuffer
+GLAD_API_CALL PFNGLBLITFRAMEBUFFEREXTPROC glad_glBlitFramebufferEXT;
+#define glBlitFramebufferEXT glad_glBlitFramebufferEXT
+GLAD_API_CALL PFNGLBUFFERDATAPROC glad_glBufferData;
+#define glBufferData glad_glBufferData
+GLAD_API_CALL PFNGLBUFFERSUBDATAPROC glad_glBufferSubData;
+#define glBufferSubData glad_glBufferSubData
+GLAD_API_CALL PFNGLCALLLISTPROC glad_glCallList;
+#define glCallList glad_glCallList
+GLAD_API_CALL PFNGLCALLLISTSPROC glad_glCallLists;
+#define glCallLists glad_glCallLists
+GLAD_API_CALL PFNGLCHECKFRAMEBUFFERSTATUSPROC glad_glCheckFramebufferStatus;
+#define glCheckFramebufferStatus glad_glCheckFramebufferStatus
+GLAD_API_CALL PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC glad_glCheckFramebufferStatusEXT;
+#define glCheckFramebufferStatusEXT glad_glCheckFramebufferStatusEXT
+GLAD_API_CALL PFNGLCLAMPCOLORPROC glad_glClampColor;
+#define glClampColor glad_glClampColor
+GLAD_API_CALL PFNGLCLEARPROC glad_glClear;
+#define glClear glad_glClear
+GLAD_API_CALL PFNGLCLEARACCUMPROC glad_glClearAccum;
+#define glClearAccum glad_glClearAccum
+GLAD_API_CALL PFNGLCLEARBUFFERFIPROC glad_glClearBufferfi;
+#define glClearBufferfi glad_glClearBufferfi
+GLAD_API_CALL PFNGLCLEARBUFFERFVPROC glad_glClearBufferfv;
+#define glClearBufferfv glad_glClearBufferfv
+GLAD_API_CALL PFNGLCLEARBUFFERIVPROC glad_glClearBufferiv;
+#define glClearBufferiv glad_glClearBufferiv
+GLAD_API_CALL PFNGLCLEARBUFFERUIVPROC glad_glClearBufferuiv;
+#define glClearBufferuiv glad_glClearBufferuiv
+GLAD_API_CALL PFNGLCLEARCOLORPROC glad_glClearColor;
+#define glClearColor glad_glClearColor
+GLAD_API_CALL PFNGLCLEARDEPTHPROC glad_glClearDepth;
+#define glClearDepth glad_glClearDepth
+GLAD_API_CALL PFNGLCLEARINDEXPROC glad_glClearIndex;
+#define glClearIndex glad_glClearIndex
+GLAD_API_CALL PFNGLCLEARSTENCILPROC glad_glClearStencil;
+#define glClearStencil glad_glClearStencil
+GLAD_API_CALL PFNGLCLIENTACTIVETEXTUREPROC glad_glClientActiveTexture;
+#define glClientActiveTexture glad_glClientActiveTexture
+GLAD_API_CALL PFNGLCLIENTWAITSYNCPROC glad_glClientWaitSync;
+#define glClientWaitSync glad_glClientWaitSync
+GLAD_API_CALL PFNGLCLIPPLANEPROC glad_glClipPlane;
+#define glClipPlane glad_glClipPlane
+GLAD_API_CALL PFNGLCOLOR3BPROC glad_glColor3b;
+#define glColor3b glad_glColor3b
+GLAD_API_CALL PFNGLCOLOR3BVPROC glad_glColor3bv;
+#define glColor3bv glad_glColor3bv
+GLAD_API_CALL PFNGLCOLOR3DPROC glad_glColor3d;
+#define glColor3d glad_glColor3d
+GLAD_API_CALL PFNGLCOLOR3DVPROC glad_glColor3dv;
+#define glColor3dv glad_glColor3dv
+GLAD_API_CALL PFNGLCOLOR3FPROC glad_glColor3f;
+#define glColor3f glad_glColor3f
+GLAD_API_CALL PFNGLCOLOR3FVPROC glad_glColor3fv;
+#define glColor3fv glad_glColor3fv
+GLAD_API_CALL PFNGLCOLOR3IPROC glad_glColor3i;
+#define glColor3i glad_glColor3i
+GLAD_API_CALL PFNGLCOLOR3IVPROC glad_glColor3iv;
+#define glColor3iv glad_glColor3iv
+GLAD_API_CALL PFNGLCOLOR3SPROC glad_glColor3s;
+#define glColor3s glad_glColor3s
+GLAD_API_CALL PFNGLCOLOR3SVPROC glad_glColor3sv;
+#define glColor3sv glad_glColor3sv
+GLAD_API_CALL PFNGLCOLOR3UBPROC glad_glColor3ub;
+#define glColor3ub glad_glColor3ub
+GLAD_API_CALL PFNGLCOLOR3UBVPROC glad_glColor3ubv;
+#define glColor3ubv glad_glColor3ubv
+GLAD_API_CALL PFNGLCOLOR3UIPROC glad_glColor3ui;
+#define glColor3ui glad_glColor3ui
+GLAD_API_CALL PFNGLCOLOR3UIVPROC glad_glColor3uiv;
+#define glColor3uiv glad_glColor3uiv
+GLAD_API_CALL PFNGLCOLOR3USPROC glad_glColor3us;
+#define glColor3us glad_glColor3us
+GLAD_API_CALL PFNGLCOLOR3USVPROC glad_glColor3usv;
+#define glColor3usv glad_glColor3usv
+GLAD_API_CALL PFNGLCOLOR4BPROC glad_glColor4b;
+#define glColor4b glad_glColor4b
+GLAD_API_CALL PFNGLCOLOR4BVPROC glad_glColor4bv;
+#define glColor4bv glad_glColor4bv
+GLAD_API_CALL PFNGLCOLOR4DPROC glad_glColor4d;
+#define glColor4d glad_glColor4d
+GLAD_API_CALL PFNGLCOLOR4DVPROC glad_glColor4dv;
+#define glColor4dv glad_glColor4dv
+GLAD_API_CALL PFNGLCOLOR4FPROC glad_glColor4f;
+#define glColor4f glad_glColor4f
+GLAD_API_CALL PFNGLCOLOR4FVPROC glad_glColor4fv;
+#define glColor4fv glad_glColor4fv
+GLAD_API_CALL PFNGLCOLOR4IPROC glad_glColor4i;
+#define glColor4i glad_glColor4i
+GLAD_API_CALL PFNGLCOLOR4IVPROC glad_glColor4iv;
+#define glColor4iv glad_glColor4iv
+GLAD_API_CALL PFNGLCOLOR4SPROC glad_glColor4s;
+#define glColor4s glad_glColor4s
+GLAD_API_CALL PFNGLCOLOR4SVPROC glad_glColor4sv;
+#define glColor4sv glad_glColor4sv
+GLAD_API_CALL PFNGLCOLOR4UBPROC glad_glColor4ub;
+#define glColor4ub glad_glColor4ub
+GLAD_API_CALL PFNGLCOLOR4UBVPROC glad_glColor4ubv;
+#define glColor4ubv glad_glColor4ubv
+GLAD_API_CALL PFNGLCOLOR4UIPROC glad_glColor4ui;
+#define glColor4ui glad_glColor4ui
+GLAD_API_CALL PFNGLCOLOR4UIVPROC glad_glColor4uiv;
+#define glColor4uiv glad_glColor4uiv
+GLAD_API_CALL PFNGLCOLOR4USPROC glad_glColor4us;
+#define glColor4us glad_glColor4us
+GLAD_API_CALL PFNGLCOLOR4USVPROC glad_glColor4usv;
+#define glColor4usv glad_glColor4usv
+GLAD_API_CALL PFNGLCOLORMASKPROC glad_glColorMask;
+#define glColorMask glad_glColorMask
+GLAD_API_CALL PFNGLCOLORMASKIPROC glad_glColorMaski;
+#define glColorMaski glad_glColorMaski
+GLAD_API_CALL PFNGLCOLORMATERIALPROC glad_glColorMaterial;
+#define glColorMaterial glad_glColorMaterial
+GLAD_API_CALL PFNGLCOLORP3UIPROC glad_glColorP3ui;
+#define glColorP3ui glad_glColorP3ui
+GLAD_API_CALL PFNGLCOLORP3UIVPROC glad_glColorP3uiv;
+#define glColorP3uiv glad_glColorP3uiv
+GLAD_API_CALL PFNGLCOLORP4UIPROC glad_glColorP4ui;
+#define glColorP4ui glad_glColorP4ui
+GLAD_API_CALL PFNGLCOLORP4UIVPROC glad_glColorP4uiv;
+#define glColorP4uiv glad_glColorP4uiv
+GLAD_API_CALL PFNGLCOLORPOINTERPROC glad_glColorPointer;
+#define glColorPointer glad_glColorPointer
+GLAD_API_CALL PFNGLCOMPILESHADERPROC glad_glCompileShader;
+#define glCompileShader glad_glCompileShader
+GLAD_API_CALL PFNGLCOMPRESSEDTEXIMAGE1DPROC glad_glCompressedTexImage1D;
+#define glCompressedTexImage1D glad_glCompressedTexImage1D
+GLAD_API_CALL PFNGLCOMPRESSEDTEXIMAGE2DPROC glad_glCompressedTexImage2D;
+#define glCompressedTexImage2D glad_glCompressedTexImage2D
+GLAD_API_CALL PFNGLCOMPRESSEDTEXIMAGE3DPROC glad_glCompressedTexImage3D;
+#define glCompressedTexImage3D glad_glCompressedTexImage3D
+GLAD_API_CALL PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC glad_glCompressedTexSubImage1D;
+#define glCompressedTexSubImage1D glad_glCompressedTexSubImage1D
+GLAD_API_CALL PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC glad_glCompressedTexSubImage2D;
+#define glCompressedTexSubImage2D glad_glCompressedTexSubImage2D
+GLAD_API_CALL PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC glad_glCompressedTexSubImage3D;
+#define glCompressedTexSubImage3D glad_glCompressedTexSubImage3D
+GLAD_API_CALL PFNGLCOPYBUFFERSUBDATAPROC glad_glCopyBufferSubData;
+#define glCopyBufferSubData glad_glCopyBufferSubData
+GLAD_API_CALL PFNGLCOPYPIXELSPROC glad_glCopyPixels;
+#define glCopyPixels glad_glCopyPixels
+GLAD_API_CALL PFNGLCOPYTEXIMAGE1DPROC glad_glCopyTexImage1D;
+#define glCopyTexImage1D glad_glCopyTexImage1D
+GLAD_API_CALL PFNGLCOPYTEXIMAGE2DPROC glad_glCopyTexImage2D;
+#define glCopyTexImage2D glad_glCopyTexImage2D
+GLAD_API_CALL PFNGLCOPYTEXSUBIMAGE1DPROC glad_glCopyTexSubImage1D;
+#define glCopyTexSubImage1D glad_glCopyTexSubImage1D
+GLAD_API_CALL PFNGLCOPYTEXSUBIMAGE2DPROC glad_glCopyTexSubImage2D;
+#define glCopyTexSubImage2D glad_glCopyTexSubImage2D
+GLAD_API_CALL PFNGLCOPYTEXSUBIMAGE3DPROC glad_glCopyTexSubImage3D;
+#define glCopyTexSubImage3D glad_glCopyTexSubImage3D
+GLAD_API_CALL PFNGLCREATEPROGRAMPROC glad_glCreateProgram;
+#define glCreateProgram glad_glCreateProgram
+GLAD_API_CALL PFNGLCREATESHADERPROC glad_glCreateShader;
+#define glCreateShader glad_glCreateShader
+GLAD_API_CALL PFNGLCULLFACEPROC glad_glCullFace;
+#define glCullFace glad_glCullFace
+GLAD_API_CALL PFNGLDEBUGMESSAGECALLBACKARBPROC glad_glDebugMessageCallbackARB;
+#define glDebugMessageCallbackARB glad_glDebugMessageCallbackARB
+GLAD_API_CALL PFNGLDEBUGMESSAGECONTROLARBPROC glad_glDebugMessageControlARB;
+#define glDebugMessageControlARB glad_glDebugMessageControlARB
+GLAD_API_CALL PFNGLDEBUGMESSAGEINSERTARBPROC glad_glDebugMessageInsertARB;
+#define glDebugMessageInsertARB glad_glDebugMessageInsertARB
+GLAD_API_CALL PFNGLDELETEBUFFERSPROC glad_glDeleteBuffers;
+#define glDeleteBuffers glad_glDeleteBuffers
+GLAD_API_CALL PFNGLDELETEFRAMEBUFFERSPROC glad_glDeleteFramebuffers;
+#define glDeleteFramebuffers glad_glDeleteFramebuffers
+GLAD_API_CALL PFNGLDELETEFRAMEBUFFERSEXTPROC glad_glDeleteFramebuffersEXT;
+#define glDeleteFramebuffersEXT glad_glDeleteFramebuffersEXT
+GLAD_API_CALL PFNGLDELETELISTSPROC glad_glDeleteLists;
+#define glDeleteLists glad_glDeleteLists
+GLAD_API_CALL PFNGLDELETEPROGRAMPROC glad_glDeleteProgram;
+#define glDeleteProgram glad_glDeleteProgram
+GLAD_API_CALL PFNGLDELETEQUERIESPROC glad_glDeleteQueries;
+#define glDeleteQueries glad_glDeleteQueries
+GLAD_API_CALL PFNGLDELETERENDERBUFFERSPROC glad_glDeleteRenderbuffers;
+#define glDeleteRenderbuffers glad_glDeleteRenderbuffers
+GLAD_API_CALL PFNGLDELETERENDERBUFFERSEXTPROC glad_glDeleteRenderbuffersEXT;
+#define glDeleteRenderbuffersEXT glad_glDeleteRenderbuffersEXT
+GLAD_API_CALL PFNGLDELETESAMPLERSPROC glad_glDeleteSamplers;
+#define glDeleteSamplers glad_glDeleteSamplers
+GLAD_API_CALL PFNGLDELETESHADERPROC glad_glDeleteShader;
+#define glDeleteShader glad_glDeleteShader
+GLAD_API_CALL PFNGLDELETESYNCPROC glad_glDeleteSync;
+#define glDeleteSync glad_glDeleteSync
+GLAD_API_CALL PFNGLDELETETEXTURESPROC glad_glDeleteTextures;
+#define glDeleteTextures glad_glDeleteTextures
+GLAD_API_CALL PFNGLDELETEVERTEXARRAYSPROC glad_glDeleteVertexArrays;
+#define glDeleteVertexArrays glad_glDeleteVertexArrays
+GLAD_API_CALL PFNGLDEPTHFUNCPROC glad_glDepthFunc;
+#define glDepthFunc glad_glDepthFunc
+GLAD_API_CALL PFNGLDEPTHMASKPROC glad_glDepthMask;
+#define glDepthMask glad_glDepthMask
+GLAD_API_CALL PFNGLDEPTHRANGEPROC glad_glDepthRange;
+#define glDepthRange glad_glDepthRange
+GLAD_API_CALL PFNGLDETACHSHADERPROC glad_glDetachShader;
+#define glDetachShader glad_glDetachShader
+GLAD_API_CALL PFNGLDISABLEPROC glad_glDisable;
+#define glDisable glad_glDisable
+GLAD_API_CALL PFNGLDISABLECLIENTSTATEPROC glad_glDisableClientState;
+#define glDisableClientState glad_glDisableClientState
+GLAD_API_CALL PFNGLDISABLEVERTEXATTRIBARRAYPROC glad_glDisableVertexAttribArray;
+#define glDisableVertexAttribArray glad_glDisableVertexAttribArray
+GLAD_API_CALL PFNGLDISABLEIPROC glad_glDisablei;
+#define glDisablei glad_glDisablei
+GLAD_API_CALL PFNGLDRAWARRAYSPROC glad_glDrawArrays;
+#define glDrawArrays glad_glDrawArrays
+GLAD_API_CALL PFNGLDRAWARRAYSINSTANCEDPROC glad_glDrawArraysInstanced;
+#define glDrawArraysInstanced glad_glDrawArraysInstanced
+GLAD_API_CALL PFNGLDRAWBUFFERPROC glad_glDrawBuffer;
+#define glDrawBuffer glad_glDrawBuffer
+GLAD_API_CALL PFNGLDRAWBUFFERSPROC glad_glDrawBuffers;
+#define glDrawBuffers glad_glDrawBuffers
+GLAD_API_CALL PFNGLDRAWELEMENTSPROC glad_glDrawElements;
+#define glDrawElements glad_glDrawElements
+GLAD_API_CALL PFNGLDRAWELEMENTSBASEVERTEXPROC glad_glDrawElementsBaseVertex;
+#define glDrawElementsBaseVertex glad_glDrawElementsBaseVertex
+GLAD_API_CALL PFNGLDRAWELEMENTSINSTANCEDPROC glad_glDrawElementsInstanced;
+#define glDrawElementsInstanced glad_glDrawElementsInstanced
+GLAD_API_CALL PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC glad_glDrawElementsInstancedBaseVertex;
+#define glDrawElementsInstancedBaseVertex glad_glDrawElementsInstancedBaseVertex
+GLAD_API_CALL PFNGLDRAWPIXELSPROC glad_glDrawPixels;
+#define glDrawPixels glad_glDrawPixels
+GLAD_API_CALL PFNGLDRAWRANGEELEMENTSPROC glad_glDrawRangeElements;
+#define glDrawRangeElements glad_glDrawRangeElements
+GLAD_API_CALL PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC glad_glDrawRangeElementsBaseVertex;
+#define glDrawRangeElementsBaseVertex glad_glDrawRangeElementsBaseVertex
+GLAD_API_CALL PFNGLEDGEFLAGPROC glad_glEdgeFlag;
+#define glEdgeFlag glad_glEdgeFlag
+GLAD_API_CALL PFNGLEDGEFLAGPOINTERPROC glad_glEdgeFlagPointer;
+#define glEdgeFlagPointer glad_glEdgeFlagPointer
+GLAD_API_CALL PFNGLEDGEFLAGVPROC glad_glEdgeFlagv;
+#define glEdgeFlagv glad_glEdgeFlagv
+GLAD_API_CALL PFNGLENABLEPROC glad_glEnable;
+#define glEnable glad_glEnable
+GLAD_API_CALL PFNGLENABLECLIENTSTATEPROC glad_glEnableClientState;
+#define glEnableClientState glad_glEnableClientState
+GLAD_API_CALL PFNGLENABLEVERTEXATTRIBARRAYPROC glad_glEnableVertexAttribArray;
+#define glEnableVertexAttribArray glad_glEnableVertexAttribArray
+GLAD_API_CALL PFNGLENABLEIPROC glad_glEnablei;
+#define glEnablei glad_glEnablei
+GLAD_API_CALL PFNGLENDPROC glad_glEnd;
+#define glEnd glad_glEnd
+GLAD_API_CALL PFNGLENDCONDITIONALRENDERPROC glad_glEndConditionalRender;
+#define glEndConditionalRender glad_glEndConditionalRender
+GLAD_API_CALL PFNGLENDLISTPROC glad_glEndList;
+#define glEndList glad_glEndList
+GLAD_API_CALL PFNGLENDQUERYPROC glad_glEndQuery;
+#define glEndQuery glad_glEndQuery
+GLAD_API_CALL PFNGLENDTRANSFORMFEEDBACKPROC glad_glEndTransformFeedback;
+#define glEndTransformFeedback glad_glEndTransformFeedback
+GLAD_API_CALL PFNGLEVALCOORD1DPROC glad_glEvalCoord1d;
+#define glEvalCoord1d glad_glEvalCoord1d
+GLAD_API_CALL PFNGLEVALCOORD1DVPROC glad_glEvalCoord1dv;
+#define glEvalCoord1dv glad_glEvalCoord1dv
+GLAD_API_CALL PFNGLEVALCOORD1FPROC glad_glEvalCoord1f;
+#define glEvalCoord1f glad_glEvalCoord1f
+GLAD_API_CALL PFNGLEVALCOORD1FVPROC glad_glEvalCoord1fv;
+#define glEvalCoord1fv glad_glEvalCoord1fv
+GLAD_API_CALL PFNGLEVALCOORD2DPROC glad_glEvalCoord2d;
+#define glEvalCoord2d glad_glEvalCoord2d
+GLAD_API_CALL PFNGLEVALCOORD2DVPROC glad_glEvalCoord2dv;
+#define glEvalCoord2dv glad_glEvalCoord2dv
+GLAD_API_CALL PFNGLEVALCOORD2FPROC glad_glEvalCoord2f;
+#define glEvalCoord2f glad_glEvalCoord2f
+GLAD_API_CALL PFNGLEVALCOORD2FVPROC glad_glEvalCoord2fv;
+#define glEvalCoord2fv glad_glEvalCoord2fv
+GLAD_API_CALL PFNGLEVALMESH1PROC glad_glEvalMesh1;
+#define glEvalMesh1 glad_glEvalMesh1
+GLAD_API_CALL PFNGLEVALMESH2PROC glad_glEvalMesh2;
+#define glEvalMesh2 glad_glEvalMesh2
+GLAD_API_CALL PFNGLEVALPOINT1PROC glad_glEvalPoint1;
+#define glEvalPoint1 glad_glEvalPoint1
+GLAD_API_CALL PFNGLEVALPOINT2PROC glad_glEvalPoint2;
+#define glEvalPoint2 glad_glEvalPoint2
+GLAD_API_CALL PFNGLFEEDBACKBUFFERPROC glad_glFeedbackBuffer;
+#define glFeedbackBuffer glad_glFeedbackBuffer
+GLAD_API_CALL PFNGLFENCESYNCPROC glad_glFenceSync;
+#define glFenceSync glad_glFenceSync
+GLAD_API_CALL PFNGLFINISHPROC glad_glFinish;
+#define glFinish glad_glFinish
+GLAD_API_CALL PFNGLFLUSHPROC glad_glFlush;
+#define glFlush glad_glFlush
+GLAD_API_CALL PFNGLFLUSHMAPPEDBUFFERRANGEPROC glad_glFlushMappedBufferRange;
+#define glFlushMappedBufferRange glad_glFlushMappedBufferRange
+GLAD_API_CALL PFNGLFOGCOORDPOINTERPROC glad_glFogCoordPointer;
+#define glFogCoordPointer glad_glFogCoordPointer
+GLAD_API_CALL PFNGLFOGCOORDDPROC glad_glFogCoordd;
+#define glFogCoordd glad_glFogCoordd
+GLAD_API_CALL PFNGLFOGCOORDDVPROC glad_glFogCoorddv;
+#define glFogCoorddv glad_glFogCoorddv
+GLAD_API_CALL PFNGLFOGCOORDFPROC glad_glFogCoordf;
+#define glFogCoordf glad_glFogCoordf
+GLAD_API_CALL PFNGLFOGCOORDFVPROC glad_glFogCoordfv;
+#define glFogCoordfv glad_glFogCoordfv
+GLAD_API_CALL PFNGLFOGFPROC glad_glFogf;
+#define glFogf glad_glFogf
+GLAD_API_CALL PFNGLFOGFVPROC glad_glFogfv;
+#define glFogfv glad_glFogfv
+GLAD_API_CALL PFNGLFOGIPROC glad_glFogi;
+#define glFogi glad_glFogi
+GLAD_API_CALL PFNGLFOGIVPROC glad_glFogiv;
+#define glFogiv glad_glFogiv
+GLAD_API_CALL PFNGLFRAMEBUFFERRENDERBUFFERPROC glad_glFramebufferRenderbuffer;
+#define glFramebufferRenderbuffer glad_glFramebufferRenderbuffer
+GLAD_API_CALL PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glad_glFramebufferRenderbufferEXT;
+#define glFramebufferRenderbufferEXT glad_glFramebufferRenderbufferEXT
+GLAD_API_CALL PFNGLFRAMEBUFFERTEXTUREPROC glad_glFramebufferTexture;
+#define glFramebufferTexture glad_glFramebufferTexture
+GLAD_API_CALL PFNGLFRAMEBUFFERTEXTURE1DPROC glad_glFramebufferTexture1D;
+#define glFramebufferTexture1D glad_glFramebufferTexture1D
+GLAD_API_CALL PFNGLFRAMEBUFFERTEXTURE1DEXTPROC glad_glFramebufferTexture1DEXT;
+#define glFramebufferTexture1DEXT glad_glFramebufferTexture1DEXT
+GLAD_API_CALL PFNGLFRAMEBUFFERTEXTURE2DPROC glad_glFramebufferTexture2D;
+#define glFramebufferTexture2D glad_glFramebufferTexture2D
+GLAD_API_CALL PFNGLFRAMEBUFFERTEXTURE2DEXTPROC glad_glFramebufferTexture2DEXT;
+#define glFramebufferTexture2DEXT glad_glFramebufferTexture2DEXT
+GLAD_API_CALL PFNGLFRAMEBUFFERTEXTURE3DPROC glad_glFramebufferTexture3D;
+#define glFramebufferTexture3D glad_glFramebufferTexture3D
+GLAD_API_CALL PFNGLFRAMEBUFFERTEXTURE3DEXTPROC glad_glFramebufferTexture3DEXT;
+#define glFramebufferTexture3DEXT glad_glFramebufferTexture3DEXT
+GLAD_API_CALL PFNGLFRAMEBUFFERTEXTURELAYERPROC glad_glFramebufferTextureLayer;
+#define glFramebufferTextureLayer glad_glFramebufferTextureLayer
+GLAD_API_CALL PFNGLFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC glad_glFramebufferTextureMultiviewOVR;
+#define glFramebufferTextureMultiviewOVR glad_glFramebufferTextureMultiviewOVR
+GLAD_API_CALL PFNGLFRONTFACEPROC glad_glFrontFace;
+#define glFrontFace glad_glFrontFace
+GLAD_API_CALL PFNGLFRUSTUMPROC glad_glFrustum;
+#define glFrustum glad_glFrustum
+GLAD_API_CALL PFNGLGENBUFFERSPROC glad_glGenBuffers;
+#define glGenBuffers glad_glGenBuffers
+GLAD_API_CALL PFNGLGENFRAMEBUFFERSPROC glad_glGenFramebuffers;
+#define glGenFramebuffers glad_glGenFramebuffers
+GLAD_API_CALL PFNGLGENFRAMEBUFFERSEXTPROC glad_glGenFramebuffersEXT;
+#define glGenFramebuffersEXT glad_glGenFramebuffersEXT
+GLAD_API_CALL PFNGLGENLISTSPROC glad_glGenLists;
+#define glGenLists glad_glGenLists
+GLAD_API_CALL PFNGLGENQUERIESPROC glad_glGenQueries;
+#define glGenQueries glad_glGenQueries
+GLAD_API_CALL PFNGLGENRENDERBUFFERSPROC glad_glGenRenderbuffers;
+#define glGenRenderbuffers glad_glGenRenderbuffers
+GLAD_API_CALL PFNGLGENRENDERBUFFERSEXTPROC glad_glGenRenderbuffersEXT;
+#define glGenRenderbuffersEXT glad_glGenRenderbuffersEXT
+GLAD_API_CALL PFNGLGENSAMPLERSPROC glad_glGenSamplers;
+#define glGenSamplers glad_glGenSamplers
+GLAD_API_CALL PFNGLGENTEXTURESPROC glad_glGenTextures;
+#define glGenTextures glad_glGenTextures
+GLAD_API_CALL PFNGLGENVERTEXARRAYSPROC glad_glGenVertexArrays;
+#define glGenVertexArrays glad_glGenVertexArrays
+GLAD_API_CALL PFNGLGENERATEMIPMAPPROC glad_glGenerateMipmap;
+#define glGenerateMipmap glad_glGenerateMipmap
+GLAD_API_CALL PFNGLGENERATEMIPMAPEXTPROC glad_glGenerateMipmapEXT;
+#define glGenerateMipmapEXT glad_glGenerateMipmapEXT
+GLAD_API_CALL PFNGLGETACTIVEATTRIBPROC glad_glGetActiveAttrib;
+#define glGetActiveAttrib glad_glGetActiveAttrib
+GLAD_API_CALL PFNGLGETACTIVEUNIFORMPROC glad_glGetActiveUniform;
+#define glGetActiveUniform glad_glGetActiveUniform
+GLAD_API_CALL PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC glad_glGetActiveUniformBlockName;
+#define glGetActiveUniformBlockName glad_glGetActiveUniformBlockName
+GLAD_API_CALL PFNGLGETACTIVEUNIFORMBLOCKIVPROC glad_glGetActiveUniformBlockiv;
+#define glGetActiveUniformBlockiv glad_glGetActiveUniformBlockiv
+GLAD_API_CALL PFNGLGETACTIVEUNIFORMNAMEPROC glad_glGetActiveUniformName;
+#define glGetActiveUniformName glad_glGetActiveUniformName
+GLAD_API_CALL PFNGLGETACTIVEUNIFORMSIVPROC glad_glGetActiveUniformsiv;
+#define glGetActiveUniformsiv glad_glGetActiveUniformsiv
+GLAD_API_CALL PFNGLGETATTACHEDSHADERSPROC glad_glGetAttachedShaders;
+#define glGetAttachedShaders glad_glGetAttachedShaders
+GLAD_API_CALL PFNGLGETATTRIBLOCATIONPROC glad_glGetAttribLocation;
+#define glGetAttribLocation glad_glGetAttribLocation
+GLAD_API_CALL PFNGLGETBOOLEANI_VPROC glad_glGetBooleani_v;
+#define glGetBooleani_v glad_glGetBooleani_v
+GLAD_API_CALL PFNGLGETBOOLEANVPROC glad_glGetBooleanv;
+#define glGetBooleanv glad_glGetBooleanv
+GLAD_API_CALL PFNGLGETBUFFERPARAMETERI64VPROC glad_glGetBufferParameteri64v;
+#define glGetBufferParameteri64v glad_glGetBufferParameteri64v
+GLAD_API_CALL PFNGLGETBUFFERPARAMETERIVPROC glad_glGetBufferParameteriv;
+#define glGetBufferParameteriv glad_glGetBufferParameteriv
+GLAD_API_CALL PFNGLGETBUFFERPOINTERVPROC glad_glGetBufferPointerv;
+#define glGetBufferPointerv glad_glGetBufferPointerv
+GLAD_API_CALL PFNGLGETBUFFERSUBDATAPROC glad_glGetBufferSubData;
+#define glGetBufferSubData glad_glGetBufferSubData
+GLAD_API_CALL PFNGLGETCLIPPLANEPROC glad_glGetClipPlane;
+#define glGetClipPlane glad_glGetClipPlane
+GLAD_API_CALL PFNGLGETCOMPRESSEDTEXIMAGEPROC glad_glGetCompressedTexImage;
+#define glGetCompressedTexImage glad_glGetCompressedTexImage
+GLAD_API_CALL PFNGLGETDEBUGMESSAGELOGARBPROC glad_glGetDebugMessageLogARB;
+#define glGetDebugMessageLogARB glad_glGetDebugMessageLogARB
+GLAD_API_CALL PFNGLGETDOUBLEVPROC glad_glGetDoublev;
+#define glGetDoublev glad_glGetDoublev
+GLAD_API_CALL PFNGLGETERRORPROC glad_glGetError;
+#define glGetError glad_glGetError
+GLAD_API_CALL PFNGLGETFLOATVPROC glad_glGetFloatv;
+#define glGetFloatv glad_glGetFloatv
+GLAD_API_CALL PFNGLGETFRAGDATAINDEXPROC glad_glGetFragDataIndex;
+#define glGetFragDataIndex glad_glGetFragDataIndex
+GLAD_API_CALL PFNGLGETFRAGDATALOCATIONPROC glad_glGetFragDataLocation;
+#define glGetFragDataLocation glad_glGetFragDataLocation
+GLAD_API_CALL PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC glad_glGetFramebufferAttachmentParameteriv;
+#define glGetFramebufferAttachmentParameteriv glad_glGetFramebufferAttachmentParameteriv
+GLAD_API_CALL PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC glad_glGetFramebufferAttachmentParameterivEXT;
+#define glGetFramebufferAttachmentParameterivEXT glad_glGetFramebufferAttachmentParameterivEXT
+GLAD_API_CALL PFNGLGETINTEGER64I_VPROC glad_glGetInteger64i_v;
+#define glGetInteger64i_v glad_glGetInteger64i_v
+GLAD_API_CALL PFNGLGETINTEGER64VPROC glad_glGetInteger64v;
+#define glGetInteger64v glad_glGetInteger64v
+GLAD_API_CALL PFNGLGETINTEGERI_VPROC glad_glGetIntegeri_v;
+#define glGetIntegeri_v glad_glGetIntegeri_v
+GLAD_API_CALL PFNGLGETINTEGERVPROC glad_glGetIntegerv;
+#define glGetIntegerv glad_glGetIntegerv
+GLAD_API_CALL PFNGLGETLIGHTFVPROC glad_glGetLightfv;
+#define glGetLightfv glad_glGetLightfv
+GLAD_API_CALL PFNGLGETLIGHTIVPROC glad_glGetLightiv;
+#define glGetLightiv glad_glGetLightiv
+GLAD_API_CALL PFNGLGETMAPDVPROC glad_glGetMapdv;
+#define glGetMapdv glad_glGetMapdv
+GLAD_API_CALL PFNGLGETMAPFVPROC glad_glGetMapfv;
+#define glGetMapfv glad_glGetMapfv
+GLAD_API_CALL PFNGLGETMAPIVPROC glad_glGetMapiv;
+#define glGetMapiv glad_glGetMapiv
+GLAD_API_CALL PFNGLGETMATERIALFVPROC glad_glGetMaterialfv;
+#define glGetMaterialfv glad_glGetMaterialfv
+GLAD_API_CALL PFNGLGETMATERIALIVPROC glad_glGetMaterialiv;
+#define glGetMaterialiv glad_glGetMaterialiv
+GLAD_API_CALL PFNGLGETMULTISAMPLEFVPROC glad_glGetMultisamplefv;
+#define glGetMultisamplefv glad_glGetMultisamplefv
+GLAD_API_CALL PFNGLGETPIXELMAPFVPROC glad_glGetPixelMapfv;
+#define glGetPixelMapfv glad_glGetPixelMapfv
+GLAD_API_CALL PFNGLGETPIXELMAPUIVPROC glad_glGetPixelMapuiv;
+#define glGetPixelMapuiv glad_glGetPixelMapuiv
+GLAD_API_CALL PFNGLGETPIXELMAPUSVPROC glad_glGetPixelMapusv;
+#define glGetPixelMapusv glad_glGetPixelMapusv
+GLAD_API_CALL PFNGLGETPOINTERVPROC glad_glGetPointerv;
+#define glGetPointerv glad_glGetPointerv
+GLAD_API_CALL PFNGLGETPOLYGONSTIPPLEPROC glad_glGetPolygonStipple;
+#define glGetPolygonStipple glad_glGetPolygonStipple
+GLAD_API_CALL PFNGLGETPROGRAMINFOLOGPROC glad_glGetProgramInfoLog;
+#define glGetProgramInfoLog glad_glGetProgramInfoLog
+GLAD_API_CALL PFNGLGETPROGRAMIVPROC glad_glGetProgramiv;
+#define glGetProgramiv glad_glGetProgramiv
+GLAD_API_CALL PFNGLGETQUERYOBJECTI64VPROC glad_glGetQueryObjecti64v;
+#define glGetQueryObjecti64v glad_glGetQueryObjecti64v
+GLAD_API_CALL PFNGLGETQUERYOBJECTIVPROC glad_glGetQueryObjectiv;
+#define glGetQueryObjectiv glad_glGetQueryObjectiv
+GLAD_API_CALL PFNGLGETQUERYOBJECTUI64VPROC glad_glGetQueryObjectui64v;
+#define glGetQueryObjectui64v glad_glGetQueryObjectui64v
+GLAD_API_CALL PFNGLGETQUERYOBJECTUIVPROC glad_glGetQueryObjectuiv;
+#define glGetQueryObjectuiv glad_glGetQueryObjectuiv
+GLAD_API_CALL PFNGLGETQUERYIVPROC glad_glGetQueryiv;
+#define glGetQueryiv glad_glGetQueryiv
+GLAD_API_CALL PFNGLGETRENDERBUFFERPARAMETERIVPROC glad_glGetRenderbufferParameteriv;
+#define glGetRenderbufferParameteriv glad_glGetRenderbufferParameteriv
+GLAD_API_CALL PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC glad_glGetRenderbufferParameterivEXT;
+#define glGetRenderbufferParameterivEXT glad_glGetRenderbufferParameterivEXT
+GLAD_API_CALL PFNGLGETSAMPLERPARAMETERIIVPROC glad_glGetSamplerParameterIiv;
+#define glGetSamplerParameterIiv glad_glGetSamplerParameterIiv
+GLAD_API_CALL PFNGLGETSAMPLERPARAMETERIUIVPROC glad_glGetSamplerParameterIuiv;
+#define glGetSamplerParameterIuiv glad_glGetSamplerParameterIuiv
+GLAD_API_CALL PFNGLGETSAMPLERPARAMETERFVPROC glad_glGetSamplerParameterfv;
+#define glGetSamplerParameterfv glad_glGetSamplerParameterfv
+GLAD_API_CALL PFNGLGETSAMPLERPARAMETERIVPROC glad_glGetSamplerParameteriv;
+#define glGetSamplerParameteriv glad_glGetSamplerParameteriv
+GLAD_API_CALL PFNGLGETSHADERINFOLOGPROC glad_glGetShaderInfoLog;
+#define glGetShaderInfoLog glad_glGetShaderInfoLog
+GLAD_API_CALL PFNGLGETSHADERSOURCEPROC glad_glGetShaderSource;
+#define glGetShaderSource glad_glGetShaderSource
+GLAD_API_CALL PFNGLGETSHADERIVPROC glad_glGetShaderiv;
+#define glGetShaderiv glad_glGetShaderiv
+GLAD_API_CALL PFNGLGETSTRINGPROC glad_glGetString;
+#define glGetString glad_glGetString
+GLAD_API_CALL PFNGLGETSTRINGIPROC glad_glGetStringi;
+#define glGetStringi glad_glGetStringi
+GLAD_API_CALL PFNGLGETSYNCIVPROC glad_glGetSynciv;
+#define glGetSynciv glad_glGetSynciv
+GLAD_API_CALL PFNGLGETTEXENVFVPROC glad_glGetTexEnvfv;
+#define glGetTexEnvfv glad_glGetTexEnvfv
+GLAD_API_CALL PFNGLGETTEXENVIVPROC glad_glGetTexEnviv;
+#define glGetTexEnviv glad_glGetTexEnviv
+GLAD_API_CALL PFNGLGETTEXGENDVPROC glad_glGetTexGendv;
+#define glGetTexGendv glad_glGetTexGendv
+GLAD_API_CALL PFNGLGETTEXGENFVPROC glad_glGetTexGenfv;
+#define glGetTexGenfv glad_glGetTexGenfv
+GLAD_API_CALL PFNGLGETTEXGENIVPROC glad_glGetTexGeniv;
+#define glGetTexGeniv glad_glGetTexGeniv
+GLAD_API_CALL PFNGLGETTEXIMAGEPROC glad_glGetTexImage;
+#define glGetTexImage glad_glGetTexImage
+GLAD_API_CALL PFNGLGETTEXLEVELPARAMETERFVPROC glad_glGetTexLevelParameterfv;
+#define glGetTexLevelParameterfv glad_glGetTexLevelParameterfv
+GLAD_API_CALL PFNGLGETTEXLEVELPARAMETERIVPROC glad_glGetTexLevelParameteriv;
+#define glGetTexLevelParameteriv glad_glGetTexLevelParameteriv
+GLAD_API_CALL PFNGLGETTEXPARAMETERIIVPROC glad_glGetTexParameterIiv;
+#define glGetTexParameterIiv glad_glGetTexParameterIiv
+GLAD_API_CALL PFNGLGETTEXPARAMETERIUIVPROC glad_glGetTexParameterIuiv;
+#define glGetTexParameterIuiv glad_glGetTexParameterIuiv
+GLAD_API_CALL PFNGLGETTEXPARAMETERFVPROC glad_glGetTexParameterfv;
+#define glGetTexParameterfv glad_glGetTexParameterfv
+GLAD_API_CALL PFNGLGETTEXPARAMETERIVPROC glad_glGetTexParameteriv;
+#define glGetTexParameteriv glad_glGetTexParameteriv
+GLAD_API_CALL PFNGLGETTRANSFORMFEEDBACKVARYINGPROC glad_glGetTransformFeedbackVarying;
+#define glGetTransformFeedbackVarying glad_glGetTransformFeedbackVarying
+GLAD_API_CALL PFNGLGETUNIFORMBLOCKINDEXPROC glad_glGetUniformBlockIndex;
+#define glGetUniformBlockIndex glad_glGetUniformBlockIndex
+GLAD_API_CALL PFNGLGETUNIFORMINDICESPROC glad_glGetUniformIndices;
+#define glGetUniformIndices glad_glGetUniformIndices
+GLAD_API_CALL PFNGLGETUNIFORMLOCATIONPROC glad_glGetUniformLocation;
+#define glGetUniformLocation glad_glGetUniformLocation
+GLAD_API_CALL PFNGLGETUNIFORMFVPROC glad_glGetUniformfv;
+#define glGetUniformfv glad_glGetUniformfv
+GLAD_API_CALL PFNGLGETUNIFORMIVPROC glad_glGetUniformiv;
+#define glGetUniformiv glad_glGetUniformiv
+GLAD_API_CALL PFNGLGETUNIFORMUIVPROC glad_glGetUniformuiv;
+#define glGetUniformuiv glad_glGetUniformuiv
+GLAD_API_CALL PFNGLGETVERTEXATTRIBIIVPROC glad_glGetVertexAttribIiv;
+#define glGetVertexAttribIiv glad_glGetVertexAttribIiv
+GLAD_API_CALL PFNGLGETVERTEXATTRIBIUIVPROC glad_glGetVertexAttribIuiv;
+#define glGetVertexAttribIuiv glad_glGetVertexAttribIuiv
+GLAD_API_CALL PFNGLGETVERTEXATTRIBPOINTERVPROC glad_glGetVertexAttribPointerv;
+#define glGetVertexAttribPointerv glad_glGetVertexAttribPointerv
+GLAD_API_CALL PFNGLGETVERTEXATTRIBDVPROC glad_glGetVertexAttribdv;
+#define glGetVertexAttribdv glad_glGetVertexAttribdv
+GLAD_API_CALL PFNGLGETVERTEXATTRIBFVPROC glad_glGetVertexAttribfv;
+#define glGetVertexAttribfv glad_glGetVertexAttribfv
+GLAD_API_CALL PFNGLGETVERTEXATTRIBIVPROC glad_glGetVertexAttribiv;
+#define glGetVertexAttribiv glad_glGetVertexAttribiv
+GLAD_API_CALL PFNGLHINTPROC glad_glHint;
+#define glHint glad_glHint
+GLAD_API_CALL PFNGLINDEXMASKPROC glad_glIndexMask;
+#define glIndexMask glad_glIndexMask
+GLAD_API_CALL PFNGLINDEXPOINTERPROC glad_glIndexPointer;
+#define glIndexPointer glad_glIndexPointer
+GLAD_API_CALL PFNGLINDEXDPROC glad_glIndexd;
+#define glIndexd glad_glIndexd
+GLAD_API_CALL PFNGLINDEXDVPROC glad_glIndexdv;
+#define glIndexdv glad_glIndexdv
+GLAD_API_CALL PFNGLINDEXFPROC glad_glIndexf;
+#define glIndexf glad_glIndexf
+GLAD_API_CALL PFNGLINDEXFVPROC glad_glIndexfv;
+#define glIndexfv glad_glIndexfv
+GLAD_API_CALL PFNGLINDEXIPROC glad_glIndexi;
+#define glIndexi glad_glIndexi
+GLAD_API_CALL PFNGLINDEXIVPROC glad_glIndexiv;
+#define glIndexiv glad_glIndexiv
+GLAD_API_CALL PFNGLINDEXSPROC glad_glIndexs;
+#define glIndexs glad_glIndexs
+GLAD_API_CALL PFNGLINDEXSVPROC glad_glIndexsv;
+#define glIndexsv glad_glIndexsv
+GLAD_API_CALL PFNGLINDEXUBPROC glad_glIndexub;
+#define glIndexub glad_glIndexub
+GLAD_API_CALL PFNGLINDEXUBVPROC glad_glIndexubv;
+#define glIndexubv glad_glIndexubv
+GLAD_API_CALL PFNGLINITNAMESPROC glad_glInitNames;
+#define glInitNames glad_glInitNames
+GLAD_API_CALL PFNGLINTERLEAVEDARRAYSPROC glad_glInterleavedArrays;
+#define glInterleavedArrays glad_glInterleavedArrays
+GLAD_API_CALL PFNGLISBUFFERPROC glad_glIsBuffer;
+#define glIsBuffer glad_glIsBuffer
+GLAD_API_CALL PFNGLISENABLEDPROC glad_glIsEnabled;
+#define glIsEnabled glad_glIsEnabled
+GLAD_API_CALL PFNGLISENABLEDIPROC glad_glIsEnabledi;
+#define glIsEnabledi glad_glIsEnabledi
+GLAD_API_CALL PFNGLISFRAMEBUFFERPROC glad_glIsFramebuffer;
+#define glIsFramebuffer glad_glIsFramebuffer
+GLAD_API_CALL PFNGLISFRAMEBUFFEREXTPROC glad_glIsFramebufferEXT;
+#define glIsFramebufferEXT glad_glIsFramebufferEXT
+GLAD_API_CALL PFNGLISLISTPROC glad_glIsList;
+#define glIsList glad_glIsList
+GLAD_API_CALL PFNGLISPROGRAMPROC glad_glIsProgram;
+#define glIsProgram glad_glIsProgram
+GLAD_API_CALL PFNGLISQUERYPROC glad_glIsQuery;
+#define glIsQuery glad_glIsQuery
+GLAD_API_CALL PFNGLISRENDERBUFFERPROC glad_glIsRenderbuffer;
+#define glIsRenderbuffer glad_glIsRenderbuffer
+GLAD_API_CALL PFNGLISRENDERBUFFEREXTPROC glad_glIsRenderbufferEXT;
+#define glIsRenderbufferEXT glad_glIsRenderbufferEXT
+GLAD_API_CALL PFNGLISSAMPLERPROC glad_glIsSampler;
+#define glIsSampler glad_glIsSampler
+GLAD_API_CALL PFNGLISSHADERPROC glad_glIsShader;
+#define glIsShader glad_glIsShader
+GLAD_API_CALL PFNGLISSYNCPROC glad_glIsSync;
+#define glIsSync glad_glIsSync
+GLAD_API_CALL PFNGLISTEXTUREPROC glad_glIsTexture;
+#define glIsTexture glad_glIsTexture
+GLAD_API_CALL PFNGLISVERTEXARRAYPROC glad_glIsVertexArray;
+#define glIsVertexArray glad_glIsVertexArray
+GLAD_API_CALL PFNGLLIGHTMODELFPROC glad_glLightModelf;
+#define glLightModelf glad_glLightModelf
+GLAD_API_CALL PFNGLLIGHTMODELFVPROC glad_glLightModelfv;
+#define glLightModelfv glad_glLightModelfv
+GLAD_API_CALL PFNGLLIGHTMODELIPROC glad_glLightModeli;
+#define glLightModeli glad_glLightModeli
+GLAD_API_CALL PFNGLLIGHTMODELIVPROC glad_glLightModeliv;
+#define glLightModeliv glad_glLightModeliv
+GLAD_API_CALL PFNGLLIGHTFPROC glad_glLightf;
+#define glLightf glad_glLightf
+GLAD_API_CALL PFNGLLIGHTFVPROC glad_glLightfv;
+#define glLightfv glad_glLightfv
+GLAD_API_CALL PFNGLLIGHTIPROC glad_glLighti;
+#define glLighti glad_glLighti
+GLAD_API_CALL PFNGLLIGHTIVPROC glad_glLightiv;
+#define glLightiv glad_glLightiv
+GLAD_API_CALL PFNGLLINESTIPPLEPROC glad_glLineStipple;
+#define glLineStipple glad_glLineStipple
+GLAD_API_CALL PFNGLLINEWIDTHPROC glad_glLineWidth;
+#define glLineWidth glad_glLineWidth
+GLAD_API_CALL PFNGLLINKPROGRAMPROC glad_glLinkProgram;
+#define glLinkProgram glad_glLinkProgram
+GLAD_API_CALL PFNGLLISTBASEPROC glad_glListBase;
+#define glListBase glad_glListBase
+GLAD_API_CALL PFNGLLOADIDENTITYPROC glad_glLoadIdentity;
+#define glLoadIdentity glad_glLoadIdentity
+GLAD_API_CALL PFNGLLOADMATRIXDPROC glad_glLoadMatrixd;
+#define glLoadMatrixd glad_glLoadMatrixd
+GLAD_API_CALL PFNGLLOADMATRIXFPROC glad_glLoadMatrixf;
+#define glLoadMatrixf glad_glLoadMatrixf
+GLAD_API_CALL PFNGLLOADNAMEPROC glad_glLoadName;
+#define glLoadName glad_glLoadName
+GLAD_API_CALL PFNGLLOADTRANSPOSEMATRIXDPROC glad_glLoadTransposeMatrixd;
+#define glLoadTransposeMatrixd glad_glLoadTransposeMatrixd
+GLAD_API_CALL PFNGLLOADTRANSPOSEMATRIXFPROC glad_glLoadTransposeMatrixf;
+#define glLoadTransposeMatrixf glad_glLoadTransposeMatrixf
+GLAD_API_CALL PFNGLLOGICOPPROC glad_glLogicOp;
+#define glLogicOp glad_glLogicOp
+GLAD_API_CALL PFNGLMAP1DPROC glad_glMap1d;
+#define glMap1d glad_glMap1d
+GLAD_API_CALL PFNGLMAP1FPROC glad_glMap1f;
+#define glMap1f glad_glMap1f
+GLAD_API_CALL PFNGLMAP2DPROC glad_glMap2d;
+#define glMap2d glad_glMap2d
+GLAD_API_CALL PFNGLMAP2FPROC glad_glMap2f;
+#define glMap2f glad_glMap2f
+GLAD_API_CALL PFNGLMAPBUFFERPROC glad_glMapBuffer;
+#define glMapBuffer glad_glMapBuffer
+GLAD_API_CALL PFNGLMAPBUFFERRANGEPROC glad_glMapBufferRange;
+#define glMapBufferRange glad_glMapBufferRange
+GLAD_API_CALL PFNGLMAPGRID1DPROC glad_glMapGrid1d;
+#define glMapGrid1d glad_glMapGrid1d
+GLAD_API_CALL PFNGLMAPGRID1FPROC glad_glMapGrid1f;
+#define glMapGrid1f glad_glMapGrid1f
+GLAD_API_CALL PFNGLMAPGRID2DPROC glad_glMapGrid2d;
+#define glMapGrid2d glad_glMapGrid2d
+GLAD_API_CALL PFNGLMAPGRID2FPROC glad_glMapGrid2f;
+#define glMapGrid2f glad_glMapGrid2f
+GLAD_API_CALL PFNGLMATERIALFPROC glad_glMaterialf;
+#define glMaterialf glad_glMaterialf
+GLAD_API_CALL PFNGLMATERIALFVPROC glad_glMaterialfv;
+#define glMaterialfv glad_glMaterialfv
+GLAD_API_CALL PFNGLMATERIALIPROC glad_glMateriali;
+#define glMateriali glad_glMateriali
+GLAD_API_CALL PFNGLMATERIALIVPROC glad_glMaterialiv;
+#define glMaterialiv glad_glMaterialiv
+GLAD_API_CALL PFNGLMATRIXMODEPROC glad_glMatrixMode;
+#define glMatrixMode glad_glMatrixMode
+GLAD_API_CALL PFNGLMULTMATRIXDPROC glad_glMultMatrixd;
+#define glMultMatrixd glad_glMultMatrixd
+GLAD_API_CALL PFNGLMULTMATRIXFPROC glad_glMultMatrixf;
+#define glMultMatrixf glad_glMultMatrixf
+GLAD_API_CALL PFNGLMULTTRANSPOSEMATRIXDPROC glad_glMultTransposeMatrixd;
+#define glMultTransposeMatrixd glad_glMultTransposeMatrixd
+GLAD_API_CALL PFNGLMULTTRANSPOSEMATRIXFPROC glad_glMultTransposeMatrixf;
+#define glMultTransposeMatrixf glad_glMultTransposeMatrixf
+GLAD_API_CALL PFNGLMULTIDRAWARRAYSPROC glad_glMultiDrawArrays;
+#define glMultiDrawArrays glad_glMultiDrawArrays
+GLAD_API_CALL PFNGLMULTIDRAWELEMENTSPROC glad_glMultiDrawElements;
+#define glMultiDrawElements glad_glMultiDrawElements
+GLAD_API_CALL PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC glad_glMultiDrawElementsBaseVertex;
+#define glMultiDrawElementsBaseVertex glad_glMultiDrawElementsBaseVertex
+GLAD_API_CALL PFNGLMULTITEXCOORD1DPROC glad_glMultiTexCoord1d;
+#define glMultiTexCoord1d glad_glMultiTexCoord1d
+GLAD_API_CALL PFNGLMULTITEXCOORD1DVPROC glad_glMultiTexCoord1dv;
+#define glMultiTexCoord1dv glad_glMultiTexCoord1dv
+GLAD_API_CALL PFNGLMULTITEXCOORD1FPROC glad_glMultiTexCoord1f;
+#define glMultiTexCoord1f glad_glMultiTexCoord1f
+GLAD_API_CALL PFNGLMULTITEXCOORD1FVPROC glad_glMultiTexCoord1fv;
+#define glMultiTexCoord1fv glad_glMultiTexCoord1fv
+GLAD_API_CALL PFNGLMULTITEXCOORD1IPROC glad_glMultiTexCoord1i;
+#define glMultiTexCoord1i glad_glMultiTexCoord1i
+GLAD_API_CALL PFNGLMULTITEXCOORD1IVPROC glad_glMultiTexCoord1iv;
+#define glMultiTexCoord1iv glad_glMultiTexCoord1iv
+GLAD_API_CALL PFNGLMULTITEXCOORD1SPROC glad_glMultiTexCoord1s;
+#define glMultiTexCoord1s glad_glMultiTexCoord1s
+GLAD_API_CALL PFNGLMULTITEXCOORD1SVPROC glad_glMultiTexCoord1sv;
+#define glMultiTexCoord1sv glad_glMultiTexCoord1sv
+GLAD_API_CALL PFNGLMULTITEXCOORD2DPROC glad_glMultiTexCoord2d;
+#define glMultiTexCoord2d glad_glMultiTexCoord2d
+GLAD_API_CALL PFNGLMULTITEXCOORD2DVPROC glad_glMultiTexCoord2dv;
+#define glMultiTexCoord2dv glad_glMultiTexCoord2dv
+GLAD_API_CALL PFNGLMULTITEXCOORD2FPROC glad_glMultiTexCoord2f;
+#define glMultiTexCoord2f glad_glMultiTexCoord2f
+GLAD_API_CALL PFNGLMULTITEXCOORD2FVPROC glad_glMultiTexCoord2fv;
+#define glMultiTexCoord2fv glad_glMultiTexCoord2fv
+GLAD_API_CALL PFNGLMULTITEXCOORD2IPROC glad_glMultiTexCoord2i;
+#define glMultiTexCoord2i glad_glMultiTexCoord2i
+GLAD_API_CALL PFNGLMULTITEXCOORD2IVPROC glad_glMultiTexCoord2iv;
+#define glMultiTexCoord2iv glad_glMultiTexCoord2iv
+GLAD_API_CALL PFNGLMULTITEXCOORD2SPROC glad_glMultiTexCoord2s;
+#define glMultiTexCoord2s glad_glMultiTexCoord2s
+GLAD_API_CALL PFNGLMULTITEXCOORD2SVPROC glad_glMultiTexCoord2sv;
+#define glMultiTexCoord2sv glad_glMultiTexCoord2sv
+GLAD_API_CALL PFNGLMULTITEXCOORD3DPROC glad_glMultiTexCoord3d;
+#define glMultiTexCoord3d glad_glMultiTexCoord3d
+GLAD_API_CALL PFNGLMULTITEXCOORD3DVPROC glad_glMultiTexCoord3dv;
+#define glMultiTexCoord3dv glad_glMultiTexCoord3dv
+GLAD_API_CALL PFNGLMULTITEXCOORD3FPROC glad_glMultiTexCoord3f;
+#define glMultiTexCoord3f glad_glMultiTexCoord3f
+GLAD_API_CALL PFNGLMULTITEXCOORD3FVPROC glad_glMultiTexCoord3fv;
+#define glMultiTexCoord3fv glad_glMultiTexCoord3fv
+GLAD_API_CALL PFNGLMULTITEXCOORD3IPROC glad_glMultiTexCoord3i;
+#define glMultiTexCoord3i glad_glMultiTexCoord3i
+GLAD_API_CALL PFNGLMULTITEXCOORD3IVPROC glad_glMultiTexCoord3iv;
+#define glMultiTexCoord3iv glad_glMultiTexCoord3iv
+GLAD_API_CALL PFNGLMULTITEXCOORD3SPROC glad_glMultiTexCoord3s;
+#define glMultiTexCoord3s glad_glMultiTexCoord3s
+GLAD_API_CALL PFNGLMULTITEXCOORD3SVPROC glad_glMultiTexCoord3sv;
+#define glMultiTexCoord3sv glad_glMultiTexCoord3sv
+GLAD_API_CALL PFNGLMULTITEXCOORD4DPROC glad_glMultiTexCoord4d;
+#define glMultiTexCoord4d glad_glMultiTexCoord4d
+GLAD_API_CALL PFNGLMULTITEXCOORD4DVPROC glad_glMultiTexCoord4dv;
+#define glMultiTexCoord4dv glad_glMultiTexCoord4dv
+GLAD_API_CALL PFNGLMULTITEXCOORD4FPROC glad_glMultiTexCoord4f;
+#define glMultiTexCoord4f glad_glMultiTexCoord4f
+GLAD_API_CALL PFNGLMULTITEXCOORD4FVPROC glad_glMultiTexCoord4fv;
+#define glMultiTexCoord4fv glad_glMultiTexCoord4fv
+GLAD_API_CALL PFNGLMULTITEXCOORD4IPROC glad_glMultiTexCoord4i;
+#define glMultiTexCoord4i glad_glMultiTexCoord4i
+GLAD_API_CALL PFNGLMULTITEXCOORD4IVPROC glad_glMultiTexCoord4iv;
+#define glMultiTexCoord4iv glad_glMultiTexCoord4iv
+GLAD_API_CALL PFNGLMULTITEXCOORD4SPROC glad_glMultiTexCoord4s;
+#define glMultiTexCoord4s glad_glMultiTexCoord4s
+GLAD_API_CALL PFNGLMULTITEXCOORD4SVPROC glad_glMultiTexCoord4sv;
+#define glMultiTexCoord4sv glad_glMultiTexCoord4sv
+GLAD_API_CALL PFNGLMULTITEXCOORDP1UIPROC glad_glMultiTexCoordP1ui;
+#define glMultiTexCoordP1ui glad_glMultiTexCoordP1ui
+GLAD_API_CALL PFNGLMULTITEXCOORDP1UIVPROC glad_glMultiTexCoordP1uiv;
+#define glMultiTexCoordP1uiv glad_glMultiTexCoordP1uiv
+GLAD_API_CALL PFNGLMULTITEXCOORDP2UIPROC glad_glMultiTexCoordP2ui;
+#define glMultiTexCoordP2ui glad_glMultiTexCoordP2ui
+GLAD_API_CALL PFNGLMULTITEXCOORDP2UIVPROC glad_glMultiTexCoordP2uiv;
+#define glMultiTexCoordP2uiv glad_glMultiTexCoordP2uiv
+GLAD_API_CALL PFNGLMULTITEXCOORDP3UIPROC glad_glMultiTexCoordP3ui;
+#define glMultiTexCoordP3ui glad_glMultiTexCoordP3ui
+GLAD_API_CALL PFNGLMULTITEXCOORDP3UIVPROC glad_glMultiTexCoordP3uiv;
+#define glMultiTexCoordP3uiv glad_glMultiTexCoordP3uiv
+GLAD_API_CALL PFNGLMULTITEXCOORDP4UIPROC glad_glMultiTexCoordP4ui;
+#define glMultiTexCoordP4ui glad_glMultiTexCoordP4ui
+GLAD_API_CALL PFNGLMULTITEXCOORDP4UIVPROC glad_glMultiTexCoordP4uiv;
+#define glMultiTexCoordP4uiv glad_glMultiTexCoordP4uiv
+GLAD_API_CALL PFNGLNEWLISTPROC glad_glNewList;
+#define glNewList glad_glNewList
+GLAD_API_CALL PFNGLNORMAL3BPROC glad_glNormal3b;
+#define glNormal3b glad_glNormal3b
+GLAD_API_CALL PFNGLNORMAL3BVPROC glad_glNormal3bv;
+#define glNormal3bv glad_glNormal3bv
+GLAD_API_CALL PFNGLNORMAL3DPROC glad_glNormal3d;
+#define glNormal3d glad_glNormal3d
+GLAD_API_CALL PFNGLNORMAL3DVPROC glad_glNormal3dv;
+#define glNormal3dv glad_glNormal3dv
+GLAD_API_CALL PFNGLNORMAL3FPROC glad_glNormal3f;
+#define glNormal3f glad_glNormal3f
+GLAD_API_CALL PFNGLNORMAL3FVPROC glad_glNormal3fv;
+#define glNormal3fv glad_glNormal3fv
+GLAD_API_CALL PFNGLNORMAL3IPROC glad_glNormal3i;
+#define glNormal3i glad_glNormal3i
+GLAD_API_CALL PFNGLNORMAL3IVPROC glad_glNormal3iv;
+#define glNormal3iv glad_glNormal3iv
+GLAD_API_CALL PFNGLNORMAL3SPROC glad_glNormal3s;
+#define glNormal3s glad_glNormal3s
+GLAD_API_CALL PFNGLNORMAL3SVPROC glad_glNormal3sv;
+#define glNormal3sv glad_glNormal3sv
+GLAD_API_CALL PFNGLNORMALP3UIPROC glad_glNormalP3ui;
+#define glNormalP3ui glad_glNormalP3ui
+GLAD_API_CALL PFNGLNORMALP3UIVPROC glad_glNormalP3uiv;
+#define glNormalP3uiv glad_glNormalP3uiv
+GLAD_API_CALL PFNGLNORMALPOINTERPROC glad_glNormalPointer;
+#define glNormalPointer glad_glNormalPointer
+GLAD_API_CALL PFNGLORTHOPROC glad_glOrtho;
+#define glOrtho glad_glOrtho
+GLAD_API_CALL PFNGLPASSTHROUGHPROC glad_glPassThrough;
+#define glPassThrough glad_glPassThrough
+GLAD_API_CALL PFNGLPIXELMAPFVPROC glad_glPixelMapfv;
+#define glPixelMapfv glad_glPixelMapfv
+GLAD_API_CALL PFNGLPIXELMAPUIVPROC glad_glPixelMapuiv;
+#define glPixelMapuiv glad_glPixelMapuiv
+GLAD_API_CALL PFNGLPIXELMAPUSVPROC glad_glPixelMapusv;
+#define glPixelMapusv glad_glPixelMapusv
+GLAD_API_CALL PFNGLPIXELSTOREFPROC glad_glPixelStoref;
+#define glPixelStoref glad_glPixelStoref
+GLAD_API_CALL PFNGLPIXELSTOREIPROC glad_glPixelStorei;
+#define glPixelStorei glad_glPixelStorei
+GLAD_API_CALL PFNGLPIXELTRANSFERFPROC glad_glPixelTransferf;
+#define glPixelTransferf glad_glPixelTransferf
+GLAD_API_CALL PFNGLPIXELTRANSFERIPROC glad_glPixelTransferi;
+#define glPixelTransferi glad_glPixelTransferi
+GLAD_API_CALL PFNGLPIXELZOOMPROC glad_glPixelZoom;
+#define glPixelZoom glad_glPixelZoom
+GLAD_API_CALL PFNGLPOINTPARAMETERFPROC glad_glPointParameterf;
+#define glPointParameterf glad_glPointParameterf
+GLAD_API_CALL PFNGLPOINTPARAMETERFVPROC glad_glPointParameterfv;
+#define glPointParameterfv glad_glPointParameterfv
+GLAD_API_CALL PFNGLPOINTPARAMETERIPROC glad_glPointParameteri;
+#define glPointParameteri glad_glPointParameteri
+GLAD_API_CALL PFNGLPOINTPARAMETERIVPROC glad_glPointParameteriv;
+#define glPointParameteriv glad_glPointParameteriv
+GLAD_API_CALL PFNGLPOINTSIZEPROC glad_glPointSize;
+#define glPointSize glad_glPointSize
+GLAD_API_CALL PFNGLPOLYGONMODEPROC glad_glPolygonMode;
+#define glPolygonMode glad_glPolygonMode
+GLAD_API_CALL PFNGLPOLYGONOFFSETPROC glad_glPolygonOffset;
+#define glPolygonOffset glad_glPolygonOffset
+GLAD_API_CALL PFNGLPOLYGONSTIPPLEPROC glad_glPolygonStipple;
+#define glPolygonStipple glad_glPolygonStipple
+GLAD_API_CALL PFNGLPOPATTRIBPROC glad_glPopAttrib;
+#define glPopAttrib glad_glPopAttrib
+GLAD_API_CALL PFNGLPOPCLIENTATTRIBPROC glad_glPopClientAttrib;
+#define glPopClientAttrib glad_glPopClientAttrib
+GLAD_API_CALL PFNGLPOPMATRIXPROC glad_glPopMatrix;
+#define glPopMatrix glad_glPopMatrix
+GLAD_API_CALL PFNGLPOPNAMEPROC glad_glPopName;
+#define glPopName glad_glPopName
+GLAD_API_CALL PFNGLPRIMITIVERESTARTINDEXPROC glad_glPrimitiveRestartIndex;
+#define glPrimitiveRestartIndex glad_glPrimitiveRestartIndex
+GLAD_API_CALL PFNGLPRIORITIZETEXTURESPROC glad_glPrioritizeTextures;
+#define glPrioritizeTextures glad_glPrioritizeTextures
+GLAD_API_CALL PFNGLPROVOKINGVERTEXPROC glad_glProvokingVertex;
+#define glProvokingVertex glad_glProvokingVertex
+GLAD_API_CALL PFNGLPUSHATTRIBPROC glad_glPushAttrib;
+#define glPushAttrib glad_glPushAttrib
+GLAD_API_CALL PFNGLPUSHCLIENTATTRIBPROC glad_glPushClientAttrib;
+#define glPushClientAttrib glad_glPushClientAttrib
+GLAD_API_CALL PFNGLPUSHMATRIXPROC glad_glPushMatrix;
+#define glPushMatrix glad_glPushMatrix
+GLAD_API_CALL PFNGLPUSHNAMEPROC glad_glPushName;
+#define glPushName glad_glPushName
+GLAD_API_CALL PFNGLQUERYCOUNTERPROC glad_glQueryCounter;
+#define glQueryCounter glad_glQueryCounter
+GLAD_API_CALL PFNGLRASTERPOS2DPROC glad_glRasterPos2d;
+#define glRasterPos2d glad_glRasterPos2d
+GLAD_API_CALL PFNGLRASTERPOS2DVPROC glad_glRasterPos2dv;
+#define glRasterPos2dv glad_glRasterPos2dv
+GLAD_API_CALL PFNGLRASTERPOS2FPROC glad_glRasterPos2f;
+#define glRasterPos2f glad_glRasterPos2f
+GLAD_API_CALL PFNGLRASTERPOS2FVPROC glad_glRasterPos2fv;
+#define glRasterPos2fv glad_glRasterPos2fv
+GLAD_API_CALL PFNGLRASTERPOS2IPROC glad_glRasterPos2i;
+#define glRasterPos2i glad_glRasterPos2i
+GLAD_API_CALL PFNGLRASTERPOS2IVPROC glad_glRasterPos2iv;
+#define glRasterPos2iv glad_glRasterPos2iv
+GLAD_API_CALL PFNGLRASTERPOS2SPROC glad_glRasterPos2s;
+#define glRasterPos2s glad_glRasterPos2s
+GLAD_API_CALL PFNGLRASTERPOS2SVPROC glad_glRasterPos2sv;
+#define glRasterPos2sv glad_glRasterPos2sv
+GLAD_API_CALL PFNGLRASTERPOS3DPROC glad_glRasterPos3d;
+#define glRasterPos3d glad_glRasterPos3d
+GLAD_API_CALL PFNGLRASTERPOS3DVPROC glad_glRasterPos3dv;
+#define glRasterPos3dv glad_glRasterPos3dv
+GLAD_API_CALL PFNGLRASTERPOS3FPROC glad_glRasterPos3f;
+#define glRasterPos3f glad_glRasterPos3f
+GLAD_API_CALL PFNGLRASTERPOS3FVPROC glad_glRasterPos3fv;
+#define glRasterPos3fv glad_glRasterPos3fv
+GLAD_API_CALL PFNGLRASTERPOS3IPROC glad_glRasterPos3i;
+#define glRasterPos3i glad_glRasterPos3i
+GLAD_API_CALL PFNGLRASTERPOS3IVPROC glad_glRasterPos3iv;
+#define glRasterPos3iv glad_glRasterPos3iv
+GLAD_API_CALL PFNGLRASTERPOS3SPROC glad_glRasterPos3s;
+#define glRasterPos3s glad_glRasterPos3s
+GLAD_API_CALL PFNGLRASTERPOS3SVPROC glad_glRasterPos3sv;
+#define glRasterPos3sv glad_glRasterPos3sv
+GLAD_API_CALL PFNGLRASTERPOS4DPROC glad_glRasterPos4d;
+#define glRasterPos4d glad_glRasterPos4d
+GLAD_API_CALL PFNGLRASTERPOS4DVPROC glad_glRasterPos4dv;
+#define glRasterPos4dv glad_glRasterPos4dv
+GLAD_API_CALL PFNGLRASTERPOS4FPROC glad_glRasterPos4f;
+#define glRasterPos4f glad_glRasterPos4f
+GLAD_API_CALL PFNGLRASTERPOS4FVPROC glad_glRasterPos4fv;
+#define glRasterPos4fv glad_glRasterPos4fv
+GLAD_API_CALL PFNGLRASTERPOS4IPROC glad_glRasterPos4i;
+#define glRasterPos4i glad_glRasterPos4i
+GLAD_API_CALL PFNGLRASTERPOS4IVPROC glad_glRasterPos4iv;
+#define glRasterPos4iv glad_glRasterPos4iv
+GLAD_API_CALL PFNGLRASTERPOS4SPROC glad_glRasterPos4s;
+#define glRasterPos4s glad_glRasterPos4s
+GLAD_API_CALL PFNGLRASTERPOS4SVPROC glad_glRasterPos4sv;
+#define glRasterPos4sv glad_glRasterPos4sv
+GLAD_API_CALL PFNGLREADBUFFERPROC glad_glReadBuffer;
+#define glReadBuffer glad_glReadBuffer
+GLAD_API_CALL PFNGLREADPIXELSPROC glad_glReadPixels;
+#define glReadPixels glad_glReadPixels
+GLAD_API_CALL PFNGLRECTDPROC glad_glRectd;
+#define glRectd glad_glRectd
+GLAD_API_CALL PFNGLRECTDVPROC glad_glRectdv;
+#define glRectdv glad_glRectdv
+GLAD_API_CALL PFNGLRECTFPROC glad_glRectf;
+#define glRectf glad_glRectf
+GLAD_API_CALL PFNGLRECTFVPROC glad_glRectfv;
+#define glRectfv glad_glRectfv
+GLAD_API_CALL PFNGLRECTIPROC glad_glRecti;
+#define glRecti glad_glRecti
+GLAD_API_CALL PFNGLRECTIVPROC glad_glRectiv;
+#define glRectiv glad_glRectiv
+GLAD_API_CALL PFNGLRECTSPROC glad_glRects;
+#define glRects glad_glRects
+GLAD_API_CALL PFNGLRECTSVPROC glad_glRectsv;
+#define glRectsv glad_glRectsv
+GLAD_API_CALL PFNGLRENDERMODEPROC glad_glRenderMode;
+#define glRenderMode glad_glRenderMode
+GLAD_API_CALL PFNGLRENDERBUFFERSTORAGEPROC glad_glRenderbufferStorage;
+#define glRenderbufferStorage glad_glRenderbufferStorage
+GLAD_API_CALL PFNGLRENDERBUFFERSTORAGEEXTPROC glad_glRenderbufferStorageEXT;
+#define glRenderbufferStorageEXT glad_glRenderbufferStorageEXT
+GLAD_API_CALL PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC glad_glRenderbufferStorageMultisample;
+#define glRenderbufferStorageMultisample glad_glRenderbufferStorageMultisample
+GLAD_API_CALL PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC glad_glRenderbufferStorageMultisampleEXT;
+#define glRenderbufferStorageMultisampleEXT glad_glRenderbufferStorageMultisampleEXT
+GLAD_API_CALL PFNGLROTATEDPROC glad_glRotated;
+#define glRotated glad_glRotated
+GLAD_API_CALL PFNGLROTATEFPROC glad_glRotatef;
+#define glRotatef glad_glRotatef
+GLAD_API_CALL PFNGLSAMPLECOVERAGEPROC glad_glSampleCoverage;
+#define glSampleCoverage glad_glSampleCoverage
+GLAD_API_CALL PFNGLSAMPLEMASKIPROC glad_glSampleMaski;
+#define glSampleMaski glad_glSampleMaski
+GLAD_API_CALL PFNGLSAMPLERPARAMETERIIVPROC glad_glSamplerParameterIiv;
+#define glSamplerParameterIiv glad_glSamplerParameterIiv
+GLAD_API_CALL PFNGLSAMPLERPARAMETERIUIVPROC glad_glSamplerParameterIuiv;
+#define glSamplerParameterIuiv glad_glSamplerParameterIuiv
+GLAD_API_CALL PFNGLSAMPLERPARAMETERFPROC glad_glSamplerParameterf;
+#define glSamplerParameterf glad_glSamplerParameterf
+GLAD_API_CALL PFNGLSAMPLERPARAMETERFVPROC glad_glSamplerParameterfv;
+#define glSamplerParameterfv glad_glSamplerParameterfv
+GLAD_API_CALL PFNGLSAMPLERPARAMETERIPROC glad_glSamplerParameteri;
+#define glSamplerParameteri glad_glSamplerParameteri
+GLAD_API_CALL PFNGLSAMPLERPARAMETERIVPROC glad_glSamplerParameteriv;
+#define glSamplerParameteriv glad_glSamplerParameteriv
+GLAD_API_CALL PFNGLSCALEDPROC glad_glScaled;
+#define glScaled glad_glScaled
+GLAD_API_CALL PFNGLSCALEFPROC glad_glScalef;
+#define glScalef glad_glScalef
+GLAD_API_CALL PFNGLSCISSORPROC glad_glScissor;
+#define glScissor glad_glScissor
+GLAD_API_CALL PFNGLSECONDARYCOLOR3BPROC glad_glSecondaryColor3b;
+#define glSecondaryColor3b glad_glSecondaryColor3b
+GLAD_API_CALL PFNGLSECONDARYCOLOR3BVPROC glad_glSecondaryColor3bv;
+#define glSecondaryColor3bv glad_glSecondaryColor3bv
+GLAD_API_CALL PFNGLSECONDARYCOLOR3DPROC glad_glSecondaryColor3d;
+#define glSecondaryColor3d glad_glSecondaryColor3d
+GLAD_API_CALL PFNGLSECONDARYCOLOR3DVPROC glad_glSecondaryColor3dv;
+#define glSecondaryColor3dv glad_glSecondaryColor3dv
+GLAD_API_CALL PFNGLSECONDARYCOLOR3FPROC glad_glSecondaryColor3f;
+#define glSecondaryColor3f glad_glSecondaryColor3f
+GLAD_API_CALL PFNGLSECONDARYCOLOR3FVPROC glad_glSecondaryColor3fv;
+#define glSecondaryColor3fv glad_glSecondaryColor3fv
+GLAD_API_CALL PFNGLSECONDARYCOLOR3IPROC glad_glSecondaryColor3i;
+#define glSecondaryColor3i glad_glSecondaryColor3i
+GLAD_API_CALL PFNGLSECONDARYCOLOR3IVPROC glad_glSecondaryColor3iv;
+#define glSecondaryColor3iv glad_glSecondaryColor3iv
+GLAD_API_CALL PFNGLSECONDARYCOLOR3SPROC glad_glSecondaryColor3s;
+#define glSecondaryColor3s glad_glSecondaryColor3s
+GLAD_API_CALL PFNGLSECONDARYCOLOR3SVPROC glad_glSecondaryColor3sv;
+#define glSecondaryColor3sv glad_glSecondaryColor3sv
+GLAD_API_CALL PFNGLSECONDARYCOLOR3UBPROC glad_glSecondaryColor3ub;
+#define glSecondaryColor3ub glad_glSecondaryColor3ub
+GLAD_API_CALL PFNGLSECONDARYCOLOR3UBVPROC glad_glSecondaryColor3ubv;
+#define glSecondaryColor3ubv glad_glSecondaryColor3ubv
+GLAD_API_CALL PFNGLSECONDARYCOLOR3UIPROC glad_glSecondaryColor3ui;
+#define glSecondaryColor3ui glad_glSecondaryColor3ui
+GLAD_API_CALL PFNGLSECONDARYCOLOR3UIVPROC glad_glSecondaryColor3uiv;
+#define glSecondaryColor3uiv glad_glSecondaryColor3uiv
+GLAD_API_CALL PFNGLSECONDARYCOLOR3USPROC glad_glSecondaryColor3us;
+#define glSecondaryColor3us glad_glSecondaryColor3us
+GLAD_API_CALL PFNGLSECONDARYCOLOR3USVPROC glad_glSecondaryColor3usv;
+#define glSecondaryColor3usv glad_glSecondaryColor3usv
+GLAD_API_CALL PFNGLSECONDARYCOLORP3UIPROC glad_glSecondaryColorP3ui;
+#define glSecondaryColorP3ui glad_glSecondaryColorP3ui
+GLAD_API_CALL PFNGLSECONDARYCOLORP3UIVPROC glad_glSecondaryColorP3uiv;
+#define glSecondaryColorP3uiv glad_glSecondaryColorP3uiv
+GLAD_API_CALL PFNGLSECONDARYCOLORPOINTERPROC glad_glSecondaryColorPointer;
+#define glSecondaryColorPointer glad_glSecondaryColorPointer
+GLAD_API_CALL PFNGLSELECTBUFFERPROC glad_glSelectBuffer;
+#define glSelectBuffer glad_glSelectBuffer
+GLAD_API_CALL PFNGLSHADEMODELPROC glad_glShadeModel;
+#define glShadeModel glad_glShadeModel
+GLAD_API_CALL PFNGLSHADERSOURCEPROC glad_glShaderSource;
+#define glShaderSource glad_glShaderSource
+GLAD_API_CALL PFNGLSTENCILFUNCPROC glad_glStencilFunc;
+#define glStencilFunc glad_glStencilFunc
+GLAD_API_CALL PFNGLSTENCILFUNCSEPARATEPROC glad_glStencilFuncSeparate;
+#define glStencilFuncSeparate glad_glStencilFuncSeparate
+GLAD_API_CALL PFNGLSTENCILMASKPROC glad_glStencilMask;
+#define glStencilMask glad_glStencilMask
+GLAD_API_CALL PFNGLSTENCILMASKSEPARATEPROC glad_glStencilMaskSeparate;
+#define glStencilMaskSeparate glad_glStencilMaskSeparate
+GLAD_API_CALL PFNGLSTENCILOPPROC glad_glStencilOp;
+#define glStencilOp glad_glStencilOp
+GLAD_API_CALL PFNGLSTENCILOPSEPARATEPROC glad_glStencilOpSeparate;
+#define glStencilOpSeparate glad_glStencilOpSeparate
+GLAD_API_CALL PFNGLTEXBUFFERPROC glad_glTexBuffer;
+#define glTexBuffer glad_glTexBuffer
+GLAD_API_CALL PFNGLTEXCOORD1DPROC glad_glTexCoord1d;
+#define glTexCoord1d glad_glTexCoord1d
+GLAD_API_CALL PFNGLTEXCOORD1DVPROC glad_glTexCoord1dv;
+#define glTexCoord1dv glad_glTexCoord1dv
+GLAD_API_CALL PFNGLTEXCOORD1FPROC glad_glTexCoord1f;
+#define glTexCoord1f glad_glTexCoord1f
+GLAD_API_CALL PFNGLTEXCOORD1FVPROC glad_glTexCoord1fv;
+#define glTexCoord1fv glad_glTexCoord1fv
+GLAD_API_CALL PFNGLTEXCOORD1IPROC glad_glTexCoord1i;
+#define glTexCoord1i glad_glTexCoord1i
+GLAD_API_CALL PFNGLTEXCOORD1IVPROC glad_glTexCoord1iv;
+#define glTexCoord1iv glad_glTexCoord1iv
+GLAD_API_CALL PFNGLTEXCOORD1SPROC glad_glTexCoord1s;
+#define glTexCoord1s glad_glTexCoord1s
+GLAD_API_CALL PFNGLTEXCOORD1SVPROC glad_glTexCoord1sv;
+#define glTexCoord1sv glad_glTexCoord1sv
+GLAD_API_CALL PFNGLTEXCOORD2DPROC glad_glTexCoord2d;
+#define glTexCoord2d glad_glTexCoord2d
+GLAD_API_CALL PFNGLTEXCOORD2DVPROC glad_glTexCoord2dv;
+#define glTexCoord2dv glad_glTexCoord2dv
+GLAD_API_CALL PFNGLTEXCOORD2FPROC glad_glTexCoord2f;
+#define glTexCoord2f glad_glTexCoord2f
+GLAD_API_CALL PFNGLTEXCOORD2FVPROC glad_glTexCoord2fv;
+#define glTexCoord2fv glad_glTexCoord2fv
+GLAD_API_CALL PFNGLTEXCOORD2IPROC glad_glTexCoord2i;
+#define glTexCoord2i glad_glTexCoord2i
+GLAD_API_CALL PFNGLTEXCOORD2IVPROC glad_glTexCoord2iv;
+#define glTexCoord2iv glad_glTexCoord2iv
+GLAD_API_CALL PFNGLTEXCOORD2SPROC glad_glTexCoord2s;
+#define glTexCoord2s glad_glTexCoord2s
+GLAD_API_CALL PFNGLTEXCOORD2SVPROC glad_glTexCoord2sv;
+#define glTexCoord2sv glad_glTexCoord2sv
+GLAD_API_CALL PFNGLTEXCOORD3DPROC glad_glTexCoord3d;
+#define glTexCoord3d glad_glTexCoord3d
+GLAD_API_CALL PFNGLTEXCOORD3DVPROC glad_glTexCoord3dv;
+#define glTexCoord3dv glad_glTexCoord3dv
+GLAD_API_CALL PFNGLTEXCOORD3FPROC glad_glTexCoord3f;
+#define glTexCoord3f glad_glTexCoord3f
+GLAD_API_CALL PFNGLTEXCOORD3FVPROC glad_glTexCoord3fv;
+#define glTexCoord3fv glad_glTexCoord3fv
+GLAD_API_CALL PFNGLTEXCOORD3IPROC glad_glTexCoord3i;
+#define glTexCoord3i glad_glTexCoord3i
+GLAD_API_CALL PFNGLTEXCOORD3IVPROC glad_glTexCoord3iv;
+#define glTexCoord3iv glad_glTexCoord3iv
+GLAD_API_CALL PFNGLTEXCOORD3SPROC glad_glTexCoord3s;
+#define glTexCoord3s glad_glTexCoord3s
+GLAD_API_CALL PFNGLTEXCOORD3SVPROC glad_glTexCoord3sv;
+#define glTexCoord3sv glad_glTexCoord3sv
+GLAD_API_CALL PFNGLTEXCOORD4DPROC glad_glTexCoord4d;
+#define glTexCoord4d glad_glTexCoord4d
+GLAD_API_CALL PFNGLTEXCOORD4DVPROC glad_glTexCoord4dv;
+#define glTexCoord4dv glad_glTexCoord4dv
+GLAD_API_CALL PFNGLTEXCOORD4FPROC glad_glTexCoord4f;
+#define glTexCoord4f glad_glTexCoord4f
+GLAD_API_CALL PFNGLTEXCOORD4FVPROC glad_glTexCoord4fv;
+#define glTexCoord4fv glad_glTexCoord4fv
+GLAD_API_CALL PFNGLTEXCOORD4IPROC glad_glTexCoord4i;
+#define glTexCoord4i glad_glTexCoord4i
+GLAD_API_CALL PFNGLTEXCOORD4IVPROC glad_glTexCoord4iv;
+#define glTexCoord4iv glad_glTexCoord4iv
+GLAD_API_CALL PFNGLTEXCOORD4SPROC glad_glTexCoord4s;
+#define glTexCoord4s glad_glTexCoord4s
+GLAD_API_CALL PFNGLTEXCOORD4SVPROC glad_glTexCoord4sv;
+#define glTexCoord4sv glad_glTexCoord4sv
+GLAD_API_CALL PFNGLTEXCOORDP1UIPROC glad_glTexCoordP1ui;
+#define glTexCoordP1ui glad_glTexCoordP1ui
+GLAD_API_CALL PFNGLTEXCOORDP1UIVPROC glad_glTexCoordP1uiv;
+#define glTexCoordP1uiv glad_glTexCoordP1uiv
+GLAD_API_CALL PFNGLTEXCOORDP2UIPROC glad_glTexCoordP2ui;
+#define glTexCoordP2ui glad_glTexCoordP2ui
+GLAD_API_CALL PFNGLTEXCOORDP2UIVPROC glad_glTexCoordP2uiv;
+#define glTexCoordP2uiv glad_glTexCoordP2uiv
+GLAD_API_CALL PFNGLTEXCOORDP3UIPROC glad_glTexCoordP3ui;
+#define glTexCoordP3ui glad_glTexCoordP3ui
+GLAD_API_CALL PFNGLTEXCOORDP3UIVPROC glad_glTexCoordP3uiv;
+#define glTexCoordP3uiv glad_glTexCoordP3uiv
+GLAD_API_CALL PFNGLTEXCOORDP4UIPROC glad_glTexCoordP4ui;
+#define glTexCoordP4ui glad_glTexCoordP4ui
+GLAD_API_CALL PFNGLTEXCOORDP4UIVPROC glad_glTexCoordP4uiv;
+#define glTexCoordP4uiv glad_glTexCoordP4uiv
+GLAD_API_CALL PFNGLTEXCOORDPOINTERPROC glad_glTexCoordPointer;
+#define glTexCoordPointer glad_glTexCoordPointer
+GLAD_API_CALL PFNGLTEXENVFPROC glad_glTexEnvf;
+#define glTexEnvf glad_glTexEnvf
+GLAD_API_CALL PFNGLTEXENVFVPROC glad_glTexEnvfv;
+#define glTexEnvfv glad_glTexEnvfv
+GLAD_API_CALL PFNGLTEXENVIPROC glad_glTexEnvi;
+#define glTexEnvi glad_glTexEnvi
+GLAD_API_CALL PFNGLTEXENVIVPROC glad_glTexEnviv;
+#define glTexEnviv glad_glTexEnviv
+GLAD_API_CALL PFNGLTEXGENDPROC glad_glTexGend;
+#define glTexGend glad_glTexGend
+GLAD_API_CALL PFNGLTEXGENDVPROC glad_glTexGendv;
+#define glTexGendv glad_glTexGendv
+GLAD_API_CALL PFNGLTEXGENFPROC glad_glTexGenf;
+#define glTexGenf glad_glTexGenf
+GLAD_API_CALL PFNGLTEXGENFVPROC glad_glTexGenfv;
+#define glTexGenfv glad_glTexGenfv
+GLAD_API_CALL PFNGLTEXGENIPROC glad_glTexGeni;
+#define glTexGeni glad_glTexGeni
+GLAD_API_CALL PFNGLTEXGENIVPROC glad_glTexGeniv;
+#define glTexGeniv glad_glTexGeniv
+GLAD_API_CALL PFNGLTEXIMAGE1DPROC glad_glTexImage1D;
+#define glTexImage1D glad_glTexImage1D
+GLAD_API_CALL PFNGLTEXIMAGE2DPROC glad_glTexImage2D;
+#define glTexImage2D glad_glTexImage2D
+GLAD_API_CALL PFNGLTEXIMAGE2DMULTISAMPLEPROC glad_glTexImage2DMultisample;
+#define glTexImage2DMultisample glad_glTexImage2DMultisample
+GLAD_API_CALL PFNGLTEXIMAGE3DPROC glad_glTexImage3D;
+#define glTexImage3D glad_glTexImage3D
+GLAD_API_CALL PFNGLTEXIMAGE3DMULTISAMPLEPROC glad_glTexImage3DMultisample;
+#define glTexImage3DMultisample glad_glTexImage3DMultisample
+GLAD_API_CALL PFNGLTEXPARAMETERIIVPROC glad_glTexParameterIiv;
+#define glTexParameterIiv glad_glTexParameterIiv
+GLAD_API_CALL PFNGLTEXPARAMETERIUIVPROC glad_glTexParameterIuiv;
+#define glTexParameterIuiv glad_glTexParameterIuiv
+GLAD_API_CALL PFNGLTEXPARAMETERFPROC glad_glTexParameterf;
+#define glTexParameterf glad_glTexParameterf
+GLAD_API_CALL PFNGLTEXPARAMETERFVPROC glad_glTexParameterfv;
+#define glTexParameterfv glad_glTexParameterfv
+GLAD_API_CALL PFNGLTEXPARAMETERIPROC glad_glTexParameteri;
+#define glTexParameteri glad_glTexParameteri
+GLAD_API_CALL PFNGLTEXPARAMETERIVPROC glad_glTexParameteriv;
+#define glTexParameteriv glad_glTexParameteriv
+GLAD_API_CALL PFNGLTEXSUBIMAGE1DPROC glad_glTexSubImage1D;
+#define glTexSubImage1D glad_glTexSubImage1D
+GLAD_API_CALL PFNGLTEXSUBIMAGE2DPROC glad_glTexSubImage2D;
+#define glTexSubImage2D glad_glTexSubImage2D
+GLAD_API_CALL PFNGLTEXSUBIMAGE3DPROC glad_glTexSubImage3D;
+#define glTexSubImage3D glad_glTexSubImage3D
+GLAD_API_CALL PFNGLTRANSFORMFEEDBACKVARYINGSPROC glad_glTransformFeedbackVaryings;
+#define glTransformFeedbackVaryings glad_glTransformFeedbackVaryings
+GLAD_API_CALL PFNGLTRANSLATEDPROC glad_glTranslated;
+#define glTranslated glad_glTranslated
+GLAD_API_CALL PFNGLTRANSLATEFPROC glad_glTranslatef;
+#define glTranslatef glad_glTranslatef
+GLAD_API_CALL PFNGLUNIFORM1FPROC glad_glUniform1f;
+#define glUniform1f glad_glUniform1f
+GLAD_API_CALL PFNGLUNIFORM1FVPROC glad_glUniform1fv;
+#define glUniform1fv glad_glUniform1fv
+GLAD_API_CALL PFNGLUNIFORM1IPROC glad_glUniform1i;
+#define glUniform1i glad_glUniform1i
+GLAD_API_CALL PFNGLUNIFORM1IVPROC glad_glUniform1iv;
+#define glUniform1iv glad_glUniform1iv
+GLAD_API_CALL PFNGLUNIFORM1UIPROC glad_glUniform1ui;
+#define glUniform1ui glad_glUniform1ui
+GLAD_API_CALL PFNGLUNIFORM1UIVPROC glad_glUniform1uiv;
+#define glUniform1uiv glad_glUniform1uiv
+GLAD_API_CALL PFNGLUNIFORM2FPROC glad_glUniform2f;
+#define glUniform2f glad_glUniform2f
+GLAD_API_CALL PFNGLUNIFORM2FVPROC glad_glUniform2fv;
+#define glUniform2fv glad_glUniform2fv
+GLAD_API_CALL PFNGLUNIFORM2IPROC glad_glUniform2i;
+#define glUniform2i glad_glUniform2i
+GLAD_API_CALL PFNGLUNIFORM2IVPROC glad_glUniform2iv;
+#define glUniform2iv glad_glUniform2iv
+GLAD_API_CALL PFNGLUNIFORM2UIPROC glad_glUniform2ui;
+#define glUniform2ui glad_glUniform2ui
+GLAD_API_CALL PFNGLUNIFORM2UIVPROC glad_glUniform2uiv;
+#define glUniform2uiv glad_glUniform2uiv
+GLAD_API_CALL PFNGLUNIFORM3FPROC glad_glUniform3f;
+#define glUniform3f glad_glUniform3f
+GLAD_API_CALL PFNGLUNIFORM3FVPROC glad_glUniform3fv;
+#define glUniform3fv glad_glUniform3fv
+GLAD_API_CALL PFNGLUNIFORM3IPROC glad_glUniform3i;
+#define glUniform3i glad_glUniform3i
+GLAD_API_CALL PFNGLUNIFORM3IVPROC glad_glUniform3iv;
+#define glUniform3iv glad_glUniform3iv
+GLAD_API_CALL PFNGLUNIFORM3UIPROC glad_glUniform3ui;
+#define glUniform3ui glad_glUniform3ui
+GLAD_API_CALL PFNGLUNIFORM3UIVPROC glad_glUniform3uiv;
+#define glUniform3uiv glad_glUniform3uiv
+GLAD_API_CALL PFNGLUNIFORM4FPROC glad_glUniform4f;
+#define glUniform4f glad_glUniform4f
+GLAD_API_CALL PFNGLUNIFORM4FVPROC glad_glUniform4fv;
+#define glUniform4fv glad_glUniform4fv
+GLAD_API_CALL PFNGLUNIFORM4IPROC glad_glUniform4i;
+#define glUniform4i glad_glUniform4i
+GLAD_API_CALL PFNGLUNIFORM4IVPROC glad_glUniform4iv;
+#define glUniform4iv glad_glUniform4iv
+GLAD_API_CALL PFNGLUNIFORM4UIPROC glad_glUniform4ui;
+#define glUniform4ui glad_glUniform4ui
+GLAD_API_CALL PFNGLUNIFORM4UIVPROC glad_glUniform4uiv;
+#define glUniform4uiv glad_glUniform4uiv
+GLAD_API_CALL PFNGLUNIFORMBLOCKBINDINGPROC glad_glUniformBlockBinding;
+#define glUniformBlockBinding glad_glUniformBlockBinding
+GLAD_API_CALL PFNGLUNIFORMMATRIX2FVPROC glad_glUniformMatrix2fv;
+#define glUniformMatrix2fv glad_glUniformMatrix2fv
+GLAD_API_CALL PFNGLUNIFORMMATRIX2X3FVPROC glad_glUniformMatrix2x3fv;
+#define glUniformMatrix2x3fv glad_glUniformMatrix2x3fv
+GLAD_API_CALL PFNGLUNIFORMMATRIX2X4FVPROC glad_glUniformMatrix2x4fv;
+#define glUniformMatrix2x4fv glad_glUniformMatrix2x4fv
+GLAD_API_CALL PFNGLUNIFORMMATRIX3FVPROC glad_glUniformMatrix3fv;
+#define glUniformMatrix3fv glad_glUniformMatrix3fv
+GLAD_API_CALL PFNGLUNIFORMMATRIX3X2FVPROC glad_glUniformMatrix3x2fv;
+#define glUniformMatrix3x2fv glad_glUniformMatrix3x2fv
+GLAD_API_CALL PFNGLUNIFORMMATRIX3X4FVPROC glad_glUniformMatrix3x4fv;
+#define glUniformMatrix3x4fv glad_glUniformMatrix3x4fv
+GLAD_API_CALL PFNGLUNIFORMMATRIX4FVPROC glad_glUniformMatrix4fv;
+#define glUniformMatrix4fv glad_glUniformMatrix4fv
+GLAD_API_CALL PFNGLUNIFORMMATRIX4X2FVPROC glad_glUniformMatrix4x2fv;
+#define glUniformMatrix4x2fv glad_glUniformMatrix4x2fv
+GLAD_API_CALL PFNGLUNIFORMMATRIX4X3FVPROC glad_glUniformMatrix4x3fv;
+#define glUniformMatrix4x3fv glad_glUniformMatrix4x3fv
+GLAD_API_CALL PFNGLUNMAPBUFFERPROC glad_glUnmapBuffer;
+#define glUnmapBuffer glad_glUnmapBuffer
+GLAD_API_CALL PFNGLUSEPROGRAMPROC glad_glUseProgram;
+#define glUseProgram glad_glUseProgram
+GLAD_API_CALL PFNGLVALIDATEPROGRAMPROC glad_glValidateProgram;
+#define glValidateProgram glad_glValidateProgram
+GLAD_API_CALL PFNGLVERTEX2DPROC glad_glVertex2d;
+#define glVertex2d glad_glVertex2d
+GLAD_API_CALL PFNGLVERTEX2DVPROC glad_glVertex2dv;
+#define glVertex2dv glad_glVertex2dv
+GLAD_API_CALL PFNGLVERTEX2FPROC glad_glVertex2f;
+#define glVertex2f glad_glVertex2f
+GLAD_API_CALL PFNGLVERTEX2FVPROC glad_glVertex2fv;
+#define glVertex2fv glad_glVertex2fv
+GLAD_API_CALL PFNGLVERTEX2IPROC glad_glVertex2i;
+#define glVertex2i glad_glVertex2i
+GLAD_API_CALL PFNGLVERTEX2IVPROC glad_glVertex2iv;
+#define glVertex2iv glad_glVertex2iv
+GLAD_API_CALL PFNGLVERTEX2SPROC glad_glVertex2s;
+#define glVertex2s glad_glVertex2s
+GLAD_API_CALL PFNGLVERTEX2SVPROC glad_glVertex2sv;
+#define glVertex2sv glad_glVertex2sv
+GLAD_API_CALL PFNGLVERTEX3DPROC glad_glVertex3d;
+#define glVertex3d glad_glVertex3d
+GLAD_API_CALL PFNGLVERTEX3DVPROC glad_glVertex3dv;
+#define glVertex3dv glad_glVertex3dv
+GLAD_API_CALL PFNGLVERTEX3FPROC glad_glVertex3f;
+#define glVertex3f glad_glVertex3f
+GLAD_API_CALL PFNGLVERTEX3FVPROC glad_glVertex3fv;
+#define glVertex3fv glad_glVertex3fv
+GLAD_API_CALL PFNGLVERTEX3IPROC glad_glVertex3i;
+#define glVertex3i glad_glVertex3i
+GLAD_API_CALL PFNGLVERTEX3IVPROC glad_glVertex3iv;
+#define glVertex3iv glad_glVertex3iv
+GLAD_API_CALL PFNGLVERTEX3SPROC glad_glVertex3s;
+#define glVertex3s glad_glVertex3s
+GLAD_API_CALL PFNGLVERTEX3SVPROC glad_glVertex3sv;
+#define glVertex3sv glad_glVertex3sv
+GLAD_API_CALL PFNGLVERTEX4DPROC glad_glVertex4d;
+#define glVertex4d glad_glVertex4d
+GLAD_API_CALL PFNGLVERTEX4DVPROC glad_glVertex4dv;
+#define glVertex4dv glad_glVertex4dv
+GLAD_API_CALL PFNGLVERTEX4FPROC glad_glVertex4f;
+#define glVertex4f glad_glVertex4f
+GLAD_API_CALL PFNGLVERTEX4FVPROC glad_glVertex4fv;
+#define glVertex4fv glad_glVertex4fv
+GLAD_API_CALL PFNGLVERTEX4IPROC glad_glVertex4i;
+#define glVertex4i glad_glVertex4i
+GLAD_API_CALL PFNGLVERTEX4IVPROC glad_glVertex4iv;
+#define glVertex4iv glad_glVertex4iv
+GLAD_API_CALL PFNGLVERTEX4SPROC glad_glVertex4s;
+#define glVertex4s glad_glVertex4s
+GLAD_API_CALL PFNGLVERTEX4SVPROC glad_glVertex4sv;
+#define glVertex4sv glad_glVertex4sv
+GLAD_API_CALL PFNGLVERTEXATTRIB1DPROC glad_glVertexAttrib1d;
+#define glVertexAttrib1d glad_glVertexAttrib1d
+GLAD_API_CALL PFNGLVERTEXATTRIB1DVPROC glad_glVertexAttrib1dv;
+#define glVertexAttrib1dv glad_glVertexAttrib1dv
+GLAD_API_CALL PFNGLVERTEXATTRIB1FPROC glad_glVertexAttrib1f;
+#define glVertexAttrib1f glad_glVertexAttrib1f
+GLAD_API_CALL PFNGLVERTEXATTRIB1FVPROC glad_glVertexAttrib1fv;
+#define glVertexAttrib1fv glad_glVertexAttrib1fv
+GLAD_API_CALL PFNGLVERTEXATTRIB1SPROC glad_glVertexAttrib1s;
+#define glVertexAttrib1s glad_glVertexAttrib1s
+GLAD_API_CALL PFNGLVERTEXATTRIB1SVPROC glad_glVertexAttrib1sv;
+#define glVertexAttrib1sv glad_glVertexAttrib1sv
+GLAD_API_CALL PFNGLVERTEXATTRIB2DPROC glad_glVertexAttrib2d;
+#define glVertexAttrib2d glad_glVertexAttrib2d
+GLAD_API_CALL PFNGLVERTEXATTRIB2DVPROC glad_glVertexAttrib2dv;
+#define glVertexAttrib2dv glad_glVertexAttrib2dv
+GLAD_API_CALL PFNGLVERTEXATTRIB2FPROC glad_glVertexAttrib2f;
+#define glVertexAttrib2f glad_glVertexAttrib2f
+GLAD_API_CALL PFNGLVERTEXATTRIB2FVPROC glad_glVertexAttrib2fv;
+#define glVertexAttrib2fv glad_glVertexAttrib2fv
+GLAD_API_CALL PFNGLVERTEXATTRIB2SPROC glad_glVertexAttrib2s;
+#define glVertexAttrib2s glad_glVertexAttrib2s
+GLAD_API_CALL PFNGLVERTEXATTRIB2SVPROC glad_glVertexAttrib2sv;
+#define glVertexAttrib2sv glad_glVertexAttrib2sv
+GLAD_API_CALL PFNGLVERTEXATTRIB3DPROC glad_glVertexAttrib3d;
+#define glVertexAttrib3d glad_glVertexAttrib3d
+GLAD_API_CALL PFNGLVERTEXATTRIB3DVPROC glad_glVertexAttrib3dv;
+#define glVertexAttrib3dv glad_glVertexAttrib3dv
+GLAD_API_CALL PFNGLVERTEXATTRIB3FPROC glad_glVertexAttrib3f;
+#define glVertexAttrib3f glad_glVertexAttrib3f
+GLAD_API_CALL PFNGLVERTEXATTRIB3FVPROC glad_glVertexAttrib3fv;
+#define glVertexAttrib3fv glad_glVertexAttrib3fv
+GLAD_API_CALL PFNGLVERTEXATTRIB3SPROC glad_glVertexAttrib3s;
+#define glVertexAttrib3s glad_glVertexAttrib3s
+GLAD_API_CALL PFNGLVERTEXATTRIB3SVPROC glad_glVertexAttrib3sv;
+#define glVertexAttrib3sv glad_glVertexAttrib3sv
+GLAD_API_CALL PFNGLVERTEXATTRIB4NBVPROC glad_glVertexAttrib4Nbv;
+#define glVertexAttrib4Nbv glad_glVertexAttrib4Nbv
+GLAD_API_CALL PFNGLVERTEXATTRIB4NIVPROC glad_glVertexAttrib4Niv;
+#define glVertexAttrib4Niv glad_glVertexAttrib4Niv
+GLAD_API_CALL PFNGLVERTEXATTRIB4NSVPROC glad_glVertexAttrib4Nsv;
+#define glVertexAttrib4Nsv glad_glVertexAttrib4Nsv
+GLAD_API_CALL PFNGLVERTEXATTRIB4NUBPROC glad_glVertexAttrib4Nub;
+#define glVertexAttrib4Nub glad_glVertexAttrib4Nub
+GLAD_API_CALL PFNGLVERTEXATTRIB4NUBVPROC glad_glVertexAttrib4Nubv;
+#define glVertexAttrib4Nubv glad_glVertexAttrib4Nubv
+GLAD_API_CALL PFNGLVERTEXATTRIB4NUIVPROC glad_glVertexAttrib4Nuiv;
+#define glVertexAttrib4Nuiv glad_glVertexAttrib4Nuiv
+GLAD_API_CALL PFNGLVERTEXATTRIB4NUSVPROC glad_glVertexAttrib4Nusv;
+#define glVertexAttrib4Nusv glad_glVertexAttrib4Nusv
+GLAD_API_CALL PFNGLVERTEXATTRIB4BVPROC glad_glVertexAttrib4bv;
+#define glVertexAttrib4bv glad_glVertexAttrib4bv
+GLAD_API_CALL PFNGLVERTEXATTRIB4DPROC glad_glVertexAttrib4d;
+#define glVertexAttrib4d glad_glVertexAttrib4d
+GLAD_API_CALL PFNGLVERTEXATTRIB4DVPROC glad_glVertexAttrib4dv;
+#define glVertexAttrib4dv glad_glVertexAttrib4dv
+GLAD_API_CALL PFNGLVERTEXATTRIB4FPROC glad_glVertexAttrib4f;
+#define glVertexAttrib4f glad_glVertexAttrib4f
+GLAD_API_CALL PFNGLVERTEXATTRIB4FVPROC glad_glVertexAttrib4fv;
+#define glVertexAttrib4fv glad_glVertexAttrib4fv
+GLAD_API_CALL PFNGLVERTEXATTRIB4IVPROC glad_glVertexAttrib4iv;
+#define glVertexAttrib4iv glad_glVertexAttrib4iv
+GLAD_API_CALL PFNGLVERTEXATTRIB4SPROC glad_glVertexAttrib4s;
+#define glVertexAttrib4s glad_glVertexAttrib4s
+GLAD_API_CALL PFNGLVERTEXATTRIB4SVPROC glad_glVertexAttrib4sv;
+#define glVertexAttrib4sv glad_glVertexAttrib4sv
+GLAD_API_CALL PFNGLVERTEXATTRIB4UBVPROC glad_glVertexAttrib4ubv;
+#define glVertexAttrib4ubv glad_glVertexAttrib4ubv
+GLAD_API_CALL PFNGLVERTEXATTRIB4UIVPROC glad_glVertexAttrib4uiv;
+#define glVertexAttrib4uiv glad_glVertexAttrib4uiv
+GLAD_API_CALL PFNGLVERTEXATTRIB4USVPROC glad_glVertexAttrib4usv;
+#define glVertexAttrib4usv glad_glVertexAttrib4usv
+GLAD_API_CALL PFNGLVERTEXATTRIBDIVISORPROC glad_glVertexAttribDivisor;
+#define glVertexAttribDivisor glad_glVertexAttribDivisor
+GLAD_API_CALL PFNGLVERTEXATTRIBI1IPROC glad_glVertexAttribI1i;
+#define glVertexAttribI1i glad_glVertexAttribI1i
+GLAD_API_CALL PFNGLVERTEXATTRIBI1IVPROC glad_glVertexAttribI1iv;
+#define glVertexAttribI1iv glad_glVertexAttribI1iv
+GLAD_API_CALL PFNGLVERTEXATTRIBI1UIPROC glad_glVertexAttribI1ui;
+#define glVertexAttribI1ui glad_glVertexAttribI1ui
+GLAD_API_CALL PFNGLVERTEXATTRIBI1UIVPROC glad_glVertexAttribI1uiv;
+#define glVertexAttribI1uiv glad_glVertexAttribI1uiv
+GLAD_API_CALL PFNGLVERTEXATTRIBI2IPROC glad_glVertexAttribI2i;
+#define glVertexAttribI2i glad_glVertexAttribI2i
+GLAD_API_CALL PFNGLVERTEXATTRIBI2IVPROC glad_glVertexAttribI2iv;
+#define glVertexAttribI2iv glad_glVertexAttribI2iv
+GLAD_API_CALL PFNGLVERTEXATTRIBI2UIPROC glad_glVertexAttribI2ui;
+#define glVertexAttribI2ui glad_glVertexAttribI2ui
+GLAD_API_CALL PFNGLVERTEXATTRIBI2UIVPROC glad_glVertexAttribI2uiv;
+#define glVertexAttribI2uiv glad_glVertexAttribI2uiv
+GLAD_API_CALL PFNGLVERTEXATTRIBI3IPROC glad_glVertexAttribI3i;
+#define glVertexAttribI3i glad_glVertexAttribI3i
+GLAD_API_CALL PFNGLVERTEXATTRIBI3IVPROC glad_glVertexAttribI3iv;
+#define glVertexAttribI3iv glad_glVertexAttribI3iv
+GLAD_API_CALL PFNGLVERTEXATTRIBI3UIPROC glad_glVertexAttribI3ui;
+#define glVertexAttribI3ui glad_glVertexAttribI3ui
+GLAD_API_CALL PFNGLVERTEXATTRIBI3UIVPROC glad_glVertexAttribI3uiv;
+#define glVertexAttribI3uiv glad_glVertexAttribI3uiv
+GLAD_API_CALL PFNGLVERTEXATTRIBI4BVPROC glad_glVertexAttribI4bv;
+#define glVertexAttribI4bv glad_glVertexAttribI4bv
+GLAD_API_CALL PFNGLVERTEXATTRIBI4IPROC glad_glVertexAttribI4i;
+#define glVertexAttribI4i glad_glVertexAttribI4i
+GLAD_API_CALL PFNGLVERTEXATTRIBI4IVPROC glad_glVertexAttribI4iv;
+#define glVertexAttribI4iv glad_glVertexAttribI4iv
+GLAD_API_CALL PFNGLVERTEXATTRIBI4SVPROC glad_glVertexAttribI4sv;
+#define glVertexAttribI4sv glad_glVertexAttribI4sv
+GLAD_API_CALL PFNGLVERTEXATTRIBI4UBVPROC glad_glVertexAttribI4ubv;
+#define glVertexAttribI4ubv glad_glVertexAttribI4ubv
+GLAD_API_CALL PFNGLVERTEXATTRIBI4UIPROC glad_glVertexAttribI4ui;
+#define glVertexAttribI4ui glad_glVertexAttribI4ui
+GLAD_API_CALL PFNGLVERTEXATTRIBI4UIVPROC glad_glVertexAttribI4uiv;
+#define glVertexAttribI4uiv glad_glVertexAttribI4uiv
+GLAD_API_CALL PFNGLVERTEXATTRIBI4USVPROC glad_glVertexAttribI4usv;
+#define glVertexAttribI4usv glad_glVertexAttribI4usv
+GLAD_API_CALL PFNGLVERTEXATTRIBIPOINTERPROC glad_glVertexAttribIPointer;
+#define glVertexAttribIPointer glad_glVertexAttribIPointer
+GLAD_API_CALL PFNGLVERTEXATTRIBP1UIPROC glad_glVertexAttribP1ui;
+#define glVertexAttribP1ui glad_glVertexAttribP1ui
+GLAD_API_CALL PFNGLVERTEXATTRIBP1UIVPROC glad_glVertexAttribP1uiv;
+#define glVertexAttribP1uiv glad_glVertexAttribP1uiv
+GLAD_API_CALL PFNGLVERTEXATTRIBP2UIPROC glad_glVertexAttribP2ui;
+#define glVertexAttribP2ui glad_glVertexAttribP2ui
+GLAD_API_CALL PFNGLVERTEXATTRIBP2UIVPROC glad_glVertexAttribP2uiv;
+#define glVertexAttribP2uiv glad_glVertexAttribP2uiv
+GLAD_API_CALL PFNGLVERTEXATTRIBP3UIPROC glad_glVertexAttribP3ui;
+#define glVertexAttribP3ui glad_glVertexAttribP3ui
+GLAD_API_CALL PFNGLVERTEXATTRIBP3UIVPROC glad_glVertexAttribP3uiv;
+#define glVertexAttribP3uiv glad_glVertexAttribP3uiv
+GLAD_API_CALL PFNGLVERTEXATTRIBP4UIPROC glad_glVertexAttribP4ui;
+#define glVertexAttribP4ui glad_glVertexAttribP4ui
+GLAD_API_CALL PFNGLVERTEXATTRIBP4UIVPROC glad_glVertexAttribP4uiv;
+#define glVertexAttribP4uiv glad_glVertexAttribP4uiv
+GLAD_API_CALL PFNGLVERTEXATTRIBPOINTERPROC glad_glVertexAttribPointer;
+#define glVertexAttribPointer glad_glVertexAttribPointer
+GLAD_API_CALL PFNGLVERTEXP2UIPROC glad_glVertexP2ui;
+#define glVertexP2ui glad_glVertexP2ui
+GLAD_API_CALL PFNGLVERTEXP2UIVPROC glad_glVertexP2uiv;
+#define glVertexP2uiv glad_glVertexP2uiv
+GLAD_API_CALL PFNGLVERTEXP3UIPROC glad_glVertexP3ui;
+#define glVertexP3ui glad_glVertexP3ui
+GLAD_API_CALL PFNGLVERTEXP3UIVPROC glad_glVertexP3uiv;
+#define glVertexP3uiv glad_glVertexP3uiv
+GLAD_API_CALL PFNGLVERTEXP4UIPROC glad_glVertexP4ui;
+#define glVertexP4ui glad_glVertexP4ui
+GLAD_API_CALL PFNGLVERTEXP4UIVPROC glad_glVertexP4uiv;
+#define glVertexP4uiv glad_glVertexP4uiv
+GLAD_API_CALL PFNGLVERTEXPOINTERPROC glad_glVertexPointer;
+#define glVertexPointer glad_glVertexPointer
+GLAD_API_CALL PFNGLVIEWPORTPROC glad_glViewport;
+#define glViewport glad_glViewport
+GLAD_API_CALL PFNGLWAITSYNCPROC glad_glWaitSync;
+#define glWaitSync glad_glWaitSync
+GLAD_API_CALL PFNGLWINDOWPOS2DPROC glad_glWindowPos2d;
+#define glWindowPos2d glad_glWindowPos2d
+GLAD_API_CALL PFNGLWINDOWPOS2DVPROC glad_glWindowPos2dv;
+#define glWindowPos2dv glad_glWindowPos2dv
+GLAD_API_CALL PFNGLWINDOWPOS2FPROC glad_glWindowPos2f;
+#define glWindowPos2f glad_glWindowPos2f
+GLAD_API_CALL PFNGLWINDOWPOS2FVPROC glad_glWindowPos2fv;
+#define glWindowPos2fv glad_glWindowPos2fv
+GLAD_API_CALL PFNGLWINDOWPOS2IPROC glad_glWindowPos2i;
+#define glWindowPos2i glad_glWindowPos2i
+GLAD_API_CALL PFNGLWINDOWPOS2IVPROC glad_glWindowPos2iv;
+#define glWindowPos2iv glad_glWindowPos2iv
+GLAD_API_CALL PFNGLWINDOWPOS2SPROC glad_glWindowPos2s;
+#define glWindowPos2s glad_glWindowPos2s
+GLAD_API_CALL PFNGLWINDOWPOS2SVPROC glad_glWindowPos2sv;
+#define glWindowPos2sv glad_glWindowPos2sv
+GLAD_API_CALL PFNGLWINDOWPOS3DPROC glad_glWindowPos3d;
+#define glWindowPos3d glad_glWindowPos3d
+GLAD_API_CALL PFNGLWINDOWPOS3DVPROC glad_glWindowPos3dv;
+#define glWindowPos3dv glad_glWindowPos3dv
+GLAD_API_CALL PFNGLWINDOWPOS3FPROC glad_glWindowPos3f;
+#define glWindowPos3f glad_glWindowPos3f
+GLAD_API_CALL PFNGLWINDOWPOS3FVPROC glad_glWindowPos3fv;
+#define glWindowPos3fv glad_glWindowPos3fv
+GLAD_API_CALL PFNGLWINDOWPOS3IPROC glad_glWindowPos3i;
+#define glWindowPos3i glad_glWindowPos3i
+GLAD_API_CALL PFNGLWINDOWPOS3IVPROC glad_glWindowPos3iv;
+#define glWindowPos3iv glad_glWindowPos3iv
+GLAD_API_CALL PFNGLWINDOWPOS3SPROC glad_glWindowPos3s;
+#define glWindowPos3s glad_glWindowPos3s
+GLAD_API_CALL PFNGLWINDOWPOS3SVPROC glad_glWindowPos3sv;
+#define glWindowPos3sv glad_glWindowPos3sv
+
+
+
+
+
+GLAD_API_CALL int gladLoadGLUserPtr( GLADuserptrloadfunc load, void *userptr);
+GLAD_API_CALL int gladLoadGL( GLADloadfunc load);
+
+
+#ifdef GLAD_GL
+
+GLAD_API_CALL int gladLoaderLoadGL(void);
+GLAD_API_CALL void gladLoaderUnloadGL(void);
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/thirdparty/glad/glad/glad.h b/thirdparty/glad/glad/glad.h
deleted file mode 100644
index 37d12e4ee2..0000000000
--- a/thirdparty/glad/glad/glad.h
+++ /dev/null
@@ -1,3801 +0,0 @@
-/*
-
- OpenGL loader generated by glad 0.1.36 on Sun Sep 4 15:50:32 2022.
-
- Language/Generator: C/C++
- Specification: gl
- APIs: gl=3.3
- Profile: compatibility
- Extensions:
- GL_ARB_debug_output,
- GL_ARB_framebuffer_object,
- GL_EXT_framebuffer_blit,
- GL_EXT_framebuffer_multisample,
- GL_EXT_framebuffer_object,
- GL_OVR_multiview,
- GL_OVR_multiview2
- Loader: True
- Local files: False
- Omit khrplatform: False
- Reproducible: False
-
- Commandline:
- --profile="compatibility" --api="gl=3.3" --generator="c" --spec="gl" --extensions="GL_ARB_debug_output,GL_ARB_framebuffer_object,GL_EXT_framebuffer_blit,GL_EXT_framebuffer_multisample,GL_EXT_framebuffer_object,GL_OVR_multiview,GL_OVR_multiview2"
- Online:
- https://glad.dav1d.de/#profile=compatibility&language=c&specification=gl&loader=on&api=gl%3D3.3&extensions=GL_ARB_debug_output&extensions=GL_ARB_framebuffer_object&extensions=GL_EXT_framebuffer_blit&extensions=GL_EXT_framebuffer_multisample&extensions=GL_EXT_framebuffer_object&extensions=GL_OVR_multiview&extensions=GL_OVR_multiview2
-*/
-
-
-#ifndef __glad_h_
-#define __glad_h_
-
-#ifdef __gl_h_
-#error OpenGL header already included, remove this include, glad already provides it
-#endif
-#define __gl_h_
-
-#if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__)
-#define APIENTRY __stdcall
-#endif
-
-#ifndef APIENTRY
-#define APIENTRY
-#endif
-#ifndef APIENTRYP
-#define APIENTRYP APIENTRY *
-#endif
-
-#ifndef GLAPIENTRY
-#define GLAPIENTRY APIENTRY
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct gladGLversionStruct {
- int major;
- int minor;
-};
-
-typedef void* (* GLADloadproc)(const char *name);
-
-#ifndef GLAPI
-# if defined(GLAD_GLAPI_EXPORT)
-# if defined(_WIN32) || defined(__CYGWIN__)
-# if defined(GLAD_GLAPI_EXPORT_BUILD)
-# if defined(__GNUC__)
-# define GLAPI __attribute__ ((dllexport)) extern
-# else
-# define GLAPI __declspec(dllexport) extern
-# endif
-# else
-# if defined(__GNUC__)
-# define GLAPI __attribute__ ((dllimport)) extern
-# else
-# define GLAPI __declspec(dllimport) extern
-# endif
-# endif
-# elif defined(__GNUC__) && defined(GLAD_GLAPI_EXPORT_BUILD)
-# define GLAPI __attribute__ ((visibility ("default"))) extern
-# else
-# define GLAPI extern
-# endif
-# else
-# define GLAPI extern
-# endif
-#endif
-
-GLAPI struct gladGLversionStruct GLVersion;
-
-GLAPI int gladLoadGL(void);
-
-GLAPI int gladLoadGLLoader(GLADloadproc);
-
-#include <KHR/khrplatform.h>
-typedef unsigned int GLenum;
-typedef unsigned char GLboolean;
-typedef unsigned int GLbitfield;
-typedef void GLvoid;
-typedef khronos_int8_t GLbyte;
-typedef khronos_uint8_t GLubyte;
-typedef khronos_int16_t GLshort;
-typedef khronos_uint16_t GLushort;
-typedef int GLint;
-typedef unsigned int GLuint;
-typedef khronos_int32_t GLclampx;
-typedef int GLsizei;
-typedef khronos_float_t GLfloat;
-typedef khronos_float_t GLclampf;
-typedef double GLdouble;
-typedef double GLclampd;
-typedef void *GLeglClientBufferEXT;
-typedef void *GLeglImageOES;
-typedef char GLchar;
-typedef char GLcharARB;
-#ifdef __APPLE__
-typedef void *GLhandleARB;
-#else
-typedef unsigned int GLhandleARB;
-#endif
-typedef khronos_uint16_t GLhalf;
-typedef khronos_uint16_t GLhalfARB;
-typedef khronos_int32_t GLfixed;
-typedef khronos_intptr_t GLintptr;
-typedef khronos_intptr_t GLintptrARB;
-typedef khronos_ssize_t GLsizeiptr;
-typedef khronos_ssize_t GLsizeiptrARB;
-typedef khronos_int64_t GLint64;
-typedef khronos_int64_t GLint64EXT;
-typedef khronos_uint64_t GLuint64;
-typedef khronos_uint64_t GLuint64EXT;
-typedef struct __GLsync *GLsync;
-struct _cl_context;
-struct _cl_event;
-typedef void (APIENTRY *GLDEBUGPROC)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam);
-typedef void (APIENTRY *GLDEBUGPROCARB)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam);
-typedef void (APIENTRY *GLDEBUGPROCKHR)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam);
-typedef void (APIENTRY *GLDEBUGPROCAMD)(GLuint id,GLenum category,GLenum severity,GLsizei length,const GLchar *message,void *userParam);
-typedef unsigned short GLhalfNV;
-typedef GLintptr GLvdpauSurfaceNV;
-typedef void (APIENTRY *GLVULKANPROCNV)(void);
-#define GL_DEPTH_BUFFER_BIT 0x00000100
-#define GL_STENCIL_BUFFER_BIT 0x00000400
-#define GL_COLOR_BUFFER_BIT 0x00004000
-#define GL_FALSE 0
-#define GL_TRUE 1
-#define GL_POINTS 0x0000
-#define GL_LINES 0x0001
-#define GL_LINE_LOOP 0x0002
-#define GL_LINE_STRIP 0x0003
-#define GL_TRIANGLES 0x0004
-#define GL_TRIANGLE_STRIP 0x0005
-#define GL_TRIANGLE_FAN 0x0006
-#define GL_QUADS 0x0007
-#define GL_NEVER 0x0200
-#define GL_LESS 0x0201
-#define GL_EQUAL 0x0202
-#define GL_LEQUAL 0x0203
-#define GL_GREATER 0x0204
-#define GL_NOTEQUAL 0x0205
-#define GL_GEQUAL 0x0206
-#define GL_ALWAYS 0x0207
-#define GL_ZERO 0
-#define GL_ONE 1
-#define GL_SRC_COLOR 0x0300
-#define GL_ONE_MINUS_SRC_COLOR 0x0301
-#define GL_SRC_ALPHA 0x0302
-#define GL_ONE_MINUS_SRC_ALPHA 0x0303
-#define GL_DST_ALPHA 0x0304
-#define GL_ONE_MINUS_DST_ALPHA 0x0305
-#define GL_DST_COLOR 0x0306
-#define GL_ONE_MINUS_DST_COLOR 0x0307
-#define GL_SRC_ALPHA_SATURATE 0x0308
-#define GL_NONE 0
-#define GL_FRONT_LEFT 0x0400
-#define GL_FRONT_RIGHT 0x0401
-#define GL_BACK_LEFT 0x0402
-#define GL_BACK_RIGHT 0x0403
-#define GL_FRONT 0x0404
-#define GL_BACK 0x0405
-#define GL_LEFT 0x0406
-#define GL_RIGHT 0x0407
-#define GL_FRONT_AND_BACK 0x0408
-#define GL_NO_ERROR 0
-#define GL_INVALID_ENUM 0x0500
-#define GL_INVALID_VALUE 0x0501
-#define GL_INVALID_OPERATION 0x0502
-#define GL_OUT_OF_MEMORY 0x0505
-#define GL_CW 0x0900
-#define GL_CCW 0x0901
-#define GL_POINT_SIZE 0x0B11
-#define GL_POINT_SIZE_RANGE 0x0B12
-#define GL_POINT_SIZE_GRANULARITY 0x0B13
-#define GL_LINE_SMOOTH 0x0B20
-#define GL_LINE_WIDTH 0x0B21
-#define GL_LINE_WIDTH_RANGE 0x0B22
-#define GL_LINE_WIDTH_GRANULARITY 0x0B23
-#define GL_POLYGON_MODE 0x0B40
-#define GL_POLYGON_SMOOTH 0x0B41
-#define GL_CULL_FACE 0x0B44
-#define GL_CULL_FACE_MODE 0x0B45
-#define GL_FRONT_FACE 0x0B46
-#define GL_DEPTH_RANGE 0x0B70
-#define GL_DEPTH_TEST 0x0B71
-#define GL_DEPTH_WRITEMASK 0x0B72
-#define GL_DEPTH_CLEAR_VALUE 0x0B73
-#define GL_DEPTH_FUNC 0x0B74
-#define GL_STENCIL_TEST 0x0B90
-#define GL_STENCIL_CLEAR_VALUE 0x0B91
-#define GL_STENCIL_FUNC 0x0B92
-#define GL_STENCIL_VALUE_MASK 0x0B93
-#define GL_STENCIL_FAIL 0x0B94
-#define GL_STENCIL_PASS_DEPTH_FAIL 0x0B95
-#define GL_STENCIL_PASS_DEPTH_PASS 0x0B96
-#define GL_STENCIL_REF 0x0B97
-#define GL_STENCIL_WRITEMASK 0x0B98
-#define GL_VIEWPORT 0x0BA2
-#define GL_DITHER 0x0BD0
-#define GL_BLEND_DST 0x0BE0
-#define GL_BLEND_SRC 0x0BE1
-#define GL_BLEND 0x0BE2
-#define GL_LOGIC_OP_MODE 0x0BF0
-#define GL_DRAW_BUFFER 0x0C01
-#define GL_READ_BUFFER 0x0C02
-#define GL_SCISSOR_BOX 0x0C10
-#define GL_SCISSOR_TEST 0x0C11
-#define GL_COLOR_CLEAR_VALUE 0x0C22
-#define GL_COLOR_WRITEMASK 0x0C23
-#define GL_DOUBLEBUFFER 0x0C32
-#define GL_STEREO 0x0C33
-#define GL_LINE_SMOOTH_HINT 0x0C52
-#define GL_POLYGON_SMOOTH_HINT 0x0C53
-#define GL_UNPACK_SWAP_BYTES 0x0CF0
-#define GL_UNPACK_LSB_FIRST 0x0CF1
-#define GL_UNPACK_ROW_LENGTH 0x0CF2
-#define GL_UNPACK_SKIP_ROWS 0x0CF3
-#define GL_UNPACK_SKIP_PIXELS 0x0CF4
-#define GL_UNPACK_ALIGNMENT 0x0CF5
-#define GL_PACK_SWAP_BYTES 0x0D00
-#define GL_PACK_LSB_FIRST 0x0D01
-#define GL_PACK_ROW_LENGTH 0x0D02
-#define GL_PACK_SKIP_ROWS 0x0D03
-#define GL_PACK_SKIP_PIXELS 0x0D04
-#define GL_PACK_ALIGNMENT 0x0D05
-#define GL_MAX_TEXTURE_SIZE 0x0D33
-#define GL_MAX_VIEWPORT_DIMS 0x0D3A
-#define GL_SUBPIXEL_BITS 0x0D50
-#define GL_TEXTURE_1D 0x0DE0
-#define GL_TEXTURE_2D 0x0DE1
-#define GL_TEXTURE_WIDTH 0x1000
-#define GL_TEXTURE_HEIGHT 0x1001
-#define GL_TEXTURE_BORDER_COLOR 0x1004
-#define GL_DONT_CARE 0x1100
-#define GL_FASTEST 0x1101
-#define GL_NICEST 0x1102
-#define GL_BYTE 0x1400
-#define GL_UNSIGNED_BYTE 0x1401
-#define GL_SHORT 0x1402
-#define GL_UNSIGNED_SHORT 0x1403
-#define GL_INT 0x1404
-#define GL_UNSIGNED_INT 0x1405
-#define GL_FLOAT 0x1406
-#define GL_STACK_OVERFLOW 0x0503
-#define GL_STACK_UNDERFLOW 0x0504
-#define GL_CLEAR 0x1500
-#define GL_AND 0x1501
-#define GL_AND_REVERSE 0x1502
-#define GL_COPY 0x1503
-#define GL_AND_INVERTED 0x1504
-#define GL_NOOP 0x1505
-#define GL_XOR 0x1506
-#define GL_OR 0x1507
-#define GL_NOR 0x1508
-#define GL_EQUIV 0x1509
-#define GL_INVERT 0x150A
-#define GL_OR_REVERSE 0x150B
-#define GL_COPY_INVERTED 0x150C
-#define GL_OR_INVERTED 0x150D
-#define GL_NAND 0x150E
-#define GL_SET 0x150F
-#define GL_TEXTURE 0x1702
-#define GL_COLOR 0x1800
-#define GL_DEPTH 0x1801
-#define GL_STENCIL 0x1802
-#define GL_STENCIL_INDEX 0x1901
-#define GL_DEPTH_COMPONENT 0x1902
-#define GL_RED 0x1903
-#define GL_GREEN 0x1904
-#define GL_BLUE 0x1905
-#define GL_ALPHA 0x1906
-#define GL_RGB 0x1907
-#define GL_RGBA 0x1908
-#define GL_POINT 0x1B00
-#define GL_LINE 0x1B01
-#define GL_FILL 0x1B02
-#define GL_KEEP 0x1E00
-#define GL_REPLACE 0x1E01
-#define GL_INCR 0x1E02
-#define GL_DECR 0x1E03
-#define GL_VENDOR 0x1F00
-#define GL_RENDERER 0x1F01
-#define GL_VERSION 0x1F02
-#define GL_EXTENSIONS 0x1F03
-#define GL_NEAREST 0x2600
-#define GL_LINEAR 0x2601
-#define GL_NEAREST_MIPMAP_NEAREST 0x2700
-#define GL_LINEAR_MIPMAP_NEAREST 0x2701
-#define GL_NEAREST_MIPMAP_LINEAR 0x2702
-#define GL_LINEAR_MIPMAP_LINEAR 0x2703
-#define GL_TEXTURE_MAG_FILTER 0x2800
-#define GL_TEXTURE_MIN_FILTER 0x2801
-#define GL_TEXTURE_WRAP_S 0x2802
-#define GL_TEXTURE_WRAP_T 0x2803
-#define GL_REPEAT 0x2901
-#define GL_CURRENT_BIT 0x00000001
-#define GL_POINT_BIT 0x00000002
-#define GL_LINE_BIT 0x00000004
-#define GL_POLYGON_BIT 0x00000008
-#define GL_POLYGON_STIPPLE_BIT 0x00000010
-#define GL_PIXEL_MODE_BIT 0x00000020
-#define GL_LIGHTING_BIT 0x00000040
-#define GL_FOG_BIT 0x00000080
-#define GL_ACCUM_BUFFER_BIT 0x00000200
-#define GL_VIEWPORT_BIT 0x00000800
-#define GL_TRANSFORM_BIT 0x00001000
-#define GL_ENABLE_BIT 0x00002000
-#define GL_HINT_BIT 0x00008000
-#define GL_EVAL_BIT 0x00010000
-#define GL_LIST_BIT 0x00020000
-#define GL_TEXTURE_BIT 0x00040000
-#define GL_SCISSOR_BIT 0x00080000
-#define GL_ALL_ATTRIB_BITS 0xFFFFFFFF
-#define GL_QUAD_STRIP 0x0008
-#define GL_POLYGON 0x0009
-#define GL_ACCUM 0x0100
-#define GL_LOAD 0x0101
-#define GL_RETURN 0x0102
-#define GL_MULT 0x0103
-#define GL_ADD 0x0104
-#define GL_AUX0 0x0409
-#define GL_AUX1 0x040A
-#define GL_AUX2 0x040B
-#define GL_AUX3 0x040C
-#define GL_2D 0x0600
-#define GL_3D 0x0601
-#define GL_3D_COLOR 0x0602
-#define GL_3D_COLOR_TEXTURE 0x0603
-#define GL_4D_COLOR_TEXTURE 0x0604
-#define GL_PASS_THROUGH_TOKEN 0x0700
-#define GL_POINT_TOKEN 0x0701
-#define GL_LINE_TOKEN 0x0702
-#define GL_POLYGON_TOKEN 0x0703
-#define GL_BITMAP_TOKEN 0x0704
-#define GL_DRAW_PIXEL_TOKEN 0x0705
-#define GL_COPY_PIXEL_TOKEN 0x0706
-#define GL_LINE_RESET_TOKEN 0x0707
-#define GL_EXP 0x0800
-#define GL_EXP2 0x0801
-#define GL_COEFF 0x0A00
-#define GL_ORDER 0x0A01
-#define GL_DOMAIN 0x0A02
-#define GL_PIXEL_MAP_I_TO_I 0x0C70
-#define GL_PIXEL_MAP_S_TO_S 0x0C71
-#define GL_PIXEL_MAP_I_TO_R 0x0C72
-#define GL_PIXEL_MAP_I_TO_G 0x0C73
-#define GL_PIXEL_MAP_I_TO_B 0x0C74
-#define GL_PIXEL_MAP_I_TO_A 0x0C75
-#define GL_PIXEL_MAP_R_TO_R 0x0C76
-#define GL_PIXEL_MAP_G_TO_G 0x0C77
-#define GL_PIXEL_MAP_B_TO_B 0x0C78
-#define GL_PIXEL_MAP_A_TO_A 0x0C79
-#define GL_CURRENT_COLOR 0x0B00
-#define GL_CURRENT_INDEX 0x0B01
-#define GL_CURRENT_NORMAL 0x0B02
-#define GL_CURRENT_TEXTURE_COORDS 0x0B03
-#define GL_CURRENT_RASTER_COLOR 0x0B04
-#define GL_CURRENT_RASTER_INDEX 0x0B05
-#define GL_CURRENT_RASTER_TEXTURE_COORDS 0x0B06
-#define GL_CURRENT_RASTER_POSITION 0x0B07
-#define GL_CURRENT_RASTER_POSITION_VALID 0x0B08
-#define GL_CURRENT_RASTER_DISTANCE 0x0B09
-#define GL_POINT_SMOOTH 0x0B10
-#define GL_LINE_STIPPLE 0x0B24
-#define GL_LINE_STIPPLE_PATTERN 0x0B25
-#define GL_LINE_STIPPLE_REPEAT 0x0B26
-#define GL_LIST_MODE 0x0B30
-#define GL_MAX_LIST_NESTING 0x0B31
-#define GL_LIST_BASE 0x0B32
-#define GL_LIST_INDEX 0x0B33
-#define GL_POLYGON_STIPPLE 0x0B42
-#define GL_EDGE_FLAG 0x0B43
-#define GL_LIGHTING 0x0B50
-#define GL_LIGHT_MODEL_LOCAL_VIEWER 0x0B51
-#define GL_LIGHT_MODEL_TWO_SIDE 0x0B52
-#define GL_LIGHT_MODEL_AMBIENT 0x0B53
-#define GL_SHADE_MODEL 0x0B54
-#define GL_COLOR_MATERIAL_FACE 0x0B55
-#define GL_COLOR_MATERIAL_PARAMETER 0x0B56
-#define GL_COLOR_MATERIAL 0x0B57
-#define GL_FOG 0x0B60
-#define GL_FOG_INDEX 0x0B61
-#define GL_FOG_DENSITY 0x0B62
-#define GL_FOG_START 0x0B63
-#define GL_FOG_END 0x0B64
-#define GL_FOG_MODE 0x0B65
-#define GL_FOG_COLOR 0x0B66
-#define GL_ACCUM_CLEAR_VALUE 0x0B80
-#define GL_MATRIX_MODE 0x0BA0
-#define GL_NORMALIZE 0x0BA1
-#define GL_MODELVIEW_STACK_DEPTH 0x0BA3
-#define GL_PROJECTION_STACK_DEPTH 0x0BA4
-#define GL_TEXTURE_STACK_DEPTH 0x0BA5
-#define GL_MODELVIEW_MATRIX 0x0BA6
-#define GL_PROJECTION_MATRIX 0x0BA7
-#define GL_TEXTURE_MATRIX 0x0BA8
-#define GL_ATTRIB_STACK_DEPTH 0x0BB0
-#define GL_ALPHA_TEST 0x0BC0
-#define GL_ALPHA_TEST_FUNC 0x0BC1
-#define GL_ALPHA_TEST_REF 0x0BC2
-#define GL_LOGIC_OP 0x0BF1
-#define GL_AUX_BUFFERS 0x0C00
-#define GL_INDEX_CLEAR_VALUE 0x0C20
-#define GL_INDEX_WRITEMASK 0x0C21
-#define GL_INDEX_MODE 0x0C30
-#define GL_RGBA_MODE 0x0C31
-#define GL_RENDER_MODE 0x0C40
-#define GL_PERSPECTIVE_CORRECTION_HINT 0x0C50
-#define GL_POINT_SMOOTH_HINT 0x0C51
-#define GL_FOG_HINT 0x0C54
-#define GL_TEXTURE_GEN_S 0x0C60
-#define GL_TEXTURE_GEN_T 0x0C61
-#define GL_TEXTURE_GEN_R 0x0C62
-#define GL_TEXTURE_GEN_Q 0x0C63
-#define GL_PIXEL_MAP_I_TO_I_SIZE 0x0CB0
-#define GL_PIXEL_MAP_S_TO_S_SIZE 0x0CB1
-#define GL_PIXEL_MAP_I_TO_R_SIZE 0x0CB2
-#define GL_PIXEL_MAP_I_TO_G_SIZE 0x0CB3
-#define GL_PIXEL_MAP_I_TO_B_SIZE 0x0CB4
-#define GL_PIXEL_MAP_I_TO_A_SIZE 0x0CB5
-#define GL_PIXEL_MAP_R_TO_R_SIZE 0x0CB6
-#define GL_PIXEL_MAP_G_TO_G_SIZE 0x0CB7
-#define GL_PIXEL_MAP_B_TO_B_SIZE 0x0CB8
-#define GL_PIXEL_MAP_A_TO_A_SIZE 0x0CB9
-#define GL_MAP_COLOR 0x0D10
-#define GL_MAP_STENCIL 0x0D11
-#define GL_INDEX_SHIFT 0x0D12
-#define GL_INDEX_OFFSET 0x0D13
-#define GL_RED_SCALE 0x0D14
-#define GL_RED_BIAS 0x0D15
-#define GL_ZOOM_X 0x0D16
-#define GL_ZOOM_Y 0x0D17
-#define GL_GREEN_SCALE 0x0D18
-#define GL_GREEN_BIAS 0x0D19
-#define GL_BLUE_SCALE 0x0D1A
-#define GL_BLUE_BIAS 0x0D1B
-#define GL_ALPHA_SCALE 0x0D1C
-#define GL_ALPHA_BIAS 0x0D1D
-#define GL_DEPTH_SCALE 0x0D1E
-#define GL_DEPTH_BIAS 0x0D1F
-#define GL_MAX_EVAL_ORDER 0x0D30
-#define GL_MAX_LIGHTS 0x0D31
-#define GL_MAX_CLIP_PLANES 0x0D32
-#define GL_MAX_PIXEL_MAP_TABLE 0x0D34
-#define GL_MAX_ATTRIB_STACK_DEPTH 0x0D35
-#define GL_MAX_MODELVIEW_STACK_DEPTH 0x0D36
-#define GL_MAX_NAME_STACK_DEPTH 0x0D37
-#define GL_MAX_PROJECTION_STACK_DEPTH 0x0D38
-#define GL_MAX_TEXTURE_STACK_DEPTH 0x0D39
-#define GL_INDEX_BITS 0x0D51
-#define GL_RED_BITS 0x0D52
-#define GL_GREEN_BITS 0x0D53
-#define GL_BLUE_BITS 0x0D54
-#define GL_ALPHA_BITS 0x0D55
-#define GL_DEPTH_BITS 0x0D56
-#define GL_STENCIL_BITS 0x0D57
-#define GL_ACCUM_RED_BITS 0x0D58
-#define GL_ACCUM_GREEN_BITS 0x0D59
-#define GL_ACCUM_BLUE_BITS 0x0D5A
-#define GL_ACCUM_ALPHA_BITS 0x0D5B
-#define GL_NAME_STACK_DEPTH 0x0D70
-#define GL_AUTO_NORMAL 0x0D80
-#define GL_MAP1_COLOR_4 0x0D90
-#define GL_MAP1_INDEX 0x0D91
-#define GL_MAP1_NORMAL 0x0D92
-#define GL_MAP1_TEXTURE_COORD_1 0x0D93
-#define GL_MAP1_TEXTURE_COORD_2 0x0D94
-#define GL_MAP1_TEXTURE_COORD_3 0x0D95
-#define GL_MAP1_TEXTURE_COORD_4 0x0D96
-#define GL_MAP1_VERTEX_3 0x0D97
-#define GL_MAP1_VERTEX_4 0x0D98
-#define GL_MAP2_COLOR_4 0x0DB0
-#define GL_MAP2_INDEX 0x0DB1
-#define GL_MAP2_NORMAL 0x0DB2
-#define GL_MAP2_TEXTURE_COORD_1 0x0DB3
-#define GL_MAP2_TEXTURE_COORD_2 0x0DB4
-#define GL_MAP2_TEXTURE_COORD_3 0x0DB5
-#define GL_MAP2_TEXTURE_COORD_4 0x0DB6
-#define GL_MAP2_VERTEX_3 0x0DB7
-#define GL_MAP2_VERTEX_4 0x0DB8
-#define GL_MAP1_GRID_DOMAIN 0x0DD0
-#define GL_MAP1_GRID_SEGMENTS 0x0DD1
-#define GL_MAP2_GRID_DOMAIN 0x0DD2
-#define GL_MAP2_GRID_SEGMENTS 0x0DD3
-#define GL_TEXTURE_COMPONENTS 0x1003
-#define GL_TEXTURE_BORDER 0x1005
-#define GL_AMBIENT 0x1200
-#define GL_DIFFUSE 0x1201
-#define GL_SPECULAR 0x1202
-#define GL_POSITION 0x1203
-#define GL_SPOT_DIRECTION 0x1204
-#define GL_SPOT_EXPONENT 0x1205
-#define GL_SPOT_CUTOFF 0x1206
-#define GL_CONSTANT_ATTENUATION 0x1207
-#define GL_LINEAR_ATTENUATION 0x1208
-#define GL_QUADRATIC_ATTENUATION 0x1209
-#define GL_COMPILE 0x1300
-#define GL_COMPILE_AND_EXECUTE 0x1301
-#define GL_2_BYTES 0x1407
-#define GL_3_BYTES 0x1408
-#define GL_4_BYTES 0x1409
-#define GL_EMISSION 0x1600
-#define GL_SHININESS 0x1601
-#define GL_AMBIENT_AND_DIFFUSE 0x1602
-#define GL_COLOR_INDEXES 0x1603
-#define GL_MODELVIEW 0x1700
-#define GL_PROJECTION 0x1701
-#define GL_COLOR_INDEX 0x1900
-#define GL_LUMINANCE 0x1909
-#define GL_LUMINANCE_ALPHA 0x190A
-#define GL_BITMAP 0x1A00
-#define GL_RENDER 0x1C00
-#define GL_FEEDBACK 0x1C01
-#define GL_SELECT 0x1C02
-#define GL_FLAT 0x1D00
-#define GL_SMOOTH 0x1D01
-#define GL_S 0x2000
-#define GL_T 0x2001
-#define GL_R 0x2002
-#define GL_Q 0x2003
-#define GL_MODULATE 0x2100
-#define GL_DECAL 0x2101
-#define GL_TEXTURE_ENV_MODE 0x2200
-#define GL_TEXTURE_ENV_COLOR 0x2201
-#define GL_TEXTURE_ENV 0x2300
-#define GL_EYE_LINEAR 0x2400
-#define GL_OBJECT_LINEAR 0x2401
-#define GL_SPHERE_MAP 0x2402
-#define GL_TEXTURE_GEN_MODE 0x2500
-#define GL_OBJECT_PLANE 0x2501
-#define GL_EYE_PLANE 0x2502
-#define GL_CLAMP 0x2900
-#define GL_CLIP_PLANE0 0x3000
-#define GL_CLIP_PLANE1 0x3001
-#define GL_CLIP_PLANE2 0x3002
-#define GL_CLIP_PLANE3 0x3003
-#define GL_CLIP_PLANE4 0x3004
-#define GL_CLIP_PLANE5 0x3005
-#define GL_LIGHT0 0x4000
-#define GL_LIGHT1 0x4001
-#define GL_LIGHT2 0x4002
-#define GL_LIGHT3 0x4003
-#define GL_LIGHT4 0x4004
-#define GL_LIGHT5 0x4005
-#define GL_LIGHT6 0x4006
-#define GL_LIGHT7 0x4007
-#define GL_COLOR_LOGIC_OP 0x0BF2
-#define GL_POLYGON_OFFSET_UNITS 0x2A00
-#define GL_POLYGON_OFFSET_POINT 0x2A01
-#define GL_POLYGON_OFFSET_LINE 0x2A02
-#define GL_POLYGON_OFFSET_FILL 0x8037
-#define GL_POLYGON_OFFSET_FACTOR 0x8038
-#define GL_TEXTURE_BINDING_1D 0x8068
-#define GL_TEXTURE_BINDING_2D 0x8069
-#define GL_TEXTURE_INTERNAL_FORMAT 0x1003
-#define GL_TEXTURE_RED_SIZE 0x805C
-#define GL_TEXTURE_GREEN_SIZE 0x805D
-#define GL_TEXTURE_BLUE_SIZE 0x805E
-#define GL_TEXTURE_ALPHA_SIZE 0x805F
-#define GL_DOUBLE 0x140A
-#define GL_PROXY_TEXTURE_1D 0x8063
-#define GL_PROXY_TEXTURE_2D 0x8064
-#define GL_R3_G3_B2 0x2A10
-#define GL_RGB4 0x804F
-#define GL_RGB5 0x8050
-#define GL_RGB8 0x8051
-#define GL_RGB10 0x8052
-#define GL_RGB12 0x8053
-#define GL_RGB16 0x8054
-#define GL_RGBA2 0x8055
-#define GL_RGBA4 0x8056
-#define GL_RGB5_A1 0x8057
-#define GL_RGBA8 0x8058
-#define GL_RGB10_A2 0x8059
-#define GL_RGBA12 0x805A
-#define GL_RGBA16 0x805B
-#define GL_CLIENT_PIXEL_STORE_BIT 0x00000001
-#define GL_CLIENT_VERTEX_ARRAY_BIT 0x00000002
-#define GL_CLIENT_ALL_ATTRIB_BITS 0xFFFFFFFF
-#define GL_VERTEX_ARRAY_POINTER 0x808E
-#define GL_NORMAL_ARRAY_POINTER 0x808F
-#define GL_COLOR_ARRAY_POINTER 0x8090
-#define GL_INDEX_ARRAY_POINTER 0x8091
-#define GL_TEXTURE_COORD_ARRAY_POINTER 0x8092
-#define GL_EDGE_FLAG_ARRAY_POINTER 0x8093
-#define GL_FEEDBACK_BUFFER_POINTER 0x0DF0
-#define GL_SELECTION_BUFFER_POINTER 0x0DF3
-#define GL_CLIENT_ATTRIB_STACK_DEPTH 0x0BB1
-#define GL_INDEX_LOGIC_OP 0x0BF1
-#define GL_MAX_CLIENT_ATTRIB_STACK_DEPTH 0x0D3B
-#define GL_FEEDBACK_BUFFER_SIZE 0x0DF1
-#define GL_FEEDBACK_BUFFER_TYPE 0x0DF2
-#define GL_SELECTION_BUFFER_SIZE 0x0DF4
-#define GL_VERTEX_ARRAY 0x8074
-#define GL_NORMAL_ARRAY 0x8075
-#define GL_COLOR_ARRAY 0x8076
-#define GL_INDEX_ARRAY 0x8077
-#define GL_TEXTURE_COORD_ARRAY 0x8078
-#define GL_EDGE_FLAG_ARRAY 0x8079
-#define GL_VERTEX_ARRAY_SIZE 0x807A
-#define GL_VERTEX_ARRAY_TYPE 0x807B
-#define GL_VERTEX_ARRAY_STRIDE 0x807C
-#define GL_NORMAL_ARRAY_TYPE 0x807E
-#define GL_NORMAL_ARRAY_STRIDE 0x807F
-#define GL_COLOR_ARRAY_SIZE 0x8081
-#define GL_COLOR_ARRAY_TYPE 0x8082
-#define GL_COLOR_ARRAY_STRIDE 0x8083
-#define GL_INDEX_ARRAY_TYPE 0x8085
-#define GL_INDEX_ARRAY_STRIDE 0x8086
-#define GL_TEXTURE_COORD_ARRAY_SIZE 0x8088
-#define GL_TEXTURE_COORD_ARRAY_TYPE 0x8089
-#define GL_TEXTURE_COORD_ARRAY_STRIDE 0x808A
-#define GL_EDGE_FLAG_ARRAY_STRIDE 0x808C
-#define GL_TEXTURE_LUMINANCE_SIZE 0x8060
-#define GL_TEXTURE_INTENSITY_SIZE 0x8061
-#define GL_TEXTURE_PRIORITY 0x8066
-#define GL_TEXTURE_RESIDENT 0x8067
-#define GL_ALPHA4 0x803B
-#define GL_ALPHA8 0x803C
-#define GL_ALPHA12 0x803D
-#define GL_ALPHA16 0x803E
-#define GL_LUMINANCE4 0x803F
-#define GL_LUMINANCE8 0x8040
-#define GL_LUMINANCE12 0x8041
-#define GL_LUMINANCE16 0x8042
-#define GL_LUMINANCE4_ALPHA4 0x8043
-#define GL_LUMINANCE6_ALPHA2 0x8044
-#define GL_LUMINANCE8_ALPHA8 0x8045
-#define GL_LUMINANCE12_ALPHA4 0x8046
-#define GL_LUMINANCE12_ALPHA12 0x8047
-#define GL_LUMINANCE16_ALPHA16 0x8048
-#define GL_INTENSITY 0x8049
-#define GL_INTENSITY4 0x804A
-#define GL_INTENSITY8 0x804B
-#define GL_INTENSITY12 0x804C
-#define GL_INTENSITY16 0x804D
-#define GL_V2F 0x2A20
-#define GL_V3F 0x2A21
-#define GL_C4UB_V2F 0x2A22
-#define GL_C4UB_V3F 0x2A23
-#define GL_C3F_V3F 0x2A24
-#define GL_N3F_V3F 0x2A25
-#define GL_C4F_N3F_V3F 0x2A26
-#define GL_T2F_V3F 0x2A27
-#define GL_T4F_V4F 0x2A28
-#define GL_T2F_C4UB_V3F 0x2A29
-#define GL_T2F_C3F_V3F 0x2A2A
-#define GL_T2F_N3F_V3F 0x2A2B
-#define GL_T2F_C4F_N3F_V3F 0x2A2C
-#define GL_T4F_C4F_N3F_V4F 0x2A2D
-#define GL_UNSIGNED_BYTE_3_3_2 0x8032
-#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033
-#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034
-#define GL_UNSIGNED_INT_8_8_8_8 0x8035
-#define GL_UNSIGNED_INT_10_10_10_2 0x8036
-#define GL_TEXTURE_BINDING_3D 0x806A
-#define GL_PACK_SKIP_IMAGES 0x806B
-#define GL_PACK_IMAGE_HEIGHT 0x806C
-#define GL_UNPACK_SKIP_IMAGES 0x806D
-#define GL_UNPACK_IMAGE_HEIGHT 0x806E
-#define GL_TEXTURE_3D 0x806F
-#define GL_PROXY_TEXTURE_3D 0x8070
-#define GL_TEXTURE_DEPTH 0x8071
-#define GL_TEXTURE_WRAP_R 0x8072
-#define GL_MAX_3D_TEXTURE_SIZE 0x8073
-#define GL_UNSIGNED_BYTE_2_3_3_REV 0x8362
-#define GL_UNSIGNED_SHORT_5_6_5 0x8363
-#define GL_UNSIGNED_SHORT_5_6_5_REV 0x8364
-#define GL_UNSIGNED_SHORT_4_4_4_4_REV 0x8365
-#define GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366
-#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367
-#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368
-#define GL_BGR 0x80E0
-#define GL_BGRA 0x80E1
-#define GL_MAX_ELEMENTS_VERTICES 0x80E8
-#define GL_MAX_ELEMENTS_INDICES 0x80E9
-#define GL_CLAMP_TO_EDGE 0x812F
-#define GL_TEXTURE_MIN_LOD 0x813A
-#define GL_TEXTURE_MAX_LOD 0x813B
-#define GL_TEXTURE_BASE_LEVEL 0x813C
-#define GL_TEXTURE_MAX_LEVEL 0x813D
-#define GL_SMOOTH_POINT_SIZE_RANGE 0x0B12
-#define GL_SMOOTH_POINT_SIZE_GRANULARITY 0x0B13
-#define GL_SMOOTH_LINE_WIDTH_RANGE 0x0B22
-#define GL_SMOOTH_LINE_WIDTH_GRANULARITY 0x0B23
-#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E
-#define GL_RESCALE_NORMAL 0x803A
-#define GL_LIGHT_MODEL_COLOR_CONTROL 0x81F8
-#define GL_SINGLE_COLOR 0x81F9
-#define GL_SEPARATE_SPECULAR_COLOR 0x81FA
-#define GL_ALIASED_POINT_SIZE_RANGE 0x846D
-#define GL_TEXTURE0 0x84C0
-#define GL_TEXTURE1 0x84C1
-#define GL_TEXTURE2 0x84C2
-#define GL_TEXTURE3 0x84C3
-#define GL_TEXTURE4 0x84C4
-#define GL_TEXTURE5 0x84C5
-#define GL_TEXTURE6 0x84C6
-#define GL_TEXTURE7 0x84C7
-#define GL_TEXTURE8 0x84C8
-#define GL_TEXTURE9 0x84C9
-#define GL_TEXTURE10 0x84CA
-#define GL_TEXTURE11 0x84CB
-#define GL_TEXTURE12 0x84CC
-#define GL_TEXTURE13 0x84CD
-#define GL_TEXTURE14 0x84CE
-#define GL_TEXTURE15 0x84CF
-#define GL_TEXTURE16 0x84D0
-#define GL_TEXTURE17 0x84D1
-#define GL_TEXTURE18 0x84D2
-#define GL_TEXTURE19 0x84D3
-#define GL_TEXTURE20 0x84D4
-#define GL_TEXTURE21 0x84D5
-#define GL_TEXTURE22 0x84D6
-#define GL_TEXTURE23 0x84D7
-#define GL_TEXTURE24 0x84D8
-#define GL_TEXTURE25 0x84D9
-#define GL_TEXTURE26 0x84DA
-#define GL_TEXTURE27 0x84DB
-#define GL_TEXTURE28 0x84DC
-#define GL_TEXTURE29 0x84DD
-#define GL_TEXTURE30 0x84DE
-#define GL_TEXTURE31 0x84DF
-#define GL_ACTIVE_TEXTURE 0x84E0
-#define GL_MULTISAMPLE 0x809D
-#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E
-#define GL_SAMPLE_ALPHA_TO_ONE 0x809F
-#define GL_SAMPLE_COVERAGE 0x80A0
-#define GL_SAMPLE_BUFFERS 0x80A8
-#define GL_SAMPLES 0x80A9
-#define GL_SAMPLE_COVERAGE_VALUE 0x80AA
-#define GL_SAMPLE_COVERAGE_INVERT 0x80AB
-#define GL_TEXTURE_CUBE_MAP 0x8513
-#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514
-#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515
-#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516
-#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517
-#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518
-#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519
-#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A
-#define GL_PROXY_TEXTURE_CUBE_MAP 0x851B
-#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C
-#define GL_COMPRESSED_RGB 0x84ED
-#define GL_COMPRESSED_RGBA 0x84EE
-#define GL_TEXTURE_COMPRESSION_HINT 0x84EF
-#define GL_TEXTURE_COMPRESSED_IMAGE_SIZE 0x86A0
-#define GL_TEXTURE_COMPRESSED 0x86A1
-#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2
-#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3
-#define GL_CLAMP_TO_BORDER 0x812D
-#define GL_CLIENT_ACTIVE_TEXTURE 0x84E1
-#define GL_MAX_TEXTURE_UNITS 0x84E2
-#define GL_TRANSPOSE_MODELVIEW_MATRIX 0x84E3
-#define GL_TRANSPOSE_PROJECTION_MATRIX 0x84E4
-#define GL_TRANSPOSE_TEXTURE_MATRIX 0x84E5
-#define GL_TRANSPOSE_COLOR_MATRIX 0x84E6
-#define GL_MULTISAMPLE_BIT 0x20000000
-#define GL_NORMAL_MAP 0x8511
-#define GL_REFLECTION_MAP 0x8512
-#define GL_COMPRESSED_ALPHA 0x84E9
-#define GL_COMPRESSED_LUMINANCE 0x84EA
-#define GL_COMPRESSED_LUMINANCE_ALPHA 0x84EB
-#define GL_COMPRESSED_INTENSITY 0x84EC
-#define GL_COMBINE 0x8570
-#define GL_COMBINE_RGB 0x8571
-#define GL_COMBINE_ALPHA 0x8572
-#define GL_SOURCE0_RGB 0x8580
-#define GL_SOURCE1_RGB 0x8581
-#define GL_SOURCE2_RGB 0x8582
-#define GL_SOURCE0_ALPHA 0x8588
-#define GL_SOURCE1_ALPHA 0x8589
-#define GL_SOURCE2_ALPHA 0x858A
-#define GL_OPERAND0_RGB 0x8590
-#define GL_OPERAND1_RGB 0x8591
-#define GL_OPERAND2_RGB 0x8592
-#define GL_OPERAND0_ALPHA 0x8598
-#define GL_OPERAND1_ALPHA 0x8599
-#define GL_OPERAND2_ALPHA 0x859A
-#define GL_RGB_SCALE 0x8573
-#define GL_ADD_SIGNED 0x8574
-#define GL_INTERPOLATE 0x8575
-#define GL_SUBTRACT 0x84E7
-#define GL_CONSTANT 0x8576
-#define GL_PRIMARY_COLOR 0x8577
-#define GL_PREVIOUS 0x8578
-#define GL_DOT3_RGB 0x86AE
-#define GL_DOT3_RGBA 0x86AF
-#define GL_BLEND_DST_RGB 0x80C8
-#define GL_BLEND_SRC_RGB 0x80C9
-#define GL_BLEND_DST_ALPHA 0x80CA
-#define GL_BLEND_SRC_ALPHA 0x80CB
-#define GL_POINT_FADE_THRESHOLD_SIZE 0x8128
-#define GL_DEPTH_COMPONENT16 0x81A5
-#define GL_DEPTH_COMPONENT24 0x81A6
-#define GL_DEPTH_COMPONENT32 0x81A7
-#define GL_MIRRORED_REPEAT 0x8370
-#define GL_MAX_TEXTURE_LOD_BIAS 0x84FD
-#define GL_TEXTURE_LOD_BIAS 0x8501
-#define GL_INCR_WRAP 0x8507
-#define GL_DECR_WRAP 0x8508
-#define GL_TEXTURE_DEPTH_SIZE 0x884A
-#define GL_TEXTURE_COMPARE_MODE 0x884C
-#define GL_TEXTURE_COMPARE_FUNC 0x884D
-#define GL_POINT_SIZE_MIN 0x8126
-#define GL_POINT_SIZE_MAX 0x8127
-#define GL_POINT_DISTANCE_ATTENUATION 0x8129
-#define GL_GENERATE_MIPMAP 0x8191
-#define GL_GENERATE_MIPMAP_HINT 0x8192
-#define GL_FOG_COORDINATE_SOURCE 0x8450
-#define GL_FOG_COORDINATE 0x8451
-#define GL_FRAGMENT_DEPTH 0x8452
-#define GL_CURRENT_FOG_COORDINATE 0x8453
-#define GL_FOG_COORDINATE_ARRAY_TYPE 0x8454
-#define GL_FOG_COORDINATE_ARRAY_STRIDE 0x8455
-#define GL_FOG_COORDINATE_ARRAY_POINTER 0x8456
-#define GL_FOG_COORDINATE_ARRAY 0x8457
-#define GL_COLOR_SUM 0x8458
-#define GL_CURRENT_SECONDARY_COLOR 0x8459
-#define GL_SECONDARY_COLOR_ARRAY_SIZE 0x845A
-#define GL_SECONDARY_COLOR_ARRAY_TYPE 0x845B
-#define GL_SECONDARY_COLOR_ARRAY_STRIDE 0x845C
-#define GL_SECONDARY_COLOR_ARRAY_POINTER 0x845D
-#define GL_SECONDARY_COLOR_ARRAY 0x845E
-#define GL_TEXTURE_FILTER_CONTROL 0x8500
-#define GL_DEPTH_TEXTURE_MODE 0x884B
-#define GL_COMPARE_R_TO_TEXTURE 0x884E
-#define GL_BLEND_COLOR 0x8005
-#define GL_BLEND_EQUATION 0x8009
-#define GL_CONSTANT_COLOR 0x8001
-#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002
-#define GL_CONSTANT_ALPHA 0x8003
-#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004
-#define GL_FUNC_ADD 0x8006
-#define GL_FUNC_REVERSE_SUBTRACT 0x800B
-#define GL_FUNC_SUBTRACT 0x800A
-#define GL_MIN 0x8007
-#define GL_MAX 0x8008
-#define GL_BUFFER_SIZE 0x8764
-#define GL_BUFFER_USAGE 0x8765
-#define GL_QUERY_COUNTER_BITS 0x8864
-#define GL_CURRENT_QUERY 0x8865
-#define GL_QUERY_RESULT 0x8866
-#define GL_QUERY_RESULT_AVAILABLE 0x8867
-#define GL_ARRAY_BUFFER 0x8892
-#define GL_ELEMENT_ARRAY_BUFFER 0x8893
-#define GL_ARRAY_BUFFER_BINDING 0x8894
-#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895
-#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F
-#define GL_READ_ONLY 0x88B8
-#define GL_WRITE_ONLY 0x88B9
-#define GL_READ_WRITE 0x88BA
-#define GL_BUFFER_ACCESS 0x88BB
-#define GL_BUFFER_MAPPED 0x88BC
-#define GL_BUFFER_MAP_POINTER 0x88BD
-#define GL_STREAM_DRAW 0x88E0
-#define GL_STREAM_READ 0x88E1
-#define GL_STREAM_COPY 0x88E2
-#define GL_STATIC_DRAW 0x88E4
-#define GL_STATIC_READ 0x88E5
-#define GL_STATIC_COPY 0x88E6
-#define GL_DYNAMIC_DRAW 0x88E8
-#define GL_DYNAMIC_READ 0x88E9
-#define GL_DYNAMIC_COPY 0x88EA
-#define GL_SAMPLES_PASSED 0x8914
-#define GL_SRC1_ALPHA 0x8589
-#define GL_VERTEX_ARRAY_BUFFER_BINDING 0x8896
-#define GL_NORMAL_ARRAY_BUFFER_BINDING 0x8897
-#define GL_COLOR_ARRAY_BUFFER_BINDING 0x8898
-#define GL_INDEX_ARRAY_BUFFER_BINDING 0x8899
-#define GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING 0x889A
-#define GL_EDGE_FLAG_ARRAY_BUFFER_BINDING 0x889B
-#define GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING 0x889C
-#define GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING 0x889D
-#define GL_WEIGHT_ARRAY_BUFFER_BINDING 0x889E
-#define GL_FOG_COORD_SRC 0x8450
-#define GL_FOG_COORD 0x8451
-#define GL_CURRENT_FOG_COORD 0x8453
-#define GL_FOG_COORD_ARRAY_TYPE 0x8454
-#define GL_FOG_COORD_ARRAY_STRIDE 0x8455
-#define GL_FOG_COORD_ARRAY_POINTER 0x8456
-#define GL_FOG_COORD_ARRAY 0x8457
-#define GL_FOG_COORD_ARRAY_BUFFER_BINDING 0x889D
-#define GL_SRC0_RGB 0x8580
-#define GL_SRC1_RGB 0x8581
-#define GL_SRC2_RGB 0x8582
-#define GL_SRC0_ALPHA 0x8588
-#define GL_SRC2_ALPHA 0x858A
-#define GL_BLEND_EQUATION_RGB 0x8009
-#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622
-#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623
-#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624
-#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625
-#define GL_CURRENT_VERTEX_ATTRIB 0x8626
-#define GL_VERTEX_PROGRAM_POINT_SIZE 0x8642
-#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645
-#define GL_STENCIL_BACK_FUNC 0x8800
-#define GL_STENCIL_BACK_FAIL 0x8801
-#define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802
-#define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803
-#define GL_MAX_DRAW_BUFFERS 0x8824
-#define GL_DRAW_BUFFER0 0x8825
-#define GL_DRAW_BUFFER1 0x8826
-#define GL_DRAW_BUFFER2 0x8827
-#define GL_DRAW_BUFFER3 0x8828
-#define GL_DRAW_BUFFER4 0x8829
-#define GL_DRAW_BUFFER5 0x882A
-#define GL_DRAW_BUFFER6 0x882B
-#define GL_DRAW_BUFFER7 0x882C
-#define GL_DRAW_BUFFER8 0x882D
-#define GL_DRAW_BUFFER9 0x882E
-#define GL_DRAW_BUFFER10 0x882F
-#define GL_DRAW_BUFFER11 0x8830
-#define GL_DRAW_BUFFER12 0x8831
-#define GL_DRAW_BUFFER13 0x8832
-#define GL_DRAW_BUFFER14 0x8833
-#define GL_DRAW_BUFFER15 0x8834
-#define GL_BLEND_EQUATION_ALPHA 0x883D
-#define GL_MAX_VERTEX_ATTRIBS 0x8869
-#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A
-#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872
-#define GL_FRAGMENT_SHADER 0x8B30
-#define GL_VERTEX_SHADER 0x8B31
-#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS 0x8B49
-#define GL_MAX_VERTEX_UNIFORM_COMPONENTS 0x8B4A
-#define GL_MAX_VARYING_FLOATS 0x8B4B
-#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C
-#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D
-#define GL_SHADER_TYPE 0x8B4F
-#define GL_FLOAT_VEC2 0x8B50
-#define GL_FLOAT_VEC3 0x8B51
-#define GL_FLOAT_VEC4 0x8B52
-#define GL_INT_VEC2 0x8B53
-#define GL_INT_VEC3 0x8B54
-#define GL_INT_VEC4 0x8B55
-#define GL_BOOL 0x8B56
-#define GL_BOOL_VEC2 0x8B57
-#define GL_BOOL_VEC3 0x8B58
-#define GL_BOOL_VEC4 0x8B59
-#define GL_FLOAT_MAT2 0x8B5A
-#define GL_FLOAT_MAT3 0x8B5B
-#define GL_FLOAT_MAT4 0x8B5C
-#define GL_SAMPLER_1D 0x8B5D
-#define GL_SAMPLER_2D 0x8B5E
-#define GL_SAMPLER_3D 0x8B5F
-#define GL_SAMPLER_CUBE 0x8B60
-#define GL_SAMPLER_1D_SHADOW 0x8B61
-#define GL_SAMPLER_2D_SHADOW 0x8B62
-#define GL_DELETE_STATUS 0x8B80
-#define GL_COMPILE_STATUS 0x8B81
-#define GL_LINK_STATUS 0x8B82
-#define GL_VALIDATE_STATUS 0x8B83
-#define GL_INFO_LOG_LENGTH 0x8B84
-#define GL_ATTACHED_SHADERS 0x8B85
-#define GL_ACTIVE_UNIFORMS 0x8B86
-#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87
-#define GL_SHADER_SOURCE_LENGTH 0x8B88
-#define GL_ACTIVE_ATTRIBUTES 0x8B89
-#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A
-#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT 0x8B8B
-#define GL_SHADING_LANGUAGE_VERSION 0x8B8C
-#define GL_CURRENT_PROGRAM 0x8B8D
-#define GL_POINT_SPRITE_COORD_ORIGIN 0x8CA0
-#define GL_LOWER_LEFT 0x8CA1
-#define GL_UPPER_LEFT 0x8CA2
-#define GL_STENCIL_BACK_REF 0x8CA3
-#define GL_STENCIL_BACK_VALUE_MASK 0x8CA4
-#define GL_STENCIL_BACK_WRITEMASK 0x8CA5
-#define GL_VERTEX_PROGRAM_TWO_SIDE 0x8643
-#define GL_POINT_SPRITE 0x8861
-#define GL_COORD_REPLACE 0x8862
-#define GL_MAX_TEXTURE_COORDS 0x8871
-#define GL_PIXEL_PACK_BUFFER 0x88EB
-#define GL_PIXEL_UNPACK_BUFFER 0x88EC
-#define GL_PIXEL_PACK_BUFFER_BINDING 0x88ED
-#define GL_PIXEL_UNPACK_BUFFER_BINDING 0x88EF
-#define GL_FLOAT_MAT2x3 0x8B65
-#define GL_FLOAT_MAT2x4 0x8B66
-#define GL_FLOAT_MAT3x2 0x8B67
-#define GL_FLOAT_MAT3x4 0x8B68
-#define GL_FLOAT_MAT4x2 0x8B69
-#define GL_FLOAT_MAT4x3 0x8B6A
-#define GL_SRGB 0x8C40
-#define GL_SRGB8 0x8C41
-#define GL_SRGB_ALPHA 0x8C42
-#define GL_SRGB8_ALPHA8 0x8C43
-#define GL_COMPRESSED_SRGB 0x8C48
-#define GL_COMPRESSED_SRGB_ALPHA 0x8C49
-#define GL_CURRENT_RASTER_SECONDARY_COLOR 0x845F
-#define GL_SLUMINANCE_ALPHA 0x8C44
-#define GL_SLUMINANCE8_ALPHA8 0x8C45
-#define GL_SLUMINANCE 0x8C46
-#define GL_SLUMINANCE8 0x8C47
-#define GL_COMPRESSED_SLUMINANCE 0x8C4A
-#define GL_COMPRESSED_SLUMINANCE_ALPHA 0x8C4B
-#define GL_COMPARE_REF_TO_TEXTURE 0x884E
-#define GL_CLIP_DISTANCE0 0x3000
-#define GL_CLIP_DISTANCE1 0x3001
-#define GL_CLIP_DISTANCE2 0x3002
-#define GL_CLIP_DISTANCE3 0x3003
-#define GL_CLIP_DISTANCE4 0x3004
-#define GL_CLIP_DISTANCE5 0x3005
-#define GL_CLIP_DISTANCE6 0x3006
-#define GL_CLIP_DISTANCE7 0x3007
-#define GL_MAX_CLIP_DISTANCES 0x0D32
-#define GL_MAJOR_VERSION 0x821B
-#define GL_MINOR_VERSION 0x821C
-#define GL_NUM_EXTENSIONS 0x821D
-#define GL_CONTEXT_FLAGS 0x821E
-#define GL_COMPRESSED_RED 0x8225
-#define GL_COMPRESSED_RG 0x8226
-#define GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT 0x00000001
-#define GL_RGBA32F 0x8814
-#define GL_RGB32F 0x8815
-#define GL_RGBA16F 0x881A
-#define GL_RGB16F 0x881B
-#define GL_VERTEX_ATTRIB_ARRAY_INTEGER 0x88FD
-#define GL_MAX_ARRAY_TEXTURE_LAYERS 0x88FF
-#define GL_MIN_PROGRAM_TEXEL_OFFSET 0x8904
-#define GL_MAX_PROGRAM_TEXEL_OFFSET 0x8905
-#define GL_CLAMP_READ_COLOR 0x891C
-#define GL_FIXED_ONLY 0x891D
-#define GL_MAX_VARYING_COMPONENTS 0x8B4B
-#define GL_TEXTURE_1D_ARRAY 0x8C18
-#define GL_PROXY_TEXTURE_1D_ARRAY 0x8C19
-#define GL_TEXTURE_2D_ARRAY 0x8C1A
-#define GL_PROXY_TEXTURE_2D_ARRAY 0x8C1B
-#define GL_TEXTURE_BINDING_1D_ARRAY 0x8C1C
-#define GL_TEXTURE_BINDING_2D_ARRAY 0x8C1D
-#define GL_R11F_G11F_B10F 0x8C3A
-#define GL_UNSIGNED_INT_10F_11F_11F_REV 0x8C3B
-#define GL_RGB9_E5 0x8C3D
-#define GL_UNSIGNED_INT_5_9_9_9_REV 0x8C3E
-#define GL_TEXTURE_SHARED_SIZE 0x8C3F
-#define GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH 0x8C76
-#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE 0x8C7F
-#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS 0x8C80
-#define GL_TRANSFORM_FEEDBACK_VARYINGS 0x8C83
-#define GL_TRANSFORM_FEEDBACK_BUFFER_START 0x8C84
-#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE 0x8C85
-#define GL_PRIMITIVES_GENERATED 0x8C87
-#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN 0x8C88
-#define GL_RASTERIZER_DISCARD 0x8C89
-#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS 0x8C8A
-#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS 0x8C8B
-#define GL_INTERLEAVED_ATTRIBS 0x8C8C
-#define GL_SEPARATE_ATTRIBS 0x8C8D
-#define GL_TRANSFORM_FEEDBACK_BUFFER 0x8C8E
-#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING 0x8C8F
-#define GL_RGBA32UI 0x8D70
-#define GL_RGB32UI 0x8D71
-#define GL_RGBA16UI 0x8D76
-#define GL_RGB16UI 0x8D77
-#define GL_RGBA8UI 0x8D7C
-#define GL_RGB8UI 0x8D7D
-#define GL_RGBA32I 0x8D82
-#define GL_RGB32I 0x8D83
-#define GL_RGBA16I 0x8D88
-#define GL_RGB16I 0x8D89
-#define GL_RGBA8I 0x8D8E
-#define GL_RGB8I 0x8D8F
-#define GL_RED_INTEGER 0x8D94
-#define GL_GREEN_INTEGER 0x8D95
-#define GL_BLUE_INTEGER 0x8D96
-#define GL_RGB_INTEGER 0x8D98
-#define GL_RGBA_INTEGER 0x8D99
-#define GL_BGR_INTEGER 0x8D9A
-#define GL_BGRA_INTEGER 0x8D9B
-#define GL_SAMPLER_1D_ARRAY 0x8DC0
-#define GL_SAMPLER_2D_ARRAY 0x8DC1
-#define GL_SAMPLER_1D_ARRAY_SHADOW 0x8DC3
-#define GL_SAMPLER_2D_ARRAY_SHADOW 0x8DC4
-#define GL_SAMPLER_CUBE_SHADOW 0x8DC5
-#define GL_UNSIGNED_INT_VEC2 0x8DC6
-#define GL_UNSIGNED_INT_VEC3 0x8DC7
-#define GL_UNSIGNED_INT_VEC4 0x8DC8
-#define GL_INT_SAMPLER_1D 0x8DC9
-#define GL_INT_SAMPLER_2D 0x8DCA
-#define GL_INT_SAMPLER_3D 0x8DCB
-#define GL_INT_SAMPLER_CUBE 0x8DCC
-#define GL_INT_SAMPLER_1D_ARRAY 0x8DCE
-#define GL_INT_SAMPLER_2D_ARRAY 0x8DCF
-#define GL_UNSIGNED_INT_SAMPLER_1D 0x8DD1
-#define GL_UNSIGNED_INT_SAMPLER_2D 0x8DD2
-#define GL_UNSIGNED_INT_SAMPLER_3D 0x8DD3
-#define GL_UNSIGNED_INT_SAMPLER_CUBE 0x8DD4
-#define GL_UNSIGNED_INT_SAMPLER_1D_ARRAY 0x8DD6
-#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY 0x8DD7
-#define GL_QUERY_WAIT 0x8E13
-#define GL_QUERY_NO_WAIT 0x8E14
-#define GL_QUERY_BY_REGION_WAIT 0x8E15
-#define GL_QUERY_BY_REGION_NO_WAIT 0x8E16
-#define GL_BUFFER_ACCESS_FLAGS 0x911F
-#define GL_BUFFER_MAP_LENGTH 0x9120
-#define GL_BUFFER_MAP_OFFSET 0x9121
-#define GL_DEPTH_COMPONENT32F 0x8CAC
-#define GL_DEPTH32F_STENCIL8 0x8CAD
-#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV 0x8DAD
-#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506
-#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING 0x8210
-#define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE 0x8211
-#define GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE 0x8212
-#define GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE 0x8213
-#define GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE 0x8214
-#define GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE 0x8215
-#define GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE 0x8216
-#define GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE 0x8217
-#define GL_FRAMEBUFFER_DEFAULT 0x8218
-#define GL_FRAMEBUFFER_UNDEFINED 0x8219
-#define GL_DEPTH_STENCIL_ATTACHMENT 0x821A
-#define GL_MAX_RENDERBUFFER_SIZE 0x84E8
-#define GL_DEPTH_STENCIL 0x84F9
-#define GL_UNSIGNED_INT_24_8 0x84FA
-#define GL_DEPTH24_STENCIL8 0x88F0
-#define GL_TEXTURE_STENCIL_SIZE 0x88F1
-#define GL_TEXTURE_RED_TYPE 0x8C10
-#define GL_TEXTURE_GREEN_TYPE 0x8C11
-#define GL_TEXTURE_BLUE_TYPE 0x8C12
-#define GL_TEXTURE_ALPHA_TYPE 0x8C13
-#define GL_TEXTURE_DEPTH_TYPE 0x8C16
-#define GL_UNSIGNED_NORMALIZED 0x8C17
-#define GL_FRAMEBUFFER_BINDING 0x8CA6
-#define GL_DRAW_FRAMEBUFFER_BINDING 0x8CA6
-#define GL_RENDERBUFFER_BINDING 0x8CA7
-#define GL_READ_FRAMEBUFFER 0x8CA8
-#define GL_DRAW_FRAMEBUFFER 0x8CA9
-#define GL_READ_FRAMEBUFFER_BINDING 0x8CAA
-#define GL_RENDERBUFFER_SAMPLES 0x8CAB
-#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0
-#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1
-#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2
-#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3
-#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER 0x8CD4
-#define GL_FRAMEBUFFER_COMPLETE 0x8CD5
-#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6
-#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7
-#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER 0x8CDB
-#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER 0x8CDC
-#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD
-#define GL_MAX_COLOR_ATTACHMENTS 0x8CDF
-#define GL_COLOR_ATTACHMENT0 0x8CE0
-#define GL_COLOR_ATTACHMENT1 0x8CE1
-#define GL_COLOR_ATTACHMENT2 0x8CE2
-#define GL_COLOR_ATTACHMENT3 0x8CE3
-#define GL_COLOR_ATTACHMENT4 0x8CE4
-#define GL_COLOR_ATTACHMENT5 0x8CE5
-#define GL_COLOR_ATTACHMENT6 0x8CE6
-#define GL_COLOR_ATTACHMENT7 0x8CE7
-#define GL_COLOR_ATTACHMENT8 0x8CE8
-#define GL_COLOR_ATTACHMENT9 0x8CE9
-#define GL_COLOR_ATTACHMENT10 0x8CEA
-#define GL_COLOR_ATTACHMENT11 0x8CEB
-#define GL_COLOR_ATTACHMENT12 0x8CEC
-#define GL_COLOR_ATTACHMENT13 0x8CED
-#define GL_COLOR_ATTACHMENT14 0x8CEE
-#define GL_COLOR_ATTACHMENT15 0x8CEF
-#define GL_COLOR_ATTACHMENT16 0x8CF0
-#define GL_COLOR_ATTACHMENT17 0x8CF1
-#define GL_COLOR_ATTACHMENT18 0x8CF2
-#define GL_COLOR_ATTACHMENT19 0x8CF3
-#define GL_COLOR_ATTACHMENT20 0x8CF4
-#define GL_COLOR_ATTACHMENT21 0x8CF5
-#define GL_COLOR_ATTACHMENT22 0x8CF6
-#define GL_COLOR_ATTACHMENT23 0x8CF7
-#define GL_COLOR_ATTACHMENT24 0x8CF8
-#define GL_COLOR_ATTACHMENT25 0x8CF9
-#define GL_COLOR_ATTACHMENT26 0x8CFA
-#define GL_COLOR_ATTACHMENT27 0x8CFB
-#define GL_COLOR_ATTACHMENT28 0x8CFC
-#define GL_COLOR_ATTACHMENT29 0x8CFD
-#define GL_COLOR_ATTACHMENT30 0x8CFE
-#define GL_COLOR_ATTACHMENT31 0x8CFF
-#define GL_DEPTH_ATTACHMENT 0x8D00
-#define GL_STENCIL_ATTACHMENT 0x8D20
-#define GL_FRAMEBUFFER 0x8D40
-#define GL_RENDERBUFFER 0x8D41
-#define GL_RENDERBUFFER_WIDTH 0x8D42
-#define GL_RENDERBUFFER_HEIGHT 0x8D43
-#define GL_RENDERBUFFER_INTERNAL_FORMAT 0x8D44
-#define GL_STENCIL_INDEX1 0x8D46
-#define GL_STENCIL_INDEX4 0x8D47
-#define GL_STENCIL_INDEX8 0x8D48
-#define GL_STENCIL_INDEX16 0x8D49
-#define GL_RENDERBUFFER_RED_SIZE 0x8D50
-#define GL_RENDERBUFFER_GREEN_SIZE 0x8D51
-#define GL_RENDERBUFFER_BLUE_SIZE 0x8D52
-#define GL_RENDERBUFFER_ALPHA_SIZE 0x8D53
-#define GL_RENDERBUFFER_DEPTH_SIZE 0x8D54
-#define GL_RENDERBUFFER_STENCIL_SIZE 0x8D55
-#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 0x8D56
-#define GL_MAX_SAMPLES 0x8D57
-#define GL_INDEX 0x8222
-#define GL_TEXTURE_LUMINANCE_TYPE 0x8C14
-#define GL_TEXTURE_INTENSITY_TYPE 0x8C15
-#define GL_FRAMEBUFFER_SRGB 0x8DB9
-#define GL_HALF_FLOAT 0x140B
-#define GL_MAP_READ_BIT 0x0001
-#define GL_MAP_WRITE_BIT 0x0002
-#define GL_MAP_INVALIDATE_RANGE_BIT 0x0004
-#define GL_MAP_INVALIDATE_BUFFER_BIT 0x0008
-#define GL_MAP_FLUSH_EXPLICIT_BIT 0x0010
-#define GL_MAP_UNSYNCHRONIZED_BIT 0x0020
-#define GL_COMPRESSED_RED_RGTC1 0x8DBB
-#define GL_COMPRESSED_SIGNED_RED_RGTC1 0x8DBC
-#define GL_COMPRESSED_RG_RGTC2 0x8DBD
-#define GL_COMPRESSED_SIGNED_RG_RGTC2 0x8DBE
-#define GL_RG 0x8227
-#define GL_RG_INTEGER 0x8228
-#define GL_R8 0x8229
-#define GL_R16 0x822A
-#define GL_RG8 0x822B
-#define GL_RG16 0x822C
-#define GL_R16F 0x822D
-#define GL_R32F 0x822E
-#define GL_RG16F 0x822F
-#define GL_RG32F 0x8230
-#define GL_R8I 0x8231
-#define GL_R8UI 0x8232
-#define GL_R16I 0x8233
-#define GL_R16UI 0x8234
-#define GL_R32I 0x8235
-#define GL_R32UI 0x8236
-#define GL_RG8I 0x8237
-#define GL_RG8UI 0x8238
-#define GL_RG16I 0x8239
-#define GL_RG16UI 0x823A
-#define GL_RG32I 0x823B
-#define GL_RG32UI 0x823C
-#define GL_VERTEX_ARRAY_BINDING 0x85B5
-#define GL_CLAMP_VERTEX_COLOR 0x891A
-#define GL_CLAMP_FRAGMENT_COLOR 0x891B
-#define GL_ALPHA_INTEGER 0x8D97
-#define GL_SAMPLER_2D_RECT 0x8B63
-#define GL_SAMPLER_2D_RECT_SHADOW 0x8B64
-#define GL_SAMPLER_BUFFER 0x8DC2
-#define GL_INT_SAMPLER_2D_RECT 0x8DCD
-#define GL_INT_SAMPLER_BUFFER 0x8DD0
-#define GL_UNSIGNED_INT_SAMPLER_2D_RECT 0x8DD5
-#define GL_UNSIGNED_INT_SAMPLER_BUFFER 0x8DD8
-#define GL_TEXTURE_BUFFER 0x8C2A
-#define GL_MAX_TEXTURE_BUFFER_SIZE 0x8C2B
-#define GL_TEXTURE_BINDING_BUFFER 0x8C2C
-#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING 0x8C2D
-#define GL_TEXTURE_RECTANGLE 0x84F5
-#define GL_TEXTURE_BINDING_RECTANGLE 0x84F6
-#define GL_PROXY_TEXTURE_RECTANGLE 0x84F7
-#define GL_MAX_RECTANGLE_TEXTURE_SIZE 0x84F8
-#define GL_R8_SNORM 0x8F94
-#define GL_RG8_SNORM 0x8F95
-#define GL_RGB8_SNORM 0x8F96
-#define GL_RGBA8_SNORM 0x8F97
-#define GL_R16_SNORM 0x8F98
-#define GL_RG16_SNORM 0x8F99
-#define GL_RGB16_SNORM 0x8F9A
-#define GL_RGBA16_SNORM 0x8F9B
-#define GL_SIGNED_NORMALIZED 0x8F9C
-#define GL_PRIMITIVE_RESTART 0x8F9D
-#define GL_PRIMITIVE_RESTART_INDEX 0x8F9E
-#define GL_COPY_READ_BUFFER 0x8F36
-#define GL_COPY_WRITE_BUFFER 0x8F37
-#define GL_UNIFORM_BUFFER 0x8A11
-#define GL_UNIFORM_BUFFER_BINDING 0x8A28
-#define GL_UNIFORM_BUFFER_START 0x8A29
-#define GL_UNIFORM_BUFFER_SIZE 0x8A2A
-#define GL_MAX_VERTEX_UNIFORM_BLOCKS 0x8A2B
-#define GL_MAX_GEOMETRY_UNIFORM_BLOCKS 0x8A2C
-#define GL_MAX_FRAGMENT_UNIFORM_BLOCKS 0x8A2D
-#define GL_MAX_COMBINED_UNIFORM_BLOCKS 0x8A2E
-#define GL_MAX_UNIFORM_BUFFER_BINDINGS 0x8A2F
-#define GL_MAX_UNIFORM_BLOCK_SIZE 0x8A30
-#define GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS 0x8A31
-#define GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS 0x8A32
-#define GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS 0x8A33
-#define GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT 0x8A34
-#define GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH 0x8A35
-#define GL_ACTIVE_UNIFORM_BLOCKS 0x8A36
-#define GL_UNIFORM_TYPE 0x8A37
-#define GL_UNIFORM_SIZE 0x8A38
-#define GL_UNIFORM_NAME_LENGTH 0x8A39
-#define GL_UNIFORM_BLOCK_INDEX 0x8A3A
-#define GL_UNIFORM_OFFSET 0x8A3B
-#define GL_UNIFORM_ARRAY_STRIDE 0x8A3C
-#define GL_UNIFORM_MATRIX_STRIDE 0x8A3D
-#define GL_UNIFORM_IS_ROW_MAJOR 0x8A3E
-#define GL_UNIFORM_BLOCK_BINDING 0x8A3F
-#define GL_UNIFORM_BLOCK_DATA_SIZE 0x8A40
-#define GL_UNIFORM_BLOCK_NAME_LENGTH 0x8A41
-#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS 0x8A42
-#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES 0x8A43
-#define GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER 0x8A44
-#define GL_UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER 0x8A45
-#define GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER 0x8A46
-#define GL_INVALID_INDEX 0xFFFFFFFF
-#define GL_CONTEXT_CORE_PROFILE_BIT 0x00000001
-#define GL_CONTEXT_COMPATIBILITY_PROFILE_BIT 0x00000002
-#define GL_LINES_ADJACENCY 0x000A
-#define GL_LINE_STRIP_ADJACENCY 0x000B
-#define GL_TRIANGLES_ADJACENCY 0x000C
-#define GL_TRIANGLE_STRIP_ADJACENCY 0x000D
-#define GL_PROGRAM_POINT_SIZE 0x8642
-#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS 0x8C29
-#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED 0x8DA7
-#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS 0x8DA8
-#define GL_GEOMETRY_SHADER 0x8DD9
-#define GL_GEOMETRY_VERTICES_OUT 0x8916
-#define GL_GEOMETRY_INPUT_TYPE 0x8917
-#define GL_GEOMETRY_OUTPUT_TYPE 0x8918
-#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS 0x8DDF
-#define GL_MAX_GEOMETRY_OUTPUT_VERTICES 0x8DE0
-#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS 0x8DE1
-#define GL_MAX_VERTEX_OUTPUT_COMPONENTS 0x9122
-#define GL_MAX_GEOMETRY_INPUT_COMPONENTS 0x9123
-#define GL_MAX_GEOMETRY_OUTPUT_COMPONENTS 0x9124
-#define GL_MAX_FRAGMENT_INPUT_COMPONENTS 0x9125
-#define GL_CONTEXT_PROFILE_MASK 0x9126
-#define GL_DEPTH_CLAMP 0x864F
-#define GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION 0x8E4C
-#define GL_FIRST_VERTEX_CONVENTION 0x8E4D
-#define GL_LAST_VERTEX_CONVENTION 0x8E4E
-#define GL_PROVOKING_VERTEX 0x8E4F
-#define GL_TEXTURE_CUBE_MAP_SEAMLESS 0x884F
-#define GL_MAX_SERVER_WAIT_TIMEOUT 0x9111
-#define GL_OBJECT_TYPE 0x9112
-#define GL_SYNC_CONDITION 0x9113
-#define GL_SYNC_STATUS 0x9114
-#define GL_SYNC_FLAGS 0x9115
-#define GL_SYNC_FENCE 0x9116
-#define GL_SYNC_GPU_COMMANDS_COMPLETE 0x9117
-#define GL_UNSIGNALED 0x9118
-#define GL_SIGNALED 0x9119
-#define GL_ALREADY_SIGNALED 0x911A
-#define GL_TIMEOUT_EXPIRED 0x911B
-#define GL_CONDITION_SATISFIED 0x911C
-#define GL_WAIT_FAILED 0x911D
-#define GL_TIMEOUT_IGNORED 0xFFFFFFFFFFFFFFFF
-#define GL_SYNC_FLUSH_COMMANDS_BIT 0x00000001
-#define GL_SAMPLE_POSITION 0x8E50
-#define GL_SAMPLE_MASK 0x8E51
-#define GL_SAMPLE_MASK_VALUE 0x8E52
-#define GL_MAX_SAMPLE_MASK_WORDS 0x8E59
-#define GL_TEXTURE_2D_MULTISAMPLE 0x9100
-#define GL_PROXY_TEXTURE_2D_MULTISAMPLE 0x9101
-#define GL_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9102
-#define GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9103
-#define GL_TEXTURE_BINDING_2D_MULTISAMPLE 0x9104
-#define GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY 0x9105
-#define GL_TEXTURE_SAMPLES 0x9106
-#define GL_TEXTURE_FIXED_SAMPLE_LOCATIONS 0x9107
-#define GL_SAMPLER_2D_MULTISAMPLE 0x9108
-#define GL_INT_SAMPLER_2D_MULTISAMPLE 0x9109
-#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE 0x910A
-#define GL_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910B
-#define GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910C
-#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910D
-#define GL_MAX_COLOR_TEXTURE_SAMPLES 0x910E
-#define GL_MAX_DEPTH_TEXTURE_SAMPLES 0x910F
-#define GL_MAX_INTEGER_SAMPLES 0x9110
-#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR 0x88FE
-#define GL_SRC1_COLOR 0x88F9
-#define GL_ONE_MINUS_SRC1_COLOR 0x88FA
-#define GL_ONE_MINUS_SRC1_ALPHA 0x88FB
-#define GL_MAX_DUAL_SOURCE_DRAW_BUFFERS 0x88FC
-#define GL_ANY_SAMPLES_PASSED 0x8C2F
-#define GL_SAMPLER_BINDING 0x8919
-#define GL_RGB10_A2UI 0x906F
-#define GL_TEXTURE_SWIZZLE_R 0x8E42
-#define GL_TEXTURE_SWIZZLE_G 0x8E43
-#define GL_TEXTURE_SWIZZLE_B 0x8E44
-#define GL_TEXTURE_SWIZZLE_A 0x8E45
-#define GL_TEXTURE_SWIZZLE_RGBA 0x8E46
-#define GL_TIME_ELAPSED 0x88BF
-#define GL_TIMESTAMP 0x8E28
-#define GL_INT_2_10_10_10_REV 0x8D9F
-#ifndef GL_VERSION_1_0
-#define GL_VERSION_1_0 1
-GLAPI int GLAD_GL_VERSION_1_0;
-typedef void (APIENTRYP PFNGLCULLFACEPROC)(GLenum mode);
-GLAPI PFNGLCULLFACEPROC glad_glCullFace;
-#define glCullFace glad_glCullFace
-typedef void (APIENTRYP PFNGLFRONTFACEPROC)(GLenum mode);
-GLAPI PFNGLFRONTFACEPROC glad_glFrontFace;
-#define glFrontFace glad_glFrontFace
-typedef void (APIENTRYP PFNGLHINTPROC)(GLenum target, GLenum mode);
-GLAPI PFNGLHINTPROC glad_glHint;
-#define glHint glad_glHint
-typedef void (APIENTRYP PFNGLLINEWIDTHPROC)(GLfloat width);
-GLAPI PFNGLLINEWIDTHPROC glad_glLineWidth;
-#define glLineWidth glad_glLineWidth
-typedef void (APIENTRYP PFNGLPOINTSIZEPROC)(GLfloat size);
-GLAPI PFNGLPOINTSIZEPROC glad_glPointSize;
-#define glPointSize glad_glPointSize
-typedef void (APIENTRYP PFNGLPOLYGONMODEPROC)(GLenum face, GLenum mode);
-GLAPI PFNGLPOLYGONMODEPROC glad_glPolygonMode;
-#define glPolygonMode glad_glPolygonMode
-typedef void (APIENTRYP PFNGLSCISSORPROC)(GLint x, GLint y, GLsizei width, GLsizei height);
-GLAPI PFNGLSCISSORPROC glad_glScissor;
-#define glScissor glad_glScissor
-typedef void (APIENTRYP PFNGLTEXPARAMETERFPROC)(GLenum target, GLenum pname, GLfloat param);
-GLAPI PFNGLTEXPARAMETERFPROC glad_glTexParameterf;
-#define glTexParameterf glad_glTexParameterf
-typedef void (APIENTRYP PFNGLTEXPARAMETERFVPROC)(GLenum target, GLenum pname, const GLfloat *params);
-GLAPI PFNGLTEXPARAMETERFVPROC glad_glTexParameterfv;
-#define glTexParameterfv glad_glTexParameterfv
-typedef void (APIENTRYP PFNGLTEXPARAMETERIPROC)(GLenum target, GLenum pname, GLint param);
-GLAPI PFNGLTEXPARAMETERIPROC glad_glTexParameteri;
-#define glTexParameteri glad_glTexParameteri
-typedef void (APIENTRYP PFNGLTEXPARAMETERIVPROC)(GLenum target, GLenum pname, const GLint *params);
-GLAPI PFNGLTEXPARAMETERIVPROC glad_glTexParameteriv;
-#define glTexParameteriv glad_glTexParameteriv
-typedef void (APIENTRYP PFNGLTEXIMAGE1DPROC)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const void *pixels);
-GLAPI PFNGLTEXIMAGE1DPROC glad_glTexImage1D;
-#define glTexImage1D glad_glTexImage1D
-typedef void (APIENTRYP PFNGLTEXIMAGE2DPROC)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels);
-GLAPI PFNGLTEXIMAGE2DPROC glad_glTexImage2D;
-#define glTexImage2D glad_glTexImage2D
-typedef void (APIENTRYP PFNGLDRAWBUFFERPROC)(GLenum buf);
-GLAPI PFNGLDRAWBUFFERPROC glad_glDrawBuffer;
-#define glDrawBuffer glad_glDrawBuffer
-typedef void (APIENTRYP PFNGLCLEARPROC)(GLbitfield mask);
-GLAPI PFNGLCLEARPROC glad_glClear;
-#define glClear glad_glClear
-typedef void (APIENTRYP PFNGLCLEARCOLORPROC)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
-GLAPI PFNGLCLEARCOLORPROC glad_glClearColor;
-#define glClearColor glad_glClearColor
-typedef void (APIENTRYP PFNGLCLEARSTENCILPROC)(GLint s);
-GLAPI PFNGLCLEARSTENCILPROC glad_glClearStencil;
-#define glClearStencil glad_glClearStencil
-typedef void (APIENTRYP PFNGLCLEARDEPTHPROC)(GLdouble depth);
-GLAPI PFNGLCLEARDEPTHPROC glad_glClearDepth;
-#define glClearDepth glad_glClearDepth
-typedef void (APIENTRYP PFNGLSTENCILMASKPROC)(GLuint mask);
-GLAPI PFNGLSTENCILMASKPROC glad_glStencilMask;
-#define glStencilMask glad_glStencilMask
-typedef void (APIENTRYP PFNGLCOLORMASKPROC)(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
-GLAPI PFNGLCOLORMASKPROC glad_glColorMask;
-#define glColorMask glad_glColorMask
-typedef void (APIENTRYP PFNGLDEPTHMASKPROC)(GLboolean flag);
-GLAPI PFNGLDEPTHMASKPROC glad_glDepthMask;
-#define glDepthMask glad_glDepthMask
-typedef void (APIENTRYP PFNGLDISABLEPROC)(GLenum cap);
-GLAPI PFNGLDISABLEPROC glad_glDisable;
-#define glDisable glad_glDisable
-typedef void (APIENTRYP PFNGLENABLEPROC)(GLenum cap);
-GLAPI PFNGLENABLEPROC glad_glEnable;
-#define glEnable glad_glEnable
-typedef void (APIENTRYP PFNGLFINISHPROC)(void);
-GLAPI PFNGLFINISHPROC glad_glFinish;
-#define glFinish glad_glFinish
-typedef void (APIENTRYP PFNGLFLUSHPROC)(void);
-GLAPI PFNGLFLUSHPROC glad_glFlush;
-#define glFlush glad_glFlush
-typedef void (APIENTRYP PFNGLBLENDFUNCPROC)(GLenum sfactor, GLenum dfactor);
-GLAPI PFNGLBLENDFUNCPROC glad_glBlendFunc;
-#define glBlendFunc glad_glBlendFunc
-typedef void (APIENTRYP PFNGLLOGICOPPROC)(GLenum opcode);
-GLAPI PFNGLLOGICOPPROC glad_glLogicOp;
-#define glLogicOp glad_glLogicOp
-typedef void (APIENTRYP PFNGLSTENCILFUNCPROC)(GLenum func, GLint ref, GLuint mask);
-GLAPI PFNGLSTENCILFUNCPROC glad_glStencilFunc;
-#define glStencilFunc glad_glStencilFunc
-typedef void (APIENTRYP PFNGLSTENCILOPPROC)(GLenum fail, GLenum zfail, GLenum zpass);
-GLAPI PFNGLSTENCILOPPROC glad_glStencilOp;
-#define glStencilOp glad_glStencilOp
-typedef void (APIENTRYP PFNGLDEPTHFUNCPROC)(GLenum func);
-GLAPI PFNGLDEPTHFUNCPROC glad_glDepthFunc;
-#define glDepthFunc glad_glDepthFunc
-typedef void (APIENTRYP PFNGLPIXELSTOREFPROC)(GLenum pname, GLfloat param);
-GLAPI PFNGLPIXELSTOREFPROC glad_glPixelStoref;
-#define glPixelStoref glad_glPixelStoref
-typedef void (APIENTRYP PFNGLPIXELSTOREIPROC)(GLenum pname, GLint param);
-GLAPI PFNGLPIXELSTOREIPROC glad_glPixelStorei;
-#define glPixelStorei glad_glPixelStorei
-typedef void (APIENTRYP PFNGLREADBUFFERPROC)(GLenum src);
-GLAPI PFNGLREADBUFFERPROC glad_glReadBuffer;
-#define glReadBuffer glad_glReadBuffer
-typedef void (APIENTRYP PFNGLREADPIXELSPROC)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels);
-GLAPI PFNGLREADPIXELSPROC glad_glReadPixels;
-#define glReadPixels glad_glReadPixels
-typedef void (APIENTRYP PFNGLGETBOOLEANVPROC)(GLenum pname, GLboolean *data);
-GLAPI PFNGLGETBOOLEANVPROC glad_glGetBooleanv;
-#define glGetBooleanv glad_glGetBooleanv
-typedef void (APIENTRYP PFNGLGETDOUBLEVPROC)(GLenum pname, GLdouble *data);
-GLAPI PFNGLGETDOUBLEVPROC glad_glGetDoublev;
-#define glGetDoublev glad_glGetDoublev
-typedef GLenum (APIENTRYP PFNGLGETERRORPROC)(void);
-GLAPI PFNGLGETERRORPROC glad_glGetError;
-#define glGetError glad_glGetError
-typedef void (APIENTRYP PFNGLGETFLOATVPROC)(GLenum pname, GLfloat *data);
-GLAPI PFNGLGETFLOATVPROC glad_glGetFloatv;
-#define glGetFloatv glad_glGetFloatv
-typedef void (APIENTRYP PFNGLGETINTEGERVPROC)(GLenum pname, GLint *data);
-GLAPI PFNGLGETINTEGERVPROC glad_glGetIntegerv;
-#define glGetIntegerv glad_glGetIntegerv
-typedef const GLubyte * (APIENTRYP PFNGLGETSTRINGPROC)(GLenum name);
-GLAPI PFNGLGETSTRINGPROC glad_glGetString;
-#define glGetString glad_glGetString
-typedef void (APIENTRYP PFNGLGETTEXIMAGEPROC)(GLenum target, GLint level, GLenum format, GLenum type, void *pixels);
-GLAPI PFNGLGETTEXIMAGEPROC glad_glGetTexImage;
-#define glGetTexImage glad_glGetTexImage
-typedef void (APIENTRYP PFNGLGETTEXPARAMETERFVPROC)(GLenum target, GLenum pname, GLfloat *params);
-GLAPI PFNGLGETTEXPARAMETERFVPROC glad_glGetTexParameterfv;
-#define glGetTexParameterfv glad_glGetTexParameterfv
-typedef void (APIENTRYP PFNGLGETTEXPARAMETERIVPROC)(GLenum target, GLenum pname, GLint *params);
-GLAPI PFNGLGETTEXPARAMETERIVPROC glad_glGetTexParameteriv;
-#define glGetTexParameteriv glad_glGetTexParameteriv
-typedef void (APIENTRYP PFNGLGETTEXLEVELPARAMETERFVPROC)(GLenum target, GLint level, GLenum pname, GLfloat *params);
-GLAPI PFNGLGETTEXLEVELPARAMETERFVPROC glad_glGetTexLevelParameterfv;
-#define glGetTexLevelParameterfv glad_glGetTexLevelParameterfv
-typedef void (APIENTRYP PFNGLGETTEXLEVELPARAMETERIVPROC)(GLenum target, GLint level, GLenum pname, GLint *params);
-GLAPI PFNGLGETTEXLEVELPARAMETERIVPROC glad_glGetTexLevelParameteriv;
-#define glGetTexLevelParameteriv glad_glGetTexLevelParameteriv
-typedef GLboolean (APIENTRYP PFNGLISENABLEDPROC)(GLenum cap);
-GLAPI PFNGLISENABLEDPROC glad_glIsEnabled;
-#define glIsEnabled glad_glIsEnabled
-typedef void (APIENTRYP PFNGLDEPTHRANGEPROC)(GLdouble n, GLdouble f);
-GLAPI PFNGLDEPTHRANGEPROC glad_glDepthRange;
-#define glDepthRange glad_glDepthRange
-typedef void (APIENTRYP PFNGLVIEWPORTPROC)(GLint x, GLint y, GLsizei width, GLsizei height);
-GLAPI PFNGLVIEWPORTPROC glad_glViewport;
-#define glViewport glad_glViewport
-typedef void (APIENTRYP PFNGLNEWLISTPROC)(GLuint list, GLenum mode);
-GLAPI PFNGLNEWLISTPROC glad_glNewList;
-#define glNewList glad_glNewList
-typedef void (APIENTRYP PFNGLENDLISTPROC)(void);
-GLAPI PFNGLENDLISTPROC glad_glEndList;
-#define glEndList glad_glEndList
-typedef void (APIENTRYP PFNGLCALLLISTPROC)(GLuint list);
-GLAPI PFNGLCALLLISTPROC glad_glCallList;
-#define glCallList glad_glCallList
-typedef void (APIENTRYP PFNGLCALLLISTSPROC)(GLsizei n, GLenum type, const void *lists);
-GLAPI PFNGLCALLLISTSPROC glad_glCallLists;
-#define glCallLists glad_glCallLists
-typedef void (APIENTRYP PFNGLDELETELISTSPROC)(GLuint list, GLsizei range);
-GLAPI PFNGLDELETELISTSPROC glad_glDeleteLists;
-#define glDeleteLists glad_glDeleteLists
-typedef GLuint (APIENTRYP PFNGLGENLISTSPROC)(GLsizei range);
-GLAPI PFNGLGENLISTSPROC glad_glGenLists;
-#define glGenLists glad_glGenLists
-typedef void (APIENTRYP PFNGLLISTBASEPROC)(GLuint base);
-GLAPI PFNGLLISTBASEPROC glad_glListBase;
-#define glListBase glad_glListBase
-typedef void (APIENTRYP PFNGLBEGINPROC)(GLenum mode);
-GLAPI PFNGLBEGINPROC glad_glBegin;
-#define glBegin glad_glBegin
-typedef void (APIENTRYP PFNGLBITMAPPROC)(GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, const GLubyte *bitmap);
-GLAPI PFNGLBITMAPPROC glad_glBitmap;
-#define glBitmap glad_glBitmap
-typedef void (APIENTRYP PFNGLCOLOR3BPROC)(GLbyte red, GLbyte green, GLbyte blue);
-GLAPI PFNGLCOLOR3BPROC glad_glColor3b;
-#define glColor3b glad_glColor3b
-typedef void (APIENTRYP PFNGLCOLOR3BVPROC)(const GLbyte *v);
-GLAPI PFNGLCOLOR3BVPROC glad_glColor3bv;
-#define glColor3bv glad_glColor3bv
-typedef void (APIENTRYP PFNGLCOLOR3DPROC)(GLdouble red, GLdouble green, GLdouble blue);
-GLAPI PFNGLCOLOR3DPROC glad_glColor3d;
-#define glColor3d glad_glColor3d
-typedef void (APIENTRYP PFNGLCOLOR3DVPROC)(const GLdouble *v);
-GLAPI PFNGLCOLOR3DVPROC glad_glColor3dv;
-#define glColor3dv glad_glColor3dv
-typedef void (APIENTRYP PFNGLCOLOR3FPROC)(GLfloat red, GLfloat green, GLfloat blue);
-GLAPI PFNGLCOLOR3FPROC glad_glColor3f;
-#define glColor3f glad_glColor3f
-typedef void (APIENTRYP PFNGLCOLOR3FVPROC)(const GLfloat *v);
-GLAPI PFNGLCOLOR3FVPROC glad_glColor3fv;
-#define glColor3fv glad_glColor3fv
-typedef void (APIENTRYP PFNGLCOLOR3IPROC)(GLint red, GLint green, GLint blue);
-GLAPI PFNGLCOLOR3IPROC glad_glColor3i;
-#define glColor3i glad_glColor3i
-typedef void (APIENTRYP PFNGLCOLOR3IVPROC)(const GLint *v);
-GLAPI PFNGLCOLOR3IVPROC glad_glColor3iv;
-#define glColor3iv glad_glColor3iv
-typedef void (APIENTRYP PFNGLCOLOR3SPROC)(GLshort red, GLshort green, GLshort blue);
-GLAPI PFNGLCOLOR3SPROC glad_glColor3s;
-#define glColor3s glad_glColor3s
-typedef void (APIENTRYP PFNGLCOLOR3SVPROC)(const GLshort *v);
-GLAPI PFNGLCOLOR3SVPROC glad_glColor3sv;
-#define glColor3sv glad_glColor3sv
-typedef void (APIENTRYP PFNGLCOLOR3UBPROC)(GLubyte red, GLubyte green, GLubyte blue);
-GLAPI PFNGLCOLOR3UBPROC glad_glColor3ub;
-#define glColor3ub glad_glColor3ub
-typedef void (APIENTRYP PFNGLCOLOR3UBVPROC)(const GLubyte *v);
-GLAPI PFNGLCOLOR3UBVPROC glad_glColor3ubv;
-#define glColor3ubv glad_glColor3ubv
-typedef void (APIENTRYP PFNGLCOLOR3UIPROC)(GLuint red, GLuint green, GLuint blue);
-GLAPI PFNGLCOLOR3UIPROC glad_glColor3ui;
-#define glColor3ui glad_glColor3ui
-typedef void (APIENTRYP PFNGLCOLOR3UIVPROC)(const GLuint *v);
-GLAPI PFNGLCOLOR3UIVPROC glad_glColor3uiv;
-#define glColor3uiv glad_glColor3uiv
-typedef void (APIENTRYP PFNGLCOLOR3USPROC)(GLushort red, GLushort green, GLushort blue);
-GLAPI PFNGLCOLOR3USPROC glad_glColor3us;
-#define glColor3us glad_glColor3us
-typedef void (APIENTRYP PFNGLCOLOR3USVPROC)(const GLushort *v);
-GLAPI PFNGLCOLOR3USVPROC glad_glColor3usv;
-#define glColor3usv glad_glColor3usv
-typedef void (APIENTRYP PFNGLCOLOR4BPROC)(GLbyte red, GLbyte green, GLbyte blue, GLbyte alpha);
-GLAPI PFNGLCOLOR4BPROC glad_glColor4b;
-#define glColor4b glad_glColor4b
-typedef void (APIENTRYP PFNGLCOLOR4BVPROC)(const GLbyte *v);
-GLAPI PFNGLCOLOR4BVPROC glad_glColor4bv;
-#define glColor4bv glad_glColor4bv
-typedef void (APIENTRYP PFNGLCOLOR4DPROC)(GLdouble red, GLdouble green, GLdouble blue, GLdouble alpha);
-GLAPI PFNGLCOLOR4DPROC glad_glColor4d;
-#define glColor4d glad_glColor4d
-typedef void (APIENTRYP PFNGLCOLOR4DVPROC)(const GLdouble *v);
-GLAPI PFNGLCOLOR4DVPROC glad_glColor4dv;
-#define glColor4dv glad_glColor4dv
-typedef void (APIENTRYP PFNGLCOLOR4FPROC)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
-GLAPI PFNGLCOLOR4FPROC glad_glColor4f;
-#define glColor4f glad_glColor4f
-typedef void (APIENTRYP PFNGLCOLOR4FVPROC)(const GLfloat *v);
-GLAPI PFNGLCOLOR4FVPROC glad_glColor4fv;
-#define glColor4fv glad_glColor4fv
-typedef void (APIENTRYP PFNGLCOLOR4IPROC)(GLint red, GLint green, GLint blue, GLint alpha);
-GLAPI PFNGLCOLOR4IPROC glad_glColor4i;
-#define glColor4i glad_glColor4i
-typedef void (APIENTRYP PFNGLCOLOR4IVPROC)(const GLint *v);
-GLAPI PFNGLCOLOR4IVPROC glad_glColor4iv;
-#define glColor4iv glad_glColor4iv
-typedef void (APIENTRYP PFNGLCOLOR4SPROC)(GLshort red, GLshort green, GLshort blue, GLshort alpha);
-GLAPI PFNGLCOLOR4SPROC glad_glColor4s;
-#define glColor4s glad_glColor4s
-typedef void (APIENTRYP PFNGLCOLOR4SVPROC)(const GLshort *v);
-GLAPI PFNGLCOLOR4SVPROC glad_glColor4sv;
-#define glColor4sv glad_glColor4sv
-typedef void (APIENTRYP PFNGLCOLOR4UBPROC)(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha);
-GLAPI PFNGLCOLOR4UBPROC glad_glColor4ub;
-#define glColor4ub glad_glColor4ub
-typedef void (APIENTRYP PFNGLCOLOR4UBVPROC)(const GLubyte *v);
-GLAPI PFNGLCOLOR4UBVPROC glad_glColor4ubv;
-#define glColor4ubv glad_glColor4ubv
-typedef void (APIENTRYP PFNGLCOLOR4UIPROC)(GLuint red, GLuint green, GLuint blue, GLuint alpha);
-GLAPI PFNGLCOLOR4UIPROC glad_glColor4ui;
-#define glColor4ui glad_glColor4ui
-typedef void (APIENTRYP PFNGLCOLOR4UIVPROC)(const GLuint *v);
-GLAPI PFNGLCOLOR4UIVPROC glad_glColor4uiv;
-#define glColor4uiv glad_glColor4uiv
-typedef void (APIENTRYP PFNGLCOLOR4USPROC)(GLushort red, GLushort green, GLushort blue, GLushort alpha);
-GLAPI PFNGLCOLOR4USPROC glad_glColor4us;
-#define glColor4us glad_glColor4us
-typedef void (APIENTRYP PFNGLCOLOR4USVPROC)(const GLushort *v);
-GLAPI PFNGLCOLOR4USVPROC glad_glColor4usv;
-#define glColor4usv glad_glColor4usv
-typedef void (APIENTRYP PFNGLEDGEFLAGPROC)(GLboolean flag);
-GLAPI PFNGLEDGEFLAGPROC glad_glEdgeFlag;
-#define glEdgeFlag glad_glEdgeFlag
-typedef void (APIENTRYP PFNGLEDGEFLAGVPROC)(const GLboolean *flag);
-GLAPI PFNGLEDGEFLAGVPROC glad_glEdgeFlagv;
-#define glEdgeFlagv glad_glEdgeFlagv
-typedef void (APIENTRYP PFNGLENDPROC)(void);
-GLAPI PFNGLENDPROC glad_glEnd;
-#define glEnd glad_glEnd
-typedef void (APIENTRYP PFNGLINDEXDPROC)(GLdouble c);
-GLAPI PFNGLINDEXDPROC glad_glIndexd;
-#define glIndexd glad_glIndexd
-typedef void (APIENTRYP PFNGLINDEXDVPROC)(const GLdouble *c);
-GLAPI PFNGLINDEXDVPROC glad_glIndexdv;
-#define glIndexdv glad_glIndexdv
-typedef void (APIENTRYP PFNGLINDEXFPROC)(GLfloat c);
-GLAPI PFNGLINDEXFPROC glad_glIndexf;
-#define glIndexf glad_glIndexf
-typedef void (APIENTRYP PFNGLINDEXFVPROC)(const GLfloat *c);
-GLAPI PFNGLINDEXFVPROC glad_glIndexfv;
-#define glIndexfv glad_glIndexfv
-typedef void (APIENTRYP PFNGLINDEXIPROC)(GLint c);
-GLAPI PFNGLINDEXIPROC glad_glIndexi;
-#define glIndexi glad_glIndexi
-typedef void (APIENTRYP PFNGLINDEXIVPROC)(const GLint *c);
-GLAPI PFNGLINDEXIVPROC glad_glIndexiv;
-#define glIndexiv glad_glIndexiv
-typedef void (APIENTRYP PFNGLINDEXSPROC)(GLshort c);
-GLAPI PFNGLINDEXSPROC glad_glIndexs;
-#define glIndexs glad_glIndexs
-typedef void (APIENTRYP PFNGLINDEXSVPROC)(const GLshort *c);
-GLAPI PFNGLINDEXSVPROC glad_glIndexsv;
-#define glIndexsv glad_glIndexsv
-typedef void (APIENTRYP PFNGLNORMAL3BPROC)(GLbyte nx, GLbyte ny, GLbyte nz);
-GLAPI PFNGLNORMAL3BPROC glad_glNormal3b;
-#define glNormal3b glad_glNormal3b
-typedef void (APIENTRYP PFNGLNORMAL3BVPROC)(const GLbyte *v);
-GLAPI PFNGLNORMAL3BVPROC glad_glNormal3bv;
-#define glNormal3bv glad_glNormal3bv
-typedef void (APIENTRYP PFNGLNORMAL3DPROC)(GLdouble nx, GLdouble ny, GLdouble nz);
-GLAPI PFNGLNORMAL3DPROC glad_glNormal3d;
-#define glNormal3d glad_glNormal3d
-typedef void (APIENTRYP PFNGLNORMAL3DVPROC)(const GLdouble *v);
-GLAPI PFNGLNORMAL3DVPROC glad_glNormal3dv;
-#define glNormal3dv glad_glNormal3dv
-typedef void (APIENTRYP PFNGLNORMAL3FPROC)(GLfloat nx, GLfloat ny, GLfloat nz);
-GLAPI PFNGLNORMAL3FPROC glad_glNormal3f;
-#define glNormal3f glad_glNormal3f
-typedef void (APIENTRYP PFNGLNORMAL3FVPROC)(const GLfloat *v);
-GLAPI PFNGLNORMAL3FVPROC glad_glNormal3fv;
-#define glNormal3fv glad_glNormal3fv
-typedef void (APIENTRYP PFNGLNORMAL3IPROC)(GLint nx, GLint ny, GLint nz);
-GLAPI PFNGLNORMAL3IPROC glad_glNormal3i;
-#define glNormal3i glad_glNormal3i
-typedef void (APIENTRYP PFNGLNORMAL3IVPROC)(const GLint *v);
-GLAPI PFNGLNORMAL3IVPROC glad_glNormal3iv;
-#define glNormal3iv glad_glNormal3iv
-typedef void (APIENTRYP PFNGLNORMAL3SPROC)(GLshort nx, GLshort ny, GLshort nz);
-GLAPI PFNGLNORMAL3SPROC glad_glNormal3s;
-#define glNormal3s glad_glNormal3s
-typedef void (APIENTRYP PFNGLNORMAL3SVPROC)(const GLshort *v);
-GLAPI PFNGLNORMAL3SVPROC glad_glNormal3sv;
-#define glNormal3sv glad_glNormal3sv
-typedef void (APIENTRYP PFNGLRASTERPOS2DPROC)(GLdouble x, GLdouble y);
-GLAPI PFNGLRASTERPOS2DPROC glad_glRasterPos2d;
-#define glRasterPos2d glad_glRasterPos2d
-typedef void (APIENTRYP PFNGLRASTERPOS2DVPROC)(const GLdouble *v);
-GLAPI PFNGLRASTERPOS2DVPROC glad_glRasterPos2dv;
-#define glRasterPos2dv glad_glRasterPos2dv
-typedef void (APIENTRYP PFNGLRASTERPOS2FPROC)(GLfloat x, GLfloat y);
-GLAPI PFNGLRASTERPOS2FPROC glad_glRasterPos2f;
-#define glRasterPos2f glad_glRasterPos2f
-typedef void (APIENTRYP PFNGLRASTERPOS2FVPROC)(const GLfloat *v);
-GLAPI PFNGLRASTERPOS2FVPROC glad_glRasterPos2fv;
-#define glRasterPos2fv glad_glRasterPos2fv
-typedef void (APIENTRYP PFNGLRASTERPOS2IPROC)(GLint x, GLint y);
-GLAPI PFNGLRASTERPOS2IPROC glad_glRasterPos2i;
-#define glRasterPos2i glad_glRasterPos2i
-typedef void (APIENTRYP PFNGLRASTERPOS2IVPROC)(const GLint *v);
-GLAPI PFNGLRASTERPOS2IVPROC glad_glRasterPos2iv;
-#define glRasterPos2iv glad_glRasterPos2iv
-typedef void (APIENTRYP PFNGLRASTERPOS2SPROC)(GLshort x, GLshort y);
-GLAPI PFNGLRASTERPOS2SPROC glad_glRasterPos2s;
-#define glRasterPos2s glad_glRasterPos2s
-typedef void (APIENTRYP PFNGLRASTERPOS2SVPROC)(const GLshort *v);
-GLAPI PFNGLRASTERPOS2SVPROC glad_glRasterPos2sv;
-#define glRasterPos2sv glad_glRasterPos2sv
-typedef void (APIENTRYP PFNGLRASTERPOS3DPROC)(GLdouble x, GLdouble y, GLdouble z);
-GLAPI PFNGLRASTERPOS3DPROC glad_glRasterPos3d;
-#define glRasterPos3d glad_glRasterPos3d
-typedef void (APIENTRYP PFNGLRASTERPOS3DVPROC)(const GLdouble *v);
-GLAPI PFNGLRASTERPOS3DVPROC glad_glRasterPos3dv;
-#define glRasterPos3dv glad_glRasterPos3dv
-typedef void (APIENTRYP PFNGLRASTERPOS3FPROC)(GLfloat x, GLfloat y, GLfloat z);
-GLAPI PFNGLRASTERPOS3FPROC glad_glRasterPos3f;
-#define glRasterPos3f glad_glRasterPos3f
-typedef void (APIENTRYP PFNGLRASTERPOS3FVPROC)(const GLfloat *v);
-GLAPI PFNGLRASTERPOS3FVPROC glad_glRasterPos3fv;
-#define glRasterPos3fv glad_glRasterPos3fv
-typedef void (APIENTRYP PFNGLRASTERPOS3IPROC)(GLint x, GLint y, GLint z);
-GLAPI PFNGLRASTERPOS3IPROC glad_glRasterPos3i;
-#define glRasterPos3i glad_glRasterPos3i
-typedef void (APIENTRYP PFNGLRASTERPOS3IVPROC)(const GLint *v);
-GLAPI PFNGLRASTERPOS3IVPROC glad_glRasterPos3iv;
-#define glRasterPos3iv glad_glRasterPos3iv
-typedef void (APIENTRYP PFNGLRASTERPOS3SPROC)(GLshort x, GLshort y, GLshort z);
-GLAPI PFNGLRASTERPOS3SPROC glad_glRasterPos3s;
-#define glRasterPos3s glad_glRasterPos3s
-typedef void (APIENTRYP PFNGLRASTERPOS3SVPROC)(const GLshort *v);
-GLAPI PFNGLRASTERPOS3SVPROC glad_glRasterPos3sv;
-#define glRasterPos3sv glad_glRasterPos3sv
-typedef void (APIENTRYP PFNGLRASTERPOS4DPROC)(GLdouble x, GLdouble y, GLdouble z, GLdouble w);
-GLAPI PFNGLRASTERPOS4DPROC glad_glRasterPos4d;
-#define glRasterPos4d glad_glRasterPos4d
-typedef void (APIENTRYP PFNGLRASTERPOS4DVPROC)(const GLdouble *v);
-GLAPI PFNGLRASTERPOS4DVPROC glad_glRasterPos4dv;
-#define glRasterPos4dv glad_glRasterPos4dv
-typedef void (APIENTRYP PFNGLRASTERPOS4FPROC)(GLfloat x, GLfloat y, GLfloat z, GLfloat w);
-GLAPI PFNGLRASTERPOS4FPROC glad_glRasterPos4f;
-#define glRasterPos4f glad_glRasterPos4f
-typedef void (APIENTRYP PFNGLRASTERPOS4FVPROC)(const GLfloat *v);
-GLAPI PFNGLRASTERPOS4FVPROC glad_glRasterPos4fv;
-#define glRasterPos4fv glad_glRasterPos4fv
-typedef void (APIENTRYP PFNGLRASTERPOS4IPROC)(GLint x, GLint y, GLint z, GLint w);
-GLAPI PFNGLRASTERPOS4IPROC glad_glRasterPos4i;
-#define glRasterPos4i glad_glRasterPos4i
-typedef void (APIENTRYP PFNGLRASTERPOS4IVPROC)(const GLint *v);
-GLAPI PFNGLRASTERPOS4IVPROC glad_glRasterPos4iv;
-#define glRasterPos4iv glad_glRasterPos4iv
-typedef void (APIENTRYP PFNGLRASTERPOS4SPROC)(GLshort x, GLshort y, GLshort z, GLshort w);
-GLAPI PFNGLRASTERPOS4SPROC glad_glRasterPos4s;
-#define glRasterPos4s glad_glRasterPos4s
-typedef void (APIENTRYP PFNGLRASTERPOS4SVPROC)(const GLshort *v);
-GLAPI PFNGLRASTERPOS4SVPROC glad_glRasterPos4sv;
-#define glRasterPos4sv glad_glRasterPos4sv
-typedef void (APIENTRYP PFNGLRECTDPROC)(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2);
-GLAPI PFNGLRECTDPROC glad_glRectd;
-#define glRectd glad_glRectd
-typedef void (APIENTRYP PFNGLRECTDVPROC)(const GLdouble *v1, const GLdouble *v2);
-GLAPI PFNGLRECTDVPROC glad_glRectdv;
-#define glRectdv glad_glRectdv
-typedef void (APIENTRYP PFNGLRECTFPROC)(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2);
-GLAPI PFNGLRECTFPROC glad_glRectf;
-#define glRectf glad_glRectf
-typedef void (APIENTRYP PFNGLRECTFVPROC)(const GLfloat *v1, const GLfloat *v2);
-GLAPI PFNGLRECTFVPROC glad_glRectfv;
-#define glRectfv glad_glRectfv
-typedef void (APIENTRYP PFNGLRECTIPROC)(GLint x1, GLint y1, GLint x2, GLint y2);
-GLAPI PFNGLRECTIPROC glad_glRecti;
-#define glRecti glad_glRecti
-typedef void (APIENTRYP PFNGLRECTIVPROC)(const GLint *v1, const GLint *v2);
-GLAPI PFNGLRECTIVPROC glad_glRectiv;
-#define glRectiv glad_glRectiv
-typedef void (APIENTRYP PFNGLRECTSPROC)(GLshort x1, GLshort y1, GLshort x2, GLshort y2);
-GLAPI PFNGLRECTSPROC glad_glRects;
-#define glRects glad_glRects
-typedef void (APIENTRYP PFNGLRECTSVPROC)(const GLshort *v1, const GLshort *v2);
-GLAPI PFNGLRECTSVPROC glad_glRectsv;
-#define glRectsv glad_glRectsv
-typedef void (APIENTRYP PFNGLTEXCOORD1DPROC)(GLdouble s);
-GLAPI PFNGLTEXCOORD1DPROC glad_glTexCoord1d;
-#define glTexCoord1d glad_glTexCoord1d
-typedef void (APIENTRYP PFNGLTEXCOORD1DVPROC)(const GLdouble *v);
-GLAPI PFNGLTEXCOORD1DVPROC glad_glTexCoord1dv;
-#define glTexCoord1dv glad_glTexCoord1dv
-typedef void (APIENTRYP PFNGLTEXCOORD1FPROC)(GLfloat s);
-GLAPI PFNGLTEXCOORD1FPROC glad_glTexCoord1f;
-#define glTexCoord1f glad_glTexCoord1f
-typedef void (APIENTRYP PFNGLTEXCOORD1FVPROC)(const GLfloat *v);
-GLAPI PFNGLTEXCOORD1FVPROC glad_glTexCoord1fv;
-#define glTexCoord1fv glad_glTexCoord1fv
-typedef void (APIENTRYP PFNGLTEXCOORD1IPROC)(GLint s);
-GLAPI PFNGLTEXCOORD1IPROC glad_glTexCoord1i;
-#define glTexCoord1i glad_glTexCoord1i
-typedef void (APIENTRYP PFNGLTEXCOORD1IVPROC)(const GLint *v);
-GLAPI PFNGLTEXCOORD1IVPROC glad_glTexCoord1iv;
-#define glTexCoord1iv glad_glTexCoord1iv
-typedef void (APIENTRYP PFNGLTEXCOORD1SPROC)(GLshort s);
-GLAPI PFNGLTEXCOORD1SPROC glad_glTexCoord1s;
-#define glTexCoord1s glad_glTexCoord1s
-typedef void (APIENTRYP PFNGLTEXCOORD1SVPROC)(const GLshort *v);
-GLAPI PFNGLTEXCOORD1SVPROC glad_glTexCoord1sv;
-#define glTexCoord1sv glad_glTexCoord1sv
-typedef void (APIENTRYP PFNGLTEXCOORD2DPROC)(GLdouble s, GLdouble t);
-GLAPI PFNGLTEXCOORD2DPROC glad_glTexCoord2d;
-#define glTexCoord2d glad_glTexCoord2d
-typedef void (APIENTRYP PFNGLTEXCOORD2DVPROC)(const GLdouble *v);
-GLAPI PFNGLTEXCOORD2DVPROC glad_glTexCoord2dv;
-#define glTexCoord2dv glad_glTexCoord2dv
-typedef void (APIENTRYP PFNGLTEXCOORD2FPROC)(GLfloat s, GLfloat t);
-GLAPI PFNGLTEXCOORD2FPROC glad_glTexCoord2f;
-#define glTexCoord2f glad_glTexCoord2f
-typedef void (APIENTRYP PFNGLTEXCOORD2FVPROC)(const GLfloat *v);
-GLAPI PFNGLTEXCOORD2FVPROC glad_glTexCoord2fv;
-#define glTexCoord2fv glad_glTexCoord2fv
-typedef void (APIENTRYP PFNGLTEXCOORD2IPROC)(GLint s, GLint t);
-GLAPI PFNGLTEXCOORD2IPROC glad_glTexCoord2i;
-#define glTexCoord2i glad_glTexCoord2i
-typedef void (APIENTRYP PFNGLTEXCOORD2IVPROC)(const GLint *v);
-GLAPI PFNGLTEXCOORD2IVPROC glad_glTexCoord2iv;
-#define glTexCoord2iv glad_glTexCoord2iv
-typedef void (APIENTRYP PFNGLTEXCOORD2SPROC)(GLshort s, GLshort t);
-GLAPI PFNGLTEXCOORD2SPROC glad_glTexCoord2s;
-#define glTexCoord2s glad_glTexCoord2s
-typedef void (APIENTRYP PFNGLTEXCOORD2SVPROC)(const GLshort *v);
-GLAPI PFNGLTEXCOORD2SVPROC glad_glTexCoord2sv;
-#define glTexCoord2sv glad_glTexCoord2sv
-typedef void (APIENTRYP PFNGLTEXCOORD3DPROC)(GLdouble s, GLdouble t, GLdouble r);
-GLAPI PFNGLTEXCOORD3DPROC glad_glTexCoord3d;
-#define glTexCoord3d glad_glTexCoord3d
-typedef void (APIENTRYP PFNGLTEXCOORD3DVPROC)(const GLdouble *v);
-GLAPI PFNGLTEXCOORD3DVPROC glad_glTexCoord3dv;
-#define glTexCoord3dv glad_glTexCoord3dv
-typedef void (APIENTRYP PFNGLTEXCOORD3FPROC)(GLfloat s, GLfloat t, GLfloat r);
-GLAPI PFNGLTEXCOORD3FPROC glad_glTexCoord3f;
-#define glTexCoord3f glad_glTexCoord3f
-typedef void (APIENTRYP PFNGLTEXCOORD3FVPROC)(const GLfloat *v);
-GLAPI PFNGLTEXCOORD3FVPROC glad_glTexCoord3fv;
-#define glTexCoord3fv glad_glTexCoord3fv
-typedef void (APIENTRYP PFNGLTEXCOORD3IPROC)(GLint s, GLint t, GLint r);
-GLAPI PFNGLTEXCOORD3IPROC glad_glTexCoord3i;
-#define glTexCoord3i glad_glTexCoord3i
-typedef void (APIENTRYP PFNGLTEXCOORD3IVPROC)(const GLint *v);
-GLAPI PFNGLTEXCOORD3IVPROC glad_glTexCoord3iv;
-#define glTexCoord3iv glad_glTexCoord3iv
-typedef void (APIENTRYP PFNGLTEXCOORD3SPROC)(GLshort s, GLshort t, GLshort r);
-GLAPI PFNGLTEXCOORD3SPROC glad_glTexCoord3s;
-#define glTexCoord3s glad_glTexCoord3s
-typedef void (APIENTRYP PFNGLTEXCOORD3SVPROC)(const GLshort *v);
-GLAPI PFNGLTEXCOORD3SVPROC glad_glTexCoord3sv;
-#define glTexCoord3sv glad_glTexCoord3sv
-typedef void (APIENTRYP PFNGLTEXCOORD4DPROC)(GLdouble s, GLdouble t, GLdouble r, GLdouble q);
-GLAPI PFNGLTEXCOORD4DPROC glad_glTexCoord4d;
-#define glTexCoord4d glad_glTexCoord4d
-typedef void (APIENTRYP PFNGLTEXCOORD4DVPROC)(const GLdouble *v);
-GLAPI PFNGLTEXCOORD4DVPROC glad_glTexCoord4dv;
-#define glTexCoord4dv glad_glTexCoord4dv
-typedef void (APIENTRYP PFNGLTEXCOORD4FPROC)(GLfloat s, GLfloat t, GLfloat r, GLfloat q);
-GLAPI PFNGLTEXCOORD4FPROC glad_glTexCoord4f;
-#define glTexCoord4f glad_glTexCoord4f
-typedef void (APIENTRYP PFNGLTEXCOORD4FVPROC)(const GLfloat *v);
-GLAPI PFNGLTEXCOORD4FVPROC glad_glTexCoord4fv;
-#define glTexCoord4fv glad_glTexCoord4fv
-typedef void (APIENTRYP PFNGLTEXCOORD4IPROC)(GLint s, GLint t, GLint r, GLint q);
-GLAPI PFNGLTEXCOORD4IPROC glad_glTexCoord4i;
-#define glTexCoord4i glad_glTexCoord4i
-typedef void (APIENTRYP PFNGLTEXCOORD4IVPROC)(const GLint *v);
-GLAPI PFNGLTEXCOORD4IVPROC glad_glTexCoord4iv;
-#define glTexCoord4iv glad_glTexCoord4iv
-typedef void (APIENTRYP PFNGLTEXCOORD4SPROC)(GLshort s, GLshort t, GLshort r, GLshort q);
-GLAPI PFNGLTEXCOORD4SPROC glad_glTexCoord4s;
-#define glTexCoord4s glad_glTexCoord4s
-typedef void (APIENTRYP PFNGLTEXCOORD4SVPROC)(const GLshort *v);
-GLAPI PFNGLTEXCOORD4SVPROC glad_glTexCoord4sv;
-#define glTexCoord4sv glad_glTexCoord4sv
-typedef void (APIENTRYP PFNGLVERTEX2DPROC)(GLdouble x, GLdouble y);
-GLAPI PFNGLVERTEX2DPROC glad_glVertex2d;
-#define glVertex2d glad_glVertex2d
-typedef void (APIENTRYP PFNGLVERTEX2DVPROC)(const GLdouble *v);
-GLAPI PFNGLVERTEX2DVPROC glad_glVertex2dv;
-#define glVertex2dv glad_glVertex2dv
-typedef void (APIENTRYP PFNGLVERTEX2FPROC)(GLfloat x, GLfloat y);
-GLAPI PFNGLVERTEX2FPROC glad_glVertex2f;
-#define glVertex2f glad_glVertex2f
-typedef void (APIENTRYP PFNGLVERTEX2FVPROC)(const GLfloat *v);
-GLAPI PFNGLVERTEX2FVPROC glad_glVertex2fv;
-#define glVertex2fv glad_glVertex2fv
-typedef void (APIENTRYP PFNGLVERTEX2IPROC)(GLint x, GLint y);
-GLAPI PFNGLVERTEX2IPROC glad_glVertex2i;
-#define glVertex2i glad_glVertex2i
-typedef void (APIENTRYP PFNGLVERTEX2IVPROC)(const GLint *v);
-GLAPI PFNGLVERTEX2IVPROC glad_glVertex2iv;
-#define glVertex2iv glad_glVertex2iv
-typedef void (APIENTRYP PFNGLVERTEX2SPROC)(GLshort x, GLshort y);
-GLAPI PFNGLVERTEX2SPROC glad_glVertex2s;
-#define glVertex2s glad_glVertex2s
-typedef void (APIENTRYP PFNGLVERTEX2SVPROC)(const GLshort *v);
-GLAPI PFNGLVERTEX2SVPROC glad_glVertex2sv;
-#define glVertex2sv glad_glVertex2sv
-typedef void (APIENTRYP PFNGLVERTEX3DPROC)(GLdouble x, GLdouble y, GLdouble z);
-GLAPI PFNGLVERTEX3DPROC glad_glVertex3d;
-#define glVertex3d glad_glVertex3d
-typedef void (APIENTRYP PFNGLVERTEX3DVPROC)(const GLdouble *v);
-GLAPI PFNGLVERTEX3DVPROC glad_glVertex3dv;
-#define glVertex3dv glad_glVertex3dv
-typedef void (APIENTRYP PFNGLVERTEX3FPROC)(GLfloat x, GLfloat y, GLfloat z);
-GLAPI PFNGLVERTEX3FPROC glad_glVertex3f;
-#define glVertex3f glad_glVertex3f
-typedef void (APIENTRYP PFNGLVERTEX3FVPROC)(const GLfloat *v);
-GLAPI PFNGLVERTEX3FVPROC glad_glVertex3fv;
-#define glVertex3fv glad_glVertex3fv
-typedef void (APIENTRYP PFNGLVERTEX3IPROC)(GLint x, GLint y, GLint z);
-GLAPI PFNGLVERTEX3IPROC glad_glVertex3i;
-#define glVertex3i glad_glVertex3i
-typedef void (APIENTRYP PFNGLVERTEX3IVPROC)(const GLint *v);
-GLAPI PFNGLVERTEX3IVPROC glad_glVertex3iv;
-#define glVertex3iv glad_glVertex3iv
-typedef void (APIENTRYP PFNGLVERTEX3SPROC)(GLshort x, GLshort y, GLshort z);
-GLAPI PFNGLVERTEX3SPROC glad_glVertex3s;
-#define glVertex3s glad_glVertex3s
-typedef void (APIENTRYP PFNGLVERTEX3SVPROC)(const GLshort *v);
-GLAPI PFNGLVERTEX3SVPROC glad_glVertex3sv;
-#define glVertex3sv glad_glVertex3sv
-typedef void (APIENTRYP PFNGLVERTEX4DPROC)(GLdouble x, GLdouble y, GLdouble z, GLdouble w);
-GLAPI PFNGLVERTEX4DPROC glad_glVertex4d;
-#define glVertex4d glad_glVertex4d
-typedef void (APIENTRYP PFNGLVERTEX4DVPROC)(const GLdouble *v);
-GLAPI PFNGLVERTEX4DVPROC glad_glVertex4dv;
-#define glVertex4dv glad_glVertex4dv
-typedef void (APIENTRYP PFNGLVERTEX4FPROC)(GLfloat x, GLfloat y, GLfloat z, GLfloat w);
-GLAPI PFNGLVERTEX4FPROC glad_glVertex4f;
-#define glVertex4f glad_glVertex4f
-typedef void (APIENTRYP PFNGLVERTEX4FVPROC)(const GLfloat *v);
-GLAPI PFNGLVERTEX4FVPROC glad_glVertex4fv;
-#define glVertex4fv glad_glVertex4fv
-typedef void (APIENTRYP PFNGLVERTEX4IPROC)(GLint x, GLint y, GLint z, GLint w);
-GLAPI PFNGLVERTEX4IPROC glad_glVertex4i;
-#define glVertex4i glad_glVertex4i
-typedef void (APIENTRYP PFNGLVERTEX4IVPROC)(const GLint *v);
-GLAPI PFNGLVERTEX4IVPROC glad_glVertex4iv;
-#define glVertex4iv glad_glVertex4iv
-typedef void (APIENTRYP PFNGLVERTEX4SPROC)(GLshort x, GLshort y, GLshort z, GLshort w);
-GLAPI PFNGLVERTEX4SPROC glad_glVertex4s;
-#define glVertex4s glad_glVertex4s
-typedef void (APIENTRYP PFNGLVERTEX4SVPROC)(const GLshort *v);
-GLAPI PFNGLVERTEX4SVPROC glad_glVertex4sv;
-#define glVertex4sv glad_glVertex4sv
-typedef void (APIENTRYP PFNGLCLIPPLANEPROC)(GLenum plane, const GLdouble *equation);
-GLAPI PFNGLCLIPPLANEPROC glad_glClipPlane;
-#define glClipPlane glad_glClipPlane
-typedef void (APIENTRYP PFNGLCOLORMATERIALPROC)(GLenum face, GLenum mode);
-GLAPI PFNGLCOLORMATERIALPROC glad_glColorMaterial;
-#define glColorMaterial glad_glColorMaterial
-typedef void (APIENTRYP PFNGLFOGFPROC)(GLenum pname, GLfloat param);
-GLAPI PFNGLFOGFPROC glad_glFogf;
-#define glFogf glad_glFogf
-typedef void (APIENTRYP PFNGLFOGFVPROC)(GLenum pname, const GLfloat *params);
-GLAPI PFNGLFOGFVPROC glad_glFogfv;
-#define glFogfv glad_glFogfv
-typedef void (APIENTRYP PFNGLFOGIPROC)(GLenum pname, GLint param);
-GLAPI PFNGLFOGIPROC glad_glFogi;
-#define glFogi glad_glFogi
-typedef void (APIENTRYP PFNGLFOGIVPROC)(GLenum pname, const GLint *params);
-GLAPI PFNGLFOGIVPROC glad_glFogiv;
-#define glFogiv glad_glFogiv
-typedef void (APIENTRYP PFNGLLIGHTFPROC)(GLenum light, GLenum pname, GLfloat param);
-GLAPI PFNGLLIGHTFPROC glad_glLightf;
-#define glLightf glad_glLightf
-typedef void (APIENTRYP PFNGLLIGHTFVPROC)(GLenum light, GLenum pname, const GLfloat *params);
-GLAPI PFNGLLIGHTFVPROC glad_glLightfv;
-#define glLightfv glad_glLightfv
-typedef void (APIENTRYP PFNGLLIGHTIPROC)(GLenum light, GLenum pname, GLint param);
-GLAPI PFNGLLIGHTIPROC glad_glLighti;
-#define glLighti glad_glLighti
-typedef void (APIENTRYP PFNGLLIGHTIVPROC)(GLenum light, GLenum pname, const GLint *params);
-GLAPI PFNGLLIGHTIVPROC glad_glLightiv;
-#define glLightiv glad_glLightiv
-typedef void (APIENTRYP PFNGLLIGHTMODELFPROC)(GLenum pname, GLfloat param);
-GLAPI PFNGLLIGHTMODELFPROC glad_glLightModelf;
-#define glLightModelf glad_glLightModelf
-typedef void (APIENTRYP PFNGLLIGHTMODELFVPROC)(GLenum pname, const GLfloat *params);
-GLAPI PFNGLLIGHTMODELFVPROC glad_glLightModelfv;
-#define glLightModelfv glad_glLightModelfv
-typedef void (APIENTRYP PFNGLLIGHTMODELIPROC)(GLenum pname, GLint param);
-GLAPI PFNGLLIGHTMODELIPROC glad_glLightModeli;
-#define glLightModeli glad_glLightModeli
-typedef void (APIENTRYP PFNGLLIGHTMODELIVPROC)(GLenum pname, const GLint *params);
-GLAPI PFNGLLIGHTMODELIVPROC glad_glLightModeliv;
-#define glLightModeliv glad_glLightModeliv
-typedef void (APIENTRYP PFNGLLINESTIPPLEPROC)(GLint factor, GLushort pattern);
-GLAPI PFNGLLINESTIPPLEPROC glad_glLineStipple;
-#define glLineStipple glad_glLineStipple
-typedef void (APIENTRYP PFNGLMATERIALFPROC)(GLenum face, GLenum pname, GLfloat param);
-GLAPI PFNGLMATERIALFPROC glad_glMaterialf;
-#define glMaterialf glad_glMaterialf
-typedef void (APIENTRYP PFNGLMATERIALFVPROC)(GLenum face, GLenum pname, const GLfloat *params);
-GLAPI PFNGLMATERIALFVPROC glad_glMaterialfv;
-#define glMaterialfv glad_glMaterialfv
-typedef void (APIENTRYP PFNGLMATERIALIPROC)(GLenum face, GLenum pname, GLint param);
-GLAPI PFNGLMATERIALIPROC glad_glMateriali;
-#define glMateriali glad_glMateriali
-typedef void (APIENTRYP PFNGLMATERIALIVPROC)(GLenum face, GLenum pname, const GLint *params);
-GLAPI PFNGLMATERIALIVPROC glad_glMaterialiv;
-#define glMaterialiv glad_glMaterialiv
-typedef void (APIENTRYP PFNGLPOLYGONSTIPPLEPROC)(const GLubyte *mask);
-GLAPI PFNGLPOLYGONSTIPPLEPROC glad_glPolygonStipple;
-#define glPolygonStipple glad_glPolygonStipple
-typedef void (APIENTRYP PFNGLSHADEMODELPROC)(GLenum mode);
-GLAPI PFNGLSHADEMODELPROC glad_glShadeModel;
-#define glShadeModel glad_glShadeModel
-typedef void (APIENTRYP PFNGLTEXENVFPROC)(GLenum target, GLenum pname, GLfloat param);
-GLAPI PFNGLTEXENVFPROC glad_glTexEnvf;
-#define glTexEnvf glad_glTexEnvf
-typedef void (APIENTRYP PFNGLTEXENVFVPROC)(GLenum target, GLenum pname, const GLfloat *params);
-GLAPI PFNGLTEXENVFVPROC glad_glTexEnvfv;
-#define glTexEnvfv glad_glTexEnvfv
-typedef void (APIENTRYP PFNGLTEXENVIPROC)(GLenum target, GLenum pname, GLint param);
-GLAPI PFNGLTEXENVIPROC glad_glTexEnvi;
-#define glTexEnvi glad_glTexEnvi
-typedef void (APIENTRYP PFNGLTEXENVIVPROC)(GLenum target, GLenum pname, const GLint *params);
-GLAPI PFNGLTEXENVIVPROC glad_glTexEnviv;
-#define glTexEnviv glad_glTexEnviv
-typedef void (APIENTRYP PFNGLTEXGENDPROC)(GLenum coord, GLenum pname, GLdouble param);
-GLAPI PFNGLTEXGENDPROC glad_glTexGend;
-#define glTexGend glad_glTexGend
-typedef void (APIENTRYP PFNGLTEXGENDVPROC)(GLenum coord, GLenum pname, const GLdouble *params);
-GLAPI PFNGLTEXGENDVPROC glad_glTexGendv;
-#define glTexGendv glad_glTexGendv
-typedef void (APIENTRYP PFNGLTEXGENFPROC)(GLenum coord, GLenum pname, GLfloat param);
-GLAPI PFNGLTEXGENFPROC glad_glTexGenf;
-#define glTexGenf glad_glTexGenf
-typedef void (APIENTRYP PFNGLTEXGENFVPROC)(GLenum coord, GLenum pname, const GLfloat *params);
-GLAPI PFNGLTEXGENFVPROC glad_glTexGenfv;
-#define glTexGenfv glad_glTexGenfv
-typedef void (APIENTRYP PFNGLTEXGENIPROC)(GLenum coord, GLenum pname, GLint param);
-GLAPI PFNGLTEXGENIPROC glad_glTexGeni;
-#define glTexGeni glad_glTexGeni
-typedef void (APIENTRYP PFNGLTEXGENIVPROC)(GLenum coord, GLenum pname, const GLint *params);
-GLAPI PFNGLTEXGENIVPROC glad_glTexGeniv;
-#define glTexGeniv glad_glTexGeniv
-typedef void (APIENTRYP PFNGLFEEDBACKBUFFERPROC)(GLsizei size, GLenum type, GLfloat *buffer);
-GLAPI PFNGLFEEDBACKBUFFERPROC glad_glFeedbackBuffer;
-#define glFeedbackBuffer glad_glFeedbackBuffer
-typedef void (APIENTRYP PFNGLSELECTBUFFERPROC)(GLsizei size, GLuint *buffer);
-GLAPI PFNGLSELECTBUFFERPROC glad_glSelectBuffer;
-#define glSelectBuffer glad_glSelectBuffer
-typedef GLint (APIENTRYP PFNGLRENDERMODEPROC)(GLenum mode);
-GLAPI PFNGLRENDERMODEPROC glad_glRenderMode;
-#define glRenderMode glad_glRenderMode
-typedef void (APIENTRYP PFNGLINITNAMESPROC)(void);
-GLAPI PFNGLINITNAMESPROC glad_glInitNames;
-#define glInitNames glad_glInitNames
-typedef void (APIENTRYP PFNGLLOADNAMEPROC)(GLuint name);
-GLAPI PFNGLLOADNAMEPROC glad_glLoadName;
-#define glLoadName glad_glLoadName
-typedef void (APIENTRYP PFNGLPASSTHROUGHPROC)(GLfloat token);
-GLAPI PFNGLPASSTHROUGHPROC glad_glPassThrough;
-#define glPassThrough glad_glPassThrough
-typedef void (APIENTRYP PFNGLPOPNAMEPROC)(void);
-GLAPI PFNGLPOPNAMEPROC glad_glPopName;
-#define glPopName glad_glPopName
-typedef void (APIENTRYP PFNGLPUSHNAMEPROC)(GLuint name);
-GLAPI PFNGLPUSHNAMEPROC glad_glPushName;
-#define glPushName glad_glPushName
-typedef void (APIENTRYP PFNGLCLEARACCUMPROC)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
-GLAPI PFNGLCLEARACCUMPROC glad_glClearAccum;
-#define glClearAccum glad_glClearAccum
-typedef void (APIENTRYP PFNGLCLEARINDEXPROC)(GLfloat c);
-GLAPI PFNGLCLEARINDEXPROC glad_glClearIndex;
-#define glClearIndex glad_glClearIndex
-typedef void (APIENTRYP PFNGLINDEXMASKPROC)(GLuint mask);
-GLAPI PFNGLINDEXMASKPROC glad_glIndexMask;
-#define glIndexMask glad_glIndexMask
-typedef void (APIENTRYP PFNGLACCUMPROC)(GLenum op, GLfloat value);
-GLAPI PFNGLACCUMPROC glad_glAccum;
-#define glAccum glad_glAccum
-typedef void (APIENTRYP PFNGLPOPATTRIBPROC)(void);
-GLAPI PFNGLPOPATTRIBPROC glad_glPopAttrib;
-#define glPopAttrib glad_glPopAttrib
-typedef void (APIENTRYP PFNGLPUSHATTRIBPROC)(GLbitfield mask);
-GLAPI PFNGLPUSHATTRIBPROC glad_glPushAttrib;
-#define glPushAttrib glad_glPushAttrib
-typedef void (APIENTRYP PFNGLMAP1DPROC)(GLenum target, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble *points);
-GLAPI PFNGLMAP1DPROC glad_glMap1d;
-#define glMap1d glad_glMap1d
-typedef void (APIENTRYP PFNGLMAP1FPROC)(GLenum target, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat *points);
-GLAPI PFNGLMAP1FPROC glad_glMap1f;
-#define glMap1f glad_glMap1f
-typedef void (APIENTRYP PFNGLMAP2DPROC)(GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble *points);
-GLAPI PFNGLMAP2DPROC glad_glMap2d;
-#define glMap2d glad_glMap2d
-typedef void (APIENTRYP PFNGLMAP2FPROC)(GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat *points);
-GLAPI PFNGLMAP2FPROC glad_glMap2f;
-#define glMap2f glad_glMap2f
-typedef void (APIENTRYP PFNGLMAPGRID1DPROC)(GLint un, GLdouble u1, GLdouble u2);
-GLAPI PFNGLMAPGRID1DPROC glad_glMapGrid1d;
-#define glMapGrid1d glad_glMapGrid1d
-typedef void (APIENTRYP PFNGLMAPGRID1FPROC)(GLint un, GLfloat u1, GLfloat u2);
-GLAPI PFNGLMAPGRID1FPROC glad_glMapGrid1f;
-#define glMapGrid1f glad_glMapGrid1f
-typedef void (APIENTRYP PFNGLMAPGRID2DPROC)(GLint un, GLdouble u1, GLdouble u2, GLint vn, GLdouble v1, GLdouble v2);
-GLAPI PFNGLMAPGRID2DPROC glad_glMapGrid2d;
-#define glMapGrid2d glad_glMapGrid2d
-typedef void (APIENTRYP PFNGLMAPGRID2FPROC)(GLint un, GLfloat u1, GLfloat u2, GLint vn, GLfloat v1, GLfloat v2);
-GLAPI PFNGLMAPGRID2FPROC glad_glMapGrid2f;
-#define glMapGrid2f glad_glMapGrid2f
-typedef void (APIENTRYP PFNGLEVALCOORD1DPROC)(GLdouble u);
-GLAPI PFNGLEVALCOORD1DPROC glad_glEvalCoord1d;
-#define glEvalCoord1d glad_glEvalCoord1d
-typedef void (APIENTRYP PFNGLEVALCOORD1DVPROC)(const GLdouble *u);
-GLAPI PFNGLEVALCOORD1DVPROC glad_glEvalCoord1dv;
-#define glEvalCoord1dv glad_glEvalCoord1dv
-typedef void (APIENTRYP PFNGLEVALCOORD1FPROC)(GLfloat u);
-GLAPI PFNGLEVALCOORD1FPROC glad_glEvalCoord1f;
-#define glEvalCoord1f glad_glEvalCoord1f
-typedef void (APIENTRYP PFNGLEVALCOORD1FVPROC)(const GLfloat *u);
-GLAPI PFNGLEVALCOORD1FVPROC glad_glEvalCoord1fv;
-#define glEvalCoord1fv glad_glEvalCoord1fv
-typedef void (APIENTRYP PFNGLEVALCOORD2DPROC)(GLdouble u, GLdouble v);
-GLAPI PFNGLEVALCOORD2DPROC glad_glEvalCoord2d;
-#define glEvalCoord2d glad_glEvalCoord2d
-typedef void (APIENTRYP PFNGLEVALCOORD2DVPROC)(const GLdouble *u);
-GLAPI PFNGLEVALCOORD2DVPROC glad_glEvalCoord2dv;
-#define glEvalCoord2dv glad_glEvalCoord2dv
-typedef void (APIENTRYP PFNGLEVALCOORD2FPROC)(GLfloat u, GLfloat v);
-GLAPI PFNGLEVALCOORD2FPROC glad_glEvalCoord2f;
-#define glEvalCoord2f glad_glEvalCoord2f
-typedef void (APIENTRYP PFNGLEVALCOORD2FVPROC)(const GLfloat *u);
-GLAPI PFNGLEVALCOORD2FVPROC glad_glEvalCoord2fv;
-#define glEvalCoord2fv glad_glEvalCoord2fv
-typedef void (APIENTRYP PFNGLEVALMESH1PROC)(GLenum mode, GLint i1, GLint i2);
-GLAPI PFNGLEVALMESH1PROC glad_glEvalMesh1;
-#define glEvalMesh1 glad_glEvalMesh1
-typedef void (APIENTRYP PFNGLEVALPOINT1PROC)(GLint i);
-GLAPI PFNGLEVALPOINT1PROC glad_glEvalPoint1;
-#define glEvalPoint1 glad_glEvalPoint1
-typedef void (APIENTRYP PFNGLEVALMESH2PROC)(GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2);
-GLAPI PFNGLEVALMESH2PROC glad_glEvalMesh2;
-#define glEvalMesh2 glad_glEvalMesh2
-typedef void (APIENTRYP PFNGLEVALPOINT2PROC)(GLint i, GLint j);
-GLAPI PFNGLEVALPOINT2PROC glad_glEvalPoint2;
-#define glEvalPoint2 glad_glEvalPoint2
-typedef void (APIENTRYP PFNGLALPHAFUNCPROC)(GLenum func, GLfloat ref);
-GLAPI PFNGLALPHAFUNCPROC glad_glAlphaFunc;
-#define glAlphaFunc glad_glAlphaFunc
-typedef void (APIENTRYP PFNGLPIXELZOOMPROC)(GLfloat xfactor, GLfloat yfactor);
-GLAPI PFNGLPIXELZOOMPROC glad_glPixelZoom;
-#define glPixelZoom glad_glPixelZoom
-typedef void (APIENTRYP PFNGLPIXELTRANSFERFPROC)(GLenum pname, GLfloat param);
-GLAPI PFNGLPIXELTRANSFERFPROC glad_glPixelTransferf;
-#define glPixelTransferf glad_glPixelTransferf
-typedef void (APIENTRYP PFNGLPIXELTRANSFERIPROC)(GLenum pname, GLint param);
-GLAPI PFNGLPIXELTRANSFERIPROC glad_glPixelTransferi;
-#define glPixelTransferi glad_glPixelTransferi
-typedef void (APIENTRYP PFNGLPIXELMAPFVPROC)(GLenum map, GLsizei mapsize, const GLfloat *values);
-GLAPI PFNGLPIXELMAPFVPROC glad_glPixelMapfv;
-#define glPixelMapfv glad_glPixelMapfv
-typedef void (APIENTRYP PFNGLPIXELMAPUIVPROC)(GLenum map, GLsizei mapsize, const GLuint *values);
-GLAPI PFNGLPIXELMAPUIVPROC glad_glPixelMapuiv;
-#define glPixelMapuiv glad_glPixelMapuiv
-typedef void (APIENTRYP PFNGLPIXELMAPUSVPROC)(GLenum map, GLsizei mapsize, const GLushort *values);
-GLAPI PFNGLPIXELMAPUSVPROC glad_glPixelMapusv;
-#define glPixelMapusv glad_glPixelMapusv
-typedef void (APIENTRYP PFNGLCOPYPIXELSPROC)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type);
-GLAPI PFNGLCOPYPIXELSPROC glad_glCopyPixels;
-#define glCopyPixels glad_glCopyPixels
-typedef void (APIENTRYP PFNGLDRAWPIXELSPROC)(GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);
-GLAPI PFNGLDRAWPIXELSPROC glad_glDrawPixels;
-#define glDrawPixels glad_glDrawPixels
-typedef void (APIENTRYP PFNGLGETCLIPPLANEPROC)(GLenum plane, GLdouble *equation);
-GLAPI PFNGLGETCLIPPLANEPROC glad_glGetClipPlane;
-#define glGetClipPlane glad_glGetClipPlane
-typedef void (APIENTRYP PFNGLGETLIGHTFVPROC)(GLenum light, GLenum pname, GLfloat *params);
-GLAPI PFNGLGETLIGHTFVPROC glad_glGetLightfv;
-#define glGetLightfv glad_glGetLightfv
-typedef void (APIENTRYP PFNGLGETLIGHTIVPROC)(GLenum light, GLenum pname, GLint *params);
-GLAPI PFNGLGETLIGHTIVPROC glad_glGetLightiv;
-#define glGetLightiv glad_glGetLightiv
-typedef void (APIENTRYP PFNGLGETMAPDVPROC)(GLenum target, GLenum query, GLdouble *v);
-GLAPI PFNGLGETMAPDVPROC glad_glGetMapdv;
-#define glGetMapdv glad_glGetMapdv
-typedef void (APIENTRYP PFNGLGETMAPFVPROC)(GLenum target, GLenum query, GLfloat *v);
-GLAPI PFNGLGETMAPFVPROC glad_glGetMapfv;
-#define glGetMapfv glad_glGetMapfv
-typedef void (APIENTRYP PFNGLGETMAPIVPROC)(GLenum target, GLenum query, GLint *v);
-GLAPI PFNGLGETMAPIVPROC glad_glGetMapiv;
-#define glGetMapiv glad_glGetMapiv
-typedef void (APIENTRYP PFNGLGETMATERIALFVPROC)(GLenum face, GLenum pname, GLfloat *params);
-GLAPI PFNGLGETMATERIALFVPROC glad_glGetMaterialfv;
-#define glGetMaterialfv glad_glGetMaterialfv
-typedef void (APIENTRYP PFNGLGETMATERIALIVPROC)(GLenum face, GLenum pname, GLint *params);
-GLAPI PFNGLGETMATERIALIVPROC glad_glGetMaterialiv;
-#define glGetMaterialiv glad_glGetMaterialiv
-typedef void (APIENTRYP PFNGLGETPIXELMAPFVPROC)(GLenum map, GLfloat *values);
-GLAPI PFNGLGETPIXELMAPFVPROC glad_glGetPixelMapfv;
-#define glGetPixelMapfv glad_glGetPixelMapfv
-typedef void (APIENTRYP PFNGLGETPIXELMAPUIVPROC)(GLenum map, GLuint *values);
-GLAPI PFNGLGETPIXELMAPUIVPROC glad_glGetPixelMapuiv;
-#define glGetPixelMapuiv glad_glGetPixelMapuiv
-typedef void (APIENTRYP PFNGLGETPIXELMAPUSVPROC)(GLenum map, GLushort *values);
-GLAPI PFNGLGETPIXELMAPUSVPROC glad_glGetPixelMapusv;
-#define glGetPixelMapusv glad_glGetPixelMapusv
-typedef void (APIENTRYP PFNGLGETPOLYGONSTIPPLEPROC)(GLubyte *mask);
-GLAPI PFNGLGETPOLYGONSTIPPLEPROC glad_glGetPolygonStipple;
-#define glGetPolygonStipple glad_glGetPolygonStipple
-typedef void (APIENTRYP PFNGLGETTEXENVFVPROC)(GLenum target, GLenum pname, GLfloat *params);
-GLAPI PFNGLGETTEXENVFVPROC glad_glGetTexEnvfv;
-#define glGetTexEnvfv glad_glGetTexEnvfv
-typedef void (APIENTRYP PFNGLGETTEXENVIVPROC)(GLenum target, GLenum pname, GLint *params);
-GLAPI PFNGLGETTEXENVIVPROC glad_glGetTexEnviv;
-#define glGetTexEnviv glad_glGetTexEnviv
-typedef void (APIENTRYP PFNGLGETTEXGENDVPROC)(GLenum coord, GLenum pname, GLdouble *params);
-GLAPI PFNGLGETTEXGENDVPROC glad_glGetTexGendv;
-#define glGetTexGendv glad_glGetTexGendv
-typedef void (APIENTRYP PFNGLGETTEXGENFVPROC)(GLenum coord, GLenum pname, GLfloat *params);
-GLAPI PFNGLGETTEXGENFVPROC glad_glGetTexGenfv;
-#define glGetTexGenfv glad_glGetTexGenfv
-typedef void (APIENTRYP PFNGLGETTEXGENIVPROC)(GLenum coord, GLenum pname, GLint *params);
-GLAPI PFNGLGETTEXGENIVPROC glad_glGetTexGeniv;
-#define glGetTexGeniv glad_glGetTexGeniv
-typedef GLboolean (APIENTRYP PFNGLISLISTPROC)(GLuint list);
-GLAPI PFNGLISLISTPROC glad_glIsList;
-#define glIsList glad_glIsList
-typedef void (APIENTRYP PFNGLFRUSTUMPROC)(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);
-GLAPI PFNGLFRUSTUMPROC glad_glFrustum;
-#define glFrustum glad_glFrustum
-typedef void (APIENTRYP PFNGLLOADIDENTITYPROC)(void);
-GLAPI PFNGLLOADIDENTITYPROC glad_glLoadIdentity;
-#define glLoadIdentity glad_glLoadIdentity
-typedef void (APIENTRYP PFNGLLOADMATRIXFPROC)(const GLfloat *m);
-GLAPI PFNGLLOADMATRIXFPROC glad_glLoadMatrixf;
-#define glLoadMatrixf glad_glLoadMatrixf
-typedef void (APIENTRYP PFNGLLOADMATRIXDPROC)(const GLdouble *m);
-GLAPI PFNGLLOADMATRIXDPROC glad_glLoadMatrixd;
-#define glLoadMatrixd glad_glLoadMatrixd
-typedef void (APIENTRYP PFNGLMATRIXMODEPROC)(GLenum mode);
-GLAPI PFNGLMATRIXMODEPROC glad_glMatrixMode;
-#define glMatrixMode glad_glMatrixMode
-typedef void (APIENTRYP PFNGLMULTMATRIXFPROC)(const GLfloat *m);
-GLAPI PFNGLMULTMATRIXFPROC glad_glMultMatrixf;
-#define glMultMatrixf glad_glMultMatrixf
-typedef void (APIENTRYP PFNGLMULTMATRIXDPROC)(const GLdouble *m);
-GLAPI PFNGLMULTMATRIXDPROC glad_glMultMatrixd;
-#define glMultMatrixd glad_glMultMatrixd
-typedef void (APIENTRYP PFNGLORTHOPROC)(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);
-GLAPI PFNGLORTHOPROC glad_glOrtho;
-#define glOrtho glad_glOrtho
-typedef void (APIENTRYP PFNGLPOPMATRIXPROC)(void);
-GLAPI PFNGLPOPMATRIXPROC glad_glPopMatrix;
-#define glPopMatrix glad_glPopMatrix
-typedef void (APIENTRYP PFNGLPUSHMATRIXPROC)(void);
-GLAPI PFNGLPUSHMATRIXPROC glad_glPushMatrix;
-#define glPushMatrix glad_glPushMatrix
-typedef void (APIENTRYP PFNGLROTATEDPROC)(GLdouble angle, GLdouble x, GLdouble y, GLdouble z);
-GLAPI PFNGLROTATEDPROC glad_glRotated;
-#define glRotated glad_glRotated
-typedef void (APIENTRYP PFNGLROTATEFPROC)(GLfloat angle, GLfloat x, GLfloat y, GLfloat z);
-GLAPI PFNGLROTATEFPROC glad_glRotatef;
-#define glRotatef glad_glRotatef
-typedef void (APIENTRYP PFNGLSCALEDPROC)(GLdouble x, GLdouble y, GLdouble z);
-GLAPI PFNGLSCALEDPROC glad_glScaled;
-#define glScaled glad_glScaled
-typedef void (APIENTRYP PFNGLSCALEFPROC)(GLfloat x, GLfloat y, GLfloat z);
-GLAPI PFNGLSCALEFPROC glad_glScalef;
-#define glScalef glad_glScalef
-typedef void (APIENTRYP PFNGLTRANSLATEDPROC)(GLdouble x, GLdouble y, GLdouble z);
-GLAPI PFNGLTRANSLATEDPROC glad_glTranslated;
-#define glTranslated glad_glTranslated
-typedef void (APIENTRYP PFNGLTRANSLATEFPROC)(GLfloat x, GLfloat y, GLfloat z);
-GLAPI PFNGLTRANSLATEFPROC glad_glTranslatef;
-#define glTranslatef glad_glTranslatef
-#endif
-#ifndef GL_VERSION_1_1
-#define GL_VERSION_1_1 1
-GLAPI int GLAD_GL_VERSION_1_1;
-typedef void (APIENTRYP PFNGLDRAWARRAYSPROC)(GLenum mode, GLint first, GLsizei count);
-GLAPI PFNGLDRAWARRAYSPROC glad_glDrawArrays;
-#define glDrawArrays glad_glDrawArrays
-typedef void (APIENTRYP PFNGLDRAWELEMENTSPROC)(GLenum mode, GLsizei count, GLenum type, const void *indices);
-GLAPI PFNGLDRAWELEMENTSPROC glad_glDrawElements;
-#define glDrawElements glad_glDrawElements
-typedef void (APIENTRYP PFNGLGETPOINTERVPROC)(GLenum pname, void **params);
-GLAPI PFNGLGETPOINTERVPROC glad_glGetPointerv;
-#define glGetPointerv glad_glGetPointerv
-typedef void (APIENTRYP PFNGLPOLYGONOFFSETPROC)(GLfloat factor, GLfloat units);
-GLAPI PFNGLPOLYGONOFFSETPROC glad_glPolygonOffset;
-#define glPolygonOffset glad_glPolygonOffset
-typedef void (APIENTRYP PFNGLCOPYTEXIMAGE1DPROC)(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border);
-GLAPI PFNGLCOPYTEXIMAGE1DPROC glad_glCopyTexImage1D;
-#define glCopyTexImage1D glad_glCopyTexImage1D
-typedef void (APIENTRYP PFNGLCOPYTEXIMAGE2DPROC)(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
-GLAPI PFNGLCOPYTEXIMAGE2DPROC glad_glCopyTexImage2D;
-#define glCopyTexImage2D glad_glCopyTexImage2D
-typedef void (APIENTRYP PFNGLCOPYTEXSUBIMAGE1DPROC)(GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width);
-GLAPI PFNGLCOPYTEXSUBIMAGE1DPROC glad_glCopyTexSubImage1D;
-#define glCopyTexSubImage1D glad_glCopyTexSubImage1D
-typedef void (APIENTRYP PFNGLCOPYTEXSUBIMAGE2DPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
-GLAPI PFNGLCOPYTEXSUBIMAGE2DPROC glad_glCopyTexSubImage2D;
-#define glCopyTexSubImage2D glad_glCopyTexSubImage2D
-typedef void (APIENTRYP PFNGLTEXSUBIMAGE1DPROC)(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void *pixels);
-GLAPI PFNGLTEXSUBIMAGE1DPROC glad_glTexSubImage1D;
-#define glTexSubImage1D glad_glTexSubImage1D
-typedef void (APIENTRYP PFNGLTEXSUBIMAGE2DPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);
-GLAPI PFNGLTEXSUBIMAGE2DPROC glad_glTexSubImage2D;
-#define glTexSubImage2D glad_glTexSubImage2D
-typedef void (APIENTRYP PFNGLBINDTEXTUREPROC)(GLenum target, GLuint texture);
-GLAPI PFNGLBINDTEXTUREPROC glad_glBindTexture;
-#define glBindTexture glad_glBindTexture
-typedef void (APIENTRYP PFNGLDELETETEXTURESPROC)(GLsizei n, const GLuint *textures);
-GLAPI PFNGLDELETETEXTURESPROC glad_glDeleteTextures;
-#define glDeleteTextures glad_glDeleteTextures
-typedef void (APIENTRYP PFNGLGENTEXTURESPROC)(GLsizei n, GLuint *textures);
-GLAPI PFNGLGENTEXTURESPROC glad_glGenTextures;
-#define glGenTextures glad_glGenTextures
-typedef GLboolean (APIENTRYP PFNGLISTEXTUREPROC)(GLuint texture);
-GLAPI PFNGLISTEXTUREPROC glad_glIsTexture;
-#define glIsTexture glad_glIsTexture
-typedef void (APIENTRYP PFNGLARRAYELEMENTPROC)(GLint i);
-GLAPI PFNGLARRAYELEMENTPROC glad_glArrayElement;
-#define glArrayElement glad_glArrayElement
-typedef void (APIENTRYP PFNGLCOLORPOINTERPROC)(GLint size, GLenum type, GLsizei stride, const void *pointer);
-GLAPI PFNGLCOLORPOINTERPROC glad_glColorPointer;
-#define glColorPointer glad_glColorPointer
-typedef void (APIENTRYP PFNGLDISABLECLIENTSTATEPROC)(GLenum array);
-GLAPI PFNGLDISABLECLIENTSTATEPROC glad_glDisableClientState;
-#define glDisableClientState glad_glDisableClientState
-typedef void (APIENTRYP PFNGLEDGEFLAGPOINTERPROC)(GLsizei stride, const void *pointer);
-GLAPI PFNGLEDGEFLAGPOINTERPROC glad_glEdgeFlagPointer;
-#define glEdgeFlagPointer glad_glEdgeFlagPointer
-typedef void (APIENTRYP PFNGLENABLECLIENTSTATEPROC)(GLenum array);
-GLAPI PFNGLENABLECLIENTSTATEPROC glad_glEnableClientState;
-#define glEnableClientState glad_glEnableClientState
-typedef void (APIENTRYP PFNGLINDEXPOINTERPROC)(GLenum type, GLsizei stride, const void *pointer);
-GLAPI PFNGLINDEXPOINTERPROC glad_glIndexPointer;
-#define glIndexPointer glad_glIndexPointer
-typedef void (APIENTRYP PFNGLINTERLEAVEDARRAYSPROC)(GLenum format, GLsizei stride, const void *pointer);
-GLAPI PFNGLINTERLEAVEDARRAYSPROC glad_glInterleavedArrays;
-#define glInterleavedArrays glad_glInterleavedArrays
-typedef void (APIENTRYP PFNGLNORMALPOINTERPROC)(GLenum type, GLsizei stride, const void *pointer);
-GLAPI PFNGLNORMALPOINTERPROC glad_glNormalPointer;
-#define glNormalPointer glad_glNormalPointer
-typedef void (APIENTRYP PFNGLTEXCOORDPOINTERPROC)(GLint size, GLenum type, GLsizei stride, const void *pointer);
-GLAPI PFNGLTEXCOORDPOINTERPROC glad_glTexCoordPointer;
-#define glTexCoordPointer glad_glTexCoordPointer
-typedef void (APIENTRYP PFNGLVERTEXPOINTERPROC)(GLint size, GLenum type, GLsizei stride, const void *pointer);
-GLAPI PFNGLVERTEXPOINTERPROC glad_glVertexPointer;
-#define glVertexPointer glad_glVertexPointer
-typedef GLboolean (APIENTRYP PFNGLARETEXTURESRESIDENTPROC)(GLsizei n, const GLuint *textures, GLboolean *residences);
-GLAPI PFNGLARETEXTURESRESIDENTPROC glad_glAreTexturesResident;
-#define glAreTexturesResident glad_glAreTexturesResident
-typedef void (APIENTRYP PFNGLPRIORITIZETEXTURESPROC)(GLsizei n, const GLuint *textures, const GLfloat *priorities);
-GLAPI PFNGLPRIORITIZETEXTURESPROC glad_glPrioritizeTextures;
-#define glPrioritizeTextures glad_glPrioritizeTextures
-typedef void (APIENTRYP PFNGLINDEXUBPROC)(GLubyte c);
-GLAPI PFNGLINDEXUBPROC glad_glIndexub;
-#define glIndexub glad_glIndexub
-typedef void (APIENTRYP PFNGLINDEXUBVPROC)(const GLubyte *c);
-GLAPI PFNGLINDEXUBVPROC glad_glIndexubv;
-#define glIndexubv glad_glIndexubv
-typedef void (APIENTRYP PFNGLPOPCLIENTATTRIBPROC)(void);
-GLAPI PFNGLPOPCLIENTATTRIBPROC glad_glPopClientAttrib;
-#define glPopClientAttrib glad_glPopClientAttrib
-typedef void (APIENTRYP PFNGLPUSHCLIENTATTRIBPROC)(GLbitfield mask);
-GLAPI PFNGLPUSHCLIENTATTRIBPROC glad_glPushClientAttrib;
-#define glPushClientAttrib glad_glPushClientAttrib
-#endif
-#ifndef GL_VERSION_1_2
-#define GL_VERSION_1_2 1
-GLAPI int GLAD_GL_VERSION_1_2;
-typedef void (APIENTRYP PFNGLDRAWRANGEELEMENTSPROC)(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices);
-GLAPI PFNGLDRAWRANGEELEMENTSPROC glad_glDrawRangeElements;
-#define glDrawRangeElements glad_glDrawRangeElements
-typedef void (APIENTRYP PFNGLTEXIMAGE3DPROC)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels);
-GLAPI PFNGLTEXIMAGE3DPROC glad_glTexImage3D;
-#define glTexImage3D glad_glTexImage3D
-typedef void (APIENTRYP PFNGLTEXSUBIMAGE3DPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels);
-GLAPI PFNGLTEXSUBIMAGE3DPROC glad_glTexSubImage3D;
-#define glTexSubImage3D glad_glTexSubImage3D
-typedef void (APIENTRYP PFNGLCOPYTEXSUBIMAGE3DPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
-GLAPI PFNGLCOPYTEXSUBIMAGE3DPROC glad_glCopyTexSubImage3D;
-#define glCopyTexSubImage3D glad_glCopyTexSubImage3D
-#endif
-#ifndef GL_VERSION_1_3
-#define GL_VERSION_1_3 1
-GLAPI int GLAD_GL_VERSION_1_3;
-typedef void (APIENTRYP PFNGLACTIVETEXTUREPROC)(GLenum texture);
-GLAPI PFNGLACTIVETEXTUREPROC glad_glActiveTexture;
-#define glActiveTexture glad_glActiveTexture
-typedef void (APIENTRYP PFNGLSAMPLECOVERAGEPROC)(GLfloat value, GLboolean invert);
-GLAPI PFNGLSAMPLECOVERAGEPROC glad_glSampleCoverage;
-#define glSampleCoverage glad_glSampleCoverage
-typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE3DPROC)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data);
-GLAPI PFNGLCOMPRESSEDTEXIMAGE3DPROC glad_glCompressedTexImage3D;
-#define glCompressedTexImage3D glad_glCompressedTexImage3D
-typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE2DPROC)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data);
-GLAPI PFNGLCOMPRESSEDTEXIMAGE2DPROC glad_glCompressedTexImage2D;
-#define glCompressedTexImage2D glad_glCompressedTexImage2D
-typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE1DPROC)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void *data);
-GLAPI PFNGLCOMPRESSEDTEXIMAGE1DPROC glad_glCompressedTexImage1D;
-#define glCompressedTexImage1D glad_glCompressedTexImage1D
-typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data);
-GLAPI PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC glad_glCompressedTexSubImage3D;
-#define glCompressedTexSubImage3D glad_glCompressedTexSubImage3D
-typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data);
-GLAPI PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC glad_glCompressedTexSubImage2D;
-#define glCompressedTexSubImage2D glad_glCompressedTexSubImage2D
-typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC)(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void *data);
-GLAPI PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC glad_glCompressedTexSubImage1D;
-#define glCompressedTexSubImage1D glad_glCompressedTexSubImage1D
-typedef void (APIENTRYP PFNGLGETCOMPRESSEDTEXIMAGEPROC)(GLenum target, GLint level, void *img);
-GLAPI PFNGLGETCOMPRESSEDTEXIMAGEPROC glad_glGetCompressedTexImage;
-#define glGetCompressedTexImage glad_glGetCompressedTexImage
-typedef void (APIENTRYP PFNGLCLIENTACTIVETEXTUREPROC)(GLenum texture);
-GLAPI PFNGLCLIENTACTIVETEXTUREPROC glad_glClientActiveTexture;
-#define glClientActiveTexture glad_glClientActiveTexture
-typedef void (APIENTRYP PFNGLMULTITEXCOORD1DPROC)(GLenum target, GLdouble s);
-GLAPI PFNGLMULTITEXCOORD1DPROC glad_glMultiTexCoord1d;
-#define glMultiTexCoord1d glad_glMultiTexCoord1d
-typedef void (APIENTRYP PFNGLMULTITEXCOORD1DVPROC)(GLenum target, const GLdouble *v);
-GLAPI PFNGLMULTITEXCOORD1DVPROC glad_glMultiTexCoord1dv;
-#define glMultiTexCoord1dv glad_glMultiTexCoord1dv
-typedef void (APIENTRYP PFNGLMULTITEXCOORD1FPROC)(GLenum target, GLfloat s);
-GLAPI PFNGLMULTITEXCOORD1FPROC glad_glMultiTexCoord1f;
-#define glMultiTexCoord1f glad_glMultiTexCoord1f
-typedef void (APIENTRYP PFNGLMULTITEXCOORD1FVPROC)(GLenum target, const GLfloat *v);
-GLAPI PFNGLMULTITEXCOORD1FVPROC glad_glMultiTexCoord1fv;
-#define glMultiTexCoord1fv glad_glMultiTexCoord1fv
-typedef void (APIENTRYP PFNGLMULTITEXCOORD1IPROC)(GLenum target, GLint s);
-GLAPI PFNGLMULTITEXCOORD1IPROC glad_glMultiTexCoord1i;
-#define glMultiTexCoord1i glad_glMultiTexCoord1i
-typedef void (APIENTRYP PFNGLMULTITEXCOORD1IVPROC)(GLenum target, const GLint *v);
-GLAPI PFNGLMULTITEXCOORD1IVPROC glad_glMultiTexCoord1iv;
-#define glMultiTexCoord1iv glad_glMultiTexCoord1iv
-typedef void (APIENTRYP PFNGLMULTITEXCOORD1SPROC)(GLenum target, GLshort s);
-GLAPI PFNGLMULTITEXCOORD1SPROC glad_glMultiTexCoord1s;
-#define glMultiTexCoord1s glad_glMultiTexCoord1s
-typedef void (APIENTRYP PFNGLMULTITEXCOORD1SVPROC)(GLenum target, const GLshort *v);
-GLAPI PFNGLMULTITEXCOORD1SVPROC glad_glMultiTexCoord1sv;
-#define glMultiTexCoord1sv glad_glMultiTexCoord1sv
-typedef void (APIENTRYP PFNGLMULTITEXCOORD2DPROC)(GLenum target, GLdouble s, GLdouble t);
-GLAPI PFNGLMULTITEXCOORD2DPROC glad_glMultiTexCoord2d;
-#define glMultiTexCoord2d glad_glMultiTexCoord2d
-typedef void (APIENTRYP PFNGLMULTITEXCOORD2DVPROC)(GLenum target, const GLdouble *v);
-GLAPI PFNGLMULTITEXCOORD2DVPROC glad_glMultiTexCoord2dv;
-#define glMultiTexCoord2dv glad_glMultiTexCoord2dv
-typedef void (APIENTRYP PFNGLMULTITEXCOORD2FPROC)(GLenum target, GLfloat s, GLfloat t);
-GLAPI PFNGLMULTITEXCOORD2FPROC glad_glMultiTexCoord2f;
-#define glMultiTexCoord2f glad_glMultiTexCoord2f
-typedef void (APIENTRYP PFNGLMULTITEXCOORD2FVPROC)(GLenum target, const GLfloat *v);
-GLAPI PFNGLMULTITEXCOORD2FVPROC glad_glMultiTexCoord2fv;
-#define glMultiTexCoord2fv glad_glMultiTexCoord2fv
-typedef void (APIENTRYP PFNGLMULTITEXCOORD2IPROC)(GLenum target, GLint s, GLint t);
-GLAPI PFNGLMULTITEXCOORD2IPROC glad_glMultiTexCoord2i;
-#define glMultiTexCoord2i glad_glMultiTexCoord2i
-typedef void (APIENTRYP PFNGLMULTITEXCOORD2IVPROC)(GLenum target, const GLint *v);
-GLAPI PFNGLMULTITEXCOORD2IVPROC glad_glMultiTexCoord2iv;
-#define glMultiTexCoord2iv glad_glMultiTexCoord2iv
-typedef void (APIENTRYP PFNGLMULTITEXCOORD2SPROC)(GLenum target, GLshort s, GLshort t);
-GLAPI PFNGLMULTITEXCOORD2SPROC glad_glMultiTexCoord2s;
-#define glMultiTexCoord2s glad_glMultiTexCoord2s
-typedef void (APIENTRYP PFNGLMULTITEXCOORD2SVPROC)(GLenum target, const GLshort *v);
-GLAPI PFNGLMULTITEXCOORD2SVPROC glad_glMultiTexCoord2sv;
-#define glMultiTexCoord2sv glad_glMultiTexCoord2sv
-typedef void (APIENTRYP PFNGLMULTITEXCOORD3DPROC)(GLenum target, GLdouble s, GLdouble t, GLdouble r);
-GLAPI PFNGLMULTITEXCOORD3DPROC glad_glMultiTexCoord3d;
-#define glMultiTexCoord3d glad_glMultiTexCoord3d
-typedef void (APIENTRYP PFNGLMULTITEXCOORD3DVPROC)(GLenum target, const GLdouble *v);
-GLAPI PFNGLMULTITEXCOORD3DVPROC glad_glMultiTexCoord3dv;
-#define glMultiTexCoord3dv glad_glMultiTexCoord3dv
-typedef void (APIENTRYP PFNGLMULTITEXCOORD3FPROC)(GLenum target, GLfloat s, GLfloat t, GLfloat r);
-GLAPI PFNGLMULTITEXCOORD3FPROC glad_glMultiTexCoord3f;
-#define glMultiTexCoord3f glad_glMultiTexCoord3f
-typedef void (APIENTRYP PFNGLMULTITEXCOORD3FVPROC)(GLenum target, const GLfloat *v);
-GLAPI PFNGLMULTITEXCOORD3FVPROC glad_glMultiTexCoord3fv;
-#define glMultiTexCoord3fv glad_glMultiTexCoord3fv
-typedef void (APIENTRYP PFNGLMULTITEXCOORD3IPROC)(GLenum target, GLint s, GLint t, GLint r);
-GLAPI PFNGLMULTITEXCOORD3IPROC glad_glMultiTexCoord3i;
-#define glMultiTexCoord3i glad_glMultiTexCoord3i
-typedef void (APIENTRYP PFNGLMULTITEXCOORD3IVPROC)(GLenum target, const GLint *v);
-GLAPI PFNGLMULTITEXCOORD3IVPROC glad_glMultiTexCoord3iv;
-#define glMultiTexCoord3iv glad_glMultiTexCoord3iv
-typedef void (APIENTRYP PFNGLMULTITEXCOORD3SPROC)(GLenum target, GLshort s, GLshort t, GLshort r);
-GLAPI PFNGLMULTITEXCOORD3SPROC glad_glMultiTexCoord3s;
-#define glMultiTexCoord3s glad_glMultiTexCoord3s
-typedef void (APIENTRYP PFNGLMULTITEXCOORD3SVPROC)(GLenum target, const GLshort *v);
-GLAPI PFNGLMULTITEXCOORD3SVPROC glad_glMultiTexCoord3sv;
-#define glMultiTexCoord3sv glad_glMultiTexCoord3sv
-typedef void (APIENTRYP PFNGLMULTITEXCOORD4DPROC)(GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q);
-GLAPI PFNGLMULTITEXCOORD4DPROC glad_glMultiTexCoord4d;
-#define glMultiTexCoord4d glad_glMultiTexCoord4d
-typedef void (APIENTRYP PFNGLMULTITEXCOORD4DVPROC)(GLenum target, const GLdouble *v);
-GLAPI PFNGLMULTITEXCOORD4DVPROC glad_glMultiTexCoord4dv;
-#define glMultiTexCoord4dv glad_glMultiTexCoord4dv
-typedef void (APIENTRYP PFNGLMULTITEXCOORD4FPROC)(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q);
-GLAPI PFNGLMULTITEXCOORD4FPROC glad_glMultiTexCoord4f;
-#define glMultiTexCoord4f glad_glMultiTexCoord4f
-typedef void (APIENTRYP PFNGLMULTITEXCOORD4FVPROC)(GLenum target, const GLfloat *v);
-GLAPI PFNGLMULTITEXCOORD4FVPROC glad_glMultiTexCoord4fv;
-#define glMultiTexCoord4fv glad_glMultiTexCoord4fv
-typedef void (APIENTRYP PFNGLMULTITEXCOORD4IPROC)(GLenum target, GLint s, GLint t, GLint r, GLint q);
-GLAPI PFNGLMULTITEXCOORD4IPROC glad_glMultiTexCoord4i;
-#define glMultiTexCoord4i glad_glMultiTexCoord4i
-typedef void (APIENTRYP PFNGLMULTITEXCOORD4IVPROC)(GLenum target, const GLint *v);
-GLAPI PFNGLMULTITEXCOORD4IVPROC glad_glMultiTexCoord4iv;
-#define glMultiTexCoord4iv glad_glMultiTexCoord4iv
-typedef void (APIENTRYP PFNGLMULTITEXCOORD4SPROC)(GLenum target, GLshort s, GLshort t, GLshort r, GLshort q);
-GLAPI PFNGLMULTITEXCOORD4SPROC glad_glMultiTexCoord4s;
-#define glMultiTexCoord4s glad_glMultiTexCoord4s
-typedef void (APIENTRYP PFNGLMULTITEXCOORD4SVPROC)(GLenum target, const GLshort *v);
-GLAPI PFNGLMULTITEXCOORD4SVPROC glad_glMultiTexCoord4sv;
-#define glMultiTexCoord4sv glad_glMultiTexCoord4sv
-typedef void (APIENTRYP PFNGLLOADTRANSPOSEMATRIXFPROC)(const GLfloat *m);
-GLAPI PFNGLLOADTRANSPOSEMATRIXFPROC glad_glLoadTransposeMatrixf;
-#define glLoadTransposeMatrixf glad_glLoadTransposeMatrixf
-typedef void (APIENTRYP PFNGLLOADTRANSPOSEMATRIXDPROC)(const GLdouble *m);
-GLAPI PFNGLLOADTRANSPOSEMATRIXDPROC glad_glLoadTransposeMatrixd;
-#define glLoadTransposeMatrixd glad_glLoadTransposeMatrixd
-typedef void (APIENTRYP PFNGLMULTTRANSPOSEMATRIXFPROC)(const GLfloat *m);
-GLAPI PFNGLMULTTRANSPOSEMATRIXFPROC glad_glMultTransposeMatrixf;
-#define glMultTransposeMatrixf glad_glMultTransposeMatrixf
-typedef void (APIENTRYP PFNGLMULTTRANSPOSEMATRIXDPROC)(const GLdouble *m);
-GLAPI PFNGLMULTTRANSPOSEMATRIXDPROC glad_glMultTransposeMatrixd;
-#define glMultTransposeMatrixd glad_glMultTransposeMatrixd
-#endif
-#ifndef GL_VERSION_1_4
-#define GL_VERSION_1_4 1
-GLAPI int GLAD_GL_VERSION_1_4;
-typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEPROC)(GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
-GLAPI PFNGLBLENDFUNCSEPARATEPROC glad_glBlendFuncSeparate;
-#define glBlendFuncSeparate glad_glBlendFuncSeparate
-typedef void (APIENTRYP PFNGLMULTIDRAWARRAYSPROC)(GLenum mode, const GLint *first, const GLsizei *count, GLsizei drawcount);
-GLAPI PFNGLMULTIDRAWARRAYSPROC glad_glMultiDrawArrays;
-#define glMultiDrawArrays glad_glMultiDrawArrays
-typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSPROC)(GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei drawcount);
-GLAPI PFNGLMULTIDRAWELEMENTSPROC glad_glMultiDrawElements;
-#define glMultiDrawElements glad_glMultiDrawElements
-typedef void (APIENTRYP PFNGLPOINTPARAMETERFPROC)(GLenum pname, GLfloat param);
-GLAPI PFNGLPOINTPARAMETERFPROC glad_glPointParameterf;
-#define glPointParameterf glad_glPointParameterf
-typedef void (APIENTRYP PFNGLPOINTPARAMETERFVPROC)(GLenum pname, const GLfloat *params);
-GLAPI PFNGLPOINTPARAMETERFVPROC glad_glPointParameterfv;
-#define glPointParameterfv glad_glPointParameterfv
-typedef void (APIENTRYP PFNGLPOINTPARAMETERIPROC)(GLenum pname, GLint param);
-GLAPI PFNGLPOINTPARAMETERIPROC glad_glPointParameteri;
-#define glPointParameteri glad_glPointParameteri
-typedef void (APIENTRYP PFNGLPOINTPARAMETERIVPROC)(GLenum pname, const GLint *params);
-GLAPI PFNGLPOINTPARAMETERIVPROC glad_glPointParameteriv;
-#define glPointParameteriv glad_glPointParameteriv
-typedef void (APIENTRYP PFNGLFOGCOORDFPROC)(GLfloat coord);
-GLAPI PFNGLFOGCOORDFPROC glad_glFogCoordf;
-#define glFogCoordf glad_glFogCoordf
-typedef void (APIENTRYP PFNGLFOGCOORDFVPROC)(const GLfloat *coord);
-GLAPI PFNGLFOGCOORDFVPROC glad_glFogCoordfv;
-#define glFogCoordfv glad_glFogCoordfv
-typedef void (APIENTRYP PFNGLFOGCOORDDPROC)(GLdouble coord);
-GLAPI PFNGLFOGCOORDDPROC glad_glFogCoordd;
-#define glFogCoordd glad_glFogCoordd
-typedef void (APIENTRYP PFNGLFOGCOORDDVPROC)(const GLdouble *coord);
-GLAPI PFNGLFOGCOORDDVPROC glad_glFogCoorddv;
-#define glFogCoorddv glad_glFogCoorddv
-typedef void (APIENTRYP PFNGLFOGCOORDPOINTERPROC)(GLenum type, GLsizei stride, const void *pointer);
-GLAPI PFNGLFOGCOORDPOINTERPROC glad_glFogCoordPointer;
-#define glFogCoordPointer glad_glFogCoordPointer
-typedef void (APIENTRYP PFNGLSECONDARYCOLOR3BPROC)(GLbyte red, GLbyte green, GLbyte blue);
-GLAPI PFNGLSECONDARYCOLOR3BPROC glad_glSecondaryColor3b;
-#define glSecondaryColor3b glad_glSecondaryColor3b
-typedef void (APIENTRYP PFNGLSECONDARYCOLOR3BVPROC)(const GLbyte *v);
-GLAPI PFNGLSECONDARYCOLOR3BVPROC glad_glSecondaryColor3bv;
-#define glSecondaryColor3bv glad_glSecondaryColor3bv
-typedef void (APIENTRYP PFNGLSECONDARYCOLOR3DPROC)(GLdouble red, GLdouble green, GLdouble blue);
-GLAPI PFNGLSECONDARYCOLOR3DPROC glad_glSecondaryColor3d;
-#define glSecondaryColor3d glad_glSecondaryColor3d
-typedef void (APIENTRYP PFNGLSECONDARYCOLOR3DVPROC)(const GLdouble *v);
-GLAPI PFNGLSECONDARYCOLOR3DVPROC glad_glSecondaryColor3dv;
-#define glSecondaryColor3dv glad_glSecondaryColor3dv
-typedef void (APIENTRYP PFNGLSECONDARYCOLOR3FPROC)(GLfloat red, GLfloat green, GLfloat blue);
-GLAPI PFNGLSECONDARYCOLOR3FPROC glad_glSecondaryColor3f;
-#define glSecondaryColor3f glad_glSecondaryColor3f
-typedef void (APIENTRYP PFNGLSECONDARYCOLOR3FVPROC)(const GLfloat *v);
-GLAPI PFNGLSECONDARYCOLOR3FVPROC glad_glSecondaryColor3fv;
-#define glSecondaryColor3fv glad_glSecondaryColor3fv
-typedef void (APIENTRYP PFNGLSECONDARYCOLOR3IPROC)(GLint red, GLint green, GLint blue);
-GLAPI PFNGLSECONDARYCOLOR3IPROC glad_glSecondaryColor3i;
-#define glSecondaryColor3i glad_glSecondaryColor3i
-typedef void (APIENTRYP PFNGLSECONDARYCOLOR3IVPROC)(const GLint *v);
-GLAPI PFNGLSECONDARYCOLOR3IVPROC glad_glSecondaryColor3iv;
-#define glSecondaryColor3iv glad_glSecondaryColor3iv
-typedef void (APIENTRYP PFNGLSECONDARYCOLOR3SPROC)(GLshort red, GLshort green, GLshort blue);
-GLAPI PFNGLSECONDARYCOLOR3SPROC glad_glSecondaryColor3s;
-#define glSecondaryColor3s glad_glSecondaryColor3s
-typedef void (APIENTRYP PFNGLSECONDARYCOLOR3SVPROC)(const GLshort *v);
-GLAPI PFNGLSECONDARYCOLOR3SVPROC glad_glSecondaryColor3sv;
-#define glSecondaryColor3sv glad_glSecondaryColor3sv
-typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UBPROC)(GLubyte red, GLubyte green, GLubyte blue);
-GLAPI PFNGLSECONDARYCOLOR3UBPROC glad_glSecondaryColor3ub;
-#define glSecondaryColor3ub glad_glSecondaryColor3ub
-typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UBVPROC)(const GLubyte *v);
-GLAPI PFNGLSECONDARYCOLOR3UBVPROC glad_glSecondaryColor3ubv;
-#define glSecondaryColor3ubv glad_glSecondaryColor3ubv
-typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UIPROC)(GLuint red, GLuint green, GLuint blue);
-GLAPI PFNGLSECONDARYCOLOR3UIPROC glad_glSecondaryColor3ui;
-#define glSecondaryColor3ui glad_glSecondaryColor3ui
-typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UIVPROC)(const GLuint *v);
-GLAPI PFNGLSECONDARYCOLOR3UIVPROC glad_glSecondaryColor3uiv;
-#define glSecondaryColor3uiv glad_glSecondaryColor3uiv
-typedef void (APIENTRYP PFNGLSECONDARYCOLOR3USPROC)(GLushort red, GLushort green, GLushort blue);
-GLAPI PFNGLSECONDARYCOLOR3USPROC glad_glSecondaryColor3us;
-#define glSecondaryColor3us glad_glSecondaryColor3us
-typedef void (APIENTRYP PFNGLSECONDARYCOLOR3USVPROC)(const GLushort *v);
-GLAPI PFNGLSECONDARYCOLOR3USVPROC glad_glSecondaryColor3usv;
-#define glSecondaryColor3usv glad_glSecondaryColor3usv
-typedef void (APIENTRYP PFNGLSECONDARYCOLORPOINTERPROC)(GLint size, GLenum type, GLsizei stride, const void *pointer);
-GLAPI PFNGLSECONDARYCOLORPOINTERPROC glad_glSecondaryColorPointer;
-#define glSecondaryColorPointer glad_glSecondaryColorPointer
-typedef void (APIENTRYP PFNGLWINDOWPOS2DPROC)(GLdouble x, GLdouble y);
-GLAPI PFNGLWINDOWPOS2DPROC glad_glWindowPos2d;
-#define glWindowPos2d glad_glWindowPos2d
-typedef void (APIENTRYP PFNGLWINDOWPOS2DVPROC)(const GLdouble *v);
-GLAPI PFNGLWINDOWPOS2DVPROC glad_glWindowPos2dv;
-#define glWindowPos2dv glad_glWindowPos2dv
-typedef void (APIENTRYP PFNGLWINDOWPOS2FPROC)(GLfloat x, GLfloat y);
-GLAPI PFNGLWINDOWPOS2FPROC glad_glWindowPos2f;
-#define glWindowPos2f glad_glWindowPos2f
-typedef void (APIENTRYP PFNGLWINDOWPOS2FVPROC)(const GLfloat *v);
-GLAPI PFNGLWINDOWPOS2FVPROC glad_glWindowPos2fv;
-#define glWindowPos2fv glad_glWindowPos2fv
-typedef void (APIENTRYP PFNGLWINDOWPOS2IPROC)(GLint x, GLint y);
-GLAPI PFNGLWINDOWPOS2IPROC glad_glWindowPos2i;
-#define glWindowPos2i glad_glWindowPos2i
-typedef void (APIENTRYP PFNGLWINDOWPOS2IVPROC)(const GLint *v);
-GLAPI PFNGLWINDOWPOS2IVPROC glad_glWindowPos2iv;
-#define glWindowPos2iv glad_glWindowPos2iv
-typedef void (APIENTRYP PFNGLWINDOWPOS2SPROC)(GLshort x, GLshort y);
-GLAPI PFNGLWINDOWPOS2SPROC glad_glWindowPos2s;
-#define glWindowPos2s glad_glWindowPos2s
-typedef void (APIENTRYP PFNGLWINDOWPOS2SVPROC)(const GLshort *v);
-GLAPI PFNGLWINDOWPOS2SVPROC glad_glWindowPos2sv;
-#define glWindowPos2sv glad_glWindowPos2sv
-typedef void (APIENTRYP PFNGLWINDOWPOS3DPROC)(GLdouble x, GLdouble y, GLdouble z);
-GLAPI PFNGLWINDOWPOS3DPROC glad_glWindowPos3d;
-#define glWindowPos3d glad_glWindowPos3d
-typedef void (APIENTRYP PFNGLWINDOWPOS3DVPROC)(const GLdouble *v);
-GLAPI PFNGLWINDOWPOS3DVPROC glad_glWindowPos3dv;
-#define glWindowPos3dv glad_glWindowPos3dv
-typedef void (APIENTRYP PFNGLWINDOWPOS3FPROC)(GLfloat x, GLfloat y, GLfloat z);
-GLAPI PFNGLWINDOWPOS3FPROC glad_glWindowPos3f;
-#define glWindowPos3f glad_glWindowPos3f
-typedef void (APIENTRYP PFNGLWINDOWPOS3FVPROC)(const GLfloat *v);
-GLAPI PFNGLWINDOWPOS3FVPROC glad_glWindowPos3fv;
-#define glWindowPos3fv glad_glWindowPos3fv
-typedef void (APIENTRYP PFNGLWINDOWPOS3IPROC)(GLint x, GLint y, GLint z);
-GLAPI PFNGLWINDOWPOS3IPROC glad_glWindowPos3i;
-#define glWindowPos3i glad_glWindowPos3i
-typedef void (APIENTRYP PFNGLWINDOWPOS3IVPROC)(const GLint *v);
-GLAPI PFNGLWINDOWPOS3IVPROC glad_glWindowPos3iv;
-#define glWindowPos3iv glad_glWindowPos3iv
-typedef void (APIENTRYP PFNGLWINDOWPOS3SPROC)(GLshort x, GLshort y, GLshort z);
-GLAPI PFNGLWINDOWPOS3SPROC glad_glWindowPos3s;
-#define glWindowPos3s glad_glWindowPos3s
-typedef void (APIENTRYP PFNGLWINDOWPOS3SVPROC)(const GLshort *v);
-GLAPI PFNGLWINDOWPOS3SVPROC glad_glWindowPos3sv;
-#define glWindowPos3sv glad_glWindowPos3sv
-typedef void (APIENTRYP PFNGLBLENDCOLORPROC)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
-GLAPI PFNGLBLENDCOLORPROC glad_glBlendColor;
-#define glBlendColor glad_glBlendColor
-typedef void (APIENTRYP PFNGLBLENDEQUATIONPROC)(GLenum mode);
-GLAPI PFNGLBLENDEQUATIONPROC glad_glBlendEquation;
-#define glBlendEquation glad_glBlendEquation
-#endif
-#ifndef GL_VERSION_1_5
-#define GL_VERSION_1_5 1
-GLAPI int GLAD_GL_VERSION_1_5;
-typedef void (APIENTRYP PFNGLGENQUERIESPROC)(GLsizei n, GLuint *ids);
-GLAPI PFNGLGENQUERIESPROC glad_glGenQueries;
-#define glGenQueries glad_glGenQueries
-typedef void (APIENTRYP PFNGLDELETEQUERIESPROC)(GLsizei n, const GLuint *ids);
-GLAPI PFNGLDELETEQUERIESPROC glad_glDeleteQueries;
-#define glDeleteQueries glad_glDeleteQueries
-typedef GLboolean (APIENTRYP PFNGLISQUERYPROC)(GLuint id);
-GLAPI PFNGLISQUERYPROC glad_glIsQuery;
-#define glIsQuery glad_glIsQuery
-typedef void (APIENTRYP PFNGLBEGINQUERYPROC)(GLenum target, GLuint id);
-GLAPI PFNGLBEGINQUERYPROC glad_glBeginQuery;
-#define glBeginQuery glad_glBeginQuery
-typedef void (APIENTRYP PFNGLENDQUERYPROC)(GLenum target);
-GLAPI PFNGLENDQUERYPROC glad_glEndQuery;
-#define glEndQuery glad_glEndQuery
-typedef void (APIENTRYP PFNGLGETQUERYIVPROC)(GLenum target, GLenum pname, GLint *params);
-GLAPI PFNGLGETQUERYIVPROC glad_glGetQueryiv;
-#define glGetQueryiv glad_glGetQueryiv
-typedef void (APIENTRYP PFNGLGETQUERYOBJECTIVPROC)(GLuint id, GLenum pname, GLint *params);
-GLAPI PFNGLGETQUERYOBJECTIVPROC glad_glGetQueryObjectiv;
-#define glGetQueryObjectiv glad_glGetQueryObjectiv
-typedef void (APIENTRYP PFNGLGETQUERYOBJECTUIVPROC)(GLuint id, GLenum pname, GLuint *params);
-GLAPI PFNGLGETQUERYOBJECTUIVPROC glad_glGetQueryObjectuiv;
-#define glGetQueryObjectuiv glad_glGetQueryObjectuiv
-typedef void (APIENTRYP PFNGLBINDBUFFERPROC)(GLenum target, GLuint buffer);
-GLAPI PFNGLBINDBUFFERPROC glad_glBindBuffer;
-#define glBindBuffer glad_glBindBuffer
-typedef void (APIENTRYP PFNGLDELETEBUFFERSPROC)(GLsizei n, const GLuint *buffers);
-GLAPI PFNGLDELETEBUFFERSPROC glad_glDeleteBuffers;
-#define glDeleteBuffers glad_glDeleteBuffers
-typedef void (APIENTRYP PFNGLGENBUFFERSPROC)(GLsizei n, GLuint *buffers);
-GLAPI PFNGLGENBUFFERSPROC glad_glGenBuffers;
-#define glGenBuffers glad_glGenBuffers
-typedef GLboolean (APIENTRYP PFNGLISBUFFERPROC)(GLuint buffer);
-GLAPI PFNGLISBUFFERPROC glad_glIsBuffer;
-#define glIsBuffer glad_glIsBuffer
-typedef void (APIENTRYP PFNGLBUFFERDATAPROC)(GLenum target, GLsizeiptr size, const void *data, GLenum usage);
-GLAPI PFNGLBUFFERDATAPROC glad_glBufferData;
-#define glBufferData glad_glBufferData
-typedef void (APIENTRYP PFNGLBUFFERSUBDATAPROC)(GLenum target, GLintptr offset, GLsizeiptr size, const void *data);
-GLAPI PFNGLBUFFERSUBDATAPROC glad_glBufferSubData;
-#define glBufferSubData glad_glBufferSubData
-typedef void (APIENTRYP PFNGLGETBUFFERSUBDATAPROC)(GLenum target, GLintptr offset, GLsizeiptr size, void *data);
-GLAPI PFNGLGETBUFFERSUBDATAPROC glad_glGetBufferSubData;
-#define glGetBufferSubData glad_glGetBufferSubData
-typedef void * (APIENTRYP PFNGLMAPBUFFERPROC)(GLenum target, GLenum access);
-GLAPI PFNGLMAPBUFFERPROC glad_glMapBuffer;
-#define glMapBuffer glad_glMapBuffer
-typedef GLboolean (APIENTRYP PFNGLUNMAPBUFFERPROC)(GLenum target);
-GLAPI PFNGLUNMAPBUFFERPROC glad_glUnmapBuffer;
-#define glUnmapBuffer glad_glUnmapBuffer
-typedef void (APIENTRYP PFNGLGETBUFFERPARAMETERIVPROC)(GLenum target, GLenum pname, GLint *params);
-GLAPI PFNGLGETBUFFERPARAMETERIVPROC glad_glGetBufferParameteriv;
-#define glGetBufferParameteriv glad_glGetBufferParameteriv
-typedef void (APIENTRYP PFNGLGETBUFFERPOINTERVPROC)(GLenum target, GLenum pname, void **params);
-GLAPI PFNGLGETBUFFERPOINTERVPROC glad_glGetBufferPointerv;
-#define glGetBufferPointerv glad_glGetBufferPointerv
-#endif
-#ifndef GL_VERSION_2_0
-#define GL_VERSION_2_0 1
-GLAPI int GLAD_GL_VERSION_2_0;
-typedef void (APIENTRYP PFNGLBLENDEQUATIONSEPARATEPROC)(GLenum modeRGB, GLenum modeAlpha);
-GLAPI PFNGLBLENDEQUATIONSEPARATEPROC glad_glBlendEquationSeparate;
-#define glBlendEquationSeparate glad_glBlendEquationSeparate
-typedef void (APIENTRYP PFNGLDRAWBUFFERSPROC)(GLsizei n, const GLenum *bufs);
-GLAPI PFNGLDRAWBUFFERSPROC glad_glDrawBuffers;
-#define glDrawBuffers glad_glDrawBuffers
-typedef void (APIENTRYP PFNGLSTENCILOPSEPARATEPROC)(GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);
-GLAPI PFNGLSTENCILOPSEPARATEPROC glad_glStencilOpSeparate;
-#define glStencilOpSeparate glad_glStencilOpSeparate
-typedef void (APIENTRYP PFNGLSTENCILFUNCSEPARATEPROC)(GLenum face, GLenum func, GLint ref, GLuint mask);
-GLAPI PFNGLSTENCILFUNCSEPARATEPROC glad_glStencilFuncSeparate;
-#define glStencilFuncSeparate glad_glStencilFuncSeparate
-typedef void (APIENTRYP PFNGLSTENCILMASKSEPARATEPROC)(GLenum face, GLuint mask);
-GLAPI PFNGLSTENCILMASKSEPARATEPROC glad_glStencilMaskSeparate;
-#define glStencilMaskSeparate glad_glStencilMaskSeparate
-typedef void (APIENTRYP PFNGLATTACHSHADERPROC)(GLuint program, GLuint shader);
-GLAPI PFNGLATTACHSHADERPROC glad_glAttachShader;
-#define glAttachShader glad_glAttachShader
-typedef void (APIENTRYP PFNGLBINDATTRIBLOCATIONPROC)(GLuint program, GLuint index, const GLchar *name);
-GLAPI PFNGLBINDATTRIBLOCATIONPROC glad_glBindAttribLocation;
-#define glBindAttribLocation glad_glBindAttribLocation
-typedef void (APIENTRYP PFNGLCOMPILESHADERPROC)(GLuint shader);
-GLAPI PFNGLCOMPILESHADERPROC glad_glCompileShader;
-#define glCompileShader glad_glCompileShader
-typedef GLuint (APIENTRYP PFNGLCREATEPROGRAMPROC)(void);
-GLAPI PFNGLCREATEPROGRAMPROC glad_glCreateProgram;
-#define glCreateProgram glad_glCreateProgram
-typedef GLuint (APIENTRYP PFNGLCREATESHADERPROC)(GLenum type);
-GLAPI PFNGLCREATESHADERPROC glad_glCreateShader;
-#define glCreateShader glad_glCreateShader
-typedef void (APIENTRYP PFNGLDELETEPROGRAMPROC)(GLuint program);
-GLAPI PFNGLDELETEPROGRAMPROC glad_glDeleteProgram;
-#define glDeleteProgram glad_glDeleteProgram
-typedef void (APIENTRYP PFNGLDELETESHADERPROC)(GLuint shader);
-GLAPI PFNGLDELETESHADERPROC glad_glDeleteShader;
-#define glDeleteShader glad_glDeleteShader
-typedef void (APIENTRYP PFNGLDETACHSHADERPROC)(GLuint program, GLuint shader);
-GLAPI PFNGLDETACHSHADERPROC glad_glDetachShader;
-#define glDetachShader glad_glDetachShader
-typedef void (APIENTRYP PFNGLDISABLEVERTEXATTRIBARRAYPROC)(GLuint index);
-GLAPI PFNGLDISABLEVERTEXATTRIBARRAYPROC glad_glDisableVertexAttribArray;
-#define glDisableVertexAttribArray glad_glDisableVertexAttribArray
-typedef void (APIENTRYP PFNGLENABLEVERTEXATTRIBARRAYPROC)(GLuint index);
-GLAPI PFNGLENABLEVERTEXATTRIBARRAYPROC glad_glEnableVertexAttribArray;
-#define glEnableVertexAttribArray glad_glEnableVertexAttribArray
-typedef void (APIENTRYP PFNGLGETACTIVEATTRIBPROC)(GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
-GLAPI PFNGLGETACTIVEATTRIBPROC glad_glGetActiveAttrib;
-#define glGetActiveAttrib glad_glGetActiveAttrib
-typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMPROC)(GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
-GLAPI PFNGLGETACTIVEUNIFORMPROC glad_glGetActiveUniform;
-#define glGetActiveUniform glad_glGetActiveUniform
-typedef void (APIENTRYP PFNGLGETATTACHEDSHADERSPROC)(GLuint program, GLsizei maxCount, GLsizei *count, GLuint *shaders);
-GLAPI PFNGLGETATTACHEDSHADERSPROC glad_glGetAttachedShaders;
-#define glGetAttachedShaders glad_glGetAttachedShaders
-typedef GLint (APIENTRYP PFNGLGETATTRIBLOCATIONPROC)(GLuint program, const GLchar *name);
-GLAPI PFNGLGETATTRIBLOCATIONPROC glad_glGetAttribLocation;
-#define glGetAttribLocation glad_glGetAttribLocation
-typedef void (APIENTRYP PFNGLGETPROGRAMIVPROC)(GLuint program, GLenum pname, GLint *params);
-GLAPI PFNGLGETPROGRAMIVPROC glad_glGetProgramiv;
-#define glGetProgramiv glad_glGetProgramiv
-typedef void (APIENTRYP PFNGLGETPROGRAMINFOLOGPROC)(GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
-GLAPI PFNGLGETPROGRAMINFOLOGPROC glad_glGetProgramInfoLog;
-#define glGetProgramInfoLog glad_glGetProgramInfoLog
-typedef void (APIENTRYP PFNGLGETSHADERIVPROC)(GLuint shader, GLenum pname, GLint *params);
-GLAPI PFNGLGETSHADERIVPROC glad_glGetShaderiv;
-#define glGetShaderiv glad_glGetShaderiv
-typedef void (APIENTRYP PFNGLGETSHADERINFOLOGPROC)(GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
-GLAPI PFNGLGETSHADERINFOLOGPROC glad_glGetShaderInfoLog;
-#define glGetShaderInfoLog glad_glGetShaderInfoLog
-typedef void (APIENTRYP PFNGLGETSHADERSOURCEPROC)(GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source);
-GLAPI PFNGLGETSHADERSOURCEPROC glad_glGetShaderSource;
-#define glGetShaderSource glad_glGetShaderSource
-typedef GLint (APIENTRYP PFNGLGETUNIFORMLOCATIONPROC)(GLuint program, const GLchar *name);
-GLAPI PFNGLGETUNIFORMLOCATIONPROC glad_glGetUniformLocation;
-#define glGetUniformLocation glad_glGetUniformLocation
-typedef void (APIENTRYP PFNGLGETUNIFORMFVPROC)(GLuint program, GLint location, GLfloat *params);
-GLAPI PFNGLGETUNIFORMFVPROC glad_glGetUniformfv;
-#define glGetUniformfv glad_glGetUniformfv
-typedef void (APIENTRYP PFNGLGETUNIFORMIVPROC)(GLuint program, GLint location, GLint *params);
-GLAPI PFNGLGETUNIFORMIVPROC glad_glGetUniformiv;
-#define glGetUniformiv glad_glGetUniformiv
-typedef void (APIENTRYP PFNGLGETVERTEXATTRIBDVPROC)(GLuint index, GLenum pname, GLdouble *params);
-GLAPI PFNGLGETVERTEXATTRIBDVPROC glad_glGetVertexAttribdv;
-#define glGetVertexAttribdv glad_glGetVertexAttribdv
-typedef void (APIENTRYP PFNGLGETVERTEXATTRIBFVPROC)(GLuint index, GLenum pname, GLfloat *params);
-GLAPI PFNGLGETVERTEXATTRIBFVPROC glad_glGetVertexAttribfv;
-#define glGetVertexAttribfv glad_glGetVertexAttribfv
-typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIVPROC)(GLuint index, GLenum pname, GLint *params);
-GLAPI PFNGLGETVERTEXATTRIBIVPROC glad_glGetVertexAttribiv;
-#define glGetVertexAttribiv glad_glGetVertexAttribiv
-typedef void (APIENTRYP PFNGLGETVERTEXATTRIBPOINTERVPROC)(GLuint index, GLenum pname, void **pointer);
-GLAPI PFNGLGETVERTEXATTRIBPOINTERVPROC glad_glGetVertexAttribPointerv;
-#define glGetVertexAttribPointerv glad_glGetVertexAttribPointerv
-typedef GLboolean (APIENTRYP PFNGLISPROGRAMPROC)(GLuint program);
-GLAPI PFNGLISPROGRAMPROC glad_glIsProgram;
-#define glIsProgram glad_glIsProgram
-typedef GLboolean (APIENTRYP PFNGLISSHADERPROC)(GLuint shader);
-GLAPI PFNGLISSHADERPROC glad_glIsShader;
-#define glIsShader glad_glIsShader
-typedef void (APIENTRYP PFNGLLINKPROGRAMPROC)(GLuint program);
-GLAPI PFNGLLINKPROGRAMPROC glad_glLinkProgram;
-#define glLinkProgram glad_glLinkProgram
-typedef void (APIENTRYP PFNGLSHADERSOURCEPROC)(GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length);
-GLAPI PFNGLSHADERSOURCEPROC glad_glShaderSource;
-#define glShaderSource glad_glShaderSource
-typedef void (APIENTRYP PFNGLUSEPROGRAMPROC)(GLuint program);
-GLAPI PFNGLUSEPROGRAMPROC glad_glUseProgram;
-#define glUseProgram glad_glUseProgram
-typedef void (APIENTRYP PFNGLUNIFORM1FPROC)(GLint location, GLfloat v0);
-GLAPI PFNGLUNIFORM1FPROC glad_glUniform1f;
-#define glUniform1f glad_glUniform1f
-typedef void (APIENTRYP PFNGLUNIFORM2FPROC)(GLint location, GLfloat v0, GLfloat v1);
-GLAPI PFNGLUNIFORM2FPROC glad_glUniform2f;
-#define glUniform2f glad_glUniform2f
-typedef void (APIENTRYP PFNGLUNIFORM3FPROC)(GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
-GLAPI PFNGLUNIFORM3FPROC glad_glUniform3f;
-#define glUniform3f glad_glUniform3f
-typedef void (APIENTRYP PFNGLUNIFORM4FPROC)(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
-GLAPI PFNGLUNIFORM4FPROC glad_glUniform4f;
-#define glUniform4f glad_glUniform4f
-typedef void (APIENTRYP PFNGLUNIFORM1IPROC)(GLint location, GLint v0);
-GLAPI PFNGLUNIFORM1IPROC glad_glUniform1i;
-#define glUniform1i glad_glUniform1i
-typedef void (APIENTRYP PFNGLUNIFORM2IPROC)(GLint location, GLint v0, GLint v1);
-GLAPI PFNGLUNIFORM2IPROC glad_glUniform2i;
-#define glUniform2i glad_glUniform2i
-typedef void (APIENTRYP PFNGLUNIFORM3IPROC)(GLint location, GLint v0, GLint v1, GLint v2);
-GLAPI PFNGLUNIFORM3IPROC glad_glUniform3i;
-#define glUniform3i glad_glUniform3i
-typedef void (APIENTRYP PFNGLUNIFORM4IPROC)(GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
-GLAPI PFNGLUNIFORM4IPROC glad_glUniform4i;
-#define glUniform4i glad_glUniform4i
-typedef void (APIENTRYP PFNGLUNIFORM1FVPROC)(GLint location, GLsizei count, const GLfloat *value);
-GLAPI PFNGLUNIFORM1FVPROC glad_glUniform1fv;
-#define glUniform1fv glad_glUniform1fv
-typedef void (APIENTRYP PFNGLUNIFORM2FVPROC)(GLint location, GLsizei count, const GLfloat *value);
-GLAPI PFNGLUNIFORM2FVPROC glad_glUniform2fv;
-#define glUniform2fv glad_glUniform2fv
-typedef void (APIENTRYP PFNGLUNIFORM3FVPROC)(GLint location, GLsizei count, const GLfloat *value);
-GLAPI PFNGLUNIFORM3FVPROC glad_glUniform3fv;
-#define glUniform3fv glad_glUniform3fv
-typedef void (APIENTRYP PFNGLUNIFORM4FVPROC)(GLint location, GLsizei count, const GLfloat *value);
-GLAPI PFNGLUNIFORM4FVPROC glad_glUniform4fv;
-#define glUniform4fv glad_glUniform4fv
-typedef void (APIENTRYP PFNGLUNIFORM1IVPROC)(GLint location, GLsizei count, const GLint *value);
-GLAPI PFNGLUNIFORM1IVPROC glad_glUniform1iv;
-#define glUniform1iv glad_glUniform1iv
-typedef void (APIENTRYP PFNGLUNIFORM2IVPROC)(GLint location, GLsizei count, const GLint *value);
-GLAPI PFNGLUNIFORM2IVPROC glad_glUniform2iv;
-#define glUniform2iv glad_glUniform2iv
-typedef void (APIENTRYP PFNGLUNIFORM3IVPROC)(GLint location, GLsizei count, const GLint *value);
-GLAPI PFNGLUNIFORM3IVPROC glad_glUniform3iv;
-#define glUniform3iv glad_glUniform3iv
-typedef void (APIENTRYP PFNGLUNIFORM4IVPROC)(GLint location, GLsizei count, const GLint *value);
-GLAPI PFNGLUNIFORM4IVPROC glad_glUniform4iv;
-#define glUniform4iv glad_glUniform4iv
-typedef void (APIENTRYP PFNGLUNIFORMMATRIX2FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
-GLAPI PFNGLUNIFORMMATRIX2FVPROC glad_glUniformMatrix2fv;
-#define glUniformMatrix2fv glad_glUniformMatrix2fv
-typedef void (APIENTRYP PFNGLUNIFORMMATRIX3FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
-GLAPI PFNGLUNIFORMMATRIX3FVPROC glad_glUniformMatrix3fv;
-#define glUniformMatrix3fv glad_glUniformMatrix3fv
-typedef void (APIENTRYP PFNGLUNIFORMMATRIX4FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
-GLAPI PFNGLUNIFORMMATRIX4FVPROC glad_glUniformMatrix4fv;
-#define glUniformMatrix4fv glad_glUniformMatrix4fv
-typedef void (APIENTRYP PFNGLVALIDATEPROGRAMPROC)(GLuint program);
-GLAPI PFNGLVALIDATEPROGRAMPROC glad_glValidateProgram;
-#define glValidateProgram glad_glValidateProgram
-typedef void (APIENTRYP PFNGLVERTEXATTRIB1DPROC)(GLuint index, GLdouble x);
-GLAPI PFNGLVERTEXATTRIB1DPROC glad_glVertexAttrib1d;
-#define glVertexAttrib1d glad_glVertexAttrib1d
-typedef void (APIENTRYP PFNGLVERTEXATTRIB1DVPROC)(GLuint index, const GLdouble *v);
-GLAPI PFNGLVERTEXATTRIB1DVPROC glad_glVertexAttrib1dv;
-#define glVertexAttrib1dv glad_glVertexAttrib1dv
-typedef void (APIENTRYP PFNGLVERTEXATTRIB1FPROC)(GLuint index, GLfloat x);
-GLAPI PFNGLVERTEXATTRIB1FPROC glad_glVertexAttrib1f;
-#define glVertexAttrib1f glad_glVertexAttrib1f
-typedef void (APIENTRYP PFNGLVERTEXATTRIB1FVPROC)(GLuint index, const GLfloat *v);
-GLAPI PFNGLVERTEXATTRIB1FVPROC glad_glVertexAttrib1fv;
-#define glVertexAttrib1fv glad_glVertexAttrib1fv
-typedef void (APIENTRYP PFNGLVERTEXATTRIB1SPROC)(GLuint index, GLshort x);
-GLAPI PFNGLVERTEXATTRIB1SPROC glad_glVertexAttrib1s;
-#define glVertexAttrib1s glad_glVertexAttrib1s
-typedef void (APIENTRYP PFNGLVERTEXATTRIB1SVPROC)(GLuint index, const GLshort *v);
-GLAPI PFNGLVERTEXATTRIB1SVPROC glad_glVertexAttrib1sv;
-#define glVertexAttrib1sv glad_glVertexAttrib1sv
-typedef void (APIENTRYP PFNGLVERTEXATTRIB2DPROC)(GLuint index, GLdouble x, GLdouble y);
-GLAPI PFNGLVERTEXATTRIB2DPROC glad_glVertexAttrib2d;
-#define glVertexAttrib2d glad_glVertexAttrib2d
-typedef void (APIENTRYP PFNGLVERTEXATTRIB2DVPROC)(GLuint index, const GLdouble *v);
-GLAPI PFNGLVERTEXATTRIB2DVPROC glad_glVertexAttrib2dv;
-#define glVertexAttrib2dv glad_glVertexAttrib2dv
-typedef void (APIENTRYP PFNGLVERTEXATTRIB2FPROC)(GLuint index, GLfloat x, GLfloat y);
-GLAPI PFNGLVERTEXATTRIB2FPROC glad_glVertexAttrib2f;
-#define glVertexAttrib2f glad_glVertexAttrib2f
-typedef void (APIENTRYP PFNGLVERTEXATTRIB2FVPROC)(GLuint index, const GLfloat *v);
-GLAPI PFNGLVERTEXATTRIB2FVPROC glad_glVertexAttrib2fv;
-#define glVertexAttrib2fv glad_glVertexAttrib2fv
-typedef void (APIENTRYP PFNGLVERTEXATTRIB2SPROC)(GLuint index, GLshort x, GLshort y);
-GLAPI PFNGLVERTEXATTRIB2SPROC glad_glVertexAttrib2s;
-#define glVertexAttrib2s glad_glVertexAttrib2s
-typedef void (APIENTRYP PFNGLVERTEXATTRIB2SVPROC)(GLuint index, const GLshort *v);
-GLAPI PFNGLVERTEXATTRIB2SVPROC glad_glVertexAttrib2sv;
-#define glVertexAttrib2sv glad_glVertexAttrib2sv
-typedef void (APIENTRYP PFNGLVERTEXATTRIB3DPROC)(GLuint index, GLdouble x, GLdouble y, GLdouble z);
-GLAPI PFNGLVERTEXATTRIB3DPROC glad_glVertexAttrib3d;
-#define glVertexAttrib3d glad_glVertexAttrib3d
-typedef void (APIENTRYP PFNGLVERTEXATTRIB3DVPROC)(GLuint index, const GLdouble *v);
-GLAPI PFNGLVERTEXATTRIB3DVPROC glad_glVertexAttrib3dv;
-#define glVertexAttrib3dv glad_glVertexAttrib3dv
-typedef void (APIENTRYP PFNGLVERTEXATTRIB3FPROC)(GLuint index, GLfloat x, GLfloat y, GLfloat z);
-GLAPI PFNGLVERTEXATTRIB3FPROC glad_glVertexAttrib3f;
-#define glVertexAttrib3f glad_glVertexAttrib3f
-typedef void (APIENTRYP PFNGLVERTEXATTRIB3FVPROC)(GLuint index, const GLfloat *v);
-GLAPI PFNGLVERTEXATTRIB3FVPROC glad_glVertexAttrib3fv;
-#define glVertexAttrib3fv glad_glVertexAttrib3fv
-typedef void (APIENTRYP PFNGLVERTEXATTRIB3SPROC)(GLuint index, GLshort x, GLshort y, GLshort z);
-GLAPI PFNGLVERTEXATTRIB3SPROC glad_glVertexAttrib3s;
-#define glVertexAttrib3s glad_glVertexAttrib3s
-typedef void (APIENTRYP PFNGLVERTEXATTRIB3SVPROC)(GLuint index, const GLshort *v);
-GLAPI PFNGLVERTEXATTRIB3SVPROC glad_glVertexAttrib3sv;
-#define glVertexAttrib3sv glad_glVertexAttrib3sv
-typedef void (APIENTRYP PFNGLVERTEXATTRIB4NBVPROC)(GLuint index, const GLbyte *v);
-GLAPI PFNGLVERTEXATTRIB4NBVPROC glad_glVertexAttrib4Nbv;
-#define glVertexAttrib4Nbv glad_glVertexAttrib4Nbv
-typedef void (APIENTRYP PFNGLVERTEXATTRIB4NIVPROC)(GLuint index, const GLint *v);
-GLAPI PFNGLVERTEXATTRIB4NIVPROC glad_glVertexAttrib4Niv;
-#define glVertexAttrib4Niv glad_glVertexAttrib4Niv
-typedef void (APIENTRYP PFNGLVERTEXATTRIB4NSVPROC)(GLuint index, const GLshort *v);
-GLAPI PFNGLVERTEXATTRIB4NSVPROC glad_glVertexAttrib4Nsv;
-#define glVertexAttrib4Nsv glad_glVertexAttrib4Nsv
-typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUBPROC)(GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w);
-GLAPI PFNGLVERTEXATTRIB4NUBPROC glad_glVertexAttrib4Nub;
-#define glVertexAttrib4Nub glad_glVertexAttrib4Nub
-typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUBVPROC)(GLuint index, const GLubyte *v);
-GLAPI PFNGLVERTEXATTRIB4NUBVPROC glad_glVertexAttrib4Nubv;
-#define glVertexAttrib4Nubv glad_glVertexAttrib4Nubv
-typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUIVPROC)(GLuint index, const GLuint *v);
-GLAPI PFNGLVERTEXATTRIB4NUIVPROC glad_glVertexAttrib4Nuiv;
-#define glVertexAttrib4Nuiv glad_glVertexAttrib4Nuiv
-typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUSVPROC)(GLuint index, const GLushort *v);
-GLAPI PFNGLVERTEXATTRIB4NUSVPROC glad_glVertexAttrib4Nusv;
-#define glVertexAttrib4Nusv glad_glVertexAttrib4Nusv
-typedef void (APIENTRYP PFNGLVERTEXATTRIB4BVPROC)(GLuint index, const GLbyte *v);
-GLAPI PFNGLVERTEXATTRIB4BVPROC glad_glVertexAttrib4bv;
-#define glVertexAttrib4bv glad_glVertexAttrib4bv
-typedef void (APIENTRYP PFNGLVERTEXATTRIB4DPROC)(GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
-GLAPI PFNGLVERTEXATTRIB4DPROC glad_glVertexAttrib4d;
-#define glVertexAttrib4d glad_glVertexAttrib4d
-typedef void (APIENTRYP PFNGLVERTEXATTRIB4DVPROC)(GLuint index, const GLdouble *v);
-GLAPI PFNGLVERTEXATTRIB4DVPROC glad_glVertexAttrib4dv;
-#define glVertexAttrib4dv glad_glVertexAttrib4dv
-typedef void (APIENTRYP PFNGLVERTEXATTRIB4FPROC)(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
-GLAPI PFNGLVERTEXATTRIB4FPROC glad_glVertexAttrib4f;
-#define glVertexAttrib4f glad_glVertexAttrib4f
-typedef void (APIENTRYP PFNGLVERTEXATTRIB4FVPROC)(GLuint index, const GLfloat *v);
-GLAPI PFNGLVERTEXATTRIB4FVPROC glad_glVertexAttrib4fv;
-#define glVertexAttrib4fv glad_glVertexAttrib4fv
-typedef void (APIENTRYP PFNGLVERTEXATTRIB4IVPROC)(GLuint index, const GLint *v);
-GLAPI PFNGLVERTEXATTRIB4IVPROC glad_glVertexAttrib4iv;
-#define glVertexAttrib4iv glad_glVertexAttrib4iv
-typedef void (APIENTRYP PFNGLVERTEXATTRIB4SPROC)(GLuint index, GLshort x, GLshort y, GLshort z, GLshort w);
-GLAPI PFNGLVERTEXATTRIB4SPROC glad_glVertexAttrib4s;
-#define glVertexAttrib4s glad_glVertexAttrib4s
-typedef void (APIENTRYP PFNGLVERTEXATTRIB4SVPROC)(GLuint index, const GLshort *v);
-GLAPI PFNGLVERTEXATTRIB4SVPROC glad_glVertexAttrib4sv;
-#define glVertexAttrib4sv glad_glVertexAttrib4sv
-typedef void (APIENTRYP PFNGLVERTEXATTRIB4UBVPROC)(GLuint index, const GLubyte *v);
-GLAPI PFNGLVERTEXATTRIB4UBVPROC glad_glVertexAttrib4ubv;
-#define glVertexAttrib4ubv glad_glVertexAttrib4ubv
-typedef void (APIENTRYP PFNGLVERTEXATTRIB4UIVPROC)(GLuint index, const GLuint *v);
-GLAPI PFNGLVERTEXATTRIB4UIVPROC glad_glVertexAttrib4uiv;
-#define glVertexAttrib4uiv glad_glVertexAttrib4uiv
-typedef void (APIENTRYP PFNGLVERTEXATTRIB4USVPROC)(GLuint index, const GLushort *v);
-GLAPI PFNGLVERTEXATTRIB4USVPROC glad_glVertexAttrib4usv;
-#define glVertexAttrib4usv glad_glVertexAttrib4usv
-typedef void (APIENTRYP PFNGLVERTEXATTRIBPOINTERPROC)(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer);
-GLAPI PFNGLVERTEXATTRIBPOINTERPROC glad_glVertexAttribPointer;
-#define glVertexAttribPointer glad_glVertexAttribPointer
-#endif
-#ifndef GL_VERSION_2_1
-#define GL_VERSION_2_1 1
-GLAPI int GLAD_GL_VERSION_2_1;
-typedef void (APIENTRYP PFNGLUNIFORMMATRIX2X3FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
-GLAPI PFNGLUNIFORMMATRIX2X3FVPROC glad_glUniformMatrix2x3fv;
-#define glUniformMatrix2x3fv glad_glUniformMatrix2x3fv
-typedef void (APIENTRYP PFNGLUNIFORMMATRIX3X2FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
-GLAPI PFNGLUNIFORMMATRIX3X2FVPROC glad_glUniformMatrix3x2fv;
-#define glUniformMatrix3x2fv glad_glUniformMatrix3x2fv
-typedef void (APIENTRYP PFNGLUNIFORMMATRIX2X4FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
-GLAPI PFNGLUNIFORMMATRIX2X4FVPROC glad_glUniformMatrix2x4fv;
-#define glUniformMatrix2x4fv glad_glUniformMatrix2x4fv
-typedef void (APIENTRYP PFNGLUNIFORMMATRIX4X2FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
-GLAPI PFNGLUNIFORMMATRIX4X2FVPROC glad_glUniformMatrix4x2fv;
-#define glUniformMatrix4x2fv glad_glUniformMatrix4x2fv
-typedef void (APIENTRYP PFNGLUNIFORMMATRIX3X4FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
-GLAPI PFNGLUNIFORMMATRIX3X4FVPROC glad_glUniformMatrix3x4fv;
-#define glUniformMatrix3x4fv glad_glUniformMatrix3x4fv
-typedef void (APIENTRYP PFNGLUNIFORMMATRIX4X3FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
-GLAPI PFNGLUNIFORMMATRIX4X3FVPROC glad_glUniformMatrix4x3fv;
-#define glUniformMatrix4x3fv glad_glUniformMatrix4x3fv
-#endif
-#ifndef GL_VERSION_3_0
-#define GL_VERSION_3_0 1
-GLAPI int GLAD_GL_VERSION_3_0;
-typedef void (APIENTRYP PFNGLCOLORMASKIPROC)(GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a);
-GLAPI PFNGLCOLORMASKIPROC glad_glColorMaski;
-#define glColorMaski glad_glColorMaski
-typedef void (APIENTRYP PFNGLGETBOOLEANI_VPROC)(GLenum target, GLuint index, GLboolean *data);
-GLAPI PFNGLGETBOOLEANI_VPROC glad_glGetBooleani_v;
-#define glGetBooleani_v glad_glGetBooleani_v
-typedef void (APIENTRYP PFNGLGETINTEGERI_VPROC)(GLenum target, GLuint index, GLint *data);
-GLAPI PFNGLGETINTEGERI_VPROC glad_glGetIntegeri_v;
-#define glGetIntegeri_v glad_glGetIntegeri_v
-typedef void (APIENTRYP PFNGLENABLEIPROC)(GLenum target, GLuint index);
-GLAPI PFNGLENABLEIPROC glad_glEnablei;
-#define glEnablei glad_glEnablei
-typedef void (APIENTRYP PFNGLDISABLEIPROC)(GLenum target, GLuint index);
-GLAPI PFNGLDISABLEIPROC glad_glDisablei;
-#define glDisablei glad_glDisablei
-typedef GLboolean (APIENTRYP PFNGLISENABLEDIPROC)(GLenum target, GLuint index);
-GLAPI PFNGLISENABLEDIPROC glad_glIsEnabledi;
-#define glIsEnabledi glad_glIsEnabledi
-typedef void (APIENTRYP PFNGLBEGINTRANSFORMFEEDBACKPROC)(GLenum primitiveMode);
-GLAPI PFNGLBEGINTRANSFORMFEEDBACKPROC glad_glBeginTransformFeedback;
-#define glBeginTransformFeedback glad_glBeginTransformFeedback
-typedef void (APIENTRYP PFNGLENDTRANSFORMFEEDBACKPROC)(void);
-GLAPI PFNGLENDTRANSFORMFEEDBACKPROC glad_glEndTransformFeedback;
-#define glEndTransformFeedback glad_glEndTransformFeedback
-typedef void (APIENTRYP PFNGLBINDBUFFERRANGEPROC)(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
-GLAPI PFNGLBINDBUFFERRANGEPROC glad_glBindBufferRange;
-#define glBindBufferRange glad_glBindBufferRange
-typedef void (APIENTRYP PFNGLBINDBUFFERBASEPROC)(GLenum target, GLuint index, GLuint buffer);
-GLAPI PFNGLBINDBUFFERBASEPROC glad_glBindBufferBase;
-#define glBindBufferBase glad_glBindBufferBase
-typedef void (APIENTRYP PFNGLTRANSFORMFEEDBACKVARYINGSPROC)(GLuint program, GLsizei count, const GLchar *const*varyings, GLenum bufferMode);
-GLAPI PFNGLTRANSFORMFEEDBACKVARYINGSPROC glad_glTransformFeedbackVaryings;
-#define glTransformFeedbackVaryings glad_glTransformFeedbackVaryings
-typedef void (APIENTRYP PFNGLGETTRANSFORMFEEDBACKVARYINGPROC)(GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name);
-GLAPI PFNGLGETTRANSFORMFEEDBACKVARYINGPROC glad_glGetTransformFeedbackVarying;
-#define glGetTransformFeedbackVarying glad_glGetTransformFeedbackVarying
-typedef void (APIENTRYP PFNGLCLAMPCOLORPROC)(GLenum target, GLenum clamp);
-GLAPI PFNGLCLAMPCOLORPROC glad_glClampColor;
-#define glClampColor glad_glClampColor
-typedef void (APIENTRYP PFNGLBEGINCONDITIONALRENDERPROC)(GLuint id, GLenum mode);
-GLAPI PFNGLBEGINCONDITIONALRENDERPROC glad_glBeginConditionalRender;
-#define glBeginConditionalRender glad_glBeginConditionalRender
-typedef void (APIENTRYP PFNGLENDCONDITIONALRENDERPROC)(void);
-GLAPI PFNGLENDCONDITIONALRENDERPROC glad_glEndConditionalRender;
-#define glEndConditionalRender glad_glEndConditionalRender
-typedef void (APIENTRYP PFNGLVERTEXATTRIBIPOINTERPROC)(GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer);
-GLAPI PFNGLVERTEXATTRIBIPOINTERPROC glad_glVertexAttribIPointer;
-#define glVertexAttribIPointer glad_glVertexAttribIPointer
-typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIIVPROC)(GLuint index, GLenum pname, GLint *params);
-GLAPI PFNGLGETVERTEXATTRIBIIVPROC glad_glGetVertexAttribIiv;
-#define glGetVertexAttribIiv glad_glGetVertexAttribIiv
-typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIUIVPROC)(GLuint index, GLenum pname, GLuint *params);
-GLAPI PFNGLGETVERTEXATTRIBIUIVPROC glad_glGetVertexAttribIuiv;
-#define glGetVertexAttribIuiv glad_glGetVertexAttribIuiv
-typedef void (APIENTRYP PFNGLVERTEXATTRIBI1IPROC)(GLuint index, GLint x);
-GLAPI PFNGLVERTEXATTRIBI1IPROC glad_glVertexAttribI1i;
-#define glVertexAttribI1i glad_glVertexAttribI1i
-typedef void (APIENTRYP PFNGLVERTEXATTRIBI2IPROC)(GLuint index, GLint x, GLint y);
-GLAPI PFNGLVERTEXATTRIBI2IPROC glad_glVertexAttribI2i;
-#define glVertexAttribI2i glad_glVertexAttribI2i
-typedef void (APIENTRYP PFNGLVERTEXATTRIBI3IPROC)(GLuint index, GLint x, GLint y, GLint z);
-GLAPI PFNGLVERTEXATTRIBI3IPROC glad_glVertexAttribI3i;
-#define glVertexAttribI3i glad_glVertexAttribI3i
-typedef void (APIENTRYP PFNGLVERTEXATTRIBI4IPROC)(GLuint index, GLint x, GLint y, GLint z, GLint w);
-GLAPI PFNGLVERTEXATTRIBI4IPROC glad_glVertexAttribI4i;
-#define glVertexAttribI4i glad_glVertexAttribI4i
-typedef void (APIENTRYP PFNGLVERTEXATTRIBI1UIPROC)(GLuint index, GLuint x);
-GLAPI PFNGLVERTEXATTRIBI1UIPROC glad_glVertexAttribI1ui;
-#define glVertexAttribI1ui glad_glVertexAttribI1ui
-typedef void (APIENTRYP PFNGLVERTEXATTRIBI2UIPROC)(GLuint index, GLuint x, GLuint y);
-GLAPI PFNGLVERTEXATTRIBI2UIPROC glad_glVertexAttribI2ui;
-#define glVertexAttribI2ui glad_glVertexAttribI2ui
-typedef void (APIENTRYP PFNGLVERTEXATTRIBI3UIPROC)(GLuint index, GLuint x, GLuint y, GLuint z);
-GLAPI PFNGLVERTEXATTRIBI3UIPROC glad_glVertexAttribI3ui;
-#define glVertexAttribI3ui glad_glVertexAttribI3ui
-typedef void (APIENTRYP PFNGLVERTEXATTRIBI4UIPROC)(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
-GLAPI PFNGLVERTEXATTRIBI4UIPROC glad_glVertexAttribI4ui;
-#define glVertexAttribI4ui glad_glVertexAttribI4ui
-typedef void (APIENTRYP PFNGLVERTEXATTRIBI1IVPROC)(GLuint index, const GLint *v);
-GLAPI PFNGLVERTEXATTRIBI1IVPROC glad_glVertexAttribI1iv;
-#define glVertexAttribI1iv glad_glVertexAttribI1iv
-typedef void (APIENTRYP PFNGLVERTEXATTRIBI2IVPROC)(GLuint index, const GLint *v);
-GLAPI PFNGLVERTEXATTRIBI2IVPROC glad_glVertexAttribI2iv;
-#define glVertexAttribI2iv glad_glVertexAttribI2iv
-typedef void (APIENTRYP PFNGLVERTEXATTRIBI3IVPROC)(GLuint index, const GLint *v);
-GLAPI PFNGLVERTEXATTRIBI3IVPROC glad_glVertexAttribI3iv;
-#define glVertexAttribI3iv glad_glVertexAttribI3iv
-typedef void (APIENTRYP PFNGLVERTEXATTRIBI4IVPROC)(GLuint index, const GLint *v);
-GLAPI PFNGLVERTEXATTRIBI4IVPROC glad_glVertexAttribI4iv;
-#define glVertexAttribI4iv glad_glVertexAttribI4iv
-typedef void (APIENTRYP PFNGLVERTEXATTRIBI1UIVPROC)(GLuint index, const GLuint *v);
-GLAPI PFNGLVERTEXATTRIBI1UIVPROC glad_glVertexAttribI1uiv;
-#define glVertexAttribI1uiv glad_glVertexAttribI1uiv
-typedef void (APIENTRYP PFNGLVERTEXATTRIBI2UIVPROC)(GLuint index, const GLuint *v);
-GLAPI PFNGLVERTEXATTRIBI2UIVPROC glad_glVertexAttribI2uiv;
-#define glVertexAttribI2uiv glad_glVertexAttribI2uiv
-typedef void (APIENTRYP PFNGLVERTEXATTRIBI3UIVPROC)(GLuint index, const GLuint *v);
-GLAPI PFNGLVERTEXATTRIBI3UIVPROC glad_glVertexAttribI3uiv;
-#define glVertexAttribI3uiv glad_glVertexAttribI3uiv
-typedef void (APIENTRYP PFNGLVERTEXATTRIBI4UIVPROC)(GLuint index, const GLuint *v);
-GLAPI PFNGLVERTEXATTRIBI4UIVPROC glad_glVertexAttribI4uiv;
-#define glVertexAttribI4uiv glad_glVertexAttribI4uiv
-typedef void (APIENTRYP PFNGLVERTEXATTRIBI4BVPROC)(GLuint index, const GLbyte *v);
-GLAPI PFNGLVERTEXATTRIBI4BVPROC glad_glVertexAttribI4bv;
-#define glVertexAttribI4bv glad_glVertexAttribI4bv
-typedef void (APIENTRYP PFNGLVERTEXATTRIBI4SVPROC)(GLuint index, const GLshort *v);
-GLAPI PFNGLVERTEXATTRIBI4SVPROC glad_glVertexAttribI4sv;
-#define glVertexAttribI4sv glad_glVertexAttribI4sv
-typedef void (APIENTRYP PFNGLVERTEXATTRIBI4UBVPROC)(GLuint index, const GLubyte *v);
-GLAPI PFNGLVERTEXATTRIBI4UBVPROC glad_glVertexAttribI4ubv;
-#define glVertexAttribI4ubv glad_glVertexAttribI4ubv
-typedef void (APIENTRYP PFNGLVERTEXATTRIBI4USVPROC)(GLuint index, const GLushort *v);
-GLAPI PFNGLVERTEXATTRIBI4USVPROC glad_glVertexAttribI4usv;
-#define glVertexAttribI4usv glad_glVertexAttribI4usv
-typedef void (APIENTRYP PFNGLGETUNIFORMUIVPROC)(GLuint program, GLint location, GLuint *params);
-GLAPI PFNGLGETUNIFORMUIVPROC glad_glGetUniformuiv;
-#define glGetUniformuiv glad_glGetUniformuiv
-typedef void (APIENTRYP PFNGLBINDFRAGDATALOCATIONPROC)(GLuint program, GLuint color, const GLchar *name);
-GLAPI PFNGLBINDFRAGDATALOCATIONPROC glad_glBindFragDataLocation;
-#define glBindFragDataLocation glad_glBindFragDataLocation
-typedef GLint (APIENTRYP PFNGLGETFRAGDATALOCATIONPROC)(GLuint program, const GLchar *name);
-GLAPI PFNGLGETFRAGDATALOCATIONPROC glad_glGetFragDataLocation;
-#define glGetFragDataLocation glad_glGetFragDataLocation
-typedef void (APIENTRYP PFNGLUNIFORM1UIPROC)(GLint location, GLuint v0);
-GLAPI PFNGLUNIFORM1UIPROC glad_glUniform1ui;
-#define glUniform1ui glad_glUniform1ui
-typedef void (APIENTRYP PFNGLUNIFORM2UIPROC)(GLint location, GLuint v0, GLuint v1);
-GLAPI PFNGLUNIFORM2UIPROC glad_glUniform2ui;
-#define glUniform2ui glad_glUniform2ui
-typedef void (APIENTRYP PFNGLUNIFORM3UIPROC)(GLint location, GLuint v0, GLuint v1, GLuint v2);
-GLAPI PFNGLUNIFORM3UIPROC glad_glUniform3ui;
-#define glUniform3ui glad_glUniform3ui
-typedef void (APIENTRYP PFNGLUNIFORM4UIPROC)(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
-GLAPI PFNGLUNIFORM4UIPROC glad_glUniform4ui;
-#define glUniform4ui glad_glUniform4ui
-typedef void (APIENTRYP PFNGLUNIFORM1UIVPROC)(GLint location, GLsizei count, const GLuint *value);
-GLAPI PFNGLUNIFORM1UIVPROC glad_glUniform1uiv;
-#define glUniform1uiv glad_glUniform1uiv
-typedef void (APIENTRYP PFNGLUNIFORM2UIVPROC)(GLint location, GLsizei count, const GLuint *value);
-GLAPI PFNGLUNIFORM2UIVPROC glad_glUniform2uiv;
-#define glUniform2uiv glad_glUniform2uiv
-typedef void (APIENTRYP PFNGLUNIFORM3UIVPROC)(GLint location, GLsizei count, const GLuint *value);
-GLAPI PFNGLUNIFORM3UIVPROC glad_glUniform3uiv;
-#define glUniform3uiv glad_glUniform3uiv
-typedef void (APIENTRYP PFNGLUNIFORM4UIVPROC)(GLint location, GLsizei count, const GLuint *value);
-GLAPI PFNGLUNIFORM4UIVPROC glad_glUniform4uiv;
-#define glUniform4uiv glad_glUniform4uiv
-typedef void (APIENTRYP PFNGLTEXPARAMETERIIVPROC)(GLenum target, GLenum pname, const GLint *params);
-GLAPI PFNGLTEXPARAMETERIIVPROC glad_glTexParameterIiv;
-#define glTexParameterIiv glad_glTexParameterIiv
-typedef void (APIENTRYP PFNGLTEXPARAMETERIUIVPROC)(GLenum target, GLenum pname, const GLuint *params);
-GLAPI PFNGLTEXPARAMETERIUIVPROC glad_glTexParameterIuiv;
-#define glTexParameterIuiv glad_glTexParameterIuiv
-typedef void (APIENTRYP PFNGLGETTEXPARAMETERIIVPROC)(GLenum target, GLenum pname, GLint *params);
-GLAPI PFNGLGETTEXPARAMETERIIVPROC glad_glGetTexParameterIiv;
-#define glGetTexParameterIiv glad_glGetTexParameterIiv
-typedef void (APIENTRYP PFNGLGETTEXPARAMETERIUIVPROC)(GLenum target, GLenum pname, GLuint *params);
-GLAPI PFNGLGETTEXPARAMETERIUIVPROC glad_glGetTexParameterIuiv;
-#define glGetTexParameterIuiv glad_glGetTexParameterIuiv
-typedef void (APIENTRYP PFNGLCLEARBUFFERIVPROC)(GLenum buffer, GLint drawbuffer, const GLint *value);
-GLAPI PFNGLCLEARBUFFERIVPROC glad_glClearBufferiv;
-#define glClearBufferiv glad_glClearBufferiv
-typedef void (APIENTRYP PFNGLCLEARBUFFERUIVPROC)(GLenum buffer, GLint drawbuffer, const GLuint *value);
-GLAPI PFNGLCLEARBUFFERUIVPROC glad_glClearBufferuiv;
-#define glClearBufferuiv glad_glClearBufferuiv
-typedef void (APIENTRYP PFNGLCLEARBUFFERFVPROC)(GLenum buffer, GLint drawbuffer, const GLfloat *value);
-GLAPI PFNGLCLEARBUFFERFVPROC glad_glClearBufferfv;
-#define glClearBufferfv glad_glClearBufferfv
-typedef void (APIENTRYP PFNGLCLEARBUFFERFIPROC)(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil);
-GLAPI PFNGLCLEARBUFFERFIPROC glad_glClearBufferfi;
-#define glClearBufferfi glad_glClearBufferfi
-typedef const GLubyte * (APIENTRYP PFNGLGETSTRINGIPROC)(GLenum name, GLuint index);
-GLAPI PFNGLGETSTRINGIPROC glad_glGetStringi;
-#define glGetStringi glad_glGetStringi
-typedef GLboolean (APIENTRYP PFNGLISRENDERBUFFERPROC)(GLuint renderbuffer);
-GLAPI PFNGLISRENDERBUFFERPROC glad_glIsRenderbuffer;
-#define glIsRenderbuffer glad_glIsRenderbuffer
-typedef void (APIENTRYP PFNGLBINDRENDERBUFFERPROC)(GLenum target, GLuint renderbuffer);
-GLAPI PFNGLBINDRENDERBUFFERPROC glad_glBindRenderbuffer;
-#define glBindRenderbuffer glad_glBindRenderbuffer
-typedef void (APIENTRYP PFNGLDELETERENDERBUFFERSPROC)(GLsizei n, const GLuint *renderbuffers);
-GLAPI PFNGLDELETERENDERBUFFERSPROC glad_glDeleteRenderbuffers;
-#define glDeleteRenderbuffers glad_glDeleteRenderbuffers
-typedef void (APIENTRYP PFNGLGENRENDERBUFFERSPROC)(GLsizei n, GLuint *renderbuffers);
-GLAPI PFNGLGENRENDERBUFFERSPROC glad_glGenRenderbuffers;
-#define glGenRenderbuffers glad_glGenRenderbuffers
-typedef void (APIENTRYP PFNGLRENDERBUFFERSTORAGEPROC)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
-GLAPI PFNGLRENDERBUFFERSTORAGEPROC glad_glRenderbufferStorage;
-#define glRenderbufferStorage glad_glRenderbufferStorage
-typedef void (APIENTRYP PFNGLGETRENDERBUFFERPARAMETERIVPROC)(GLenum target, GLenum pname, GLint *params);
-GLAPI PFNGLGETRENDERBUFFERPARAMETERIVPROC glad_glGetRenderbufferParameteriv;
-#define glGetRenderbufferParameteriv glad_glGetRenderbufferParameteriv
-typedef GLboolean (APIENTRYP PFNGLISFRAMEBUFFERPROC)(GLuint framebuffer);
-GLAPI PFNGLISFRAMEBUFFERPROC glad_glIsFramebuffer;
-#define glIsFramebuffer glad_glIsFramebuffer
-typedef void (APIENTRYP PFNGLBINDFRAMEBUFFERPROC)(GLenum target, GLuint framebuffer);
-GLAPI PFNGLBINDFRAMEBUFFERPROC glad_glBindFramebuffer;
-#define glBindFramebuffer glad_glBindFramebuffer
-typedef void (APIENTRYP PFNGLDELETEFRAMEBUFFERSPROC)(GLsizei n, const GLuint *framebuffers);
-GLAPI PFNGLDELETEFRAMEBUFFERSPROC glad_glDeleteFramebuffers;
-#define glDeleteFramebuffers glad_glDeleteFramebuffers
-typedef void (APIENTRYP PFNGLGENFRAMEBUFFERSPROC)(GLsizei n, GLuint *framebuffers);
-GLAPI PFNGLGENFRAMEBUFFERSPROC glad_glGenFramebuffers;
-#define glGenFramebuffers glad_glGenFramebuffers
-typedef GLenum (APIENTRYP PFNGLCHECKFRAMEBUFFERSTATUSPROC)(GLenum target);
-GLAPI PFNGLCHECKFRAMEBUFFERSTATUSPROC glad_glCheckFramebufferStatus;
-#define glCheckFramebufferStatus glad_glCheckFramebufferStatus
-typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE1DPROC)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
-GLAPI PFNGLFRAMEBUFFERTEXTURE1DPROC glad_glFramebufferTexture1D;
-#define glFramebufferTexture1D glad_glFramebufferTexture1D
-typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DPROC)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
-GLAPI PFNGLFRAMEBUFFERTEXTURE2DPROC glad_glFramebufferTexture2D;
-#define glFramebufferTexture2D glad_glFramebufferTexture2D
-typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE3DPROC)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
-GLAPI PFNGLFRAMEBUFFERTEXTURE3DPROC glad_glFramebufferTexture3D;
-#define glFramebufferTexture3D glad_glFramebufferTexture3D
-typedef void (APIENTRYP PFNGLFRAMEBUFFERRENDERBUFFERPROC)(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
-GLAPI PFNGLFRAMEBUFFERRENDERBUFFERPROC glad_glFramebufferRenderbuffer;
-#define glFramebufferRenderbuffer glad_glFramebufferRenderbuffer
-typedef void (APIENTRYP PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC)(GLenum target, GLenum attachment, GLenum pname, GLint *params);
-GLAPI PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC glad_glGetFramebufferAttachmentParameteriv;
-#define glGetFramebufferAttachmentParameteriv glad_glGetFramebufferAttachmentParameteriv
-typedef void (APIENTRYP PFNGLGENERATEMIPMAPPROC)(GLenum target);
-GLAPI PFNGLGENERATEMIPMAPPROC glad_glGenerateMipmap;
-#define glGenerateMipmap glad_glGenerateMipmap
-typedef void (APIENTRYP PFNGLBLITFRAMEBUFFERPROC)(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
-GLAPI PFNGLBLITFRAMEBUFFERPROC glad_glBlitFramebuffer;
-#define glBlitFramebuffer glad_glBlitFramebuffer
-typedef void (APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
-GLAPI PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC glad_glRenderbufferStorageMultisample;
-#define glRenderbufferStorageMultisample glad_glRenderbufferStorageMultisample
-typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURELAYERPROC)(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
-GLAPI PFNGLFRAMEBUFFERTEXTURELAYERPROC glad_glFramebufferTextureLayer;
-#define glFramebufferTextureLayer glad_glFramebufferTextureLayer
-typedef void * (APIENTRYP PFNGLMAPBUFFERRANGEPROC)(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
-GLAPI PFNGLMAPBUFFERRANGEPROC glad_glMapBufferRange;
-#define glMapBufferRange glad_glMapBufferRange
-typedef void (APIENTRYP PFNGLFLUSHMAPPEDBUFFERRANGEPROC)(GLenum target, GLintptr offset, GLsizeiptr length);
-GLAPI PFNGLFLUSHMAPPEDBUFFERRANGEPROC glad_glFlushMappedBufferRange;
-#define glFlushMappedBufferRange glad_glFlushMappedBufferRange
-typedef void (APIENTRYP PFNGLBINDVERTEXARRAYPROC)(GLuint array);
-GLAPI PFNGLBINDVERTEXARRAYPROC glad_glBindVertexArray;
-#define glBindVertexArray glad_glBindVertexArray
-typedef void (APIENTRYP PFNGLDELETEVERTEXARRAYSPROC)(GLsizei n, const GLuint *arrays);
-GLAPI PFNGLDELETEVERTEXARRAYSPROC glad_glDeleteVertexArrays;
-#define glDeleteVertexArrays glad_glDeleteVertexArrays
-typedef void (APIENTRYP PFNGLGENVERTEXARRAYSPROC)(GLsizei n, GLuint *arrays);
-GLAPI PFNGLGENVERTEXARRAYSPROC glad_glGenVertexArrays;
-#define glGenVertexArrays glad_glGenVertexArrays
-typedef GLboolean (APIENTRYP PFNGLISVERTEXARRAYPROC)(GLuint array);
-GLAPI PFNGLISVERTEXARRAYPROC glad_glIsVertexArray;
-#define glIsVertexArray glad_glIsVertexArray
-#endif
-#ifndef GL_VERSION_3_1
-#define GL_VERSION_3_1 1
-GLAPI int GLAD_GL_VERSION_3_1;
-typedef void (APIENTRYP PFNGLDRAWARRAYSINSTANCEDPROC)(GLenum mode, GLint first, GLsizei count, GLsizei instancecount);
-GLAPI PFNGLDRAWARRAYSINSTANCEDPROC glad_glDrawArraysInstanced;
-#define glDrawArraysInstanced glad_glDrawArraysInstanced
-typedef void (APIENTRYP PFNGLDRAWELEMENTSINSTANCEDPROC)(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount);
-GLAPI PFNGLDRAWELEMENTSINSTANCEDPROC glad_glDrawElementsInstanced;
-#define glDrawElementsInstanced glad_glDrawElementsInstanced
-typedef void (APIENTRYP PFNGLTEXBUFFERPROC)(GLenum target, GLenum internalformat, GLuint buffer);
-GLAPI PFNGLTEXBUFFERPROC glad_glTexBuffer;
-#define glTexBuffer glad_glTexBuffer
-typedef void (APIENTRYP PFNGLPRIMITIVERESTARTINDEXPROC)(GLuint index);
-GLAPI PFNGLPRIMITIVERESTARTINDEXPROC glad_glPrimitiveRestartIndex;
-#define glPrimitiveRestartIndex glad_glPrimitiveRestartIndex
-typedef void (APIENTRYP PFNGLCOPYBUFFERSUBDATAPROC)(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
-GLAPI PFNGLCOPYBUFFERSUBDATAPROC glad_glCopyBufferSubData;
-#define glCopyBufferSubData glad_glCopyBufferSubData
-typedef void (APIENTRYP PFNGLGETUNIFORMINDICESPROC)(GLuint program, GLsizei uniformCount, const GLchar *const*uniformNames, GLuint *uniformIndices);
-GLAPI PFNGLGETUNIFORMINDICESPROC glad_glGetUniformIndices;
-#define glGetUniformIndices glad_glGetUniformIndices
-typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMSIVPROC)(GLuint program, GLsizei uniformCount, const GLuint *uniformIndices, GLenum pname, GLint *params);
-GLAPI PFNGLGETACTIVEUNIFORMSIVPROC glad_glGetActiveUniformsiv;
-#define glGetActiveUniformsiv glad_glGetActiveUniformsiv
-typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMNAMEPROC)(GLuint program, GLuint uniformIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformName);
-GLAPI PFNGLGETACTIVEUNIFORMNAMEPROC glad_glGetActiveUniformName;
-#define glGetActiveUniformName glad_glGetActiveUniformName
-typedef GLuint (APIENTRYP PFNGLGETUNIFORMBLOCKINDEXPROC)(GLuint program, const GLchar *uniformBlockName);
-GLAPI PFNGLGETUNIFORMBLOCKINDEXPROC glad_glGetUniformBlockIndex;
-#define glGetUniformBlockIndex glad_glGetUniformBlockIndex
-typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMBLOCKIVPROC)(GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint *params);
-GLAPI PFNGLGETACTIVEUNIFORMBLOCKIVPROC glad_glGetActiveUniformBlockiv;
-#define glGetActiveUniformBlockiv glad_glGetActiveUniformBlockiv
-typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC)(GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName);
-GLAPI PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC glad_glGetActiveUniformBlockName;
-#define glGetActiveUniformBlockName glad_glGetActiveUniformBlockName
-typedef void (APIENTRYP PFNGLUNIFORMBLOCKBINDINGPROC)(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding);
-GLAPI PFNGLUNIFORMBLOCKBINDINGPROC glad_glUniformBlockBinding;
-#define glUniformBlockBinding glad_glUniformBlockBinding
-#endif
-#ifndef GL_VERSION_3_2
-#define GL_VERSION_3_2 1
-GLAPI int GLAD_GL_VERSION_3_2;
-typedef void (APIENTRYP PFNGLDRAWELEMENTSBASEVERTEXPROC)(GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex);
-GLAPI PFNGLDRAWELEMENTSBASEVERTEXPROC glad_glDrawElementsBaseVertex;
-#define glDrawElementsBaseVertex glad_glDrawElementsBaseVertex
-typedef void (APIENTRYP PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC)(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices, GLint basevertex);
-GLAPI PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC glad_glDrawRangeElementsBaseVertex;
-#define glDrawRangeElementsBaseVertex glad_glDrawRangeElementsBaseVertex
-typedef void (APIENTRYP PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC)(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex);
-GLAPI PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC glad_glDrawElementsInstancedBaseVertex;
-#define glDrawElementsInstancedBaseVertex glad_glDrawElementsInstancedBaseVertex
-typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC)(GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei drawcount, const GLint *basevertex);
-GLAPI PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC glad_glMultiDrawElementsBaseVertex;
-#define glMultiDrawElementsBaseVertex glad_glMultiDrawElementsBaseVertex
-typedef void (APIENTRYP PFNGLPROVOKINGVERTEXPROC)(GLenum mode);
-GLAPI PFNGLPROVOKINGVERTEXPROC glad_glProvokingVertex;
-#define glProvokingVertex glad_glProvokingVertex
-typedef GLsync (APIENTRYP PFNGLFENCESYNCPROC)(GLenum condition, GLbitfield flags);
-GLAPI PFNGLFENCESYNCPROC glad_glFenceSync;
-#define glFenceSync glad_glFenceSync
-typedef GLboolean (APIENTRYP PFNGLISSYNCPROC)(GLsync sync);
-GLAPI PFNGLISSYNCPROC glad_glIsSync;
-#define glIsSync glad_glIsSync
-typedef void (APIENTRYP PFNGLDELETESYNCPROC)(GLsync sync);
-GLAPI PFNGLDELETESYNCPROC glad_glDeleteSync;
-#define glDeleteSync glad_glDeleteSync
-typedef GLenum (APIENTRYP PFNGLCLIENTWAITSYNCPROC)(GLsync sync, GLbitfield flags, GLuint64 timeout);
-GLAPI PFNGLCLIENTWAITSYNCPROC glad_glClientWaitSync;
-#define glClientWaitSync glad_glClientWaitSync
-typedef void (APIENTRYP PFNGLWAITSYNCPROC)(GLsync sync, GLbitfield flags, GLuint64 timeout);
-GLAPI PFNGLWAITSYNCPROC glad_glWaitSync;
-#define glWaitSync glad_glWaitSync
-typedef void (APIENTRYP PFNGLGETINTEGER64VPROC)(GLenum pname, GLint64 *data);
-GLAPI PFNGLGETINTEGER64VPROC glad_glGetInteger64v;
-#define glGetInteger64v glad_glGetInteger64v
-typedef void (APIENTRYP PFNGLGETSYNCIVPROC)(GLsync sync, GLenum pname, GLsizei count, GLsizei *length, GLint *values);
-GLAPI PFNGLGETSYNCIVPROC glad_glGetSynciv;
-#define glGetSynciv glad_glGetSynciv
-typedef void (APIENTRYP PFNGLGETINTEGER64I_VPROC)(GLenum target, GLuint index, GLint64 *data);
-GLAPI PFNGLGETINTEGER64I_VPROC glad_glGetInteger64i_v;
-#define glGetInteger64i_v glad_glGetInteger64i_v
-typedef void (APIENTRYP PFNGLGETBUFFERPARAMETERI64VPROC)(GLenum target, GLenum pname, GLint64 *params);
-GLAPI PFNGLGETBUFFERPARAMETERI64VPROC glad_glGetBufferParameteri64v;
-#define glGetBufferParameteri64v glad_glGetBufferParameteri64v
-typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTUREPROC)(GLenum target, GLenum attachment, GLuint texture, GLint level);
-GLAPI PFNGLFRAMEBUFFERTEXTUREPROC glad_glFramebufferTexture;
-#define glFramebufferTexture glad_glFramebufferTexture
-typedef void (APIENTRYP PFNGLTEXIMAGE2DMULTISAMPLEPROC)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations);
-GLAPI PFNGLTEXIMAGE2DMULTISAMPLEPROC glad_glTexImage2DMultisample;
-#define glTexImage2DMultisample glad_glTexImage2DMultisample
-typedef void (APIENTRYP PFNGLTEXIMAGE3DMULTISAMPLEPROC)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations);
-GLAPI PFNGLTEXIMAGE3DMULTISAMPLEPROC glad_glTexImage3DMultisample;
-#define glTexImage3DMultisample glad_glTexImage3DMultisample
-typedef void (APIENTRYP PFNGLGETMULTISAMPLEFVPROC)(GLenum pname, GLuint index, GLfloat *val);
-GLAPI PFNGLGETMULTISAMPLEFVPROC glad_glGetMultisamplefv;
-#define glGetMultisamplefv glad_glGetMultisamplefv
-typedef void (APIENTRYP PFNGLSAMPLEMASKIPROC)(GLuint maskNumber, GLbitfield mask);
-GLAPI PFNGLSAMPLEMASKIPROC glad_glSampleMaski;
-#define glSampleMaski glad_glSampleMaski
-#endif
-#ifndef GL_VERSION_3_3
-#define GL_VERSION_3_3 1
-GLAPI int GLAD_GL_VERSION_3_3;
-typedef void (APIENTRYP PFNGLBINDFRAGDATALOCATIONINDEXEDPROC)(GLuint program, GLuint colorNumber, GLuint index, const GLchar *name);
-GLAPI PFNGLBINDFRAGDATALOCATIONINDEXEDPROC glad_glBindFragDataLocationIndexed;
-#define glBindFragDataLocationIndexed glad_glBindFragDataLocationIndexed
-typedef GLint (APIENTRYP PFNGLGETFRAGDATAINDEXPROC)(GLuint program, const GLchar *name);
-GLAPI PFNGLGETFRAGDATAINDEXPROC glad_glGetFragDataIndex;
-#define glGetFragDataIndex glad_glGetFragDataIndex
-typedef void (APIENTRYP PFNGLGENSAMPLERSPROC)(GLsizei count, GLuint *samplers);
-GLAPI PFNGLGENSAMPLERSPROC glad_glGenSamplers;
-#define glGenSamplers glad_glGenSamplers
-typedef void (APIENTRYP PFNGLDELETESAMPLERSPROC)(GLsizei count, const GLuint *samplers);
-GLAPI PFNGLDELETESAMPLERSPROC glad_glDeleteSamplers;
-#define glDeleteSamplers glad_glDeleteSamplers
-typedef GLboolean (APIENTRYP PFNGLISSAMPLERPROC)(GLuint sampler);
-GLAPI PFNGLISSAMPLERPROC glad_glIsSampler;
-#define glIsSampler glad_glIsSampler
-typedef void (APIENTRYP PFNGLBINDSAMPLERPROC)(GLuint unit, GLuint sampler);
-GLAPI PFNGLBINDSAMPLERPROC glad_glBindSampler;
-#define glBindSampler glad_glBindSampler
-typedef void (APIENTRYP PFNGLSAMPLERPARAMETERIPROC)(GLuint sampler, GLenum pname, GLint param);
-GLAPI PFNGLSAMPLERPARAMETERIPROC glad_glSamplerParameteri;
-#define glSamplerParameteri glad_glSamplerParameteri
-typedef void (APIENTRYP PFNGLSAMPLERPARAMETERIVPROC)(GLuint sampler, GLenum pname, const GLint *param);
-GLAPI PFNGLSAMPLERPARAMETERIVPROC glad_glSamplerParameteriv;
-#define glSamplerParameteriv glad_glSamplerParameteriv
-typedef void (APIENTRYP PFNGLSAMPLERPARAMETERFPROC)(GLuint sampler, GLenum pname, GLfloat param);
-GLAPI PFNGLSAMPLERPARAMETERFPROC glad_glSamplerParameterf;
-#define glSamplerParameterf glad_glSamplerParameterf
-typedef void (APIENTRYP PFNGLSAMPLERPARAMETERFVPROC)(GLuint sampler, GLenum pname, const GLfloat *param);
-GLAPI PFNGLSAMPLERPARAMETERFVPROC glad_glSamplerParameterfv;
-#define glSamplerParameterfv glad_glSamplerParameterfv
-typedef void (APIENTRYP PFNGLSAMPLERPARAMETERIIVPROC)(GLuint sampler, GLenum pname, const GLint *param);
-GLAPI PFNGLSAMPLERPARAMETERIIVPROC glad_glSamplerParameterIiv;
-#define glSamplerParameterIiv glad_glSamplerParameterIiv
-typedef void (APIENTRYP PFNGLSAMPLERPARAMETERIUIVPROC)(GLuint sampler, GLenum pname, const GLuint *param);
-GLAPI PFNGLSAMPLERPARAMETERIUIVPROC glad_glSamplerParameterIuiv;
-#define glSamplerParameterIuiv glad_glSamplerParameterIuiv
-typedef void (APIENTRYP PFNGLGETSAMPLERPARAMETERIVPROC)(GLuint sampler, GLenum pname, GLint *params);
-GLAPI PFNGLGETSAMPLERPARAMETERIVPROC glad_glGetSamplerParameteriv;
-#define glGetSamplerParameteriv glad_glGetSamplerParameteriv
-typedef void (APIENTRYP PFNGLGETSAMPLERPARAMETERIIVPROC)(GLuint sampler, GLenum pname, GLint *params);
-GLAPI PFNGLGETSAMPLERPARAMETERIIVPROC glad_glGetSamplerParameterIiv;
-#define glGetSamplerParameterIiv glad_glGetSamplerParameterIiv
-typedef void (APIENTRYP PFNGLGETSAMPLERPARAMETERFVPROC)(GLuint sampler, GLenum pname, GLfloat *params);
-GLAPI PFNGLGETSAMPLERPARAMETERFVPROC glad_glGetSamplerParameterfv;
-#define glGetSamplerParameterfv glad_glGetSamplerParameterfv
-typedef void (APIENTRYP PFNGLGETSAMPLERPARAMETERIUIVPROC)(GLuint sampler, GLenum pname, GLuint *params);
-GLAPI PFNGLGETSAMPLERPARAMETERIUIVPROC glad_glGetSamplerParameterIuiv;
-#define glGetSamplerParameterIuiv glad_glGetSamplerParameterIuiv
-typedef void (APIENTRYP PFNGLQUERYCOUNTERPROC)(GLuint id, GLenum target);
-GLAPI PFNGLQUERYCOUNTERPROC glad_glQueryCounter;
-#define glQueryCounter glad_glQueryCounter
-typedef void (APIENTRYP PFNGLGETQUERYOBJECTI64VPROC)(GLuint id, GLenum pname, GLint64 *params);
-GLAPI PFNGLGETQUERYOBJECTI64VPROC glad_glGetQueryObjecti64v;
-#define glGetQueryObjecti64v glad_glGetQueryObjecti64v
-typedef void (APIENTRYP PFNGLGETQUERYOBJECTUI64VPROC)(GLuint id, GLenum pname, GLuint64 *params);
-GLAPI PFNGLGETQUERYOBJECTUI64VPROC glad_glGetQueryObjectui64v;
-#define glGetQueryObjectui64v glad_glGetQueryObjectui64v
-typedef void (APIENTRYP PFNGLVERTEXATTRIBDIVISORPROC)(GLuint index, GLuint divisor);
-GLAPI PFNGLVERTEXATTRIBDIVISORPROC glad_glVertexAttribDivisor;
-#define glVertexAttribDivisor glad_glVertexAttribDivisor
-typedef void (APIENTRYP PFNGLVERTEXATTRIBP1UIPROC)(GLuint index, GLenum type, GLboolean normalized, GLuint value);
-GLAPI PFNGLVERTEXATTRIBP1UIPROC glad_glVertexAttribP1ui;
-#define glVertexAttribP1ui glad_glVertexAttribP1ui
-typedef void (APIENTRYP PFNGLVERTEXATTRIBP1UIVPROC)(GLuint index, GLenum type, GLboolean normalized, const GLuint *value);
-GLAPI PFNGLVERTEXATTRIBP1UIVPROC glad_glVertexAttribP1uiv;
-#define glVertexAttribP1uiv glad_glVertexAttribP1uiv
-typedef void (APIENTRYP PFNGLVERTEXATTRIBP2UIPROC)(GLuint index, GLenum type, GLboolean normalized, GLuint value);
-GLAPI PFNGLVERTEXATTRIBP2UIPROC glad_glVertexAttribP2ui;
-#define glVertexAttribP2ui glad_glVertexAttribP2ui
-typedef void (APIENTRYP PFNGLVERTEXATTRIBP2UIVPROC)(GLuint index, GLenum type, GLboolean normalized, const GLuint *value);
-GLAPI PFNGLVERTEXATTRIBP2UIVPROC glad_glVertexAttribP2uiv;
-#define glVertexAttribP2uiv glad_glVertexAttribP2uiv
-typedef void (APIENTRYP PFNGLVERTEXATTRIBP3UIPROC)(GLuint index, GLenum type, GLboolean normalized, GLuint value);
-GLAPI PFNGLVERTEXATTRIBP3UIPROC glad_glVertexAttribP3ui;
-#define glVertexAttribP3ui glad_glVertexAttribP3ui
-typedef void (APIENTRYP PFNGLVERTEXATTRIBP3UIVPROC)(GLuint index, GLenum type, GLboolean normalized, const GLuint *value);
-GLAPI PFNGLVERTEXATTRIBP3UIVPROC glad_glVertexAttribP3uiv;
-#define glVertexAttribP3uiv glad_glVertexAttribP3uiv
-typedef void (APIENTRYP PFNGLVERTEXATTRIBP4UIPROC)(GLuint index, GLenum type, GLboolean normalized, GLuint value);
-GLAPI PFNGLVERTEXATTRIBP4UIPROC glad_glVertexAttribP4ui;
-#define glVertexAttribP4ui glad_glVertexAttribP4ui
-typedef void (APIENTRYP PFNGLVERTEXATTRIBP4UIVPROC)(GLuint index, GLenum type, GLboolean normalized, const GLuint *value);
-GLAPI PFNGLVERTEXATTRIBP4UIVPROC glad_glVertexAttribP4uiv;
-#define glVertexAttribP4uiv glad_glVertexAttribP4uiv
-typedef void (APIENTRYP PFNGLVERTEXP2UIPROC)(GLenum type, GLuint value);
-GLAPI PFNGLVERTEXP2UIPROC glad_glVertexP2ui;
-#define glVertexP2ui glad_glVertexP2ui
-typedef void (APIENTRYP PFNGLVERTEXP2UIVPROC)(GLenum type, const GLuint *value);
-GLAPI PFNGLVERTEXP2UIVPROC glad_glVertexP2uiv;
-#define glVertexP2uiv glad_glVertexP2uiv
-typedef void (APIENTRYP PFNGLVERTEXP3UIPROC)(GLenum type, GLuint value);
-GLAPI PFNGLVERTEXP3UIPROC glad_glVertexP3ui;
-#define glVertexP3ui glad_glVertexP3ui
-typedef void (APIENTRYP PFNGLVERTEXP3UIVPROC)(GLenum type, const GLuint *value);
-GLAPI PFNGLVERTEXP3UIVPROC glad_glVertexP3uiv;
-#define glVertexP3uiv glad_glVertexP3uiv
-typedef void (APIENTRYP PFNGLVERTEXP4UIPROC)(GLenum type, GLuint value);
-GLAPI PFNGLVERTEXP4UIPROC glad_glVertexP4ui;
-#define glVertexP4ui glad_glVertexP4ui
-typedef void (APIENTRYP PFNGLVERTEXP4UIVPROC)(GLenum type, const GLuint *value);
-GLAPI PFNGLVERTEXP4UIVPROC glad_glVertexP4uiv;
-#define glVertexP4uiv glad_glVertexP4uiv
-typedef void (APIENTRYP PFNGLTEXCOORDP1UIPROC)(GLenum type, GLuint coords);
-GLAPI PFNGLTEXCOORDP1UIPROC glad_glTexCoordP1ui;
-#define glTexCoordP1ui glad_glTexCoordP1ui
-typedef void (APIENTRYP PFNGLTEXCOORDP1UIVPROC)(GLenum type, const GLuint *coords);
-GLAPI PFNGLTEXCOORDP1UIVPROC glad_glTexCoordP1uiv;
-#define glTexCoordP1uiv glad_glTexCoordP1uiv
-typedef void (APIENTRYP PFNGLTEXCOORDP2UIPROC)(GLenum type, GLuint coords);
-GLAPI PFNGLTEXCOORDP2UIPROC glad_glTexCoordP2ui;
-#define glTexCoordP2ui glad_glTexCoordP2ui
-typedef void (APIENTRYP PFNGLTEXCOORDP2UIVPROC)(GLenum type, const GLuint *coords);
-GLAPI PFNGLTEXCOORDP2UIVPROC glad_glTexCoordP2uiv;
-#define glTexCoordP2uiv glad_glTexCoordP2uiv
-typedef void (APIENTRYP PFNGLTEXCOORDP3UIPROC)(GLenum type, GLuint coords);
-GLAPI PFNGLTEXCOORDP3UIPROC glad_glTexCoordP3ui;
-#define glTexCoordP3ui glad_glTexCoordP3ui
-typedef void (APIENTRYP PFNGLTEXCOORDP3UIVPROC)(GLenum type, const GLuint *coords);
-GLAPI PFNGLTEXCOORDP3UIVPROC glad_glTexCoordP3uiv;
-#define glTexCoordP3uiv glad_glTexCoordP3uiv
-typedef void (APIENTRYP PFNGLTEXCOORDP4UIPROC)(GLenum type, GLuint coords);
-GLAPI PFNGLTEXCOORDP4UIPROC glad_glTexCoordP4ui;
-#define glTexCoordP4ui glad_glTexCoordP4ui
-typedef void (APIENTRYP PFNGLTEXCOORDP4UIVPROC)(GLenum type, const GLuint *coords);
-GLAPI PFNGLTEXCOORDP4UIVPROC glad_glTexCoordP4uiv;
-#define glTexCoordP4uiv glad_glTexCoordP4uiv
-typedef void (APIENTRYP PFNGLMULTITEXCOORDP1UIPROC)(GLenum texture, GLenum type, GLuint coords);
-GLAPI PFNGLMULTITEXCOORDP1UIPROC glad_glMultiTexCoordP1ui;
-#define glMultiTexCoordP1ui glad_glMultiTexCoordP1ui
-typedef void (APIENTRYP PFNGLMULTITEXCOORDP1UIVPROC)(GLenum texture, GLenum type, const GLuint *coords);
-GLAPI PFNGLMULTITEXCOORDP1UIVPROC glad_glMultiTexCoordP1uiv;
-#define glMultiTexCoordP1uiv glad_glMultiTexCoordP1uiv
-typedef void (APIENTRYP PFNGLMULTITEXCOORDP2UIPROC)(GLenum texture, GLenum type, GLuint coords);
-GLAPI PFNGLMULTITEXCOORDP2UIPROC glad_glMultiTexCoordP2ui;
-#define glMultiTexCoordP2ui glad_glMultiTexCoordP2ui
-typedef void (APIENTRYP PFNGLMULTITEXCOORDP2UIVPROC)(GLenum texture, GLenum type, const GLuint *coords);
-GLAPI PFNGLMULTITEXCOORDP2UIVPROC glad_glMultiTexCoordP2uiv;
-#define glMultiTexCoordP2uiv glad_glMultiTexCoordP2uiv
-typedef void (APIENTRYP PFNGLMULTITEXCOORDP3UIPROC)(GLenum texture, GLenum type, GLuint coords);
-GLAPI PFNGLMULTITEXCOORDP3UIPROC glad_glMultiTexCoordP3ui;
-#define glMultiTexCoordP3ui glad_glMultiTexCoordP3ui
-typedef void (APIENTRYP PFNGLMULTITEXCOORDP3UIVPROC)(GLenum texture, GLenum type, const GLuint *coords);
-GLAPI PFNGLMULTITEXCOORDP3UIVPROC glad_glMultiTexCoordP3uiv;
-#define glMultiTexCoordP3uiv glad_glMultiTexCoordP3uiv
-typedef void (APIENTRYP PFNGLMULTITEXCOORDP4UIPROC)(GLenum texture, GLenum type, GLuint coords);
-GLAPI PFNGLMULTITEXCOORDP4UIPROC glad_glMultiTexCoordP4ui;
-#define glMultiTexCoordP4ui glad_glMultiTexCoordP4ui
-typedef void (APIENTRYP PFNGLMULTITEXCOORDP4UIVPROC)(GLenum texture, GLenum type, const GLuint *coords);
-GLAPI PFNGLMULTITEXCOORDP4UIVPROC glad_glMultiTexCoordP4uiv;
-#define glMultiTexCoordP4uiv glad_glMultiTexCoordP4uiv
-typedef void (APIENTRYP PFNGLNORMALP3UIPROC)(GLenum type, GLuint coords);
-GLAPI PFNGLNORMALP3UIPROC glad_glNormalP3ui;
-#define glNormalP3ui glad_glNormalP3ui
-typedef void (APIENTRYP PFNGLNORMALP3UIVPROC)(GLenum type, const GLuint *coords);
-GLAPI PFNGLNORMALP3UIVPROC glad_glNormalP3uiv;
-#define glNormalP3uiv glad_glNormalP3uiv
-typedef void (APIENTRYP PFNGLCOLORP3UIPROC)(GLenum type, GLuint color);
-GLAPI PFNGLCOLORP3UIPROC glad_glColorP3ui;
-#define glColorP3ui glad_glColorP3ui
-typedef void (APIENTRYP PFNGLCOLORP3UIVPROC)(GLenum type, const GLuint *color);
-GLAPI PFNGLCOLORP3UIVPROC glad_glColorP3uiv;
-#define glColorP3uiv glad_glColorP3uiv
-typedef void (APIENTRYP PFNGLCOLORP4UIPROC)(GLenum type, GLuint color);
-GLAPI PFNGLCOLORP4UIPROC glad_glColorP4ui;
-#define glColorP4ui glad_glColorP4ui
-typedef void (APIENTRYP PFNGLCOLORP4UIVPROC)(GLenum type, const GLuint *color);
-GLAPI PFNGLCOLORP4UIVPROC glad_glColorP4uiv;
-#define glColorP4uiv glad_glColorP4uiv
-typedef void (APIENTRYP PFNGLSECONDARYCOLORP3UIPROC)(GLenum type, GLuint color);
-GLAPI PFNGLSECONDARYCOLORP3UIPROC glad_glSecondaryColorP3ui;
-#define glSecondaryColorP3ui glad_glSecondaryColorP3ui
-typedef void (APIENTRYP PFNGLSECONDARYCOLORP3UIVPROC)(GLenum type, const GLuint *color);
-GLAPI PFNGLSECONDARYCOLORP3UIVPROC glad_glSecondaryColorP3uiv;
-#define glSecondaryColorP3uiv glad_glSecondaryColorP3uiv
-#endif
-#define GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB 0x8242
-#define GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_ARB 0x8243
-#define GL_DEBUG_CALLBACK_FUNCTION_ARB 0x8244
-#define GL_DEBUG_CALLBACK_USER_PARAM_ARB 0x8245
-#define GL_DEBUG_SOURCE_API_ARB 0x8246
-#define GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB 0x8247
-#define GL_DEBUG_SOURCE_SHADER_COMPILER_ARB 0x8248
-#define GL_DEBUG_SOURCE_THIRD_PARTY_ARB 0x8249
-#define GL_DEBUG_SOURCE_APPLICATION_ARB 0x824A
-#define GL_DEBUG_SOURCE_OTHER_ARB 0x824B
-#define GL_DEBUG_TYPE_ERROR_ARB 0x824C
-#define GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB 0x824D
-#define GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB 0x824E
-#define GL_DEBUG_TYPE_PORTABILITY_ARB 0x824F
-#define GL_DEBUG_TYPE_PERFORMANCE_ARB 0x8250
-#define GL_DEBUG_TYPE_OTHER_ARB 0x8251
-#define GL_MAX_DEBUG_MESSAGE_LENGTH_ARB 0x9143
-#define GL_MAX_DEBUG_LOGGED_MESSAGES_ARB 0x9144
-#define GL_DEBUG_LOGGED_MESSAGES_ARB 0x9145
-#define GL_DEBUG_SEVERITY_HIGH_ARB 0x9146
-#define GL_DEBUG_SEVERITY_MEDIUM_ARB 0x9147
-#define GL_DEBUG_SEVERITY_LOW_ARB 0x9148
-#define GL_READ_FRAMEBUFFER_EXT 0x8CA8
-#define GL_DRAW_FRAMEBUFFER_EXT 0x8CA9
-#define GL_DRAW_FRAMEBUFFER_BINDING_EXT 0x8CA6
-#define GL_READ_FRAMEBUFFER_BINDING_EXT 0x8CAA
-#define GL_RENDERBUFFER_SAMPLES_EXT 0x8CAB
-#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT 0x8D56
-#define GL_MAX_SAMPLES_EXT 0x8D57
-#define GL_INVALID_FRAMEBUFFER_OPERATION_EXT 0x0506
-#define GL_MAX_RENDERBUFFER_SIZE_EXT 0x84E8
-#define GL_FRAMEBUFFER_BINDING_EXT 0x8CA6
-#define GL_RENDERBUFFER_BINDING_EXT 0x8CA7
-#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT 0x8CD0
-#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT 0x8CD1
-#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT 0x8CD2
-#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT 0x8CD3
-#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT 0x8CD4
-#define GL_FRAMEBUFFER_COMPLETE_EXT 0x8CD5
-#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT 0x8CD6
-#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT 0x8CD7
-#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT 0x8CD9
-#define GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT 0x8CDA
-#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT 0x8CDB
-#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT 0x8CDC
-#define GL_FRAMEBUFFER_UNSUPPORTED_EXT 0x8CDD
-#define GL_MAX_COLOR_ATTACHMENTS_EXT 0x8CDF
-#define GL_COLOR_ATTACHMENT0_EXT 0x8CE0
-#define GL_COLOR_ATTACHMENT1_EXT 0x8CE1
-#define GL_COLOR_ATTACHMENT2_EXT 0x8CE2
-#define GL_COLOR_ATTACHMENT3_EXT 0x8CE3
-#define GL_COLOR_ATTACHMENT4_EXT 0x8CE4
-#define GL_COLOR_ATTACHMENT5_EXT 0x8CE5
-#define GL_COLOR_ATTACHMENT6_EXT 0x8CE6
-#define GL_COLOR_ATTACHMENT7_EXT 0x8CE7
-#define GL_COLOR_ATTACHMENT8_EXT 0x8CE8
-#define GL_COLOR_ATTACHMENT9_EXT 0x8CE9
-#define GL_COLOR_ATTACHMENT10_EXT 0x8CEA
-#define GL_COLOR_ATTACHMENT11_EXT 0x8CEB
-#define GL_COLOR_ATTACHMENT12_EXT 0x8CEC
-#define GL_COLOR_ATTACHMENT13_EXT 0x8CED
-#define GL_COLOR_ATTACHMENT14_EXT 0x8CEE
-#define GL_COLOR_ATTACHMENT15_EXT 0x8CEF
-#define GL_DEPTH_ATTACHMENT_EXT 0x8D00
-#define GL_STENCIL_ATTACHMENT_EXT 0x8D20
-#define GL_FRAMEBUFFER_EXT 0x8D40
-#define GL_RENDERBUFFER_EXT 0x8D41
-#define GL_RENDERBUFFER_WIDTH_EXT 0x8D42
-#define GL_RENDERBUFFER_HEIGHT_EXT 0x8D43
-#define GL_RENDERBUFFER_INTERNAL_FORMAT_EXT 0x8D44
-#define GL_STENCIL_INDEX1_EXT 0x8D46
-#define GL_STENCIL_INDEX4_EXT 0x8D47
-#define GL_STENCIL_INDEX8_EXT 0x8D48
-#define GL_STENCIL_INDEX16_EXT 0x8D49
-#define GL_RENDERBUFFER_RED_SIZE_EXT 0x8D50
-#define GL_RENDERBUFFER_GREEN_SIZE_EXT 0x8D51
-#define GL_RENDERBUFFER_BLUE_SIZE_EXT 0x8D52
-#define GL_RENDERBUFFER_ALPHA_SIZE_EXT 0x8D53
-#define GL_RENDERBUFFER_DEPTH_SIZE_EXT 0x8D54
-#define GL_RENDERBUFFER_STENCIL_SIZE_EXT 0x8D55
-#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_OVR 0x9630
-#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_OVR 0x9632
-#define GL_MAX_VIEWS_OVR 0x9631
-#define GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_OVR 0x9633
-#ifndef GL_ARB_debug_output
-#define GL_ARB_debug_output 1
-GLAPI int GLAD_GL_ARB_debug_output;
-typedef void (APIENTRYP PFNGLDEBUGMESSAGECONTROLARBPROC)(GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled);
-GLAPI PFNGLDEBUGMESSAGECONTROLARBPROC glad_glDebugMessageControlARB;
-#define glDebugMessageControlARB glad_glDebugMessageControlARB
-typedef void (APIENTRYP PFNGLDEBUGMESSAGEINSERTARBPROC)(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf);
-GLAPI PFNGLDEBUGMESSAGEINSERTARBPROC glad_glDebugMessageInsertARB;
-#define glDebugMessageInsertARB glad_glDebugMessageInsertARB
-typedef void (APIENTRYP PFNGLDEBUGMESSAGECALLBACKARBPROC)(GLDEBUGPROCARB callback, const void *userParam);
-GLAPI PFNGLDEBUGMESSAGECALLBACKARBPROC glad_glDebugMessageCallbackARB;
-#define glDebugMessageCallbackARB glad_glDebugMessageCallbackARB
-typedef GLuint (APIENTRYP PFNGLGETDEBUGMESSAGELOGARBPROC)(GLuint count, GLsizei bufSize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog);
-GLAPI PFNGLGETDEBUGMESSAGELOGARBPROC glad_glGetDebugMessageLogARB;
-#define glGetDebugMessageLogARB glad_glGetDebugMessageLogARB
-#endif
-#ifndef GL_ARB_framebuffer_object
-#define GL_ARB_framebuffer_object 1
-GLAPI int GLAD_GL_ARB_framebuffer_object;
-#endif
-#ifndef GL_EXT_framebuffer_blit
-#define GL_EXT_framebuffer_blit 1
-GLAPI int GLAD_GL_EXT_framebuffer_blit;
-typedef void (APIENTRYP PFNGLBLITFRAMEBUFFEREXTPROC)(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
-GLAPI PFNGLBLITFRAMEBUFFEREXTPROC glad_glBlitFramebufferEXT;
-#define glBlitFramebufferEXT glad_glBlitFramebufferEXT
-#endif
-#ifndef GL_EXT_framebuffer_multisample
-#define GL_EXT_framebuffer_multisample 1
-GLAPI int GLAD_GL_EXT_framebuffer_multisample;
-typedef void (APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
-GLAPI PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC glad_glRenderbufferStorageMultisampleEXT;
-#define glRenderbufferStorageMultisampleEXT glad_glRenderbufferStorageMultisampleEXT
-#endif
-#ifndef GL_EXT_framebuffer_object
-#define GL_EXT_framebuffer_object 1
-GLAPI int GLAD_GL_EXT_framebuffer_object;
-typedef GLboolean (APIENTRYP PFNGLISRENDERBUFFEREXTPROC)(GLuint renderbuffer);
-GLAPI PFNGLISRENDERBUFFEREXTPROC glad_glIsRenderbufferEXT;
-#define glIsRenderbufferEXT glad_glIsRenderbufferEXT
-typedef void (APIENTRYP PFNGLBINDRENDERBUFFEREXTPROC)(GLenum target, GLuint renderbuffer);
-GLAPI PFNGLBINDRENDERBUFFEREXTPROC glad_glBindRenderbufferEXT;
-#define glBindRenderbufferEXT glad_glBindRenderbufferEXT
-typedef void (APIENTRYP PFNGLDELETERENDERBUFFERSEXTPROC)(GLsizei n, const GLuint *renderbuffers);
-GLAPI PFNGLDELETERENDERBUFFERSEXTPROC glad_glDeleteRenderbuffersEXT;
-#define glDeleteRenderbuffersEXT glad_glDeleteRenderbuffersEXT
-typedef void (APIENTRYP PFNGLGENRENDERBUFFERSEXTPROC)(GLsizei n, GLuint *renderbuffers);
-GLAPI PFNGLGENRENDERBUFFERSEXTPROC glad_glGenRenderbuffersEXT;
-#define glGenRenderbuffersEXT glad_glGenRenderbuffersEXT
-typedef void (APIENTRYP PFNGLRENDERBUFFERSTORAGEEXTPROC)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
-GLAPI PFNGLRENDERBUFFERSTORAGEEXTPROC glad_glRenderbufferStorageEXT;
-#define glRenderbufferStorageEXT glad_glRenderbufferStorageEXT
-typedef void (APIENTRYP PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC)(GLenum target, GLenum pname, GLint *params);
-GLAPI PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC glad_glGetRenderbufferParameterivEXT;
-#define glGetRenderbufferParameterivEXT glad_glGetRenderbufferParameterivEXT
-typedef GLboolean (APIENTRYP PFNGLISFRAMEBUFFEREXTPROC)(GLuint framebuffer);
-GLAPI PFNGLISFRAMEBUFFEREXTPROC glad_glIsFramebufferEXT;
-#define glIsFramebufferEXT glad_glIsFramebufferEXT
-typedef void (APIENTRYP PFNGLBINDFRAMEBUFFEREXTPROC)(GLenum target, GLuint framebuffer);
-GLAPI PFNGLBINDFRAMEBUFFEREXTPROC glad_glBindFramebufferEXT;
-#define glBindFramebufferEXT glad_glBindFramebufferEXT
-typedef void (APIENTRYP PFNGLDELETEFRAMEBUFFERSEXTPROC)(GLsizei n, const GLuint *framebuffers);
-GLAPI PFNGLDELETEFRAMEBUFFERSEXTPROC glad_glDeleteFramebuffersEXT;
-#define glDeleteFramebuffersEXT glad_glDeleteFramebuffersEXT
-typedef void (APIENTRYP PFNGLGENFRAMEBUFFERSEXTPROC)(GLsizei n, GLuint *framebuffers);
-GLAPI PFNGLGENFRAMEBUFFERSEXTPROC glad_glGenFramebuffersEXT;
-#define glGenFramebuffersEXT glad_glGenFramebuffersEXT
-typedef GLenum (APIENTRYP PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC)(GLenum target);
-GLAPI PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC glad_glCheckFramebufferStatusEXT;
-#define glCheckFramebufferStatusEXT glad_glCheckFramebufferStatusEXT
-typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE1DEXTPROC)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
-GLAPI PFNGLFRAMEBUFFERTEXTURE1DEXTPROC glad_glFramebufferTexture1DEXT;
-#define glFramebufferTexture1DEXT glad_glFramebufferTexture1DEXT
-typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DEXTPROC)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
-GLAPI PFNGLFRAMEBUFFERTEXTURE2DEXTPROC glad_glFramebufferTexture2DEXT;
-#define glFramebufferTexture2DEXT glad_glFramebufferTexture2DEXT
-typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE3DEXTPROC)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
-GLAPI PFNGLFRAMEBUFFERTEXTURE3DEXTPROC glad_glFramebufferTexture3DEXT;
-#define glFramebufferTexture3DEXT glad_glFramebufferTexture3DEXT
-typedef void (APIENTRYP PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC)(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
-GLAPI PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glad_glFramebufferRenderbufferEXT;
-#define glFramebufferRenderbufferEXT glad_glFramebufferRenderbufferEXT
-typedef void (APIENTRYP PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC)(GLenum target, GLenum attachment, GLenum pname, GLint *params);
-GLAPI PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC glad_glGetFramebufferAttachmentParameterivEXT;
-#define glGetFramebufferAttachmentParameterivEXT glad_glGetFramebufferAttachmentParameterivEXT
-typedef void (APIENTRYP PFNGLGENERATEMIPMAPEXTPROC)(GLenum target);
-GLAPI PFNGLGENERATEMIPMAPEXTPROC glad_glGenerateMipmapEXT;
-#define glGenerateMipmapEXT glad_glGenerateMipmapEXT
-#endif
-#ifndef GL_OVR_multiview
-#define GL_OVR_multiview 1
-GLAPI int GLAD_GL_OVR_multiview;
-typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC)(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint baseViewIndex, GLsizei numViews);
-GLAPI PFNGLFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC glad_glFramebufferTextureMultiviewOVR;
-#define glFramebufferTextureMultiviewOVR glad_glFramebufferTextureMultiviewOVR
-#endif
-#ifndef GL_OVR_multiview2
-#define GL_OVR_multiview2 1
-GLAPI int GLAD_GL_OVR_multiview2;
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/thirdparty/glad/glad/glx.h b/thirdparty/glad/glad/glx.h
new file mode 100644
index 0000000000..ac115fa63b
--- /dev/null
+++ b/thirdparty/glad/glad/glx.h
@@ -0,0 +1,605 @@
+/**
+ * Loader generated by glad 2.0.2 on Tue Nov 15 09:49:49 2022
+ *
+ * SPDX-License-Identifier: (WTFPL OR CC0-1.0) AND Apache-2.0
+ *
+ * Generator: C/C++
+ * Specification: glx
+ * Extensions: 6
+ *
+ * APIs:
+ * - glx=1.4
+ *
+ * Options:
+ * - ALIAS = False
+ * - DEBUG = False
+ * - HEADER_ONLY = False
+ * - LOADER = True
+ * - MX = False
+ * - ON_DEMAND = False
+ *
+ * Commandline:
+ * --api='glx=1.4' --extensions='GLX_ARB_create_context,GLX_ARB_create_context_profile,GLX_ARB_get_proc_address,GLX_EXT_swap_control,GLX_MESA_swap_control,GLX_SGI_swap_control' c --loader
+ *
+ * Online:
+ * http://glad.sh/#api=glx%3D1.4&extensions=GLX_ARB_create_context%2CGLX_ARB_create_context_profile%2CGLX_ARB_get_proc_address%2CGLX_EXT_swap_control%2CGLX_MESA_swap_control%2CGLX_SGI_swap_control&generator=c&options=LOADER
+ *
+ */
+
+#ifndef GLAD_GLX_H_
+#define GLAD_GLX_H_
+
+#ifdef GLX_H
+ #error GLX header already included (API: glx), remove previous include!
+#endif
+#define GLX_H 1
+
+
+#include <X11/X.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+#include <glad/gl.h>
+
+#define GLAD_GLX
+#define GLAD_OPTION_GLX_LOADER
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef GLAD_PLATFORM_H_
+#define GLAD_PLATFORM_H_
+
+#ifndef GLAD_PLATFORM_WIN32
+ #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) || defined(__MINGW32__)
+ #define GLAD_PLATFORM_WIN32 1
+ #else
+ #define GLAD_PLATFORM_WIN32 0
+ #endif
+#endif
+
+#ifndef GLAD_PLATFORM_APPLE
+ #ifdef __APPLE__
+ #define GLAD_PLATFORM_APPLE 1
+ #else
+ #define GLAD_PLATFORM_APPLE 0
+ #endif
+#endif
+
+#ifndef GLAD_PLATFORM_EMSCRIPTEN
+ #ifdef __EMSCRIPTEN__
+ #define GLAD_PLATFORM_EMSCRIPTEN 1
+ #else
+ #define GLAD_PLATFORM_EMSCRIPTEN 0
+ #endif
+#endif
+
+#ifndef GLAD_PLATFORM_UWP
+ #if defined(_MSC_VER) && !defined(GLAD_INTERNAL_HAVE_WINAPIFAMILY)
+ #ifdef __has_include
+ #if __has_include(<winapifamily.h>)
+ #define GLAD_INTERNAL_HAVE_WINAPIFAMILY 1
+ #endif
+ #elif _MSC_VER >= 1700 && !_USING_V110_SDK71_
+ #define GLAD_INTERNAL_HAVE_WINAPIFAMILY 1
+ #endif
+ #endif
+
+ #ifdef GLAD_INTERNAL_HAVE_WINAPIFAMILY
+ #include <winapifamily.h>
+ #if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)
+ #define GLAD_PLATFORM_UWP 1
+ #endif
+ #endif
+
+ #ifndef GLAD_PLATFORM_UWP
+ #define GLAD_PLATFORM_UWP 0
+ #endif
+#endif
+
+#ifdef __GNUC__
+ #define GLAD_GNUC_EXTENSION __extension__
+#else
+ #define GLAD_GNUC_EXTENSION
+#endif
+
+#define GLAD_UNUSED(x) (void)(x)
+
+#ifndef GLAD_API_CALL
+ #if defined(GLAD_API_CALL_EXPORT)
+ #if GLAD_PLATFORM_WIN32 || defined(__CYGWIN__)
+ #if defined(GLAD_API_CALL_EXPORT_BUILD)
+ #if defined(__GNUC__)
+ #define GLAD_API_CALL __attribute__ ((dllexport)) extern
+ #else
+ #define GLAD_API_CALL __declspec(dllexport) extern
+ #endif
+ #else
+ #if defined(__GNUC__)
+ #define GLAD_API_CALL __attribute__ ((dllimport)) extern
+ #else
+ #define GLAD_API_CALL __declspec(dllimport) extern
+ #endif
+ #endif
+ #elif defined(__GNUC__) && defined(GLAD_API_CALL_EXPORT_BUILD)
+ #define GLAD_API_CALL __attribute__ ((visibility ("default"))) extern
+ #else
+ #define GLAD_API_CALL extern
+ #endif
+ #else
+ #define GLAD_API_CALL extern
+ #endif
+#endif
+
+#ifdef APIENTRY
+ #define GLAD_API_PTR APIENTRY
+#elif GLAD_PLATFORM_WIN32
+ #define GLAD_API_PTR __stdcall
+#else
+ #define GLAD_API_PTR
+#endif
+
+#ifndef GLAPI
+#define GLAPI GLAD_API_CALL
+#endif
+
+#ifndef GLAPIENTRY
+#define GLAPIENTRY GLAD_API_PTR
+#endif
+
+#define GLAD_MAKE_VERSION(major, minor) (major * 10000 + minor)
+#define GLAD_VERSION_MAJOR(version) (version / 10000)
+#define GLAD_VERSION_MINOR(version) (version % 10000)
+
+#define GLAD_GENERATOR_VERSION "2.0.2"
+
+typedef void (*GLADapiproc)(void);
+
+typedef GLADapiproc (*GLADloadfunc)(const char *name);
+typedef GLADapiproc (*GLADuserptrloadfunc)(void *userptr, const char *name);
+
+typedef void (*GLADprecallback)(const char *name, GLADapiproc apiproc, int len_args, ...);
+typedef void (*GLADpostcallback)(void *ret, const char *name, GLADapiproc apiproc, int len_args, ...);
+
+#endif /* GLAD_PLATFORM_H_ */
+
+#define GLX_ACCUM_ALPHA_SIZE 17
+#define GLX_ACCUM_BLUE_SIZE 16
+#define GLX_ACCUM_BUFFER_BIT 0x00000080
+#define GLX_ACCUM_GREEN_SIZE 15
+#define GLX_ACCUM_RED_SIZE 14
+#define GLX_ALPHA_SIZE 11
+#define GLX_AUX_BUFFERS 7
+#define GLX_AUX_BUFFERS_BIT 0x00000010
+#define GLX_BACK_LEFT_BUFFER_BIT 0x00000004
+#define GLX_BACK_RIGHT_BUFFER_BIT 0x00000008
+#define GLX_BAD_ATTRIBUTE 2
+#define GLX_BAD_CONTEXT 5
+#define GLX_BAD_ENUM 7
+#define GLX_BAD_SCREEN 1
+#define GLX_BAD_VALUE 6
+#define GLX_BAD_VISUAL 4
+#define GLX_BLUE_SIZE 10
+#define GLX_BUFFER_SIZE 2
+#define GLX_BufferSwapComplete 1
+#define GLX_COLOR_INDEX_BIT 0x00000002
+#define GLX_COLOR_INDEX_TYPE 0x8015
+#define GLX_CONFIG_CAVEAT 0x20
+#define GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
+#define GLX_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
+#define GLX_CONTEXT_DEBUG_BIT_ARB 0x00000001
+#define GLX_CONTEXT_FLAGS_ARB 0x2094
+#define GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x00000002
+#define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091
+#define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092
+#define GLX_CONTEXT_PROFILE_MASK_ARB 0x9126
+#define GLX_DAMAGED 0x8020
+#define GLX_DEPTH_BUFFER_BIT 0x00000020
+#define GLX_DEPTH_SIZE 12
+#define GLX_DIRECT_COLOR 0x8003
+#define GLX_DONT_CARE 0xFFFFFFFF
+#define GLX_DOUBLEBUFFER 5
+#define GLX_DRAWABLE_TYPE 0x8010
+#define GLX_EVENT_MASK 0x801F
+#define GLX_EXTENSIONS 0x3
+#define GLX_EXTENSION_NAME "GLX"
+#define GLX_FBCONFIG_ID 0x8013
+#define GLX_FRONT_LEFT_BUFFER_BIT 0x00000001
+#define GLX_FRONT_RIGHT_BUFFER_BIT 0x00000002
+#define GLX_GRAY_SCALE 0x8006
+#define GLX_GREEN_SIZE 9
+#define GLX_HEIGHT 0x801E
+#define GLX_LARGEST_PBUFFER 0x801C
+#define GLX_LEVEL 3
+#define GLX_MAX_PBUFFER_HEIGHT 0x8017
+#define GLX_MAX_PBUFFER_PIXELS 0x8018
+#define GLX_MAX_PBUFFER_WIDTH 0x8016
+#define GLX_MAX_SWAP_INTERVAL_EXT 0x20F2
+#define GLX_NONE 0x8000
+#define GLX_NON_CONFORMANT_CONFIG 0x800D
+#define GLX_NO_EXTENSION 3
+#define GLX_PBUFFER 0x8023
+#define GLX_PBUFFER_BIT 0x00000004
+#define GLX_PBUFFER_CLOBBER_MASK 0x08000000
+#define GLX_PBUFFER_HEIGHT 0x8040
+#define GLX_PBUFFER_WIDTH 0x8041
+#define GLX_PIXMAP_BIT 0x00000002
+#define GLX_PRESERVED_CONTENTS 0x801B
+#define GLX_PSEUDO_COLOR 0x8004
+#define GLX_PbufferClobber 0
+#define GLX_RED_SIZE 8
+#define GLX_RENDER_TYPE 0x8011
+#define GLX_RGBA 4
+#define GLX_RGBA_BIT 0x00000001
+#define GLX_RGBA_TYPE 0x8014
+#define GLX_SAMPLES 100001
+#define GLX_SAMPLE_BUFFERS 100000
+#define GLX_SAVED 0x8021
+#define GLX_SCREEN 0x800C
+#define GLX_SLOW_CONFIG 0x8001
+#define GLX_STATIC_COLOR 0x8005
+#define GLX_STATIC_GRAY 0x8007
+#define GLX_STENCIL_BUFFER_BIT 0x00000040
+#define GLX_STENCIL_SIZE 13
+#define GLX_STEREO 6
+#define GLX_SWAP_INTERVAL_EXT 0x20F1
+#define GLX_TRANSPARENT_ALPHA_VALUE 0x28
+#define GLX_TRANSPARENT_BLUE_VALUE 0x27
+#define GLX_TRANSPARENT_GREEN_VALUE 0x26
+#define GLX_TRANSPARENT_INDEX 0x8009
+#define GLX_TRANSPARENT_INDEX_VALUE 0x24
+#define GLX_TRANSPARENT_RED_VALUE 0x25
+#define GLX_TRANSPARENT_RGB 0x8008
+#define GLX_TRANSPARENT_TYPE 0x23
+#define GLX_TRUE_COLOR 0x8002
+#define GLX_USE_GL 1
+#define GLX_VENDOR 0x1
+#define GLX_VERSION 0x2
+#define GLX_VISUAL_ID 0x800B
+#define GLX_WIDTH 0x801D
+#define GLX_WINDOW 0x8022
+#define GLX_WINDOW_BIT 0x00000001
+#define GLX_X_RENDERABLE 0x8012
+#define GLX_X_VISUAL_TYPE 0x22
+#define __GLX_NUMBER_EVENTS 17
+
+
+#ifndef GLEXT_64_TYPES_DEFINED
+/* This code block is duplicated in glext.h, so must be protected */
+#define GLEXT_64_TYPES_DEFINED
+/* Define int32_t, int64_t, and uint64_t types for UST/MSC */
+/* (as used in the GLX_OML_sync_control extension). */
+#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+#include <inttypes.h>
+#elif defined(__sun__) || defined(__digital__)
+#include <inttypes.h>
+#if defined(__STDC__)
+#if defined(__arch64__) || defined(_LP64)
+typedef long int int64_t;
+typedef unsigned long int uint64_t;
+#else
+typedef long long int int64_t;
+typedef unsigned long long int uint64_t;
+#endif /* __arch64__ */
+#endif /* __STDC__ */
+#elif defined( __VMS ) || defined(__sgi)
+#include <inttypes.h>
+#elif defined(__SCO__) || defined(__USLC__)
+#include <stdint.h>
+#elif defined(__UNIXOS2__) || defined(__SOL64__)
+typedef long int int32_t;
+typedef long long int int64_t;
+typedef unsigned long long int uint64_t;
+#elif defined(_WIN32) && defined(__GNUC__)
+#include <stdint.h>
+#elif defined(_WIN32)
+typedef __int32 int32_t;
+typedef __int64 int64_t;
+typedef unsigned __int64 uint64_t;
+#else
+/* Fallback if nothing above works */
+#include <inttypes.h>
+#endif
+#endif
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ > 1060)
+
+#else
+
+#endif
+
+#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ > 1060)
+
+#else
+
+#endif
+
+
+
+
+
+
+
+typedef XID GLXFBConfigID;
+typedef struct __GLXFBConfigRec *GLXFBConfig;
+typedef XID GLXContextID;
+typedef struct __GLXcontextRec *GLXContext;
+typedef XID GLXPixmap;
+typedef XID GLXDrawable;
+typedef XID GLXWindow;
+typedef XID GLXPbuffer;
+typedef void (GLAD_API_PTR *__GLXextFuncPtr)(void);
+typedef XID GLXVideoCaptureDeviceNV;
+typedef unsigned int GLXVideoDeviceNV;
+typedef XID GLXVideoSourceSGIX;
+typedef XID GLXFBConfigIDSGIX;
+typedef struct __GLXFBConfigRec *GLXFBConfigSGIX;
+typedef XID GLXPbufferSGIX;
+typedef struct {
+ int event_type; /* GLX_DAMAGED or GLX_SAVED */
+ int draw_type; /* GLX_WINDOW or GLX_PBUFFER */
+ unsigned long serial; /* # of last request processed by server */
+ Bool send_event; /* true if this came for SendEvent request */
+ Display *display; /* display the event was read from */
+ GLXDrawable drawable; /* XID of Drawable */
+ unsigned int buffer_mask; /* mask indicating which buffers are affected */
+ unsigned int aux_buffer; /* which aux buffer was affected */
+ int x, y;
+ int width, height;
+ int count; /* if nonzero, at least this many more */
+} GLXPbufferClobberEvent;
+typedef struct {
+ int type;
+ unsigned long serial; /* # of last request processed by server */
+ Bool send_event; /* true if this came from a SendEvent request */
+ Display *display; /* Display the event was read from */
+ GLXDrawable drawable; /* drawable on which event was requested in event mask */
+ int event_type;
+ int64_t ust;
+ int64_t msc;
+ int64_t sbc;
+} GLXBufferSwapComplete;
+typedef union __GLXEvent {
+ GLXPbufferClobberEvent glxpbufferclobber;
+ GLXBufferSwapComplete glxbufferswapcomplete;
+ long pad[24];
+} GLXEvent;
+typedef struct {
+ int type;
+ unsigned long serial;
+ Bool send_event;
+ Display *display;
+ int extension;
+ int evtype;
+ GLXDrawable window;
+ Bool stereo_tree;
+} GLXStereoNotifyEventEXT;
+typedef struct {
+ int type;
+ unsigned long serial; /* # of last request processed by server */
+ Bool send_event; /* true if this came for SendEvent request */
+ Display *display; /* display the event was read from */
+ GLXDrawable drawable; /* i.d. of Drawable */
+ int event_type; /* GLX_DAMAGED_SGIX or GLX_SAVED_SGIX */
+ int draw_type; /* GLX_WINDOW_SGIX or GLX_PBUFFER_SGIX */
+ unsigned int mask; /* mask indicating which buffers are affected*/
+ int x, y;
+ int width, height;
+ int count; /* if nonzero, at least this many more */
+} GLXBufferClobberEventSGIX;
+typedef struct {
+ char pipeName[80]; /* Should be [GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX] */
+ int networkId;
+} GLXHyperpipeNetworkSGIX;
+typedef struct {
+ char pipeName[80]; /* Should be [GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX] */
+ int channel;
+ unsigned int participationType;
+ int timeSlice;
+} GLXHyperpipeConfigSGIX;
+typedef struct {
+ char pipeName[80]; /* Should be [GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX] */
+ int srcXOrigin, srcYOrigin, srcWidth, srcHeight;
+ int destXOrigin, destYOrigin, destWidth, destHeight;
+} GLXPipeRect;
+typedef struct {
+ char pipeName[80]; /* Should be [GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX] */
+ int XOrigin, YOrigin, maxHeight, maxWidth;
+} GLXPipeRectLimits;
+
+
+#define GLX_VERSION_1_0 1
+GLAD_API_CALL int GLAD_GLX_VERSION_1_0;
+#define GLX_VERSION_1_1 1
+GLAD_API_CALL int GLAD_GLX_VERSION_1_1;
+#define GLX_VERSION_1_2 1
+GLAD_API_CALL int GLAD_GLX_VERSION_1_2;
+#define GLX_VERSION_1_3 1
+GLAD_API_CALL int GLAD_GLX_VERSION_1_3;
+#define GLX_VERSION_1_4 1
+GLAD_API_CALL int GLAD_GLX_VERSION_1_4;
+#define GLX_ARB_create_context 1
+GLAD_API_CALL int GLAD_GLX_ARB_create_context;
+#define GLX_ARB_create_context_profile 1
+GLAD_API_CALL int GLAD_GLX_ARB_create_context_profile;
+#define GLX_ARB_get_proc_address 1
+GLAD_API_CALL int GLAD_GLX_ARB_get_proc_address;
+#define GLX_EXT_swap_control 1
+GLAD_API_CALL int GLAD_GLX_EXT_swap_control;
+#define GLX_MESA_swap_control 1
+GLAD_API_CALL int GLAD_GLX_MESA_swap_control;
+#define GLX_SGI_swap_control 1
+GLAD_API_CALL int GLAD_GLX_SGI_swap_control;
+
+
+typedef GLXFBConfig * (GLAD_API_PTR *PFNGLXCHOOSEFBCONFIGPROC)(Display * dpy, int screen, const int * attrib_list, int * nelements);
+typedef XVisualInfo * (GLAD_API_PTR *PFNGLXCHOOSEVISUALPROC)(Display * dpy, int screen, int * attribList);
+typedef void (GLAD_API_PTR *PFNGLXCOPYCONTEXTPROC)(Display * dpy, GLXContext src, GLXContext dst, unsigned long mask);
+typedef GLXContext (GLAD_API_PTR *PFNGLXCREATECONTEXTPROC)(Display * dpy, XVisualInfo * vis, GLXContext shareList, Bool direct);
+typedef GLXContext (GLAD_API_PTR *PFNGLXCREATECONTEXTATTRIBSARBPROC)(Display * dpy, GLXFBConfig config, GLXContext share_context, Bool direct, const int * attrib_list);
+typedef GLXPixmap (GLAD_API_PTR *PFNGLXCREATEGLXPIXMAPPROC)(Display * dpy, XVisualInfo * visual, Pixmap pixmap);
+typedef GLXContext (GLAD_API_PTR *PFNGLXCREATENEWCONTEXTPROC)(Display * dpy, GLXFBConfig config, int render_type, GLXContext share_list, Bool direct);
+typedef GLXPbuffer (GLAD_API_PTR *PFNGLXCREATEPBUFFERPROC)(Display * dpy, GLXFBConfig config, const int * attrib_list);
+typedef GLXPixmap (GLAD_API_PTR *PFNGLXCREATEPIXMAPPROC)(Display * dpy, GLXFBConfig config, Pixmap pixmap, const int * attrib_list);
+typedef GLXWindow (GLAD_API_PTR *PFNGLXCREATEWINDOWPROC)(Display * dpy, GLXFBConfig config, Window win, const int * attrib_list);
+typedef void (GLAD_API_PTR *PFNGLXDESTROYCONTEXTPROC)(Display * dpy, GLXContext ctx);
+typedef void (GLAD_API_PTR *PFNGLXDESTROYGLXPIXMAPPROC)(Display * dpy, GLXPixmap pixmap);
+typedef void (GLAD_API_PTR *PFNGLXDESTROYPBUFFERPROC)(Display * dpy, GLXPbuffer pbuf);
+typedef void (GLAD_API_PTR *PFNGLXDESTROYPIXMAPPROC)(Display * dpy, GLXPixmap pixmap);
+typedef void (GLAD_API_PTR *PFNGLXDESTROYWINDOWPROC)(Display * dpy, GLXWindow win);
+typedef const char * (GLAD_API_PTR *PFNGLXGETCLIENTSTRINGPROC)(Display * dpy, int name);
+typedef int (GLAD_API_PTR *PFNGLXGETCONFIGPROC)(Display * dpy, XVisualInfo * visual, int attrib, int * value);
+typedef GLXContext (GLAD_API_PTR *PFNGLXGETCURRENTCONTEXTPROC)(void);
+typedef Display * (GLAD_API_PTR *PFNGLXGETCURRENTDISPLAYPROC)(void);
+typedef GLXDrawable (GLAD_API_PTR *PFNGLXGETCURRENTDRAWABLEPROC)(void);
+typedef GLXDrawable (GLAD_API_PTR *PFNGLXGETCURRENTREADDRAWABLEPROC)(void);
+typedef int (GLAD_API_PTR *PFNGLXGETFBCONFIGATTRIBPROC)(Display * dpy, GLXFBConfig config, int attribute, int * value);
+typedef GLXFBConfig * (GLAD_API_PTR *PFNGLXGETFBCONFIGSPROC)(Display * dpy, int screen, int * nelements);
+typedef __GLXextFuncPtr (GLAD_API_PTR *PFNGLXGETPROCADDRESSPROC)(const GLubyte * procName);
+typedef __GLXextFuncPtr (GLAD_API_PTR *PFNGLXGETPROCADDRESSARBPROC)(const GLubyte * procName);
+typedef void (GLAD_API_PTR *PFNGLXGETSELECTEDEVENTPROC)(Display * dpy, GLXDrawable draw, unsigned long * event_mask);
+typedef int (GLAD_API_PTR *PFNGLXGETSWAPINTERVALMESAPROC)(void);
+typedef XVisualInfo * (GLAD_API_PTR *PFNGLXGETVISUALFROMFBCONFIGPROC)(Display * dpy, GLXFBConfig config);
+typedef Bool (GLAD_API_PTR *PFNGLXISDIRECTPROC)(Display * dpy, GLXContext ctx);
+typedef Bool (GLAD_API_PTR *PFNGLXMAKECONTEXTCURRENTPROC)(Display * dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx);
+typedef Bool (GLAD_API_PTR *PFNGLXMAKECURRENTPROC)(Display * dpy, GLXDrawable drawable, GLXContext ctx);
+typedef int (GLAD_API_PTR *PFNGLXQUERYCONTEXTPROC)(Display * dpy, GLXContext ctx, int attribute, int * value);
+typedef void (GLAD_API_PTR *PFNGLXQUERYDRAWABLEPROC)(Display * dpy, GLXDrawable draw, int attribute, unsigned int * value);
+typedef Bool (GLAD_API_PTR *PFNGLXQUERYEXTENSIONPROC)(Display * dpy, int * errorb, int * event);
+typedef const char * (GLAD_API_PTR *PFNGLXQUERYEXTENSIONSSTRINGPROC)(Display * dpy, int screen);
+typedef const char * (GLAD_API_PTR *PFNGLXQUERYSERVERSTRINGPROC)(Display * dpy, int screen, int name);
+typedef Bool (GLAD_API_PTR *PFNGLXQUERYVERSIONPROC)(Display * dpy, int * maj, int * min);
+typedef void (GLAD_API_PTR *PFNGLXSELECTEVENTPROC)(Display * dpy, GLXDrawable draw, unsigned long event_mask);
+typedef void (GLAD_API_PTR *PFNGLXSWAPBUFFERSPROC)(Display * dpy, GLXDrawable drawable);
+typedef void (GLAD_API_PTR *PFNGLXSWAPINTERVALEXTPROC)(Display * dpy, GLXDrawable drawable, int interval);
+typedef int (GLAD_API_PTR *PFNGLXSWAPINTERVALMESAPROC)(unsigned int interval);
+typedef int (GLAD_API_PTR *PFNGLXSWAPINTERVALSGIPROC)(int interval);
+typedef void (GLAD_API_PTR *PFNGLXUSEXFONTPROC)(Font font, int first, int count, int list);
+typedef void (GLAD_API_PTR *PFNGLXWAITGLPROC)(void);
+typedef void (GLAD_API_PTR *PFNGLXWAITXPROC)(void);
+
+GLAD_API_CALL PFNGLXCHOOSEFBCONFIGPROC glad_glXChooseFBConfig;
+#define glXChooseFBConfig glad_glXChooseFBConfig
+GLAD_API_CALL PFNGLXCHOOSEVISUALPROC glad_glXChooseVisual;
+#define glXChooseVisual glad_glXChooseVisual
+GLAD_API_CALL PFNGLXCOPYCONTEXTPROC glad_glXCopyContext;
+#define glXCopyContext glad_glXCopyContext
+GLAD_API_CALL PFNGLXCREATECONTEXTPROC glad_glXCreateContext;
+#define glXCreateContext glad_glXCreateContext
+GLAD_API_CALL PFNGLXCREATECONTEXTATTRIBSARBPROC glad_glXCreateContextAttribsARB;
+#define glXCreateContextAttribsARB glad_glXCreateContextAttribsARB
+GLAD_API_CALL PFNGLXCREATEGLXPIXMAPPROC glad_glXCreateGLXPixmap;
+#define glXCreateGLXPixmap glad_glXCreateGLXPixmap
+GLAD_API_CALL PFNGLXCREATENEWCONTEXTPROC glad_glXCreateNewContext;
+#define glXCreateNewContext glad_glXCreateNewContext
+GLAD_API_CALL PFNGLXCREATEPBUFFERPROC glad_glXCreatePbuffer;
+#define glXCreatePbuffer glad_glXCreatePbuffer
+GLAD_API_CALL PFNGLXCREATEPIXMAPPROC glad_glXCreatePixmap;
+#define glXCreatePixmap glad_glXCreatePixmap
+GLAD_API_CALL PFNGLXCREATEWINDOWPROC glad_glXCreateWindow;
+#define glXCreateWindow glad_glXCreateWindow
+GLAD_API_CALL PFNGLXDESTROYCONTEXTPROC glad_glXDestroyContext;
+#define glXDestroyContext glad_glXDestroyContext
+GLAD_API_CALL PFNGLXDESTROYGLXPIXMAPPROC glad_glXDestroyGLXPixmap;
+#define glXDestroyGLXPixmap glad_glXDestroyGLXPixmap
+GLAD_API_CALL PFNGLXDESTROYPBUFFERPROC glad_glXDestroyPbuffer;
+#define glXDestroyPbuffer glad_glXDestroyPbuffer
+GLAD_API_CALL PFNGLXDESTROYPIXMAPPROC glad_glXDestroyPixmap;
+#define glXDestroyPixmap glad_glXDestroyPixmap
+GLAD_API_CALL PFNGLXDESTROYWINDOWPROC glad_glXDestroyWindow;
+#define glXDestroyWindow glad_glXDestroyWindow
+GLAD_API_CALL PFNGLXGETCLIENTSTRINGPROC glad_glXGetClientString;
+#define glXGetClientString glad_glXGetClientString
+GLAD_API_CALL PFNGLXGETCONFIGPROC glad_glXGetConfig;
+#define glXGetConfig glad_glXGetConfig
+GLAD_API_CALL PFNGLXGETCURRENTCONTEXTPROC glad_glXGetCurrentContext;
+#define glXGetCurrentContext glad_glXGetCurrentContext
+GLAD_API_CALL PFNGLXGETCURRENTDISPLAYPROC glad_glXGetCurrentDisplay;
+#define glXGetCurrentDisplay glad_glXGetCurrentDisplay
+GLAD_API_CALL PFNGLXGETCURRENTDRAWABLEPROC glad_glXGetCurrentDrawable;
+#define glXGetCurrentDrawable glad_glXGetCurrentDrawable
+GLAD_API_CALL PFNGLXGETCURRENTREADDRAWABLEPROC glad_glXGetCurrentReadDrawable;
+#define glXGetCurrentReadDrawable glad_glXGetCurrentReadDrawable
+GLAD_API_CALL PFNGLXGETFBCONFIGATTRIBPROC glad_glXGetFBConfigAttrib;
+#define glXGetFBConfigAttrib glad_glXGetFBConfigAttrib
+GLAD_API_CALL PFNGLXGETFBCONFIGSPROC glad_glXGetFBConfigs;
+#define glXGetFBConfigs glad_glXGetFBConfigs
+GLAD_API_CALL PFNGLXGETPROCADDRESSPROC glad_glXGetProcAddress;
+#define glXGetProcAddress glad_glXGetProcAddress
+GLAD_API_CALL PFNGLXGETPROCADDRESSARBPROC glad_glXGetProcAddressARB;
+#define glXGetProcAddressARB glad_glXGetProcAddressARB
+GLAD_API_CALL PFNGLXGETSELECTEDEVENTPROC glad_glXGetSelectedEvent;
+#define glXGetSelectedEvent glad_glXGetSelectedEvent
+GLAD_API_CALL PFNGLXGETSWAPINTERVALMESAPROC glad_glXGetSwapIntervalMESA;
+#define glXGetSwapIntervalMESA glad_glXGetSwapIntervalMESA
+GLAD_API_CALL PFNGLXGETVISUALFROMFBCONFIGPROC glad_glXGetVisualFromFBConfig;
+#define glXGetVisualFromFBConfig glad_glXGetVisualFromFBConfig
+GLAD_API_CALL PFNGLXISDIRECTPROC glad_glXIsDirect;
+#define glXIsDirect glad_glXIsDirect
+GLAD_API_CALL PFNGLXMAKECONTEXTCURRENTPROC glad_glXMakeContextCurrent;
+#define glXMakeContextCurrent glad_glXMakeContextCurrent
+GLAD_API_CALL PFNGLXMAKECURRENTPROC glad_glXMakeCurrent;
+#define glXMakeCurrent glad_glXMakeCurrent
+GLAD_API_CALL PFNGLXQUERYCONTEXTPROC glad_glXQueryContext;
+#define glXQueryContext glad_glXQueryContext
+GLAD_API_CALL PFNGLXQUERYDRAWABLEPROC glad_glXQueryDrawable;
+#define glXQueryDrawable glad_glXQueryDrawable
+GLAD_API_CALL PFNGLXQUERYEXTENSIONPROC glad_glXQueryExtension;
+#define glXQueryExtension glad_glXQueryExtension
+GLAD_API_CALL PFNGLXQUERYEXTENSIONSSTRINGPROC glad_glXQueryExtensionsString;
+#define glXQueryExtensionsString glad_glXQueryExtensionsString
+GLAD_API_CALL PFNGLXQUERYSERVERSTRINGPROC glad_glXQueryServerString;
+#define glXQueryServerString glad_glXQueryServerString
+GLAD_API_CALL PFNGLXQUERYVERSIONPROC glad_glXQueryVersion;
+#define glXQueryVersion glad_glXQueryVersion
+GLAD_API_CALL PFNGLXSELECTEVENTPROC glad_glXSelectEvent;
+#define glXSelectEvent glad_glXSelectEvent
+GLAD_API_CALL PFNGLXSWAPBUFFERSPROC glad_glXSwapBuffers;
+#define glXSwapBuffers glad_glXSwapBuffers
+GLAD_API_CALL PFNGLXSWAPINTERVALEXTPROC glad_glXSwapIntervalEXT;
+#define glXSwapIntervalEXT glad_glXSwapIntervalEXT
+GLAD_API_CALL PFNGLXSWAPINTERVALMESAPROC glad_glXSwapIntervalMESA;
+#define glXSwapIntervalMESA glad_glXSwapIntervalMESA
+GLAD_API_CALL PFNGLXSWAPINTERVALSGIPROC glad_glXSwapIntervalSGI;
+#define glXSwapIntervalSGI glad_glXSwapIntervalSGI
+GLAD_API_CALL PFNGLXUSEXFONTPROC glad_glXUseXFont;
+#define glXUseXFont glad_glXUseXFont
+GLAD_API_CALL PFNGLXWAITGLPROC glad_glXWaitGL;
+#define glXWaitGL glad_glXWaitGL
+GLAD_API_CALL PFNGLXWAITXPROC glad_glXWaitX;
+#define glXWaitX glad_glXWaitX
+
+
+
+
+
+GLAD_API_CALL int gladLoadGLXUserPtr(Display *display, int screen, GLADuserptrloadfunc load, void *userptr);
+GLAD_API_CALL int gladLoadGLX(Display *display, int screen, GLADloadfunc load);
+
+#ifdef GLAD_GLX
+
+GLAD_API_CALL int gladLoaderLoadGLX(Display *display, int screen);
+
+GLAD_API_CALL void gladLoaderUnloadGLX(void);
+
+#endif
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/thirdparty/glad/glx.c b/thirdparty/glad/glx.c
new file mode 100644
index 0000000000..6391027db2
--- /dev/null
+++ b/thirdparty/glad/glx.c
@@ -0,0 +1,395 @@
+/**
+ * SPDX-License-Identifier: (WTFPL OR CC0-1.0) AND Apache-2.0
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <glad/glx.h>
+
+#ifndef GLAD_IMPL_UTIL_C_
+#define GLAD_IMPL_UTIL_C_
+
+#ifdef _MSC_VER
+#define GLAD_IMPL_UTIL_SSCANF sscanf_s
+#else
+#define GLAD_IMPL_UTIL_SSCANF sscanf
+#endif
+
+#endif /* GLAD_IMPL_UTIL_C_ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+
+int GLAD_GLX_VERSION_1_0 = 0;
+int GLAD_GLX_VERSION_1_1 = 0;
+int GLAD_GLX_VERSION_1_2 = 0;
+int GLAD_GLX_VERSION_1_3 = 0;
+int GLAD_GLX_VERSION_1_4 = 0;
+int GLAD_GLX_ARB_create_context = 0;
+int GLAD_GLX_ARB_create_context_profile = 0;
+int GLAD_GLX_ARB_get_proc_address = 0;
+int GLAD_GLX_EXT_swap_control = 0;
+int GLAD_GLX_MESA_swap_control = 0;
+int GLAD_GLX_SGI_swap_control = 0;
+
+
+
+PFNGLXCHOOSEFBCONFIGPROC glad_glXChooseFBConfig = NULL;
+PFNGLXCHOOSEVISUALPROC glad_glXChooseVisual = NULL;
+PFNGLXCOPYCONTEXTPROC glad_glXCopyContext = NULL;
+PFNGLXCREATECONTEXTPROC glad_glXCreateContext = NULL;
+PFNGLXCREATECONTEXTATTRIBSARBPROC glad_glXCreateContextAttribsARB = NULL;
+PFNGLXCREATEGLXPIXMAPPROC glad_glXCreateGLXPixmap = NULL;
+PFNGLXCREATENEWCONTEXTPROC glad_glXCreateNewContext = NULL;
+PFNGLXCREATEPBUFFERPROC glad_glXCreatePbuffer = NULL;
+PFNGLXCREATEPIXMAPPROC glad_glXCreatePixmap = NULL;
+PFNGLXCREATEWINDOWPROC glad_glXCreateWindow = NULL;
+PFNGLXDESTROYCONTEXTPROC glad_glXDestroyContext = NULL;
+PFNGLXDESTROYGLXPIXMAPPROC glad_glXDestroyGLXPixmap = NULL;
+PFNGLXDESTROYPBUFFERPROC glad_glXDestroyPbuffer = NULL;
+PFNGLXDESTROYPIXMAPPROC glad_glXDestroyPixmap = NULL;
+PFNGLXDESTROYWINDOWPROC glad_glXDestroyWindow = NULL;
+PFNGLXGETCLIENTSTRINGPROC glad_glXGetClientString = NULL;
+PFNGLXGETCONFIGPROC glad_glXGetConfig = NULL;
+PFNGLXGETCURRENTCONTEXTPROC glad_glXGetCurrentContext = NULL;
+PFNGLXGETCURRENTDISPLAYPROC glad_glXGetCurrentDisplay = NULL;
+PFNGLXGETCURRENTDRAWABLEPROC glad_glXGetCurrentDrawable = NULL;
+PFNGLXGETCURRENTREADDRAWABLEPROC glad_glXGetCurrentReadDrawable = NULL;
+PFNGLXGETFBCONFIGATTRIBPROC glad_glXGetFBConfigAttrib = NULL;
+PFNGLXGETFBCONFIGSPROC glad_glXGetFBConfigs = NULL;
+PFNGLXGETPROCADDRESSPROC glad_glXGetProcAddress = NULL;
+PFNGLXGETPROCADDRESSARBPROC glad_glXGetProcAddressARB = NULL;
+PFNGLXGETSELECTEDEVENTPROC glad_glXGetSelectedEvent = NULL;
+PFNGLXGETSWAPINTERVALMESAPROC glad_glXGetSwapIntervalMESA = NULL;
+PFNGLXGETVISUALFROMFBCONFIGPROC glad_glXGetVisualFromFBConfig = NULL;
+PFNGLXISDIRECTPROC glad_glXIsDirect = NULL;
+PFNGLXMAKECONTEXTCURRENTPROC glad_glXMakeContextCurrent = NULL;
+PFNGLXMAKECURRENTPROC glad_glXMakeCurrent = NULL;
+PFNGLXQUERYCONTEXTPROC glad_glXQueryContext = NULL;
+PFNGLXQUERYDRAWABLEPROC glad_glXQueryDrawable = NULL;
+PFNGLXQUERYEXTENSIONPROC glad_glXQueryExtension = NULL;
+PFNGLXQUERYEXTENSIONSSTRINGPROC glad_glXQueryExtensionsString = NULL;
+PFNGLXQUERYSERVERSTRINGPROC glad_glXQueryServerString = NULL;
+PFNGLXQUERYVERSIONPROC glad_glXQueryVersion = NULL;
+PFNGLXSELECTEVENTPROC glad_glXSelectEvent = NULL;
+PFNGLXSWAPBUFFERSPROC glad_glXSwapBuffers = NULL;
+PFNGLXSWAPINTERVALEXTPROC glad_glXSwapIntervalEXT = NULL;
+PFNGLXSWAPINTERVALMESAPROC glad_glXSwapIntervalMESA = NULL;
+PFNGLXSWAPINTERVALSGIPROC glad_glXSwapIntervalSGI = NULL;
+PFNGLXUSEXFONTPROC glad_glXUseXFont = NULL;
+PFNGLXWAITGLPROC glad_glXWaitGL = NULL;
+PFNGLXWAITXPROC glad_glXWaitX = NULL;
+
+
+static void glad_glx_load_GLX_VERSION_1_0( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GLX_VERSION_1_0) return;
+ glad_glXChooseVisual = (PFNGLXCHOOSEVISUALPROC) load(userptr, "glXChooseVisual");
+ glad_glXCopyContext = (PFNGLXCOPYCONTEXTPROC) load(userptr, "glXCopyContext");
+ glad_glXCreateContext = (PFNGLXCREATECONTEXTPROC) load(userptr, "glXCreateContext");
+ glad_glXCreateGLXPixmap = (PFNGLXCREATEGLXPIXMAPPROC) load(userptr, "glXCreateGLXPixmap");
+ glad_glXDestroyContext = (PFNGLXDESTROYCONTEXTPROC) load(userptr, "glXDestroyContext");
+ glad_glXDestroyGLXPixmap = (PFNGLXDESTROYGLXPIXMAPPROC) load(userptr, "glXDestroyGLXPixmap");
+ glad_glXGetConfig = (PFNGLXGETCONFIGPROC) load(userptr, "glXGetConfig");
+ glad_glXGetCurrentContext = (PFNGLXGETCURRENTCONTEXTPROC) load(userptr, "glXGetCurrentContext");
+ glad_glXGetCurrentDrawable = (PFNGLXGETCURRENTDRAWABLEPROC) load(userptr, "glXGetCurrentDrawable");
+ glad_glXIsDirect = (PFNGLXISDIRECTPROC) load(userptr, "glXIsDirect");
+ glad_glXMakeCurrent = (PFNGLXMAKECURRENTPROC) load(userptr, "glXMakeCurrent");
+ glad_glXQueryExtension = (PFNGLXQUERYEXTENSIONPROC) load(userptr, "glXQueryExtension");
+ glad_glXQueryVersion = (PFNGLXQUERYVERSIONPROC) load(userptr, "glXQueryVersion");
+ glad_glXSwapBuffers = (PFNGLXSWAPBUFFERSPROC) load(userptr, "glXSwapBuffers");
+ glad_glXUseXFont = (PFNGLXUSEXFONTPROC) load(userptr, "glXUseXFont");
+ glad_glXWaitGL = (PFNGLXWAITGLPROC) load(userptr, "glXWaitGL");
+ glad_glXWaitX = (PFNGLXWAITXPROC) load(userptr, "glXWaitX");
+}
+static void glad_glx_load_GLX_VERSION_1_1( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GLX_VERSION_1_1) return;
+ glad_glXGetClientString = (PFNGLXGETCLIENTSTRINGPROC) load(userptr, "glXGetClientString");
+ glad_glXQueryExtensionsString = (PFNGLXQUERYEXTENSIONSSTRINGPROC) load(userptr, "glXQueryExtensionsString");
+ glad_glXQueryServerString = (PFNGLXQUERYSERVERSTRINGPROC) load(userptr, "glXQueryServerString");
+}
+static void glad_glx_load_GLX_VERSION_1_2( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GLX_VERSION_1_2) return;
+ glad_glXGetCurrentDisplay = (PFNGLXGETCURRENTDISPLAYPROC) load(userptr, "glXGetCurrentDisplay");
+}
+static void glad_glx_load_GLX_VERSION_1_3( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GLX_VERSION_1_3) return;
+ glad_glXChooseFBConfig = (PFNGLXCHOOSEFBCONFIGPROC) load(userptr, "glXChooseFBConfig");
+ glad_glXCreateNewContext = (PFNGLXCREATENEWCONTEXTPROC) load(userptr, "glXCreateNewContext");
+ glad_glXCreatePbuffer = (PFNGLXCREATEPBUFFERPROC) load(userptr, "glXCreatePbuffer");
+ glad_glXCreatePixmap = (PFNGLXCREATEPIXMAPPROC) load(userptr, "glXCreatePixmap");
+ glad_glXCreateWindow = (PFNGLXCREATEWINDOWPROC) load(userptr, "glXCreateWindow");
+ glad_glXDestroyPbuffer = (PFNGLXDESTROYPBUFFERPROC) load(userptr, "glXDestroyPbuffer");
+ glad_glXDestroyPixmap = (PFNGLXDESTROYPIXMAPPROC) load(userptr, "glXDestroyPixmap");
+ glad_glXDestroyWindow = (PFNGLXDESTROYWINDOWPROC) load(userptr, "glXDestroyWindow");
+ glad_glXGetCurrentReadDrawable = (PFNGLXGETCURRENTREADDRAWABLEPROC) load(userptr, "glXGetCurrentReadDrawable");
+ glad_glXGetFBConfigAttrib = (PFNGLXGETFBCONFIGATTRIBPROC) load(userptr, "glXGetFBConfigAttrib");
+ glad_glXGetFBConfigs = (PFNGLXGETFBCONFIGSPROC) load(userptr, "glXGetFBConfigs");
+ glad_glXGetSelectedEvent = (PFNGLXGETSELECTEDEVENTPROC) load(userptr, "glXGetSelectedEvent");
+ glad_glXGetVisualFromFBConfig = (PFNGLXGETVISUALFROMFBCONFIGPROC) load(userptr, "glXGetVisualFromFBConfig");
+ glad_glXMakeContextCurrent = (PFNGLXMAKECONTEXTCURRENTPROC) load(userptr, "glXMakeContextCurrent");
+ glad_glXQueryContext = (PFNGLXQUERYCONTEXTPROC) load(userptr, "glXQueryContext");
+ glad_glXQueryDrawable = (PFNGLXQUERYDRAWABLEPROC) load(userptr, "glXQueryDrawable");
+ glad_glXSelectEvent = (PFNGLXSELECTEVENTPROC) load(userptr, "glXSelectEvent");
+}
+static void glad_glx_load_GLX_VERSION_1_4( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GLX_VERSION_1_4) return;
+ glad_glXGetProcAddress = (PFNGLXGETPROCADDRESSPROC) load(userptr, "glXGetProcAddress");
+}
+static void glad_glx_load_GLX_ARB_create_context( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GLX_ARB_create_context) return;
+ glad_glXCreateContextAttribsARB = (PFNGLXCREATECONTEXTATTRIBSARBPROC) load(userptr, "glXCreateContextAttribsARB");
+}
+static void glad_glx_load_GLX_ARB_get_proc_address( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GLX_ARB_get_proc_address) return;
+ glad_glXGetProcAddressARB = (PFNGLXGETPROCADDRESSARBPROC) load(userptr, "glXGetProcAddressARB");
+}
+static void glad_glx_load_GLX_EXT_swap_control( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GLX_EXT_swap_control) return;
+ glad_glXSwapIntervalEXT = (PFNGLXSWAPINTERVALEXTPROC) load(userptr, "glXSwapIntervalEXT");
+}
+static void glad_glx_load_GLX_MESA_swap_control( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GLX_MESA_swap_control) return;
+ glad_glXGetSwapIntervalMESA = (PFNGLXGETSWAPINTERVALMESAPROC) load(userptr, "glXGetSwapIntervalMESA");
+ glad_glXSwapIntervalMESA = (PFNGLXSWAPINTERVALMESAPROC) load(userptr, "glXSwapIntervalMESA");
+}
+static void glad_glx_load_GLX_SGI_swap_control( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GLX_SGI_swap_control) return;
+ glad_glXSwapIntervalSGI = (PFNGLXSWAPINTERVALSGIPROC) load(userptr, "glXSwapIntervalSGI");
+}
+
+
+
+static int glad_glx_has_extension(Display *display, int screen, const char *ext) {
+#ifndef GLX_VERSION_1_1
+ GLAD_UNUSED(display);
+ GLAD_UNUSED(screen);
+ GLAD_UNUSED(ext);
+#else
+ const char *terminator;
+ const char *loc;
+ const char *extensions;
+
+ if (glXQueryExtensionsString == NULL) {
+ return 0;
+ }
+
+ extensions = glXQueryExtensionsString(display, screen);
+
+ if(extensions == NULL || ext == NULL) {
+ return 0;
+ }
+
+ while(1) {
+ loc = strstr(extensions, ext);
+ if(loc == NULL)
+ break;
+
+ terminator = loc + strlen(ext);
+ if((loc == extensions || *(loc - 1) == ' ') &&
+ (*terminator == ' ' || *terminator == '\0')) {
+ return 1;
+ }
+ extensions = terminator;
+ }
+#endif
+
+ return 0;
+}
+
+static GLADapiproc glad_glx_get_proc_from_userptr(void *userptr, const char* name) {
+ return (GLAD_GNUC_EXTENSION (GLADapiproc (*)(const char *name)) userptr)(name);
+}
+
+static int glad_glx_find_extensions(Display *display, int screen) {
+ GLAD_GLX_ARB_create_context = glad_glx_has_extension(display, screen, "GLX_ARB_create_context");
+ GLAD_GLX_ARB_create_context_profile = glad_glx_has_extension(display, screen, "GLX_ARB_create_context_profile");
+ GLAD_GLX_ARB_get_proc_address = glad_glx_has_extension(display, screen, "GLX_ARB_get_proc_address");
+ GLAD_GLX_EXT_swap_control = glad_glx_has_extension(display, screen, "GLX_EXT_swap_control");
+ GLAD_GLX_MESA_swap_control = glad_glx_has_extension(display, screen, "GLX_MESA_swap_control");
+ GLAD_GLX_SGI_swap_control = glad_glx_has_extension(display, screen, "GLX_SGI_swap_control");
+ return 1;
+}
+
+static int glad_glx_find_core_glx(Display **display, int *screen) {
+ int major = 0, minor = 0;
+ if(*display == NULL) {
+#ifdef GLAD_GLX_NO_X11
+ GLAD_UNUSED(screen);
+ return 0;
+#else
+ *display = XOpenDisplay(0);
+ if (*display == NULL) {
+ return 0;
+ }
+ *screen = XScreenNumberOfScreen(XDefaultScreenOfDisplay(*display));
+#endif
+ }
+ glXQueryVersion(*display, &major, &minor);
+ GLAD_GLX_VERSION_1_0 = (major == 1 && minor >= 0) || major > 1;
+ GLAD_GLX_VERSION_1_1 = (major == 1 && minor >= 1) || major > 1;
+ GLAD_GLX_VERSION_1_2 = (major == 1 && minor >= 2) || major > 1;
+ GLAD_GLX_VERSION_1_3 = (major == 1 && minor >= 3) || major > 1;
+ GLAD_GLX_VERSION_1_4 = (major == 1 && minor >= 4) || major > 1;
+ return GLAD_MAKE_VERSION(major, minor);
+}
+
+int gladLoadGLXUserPtr(Display *display, int screen, GLADuserptrloadfunc load, void *userptr) {
+ int version;
+ glXQueryVersion = (PFNGLXQUERYVERSIONPROC) load(userptr, "glXQueryVersion");
+ if(glXQueryVersion == NULL) return 0;
+ version = glad_glx_find_core_glx(&display, &screen);
+
+ glad_glx_load_GLX_VERSION_1_0(load, userptr);
+ glad_glx_load_GLX_VERSION_1_1(load, userptr);
+ glad_glx_load_GLX_VERSION_1_2(load, userptr);
+ glad_glx_load_GLX_VERSION_1_3(load, userptr);
+ glad_glx_load_GLX_VERSION_1_4(load, userptr);
+
+ if (!glad_glx_find_extensions(display, screen)) return 0;
+ glad_glx_load_GLX_ARB_create_context(load, userptr);
+ glad_glx_load_GLX_ARB_get_proc_address(load, userptr);
+ glad_glx_load_GLX_EXT_swap_control(load, userptr);
+ glad_glx_load_GLX_MESA_swap_control(load, userptr);
+ glad_glx_load_GLX_SGI_swap_control(load, userptr);
+
+
+ return version;
+}
+
+int gladLoadGLX(Display *display, int screen, GLADloadfunc load) {
+ return gladLoadGLXUserPtr(display, screen, glad_glx_get_proc_from_userptr, GLAD_GNUC_EXTENSION (void*) load);
+}
+
+
+
+#ifdef GLAD_GLX
+
+#ifndef GLAD_LOADER_LIBRARY_C_
+#define GLAD_LOADER_LIBRARY_C_
+
+#include <stddef.h>
+#include <stdlib.h>
+
+#if GLAD_PLATFORM_WIN32
+#include <windows.h>
+#else
+#include <dlfcn.h>
+#endif
+
+
+static void* glad_get_dlopen_handle(const char *lib_names[], int length) {
+ void *handle = NULL;
+ int i;
+
+ for (i = 0; i < length; ++i) {
+#if GLAD_PLATFORM_WIN32
+ #if GLAD_PLATFORM_UWP
+ size_t buffer_size = (strlen(lib_names[i]) + 1) * sizeof(WCHAR);
+ LPWSTR buffer = (LPWSTR) malloc(buffer_size);
+ if (buffer != NULL) {
+ int ret = MultiByteToWideChar(CP_ACP, 0, lib_names[i], -1, buffer, buffer_size);
+ if (ret != 0) {
+ handle = (void*) LoadPackagedLibrary(buffer, 0);
+ }
+ free((void*) buffer);
+ }
+ #else
+ handle = (void*) LoadLibraryA(lib_names[i]);
+ #endif
+#else
+ handle = dlopen(lib_names[i], RTLD_LAZY | RTLD_LOCAL);
+#endif
+ if (handle != NULL) {
+ return handle;
+ }
+ }
+
+ return NULL;
+}
+
+static void glad_close_dlopen_handle(void* handle) {
+ if (handle != NULL) {
+#if GLAD_PLATFORM_WIN32
+ FreeLibrary((HMODULE) handle);
+#else
+ dlclose(handle);
+#endif
+ }
+}
+
+static GLADapiproc glad_dlsym_handle(void* handle, const char *name) {
+ if (handle == NULL) {
+ return NULL;
+ }
+
+#if GLAD_PLATFORM_WIN32
+ return (GLADapiproc) GetProcAddress((HMODULE) handle, name);
+#else
+ return GLAD_GNUC_EXTENSION (GLADapiproc) dlsym(handle, name);
+#endif
+}
+
+#endif /* GLAD_LOADER_LIBRARY_C_ */
+
+typedef void* (GLAD_API_PTR *GLADglxprocaddrfunc)(const char*);
+
+static GLADapiproc glad_glx_get_proc(void *userptr, const char *name) {
+ return GLAD_GNUC_EXTENSION ((GLADapiproc (*)(const char *name)) userptr)(name);
+}
+
+static void* _glx_handle;
+
+static void* glad_glx_dlopen_handle(void) {
+ static const char *NAMES[] = {
+#if defined __CYGWIN__
+ "libGL-1.so",
+#endif
+ "libGL.so.1",
+ "libGL.so"
+ };
+
+ if (_glx_handle == NULL) {
+ _glx_handle = glad_get_dlopen_handle(NAMES, sizeof(NAMES) / sizeof(NAMES[0]));
+ }
+
+ return _glx_handle;
+}
+
+int gladLoaderLoadGLX(Display *display, int screen) {
+ int version = 0;
+ void *handle = NULL;
+ int did_load = 0;
+ GLADglxprocaddrfunc loader;
+
+ did_load = _glx_handle == NULL;
+ handle = glad_glx_dlopen_handle();
+ if (handle != NULL) {
+ loader = (GLADglxprocaddrfunc) glad_dlsym_handle(handle, "glXGetProcAddressARB");
+ if (loader != NULL) {
+ version = gladLoadGLXUserPtr(display, screen, glad_glx_get_proc, GLAD_GNUC_EXTENSION (void*) loader);
+ }
+
+ if (!version && did_load) {
+ gladLoaderUnloadGLX();
+ }
+ }
+
+ return version;
+}
+
+
+void gladLoaderUnloadGLX() {
+ if (_glx_handle != NULL) {
+ glad_close_dlopen_handle(_glx_handle);
+ _glx_handle = NULL;
+ }
+}
+
+#endif /* GLAD_GLX */
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/thirdparty/graphite/include/graphite2/Font.h b/thirdparty/graphite/include/graphite2/Font.h
index fe569295a5..b0a1e36370 100644
--- a/thirdparty/graphite/include/graphite2/Font.h
+++ b/thirdparty/graphite/include/graphite2/Font.h
@@ -1,29 +1,5 @@
-/* GRAPHITE2 LICENSING
-
- Copyright 2010, SIL International
- All rights reserved.
-
- This library is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should also have received a copy of the GNU Lesser General Public
- License along with this library in the file named "LICENSE".
- If not, write to the Free Software Foundation, 51 Franklin Street,
- Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
- internet at http://www.fsf.org/licenses/lgpl.html.
-
- Alternatively, the contents of this file may be used under the terms
- of the Mozilla Public License (http://mozilla.org/MPL) or the GNU
- General Public License, as published by the Free Software Foundation,
- either version 2 of the License or (at your option) any later version.
-*/
+/* SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later */
+/* Copyright 2010, SIL International, All rights reserved. */
#pragma once
#include "graphite2/Types.h"
diff --git a/thirdparty/graphite/include/graphite2/Log.h b/thirdparty/graphite/include/graphite2/Log.h
index a5a6947fab..d83b1b90e7 100644
--- a/thirdparty/graphite/include/graphite2/Log.h
+++ b/thirdparty/graphite/include/graphite2/Log.h
@@ -1,29 +1,5 @@
-/* GRAPHITE2 LICENSING
-
- Copyright 2010, SIL International
- All rights reserved.
-
- This library is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should also have received a copy of the GNU Lesser General Public
- License along with this library in the file named "LICENSE".
- If not, write to the Free Software Foundation, 51 Franklin Street,
- Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
- internet at http://www.fsf.org/licenses/lgpl.html.
-
- Alternatively, the contents of this file may be used under the terms
- of the Mozilla Public License (http://mozilla.org/MPL) or the GNU
- General Public License, as published by the Free Software Foundation,
- either version 2 of the License or (at your option) any later version.
-*/
+/* SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later */
+/* Copyright 2010, SIL International, All rights reserved. */
#pragma once
#include <graphite2/Types.h>
diff --git a/thirdparty/graphite/include/graphite2/Segment.h b/thirdparty/graphite/include/graphite2/Segment.h
index 0e24f5d795..9969b4eb45 100644
--- a/thirdparty/graphite/include/graphite2/Segment.h
+++ b/thirdparty/graphite/include/graphite2/Segment.h
@@ -1,29 +1,5 @@
-/* GRAPHITE2 LICENSING
-
- Copyright 2010, SIL International
- All rights reserved.
-
- This library is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should also have received a copy of the GNU Lesser General Public
- License along with this library in the file named "LICENSE".
- If not, write to the Free Software Foundation, 51 Franklin Street,
- Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
- internet at http://www.fsf.org/licenses/lgpl.html.
-
- Alternatively, the contents of this file may be used under the terms
- of the Mozilla Public License (http://mozilla.org/MPL) or the GNU
- General Public License, as published by the Free Software Foundation,
- either version 2 of the License or (at your option) any later version.
-*/
+/* SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later */
+/* Copyright 2010, SIL International, All rights reserved. */
#pragma once
#include "graphite2/Types.h"
diff --git a/thirdparty/graphite/include/graphite2/Types.h b/thirdparty/graphite/include/graphite2/Types.h
index 916c91191b..32236a6195 100644
--- a/thirdparty/graphite/include/graphite2/Types.h
+++ b/thirdparty/graphite/include/graphite2/Types.h
@@ -1,29 +1,5 @@
-/* GRAPHITE2 LICENSING
-
- Copyright 2010, SIL International
- All rights reserved.
-
- This library is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should also have received a copy of the GNU Lesser General Public
- License along with this library in the file named "LICENSE".
- If not, write to the Free Software Foundation, 51 Franklin Street,
- Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
- internet at http://www.fsf.org/licenses/lgpl.html.
-
- Alternatively, the contents of this file may be used under the terms
- of the Mozilla Public License (http://mozilla.org/MPL) or the GNU
- General Public License, as published by the Free Software Foundation,
- either version 2 of the License or (at your option) any later version.
-*/
+/* SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later */
+/* Copyright 2010, SIL International, All rights reserved. */
#pragma once
#include <stddef.h>
diff --git a/thirdparty/graphite/src/CmapCache.cpp b/thirdparty/graphite/src/CmapCache.cpp
index d070019a34..ac860e9ee2 100644
--- a/thirdparty/graphite/src/CmapCache.cpp
+++ b/thirdparty/graphite/src/CmapCache.cpp
@@ -1,29 +1,6 @@
-/* GRAPHITE2 LICENSING
-
- Copyright 2010, SIL International
- All rights reserved.
-
- This library is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should also have received a copy of the GNU Lesser General Public
- License along with this library in the file named "LICENSE".
- If not, write to the Free Software Foundation, 51 Franklin Street,
- Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
- internet at http://www.fsf.org/licenses/lgpl.html.
-
-Alternatively, the contents of this file may be used under the terms of the
-Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
-License, as published by the Free Software Foundation, either version 2
-of the License or (at your option) any later version.
-*/
+// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
+// Copyright 2010, SIL International, All rights reserved.
+
#include "inc/Main.h"
#include "inc/CmapCache.h"
diff --git a/thirdparty/graphite/src/Code.cpp b/thirdparty/graphite/src/Code.cpp
index ec5ab298ca..4a53ae871b 100644
--- a/thirdparty/graphite/src/Code.cpp
+++ b/thirdparty/graphite/src/Code.cpp
@@ -1,29 +1,6 @@
-/* GRAPHITE2 LICENSING
-
- Copyright 2010, SIL International
- All rights reserved.
-
- This library is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should also have received a copy of the GNU Lesser General Public
- License along with this library in the file named "LICENSE".
- If not, write to the Free Software Foundation, 51 Franklin Street,
- Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
- internet at http://www.fsf.org/licenses/lgpl.html.
-
-Alternatively, the contents of this file may be used under the terms of the
-Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
-License, as published by the Free Software Foundation, either version 2
-of the License or (at your option) any later version.
-*/
+// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
+// Copyright 2010, SIL International, All rights reserved.
+
// This class represents loaded graphite stack machine code. It performs
// basic sanity checks, on the incoming code to prevent more obvious problems
// from crashing graphite.
diff --git a/thirdparty/graphite/src/Collider.cpp b/thirdparty/graphite/src/Collider.cpp
index 1929b39a58..ca36d4550a 100644
--- a/thirdparty/graphite/src/Collider.cpp
+++ b/thirdparty/graphite/src/Collider.cpp
@@ -1,29 +1,6 @@
-/* GRAPHITE2 LICENSING
-
- Copyright 2010, SIL International
- All rights reserved.
-
- This library is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should also have received a copy of the GNU Lesser General Public
- License along with this library in the file named "LICENSE".
- If not, write to the Free Software Foundation, 51 Franklin Street,
- Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
- internet at http://www.fsf.org/licenses/lgpl.html.
-
-Alternatively, the contents of this file may be used under the terms of the
-Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
-License, as published by the Free Software Foundation, either version 2
-of the License or (at your option) any later version.
-*/
+// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
+// Copyright 2010, SIL International, All rights reserved.
+
#include <algorithm>
#include <limits>
#include <cmath>
diff --git a/thirdparty/graphite/src/Decompressor.cpp b/thirdparty/graphite/src/Decompressor.cpp
index 42dc9113e5..f9f1e28e5b 100644
--- a/thirdparty/graphite/src/Decompressor.cpp
+++ b/thirdparty/graphite/src/Decompressor.cpp
@@ -1,29 +1,6 @@
-/* GRAPHITE2 LICENSING
-
- Copyright 2015, SIL International
- All rights reserved.
-
- This library is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should also have received a copy of the GNU Lesser General Public
- License along with this library in the file named "LICENSE".
- If not, write to the Free Software Foundation, 51 Franklin Street,
- Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
- internet at http://www.fsf.org/licenses/lgpl.html.
-
-Alternatively, the contents of this file may be used under the terms of the
-Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
-License, as published by the Free Software Foundation, either version 2
-of the License or (at your option) any later version.
-*/
+// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
+// Copyright 2015, SIL International, All rights reserved.
+
#include <cassert>
#include "inc/Decompressor.h"
diff --git a/thirdparty/graphite/src/Face.cpp b/thirdparty/graphite/src/Face.cpp
index 3e106050d7..4dd5a780cf 100644
--- a/thirdparty/graphite/src/Face.cpp
+++ b/thirdparty/graphite/src/Face.cpp
@@ -1,29 +1,6 @@
-/* GRAPHITE2 LICENSING
-
- Copyright 2010, SIL International
- All rights reserved.
-
- This library is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should also have received a copy of the GNU Lesser General Public
- License along with this library in the file named "LICENSE".
- If not, write to the Free Software Foundation, 51 Franklin Street,
- Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
- internet at http://www.fsf.org/licenses/lgpl.html.
-
-Alternatively, the contents of this file may be used under the terms of the
-Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
-License, as published by the Free Software Foundation, either version 2
-of the License or (at your option) any later version.
-*/
+// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
+// Copyright 2010, SIL International, All rights reserved.
+
#include <cstring>
#include "graphite2/Segment.h"
#include "inc/CmapCache.h"
diff --git a/thirdparty/graphite/src/FeatureMap.cpp b/thirdparty/graphite/src/FeatureMap.cpp
index 014a88fd08..992be05540 100644
--- a/thirdparty/graphite/src/FeatureMap.cpp
+++ b/thirdparty/graphite/src/FeatureMap.cpp
@@ -1,29 +1,6 @@
-/* GRAPHITE2 LICENSING
-
- Copyright 2010, SIL International
- All rights reserved.
-
- This library is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should also have received a copy of the GNU Lesser General Public
- License along with this library in the file named "LICENSE".
- If not, write to the Free Software Foundation, 51 Franklin Street,
- Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
- internet at http://www.fsf.org/licenses/lgpl.html.
-
-Alternatively, the contents of this file may be used under the terms of the
-Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
-License, as published by the Free Software Foundation, either version 2
-of the License or (at your option) any later version.
-*/
+// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
+// Copyright 2010, SIL International, All rights reserved.
+
#include <cstring>
#include "inc/Main.h"
diff --git a/thirdparty/graphite/src/FileFace.cpp b/thirdparty/graphite/src/FileFace.cpp
index 7e663876a7..2e41044688 100644
--- a/thirdparty/graphite/src/FileFace.cpp
+++ b/thirdparty/graphite/src/FileFace.cpp
@@ -1,29 +1,6 @@
-/* GRAPHITE2 LICENSING
-
- Copyright 2012, SIL International
- All rights reserved.
-
- This library is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should also have received a copy of the GNU Lesser General Public
- License along with this library in the file named "LICENSE".
- If not, write to the Free Software Foundation, 51 Franklin Street,
- Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
- internet at http://www.fsf.org/licenses/lgpl.html.
-
-Alternatively, the contents of this file may be used under the terms of the
-Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
-License, as published by the Free Software Foundation, either version 2
-of the License or (at your option) any later version.
-*/
+// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
+// Copyright 2012, SIL International, All rights reserved.
+
#include <cstring>
#include "inc/FileFace.h"
diff --git a/thirdparty/graphite/src/Font.cpp b/thirdparty/graphite/src/Font.cpp
index faf3715f9d..bffb4223d5 100644
--- a/thirdparty/graphite/src/Font.cpp
+++ b/thirdparty/graphite/src/Font.cpp
@@ -1,29 +1,6 @@
-/* GRAPHITE2 LICENSING
+// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
+// Copyright 2010, SIL International, All rights reserved.
- Copyright 2010, SIL International
- All rights reserved.
-
- This library is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should also have received a copy of the GNU Lesser General Public
- License along with this library in the file named "LICENSE".
- If not, write to the Free Software Foundation, 51 Franklin Street,
- Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
- internet at http://www.fsf.org/licenses/lgpl.html.
-
-Alternatively, the contents of this file may be used under the terms of the
-Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
-License, as published by the Free Software Foundation, either version 2
-of the License or (at your option) any later version.
-*/
#include "inc/Face.h"
#include "inc/Font.h"
#include "inc/GlyphCache.h"
diff --git a/thirdparty/graphite/src/GlyphCache.cpp b/thirdparty/graphite/src/GlyphCache.cpp
index 282bdc18fd..30479bdc4d 100644
--- a/thirdparty/graphite/src/GlyphCache.cpp
+++ b/thirdparty/graphite/src/GlyphCache.cpp
@@ -1,29 +1,6 @@
-/* GRAPHITE2 LICENSING
-
- Copyright 2012, SIL International
- All rights reserved.
-
- This library is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should also have received a copy of the GNU Lesser General Public
- License along with this library in the file named "LICENSE".
- If not, write to the Free Software Foundation, 51 Franklin Street,
- Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
- internet at http://www.fsf.org/licenses/lgpl.html.
-
-Alternatively, the contents of this file may be used under the terms of the
-Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
-License, as published by the Free Software Foundation, either version 2
-of the License or (at your option) any later version.
-*/
+// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
+// Copyright 2012, SIL International, All rights reserved.
+
#include "graphite2/Font.h"
#include "inc/Main.h"
@@ -44,12 +21,18 @@ namespace
// variable length structures.
template<typename W>
- class _glat_iterator : public std::iterator<std::input_iterator_tag, std::pair<sparse::key_type, sparse::mapped_type> >
+ class _glat_iterator
{
unsigned short key() const { return uint16(be::peek<W>(_e) + _n); }
unsigned int run() const { return be::peek<W>(_e+sizeof(W)); }
void advance_entry() { _n = 0; _e = _v; be::skip<W>(_v,2); }
public:
+ using iterator_category = std::input_iterator_tag;
+ using value_type = std::pair<sparse::key_type, sparse::mapped_type>;
+ using difference_type = ptrdiff_t;
+ using pointer = value_type *;
+ using reference = value_type &;
+
_glat_iterator(const void * glat=0) : _e(reinterpret_cast<const byte *>(glat)), _v(_e+2*sizeof(W)), _n(0) {}
_glat_iterator<W> & operator ++ () {
diff --git a/thirdparty/graphite/src/GlyphFace.cpp b/thirdparty/graphite/src/GlyphFace.cpp
index bc5e63a9f0..d9408f556b 100644
--- a/thirdparty/graphite/src/GlyphFace.cpp
+++ b/thirdparty/graphite/src/GlyphFace.cpp
@@ -1,29 +1,6 @@
-/* GRAPHITE2 LICENSING
+// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
+// Copyright 2010, SIL International, All rights reserved.
- Copyright 2010, SIL International
- All rights reserved.
-
- This library is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should also have received a copy of the GNU Lesser General Public
- License along with this library in the file named "LICENSE".
- If not, write to the Free Software Foundation, 51 Franklin Street,
- Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
- internet at http://www.fsf.org/licenses/lgpl.html.
-
-Alternatively, the contents of this file may be used under the terms of the
-Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
-License, as published by the Free Software Foundation, either version 2
-of the License or (at your option) any later version.
-*/
#include "inc/GlyphFace.h"
diff --git a/thirdparty/graphite/src/Intervals.cpp b/thirdparty/graphite/src/Intervals.cpp
index 0fe99a127a..b223a67f56 100644
--- a/thirdparty/graphite/src/Intervals.cpp
+++ b/thirdparty/graphite/src/Intervals.cpp
@@ -1,29 +1,6 @@
-/* GRAPHITE2 LICENSING
-
- Copyright 2010, SIL International
- All rights reserved.
-
- This library is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should also have received a copy of the GNU Lesser General Public
- License along with this library in the file named "LICENSE".
- If not, write to the Free Software Foundation, 51 Franklin Street,
- Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
- internet at http://www.fsf.org/licenses/lgpl.html.
-
-Alternatively, the contents of this file may be used under the terms of the
-Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
-License, as published by the Free Software Foundation, either version 2
-of the License or (at your option) any later version.
-*/
+// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
+// Copyright 2010, SIL International, All rights reserved.
+
#include <algorithm>
#include <cmath>
#include <limits>
diff --git a/thirdparty/graphite/src/Justifier.cpp b/thirdparty/graphite/src/Justifier.cpp
index 78c11e6a51..0bb18225b9 100644
--- a/thirdparty/graphite/src/Justifier.cpp
+++ b/thirdparty/graphite/src/Justifier.cpp
@@ -1,29 +1,6 @@
-/* GRAPHITE2 LICENSING
+// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
+// Copyright 2012, SIL International, All rights reserved.
- Copyright 2012, SIL International
- All rights reserved.
-
- This library is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should also have received a copy of the GNU Lesser General Public
- License along with this library in the file named "LICENSE".
- If not, write to the Free Software Foundation, 51 Franklin Street,
- Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
- internet at http://www.fsf.org/licenses/lgpl.html.
-
-Alternatively, the contents of this file may be used under the terms of the
-Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
-License, as published by the Free Software Foundation, either version 2
-of the License or (at your option) any later version.
-*/
#include "inc/Segment.h"
#include "graphite2/Font.h"
diff --git a/thirdparty/graphite/src/NameTable.cpp b/thirdparty/graphite/src/NameTable.cpp
index d42b7f95bd..85892f179c 100644
--- a/thirdparty/graphite/src/NameTable.cpp
+++ b/thirdparty/graphite/src/NameTable.cpp
@@ -1,29 +1,6 @@
-/* GRAPHITE2 LICENSING
+// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
+// Copyright 2010, SIL International, All rights reserved.
- Copyright 2010, SIL International
- All rights reserved.
-
- This library is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should also have received a copy of the GNU Lesser General Public
- License along with this library in the file named "LICENSE".
- If not, write to the Free Software Foundation, 51 Franklin Street,
- Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
- internet at http://www.fsf.org/licenses/lgpl.html.
-
-Alternatively, the contents of this file may be used under the terms of the
-Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
-License, as published by the Free Software Foundation, either version 2
-of the License or (at your option) any later version.
-*/
#include "inc/Main.h"
#include "inc/Endian.h"
diff --git a/thirdparty/graphite/src/Pass.cpp b/thirdparty/graphite/src/Pass.cpp
index 47ae2064f7..986fed83b1 100644
--- a/thirdparty/graphite/src/Pass.cpp
+++ b/thirdparty/graphite/src/Pass.cpp
@@ -1,29 +1,6 @@
-/* GRAPHITE2 LICENSING
-
- Copyright 2010, SIL International
- All rights reserved.
-
- This library is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should also have received a copy of the GNU Lesser General Public
- License along with this library in the file named "LICENSE".
- If not, write to the Free Software Foundation, 51 Franklin Street,
- Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
- internet at http://www.fsf.org/licenses/lgpl.html.
-
-Alternatively, the contents of this file may be used under the terms of the
-Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
-License, as published by the Free Software Foundation, either version 2
-of the License or (at your option) any later version.
-*/
+// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
+// Copyright 2010, SIL International, All rights reserved.
+
#include "inc/Main.h"
#include "inc/debug.h"
#include "inc/Endian.h"
@@ -194,7 +171,7 @@ bool Pass::readPass(const byte * const pass_start, size_t pass_length, size_t su
m_cPConstraint = vm::Machine::Code(true, pcCode, pcCode + pass_constraint_len,
precontext[0], be::peek<uint16>(sort_keys), *m_silf, face, PASS_TYPE_UNKNOWN);
if (e.test(!m_cPConstraint, E_OUTOFMEM)
- || e.test(m_cPConstraint.status() != Code::loaded, m_cPConstraint.status() + E_CODEFAILURE))
+ || e.test(m_cPConstraint.status() != Code::loaded, int(m_cPConstraint.status()) + E_CODEFAILURE))
return face.error(e);
face.error_context(face.error_context() - 1);
}
@@ -266,8 +243,8 @@ bool Pass::readRules(const byte * rule_map, const size_t num_entries,
r->constraint = new (m_codes+n*2-1) vm::Machine::Code(true, rc_begin, rc_end, r->preContext, r->sort, *m_silf, face, pt, &prog_pool_free);
if (e.test(!r->action || !r->constraint, E_OUTOFMEM)
- || e.test(r->action->status() != Code::loaded, r->action->status() + E_CODEFAILURE)
- || e.test(r->constraint->status() != Code::loaded, r->constraint->status() + E_CODEFAILURE)
+ || e.test(r->action->status() != Code::loaded, int(r->action->status()) + E_CODEFAILURE)
+ || e.test(r->constraint->status() != Code::loaded, int(r->constraint->status()) + E_CODEFAILURE)
|| e.test(!r->constraint->immutable(), E_MUTABLECCODE))
return face.error(e);
}
diff --git a/thirdparty/graphite/src/Position.cpp b/thirdparty/graphite/src/Position.cpp
index d2fdbd4e7c..a727f61664 100644
--- a/thirdparty/graphite/src/Position.cpp
+++ b/thirdparty/graphite/src/Position.cpp
@@ -1,29 +1,6 @@
-/* GRAPHITE2 LICENSING
+// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
+// Copyright 2010, SIL International, All rights reserved.
- Copyright 2010, SIL International
- All rights reserved.
-
- This library is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should also have received a copy of the GNU Lesser General Public
- License along with this library in the file named "LICENSE".
- If not, write to the Free Software Foundation, 51 Franklin Street,
- Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
- internet at http://www.fsf.org/licenses/lgpl.html.
-
-Alternatively, the contents of this file may be used under the terms of the
-Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
-License, as published by the Free Software Foundation, either version 2
-of the License or (at your option) any later version.
-*/
#include "inc/Position.h"
#include <cmath>
diff --git a/thirdparty/graphite/src/Segment.cpp b/thirdparty/graphite/src/Segment.cpp
index 62edd4250f..7bb3d132fa 100644
--- a/thirdparty/graphite/src/Segment.cpp
+++ b/thirdparty/graphite/src/Segment.cpp
@@ -1,29 +1,6 @@
-/* GRAPHITE2 LICENSING
-
- Copyright 2010, SIL International
- All rights reserved.
-
- This library is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should also have received a copy of the GNU Lesser General Public
- License along with this library in the file named "LICENSE".
- If not, write to the Free Software Foundation, 51 Franklin Street,
- Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
- internet at http://www.fsf.org/licenses/lgpl.html.
-
-Alternatively, the contents of this file may be used under the terms of the
-Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
-License, as published by the Free Software Foundation, either version 2
-of the License or (at your option) any later version.
-*/
+// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
+// Copyright 2010, SIL International, All rights reserved.
+
#include "inc/UtfCodec.h"
#include <cstring>
#include <cstdlib>
diff --git a/thirdparty/graphite/src/Silf.cpp b/thirdparty/graphite/src/Silf.cpp
index 44d3c96171..51a7473627 100644
--- a/thirdparty/graphite/src/Silf.cpp
+++ b/thirdparty/graphite/src/Silf.cpp
@@ -1,29 +1,6 @@
-/* GRAPHITE2 LICENSING
-
- Copyright 2010, SIL International
- All rights reserved.
-
- This library is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should also have received a copy of the GNU Lesser General Public
- License along with this library in the file named "LICENSE".
- If not, write to the Free Software Foundation, 51 Franklin Street,
- Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
- internet at http://www.fsf.org/licenses/lgpl.html.
-
-Alternatively, the contents of this file may be used under the terms of the
-Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
-License, as published by the Free Software Foundation, either version 2
-of the License or (at your option) any later version.
-*/
+// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
+// Copyright 2010, SIL International, All rights reserved.
+
#include <cstdlib>
#include "graphite2/Segment.h"
#include "inc/debug.h"
diff --git a/thirdparty/graphite/src/Slot.cpp b/thirdparty/graphite/src/Slot.cpp
index 0fdb098952..040e90d109 100644
--- a/thirdparty/graphite/src/Slot.cpp
+++ b/thirdparty/graphite/src/Slot.cpp
@@ -1,29 +1,6 @@
-/* GRAPHITE2 LICENSING
-
- Copyright 2010, SIL International
- All rights reserved.
-
- This library is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should also have received a copy of the GNU Lesser General Public
- License along with this library in the file named "LICENSE".
- If not, write to the Free Software Foundation, 51 Franklin Street,
- Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
- internet at http://www.fsf.org/licenses/lgpl.html.
-
-Alternatively, the contents of this file may be used under the terms of the
-Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
-License, as published by the Free Software Foundation, either version 2
-of the License or (at your option) any later version.
-*/
+// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
+// Copyright 2010, SIL International, All rights reserved.
+
#include "inc/Segment.h"
#include "inc/Slot.h"
#include "inc/Silf.h"
diff --git a/thirdparty/graphite/src/Sparse.cpp b/thirdparty/graphite/src/Sparse.cpp
index aa43113669..746dfc9522 100644
--- a/thirdparty/graphite/src/Sparse.cpp
+++ b/thirdparty/graphite/src/Sparse.cpp
@@ -1,29 +1,6 @@
-/* GRAPHITE2 LICENSING
-
- Copyright 2011, SIL International
- All rights reserved.
-
- This library is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should also have received a copy of the GNU Lesser General Public
- License along with this library in the file named "LICENSE".
- If not, write to the Free Software Foundation, 51 Franklin Street,
- Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
- internet at http://www.fsf.org/licenses/lgpl.html.
-
-Alternatively, the contents of this file may be used under the terms of the
-Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
-License, as published by the Free Software Foundation, either version 2
-of the License or (at your option) any later version.
-*/
+// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
+// Copyright 2011, SIL International, All rights reserved.
+
#include <cassert>
#include "inc/Sparse.h"
#include "inc/bits.h"
diff --git a/thirdparty/graphite/src/TtfUtil.cpp b/thirdparty/graphite/src/TtfUtil.cpp
index 2eb46a11fb..47940112ee 100644
--- a/thirdparty/graphite/src/TtfUtil.cpp
+++ b/thirdparty/graphite/src/TtfUtil.cpp
@@ -1,39 +1,14 @@
-/* GRAPHITE2 LICENSING
-
- Copyright 2010, SIL International
- All rights reserved.
-
- This library is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should also have received a copy of the GNU Lesser General Public
- License along with this library in the file named "LICENSE".
- If not, write to the Free Software Foundation, 51 Franklin Street,
- Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
- internet at http://www.fsf.org/licenses/lgpl.html.
-
-Alternatively, the contents of this file may be used under the terms of the
-Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
-License, as published by the Free Software Foundation, either version 2
-of the License or (at your option) any later version.
-*/
-/*--------------------------------------------------------------------*//*:Ignore this sentence.
+// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
+// Copyright 2010, SIL International, All rights reserved.
-File: TtfUtil.cpp
+/*
Responsibility: Alan Ward
Last reviewed: Not yet.
Description
Implements the methods for TtfUtil class. This file should remain portable to any C++
environment by only using standard C++ and the TTF structurs defined in Tt.h.
--------------------------------------------------------------------------------*//*:End Ignore*/
+*/
/***********************************************************************************************
diff --git a/thirdparty/graphite/src/UtfCodec.cpp b/thirdparty/graphite/src/UtfCodec.cpp
index a944bbf9d0..9156bad00f 100644
--- a/thirdparty/graphite/src/UtfCodec.cpp
+++ b/thirdparty/graphite/src/UtfCodec.cpp
@@ -1,29 +1,6 @@
-/* GRAPHITE2 LICENSING
+// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
+// Copyright 2010, SIL International, All rights reserved.
- Copyright 2010, SIL International
- All rights reserved.
-
- This library is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should also have received a copy of the GNU Lesser General Public
- License along with this library in the file named "LICENSE".
- If not, write to the Free Software Foundation, 51 Franklin Street,
- Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
- internet at http://www.fsf.org/licenses/lgpl.html.
-
-Alternatively, the contents of this file may be used under the terms of the
-Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
-License, as published by the Free Software Foundation, either version 2
-of the License or (at your option) any later version.
-*/
#include "inc/UtfCodec.h"
//using namespace graphite2;
diff --git a/thirdparty/graphite/src/call_machine.cpp b/thirdparty/graphite/src/call_machine.cpp
index fcd8a0c2c1..7d9d1ef315 100644
--- a/thirdparty/graphite/src/call_machine.cpp
+++ b/thirdparty/graphite/src/call_machine.cpp
@@ -1,29 +1,6 @@
-/* GRAPHITE2 LICENSING
-
- Copyright 2010, SIL International
- All rights reserved.
-
- This library is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should also have received a copy of the GNU Lesser General Public
- License along with this library in the file named "LICENSE".
- If not, write to the Free Software Foundation, 51 Franklin Street,
- Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
- internet at http://www.fsf.org/licenses/lgpl.html.
-
-Alternatively, the contents of this file may be used under the terms of the
-Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
-License, as published by the Free Software Foundation, either version 2
-of the License or (at your option) any later version.
-*/
+// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
+// Copyright 2010, SIL International, All rights reserved.
+
// This call threaded interpreter implmentation for machine.h
// Author: Tim Eves
diff --git a/thirdparty/graphite/src/direct_machine.cpp b/thirdparty/graphite/src/direct_machine.cpp
index 86206cfe37..e3a28fa536 100644
--- a/thirdparty/graphite/src/direct_machine.cpp
+++ b/thirdparty/graphite/src/direct_machine.cpp
@@ -1,29 +1,6 @@
-/* GRAPHITE2 LICENSING
-
- Copyright 2010, SIL International
- All rights reserved.
-
- This library is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should also have received a copy of the GNU Lesser General Public
- License along with this library in the file named "LICENSE".
- If not, write to the Free Software Foundation, 51 Franklin Street,
- Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
- internet at http://www.fsf.org/licenses/lgpl.html.
-
-Alternatively, the contents of this file may be used under the terms of the
-Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
-License, as published by the Free Software Foundation, either version 2
-of the License or (at your option) any later version.
-*/
+// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
+// Copyright 2010, SIL International, All rights reserved.
+
// This direct threaded interpreter implmentation for machine.h
// Author: Tim Eves
diff --git a/thirdparty/graphite/src/gr_char_info.cpp b/thirdparty/graphite/src/gr_char_info.cpp
index 612f9ba694..1345fae847 100644
--- a/thirdparty/graphite/src/gr_char_info.cpp
+++ b/thirdparty/graphite/src/gr_char_info.cpp
@@ -1,29 +1,6 @@
-/* GRAPHITE2 LICENSING
+// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
+// Copyright 2010, SIL International, All rights reserved.
- Copyright 2010, SIL International
- All rights reserved.
-
- This library is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should also have received a copy of the GNU Lesser General Public
- License along with this library in the file named "LICENSE".
- If not, write to the Free Software Foundation, 51 Franklin Street,
- Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
- internet at http://www.fsf.org/licenses/lgpl.html.
-
-Alternatively, the contents of this file may be used under the terms of the
-Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
-License, as published by the Free Software Foundation, either version 2
-of the License or (at your option) any later version.
-*/
#include <cassert>
#include "graphite2/Segment.h"
#include "inc/CharInfo.h"
diff --git a/thirdparty/graphite/src/gr_face.cpp b/thirdparty/graphite/src/gr_face.cpp
index baa469727b..6e80036113 100644
--- a/thirdparty/graphite/src/gr_face.cpp
+++ b/thirdparty/graphite/src/gr_face.cpp
@@ -1,29 +1,6 @@
-/* GRAPHITE2 LICENSING
-
- Copyright 2010, SIL International
- All rights reserved.
-
- This library is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should also have received a copy of the GNU Lesser General Public
- License along with this library in the file named "LICENSE".
- If not, write to the Free Software Foundation, 51 Franklin Street,
- Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
- internet at http://www.fsf.org/licenses/lgpl.html.
-
-Alternatively, the contents of this file may be used under the terms of the
-Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
-License, as published by the Free Software Foundation, either version 2
-of the License or (at your option) any later version.
-*/
+// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
+// Copyright 2010, SIL International, All rights reserved.
+
#include "graphite2/Font.h"
#include "inc/Face.h"
#include "inc/FileFace.h"
diff --git a/thirdparty/graphite/src/gr_features.cpp b/thirdparty/graphite/src/gr_features.cpp
index a560e053f2..67208f14e6 100644
--- a/thirdparty/graphite/src/gr_features.cpp
+++ b/thirdparty/graphite/src/gr_features.cpp
@@ -1,29 +1,6 @@
-/* GRAPHITE2 LICENSING
-
- Copyright 2010, SIL International
- All rights reserved.
-
- This library is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should also have received a copy of the GNU Lesser General Public
- License along with this library in the file named "LICENSE".
- If not, write to the Free Software Foundation, 51 Franklin Street,
- Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
- internet at http://www.fsf.org/licenses/lgpl.html.
-
-Alternatively, the contents of this file may be used under the terms of the
-Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
-License, as published by the Free Software Foundation, either version 2
-of the License or (at your option) any later version.
-*/
+// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
+// Copyright 2010, SIL International, All rights reserved.
+
#include "graphite2/Font.h"
#include "inc/Face.h"
#include "inc/FeatureMap.h"
diff --git a/thirdparty/graphite/src/gr_font.cpp b/thirdparty/graphite/src/gr_font.cpp
index 724cc83c13..fc85112e24 100644
--- a/thirdparty/graphite/src/gr_font.cpp
+++ b/thirdparty/graphite/src/gr_font.cpp
@@ -1,29 +1,6 @@
-/* GRAPHITE2 LICENSING
+// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
+// Copyright 2010, SIL International, All rights reserved.
- Copyright 2010, SIL International
- All rights reserved.
-
- This library is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should also have received a copy of the GNU Lesser General Public
- License along with this library in the file named "LICENSE".
- If not, write to the Free Software Foundation, 51 Franklin Street,
- Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
- internet at http://www.fsf.org/licenses/lgpl.html.
-
-Alternatively, the contents of this file may be used under the terms of the
-Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
-License, as published by the Free Software Foundation, either version 2
-of the License or (at your option) any later version.
-*/
#include "graphite2/Font.h"
#include "inc/Font.h"
diff --git a/thirdparty/graphite/src/gr_logging.cpp b/thirdparty/graphite/src/gr_logging.cpp
index 8f1e675e62..c6f03fd616 100644
--- a/thirdparty/graphite/src/gr_logging.cpp
+++ b/thirdparty/graphite/src/gr_logging.cpp
@@ -1,29 +1,6 @@
-/* GRAPHITE2 LICENSING
+// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
+// Copyright 2010, SIL International, All rights reserved.
- Copyright 2010, SIL International
- All rights reserved.
-
- This library is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should also have received a copy of the GNU Lesser General Public
- License along with this library in the file named "LICENSE".
- If not, write to the Free Software Foundation, 51 Franklin Street,
- Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
- internet at http://www.fsf.org/licenses/lgpl.html.
-
-Alternatively, the contents of this file may be used under the terms of the
-Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
-License, as published by the Free Software Foundation, either version 2
-of the License or (at your option) any later version.
-*/
#include <cstdio>
#include "graphite2/Log.h"
diff --git a/thirdparty/graphite/src/gr_segment.cpp b/thirdparty/graphite/src/gr_segment.cpp
index 7a27e9c562..7592296c04 100644
--- a/thirdparty/graphite/src/gr_segment.cpp
+++ b/thirdparty/graphite/src/gr_segment.cpp
@@ -1,29 +1,6 @@
-/* GRAPHITE2 LICENSING
-
- Copyright 2010, SIL International
- All rights reserved.
-
- This library is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should also have received a copy of the GNU Lesser General Public
- License along with this library in the file named "LICENSE".
- If not, write to the Free Software Foundation, 51 Franklin Street,
- Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
- internet at http://www.fsf.org/licenses/lgpl.html.
-
-Alternatively, the contents of this file may be used under the terms of the
-Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
-License, as published by the Free Software Foundation, either version 2
-of the License or (at your option) any later version.
-*/
+// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
+// Copyright 2010, SIL International, All rights reserved.
+
#include "graphite2/Segment.h"
#include "inc/UtfCodec.h"
#include "inc/Segment.h"
diff --git a/thirdparty/graphite/src/gr_slot.cpp b/thirdparty/graphite/src/gr_slot.cpp
index a3c6b46a7f..a6adefec61 100644
--- a/thirdparty/graphite/src/gr_slot.cpp
+++ b/thirdparty/graphite/src/gr_slot.cpp
@@ -1,29 +1,6 @@
-/* GRAPHITE2 LICENSING
-
- Copyright 2010, SIL International
- All rights reserved.
-
- This library is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should also have received a copy of the GNU Lesser General Public
- License along with this library in the file named "LICENSE".
- If not, write to the Free Software Foundation, 51 Franklin Street,
- Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
- internet at http://www.fsf.org/licenses/lgpl.html.
-
-Alternatively, the contents of this file may be used under the terms of the
-Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
-License, as published by the Free Software Foundation, either version 2
-of the License or (at your option) any later version.
-*/
+// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
+// Copyright 2010, SIL International, All rights reserved.
+
#include "graphite2/Segment.h"
#include "inc/Segment.h"
#include "inc/Slot.h"
diff --git a/thirdparty/graphite/src/inc/CharInfo.h b/thirdparty/graphite/src/inc/CharInfo.h
index 01e7e31ac9..0fbfefda4d 100644
--- a/thirdparty/graphite/src/inc/CharInfo.h
+++ b/thirdparty/graphite/src/inc/CharInfo.h
@@ -1,29 +1,6 @@
-/* GRAPHITE2 LICENSING
+// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
+// Copyright 2010, SIL International, All rights reserved.
- Copyright 2010, SIL International
- All rights reserved.
-
- This library is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should also have received a copy of the GNU Lesser General Public
- License along with this library in the file named "LICENSE".
- If not, write to the Free Software Foundation, 51 Franklin Street,
- Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
- internet at http://www.fsf.org/licenses/lgpl.html.
-
-Alternatively, the contents of this file may be used under the terms of the
-Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
-License, as published by the Free Software Foundation, either version 2
-of the License or (at your option) any later version.
-*/
#pragma once
#include "inc/Main.h"
diff --git a/thirdparty/graphite/src/inc/CmapCache.h b/thirdparty/graphite/src/inc/CmapCache.h
index 7820c958b0..b18ce2929b 100644
--- a/thirdparty/graphite/src/inc/CmapCache.h
+++ b/thirdparty/graphite/src/inc/CmapCache.h
@@ -1,29 +1,6 @@
-/* GRAPHITE2 LICENSING
+// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
+// Copyright 2010, SIL International, All rights reserved.
- Copyright 2010, SIL International
- All rights reserved.
-
- This library is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should also have received a copy of the GNU Lesser General Public
- License along with this library in the file named "LICENSE".
- If not, write to the Free Software Foundation, 51 Franklin Street,
- Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
- internet at http://www.fsf.org/licenses/lgpl.html.
-
-Alternatively, the contents of this file may be used under the terms of the
-Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
-License, as published by the Free Software Foundation, either version 2
-of the License or (at your option) any later version.
-*/
#pragma once
#include "inc/Main.h"
diff --git a/thirdparty/graphite/src/inc/Code.h b/thirdparty/graphite/src/inc/Code.h
index 3cee67c81d..24e92e429d 100644
--- a/thirdparty/graphite/src/inc/Code.h
+++ b/thirdparty/graphite/src/inc/Code.h
@@ -1,29 +1,6 @@
-/* GRAPHITE2 LICENSING
-
- Copyright 2010, SIL International
- All rights reserved.
-
- This library is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should also have received a copy of the GNU Lesser General Public
- License along with this library in the file named "LICENSE".
- If not, write to the Free Software Foundation, 51 Franklin Street,
- Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
- internet at http://www.fsf.org/licenses/lgpl.html.
-
-Alternatively, the contents of this file may be used under the terms of the
-Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
-License, as published by the Free Software Foundation, either version 2
-of the License or (at your option) any later version.
-*/
+// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
+// Copyright 2010, SIL International, All rights reserved.
+
// This class represents loaded graphite stack machine code. It performs
// basic sanity checks, on the incoming code to prevent more obvious problems
// from crashing graphite.
diff --git a/thirdparty/graphite/src/inc/Collider.h b/thirdparty/graphite/src/inc/Collider.h
index 71e8400501..3a922660d4 100644
--- a/thirdparty/graphite/src/inc/Collider.h
+++ b/thirdparty/graphite/src/inc/Collider.h
@@ -1,29 +1,6 @@
-/* GRAPHITE2 LICENSING
-
- Copyright 2010, SIL International
- All rights reserved.
-
- This library is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should also have received a copy of the GNU Lesser General Public
- License along with this library in the file named "LICENSE".
- If not, write to the Free Software Foundation, 51 Franklin Street,
- Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
- internet at http://www.fsf.org/licenses/lgpl.html.
-
-Alternatively, the contents of this file may be used under the terms of the
-Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
-License, as published by the Free Software Foundation, either version 2
-of the License or (at your option) any later version.
-*/
+// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
+// Copyright 2010, SIL International, All rights reserved.
+
#pragma once
#include "inc/List.h"
diff --git a/thirdparty/graphite/src/inc/Compression.h b/thirdparty/graphite/src/inc/Compression.h
index 9fe10e025d..4f5193b931 100644
--- a/thirdparty/graphite/src/inc/Compression.h
+++ b/thirdparty/graphite/src/inc/Compression.h
@@ -1,29 +1,6 @@
-/* GRAPHITE2 LICENSING
+// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
+// Copyright 2015, SIL International, All rights reserved.
- Copyright 2015, SIL International
- All rights reserved.
-
- This library is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should also have received a copy of the GNU Lesser General Public
- License along with this library in the file named "LICENSE".
- If not, write to the Free Software Foundation, 51 Franklin Street,
- Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
- internet at http://www.fsf.org/licenses/lgpl.html.
-
-Alternatively, the contents of this file may be used under the terms of the
-Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
-License, as published by the Free Software Foundation, either version 2
-of the License or (at your option) any later version.
-*/
#pragma once
diff --git a/thirdparty/graphite/src/inc/Decompressor.h b/thirdparty/graphite/src/inc/Decompressor.h
index 10f21b7af1..1113e004c1 100644
--- a/thirdparty/graphite/src/inc/Decompressor.h
+++ b/thirdparty/graphite/src/inc/Decompressor.h
@@ -1,29 +1,6 @@
-/* GRAPHITE2 LICENSING
+// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
+// Copyright 2015, SIL International, All rights reserved.
- Copyright 2015, SIL International
- All rights reserved.
-
- This library is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should also have received a copy of the GNU Lesser General Public
- License along with this library in the file named "LICENSE".
- If not, write to the Free Software Foundation, 51 Franklin Street,
- Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
- internet at http://www.fsf.org/licenses/lgpl.html.
-
-Alternatively, the contents of this file may be used under the terms of the
-Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
-License, as published by the Free Software Foundation, either version 2
-of the License or (at your option) any later version.
-*/
#pragma once
diff --git a/thirdparty/graphite/src/inc/Endian.h b/thirdparty/graphite/src/inc/Endian.h
index 56ecfd8667..7bd201f92b 100644
--- a/thirdparty/graphite/src/inc/Endian.h
+++ b/thirdparty/graphite/src/inc/Endian.h
@@ -1,30 +1,5 @@
-/* GRAPHITE2 LICENSING
-
- Copyright 2011, SIL International
- All rights reserved.
-
- This library is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should also have received a copy of the GNU Lesser General Public
- License along with this library in the file named "LICENSE".
- If not, write to the Free Software Foundation, 51 Franklin Street,
- Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
- internet at http://www.fsf.org/licenses/lgpl.html.
-
-Alternatively, the contents of this file may be used under the terms of the
-Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
-License, as published by the Free Software Foundation, either version 2
-of the License or (at your option) any later version.
-*/
-
+// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
+// Copyright 2011, SIL International, All rights reserved.
/*
Description:
A set of fast template based decoders for decoding values of any C integer
diff --git a/thirdparty/graphite/src/inc/Error.h b/thirdparty/graphite/src/inc/Error.h
index 2b7ab763a2..7e14c8e754 100644
--- a/thirdparty/graphite/src/inc/Error.h
+++ b/thirdparty/graphite/src/inc/Error.h
@@ -1,29 +1,6 @@
-/* GRAPHITE2 LICENSING
+// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
+// Copyright 2013, SIL International, All rights reserved.
- Copyright 2013, SIL International
- All rights reserved.
-
- This library is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should also have received a copy of the GNU Lesser General Public
- License along with this library in the file named "LICENSE".
- If not, write to the Free Software Foundation, 51 Franklin Street,
- Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
- internet at http://www.fsf.org/licenses/lgpl.html.
-
-Alternatively, the contents of this file may be used under the terms of the
-Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
-License, as published by the Free Software Foundation, either version 2
-of the License or (at your option) any later version.
-*/
#pragma once
// numbers are explicitly assigned for future proofing
@@ -38,7 +15,7 @@ public:
operator bool() { return (_e != 0); }
int error() { return _e; }
void error(int e) { _e = e; }
- bool test(bool pr, int err) { return (_e = int(pr) * err); }
+ bool test(bool pr, int err) { return (_e = pr ? err : 0); }
private:
int _e;
@@ -56,7 +33,7 @@ enum errcontext {
EC_ARULEMAP = 9 // in Silf %d, pass %d, state %d
};
-enum errors {
+enum error {
E_OUTOFMEM = 1, // Out of memory
E_NOGLYPHS = 2, // There are no glyphs in the font
E_BADUPEM = 3, // The units per em for the font is bad (0)
@@ -125,7 +102,7 @@ enum errors {
E_BADJUMPCODE = 65, // Code jumps past end of op codes
E_CODEBADARGS = 66, // Code arguments exhausted
E_CODENORETURN = 67, // Missing return type op code at end of code
- E_CODENESTEDCTXT = 68, // Nested context encountered in code
+ E_CODENESTEDCTXT = 68, // Nested context encountered in code
// Compression errors
E_BADSCHEME = 69,
E_SHRINKERFAILED = 70,
diff --git a/thirdparty/graphite/src/inc/Face.h b/thirdparty/graphite/src/inc/Face.h
index 355c5aa0d3..fac7fd4b8e 100644
--- a/thirdparty/graphite/src/inc/Face.h
+++ b/thirdparty/graphite/src/inc/Face.h
@@ -1,29 +1,6 @@
-/* GRAPHITE2 LICENSING
-
- Copyright 2010, SIL International
- All rights reserved.
-
- This library is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should also have received a copy of the GNU Lesser General Public
- License along with this library in the file named "LICENSE".
- If not, write to the Free Software Foundation, 51 Franklin Street,
- Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
- internet at http://www.fsf.org/licenses/lgpl.html.
-
-Alternatively, the contents of this file may be used under the terms of the
-Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
-License, as published by the Free Software Foundation, either version 2
-of the License or (at your option) any later version.
-*/
+// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
+// Copyright 2010, SIL International, All rights reserved.
+
#pragma once
#include <cstdio>
diff --git a/thirdparty/graphite/src/inc/FeatureMap.h b/thirdparty/graphite/src/inc/FeatureMap.h
index 0f05e941a2..a98008f738 100644
--- a/thirdparty/graphite/src/inc/FeatureMap.h
+++ b/thirdparty/graphite/src/inc/FeatureMap.h
@@ -1,29 +1,6 @@
-/* GRAPHITE2 LICENSING
-
- Copyright 2010, SIL International
- All rights reserved.
-
- This library is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should also have received a copy of the GNU Lesser General Public
- License along with this library in the file named "LICENSE".
- If not, write to the Free Software Foundation, 51 Franklin Street,
- Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
- internet at http://www.fsf.org/licenses/lgpl.html.
-
-Alternatively, the contents of this file may be used under the terms of the
-Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
-License, as published by the Free Software Foundation, either version 2
-of the License or (at your option) any later version.
-*/
+// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
+// Copyright 2010, SIL International, All rights reserved.
+
#pragma once
#include "inc/Main.h"
#include "inc/FeatureVal.h"
diff --git a/thirdparty/graphite/src/inc/FeatureVal.h b/thirdparty/graphite/src/inc/FeatureVal.h
index cd3f93b2b5..35397f0f3b 100644
--- a/thirdparty/graphite/src/inc/FeatureVal.h
+++ b/thirdparty/graphite/src/inc/FeatureVal.h
@@ -1,29 +1,6 @@
-/* GRAPHITE2 LICENSING
+// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
+// Copyright 2010, SIL International, All rights reserved.
- Copyright 2010, SIL International
- All rights reserved.
-
- This library is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should also have received a copy of the GNU Lesser General Public
- License along with this library in the file named "LICENSE".
- If not, write to the Free Software Foundation, 51 Franklin Street,
- Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
- internet at http://www.fsf.org/licenses/lgpl.html.
-
-Alternatively, the contents of this file may be used under the terms of the
-Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
-License, as published by the Free Software Foundation, either version 2
-of the License or (at your option) any later version.
-*/
#pragma once
#include <cstring>
#include <cassert>
diff --git a/thirdparty/graphite/src/inc/FileFace.h b/thirdparty/graphite/src/inc/FileFace.h
index 35927847f8..521942ee85 100644
--- a/thirdparty/graphite/src/inc/FileFace.h
+++ b/thirdparty/graphite/src/inc/FileFace.h
@@ -1,29 +1,6 @@
-/* GRAPHITE2 LICENSING
-
- Copyright 2012, SIL International
- All rights reserved.
-
- This library is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should also have received a copy of the GNU Lesser General Public
- License along with this library in the file named "LICENSE".
- If not, write to the Free Software Foundation, 51 Franklin Street,
- Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
- internet at http://www.fsf.org/licenses/lgpl.html.
-
-Alternatively, the contents of this file may be used under the terms of the
-Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
-License, as published by the Free Software Foundation, either version 2
-of the License or (at your option) any later version.
-*/
+// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
+// Copyright 2012, SIL International, All rights reserved.
+
#pragma once
//#include "inc/FeatureMap.h"
diff --git a/thirdparty/graphite/src/inc/Font.h b/thirdparty/graphite/src/inc/Font.h
index 9bc9ffb510..537ad9de0e 100644
--- a/thirdparty/graphite/src/inc/Font.h
+++ b/thirdparty/graphite/src/inc/Font.h
@@ -1,29 +1,6 @@
-/* GRAPHITE2 LICENSING
+// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
+// Copyright 2010, SIL International, All rights reserved.
- Copyright 2010, SIL International
- All rights reserved.
-
- This library is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should also have received a copy of the GNU Lesser General Public
- License along with this library in the file named "LICENSE".
- If not, write to the Free Software Foundation, 51 Franklin Street,
- Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
- internet at http://www.fsf.org/licenses/lgpl.html.
-
-Alternatively, the contents of this file may be used under the terms of the
-Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
-License, as published by the Free Software Foundation, either version 2
-of the License or (at your option) any later version.
-*/
#pragma once
#include <cassert>
#include "graphite2/Font.h"
diff --git a/thirdparty/graphite/src/inc/GlyphCache.h b/thirdparty/graphite/src/inc/GlyphCache.h
index 7d5324e522..5f6d3eea18 100644
--- a/thirdparty/graphite/src/inc/GlyphCache.h
+++ b/thirdparty/graphite/src/inc/GlyphCache.h
@@ -1,29 +1,6 @@
-/* GRAPHITE2 LICENSING
-
- Copyright 2012, SIL International
- All rights reserved.
-
- This library is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should also have received a copy of the GNU Lesser General Public
- License along with this library in the file named "LICENSE".
- If not, write to the Free Software Foundation, 51 Franklin Street,
- Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
- internet at http://www.fsf.org/licenses/lgpl.html.
-
-Alternatively, the contents of this file may be used under the terms of the
-Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
-License, as published by the Free Software Foundation, either version 2
-of the License or (at your option) any later version.
-*/
+// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
+// Copyright 2012, SIL International, All rights reserved.
+
#pragma once
diff --git a/thirdparty/graphite/src/inc/GlyphFace.h b/thirdparty/graphite/src/inc/GlyphFace.h
index fc29056146..f964c0581a 100644
--- a/thirdparty/graphite/src/inc/GlyphFace.h
+++ b/thirdparty/graphite/src/inc/GlyphFace.h
@@ -1,29 +1,6 @@
-/* GRAPHITE2 LICENSING
+// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
+// Copyright 2010, SIL International, All rights reserved.
- Copyright 2010, SIL International
- All rights reserved.
-
- This library is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should also have received a copy of the GNU Lesser General Public
- License along with this library in the file named "LICENSE".
- If not, write to the Free Software Foundation, 51 Franklin Street,
- Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
- internet at http://www.fsf.org/licenses/lgpl.html.
-
-Alternatively, the contents of this file may be used under the terms of the
-Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
-License, as published by the Free Software Foundation, either version 2
-of the License or (at your option) any later version.
-*/
#pragma once
#include "inc/Main.h"
diff --git a/thirdparty/graphite/src/inc/Intervals.h b/thirdparty/graphite/src/inc/Intervals.h
index 81d23187b6..15427d428a 100644
--- a/thirdparty/graphite/src/inc/Intervals.h
+++ b/thirdparty/graphite/src/inc/Intervals.h
@@ -1,29 +1,6 @@
-/* GRAPHITE2 LICENSING
-
- Copyright 2010, SIL International
- All rights reserved.
-
- This library is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should also have received a copy of the GNU Lesser General Public
- License along with this library in the file named "LICENSE".
- If not, write to the Free Software Foundation, 51 Franklin Street,
- Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
- internet at http://www.fsf.org/licenses/lgpl.html.
-
-Alternatively, the contents of this file may be used under the terms of the
-Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
-License, as published by the Free Software Foundation, either version 2
-of the License or (at your option) any later version.
-*/
+// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
+// Copyright 2010, SIL International, All rights reserved.
+
#pragma once
#include <utility>
diff --git a/thirdparty/graphite/src/inc/List.h b/thirdparty/graphite/src/inc/List.h
index a3b7a77961..3a36c17a7a 100644
--- a/thirdparty/graphite/src/inc/List.h
+++ b/thirdparty/graphite/src/inc/List.h
@@ -1,29 +1,6 @@
-/* GRAPHITE2 LICENSING
-
- Copyright 2010, SIL International
- All rights reserved.
-
- This library is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should also have received a copy of the GNU Lesser General Public
- License along with this library in the file named "LICENSE".
- If not, write to the Free Software Foundation, 51 Franklin Street,
- Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
- internet at http://www.fsf.org/licenses/lgpl.html.
-
-Alternatively, the contents of this file may be used under the terms of the
-Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
-License, as published by the Free Software Foundation, either version 2
-of the License or (at your option) any later version.
-*/
+// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
+// Copyright 2010, SIL International, All rights reserved.
+
// designed to have a limited subset of the std::vector api
#pragma once
diff --git a/thirdparty/graphite/src/inc/Machine.h b/thirdparty/graphite/src/inc/Machine.h
index b23819fb98..5ceedc296d 100644
--- a/thirdparty/graphite/src/inc/Machine.h
+++ b/thirdparty/graphite/src/inc/Machine.h
@@ -1,29 +1,6 @@
-/* GRAPHITE2 LICENSING
-
- Copyright 2010, SIL International
- All rights reserved.
-
- This library is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should also have received a copy of the GNU Lesser General Public
- License along with this library in the file named "LICENSE".
- If not, write to the Free Software Foundation, 51 Franklin Street,
- Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
- internet at http://www.fsf.org/licenses/lgpl.html.
-
-Alternatively, the contents of this file may be used under the terms of the
-Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
-License, as published by the Free Software Foundation, either version 2
-of the License or (at your option) any later version.
-*/
+// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
+// Copyright 2010, SIL International, All rights reserved.
+
// This general interpreter interface.
// Author: Tim Eves
diff --git a/thirdparty/graphite/src/inc/Main.h b/thirdparty/graphite/src/inc/Main.h
index ebf02dd553..6a412efeca 100644
--- a/thirdparty/graphite/src/inc/Main.h
+++ b/thirdparty/graphite/src/inc/Main.h
@@ -1,29 +1,6 @@
-/* GRAPHITE2 LICENSING
-
- Copyright 2010, SIL International
- All rights reserved.
-
- This library is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should also have received a copy of the GNU Lesser General Public
- License along with this library in the file named "LICENSE".
- If not, write to the Free Software Foundation, 51 Franklin Street,
- Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
- internet at http://www.fsf.org/licenses/lgpl.html.
-
-Alternatively, the contents of this file may be used under the terms of the
-Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
-License, as published by the Free Software Foundation, either version 2
-of the License or (at your option) any later version.
-*/
+// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
+// Copyright 2010, SIL International, All rights reserved.
+
#pragma once
#include <cstdlib>
diff --git a/thirdparty/graphite/src/inc/NameTable.h b/thirdparty/graphite/src/inc/NameTable.h
index 0fdbeb4d85..5a7913ddc5 100644
--- a/thirdparty/graphite/src/inc/NameTable.h
+++ b/thirdparty/graphite/src/inc/NameTable.h
@@ -1,29 +1,6 @@
-/* GRAPHITE2 LICENSING
+// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
+// Copyright 2010, SIL International, All rights reserved.
- Copyright 2010, SIL International
- All rights reserved.
-
- This library is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should also have received a copy of the GNU Lesser General Public
- License along with this library in the file named "LICENSE".
- If not, write to the Free Software Foundation, 51 Franklin Street,
- Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
- internet at http://www.fsf.org/licenses/lgpl.html.
-
-Alternatively, the contents of this file may be used under the terms of the
-Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
-License, as published by the Free Software Foundation, either version 2
-of the License or (at your option) any later version.
-*/
#pragma once
#include <graphite2/Segment.h>
diff --git a/thirdparty/graphite/src/inc/Pass.h b/thirdparty/graphite/src/inc/Pass.h
index e687a87d8c..fb507e6a04 100644
--- a/thirdparty/graphite/src/inc/Pass.h
+++ b/thirdparty/graphite/src/inc/Pass.h
@@ -1,29 +1,6 @@
-/* GRAPHITE2 LICENSING
+// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
+// Copyright 2010, SIL International, All rights reserved.
- Copyright 2010, SIL International
- All rights reserved.
-
- This library is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should also have received a copy of the GNU Lesser General Public
- License along with this library in the file named "LICENSE".
- If not, write to the Free Software Foundation, 51 Franklin Street,
- Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
- internet at http://www.fsf.org/licenses/lgpl.html.
-
-Alternatively, the contents of this file may be used under the terms of the
-Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
-License, as published by the Free Software Foundation, either version 2
-of the License or (at your option) any later version.
-*/
#pragma once
#include <cstdlib>
diff --git a/thirdparty/graphite/src/inc/Position.h b/thirdparty/graphite/src/inc/Position.h
index 510e4f4c41..554acc411e 100644
--- a/thirdparty/graphite/src/inc/Position.h
+++ b/thirdparty/graphite/src/inc/Position.h
@@ -1,29 +1,6 @@
-/* GRAPHITE2 LICENSING
+// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
+// Copyright 2010, SIL International, All rights reserved.
- Copyright 2010, SIL International
- All rights reserved.
-
- This library is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should also have received a copy of the GNU Lesser General Public
- License along with this library in the file named "LICENSE".
- If not, write to the Free Software Foundation, 51 Franklin Street,
- Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
- internet at http://www.fsf.org/licenses/lgpl.html.
-
-Alternatively, the contents of this file may be used under the terms of the
-Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
-License, as published by the Free Software Foundation, either version 2
-of the License or (at your option) any later version.
-*/
#pragma once
namespace graphite2 {
diff --git a/thirdparty/graphite/src/inc/Rule.h b/thirdparty/graphite/src/inc/Rule.h
index 5964e003a6..09025dc799 100644
--- a/thirdparty/graphite/src/inc/Rule.h
+++ b/thirdparty/graphite/src/inc/Rule.h
@@ -1,29 +1,6 @@
-/* GRAPHITE2 LICENSING
-
- Copyright 2011, SIL International
- All rights reserved.
-
- This library is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should also have received a copy of the GNU Lesser General Public
- License along with this library in the file named "LICENSE".
- If not, write to the Free Software Foundation, 51 Franklin Street,
- Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
- internet at http://www.fsf.org/licenses/lgpl.html.
-
-Alternatively, the contents of this file may be used under the terms of the
-Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
-License, as published by the Free Software Foundation, either version 2
-of the License or (at your option) any later version.
-*/
+// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
+// Copyright 2011, SIL International, All rights reserved.
+
#pragma once
diff --git a/thirdparty/graphite/src/inc/Segment.h b/thirdparty/graphite/src/inc/Segment.h
index 6cf83408d4..a3a8eef648 100644
--- a/thirdparty/graphite/src/inc/Segment.h
+++ b/thirdparty/graphite/src/inc/Segment.h
@@ -1,29 +1,6 @@
-/* GRAPHITE2 LICENSING
-
- Copyright 2010, SIL International
- All rights reserved.
-
- This library is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should also have received a copy of the GNU Lesser General Public
- License along with this library in the file named "LICENSE".
- If not, write to the Free Software Foundation, 51 Franklin Street,
- Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
- internet at http://www.fsf.org/licenses/lgpl.html.
-
-Alternatively, the contents of this file may be used under the terms of the
-Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
-License, as published by the Free Software Foundation, either version 2
-of the License or (at your option) any later version.
-*/
+// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
+// Copyright 2010, SIL International, All rights reserved.
+
#pragma once
#include "inc/Main.h"
diff --git a/thirdparty/graphite/src/inc/Silf.h b/thirdparty/graphite/src/inc/Silf.h
index edc0c3a16d..6fe2aaef1f 100644
--- a/thirdparty/graphite/src/inc/Silf.h
+++ b/thirdparty/graphite/src/inc/Silf.h
@@ -1,29 +1,6 @@
-/* GRAPHITE2 LICENSING
-
- Copyright 2010, SIL International
- All rights reserved.
-
- This library is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should also have received a copy of the GNU Lesser General Public
- License along with this library in the file named "LICENSE".
- If not, write to the Free Software Foundation, 51 Franklin Street,
- Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
- internet at http://www.fsf.org/licenses/lgpl.html.
-
-Alternatively, the contents of this file may be used under the terms of the
-Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
-License, as published by the Free Software Foundation, either version 2
-of the License or (at your option) any later version.
-*/
+// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
+// Copyright 2010, SIL International, All rights reserved.
+
#pragma once
#include "graphite2/Font.h"
diff --git a/thirdparty/graphite/src/inc/Slot.h b/thirdparty/graphite/src/inc/Slot.h
index df39d9a3bb..0d8571d336 100644
--- a/thirdparty/graphite/src/inc/Slot.h
+++ b/thirdparty/graphite/src/inc/Slot.h
@@ -1,29 +1,6 @@
-/* GRAPHITE2 LICENSING
-
- Copyright 2010, SIL International
- All rights reserved.
-
- This library is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should also have received a copy of the GNU Lesser General Public
- License along with this library in the file named "LICENSE".
- If not, write to the Free Software Foundation, 51 Franklin Street,
- Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
- internet at http://www.fsf.org/licenses/lgpl.html.
-
-Alternatively, the contents of this file may be used under the terms of the
-Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
-License, as published by the Free Software Foundation, either version 2
-of the License or (at your option) any later version.
-*/
+// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
+// Copyright 2010, SIL International, All rights reserved.
+
#pragma once
#include "graphite2/Types.h"
diff --git a/thirdparty/graphite/src/inc/Sparse.h b/thirdparty/graphite/src/inc/Sparse.h
index fcda890171..3c5d33ae5d 100644
--- a/thirdparty/graphite/src/inc/Sparse.h
+++ b/thirdparty/graphite/src/inc/Sparse.h
@@ -1,29 +1,6 @@
-/* GRAPHITE2 LICENSING
-
- Copyright 2011, SIL International
- All rights reserved.
-
- This library is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should also have received a copy of the GNU Lesser General Public
- License along with this library in the file named "LICENSE".
- If not, write to the Free Software Foundation, 51 Franklin Street,
- Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
- internet at http://www.fsf.org/licenses/lgpl.html.
-
-Alternatively, the contents of this file may be used under the terms of the
-Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
-License, as published by the Free Software Foundation, either version 2
-of the License or (at your option) any later version.
-*/
+// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
+// Copyright 2011, SIL International, All rights reserved.
+
#pragma once
#include <iterator>
#include <utility>
diff --git a/thirdparty/graphite/src/inc/TtfTypes.h b/thirdparty/graphite/src/inc/TtfTypes.h
index ae67915304..e4fd49f943 100644
--- a/thirdparty/graphite/src/inc/TtfTypes.h
+++ b/thirdparty/graphite/src/inc/TtfTypes.h
@@ -1,39 +1,14 @@
-/* GRAPHITE2 LICENSING
-
- Copyright 2010, SIL International
- All rights reserved.
-
- This library is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should also have received a copy of the GNU Lesser General Public
- License along with this library in the file named "LICENSE".
- If not, write to the Free Software Foundation, 51 Franklin Street,
- Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
- internet at http://www.fsf.org/licenses/lgpl.html.
-
-Alternatively, the contents of this file may be used under the terms of the
-Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
-License, as published by the Free Software Foundation, either version 2
-of the License or (at your option) any later version.
-*/
-#pragma once
-/*--------------------------------------------------------------------*//*:Ignore this sentence.
+// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
+// Copyright 2010, SIL International, All rights reserved.
-File: TtfTypes.h
+#pragma once
+/*
Responsibility: Tim Eves
Last reviewed: Not yet.
Description:
Provides types required to represent the TTF basic types.
--------------------------------------------------------------------------------*//*:End Ignore*/
+*/
//**********************************************************************************************
diff --git a/thirdparty/graphite/src/inc/TtfUtil.h b/thirdparty/graphite/src/inc/TtfUtil.h
index 3952bc06fb..1ccab42fb8 100644
--- a/thirdparty/graphite/src/inc/TtfUtil.h
+++ b/thirdparty/graphite/src/inc/TtfUtil.h
@@ -1,39 +1,13 @@
-/* GRAPHITE2 LICENSING
-
- Copyright 2010, SIL International
- All rights reserved.
-
- This library is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should also have received a copy of the GNU Lesser General Public
- License along with this library in the file named "LICENSE".
- If not, write to the Free Software Foundation, 51 Franklin Street,
- Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
- internet at http://www.fsf.org/licenses/lgpl.html.
-
-Alternatively, the contents of this file may be used under the terms of the
-Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
-License, as published by the Free Software Foundation, either version 2
-of the License or (at your option) any later version.
-*/
-#pragma once
-/*--------------------------------------------------------------------*//*:Ignore this sentence.
-
-File: TtfUtil.h
+// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
+// Copyright 2010, SIL International, All rights reserved.
+/*
Responsibility: Alan Ward
Last reviewed: Not yet.
Description:
Utility class for handling TrueType font files.
-----------------------------------------------------------------------------------------------*/
+*/
+#pragma once
#include <cstddef>
diff --git a/thirdparty/graphite/src/inc/UtfCodec.h b/thirdparty/graphite/src/inc/UtfCodec.h
index 24a343d8d9..bab652c119 100644
--- a/thirdparty/graphite/src/inc/UtfCodec.h
+++ b/thirdparty/graphite/src/inc/UtfCodec.h
@@ -1,29 +1,6 @@
-/* GRAPHITE2 LICENSING
-
- Copyright 2011, SIL International
- All rights reserved.
-
- This library is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should also have received a copy of the GNU Lesser General Public
- License along with this library in the file named "LICENSE".
- If not, write to the Free Software Foundation, 51 Franklin Street,
- Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
- internet at http://www.fsf.org/licenses/lgpl.html.
-
-Alternatively, the contents of this file may be used under the terms of the
-Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
-License, as published by the Free Software Foundation, either version 2
-of the License or (at your option) any later version.
-*/
+// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
+// Copyright 2011, SIL International, All rights reserved.
+
#pragma once
#include <cstdlib>
diff --git a/thirdparty/graphite/src/inc/bits.h b/thirdparty/graphite/src/inc/bits.h
index 9365986a10..168ff256d3 100644
--- a/thirdparty/graphite/src/inc/bits.h
+++ b/thirdparty/graphite/src/inc/bits.h
@@ -1,29 +1,6 @@
-/* GRAPHITE2 LICENSING
-
- Copyright 2012, SIL International
- All rights reserved.
-
- This library is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should also have received a copy of the GNU Lesser General Public
- License along with this library in the file named "LICENSE".
- If not, write to the Free Software Foundation, 51 Franklin Street,
- Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
- internet at http://www.fsf.org/licenses/lgpl.html.
-
-Alternatively, the contents of this file may be used under the terms of the
-Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
-License, as published by the Free Software Foundation, either version 2
-of the License or (at your option) any later version.
-*/
+// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
+// Copyright 2012, SIL International, All rights reserved.
+
#pragma once
namespace graphite2
diff --git a/thirdparty/graphite/src/inc/debug.h b/thirdparty/graphite/src/inc/debug.h
index 97175eb2cc..5b9c63872b 100644
--- a/thirdparty/graphite/src/inc/debug.h
+++ b/thirdparty/graphite/src/inc/debug.h
@@ -1,29 +1,6 @@
-/* GRAPHITE2 LICENSING
-
- Copyright 2011, SIL International
- All rights reserved.
-
- This library is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should also have received a copy of the GNU Lesser General Public
- License along with this library in the file named "LICENSE".
- If not, write to the Free Software Foundation, 51 Franklin Street,
- Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
- internet at http://www.fsf.org/licenses/lgpl.html.
-
-Alternatively, the contents of this file may be used under the terms of the
-Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
-License, as published by the Free Software Foundation, either version 2
-of the License or (at your option) any later version.
-*/
+// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
+// Copyright 2011, SIL International, All rights reserved.
+
// debug.h
//
// Created on: 22 Dec 2011
diff --git a/thirdparty/graphite/src/inc/json.h b/thirdparty/graphite/src/inc/json.h
index 554cd9a3d1..72011ef198 100644
--- a/thirdparty/graphite/src/inc/json.h
+++ b/thirdparty/graphite/src/inc/json.h
@@ -1,29 +1,6 @@
-/* GRAPHITE2 LICENSING
-
- Copyright 2011, SIL International
- All rights reserved.
-
- This library is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should also have received a copy of the GNU Lesser General Public
- License along with this library in the file named "LICENSE".
- If not, write to the Free Software Foundation, 51 Franklin Street,
- Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
- internet at http://www.fsf.org/licenses/lgpl.html.
-
-Alternatively, the contents of this file may be used under the terms of the
-Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
-License, as published by the Free Software Foundation, either version 2
-of the License or (at your option) any later version.
-*/
+// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
+// Copyright 2011, SIL International, All rights reserved.
+
// JSON pretty printer for graphite font debug output logging.
// Created on: 15 Dec 2011
// Author: Tim Eves
diff --git a/thirdparty/graphite/src/inc/locale2lcid.h b/thirdparty/graphite/src/inc/locale2lcid.h
index 25d5c0a3c8..e591c42b28 100644
--- a/thirdparty/graphite/src/inc/locale2lcid.h
+++ b/thirdparty/graphite/src/inc/locale2lcid.h
@@ -1,29 +1,6 @@
-/* GRAPHITE2 LICENSING
+// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
+// Copyright 2010, SIL International, All rights reserved.
- Copyright 2010, SIL International
- All rights reserved.
-
- This library is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should also have received a copy of the GNU Lesser General Public
- License along with this library in the file named "LICENSE".
- If not, write to the Free Software Foundation, 51 Franklin Street,
- Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
- internet at http://www.fsf.org/licenses/lgpl.html.
-
-Alternatively, the contents of this file may be used under the terms of the
-Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
-License, as published by the Free Software Foundation, either version 2
-of the License or (at your option) any later version.
-*/
#pragma once
#include <cstring>
#include <cassert>
diff --git a/thirdparty/graphite/src/inc/opcode_table.h b/thirdparty/graphite/src/inc/opcode_table.h
index cb5acde9a4..01a84831bc 100644
--- a/thirdparty/graphite/src/inc/opcode_table.h
+++ b/thirdparty/graphite/src/inc/opcode_table.h
@@ -1,29 +1,6 @@
-/* GRAPHITE2 LICENSING
+// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
+// Copyright 2010, SIL International, All rights reserved.
- Copyright 2010, SIL International
- All rights reserved.
-
- This library is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should also have received a copy of the GNU Lesser General Public
- License along with this library in the file named "LICENSE".
- If not, write to the Free Software Foundation, 51 Franklin Street,
- Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
- internet at http://www.fsf.org/licenses/lgpl.html.
-
-Alternatively, the contents of this file may be used under the terms of the
-Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
-License, as published by the Free Software Foundation, either version 2
-of the License or (at your option) any later version.
-*/
// This file will be pulled into and integrated into a machine implmentation
// DO NOT build directly
#pragma once
diff --git a/thirdparty/graphite/src/inc/opcodes.h b/thirdparty/graphite/src/inc/opcodes.h
index ff2f1741e2..10ba177229 100644
--- a/thirdparty/graphite/src/inc/opcodes.h
+++ b/thirdparty/graphite/src/inc/opcodes.h
@@ -1,29 +1,6 @@
-/* GRAPHITE2 LICENSING
-
- Copyright 2010, SIL International
- All rights reserved.
-
- This library is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should also have received a copy of the GNU Lesser General Public
- License along with this library in the file named "LICENSE".
- If not, write to the Free Software Foundation, 51 Franklin Street,
- Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
- internet at http://www.fsf.org/licenses/lgpl.html.
-
-Alternatively, the contents of this file may be used under the terms of the
-Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
-License, as published by the Free Software Foundation, either version 2
-of the License or (at your option) any later version.
-*/
+// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
+// Copyright 2010, SIL International, All rights reserved.
+
#pragma once
// This file will be pulled into and integrated into a machine implmentation
// DO NOT build directly and under no circumstances ever #include headers in
diff --git a/thirdparty/graphite/src/json.cpp b/thirdparty/graphite/src/json.cpp
index 25f2190f71..7990654eb8 100644
--- a/thirdparty/graphite/src/json.cpp
+++ b/thirdparty/graphite/src/json.cpp
@@ -1,29 +1,6 @@
-/* GRAPHITE2 LICENSING
-
- Copyright 2011, SIL International
- All rights reserved.
-
- This library is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should also have received a copy of the GNU Lesser General Public
- License along with this library in the file named "LICENSE".
- If not, write to the Free Software Foundation, 51 Franklin Street,
- Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
- internet at http://www.fsf.org/licenses/lgpl.html.
-
-Alternatively, the contents of this file may be used under the terms of the
-Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
-License, as published by the Free Software Foundation, either version 2
-of the License or (at your option) any later version.
-*/
+// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
+// Copyright 2011, SIL International, All rights reserved.
+
// JSON debug logging
// Author: Tim Eves
diff --git a/thirdparty/harfbuzz/src/OT/Layout/Common/Coverage.hh b/thirdparty/harfbuzz/src/OT/Layout/Common/Coverage.hh
index eef89a2879..fbd7c642ab 100644
--- a/thirdparty/harfbuzz/src/OT/Layout/Common/Coverage.hh
+++ b/thirdparty/harfbuzz/src/OT/Layout/Common/Coverage.hh
@@ -49,7 +49,7 @@ struct Coverage
HBUINT16 format; /* Format identifier */
CoverageFormat1_3<SmallTypes> format1;
CoverageFormat2_4<SmallTypes> format2;
-#ifndef HB_NO_BORING_EXPANSION
+#ifndef HB_NO_BEYOND_64K
CoverageFormat1_3<MediumTypes>format3;
CoverageFormat2_4<MediumTypes>format4;
#endif
@@ -65,7 +65,7 @@ struct Coverage
{
case 1: return_trace (u.format1.sanitize (c));
case 2: return_trace (u.format2.sanitize (c));
-#ifndef HB_NO_BORING_EXPANSION
+#ifndef HB_NO_BEYOND_64K
case 3: return_trace (u.format3.sanitize (c));
case 4: return_trace (u.format4.sanitize (c));
#endif
@@ -74,10 +74,8 @@ 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; }
+ unsigned operator [] (hb_codepoint_t k) const { return get (k); }
+ bool has (hb_codepoint_t k) const { return (*this)[k] != NOT_COVERED; }
/* Predicate. */
bool operator () (hb_codepoint_t k) const { return has (k); }
@@ -87,7 +85,7 @@ struct Coverage
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
+#ifndef HB_NO_BEYOND_64K
case 3: return u.format3.get_coverage (glyph_id);
case 4: return u.format4.get_coverage (glyph_id);
#endif
@@ -100,7 +98,7 @@ struct Coverage
switch (u.format) {
case 1: return u.format1.get_population ();
case 2: return u.format2.get_population ();
-#ifndef HB_NO_BORING_EXPANSION
+#ifndef HB_NO_BEYOND_64K
case 3: return u.format3.get_population ();
case 4: return u.format4.get_population ();
#endif
@@ -127,7 +125,7 @@ struct Coverage
}
u.format = count <= num_ranges * 3 ? 1 : 2;
-#ifndef HB_NO_BORING_EXPANSION
+#ifndef HB_NO_BEYOND_64K
if (count && last > 0xFFFFu)
u.format += 2;
#endif
@@ -136,7 +134,7 @@ struct Coverage
{
case 1: return_trace (u.format1.serialize (c, glyphs));
case 2: return_trace (u.format2.serialize (c, glyphs));
-#ifndef HB_NO_BORING_EXPANSION
+#ifndef HB_NO_BEYOND_64K
case 3: return_trace (u.format3.serialize (c, glyphs));
case 4: return_trace (u.format4.serialize (c, glyphs));
#endif
@@ -166,7 +164,7 @@ struct Coverage
{
case 1: return u.format1.intersects (glyphs);
case 2: return u.format2.intersects (glyphs);
-#ifndef HB_NO_BORING_EXPANSION
+#ifndef HB_NO_BEYOND_64K
case 3: return u.format3.intersects (glyphs);
case 4: return u.format4.intersects (glyphs);
#endif
@@ -179,7 +177,7 @@ struct Coverage
{
case 1: return u.format1.intersects_coverage (glyphs, index);
case 2: return u.format2.intersects_coverage (glyphs, index);
-#ifndef HB_NO_BORING_EXPANSION
+#ifndef HB_NO_BEYOND_64K
case 3: return u.format3.intersects_coverage (glyphs, index);
case 4: return u.format4.intersects_coverage (glyphs, index);
#endif
@@ -196,7 +194,7 @@ struct Coverage
{
case 1: return u.format1.collect_coverage (glyphs);
case 2: return u.format2.collect_coverage (glyphs);
-#ifndef HB_NO_BORING_EXPANSION
+#ifndef HB_NO_BEYOND_64K
case 3: return u.format3.collect_coverage (glyphs);
case 4: return u.format4.collect_coverage (glyphs);
#endif
@@ -212,7 +210,7 @@ struct Coverage
{
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
+#ifndef HB_NO_BEYOND_64K
case 3: return u.format3.intersect_set (glyphs, intersect_glyphs);
case 4: return u.format4.intersect_set (glyphs, intersect_glyphs);
#endif
@@ -225,13 +223,13 @@ struct Coverage
static constexpr bool is_sorted_iterator = true;
iter_t (const Coverage &c_ = Null (Coverage))
{
- memset (this, 0, sizeof (*this));
+ hb_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
+#ifndef HB_NO_BEYOND_64K
case 3: u.format3.init (c_.u.format3); return;
case 4: u.format4.init (c_.u.format4); return;
#endif
@@ -244,7 +242,7 @@ struct Coverage
{
case 1: return u.format1.__more__ ();
case 2: return u.format2.__more__ ();
-#ifndef HB_NO_BORING_EXPANSION
+#ifndef HB_NO_BEYOND_64K
case 3: return u.format3.__more__ ();
case 4: return u.format4.__more__ ();
#endif
@@ -257,7 +255,7 @@ struct Coverage
{
case 1: u.format1.__next__ (); break;
case 2: u.format2.__next__ (); break;
-#ifndef HB_NO_BORING_EXPANSION
+#ifndef HB_NO_BEYOND_64K
case 3: u.format3.__next__ (); break;
case 4: u.format4.__next__ (); break;
#endif
@@ -273,7 +271,7 @@ struct Coverage
{
case 1: return u.format1.get_glyph ();
case 2: return u.format2.get_glyph ();
-#ifndef HB_NO_BORING_EXPANSION
+#ifndef HB_NO_BEYOND_64K
case 3: return u.format3.get_glyph ();
case 4: return u.format4.get_glyph ();
#endif
@@ -287,7 +285,7 @@ struct Coverage
{
case 1: return u.format1 != o.u.format1;
case 2: return u.format2 != o.u.format2;
-#ifndef HB_NO_BORING_EXPANSION
+#ifndef HB_NO_BEYOND_64K
case 3: return u.format3 != o.u.format3;
case 4: return u.format4 != o.u.format4;
#endif
@@ -302,7 +300,7 @@ struct Coverage
{
case 1: it.u.format1 = u.format1.__end__ (); break;
case 2: it.u.format2 = u.format2.__end__ (); break;
-#ifndef HB_NO_BORING_EXPANSION
+#ifndef HB_NO_BEYOND_64K
case 3: it.u.format3 = u.format3.__end__ (); break;
case 4: it.u.format4 = u.format4.__end__ (); break;
#endif
@@ -314,7 +312,7 @@ struct Coverage
private:
unsigned int format;
union {
-#ifndef HB_NO_BORING_EXPANSION
+#ifndef HB_NO_BEYOND_64K
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
diff --git a/thirdparty/harfbuzz/src/OT/Layout/Common/CoverageFormat1.hh b/thirdparty/harfbuzz/src/OT/Layout/Common/CoverageFormat1.hh
index 82fd48dc50..5d68e3d15e 100644
--- a/thirdparty/harfbuzz/src/OT/Layout/Common/CoverageFormat1.hh
+++ b/thirdparty/harfbuzz/src/OT/Layout/Common/CoverageFormat1.hh
@@ -77,7 +77,14 @@ struct CoverageFormat1_3
bool intersects (const hb_set_t *glyphs) const
{
- /* TODO Speed up, using hb_set_next() and bsearch()? */
+ if (glyphArray.len > glyphs->get_population () * hb_bit_storage ((unsigned) glyphArray.len) / 2)
+ {
+ for (hb_codepoint_t g = HB_SET_VALUE_INVALID; glyphs->next (&g);)
+ if (get_coverage (g) != NOT_COVERED)
+ return true;
+ return false;
+ }
+
for (const auto& g : glyphArray.as_array ())
if (glyphs->has (g))
return true;
diff --git a/thirdparty/harfbuzz/src/OT/Layout/Common/CoverageFormat2.hh b/thirdparty/harfbuzz/src/OT/Layout/Common/CoverageFormat2.hh
index 974d094633..d7fcc35202 100644
--- a/thirdparty/harfbuzz/src/OT/Layout/Common/CoverageFormat2.hh
+++ b/thirdparty/harfbuzz/src/OT/Layout/Common/CoverageFormat2.hh
@@ -80,8 +80,6 @@ struct CoverageFormat2_4
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)
@@ -115,26 +113,22 @@ struct CoverageFormat2_4
bool intersects (const hb_set_t *glyphs) const
{
+ if (rangeRecord.len > glyphs->get_population () * hb_bit_storage ((unsigned) rangeRecord.len) / 2)
+ {
+ for (hb_codepoint_t g = HB_SET_VALUE_INVALID; glyphs->next (&g);)
+ if (get_coverage (g) != NOT_COVERED)
+ return true;
+ return false;
+ }
+
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);
+ auto *range = rangeRecord.as_array ().bsearch (index);
+ if (range)
+ return range->intersects (*glyphs);
return false;
}
@@ -142,9 +136,14 @@ struct CoverageFormat2_4
hb_requires (hb_is_sink_of (IterableOut, hb_codepoint_t))>
void intersect_set (const hb_set_t &glyphs, IterableOut&& intersect_glyphs) const
{
+ /* Break out of loop for overlapping, broken, tables,
+ * to avoid fuzzer timouts. */
+ hb_codepoint_t last = 0;
for (const auto& range : rangeRecord)
{
- hb_codepoint_t last = range.last;
+ if (unlikely (range.first < last))
+ break;
+ last = range.last;
for (hb_codepoint_t g = range.first - 1;
glyphs.next (&g) && g <= last;)
intersect_glyphs << g;
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkBasePos.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkBasePos.hh
index c99b6b2e4b..edf7099c07 100644
--- a/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkBasePos.hh
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkBasePos.hh
@@ -13,7 +13,7 @@ struct MarkBasePos
union {
HBUINT16 format; /* Format identifier */
MarkBasePosFormat1_2<SmallTypes> format1;
-#ifndef HB_NO_BORING_EXPANSION
+#ifndef HB_NO_BEYOND_64K
MarkBasePosFormat1_2<MediumTypes> format2;
#endif
} u;
@@ -26,7 +26,7 @@ struct MarkBasePos
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
+#ifndef HB_NO_BEYOND_64K
case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
#endif
default:return_trace (c->default_return_value ());
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkLigPos.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkLigPos.hh
index 8a4de9ffaa..09152fd876 100644
--- a/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkLigPos.hh
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkLigPos.hh
@@ -13,7 +13,7 @@ struct MarkLigPos
union {
HBUINT16 format; /* Format identifier */
MarkLigPosFormat1_2<SmallTypes> format1;
-#ifndef HB_NO_BORING_EXPANSION
+#ifndef HB_NO_BEYOND_64K
MarkLigPosFormat1_2<MediumTypes> format2;
#endif
} u;
@@ -26,7 +26,7 @@ struct MarkLigPos
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
+#ifndef HB_NO_BEYOND_64K
case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
#endif
default:return_trace (c->default_return_value ());
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkMarkPos.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkMarkPos.hh
index 74b5105c42..4118fc304f 100644
--- a/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkMarkPos.hh
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkMarkPos.hh
@@ -13,7 +13,7 @@ struct MarkMarkPos
union {
HBUINT16 format; /* Format identifier */
MarkMarkPosFormat1_2<SmallTypes> format1;
-#ifndef HB_NO_BORING_EXPANSION
+#ifndef HB_NO_BEYOND_64K
MarkMarkPosFormat1_2<MediumTypes> format2;
#endif
} u;
@@ -26,7 +26,7 @@ struct MarkMarkPos
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
+#ifndef HB_NO_BEYOND_64K
case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
#endif
default:return_trace (c->default_return_value ());
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairPos.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairPos.hh
index 72bfc43dc4..9823768cbc 100644
--- a/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairPos.hh
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairPos.hh
@@ -15,7 +15,7 @@ struct PairPos
HBUINT16 format; /* Format identifier */
PairPosFormat1_3<SmallTypes> format1;
PairPosFormat2_4<SmallTypes> format2;
-#ifndef HB_NO_BORING_EXPANSION
+#ifndef HB_NO_BEYOND_64K
PairPosFormat1_3<MediumTypes> format3;
PairPosFormat2_4<MediumTypes> format4;
#endif
@@ -30,7 +30,7 @@ struct PairPos
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
+#ifndef HB_NO_BEYOND_64K
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
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairPosFormat1.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairPosFormat1.hh
index ddf7313f94..9c9b268889 100644
--- a/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairPosFormat1.hh
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairPosFormat1.hh
@@ -51,8 +51,21 @@ struct PairPosFormat1_3
bool intersects (const hb_set_t *glyphs) const
{
+ auto &cov = this+coverage;
+
+ if (pairSet.len > glyphs->get_population () * hb_bit_storage ((unsigned) pairSet.len) / 4)
+ {
+ for (hb_codepoint_t g = HB_SET_VALUE_INVALID; glyphs->next (&g);)
+ {
+ unsigned i = cov.get_coverage (g);
+ if ((this+pairSet[i]).intersects (glyphs, valueFormat))
+ return true;
+ }
+ return false;
+ }
+
return
- + hb_zip (this+coverage, pairSet)
+ + hb_zip (cov, pairSet)
| hb_filter (*glyphs, hb_first)
| hb_map (hb_second)
| hb_map ([glyphs, this] (const typename Types::template OffsetTo<PairSet> &_)
@@ -171,12 +184,16 @@ struct PairPosFormat1_3
unsigned format1 = 0;
unsigned format2 = 0;
for (const auto & _ :
- + hb_zip (this+coverage, pairSet) | hb_filter (glyphset, hb_first) | hb_map (hb_second))
+ + 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++)
+ unsigned count = set.len;
+ for (unsigned i = 0; i < count; i++)
{
if (record->intersects (glyphset))
{
@@ -185,6 +202,9 @@ struct PairPosFormat1_3
}
record = &StructAtOffset<const PairValueRecord> (record, record_size);
}
+
+ if (format1 == valueFormat[0] && format2 == valueFormat[1])
+ break;
}
return hb_pair (format1, format2);
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairPosFormat2.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairPosFormat2.hh
index 83b093b988..9c87ac2b03 100644
--- a/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairPosFormat2.hh
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairPosFormat2.hh
@@ -220,17 +220,25 @@ struct PairPosFormat2_4
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
{
c->buffer->message (c->font,
- "kerning glyphs at %d,%d",
+ "try 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 (applied_first || applied_second)
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->message (c->font,
+ "kerned glyphs at %d,%d",
+ c->buffer->idx, skippy_iter.idx);
+ }
+
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
{
c->buffer->message (c->font,
- "kerned glyphs at %d,%d",
+ "tried kerning glyphs at %d,%d",
c->buffer->idx, skippy_iter.idx);
}
@@ -241,10 +249,15 @@ struct PairPosFormat2_4
boring:
buffer->unsafe_to_concat (buffer->idx, skippy_iter.idx + 1);
+ if (len2)
+ {
+ skippy_iter.idx++;
+ // https://github.com/harfbuzz/harfbuzz/issues/3824
+ // https://github.com/harfbuzz/harfbuzz/issues/3888#issuecomment-1326781116
+ buffer->unsafe_to_break (buffer->idx, skippy_iter.idx + 1);
+ }
buffer->idx = skippy_iter.idx;
- if (len2)
- buffer->idx++;
return_trace (true);
}
@@ -309,6 +322,7 @@ struct PairPosFormat2_4
{
unsigned len1 = valueFormat1.get_len ();
unsigned len2 = valueFormat2.get_len ();
+ unsigned record_size = len1 + len2;
unsigned format1 = 0;
unsigned format2 = 0;
@@ -317,10 +331,13 @@ struct PairPosFormat2_4
{
for (unsigned class2_idx : + hb_range ((unsigned) class2Count) | hb_filter (klass2_map))
{
- unsigned idx = (class1_idx * (unsigned) class2Count + class2_idx) * (len1 + len2);
+ unsigned idx = (class1_idx * (unsigned) class2Count + class2_idx) * record_size;
format1 = format1 | valueFormat1.get_effective_format (&values[idx]);
format2 = format2 | valueFormat2.get_effective_format (&values[idx + len1]);
}
+
+ if (format1 == valueFormat1 && format2 == valueFormat2)
+ break;
}
return hb_pair (format1, format2);
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairSet.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairSet.hh
index aa48d933c3..a318f39913 100644
--- a/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairSet.hh
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairSet.hh
@@ -112,24 +112,38 @@ struct PairSet
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
{
c->buffer->message (c->font,
- "kerning glyphs at %d,%d",
+ "try 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 (applied_first || applied_second)
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->message (c->font,
+ "kerned glyphs at %d,%d",
+ c->buffer->idx, pos);
+ }
+
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
{
c->buffer->message (c->font,
- "kerned glyphs at %d,%d",
+ "tried kerning glyphs at %d,%d",
c->buffer->idx, pos);
}
if (applied_first || applied_second)
buffer->unsafe_to_break (buffer->idx, pos + 1);
+
if (len2)
- pos++;
+ {
+ pos++;
+ // https://github.com/harfbuzz/harfbuzz/issues/3824
+ // https://github.com/harfbuzz/harfbuzz/issues/3888#issuecomment-1326781116
+ buffer->unsafe_to_break (buffer->idx, pos + 1);
+ }
buffer->idx = pos;
return_trace (true);
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/AlternateSet.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/AlternateSet.hh
index 4a9e9672eb..6c50c9717a 100644
--- a/thirdparty/harfbuzz/src/OT/Layout/GSUB/AlternateSet.hh
+++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/AlternateSet.hh
@@ -84,7 +84,7 @@ struct AlternateSet
{
if (alternates.len && alternate_count)
{
- + alternates.sub_array (start_offset, alternate_count)
+ + alternates.as_array ().sub_array (start_offset, alternate_count)
| hb_sink (hb_array (alternate_glyphs, *alternate_count))
;
}
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/AlternateSubst.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/AlternateSubst.hh
index 37406179a2..9d7cd6fddf 100644
--- a/thirdparty/harfbuzz/src/OT/Layout/GSUB/AlternateSubst.hh
+++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/AlternateSubst.hh
@@ -14,7 +14,7 @@ struct AlternateSubst
union {
HBUINT16 format; /* Format identifier */
AlternateSubstFormat1_2<SmallTypes> format1;
-#ifndef HB_NO_BORING_EXPANSION
+#ifndef HB_NO_BEYOND_64K
AlternateSubstFormat1_2<MediumTypes> format2;
#endif
} u;
@@ -27,7 +27,7 @@ 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
+#ifndef HB_NO_BEYOND_64K
case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
#endif
default:return_trace (c->default_return_value ());
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/Ligature.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/Ligature.hh
index 6caa80e056..cdb35f525b 100644
--- a/thirdparty/harfbuzz/src/OT/Layout/GSUB/Ligature.hh
+++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/Ligature.hh
@@ -118,7 +118,7 @@ struct Ligature
match_positions[i] += delta;
if (i)
*p++ = ',';
- snprintf (p, sizeof(buf), "%u", match_positions[i]);
+ snprintf (p, sizeof(buf) - (p - buf), "%u", match_positions[i]);
p += strlen(p);
}
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/LigatureSubst.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/LigatureSubst.hh
index 63707972a8..7ba19e844c 100644
--- a/thirdparty/harfbuzz/src/OT/Layout/GSUB/LigatureSubst.hh
+++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/LigatureSubst.hh
@@ -14,7 +14,7 @@ struct LigatureSubst
union {
HBUINT16 format; /* Format identifier */
LigatureSubstFormat1_2<SmallTypes> format1;
-#ifndef HB_NO_BORING_EXPANSION
+#ifndef HB_NO_BEYOND_64K
LigatureSubstFormat1_2<MediumTypes> format2;
#endif
} u;
@@ -27,7 +27,7 @@ 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
+#ifndef HB_NO_BEYOND_64K
case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
#endif
default:return_trace (c->default_return_value ());
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/MultipleSubst.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/MultipleSubst.hh
index 852ca3eac5..95710ed2be 100644
--- a/thirdparty/harfbuzz/src/OT/Layout/GSUB/MultipleSubst.hh
+++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/MultipleSubst.hh
@@ -14,7 +14,7 @@ struct MultipleSubst
union {
HBUINT16 format; /* Format identifier */
MultipleSubstFormat1_2<SmallTypes> format1;
-#ifndef HB_NO_BORING_EXPANSION
+#ifndef HB_NO_BEYOND_64K
MultipleSubstFormat1_2<MediumTypes> format2;
#endif
} u;
@@ -28,7 +28,7 @@ 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
+#ifndef HB_NO_BEYOND_64K
case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
#endif
default:return_trace (c->default_return_value ());
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/Sequence.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/Sequence.hh
index abf1c643ff..e2190078b8 100644
--- a/thirdparty/harfbuzz/src/OT/Layout/GSUB/Sequence.hh
+++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/Sequence.hh
@@ -117,7 +117,7 @@ struct Sequence
{
if (buf < p)
*p++ = ',';
- snprintf (p, sizeof(buf), "%u", i);
+ snprintf (p, sizeof(buf) - (p - buf), "%u", i);
p += strlen(p);
}
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/SingleSubst.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/SingleSubst.hh
index 6942e6997f..7da8103168 100644
--- a/thirdparty/harfbuzz/src/OT/Layout/GSUB/SingleSubst.hh
+++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/SingleSubst.hh
@@ -16,7 +16,7 @@ struct SingleSubst
HBUINT16 format; /* Format identifier */
SingleSubstFormat1_3<SmallTypes> format1;
SingleSubstFormat2_4<SmallTypes> format2;
-#ifndef HB_NO_BORING_EXPANSION
+#ifndef HB_NO_BEYOND_64K
SingleSubstFormat1_3<MediumTypes> format3;
SingleSubstFormat2_4<MediumTypes> format4;
#endif
@@ -32,7 +32,7 @@ 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
+#ifndef HB_NO_BEYOND_64K
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
@@ -55,7 +55,7 @@ struct SingleSubst
format = 1;
hb_codepoint_t mask = 0xFFFFu;
-#ifndef HB_NO_BORING_EXPANSION
+#ifndef HB_NO_BEYOND_64K
if (+ glyphs
| hb_map_retains_sorting (hb_first)
| hb_filter ([] (hb_codepoint_t gid) { return gid > 0xFFFFu; }))
@@ -78,7 +78,7 @@ struct SingleSubst
| hb_map_retains_sorting (hb_first),
delta));
case 2: return_trace (u.format2.serialize (c, glyphs));
-#ifndef HB_NO_BORING_EXPANSION
+#ifndef HB_NO_BEYOND_64K
case 3: return_trace (u.format3.serialize (c,
+ glyphs
| hb_map_retains_sorting (hb_first),
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/SingleSubstFormat1.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/SingleSubstFormat1.hh
index 13665d7ba1..1be21b98bc 100644
--- a/thirdparty/harfbuzz/src/OT/Layout/GSUB/SingleSubstFormat1.hh
+++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/SingleSubstFormat1.hh
@@ -57,7 +57,7 @@ struct SingleSubstFormat1_3
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 (pop >= max_before - min_before &&
+ if (intersection.get_population () == max_before - min_before + 1 &&
((min_before <= min_after && min_after <= max_before) ||
(min_before <= max_after && max_after <= max_before)))
return;
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/SingleSubstFormat2.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/SingleSubstFormat2.hh
index 5416299754..01df714525 100644
--- a/thirdparty/harfbuzz/src/OT/Layout/GSUB/SingleSubstFormat2.hh
+++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/SingleSubstFormat2.hh
@@ -36,8 +36,24 @@ struct SingleSubstFormat2_4
void closure (hb_closure_context_t *c) const
{
- + hb_zip (this+coverage, substitute)
- | hb_filter (c->parent_active_glyphs (), hb_first)
+ auto &cov = this+coverage;
+ auto &glyph_set = c->parent_active_glyphs ();
+
+ if (substitute.len > glyph_set.get_population () * 4)
+ {
+ for (auto g : glyph_set)
+ {
+ unsigned i = cov.get_coverage (g);
+ if (i == NOT_COVERED || i >= substitute.len)
+ continue;
+ c->output->add (substitute.arrayZ[i]);
+ }
+
+ return;
+ }
+
+ + hb_zip (cov, substitute)
+ | hb_filter (glyph_set, hb_first)
| hb_map (hb_second)
| hb_sink (c->output)
;
diff --git a/thirdparty/harfbuzz/src/OT/glyf/CompositeGlyph.hh b/thirdparty/harfbuzz/src/OT/glyf/CompositeGlyph.hh
index fc8e309bc9..edf8cd8797 100644
--- a/thirdparty/harfbuzz/src/OT/glyf/CompositeGlyph.hh
+++ b/thirdparty/harfbuzz/src/OT/glyf/CompositeGlyph.hh
@@ -3,6 +3,7 @@
#include "../../hb-open-type.hh"
+#include "composite-iter.hh"
namespace OT {
@@ -121,7 +122,7 @@ struct CompositeGlyphRecord
if (flags & ARG_1_AND_2_ARE_WORDS)
{
// no overflow, copy and update value with deltas
- memcpy (out, this, len);
+ hb_memcpy (out, this, len);
const HBINT16 *px = reinterpret_cast<const HBINT16 *> (p);
HBINT16 *o = reinterpret_cast<HBINT16 *> (out + len_before_val);
@@ -135,7 +136,7 @@ struct CompositeGlyphRecord
if (new_x <= 127 && new_x >= -128 &&
new_y <= 127 && new_y >= -128)
{
- memcpy (out, this, len);
+ hb_memcpy (out, this, len);
HBINT8 *o = reinterpret_cast<HBINT8 *> (out + len_before_val);
o[0] = new_x;
o[1] = new_y;
@@ -143,7 +144,7 @@ struct CompositeGlyphRecord
else
{
// int8 overflows after deltas applied
- memcpy (out, this, len_before_val);
+ hb_memcpy (out, this, len_before_val);
//update flags
CompositeGlyphRecord *o = reinterpret_cast<CompositeGlyphRecord *> (out);
@@ -152,14 +153,14 @@ struct CompositeGlyphRecord
HBINT16 new_value;
new_value = new_x;
- memcpy (out, &new_value, HBINT16::static_size);
+ hb_memcpy (out, &new_value, HBINT16::static_size);
out += HBINT16::static_size;
new_value = new_y;
- memcpy (out, &new_value, HBINT16::static_size);
+ hb_memcpy (out, &new_value, HBINT16::static_size);
out += HBINT16::static_size;
- memcpy (out, p+2, len - len_before_val - 2);
+ hb_memcpy (out, p+2, len - len_before_val - 2);
len += 2;
}
}
@@ -252,55 +253,7 @@ struct CompositeGlyphRecord
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;
-};
+using composite_iter_t = composite_iter_tmpl<CompositeGlyphRecord>;
struct CompositeGlyph
{
@@ -382,7 +335,7 @@ struct CompositeGlyph
unsigned comp_len = component.get_size ();
if (component.is_anchored ())
{
- memcpy (p, &component, comp_len);
+ hb_memcpy (p, &component, comp_len);
p += comp_len;
}
else
@@ -398,7 +351,7 @@ struct CompositeGlyph
if (source_len > source_comp_len)
{
unsigned instr_len = source_len - source_comp_len;
- memcpy (p, (const char *)c + source_comp_len, instr_len);
+ hb_memcpy (p, (const char *)c + source_comp_len, instr_len);
p += instr_len;
}
diff --git a/thirdparty/harfbuzz/src/OT/glyf/Glyph.hh b/thirdparty/harfbuzz/src/OT/glyf/Glyph.hh
index 0b25659acc..b7215b0170 100644
--- a/thirdparty/harfbuzz/src/OT/glyf/Glyph.hh
+++ b/thirdparty/harfbuzz/src/OT/glyf/Glyph.hh
@@ -7,6 +7,8 @@
#include "GlyphHeader.hh"
#include "SimpleGlyph.hh"
#include "CompositeGlyph.hh"
+#include "VarCompositeGlyph.hh"
+#include "coord-setter.hh"
namespace OT {
@@ -16,6 +18,11 @@ struct glyf_accelerator_t;
namespace glyf_impl {
+#ifndef HB_GLYF_MAX_POINTS
+#define HB_GLYF_MAX_POINTS 10000
+#endif
+
+
enum phantom_point_index_t
{
PHANTOM_LEFT = 0,
@@ -27,7 +34,7 @@ enum phantom_point_index_t
struct Glyph
{
- enum glyph_type_t { EMPTY, SIMPLE, COMPOSITE };
+ enum glyph_type_t { EMPTY, SIMPLE, COMPOSITE, VAR_COMPOSITE };
public:
composite_iter_t get_composite_iterator () const
@@ -35,6 +42,11 @@ struct Glyph
if (type != COMPOSITE) return composite_iter_t ();
return CompositeGlyph (*header, bytes).iter ();
}
+ var_composite_iter_t get_var_composite_iterator () const
+ {
+ if (type != VAR_COMPOSITE) return var_composite_iter_t ();
+ return VarCompositeGlyph (*header, bytes).iter ();
+ }
const hb_bytes_t trim_padding () const
{
@@ -108,25 +120,25 @@ struct Glyph
if (unlikely (!glyph_header)) return false;
}
- int xMin = 0, xMax = 0;
- int yMin = 0, yMax = 0;
+ float xMin = 0, xMax = 0;
+ float yMin = 0, yMax = 0;
if (all_points.length > 4)
{
- xMin = xMax = roundf (all_points[0].x);
- yMin = yMax = roundf (all_points[0].y);
+ xMin = xMax = all_points[0].x;
+ yMin = yMax = all_points[0].y;
}
for (unsigned i = 1; i < all_points.length - 4; i++)
{
- float rounded_x = roundf (all_points[i].x);
- float rounded_y = roundf (all_points[i].y);
- xMin = hb_min (xMin, rounded_x);
- xMax = hb_max (xMax, rounded_x);
- yMin = hb_min (yMin, rounded_y);
- yMax = hb_max (yMax, rounded_y);
+ float x = all_points[i].x;
+ float y = all_points[i].y;
+ xMin = hb_min (xMin, x);
+ xMax = hb_max (xMax, x);
+ yMin = hb_min (yMin, y);
+ yMax = hb_max (yMax, y);
}
- update_mtx (plan, xMin, yMax, all_points);
+ update_mtx (plan, roundf (xMin), roundf (yMax), all_points);
/*for empty glyphs: all_points only include phantom points.
*just update metrics and then return */
@@ -134,10 +146,10 @@ struct Glyph
return true;
glyph_header->numberOfContours = header->numberOfContours;
- glyph_header->xMin = xMin;
- glyph_header->yMin = yMin;
- glyph_header->xMax = xMax;
- glyph_header->yMax = yMax;
+ glyph_header->xMin = roundf (xMin);
+ glyph_header->yMin = roundf (yMin);
+ glyph_header->xMax = roundf (xMax);
+ glyph_header->yMax = roundf (yMax);
dest_bytes = hb_bytes_t ((const char *)glyph_header, GlyphHeader::static_size);
return true;
@@ -199,15 +211,24 @@ struct Glyph
bool shift_points_hori = true,
bool use_my_metrics = true,
bool phantom_only = false,
+ hb_array_t<int> coords = hb_array_t<int> (),
unsigned int depth = 0) const
{
if (unlikely (depth > HB_MAX_NESTING_LEVEL)) return false;
+
+ if (!coords)
+ coords = hb_array (font->coords, font->num_coords);
+
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 SIMPLE:
+ if (unlikely (!SimpleGlyph (*header, bytes).get_contour_points (points, phantom_only)))
+ return false;
+ break;
case COMPOSITE:
{
/* pseudo component points for each component in composite glyph */
@@ -215,20 +236,25 @@ struct Glyph
if (unlikely (!points.resize (num_points))) return false;
break;
}
- case SIMPLE:
- if (unlikely (!SimpleGlyph (*header, bytes).get_contour_points (points, phantom_only)))
- return false;
+#ifndef HB_NO_VAR_COMPOSITES
+ case VAR_COMPOSITE:
+ {
+ for (auto &item : get_var_composite_iterator ())
+ if (unlikely (!item.get_points (points))) return false;
+ }
+#endif
+ default:
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);
+ hb_array_t<contour_point_t> phantoms = points.as_array ().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;
+ HB_UNUSED 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)
@@ -257,7 +283,9 @@ struct Glyph
}
#ifndef HB_NO_VAR
- glyf_accelerator.gvar->apply_deltas_to_points (gid, font, points.as_array ());
+ glyf_accelerator.gvar->apply_deltas_to_points (gid,
+ coords,
+ points.as_array ());
#endif
// mainly used by CompositeGlyph calculating new X/Y offset value so no need to extend it
@@ -283,11 +311,24 @@ struct Glyph
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,
- deltas, shift_points_hori, use_my_metrics, phantom_only, depth + 1)))
+ .get_points (font,
+ glyf_accelerator,
+ comp_points,
+ deltas,
+ shift_points_hori,
+ use_my_metrics,
+ phantom_only,
+ coords,
+ depth + 1)))
return false;
+ /* Copy phantom points from component if USE_MY_METRICS flag set */
+ if (use_my_metrics && 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);
@@ -308,20 +349,63 @@ struct Glyph
}
}
+ all_points.extend (comp_points.as_array ().sub_array (0, comp_points.length - PHANTOM_COUNT));
+
+ if (all_points.length > HB_GLYF_MAX_POINTS)
+ return false;
+
+ comp_index++;
+ }
+
+ all_points.extend (phantoms);
+ } break;
+#ifndef HB_NO_VAR_COMPOSITES
+ case VAR_COMPOSITE:
+ {
+ contour_point_vector_t comp_points;
+ hb_array_t<contour_point_t> points_left = points.as_array ();
+ for (auto &item : get_var_composite_iterator ())
+ {
+ hb_array_t<contour_point_t> record_points = points_left.sub_array (0, item.get_num_points ());
+
+ comp_points.reset ();
+
+ coord_setter_t coord_setter (coords);
+ item.set_variations (coord_setter, record_points);
+
+ if (unlikely (!glyf_accelerator.glyph_for_gid (item.get_gid ())
+ .get_points (font,
+ glyf_accelerator,
+ comp_points,
+ deltas,
+ shift_points_hori,
+ use_my_metrics,
+ phantom_only,
+ coord_setter.get_coords (),
+ depth + 1)))
+ return false;
+
+ /* Apply component transformation */
+ item.transform_points (record_points, comp_points);
+
/* Copy phantom points from component if USE_MY_METRICS flag set */
if (use_my_metrics && item.is_use_my_metrics ())
for (unsigned int i = 0; i < PHANTOM_COUNT; i++)
phantoms[i] = comp_points[comp_points.length - PHANTOM_COUNT + i];
- all_points.extend (comp_points.sub_array (0, comp_points.length - PHANTOM_COUNT));
+ all_points.extend (comp_points.as_array ().sub_array (0, comp_points.length - PHANTOM_COUNT));
- comp_index++;
- }
+ if (all_points.length > HB_GLYF_MAX_POINTS)
+ return false;
+ points_left += item.get_num_points ();
+ }
all_points.extend (phantoms);
} break;
+#endif
default:
all_points.extend (phantoms);
+ break;
}
if (depth == 0 && shift_points_hori) /* Apply at top level */
@@ -360,6 +444,7 @@ struct Glyph
int num_contours = header->numberOfContours;
if (unlikely (num_contours == 0)) type = EMPTY;
else if (num_contours > 0) type = SIMPLE;
+ else if (num_contours == -2) type = VAR_COMPOSITE;
else type = COMPOSITE; /* negative numbers */
}
diff --git a/thirdparty/harfbuzz/src/OT/glyf/SimpleGlyph.hh b/thirdparty/harfbuzz/src/OT/glyf/SimpleGlyph.hh
index d45f4eb350..2b4aa99d25 100644
--- a/thirdparty/harfbuzz/src/OT/glyf/SimpleGlyph.hh
+++ b/thirdparty/harfbuzz/src/OT/glyf/SimpleGlyph.hh
@@ -132,8 +132,8 @@ struct SimpleGlyph
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;
+ for (; i < stop; i++)
+ points_.arrayZ[i].flag = flag;
}
}
return true;
@@ -223,33 +223,34 @@ struct SimpleGlyph
if (value > 0) flag |= same_flag;
else value = -value;
- coords.push ((uint8_t)value);
+ coords.arrayZ[coords.length++] = (uint8_t) value;
}
else
{
int16_t val = value;
- coords.push (val >> 8);
- coords.push (val & 0xff);
+ coords.arrayZ[coords.length++] = val >> 8;
+ coords.arrayZ[coords.length++] = val & 0xff;
}
}
static void encode_flag (uint8_t &flag,
uint8_t &repeat,
- uint8_t &lastflag,
+ uint8_t lastflag,
hb_vector_t<uint8_t> &flags /* OUT */)
{
if (flag == lastflag && repeat != 255)
{
- repeat = repeat + 1;
+ repeat++;
if (repeat == 1)
{
- flags.push(flag);
+ /* We know there's room. */
+ flags.arrayZ[flags.length++] = flag;
}
else
{
unsigned len = flags.length;
- flags[len-2] = flag | FLAG_REPEAT;
- flags[len-1] = repeat;
+ flags.arrayZ[len-2] = flag | FLAG_REPEAT;
+ flags.arrayZ[len-1] = repeat;
}
}
else
@@ -257,7 +258,6 @@ struct SimpleGlyph
repeat = 0;
flags.push (flag);
}
- lastflag = flag;
}
bool compile_bytes_with_deltas (const contour_point_vector_t &all_points,
@@ -269,7 +269,6 @@ struct SimpleGlyph
dest_bytes = hb_bytes_t ();
return true;
}
- //convert absolute values to relative values
unsigned num_points = all_points.length - 4;
hb_vector_t<uint8_t> flags, x_coords, y_coords;
@@ -277,23 +276,23 @@ struct SimpleGlyph
if (unlikely (!x_coords.alloc (2*num_points))) return false;
if (unlikely (!y_coords.alloc (2*num_points))) return false;
- uint8_t lastflag = 0, repeat = 0;
- int prev_x = 0.f, prev_y = 0.f;
-
+ uint8_t lastflag = 255, repeat = 0;
+ int prev_x = 0, prev_y = 0;
+
for (unsigned i = 0; i < num_points; i++)
{
- uint8_t flag = all_points[i].flag;
+ uint8_t flag = all_points.arrayZ[i].flag;
flag &= FLAG_ON_CURVE + FLAG_OVERLAP_SIMPLE;
- float cur_x = roundf (all_points[i].x);
- float cur_y = roundf (all_points[i].y);
+ int cur_x = roundf (all_points.arrayZ[i].x);
+ int cur_y = roundf (all_points.arrayZ[i].y);
encode_coord (cur_x - prev_x, flag, FLAG_X_SHORT, FLAG_X_SAME, x_coords);
encode_coord (cur_y - prev_y, flag, FLAG_Y_SHORT, FLAG_Y_SAME, y_coords);
- if (i == 0) lastflag = flag + 1; //make lastflag != flag for the first point
encode_flag (flag, repeat, lastflag, flags);
prev_x = cur_x;
prev_y = cur_y;
+ lastflag = flag;
}
unsigned len_before_instrs = 2 * header.numberOfContours + 2;
@@ -303,29 +302,29 @@ struct SimpleGlyph
if (!no_hinting)
total_len += len_instrs;
- char *p = (char *) hb_calloc (total_len, sizeof (char));
+ char *p = (char *) hb_malloc (total_len);
if (unlikely (!p)) return false;
const char *src = bytes.arrayZ + GlyphHeader::static_size;
char *cur = p;
- memcpy (p, src, len_before_instrs);
+ hb_memcpy (p, src, len_before_instrs);
cur += len_before_instrs;
src += len_before_instrs;
if (!no_hinting)
{
- memcpy (cur, src, len_instrs);
+ hb_memcpy (cur, src, len_instrs);
cur += len_instrs;
}
- memcpy (cur, flags.arrayZ, flags.length);
+ hb_memcpy (cur, flags.arrayZ, flags.length);
cur += flags.length;
- memcpy (cur, x_coords.arrayZ, x_coords.length);
+ hb_memcpy (cur, x_coords.arrayZ, x_coords.length);
cur += x_coords.length;
- memcpy (cur, y_coords.arrayZ, y_coords.length);
+ hb_memcpy (cur, y_coords.arrayZ, y_coords.length);
dest_bytes = hb_bytes_t (p, total_len);
return true;
diff --git a/thirdparty/harfbuzz/src/OT/glyf/SubsetGlyph.hh b/thirdparty/harfbuzz/src/OT/glyf/SubsetGlyph.hh
index 88fc93c435..1a0370c757 100644
--- a/thirdparty/harfbuzz/src/OT/glyf/SubsetGlyph.hh
+++ b/thirdparty/harfbuzz/src/OT/glyf/SubsetGlyph.hh
@@ -21,10 +21,18 @@ struct SubsetGlyph
bool serialize (hb_serialize_context_t *c,
bool use_short_loca,
- const hb_subset_plan_t *plan) const
+ const hb_subset_plan_t *plan,
+ hb_font_t *font)
{
TRACE_SERIALIZE (this);
+ if (font)
+ {
+ const OT::glyf_accelerator_t &glyf = *font->face->table.glyf;
+ if (!this->compile_bytes_with_deltas (plan, font, glyf))
+ return_trace (false);
+ }
+
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;
diff --git a/thirdparty/harfbuzz/src/OT/glyf/VarCompositeGlyph.hh b/thirdparty/harfbuzz/src/OT/glyf/VarCompositeGlyph.hh
new file mode 100644
index 0000000000..0f4c71c83d
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/glyf/VarCompositeGlyph.hh
@@ -0,0 +1,353 @@
+#ifndef OT_GLYF_VARCOMPOSITEGLYPH_HH
+#define OT_GLYF_VARCOMPOSITEGLYPH_HH
+
+
+#include "../../hb-open-type.hh"
+#include "coord-setter.hh"
+
+
+namespace OT {
+namespace glyf_impl {
+
+
+struct VarCompositeGlyphRecord
+{
+ protected:
+ enum var_composite_glyph_flag_t
+ {
+ USE_MY_METRICS = 0x0001,
+ AXIS_INDICES_ARE_SHORT = 0x0002,
+ UNIFORM_SCALE = 0x0004,
+ HAVE_TRANSLATE_X = 0x0008,
+ HAVE_TRANSLATE_Y = 0x0010,
+ HAVE_ROTATION = 0x0020,
+ HAVE_SCALE_X = 0x0040,
+ HAVE_SCALE_Y = 0x0080,
+ HAVE_SKEW_X = 0x0100,
+ HAVE_SKEW_Y = 0x0200,
+ HAVE_TCENTER_X = 0x0400,
+ HAVE_TCENTER_Y = 0x0800,
+ GID_IS_24 = 0x1000,
+ AXES_HAVE_VARIATION = 0x2000,
+ };
+
+ public:
+
+ unsigned int get_size () const
+ {
+ unsigned int size = min_size;
+
+ unsigned axis_width = (flags & AXIS_INDICES_ARE_SHORT) ? 4 : 3;
+ size += numAxes * axis_width;
+
+ // gid
+ size += 2;
+ if (flags & GID_IS_24) size += 1;
+
+ if (flags & HAVE_TRANSLATE_X) size += 2;
+ if (flags & HAVE_TRANSLATE_Y) size += 2;
+ if (flags & HAVE_ROTATION) size += 2;
+ if (flags & HAVE_SCALE_X) size += 2;
+ if (flags & HAVE_SCALE_Y) size += 2;
+ if (flags & HAVE_SKEW_X) size += 2;
+ if (flags & HAVE_SKEW_Y) size += 2;
+ if (flags & HAVE_TCENTER_X) size += 2;
+ if (flags & HAVE_TCENTER_Y) size += 2;
+
+ return size;
+ }
+
+ bool has_more () const { return true; }
+
+ bool is_use_my_metrics () const { return flags & USE_MY_METRICS; }
+
+ hb_codepoint_t get_gid () const
+ {
+ if (flags & GID_IS_24)
+ return StructAfter<const HBGlyphID24> (numAxes);
+ else
+ return StructAfter<const HBGlyphID16> (numAxes);
+ }
+
+ unsigned get_numAxes () const
+ {
+ return numAxes;
+ }
+
+ unsigned get_num_points () const
+ {
+ unsigned num = 0;
+ if (flags & AXES_HAVE_VARIATION) num += numAxes;
+ if (flags & (HAVE_TRANSLATE_X | HAVE_TRANSLATE_Y)) num++;
+ if (flags & HAVE_ROTATION) num++;
+ if (flags & (HAVE_SCALE_X | HAVE_SCALE_Y)) num++;
+ if (flags & (HAVE_SKEW_X | HAVE_SKEW_Y)) num++;
+ if (flags & (HAVE_TCENTER_X | HAVE_TCENTER_Y)) num++;
+ return num;
+ }
+
+ void transform_points (hb_array_t<contour_point_t> record_points,
+ contour_point_vector_t &points) const
+ {
+ float matrix[4];
+ contour_point_t trans;
+
+ get_transformation_from_points (record_points, matrix, trans);
+
+ points.transform (matrix);
+ points.translate (trans);
+ }
+
+ static inline void transform (float (&matrix)[4], contour_point_t &trans,
+ float (other)[6])
+ {
+ // https://github.com/fonttools/fonttools/blob/f66ee05f71c8b57b5f519ee975e95edcd1466e14/Lib/fontTools/misc/transform.py#L268
+ float xx1 = other[0];
+ float xy1 = other[1];
+ float yx1 = other[2];
+ float yy1 = other[3];
+ float dx1 = other[4];
+ float dy1 = other[5];
+ float xx2 = matrix[0];
+ float xy2 = matrix[1];
+ float yx2 = matrix[2];
+ float yy2 = matrix[3];
+ float dx2 = trans.x;
+ float dy2 = trans.y;
+
+ matrix[0] = xx1*xx2 + xy1*yx2;
+ matrix[1] = xx1*xy2 + xy1*yy2;
+ matrix[2] = yx1*xx2 + yy1*yx2;
+ matrix[3] = yx1*xy2 + yy1*yy2;
+ trans.x = xx2*dx1 + yx2*dy1 + dx2;
+ trans.y = xy2*dx1 + yy2*dy1 + dy2;
+ }
+
+ static void translate (float (&matrix)[4], contour_point_t &trans,
+ float translateX, float translateY)
+ {
+ // https://github.com/fonttools/fonttools/blob/f66ee05f71c8b57b5f519ee975e95edcd1466e14/Lib/fontTools/misc/transform.py#L213
+ float other[6] = {1.f, 0.f, 0.f, 1.f, translateX, translateY};
+ transform (matrix, trans, other);
+ }
+
+ static void scale (float (&matrix)[4], contour_point_t &trans,
+ float scaleX, float scaleY)
+ {
+ // https://github.com/fonttools/fonttools/blob/f66ee05f71c8b57b5f519ee975e95edcd1466e14/Lib/fontTools/misc/transform.py#L224
+ float other[6] = {scaleX, 0.f, 0.f, scaleY, 0.f, 0.f};
+ transform (matrix, trans, other);
+ }
+
+ static void rotate (float (&matrix)[4], contour_point_t &trans,
+ float rotation)
+ {
+ // https://github.com/fonttools/fonttools/blob/f66ee05f71c8b57b5f519ee975e95edcd1466e14/Lib/fontTools/misc/transform.py#L240
+ rotation = rotation * float (M_PI);
+ float c = cosf (rotation);
+ float s = sinf (rotation);
+ float other[6] = {c, s, -s, c, 0.f, 0.f};
+ transform (matrix, trans, other);
+ }
+
+ static void skew (float (&matrix)[4], contour_point_t &trans,
+ float skewX, float skewY)
+ {
+ // https://github.com/fonttools/fonttools/blob/f66ee05f71c8b57b5f519ee975e95edcd1466e14/Lib/fontTools/misc/transform.py#L255
+ skewX = skewX * float (M_PI);
+ skewY = skewY * float (M_PI);
+ float other[6] = {1.f, tanf (skewY), tanf (skewX), 1.f, 0.f, 0.f};
+ transform (matrix, trans, other);
+ }
+
+ bool get_points (contour_point_vector_t &points) const
+ {
+ float translateX = 0.f;
+ float translateY = 0.f;
+ float rotation = 0.f;
+ float scaleX = 1.f * (1 << 12);
+ float scaleY = 1.f * (1 << 12);
+ float skewX = 0.f;
+ float skewY = 0.f;
+ float tCenterX = 0.f;
+ float tCenterY = 0.f;
+
+ if (unlikely (!points.resize (points.length + get_num_points ()))) return false;
+
+ unsigned axis_width = (flags & AXIS_INDICES_ARE_SHORT) ? 2 : 1;
+ unsigned axes_size = numAxes * axis_width;
+
+ const F2DOT14 *q = (const F2DOT14 *) (axes_size +
+ (flags & GID_IS_24 ? 3 : 2) +
+ &StructAfter<const HBUINT8> (numAxes));
+
+ hb_array_t<contour_point_t> rec_points = points.as_array ().sub_array (points.length - get_num_points ());
+
+ unsigned count = numAxes;
+ if (flags & AXES_HAVE_VARIATION)
+ {
+ for (unsigned i = 0; i < count; i++)
+ rec_points[i].x = *q++;
+ rec_points += count;
+ }
+ else
+ q += count;
+
+ const HBUINT16 *p = (const HBUINT16 *) q;
+
+ if (flags & HAVE_TRANSLATE_X) translateX = * (const FWORD *) p++;
+ if (flags & HAVE_TRANSLATE_Y) translateY = * (const FWORD *) p++;
+ if (flags & HAVE_ROTATION) rotation = * (const F2DOT14 *) p++;
+ if (flags & HAVE_SCALE_X) scaleX = * (const F4DOT12 *) p++;
+ if (flags & HAVE_SCALE_Y) scaleY = * (const F4DOT12 *) p++;
+ if (flags & HAVE_SKEW_X) skewX = * (const F2DOT14 *) p++;
+ if (flags & HAVE_SKEW_Y) skewY = * (const F2DOT14 *) p++;
+ if (flags & HAVE_TCENTER_X) tCenterX = * (const FWORD *) p++;
+ if (flags & HAVE_TCENTER_Y) tCenterY = * (const FWORD *) p++;
+
+ if ((flags & UNIFORM_SCALE) && !(flags & HAVE_SCALE_Y))
+ scaleY = scaleX;
+
+ if (flags & (HAVE_TRANSLATE_X | HAVE_TRANSLATE_Y))
+ {
+ rec_points[0].x = translateX;
+ rec_points[0].y = translateY;
+ rec_points++;
+ }
+ if (flags & HAVE_ROTATION)
+ {
+ rec_points[0].x = rotation;
+ rec_points++;
+ }
+ if (flags & (HAVE_SCALE_X | HAVE_SCALE_Y))
+ {
+ rec_points[0].x = scaleX;
+ rec_points[0].y = scaleY;
+ rec_points++;
+ }
+ if (flags & (HAVE_SKEW_X | HAVE_SKEW_Y))
+ {
+ rec_points[0].x = skewX;
+ rec_points[0].y = skewY;
+ rec_points++;
+ }
+ if (flags & (HAVE_TCENTER_X | HAVE_TCENTER_Y))
+ {
+ rec_points[0].x = tCenterX;
+ rec_points[0].y = tCenterY;
+ rec_points++;
+ }
+ assert (!rec_points);
+
+ return true;
+ }
+
+ void get_transformation_from_points (hb_array_t<contour_point_t> rec_points,
+ float (&matrix)[4], contour_point_t &trans) const
+ {
+ if (flags & AXES_HAVE_VARIATION)
+ rec_points += numAxes;
+
+ matrix[0] = matrix[3] = 1.f;
+ matrix[1] = matrix[2] = 0.f;
+ trans.init (0.f, 0.f);
+
+ float translateX = 0.f;
+ float translateY = 0.f;
+ float rotation = 0.f;
+ float scaleX = 1.f;
+ float scaleY = 1.f;
+ float skewX = 0.f;
+ float skewY = 0.f;
+ float tCenterX = 0.f;
+ float tCenterY = 0.f;
+
+ if (flags & (HAVE_TRANSLATE_X | HAVE_TRANSLATE_Y))
+ {
+ translateX = rec_points[0].x;
+ translateY = rec_points[0].y;
+ rec_points++;
+ }
+ if (flags & HAVE_ROTATION)
+ {
+ rotation = rec_points[0].x / (1 << 14);
+ rec_points++;
+ }
+ if (flags & (HAVE_SCALE_X | HAVE_SCALE_Y))
+ {
+ scaleX = rec_points[0].x / (1 << 12);
+ scaleY = rec_points[0].y / (1 << 12);
+ rec_points++;
+ }
+ if (flags & (HAVE_SKEW_X | HAVE_SKEW_Y))
+ {
+ skewX = rec_points[0].x / (1 << 14);
+ skewY = rec_points[0].y / (1 << 14);
+ rec_points++;
+ }
+ if (flags & (HAVE_TCENTER_X | HAVE_TCENTER_Y))
+ {
+ tCenterX = rec_points[0].x;
+ tCenterY = rec_points[0].y;
+ rec_points++;
+ }
+ assert (!rec_points);
+
+ translate (matrix, trans, translateX + tCenterX, translateY + tCenterY);
+ rotate (matrix, trans, rotation);
+ scale (matrix, trans, scaleX, scaleY);
+ skew (matrix, trans, -skewX, skewY);
+ translate (matrix, trans, -tCenterX, -tCenterY);
+ }
+
+ void set_variations (coord_setter_t &setter,
+ hb_array_t<contour_point_t> rec_points) const
+ {
+ bool have_variations = flags & AXES_HAVE_VARIATION;
+ unsigned axis_width = (flags & AXIS_INDICES_ARE_SHORT) ? 2 : 1;
+
+ const HBUINT8 *p = (const HBUINT8 *) (((HBUINT8 *) &numAxes) + numAxes.static_size + (flags & GID_IS_24 ? 3 : 2));
+ const HBUINT16 *q = (const HBUINT16 *) (((HBUINT8 *) &numAxes) + numAxes.static_size + (flags & GID_IS_24 ? 3 : 2));
+
+ const F2DOT14 *a = (const F2DOT14 *) ((HBUINT8 *) (axis_width == 1 ? (p + numAxes) : (HBUINT8 *) (q + numAxes)));
+
+ unsigned count = numAxes;
+ for (unsigned i = 0; i < count; i++)
+ {
+ unsigned axis_index = axis_width == 1 ? (unsigned) *p++ : (unsigned) *q++;
+
+ signed v = have_variations ? rec_points[i].x : *a++;
+
+ v += setter[axis_index];
+ v = hb_clamp (v, -(1<<14), (1<<14));
+ setter[axis_index] = v;
+ }
+ }
+
+ protected:
+ HBUINT16 flags;
+ HBUINT8 numAxes;
+ public:
+ DEFINE_SIZE_MIN (3);
+};
+
+using var_composite_iter_t = composite_iter_tmpl<VarCompositeGlyphRecord>;
+
+struct VarCompositeGlyph
+{
+ const GlyphHeader &header;
+ hb_bytes_t bytes;
+ VarCompositeGlyph (const GlyphHeader &header_, hb_bytes_t bytes_) :
+ header (header_), bytes (bytes_) {}
+
+ var_composite_iter_t iter () const
+ { return var_composite_iter_t (bytes, &StructAfter<VarCompositeGlyphRecord, GlyphHeader> (header)); }
+
+};
+
+
+} /* namespace glyf_impl */
+} /* namespace OT */
+
+
+#endif /* OT_GLYF_VARCOMPOSITEGLYPH_HH */
diff --git a/thirdparty/harfbuzz/src/OT/glyf/composite-iter.hh b/thirdparty/harfbuzz/src/OT/glyf/composite-iter.hh
new file mode 100644
index 0000000000..d05701f3d1
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/glyf/composite-iter.hh
@@ -0,0 +1,68 @@
+#ifndef OT_GLYF_COMPOSITE_ITER_HH
+#define OT_GLYF_COMPOSITE_ITER_HH
+
+
+#include "../../hb.hh"
+
+
+namespace OT {
+namespace glyf_impl {
+
+
+template <typename CompositeGlyphRecord>
+struct composite_iter_tmpl : hb_iter_with_fallback_t<composite_iter_tmpl<CompositeGlyphRecord>,
+ const CompositeGlyphRecord &>
+{
+ typedef const CompositeGlyphRecord *__item_t__;
+ composite_iter_tmpl (hb_bytes_t glyph_, __item_t__ current_) :
+ glyph (glyph_), current (nullptr), current_size (0)
+ {
+ set_current (current_);
+ }
+
+ composite_iter_tmpl () : glyph (hb_bytes_t ()), current (nullptr), current_size (0) {}
+
+ const CompositeGlyphRecord & __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_tmpl __end__ () const { return composite_iter_tmpl (); }
+ bool operator != (const composite_iter_tmpl& 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;
+};
+
+
+} /* namespace glyf_impl */
+} /* namespace OT */
+
+#endif /* OT_GLYF_COMPOSITE_ITER_HH */
diff --git a/thirdparty/harfbuzz/src/OT/glyf/coord-setter.hh b/thirdparty/harfbuzz/src/OT/glyf/coord-setter.hh
new file mode 100644
index 0000000000..df64ed5af7
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/glyf/coord-setter.hh
@@ -0,0 +1,34 @@
+#ifndef OT_GLYF_COORD_SETTER_HH
+#define OT_GLYF_COORD_SETTER_HH
+
+
+#include "../../hb.hh"
+
+
+namespace OT {
+namespace glyf_impl {
+
+
+struct coord_setter_t
+{
+ coord_setter_t (hb_array_t<int> coords) :
+ coords (coords) {}
+
+ int& operator [] (unsigned idx)
+ {
+ if (coords.length < idx + 1)
+ coords.resize (idx + 1);
+ return coords[idx];
+ }
+
+ hb_array_t<int> get_coords ()
+ { return coords.as_array (); }
+
+ hb_vector_t<int> coords;
+};
+
+
+} /* namespace glyf_impl */
+} /* namespace OT */
+
+#endif /* OT_GLYF_COORD_SETTER_HH */
diff --git a/thirdparty/harfbuzz/src/OT/glyf/glyf.hh b/thirdparty/harfbuzz/src/OT/glyf/glyf.hh
index 5fb32f67f3..e6e985c38c 100644
--- a/thirdparty/harfbuzz/src/OT/glyf/glyf.hh
+++ b/thirdparty/harfbuzz/src/OT/glyf/glyf.hh
@@ -42,11 +42,15 @@ struct glyf
bool serialize (hb_serialize_context_t *c,
Iterator it,
bool use_short_loca,
- const hb_subset_plan_t *plan)
+ const hb_subset_plan_t *plan,
+ hb_font_t *font)
{
TRACE_SERIALIZE (this);
+
unsigned init_len = c->length ();
- for (const auto &_ : it) _.serialize (c, use_short_loca, plan);
+ for (auto &_ : it)
+ if (unlikely (!_.serialize (c, use_short_loca, plan, font)))
+ return false;
/* 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
@@ -74,10 +78,11 @@ struct glyf
hb_vector_t<glyf_impl::SubsetGlyph> glyphs;
_populate_subset_glyphs (c->plan, glyphs);
+ hb_font_t *font = nullptr;
if (!c->plan->pinned_at_default)
{
- if (!_compile_subset_glyphs_with_deltas (c->plan, &glyphs))
- return_trace (false);
+ font = _create_font_for_instancing (c->plan);
+ if (unlikely (!font)) return false;
}
auto padded_offsets =
@@ -85,11 +90,14 @@ struct glyf
| hb_map (&glyf_impl::SubsetGlyph::padded_size)
;
- unsigned max_offset = + padded_offsets | hb_reduce (hb_add, 0);
- bool use_short_loca = max_offset < 0x1FFFF;
-
+ bool use_short_loca = false;
+ if (likely (!c->plan->force_long_loca))
+ {
+ unsigned max_offset = + padded_offsets | hb_reduce (hb_add, 0);
+ use_short_loca = max_offset < 0x1FFFF;
+ }
- glyf_prime->serialize (c->serializer, hb_iter (glyphs), use_short_loca, c->plan);
+ glyf_prime->serialize (c->serializer, glyphs.writer (), use_short_loca, c->plan, font);
if (!use_short_loca) {
padded_offsets =
+ hb_iter (glyphs)
@@ -97,9 +105,12 @@ struct glyf
;
}
-
- if (!c->plan->pinned_at_default)
+ if (font)
+ {
_free_compiled_subset_glyphs (&glyphs);
+ hb_font_destroy (font);
+ }
+
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,
@@ -110,9 +121,8 @@ struct glyf
_populate_subset_glyphs (const hb_subset_plan_t *plan,
hb_vector_t<glyf_impl::SubsetGlyph> &glyphs /* OUT */) const;
- bool
- _compile_subset_glyphs_with_deltas (const hb_subset_plan_t *plan,
- hb_vector_t<glyf_impl::SubsetGlyph> *glyphs /* OUT */) const;
+ hb_font_t *
+ _create_font_for_instancing (const hb_subset_plan_t *plan) const;
void _free_compiled_subset_glyphs (hb_vector_t<glyf_impl::SubsetGlyph> *glyphs) const
{
@@ -394,7 +404,11 @@ glyf::_populate_subset_glyphs (const hb_subset_plan_t *plan,
plan->pinned_at_default)
subset_glyph.source_glyph = glyf_impl::Glyph ();
else
- subset_glyph.source_glyph = glyf.glyph_for_gid (subset_glyph.old_gid, true);
+ {
+ /* If plan has an accelerator, the preprocessing step already trimmed glyphs.
+ * Don't trim them again! */
+ subset_glyph.source_glyph = glyf.glyph_for_gid (subset_glyph.old_gid, !plan->accelerator);
+ }
if (plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
subset_glyph.drop_hints_bytes ();
@@ -403,17 +417,15 @@ glyf::_populate_subset_glyphs (const hb_subset_plan_t *plan,
}
}
-inline bool
-glyf::_compile_subset_glyphs_with_deltas (const hb_subset_plan_t *plan,
- hb_vector_t<glyf_impl::SubsetGlyph> *glyphs /* OUT */) const
+inline hb_font_t *
+glyf::_create_font_for_instancing (const hb_subset_plan_t *plan) const
{
- OT::glyf_accelerator_t glyf (plan->source);
hb_font_t *font = hb_font_create (plan->source);
- if (unlikely (!font)) return false;
+ if (unlikely (font == hb_font_get_empty ())) return nullptr;
hb_vector_t<hb_variation_t> vars;
if (unlikely (!vars.alloc (plan->user_axes_location->get_population ())))
- return false;
+ return nullptr;
for (auto _ : *plan->user_axes_location)
{
@@ -423,18 +435,10 @@ glyf::_compile_subset_glyphs_with_deltas (const hb_subset_plan_t *plan,
vars.push (var);
}
+#ifndef HB_NO_VAR
hb_font_set_variations (font, vars.arrayZ, plan->user_axes_location->get_population ());
- for (auto& subset_glyph : *glyphs)
- {
- if (!const_cast<glyf_impl::SubsetGlyph &> (subset_glyph).compile_bytes_with_deltas (plan, font, glyf))
- {
- hb_font_destroy (font);
- return false;
- }
- }
-
- hb_font_destroy (font);
- return true;
+#endif
+ return font;
}
diff --git a/thirdparty/harfbuzz/src/graph/classdef-graph.hh b/thirdparty/harfbuzz/src/graph/classdef-graph.hh
index 0bda76ac2f..c2e24a7067 100644
--- a/thirdparty/harfbuzz/src/graph/classdef-graph.hh
+++ b/thirdparty/harfbuzz/src/graph/classdef-graph.hh
@@ -112,7 +112,7 @@ struct ClassDef : public OT::ClassDef
{
case 1: return ((ClassDefFormat1*)this)->sanitize (vertex);
case 2: return ((ClassDefFormat2*)this)->sanitize (vertex);
-#ifndef HB_NO_BORING_EXPANSION
+#ifndef HB_NO_BEYOND_64K
// Not currently supported
case 3:
case 4:
diff --git a/thirdparty/harfbuzz/src/graph/coverage-graph.hh b/thirdparty/harfbuzz/src/graph/coverage-graph.hh
index 3c1022f090..49d0936315 100644
--- a/thirdparty/harfbuzz/src/graph/coverage-graph.hh
+++ b/thirdparty/harfbuzz/src/graph/coverage-graph.hh
@@ -136,7 +136,7 @@ struct Coverage : public OT::Layout::Common::Coverage
{
case 1: return ((CoverageFormat1*)this)->sanitize (vertex);
case 2: return ((CoverageFormat2*)this)->sanitize (vertex);
-#ifndef HB_NO_BORING_EXPANSION
+#ifndef HB_NO_BEYOND_64K
// Not currently supported
case 3:
case 4:
diff --git a/thirdparty/harfbuzz/src/graph/graph.hh b/thirdparty/harfbuzz/src/graph/graph.hh
index 79c7e690a1..dc5b6a36fe 100644
--- a/thirdparty/harfbuzz/src/graph/graph.hh
+++ b/thirdparty/harfbuzz/src/graph/graph.hh
@@ -49,6 +49,50 @@ struct graph_t
unsigned end = 0;
unsigned priority = 0;
+
+ bool link_positions_valid (unsigned num_objects, bool removed_nil)
+ {
+ hb_set_t assigned_bytes;
+ for (const auto& l : obj.real_links)
+ {
+ if (l.objidx >= num_objects
+ || (removed_nil && !l.objidx))
+ {
+ DEBUG_MSG (SUBSET_REPACK, nullptr,
+ "Invalid graph. Invalid object index.");
+ return false;
+ }
+
+ unsigned start = l.position;
+ unsigned end = start + l.width - 1;
+
+ if (unlikely (l.width < 2 || l.width > 4))
+ {
+ DEBUG_MSG (SUBSET_REPACK, nullptr,
+ "Invalid graph. Invalid link width.");
+ return false;
+ }
+
+ if (unlikely (end >= table_size ()))
+ {
+ DEBUG_MSG (SUBSET_REPACK, nullptr,
+ "Invalid graph. Link position is out of bounds.");
+ return false;
+ }
+
+ if (unlikely (assigned_bytes.intersects (start, end)))
+ {
+ DEBUG_MSG (SUBSET_REPACK, nullptr,
+ "Invalid graph. Found offsets whose positions overlap.");
+ return false;
+ }
+
+ assigned_bytes.add_range (start, end);
+ }
+
+ return !assigned_bytes.in_error ();
+ }
+
void normalize ()
{
obj.real_links.qsort ();
@@ -132,7 +176,7 @@ struct graph_t
for (unsigned i = 0; i < parents.length; i++)
{
if (parents[i] != parent_index) continue;
- parents.remove (i);
+ parents.remove_unordered (i);
break;
}
}
@@ -148,7 +192,7 @@ struct graph_t
if ((obj.head + link.position) != offset)
continue;
- obj.real_links.remove (i);
+ obj.real_links.remove_unordered (i);
return;
}
}
@@ -286,8 +330,6 @@ struct graph_t
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])
@@ -299,6 +341,9 @@ struct graph_t
vertex_t* v = vertices_.push ();
if (check_success (!vertices_.in_error ()))
v->obj = *objects[i];
+
+ check_success (v->link_positions_valid (objects.length, removed_nil));
+
if (!removed_nil) continue;
// Fix indices to account for removed nil object.
for (auto& l : v->obj.all_links_writer ()) {
@@ -418,6 +463,13 @@ struct graph_t
hb_swap (sorted_graph[new_id], vertices_[next_id]);
const vertex_t& next = sorted_graph[new_id];
+ if (unlikely (!check_success(new_id >= 0))) {
+ // We are out of ids. Which means we've visited a node more than once.
+ // This graph contains a cycle which is not allowed.
+ DEBUG_MSG (SUBSET_REPACK, nullptr, "Invalid graph. Contains cycle.");
+ return;
+ }
+
id_map[next_id] = new_id--;
for (const auto& link : next.obj.all_links ()) {
@@ -580,7 +632,7 @@ struct graph_t
while (roots)
{
- unsigned next = HB_SET_VALUE_INVALID;
+ uint32_t next = HB_SET_VALUE_INVALID;
if (unlikely (!check_success (!roots.in_error ()))) break;
if (!roots.next (&next)) break;
@@ -661,8 +713,8 @@ struct graph_t
auto new_subgraph =
+ subgraph.keys ()
- | hb_map([&] (unsigned node_idx) {
- const unsigned *v;
+ | hb_map([&] (uint32_t node_idx) {
+ const uint32_t *v;
if (index_map.has (node_idx, &v)) return *v;
return node_idx;
})
@@ -672,10 +724,10 @@ struct graph_t
remap_obj_indices (index_map, parents.iter (), true);
// Update roots set with new indices as needed.
- unsigned next = HB_SET_VALUE_INVALID;
+ uint32_t next = HB_SET_VALUE_INVALID;
while (roots.next (&next))
{
- const unsigned *v;
+ const uint32_t *v;
if (index_map.has (next, &v))
{
roots.del (next);
@@ -690,7 +742,7 @@ struct graph_t
{
for (const auto& link : vertices_[node_idx].obj.all_links ())
{
- const unsigned *v;
+ const uint32_t *v;
if (subgraph.has (link.objidx, &v))
{
subgraph.set (link.objidx, *v + 1);
@@ -941,6 +993,72 @@ struct graph_t
return made_change;
}
+ bool is_fully_connected ()
+ {
+ update_parents();
+
+ if (root().parents)
+ // Root cannot have parents.
+ return false;
+
+ for (unsigned i = 0; i < root_idx (); i++)
+ {
+ if (!vertices_[i].parents)
+ return false;
+ }
+ return true;
+ }
+
+#if 0
+ /*
+ * Saves the current graph to a packed binary format which the repacker fuzzer takes
+ * as a seed.
+ */
+ void save_fuzzer_seed (hb_tag_t tag) const
+ {
+ FILE* f = fopen ("./repacker_fuzzer_seed", "w");
+ fwrite ((void*) &tag, sizeof (tag), 1, f);
+
+ uint16_t num_objects = vertices_.length;
+ fwrite ((void*) &num_objects, sizeof (num_objects), 1, f);
+
+ for (const auto& v : vertices_)
+ {
+ uint16_t blob_size = v.table_size ();
+ fwrite ((void*) &blob_size, sizeof (blob_size), 1, f);
+ fwrite ((const void*) v.obj.head, blob_size, 1, f);
+ }
+
+ uint16_t link_count = 0;
+ for (const auto& v : vertices_)
+ link_count += v.obj.real_links.length;
+
+ fwrite ((void*) &link_count, sizeof (link_count), 1, f);
+
+ typedef struct
+ {
+ uint16_t parent;
+ uint16_t child;
+ uint16_t position;
+ uint8_t width;
+ } link_t;
+
+ for (unsigned i = 0; i < vertices_.length; i++)
+ {
+ for (const auto& l : vertices_[i].obj.real_links)
+ {
+ link_t link {
+ (uint16_t) i, (uint16_t) l.objidx,
+ (uint16_t) l.position, (uint8_t) l.width
+ };
+ fwrite ((void*) &link, sizeof (link), 1, f);
+ }
+ }
+
+ fclose (f);
+ }
+#endif
+
void print_orphaned_nodes ()
{
if (!DEBUG_ENABLED(SUBSET_REPACK)) return;
@@ -949,6 +1067,10 @@ struct graph_t
parents_invalid = true;
update_parents();
+ if (root().parents) {
+ DEBUG_MSG (SUBSET_REPACK, nullptr, "Root node has incoming edges.");
+ }
+
for (unsigned i = 0; i < root_idx (); i++)
{
const auto& v = vertices_[i];
@@ -1065,6 +1187,11 @@ struct graph_t
}
}
+ for (unsigned i = 0; i < vertices_.length; i++)
+ // parents arrays must be accurate or downstream operations like cycle detection
+ // and sorting won't work correctly.
+ check_success (!vertices_[i].parents.in_error ());
+
parents_invalid = false;
}
@@ -1183,7 +1310,7 @@ struct graph_t
{
for (auto& link : vertices_[i].obj.all_links_writer ())
{
- const unsigned *v;
+ const uint32_t *v;
if (!id_map.has (link.objidx, &v)) continue;
if (only_wide && !(link.width == 4 && !link.is_signed)) continue;
diff --git a/thirdparty/harfbuzz/src/graph/gsubgpos-graph.hh b/thirdparty/harfbuzz/src/graph/gsubgpos-graph.hh
index e8d5bef9a8..c170638409 100644
--- a/thirdparty/harfbuzz/src/graph/gsubgpos-graph.hh
+++ b/thirdparty/harfbuzz/src/graph/gsubgpos-graph.hh
@@ -201,7 +201,7 @@ struct Lookup : public OT::Lookup
+ new_subtable_count * OT::Offset16::static_size;
char* buffer = (char*) hb_calloc (1, new_size);
c.add_buffer (buffer);
- memcpy (buffer, v.obj.head, v.table_size());
+ hb_memcpy (buffer, v.obj.head, v.table_size());
v.obj.head = buffer;
v.obj.tail = buffer + new_size;
@@ -355,7 +355,7 @@ struct GSTAR : public OT::GSUBGPOS
{
switch (u.version.major) {
case 1: return u.version1.get_lookup_list_offset ();
-#ifndef HB_NO_BORING_EXPANSION
+#ifndef HB_NO_BEYOND_64K
case 2: return u.version2.get_lookup_list_offset ();
#endif
default: return 0;
@@ -374,7 +374,7 @@ struct GSTAR : public OT::GSUBGPOS
{
switch (u.version.major) {
case 1: find_lookups<SmallTypes> (graph, lookups); break;
-#ifndef HB_NO_BORING_EXPANSION
+#ifndef HB_NO_BEYOND_64K
case 2: find_lookups<MediumTypes> (graph, lookups); break;
#endif
}
diff --git a/thirdparty/harfbuzz/src/graph/markbasepos-graph.hh b/thirdparty/harfbuzz/src/graph/markbasepos-graph.hh
index e42a6042cc..84ef5f71b9 100644
--- a/thirdparty/harfbuzz/src/graph/markbasepos-graph.hh
+++ b/thirdparty/harfbuzz/src/graph/markbasepos-graph.hh
@@ -112,7 +112,7 @@ struct AnchorMatrix : public OT::Layout::GPOS_impl::AnchorMatrix
auto& child = c.graph.vertices_[child_idx];
child.remove_parent (this_index);
- o.real_links.remove (i);
+ o.real_links.remove_unordered (i);
num_links--;
i--;
}
@@ -372,7 +372,7 @@ struct MarkBasePosFormat1 : public OT::Layout::GPOS_impl::MarkBasePosFormat1_2<S
if (!mark_coverage) return false;
hb_set_t marks = sc.marks_for (0, count);
auto new_coverage =
- + hb_zip (hb_range (), mark_coverage.table->iter ())
+ + hb_enumerate (mark_coverage.table->iter ())
| hb_filter (marks, hb_first)
| hb_map_retains_sorting (hb_second)
;
@@ -431,7 +431,7 @@ struct MarkBasePosFormat1 : public OT::Layout::GPOS_impl::MarkBasePosFormat1_2<S
if (!mark_coverage) return false;
hb_set_t marks = sc.marks_for (start, end);
auto new_coverage =
- + hb_zip (hb_range (), mark_coverage.table->iter ())
+ + hb_enumerate (mark_coverage.table->iter ())
| hb_filter (marks, hb_first)
| hb_map_retains_sorting (hb_second)
;
@@ -477,7 +477,7 @@ struct MarkBasePos : public OT::Layout::GPOS_impl::MarkBasePos
switch (u.format) {
case 1:
return ((MarkBasePosFormat1*)(&u.format1))->split_subtables (c, parent_index, this_index);
-#ifndef HB_NO_BORING_EXPANSION
+#ifndef HB_NO_BEYOND_64K
case 2: HB_FALLTHROUGH;
// Don't split 24bit PairPos's.
#endif
@@ -494,7 +494,7 @@ struct MarkBasePos : public OT::Layout::GPOS_impl::MarkBasePos
switch (u.format) {
case 1:
return ((MarkBasePosFormat1*)(&u.format1))->sanitize (vertex);
-#ifndef HB_NO_BORING_EXPANSION
+#ifndef HB_NO_BEYOND_64K
case 2: HB_FALLTHROUGH;
#endif
default:
diff --git a/thirdparty/harfbuzz/src/graph/pairpos-graph.hh b/thirdparty/harfbuzz/src/graph/pairpos-graph.hh
index 8040778ea3..1c13eb24f9 100644
--- a/thirdparty/harfbuzz/src/graph/pairpos-graph.hh
+++ b/thirdparty/harfbuzz/src/graph/pairpos-graph.hh
@@ -434,7 +434,7 @@ struct PairPosFormat2 : public OT::Layout::GPOS_impl::PairPosFormat2_4<SmallType
char* start_addr = ((char*)&values[0]) + start * split_context.class1_record_size;
unsigned num_records = end - start;
- memcpy (&pair_pos_prime->values[0],
+ hb_memcpy (&pair_pos_prime->values[0],
start_addr,
num_records * split_context.class1_record_size);
@@ -611,7 +611,7 @@ struct PairPos : public OT::Layout::GPOS_impl::PairPos
return ((PairPosFormat1*)(&u.format1))->split_subtables (c, parent_index, this_index);
case 2:
return ((PairPosFormat2*)(&u.format2))->split_subtables (c, parent_index, this_index);
-#ifndef HB_NO_BORING_EXPANSION
+#ifndef HB_NO_BEYOND_64K
case 3: HB_FALLTHROUGH;
case 4: HB_FALLTHROUGH;
// Don't split 24bit PairPos's.
@@ -631,7 +631,7 @@ struct PairPos : public OT::Layout::GPOS_impl::PairPos
return ((PairPosFormat1*)(&u.format1))->sanitize (vertex);
case 2:
return ((PairPosFormat2*)(&u.format2))->sanitize (vertex);
-#ifndef HB_NO_BORING_EXPANSION
+#ifndef HB_NO_BEYOND_64K
case 3: HB_FALLTHROUGH;
case 4: HB_FALLTHROUGH;
#endif
diff --git a/thirdparty/harfbuzz/src/graph/serialize.hh b/thirdparty/harfbuzz/src/graph/serialize.hh
index ecc6cc5aea..d03a61bd19 100644
--- a/thirdparty/harfbuzz/src/graph/serialize.hh
+++ b/thirdparty/harfbuzz/src/graph/serialize.hh
@@ -33,6 +33,23 @@ struct overflow_record_t
{
unsigned parent;
unsigned child;
+
+ bool operator != (const overflow_record_t o) const
+ { return !(*this == o); }
+
+ inline bool operator == (const overflow_record_t& o) const
+ {
+ return parent == o.parent &&
+ child == o.child;
+ }
+
+ inline uint32_t hash () const
+ {
+ uint32_t current = 0;
+ current = current * 31 + hb_hash (parent);
+ current = current * 31 + hb_hash (child);
+ return current;
+ }
};
inline
@@ -94,6 +111,7 @@ will_overflow (graph_t& graph,
if (overflows) overflows->resize (0);
graph.update_positions ();
+ hb_hashmap_t<overflow_record_t*, bool> record_set;
const auto& vertices = graph.vertices_;
for (int parent_idx = vertices.length - 1; parent_idx >= 0; parent_idx--)
{
@@ -109,7 +127,10 @@ will_overflow (graph_t& graph,
overflow_record_t r;
r.parent = parent_idx;
r.child = link.objidx;
+ if (record_set.has(&r)) continue; // don't keep duplicate overflows.
+
overflows->push (r);
+ record_set.set(&r, true);
}
}
@@ -223,7 +244,7 @@ inline hb_blob_t* serialize (const graph_t& graph)
return nullptr;
}
- memcpy (start, vertices[i].obj.head, size);
+ hb_memcpy (start, vertices[i].obj.head, size);
// Only real links needs to be serialized.
for (const auto& link : vertices[i].obj.real_links)
diff --git a/thirdparty/harfbuzz/src/hb-aat-layout-morx-table.hh b/thirdparty/harfbuzz/src/hb-aat-layout-morx-table.hh
index aa4ad4cf3c..8b9190d0be 100644
--- a/thirdparty/harfbuzz/src/hb-aat-layout-morx-table.hh
+++ b/thirdparty/harfbuzz/src/hb-aat-layout-morx-table.hh
@@ -131,14 +131,14 @@ struct RearrangementSubtable
hb_glyph_info_t *info = buffer->info;
hb_glyph_info_t buf[4];
- memcpy (buf, info + start, l * sizeof (buf[0]));
- memcpy (buf + 2, info + end - r, r * sizeof (buf[0]));
+ hb_memcpy (buf, info + start, l * sizeof (buf[0]));
+ hb_memcpy (buf + 2, info + end - r, r * sizeof (buf[0]));
if (l != r)
memmove (info + start + r, info + start + l, (end - start - l - r) * sizeof (buf[0]));
- memcpy (info + start, buf + 2, r * sizeof (buf[0]));
- memcpy (info + end - l, buf, l * sizeof (buf[0]));
+ hb_memcpy (info + start, buf + 2, r * sizeof (buf[0]));
+ hb_memcpy (info + end - l, buf, l * sizeof (buf[0]));
if (reverse_l)
{
buf[0] = info[end - 1];
diff --git a/thirdparty/harfbuzz/src/hb-aat-layout.cc b/thirdparty/harfbuzz/src/hb-aat-layout.cc
index d60126fe19..78427b0d5a 100644
--- a/thirdparty/harfbuzz/src/hb-aat-layout.cc
+++ b/thirdparty/harfbuzz/src/hb-aat-layout.cc
@@ -289,7 +289,7 @@ is_deleted_glyph (const hb_glyph_info_t *info)
void
hb_aat_layout_remove_deleted_glyphs (hb_buffer_t *buffer)
{
- hb_ot_layout_delete_glyphs_inplace (buffer, is_deleted_glyph);
+ buffer->delete_glyphs_inplace (is_deleted_glyph);
}
/**
diff --git a/thirdparty/harfbuzz/src/hb-aat-map.hh b/thirdparty/harfbuzz/src/hb-aat-map.hh
index c914f58d70..d0ee7d672c 100644
--- a/thirdparty/harfbuzz/src/hb-aat-map.hh
+++ b/thirdparty/harfbuzz/src/hb-aat-map.hh
@@ -38,7 +38,7 @@ struct hb_aat_map_t
void init ()
{
- memset (this, 0, sizeof (*this));
+ hb_memset (this, 0, sizeof (*this));
chain_flags.init ();
}
void fini () { chain_flags.fini (); }
diff --git a/thirdparty/harfbuzz/src/hb-algs.hh b/thirdparty/harfbuzz/src/hb-algs.hh
index cc37c073da..d85a4afe10 100644
--- a/thirdparty/harfbuzz/src/hb-algs.hh
+++ b/thirdparty/harfbuzz/src/hb-algs.hh
@@ -236,17 +236,6 @@ struct
template <typename T> constexpr auto
impl (const T& v, hb_priority<1>) const HB_RETURN (uint32_t, hb_deref (v).hash ())
- 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> 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)))
@@ -495,6 +484,17 @@ struct
}
HB_FUNCOBJ (hb_equal);
+struct
+{
+ template <typename T> void
+ operator () (T& a, T& b) const
+ {
+ using std::swap; // allow ADL
+ swap (a, b);
+ }
+}
+HB_FUNCOBJ (hb_swap);
+
template <typename T1, typename T2>
struct hb_pair_t
@@ -507,7 +507,7 @@ struct hb_pair_t
hb_enable_if (std::is_default_constructible<U1>::value &&
std::is_default_constructible<U2>::value)>
hb_pair_t () : first (), second () {}
- hb_pair_t (T1 a, T2 b) : first (a), second (b) {}
+ hb_pair_t (T1 a, T2 b) : first (std::forward<T1> (a)), second (std::forward<T2> (b)) {}
template <typename Q1, typename Q2,
hb_enable_if (hb_is_convertible (T1, Q1) &&
@@ -524,6 +524,25 @@ struct hb_pair_t
bool operator > (const pair_t& o) const { return first > o.first || (first == o.first && second > o.second); }
bool operator <= (const pair_t& o) const { return !(*this > o); }
+ static int cmp (const void *pa, const void *pb)
+ {
+ pair_t *a = (pair_t *) pa;
+ pair_t *b = (pair_t *) pb;
+
+ if (a->first < b->first) return -1;
+ if (a->first > b->first) return +1;
+ if (a->second < b->second) return -1;
+ if (a->second > b->second) return +1;
+ return 0;
+ }
+
+ friend void swap (hb_pair_t& a, hb_pair_t& b)
+ {
+ hb_swap (a.first, b.first);
+ hb_swap (a.second, b.second);
+ }
+
+
T1 first;
T2 second;
};
@@ -570,17 +589,6 @@ struct
}
HB_FUNCOBJ (hb_clamp);
-struct
-{
- template <typename T> void
- operator () (T& a, T& b) const
- {
- using std::swap; // allow ADL
- swap (a, b);
- }
-}
-HB_FUNCOBJ (hb_swap);
-
/*
* Bithacks.
*/
@@ -849,19 +857,14 @@ hb_in_range (T u, T lo, T hi)
return (T)(u - lo) <= (T)(hi - lo);
}
template <typename T> static inline bool
-hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2)
+hb_in_ranges (T u, T lo1, T hi1)
{
- return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2);
+ return hb_in_range (u, lo1, hi1);
}
-template <typename T> static inline bool
-hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2, T lo3, T hi3)
+template <typename T, typename ...Ts> static inline bool
+hb_in_ranges (T u, T lo1, T hi1, Ts... ds)
{
- 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);
+ return hb_in_range<T> (u, lo1, hi1) || hb_in_ranges<T> (u, ds...);
}
@@ -869,10 +872,18 @@ hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2, T lo3, T hi3, T lo4, T hi4)
* Overflow checking.
*/
-/* Consider __builtin_mul_overflow use here also */
static inline bool
-hb_unsigned_mul_overflows (unsigned int count, unsigned int size)
+hb_unsigned_mul_overflows (unsigned int count, unsigned int size, unsigned *result = nullptr)
{
+#if (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__)
+ unsigned stack_result;
+ if (!result)
+ result = &stack_result;
+ return __builtin_mul_overflow (count, size, result);
+#endif
+
+ if (result)
+ *result = count * size;
return (size > 0) && (count >= ((unsigned int) -1) / size);
}
@@ -1164,9 +1175,12 @@ hb_qsort (void *base, size_t nel, size_t width,
}
-template <typename T, typename T2, typename T3> static inline void
-hb_stable_sort (T *array, unsigned int len, int(*compar)(const T2 *, const T2 *), T3 *array2)
+template <typename T, typename T2, typename T3 = int> static inline void
+hb_stable_sort (T *array, unsigned int len, int(*compar)(const T2 *, const T2 *), T3 *array2 = nullptr)
{
+ static_assert (hb_is_trivially_copy_assignable (T), "");
+ static_assert (hb_is_trivially_copy_assignable (T3), "");
+
for (unsigned int i = 1; i < len; i++)
{
unsigned int j = i;
@@ -1189,12 +1203,6 @@ hb_stable_sort (T *array, unsigned int len, int(*compar)(const T2 *, const T2 *)
}
}
-template <typename T> static inline void
-hb_stable_sort (T *array, unsigned int len, int(*compar)(const T *, const T *))
-{
- hb_stable_sort (array, len, compar, (int *) nullptr);
-}
-
static inline hb_bool_t
hb_codepoint_parse (const char *s, unsigned int len, int base, hb_codepoint_t *out)
{
@@ -1322,47 +1330,4 @@ struct
HB_FUNCOBJ (hb_dec);
-/* Compiler-assisted vectorization. */
-
-/* Type behaving similar to vectorized vars defined using __attribute__((vector_size(...))),
- * basically a fixed-size bitset. */
-template <typename elt_t, unsigned int byte_size>
-struct hb_vector_size_t
-{
- elt_t& operator [] (unsigned int i) { return v[i]; }
- const elt_t& operator [] (unsigned int i) const { return v[i]; }
-
- void clear (unsigned char v = 0) { memset (this, v, sizeof (*this)); }
-
- template <typename Op>
- hb_vector_size_t process (const Op& op) const
- {
- hb_vector_size_t r;
- for (unsigned int i = 0; i < ARRAY_LENGTH (v); i++)
- r.v[i] = op (v[i]);
- return r;
- }
- template <typename Op>
- hb_vector_size_t process (const Op& op, const hb_vector_size_t &o) const
- {
- hb_vector_size_t r;
- for (unsigned int i = 0; i < ARRAY_LENGTH (v); i++)
- r.v[i] = op (v[i], o.v[i]);
- return r;
- }
- hb_vector_size_t operator | (const hb_vector_size_t &o) const
- { return process (hb_bitwise_or, o); }
- hb_vector_size_t operator & (const hb_vector_size_t &o) const
- { return process (hb_bitwise_and, o); }
- hb_vector_size_t operator ^ (const hb_vector_size_t &o) const
- { return process (hb_bitwise_xor, o); }
- hb_vector_size_t operator ~ () const
- { return process (hb_bitwise_neg); }
-
- private:
- static_assert (0 == byte_size % sizeof (elt_t), "");
- elt_t v[byte_size / sizeof (elt_t)];
-};
-
-
#endif /* HB_ALGS_HH */
diff --git a/thirdparty/harfbuzz/src/hb-array.hh b/thirdparty/harfbuzz/src/hb-array.hh
index 5884007c19..17562bc336 100644
--- a/thirdparty/harfbuzz/src/hb-array.hh
+++ b/thirdparty/harfbuzz/src/hb-array.hh
@@ -100,10 +100,18 @@ 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 and length. */
+ * for range-based for loop and just compare arrayZ and length.
+ *
+ * The above comment is outdated now because we implemented separate begin/end to
+ * objects that were using hb_array_t for range-based loop before. */
bool operator != (const hb_array_t& o) const
{ return this->arrayZ != o.arrayZ || this->length != o.length; }
+ /* Faster range-based for loop without bounds-check. */
+ Type *begin () const { return arrayZ; }
+ Type *end () const { return arrayZ + length; }
+
+
/* Extra operators.
*/
Type * operator & () const { return arrayZ; }
@@ -112,11 +120,11 @@ struct hb_array_t : hb_iter_with_fallback_t<hb_array_t<Type>, Type&>
HB_INTERNAL bool operator == (const hb_array_t &o) const;
- uint32_t hash () const {
+ uint32_t hash () const
+ {
uint32_t current = 0;
- for (unsigned int i = 0; i < this->length; i++) {
- current = current * 31 + hb_hash (this->arrayZ[i]);
- }
+ for (auto &v : *this)
+ current = current * 31 + hb_hash (v);
return current;
}
@@ -184,23 +192,18 @@ struct hb_array_t : hb_iter_with_fallback_t<hb_array_t<Type>, Type&>
hb_sorted_array_t<Type> qsort (int (*cmp_)(const void*, const void*))
{
+ //static_assert (hb_enable_if (hb_is_trivially_copy_assignable(Type)), "");
if (likely (length))
hb_qsort (arrayZ, length, this->get_item_size (), cmp_);
return hb_sorted_array_t<Type> (*this);
}
hb_sorted_array_t<Type> qsort ()
{
+ //static_assert (hb_enable_if (hb_is_trivially_copy_assignable(Type)), "");
if (likely (length))
hb_qsort (arrayZ, length, this->get_item_size (), Type::cmp);
return hb_sorted_array_t<Type> (*this);
}
- void qsort (unsigned int start, unsigned int end)
- {
- end = hb_min (end, length);
- assert (start <= end);
- if (likely (start < end))
- hb_qsort (arrayZ + start, end - start, this->get_item_size (), Type::cmp);
- }
/*
* Other methods.
@@ -262,17 +265,31 @@ struct hb_array_t : hb_iter_with_fallback_t<hb_array_t<Type>, Type&>
void fini ()
{ hb_free ((void *) arrayZ); arrayZ = nullptr; length = 0; }
- template <typename hb_serialize_context_t>
+ template <typename hb_serialize_context_t,
+ typename U = Type,
+ hb_enable_if (!(sizeof (U) < sizeof (long long) && hb_is_trivially_copy_assignable(hb_decay<Type>)))>
hb_array_t copy (hb_serialize_context_t *c) const
{
TRACE_SERIALIZE (this);
auto* out = c->start_embed (arrayZ);
- if (unlikely (!c->extend_size (out, get_size ()))) return_trace (hb_array_t ());
+ if (unlikely (!c->extend_size (out, get_size (), false))) return_trace (hb_array_t ());
for (unsigned i = 0; i < length; i++)
out[i] = arrayZ[i]; /* TODO: add version that calls c->copy() */
return_trace (hb_array_t (out, length));
}
+ template <typename hb_serialize_context_t,
+ typename U = Type,
+ hb_enable_if (sizeof (U) < sizeof (long long) && hb_is_trivially_copy_assignable(hb_decay<Type>))>
+ hb_array_t copy (hb_serialize_context_t *c) const
+ {
+ TRACE_SERIALIZE (this);
+ auto* out = c->start_embed (arrayZ);
+ if (unlikely (!c->extend_size (out, get_size (), false))) return_trace (hb_array_t ());
+ hb_memcpy (out, arrayZ, get_size ());
+ return_trace (hb_array_t (out, length));
+ }
+
template <typename hb_sanitize_context_t>
bool sanitize (hb_sanitize_context_t *c) const
{ return c->check_array (arrayZ, length); }
@@ -295,8 +312,8 @@ hb_array (T (&array_)[length_])
template <typename Type>
struct hb_sorted_array_t :
- hb_iter_t<hb_sorted_array_t<Type>, Type&>,
- hb_array_t<Type>
+ hb_array_t<Type>,
+ hb_iter_t<hb_sorted_array_t<Type>, Type&>
{
typedef hb_iter_t<hb_sorted_array_t, Type&> iter_base_t;
HB_ITER_USING (iter_base_t);
@@ -316,8 +333,8 @@ struct hb_sorted_array_t :
template <typename U,
hb_enable_if (hb_is_cr_convertible(U, Type))>
constexpr hb_sorted_array_t (const hb_array_t<U> &o) :
- hb_iter_t<hb_sorted_array_t, Type&> (),
- hb_array_t<Type> (o) {}
+ hb_array_t<Type> (o),
+ hb_iter_t<hb_sorted_array_t, Type&> () {}
template <typename U,
hb_enable_if (hb_is_cr_convertible(U, Type))>
hb_sorted_array_t& operator = (const hb_array_t<U> &o)
@@ -329,6 +346,11 @@ struct hb_sorted_array_t :
bool operator != (const hb_sorted_array_t& o) const
{ return this->arrayZ != o.arrayZ || this->length != o.length; }
+ /* Faster range-based for loop without bounds-check. */
+ Type *begin () const { return this->arrayZ; }
+ Type *end () const { return this->arrayZ + this->length; }
+
+
hb_sorted_array_t sub_array (unsigned int start_offset, unsigned int *seg_count /* IN/OUT */) const
{ return hb_sorted_array_t (((const hb_array_t<Type> *) (this))->sub_array (start_offset, seg_count)); }
hb_sorted_array_t sub_array (unsigned int start_offset, unsigned int seg_count) const
@@ -421,18 +443,42 @@ inline bool hb_array_t<const unsigned char>::operator == (const hb_array_t<const
return 0 == hb_memcmp (arrayZ, o.arrayZ, length);
}
+
+/* Specialize hash() for byte arrays. */
+
template <>
-inline uint32_t hb_array_t<const char>::hash () const {
+inline uint32_t hb_array_t<const char>::hash () const
+{
uint32_t current = 0;
- for (unsigned int i = 0; i < this->length; i++)
- current = current * 31 + (uint32_t) (this->arrayZ[i] * 2654435761u);
+ unsigned i = 0;
+
+#if defined(__OPTIMIZE__) && !defined(HB_NO_PACKED) && \
+ ((defined(__GNUC__) && __GNUC__ >= 5) || defined(__clang__))
+ struct __attribute__((packed)) packed_uint32_t { uint32_t v; };
+ for (; i + 4 <= this->length; i += 4)
+ current = current * 31 + hb_hash ((uint32_t) ((packed_uint32_t *) &this->arrayZ[i])->v);
+#endif
+
+ for (; i < this->length; i++)
+ current = current * 31 + hb_hash (this->arrayZ[i]);
return current;
}
+
template <>
-inline uint32_t hb_array_t<const unsigned char>::hash () const {
+inline uint32_t hb_array_t<const unsigned char>::hash () const
+{
uint32_t current = 0;
- for (unsigned int i = 0; i < this->length; i++)
- current = current * 31 + (uint32_t) (this->arrayZ[i] * 2654435761u);
+ unsigned i = 0;
+
+#if defined(__OPTIMIZE__) && !defined(HB_NO_PACKED) && \
+ ((defined(__GNUC__) && __GNUC__ >= 5) || defined(__clang__))
+ struct __attribute__((packed)) packed_uint32_t { uint32_t v; };
+ for (; i + 4 <= this->length; i += 4)
+ current = current * 31 + hb_hash ((uint32_t) ((packed_uint32_t *) &this->arrayZ[i])->v);
+#endif
+
+ for (; i < this->length; i++)
+ current = current * 31 + hb_hash (this->arrayZ[i]);
return current;
}
diff --git a/thirdparty/harfbuzz/src/hb-bit-page.hh b/thirdparty/harfbuzz/src/hb-bit-page.hh
index 95ae1b7bf9..11987054f8 100644
--- a/thirdparty/harfbuzz/src/hb-bit-page.hh
+++ b/thirdparty/harfbuzz/src/hb-bit-page.hh
@@ -30,6 +30,53 @@
#include "hb.hh"
+
+/* Compiler-assisted vectorization. */
+
+/* Type behaving similar to vectorized vars defined using __attribute__((vector_size(...))),
+ * basically a fixed-size bitset. */
+template <typename elt_t, unsigned int byte_size>
+struct hb_vector_size_t
+{
+ elt_t& operator [] (unsigned int i) { return v[i]; }
+ const elt_t& operator [] (unsigned int i) const { return v[i]; }
+
+ void clear (unsigned char v = 0) { hb_memset (this, v, sizeof (*this)); }
+
+ template <typename Op>
+ hb_vector_size_t process (const Op& op) const
+ {
+ hb_vector_size_t r;
+ for (unsigned int i = 0; i < ARRAY_LENGTH (v); i++)
+ r.v[i] = op (v[i]);
+ return r;
+ }
+ template <typename Op>
+ hb_vector_size_t process (const Op& op, const hb_vector_size_t &o) const
+ {
+ hb_vector_size_t r;
+ for (unsigned int i = 0; i < ARRAY_LENGTH (v); i++)
+ r.v[i] = op (v[i], o.v[i]);
+ return r;
+ }
+ hb_vector_size_t operator | (const hb_vector_size_t &o) const
+ { return process (hb_bitwise_or, o); }
+ hb_vector_size_t operator & (const hb_vector_size_t &o) const
+ { return process (hb_bitwise_and, o); }
+ hb_vector_size_t operator ^ (const hb_vector_size_t &o) const
+ { return process (hb_bitwise_xor, o); }
+ hb_vector_size_t operator ~ () const
+ { return process (hb_bitwise_neg); }
+
+ hb_array_t<const elt_t> iter () const
+ { return hb_array (v); }
+
+ private:
+ static_assert (0 == byte_size % sizeof (elt_t), "");
+ elt_t v[byte_size / sizeof (elt_t)];
+};
+
+
struct hb_bit_page_t
{
void init0 () { v.clear (); }
@@ -40,17 +87,17 @@ struct hb_bit_page_t
bool is_empty () const
{
- for (unsigned i = 0; i < len (); i++)
- if (v[i])
- return false;
- return true;
+ return
+ + hb_iter (v)
+ | hb_none
+ ;
}
uint32_t hash () const
{
- uint32_t h = 0;
- for (unsigned i = 0; i < len (); i++)
- h = h * 31 + hb_hash (v[i]);
- return h;
+ return
+ + hb_iter (v)
+ | hb_reduce ([] (uint32_t h, const elt_t &_) { return h * 31 + hb_hash (_); }, (uint32_t) 0u)
+ ;
}
void add (hb_codepoint_t g) { elt (g) |= mask (g); }
@@ -69,7 +116,7 @@ struct hb_bit_page_t
*la |= ~(mask (a) - 1);
la++;
- memset (la, 0xff, (char *) lb - (char *) la);
+ hb_memset (la, 0xff, (char *) lb - (char *) la);
*lb |= ((mask (b) << 1) - 1);
}
@@ -85,7 +132,7 @@ struct hb_bit_page_t
*la &= mask (a) - 1;
la++;
- memset (la, 0, (char *) lb - (char *) la);
+ hb_memset (la, 0, (char *) lb - (char *) la);
*lb &= ~((mask (b) << 1) - 1);
}
@@ -101,13 +148,13 @@ struct hb_bit_page_t
hb_codepoint_t *p,
unsigned int size) const
{
- unsigned int start_v = start_value >> ELT_BITS_LOG_2;
+ unsigned int start_v = start_value / ELT_BITS;
unsigned int start_bit = start_value & ELT_MASK;
unsigned int count = 0;
for (unsigned i = start_v; i < len () && count < size; i++)
{
elt_t bits = v[i];
- uint32_t v_base = base | (i << ELT_BITS_LOG_2);
+ uint32_t v_base = base | (i * ELT_BITS);
for (unsigned int j = start_bit; j < ELT_BITS && count < size; j++)
{
if ((elt_t(1) << j) & bits) {
@@ -132,13 +179,13 @@ struct hb_bit_page_t
unsigned int size,
hb_codepoint_t *next_value) const
{
- unsigned int start_v = start_value >> ELT_BITS_LOG_2;
+ unsigned int start_v = start_value / ELT_BITS;
unsigned int start_bit = start_value & ELT_MASK;
unsigned int count = 0;
for (unsigned i = start_v; i < len () && count < size; i++)
{
elt_t bits = v[i];
- uint32_t v_offset = i << ELT_BITS_LOG_2;
+ uint32_t v_offset = i * ELT_BITS;
for (unsigned int j = start_bit; j < ELT_BITS && count < size; j++)
{
if ((elt_t(1) << j) & bits)
@@ -161,7 +208,10 @@ struct hb_bit_page_t
bool is_equal (const hb_bit_page_t &other) const
{
- return 0 == hb_memcmp (&v, &other.v, sizeof (v));
+ for (unsigned i = 0; i < len (); i++)
+ if (v[i] != other.v[i])
+ return false;
+ return true;
}
bool is_subset (const hb_bit_page_t &larger_page) const
{
@@ -173,10 +223,10 @@ struct hb_bit_page_t
unsigned int get_population () const
{
- unsigned int pop = 0;
- for (unsigned int i = 0; i < len (); i++)
- pop += hb_popcount (v[i]);
- return pop;
+ return
+ + hb_iter (v)
+ | hb_reduce ([] (unsigned pop, const elt_t &_) { return pop + hb_popcount (_); }, 0u)
+ ;
}
bool next (hb_codepoint_t *codepoint) const
@@ -262,8 +312,6 @@ struct hb_bit_page_t
typedef hb_vector_size_t<elt_t, PAGE_BITS / 8> vector_t;
static constexpr unsigned ELT_BITS = sizeof (elt_t) * 8;
- static constexpr unsigned ELT_BITS_LOG_2 = 6;
- static_assert (1 << ELT_BITS_LOG_2 == ELT_BITS, "");
static constexpr unsigned ELT_MASK = ELT_BITS - 1;
static constexpr unsigned BITS = sizeof (vector_t) * 8;
diff --git a/thirdparty/harfbuzz/src/hb-bit-set-invertible.hh b/thirdparty/harfbuzz/src/hb-bit-set-invertible.hh
index 27fb0732ea..ff8aecc60c 100644
--- a/thirdparty/harfbuzz/src/hb-bit-set-invertible.hh
+++ b/thirdparty/harfbuzz/src/hb-bit-set-invertible.hh
@@ -123,10 +123,8 @@ struct hb_bit_set_invertible_t
bool get (hb_codepoint_t g) const { return s.get (g) ^ inverted; }
/* Has interface. */
- static constexpr bool SENTINEL = false;
- typedef bool value_t;
- value_t operator [] (hb_codepoint_t k) const { return get (k); }
- bool has (hb_codepoint_t k) const { return (*this)[k] != SENTINEL; }
+ bool operator [] (hb_codepoint_t k) const { return get (k); }
+ bool has (hb_codepoint_t k) const { return (*this)[k]; }
/* Predicate. */
bool operator () (hb_codepoint_t k) const { return has (k); }
diff --git a/thirdparty/harfbuzz/src/hb-bit-set.hh b/thirdparty/harfbuzz/src/hb-bit-set.hh
index a63887efda..8de6e037fb 100644
--- a/thirdparty/harfbuzz/src/hb-bit-set.hh
+++ b/thirdparty/harfbuzz/src/hb-bit-set.hh
@@ -85,10 +85,10 @@ struct hb_bit_set_t
void err () { if (successful) successful = false; } /* TODO Remove */
bool in_error () const { return !successful; }
- bool resize (unsigned int count)
+ bool resize (unsigned int count, bool clear = true)
{
if (unlikely (!successful)) return false;
- if (unlikely (!pages.resize (count) || !page_map.resize (count)))
+ if (unlikely (!pages.resize (count, clear) || !page_map.resize (count, clear)))
{
pages.resize (page_map.length);
successful = false;
@@ -330,10 +330,8 @@ struct hb_bit_set_t
}
/* Has interface. */
- static constexpr bool SENTINEL = false;
- typedef bool value_t;
- value_t operator [] (hb_codepoint_t k) const { return get (k); }
- bool has (hb_codepoint_t k) const { return (*this)[k] != SENTINEL; }
+ bool operator [] (hb_codepoint_t k) const { return get (k); }
+ bool has (hb_codepoint_t k) const { return (*this)[k]; }
/* Predicate. */
bool operator () (hb_codepoint_t k) const { return has (k); }
@@ -352,7 +350,7 @@ struct hb_bit_set_t
{
if (unlikely (!successful)) return;
unsigned int count = other.pages.length;
- if (unlikely (!resize (count)))
+ if (unlikely (!resize (count, false)))
return;
population = other.population;
@@ -391,7 +389,7 @@ struct hb_bit_set_t
bool is_subset (const hb_bit_set_t &larger_set) const
{
if (has_population () && larger_set.has_population () &&
- population != larger_set.population)
+ population > larger_set.population)
return false;
uint32_t spi = 0;
@@ -540,21 +538,21 @@ struct hb_bit_set_t
b = nb;
for (; a && b; )
{
- if (page_map[a - 1].major == other.page_map[b - 1].major)
+ if (page_map.arrayZ[a - 1].major == other.page_map.arrayZ[b - 1].major)
{
a--;
b--;
count--;
- page_map[count] = page_map[a];
+ page_map.arrayZ[count] = page_map.arrayZ[a];
page_at (count).v = op (page_at (a).v, other.page_at (b).v);
}
- else if (page_map[a - 1].major > other.page_map[b - 1].major)
+ else if (page_map.arrayZ[a - 1].major > other.page_map.arrayZ[b - 1].major)
{
a--;
if (passthru_left)
{
count--;
- page_map[count] = page_map[a];
+ page_map.arrayZ[count] = page_map.arrayZ[a];
}
}
else
@@ -563,8 +561,8 @@ struct hb_bit_set_t
if (passthru_right)
{
count--;
- page_map[count].major = other.page_map[b].major;
- page_map[count].index = next_page++;
+ page_map.arrayZ[count].major = other.page_map.arrayZ[b].major;
+ page_map.arrayZ[count].index = next_page++;
page_at (count).v = other.page_at (b).v;
}
}
@@ -574,15 +572,15 @@ struct hb_bit_set_t
{
a--;
count--;
- page_map[count] = page_map [a];
+ page_map.arrayZ[count] = page_map.arrayZ[a];
}
if (passthru_right)
while (b)
{
b--;
count--;
- page_map[count].major = other.page_map[b].major;
- page_map[count].index = next_page++;
+ page_map.arrayZ[count].major = other.page_map.arrayZ[b].major;
+ page_map.arrayZ[count].index = next_page++;
page_at (count).v = other.page_at (b).v;
}
assert (!count);
@@ -605,8 +603,6 @@ struct hb_bit_set_t
bool next (hb_codepoint_t *codepoint) const
{
- // TODO: this should be merged with prev() as both implementations
- // are very similar.
if (unlikely (*codepoint == INVALID)) {
*codepoint = get_min ();
return *codepoint != INVALID;
@@ -640,7 +636,7 @@ struct hb_bit_set_t
for (; i < page_map.length; i++)
{
- const page_map_t &current = page_map.arrayZ[i];
+ const page_map_t &current = page_map_array[i];
hb_codepoint_t m = pages_array[current.index].get_min ();
if (m != INVALID)
{
@@ -663,21 +659,21 @@ struct hb_bit_set_t
page_map_t map = {get_major (*codepoint), 0};
unsigned int i;
page_map.bfind (map, &i, HB_NOT_FOUND_STORE_CLOSEST);
- if (i < page_map.length && page_map[i].major == map.major)
+ if (i < page_map.length && page_map.arrayZ[i].major == map.major)
{
- if (pages[page_map[i].index].previous (codepoint))
+ if (pages[page_map.arrayZ[i].index].previous (codepoint))
{
- *codepoint += page_map[i].major * page_t::PAGE_BITS;
+ *codepoint += page_map.arrayZ[i].major * page_t::PAGE_BITS;
return true;
}
}
i--;
for (; (int) i >= 0; i--)
{
- hb_codepoint_t m = pages[page_map[i].index].get_max ();
+ hb_codepoint_t m = pages.arrayZ[page_map.arrayZ[i].index].get_max ();
if (m != INVALID)
{
- *codepoint = page_map[i].major * page_t::PAGE_BITS + m;
+ *codepoint = page_map.arrayZ[i].major * page_t::PAGE_BITS + m;
return true;
}
}
@@ -905,7 +901,7 @@ struct hb_bit_set_t
{
auto &cached_page = page_map.arrayZ[i];
if (cached_page.major == major)
- return &pages[cached_page.index];
+ return &pages.arrayZ[cached_page.index];
}
page_map_t map = {major, pages.length};
@@ -917,15 +913,15 @@ struct hb_bit_set_t
if (unlikely (!resize (pages.length + 1)))
return nullptr;
- pages[map.index].init0 ();
- memmove (page_map + i + 1,
- page_map + i,
+ pages.arrayZ[map.index].init0 ();
+ memmove (page_map.arrayZ + i + 1,
+ page_map.arrayZ + i,
(page_map.length - 1 - i) * page_map.item_size);
page_map[i] = map;
}
last_page_lookup = i;
- return &pages[page_map[i].index];
+ return &pages.arrayZ[page_map.arrayZ[i].index];
}
const page_t *page_for (hb_codepoint_t g) const
{
@@ -939,7 +935,7 @@ struct hb_bit_set_t
{
auto &cached_page = page_map.arrayZ[i];
if (cached_page.major == major)
- return &pages[cached_page.index];
+ return &pages.arrayZ[cached_page.index];
}
page_map_t key = {major};
@@ -947,10 +943,18 @@ struct hb_bit_set_t
return nullptr;
last_page_lookup = i;
- return &pages[page_map[i].index];
+ return &pages.arrayZ[page_map[i].index];
+ }
+ page_t &page_at (unsigned int i)
+ {
+ assert (i < page_map.length);
+ return pages.arrayZ[page_map.arrayZ[i].index];
+ }
+ const page_t &page_at (unsigned int i) const
+ {
+ assert (i < page_map.length);
+ return pages.arrayZ[page_map.arrayZ[i].index];
}
- page_t &page_at (unsigned int i) { return pages[page_map[i].index]; }
- const page_t &page_at (unsigned int i) const { return pages[page_map[i].index]; }
unsigned int get_major (hb_codepoint_t g) const { return g >> page_t::PAGE_BITS_LOG_2; }
unsigned int page_remainder (hb_codepoint_t g) const { return g & page_t::PAGE_BITMASK; }
hb_codepoint_t major_start (unsigned int major) const { return major << page_t::PAGE_BITS_LOG_2; }
diff --git a/thirdparty/harfbuzz/src/hb-blob.cc b/thirdparty/harfbuzz/src/hb-blob.cc
index 9bc12ea3fa..f0fda1fa4d 100644
--- a/thirdparty/harfbuzz/src/hb-blob.cc
+++ b/thirdparty/harfbuzz/src/hb-blob.cc
@@ -495,7 +495,7 @@ hb_blob_t::try_make_writable ()
DEBUG_MSG_FUNC (BLOB, this, "dupped successfully -> %p\n", this->data);
- memcpy (new_data, this->data, this->length);
+ hb_memcpy (new_data, this->data, this->length);
this->destroy_user_data ();
this->mode = HB_MEMORY_MODE_WRITABLE;
this->data = new_data;
diff --git a/thirdparty/harfbuzz/src/hb-buffer-deserialize-json.hh b/thirdparty/harfbuzz/src/hb-buffer-deserialize-json.hh
index 87095855d6..993bb1f698 100644
--- a/thirdparty/harfbuzz/src/hb-buffer-deserialize-json.hh
+++ b/thirdparty/harfbuzz/src/hb-buffer-deserialize-json.hh
@@ -32,7 +32,7 @@
#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,
@@ -557,12 +557,12 @@ _hb_buffer_deserialize_json (hb_buffer_t *buffer,
hb_glyph_info_t info = {0};
hb_glyph_position_t pos = {0};
-#line 561 "hb-buffer-deserialize-json.hh"
+#line 554 "hb-buffer-deserialize-json.hh"
{
cs = deserialize_json_start;
}
-#line 566 "hb-buffer-deserialize-json.hh"
+#line 557 "hb-buffer-deserialize-json.hh"
{
int _slen;
int _trans;
@@ -590,8 +590,8 @@ _resume:
case 1:
#line 38 "hb-buffer-deserialize-json.rl"
{
- memset (&info, 0, sizeof (info));
- memset (&pos , 0, sizeof (pos ));
+ hb_memset (&info, 0, sizeof (info));
+ hb_memset (&pos , 0, sizeof (pos ));
}
break;
case 5:
@@ -774,7 +774,7 @@ _resume:
*end_ptr = p;
}
break;
-#line 778 "hb-buffer-deserialize-json.hh"
+#line 735 "hb-buffer-deserialize-json.hh"
}
_again:
diff --git a/thirdparty/harfbuzz/src/hb-buffer-deserialize-text.hh b/thirdparty/harfbuzz/src/hb-buffer-deserialize-text.hh
index 9062610de2..6b9b4282fc 100644
--- a/thirdparty/harfbuzz/src/hb-buffer-deserialize-text.hh
+++ b/thirdparty/harfbuzz/src/hb-buffer-deserialize-text.hh
@@ -32,32 +32,30 @@
#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, 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,
+ 0u, 0u, 9u, 91u, 85u, 85u, 43u, 43u, 48u, 102u, 9u, 85u, 48u, 57u, 48u, 57u,
+ 45u, 57u, 48u, 57u, 45u, 57u, 48u, 57u, 48u, 57u, 45u, 57u, 48u, 57u, 44u, 44u,
+ 45u, 57u, 48u, 57u, 44u, 57u, 43u, 124u, 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, 9u, 124u, 9u, 124u, 9u, 124u,
- 9u, 124u, 9u, 124u, 9u, 124u, 0
+ 0
};
static const char _deserialize_text_key_spans[] = {
- 0, 83, 1, 1, 55, 77, 10, 13,
- 10, 10, 10, 13, 10, 1, 13, 10,
- 14, 82, 13, 10, 116, 116, 0, 77,
- 116, 116, 116, 116, 116, 116, 116, 116,
+ 0, 83, 1, 1, 55, 77, 10, 10,
+ 13, 10, 13, 10, 10, 13, 10, 1,
+ 13, 10, 14, 82, 116, 116, 0, 77,
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, 280, 294, 305, 307, 321,
- 332, 347, 430, 444, 455, 572, 689, 690,
+ 244, 258, 269, 283, 294, 305, 319, 330,
+ 332, 346, 357, 372, 455, 572, 689, 690,
768, 885, 1002, 1119, 1236, 1353, 1470, 1587,
- 1704, 1821, 1938, 2055, 2172, 2289, 2406, 2523,
- 2640, 2757, 2874
+ 1704, 1821, 1938, 2055, 2172, 2289, 2406, 2523
};
static const char _deserialize_text_indicies[] = {
@@ -90,34 +88,34 @@ static const char _deserialize_text_indicies[] = {
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 4, 1, 8,
9, 9, 9, 9, 9, 9, 9, 9,
- 9, 1, 10, 1, 1, 11, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 1,
+ 9, 1, 10, 11, 11, 11, 11, 11,
+ 11, 11, 11, 11, 1, 12, 1, 1,
13, 14, 14, 14, 14, 14, 14, 14,
14, 14, 1, 15, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 1, 17, 18,
- 18, 18, 18, 18, 18, 18, 18, 18,
- 1, 19, 1, 1, 20, 21, 21, 21,
+ 16, 16, 16, 16, 16, 1, 17, 1,
+ 1, 18, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 1, 20, 21, 21, 21,
21, 21, 21, 21, 21, 21, 1, 22,
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, 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,
+ 23, 1, 24, 1, 1, 25, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 1,
+ 27, 28, 28, 28, 28, 28, 28, 28,
+ 28, 28, 1, 29, 1, 30, 1, 1,
+ 31, 32, 32, 32, 32, 32, 32, 32,
+ 32, 32, 1, 33, 34, 34, 34, 34,
+ 34, 34, 34, 34, 34, 1, 29, 1,
+ 1, 1, 28, 28, 28, 28, 28, 28,
+ 28, 28, 28, 28, 1, 35, 35, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 30, 1,
- 1, 30, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 35,
+ 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, 1, 30, 30, 1,
+ 1, 1, 1, 1, 1, 1, 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, 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,
+ 1, 1, 1, 1, 1, 1, 35, 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,
@@ -201,282 +199,235 @@ static const char _deserialize_text_indicies[] = {
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,
+ 57, 57, 57, 57, 57, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 57,
+ 35, 35, 58, 35, 35, 35, 35, 35,
+ 35, 35, 59, 1, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 60, 35, 35, 61,
+ 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, 62, 63, 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, 64, 35, 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, 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, 70, 1,
+ 1, 66, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 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,
+ 67, 1, 68, 68, 68, 68, 68, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 72, 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, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 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, 1, 1, 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, 73, 1, 74, 74, 74, 74,
- 74, 48, 48, 48, 48, 48, 48, 48,
+ 1, 1, 1, 1, 1, 69, 1, 70,
+ 70, 70, 70, 70, 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, 70, 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,
- 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, 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, 56,
- 48, 75, 75, 75, 75, 75, 1, 1,
+ 48, 48, 48, 48, 48, 48, 48, 48,
+ 48, 48, 56, 48, 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, 72, 1,
+ 1, 1, 1, 1, 1, 1, 1, 73,
1, 1, 1, 1, 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,
- 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, 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, 1, 79, 1, 80, 80,
- 80, 80, 80, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 75,
+ 1, 76, 76, 76, 76, 76, 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,
+ 76, 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, 1, 1, 1, 1,
1, 1, 1, 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, 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, 82, 1, 80, 80, 80, 80, 80,
+ 1, 1, 1, 1, 79, 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,
+ 77, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 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, 1,
+ 1, 1, 78, 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, 1, 1,
+ 1, 79, 1, 71, 71, 71, 71, 71,
1, 1, 1, 1, 1, 1, 1, 1,
- 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, 71, 1, 1, 72, 1, 1,
+ 1, 1, 1, 1, 1, 1, 73, 1,
+ 1, 1, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 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, 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, 75, 1,
+ 80, 80, 80, 80, 80, 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, 80,
+ 1, 1, 81, 1, 1, 1, 1, 1,
+ 1, 1, 82, 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, 83,
1, 1, 1, 1, 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, 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, 84, 1, 85, 85, 85,
+ 85, 85, 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, 85, 1, 1, 86,
+ 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, 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,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 88, 1, 1, 1, 1, 1, 1,
1, 1, 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, 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,
+ 89, 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, 86, 1, 1, 1,
+ 1, 1, 1, 1, 87, 1, 1, 1,
+ 1, 34, 34, 34, 34, 34, 34, 34,
+ 34, 34, 34, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 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, 88, 1,
1, 1, 1, 1, 1, 1, 1, 1,
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, 89, 1, 80,
+ 80, 80, 80, 80, 1, 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,
+ 1, 1, 1, 1, 1, 1, 80, 1,
+ 1, 81, 1, 1, 1, 1, 1, 1,
+ 1, 82, 1, 1, 1, 1, 90, 90,
+ 90, 90, 90, 90, 90, 90, 90, 90,
+ 1, 1, 1, 1, 1, 1, 83, 1,
1, 1, 1, 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, 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, 84, 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,
- 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, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 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, 70, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 66, 1, 1, 1, 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
+ 1, 1, 1, 1, 1, 1, 1, 67,
+ 1, 0
};
static const char _deserialize_text_trans_targs[] = {
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,
+ 24, 25, 28, 39, 9, 31, 34, 31,
+ 34, 11, 32, 33, 32, 33, 35, 38,
+ 14, 15, 18, 15, 18, 16, 17, 36,
+ 37, 36, 37, 27, 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
+ 27, 27, 7, 8, 12, 13, 19, 22,
+ 30, 27, 7, 8, 12, 13, 19, 22,
+ 30, 29, 22, 30, 29, 30, 30, 29,
+ 7, 10, 22, 30, 29, 7, 22, 30,
+ 29, 7, 8, 13, 30, 29, 7, 8,
+ 22, 30, 38, 39
};
static const char _deserialize_text_trans_actions[] = {
0, 0, 0, 0, 1, 0, 2, 0,
- 2, 2, 3, 4, 4, 5, 5, 4,
- 4, 4, 4, 3, 3, 3, 0, 0,
- 6, 3, 4, 4, 5, 5, 5, 3,
- 4, 4, 5, 5, 7, 8, 9, 7,
+ 2, 2, 3, 3, 4, 3, 3, 5,
+ 5, 4, 3, 3, 5, 5, 3, 3,
+ 4, 4, 4, 0, 0, 6, 4, 3,
+ 3, 5, 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
+ 12, 13, 14, 14, 14, 14, 15, 11,
+ 11, 17, 18, 18, 18, 18, 0, 16,
+ 16, 19, 19, 19, 0, 0, 13, 20,
+ 21, 21, 20, 20, 22, 23, 22, 22,
+ 10, 24, 24, 24, 10, 25, 26, 26,
+ 25, 25, 5, 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, 0, 7, 0, 0, 0,
- 10, 10, 11, 17, 17, 21, 0, 11,
- 10, 24, 24, 25, 25, 10, 27, 27,
- 21, 29, 29
+ 10, 10, 11, 16, 19, 0, 11, 20,
+ 22, 22, 20, 10, 25, 25, 10, 19
};
static const int deserialize_text_start = 1;
@@ -509,12 +460,12 @@ _hb_buffer_deserialize_text (hb_buffer_t *buffer,
hb_glyph_info_t info = {0};
hb_glyph_position_t pos = {0};
-#line 513 "hb-buffer-deserialize-text.hh"
+#line 457 "hb-buffer-deserialize-text.hh"
{
cs = deserialize_text_start;
}
-#line 518 "hb-buffer-deserialize-text.hh"
+#line 460 "hb-buffer-deserialize-text.hh"
{
int _slen;
int _trans;
@@ -542,11 +493,11 @@ _resume:
case 1:
#line 38 "hb-buffer-deserialize-text.rl"
{
- memset (&info, 0, sizeof (info));
- memset (&pos , 0, sizeof (pos ));
+ hb_memset (&info, 0, sizeof (info));
+ hb_memset (&pos , 0, sizeof (pos ));
}
break;
- case 3:
+ case 4:
#line 51 "hb-buffer-deserialize-text.rl"
{
tok = p;
@@ -560,7 +511,7 @@ _resume:
#line 56 "hb-buffer-deserialize-text.rl"
{ if (unlikely (!buffer->ensure_unicode ())) return false; }
break;
- case 20:
+ case 18:
#line 58 "hb-buffer-deserialize-text.rl"
{
/* TODO Unescape delimiters. */
@@ -574,7 +525,7 @@ _resume:
#line 66 "hb-buffer-deserialize-text.rl"
{if (!parse_hex (tok, p, &info.codepoint )) return false; }
break;
- case 23:
+ case 24:
#line 68 "hb-buffer-deserialize-text.rl"
{ if (!parse_uint (tok, p, &info.cluster )) return false; }
break;
@@ -586,26 +537,26 @@ _resume:
#line 70 "hb-buffer-deserialize-text.rl"
{ if (!parse_int (tok, p, &pos.y_offset )) return false; }
break;
- case 22:
+ case 21:
#line 71 "hb-buffer-deserialize-text.rl"
{ if (!parse_int (tok, p, &pos.x_advance)) return false; }
break;
- case 28:
+ case 23:
#line 72 "hb-buffer-deserialize-text.rl"
{ if (!parse_int (tok, p, &pos.y_advance)) return false; }
break;
- case 16:
+ case 15:
#line 38 "hb-buffer-deserialize-text.rl"
{
- memset (&info, 0, sizeof (info));
- memset (&pos , 0, sizeof (pos ));
+ hb_memset (&info, 0, sizeof (info));
+ hb_memset (&pos , 0, sizeof (pos ));
}
#line 51 "hb-buffer-deserialize-text.rl"
{
tok = p;
}
break;
- case 4:
+ case 3:
#line 51 "hb-buffer-deserialize-text.rl"
{
tok = p;
@@ -621,7 +572,7 @@ _resume:
#line 56 "hb-buffer-deserialize-text.rl"
{ if (unlikely (!buffer->ensure_unicode ())) return false; }
break;
- case 17:
+ case 16:
#line 58 "hb-buffer-deserialize-text.rl"
{
/* TODO Unescape delimiters. */
@@ -639,18 +590,6 @@ _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; }
@@ -687,7 +626,7 @@ _resume:
*end_ptr = p;
}
break;
- case 21:
+ case 20:
#line 71 "hb-buffer-deserialize-text.rl"
{ if (!parse_int (tok, p, &pos.x_advance)) return false; }
#line 43 "hb-buffer-deserialize-text.rl"
@@ -699,7 +638,7 @@ _resume:
*end_ptr = p;
}
break;
- case 27:
+ case 22:
#line 72 "hb-buffer-deserialize-text.rl"
{ if (!parse_int (tok, p, &pos.y_advance)) return false; }
#line 43 "hb-buffer-deserialize-text.rl"
@@ -711,7 +650,7 @@ _resume:
*end_ptr = p;
}
break;
- case 24:
+ case 19:
#line 73 "hb-buffer-deserialize-text.rl"
{ if (!parse_uint (tok, p, &info.mask )) return false; }
#line 43 "hb-buffer-deserialize-text.rl"
@@ -726,8 +665,8 @@ _resume:
case 12:
#line 38 "hb-buffer-deserialize-text.rl"
{
- memset (&info, 0, sizeof (info));
- memset (&pos , 0, sizeof (pos ));
+ hb_memset (&info, 0, sizeof (info));
+ hb_memset (&pos , 0, sizeof (pos ));
}
#line 51 "hb-buffer-deserialize-text.rl"
{
@@ -736,11 +675,11 @@ _resume:
#line 55 "hb-buffer-deserialize-text.rl"
{ if (unlikely (!buffer->ensure_glyphs ())) return false; }
break;
- case 15:
+ case 14:
#line 38 "hb-buffer-deserialize-text.rl"
{
- memset (&info, 0, sizeof (info));
- memset (&pos , 0, sizeof (pos ));
+ hb_memset (&info, 0, sizeof (info));
+ hb_memset (&pos , 0, sizeof (pos ));
}
#line 51 "hb-buffer-deserialize-text.rl"
{
@@ -755,7 +694,7 @@ _resume:
return false;
}
break;
- case 18:
+ case 17:
#line 58 "hb-buffer-deserialize-text.rl"
{
/* TODO Unescape delimiters. */
@@ -775,31 +714,11 @@ _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"
{
- memset (&info, 0, sizeof (info));
- memset (&pos , 0, sizeof (pos ));
+ hb_memset (&info, 0, sizeof (info));
+ hb_memset (&pos , 0, sizeof (pos ));
}
#line 51 "hb-buffer-deserialize-text.rl"
{
@@ -822,54 +741,11 @@ _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"
{
- memset (&info, 0, sizeof (info));
- memset (&pos , 0, sizeof (pos ));
+ hb_memset (&info, 0, sizeof (info));
+ hb_memset (&pos , 0, sizeof (pos ));
}
#line 51 "hb-buffer-deserialize-text.rl"
{
@@ -894,7 +770,7 @@ _resume:
*end_ptr = p;
}
break;
-#line 898 "hb-buffer-deserialize-text.hh"
+#line 715 "hb-buffer-deserialize-text.hh"
}
_again:
@@ -906,7 +782,7 @@ _again:
if ( p == eof )
{
switch ( _deserialize_text_eof_actions[cs] ) {
- case 17:
+ case 16:
#line 58 "hb-buffer-deserialize-text.rl"
{
/* TODO Unescape delimiters. */
@@ -960,7 +836,7 @@ _again:
*end_ptr = p;
}
break;
- case 21:
+ case 20:
#line 71 "hb-buffer-deserialize-text.rl"
{ if (!parse_int (tok, p, &pos.x_advance)) return false; }
#line 43 "hb-buffer-deserialize-text.rl"
@@ -972,7 +848,7 @@ _again:
*end_ptr = p;
}
break;
- case 27:
+ case 22:
#line 72 "hb-buffer-deserialize-text.rl"
{ if (!parse_int (tok, p, &pos.y_advance)) return false; }
#line 43 "hb-buffer-deserialize-text.rl"
@@ -984,27 +860,7 @@ _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;
-}
+ case 19:
#line 73 "hb-buffer-deserialize-text.rl"
{ if (!parse_uint (tok, p, &info.mask )) return false; }
#line 43 "hb-buffer-deserialize-text.rl"
@@ -1019,8 +875,8 @@ _again:
case 11:
#line 38 "hb-buffer-deserialize-text.rl"
{
- memset (&info, 0, sizeof (info));
- memset (&pos , 0, sizeof (pos ));
+ hb_memset (&info, 0, sizeof (info));
+ hb_memset (&pos , 0, sizeof (pos ));
}
#line 51 "hb-buffer-deserialize-text.rl"
{
@@ -1043,7 +899,7 @@ _again:
*end_ptr = p;
}
break;
-#line 1047 "hb-buffer-deserialize-text.hh"
+#line 825 "hb-buffer-deserialize-text.hh"
}
}
diff --git a/thirdparty/harfbuzz/src/hb-buffer-serialize.cc b/thirdparty/harfbuzz/src/hb-buffer-serialize.cc
index d1e1775430..a458f2318f 100644
--- a/thirdparty/harfbuzz/src/hb-buffer-serialize.cc
+++ b/thirdparty/harfbuzz/src/hb-buffer-serialize.cc
@@ -183,7 +183,7 @@ _hb_buffer_serialize_glyphs_json (hb_buffer_t *buffer,
unsigned int l = p - b;
if (buf_size > l)
{
- memcpy (buf, b, l);
+ hb_memcpy (buf, b, l);
buf += l;
buf_size -= l;
*buf_consumed += l;
@@ -241,7 +241,7 @@ _hb_buffer_serialize_unicode_json (hb_buffer_t *buffer,
unsigned int l = p - b;
if (buf_size > l)
{
- memcpy (buf, b, l);
+ hb_memcpy (buf, b, l);
buf += l;
buf_size -= l;
*buf_consumed += l;
@@ -329,7 +329,7 @@ _hb_buffer_serialize_glyphs_text (hb_buffer_t *buffer,
unsigned int l = p - b;
if (buf_size > l)
{
- memcpy (buf, b, l);
+ hb_memcpy (buf, b, l);
buf += l;
buf_size -= l;
*buf_consumed += l;
@@ -381,7 +381,7 @@ _hb_buffer_serialize_unicode_text (hb_buffer_t *buffer,
unsigned int l = p - b;
if (buf_size > l)
{
- memcpy (buf, b, l);
+ hb_memcpy (buf, b, l);
buf += l;
buf_size -= l;
*buf_consumed += l;
diff --git a/thirdparty/harfbuzz/src/hb-buffer-verify.cc b/thirdparty/harfbuzz/src/hb-buffer-verify.cc
index 5453e1ca94..1cd52b39b1 100644
--- a/thirdparty/harfbuzz/src/hb-buffer-verify.cc
+++ b/thirdparty/harfbuzz/src/hb-buffer-verify.cc
@@ -186,7 +186,7 @@ buffer_verify_unsafe_to_break (hb_buffer_t *buffer,
bool ret = true;
hb_buffer_diff_flags_t diff = hb_buffer_diff (reconstruction, buffer, (hb_codepoint_t) -1, 0);
- if (diff)
+ if (diff & ~HB_BUFFER_DIFF_FLAG_GLYPH_FLAGS_MISMATCH)
{
buffer_verify_error (buffer, font, BUFFER_VERIFY_ERROR "unsafe-to-break test failed.");
ret = false;
@@ -313,7 +313,6 @@ buffer_verify_unsafe_to_concat (hb_buffer_t *buffer,
bool ret = true;
hb_buffer_diff_flags_t diff;
-
/*
* Shape the two fragment streams.
*/
@@ -382,7 +381,7 @@ buffer_verify_unsafe_to_concat (hb_buffer_t *buffer,
* Diff results.
*/
diff = hb_buffer_diff (reconstruction, buffer, (hb_codepoint_t) -1, 0);
- if (diff)
+ if (diff & ~HB_BUFFER_DIFF_FLAG_GLYPH_FLAGS_MISMATCH)
{
buffer_verify_error (buffer, font, BUFFER_VERIFY_ERROR "unsafe-to-concat test failed.");
ret = false;
diff --git a/thirdparty/harfbuzz/src/hb-buffer.cc b/thirdparty/harfbuzz/src/hb-buffer.cc
index 57a5ae03ed..4b6c2d9eaa 100644
--- a/thirdparty/harfbuzz/src/hb-buffer.cc
+++ b/thirdparty/harfbuzz/src/hb-buffer.cc
@@ -172,12 +172,13 @@ hb_buffer_t::enlarge (unsigned int size)
while (size >= new_allocated)
new_allocated += (new_allocated >> 1) + 32;
- static_assert ((sizeof (info[0]) == sizeof (pos[0])), "");
- if (unlikely (hb_unsigned_mul_overflows (new_allocated, sizeof (info[0]))))
+ unsigned new_bytes;
+ if (unlikely (hb_unsigned_mul_overflows (new_allocated, sizeof (info[0]), &new_bytes)))
goto done;
- new_pos = (hb_glyph_position_t *) hb_realloc (pos, new_allocated * sizeof (pos[0]));
- new_info = (hb_glyph_info_t *) hb_realloc (info, new_allocated * sizeof (info[0]));
+ static_assert (sizeof (info[0]) == sizeof (pos[0]), "");
+ new_pos = (hb_glyph_position_t *) hb_realloc (pos, new_bytes);
+ new_info = (hb_glyph_info_t *) hb_realloc (info, new_bytes);
done:
if (unlikely (!new_pos || !new_info))
@@ -208,7 +209,7 @@ hb_buffer_t::make_room_for (unsigned int num_in,
assert (have_output);
out_info = (hb_glyph_info_t *) pos;
- memcpy (out_info, info, out_len * sizeof (out_info[0]));
+ hb_memcpy (out_info, info, out_len * sizeof (out_info[0]));
}
return true;
@@ -229,7 +230,7 @@ hb_buffer_t::shift_forward (unsigned int count)
* Ideally, we should at least set Default_Ignorable bits on
* these, as well as consistent cluster values. But the former
* is layering violation... */
- memset (info + len, 0, (idx + count - len) * sizeof (info[0]));
+ hb_memset (info + len, 0, (idx + count - len) * sizeof (info[0]));
}
len += count;
idx += count;
@@ -298,8 +299,8 @@ hb_buffer_t::clear ()
out_len = 0;
out_info = info;
- memset (context, 0, sizeof context);
- memset (context_len, 0, sizeof context_len);
+ hb_memset (context, 0, sizeof context);
+ hb_memset (context_len, 0, sizeof context_len);
deallocate_var_all ();
serial = 0;
@@ -313,15 +314,14 @@ hb_buffer_t::enter ()
serial = 0;
shaping_failed = false;
scratch_flags = HB_BUFFER_SCRATCH_FLAG_DEFAULT;
- if (likely (!hb_unsigned_mul_overflows (len, HB_BUFFER_MAX_LEN_FACTOR)))
+ unsigned mul;
+ if (likely (!hb_unsigned_mul_overflows (len, HB_BUFFER_MAX_LEN_FACTOR, &mul)))
{
- max_len = hb_max (len * HB_BUFFER_MAX_LEN_FACTOR,
- (unsigned) HB_BUFFER_MAX_LEN_MIN);
+ max_len = hb_max (mul, (unsigned) HB_BUFFER_MAX_LEN_MIN);
}
- if (likely (!hb_unsigned_mul_overflows (len, HB_BUFFER_MAX_OPS_FACTOR)))
+ if (likely (!hb_unsigned_mul_overflows (len, HB_BUFFER_MAX_OPS_FACTOR, &mul)))
{
- max_ops = hb_max (len * HB_BUFFER_MAX_OPS_FACTOR,
- (unsigned) HB_BUFFER_MAX_OPS_MIN);
+ max_ops = hb_max (mul, (unsigned) HB_BUFFER_MAX_OPS_MIN);
}
}
void
@@ -345,7 +345,7 @@ hb_buffer_t::add (hb_codepoint_t codepoint,
glyph = &info[len];
- memset (glyph, 0, sizeof (*glyph));
+ hb_memset (glyph, 0, sizeof (*glyph));
glyph->codepoint = codepoint;
glyph->mask = 0;
glyph->cluster = cluster;
@@ -606,6 +606,53 @@ done:
}
void
+hb_buffer_t::delete_glyphs_inplace (bool (*filter) (const hb_glyph_info_t *info))
+{
+ /* Merge clusters and delete filtered glyphs.
+ * NOTE! We can't use out-buffer as we have positioning data. */
+ unsigned int j = 0;
+ unsigned int count = len;
+ for (unsigned int i = 0; i < count; i++)
+ {
+ if (filter (&info[i]))
+ {
+ /* Merge clusters.
+ * Same logic as delete_glyph(), but for in-place removal. */
+
+ unsigned int cluster = info[i].cluster;
+ if (i + 1 < count && cluster == info[i + 1].cluster)
+ continue; /* Cluster survives; do nothing. */
+
+ if (j)
+ {
+ /* Merge cluster backward. */
+ if (cluster < info[j - 1].cluster)
+ {
+ unsigned int mask = info[i].mask;
+ unsigned int old_cluster = info[j - 1].cluster;
+ for (unsigned k = j; k && info[k - 1].cluster == old_cluster; k--)
+ set_cluster (info[k - 1], cluster, mask);
+ }
+ continue;
+ }
+
+ if (i + 1 < count)
+ merge_clusters (i, i + 2); /* Merge cluster forward. */
+
+ continue;
+ }
+
+ if (j != i)
+ {
+ info[j] = info[i];
+ pos[j] = pos[i];
+ }
+ j++;
+ }
+ len = j;
+}
+
+void
hb_buffer_t::guess_segment_properties ()
{
assert_unicode ();
@@ -933,7 +980,6 @@ hb_buffer_get_unicode_funcs (const hb_buffer_t *buffer)
void
hb_buffer_set_direction (hb_buffer_t *buffer,
hb_direction_t direction)
-
{
if (unlikely (hb_object_is_immutable (buffer)))
return;
@@ -1385,9 +1431,9 @@ hb_buffer_set_length (hb_buffer_t *buffer,
/* Wipe the new space */
if (length > buffer->len) {
- memset (buffer->info + buffer->len, 0, sizeof (buffer->info[0]) * (length - buffer->len));
+ hb_memset (buffer->info + buffer->len, 0, sizeof (buffer->info[0]) * (length - buffer->len));
if (buffer->have_positions)
- memset (buffer->pos + buffer->len, 0, sizeof (buffer->pos[0]) * (length - buffer->len));
+ hb_memset (buffer->pos + buffer->len, 0, sizeof (buffer->pos[0]) * (length - buffer->len));
}
buffer->len = length;
@@ -1795,7 +1841,9 @@ hb_buffer_add_latin1 (hb_buffer_t *buffer,
* marks at stat of run.
*
* This function does not check the validity of @text, it is up to the caller
- * to ensure it contains a valid Unicode code points.
+ * to ensure it contains a valid Unicode scalar values. In contrast,
+ * hb_buffer_add_utf32() can be used that takes similar input but performs
+ * sanity-check on the input.
*
* Since: 0.9.31
**/
@@ -1858,9 +1906,9 @@ hb_buffer_append (hb_buffer_t *buffer,
hb_segment_properties_overlay (&buffer->props, &source->props);
- memcpy (buffer->info + orig_len, source->info + start, (end - start) * sizeof (buffer->info[0]));
+ hb_memcpy (buffer->info + orig_len, source->info + start, (end - start) * sizeof (buffer->info[0]));
if (buffer->have_positions)
- memcpy (buffer->pos + orig_len, source->pos + start, (end - start) * sizeof (buffer->pos[0]));
+ hb_memcpy (buffer->pos + orig_len, source->pos + start, (end - start) * sizeof (buffer->pos[0]));
if (source->content_type == HB_BUFFER_CONTENT_TYPE_UNICODE)
{
@@ -2048,7 +2096,7 @@ hb_buffer_diff (hb_buffer_t *buffer,
result |= HB_BUFFER_DIFF_FLAG_CODEPOINT_MISMATCH;
if (buf_info->cluster != ref_info->cluster)
result |= HB_BUFFER_DIFF_FLAG_CLUSTER_MISMATCH;
- if ((buf_info->mask & ~ref_info->mask & HB_GLYPH_FLAG_DEFINED))
+ if ((buf_info->mask ^ ref_info->mask) & HB_GLYPH_FLAG_DEFINED)
result |= HB_BUFFER_DIFF_FLAG_GLYPH_FLAGS_MISMATCH;
if (contains && ref_info->codepoint == dottedcircle_glyph)
result |= HB_BUFFER_DIFF_FLAG_DOTTED_CIRCLE_PRESENT;
@@ -2103,6 +2151,13 @@ hb_buffer_set_message_func (hb_buffer_t *buffer,
hb_buffer_message_func_t func,
void *user_data, hb_destroy_func_t destroy)
{
+ if (unlikely (hb_object_is_immutable (buffer)))
+ {
+ if (destroy)
+ destroy (user_data);
+ return;
+ }
+
if (buffer->message_destroy)
buffer->message_destroy (buffer->message_data);
diff --git a/thirdparty/harfbuzz/src/hb-buffer.hh b/thirdparty/harfbuzz/src/hb-buffer.hh
index 26c3f0fac8..bb1efe9dd3 100644
--- a/thirdparty/harfbuzz/src/hb-buffer.hh
+++ b/thirdparty/harfbuzz/src/hb-buffer.hh
@@ -32,6 +32,7 @@
#include "hb.hh"
#include "hb-unicode.hh"
+#include "hb-set-digest.hh"
#ifndef HB_BUFFER_MAX_LEN_FACTOR
@@ -207,6 +208,14 @@ struct hb_buffer_t
hb_glyph_info_t &prev () { return out_info[out_len ? out_len - 1 : 0]; }
hb_glyph_info_t prev () const { return out_info[out_len ? out_len - 1 : 0]; }
+ hb_set_digest_t digest () const
+ {
+ hb_set_digest_t d;
+ d.init ();
+ d.add_array (&info[0].codepoint, len, sizeof (info[0]));
+ return d;
+ }
+
HB_INTERNAL void similar (const hb_buffer_t &src);
HB_INTERNAL void reset ();
HB_INTERNAL void clear ();
@@ -402,6 +411,8 @@ struct hb_buffer_t
HB_INTERNAL void merge_out_clusters (unsigned int start, unsigned int end);
/* Merge clusters for deleting current glyph, and skip it. */
HB_INTERNAL void delete_glyph ();
+ HB_INTERNAL void delete_glyphs_inplace (bool (*filter) (const hb_glyph_info_t *info));
+
/* Adds glyph flags in mask to infos with clusters between start and end.
diff --git a/thirdparty/harfbuzz/src/hb-cache.hh b/thirdparty/harfbuzz/src/hb-cache.hh
index 897f313fbd..f8c8108f1f 100644
--- a/thirdparty/harfbuzz/src/hb-cache.hh
+++ b/thirdparty/harfbuzz/src/hb-cache.hh
@@ -46,7 +46,7 @@ struct hb_cache_t
>::type;
static_assert ((key_bits >= cache_bits), "");
- static_assert ((key_bits + value_bits - cache_bits <= 8 * sizeof (item_t)), "");
+ static_assert ((key_bits + value_bits <= cache_bits + 8 * sizeof (item_t)), "");
void init () { clear (); }
void fini () {}
diff --git a/thirdparty/harfbuzz/src/hb-cff-interp-common.hh b/thirdparty/harfbuzz/src/hb-cff-interp-common.hh
index 5c2cb060a4..49805a89c5 100644
--- a/thirdparty/harfbuzz/src/hb-cff-interp-common.hh
+++ b/thirdparty/harfbuzz/src/hb-cff-interp-common.hh
@@ -284,65 +284,56 @@ struct UnsizedByteStr : UnsizedArrayOf <HBUINT8>
/* A byte string associated with the current offset and an error condition */
struct byte_str_ref_t
{
- byte_str_ref_t () { init (); }
-
- void init ()
- {
- str = hb_ubytes_t ();
- offset = 0;
- error = false;
- }
-
- void fini () {}
+ byte_str_ref_t ()
+ : str () {}
byte_str_ref_t (const hb_ubytes_t &str_, unsigned int offset_ = 0)
- : str (str_), offset (offset_), error (false) {}
+ : str (str_) { set_offset (offset_); }
void reset (const hb_ubytes_t &str_, unsigned int offset_ = 0)
{
str = str_;
- offset = offset_;
- error = false;
+ set_offset (offset_);
}
const unsigned char& operator [] (int i) {
- if (unlikely ((unsigned int) (offset + i) >= str.length))
+ if (unlikely ((unsigned int) (get_offset () + i) >= str.length))
{
set_error ();
return Null (unsigned char);
}
- return str[offset + i];
+ return str.arrayZ[get_offset () + i];
}
+ unsigned char head_unchecked () const { return str.arrayZ[get_offset ()]; }
+
/* Conversion to hb_ubytes_t */
- operator hb_ubytes_t () const { return str.sub_array (offset, str.length - offset); }
+ operator hb_ubytes_t () const { return str.sub_array (get_offset ()); }
hb_ubytes_t sub_array (unsigned int offset_, unsigned int len_) const
{ return str.sub_array (offset_, len_); }
bool avail (unsigned int count=1) const
- { return (!in_error () && offset + count <= str.length); }
+ { return get_offset () + count <= str.length; }
void inc (unsigned int count=1)
{
- if (likely (!in_error () && (offset <= str.length) && (offset + count <= str.length)))
- {
- offset += count;
- }
- else
- {
- offset = str.length;
- set_error ();
- }
+ /* Automatically puts us in error if count is out-of-range. */
+ set_offset (get_offset () + count);
}
- void set_error () { error = true; }
- bool in_error () const { return error; }
+ /* We (ab)use ubytes backwards_length as a cursor (called offset),
+ * as well as to store error condition. */
- hb_ubytes_t str;
- unsigned int offset; /* beginning of the sub-string within str */
+ unsigned get_offset () const { return str.backwards_length; }
+ void set_offset (unsigned offset) { str.backwards_length = offset; }
+
+ void set_error () { str.backwards_length = str.length + 1; }
+ bool in_error () const { return str.backwards_length > str.length; }
+
+ unsigned total_size () const { return str.length; }
protected:
- bool error;
+ hb_ubytes_t str;
};
using byte_str_array_t = hb_vector_t<hb_ubytes_t>;
@@ -491,8 +482,15 @@ struct arg_stack_t : cff_stack_t<ARG, 513>
/* an operator prefixed by its operands in a byte string */
struct op_str_t
{
- hb_ubytes_t str;
+ /* This used to have a hb_ubytes_t. Using a pointer and length
+ * in a particular order, saves 8 bytes in this struct and more
+ * in our parsed_cs_op_t subclass. */
+
+ const unsigned char *ptr = nullptr;
+
op_code_t op;
+
+ uint8_t length = 0;
};
/* base of OP_SERIALIZER */
@@ -503,9 +501,11 @@ struct op_serializer_t
{
TRACE_SERIALIZE (this);
- HBUINT8 *d = c->allocate_size<HBUINT8> (opstr.str.length);
+ unsigned char *d = c->allocate_size<unsigned char> (opstr.length);
if (unlikely (!d)) return_trace (false);
- memcpy (d, &opstr.str[0], opstr.str.length);
+ /* Faster than hb_memcpy for small strings. */
+ for (unsigned i = 0; i < opstr.length; i++)
+ d[i] = opstr.ptr[i];
return_trace (true);
}
};
@@ -529,16 +529,20 @@ struct parsed_values_t
{
VAL *val = values.push ();
val->op = op;
- val->str = str_ref.str.sub_array (opStart, str_ref.offset - opStart);
- opStart = str_ref.offset;
+ auto arr = str_ref.sub_array (opStart, str_ref.get_offset () - opStart);
+ val->ptr = arr.arrayZ;
+ val->length = arr.length;
+ opStart = str_ref.get_offset ();
}
void add_op (op_code_t op, const byte_str_ref_t& str_ref, const VAL &v)
{
VAL *val = values.push (v);
val->op = op;
- val->str = str_ref.sub_array ( opStart, str_ref.offset - opStart);
- opStart = str_ref.offset;
+ auto arr = str_ref.sub_array (opStart, str_ref.get_offset () - opStart);
+ val->ptr = arr.arrayZ;
+ val->length = arr.length;
+ opStart = str_ref.get_offset ();
}
bool has_op (op_code_t op) const
@@ -549,8 +553,7 @@ struct parsed_values_t
}
unsigned get_count () const { return values.length; }
- const VAL &get_value (unsigned int i) const { return values[i]; }
- const VAL &operator [] (unsigned int i) const { return get_value (i); }
+ const VAL &operator [] (unsigned int i) const { return values[i]; }
unsigned int opStart;
hb_vector_t<VAL> values;
@@ -565,23 +568,23 @@ struct interp_env_t
str_ref.reset (str_);
}
bool in_error () const
- { return error || str_ref.in_error () || argStack.in_error (); }
+ { return str_ref.in_error () || argStack.in_error (); }
- void set_error () { error = true; }
+ void set_error () { str_ref.set_error (); }
op_code_t fetch_op ()
{
op_code_t op = OpCode_Invalid;
if (unlikely (!str_ref.avail ()))
return OpCode_Invalid;
- op = (op_code_t)(unsigned char)str_ref[0];
+ op = (op_code_t) str_ref.head_unchecked ();
+ str_ref.inc ();
if (op == OpCode_escape) {
if (unlikely (!str_ref.avail ()))
return OpCode_Invalid;
- op = Make_OpCode_ESC(str_ref[1]);
+ op = Make_OpCode_ESC (str_ref.head_unchecked ());
str_ref.inc ();
}
- str_ref.inc ();
return op;
}
@@ -596,8 +599,6 @@ struct interp_env_t
str_ref;
arg_stack_t<ARG>
argStack;
- protected:
- bool error = false;
};
using num_interp_env_t = interp_env_t<>;
diff --git a/thirdparty/harfbuzz/src/hb-cff2-interp-cs.hh b/thirdparty/harfbuzz/src/hb-cff2-interp-cs.hh
index d0b9e7b086..00c25800e6 100644
--- a/thirdparty/harfbuzz/src/hb-cff2-interp-cs.hh
+++ b/thirdparty/harfbuzz/src/hb-cff2-interp-cs.hh
@@ -40,13 +40,15 @@ struct blend_arg_t : number_t
void set_real (double v) { reset_blends (); number_t::set_real (v); }
void set_blends (unsigned int numValues_, unsigned int valueIndex_,
- unsigned int numBlends, hb_array_t<const blend_arg_t> blends_)
+ hb_array_t<const blend_arg_t> blends_)
{
numValues = numValues_;
valueIndex = valueIndex_;
- deltas.resize (numBlends);
+ unsigned numBlends = blends_.length;
+ if (unlikely (!deltas.resize (numBlends)))
+ return;
for (unsigned int i = 0; i < numBlends; i++)
- deltas[i] = blends_[i];
+ deltas.arrayZ[i] = blends_.arrayZ[i];
}
bool blending () const { return deltas.length > 0; }
@@ -61,7 +63,6 @@ struct blend_arg_t : number_t
hb_vector_t<number_t> deltas;
};
-typedef interp_env_t<blend_arg_t> BlendInterpEnv;
typedef biased_subrs_t<CFF2Subrs> cff2_biased_subrs_t;
template <typename ELEM>
@@ -154,8 +155,9 @@ struct cff2_cs_interp_env_t : cs_interp_env_t<ELEM, CFF2Subrs>
{
if (likely (scalars.length == deltas.length))
{
- for (unsigned int i = 0; i < scalars.length; i++)
- v += (double) scalars[i] * deltas[i].to_real ();
+ unsigned count = scalars.length;
+ for (unsigned i = 0; i < count; i++)
+ v += (double) scalars.arrayZ[i] * deltas.arrayZ[i].to_real ();
}
}
return v;
@@ -220,7 +222,7 @@ struct cff2_cs_opset_t : cs_opset_t<ELEM, OPSET, cff2_cs_interp_env_t<ELEM>, PAR
const hb_array_t<const ELEM> blends,
unsigned n, unsigned i)
{
- arg.set_blends (n, i, blends.length, blends);
+ arg.set_blends (n, i, blends);
}
template <typename T = ELEM,
hb_enable_if (!hb_is_same (T, blend_arg_t))>
diff --git a/thirdparty/harfbuzz/src/hb-common.cc b/thirdparty/harfbuzz/src/hb-common.cc
index bbb6cd552b..e9f9cfeb5f 100644
--- a/thirdparty/harfbuzz/src/hb-common.cc
+++ b/thirdparty/harfbuzz/src/hb-common.cc
@@ -285,7 +285,7 @@ struct hb_language_item_t {
lang = (hb_language_t) hb_malloc(len);
if (likely (lang))
{
- memcpy((unsigned char *) lang, s, len);
+ hb_memcpy((unsigned char *) lang, s, len);
for (unsigned char *p = (unsigned char *) lang; *p; p++)
*p = canon_map[*p];
}
@@ -379,7 +379,7 @@ hb_language_from_string (const char *str, int len)
/* NUL-terminate it. */
char strbuf[64];
len = hb_min (len, (int) sizeof (strbuf) - 1);
- memcpy (strbuf, str, len);
+ hb_memcpy (strbuf, str, len);
strbuf[len] = '\0';
item = lang_find_or_insert (strbuf);
}
@@ -976,7 +976,7 @@ hb_feature_from_string (const char *str, int len,
}
if (feature)
- memset (feature, 0, sizeof (*feature));
+ hb_memset (feature, 0, sizeof (*feature));
return false;
}
@@ -1025,7 +1025,7 @@ hb_feature_to_string (hb_feature_t *feature,
}
assert (len < ARRAY_LENGTH (s));
len = hb_min (len, size - 1);
- memcpy (buf, s, len);
+ hb_memcpy (buf, s, len);
buf[len] = '\0';
}
@@ -1088,7 +1088,7 @@ hb_variation_from_string (const char *str, int len,
}
if (variation)
- memset (variation, 0, sizeof (*variation));
+ hb_memset (variation, 0, sizeof (*variation));
return false;
}
@@ -1136,7 +1136,7 @@ get_C_locale ()
/**
* hb_variation_to_string:
* @variation: an #hb_variation_t to convert
- * @buf: (array length=size) (out): output string
+ * @buf: (array length=size) (out caller-allocates): output string
* @size: the allocated size of @buf
*
* Converts an #hb_variation_t into a `NULL`-terminated string in the format
@@ -1166,7 +1166,7 @@ hb_variation_to_string (hb_variation_t *variation,
assert (len < ARRAY_LENGTH (s));
len = hb_min (len, size - 1);
- memcpy (buf, s, len);
+ hb_memcpy (buf, s, len);
buf[len] = '\0';
}
diff --git a/thirdparty/harfbuzz/src/hb-config.hh b/thirdparty/harfbuzz/src/hb-config.hh
index d56617f6a9..98b1e9d0cf 100644
--- a/thirdparty/harfbuzz/src/hb-config.hh
+++ b/thirdparty/harfbuzz/src/hb-config.hh
@@ -35,8 +35,9 @@
#include "config.h"
#endif
-#ifndef HB_BORING_EXPANSION
-#define HB_NO_BORING_EXPANSION
+#ifndef HB_EXPERIMENTAL_API
+#define HB_NO_BEYOND_64K
+#define HB_NO_VAR_COMPOSITES
#endif
#ifdef HB_TINY
@@ -84,6 +85,7 @@
#define HB_NO_OT_SHAPE_FRACTIONS
#define HB_NO_STYLE
#define HB_NO_SUBSET_LAYOUT
+#define HB_NO_VERTICAL
#define HB_NO_VAR
#endif
@@ -104,7 +106,7 @@
#ifdef HB_NO_BORING_EXPANSION
#define HB_NO_BEYOND_64K
-#define HB_NO_VARIATIONS2
+#define HB_NO_AVAR2
#endif
#ifdef HB_DISABLE_DEPRECATED
@@ -113,6 +115,11 @@
#define HB_IF_NOT_DEPRECATED(x) x
#endif
+#ifdef HB_NO_SHAPER
+#define HB_NO_OT_SHAPE
+#define HB_NO_AAT_SHAPE
+#endif
+
#ifdef HB_NO_AAT
#define HB_NO_OT_NAME_LANGUAGE_AAT
#define HB_NO_AAT_SHAPE
@@ -159,6 +166,7 @@
#define HB_NO_OT_SHAPER_HEBREW_FALLBACK
#define HB_NO_OT_SHAPER_THAI_FALLBACK
#define HB_NO_OT_SHAPER_VOWEL_CONSTRAINTS
+#define HB_NO_OT_SHAPER_MYANMAR_ZAWGYI
#endif
#ifdef NDEBUG
diff --git a/thirdparty/harfbuzz/src/hb-coretext.cc b/thirdparty/harfbuzz/src/hb-coretext.cc
index 99b33c001e..4267e0e13e 100644
--- a/thirdparty/harfbuzz/src/hb-coretext.cc
+++ b/thirdparty/harfbuzz/src/hb-coretext.cc
@@ -347,10 +347,13 @@ _hb_coretext_shaper_font_data_create (hb_font_t *font)
hb_ot_var_axis_info_t info;
unsigned int c = 1;
hb_ot_var_get_axis_infos (font->face, i, &c, &info);
- CFDictionarySetValue (variations,
- CFNumberCreate (kCFAllocatorDefault, kCFNumberIntType, &info.tag),
- CFNumberCreate (kCFAllocatorDefault, kCFNumberFloatType, &font->design_coords[i])
- );
+ float v = hb_clamp (font->design_coords[i], info.min_value, info.max_value);
+
+ CFNumberRef tag_number = CFNumberCreate (kCFAllocatorDefault, kCFNumberIntType, &info.tag);
+ CFNumberRef value_number = CFNumberCreate (kCFAllocatorDefault, kCFNumberFloatType, &v);
+ CFDictionarySetValue (variations, tag_number, value_number);
+ CFRelease (tag_number);
+ CFRelease (value_number);
}
CFDictionaryRef attributes =
@@ -648,7 +651,7 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan,
} else {
active_feature_t *feature = active_features.lsearch (event->feature);
if (feature)
- active_features.remove (feature - active_features.arrayZ);
+ active_features.remove_ordered (feature - active_features.arrayZ);
}
}
}
diff --git a/thirdparty/harfbuzz/src/hb-draw.cc b/thirdparty/harfbuzz/src/hb-draw.cc
index 46797e64e6..72c203f24f 100644
--- a/thirdparty/harfbuzz/src/hb-draw.cc
+++ b/thirdparty/harfbuzz/src/hb-draw.cc
@@ -80,6 +80,56 @@ hb_draw_close_path_nil (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data HB_UN
void *user_data HB_UNUSED) {}
+static bool
+_hb_draw_funcs_set_preamble (hb_draw_funcs_t *dfuncs,
+ bool func_is_null,
+ void **user_data,
+ hb_destroy_func_t *destroy)
+{
+ if (hb_object_is_immutable (dfuncs))
+ {
+ if (*destroy)
+ (*destroy) (*user_data);
+ return false;
+ }
+
+ if (func_is_null)
+ {
+ if (*destroy)
+ (*destroy) (*user_data);
+ *destroy = nullptr;
+ *user_data = nullptr;
+ }
+
+ return true;
+}
+
+static bool
+_hb_draw_funcs_set_middle (hb_draw_funcs_t *dfuncs,
+ void *user_data,
+ hb_destroy_func_t destroy)
+{
+ 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;
+ }
+
+ return true;
+
+fail:
+ if (destroy)
+ (destroy) (user_data);
+ return false;
+}
+
#define HB_DRAW_FUNC_IMPLEMENT(name) \
\
void \
@@ -88,43 +138,24 @@ hb_draw_funcs_set_##name##_func (hb_draw_funcs_t *dfuncs, \
void *user_data, \
hb_destroy_func_t destroy) \
{ \
- if (hb_object_is_immutable (dfuncs)) \
- return; \
+ if (!_hb_draw_funcs_set_preamble (dfuncs, !func, &user_data, &destroy))\
+ return; \
\
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 (!_hb_draw_funcs_set_middle (dfuncs, user_data, destroy)) \
+ return; \
\
- if (func) { \
+ if (func) \
dfuncs->func.name = func; \
- if (dfuncs->user_data) \
- dfuncs->user_data->name = user_data; \
- if (dfuncs->destroy) \
- dfuncs->destroy->name = destroy; \
- } else { \
+ 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); \
+ \
+ if (dfuncs->user_data) \
+ dfuncs->user_data->name = user_data; \
+ if (dfuncs->destroy) \
+ dfuncs->destroy->name = destroy; \
}
HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS
diff --git a/thirdparty/harfbuzz/src/hb-face.cc b/thirdparty/harfbuzz/src/hb-face.cc
index e7deb31dd8..8b4b635c7a 100644
--- a/thirdparty/harfbuzz/src/hb-face.cc
+++ b/thirdparty/harfbuzz/src/hb-face.cc
@@ -288,6 +288,7 @@ hb_face_destroy (hb_face_t *face)
{
if (!hb_object_destroy (face)) return;
+#ifndef HB_NO_SHAPER
for (hb_face_t::plan_node_t *node = face->shape_plans; node; )
{
hb_face_t::plan_node_t *next = node->next;
@@ -295,6 +296,7 @@ hb_face_destroy (hb_face_t *face)
hb_free (node);
node = next;
}
+#endif
face->data.fini ();
face->table.fini ();
@@ -636,7 +638,7 @@ hb_face_collect_variation_unicodes (hb_face_t *face,
struct face_table_info_t
{
hb_blob_t* data;
- unsigned order;
+ signed order;
};
struct hb_face_builder_data_t
@@ -784,16 +786,16 @@ hb_face_builder_create ()
hb_bool_t
hb_face_builder_add_table (hb_face_t *face, hb_tag_t tag, hb_blob_t *blob)
{
- if (tag == HB_MAP_VALUE_INVALID)
+ if (unlikely (face->destroy != (hb_destroy_func_t) _hb_face_builder_data_destroy))
return false;
- if (unlikely (face->destroy != (hb_destroy_func_t) _hb_face_builder_data_destroy))
+ if (tag == HB_MAP_VALUE_INVALID)
return false;
hb_face_builder_data_t *data = (hb_face_builder_data_t *) face->user_data;
hb_blob_t* previous = data->tables.get (tag).data;
- if (!data->tables.set (tag, face_table_info_t {hb_blob_reference (blob), 0}))
+ if (!data->tables.set (tag, face_table_info_t {hb_blob_reference (blob), -1}))
{
hb_blob_destroy (blob);
return false;
@@ -819,13 +821,16 @@ void
hb_face_builder_sort_tables (hb_face_t *face,
const hb_tag_t *tags)
{
+ if (unlikely (face->destroy != (hb_destroy_func_t) _hb_face_builder_data_destroy))
+ return;
+
hb_face_builder_data_t *data = (hb_face_builder_data_t *) face->user_data;
// Sort all unspecified tables after any specified tables.
for (auto& info : data->tables.values_ref())
- info.order = -1;
+ info.order = (unsigned) -1;
- unsigned order = 0;
+ signed order = 0;
for (const hb_tag_t* tag = tags;
*tag;
tag++)
diff --git a/thirdparty/harfbuzz/src/hb-face.hh b/thirdparty/harfbuzz/src/hb-face.hh
index 12e10d01e0..1bf0606e52 100644
--- a/thirdparty/harfbuzz/src/hb-face.hh
+++ b/thirdparty/harfbuzz/src/hb-face.hh
@@ -65,7 +65,9 @@ struct hb_face_t
hb_shape_plan_t *shape_plan;
plan_node_t *next;
};
+#ifndef HB_NO_SHAPER
hb_atomic_ptr_t<plan_node_t> shape_plans;
+#endif
hb_blob_t *reference_table (hb_tag_t tag) const
{
diff --git a/thirdparty/harfbuzz/src/hb-fallback-shape.cc b/thirdparty/harfbuzz/src/hb-fallback-shape.cc
index f8524ecc8e..c54ad8764b 100644
--- a/thirdparty/harfbuzz/src/hb-fallback-shape.cc
+++ b/thirdparty/harfbuzz/src/hb-fallback-shape.cc
@@ -75,16 +75,6 @@ _hb_fallback_shape (hb_shape_plan_t *shape_plan HB_UNUSED,
const hb_feature_t *features HB_UNUSED,
unsigned int num_features HB_UNUSED)
{
- /* TODO
- *
- * - Apply fallback kern.
- * - Handle Variation Selectors?
- * - Apply normalization?
- *
- * This will make the fallback shaper into a dumb "TrueType"
- * shaper which many people unfortunately still request.
- */
-
hb_codepoint_t space;
bool has_space = (bool) font->get_nominal_glyph (' ', &space);
diff --git a/thirdparty/harfbuzz/src/hb-font.cc b/thirdparty/harfbuzz/src/hb-font.cc
index 856bbdda32..0ce3e2608a 100644
--- a/thirdparty/harfbuzz/src/hb-font.cc
+++ b/thirdparty/harfbuzz/src/hb-font.cc
@@ -71,7 +71,7 @@ hb_font_get_font_h_extents_nil (hb_font_t *font HB_UNUSED,
hb_font_extents_t *extents,
void *user_data HB_UNUSED)
{
- memset (extents, 0, sizeof (*extents));
+ hb_memset (extents, 0, sizeof (*extents));
return false;
}
@@ -96,7 +96,7 @@ hb_font_get_font_v_extents_nil (hb_font_t *font HB_UNUSED,
hb_font_extents_t *extents,
void *user_data HB_UNUSED)
{
- memset (extents, 0, sizeof (*extents));
+ hb_memset (extents, 0, sizeof (*extents));
return false;
}
@@ -409,7 +409,7 @@ hb_font_get_glyph_extents_nil (hb_font_t *font HB_UNUSED,
hb_glyph_extents_t *extents,
void *user_data HB_UNUSED)
{
- memset (extents, 0, sizeof (*extents));
+ hb_memset (extents, 0, sizeof (*extents));
return false;
}
@@ -518,6 +518,7 @@ typedef struct hb_font_get_glyph_shape_default_adaptor_t {
void *draw_data;
float x_scale;
float y_scale;
+ float slant;
} hb_font_get_glyph_shape_default_adaptor_t;
static void
@@ -530,9 +531,10 @@ hb_draw_move_to_default (hb_draw_funcs_t *dfuncs HB_UNUSED,
hb_font_get_glyph_shape_default_adaptor_t *adaptor = (hb_font_get_glyph_shape_default_adaptor_t *) draw_data;
float x_scale = adaptor->x_scale;
float y_scale = adaptor->y_scale;
+ float slant = adaptor->slant;
adaptor->draw_funcs->emit_move_to (adaptor->draw_data, *st,
- x_scale * to_x, y_scale * to_y);
+ x_scale * to_x + slant * to_y, y_scale * to_y);
}
static void
@@ -544,12 +546,13 @@ hb_draw_line_to_default (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data,
hb_font_get_glyph_shape_default_adaptor_t *adaptor = (hb_font_get_glyph_shape_default_adaptor_t *) draw_data;
float x_scale = adaptor->x_scale;
float y_scale = adaptor->y_scale;
+ float slant = adaptor->slant;
- st->current_x *= x_scale;
- st->current_y *= y_scale;
+ st->current_x = st->current_x * x_scale + st->current_y * slant;
+ st->current_y = st->current_y * y_scale;
adaptor->draw_funcs->emit_line_to (adaptor->draw_data, *st,
- x_scale * to_x, y_scale * to_y);
+ x_scale * to_x + slant * to_y, y_scale * to_y);
}
static void
@@ -562,13 +565,14 @@ hb_draw_quadratic_to_default (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data
hb_font_get_glyph_shape_default_adaptor_t *adaptor = (hb_font_get_glyph_shape_default_adaptor_t *) draw_data;
float x_scale = adaptor->x_scale;
float y_scale = adaptor->y_scale;
+ float slant = adaptor->slant;
- st->current_x *= x_scale;
- st->current_y *= y_scale;
+ st->current_x = st->current_x * x_scale + st->current_y * slant;
+ st->current_y = st->current_y * y_scale;
adaptor->draw_funcs->emit_quadratic_to (adaptor->draw_data, *st,
- x_scale * control_x, y_scale * control_y,
- x_scale * to_x, y_scale * to_y);
+ x_scale * control_x + slant * control_y, y_scale * control_y,
+ x_scale * to_x + slant * to_y, y_scale * to_y);
}
static void
@@ -582,14 +586,15 @@ hb_draw_cubic_to_default (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data,
hb_font_get_glyph_shape_default_adaptor_t *adaptor = (hb_font_get_glyph_shape_default_adaptor_t *) draw_data;
float x_scale = adaptor->x_scale;
float y_scale = adaptor->y_scale;
+ float slant = adaptor->slant;
- st->current_x *= x_scale;
- st->current_y *= y_scale;
+ st->current_x = st->current_x * x_scale + st->current_y * slant;
+ st->current_y = st->current_y * y_scale;
adaptor->draw_funcs->emit_cubic_to (adaptor->draw_data, *st,
- x_scale * control1_x, y_scale * control1_y,
- x_scale * control2_x, y_scale * control2_y,
- x_scale * to_x, y_scale * to_y);
+ x_scale * control1_x + slant * control1_y, y_scale * control1_y,
+ x_scale * control2_x + slant * control2_y, y_scale * control2_y,
+ x_scale * to_x + slant * to_y, y_scale * to_y);
}
static void
@@ -623,8 +628,10 @@ hb_font_get_glyph_shape_default (hb_font_t *font,
hb_font_get_glyph_shape_default_adaptor_t adaptor = {
draw_funcs,
draw_data,
- (float) font->x_scale / (float) font->parent->x_scale,
- (float) font->y_scale / (float) font->parent->y_scale
+ font->parent->x_scale ? (float) font->x_scale / (float) font->parent->x_scale : 0.f,
+ font->parent->y_scale ? (float) font->y_scale / (float) font->parent->y_scale : 0.f,
+ font->parent->y_scale ? (font->slant - font->parent->slant) *
+ (float) font->x_scale / (float) font->parent->y_scale : 0.f
};
font->parent->get_glyph_shape (glyph,
@@ -822,6 +829,56 @@ hb_font_funcs_is_immutable (hb_font_funcs_t *ffuncs)
}
+static bool
+_hb_font_funcs_set_preamble (hb_font_funcs_t *ffuncs,
+ bool func_is_null,
+ void **user_data,
+ hb_destroy_func_t *destroy)
+{
+ if (hb_object_is_immutable (ffuncs))
+ {
+ if (*destroy)
+ (*destroy) (*user_data);
+ return false;
+ }
+
+ if (func_is_null)
+ {
+ if (*destroy)
+ (*destroy) (*user_data);
+ *destroy = nullptr;
+ *user_data = nullptr;
+ }
+
+ return true;
+}
+
+static bool
+_hb_font_funcs_set_middle (hb_font_funcs_t *ffuncs,
+ void *user_data,
+ hb_destroy_func_t destroy)
+{
+ 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;
+ }
+
+ return true;
+
+fail:
+ if (destroy)
+ (destroy) (user_data);
+ return false;
+}
+
#define HB_FONT_FUNC_IMPLEMENT(name) \
\
void \
@@ -830,51 +887,24 @@ hb_font_funcs_set_##name##_func (hb_font_funcs_t *ffuncs, \
void *user_data, \
hb_destroy_func_t destroy) \
{ \
- if (hb_object_is_immutable (ffuncs)) \
- goto fail; \
- \
- if (!func) \
- { \
- if (destroy) \
- destroy (user_data); \
- destroy = nullptr; \
- user_data = nullptr; \
- } \
+ if (!_hb_font_funcs_set_preamble (ffuncs, !func, &user_data, &destroy))\
+ return; \
\
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 (!_hb_font_funcs_set_middle (ffuncs, user_data, destroy)) \
+ return; \
\
- if (func) { \
+ if (func) \
ffuncs->get.f.name = func; \
- if (ffuncs->user_data) \
- ffuncs->user_data->name = user_data; \
- if (ffuncs->destroy) \
- ffuncs->destroy->name = destroy; \
- } else { \
+ else \
ffuncs->get.f.name = hb_font_get_##name##_default; \
- if (ffuncs->user_data) \
- ffuncs->user_data->name = nullptr; \
- if (ffuncs->destroy) \
- ffuncs->destroy->name = nullptr; \
- } \
- return; \
- \
-fail: \
- if (destroy) \
- destroy (user_data); \
+ \
+ if (ffuncs->user_data) \
+ ffuncs->user_data->name = user_data; \
+ if (ffuncs->destroy) \
+ ffuncs->destroy->name = destroy; \
}
HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
@@ -1323,7 +1353,7 @@ hb_font_get_glyph_from_name (hb_font_t *font,
* @draw_data: User data to pass to draw callbacks
*
* Fetches the glyph shape that corresponds to a glyph in the specified @font.
- * The shape is returned by way of calls to the callsbacks of the @dfuncs
+ * The shape is returned by way of calls to the callbacks of the @dfuncs
* objects, with @draw_data passed to them.
*
* Since: 4.0.0
@@ -1780,8 +1810,8 @@ hb_font_create_sub_font (hb_font_t *parent)
float *design_coords = (float *) hb_calloc (num_coords, sizeof (parent->design_coords[0]));
if (likely (coords && design_coords))
{
- memcpy (coords, parent->coords, num_coords * sizeof (parent->coords[0]));
- memcpy (design_coords, parent->design_coords, num_coords * sizeof (parent->design_coords[0]));
+ hb_memcpy (coords, parent->coords, num_coords * sizeof (parent->coords[0]));
+ hb_memcpy (design_coords, parent->design_coords, num_coords * sizeof (parent->design_coords[0]));
_hb_font_adopt_var_coords (font, coords, design_coords, num_coords);
}
else
@@ -2443,7 +2473,7 @@ hb_font_set_var_coords_design (hb_font_t *font,
}
if (coords_length)
- memcpy (design_coords, coords, coords_length * sizeof (font->design_coords[0]));
+ hb_memcpy (design_coords, coords, coords_length * sizeof (font->design_coords[0]));
hb_ot_var_normalize_coords (font->face, coords_length, coords, normalized);
_hb_font_adopt_var_coords (font, normalized, design_coords, coords_length);
@@ -2519,8 +2549,8 @@ hb_font_set_var_coords_normalized (hb_font_t *font,
if (coords_length)
{
- memcpy (copy, coords, coords_length * sizeof (coords[0]));
- memcpy (unmapped, coords, coords_length * sizeof (coords[0]));
+ hb_memcpy (copy, coords, coords_length * sizeof (coords[0]));
+ hb_memcpy (unmapped, coords, coords_length * sizeof (coords[0]));
}
/* Best effort design coords simulation */
diff --git a/thirdparty/harfbuzz/src/hb-font.hh b/thirdparty/harfbuzz/src/hb-font.hh
index bb402e23eb..6942d99c70 100644
--- a/thirdparty/harfbuzz/src/hb-font.hh
+++ b/thirdparty/harfbuzz/src/hb-font.hh
@@ -206,14 +206,14 @@ struct hb_font_t
hb_bool_t get_font_h_extents (hb_font_extents_t *extents)
{
- memset (extents, 0, sizeof (*extents));
+ hb_memset (extents, 0, sizeof (*extents));
return klass->get.f.font_h_extents (this, user_data,
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));
+ hb_memset (extents, 0, sizeof (*extents));
return klass->get.f.font_v_extents (this, user_data,
extents,
!klass->user_data ? nullptr : klass->user_data->font_v_extents);
@@ -342,7 +342,7 @@ struct hb_font_t
hb_bool_t get_glyph_extents (hb_codepoint_t glyph,
hb_glyph_extents_t *extents)
{
- memset (extents, 0, sizeof (*extents));
+ hb_memset (extents, 0, sizeof (*extents));
return klass->get.f.glyph_extents (this, user_data,
glyph,
extents,
diff --git a/thirdparty/harfbuzz/src/hb-ft.cc b/thirdparty/harfbuzz/src/hb-ft.cc
index bcc1dd080f..3892dedc13 100644
--- a/thirdparty/harfbuzz/src/hb-ft.cc
+++ b/thirdparty/harfbuzz/src/hb-ft.cc
@@ -89,7 +89,7 @@ struct hb_ft_font_t
bool unref; /* Whether to destroy ft_face when done. */
bool transform; /* Whether to apply FT_Face's transform. */
- mutable hb_mutex_t lock;
+ mutable hb_mutex_t lock; /* Protects members below. */
FT_Face ft_face;
mutable unsigned cached_serial;
mutable hb_ft_advance_cache_t advance_cache;
@@ -732,16 +732,18 @@ hb_ft_get_font_h_extents (hb_font_t *font HB_UNUSED,
static int
_hb_ft_move_to (const FT_Vector *to,
- hb_draw_session_t *drawing)
+ void *arg)
{
+ hb_draw_session_t *drawing = (hb_draw_session_t *) arg;
drawing->move_to (to->x, to->y);
return FT_Err_Ok;
}
static int
_hb_ft_line_to (const FT_Vector *to,
- hb_draw_session_t *drawing)
+ void *arg)
{
+ hb_draw_session_t *drawing = (hb_draw_session_t *) arg;
drawing->line_to (to->x, to->y);
return FT_Err_Ok;
}
@@ -749,8 +751,9 @@ _hb_ft_line_to (const FT_Vector *to,
static int
_hb_ft_conic_to (const FT_Vector *control,
const FT_Vector *to,
- hb_draw_session_t *drawing)
+ void *arg)
{
+ hb_draw_session_t *drawing = (hb_draw_session_t *) arg;
drawing->quadratic_to (control->x, control->y,
to->x, to->y);
return FT_Err_Ok;
@@ -760,8 +763,9 @@ static int
_hb_ft_cubic_to (const FT_Vector *control1,
const FT_Vector *control2,
const FT_Vector *to,
- hb_draw_session_t *drawing)
+ void *arg)
{
+ hb_draw_session_t *drawing = (hb_draw_session_t *) arg;
drawing->cubic_to (control1->x, control1->y,
control2->x, control2->y,
to->x, to->y);
@@ -787,10 +791,10 @@ hb_ft_get_glyph_shape (hb_font_t *font HB_UNUSED,
return;
const FT_Outline_Funcs outline_funcs = {
- (FT_Outline_MoveToFunc) _hb_ft_move_to,
- (FT_Outline_LineToFunc) _hb_ft_line_to,
- (FT_Outline_ConicToFunc) _hb_ft_conic_to,
- (FT_Outline_CubicToFunc) _hb_ft_cubic_to,
+ _hb_ft_move_to,
+ _hb_ft_line_to,
+ _hb_ft_conic_to,
+ _hb_ft_cubic_to,
0, /* shift */
0, /* delta */
};
@@ -975,8 +979,9 @@ hb_ft_face_create_referenced (FT_Face ft_face)
}
static void
-hb_ft_face_finalize (FT_Face ft_face)
+hb_ft_face_finalize (void *arg)
{
+ FT_Face ft_face = (FT_Face) arg;
hb_face_destroy ((hb_face_t *) ft_face->generic.data);
}
@@ -1008,7 +1013,7 @@ hb_ft_face_create_cached (FT_Face ft_face)
ft_face->generic.finalizer (ft_face);
ft_face->generic.data = hb_ft_face_create (ft_face, nullptr);
- ft_face->generic.finalizer = (FT_Generic_Finalizer) hb_ft_face_finalize;
+ ft_face->generic.finalizer = hb_ft_face_finalize;
}
return hb_face_reference ((hb_face_t *) ft_face->generic.data);
@@ -1217,8 +1222,9 @@ get_ft_library ()
}
static void
-_release_blob (FT_Face ft_face)
+_release_blob (void *arg)
{
+ FT_Face ft_face = (FT_Face) arg;
hb_blob_destroy ((hb_blob_t *) ft_face->generic.data);
}
@@ -1271,7 +1277,7 @@ hb_ft_font_set_funcs (hb_font_t *font)
ft_face->generic.data = blob;
- ft_face->generic.finalizer = (FT_Generic_Finalizer) _release_blob;
+ ft_face->generic.finalizer = _release_blob;
_hb_ft_font_set_funcs (font, ft_face, true);
hb_ft_font_set_load_flags (font, FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING);
diff --git a/thirdparty/harfbuzz/src/hb-glib.cc b/thirdparty/harfbuzz/src/hb-glib.cc
index 8ddc7ebad8..1da81696e7 100644
--- a/thirdparty/harfbuzz/src/hb-glib.cc
+++ b/thirdparty/harfbuzz/src/hb-glib.cc
@@ -129,32 +129,9 @@ hb_glib_unicode_compose (hb_unicode_funcs_t *ufuncs HB_UNUSED,
{
#if GLIB_CHECK_VERSION(2,29,12)
return g_unichar_compose (a, b, ab);
+#else
+ return false;
#endif
-
- /* We don't ifdef-out the fallback code such that compiler always
- * sees it and makes sure it's compilable. */
-
- gchar utf8[12];
- gchar *normalized;
- int len;
- hb_bool_t ret;
-
- len = g_unichar_to_utf8 (a, utf8);
- len += g_unichar_to_utf8 (b, utf8 + len);
- normalized = g_utf8_normalize (utf8, len, G_NORMALIZE_NFC);
- len = g_utf8_strlen (normalized, -1);
- if (unlikely (!len))
- return false;
-
- if (len == 1) {
- *ab = g_utf8_get_char (normalized);
- ret = true;
- } else {
- ret = false;
- }
-
- g_free (normalized);
- return ret;
}
static hb_bool_t
@@ -166,55 +143,9 @@ hb_glib_unicode_decompose (hb_unicode_funcs_t *ufuncs HB_UNUSED,
{
#if GLIB_CHECK_VERSION(2,29,12)
return g_unichar_decompose (ab, a, b);
+#else
+ return false;
#endif
-
- /* We don't ifdef-out the fallback code such that compiler always
- * sees it and makes sure it's compilable. */
-
- gchar utf8[6];
- gchar *normalized;
- int len;
- hb_bool_t ret;
-
- len = g_unichar_to_utf8 (ab, utf8);
- normalized = g_utf8_normalize (utf8, len, G_NORMALIZE_NFD);
- len = g_utf8_strlen (normalized, -1);
- if (unlikely (!len))
- return false;
-
- if (len == 1) {
- *a = g_utf8_get_char (normalized);
- *b = 0;
- ret = *a != ab;
- } else if (len == 2) {
- *a = g_utf8_get_char (normalized);
- *b = g_utf8_get_char (g_utf8_next_char (normalized));
- /* Here's the ugly part: if ab decomposes to a single character and
- * that character decomposes again, we have to detect that and undo
- * the second part :-(. */
- gchar *recomposed = g_utf8_normalize (normalized, -1, G_NORMALIZE_NFC);
- hb_codepoint_t c = g_utf8_get_char (recomposed);
- if (c != ab && c != *a) {
- *a = c;
- *b = 0;
- }
- g_free (recomposed);
- ret = true;
- } else {
- /* If decomposed to more than two characters, take the last one,
- * and recompose the rest to get the first component. */
- gchar *end = g_utf8_offset_to_pointer (normalized, len - 1);
- gchar *recomposed;
- *b = g_utf8_get_char (end);
- recomposed = g_utf8_normalize (normalized, end - normalized, G_NORMALIZE_NFC);
- /* We expect that recomposed has exactly one character now. */
- *a = g_utf8_get_char (recomposed);
- g_free (recomposed);
- ret = true;
- }
-
- g_free (normalized);
- return ret;
}
diff --git a/thirdparty/harfbuzz/src/hb-graphite2.cc b/thirdparty/harfbuzz/src/hb-graphite2.cc
index 4d0e687c75..9e068f8d84 100644
--- a/thirdparty/harfbuzz/src/hb-graphite2.cc
+++ b/thirdparty/harfbuzz/src/hb-graphite2.cc
@@ -318,7 +318,7 @@ _hb_graphite2_shape (hb_shape_plan_t *shape_plan HB_UNUSED,
#undef ALLOCATE_ARRAY
- memset (clusters, 0, sizeof (clusters[0]) * buffer->len);
+ hb_memset (clusters, 0, sizeof (clusters[0]) * buffer->len);
hb_codepoint_t *pg = gids;
clusters[0].cluster = buffer->info[0].cluster;
diff --git a/thirdparty/harfbuzz/src/hb-iter.hh b/thirdparty/harfbuzz/src/hb-iter.hh
index 1a3ab43de0..b57f37b132 100644
--- a/thirdparty/harfbuzz/src/hb-iter.hh
+++ b/thirdparty/harfbuzz/src/hb-iter.hh
@@ -73,8 +73,10 @@ struct hb_iter_t
/* Operators. */
iter_t iter () const { return *thiz(); }
iter_t operator + () const { return *thiz(); }
- iter_t begin () const { return *thiz(); }
- iter_t end () const { return thiz()->__end__ (); }
+ iter_t _begin () const { return *thiz(); }
+ iter_t begin () const { return _begin (); }
+ iter_t _end () const { return thiz()->__end__ (); }
+ iter_t end () const { return _end (); }
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
@@ -118,7 +120,9 @@ struct hb_iter_t
#define HB_ITER_USING(Name) \
using item_t = typename Name::item_t; \
+ using Name::_begin; \
using Name::begin; \
+ using Name::_end; \
using Name::end; \
using Name::get_item_size; \
using Name::is_iterator; \
@@ -377,7 +381,7 @@ struct hb_map_iter_t :
void __forward__ (unsigned n) { it += n; }
void __prev__ () { --it; }
void __rewind__ (unsigned n) { it -= n; }
- hb_map_iter_t __end__ () const { return hb_map_iter_t (it.end (), f); }
+ hb_map_iter_t __end__ () const { return hb_map_iter_t (it._end (), f); }
bool operator != (const hb_map_iter_t& o) const
{ return it != o.it; }
@@ -440,7 +444,7 @@ struct hb_filter_iter_t :
bool __more__ () const { return bool (it); }
void __next__ () { do ++it; while (it && !hb_has (p.get (), hb_get (f.get (), *it))); }
void __prev__ () { do --it; while (it && !hb_has (p.get (), hb_get (f.get (), *it))); }
- hb_filter_iter_t __end__ () const { return hb_filter_iter_t (it.end (), p, f); }
+ hb_filter_iter_t __end__ () const { return hb_filter_iter_t (it._end (), p, f); }
bool operator != (const hb_filter_iter_t& o) const
{ return it != o.it; }
@@ -553,7 +557,7 @@ struct hb_zip_iter_t :
void __forward__ (unsigned n) { a += n; b += n; }
void __prev__ () { --a; --b; }
void __rewind__ (unsigned n) { a -= n; b -= n; }
- hb_zip_iter_t __end__ () const { return hb_zip_iter_t (a.end (), b.end ()); }
+ hb_zip_iter_t __end__ () const { return hb_zip_iter_t (a._end (), b._end ()); }
/* Note, we should stop if ANY of the iters reaches end. As such two compare
* unequal if both items are unequal, NOT if either is unequal. */
bool operator != (const hb_zip_iter_t& o) const
@@ -637,7 +641,7 @@ struct hb_concat_iter_t :
}
}
- hb_concat_iter_t __end__ () const { return hb_concat_iter_t (a.end (), b.end ()); }
+ hb_concat_iter_t __end__ () const { return hb_concat_iter_t (a._end (), b._end ()); }
bool operator != (const hb_concat_iter_t& o) const
{
return a != o.a
diff --git a/thirdparty/harfbuzz/src/hb-machinery.hh b/thirdparty/harfbuzz/src/hb-machinery.hh
index 2571f22e15..b555739cfb 100644
--- a/thirdparty/harfbuzz/src/hb-machinery.hh
+++ b/thirdparty/harfbuzz/src/hb-machinery.hh
@@ -136,6 +136,13 @@ static inline Type& StructAfter(TObject &X)
/*
* Lazy loaders.
+ *
+ * The lazy-loaders are thread-safe pointer-like objects that create their
+ * instead on-demand. They also support access to a "data" object that is
+ * necessary for creating their instance. The data object, if specified,
+ * is accessed via pointer math, located at a location before the position
+ * of the loader itself. This avoids having to store a pointer to data
+ * for every lazy-loader. Multiple lazy-loaders can access the same data.
*/
template <typename Data, unsigned int WheresData>
@@ -228,7 +235,8 @@ struct hb_lazy_loader_t : hb_data_wrapper_t<Data, WheresData>
bool cmpexch (Stored *current, Stored *value) const
{
- /* This *must* be called when there are no other threads accessing. */
+ /* This function can only be safely called directly if no
+ * other thread is accessing. */
return this->instance.cmpexch (current, value);
}
@@ -261,7 +269,7 @@ struct hb_lazy_loader_t : hb_data_wrapper_t<Data, WheresData>
hb_free (p);
}
-// private:
+ private:
/* Must only have one pointer. */
hb_atomic_ptr_t<Stored *> instance;
};
@@ -283,7 +291,7 @@ struct hb_table_lazy_loader_t : hb_lazy_loader_t<T,
{
auto c = hb_sanitize_context_t ();
if (core)
- c.set_num_glyphs (0); // So we don't recurse ad infinitum...
+ c.set_num_glyphs (0); // So we don't recurse ad infinitum, or doesn't need num_glyphs
return c.reference_table<T> (face);
}
static void destroy (hb_blob_t *p) { hb_blob_destroy (p); }
diff --git a/thirdparty/harfbuzz/src/hb-map.hh b/thirdparty/harfbuzz/src/hb-map.hh
index 8302e3f8c7..bfb1b3f768 100644
--- a/thirdparty/harfbuzz/src/hb-map.hh
+++ b/thirdparty/harfbuzz/src/hb-map.hh
@@ -43,9 +43,9 @@ struct hb_hashmap_t
hb_hashmap_t () { init (); }
~hb_hashmap_t () { fini (); }
- hb_hashmap_t (const hb_hashmap_t& o) : hb_hashmap_t () { resize (population); hb_copy (o, *this); }
+ hb_hashmap_t (const hb_hashmap_t& o) : hb_hashmap_t () { resize (o.population); hb_copy (o, *this); }
hb_hashmap_t (hb_hashmap_t&& o) : hb_hashmap_t () { hb_swap (*this, o); }
- hb_hashmap_t& operator= (const hb_hashmap_t& o) { resize (population); hb_copy (o, *this); return *this; }
+ hb_hashmap_t& operator= (const hb_hashmap_t& o) { reset (); resize (o.population); hb_copy (o, *this); return *this; }
hb_hashmap_t& operator= (hb_hashmap_t&& o) { hb_swap (*this, o); return *this; }
hb_hashmap_t (std::initializer_list<hb_pair_t<K, V>> lst) : hb_hashmap_t ()
@@ -71,6 +71,11 @@ struct hb_hashmap_t
uint32_t is_tombstone_ : 1;
V value;
+ item_t () : key (),
+ hash (0),
+ is_used_ (false), is_tombstone_ (false),
+ value () {}
+
bool is_used () const { return is_used_; }
void set_used (bool is_used) { is_used_ = is_used; }
bool is_tombstone () const { return is_tombstone_; }
@@ -88,17 +93,8 @@ struct hb_hashmap_t
return minus_1;
};
- void clear ()
- {
- new (std::addressof (key)) K ();
- new (std::addressof (value)) V ();
- 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 operator == (const K &o) const { return hb_deref (key) == hb_deref (o); }
+ bool operator == (const item_t &o) const { return *this == o.key; }
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); }
@@ -107,8 +103,8 @@ struct hb_hashmap_t
};
hb_object_header_t header;
- bool successful; /* Allocations successful */
- unsigned int population; /* Not including tombstones. */
+ unsigned int successful : 1; /* Allocations successful */
+ unsigned int population : 31; /* Not including tombstones. */
unsigned int occupancy; /* Including tombstones. */
unsigned int mask;
unsigned int prime;
@@ -118,7 +114,10 @@ struct hb_hashmap_t
{
if (unlikely (!a.successful || !b.successful))
return;
- hb_swap (a.population, b.population);
+ unsigned tmp = a.population;
+ a.population = b.population;
+ b.population = tmp;
+ //hb_swap (a.population, b.population);
hb_swap (a.occupancy, b.occupancy);
hb_swap (a.mask, b.mask);
hb_swap (a.prime, b.prime);
@@ -160,7 +159,9 @@ struct hb_hashmap_t
{
if (unlikely (!successful)) return false;
- unsigned int power = hb_bit_storage (hb_max (population, new_population) * 2 + 8);
+ if (new_population != 0 && (new_population + new_population / 2) < mask) return true;
+
+ unsigned int power = hb_bit_storage (hb_max ((unsigned) population, new_population) * 2 + 8);
unsigned int new_size = 1u << power;
item_t *new_items = (item_t *) hb_malloc ((size_t) new_size * sizeof (item_t));
if (unlikely (!new_items))
@@ -169,9 +170,9 @@ struct hb_hashmap_t
return false;
}
for (auto &_ : hb_iter (new_items, new_size))
- _.clear ();
+ new (&_) item_t ();
- unsigned int old_size = mask + 1;
+ unsigned int old_size = size ();
item_t *old_items = items;
/* Switch to new, empty, array. */
@@ -181,47 +182,82 @@ struct hb_hashmap_t
items = new_items;
/* Insert back old items. */
- if (old_items)
- for (unsigned int i = 0; i < old_size; i++)
+ for (unsigned int i = 0; i < old_size; i++)
+ {
+ if (old_items[i].is_real ())
{
- if (old_items[i].is_real ())
- {
- set_with_hash (old_items[i].key,
- old_items[i].hash,
- std::move (old_items[i].value));
- }
- old_items[i].~item_t ();
+ set_with_hash (std::move (old_items[i].key),
+ old_items[i].hash,
+ std::move (old_items[i].value));
}
+ old_items[i].~item_t ();
+ }
hb_free (old_items);
return true;
}
+ template <typename KK, typename VV>
+ bool set_with_hash (KK&& key, uint32_t hash, VV&& value, bool is_delete=false)
+ {
+ if (unlikely (!successful)) return false;
+ if (unlikely ((occupancy + occupancy / 2) >= mask && !resize ())) return false;
+ item_t &item = item_for_hash (key, hash);
+
+ if (is_delete && !(item == key))
+ return true; /* Trying to delete non-existent key. */
+
+ if (item.is_used ())
+ {
+ occupancy--;
+ if (!item.is_tombstone ())
+ population--;
+ }
+
+ item.key = std::forward<KK> (key);
+ item.value = std::forward<VV> (value);
+ item.hash = hash;
+ item.set_used (true);
+ item.set_tombstone (is_delete);
+
+ occupancy++;
+ if (!is_delete)
+ population++;
+
+ return true;
+ }
+
+ template <typename VV>
+ bool set (const K &key, VV&& value) { return set_with_hash (key, hb_hash (key), std::forward<VV> (value)); }
template <typename VV>
- bool set (K key, VV&& value) { return set_with_hash (key, hb_hash (key), std::forward<VV> (value)); }
+ bool set (K &&key, VV&& value) { return set_with_hash (std::move (key), hb_hash (key), std::forward<VV> (value)); }
- const V& get (K key) const
+ const V& get_with_hash (const K &key, uint32_t hash) const
+ {
+ if (unlikely (!items)) return item_t::default_value ();
+ auto &item = item_for_hash (key, hash);
+ return item.is_real () && item == key ? item.value : item_t::default_value ();
+ }
+ const V& get (const K &key) const
{
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 : item_t::default_value ();
+ return get_with_hash (key, hb_hash (key));
}
- void del (K key) { set_with_hash (key, hb_hash (key), item_t::default_value (), true); }
+ void del (const K &key) { set_with_hash (key, hb_hash (key), item_t::default_value (), true); }
/* Has interface. */
- typedef const V& value_t;
- value_t operator [] (K k) const { return get (k); }
+ const V& operator [] (K k) const { return get (k); }
template <typename VV=V>
bool has (K key, VV **vp = nullptr) const
{
if (unlikely (!items))
return false;
- unsigned int i = bucket_for (key);
- if (items[i].is_real () && items[i] == key)
+ auto &item = item_for_hash (key, hb_hash (key));
+ if (item.is_real () && item == key)
{
- if (vp) *vp = &items[i].value;
+ if (vp) *vp = std::addressof (item.value);
return true;
}
else
@@ -230,13 +266,18 @@ struct hb_hashmap_t
/* Projection. */
V operator () (K k) const { return get (k); }
+ unsigned size () const { return mask ? mask + 1 : 0; }
+
void clear ()
{
if (unlikely (!successful)) return;
- if (items)
- for (auto &_ : hb_iter (items, mask + 1))
- _.clear ();
+ for (auto &_ : hb_iter (items, size ()))
+ {
+ /* Reconstruct items. */
+ _.~item_t ();
+ new (&_) item_t ();
+ }
population = occupancy = 0;
}
@@ -246,11 +287,10 @@ struct hb_hashmap_t
uint32_t hash () const
{
- uint32_t h = 0;
- for (const auto &item : + hb_array (items, mask ? mask + 1 : 0)
- | hb_filter (&item_t::is_real))
- h ^= item.total_hash ();
- return h;
+ return
+ + iter_items ()
+ | hb_reduce ([] (uint32_t h, const item_t &_) { return h ^ _.total_hash (); }, (uint32_t) 0u)
+ ;
}
bool is_equal (const hb_hashmap_t &other) const
@@ -258,7 +298,7 @@ struct hb_hashmap_t
if (population != other.population) return false;
for (auto pair : iter ())
- if (get (pair.first) != pair.second)
+ if (other.get (pair.first) != pair.second)
return false;
return true;
@@ -271,87 +311,54 @@ struct hb_hashmap_t
/*
* Iterator
*/
- auto iter () const HB_AUTO_RETURN
+
+ auto iter_items () const HB_AUTO_RETURN
(
- + hb_array (items, mask ? mask + 1 : 0)
+ + hb_iter (items, size ())
| 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)
+ + iter_items ()
| hb_map (&item_t::get_pair_ref)
)
- auto keys () const HB_AUTO_RETURN
+ auto iter () const HB_AUTO_RETURN
(
- + hb_array (items, mask ? mask + 1 : 0)
- | hb_filter (&item_t::is_real)
- | hb_map (&item_t::key)
- | hb_map (hb_ridentity)
+ + iter_items ()
+ | hb_map (&item_t::get_pair)
)
auto keys_ref () const HB_AUTO_RETURN
(
- + hb_array (items, mask ? mask + 1 : 0)
- | hb_filter (&item_t::is_real)
+ + iter_items ()
| hb_map (&item_t::key)
)
- auto values () const HB_AUTO_RETURN
+ auto keys () const HB_AUTO_RETURN
(
- + hb_array (items, mask ? mask + 1 : 0)
- | hb_filter (&item_t::is_real)
- | hb_map (&item_t::value)
+ + keys_ref ()
| hb_map (hb_ridentity)
)
auto values_ref () const HB_AUTO_RETURN
(
- + hb_array (items, mask ? mask + 1 : 0)
- | hb_filter (&item_t::is_real)
+ + iter_items ()
| hb_map (&item_t::value)
)
+ auto values () const HB_AUTO_RETURN
+ (
+ + values_ref ()
+ | hb_map (hb_ridentity)
+ )
/* Sink interface. */
hb_hashmap_t& operator << (const hb_pair_t<K, V>& v)
{ set (v.first, v.second); return *this; }
-
- protected:
-
- template <typename VV>
- bool set_with_hash (K key, uint32_t hash, VV&& value, bool is_delete=false)
- {
- if (unlikely (!successful)) return false;
- if (unlikely ((occupancy + occupancy / 2) >= mask && !resize ())) return false;
- unsigned int i = bucket_for_hash (key, hash);
-
- if (is_delete && items[i].key != key)
- return true; /* Trying to delete non-existent key. */
-
- if (items[i].is_used ())
- {
- occupancy--;
- if (!items[i].is_tombstone ())
- population--;
- }
-
- items[i].key = key;
- items[i].value = std::forward<VV> (value);
- items[i].hash = hash;
- items[i].set_used (true);
- items[i].set_tombstone (is_delete);
-
- occupancy++;
- if (!is_delete)
- population++;
-
- return true;
- }
-
- unsigned int bucket_for (const K &key) const
- {
- return bucket_for_hash (key, hb_hash (key));
- }
-
- unsigned int bucket_for_hash (const K &key, uint32_t hash) const
+ hb_hashmap_t& operator << (const hb_pair_t<K, V&&>& v)
+ { set (v.first, std::move (v.second)); return *this; }
+ hb_hashmap_t& operator << (const hb_pair_t<K&&, V>& v)
+ { set (std::move (v.first), v.second); return *this; }
+ hb_hashmap_t& operator << (const hb_pair_t<K&&, V&&>& v)
+ { set (std::move (v.first), std::move (v.second)); return *this; }
+
+ item_t& item_for_hash (const K &key, uint32_t hash) const
{
hash &= 0x3FFFFFFF; // We only store lower 30bit of hash
unsigned int i = hash % prime;
@@ -360,12 +367,12 @@ struct hb_hashmap_t
while (items[i].is_used ())
{
if (items[i].hash == hash && items[i] == key)
- return i;
+ return items[i];
if (tombstone == (unsigned) -1 && items[i].is_tombstone ())
tombstone = i;
i = (i + ++step) & mask;
}
- return tombstone == (unsigned) -1 ? i : tombstone;
+ return items[tombstone == (unsigned) -1 ? i : tombstone];
}
static unsigned int prime_for (unsigned int shift)
diff --git a/thirdparty/harfbuzz/src/hb-meta.hh b/thirdparty/harfbuzz/src/hb-meta.hh
index 52a6791e31..31aa7fa6f1 100644
--- a/thirdparty/harfbuzz/src/hb-meta.hh
+++ b/thirdparty/harfbuzz/src/hb-meta.hh
@@ -112,8 +112,7 @@ template <typename T> auto _hb_try_add_pointer (hb_priority<1>) -> hb_type_ident
template <typename T> using hb_add_pointer = decltype (_hb_try_add_pointer<T> (hb_prioritize));
-/* TODO Add feature-parity to std::decay. */
-template <typename T> using hb_decay = hb_remove_const<hb_remove_reference<T>>;
+template <typename T> using hb_decay = typename std::decay<T>::type;
#define hb_is_convertible(From,To) std::is_convertible<From, To>::value
diff --git a/thirdparty/harfbuzz/src/hb-ms-feature-ranges.hh b/thirdparty/harfbuzz/src/hb-ms-feature-ranges.hh
index d40fdeaa82..46a20c91ea 100644
--- a/thirdparty/harfbuzz/src/hb-ms-feature-ranges.hh
+++ b/thirdparty/harfbuzz/src/hb-ms-feature-ranges.hh
@@ -166,7 +166,7 @@ hb_ms_setup_features (const hb_feature_t *features,
{
auto *feature = active_features.lsearch (event->feature);
if (feature)
- active_features.remove (feature - active_features.arrayZ);
+ active_features.remove_ordered (feature - active_features.arrayZ);
}
}
diff --git a/thirdparty/harfbuzz/src/hb-multimap.hh b/thirdparty/harfbuzz/src/hb-multimap.hh
new file mode 100644
index 0000000000..f0f95917aa
--- /dev/null
+++ b/thirdparty/harfbuzz/src/hb-multimap.hh
@@ -0,0 +1,92 @@
+/*
+ * 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_MULTIMAP_HH
+#define HB_MULTIMAP_HH
+
+#include "hb.hh"
+#include "hb-map.hh"
+#include "hb-vector.hh"
+
+
+/*
+ * hb_multimap_t
+ */
+
+struct hb_multimap_t
+{
+ void add (hb_codepoint_t k, hb_codepoint_t v)
+ {
+ hb_codepoint_t *i;
+ if (multiples_indices.has (k, &i))
+ {
+ multiples_values[*i].push (v);
+ return;
+ }
+
+ hb_codepoint_t *old_v;
+ if (singulars.has (k, &old_v))
+ {
+ hb_codepoint_t old = *old_v;
+ singulars.del (k);
+
+ multiples_indices.set (k, multiples_values.length);
+ auto *vec = multiples_values.push ();
+
+ vec->push (old);
+ vec->push (v);
+
+ return;
+ }
+
+ singulars.set (k, v);
+ }
+
+ hb_array_t<const hb_codepoint_t> get (hb_codepoint_t k) const
+ {
+ hb_codepoint_t *v;
+ if (singulars.has (k, &v))
+ return hb_array (v, 1);
+
+ hb_codepoint_t *i;
+ if (multiples_indices.has (k, &i))
+ return multiples_values[*i].as_array ();
+
+ return hb_array_t<hb_codepoint_t> ();
+ }
+
+ bool in_error () const
+ {
+ return singulars.in_error () || multiples_indices.in_error () || multiples_values.in_error ();
+ }
+
+ protected:
+ hb_map_t singulars;
+ hb_map_t multiples_indices;
+ hb_vector_t<hb_vector_t<hb_codepoint_t>> multiples_values;
+};
+
+
+
+#endif /* HB_MULTIMAP_HH */
diff --git a/thirdparty/harfbuzz/src/hb-mutex.hh b/thirdparty/harfbuzz/src/hb-mutex.hh
index 6914b22450..053f9ddcc4 100644
--- a/thirdparty/harfbuzz/src/hb-mutex.hh
+++ b/thirdparty/harfbuzz/src/hb-mutex.hh
@@ -108,10 +108,11 @@ struct hb_mutex_t
struct hb_lock_t
{
- hb_lock_t (hb_mutex_t &mutex_) : mutex (mutex_) { mutex.lock (); }
- ~hb_lock_t () { mutex.unlock (); }
+ hb_lock_t (hb_mutex_t &mutex_) : mutex (&mutex_) { mutex->lock (); }
+ hb_lock_t (hb_mutex_t *mutex_) : mutex (mutex_) { if (mutex) mutex->lock (); }
+ ~hb_lock_t () { if (mutex) mutex->unlock (); }
private:
- hb_mutex_t &mutex;
+ hb_mutex_t *mutex;
};
diff --git a/thirdparty/harfbuzz/src/hb-number-parser.hh b/thirdparty/harfbuzz/src/hb-number-parser.hh
index 1a9dbba6dd..ec68c3a728 100644
--- a/thirdparty/harfbuzz/src/hb-number-parser.hh
+++ b/thirdparty/harfbuzz/src/hb-number-parser.hh
@@ -31,7 +31,7 @@
#include "hb.hh"
-#line 35 "hb-number-parser.hh"
+#line 32 "hb-number-parser.hh"
static const unsigned char _double_parser_trans_keys[] = {
0u, 0u, 43u, 57u, 46u, 57u, 48u, 57u, 43u, 57u, 48u, 57u, 48u, 101u, 48u, 57u,
46u, 101u, 0
@@ -135,12 +135,12 @@ strtod_rl (const char *p, const char **end_ptr /* IN/OUT */)
int cs;
-#line 139 "hb-number-parser.hh"
+#line 132 "hb-number-parser.hh"
{
cs = double_parser_start;
}
-#line 144 "hb-number-parser.hh"
+#line 135 "hb-number-parser.hh"
{
int _slen;
int _trans;
@@ -198,7 +198,7 @@ _resume:
exp_overflow = true;
}
break;
-#line 202 "hb-number-parser.hh"
+#line 187 "hb-number-parser.hh"
}
_again:
diff --git a/thirdparty/harfbuzz/src/hb-object.hh b/thirdparty/harfbuzz/src/hb-object.hh
index 9876c2923c..a23c25f7ca 100644
--- a/thirdparty/harfbuzz/src/hb-object.hh
+++ b/thirdparty/harfbuzz/src/hb-object.hh
@@ -80,7 +80,7 @@ struct hb_lockable_set_t
if (item)
{
item_t old = *item;
- *item = items[items.length - 1];
+ *item = std::move (items.tail ());
items.pop ();
l.unlock ();
old.fini ();
@@ -123,7 +123,7 @@ struct hb_lockable_set_t
l.lock ();
while (items.length)
{
- item_t old = items[items.length - 1];
+ item_t old = items.tail ();
items.pop ();
l.unlock ();
old.fini ();
diff --git a/thirdparty/harfbuzz/src/hb-open-file.hh b/thirdparty/harfbuzz/src/hb-open-file.hh
index 6eee5827c1..13570a46e0 100644
--- a/thirdparty/harfbuzz/src/hb-open-file.hh
+++ b/thirdparty/harfbuzz/src/hb-open-file.hh
@@ -90,7 +90,7 @@ typedef struct OpenTypeOffsetTable
{
if (table_count)
{
- + tables.sub_array (start_offset, table_count)
+ + tables.as_array ().sub_array (start_offset, table_count)
| hb_map (&TableRecord::tag)
| hb_sink (hb_array (table_tags, *table_count))
;
@@ -158,7 +158,7 @@ typedef struct OpenTypeOffsetTable
return_trace (false);
if (likely (len))
- memcpy (start, blob->data, len);
+ hb_memcpy (start, blob->data, len);
/* 4-byte alignment. */
c->align (4);
diff --git a/thirdparty/harfbuzz/src/hb-open-type.hh b/thirdparty/harfbuzz/src/hb-open-type.hh
index e66f451820..290799127a 100644
--- a/thirdparty/harfbuzz/src/hb-open-type.hh
+++ b/thirdparty/harfbuzz/src/hb-open-type.hh
@@ -148,7 +148,7 @@ struct HBFixed : Type
static_assert (Type::static_size * 8 > fraction_bits, "");
HBFixed& operator = (typename Type::type i ) { Type::operator= (i); return *this; }
- float to_float () const { return ((int32_t) Type::v) / shift; }
+ float to_float (float offset = 0) const { return ((int32_t) Type::v + offset) / shift; }
void set_float (float f) { Type::v = roundf (f * shift); }
public:
DEFINE_SIZE_STATIC (Type::static_size);
@@ -157,6 +157,9 @@ struct HBFixed : Type
/* 16-bit signed fixed number with the low 14 bits of fraction (2.14). */
using F2DOT14 = HBFixed<HBINT16, 14>;
+/* 16-bit signed fixed number with the low 12 bits of fraction (4.12). */
+using F4DOT12 = HBFixed<HBINT16, 12>;
+
/* 32-bit signed fixed-point number (16.16). */
using F16DOT16 = HBFixed<HBINT32, 16>;
@@ -209,6 +212,12 @@ typedef Index NameID;
struct VarIdx : HBUINT32 {
static constexpr unsigned NO_VARIATION = 0xFFFFFFFFu;
+ static_assert (NO_VARIATION == HB_OT_LAYOUT_NO_VARIATIONS_INDEX, "");
+ static uint32_t add (uint32_t i, unsigned short v)
+ {
+ if (i == NO_VARIATION) return i;
+ return i + v;
+ }
VarIdx& operator = (uint32_t i) { HBUINT32::operator= (i); return *this; }
};
DECLARE_NULL_NAMESPACE_BYTES (OT, VarIdx);
@@ -493,10 +502,10 @@ struct UnsizedArrayOf
void qsort (unsigned int len, unsigned int start = 0, unsigned int end = (unsigned int) -1)
{ as_array (len).qsort (start, end); }
- bool serialize (hb_serialize_context_t *c, unsigned int items_len)
+ bool serialize (hb_serialize_context_t *c, unsigned int items_len, bool clear = true)
{
TRACE_SERIALIZE (this);
- if (unlikely (!c->extend (this, items_len))) return_trace (false);
+ if (unlikely (!c->extend_size (this, get_size (items_len), clear))) return_trace (false);
return_trace (true);
}
template <typename Iterator,
@@ -504,8 +513,8 @@ struct UnsizedArrayOf
bool serialize (hb_serialize_context_t *c, Iterator items)
{
TRACE_SERIALIZE (this);
- unsigned count = items.len ();
- if (unlikely (!serialize (c, count))) return_trace (false);
+ unsigned count = hb_len (items);
+ if (unlikely (!serialize (c, count, false))) return_trace (false);
/* TODO Umm. Just exhaust the iterator instead? Being extra
* cautious right now.. */
for (unsigned i = 0; i < count; i++, ++items)
@@ -646,14 +655,9 @@ struct ArrayOf
operator iter_t () const { return iter (); }
operator writer_t () { return writer (); }
- hb_array_t<const Type> sub_array (unsigned int start_offset, unsigned int count) const
- { return as_array ().sub_array (start_offset, count); }
- hb_array_t<const Type> sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */) const
- { return as_array ().sub_array (start_offset, count); }
- hb_array_t<Type> sub_array (unsigned int start_offset, unsigned int count)
- { return as_array ().sub_array (start_offset, count); }
- hb_array_t<Type> sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */)
- { return as_array ().sub_array (start_offset, count); }
+ /* Faster range-based for loop. */
+ const Type *begin () const { return arrayZ; }
+ const Type *end () const { return arrayZ + len; }
template <typename T>
Type &lsearch (const T &x, Type &not_found = Crap (Type))
@@ -667,15 +671,15 @@ struct ArrayOf
unsigned int to_store = (unsigned int) -1) const
{ return as_array ().lfind (x, i, not_found, to_store); }
- void qsort (unsigned int start = 0, unsigned int end = (unsigned int) -1)
- { as_array ().qsort (start, end); }
+ void qsort ()
+ { as_array ().qsort (); }
- HB_NODISCARD bool serialize (hb_serialize_context_t *c, unsigned items_len)
+ HB_NODISCARD bool serialize (hb_serialize_context_t *c, unsigned items_len, bool clear = true)
{
TRACE_SERIALIZE (this);
if (unlikely (!c->extend_min (this))) return_trace (false);
c->check_assign (len, items_len, HB_SERIALIZE_ERROR_ARRAY_OVERFLOW);
- if (unlikely (!c->extend (this))) return_trace (false);
+ if (unlikely (!c->extend_size (this, get_size (), clear))) return_trace (false);
return_trace (true);
}
template <typename Iterator,
@@ -683,8 +687,8 @@ struct ArrayOf
HB_NODISCARD bool serialize (hb_serialize_context_t *c, Iterator items)
{
TRACE_SERIALIZE (this);
- unsigned count = items.len ();
- if (unlikely (!serialize (c, count))) return_trace (false);
+ unsigned count = hb_len (items);
+ if (unlikely (!serialize (c, count, false))) return_trace (false);
/* TODO Umm. Just exhaust the iterator instead? Being extra
* cautious right now.. */
for (unsigned i = 0; i < count; i++, ++items)
@@ -828,21 +832,25 @@ struct HeadlessArrayOf
operator iter_t () const { return iter (); }
operator writer_t () { return writer (); }
- bool serialize (hb_serialize_context_t *c, unsigned int items_len)
+ /* Faster range-based for loop. */
+ const Type *begin () const { return arrayZ; }
+ const Type *end () const { return arrayZ + get_length (); }
+
+ HB_NODISCARD bool serialize (hb_serialize_context_t *c, unsigned int items_len, bool clear = true)
{
TRACE_SERIALIZE (this);
if (unlikely (!c->extend_min (this))) return_trace (false);
c->check_assign (lenP1, items_len + 1, HB_SERIALIZE_ERROR_ARRAY_OVERFLOW);
- if (unlikely (!c->extend (this))) return_trace (false);
+ if (unlikely (!c->extend_size (this, get_size (), clear))) return_trace (false);
return_trace (true);
}
template <typename Iterator,
hb_requires (hb_is_source_of (Iterator, Type))>
- bool serialize (hb_serialize_context_t *c, Iterator items)
+ HB_NODISCARD bool serialize (hb_serialize_context_t *c, Iterator items)
{
TRACE_SERIALIZE (this);
- unsigned count = items.len ();
- if (unlikely (!serialize (c, count))) return_trace (false);
+ unsigned count = hb_len (items);
+ if (unlikely (!serialize (c, count, false))) return_trace (false);
/* TODO Umm. Just exhaust the iterator instead? Being extra
* cautious right now.. */
for (unsigned i = 0; i < count; i++, ++items)
@@ -944,14 +952,9 @@ struct SortedArrayOf : ArrayOf<Type, LenType>
operator iter_t () const { return iter (); }
operator writer_t () { return writer (); }
- hb_sorted_array_t<const Type> sub_array (unsigned int start_offset, unsigned int count) const
- { return as_array ().sub_array (start_offset, count); }
- hb_sorted_array_t<const Type> sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */) const
- { return as_array ().sub_array (start_offset, count); }
- hb_sorted_array_t<Type> sub_array (unsigned int start_offset, unsigned int count)
- { return as_array ().sub_array (start_offset, count); }
- hb_sorted_array_t<Type> sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */)
- { return as_array ().sub_array (start_offset, count); }
+ /* Faster range-based for loop. */
+ const Type *begin () const { return this->arrayZ; }
+ const Type *end () const { return this->arrayZ + this->len; }
bool serialize (hb_serialize_context_t *c, unsigned int items_len)
{
diff --git a/thirdparty/harfbuzz/src/hb-ot-cff-common.hh b/thirdparty/harfbuzz/src/hb-ot-cff-common.hh
index ae3b83a256..f22824fc69 100644
--- a/thirdparty/harfbuzz/src/hb-ot-cff-common.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-cff-common.hh
@@ -66,95 +66,25 @@ struct CFFIndex
{
TRACE_SERIALIZE (this);
unsigned int size = get_size ();
- CFFIndex *out = c->allocate_size<CFFIndex> (size);
+ CFFIndex *out = c->allocate_size<CFFIndex> (size, false);
if (likely (out))
- memcpy (out, this, size);
+ hb_memcpy (out, this, size);
return_trace (out);
}
+ template <typename Iterable,
+ hb_requires (hb_is_iterable (Iterable))>
bool serialize (hb_serialize_context_t *c,
- unsigned int offSize_,
- const byte_str_array_t &byteArray)
+ const Iterable &iterable)
{
TRACE_SERIALIZE (this);
-
- if (byteArray.length == 0)
- {
- COUNT *dest = c->allocate_min<COUNT> ();
- if (unlikely (!dest)) return_trace (false);
- *dest = 0;
- return_trace (true);
- }
-
- /* serialize CFFIndex header */
- if (unlikely (!c->extend_min (this))) return_trace (false);
- this->count = byteArray.length;
- this->offSize = offSize_;
- if (unlikely (!c->allocate_size<HBUINT8> (offSize_ * (byteArray.length + 1))))
- return_trace (false);
-
- /* serialize indices */
- unsigned int offset = 1;
- unsigned int i = 0;
- for (; i < byteArray.length; i++)
- {
- set_offset_at (i, offset);
- offset += byteArray[i].get_size ();
- }
- set_offset_at (i, offset);
-
- /* serialize data */
- for (unsigned int i = 0; i < byteArray.length; i++)
- {
- const hb_ubytes_t &bs = byteArray[i];
- unsigned char *dest = c->allocate_size<unsigned char> (bs.length);
- if (unlikely (!dest)) return_trace (false);
- memcpy (dest, &bs[0], bs.length);
- }
-
- return_trace (true);
- }
-
- bool serialize (hb_serialize_context_t *c,
- unsigned int offSize_,
- const str_buff_vec_t &buffArray)
- {
- byte_str_array_t byteArray;
- byteArray.init ();
- byteArray.resize (buffArray.length);
- for (unsigned int i = 0; i < byteArray.length; i++)
- byteArray[i] = hb_ubytes_t (buffArray[i].arrayZ, buffArray[i].length);
- bool result = this->serialize (c, offSize_, byteArray);
- byteArray.fini ();
- return result;
- }
-
- template <typename Iterator,
- hb_requires (hb_is_iterator (Iterator))>
- bool serialize (hb_serialize_context_t *c,
- Iterator it)
- {
- TRACE_SERIALIZE (this);
- serialize_header(c, + it | hb_map ([] (const hb_ubytes_t &_) { return _.length; }));
+ auto it = hb_iter (iterable);
+ serialize_header(c, + it | hb_map (hb_iter) | hb_map (hb_len));
for (const auto &_ : +it)
- _.copy (c);
+ hb_iter (_).copy (c);
return_trace (true);
}
- bool serialize (hb_serialize_context_t *c,
- const byte_str_array_t &byteArray)
- { return serialize (c, + hb_iter (byteArray)); }
-
- bool serialize (hb_serialize_context_t *c,
- const str_buff_vec_t &buffArray)
- {
- auto it =
- + hb_iter (buffArray)
- | hb_map ([] (const str_buff_t &_) { return hb_ubytes_t (_.arrayZ, _.length); })
- ;
- return serialize (c, it);
- }
-
template <typename Iterator,
hb_requires (hb_is_iterator (Iterator))>
bool serialize_header (hb_serialize_context_t *c,
@@ -171,7 +101,7 @@ struct CFFIndex
if (!this->count) return_trace (true);
if (unlikely (!c->extend (this->offSize))) return_trace (false);
this->offSize = off_size;
- if (unlikely (!c->allocate_size<HBUINT8> (off_size * (this->count + 1))))
+ if (unlikely (!c->allocate_size<HBUINT8> (off_size * (this->count + 1), false)))
return_trace (false);
/* serialize indices */
@@ -179,14 +109,27 @@ struct CFFIndex
unsigned int i = 0;
for (unsigned _ : +it)
{
- CFFIndex<COUNT>::set_offset_at (i++, offset);
+ set_offset_at (i++, offset);
offset += _;
}
- CFFIndex<COUNT>::set_offset_at (i, offset);
+ set_offset_at (i, offset);
return_trace (true);
}
+ template <typename Iterable,
+ hb_requires (hb_is_iterable (Iterable))>
+ static unsigned total_size (const Iterable &iterable)
+ {
+ auto it = + hb_iter (iterable) | hb_map (hb_iter) | hb_map (hb_len);
+ if (!it) return 0;
+
+ unsigned total = + it | hb_reduce (hb_add, 0);
+ unsigned off_size = (hb_bit_storage (total + 1) + 7) / 8;
+
+ return min_size + HBUINT8::static_size + (hb_len (it) + 1) * off_size + total;
+ }
+
void set_offset_at (unsigned int index, unsigned int offset)
{
assert (index <= count);
@@ -207,10 +150,14 @@ struct CFFIndex
unsigned int size = offSize;
const HBUINT8 *p = offsets + size * index;
- unsigned int offset = 0;
- for (; size; size--)
- offset = (offset << 8) + *p++;
- return offset;
+ switch (size)
+ {
+ case 1: return * (HBUINT8 *) p;
+ case 2: return * (HBUINT16 *) p;
+ case 3: return * (HBUINT24 *) p;
+ case 4: return * (HBUINT32 *) p;
+ default: return 0;
+ }
}
unsigned int length_at (unsigned int index) const
@@ -229,6 +176,7 @@ struct CFFIndex
hb_ubytes_t operator [] (unsigned int index) const
{
if (unlikely (index >= count)) return hb_ubytes_t ();
+ _hb_compiler_memory_r_barrier ();
unsigned length = length_at (index);
if (unlikely (!length)) return hb_ubytes_t ();
return hb_ubytes_t (data_base () + offset_at (index) - 1, length);
@@ -280,7 +228,7 @@ struct CFFIndexOf : CFFIndex<COUNT>
if (unlikely (!c->extend_min (this))) return_trace (false);
this->count = dataArrayLen;
this->offSize = offSize_;
- if (unlikely (!c->allocate_size<HBUINT8> (offSize_ * (dataArrayLen + 1))))
+ if (unlikely (!c->allocate_size<HBUINT8> (offSize_ * (dataArrayLen + 1), false)))
return_trace (false);
/* serialize indices */
@@ -288,10 +236,10 @@ struct CFFIndexOf : CFFIndex<COUNT>
unsigned int i = 0;
for (; i < dataArrayLen; i++)
{
- CFFIndex<COUNT>::set_offset_at (i, offset);
+ this->set_offset_at (i, offset);
offset += dataSizeArray[i];
}
- CFFIndex<COUNT>::set_offset_at (i, offset);
+ this->set_offset_at (i, offset);
/* serialize data */
for (unsigned int i = 0; i < dataArrayLen; i++)
@@ -324,13 +272,12 @@ struct Dict : UnsizedByteStr
template <typename T, typename V>
static bool serialize_int_op (hb_serialize_context_t *c, op_code_t op, V value, op_code_t intOp)
{
- // XXX: not sure why but LLVM fails to compile the following 'unlikely' macro invocation
- if (/*unlikely*/ (!serialize_int<T, V> (c, intOp, value)))
+ if (unlikely ((!serialize_int<T, V> (c, intOp, value))))
return false;
TRACE_SERIALIZE (this);
/* serialize the opcode */
- HBUINT8 *p = c->allocate_size<HBUINT8> (OpCode_Size (op));
+ HBUINT8 *p = c->allocate_size<HBUINT8> (OpCode_Size (op), false);
if (unlikely (!p)) return_trace (false);
if (Is_OpCode_ESC (op))
{
@@ -415,9 +362,8 @@ struct FDSelect0 {
TRACE_SANITIZE (this);
if (unlikely (!(c->check_struct (this))))
return_trace (false);
- for (unsigned int i = 0; i < c->get_num_glyphs (); i++)
- if (unlikely (!fds[i].sanitize (c)))
- return_trace (false);
+ if (unlikely (!c->check_array (fds, c->get_num_glyphs ())))
+ return_trace (false);
return_trace (true);
}
@@ -471,14 +417,20 @@ struct FDSelect3_4
return_trace (true);
}
- hb_codepoint_t get_fd (hb_codepoint_t glyph) const
+ static int _cmp_range (const void *_key, const void *_item)
{
- unsigned int i;
- for (i = 1; i < nRanges (); i++)
- if (glyph < ranges[i].first)
- break;
+ hb_codepoint_t glyph = * (hb_codepoint_t *) _key;
+ FDSelect3_4_Range<GID_TYPE, FD_TYPE> *range = (FDSelect3_4_Range<GID_TYPE, FD_TYPE> *) _item;
- return (hb_codepoint_t) ranges[i - 1].fd;
+ if (glyph < range[0].first) return -1;
+ if (glyph < range[1].first) return 0;
+ return +1;
+ }
+
+ hb_codepoint_t get_fd (hb_codepoint_t glyph) const
+ {
+ auto *range = hb_bsearch (glyph, &ranges[0], nRanges () - 1, sizeof (ranges[0]), _cmp_range);
+ return range ? range->fd : ranges[nRanges () - 1].fd;
}
GID_TYPE &nRanges () { return ranges.len; }
@@ -501,9 +453,9 @@ struct FDSelect
{
TRACE_SERIALIZE (this);
unsigned int size = src.get_size (num_glyphs);
- FDSelect *dest = c->allocate_size<FDSelect> (size);
+ FDSelect *dest = c->allocate_size<FDSelect> (size, false);
if (unlikely (!dest)) return_trace (false);
- memcpy (dest, &src, size);
+ hb_memcpy (dest, &src, size);
return_trace (true);
}
diff --git a/thirdparty/harfbuzz/src/hb-ot-cff1-table.hh b/thirdparty/harfbuzz/src/hb-ot-cff1-table.hh
index 17b0296616..bb856c9ddb 100644
--- a/thirdparty/harfbuzz/src/hb-ot-cff1-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-cff1-table.hh
@@ -175,7 +175,7 @@ struct Encoding
unsigned int size = src.get_size ();
Encoding *dest = c->allocate_size<Encoding> (size);
if (unlikely (!dest)) return_trace (false);
- memcpy (dest, &src, size);
+ hb_memcpy (dest, &src, size);
return_trace (true);
}
@@ -471,7 +471,7 @@ struct Charset
unsigned int size = src.get_size (num_glyphs);
Charset *dest = c->allocate_size<Charset> (size);
if (unlikely (!dest)) return_trace (false);
- memcpy (dest, &src, size);
+ hb_memcpy (dest, &src, size);
return_trace (true);
}
@@ -617,7 +617,6 @@ struct CFF1StringIndex : CFF1Index
}
byte_str_array_t bytesArray;
- bytesArray.init ();
if (!bytesArray.resize (sidmap.get_population ()))
return_trace (false);
for (unsigned int i = 0; i < strings.count; i++)
@@ -628,7 +627,6 @@ struct CFF1StringIndex : CFF1Index
}
bool result = CFF1Index::serialize (c, bytesArray);
- bytesArray.fini ();
return_trace (result);
}
};
@@ -813,7 +811,7 @@ struct cff1_top_dict_opset_t : top_dict_opset_t<cff1_top_dict_val_t>
break;
default:
- env.last_offset = env.str_ref.offset;
+ env.last_offset = env.str_ref.get_offset ();
top_dict_opset_t<cff1_top_dict_val_t>::process_op (op, env, dictval);
/* Record this operand below if stack is empty, otherwise done */
if (!env.argStack.is_empty ()) return;
@@ -1295,10 +1293,10 @@ struct cff1
}
protected:
- hb_blob_t *blob = nullptr;
hb_sanitize_context_t sc;
public:
+ hb_blob_t *blob = nullptr;
const Encoding *encoding = nullptr;
const Charset *charset = nullptr;
const CFF1NameIndex *nameIndex = nullptr;
diff --git a/thirdparty/harfbuzz/src/hb-ot-cff2-table.hh b/thirdparty/harfbuzz/src/hb-ot-cff2-table.hh
index 746160dc8e..9081930bbe 100644
--- a/thirdparty/harfbuzz/src/hb-ot-cff2-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-cff2-table.hh
@@ -56,7 +56,7 @@ struct CFF2FDSelect
unsigned int size = src.get_size (num_glyphs);
CFF2FDSelect *dest = c->allocate_size<CFF2FDSelect> (size);
if (unlikely (!dest)) return_trace (false);
- memcpy (dest, &src, size);
+ hb_memcpy (dest, &src, size);
return_trace (true);
}
@@ -124,7 +124,7 @@ struct CFF2VariationStore
unsigned int size_ = varStore->get_size ();
CFF2VariationStore *dest = c->allocate_size<CFF2VariationStore> (size_);
if (unlikely (!dest)) return_trace (false);
- memcpy (dest, varStore, size_);
+ hb_memcpy (dest, varStore, size_);
return_trace (true);
}
@@ -483,13 +483,18 @@ struct cff2
blob = nullptr;
}
+ hb_map_t *create_glyph_to_sid_map () const
+ {
+ return nullptr;
+ }
+
bool is_valid () const { return blob; }
protected:
- hb_blob_t *blob = nullptr;
hb_sanitize_context_t sc;
public:
+ hb_blob_t *blob = nullptr;
cff2_top_dict_values_t topDict;
const CFF2Subrs *globalSubrs = nullptr;
const CFF2VariationStore *varStore = nullptr;
diff --git a/thirdparty/harfbuzz/src/hb-ot-cmap-table.hh b/thirdparty/harfbuzz/src/hb-ot-cmap-table.hh
index 09c9fe93f3..523196fa79 100644
--- a/thirdparty/harfbuzz/src/hb-ot-cmap-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-cmap-table.hh
@@ -909,7 +909,7 @@ struct DefaultUVS : SortedArray32Of<UnicodeValueRange>
hb_codepoint_t first = arrayZ[i].startUnicodeValue;
hb_codepoint_t last = hb_min ((hb_codepoint_t) (first + arrayZ[i].additionalCount),
(hb_codepoint_t) HB_UNICODE_MAX);
- out->add_range (first, hb_min (last, 0x10FFFFu));
+ out->add_range (first, last);
}
}
@@ -925,37 +925,75 @@ struct DefaultUVS : SortedArray32Of<UnicodeValueRange>
if (unlikely (!c->copy<HBUINT32> (len))) return nullptr;
unsigned init_len = c->length ();
- hb_codepoint_t lastCode = HB_MAP_VALUE_INVALID;
- int count = -1;
-
- for (const UnicodeValueRange& _ : as_array ())
+ if (this->len > unicodes->get_population () * hb_bit_storage ((unsigned) this->len))
{
- for (const unsigned addcnt : hb_range ((unsigned) _.additionalCount + 1))
+ hb_codepoint_t start = HB_SET_VALUE_INVALID;
+ hb_codepoint_t end = HB_SET_VALUE_INVALID;
+
+ for (hb_codepoint_t u = HB_SET_VALUE_INVALID;
+ unicodes->next (&u);)
{
- unsigned curEntry = (unsigned) _.startUnicodeValue + addcnt;
- if (!unicodes->has (curEntry)) continue;
- count += 1;
- if (lastCode == HB_MAP_VALUE_INVALID)
- lastCode = curEntry;
- else if (lastCode + count != curEntry)
+ if (!as_array ().bsearch (u))
+ continue;
+ if (start == HB_SET_VALUE_INVALID)
{
+ start = u;
+ end = start - 1;
+ }
+ if (end + 1 != u || end - start == 255)
+ {
UnicodeValueRange rec;
- rec.startUnicodeValue = lastCode;
- rec.additionalCount = count - 1;
+ rec.startUnicodeValue = start;
+ rec.additionalCount = end - start;
c->copy<UnicodeValueRange> (rec);
-
- lastCode = curEntry;
- count = 0;
+ start = u;
}
+ end = u;
+ }
+ if (start != HB_SET_VALUE_INVALID)
+ {
+ UnicodeValueRange rec;
+ rec.startUnicodeValue = start;
+ rec.additionalCount = end - start;
+ c->copy<UnicodeValueRange> (rec);
}
- }
- if (lastCode != HB_MAP_VALUE_INVALID)
+ }
+ else
{
- UnicodeValueRange rec;
- rec.startUnicodeValue = lastCode;
- rec.additionalCount = count;
- c->copy<UnicodeValueRange> (rec);
+ hb_codepoint_t lastCode = HB_SET_VALUE_INVALID;
+ int count = -1;
+
+ for (const UnicodeValueRange& _ : *this)
+ {
+ hb_codepoint_t curEntry = (hb_codepoint_t) (_.startUnicodeValue - 1);
+ hb_codepoint_t end = curEntry + _.additionalCount + 2;
+
+ for (; unicodes->next (&curEntry) && curEntry < end;)
+ {
+ count += 1;
+ if (lastCode == HB_SET_VALUE_INVALID)
+ lastCode = curEntry;
+ else if (lastCode + count != curEntry)
+ {
+ UnicodeValueRange rec;
+ rec.startUnicodeValue = lastCode;
+ rec.additionalCount = count - 1;
+ c->copy<UnicodeValueRange> (rec);
+
+ lastCode = curEntry;
+ count = 0;
+ }
+ }
+ }
+
+ if (lastCode != HB_MAP_VALUE_INVALID)
+ {
+ UnicodeValueRange rec;
+ rec.startUnicodeValue = lastCode;
+ rec.additionalCount = count;
+ c->copy<UnicodeValueRange> (rec);
+ }
}
if (c->length () - init_len == 0)
@@ -1474,32 +1512,80 @@ struct EncodingRecord
DEFINE_SIZE_STATIC (8);
};
+struct cmap;
+
struct SubtableUnicodesCache {
private:
- const void* base;
- hb_hashmap_t<intptr_t, hb::unique_ptr<hb_set_t>> cached_unicodes;
+ hb_blob_ptr_t<cmap> base_blob;
+ const char* base;
+ hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> cached_unicodes;
public:
+
+ static SubtableUnicodesCache* create (hb_blob_ptr_t<cmap> source_table)
+ {
+ SubtableUnicodesCache* cache =
+ (SubtableUnicodesCache*) hb_malloc (sizeof(SubtableUnicodesCache));
+ new (cache) SubtableUnicodesCache (source_table);
+ return cache;
+ }
+
+ static void destroy (void* value) {
+ if (!value) return;
+
+ SubtableUnicodesCache* cache = (SubtableUnicodesCache*) value;
+ cache->~SubtableUnicodesCache ();
+ hb_free (cache);
+ }
+
SubtableUnicodesCache(const void* cmap_base)
- : base(cmap_base), cached_unicodes() {}
+ : base_blob(),
+ base ((const char*) cmap_base),
+ cached_unicodes ()
+ {}
+
+ SubtableUnicodesCache(hb_blob_ptr_t<cmap> base_blob_)
+ : base_blob(base_blob_),
+ base ((const char *) base_blob.get()),
+ cached_unicodes ()
+ {}
+
+ ~SubtableUnicodesCache()
+ {
+ base_blob.destroy ();
+ }
+
+ bool same_base(const void* other) const
+ {
+ return other == (const void*) base;
+ }
- hb_set_t* set_for (const EncodingRecord* record)
+ const hb_set_t* set_for (const EncodingRecord* record,
+ SubtableUnicodesCache& mutable_cache) const
{
- if (!cached_unicodes.has ((intptr_t) record))
+ if (cached_unicodes.has ((unsigned) ((const char *) record - base)))
+ return cached_unicodes.get ((unsigned) ((const char *) record - base));
+
+ return mutable_cache.set_for (record);
+ }
+
+ const hb_set_t* set_for (const EncodingRecord* record)
+ {
+ if (!cached_unicodes.has ((unsigned) ((const char *) record - base)))
{
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})))
+ if (unlikely (!cached_unicodes.set ((unsigned) ((const char *) record - base), hb::unique_ptr<hb_set_t> {s})))
return hb_set_get_empty ();
return s;
}
- return cached_unicodes.get ((intptr_t) record);
+ return cached_unicodes.get ((unsigned) ((const char *) record - base));
}
};
@@ -1523,13 +1609,30 @@ struct cmap
{
static constexpr hb_tag_t tableTag = HB_OT_TAG_cmap;
+
+ static SubtableUnicodesCache* create_filled_cache(hb_blob_ptr_t<cmap> source_table) {
+ const cmap* cmap = source_table.get();
+ auto it =
+ + hb_iter (cmap->encodingRecord)
+ | hb_filter ([&](const EncodingRecord& _) {
+ return cmap::filter_encoding_records_for_subset (cmap, _);
+ })
+ ;
+
+ SubtableUnicodesCache* cache = SubtableUnicodesCache::create(source_table);
+ for (const EncodingRecord& _ : it)
+ cache->set_for(&_); // populate the cache for this encoding record.
+
+ return cache;
+ }
+
template<typename Iterator, typename EncodingRecIter,
hb_requires (hb_is_iterator (EncodingRecIter))>
bool serialize (hb_serialize_context_t *c,
Iterator it,
EncodingRecIter encodingrec_iter,
const void *base,
- const hb_subset_plan_t *plan,
+ hb_subset_plan_t *plan,
bool drop_format_4 = false)
{
if (unlikely (!c->extend_min ((*this)))) return false;
@@ -1538,7 +1641,14 @@ struct cmap
unsigned format4objidx = 0, format12objidx = 0, format14objidx = 0;
auto snap = c->snapshot ();
- SubtableUnicodesCache unicodes_cache (base);
+ SubtableUnicodesCache local_unicodes_cache (base);
+ const SubtableUnicodesCache* unicodes_cache = &local_unicodes_cache;
+
+ if (plan->accelerator &&
+ plan->accelerator->cmap_cache &&
+ plan->accelerator->cmap_cache->same_base (base))
+ unicodes_cache = plan->accelerator->cmap_cache;
+
for (const EncodingRecord& _ : encodingrec_iter)
{
if (c->in_error ())
@@ -1547,7 +1657,7 @@ struct cmap
unsigned format = (base+_.subtable).u.format;
if (format != 4 && format != 12 && format != 14) continue;
- hb_set_t* unicodes_set = unicodes_cache.set_for (&_);
+ const hb_set_t* unicodes_set = unicodes_cache->set_for (&_, local_unicodes_cache);
if (!drop_format_4 && format == 4)
{
@@ -1566,7 +1676,13 @@ struct cmap
else if (format == 12)
{
- if (_can_drop (_, *unicodes_set, base, unicodes_cache, + it | hb_map (hb_first), encodingrec_iter)) continue;
+ if (_can_drop (_,
+ *unicodes_set,
+ base,
+ *unicodes_cache,
+ local_unicodes_cache,
+ + it | hb_map (hb_first), encodingrec_iter))
+ continue;
c->copy (_, + it | hb_filter (*unicodes_set, hb_first), 12u, base, plan, &format12objidx);
}
else if (format == 14) c->copy (_, it, 14u, base, plan, &format14objidx);
@@ -1585,7 +1701,8 @@ struct cmap
bool _can_drop (const EncodingRecord& cmap12,
const hb_set_t& cmap12_unicodes,
const void* base,
- SubtableUnicodesCache& unicodes_cache,
+ const SubtableUnicodesCache& unicodes_cache,
+ SubtableUnicodesCache& local_unicodes_cache,
Iterator subset_unicodes,
EncodingRecordIterator encoding_records)
{
@@ -1616,7 +1733,7 @@ struct cmap
|| (base+_.subtable).get_language() != target_language)
continue;
- hb_set_t* sibling_unicodes = unicodes_cache.set_for (&_);
+ const hb_set_t* sibling_unicodes = unicodes_cache.set_for (&_, local_unicodes_cache);
auto cmap12 = + subset_unicodes | hb_filter (cmap12_unicodes);
auto sibling = + subset_unicodes | hb_filter (*sibling_unicodes);
@@ -1653,17 +1770,9 @@ struct cmap
auto encodingrec_iter =
+ hb_iter (encodingRecord)
- | hb_filter ([&] (const EncodingRecord& _)
- {
- if ((_.platformID == 0 && _.encodingID == 3) ||
- (_.platformID == 0 && _.encodingID == 4) ||
- (_.platformID == 3 && _.encodingID == 1) ||
- (_.platformID == 3 && _.encodingID == 10) ||
- (this + _.subtable).u.format == 14)
- return true;
-
- return false;
- })
+ | hb_filter ([&](const EncodingRecord& _) {
+ return cmap::filter_encoding_records_for_subset (this, _);
+ })
;
if (unlikely (!encodingrec_iter.len ())) return_trace (false);
@@ -1692,7 +1801,11 @@ struct cmap
{ return (_.second != HB_MAP_VALUE_INVALID); })
;
- return_trace (cmap_prime->serialize (c->serializer, it, encodingrec_iter, this, c->plan));
+ return_trace (cmap_prime->serialize (c->serializer,
+ it,
+ encodingrec_iter,
+ this,
+ c->plan));
}
const CmapSubtable *find_best_subtable (bool *symbol = nullptr) const
@@ -1928,6 +2041,19 @@ struct cmap
encodingRecord.sanitize (c, this));
}
+ private:
+
+ static bool filter_encoding_records_for_subset(const cmap* cmap,
+ const EncodingRecord& _)
+ {
+ return
+ (_.platformID == 0 && _.encodingID == 3) ||
+ (_.platformID == 0 && _.encodingID == 4) ||
+ (_.platformID == 3 && _.encodingID == 1) ||
+ (_.platformID == 3 && _.encodingID == 10) ||
+ (cmap + _.subtable).u.format == 14;
+ }
+
protected:
HBUINT16 version; /* Table version number (0). */
SortedArray16Of<EncodingRecord>
diff --git a/thirdparty/harfbuzz/src/hb-ot-color-cbdt-table.hh b/thirdparty/harfbuzz/src/hb-ot-color-cbdt-table.hh
index 23fa56c4f6..3246894d39 100644
--- a/thirdparty/harfbuzz/src/hb-ot-color-cbdt-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-color-cbdt-table.hh
@@ -67,7 +67,7 @@ _copy_data_to_cbdt (hb_vector_t<char> *cbdt_prime,
{
unsigned int new_len = cbdt_prime->length + length;
if (unlikely (!cbdt_prime->alloc (new_len))) return false;
- memcpy (cbdt_prime->arrayZ + cbdt_prime->length, data, length);
+ hb_memcpy (cbdt_prime->arrayZ + cbdt_prime->length, data, length);
cbdt_prime->length = new_len;
return true;
}
@@ -468,13 +468,13 @@ struct IndexSubtableRecord
if (unlikely (!c->serializer->check_success (records->resize (records->length + 1))))
return_trace (false);
- (*records)[records->length - 1].firstGlyphIndex = 1;
- (*records)[records->length - 1].lastGlyphIndex = 0;
+ records->tail ().firstGlyphIndex = 1;
+ records->tail ().lastGlyphIndex = 0;
bitmap_size_context->size += IndexSubtableRecord::min_size;
c->serializer->push ();
- if (unlikely (!add_new_subtable (c, bitmap_size_context, &((*records)[records->length - 1]), lookup, base, start)))
+ if (unlikely (!add_new_subtable (c, bitmap_size_context, &(records->tail ()), lookup, base, start)))
{
c->serializer->pop_discard ();
c->serializer->revert (snap);
diff --git a/thirdparty/harfbuzz/src/hb-ot-color-colr-table.hh b/thirdparty/harfbuzz/src/hb-ot-color-colr-table.hh
index 908bf550f0..1af9d30937 100644
--- a/thirdparty/harfbuzz/src/hb-ot-color-colr-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-color-colr-table.hh
@@ -39,11 +39,7 @@
#define HB_OT_TAG_COLR HB_TAG('C','O','L','R')
#ifndef HB_COLRV1_MAX_NESTING_LEVEL
-#define HB_COLRV1_MAX_NESTING_LEVEL 100
-#endif
-
-#ifndef COLRV1_ENABLE_SUBSETTING
-#define COLRV1_ENABLE_SUBSETTING 1
+#define HB_COLRV1_MAX_NESTING_LEVEL 16
#endif
namespace OT {
@@ -188,6 +184,7 @@ struct Variable
protected:
T value;
+ public:
VarIdx varIdxBase;
public:
DEFINE_SIZE_STATIC (4 + T::static_size);
@@ -196,6 +193,8 @@ struct Variable
template <typename T>
struct NoVariable
{
+ static constexpr uint32_t varIdxBase = VarIdx::NO_VARIATION;
+
NoVariable<T>* copy (hb_serialize_context_t *c) const
{
TRACE_SERIALIZE (this);
@@ -888,6 +887,11 @@ struct PaintComposite
DEFINE_SIZE_STATIC (8);
};
+struct ClipBoxData
+{
+ int xMin, yMin, xMax, yMax;
+};
+
struct ClipBoxFormat1
{
bool sanitize (hb_sanitize_context_t *c) const
@@ -896,6 +900,14 @@ struct ClipBoxFormat1
return_trace (c->check_struct (this));
}
+ void get_clip_box (ClipBoxData &clip_box, const VarStoreInstancer &instancer HB_UNUSED) const
+ {
+ clip_box.xMin = xMin;
+ clip_box.yMin = yMin;
+ clip_box.xMax = xMax;
+ clip_box.yMax = yMax;
+ }
+
public:
HBUINT8 format; /* format = 1(noVar) or 2(Var)*/
FWORD xMin;
@@ -906,7 +918,20 @@ struct ClipBoxFormat1
DEFINE_SIZE_STATIC (1 + 4 * FWORD::static_size);
};
-struct ClipBoxFormat2 : Variable<ClipBoxFormat1> {};
+struct ClipBoxFormat2 : Variable<ClipBoxFormat1>
+{
+ void get_clip_box (ClipBoxData &clip_box, const VarStoreInstancer &instancer) const
+ {
+ value.get_clip_box(clip_box, instancer);
+ if (instancer)
+ {
+ clip_box.xMin += _hb_roundf (instancer (varIdxBase, 0));
+ clip_box.yMin += _hb_roundf (instancer (varIdxBase, 1));
+ clip_box.xMax += _hb_roundf (instancer (varIdxBase, 2));
+ clip_box.yMax += _hb_roundf (instancer (varIdxBase, 3));
+ }
+ }
+};
struct ClipBox
{
@@ -932,6 +957,28 @@ struct ClipBox
}
}
+ bool get_extents (hb_glyph_extents_t *extents,
+ const VarStoreInstancer &instancer) const
+ {
+ ClipBoxData clip_box;
+ switch (u.format) {
+ case 1:
+ u.format1.get_clip_box (clip_box, instancer);
+ break;
+ case 2:
+ u.format2.get_clip_box (clip_box, instancer);
+ break;
+ default:
+ return false;
+ }
+
+ extents->x_bearing = clip_box.xMin;
+ extents->y_bearing = clip_box.yMax;
+ extents->width = clip_box.xMax - clip_box.xMin;
+ extents->height = clip_box.yMin - clip_box.yMax;
+ return true;
+ }
+
protected:
union {
HBUINT8 format; /* Format identifier */
@@ -942,6 +989,9 @@ struct ClipBox
struct ClipRecord
{
+ int cmp (hb_codepoint_t g) const
+ { return g < startGlyphID ? -1 : g <= endGlyphID ? 0 : +1; }
+
ClipRecord* copy (hb_serialize_context_t *c, const void *base) const
{
TRACE_SERIALIZE (this);
@@ -957,6 +1007,13 @@ struct ClipRecord
return_trace (c->check_struct (this) && clipBox.sanitize (c, base));
}
+ bool get_extents (hb_glyph_extents_t *extents,
+ const void *base,
+ const VarStoreInstancer &instancer) const
+ {
+ return (base+clipBox).get_extents (extents, instancer);
+ }
+
public:
HBUINT16 startGlyphID; // first gid clip applies to
HBUINT16 endGlyphID; // last gid clip applies to, inclusive
@@ -964,6 +1021,7 @@ struct ClipRecord
public:
DEFINE_SIZE_STATIC (7);
};
+DECLARE_NULL_NAMESPACE_BYTES (OT, ClipRecord);
struct ClipList
{
@@ -1052,11 +1110,26 @@ struct ClipList
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
+ // TODO Make a formatted struct!
return_trace (c->check_struct (this) && clips.sanitize (c, this));
}
+ bool
+ get_extents (hb_codepoint_t gid,
+ hb_glyph_extents_t *extents,
+ const VarStoreInstancer &instancer) const
+ {
+ auto *rec = clips.as_array ().bsearch (gid);
+ if (rec)
+ {
+ rec->get_extents (extents, this, instancer);
+ return true;
+ }
+ return false;
+ }
+
HBUINT8 format; // Set to 1.
- Array32Of<ClipRecord> clips; // Clip records, sorted by startGlyphID
+ SortedArray32Of<ClipRecord> clips; // Clip records, sorted by startGlyphID
public:
DEFINE_SIZE_ARRAY_SIZED (5, clips);
};
@@ -1359,7 +1432,7 @@ struct COLR
(this+baseGlyphsZ).sanitize (c, numBaseGlyphs) &&
(this+layersZ).sanitize (c, numLayers) &&
(version == 0 ||
- (COLRV1_ENABLE_SUBSETTING && version == 1 &&
+ (version == 1 &&
baseGlyphList.sanitize (c, this) &&
layerList.sanitize (c, this) &&
clipList.sanitize (c, this) &&
@@ -1516,6 +1589,30 @@ struct COLR
return_trace (true);
}
+ bool
+ get_extents (hb_font_t *font, hb_codepoint_t glyph, hb_glyph_extents_t *extents) const
+ {
+ if (version != 1)
+ return false;
+
+ VarStoreInstancer instancer (this+varStore,
+ this+varIdxMap,
+ hb_array (font->coords, font->num_coords));
+
+ if ((this+clipList).get_extents (glyph,
+ extents,
+ instancer))
+ {
+ extents->x_bearing = font->em_scale_x (extents->x_bearing);
+ extents->y_bearing = font->em_scale_x (extents->y_bearing);
+ extents->width = font->em_scale_x (extents->width);
+ extents->height = font->em_scale_x (extents->height);
+ return true;
+ }
+
+ return false;
+ }
+
protected:
HBUINT16 version; /* Table version number (starts at 0). */
HBUINT16 numBaseGlyphs; /* Number of Base Glyph Records. */
diff --git a/thirdparty/harfbuzz/src/hb-ot-face-table-list.hh b/thirdparty/harfbuzz/src/hb-ot-face-table-list.hh
index c05034b3bb..c9da36c1bb 100644
--- a/thirdparty/harfbuzz/src/hb-ot-face-table-list.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-face-table-list.hh
@@ -56,9 +56,9 @@ HB_OT_CORE_TABLE (OT, maxp)
#if !defined(HB_NO_FACE_COLLECT_UNICODES) || !defined(HB_NO_OT_FONT)
HB_OT_ACCELERATOR (OT, cmap)
#endif
-HB_OT_TABLE (OT, hhea)
+HB_OT_CORE_TABLE (OT, hhea)
HB_OT_ACCELERATOR (OT, hmtx)
-HB_OT_TABLE (OT, OS2)
+HB_OT_CORE_TABLE (OT, OS2)
#if !defined(HB_NO_OT_FONT_GLYPH_NAMES) || !defined(HB_NO_METRICS) || !defined(HB_NO_STYLE)
HB_OT_ACCELERATOR (OT, post)
#endif
@@ -66,7 +66,7 @@ HB_OT_ACCELERATOR (OT, post)
HB_OT_ACCELERATOR (OT, name)
#endif
#ifndef HB_NO_STYLE
-HB_OT_TABLE (OT, STAT)
+HB_OT_CORE_TABLE (OT, STAT)
#endif
#ifndef HB_NO_META
HB_OT_ACCELERATOR (OT, meta)
@@ -74,9 +74,9 @@ HB_OT_ACCELERATOR (OT, meta)
/* Vertical layout. */
#ifndef HB_NO_VERTICAL
-HB_OT_TABLE (OT, vhea)
+HB_OT_CORE_TABLE (OT, vhea)
HB_OT_ACCELERATOR (OT, vmtx)
-HB_OT_TABLE (OT, VORG)
+HB_OT_CORE_TABLE (OT, VORG)
#endif
/* TrueType outlines. */
@@ -91,15 +91,15 @@ HB_OT_ACCELERATOR (OT, cff2)
/* OpenType variations. */
#ifndef HB_NO_VAR
-HB_OT_TABLE (OT, fvar)
-HB_OT_TABLE (OT, avar)
+HB_OT_CORE_TABLE (OT, fvar)
+HB_OT_CORE_TABLE (OT, avar)
HB_OT_ACCELERATOR (OT, gvar)
-HB_OT_TABLE (OT, MVAR)
+HB_OT_CORE_TABLE (OT, MVAR)
#endif
/* Legacy kern. */
#ifndef HB_NO_OT_KERN
-HB_OT_TABLE (OT, kern)
+HB_OT_CORE_TABLE (OT, kern)
#endif
/* OpenType shaping. */
@@ -107,12 +107,12 @@ HB_OT_TABLE (OT, kern)
HB_OT_ACCELERATOR (OT, GDEF)
HB_OT_ACCELERATOR (OT, GSUB)
HB_OT_ACCELERATOR (OT, GPOS)
-//HB_OT_TABLE (OT, JSTF)
+//HB_OT_CORE_TABLE (OT, JSTF)
#endif
/* OpenType baseline. */
#ifndef HB_NO_BASE
-HB_OT_TABLE (OT, BASE)
+HB_OT_CORE_TABLE (OT, BASE)
#endif
/* AAT shaping. */
@@ -129,8 +129,8 @@ HB_OT_TABLE (AAT, feat)
/* OpenType color fonts. */
#ifndef HB_NO_COLOR
-HB_OT_TABLE (OT, COLR)
-HB_OT_TABLE (OT, CPAL)
+HB_OT_CORE_TABLE (OT, COLR)
+HB_OT_CORE_TABLE (OT, CPAL)
HB_OT_ACCELERATOR (OT, CBDT)
HB_OT_ACCELERATOR (OT, sbix)
HB_OT_ACCELERATOR (OT, SVG)
@@ -138,7 +138,7 @@ HB_OT_ACCELERATOR (OT, SVG)
/* OpenType math. */
#ifndef HB_NO_MATH
-HB_OT_TABLE (OT, MATH)
+HB_OT_CORE_TABLE (OT, MATH)
#endif
diff --git a/thirdparty/harfbuzz/src/hb-ot-font.cc b/thirdparty/harfbuzz/src/hb-ot-font.cc
index 825b30853c..8405103423 100644
--- a/thirdparty/harfbuzz/src/hb-ot-font.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-font.cc
@@ -45,6 +45,7 @@
#include "hb-ot-vorg-table.hh"
#include "hb-ot-color-cbdt-table.hh"
#include "hb-ot-color-sbix-table.hh"
+#include "hb-ot-color-colr-table.hh"
/**
@@ -350,13 +351,15 @@ hb_ot_get_glyph_extents (hb_font_t *font,
if (ot_face->sbix->get_extents (font, glyph, extents)) return true;
if (ot_face->CBDT->get_extents (font, glyph, extents)) return true;
#endif
+#if !defined(HB_NO_COLOR)
+ if (ot_face->COLR->get_extents (font, glyph, extents)) return true;
+#endif
if (ot_face->glyf->get_extents (font, glyph, extents)) return true;
#ifndef HB_NO_OT_FONT_CFF
if (ot_face->cff1->get_extents (font, glyph, extents)) return true;
if (ot_face->cff2->get_extents (font, glyph, extents)) return true;
#endif
- // TODO Hook up side-bearings variations.
return false;
}
diff --git a/thirdparty/harfbuzz/src/hb-ot-layout-common.hh b/thirdparty/harfbuzz/src/hb-ot-layout-common.hh
index 579abf011a..0f424f5aa6 100644
--- a/thirdparty/harfbuzz/src/hb-ot-layout-common.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-layout-common.hh
@@ -478,7 +478,7 @@ struct IndexArray : Array16Of<Index>
{
if (_count)
{
- + this->sub_array (start_offset, _count)
+ + this->as_array ().sub_array (start_offset, _count)
| hb_sink (hb_array (_indexes, *_count))
;
}
@@ -658,7 +658,7 @@ struct FeatureParamsCharacterVariants
{
if (char_count)
{
- + characters.sub_array (start_offset, char_count)
+ + characters.as_array ().sub_array (start_offset, char_count)
| hb_sink (hb_array (chars, *char_count))
;
}
@@ -932,7 +932,7 @@ struct RecordArrayOf : SortedArray16Of<Record<Type>>
{
if (record_count)
{
- + this->sub_array (start_offset, record_count)
+ + this->as_array ().sub_array (start_offset, record_count)
| hb_map (&Record<Type>::tag)
| hb_sink (hb_array (record_tags, *record_count))
;
@@ -980,18 +980,16 @@ struct RecordListOfFeature : RecordListOf<Feature>
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_apply ([l, out, this] (const hb_pair_t<const Record<Feature>&, unsigned>& _)
+ + hb_enumerate (*this)
+ | hb_filter (l->feature_index_map, hb_first)
+ | hb_apply ([l, out, this] (const hb_pair_t<unsigned, const Record<Feature>&>& _)
{
const Feature *f_sub = nullptr;
const Feature **f = nullptr;
- if (l->feature_substitutes_map->has (_.second, &f))
+ if (l->feature_substitutes_map->has (_.first, &f))
f_sub = *f;
- subset_record_array (l, out, this, f_sub) (_.first);
+ subset_record_array (l, out, this, f_sub) (_.second);
})
;
@@ -1079,7 +1077,7 @@ struct LangSys
auto *out = c->serializer->start_embed (*this);
if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
- const unsigned *v;
+ const uint32_t *v;
out->reqFeatureIndex = l->feature_index_map->has (reqFeatureIndex, &v) ? *v : 0xFFFFu;
if (!l->visitFeatureIndex (featureIndex.len))
@@ -1147,7 +1145,6 @@ struct Script
return;
}
- unsigned langsys_count = get_lang_sys_count ();
if (has_default_lang_sys ())
{
//only collect features from non-redundant langsys
@@ -1156,24 +1153,24 @@ struct Script
d.collect_features (c);
}
- for (auto _ : + hb_zip (langSys, hb_range (langsys_count)))
+ for (auto _ : + hb_enumerate (langSys))
{
- const LangSys& l = this+_.first.offset;
+ const LangSys& l = this+_.second.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);
+ c->script_langsys_map->get (script_index)->add (_.first);
}
}
else
{
- for (auto _ : + hb_zip (langSys, hb_range (langsys_count)))
+ for (auto _ : + hb_enumerate (langSys))
{
- const LangSys& l = this+_.first.offset;
+ const LangSys& l = this+_.second.offset;
if (!c->visitLangsys (l.get_feature_count ())) continue;
l.collect_features (c);
- c->script_langsys_map->get (script_index)->add (_.second);
+ c->script_langsys_map->get (script_index)->add (_.first);
}
}
}
@@ -1211,10 +1208,9 @@ struct Script
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_enumerate (langSys)
+ | hb_filter (active_langsys, hb_first)
+ | hb_map (hb_second)
| hb_filter ([=] (const Record<LangSys>& record) {return l->visitLangSys (); })
| hb_apply (subset_record_array (l, &(out->langSys), this))
;
@@ -1250,12 +1246,11 @@ struct RecordListOfScript : RecordListOf<Script>
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)))
+ for (auto _ : + hb_enumerate (*this))
{
auto snap = c->serializer->snapshot ();
- l->cur_script_index = _.second;
- bool ret = _.first.subset (l, this);
+ l->cur_script_index = _.first;
+ bool ret = _.second.subset (l, this);
if (!ret) c->serializer->revert (snap);
else out->len++;
}
@@ -1388,7 +1383,13 @@ struct Lookup
outMarkFilteringSet = markFilteringSet;
}
- return_trace (out->subTable.len);
+ // Always keep the lookup even if it's empty. The rest of layout subsetting depends on lookup
+ // indices being consistent with those computed during planning. So if an empty lookup is
+ // discarded during the subset phase it will invalidate all subsequent lookup indices.
+ // Generally we shouldn't end up with an empty lookup as we pre-prune them during the planning
+ // phase, but it can happen in rare cases such as when during closure subtable is considered
+ // degenerate (see: https://github.com/harfbuzz/harfbuzz/issues/3853)
+ return true;
}
template <typename TSubTable>
@@ -1454,10 +1455,9 @@ struct LookupOffsetList : List16OfOffsetTo<TLookup, OffsetType>
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->lookup_index_map, hb_second)
- | hb_map (hb_first)
+ + hb_enumerate (*this)
+ | hb_filter (l->lookup_index_map, hb_first)
+ | hb_map (hb_second)
| hb_apply (subset_offset_array (c, *out, this))
;
return_trace (true);
@@ -1491,7 +1491,7 @@ static bool ClassDef_remap_and_serialize (hb_serialize_context_t *c,
klass_map->set (0, 0);
unsigned idx = klass_map->has (0) ? 1 : 0;
- for (const unsigned k: klasses.iter ())
+ for (const unsigned k: klasses)
{
if (klass_map->has (k)) continue;
klass_map->set (k, idx);
@@ -1524,6 +1524,11 @@ struct ClassDefFormat1_3
return classValue[(unsigned int) (glyph_id - startGlyph)];
}
+ unsigned get_population () const
+ {
+ return classValue.len;
+ }
+
template<typename Iterator,
hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_t))>
bool serialize (hb_serialize_context_t *c,
@@ -1548,7 +1553,7 @@ struct ClassDefFormat1_3
startGlyph = glyph_min;
if (unlikely (!classValue.serialize (c, glyph_count))) return_trace (false);
- for (const hb_pair_t<hb_codepoint_t, unsigned> gid_klass_pair : + it)
+ for (const hb_pair_t<hb_codepoint_t, uint32_t> gid_klass_pair : + it)
{
unsigned idx = gid_klass_pair.first - glyph_min;
classValue[idx] = gid_klass_pair.second;
@@ -1639,11 +1644,10 @@ struct ClassDefFormat1_3
bool intersects (const hb_set_t *glyphs) const
{
- /* TODO Speed up, using hb_set_next()? */
hb_codepoint_t start = startGlyph;
hb_codepoint_t end = startGlyph + classValue.len;
for (hb_codepoint_t iter = startGlyph - 1;
- hb_set_next (glyphs, &iter) && iter < end;)
+ glyphs->next (&iter) && iter < end;)
if (classValue[iter - start]) return true;
return false;
}
@@ -1654,10 +1658,10 @@ struct ClassDefFormat1_3
{
/* Match if there's any glyph that is not listed! */
hb_codepoint_t g = HB_SET_VALUE_INVALID;
- if (!hb_set_next (glyphs, &g)) return false;
+ if (!glyphs->next (&g)) return false;
if (g < startGlyph) return true;
g = startGlyph + count - 1;
- if (hb_set_next (glyphs, &g)) return true;
+ if (glyphs->next (&g)) return true;
/* Fall through. */
}
/* TODO Speed up, using set overlap first? */
@@ -1675,12 +1679,12 @@ struct ClassDefFormat1_3
if (klass == 0)
{
unsigned start_glyph = startGlyph;
- for (unsigned g = HB_SET_VALUE_INVALID;
- hb_set_next (glyphs, &g) && g < start_glyph;)
+ for (uint32_t g = HB_SET_VALUE_INVALID;
+ glyphs->next (&g) && g < start_glyph;)
intersect_glyphs->add (g);
- for (unsigned g = startGlyph + count - 1;
- hb_set_next (glyphs, &g);)
+ for (uint32_t g = startGlyph + count - 1;
+ glyphs-> next (&g);)
intersect_glyphs->add (g);
return;
@@ -1696,7 +1700,7 @@ struct ClassDefFormat1_3
unsigned start_glyph = startGlyph;
unsigned end_glyph = start_glyph + count;
for (unsigned g = startGlyph - 1;
- hb_set_next (glyphs, &g) && g < end_glyph;)
+ glyphs->next (&g) && g < end_glyph;)
if (classValue.arrayZ[g - start_glyph] == klass)
intersect_glyphs->add (g);
#endif
@@ -1739,6 +1743,14 @@ struct ClassDefFormat2_4
return rangeRecord.bsearch (glyph_id).value;
}
+ 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,
@@ -1802,28 +1814,45 @@ struct ClassDefFormat2_4
{
TRACE_SUBSET (this);
const hb_map_t &glyph_map = *c->plan->glyph_map_gsub;
+ const hb_set_t &glyph_set = *c->plan->glyphset_gsub ();
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++)
+ if (glyph_set.get_population () * hb_bit_storage ((unsigned) rangeRecord.len) / 2
+ < get_population ())
{
- unsigned klass = rangeRecord[i].value;
- if (!klass) continue;
- hb_codepoint_t start = rangeRecord[i].first;
- hb_codepoint_t end = hb_min (rangeRecord[i].last + 1, num_source_glyphs);
- for (hb_codepoint_t g = start; g < end; g++)
+ for (hb_codepoint_t g : glyph_set)
{
- hb_codepoint_t new_gid = glyph_map[g];
+ unsigned klass = get_class (g);
+ if (!klass) continue;
+ hb_codepoint_t new_gid = glyph_map[g];
if (new_gid == HB_MAP_VALUE_INVALID) continue;
- if (glyph_filter && !glyph_filter->has (g)) continue;
-
+ if (glyph_filter && !glyph_filter->has (g)) continue;
glyph_and_klass.push (hb_pair (new_gid, klass));
orig_klasses.add (klass);
}
}
+ else
+ {
+ unsigned num_source_glyphs = c->plan->source->get_num_glyphs ();
+ for (auto &range : rangeRecord)
+ {
+ unsigned klass = range.value;
+ if (!klass) continue;
+ hb_codepoint_t start = range.first;
+ hb_codepoint_t end = hb_min (range.last + 1, num_source_glyphs);
+ for (hb_codepoint_t g = start; g < end; g++)
+ {
+ hb_codepoint_t new_gid = glyph_map[g];
+ if (new_gid == HB_MAP_VALUE_INVALID) continue;
+ if (glyph_filter && !glyph_filter->has (g)) continue;
+
+ glyph_and_klass.push (hb_pair (new_gid, klass));
+ orig_klasses.add (klass);
+ }
+ }
+ }
const hb_set_t& glyphset = *c->plan->glyphset_gsub ();
unsigned glyph_count = glyph_filter
@@ -1850,10 +1879,9 @@ struct ClassDefFormat2_4
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 (rangeRecord[i].value)
- if (unlikely (!rangeRecord[i].collect_coverage (glyphs)))
+ for (auto &range : rangeRecord)
+ if (range.value)
+ if (unlikely (!range.collect_coverage (glyphs)))
return false;
return true;
}
@@ -1861,11 +1889,10 @@ struct ClassDefFormat2_4
template <typename set_t>
bool collect_class (set_t *glyphs, unsigned int klass) const
{
- unsigned int count = rangeRecord.len;
- for (unsigned int i = 0; i < count; i++)
+ for (auto &range : rangeRecord)
{
- if (rangeRecord[i].value == klass)
- if (unlikely (!rangeRecord[i].collect_coverage (glyphs)))
+ if (range.value == klass)
+ if (unlikely (!range.collect_coverage (glyphs)))
return false;
}
return true;
@@ -1873,32 +1900,32 @@ struct ClassDefFormat2_4
bool intersects (const hb_set_t *glyphs) const
{
- /* TODO Speed up, using hb_set_next() and bsearch()? */
- unsigned int count = rangeRecord.len;
- for (unsigned int i = 0; i < count; i++)
+ if (rangeRecord.len > glyphs->get_population () * hb_bit_storage ((unsigned) rangeRecord.len) / 2)
{
- const auto& range = rangeRecord[i];
- if (range.intersects (*glyphs) && range.value)
- return true;
+ for (hb_codepoint_t g = HB_SET_VALUE_INVALID; glyphs->next (&g);)
+ if (get_class (g))
+ return true;
+ return false;
}
- return false;
+
+ return hb_any (+ hb_iter (rangeRecord)
+ | hb_map ([glyphs] (const RangeRecord<Types> &range) { return range.intersects (*glyphs) && range.value; }));
}
bool intersects_class (const hb_set_t *glyphs, uint16_t klass) const
{
- unsigned int count = rangeRecord.len;
if (klass == 0)
{
/* Match if there's any glyph that is not listed! */
hb_codepoint_t g = HB_SET_VALUE_INVALID;
- for (unsigned int i = 0; i < count; i++)
+ for (auto &range : rangeRecord)
{
- if (!hb_set_next (glyphs, &g))
+ if (!glyphs->next (&g))
break;
- if (g < rangeRecord[i].first)
+ if (g < range.first)
return true;
- g = rangeRecord[i].last;
+ g = range.last;
}
- if (g != HB_SET_VALUE_INVALID && hb_set_next (glyphs, &g))
+ if (g != HB_SET_VALUE_INVALID && glyphs->next (&g))
return true;
/* Fall through. */
}
@@ -1910,49 +1937,49 @@ struct ClassDefFormat2_4
void intersected_class_glyphs (const hb_set_t *glyphs, unsigned klass, hb_set_t *intersect_glyphs) const
{
- unsigned count = rangeRecord.len;
if (klass == 0)
{
hb_codepoint_t g = HB_SET_VALUE_INVALID;
- for (unsigned int i = 0; i < count; i++)
+ for (auto &range : rangeRecord)
{
- if (!hb_set_next (glyphs, &g))
+ if (!glyphs->next (&g))
goto done;
- while (g < rangeRecord[i].first)
+ while (g < range.first)
{
intersect_glyphs->add (g);
- if (!hb_set_next (glyphs, &g))
+ if (!glyphs->next (&g))
goto done;
}
- g = rangeRecord[i].last;
+ g = range.last;
}
- while (hb_set_next (glyphs, &g))
+ while (glyphs->next (&g))
intersect_glyphs->add (g);
done:
return;
}
-#if 0
- /* The following implementation is faster asymptotically, but slower
- * in practice. */
- if ((count >> 3) > glyphs->get_population ())
+ unsigned count = rangeRecord.len;
+ if (count > glyphs->get_population () * hb_bit_storage (count) * 8)
{
for (hb_codepoint_t g = HB_SET_VALUE_INVALID;
- hb_set_next (glyphs, &g);)
- if (rangeRecord.as_array ().bfind (g))
+ glyphs->next (&g);)
+ {
+ unsigned i;
+ if (rangeRecord.as_array ().bfind (g, &i) &&
+ rangeRecord.arrayZ[i].value == klass)
intersect_glyphs->add (g);
+ }
return;
}
-#endif
- for (unsigned int i = 0; i < count; i++)
+ for (auto &range : rangeRecord)
{
- if (rangeRecord[i].value != klass) continue;
+ if (range.value != klass) continue;
- unsigned end = rangeRecord[i].last + 1;
- for (hb_codepoint_t g = rangeRecord[i].first - 1;
- hb_set_next (glyphs, &g) && g < end;)
+ unsigned end = range.last + 1;
+ for (hb_codepoint_t g = range.first - 1;
+ glyphs->next (&g) && g < end;)
intersect_glyphs->add (g);
}
}
@@ -1961,25 +1988,24 @@ struct ClassDefFormat2_4
{
if (glyphs->is_empty ()) return;
- unsigned count = rangeRecord.len;
hb_codepoint_t g = HB_SET_VALUE_INVALID;
- for (unsigned int i = 0; i < count; i++)
+ for (auto &range : rangeRecord)
{
- if (!hb_set_next (glyphs, &g))
+ if (!glyphs->next (&g))
break;
- if (g < rangeRecord[i].first)
+ if (g < range.first)
{
intersect_classes->add (0);
break;
}
- g = rangeRecord[i].last;
+ g = range.last;
}
- if (g != HB_SET_VALUE_INVALID && hb_set_next (glyphs, &g))
+ if (g != HB_SET_VALUE_INVALID && glyphs->next (&g))
intersect_classes->add (0);
- for (const auto& record : rangeRecord.iter ())
- if (record.intersects (*glyphs))
- intersect_classes->add (record.value);
+ for (const auto& range : rangeRecord)
+ if (range.intersects (*glyphs))
+ intersect_classes->add (range.value);
}
protected:
@@ -1994,10 +2020,8 @@ struct ClassDefFormat2_4
struct ClassDef
{
/* Has interface. */
- static constexpr unsigned SENTINEL = 0;
- 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; }
+ unsigned operator [] (hb_codepoint_t k) const { return get (k); }
+ bool has (hb_codepoint_t k) const { return (*this)[k]; }
/* Projection. */
hb_codepoint_t operator () (hb_codepoint_t k) const { return get (k); }
@@ -2015,6 +2039,19 @@ struct ClassDef
}
}
+ unsigned get_population () const
+ {
+ switch (u.format) {
+ case 1: return u.format1.get_population ();
+ case 2: return u.format2.get_population ();
+#ifndef HB_NO_BEYOND_64K
+ 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 it_with_class_zero)
@@ -2332,7 +2369,7 @@ struct VarRegionList
{
unsigned int backward = region_map.backward (r);
if (backward >= region_count) return_trace (false);
- memcpy (&axesZ[axisCount * r], &src->axesZ[axisCount * backward], VarRegionAxis::static_size * axisCount);
+ hb_memcpy (&axesZ[axisCount * r], &src->axesZ[axisCount * backward], VarRegionAxis::static_size * axisCount);
}
return_trace (true);
@@ -2442,21 +2479,26 @@ struct VarData
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 */
+ hb_vector_t<unsigned int> ri_map; /* maps new index to old index */
delta_sz.resize (ri_count);
ri_map.resize (ri_count);
unsigned int new_word_count = 0;
unsigned int r;
+ const HBUINT8 *src_delta_bytes = src->get_delta_bytes ();
+ unsigned src_row_size = src->get_row_size ();
+ unsigned src_word_count = src->wordCount ();
+ bool src_long_words = src->longWords ();
+
bool has_long = false;
- if (src->longWords ())
+ if (src_long_words)
{
- for (r = 0; r < ri_count; r++)
+ for (r = 0; r < src_word_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);
+ int32_t delta = src->get_item_delta_fast (old, r, src_delta_bytes, src_row_size);
if (delta < -65536 || 65535 < delta)
{
has_long = true;
@@ -2470,11 +2512,13 @@ struct VarData
signed max_threshold = has_long ? +65535 : +127;
for (r = 0; r < ri_count; r++)
{
+ bool short_circuit = src_long_words == has_long && src_word_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);
- int32_t delta = src->get_item_delta (old, r);
+ int32_t delta = src->get_item_delta_fast (old, r, src_delta_bytes, src_row_size);
if (delta < min_threshold || max_threshold < delta)
{
delta_sz[r] = kWord;
@@ -2482,7 +2526,11 @@ struct VarData
break;
}
else if (delta != 0)
+ {
delta_sz[r] = kNonWord;
+ if (short_circuit)
+ break;
+ }
}
}
@@ -2492,7 +2540,8 @@ struct VarData
for (r = 0; r < ri_count; r++)
if (delta_sz[r])
{
- ri_map[r] = (delta_sz[r] == kWord)? word_index++ : non_word_index++;
+ unsigned new_r = (delta_sz[r] == kWord)? word_index++ : non_word_index++;
+ ri_map[new_r] = r;
new_ri_count++;
}
@@ -2502,14 +2551,20 @@ struct VarData
if (unlikely (!c->extend (this))) return_trace (false);
- for (r = 0; r < ri_count; r++)
- if (delta_sz[r]) regionIndices[ri_map[r]] = region_map[src->regionIndices[r]];
+ for (r = 0; r < new_ri_count; r++)
+ regionIndices[r] = region_map[src->regionIndices[ri_map[r]]];
- for (unsigned int i = 0; i < itemCount; i++)
+ HBUINT8 *delta_bytes = get_delta_bytes ();
+ unsigned row_size = get_row_size ();
+ unsigned count = itemCount;
+ for (unsigned int i = 0; i < count; i++)
{
- unsigned int old = inner_map.backward (i);
- for (unsigned int r = 0; r < ri_count; r++)
- if (delta_sz[r]) set_item_delta (i, ri_map[r], src->get_item_delta (old, r));
+ unsigned int old = inner_map.backward (i);
+ for (unsigned int r = 0; r < new_ri_count; r++)
+ set_item_delta_fast (i, r,
+ src->get_item_delta_fast (old, ri_map[r],
+ src_delta_bytes, src_row_size),
+ delta_bytes, row_size);
}
return_trace (true);
@@ -2517,12 +2572,15 @@ struct VarData
void collect_region_refs (hb_set_t &region_indices, const hb_inc_bimap_t &inner_map) const
{
+ const HBUINT8 *delta_bytes = get_delta_bytes ();
+ unsigned row_size = get_row_size ();
+
for (unsigned int r = 0; r < regionIndices.len; r++)
{
- unsigned int region = regionIndices[r];
+ unsigned int region = regionIndices.arrayZ[r];
if (region_indices.has (region)) continue;
for (unsigned int i = 0; i < inner_map.get_next_value (); i++)
- if (get_item_delta (inner_map.backward (i), r) != 0)
+ if (get_item_delta_fast (inner_map.backward (i), r, delta_bytes, row_size) != 0)
{
region_indices.add (region);
break;
@@ -2537,10 +2595,12 @@ struct VarData
HBUINT8 *get_delta_bytes ()
{ return &StructAfter<HBUINT8> (regionIndices); }
- int32_t get_item_delta (unsigned int item, unsigned int region) const
+ int32_t get_item_delta_fast (unsigned int item, unsigned int region,
+ const HBUINT8 *delta_bytes, unsigned row_size) const
{
- if ( item >= itemCount || unlikely (region >= regionIndices.len)) return 0;
- const HBINT8 *p = (const HBINT8 *) get_delta_bytes () + item * get_row_size ();
+ if (unlikely (item >= itemCount || region >= regionIndices.len)) return 0;
+
+ const HBINT8 *p = (const HBINT8 *) delta_bytes + item * row_size;
unsigned word_count = wordCount ();
bool is_long = longWords ();
if (is_long)
@@ -2558,10 +2618,17 @@ struct VarData
return (p + HBINT16::static_size * word_count)[region - word_count];
}
}
+ int32_t get_item_delta (unsigned int item, unsigned int region) const
+ {
+ return get_item_delta_fast (item, region,
+ get_delta_bytes (),
+ get_row_size ());
+ }
- void set_item_delta (unsigned int item, unsigned int region, int32_t delta)
+ void set_item_delta_fast (unsigned int item, unsigned int region, int32_t delta,
+ HBUINT8 *delta_bytes, unsigned row_size)
{
- HBINT8 *p = (HBINT8 *)get_delta_bytes () + item * get_row_size ();
+ HBINT8 *p = (HBINT8 *) delta_bytes + item * row_size;
unsigned word_count = wordCount ();
bool is_long = longWords ();
if (is_long)
@@ -2579,6 +2646,12 @@ struct VarData
(p + HBINT16::static_size * word_count)[region - word_count] = delta;
}
}
+ void set_item_delta (unsigned int item, unsigned int region, int32_t delta)
+ {
+ set_item_delta_fast (item, region, delta,
+ get_delta_bytes (),
+ get_row_size ());
+ }
bool longWords () const { return wordSizeCount & 0x8000u /* LONG_WORDS */; }
unsigned wordCount () const { return wordSizeCount & 0x7FFFu /* WORD_DELTA_COUNT_MASK */; }
@@ -2642,6 +2715,14 @@ struct VariationStore
unsigned int inner = index & 0xFFFF;
return get_delta (outer, inner, coords, coord_count, cache);
}
+ float get_delta (unsigned int index,
+ hb_array_t<int> coords,
+ VarRegionList::cache_t *cache = nullptr) const
+ {
+ return get_delta (index,
+ coords.arrayZ, coords.length,
+ cache);
+ }
bool sanitize (hb_sanitize_context_t *c) const
{
@@ -2948,7 +3029,7 @@ struct ConditionSet
// all conditions met
if (num_kept_cond == 0) return DROP_COND_WITH_VAR;
-
+
//check if condition_set is unique with variations
if (c->conditionset_map->has (p))
//duplicate found, drop the entire record
@@ -3420,17 +3501,16 @@ struct VariationDevice
{
TRACE_SERIALIZE (this);
if (!layout_variation_idx_delta_map) return_trace (nullptr);
- auto snap = c->snapshot ();
+
+ hb_pair_t<unsigned, int> *v;
+ if (!layout_variation_idx_delta_map->has (varIdx, &v))
+ return_trace (nullptr);
+
+ c->start_zerocopy (this->static_size);
auto *out = c->embed (this);
if (unlikely (!out)) return_trace (nullptr);
- /* TODO Just get() and bail if NO_VARIATION. Needs to setup the map to return that. */
- if (!layout_variation_idx_delta_map->has (varIdx))
- {
- c->revert (snap);
- return_trace (nullptr);
- }
- unsigned new_idx = hb_first (layout_variation_idx_delta_map->get (varIdx));
+ unsigned new_idx = hb_first (*v);
out->varIdx = new_idx;
return_trace (out);
}
diff --git a/thirdparty/harfbuzz/src/hb-ot-layout-gdef-table.hh b/thirdparty/harfbuzz/src/hb-ot-layout-gdef-table.hh
index 22925fdfa9..a84edef162 100644
--- a/thirdparty/harfbuzz/src/hb-ot-layout-gdef-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-layout-gdef-table.hh
@@ -73,7 +73,7 @@ struct AttachList
if (point_count)
{
- + points.sub_array (start_offset, point_count)
+ + points.as_array ().sub_array (start_offset, point_count)
| hb_sink (hb_array (point_array, *point_count))
;
}
@@ -322,7 +322,7 @@ struct LigGlyph
{
if (caret_count)
{
- + carets.sub_array (start_offset, caret_count)
+ + carets.as_array ().sub_array (start_offset, caret_count)
| hb_map (hb_add (this))
| hb_map ([&] (const CaretValue &value) { return value.get_caret_value (font, direction, glyph_id, var_store); })
| hb_sink (hb_array (caret_array, *caret_count))
diff --git a/thirdparty/harfbuzz/src/hb-ot-layout-gsubgpos.hh b/thirdparty/harfbuzz/src/hb-ot-layout-gsubgpos.hh
index d1d94255f4..04ccefd108 100644
--- a/thirdparty/harfbuzz/src/hb-ot-layout-gsubgpos.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-layout-gsubgpos.hh
@@ -100,8 +100,8 @@ struct hb_closure_context_t :
bool is_lookup_done (unsigned int lookup_index)
{
- if (done_lookups_glyph_count->in_error () ||
- done_lookups_glyph_set->in_error ())
+ if (unlikely (done_lookups_glyph_count->in_error () ||
+ done_lookups_glyph_set->in_error ()))
return true;
/* Have we visited this lookup with the current set of glyphs? */
@@ -535,7 +535,12 @@ struct hb_ot_apply_context_t :
bool next (unsigned *unsafe_to = nullptr)
{
assert (num_items > 0);
- while (idx + num_items < end)
+ /* The alternate condition below is faster at string boundaries,
+ * but produces subpar "unsafe-to-concat" values. */
+ signed stop = (signed) end - (signed) num_items;
+ if (c->buffer->flags & HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT)
+ stop = (signed) end - 1;
+ while ((signed) idx < stop)
{
idx++;
hb_glyph_info_t &info = c->buffer->info[idx];
@@ -568,7 +573,12 @@ struct hb_ot_apply_context_t :
bool prev (unsigned *unsafe_from = nullptr)
{
assert (num_items > 0);
- while (idx > num_items - 1)
+ /* The alternate condition below is faster at string boundaries,
+ * but produces subpar "unsafe-to-concat" values. */
+ unsigned stop = num_items - 1;
+ if (c->buffer->flags & HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT)
+ stop = 1 - 1;
+ while (idx > stop)
{
idx--;
hb_glyph_info_t &info = c->buffer->out_info[idx];
@@ -672,6 +682,7 @@ struct hb_ot_apply_context_t :
const GDEF &gdef;
const VariationStore &var_store;
VariationStore::cache_t *var_store_cache;
+ hb_set_digest_t digest;
hb_direction_t direction;
hb_mask_t lookup_mask = 1;
@@ -707,6 +718,7 @@ struct hb_ot_apply_context_t :
nullptr
#endif
),
+ digest (buffer_->digest ()),
direction (buffer_->props.direction),
has_glyph_classes (gdef.has_glyph_classes ())
{ init_iters (); }
@@ -781,8 +793,10 @@ struct hb_ot_apply_context_t :
void _set_glyph_class (hb_codepoint_t glyph_index,
unsigned int class_guess = 0,
bool ligature = false,
- bool component = false) const
+ bool component = false)
{
+ digest.add (glyph_index);
+
if (new_syllables != (unsigned) -1)
buffer->cur().syllable() = new_syllables;
@@ -815,24 +829,24 @@ struct hb_ot_apply_context_t :
_hb_glyph_info_set_glyph_props (&buffer->cur(), props);
}
- void replace_glyph (hb_codepoint_t glyph_index) const
+ void replace_glyph (hb_codepoint_t glyph_index)
{
_set_glyph_class (glyph_index);
(void) buffer->replace_glyph (glyph_index);
}
- void replace_glyph_inplace (hb_codepoint_t glyph_index) const
+ void replace_glyph_inplace (hb_codepoint_t glyph_index)
{
_set_glyph_class (glyph_index);
buffer->cur().codepoint = glyph_index;
}
void replace_glyph_with_ligature (hb_codepoint_t glyph_index,
- unsigned int class_guess) const
+ unsigned int class_guess)
{
_set_glyph_class (glyph_index, class_guess, true);
(void) buffer->replace_glyph (glyph_index);
}
void output_glyph_for_component (hb_codepoint_t glyph_index,
- unsigned int class_guess) const
+ unsigned int class_guess)
{
_set_glyph_class (glyph_index, class_guess, false, true);
(void) buffer->output_glyph (glyph_index);
@@ -844,7 +858,7 @@ 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)
+ static inline bool apply_to (const void *obj, hb_ot_apply_context_t *c)
{
const Type *typed_obj = (const Type *) obj;
return typed_obj->apply (c);
@@ -852,30 +866,30 @@ struct hb_accelerate_subtables_context_t :
#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) )
+ static inline auto apply_cached_ (const T *obj, 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) )
+ static inline auto apply_cached_ (const T *obj, 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)
+ static inline bool apply_cached_to (const void *obj, 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) )
+ static inline auto cache_func_ (const T *obj, 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; }
+ static inline bool cache_func_ (const T *obj, 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)
+ static inline bool cache_func_to (const void *obj, 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);
+ typedef bool (*hb_apply_func_t) (const void *obj, hb_ot_apply_context_t *c);
+ typedef bool (*hb_cache_func_t) (const void *obj, hb_ot_apply_context_t *c, bool enter);
struct hb_applicable_t
{
@@ -901,20 +915,20 @@ struct hb_accelerate_subtables_context_t :
obj_.get_coverage ().collect_coverage (&digest);
}
- bool apply (OT::hb_ot_apply_context_t *c) const
+ bool apply (hb_ot_apply_context_t *c) const
{
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
+ bool apply_cached (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
+ bool cache_enter (hb_ot_apply_context_t *c) const
{
return cache_func (obj, c, true);
}
- void cache_leave (OT::hb_ot_apply_context_t *c) const
+ void cache_leave (hb_ot_apply_context_t *c) const
{
cache_func (obj, c, false);
}
@@ -988,8 +1002,8 @@ struct hb_accelerate_subtables_context_t :
};
-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 bool (*intersects_func_t) (const hb_set_t *glyphs, unsigned value, const void *data, void *cache);
+typedef void (*intersected_glyphs_func_t) (const hb_set_t *glyphs, const void *data, unsigned value, hb_set_t *intersected_glyphs, void *cache);
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);
@@ -1012,16 +1026,25 @@ struct ChainContextApplyFuncs
};
-static inline bool intersects_glyph (const hb_set_t *glyphs, unsigned value, const void *data HB_UNUSED)
+static inline bool intersects_glyph (const hb_set_t *glyphs, unsigned value, const void *data HB_UNUSED, void *cache HB_UNUSED)
{
return glyphs->has (value);
}
-static inline bool intersects_class (const hb_set_t *glyphs, unsigned value, const void *data)
+static inline bool intersects_class (const hb_set_t *glyphs, unsigned value, const void *data, void *cache)
{
const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
- return class_def.intersects_class (glyphs, value);
+ hb_map_t *map = (hb_map_t *) cache;
+
+ hb_codepoint_t *cached_v;
+ if (map->has (value, &cached_v))
+ return *cached_v;
+
+ bool v = class_def.intersects_class (glyphs, value);
+ map->set (value, v);
+
+ return v;
}
-static inline bool intersects_coverage (const hb_set_t *glyphs, unsigned value, const void *data)
+static inline bool intersects_coverage (const hb_set_t *glyphs, unsigned value, const void *data, void *cache HB_UNUSED)
{
Offset16To<Coverage> coverage;
coverage = value;
@@ -1029,17 +1052,36 @@ static inline bool intersects_coverage (const hb_set_t *glyphs, unsigned value,
}
-static inline void intersected_glyph (const hb_set_t *glyphs HB_UNUSED, const void *data, unsigned value, hb_set_t *intersected_glyphs)
+static inline void intersected_glyph (const hb_set_t *glyphs HB_UNUSED, const void *data, unsigned value, hb_set_t *intersected_glyphs, HB_UNUSED void *cache)
{
unsigned g = reinterpret_cast<const HBUINT16 *>(data)[value];
intersected_glyphs->add (g);
}
-static inline void intersected_class_glyphs (const hb_set_t *glyphs, const void *data, unsigned value, hb_set_t *intersected_glyphs)
+
+using intersected_class_cache_t = hb_hashmap_t<unsigned, hb_set_t>;
+
+static inline void intersected_class_glyphs (const hb_set_t *glyphs, const void *data, unsigned value, hb_set_t *intersected_glyphs, void *cache)
{
const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
- class_def.intersected_class_glyphs (glyphs, value, intersected_glyphs);
+
+ intersected_class_cache_t *map = (intersected_class_cache_t *) cache;
+
+ hb_set_t *cached_v;
+ if (map->has (value, &cached_v))
+ {
+ intersected_glyphs->union_ (*cached_v);
+ return;
+ }
+
+ hb_set_t v;
+ class_def.intersected_class_glyphs (glyphs, value, &v);
+
+ intersected_glyphs->union_ (v);
+
+ map->set (value, std::move (v));
}
-static inline void intersected_coverage_glyphs (const hb_set_t *glyphs, const void *data, unsigned value, hb_set_t *intersected_glyphs)
+
+static inline void intersected_coverage_glyphs (const hb_set_t *glyphs, const void *data, unsigned value, hb_set_t *intersected_glyphs, HB_UNUSED void *cache)
{
Offset16To<Coverage> coverage;
coverage = value;
@@ -1052,10 +1094,11 @@ static inline bool array_is_subset_of (const hb_set_t *glyphs,
unsigned int count,
const HBUINT values[],
intersects_func_t intersects_func,
- const void *intersects_data)
+ const void *intersects_data,
+ void *cache)
{
for (const auto &_ : + hb_iter (values, count))
- if (!intersects_func (glyphs, _, intersects_data)) return false;
+ if (!intersects_func (glyphs, _, intersects_data, cache)) return false;
return true;
}
@@ -1492,7 +1535,8 @@ static void context_closure_recurse_lookups (hb_closure_context_t *c,
unsigned value,
ContextFormat context_format,
const void *data,
- intersected_glyphs_func_t intersected_glyphs_func)
+ intersected_glyphs_func_t intersected_glyphs_func,
+ void *cache)
{
hb_set_t *covered_seq_indicies = hb_set_create ();
for (unsigned int i = 0; i < lookupCount; i++)
@@ -1513,7 +1557,7 @@ static void context_closure_recurse_lookups (hb_closure_context_t *c,
pos_glyphs.add (value);
break;
case ContextFormat::ClassBasedContext:
- intersected_glyphs_func (&c->parent_active_glyphs (), data, value, &pos_glyphs);
+ intersected_glyphs_func (&c->parent_active_glyphs (), data, value, &pos_glyphs, cache);
break;
case ContextFormat::CoverageBasedContext:
pos_glyphs.set (c->parent_active_glyphs ());
@@ -1530,7 +1574,7 @@ static void context_closure_recurse_lookups (hb_closure_context_t *c,
input_value = input[seqIndex - 1];
}
- intersected_glyphs_func (c->glyphs, input_data, input_value, &pos_glyphs);
+ intersected_glyphs_func (c->glyphs, input_data, input_value, &pos_glyphs, cache);
}
}
@@ -1710,6 +1754,8 @@ struct ContextClosureLookupContext
ContextClosureFuncs funcs;
ContextFormat context_format;
const void *intersects_data;
+ void *intersects_cache;
+ void *intersected_glyphs_cache;
};
struct ContextCollectGlyphsLookupContext
@@ -1732,7 +1778,9 @@ static inline bool context_intersects (const hb_set_t *glyphs,
{
return array_is_subset_of (glyphs,
inputCount ? inputCount - 1 : 0, input,
- lookup_context.funcs.intersects, lookup_context.intersects_data);
+ lookup_context.funcs.intersects,
+ lookup_context.intersects_data,
+ lookup_context.intersects_cache);
}
template <typename HBUINT>
@@ -1753,7 +1801,8 @@ static inline void context_closure_lookup (hb_closure_context_t *c,
value,
lookup_context.context_format,
lookup_context.intersects_data,
- lookup_context.funcs.intersected_glyphs);
+ lookup_context.funcs.intersected_glyphs,
+ lookup_context.intersected_glyphs_cache);
}
template <typename HBUINT>
@@ -1777,7 +1826,7 @@ static inline bool context_would_apply_lookup (hb_would_apply_context_t *c,
const HBUINT input[], /* Array of input values--start with second glyph */
unsigned int lookupCount HB_UNUSED,
const LookupRecord lookupRecord[] HB_UNUSED,
- ContextApplyLookupContext &lookup_context)
+ const ContextApplyLookupContext &lookup_context)
{
return would_match_input (c,
inputCount, input,
@@ -1790,7 +1839,7 @@ static inline bool context_apply_lookup (hb_ot_apply_context_t *c,
const HBUINT input[], /* Array of input values--start with second glyph */
unsigned int lookupCount,
const LookupRecord lookupRecord[],
- ContextApplyLookupContext &lookup_context)
+ const ContextApplyLookupContext &lookup_context)
{
unsigned match_end = 0;
unsigned match_positions[HB_MAX_CONTEXT_LENGTH];
@@ -1858,7 +1907,7 @@ struct Rule
}
bool would_apply (hb_would_apply_context_t *c,
- ContextApplyLookupContext &lookup_context) const
+ const ContextApplyLookupContext &lookup_context) const
{
const auto &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>>
(inputZ.as_array (inputCount ? inputCount - 1 : 0));
@@ -1869,7 +1918,7 @@ struct Rule
}
bool apply (hb_ot_apply_context_t *c,
- ContextApplyLookupContext &lookup_context) const
+ const ContextApplyLookupContext &lookup_context) const
{
TRACE_APPLY (this);
const auto &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>>
@@ -1989,7 +2038,7 @@ struct RuleSet
}
bool would_apply (hb_would_apply_context_t *c,
- ContextApplyLookupContext &lookup_context) const
+ const ContextApplyLookupContext &lookup_context) const
{
return
+ hb_iter (rule)
@@ -2000,7 +2049,7 @@ struct RuleSet
}
bool apply (hb_ot_apply_context_t *c,
- ContextApplyLookupContext &lookup_context) const
+ const ContextApplyLookupContext &lookup_context) const
{
TRACE_APPLY (this);
return_trace (
@@ -2108,7 +2157,7 @@ struct ContextFormat1_4
void closure_lookups (hb_closure_lookups_context_t *c) const
{
struct ContextClosureLookupContext lookup_context = {
- {intersects_glyph, intersected_glyph},
+ {intersects_glyph, nullptr},
ContextFormat::SimpleContext,
nullptr
};
@@ -2220,10 +2269,12 @@ struct ContextFormat2_5
const ClassDef &class_def = this+classDef;
+ hb_map_t cache;
struct ContextClosureLookupContext lookup_context = {
- {intersects_class, intersected_class_glyphs},
+ {intersects_class, nullptr},
ContextFormat::ClassBasedContext,
- &class_def
+ &class_def,
+ &cache
};
hb_set_t retained_coverage_glyphs;
@@ -2259,10 +2310,14 @@ struct ContextFormat2_5
const ClassDef &class_def = this+classDef;
+ hb_map_t cache;
+ intersected_class_cache_t intersected_cache;
struct ContextClosureLookupContext lookup_context = {
{intersects_class, intersected_class_glyphs},
ContextFormat::ClassBasedContext,
- &class_def
+ &class_def,
+ &cache,
+ &intersected_cache
};
+ hb_enumerate (ruleSet)
@@ -2286,10 +2341,12 @@ struct ContextFormat2_5
const ClassDef &class_def = this+classDef;
+ hb_map_t cache;
struct ContextClosureLookupContext lookup_context = {
- {intersects_class, intersected_class_glyphs},
+ {intersects_class, nullptr},
ContextFormat::ClassBasedContext,
- &class_def
+ &class_def,
+ &cache
};
+ hb_iter (ruleSet)
@@ -2407,6 +2464,7 @@ struct ContextFormat2_5
const hb_map_t *lookup_map = c->table_tag == HB_OT_TAG_GSUB ? c->plan->gsub_lookups : c->plan->gpos_lookups;
bool ret = true;
int non_zero_index = -1, index = 0;
+ auto snapshot = c->serializer->snapshot();
for (const auto& _ : + hb_enumerate (ruleSet)
| hb_filter (klass_map, hb_first))
{
@@ -2418,8 +2476,10 @@ struct ContextFormat2_5
}
if (coverage_glyph_classes.has (_.first) &&
- o->serialize_subset (c, _.second, this, lookup_map, &klass_map))
+ o->serialize_subset (c, _.second, this, lookup_map, &klass_map)) {
non_zero_index = index;
+ snapshot = c->serializer->snapshot();
+ }
index++;
}
@@ -2433,6 +2493,7 @@ struct ContextFormat2_5
out->ruleSet.pop ();
index--;
}
+ c->serializer->revert (snapshot);
return_trace (bool (out->ruleSet));
}
@@ -2469,7 +2530,7 @@ struct ContextFormat3
return false;
struct ContextClosureLookupContext lookup_context = {
- {intersects_coverage, intersected_coverage_glyphs},
+ {intersects_coverage, nullptr},
ContextFormat::CoverageBasedContext,
this
};
@@ -2655,6 +2716,8 @@ struct ChainContextClosureLookupContext
ContextClosureFuncs funcs;
ContextFormat context_format;
const void *intersects_data[3];
+ void *intersects_cache[3];
+ void *intersected_glyphs_cache;
};
struct ChainContextCollectGlyphsLookupContext
@@ -2681,13 +2744,19 @@ static inline bool chain_context_intersects (const hb_set_t *glyphs,
{
return array_is_subset_of (glyphs,
backtrackCount, backtrack,
- lookup_context.funcs.intersects, lookup_context.intersects_data[0])
+ lookup_context.funcs.intersects,
+ lookup_context.intersects_data[0],
+ lookup_context.intersects_cache[0])
&& array_is_subset_of (glyphs,
inputCount ? inputCount - 1 : 0, input,
- lookup_context.funcs.intersects, lookup_context.intersects_data[1])
+ lookup_context.funcs.intersects,
+ lookup_context.intersects_data[1],
+ lookup_context.intersects_cache[1])
&& array_is_subset_of (glyphs,
lookaheadCount, lookahead,
- lookup_context.funcs.intersects, lookup_context.intersects_data[2]);
+ lookup_context.funcs.intersects,
+ lookup_context.intersects_data[2],
+ lookup_context.intersects_cache[2]);
}
template <typename HBUINT>
@@ -2714,7 +2783,8 @@ static inline void chain_context_closure_lookup (hb_closure_context_t *c,
value,
lookup_context.context_format,
lookup_context.intersects_data[1],
- lookup_context.funcs.intersected_glyphs);
+ lookup_context.funcs.intersected_glyphs,
+ lookup_context.intersected_glyphs_cache);
}
template <typename HBUINT>
@@ -2752,7 +2822,7 @@ static inline bool chain_context_would_apply_lookup (hb_would_apply_context_t *c
const HBUINT lookahead[] HB_UNUSED,
unsigned int lookupCount HB_UNUSED,
const LookupRecord lookupRecord[] HB_UNUSED,
- ChainContextApplyLookupContext &lookup_context)
+ const ChainContextApplyLookupContext &lookup_context)
{
return (c->zero_context ? !backtrackCount && !lookaheadCount : true)
&& would_match_input (c,
@@ -2770,7 +2840,7 @@ static inline bool chain_context_apply_lookup (hb_ot_apply_context_t *c,
const HBUINT lookahead[],
unsigned int lookupCount,
const LookupRecord lookupRecord[],
- ChainContextApplyLookupContext &lookup_context)
+ const ChainContextApplyLookupContext &lookup_context)
{
unsigned end_index = c->buffer->idx;
unsigned match_end = 0;
@@ -2864,7 +2934,7 @@ struct ChainRule
}
bool would_apply (hb_would_apply_context_t *c,
- ChainContextApplyLookupContext &lookup_context) const
+ const ChainContextApplyLookupContext &lookup_context) const
{
const auto &input = StructAfter<decltype (inputX)> (backtrack);
const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
@@ -2876,7 +2946,8 @@ struct ChainRule
lookup.arrayZ, lookup_context);
}
- bool apply (hb_ot_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
+ bool apply (hb_ot_apply_context_t *c,
+ const ChainContextApplyLookupContext &lookup_context) const
{
TRACE_APPLY (this);
const auto &input = StructAfter<decltype (inputX)> (backtrack);
@@ -3042,7 +3113,8 @@ struct ChainRuleSet
;
}
- bool would_apply (hb_would_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
+ bool would_apply (hb_would_apply_context_t *c,
+ const ChainContextApplyLookupContext &lookup_context) const
{
return
+ hb_iter (rule)
@@ -3052,7 +3124,8 @@ struct ChainRuleSet
;
}
- bool apply (hb_ot_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
+ bool apply (hb_ot_apply_context_t *c,
+ const ChainContextApplyLookupContext &lookup_context) const
{
TRACE_APPLY (this);
return_trace (
@@ -3166,7 +3239,7 @@ struct ChainContextFormat1_4
void closure_lookups (hb_closure_lookups_context_t *c) const
{
struct ChainContextClosureLookupContext lookup_context = {
- {intersects_glyph, intersected_glyph},
+ {intersects_glyph, nullptr},
ContextFormat::SimpleContext,
{nullptr, nullptr, nullptr}
};
@@ -3278,12 +3351,14 @@ struct ChainContextFormat2_5
const ClassDef &input_class_def = this+inputClassDef;
const ClassDef &lookahead_class_def = this+lookaheadClassDef;
+ hb_map_t caches[3] = {};
struct ChainContextClosureLookupContext lookup_context = {
- {intersects_class, intersected_class_glyphs},
+ {intersects_class, nullptr},
ContextFormat::ClassBasedContext,
{&backtrack_class_def,
&input_class_def,
- &lookahead_class_def}
+ &lookahead_class_def},
+ {&caches[0], &caches[1], &caches[2]}
};
hb_set_t retained_coverage_glyphs;
@@ -3321,12 +3396,16 @@ struct ChainContextFormat2_5
const ClassDef &input_class_def = this+inputClassDef;
const ClassDef &lookahead_class_def = this+lookaheadClassDef;
+ hb_map_t caches[3] = {};
+ intersected_class_cache_t intersected_cache;
struct ChainContextClosureLookupContext lookup_context = {
{intersects_class, intersected_class_glyphs},
ContextFormat::ClassBasedContext,
{&backtrack_class_def,
&input_class_def,
- &lookahead_class_def}
+ &lookahead_class_def},
+ {&caches[0], &caches[1], &caches[2]},
+ &intersected_cache
};
+ hb_enumerate (ruleSet)
@@ -3352,12 +3431,14 @@ struct ChainContextFormat2_5
const ClassDef &input_class_def = this+inputClassDef;
const ClassDef &lookahead_class_def = this+lookaheadClassDef;
+ hb_map_t caches[3] = {};
struct ChainContextClosureLookupContext lookup_context = {
- {intersects_class, intersected_class_glyphs},
+ {intersects_class, nullptr},
ContextFormat::ClassBasedContext,
{&backtrack_class_def,
&input_class_def,
- &lookahead_class_def}
+ &lookahead_class_def},
+ {&caches[0], &caches[1], &caches[2]}
};
+ hb_iter (ruleSet)
@@ -3587,7 +3668,7 @@ struct ChainContextFormat3
const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
struct ChainContextClosureLookupContext lookup_context = {
- {intersects_coverage, intersected_coverage_glyphs},
+ {intersects_coverage, nullptr},
ContextFormat::CoverageBasedContext,
{this, this, this}
};
@@ -3938,13 +4019,14 @@ struct hb_ot_layout_lookup_accelerator_t
template <typename TLookup>
void init (const TLookup &lookup)
{
- digest.init ();
- lookup.collect_coverage (&digest);
-
subtables.init ();
- OT::hb_accelerate_subtables_context_t c_accelerate_subtables (subtables);
+ hb_accelerate_subtables_context_t c_accelerate_subtables (subtables);
lookup.dispatch (&c_accelerate_subtables);
+ digest.init ();
+ for (auto& subtable : hb_iter (subtables))
+ digest.add (subtable.digest);
+
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
cache_user_idx = c_accelerate_subtables.cache_user_idx;
for (unsigned i = 0; i < subtables.length; i++)
@@ -3962,21 +4044,25 @@ struct hb_ot_layout_lookup_accelerator_t
#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;
+ return
+ + hb_iter (subtables)
+ | hb_map ([&c] (const hb_accelerate_subtables_context_t::hb_applicable_t &_) { return _.apply_cached (c); })
+ | hb_any
+ ;
}
else
#endif
{
- for (unsigned int i = 0; i < subtables.length; i++)
- if (subtables[i].apply (c))
- return true;
+ return
+ + hb_iter (subtables)
+ | hb_map ([&c] (const hb_accelerate_subtables_context_t::hb_applicable_t &_) { return _.apply (c); })
+ | hb_any
+ ;
}
return false;
}
- bool cache_enter (OT::hb_ot_apply_context_t *c) const
+ bool cache_enter (hb_ot_apply_context_t *c) const
{
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
return cache_user_idx != (unsigned) -1 &&
@@ -3985,7 +4071,7 @@ struct hb_ot_layout_lookup_accelerator_t
return false;
#endif
}
- void cache_leave (OT::hb_ot_apply_context_t *c) const
+ void cache_leave (hb_ot_apply_context_t *c) const
{
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
subtables[cache_user_idx].cache_leave (c);
@@ -3993,8 +4079,8 @@ struct hb_ot_layout_lookup_accelerator_t
}
- private:
hb_set_digest_t digest;
+ private:
hb_accelerate_subtables_context_t::array_t subtables;
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
unsigned cache_user_idx = (unsigned) -1;
@@ -4255,11 +4341,11 @@ struct GSUBGPOS
hb_set_t *lookup_indexes /* IN/OUT */) const
{
hb_set_t visited_lookups, inactive_lookups;
- OT::hb_closure_lookups_context_t c (face, glyphs, &visited_lookups, &inactive_lookups);
+ 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))
+ for (unsigned lookup_index : *lookup_indexes)
reinterpret_cast<const TLookup &> (get_lookup (lookup_index)).closure_lookups (&c, lookup_index);
hb_set_union (lookup_indexes, &visited_lookups);
@@ -4301,7 +4387,7 @@ struct GSUBGPOS
}
#endif
- for (unsigned i : feature_indices->iter())
+ for (unsigned i : hb_iter (feature_indices))
{
hb_tag_t tag = get_feature_tag (i);
if (tag == HB_TAG ('p', 'r', 'e', 'f'))
diff --git a/thirdparty/harfbuzz/src/hb-ot-layout.cc b/thirdparty/harfbuzz/src/hb-ot-layout.cc
index dbb30076a2..e8091ec3e0 100644
--- a/thirdparty/harfbuzz/src/hb-ot-layout.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-layout.cc
@@ -1465,56 +1465,6 @@ hb_ot_layout_substitute_start (hb_font_t *font,
_hb_ot_layout_set_glyph_props (font, buffer);
}
-void
-hb_ot_layout_delete_glyphs_inplace (hb_buffer_t *buffer,
- bool (*filter) (const hb_glyph_info_t *info))
-{
- /* Merge clusters and delete filtered glyphs.
- * NOTE! We can't use out-buffer as we have positioning data. */
- unsigned int j = 0;
- unsigned int count = buffer->len;
- hb_glyph_info_t *info = buffer->info;
- hb_glyph_position_t *pos = buffer->pos;
- for (unsigned int i = 0; i < count; i++)
- {
- if (filter (&info[i]))
- {
- /* Merge clusters.
- * Same logic as buffer->delete_glyph(), but for in-place removal. */
-
- unsigned int cluster = info[i].cluster;
- if (i + 1 < count && cluster == info[i + 1].cluster)
- continue; /* Cluster survives; do nothing. */
-
- if (j)
- {
- /* Merge cluster backward. */
- if (cluster < info[j - 1].cluster)
- {
- unsigned int mask = info[i].mask;
- unsigned int old_cluster = info[j - 1].cluster;
- for (unsigned k = j; k && info[k - 1].cluster == old_cluster; k--)
- buffer->set_cluster (info[k - 1], cluster, mask);
- }
- continue;
- }
-
- if (i + 1 < count)
- buffer->merge_clusters (i, i + 2); /* Merge cluster forward. */
-
- continue;
- }
-
- if (j != i)
- {
- info[j] = info[i];
- pos[j] = pos[i];
- }
- j++;
- }
- buffer->len = j;
-}
-
/**
* hb_ot_layout_lookup_substitute_closure:
* @face: #hb_face_t to work upon
@@ -1867,7 +1817,7 @@ apply_forward (OT::hb_ot_apply_context_t *c,
while (buffer->idx < buffer->len && buffer->successful)
{
bool applied = false;
- if (accel.may_have (buffer->cur().codepoint) &&
+ if (accel.digest.may_have (buffer->cur().codepoint) &&
(buffer->cur().mask & c->lookup_mask) &&
c->check_glyph_property (&buffer->cur(), c->lookup_props))
{
@@ -1894,7 +1844,7 @@ apply_backward (OT::hb_ot_apply_context_t *c,
hb_buffer_t *buffer = c->buffer;
do
{
- if (accel.may_have (buffer->cur().codepoint) &&
+ if (accel.digest.may_have (buffer->cur().codepoint) &&
(buffer->cur().mask & c->lookup_mask) &&
c->check_glyph_property (&buffer->cur(), c->lookup_props))
ret |= accel.apply (c, false);
@@ -1908,15 +1858,16 @@ apply_backward (OT::hb_ot_apply_context_t *c,
}
template <typename Proxy>
-static inline void
+static inline bool
apply_string (OT::hb_ot_apply_context_t *c,
const typename Proxy::Lookup &lookup,
const OT::hb_ot_layout_lookup_accelerator_t &accel)
{
+ bool ret = false;
hb_buffer_t *buffer = c->buffer;
if (unlikely (!buffer->len || !c->lookup_mask))
- return;
+ return ret;
c->set_lookup_props (lookup.get_props ());
@@ -1927,7 +1878,7 @@ apply_string (OT::hb_ot_apply_context_t *c,
buffer->clear_output ();
buffer->idx = 0;
- apply_forward (c, accel);
+ ret = apply_forward (c, accel);
if (!Proxy::always_inplace)
buffer->sync ();
@@ -1937,8 +1888,10 @@ apply_string (OT::hb_ot_apply_context_t *c,
/* in-place backward substitution/positioning */
assert (!buffer->have_output);
buffer->idx = buffer->len - 1;
- apply_backward (c, accel);
+ ret = apply_backward (c, accel);
}
+
+ return ret;
}
template <typename Proxy>
@@ -1957,23 +1910,42 @@ inline void hb_ot_map_t::apply (const Proxy &proxy,
const stage_map_t *stage = &stages[table_index][stage_index];
for (; i < stage->last_lookup; i++)
{
- unsigned int lookup_index = lookups[table_index][i].index;
- if (!buffer->message (font, "start lookup %d", lookup_index)) continue;
- c.set_lookup_index (lookup_index);
- c.set_lookup_mask (lookups[table_index][i].mask);
- c.set_auto_zwj (lookups[table_index][i].auto_zwj);
- c.set_auto_zwnj (lookups[table_index][i].auto_zwnj);
- c.set_random (lookups[table_index][i].random);
- c.set_per_syllable (lookups[table_index][i].per_syllable);
-
- apply_string<Proxy> (&c,
- proxy.table.get_lookup (lookup_index),
- proxy.accels[lookup_index]);
- (void) buffer->message (font, "end lookup %d", lookup_index);
+ auto &lookup = lookups[table_index][i];
+
+ unsigned int lookup_index = lookup.index;
+ if (!buffer->message (font, "start lookup %d feature '%c%c%c%c'", lookup_index, HB_UNTAG (lookup.feature_tag))) continue;
+
+ /* c.digest is a digest of all the current glyphs in the buffer
+ * (plus some past glyphs).
+ *
+ * Only try applying the lookup if there is any overlap. */
+ if (proxy.accels[lookup_index].digest.may_have (c.digest))
+ {
+ c.set_lookup_index (lookup_index);
+ c.set_lookup_mask (lookup.mask);
+ c.set_auto_zwj (lookup.auto_zwj);
+ c.set_auto_zwnj (lookup.auto_zwnj);
+ c.set_random (lookup.random);
+ c.set_per_syllable (lookup.per_syllable);
+
+ apply_string<Proxy> (&c,
+ proxy.table.get_lookup (lookup_index),
+ proxy.accels[lookup_index]);
+ }
+ else
+ (void) buffer->message (font, "skipped lookup %d feature '%c%c%c%c' because no glyph matches", lookup_index, HB_UNTAG (lookup.feature_tag));
+
+ (void) buffer->message (font, "end lookup %d feature '%c%c%c%c'", lookup_index, HB_UNTAG (lookup.feature_tag));
}
if (stage->pause_func)
- stage->pause_func (plan, font, buffer);
+ {
+ if (stage->pause_func (plan, font, buffer))
+ {
+ /* Refresh working buffer digest since buffer changed. */
+ c.digest = buffer->digest ();
+ }
+ }
}
}
diff --git a/thirdparty/harfbuzz/src/hb-ot-layout.hh b/thirdparty/harfbuzz/src/hb-ot-layout.hh
index de06610cb5..9505d5f147 100644
--- a/thirdparty/harfbuzz/src/hb-ot-layout.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-layout.hh
@@ -102,10 +102,6 @@ HB_INTERNAL void
hb_ot_layout_substitute_start (hb_font_t *font,
hb_buffer_t *buffer);
-HB_INTERNAL void
-hb_ot_layout_delete_glyphs_inplace (hb_buffer_t *buffer,
- bool (*filter) (const hb_glyph_info_t *info));
-
namespace OT {
struct hb_ot_apply_context_t;
struct hb_ot_layout_lookup_accelerator_t;
@@ -552,7 +548,7 @@ _hb_glyph_info_clear_substituted (hb_glyph_info_t *info)
info->glyph_props() &= ~(HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED);
}
-static inline void
+static inline bool
_hb_clear_substitution_flags (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_font_t *font HB_UNUSED,
hb_buffer_t *buffer)
@@ -561,6 +557,7 @@ _hb_clear_substitution_flags (const hb_ot_shape_plan_t *plan HB_UNUSED,
unsigned int count = buffer->len;
for (unsigned int i = 0; i < count; i++)
_hb_glyph_info_clear_substituted (&info[i]);
+ return false;
}
diff --git a/thirdparty/harfbuzz/src/hb-ot-map.cc b/thirdparty/harfbuzz/src/hb-ot-map.cc
index 39215b335f..8882dbaccb 100644
--- a/thirdparty/harfbuzz/src/hb-ot-map.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-map.cc
@@ -45,7 +45,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_)
{
- memset (this, 0, sizeof (*this));
+ hb_memset (this, 0, sizeof (*this));
feature_infos.init ();
for (unsigned int table_index = 0; table_index < 2; table_index++)
@@ -133,7 +133,8 @@ hb_ot_map_builder_t::add_lookups (hb_ot_map_t &m,
bool auto_zwnj,
bool auto_zwj,
bool random,
- bool per_syllable)
+ bool per_syllable,
+ hb_tag_t feature_tag)
{
unsigned int lookup_indices[32];
unsigned int offset, len;
@@ -162,6 +163,7 @@ hb_ot_map_builder_t::add_lookups (hb_ot_map_t &m,
lookup->auto_zwj = auto_zwj;
lookup->random = random;
lookup->per_syllable = per_syllable;
+ lookup->feature_tag = feature_tag;
}
offset += len;
@@ -212,24 +214,26 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m,
if (feature_infos.length)
{
feature_infos.qsort ();
+ auto *f = feature_infos.arrayZ;
unsigned int j = 0;
- for (unsigned int i = 1; i < feature_infos.length; i++)
- if (feature_infos[i].tag != feature_infos[j].tag)
- feature_infos[++j] = feature_infos[i];
+ unsigned count = feature_infos.length;
+ for (unsigned int i = 1; i < count; i++)
+ if (f[i].tag != f[j].tag)
+ f[++j] = f[i];
else {
- if (feature_infos[i].flags & F_GLOBAL) {
- feature_infos[j].flags |= F_GLOBAL;
- feature_infos[j].max_value = feature_infos[i].max_value;
- feature_infos[j].default_value = feature_infos[i].default_value;
+ if (f[i].flags & F_GLOBAL) {
+ f[j].flags |= F_GLOBAL;
+ f[j].max_value = f[i].max_value;
+ f[j].default_value = f[i].default_value;
} else {
- if (feature_infos[j].flags & F_GLOBAL)
- feature_infos[j].flags ^= F_GLOBAL;
- feature_infos[j].max_value = hb_max (feature_infos[j].max_value, feature_infos[i].max_value);
+ if (f[j].flags & F_GLOBAL)
+ f[j].flags ^= F_GLOBAL;
+ f[j].max_value = hb_max (f[j].max_value, f[i].max_value);
/* Inherit default_value from j */
}
- feature_infos[j].flags |= (feature_infos[i].flags & F_HAS_FALLBACK);
- feature_infos[j].stage[0] = hb_min (feature_infos[j].stage[0], feature_infos[i].stage[0]);
- feature_infos[j].stage[1] = hb_min (feature_infos[j].stage[1], feature_infos[i].stage[1]);
+ f[j].flags |= (f[i].flags & F_HAS_FALLBACK);
+ f[j].stage[0] = hb_min (f[j].stage[0], f[i].stage[0]);
+ f[j].stage[1] = hb_min (f[j].stage[1], f[i].stage[1]);
}
feature_infos.shrink (j + 1);
}
@@ -239,7 +243,8 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m,
static_assert ((!(HB_GLYPH_FLAG_DEFINED & (HB_GLYPH_FLAG_DEFINED + 1))), "");
unsigned int next_bit = hb_popcount (HB_GLYPH_FLAG_DEFINED) + 1;
- for (unsigned int i = 0; i < feature_infos.length; i++)
+ unsigned count = feature_infos.length;
+ for (unsigned int i = 0; i < count; i++)
{
const feature_info_t *info = &feature_infos[i];
@@ -308,7 +313,7 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m,
map->_1_mask = (1u << map->shift) & map->mask;
map->needs_fallback = !found;
}
- feature_infos.shrink (0); /* Done with these */
+ //feature_infos.shrink (0); /* Done with these */
add_gsub_pause (nullptr);
@@ -317,6 +322,7 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m,
for (unsigned int table_index = 0; table_index < 2; table_index++)
{
/* Collect lookup indices for features */
+ auto &lookups = m.lookups[table_index];
unsigned int stage_index = 0;
unsigned int last_num_lookups = 0;
@@ -329,36 +335,39 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m,
key.variations_index[table_index],
global_bit_mask);
- for (unsigned i = 0; i < m.features.length; i++)
- if (m.features[i].stage[table_index] == stage)
+ for (auto &feature : m.features)
+ {
+ if (feature.stage[table_index] == stage)
add_lookups (m, table_index,
- m.features[i].index[table_index],
+ feature.index[table_index],
key.variations_index[table_index],
- m.features[i].mask,
- m.features[i].auto_zwnj,
- m.features[i].auto_zwj,
- m.features[i].random,
- m.features[i].per_syllable);
+ feature.mask,
+ feature.auto_zwnj,
+ feature.auto_zwj,
+ feature.random,
+ feature.per_syllable,
+ feature.tag);
+ }
/* Sort lookups and merge duplicates */
- if (last_num_lookups < m.lookups[table_index].length)
+ if (last_num_lookups < lookups.length)
{
- m.lookups[table_index].qsort (last_num_lookups, m.lookups[table_index].length);
+ lookups.as_array ().sub_array (last_num_lookups, lookups.length - last_num_lookups).qsort ();
unsigned int j = last_num_lookups;
- for (unsigned int i = j + 1; i < m.lookups[table_index].length; i++)
- if (m.lookups[table_index][i].index != m.lookups[table_index][j].index)
- m.lookups[table_index][++j] = m.lookups[table_index][i];
+ for (unsigned int i = j + 1; i < lookups.length; i++)
+ if (lookups.arrayZ[i].index != lookups.arrayZ[j].index)
+ lookups.arrayZ[++j] = lookups.arrayZ[i];
else
{
- m.lookups[table_index][j].mask |= m.lookups[table_index][i].mask;
- m.lookups[table_index][j].auto_zwnj &= m.lookups[table_index][i].auto_zwnj;
- m.lookups[table_index][j].auto_zwj &= m.lookups[table_index][i].auto_zwj;
+ lookups.arrayZ[j].mask |= lookups.arrayZ[i].mask;
+ lookups.arrayZ[j].auto_zwnj &= lookups.arrayZ[i].auto_zwnj;
+ lookups.arrayZ[j].auto_zwj &= lookups.arrayZ[i].auto_zwj;
}
- m.lookups[table_index].shrink (j + 1);
+ lookups.shrink (j + 1);
}
- last_num_lookups = m.lookups[table_index].length;
+ last_num_lookups = lookups.length;
if (stage_index < stages[table_index].length && stages[table_index][stage_index].index == stage) {
hb_ot_map_t::stage_map_t *stage_map = m.stages[table_index].push ();
diff --git a/thirdparty/harfbuzz/src/hb-ot-map.hh b/thirdparty/harfbuzz/src/hb-ot-map.hh
index a7b5eec30d..efc8cae96a 100644
--- a/thirdparty/harfbuzz/src/hb-ot-map.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-map.hh
@@ -69,6 +69,7 @@ struct hb_ot_map_t
unsigned short random : 1;
unsigned short per_syllable : 1;
hb_mask_t mask;
+ hb_tag_t feature_tag;
HB_INTERNAL static int cmp (const void *pa, const void *pb)
{
@@ -78,7 +79,9 @@ struct hb_ot_map_t
}
};
- typedef void (*pause_func_t) (const struct hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer);
+ /* Pause functions return true if new glyph indices might have been
+ * added to the buffer. This is used to update buffer digest. */
+ typedef bool (*pause_func_t) (const struct hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer);
struct stage_map_t {
unsigned int last_lookup; /* Cumulative */
@@ -87,13 +90,13 @@ struct hb_ot_map_t
void init ()
{
- memset (this, 0, sizeof (*this));
+ hb_memset (this, 0, sizeof (*this));
- features.init ();
+ features.init0 ();
for (unsigned int table_index = 0; table_index < 2; table_index++)
{
- lookups[table_index].init ();
- stages[table_index].init ();
+ lookups[table_index].init0 ();
+ stages[table_index].init0 ();
}
}
void fini ()
@@ -239,7 +242,8 @@ struct hb_ot_map_builder_t
bool auto_zwnj = true,
bool auto_zwj = true,
bool random = false,
- bool per_syllable = false);
+ bool per_syllable = false,
+ hb_tag_t feature_tag = HB_TAG(' ',' ',' ',' '));
struct feature_info_t {
hb_tag_t tag;
diff --git a/thirdparty/harfbuzz/src/hb-ot-math-table.hh b/thirdparty/harfbuzz/src/hb-ot-math-table.hh
index d834d94371..93953370e2 100644
--- a/thirdparty/harfbuzz/src/hb-ot-math-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-math-table.hh
@@ -77,11 +77,11 @@ struct MathConstants
HBINT16 *p = c->allocate_size<HBINT16> (HBINT16::static_size * 2);
if (unlikely (!p)) return_trace (nullptr);
- memcpy (p, percentScaleDown, HBINT16::static_size * 2);
+ hb_memcpy (p, percentScaleDown, HBINT16::static_size * 2);
HBUINT16 *m = c->allocate_size<HBUINT16> (HBUINT16::static_size * 2);
if (unlikely (!m)) return_trace (nullptr);
- memcpy (m, minHeight, HBUINT16::static_size * 2);
+ hb_memcpy (m, minHeight, HBUINT16::static_size * 2);
unsigned count = ARRAY_LENGTH (mathValueRecords);
for (unsigned i = 0; i < count; i++)
@@ -786,7 +786,7 @@ struct MathGlyphAssembly
if (parts_count)
{
int64_t mult = font->dir_mult (direction);
- for (auto _ : hb_zip (partRecords.sub_array (start_offset, parts_count),
+ for (auto _ : hb_zip (partRecords.as_array ().sub_array (start_offset, parts_count),
hb_array (parts, *parts_count)))
_.first.extract (_.second, mult, font);
}
@@ -855,7 +855,7 @@ struct MathGlyphConstruction
if (variants_count)
{
int64_t mult = font->dir_mult (direction);
- for (auto _ : hb_zip (mathGlyphVariantRecord.sub_array (start_offset, variants_count),
+ for (auto _ : hb_zip (mathGlyphVariantRecord.as_array ().sub_array (start_offset, variants_count),
hb_array (variants, *variants_count)))
_.second = {_.first.variantGlyph, font->em_mult (_.first.advanceMeasurement, mult)};
}
diff --git a/thirdparty/harfbuzz/src/hb-ot-meta-table.hh b/thirdparty/harfbuzz/src/hb-ot-meta-table.hh
index 93e64c5327..e1b68bcf91 100644
--- a/thirdparty/harfbuzz/src/hb-ot-meta-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-meta-table.hh
@@ -84,7 +84,7 @@ struct meta
{
if (count)
{
- + table->dataMaps.sub_array (start_offset, count)
+ + table->dataMaps.as_array ().sub_array (start_offset, count)
| hb_map (&DataMap::get_tag)
| hb_map ([](hb_tag_t tag) { return (hb_ot_meta_tag_t) tag; })
| hb_sink (hb_array (entries, *count))
diff --git a/thirdparty/harfbuzz/src/hb-ot-name-table.hh b/thirdparty/harfbuzz/src/hb-ot-name-table.hh
index 1f2131ffcc..6f4461cc15 100644
--- a/thirdparty/harfbuzz/src/hb-ot-name-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-name-table.hh
@@ -30,10 +30,55 @@
#include "hb-open-type.hh"
#include "hb-ot-name-language.hh"
#include "hb-aat-layout.hh"
+#include "hb-utf.hh"
namespace OT {
+template <typename in_utf_t, typename out_utf_t>
+inline unsigned int
+hb_ot_name_convert_utf (hb_bytes_t bytes,
+ unsigned int *text_size /* IN/OUT */,
+ typename out_utf_t::codepoint_t *text /* OUT */)
+{
+ unsigned int src_len = bytes.length / sizeof (typename in_utf_t::codepoint_t);
+ const typename in_utf_t::codepoint_t *src = (const typename in_utf_t::codepoint_t *) bytes.arrayZ;
+ const typename in_utf_t::codepoint_t *src_end = src + src_len;
+
+ typename out_utf_t::codepoint_t *dst = text;
+
+ hb_codepoint_t unicode;
+ const hb_codepoint_t replacement = HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT;
+
+ if (text_size && *text_size)
+ {
+ (*text_size)--; /* Save room for NUL-termination. */
+ const typename out_utf_t::codepoint_t *dst_end = text + *text_size;
+
+ while (src < src_end && dst < dst_end)
+ {
+ const typename in_utf_t::codepoint_t *src_next = in_utf_t::next (src, src_end, &unicode, replacement);
+ typename out_utf_t::codepoint_t *dst_next = out_utf_t::encode (dst, dst_end, unicode);
+ if (dst_next == dst)
+ break; /* Out-of-room. */
+
+ dst = dst_next;
+ src = src_next;
+ }
+
+ *text_size = dst - text;
+ *dst = 0; /* NUL-terminate. */
+ }
+
+ /* Accumulate length of rest. */
+ unsigned int dst_len = dst - text;
+ while (src < src_end)
+ {
+ src = in_utf_t::next (src, src_end, &unicode, replacement);
+ dst_len += out_utf_t::encode_len (unicode);
+ }
+ return dst_len;
+}
#define entry_score var.u16[0]
#define entry_index var.u16[1]
@@ -97,12 +142,68 @@ struct NameRecord
return UNSUPPORTED;
}
- NameRecord* copy (hb_serialize_context_t *c, const void *base) const
+ NameRecord* copy (hb_serialize_context_t *c, const void *base
+#ifdef HB_EXPERIMENTAL_API
+ , const hb_hashmap_t<hb_ot_name_record_ids_t, hb_bytes_t> *name_table_overrides
+#endif
+ ) const
{
TRACE_SERIALIZE (this);
+ HB_UNUSED auto snap = c->snapshot ();
auto *out = c->embed (this);
if (unlikely (!out)) return_trace (nullptr);
- out->offset.serialize_copy (c, offset, base, 0, hb_serialize_context_t::Tail, length);
+#ifdef HB_EXPERIMENTAL_API
+ hb_ot_name_record_ids_t record_ids (platformID, encodingID, languageID, nameID);
+ hb_bytes_t* name_bytes;
+
+ if (name_table_overrides->has (record_ids, &name_bytes)) {
+ hb_bytes_t encoded_bytes = *name_bytes;
+ char *name_str_utf16_be = nullptr;
+
+ if (platformID != 1)
+ {
+ unsigned text_size = hb_ot_name_convert_utf<hb_utf8_t, hb_utf16_be_t> (*name_bytes, nullptr, nullptr);
+
+ text_size++; // needs to consider NULL terminator for use in hb_ot_name_convert_utf()
+ unsigned byte_len = text_size * hb_utf16_be_t::codepoint_t::static_size;
+ name_str_utf16_be = (char *) hb_calloc (byte_len, 1);
+ if (!name_str_utf16_be)
+ {
+ c->revert (snap);
+ return_trace (nullptr);
+ }
+ hb_ot_name_convert_utf<hb_utf8_t, hb_utf16_be_t> (*name_bytes, &text_size,
+ (hb_utf16_be_t::codepoint_t *) name_str_utf16_be);
+
+ unsigned encoded_byte_len = text_size * hb_utf16_be_t::codepoint_t::static_size;
+ if (!encoded_byte_len || !c->check_assign (out->length, encoded_byte_len, HB_SERIALIZE_ERROR_INT_OVERFLOW)) {
+ c->revert (snap);
+ hb_free (name_str_utf16_be);
+ return_trace (nullptr);
+ }
+
+ encoded_bytes = hb_bytes_t (name_str_utf16_be, encoded_byte_len);
+ }
+ else
+ {
+ // mac platform, copy the UTF-8 string(all ascii characters) as is
+ if (!c->check_assign (out->length, encoded_bytes.length, HB_SERIALIZE_ERROR_INT_OVERFLOW)) {
+ c->revert (snap);
+ return_trace (nullptr);
+ }
+ }
+
+ out->offset = 0;
+ c->push ();
+ encoded_bytes.copy (c);
+ c->add_link (out->offset, c->pop_pack (), hb_serialize_context_t::Tail, 0);
+ hb_free (name_str_utf16_be);
+ }
+ else
+#endif
+ {
+ out->offset.serialize_copy (c, offset, base, 0, hb_serialize_context_t::Tail, length);
+ }
return_trace (out);
}
@@ -216,29 +317,61 @@ struct name
hb_requires (hb_is_source_of (Iterator, const NameRecord &))>
bool serialize (hb_serialize_context_t *c,
Iterator it,
- const void *src_string_pool)
+ const void *src_string_pool
+#ifdef HB_EXPERIMENTAL_API
+ , const hb_vector_t<hb_ot_name_record_ids_t>& insert_name_records
+ , const hb_hashmap_t<hb_ot_name_record_ids_t, hb_bytes_t> *name_table_overrides
+#endif
+ )
{
TRACE_SERIALIZE (this);
if (unlikely (!c->extend_min ((*this)))) return_trace (false);
+ unsigned total_count = it.len ()
+#ifdef HB_EXPERIMENTAL_API
+ + insert_name_records.length
+#endif
+ ;
this->format = 0;
- this->count = it.len ();
+ if (!c->check_assign (this->count, total_count, HB_SERIALIZE_ERROR_INT_OVERFLOW))
+ return false;
- NameRecord *name_records = (NameRecord *) hb_calloc (it.len (), NameRecord::static_size);
+ NameRecord *name_records = (NameRecord *) hb_calloc (total_count, NameRecord::static_size);
if (unlikely (!name_records)) return_trace (false);
- hb_array_t<NameRecord> records (name_records, it.len ());
+ hb_array_t<NameRecord> records (name_records, total_count);
for (const NameRecord& record : it)
{
+ hb_memcpy (name_records, &record, NameRecord::static_size);
+ name_records++;
+ }
+
+#ifdef HB_EXPERIMENTAL_API
+ for (unsigned i = 0; i < insert_name_records.length; i++)
+ {
+ const hb_ot_name_record_ids_t& ids = insert_name_records[i];
+ NameRecord record;
+ record.platformID = ids.platform_id;
+ record.encodingID = ids.encoding_id;
+ record.languageID = ids.language_id;
+ record.nameID = ids.name_id;
+ record.length = 0; // handled in NameRecord copy()
+ record.offset = 0;
memcpy (name_records, &record, NameRecord::static_size);
name_records++;
}
+#endif
records.qsort ();
- c->copy_all (records, src_string_pool);
+ c->copy_all (records,
+ src_string_pool
+#ifdef HB_EXPERIMENTAL_API
+ , name_table_overrides
+#endif
+ );
hb_free (records.arrayZ);
@@ -256,6 +389,11 @@ struct name
name *name_prime = c->serializer->start_embed<name> ();
if (unlikely (!name_prime)) return_trace (false);
+#ifdef HB_EXPERIMENTAL_API
+ const hb_hashmap_t<hb_ot_name_record_ids_t, hb_bytes_t> *name_table_overrides =
+ c->plan->name_table_overrides;
+#endif
+
auto it =
+ nameRecordZ.as_array (count)
| hb_filter (c->plan->name_ids, &NameRecord::nameID)
@@ -265,10 +403,48 @@ struct name
(c->plan->flags & HB_SUBSET_FLAGS_NAME_LEGACY)
|| namerecord.isUnicode ();
})
+#ifdef HB_EXPERIMENTAL_API
+ | hb_filter ([&] (const NameRecord& namerecord) {
+ if (name_table_overrides->is_empty ())
+ return true;
+ hb_ot_name_record_ids_t rec_ids (namerecord.platformID,
+ namerecord.encodingID,
+ namerecord.languageID,
+ namerecord.nameID);
+
+ hb_bytes_t *p;
+ if (name_table_overrides->has (rec_ids, &p) &&
+ (*p).length == 0)
+ return false;
+ return true;
+ })
+#endif
;
- name_prime->serialize (c->serializer, it, std::addressof (this + stringOffset));
- return_trace (name_prime->count);
+#ifdef HB_EXPERIMENTAL_API
+ hb_vector_t<hb_ot_name_record_ids_t> insert_name_records;
+ if (!name_table_overrides->is_empty ())
+ {
+ if (unlikely (!insert_name_records.alloc (name_table_overrides->get_population ())))
+ return_trace (false);
+ for (const auto& record_ids : name_table_overrides->keys ())
+ {
+ if (name_table_overrides->get (record_ids).length == 0)
+ continue;
+ if (has_name_record_with_ids (record_ids))
+ continue;
+ insert_name_records.push (record_ids);
+ }
+ }
+#endif
+
+ return (name_prime->serialize (c->serializer, it,
+ std::addressof (this + stringOffset)
+#ifdef HB_EXPERIMENTAL_API
+ , insert_name_records
+ , name_table_overrides
+#endif
+ ));
}
bool sanitize_records (hb_sanitize_context_t *c) const
@@ -378,6 +554,23 @@ struct name
hb_vector_t<hb_ot_name_entry_t> names;
};
+ private:
+ // sometimes NameRecords are not sorted in the font file, so use linear search
+ // here
+ bool has_name_record_with_ids (const hb_ot_name_record_ids_t& record_ids) const
+ {
+ for (const auto& record : nameRecordZ.as_array (count))
+ {
+ if (record.platformID == record_ids.platform_id &&
+ record.encodingID == record_ids.encoding_id &&
+ record.languageID == record_ids.language_id &&
+ record.nameID == record_ids.name_id)
+ return true;
+ }
+ return false;
+ }
+
+ public:
/* We only implement format 0 for now. */
HBUINT16 format; /* Format selector (=0/1). */
HBUINT16 count; /* Number of name records. */
diff --git a/thirdparty/harfbuzz/src/hb-ot-name.cc b/thirdparty/harfbuzz/src/hb-ot-name.cc
index c35ac5b3dc..6adf1e8fbe 100644
--- a/thirdparty/harfbuzz/src/hb-ot-name.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-name.cc
@@ -64,52 +64,6 @@ hb_ot_name_list_names (hb_face_t *face,
return (const hb_ot_name_entry_t *) name.names;
}
-
-template <typename in_utf_t, typename out_utf_t>
-static inline unsigned int
-hb_ot_name_convert_utf (hb_bytes_t bytes,
- unsigned int *text_size /* IN/OUT */,
- typename out_utf_t::codepoint_t *text /* OUT */)
-{
- unsigned int src_len = bytes.length / sizeof (typename in_utf_t::codepoint_t);
- const typename in_utf_t::codepoint_t *src = (const typename in_utf_t::codepoint_t *) bytes.arrayZ;
- const typename in_utf_t::codepoint_t *src_end = src + src_len;
-
- typename out_utf_t::codepoint_t *dst = text;
-
- hb_codepoint_t unicode;
- const hb_codepoint_t replacement = HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT;
-
- if (text_size && *text_size)
- {
- (*text_size)--; /* Same room for NUL-termination. */
- const typename out_utf_t::codepoint_t *dst_end = text + *text_size;
-
- while (src < src_end && dst < dst_end)
- {
- const typename in_utf_t::codepoint_t *src_next = in_utf_t::next (src, src_end, &unicode, replacement);
- typename out_utf_t::codepoint_t *dst_next = out_utf_t::encode (dst, dst_end, unicode);
- if (dst_next == dst)
- break; /* Out-of-room. */
-
- dst = dst_next;
- src = src_next;
- }
-
- *text_size = dst - text;
- *dst = 0; /* NUL-terminate. */
- }
-
- /* Accumulate length of rest. */
- unsigned int dst_len = dst - text;
- while (src < src_end)
- {
- src = in_utf_t::next (src, src_end, &unicode, replacement);
- dst_len += out_utf_t::encode_len (unicode);
- }
- return dst_len;
-}
-
template <typename utf_t>
static inline unsigned int
hb_ot_name_get_utf (hb_face_t *face,
@@ -130,10 +84,10 @@ hb_ot_name_get_utf (hb_face_t *face,
hb_bytes_t bytes = name.get_name (idx);
if (width == 2) /* UTF16-BE */
- return hb_ot_name_convert_utf<hb_utf16_be_t, utf_t> (bytes, text_size, text);
+ return OT::hb_ot_name_convert_utf<hb_utf16_be_t, utf_t> (bytes, text_size, text);
if (width == 1) /* ASCII */
- return hb_ot_name_convert_utf<hb_ascii_t, utf_t> (bytes, text_size, text);
+ return OT::hb_ot_name_convert_utf<hb_ascii_t, utf_t> (bytes, text_size, text);
}
if (text_size)
@@ -227,5 +181,4 @@ hb_ot_name_get_utf32 (hb_face_t *face,
return hb_ot_name_get_utf<hb_utf32_t> (face, name_id, language, text_size, text);
}
-
#endif
diff --git a/thirdparty/harfbuzz/src/hb-ot-os2-table.hh b/thirdparty/harfbuzz/src/hb-ot-os2-table.hh
index c6e8fad6fc..5b017d56a6 100644
--- a/thirdparty/harfbuzz/src/hb-ot-os2-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-os2-table.hh
@@ -212,17 +212,6 @@ struct OS2
TRACE_SUBSET (this);
OS2 *os2_prime = c->serializer->embed (this);
if (unlikely (!os2_prime)) return_trace (false);
- if (c->plan->flags & HB_SUBSET_FLAGS_NO_PRUNE_UNICODE_RANGES)
- return_trace (true);
-
- /* when --gids option is not used, no need to do collect_mapping that is
- * iterating all codepoints in each subtable, which is not efficient */
- uint16_t min_cp, max_cp;
- find_min_and_max_codepoint (c->plan->unicodes, &min_cp, &max_cp);
- os2_prime->usFirstCharIndex = min_cp;
- os2_prime->usLastCharIndex = max_cp;
-
- _update_unicode_ranges (c->plan->unicodes, os2_prime->ulUnicodeRange);
if (c->plan->user_axes_location->has (HB_TAG ('w','g','h','t')) &&
!c->plan->pinned_at_default)
@@ -244,6 +233,18 @@ struct OS2
return_trace (false);
}
+ if (c->plan->flags & HB_SUBSET_FLAGS_NO_PRUNE_UNICODE_RANGES)
+ return_trace (true);
+
+ /* when --gids option is not used, no need to do collect_mapping that is
+ * iterating all codepoints in each subtable, which is not efficient */
+ uint16_t min_cp, max_cp;
+ find_min_and_max_codepoint (c->plan->unicodes, &min_cp, &max_cp);
+ os2_prime->usFirstCharIndex = min_cp;
+ os2_prime->usLastCharIndex = max_cp;
+
+ _update_unicode_ranges (c->plan->unicodes, os2_prime->ulUnicodeRange);
+
return_trace (true);
}
diff --git a/thirdparty/harfbuzz/src/hb-ot-post-table-v2subset.hh b/thirdparty/harfbuzz/src/hb-ot-post-table-v2subset.hh
index 4d427e5431..951e6395d6 100644
--- a/thirdparty/harfbuzz/src/hb-ot-post-table-v2subset.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-post-table-v2subset.hh
@@ -78,14 +78,14 @@ 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, true> glyph_name_to_new_index;
+ hb_hashmap_t<hb_bytes_t, uint32_t, 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;
+ const uint32_t *new_index2;
if (old_index <= 257) new_index = old_index;
else if (old_new_index_map.has (old_index, &new_index2))
{
diff --git a/thirdparty/harfbuzz/src/hb-ot-post-table.hh b/thirdparty/harfbuzz/src/hb-ot-post-table.hh
index 59c1de3784..a04b80357b 100644
--- a/thirdparty/harfbuzz/src/hb-ot-post-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-post-table.hh
@@ -84,7 +84,7 @@ struct post
post *post_prime = c->allocate_min<post> ();
if (unlikely (!post_prime)) return_trace (false);
- memcpy (post_prime, this, post::min_size);
+ hb_memcpy (post_prime, this, post::min_size);
if (!glyph_names)
return_trace (c->check_assign (post_prime->version.major, 3,
HB_SERIALIZE_ERROR_INT_OVERFLOW)); // Version 3 does not have any glyph names.
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-normalize.cc b/thirdparty/harfbuzz/src/hb-ot-shape-normalize.cc
index 7db0b25b73..897377aa15 100644
--- a/thirdparty/harfbuzz/src/hb-ot-shape-normalize.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-shape-normalize.cc
@@ -341,7 +341,7 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan,
{
unsigned int end;
for (end = buffer->idx + 1; end < count; end++)
- if (unlikely (_hb_glyph_info_is_unicode_mark (&buffer->info[end])))
+ if (_hb_glyph_info_is_unicode_mark (&buffer->info[end]))
break;
if (end < count)
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape.cc b/thirdparty/harfbuzz/src/hb-ot-shape.cc
index 249b5a864c..bbdfc214a1 100644
--- a/thirdparty/harfbuzz/src/hb-ot-shape.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-shape.cc
@@ -91,9 +91,11 @@ hb_ot_shape_planner_t::hb_ot_shape_planner_t (hb_face_t *fac
script_zero_marks = shaper->zero_width_marks != HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE;
script_fallback_mark_positioning = shaper->fallback_position;
+#ifndef HB_NO_AAT_SHAPE
/* https://github.com/harfbuzz/harfbuzz/issues/1528 */
if (apply_morx && shaper != &_hb_ot_shaper_default)
shaper = &_hb_ot_shaper_dumber;
+#endif
}
void
@@ -864,7 +866,7 @@ hb_ot_hide_default_ignorables (hb_buffer_t *buffer,
}
}
else
- hb_ot_layout_delete_glyphs_inplace (buffer, _hb_glyph_info_is_default_ignorable);
+ buffer->delete_glyphs_inplace (_hb_glyph_info_is_default_ignorable);
}
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape.hh b/thirdparty/harfbuzz/src/hb-ot-shape.hh
index cd6f15cbe2..ace28602f6 100644
--- a/thirdparty/harfbuzz/src/hb-ot-shape.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-shape.hh
@@ -51,7 +51,7 @@ struct hb_ot_shape_plan_key_t
bool equal (const hb_ot_shape_plan_key_t *other)
{
- return 0 == memcmp (this, other, sizeof (*this));
+ return 0 == hb_memcmp (this, other, sizeof (*this));
}
};
diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-arabic.cc b/thirdparty/harfbuzz/src/hb-ot-shaper-arabic.cc
index ed2748b828..2332ae3697 100644
--- a/thirdparty/harfbuzz/src/hb-ot-shaper-arabic.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-shaper-arabic.cc
@@ -161,22 +161,23 @@ static const struct arabic_state_table_entry {
};
-static void
+static bool
arabic_fallback_shape (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer);
-static void
+static bool
record_stch (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer);
-static void
+static bool
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);
+ return false;
}
static void
@@ -412,19 +413,19 @@ setup_masks_arabic (const hb_ot_shape_plan_t *plan,
setup_masks_arabic_plan (arabic_plan, buffer, plan->props.script);
}
-static void
+static bool
arabic_fallback_shape (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer)
{
#ifdef HB_NO_OT_SHAPER_ARABIC_FALLBACK
- return;
+ return false;
#endif
const arabic_shape_plan_t *arabic_plan = (const arabic_shape_plan_t *) plan->data;
if (!arabic_plan->do_fallback)
- return;
+ return false;
retry:
arabic_fallback_plan_t *fallback_plan = arabic_plan->fallback_plan;
@@ -440,6 +441,7 @@ retry:
}
arabic_fallback_plan_shape (fallback_plan, font, buffer);
+ return true;
}
/*
@@ -450,14 +452,14 @@ retry:
* marks can use it as well.
*/
-static void
+static bool
record_stch (const hb_ot_shape_plan_t *plan,
hb_font_t *font HB_UNUSED,
hb_buffer_t *buffer)
{
const arabic_shape_plan_t *arabic_plan = (const arabic_shape_plan_t *) plan->data;
if (!arabic_plan->has_stch)
- return;
+ return false;
/* 'stch' feature was just applied. Look for anything that multiplied,
* and record it for stch treatment later. Note that rtlm, frac, etc
@@ -473,6 +475,7 @@ record_stch (const hb_ot_shape_plan_t *plan,
info[i].arabic_shaping_action() = comp % 2 ? STCH_REPEATING : STCH_FIXED;
buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_ARABIC_HAS_STCH;
}
+ return false;
}
static void
diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-default.cc b/thirdparty/harfbuzz/src/hb-ot-shaper-default.cc
index 2f6f499eec..f0404a4d2c 100644
--- a/thirdparty/harfbuzz/src/hb-ot-shaper-default.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-shaper-default.cc
@@ -49,6 +49,7 @@ const hb_ot_shaper_t _hb_ot_shaper_default =
true, /* fallback_position */
};
+#ifndef HB_NO_AAT_SHAPE
/* Same as default but no mark advance zeroing / fallback positioning.
* Dumbest shaper ever, basically. */
const hb_ot_shaper_t _hb_ot_shaper_dumber =
@@ -68,6 +69,7 @@ const hb_ot_shaper_t _hb_ot_shaper_dumber =
HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE,
false, /* fallback_position */
};
+#endif
#endif
diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-indic-machine.hh b/thirdparty/harfbuzz/src/hb-ot-shaper-indic-machine.hh
index d52b13f616..d6c67b81bd 100644
--- a/thirdparty/harfbuzz/src/hb-ot-shaper-indic-machine.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-shaper-indic-machine.hh
@@ -53,7 +53,7 @@ enum indic_syllable_type_t {
};
-#line 57 "hb-ot-shaper-indic-machine.hh"
+#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
@@ -61,6 +61,7 @@ enum indic_syllable_type_t {
#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_MPst 13u
#define indic_syllable_machine_ex_N 3u
#define indic_syllable_machine_ex_PLACEHOLDER 10u
#define indic_syllable_machine_ex_RS 12u
@@ -75,268 +76,302 @@ enum indic_syllable_type_t {
#define indic_syllable_machine_ex_ZWNJ 5u
-#line 79 "hb-ot-shaper-indic-machine.hh"
+#line 75 "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
+ 8u, 8u, 4u, 13u, 5u, 13u, 5u, 13u, 13u, 13u, 4u, 13u, 4u, 13u, 4u, 13u,
+ 8u, 8u, 5u, 13u, 5u, 13u, 13u, 13u, 4u, 13u, 4u, 13u, 4u, 13u, 4u, 13u,
+ 8u, 8u, 5u, 13u, 5u, 13u, 13u, 13u, 4u, 13u, 4u, 13u, 4u, 13u, 8u, 8u,
+ 5u, 13u, 5u, 13u, 13u, 13u, 4u, 13u, 4u, 13u, 5u, 13u, 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, 13u, 4u, 13u, 5u, 13u, 5u, 13u, 4u, 13u,
+ 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, 13u, 4u, 13u, 5u, 13u, 5u, 13u, 4u, 13u, 5u, 9u,
+ 5u, 9u, 3u, 9u, 5u, 9u, 3u, 16u, 3u, 16u, 4u, 13u, 3u, 16u, 3u, 16u,
+ 4u, 16u, 1u, 15u, 3u, 16u, 1u, 15u, 5u, 9u, 9u, 9u, 5u, 9u, 1u, 15u,
+ 1u, 15u, 3u, 13u, 4u, 13u, 5u, 13u, 5u, 13u, 3u, 16u, 4u, 13u, 5u, 9u,
+ 5u, 9u, 3u, 9u, 5u, 9u, 3u, 16u, 4u, 13u, 4u, 13u, 3u, 16u, 3u, 16u,
+ 4u, 16u, 1u, 15u, 3u, 16u, 1u, 15u, 5u, 9u, 9u, 9u, 5u, 9u, 1u, 15u,
+ 1u, 15u, 3u, 13u, 4u, 13u, 5u, 13u, 5u, 13u, 3u, 16u, 4u, 13u, 5u, 9u,
+ 5u, 9u, 3u, 9u, 5u, 9u, 1u, 16u, 3u, 16u, 1u, 16u, 4u, 13u, 5u, 13u,
+ 5u, 13u, 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
+ 1, 10, 9, 9, 1, 10, 10, 10,
+ 1, 9, 9, 1, 10, 10, 10, 10,
+ 1, 9, 9, 1, 10, 10, 10, 1,
+ 9, 9, 1, 10, 10, 9, 1, 18,
+ 14, 14, 13, 15, 5, 5, 1, 5,
+ 15, 15, 15, 11, 10, 9, 9, 10,
+ 5, 7, 5, 14, 14, 14, 14, 13,
+ 15, 14, 14, 13, 15, 5, 1, 5,
+ 15, 15, 11, 10, 9, 9, 10, 5,
+ 5, 7, 5, 14, 14, 10, 14, 14,
+ 13, 15, 14, 15, 5, 1, 5, 15,
+ 15, 11, 10, 9, 9, 14, 10, 5,
+ 5, 7, 5, 14, 10, 10, 14, 14,
+ 13, 15, 14, 15, 5, 1, 5, 15,
+ 15, 11, 10, 9, 9, 14, 10, 5,
+ 5, 7, 5, 16, 14, 16, 10, 9,
+ 9, 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
+ 0, 2, 13, 23, 33, 35, 46, 57,
+ 68, 70, 80, 90, 92, 103, 114, 125,
+ 136, 138, 148, 158, 160, 171, 182, 193,
+ 195, 205, 215, 217, 228, 239, 249, 251,
+ 270, 285, 300, 314, 330, 336, 342, 344,
+ 350, 366, 382, 398, 410, 421, 431, 441,
+ 452, 458, 466, 472, 487, 502, 517, 532,
+ 546, 562, 577, 592, 606, 622, 628, 630,
+ 636, 652, 668, 680, 691, 701, 711, 722,
+ 728, 734, 742, 748, 763, 778, 789, 804,
+ 819, 833, 849, 864, 880, 886, 888, 894,
+ 910, 926, 938, 949, 959, 969, 984, 995,
+ 1001, 1007, 1015, 1021, 1036, 1047, 1058, 1073,
+ 1088, 1102, 1118, 1133, 1149, 1155, 1157, 1163,
+ 1179, 1195, 1207, 1218, 1228, 1238, 1253, 1264,
+ 1270, 1276, 1284, 1290, 1307, 1322, 1339, 1350,
+ 1360, 1370, 1372, 1378, 1394, 1402, 1408, 1414,
+ 1416, 1422
};
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
+ 1, 0, 2, 3, 3, 4, 5, 0,
+ 0, 0, 0, 4, 0, 3, 3, 4,
+ 6, 0, 0, 0, 0, 4, 0, 3,
+ 3, 4, 5, 0, 0, 0, 0, 4,
+ 0, 4, 0, 7, 3, 3, 4, 5,
+ 0, 0, 0, 0, 4, 0, 2, 3,
+ 3, 4, 5, 0, 0, 0, 8, 4,
+ 0, 10, 11, 11, 12, 13, 9, 9,
+ 9, 9, 12, 9, 14, 9, 11, 11,
+ 12, 15, 9, 9, 9, 9, 12, 9,
+ 11, 11, 12, 13, 9, 9, 9, 9,
+ 12, 9, 12, 9, 16, 11, 11, 12,
+ 13, 9, 9, 9, 9, 12, 9, 10,
+ 11, 11, 12, 13, 9, 9, 9, 17,
+ 12, 9, 10, 11, 11, 12, 13, 9,
+ 9, 9, 18, 12, 9, 20, 21, 21,
+ 22, 23, 19, 19, 19, 24, 22, 19,
+ 25, 19, 21, 21, 22, 27, 26, 26,
+ 26, 26, 22, 26, 21, 21, 22, 23,
+ 19, 19, 19, 19, 22, 19, 22, 26,
+ 20, 21, 21, 22, 23, 19, 19, 19,
+ 19, 22, 19, 28, 21, 21, 22, 23,
+ 19, 19, 19, 19, 22, 19, 30, 31,
+ 31, 32, 33, 29, 29, 29, 34, 32,
+ 29, 35, 29, 31, 31, 32, 36, 29,
+ 29, 29, 29, 32, 29, 31, 31, 32,
+ 33, 29, 29, 29, 29, 32, 29, 32,
+ 29, 30, 31, 31, 32, 33, 29, 29,
+ 29, 29, 32, 29, 37, 31, 31, 32,
+ 33, 29, 29, 29, 29, 32, 29, 21,
+ 21, 22, 38, 0, 0, 0, 0, 22,
+ 0, 40, 39, 42, 43, 44, 45, 46,
+ 47, 22, 23, 48, 49, 49, 24, 22,
+ 50, 51, 52, 53, 54, 41, 56, 57,
+ 58, 59, 4, 5, 60, 55, 55, 8,
+ 4, 55, 55, 61, 55, 62, 57, 63,
+ 63, 4, 5, 60, 55, 55, 55, 4,
+ 55, 55, 61, 55, 57, 63, 63, 4,
+ 5, 60, 55, 55, 55, 4, 55, 55,
+ 61, 55, 42, 55, 55, 55, 64, 65,
+ 55, 1, 60, 55, 55, 55, 55, 55,
+ 42, 55, 66, 66, 55, 1, 60, 55,
+ 60, 55, 55, 67, 60, 55, 60, 55,
+ 60, 55, 55, 55, 60, 55, 42, 55,
+ 68, 55, 66, 66, 55, 1, 60, 55,
+ 55, 55, 55, 55, 42, 55, 42, 55,
+ 55, 55, 66, 66, 55, 1, 60, 55,
+ 55, 55, 55, 55, 42, 55, 42, 55,
+ 55, 55, 66, 65, 55, 1, 60, 55,
+ 55, 55, 55, 55, 42, 55, 69, 70,
+ 71, 71, 4, 5, 60, 55, 55, 55,
+ 4, 55, 70, 71, 71, 4, 5, 60,
+ 55, 55, 55, 4, 55, 71, 71, 4,
+ 5, 60, 55, 55, 55, 4, 55, 60,
+ 55, 55, 67, 60, 55, 55, 55, 4,
+ 55, 72, 73, 73, 4, 5, 60, 55,
+ 55, 55, 4, 55, 64, 74, 55, 1,
+ 60, 55, 64, 55, 66, 66, 55, 1,
+ 60, 55, 66, 74, 55, 1, 60, 55,
+ 56, 57, 63, 63, 4, 5, 60, 55,
+ 55, 55, 4, 55, 55, 61, 55, 56,
+ 57, 58, 63, 4, 5, 60, 55, 55,
+ 8, 4, 55, 55, 61, 55, 76, 77,
+ 78, 79, 12, 13, 80, 75, 75, 18,
+ 12, 75, 75, 81, 75, 82, 77, 83,
+ 79, 12, 13, 80, 75, 75, 75, 12,
+ 75, 75, 81, 75, 77, 83, 79, 12,
+ 13, 80, 75, 75, 75, 12, 75, 75,
+ 81, 75, 84, 75, 75, 75, 85, 86,
+ 75, 14, 80, 75, 75, 75, 75, 75,
+ 84, 75, 87, 77, 88, 89, 12, 13,
+ 80, 75, 75, 17, 12, 75, 75, 81,
+ 75, 90, 77, 83, 83, 12, 13, 80,
+ 75, 75, 75, 12, 75, 75, 81, 75,
+ 77, 83, 83, 12, 13, 80, 75, 75,
+ 75, 12, 75, 75, 81, 75, 84, 75,
+ 75, 75, 91, 86, 75, 14, 80, 75,
+ 75, 75, 75, 75, 84, 75, 80, 75,
+ 75, 92, 80, 75, 80, 75, 80, 75,
+ 75, 75, 80, 75, 84, 75, 93, 75,
+ 91, 91, 75, 14, 80, 75, 75, 75,
+ 75, 75, 84, 75, 84, 75, 75, 75,
+ 91, 91, 75, 14, 80, 75, 75, 75,
+ 75, 75, 84, 75, 94, 95, 96, 96,
+ 12, 13, 80, 75, 75, 75, 12, 75,
+ 95, 96, 96, 12, 13, 80, 75, 75,
+ 75, 12, 75, 96, 96, 12, 13, 80,
+ 75, 75, 75, 12, 75, 80, 75, 75,
+ 92, 80, 75, 75, 75, 12, 75, 97,
+ 98, 98, 12, 13, 80, 75, 75, 75,
+ 12, 75, 85, 99, 75, 14, 80, 75,
+ 91, 91, 75, 14, 80, 75, 85, 75,
+ 91, 91, 75, 14, 80, 75, 91, 99,
+ 75, 14, 80, 75, 87, 77, 83, 83,
+ 12, 13, 80, 75, 75, 75, 12, 75,
+ 75, 81, 75, 87, 77, 88, 83, 12,
+ 13, 80, 75, 75, 17, 12, 75, 75,
+ 81, 75, 10, 11, 11, 12, 13, 75,
+ 75, 75, 75, 12, 75, 76, 77, 83,
+ 79, 12, 13, 80, 75, 75, 75, 12,
+ 75, 75, 81, 75, 101, 45, 102, 102,
+ 22, 23, 48, 100, 100, 100, 22, 100,
+ 100, 52, 100, 45, 102, 102, 22, 23,
+ 48, 100, 100, 100, 22, 100, 100, 52,
+ 100, 103, 100, 100, 100, 104, 105, 100,
+ 25, 48, 100, 100, 100, 100, 100, 103,
+ 100, 44, 45, 106, 107, 22, 23, 48,
+ 100, 100, 24, 22, 100, 100, 52, 100,
+ 103, 100, 100, 100, 108, 105, 100, 25,
+ 48, 100, 100, 100, 100, 100, 103, 100,
+ 48, 100, 100, 109, 48, 100, 48, 100,
+ 48, 100, 100, 100, 48, 100, 103, 100,
+ 110, 100, 108, 108, 100, 25, 48, 100,
+ 100, 100, 100, 100, 103, 100, 103, 100,
+ 100, 100, 108, 108, 100, 25, 48, 100,
+ 100, 100, 100, 100, 103, 100, 111, 112,
+ 113, 113, 22, 23, 48, 100, 100, 100,
+ 22, 100, 112, 113, 113, 22, 23, 48,
+ 100, 100, 100, 22, 100, 113, 113, 22,
+ 23, 48, 100, 100, 100, 22, 100, 48,
+ 100, 100, 109, 48, 100, 100, 100, 22,
+ 100, 44, 45, 102, 102, 22, 23, 48,
+ 100, 100, 100, 22, 100, 100, 52, 100,
+ 114, 115, 115, 22, 23, 48, 100, 100,
+ 100, 22, 100, 104, 116, 100, 25, 48,
+ 100, 108, 108, 100, 25, 48, 100, 104,
+ 100, 108, 108, 100, 25, 48, 100, 108,
+ 116, 100, 25, 48, 100, 44, 45, 106,
+ 102, 22, 23, 48, 100, 100, 24, 22,
+ 100, 100, 52, 100, 20, 21, 21, 22,
+ 23, 117, 117, 117, 24, 22, 117, 20,
+ 21, 21, 22, 23, 117, 117, 117, 117,
+ 22, 117, 119, 120, 121, 122, 32, 33,
+ 123, 118, 118, 34, 32, 118, 118, 124,
+ 118, 125, 120, 122, 122, 32, 33, 123,
+ 118, 118, 118, 32, 118, 118, 124, 118,
+ 120, 122, 122, 32, 33, 123, 118, 118,
+ 118, 32, 118, 118, 124, 118, 126, 118,
+ 118, 118, 127, 128, 118, 35, 123, 118,
+ 118, 118, 118, 118, 126, 118, 119, 120,
+ 121, 49, 32, 33, 123, 118, 118, 34,
+ 32, 118, 118, 124, 118, 126, 118, 118,
+ 118, 129, 128, 118, 35, 123, 118, 118,
+ 118, 118, 118, 126, 118, 123, 118, 118,
+ 130, 123, 118, 123, 118, 123, 118, 118,
+ 118, 123, 118, 126, 118, 131, 118, 129,
+ 129, 118, 35, 123, 118, 118, 118, 118,
+ 118, 126, 118, 126, 118, 118, 118, 129,
+ 129, 118, 35, 123, 118, 118, 118, 118,
+ 118, 126, 118, 132, 133, 134, 134, 32,
+ 33, 123, 118, 118, 118, 32, 118, 133,
+ 134, 134, 32, 33, 123, 118, 118, 118,
+ 32, 118, 134, 134, 32, 33, 123, 118,
+ 118, 118, 32, 118, 123, 118, 118, 130,
+ 123, 118, 118, 118, 32, 118, 119, 120,
+ 122, 122, 32, 33, 123, 118, 118, 118,
+ 32, 118, 118, 124, 118, 135, 136, 136,
+ 32, 33, 123, 118, 118, 118, 32, 118,
+ 127, 137, 118, 35, 123, 118, 129, 129,
+ 118, 35, 123, 118, 127, 118, 129, 129,
+ 118, 35, 123, 118, 129, 137, 118, 35,
+ 123, 118, 42, 43, 44, 45, 106, 102,
+ 22, 23, 48, 49, 49, 24, 22, 100,
+ 42, 52, 100, 56, 138, 58, 59, 4,
+ 5, 60, 55, 55, 8, 4, 55, 55,
+ 61, 55, 42, 43, 44, 45, 139, 140,
+ 22, 141, 142, 55, 49, 24, 22, 55,
+ 42, 52, 55, 20, 143, 143, 22, 141,
+ 60, 55, 55, 24, 22, 55, 60, 55,
+ 55, 67, 60, 55, 55, 55, 22, 55,
+ 142, 55, 55, 144, 142, 55, 55, 55,
+ 22, 55, 142, 55, 142, 55, 55, 55,
+ 142, 55, 42, 55, 68, 20, 143, 143,
+ 22, 141, 60, 55, 55, 55, 22, 55,
+ 42, 55, 146, 145, 147, 147, 145, 40,
+ 148, 145, 147, 147, 145, 40, 148, 145,
+ 148, 145, 145, 149, 148, 145, 148, 145,
+ 148, 145, 145, 145, 148, 145, 42, 117,
+ 117, 117, 117, 117, 117, 117, 117, 49,
+ 117, 117, 117, 117, 42, 117, 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
+ 31, 37, 42, 2, 43, 46, 4, 50,
+ 51, 31, 60, 9, 66, 69, 61, 11,
+ 74, 75, 78, 31, 83, 17, 89, 92,
+ 93, 84, 31, 19, 98, 31, 107, 24,
+ 113, 116, 117, 108, 26, 122, 127, 31,
+ 134, 31, 32, 53, 79, 81, 100, 101,
+ 85, 102, 123, 124, 94, 132, 137, 31,
+ 33, 35, 6, 52, 38, 47, 34, 1,
+ 36, 40, 0, 39, 41, 44, 45, 3,
+ 48, 5, 49, 31, 54, 56, 14, 77,
+ 62, 70, 55, 7, 57, 72, 64, 58,
+ 13, 76, 59, 8, 63, 65, 67, 68,
+ 10, 71, 12, 73, 31, 80, 20, 82,
+ 96, 87, 15, 99, 16, 86, 88, 90,
+ 91, 18, 95, 21, 97, 31, 31, 103,
+ 105, 22, 27, 109, 118, 104, 106, 120,
+ 111, 23, 110, 112, 114, 115, 25, 119,
+ 28, 121, 125, 126, 131, 128, 129, 29,
+ 130, 31, 133, 30, 135, 136
};
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,
+ 1, 0, 2, 0, 2, 0, 0, 2,
+ 2, 3, 2, 0, 2, 0, 0, 0,
+ 2, 2, 2, 4, 2, 0, 5, 0,
+ 5, 0, 6, 0, 2, 7, 2, 0,
+ 2, 0, 2, 0, 0, 2, 0, 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, 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
+ 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, 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,
@@ -349,14 +384,16 @@ 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
};
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, 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,
@@ -369,41 +406,42 @@ 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
};
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
+ 1, 1, 1, 1, 1, 1, 1, 10,
+ 10, 10, 10, 10, 10, 10, 10, 20,
+ 20, 27, 20, 27, 20, 20, 30, 30,
+ 30, 30, 30, 30, 30, 1, 40, 0,
+ 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 76, 76, 76,
+ 76, 76, 76, 76, 76, 76, 76, 76,
+ 76, 76, 76, 76, 76, 76, 76, 76,
+ 76, 76, 76, 76, 76, 76, 76, 101,
+ 101, 101, 101, 101, 101, 101, 101, 101,
+ 101, 101, 101, 101, 101, 101, 101, 101,
+ 101, 101, 101, 101, 118, 118, 119, 119,
+ 119, 119, 119, 119, 119, 119, 119, 119,
+ 119, 119, 119, 119, 119, 119, 119, 119,
+ 119, 119, 119, 101, 56, 56, 56, 56,
+ 56, 56, 56, 56, 146, 146, 146, 146,
+ 146, 118
};
-static const int indic_syllable_machine_start = 27;
-static const int indic_syllable_machine_first_final = 27;
+static const int indic_syllable_machine_start = 31;
+static const int indic_syllable_machine_first_final = 31;
static const int indic_syllable_machine_error = -1;
-static const int indic_syllable_machine_en_main = 27;
+static const int indic_syllable_machine_en_main = 31;
#line 58 "hb-ot-shaper-indic-machine.rl"
-#line 117 "hb-ot-shaper-indic-machine.rl"
+#line 118 "hb-ot-shaper-indic-machine.rl"
#define found_syllable(syllable_type) \
@@ -412,7 +450,7 @@ static const int indic_syllable_machine_en_main = 27;
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; \
+ if (syllable_serial == 16) syllable_serial = 1; \
} HB_STMT_END
inline void
@@ -422,7 +460,7 @@ find_syllables_indic (hb_buffer_t *buffer)
int cs;
hb_glyph_info_t *info = buffer->info;
-#line 426 "hb-ot-shaper-indic-machine.hh"
+#line 453 "hb-ot-shaper-indic-machine.hh"
{
cs = indic_syllable_machine_start;
ts = 0;
@@ -430,7 +468,7 @@ find_syllables_indic (hb_buffer_t *buffer)
act = 0;
}
-#line 137 "hb-ot-shaper-indic-machine.rl"
+#line 138 "hb-ot-shaper-indic-machine.rl"
p = 0;
@@ -438,7 +476,7 @@ find_syllables_indic (hb_buffer_t *buffer)
unsigned int syllable_serial = 1;
-#line 442 "hb-ot-shaper-indic-machine.hh"
+#line 465 "hb-ot-shaper-indic-machine.hh"
{
int _slen;
int _trans;
@@ -452,7 +490,7 @@ _resume:
#line 1 "NONE"
{ts = p;}
break;
-#line 456 "hb-ot-shaper-indic-machine.hh"
+#line 477 "hb-ot-shaper-indic-machine.hh"
}
_keys = _indic_syllable_machine_trans_keys + (cs<<1);
@@ -475,51 +513,51 @@ _eof_trans:
{te = p+1;}
break;
case 11:
-#line 113 "hb-ot-shaper-indic-machine.rl"
+#line 114 "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"
+#line 109 "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"
+#line 110 "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"
+#line 111 "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"
+#line 112 "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"
+#line 113 "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"
+#line 114 "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"
+#line 109 "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"
+#line 110 "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"
+#line 111 "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"
+#line 112 "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"
+#line 113 "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:
@@ -540,19 +578,19 @@ _eof_trans:
case 18:
#line 1 "NONE"
{te = p+1;}
-#line 108 "hb-ot-shaper-indic-machine.rl"
+#line 109 "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"
+#line 113 "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"
+#line 114 "hb-ot-shaper-indic-machine.rl"
{act = 6;}
break;
#line 559 "hb-ot-shaper-indic-machine.hh"
@@ -564,7 +602,7 @@ _again:
#line 1 "NONE"
{ts = 0;}
break;
-#line 568 "hb-ot-shaper-indic-machine.hh"
+#line 566 "hb-ot-shaper-indic-machine.hh"
}
if ( ++p != pe )
@@ -580,7 +618,7 @@ _again:
}
-#line 145 "hb-ot-shaper-indic-machine.rl"
+#line 146 "hb-ot-shaper-indic-machine.rl"
}
diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-indic-table.cc b/thirdparty/harfbuzz/src/hb-ot-shaper-indic-table.cc
index bf6a2757bb..d9fb0510e4 100644
--- a/thirdparty/harfbuzz/src/hb-ot-shaper-indic-table.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-shaper-indic-table.cc
@@ -42,6 +42,7 @@
#define OT_PLACEHOLDER I_Cat(PLACEHOLDER)
#define OT_DOTTEDCIRCLE I_Cat(DOTTEDCIRCLE)
#define OT_RS I_Cat(RS)
+#define OT_MPst I_Cat(MPst)
#define OT_Repha I_Cat(Repha)
#define OT_Ra I_Cat(Ra)
#define OT_CM I_Cat(CM)
@@ -80,9 +81,10 @@ static_assert (OT_VPst == M_Cat(VPst), "");
#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_M OT_M /* 142 chars; M */
#define _OT_MH OT_MH /* 1 chars; MH */
#define _OT_ML OT_ML /* 1 chars; ML */
+#define _OT_MP OT_MPst /* 1 chars; MPst */
#define _OT_MR OT_MR /* 1 chars; MR */
#define _OT_MW OT_MW /* 2 chars; MW */
#define _OT_MY OT_MY /* 3 chars; MY */
@@ -200,7 +202,7 @@ static const uint16_t indic_table[] = {
/* 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),
+ /* 0A40 */_(MP,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),
@@ -451,15 +453,12 @@ static const uint16_t indic_table[] = {
/* 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),
+
+#define indic_offset_0x11338u 1720
+
/* 11338 */ _(X,X), _(X,X), _(X,X), _(N,X), _(N,X), _(X,X), _(X,X), _(X,X),
-}; /* Table items: 1776; occupancy: 69% */
+}; /* Table items: 1728; occupancy: 71% */
uint16_t
hb_indic_get_categories (hb_codepoint_t u)
@@ -497,7 +496,8 @@ hb_indic_get_categories (hb_codepoint_t u)
break;
case 0x11u:
- if (hb_in_range<hb_codepoint_t> (u, 0x11300u, 0x1133Fu)) return indic_table[u - 0x11300u + indic_offset_0x11300u];
+ if (hb_in_range<hb_codepoint_t> (u, 0x11300u, 0x11307u)) return indic_table[u - 0x11300u + indic_offset_0x11300u];
+ if (hb_in_range<hb_codepoint_t> (u, 0x11338u, 0x1133Fu)) return indic_table[u - 0x11338u + indic_offset_0x11338u];
break;
default:
@@ -519,6 +519,7 @@ hb_indic_get_categories (hb_codepoint_t u)
#undef _OT_M
#undef _OT_MH
#undef _OT_ML
+#undef _OT_MP
#undef _OT_MR
#undef _OT_MW
#undef _OT_MY
diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-indic.cc b/thirdparty/harfbuzz/src/hb-ot-shaper-indic.cc
index 55509c1101..7652210d9d 100644
--- a/thirdparty/harfbuzz/src/hb-ot-shaper-indic.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-shaper-indic.cc
@@ -223,15 +223,15 @@ enum {
INDIC_BASIC_FEATURES = INDIC_INIT, /* Don't forget to update this! */
};
-static void
+static bool
setup_syllables_indic (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer);
-static void
+static bool
initial_reordering_indic (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer);
-static void
+static bool
final_reordering_indic (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer);
@@ -413,7 +413,7 @@ setup_masks_indic (const hb_ot_shape_plan_t *plan HB_UNUSED,
set_indic_properties (info[i]);
}
-static void
+static bool
setup_syllables_indic (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_font_t *font HB_UNUSED,
hb_buffer_t *buffer)
@@ -422,6 +422,7 @@ setup_syllables_indic (const hb_ot_shape_plan_t *plan HB_UNUSED,
find_syllables_indic (buffer);
foreach_syllable (buffer, start, end)
buffer->unsafe_to_break (start, end);
+ return false;
}
static int
@@ -714,6 +715,9 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
}
}
} else if (info[i].indic_position() != POS_SMVD) {
+ if (info[i].indic_category() == I_Cat(MPst) &&
+ i > start && info[i - 1].indic_category() == I_Cat(SM))
+ info[i - 1].indic_position() = info[i].indic_position();
last_pos = (indic_position_t) info[i].indic_position();
}
}
@@ -729,7 +733,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() == I_Cat(M))
+ } else if (FLAG_UNSAFE (info[i].indic_category()) & (FLAG (I_Cat(M)) | FLAG (I_Cat(MPst))))
last = i;
}
@@ -742,14 +746,40 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
/* Sit tight, rock 'n roll! */
hb_stable_sort (info + start, end - start, compare_indic_order);
- /* Find base again */
+
+ /* Find base again; also flip left-matra sequence. */
+ unsigned first_left_matra = end;
+ unsigned last_left_matra = end;
base = end;
for (unsigned int i = start; i < end; i++)
+ {
if (info[i].indic_position() == POS_BASE_C)
{
base = i;
break;
}
+ else if (info[i].indic_position() == POS_PRE_M)
+ {
+ if (first_left_matra == end)
+ first_left_matra = i;
+ last_left_matra = i;
+ }
+ }
+ /* https://github.com/harfbuzz/harfbuzz/issues/3863 */
+ if (first_left_matra < last_left_matra)
+ {
+ /* No need to merge clusters, handled later. */
+ buffer->reverse_range (first_left_matra, last_left_matra + 1);
+ /* Reverse back nuktas, etc. */
+ unsigned i = first_left_matra;
+ for (unsigned j = i; j <= last_left_matra; j++)
+ if (FLAG_UNSAFE (info[j].indic_category()) & (FLAG (I_Cat(M)) | FLAG (I_Cat(MPst))))
+ {
+ buffer->reverse_range (i, j + 1);
+ i = j + 1;
+ }
+ }
+
/* Things are out-of-control for post base positions, they may shuffle
* around like crazy. In old-spec mode, we move halants around, so in
* that case merge all clusters after base. Otherwise, check the sort
@@ -955,25 +985,29 @@ initial_reordering_syllable_indic (const hb_ot_shape_plan_t *plan,
}
}
-static void
+static bool
initial_reordering_indic (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer)
{
+ bool ret = false;
if (!buffer->message (font, "start reordering indic initial"))
- return;
+ return ret;
update_consonant_positions_indic (plan, font, buffer);
- hb_syllabic_insert_dotted_circles (font, buffer,
- indic_broken_cluster,
- I_Cat(DOTTEDCIRCLE),
- I_Cat(Repha),
- POS_END);
+ if (hb_syllabic_insert_dotted_circles (font, buffer,
+ indic_broken_cluster,
+ I_Cat(DOTTEDCIRCLE),
+ I_Cat(Repha),
+ POS_END))
+ ret = true;
foreach_syllable (buffer, start, end)
initial_reordering_syllable_indic (plan, font->face, buffer, start, end);
(void) buffer->message (font, "end reordering indic initial");
+
+ return ret;
}
static void
@@ -1116,7 +1150,7 @@ final_reordering_syllable_indic (const hb_ot_shape_plan_t *plan,
{
search:
while (new_pos > start &&
- !(is_one_of (info[new_pos], (FLAG (I_Cat(M)) | FLAG (I_Cat(H))))))
+ !(is_one_of (info[new_pos], (FLAG (I_Cat(M)) | FLAG (I_Cat(MPst)) | FLAG (I_Cat(H))))))
new_pos--;
/* If we found no Halant we are done.
@@ -1316,7 +1350,8 @@ 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() == I_Cat(M)) {
+ if (FLAG_UNSAFE (info[i].indic_category()) & (FLAG (I_Cat(M)) | FLAG (I_Cat(MPst))))
+ {
/* Ok, got it. */
new_reph_pos--;
}
@@ -1376,7 +1411,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(I_Cat(M)) | FLAG (I_Cat(H)))))
+ !(is_one_of (info[new_pos - 1], FLAG (I_Cat(M)) | FLAG (I_Cat(MPst)) | FLAG (I_Cat(H)))))
new_pos--;
}
@@ -1439,13 +1474,13 @@ final_reordering_syllable_indic (const hb_ot_shape_plan_t *plan,
}
-static void
+static bool
final_reordering_indic (const hb_ot_shape_plan_t *plan,
hb_font_t *font HB_UNUSED,
hb_buffer_t *buffer)
{
unsigned int count = buffer->len;
- if (unlikely (!count)) return;
+ if (unlikely (!count)) return false;
if (buffer->message (font, "start reordering indic final")) {
foreach_syllable (buffer, start, end)
@@ -1455,6 +1490,8 @@ final_reordering_indic (const hb_ot_shape_plan_t *plan,
HB_BUFFER_DEALLOCATE_VAR (buffer, indic_category);
HB_BUFFER_DEALLOCATE_VAR (buffer, indic_position);
+
+ return false;
}
diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-khmer-machine.hh b/thirdparty/harfbuzz/src/hb-ot-shaper-khmer-machine.hh
index e18bd75ef1..fd91ee0caf 100644
--- a/thirdparty/harfbuzz/src/hb-ot-shaper-khmer-machine.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-shaper-khmer-machine.hh
@@ -48,7 +48,7 @@ enum khmer_syllable_type_t {
};
-#line 52 "hb-ot-shaper-khmer-machine.hh"
+#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
@@ -66,7 +66,7 @@ enum khmer_syllable_type_t {
#define khmer_syllable_machine_ex_ZWNJ 5u
-#line 70 "hb-ot-shaper-khmer-machine.hh"
+#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,
@@ -284,7 +284,7 @@ static const int khmer_syllable_machine_en_main = 21;
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; \
+ if (syllable_serial == 16) syllable_serial = 1; \
} HB_STMT_END
inline void
@@ -294,7 +294,7 @@ find_syllables_khmer (hb_buffer_t *buffer)
int cs;
hb_glyph_info_t *info = buffer->info;
-#line 298 "hb-ot-shaper-khmer-machine.hh"
+#line 287 "hb-ot-shaper-khmer-machine.hh"
{
cs = khmer_syllable_machine_start;
ts = 0;
@@ -310,7 +310,7 @@ find_syllables_khmer (hb_buffer_t *buffer)
unsigned int syllable_serial = 1;
-#line 314 "hb-ot-shaper-khmer-machine.hh"
+#line 299 "hb-ot-shaper-khmer-machine.hh"
{
int _slen;
int _trans;
@@ -324,7 +324,7 @@ _resume:
#line 1 "NONE"
{ts = p;}
break;
-#line 328 "hb-ot-shaper-khmer-machine.hh"
+#line 311 "hb-ot-shaper-khmer-machine.hh"
}
_keys = _khmer_syllable_machine_trans_keys + (cs<<1);
@@ -394,7 +394,7 @@ _eof_trans:
#line 98 "hb-ot-shaper-khmer-machine.rl"
{act = 3;}
break;
-#line 398 "hb-ot-shaper-khmer-machine.hh"
+#line 368 "hb-ot-shaper-khmer-machine.hh"
}
_again:
@@ -403,7 +403,7 @@ _again:
#line 1 "NONE"
{ts = 0;}
break;
-#line 407 "hb-ot-shaper-khmer-machine.hh"
+#line 375 "hb-ot-shaper-khmer-machine.hh"
}
if ( ++p != pe )
diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-khmer.cc b/thirdparty/harfbuzz/src/hb-ot-shaper-khmer.cc
index d9795589fa..019a285102 100644
--- a/thirdparty/harfbuzz/src/hb-ot-shaper-khmer.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-shaper-khmer.cc
@@ -89,11 +89,11 @@ set_khmer_properties (hb_glyph_info_t &info)
info.khmer_category() = (khmer_category_t) (type & 0xFFu);
}
-static void
+static bool
setup_syllables_khmer (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer);
-static void
+static bool
reorder_khmer (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer);
@@ -192,7 +192,7 @@ setup_masks_khmer (const hb_ot_shape_plan_t *plan HB_UNUSED,
set_khmer_properties (info[i]);
}
-static void
+static bool
setup_syllables_khmer (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_font_t *font HB_UNUSED,
hb_buffer_t *buffer)
@@ -201,6 +201,7 @@ setup_syllables_khmer (const hb_ot_shape_plan_t *plan HB_UNUSED,
find_syllables_khmer (buffer);
foreach_syllable (buffer, start, end)
buffer->unsafe_to_break (start, end);
+ return false;
}
@@ -303,23 +304,27 @@ reorder_syllable_khmer (const hb_ot_shape_plan_t *plan,
}
}
-static void
+static bool
reorder_khmer (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer)
{
+ bool ret = false;
if (buffer->message (font, "start reordering khmer"))
{
- hb_syllabic_insert_dotted_circles (font, buffer,
- khmer_broken_cluster,
- K_Cat(DOTTEDCIRCLE),
- (unsigned) -1);
+ if (hb_syllabic_insert_dotted_circles (font, buffer,
+ khmer_broken_cluster,
+ K_Cat(DOTTEDCIRCLE),
+ (unsigned) -1))
+ ret = true;
foreach_syllable (buffer, start, end)
reorder_syllable_khmer (plan, font->face, buffer, start, end);
(void) buffer->message (font, "end reordering khmer");
}
HB_BUFFER_DEALLOCATE_VAR (buffer, khmer_category);
+
+ return ret;
}
diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-myanmar-machine.hh b/thirdparty/harfbuzz/src/hb-ot-shaper-myanmar-machine.hh
index b109708937..87cded4ed8 100644
--- a/thirdparty/harfbuzz/src/hb-ot-shaper-myanmar-machine.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-shaper-myanmar-machine.hh
@@ -50,7 +50,7 @@ enum myanmar_syllable_type_t {
};
-#line 54 "hb-ot-shaper-myanmar-machine.hh"
+#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
@@ -77,7 +77,7 @@ enum myanmar_syllable_type_t {
#define myanmar_syllable_machine_ex_ZWNJ 5u
-#line 81 "hb-ot-shaper-myanmar-machine.hh"
+#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,
@@ -433,7 +433,7 @@ static const int myanmar_syllable_machine_en_main = 0;
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; \
+ if (syllable_serial == 16) syllable_serial = 1; \
} HB_STMT_END
inline void
@@ -443,7 +443,7 @@ find_syllables_myanmar (hb_buffer_t *buffer)
int cs;
hb_glyph_info_t *info = buffer->info;
-#line 447 "hb-ot-shaper-myanmar-machine.hh"
+#line 436 "hb-ot-shaper-myanmar-machine.hh"
{
cs = myanmar_syllable_machine_start;
ts = 0;
@@ -459,7 +459,7 @@ find_syllables_myanmar (hb_buffer_t *buffer)
unsigned int syllable_serial = 1;
-#line 463 "hb-ot-shaper-myanmar-machine.hh"
+#line 448 "hb-ot-shaper-myanmar-machine.hh"
{
int _slen;
int _trans;
@@ -473,7 +473,7 @@ _resume:
#line 1 "NONE"
{ts = p;}
break;
-#line 477 "hb-ot-shaper-myanmar-machine.hh"
+#line 460 "hb-ot-shaper-myanmar-machine.hh"
}
_keys = _myanmar_syllable_machine_trans_keys + (cs<<1);
@@ -519,7 +519,7 @@ _eof_trans:
#line 113 "hb-ot-shaper-myanmar-machine.rl"
{te = p;p--;{ found_syllable (myanmar_non_myanmar_cluster); }}
break;
-#line 523 "hb-ot-shaper-myanmar-machine.hh"
+#line 498 "hb-ot-shaper-myanmar-machine.hh"
}
_again:
@@ -528,7 +528,7 @@ _again:
#line 1 "NONE"
{ts = 0;}
break;
-#line 532 "hb-ot-shaper-myanmar-machine.hh"
+#line 505 "hb-ot-shaper-myanmar-machine.hh"
}
if ( ++p != pe )
diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-myanmar.cc b/thirdparty/harfbuzz/src/hb-ot-shaper-myanmar.cc
index 78bd8de524..1b2a085a8d 100644
--- a/thirdparty/harfbuzz/src/hb-ot-shaper-myanmar.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-shaper-myanmar.cc
@@ -98,11 +98,11 @@ is_consonant_myanmar (const hb_glyph_info_t &info)
}
-static void
+static bool
setup_syllables_myanmar (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer);
-static void
+static bool
reorder_myanmar (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer);
@@ -150,7 +150,7 @@ setup_masks_myanmar (const hb_ot_shape_plan_t *plan HB_UNUSED,
set_myanmar_properties (info[i]);
}
-static void
+static bool
setup_syllables_myanmar (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_font_t *font HB_UNUSED,
hb_buffer_t *buffer)
@@ -159,6 +159,7 @@ setup_syllables_myanmar (const hb_ot_shape_plan_t *plan HB_UNUSED,
find_syllables_myanmar (buffer);
foreach_syllable (buffer, start, end)
buffer->unsafe_to_break (start, end);
+ return false;
}
static int
@@ -270,6 +271,33 @@ initial_reordering_consonant_syllable (hb_buffer_t *buffer,
/* Sit tight, rock 'n roll! */
buffer->sort (start, end, compare_myanmar_order);
+
+ /* Flip left-matra sequence. */
+ unsigned first_left_matra = end;
+ unsigned last_left_matra = end;
+ for (unsigned int i = start; i < end; i++)
+ {
+ if (info[i].myanmar_position() == POS_PRE_M)
+ {
+ if (first_left_matra == end)
+ first_left_matra = i;
+ last_left_matra = i;
+ }
+ }
+ /* https://github.com/harfbuzz/harfbuzz/issues/3863 */
+ if (first_left_matra < last_left_matra)
+ {
+ /* No need to merge clusters, done already? */
+ buffer->reverse_range (first_left_matra, last_left_matra + 1);
+ /* Reverse back VS, etc. */
+ unsigned i = first_left_matra;
+ for (unsigned j = i; j <= last_left_matra; j++)
+ if (info[j].myanmar_category() == M_Cat(VPre))
+ {
+ buffer->reverse_range (i, j + 1);
+ i = j + 1;
+ }
+ }
}
static void
@@ -291,16 +319,18 @@ reorder_syllable_myanmar (const hb_ot_shape_plan_t *plan HB_UNUSED,
}
}
-static void
+static bool
reorder_myanmar (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer)
{
+ bool ret = false;
if (buffer->message (font, "start reordering myanmar"))
{
- hb_syllabic_insert_dotted_circles (font, buffer,
- myanmar_broken_cluster,
- M_Cat(DOTTEDCIRCLE));
+ if (hb_syllabic_insert_dotted_circles (font, buffer,
+ myanmar_broken_cluster,
+ M_Cat(DOTTEDCIRCLE)))
+ ret = true;
foreach_syllable (buffer, start, end)
reorder_syllable_myanmar (plan, font->face, buffer, start, end);
@@ -309,6 +339,8 @@ reorder_myanmar (const hb_ot_shape_plan_t *plan,
HB_BUFFER_DEALLOCATE_VAR (buffer, myanmar_category);
HB_BUFFER_DEALLOCATE_VAR (buffer, myanmar_position);
+
+ return ret;
}
@@ -331,6 +363,7 @@ const hb_ot_shaper_t _hb_ot_shaper_myanmar =
};
+#ifndef HB_NO_OT_SHAPER_MYANMAR_ZAWGYI
/* Ugly Zawgyi encoding.
* Disable all auto processing.
* https://github.com/harfbuzz/harfbuzz/issues/1162 */
@@ -351,6 +384,7 @@ const hb_ot_shaper_t _hb_ot_shaper_myanmar_zawgyi =
HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE,
false, /* fallback_position */
};
+#endif
#endif
diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-syllabic.cc b/thirdparty/harfbuzz/src/hb-ot-shaper-syllabic.cc
index a8e0d8e8c1..89226ae4a1 100644
--- a/thirdparty/harfbuzz/src/hb-ot-shaper-syllabic.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-shaper-syllabic.cc
@@ -29,7 +29,7 @@
#include "hb-ot-shaper-syllabic.hh"
-void
+bool
hb_syllabic_insert_dotted_circles (hb_font_t *font,
hb_buffer_t *buffer,
unsigned int broken_syllable_type,
@@ -38,13 +38,13 @@ hb_syllabic_insert_dotted_circles (hb_font_t *font,
int dottedcircle_position)
{
if (unlikely (buffer->flags & HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE))
- return;
+ return false;
if (likely (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_BROKEN_SYLLABLE)))
- return;
+ return false;
hb_codepoint_t dottedcircle_glyph;
if (!font->get_nominal_glyph (0x25CCu, &dottedcircle_glyph))
- return;
+ return false;
hb_glyph_info_t dottedcircle = {0};
dottedcircle.codepoint = 0x25CCu;
@@ -84,14 +84,16 @@ hb_syllabic_insert_dotted_circles (hb_font_t *font,
(void) buffer->next_glyph ();
}
buffer->sync ();
+ return true;
}
-HB_INTERNAL void
+HB_INTERNAL bool
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);
+ return false;
}
diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-syllabic.hh b/thirdparty/harfbuzz/src/hb-ot-shaper-syllabic.hh
index e8a15bb48a..f240ad1c26 100644
--- a/thirdparty/harfbuzz/src/hb-ot-shaper-syllabic.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-shaper-syllabic.hh
@@ -30,7 +30,7 @@
#include "hb-ot-shaper.hh"
-HB_INTERNAL void
+HB_INTERNAL bool
hb_syllabic_insert_dotted_circles (hb_font_t *font,
hb_buffer_t *buffer,
unsigned int broken_syllable_type,
@@ -38,7 +38,7 @@ hb_syllabic_insert_dotted_circles (hb_font_t *font,
int repha_category = -1,
int dottedcircle_position = -1);
-HB_INTERNAL void
+HB_INTERNAL bool
hb_syllabic_clear_var (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer);
diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-thai.cc b/thirdparty/harfbuzz/src/hb-ot-shaper-thai.cc
index 15349b1e64..6cd67cde35 100644
--- a/thirdparty/harfbuzz/src/hb-ot-shaper-thai.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-shaper-thai.cc
@@ -98,9 +98,9 @@ static hb_codepoint_t
thai_pua_shape (hb_codepoint_t u, thai_action_t action, hb_font_t *font)
{
struct thai_pua_mapping_t {
- hb_codepoint_t u;
- hb_codepoint_t win_pua;
- hb_codepoint_t mac_pua;
+ uint16_t u;
+ uint16_t win_pua;
+ uint16_t mac_pua;
} const *pua_mappings = nullptr;
static const thai_pua_mapping_t SD_mappings[] = {
{0x0E48u, 0xF70Au, 0xF88Bu}, /* MAI EK */
diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-use-machine.hh b/thirdparty/harfbuzz/src/hb-ot-shaper-use-machine.hh
index 41e8a34f3b..f2fbdb725b 100644
--- a/thirdparty/harfbuzz/src/hb-ot-shaper-use-machine.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-shaper-use-machine.hh
@@ -53,7 +53,7 @@ enum use_syllable_type_t {
};
-#line 57 "hb-ot-shaper-use-machine.hh"
+#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
@@ -97,7 +97,7 @@ enum use_syllable_type_t {
#define use_syllable_machine_ex_ZWNJ 14u
-#line 101 "hb-ot-shaper-use-machine.hh"
+#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, 14u, 48u, 14u, 47u, 14u, 47u, 14u, 47u,
14u, 46u, 14u, 46u, 14u, 14u, 14u, 48u, 14u, 48u, 14u, 48u, 1u, 14u, 14u, 48u,
@@ -839,7 +839,7 @@ static const int use_syllable_machine_en_main = 0;
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; \
+ if (syllable_serial == 16) syllable_serial = 1; \
} HB_STMT_END
@@ -929,7 +929,7 @@ find_syllables_use (hb_buffer_t *buffer)
unsigned int act HB_UNUSED;
int cs;
-#line 933 "hb-ot-shaper-use-machine.hh"
+#line 922 "hb-ot-shaper-use-machine.hh"
{
cs = use_syllable_machine_start;
ts = 0;
@@ -942,7 +942,7 @@ find_syllables_use (hb_buffer_t *buffer)
unsigned int syllable_serial = 1;
-#line 946 "hb-ot-shaper-use-machine.hh"
+#line 931 "hb-ot-shaper-use-machine.hh"
{
int _slen;
int _trans;
@@ -956,7 +956,7 @@ _resume:
#line 1 "NONE"
{ts = p;}
break;
-#line 960 "hb-ot-shaper-use-machine.hh"
+#line 943 "hb-ot-shaper-use-machine.hh"
}
_keys = _use_syllable_machine_trans_keys + (cs<<1);
@@ -1046,7 +1046,7 @@ _eof_trans:
#line 178 "hb-ot-shaper-use-machine.rl"
{te = p;p--;{ found_syllable (use_non_cluster); }}
break;
-#line 1050 "hb-ot-shaper-use-machine.hh"
+#line 1014 "hb-ot-shaper-use-machine.hh"
}
_again:
@@ -1055,7 +1055,7 @@ _again:
#line 1 "NONE"
{ts = 0;}
break;
-#line 1059 "hb-ot-shaper-use-machine.hh"
+#line 1021 "hb-ot-shaper-use-machine.hh"
}
if ( ++p != pe )
diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-use-table.hh b/thirdparty/harfbuzz/src/hb-ot-shaper-use-table.hh
index 9833fb55de..6b6b552ee5 100644
--- a/thirdparty/harfbuzz/src/hb-ot-shaper-use-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-shaper-use-table.hh
@@ -91,6 +91,9 @@
#define VMPre USE(VMPre)
#pragma GCC diagnostic pop
+
+#ifndef HB_OPTIMIZE_SIZE
+
static const uint8_t
hb_use_u8[3141] =
{
@@ -357,6 +360,273 @@ hb_use_get_category (unsigned u)
return u<921600u?hb_use_u8[2777+(((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;
}
+
+#else
+
+static const uint8_t
+hb_use_u8[3413] =
+{
+ 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, 1, 2, 1, 1, 3, 4, 5, 6, 7, 8, 9, 10, 1,
+ 11, 12, 1, 1, 1, 1, 1, 1, 13, 14, 15, 16, 17, 18, 19, 1,
+ 1, 20, 1, 1, 1, 1, 21, 1, 1, 1, 1, 1, 1, 1, 22, 1,
+ 1, 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, 24, 25, 26, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27,
+ 28, 1, 1, 1, 1, 1, 29, 1, 1, 1, 1, 30, 31, 1, 32, 33,
+ 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 1, 46, 47, 48,
+ 49, 50, 50, 50, 50, 51, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 52, 53, 1, 1, 1,
+ 54, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 50, 55, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 56, 1, 1,
+ 1, 1, 57, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 58, 59, 1, 60, 1, 1, 1, 1, 61, 1, 1, 1, 1, 1,
+ 1, 62, 63, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
+ 62, 0, 1, 0, 0, 0, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 6, 7, 0, 0, 8, 0, 0, 0, 0,
+ 0, 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, 35, 36, 37, 38, 39,
+ 40, 41, 42, 43, 36, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
+ 0, 55, 56, 57, 58, 59, 0, 0, 0, 60, 61, 62, 63, 55, 64, 65,
+ 66, 67, 55, 55, 68, 69, 70, 0, 0, 71, 72, 73, 74, 55, 75, 76,
+ 0, 77, 55, 78, 79, 80, 0, 0, 0, 81, 82, 83, 84, 85, 86, 55,
+ 87, 55, 88, 89, 0, 0, 0, 90, 91, 0, 0, 0, 0, 0, 0, 0,
+ 92, 93, 94, 0, 95, 96, 0, 0, 97, 0, 0, 0, 0, 0, 0, 98,
+ 0, 0, 99, 55, 100, 0, 0, 0, 0, 101, 102, 55, 103, 104, 105, 106,
+ 107, 55, 108, 109, 0, 110, 111, 112, 113, 55, 114, 115, 116, 55, 117, 118,
+ 119, 0, 0, 0, 0, 0, 0, 55, 120, 121, 0, 0, 0, 0, 0, 0,
+ 122, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 124, 125, 126, 0,
+ 0, 127, 128, 129, 0, 0, 0, 50, 130, 0, 0, 0, 0, 131, 132, 0,
+ 0, 55, 133, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 134, 0,
+ 0, 0, 99, 135, 99, 136, 137, 138, 0, 139, 140, 141, 142, 143, 144, 145,
+ 0, 146, 147, 148, 149, 143, 150, 151, 152, 153, 154, 155, 0, 156, 157, 158,
+ 159, 160, 161, 162, 163, 0, 0, 0, 0, 55, 164, 165, 166, 167, 168, 169,
+ 0, 0, 0, 0, 0, 55, 170, 171, 0, 55, 172, 173, 0, 55, 174, 66,
+ 0, 175, 176, 177, 0, 0, 0, 0, 0, 55, 178, 0, 0, 0, 0, 0,
+ 0, 179, 180, 181, 0, 0, 182, 183, 184, 185, 186, 187, 55, 188, 0, 0,
+ 0, 189, 190, 191, 192, 193, 194, 0, 0, 195, 196, 197, 198, 199, 66, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 200, 201, 202, 203, 0, 0, 0, 0,
+ 0, 55, 55, 55, 55, 55, 55, 55, 55, 55, 204, 205, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 66, 0, 55, 206, 0, 0, 0, 0, 0,
+ 0, 55, 55, 207, 208, 209, 0, 0, 210, 55, 55, 55, 55, 55, 55, 211,
+ 0, 55, 55, 55, 212, 213, 0, 0, 0, 0, 0, 0, 214, 0, 0, 0,
+ 0, 55, 215, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 217, 55,
+ 218, 0, 0, 0, 0, 0, 0, 99, 219, 55, 55, 220, 0, 0, 0, 0,
+ 0, 221, 221, 221, 221, 221, 221, 221, 221, 222, 222, 222, 222, 222, 222, 222,
+ 223, 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, 39, 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, 49, 9, 3, 0, 0, 0, 0, 0, 0, 0, 116, 0,
+ 0, 0, 0, 0, 0, 0, 4, 117, 118, 40, 40, 3, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 118, 118, 119, 118, 118, 118, 118, 118, 118, 118,
+ 118, 0, 0, 120, 0, 0, 0, 0, 0, 0, 5, 120, 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,
+ 121, 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, 122, 21, 21, 21, 21, 21, 21, 21, 123, 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, 124, 114, 0, 2, 2, 2, 125, 18, 57, 18,
+ 111, 100, 126, 0, 0, 0, 0, 0, 0, 9, 127, 2, 2, 2, 2, 2,
+ 2, 2, 128, 21, 20, 18, 46, 129, 130, 131, 0, 0, 0, 0, 0, 0,
+ 0, 2, 2, 50, 28, 2, 2, 2, 2, 2, 2, 2, 2, 8, 20, 57,
+ 97, 74, 132, 133, 134, 0, 0, 0, 0, 2, 135, 2, 2, 2, 2, 136,
+ 0, 28, 2, 40, 3, 0, 77, 13, 2, 51, 20, 137, 50, 51, 2, 2,
+ 103, 8, 7, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 138, 19,
+ 23, 0, 0, 139, 140, 0, 0, 0, 0, 2, 63, 43, 21, 78, 45, 141,
+ 0, 79, 79, 79, 79, 79, 79, 79, 79, 0, 0, 0, 0, 0, 0, 0,
+ 4, 118, 118, 118, 118, 119, 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, 125, 18, 25, 29, 0, 0, 142, 143, 2, 2, 28, 2, 28, 2, 2,
+ 2, 2, 2, 2, 0, 12, 35, 0, 144, 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, 145, 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, 146, 147, 148, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 20, 20, 18, 18, 18, 20, 20, 131, 0, 0, 0,
+ 0, 0, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 2, 2, 2, 2,
+ 2, 51, 50, 51, 0, 0, 0, 0, 150, 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, 125, 18, 20, 151,
+ 20, 19, 152, 153, 2, 2, 2, 2, 2, 0, 0, 63, 154, 0, 0, 0,
+ 0, 2, 11, 0, 0, 0, 0, 0, 0, 2, 63, 23, 18, 18, 18, 20,
+ 20, 106, 155, 0, 0, 54, 156, 29, 157, 28, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 21, 17, 20, 20, 158, 42, 0, 0, 0,
+ 47, 125, 0, 0, 0, 0, 0, 0, 0, 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, 159, 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, 123, 13, 15, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 0,
+ 160, 161, 0, 0, 0, 0, 0, 0, 0, 16, 17, 18, 18, 64, 97, 23,
+ 157, 9, 162, 7, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2,
+ 63, 23, 18, 18, 0, 46, 46, 9, 163, 35, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 2, 2, 18, 0, 21, 17, 18, 18, 19, 14, 80,
+ 163, 36, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 8, 164,
+ 23, 18, 20, 20, 162, 7, 0, 0, 0, 2, 2, 2, 2, 2, 7, 41,
+ 133, 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, 163, 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, 165, 166, 167, 168, 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, 137, 2,
+ 2, 2, 169, 170, 9, 13, 171, 70, 172, 0, 0, 1, 144, 0, 0, 0,
+ 0, 50, 18, 20, 14, 17, 18, 2, 2, 2, 2, 155, 155, 155, 173, 173,
+ 173, 173, 173, 173, 13, 174, 0, 28, 0, 20, 18, 18, 29, 20, 20, 9,
+ 163, 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, 156, 175, 171, 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, 176, 64, 45, 0, 0, 0, 0, 9, 177, 2, 2, 2, 2, 2,
+ 2, 2, 2, 21, 20, 18, 29, 0, 46, 14, 140, 0, 0, 0, 0, 0,
+ 0, 178, 178, 178, 106, 179, 178, 0, 0, 145, 2, 2, 180, 114, 114, 114,
+ 114, 114, 114, 114, 0, 0, 0, 0, 0, 9, 9, 9, 44, 0, 0, 0,
+ 0, 2, 2, 2, 2, 2, 7, 0, 56, 181, 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, 118, 118, 118, 119, 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, 2, 2, 2, 2, 20,
+ 20, 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,VMPst, B, VAbv, VAbv,
+ B, R, O, HVM, O, O,FMBlw, O,CMAbv, O,CMBlw, VAbv, VBlw, B, SUB, SUB,
+ SUB, O, SUB, SUB, O,FMBlw, 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, 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,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, R,VMPst, H, H, B,
+ H, B,VMBlw, O, VBlw,
+};
+static const uint16_t
+hb_use_u16[448] =
+{
+ 0, 0, 1, 2, 3, 4, 0, 5, 6, 0, 7, 0, 8, 9, 10, 11,
+ 9, 12, 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, 60, 61, 9, 62, 63, 64, 30, 65,
+ 66, 67, 9, 68, 69, 9, 70, 71, 72, 73, 74, 75, 76, 0, 9, 9,
+ 77, 78, 79, 80, 81, 82, 83, 84, 9, 85, 9, 86, 9, 87, 88, 89,
+ 9, 90, 91, 92, 2, 0, 93, 0, 9, 94, 95, 9, 96, 0, 97, 98,
+ 99,100, 30, 9,101,102,103, 9,104,105, 9,106, 9,107,108,109,
+ 2, 2,110, 9, 9,111,112, 2,113,114,115, 9,116, 9,117,118,
+ 119,120,121, 0, 0,122,123,124, 0,125,126,127,128, 0,129,130,
+ 131, 0, 0,132,133, 0, 0, 9,134,135,136, 9,137, 0, 9,138,
+ 139, 9, 9,140,141, 2,142,143,144, 9,145,146,147, 9, 9,148,
+ 149, 2,150, 98,151,152,153, 2, 9,154, 9,155,156, 0,157,158,
+ 159, 2,160, 0, 0,161, 0,162, 0,163,163,164, 33,165,166,167,
+ 9,168, 94, 0,169, 0, 9,170,171, 0,172, 2,173,170,174,175,
+ 176, 0, 0,177,178, 0,179, 9, 9,180,181,182,183,184,185, 9,
+ 9,186,187, 0,188, 9,189,190,191, 9, 9,192, 9,193,194,105,
+ 195,102, 9, 33,196,197,198, 0,199,200, 94, 9, 9,201,202, 2,
+ 203, 20, 21,204,205,206,207,208, 9,209,210,211,212, 0,195, 9,
+ 9,213,214, 2,215,216,217,218, 9,219,220, 2,221,222, 9,223,
+ 224,103,225, 0,226,227,228,229, 9,230,231, 2,232, 9, 9,233,
+ 234, 0,235, 9, 9,236,237,238,239,240, 21, 9,215,241, 7, 9,
+ 70, 18, 9,242, 73,243,244, 9, 9,245,246, 2,247, 9,248,249,
+ 9,250,251, 48, 9,252,253, 2, 9,254,255,256, 9,257,258,259,
+ 260,260,261,262,263, 0, 9,264,105, 70, 94,265, 0,266, 70,267,
+ 268, 0,269, 0,270, 2,271, 2,272, 2,129,129,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[3049+(((hb_use_u8[865+(((hb_use_u16[((hb_use_u8[353+(((hb_use_u8[113+(((hb_use_b4(hb_use_u8,u>>1>>3>>1>>3>>4))<<4)+((u>>1>>3>>1>>3)&15u))])<<3)+((u>>1>>3>>1)&7u))])<<1)+((u>>1>>3)&1u)])<<3)+((u>>1)&7u))])<<1)+((u)&1u))]:O;
+}
+
+#endif
+
#undef B
#undef CGJ
#undef CS
diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-use.cc b/thirdparty/harfbuzz/src/hb-ot-shaper-use.cc
index c40ec52f9c..342aba1235 100644
--- a/thirdparty/harfbuzz/src/hb-ot-shaper-use.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-shaper-use.cc
@@ -89,19 +89,19 @@ use_other_features[] =
HB_TAG('p','s','t','s'),
};
-static void
+static bool
setup_syllables_use (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer);
-static void
+static bool
record_rphf_use (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer);
-static void
+static bool
record_pref_use (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer);
-static void
+static bool
reorder_use (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer);
@@ -293,7 +293,7 @@ setup_topographical_masks (const hb_ot_shape_plan_t *plan,
}
}
-static void
+static bool
setup_syllables_use (const hb_ot_shape_plan_t *plan,
hb_font_t *font HB_UNUSED,
hb_buffer_t *buffer)
@@ -304,9 +304,10 @@ setup_syllables_use (const hb_ot_shape_plan_t *plan,
buffer->unsafe_to_break (start, end);
setup_rphf_mask (plan, buffer);
setup_topographical_masks (plan, buffer);
+ return false;
}
-static void
+static bool
record_rphf_use (const hb_ot_shape_plan_t *plan,
hb_font_t *font HB_UNUSED,
hb_buffer_t *buffer)
@@ -314,7 +315,7 @@ record_rphf_use (const hb_ot_shape_plan_t *plan,
const use_shape_plan_t *use_plan = (const use_shape_plan_t *) plan->data;
hb_mask_t mask = use_plan->rphf_mask;
- if (!mask) return;
+ if (!mask) return false;
hb_glyph_info_t *info = buffer->info;
foreach_syllable (buffer, start, end)
@@ -327,9 +328,10 @@ record_rphf_use (const hb_ot_shape_plan_t *plan,
break;
}
}
+ return false;
}
-static void
+static bool
record_pref_use (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_font_t *font HB_UNUSED,
hb_buffer_t *buffer)
@@ -346,6 +348,7 @@ record_pref_use (const hb_ot_shape_plan_t *plan HB_UNUSED,
break;
}
}
+ return false;
}
static inline bool
@@ -438,17 +441,19 @@ reorder_syllable_use (hb_buffer_t *buffer, unsigned int start, unsigned int end)
}
}
-static void
+static bool
reorder_use (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer)
{
+ bool ret = false;
if (buffer->message (font, "start reordering USE"))
{
- hb_syllabic_insert_dotted_circles (font, buffer,
- use_broken_cluster,
- USE(B),
- USE(R));
+ if (hb_syllabic_insert_dotted_circles (font, buffer,
+ use_broken_cluster,
+ USE(B),
+ USE(R)))
+ ret = true;
foreach_syllable (buffer, start, end)
reorder_syllable_use (buffer, start, end);
@@ -457,6 +462,8 @@ reorder_use (const hb_ot_shape_plan_t *plan,
}
HB_BUFFER_DEALLOCATE_VAR (buffer, use_category);
+
+ return ret;
}
diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper.hh b/thirdparty/harfbuzz/src/hb-ot-shaper.hh
index b2d1acb39b..0207b2bbe3 100644
--- a/thirdparty/harfbuzz/src/hb-ot-shaper.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-shaper.hh
@@ -262,11 +262,13 @@ hb_ot_shaper_categorize (const hb_ot_shape_planner_t *planner)
return &_hb_ot_shaper_myanmar;
+#ifndef HB_NO_OT_SHAPER_MYANMAR_ZAWGYI
#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_shaper_myanmar_zawgyi;
+#endif
/* Unicode-2.0 additions */
diff --git a/thirdparty/harfbuzz/src/hb-ot-stat-table.hh b/thirdparty/harfbuzz/src/hb-ot-stat-table.hh
index af6d550c0e..59bb2daccd 100644
--- a/thirdparty/harfbuzz/src/hb-ot-stat-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-stat-table.hh
@@ -320,7 +320,7 @@ struct AxisValueFormat4
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);
+ hb_memcpy (out, this, total_size);
return_trace (true);
}
diff --git a/thirdparty/harfbuzz/src/hb-ot-tag.cc b/thirdparty/harfbuzz/src/hb-ot-tag.cc
index 1b18270cca..f6ba3b0d47 100644
--- a/thirdparty/harfbuzz/src/hb-ot-tag.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-tag.cc
@@ -577,7 +577,7 @@ hb_ot_tags_to_script_and_language (hb_tag_t script_tag,
else
{
int shift;
- memcpy (buf, lang_str, len);
+ hb_memcpy (buf, lang_str, len);
if (lang_str[0] != 'x' || lang_str[1] != '-') {
buf[len++] = '-';
buf[len++] = 'x';
diff --git a/thirdparty/harfbuzz/src/hb-ot-var-avar-table.hh b/thirdparty/harfbuzz/src/hb-ot-var-avar-table.hh
index f60bc4a3ce..cc5c5c0068 100644
--- a/thirdparty/harfbuzz/src/hb-ot-var-avar-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-var-avar-table.hh
@@ -143,7 +143,7 @@ struct avar
TRACE_SANITIZE (this);
if (!(version.sanitize (c) &&
(version.major == 1
-#ifndef HB_NO_VARIATIONS2
+#ifndef HB_NO_AVAR2
|| version.major == 2
#endif
) &&
@@ -159,7 +159,7 @@ struct avar
map = &StructAfter<SegmentMaps> (*map);
}
-#ifndef HB_NO_VARIATIONS2
+#ifndef HB_NO_AVAR2
if (version.major < 2)
return_trace (true);
@@ -182,7 +182,7 @@ struct avar
map = &StructAfter<SegmentMaps> (*map);
}
-#ifndef HB_NO_VARIATIONS2
+#ifndef HB_NO_AVAR2
if (version.major < 2)
return;
diff --git a/thirdparty/harfbuzz/src/hb-ot-var-common.hh b/thirdparty/harfbuzz/src/hb-ot-var-common.hh
index 1d29e3e4f9..4997c2e2e8 100644
--- a/thirdparty/harfbuzz/src/hb-ot-var-common.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-var-common.hh
@@ -47,7 +47,7 @@ struct DeltaSetIndexMapFormat01
HBUINT8 *p = c->allocate_size<HBUINT8> (total_size);
if (unlikely (!p)) return_trace (nullptr);
- memcpy (p, this, HBUINT8::static_size * total_size);
+ hb_memcpy (p, this, HBUINT8::static_size * total_size);
return_trace (out);
}
@@ -219,6 +219,25 @@ struct DeltaSetIndexMap
DEFINE_SIZE_UNION (1, format);
};
+
+struct VarStoreInstancer
+{
+ VarStoreInstancer (const VariationStore &varStore,
+ const DeltaSetIndexMap &varIdxMap,
+ hb_array_t<int> coords) :
+ varStore (varStore), varIdxMap (varIdxMap), coords (coords) {}
+
+ operator bool () const { return bool (coords); }
+
+ float operator() (uint32_t varIdx, unsigned short offset = 0) const
+ { return varStore.get_delta (varIdxMap.map (VarIdx::add (varIdx, offset)), coords); }
+
+ const VariationStore &varStore;
+ const DeltaSetIndexMap &varIdxMap;
+ hb_array_t<int> coords;
+};
+
+
} /* namespace OT */
diff --git a/thirdparty/harfbuzz/src/hb-ot-var-fvar-table.hh b/thirdparty/harfbuzz/src/hb-ot-var-fvar-table.hh
index af23862870..c1d57a002a 100644
--- a/thirdparty/harfbuzz/src/hb-ot-var-fvar-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-var-fvar-table.hh
@@ -59,7 +59,7 @@ struct InstanceRecord
const hb_hashmap_t<hb_tag_t, float> *axes_location = c->plan->user_axes_location;
for (unsigned i = 0 ; i < axis_count; i++)
{
- unsigned *axis_tag;
+ uint32_t *axis_tag;
// only keep instances whose coordinates == pinned axis location
if (!c->plan->axes_old_index_tag_map->has (i, &axis_tag)) continue;
@@ -337,13 +337,13 @@ struct fvar
{
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 F16DOT16&, unsigned>& _)
+ if (hb_any (+ hb_enumerate (instance->get_coordinates (axisCount))
+ | hb_filter (pinned_axes, hb_first)
+ | hb_map ([&] (const hb_pair_t<unsigned, const F16DOT16&>& _)
{
- hb_tag_t axis_tag = pinned_axes.get (_.second);
+ hb_tag_t axis_tag = pinned_axes.get (_.first);
float location = user_axes_location->get (axis_tag);
- if (fabs ((double)location - (double)_.first.to_float ()) > 0.001) return true;
+ if (fabs ((double)location - (double)_.second.to_float ()) > 0.001) return true;
return false;
})
))
diff --git a/thirdparty/harfbuzz/src/hb-ot-var-gvar-table.hh b/thirdparty/harfbuzz/src/hb-ot-var-gvar-table.hh
index bf1039d1d6..e02063ca43 100644
--- a/thirdparty/harfbuzz/src/hb-ot-var-gvar-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-var-gvar-table.hh
@@ -56,12 +56,11 @@ 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;
- if (unlikely (!resize (old_len + a.length)))
+ if (unlikely (!resize (old_len + a.length, false)))
return;
auto arrayZ = this->arrayZ + old_len;
unsigned count = a.length;
- for (unsigned int i = 0; i < count; i++)
- arrayZ[i] = a.arrayZ[i];
+ hb_memcpy (arrayZ, a.arrayZ, count * sizeof (arrayZ[0]));
}
void transform (const float (&matrix)[4])
@@ -231,8 +230,8 @@ struct GlyphVariationData
{
return (index < var_data->tupleVarCount.get_count ()) &&
var_data_bytes.check_range (current_tuple, TupleVariationHeader::min_size) &&
- var_data_bytes.check_range (current_tuple, hb_max (current_tuple->get_data_size (), current_tuple->get_size (axis_count))) &&
- current_tuple->get_size (axis_count);
+ var_data_bytes.check_range (current_tuple, hb_max (current_tuple->get_data_size (),
+ current_tuple->get_size (axis_count)));
}
bool move_to_next ()
@@ -281,42 +280,42 @@ struct GlyphVariationData
if (unlikely (p + 1 > end)) return false;
- uint16_t count = *p++;
+ unsigned count = *p++;
if (count & POINTS_ARE_WORDS)
{
if (unlikely (p + 1 > end)) return false;
count = ((count & POINT_RUN_COUNT_MASK) << 8) | *p++;
}
- if (unlikely (!points.resize (count))) return false;
+ if (unlikely (!points.resize (count, false))) return false;
- unsigned int n = 0;
- uint16_t i = 0;
+ unsigned n = 0;
+ unsigned i = 0;
while (i < count)
{
if (unlikely (p + 1 > end)) return false;
- uint16_t j;
- uint8_t control = *p++;
- uint16_t run_count = (control & POINT_RUN_COUNT_MASK) + 1;
+ unsigned control = *p++;
+ unsigned run_count = (control & POINT_RUN_COUNT_MASK) + 1;
+ if (unlikely (i + run_count > count)) return false;
+ unsigned j;
if (control & POINTS_ARE_WORDS)
{
- for (j = 0; j < run_count && i < count; j++, i++)
+ if (unlikely (p + run_count * HBUINT16::static_size > end)) return false;
+ for (j = 0; j < run_count; j++, i++)
{
- if (unlikely (p + HBUINT16::static_size > end)) return false;
n += *(const HBUINT16 *)p;
- points[i] = n;
+ points.arrayZ[i] = n;
p += HBUINT16::static_size;
}
}
else
{
- for (j = 0; j < run_count && i < count; j++, i++)
+ if (unlikely (p + run_count > end)) return false;
+ for (j = 0; j < run_count; j++, i++)
{
- if (unlikely (p + 1 > end)) return false;
n += *p++;
- points[i] = n;
+ points.arrayZ[i] = n;
}
}
- if (j < run_count) return false;
}
return true;
}
@@ -332,32 +331,37 @@ struct GlyphVariationData
DELTA_RUN_COUNT_MASK = 0x3F
};
- unsigned int i = 0;
- unsigned int count = deltas.length;
+ unsigned i = 0;
+ unsigned count = deltas.length;
while (i < count)
{
if (unlikely (p + 1 > end)) return false;
- uint8_t control = *p++;
- unsigned int run_count = (control & DELTA_RUN_COUNT_MASK) + 1;
- unsigned int j;
+ unsigned control = *p++;
+ unsigned run_count = (control & DELTA_RUN_COUNT_MASK) + 1;
+ if (unlikely (i + run_count > count)) return false;
+ unsigned j;
if (control & DELTAS_ARE_ZERO)
- for (j = 0; j < run_count && i < count; j++, i++)
- deltas[i] = 0;
+ {
+ for (j = 0; j < run_count; j++, i++)
+ deltas.arrayZ[i] = 0;
+ }
else if (control & DELTAS_ARE_WORDS)
- for (j = 0; j < run_count && i < count; j++, i++)
+ {
+ if (unlikely (p + run_count * HBUINT16::static_size > end)) return false;
+ for (j = 0; j < run_count; j++, i++)
{
- if (unlikely (p + HBUINT16::static_size > end)) return false;
- deltas[i] = *(const HBINT16 *) p;
+ deltas.arrayZ[i] = * (const HBINT16 *) p;
p += HBUINT16::static_size;
}
+ }
else
- for (j = 0; j < run_count && i < count; j++, i++)
+ {
+ if (unlikely (p + run_count > end)) return false;
+ for (j = 0; j < run_count; j++, i++)
{
- if (unlikely (p + 1 > end)) return false;
- deltas[i] = *(const HBINT8 *) p++;
+ deltas.arrayZ[i] = * (const HBINT8 *) p++;
}
- if (j < run_count)
- return false;
+ }
}
return true;
}
@@ -450,7 +454,7 @@ struct gvar
F2DOT14 *tuples = c->serializer->allocate_size<F2DOT14> (shared_tuple_size);
if (!tuples) return_trace (false);
out->sharedTuples = (char *) tuples - (char *) out;
- memcpy (tuples, this+sharedTuples, shared_tuple_size);
+ hb_memcpy (tuples, this+sharedTuples, shared_tuple_size);
}
char *subset_data = c->serializer->allocate_size<char> (subset_data_size);
@@ -473,7 +477,7 @@ struct gvar
((HBUINT16 *) subset_offsets)[gid] = glyph_offset / 2;
if (var_data_bytes.length > 0)
- memcpy (subset_data, var_data_bytes.arrayZ, var_data_bytes.length);
+ hb_memcpy (subset_data, var_data_bytes.arrayZ, var_data_bytes.length);
subset_data += var_data_bytes.length;
glyph_offset += var_data_bytes.length;
}
@@ -501,6 +505,7 @@ struct gvar
unsigned get_offset (unsigned i) const
{
if (unlikely (i > glyphCount)) return 0;
+ _hb_compiler_memory_r_barrier ();
return is_long_offset () ? get_long_offset_array ()[i] : get_short_offset_array ()[i] * 2;
}
@@ -521,11 +526,11 @@ struct gvar
unsigned int target, unsigned int prev, unsigned int next,
float contour_point_t::*m)
{
- 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;
+ float target_val = points.arrayZ[target].*m;
+ float prev_val = points.arrayZ[prev].*m;
+ float next_val = points.arrayZ[next].*m;
+ float prev_delta = deltas.arrayZ[prev].*m;
+ float next_delta = deltas.arrayZ[next].*m;
if (prev_val == next_val)
return (prev_delta == next_delta) ? prev_delta : 0.f;
@@ -543,10 +548,11 @@ struct gvar
{ return (i >= end) ? start : (i + 1); }
public:
- bool apply_deltas_to_points (hb_codepoint_t glyph, hb_font_t *font,
+ bool apply_deltas_to_points (hb_codepoint_t glyph,
+ hb_array_t<int> coords,
const hb_array_t<contour_point_t> points) const
{
- if (!font->num_coords) return true;
+ if (!coords) return true;
if (unlikely (glyph >= table->glyphCount)) return true;
@@ -559,20 +565,20 @@ struct gvar
return true; /* so isn't applied at all */
/* Save original points for inferred delta calculation */
- contour_point_vector_t orig_points;
- if (unlikely (!orig_points.resize (points.length))) return false;
- for (unsigned int i = 0; i < orig_points.length; i++)
- orig_points.arrayZ[i] = points.arrayZ[i];
+ contour_point_vector_t orig_points_vec;
+ orig_points_vec.extend (points);
+ if (unlikely (orig_points_vec.in_error ())) return false;
+ auto orig_points = orig_points_vec.as_array ();
- contour_point_vector_t deltas; /* flag is used to indicate referenced point */
- if (unlikely (!deltas.resize (points.length))) return false;
+ contour_point_vector_t deltas_vec; /* flag is used to indicate referenced point */
+ if (unlikely (!deltas_vec.resize (points.length, false))) return false;
+ auto deltas = deltas_vec.as_array ();
hb_vector_t<unsigned> end_points;
for (unsigned i = 0; i < points.length; ++i)
- if (points[i].is_end_point)
+ if (points.arrayZ[i].is_end_point)
end_points.push (i);
- 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);
@@ -598,70 +604,89 @@ struct gvar
bool apply_to_all = (indices.length == 0);
unsigned int num_deltas = apply_to_all ? points.length : indices.length;
- if (unlikely (!x_deltas.resize (num_deltas))) return false;
+ if (unlikely (!x_deltas.resize (num_deltas, false))) return false;
if (unlikely (!GlyphVariationData::unpack_deltas (p, x_deltas, end))) return false;
- if (unlikely (!y_deltas.resize (num_deltas))) return false;
+ if (unlikely (!y_deltas.resize (num_deltas, false))) 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];
- 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;
- }
+ hb_memset (deltas.arrayZ, 0, deltas.get_size ());
+
+ unsigned ref_points = 0;
+ if (scalar != 1.0f)
+ for (unsigned int i = 0; i < num_deltas; i++)
+ {
+ unsigned int pt_index = apply_to_all ? i : indices[i];
+ if (unlikely (pt_index >= deltas.length)) continue;
+ auto &delta = deltas.arrayZ[pt_index];
+ ref_points += !delta.flag;
+ delta.flag = 1; /* this point is referenced, i.e., explicit deltas specified */
+ delta.x += x_deltas.arrayZ[i] * scalar;
+ delta.y += y_deltas.arrayZ[i] * scalar;
+ }
+ else
+ for (unsigned int i = 0; i < num_deltas; i++)
+ {
+ unsigned int pt_index = apply_to_all ? i : indices[i];
+ if (unlikely (pt_index >= deltas.length)) continue;
+ auto &delta = deltas.arrayZ[pt_index];
+ ref_points += !delta.flag;
+ delta.flag = 1; /* this point is referenced, i.e., explicit deltas specified */
+ delta.x += x_deltas.arrayZ[i];
+ delta.y += y_deltas.arrayZ[i];
+ }
/* infer deltas for unreferenced points */
- unsigned start_point = 0;
- for (unsigned c = 0; c < end_points.length; c++)
+ if (ref_points && ref_points < orig_points.length)
{
- unsigned end_point = end_points[c];
+ unsigned start_point = 0;
+ for (unsigned c = 0; c < end_points.length; c++)
+ {
+ unsigned end_point = end_points.arrayZ[c];
- /* Check the number of unreferenced points in a contour. If no unref points or no ref points, nothing to do. */
- unsigned unref_count = 0;
- for (unsigned i = start_point; i <= end_point; i++)
- if (!deltas[i].flag) unref_count++;
+ /* Check the number of unreferenced points in a contour. If no unref points or no ref points, nothing to do. */
+ unsigned unref_count = 0;
+ for (unsigned i = start_point; i < end_point + 1; i++)
+ unref_count += deltas.arrayZ[i].flag;
+ unref_count = (end_point - start_point + 1) - unref_count;
- unsigned j = start_point;
- if (unref_count == 0 || unref_count > end_point - start_point)
- goto no_more_gaps;
+ unsigned j = start_point;
+ if (unref_count == 0 || unref_count > end_point - start_point)
+ goto no_more_gaps;
- for (;;)
- {
- /* Locate the next gap of unreferenced points between two referenced points prev and next.
- * Note that a gap may wrap around at left (start_point) and/or at right (end_point).
- */
- unsigned int prev, next, i;
- for (;;)
- {
- i = j;
- j = next_index (i, start_point, end_point);
- if (deltas[i].flag && !deltas[j].flag) break;
- }
- prev = j = i;
- for (;;)
- {
- i = j;
- j = next_index (i, start_point, end_point);
- if (!deltas[i].flag && deltas[j].flag) break;
- }
- next = j;
- /* Infer deltas for all unref points in the gap between prev and next */
- i = prev;
for (;;)
{
- i = next_index (i, start_point, end_point);
- if (i == next) break;
- 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;
+ /* Locate the next gap of unreferenced points between two referenced points prev and next.
+ * Note that a gap may wrap around at left (start_point) and/or at right (end_point).
+ */
+ unsigned int prev, next, i;
+ for (;;)
+ {
+ i = j;
+ j = next_index (i, start_point, end_point);
+ if (deltas.arrayZ[i].flag && !deltas.arrayZ[j].flag) break;
+ }
+ prev = j = i;
+ for (;;)
+ {
+ i = j;
+ j = next_index (i, start_point, end_point);
+ if (!deltas.arrayZ[i].flag && deltas.arrayZ[j].flag) break;
+ }
+ next = j;
+ /* Infer deltas for all unref points in the gap between prev and next */
+ i = prev;
+ for (;;)
+ {
+ i = next_index (i, start_point, end_point);
+ if (i == next) break;
+ deltas.arrayZ[i].x = infer_delta (orig_points, deltas, i, prev, next, &contour_point_t::x);
+ deltas.arrayZ[i].y = infer_delta (orig_points, deltas, i, prev, next, &contour_point_t::y);
+ if (--unref_count == 0) goto no_more_gaps;
+ }
}
+ no_more_gaps:
+ start_point = end_point + 1;
}
- no_more_gaps:
- start_point = end_point + 1;
}
/* apply specified / inferred deltas to points */
diff --git a/thirdparty/harfbuzz/src/hb-pool.hh b/thirdparty/harfbuzz/src/hb-pool.hh
index dcf8f6627d..e4bb64f627 100644
--- a/thirdparty/harfbuzz/src/hb-pool.hh
+++ b/thirdparty/harfbuzz/src/hb-pool.hh
@@ -35,15 +35,13 @@ template <typename T, unsigned ChunkLen = 16>
struct hb_pool_t
{
hb_pool_t () : next (nullptr) {}
- ~hb_pool_t () { fini (); }
-
- void fini ()
+ ~hb_pool_t ()
{
next = nullptr;
- for (chunk_t *_ : chunks) hb_free (_);
-
- chunks.fini ();
+ + hb_iter (chunks)
+ | hb_apply (hb_free)
+ ;
}
T* alloc ()
@@ -60,7 +58,7 @@ struct hb_pool_t
T* obj = next;
next = * ((T**) next);
- memset (obj, 0, sizeof (T));
+ hb_memset (obj, 0, sizeof (T));
return obj;
}
diff --git a/thirdparty/harfbuzz/src/hb-priority-queue.hh b/thirdparty/harfbuzz/src/hb-priority-queue.hh
index ffb86e30ae..ac76b7d955 100644
--- a/thirdparty/harfbuzz/src/hb-priority-queue.hh
+++ b/thirdparty/harfbuzz/src/hb-priority-queue.hh
@@ -63,7 +63,9 @@ struct hb_priority_queue_t
heap.arrayZ[0] = heap.arrayZ[heap.length - 1];
heap.shrink (heap.length - 1);
- bubble_down (0);
+
+ if (!is_empty ())
+ bubble_down (0);
return result;
}
@@ -100,7 +102,7 @@ struct hb_priority_queue_t
void bubble_down (unsigned index)
{
- assert (index <= heap.length);
+ assert (index < heap.length);
unsigned left = left_child (index);
unsigned right = right_child (index);
@@ -112,7 +114,7 @@ struct hb_priority_queue_t
bool has_right = right < heap.length;
if (heap.arrayZ[index].first <= heap.arrayZ[left].first
- && (!has_right || heap[index].first <= heap.arrayZ[right].first))
+ && (!has_right || heap.arrayZ[index].first <= heap.arrayZ[right].first))
return;
if (!has_right || heap.arrayZ[left].first < heap.arrayZ[right].first)
@@ -128,7 +130,7 @@ struct hb_priority_queue_t
void bubble_up (unsigned index)
{
- assert (index <= heap.length);
+ assert (index < heap.length);
if (index == 0) return;
@@ -142,8 +144,8 @@ struct hb_priority_queue_t
void swap (unsigned a, unsigned b)
{
- assert (a <= heap.length);
- assert (b <= heap.length);
+ assert (a < heap.length);
+ assert (b < heap.length);
hb_swap (heap.arrayZ[a], heap.arrayZ[b]);
}
};
diff --git a/thirdparty/harfbuzz/src/hb-repacker.hh b/thirdparty/harfbuzz/src/hb-repacker.hh
index c97ce6cc2c..7a3143cec3 100644
--- a/thirdparty/harfbuzz/src/hb-repacker.hh
+++ b/thirdparty/harfbuzz/src/hb-repacker.hh
@@ -209,7 +209,7 @@ bool _try_isolating_subgraphs (const hb_vector_t<graph::overflow_record_t>& over
// Only move at most half of the roots in a space at a time.
unsigned extra = roots_to_isolate.get_population () - maximum_to_move;
while (extra--) {
- unsigned root = HB_SET_VALUE_INVALID;
+ uint32_t root = HB_SET_VALUE_INVALID;
roots_to_isolate.previous (&root);
roots_to_isolate.del (root);
}
@@ -283,6 +283,11 @@ hb_resolve_graph_overflows (hb_tag_t table_tag,
graph_t& sorted_graph /* IN/OUT */)
{
sorted_graph.sort_shortest_distance ();
+ if (sorted_graph.in_error ())
+ {
+ DEBUG_MSG (SUBSET_REPACK, nullptr, "Sorted graph in error state after initial sort.");
+ return false;
+ }
bool will_overflow = graph::will_overflow (sorted_graph);
if (!will_overflow)
@@ -376,6 +381,26 @@ hb_resolve_overflows (const T& packed,
unsigned max_rounds = 20,
bool recalculate_extensions = false) {
graph_t sorted_graph (packed);
+ if (sorted_graph.in_error ())
+ {
+ // Invalid graph definition.
+ return nullptr;
+ }
+
+ if (!sorted_graph.is_fully_connected ())
+ {
+ sorted_graph.print_orphaned_nodes ();
+ return nullptr;
+ }
+
+ if (sorted_graph.in_error ())
+ {
+ // Allocations failed somewhere
+ DEBUG_MSG (SUBSET_REPACK, nullptr,
+ "Graph is in error, likely due to a memory allocation error.");
+ return nullptr;
+ }
+
if (!hb_resolve_graph_overflows (table_tag, max_rounds, recalculate_extensions, sorted_graph))
return nullptr;
diff --git a/thirdparty/harfbuzz/src/hb-sanitize.hh b/thirdparty/harfbuzz/src/hb-sanitize.hh
index 65c2772201..bd3250e580 100644
--- a/thirdparty/harfbuzz/src/hb-sanitize.hh
+++ b/thirdparty/harfbuzz/src/hb-sanitize.hh
@@ -198,10 +198,11 @@ struct hb_sanitize_context_t :
void start_processing ()
{
reset_object ();
- if (unlikely (hb_unsigned_mul_overflows (this->end - this->start, HB_SANITIZE_MAX_OPS_FACTOR)))
+ unsigned m;
+ if (unlikely (hb_unsigned_mul_overflows (this->end - this->start, HB_SANITIZE_MAX_OPS_FACTOR, &m)))
this->max_ops = HB_SANITIZE_MAX_OPS_MAX;
else
- this->max_ops = hb_clamp ((unsigned) (this->end - this->start) * HB_SANITIZE_MAX_OPS_FACTOR,
+ this->max_ops = hb_clamp (m,
(unsigned) HB_SANITIZE_MAX_OPS_MIN,
(unsigned) HB_SANITIZE_MAX_OPS_MAX);
this->edit_count = 0;
@@ -252,8 +253,9 @@ struct hb_sanitize_context_t :
unsigned int a,
unsigned int b) const
{
- return !hb_unsigned_mul_overflows (a, b) &&
- this->check_range (base, a * b);
+ unsigned m;
+ return !hb_unsigned_mul_overflows (a, b, &m) &&
+ this->check_range (base, m);
}
template <typename T>
@@ -262,8 +264,9 @@ struct hb_sanitize_context_t :
unsigned int b,
unsigned int c) const
{
- return !hb_unsigned_mul_overflows (a, b) &&
- this->check_range (base, a * b, c);
+ unsigned m;
+ return !hb_unsigned_mul_overflows (a, b, &m) &&
+ this->check_range (base, m, c);
}
template <typename T>
diff --git a/thirdparty/harfbuzz/src/hb-serialize.hh b/thirdparty/harfbuzz/src/hb-serialize.hh
index f47cde5eb5..d5573281f1 100644
--- a/thirdparty/harfbuzz/src/hb-serialize.hh
+++ b/thirdparty/harfbuzz/src/hb-serialize.hh
@@ -194,7 +194,6 @@ struct hb_serialize_context_t
current = current->next;
_->fini ();
}
- object_pool.fini ();
}
bool in_error () const { return bool (errors); }
@@ -224,6 +223,7 @@ struct hb_serialize_context_t
this->errors = HB_SERIALIZE_ERROR_NONE;
this->head = this->start;
this->tail = this->end;
+ this->zerocopy = nullptr;
this->debug_depth = 0;
fini ();
@@ -326,7 +326,8 @@ struct hb_serialize_context_t
if (unlikely (in_error() && !only_overflow ())) return;
current = current->next;
- revert (obj->head, obj->tail);
+ revert (zerocopy ? zerocopy : obj->head, obj->tail);
+ zerocopy = nullptr;
obj->fini ();
object_pool.release (obj);
}
@@ -344,8 +345,11 @@ struct hb_serialize_context_t
current = current->next;
obj->tail = head;
obj->next = nullptr;
+ assert (obj->head <= obj->tail);
unsigned len = obj->tail - obj->head;
- head = obj->head; /* Rewind head. */
+ head = zerocopy ? zerocopy : obj->head; /* Rewind head. */
+ bool was_zerocopy = zerocopy;
+ zerocopy = nullptr;
if (!len)
{
@@ -355,9 +359,11 @@ struct hb_serialize_context_t
}
objidx_t objidx;
+ uint32_t hash = 0;
if (share)
{
- objidx = packed_map.get (obj);
+ hash = hb_hash (obj);
+ objidx = packed_map.get_with_hash (obj, hash);
if (objidx)
{
merge_virtual_links (obj, objidx);
@@ -367,7 +373,10 @@ struct hb_serialize_context_t
}
tail -= len;
- memmove (tail, obj->head, len);
+ if (was_zerocopy)
+ assert (tail == obj->head);
+ else
+ memmove (tail, obj->head, len);
obj->head = tail;
obj->tail = tail + len;
@@ -385,7 +394,7 @@ struct hb_serialize_context_t
objidx = packed.length - 1;
- if (share) packed_map.set (obj, objidx);
+ if (share) packed_map.set_with_hash (obj, hash, objidx);
propagate_error (packed_map);
return objidx;
@@ -569,8 +578,26 @@ struct hb_serialize_context_t
return !bool ((errors = (errors | err_type)));
}
+ bool start_zerocopy (size_t size)
+ {
+ if (unlikely (in_error ())) return false;
+
+ if (unlikely (size > INT_MAX || this->tail - this->head < ptrdiff_t (size)))
+ {
+ err (HB_SERIALIZE_ERROR_OUT_OF_ROOM);
+ return false;
+ }
+
+ assert (!this->zerocopy);
+ this->zerocopy = this->head;
+
+ assert (this->current->head == this->head);
+ this->current->head = this->current->tail = this->head = this->tail - size;
+ return true;
+ }
+
template <typename Type>
- Type *allocate_size (size_t size)
+ Type *allocate_size (size_t size, bool clear = true)
{
if (unlikely (in_error ())) return nullptr;
@@ -579,7 +606,8 @@ struct hb_serialize_context_t
err (HB_SERIALIZE_ERROR_OUT_OF_ROOM);
return nullptr;
}
- hb_memset (this->head, 0, size);
+ if (clear)
+ hb_memset (this->head, 0, size);
char *ret = this->head;
this->head += size;
return reinterpret_cast<Type *> (ret);
@@ -593,9 +621,9 @@ struct hb_serialize_context_t
Type *embed (const Type *obj)
{
unsigned int size = obj->get_size ();
- Type *ret = this->allocate_size<Type> (size);
+ Type *ret = this->allocate_size<Type> (size, false);
if (unlikely (!ret)) return nullptr;
- memcpy (ret, obj, size);
+ hb_memcpy (ret, obj, size);
return ret;
}
template <typename Type>
@@ -616,7 +644,7 @@ struct hb_serialize_context_t
}
/* Like embed, but active: calls obj.operator=() or obj.copy() to transfer data
- * instead of memcpy(). */
+ * instead of hb_memcpy(). */
template <typename Type, typename ...Ts>
Type *copy (const Type &src, Ts&&... ds)
{ return _copy (src, hb_prioritize, std::forward<Ts> (ds)...); }
@@ -634,7 +662,7 @@ struct hb_serialize_context_t
hb_serialize_context_t& operator << (const Type &obj) & { embed (obj); return *this; }
template <typename Type>
- Type *extend_size (Type *obj, size_t size)
+ Type *extend_size (Type *obj, size_t size, bool clear = true)
{
if (unlikely (in_error ())) return nullptr;
@@ -642,12 +670,12 @@ struct hb_serialize_context_t
assert ((char *) obj <= this->head);
assert ((size_t) (this->head - (char *) obj) <= size);
if (unlikely (((char *) obj + size < (char *) obj) ||
- !this->allocate_size<Type> (((char *) obj) + size - this->head))) return nullptr;
+ !this->allocate_size<Type> (((char *) obj) + size - this->head, clear))) return nullptr;
return reinterpret_cast<Type *> (obj);
}
template <typename Type>
- Type *extend_size (Type &obj, size_t size)
- { return extend_size (std::addressof (obj), size); }
+ Type *extend_size (Type &obj, size_t size, bool clear = true)
+ { return extend_size (std::addressof (obj), size, clear); }
template <typename Type>
Type *extend_min (Type *obj) { return extend_size (obj, obj->min_size); }
@@ -676,8 +704,8 @@ struct hb_serialize_context_t
char *p = (char *) hb_malloc (len);
if (unlikely (!p)) return hb_bytes_t ();
- memcpy (p, this->start, this->head - this->start);
- memcpy (p + (this->head - this->start), this->tail, this->end - this->tail);
+ hb_memcpy (p, this->start, this->head - this->start);
+ hb_memcpy (p + (this->head - this->start), this->tail, this->end - this->tail);
return hb_bytes_t (p, len);
}
template <typename Type>
@@ -704,7 +732,7 @@ struct hb_serialize_context_t
}
public:
- char *start, *head, *tail, *end;
+ char *start, *head, *tail, *end, *zerocopy;
unsigned int debug_depth;
hb_serialize_error_t errors;
diff --git a/thirdparty/harfbuzz/src/hb-set-digest.hh b/thirdparty/harfbuzz/src/hb-set-digest.hh
index fab36216e4..e8409111f2 100644
--- a/thirdparty/harfbuzz/src/hb-set-digest.hh
+++ b/thirdparty/harfbuzz/src/hb-set-digest.hh
@@ -28,6 +28,7 @@
#define HB_SET_DIGEST_HH
#include "hb.hh"
+#include "hb-machinery.hh"
/*
* The set-digests here implement various "filters" that support
@@ -75,6 +76,8 @@ struct hb_set_digest_bits_pattern_t
void init () { mask = 0; }
+ void add (const hb_set_digest_bits_pattern_t &o) { mask |= o.mask; }
+
void add (hb_codepoint_t g) { mask |= mask_for (g); }
bool add_range (hb_codepoint_t a, hb_codepoint_t b)
@@ -95,7 +98,7 @@ struct hb_set_digest_bits_pattern_t
for (unsigned int i = 0; i < count; i++)
{
add (*array);
- array = (const T *) (stride + (const char *) array);
+ array = &StructAtOffsetUnaligned<T> ((const void *) array, stride);
}
}
template <typename T>
@@ -103,16 +106,15 @@ struct hb_set_digest_bits_pattern_t
template <typename T>
bool add_sorted_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
{
- for (unsigned int i = 0; i < count; i++)
- {
- add (*array);
- array = (const T *) (stride + (const char *) array);
- }
+ add_array (array, count, stride);
return true;
}
template <typename T>
bool add_sorted_array (const hb_sorted_array_t<const T>& arr) { return add_sorted_array (&arr, arr.len ()); }
+ bool may_have (const hb_set_digest_bits_pattern_t &o) const
+ { return mask & o.mask; }
+
bool may_have (hb_codepoint_t g) const
{ return mask & mask_for (g); }
@@ -132,6 +134,12 @@ struct hb_set_digest_combiner_t
tail.init ();
}
+ void add (const hb_set_digest_combiner_t &o)
+ {
+ head.add (o.head);
+ tail.add (o.tail);
+ }
+
void add (hb_codepoint_t g)
{
head.add (g);
@@ -140,9 +148,8 @@ struct hb_set_digest_combiner_t
bool add_range (hb_codepoint_t a, hb_codepoint_t b)
{
- head.add_range (a, b);
- tail.add_range (a, b);
- return true;
+ return head.add_range (a, b) &&
+ tail.add_range (a, b);
}
template <typename T>
void add_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
@@ -155,13 +162,17 @@ struct hb_set_digest_combiner_t
template <typename T>
bool add_sorted_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
{
- head.add_sorted_array (array, count, stride);
- tail.add_sorted_array (array, count, stride);
- return true;
+ return head.add_sorted_array (array, count, stride) &&
+ tail.add_sorted_array (array, count, stride);
}
template <typename T>
bool add_sorted_array (const hb_sorted_array_t<const T>& arr) { return add_sorted_array (&arr, arr.len ()); }
+ bool may_have (const hb_set_digest_combiner_t &o) const
+ {
+ return head.may_have (o.head) && tail.may_have (o.tail);
+ }
+
bool may_have (hb_codepoint_t g) const
{
return head.may_have (g) && tail.may_have (g);
diff --git a/thirdparty/harfbuzz/src/hb-set.hh b/thirdparty/harfbuzz/src/hb-set.hh
index 5d5576cb9e..f958a081fb 100644
--- a/thirdparty/harfbuzz/src/hb-set.hh
+++ b/thirdparty/harfbuzz/src/hb-set.hh
@@ -105,10 +105,8 @@ struct hb_sparseset_t
bool get (hb_codepoint_t g) const { return s.get (g); }
/* Has interface. */
- static constexpr bool SENTINEL = false;
- typedef bool value_t;
- value_t operator [] (hb_codepoint_t k) const { return get (k); }
- bool has (hb_codepoint_t k) const { return (*this)[k] != SENTINEL; }
+ bool operator [] (hb_codepoint_t k) const { return get (k); }
+ bool has (hb_codepoint_t k) const { return (*this)[k]; }
/* Predicate. */
bool operator () (hb_codepoint_t k) const { return has (k); }
diff --git a/thirdparty/harfbuzz/src/hb-shape-plan.cc b/thirdparty/harfbuzz/src/hb-shape-plan.cc
index 9e513c0458..cabcbd4e72 100644
--- a/thirdparty/harfbuzz/src/hb-shape-plan.cc
+++ b/thirdparty/harfbuzz/src/hb-shape-plan.cc
@@ -31,6 +31,8 @@
#include "hb-buffer.hh"
+#ifndef HB_NO_SHAPER
+
/**
* SECTION:hb-shape-plan
* @title: hb-shape-plan
@@ -74,7 +76,7 @@ hb_shape_plan_key_t::init (bool copy,
this->user_features = copy ? features : user_features;
if (copy && num_user_features)
{
- memcpy (features, user_features, num_user_features * sizeof (hb_feature_t));
+ hb_memcpy (features, user_features, num_user_features * sizeof (hb_feature_t));
/* Make start/end uniform to easier catch bugs. */
for (unsigned int i = 0; i < num_user_features; i++)
{
@@ -574,3 +576,6 @@ retry:
return hb_shape_plan_reference (shape_plan);
}
+
+
+#endif
diff --git a/thirdparty/harfbuzz/src/hb-shape.cc b/thirdparty/harfbuzz/src/hb-shape.cc
index 547d0afc47..7b5bf2c5ef 100644
--- a/thirdparty/harfbuzz/src/hb-shape.cc
+++ b/thirdparty/harfbuzz/src/hb-shape.cc
@@ -35,6 +35,8 @@
#include "hb-machinery.hh"
+#ifndef HB_NO_SHAPER
+
/**
* SECTION:hb-shape
* @title: hb-shape
@@ -192,3 +194,6 @@ hb_shape (hb_font_t *font,
{
hb_shape_full (font, buffer, features, num_features, nullptr);
}
+
+
+#endif
diff --git a/thirdparty/harfbuzz/src/hb-shaper.cc b/thirdparty/harfbuzz/src/hb-shaper.cc
index a900ac6991..c4885cda94 100644
--- a/thirdparty/harfbuzz/src/hb-shaper.cc
+++ b/thirdparty/harfbuzz/src/hb-shaper.cc
@@ -53,7 +53,7 @@ static struct hb_shapers_lazy_loader_t : hb_lazy_loader_t<hb_shaper_entry_t,
if (unlikely (!shapers))
return nullptr;
- memcpy (shapers, _hb_all_shapers, sizeof (_hb_all_shapers));
+ hb_memcpy (shapers, _hb_all_shapers, sizeof (_hb_all_shapers));
/* Reorder shaper list to prefer requested shapers. */
unsigned int i = 0;
diff --git a/thirdparty/harfbuzz/src/hb-static.cc b/thirdparty/harfbuzz/src/hb-static.cc
index 5d4c7cda1b..eac50754c2 100644
--- a/thirdparty/harfbuzz/src/hb-static.cc
+++ b/thirdparty/harfbuzz/src/hb-static.cc
@@ -33,6 +33,7 @@
#include "hb-aat-layout-feat-table.hh"
#include "hb-ot-layout-common.hh"
#include "hb-ot-cmap-table.hh"
+#include "hb-ot-color-colr-table.hh"
#include "hb-ot-glyf-table.hh"
#include "hb-ot-head-table.hh"
#include "hb-ot-maxp-table.hh"
@@ -47,6 +48,7 @@ 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) = {0x01};
+DEFINE_NULL_NAMESPACE_BYTES (OT, ClipRecord) = {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};
DEFINE_NULL_NAMESPACE_BYTES (AAT, Lookup) = {0xFF,0xFF};
diff --git a/thirdparty/harfbuzz/src/hb-subset-accelerator.hh b/thirdparty/harfbuzz/src/hb-subset-accelerator.hh
index 34bd0534fb..63ae6d77e2 100644
--- a/thirdparty/harfbuzz/src/hb-subset-accelerator.hh
+++ b/thirdparty/harfbuzz/src/hb-subset-accelerator.hh
@@ -31,21 +31,34 @@
#include "hb.hh"
#include "hb-map.hh"
+#include "hb-multimap.hh"
#include "hb-set.hh"
+extern HB_INTERNAL hb_user_data_key_t _hb_subset_accelerator_user_data_key;
+
+namespace CFF {
+struct cff_subset_accelerator_t;
+}
+
+namespace OT {
+struct SubtableUnicodesCache;
+};
+
struct hb_subset_accelerator_t
{
static hb_user_data_key_t* user_data_key()
{
- static hb_user_data_key_t key;
- return &key;
+ return &_hb_subset_accelerator_user_data_key;
}
static hb_subset_accelerator_t* create(const hb_map_t& unicode_to_gid_,
- const hb_set_t& unicodes_) {
+ const hb_multimap_t gid_to_unicodes_,
+ const hb_set_t& unicodes_,
+ bool has_seac_) {
hb_subset_accelerator_t* accel =
(hb_subset_accelerator_t*) hb_malloc (sizeof(hb_subset_accelerator_t));
- new (accel) hb_subset_accelerator_t (unicode_to_gid_, unicodes_);
+ new (accel) hb_subset_accelerator_t (unicode_to_gid_, gid_to_unicodes_, unicodes_);
+ accel->has_seac = has_seac_;
return accel;
}
@@ -53,22 +66,54 @@ struct hb_subset_accelerator_t
if (!value) return;
hb_subset_accelerator_t* accel = (hb_subset_accelerator_t*) value;
+
+ if (accel->cff_accelerator && accel->destroy_cff_accelerator)
+ accel->destroy_cff_accelerator ((void*) accel->cff_accelerator);
+
+ if (accel->cmap_cache && accel->destroy_cmap_cache)
+ accel->destroy_cmap_cache ((void*) accel->cmap_cache);
+
accel->~hb_subset_accelerator_t ();
hb_free (accel);
}
- hb_subset_accelerator_t(const hb_map_t& unicode_to_gid_,
+ hb_subset_accelerator_t (const hb_map_t& unicode_to_gid_,
+ const hb_multimap_t& gid_to_unicodes_,
const hb_set_t& unicodes_)
- : unicode_to_gid(unicode_to_gid_), unicodes(unicodes_) {}
+ : unicode_to_gid(unicode_to_gid_), gid_to_unicodes (gid_to_unicodes_), unicodes(unicodes_),
+ cmap_cache(nullptr), destroy_cmap_cache(nullptr),
+ has_seac(false), cff_accelerator(nullptr), destroy_cff_accelerator(nullptr)
+ { sanitized_table_cache_lock.init (); }
+
+ ~hb_subset_accelerator_t ()
+ { sanitized_table_cache_lock.fini (); }
+
+ // Generic
+
+ mutable hb_mutex_t sanitized_table_cache_lock;
+ mutable hb_hashmap_t<hb_tag_t, hb::unique_ptr<hb_blob_t>> sanitized_table_cache;
const hb_map_t unicode_to_gid;
+ const hb_multimap_t gid_to_unicodes;
const hb_set_t unicodes;
+
+ // cmap
+ const OT::SubtableUnicodesCache* cmap_cache;
+ hb_destroy_func_t destroy_cmap_cache;
+
+ // CFF
+ bool has_seac;
+ const CFF::cff_subset_accelerator_t* cff_accelerator;
+ hb_destroy_func_t destroy_cff_accelerator;
+
// TODO(garretrieger): cumulative glyf checksum map
- // TODO(garretrieger): sanitized table cache.
bool in_error () const
{
- return unicode_to_gid.in_error() || unicodes.in_error ();
+ return unicode_to_gid.in_error () ||
+ gid_to_unicodes.in_error () ||
+ unicodes.in_error () ||
+ sanitized_table_cache.in_error ();
}
};
diff --git a/thirdparty/harfbuzz/src/hb-subset-cff-common.cc b/thirdparty/harfbuzz/src/hb-subset-cff-common.cc
index 711b2236d6..6e1b6f713d 100644
--- a/thirdparty/harfbuzz/src/hb-subset-cff-common.cc
+++ b/thirdparty/harfbuzz/src/hb-subset-cff-common.cc
@@ -66,8 +66,7 @@ hb_plan_subset_cff_fdselect (const hb_subset_plan_t *plan,
{
/* use hb_set to determine the subset of font dicts */
- hb_set_t *set = hb_set_create ();
- if (unlikely (set == &Null (hb_set_t))) return false;
+ hb_set_t set;
hb_codepoint_t prev_fd = CFF_UNDEF_CODE;
for (hb_codepoint_t i = 0; i < subset_num_glyphs; i++)
{
@@ -79,7 +78,7 @@ hb_plan_subset_cff_fdselect (const hb_subset_plan_t *plan,
glyph = i;
}
fd = src.get_fd (glyph);
- set->add (fd);
+ set.add (fd);
if (fd != prev_fd)
{
@@ -90,12 +89,11 @@ hb_plan_subset_cff_fdselect (const hb_subset_plan_t *plan,
}
}
- subset_fd_count = set->get_population ();
+ subset_fd_count = set.get_population ();
if (subset_fd_count == fdCount)
{
/* all font dicts belong to the subset. no need to subset FDSelect & FDArray */
fdmap.identity (fdCount);
- hb_set_destroy (set);
}
else
{
@@ -103,9 +101,8 @@ hb_plan_subset_cff_fdselect (const hb_subset_plan_t *plan,
fdmap.reset ();
hb_codepoint_t fd = CFF_UNDEF_CODE;
- while (set->next (&fd))
+ while (set.next (&fd))
fdmap.add (fd);
- hb_set_destroy (set);
if (unlikely (fdmap.get_population () != subset_fd_count))
return false;
}
diff --git a/thirdparty/harfbuzz/src/hb-subset-cff-common.hh b/thirdparty/harfbuzz/src/hb-subset-cff-common.hh
index bb9f27eec1..8bbc017656 100644
--- a/thirdparty/harfbuzz/src/hb-subset-cff-common.hh
+++ b/thirdparty/harfbuzz/src/hb-subset-cff-common.hh
@@ -38,15 +38,16 @@ namespace CFF {
struct str_encoder_t
{
str_encoder_t (str_buff_t &buff_)
- : buff (buff_), error (false) {}
+ : buff (buff_) {}
void reset () { buff.reset (); }
void encode_byte (unsigned char b)
{
- buff.push (b);
- if (unlikely (buff.in_error ()))
- set_error ();
+ if (likely ((signed) buff.length < buff.allocated))
+ buff.arrayZ[buff.length++] = b;
+ else
+ buff.push (b);
}
void encode_int (int v)
@@ -108,27 +109,18 @@ struct str_encoder_t
encode_byte (op);
}
- void copy_str (const hb_ubytes_t &str)
+ void copy_str (const unsigned char *str, unsigned length)
{
- unsigned int offset = buff.length;
- /* Manually resize buffer since faster. */
- if ((signed) (buff.length + str.length) <= buff.allocated)
- buff.length += str.length;
- else if (unlikely (!buff.resize (offset + str.length)))
- {
- set_error ();
- return;
- }
- memcpy (buff.arrayZ + offset, &str[0], str.length);
+ assert ((signed) (buff.length + length) <= buff.allocated);
+ hb_memcpy (buff.arrayZ + buff.length, str, length);
+ buff.length += length;
}
- bool is_error () const { return error; }
+ bool in_error () const { return buff.in_error (); }
protected:
- void set_error () { error = true; }
str_buff_t &buff;
- bool error;
};
struct cff_sub_table_info_t {
@@ -187,9 +179,12 @@ struct cff_font_dict_op_serializer_t : op_serializer_t
}
else
{
- HBUINT8 *d = c->allocate_size<HBUINT8> (opstr.str.length);
+ unsigned char *d = c->allocate_size<unsigned char> (opstr.length);
if (unlikely (!d)) return_trace (false);
- memcpy (d, &opstr.str[0], opstr.str.length);
+ /* Faster than hb_memcpy for small strings. */
+ for (unsigned i = 0; i < opstr.length; i++)
+ d[i] = opstr.ptr[i];
+ //hb_memcpy (d, opstr.ptr, opstr.length);
}
return_trace (true);
}
@@ -239,11 +234,10 @@ struct subr_flattener_t
bool flatten (str_buff_vec_t &flat_charstrings)
{
- if (!flat_charstrings.resize (plan->num_output_glyphs ()))
+ unsigned count = plan->num_output_glyphs ();
+ if (!flat_charstrings.resize (count))
return false;
- for (unsigned int i = 0; i < plan->num_output_glyphs (); i++)
- flat_charstrings[i].init ();
- for (unsigned int i = 0; i < plan->num_output_glyphs (); i++)
+ for (unsigned int i = 0; i < count; i++)
{
hb_codepoint_t glyph;
if (!plan->old_gid_for_new_gid (i, &glyph))
@@ -259,7 +253,7 @@ struct subr_flattener_t
ENV env (str, acc, fd);
cs_interpreter_t<ENV, OPSET, flatten_param_t> interp (env);
flatten_param_t param = {
- flat_charstrings[i],
+ flat_charstrings.arrayZ[i],
(bool) (plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
};
if (unlikely (!interp.interpret (param)))
@@ -274,11 +268,9 @@ struct subr_flattener_t
struct subr_closures_t
{
- subr_closures_t (unsigned int fd_count) : valid (false), global_closure (), local_closures ()
+ subr_closures_t (unsigned int fd_count) : global_closure (), local_closures ()
{
- valid = true;
- if (!local_closures.resize (fd_count))
- valid = false;
+ local_closures.resize (fd_count);
}
void reset ()
@@ -288,47 +280,38 @@ struct subr_closures_t
local_closures[i].clear();
}
- bool is_valid () const { return valid; }
- bool valid;
+ bool in_error () const { return local_closures.in_error (); }
hb_set_t global_closure;
hb_vector_t<hb_set_t> local_closures;
};
struct parsed_cs_op_t : op_str_t
{
- void init (unsigned int subr_num_ = 0)
- {
- subr_num = subr_num_;
- drop_flag = false;
- keep_flag = false;
- skip_flag = false;
- }
-
- bool for_drop () const { return drop_flag; }
- void set_drop () { if (!for_keep ()) drop_flag = true; }
+ parsed_cs_op_t (unsigned int subr_num_ = 0) :
+ subr_num (subr_num_) {}
- bool for_keep () const { return keep_flag; }
- void set_keep () { keep_flag = true; }
+ bool is_hinting () const { return hinting_flag; }
+ void set_hinting () { hinting_flag = true; }
- bool for_skip () const { return skip_flag; }
- void set_skip () { skip_flag = true; }
-
- unsigned int subr_num;
+ /* The layout of this struct is designed to fit within the
+ * padding of op_str_t! */
protected:
- bool drop_flag;
- bool keep_flag;
- bool skip_flag;
+ bool hinting_flag = false;
+
+ public:
+ uint16_t subr_num;
};
struct parsed_cs_str_t : parsed_values_t<parsed_cs_op_t>
{
- void init ()
+ parsed_cs_str_t () :
+ parsed (false),
+ hint_dropped (false),
+ has_prefix_ (false),
+ has_calls_ (false)
{
SUPER::init ();
- parsed = false;
- hint_dropped = false;
- has_prefix_ = false;
}
void add_op (op_code_t op, const byte_str_ref_t& str_ref)
@@ -341,13 +324,12 @@ struct parsed_cs_str_t : parsed_values_t<parsed_cs_op_t>
{
if (!is_parsed ())
{
- unsigned int parsed_len = get_count ();
- if (likely (parsed_len > 0))
- values[parsed_len-1].set_skip ();
+ has_calls_ = true;
- parsed_cs_op_t val;
- val.init (subr_num);
- SUPER::add_op (op, str_ref, val);
+ /* Pop the subroutine number. */
+ values.pop ();
+
+ SUPER::add_op (op, str_ref, {subr_num});
}
}
@@ -377,11 +359,14 @@ struct parsed_cs_str_t : parsed_values_t<parsed_cs_op_t>
op_code_t prefix_op () const { return prefix_op_; }
const number_t &prefix_num () const { return prefix_num_; }
+ bool has_calls () const { return has_calls_; }
+
protected:
- bool parsed;
- bool hint_dropped;
- bool vsindex_dropped;
- bool has_prefix_;
+ bool parsed : 1;
+ bool hint_dropped : 1;
+ bool vsindex_dropped : 1;
+ bool has_prefix_ : 1;
+ bool has_calls_ : 1;
op_code_t prefix_op_;
number_t prefix_num_;
@@ -395,6 +380,59 @@ struct parsed_cs_str_vec_t : hb_vector_t<parsed_cs_str_t>
typedef hb_vector_t<parsed_cs_str_t> SUPER;
};
+struct cff_subset_accelerator_t
+{
+ static cff_subset_accelerator_t* create (
+ hb_blob_t* original_blob,
+ const parsed_cs_str_vec_t& parsed_charstrings,
+ const parsed_cs_str_vec_t& parsed_global_subrs,
+ const hb_vector_t<parsed_cs_str_vec_t>& parsed_local_subrs) {
+ cff_subset_accelerator_t* accel =
+ (cff_subset_accelerator_t*) hb_malloc (sizeof(cff_subset_accelerator_t));
+ new (accel) cff_subset_accelerator_t (original_blob,
+ parsed_charstrings,
+ parsed_global_subrs,
+ parsed_local_subrs);
+ return accel;
+ }
+
+ static void destroy (void* value) {
+ if (!value) return;
+
+ cff_subset_accelerator_t* accel = (cff_subset_accelerator_t*) value;
+ accel->~cff_subset_accelerator_t ();
+ hb_free (accel);
+ }
+
+ cff_subset_accelerator_t(
+ hb_blob_t* original_blob_,
+ const parsed_cs_str_vec_t& parsed_charstrings_,
+ const parsed_cs_str_vec_t& parsed_global_subrs_,
+ const hb_vector_t<parsed_cs_str_vec_t>& parsed_local_subrs_)
+ {
+ parsed_charstrings = parsed_charstrings_;
+ parsed_global_subrs = parsed_global_subrs_;
+ parsed_local_subrs = parsed_local_subrs_;
+
+ // the parsed charstrings point to memory in the original CFF table so we must hold a reference
+ // to it to keep the memory valid.
+ original_blob = hb_blob_reference (original_blob_);
+ }
+
+ ~cff_subset_accelerator_t() {
+ hb_blob_destroy (original_blob);
+ hb_map_destroy (glyph_to_sid_map.get_relaxed ());
+ }
+
+ parsed_cs_str_vec_t parsed_charstrings;
+ parsed_cs_str_vec_t parsed_global_subrs;
+ hb_vector_t<parsed_cs_str_vec_t> parsed_local_subrs;
+ mutable hb_atomic_ptr_t<hb_map_t> glyph_to_sid_map = nullptr;
+
+ private:
+ hb_blob_t* original_blob;
+};
+
struct subr_subset_param_t
{
subr_subset_param_t (parsed_cs_str_t *parsed_charstring_,
@@ -446,7 +484,11 @@ struct subr_subset_param_t
if (unlikely (calling && !parsed_str->is_parsed () && (parsed_str->values.length > 0)))
env.set_error ();
else
+ {
+ if (!parsed_str->is_parsed ())
+ parsed_str->alloc (env.str_ref.total_size () / 2);
current_parsed_str = parsed_str;
+ }
}
parsed_cs_str_t *current_parsed_str;
@@ -506,7 +548,7 @@ struct subr_remaps_t
{
global_remap.create (&closures.global_closure);
for (unsigned int i = 0; i < local_remaps.length; i++)
- local_remaps[i].create (&closures.local_closures[i]);
+ local_remaps.arrayZ[i].create (&closures.local_closures[i]);
}
subr_remap_t global_remap;
@@ -517,7 +559,8 @@ template <typename SUBSETTER, typename SUBRS, typename ACC, typename ENV, typena
struct subr_subsetter_t
{
subr_subsetter_t (ACC &acc_, const hb_subset_plan_t *plan_)
- : acc (acc_), plan (plan_), closures(acc_.fdCount), remaps(acc_.fdCount)
+ : acc (acc_), plan (plan_), closures(acc_.fdCount),
+ remaps(acc_.fdCount)
{}
/* Subroutine subsetting with --no-desubroutinize runs in phases:
@@ -536,55 +579,96 @@ struct subr_subsetter_t
*/
bool subset (void)
{
- parsed_charstrings.resize (plan->num_output_glyphs ());
- parsed_global_subrs.resize (acc.globalSubrs->count);
-
- if (unlikely (remaps.in_error()
- || parsed_charstrings.in_error ()
- || parsed_global_subrs.in_error ())) {
- return false;
+ unsigned fd_count = acc.fdCount;
+ const cff_subset_accelerator_t* cff_accelerator = nullptr;
+ if (plan->accelerator && plan->accelerator->cff_accelerator) {
+ cff_accelerator = plan->accelerator->cff_accelerator;
+ fd_count = cff_accelerator->parsed_local_subrs.length;
}
- if (unlikely (!parsed_local_subrs.resize (acc.fdCount))) return false;
+ if (cff_accelerator) {
+ // If we are not dropping hinting then charstrings are not modified so we can
+ // just use a reference to the cached copies.
+ cached_charstrings.resize (plan->num_output_glyphs ());
+ parsed_global_subrs = &cff_accelerator->parsed_global_subrs;
+ parsed_local_subrs = &cff_accelerator->parsed_local_subrs;
+ } else {
+ parsed_charstrings.resize (plan->num_output_glyphs ());
+ parsed_global_subrs_storage.resize (acc.globalSubrs->count);
- for (unsigned int i = 0; i < acc.fdCount; i++)
- {
- parsed_local_subrs[i].resize (acc.privateDicts[i].localSubrs->count);
- if (unlikely (parsed_local_subrs[i].in_error ())) return false;
+ if (unlikely (!parsed_local_subrs_storage.resize (fd_count))) return false;
+
+ for (unsigned int i = 0; i < acc.fdCount; i++)
+ {
+ unsigned count = acc.privateDicts[i].localSubrs->count;
+ parsed_local_subrs_storage[i].resize (count);
+ if (unlikely (parsed_local_subrs_storage[i].in_error ())) return false;
+ }
+
+ parsed_global_subrs = &parsed_global_subrs_storage;
+ parsed_local_subrs = &parsed_local_subrs_storage;
}
- if (unlikely (!closures.valid))
+
+ if (unlikely (remaps.in_error()
+ || cached_charstrings.in_error ()
+ || parsed_charstrings.in_error ()
+ || parsed_global_subrs->in_error ()
+ || closures.in_error ())) {
return false;
+ }
/* phase 1 & 2 */
for (unsigned int i = 0; i < plan->num_output_glyphs (); i++)
{
hb_codepoint_t glyph;
if (!plan->old_gid_for_new_gid (i, &glyph))
- continue;
+ continue;
+
const hb_ubytes_t str = (*acc.charStrings)[glyph];
unsigned int fd = acc.fdSelect->get_fd (glyph);
if (unlikely (fd >= acc.fdCount))
- return false;
+ return false;
+
+ if (cff_accelerator)
+ {
+ // parsed string already exists in accelerator, copy it and move
+ // on.
+ if (cached_charstrings)
+ cached_charstrings[i] = &cff_accelerator->parsed_charstrings[glyph];
+ else
+ parsed_charstrings[i] = cff_accelerator->parsed_charstrings[glyph];
+
+ continue;
+ }
ENV env (str, acc, fd);
cs_interpreter_t<ENV, OPSET, subr_subset_param_t> interp (env);
- parsed_charstrings[i].alloc (str.length);
+ parsed_charstrings[i].alloc (str.length / 2);
subr_subset_param_t param (&parsed_charstrings[i],
- &parsed_global_subrs,
- &parsed_local_subrs[fd],
- &closures.global_closure,
- &closures.local_closures[fd],
- plan->flags & HB_SUBSET_FLAGS_NO_HINTING);
+ &parsed_global_subrs_storage,
+ &parsed_local_subrs_storage[fd],
+ &closures.global_closure,
+ &closures.local_closures[fd],
+ plan->flags & HB_SUBSET_FLAGS_NO_HINTING);
if (unlikely (!interp.interpret (param)))
- return false;
+ return false;
/* complete parsed string esp. copy CFF1 width or CFF2 vsindex to the parsed charstring for encoding */
SUBSETTER::complete_parsed_str (interp.env, param, parsed_charstrings[i]);
}
- if (plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
+ // Since parsed strings were loaded from accelerator, we still need
+ // to compute the subroutine closures which would have normally happened during
+ // parsing.
+ if (cff_accelerator &&
+ !closure_subroutines(*parsed_global_subrs,
+ *parsed_local_subrs))
+ return false;
+
+ if ((plan->flags & HB_SUBSET_FLAGS_NO_HINTING && !cff_accelerator) ||
+ plan->inprogress_accelerator)
{
/* mark hint ops and arguments for drop */
for (unsigned int i = 0; i < plan->num_output_glyphs (); i++)
@@ -596,8 +680,8 @@ struct subr_subsetter_t
if (unlikely (fd >= acc.fdCount))
return false;
subr_subset_param_t param (&parsed_charstrings[i],
- &parsed_global_subrs,
- &parsed_local_subrs[fd],
+ &parsed_global_subrs_storage,
+ &parsed_local_subrs_storage[fd],
&closures.global_closure,
&closures.local_closures[fd],
plan->flags & HB_SUBSET_FLAGS_NO_HINTING);
@@ -612,27 +696,14 @@ struct subr_subsetter_t
}
/* after dropping hints recreate closures of actually used subrs */
- closures.reset ();
- for (unsigned int i = 0; i < plan->num_output_glyphs (); i++)
- {
- hb_codepoint_t glyph;
- if (!plan->old_gid_for_new_gid (i, &glyph))
- continue;
- unsigned int fd = acc.fdSelect->get_fd (glyph);
- if (unlikely (fd >= acc.fdCount))
- return false;
- subr_subset_param_t param (&parsed_charstrings[i],
- &parsed_global_subrs,
- &parsed_local_subrs[fd],
- &closures.global_closure,
- &closures.local_closures[fd],
- plan->flags & HB_SUBSET_FLAGS_NO_HINTING);
- collect_subr_refs_in_str (parsed_charstrings[i], param);
- }
+ if (plan->flags & HB_SUBSET_FLAGS_NO_HINTING &&
+ !cff_accelerator &&
+ !closure_subroutines(*parsed_global_subrs, *parsed_local_subrs)) return false;
}
remaps.create (closures);
+ populate_subset_accelerator ();
return true;
}
@@ -646,13 +717,13 @@ struct subr_subsetter_t
if (!plan->old_gid_for_new_gid (i, &glyph))
{
/* add an endchar only charstring for a missing glyph if CFF1 */
- if (endchar_op != OpCode_Invalid) buffArray[i].push (endchar_op);
+ if (endchar_op != OpCode_Invalid) buffArray.arrayZ[i].push (endchar_op);
continue;
}
unsigned int fd = acc.fdSelect->get_fd (glyph);
if (unlikely (fd >= acc.fdCount))
return false;
- if (unlikely (!encode_str (parsed_charstrings[i], fd, buffArray[i])))
+ if (unlikely (!encode_str (get_parsed_charstring (i), fd, buffArray.arrayZ[i])))
return false;
}
return true;
@@ -664,26 +735,25 @@ struct subr_subsetter_t
if (unlikely (!buffArray.resize (count)))
return false;
- for (unsigned int old_num = 0; old_num < subrs.length; old_num++)
+ for (unsigned int new_num = 0; new_num < count; new_num++)
{
- hb_codepoint_t new_num = remap[old_num];
- if (new_num != CFF_UNDEF_CODE)
- {
- if (unlikely (!encode_str (subrs[old_num], fd, buffArray[new_num])))
- return false;
- }
+ hb_codepoint_t old_num = remap.backward (new_num);
+ assert (old_num != CFF_UNDEF_CODE);
+
+ if (unlikely (!encode_str (subrs[old_num], fd, buffArray[new_num])))
+ return false;
}
return true;
}
bool encode_globalsubrs (str_buff_vec_t &buffArray)
{
- return encode_subrs (parsed_global_subrs, remaps.global_remap, 0, buffArray);
+ return encode_subrs (*parsed_global_subrs, remaps.global_remap, 0, buffArray);
}
bool encode_localsubrs (unsigned int fd, str_buff_vec_t &buffArray) const
{
- return encode_subrs (parsed_local_subrs[fd], remaps.local_remaps[fd], fd, buffArray);
+ return encode_subrs ((*parsed_local_subrs)[fd], remaps.local_remaps[fd], fd, buffArray);
}
protected:
@@ -712,7 +782,7 @@ struct subr_subsetter_t
* then this entire subroutine must be a hint. drop its call. */
if (drop.ends_in_hint)
{
- str.values[pos].set_drop ();
+ str.values[pos].set_hinting ();
/* if this subr call is at the end of the parent subr, propagate the flag
* otherwise reset the flag */
if (!str.at_end (pos))
@@ -720,7 +790,7 @@ struct subr_subsetter_t
}
else if (drop.all_dropped)
{
- str.values[pos].set_drop ();
+ str.values[pos].set_hinting ();
}
return has_hint;
@@ -731,20 +801,22 @@ struct subr_subsetter_t
{
bool seen_hint = false;
- for (unsigned int pos = 0; pos < str.values.length; pos++)
+ unsigned count = str.values.length;
+ auto *values = str.values.arrayZ;
+ for (unsigned int pos = 0; pos < count; pos++)
{
bool has_hint = false;
- switch (str.values[pos].op)
+ switch (values[pos].op)
{
case OpCode_callsubr:
has_hint = drop_hints_in_subr (str, pos,
- *param.parsed_local_subrs, str.values[pos].subr_num,
+ *param.parsed_local_subrs, values[pos].subr_num,
param, drop);
break;
case OpCode_callgsubr:
has_hint = drop_hints_in_subr (str, pos,
- *param.parsed_global_subrs, str.values[pos].subr_num,
+ *param.parsed_global_subrs, values[pos].subr_num,
param, drop);
break;
@@ -758,7 +830,7 @@ struct subr_subsetter_t
case OpCode_cntrmask:
if (drop.seen_moveto)
{
- str.values[pos].set_drop ();
+ values[pos].set_hinting ();
break;
}
HB_FALLTHROUGH;
@@ -768,13 +840,13 @@ struct subr_subsetter_t
case OpCode_hstem:
case OpCode_vstem:
has_hint = true;
- str.values[pos].set_drop ();
+ values[pos].set_hinting ();
if (str.at_end (pos))
drop.ends_in_hint = true;
break;
case OpCode_dotsection:
- str.values[pos].set_drop ();
+ values[pos].set_hinting ();
break;
default:
@@ -785,10 +857,10 @@ struct subr_subsetter_t
{
for (int i = pos - 1; i >= 0; i--)
{
- parsed_cs_op_t &csop = str.values[(unsigned)i];
- if (csop.for_drop ())
+ parsed_cs_op_t &csop = values[(unsigned)i];
+ if (csop.is_hinting ())
break;
- csop.set_drop ();
+ csop.set_hinting ();
if (csop.op == OpCode_vsindexcs)
drop.vsindex_dropped = true;
}
@@ -801,12 +873,12 @@ struct subr_subsetter_t
* only (usually one) hintmask operator, then calls to this subr can be dropped.
*/
drop.all_dropped = true;
- for (unsigned int pos = 0; pos < str.values.length; pos++)
+ for (unsigned int pos = 0; pos < count; pos++)
{
- parsed_cs_op_t &csop = str.values[pos];
+ parsed_cs_op_t &csop = values[pos];
if (csop.op == OpCode_return)
break;
- if (!csop.for_drop ())
+ if (!csop.is_hinting ())
{
drop.all_dropped = false;
break;
@@ -816,32 +888,62 @@ struct subr_subsetter_t
return seen_hint;
}
- void collect_subr_refs_in_subr (parsed_cs_str_t &str, unsigned int pos,
- unsigned int subr_num, parsed_cs_str_vec_t &subrs,
+ bool closure_subroutines (const parsed_cs_str_vec_t& global_subrs,
+ const hb_vector_t<parsed_cs_str_vec_t>& local_subrs)
+ {
+ closures.reset ();
+ for (unsigned int i = 0; i < plan->num_output_glyphs (); i++)
+ {
+ hb_codepoint_t glyph;
+ if (!plan->old_gid_for_new_gid (i, &glyph))
+ continue;
+ unsigned int fd = acc.fdSelect->get_fd (glyph);
+ if (unlikely (fd >= acc.fdCount))
+ return false;
+
+ // Note: const cast is safe here because the collect_subr_refs_in_str only performs a
+ // closure and does not modify any of the charstrings.
+ subr_subset_param_t param (const_cast<parsed_cs_str_t*> (&get_parsed_charstring (i)),
+ const_cast<parsed_cs_str_vec_t*> (&global_subrs),
+ const_cast<parsed_cs_str_vec_t*> (&local_subrs[fd]),
+ &closures.global_closure,
+ &closures.local_closures[fd],
+ plan->flags & HB_SUBSET_FLAGS_NO_HINTING);
+ collect_subr_refs_in_str (get_parsed_charstring (i), param);
+ }
+
+ return true;
+ }
+
+ void collect_subr_refs_in_subr (unsigned int subr_num, parsed_cs_str_vec_t &subrs,
hb_set_t *closure,
const subr_subset_param_t &param)
{
+ if (closure->has (subr_num))
+ return;
closure->add (subr_num);
collect_subr_refs_in_str (subrs[subr_num], param);
}
- void collect_subr_refs_in_str (parsed_cs_str_t &str, const subr_subset_param_t &param)
+ void collect_subr_refs_in_str (const parsed_cs_str_t &str,
+ const subr_subset_param_t &param)
{
- for (unsigned int pos = 0; pos < str.values.length; pos++)
+ if (!str.has_calls ())
+ return;
+
+ for (auto &opstr : str.values)
{
- if (!str.values[pos].for_drop ())
+ if (!param.drop_hints || !opstr.is_hinting ())
{
- switch (str.values[pos].op)
+ switch (opstr.op)
{
case OpCode_callsubr:
- collect_subr_refs_in_subr (str, pos,
- str.values[pos].subr_num, *param.parsed_local_subrs,
+ collect_subr_refs_in_subr (opstr.subr_num, *param.parsed_local_subrs,
param.local_closure, param);
break;
case OpCode_callgsubr:
- collect_subr_refs_in_subr (str, pos,
- str.values[pos].subr_num, *param.parsed_global_subrs,
+ collect_subr_refs_in_subr (opstr.subr_num, *param.parsed_global_subrs,
param.global_closure, param);
break;
@@ -853,42 +955,113 @@ struct subr_subsetter_t
bool encode_str (const parsed_cs_str_t &str, const unsigned int fd, str_buff_t &buff) const
{
- unsigned count = str.get_count ();
str_encoder_t encoder (buff);
encoder.reset ();
- buff.alloc (count * 3);
+ bool hinting = !(plan->flags & HB_SUBSET_FLAGS_NO_HINTING);
/* if a prefix (CFF1 width or CFF2 vsindex) has been removed along with hints,
* re-insert it at the beginning of charstreing */
- if (str.has_prefix () && str.is_hint_dropped ())
+ if (str.has_prefix () && !hinting && str.is_hint_dropped ())
{
encoder.encode_num (str.prefix_num ());
if (str.prefix_op () != OpCode_Invalid)
encoder.encode_op (str.prefix_op ());
}
- for (unsigned int i = 0; i < count; i++)
+
+ unsigned size = 0;
+ for (auto &opstr : str.values)
{
- const parsed_cs_op_t &opstr = str.values[i];
- if (!opstr.for_drop () && !opstr.for_skip ())
+ size += opstr.length;
+ if (opstr.op == OpCode_callsubr || opstr.op == OpCode_callgsubr)
+ size += 3;
+ }
+ if (!buff.alloc (buff.length + size))
+ return false;
+
+ for (auto &opstr : str.values)
+ {
+ if (hinting || !opstr.is_hinting ())
{
switch (opstr.op)
{
case OpCode_callsubr:
encoder.encode_int (remaps.local_remaps[fd].biased_num (opstr.subr_num));
- encoder.encode_op (OpCode_callsubr);
+ encoder.copy_str (opstr.ptr, opstr.length);
break;
case OpCode_callgsubr:
encoder.encode_int (remaps.global_remap.biased_num (opstr.subr_num));
- encoder.encode_op (OpCode_callgsubr);
+ encoder.copy_str (opstr.ptr, opstr.length);
break;
default:
- encoder.copy_str (opstr.str);
+ encoder.copy_str (opstr.ptr, opstr.length);
break;
}
}
}
- return !encoder.is_error ();
+ return !encoder.in_error ();
+ }
+
+ void compact_parsed_strings () const
+ {
+ for (auto &cs : parsed_charstrings)
+ compact_string (cs);
+ for (auto &cs : parsed_global_subrs_storage)
+ compact_string (cs);
+ for (auto &vec : parsed_local_subrs_storage)
+ for (auto &cs : vec)
+ compact_string (cs);
+ }
+
+ static void compact_string (parsed_cs_str_t &str)
+ {
+ unsigned count = str.values.length;
+ if (unlikely (!count)) return;
+ auto &opstr = str.values.arrayZ;
+ unsigned j = 0;
+ for (unsigned i = 1; i < count; i++)
+ {
+ /* See if we can combine op j and op i. */
+ bool combine =
+ (opstr[j].op != OpCode_callsubr && opstr[j].op != OpCode_callgsubr) &&
+ (opstr[i].op != OpCode_callsubr && opstr[i].op != OpCode_callgsubr) &&
+ (opstr[j].is_hinting () == opstr[i].is_hinting ()) &&
+ (opstr[j].ptr + opstr[j].length == opstr[i].ptr) &&
+ (opstr[j].length + opstr[i].length <= 255);
+
+ if (combine)
+ {
+ opstr[j].length += opstr[i].length;
+ opstr[j].op = OpCode_Invalid;
+ }
+ else
+ {
+ opstr[++j] = opstr[i];
+ }
+ }
+ str.values.shrink (j + 1);
+ }
+
+ void populate_subset_accelerator () const
+ {
+ if (!plan->inprogress_accelerator) return;
+
+ compact_parsed_strings ();
+
+ plan->inprogress_accelerator->cff_accelerator =
+ cff_subset_accelerator_t::create(acc.blob,
+ parsed_charstrings,
+ parsed_global_subrs_storage,
+ parsed_local_subrs_storage);
+ plan->inprogress_accelerator->destroy_cff_accelerator =
+ cff_subset_accelerator_t::destroy;
+
+ }
+
+ const parsed_cs_str_t& get_parsed_charstring (unsigned i) const
+ {
+ if (cached_charstrings) return *(cached_charstrings[i]);
+ return parsed_charstrings[i];
}
protected:
@@ -897,13 +1070,17 @@ struct subr_subsetter_t
subr_closures_t closures;
- parsed_cs_str_vec_t parsed_charstrings;
- parsed_cs_str_vec_t parsed_global_subrs;
- hb_vector_t<parsed_cs_str_vec_t> parsed_local_subrs;
+ hb_vector_t<const parsed_cs_str_t*> cached_charstrings;
+ const parsed_cs_str_vec_t* parsed_global_subrs;
+ const hb_vector_t<parsed_cs_str_vec_t>* parsed_local_subrs;
subr_remaps_t remaps;
private:
+
+ parsed_cs_str_vec_t parsed_charstrings;
+ parsed_cs_str_vec_t parsed_global_subrs_storage;
+ hb_vector_t<parsed_cs_str_vec_t> parsed_local_subrs_storage;
typedef typename SUBRS::count_type subr_count_type;
};
diff --git a/thirdparty/harfbuzz/src/hb-subset-cff1.cc b/thirdparty/harfbuzz/src/hb-subset-cff1.cc
index 52bb13d320..538f28f5aa 100644
--- a/thirdparty/harfbuzz/src/hb-subset-cff1.cc
+++ b/thirdparty/harfbuzz/src/hb-subset-cff1.cc
@@ -167,9 +167,10 @@ struct cff1_top_dict_op_serializer_t : cff_top_dict_op_serializer_t<cff1_top_dic
* for supplement, the original byte string is copied along with the op code */
op_str_t supp_op;
supp_op.op = op;
- if ( unlikely (!(opstr.str.length >= opstr.last_arg_offset + 3)))
+ if ( unlikely (!(opstr.length >= opstr.last_arg_offset + 3)))
return_trace (false);
- supp_op.str = hb_ubytes_t (&opstr.str + opstr.last_arg_offset, opstr.str.length - opstr.last_arg_offset);
+ supp_op.ptr = opstr.ptr + opstr.last_arg_offset;
+ supp_op.length = opstr.length - opstr.last_arg_offset;
return_trace (UnsizedByteStr::serialize_int2 (c, mod.nameSIDs[name_dict_values_t::registry]) &&
UnsizedByteStr::serialize_int2 (c, mod.nameSIDs[name_dict_values_t::ordering]) &&
copy_opstr (c, supp_op));
@@ -442,8 +443,17 @@ struct cff_subset_plan {
return;
}
- bool use_glyph_to_sid_map = plan->num_output_glyphs () > plan->source->get_num_glyphs () / 8.;
- hb_map_t *glyph_to_sid_map = use_glyph_to_sid_map ? acc.create_glyph_to_sid_map () : nullptr;
+ hb_map_t *glyph_to_sid_map = (plan->accelerator && plan->accelerator->cff_accelerator) ?
+ plan->accelerator->cff_accelerator->glyph_to_sid_map :
+ nullptr;
+ bool created_map = false;
+ if (!glyph_to_sid_map &&
+ ((plan->accelerator && plan->accelerator->cff_accelerator) ||
+ plan->num_output_glyphs () > plan->source->get_num_glyphs () / 8.))
+ {
+ created_map = true;
+ glyph_to_sid_map = acc.create_glyph_to_sid_map ();
+ }
unsigned int glyph;
for (glyph = 1; glyph < plan->num_output_glyphs (); glyph++)
@@ -467,8 +477,12 @@ struct cff_subset_plan {
last_sid = sid;
}
- if (glyph_to_sid_map)
- hb_map_destroy (glyph_to_sid_map);
+ if (created_map)
+ {
+ if (!(plan->accelerator && plan->accelerator->cff_accelerator) ||
+ !plan->accelerator->cff_accelerator->glyph_to_sid_map.cmpexch (nullptr, glyph_to_sid_map))
+ hb_map_destroy (glyph_to_sid_map);
+ }
bool two_byte = subset_charset_ranges.complete (glyph);
@@ -728,11 +742,17 @@ static bool _serialize_cff1 (hb_serialize_context_t *c,
/* CharStrings */
{
+ c->push<CFF1CharStrings> ();
+
+ unsigned total_size = CFF1CharStrings::total_size (plan.subset_charstrings);
+ if (unlikely (!c->start_zerocopy (total_size)))
+ return false;
+
CFF1CharStrings *cs = c->start_embed<CFF1CharStrings> ();
if (unlikely (!cs)) return false;
- c->push ();
+
if (likely (cs->serialize (c, plan.subset_charstrings)))
- plan.info.char_strings_link = c->pop_pack ();
+ plan.info.char_strings_link = c->pop_pack (false);
else
{
c->pop_discard ();
@@ -815,7 +835,7 @@ static bool _serialize_cff1 (hb_serialize_context_t *c,
CFF1Subrs *dest = c->start_embed <CFF1Subrs> ();
if (unlikely (!dest)) return false;
if (likely (dest->serialize (c, plan.subset_globalsubrs)))
- c->pop_pack ();
+ c->pop_pack (false);
else
{
c->pop_discard ();
diff --git a/thirdparty/harfbuzz/src/hb-subset-cff2.cc b/thirdparty/harfbuzz/src/hb-subset-cff2.cc
index 08e820efcf..60946b0281 100644
--- a/thirdparty/harfbuzz/src/hb-subset-cff2.cc
+++ b/thirdparty/harfbuzz/src/hb-subset-cff2.cc
@@ -334,7 +334,7 @@ static bool _serialize_cff2 (hb_serialize_context_t *c,
if (unlikely (!dest)) return false;
c->push ();
if (likely (dest->serialize (c, plan.subset_localsubrs[i])))
- subrs_link = c->pop_pack ();
+ subrs_link = c->pop_pack (false);
else
{
c->pop_discard ();
@@ -361,11 +361,17 @@ static bool _serialize_cff2 (hb_serialize_context_t *c,
/* CharStrings */
{
+ c->push ();
+
+ unsigned total_size = CFF2CharStrings::total_size (plan.subset_charstrings);
+ if (unlikely (!c->start_zerocopy (total_size)))
+ return false;
+
CFF2CharStrings *cs = c->start_embed<CFF2CharStrings> ();
if (unlikely (!cs)) return false;
- c->push ();
+
if (likely (cs->serialize (c, plan.subset_charstrings)))
- plan.info.char_strings_link = c->pop_pack ();
+ plan.info.char_strings_link = c->pop_pack (false);
else
{
c->pop_discard ();
@@ -377,9 +383,10 @@ static bool _serialize_cff2 (hb_serialize_context_t *c,
if (acc.fdSelect != &Null (CFF2FDSelect))
{
c->push ();
- if (likely (hb_serialize_cff_fdselect (c, num_glyphs, *(const FDSelect *)acc.fdSelect, plan.orig_fdcount,
- plan.subset_fdselect_format, plan.subset_fdselect_size,
- plan.subset_fdselect_ranges)))
+ if (likely (hb_serialize_cff_fdselect (c, num_glyphs, *(const FDSelect *)acc.fdSelect,
+ plan.orig_fdcount,
+ plan.subset_fdselect_format, plan.subset_fdselect_size,
+ plan.subset_fdselect_ranges)))
plan.info.fd_select.link = c->pop_pack ();
else
{
@@ -401,7 +408,7 @@ static bool _serialize_cff2 (hb_serialize_context_t *c,
hb_iter (private_dict_infos))
;
if (unlikely (!fda->serialize (c, it, fontSzr))) return false;
- plan.info.fd_array_link = c->pop_pack ();
+ plan.info.fd_array_link = c->pop_pack (false);
}
/* variation store */
@@ -410,7 +417,7 @@ static bool _serialize_cff2 (hb_serialize_context_t *c,
c->push ();
CFF2VariationStore *dest = c->start_embed<CFF2VariationStore> ();
if (unlikely (!dest || !dest->serialize (c, acc.varStore))) return false;
- plan.info.var_store_link = c->pop_pack ();
+ plan.info.var_store_link = c->pop_pack (false);
}
OT::cff2 *cff2 = c->allocate_min<OT::cff2> ();
diff --git a/thirdparty/harfbuzz/src/hb-subset-input.cc b/thirdparty/harfbuzz/src/hb-subset-input.cc
index fd250104bb..42434ae0ef 100644
--- a/thirdparty/harfbuzz/src/hb-subset-input.cc
+++ b/thirdparty/harfbuzz/src/hb-subset-input.cc
@@ -26,7 +26,7 @@
#include "hb-subset.hh"
#include "hb-set.hh"
-
+#include "hb-utf.hh"
/**
* hb_subset_input_create_or_fail:
*
@@ -49,8 +49,15 @@ hb_subset_input_create_or_fail (void)
set = hb_set_create ();
input->axes_location = hb_hashmap_create<hb_tag_t, float> ();
+#ifdef HB_EXPERIMENTAL_API
+ input->name_table_overrides = hb_hashmap_create<hb_ot_name_record_ids_t, hb_bytes_t> ();
+#endif
- if (!input->axes_location || input->in_error ())
+ if (!input->axes_location ||
+#ifdef HB_EXPERIMENTAL_API
+ !input->name_table_overrides ||
+#endif
+ input->in_error ())
{
hb_subset_input_destroy (input);
return nullptr;
@@ -248,6 +255,15 @@ hb_subset_input_destroy (hb_subset_input_t *input)
hb_hashmap_destroy (input->axes_location);
+#ifdef HB_EXPERIMENTAL_API
+ if (input->name_table_overrides)
+ {
+ for (auto _ : *input->name_table_overrides)
+ _.second.fini ();
+ }
+ hb_hashmap_destroy (input->name_table_overrides);
+#endif
+
hb_free (input);
}
@@ -379,7 +395,6 @@ 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)
@@ -388,9 +403,12 @@ hb_subset_input_get_user_data (const hb_subset_input_t *input,
*
* Pin an axis to its default location in the given subset input object.
*
+ * Currently only works for fonts with 'glyf' tables. CFF and CFF2 is not
+ * yet supported. Additionally all axes in a font must be pinned.
+ *
* Return value: `true` if success, `false` otherwise
*
- * Since: EXPERIMENTAL
+ * Since: 6.0.0
**/
HB_EXTERN hb_bool_t
hb_subset_input_pin_axis_to_default (hb_subset_input_t *input,
@@ -412,9 +430,12 @@ hb_subset_input_pin_axis_to_default (hb_subset_input_t *input,
*
* Pin an axis to a fixed location in the given subset input object.
*
+ * Currently only works for fonts with 'glyf' tables. CFF and CFF2 is not
+ * yet supported. Additionally all axes in a font must be pinned.
+ *
* Return value: `true` if success, `false` otherwise
*
- * Since: EXPERIMENTAL
+ * Since: 6.0.0
**/
HB_EXTERN hb_bool_t
hb_subset_input_pin_axis_location (hb_subset_input_t *input,
@@ -430,28 +451,41 @@ hb_subset_input_pin_axis_location (hb_subset_input_t *input,
return input->axes_location->set (axis_tag, val);
}
#endif
-#endif
-#ifdef HB_EXPERIMENTAL_API
/**
- * hb_subset_preprocess
- * @input: a #hb_face_t object.
+ * hb_subset_preprocess:
+ * @source: a #hb_face_t object.
*
* Preprocesses the face and attaches data that will be needed by the
* subsetter. Future subsetting operations can then use the precomputed data
* to speed up the subsetting operation.
*
- * Since: EXPERIMENTAL
+ * See [subset-preprocessing](https://github.com/harfbuzz/harfbuzz/blob/main/docs/subset-preprocessing.md)
+ * for more information.
+ *
+ * Note: the preprocessed face may contain sub-blobs that reference the memory
+ * backing the source #hb_face_t. Therefore in the case that this memory is not
+ * owned by the source face you will need to ensure that memory lives
+ * as long as the returned #hb_face_t.
+ *
+ * Returns: a new #hb_face_t.
+ *
+ * Since: 6.0.0
**/
HB_EXTERN hb_face_t *
hb_subset_preprocess (hb_face_t *source)
{
hb_subset_input_t* input = hb_subset_input_create_or_fail ();
+ if (!input)
+ return source;
hb_set_clear (hb_subset_input_set(input, HB_SUBSET_SETS_UNICODE));
hb_set_invert (hb_subset_input_set(input, HB_SUBSET_SETS_UNICODE));
+ hb_set_clear (hb_subset_input_set(input, HB_SUBSET_SETS_GLYPH_INDEX));
+ hb_set_invert (hb_subset_input_set(input, HB_SUBSET_SETS_GLYPH_INDEX));
+
hb_set_clear (hb_subset_input_set(input,
HB_SUBSET_SETS_LAYOUT_FEATURE_TAG));
hb_set_invert (hb_subset_input_set(input,
@@ -467,15 +501,100 @@ hb_subset_preprocess (hb_face_t *source)
hb_set_invert (hb_subset_input_set(input,
HB_SUBSET_SETS_NAME_ID));
+ hb_set_clear (hb_subset_input_set(input,
+ HB_SUBSET_SETS_NAME_LANG_ID));
+ hb_set_invert (hb_subset_input_set(input,
+ HB_SUBSET_SETS_NAME_LANG_ID));
+
hb_subset_input_set_flags(input,
HB_SUBSET_FLAGS_NOTDEF_OUTLINE |
HB_SUBSET_FLAGS_GLYPH_NAMES |
- HB_SUBSET_FLAGS_RETAIN_GIDS);
+ HB_SUBSET_FLAGS_RETAIN_GIDS |
+ HB_SUBSET_FLAGS_NO_PRUNE_UNICODE_RANGES);
input->attach_accelerator_data = true;
+ // Always use long loca in the preprocessed version. This allows
+ // us to store the glyph bytes unpadded which allows the future subset
+ // operation to run faster by skipping the trim padding step.
+ input->force_long_loca = true;
+
hb_face_t* new_source = hb_subset_or_fail (source, input);
hb_subset_input_destroy (input);
+ if (!new_source) {
+ DEBUG_MSG (SUBSET, nullptr, "Preprocessing failed due to subset failure.");
+ return source;
+ }
+
return new_source;
}
+
+#ifdef HB_EXPERIMENTAL_API
+/**
+ * hb_subset_input_override_name_table:
+ * @input: a #hb_subset_input_t object.
+ * @name_id: name_id of a nameRecord
+ * @platform_id: platform ID of a nameRecord
+ * @encoding_id: encoding ID of a nameRecord
+ * @language_id: language ID of a nameRecord
+ * @name_str: pointer to name string new value or null to indicate should remove
+ * @str_len: the size of @name_str, or -1 if it is `NULL`-terminated
+ *
+ * Override the name string of the NameRecord identified by name_id,
+ * platform_id, encoding_id and language_id. If a record with that name_id
+ * doesn't exist, create it and insert to the name table.
+ *
+ * Note: for mac platform, we only support name_str with all ascii characters,
+ * name_str with non-ascii characters will be ignored.
+ *
+ * Since: EXPERIMENTAL
+ **/
+HB_EXTERN hb_bool_t
+hb_subset_input_override_name_table (hb_subset_input_t *input,
+ hb_ot_name_id_t name_id,
+ unsigned platform_id,
+ unsigned encoding_id,
+ unsigned language_id,
+ const char *name_str,
+ int str_len /* -1 means nul-terminated */)
+{
+ if (!name_str)
+ {
+ str_len = 0;
+ }
+ else if (str_len == -1)
+ {
+ str_len = strlen (name_str);
+ }
+
+ hb_bytes_t name_bytes (nullptr, 0);
+ if (str_len)
+ {
+ if (platform_id == 1)
+ {
+ const uint8_t *src = reinterpret_cast<const uint8_t*> (name_str);
+ const uint8_t *src_end = src + str_len;
+
+ hb_codepoint_t unicode;
+ const hb_codepoint_t replacement = HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT;
+ while (src < src_end)
+ {
+ src = hb_utf8_t::next (src, src_end, &unicode, replacement);
+ if (unicode >= 0x0080u)
+ {
+ printf ("Non-ascii character detected, ignored...This API supports acsii characters only for mac platform\n");
+ return false;
+ }
+ }
+ }
+ char *override_name = (char *) hb_malloc (str_len);
+ if (unlikely (!override_name)) return false;
+
+ hb_memcpy (override_name, name_str, str_len);
+ name_bytes = hb_bytes_t (override_name, str_len);
+ }
+ input->name_table_overrides->set (hb_ot_name_record_ids_t (platform_id, encoding_id, language_id, name_id), name_bytes);
+ return true;
+}
+
#endif
diff --git a/thirdparty/harfbuzz/src/hb-subset-input.hh b/thirdparty/harfbuzz/src/hb-subset-input.hh
index dabb4918fe..ecd47b7abf 100644
--- a/thirdparty/harfbuzz/src/hb-subset-input.hh
+++ b/thirdparty/harfbuzz/src/hb-subset-input.hh
@@ -36,6 +36,48 @@
#include "hb-font.hh"
+struct hb_ot_name_record_ids_t
+{
+ hb_ot_name_record_ids_t () = default;
+ hb_ot_name_record_ids_t (unsigned platform_id_,
+ unsigned encoding_id_,
+ unsigned language_id_,
+ unsigned name_id_)
+ :platform_id (platform_id_),
+ encoding_id (encoding_id_),
+ language_id (language_id_),
+ name_id (name_id_) {}
+
+ bool operator != (const hb_ot_name_record_ids_t o) const
+ { return !(*this == o); }
+
+ inline bool operator == (const hb_ot_name_record_ids_t& o) const
+ {
+ return platform_id == o.platform_id &&
+ encoding_id == o.encoding_id &&
+ language_id == o.language_id &&
+ name_id == o.name_id;
+ }
+
+ inline uint32_t hash () const
+ {
+ uint32_t current = 0;
+ current = current * 31 + hb_hash (platform_id);
+ current = current * 31 + hb_hash (encoding_id);
+ current = current * 31 + hb_hash (language_id);
+ current = current * 31 + hb_hash (name_id);
+ return current;
+ }
+
+ unsigned platform_id;
+ unsigned encoding_id;
+ unsigned language_id;
+ unsigned name_id;
+};
+
+typedef struct hb_ot_name_record_ids_t hb_ot_name_record_ids_t;
+
+
HB_MARK_AS_FLAG_T (hb_subset_flags_t);
struct hb_subset_input_t
@@ -60,7 +102,14 @@ struct hb_subset_input_t
unsigned flags;
bool attach_accelerator_data = false;
+
+ // If set loca format will always be the long version.
+ bool force_long_loca = false;
+
hb_hashmap_t<hb_tag_t, float> *axes_location;
+#ifdef HB_EXPERIMENTAL_API
+ hb_hashmap_t<hb_ot_name_record_ids_t, hb_bytes_t> *name_table_overrides;
+#endif
inline unsigned num_sets () const
{
@@ -80,7 +129,11 @@ struct hb_subset_input_t
return true;
}
- return axes_location->in_error ();
+ return axes_location->in_error ()
+#ifdef HB_EXPERIMENTAL_API
+ || name_table_overrides->in_error ()
+#endif
+ ;
}
};
diff --git a/thirdparty/harfbuzz/src/hb-subset-plan.cc b/thirdparty/harfbuzz/src/hb-subset-plan.cc
index 9cf7c9e431..71bc908ffb 100644
--- a/thirdparty/harfbuzz/src/hb-subset-plan.cc
+++ b/thirdparty/harfbuzz/src/hb-subset-plan.cc
@@ -27,6 +27,7 @@
#include "hb-subset-plan.hh"
#include "hb-subset-accelerator.hh"
#include "hb-map.hh"
+#include "hb-multimap.hh"
#include "hb-set.hh"
#include "hb-ot-cmap-table.hh"
@@ -47,7 +48,7 @@ using OT::Layout::GPOS;
typedef hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> script_langsys_map;
#ifndef HB_NO_SUBSET_CFF
-static inline void
+static inline bool
_add_cff_seac_components (const OT::cff1::accelerator_t &cff,
hb_codepoint_t gid,
hb_set_t *gids_to_retain)
@@ -57,7 +58,9 @@ _add_cff_seac_components (const OT::cff1::accelerator_t &cff,
{
gids_to_retain->add (base_gid);
gids_to_retain->add (accent_gid);
+ return true;
}
+ return false;
}
#endif
@@ -82,10 +85,8 @@ static void
_remap_indexes (const hb_set_t *indexes,
hb_map_t *mapping /* OUT */)
{
- unsigned count = indexes->get_population ();
-
- for (auto _ : + hb_zip (indexes->iter (), hb_range (count)))
- mapping->set (_.first, _.second);
+ for (auto _ : + hb_enumerate (indexes->iter ()))
+ mapping->set (_.second, _.first);
}
@@ -344,7 +345,9 @@ _get_hb_font_with_variations (const hb_subset_plan_t *plan)
vars.push (var);
}
+#ifndef HB_NO_VAR
hb_font_set_variations (font, vars.arrayZ, plan->user_axes_location->get_population ());
+#endif
return font;
}
@@ -521,14 +524,44 @@ _populate_unicodes_to_retain (const hb_set_t *unicodes,
cmap_unicodes = &plan->accelerator->unicodes;
}
- for (hb_codepoint_t cp : *cmap_unicodes)
+ if (plan->accelerator &&
+ unicodes->get_population () < cmap_unicodes->get_population () &&
+ glyphs->get_population () < cmap_unicodes->get_population ())
+ {
+ auto &gid_to_unicodes = plan->accelerator->gid_to_unicodes;
+ for (hb_codepoint_t gid : *glyphs)
+ {
+ auto unicodes = gid_to_unicodes.get (gid);
+
+ for (hb_codepoint_t cp : unicodes)
+ {
+ plan->codepoint_to_glyph->set (cp, gid);
+ plan->unicode_to_new_gid_list.push (hb_pair (cp, gid));
+ }
+ }
+ for (hb_codepoint_t cp : *unicodes)
+ {
+ /* Don't double-add entry. */
+ if (plan->codepoint_to_glyph->has (cp))
+ continue;
+
+ hb_codepoint_t gid = (*unicode_glyphid_map)[cp];
+ plan->codepoint_to_glyph->set (cp, gid);
+ plan->unicode_to_new_gid_list.push (hb_pair (cp, gid));
+ }
+ plan->unicode_to_new_gid_list.qsort ();
+ }
+ else
{
- hb_codepoint_t gid = (*unicode_glyphid_map)[cp];
- if (!unicodes->has (cp) && !glyphs->has (gid))
- continue;
+ for (hb_codepoint_t cp : *cmap_unicodes)
+ {
+ hb_codepoint_t gid = (*unicode_glyphid_map)[cp];
+ if (!unicodes->has (cp) && !glyphs->has (gid))
+ continue;
- plan->codepoint_to_glyph->set (cp, gid);
- plan->unicode_to_new_gid_list.push (hb_pair (cp, gid));
+ plan->codepoint_to_glyph->set (cp, gid);
+ plan->unicode_to_new_gid_list.push (hb_pair (cp, gid));
+ }
}
/* Add gids which where requested, but not mapped in cmap */
@@ -639,9 +672,15 @@ _populate_gids_to_retain (hb_subset_plan_t* plan,
else
plan->_glyphset->union_ (cur_glyphset);
#ifndef HB_NO_SUBSET_CFF
- if (cff.is_valid ())
- for (hb_codepoint_t gid : cur_glyphset)
- _add_cff_seac_components (cff, gid, plan->_glyphset);
+ if (!plan->accelerator || plan->accelerator->has_seac)
+ {
+ bool has_seac = false;
+ if (cff.is_valid ())
+ for (hb_codepoint_t gid : cur_glyphset)
+ if (_add_cff_seac_components (cff, gid, plan->_glyphset))
+ has_seac = true;
+ plan->has_seac = has_seac;
+ }
#endif
_remove_invalid_gids (plan->_glyphset, plan->source->get_num_glyphs ());
@@ -848,9 +887,28 @@ hb_subset_plan_create_or_fail (hb_face_t *face,
plan->check_success (plan->vmtx_map = hb_hashmap_create<unsigned, hb_pair_t<unsigned, int>> ());
plan->check_success (plan->hmtx_map = hb_hashmap_create<unsigned, hb_pair_t<unsigned, int>> ());
+#ifdef HB_EXPERIMENTAL_API
+ plan->check_success (plan->name_table_overrides = hb_hashmap_create<hb_ot_name_record_ids_t, hb_bytes_t> ());
+ if (plan->name_table_overrides && input->name_table_overrides)
+ {
+ for (auto _ : *input->name_table_overrides)
+ {
+ hb_bytes_t name_bytes = _.second;
+ unsigned len = name_bytes.length;
+ char *name_str = (char *) hb_malloc (len);
+ if (unlikely (!plan->check_success (name_str)))
+ break;
+
+ hb_memcpy (name_str, name_bytes.arrayZ, len);
+ plan->name_table_overrides->set (_.first, hb_bytes_t (name_str, len));
+ }
+ }
+#endif
+
void* accel = hb_face_get_user_data(face, hb_subset_accelerator_t::user_data_key());
plan->attach_accelerator_data = input->attach_accelerator_data;
+ plan->force_long_loca = input->force_long_loca;
if (accel)
plan->accelerator = (hb_subset_accelerator_t*) accel;
@@ -893,6 +951,28 @@ hb_subset_plan_create_or_fail (hb_face_t *face,
hb_subset_plan_destroy (plan);
return nullptr;
}
+
+
+ if (plan->attach_accelerator_data)
+ {
+ hb_multimap_t gid_to_unicodes;
+
+ hb_map_t &unicode_to_gid = *plan->codepoint_to_glyph;
+
+ for (auto unicode : *plan->unicodes)
+ {
+ auto gid = unicode_to_gid[unicode];
+ gid_to_unicodes.add (gid, unicode);
+ }
+
+ plan->inprogress_accelerator =
+ hb_subset_accelerator_t::create (*plan->codepoint_to_glyph,
+ gid_to_unicodes,
+ *plan->unicodes,
+ plan->has_seac);
+ }
+
+
return plan;
}
diff --git a/thirdparty/harfbuzz/src/hb-subset-plan.hh b/thirdparty/harfbuzz/src/hb-subset-plan.hh
index 15fabba9c3..1b2aee7825 100644
--- a/thirdparty/harfbuzz/src/hb-subset-plan.hh
+++ b/thirdparty/harfbuzz/src/hb-subset-plan.hh
@@ -87,6 +87,18 @@ struct hb_subset_plan_t
hb_hashmap_destroy (vmtx_map);
hb_hashmap_destroy (layout_variation_idx_delta_map);
+#ifdef HB_EXPERIMENTAL_API
+ if (name_table_overrides)
+ {
+ for (auto _ : *name_table_overrides)
+ _.second.fini ();
+ }
+ hb_hashmap_destroy (name_table_overrides);
+#endif
+
+ if (inprogress_accelerator)
+ hb_subset_accelerator_t::destroy ((void*) inprogress_accelerator);
+
if (user_axes_location)
{
hb_object_destroy (user_axes_location);
@@ -99,10 +111,11 @@ struct hb_subset_plan_t
bool successful;
unsigned flags;
bool attach_accelerator_data = false;
+ bool force_long_loca = false;
// For each cp that we'd like to retain maps to the corresponding gid.
hb_set_t *unicodes;
- hb_vector_t<hb_pair_t<hb_codepoint_t, hb_codepoint_t>> unicode_to_new_gid_list;
+ hb_sorted_vector_t<hb_pair_t<hb_codepoint_t, hb_codepoint_t>> unicode_to_new_gid_list;
// name_ids we would like to retain
hb_set_t *name_ids;
@@ -185,31 +198,41 @@ struct hb_subset_plan_t
hb_map_t *axes_old_index_tag_map;
bool all_axes_pinned;
bool pinned_at_default;
+ bool has_seac;
//hmtx metrics map: new gid->(advance, lsb)
hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *hmtx_map;
//vmtx metrics map: new gid->(advance, lsb)
hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *vmtx_map;
+#ifdef HB_EXPERIMENTAL_API
+ // name table overrides map: hb_ot_name_record_ids_t-> name string new value or
+ // None to indicate should remove
+ hb_hashmap_t<hb_ot_name_record_ids_t, hb_bytes_t> *name_table_overrides;
+#endif
+
const hb_subset_accelerator_t* accelerator;
+ hb_subset_accelerator_t* inprogress_accelerator;
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_lock_t (accelerator ? &accelerator->sanitized_table_cache_lock : nullptr);
+
+ auto *cache = accelerator ? &accelerator->sanitized_table_cache : sanitized_table_cache;
+ if (cache
+ && !cache->in_error ()
+ && cache->has (+T::tableTag)) {
+ return hb_blob_reference (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));
+ if (likely (cache))
+ cache->set (+T::tableTag, std::move (table_blob));
return ret;
}
diff --git a/thirdparty/harfbuzz/src/hb-subset.cc b/thirdparty/harfbuzz/src/hb-subset.cc
index 6026aa6eff..186b12dbb8 100644
--- a/thirdparty/harfbuzz/src/hb-subset.cc
+++ b/thirdparty/harfbuzz/src/hb-subset.cc
@@ -82,6 +82,10 @@ using OT::Layout::GPOS;
* retain glyph ids option and configure the subset to pass through the layout tables untouched.
*/
+
+hb_user_data_key_t _hb_subset_accelerator_user_data_key = {};
+
+
/*
* 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.
@@ -409,20 +413,14 @@ _passthrough (hb_subset_plan_t *plan, hb_tag_t tag)
static bool
_dependencies_satisfied (hb_subset_plan_t *plan, hb_tag_t tag,
- hb_set_t &visited_set, hb_set_t &revisit_set)
+ const hb_set_t &subsetted_tags,
+ const hb_set_t &pending_subset_tags)
{
switch (tag)
{
case HB_OT_TAG_hmtx:
case HB_OT_TAG_vmtx:
- if (!plan->pinned_at_default &&
- !visited_set.has (HB_OT_TAG_glyf))
- {
- revisit_set.add (tag);
- return false;
- }
- return true;
-
+ return plan->pinned_at_default || !pending_subset_tags.has (HB_OT_TAG_glyf);
default:
return true;
}
@@ -495,12 +493,14 @@ _subset_table (hb_subset_plan_t *plan,
}
}
-static void _attach_accelerator_data (const hb_subset_plan_t* plan,
+static void _attach_accelerator_data (hb_subset_plan_t* plan,
hb_face_t* face /* IN/OUT */)
{
- hb_subset_accelerator_t* accel =
- hb_subset_accelerator_t::create (*plan->codepoint_to_glyph,
- *plan->unicodes);
+ if (!plan->inprogress_accelerator) return;
+
+ // Transfer the accelerator from the plan to us.
+ hb_subset_accelerator_t* accel = plan->inprogress_accelerator;
+ plan->inprogress_accelerator = nullptr;
if (accel->in_error ())
{
@@ -508,6 +508,11 @@ static void _attach_accelerator_data (const hb_subset_plan_t* plan,
return;
}
+ // Populate caches that need access to the final tables.
+ hb_blob_ptr_t<OT::cmap> cmap_ptr (hb_sanitize_context_t ().reference_table<OT::cmap> (face));
+ accel->cmap_cache = OT::cmap::create_filled_cache (cmap_ptr);
+ accel->destroy_cmap_cache = OT::SubtableUnicodesCache::destroy;
+
if (!hb_face_set_user_data(face,
hb_subset_accelerator_t::user_data_key(),
accel,
@@ -561,41 +566,63 @@ hb_subset_plan_execute_or_fail (hb_subset_plan_t *plan)
return nullptr;
}
- hb_set_t tags_set, revisit_set;
- bool success = true;
hb_tag_t table_tags[32];
unsigned offset = 0, num_tables = ARRAY_LENGTH (table_tags);
- hb_vector_t<char> buf;
- buf.alloc (4096 - 16);
+ hb_set_t subsetted_tags, pending_subset_tags;
while (((void) _get_table_tags (plan, offset, &num_tables, table_tags), num_tables))
{
for (unsigned i = 0; i < num_tables; ++i)
{
hb_tag_t tag = table_tags[i];
- if (_should_drop_table (plan, tag) && !tags_set.has (tag)) continue;
- if (!_dependencies_satisfied (plan, tag, tags_set, revisit_set)) continue;
- tags_set.add (tag);
- success = _subset_table (plan, buf, tag);
- if (unlikely (!success)) goto end;
+ if (_should_drop_table (plan, tag)) continue;
+ pending_subset_tags.add (tag);
+ }
+
+ offset += num_tables;
+ }
+
+ hb_vector_t<char> buf;
+ buf.alloc (4096 - 16);
+
+
+ bool success = true;
+
+ while (!pending_subset_tags.is_empty ())
+ {
+ if (subsetted_tags.in_error ()
+ || pending_subset_tags.in_error ()) {
+ success = false;
+ goto end;
}
- /*delayed subsetting for some tables since they might have dependency on other tables in some cases:
- e.g: during instantiating glyf tables, hmetrics/vmetrics are updated and saved in subset plan,
- hmtx/vmtx subsetting need to use these updated metrics values*/
- while (!revisit_set.is_empty ())
+ bool made_changes = false;
+ for (hb_tag_t tag : pending_subset_tags)
{
- hb_set_t revisit_temp;
- for (hb_tag_t tag : revisit_set)
+ if (!_dependencies_satisfied (plan, tag,
+ subsetted_tags,
+ pending_subset_tags))
{
- if (!_dependencies_satisfied (plan, tag, tags_set, revisit_temp)) continue;
- tags_set.add (tag);
- success = _subset_table (plan, buf, tag);
- if (unlikely (!success)) goto end;
+ // delayed subsetting for some tables since they might have dependency on other tables
+ // in some cases: e.g: during instantiating glyf tables, hmetrics/vmetrics are updated
+ // and saved in subset plan, hmtx/vmtx subsetting need to use these updated metrics values
+ continue;
}
- revisit_set = revisit_temp;
+
+ pending_subset_tags.del (tag);
+ subsetted_tags.add (tag);
+ made_changes = true;
+
+ success = _subset_table (plan, buf, tag);
+ if (unlikely (!success)) goto end;
+ }
+
+ if (!made_changes)
+ {
+ DEBUG_MSG (SUBSET, nullptr, "Table dependencies unable to be satisfied. Subset failed.");
+ success = false;
+ goto end;
}
- offset += num_tables;
}
if (success && plan->attach_accelerator_data) {
diff --git a/thirdparty/harfbuzz/src/hb-subset.h b/thirdparty/harfbuzz/src/hb-subset.h
index 6a2c5f6114..b83264ea5e 100644
--- a/thirdparty/harfbuzz/src/hb-subset.h
+++ b/thirdparty/harfbuzz/src/hb-subset.h
@@ -28,6 +28,7 @@
#define HB_SUBSET_H
#include "hb.h"
+#include "hb-ot.h"
HB_BEGIN_DECLS
@@ -164,8 +165,6 @@ 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,
@@ -176,16 +175,22 @@ 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
#ifdef HB_EXPERIMENTAL_API
+HB_EXTERN hb_bool_t
+hb_subset_input_override_name_table (hb_subset_input_t *input,
+ hb_ot_name_id_t name_id,
+ unsigned platform_id,
+ unsigned encoding_id,
+ unsigned language_id,
+ const char *name_str,
+ int str_len);
+
+#endif
HB_EXTERN hb_face_t *
hb_subset_preprocess (hb_face_t *source);
-#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 a372a4afce..f7d76eee18 100644
--- a/thirdparty/harfbuzz/src/hb-ucd-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ucd-table.hh
@@ -1069,7 +1069,7 @@ _hb_ucd_dm2_u64_map[388] =
#ifndef HB_OPTIMIZE_SIZE
static const uint8_t
-_hb_ucd_u8[18260] =
+_hb_ucd_u8[17868] =
{
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,
@@ -1535,191 +1535,166 @@ _hb_ucd_u8[18260] =
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 37, 0, 0, 0, 0, 0, 0, 0,
0, 0, 38, 39, 0, 0, 0, 0, 0, 0, 40, 41, 42, 0, 43, 0,
- 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, 5, 0, 0, 0, 0, 0, 0, 0, 6, 7, 8, 0,
- 9, 0, 10, 11, 0, 0, 12, 13, 14, 15, 16, 0, 0, 0, 0, 17,
- 18, 19, 20, 0, 21, 0, 22, 23, 0, 24, 25, 0, 0, 24, 26, 27,
- 0, 24, 26, 0, 0, 24, 26, 0, 0, 24, 26, 0, 0, 0, 26, 0,
- 0, 24, 28, 0, 0, 24, 26, 0, 0, 29, 26, 0, 0, 0, 30, 0,
- 0, 31, 32, 0, 0, 33, 34, 0, 35, 36, 0, 37, 38, 0, 39, 0,
- 0, 40, 0, 0, 41, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 43, 44, 0, 0, 0, 0, 45, 0,
- 0, 0, 0, 0, 0, 46, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0,
- 48, 0, 0, 49, 0, 50, 51, 0, 0, 52, 53, 54, 0, 55, 0, 56,
- 0, 57, 0, 0, 0, 0, 58, 59, 0, 0, 0, 0, 0, 0, 60, 61,
- 0, 0, 0, 0, 0, 0, 62, 63, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 65, 0, 0, 0, 66,
- 0, 67, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 69, 70, 0, 0, 71, 0, 0, 0, 0, 0, 0, 0, 0,
- 72, 73, 0, 0, 0, 0, 53, 74, 0, 75, 76, 0, 0, 77, 78, 0,
- 0, 0, 0, 0, 0, 79, 80, 81, 0, 0, 0, 0, 0, 0, 0, 26,
- 0, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0,
- 0, 83, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84,
- 0, 0, 0, 0, 0, 0, 0, 85, 0, 0, 0, 86, 0, 0, 0, 0,
- 87, 88, 0, 0, 0, 0, 0, 89, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 91, 0, 92, 0, 0, 93, 0, 94, 0, 0, 0,
- 0, 0, 72, 95, 0, 96, 0, 0, 97, 98, 0, 77, 0, 0, 99, 0,
- 0,100, 0, 0, 0, 0, 0,101, 0,102, 26,103, 0, 0, 0, 0,
- 0, 0,104, 0, 0, 0,105, 0, 0, 0, 0, 0, 0, 65,106, 0,
- 0, 65, 0, 0, 0,107, 0, 0, 0,108, 0, 0, 0, 0, 0, 0,
- 0, 96, 0, 0, 0, 0, 0, 0, 0,109,110, 0, 0, 0, 0, 78,
- 0, 44,111, 0,112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 65, 0, 0, 0, 0, 0, 0, 0, 0,113, 0,114, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,115, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,116, 0,117, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,118,
- 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, 0, 0,120,121,122, 0, 0,
- 0, 0,123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 124,125, 0, 0,126, 0, 0, 0, 0,117, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0,127, 0,128, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,129, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0,130, 0, 0, 0,131, 0, 0, 0, 0, 0,
- 0, 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, 0, 0, 0, 0, 19, 1, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 20, 21, 22, 1, 23, 4, 21, 24, 25, 26, 27, 28,
- 29, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 31, 0,
- 0, 0, 32, 33, 34, 35, 1, 36, 0, 0, 0, 0, 37, 0, 0, 0,
- 0, 0, 0, 0, 0, 38, 1, 39, 14, 39, 40, 41, 0, 0, 0, 0,
- 0, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 43, 36, 44, 45,
- 21, 45, 46, 0, 0, 0, 0, 0, 0, 0, 19, 1, 21, 0, 0, 47,
- 0, 0, 0, 0, 0, 38, 48, 1, 1, 49, 49, 50, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 51, 0, 0, 0, 0, 0, 0, 0, 52, 1,
- 0, 0, 38, 14, 4, 1, 1, 1, 53, 21, 43, 52, 54, 21, 35, 1,
- 0, 0, 0, 0, 0, 0, 0, 55, 0, 0, 0, 56, 57, 58, 0, 0,
- 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59,
- 0, 0, 0, 56, 0, 60, 0, 0, 0, 0, 0, 0, 0, 0, 61, 62,
- 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0,
- 0, 0, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 0,
- 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 0,
- 0, 0, 0, 0, 0, 69, 70, 0, 0, 0, 0, 0, 71, 72, 73, 74,
- 75, 76, 0, 0, 0, 0, 0, 0, 0, 77, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 78, 79, 0, 0, 0, 0, 47, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 49, 0, 0, 0, 0, 0, 80, 0, 0,
- 0, 0, 0, 0, 0, 62, 0, 0, 0, 0, 0, 0, 63, 0, 0, 81,
- 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 0,
- 0, 0, 0, 0, 0, 19, 84, 0, 62, 0, 0, 0, 0, 49, 1, 85,
- 0, 0, 0, 0, 1, 52, 15, 86, 36, 10, 21, 87, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 55, 0, 0, 0, 62, 0, 0, 0, 0, 0, 0,
- 0, 0, 19, 10, 1, 0, 0, 0, 0, 0, 88, 0, 0, 0, 0, 0,
- 0, 89, 0, 0, 88, 0, 0, 0, 0, 0, 0, 0, 0, 78, 0, 0,
- 0, 0, 0, 0, 87, 9, 12, 4, 90, 8, 91, 47, 0, 58, 50, 0,
- 21, 1, 21, 92, 93, 1, 1, 1, 1, 1, 1, 1, 1, 94, 95, 96,
- 0, 0, 0, 0, 97, 1, 98, 58, 81, 99,100, 4, 58, 0, 0, 0,
- 0, 0, 0, 19, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 61,
- 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,101,102, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0,103, 0, 0, 0, 0, 19, 0, 1, 1, 50,
- 0, 0, 0, 0, 0, 0, 0, 38, 0, 0, 0, 0, 50, 0, 0, 0,
- 0, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 0, 0,
- 1, 1, 1, 1, 50, 0, 0, 0, 0, 0,104, 68, 0, 0, 0, 0,
- 0, 0, 0, 0, 61, 0, 0, 0, 0, 0, 0, 0, 78, 0, 0, 0,
- 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,105,106, 58, 38,
- 81, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,107, 1, 14, 4, 12, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 47, 84, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 38, 87, 0, 0, 0, 0,108, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0,109, 61, 0,110, 0, 0, 0, 0, 0, 0,
- 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 19, 58, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 51, 0,111, 14, 52, 84, 0, 0, 0,
- 112, 41, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 61,
- 0, 0, 0, 0, 0, 0,113, 0, 87, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 61, 62, 0, 0, 62, 0, 89, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0,113, 0, 0, 0, 0,114, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 78, 55, 0, 38, 1, 58, 1, 58, 0, 0,
- 63, 89, 0, 0, 0, 0, 0, 59,115, 0, 0, 0, 0, 0, 0, 0,
- 55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,115, 0, 0,
- 0, 0, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79,
- 78, 0, 0, 0, 0, 0, 0, 0, 0, 61, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 56, 0, 89, 80, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 61, 0, 0, 79, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 8, 91, 0, 0, 0, 0, 0, 0, 1, 87, 0, 0,
- 0, 0, 0, 0,116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,117,
- 0,118,119,120,121, 0,104, 4,122, 49, 23, 0, 0, 0, 0, 0,
- 0, 0, 38, 50, 0, 0, 0, 0, 38, 58, 0, 0, 0, 0, 0, 0,
- 1, 87, 1, 1, 1, 1, 39, 1, 48,105, 87, 0, 0, 0, 0, 0,
- 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 59, 0, 0, 0, 0,
- 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,123, 0, 0, 0, 0,
- 0, 0, 0, 0, 4,122, 0, 0, 0, 1,124, 0, 0, 0, 0, 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,232,232,220,230,
- 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,
+ 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, 76, 0, 77, 78, 0, 0, 79, 80, 0, 81, 62, 0, 82,
+ 83, 0, 0, 84, 85, 86, 0, 0, 0, 87, 0, 88, 0, 0, 51, 89,
+ 51, 0, 90, 0, 91, 0, 0, 0, 80, 0, 0, 0, 92, 93, 0, 94,
+ 95, 96, 97, 0, 0, 0, 0, 0, 51, 0, 0, 0, 0, 98, 99, 0,
+ 0, 0, 0, 0, 0,100, 0, 0, 0, 0, 0,101,102, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,103, 0, 0,104, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,105,106, 0, 0,107, 0, 0, 0, 0, 0, 0,
+ 108, 0,109, 0,102, 0, 0, 0, 0, 0,110,111, 0, 0, 0, 0,
+ 0, 0, 0,112, 0, 0, 0, 0, 0, 0, 0,113, 0,114, 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,
+ 0, 0, 0,100,101, 93, 0, 0,102, 0, 0, 0, 84, 0, 0,103,
+ 0, 0, 0,104,105, 0, 0,106,107, 0, 0, 0, 0, 0, 0,108,
+ 0, 0,109, 0, 0, 0, 0,110, 33, 0,111,112,113, 35, 0, 0,
+ 114, 0, 0, 0,115, 0, 0, 0, 0, 0, 0,116, 0, 0,117, 0,
+ 0, 0, 0,118, 88, 0, 0, 0, 0, 0, 57, 0, 0, 0, 0, 52,
+ 119, 0, 0, 0, 0,120, 0, 0,121, 0, 0, 0, 0,119, 0, 0,
+ 122, 0, 0, 0, 0, 0, 0,123, 0, 0, 0,124, 0, 0, 0,125,
+ 0,126, 0, 0, 0, 0,127,128,129, 0,130, 0,131, 0, 0, 0,
+ 132,133,134, 0, 77, 0, 0, 0, 0, 0, 35, 0, 0, 0,135, 0,
+ 0, 0,136, 0, 0,137, 0, 0,138, 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, 0, 0, 51,
+ 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, 79, 0, 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, 0, 0, 0,123,
+ 4,122, 0, 0, 0, 1,124, 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,232,232,220,230,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,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, 7,
- 44, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 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, 7, 44, 13, 13, 13, 13, 13, 13, 13,
13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
@@ -1740,420 +1715,420 @@ _hb_ucd_u8[18260] =
13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
13, 13, 13, 13, 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, 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,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 45, 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, 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,
+ 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, 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,156, 96,157,158,159,160, 96,161,162,163,164,164,
- 164,164,164,164,164,165,166,164,167, 96, 96, 96, 96, 96, 96, 96,
- 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,168,169,169,
- 169,169,169,169,169,169,170, 96, 96, 96, 96, 96, 96, 96, 96, 96,
- 96, 96, 96, 96, 96, 96,171,171,171,171,172, 96, 96, 96,173,173,
- 173,173,174,175,176,177, 96, 96, 96, 96,178,179,180,181,182,182,
+ 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,156, 96,157,158,
+ 159,160, 96,161,162,163,164,164,164,164,164,164,164,165,166,164,
+ 167, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
+ 96, 96, 96, 96, 96,168,169,169,169,169,169,169,169,169,170, 96,
+ 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,171,171,
+ 171,171,172, 96, 96, 96,173,173,173,173,174,175,176,177, 96, 96,
+ 96, 96,178,179,180,181,182,182,182,182,182,182,182,182,182,182,
182,182,182,182,182,182,182,182,182,182,182,182,182,182,182,182,
- 182,182,182,182,182,182,182,182,182,182,182,182,182,183,182,182,
- 182,182,182,182,184,184,184,185,186, 96, 96, 96, 96, 96, 96, 96,
- 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,187,188,189,
- 190,191,191,192, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
- 96, 96, 96, 96, 96, 96,193,194, 96, 96, 96, 96, 96, 96, 96, 96,
- 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,195,196, 59,197,
- 198,199,200,201,202, 96,203,204,205, 59, 59,206, 59,207,208,208,
- 208,208,208,209, 96, 96, 96, 96, 96, 96, 96, 96,210, 96,211,212,
- 213, 96, 96,214, 96, 96, 96,215, 96, 96, 96, 96, 96,216,217,218,
- 219, 96, 96, 96, 96, 96,220,221,222, 96,223,224, 96, 96,225,226,
- 59,227,228, 96, 59, 59, 59, 59, 59, 59, 59,229,230,231,232,233,
- 59, 59,234,235, 59,236, 96, 96, 96, 96, 96, 96, 96, 96, 70, 70,
- 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,237, 70, 70, 70, 70,
- 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,238, 70,239, 70,
+ 182,182,182,182,182,183,182,182,182,182,182,182,184,184,184,185,
+ 186, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
+ 96, 96, 96, 96, 96,187,188,189,190,191,191,192, 96, 96, 96, 96,
+ 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,193,194,
+ 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
+ 96, 96, 96, 96,195,196, 59,197,198,199,200,201,202, 96,203,204,
+ 205, 59, 59,206, 59,207,208,208,208,208,208,209, 96, 96, 96, 96,
+ 96, 96, 96, 96,210, 96,211,212,213, 96, 96,214, 96, 96, 96,215,
+ 96, 96, 96, 96, 96,216,217,218,219, 96, 96, 96, 96, 96,220,221,
+ 222, 96,223,224, 96, 96,225,226, 59,227,228, 96, 59, 59, 59, 59,
+ 59, 59, 59,229,230,231,232,233, 59, 59,234,235, 59,236, 96, 96,
+ 96, 96, 96, 96, 96, 96, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
+ 70, 70, 70,237, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
+ 70, 70, 70, 70,238, 70,239, 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,240, 70, 70, 70, 70,
- 70, 70, 70, 70, 70,241, 96, 96, 96, 96, 96, 96, 96, 96, 70, 70,
- 70, 70,242, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 70, 70,
- 70, 70, 70, 70,243, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
- 70, 70, 70, 70, 70,244, 96, 96, 96, 96, 96, 96, 96, 96,245, 96,
- 246,247, 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, 16, 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,
- 18, 18, 18, 18, 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, 2, 2,
- 2, 2, 2, 3, 3, 3,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, 2, 2, 2, 2, 2, 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, 7, 7, 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,163,163,163,163,163,163,163,163,163, 2,
- 163,163,163,163,163,163,163,163,163, 2, 2, 2,163,163,163,163,
- 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, 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, 2, 2,
- 15, 2, 2, 2, 2, 2, 15, 15, 15, 2, 2, 17, 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, 2, 2,
- 2, 2, 2, 19, 19, 19, 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, 6, 6, 6, 6, 6, 6, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 6,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,164,164,164,164,164,164,164,164,164,164,
- 2, 2, 2, 2, 2, 2, 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, 0, 0, 0, 0, 2, 2, 2, 0, 0, 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,
+ 70, 70, 70,240, 70, 70, 70, 70, 70, 70, 70, 70, 70,241, 96, 96,
+ 96, 96, 96, 96, 96, 96, 70, 70, 70, 70,242, 96, 96, 96, 96, 96,
+ 96, 96, 96, 96, 96, 96, 70, 70, 70, 70, 70, 70,243, 70, 70, 70,
+ 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,244, 96, 96,
+ 96, 96, 96, 96, 96, 96,245, 96,246,247, 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, 16, 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, 18, 18, 18, 18, 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, 2, 2, 2, 2, 2, 3, 3, 3,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,
+ 2, 2, 2, 2, 2, 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, 7, 7,
+ 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,163,163,
+ 163,163,163,163,163,163,163, 2,163,163,163,163,163,163,163,163,
+ 163, 2, 2, 2,163,163,163,163, 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, 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, 2, 2, 15, 2, 2, 2, 2, 2, 15, 15,
+ 15, 2, 2, 17, 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, 2, 2, 2, 2, 2, 19, 19, 19, 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, 6, 6,
+ 6, 6, 6, 6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6,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,164,164,
+ 164,164,164,164,164,164,164,164, 2, 2, 2, 2, 2, 2, 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, 0, 0, 0, 0, 2, 2,
+ 2, 0, 0, 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, 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, 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, 22, 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,
@@ -2162,57 +2137,57 @@ _hb_ucd_u8[18260] =
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 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,
+ 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, 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, 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, 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, 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,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,117, 0, 0, 0, 0, 0, 0,
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,
+ 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,168, 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,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,
+ 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[9320] =
@@ -2827,7 +2802,7 @@ _hb_ucd_gc (unsigned u)
static inline uint_fast8_t
_hb_ucd_ccc (unsigned u)
{
- return u<125259u?_hb_ucd_u8[9184+(((_hb_ucd_u8[8128+(((_hb_ucd_u8[7424+(((_hb_ucd_u8[7178+(u>>2>>3>>4)])<<4)+((u>>2>>3)&15u))])<<3)+((u>>2)&7u))])<<2)+((u)&3u))]:0;
+ return u<125259u?_hb_ucd_u8[8792+(((_hb_ucd_u8[8236+(((_hb_ucd_u8[7776+(((_hb_ucd_u8[7424+(((_hb_ucd_u8[7178+(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)
@@ -2837,24 +2812,24 @@ _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[9932+(((_hb_ucd_u8[9812+(((_hb_ucd_b4(9684+_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[9540+(((_hb_ucd_u8[9420+(((_hb_ucd_b4(9292+_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[11454+(((_hb_ucd_u16[2040+(((_hb_ucd_u8[10718+(((_hb_ucd_u8[10268+(u>>3>>4>>4)])<<4)+((u>>3>>4)&15u))])<<4)+((u>>3)&15u))])<<3)+((u)&7u))]:2;
+ return u<918000u?_hb_ucd_u8[11062+(((_hb_ucd_u16[2040+(((_hb_ucd_u8[10326+(((_hb_ucd_u8[9876+(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[6008+(((_hb_ucd_u8[17460+(((_hb_ucd_u8[17078+(u>>4>>5)])<<5)+((u>>4)&31u))])<<4)+((u)&15u))]:0;
+ return u<195102u?_hb_ucd_u16[6008+(((_hb_ucd_u8[17068+(((_hb_ucd_u8[16686+(u>>4>>5)])<<5)+((u>>4)&31u))])<<4)+((u)&15u))]:0;
}
#elif !defined(HB_NO_UCD_UNASSIGNED)
static const uint8_t
-_hb_ucd_u8[17868] =
+_hb_ucd_u8[14744] =
{
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,
@@ -3436,51 +3411,54 @@ _hb_ucd_u8[17868] =
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,232,232,220,230,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,
+ 220,220,220, 0,232,232,220,230,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, 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, 7, 44, 13, 13, 13, 13, 13, 13, 13,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 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,
+ 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, 7,
+ 44, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
@@ -3501,419 +3479,221 @@ _hb_ucd_u8[17868] =
13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 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, 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,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 45, 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, 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,
+ 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, 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,156, 96,157,158,
- 159,160, 96,161,162,163,164,164,164,164,164,164,164,165,166,164,
- 167, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
- 96, 96, 96, 96, 96,168,169,169,169,169,169,169,169,169,170, 96,
- 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,171,171,
- 171,171,172, 96, 96, 96,173,173,173,173,174,175,176,177, 96, 96,
- 96, 96,178,179,180,181,182,182,182,182,182,182,182,182,182,182,
- 182,182,182,182,182,182,182,182,182,182,182,182,182,182,182,182,
- 182,182,182,182,182,183,182,182,182,182,182,182,184,184,184,185,
- 186, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
- 96, 96, 96, 96, 96,187,188,189,190,191,191,192, 96, 96, 96, 96,
- 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,193,194,
+ 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,
- 96, 96, 96, 96,195,196, 59,197,198,199,200,201,202, 96,203,204,
- 205, 59, 59,206, 59,207,208,208,208,208,208,209, 96, 96, 96, 96,
- 96, 96, 96, 96,210, 96,211,212,213, 96, 96,214, 96, 96, 96,215,
- 96, 96, 96, 96, 96,216,217,218,219, 96, 96, 96, 96, 96,220,221,
- 222, 96,223,224, 96, 96,225,226, 59,227,228, 96, 59, 59, 59, 59,
- 59, 59, 59,229,230,231,232,233, 59, 59,234,235, 59,236, 96, 96,
- 96, 96, 96, 96, 96, 96, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
- 70, 70, 70,237, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
- 70, 70, 70, 70,238, 70,239, 70, 70, 70, 70, 70, 70, 70, 70, 70,
+ 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,156, 96,157,158,159,160, 96,161,162,163,164,164,
+ 164,164,164,164,164,165,166,164,167, 96, 96, 96, 96, 96, 96, 96,
+ 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,168,169,169,
+ 169,169,169,169,169,169,170, 96, 96, 96, 96, 96, 96, 96, 96, 96,
+ 96, 96, 96, 96, 96, 96,171,171,171,171,172, 96, 96, 96,173,173,
+ 173,173,174,175,176,177, 96, 96, 96, 96,178,179,180,181,182,182,
+ 182,182,182,182,182,182,182,182,182,182,182,182,182,182,182,182,
+ 182,182,182,182,182,182,182,182,182,182,182,182,182,183,182,182,
+ 182,182,182,182,184,184,184,185,186, 96, 96, 96, 96, 96, 96, 96,
+ 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,187,188,189,
+ 190,191,191,192, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
+ 96, 96, 96, 96, 96, 96,193,194, 96, 96, 96, 96, 96, 96, 96, 96,
+ 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,195,196, 59,197,
+ 198,199,200,201,202, 96,203,204,205, 59, 59,206, 59,207,208,208,
+ 208,208,208,209, 96, 96, 96, 96, 96, 96, 96, 96,210, 96,211,212,
+ 213, 96, 96,214, 96, 96, 96,215, 96, 96, 96, 96, 96,216,217,218,
+ 219, 96, 96, 96, 96, 96,220,221,222, 96,223,224, 96, 96,225,226,
+ 59,227,228, 96, 59, 59, 59, 59, 59, 59, 59,229,230,231,232,233,
+ 59, 59,234,235, 59,236, 96, 96, 96, 96, 96, 96, 96, 96, 70, 70,
+ 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,237, 70, 70, 70, 70,
+ 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,238, 70,239, 70,
70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
- 70, 70, 70,240, 70, 70, 70, 70, 70, 70, 70, 70, 70,241, 96, 96,
- 96, 96, 96, 96, 96, 96, 70, 70, 70, 70,242, 96, 96, 96, 96, 96,
- 96, 96, 96, 96, 96, 96, 70, 70, 70, 70, 70, 70,243, 70, 70, 70,
- 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,244, 96, 96,
- 96, 96, 96, 96, 96, 96,245, 96,246,247, 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, 16, 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, 18, 18, 18, 18, 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, 2, 2, 2, 2, 2, 3, 3, 3,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,
- 2, 2, 2, 2, 2, 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, 7, 7,
- 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,163,163,
- 163,163,163,163,163,163,163, 2,163,163,163,163,163,163,163,163,
- 163, 2, 2, 2,163,163,163,163, 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, 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,
+ 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,240, 70, 70, 70, 70,
+ 70, 70, 70, 70, 70,241, 96, 96, 96, 96, 96, 96, 96, 96, 70, 70,
+ 70, 70,242, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 70, 70,
+ 70, 70, 70, 70,243, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
+ 70, 70, 70, 70, 70,244, 96, 96, 96, 96, 96, 96, 96, 96,245, 96,
+ 246,247, 0, 1, 2, 2, 0, 1, 2, 2, 2, 3, 4, 5, 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, 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,
+ 2, 9, 9, 9, 55, 55, 55, 55, 55, 55, 6, 6, 6, 6, 6, 1,
+ 1, 6, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 2, 2, 2, 2, 14, 14, 2,
+ 2, 2, 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, 37, 37, 2, 37, 37, 37, 37, 2, 2, 37, 37, 37, 38, 38,
+ 38, 38, 38, 38, 2, 2, 64, 64, 64, 64, 64, 64, 64, 2, 2, 64,
+ 64, 64, 90, 90, 90, 90, 90, 90, 2, 2, 90, 90, 90, 2, 95, 95,
+ 95, 95, 2, 2, 95, 2, 3, 3, 3, 2, 3, 3, 2, 2, 3, 3,
+ 0, 3, 7, 7, 7, 7, 7, 1, 1, 1, 1, 7, 7, 7, 0, 0,
+ 7, 7, 5, 5, 5, 5, 2, 5, 5, 5, 5, 2, 2, 5, 5, 2,
+ 5, 5, 5, 2, 5, 2, 2, 2, 5, 5, 5, 5, 2, 2, 5, 5,
+ 5, 2, 2, 2, 2, 5, 5, 5, 2, 5, 2, 11, 11, 11, 11, 11,
+ 11, 2, 2, 2, 2, 11, 11, 2, 2, 11, 11, 11, 11, 11, 11, 2,
+ 11, 11, 2, 11, 11, 2, 11, 11, 2, 2, 2, 11, 2, 2, 11, 2,
+ 11, 2, 2, 2, 11, 11, 2, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+ 2, 10, 10, 2, 10, 10, 10, 10, 2, 2, 10, 2, 2, 2, 2, 2,
+ 10, 10, 2, 21, 21, 21, 21, 21, 21, 21, 21, 2, 2, 21, 21, 2,
+ 21, 21, 21, 21, 2, 2, 21, 21, 2, 21, 2, 2, 21, 21, 2, 2,
+ 22, 22, 2, 22, 22, 22, 22, 22, 22, 2, 22, 2, 22, 22, 22, 22,
+ 2, 2, 2, 22, 22, 2, 2, 2, 2, 22, 22, 2, 2, 2, 22, 22,
+ 22, 22, 23, 23, 23, 23, 23, 2, 23, 23, 23, 23, 2, 2, 2, 23,
+ 23, 2, 23, 23, 23, 2, 2, 23, 2, 2, 2, 2, 23, 23, 2, 2,
+ 2, 23, 16, 16, 16, 16, 16, 2, 16, 16, 2, 16, 16, 16, 16, 16,
+ 2, 2, 2, 16, 16, 2, 2, 2, 16, 16, 20, 20, 20, 20, 20, 2,
+ 20, 20, 2, 2, 20, 20, 2, 36, 36, 36, 36, 36, 36, 36, 36, 36,
+ 36, 2, 2, 2, 36, 36, 36, 36, 2, 36, 2, 36, 2, 2, 2, 2,
+ 36, 2, 2, 2, 2, 36, 36, 2, 36, 2, 36, 2, 2, 2, 2, 24,
+ 24, 24, 24, 24, 24, 24, 24, 24, 24, 2, 2, 2, 2, 0, 2, 18,
+ 18, 2, 18, 2, 18, 18, 18, 18, 18, 2, 18, 18, 18, 18, 2, 18,
+ 2, 18, 18, 18, 2, 2, 18, 2, 18, 2, 25, 25, 25, 25, 2, 25,
+ 25, 25, 25, 2, 2, 2, 25, 2, 25, 25, 25, 0, 0, 0, 0, 25,
+ 25, 2, 33, 33, 33, 33, 8, 8, 8, 8, 8, 8, 2, 8, 2, 8,
+ 2, 2, 8, 8, 8, 0, 12, 12, 12, 12, 30, 30, 30, 30, 30, 2,
+ 30, 30, 30, 30, 2, 2, 30, 30, 30, 2, 2, 30, 30, 30, 30, 2,
+ 2, 2, 29, 29, 29, 29, 29, 29, 2, 2, 28, 28, 28, 28, 34, 34,
+ 34, 34, 34, 2, 2, 2, 35, 35, 35, 35, 35, 35, 35, 0, 0, 0,
+ 35, 35, 35, 2, 2, 2, 45, 45, 45, 45, 45, 45, 2, 2, 2, 2,
+ 2, 45, 44, 44, 44, 44, 44, 0, 0, 2, 43, 43, 43, 43, 46, 46,
+ 46, 46, 46, 2, 46, 46, 31, 31, 31, 31, 31, 31, 2, 2, 32, 32,
+ 0, 0, 32, 0, 32, 32, 32, 32, 32, 32, 32, 32, 2, 2, 32, 2,
+ 2, 2, 32, 32, 32, 2, 28, 28, 2, 2, 48, 48, 48, 48, 48, 48,
+ 48, 2, 48, 2, 2, 2, 52, 52, 52, 52, 52, 52, 2, 2, 52, 2,
+ 2, 2, 58, 58, 58, 58, 58, 58, 2, 2, 58, 58, 58, 2, 2, 2,
+ 58, 58, 54, 54, 54, 54, 2, 2, 54, 54, 91, 91, 91, 91, 91, 91,
+ 91, 2, 91, 2, 2, 91, 91, 91, 2, 2, 1, 1, 1, 2, 62, 62,
+ 62, 62, 62, 2, 2, 2, 62, 62, 62, 2, 76, 76, 76, 76, 93, 93,
+ 93, 93, 70, 70, 70, 70, 2, 2, 2, 70, 70, 70, 2, 2, 2, 70,
+ 70, 70, 73, 73, 73, 73, 6, 2, 2, 2, 8, 8, 8, 2, 2, 8,
+ 8, 8, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1,
+ 0, 0, 1, 1, 0, 2, 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, 9, 9, 2, 2, 2, 9, 2, 9, 2, 9, 9, 9, 1, 1,
+ 0, 0, 0, 2, 0, 0, 0, 19, 2, 2, 0, 0, 0, 19, 0, 0,
+ 0, 2, 19, 2, 2, 2, 0, 2, 2, 2, 1, 2, 2, 2, 0, 0,
+ 9, 0, 0, 0, 19, 19, 27, 27, 27, 27, 2, 2, 0, 0, 0, 0,
+ 2, 0, 56, 56, 56, 56, 2, 55, 55, 55, 61, 61, 61, 61, 2, 2,
+ 2, 61, 61, 2, 2, 2, 0, 0, 2, 2, 13, 13, 13, 13, 13, 13,
+ 2, 13, 13, 13, 2, 2, 0, 13, 0, 13, 0, 13, 13, 13, 13, 13,
+ 1, 1, 1, 1, 12, 12, 2, 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, 0, 2, 26, 26, 26, 26, 26, 26, 26, 2, 12,
+ 12, 12, 12, 12, 12, 2, 12, 12, 12, 0, 39, 39, 39, 39, 39, 2,
+ 2, 2, 39, 39, 39, 2, 86, 86, 86, 86, 77, 77, 77, 77, 79, 79,
+ 79, 79, 19, 19, 19, 2, 19, 19, 2, 19, 2, 19, 19, 19, 19, 19,
+ 2, 2, 2, 2, 19, 19, 60, 60, 60, 60, 60, 2, 2, 2, 65, 65,
+ 65, 65, 75, 75, 75, 75, 75, 75, 2, 2, 2, 2, 75, 75, 69, 69,
+ 69, 69, 69, 69, 0, 69, 74, 74, 74, 74, 2, 2, 2, 74, 12, 2,
+ 2, 2, 84, 84, 84, 84, 84, 84, 2, 0, 84, 84, 2, 2, 2, 2,
+ 84, 84, 33, 33, 33, 2, 68, 68, 68, 68, 68, 68, 68, 2, 68, 68,
+ 2, 2, 92, 92, 92, 92, 92, 92, 92, 2, 2, 2, 2, 92, 87, 87,
+ 87, 87, 87, 87, 87, 2, 19, 9, 19, 19, 19, 19, 0, 0, 87, 87,
+ 2, 2, 2, 2, 2, 12, 2, 2, 2, 4, 14, 2, 14, 2, 14, 14,
+ 2, 14, 14, 2, 14, 14, 2, 2, 2, 3, 3, 3, 0, 0, 2, 2,
+ 3, 3, 1, 1, 6, 6, 3, 2, 3, 3, 3, 2, 2, 0, 2, 0,
+ 0, 0, 0, 0, 17, 17, 17, 17, 0, 0, 2, 2, 12, 12, 49, 49,
+ 49, 49, 2, 49, 49, 49, 49, 49, 49, 2, 49, 49, 2, 49, 49, 49,
+ 2, 2, 9, 2, 2, 2, 0, 1, 2, 2, 71, 71, 71, 71, 71, 2,
+ 2, 2, 67, 67, 67, 67, 67, 2, 2, 2, 42, 42, 42, 42, 2, 42,
+ 42, 42, 41, 41, 41, 41, 41, 41, 41, 2,118,118,118,118,118,118,
+ 118, 2, 53, 53, 53, 53, 53, 53, 2, 53, 59, 59, 59, 59, 59, 59,
+ 2, 2, 40, 40, 40, 40, 51, 51, 51, 51, 50, 50, 50, 50, 50, 50,
+ 2, 2,135,135,135,135,106,106,106,106,104,104,104,104, 2, 2,
+ 2,104,161,161,161,161,161,161,161, 2,161,161, 2,161,161, 2,
+ 2, 2,110,110,110,110,110,110,110, 2,110,110, 2, 2, 19, 2,
+ 19, 19, 47, 47, 47, 47, 47, 47, 2, 2, 47, 2, 47, 47, 47, 47,
+ 2, 47, 47, 2, 2, 2, 47, 2, 2, 47, 81, 81, 81, 81, 81, 81,
+ 2, 81,120,120,120,120,116,116,116,116,116,116,116, 2, 2, 2,
+ 2,116,128,128,128,128,128,128,128, 2,128,128, 2, 2, 2, 2,
+ 2,128, 66, 66, 66, 66, 2, 2, 2, 66, 72, 72, 72, 72, 72, 72,
+ 2, 2, 2, 2, 2, 72, 98, 98, 98, 98, 97, 97, 97, 97, 2, 2,
+ 97, 97, 57, 57, 57, 57, 2, 57, 57, 2, 2, 57, 57, 57, 57, 57,
+ 2, 2, 57, 57, 57, 2, 2, 2, 2, 57, 57, 2, 2, 2, 88, 88,
+ 88, 88,117,117,117,117,112,112,112,112,112,112,112, 2, 2, 2,
+ 2,112, 78, 78, 78, 78, 78, 78, 2, 2, 2, 78, 78, 78, 83, 83,
+ 83, 83, 83, 83, 2, 2, 82, 82, 82, 82, 82, 82, 82, 2,122,122,
+ 122,122,122,122, 2, 2, 2,122,122,122,122, 2, 2, 2, 89, 89,
+ 89, 89, 89, 2, 2, 2,130,130,130,130,130,130,130, 2, 2, 2,
+ 130,130,144,144,144,144,144,144, 2, 2,156,156,156,156,156,156,
+ 2,156,156,156, 2, 2, 2, 3, 3, 3,147,147,147,147,148,148,
+ 148,148,148,148, 2, 2,158,158,158,158,158,158, 2, 2,153,153,
+ 153,153,149,149,149,149,149,149,149, 2, 94, 94, 94, 94, 94, 94,
+ 2, 2, 2, 2, 94, 94, 2, 2, 2, 94, 85, 85, 85, 85, 85, 85,
+ 85, 2, 2, 85, 2, 2,101,101,101,101,101, 2, 2, 2,101,101,
+ 2, 2, 96, 96, 96, 96, 96, 2, 96, 96,111,111,111,111,111,111,
+ 111, 2,100,100,100,100,108,108,108,108,108,108, 2,108,108,108,
+ 2, 2,129,129,129,129,129,129,129, 2,129, 2,129,129,129,129,
+ 2,129,129,129, 2, 2,109,109,109,109,109,109,109, 2,109,109,
+ 2, 2,107,107,107,107, 2,107,107,107,107, 2, 2,107,107, 2,
+ 107,107,107,107, 2, 1,107,107, 2, 2,107, 2, 2, 2, 2, 2,
+ 2,107, 2, 2,107,107,137,137,137,137, 2,137,137,137,137,137,
+ 2, 2,124,124,124,124,124,124, 2, 2,123,123,123,123,123,123,
+ 2, 2,114,114,114,114,114, 2, 2, 2,114,114, 2, 2,102,102,
+ 102,102,102,102, 2, 2,126,126,126,126,126,126,126, 2, 2,126,
+ 126,126,142,142,142,142,125,125,125,125,125,125,125, 2, 2, 2,
+ 2,125,154,154,154,154,154,154,154, 2, 2,154, 2, 2, 2,154,
+ 154, 2,154,154, 2,154,154, 2, 2,154,154,154, 2, 2,150,150,
+ 150,150, 2, 2,150,150,150, 2, 2, 2,141,141,141,141,140,140,
+ 140,140,140,140,140, 2,121,121,121,121,121, 2, 2, 2, 7, 7,
+ 2, 2,133,133,133,133,133, 2,133,133,133,133,133, 2,133,133,
+ 2, 2,133, 2, 2, 2,134,134,134,134, 2, 2,134,134, 2,134,
+ 134,134,134,134,134, 2,138,138,138,138,138,138,138, 2,138,138,
+ 2,138, 2, 2,138, 2,138,138, 2, 2,143,143,143,143,143,143,
+ 2,143,143, 2,143,143,143,143,143, 2,143, 2, 2, 2,143,143,
+ 2, 2,145,145,145,145,145, 2, 2, 2,163,163,163,163,163, 2,
+ 163,163,163,163,163, 2, 2, 2,163,163,163,163, 2, 2, 86, 2,
+ 2, 2, 63, 63, 63, 63, 63, 63, 2, 2, 63, 63, 63, 2, 63, 2,
+ 2, 2,157,157,157,157,157,157,157, 2, 80, 80, 80, 80, 80, 80,
+ 2, 2,127,127,127,127,127,127,127, 2, 79, 2, 2, 2,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, 2, 2, 15, 2, 2, 2, 2, 2, 15, 15,
- 15, 2, 2, 17, 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, 2, 2, 2, 2, 2, 19, 19, 19, 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, 6, 6,
- 6, 6, 6, 6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6,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,164,164,
- 164,164,164,164,164,164,164,164, 2, 2, 2, 2, 2, 2, 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, 0, 0, 0, 0, 2, 2,
- 2, 0, 0, 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,
+ 159,159,159,159,159, 2,159,159, 2, 2,103,103,103,103,103,103,
+ 2, 2,119,119,119,119,119,119, 2, 2,119,119, 2,119, 2,119,
+ 119,119,146,146,146,146,146,146,146, 2, 99, 99, 99, 99, 99, 99,
+ 99, 2, 2, 2, 2, 99,136,139, 13, 13,155, 2, 2, 2,136,136,
+ 136,136,155,155,155,155,155,155, 2, 2,136, 2, 2, 2, 2, 17,
+ 17, 17, 2, 17, 17, 2, 17, 15, 15, 15, 17, 17, 17, 2, 2, 2,
+ 15, 2, 2, 17, 2, 2,139,139,139,139,105,105,105,105,105,105,
+ 105, 2,105, 2, 2, 2,105,105, 2, 2, 1, 1, 2, 2, 0, 0,
+ 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 2, 2, 0, 2, 2, 0,
+ 0, 2, 0, 2, 0, 2,131,131,131,131, 2, 2, 2,131, 2,131,
+ 131,131, 56, 56, 56, 2, 56, 2, 2, 56, 56, 56, 2, 56, 56, 2,
+ 56, 56, 6, 6, 2, 2, 2, 2, 2, 6,151,151,151,151,151, 2,
+ 2, 2,151,151, 2, 2, 2, 2,151,151,160,160,160,160,160,160,
+ 160, 2,152,152,152,152,152,152, 2, 2, 2, 2, 2,152,164,164,
+ 164,164,164,164, 2, 2, 2, 30, 30, 2,113,113,113,113,113, 2,
+ 2,113,113,113,113, 2,132,132,132,132,132,132, 2, 2, 2, 2,
+ 132,132, 2, 3, 3, 2, 3, 2, 2, 3, 2, 3, 2, 3, 2, 2,
+ 3, 2, 3, 2, 3, 2, 3, 3, 2, 3, 15, 0, 0, 2, 13, 2,
+ 2, 2, 13, 13, 13, 2, 2, 0, 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, 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, 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, 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, 9, 9, 9, 9, 9, 9,
@@ -3922,60 +3702,60 @@ _hb_ucd_u8[17868] =
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 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,
+ 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, 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, 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,
- 118,119,120,121, 0,122,123,124,125,126, 0,127, 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, 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,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,
- 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,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,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,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, 0, 0, 0, 0, 1, 2, 3, 4,
+ 0, 0, 0, 0, 1, 2, 3, 4,
};
static const uint16_t
-_hb_ucd_u16[9320] =
+_hb_ucd_u16[10040] =
{
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,
@@ -4104,255 +3884,300 @@ _hb_ucd_u16[9320] =
48, 48, 48, 48, 71, 48, 48, 48, 48, 48, 48, 140, 140, 140, 140, 140,
683, 140, 570, 570, 570, 570, 570, 570, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 140, 391, 391, 391, 391, 391, 391, 391, 684,
- 391, 391, 391, 391, 391, 391, 391, 685, 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, 156, 152, 157, 26, 26, 26, 26, 158, 158, 158, 158, 158, 158, 158, 158,
- 158, 159, 158, 158, 158, 160, 159, 158, 158, 158, 158, 159, 158, 158, 158, 161,
- 158, 161, 162, 163, 26, 26, 26, 26, 164, 164, 164, 164, 164, 164, 164, 164,
- 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 165, 165, 165, 165,
- 166, 167, 165, 165, 165, 165, 165, 168, 169, 169, 169, 169, 169, 169, 169, 169,
- 169, 169, 169, 169, 169, 169, 169, 169, 170, 170, 170, 170, 170, 170, 170, 170,
- 170, 171, 172, 171, 170, 170, 170, 170, 170, 171, 170, 170, 170, 170, 171, 172,
- 171, 170, 172, 170, 170, 170, 170, 170, 170, 170, 171, 170, 170, 170, 170, 170,
- 170, 170, 170, 173, 170, 170, 170, 174, 170, 170, 170, 175, 176, 176, 176, 176,
- 176, 176, 176, 176, 176, 176, 177, 177, 178, 178, 178, 178, 178, 178, 178, 178,
- 178, 178, 178, 178, 178, 178, 178, 178, 179, 179, 179, 180, 181, 181, 181, 181,
- 181, 181, 181, 181, 181, 182, 181, 183, 184, 184, 185, 186, 187, 187, 188, 26,
- 189, 189, 190, 26, 191, 192, 193, 26, 194, 194, 194, 194, 194, 194, 194, 194,
- 194, 194, 194, 195, 194, 196, 194, 196, 197, 198, 198, 199, 198, 198, 198, 198,
- 198, 198, 198, 198, 198, 198, 198, 200, 198, 198, 198, 198, 198, 201, 178, 178,
- 178, 178, 178, 178, 178, 178, 202, 26, 203, 203, 203, 204, 203, 205, 203, 205,
- 206, 203, 207, 207, 207, 208, 209, 26, 210, 210, 210, 210, 210, 211, 210, 210,
- 210, 212, 210, 213, 194, 194, 194, 194, 214, 214, 214, 215, 216, 216, 216, 216,
- 216, 216, 216, 217, 216, 216, 216, 218, 216, 219, 216, 219, 216, 220, 9, 9,
- 9, 221, 26, 26, 26, 26, 26, 26, 222, 222, 222, 222, 222, 222, 222, 222,
- 222, 223, 222, 222, 222, 222, 222, 224, 225, 225, 225, 225, 225, 225, 225, 225,
- 226, 226, 226, 226, 226, 226, 227, 228, 229, 229, 229, 229, 229, 229, 229, 230,
- 229, 231, 232, 232, 232, 232, 232, 232, 18, 233, 165, 165, 165, 165, 165, 234,
- 225, 26, 235, 9, 236, 237, 238, 239, 2, 2, 2, 2, 240, 241, 2, 2,
- 2, 2, 2, 242, 243, 244, 2, 245, 2, 2, 2, 2, 2, 2, 2, 246,
- 9, 9, 9, 9, 9, 9, 9, 9, 14, 14, 247, 247, 14, 14, 14, 14,
- 247, 247, 14, 248, 14, 14, 14, 247, 14, 14, 14, 14, 14, 14, 249, 14,
- 249, 14, 250, 251, 14, 14, 252, 253, 0, 254, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 255, 0, 256, 257, 0, 258, 2, 259, 0, 0, 0, 0,
- 260, 26, 9, 9, 9, 9, 261, 26, 0, 0, 0, 0, 262, 263, 4, 0,
- 0, 264, 0, 0, 2, 2, 2, 2, 2, 265, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 258, 26, 26, 26,
- 0, 266, 26, 26, 0, 0, 0, 0, 267, 267, 267, 267, 267, 267, 267, 267,
- 267, 267, 267, 267, 267, 267, 267, 267, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 268, 0, 0, 0, 269, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 270, 270, 270, 270, 270, 270, 270, 270,
- 270, 270, 270, 270, 2, 2, 2, 2, 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 271, 272, 165, 165, 165, 165, 166, 167, 273, 273,
- 273, 273, 273, 273, 273, 274, 275, 274, 170, 170, 172, 26, 172, 172, 172, 172,
- 172, 172, 172, 172, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 276, 26, 26, 26, 26, 277, 277, 277, 278, 277, 277, 277, 277,
- 277, 277, 277, 277, 277, 277, 279, 26, 277, 277, 277, 277, 277, 277, 277, 277,
- 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277,
- 277, 277, 280, 26, 26, 26, 0, 281, 282, 0, 0, 0, 283, 284, 0, 285,
- 286, 287, 287, 287, 287, 287, 287, 287, 287, 287, 288, 289, 290, 291, 291, 291,
- 291, 291, 291, 291, 291, 291, 291, 292, 293, 294, 294, 294, 294, 294, 295, 169,
- 169, 169, 169, 169, 169, 169, 169, 169, 169, 296, 0, 0, 294, 294, 294, 294,
- 0, 0, 0, 0, 281, 26, 291, 291, 169, 169, 169, 296, 0, 0, 0, 0,
- 0, 0, 0, 0, 169, 169, 169, 297, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 291, 291, 291, 291, 291, 298, 291, 291, 291, 291, 291, 291, 291, 291,
- 291, 291, 291, 0, 0, 0, 0, 0, 277, 277, 277, 277, 277, 277, 277, 277,
- 0, 0, 0, 0, 0, 0, 0, 0, 299, 299, 299, 299, 299, 299, 299, 299,
- 299, 299, 299, 299, 299, 299, 299, 299, 299, 300, 299, 299, 299, 299, 299, 299,
- 301, 26, 302, 302, 302, 302, 302, 302, 303, 303, 303, 303, 303, 303, 303, 303,
- 303, 303, 303, 303, 303, 303, 303, 303, 303, 303, 303, 303, 303, 304, 26, 26,
- 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 305, 305, 305, 305,
- 305, 305, 305, 305, 305, 305, 305, 26, 0, 0, 0, 0, 306, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 307, 2, 2, 2, 2, 2, 2,
- 2, 308, 309, 310, 26, 26, 311, 2, 312, 312, 312, 312, 312, 313, 0, 314,
- 315, 315, 315, 315, 315, 315, 315, 26, 316, 316, 316, 316, 316, 316, 316, 316,
- 317, 318, 316, 319, 53, 53, 53, 53, 320, 320, 320, 320, 320, 321, 322, 322,
- 322, 322, 323, 324, 169, 169, 169, 325, 326, 326, 326, 326, 326, 326, 326, 326,
- 326, 327, 326, 328, 164, 164, 164, 329, 330, 330, 330, 330, 330, 330, 331, 26,
- 330, 332, 330, 333, 164, 164, 164, 164, 334, 334, 334, 334, 334, 334, 334, 334,
- 335, 26, 26, 336, 337, 337, 338, 26, 339, 339, 339, 26, 172, 172, 2, 2,
- 2, 2, 2, 340, 341, 342, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176,
- 337, 337, 337, 337, 337, 343, 337, 344, 169, 169, 169, 169, 345, 26, 169, 169,
- 296, 346, 169, 169, 169, 169, 169, 345, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 277, 277, 277, 277, 277, 277, 277, 277,
- 277, 277, 277, 277, 277, 280, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277,
- 277, 277, 277, 347, 26, 26, 26, 26, 348, 26, 349, 350, 25, 25, 351, 352,
- 353, 25, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
- 354, 26, 355, 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, 356,
- 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 357, 31, 31, 31, 31, 31,
- 31, 358, 26, 26, 26, 26, 31, 31, 9, 9, 0, 314, 9, 359, 0, 0,
- 0, 0, 360, 0, 258, 281, 361, 31, 31, 31, 31, 31, 31, 31, 31, 31,
- 31, 31, 31, 31, 31, 31, 31, 362, 363, 0, 0, 0, 1, 2, 2, 3,
- 1, 2, 2, 3, 364, 291, 290, 291, 291, 291, 291, 365, 169, 169, 169, 296,
- 366, 366, 366, 367, 258, 258, 26, 368, 369, 370, 369, 369, 371, 369, 369, 372,
- 369, 373, 369, 373, 26, 26, 26, 26, 369, 369, 369, 369, 369, 369, 369, 369,
- 369, 369, 369, 369, 369, 369, 369, 374, 375, 0, 0, 0, 0, 0, 376, 0,
- 14, 14, 14, 14, 14, 14, 14, 14, 14, 253, 0, 377, 378, 26, 26, 26,
- 26, 26, 0, 0, 0, 0, 0, 379, 380, 380, 380, 381, 382, 382, 382, 382,
- 382, 382, 383, 26, 384, 0, 0, 281, 385, 385, 385, 385, 386, 387, 388, 388,
- 388, 389, 390, 390, 390, 390, 390, 391, 392, 392, 392, 393, 394, 394, 394, 394,
- 395, 394, 396, 26, 26, 26, 26, 26, 397, 397, 397, 397, 397, 397, 397, 397,
- 397, 397, 398, 398, 398, 398, 398, 398, 399, 399, 399, 400, 399, 401, 402, 402,
- 402, 402, 403, 402, 402, 402, 402, 403, 404, 404, 404, 404, 404, 26, 405, 405,
- 405, 405, 405, 405, 406, 407, 408, 409, 408, 409, 410, 408, 411, 408, 411, 412,
- 26, 26, 26, 26, 26, 26, 26, 26, 413, 413, 413, 413, 413, 413, 413, 413,
- 413, 413, 413, 413, 413, 413, 413, 413, 413, 413, 413, 413, 413, 413, 414, 26,
- 413, 413, 415, 26, 413, 26, 26, 26, 416, 2, 2, 2, 2, 2, 417, 308,
- 26, 26, 26, 26, 26, 26, 26, 26, 418, 419, 420, 420, 420, 420, 421, 422,
- 423, 423, 424, 423, 425, 425, 425, 425, 426, 426, 426, 427, 428, 426, 26, 26,
- 26, 26, 26, 26, 429, 429, 430, 431, 432, 432, 432, 433, 434, 434, 434, 435,
- 26, 26, 26, 26, 26, 26, 26, 26, 436, 436, 436, 436, 437, 437, 437, 438,
- 437, 437, 439, 437, 437, 437, 437, 437, 440, 441, 442, 443, 444, 444, 445, 446,
- 444, 447, 444, 447, 448, 448, 448, 448, 449, 449, 449, 449, 26, 26, 26, 26,
- 450, 450, 450, 450, 451, 452, 451, 26, 453, 453, 453, 453, 453, 453, 454, 455,
- 456, 456, 457, 456, 458, 458, 459, 458, 460, 460, 461, 462, 26, 463, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 464, 464, 464, 464, 464, 464, 464, 464,
- 464, 465, 26, 26, 26, 26, 26, 26, 466, 466, 466, 466, 466, 466, 467, 26,
- 466, 466, 466, 466, 466, 466, 467, 468, 469, 469, 469, 469, 469, 26, 469, 470,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 31, 31, 31, 50, 471, 471, 471, 471, 471, 472, 473, 26,
- 26, 26, 26, 26, 26, 26, 26, 474, 475, 475, 475, 475, 475, 26, 476, 476,
- 476, 476, 476, 477, 26, 26, 478, 478, 478, 479, 26, 26, 26, 26, 480, 480,
- 480, 481, 26, 26, 482, 482, 483, 26, 484, 484, 484, 484, 484, 484, 484, 484,
- 484, 485, 486, 484, 484, 484, 485, 487, 488, 488, 488, 488, 488, 488, 488, 488,
- 489, 490, 491, 491, 491, 492, 491, 493, 494, 494, 494, 494, 494, 494, 495, 494,
- 494, 26, 496, 496, 496, 496, 497, 26, 498, 498, 498, 498, 498, 498, 498, 498,
- 498, 498, 498, 498, 499, 137, 500, 26, 501, 501, 502, 501, 501, 501, 501, 501,
- 503, 26, 26, 26, 26, 26, 26, 26, 504, 505, 506, 507, 506, 508, 509, 509,
- 509, 509, 509, 509, 509, 510, 509, 511, 512, 513, 514, 515, 515, 516, 517, 518,
- 513, 519, 520, 521, 522, 523, 523, 26, 524, 524, 524, 524, 524, 524, 524, 524,
- 524, 524, 524, 525, 526, 26, 26, 26, 527, 527, 527, 527, 527, 527, 527, 527,
- 527, 26, 527, 528, 26, 26, 26, 26, 529, 529, 529, 529, 529, 529, 530, 529,
- 529, 529, 529, 530, 26, 26, 26, 26, 531, 531, 531, 531, 531, 531, 531, 531,
- 532, 26, 531, 533, 198, 534, 26, 26, 535, 535, 535, 535, 535, 535, 535, 536,
- 535, 536, 26, 26, 26, 26, 26, 26, 537, 537, 537, 538, 537, 539, 537, 537,
- 540, 26, 26, 26, 26, 26, 26, 26, 541, 541, 541, 541, 541, 541, 541, 542,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 543, 543, 543, 543,
- 543, 543, 543, 543, 543, 543, 544, 545, 546, 547, 548, 549, 549, 549, 550, 551,
- 546, 26, 549, 552, 26, 26, 26, 26, 26, 26, 26, 26, 553, 554, 553, 553,
- 553, 553, 553, 554, 555, 26, 26, 26, 556, 556, 556, 556, 556, 556, 556, 556,
- 556, 26, 557, 557, 557, 557, 557, 557, 557, 557, 557, 557, 558, 26, 178, 178,
- 559, 559, 559, 559, 559, 559, 559, 560, 53, 561, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 562, 563, 562, 562, 562, 562, 564, 562,
- 565, 26, 562, 562, 562, 566, 567, 567, 567, 567, 568, 567, 567, 569, 570, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 571, 572, 573, 573, 573, 573, 571, 574,
- 573, 26, 573, 575, 576, 577, 578, 578, 578, 579, 580, 581, 578, 582, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 583, 583, 583, 584, 585, 585, 586, 585, 585, 585, 585, 587,
- 585, 585, 585, 588, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 589, 26,
- 108, 108, 108, 108, 108, 108, 590, 591, 592, 592, 592, 592, 592, 592, 592, 592,
- 592, 592, 592, 592, 592, 592, 592, 592, 592, 592, 592, 593, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 592, 592, 592, 592, 592, 592, 592, 592,
- 592, 592, 592, 592, 592, 594, 595, 26, 592, 592, 592, 592, 592, 592, 592, 592,
- 596, 26, 26, 26, 26, 26, 26, 26, 26, 26, 597, 597, 597, 597, 597, 597,
- 597, 597, 597, 597, 597, 597, 598, 26, 599, 599, 599, 599, 599, 599, 599, 599,
- 599, 599, 599, 599, 599, 599, 599, 599, 599, 599, 599, 599, 599, 599, 599, 599,
- 599, 599, 600, 26, 26, 26, 26, 26, 601, 601, 601, 601, 601, 601, 601, 601,
- 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601,
- 602, 26, 26, 26, 26, 26, 26, 26, 305, 305, 305, 305, 305, 305, 305, 305,
- 305, 305, 305, 305, 305, 305, 305, 305, 305, 305, 305, 305, 305, 305, 305, 603,
- 604, 604, 604, 605, 604, 606, 607, 607, 607, 607, 607, 607, 607, 607, 607, 608,
- 607, 609, 610, 610, 610, 611, 611, 26, 612, 612, 612, 612, 612, 612, 612, 612,
- 613, 26, 612, 614, 614, 612, 612, 615, 612, 612, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 617, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 618, 618, 618, 618, 618, 618, 618, 618,
- 618, 619, 618, 618, 618, 618, 618, 618, 618, 620, 618, 618, 26, 26, 26, 26,
- 26, 26, 26, 26, 621, 26, 347, 26, 622, 622, 622, 622, 622, 622, 622, 622,
- 622, 622, 622, 622, 622, 622, 622, 622, 622, 622, 622, 622, 622, 622, 622, 622,
- 622, 622, 622, 622, 622, 622, 622, 26, 623, 623, 623, 623, 623, 623, 623, 623,
- 623, 623, 623, 623, 623, 623, 623, 623, 623, 623, 623, 623, 623, 623, 623, 623,
- 623, 623, 624, 26, 26, 26, 26, 26, 622, 625, 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, 626, 627, 628, 287, 287, 287, 287, 287, 287, 287,
- 287, 287, 287, 287, 287, 287, 287, 287, 287, 287, 287, 287, 287, 287, 287, 287,
- 287, 287, 287, 287, 287, 287, 287, 287, 287, 287, 287, 287, 629, 26, 630, 26,
- 26, 26, 631, 26, 632, 26, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633,
- 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633,
- 633, 633, 633, 633, 633, 633, 633, 634, 635, 635, 635, 635, 635, 635, 635, 635,
- 635, 635, 635, 635, 635, 636, 635, 637, 635, 638, 635, 639, 281, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 9, 9, 9, 9, 9, 640, 9, 9,
- 221, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 281, 26, 26, 26, 26, 26, 26, 26, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 276, 26, 0, 0, 0, 0, 258, 363, 0, 0,
- 0, 0, 0, 0, 641, 642, 0, 643, 644, 645, 0, 0, 0, 646, 0, 0,
- 0, 0, 0, 0, 0, 266, 26, 26, 14, 14, 14, 14, 14, 14, 14, 14,
- 247, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 0, 0, 281, 26, 0, 0, 281, 26, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 258, 26, 0, 0, 0, 260, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 255, 647, 648, 0, 649,
- 650, 0, 0, 0, 0, 0, 0, 0, 269, 651, 255, 255, 0, 0, 0, 652,
- 653, 654, 655, 0, 0, 0, 0, 0, 0, 0, 0, 0, 276, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 268, 0, 0, 0, 0, 0, 0, 656, 656, 656, 656, 656, 656, 656, 656,
- 656, 656, 656, 656, 656, 656, 656, 656, 656, 657, 26, 658, 659, 656, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 2, 2, 2, 348, 660, 308, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 661, 270, 270, 662, 663, 664, 18, 18,
- 18, 18, 18, 18, 18, 665, 26, 26, 26, 666, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 667, 667, 667, 667, 667, 668, 667, 669,
- 667, 670, 26, 26, 26, 26, 26, 26, 26, 26, 671, 671, 671, 672, 26, 26,
- 673, 673, 673, 673, 673, 673, 673, 674, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 675, 675, 675, 675, 675, 676, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 172, 677, 170, 172, 678, 678, 678, 678, 678, 678, 678, 678,
- 678, 678, 678, 678, 678, 678, 678, 678, 678, 678, 678, 678, 678, 678, 678, 678,
- 679, 678, 680, 26, 26, 26, 26, 26, 681, 681, 681, 681, 681, 681, 681, 681,
- 681, 682, 681, 683, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 363, 0, 0, 0, 0, 0, 0, 0, 377, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 363, 0, 0, 0, 0, 0, 0, 276,
- 26, 26, 26, 26, 26, 26, 26, 26, 684, 31, 31, 31, 685, 686, 687, 688,
- 689, 690, 685, 691, 685, 687, 687, 692, 31, 693, 31, 694, 695, 693, 31, 694,
- 26, 26, 26, 26, 26, 26, 51, 26, 0, 0, 0, 0, 0, 281, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 281, 26, 0, 258, 363, 0,
- 363, 0, 363, 0, 0, 0, 276, 26, 0, 0, 0, 0, 0, 276, 26, 26,
- 26, 26, 26, 26, 696, 0, 0, 0, 697, 26, 0, 0, 0, 0, 0, 281,
- 0, 260, 314, 26, 276, 26, 26, 26, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 698, 0, 377, 0, 377, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 258, 699, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 314, 0, 281, 260, 26, 0, 281, 0, 0, 0, 0, 0, 0,
- 0, 26, 0, 314, 0, 0, 0, 0, 0, 26, 0, 0, 0, 276, 314, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 281, 26, 0, 276, 0, 377, 0, 260, 0, 0, 0, 0, 0, 269,
- 276, 696, 0, 281, 0, 260, 0, 260, 0, 0, 360, 0, 0, 0, 0, 0,
- 0, 266, 26, 26, 26, 26, 0, 314, 277, 277, 277, 277, 277, 277, 277, 277,
- 277, 277, 277, 277, 26, 26, 26, 26, 277, 277, 277, 277, 277, 277, 277, 347,
- 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 280, 277, 277, 277, 277,
- 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 347, 26, 277, 277,
- 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277,
- 277, 277, 277, 277, 700, 26, 26, 26, 277, 277, 277, 280, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 277, 277, 277, 277, 277, 277, 277, 277,
- 277, 701, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 702, 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,
+ 391, 391, 391, 391, 391, 391, 391, 685, 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, 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,
+ 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, 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,
+ 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, 234, 125, 235, 125, 0, 0,
+ 236, 236, 236, 236, 236, 236, 236, 236, 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,
+ 248, 248, 248, 248, 0, 0, 0, 0, 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, 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, 315, 142, 316, 142, 142, 317, 125, 125, 125, 125, 125, 125, 125, 125,
+ 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, 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, 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, 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, 27, 45, 437, 437, 438, 439, 125, 125, 125, 440,
+ 441, 441, 442, 443, 443, 444, 125, 445, 446, 125, 125, 447, 448, 125, 449, 450,
+ 451, 451, 451, 451, 452, 453, 451, 454, 455, 455, 455, 455, 456, 457, 458, 459,
+ 460, 460, 460, 461, 462, 463, 463, 464, 465, 465, 465, 465, 465, 465, 466, 467,
+ 468, 469, 468, 468, 470, 125, 125, 125, 471, 472, 473, 474, 474, 474, 475, 476,
+ 477, 478, 479, 480, 481, 482, 483, 484, 485, 485, 485, 485, 485, 486, 487, 125,
+ 488, 488, 488, 488, 489, 490, 125, 125, 491, 491, 491, 492, 491, 493, 125, 125,
+ 494, 494, 494, 494, 495, 496, 497, 125, 498, 498, 498, 499, 499, 125, 125, 125,
+ 500, 501, 502, 500, 503, 125, 125, 125, 504, 504, 504, 505, 125, 125, 125, 125,
+ 125, 125, 506, 506, 506, 506, 506, 507, 508, 509, 510, 511, 512, 513, 125, 125,
+ 125, 125, 514, 515, 515, 514, 516, 125, 517, 517, 517, 517, 518, 519, 519, 519,
+ 519, 519, 520, 154, 521, 521, 521, 522, 523, 125, 125, 125, 125, 125, 125, 125,
+ 524, 525, 525, 526, 527, 525, 528, 529, 529, 530, 531, 532, 125, 125, 125, 125,
+ 533, 534, 534, 535, 536, 537, 538, 539, 540, 541, 542, 125, 125, 125, 125, 125,
+ 125, 125, 125, 125, 125, 125, 543, 544, 545, 546, 545, 547, 545, 548, 125, 125,
+ 125, 125, 125, 549, 550, 550, 550, 551, 552, 552, 552, 552, 552, 552, 552, 552,
+ 552, 553, 125, 125, 125, 125, 125, 125, 552, 552, 552, 552, 552, 552, 554, 555,
+ 552, 552, 552, 552, 556, 125, 125, 125, 125, 557, 557, 557, 557, 557, 557, 558,
+ 559, 559, 559, 559, 559, 559, 559, 559, 559, 559, 559, 559, 559, 560, 125, 125,
+ 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 562, 125, 125, 125,
+ 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 563, 564, 565, 566, 567,
+ 567, 567, 567, 568, 569, 570, 571, 572, 573, 573, 573, 573, 574, 575, 576, 577,
+ 573, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 578, 578, 578, 578,
+ 578, 579, 125, 125, 125, 125, 125, 125, 580, 580, 580, 580, 581, 580, 580, 580,
+ 582, 580, 125, 125, 125, 125, 583, 584, 585, 585, 585, 585, 585, 585, 585, 585,
+ 585, 585, 585, 585, 585, 585, 585, 586, 587, 587, 587, 587, 587, 587, 587, 587,
+ 587, 587, 587, 587, 587, 588, 125, 125, 589, 125, 125, 125, 125, 125, 125, 125,
+ 125, 125, 125, 125, 125, 125, 125, 590, 591, 257, 257, 257, 257, 257, 257, 257,
+ 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 592, 593, 125, 594, 595, 596,
+ 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 597,
+ 598, 598, 598, 598, 598, 598, 599, 600, 601, 602, 266, 125, 125, 125, 125, 125,
+ 8, 8, 603, 8, 604, 0, 0, 0, 0, 0, 0, 0, 266, 125, 125, 125,
+ 0, 0, 0, 0, 0, 0, 0, 605, 0, 0, 606, 0, 0, 0, 607, 608,
+ 609, 0, 610, 0, 0, 0, 235, 125, 11, 11, 11, 11, 611, 125, 125, 125,
+ 125, 125, 125, 125, 0, 266, 0, 266, 0, 0, 0, 0, 0, 234, 0, 612,
+ 0, 0, 0, 0, 0, 224, 0, 0, 0, 613, 614, 615, 616, 0, 0, 0,
+ 617, 618, 0, 619, 620, 621, 0, 0, 0, 0, 622, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 623, 0, 0, 0, 624, 624, 624, 624, 624, 624, 624, 624,
+ 625, 626, 627, 125, 125, 125, 125, 125, 4, 628, 629, 125, 125, 125, 125, 125,
+ 630, 631, 632, 14, 14, 14, 633, 125, 634, 125, 125, 125, 125, 125, 125, 125,
+ 635, 635, 636, 637, 638, 125, 125, 125, 125, 639, 640, 125, 641, 641, 641, 642,
+ 125, 125, 125, 125, 125, 643, 643, 644, 125, 125, 125, 125, 125, 125, 645, 646,
+ 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 648, 649, 125, 125,
+ 650, 650, 650, 650, 651, 652, 125, 125, 125, 125, 125, 125, 125, 125, 125, 334,
+ 0, 0, 0, 653, 125, 125, 125, 125, 334, 0, 0, 247, 125, 125, 125, 125,
+ 654, 27, 655, 656, 657, 658, 659, 660, 661, 662, 663, 662, 125, 125, 125, 664,
+ 0, 0, 252, 0, 0, 0, 0, 0, 0, 266, 226, 334, 334, 334, 0, 605,
+ 0, 0, 247, 125, 125, 125, 665, 0, 666, 0, 0, 252, 612, 667, 605, 125,
+ 0, 0, 0, 0, 0, 668, 350, 350, 0, 0, 0, 0, 0, 0, 0, 669,
+ 0, 0, 0, 0, 0, 285, 252, 228, 252, 0, 0, 0, 670, 285, 0, 0,
+ 670, 0, 247, 667, 125, 125, 125, 125, 0, 0, 0, 0, 0, 266, 247, 350,
+ 612, 0, 0, 671, 672, 252, 612, 612, 0, 330, 0, 0, 235, 125, 125, 285,
+ 248, 248, 248, 248, 248, 248, 125, 125, 248, 248, 248, 319, 248, 248, 248, 248,
+ 248, 318, 248, 248, 248, 248, 248, 248, 248, 248, 584, 248, 248, 248, 248, 248,
+ 248, 248, 248, 248, 248, 248, 673, 125, 248, 318, 125, 125, 125, 125, 125, 125,
+ 248, 248, 248, 248, 674, 248, 248, 248, 248, 248, 248, 125, 125, 125, 125, 125,
+ 675, 125, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 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, 10, 11,
+ 12, 13, 14, 15, 8, 8, 8, 8, 16, 8, 8, 8, 17, 18, 18, 18,
+ 19, 19, 19, 19, 19, 20, 19, 19, 21, 22, 22, 22, 22, 22, 22, 22,
+ 22, 23, 21, 22, 22, 22, 23, 21, 24, 25, 25, 25, 25, 25, 25, 25,
+ 25, 25, 12, 12, 25, 25, 26, 27, 25, 28, 12, 12, 29, 30, 29, 31,
+ 29, 29, 32, 32, 29, 29, 29, 29, 31, 29, 33, 7, 7, 34, 29, 29,
+ 35, 29, 29, 29, 29, 29, 29, 30, 36, 36, 36, 37, 36, 36, 36, 36,
+ 36, 36, 38, 39, 40, 40, 40, 40, 41, 12, 12, 12, 42, 42, 42, 42,
+ 42, 42, 43, 44, 45, 45, 45, 45, 45, 45, 45, 46, 45, 45, 45, 47,
+ 48, 48, 48, 48, 48, 48, 48, 49, 36, 36, 38, 12, 29, 29, 29, 50,
+ 51, 12, 29, 29, 52, 29, 29, 29, 53, 53, 53, 53, 54, 55, 53, 53,
+ 53, 56, 53, 53, 57, 58, 57, 59, 59, 57, 57, 57, 57, 57, 60, 57,
+ 61, 62, 63, 57, 57, 59, 59, 64, 12, 65, 12, 66, 57, 62, 57, 57,
+ 57, 57, 57, 64, 67, 67, 68, 69, 70, 71, 71, 71, 71, 71, 72, 71,
+ 72, 73, 74, 72, 68, 69, 70, 74, 75, 12, 67, 76, 12, 77, 71, 71,
+ 71, 68, 12, 12, 78, 78, 79, 80, 80, 79, 79, 79, 79, 79, 81, 79,
+ 81, 78, 82, 79, 79, 80, 80, 82, 83, 12, 12, 12, 79, 84, 79, 79,
+ 82, 12, 78, 79, 85, 85, 86, 87, 87, 86, 86, 86, 86, 86, 88, 86,
+ 88, 85, 89, 86, 86, 87, 87, 89, 12, 85, 12, 90, 86, 91, 86, 86,
+ 86, 86, 12, 12, 92, 93, 94, 92, 95, 96, 97, 95, 98, 99, 94, 92,
+ 100, 100, 96, 92, 94, 92, 95, 96, 99, 98, 12, 12, 12, 92, 100, 100,
+ 100, 100, 94, 12, 101, 101, 101, 102, 102, 101, 101, 101, 101, 101, 102, 101,
+ 101, 101, 103, 101, 101, 102, 102, 103, 12, 104, 105, 106, 101, 107, 101, 101,
+ 12, 108, 101, 101, 109, 109, 109, 110, 110, 109, 109, 109, 109, 109, 110, 109,
+ 109, 111, 112, 109, 109, 110, 110, 112, 12, 113, 12, 113, 109, 114, 109, 109,
+ 111, 12, 12, 12, 115, 115, 115, 116, 116, 115, 115, 115, 115, 115, 115, 115,
+ 115, 116, 116, 115, 12, 115, 115, 115, 115, 117, 115, 115, 118, 118, 119, 119,
+ 119, 120, 121, 119, 119, 119, 119, 119, 122, 119, 119, 123, 119, 120, 124, 125,
+ 119, 126, 119, 119, 12, 121, 119, 119, 121, 127, 12, 12, 128, 129, 129, 129,
+ 129, 129, 129, 129, 129, 129, 130, 131, 129, 129, 129, 12, 12, 12, 12, 12,
+ 132, 133, 134, 135, 135, 135, 135, 135, 135, 136, 135, 135, 135, 135, 135, 137,
+ 135, 138, 135, 134, 135, 135, 137, 135, 139, 139, 139, 139, 139, 139, 140, 139,
+ 139, 139, 139, 141, 140, 139, 139, 139, 139, 139, 139, 142, 139, 143, 144, 12,
+ 145, 145, 145, 145, 146, 146, 146, 146, 146, 147, 12, 148, 146, 146, 149, 146,
+ 150, 150, 150, 150, 151, 151, 151, 151, 151, 151, 152, 153, 151, 154, 152, 153,
+ 152, 153, 151, 154, 152, 153, 151, 151, 151, 154, 151, 151, 151, 151, 154, 155,
+ 151, 151, 151, 156, 151, 151, 153, 12, 157, 157, 157, 157, 157, 158, 157, 158,
+ 159, 159, 159, 159, 160, 160, 160, 160, 160, 160, 160, 161, 162, 162, 162, 162,
+ 162, 162, 163, 164, 162, 162, 165, 12, 166, 166, 166, 166, 166, 167, 12, 168,
+ 169, 169, 169, 169, 169, 170, 12, 12, 171, 171, 171, 171, 171, 12, 12, 12,
+ 172, 172, 172, 173, 173, 12, 12, 12, 174, 174, 174, 174, 174, 174, 174, 175,
+ 174, 174, 175, 12, 176, 177, 178, 178, 178, 178, 179, 12, 178, 178, 178, 178,
+ 178, 178, 180, 12, 178, 178, 181, 12, 159, 182, 12, 12, 183, 183, 183, 183,
+ 183, 183, 183, 184, 183, 183, 183, 12, 185, 183, 183, 183, 186, 186, 186, 186,
+ 186, 186, 186, 187, 186, 188, 12, 12, 189, 189, 189, 189, 189, 189, 189, 12,
+ 189, 189, 190, 12, 189, 189, 191, 192, 193, 193, 193, 193, 193, 193, 193, 194,
+ 195, 195, 195, 195, 195, 195, 195, 196, 195, 195, 195, 197, 195, 195, 198, 12,
+ 195, 195, 195, 198, 7, 7, 7, 199, 200, 200, 200, 200, 200, 200, 200, 201,
+ 200, 200, 200, 202, 203, 203, 203, 203, 204, 204, 204, 204, 204, 12, 12, 204,
+ 205, 205, 205, 205, 205, 205, 206, 205, 205, 205, 207, 208, 209, 209, 209, 209,
+ 19, 19, 210, 12, 146, 146, 211, 212, 203, 203, 12, 12, 213, 7, 7, 7,
+ 214, 7, 215, 216, 0, 215, 217, 12, 2, 218, 219, 2, 2, 2, 2, 220,
+ 221, 218, 222, 2, 2, 2, 223, 2, 2, 2, 2, 224, 8, 225, 8, 225,
+ 8, 8, 226, 226, 8, 8, 8, 225, 8, 15, 8, 8, 8, 10, 8, 227,
+ 10, 15, 8, 14, 0, 0, 0, 228, 0, 229, 0, 0, 230, 0, 0, 231,
+ 0, 0, 0, 232, 2, 2, 2, 233, 234, 12, 12, 12, 235, 12, 12, 12,
+ 0, 236, 237, 0, 4, 0, 0, 0, 0, 0, 0, 4, 2, 2, 5, 12,
+ 0, 232, 12, 12, 0, 0, 232, 12, 238, 238, 238, 238, 0, 239, 0, 0,
+ 0, 240, 0, 0, 241, 241, 241, 241, 18, 18, 18, 18, 18, 12, 242, 18,
+ 243, 243, 243, 243, 243, 243, 12, 244, 245, 12, 12, 244, 151, 154, 12, 12,
+ 151, 154, 151, 154, 0, 0, 0, 246, 247, 247, 247, 247, 247, 247, 248, 247,
+ 247, 12, 12, 12, 247, 249, 12, 12, 0, 0, 0, 12, 0, 250, 0, 0,
+ 251, 247, 252, 253, 0, 0, 247, 0, 254, 255, 255, 255, 255, 255, 255, 255,
+ 255, 256, 257, 258, 259, 260, 260, 260, 260, 260, 260, 260, 260, 260, 261, 259,
+ 12, 262, 263, 263, 263, 263, 263, 263, 264, 150, 150, 150, 150, 150, 150, 265,
+ 0, 12, 12, 12, 150, 150, 150, 266, 260, 260, 260, 261, 260, 260, 0, 0,
+ 267, 267, 267, 267, 267, 267, 267, 268, 267, 269, 12, 12, 270, 270, 270, 270,
+ 271, 271, 271, 271, 271, 271, 271, 12, 272, 272, 272, 272, 272, 272, 12, 12,
+ 237, 2, 2, 2, 2, 2, 231, 2, 2, 2, 273, 12, 274, 275, 276, 12,
+ 277, 2, 2, 2, 278, 278, 278, 278, 278, 278, 278, 279, 0, 0, 246, 12,
+ 280, 280, 280, 280, 280, 280, 12, 12, 281, 281, 281, 281, 281, 282, 12, 283,
+ 281, 281, 282, 12, 284, 284, 284, 284, 284, 284, 284, 285, 286, 286, 286, 286,
+ 286, 12, 12, 287, 150, 150, 150, 288, 289, 289, 289, 289, 289, 289, 289, 290,
+ 289, 289, 291, 292, 145, 145, 145, 293, 294, 294, 294, 294, 294, 295, 12, 12,
+ 294, 294, 294, 296, 294, 294, 296, 294, 297, 297, 297, 297, 298, 12, 12, 12,
+ 12, 12, 299, 297, 300, 300, 300, 300, 300, 301, 12, 12, 155, 154, 155, 154,
+ 155, 154, 12, 12, 2, 2, 3, 2, 2, 302, 303, 12, 300, 300, 300, 304,
+ 300, 300, 304, 12, 150, 12, 12, 12, 150, 265, 305, 150, 150, 150, 150, 12,
+ 247, 247, 247, 249, 247, 247, 249, 12, 2, 273, 12, 12, 306, 22, 12, 24,
+ 25, 26, 25, 307, 308, 309, 25, 25, 50, 12, 12, 12, 310, 29, 29, 29,
+ 29, 29, 29, 311, 312, 29, 29, 29, 29, 29, 12, 310, 7, 7, 7, 313,
+ 232, 0, 0, 0, 0, 232, 0, 12, 29, 314, 29, 29, 29, 29, 29, 315,
+ 316, 0, 0, 0, 0, 317, 260, 260, 260, 260, 260, 318, 319, 150, 319, 150,
+ 319, 150, 319, 288, 0, 232, 0, 232, 12, 12, 316, 246, 320, 320, 320, 321,
+ 320, 320, 320, 320, 320, 322, 320, 320, 320, 320, 322, 323, 320, 320, 320, 324,
+ 320, 320, 322, 12, 232, 131, 0, 0, 0, 131, 0, 0, 8, 8, 8, 14,
+ 0, 0, 0, 234, 325, 12, 12, 12, 0, 0, 0, 326, 327, 327, 327, 327,
+ 327, 327, 327, 328, 329, 329, 329, 329, 330, 12, 12, 12, 215, 0, 0, 0,
+ 331, 331, 331, 331, 331, 12, 12, 332, 333, 333, 333, 333, 333, 333, 334, 12,
+ 335, 335, 335, 335, 335, 335, 336, 12, 337, 337, 337, 337, 337, 337, 337, 338,
+ 339, 339, 339, 339, 339, 12, 339, 339, 339, 340, 12, 12, 341, 341, 341, 341,
+ 342, 342, 342, 342, 343, 343, 343, 343, 343, 343, 343, 344, 343, 343, 344, 12,
+ 345, 345, 345, 345, 345, 12, 345, 345, 345, 345, 345, 12, 346, 346, 346, 346,
+ 346, 346, 12, 12, 347, 347, 347, 347, 347, 12, 12, 348, 349, 349, 350, 349,
+ 350, 351, 349, 349, 351, 349, 349, 349, 351, 349, 351, 352, 353, 353, 353, 353,
+ 353, 354, 12, 12, 353, 355, 12, 12, 353, 353, 12, 12, 2, 274, 2, 2,
+ 356, 2, 273, 12, 357, 358, 359, 357, 357, 357, 357, 357, 357, 360, 361, 362,
+ 363, 363, 363, 363, 363, 364, 363, 363, 365, 365, 365, 365, 366, 366, 366, 366,
+ 366, 366, 366, 367, 12, 368, 366, 366, 369, 369, 369, 369, 370, 371, 372, 369,
+ 373, 373, 373, 373, 373, 373, 373, 374, 375, 375, 375, 375, 375, 375, 376, 377,
+ 378, 378, 378, 378, 379, 379, 379, 379, 379, 379, 12, 379, 380, 379, 379, 379,
+ 381, 382, 12, 381, 381, 383, 383, 381, 381, 381, 381, 381, 381, 384, 385, 386,
+ 381, 381, 387, 12, 388, 388, 388, 388, 389, 389, 389, 389, 390, 390, 390, 390,
+ 390, 391, 392, 390, 390, 391, 12, 12, 393, 393, 393, 393, 393, 394, 395, 393,
+ 396, 396, 396, 396, 396, 397, 396, 396, 398, 398, 398, 398, 399, 12, 398, 398,
+ 400, 400, 400, 400, 401, 12, 402, 403, 12, 12, 402, 400, 404, 404, 404, 404,
+ 404, 404, 405, 12, 406, 406, 406, 406, 407, 12, 12, 12, 407, 12, 408, 406,
+ 409, 409, 409, 409, 409, 409, 12, 12, 409, 409, 410, 12, 411, 411, 411, 411,
+ 411, 411, 412, 413, 413, 12, 12, 12, 12, 12, 12, 414, 415, 415, 415, 415,
+ 415, 415, 12, 12, 416, 416, 416, 416, 416, 416, 417, 12, 418, 418, 418, 418,
+ 418, 418, 419, 12, 420, 420, 420, 420, 420, 420, 420, 12, 421, 421, 421, 421,
+ 421, 422, 12, 12, 423, 423, 423, 423, 423, 423, 423, 424, 425, 423, 423, 423,
+ 423, 424, 12, 426, 427, 427, 427, 427, 428, 12, 12, 429, 430, 430, 430, 430,
+ 430, 430, 431, 12, 430, 430, 432, 12, 433, 433, 433, 433, 433, 434, 433, 433,
+ 433, 433, 12, 12, 435, 435, 435, 435, 435, 436, 12, 12, 437, 437, 437, 437,
+ 118, 119, 119, 119, 119, 127, 12, 12, 438, 438, 438, 438, 439, 438, 438, 438,
+ 440, 12, 12, 12, 441, 442, 443, 444, 441, 441, 441, 444, 441, 441, 445, 12,
+ 446, 446, 446, 446, 446, 446, 447, 12, 446, 446, 448, 12, 449, 450, 449, 451,
+ 451, 449, 449, 449, 449, 449, 452, 449, 452, 450, 453, 449, 449, 451, 451, 454,
+ 455, 456, 12, 450, 449, 457, 449, 455, 449, 455, 12, 12, 458, 458, 458, 458,
+ 458, 458, 458, 459, 460, 12, 12, 12, 461, 461, 461, 461, 461, 461, 12, 12,
+ 461, 461, 462, 12, 463, 463, 463, 463, 463, 464, 463, 463, 463, 463, 463, 464,
+ 465, 465, 465, 465, 465, 466, 12, 12, 465, 465, 467, 12, 178, 178, 178, 180,
+ 468, 468, 468, 468, 468, 468, 469, 12, 470, 470, 470, 470, 470, 470, 471, 472,
+ 470, 470, 470, 12, 470, 471, 12, 12, 473, 473, 473, 473, 473, 473, 473, 12,
+ 474, 474, 474, 474, 475, 12, 12, 476, 477, 478, 479, 477, 477, 480, 477, 477,
+ 477, 477, 477, 477, 477, 481, 482, 477, 477, 478, 12, 12, 477, 477, 483, 12,
+ 484, 484, 485, 484, 484, 484, 484, 484, 484, 486, 12, 12, 487, 487, 487, 487,
+ 487, 487, 12, 12, 488, 488, 488, 488, 489, 12, 12, 12, 490, 490, 490, 490,
+ 490, 490, 491, 12, 53, 53, 492, 12, 493, 493, 494, 493, 493, 493, 493, 493,
+ 493, 495, 493, 493, 493, 496, 12, 12, 493, 493, 493, 497, 498, 498, 498, 498,
+ 499, 498, 498, 498, 498, 498, 500, 498, 498, 501, 12, 12, 502, 503, 504, 502,
+ 502, 502, 502, 502, 502, 503, 505, 504, 502, 502, 12, 12, 502, 502, 506, 12,
+ 507, 508, 509, 507, 507, 507, 507, 507, 507, 507, 507, 510, 508, 507, 511, 12,
+ 507, 507, 512, 12, 513, 513, 513, 513, 513, 513, 514, 12, 515, 515, 515, 515,
+ 516, 515, 515, 515, 515, 515, 517, 518, 515, 515, 519, 12, 520, 12, 12, 12,
+ 100, 100, 100, 100, 96, 12, 12, 98, 521, 521, 521, 521, 521, 521, 522, 12,
+ 521, 521, 521, 523, 521, 524, 12, 12, 521, 12, 12, 12, 525, 525, 525, 525,
+ 526, 12, 12, 12, 527, 527, 527, 527, 527, 528, 12, 12, 529, 529, 529, 529,
+ 529, 530, 12, 12, 272, 272, 531, 12, 532, 532, 532, 532, 532, 532, 532, 533,
+ 532, 532, 534, 535, 536, 536, 536, 536, 536, 536, 536, 537, 536, 536, 538, 12,
+ 539, 539, 539, 539, 539, 539, 539, 540, 539, 540, 12, 12, 541, 541, 541, 541,
+ 541, 542, 12, 12, 541, 541, 543, 541, 543, 541, 541, 541, 541, 541, 12, 544,
+ 545, 545, 545, 545, 545, 545, 546, 12, 547, 547, 547, 547, 547, 547, 548, 549,
+ 547, 547, 12, 549, 550, 551, 12, 12, 249, 12, 12, 12, 552, 552, 552, 552,
+ 552, 552, 12, 12, 553, 553, 553, 553, 553, 554, 12, 12, 552, 552, 555, 12,
+ 260, 556, 260, 557, 558, 255, 255, 255, 559, 12, 12, 12, 560, 12, 12, 12,
+ 256, 561, 12, 12, 12, 260, 12, 12, 562, 562, 562, 562, 562, 562, 562, 12,
+ 563, 563, 563, 563, 563, 563, 564, 12, 563, 563, 563, 565, 563, 563, 565, 12,
+ 563, 563, 566, 563, 7, 7, 7, 567, 7, 199, 12, 12, 0, 246, 12, 12,
+ 0, 232, 316, 0, 0, 568, 228, 0, 0, 0, 568, 7, 213, 569, 7, 0,
+ 0, 0, 570, 228, 8, 225, 12, 12, 0, 0, 234, 12, 0, 0, 0, 229,
+ 571, 572, 316, 229, 0, 0, 240, 316, 0, 316, 0, 0, 0, 240, 232, 316,
+ 0, 229, 0, 229, 0, 0, 240, 232, 0, 573, 239, 0, 229, 0, 0, 0,
+ 0, 246, 0, 0, 0, 0, 0, 239, 574, 574, 574, 574, 574, 574, 574, 12,
+ 12, 12, 575, 574, 576, 574, 574, 574, 2, 2, 2, 273, 12, 275, 273, 12,
+ 241, 577, 241, 241, 241, 241, 578, 241, 579, 580, 577, 12, 19, 19, 19, 581,
+ 12, 12, 12, 582, 583, 583, 583, 583, 583, 583, 583, 584, 583, 583, 583, 585,
+ 583, 583, 585, 586, 587, 587, 587, 587, 587, 587, 587, 588, 589, 589, 589, 589,
+ 589, 589, 590, 591, 592, 592, 592, 592, 592, 592, 593, 12, 151, 154, 151, 594,
+ 151, 151, 151, 154, 595, 595, 595, 595, 595, 596, 595, 595, 595, 597, 12, 12,
+ 598, 598, 598, 598, 598, 598, 598, 12, 598, 598, 599, 600, 0, 234, 12, 12,
+ 29, 414, 29, 29, 601, 602, 414, 29, 50, 29, 603, 12, 604, 310, 603, 414,
+ 601, 602, 603, 603, 601, 602, 50, 29, 50, 29, 414, 605, 29, 29, 606, 29,
+ 29, 29, 29, 12, 414, 414, 606, 29, 51, 12, 12, 12, 12, 239, 0, 0,
+ 607, 12, 12, 12, 246, 12, 12, 12, 0, 0, 12, 0, 0, 232, 131, 0,
+ 0, 0, 12, 12, 0, 0, 0, 240, 0, 246, 12, 239, 608, 12, 12, 12,
+ 247, 247, 609, 12, 610, 12, 12, 12, 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,
@@ -4562,21 +4387,14 @@ _hb_ucd_u16[9320] =
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
@@ -4597,17 +4415,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[9540+(((_hb_ucd_u8[9420+(((_hb_ucd_b4(9292+_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[9684+(((_hb_ucd_u8[9452+(((_hb_ucd_u8[9356+(((_hb_ucd_b4(9292+_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<918000u?_hb_ucd_u8[11062+(((_hb_ucd_u16[2040+(((_hb_ucd_u8[10326+(((_hb_ucd_u8[9876+(u>>3>>4>>4)])<<4)+((u>>3>>4)&15u))])<<4)+((u>>3)&15u))])<<3)+((u)&7u))]:2;
+ return u<918000u?_hb_ucd_u8[11118+(((_hb_ucd_u16[4024+(((_hb_ucd_u16[2040+(((_hb_ucd_u8[10382+(((_hb_ucd_u8[9932+(u>>2>>2>>3>>4)])<<4)+((u>>2>>2>>3)&15u))])<<3)+((u>>2>>2)&7u))])<<2)+((u>>2)&3u))])<<2)+((u)&3u))]:2;
}
static inline uint_fast16_t
_hb_ucd_dm (unsigned u)
{
- return u<195102u?_hb_ucd_u16[6008+(((_hb_ucd_u8[17068+(((_hb_ucd_u8[16686+(u>>4>>5)])<<5)+((u>>4)&31u))])<<4)+((u)&15u))]:0;
+ return u<195102u?_hb_ucd_u16[6728+(((_hb_ucd_u8[13944+(((_hb_ucd_u8[13562+(u>>4>>5)])<<5)+((u>>4)&31u))])<<4)+((u)&15u))]:0;
}
diff --git a/thirdparty/harfbuzz/src/hb-ucd.cc b/thirdparty/harfbuzz/src/hb-ucd.cc
index baea224a25..4c8b1ee5e6 100644
--- a/thirdparty/harfbuzz/src/hb-ucd.cc
+++ b/thirdparty/harfbuzz/src/hb-ucd.cc
@@ -129,12 +129,16 @@ hb_ucd_compose (hb_unicode_funcs_t *ufuncs HB_UNUSED,
hb_codepoint_t a, hb_codepoint_t b, hb_codepoint_t *ab,
void *user_data HB_UNUSED)
{
+ // Hangul is handled algorithmically.
if (_hb_ucd_compose_hangul (a, b, ab)) return true;
hb_codepoint_t u = 0;
if ((a & 0xFFFFF800u) == 0x0000u && (b & 0xFFFFFF80) == 0x0300u)
{
+ /* If "a" is small enough and "b" is in the U+0300 range,
+ * the composition data is encoded in a 32bit array sorted
+ * by "a,b" pair. */
uint32_t k = HB_CODEPOINT_ENCODE3_11_7_14 (a, b, 0);
const uint32_t *v = hb_bsearch (k,
_hb_ucd_dm2_u32_map,
@@ -146,6 +150,8 @@ hb_ucd_compose (hb_unicode_funcs_t *ufuncs HB_UNUSED,
}
else
{
+ /* Otherwise it is stored in a 64bit array sorted by
+ * "a,b" pair. */
uint64_t k = HB_CODEPOINT_ENCODE3 (a, b, 0);
const uint64_t *v = hb_bsearch (k,
_hb_ucd_dm2_u64_map,
@@ -170,15 +176,22 @@ hb_ucd_decompose (hb_unicode_funcs_t *ufuncs HB_UNUSED,
unsigned i = _hb_ucd_dm (ab);
+ /* If no data, there's no decomposition. */
if (likely (!i)) return false;
i--;
+ /* Check if it's a single-character decomposition. */
if (i < ARRAY_LENGTH (_hb_ucd_dm1_p0_map) + ARRAY_LENGTH (_hb_ucd_dm1_p2_map))
{
+ /* Single-character decompositions currently are only in plane 0 or plane 2. */
if (i < ARRAY_LENGTH (_hb_ucd_dm1_p0_map))
+ {
+ /* Plane 0. */
*a = _hb_ucd_dm1_p0_map[i];
+ }
else
{
+ /* Plane 2. */
i -= ARRAY_LENGTH (_hb_ucd_dm1_p0_map);
*a = 0x20000 | _hb_ucd_dm1_p2_map[i];
}
@@ -187,8 +200,10 @@ hb_ucd_decompose (hb_unicode_funcs_t *ufuncs HB_UNUSED,
}
i -= ARRAY_LENGTH (_hb_ucd_dm1_p0_map) + ARRAY_LENGTH (_hb_ucd_dm1_p2_map);
+ /* Otherwise they are encoded either in a 32bit array or a 64bit array. */
if (i < ARRAY_LENGTH (_hb_ucd_dm2_u32_map))
{
+ /* 32bit array. */
uint32_t v = _hb_ucd_dm2_u32_map[i];
*a = HB_CODEPOINT_DECODE3_11_7_14_1 (v);
*b = HB_CODEPOINT_DECODE3_11_7_14_2 (v);
@@ -196,6 +211,7 @@ hb_ucd_decompose (hb_unicode_funcs_t *ufuncs HB_UNUSED,
}
i -= ARRAY_LENGTH (_hb_ucd_dm2_u32_map);
+ /* 64bit array. */
uint64_t v = _hb_ucd_dm2_u64_map[i];
*a = HB_CODEPOINT_DECODE3_1 (v);
*b = HB_CODEPOINT_DECODE3_2 (v);
diff --git a/thirdparty/harfbuzz/src/hb-unicode.cc b/thirdparty/harfbuzz/src/hb-unicode.cc
index c1795dc7f2..9a6471e52c 100644
--- a/thirdparty/harfbuzz/src/hb-unicode.cc
+++ b/thirdparty/harfbuzz/src/hb-unicode.cc
@@ -377,20 +377,30 @@ hb_unicode_funcs_set_##name##_func (hb_unicode_funcs_t *ufuncs, \
hb_destroy_func_t destroy) \
{ \
if (hb_object_is_immutable (ufuncs)) \
- return; \
+ goto fail; \
+ \
+ if (!func) \
+ { \
+ if (destroy) \
+ destroy (user_data); \
+ destroy = nullptr; \
+ user_data = ufuncs->parent->user_data.name; \
+ } \
\
if (ufuncs->destroy.name) \
ufuncs->destroy.name (ufuncs->user_data.name); \
\
- if (func) { \
+ if (func) \
ufuncs->func.name = func; \
- ufuncs->user_data.name = user_data; \
- ufuncs->destroy.name = destroy; \
- } else { \
+ else \
ufuncs->func.name = ufuncs->parent->func.name; \
- ufuncs->user_data.name = ufuncs->parent->user_data.name; \
- ufuncs->destroy.name = nullptr; \
- } \
+ ufuncs->user_data.name = user_data; \
+ ufuncs->destroy.name = destroy; \
+ return; \
+ \
+fail: \
+ if (destroy) \
+ destroy (user_data); \
}
HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS
diff --git a/thirdparty/harfbuzz/src/hb-uniscribe.cc b/thirdparty/harfbuzz/src/hb-uniscribe.cc
index 50f71ce9ce..9648e02663 100644
--- a/thirdparty/harfbuzz/src/hb-uniscribe.cc
+++ b/thirdparty/harfbuzz/src/hb-uniscribe.cc
@@ -355,7 +355,7 @@ _hb_rename_font (hb_blob_t *blob, wchar_t *new_name)
return nullptr;
}
- memcpy(new_sfnt_data, orig_sfnt_data, length);
+ hb_memcpy(new_sfnt_data, orig_sfnt_data, length);
OT::name &name = StructAtOffset<OT::name> (new_sfnt_data, name_table_offset);
name.format = 0;
@@ -478,11 +478,11 @@ populate_log_font (LOGFONTW *lf,
hb_font_t *font,
unsigned int font_size)
{
- memset (lf, 0, sizeof (*lf));
+ hb_memset (lf, 0, sizeof (*lf));
lf->lfHeight = - (int) font_size;
lf->lfCharSet = DEFAULT_CHARSET;
- memcpy (lf->lfFaceName, font->face->data.uniscribe->face_name, sizeof (lf->lfFaceName));
+ hb_memcpy (lf->lfFaceName, font->face->data.uniscribe->face_name, sizeof (lf->lfFaceName));
return true;
}
diff --git a/thirdparty/harfbuzz/src/hb-vector.hh b/thirdparty/harfbuzz/src/hb-vector.hh
index a6d9f6b3fb..9b52f5ca95 100644
--- a/thirdparty/harfbuzz/src/hb-vector.hh
+++ b/thirdparty/harfbuzz/src/hb-vector.hh
@@ -35,7 +35,7 @@
template <typename Type,
bool sorted=false>
-struct hb_vector_t : std::conditional<sorted, hb_vector_t<Type, false>, hb_empty_t>::type
+struct hb_vector_t
{
typedef Type item_t;
static constexpr unsigned item_size = hb_static_size (Type);
@@ -53,9 +53,10 @@ struct hb_vector_t : std::conditional<sorted, hb_vector_t<Type, false>, hb_empty
hb_requires (hb_is_iterable (Iterable))>
hb_vector_t (const Iterable &o) : hb_vector_t ()
{
- if (hb_iter (o).is_random_access_iterator)
- alloc (hb_len (hb_iter (o)));
- hb_copy (o, *this);
+ auto iter = hb_iter (o);
+ if (iter.is_random_access_iterator)
+ alloc (hb_len (iter));
+ hb_copy (iter, *this);
}
hb_vector_t (const hb_vector_t &o) : hb_vector_t ()
{
@@ -83,6 +84,9 @@ struct hb_vector_t : std::conditional<sorted, hb_vector_t<Type, false>, hb_empty
allocated = length = 0;
arrayZ = nullptr;
}
+ void init0 ()
+ {
+ }
void fini ()
{
@@ -94,7 +98,11 @@ struct hb_vector_t : std::conditional<sorted, hb_vector_t<Type, false>, hb_empty
void reset ()
{
if (unlikely (in_error ()))
- allocated = length; // Big hack!
+ /* Big Hack! We don't know the true allocated size before
+ * an allocation failure happened. But we know it was at
+ * least as big as length. Restore it to that and continue
+ * as if error did not happen. */
+ allocated = length;
resize (0);
}
@@ -122,7 +130,7 @@ struct hb_vector_t : std::conditional<sorted, hb_vector_t<Type, false>, hb_empty
}
hb_bytes_t as_bytes () const
- { return hb_bytes_t ((const char *) arrayZ, length * item_size); }
+ { return hb_bytes_t ((const char *) arrayZ, get_size ()); }
bool operator == (const hb_vector_t &o) const { return as_array () == o.as_array (); }
bool operator != (const hb_vector_t &o) const { return !(*this == o); }
@@ -164,14 +172,10 @@ struct hb_vector_t : std::conditional<sorted, hb_vector_t<Type, false>, hb_empty
operator iter_t () const { return iter (); }
operator writer_t () { return writer (); }
- c_array_t sub_array (unsigned int start_offset, unsigned int count) const
- { return as_array ().sub_array (start_offset, count); }
- c_array_t sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */) const
- { return as_array ().sub_array (start_offset, count); }
- array_t sub_array (unsigned int start_offset, unsigned int count)
- { return as_array ().sub_array (start_offset, count); }
- array_t sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */)
- { return as_array ().sub_array (start_offset, count); }
+ /* Faster range-based for loop. */
+ Type *begin () const { return arrayZ; }
+ Type *end () const { return arrayZ + length; }
+
hb_sorted_array_t<Type> as_sorted_array ()
{ return hb_sorted_array (arrayZ, length); }
@@ -240,12 +244,11 @@ struct hb_vector_t : std::conditional<sorted, hb_vector_t<Type, false>, hb_empty
if (likely (new_array))
{
for (unsigned i = 0; i < length; i++)
+ {
new (std::addressof (new_array[i])) Type ();
- for (unsigned i = 0; i < (unsigned) length; i++)
new_array[i] = std::move (arrayZ[i]);
- unsigned old_length = length;
- shrink_vector (0);
- length = old_length;
+ arrayZ[i].~Type ();
+ }
hb_free (arrayZ);
}
return new_array;
@@ -277,7 +280,14 @@ struct hb_vector_t : std::conditional<sorted, hb_vector_t<Type, false>, hb_empty
copy_vector (const hb_vector_t &other)
{
length = other.length;
- hb_memcpy ((void *) arrayZ, (const void *) other.arrayZ, length * item_size);
+#ifndef HB_OPTIMIZE_SIZE
+ if (sizeof (T) >= sizeof (long long))
+ /* This runs faster because of alignment. */
+ for (unsigned i = 0; i < length; i++)
+ arrayZ[i] = other.arrayZ[i];
+ else
+#endif
+ hb_memcpy ((void *) arrayZ, (const void *) other.arrayZ, length * item_size);
}
template <typename T = Type,
hb_enable_if (!hb_is_trivially_copyable (T) &&
@@ -309,15 +319,6 @@ struct hb_vector_t : std::conditional<sorted, hb_vector_t<Type, false>, hb_empty
}
}
- template <typename T = Type,
- hb_enable_if (hb_is_trivially_destructible(T))>
- void
- shrink_vector (unsigned size)
- {
- length = size;
- }
- template <typename T = Type,
- hb_enable_if (!hb_is_trivially_destructible(T))>
void
shrink_vector (unsigned size)
{
@@ -328,17 +329,6 @@ struct hb_vector_t : std::conditional<sorted, hb_vector_t<Type, false>, hb_empty
}
}
- template <typename T = Type,
- hb_enable_if (hb_is_trivially_copy_assignable(T))>
- void
- shift_down_vector (unsigned i)
- {
- memmove (static_cast<void *> (&arrayZ[i - 1]),
- static_cast<void *> (&arrayZ[i]),
- (length - i) * sizeof (Type));
- }
- template <typename T = Type,
- hb_enable_if (!hb_is_trivially_copy_assignable(T))>
void
shift_down_vector (unsigned i)
{
@@ -381,16 +371,22 @@ struct hb_vector_t : std::conditional<sorted, hb_vector_t<Type, false>, hb_empty
return true;
}
- bool resize (int size_)
+ bool resize (int size_, bool initialize = true)
{
unsigned int size = size_ < 0 ? 0u : (unsigned int) size_;
if (!alloc (size))
return false;
if (size > length)
- grow_vector (size);
+ {
+ if (initialize)
+ grow_vector (size);
+ }
else if (size < length)
- shrink_vector (size);
+ {
+ if (initialize)
+ shrink_vector (size);
+ }
length = size;
return true;
@@ -399,13 +395,13 @@ struct hb_vector_t : std::conditional<sorted, hb_vector_t<Type, false>, hb_empty
Type pop ()
{
if (!length) return Null (Type);
- Type v = arrayZ[length - 1];
+ Type v {std::move (arrayZ[length - 1])};
arrayZ[length - 1].~Type ();
length--;
return v;
}
- void remove (unsigned int i)
+ void remove_ordered (unsigned int i)
{
if (unlikely (i >= length))
return;
@@ -414,6 +410,18 @@ struct hb_vector_t : std::conditional<sorted, hb_vector_t<Type, false>, hb_empty
length--;
}
+ template <bool Sorted = sorted,
+ hb_enable_if (!Sorted)>
+ void remove_unordered (unsigned int i)
+ {
+ if (unlikely (i >= length))
+ return;
+ if (i != length - 1)
+ arrayZ[i] = std::move (arrayZ[length - 1]);
+ arrayZ[length - 1].~Type ();
+ length--;
+ }
+
void shrink (int size_)
{
unsigned int size = size_ < 0 ? 0u : (unsigned int) size_;
@@ -425,10 +433,8 @@ struct hb_vector_t : std::conditional<sorted, hb_vector_t<Type, false>, hb_empty
/* Sorting API. */
- void qsort (int (*cmp)(const void*, const void*))
+ void qsort (int (*cmp)(const void*, const void*) = Type::cmp)
{ as_array ().qsort (cmp); }
- void qsort (unsigned int start = 0, unsigned int end = (unsigned int) -1)
- { as_array ().qsort (start, end); }
/* Unsorted search API. */
template <typename T>
diff --git a/thirdparty/harfbuzz/src/hb-version.h b/thirdparty/harfbuzz/src/hb-version.h
index 8d6ec66e13..1070262a3b 100644
--- a/thirdparty/harfbuzz/src/hb-version.h
+++ b/thirdparty/harfbuzz/src/hb-version.h
@@ -41,26 +41,26 @@ HB_BEGIN_DECLS
*
* The major component of the library version available at compile-time.
*/
-#define HB_VERSION_MAJOR 5
+#define HB_VERSION_MAJOR 6
/**
* HB_VERSION_MINOR:
*
* The minor component of the library version available at compile-time.
*/
-#define HB_VERSION_MINOR 3
+#define HB_VERSION_MINOR 0
/**
* HB_VERSION_MICRO:
*
* The micro component of the library version available at compile-time.
*/
-#define HB_VERSION_MICRO 1
+#define HB_VERSION_MICRO 0
/**
* HB_VERSION_STRING:
*
* A string literal containing the library version available at compile-time.
*/
-#define HB_VERSION_STRING "5.3.1"
+#define HB_VERSION_STRING "6.0.0"
/**
* HB_VERSION_ATLEAST:
diff --git a/thirdparty/harfbuzz/src/hb.hh b/thirdparty/harfbuzz/src/hb.hh
index 8ec638a2b4..410d090d36 100644
--- a/thirdparty/harfbuzz/src/hb.hh
+++ b/thirdparty/harfbuzz/src/hb.hh
@@ -126,6 +126,7 @@
/* Ignored intentionally. */
#ifndef HB_NO_PRAGMA_GCC_DIAGNOSTIC_IGNORED
#pragma GCC diagnostic ignored "-Wclass-memaccess"
+#pragma GCC diagnostic ignored "-Wcast-function-type-strict" // https://github.com/harfbuzz/harfbuzz/pull/3859#issuecomment-1295409126
#pragma GCC diagnostic ignored "-Wformat-nonliteral"
#pragma GCC diagnostic ignored "-Wformat-zero-length"
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
diff --git a/thirdparty/libpng/arm/arm_init.c b/thirdparty/libpng/arm/arm_init.c
index ab22525b38..84d05556f8 100644
--- a/thirdparty/libpng/arm/arm_init.c
+++ b/thirdparty/libpng/arm/arm_init.c
@@ -36,7 +36,10 @@
#ifndef PNG_ARM_NEON_FILE
# if defined(__aarch64__) || defined(_M_ARM64)
/* ARM Neon is expected to be unconditionally available on ARM64. */
-# error "PNG_ARM_NEON_CHECK_SUPPORTED must not be defined on this platform"
+# error "PNG_ARM_NEON_CHECK_SUPPORTED must not be defined on ARM64"
+# elif defined(__ARM_NEON__) || defined(__ARM_NEON)
+ /* ARM Neon is expected to be available on the target CPU architecture. */
+# error "PNG_ARM_NEON_CHECK_SUPPORTED must not be defined on this CPU arch"
# elif defined(__linux__)
# define PNG_ARM_NEON_FILE "contrib/arm-neon/linux.c"
# else
diff --git a/thirdparty/libpng/png.c b/thirdparty/libpng/png.c
index fc09564262..4f3e8bbd31 100644
--- a/thirdparty/libpng/png.c
+++ b/thirdparty/libpng/png.c
@@ -14,7 +14,7 @@
#include "pngpriv.h"
/* Generate a compiler error if there is an old png.h in the search path. */
-typedef png_libpng_version_1_6_38 Your_png_h_is_not_version_1_6_38;
+typedef png_libpng_version_1_6_39 Your_png_h_is_not_version_1_6_39;
#ifdef __GNUC__
/* The version tests may need to be added to, but the problem warning has
@@ -815,7 +815,7 @@ png_get_copyright(png_const_structrp png_ptr)
return PNG_STRING_COPYRIGHT
#else
return PNG_STRING_NEWLINE \
- "libpng version 1.6.38" PNG_STRING_NEWLINE \
+ "libpng version 1.6.39" PNG_STRING_NEWLINE \
"Copyright (c) 2018-2022 Cosmin Truta" PNG_STRING_NEWLINE \
"Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson" \
PNG_STRING_NEWLINE \
@@ -2710,7 +2710,7 @@ png_check_IHDR(png_const_structrp png_ptr,
int /* PRIVATE */
png_check_fp_number(png_const_charp string, size_t size, int *statep,
- png_size_tp whereami)
+ size_t *whereami)
{
int state = *statep;
size_t i = *whereami;
diff --git a/thirdparty/libpng/png.h b/thirdparty/libpng/png.h
index 5fb494fb1a..f109cdf336 100644
--- a/thirdparty/libpng/png.h
+++ b/thirdparty/libpng/png.h
@@ -1,7 +1,7 @@
/* png.h - header file for PNG reference library
*
- * libpng version 1.6.38 - September 14, 2022
+ * libpng version 1.6.39 - November 20, 2022
*
* Copyright (c) 2018-2022 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
@@ -15,7 +15,7 @@
* libpng versions 0.89, June 1996, through 0.96, May 1997: Andreas Dilger
* libpng versions 0.97, January 1998, through 1.6.35, July 2018:
* Glenn Randers-Pehrson
- * libpng versions 1.6.36, December 2018, through 1.6.38, September 2022:
+ * libpng versions 1.6.36, December 2018, through 1.6.39, November 2022:
* Cosmin Truta
* See also "Contributing Authors", below.
*/
@@ -239,7 +239,7 @@
* ...
* 1.5.30 15 10530 15.so.15.30[.0]
* ...
- * 1.6.38 16 10638 16.so.16.38[.0]
+ * 1.6.39 16 10639 16.so.16.39[.0]
*
* Henceforth the source version will match the shared-library major and
* minor numbers; the shared-library major version number will be used for
@@ -278,8 +278,8 @@
*/
/* Version information for png.h - this should match the version in png.c */
-#define PNG_LIBPNG_VER_STRING "1.6.38"
-#define PNG_HEADER_VERSION_STRING " libpng version 1.6.38 - September 14, 2022\n"
+#define PNG_LIBPNG_VER_STRING "1.6.39"
+#define PNG_HEADER_VERSION_STRING " libpng version 1.6.39 - November 20, 2022\n"
#define PNG_LIBPNG_VER_SONUM 16
#define PNG_LIBPNG_VER_DLLNUM 16
@@ -287,7 +287,7 @@
/* These should match the first 3 components of PNG_LIBPNG_VER_STRING: */
#define PNG_LIBPNG_VER_MAJOR 1
#define PNG_LIBPNG_VER_MINOR 6
-#define PNG_LIBPNG_VER_RELEASE 38
+#define PNG_LIBPNG_VER_RELEASE 39
/* This should be zero for a public release, or non-zero for a
* development version. [Deprecated]
@@ -318,7 +318,7 @@
* From version 1.0.1 it is:
* XXYYZZ, where XX=major, YY=minor, ZZ=release
*/
-#define PNG_LIBPNG_VER 10638 /* 1.6.38 */
+#define PNG_LIBPNG_VER 10639 /* 1.6.39 */
/* Library configuration: these options cannot be changed after
* the library has been built.
@@ -428,7 +428,7 @@ extern "C" {
/* This triggers a compiler error in png.c, if png.c and png.h
* do not agree upon the version number.
*/
-typedef char* png_libpng_version_1_6_38;
+typedef char* png_libpng_version_1_6_39;
/* Basic control structions. Read libpng-manual.txt or libpng.3 for more info.
*
diff --git a/thirdparty/libpng/pngconf.h b/thirdparty/libpng/pngconf.h
index 89d28f83a0..fcb4b43069 100644
--- a/thirdparty/libpng/pngconf.h
+++ b/thirdparty/libpng/pngconf.h
@@ -1,7 +1,7 @@
/* pngconf.h - machine-configurable file for libpng
*
- * libpng version 1.6.38
+ * libpng version 1.6.39
*
* Copyright (c) 2018-2022 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2016,2018 Glenn Randers-Pehrson
diff --git a/thirdparty/libpng/pnglibconf.h b/thirdparty/libpng/pnglibconf.h
index 89d5b4c8ad..e5948c8ce1 100644
--- a/thirdparty/libpng/pnglibconf.h
+++ b/thirdparty/libpng/pnglibconf.h
@@ -1,6 +1,6 @@
/* pnglibconf.h - library build configuration */
-/* libpng version 1.6.38 */
+/* libpng version 1.6.39 */
/* Copyright (c) 2018-2022 Cosmin Truta */
/* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson */
diff --git a/thirdparty/libpng/pngpriv.h b/thirdparty/libpng/pngpriv.h
index 2e426cf47d..b8a73b685d 100644
--- a/thirdparty/libpng/pngpriv.h
+++ b/thirdparty/libpng/pngpriv.h
@@ -1946,7 +1946,7 @@ PNG_INTERNAL_FUNCTION(void,png_ascii_from_fixed,(png_const_structrp png_ptr,
* the problem character.) This has not been tested within libpng.
*/
PNG_INTERNAL_FUNCTION(int,png_check_fp_number,(png_const_charp string,
- size_t size, int *statep, png_size_tp whereami),PNG_EMPTY);
+ size_t size, int *statep, size_t *whereami),PNG_EMPTY);
/* This is the same but it checks a complete string and returns true
* only if it just contains a floating point number. As of 1.5.4 this
diff --git a/thirdparty/libpng/pngread.c b/thirdparty/libpng/pngread.c
index 5ab9224038..96996ced5b 100644
--- a/thirdparty/libpng/pngread.c
+++ b/thirdparty/libpng/pngread.c
@@ -3762,13 +3762,13 @@ png_image_read_direct(png_voidp argument)
mode = PNG_ALPHA_PNG;
output_gamma = PNG_DEFAULT_sRGB;
}
-
+
if ((change & PNG_FORMAT_FLAG_ASSOCIATED_ALPHA) != 0)
{
mode = PNG_ALPHA_OPTIMIZED;
change &= ~PNG_FORMAT_FLAG_ASSOCIATED_ALPHA;
}
-
+
/* If 'do_local_background' is set check for the presence of gamma
* correction; this is part of the work-round for the libpng bug
* described above.
diff --git a/thirdparty/libpng/pngrutil.c b/thirdparty/libpng/pngrutil.c
index ca060dd15f..068ab193a3 100644
--- a/thirdparty/libpng/pngrutil.c
+++ b/thirdparty/libpng/pngrutil.c
@@ -3186,7 +3186,7 @@ png_check_chunk_length(png_const_structrp png_ptr, png_uint_32 length)
{
png_debug2(0," length = %lu, limit = %lu",
(unsigned long)length,(unsigned long)limit);
- png_chunk_error(png_ptr, "chunk data is too large");
+ png_benign_error(png_ptr, "chunk data is too large");
}
}
diff --git a/thirdparty/libpng/pngwrite.c b/thirdparty/libpng/pngwrite.c
index 06c45d16ab..4e58d776a9 100644
--- a/thirdparty/libpng/pngwrite.c
+++ b/thirdparty/libpng/pngwrite.c
@@ -75,10 +75,10 @@ write_unknown_chunks(png_structrp png_ptr, png_const_inforp info_ptr,
* library. If you have a new chunk to add, make a function to write it,
* and put it in the correct location here. If you want the chunk written
* after the image data, put it in png_write_end(). I strongly encourage
- * you to supply a PNG_INFO_ flag, and check info_ptr->valid before writing
- * the chunk, as that will keep the code from breaking if you want to just
- * write a plain PNG file. If you have long comments, I suggest writing
- * them in png_write_end(), and compressing them.
+ * you to supply a PNG_INFO_<chunk> flag, and check info_ptr->valid before
+ * writing the chunk, as that will keep the code from breaking if you want
+ * to just write a plain PNG file. If you have long comments, I suggest
+ * writing them in png_write_end(), and compressing them.
*/
void PNGAPI
png_write_info_before_PLTE(png_structrp png_ptr, png_const_inforp info_ptr)
diff --git a/thirdparty/libpng/pngwutil.c b/thirdparty/libpng/pngwutil.c
index 16345e4c0b..01f0607c70 100644
--- a/thirdparty/libpng/pngwutil.c
+++ b/thirdparty/libpng/pngwutil.c
@@ -1,7 +1,7 @@
/* pngwutil.c - utilities to write a PNG file
*
- * Copyright (c) 2018 Cosmin Truta
+ * Copyright (c) 2018-2022 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
* Copyright (c) 1996-1997 Andreas Dilger
* Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
@@ -1747,7 +1747,7 @@ png_write_pCAL(png_structrp png_ptr, png_charp purpose, png_int_32 X0,
{
png_uint_32 purpose_len;
size_t units_len, total_len;
- png_size_tp params_len;
+ size_t *params_len;
png_byte buf[10];
png_byte new_purpose[80];
int i;
@@ -1769,7 +1769,7 @@ png_write_pCAL(png_structrp png_ptr, png_charp purpose, png_int_32 X0,
png_debug1(3, "pCAL units length = %d", (int)units_len);
total_len = purpose_len + units_len + 10;
- params_len = (png_size_tp)png_malloc(png_ptr,
+ params_len = (size_t *)png_malloc(png_ptr,
(png_alloc_size_t)((png_alloc_size_t)nparams * (sizeof (size_t))));
/* Find the length of each parameter, making sure we don't count the
diff --git a/thirdparty/libtheora/LICENSE b/thirdparty/libtheora/LICENSE
index 5e5ec08469..97e8431790 100644
--- a/thirdparty/libtheora/LICENSE
+++ b/thirdparty/libtheora/LICENSE
@@ -4,13 +4,13 @@ In addition to and irrespective of the copyright license associated
with this software, On2 Technologies, Inc. makes the following statement
regarding technology used in this software:
- On2 represents and warrants that it shall not assert any rights
+ On2 represents and warrants that it shall not assert any rights
relating to infringement of On2's registered patents, nor initiate
any litigation asserting such rights, against any person who, or
- entity which utilizes the On2 VP3 Codec Software, including any
- use, distribution, and sale of said Software; which make changes,
+ entity which utilizes the On2 VP3 Codec Software, including any
+ use, distribution, and sale of said Software; which make changes,
modifications, and improvements in said Software; and to use,
- distribute, and sell said changes as well as applications for other
+ distribute, and sell said changes as well as applications for other
fields of use.
This reference implementation is originally derived from the On2 VP3
diff --git a/thirdparty/libtheora/analyze.c b/thirdparty/libtheora/analyze.c
index af01b60dff..19d7612d23 100644
--- a/thirdparty/libtheora/analyze.c
+++ b/thirdparty/libtheora/analyze.c
@@ -18,12 +18,12 @@
#include <string.h>
#include "encint.h"
#include "modedec.h"
+#if defined(OC_COLLECT_METRICS)
+# include "collect.c"
+#endif
-typedef struct oc_fr_state oc_fr_state;
-typedef struct oc_qii_state oc_qii_state;
-typedef struct oc_enc_pipeline_state oc_enc_pipeline_state;
typedef struct oc_rd_metric oc_rd_metric;
typedef struct oc_mode_choice oc_mode_choice;
@@ -42,7 +42,7 @@ typedef struct oc_mode_choice oc_mode_choice;
This is the inverse of the equivalent table OC_MODE_ALPHABETS in the
decoder.*/
static const unsigned char OC_MODE_RANKS[7][OC_NMODES]={
- /*Last MV dominates.*/
+ /*Last MV dominates.*/
/*L P M N I G GM 4*/
{3,4,2,0,1,5,6,7},
/*L P N M I G GM 4*/
@@ -87,6 +87,29 @@ static void oc_mode_scheme_chooser_reset(oc_mode_scheme_chooser *_chooser){
}
}
+/*Return the cost of coding _mb_mode in the specified scheme.*/
+static int oc_mode_scheme_chooser_scheme_mb_cost(
+ const oc_mode_scheme_chooser *_chooser,int _scheme,int _mb_mode){
+ int codebook;
+ int ri;
+ codebook=_scheme+1>>3;
+ /*For any scheme except 0, we can just use the bit cost of the mode's rank
+ in that scheme.*/
+ ri=_chooser->mode_ranks[_scheme][_mb_mode];
+ if(_scheme==0){
+ int mc;
+ /*For scheme 0, incrementing the mode count could potentially change the
+ mode's rank.
+ Find the index where the mode would be moved to in the optimal list,
+ and use its bit cost instead of the one for the mode's current
+ position in the list.*/
+ /*We don't actually reorder the list; this is for computing opportunity
+ cost, not an update.*/
+ mc=_chooser->mode_counts[_mb_mode];
+ while(ri>0&&mc>=_chooser->mode_counts[_chooser->scheme0_list[ri-1]])ri--;
+ }
+ return OC_MODE_BITS[codebook][ri];
+}
/*This is the real purpose of this data structure: not actually selecting a
mode scheme, but estimating the cost of coding a given mode given all the
@@ -108,46 +131,32 @@ static int oc_mode_scheme_chooser_cost(oc_mode_scheme_chooser *_chooser,
int best_bits;
int mode_bits;
int si;
- int scheme_bits;
+ int scheme0_bits;
+ int scheme1_bits;
scheme0=_chooser->scheme_list[0];
scheme1=_chooser->scheme_list[1];
- best_bits=_chooser->scheme_bits[scheme0];
- mode_bits=OC_MODE_BITS[scheme0+1>>3][_chooser->mode_ranks[scheme0][_mb_mode]];
+ scheme0_bits=_chooser->scheme_bits[scheme0];
+ scheme1_bits=_chooser->scheme_bits[scheme1];
+ mode_bits=oc_mode_scheme_chooser_scheme_mb_cost(_chooser,scheme0,_mb_mode);
/*Typical case: If the difference between the best scheme and the next best
is greater than 6 bits, then adding just one mode cannot change which
scheme we use.*/
- if(_chooser->scheme_bits[scheme1]-best_bits>6)return mode_bits;
+ if(scheme1_bits-scheme0_bits>6)return mode_bits;
/*Otherwise, check to see if adding this mode selects a different scheme as
the best.*/
si=1;
- best_bits+=mode_bits;
+ best_bits=scheme0_bits+mode_bits;
do{
- /*For any scheme except 0, we can just use the bit cost of the mode's rank
- in that scheme.*/
- if(scheme1!=0){
- scheme_bits=_chooser->scheme_bits[scheme1]+
- OC_MODE_BITS[scheme1+1>>3][_chooser->mode_ranks[scheme1][_mb_mode]];
- }
- else{
- int ri;
- /*For scheme 0, incrementing the mode count could potentially change the
- mode's rank.
- Find the index where the mode would be moved to in the optimal list,
- and use its bit cost instead of the one for the mode's current
- position in the list.*/
- /*We don't recompute scheme bits; this is computing opportunity cost, not
- an update.*/
- for(ri=_chooser->scheme0_ranks[_mb_mode];ri>0&&
- _chooser->mode_counts[_mb_mode]>=
- _chooser->mode_counts[_chooser->scheme0_list[ri-1]];ri--);
- scheme_bits=_chooser->scheme_bits[0]+OC_MODE_BITS[0][ri];
- }
- if(scheme_bits<best_bits)best_bits=scheme_bits;
+ int cur_bits;
+ cur_bits=scheme1_bits+
+ oc_mode_scheme_chooser_scheme_mb_cost(_chooser,scheme1,_mb_mode);
+ if(cur_bits<best_bits)best_bits=cur_bits;
if(++si>=8)break;
scheme1=_chooser->scheme_list[si];
+ scheme1_bits=_chooser->scheme_bits[scheme1];
}
- while(_chooser->scheme_bits[scheme1]-_chooser->scheme_bits[scheme0]<=6);
- return best_bits-_chooser->scheme_bits[scheme0];
+ while(scheme1_bits-scheme0_bits<=6);
+ return best_bits-scheme0_bits;
}
/*Incrementally update the mode counts and per-scheme bit counts and re-order
@@ -211,22 +220,6 @@ static int oc_block_run_bits(int _run_count){
-/*State to track coded block flags and their bit cost.*/
-struct oc_fr_state{
- ptrdiff_t bits;
- unsigned sb_partial_count:16;
- unsigned sb_full_count:16;
- unsigned b_coded_count_prev:8;
- unsigned b_coded_count:8;
- unsigned b_count:8;
- signed int sb_partial:2;
- signed int sb_full:2;
- signed int b_coded_prev:2;
- signed int b_coded:2;
-};
-
-
-
static void oc_fr_state_init(oc_fr_state *_fr){
_fr->bits=0;
_fr->sb_partial_count=0;
@@ -234,6 +227,8 @@ static void oc_fr_state_init(oc_fr_state *_fr){
_fr->b_coded_count_prev=0;
_fr->b_coded_count=0;
_fr->b_count=0;
+ _fr->sb_prefer_partial=0;
+ _fr->sb_bits=0;
_fr->sb_partial=-1;
_fr->sb_full=-1;
_fr->b_coded_prev=-1;
@@ -241,14 +236,14 @@ static void oc_fr_state_init(oc_fr_state *_fr){
}
-static void oc_fr_state_advance_sb(oc_fr_state *_fr,
+static int oc_fr_state_sb_cost(const oc_fr_state *_fr,
int _sb_partial,int _sb_full){
- ptrdiff_t bits;
- int sb_partial_count;
- int sb_full_count;
- bits=_fr->bits;
+ int bits;
+ int sb_partial_count;
+ int sb_full_count;
+ bits=0;
+ sb_partial_count=_fr->sb_partial_count;
/*Extend the sb_partial run, or start a new one.*/
- sb_partial_count=_fr->sb_partial;
if(_fr->sb_partial==_sb_partial){
if(sb_partial_count>=4129){
bits++;
@@ -257,8 +252,7 @@ static void oc_fr_state_advance_sb(oc_fr_state *_fr,
else bits-=oc_sb_run_bits(sb_partial_count);
}
else sb_partial_count=0;
- sb_partial_count++;
- bits+=oc_sb_run_bits(sb_partial_count);
+ bits+=oc_sb_run_bits(++sb_partial_count);
if(!_sb_partial){
/*Extend the sb_full run, or start a new one.*/
sb_full_count=_fr->sb_full_count;
@@ -270,98 +264,161 @@ static void oc_fr_state_advance_sb(oc_fr_state *_fr,
else bits-=oc_sb_run_bits(sb_full_count);
}
else sb_full_count=0;
+ bits+=oc_sb_run_bits(++sb_full_count);
+ }
+ return bits;
+}
+
+static void oc_fr_state_advance_sb(oc_fr_state *_fr,
+ int _sb_partial,int _sb_full){
+ int sb_partial_count;
+ int sb_full_count;
+ sb_partial_count=_fr->sb_partial_count;
+ if(_fr->sb_partial!=_sb_partial||sb_partial_count>=4129)sb_partial_count=0;
+ sb_partial_count++;
+ if(!_sb_partial){
+ sb_full_count=_fr->sb_full_count;
+ if(_fr->sb_full!=_sb_full||sb_full_count>=4129)sb_full_count=0;
sb_full_count++;
- bits+=oc_sb_run_bits(sb_full_count);
- _fr->sb_full=_sb_full;
_fr->sb_full_count=sb_full_count;
+ _fr->sb_full=_sb_full;
+ /*Roll back the partial block state.*/
+ _fr->b_coded=_fr->b_coded_prev;
+ _fr->b_coded_count=_fr->b_coded_count_prev;
+ }
+ else{
+ /*Commit back the partial block state.*/
+ _fr->b_coded_prev=_fr->b_coded;
+ _fr->b_coded_count_prev=_fr->b_coded_count;
}
- _fr->bits=bits;
- _fr->sb_partial=_sb_partial;
_fr->sb_partial_count=sb_partial_count;
+ _fr->sb_partial=_sb_partial;
+ _fr->b_count=0;
+ _fr->sb_prefer_partial=0;
+ _fr->sb_bits=0;
}
-/*Flush any outstanding block flags for a SB (e.g., one with fewer than 16
- blocks).*/
+/*Commit the state of the current super block and advance to the next.*/
static void oc_fr_state_flush_sb(oc_fr_state *_fr){
- ptrdiff_t bits;
- int sb_partial;
- int sb_full=sb_full;
- int b_coded_count;
- int b_coded;
- int b_count;
+ int sb_partial;
+ int sb_full;
+ int b_coded_count;
+ int b_count;
b_count=_fr->b_count;
- if(b_count>0){
- bits=_fr->bits;
- b_coded=_fr->b_coded;
- b_coded_count=_fr->b_coded_count;
- if(b_coded_count>=b_count){
- /*This SB was fully coded/uncoded; roll back the partial block flags.*/
- bits-=oc_block_run_bits(b_coded_count);
- if(b_coded_count>b_count)bits+=oc_block_run_bits(b_coded_count-b_count);
- sb_partial=0;
- sb_full=b_coded;
- b_coded=_fr->b_coded_prev;
- b_coded_count=_fr->b_coded_count_prev;
- }
- else{
- /*It was partially coded.*/
- sb_partial=1;
- /*sb_full is unused.*/
+ b_coded_count=_fr->b_coded_count;
+ sb_full=_fr->b_coded;
+ sb_partial=b_coded_count<b_count;
+ if(!sb_partial){
+ /*If the super block is fully coded/uncoded...*/
+ if(_fr->sb_prefer_partial){
+ /*So far coding this super block as partial was cheaper anyway.*/
+ if(b_coded_count>15||_fr->b_coded_prev<0){
+ int sb_bits;
+ /*If the block run is too long, this will limit how far it can be
+ extended into the next partial super block.
+ If we need to extend it farther, we don't want to have to roll all
+ the way back here (since there could be many full SBs between now
+ and then), so we disallow this.
+ Similarly, if this is the start of a stripe, we don't know how the
+ length of the outstanding block run from the previous stripe.*/
+ sb_bits=oc_fr_state_sb_cost(_fr,sb_partial,sb_full);
+ _fr->bits+=sb_bits-_fr->sb_bits;
+ _fr->sb_bits=sb_bits;
+ }
+ else sb_partial=1;
}
- _fr->bits=bits;
- _fr->b_coded_count=b_coded_count;
- _fr->b_coded_count_prev=b_coded_count;
- _fr->b_count=0;
- _fr->b_coded=b_coded;
- _fr->b_coded_prev=b_coded;
- oc_fr_state_advance_sb(_fr,sb_partial,sb_full);
}
+ oc_fr_state_advance_sb(_fr,sb_partial,sb_full);
}
static void oc_fr_state_advance_block(oc_fr_state *_fr,int _b_coded){
ptrdiff_t bits;
+ int sb_bits;
int b_coded_count;
int b_count;
- int sb_partial;
- int sb_full=sb_full;
- bits=_fr->bits;
- /*Extend the b_coded run, or start a new one.*/
+ int sb_prefer_partial;
+ sb_bits=_fr->sb_bits;
+ bits=_fr->bits-sb_bits;
+ b_count=_fr->b_count;
b_coded_count=_fr->b_coded_count;
- if(_fr->b_coded==_b_coded)bits-=oc_block_run_bits(b_coded_count);
- else b_coded_count=0;
- b_coded_count++;
- b_count=_fr->b_count+1;
- if(b_count>=16){
- /*We finished a superblock.*/
- if(b_coded_count>=16){
- /*It was fully coded/uncoded; roll back the partial block flags.*/
- if(b_coded_count>16)bits+=oc_block_run_bits(b_coded_count-16);
- sb_partial=0;
- sb_full=_b_coded;
- _b_coded=_fr->b_coded_prev;
- b_coded_count=_fr->b_coded_count_prev;
+ sb_prefer_partial=_fr->sb_prefer_partial;
+ if(b_coded_count>=b_count){
+ int sb_partial_bits;
+ /*This super block is currently fully coded/uncoded.*/
+ if(b_count<=0){
+ /*This is the first block in this SB.*/
+ b_count=1;
+ /*Check to see whether it's cheaper to code it partially or fully.*/
+ if(_fr->b_coded==_b_coded){
+ sb_partial_bits=-oc_block_run_bits(b_coded_count);
+ sb_partial_bits+=oc_block_run_bits(++b_coded_count);
+ }
+ else{
+ b_coded_count=1;
+ sb_partial_bits=2;
+ }
+ sb_partial_bits+=oc_fr_state_sb_cost(_fr,1,_b_coded);
+ sb_bits=oc_fr_state_sb_cost(_fr,0,_b_coded);
+ sb_prefer_partial=sb_partial_bits<sb_bits;
+ sb_bits^=(sb_partial_bits^sb_bits)&-sb_prefer_partial;
+ }
+ else if(_fr->b_coded==_b_coded){
+ b_coded_count++;
+ if(++b_count<16){
+ if(sb_prefer_partial){
+ /*Check to see if it's cheaper to code it fully.*/
+ sb_partial_bits=sb_bits;
+ sb_partial_bits+=oc_block_run_bits(b_coded_count);
+ if(b_coded_count>0){
+ sb_partial_bits-=oc_block_run_bits(b_coded_count-1);
+ }
+ sb_bits=oc_fr_state_sb_cost(_fr,0,_b_coded);
+ sb_prefer_partial=sb_partial_bits<sb_bits;
+ sb_bits^=(sb_partial_bits^sb_bits)&-sb_prefer_partial;
+ }
+ /*There's no need to check the converse (whether it's cheaper to code
+ this SB partially if we were coding it fully), since the cost to
+ code a SB partially can only increase as we add more blocks, whereas
+ the cost to code it fully stays constant.*/
+ }
+ else{
+ /*If we get to the end and this SB is still full, then force it to be
+ coded full.
+ Otherwise we might not be able to extend the block run far enough
+ into the next partial SB.*/
+ if(sb_prefer_partial){
+ sb_prefer_partial=0;
+ sb_bits=oc_fr_state_sb_cost(_fr,0,_b_coded);
+ }
+ }
}
else{
- bits+=oc_block_run_bits(b_coded_count);
- /*It was partially coded.*/
- sb_partial=1;
- /*sb_full is unused.*/
+ /*This SB was full, but now must be made partial.*/
+ if(!sb_prefer_partial){
+ sb_bits=oc_block_run_bits(b_coded_count);
+ if(b_coded_count>b_count){
+ sb_bits-=oc_block_run_bits(b_coded_count-b_count);
+ }
+ sb_bits+=oc_fr_state_sb_cost(_fr,1,_b_coded);
+ }
+ b_count++;
+ b_coded_count=1;
+ sb_prefer_partial=1;
+ sb_bits+=2;
}
- _fr->bits=bits;
- _fr->b_coded_count=b_coded_count;
- _fr->b_coded_count_prev=b_coded_count;
- _fr->b_count=0;
- _fr->b_coded=_b_coded;
- _fr->b_coded_prev=_b_coded;
- oc_fr_state_advance_sb(_fr,sb_partial,sb_full);
}
else{
- bits+=oc_block_run_bits(b_coded_count);
- _fr->bits=bits;
- _fr->b_coded_count=b_coded_count;
- _fr->b_count=b_count;
- _fr->b_coded=_b_coded;
+ b_count++;
+ if(_fr->b_coded==_b_coded)sb_bits-=oc_block_run_bits(b_coded_count);
+ else b_coded_count=0;
+ sb_bits+=oc_block_run_bits(++b_coded_count);
}
+ _fr->bits=bits+sb_bits;
+ _fr->b_coded_count=b_coded_count;
+ _fr->b_coded=_b_coded;
+ _fr->b_count=b_count;
+ _fr->sb_prefer_partial=sb_prefer_partial;
+ _fr->sb_bits=sb_bits;
}
static void oc_fr_skip_block(oc_fr_state *_fr){
@@ -395,16 +452,6 @@ static int oc_fr_cost4(const oc_fr_state *_pre,const oc_fr_state *_post){
-struct oc_qii_state{
- ptrdiff_t bits;
- unsigned qi01_count:14;
- signed int qi01:2;
- unsigned qi12_count:14;
- signed int qi12:2;
-};
-
-
-
static void oc_qii_state_init(oc_qii_state *_qs){
_qs->bits=0;
_qs->qi01_count=0;
@@ -458,49 +505,17 @@ static void oc_qii_state_advance(oc_qii_state *_qd,
-/*Temporary encoder state for the analysis pipeline.*/
-struct oc_enc_pipeline_state{
- int bounding_values[256];
- oc_fr_state fr[3];
- oc_qii_state qs[3];
- /*Condensed dequantization tables.*/
- const ogg_uint16_t *dequant[3][3][2];
- /*Condensed quantization tables.*/
- const oc_iquant *enquant[3][3][2];
- /*Skip SSD storage for the current MCU in each plane.*/
- unsigned *skip_ssd[3];
- /*Coded/uncoded fragment lists for each plane for the current MCU.*/
- ptrdiff_t *coded_fragis[3];
- ptrdiff_t *uncoded_fragis[3];
- ptrdiff_t ncoded_fragis[3];
- ptrdiff_t nuncoded_fragis[3];
- /*The starting fragment for the current MCU in each plane.*/
- ptrdiff_t froffset[3];
- /*The starting row for the current MCU in each plane.*/
- int fragy0[3];
- /*The ending row for the current MCU in each plane.*/
- int fragy_end[3];
- /*The starting superblock for the current MCU in each plane.*/
- unsigned sbi0[3];
- /*The ending superblock for the current MCU in each plane.*/
- unsigned sbi_end[3];
- /*The number of tokens for zzi=1 for each color plane.*/
- int ndct_tokens1[3];
- /*The outstanding eob_run count for zzi=1 for each color plane.*/
- int eob_run1[3];
- /*Whether or not the loop filter is enabled.*/
- int loop_filter;
-};
-
-
static void oc_enc_pipeline_init(oc_enc_ctx *_enc,oc_enc_pipeline_state *_pipe){
ptrdiff_t *coded_fragis;
unsigned mcu_nvsbs;
ptrdiff_t mcu_nfrags;
+ int flimit;
int hdec;
int vdec;
int pli;
+ int nqis;
int qii;
+ int qi0;
int qti;
/*Initialize the per-plane coded block flag trackers.
These are used for bit-estimation purposes only; the real flag bits span
@@ -529,24 +544,36 @@ static void oc_enc_pipeline_init(oc_enc_ctx *_enc,oc_enc_pipeline_state *_pipe){
memset(_pipe->ncoded_fragis,0,sizeof(_pipe->ncoded_fragis));
memset(_pipe->nuncoded_fragis,0,sizeof(_pipe->nuncoded_fragis));
/*Set up condensed quantizer tables.*/
+ qi0=_enc->state.qis[0];
+ nqis=_enc->state.nqis;
for(pli=0;pli<3;pli++){
- for(qii=0;qii<_enc->state.nqis;qii++){
+ for(qii=0;qii<nqis;qii++){
int qi;
qi=_enc->state.qis[qii];
for(qti=0;qti<2;qti++){
- _pipe->dequant[pli][qii][qti]=_enc->state.dequant_tables[qi][pli][qti];
- _pipe->enquant[pli][qii][qti]=_enc->enquant_tables[qi][pli][qti];
+ /*Set the DC coefficient in the dequantization table.*/
+ _enc->state.dequant_tables[qi][pli][qti][0]=
+ _enc->dequant_dc[qi0][pli][qti];
+ _enc->dequant[pli][qii][qti]=_enc->state.dequant_tables[qi][pli][qti];
+ /*Copy over the quantization table.*/
+ memcpy(_enc->enquant[pli][qii][qti],_enc->enquant_tables[qi][pli][qti],
+ _enc->opt_data.enquant_table_size);
}
}
}
+ /*Fix up the DC coefficients in the quantization tables.*/
+ oc_enc_enquant_table_fixup(_enc,_enc->enquant,nqis);
/*Initialize the tokenization state.*/
for(pli=0;pli<3;pli++){
_pipe->ndct_tokens1[pli]=0;
_pipe->eob_run1[pli]=0;
}
/*Initialize the bounding value array for the loop filter.*/
- _pipe->loop_filter=!oc_state_loop_filter_init(&_enc->state,
- _pipe->bounding_values);
+ flimit=_enc->state.loop_filter_limits[_enc->state.qis[0]];
+ _pipe->loop_filter=flimit!=0;
+ if(flimit!=0)oc_loop_filter_init(&_enc->state,_pipe->bounding_values,flimit);
+ /*Clear the temporary DCT scratch space.*/
+ memset(_pipe->dct_data,0,sizeof(_pipe->dct_data));
}
/*Sets the current MCU stripe to super block row _sby.
@@ -585,13 +612,17 @@ static int oc_enc_pipeline_set_stripe(oc_enc_ctx *_enc,
static void oc_enc_pipeline_finish_mcu_plane(oc_enc_ctx *_enc,
oc_enc_pipeline_state *_pipe,int _pli,int _sdelay,int _edelay){
- int refi;
/*Copy over all the uncoded fragments from this plane and advance the uncoded
fragment list.*/
- _pipe->uncoded_fragis[_pli]-=_pipe->nuncoded_fragis[_pli];
- oc_state_frag_copy_list(&_enc->state,_pipe->uncoded_fragis[_pli],
- _pipe->nuncoded_fragis[_pli],OC_FRAME_SELF,OC_FRAME_PREV,_pli);
- _pipe->nuncoded_fragis[_pli]=0;
+ if(_pipe->nuncoded_fragis[_pli]>0){
+ _pipe->uncoded_fragis[_pli]-=_pipe->nuncoded_fragis[_pli];
+ oc_frag_copy_list(&_enc->state,
+ _enc->state.ref_frame_data[OC_FRAME_SELF],
+ _enc->state.ref_frame_data[OC_FRAME_PREV],
+ _enc->state.ref_ystride[_pli],_pipe->uncoded_fragis[_pli],
+ _pipe->nuncoded_fragis[_pli],_enc->state.frag_buf_offs);
+ _pipe->nuncoded_fragis[_pli]=0;
+ }
/*Perform DC prediction.*/
oc_enc_pred_dc_frag_rows(_enc,_pli,
_pipe->fragy0[_pli],_pipe->fragy_end[_pli]);
@@ -606,17 +637,18 @@ static void oc_enc_pipeline_finish_mcu_plane(oc_enc_ctx *_enc,
_pipe->coded_fragis[_pli]+=_pipe->ncoded_fragis[_pli];
_pipe->ncoded_fragis[_pli]=0;
/*Apply the loop filter if necessary.*/
- refi=_enc->state.ref_frame_idx[OC_FRAME_SELF];
if(_pipe->loop_filter){
- oc_state_loop_filter_frag_rows(&_enc->state,_pipe->bounding_values,
- refi,_pli,_pipe->fragy0[_pli]-_sdelay,_pipe->fragy_end[_pli]-_edelay);
+ oc_state_loop_filter_frag_rows(&_enc->state,
+ _pipe->bounding_values,OC_FRAME_SELF,_pli,
+ _pipe->fragy0[_pli]-_sdelay,_pipe->fragy_end[_pli]-_edelay);
}
else _sdelay=_edelay=0;
/*To fill borders, we have an additional two pixel delay, since a fragment
in the next row could filter its top edge, using two pixels from a
fragment in this row.
But there's no reason to delay a full fragment between the two.*/
- oc_state_borders_fill_rows(&_enc->state,refi,_pli,
+ oc_state_borders_fill_rows(&_enc->state,
+ _enc->state.ref_frame_idx[OC_FRAME_SELF],_pli,
(_pipe->fragy0[_pli]-_sdelay<<3)-(_sdelay<<1),
(_pipe->fragy_end[_pli]-_edelay<<3)-(_edelay<<1));
}
@@ -634,62 +666,62 @@ struct oc_rd_metric{
static int oc_enc_block_transform_quantize(oc_enc_ctx *_enc,
- oc_enc_pipeline_state *_pipe,int _pli,ptrdiff_t _fragi,int _overhead_bits,
- oc_rd_metric *_mo,oc_token_checkpoint **_stack){
- OC_ALIGN16(ogg_int16_t dct[64]);
- OC_ALIGN16(ogg_int16_t data[64]);
- ogg_uint16_t dc_dequant;
+ oc_enc_pipeline_state *_pipe,int _pli,ptrdiff_t _fragi,
+ unsigned _rd_scale,unsigned _rd_iscale,oc_rd_metric *_mo,
+ oc_fr_state *_fr,oc_token_checkpoint **_stack){
+ ogg_int16_t *data;
+ ogg_int16_t *dct;
+ ogg_int16_t *idct;
+ oc_qii_state qs;
const ogg_uint16_t *dequant;
- const oc_iquant *enquant;
+ ogg_uint16_t dequant_dc;
ptrdiff_t frag_offs;
int ystride;
const unsigned char *src;
const unsigned char *ref;
unsigned char *dst;
- int frame_type;
int nonzero;
unsigned uncoded_ssd;
unsigned coded_ssd;
- int coded_dc;
oc_token_checkpoint *checkpoint;
oc_fragment *frags;
int mb_mode;
+ int refi;
int mv_offs[2];
int nmv_offs;
int ac_bits;
int borderi;
+ int nqis;
int qti;
int qii;
- int pi;
- int zzi;
- int v;
- int val;
- int d;
- int s;
int dc;
+ nqis=_enc->state.nqis;
frags=_enc->state.frags;
frag_offs=_enc->state.frag_buf_offs[_fragi];
ystride=_enc->state.ref_ystride[_pli];
src=_enc->state.ref_frame_data[OC_FRAME_IO]+frag_offs;
borderi=frags[_fragi].borderi;
qii=frags[_fragi].qii;
+ data=_enc->pipe.dct_data;
+ dct=data+64;
+ idct=data+128;
if(qii&~3){
#if !defined(OC_COLLECT_METRICS)
if(_enc->sp_level>=OC_SP_LEVEL_EARLY_SKIP){
/*Enable early skip detection.*/
frags[_fragi].coded=0;
+ frags[_fragi].refi=OC_FRAME_NONE;
+ oc_fr_skip_block(_fr);
return 0;
}
#endif
/*Try and code this block anyway.*/
qii&=3;
- frags[_fragi].qii=qii;
}
+ refi=frags[_fragi].refi;
mb_mode=frags[_fragi].mb_mode;
- ref=_enc->state.ref_frame_data[
- _enc->state.ref_frame_idx[OC_FRAME_FOR_MODE(mb_mode)]]+frag_offs;
- dst=_enc->state.ref_frame_data[_enc->state.ref_frame_idx[OC_FRAME_SELF]]
- +frag_offs;
+ ref=_enc->state.ref_frame_data[refi]+frag_offs;
+ dst=_enc->state.ref_frame_data[OC_FRAME_SELF]+frag_offs;
/*Motion compensation:*/
switch(mb_mode){
case OC_MODE_INTRA:{
@@ -704,9 +736,9 @@ static int oc_enc_block_transform_quantize(oc_enc_ctx *_enc,
}break;
default:{
const oc_mv *frag_mvs;
- frag_mvs=(const oc_mv *)_enc->state.frag_mvs;
- nmv_offs=oc_state_get_mv_offsets(&_enc->state,mv_offs,_pli,
- frag_mvs[_fragi][0],frag_mvs[_fragi][1]);
+ frag_mvs=_enc->state.frag_mvs;
+ nmv_offs=oc_state_get_mv_offsets(&_enc->state,mv_offs,
+ _pli,frag_mvs[_fragi]);
if(nmv_offs>1){
oc_enc_frag_copy2(_enc,dst,
ref+mv_offs[0],ref+mv_offs[1],ystride);
@@ -717,126 +749,121 @@ static int oc_enc_block_transform_quantize(oc_enc_ctx *_enc,
}
#if defined(OC_COLLECT_METRICS)
{
+ unsigned sad;
unsigned satd;
switch(nmv_offs){
- case 0:satd=oc_enc_frag_intra_satd(_enc,src,ystride);break;
+ case 0:{
+ sad=oc_enc_frag_intra_sad(_enc,src,ystride);
+ satd=oc_enc_frag_intra_satd(_enc,&dc,src,ystride);
+ }break;
case 1:{
- satd=oc_enc_frag_satd_thresh(_enc,src,ref+mv_offs[0],ystride,UINT_MAX);
+ sad=oc_enc_frag_sad_thresh(_enc,src,ref+mv_offs[0],ystride,UINT_MAX);
+ satd=oc_enc_frag_satd(_enc,&dc,src,ref+mv_offs[0],ystride);
+ satd+=abs(dc);
}break;
default:{
- satd=oc_enc_frag_satd_thresh(_enc,src,dst,ystride,UINT_MAX);
- }
+ sad=oc_enc_frag_sad_thresh(_enc,src,dst,ystride,UINT_MAX);
+ satd=oc_enc_frag_satd(_enc,&dc,src,dst,ystride);
+ satd+=abs(dc);
+ }break;
}
+ _enc->frag_sad[_fragi]=sad;
_enc->frag_satd[_fragi]=satd;
}
#endif
/*Transform:*/
oc_enc_fdct8x8(_enc,dct,data);
- /*Quantize the DC coefficient:*/
+ /*Quantize:*/
qti=mb_mode!=OC_MODE_INTRA;
- enquant=_pipe->enquant[_pli][0][qti];
- dc_dequant=_pipe->dequant[_pli][0][qti][0];
- v=dct[0];
- val=v<<1;
- s=OC_SIGNMASK(val);
- val+=dc_dequant+s^s;
- val=((enquant[0].m*(ogg_int32_t)val>>16)+val>>enquant[0].l)-s;
- dc=OC_CLAMPI(-580,val,580);
- nonzero=0;
- /*Quantize the AC coefficients:*/
- dequant=_pipe->dequant[_pli][qii][qti];
- enquant=_pipe->enquant[_pli][qii][qti];
- for(zzi=1;zzi<64;zzi++){
- v=dct[OC_FZIG_ZAG[zzi]];
- d=dequant[zzi];
- val=v<<1;
- v=abs(val);
- if(v>=d){
- s=OC_SIGNMASK(val);
- /*The bias added here rounds ties away from zero, since token
- optimization can only decrease the magnitude of the quantized
- value.*/
- val+=d+s^s;
- /*Note the arithmetic right shift is not guaranteed by ANSI C.
- Hopefully no one still uses ones-complement architectures.*/
- val=((enquant[zzi].m*(ogg_int32_t)val>>16)+val>>enquant[zzi].l)-s;
- data[zzi]=OC_CLAMPI(-580,val,580);
- nonzero=zzi;
- }
- else data[zzi]=0;
- }
+ dequant=_enc->dequant[_pli][qii][qti];
+ nonzero=oc_enc_quantize(_enc,data,dct,dequant,_enc->enquant[_pli][qii][qti]);
+ dc=data[0];
/*Tokenize.*/
checkpoint=*_stack;
- ac_bits=oc_enc_tokenize_ac(_enc,_pli,_fragi,data,dequant,dct,nonzero+1,
- _stack,qti?0:3);
+ if(_enc->sp_level<OC_SP_LEVEL_FAST_ANALYSIS){
+ ac_bits=oc_enc_tokenize_ac(_enc,_pli,_fragi,idct,data,dequant,dct,
+ nonzero+1,_stack,OC_RD_ISCALE(_enc->lambda,_rd_iscale),qti?0:3);
+ }
+ else{
+ ac_bits=oc_enc_tokenize_ac_fast(_enc,_pli,_fragi,idct,data,dequant,dct,
+ nonzero+1,_stack,OC_RD_ISCALE(_enc->lambda,_rd_iscale),qti?0:3);
+ }
/*Reconstruct.
TODO: nonzero may need to be adjusted after tokenization.*/
+ dequant_dc=dequant[0];
if(nonzero==0){
ogg_int16_t p;
int ci;
+ int qi01;
+ int qi12;
/*We round this dequant product (and not any of the others) because there's
no iDCT rounding.*/
- p=(ogg_int16_t)(dc*(ogg_int32_t)dc_dequant+15>>5);
+ p=(ogg_int16_t)(dc*(ogg_int32_t)dequant_dc+15>>5);
/*LOOP VECTORIZES.*/
for(ci=0;ci<64;ci++)data[ci]=p;
+ /*We didn't code any AC coefficients, so don't change the quantizer.*/
+ qi01=_pipe->qs[_pli].qi01;
+ qi12=_pipe->qs[_pli].qi12;
+ if(qi01>0)qii=1+qi12;
+ else if(qi01>=0)qii=0;
}
else{
- data[0]=dc*dc_dequant;
- oc_idct8x8(&_enc->state,data,nonzero+1);
+ idct[0]=dc*dequant_dc;
+ /*Note: This clears idct[] back to zero for the next block.*/
+ oc_idct8x8(&_enc->state,data,idct,nonzero+1);
+ }
+ frags[_fragi].qii=qii;
+ if(nqis>1){
+ oc_qii_state_advance(&qs,_pipe->qs+_pli,qii);
+ ac_bits+=qs.bits-_pipe->qs[_pli].bits;
}
if(!qti)oc_enc_frag_recon_intra(_enc,dst,ystride,data);
else{
oc_enc_frag_recon_inter(_enc,dst,
nmv_offs==1?ref+mv_offs[0]:dst,ystride,data);
}
- frame_type=_enc->state.frame_type;
+ /*If _fr is NULL, then this is an INTRA frame, and we can't skip blocks.*/
#if !defined(OC_COLLECT_METRICS)
- if(frame_type!=OC_INTRA_FRAME)
+ if(_fr!=NULL)
#endif
{
/*In retrospect, should we have skipped this block?*/
- oc_enc_frag_sub(_enc,data,src,dst,ystride);
- coded_ssd=coded_dc=0;
if(borderi<0){
- for(pi=0;pi<64;pi++){
- coded_ssd+=data[pi]*data[pi];
- coded_dc+=data[pi];
- }
+ coded_ssd=oc_enc_frag_ssd(_enc,src,dst,ystride);
}
else{
- ogg_int64_t mask;
- mask=_enc->state.borders[borderi].mask;
- for(pi=0;pi<64;pi++,mask>>=1)if(mask&1){
- coded_ssd+=data[pi]*data[pi];
- coded_dc+=data[pi];
- }
+ coded_ssd=oc_enc_frag_border_ssd(_enc,src,dst,ystride,
+ _enc->state.borders[borderi].mask);
}
/*Scale to match DCT domain.*/
coded_ssd<<=4;
- /*We actually only want the AC contribution to the SSD.*/
- coded_ssd-=coded_dc*coded_dc>>2;
#if defined(OC_COLLECT_METRICS)
_enc->frag_ssd[_fragi]=coded_ssd;
}
- if(frame_type!=OC_INTRA_FRAME){
+ if(_fr!=NULL){
#endif
+ coded_ssd=OC_RD_SCALE(coded_ssd,_rd_scale);
uncoded_ssd=_pipe->skip_ssd[_pli][_fragi-_pipe->froffset[_pli]];
- if(uncoded_ssd<UINT_MAX){
+ if(uncoded_ssd<UINT_MAX&&
+ /*Don't allow luma blocks to be skipped in 4MV mode when VP3 compatibility
+ is enabled.*/
+ (!_enc->vp3_compatible||mb_mode!=OC_MODE_INTER_MV_FOUR||_pli)){
+ int overhead_bits;
+ overhead_bits=oc_fr_cost1(_fr);
/*Although the fragment coding overhead determination is accurate, it is
greedy, using very coarse-grained local information.
Allowing it to mildly discourage coding turns out to be beneficial, but
it's not clear that allowing it to encourage coding through negative
coding overhead deltas is useful.
- For that reason, we disallow negative coding_overheads.*/
- if(_overhead_bits<0)_overhead_bits=0;
- if(uncoded_ssd<=coded_ssd+(_overhead_bits+ac_bits)*_enc->lambda&&
- /*Don't allow luma blocks to be skipped in 4MV mode when VP3
- compatibility is enabled.*/
- (!_enc->vp3_compatible||mb_mode!=OC_MODE_INTER_MV_FOUR||_pli)){
+ For that reason, we disallow negative coding overheads.*/
+ if(overhead_bits<0)overhead_bits=0;
+ if(uncoded_ssd<=coded_ssd+(overhead_bits+ac_bits)*_enc->lambda){
/*Hm, not worth it; roll back.*/
oc_enc_tokenlog_rollback(_enc,checkpoint,(*_stack)-checkpoint);
*_stack=checkpoint;
frags[_fragi].coded=0;
+ frags[_fragi].refi=OC_FRAME_NONE;
+ oc_fr_skip_block(_fr);
return 0;
}
}
@@ -844,15 +871,20 @@ static int oc_enc_block_transform_quantize(oc_enc_ctx *_enc,
_mo->uncoded_ac_ssd+=uncoded_ssd;
_mo->coded_ac_ssd+=coded_ssd;
_mo->ac_bits+=ac_bits;
+ oc_fr_code_block(_fr);
}
- oc_qii_state_advance(_pipe->qs+_pli,_pipe->qs+_pli,qii);
+ /*GCC 4.4.4 generates a warning here because it can't tell that
+ the init code in the nqis check above will run anytime this
+ line runs.*/
+ if(nqis>1)*(_pipe->qs+_pli)=*&qs;
frags[_fragi].dc=dc;
frags[_fragi].coded=1;
return 1;
}
-static int oc_enc_mb_transform_quantize_luma(oc_enc_ctx *_enc,
- oc_enc_pipeline_state *_pipe,unsigned _mbi,int _mode_overhead){
+static int oc_enc_mb_transform_quantize_inter_luma(oc_enc_ctx *_enc,
+ oc_enc_pipeline_state *_pipe,unsigned _mbi,int _mode_overhead,
+ const unsigned _rd_scale[4],const unsigned _rd_iscale[4]){
/*Worst case token stack usage for 4 fragments.*/
oc_token_checkpoint stack[64*4];
oc_token_checkpoint *stackptr;
@@ -867,6 +899,7 @@ static int oc_enc_mb_transform_quantize_luma(oc_enc_ctx *_enc,
oc_fr_state fr_checkpoint;
oc_qii_state qs_checkpoint;
int mb_mode;
+ int refi;
int ncoded;
ptrdiff_t fragi;
int bi;
@@ -880,78 +913,83 @@ static int oc_enc_mb_transform_quantize_luma(oc_enc_ctx *_enc,
uncoded_fragis=_pipe->uncoded_fragis[0];
nuncoded_fragis=_pipe->nuncoded_fragis[0];
mb_mode=mb_modes[_mbi];
+ refi=OC_FRAME_FOR_MODE(mb_mode);
ncoded=0;
stackptr=stack;
memset(&mo,0,sizeof(mo));
for(bi=0;bi<4;bi++){
fragi=sb_maps[_mbi>>2][_mbi&3][bi];
+ frags[fragi].refi=refi;
frags[fragi].mb_mode=mb_mode;
- if(oc_enc_block_transform_quantize(_enc,
- _pipe,0,fragi,oc_fr_cost1(_pipe->fr+0),&mo,&stackptr)){
- oc_fr_code_block(_pipe->fr+0);
+ if(oc_enc_block_transform_quantize(_enc,_pipe,0,fragi,
+ _rd_scale[bi],_rd_iscale[bi],&mo,_pipe->fr+0,&stackptr)){
coded_fragis[ncoded_fragis++]=fragi;
ncoded++;
}
- else{
- *(uncoded_fragis-++nuncoded_fragis)=fragi;
- oc_fr_skip_block(_pipe->fr+0);
- }
+ else *(uncoded_fragis-++nuncoded_fragis)=fragi;
}
- if(_enc->state.frame_type!=OC_INTRA_FRAME){
- if(ncoded>0&&!mo.dc_flag){
- int cost;
- /*Some individual blocks were worth coding.
- See if that's still true when accounting for mode and MV overhead.*/
- cost=mo.coded_ac_ssd+_enc->lambda*(mo.ac_bits
- +oc_fr_cost4(&fr_checkpoint,_pipe->fr+0)+_mode_overhead);
- if(mo.uncoded_ac_ssd<=cost){
- /*Taking macroblock overhead into account, it is not worth coding this
- MB.*/
- oc_enc_tokenlog_rollback(_enc,stack,stackptr-stack);
- *(_pipe->fr+0)=*&fr_checkpoint;
- *(_pipe->qs+0)=*&qs_checkpoint;
- for(bi=0;bi<4;bi++){
- fragi=sb_maps[_mbi>>2][_mbi&3][bi];
- if(frags[fragi].coded){
- *(uncoded_fragis-++nuncoded_fragis)=fragi;
- frags[fragi].coded=0;
- }
- oc_fr_skip_block(_pipe->fr+0);
+ if(ncoded>0&&!mo.dc_flag){
+ int cost;
+ /*Some individual blocks were worth coding.
+ See if that's still true when accounting for mode and MV overhead.*/
+ cost=mo.coded_ac_ssd+_enc->lambda*(mo.ac_bits
+ +oc_fr_cost4(&fr_checkpoint,_pipe->fr+0)+_mode_overhead);
+ if(mo.uncoded_ac_ssd<=cost){
+ /*Taking macroblock overhead into account, it is not worth coding this
+ MB.*/
+ oc_enc_tokenlog_rollback(_enc,stack,stackptr-stack);
+ *(_pipe->fr+0)=*&fr_checkpoint;
+ *(_pipe->qs+0)=*&qs_checkpoint;
+ for(bi=0;bi<4;bi++){
+ fragi=sb_maps[_mbi>>2][_mbi&3][bi];
+ if(frags[fragi].coded){
+ *(uncoded_fragis-++nuncoded_fragis)=fragi;
+ frags[fragi].coded=0;
+ frags[fragi].refi=OC_FRAME_NONE;
}
- ncoded_fragis-=ncoded;
- ncoded=0;
+ oc_fr_skip_block(_pipe->fr+0);
}
- }
- /*If no luma blocks coded, the mode is forced.*/
- if(ncoded==0)mb_modes[_mbi]=OC_MODE_INTER_NOMV;
- /*Assume that a 1MV with a single coded block is always cheaper than a 4MV
- with a single coded block.
- This may not be strictly true: a 4MV computes chroma MVs using (0,0) for
- skipped blocks, while a 1MV does not.*/
- else if(ncoded==1&&mb_mode==OC_MODE_INTER_MV_FOUR){
- mb_modes[_mbi]=OC_MODE_INTER_MV;
+ ncoded_fragis-=ncoded;
+ ncoded=0;
}
}
+ /*If no luma blocks coded, the mode is forced.*/
+ if(ncoded==0)mb_modes[_mbi]=OC_MODE_INTER_NOMV;
+ /*Assume that a 1MV with a single coded block is always cheaper than a 4MV
+ with a single coded block.
+ This may not be strictly true: a 4MV computes chroma MVs using (0,0) for
+ skipped blocks, while a 1MV does not.*/
+ else if(ncoded==1&&mb_mode==OC_MODE_INTER_MV_FOUR){
+ mb_modes[_mbi]=OC_MODE_INTER_MV;
+ }
_pipe->ncoded_fragis[0]=ncoded_fragis;
_pipe->nuncoded_fragis[0]=nuncoded_fragis;
return ncoded;
}
-static void oc_enc_sb_transform_quantize_chroma(oc_enc_ctx *_enc,
+static void oc_enc_sb_transform_quantize_inter_chroma(oc_enc_ctx *_enc,
oc_enc_pipeline_state *_pipe,int _pli,int _sbi_start,int _sbi_end){
- const oc_sb_map *sb_maps;
- oc_sb_flags *sb_flags;
- ptrdiff_t *coded_fragis;
- ptrdiff_t ncoded_fragis;
- ptrdiff_t *uncoded_fragis;
- ptrdiff_t nuncoded_fragis;
- int sbi;
+ const ogg_uint16_t *mcu_rd_scale;
+ const ogg_uint16_t *mcu_rd_iscale;
+ const oc_sb_map *sb_maps;
+ oc_sb_flags *sb_flags;
+ oc_fr_state *fr;
+ ptrdiff_t *coded_fragis;
+ ptrdiff_t ncoded_fragis;
+ ptrdiff_t *uncoded_fragis;
+ ptrdiff_t nuncoded_fragis;
+ ptrdiff_t froffset;
+ int sbi;
+ fr=_pipe->fr+_pli;
+ mcu_rd_scale=(const ogg_uint16_t *)_enc->mcu_rd_scale;
+ mcu_rd_iscale=(const ogg_uint16_t *)_enc->mcu_rd_iscale;
sb_maps=(const oc_sb_map *)_enc->state.sb_maps;
sb_flags=_enc->state.sb_flags;
coded_fragis=_pipe->coded_fragis[_pli];
ncoded_fragis=_pipe->ncoded_fragis[_pli];
uncoded_fragis=_pipe->uncoded_fragis[_pli];
nuncoded_fragis=_pipe->nuncoded_fragis[_pli];
+ froffset=_pipe->froffset[_pli];
for(sbi=_sbi_start;sbi<_sbi_end;sbi++){
/*Worst case token stack usage for 1 fragment.*/
oc_token_checkpoint stack[64];
@@ -964,21 +1002,21 @@ static void oc_enc_sb_transform_quantize_chroma(oc_enc_ctx *_enc,
fragi=sb_maps[sbi][quadi][bi];
if(fragi>=0){
oc_token_checkpoint *stackptr;
+ unsigned rd_scale;
+ unsigned rd_iscale;
+ rd_scale=mcu_rd_scale[fragi-froffset];
+ rd_iscale=mcu_rd_iscale[fragi-froffset];
stackptr=stack;
- if(oc_enc_block_transform_quantize(_enc,
- _pipe,_pli,fragi,oc_fr_cost1(_pipe->fr+_pli),&mo,&stackptr)){
+ if(oc_enc_block_transform_quantize(_enc,_pipe,_pli,fragi,
+ rd_scale,rd_iscale,&mo,fr,&stackptr)){
coded_fragis[ncoded_fragis++]=fragi;
- oc_fr_code_block(_pipe->fr+_pli);
- }
- else{
- *(uncoded_fragis-++nuncoded_fragis)=fragi;
- oc_fr_skip_block(_pipe->fr+_pli);
}
+ else *(uncoded_fragis-++nuncoded_fragis)=fragi;
}
}
- oc_fr_state_flush_sb(_pipe->fr+_pli);
- sb_flags[sbi].coded_fully=_pipe->fr[_pli].sb_full;
- sb_flags[sbi].coded_partially=_pipe->fr[_pli].sb_partial;
+ oc_fr_state_flush_sb(fr);
+ sb_flags[sbi].coded_fully=fr->sb_full;
+ sb_flags[sbi].coded_partially=fr->sb_partial;
}
_pipe->ncoded_fragis[_pli]=ncoded_fragis;
_pipe->nuncoded_fragis[_pli]=nuncoded_fragis;
@@ -1006,8 +1044,8 @@ static void oc_enc_sb_transform_quantize_chroma(oc_enc_ctx *_enc,
The bit counts and SSD measurements are obtained by examining actual encoded
frames, with appropriate lambda values and optimal Huffman codes selected.
EOB bits are assigned to the fragment that started the EOB run (as opposed to
- dividing them among all the blocks in the run; though the latter approach
- seems more theoretically correct, Monty's testing showed a small improvement
+ dividing them among all the blocks in the run; the latter approach seems
+ more theoretically correct, but Monty's testing showed a small improvement
with the former, though that may have been merely statistical noise).
@ARTICLE{Kim03,
@@ -1028,11 +1066,63 @@ static void oc_enc_sb_transform_quantize_chroma(oc_enc_ctx *_enc,
+(((_ssd)&(1<<OC_BIT_SCALE)-1)+((_rate)&(1<<OC_BIT_SCALE)-1)*(_lambda) \
+((1<<OC_BIT_SCALE)>>1)>>OC_BIT_SCALE)
+static void oc_enc_mode_rd_init(oc_enc_ctx *_enc){
+#if !defined(OC_COLLECT_METRICS)
+ const
+#endif
+ oc_mode_rd (*oc_mode_rd_table)[3][2][OC_COMP_BINS]=
+ _enc->sp_level<OC_SP_LEVEL_NOSATD?OC_MODE_RD_SATD:OC_MODE_RD_SAD;
+ int qii;
+#if defined(OC_COLLECT_METRICS)
+ oc_enc_mode_metrics_load(_enc);
+#endif
+ for(qii=0;qii<_enc->state.nqis;qii++){
+ int qi;
+ int pli;
+ qi=_enc->state.qis[qii];
+ for(pli=0;pli<3;pli++){
+ int qti;
+ for(qti=0;qti<2;qti++){
+ int log_plq;
+ int modeline;
+ int bin;
+ int dx;
+ int dq;
+ log_plq=_enc->log_plq[qi][pli][qti];
+ /*Find the pair of rows in the mode table that bracket this quantizer.
+ If it falls outside the range the table covers, then we just use a
+ pair on the edge for linear extrapolation.*/
+ for(modeline=0;modeline<OC_LOGQ_BINS-1&&
+ OC_MODE_LOGQ[modeline+1][pli][qti]>log_plq;modeline++);
+ /*Interpolate a row for this quantizer.*/
+ dx=OC_MODE_LOGQ[modeline][pli][qti]-log_plq;
+ dq=OC_MODE_LOGQ[modeline][pli][qti]-OC_MODE_LOGQ[modeline+1][pli][qti];
+ if(dq==0)dq=1;
+ for(bin=0;bin<OC_COMP_BINS;bin++){
+ int y0;
+ int z0;
+ int dy;
+ int dz;
+ y0=oc_mode_rd_table[modeline][pli][qti][bin].rate;
+ z0=oc_mode_rd_table[modeline][pli][qti][bin].rmse;
+ dy=oc_mode_rd_table[modeline+1][pli][qti][bin].rate-y0;
+ dz=oc_mode_rd_table[modeline+1][pli][qti][bin].rmse-z0;
+ _enc->mode_rd[qii][pli][qti][bin].rate=
+ (ogg_int16_t)OC_CLAMPI(-32768,y0+(dy*dx+(dq>>1))/dq,32767);
+ _enc->mode_rd[qii][pli][qti][bin].rmse=
+ (ogg_int16_t)OC_CLAMPI(-32768,z0+(dz*dx+(dq>>1))/dq,32767);
+ }
+ }
+ }
+ }
+}
+
/*Estimate the R-D cost of the DCT coefficients given the SATD of a block after
prediction.*/
-static unsigned oc_dct_cost2(unsigned *_ssd,
- int _qi,int _pli,int _qti,int _satd){
+static unsigned oc_dct_cost2(oc_enc_ctx *_enc,unsigned *_ssd,
+ int _qii,int _pli,int _qti,int _satd){
unsigned rmse;
+ int shift;
int bin;
int dx;
int y0;
@@ -1042,20 +1132,279 @@ static unsigned oc_dct_cost2(unsigned *_ssd,
/*SATD metrics for chroma planes vary much less than luma, so we scale them
by 4 to distribute them into the mode decision bins more evenly.*/
_satd<<=_pli+1&2;
- bin=OC_MINI(_satd>>OC_SAD_SHIFT,OC_SAD_BINS-2);
- dx=_satd-(bin<<OC_SAD_SHIFT);
- y0=OC_MODE_RD[_qi][_pli][_qti][bin].rate;
- z0=OC_MODE_RD[_qi][_pli][_qti][bin].rmse;
- dy=OC_MODE_RD[_qi][_pli][_qti][bin+1].rate-y0;
- dz=OC_MODE_RD[_qi][_pli][_qti][bin+1].rmse-z0;
- rmse=OC_MAXI(z0+(dz*dx>>OC_SAD_SHIFT),0);
+ shift=_enc->sp_level<OC_SP_LEVEL_NOSATD?OC_SATD_SHIFT:OC_SAD_SHIFT;
+ bin=OC_MINI(_satd>>shift,OC_COMP_BINS-2);
+ dx=_satd-(bin<<shift);
+ y0=_enc->mode_rd[_qii][_pli][_qti][bin].rate;
+ z0=_enc->mode_rd[_qii][_pli][_qti][bin].rmse;
+ dy=_enc->mode_rd[_qii][_pli][_qti][bin+1].rate-y0;
+ dz=_enc->mode_rd[_qii][_pli][_qti][bin+1].rmse-z0;
+ rmse=OC_MAXI(z0+(dz*dx>>shift),0);
*_ssd=rmse*rmse>>2*OC_RMSE_SCALE-OC_BIT_SCALE;
- return OC_MAXI(y0+(dy*dx>>OC_SAD_SHIFT),0);
+ return OC_MAXI(y0+(dy*dx>>shift),0);
+}
+
+/*activity_avg must be positive, or flat regions could get a zero weight, which
+ confounds analysis.
+ We set the minimum to this value so that it also avoids the need for divide
+ by zero checks in oc_mb_masking().*/
+# define OC_ACTIVITY_AVG_MIN (1<<OC_RD_SCALE_BITS)
+
+static unsigned oc_mb_activity(oc_enc_ctx *_enc,unsigned _mbi,
+ unsigned _activity[4]){
+ const unsigned char *src;
+ const ptrdiff_t *frag_buf_offs;
+ const ptrdiff_t *sb_map;
+ unsigned luma;
+ int ystride;
+ ptrdiff_t frag_offs;
+ ptrdiff_t fragi;
+ int bi;
+ frag_buf_offs=_enc->state.frag_buf_offs;
+ sb_map=_enc->state.sb_maps[_mbi>>2][_mbi&3];
+ src=_enc->state.ref_frame_data[OC_FRAME_IO];
+ ystride=_enc->state.ref_ystride[0];
+ luma=0;
+ for(bi=0;bi<4;bi++){
+ const unsigned char *s;
+ unsigned x;
+ unsigned x2;
+ unsigned act;
+ int i;
+ int j;
+ fragi=sb_map[bi];
+ frag_offs=frag_buf_offs[fragi];
+ /*TODO: This could be replaced with SATD^2, since we already have to
+ compute SATD.*/
+ x=x2=0;
+ s=src+frag_offs;
+ for(i=0;i<8;i++){
+ for(j=0;j<8;j++){
+ unsigned c;
+ c=s[j];
+ x+=c;
+ x2+=c*c;
+ }
+ s+=ystride;
+ }
+ luma+=x;
+ act=(x2<<6)-x*x;
+ if(act<8<<12){
+ /*The region is flat.*/
+ act=OC_MINI(act,5<<12);
+ }
+ else{
+ unsigned e1;
+ unsigned e2;
+ unsigned e3;
+ unsigned e4;
+ /*Test for an edge.
+ TODO: There are probably much simpler ways to do this (e.g., it could
+ probably be combined with the SATD calculation).
+ Alternatively, we could split the block around the mean and compute the
+ reduction in variance in each half.
+ For a Gaussian source the reduction should be
+ (1-2/pi) ~= 0.36338022763241865692446494650994.
+ Significantly more reduction is a good indication of a bi-level image.
+ This has the advantage of identifying, in addition to straight edges,
+ small text regions, which would otherwise be classified as "texture".*/
+ e1=e2=e3=e4=0;
+ s=src+frag_offs-1;
+ for(i=0;i<8;i++){
+ for(j=0;j<8;j++){
+ e1+=abs((s[j+2]-s[j]<<1)+(s-ystride)[j+2]-(s-ystride)[j]
+ +(s+ystride)[j+2]-(s+ystride)[j]);
+ e2+=abs(((s+ystride)[j+1]-(s-ystride)[j+1]<<1)
+ +(s+ystride)[j]-(s-ystride)[j]+(s+ystride)[j+2]-(s-ystride)[j+2]);
+ e3+=abs(((s+ystride)[j+2]-(s-ystride)[j]<<1)
+ +(s+ystride)[j+1]-s[j]+s[j+2]-(s-ystride)[j+1]);
+ e4+=abs(((s+ystride)[j]-(s-ystride)[j+2]<<1)
+ +(s+ystride)[j+1]-s[j+2]+s[j]-(s-ystride)[j+1]);
+ }
+ s+=ystride;
+ }
+ /*If the largest component of the edge energy is at least 40% of the
+ total, then classify the block as an edge block.*/
+ if(5*OC_MAXI(OC_MAXI(e1,e2),OC_MAXI(e3,e4))>2*(e1+e2+e3+e4)){
+ /*act=act_th*(act/act_th)**0.7
+ =exp(log(act_th)+0.7*(log(act)-log(act_th))).
+ Here act_th=5.0 and 0x394A=oc_blog32_q10(5<<12).*/
+ act=oc_bexp32_q10(0x394A+(7*(oc_blog32_q10(act)-0x394A+5)/10));
+ }
+ }
+ _activity[bi]=act;
+ }
+ return luma;
+}
+
+static void oc_mb_activity_fast(oc_enc_ctx *_enc,unsigned _mbi,
+ unsigned _activity[4],const unsigned _intra_satd[12]){
+ int bi;
+ for(bi=0;bi<4;bi++){
+ unsigned act;
+ act=(11*_intra_satd[bi]>>8)*_intra_satd[bi];
+ if(act<8<<12){
+ /*The region is flat.*/
+ act=OC_MINI(act,5<<12);
+ }
+ _activity[bi]=act;
+ }
+}
+
+/*Compute the masking scales for the blocks in a macro block.
+ All masking is computed from the luma blocks.
+ We derive scaling factors for the chroma blocks from these, and use the same
+ ones for all chroma blocks, regardless of the subsampling.
+ It's possible for luma to be perfectly flat and yet have high chroma energy,
+ but this is unlikely in non-artificial images, and not a case that has been
+ addressed by any research to my knowledge.
+ The output of the masking process is two scale factors, which are fed into
+ the various R-D optimizations.
+ The first, rd_scale, is applied to D in the equation
+ D*rd_scale+lambda*R.
+ This is the form that must be used to properly combine scores from multiple
+ blocks, and can be interpreted as scaling distortions by their visibility.
+ The inverse, rd_iscale, is applied to lambda in the equation
+ D+rd_iscale*lambda*R.
+ This is equivalent to the first form within a single block, but much faster
+ to use when evaluating many possible distortions (e.g., during actual
+ quantization, where separate distortions are evaluated for every
+ coefficient).
+ The two macros OC_RD_SCALE(rd_scale,d) and OC_RD_ISCALE(rd_iscale,lambda) are
+ used to perform the multiplications with the proper re-scaling for the range
+ of the scaling factors.
+ Many researchers apply masking values directly to the quantizers used, and
+ not to the R-D cost.
+ Since we generally use MSE for D, rd_scale must use the square of their
+ values to generate an equivalent effect.*/
+static unsigned oc_mb_masking(unsigned _rd_scale[5],unsigned _rd_iscale[5],
+ const ogg_uint16_t _chroma_rd_scale[2],const unsigned _activity[4],
+ unsigned _activity_avg,unsigned _luma,unsigned _luma_avg){
+ unsigned activity_sum;
+ unsigned la;
+ unsigned lb;
+ unsigned d;
+ int bi;
+ int bi_min;
+ int bi_min2;
+ /*The ratio lb/la is meant to approximate
+ ((((_luma-16)/219)*(255/128))**0.649**0.4**2), which is the
+ effective luminance masking from~\cite{LKW06} (including the self-masking
+ deflator).
+ The following actually turns out to be a pretty good approximation for
+ _luma>75 or so.
+ For smaller values luminance does not really follow Weber's Law anyway, and
+ this approximation gives a much less aggressive bitrate boost in this
+ region.
+ Though some researchers claim that contrast sensitivity actually decreases
+ for very low luminance values, in my experience excessive brightness on
+ LCDs or buggy color conversions (e.g., treating Y' as full-range instead
+ of the CCIR 601 range) make artifacts in such regions extremely visible.
+ We substitute _luma_avg for 128 to allow the strength of the masking to
+ vary with the actual average image luminance, within certain limits (the
+ caller has clamped _luma_avg to the range [90,160], inclusive).
+ @ARTICLE{LKW06,
+ author="Zhen Liu and Lina J. Karam and Andrew B. Watson",
+ title="{JPEG2000} Encoding With Perceptual Distortion Control",
+ journal="{IEEE} Transactions on Image Processing",
+ volume=15,
+ number=7,
+ pages="1763--1778",
+ month=Jul,
+ year=2006
+ }*/
+#if 0
+ la=_luma+4*_luma_avg;
+ lb=4*_luma+_luma_avg;
+#else
+ /*Disable luminance masking.*/
+ la=lb=1;
+#endif
+ activity_sum=0;
+ for(bi=0;bi<4;bi++){
+ unsigned a;
+ unsigned b;
+ activity_sum+=_activity[bi];
+ /*Apply activity masking.*/
+ a=_activity[bi]+4*_activity_avg;
+ b=4*_activity[bi]+_activity_avg;
+ d=OC_RD_SCALE(b,1);
+ /*And luminance masking.*/
+ d=(a+(d>>1))/d;
+ _rd_scale[bi]=(d*la+(lb>>1))/lb;
+ /*And now the inverse.*/
+ d=OC_MAXI(OC_RD_ISCALE(a,1),1);
+ d=(b+(d>>1))/d;
+ _rd_iscale[bi]=(d*lb+(la>>1))/la;
+ }
+ /*Now compute scaling factors for chroma blocks.
+ We start by finding the two smallest iscales from the luma blocks.*/
+ bi_min=_rd_iscale[1]<_rd_iscale[0];
+ bi_min2=1-bi_min;
+ for(bi=2;bi<4;bi++){
+ if(_rd_iscale[bi]<_rd_iscale[bi_min]){
+ bi_min2=bi_min;
+ bi_min=bi;
+ }
+ else if(_rd_iscale[bi]<_rd_iscale[bi_min2])bi_min2=bi;
+ }
+ /*If the minimum iscale is less than 1.0, use the second smallest instead,
+ and force the value to at least 1.0 (inflating chroma is a waste).*/
+ if(_rd_iscale[bi_min]<(1<<OC_RD_ISCALE_BITS))bi_min=bi_min2;
+ d=OC_MINI(_rd_scale[bi_min],1<<OC_RD_SCALE_BITS);
+ _rd_scale[4]=OC_RD_SCALE(d,_chroma_rd_scale[0]);
+ d=OC_MAXI(_rd_iscale[bi_min],1<<OC_RD_ISCALE_BITS);
+ _rd_iscale[4]=OC_RD_ISCALE(d,_chroma_rd_scale[1]);
+ return activity_sum;
+}
+
+static int oc_mb_intra_satd(oc_enc_ctx *_enc,unsigned _mbi,
+ unsigned _frag_satd[12]){
+ const unsigned char *src;
+ const ptrdiff_t *frag_buf_offs;
+ const ptrdiff_t *sb_map;
+ const oc_mb_map_plane *mb_map;
+ const unsigned char *map_idxs;
+ int map_nidxs;
+ int mapii;
+ int mapi;
+ int ystride;
+ int pli;
+ int bi;
+ ptrdiff_t fragi;
+ ptrdiff_t frag_offs;
+ unsigned luma;
+ int dc;
+ frag_buf_offs=_enc->state.frag_buf_offs;
+ sb_map=_enc->state.sb_maps[_mbi>>2][_mbi&3];
+ src=_enc->state.ref_frame_data[OC_FRAME_IO];
+ ystride=_enc->state.ref_ystride[0];
+ luma=0;
+ for(bi=0;bi<4;bi++){
+ fragi=sb_map[bi];
+ frag_offs=frag_buf_offs[fragi];
+ _frag_satd[bi]=oc_enc_frag_intra_satd(_enc,&dc,src+frag_offs,ystride);
+ luma+=dc;
+ }
+ mb_map=(const oc_mb_map_plane *)_enc->state.mb_maps[_mbi];
+ map_idxs=OC_MB_MAP_IDXS[_enc->state.info.pixel_fmt];
+ map_nidxs=OC_MB_MAP_NIDXS[_enc->state.info.pixel_fmt];
+ /*Note: This assumes ref_ystride[1]==ref_ystride[2].*/
+ ystride=_enc->state.ref_ystride[1];
+ for(mapii=4;mapii<map_nidxs;mapii++){
+ mapi=map_idxs[mapii];
+ pli=mapi>>2;
+ bi=mapi&3;
+ fragi=mb_map[pli][bi];
+ frag_offs=frag_buf_offs[fragi];
+ _frag_satd[mapii]=oc_enc_frag_intra_satd(_enc,&dc,src+frag_offs,ystride);
+ }
+ return luma;
}
/*Select luma block-level quantizers for a MB in an INTRA frame.*/
static unsigned oc_analyze_intra_mb_luma(oc_enc_ctx *_enc,
- const oc_qii_state *_qs,unsigned _mbi){
+ const oc_qii_state *_qs,unsigned _mbi,const unsigned _rd_scale[4]){
const unsigned char *src;
const ptrdiff_t *frag_buf_offs;
const oc_sb_map *sb_maps;
@@ -1068,6 +1417,7 @@ static unsigned oc_analyze_intra_mb_luma(oc_enc_ctx *_enc,
unsigned rate[4][3];
int prev[3][3];
unsigned satd;
+ int dc;
unsigned best_cost;
unsigned best_ssd;
unsigned best_rate;
@@ -1083,19 +1433,30 @@ static unsigned oc_analyze_intra_mb_luma(oc_enc_ctx *_enc,
ystride=_enc->state.ref_ystride[0];
fragi=sb_maps[_mbi>>2][_mbi&3][0];
frag_offs=frag_buf_offs[fragi];
- satd=oc_enc_frag_intra_satd(_enc,src+frag_offs,ystride);
+ if(_enc->sp_level<OC_SP_LEVEL_NOSATD){
+ satd=oc_enc_frag_intra_satd(_enc,&dc,src+frag_offs,ystride);
+ }
+ else{
+ satd=oc_enc_frag_intra_sad(_enc,src+frag_offs,ystride);
+ }
nqis=_enc->state.nqis;
lambda=_enc->lambda;
for(qii=0;qii<nqis;qii++){
oc_qii_state_advance(qs[0]+qii,_qs,qii);
- rate[0][qii]=oc_dct_cost2(ssd[0]+qii,_enc->state.qis[qii],0,0,satd)
+ rate[0][qii]=oc_dct_cost2(_enc,ssd[0]+qii,qii,0,0,satd)
+(qs[0][qii].bits-_qs->bits<<OC_BIT_SCALE);
+ ssd[0][qii]=OC_RD_SCALE(ssd[0][qii],_rd_scale[0]);
cost[0][qii]=OC_MODE_RD_COST(ssd[0][qii],rate[0][qii],lambda);
}
for(bi=1;bi<4;bi++){
fragi=sb_maps[_mbi>>2][_mbi&3][bi];
frag_offs=frag_buf_offs[fragi];
- satd=oc_enc_frag_intra_satd(_enc,src+frag_offs,ystride);
+ if(_enc->sp_level<OC_SP_LEVEL_NOSATD){
+ satd=oc_enc_frag_intra_satd(_enc,&dc,src+frag_offs,ystride);
+ }
+ else{
+ satd=oc_enc_frag_intra_sad(_enc,src+frag_offs,ystride);
+ }
for(qii=0;qii<nqis;qii++){
oc_qii_state qt[3];
unsigned cur_ssd;
@@ -1103,7 +1464,8 @@ static unsigned oc_analyze_intra_mb_luma(oc_enc_ctx *_enc,
int best_qij;
int qij;
oc_qii_state_advance(qt+0,qs[bi-1]+0,qii);
- cur_rate=oc_dct_cost2(&cur_ssd,_enc->state.qis[qii],0,0,satd);
+ cur_rate=oc_dct_cost2(_enc,&cur_ssd,qii,0,0,satd);
+ cur_ssd=OC_RD_SCALE(cur_ssd,_rd_scale[bi]);
best_ssd=ssd[bi-1][0]+cur_ssd;
best_rate=rate[bi-1][0]+cur_rate
+(qt[0].bits-qs[bi-1][0].bits<<OC_BIT_SCALE);
@@ -1152,13 +1514,14 @@ static unsigned oc_analyze_intra_mb_luma(oc_enc_ctx *_enc,
/*Select a block-level quantizer for a single chroma block in an INTRA frame.*/
static unsigned oc_analyze_intra_chroma_block(oc_enc_ctx *_enc,
- const oc_qii_state *_qs,int _pli,ptrdiff_t _fragi){
+ const oc_qii_state *_qs,int _pli,ptrdiff_t _fragi,unsigned _rd_scale){
const unsigned char *src;
oc_fragment *frags;
ptrdiff_t frag_offs;
oc_qii_state qt[3];
unsigned cost[3];
unsigned satd;
+ int dc;
unsigned best_cost;
int best_qii;
int qii;
@@ -1168,16 +1531,30 @@ static unsigned oc_analyze_intra_chroma_block(oc_enc_ctx *_enc,
src=_enc->state.ref_frame_data[OC_FRAME_IO];
ystride=_enc->state.ref_ystride[_pli];
frag_offs=_enc->state.frag_buf_offs[_fragi];
- satd=oc_enc_frag_intra_satd(_enc,src+frag_offs,ystride);
+ if(_enc->sp_level<OC_SP_LEVEL_NOSATD){
+ satd=oc_enc_frag_intra_satd(_enc,&dc,src+frag_offs,ystride);
+ }
+ else{
+ satd=oc_enc_frag_intra_sad(_enc,src+frag_offs,ystride);
+ }
+ /*Most chroma blocks have no AC coefficients to speak of anyway, so it's not
+ worth spending the bits to change the AC quantizer.
+ TODO: This may be worth revisiting when we separate out DC and AC
+ predictions from SATD.*/
+#if 0
nqis=_enc->state.nqis;
+#else
+ nqis=1;
+#endif
lambda=_enc->lambda;
best_qii=0;
for(qii=0;qii<nqis;qii++){
unsigned cur_rate;
unsigned cur_ssd;
oc_qii_state_advance(qt+qii,_qs,qii);
- cur_rate=oc_dct_cost2(&cur_ssd,_enc->state.qis[qii],_pli,0,satd)
+ cur_rate=oc_dct_cost2(_enc,&cur_ssd,qii,_pli,0,satd)
+(qt[qii].bits-_qs->bits<<OC_BIT_SCALE);
+ cur_ssd=OC_RD_SCALE(cur_ssd,_rd_scale);
cost[qii]=OC_MODE_RD_COST(cur_ssd,cur_rate,lambda);
}
best_cost=cost[0];
@@ -1192,17 +1569,49 @@ static unsigned oc_analyze_intra_chroma_block(oc_enc_ctx *_enc,
return best_cost;
}
+static void oc_enc_mb_transform_quantize_intra_luma(oc_enc_ctx *_enc,
+ oc_enc_pipeline_state *_pipe,unsigned _mbi,
+ const unsigned _rd_scale[4],const unsigned _rd_iscale[4]){
+ /*Worst case token stack usage for 4 fragments.*/
+ oc_token_checkpoint stack[64*4];
+ oc_token_checkpoint *stackptr;
+ const oc_sb_map *sb_maps;
+ oc_fragment *frags;
+ ptrdiff_t *coded_fragis;
+ ptrdiff_t ncoded_fragis;
+ ptrdiff_t fragi;
+ int bi;
+ sb_maps=(const oc_sb_map *)_enc->state.sb_maps;
+ frags=_enc->state.frags;
+ coded_fragis=_pipe->coded_fragis[0];
+ ncoded_fragis=_pipe->ncoded_fragis[0];
+ stackptr=stack;
+ for(bi=0;bi<4;bi++){
+ fragi=sb_maps[_mbi>>2][_mbi&3][bi];
+ frags[fragi].refi=OC_FRAME_SELF;
+ frags[fragi].mb_mode=OC_MODE_INTRA;
+ oc_enc_block_transform_quantize(_enc,_pipe,0,fragi,
+ _rd_scale[bi],_rd_iscale[bi],NULL,NULL,&stackptr);
+ coded_fragis[ncoded_fragis++]=fragi;
+ }
+ _pipe->ncoded_fragis[0]=ncoded_fragis;
+}
+
static void oc_enc_sb_transform_quantize_intra_chroma(oc_enc_ctx *_enc,
oc_enc_pipeline_state *_pipe,int _pli,int _sbi_start,int _sbi_end){
- const oc_sb_map *sb_maps;
- oc_sb_flags *sb_flags;
- ptrdiff_t *coded_fragis;
- ptrdiff_t ncoded_fragis;
- int sbi;
+ const ogg_uint16_t *mcu_rd_scale;
+ const ogg_uint16_t *mcu_rd_iscale;
+ const oc_sb_map *sb_maps;
+ ptrdiff_t *coded_fragis;
+ ptrdiff_t ncoded_fragis;
+ ptrdiff_t froffset;
+ int sbi;
+ mcu_rd_scale=(const ogg_uint16_t *)_enc->mcu_rd_scale;
+ mcu_rd_iscale=(const ogg_uint16_t *)_enc->mcu_rd_iscale;
sb_maps=(const oc_sb_map *)_enc->state.sb_maps;
- sb_flags=_enc->state.sb_flags;
coded_fragis=_pipe->coded_fragis[_pli];
ncoded_fragis=_pipe->ncoded_fragis[_pli];
+ froffset=_pipe->froffset[_pli];
for(sbi=_sbi_start;sbi<_sbi_end;sbi++){
/*Worst case token stack usage for 1 fragment.*/
oc_token_checkpoint stack[64];
@@ -1213,10 +1622,14 @@ static void oc_enc_sb_transform_quantize_intra_chroma(oc_enc_ctx *_enc,
fragi=sb_maps[sbi][quadi][bi];
if(fragi>=0){
oc_token_checkpoint *stackptr;
- oc_analyze_intra_chroma_block(_enc,_pipe->qs+_pli,_pli,fragi);
+ unsigned rd_scale;
+ unsigned rd_iscale;
+ rd_scale=mcu_rd_scale[fragi-froffset];
+ rd_iscale=mcu_rd_iscale[fragi-froffset];
+ oc_analyze_intra_chroma_block(_enc,_pipe->qs+_pli,_pli,fragi,rd_scale);
stackptr=stack;
- oc_enc_block_transform_quantize(_enc,
- _pipe,_pli,fragi,0,NULL,&stackptr);
+ oc_enc_block_transform_quantize(_enc,_pipe,_pli,fragi,
+ rd_scale,rd_iscale,NULL,NULL,&stackptr);
coded_fragis[ncoded_fragis++]=fragi;
}
}
@@ -1226,13 +1639,19 @@ static void oc_enc_sb_transform_quantize_intra_chroma(oc_enc_ctx *_enc,
/*Analysis stage for an INTRA frame.*/
void oc_enc_analyze_intra(oc_enc_ctx *_enc,int _recode){
- oc_enc_pipeline_state pipe;
+ ogg_int64_t activity_sum;
+ ogg_int64_t luma_sum;
+ unsigned activity_avg;
+ unsigned luma_avg;
+ const ogg_uint16_t *chroma_rd_scale;
+ ogg_uint16_t *mcu_rd_scale;
+ ogg_uint16_t *mcu_rd_iscale;
const unsigned char *map_idxs;
int nmap_idxs;
oc_sb_flags *sb_flags;
signed char *mb_modes;
const oc_mb_map *mb_maps;
- oc_mb_enc_info *embs;
+ const oc_sb_map *sb_maps;
oc_fragment *frags;
unsigned stripe_sby;
unsigned mcu_nvsbs;
@@ -1242,7 +1661,14 @@ void oc_enc_analyze_intra(oc_enc_ctx *_enc,int _recode){
int pli;
_enc->state.frame_type=OC_INTRA_FRAME;
oc_enc_tokenize_start(_enc);
- oc_enc_pipeline_init(_enc,&pipe);
+ oc_enc_pipeline_init(_enc,&_enc->pipe);
+ oc_enc_mode_rd_init(_enc);
+ activity_sum=luma_sum=0;
+ activity_avg=_enc->activity_avg;
+ luma_avg=OC_CLAMPI(90<<8,_enc->luma_avg,160<<8);
+ chroma_rd_scale=_enc->chroma_rd_scale[OC_INTRA_FRAME][_enc->state.qis[0]];
+ mcu_rd_scale=_enc->mcu_rd_scale;
+ mcu_rd_iscale=_enc->mcu_rd_iscale;
/*Choose MVs and MB modes and quantize and code luma.
Must be done in Hilbert order.*/
map_idxs=OC_MB_MAP_IDXS[_enc->state.info.pixel_fmt];
@@ -1253,52 +1679,91 @@ void oc_enc_analyze_intra(oc_enc_ctx *_enc,int _recode){
sb_flags=_enc->state.sb_flags;
mb_modes=_enc->state.mb_modes;
mb_maps=(const oc_mb_map *)_enc->state.mb_maps;
- embs=_enc->mb_info;
+ sb_maps=(const oc_sb_map *)_enc->state.sb_maps;
frags=_enc->state.frags;
notstart=0;
notdone=1;
mcu_nvsbs=_enc->mcu_nvsbs;
for(stripe_sby=0;notdone;stripe_sby+=mcu_nvsbs){
- unsigned sbi;
- unsigned sbi_end;
- notdone=oc_enc_pipeline_set_stripe(_enc,&pipe,stripe_sby);
- sbi_end=pipe.sbi_end[0];
- for(sbi=pipe.sbi0[0];sbi<sbi_end;sbi++){
+ ptrdiff_t cfroffset;
+ unsigned sbi;
+ unsigned sbi_end;
+ notdone=oc_enc_pipeline_set_stripe(_enc,&_enc->pipe,stripe_sby);
+ sbi_end=_enc->pipe.sbi_end[0];
+ cfroffset=_enc->pipe.froffset[1];
+ for(sbi=_enc->pipe.sbi0[0];sbi<sbi_end;sbi++){
int quadi;
/*Mode addressing is through Y plane, always 4 MB per SB.*/
for(quadi=0;quadi<4;quadi++)if(sb_flags[sbi].quad_valid&1<<quadi){
+ unsigned activity[4];
+ unsigned rd_scale[5];
+ unsigned rd_iscale[5];
+ unsigned luma;
unsigned mbi;
int mapii;
int mapi;
int bi;
ptrdiff_t fragi;
mbi=sbi<<2|quadi;
+ /*Activity masking.*/
+ if(_enc->sp_level<OC_SP_LEVEL_FAST_ANALYSIS){
+ luma=oc_mb_activity(_enc,mbi,activity);
+ }
+ else{
+ unsigned intra_satd[12];
+ luma=oc_mb_intra_satd(_enc,mbi,intra_satd);
+ oc_mb_activity_fast(_enc,mbi,activity,intra_satd);
+ for(bi=0;bi<4;bi++)frags[sb_maps[mbi>>2][mbi&3][bi]].qii=0;
+ }
+ activity_sum+=oc_mb_masking(rd_scale,rd_iscale,
+ chroma_rd_scale,activity,activity_avg,luma,luma_avg);
+ luma_sum+=luma;
/*Motion estimation:
- We always do a basic 1MV search for all macroblocks, coded or not,
- keyframe or not.*/
- if(!_recode&&_enc->state.curframe_num>0)oc_mcenc_search(_enc,mbi);
- oc_analyze_intra_mb_luma(_enc,pipe.qs+0,mbi);
+ We do a basic 1MV search for all macroblocks, coded or not,
+ keyframe or not, unless we aren't using motion estimation at all.*/
+ if(!_recode&&_enc->state.curframe_num>0&&
+ _enc->sp_level<OC_SP_LEVEL_NOMC&&_enc->keyframe_frequency_force>1){
+ oc_mcenc_search(_enc,mbi);
+ }
+ if(_enc->sp_level<OC_SP_LEVEL_FAST_ANALYSIS){
+ oc_analyze_intra_mb_luma(_enc,_enc->pipe.qs+0,mbi,rd_scale);
+ }
mb_modes[mbi]=OC_MODE_INTRA;
- oc_enc_mb_transform_quantize_luma(_enc,&pipe,mbi,0);
+ oc_enc_mb_transform_quantize_intra_luma(_enc,&_enc->pipe,
+ mbi,rd_scale,rd_iscale);
/*Propagate final MB mode and MVs to the chroma blocks.*/
for(mapii=4;mapii<nmap_idxs;mapii++){
mapi=map_idxs[mapii];
pli=mapi>>2;
bi=mapi&3;
fragi=mb_maps[mbi][pli][bi];
+ frags[fragi].refi=OC_FRAME_SELF;
frags[fragi].mb_mode=OC_MODE_INTRA;
}
+ /*Save masking scale factors for chroma blocks.*/
+ for(mapii=4;mapii<(nmap_idxs-4>>1)+4;mapii++){
+ mapi=map_idxs[mapii];
+ bi=mapi&3;
+ fragi=mb_maps[mbi][1][bi];
+ mcu_rd_scale[fragi-cfroffset]=(ogg_uint16_t)rd_scale[4];
+ mcu_rd_iscale[fragi-cfroffset]=(ogg_uint16_t)rd_iscale[4];
+ }
}
}
- oc_enc_pipeline_finish_mcu_plane(_enc,&pipe,0,notstart,notdone);
+ oc_enc_pipeline_finish_mcu_plane(_enc,&_enc->pipe,0,notstart,notdone);
/*Code chroma planes.*/
for(pli=1;pli<3;pli++){
- oc_enc_sb_transform_quantize_intra_chroma(_enc,&pipe,
- pli,pipe.sbi0[pli],pipe.sbi_end[pli]);
- oc_enc_pipeline_finish_mcu_plane(_enc,&pipe,pli,notstart,notdone);
+ oc_enc_sb_transform_quantize_intra_chroma(_enc,&_enc->pipe,
+ pli,_enc->pipe.sbi0[pli],_enc->pipe.sbi_end[pli]);
+ oc_enc_pipeline_finish_mcu_plane(_enc,&_enc->pipe,pli,notstart,notdone);
}
notstart=1;
}
+ /*Compute the average block activity and MB luma score for the frame.*/
+ _enc->activity_avg=OC_MAXI(OC_ACTIVITY_AVG_MIN,
+ (unsigned)((activity_sum+(_enc->state.fplanes[0].nfrags>>1))/
+ _enc->state.fplanes[0].nfrags));
+ _enc->luma_avg=(unsigned)((luma_sum+(_enc->state.nmbs>>1))/_enc->state.nmbs);
/*Finish filling in the reference frame borders.*/
refi=_enc->state.ref_frame_idx[OC_FRAME_SELF];
for(pli=0;pli<3;pli++)oc_state_borders_fill_caps(&_enc->state,refi,pli);
@@ -1339,27 +1804,21 @@ static const unsigned OC_NOSKIP[12]={
static void oc_analyze_mb_mode_luma(oc_enc_ctx *_enc,
oc_mode_choice *_modec,const oc_fr_state *_fr,const oc_qii_state *_qs,
- const unsigned _frag_satd[12],const unsigned _skip_ssd[12],int _qti){
+ const unsigned _frag_satd[12],const unsigned _skip_ssd[12],
+ const unsigned _rd_scale[4],int _qti){
oc_fr_state fr;
oc_qii_state qs;
unsigned ssd;
unsigned rate;
- int overhead;
unsigned satd;
unsigned best_ssd;
unsigned best_rate;
- int best_overhead;
int best_fri;
int best_qii;
- unsigned cur_cost;
- unsigned cur_ssd;
- unsigned cur_rate;
- int cur_overhead;
int lambda;
int nqis;
int nskipped;
int bi;
- int qii;
lambda=_enc->lambda;
nqis=_enc->state.nqis;
/*We could do a trellis optimization here, but we don't make final skip
@@ -1370,26 +1829,36 @@ static void oc_analyze_mb_mode_luma(oc_enc_ctx *_enc,
code the flags, anyway.*/
*&fr=*_fr;
*&qs=*_qs;
- ssd=rate=overhead=nskipped=0;
+ ssd=rate=nskipped=0;
for(bi=0;bi<4;bi++){
oc_fr_state ft[2];
oc_qii_state qt[3];
unsigned best_cost;
+ unsigned cur_cost;
+ unsigned cur_ssd;
+ unsigned cur_rate;
+ unsigned cur_overhead;
+ int qii;
satd=_frag_satd[bi];
*(ft+0)=*&fr;
oc_fr_code_block(ft+0);
- oc_qii_state_advance(qt+0,&qs,0);
- best_overhead=(ft[0].bits-fr.bits<<OC_BIT_SCALE);
- best_rate=oc_dct_cost2(&best_ssd,_enc->state.qis[0],0,_qti,satd)
- +(qt[0].bits-qs.bits<<OC_BIT_SCALE);
- best_cost=OC_MODE_RD_COST(ssd+best_ssd,rate+best_rate+best_overhead,lambda);
+ cur_overhead=ft[0].bits-fr.bits;
+ best_rate=oc_dct_cost2(_enc,&best_ssd,0,0,_qti,satd)
+ +(cur_overhead<<OC_BIT_SCALE);
+ if(nqis>1){
+ oc_qii_state_advance(qt+0,&qs,0);
+ best_rate+=qt[0].bits-qs.bits<<OC_BIT_SCALE;
+ }
+ best_ssd=OC_RD_SCALE(best_ssd,_rd_scale[bi]);
+ best_cost=OC_MODE_RD_COST(ssd+best_ssd,rate+best_rate,lambda);
best_fri=0;
best_qii=0;
for(qii=1;qii<nqis;qii++){
oc_qii_state_advance(qt+qii,&qs,qii);
- cur_rate=oc_dct_cost2(&cur_ssd,_enc->state.qis[qii],0,_qti,satd)
- +(qt[qii].bits-qs.bits<<OC_BIT_SCALE);
- cur_cost=OC_MODE_RD_COST(ssd+cur_ssd,rate+cur_rate+best_overhead,lambda);
+ cur_rate=oc_dct_cost2(_enc,&cur_ssd,qii,0,_qti,satd)
+ +(cur_overhead+qt[qii].bits-qs.bits<<OC_BIT_SCALE);
+ cur_ssd=OC_RD_SCALE(cur_ssd,_rd_scale[bi]);
+ cur_cost=OC_MODE_RD_COST(ssd+cur_ssd,rate+cur_rate,lambda);
if(cur_cost<best_cost){
best_cost=cur_cost;
best_ssd=cur_ssd;
@@ -1397,7 +1866,7 @@ static void oc_analyze_mb_mode_luma(oc_enc_ctx *_enc,
best_qii=qii;
}
}
- if(_skip_ssd[bi]<UINT_MAX&&nskipped<3){
+ if(_skip_ssd[bi]<(UINT_MAX>>OC_BIT_SCALE+2)&&nskipped<3){
*(ft+1)=*&fr;
oc_fr_skip_block(ft+1);
cur_overhead=ft[1].bits-fr.bits<<OC_BIT_SCALE;
@@ -1405,15 +1874,13 @@ static void oc_analyze_mb_mode_luma(oc_enc_ctx *_enc,
cur_cost=OC_MODE_RD_COST(ssd+cur_ssd,rate+cur_overhead,lambda);
if(cur_cost<=best_cost){
best_ssd=cur_ssd;
- best_rate=0;
- best_overhead=cur_overhead;
+ best_rate=cur_overhead;
best_fri=1;
best_qii+=4;
}
}
rate+=best_rate;
ssd+=best_ssd;
- overhead+=best_overhead;
*&fr=*(ft+best_fri);
if(best_fri==0)*&qs=*(qt+best_qii);
else nskipped++;
@@ -1421,12 +1888,12 @@ static void oc_analyze_mb_mode_luma(oc_enc_ctx *_enc,
}
_modec->ssd=ssd;
_modec->rate=rate;
- _modec->overhead=OC_MAXI(overhead,0);
}
static void oc_analyze_mb_mode_chroma(oc_enc_ctx *_enc,
oc_mode_choice *_modec,const oc_fr_state *_fr,const oc_qii_state *_qs,
- const unsigned _frag_satd[12],const unsigned _skip_ssd[12],int _qti){
+ const unsigned _frag_satd[12],const unsigned _skip_ssd[12],
+ unsigned _rd_scale,int _qti){
unsigned ssd;
unsigned rate;
unsigned satd;
@@ -1443,7 +1910,15 @@ static void oc_analyze_mb_mode_chroma(oc_enc_ctx *_enc,
int bi;
int qii;
lambda=_enc->lambda;
+ /*Most chroma blocks have no AC coefficients to speak of anyway, so it's not
+ worth spending the bits to change the AC quantizer.
+ TODO: This may be worth revisiting when we separate out DC and AC
+ predictions from SATD.*/
+#if 0
nqis=_enc->state.nqis;
+#else
+ nqis=1;
+#endif
ssd=_modec->ssd;
rate=_modec->rate;
/*Because (except in 4:4:4 mode) we aren't considering chroma blocks in coded
@@ -1455,13 +1930,15 @@ static void oc_analyze_mb_mode_chroma(oc_enc_ctx *_enc,
for(;bi<nblocks;bi++){
unsigned best_cost;
satd=_frag_satd[bi];
- best_rate=oc_dct_cost2(&best_ssd,_enc->state.qis[0],pli,_qti,satd)
+ best_rate=oc_dct_cost2(_enc,&best_ssd,0,pli,_qti,satd)
+OC_CHROMA_QII_RATE;
+ best_ssd=OC_RD_SCALE(best_ssd,_rd_scale);
best_cost=OC_MODE_RD_COST(ssd+best_ssd,rate+best_rate,lambda);
best_qii=0;
for(qii=1;qii<nqis;qii++){
- cur_rate=oc_dct_cost2(&cur_ssd,_enc->state.qis[qii],0,_qti,satd)
+ cur_rate=oc_dct_cost2(_enc,&cur_ssd,qii,pli,_qti,satd)
+OC_CHROMA_QII_RATE;
+ cur_ssd=OC_RD_SCALE(cur_ssd,_rd_scale);
cur_cost=OC_MODE_RD_COST(ssd+cur_ssd,rate+cur_rate,lambda);
if(cur_cost<best_cost){
best_cost=cur_cost;
@@ -1470,7 +1947,7 @@ static void oc_analyze_mb_mode_chroma(oc_enc_ctx *_enc,
best_qii=qii;
}
}
- if(_skip_ssd[bi]<UINT_MAX){
+ if(_skip_ssd[bi]<(UINT_MAX>>OC_BIT_SCALE+2)){
cur_ssd=_skip_ssd[bi]<<OC_BIT_SCALE;
cur_cost=OC_MODE_RD_COST(ssd+cur_ssd,rate,lambda);
if(cur_cost<=best_cost){
@@ -1490,65 +1967,50 @@ static void oc_analyze_mb_mode_chroma(oc_enc_ctx *_enc,
}
static void oc_skip_cost(oc_enc_ctx *_enc,oc_enc_pipeline_state *_pipe,
- unsigned _mbi,unsigned _ssd[12]){
- OC_ALIGN16(ogg_int16_t buffer[64]);
- const unsigned char *src;
- const unsigned char *ref;
- int ystride;
- const oc_fragment *frags;
- const ptrdiff_t *frag_buf_offs;
- const ptrdiff_t *sb_map;
- const oc_mb_map_plane *mb_map;
- const unsigned char *map_idxs;
- int map_nidxs;
- ogg_int64_t mask;
- unsigned uncoded_ssd;
- int uncoded_dc;
- unsigned dc_dequant;
- int dc_flag;
- int mapii;
- int mapi;
- int pli;
- int bi;
- ptrdiff_t fragi;
- ptrdiff_t frag_offs;
- int borderi;
- int pi;
+ unsigned _mbi,const unsigned _rd_scale[4],unsigned _ssd[12]){
+ const unsigned char *src;
+ const unsigned char *ref;
+ int ystride;
+ const oc_fragment *frags;
+ const ptrdiff_t *frag_buf_offs;
+ const ptrdiff_t *sb_map;
+ const oc_mb_map_plane *mb_map;
+ const unsigned char *map_idxs;
+ oc_mv *mvs;
+ int map_nidxs;
+ unsigned uncoded_ssd;
+ int mapii;
+ int mapi;
+ int pli;
+ int bi;
+ ptrdiff_t fragi;
+ ptrdiff_t frag_offs;
+ int borderi;
src=_enc->state.ref_frame_data[OC_FRAME_IO];
- ref=_enc->state.ref_frame_data[_enc->state.ref_frame_idx[OC_FRAME_PREV]];
+ ref=_enc->state.ref_frame_data[OC_FRAME_PREV];
ystride=_enc->state.ref_ystride[0];
frags=_enc->state.frags;
frag_buf_offs=_enc->state.frag_buf_offs;
sb_map=_enc->state.sb_maps[_mbi>>2][_mbi&3];
- dc_dequant=_enc->state.dequant_tables[_enc->state.qis[0]][0][1][0];
+ mvs=_enc->mb_info[_mbi].block_mv;
for(bi=0;bi<4;bi++){
fragi=sb_map[bi];
- frag_offs=frag_buf_offs[fragi];
- oc_enc_frag_sub(_enc,buffer,src+frag_offs,ref+frag_offs,ystride);
borderi=frags[fragi].borderi;
- uncoded_ssd=uncoded_dc=0;
+ frag_offs=frag_buf_offs[fragi];
if(borderi<0){
- for(pi=0;pi<64;pi++){
- uncoded_ssd+=buffer[pi]*buffer[pi];
- uncoded_dc+=buffer[pi];
- }
+ uncoded_ssd=oc_enc_frag_ssd(_enc,src+frag_offs,ref+frag_offs,ystride);
}
else{
- ogg_int64_t mask;
- mask=_enc->state.borders[borderi].mask;
- for(pi=0;pi<64;pi++,mask>>=1)if(mask&1){
- uncoded_ssd+=buffer[pi]*buffer[pi];
- uncoded_dc+=buffer[pi];
- }
+ uncoded_ssd=oc_enc_frag_border_ssd(_enc,
+ src+frag_offs,ref+frag_offs,ystride,_enc->state.borders[borderi].mask);
}
- /*Scale to match DCT domain.*/
- uncoded_ssd<<=4;
- /*We actually only want the AC contribution to the SSD.*/
- uncoded_ssd-=uncoded_dc*uncoded_dc>>2;
- /*DC is a special case; if there's more than a full-quantizer improvement
- in the effective DC component, always force-code the block.*/
- dc_flag=abs(uncoded_dc)>dc_dequant<<1;
- uncoded_ssd|=-dc_flag;
+ /*Scale to match DCT domain and RD.*/
+ uncoded_ssd=OC_RD_SKIP_SCALE(uncoded_ssd,_rd_scale[bi]);
+ /*Motion is a special case; if there is more than a full-pixel motion
+ against the prior frame, penalize skipping.
+ TODO: The factor of two here is a kludge, but it tested out better than a
+ hard limit.*/
+ if(mvs[bi]!=0)uncoded_ssd*=2;
_pipe->skip_ssd[0][fragi-_pipe->froffset[0]]=_ssd[bi]=uncoded_ssd;
}
mb_map=(const oc_mb_map_plane *)_enc->state.mb_maps[_mbi];
@@ -1556,96 +2018,52 @@ static void oc_skip_cost(oc_enc_ctx *_enc,oc_enc_pipeline_state *_pipe,
map_idxs=OC_MB_MAP_IDXS[_enc->state.info.pixel_fmt];
map_nidxs=(map_nidxs-4>>1)+4;
mapii=4;
+ mvs=_enc->mb_info[_mbi].unref_mv;
for(pli=1;pli<3;pli++){
ystride=_enc->state.ref_ystride[pli];
- dc_dequant=_enc->state.dequant_tables[_enc->state.qis[0]][pli][1][0];
for(;mapii<map_nidxs;mapii++){
mapi=map_idxs[mapii];
bi=mapi&3;
fragi=mb_map[pli][bi];
- frag_offs=frag_buf_offs[fragi];
- oc_enc_frag_sub(_enc,buffer,src+frag_offs,ref+frag_offs,ystride);
borderi=frags[fragi].borderi;
- uncoded_ssd=uncoded_dc=0;
+ frag_offs=frag_buf_offs[fragi];
if(borderi<0){
- for(pi=0;pi<64;pi++){
- uncoded_ssd+=buffer[pi]*buffer[pi];
- uncoded_dc+=buffer[pi];
- }
+ uncoded_ssd=oc_enc_frag_ssd(_enc,src+frag_offs,ref+frag_offs,ystride);
}
else{
- mask=_enc->state.borders[borderi].mask;
- for(pi=0;pi<64;pi++,mask>>=1)if(mask&1){
- uncoded_ssd+=buffer[pi]*buffer[pi];
- uncoded_dc+=buffer[pi];
- }
+ uncoded_ssd=oc_enc_frag_border_ssd(_enc,
+ src+frag_offs,ref+frag_offs,ystride,_enc->state.borders[borderi].mask);
}
- /*Scale to match DCT domain.*/
- uncoded_ssd<<=4;
- /*We actually only want the AC contribution to the SSD.*/
- uncoded_ssd-=uncoded_dc*uncoded_dc>>2;
- /*DC is a special case; if there's more than a full-quantizer improvement
- in the effective DC component, always force-code the block.*/
- dc_flag=abs(uncoded_dc)>dc_dequant<<1;
- uncoded_ssd|=-dc_flag;
+ /*Scale to match DCT domain and RD.*/
+ uncoded_ssd=OC_RD_SKIP_SCALE(uncoded_ssd,_rd_scale[4]);
+ /*Motion is a special case; if there is more than a full-pixel motion
+ against the prior frame, penalize skipping.
+ TODO: The factor of two here is a kludge, but it tested out better than
+ a hard limit*/
+ if(mvs[OC_FRAME_PREV]!=0)uncoded_ssd*=2;
_pipe->skip_ssd[pli][fragi-_pipe->froffset[pli]]=_ssd[mapii]=uncoded_ssd;
}
map_nidxs=(map_nidxs-4<<1)+4;
}
}
-static void oc_mb_intra_satd(oc_enc_ctx *_enc,unsigned _mbi,
- unsigned _frag_satd[12]){
- const unsigned char *src;
- const ptrdiff_t *frag_buf_offs;
- const ptrdiff_t *sb_map;
- const oc_mb_map_plane *mb_map;
- const unsigned char *map_idxs;
- int map_nidxs;
- int mapii;
- int mapi;
- int ystride;
- int pli;
- int bi;
- ptrdiff_t fragi;
- ptrdiff_t frag_offs;
- frag_buf_offs=_enc->state.frag_buf_offs;
- sb_map=_enc->state.sb_maps[_mbi>>2][_mbi&3];
- src=_enc->state.ref_frame_data[OC_FRAME_IO];
- ystride=_enc->state.ref_ystride[0];
- for(bi=0;bi<4;bi++){
- fragi=sb_map[bi];
- frag_offs=frag_buf_offs[fragi];
- _frag_satd[bi]=oc_enc_frag_intra_satd(_enc,src+frag_offs,ystride);
- }
- mb_map=(const oc_mb_map_plane *)_enc->state.mb_maps[_mbi];
- map_idxs=OC_MB_MAP_IDXS[_enc->state.info.pixel_fmt];
- map_nidxs=OC_MB_MAP_NIDXS[_enc->state.info.pixel_fmt];
- /*Note: This assumes ref_ystride[1]==ref_ystride[2].*/
- ystride=_enc->state.ref_ystride[1];
- for(mapii=4;mapii<map_nidxs;mapii++){
- mapi=map_idxs[mapii];
- pli=mapi>>2;
- bi=mapi&3;
- fragi=mb_map[pli][bi];
- frag_offs=frag_buf_offs[fragi];
- _frag_satd[mapii]=oc_enc_frag_intra_satd(_enc,src+frag_offs,ystride);
- }
-}
static void oc_cost_intra(oc_enc_ctx *_enc,oc_mode_choice *_modec,
unsigned _mbi,const oc_fr_state *_fr,const oc_qii_state *_qs,
- const unsigned _frag_satd[12],const unsigned _skip_ssd[12]){
- oc_analyze_mb_mode_luma(_enc,_modec,_fr,_qs,_frag_satd,_skip_ssd,0);
- oc_analyze_mb_mode_chroma(_enc,_modec,_fr,_qs,_frag_satd,_skip_ssd,0);
- _modec->overhead+=
+ const unsigned _frag_satd[12],const unsigned _skip_ssd[12],
+ const unsigned _rd_scale[5]){
+ oc_analyze_mb_mode_luma(_enc,_modec,_fr,_qs,_frag_satd,_skip_ssd,_rd_scale,0);
+ oc_analyze_mb_mode_chroma(_enc,_modec,_fr,_qs,
+ _frag_satd,_skip_ssd,_rd_scale[4],0);
+ _modec->overhead=
oc_mode_scheme_chooser_cost(&_enc->chooser,OC_MODE_INTRA)<<OC_BIT_SCALE;
oc_mode_set_cost(_modec,_enc->lambda);
}
static void oc_cost_inter(oc_enc_ctx *_enc,oc_mode_choice *_modec,
- unsigned _mbi,int _mb_mode,const signed char *_mv,
- const oc_fr_state *_fr,const oc_qii_state *_qs,const unsigned _skip_ssd[12]){
+ unsigned _mbi,int _mb_mode,oc_mv _mv,
+ const oc_fr_state *_fr,const oc_qii_state *_qs,
+ const unsigned _skip_ssd[12],const unsigned _rd_scale[5]){
unsigned frag_satd[12];
const unsigned char *src;
const unsigned char *ref;
@@ -1658,35 +2076,45 @@ static void oc_cost_inter(oc_enc_ctx *_enc,oc_mode_choice *_modec,
int mapii;
int mapi;
int mv_offs[2];
- int dx;
- int dy;
int pli;
int bi;
ptrdiff_t fragi;
ptrdiff_t frag_offs;
+ int dc;
src=_enc->state.ref_frame_data[OC_FRAME_IO];
- ref=_enc->state.ref_frame_data[
- _enc->state.ref_frame_idx[OC_FRAME_FOR_MODE(_mb_mode)]];
+ ref=_enc->state.ref_frame_data[OC_FRAME_FOR_MODE(_mb_mode)];
ystride=_enc->state.ref_ystride[0];
frag_buf_offs=_enc->state.frag_buf_offs;
sb_map=_enc->state.sb_maps[_mbi>>2][_mbi&3];
- dx=_mv[0];
- dy=_mv[1];
_modec->rate=_modec->ssd=0;
- if(oc_state_get_mv_offsets(&_enc->state,mv_offs,0,dx,dy)>1){
+ if(oc_state_get_mv_offsets(&_enc->state,mv_offs,0,_mv)>1){
for(bi=0;bi<4;bi++){
fragi=sb_map[bi];
frag_offs=frag_buf_offs[fragi];
- frag_satd[bi]=oc_enc_frag_satd2_thresh(_enc,src+frag_offs,
- ref+frag_offs+mv_offs[0],ref+frag_offs+mv_offs[1],ystride,UINT_MAX);
+ if(_enc->sp_level<OC_SP_LEVEL_NOSATD){
+ frag_satd[bi]=oc_enc_frag_satd2(_enc,&dc,src+frag_offs,
+ ref+frag_offs+mv_offs[0],ref+frag_offs+mv_offs[1],ystride);
+ frag_satd[bi]+=abs(dc);
+ }
+ else{
+ frag_satd[bi]=oc_enc_frag_sad2_thresh(_enc,src+frag_offs,
+ ref+frag_offs+mv_offs[0],ref+frag_offs+mv_offs[1],ystride,UINT_MAX);
+ }
}
}
else{
for(bi=0;bi<4;bi++){
fragi=sb_map[bi];
frag_offs=frag_buf_offs[fragi];
- frag_satd[bi]=oc_enc_frag_satd_thresh(_enc,src+frag_offs,
- ref+frag_offs+mv_offs[0],ystride,UINT_MAX);
+ if(_enc->sp_level<OC_SP_LEVEL_NOSATD){
+ frag_satd[bi]=oc_enc_frag_satd(_enc,&dc,src+frag_offs,
+ ref+frag_offs+mv_offs[0],ystride);
+ frag_satd[bi]+=abs(dc);
+ }
+ else{
+ frag_satd[bi]=oc_enc_frag_sad(_enc,src+frag_offs,
+ ref+frag_offs+mv_offs[0],ystride);
+ }
}
}
mb_map=(const oc_mb_map_plane *)_enc->state.mb_maps[_mbi];
@@ -1694,15 +2122,22 @@ static void oc_cost_inter(oc_enc_ctx *_enc,oc_mode_choice *_modec,
map_nidxs=OC_MB_MAP_NIDXS[_enc->state.info.pixel_fmt];
/*Note: This assumes ref_ystride[1]==ref_ystride[2].*/
ystride=_enc->state.ref_ystride[1];
- if(oc_state_get_mv_offsets(&_enc->state,mv_offs,1,dx,dy)>1){
+ if(oc_state_get_mv_offsets(&_enc->state,mv_offs,1,_mv)>1){
for(mapii=4;mapii<map_nidxs;mapii++){
mapi=map_idxs[mapii];
pli=mapi>>2;
bi=mapi&3;
fragi=mb_map[pli][bi];
frag_offs=frag_buf_offs[fragi];
- frag_satd[mapii]=oc_enc_frag_satd2_thresh(_enc,src+frag_offs,
- ref+frag_offs+mv_offs[0],ref+frag_offs+mv_offs[1],ystride,UINT_MAX);
+ if(_enc->sp_level<OC_SP_LEVEL_NOSATD){
+ frag_satd[mapii]=oc_enc_frag_satd2(_enc,&dc,src+frag_offs,
+ ref+frag_offs+mv_offs[0],ref+frag_offs+mv_offs[1],ystride);
+ frag_satd[mapii]+=abs(dc);
+ }
+ else{
+ frag_satd[mapii]=oc_enc_frag_sad2_thresh(_enc,src+frag_offs,
+ ref+frag_offs+mv_offs[0],ref+frag_offs+mv_offs[1],ystride,UINT_MAX);
+ }
}
}
else{
@@ -1712,30 +2147,38 @@ static void oc_cost_inter(oc_enc_ctx *_enc,oc_mode_choice *_modec,
bi=mapi&3;
fragi=mb_map[pli][bi];
frag_offs=frag_buf_offs[fragi];
- frag_satd[mapii]=oc_enc_frag_satd_thresh(_enc,src+frag_offs,
- ref+frag_offs+mv_offs[0],ystride,UINT_MAX);
+ if(_enc->sp_level<OC_SP_LEVEL_NOSATD){
+ frag_satd[mapii]=oc_enc_frag_satd(_enc,&dc,src+frag_offs,
+ ref+frag_offs+mv_offs[0],ystride);
+ frag_satd[mapii]+=abs(dc);
+ }
+ else{
+ frag_satd[mapii]=oc_enc_frag_sad(_enc,src+frag_offs,
+ ref+frag_offs+mv_offs[0],ystride);
+ }
}
}
- oc_analyze_mb_mode_luma(_enc,_modec,_fr,_qs,frag_satd,_skip_ssd,1);
- oc_analyze_mb_mode_chroma(_enc,_modec,_fr,_qs,frag_satd,_skip_ssd,1);
- _modec->overhead+=
+ oc_analyze_mb_mode_luma(_enc,_modec,_fr,_qs,frag_satd,_skip_ssd,_rd_scale,1);
+ oc_analyze_mb_mode_chroma(_enc,_modec,_fr,_qs,
+ frag_satd,_skip_ssd,_rd_scale[4],1);
+ _modec->overhead=
oc_mode_scheme_chooser_cost(&_enc->chooser,_mb_mode)<<OC_BIT_SCALE;
oc_mode_set_cost(_modec,_enc->lambda);
}
static void oc_cost_inter_nomv(oc_enc_ctx *_enc,oc_mode_choice *_modec,
unsigned _mbi,int _mb_mode,const oc_fr_state *_fr,const oc_qii_state *_qs,
- const unsigned _skip_ssd[12]){
- static const oc_mv OC_MV_ZERO;
- oc_cost_inter(_enc,_modec,_mbi,_mb_mode,OC_MV_ZERO,_fr,_qs,_skip_ssd);
+ const unsigned _skip_ssd[12],const unsigned _rd_scale[4]){
+ oc_cost_inter(_enc,_modec,_mbi,_mb_mode,0,_fr,_qs,_skip_ssd,_rd_scale);
}
static int oc_cost_inter1mv(oc_enc_ctx *_enc,oc_mode_choice *_modec,
- unsigned _mbi,int _mb_mode,const signed char *_mv,
- const oc_fr_state *_fr,const oc_qii_state *_qs,const unsigned _skip_ssd[12]){
+ unsigned _mbi,int _mb_mode,oc_mv _mv,
+ const oc_fr_state *_fr,const oc_qii_state *_qs,const unsigned _skip_ssd[12],
+ const unsigned _rd_scale[4]){
int bits0;
- oc_cost_inter(_enc,_modec,_mbi,_mb_mode,_mv,_fr,_qs,_skip_ssd);
- bits0=OC_MV_BITS[0][_mv[0]+31]+OC_MV_BITS[0][_mv[1]+31];
+ oc_cost_inter(_enc,_modec,_mbi,_mb_mode,_mv,_fr,_qs,_skip_ssd,_rd_scale);
+ bits0=OC_MV_BITS[0][OC_MV_X(_mv)+31]+OC_MV_BITS[0][OC_MV_Y(_mv)+31];
_modec->overhead+=OC_MINI(_enc->mv_bits[0]+bits0,_enc->mv_bits[1]+12)
-OC_MINI(_enc->mv_bits[0],_enc->mv_bits[1])<<OC_BIT_SCALE;
oc_mode_set_cost(_modec,_enc->lambda);
@@ -1749,7 +2192,7 @@ static const unsigned char OC_MB_PHASE[4][4]={
static void oc_cost_inter4mv(oc_enc_ctx *_enc,oc_mode_choice *_modec,
unsigned _mbi,oc_mv _mv[4],const oc_fr_state *_fr,const oc_qii_state *_qs,
- const unsigned _skip_ssd[12]){
+ const unsigned _skip_ssd[12],const unsigned _rd_scale[5]){
unsigned frag_satd[12];
oc_mv lbmvs[4];
oc_mv cbmvs[4];
@@ -1765,8 +2208,6 @@ static void oc_cost_inter4mv(oc_enc_ctx *_enc,oc_mode_choice *_modec,
int mapii;
int mapi;
int mv_offs[2];
- int dx;
- int dy;
int pli;
int bi;
ptrdiff_t fragi;
@@ -1774,8 +2215,9 @@ static void oc_cost_inter4mv(oc_enc_ctx *_enc,oc_mode_choice *_modec,
int bits0;
int bits1;
unsigned satd;
+ int dc;
src=_enc->state.ref_frame_data[OC_FRAME_IO];
- ref=_enc->state.ref_frame_data[_enc->state.ref_frame_idx[OC_FRAME_PREV]];
+ ref=_enc->state.ref_frame_data[OC_FRAME_PREV];
ystride=_enc->state.ref_ystride[0];
frag_buf_offs=_enc->state.frag_buf_offs;
frag_mvs=_enc->state.frag_mvs;
@@ -1783,41 +2225,36 @@ static void oc_cost_inter4mv(oc_enc_ctx *_enc,oc_mode_choice *_modec,
_modec->rate=_modec->ssd=0;
for(bi=0;bi<4;bi++){
fragi=mb_map[0][bi];
- dx=_mv[bi][0];
- dy=_mv[bi][1];
/*Save the block MVs as the current ones while we're here; we'll replace
them if we don't ultimately choose 4MV mode.*/
- frag_mvs[fragi][0]=(signed char)dx;
- frag_mvs[fragi][1]=(signed char)dy;
+ frag_mvs[fragi]=_mv[bi];
frag_offs=frag_buf_offs[fragi];
- if(oc_state_get_mv_offsets(&_enc->state,mv_offs,0,dx,dy)>1){
- satd=oc_enc_frag_satd2_thresh(_enc,src+frag_offs,
- ref+frag_offs+mv_offs[0],ref+frag_offs+mv_offs[1],ystride,UINT_MAX);
+ if(oc_state_get_mv_offsets(&_enc->state,mv_offs,0,_mv[bi])>1){
+ satd=oc_enc_frag_satd2(_enc,&dc,src+frag_offs,
+ ref+frag_offs+mv_offs[0],ref+frag_offs+mv_offs[1],ystride);
}
else{
- satd=oc_enc_frag_satd_thresh(_enc,src+frag_offs,
- ref+frag_offs+mv_offs[0],ystride,UINT_MAX);
+ satd=oc_enc_frag_satd(_enc,&dc,src+frag_offs,
+ ref+frag_offs+mv_offs[0],ystride);
}
- frag_satd[OC_MB_PHASE[_mbi&3][bi]]=satd;
+ frag_satd[OC_MB_PHASE[_mbi&3][bi]]=satd+abs(dc);
}
oc_analyze_mb_mode_luma(_enc,_modec,_fr,_qs,frag_satd,
- _enc->vp3_compatible?OC_NOSKIP:_skip_ssd,1);
+ _enc->vp3_compatible?OC_NOSKIP:_skip_ssd,_rd_scale,1);
/*Figure out which blocks are being skipped and give them (0,0) MVs.*/
bits0=0;
bits1=0;
nqis=_enc->state.nqis;
for(bi=0;bi<4;bi++){
- if(_modec->qii[OC_MB_PHASE[_mbi&3][bi]]>=nqis){
- memset(lbmvs+bi,0,sizeof(*lbmvs));
- }
+ if(_modec->qii[OC_MB_PHASE[_mbi&3][bi]]>=nqis)lbmvs[bi]=0;
else{
- memcpy(lbmvs+bi,_mv+bi,sizeof(*lbmvs));
- bits0+=OC_MV_BITS[0][_mv[bi][0]+31]+OC_MV_BITS[0][_mv[bi][1]+31];
+ lbmvs[bi]=_mv[bi];
+ bits0+=OC_MV_BITS[0][OC_MV_X(_mv[bi])+31]
+ +OC_MV_BITS[0][OC_MV_Y(_mv[bi])+31];
bits1+=12;
}
}
- (*OC_SET_CHROMA_MVS_TABLE[_enc->state.info.pixel_fmt])(cbmvs,
- (const oc_mv *)lbmvs);
+ (*OC_SET_CHROMA_MVS_TABLE[_enc->state.info.pixel_fmt])(cbmvs,lbmvs);
map_idxs=OC_MB_MAP_IDXS[_enc->state.info.pixel_fmt];
map_nidxs=OC_MB_MAP_NIDXS[_enc->state.info.pixel_fmt];
/*Note: This assumes ref_ystride[1]==ref_ystride[2].*/
@@ -1827,23 +2264,22 @@ static void oc_cost_inter4mv(oc_enc_ctx *_enc,oc_mode_choice *_modec,
pli=mapi>>2;
bi=mapi&3;
fragi=mb_map[pli][bi];
- dx=cbmvs[bi][0];
- dy=cbmvs[bi][1];
frag_offs=frag_buf_offs[fragi];
/*TODO: We could save half these calls by re-using the results for the Cb
and Cr planes; is it worth it?*/
- if(oc_state_get_mv_offsets(&_enc->state,mv_offs,pli,dx,dy)>1){
- satd=oc_enc_frag_satd2_thresh(_enc,src+frag_offs,
- ref+frag_offs+mv_offs[0],ref+frag_offs+mv_offs[1],ystride,UINT_MAX);
+ if(oc_state_get_mv_offsets(&_enc->state,mv_offs,pli,cbmvs[bi])>1){
+ satd=oc_enc_frag_satd2(_enc,&dc,src+frag_offs,
+ ref+frag_offs+mv_offs[0],ref+frag_offs+mv_offs[1],ystride);
}
else{
- satd=oc_enc_frag_satd_thresh(_enc,src+frag_offs,
- ref+frag_offs+mv_offs[0],ystride,UINT_MAX);
+ satd=oc_enc_frag_satd(_enc,&dc,src+frag_offs,
+ ref+frag_offs+mv_offs[0],ystride);
}
- frag_satd[mapii]=satd;
+ frag_satd[mapii]=satd+abs(dc);
}
- oc_analyze_mb_mode_chroma(_enc,_modec,_fr,_qs,frag_satd,_skip_ssd,1);
- _modec->overhead+=
+ oc_analyze_mb_mode_chroma(_enc,_modec,_fr,_qs,
+ frag_satd,_skip_ssd,_rd_scale[4],1);
+ _modec->overhead=
oc_mode_scheme_chooser_cost(&_enc->chooser,OC_MODE_INTER_MV_FOUR)
+OC_MINI(_enc->mv_bits[0]+bits0,_enc->mv_bits[1]+bits1)
-OC_MINI(_enc->mv_bits[0],_enc->mv_bits[1])<<OC_BIT_SCALE;
@@ -1852,12 +2288,18 @@ static void oc_cost_inter4mv(oc_enc_ctx *_enc,oc_mode_choice *_modec,
int oc_enc_analyze_inter(oc_enc_ctx *_enc,int _allow_keyframe,int _recode){
oc_set_chroma_mvs_func set_chroma_mvs;
- oc_enc_pipeline_state pipe;
oc_qii_state intra_luma_qs;
oc_mv last_mv;
oc_mv prior_mv;
ogg_int64_t interbits;
ogg_int64_t intrabits;
+ ogg_int64_t activity_sum;
+ ogg_int64_t luma_sum;
+ unsigned activity_avg;
+ unsigned luma_avg;
+ const ogg_uint16_t *chroma_rd_scale;
+ ogg_uint16_t *mcu_rd_scale;
+ ogg_uint16_t *mcu_rd_iscale;
const unsigned char *map_idxs;
int nmap_idxs;
unsigned *coded_mbis;
@@ -1871,30 +2313,36 @@ int oc_enc_analyze_inter(oc_enc_ctx *_enc,int _allow_keyframe,int _recode){
oc_mb_enc_info *embs;
oc_fragment *frags;
oc_mv *frag_mvs;
- int qi;
unsigned stripe_sby;
unsigned mcu_nvsbs;
int notstart;
int notdone;
- int vdec;
unsigned sbi;
unsigned sbi_end;
int refi;
int pli;
+ int sp_level;
+ sp_level=_enc->sp_level;
set_chroma_mvs=OC_SET_CHROMA_MVS_TABLE[_enc->state.info.pixel_fmt];
_enc->state.frame_type=OC_INTER_FRAME;
oc_mode_scheme_chooser_reset(&_enc->chooser);
oc_enc_tokenize_start(_enc);
- oc_enc_pipeline_init(_enc,&pipe);
+ oc_enc_pipeline_init(_enc,&_enc->pipe);
+ oc_enc_mode_rd_init(_enc);
if(_allow_keyframe)oc_qii_state_init(&intra_luma_qs);
_enc->mv_bits[0]=_enc->mv_bits[1]=0;
interbits=intrabits=0;
- last_mv[0]=last_mv[1]=prior_mv[0]=prior_mv[1]=0;
+ activity_sum=luma_sum=0;
+ activity_avg=_enc->activity_avg;
+ luma_avg=OC_CLAMPI(90<<8,_enc->luma_avg,160<<8);
+ chroma_rd_scale=_enc->chroma_rd_scale[OC_INTER_FRAME][_enc->state.qis[0]];
+ mcu_rd_scale=_enc->mcu_rd_scale;
+ mcu_rd_iscale=_enc->mcu_rd_iscale;
+ last_mv=prior_mv=0;
/*Choose MVs and MB modes and quantize and code luma.
Must be done in Hilbert order.*/
map_idxs=OC_MB_MAP_IDXS[_enc->state.info.pixel_fmt];
nmap_idxs=OC_MB_MAP_NIDXS[_enc->state.info.pixel_fmt];
- qi=_enc->state.qis[0];
coded_mbis=_enc->coded_mbis;
uncoded_mbis=coded_mbis+_enc->state.nmbs;
ncoded_mbis=0;
@@ -1909,37 +2357,51 @@ int oc_enc_analyze_inter(oc_enc_ctx *_enc,int _allow_keyframe,int _recode){
embs=_enc->mb_info;
frags=_enc->state.frags;
frag_mvs=_enc->state.frag_mvs;
- vdec=!(_enc->state.info.pixel_fmt&2);
notstart=0;
notdone=1;
mcu_nvsbs=_enc->mcu_nvsbs;
for(stripe_sby=0;notdone;stripe_sby+=mcu_nvsbs){
- notdone=oc_enc_pipeline_set_stripe(_enc,&pipe,stripe_sby);
- sbi_end=pipe.sbi_end[0];
- for(sbi=pipe.sbi0[0];sbi<sbi_end;sbi++){
+ ptrdiff_t cfroffset;
+ notdone=oc_enc_pipeline_set_stripe(_enc,&_enc->pipe,stripe_sby);
+ sbi_end=_enc->pipe.sbi_end[0];
+ cfroffset=_enc->pipe.froffset[1];
+ for(sbi=_enc->pipe.sbi0[0];sbi<sbi_end;sbi++){
int quadi;
/*Mode addressing is through Y plane, always 4 MB per SB.*/
for(quadi=0;quadi<4;quadi++)if(sb_flags[sbi].quad_valid&1<<quadi){
oc_mode_choice modes[8];
+ unsigned activity[4];
+ unsigned rd_scale[5];
+ unsigned rd_iscale[5];
unsigned skip_ssd[12];
unsigned intra_satd[12];
+ unsigned luma;
int mb_mv_bits_0;
int mb_gmv_bits_0;
int inter_mv_pref;
int mb_mode;
- int dx;
- int dy;
+ int refi;
+ int mv;
unsigned mbi;
int mapii;
int mapi;
int bi;
ptrdiff_t fragi;
mbi=sbi<<2|quadi;
+ luma=oc_mb_intra_satd(_enc,mbi,intra_satd);
+ /*Activity masking.*/
+ if(sp_level<OC_SP_LEVEL_FAST_ANALYSIS){
+ oc_mb_activity(_enc,mbi,activity);
+ }
+ else oc_mb_activity_fast(_enc,mbi,activity,intra_satd);
+ luma_sum+=luma;
+ activity_sum+=oc_mb_masking(rd_scale,rd_iscale,
+ chroma_rd_scale,activity,activity_avg,luma,luma_avg);
/*Motion estimation:
We always do a basic 1MV search for all macroblocks, coded or not,
keyframe or not.*/
- if(!_recode&&_enc->sp_level<OC_SP_LEVEL_NOMC)oc_mcenc_search(_enc,mbi);
- dx=dy=0;
+ if(!_recode&&sp_level<OC_SP_LEVEL_NOMC)oc_mcenc_search(_enc,mbi);
+ mv=0;
/*Find the block choice with the lowest estimated coding cost.
If a Cb or Cr block is coded but no Y' block from a macro block then
the mode MUST be OC_MODE_INTER_NOMV.
@@ -1948,15 +2410,16 @@ int oc_enc_analyze_inter(oc_enc_ctx *_enc,int _allow_keyframe,int _recode){
/*Block coding cost is estimated from correlated SATD metrics.*/
/*At this point, all blocks that are in frame are still marked coded.*/
if(!_recode){
- memcpy(embs[mbi].unref_mv,
- embs[mbi].analysis_mv[0],sizeof(embs[mbi].unref_mv));
+ embs[mbi].unref_mv[OC_FRAME_GOLD]=
+ embs[mbi].analysis_mv[0][OC_FRAME_GOLD];
+ embs[mbi].unref_mv[OC_FRAME_PREV]=
+ embs[mbi].analysis_mv[0][OC_FRAME_PREV];
embs[mbi].refined=0;
}
- oc_mb_intra_satd(_enc,mbi,intra_satd);
/*Estimate the cost of coding this MB in a keyframe.*/
if(_allow_keyframe){
oc_cost_intra(_enc,modes+OC_MODE_INTRA,mbi,
- pipe.fr+0,&intra_luma_qs,intra_satd,OC_NOSKIP);
+ _enc->pipe.fr+0,&intra_luma_qs,intra_satd,OC_NOSKIP,rd_scale);
intrabits+=modes[OC_MODE_INTRA].rate;
for(bi=0;bi<4;bi++){
oc_qii_state_advance(&intra_luma_qs,&intra_luma_qs,
@@ -1964,26 +2427,28 @@ int oc_enc_analyze_inter(oc_enc_ctx *_enc,int _allow_keyframe,int _recode){
}
}
/*Estimate the cost in a delta frame for various modes.*/
- oc_skip_cost(_enc,&pipe,mbi,skip_ssd);
- oc_cost_inter_nomv(_enc,modes+OC_MODE_INTER_NOMV,mbi,
- OC_MODE_INTER_NOMV,pipe.fr+0,pipe.qs+0,skip_ssd);
- if(_enc->sp_level<OC_SP_LEVEL_NOMC){
+ oc_skip_cost(_enc,&_enc->pipe,mbi,rd_scale,skip_ssd);
+ if(sp_level<OC_SP_LEVEL_NOMC){
+ oc_cost_inter_nomv(_enc,modes+OC_MODE_INTER_NOMV,mbi,
+ OC_MODE_INTER_NOMV,_enc->pipe.fr+0,_enc->pipe.qs+0,
+ skip_ssd,rd_scale);
oc_cost_intra(_enc,modes+OC_MODE_INTRA,mbi,
- pipe.fr+0,pipe.qs+0,intra_satd,skip_ssd);
+ _enc->pipe.fr+0,_enc->pipe.qs+0,intra_satd,skip_ssd,rd_scale);
mb_mv_bits_0=oc_cost_inter1mv(_enc,modes+OC_MODE_INTER_MV,mbi,
OC_MODE_INTER_MV,embs[mbi].unref_mv[OC_FRAME_PREV],
- pipe.fr+0,pipe.qs+0,skip_ssd);
+ _enc->pipe.fr+0,_enc->pipe.qs+0,skip_ssd,rd_scale);
oc_cost_inter(_enc,modes+OC_MODE_INTER_MV_LAST,mbi,
- OC_MODE_INTER_MV_LAST,last_mv,pipe.fr+0,pipe.qs+0,skip_ssd);
+ OC_MODE_INTER_MV_LAST,last_mv,_enc->pipe.fr+0,_enc->pipe.qs+0,
+ skip_ssd,rd_scale);
oc_cost_inter(_enc,modes+OC_MODE_INTER_MV_LAST2,mbi,
- OC_MODE_INTER_MV_LAST2,prior_mv,pipe.fr+0,pipe.qs+0,skip_ssd);
- oc_cost_inter4mv(_enc,modes+OC_MODE_INTER_MV_FOUR,mbi,
- embs[mbi].block_mv,pipe.fr+0,pipe.qs+0,skip_ssd);
+ OC_MODE_INTER_MV_LAST2,prior_mv,_enc->pipe.fr+0,_enc->pipe.qs+0,
+ skip_ssd,rd_scale);
oc_cost_inter_nomv(_enc,modes+OC_MODE_GOLDEN_NOMV,mbi,
- OC_MODE_GOLDEN_NOMV,pipe.fr+0,pipe.qs+0,skip_ssd);
+ OC_MODE_GOLDEN_NOMV,_enc->pipe.fr+0,_enc->pipe.qs+0,
+ skip_ssd,rd_scale);
mb_gmv_bits_0=oc_cost_inter1mv(_enc,modes+OC_MODE_GOLDEN_MV,mbi,
OC_MODE_GOLDEN_MV,embs[mbi].unref_mv[OC_FRAME_GOLD],
- pipe.fr+0,pipe.qs+0,skip_ssd);
+ _enc->pipe.fr+0,_enc->pipe.qs+0,skip_ssd,rd_scale);
/*The explicit MV modes (2,6,7) have not yet gone through halfpel
refinement.
We choose the explicit MV mode that's already furthest ahead on
@@ -1991,6 +2456,14 @@ int oc_enc_analyze_inter(oc_enc_ctx *_enc,int _allow_keyframe,int _recode){
We have to be careful to remember which ones we've refined so that
we don't refine it again if we re-encode this frame.*/
inter_mv_pref=_enc->lambda*3;
+ if(sp_level<OC_SP_LEVEL_FAST_ANALYSIS){
+ oc_cost_inter4mv(_enc,modes+OC_MODE_INTER_MV_FOUR,mbi,
+ embs[mbi].block_mv,_enc->pipe.fr+0,_enc->pipe.qs+0,
+ skip_ssd,rd_scale);
+ }
+ else{
+ modes[OC_MODE_INTER_MV_FOUR].cost=UINT_MAX;
+ }
if(modes[OC_MODE_INTER_MV_FOUR].cost<modes[OC_MODE_INTER_MV].cost&&
modes[OC_MODE_INTER_MV_FOUR].cost<modes[OC_MODE_GOLDEN_MV].cost){
if(!(embs[mbi].refined&0x80)){
@@ -1998,7 +2471,8 @@ int oc_enc_analyze_inter(oc_enc_ctx *_enc,int _allow_keyframe,int _recode){
embs[mbi].refined|=0x80;
}
oc_cost_inter4mv(_enc,modes+OC_MODE_INTER_MV_FOUR,mbi,
- embs[mbi].ref_mv,pipe.fr+0,pipe.qs+0,skip_ssd);
+ embs[mbi].ref_mv,_enc->pipe.fr+0,_enc->pipe.qs+0,
+ skip_ssd,rd_scale);
}
else if(modes[OC_MODE_GOLDEN_MV].cost+inter_mv_pref<
modes[OC_MODE_INTER_MV].cost){
@@ -2008,7 +2482,7 @@ int oc_enc_analyze_inter(oc_enc_ctx *_enc,int _allow_keyframe,int _recode){
}
mb_gmv_bits_0=oc_cost_inter1mv(_enc,modes+OC_MODE_GOLDEN_MV,mbi,
OC_MODE_GOLDEN_MV,embs[mbi].analysis_mv[0][OC_FRAME_GOLD],
- pipe.fr+0,pipe.qs+0,skip_ssd);
+ _enc->pipe.fr+0,_enc->pipe.qs+0,skip_ssd,rd_scale);
}
if(!(embs[mbi].refined&0x04)){
oc_mcenc_refine1mv(_enc,mbi,OC_FRAME_PREV);
@@ -2016,7 +2490,7 @@ int oc_enc_analyze_inter(oc_enc_ctx *_enc,int _allow_keyframe,int _recode){
}
mb_mv_bits_0=oc_cost_inter1mv(_enc,modes+OC_MODE_INTER_MV,mbi,
OC_MODE_INTER_MV,embs[mbi].analysis_mv[0][OC_FRAME_PREV],
- pipe.fr+0,pipe.qs+0,skip_ssd);
+ _enc->pipe.fr+0,_enc->pipe.qs+0,skip_ssd,rd_scale);
/*Finally, pick the mode with the cheapest estimated R-D cost.*/
mb_mode=OC_MODE_INTER_NOMV;
if(modes[OC_MODE_INTRA].cost<modes[OC_MODE_INTER_NOMV].cost){
@@ -2046,8 +2520,14 @@ int oc_enc_analyze_inter(oc_enc_ctx *_enc,int _allow_keyframe,int _recode){
}
}
else{
+ oc_cost_inter_nomv(_enc,modes+OC_MODE_INTER_NOMV,mbi,
+ OC_MODE_INTER_NOMV,_enc->pipe.fr+0,_enc->pipe.qs+0,
+ skip_ssd,rd_scale);
+ oc_cost_intra(_enc,modes+OC_MODE_INTRA,mbi,
+ _enc->pipe.fr+0,_enc->pipe.qs+0,intra_satd,skip_ssd,rd_scale);
oc_cost_inter_nomv(_enc,modes+OC_MODE_GOLDEN_NOMV,mbi,
- OC_MODE_GOLDEN_NOMV,pipe.fr+0,pipe.qs+0,skip_ssd);
+ OC_MODE_GOLDEN_NOMV,_enc->pipe.fr+0,_enc->pipe.qs+0,
+ skip_ssd,rd_scale);
mb_mode=OC_MODE_INTER_NOMV;
if(modes[OC_MODE_INTRA].cost<modes[OC_MODE_INTER_NOMV].cost){
mb_mode=OC_MODE_INTRA;
@@ -2062,67 +2542,55 @@ int oc_enc_analyze_inter(oc_enc_ctx *_enc,int _allow_keyframe,int _recode){
if(mb_mode!=OC_MODE_INTER_MV_FOUR){
switch(mb_mode){
case OC_MODE_INTER_MV:{
- dx=embs[mbi].analysis_mv[0][OC_FRAME_PREV][0];
- dy=embs[mbi].analysis_mv[0][OC_FRAME_PREV][1];
- }break;
- case OC_MODE_INTER_MV_LAST:{
- dx=last_mv[0];
- dy=last_mv[1];
- }break;
- case OC_MODE_INTER_MV_LAST2:{
- dx=prior_mv[0];
- dy=prior_mv[1];
+ mv=embs[mbi].analysis_mv[0][OC_FRAME_PREV];
}break;
+ case OC_MODE_INTER_MV_LAST:mv=last_mv;break;
+ case OC_MODE_INTER_MV_LAST2:mv=prior_mv;break;
case OC_MODE_GOLDEN_MV:{
- dx=embs[mbi].analysis_mv[0][OC_FRAME_GOLD][0];
- dy=embs[mbi].analysis_mv[0][OC_FRAME_GOLD][1];
+ mv=embs[mbi].analysis_mv[0][OC_FRAME_GOLD];
}break;
}
for(bi=0;bi<4;bi++){
fragi=mb_maps[mbi][0][bi];
- frag_mvs[fragi][0]=(signed char)dx;
- frag_mvs[fragi][1]=(signed char)dy;
+ frag_mvs[fragi]=mv;
}
}
for(bi=0;bi<4;bi++){
fragi=sb_maps[mbi>>2][mbi&3][bi];
frags[fragi].qii=modes[mb_mode].qii[bi];
}
- if(oc_enc_mb_transform_quantize_luma(_enc,&pipe,mbi,
- modes[mb_mode].overhead>>OC_BIT_SCALE)>0){
+ if(oc_enc_mb_transform_quantize_inter_luma(_enc,&_enc->pipe,mbi,
+ modes[mb_mode].overhead>>OC_BIT_SCALE,rd_scale,rd_iscale)>0){
int orig_mb_mode;
orig_mb_mode=mb_mode;
mb_mode=mb_modes[mbi];
+ refi=OC_FRAME_FOR_MODE(mb_mode);
switch(mb_mode){
case OC_MODE_INTER_MV:{
- memcpy(prior_mv,last_mv,sizeof(prior_mv));
+ prior_mv=last_mv;
/*If we're backing out from 4MV, find the MV we're actually
using.*/
if(orig_mb_mode==OC_MODE_INTER_MV_FOUR){
for(bi=0;;bi++){
fragi=mb_maps[mbi][0][bi];
if(frags[fragi].coded){
- memcpy(last_mv,frag_mvs[fragi],sizeof(last_mv));
- dx=frag_mvs[fragi][0];
- dy=frag_mvs[fragi][1];
+ mv=last_mv=frag_mvs[fragi];
break;
}
}
- mb_mv_bits_0=OC_MV_BITS[0][dx+31]+OC_MV_BITS[0][dy+31];
+ mb_mv_bits_0=OC_MV_BITS[0][OC_MV_X(mv)+31]
+ +OC_MV_BITS[0][OC_MV_Y(mv)+31];
}
/*Otherwise we used the original analysis MV.*/
- else{
- memcpy(last_mv,
- embs[mbi].analysis_mv[0][OC_FRAME_PREV],sizeof(last_mv));
- }
+ else last_mv=embs[mbi].analysis_mv[0][OC_FRAME_PREV];
_enc->mv_bits[0]+=mb_mv_bits_0;
_enc->mv_bits[1]+=12;
}break;
case OC_MODE_INTER_MV_LAST2:{
oc_mv tmp_mv;
- memcpy(tmp_mv,prior_mv,sizeof(tmp_mv));
- memcpy(prior_mv,last_mv,sizeof(prior_mv));
- memcpy(last_mv,tmp_mv,sizeof(last_mv));
+ tmp_mv=prior_mv;
+ prior_mv=last_mv;
+ last_mv=tmp_mv;
}break;
case OC_MODE_GOLDEN_MV:{
_enc->mv_bits[0]+=mb_gmv_bits_0;
@@ -2131,28 +2599,28 @@ int oc_enc_analyze_inter(oc_enc_ctx *_enc,int _allow_keyframe,int _recode){
case OC_MODE_INTER_MV_FOUR:{
oc_mv lbmvs[4];
oc_mv cbmvs[4];
- memcpy(prior_mv,last_mv,sizeof(prior_mv));
+ prior_mv=last_mv;
for(bi=0;bi<4;bi++){
fragi=mb_maps[mbi][0][bi];
if(frags[fragi].coded){
- memcpy(last_mv,frag_mvs[fragi],sizeof(last_mv));
- memcpy(lbmvs[bi],frag_mvs[fragi],sizeof(lbmvs[bi]));
- _enc->mv_bits[0]+=OC_MV_BITS[0][frag_mvs[fragi][0]+31]
- +OC_MV_BITS[0][frag_mvs[fragi][1]+31];
+ lbmvs[bi]=last_mv=frag_mvs[fragi];
+ _enc->mv_bits[0]+=OC_MV_BITS[0][OC_MV_X(last_mv)+31]
+ +OC_MV_BITS[0][OC_MV_Y(last_mv)+31];
_enc->mv_bits[1]+=12;
}
/*Replace the block MVs for not-coded blocks with (0,0).*/
- else memset(lbmvs[bi],0,sizeof(lbmvs[bi]));
+ else lbmvs[bi]=0;
}
- (*set_chroma_mvs)(cbmvs,(const oc_mv *)lbmvs);
+ (*set_chroma_mvs)(cbmvs,lbmvs);
for(mapii=4;mapii<nmap_idxs;mapii++){
mapi=map_idxs[mapii];
pli=mapi>>2;
bi=mapi&3;
fragi=mb_maps[mbi][pli][bi];
- frags[fragi].mb_mode=mb_mode;
frags[fragi].qii=modes[OC_MODE_INTER_MV_FOUR].qii[mapii];
- memcpy(frag_mvs[fragi],cbmvs[bi],sizeof(frag_mvs[fragi]));
+ frags[fragi].refi=refi;
+ frags[fragi].mb_mode=mb_mode;
+ frag_mvs[fragi]=cbmvs[bi];
}
}break;
}
@@ -2163,7 +2631,8 @@ int oc_enc_analyze_inter(oc_enc_ctx *_enc,int _allow_keyframe,int _recode){
else{
*(uncoded_mbis-++nuncoded_mbis)=mbi;
mb_mode=OC_MODE_INTER_NOMV;
- dx=dy=0;
+ refi=OC_FRAME_PREV;
+ mv=0;
}
/*Propagate final MB mode and MVs to the chroma blocks.
This has already been done for 4MV mode, since it requires individual
@@ -2174,43 +2643,56 @@ int oc_enc_analyze_inter(oc_enc_ctx *_enc,int _allow_keyframe,int _recode){
pli=mapi>>2;
bi=mapi&3;
fragi=mb_maps[mbi][pli][bi];
- frags[fragi].mb_mode=mb_mode;
/*If we switched from 4MV mode to INTER_MV mode, then the qii
values won't have been chosen with the right MV, but it's
probaby not worth re-estimating them.*/
frags[fragi].qii=modes[mb_mode].qii[mapii];
- frag_mvs[fragi][0]=(signed char)dx;
- frag_mvs[fragi][1]=(signed char)dy;
+ frags[fragi].refi=refi;
+ frags[fragi].mb_mode=mb_mode;
+ frag_mvs[fragi]=mv;
}
}
+ /*Save masking scale factors for chroma blocks.*/
+ for(mapii=4;mapii<(nmap_idxs-4>>1)+4;mapii++){
+ mapi=map_idxs[mapii];
+ bi=mapi&3;
+ fragi=mb_maps[mbi][1][bi];
+ mcu_rd_scale[fragi-cfroffset]=(ogg_uint16_t)rd_scale[4];
+ mcu_rd_iscale[fragi-cfroffset]=(ogg_uint16_t)rd_iscale[4];
+ }
}
- oc_fr_state_flush_sb(pipe.fr+0);
- sb_flags[sbi].coded_fully=pipe.fr[0].sb_full;
- sb_flags[sbi].coded_partially=pipe.fr[0].sb_partial;
+ oc_fr_state_flush_sb(_enc->pipe.fr+0);
+ sb_flags[sbi].coded_fully=_enc->pipe.fr[0].sb_full;
+ sb_flags[sbi].coded_partially=_enc->pipe.fr[0].sb_partial;
}
- oc_enc_pipeline_finish_mcu_plane(_enc,&pipe,0,notstart,notdone);
+ oc_enc_pipeline_finish_mcu_plane(_enc,&_enc->pipe,0,notstart,notdone);
/*Code chroma planes.*/
for(pli=1;pli<3;pli++){
- oc_enc_sb_transform_quantize_chroma(_enc,&pipe,
- pli,pipe.sbi0[pli],pipe.sbi_end[pli]);
- oc_enc_pipeline_finish_mcu_plane(_enc,&pipe,pli,notstart,notdone);
+ oc_enc_sb_transform_quantize_inter_chroma(_enc,&_enc->pipe,
+ pli,_enc->pipe.sbi0[pli],_enc->pipe.sbi_end[pli]);
+ oc_enc_pipeline_finish_mcu_plane(_enc,&_enc->pipe,pli,notstart,notdone);
}
notstart=1;
}
+ /*Update the average block activity and MB luma score for the frame.
+ We could use a Bessel follower here, but fast reaction is probably almost
+ always best.*/
+ _enc->activity_avg=OC_MAXI(OC_ACTIVITY_AVG_MIN,
+ (unsigned)((activity_sum+(_enc->state.fplanes[0].nfrags>>1))/
+ _enc->state.fplanes[0].nfrags));
+ _enc->luma_avg=(unsigned)((luma_sum+(_enc->state.nmbs>>1))/_enc->state.nmbs);
/*Finish filling in the reference frame borders.*/
refi=_enc->state.ref_frame_idx[OC_FRAME_SELF];
for(pli=0;pli<3;pli++)oc_state_borders_fill_caps(&_enc->state,refi,pli);
/*Finish adding flagging overhead costs to inter bit counts to determine if
we should have coded a key frame instead.*/
if(_allow_keyframe){
- if(interbits>intrabits)return 1;
/*Technically the chroma plane counts are over-estimations, because they
don't account for continuing runs from the luma planes, but the
- inaccuracy is small.*/
- for(pli=0;pli<3;pli++)interbits+=pipe.fr[pli].bits<<OC_BIT_SCALE;
- interbits+=OC_MINI(_enc->mv_bits[0],_enc->mv_bits[1])<<OC_BIT_SCALE;
- interbits+=
- _enc->chooser.scheme_bits[_enc->chooser.scheme_list[0]]<<OC_BIT_SCALE;
+ inaccuracy is small.
+ We don't need to add the luma plane coding flag costs, because they are
+ already included in the MB rate estimates.*/
+ for(pli=1;pli<3;pli++)interbits+=_enc->pipe.fr[pli].bits<<OC_BIT_SCALE;
if(interbits>intrabits)return 1;
}
_enc->ncoded_mbis=ncoded_mbis;
@@ -2228,482 +2710,3 @@ int oc_enc_analyze_inter(oc_enc_ctx *_enc,int _allow_keyframe,int _recode){
}
return 0;
}
-
-#if defined(OC_COLLECT_METRICS)
-# include <stdio.h>
-# include <math.h>
-
-/*TODO: It may be helpful (for block-level quantizers especially) to separate
- out the contributions from AC and DC into separate tables.*/
-
-# define OC_ZWEIGHT (0.25)
-
-static void oc_mode_metrics_add(oc_mode_metrics *_metrics,
- double _w,int _satd,int _rate,double _rmse){
- double rate;
- /*Accumulate statistics without the scaling; this lets us change the scale
- factor yet still use old data.*/
- rate=ldexp(_rate,-OC_BIT_SCALE);
- if(_metrics->fragw>0){
- double dsatd;
- double drate;
- double drmse;
- double w;
- dsatd=_satd-_metrics->satd/_metrics->fragw;
- drate=rate-_metrics->rate/_metrics->fragw;
- drmse=_rmse-_metrics->rmse/_metrics->fragw;
- w=_metrics->fragw*_w/(_metrics->fragw+_w);
- _metrics->satd2+=dsatd*dsatd*w;
- _metrics->satdrate+=dsatd*drate*w;
- _metrics->rate2+=drate*drate*w;
- _metrics->satdrmse+=dsatd*drmse*w;
- _metrics->rmse2+=drmse*drmse*w;
- }
- _metrics->fragw+=_w;
- _metrics->satd+=_satd*_w;
- _metrics->rate+=rate*_w;
- _metrics->rmse+=_rmse*_w;
-}
-
-static void oc_mode_metrics_merge(oc_mode_metrics *_dst,
- const oc_mode_metrics *_src,int _n){
- int i;
- /*Find a non-empty set of metrics.*/
- for(i=0;i<_n&&_src[i].fragw<=0;i++);
- if(i>=_n){
- memset(_dst,0,sizeof(*_dst));
- return;
- }
- memcpy(_dst,_src+i,sizeof(*_dst));
- /*And iterate over the remaining non-empty sets of metrics.*/
- for(i++;i<_n;i++)if(_src[i].fragw>0){
- double wa;
- double wb;
- double dsatd;
- double drate;
- double drmse;
- double w;
- wa=_dst->fragw;
- wb=_src[i].fragw;
- dsatd=_src[i].satd/wb-_dst->satd/wa;
- drate=_src[i].rate/wb-_dst->rate/wa;
- drmse=_src[i].rmse/wb-_dst->rmse/wa;
- w=wa*wb/(wa+wb);
- _dst->fragw+=_src[i].fragw;
- _dst->satd+=_src[i].satd;
- _dst->rate+=_src[i].rate;
- _dst->rmse+=_src[i].rmse;
- _dst->satd2+=_src[i].satd2+dsatd*dsatd*w;
- _dst->satdrate+=_src[i].satdrate+dsatd*drate*w;
- _dst->rate2+=_src[i].rate2+drate*drate*w;
- _dst->satdrmse+=_src[i].satdrmse+dsatd*drmse*w;
- _dst->rmse2+=_src[i].rmse2+drmse*drmse*w;
- }
-}
-
-/*Compile collected SATD/rate/RMSE metrics into a form that's immediately
- useful for mode decision.*/
-static void oc_enc_mode_metrics_update(oc_enc_ctx *_enc,int _qi){
- int pli;
- int qti;
- oc_restore_fpu(&_enc->state);
- /*Convert raw collected data into cleaned up sample points.*/
- for(pli=0;pli<3;pli++){
- for(qti=0;qti<2;qti++){
- double fragw;
- int bin0;
- int bin1;
- int bin;
- fragw=0;
- bin0=bin1=0;
- for(bin=0;bin<OC_SAD_BINS;bin++){
- oc_mode_metrics metrics;
- OC_MODE_RD[_qi][pli][qti][bin].rate=0;
- OC_MODE_RD[_qi][pli][qti][bin].rmse=0;
- /*Find some points on either side of the current bin.*/
- while((bin1<bin+1||fragw<OC_ZWEIGHT)&&bin1<OC_SAD_BINS-1){
- fragw+=OC_MODE_METRICS[_qi][pli][qti][bin1++].fragw;
- }
- while(bin0+1<bin&&bin0+1<bin1&&
- fragw-OC_MODE_METRICS[_qi][pli][qti][bin0].fragw>=OC_ZWEIGHT){
- fragw-=OC_MODE_METRICS[_qi][pli][qti][bin0++].fragw;
- }
- /*Merge statistics and fit lines.*/
- oc_mode_metrics_merge(&metrics,
- OC_MODE_METRICS[_qi][pli][qti]+bin0,bin1-bin0);
- if(metrics.fragw>0&&metrics.satd2>0){
- double a;
- double b;
- double msatd;
- double mrate;
- double mrmse;
- double rate;
- double rmse;
- msatd=metrics.satd/metrics.fragw;
- mrate=metrics.rate/metrics.fragw;
- mrmse=metrics.rmse/metrics.fragw;
- /*Compute the points on these lines corresponding to the actual bin
- value.*/
- b=metrics.satdrate/metrics.satd2;
- a=mrate-b*msatd;
- rate=ldexp(a+b*(bin<<OC_SAD_SHIFT),OC_BIT_SCALE);
- OC_MODE_RD[_qi][pli][qti][bin].rate=
- (ogg_int16_t)OC_CLAMPI(-32768,(int)(rate+0.5),32767);
- b=metrics.satdrmse/metrics.satd2;
- a=mrmse-b*msatd;
- rmse=ldexp(a+b*(bin<<OC_SAD_SHIFT),OC_RMSE_SCALE);
- OC_MODE_RD[_qi][pli][qti][bin].rmse=
- (ogg_int16_t)OC_CLAMPI(-32768,(int)(rmse+0.5),32767);
- }
- }
- }
- }
-}
-
-
-
-/*The following token skipping code used to also be used in the decoder (and
- even at one point other places in the encoder).
- However, it was obsoleted by other optimizations, and is now only used here.
- It has been moved here to avoid generating the code when it's not needed.*/
-
-/*Determines the number of blocks or coefficients to be skipped for a given
- token value.
- _token: The token value to skip.
- _extra_bits: The extra bits attached to this token.
- Return: A positive value indicates that number of coefficients are to be
- skipped in the current block.
- Otherwise, the negative of the return value indicates that number of
- blocks are to be ended.*/
-typedef ptrdiff_t (*oc_token_skip_func)(int _token,int _extra_bits);
-
-/*Handles the simple end of block tokens.*/
-static ptrdiff_t oc_token_skip_eob(int _token,int _extra_bits){
- int nblocks_adjust;
- nblocks_adjust=OC_UNIBBLE_TABLE32(0,1,2,3,7,15,0,0,_token)+1;
- return -_extra_bits-nblocks_adjust;
-}
-
-/*The last EOB token has a special case, where an EOB run of size zero ends all
- the remaining blocks in the frame.*/
-static ptrdiff_t oc_token_skip_eob6(int _token,int _extra_bits){
- /*Note: We want to return -PTRDIFF_MAX, but that requires C99, which is not
- yet available everywhere; this should be equivalent.*/
- if(!_extra_bits)return -(~(size_t)0>>1);
- return -_extra_bits;
-}
-
-/*Handles the pure zero run tokens.*/
-static ptrdiff_t oc_token_skip_zrl(int _token,int _extra_bits){
- return _extra_bits+1;
-}
-
-/*Handles a normal coefficient value token.*/
-static ptrdiff_t oc_token_skip_val(void){
- return 1;
-}
-
-/*Handles a category 1A zero run/coefficient value combo token.*/
-static ptrdiff_t oc_token_skip_run_cat1a(int _token){
- return _token-OC_DCT_RUN_CAT1A+2;
-}
-
-/*Handles category 1b, 1c, 2a, and 2b zero run/coefficient value combo tokens.*/
-static ptrdiff_t oc_token_skip_run(int _token,int _extra_bits){
- int run_cati;
- int ncoeffs_mask;
- int ncoeffs_adjust;
- run_cati=_token-OC_DCT_RUN_CAT1B;
- ncoeffs_mask=OC_BYTE_TABLE32(3,7,0,1,run_cati);
- ncoeffs_adjust=OC_BYTE_TABLE32(7,11,2,3,run_cati);
- return (_extra_bits&ncoeffs_mask)+ncoeffs_adjust;
-}
-
-/*A jump table for computing the number of coefficients or blocks to skip for
- a given token value.
- This reduces all the conditional branches, etc., needed to parse these token
- values down to one indirect jump.*/
-static const oc_token_skip_func OC_TOKEN_SKIP_TABLE[TH_NDCT_TOKENS]={
- oc_token_skip_eob,
- oc_token_skip_eob,
- oc_token_skip_eob,
- oc_token_skip_eob,
- oc_token_skip_eob,
- oc_token_skip_eob,
- oc_token_skip_eob6,
- oc_token_skip_zrl,
- oc_token_skip_zrl,
- (oc_token_skip_func)oc_token_skip_val,
- (oc_token_skip_func)oc_token_skip_val,
- (oc_token_skip_func)oc_token_skip_val,
- (oc_token_skip_func)oc_token_skip_val,
- (oc_token_skip_func)oc_token_skip_val,
- (oc_token_skip_func)oc_token_skip_val,
- (oc_token_skip_func)oc_token_skip_val,
- (oc_token_skip_func)oc_token_skip_val,
- (oc_token_skip_func)oc_token_skip_val,
- (oc_token_skip_func)oc_token_skip_val,
- (oc_token_skip_func)oc_token_skip_val,
- (oc_token_skip_func)oc_token_skip_val,
- (oc_token_skip_func)oc_token_skip_val,
- (oc_token_skip_func)oc_token_skip_val,
- (oc_token_skip_func)oc_token_skip_run_cat1a,
- (oc_token_skip_func)oc_token_skip_run_cat1a,
- (oc_token_skip_func)oc_token_skip_run_cat1a,
- (oc_token_skip_func)oc_token_skip_run_cat1a,
- (oc_token_skip_func)oc_token_skip_run_cat1a,
- oc_token_skip_run,
- oc_token_skip_run,
- oc_token_skip_run,
- oc_token_skip_run
-};
-
-/*Determines the number of blocks or coefficients to be skipped for a given
- token value.
- _token: The token value to skip.
- _extra_bits: The extra bits attached to this token.
- Return: A positive value indicates that number of coefficients are to be
- skipped in the current block.
- Otherwise, the negative of the return value indicates that number of
- blocks are to be ended.
- 0 will never be returned, so that at least one coefficient in one
- block will always be decoded for every token.*/
-static ptrdiff_t oc_dct_token_skip(int _token,int _extra_bits){
- return (*OC_TOKEN_SKIP_TABLE[_token])(_token,_extra_bits);
-}
-
-
-
-void oc_enc_mode_metrics_collect(oc_enc_ctx *_enc){
- static const unsigned char OC_ZZI_HUFF_OFFSET[64]={
- 0,16,16,16,16,16,32,32,
- 32,32,32,32,32,32,32,48,
- 48,48,48,48,48,48,48,48,
- 48,48,48,48,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,64
- };
- const oc_fragment *frags;
- const unsigned *frag_satd;
- const unsigned *frag_ssd;
- const ptrdiff_t *coded_fragis;
- ptrdiff_t ncoded_fragis;
- ptrdiff_t fragii;
- double fragw;
- int qti;
- int qii;
- int qi;
- int pli;
- int zzi;
- int token;
- int eb;
- oc_restore_fpu(&_enc->state);
- /*Load any existing mode metrics if we haven't already.*/
- if(!oc_has_mode_metrics){
- FILE *fmetrics;
- memset(OC_MODE_METRICS,0,sizeof(OC_MODE_METRICS));
- fmetrics=fopen("modedec.stats","rb");
- if(fmetrics!=NULL){
- fread(OC_MODE_METRICS,sizeof(OC_MODE_METRICS),1,fmetrics);
- fclose(fmetrics);
- }
- for(qi=0;qi<64;qi++)oc_enc_mode_metrics_update(_enc,qi);
- oc_has_mode_metrics=1;
- }
- qti=_enc->state.frame_type;
- frags=_enc->state.frags;
- frag_satd=_enc->frag_satd;
- frag_ssd=_enc->frag_ssd;
- coded_fragis=_enc->state.coded_fragis;
- ncoded_fragis=fragii=0;
- /*Weight the fragments by the inverse frame size; this prevents HD content
- from dominating the statistics.*/
- fragw=1.0/_enc->state.nfrags;
- for(pli=0;pli<3;pli++){
- ptrdiff_t ti[64];
- int eob_token[64];
- int eob_run[64];
- /*Set up token indices and eob run counts.
- We don't bother trying to figure out the real cost of the runs that span
- coefficients; instead we use the costs that were available when R-D
- token optimization was done.*/
- for(zzi=0;zzi<64;zzi++){
- ti[zzi]=_enc->dct_token_offs[pli][zzi];
- if(ti[zzi]>0){
- token=_enc->dct_tokens[pli][zzi][0];
- eb=_enc->extra_bits[pli][zzi][0];
- eob_token[zzi]=token;
- eob_run[zzi]=-oc_dct_token_skip(token,eb);
- }
- else{
- eob_token[zzi]=OC_NDCT_EOB_TOKEN_MAX;
- eob_run[zzi]=0;
- }
- }
- /*Scan the list of coded fragments for this plane.*/
- ncoded_fragis+=_enc->state.ncoded_fragis[pli];
- for(;fragii<ncoded_fragis;fragii++){
- ptrdiff_t fragi;
- ogg_uint32_t frag_bits;
- int huffi;
- int skip;
- int mb_mode;
- unsigned satd;
- int bin;
- fragi=coded_fragis[fragii];
- frag_bits=0;
- for(zzi=0;zzi<64;){
- if(eob_run[zzi]>0){
- /*We've reached the end of the block.*/
- eob_run[zzi]--;
- break;
- }
- huffi=_enc->huff_idxs[qti][zzi>0][pli+1>>1]
- +OC_ZZI_HUFF_OFFSET[zzi];
- if(eob_token[zzi]<OC_NDCT_EOB_TOKEN_MAX){
- /*This token caused an EOB run to be flushed.
- Therefore it gets the bits associated with it.*/
- frag_bits+=_enc->huff_codes[huffi][eob_token[zzi]].nbits
- +OC_DCT_TOKEN_EXTRA_BITS[eob_token[zzi]];
- eob_token[zzi]=OC_NDCT_EOB_TOKEN_MAX;
- }
- token=_enc->dct_tokens[pli][zzi][ti[zzi]];
- eb=_enc->extra_bits[pli][zzi][ti[zzi]];
- ti[zzi]++;
- skip=oc_dct_token_skip(token,eb);
- if(skip<0){
- eob_token[zzi]=token;
- eob_run[zzi]=-skip;
- }
- else{
- /*A regular DCT value token; accumulate the bits for it.*/
- frag_bits+=_enc->huff_codes[huffi][token].nbits
- +OC_DCT_TOKEN_EXTRA_BITS[token];
- zzi+=skip;
- }
- }
- mb_mode=frags[fragi].mb_mode;
- qi=_enc->state.qis[frags[fragi].qii];
- satd=frag_satd[fragi]<<(pli+1&2);
- bin=OC_MINI(satd>>OC_SAD_SHIFT,OC_SAD_BINS-1);
- oc_mode_metrics_add(OC_MODE_METRICS[qi][pli][mb_mode!=OC_MODE_INTRA]+bin,
- fragw,satd,frag_bits<<OC_BIT_SCALE,sqrt(frag_ssd[fragi]));
- }
- }
- /*Update global SATD/rate/RMSE estimation matrix.*/
- for(qii=0;qii<_enc->state.nqis;qii++){
- oc_enc_mode_metrics_update(_enc,_enc->state.qis[qii]);
- }
-}
-
-void oc_enc_mode_metrics_dump(oc_enc_ctx *_enc){
- FILE *fmetrics;
- int qi;
- /*Generate sample points for complete list of QI values.*/
- for(qi=0;qi<64;qi++)oc_enc_mode_metrics_update(_enc,qi);
- fmetrics=fopen("modedec.stats","wb");
- if(fmetrics!=NULL){
- fwrite(OC_MODE_METRICS,sizeof(OC_MODE_METRICS),1,fmetrics);
- fclose(fmetrics);
- }
- fprintf(stdout,
- "/*File generated by libtheora with OC_COLLECT_METRICS"
- " defined at compile time.*/\n"
- "#if !defined(_modedec_H)\n"
- "# define _modedec_H (1)\n"
- "\n"
- "\n"
- "\n"
- "# if defined(OC_COLLECT_METRICS)\n"
- "typedef struct oc_mode_metrics oc_mode_metrics;\n"
- "# endif\n"
- "typedef struct oc_mode_rd oc_mode_rd;\n"
- "\n"
- "\n"
- "\n"
- "/*The number of extra bits of precision at which to store rate"
- " metrics.*/\n"
- "# define OC_BIT_SCALE (%i)\n"
- "/*The number of extra bits of precision at which to store RMSE metrics.\n"
- " This must be at least half OC_BIT_SCALE (rounded up).*/\n"
- "# define OC_RMSE_SCALE (%i)\n"
- "/*The number of bins to partition statistics into.*/\n"
- "# define OC_SAD_BINS (%i)\n"
- "/*The number of bits of precision to drop"
- " from SAD scores to assign them to a\n"
- " bin.*/\n"
- "# define OC_SAD_SHIFT (%i)\n"
- "\n"
- "\n"
- "\n"
- "# if defined(OC_COLLECT_METRICS)\n"
- "struct oc_mode_metrics{\n"
- " double fragw;\n"
- " double satd;\n"
- " double rate;\n"
- " double rmse;\n"
- " double satd2;\n"
- " double satdrate;\n"
- " double rate2;\n"
- " double satdrmse;\n"
- " double rmse2;\n"
- "};\n"
- "\n"
- "\n"
- "int oc_has_mode_metrics;\n"
- "oc_mode_metrics OC_MODE_METRICS[64][3][2][OC_SAD_BINS];\n"
- "# endif\n"
- "\n"
- "\n"
- "\n"
- "struct oc_mode_rd{\n"
- " ogg_int16_t rate;\n"
- " ogg_int16_t rmse;\n"
- "};\n"
- "\n"
- "\n"
- "# if !defined(OC_COLLECT_METRICS)\n"
- "static const\n"
- "# endif\n"
- "oc_mode_rd OC_MODE_RD[64][3][2][OC_SAD_BINS]={\n",
- OC_BIT_SCALE,OC_RMSE_SCALE,OC_SAD_BINS,OC_SAD_SHIFT);
- for(qi=0;qi<64;qi++){
- int pli;
- fprintf(stdout," {\n");
- for(pli=0;pli<3;pli++){
- int qti;
- fprintf(stdout," {\n");
- for(qti=0;qti<2;qti++){
- int bin;
- static const char *pl_names[3]={"Y'","Cb","Cr"};
- static const char *qti_names[2]={"INTRA","INTER"};
- fprintf(stdout," /*%s qi=%i %s*/\n",
- pl_names[pli],qi,qti_names[qti]);
- fprintf(stdout," {\n");
- fprintf(stdout," ");
- for(bin=0;bin<OC_SAD_BINS;bin++){
- if(bin&&!(bin&0x3))fprintf(stdout,"\n ");
- fprintf(stdout,"{%5i,%5i}",
- OC_MODE_RD[qi][pli][qti][bin].rate,
- OC_MODE_RD[qi][pli][qti][bin].rmse);
- if(bin+1<OC_SAD_BINS)fprintf(stdout,",");
- }
- fprintf(stdout,"\n }");
- if(qti<1)fprintf(stdout,",");
- fprintf(stdout,"\n");
- }
- fprintf(stdout," }");
- if(pli<2)fprintf(stdout,",");
- fprintf(stdout,"\n");
- }
- fprintf(stdout," }");
- if(qi<63)fprintf(stdout,",");
- fprintf(stdout,"\n");
- }
- fprintf(stdout,
- "};\n"
- "\n"
- "#endif\n");
-}
-#endif
diff --git a/thirdparty/libtheora/apiwrapper.c b/thirdparty/libtheora/apiwrapper.c
index dc959b8d13..87b4e939f2 100644
--- a/thirdparty/libtheora/apiwrapper.c
+++ b/thirdparty/libtheora/apiwrapper.c
@@ -11,7 +11,7 @@
********************************************************************
function:
- last mod: $Id: apiwrapper.c 16503 2009-08-22 18:14:02Z giles $
+ last mod: $Id$
********************************************************************/
diff --git a/thirdparty/libtheora/apiwrapper.h b/thirdparty/libtheora/apiwrapper.h
index 93454d7bda..ff45e0a4d6 100644
--- a/thirdparty/libtheora/apiwrapper.h
+++ b/thirdparty/libtheora/apiwrapper.h
@@ -21,7 +21,7 @@
# include <theora/theora.h>
# include "theora/theoradec.h"
# include "theora/theoraenc.h"
-# include "internal.h"
+# include "state.h"
typedef struct th_api_wrapper th_api_wrapper;
typedef struct th_api_info th_api_info;
diff --git a/thirdparty/libtheora/bitpack.c b/thirdparty/libtheora/bitpack.c
index 8195003bad..5125dde6b0 100644
--- a/thirdparty/libtheora/bitpack.c
+++ b/thirdparty/libtheora/bitpack.c
@@ -11,7 +11,7 @@
********************************************************************
function: packing variable sized words into an octet stream
- last mod: $Id: bitpack.c 16503 2009-08-22 18:14:02Z giles $
+ last mod: $Id$
********************************************************************/
#include <string.h>
@@ -32,15 +32,18 @@ static oc_pb_window oc_pack_refill(oc_pack_buf *_b,int _bits){
const unsigned char *stop;
oc_pb_window window;
int available;
+ unsigned shift;
+ stop=_b->stop;
+ ptr=_b->ptr;
window=_b->window;
available=_b->bits;
- ptr=_b->ptr;
- stop=_b->stop;
- while(available<=OC_PB_WINDOW_SIZE-8&&ptr<stop){
- available+=8;
- window|=(oc_pb_window)*ptr++<<OC_PB_WINDOW_SIZE-available;
+ shift=OC_PB_WINDOW_SIZE-available;
+ while(7<shift&&ptr<stop){
+ shift-=8;
+ window|=(oc_pb_window)*ptr++<<shift;
}
_b->ptr=ptr;
+ available=OC_PB_WINDOW_SIZE-shift;
if(_bits>available){
if(ptr>=stop){
_b->eof=1;
@@ -67,7 +70,7 @@ void oc_pack_adv1(oc_pack_buf *_b){
}
/*Here we assume that 0<=_bits&&_bits<=32.*/
-long oc_pack_read(oc_pack_buf *_b,int _bits){
+long oc_pack_read_c(oc_pack_buf *_b,int _bits){
oc_pb_window window;
int available;
long result;
@@ -82,12 +85,12 @@ long oc_pack_read(oc_pack_buf *_b,int _bits){
available-=_bits;
window<<=1;
window<<=_bits-1;
- _b->bits=available;
_b->window=window;
+ _b->bits=available;
return result;
}
-int oc_pack_read1(oc_pack_buf *_b){
+int oc_pack_read1_c(oc_pack_buf *_b){
oc_pb_window window;
int available;
int result;
@@ -100,8 +103,8 @@ int oc_pack_read1(oc_pack_buf *_b){
result=window>>OC_PB_WINDOW_SIZE-1;
available--;
window<<=1;
- _b->bits=available;
_b->window=window;
+ _b->bits=available;
return result;
}
diff --git a/thirdparty/libtheora/bitpack.h b/thirdparty/libtheora/bitpack.h
index a020a292f5..237b584055 100644
--- a/thirdparty/libtheora/bitpack.h
+++ b/thirdparty/libtheora/bitpack.h
@@ -16,15 +16,32 @@
********************************************************************/
#if !defined(_bitpack_H)
# define _bitpack_H (1)
+# include <stddef.h>
# include <limits.h>
+# include "internal.h"
-typedef unsigned long oc_pb_window;
+typedef size_t oc_pb_window;
typedef struct oc_pack_buf oc_pack_buf;
+/*Custom bitpacker implementations.*/
+# if defined(OC_ARM_ASM)
+# include "arm/armbits.h"
+# endif
+
+# if !defined(oc_pack_read)
+# define oc_pack_read oc_pack_read_c
+# endif
+# if !defined(oc_pack_read1)
+# define oc_pack_read1 oc_pack_read1_c
+# endif
+# if !defined(oc_huff_token_decode)
+# define oc_huff_token_decode oc_huff_token_decode_c
+# endif
+
# define OC_PB_WINDOW_SIZE ((int)sizeof(oc_pb_window)*CHAR_BIT)
/*This is meant to be a large, positive constant that can still be efficiently
loaded as an immediate (on platforms like ARM, for example).
@@ -34,9 +51,9 @@ typedef struct oc_pack_buf oc_pack_buf;
struct oc_pack_buf{
- oc_pb_window window;
- const unsigned char *ptr;
const unsigned char *stop;
+ const unsigned char *ptr;
+ oc_pb_window window;
int bits;
int eof;
};
@@ -45,8 +62,8 @@ void oc_pack_readinit(oc_pack_buf *_b,unsigned char *_buf,long _bytes);
int oc_pack_look1(oc_pack_buf *_b);
void oc_pack_adv1(oc_pack_buf *_b);
/*Here we assume 0<=_bits&&_bits<=32.*/
-long oc_pack_read(oc_pack_buf *_b,int _bits);
-int oc_pack_read1(oc_pack_buf *_b);
+long oc_pack_read_c(oc_pack_buf *_b,int _bits);
+int oc_pack_read1_c(oc_pack_buf *_b);
/* returns -1 for read beyond EOF, or the number of whole bytes available */
long oc_pack_bytes_left(oc_pack_buf *_b);
diff --git a/thirdparty/libtheora/collect.c b/thirdparty/libtheora/collect.c
new file mode 100644
index 0000000000..c0d8a2733f
--- /dev/null
+++ b/thirdparty/libtheora/collect.c
@@ -0,0 +1,974 @@
+/********************************************************************
+ * *
+ * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. *
+ * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
+ * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
+ * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
+ * *
+ * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2011 *
+ * by the Xiph.Org Foundation http://www.xiph.org/ *
+ * *
+ ********************************************************************
+
+ function: mode selection code
+ last mod: $Id$
+
+ ********************************************************************/
+#include <stdio.h>
+#include <limits.h>
+#include <math.h>
+#include <string.h>
+#include "collect.h"
+
+#if defined(OC_COLLECT_METRICS)
+
+int OC_HAS_MODE_METRICS;
+double OC_MODE_RD_WEIGHT_SATD[OC_LOGQ_BINS][3][2][OC_COMP_BINS];
+double OC_MODE_RD_WEIGHT_SAD[OC_LOGQ_BINS][3][2][OC_COMP_BINS];
+oc_mode_metrics OC_MODE_METRICS_SATD[OC_LOGQ_BINS-1][3][2][OC_COMP_BINS];
+oc_mode_metrics OC_MODE_METRICS_SAD[OC_LOGQ_BINS-1][3][2][OC_COMP_BINS];
+const char *OC_MODE_METRICS_FILENAME="modedec.stats";
+
+void oc_mode_metrics_add(oc_mode_metrics *_metrics,
+ double _w,int _s,int _q,int _r,double _d){
+ if(_metrics->w>0){
+ double ds;
+ double dq;
+ double dr;
+ double dd;
+ double ds2;
+ double dq2;
+ double s2;
+ double sq;
+ double q2;
+ double sr;
+ double qr;
+ double sd;
+ double qd;
+ double s2q;
+ double sq2;
+ double w;
+ double wa;
+ double rwa;
+ double rwa2;
+ double rwb;
+ double rwb2;
+ double rw2;
+ double rw3;
+ double rw4;
+ wa=_metrics->w;
+ ds=_s-_metrics->s/wa;
+ dq=_q-_metrics->q/wa;
+ dr=_r-_metrics->r/wa;
+ dd=_d-_metrics->d/wa;
+ ds2=ds*ds;
+ dq2=dq*dq;
+ s2=_metrics->s2;
+ sq=_metrics->sq;
+ q2=_metrics->q2;
+ sr=_metrics->sr;
+ qr=_metrics->qr;
+ sd=_metrics->sd;
+ qd=_metrics->qd;
+ s2q=_metrics->s2q;
+ sq2=_metrics->sq2;
+ w=wa+_w;
+ rwa=wa/w;
+ rwb=_w/w;
+ rwa2=rwa*rwa;
+ rwb2=rwb*rwb;
+ rw2=wa*rwb;
+ rw3=rw2*(rwa2-rwb2);
+ rw4=_w*rwa2*rwa2+wa*rwb2*rwb2;
+ _metrics->s2q2+=-2*(ds*sq2+dq*s2q)*rwb
+ +(ds2*q2+4*ds*dq*sq+dq2*s2)*rwb2+ds2*dq2*rw4;
+ _metrics->s2q+=(-2*ds*sq-dq*s2)*rwb+ds2*dq*rw3;
+ _metrics->sq2+=(-ds*q2-2*dq*sq)*rwb+ds*dq2*rw3;
+ _metrics->sqr+=(-ds*qr-dq*sr-dr*sq)*rwb+ds*dq*dr*rw3;
+ _metrics->sqd+=(-ds*qd-dq*sd-dd*sq)*rwb+ds*dq*dd*rw3;
+ _metrics->s2+=ds2*rw2;
+ _metrics->sq+=ds*dq*rw2;
+ _metrics->q2+=dq2*rw2;
+ _metrics->sr+=ds*dr*rw2;
+ _metrics->qr+=dq*dr*rw2;
+ _metrics->r2+=dr*dr*rw2;
+ _metrics->sd+=ds*dd*rw2;
+ _metrics->qd+=dq*dd*rw2;
+ _metrics->d2+=dd*dd*rw2;
+ }
+ _metrics->w+=_w;
+ _metrics->s+=_s*_w;
+ _metrics->q+=_q*_w;
+ _metrics->r+=_r*_w;
+ _metrics->d+=_d*_w;
+}
+
+void oc_mode_metrics_merge(oc_mode_metrics *_dst,
+ const oc_mode_metrics *_src,int _n){
+ int i;
+ /*Find a non-empty set of metrics.*/
+ for(i=0;i<_n&&_src[i].w==0;i++);
+ if(i>=_n){
+ memset(_dst,0,sizeof(*_dst));
+ return;
+ }
+ memcpy(_dst,_src+i,sizeof(*_dst));
+ /*And iterate over the remaining non-empty sets of metrics.*/
+ for(i++;i<_n;i++)if(_src[i].w!=0){
+ double ds;
+ double dq;
+ double dr;
+ double dd;
+ double ds2;
+ double dq2;
+ double s2a;
+ double s2b;
+ double sqa;
+ double sqb;
+ double q2a;
+ double q2b;
+ double sra;
+ double srb;
+ double qra;
+ double qrb;
+ double sda;
+ double sdb;
+ double qda;
+ double qdb;
+ double s2qa;
+ double s2qb;
+ double sq2a;
+ double sq2b;
+ double w;
+ double wa;
+ double wb;
+ double rwa;
+ double rwb;
+ double rwa2;
+ double rwb2;
+ double rw2;
+ double rw3;
+ double rw4;
+ wa=_dst->w;
+ wb=_src[i].w;
+ ds=_src[i].s/wb-_dst->s/wa;
+ dq=_src[i].q/wb-_dst->q/wa;
+ dr=_src[i].r/wb-_dst->r/wa;
+ dd=_src[i].d/wb-_dst->d/wa;
+ ds2=ds*ds;
+ dq2=dq*dq;
+ s2a=_dst->s2;
+ sqa=_dst->sq;
+ q2a=_dst->q2;
+ sra=_dst->sr;
+ qra=_dst->qr;
+ sda=_dst->sd;
+ qda=_dst->qd;
+ s2qa=_dst->s2q;
+ sq2a=_dst->sq2;
+ s2b=_src[i].s2;
+ sqb=_src[i].sq;
+ q2b=_src[i].q2;
+ srb=_src[i].sr;
+ qrb=_src[i].qr;
+ sdb=_src[i].sd;
+ qdb=_src[i].qd;
+ s2qb=_src[i].s2q;
+ sq2b=_src[i].sq2;
+ w=wa+wb;
+ if(w==0)rwa=rwb=0;
+ else{
+ rwa=wa/w;
+ rwb=wb/w;
+ }
+ rwa2=rwa*rwa;
+ rwb2=rwb*rwb;
+ rw2=wa*rwb;
+ rw3=rw2*(rwa2-rwb2);
+ rw4=wb*rwa2*rwa2+wa*rwb2*rwb2;
+ /*
+ (1,1,1) ->
+ (0,0,0)#
+ (1,0,0) C(1,1)*C(1,0)*C(1,0)-> d^{1,0,0}*(rwa*B_{0,1,1}-rwb*A_{0,1,1})
+ (0,1,0) C(1,0)*C(1,1)*C(1,0)-> d^{0,1,0}*(rwa*B_{1,0,1}-rwb*A_{1,0,1})
+ (0,0,1) C(1,0)*C(1,0)*C(1,1)-> d^{0,0,1}*(rwa*B_{1,1,0}-rwb*A_{1,1,0})
+ (1,1,0)*
+ (1,0,1)*
+ (0,1,1)*
+ (1,1,1) C(1,1)*C(1,1)*C(1,1)-> d^{1,1,1}*(rwa^3*wb-rwb^3*wa)
+ (2,1) ->
+ (0,0)#
+ (1,0) C(2,1)*C(1,1)->2*d^{1,0}*(rwa*B_{1,1}-rwb*A_{1,1})
+ (0,1) C(2,0)*C(1,1)-> d^{0,1}*(rwa*B_{2,0}-rwb*A_{2,0})
+ (2,0)*
+ (1,1)*
+ (2,1) C(2,2)*C(1,1)-> d^{2,1}*(rwa^3*wb-rwb^3*wa)
+ (2,2) ->
+ (0,0)#
+ (1,0) C(2,1)*C(2,0)->2*d^{1,0}*(rwa*B_{1,2}-rwb*A_{1,2})
+ (0,1) C(2,0)*C(2,1)->2*d^{0,1}*(rwa*B_{2,1}-rwb*A_{2,1})
+ (2,0) C(2,2)*C(2,0)-> d^{2,0}*(rwa^2*B_{0,2}+rwb^2*A_{0,2})
+ (1,1) C(2,1)*C(2,1)->4*d^{1,1}*(rwa^2*B_{1,1}+rwb^2*A_{1,1})
+ (0,2) C(2,0)*C(2,2)-> d^{0,2}*(rwa^2*B_{2,0}+rwb^2*A_{2,0})
+ (1,2)*
+ (2,1)*
+ (2,2) C(2,2)*C(2,2)*d^{2,2}*(rwa^4*wb+rwb^4*wa)
+ */
+ _dst->s2q2+=_src[i].s2q2+2*(ds*(rwa*sq2b-rwb*sq2a)+dq*(rwa*s2qb-rwb*s2qa))
+ +ds2*(rwa2*q2b+rwb2*q2a)+4*ds*dq*(rwa2*sqb+rwb2*sqa)
+ +dq2*(rwa2*s2b+rwb2*s2a)+ds2*dq2*rw4;
+ _dst->s2q+=_src[i].s2q+2*ds*(rwa*sqb-rwb*sqa)
+ +dq*(rwa*s2b-rwb*s2a)+ds2*dq*rw3;
+ _dst->sq2+=_src[i].sq2+ds*(rwa*q2b-rwb*q2a)
+ +2*dq*(rwa*sqb-rwb*sqa)+ds*dq2*rw3;
+ _dst->sqr+=_src[i].sqr+ds*(rwa*qrb-rwb*qra)+dq*(rwa*srb-rwb*sra)
+ +dr*(rwa*sqb-rwb*sqa)+ds*dq*dr*rw3;
+ _dst->sqd+=_src[i].sqd+ds*(rwa*qdb-rwb*qda)+dq*(rwa*sdb-rwb*sda)
+ +dd*(rwa*sqb-rwb*sqa)+ds*dq*dd*rw3;
+ _dst->s2+=_src[i].s2+ds2*rw2;
+ _dst->sq+=_src[i].sq+ds*dq*rw2;
+ _dst->q2+=_src[i].q2+dq2*rw2;
+ _dst->sr+=_src[i].sr+ds*dr*rw2;
+ _dst->qr+=_src[i].qr+dq*dr*rw2;
+ _dst->r2+=_src[i].r2+dr*dr*rw2;
+ _dst->sd+=_src[i].sd+ds*dd*rw2;
+ _dst->qd+=_src[i].qd+dq*dd*rw2;
+ _dst->d2+=_src[i].d2+dd*dd*rw2;
+ _dst->w+=_src[i].w;
+ _dst->s+=_src[i].s;
+ _dst->q+=_src[i].q;
+ _dst->r+=_src[i].r;
+ _dst->d+=_src[i].d;
+ }
+}
+
+/*Adjust a single corner of a set of metric bins to minimize the squared
+ prediction error of R and D.
+ Each bin is assumed to cover a quad like so:
+ (s0,q0) (s1,q0)
+ A----------B
+ | |
+ | |
+ | |
+ | |
+ C----------Z
+ (s0,q1) (s1,q1)
+ The values A, B, and C are fixed, and Z is the free parameter.
+ Then, for example, R_i is predicted via bilinear interpolation as
+ x_i=(s_i-s0)/(s1-s0)
+ y_i=(q_i-q0)/(q1-q0)
+ dRds1_i=A+(B-A)*x_i
+ dRds2_i=C+(Z-C)*x_i
+ R_i=dRds1_i+(dRds2_i-dRds1_i)*y_i
+ To find the Z that minimizes the squared prediction error over i, this can
+ be rewritten as
+ R_i-(A+(B-A)*x_i+(C-A)*y_i+(A-B-C)*x_i*y_i)=x_i*y_i*Z
+ Letting X={...,x_i*y_i,...}^T and
+ Y={...,R_i-(A+(B-A)*x_i+(C-A)*y_i+(A-B-C)*x_i*y_i),...}^T,
+ the optimal Z is given by Z=(X^T.Y)/(X^T.X).
+ Now, we need to compute these dot products without actually storing data for
+ each sample.
+ Starting with X^T.X, we have
+ X^T.X = sum(x_i^2*y_i^2) = sum((s_i-s0)^2*(q_i-q0)^2)/((s1-s0)^2*(q1-q0)^2).
+ Expanding the interior of the sum in a monomial basis of s_i and q_i gives
+ s0^2*q0^2 *(1)
+ -2*s0*q0^2*(s_i)
+ -2*s0^2*q0*(q_i)
+ +q0^2 *(s_i^2)
+ +4*s0*q0 *(s_i*q_i)
+ +s0^2 *(q_i^2)
+ -2*q0 *(s_i^2*q_i)
+ -2*s0 *(s_i*q_i^2)
+ +1 *(s_i^2*q_i^2).
+ However, computing things directly in this basis leads to gross numerical
+ errors, as most of the terms will have similar size and destructive
+ cancellation results.
+ A much better basis is the central (co-)moment basis:
+ {1,s_i-sbar,q_i-qbar,(s_i-sbar)^2,(s_i-sbar)*(q_i-qbar),(q_i-qbar)^2,
+ (s_i-sbar)^2*(q_i-qbar),(s_i-sbar)*(q_i-qbar)^2,(s_i-sbar)^2*(q_i-qbar)^2},
+ where sbar and qbar are the average s and q values over the bin,
+ respectively.
+ In that basis, letting ds=sbar-s0 and dq=qbar-q0, (s_i-s0)^2*(q_i-q0)^2 is
+ ds^2*dq^2*(1)
+ +dq^2 *((s_i-sbar)^2)
+ +4*ds*dq*((s_i-sbar)*(q_i-qbar))
+ +ds^2 *((q_i-qbar)^2)
+ +2*dq *((s_i-sbar)^2*(q_i-qbar))
+ +2*ds *((s_i-sbar)*(q_i-qbar)^2)
+ +1 *((s_i-sbar)^2*(q_i-qbar)^2).
+ With these expressions in the central (co-)moment bases, all we need to do
+ is compute sums over the (co-)moment terms, which can be done
+ incrementally (see oc_mode_metrics_add() and oc_mode_metrics_merge()),
+ with no need to store the individual samples.
+ Now, for X^T.Y, we have
+ X^T.Y = sum((R_i-A-((B-A)/(s1-s0))*(s_i-s0)-((C-A)/(q1-q0))*(q_i-q0)
+ -((A-B-C)/((s1-s0)*(q1-q0)))*(s_i-s0)*(q_i-q0))*(s_i-s0)*(q_i-q0))/
+ ((s1-s0)*(q1-q0)),
+ or, rewriting the constants to simplify notation,
+ X^T.Y = sum((C0+C1*(s_i-s0)+C2*(q_i-q0)
+ +C3*(s_i-s0)*(q_i-q0)+R_i)*(s_i-s0)*(q_i-q0))/((s1-s0)*(q1-q0)).
+ Again, converting to the central (co-)moment basis, the interior of the
+ above sum is
+ ds*dq*(rbar+C0+C1*ds+C2*dq+C3*ds*dq) *(1)
+ +(C1*dq+C3*dq^2) *((s_i-sbar)^2)
+ +(rbar+C0+2*C1*ds+2*C2*dq+4*C3*ds*dq)*((s_i-sbar)*(q_i-qbar))
+ +(C2*ds+C3*ds^2) *((q_i-qbar)^2)
+ +dq *((s_i-sbar)*(r_i-rbar))
+ +ds *((q_i-qbar)*(r_i-rbar))
+ +(C1+2*C3*dq) *((s_i-sbar)^2*(q_i-qbar))
+ +(C2+2*C3*ds) *((s_i-sbar)*(q_i-qbar)^2)
+ +1 *((s_i-sbar)*(q_i-qbar)*(r_i-rbar))
+ +C3 *((s_i-sbar)^2*(q_i-qbar)^2).
+ You might think it would be easier (if perhaps slightly less robust) to
+ accumulate terms directly around s0 and q0.
+ However, we update each corner of the bins in turn, so we would have to
+ change basis to move the sums from corner to corner anyway.*/
+double oc_mode_metrics_solve(double *_r,double *_d,
+ const oc_mode_metrics *_metrics,const int *_s0,const int *_s1,
+ const int *_q0,const int *_q1,
+ const double *_ra,const double *_rb,const double *_rc,
+ const double *_da,const double *_db,const double *_dc,int _n){
+ double xx;
+ double rxy;
+ double dxy;
+ double wt;
+ int i;
+ xx=rxy=dxy=wt=0;
+ for(i=0;i<_n;i++)if(_metrics[i].w>0){
+ double s10;
+ double q10;
+ double sq10;
+ double ds;
+ double dq;
+ double ds2;
+ double dq2;
+ double r;
+ double d;
+ double s2;
+ double sq;
+ double q2;
+ double sr;
+ double qr;
+ double sd;
+ double qd;
+ double s2q;
+ double sq2;
+ double sqr;
+ double sqd;
+ double s2q2;
+ double c0;
+ double c1;
+ double c2;
+ double c3;
+ double w;
+ w=_metrics[i].w;
+ wt+=w;
+ s10=_s1[i]-_s0[i];
+ q10=_q1[i]-_q0[i];
+ sq10=s10*q10;
+ ds=_metrics[i].s/w-_s0[i];
+ dq=_metrics[i].q/w-_q0[i];
+ ds2=ds*ds;
+ dq2=dq*dq;
+ s2=_metrics[i].s2;
+ sq=_metrics[i].sq;
+ q2=_metrics[i].q2;
+ s2q=_metrics[i].s2q;
+ sq2=_metrics[i].sq2;
+ s2q2=_metrics[i].s2q2;
+ xx+=(dq2*(ds2*w+s2)+4*ds*dq*sq+ds2*q2+2*(dq*s2q+ds*sq2)+s2q2)/(sq10*sq10);
+ r=_metrics[i].r/w;
+ sr=_metrics[i].sr;
+ qr=_metrics[i].qr;
+ sqr=_metrics[i].sqr;
+ c0=-_ra[i];
+ c1=-(_rb[i]-_ra[i])/s10;
+ c2=-(_rc[i]-_ra[i])/q10;
+ c3=-(_ra[i]-_rb[i]-_rc[i])/sq10;
+ rxy+=(ds*dq*(r+c0+c1*ds+c2*dq+c3*ds*dq)*w+(c1*dq+c3*dq2)*s2
+ +(r+c0+2*(c1*ds+(c2+2*c3*ds)*dq))*sq+(c2*ds+c3*ds2)*q2+dq*sr+ds*qr
+ +(c1+2*c3*dq)*s2q+(c2+2*c3*ds)*sq2+sqr+c3*s2q2)/sq10;
+ d=_metrics[i].d/w;
+ sd=_metrics[i].sd;
+ qd=_metrics[i].qd;
+ sqd=_metrics[i].sqd;
+ c0=-_da[i];
+ c1=-(_db[i]-_da[i])/s10;
+ c2=-(_dc[i]-_da[i])/q10;
+ c3=-(_da[i]-_db[i]-_dc[i])/sq10;
+ dxy+=(ds*dq*(d+c0+c1*ds+c2*dq+c3*ds*dq)*w+(c1*dq+c3*dq2)*s2
+ +(d+c0+2*(c1*ds+(c2+2*c3*ds)*dq))*sq+(c2*ds+c3*ds2)*q2+dq*sd+ds*qd
+ +(c1+2*c3*dq)*s2q+(c2+2*c3*ds)*sq2+sqd+c3*s2q2)/sq10;
+ }
+ if(xx>1E-3){
+ *_r=rxy/xx;
+ *_d=dxy/xx;
+ }
+ else{
+ *_r=0;
+ *_d=0;
+ }
+ return wt;
+}
+
+/*Compile collected SATD/logq/rate/RMSE metrics into a form that's immediately
+ useful for mode decision.*/
+void oc_mode_metrics_update(oc_mode_metrics (*_metrics)[3][2][OC_COMP_BINS],
+ int _niters_min,int _reweight,oc_mode_rd (*_table)[3][2][OC_COMP_BINS],
+ int _shift,double (*_weight)[3][2][OC_COMP_BINS]){
+ int niters;
+ int prevdr;
+ int prevdd;
+ int dr;
+ int dd;
+ int pli;
+ int qti;
+ int qi;
+ int si;
+ dd=dr=INT_MAX;
+ niters=0;
+ /*The encoder interpolates rate and RMSE terms bilinearly from an
+ OC_LOGQ_BINS by OC_COMP_BINS grid of sample points in _table.
+ To find the sample values at the grid points that minimize the total
+ squared prediction error actually requires solving a relatively sparse
+ linear system with a number of variables equal to the number of grid
+ points.
+ Instead of writing a general sparse linear system solver, we just use
+ Gauss-Seidel iteration, i.e., we update one grid point at time until
+ they stop changing.*/
+ do{
+ prevdr=dr;
+ prevdd=dd;
+ dd=dr=0;
+ for(pli=0;pli<3;pli++){
+ for(qti=0;qti<2;qti++){
+ for(qi=0;qi<OC_LOGQ_BINS;qi++){
+ for(si=0;si<OC_COMP_BINS;si++){
+ oc_mode_metrics m[4];
+ int s0[4];
+ int s1[4];
+ int q0[4];
+ int q1[4];
+ double ra[4];
+ double rb[4];
+ double rc[4];
+ double da[4];
+ double db[4];
+ double dc[4];
+ double r;
+ double d;
+ int rate;
+ int rmse;
+ int ds;
+ int n;
+ n=0;
+ /*Collect the statistics for the (up to) four bins grid point
+ (si,qi) touches.*/
+ if(qi>0&&si>0){
+ q0[n]=OC_MODE_LOGQ[qi-1][pli][qti];
+ q1[n]=OC_MODE_LOGQ[qi][pli][qti];
+ s0[n]=si-1<<_shift;
+ s1[n]=si<<_shift;
+ ra[n]=ldexp(_table[qi-1][pli][qti][si-1].rate,-OC_BIT_SCALE);
+ da[n]=ldexp(_table[qi-1][pli][qti][si-1].rmse,-OC_RMSE_SCALE);
+ rb[n]=ldexp(_table[qi-1][pli][qti][si].rate,-OC_BIT_SCALE);
+ db[n]=ldexp(_table[qi-1][pli][qti][si].rmse,-OC_RMSE_SCALE);
+ rc[n]=ldexp(_table[qi][pli][qti][si-1].rate,-OC_BIT_SCALE);
+ dc[n]=ldexp(_table[qi][pli][qti][si-1].rmse,-OC_RMSE_SCALE);
+ *(m+n++)=*(_metrics[qi-1][pli][qti]+si-1);
+ }
+ if(qi>0){
+ ds=si+1<OC_COMP_BINS?1:-1;
+ q0[n]=OC_MODE_LOGQ[qi-1][pli][qti];
+ q1[n]=OC_MODE_LOGQ[qi][pli][qti];
+ s0[n]=si+ds<<_shift;
+ s1[n]=si<<_shift;
+ ra[n]=ldexp(_table[qi-1][pli][qti][si+ds].rate,-OC_BIT_SCALE);
+ da[n]=
+ ldexp(_table[qi-1][pli][qti][si+ds].rmse,-OC_RMSE_SCALE);
+ rb[n]=ldexp(_table[qi-1][pli][qti][si].rate,-OC_BIT_SCALE);
+ db[n]=ldexp(_table[qi-1][pli][qti][si].rmse,-OC_RMSE_SCALE);
+ rc[n]=ldexp(_table[qi][pli][qti][si+ds].rate,-OC_BIT_SCALE);
+ dc[n]=ldexp(_table[qi][pli][qti][si+ds].rmse,-OC_RMSE_SCALE);
+ *(m+n++)=*(_metrics[qi-1][pli][qti]+si);
+ }
+ if(qi+1<OC_LOGQ_BINS&&si>0){
+ q0[n]=OC_MODE_LOGQ[qi+1][pli][qti];
+ q1[n]=OC_MODE_LOGQ[qi][pli][qti];
+ s0[n]=si-1<<_shift;
+ s1[n]=si<<_shift;
+ ra[n]=ldexp(_table[qi+1][pli][qti][si-1].rate,-OC_BIT_SCALE);
+ da[n]=ldexp(_table[qi+1][pli][qti][si-1].rmse,-OC_RMSE_SCALE);
+ rb[n]=ldexp(_table[qi+1][pli][qti][si].rate,-OC_BIT_SCALE);
+ db[n]=ldexp(_table[qi+1][pli][qti][si].rmse,-OC_RMSE_SCALE);
+ rc[n]=ldexp(_table[qi][pli][qti][si-1].rate,-OC_BIT_SCALE);
+ dc[n]=ldexp(_table[qi][pli][qti][si-1].rmse,-OC_RMSE_SCALE);
+ *(m+n++)=*(_metrics[qi][pli][qti]+si-1);
+ }
+ if(qi+1<OC_LOGQ_BINS){
+ ds=si+1<OC_COMP_BINS?1:-1;
+ q0[n]=OC_MODE_LOGQ[qi+1][pli][qti];
+ q1[n]=OC_MODE_LOGQ[qi][pli][qti];
+ s0[n]=si+ds<<_shift;
+ s1[n]=si<<_shift;
+ ra[n]=ldexp(_table[qi+1][pli][qti][si+ds].rate,-OC_BIT_SCALE);
+ da[n]=
+ ldexp(_table[qi+1][pli][qti][si+ds].rmse,-OC_RMSE_SCALE);
+ rb[n]=ldexp(_table[qi+1][pli][qti][si].rate,-OC_BIT_SCALE);
+ db[n]=ldexp(_table[qi+1][pli][qti][si].rmse,-OC_RMSE_SCALE);
+ rc[n]=ldexp(_table[qi][pli][qti][si+ds].rate,-OC_BIT_SCALE);
+ dc[n]=ldexp(_table[qi][pli][qti][si+ds].rmse,-OC_RMSE_SCALE);
+ *(m+n++)=*(_metrics[qi][pli][qti]+si);
+ }
+ /*On the first pass, initialize with a simple weighted average of
+ the neighboring bins.*/
+ if(!OC_HAS_MODE_METRICS&&niters==0){
+ double w;
+ w=r=d=0;
+ while(n-->0){
+ w+=m[n].w;
+ r+=m[n].r;
+ d+=m[n].d;
+ }
+ r=w>1E-3?r/w:0;
+ d=w>1E-3?d/w:0;
+ _weight[qi][pli][qti][si]=w;
+ }
+ else{
+ /*Update the grid point and save the weight for later.*/
+ _weight[qi][pli][qti][si]=
+ oc_mode_metrics_solve(&r,&d,m,s0,s1,q0,q1,ra,rb,rc,da,db,dc,n);
+ }
+ rate=OC_CLAMPI(-32768,(int)(ldexp(r,OC_BIT_SCALE)+0.5),32767);
+ rmse=OC_CLAMPI(-32768,(int)(ldexp(d,OC_RMSE_SCALE)+0.5),32767);
+ dr+=abs(rate-_table[qi][pli][qti][si].rate);
+ dd+=abs(rmse-_table[qi][pli][qti][si].rmse);
+ _table[qi][pli][qti][si].rate=(ogg_int16_t)rate;
+ _table[qi][pli][qti][si].rmse=(ogg_int16_t)rmse;
+ }
+ }
+ }
+ }
+ }
+ /*After a fixed number of initial iterations, only iterate so long as the
+ total change is decreasing.
+ This ensures we don't oscillate forever, which is a danger, as all of our
+ results are rounded fairly coarsely.*/
+ while((dr>0||dd>0)&&(niters++<_niters_min||(dr<prevdr&&dd<prevdd)));
+ if(_reweight){
+ /*Now, reduce the values of the optimal solution until we get enough
+ samples in each bin to overcome the constant OC_ZWEIGHT factor.
+ This encourages sampling under-populated bins and prevents a single large
+ sample early on from discouraging coding in that bin ever again.*/
+ for(pli=0;pli<3;pli++){
+ for(qti=0;qti<2;qti++){
+ for(qi=0;qi<OC_LOGQ_BINS;qi++){
+ for(si=0;si<OC_COMP_BINS;si++){
+ double wt;
+ wt=_weight[qi][pli][qti][si];
+ wt/=OC_ZWEIGHT+wt;
+ _table[qi][pli][qti][si].rate=(ogg_int16_t)
+ (_table[qi][pli][qti][si].rate*wt+0.5);
+ _table[qi][pli][qti][si].rmse=(ogg_int16_t)
+ (_table[qi][pli][qti][si].rmse*wt+0.5);
+ }
+ }
+ }
+ }
+ }
+}
+
+/*Dump the in memory mode metrics to a file.
+ Note this data format isn't portable between different platforms.*/
+void oc_mode_metrics_dump(void){
+ FILE *fmetrics;
+ fmetrics=fopen(OC_MODE_METRICS_FILENAME,"wb");
+ if(fmetrics!=NULL){
+ (void)fwrite(OC_MODE_LOGQ,sizeof(OC_MODE_LOGQ),1,fmetrics);
+ (void)fwrite(OC_MODE_METRICS_SATD,sizeof(OC_MODE_METRICS_SATD),1,fmetrics);
+ (void)fwrite(OC_MODE_METRICS_SAD,sizeof(OC_MODE_METRICS_SAD),1,fmetrics);
+ fclose(fmetrics);
+ }
+}
+
+void oc_mode_metrics_print_rd(FILE *_fout,const char *_table_name,
+#if !defined(OC_COLLECT_METRICS)
+ const oc_mode_rd (*_mode_rd_table)[3][2][OC_COMP_BINS]){
+#else
+ oc_mode_rd (*_mode_rd_table)[3][2][OC_COMP_BINS]){
+#endif
+ int qii;
+ fprintf(_fout,
+ "# if !defined(OC_COLLECT_METRICS)\n"
+ "static const\n"
+ "# endif\n"
+ "oc_mode_rd %s[OC_LOGQ_BINS][3][2][OC_COMP_BINS]={\n",_table_name);
+ for(qii=0;qii<OC_LOGQ_BINS;qii++){
+ int pli;
+ fprintf(_fout," {\n");
+ for(pli=0;pli<3;pli++){
+ int qti;
+ fprintf(_fout," {\n");
+ for(qti=0;qti<2;qti++){
+ int bin;
+ int qi;
+ static const char *pl_names[3]={"Y'","Cb","Cr"};
+ static const char *qti_names[2]={"INTRA","INTER"};
+ qi=(63*qii+(OC_LOGQ_BINS-1>>1))/(OC_LOGQ_BINS-1);
+ fprintf(_fout," /*%s qi=%i %s*/\n",
+ pl_names[pli],qi,qti_names[qti]);
+ fprintf(_fout," {\n");
+ fprintf(_fout," ");
+ for(bin=0;bin<OC_COMP_BINS;bin++){
+ if(bin&&!(bin&0x3))fprintf(_fout,"\n ");
+ fprintf(_fout,"{%5i,%5i}",
+ _mode_rd_table[qii][pli][qti][bin].rate,
+ _mode_rd_table[qii][pli][qti][bin].rmse);
+ if(bin+1<OC_COMP_BINS)fprintf(_fout,",");
+ }
+ fprintf(_fout,"\n }");
+ if(qti<1)fprintf(_fout,",");
+ fprintf(_fout,"\n");
+ }
+ fprintf(_fout," }");
+ if(pli<2)fprintf(_fout,",");
+ fprintf(_fout,"\n");
+ }
+ fprintf(_fout," }");
+ if(qii+1<OC_LOGQ_BINS)fprintf(_fout,",");
+ fprintf(_fout,"\n");
+ }
+ fprintf(_fout,
+ "};\n"
+ "\n");
+}
+
+void oc_mode_metrics_print(FILE *_fout){
+ int qii;
+ fprintf(_fout,
+ "/*File generated by libtheora with OC_COLLECT_METRICS"
+ " defined at compile time.*/\n"
+ "#if !defined(_modedec_H)\n"
+ "# define _modedec_H (1)\n"
+ "# include \"encint.h\"\n"
+ "\n"
+ "\n"
+ "\n"
+ "/*The log of the average quantizer for each of the OC_MODE_RD table rows\n"
+ " (e.g., for the represented qi's, and each pli and qti), in Q10 format.\n"
+ " The actual statistics used by the encoder will be interpolated from\n"
+ " that table based on log_plq for the actual quantization matrix used.*/\n"
+ "# if !defined(OC_COLLECT_METRICS)\n"
+ "static const\n"
+ "# endif\n"
+ "ogg_int16_t OC_MODE_LOGQ[OC_LOGQ_BINS][3][2]={\n");
+ for(qii=0;qii<OC_LOGQ_BINS;qii++){
+ fprintf(_fout," { {0x%04X,0x%04X},{0x%04X,0x%04X},{0x%04X,0x%04X} }%s\n",
+ OC_MODE_LOGQ[qii][0][0],OC_MODE_LOGQ[qii][0][1],OC_MODE_LOGQ[qii][1][0],
+ OC_MODE_LOGQ[qii][1][1],OC_MODE_LOGQ[qii][2][0],OC_MODE_LOGQ[qii][2][1],
+ qii+1<OC_LOGQ_BINS?",":"");
+ }
+ fprintf(_fout,
+ "};\n"
+ "\n");
+ oc_mode_metrics_print_rd(_fout,"OC_MODE_RD_SATD",OC_MODE_RD_SATD);
+ oc_mode_metrics_print_rd(_fout,"OC_MODE_RD_SAD",OC_MODE_RD_SAD);
+ fprintf(_fout,
+ "#endif\n");
+}
+
+
+# if !defined(OC_COLLECT_NO_ENC_FUNCS)
+void oc_enc_mode_metrics_load(oc_enc_ctx *_enc){
+ oc_restore_fpu(&_enc->state);
+ /*Load any existing mode metrics if we haven't already.*/
+ if(!OC_HAS_MODE_METRICS){
+ FILE *fmetrics;
+ memset(OC_MODE_METRICS_SATD,0,sizeof(OC_MODE_METRICS_SATD));
+ memset(OC_MODE_METRICS_SAD,0,sizeof(OC_MODE_METRICS_SAD));
+ fmetrics=fopen(OC_MODE_METRICS_FILENAME,"rb");
+ if(fmetrics!=NULL){
+ /*Read in the binary structures as written my oc_mode_metrics_dump().
+ Note this format isn't portable between different platforms.*/
+ (void)fread(OC_MODE_LOGQ,sizeof(OC_MODE_LOGQ),1,fmetrics);
+ (void)fread(OC_MODE_METRICS_SATD,sizeof(OC_MODE_METRICS_SATD),1,fmetrics);
+ (void)fread(OC_MODE_METRICS_SAD,sizeof(OC_MODE_METRICS_SAD),1,fmetrics);
+ fclose(fmetrics);
+ }
+ else{
+ int qii;
+ int qi;
+ int pli;
+ int qti;
+ for(qii=0;qii<OC_LOGQ_BINS;qii++){
+ qi=(63*qii+(OC_LOGQ_BINS-1>>1))/(OC_LOGQ_BINS-1);
+ for(pli=0;pli<3;pli++)for(qti=0;qti<2;qti++){
+ OC_MODE_LOGQ[qii][pli][qti]=_enc->log_plq[qi][pli][qti];
+ }
+ }
+ }
+ oc_mode_metrics_update(OC_MODE_METRICS_SATD,100,1,
+ OC_MODE_RD_SATD,OC_SATD_SHIFT,OC_MODE_RD_WEIGHT_SATD);
+ oc_mode_metrics_update(OC_MODE_METRICS_SAD,100,1,
+ OC_MODE_RD_SAD,OC_SAD_SHIFT,OC_MODE_RD_WEIGHT_SAD);
+ OC_HAS_MODE_METRICS=1;
+ }
+}
+
+/*The following token skipping code used to also be used in the decoder (and
+ even at one point other places in the encoder).
+ However, it was obsoleted by other optimizations, and is now only used here.
+ It has been moved here to avoid generating the code when it's not needed.*/
+
+/*Determines the number of blocks or coefficients to be skipped for a given
+ token value.
+ _token: The token value to skip.
+ _extra_bits: The extra bits attached to this token.
+ Return: A positive value indicates that number of coefficients are to be
+ skipped in the current block.
+ Otherwise, the negative of the return value indicates that number of
+ blocks are to be ended.*/
+typedef ptrdiff_t (*oc_token_skip_func)(int _token,int _extra_bits);
+
+/*Handles the simple end of block tokens.*/
+static ptrdiff_t oc_token_skip_eob(int _token,int _extra_bits){
+ int nblocks_adjust;
+ nblocks_adjust=OC_UNIBBLE_TABLE32(0,1,2,3,7,15,0,0,_token)+1;
+ return -_extra_bits-nblocks_adjust;
+}
+
+/*The last EOB token has a special case, where an EOB run of size zero ends all
+ the remaining blocks in the frame.*/
+static ptrdiff_t oc_token_skip_eob6(int _token,int _extra_bits){
+ /*Note: We want to return -PTRDIFF_MAX, but that requires C99, which is not
+ yet available everywhere; this should be equivalent.*/
+ if(!_extra_bits)return -(~(size_t)0>>1);
+ return -_extra_bits;
+}
+
+/*Handles the pure zero run tokens.*/
+static ptrdiff_t oc_token_skip_zrl(int _token,int _extra_bits){
+ return _extra_bits+1;
+}
+
+/*Handles a normal coefficient value token.*/
+static ptrdiff_t oc_token_skip_val(void){
+ return 1;
+}
+
+/*Handles a category 1A zero run/coefficient value combo token.*/
+static ptrdiff_t oc_token_skip_run_cat1a(int _token){
+ return _token-OC_DCT_RUN_CAT1A+2;
+}
+
+/*Handles category 1b, 1c, 2a, and 2b zero run/coefficient value combo tokens.*/
+static ptrdiff_t oc_token_skip_run(int _token,int _extra_bits){
+ int run_cati;
+ int ncoeffs_mask;
+ int ncoeffs_adjust;
+ run_cati=_token-OC_DCT_RUN_CAT1B;
+ ncoeffs_mask=OC_BYTE_TABLE32(3,7,0,1,run_cati);
+ ncoeffs_adjust=OC_BYTE_TABLE32(7,11,2,3,run_cati);
+ return (_extra_bits&ncoeffs_mask)+ncoeffs_adjust;
+}
+
+/*A jump table for computing the number of coefficients or blocks to skip for
+ a given token value.
+ This reduces all the conditional branches, etc., needed to parse these token
+ values down to one indirect jump.*/
+static const oc_token_skip_func OC_TOKEN_SKIP_TABLE[TH_NDCT_TOKENS]={
+ oc_token_skip_eob,
+ oc_token_skip_eob,
+ oc_token_skip_eob,
+ oc_token_skip_eob,
+ oc_token_skip_eob,
+ oc_token_skip_eob,
+ oc_token_skip_eob6,
+ oc_token_skip_zrl,
+ oc_token_skip_zrl,
+ (oc_token_skip_func)oc_token_skip_val,
+ (oc_token_skip_func)oc_token_skip_val,
+ (oc_token_skip_func)oc_token_skip_val,
+ (oc_token_skip_func)oc_token_skip_val,
+ (oc_token_skip_func)oc_token_skip_val,
+ (oc_token_skip_func)oc_token_skip_val,
+ (oc_token_skip_func)oc_token_skip_val,
+ (oc_token_skip_func)oc_token_skip_val,
+ (oc_token_skip_func)oc_token_skip_val,
+ (oc_token_skip_func)oc_token_skip_val,
+ (oc_token_skip_func)oc_token_skip_val,
+ (oc_token_skip_func)oc_token_skip_val,
+ (oc_token_skip_func)oc_token_skip_val,
+ (oc_token_skip_func)oc_token_skip_val,
+ (oc_token_skip_func)oc_token_skip_run_cat1a,
+ (oc_token_skip_func)oc_token_skip_run_cat1a,
+ (oc_token_skip_func)oc_token_skip_run_cat1a,
+ (oc_token_skip_func)oc_token_skip_run_cat1a,
+ (oc_token_skip_func)oc_token_skip_run_cat1a,
+ oc_token_skip_run,
+ oc_token_skip_run,
+ oc_token_skip_run,
+ oc_token_skip_run
+};
+
+/*Determines the number of blocks or coefficients to be skipped for a given
+ token value.
+ _token: The token value to skip.
+ _extra_bits: The extra bits attached to this token.
+ Return: A positive value indicates that number of coefficients are to be
+ skipped in the current block.
+ Otherwise, the negative of the return value indicates that number of
+ blocks are to be ended.
+ 0 will never be returned, so that at least one coefficient in one
+ block will always be decoded for every token.*/
+static ptrdiff_t oc_dct_token_skip(int _token,int _extra_bits){
+ return (*OC_TOKEN_SKIP_TABLE[_token])(_token,_extra_bits);
+}
+
+
+void oc_enc_mode_metrics_collect(oc_enc_ctx *_enc){
+ static const unsigned char OC_ZZI_HUFF_OFFSET[64]={
+ 0,16,16,16,16,16,32,32,
+ 32,32,32,32,32,32,32,48,
+ 48,48,48,48,48,48,48,48,
+ 48,48,48,48,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,64
+ };
+ const oc_fragment *frags;
+ const unsigned *frag_sad;
+ const unsigned *frag_satd;
+ const unsigned *frag_ssd;
+ const ptrdiff_t *coded_fragis;
+ ptrdiff_t ncoded_fragis;
+ ptrdiff_t fragii;
+ double fragw;
+ int modelines[3][3][2];
+ int qti;
+ int qii;
+ int qi;
+ int pli;
+ int zzi;
+ int token;
+ int eb;
+ oc_restore_fpu(&_enc->state);
+ /*Figure out which metric bins to use for this frame's quantizers.*/
+ for(qii=0;qii<_enc->state.nqis;qii++){
+ for(pli=0;pli<3;pli++){
+ for(qti=0;qti<2;qti++){
+ int log_plq;
+ int modeline;
+ log_plq=_enc->log_plq[_enc->state.qis[qii]][pli][qti];
+ for(modeline=0;modeline<OC_LOGQ_BINS-1&&
+ OC_MODE_LOGQ[modeline+1][pli][qti]>log_plq;modeline++);
+ modelines[qii][pli][qti]=modeline;
+ }
+ }
+ }
+ qti=_enc->state.frame_type;
+ frags=_enc->state.frags;
+ frag_sad=_enc->frag_sad;
+ frag_satd=_enc->frag_satd;
+ frag_ssd=_enc->frag_ssd;
+ coded_fragis=_enc->state.coded_fragis;
+ ncoded_fragis=fragii=0;
+ /*Weight the fragments by the inverse frame size; this prevents HD content
+ from dominating the statistics.*/
+ fragw=1.0/_enc->state.nfrags;
+ for(pli=0;pli<3;pli++){
+ ptrdiff_t ti[64];
+ int eob_token[64];
+ int eob_run[64];
+ /*Set up token indices and eob run counts.
+ We don't bother trying to figure out the real cost of the runs that span
+ coefficients; instead we use the costs that were available when R-D
+ token optimization was done.*/
+ for(zzi=0;zzi<64;zzi++){
+ ti[zzi]=_enc->dct_token_offs[pli][zzi];
+ if(ti[zzi]>0){
+ token=_enc->dct_tokens[pli][zzi][0];
+ eb=_enc->extra_bits[pli][zzi][0];
+ eob_token[zzi]=token;
+ eob_run[zzi]=-oc_dct_token_skip(token,eb);
+ }
+ else{
+ eob_token[zzi]=OC_NDCT_EOB_TOKEN_MAX;
+ eob_run[zzi]=0;
+ }
+ }
+ /*Scan the list of coded fragments for this plane.*/
+ ncoded_fragis+=_enc->state.ncoded_fragis[pli];
+ for(;fragii<ncoded_fragis;fragii++){
+ ptrdiff_t fragi;
+ int frag_bits;
+ int huffi;
+ int skip;
+ int mb_mode;
+ unsigned sad;
+ unsigned satd;
+ double sqrt_ssd;
+ int bin;
+ int qtj;
+ fragi=coded_fragis[fragii];
+ frag_bits=0;
+ for(zzi=0;zzi<64;){
+ if(eob_run[zzi]>0){
+ /*We've reached the end of the block.*/
+ eob_run[zzi]--;
+ break;
+ }
+ huffi=_enc->huff_idxs[qti][zzi>0][pli+1>>1]
+ +OC_ZZI_HUFF_OFFSET[zzi];
+ if(eob_token[zzi]<OC_NDCT_EOB_TOKEN_MAX){
+ /*This token caused an EOB run to be flushed.
+ Therefore it gets the bits associated with it.*/
+ frag_bits+=_enc->huff_codes[huffi][eob_token[zzi]].nbits
+ +OC_DCT_TOKEN_EXTRA_BITS[eob_token[zzi]];
+ eob_token[zzi]=OC_NDCT_EOB_TOKEN_MAX;
+ }
+ token=_enc->dct_tokens[pli][zzi][ti[zzi]];
+ eb=_enc->extra_bits[pli][zzi][ti[zzi]];
+ ti[zzi]++;
+ skip=oc_dct_token_skip(token,eb);
+ if(skip<0){
+ eob_token[zzi]=token;
+ eob_run[zzi]=-skip;
+ }
+ else{
+ /*A regular DCT value token; accumulate the bits for it.*/
+ frag_bits+=_enc->huff_codes[huffi][token].nbits
+ +OC_DCT_TOKEN_EXTRA_BITS[token];
+ zzi+=skip;
+ }
+ }
+ mb_mode=frags[fragi].mb_mode;
+ qii=frags[fragi].qii;
+ qi=_enc->state.qis[qii];
+ sad=frag_sad[fragi]<<(pli+1&2);
+ satd=frag_satd[fragi]<<(pli+1&2);
+ sqrt_ssd=sqrt(frag_ssd[fragi]);
+ qtj=mb_mode!=OC_MODE_INTRA;
+ /*Accumulate statistics.
+ The rate (frag_bits) and RMSE (sqrt(frag_ssd)) are not scaled by
+ OC_BIT_SCALE and OC_RMSE_SCALE; this lets us change the scale factor
+ yet still use old data.*/
+ bin=OC_MINI(satd>>OC_SATD_SHIFT,OC_COMP_BINS-1);
+ oc_mode_metrics_add(
+ OC_MODE_METRICS_SATD[modelines[qii][pli][qtj]][pli][qtj]+bin,
+ fragw,satd,_enc->log_plq[qi][pli][qtj],frag_bits,sqrt_ssd);
+ bin=OC_MINI(sad>>OC_SAD_SHIFT,OC_COMP_BINS-1);
+ oc_mode_metrics_add(
+ OC_MODE_METRICS_SAD[modelines[qii][pli][qtj]][pli][qtj]+bin,
+ fragw,sad,_enc->log_plq[qi][pli][qtj],frag_bits,sqrt_ssd);
+ }
+ }
+ /*Update global SA(T)D/logq/rate/RMSE estimation matrix.*/
+ oc_mode_metrics_update(OC_MODE_METRICS_SATD,4,1,
+ OC_MODE_RD_SATD,OC_SATD_SHIFT,OC_MODE_RD_WEIGHT_SATD);
+ oc_mode_metrics_update(OC_MODE_METRICS_SAD,4,1,
+ OC_MODE_RD_SAD,OC_SAD_SHIFT,OC_MODE_RD_WEIGHT_SAD);
+}
+# endif
+
+#endif
diff --git a/thirdparty/libtheora/collect.h b/thirdparty/libtheora/collect.h
new file mode 100644
index 0000000000..9458b84e3f
--- /dev/null
+++ b/thirdparty/libtheora/collect.h
@@ -0,0 +1,109 @@
+/********************************************************************
+ * *
+ * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. *
+ * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
+ * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
+ * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
+ * *
+ * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 *
+ * by the Xiph.Org Foundation http://www.xiph.org/ *
+ * *
+ ********************************************************************
+
+ function: mode selection code
+ last mod: $Id$
+
+ ********************************************************************/
+#if !defined(_collect_H)
+# define _collect_H (1)
+# include "encint.h"
+# if defined(OC_COLLECT_METRICS)
+# include <stdio.h>
+
+
+
+typedef struct oc_mode_metrics oc_mode_metrics;
+
+
+
+/**Sets the file name to load/store mode metrics from/to.
+ * The file name string is stored by reference, and so must be valid for the
+ * lifetime of the encoder.
+ * Mode metric collection uses global tables; do not attempt to perform
+ * multiple collections at once.
+ * \param[in] _buf <tt>char[]</tt> The file name.
+ * \retval TH_EIMPL Not supported by this implementation.*/
+#define TH_ENCCTL_SET_METRICS_FILE (0x8000)
+
+
+
+/*Accumulates various weighted sums of the measurements.
+ w -> weight
+ s -> SATD
+ q -> log quantizer
+ r -> rate (in bits)
+ d -> RMSE
+ All of the single letters correspond to direct, weighted sums, e.g.,
+ w=sum(w_i), s=sum(s_i*w_i), etc.
+ The others correspond to central moments (or co-moments) of the given order,
+ e.g., sq=sum((s_i-s/w)*(q_i-q/w)*w_i).
+ Because we need some moments up to fourth order, we use central moments to
+ minimize the dynamic range and prevent rounding error from dominating the
+ calculations.*/
+struct oc_mode_metrics{
+ double w;
+ double s;
+ double q;
+ double r;
+ double d;
+ double s2;
+ double sq;
+ double q2;
+ double sr;
+ double qr;
+ double r2;
+ double sd;
+ double qd;
+ double d2;
+ double s2q;
+ double sq2;
+ double sqr;
+ double sqd;
+ double s2q2;
+};
+
+
+# define OC_ZWEIGHT (0.25)
+
+/*TODO: It may be helpful (for block-level quantizers especially) to separate
+ out the contributions from AC and DC into separate tables.*/
+
+extern ogg_int16_t OC_MODE_LOGQ[OC_LOGQ_BINS][3][2];
+extern oc_mode_rd OC_MODE_RD_SATD[OC_LOGQ_BINS][3][2][OC_COMP_BINS];
+extern oc_mode_rd OC_MODE_RD_SAD[OC_LOGQ_BINS][3][2][OC_COMP_BINS];
+
+extern int OC_HAS_MODE_METRICS;
+extern oc_mode_metrics OC_MODE_METRICS_SATD[OC_LOGQ_BINS-1][3][2][OC_COMP_BINS];
+extern oc_mode_metrics OC_MODE_METRICS_SAD[OC_LOGQ_BINS-1][3][2][OC_COMP_BINS];
+extern const char *OC_MODE_METRICS_FILENAME;
+
+void oc_mode_metrics_dump();
+void oc_mode_metrics_print(FILE *_fout);
+
+void oc_mode_metrics_add(oc_mode_metrics *_metrics,
+ double _w,int _s,int _q,int _r,double _d);
+void oc_mode_metrics_merge(oc_mode_metrics *_dst,
+ const oc_mode_metrics *_src,int _n);
+double oc_mode_metrics_solve(double *_r,double *_d,
+ const oc_mode_metrics *_metrics,const int *_s0,const int *_s1,
+ const int *_q0,const int *_q1,
+ const double *_ra,const double *_rb,const double *_rc,
+ const double *_da,const double *_db,const double *_dc,int _n);
+void oc_mode_metrics_update(oc_mode_metrics (*_metrics)[3][2][OC_COMP_BINS],
+ int _niters_min,int _reweight,oc_mode_rd (*_table)[3][2][OC_COMP_BINS],
+ int shift,double (*_weight)[3][2][OC_COMP_BINS]);
+void oc_enc_mode_metrics_load(oc_enc_ctx *_enc);
+void oc_enc_mode_metrics_collect(oc_enc_ctx *_enc);
+
+# endif
+#endif
diff --git a/thirdparty/libtheora/dct.h b/thirdparty/libtheora/dct.h
index 24ba6f111a..8052ea6bc1 100644
--- a/thirdparty/libtheora/dct.h
+++ b/thirdparty/libtheora/dct.h
@@ -11,7 +11,7 @@
********************************************************************
function:
- last mod: $Id: dct.h 16503 2009-08-22 18:14:02Z giles $
+ last mod: $Id$
********************************************************************/
diff --git a/thirdparty/libtheora/decinfo.c b/thirdparty/libtheora/decinfo.c
index 845eb1361c..a91e740b15 100644
--- a/thirdparty/libtheora/decinfo.c
+++ b/thirdparty/libtheora/decinfo.c
@@ -11,7 +11,7 @@
********************************************************************
function:
- last mod: $Id: decinfo.c 16503 2009-08-22 18:14:02Z giles $
+ last mod: $Id$
********************************************************************/
@@ -20,6 +20,11 @@
#include <limits.h>
#include "decint.h"
+/*Only used for fuzzing.*/
+#if defined(HAVE_MEMORY_CONSTRAINT)
+static const int MAX_FUZZING_WIDTH = 16384;
+static const int MAX_FUZZING_HEIGHT = 16384;
+#endif
/*Unpacks a series of octets from a given byte array into the pack buffer.
@@ -55,8 +60,8 @@ static int oc_info_unpack(oc_pack_buf *_opb,th_info *_info){
/*verify we can parse this bitstream version.
We accept earlier minors and all subminors, by spec*/
if(_info->version_major>TH_VERSION_MAJOR||
- _info->version_major==TH_VERSION_MAJOR&&
- _info->version_minor>TH_VERSION_MINOR){
+ (_info->version_major==TH_VERSION_MAJOR&&
+ _info->version_minor>TH_VERSION_MINOR)){
return TH_EVERSION;
}
/*Read the encoded frame description.*/
@@ -82,6 +87,11 @@ static int oc_info_unpack(oc_pack_buf *_opb,th_info *_info){
_info->fps_numerator==0||_info->fps_denominator==0){
return TH_EBADHEADER;
}
+#if defined(HAVE_MEMORY_CONSTRAINT)
+ if(_info->frame_width>=MAX_FUZZING_WIDTH&&_info->frame_height>=MAX_FUZZING_HEIGHT){
+ return TH_EBADHEADER;
+ }
+#endif
/*Note: The sense of pic_y is inverted in what we pass back to the
application compared to how it is stored in the bitstream.
This is because the bitstream uses a right-handed coordinate system, while
@@ -128,6 +138,10 @@ static int oc_comment_unpack(oc_pack_buf *_opb,th_comment *_tc){
_tc->comments*sizeof(_tc->comment_lengths[0]));
_tc->user_comments=(char **)_ogg_malloc(
_tc->comments*sizeof(_tc->user_comments[0]));
+ if(_tc->comment_lengths==NULL||_tc->user_comments==NULL){
+ _tc->comments=0;
+ return TH_EFAULT;
+ }
for(i=0;i<_tc->comments;i++){
len=oc_unpack_length(_opb);
if(len<0||len>oc_pack_bytes_left(_opb)){
@@ -168,9 +182,23 @@ static int oc_dec_headerin(oc_pack_buf *_opb,th_info *_info,
int ret;
val=oc_pack_read(_opb,8);
packtype=(int)val;
- /*If we're at a data packet and we have received all three headers, we're
- done.*/
- if(!(packtype&0x80)&&_info->frame_width>0&&_tc->vendor!=NULL&&*_setup!=NULL){
+ /*If we're at a data packet...*/
+ if(!(packtype&0x80)){
+ /*Check to make sure we received all three headers...
+ If we haven't seen any valid headers, assume this is not actually
+ Theora.*/
+ if(_info->frame_width<=0)return TH_ENOTFORMAT;
+ /*Follow our documentation, which says we'll return TH_EFAULT if this
+ are NULL (_info was checked by our caller).*/
+ if(_tc==NULL)return TH_EFAULT;
+ /*And if any other headers were missing, declare this packet "out of
+ sequence" instead.*/
+ if(_tc->vendor==NULL)return TH_EBADHEADER;
+ /*Don't check this until it's needed, since we allow passing NULL for the
+ arguments that we're not expecting the next header to fill in yet.*/
+ if(_setup==NULL)return TH_EFAULT;
+ if(*_setup==NULL)return TH_EBADHEADER;
+ /*If we got everything, we're done.*/
return 0;
}
/*Check the codec string.*/
diff --git a/thirdparty/libtheora/decint.h b/thirdparty/libtheora/decint.h
index 261b67631a..3cea6b1439 100644
--- a/thirdparty/libtheora/decint.h
+++ b/thirdparty/libtheora/decint.h
@@ -11,7 +11,7 @@
********************************************************************
function:
- last mod: $Id: decint.h 16503 2009-08-22 18:14:02Z giles $
+ last mod: $Id$
********************************************************************/
@@ -19,15 +19,39 @@
#if !defined(_decint_H)
# define _decint_H (1)
# include "theora/theoradec.h"
-# include "internal.h"
+# include "state.h"
# include "bitpack.h"
-
-typedef struct th_setup_info oc_setup_info;
-typedef struct th_dec_ctx oc_dec_ctx;
-
# include "huffdec.h"
# include "dequant.h"
+typedef struct th_setup_info oc_setup_info;
+typedef struct oc_dec_opt_vtable oc_dec_opt_vtable;
+typedef struct oc_dec_pipeline_state oc_dec_pipeline_state;
+typedef struct th_dec_ctx oc_dec_ctx;
+
+
+
+/*Decoder-specific accelerated functions.*/
+# if defined(OC_C64X_ASM)
+# include "c64x/c64xdec.h"
+# endif
+
+# if !defined(oc_dec_accel_init)
+# define oc_dec_accel_init oc_dec_accel_init_c
+# endif
+# if defined(OC_DEC_USE_VTABLE)
+# if !defined(oc_dec_dc_unpredict_mcu_plane)
+# define oc_dec_dc_unpredict_mcu_plane(_dec,_pipe,_pli) \
+ ((*(_dec)->opt_vtable.dc_unpredict_mcu_plane)(_dec,_pipe,_pli))
+# endif
+# else
+# if !defined(oc_dec_dc_unpredict_mcu_plane)
+# define oc_dec_dc_unpredict_mcu_plane oc_dec_dc_unpredict_mcu_plane_c
+# endif
+# endif
+
+
+
/*Constants for the packet-in state machine specific to the decoder.*/
/*Next packet to read: Data packet.*/
@@ -37,71 +61,125 @@ typedef struct th_dec_ctx oc_dec_ctx;
struct th_setup_info{
/*The Huffman codes.*/
- oc_huff_node *huff_tables[TH_NHUFFMAN_TABLES];
+ ogg_int16_t *huff_tables[TH_NHUFFMAN_TABLES];
/*The quantization parameters.*/
th_quant_info qinfo;
};
+/*Decoder specific functions with accelerated variants.*/
+struct oc_dec_opt_vtable{
+ void (*dc_unpredict_mcu_plane)(oc_dec_ctx *_dec,
+ oc_dec_pipeline_state *_pipe,int _pli);
+};
+
+
+
+struct oc_dec_pipeline_state{
+ /*Decoded DCT coefficients.
+ These are placed here instead of on the stack so that they can persist
+ between blocks, which makes clearing them back to zero much faster when
+ only a few non-zero coefficients were decoded.
+ It requires at least 65 elements because the zig-zag index array uses the
+ 65th element as a dumping ground for out-of-range indices to protect us
+ from buffer overflow.
+ We make it fully twice as large so that the second half can serve as the
+ reconstruction buffer, which saves passing another parameter to all the
+ acceleration functios.
+ It also solves problems with 16-byte alignment for NEON on ARM.
+ gcc (as of 4.2.1) only seems to be able to give stack variables 8-byte
+ alignment, and silently produces incorrect results if you ask for 16.
+ Finally, keeping it off the stack means there's less likely to be a data
+ hazard beween the NEON co-processor and the regular ARM core, which avoids
+ unnecessary stalls.*/
+ OC_ALIGN16(ogg_int16_t dct_coeffs[128]);
+ OC_ALIGN16(signed char bounding_values[256]);
+ ptrdiff_t ti[3][64];
+ ptrdiff_t ebi[3][64];
+ ptrdiff_t eob_runs[3][64];
+ const ptrdiff_t *coded_fragis[3];
+ const ptrdiff_t *uncoded_fragis[3];
+ ptrdiff_t ncoded_fragis[3];
+ ptrdiff_t nuncoded_fragis[3];
+ const ogg_uint16_t *dequant[3][3][2];
+ int fragy0[3];
+ int fragy_end[3];
+ int pred_last[3][4];
+ int mcu_nvfrags;
+ int loop_filter;
+ int pp_level;
+};
+
+
struct th_dec_ctx{
/*Shared encoder/decoder state.*/
- oc_theora_state state;
+ oc_theora_state state;
/*Whether or not packets are ready to be emitted.
This takes on negative values while there are remaining header packets to
be emitted, reaches 0 when the codec is ready for input, and goes to 1
when a frame has been processed and a data packet is ready.*/
- int packet_state;
+ int packet_state;
/*Buffer in which to assemble packets.*/
- oc_pack_buf opb;
+ oc_pack_buf opb;
/*Huffman decode trees.*/
- oc_huff_node *huff_tables[TH_NHUFFMAN_TABLES];
+ ogg_int16_t *huff_tables[TH_NHUFFMAN_TABLES];
/*The index of the first token in each plane for each coefficient.*/
- ptrdiff_t ti0[3][64];
+ ptrdiff_t ti0[3][64];
/*The number of outstanding EOB runs at the start of each coefficient in each
plane.*/
- ptrdiff_t eob_runs[3][64];
+ ptrdiff_t eob_runs[3][64];
/*The DCT token lists.*/
- unsigned char *dct_tokens;
+ unsigned char *dct_tokens;
/*The extra bits associated with DCT tokens.*/
- unsigned char *extra_bits;
+ unsigned char *extra_bits;
/*The number of dct tokens unpacked so far.*/
- int dct_tokens_count;
+ int dct_tokens_count;
/*The out-of-loop post-processing level.*/
- int pp_level;
+ int pp_level;
/*The DC scale used for out-of-loop deblocking.*/
- int pp_dc_scale[64];
+ int pp_dc_scale[64];
/*The sharpen modifier used for out-of-loop deringing.*/
- int pp_sharp_mod[64];
+ int pp_sharp_mod[64];
/*The DC quantization index of each block.*/
- unsigned char *dc_qis;
+ unsigned char *dc_qis;
/*The variance of each block.*/
- int *variances;
+ int *variances;
/*The storage for the post-processed frame buffer.*/
- unsigned char *pp_frame_data;
+ unsigned char *pp_frame_data;
/*Whether or not the post-processsed frame buffer has space for chroma.*/
- int pp_frame_state;
+ int pp_frame_state;
/*The buffer used for the post-processed frame.
Note that this is _not_ guaranteed to have the same strides and offsets as
the reference frame buffers.*/
- th_ycbcr_buffer pp_frame_buf;
+ th_ycbcr_buffer pp_frame_buf;
/*The striped decode callback function.*/
- th_stripe_callback stripe_cb;
+ th_stripe_callback stripe_cb;
+ oc_dec_pipeline_state pipe;
+# if defined(OC_DEC_USE_VTABLE)
+ /*Table for decoder acceleration functions.*/
+ oc_dec_opt_vtable opt_vtable;
+# endif
# if defined(HAVE_CAIRO)
/*Output metrics for debugging.*/
- int telemetry;
- int telemetry_mbmode;
- int telemetry_mv;
- int telemetry_qi;
- int telemetry_bits;
- int telemetry_frame_bytes;
- int telemetry_coding_bytes;
- int telemetry_mode_bytes;
- int telemetry_mv_bytes;
- int telemetry_qi_bytes;
- int telemetry_dc_bytes;
- unsigned char *telemetry_frame_data;
+ int telemetry_mbmode;
+ int telemetry_mv;
+ int telemetry_qi;
+ int telemetry_bits;
+ int telemetry_frame_bytes;
+ int telemetry_coding_bytes;
+ int telemetry_mode_bytes;
+ int telemetry_mv_bytes;
+ int telemetry_qi_bytes;
+ int telemetry_dc_bytes;
+ unsigned char *telemetry_frame_data;
# endif
};
+/*Default pure-C implementations of decoder-specific accelerated functions.*/
+void oc_dec_accel_init_c(oc_dec_ctx *_dec);
+
+void oc_dec_dc_unpredict_mcu_plane_c(oc_dec_ctx *_dec,
+ oc_dec_pipeline_state *_pipe,int _pli);
+
#endif
diff --git a/thirdparty/libtheora/decode.c b/thirdparty/libtheora/decode.c
index bde967b794..fad26e0927 100644
--- a/thirdparty/libtheora/decode.c
+++ b/thirdparty/libtheora/decode.c
@@ -11,7 +11,7 @@
********************************************************************
function:
- last mod: $Id: decode.c 16581 2009-09-25 22:56:16Z gmaxwell $
+ last mod: $Id$
********************************************************************/
@@ -118,7 +118,7 @@ static const unsigned char OC_INTERNAL_DCT_TOKEN_EXTRA_BITS[15]={
/*Whether or not an internal token needs any additional extra bits.*/
#define OC_DCT_TOKEN_NEEDS_MORE(token) \
- (token<(sizeof(OC_INTERNAL_DCT_TOKEN_EXTRA_BITS)/ \
+ (token<(int)(sizeof(OC_INTERNAL_DCT_TOKEN_EXTRA_BITS)/ \
sizeof(*OC_INTERNAL_DCT_TOKEN_EXTRA_BITS)))
/*This token (OC_DCT_REPEAT_RUN3_TOKEN) requires more than 8 extra bits.*/
@@ -129,7 +129,7 @@ static const unsigned char OC_INTERNAL_DCT_TOKEN_EXTRA_BITS[15]={
is not yet available everywhere; this should be equivalent.*/
#define OC_DCT_EOB_FINISH (~(size_t)0>>1)
-/*The location of the (6) run legth bits in the code word.
+/*The location of the (6) run length bits in the code word.
These are placed at index 0 and given 8 bits (even though 6 would suffice)
because it may be faster to extract the lower byte on some platforms.*/
#define OC_DCT_CW_RLEN_SHIFT (0)
@@ -297,8 +297,6 @@ static const ogg_int32_t OC_DCT_CODE_WORD[92]={
static int oc_sb_run_unpack(oc_pack_buf *_opb){
- long bits;
- int ret;
/*Coding scheme:
Codeword Run Length
0 1
@@ -308,32 +306,26 @@ static int oc_sb_run_unpack(oc_pack_buf *_opb){
11110xxx 10-17
111110xxxx 18-33
111111xxxxxxxxxxxx 34-4129*/
- bits=oc_pack_read1(_opb);
- if(bits==0)return 1;
- bits=oc_pack_read(_opb,2);
- if((bits&2)==0)return 2+(int)bits;
- else if((bits&1)==0){
- bits=oc_pack_read1(_opb);
- return 4+(int)bits;
- }
- bits=oc_pack_read(_opb,3);
- if((bits&4)==0)return 6+(int)bits;
- else if((bits&2)==0){
- ret=10+((bits&1)<<2);
- bits=oc_pack_read(_opb,2);
- return ret+(int)bits;
- }
- else if((bits&1)==0){
- bits=oc_pack_read(_opb,4);
- return 18+(int)bits;
+ static const ogg_int16_t OC_SB_RUN_TREE[22]={
+ 4,
+ -(1<<8|1),-(1<<8|1),-(1<<8|1),-(1<<8|1),
+ -(1<<8|1),-(1<<8|1),-(1<<8|1),-(1<<8|1),
+ -(3<<8|2),-(3<<8|2),-(3<<8|3),-(3<<8|3),
+ -(4<<8|4),-(4<<8|5),-(4<<8|2<<4|6-6),17,
+ 2,
+ -(2<<8|2<<4|10-6),-(2<<8|2<<4|14-6),-(2<<8|4<<4|18-6),-(2<<8|12<<4|34-6)
+ };
+ int ret;
+ ret=oc_huff_token_decode(_opb,OC_SB_RUN_TREE);
+ if(ret>=0x10){
+ int offs;
+ offs=ret&0x1F;
+ ret=6+offs+(int)oc_pack_read(_opb,ret-offs>>4);
}
- bits=oc_pack_read(_opb,12);
- return 34+(int)bits;
+ return ret;
}
static int oc_block_run_unpack(oc_pack_buf *_opb){
- long bits;
- long bits2;
/*Coding scheme:
Codeword Run Length
0x 1-2
@@ -342,26 +334,37 @@ static int oc_block_run_unpack(oc_pack_buf *_opb){
1110xx 7-10
11110xx 11-14
11111xxxx 15-30*/
- bits=oc_pack_read(_opb,2);
- if((bits&2)==0)return 1+(int)bits;
- else if((bits&1)==0){
- bits=oc_pack_read1(_opb);
- return 3+(int)bits;
- }
- bits=oc_pack_read(_opb,2);
- if((bits&2)==0)return 5+(int)bits;
- else if((bits&1)==0){
- bits=oc_pack_read(_opb,2);
- return 7+(int)bits;
- }
- bits=oc_pack_read(_opb,3);
- if((bits&4)==0)return 11+bits;
- bits2=oc_pack_read(_opb,2);
- return 15+((bits&3)<<2)+bits2;
+ static const ogg_int16_t OC_BLOCK_RUN_TREE[61]={
+ 5,
+ -(2<<8|1),-(2<<8|1),-(2<<8|1),-(2<<8|1),
+ -(2<<8|1),-(2<<8|1),-(2<<8|1),-(2<<8|1),
+ -(2<<8|2),-(2<<8|2),-(2<<8|2),-(2<<8|2),
+ -(2<<8|2),-(2<<8|2),-(2<<8|2),-(2<<8|2),
+ -(3<<8|3),-(3<<8|3),-(3<<8|3),-(3<<8|3),
+ -(3<<8|4),-(3<<8|4),-(3<<8|4),-(3<<8|4),
+ -(4<<8|5),-(4<<8|5),-(4<<8|6),-(4<<8|6),
+ 33, 36, 39, 44,
+ 1,-(1<<8|7),-(1<<8|8),
+ 1,-(1<<8|9),-(1<<8|10),
+ 2,-(2<<8|11),-(2<<8|12),-(2<<8|13),-(2<<8|14),
+ 4,
+ -(4<<8|15),-(4<<8|16),-(4<<8|17),-(4<<8|18),
+ -(4<<8|19),-(4<<8|20),-(4<<8|21),-(4<<8|22),
+ -(4<<8|23),-(4<<8|24),-(4<<8|25),-(4<<8|26),
+ -(4<<8|27),-(4<<8|28),-(4<<8|29),-(4<<8|30)
+ };
+ return oc_huff_token_decode(_opb,OC_BLOCK_RUN_TREE);
}
+void oc_dec_accel_init_c(oc_dec_ctx *_dec){
+# if defined(OC_DEC_USE_VTABLE)
+ _dec->opt_vtable.dc_unpredict_mcu_plane=
+ oc_dec_dc_unpredict_mcu_plane_c;
+# endif
+}
+
static int oc_dec_init(oc_dec_ctx *_dec,const th_info *_info,
const th_setup_info *_setup){
int qti;
@@ -371,7 +374,7 @@ static int oc_dec_init(oc_dec_ctx *_dec,const th_info *_info,
ret=oc_state_init(&_dec->state,_info,3);
if(ret<0)return ret;
ret=oc_huff_trees_copy(_dec->huff_tables,
- (const oc_huff_node *const *)_setup->huff_tables);
+ (const ogg_int16_t *const *)_setup->huff_tables);
if(ret<0){
oc_state_clear(&_dec->state);
return ret;
@@ -406,6 +409,7 @@ static int oc_dec_init(oc_dec_ctx *_dec,const th_info *_info,
}
memcpy(_dec->state.loop_filter_limits,_setup->qinfo.loop_filter_limits,
sizeof(_dec->state.loop_filter_limits));
+ oc_dec_accel_init(_dec);
_dec->pp_level=OC_PP_LEVEL_DISABLED;
_dec->dc_qis=NULL;
_dec->variances=NULL;
@@ -413,7 +417,6 @@ static int oc_dec_init(oc_dec_ctx *_dec,const th_info *_info,
_dec->stripe_cb.ctx=NULL;
_dec->stripe_cb.stripe_decoded=NULL;
#if defined(HAVE_CAIRO)
- _dec->telemetry=0;
_dec->telemetry_bits=0;
_dec->telemetry_qi=0;
_dec->telemetry_mbmode=0;
@@ -504,6 +507,7 @@ static void oc_dec_mark_all_intra(oc_dec_ctx *_dec){
fragi=sb_maps[sbi][quadi][bi];
if(fragi>=0){
frags[fragi].coded=1;
+ frags[fragi].refi=OC_FRAME_SELF;
frags[fragi].mb_mode=OC_MODE_INTRA;
coded_fragis[ncoded_fragis++]=fragi;
}
@@ -595,6 +599,7 @@ static void oc_dec_coded_sb_flags_unpack(oc_dec_ctx *_dec){
static void oc_dec_coded_flags_unpack(oc_dec_ctx *_dec){
const oc_sb_map *sb_maps;
const oc_sb_flags *sb_flags;
+ signed char *mb_modes;
oc_fragment *frags;
unsigned nsbs;
unsigned sbi;
@@ -617,6 +622,7 @@ static void oc_dec_coded_flags_unpack(oc_dec_ctx *_dec){
else flag=0;
sb_maps=(const oc_sb_map *)_dec->state.sb_maps;
sb_flags=_dec->state.sb_flags;
+ mb_modes=_dec->state.mb_modes;
frags=_dec->state.frags;
sbi=nsbs=run_count=0;
coded_fragis=_dec->state.coded_fragis;
@@ -627,7 +633,9 @@ static void oc_dec_coded_flags_unpack(oc_dec_ctx *_dec){
for(;sbi<nsbs;sbi++){
int quadi;
for(quadi=0;quadi<4;quadi++)if(sb_flags[sbi].quad_valid&1<<quadi){
+ int quad_coded;
int bi;
+ quad_coded=0;
for(bi=0;bi<4;bi++){
ptrdiff_t fragi;
fragi=sb_maps[sbi][quadi][bi];
@@ -645,9 +653,13 @@ static void oc_dec_coded_flags_unpack(oc_dec_ctx *_dec){
}
if(coded)coded_fragis[ncoded_fragis++]=fragi;
else *(uncoded_fragis-++nuncoded_fragis)=fragi;
+ quad_coded|=coded;
frags[fragi].coded=coded;
+ frags[fragi].refi=OC_FRAME_NONE;
}
}
+ /*Remember if there's a coded luma block in this macro block.*/
+ if(!pli)mb_modes[sbi<<2|quadi]=quad_coded;
}
}
_dec->state.ncoded_fragis[pli]=ncoded_fragis-prev_ncoded_fragis;
@@ -659,33 +671,39 @@ static void oc_dec_coded_flags_unpack(oc_dec_ctx *_dec){
}
+/*Coding scheme:
+ Codeword Mode Index
+ 0 0
+ 10 1
+ 110 2
+ 1110 3
+ 11110 4
+ 111110 5
+ 1111110 6
+ 1111111 7*/
+static const ogg_int16_t OC_VLC_MODE_TREE[26]={
+ 4,
+ -(1<<8|0),-(1<<8|0),-(1<<8|0),-(1<<8|0),
+ -(1<<8|0),-(1<<8|0),-(1<<8|0),-(1<<8|0),
+ -(2<<8|1),-(2<<8|1),-(2<<8|1),-(2<<8|1),
+ -(3<<8|2),-(3<<8|2),-(4<<8|3),17,
+ 3,
+ -(1<<8|4),-(1<<8|4),-(1<<8|4),-(1<<8|4),
+ -(2<<8|5),-(2<<8|5),-(3<<8|6),-(3<<8|7)
+};
-typedef int (*oc_mode_unpack_func)(oc_pack_buf *_opb);
-
-static int oc_vlc_mode_unpack(oc_pack_buf *_opb){
- long val;
- int i;
- for(i=0;i<7;i++){
- val=oc_pack_read1(_opb);
- if(!val)break;
- }
- return i;
-}
-
-static int oc_clc_mode_unpack(oc_pack_buf *_opb){
- long val;
- val=oc_pack_read(_opb,3);
- return (int)val;
-}
+static const ogg_int16_t OC_CLC_MODE_TREE[9]={
+ 3,
+ -(3<<8|0),-(3<<8|1),-(3<<8|2),-(3<<8|3),
+ -(3<<8|4),-(3<<8|5),-(3<<8|6),-(3<<8|7)
+};
/*Unpacks the list of macro block modes for INTER frames.*/
static void oc_dec_mb_modes_unpack(oc_dec_ctx *_dec){
- const oc_mb_map *mb_maps;
signed char *mb_modes;
- const oc_fragment *frags;
const unsigned char *alphabet;
unsigned char scheme0_alphabet[8];
- oc_mode_unpack_func mode_unpack;
+ const ogg_int16_t *mode_tree;
size_t nmbs;
size_t mbi;
long val;
@@ -707,65 +725,80 @@ static void oc_dec_mb_modes_unpack(oc_dec_ctx *_dec){
alphabet=scheme0_alphabet;
}
else alphabet=OC_MODE_ALPHABETS[mode_scheme-1];
- if(mode_scheme==7)mode_unpack=oc_clc_mode_unpack;
- else mode_unpack=oc_vlc_mode_unpack;
+ mode_tree=mode_scheme==7?OC_CLC_MODE_TREE:OC_VLC_MODE_TREE;
mb_modes=_dec->state.mb_modes;
- mb_maps=(const oc_mb_map *)_dec->state.mb_maps;
nmbs=_dec->state.nmbs;
- frags=_dec->state.frags;
for(mbi=0;mbi<nmbs;mbi++){
- if(mb_modes[mbi]!=OC_MODE_INVALID){
- int bi;
- /*Check for a coded luma block in this macro block.*/
- for(bi=0;bi<4&&!frags[mb_maps[mbi][0][bi]].coded;bi++);
- /*We found one, decode a mode.*/
- if(bi<4)mb_modes[mbi]=alphabet[(*mode_unpack)(&_dec->opb)];
- /*There were none: INTER_NOMV is forced.*/
- else mb_modes[mbi]=OC_MODE_INTER_NOMV;
+ if(mb_modes[mbi]>0){
+ /*We have a coded luma block; decode a mode.*/
+ mb_modes[mbi]=alphabet[oc_huff_token_decode(&_dec->opb,mode_tree)];
}
+ /*For other valid macro blocks, INTER_NOMV is forced, but we rely on the
+ fact that OC_MODE_INTER_NOMV is already 0.*/
}
}
-typedef int (*oc_mv_comp_unpack_func)(oc_pack_buf *_opb);
+static const ogg_int16_t OC_VLC_MV_COMP_TREE[101]={
+ 5,
+ -(3<<8|32+0),-(3<<8|32+0),-(3<<8|32+0),-(3<<8|32+0),
+ -(3<<8|32+1),-(3<<8|32+1),-(3<<8|32+1),-(3<<8|32+1),
+ -(3<<8|32-1),-(3<<8|32-1),-(3<<8|32-1),-(3<<8|32-1),
+ -(4<<8|32+2),-(4<<8|32+2),-(4<<8|32-2),-(4<<8|32-2),
+ -(4<<8|32+3),-(4<<8|32+3),-(4<<8|32-3),-(4<<8|32-3),
+ 33, 36, 39, 42,
+ 45, 50, 55, 60,
+ 65, 74, 83, 92,
+ 1,-(1<<8|32+4),-(1<<8|32-4),
+ 1,-(1<<8|32+5),-(1<<8|32-5),
+ 1,-(1<<8|32+6),-(1<<8|32-6),
+ 1,-(1<<8|32+7),-(1<<8|32-7),
+ 2,-(2<<8|32+8),-(2<<8|32-8),-(2<<8|32+9),-(2<<8|32-9),
+ 2,-(2<<8|32+10),-(2<<8|32-10),-(2<<8|32+11),-(2<<8|32-11),
+ 2,-(2<<8|32+12),-(2<<8|32-12),-(2<<8|32+13),-(2<<8|32-13),
+ 2,-(2<<8|32+14),-(2<<8|32-14),-(2<<8|32+15),-(2<<8|32-15),
+ 3,
+ -(3<<8|32+16),-(3<<8|32-16),-(3<<8|32+17),-(3<<8|32-17),
+ -(3<<8|32+18),-(3<<8|32-18),-(3<<8|32+19),-(3<<8|32-19),
+ 3,
+ -(3<<8|32+20),-(3<<8|32-20),-(3<<8|32+21),-(3<<8|32-21),
+ -(3<<8|32+22),-(3<<8|32-22),-(3<<8|32+23),-(3<<8|32-23),
+ 3,
+ -(3<<8|32+24),-(3<<8|32-24),-(3<<8|32+25),-(3<<8|32-25),
+ -(3<<8|32+26),-(3<<8|32-26),-(3<<8|32+27),-(3<<8|32-27),
+ 3,
+ -(3<<8|32+28),-(3<<8|32-28),-(3<<8|32+29),-(3<<8|32-29),
+ -(3<<8|32+30),-(3<<8|32-30),-(3<<8|32+31),-(3<<8|32-31)
+};
+
+static const ogg_int16_t OC_CLC_MV_COMP_TREE[65]={
+ 6,
+ -(6<<8|32 +0),-(6<<8|32 -0),-(6<<8|32 +1),-(6<<8|32 -1),
+ -(6<<8|32 +2),-(6<<8|32 -2),-(6<<8|32 +3),-(6<<8|32 -3),
+ -(6<<8|32 +4),-(6<<8|32 -4),-(6<<8|32 +5),-(6<<8|32 -5),
+ -(6<<8|32 +6),-(6<<8|32 -6),-(6<<8|32 +7),-(6<<8|32 -7),
+ -(6<<8|32 +8),-(6<<8|32 -8),-(6<<8|32 +9),-(6<<8|32 -9),
+ -(6<<8|32+10),-(6<<8|32-10),-(6<<8|32+11),-(6<<8|32-11),
+ -(6<<8|32+12),-(6<<8|32-12),-(6<<8|32+13),-(6<<8|32-13),
+ -(6<<8|32+14),-(6<<8|32-14),-(6<<8|32+15),-(6<<8|32-15),
+ -(6<<8|32+16),-(6<<8|32-16),-(6<<8|32+17),-(6<<8|32-17),
+ -(6<<8|32+18),-(6<<8|32-18),-(6<<8|32+19),-(6<<8|32-19),
+ -(6<<8|32+20),-(6<<8|32-20),-(6<<8|32+21),-(6<<8|32-21),
+ -(6<<8|32+22),-(6<<8|32-22),-(6<<8|32+23),-(6<<8|32-23),
+ -(6<<8|32+24),-(6<<8|32-24),-(6<<8|32+25),-(6<<8|32-25),
+ -(6<<8|32+26),-(6<<8|32-26),-(6<<8|32+27),-(6<<8|32-27),
+ -(6<<8|32+28),-(6<<8|32-28),-(6<<8|32+29),-(6<<8|32-29),
+ -(6<<8|32+30),-(6<<8|32-30),-(6<<8|32+31),-(6<<8|32-31)
+};
-static int oc_vlc_mv_comp_unpack(oc_pack_buf *_opb){
- long bits;
- int mask;
- int mv;
- bits=oc_pack_read(_opb,3);
- switch(bits){
- case 0:return 0;
- case 1:return 1;
- case 2:return -1;
- case 3:
- case 4:{
- mv=(int)(bits-1);
- bits=oc_pack_read1(_opb);
- }break;
- /*case 5:
- case 6:
- case 7:*/
- default:{
- mv=1<<bits-3;
- bits=oc_pack_read(_opb,bits-2);
- mv+=(int)(bits>>1);
- bits&=1;
- }break;
- }
- mask=-(int)bits;
- return mv+mask^mask;
-}
-static int oc_clc_mv_comp_unpack(oc_pack_buf *_opb){
- long bits;
- int mask;
- int mv;
- bits=oc_pack_read(_opb,6);
- mv=(int)bits>>1;
- mask=-((int)bits&1);
- return mv+mask^mask;
+static oc_mv oc_mv_unpack(oc_pack_buf *_opb,const ogg_int16_t *_tree){
+ int dx;
+ int dy;
+ dx=oc_huff_token_decode(_opb,_tree)-32;
+ dy=oc_huff_token_decode(_opb,_tree)-32;
+ return OC_MV(dx,dy);
}
/*Unpacks the list of motion vectors for INTER frames, and propagtes the macro
@@ -774,105 +807,93 @@ static void oc_dec_mv_unpack_and_frag_modes_fill(oc_dec_ctx *_dec){
const oc_mb_map *mb_maps;
const signed char *mb_modes;
oc_set_chroma_mvs_func set_chroma_mvs;
- oc_mv_comp_unpack_func mv_comp_unpack;
+ const ogg_int16_t *mv_comp_tree;
oc_fragment *frags;
oc_mv *frag_mvs;
const unsigned char *map_idxs;
int map_nidxs;
- oc_mv last_mv[2];
+ oc_mv last_mv;
+ oc_mv prior_mv;
oc_mv cbmvs[4];
size_t nmbs;
size_t mbi;
long val;
set_chroma_mvs=OC_SET_CHROMA_MVS_TABLE[_dec->state.info.pixel_fmt];
val=oc_pack_read1(&_dec->opb);
- mv_comp_unpack=val?oc_clc_mv_comp_unpack:oc_vlc_mv_comp_unpack;
+ mv_comp_tree=val?OC_CLC_MV_COMP_TREE:OC_VLC_MV_COMP_TREE;
map_idxs=OC_MB_MAP_IDXS[_dec->state.info.pixel_fmt];
map_nidxs=OC_MB_MAP_NIDXS[_dec->state.info.pixel_fmt];
- memset(last_mv,0,sizeof(last_mv));
+ prior_mv=last_mv=0;
frags=_dec->state.frags;
frag_mvs=_dec->state.frag_mvs;
mb_maps=(const oc_mb_map *)_dec->state.mb_maps;
mb_modes=_dec->state.mb_modes;
nmbs=_dec->state.nmbs;
for(mbi=0;mbi<nmbs;mbi++){
- int mb_mode;
+ int mb_mode;
mb_mode=mb_modes[mbi];
if(mb_mode!=OC_MODE_INVALID){
- oc_mv mbmv;
- ptrdiff_t fragi;
- int coded[13];
- int codedi;
- int ncoded;
- int mapi;
- int mapii;
- /*Search for at least one coded fragment.*/
- ncoded=mapii=0;
- do{
- mapi=map_idxs[mapii];
- fragi=mb_maps[mbi][mapi>>2][mapi&3];
- if(frags[fragi].coded)coded[ncoded++]=mapi;
- }
- while(++mapii<map_nidxs);
- if(ncoded<=0)continue;
- switch(mb_mode){
- case OC_MODE_INTER_MV_FOUR:{
- oc_mv lbmvs[4];
- int bi;
- /*Mark the tail of the list, so we don't accidentally go past it.*/
- coded[ncoded]=-1;
- for(bi=codedi=0;bi<4;bi++){
- if(coded[codedi]==bi){
- codedi++;
- fragi=mb_maps[mbi][0][bi];
- frags[fragi].mb_mode=mb_mode;
- lbmvs[bi][0]=(signed char)(*mv_comp_unpack)(&_dec->opb);
- lbmvs[bi][1]=(signed char)(*mv_comp_unpack)(&_dec->opb);
- memcpy(frag_mvs[fragi],lbmvs[bi],sizeof(lbmvs[bi]));
- }
- else lbmvs[bi][0]=lbmvs[bi][1]=0;
- }
- if(codedi>0){
- memcpy(last_mv[1],last_mv[0],sizeof(last_mv[1]));
- memcpy(last_mv[0],lbmvs[coded[codedi-1]],sizeof(last_mv[0]));
+ oc_mv mbmv;
+ ptrdiff_t fragi;
+ int mapi;
+ int mapii;
+ int refi;
+ if(mb_mode==OC_MODE_INTER_MV_FOUR){
+ oc_mv lbmvs[4];
+ int bi;
+ prior_mv=last_mv;
+ for(bi=0;bi<4;bi++){
+ fragi=mb_maps[mbi][0][bi];
+ if(frags[fragi].coded){
+ frags[fragi].refi=OC_FRAME_PREV;
+ frags[fragi].mb_mode=OC_MODE_INTER_MV_FOUR;
+ lbmvs[bi]=last_mv=oc_mv_unpack(&_dec->opb,mv_comp_tree);
+ frag_mvs[fragi]=lbmvs[bi];
}
- if(codedi<ncoded){
- (*set_chroma_mvs)(cbmvs,(const oc_mv *)lbmvs);
- for(;codedi<ncoded;codedi++){
- mapi=coded[codedi];
- bi=mapi&3;
- fragi=mb_maps[mbi][mapi>>2][bi];
- frags[fragi].mb_mode=mb_mode;
- memcpy(frag_mvs[fragi],cbmvs[bi],sizeof(cbmvs[bi]));
- }
+ else lbmvs[bi]=0;
+ }
+ (*set_chroma_mvs)(cbmvs,lbmvs);
+ for(mapii=4;mapii<map_nidxs;mapii++){
+ mapi=map_idxs[mapii];
+ bi=mapi&3;
+ fragi=mb_maps[mbi][mapi>>2][bi];
+ if(frags[fragi].coded){
+ frags[fragi].refi=OC_FRAME_PREV;
+ frags[fragi].mb_mode=OC_MODE_INTER_MV_FOUR;
+ frag_mvs[fragi]=cbmvs[bi];
}
- }break;
- case OC_MODE_INTER_MV:{
- memcpy(last_mv[1],last_mv[0],sizeof(last_mv[1]));
- mbmv[0]=last_mv[0][0]=(signed char)(*mv_comp_unpack)(&_dec->opb);
- mbmv[1]=last_mv[0][1]=(signed char)(*mv_comp_unpack)(&_dec->opb);
- }break;
- case OC_MODE_INTER_MV_LAST:memcpy(mbmv,last_mv[0],sizeof(mbmv));break;
- case OC_MODE_INTER_MV_LAST2:{
- memcpy(mbmv,last_mv[1],sizeof(mbmv));
- memcpy(last_mv[1],last_mv[0],sizeof(last_mv[1]));
- memcpy(last_mv[0],mbmv,sizeof(last_mv[0]));
- }break;
- case OC_MODE_GOLDEN_MV:{
- mbmv[0]=(signed char)(*mv_comp_unpack)(&_dec->opb);
- mbmv[1]=(signed char)(*mv_comp_unpack)(&_dec->opb);
- }break;
- default:memset(mbmv,0,sizeof(mbmv));break;
+ }
}
- /*4MV mode fills in the fragments itself.
- For all other modes we can use this common code.*/
- if(mb_mode!=OC_MODE_INTER_MV_FOUR){
- for(codedi=0;codedi<ncoded;codedi++){
- mapi=coded[codedi];
+ else{
+ switch(mb_mode){
+ case OC_MODE_INTER_MV:{
+ prior_mv=last_mv;
+ last_mv=mbmv=oc_mv_unpack(&_dec->opb,mv_comp_tree);
+ }break;
+ case OC_MODE_INTER_MV_LAST:mbmv=last_mv;break;
+ case OC_MODE_INTER_MV_LAST2:{
+ mbmv=prior_mv;
+ prior_mv=last_mv;
+ last_mv=mbmv;
+ }break;
+ case OC_MODE_GOLDEN_MV:{
+ mbmv=oc_mv_unpack(&_dec->opb,mv_comp_tree);
+ }break;
+ default:mbmv=0;break;
+ }
+ /*Fill in the MVs for the fragments.*/
+ refi=OC_FRAME_FOR_MODE(mb_mode);
+ mapii=0;
+ do{
+ mapi=map_idxs[mapii];
fragi=mb_maps[mbi][mapi>>2][mapi&3];
- frags[fragi].mb_mode=mb_mode;
- memcpy(frag_mvs[fragi],mbmv,sizeof(mbmv));
+ if(frags[fragi].coded){
+ frags[fragi].refi=refi;
+ frags[fragi].mb_mode=mb_mode;
+ frag_mvs[fragi]=mbmv;
+ }
}
+ while(++mapii<map_nidxs);
}
}
}
@@ -1181,6 +1202,9 @@ static void oc_dec_residual_tokens_unpack(oc_dec_ctx *_dec){
static int oc_dec_postprocess_init(oc_dec_ctx *_dec){
+ /*musl libc malloc()/realloc() calls might use floating point, so make sure
+ we've cleared the MMX state for them.*/
+ oc_restore_fpu(&_dec->state);
/*pp_level 0: disabled; free any memory used and return*/
if(_dec->pp_level<=OC_PP_LEVEL_DISABLED){
if(_dec->dc_qis!=NULL){
@@ -1301,34 +1325,16 @@ static int oc_dec_postprocess_init(oc_dec_ctx *_dec){
}
-
-typedef struct{
- int bounding_values[256];
- ptrdiff_t ti[3][64];
- ptrdiff_t eob_runs[3][64];
- const ptrdiff_t *coded_fragis[3];
- const ptrdiff_t *uncoded_fragis[3];
- ptrdiff_t ncoded_fragis[3];
- ptrdiff_t nuncoded_fragis[3];
- const ogg_uint16_t *dequant[3][3][2];
- int fragy0[3];
- int fragy_end[3];
- int pred_last[3][3];
- int mcu_nvfrags;
- int loop_filter;
- int pp_level;
-}oc_dec_pipeline_state;
-
-
-
/*Initialize the main decoding pipeline.*/
static void oc_dec_pipeline_init(oc_dec_ctx *_dec,
oc_dec_pipeline_state *_pipe){
const ptrdiff_t *coded_fragis;
const ptrdiff_t *uncoded_fragis;
+ int flimit;
int pli;
int qii;
int qti;
+ int zzi;
/*If chroma is sub-sampled in the vertical direction, we have to decode two
super block rows of Y' for each super block row of Cb and Cr.*/
_pipe->mcu_nvfrags=4<<!(_dec->state.info.pixel_fmt&2);
@@ -1360,8 +1366,9 @@ static void oc_dec_pipeline_init(oc_dec_ctx *_dec,
/*Set the previous DC predictor to 0 for all color planes and frame types.*/
memset(_pipe->pred_last,0,sizeof(_pipe->pred_last));
/*Initialize the bounding value array for the loop filter.*/
- _pipe->loop_filter=!oc_state_loop_filter_init(&_dec->state,
- _pipe->bounding_values);
+ flimit=_dec->state.loop_filter_limits[_dec->state.qis[0]];
+ _pipe->loop_filter=flimit!=0;
+ if(flimit!=0)oc_loop_filter_init(&_dec->state,_pipe->bounding_values,flimit);
/*Initialize any buffers needed for post-processing.
We also save the current post-processing level, to guard against the user
changing it from a callback.*/
@@ -1374,13 +1381,15 @@ static void oc_dec_pipeline_init(oc_dec_ctx *_dec,
_dec->state.ref_frame_bufs[_dec->state.ref_frame_idx[OC_FRAME_SELF]],
sizeof(_dec->pp_frame_buf[0])*3);
}
+ /*Clear down the DCT coefficient buffer for the first block.*/
+ for(zzi=0;zzi<64;zzi++)_pipe->dct_coeffs[zzi]=0;
}
/*Undo the DC prediction in a single plane of an MCU (one or two super block
rows).
As a side effect, the number of coded and uncoded fragments in this plane of
the MCU is also computed.*/
-static void oc_dec_dc_unpredict_mcu_plane(oc_dec_ctx *_dec,
+void oc_dec_dc_unpredict_mcu_plane_c(oc_dec_ctx *_dec,
oc_dec_pipeline_state *_pipe,int _pli){
const oc_fragment_plane *fplane;
oc_fragment *frags;
@@ -1408,9 +1417,9 @@ static void oc_dec_dc_unpredict_mcu_plane(oc_dec_ctx *_dec,
predictor for the same reference frame.*/
for(fragx=0;fragx<nhfrags;fragx++,fragi++){
if(frags[fragi].coded){
- int ref;
- ref=OC_FRAME_FOR_MODE(frags[fragi].mb_mode);
- pred_last[ref]=frags[fragi].dc+=pred_last[ref];
+ int refi;
+ refi=frags[fragi].refi;
+ pred_last[refi]=frags[fragi].dc+=pred_last[refi];
ncoded_fragis++;
}
}
@@ -1423,27 +1432,24 @@ static void oc_dec_dc_unpredict_mcu_plane(oc_dec_ctx *_dec,
u_frags=frags-nhfrags;
l_ref=-1;
ul_ref=-1;
- u_ref=u_frags[fragi].coded?OC_FRAME_FOR_MODE(u_frags[fragi].mb_mode):-1;
+ u_ref=u_frags[fragi].refi;
for(fragx=0;fragx<nhfrags;fragx++,fragi++){
int ur_ref;
if(fragx+1>=nhfrags)ur_ref=-1;
- else{
- ur_ref=u_frags[fragi+1].coded?
- OC_FRAME_FOR_MODE(u_frags[fragi+1].mb_mode):-1;
- }
+ else ur_ref=u_frags[fragi+1].refi;
if(frags[fragi].coded){
int pred;
- int ref;
- ref=OC_FRAME_FOR_MODE(frags[fragi].mb_mode);
+ int refi;
+ refi=frags[fragi].refi;
/*We break out a separate case based on which of our neighbors use
the same reference frames.
This is somewhat faster than trying to make a generic case which
handles all of them, since it reduces lots of poorly predicted
jumps to one switch statement, and also lets a number of the
multiplications be optimized out by strength reduction.*/
- switch((l_ref==ref)|(ul_ref==ref)<<1|
- (u_ref==ref)<<2|(ur_ref==ref)<<3){
- default:pred=pred_last[ref];break;
+ switch((l_ref==refi)|(ul_ref==refi)<<1|
+ (u_ref==refi)<<2|(ur_ref==refi)<<3){
+ default:pred=pred_last[refi];break;
case 1:
case 3:pred=frags[fragi-1].dc;break;
case 2:pred=u_frags[fragi-1].dc;break;
@@ -1455,6 +1461,7 @@ static void oc_dec_dc_unpredict_mcu_plane(oc_dec_ctx *_dec,
case 9:
case 11:
case 13:{
+ /*The TI compiler mis-compiles this line.*/
pred=(75*frags[fragi-1].dc+53*u_frags[fragi+1].dc)/128;
}break;
case 10:pred=(u_frags[fragi-1].dc+u_frags[fragi+1].dc)/2;break;
@@ -1476,9 +1483,9 @@ static void oc_dec_dc_unpredict_mcu_plane(oc_dec_ctx *_dec,
else if(abs(pred-p1)>128)pred=p1;
}break;
}
- pred_last[ref]=frags[fragi].dc+=pred;
+ pred_last[refi]=frags[fragi].dc+=pred;
ncoded_fragis++;
- l_ref=ref;
+ l_ref=refi;
}
else l_ref=-1;
ul_ref=u_ref;
@@ -1495,7 +1502,7 @@ static void oc_dec_dc_unpredict_mcu_plane(oc_dec_ctx *_dec,
/*Reconstructs all coded fragments in a single MCU (one or two super block
rows).
This requires that each coded fragment have a proper macro block mode and
- motion vector (if not in INTRA mode), and have it's DC value decoded, with
+ motion vector (if not in INTRA mode), and have its DC value decoded, with
the DC prediction process reversed, and the number of coded and uncoded
fragments in this plane of the MCU be counted.
The token lists for each color plane and coefficient should also be filled
@@ -1522,16 +1529,11 @@ static void oc_dec_frags_recon_mcu_plane(oc_dec_ctx *_dec,
eob_runs=_pipe->eob_runs[_pli];
for(qti=0;qti<2;qti++)dc_quant[qti]=_pipe->dequant[_pli][0][qti][0];
for(fragii=0;fragii<ncoded_fragis;fragii++){
- /*This array is made one element larger because the zig-zag index array
- uses the final element as a dumping ground for out-of-range indices
- to protect us from buffer overflow.*/
- OC_ALIGN8(ogg_int16_t dct_coeffs[65]);
const ogg_uint16_t *ac_quant;
ptrdiff_t fragi;
int last_zzi;
int zzi;
fragi=coded_fragis[fragii];
- for(zzi=0;zzi<64;zzi++)dct_coeffs[zzi]=0;
qti=frags[fragi].mb_mode!=OC_MODE_INTRA;
ac_quant=_pipe->dequant[_pli][frags[fragi].qii][qti];
/*Decode the AC coefficients.*/
@@ -1568,18 +1570,19 @@ static void oc_dec_frags_recon_mcu_plane(oc_dec_ctx *_dec,
eob_runs[zzi]=eob;
ti[zzi]=lti;
zzi+=rlen;
- dct_coeffs[dct_fzig_zag[zzi]]=(ogg_int16_t)(coeff*(int)ac_quant[zzi]);
+ _pipe->dct_coeffs[dct_fzig_zag[zzi]]=
+ (ogg_int16_t)(coeff*(int)ac_quant[zzi]);
zzi+=!eob;
}
}
/*TODO: zzi should be exactly 64 here.
If it's not, we should report some kind of warning.*/
zzi=OC_MINI(zzi,64);
- dct_coeffs[0]=(ogg_int16_t)frags[fragi].dc;
+ _pipe->dct_coeffs[0]=(ogg_int16_t)frags[fragi].dc;
/*last_zzi is always initialized.
If your compiler thinks otherwise, it is dumb.*/
oc_state_frag_recon(&_dec->state,fragi,_pli,
- dct_coeffs,last_zzi,dc_quant[qti]);
+ _pipe->dct_coeffs,last_zzi,dc_quant[qti]);
}
_pipe->coded_fragis[_pli]+=ncoded_fragis;
/*Right now the reconstructed MCU has only the coded blocks in it.*/
@@ -1593,9 +1596,14 @@ static void oc_dec_frags_recon_mcu_plane(oc_dec_ctx *_dec,
code, and the hard case (high bitrate, high resolution) is handled
correctly.*/
/*Copy the uncoded blocks from the previous reference frame.*/
- _pipe->uncoded_fragis[_pli]-=_pipe->nuncoded_fragis[_pli];
- oc_state_frag_copy_list(&_dec->state,_pipe->uncoded_fragis[_pli],
- _pipe->nuncoded_fragis[_pli],OC_FRAME_SELF,OC_FRAME_PREV,_pli);
+ if(_pipe->nuncoded_fragis[_pli]>0){
+ _pipe->uncoded_fragis[_pli]-=_pipe->nuncoded_fragis[_pli];
+ oc_frag_copy_list(&_dec->state,
+ _dec->state.ref_frame_data[OC_FRAME_SELF],
+ _dec->state.ref_frame_data[OC_FRAME_PREV],
+ _dec->state.ref_ystride[_pli],_pipe->uncoded_fragis[_pli],
+ _pipe->nuncoded_fragis[_pli],_dec->state.frag_buf_offs);
+ }
}
/*Filter a horizontal block edge.*/
@@ -1953,9 +1961,9 @@ static void oc_dec_dering_frag_rows(oc_dec_ctx *_dec,th_img_plane *_img,
th_dec_ctx *th_decode_alloc(const th_info *_info,const th_setup_info *_setup){
oc_dec_ctx *dec;
if(_info==NULL||_setup==NULL)return NULL;
- dec=_ogg_malloc(sizeof(*dec));
+ dec=oc_aligned_malloc(sizeof(*dec),16);
if(dec==NULL||oc_dec_init(dec,_info,_setup)<0){
- _ogg_free(dec);
+ oc_aligned_free(dec);
return NULL;
}
dec->state.curframe_num=0;
@@ -1965,7 +1973,7 @@ th_dec_ctx *th_decode_alloc(const th_info *_info,const th_setup_info *_setup){
void th_decode_free(th_dec_ctx *_dec){
if(_dec!=NULL){
oc_dec_clear(_dec);
- _ogg_free(_dec);
+ oc_aligned_free(_dec);
}
}
@@ -2013,28 +2021,24 @@ int th_decode_ctl(th_dec_ctx *_dec,int _req,void *_buf,
case TH_DECCTL_SET_TELEMETRY_MBMODE:{
if(_dec==NULL||_buf==NULL)return TH_EFAULT;
if(_buf_sz!=sizeof(int))return TH_EINVAL;
- _dec->telemetry=1;
_dec->telemetry_mbmode=*(int *)_buf;
return 0;
}break;
case TH_DECCTL_SET_TELEMETRY_MV:{
if(_dec==NULL||_buf==NULL)return TH_EFAULT;
if(_buf_sz!=sizeof(int))return TH_EINVAL;
- _dec->telemetry=1;
_dec->telemetry_mv=*(int *)_buf;
return 0;
}break;
case TH_DECCTL_SET_TELEMETRY_QI:{
if(_dec==NULL||_buf==NULL)return TH_EFAULT;
if(_buf_sz!=sizeof(int))return TH_EINVAL;
- _dec->telemetry=1;
_dec->telemetry_qi=*(int *)_buf;
return 0;
}break;
case TH_DECCTL_SET_TELEMETRY_BITS:{
if(_dec==NULL||_buf==NULL)return TH_EFAULT;
if(_buf_sz!=sizeof(int))return TH_EINVAL;
- _dec->telemetry=1;
_dec->telemetry_bits=*(int *)_buf;
return 0;
}break;
@@ -2047,63 +2051,751 @@ int th_decode_ctl(th_dec_ctx *_dec,int _req,void *_buf,
buffers (i.e., decoding did not start on a key frame).
We initialize them to a solid gray here.*/
static void oc_dec_init_dummy_frame(th_dec_ctx *_dec){
- th_info *info;
- size_t yplane_sz;
- size_t cplane_sz;
- int yhstride;
- int yheight;
- int chstride;
- int cheight;
+ th_info *info;
+ size_t yplane_sz;
+ size_t cplane_sz;
+ ptrdiff_t yoffset;
+ int yhstride;
+ int yheight;
+ int chstride;
+ int cheight;
_dec->state.ref_frame_idx[OC_FRAME_GOLD]=0;
_dec->state.ref_frame_idx[OC_FRAME_PREV]=0;
- _dec->state.ref_frame_idx[OC_FRAME_SELF]=1;
+ _dec->state.ref_frame_idx[OC_FRAME_SELF]=0;
+ _dec->state.ref_frame_data[OC_FRAME_GOLD]=
+ _dec->state.ref_frame_data[OC_FRAME_PREV]=
+ _dec->state.ref_frame_data[OC_FRAME_SELF]=
+ _dec->state.ref_frame_bufs[0][0].data;
+ memcpy(_dec->pp_frame_buf,_dec->state.ref_frame_bufs[0],
+ sizeof(_dec->pp_frame_buf[0])*3);
info=&_dec->state.info;
- yhstride=info->frame_width+2*OC_UMV_PADDING;
+ yhstride=abs(_dec->state.ref_ystride[0]);
yheight=info->frame_height+2*OC_UMV_PADDING;
- chstride=yhstride>>!(info->pixel_fmt&1);
+ chstride=abs(_dec->state.ref_ystride[1]);
cheight=yheight>>!(info->pixel_fmt&2);
- yplane_sz=yhstride*(size_t)yheight;
+ yplane_sz=yhstride*(size_t)yheight+16;
cplane_sz=chstride*(size_t)cheight;
- memset(_dec->state.ref_frame_data[0],0x80,yplane_sz+2*cplane_sz);
+ yoffset=yhstride*(ptrdiff_t)(yheight-OC_UMV_PADDING-1)+OC_UMV_PADDING;
+ memset(_dec->state.ref_frame_data[0]-yoffset,0x80,yplane_sz+2*cplane_sz);
+}
+
+#if defined(HAVE_CAIRO)
+static void oc_render_telemetry(th_dec_ctx *_dec,th_ycbcr_buffer _ycbcr,
+ int _telemetry){
+ /*Stuff the plane into cairo.*/
+ cairo_surface_t *cs;
+ unsigned char *data;
+ unsigned char *y_row;
+ unsigned char *u_row;
+ unsigned char *v_row;
+ unsigned char *rgb_row;
+ int cstride;
+ int w;
+ int h;
+ int x;
+ int y;
+ int hdec;
+ int vdec;
+ w=_ycbcr[0].width;
+ h=_ycbcr[0].height;
+ hdec=!(_dec->state.info.pixel_fmt&1);
+ vdec=!(_dec->state.info.pixel_fmt&2);
+ /*Lazy data buffer init.
+ We could try to re-use the post-processing buffer, which would save
+ memory, but complicate the allocation logic there.
+ I don't think anyone cares about memory usage when using telemetry; it is
+ not meant for embedded devices.*/
+ if(_dec->telemetry_frame_data==NULL){
+ _dec->telemetry_frame_data=_ogg_malloc(
+ (w*h+2*(w>>hdec)*(h>>vdec))*sizeof(*_dec->telemetry_frame_data));
+ if(_dec->telemetry_frame_data==NULL)return;
+ }
+ cs=cairo_image_surface_create(CAIRO_FORMAT_RGB24,w,h);
+ /*Sadly, no YUV support in Cairo (yet); convert into the RGB buffer.*/
+ data=cairo_image_surface_get_data(cs);
+ if(data==NULL){
+ cairo_surface_destroy(cs);
+ return;
+ }
+ cstride=cairo_image_surface_get_stride(cs);
+ y_row=_ycbcr[0].data;
+ u_row=_ycbcr[1].data;
+ v_row=_ycbcr[2].data;
+ rgb_row=data;
+ for(y=0;y<h;y++){
+ for(x=0;x<w;x++){
+ int r;
+ int g;
+ int b;
+ r=(1904000*y_row[x]+2609823*v_row[x>>hdec]-363703744)/1635200;
+ g=(3827562*y_row[x]-1287801*u_row[x>>hdec]
+ -2672387*v_row[x>>hdec]+447306710)/3287200;
+ b=(952000*y_row[x]+1649289*u_row[x>>hdec]-225932192)/817600;
+ rgb_row[4*x+0]=OC_CLAMP255(b);
+ rgb_row[4*x+1]=OC_CLAMP255(g);
+ rgb_row[4*x+2]=OC_CLAMP255(r);
+ }
+ y_row+=_ycbcr[0].stride;
+ u_row+=_ycbcr[1].stride&-((y&1)|!vdec);
+ v_row+=_ycbcr[2].stride&-((y&1)|!vdec);
+ rgb_row+=cstride;
+ }
+ /*Draw coded identifier for each macroblock (stored in Hilbert order).*/
+ {
+ cairo_t *c;
+ const oc_fragment *frags;
+ oc_mv *frag_mvs;
+ const signed char *mb_modes;
+ oc_mb_map *mb_maps;
+ size_t nmbs;
+ size_t mbi;
+ int row2;
+ int col2;
+ int qim[3]={0,0,0};
+ if(_dec->state.nqis==2){
+ int bqi;
+ bqi=_dec->state.qis[0];
+ if(_dec->state.qis[1]>bqi)qim[1]=1;
+ if(_dec->state.qis[1]<bqi)qim[1]=-1;
+ }
+ if(_dec->state.nqis==3){
+ int bqi;
+ int cqi;
+ int dqi;
+ bqi=_dec->state.qis[0];
+ cqi=_dec->state.qis[1];
+ dqi=_dec->state.qis[2];
+ if(cqi>bqi&&dqi>bqi){
+ if(dqi>cqi){
+ qim[1]=1;
+ qim[2]=2;
+ }
+ else{
+ qim[1]=2;
+ qim[2]=1;
+ }
+ }
+ else if(cqi<bqi&&dqi<bqi){
+ if(dqi<cqi){
+ qim[1]=-1;
+ qim[2]=-2;
+ }
+ else{
+ qim[1]=-2;
+ qim[2]=-1;
+ }
+ }
+ else{
+ if(cqi<bqi)qim[1]=-1;
+ else qim[1]=1;
+ if(dqi<bqi)qim[2]=-1;
+ else qim[2]=1;
+ }
+ }
+ c=cairo_create(cs);
+ frags=_dec->state.frags;
+ frag_mvs=_dec->state.frag_mvs;
+ mb_modes=_dec->state.mb_modes;
+ mb_maps=_dec->state.mb_maps;
+ nmbs=_dec->state.nmbs;
+ row2=0;
+ col2=0;
+ for(mbi=0;mbi<nmbs;mbi++){
+ float x;
+ float y;
+ int bi;
+ y=h-(row2+((col2+1>>1)&1))*16-16;
+ x=(col2>>1)*16;
+ cairo_set_line_width(c,1.);
+ /*Keyframe (all intra) red box.*/
+ if(_dec->state.frame_type==OC_INTRA_FRAME){
+ if(_dec->telemetry_mbmode&0x02){
+ cairo_set_source_rgba(c,1.,0,0,.5);
+ cairo_rectangle(c,x+2.5,y+2.5,11,11);
+ cairo_stroke_preserve(c);
+ cairo_set_source_rgba(c,1.,0,0,.25);
+ cairo_fill(c);
+ }
+ }
+ else{
+ ptrdiff_t fragi;
+ int frag_mvx;
+ int frag_mvy;
+ for(bi=0;bi<4;bi++){
+ fragi=mb_maps[mbi][0][bi];
+ if(fragi>=0&&frags[fragi].coded){
+ frag_mvx=OC_MV_X(frag_mvs[fragi]);
+ frag_mvy=OC_MV_Y(frag_mvs[fragi]);
+ break;
+ }
+ }
+ if(bi<4){
+ switch(mb_modes[mbi]){
+ case OC_MODE_INTRA:{
+ if(_dec->telemetry_mbmode&0x02){
+ cairo_set_source_rgba(c,1.,0,0,.5);
+ cairo_rectangle(c,x+2.5,y+2.5,11,11);
+ cairo_stroke_preserve(c);
+ cairo_set_source_rgba(c,1.,0,0,.25);
+ cairo_fill(c);
+ }
+ }break;
+ case OC_MODE_INTER_NOMV:{
+ if(_dec->telemetry_mbmode&0x01){
+ cairo_set_source_rgba(c,0,0,1.,.5);
+ cairo_rectangle(c,x+2.5,y+2.5,11,11);
+ cairo_stroke_preserve(c);
+ cairo_set_source_rgba(c,0,0,1.,.25);
+ cairo_fill(c);
+ }
+ }break;
+ case OC_MODE_INTER_MV:{
+ if(_dec->telemetry_mbmode&0x04){
+ cairo_rectangle(c,x+2.5,y+2.5,11,11);
+ cairo_set_source_rgba(c,0,1.,0,.5);
+ cairo_stroke(c);
+ }
+ if(_dec->telemetry_mv&0x04){
+ cairo_move_to(c,x+8+frag_mvx,y+8-frag_mvy);
+ cairo_set_source_rgba(c,1.,1.,1.,.9);
+ cairo_set_line_width(c,3.);
+ cairo_line_to(c,x+8+frag_mvx*.66,y+8-frag_mvy*.66);
+ cairo_stroke_preserve(c);
+ cairo_set_line_width(c,2.);
+ cairo_line_to(c,x+8+frag_mvx*.33,y+8-frag_mvy*.33);
+ cairo_stroke_preserve(c);
+ cairo_set_line_width(c,1.);
+ cairo_line_to(c,x+8,y+8);
+ cairo_stroke(c);
+ }
+ }break;
+ case OC_MODE_INTER_MV_LAST:{
+ if(_dec->telemetry_mbmode&0x08){
+ cairo_rectangle(c,x+2.5,y+2.5,11,11);
+ cairo_set_source_rgba(c,0,1.,0,.5);
+ cairo_move_to(c,x+13.5,y+2.5);
+ cairo_line_to(c,x+2.5,y+8);
+ cairo_line_to(c,x+13.5,y+13.5);
+ cairo_stroke(c);
+ }
+ if(_dec->telemetry_mv&0x08){
+ cairo_move_to(c,x+8+frag_mvx,y+8-frag_mvy);
+ cairo_set_source_rgba(c,1.,1.,1.,.9);
+ cairo_set_line_width(c,3.);
+ cairo_line_to(c,x+8+frag_mvx*.66,y+8-frag_mvy*.66);
+ cairo_stroke_preserve(c);
+ cairo_set_line_width(c,2.);
+ cairo_line_to(c,x+8+frag_mvx*.33,y+8-frag_mvy*.33);
+ cairo_stroke_preserve(c);
+ cairo_set_line_width(c,1.);
+ cairo_line_to(c,x+8,y+8);
+ cairo_stroke(c);
+ }
+ }break;
+ case OC_MODE_INTER_MV_LAST2:{
+ if(_dec->telemetry_mbmode&0x10){
+ cairo_rectangle(c,x+2.5,y+2.5,11,11);
+ cairo_set_source_rgba(c,0,1.,0,.5);
+ cairo_move_to(c,x+8,y+2.5);
+ cairo_line_to(c,x+2.5,y+8);
+ cairo_line_to(c,x+8,y+13.5);
+ cairo_move_to(c,x+13.5,y+2.5);
+ cairo_line_to(c,x+8,y+8);
+ cairo_line_to(c,x+13.5,y+13.5);
+ cairo_stroke(c);
+ }
+ if(_dec->telemetry_mv&0x10){
+ cairo_move_to(c,x+8+frag_mvx,y+8-frag_mvy);
+ cairo_set_source_rgba(c,1.,1.,1.,.9);
+ cairo_set_line_width(c,3.);
+ cairo_line_to(c,x+8+frag_mvx*.66,y+8-frag_mvy*.66);
+ cairo_stroke_preserve(c);
+ cairo_set_line_width(c,2.);
+ cairo_line_to(c,x+8+frag_mvx*.33,y+8-frag_mvy*.33);
+ cairo_stroke_preserve(c);
+ cairo_set_line_width(c,1.);
+ cairo_line_to(c,x+8,y+8);
+ cairo_stroke(c);
+ }
+ }break;
+ case OC_MODE_GOLDEN_NOMV:{
+ if(_dec->telemetry_mbmode&0x20){
+ cairo_set_source_rgba(c,1.,1.,0,.5);
+ cairo_rectangle(c,x+2.5,y+2.5,11,11);
+ cairo_stroke_preserve(c);
+ cairo_set_source_rgba(c,1.,1.,0,.25);
+ cairo_fill(c);
+ }
+ }break;
+ case OC_MODE_GOLDEN_MV:{
+ if(_dec->telemetry_mbmode&0x40){
+ cairo_rectangle(c,x+2.5,y+2.5,11,11);
+ cairo_set_source_rgba(c,1.,1.,0,.5);
+ cairo_stroke(c);
+ }
+ if(_dec->telemetry_mv&0x40){
+ cairo_move_to(c,x+8+frag_mvx,y+8-frag_mvy);
+ cairo_set_source_rgba(c,1.,1.,1.,.9);
+ cairo_set_line_width(c,3.);
+ cairo_line_to(c,x+8+frag_mvx*.66,y+8-frag_mvy*.66);
+ cairo_stroke_preserve(c);
+ cairo_set_line_width(c,2.);
+ cairo_line_to(c,x+8+frag_mvx*.33,y+8-frag_mvy*.33);
+ cairo_stroke_preserve(c);
+ cairo_set_line_width(c,1.);
+ cairo_line_to(c,x+8,y+8);
+ cairo_stroke(c);
+ }
+ }break;
+ case OC_MODE_INTER_MV_FOUR:{
+ if(_dec->telemetry_mbmode&0x80){
+ cairo_rectangle(c,x+2.5,y+2.5,4,4);
+ cairo_rectangle(c,x+9.5,y+2.5,4,4);
+ cairo_rectangle(c,x+2.5,y+9.5,4,4);
+ cairo_rectangle(c,x+9.5,y+9.5,4,4);
+ cairo_set_source_rgba(c,0,1.,0,.5);
+ cairo_stroke(c);
+ }
+ /*4mv is odd, coded in raster order.*/
+ fragi=mb_maps[mbi][0][0];
+ if(frags[fragi].coded&&_dec->telemetry_mv&0x80){
+ frag_mvx=OC_MV_X(frag_mvs[fragi]);
+ frag_mvx=OC_MV_Y(frag_mvs[fragi]);
+ cairo_move_to(c,x+4+frag_mvx,y+12-frag_mvy);
+ cairo_set_source_rgba(c,1.,1.,1.,.9);
+ cairo_set_line_width(c,3.);
+ cairo_line_to(c,x+4+frag_mvx*.66,y+12-frag_mvy*.66);
+ cairo_stroke_preserve(c);
+ cairo_set_line_width(c,2.);
+ cairo_line_to(c,x+4+frag_mvx*.33,y+12-frag_mvy*.33);
+ cairo_stroke_preserve(c);
+ cairo_set_line_width(c,1.);
+ cairo_line_to(c,x+4,y+12);
+ cairo_stroke(c);
+ }
+ fragi=mb_maps[mbi][0][1];
+ if(frags[fragi].coded&&_dec->telemetry_mv&0x80){
+ frag_mvx=OC_MV_X(frag_mvs[fragi]);
+ frag_mvx=OC_MV_Y(frag_mvs[fragi]);
+ cairo_move_to(c,x+12+frag_mvx,y+12-frag_mvy);
+ cairo_set_source_rgba(c,1.,1.,1.,.9);
+ cairo_set_line_width(c,3.);
+ cairo_line_to(c,x+12+frag_mvx*.66,y+12-frag_mvy*.66);
+ cairo_stroke_preserve(c);
+ cairo_set_line_width(c,2.);
+ cairo_line_to(c,x+12+frag_mvx*.33,y+12-frag_mvy*.33);
+ cairo_stroke_preserve(c);
+ cairo_set_line_width(c,1.);
+ cairo_line_to(c,x+12,y+12);
+ cairo_stroke(c);
+ }
+ fragi=mb_maps[mbi][0][2];
+ if(frags[fragi].coded&&_dec->telemetry_mv&0x80){
+ frag_mvx=OC_MV_X(frag_mvs[fragi]);
+ frag_mvx=OC_MV_Y(frag_mvs[fragi]);
+ cairo_move_to(c,x+4+frag_mvx,y+4-frag_mvy);
+ cairo_set_source_rgba(c,1.,1.,1.,.9);
+ cairo_set_line_width(c,3.);
+ cairo_line_to(c,x+4+frag_mvx*.66,y+4-frag_mvy*.66);
+ cairo_stroke_preserve(c);
+ cairo_set_line_width(c,2.);
+ cairo_line_to(c,x+4+frag_mvx*.33,y+4-frag_mvy*.33);
+ cairo_stroke_preserve(c);
+ cairo_set_line_width(c,1.);
+ cairo_line_to(c,x+4,y+4);
+ cairo_stroke(c);
+ }
+ fragi=mb_maps[mbi][0][3];
+ if(frags[fragi].coded&&_dec->telemetry_mv&0x80){
+ frag_mvx=OC_MV_X(frag_mvs[fragi]);
+ frag_mvx=OC_MV_Y(frag_mvs[fragi]);
+ cairo_move_to(c,x+12+frag_mvx,y+4-frag_mvy);
+ cairo_set_source_rgba(c,1.,1.,1.,.9);
+ cairo_set_line_width(c,3.);
+ cairo_line_to(c,x+12+frag_mvx*.66,y+4-frag_mvy*.66);
+ cairo_stroke_preserve(c);
+ cairo_set_line_width(c,2.);
+ cairo_line_to(c,x+12+frag_mvx*.33,y+4-frag_mvy*.33);
+ cairo_stroke_preserve(c);
+ cairo_set_line_width(c,1.);
+ cairo_line_to(c,x+12,y+4);
+ cairo_stroke(c);
+ }
+ }break;
+ }
+ }
+ }
+ /*qii illustration.*/
+ if(_dec->telemetry_qi&0x2){
+ cairo_set_line_cap(c,CAIRO_LINE_CAP_SQUARE);
+ for(bi=0;bi<4;bi++){
+ ptrdiff_t fragi;
+ int qiv;
+ int xp;
+ int yp;
+ xp=x+(bi&1)*8;
+ yp=y+8-(bi&2)*4;
+ fragi=mb_maps[mbi][0][bi];
+ if(fragi>=0&&frags[fragi].coded){
+ qiv=qim[frags[fragi].qii];
+ cairo_set_line_width(c,3.);
+ cairo_set_source_rgba(c,0.,0.,0.,.5);
+ switch(qiv){
+ /*Double plus:*/
+ case 2:{
+ if((bi&1)^((bi&2)>>1)){
+ cairo_move_to(c,xp+2.5,yp+1.5);
+ cairo_line_to(c,xp+2.5,yp+3.5);
+ cairo_move_to(c,xp+1.5,yp+2.5);
+ cairo_line_to(c,xp+3.5,yp+2.5);
+ cairo_move_to(c,xp+5.5,yp+4.5);
+ cairo_line_to(c,xp+5.5,yp+6.5);
+ cairo_move_to(c,xp+4.5,yp+5.5);
+ cairo_line_to(c,xp+6.5,yp+5.5);
+ cairo_stroke_preserve(c);
+ cairo_set_source_rgba(c,0.,1.,1.,1.);
+ }
+ else{
+ cairo_move_to(c,xp+5.5,yp+1.5);
+ cairo_line_to(c,xp+5.5,yp+3.5);
+ cairo_move_to(c,xp+4.5,yp+2.5);
+ cairo_line_to(c,xp+6.5,yp+2.5);
+ cairo_move_to(c,xp+2.5,yp+4.5);
+ cairo_line_to(c,xp+2.5,yp+6.5);
+ cairo_move_to(c,xp+1.5,yp+5.5);
+ cairo_line_to(c,xp+3.5,yp+5.5);
+ cairo_stroke_preserve(c);
+ cairo_set_source_rgba(c,0.,1.,1.,1.);
+ }
+ }break;
+ /*Double minus:*/
+ case -2:{
+ cairo_move_to(c,xp+2.5,yp+2.5);
+ cairo_line_to(c,xp+5.5,yp+2.5);
+ cairo_move_to(c,xp+2.5,yp+5.5);
+ cairo_line_to(c,xp+5.5,yp+5.5);
+ cairo_stroke_preserve(c);
+ cairo_set_source_rgba(c,1.,1.,1.,1.);
+ }break;
+ /*Plus:*/
+ case 1:{
+ if((bi&2)==0)yp-=2;
+ if((bi&1)==0)xp-=2;
+ cairo_move_to(c,xp+4.5,yp+2.5);
+ cairo_line_to(c,xp+4.5,yp+6.5);
+ cairo_move_to(c,xp+2.5,yp+4.5);
+ cairo_line_to(c,xp+6.5,yp+4.5);
+ cairo_stroke_preserve(c);
+ cairo_set_source_rgba(c,.1,1.,.3,1.);
+ break;
+ }
+ /*Fall through.*/
+ /*Minus:*/
+ case -1:{
+ cairo_move_to(c,xp+2.5,yp+4.5);
+ cairo_line_to(c,xp+6.5,yp+4.5);
+ cairo_stroke_preserve(c);
+ cairo_set_source_rgba(c,1.,.3,.1,1.);
+ }break;
+ default:continue;
+ }
+ cairo_set_line_width(c,1.);
+ cairo_stroke(c);
+ }
+ }
+ }
+ col2++;
+ if((col2>>1)>=_dec->state.nhmbs){
+ col2=0;
+ row2+=2;
+ }
+ }
+ /*Bit usage indicator[s]:*/
+ if(_dec->telemetry_bits){
+ int widths[6];
+ int fpsn;
+ int fpsd;
+ int mult;
+ int fullw;
+ int padw;
+ int i;
+ fpsn=_dec->state.info.fps_numerator;
+ fpsd=_dec->state.info.fps_denominator;
+ mult=(_dec->telemetry_bits>=0xFF?1:_dec->telemetry_bits);
+ fullw=250.f*h*fpsd*mult/fpsn;
+ padw=w-24;
+ /*Header and coded block bits.*/
+ if(_dec->telemetry_frame_bytes<0||
+ _dec->telemetry_frame_bytes==OC_LOTS_OF_BITS){
+ _dec->telemetry_frame_bytes=0;
+ }
+ if(_dec->telemetry_coding_bytes<0||
+ _dec->telemetry_coding_bytes>_dec->telemetry_frame_bytes){
+ _dec->telemetry_coding_bytes=0;
+ }
+ if(_dec->telemetry_mode_bytes<0||
+ _dec->telemetry_mode_bytes>_dec->telemetry_frame_bytes){
+ _dec->telemetry_mode_bytes=0;
+ }
+ if(_dec->telemetry_mv_bytes<0||
+ _dec->telemetry_mv_bytes>_dec->telemetry_frame_bytes){
+ _dec->telemetry_mv_bytes=0;
+ }
+ if(_dec->telemetry_qi_bytes<0||
+ _dec->telemetry_qi_bytes>_dec->telemetry_frame_bytes){
+ _dec->telemetry_qi_bytes=0;
+ }
+ if(_dec->telemetry_dc_bytes<0||
+ _dec->telemetry_dc_bytes>_dec->telemetry_frame_bytes){
+ _dec->telemetry_dc_bytes=0;
+ }
+ widths[0]=padw*
+ (_dec->telemetry_frame_bytes-_dec->telemetry_coding_bytes)/fullw;
+ widths[1]=padw*
+ (_dec->telemetry_coding_bytes-_dec->telemetry_mode_bytes)/fullw;
+ widths[2]=padw*
+ (_dec->telemetry_mode_bytes-_dec->telemetry_mv_bytes)/fullw;
+ widths[3]=padw*(_dec->telemetry_mv_bytes-_dec->telemetry_qi_bytes)/fullw;
+ widths[4]=padw*(_dec->telemetry_qi_bytes-_dec->telemetry_dc_bytes)/fullw;
+ widths[5]=padw*(_dec->telemetry_dc_bytes)/fullw;
+ for(i=0;i<6;i++)if(widths[i]>w)widths[i]=w;
+ cairo_set_source_rgba(c,.0,.0,.0,.6);
+ cairo_rectangle(c,10,h-33,widths[0]+1,5);
+ cairo_rectangle(c,10,h-29,widths[1]+1,5);
+ cairo_rectangle(c,10,h-25,widths[2]+1,5);
+ cairo_rectangle(c,10,h-21,widths[3]+1,5);
+ cairo_rectangle(c,10,h-17,widths[4]+1,5);
+ cairo_rectangle(c,10,h-13,widths[5]+1,5);
+ cairo_fill(c);
+ cairo_set_source_rgb(c,1,0,0);
+ cairo_rectangle(c,10.5,h-32.5,widths[0],4);
+ cairo_fill(c);
+ cairo_set_source_rgb(c,0,1,0);
+ cairo_rectangle(c,10.5,h-28.5,widths[1],4);
+ cairo_fill(c);
+ cairo_set_source_rgb(c,0,0,1);
+ cairo_rectangle(c,10.5,h-24.5,widths[2],4);
+ cairo_fill(c);
+ cairo_set_source_rgb(c,.6,.4,.0);
+ cairo_rectangle(c,10.5,h-20.5,widths[3],4);
+ cairo_fill(c);
+ cairo_set_source_rgb(c,.3,.3,.3);
+ cairo_rectangle(c,10.5,h-16.5,widths[4],4);
+ cairo_fill(c);
+ cairo_set_source_rgb(c,.5,.5,.8);
+ cairo_rectangle(c,10.5,h-12.5,widths[5],4);
+ cairo_fill(c);
+ }
+ /*Master qi indicator[s]:*/
+ if(_dec->telemetry_qi&0x1){
+ cairo_text_extents_t extents;
+ char buffer[10];
+ int p;
+ int y;
+ p=0;
+ y=h-7.5;
+ if(_dec->state.qis[0]>=10)buffer[p++]=48+_dec->state.qis[0]/10;
+ buffer[p++]=48+_dec->state.qis[0]%10;
+ if(_dec->state.nqis>=2){
+ buffer[p++]=' ';
+ if(_dec->state.qis[1]>=10)buffer[p++]=48+_dec->state.qis[1]/10;
+ buffer[p++]=48+_dec->state.qis[1]%10;
+ }
+ if(_dec->state.nqis==3){
+ buffer[p++]=' ';
+ if(_dec->state.qis[2]>=10)buffer[p++]=48+_dec->state.qis[2]/10;
+ buffer[p++]=48+_dec->state.qis[2]%10;
+ }
+ buffer[p++]='\0';
+ cairo_select_font_face(c,"sans",
+ CAIRO_FONT_SLANT_NORMAL,CAIRO_FONT_WEIGHT_BOLD);
+ cairo_set_font_size(c,18);
+ cairo_text_extents(c,buffer,&extents);
+ cairo_set_source_rgb(c,1,1,1);
+ cairo_move_to(c,w-extents.x_advance-10,y);
+ cairo_show_text(c,buffer);
+ cairo_set_source_rgb(c,0,0,0);
+ cairo_move_to(c,w-extents.x_advance-10,y);
+ cairo_text_path(c,buffer);
+ cairo_set_line_width(c,.8);
+ cairo_set_line_join(c,CAIRO_LINE_JOIN_ROUND);
+ cairo_stroke(c);
+ }
+ cairo_destroy(c);
+ }
+ /*Out of the Cairo plane into the telemetry YUV buffer.*/
+ _ycbcr[0].data=_dec->telemetry_frame_data;
+ _ycbcr[0].stride=_ycbcr[0].width;
+ _ycbcr[1].data=_ycbcr[0].data+h*_ycbcr[0].stride;
+ _ycbcr[1].stride=_ycbcr[1].width;
+ _ycbcr[2].data=_ycbcr[1].data+(h>>vdec)*_ycbcr[1].stride;
+ _ycbcr[2].stride=_ycbcr[2].width;
+ y_row=_ycbcr[0].data;
+ u_row=_ycbcr[1].data;
+ v_row=_ycbcr[2].data;
+ rgb_row=data;
+ /*This is one of the few places it's worth handling chroma on a
+ case-by-case basis.*/
+ switch(_dec->state.info.pixel_fmt){
+ case TH_PF_420:{
+ for(y=0;y<h;y+=2){
+ unsigned char *y_row2;
+ unsigned char *rgb_row2;
+ y_row2=y_row+_ycbcr[0].stride;
+ rgb_row2=rgb_row+cstride;
+ for(x=0;x<w;x+=2){
+ int y;
+ int u;
+ int v;
+ y=(65481*rgb_row[4*x+2]+128553*rgb_row[4*x+1]
+ +24966*rgb_row[4*x+0]+4207500)/255000;
+ y_row[x]=OC_CLAMP255(y);
+ y=(65481*rgb_row[4*x+6]+128553*rgb_row[4*x+5]
+ +24966*rgb_row[4*x+4]+4207500)/255000;
+ y_row[x+1]=OC_CLAMP255(y);
+ y=(65481*rgb_row2[4*x+2]+128553*rgb_row2[4*x+1]
+ +24966*rgb_row2[4*x+0]+4207500)/255000;
+ y_row2[x]=OC_CLAMP255(y);
+ y=(65481*rgb_row2[4*x+6]+128553*rgb_row2[4*x+5]
+ +24966*rgb_row2[4*x+4]+4207500)/255000;
+ y_row2[x+1]=OC_CLAMP255(y);
+ u=(-8372*(rgb_row[4*x+2]+rgb_row[4*x+6]
+ +rgb_row2[4*x+2]+rgb_row2[4*x+6])
+ -16436*(rgb_row[4*x+1]+rgb_row[4*x+5]
+ +rgb_row2[4*x+1]+rgb_row2[4*x+5])
+ +24808*(rgb_row[4*x+0]+rgb_row[4*x+4]
+ +rgb_row2[4*x+0]+rgb_row2[4*x+4])+29032005)/225930;
+ v=(39256*(rgb_row[4*x+2]+rgb_row[4*x+6]
+ +rgb_row2[4*x+2]+rgb_row2[4*x+6])
+ -32872*(rgb_row[4*x+1]+rgb_row[4*x+5]
+ +rgb_row2[4*x+1]+rgb_row2[4*x+5])
+ -6384*(rgb_row[4*x+0]+rgb_row[4*x+4]
+ +rgb_row2[4*x+0]+rgb_row2[4*x+4])+45940035)/357510;
+ u_row[x>>1]=OC_CLAMP255(u);
+ v_row[x>>1]=OC_CLAMP255(v);
+ }
+ y_row+=_ycbcr[0].stride<<1;
+ u_row+=_ycbcr[1].stride;
+ v_row+=_ycbcr[2].stride;
+ rgb_row+=cstride<<1;
+ }
+ }break;
+ case TH_PF_422:{
+ for(y=0;y<h;y++){
+ for(x=0;x<w;x+=2){
+ int y;
+ int u;
+ int v;
+ y=(65481*rgb_row[4*x+2]+128553*rgb_row[4*x+1]
+ +24966*rgb_row[4*x+0]+4207500)/255000;
+ y_row[x]=OC_CLAMP255(y);
+ y=(65481*rgb_row[4*x+6]+128553*rgb_row[4*x+5]
+ +24966*rgb_row[4*x+4]+4207500)/255000;
+ y_row[x+1]=OC_CLAMP255(y);
+ u=(-16744*(rgb_row[4*x+2]+rgb_row[4*x+6])
+ -32872*(rgb_row[4*x+1]+rgb_row[4*x+5])
+ +49616*(rgb_row[4*x+0]+rgb_row[4*x+4])+29032005)/225930;
+ v=(78512*(rgb_row[4*x+2]+rgb_row[4*x+6])
+ -65744*(rgb_row[4*x+1]+rgb_row[4*x+5])
+ -12768*(rgb_row[4*x+0]+rgb_row[4*x+4])+45940035)/357510;
+ u_row[x>>1]=OC_CLAMP255(u);
+ v_row[x>>1]=OC_CLAMP255(v);
+ }
+ y_row+=_ycbcr[0].stride;
+ u_row+=_ycbcr[1].stride;
+ v_row+=_ycbcr[2].stride;
+ rgb_row+=cstride;
+ }
+ }break;
+ /*case TH_PF_444:*/
+ default:{
+ for(y=0;y<h;y++){
+ for(x=0;x<w;x++){
+ int y;
+ int u;
+ int v;
+ y=(65481*rgb_row[4*x+2]+128553*rgb_row[4*x+1]
+ +24966*rgb_row[4*x+0]+4207500)/255000;
+ u=(-33488*rgb_row[4*x+2]-65744*rgb_row[4*x+1]
+ +99232*rgb_row[4*x+0]+29032005)/225930;
+ v=(157024*rgb_row[4*x+2]-131488*rgb_row[4*x+1]
+ -25536*rgb_row[4*x+0]+45940035)/357510;
+ y_row[x]=OC_CLAMP255(y);
+ u_row[x]=OC_CLAMP255(u);
+ v_row[x]=OC_CLAMP255(v);
+ }
+ y_row+=_ycbcr[0].stride;
+ u_row+=_ycbcr[1].stride;
+ v_row+=_ycbcr[2].stride;
+ rgb_row+=cstride;
+ }
+ }break;
+ }
+ /*Finished.
+ Destroy the surface.*/
+ cairo_surface_destroy(cs);
}
+#endif
int th_decode_packetin(th_dec_ctx *_dec,const ogg_packet *_op,
ogg_int64_t *_granpos){
int ret;
if(_dec==NULL||_op==NULL)return TH_EFAULT;
/*A completely empty packet indicates a dropped frame and is treated exactly
- like an inter frame with no coded blocks.
- Only proceed if we have a non-empty packet.*/
- if(_op->bytes!=0){
- oc_dec_pipeline_state pipe;
- th_ycbcr_buffer stripe_buf;
- int stripe_fragy;
- int refi;
- int pli;
- int notstart;
- int notdone;
+ like an inter frame with no coded blocks.*/
+ if(_op->bytes==0){
+ _dec->state.frame_type=OC_INTER_FRAME;
+ _dec->state.ntotal_coded_fragis=0;
+ }
+ else{
oc_pack_readinit(&_dec->opb,_op->packet,_op->bytes);
+ ret=oc_dec_frame_header_unpack(_dec);
+ if(ret<0)return ret;
+ if(_dec->state.frame_type==OC_INTRA_FRAME)oc_dec_mark_all_intra(_dec);
+ else oc_dec_coded_flags_unpack(_dec);
+ }
+ /*If there have been no reference frames, and we need one, initialize one.*/
+ if(_dec->state.frame_type!=OC_INTRA_FRAME&&
+ (_dec->state.ref_frame_idx[OC_FRAME_GOLD]<0||
+ _dec->state.ref_frame_idx[OC_FRAME_PREV]<0)){
+ oc_dec_init_dummy_frame(_dec);
+ }
+ /*If this was an inter frame with no coded blocks...*/
+ if(_dec->state.ntotal_coded_fragis<=0){
+ /*Just update the granule position and return.*/
+ _dec->state.granpos=(_dec->state.keyframe_num+_dec->state.granpos_bias<<
+ _dec->state.info.keyframe_granule_shift)
+ +(_dec->state.curframe_num-_dec->state.keyframe_num);
+ _dec->state.curframe_num++;
+ if(_granpos!=NULL)*_granpos=_dec->state.granpos;
+ return TH_DUPFRAME;
+ }
+ else{
+ th_ycbcr_buffer stripe_buf;
+ int stripe_fragy;
+ int refi;
+ int pli;
+ int notstart;
+ int notdone;
+#ifdef HAVE_CAIRO
+ int telemetry;
+ /*Save the current telemetry state.
+ This prevents it from being modified in the middle of decoding this
+ frame, which could cause us to skip calls to the striped decoding
+ callback.*/
+ telemetry=_dec->telemetry_mbmode||_dec->telemetry_mv||
+ _dec->telemetry_qi||_dec->telemetry_bits;
+#endif
+ /*Select a free buffer to use for the reconstructed version of this frame.*/
+ for(refi=0;refi==_dec->state.ref_frame_idx[OC_FRAME_GOLD]||
+ refi==_dec->state.ref_frame_idx[OC_FRAME_PREV];refi++);
+ _dec->state.ref_frame_idx[OC_FRAME_SELF]=refi;
+ _dec->state.ref_frame_data[OC_FRAME_SELF]=
+ _dec->state.ref_frame_bufs[refi][0].data;
#if defined(HAVE_CAIRO)
_dec->telemetry_frame_bytes=_op->bytes;
#endif
- ret=oc_dec_frame_header_unpack(_dec);
- if(ret<0)return ret;
- /*Select a free buffer to use for the reconstructed version of this
- frame.*/
- if(_dec->state.frame_type!=OC_INTRA_FRAME&&
- (_dec->state.ref_frame_idx[OC_FRAME_GOLD]<0||
- _dec->state.ref_frame_idx[OC_FRAME_PREV]<0)){
- /*No reference frames yet!*/
- oc_dec_init_dummy_frame(_dec);
- refi=_dec->state.ref_frame_idx[OC_FRAME_SELF];
- }
- else{
- for(refi=0;refi==_dec->state.ref_frame_idx[OC_FRAME_GOLD]||
- refi==_dec->state.ref_frame_idx[OC_FRAME_PREV];refi++);
- _dec->state.ref_frame_idx[OC_FRAME_SELF]=refi;
- }
if(_dec->state.frame_type==OC_INTRA_FRAME){
- oc_dec_mark_all_intra(_dec);
_dec->state.keyframe_num=_dec->state.curframe_num;
#if defined(HAVE_CAIRO)
_dec->telemetry_coding_bytes=
@@ -2112,7 +2804,6 @@ int th_decode_packetin(th_dec_ctx *_dec,const ogg_packet *_op,
#endif
}
else{
- oc_dec_coded_flags_unpack(_dec);
#if defined(HAVE_CAIRO)
_dec->telemetry_coding_bytes=oc_pack_bytes_left(&_dec->opb);
#endif
@@ -2160,15 +2851,15 @@ int th_decode_packetin(th_dec_ctx *_dec,const ogg_packet *_op,
An application callback allows further application processing (blitting
to video memory, color conversion, etc.) to also use the data while it's
in cache.*/
- oc_dec_pipeline_init(_dec,&pipe);
+ oc_dec_pipeline_init(_dec,&_dec->pipe);
oc_ycbcr_buffer_flip(stripe_buf,_dec->pp_frame_buf);
notstart=0;
notdone=1;
- for(stripe_fragy=0;notdone;stripe_fragy+=pipe.mcu_nvfrags){
+ for(stripe_fragy=0;notdone;stripe_fragy+=_dec->pipe.mcu_nvfrags){
int avail_fragy0;
int avail_fragy_end;
avail_fragy0=avail_fragy_end=_dec->state.fplanes[0].nvfrags;
- notdone=stripe_fragy+pipe.mcu_nvfrags<avail_fragy_end;
+ notdone=stripe_fragy+_dec->pipe.mcu_nvfrags<avail_fragy_end;
for(pli=0;pli<3;pli++){
oc_fragment_plane *fplane;
int frag_shift;
@@ -2179,45 +2870,46 @@ int th_decode_packetin(th_dec_ctx *_dec,const ogg_packet *_op,
/*Compute the first and last fragment row of the current MCU for this
plane.*/
frag_shift=pli!=0&&!(_dec->state.info.pixel_fmt&2);
- pipe.fragy0[pli]=stripe_fragy>>frag_shift;
- pipe.fragy_end[pli]=OC_MINI(fplane->nvfrags,
- pipe.fragy0[pli]+(pipe.mcu_nvfrags>>frag_shift));
- oc_dec_dc_unpredict_mcu_plane(_dec,&pipe,pli);
- oc_dec_frags_recon_mcu_plane(_dec,&pipe,pli);
+ _dec->pipe.fragy0[pli]=stripe_fragy>>frag_shift;
+ _dec->pipe.fragy_end[pli]=OC_MINI(fplane->nvfrags,
+ _dec->pipe.fragy0[pli]+(_dec->pipe.mcu_nvfrags>>frag_shift));
+ oc_dec_dc_unpredict_mcu_plane(_dec,&_dec->pipe,pli);
+ oc_dec_frags_recon_mcu_plane(_dec,&_dec->pipe,pli);
sdelay=edelay=0;
- if(pipe.loop_filter){
+ if(_dec->pipe.loop_filter){
sdelay+=notstart;
edelay+=notdone;
- oc_state_loop_filter_frag_rows(&_dec->state,pipe.bounding_values,
- refi,pli,pipe.fragy0[pli]-sdelay,pipe.fragy_end[pli]-edelay);
+ oc_state_loop_filter_frag_rows(&_dec->state,
+ _dec->pipe.bounding_values,OC_FRAME_SELF,pli,
+ _dec->pipe.fragy0[pli]-sdelay,_dec->pipe.fragy_end[pli]-edelay);
}
/*To fill the borders, we have an additional two pixel delay, since a
fragment in the next row could filter its top edge, using two pixels
from a fragment in this row.
But there's no reason to delay a full fragment between the two.*/
oc_state_borders_fill_rows(&_dec->state,refi,pli,
- (pipe.fragy0[pli]-sdelay<<3)-(sdelay<<1),
- (pipe.fragy_end[pli]-edelay<<3)-(edelay<<1));
+ (_dec->pipe.fragy0[pli]-sdelay<<3)-(sdelay<<1),
+ (_dec->pipe.fragy_end[pli]-edelay<<3)-(edelay<<1));
/*Out-of-loop post-processing.*/
pp_offset=3*(pli!=0);
- if(pipe.pp_level>=OC_PP_LEVEL_DEBLOCKY+pp_offset){
+ if(_dec->pipe.pp_level>=OC_PP_LEVEL_DEBLOCKY+pp_offset){
/*Perform de-blocking in one plane.*/
sdelay+=notstart;
edelay+=notdone;
oc_dec_deblock_frag_rows(_dec,_dec->pp_frame_buf,
_dec->state.ref_frame_bufs[refi],pli,
- pipe.fragy0[pli]-sdelay,pipe.fragy_end[pli]-edelay);
- if(pipe.pp_level>=OC_PP_LEVEL_DERINGY+pp_offset){
+ _dec->pipe.fragy0[pli]-sdelay,_dec->pipe.fragy_end[pli]-edelay);
+ if(_dec->pipe.pp_level>=OC_PP_LEVEL_DERINGY+pp_offset){
/*Perform de-ringing in one plane.*/
sdelay+=notstart;
edelay+=notdone;
oc_dec_dering_frag_rows(_dec,_dec->pp_frame_buf,pli,
- pipe.fragy0[pli]-sdelay,pipe.fragy_end[pli]-edelay);
+ _dec->pipe.fragy0[pli]-sdelay,_dec->pipe.fragy_end[pli]-edelay);
}
}
/*If no post-processing is done, we still need to delay a row for the
loop filter, thanks to the strange filtering order VP3 chose.*/
- else if(pipe.loop_filter){
+ else if(_dec->pipe.loop_filter){
sdelay+=notstart;
edelay+=notdone;
}
@@ -2226,11 +2918,16 @@ int th_decode_packetin(th_dec_ctx *_dec,const ogg_packet *_op,
doubled, but luma might have more post-processing filters enabled
than chroma, so we don't know up front which one is the limiting
factor.*/
- avail_fragy0=OC_MINI(avail_fragy0,pipe.fragy0[pli]-sdelay<<frag_shift);
+ avail_fragy0=OC_MINI(avail_fragy0,
+ _dec->pipe.fragy0[pli]-sdelay<<frag_shift);
avail_fragy_end=OC_MINI(avail_fragy_end,
- pipe.fragy_end[pli]-edelay<<frag_shift);
+ _dec->pipe.fragy_end[pli]-edelay<<frag_shift);
}
+#ifdef HAVE_CAIRO
+ if(_dec->stripe_cb.stripe_decoded!=NULL&&!telemetry){
+#else
if(_dec->stripe_cb.stripe_decoded!=NULL){
+#endif
/*The callback might want to use the FPU, so let's make sure they can.
We violate all kinds of ABI restrictions by not doing this until
now, but none of them actually matter since we don't use floating
@@ -2252,692 +2949,44 @@ int th_decode_packetin(th_dec_ctx *_dec,const ogg_packet *_op,
_dec->state.ref_frame_idx[OC_FRAME_GOLD]=
_dec->state.ref_frame_idx[OC_FRAME_PREV]=
_dec->state.ref_frame_idx[OC_FRAME_SELF];
+ _dec->state.ref_frame_data[OC_FRAME_GOLD]=
+ _dec->state.ref_frame_data[OC_FRAME_PREV]=
+ _dec->state.ref_frame_data[OC_FRAME_SELF];
}
else{
/*Otherwise, just replace the previous reference frame.*/
_dec->state.ref_frame_idx[OC_FRAME_PREV]=
_dec->state.ref_frame_idx[OC_FRAME_SELF];
+ _dec->state.ref_frame_data[OC_FRAME_PREV]=
+ _dec->state.ref_frame_data[OC_FRAME_SELF];
}
/*Restore the FPU before dump_frame, since that _does_ use the FPU (for PNG
gamma values, if nothing else).*/
oc_restore_fpu(&_dec->state);
+#ifdef HAVE_CAIRO
+ /*If telemetry ioctls are active, we need to draw to the output buffer.*/
+ if(telemetry){
+ oc_render_telemetry(_dec,stripe_buf,telemetry);
+ oc_ycbcr_buffer_flip(_dec->pp_frame_buf,stripe_buf);
+ /*If we had a striped decoding callback, we skipped calling it above
+ (because the telemetry wasn't rendered yet).
+ Call it now with the whole frame.*/
+ if(_dec->stripe_cb.stripe_decoded!=NULL){
+ (*_dec->stripe_cb.stripe_decoded)(_dec->stripe_cb.ctx,
+ stripe_buf,0,_dec->state.fplanes[0].nvfrags);
+ }
+ }
+#endif
#if defined(OC_DUMP_IMAGES)
- /*Don't dump images for dropped frames.*/
+ /*We only dump images if there were some coded blocks.*/
oc_state_dump_frame(&_dec->state,OC_FRAME_SELF,"dec");
#endif
return 0;
}
- else{
- if(_dec->state.ref_frame_idx[OC_FRAME_GOLD]<0||
- _dec->state.ref_frame_idx[OC_FRAME_PREV]<0){
- int refi;
- /*No reference frames yet!*/
- oc_dec_init_dummy_frame(_dec);
- refi=_dec->state.ref_frame_idx[OC_FRAME_PREV];
- _dec->state.ref_frame_idx[OC_FRAME_SELF]=refi;
- memcpy(_dec->pp_frame_buf,_dec->state.ref_frame_bufs[refi],
- sizeof(_dec->pp_frame_buf[0])*3);
- }
- /*Just update the granule position and return.*/
- _dec->state.granpos=(_dec->state.keyframe_num+_dec->state.granpos_bias<<
- _dec->state.info.keyframe_granule_shift)
- +(_dec->state.curframe_num-_dec->state.keyframe_num);
- _dec->state.curframe_num++;
- if(_granpos!=NULL)*_granpos=_dec->state.granpos;
- return TH_DUPFRAME;
- }
}
int th_decode_ycbcr_out(th_dec_ctx *_dec,th_ycbcr_buffer _ycbcr){
if(_dec==NULL||_ycbcr==NULL)return TH_EFAULT;
oc_ycbcr_buffer_flip(_ycbcr,_dec->pp_frame_buf);
-#if defined(HAVE_CAIRO)
- /*If telemetry ioctls are active, we need to draw to the output buffer.
- Stuff the plane into cairo.*/
- if(_dec->telemetry){
- cairo_surface_t *cs;
- unsigned char *data;
- unsigned char *y_row;
- unsigned char *u_row;
- unsigned char *v_row;
- unsigned char *rgb_row;
- int cstride;
- int w;
- int h;
- int x;
- int y;
- int hdec;
- int vdec;
- w=_ycbcr[0].width;
- h=_ycbcr[0].height;
- hdec=!(_dec->state.info.pixel_fmt&1);
- vdec=!(_dec->state.info.pixel_fmt&2);
- /*Lazy data buffer init.
- We could try to re-use the post-processing buffer, which would save
- memory, but complicate the allocation logic there.
- I don't think anyone cares about memory usage when using telemetry; it is
- not meant for embedded devices.*/
- if(_dec->telemetry_frame_data==NULL){
- _dec->telemetry_frame_data=_ogg_malloc(
- (w*h+2*(w>>hdec)*(h>>vdec))*sizeof(*_dec->telemetry_frame_data));
- if(_dec->telemetry_frame_data==NULL)return 0;
- }
- cs=cairo_image_surface_create(CAIRO_FORMAT_RGB24,w,h);
- /*Sadly, no YUV support in Cairo (yet); convert into the RGB buffer.*/
- data=cairo_image_surface_get_data(cs);
- if(data==NULL){
- cairo_surface_destroy(cs);
- return 0;
- }
- cstride=cairo_image_surface_get_stride(cs);
- y_row=_ycbcr[0].data;
- u_row=_ycbcr[1].data;
- v_row=_ycbcr[2].data;
- rgb_row=data;
- for(y=0;y<h;y++){
- for(x=0;x<w;x++){
- int r;
- int g;
- int b;
- r=(1904000*y_row[x]+2609823*v_row[x>>hdec]-363703744)/1635200;
- g=(3827562*y_row[x]-1287801*u_row[x>>hdec]
- -2672387*v_row[x>>hdec]+447306710)/3287200;
- b=(952000*y_row[x]+1649289*u_row[x>>hdec]-225932192)/817600;
- rgb_row[4*x+0]=OC_CLAMP255(b);
- rgb_row[4*x+1]=OC_CLAMP255(g);
- rgb_row[4*x+2]=OC_CLAMP255(r);
- }
- y_row+=_ycbcr[0].stride;
- u_row+=_ycbcr[1].stride&-((y&1)|!vdec);
- v_row+=_ycbcr[2].stride&-((y&1)|!vdec);
- rgb_row+=cstride;
- }
- /*Draw coded identifier for each macroblock (stored in Hilbert order).*/
- {
- cairo_t *c;
- const oc_fragment *frags;
- oc_mv *frag_mvs;
- const signed char *mb_modes;
- oc_mb_map *mb_maps;
- size_t nmbs;
- size_t mbi;
- int row2;
- int col2;
- int qim[3]={0,0,0};
- if(_dec->state.nqis==2){
- int bqi;
- bqi=_dec->state.qis[0];
- if(_dec->state.qis[1]>bqi)qim[1]=1;
- if(_dec->state.qis[1]<bqi)qim[1]=-1;
- }
- if(_dec->state.nqis==3){
- int bqi;
- int cqi;
- int dqi;
- bqi=_dec->state.qis[0];
- cqi=_dec->state.qis[1];
- dqi=_dec->state.qis[2];
- if(cqi>bqi&&dqi>bqi){
- if(dqi>cqi){
- qim[1]=1;
- qim[2]=2;
- }
- else{
- qim[1]=2;
- qim[2]=1;
- }
- }
- else if(cqi<bqi&&dqi<bqi){
- if(dqi<cqi){
- qim[1]=-1;
- qim[2]=-2;
- }
- else{
- qim[1]=-2;
- qim[2]=-1;
- }
- }
- else{
- if(cqi<bqi)qim[1]=-1;
- else qim[1]=1;
- if(dqi<bqi)qim[2]=-1;
- else qim[2]=1;
- }
- }
- c=cairo_create(cs);
- frags=_dec->state.frags;
- frag_mvs=_dec->state.frag_mvs;
- mb_modes=_dec->state.mb_modes;
- mb_maps=_dec->state.mb_maps;
- nmbs=_dec->state.nmbs;
- row2=0;
- col2=0;
- for(mbi=0;mbi<nmbs;mbi++){
- float x;
- float y;
- int bi;
- y=h-(row2+((col2+1>>1)&1))*16-16;
- x=(col2>>1)*16;
- cairo_set_line_width(c,1.);
- /*Keyframe (all intra) red box.*/
- if(_dec->state.frame_type==OC_INTRA_FRAME){
- if(_dec->telemetry_mbmode&0x02){
- cairo_set_source_rgba(c,1.,0,0,.5);
- cairo_rectangle(c,x+2.5,y+2.5,11,11);
- cairo_stroke_preserve(c);
- cairo_set_source_rgba(c,1.,0,0,.25);
- cairo_fill(c);
- }
- }
- else{
- const signed char *frag_mv;
- ptrdiff_t fragi;
- for(bi=0;bi<4;bi++){
- fragi=mb_maps[mbi][0][bi];
- if(fragi>=0&&frags[fragi].coded){
- frag_mv=frag_mvs[fragi];
- break;
- }
- }
- if(bi<4){
- switch(mb_modes[mbi]){
- case OC_MODE_INTRA:{
- if(_dec->telemetry_mbmode&0x02){
- cairo_set_source_rgba(c,1.,0,0,.5);
- cairo_rectangle(c,x+2.5,y+2.5,11,11);
- cairo_stroke_preserve(c);
- cairo_set_source_rgba(c,1.,0,0,.25);
- cairo_fill(c);
- }
- }break;
- case OC_MODE_INTER_NOMV:{
- if(_dec->telemetry_mbmode&0x01){
- cairo_set_source_rgba(c,0,0,1.,.5);
- cairo_rectangle(c,x+2.5,y+2.5,11,11);
- cairo_stroke_preserve(c);
- cairo_set_source_rgba(c,0,0,1.,.25);
- cairo_fill(c);
- }
- }break;
- case OC_MODE_INTER_MV:{
- if(_dec->telemetry_mbmode&0x04){
- cairo_rectangle(c,x+2.5,y+2.5,11,11);
- cairo_set_source_rgba(c,0,1.,0,.5);
- cairo_stroke(c);
- }
- if(_dec->telemetry_mv&0x04){
- cairo_move_to(c,x+8+frag_mv[0],y+8-frag_mv[1]);
- cairo_set_source_rgba(c,1.,1.,1.,.9);
- cairo_set_line_width(c,3.);
- cairo_line_to(c,x+8+frag_mv[0]*.66,y+8-frag_mv[1]*.66);
- cairo_stroke_preserve(c);
- cairo_set_line_width(c,2.);
- cairo_line_to(c,x+8+frag_mv[0]*.33,y+8-frag_mv[1]*.33);
- cairo_stroke_preserve(c);
- cairo_set_line_width(c,1.);
- cairo_line_to(c,x+8,y+8);
- cairo_stroke(c);
- }
- }break;
- case OC_MODE_INTER_MV_LAST:{
- if(_dec->telemetry_mbmode&0x08){
- cairo_rectangle(c,x+2.5,y+2.5,11,11);
- cairo_set_source_rgba(c,0,1.,0,.5);
- cairo_move_to(c,x+13.5,y+2.5);
- cairo_line_to(c,x+2.5,y+8);
- cairo_line_to(c,x+13.5,y+13.5);
- cairo_stroke(c);
- }
- if(_dec->telemetry_mv&0x08){
- cairo_move_to(c,x+8+frag_mv[0],y+8-frag_mv[1]);
- cairo_set_source_rgba(c,1.,1.,1.,.9);
- cairo_set_line_width(c,3.);
- cairo_line_to(c,x+8+frag_mv[0]*.66,y+8-frag_mv[1]*.66);
- cairo_stroke_preserve(c);
- cairo_set_line_width(c,2.);
- cairo_line_to(c,x+8+frag_mv[0]*.33,y+8-frag_mv[1]*.33);
- cairo_stroke_preserve(c);
- cairo_set_line_width(c,1.);
- cairo_line_to(c,x+8,y+8);
- cairo_stroke(c);
- }
- }break;
- case OC_MODE_INTER_MV_LAST2:{
- if(_dec->telemetry_mbmode&0x10){
- cairo_rectangle(c,x+2.5,y+2.5,11,11);
- cairo_set_source_rgba(c,0,1.,0,.5);
- cairo_move_to(c,x+8,y+2.5);
- cairo_line_to(c,x+2.5,y+8);
- cairo_line_to(c,x+8,y+13.5);
- cairo_move_to(c,x+13.5,y+2.5);
- cairo_line_to(c,x+8,y+8);
- cairo_line_to(c,x+13.5,y+13.5);
- cairo_stroke(c);
- }
- if(_dec->telemetry_mv&0x10){
- cairo_move_to(c,x+8+frag_mv[0],y+8-frag_mv[1]);
- cairo_set_source_rgba(c,1.,1.,1.,.9);
- cairo_set_line_width(c,3.);
- cairo_line_to(c,x+8+frag_mv[0]*.66,y+8-frag_mv[1]*.66);
- cairo_stroke_preserve(c);
- cairo_set_line_width(c,2.);
- cairo_line_to(c,x+8+frag_mv[0]*.33,y+8-frag_mv[1]*.33);
- cairo_stroke_preserve(c);
- cairo_set_line_width(c,1.);
- cairo_line_to(c,x+8,y+8);
- cairo_stroke(c);
- }
- }break;
- case OC_MODE_GOLDEN_NOMV:{
- if(_dec->telemetry_mbmode&0x20){
- cairo_set_source_rgba(c,1.,1.,0,.5);
- cairo_rectangle(c,x+2.5,y+2.5,11,11);
- cairo_stroke_preserve(c);
- cairo_set_source_rgba(c,1.,1.,0,.25);
- cairo_fill(c);
- }
- }break;
- case OC_MODE_GOLDEN_MV:{
- if(_dec->telemetry_mbmode&0x40){
- cairo_rectangle(c,x+2.5,y+2.5,11,11);
- cairo_set_source_rgba(c,1.,1.,0,.5);
- cairo_stroke(c);
- }
- if(_dec->telemetry_mv&0x40){
- cairo_move_to(c,x+8+frag_mv[0],y+8-frag_mv[1]);
- cairo_set_source_rgba(c,1.,1.,1.,.9);
- cairo_set_line_width(c,3.);
- cairo_line_to(c,x+8+frag_mv[0]*.66,y+8-frag_mv[1]*.66);
- cairo_stroke_preserve(c);
- cairo_set_line_width(c,2.);
- cairo_line_to(c,x+8+frag_mv[0]*.33,y+8-frag_mv[1]*.33);
- cairo_stroke_preserve(c);
- cairo_set_line_width(c,1.);
- cairo_line_to(c,x+8,y+8);
- cairo_stroke(c);
- }
- }break;
- case OC_MODE_INTER_MV_FOUR:{
- if(_dec->telemetry_mbmode&0x80){
- cairo_rectangle(c,x+2.5,y+2.5,4,4);
- cairo_rectangle(c,x+9.5,y+2.5,4,4);
- cairo_rectangle(c,x+2.5,y+9.5,4,4);
- cairo_rectangle(c,x+9.5,y+9.5,4,4);
- cairo_set_source_rgba(c,0,1.,0,.5);
- cairo_stroke(c);
- }
- /*4mv is odd, coded in raster order.*/
- fragi=mb_maps[mbi][0][0];
- if(frags[fragi].coded&&_dec->telemetry_mv&0x80){
- frag_mv=frag_mvs[fragi];
- cairo_move_to(c,x+4+frag_mv[0],y+12-frag_mv[1]);
- cairo_set_source_rgba(c,1.,1.,1.,.9);
- cairo_set_line_width(c,3.);
- cairo_line_to(c,x+4+frag_mv[0]*.66,y+12-frag_mv[1]*.66);
- cairo_stroke_preserve(c);
- cairo_set_line_width(c,2.);
- cairo_line_to(c,x+4+frag_mv[0]*.33,y+12-frag_mv[1]*.33);
- cairo_stroke_preserve(c);
- cairo_set_line_width(c,1.);
- cairo_line_to(c,x+4,y+12);
- cairo_stroke(c);
- }
- fragi=mb_maps[mbi][0][1];
- if(frags[fragi].coded&&_dec->telemetry_mv&0x80){
- frag_mv=frag_mvs[fragi];
- cairo_move_to(c,x+12+frag_mv[0],y+12-frag_mv[1]);
- cairo_set_source_rgba(c,1.,1.,1.,.9);
- cairo_set_line_width(c,3.);
- cairo_line_to(c,x+12+frag_mv[0]*.66,y+12-frag_mv[1]*.66);
- cairo_stroke_preserve(c);
- cairo_set_line_width(c,2.);
- cairo_line_to(c,x+12+frag_mv[0]*.33,y+12-frag_mv[1]*.33);
- cairo_stroke_preserve(c);
- cairo_set_line_width(c,1.);
- cairo_line_to(c,x+12,y+12);
- cairo_stroke(c);
- }
- fragi=mb_maps[mbi][0][2];
- if(frags[fragi].coded&&_dec->telemetry_mv&0x80){
- frag_mv=frag_mvs[fragi];
- cairo_move_to(c,x+4+frag_mv[0],y+4-frag_mv[1]);
- cairo_set_source_rgba(c,1.,1.,1.,.9);
- cairo_set_line_width(c,3.);
- cairo_line_to(c,x+4+frag_mv[0]*.66,y+4-frag_mv[1]*.66);
- cairo_stroke_preserve(c);
- cairo_set_line_width(c,2.);
- cairo_line_to(c,x+4+frag_mv[0]*.33,y+4-frag_mv[1]*.33);
- cairo_stroke_preserve(c);
- cairo_set_line_width(c,1.);
- cairo_line_to(c,x+4,y+4);
- cairo_stroke(c);
- }
- fragi=mb_maps[mbi][0][3];
- if(frags[fragi].coded&&_dec->telemetry_mv&0x80){
- frag_mv=frag_mvs[fragi];
- cairo_move_to(c,x+12+frag_mv[0],y+4-frag_mv[1]);
- cairo_set_source_rgba(c,1.,1.,1.,.9);
- cairo_set_line_width(c,3.);
- cairo_line_to(c,x+12+frag_mv[0]*.66,y+4-frag_mv[1]*.66);
- cairo_stroke_preserve(c);
- cairo_set_line_width(c,2.);
- cairo_line_to(c,x+12+frag_mv[0]*.33,y+4-frag_mv[1]*.33);
- cairo_stroke_preserve(c);
- cairo_set_line_width(c,1.);
- cairo_line_to(c,x+12,y+4);
- cairo_stroke(c);
- }
- }break;
- }
- }
- }
- /*qii illustration.*/
- if(_dec->telemetry_qi&0x2){
- cairo_set_line_cap(c,CAIRO_LINE_CAP_SQUARE);
- for(bi=0;bi<4;bi++){
- ptrdiff_t fragi;
- int qiv;
- int xp;
- int yp;
- xp=x+(bi&1)*8;
- yp=y+8-(bi&2)*4;
- fragi=mb_maps[mbi][0][bi];
- if(fragi>=0&&frags[fragi].coded){
- qiv=qim[frags[fragi].qii];
- cairo_set_line_width(c,3.);
- cairo_set_source_rgba(c,0.,0.,0.,.5);
- switch(qiv){
- /*Double plus:*/
- case 2:{
- if((bi&1)^((bi&2)>>1)){
- cairo_move_to(c,xp+2.5,yp+1.5);
- cairo_line_to(c,xp+2.5,yp+3.5);
- cairo_move_to(c,xp+1.5,yp+2.5);
- cairo_line_to(c,xp+3.5,yp+2.5);
- cairo_move_to(c,xp+5.5,yp+4.5);
- cairo_line_to(c,xp+5.5,yp+6.5);
- cairo_move_to(c,xp+4.5,yp+5.5);
- cairo_line_to(c,xp+6.5,yp+5.5);
- cairo_stroke_preserve(c);
- cairo_set_source_rgba(c,0.,1.,1.,1.);
- }
- else{
- cairo_move_to(c,xp+5.5,yp+1.5);
- cairo_line_to(c,xp+5.5,yp+3.5);
- cairo_move_to(c,xp+4.5,yp+2.5);
- cairo_line_to(c,xp+6.5,yp+2.5);
- cairo_move_to(c,xp+2.5,yp+4.5);
- cairo_line_to(c,xp+2.5,yp+6.5);
- cairo_move_to(c,xp+1.5,yp+5.5);
- cairo_line_to(c,xp+3.5,yp+5.5);
- cairo_stroke_preserve(c);
- cairo_set_source_rgba(c,0.,1.,1.,1.);
- }
- }break;
- /*Double minus:*/
- case -2:{
- cairo_move_to(c,xp+2.5,yp+2.5);
- cairo_line_to(c,xp+5.5,yp+2.5);
- cairo_move_to(c,xp+2.5,yp+5.5);
- cairo_line_to(c,xp+5.5,yp+5.5);
- cairo_stroke_preserve(c);
- cairo_set_source_rgba(c,1.,1.,1.,1.);
- }break;
- /*Plus:*/
- case 1:{
- if(bi&2==0)yp-=2;
- if(bi&1==0)xp-=2;
- cairo_move_to(c,xp+4.5,yp+2.5);
- cairo_line_to(c,xp+4.5,yp+6.5);
- cairo_move_to(c,xp+2.5,yp+4.5);
- cairo_line_to(c,xp+6.5,yp+4.5);
- cairo_stroke_preserve(c);
- cairo_set_source_rgba(c,.1,1.,.3,1.);
- break;
- }
- /*Fall through.*/
- /*Minus:*/
- case -1:{
- cairo_move_to(c,xp+2.5,yp+4.5);
- cairo_line_to(c,xp+6.5,yp+4.5);
- cairo_stroke_preserve(c);
- cairo_set_source_rgba(c,1.,.3,.1,1.);
- }break;
- default:continue;
- }
- cairo_set_line_width(c,1.);
- cairo_stroke(c);
- }
- }
- }
- col2++;
- if((col2>>1)>=_dec->state.nhmbs){
- col2=0;
- row2+=2;
- }
- }
- /*Bit usage indicator[s]:*/
- if(_dec->telemetry_bits){
- int widths[6];
- int fpsn;
- int fpsd;
- int mult;
- int fullw;
- int padw;
- int i;
- fpsn=_dec->state.info.fps_numerator;
- fpsd=_dec->state.info.fps_denominator;
- mult=(_dec->telemetry_bits>=0xFF?1:_dec->telemetry_bits);
- fullw=250.f*h*fpsd*mult/fpsn;
- padw=w-24;
- /*Header and coded block bits.*/
- if(_dec->telemetry_frame_bytes<0||
- _dec->telemetry_frame_bytes==OC_LOTS_OF_BITS){
- _dec->telemetry_frame_bytes=0;
- }
- if(_dec->telemetry_coding_bytes<0||
- _dec->telemetry_coding_bytes>_dec->telemetry_frame_bytes){
- _dec->telemetry_coding_bytes=0;
- }
- if(_dec->telemetry_mode_bytes<0||
- _dec->telemetry_mode_bytes>_dec->telemetry_frame_bytes){
- _dec->telemetry_mode_bytes=0;
- }
- if(_dec->telemetry_mv_bytes<0||
- _dec->telemetry_mv_bytes>_dec->telemetry_frame_bytes){
- _dec->telemetry_mv_bytes=0;
- }
- if(_dec->telemetry_qi_bytes<0||
- _dec->telemetry_qi_bytes>_dec->telemetry_frame_bytes){
- _dec->telemetry_qi_bytes=0;
- }
- if(_dec->telemetry_dc_bytes<0||
- _dec->telemetry_dc_bytes>_dec->telemetry_frame_bytes){
- _dec->telemetry_dc_bytes=0;
- }
- widths[0]=padw*(_dec->telemetry_frame_bytes-_dec->telemetry_coding_bytes)/fullw;
- widths[1]=padw*(_dec->telemetry_coding_bytes-_dec->telemetry_mode_bytes)/fullw;
- widths[2]=padw*(_dec->telemetry_mode_bytes-_dec->telemetry_mv_bytes)/fullw;
- widths[3]=padw*(_dec->telemetry_mv_bytes-_dec->telemetry_qi_bytes)/fullw;
- widths[4]=padw*(_dec->telemetry_qi_bytes-_dec->telemetry_dc_bytes)/fullw;
- widths[5]=padw*(_dec->telemetry_dc_bytes)/fullw;
- for(i=0;i<6;i++)if(widths[i]>w)widths[i]=w;
- cairo_set_source_rgba(c,.0,.0,.0,.6);
- cairo_rectangle(c,10,h-33,widths[0]+1,5);
- cairo_rectangle(c,10,h-29,widths[1]+1,5);
- cairo_rectangle(c,10,h-25,widths[2]+1,5);
- cairo_rectangle(c,10,h-21,widths[3]+1,5);
- cairo_rectangle(c,10,h-17,widths[4]+1,5);
- cairo_rectangle(c,10,h-13,widths[5]+1,5);
- cairo_fill(c);
- cairo_set_source_rgb(c,1,0,0);
- cairo_rectangle(c,10.5,h-32.5,widths[0],4);
- cairo_fill(c);
- cairo_set_source_rgb(c,0,1,0);
- cairo_rectangle(c,10.5,h-28.5,widths[1],4);
- cairo_fill(c);
- cairo_set_source_rgb(c,0,0,1);
- cairo_rectangle(c,10.5,h-24.5,widths[2],4);
- cairo_fill(c);
- cairo_set_source_rgb(c,.6,.4,.0);
- cairo_rectangle(c,10.5,h-20.5,widths[3],4);
- cairo_fill(c);
- cairo_set_source_rgb(c,.3,.3,.3);
- cairo_rectangle(c,10.5,h-16.5,widths[4],4);
- cairo_fill(c);
- cairo_set_source_rgb(c,.5,.5,.8);
- cairo_rectangle(c,10.5,h-12.5,widths[5],4);
- cairo_fill(c);
- }
- /*Master qi indicator[s]:*/
- if(_dec->telemetry_qi&0x1){
- cairo_text_extents_t extents;
- char buffer[10];
- int p;
- int y;
- p=0;
- y=h-7.5;
- if(_dec->state.qis[0]>=10)buffer[p++]=48+_dec->state.qis[0]/10;
- buffer[p++]=48+_dec->state.qis[0]%10;
- if(_dec->state.nqis>=2){
- buffer[p++]=' ';
- if(_dec->state.qis[1]>=10)buffer[p++]=48+_dec->state.qis[1]/10;
- buffer[p++]=48+_dec->state.qis[1]%10;
- }
- if(_dec->state.nqis==3){
- buffer[p++]=' ';
- if(_dec->state.qis[2]>=10)buffer[p++]=48+_dec->state.qis[2]/10;
- buffer[p++]=48+_dec->state.qis[2]%10;
- }
- buffer[p++]='\0';
- cairo_select_font_face(c,"sans",
- CAIRO_FONT_SLANT_NORMAL,CAIRO_FONT_WEIGHT_BOLD);
- cairo_set_font_size(c,18);
- cairo_text_extents(c,buffer,&extents);
- cairo_set_source_rgb(c,1,1,1);
- cairo_move_to(c,w-extents.x_advance-10,y);
- cairo_show_text(c,buffer);
- cairo_set_source_rgb(c,0,0,0);
- cairo_move_to(c,w-extents.x_advance-10,y);
- cairo_text_path(c,buffer);
- cairo_set_line_width(c,.8);
- cairo_set_line_join(c,CAIRO_LINE_JOIN_ROUND);
- cairo_stroke(c);
- }
- cairo_destroy(c);
- }
- /*Out of the Cairo plane into the telemetry YUV buffer.*/
- _ycbcr[0].data=_dec->telemetry_frame_data;
- _ycbcr[0].stride=_ycbcr[0].width;
- _ycbcr[1].data=_ycbcr[0].data+h*_ycbcr[0].stride;
- _ycbcr[1].stride=_ycbcr[1].width;
- _ycbcr[2].data=_ycbcr[1].data+(h>>vdec)*_ycbcr[1].stride;
- _ycbcr[2].stride=_ycbcr[2].width;
- y_row=_ycbcr[0].data;
- u_row=_ycbcr[1].data;
- v_row=_ycbcr[2].data;
- rgb_row=data;
- /*This is one of the few places it's worth handling chroma on a
- case-by-case basis.*/
- switch(_dec->state.info.pixel_fmt){
- case TH_PF_420:{
- for(y=0;y<h;y+=2){
- unsigned char *y_row2;
- unsigned char *rgb_row2;
- y_row2=y_row+_ycbcr[0].stride;
- rgb_row2=rgb_row+cstride;
- for(x=0;x<w;x+=2){
- int y;
- int u;
- int v;
- y=(65481*rgb_row[4*x+2]+128553*rgb_row[4*x+1]
- +24966*rgb_row[4*x+0]+4207500)/255000;
- y_row[x]=OC_CLAMP255(y);
- y=(65481*rgb_row[4*x+6]+128553*rgb_row[4*x+5]
- +24966*rgb_row[4*x+4]+4207500)/255000;
- y_row[x+1]=OC_CLAMP255(y);
- y=(65481*rgb_row2[4*x+2]+128553*rgb_row2[4*x+1]
- +24966*rgb_row2[4*x+0]+4207500)/255000;
- y_row2[x]=OC_CLAMP255(y);
- y=(65481*rgb_row2[4*x+6]+128553*rgb_row2[4*x+5]
- +24966*rgb_row2[4*x+4]+4207500)/255000;
- y_row2[x+1]=OC_CLAMP255(y);
- u=(-8372*(rgb_row[4*x+2]+rgb_row[4*x+6]
- +rgb_row2[4*x+2]+rgb_row2[4*x+6])
- -16436*(rgb_row[4*x+1]+rgb_row[4*x+5]
- +rgb_row2[4*x+1]+rgb_row2[4*x+5])
- +24808*(rgb_row[4*x+0]+rgb_row[4*x+4]
- +rgb_row2[4*x+0]+rgb_row2[4*x+4])+29032005)/225930;
- v=(39256*(rgb_row[4*x+2]+rgb_row[4*x+6]
- +rgb_row2[4*x+2]+rgb_row2[4*x+6])
- -32872*(rgb_row[4*x+1]+rgb_row[4*x+5]
- +rgb_row2[4*x+1]+rgb_row2[4*x+5])
- -6384*(rgb_row[4*x+0]+rgb_row[4*x+4]
- +rgb_row2[4*x+0]+rgb_row2[4*x+4])+45940035)/357510;
- u_row[x>>1]=OC_CLAMP255(u);
- v_row[x>>1]=OC_CLAMP255(v);
- }
- y_row+=_ycbcr[0].stride<<1;
- u_row+=_ycbcr[1].stride;
- v_row+=_ycbcr[2].stride;
- rgb_row+=cstride<<1;
- }
- }break;
- case TH_PF_422:{
- for(y=0;y<h;y++){
- for(x=0;x<w;x+=2){
- int y;
- int u;
- int v;
- y=(65481*rgb_row[4*x+2]+128553*rgb_row[4*x+1]
- +24966*rgb_row[4*x+0]+4207500)/255000;
- y_row[x]=OC_CLAMP255(y);
- y=(65481*rgb_row[4*x+6]+128553*rgb_row[4*x+5]
- +24966*rgb_row[4*x+4]+4207500)/255000;
- y_row[x+1]=OC_CLAMP255(y);
- u=(-16744*(rgb_row[4*x+2]+rgb_row[4*x+6])
- -32872*(rgb_row[4*x+1]+rgb_row[4*x+5])
- +49616*(rgb_row[4*x+0]+rgb_row[4*x+4])+29032005)/225930;
- v=(78512*(rgb_row[4*x+2]+rgb_row[4*x+6])
- -65744*(rgb_row[4*x+1]+rgb_row[4*x+5])
- -12768*(rgb_row[4*x+0]+rgb_row[4*x+4])+45940035)/357510;
- u_row[x>>1]=OC_CLAMP255(u);
- v_row[x>>1]=OC_CLAMP255(v);
- }
- y_row+=_ycbcr[0].stride;
- u_row+=_ycbcr[1].stride;
- v_row+=_ycbcr[2].stride;
- rgb_row+=cstride;
- }
- }break;
- /*case TH_PF_444:*/
- default:{
- for(y=0;y<h;y++){
- for(x=0;x<w;x++){
- int y;
- int u;
- int v;
- y=(65481*rgb_row[4*x+2]+128553*rgb_row[4*x+1]
- +24966*rgb_row[4*x+0]+4207500)/255000;
- u=(-33488*rgb_row[4*x+2]-65744*rgb_row[4*x+1]
- +99232*rgb_row[4*x+0]+29032005)/225930;
- v=(157024*rgb_row[4*x+2]-131488*rgb_row[4*x+1]
- -25536*rgb_row[4*x+0]+45940035)/357510;
- y_row[x]=OC_CLAMP255(y);
- u_row[x]=OC_CLAMP255(u);
- v_row[x]=OC_CLAMP255(v);
- }
- y_row+=_ycbcr[0].stride;
- u_row+=_ycbcr[1].stride;
- v_row+=_ycbcr[2].stride;
- rgb_row+=cstride;
- }
- }break;
- }
- /*Finished.
- Destroy the surface.*/
- cairo_surface_destroy(cs);
- }
-#endif
return 0;
}
diff --git a/thirdparty/libtheora/dequant.c b/thirdparty/libtheora/dequant.c
index e554872d4e..860536f72d 100644
--- a/thirdparty/libtheora/dequant.c
+++ b/thirdparty/libtheora/dequant.c
@@ -11,7 +11,7 @@
********************************************************************
function:
- last mod: $Id: dequant.c 16503 2009-08-22 18:14:02Z giles $
+ last mod: $Id$
********************************************************************/
diff --git a/thirdparty/libtheora/dequant.h b/thirdparty/libtheora/dequant.h
index ef25838e35..9d6cd6be56 100644
--- a/thirdparty/libtheora/dequant.h
+++ b/thirdparty/libtheora/dequant.h
@@ -11,7 +11,7 @@
********************************************************************
function:
- last mod: $Id: dequant.h 16503 2009-08-22 18:14:02Z giles $
+ last mod: $Id$
********************************************************************/
diff --git a/thirdparty/libtheora/encfrag.c b/thirdparty/libtheora/encfrag.c
index bb814c8e4a..0e18111ac7 100644
--- a/thirdparty/libtheora/encfrag.c
+++ b/thirdparty/libtheora/encfrag.c
@@ -11,7 +11,7 @@
********************************************************************
function:
- last mod: $Id: encfrag.c 16503 2009-08-22 18:14:02Z giles $
+ last mod: $Id$
********************************************************************/
#include <stdlib.h>
@@ -19,11 +19,6 @@
#include "encint.h"
-void oc_enc_frag_sub(const oc_enc_ctx *_enc,ogg_int16_t _diff[64],
- const unsigned char *_src,const unsigned char *_ref,int _ystride){
- (*_enc->opt_vtable.frag_sub)(_diff,_src,_ref,_ystride);
-}
-
void oc_enc_frag_sub_c(ogg_int16_t _diff[64],const unsigned char *_src,
const unsigned char *_ref,int _ystride){
int i;
@@ -35,11 +30,6 @@ void oc_enc_frag_sub_c(ogg_int16_t _diff[64],const unsigned char *_src,
}
}
-void oc_enc_frag_sub_128(const oc_enc_ctx *_enc,ogg_int16_t _diff[64],
- const unsigned char *_src,int _ystride){
- (*_enc->opt_vtable.frag_sub_128)(_diff,_src,_ystride);
-}
-
void oc_enc_frag_sub_128_c(ogg_int16_t *_diff,
const unsigned char *_src,int _ystride){
int i;
@@ -50,11 +40,6 @@ void oc_enc_frag_sub_128_c(ogg_int16_t *_diff,
}
}
-unsigned oc_enc_frag_sad(const oc_enc_ctx *_enc,const unsigned char *_x,
- const unsigned char *_y,int _ystride){
- return (*_enc->opt_vtable.frag_sad)(_x,_y,_ystride);
-}
-
unsigned oc_enc_frag_sad_c(const unsigned char *_src,
const unsigned char *_ref,int _ystride){
unsigned sad;
@@ -69,12 +54,6 @@ unsigned oc_enc_frag_sad_c(const unsigned char *_src,
return sad;
}
-unsigned oc_enc_frag_sad_thresh(const oc_enc_ctx *_enc,
- const unsigned char *_src,const unsigned char *_ref,int _ystride,
- unsigned _thresh){
- return (*_enc->opt_vtable.frag_sad_thresh)(_src,_ref,_ystride,_thresh);
-}
-
unsigned oc_enc_frag_sad_thresh_c(const unsigned char *_src,
const unsigned char *_ref,int _ystride,unsigned _thresh){
unsigned sad;
@@ -90,13 +69,6 @@ unsigned oc_enc_frag_sad_thresh_c(const unsigned char *_src,
return sad;
}
-unsigned oc_enc_frag_sad2_thresh(const oc_enc_ctx *_enc,
- const unsigned char *_src,const unsigned char *_ref1,
- const unsigned char *_ref2,int _ystride,unsigned _thresh){
- return (*_enc->opt_vtable.frag_sad2_thresh)(_src,_ref1,_ref2,_ystride,
- _thresh);
-}
-
unsigned oc_enc_frag_sad2_thresh_c(const unsigned char *_src,
const unsigned char *_ref1,const unsigned char *_ref2,int _ystride,
unsigned _thresh){
@@ -114,6 +86,27 @@ unsigned oc_enc_frag_sad2_thresh_c(const unsigned char *_src,
return sad;
}
+unsigned oc_enc_frag_intra_sad_c(const unsigned char *_src, int _ystride){
+ const unsigned char *src = _src;
+ unsigned dc;
+ unsigned sad;
+ int i;
+ dc=0;
+ for(i=8;i-->0;){
+ int j;
+ for(j=0;j<8;j++)dc+=src[j];
+ src+=_ystride;
+ }
+ dc=dc+32>>6;
+ sad=0;
+ for(i=8;i-->0;){
+ int j;
+ for(j=0;j<8;j++)sad+=abs(_src[j]-dc);
+ _src+=_ystride;
+ }
+ return sad;
+}
+
static void oc_diff_hadamard(ogg_int16_t _buf[64],const unsigned char *_src,
const unsigned char *_ref,int _ystride){
int i;
@@ -269,19 +262,20 @@ static void oc_intra_hadamard(ogg_int16_t _buf[64],const unsigned char *_src,
}
}
-unsigned oc_hadamard_sad_thresh(const ogg_int16_t _buf[64],unsigned _thresh){
- unsigned sad;
- int t0;
- int t1;
- int t2;
- int t3;
- int t4;
- int t5;
- int t6;
- int t7;
- int r;
- int i;
- sad=0;
+unsigned oc_hadamard_sad(int *_dc,const ogg_int16_t _buf[64]){
+ unsigned sad;
+ int dc;
+ int t0;
+ int t1;
+ int t2;
+ int t3;
+ int t4;
+ int t5;
+ int t6;
+ int t7;
+ int r;
+ int i;
+ sad=dc=0;
for(i=0;i<8;i++){
/*Hadamard stage 1:*/
t0=_buf[i*8+0]+_buf[i*8+4];
@@ -306,7 +300,7 @@ unsigned oc_hadamard_sad_thresh(const ogg_int16_t _buf[64],unsigned _thresh){
t5+=t7;
t7=r-t7;
/*Hadamard stage 3:*/
- r=abs(t0+t1);
+ r=abs(t0+t1)&-(i>0);
r+=abs(t0-t1);
r+=abs(t2+t3);
r+=abs(t2-t3);
@@ -315,54 +309,61 @@ unsigned oc_hadamard_sad_thresh(const ogg_int16_t _buf[64],unsigned _thresh){
r+=abs(t6+t7);
r+=abs(t6-t7);
sad+=r;
- if(sad>_thresh)break;
}
+ dc=_buf[0]+_buf[1]+_buf[2]+_buf[3]+_buf[4]+_buf[5]+_buf[6]+_buf[7];
+ *_dc=dc;
return sad;
}
-unsigned oc_enc_frag_satd_thresh(const oc_enc_ctx *_enc,
- const unsigned char *_src,const unsigned char *_ref,int _ystride,
- unsigned _thresh){
- return (*_enc->opt_vtable.frag_satd_thresh)(_src,_ref,_ystride,_thresh);
-}
-
-unsigned oc_enc_frag_satd_thresh_c(const unsigned char *_src,
- const unsigned char *_ref,int _ystride,unsigned _thresh){
+unsigned oc_enc_frag_satd_c(int *_dc,const unsigned char *_src,
+ const unsigned char *_ref,int _ystride){
ogg_int16_t buf[64];
oc_diff_hadamard(buf,_src,_ref,_ystride);
- return oc_hadamard_sad_thresh(buf,_thresh);
-}
-
-unsigned oc_enc_frag_satd2_thresh(const oc_enc_ctx *_enc,
- const unsigned char *_src,const unsigned char *_ref1,
- const unsigned char *_ref2,int _ystride,unsigned _thresh){
- return (*_enc->opt_vtable.frag_satd2_thresh)(_src,_ref1,_ref2,_ystride,
- _thresh);
+ return oc_hadamard_sad(_dc,buf);
}
-unsigned oc_enc_frag_satd2_thresh_c(const unsigned char *_src,
- const unsigned char *_ref1,const unsigned char *_ref2,int _ystride,
- unsigned _thresh){
+unsigned oc_enc_frag_satd2_c(int *_dc,const unsigned char *_src,
+ const unsigned char *_ref1,const unsigned char *_ref2,int _ystride){
ogg_int16_t buf[64];
oc_diff_hadamard2(buf,_src,_ref1,_ref2,_ystride);
- return oc_hadamard_sad_thresh(buf,_thresh);
+ return oc_hadamard_sad(_dc,buf);
}
-unsigned oc_enc_frag_intra_satd(const oc_enc_ctx *_enc,
+unsigned oc_enc_frag_intra_satd_c(int *_dc,
const unsigned char *_src,int _ystride){
- return (*_enc->opt_vtable.frag_intra_satd)(_src,_ystride);
-}
-
-unsigned oc_enc_frag_intra_satd_c(const unsigned char *_src,int _ystride){
ogg_int16_t buf[64];
oc_intra_hadamard(buf,_src,_ystride);
- return oc_hadamard_sad_thresh(buf,UINT_MAX)
- -abs(buf[0]+buf[1]+buf[2]+buf[3]+buf[4]+buf[5]+buf[6]+buf[7]);
+ return oc_hadamard_sad(_dc,buf);
}
-void oc_enc_frag_copy2(const oc_enc_ctx *_enc,unsigned char *_dst,
- const unsigned char *_src1,const unsigned char *_src2,int _ystride){
- (*_enc->opt_vtable.frag_copy2)(_dst,_src1,_src2,_ystride);
+unsigned oc_enc_frag_ssd_c(const unsigned char *_src,
+ const unsigned char *_ref,int _ystride){
+ unsigned ret;
+ int y;
+ int x;
+ ret=0;
+ for(y=0;y<8;y++){
+ for(x=0;x<8;x++)ret+=(_src[x]-_ref[x])*(_src[x]-_ref[x]);
+ _src+=_ystride;
+ _ref+=_ystride;
+ }
+ return ret;
+}
+
+unsigned oc_enc_frag_border_ssd_c(const unsigned char *_src,
+ const unsigned char *_ref,int _ystride,ogg_int64_t _mask){
+ unsigned ret;
+ int y;
+ int x;
+ ret=0;
+ for(y=0;y<8;y++){
+ for(x=0;x<8;x++,_mask>>=1){
+ if(_mask&1)ret+=(_src[x]-_ref[x])*(_src[x]-_ref[x]);
+ }
+ _src+=_ystride;
+ _ref+=_ystride;
+ }
+ return ret;
}
void oc_enc_frag_copy2_c(unsigned char *_dst,
@@ -376,13 +377,3 @@ void oc_enc_frag_copy2_c(unsigned char *_dst,
_src2+=_ystride;
}
}
-
-void oc_enc_frag_recon_intra(const oc_enc_ctx *_enc,
- unsigned char *_dst,int _ystride,const ogg_int16_t _residue[64]){
- (*_enc->opt_vtable.frag_recon_intra)(_dst,_ystride,_residue);
-}
-
-void oc_enc_frag_recon_inter(const oc_enc_ctx *_enc,unsigned char *_dst,
- const unsigned char *_src,int _ystride,const ogg_int16_t _residue[64]){
- (*_enc->opt_vtable.frag_recon_inter)(_dst,_src,_ystride,_residue);
-}
diff --git a/thirdparty/libtheora/encinfo.c b/thirdparty/libtheora/encinfo.c
index 83be1dae72..41db6bad45 100644
--- a/thirdparty/libtheora/encinfo.c
+++ b/thirdparty/libtheora/encinfo.c
@@ -1,6 +1,6 @@
#include <stdlib.h>
#include <string.h>
-#include "internal.h"
+#include "state.h"
#include "enquant.h"
#include "huffenc.h"
diff --git a/thirdparty/libtheora/encint.h b/thirdparty/libtheora/encint.h
index 97897d5a04..d25de4b8f6 100644
--- a/thirdparty/libtheora/encint.h
+++ b/thirdparty/libtheora/encint.h
@@ -11,17 +11,13 @@
********************************************************************
function:
- last mod: $Id: encint.h 16503 2009-08-22 18:14:02Z giles $
+ last mod: $Id$
********************************************************************/
#if !defined(_encint_H)
# define _encint_H (1)
-# if defined(HAVE_CONFIG_H)
-# include "config.h"
-# endif
# include "theora/theoraenc.h"
-# include "internal.h"
-# include "ocintrin.h"
+# include "state.h"
# include "mathops.h"
# include "enquant.h"
# include "huffenc.h"
@@ -32,8 +28,13 @@
typedef oc_mv oc_mv2[2];
typedef struct oc_enc_opt_vtable oc_enc_opt_vtable;
+typedef struct oc_enc_opt_data oc_enc_opt_data;
typedef struct oc_mb_enc_info oc_mb_enc_info;
typedef struct oc_mode_scheme_chooser oc_mode_scheme_chooser;
+typedef struct oc_fr_state oc_fr_state;
+typedef struct oc_qii_state oc_qii_state;
+typedef struct oc_enc_pipeline_state oc_enc_pipeline_state;
+typedef struct oc_mode_rd oc_mode_rd;
typedef struct oc_iir_filter oc_iir_filter;
typedef struct oc_frame_metrics oc_frame_metrics;
typedef struct oc_rc_state oc_rc_state;
@@ -42,6 +43,170 @@ typedef struct oc_token_checkpoint oc_token_checkpoint;
+/*Encoder-specific accelerated functions.*/
+# if defined(OC_X86_ASM)
+# if defined(_MSC_VER)
+# include "x86_vc/x86enc.h"
+# else
+# include "x86/x86enc.h"
+# endif
+# endif
+# if defined(OC_ARM_ASM)
+# include "arm/armenc.h"
+# endif
+
+# if !defined(oc_enc_accel_init)
+# define oc_enc_accel_init oc_enc_accel_init_c
+# endif
+# if defined(OC_ENC_USE_VTABLE)
+# if !defined(oc_enc_frag_sub)
+# define oc_enc_frag_sub(_enc,_diff,_src,_ref,_ystride) \
+ ((*(_enc)->opt_vtable.frag_sub)(_diff,_src,_ref,_ystride))
+# endif
+# if !defined(oc_enc_frag_sub_128)
+# define oc_enc_frag_sub_128(_enc,_diff,_src,_ystride) \
+ ((*(_enc)->opt_vtable.frag_sub_128)(_diff,_src,_ystride))
+# endif
+# if !defined(oc_enc_frag_sad)
+# define oc_enc_frag_sad(_enc,_src,_ref,_ystride) \
+ ((*(_enc)->opt_vtable.frag_sad)(_src,_ref,_ystride))
+# endif
+# if !defined(oc_enc_frag_sad_thresh)
+# define oc_enc_frag_sad_thresh(_enc,_src,_ref,_ystride,_thresh) \
+ ((*(_enc)->opt_vtable.frag_sad_thresh)(_src,_ref,_ystride,_thresh))
+# endif
+# if !defined(oc_enc_frag_sad2_thresh)
+# define oc_enc_frag_sad2_thresh(_enc,_src,_ref1,_ref2,_ystride,_thresh) \
+ ((*(_enc)->opt_vtable.frag_sad2_thresh)(_src,_ref1,_ref2,_ystride,_thresh))
+# endif
+# if !defined(oc_enc_frag_intra_sad)
+# define oc_enc_frag_intra_sad(_enc,_src,_ystride) \
+ ((*(_enc)->opt_vtable.frag_intra_sad)(_src,_ystride))
+# endif
+# if !defined(oc_enc_frag_satd)
+# define oc_enc_frag_satd(_enc,_dc,_src,_ref,_ystride) \
+ ((*(_enc)->opt_vtable.frag_satd)(_dc,_src,_ref,_ystride))
+# endif
+# if !defined(oc_enc_frag_satd2)
+# define oc_enc_frag_satd2(_enc,_dc,_src,_ref1,_ref2,_ystride) \
+ ((*(_enc)->opt_vtable.frag_satd2)(_dc,_src,_ref1,_ref2,_ystride))
+# endif
+# if !defined(oc_enc_frag_intra_satd)
+# define oc_enc_frag_intra_satd(_enc,_dc,_src,_ystride) \
+ ((*(_enc)->opt_vtable.frag_intra_satd)(_dc,_src,_ystride))
+# endif
+# if !defined(oc_enc_frag_ssd)
+# define oc_enc_frag_ssd(_enc,_src,_ref,_ystride) \
+ ((*(_enc)->opt_vtable.frag_ssd)(_src,_ref,_ystride))
+# endif
+# if !defined(oc_enc_frag_border_ssd)
+# define oc_enc_frag_border_ssd(_enc,_src,_ref,_ystride,_mask) \
+ ((*(_enc)->opt_vtable.frag_border_ssd)(_src,_ref,_ystride,_mask))
+# endif
+# if !defined(oc_enc_frag_copy2)
+# define oc_enc_frag_copy2(_enc,_dst,_src1,_src2,_ystride) \
+ ((*(_enc)->opt_vtable.frag_copy2)(_dst,_src1,_src2,_ystride))
+# endif
+# if !defined(oc_enc_enquant_table_init)
+# define oc_enc_enquant_table_init(_enc,_enquant,_dequant) \
+ ((*(_enc)->opt_vtable.enquant_table_init)(_enquant,_dequant))
+# endif
+# if !defined(oc_enc_enquant_table_fixup)
+# define oc_enc_enquant_table_fixup(_enc,_enquant,_nqis) \
+ ((*(_enc)->opt_vtable.enquant_table_fixup)(_enquant,_nqis))
+# endif
+# if !defined(oc_enc_quantize)
+# define oc_enc_quantize(_enc,_qdct,_dct,_dequant,_enquant) \
+ ((*(_enc)->opt_vtable.quantize)(_qdct,_dct,_dequant,_enquant))
+# endif
+# if !defined(oc_enc_frag_recon_intra)
+# define oc_enc_frag_recon_intra(_enc,_dst,_ystride,_residue) \
+ ((*(_enc)->opt_vtable.frag_recon_intra)(_dst,_ystride,_residue))
+# endif
+# if !defined(oc_enc_frag_recon_inter)
+# define oc_enc_frag_recon_inter(_enc,_dst,_src,_ystride,_residue) \
+ ((*(_enc)->opt_vtable.frag_recon_inter)(_dst,_src,_ystride,_residue))
+# endif
+# if !defined(oc_enc_fdct8x8)
+# define oc_enc_fdct8x8(_enc,_y,_x) \
+ ((*(_enc)->opt_vtable.fdct8x8)(_y,_x))
+# endif
+# else
+# if !defined(oc_enc_frag_sub)
+# define oc_enc_frag_sub(_enc,_diff,_src,_ref,_ystride) \
+ oc_enc_frag_sub_c(_diff,_src,_ref,_ystride)
+# endif
+# if !defined(oc_enc_frag_sub_128)
+# define oc_enc_frag_sub_128(_enc,_diff,_src,_ystride) \
+ oc_enc_frag_sub_128_c(_diff,_src,_ystride)
+# endif
+# if !defined(oc_enc_frag_sad)
+# define oc_enc_frag_sad(_enc,_src,_ref,_ystride) \
+ oc_enc_frag_sad_c(_src,_ref,_ystride)
+# endif
+# if !defined(oc_enc_frag_sad_thresh)
+# define oc_enc_frag_sad_thresh(_enc,_src,_ref,_ystride,_thresh) \
+ oc_enc_frag_sad_thresh_c(_src,_ref,_ystride,_thresh)
+# endif
+# if !defined(oc_enc_frag_sad2_thresh)
+# define oc_enc_frag_sad2_thresh(_enc,_src,_ref1,_ref2,_ystride,_thresh) \
+ oc_enc_frag_sad2_thresh_c(_src,_ref1,_ref2,_ystride,_thresh)
+# endif
+# if !defined(oc_enc_frag_intra_sad)
+# define oc_enc_frag_intra_sad(_enc,_src,_ystride) \
+ oc_enc_frag_intra_sad_c(_src,_ystride)
+# endif
+# if !defined(oc_enc_frag_satd)
+# define oc_enc_frag_satd(_enc,_dc,_src,_ref,_ystride) \
+ oc_enc_frag_satd_c(_dc,_src,_ref,_ystride)
+# endif
+# if !defined(oc_enc_frag_satd2)
+# define oc_enc_frag_satd2(_enc,_dc,_src,_ref1,_ref2,_ystride) \
+ oc_enc_frag_satd2_c(_dc,_src,_ref1,_ref2,_ystride)
+# endif
+# if !defined(oc_enc_frag_intra_satd)
+# define oc_enc_frag_intra_satd(_enc,_dc,_src,_ystride) \
+ oc_enc_frag_intra_satd_c(_dc,_src,_ystride)
+# endif
+# if !defined(oc_enc_frag_ssd)
+# define oc_enc_frag_ssd(_enc,_src,_ref,_ystride) \
+ oc_enc_frag_ssd_c(_src,_ref,_ystride)
+# endif
+# if !defined(oc_enc_frag_border_ssd)
+# define oc_enc_frag_border_ssd(_enc,_src,_ref,_ystride,_mask) \
+ oc_enc_frag_border_ssd_c(_src,_ref,_ystride,_mask)
+# endif
+# if !defined(oc_enc_frag_copy2)
+# define oc_enc_frag_copy2(_enc,_dst,_src1,_src2,_ystride) \
+ oc_enc_frag_copy2_c(_dst,_src1,_src2,_ystride)
+# endif
+# if !defined(oc_enc_enquant_table_init)
+# define oc_enc_enquant_table_init(_enc,_enquant,_dequant) \
+ oc_enc_enquant_table_init_c(_enquant,_dequant)
+# endif
+# if !defined(oc_enc_enquant_table_fixup)
+# define oc_enc_enquant_table_fixup(_enc,_enquant,_nqis) \
+ oc_enc_enquant_table_fixup_c(_enquant,_nqis)
+# endif
+# if !defined(oc_enc_quantize)
+# define oc_enc_quantize(_enc,_qdct,_dct,_dequant,_enquant) \
+ oc_enc_quantize_c(_qdct,_dct,_dequant,_enquant)
+# endif
+# if !defined(oc_enc_frag_recon_intra)
+# define oc_enc_frag_recon_intra(_enc,_dst,_ystride,_residue) \
+ oc_frag_recon_intra_c(_dst,_ystride,_residue)
+# endif
+# if !defined(oc_enc_frag_recon_inter)
+# define oc_enc_frag_recon_inter(_enc,_dst,_src,_ystride,_residue) \
+ oc_frag_recon_inter_c(_dst,_src,_ystride,_residue)
+# endif
+# if !defined(oc_enc_fdct8x8)
+# define oc_enc_fdct8x8(_enc,_y,_x) oc_enc_fdct8x8_c(_y,_x)
+# endif
+# endif
+
+
+
/*Constants for the packet-out state machine specific to the encoder.*/
/*Next packet to emit: Data packet, but none are ready yet.*/
@@ -50,13 +215,61 @@ typedef struct oc_token_checkpoint oc_token_checkpoint;
#define OC_PACKET_READY (1)
/*All features enabled.*/
-#define OC_SP_LEVEL_SLOW (0)
+#define OC_SP_LEVEL_SLOW (0)
/*Enable early skip.*/
-#define OC_SP_LEVEL_EARLY_SKIP (1)
+#define OC_SP_LEVEL_EARLY_SKIP (1)
+/*Use analysis shortcuts, single quantizer, and faster tokenization.*/
+#define OC_SP_LEVEL_FAST_ANALYSIS (2)
+/*Use SAD instead of SATD*/
+#define OC_SP_LEVEL_NOSATD (3)
/*Disable motion compensation.*/
-#define OC_SP_LEVEL_NOMC (2)
+#define OC_SP_LEVEL_NOMC (4)
/*Maximum valid speed level.*/
-#define OC_SP_LEVEL_MAX (2)
+#define OC_SP_LEVEL_MAX (4)
+
+
+/*The number of extra bits of precision at which to store rate metrics.*/
+# define OC_BIT_SCALE (6)
+/*The number of extra bits of precision at which to store RMSE metrics.
+ This must be at least half OC_BIT_SCALE (rounded up).*/
+# define OC_RMSE_SCALE (5)
+/*The number of quantizer bins to partition statistics into.*/
+# define OC_LOGQ_BINS (8)
+/*The number of SAD/SATD bins to partition statistics into.*/
+# define OC_COMP_BINS (24)
+/*The number of bits of precision to drop from SAD and SATD scores
+ to assign them to a bin.*/
+# define OC_SAD_SHIFT (6)
+# define OC_SATD_SHIFT (9)
+
+/*Masking is applied by scaling the D used in R-D optimization (via rd_scale)
+ or the lambda parameter (via rd_iscale).
+ These are only equivalent within a single block; when more than one block is
+ being considered, the former is the interpretation used.*/
+
+/*This must be at least 4 for OC_RD_SKIP_SCALE() to work below.*/
+# define OC_RD_SCALE_BITS (12-OC_BIT_SCALE)
+# define OC_RD_ISCALE_BITS (11)
+
+/*This macro is applied to _ssd values with just 4 bits of headroom
+ ((15-OC_RMSE_SCALE)*2+OC_BIT_SCALE+2); since we want to allow rd_scales as
+ large as 16, and need additional fractional bits, our only recourse that
+ doesn't lose precision on blocks with very small SSDs is to use a wider
+ multiply.*/
+# if LONG_MAX>2147483647
+# define OC_RD_SCALE(_ssd,_rd_scale) \
+ ((unsigned)((unsigned long)(_ssd)*(_rd_scale) \
+ +((1<<OC_RD_SCALE_BITS)>>1)>>OC_RD_SCALE_BITS))
+# else
+# define OC_RD_SCALE(_ssd,_rd_scale) \
+ (((_ssd)>>OC_RD_SCALE_BITS)*(_rd_scale) \
+ +(((_ssd)&(1<<OC_RD_SCALE_BITS)-1)*(_rd_scale) \
+ +((1<<OC_RD_SCALE_BITS)>>1)>>OC_RD_SCALE_BITS))
+# endif
+# define OC_RD_SKIP_SCALE(_ssd,_rd_scale) \
+ ((_ssd)*(_rd_scale)+((1<<OC_RD_SCALE_BITS-4)>>1)>>OC_RD_SCALE_BITS-4)
+# define OC_RD_ISCALE(_lambda,_rd_iscale) \
+ ((_lambda)*(_rd_iscale)+((1<<OC_RD_ISCALE_BITS)>>1)>>OC_RD_ISCALE_BITS)
/*The bits used for each of the MB mode codebooks.*/
@@ -78,6 +291,10 @@ extern const unsigned char OC_BLOCK_RUN_CODE_NBITS[30];
/*Encoder specific functions with accelerated variants.*/
struct oc_enc_opt_vtable{
+ void (*frag_sub)(ogg_int16_t _diff[64],const unsigned char *_src,
+ const unsigned char *_ref,int _ystride);
+ void (*frag_sub_128)(ogg_int16_t _diff[64],
+ const unsigned char *_src,int _ystride);
unsigned (*frag_sad)(const unsigned char *_src,
const unsigned char *_ref,int _ystride);
unsigned (*frag_sad_thresh)(const unsigned char *_src,
@@ -85,18 +302,23 @@ struct oc_enc_opt_vtable{
unsigned (*frag_sad2_thresh)(const unsigned char *_src,
const unsigned char *_ref1,const unsigned char *_ref2,int _ystride,
unsigned _thresh);
- unsigned (*frag_satd_thresh)(const unsigned char *_src,
- const unsigned char *_ref,int _ystride,unsigned _thresh);
- unsigned (*frag_satd2_thresh)(const unsigned char *_src,
- const unsigned char *_ref1,const unsigned char *_ref2,int _ystride,
- unsigned _thresh);
- unsigned (*frag_intra_satd)(const unsigned char *_src,int _ystride);
- void (*frag_sub)(ogg_int16_t _diff[64],const unsigned char *_src,
+ unsigned (*frag_intra_sad)(const unsigned char *_src,int _ystride);
+ unsigned (*frag_satd)(int *_dc,const unsigned char *_src,
const unsigned char *_ref,int _ystride);
- void (*frag_sub_128)(ogg_int16_t _diff[64],
- const unsigned char *_src,int _ystride);
+ unsigned (*frag_satd2)(int *_dc,const unsigned char *_src,
+ const unsigned char *_ref1,const unsigned char *_ref2,int _ystride);
+ unsigned (*frag_intra_satd)(int *_dc,const unsigned char *_src,int _ystride);
+ unsigned (*frag_ssd)(const unsigned char *_src,
+ const unsigned char *_ref,int _ystride);
+ unsigned (*frag_border_ssd)(const unsigned char *_src,
+ const unsigned char *_ref,int _ystride,ogg_int64_t _mask);
void (*frag_copy2)(unsigned char *_dst,
const unsigned char *_src1,const unsigned char *_src2,int _ystride);
+ void (*enquant_table_init)(void *_enquant,
+ const ogg_uint16_t _dequant[64]);
+ void (*enquant_table_fixup)(void *_enquant[3][3][2],int _nqis);
+ int (*quantize)(ogg_int16_t _qdct[64],const ogg_int16_t _dct[64],
+ const ogg_uint16_t _dequant[64],const void *_enquant);
void (*frag_recon_intra)(unsigned char *_dst,int _ystride,
const ogg_int16_t _residue[64]);
void (*frag_recon_inter)(unsigned char *_dst,
@@ -105,7 +327,19 @@ struct oc_enc_opt_vtable{
};
-void oc_enc_vtable_init(oc_enc_ctx *_enc);
+/*Encoder specific data that varies according to which variants of the above
+ functions are used.*/
+struct oc_enc_opt_data{
+ /*The size of a single quantizer table.
+ This must be a multiple of enquant_table_alignment.*/
+ size_t enquant_table_size;
+ /*The alignment required for the quantizer tables.
+ This must be a positive power of two.*/
+ int enquant_table_alignment;
+};
+
+
+void oc_enc_accel_init(oc_enc_ctx *_enc);
@@ -158,7 +392,7 @@ struct oc_mode_scheme_chooser{
corresponds to the ranks above.*/
unsigned char scheme0_list[OC_NMODES];
/*The number of times each mode has been chosen so far.*/
- int mode_counts[OC_NMODES];
+ unsigned mode_counts[OC_NMODES];
/*The list of mode coding schemes, sorted in ascending order of bit cost.*/
unsigned char scheme_list[8];
/*The number of bits used by each mode coding scheme.*/
@@ -170,6 +404,106 @@ void oc_mode_scheme_chooser_init(oc_mode_scheme_chooser *_chooser);
+/*State to track coded block flags and their bit cost.
+ We use opportunity cost to measure the bits required to code or skip the next
+ block, using the cheaper of the cost to code it fully or partially, so long
+ as both are possible.*/
+struct oc_fr_state{
+ /*The number of bits required for the coded block flags so far this frame.*/
+ ptrdiff_t bits;
+ /*The length of the current run for the partial super block flag, not
+ including the current super block.*/
+ unsigned sb_partial_count:16;
+ /*The length of the current run for the full super block flag, not
+ including the current super block.*/
+ unsigned sb_full_count:16;
+ /*The length of the coded block flag run when the current super block
+ started.*/
+ unsigned b_coded_count_prev:6;
+ /*The coded block flag when the current super block started.*/
+ signed int b_coded_prev:2;
+ /*The length of the current coded block flag run.*/
+ unsigned b_coded_count:6;
+ /*The current coded block flag.*/
+ signed int b_coded:2;
+ /*The number of blocks processed in the current super block.*/
+ unsigned b_count:5;
+ /*Whether or not it is cheaper to code the current super block partially,
+ even if it could still be coded fully.*/
+ unsigned sb_prefer_partial:1;
+ /*Whether the last super block was coded partially.*/
+ signed int sb_partial:2;
+ /*The number of bits required for the flags for the current super block.*/
+ unsigned sb_bits:6;
+ /*Whether the last non-partial super block was coded fully.*/
+ signed int sb_full:2;
+};
+
+
+
+struct oc_qii_state{
+ ptrdiff_t bits;
+ unsigned qi01_count:14;
+ signed int qi01:2;
+ unsigned qi12_count:14;
+ signed int qi12:2;
+};
+
+
+
+/*Temporary encoder state for the analysis pipeline.*/
+struct oc_enc_pipeline_state{
+ /*DCT coefficient storage.
+ This is kept off the stack because a) gcc can't align things on the stack
+ reliably on ARM, and b) it avoids (unintentional) data hazards between
+ ARM and NEON code.*/
+ OC_ALIGN16(ogg_int16_t dct_data[64*3]);
+ OC_ALIGN16(signed char bounding_values[256]);
+ oc_fr_state fr[3];
+ oc_qii_state qs[3];
+ /*Skip SSD storage for the current MCU in each plane.*/
+ unsigned *skip_ssd[3];
+ /*Coded/uncoded fragment lists for each plane for the current MCU.*/
+ ptrdiff_t *coded_fragis[3];
+ ptrdiff_t *uncoded_fragis[3];
+ ptrdiff_t ncoded_fragis[3];
+ ptrdiff_t nuncoded_fragis[3];
+ /*The starting fragment for the current MCU in each plane.*/
+ ptrdiff_t froffset[3];
+ /*The starting row for the current MCU in each plane.*/
+ int fragy0[3];
+ /*The ending row for the current MCU in each plane.*/
+ int fragy_end[3];
+ /*The starting superblock for the current MCU in each plane.*/
+ unsigned sbi0[3];
+ /*The ending superblock for the current MCU in each plane.*/
+ unsigned sbi_end[3];
+ /*The number of tokens for zzi=1 for each color plane.*/
+ int ndct_tokens1[3];
+ /*The outstanding eob_run count for zzi=1 for each color plane.*/
+ int eob_run1[3];
+ /*Whether or not the loop filter is enabled.*/
+ int loop_filter;
+};
+
+
+
+/*Statistics used to estimate R-D cost of a block in a given coding mode.
+ See modedec.h for more details.*/
+struct oc_mode_rd{
+ /*The expected bits used by the DCT tokens, shifted by OC_BIT_SCALE.*/
+ ogg_int16_t rate;
+ /*The expected square root of the sum of squared errors, shifted by
+ OC_RMSE_SCALE.*/
+ ogg_int16_t rmse;
+};
+
+# if defined(OC_COLLECT_METRICS)
+# include "collect.h"
+# endif
+
+
+
/*A 2nd order low-pass Bessel follower.
We use this for rate control because it has fast reaction time, but is
critically damped.*/
@@ -190,6 +524,8 @@ struct oc_frame_metrics{
unsigned dup_count:31;
/*The frame type from pass 1.*/
unsigned frame_type:1;
+ /*The frame activity average from pass 1.*/
+ unsigned activity_avg;
};
@@ -335,10 +671,15 @@ struct th_enc_ctx{
size_t mv_bits[2];
/*The mode scheme chooser for estimating mode coding costs.*/
oc_mode_scheme_chooser chooser;
+ /*Temporary encoder state for the analysis pipeline.*/
+ oc_enc_pipeline_state pipe;
/*The number of vertical super blocks in an MCU.*/
int mcu_nvsbs;
/*The SSD error for skipping each fragment in the current MCU.*/
unsigned *mcu_skip_ssd;
+ /*The masking scale factors for chroma blocks in the current MCU.*/
+ ogg_uint16_t *mcu_rd_scale;
+ ogg_uint16_t *mcu_rd_iscale;
/*The DCT token lists for each coefficient and each plane.*/
unsigned char **dct_tokens[3];
/*The extra bits associated with each DCT token.*/
@@ -350,8 +691,10 @@ struct th_enc_ctx{
/*The offset of the first DCT token for each coefficient for each plane.*/
unsigned char dct_token_offs[3][64];
/*The last DC coefficient for each plane and reference frame.*/
- int dc_pred_last[3][3];
+ int dc_pred_last[3][4];
#if defined(OC_COLLECT_METRICS)
+ /*Fragment SAD statistics for MB mode estimation metrics.*/
+ unsigned *frag_sad;
/*Fragment SATD statistics for MB mode estimation metrics.*/
unsigned *frag_satd;
/*Fragment SSD statistics for MB mode estimation metrics.*/
@@ -359,32 +702,56 @@ struct th_enc_ctx{
#endif
/*The R-D optimization parameter.*/
int lambda;
+ /*The average block "activity" of the previous frame.*/
+ unsigned activity_avg;
+ /*The average MB luma of the previous frame.*/
+ unsigned luma_avg;
/*The huffman tables in use.*/
th_huff_code huff_codes[TH_NHUFFMAN_TABLES][TH_NDCT_TOKENS];
/*The quantization parameters in use.*/
th_quant_info qinfo;
- oc_iquant *enquant_tables[64][3][2];
- oc_iquant_table enquant_table_data[64][3][2];
- /*An "average" quantizer for each quantizer type (INTRA or INTER) and qi
- value.
- This is used to paramterize the rate control decisions.
+ /*The original DC coefficients saved off from the dequatization tables.*/
+ ogg_uint16_t dequant_dc[64][3][2];
+ /*Condensed dequantization tables.*/
+ const ogg_uint16_t *dequant[3][3][2];
+ /*Condensed quantization tables.*/
+ void *enquant[3][3][2];
+ /*The full set of quantization tables.*/
+ void *enquant_tables[64][3][2];
+ /*Storage for the quantization tables.*/
+ unsigned char *enquant_table_data;
+ /*An "average" quantizer for each frame type (INTRA or INTER) and qi value.
+ This is used to parameterize the rate control decisions.
They are kept in the log domain to simplify later processing.
- Keep in mind these are DCT domain quantizers, and so are scaled by an
- additional factor of 4 from the pixel domain.*/
+ These are DCT domain quantizers, and so are scaled by an additional factor
+ of 4 from the pixel domain.*/
ogg_int64_t log_qavg[2][64];
+ /*The "average" quantizer futher partitioned by color plane.
+ This is used to parameterize mode decision.
+ These are DCT domain quantizers, and so are scaled by an additional factor
+ of 4 from the pixel domain.*/
+ ogg_int16_t log_plq[64][3][2];
+ /*The R-D scale factors to apply to chroma blocks for a given frame type
+ (INTRA or INTER) and qi value.
+ The first is the "D" modifier (rd_scale), while the second is the "lambda"
+ modifier (rd_iscale).*/
+ ogg_uint16_t chroma_rd_scale[2][64][2];
+ /*The interpolated mode decision R-D lookup tables for the current
+ quantizers, color plane, and quantization type.*/
+ oc_mode_rd mode_rd[3][3][2][OC_COMP_BINS];
/*The buffer state used to drive rate control.*/
oc_rc_state rc;
+# if defined(OC_ENC_USE_VTABLE)
/*Table for encoder acceleration functions.*/
oc_enc_opt_vtable opt_vtable;
+# endif
+ /*Table for encoder data used by accelerated functions.*/
+ oc_enc_opt_data opt_data;
};
void oc_enc_analyze_intra(oc_enc_ctx *_enc,int _recode);
int oc_enc_analyze_inter(oc_enc_ctx *_enc,int _allow_keyframe,int _recode);
-#if defined(OC_COLLECT_METRICS)
-void oc_enc_mode_metrics_collect(oc_enc_ctx *_enc);
-void oc_enc_mode_metrics_dump(oc_enc_ctx *_enc);
-#endif
@@ -415,8 +782,13 @@ struct oc_token_checkpoint{
void oc_enc_tokenize_start(oc_enc_ctx *_enc);
int oc_enc_tokenize_ac(oc_enc_ctx *_enc,int _pli,ptrdiff_t _fragi,
- ogg_int16_t *_qdct,const ogg_uint16_t *_dequant,const ogg_int16_t *_dct,
- int _zzi,oc_token_checkpoint **_stack,int _acmin);
+ ogg_int16_t *_qdct_out,const ogg_int16_t *_qdct_in,
+ const ogg_uint16_t *_dequant,const ogg_int16_t *_dct,
+ int _zzi,oc_token_checkpoint **_stack,int _lambda,int _acmin);
+int oc_enc_tokenize_ac_fast(oc_enc_ctx *_enc,int _pli,ptrdiff_t _fragi,
+ ogg_int16_t *_qdct_out,const ogg_int16_t *_qdct_in,
+ const ogg_uint16_t *_dequant,const ogg_int16_t *_dct,
+ int _zzi,oc_token_checkpoint **_stack,int _lambda,int _acmin);
void oc_enc_tokenlog_rollback(oc_enc_ctx *_enc,
const oc_token_checkpoint *_stack,int _n);
void oc_enc_pred_dc_frag_rows(oc_enc_ctx *_enc,
@@ -436,45 +808,13 @@ int oc_state_flushheader(oc_theora_state *_state,int *_packet_state,
-/*Encoder-specific accelerated functions.*/
-void oc_enc_frag_sub(const oc_enc_ctx *_enc,ogg_int16_t _diff[64],
- const unsigned char *_src,const unsigned char *_ref,int _ystride);
-void oc_enc_frag_sub_128(const oc_enc_ctx *_enc,ogg_int16_t _diff[64],
- const unsigned char *_src,int _ystride);
-unsigned oc_enc_frag_sad(const oc_enc_ctx *_enc,const unsigned char *_src,
- const unsigned char *_ref,int _ystride);
-unsigned oc_enc_frag_sad_thresh(const oc_enc_ctx *_enc,
- const unsigned char *_src,const unsigned char *_ref,int _ystride,
- unsigned _thresh);
-unsigned oc_enc_frag_sad2_thresh(const oc_enc_ctx *_enc,
- const unsigned char *_src,const unsigned char *_ref1,
- const unsigned char *_ref2,int _ystride,unsigned _thresh);
-unsigned oc_enc_frag_satd_thresh(const oc_enc_ctx *_enc,
- const unsigned char *_src,const unsigned char *_ref,int _ystride,
- unsigned _thresh);
-unsigned oc_enc_frag_satd2_thresh(const oc_enc_ctx *_enc,
- const unsigned char *_src,const unsigned char *_ref1,
- const unsigned char *_ref2,int _ystride,unsigned _thresh);
-unsigned oc_enc_frag_intra_satd(const oc_enc_ctx *_enc,
- const unsigned char *_src,int _ystride);
-void oc_enc_frag_copy2(const oc_enc_ctx *_enc,unsigned char *_dst,
- const unsigned char *_src1,const unsigned char *_src2,int _ystride);
-void oc_enc_frag_recon_intra(const oc_enc_ctx *_enc,
- unsigned char *_dst,int _ystride,const ogg_int16_t _residue[64]);
-void oc_enc_frag_recon_inter(const oc_enc_ctx *_enc,unsigned char *_dst,
- const unsigned char *_src,int _ystride,const ogg_int16_t _residue[64]);
-void oc_enc_fdct8x8(const oc_enc_ctx *_enc,ogg_int16_t _y[64],
- const ogg_int16_t _x[64]);
-
-/*Default pure-C implementations.*/
-void oc_enc_vtable_init_c(oc_enc_ctx *_enc);
+/*Default pure-C implementations of encoder-specific accelerated functions.*/
+void oc_enc_accel_init_c(oc_enc_ctx *_enc);
void oc_enc_frag_sub_c(ogg_int16_t _diff[64],
const unsigned char *_src,const unsigned char *_ref,int _ystride);
void oc_enc_frag_sub_128_c(ogg_int16_t _diff[64],
const unsigned char *_src,int _ystride);
-void oc_enc_frag_copy2_c(unsigned char *_dst,
- const unsigned char *_src1,const unsigned char *_src2,int _ystride);
unsigned oc_enc_frag_sad_c(const unsigned char *_src,
const unsigned char *_ref,int _ystride);
unsigned oc_enc_frag_sad_thresh_c(const unsigned char *_src,
@@ -482,12 +822,24 @@ unsigned oc_enc_frag_sad_thresh_c(const unsigned char *_src,
unsigned oc_enc_frag_sad2_thresh_c(const unsigned char *_src,
const unsigned char *_ref1,const unsigned char *_ref2,int _ystride,
unsigned _thresh);
-unsigned oc_enc_frag_satd_thresh_c(const unsigned char *_src,
- const unsigned char *_ref,int _ystride,unsigned _thresh);
-unsigned oc_enc_frag_satd2_thresh_c(const unsigned char *_src,
- const unsigned char *_ref1,const unsigned char *_ref2,int _ystride,
- unsigned _thresh);
-unsigned oc_enc_frag_intra_satd_c(const unsigned char *_src,int _ystride);
+unsigned oc_enc_frag_intra_sad_c(const unsigned char *_src, int _ystride);
+unsigned oc_enc_frag_satd_c(int *_dc,const unsigned char *_src,
+ const unsigned char *_ref,int _ystride);
+unsigned oc_enc_frag_satd2_c(int *_dc,const unsigned char *_src,
+ const unsigned char *_ref1,const unsigned char *_ref2,int _ystride);
+unsigned oc_enc_frag_intra_satd_c(int *_dc,
+ const unsigned char *_src,int _ystride);
+unsigned oc_enc_frag_ssd_c(const unsigned char *_src,
+ const unsigned char *_ref,int _ystride);
+unsigned oc_enc_frag_border_ssd_c(const unsigned char *_src,
+ const unsigned char *_ref,int _ystride,ogg_int64_t _mask);
+void oc_enc_frag_copy2_c(unsigned char *_dst,
+ const unsigned char *_src1,const unsigned char *_src2,int _ystride);
+void oc_enc_enquant_table_init_c(void *_enquant,
+ const ogg_uint16_t _dequant[64]);
+void oc_enc_enquant_table_fixup_c(void *_enquant[3][3][2],int _nqis);
+int oc_enc_quantize_c(ogg_int16_t _qdct[64],const ogg_int16_t _dct[64],
+ const ogg_uint16_t _dequant[64],const void *_enquant);
void oc_enc_fdct8x8_c(ogg_int16_t _y[64],const ogg_int16_t _x[64]);
#endif
diff --git a/thirdparty/libtheora/encode.c b/thirdparty/libtheora/encode.c
index 0c5ea6a172..3309f97c03 100644
--- a/thirdparty/libtheora/encode.c
+++ b/thirdparty/libtheora/encode.c
@@ -11,15 +11,13 @@
********************************************************************
function:
- last mod: $Id: encode.c 16503 2009-08-22 18:14:02Z giles $
+ last mod: $Id$
********************************************************************/
#include <stdlib.h>
#include <string.h>
#include "encint.h"
-#if defined(OC_X86_ASM)
-# include "x86/x86enc.h"
-#endif
+#include "dequant.h"
@@ -288,12 +286,12 @@ const th_quant_info TH_DEF_QUANT_INFO={
28, 25, 24, 22, 20, 17, 14, 10
},
{
- 30,25,20,20,15,15,14,14,
- 13,13,12,12,11,11,10,10,
- 9, 9, 8, 8, 7, 7, 7, 7,
- 6, 6, 6, 6, 5, 5, 5, 5,
- 4, 4, 4, 4, 3, 3, 3, 3,
+ 15,12, 9, 8, 6, 6, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5,
+ 4, 4, 4, 4, 4, 4, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
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, 0, 0, 0, 0
},
@@ -623,11 +621,15 @@ static void oc_enc_mb_modes_pack(oc_enc_ctx *_enc){
}
}
-static void oc_enc_mv_pack(oc_enc_ctx *_enc,int _mv_scheme,int _dx,int _dy){
+static void oc_enc_mv_pack(oc_enc_ctx *_enc,int _mv_scheme,oc_mv _mv){
+ int dx;
+ int dy;
+ dx=OC_MV_X(_mv);
+ dy=OC_MV_Y(_mv);
oggpackB_write(&_enc->opb,
- OC_MV_CODES[_mv_scheme][_dx+31],OC_MV_BITS[_mv_scheme][_dx+31]);
+ OC_MV_CODES[_mv_scheme][dx+31],OC_MV_BITS[_mv_scheme][dx+31]);
oggpackB_write(&_enc->opb,
- OC_MV_CODES[_mv_scheme][_dy+31],OC_MV_BITS[_mv_scheme][_dy+31]);
+ OC_MV_CODES[_mv_scheme][dy+31],OC_MV_BITS[_mv_scheme][dy+31]);
}
static void oc_enc_mvs_pack(oc_enc_ctx *_enc){
@@ -650,7 +652,7 @@ static void oc_enc_mvs_pack(oc_enc_ctx *_enc){
mb_modes=_enc->state.mb_modes;
mb_maps=(const oc_mb_map *)_enc->state.mb_maps;
frags=_enc->state.frags;
- frag_mvs=(const oc_mv *)_enc->state.frag_mvs;
+ frag_mvs=_enc->state.frag_mvs;
for(mbii=0;mbii<ncoded_mbis;mbii++){
ptrdiff_t fragi;
unsigned mbi;
@@ -662,8 +664,7 @@ static void oc_enc_mvs_pack(oc_enc_ctx *_enc){
for(bi=0;;bi++){
fragi=mb_maps[mbi][0][bi];
if(frags[fragi].coded){
- oc_enc_mv_pack(_enc,mv_scheme,
- frag_mvs[fragi][0],frag_mvs[fragi][1]);
+ oc_enc_mv_pack(_enc,mv_scheme,frag_mvs[fragi]);
/*Only code a single MV for this macro block.*/
break;
}
@@ -673,8 +674,7 @@ static void oc_enc_mvs_pack(oc_enc_ctx *_enc){
for(bi=0;bi<4;bi++){
fragi=mb_maps[mbi][0][bi];
if(frags[fragi].coded){
- oc_enc_mv_pack(_enc,mv_scheme,
- frag_mvs[fragi][0],frag_mvs[fragi][1]);
+ oc_enc_mv_pack(_enc,mv_scheme,frag_mvs[fragi]);
/*Keep coding all the MVs for this macro block.*/
}
}
@@ -863,11 +863,55 @@ static void oc_enc_residual_tokens_pack(oc_enc_ctx *_enc){
}
}
+/*Packs an explicit drop frame, instead of using the more efficient 0-byte
+ packet.
+ This is only enabled in VP3-compatibility mode, even though it is not
+ strictly required for VP3 compatibility (VP3 could be encoded in AVI, which
+ also supports dropping frames by inserting 0 byte packets).
+ However, almost every _Theora_ player used to get this wrong (and many still
+ do), and it wasn't until we started shipping a post-VP3 encoder that
+ actually used non-VP3 features that this began to be discovered and fixed,
+ despite being in the standard since 2004.
+ The pack buffer must be reset before calling this function.*/
+static void oc_enc_drop_frame_pack(oc_enc_ctx *_enc){
+ unsigned nsbs;
+ /*Mark this as a data packet.*/
+ oggpackB_write(&_enc->opb,0,1);
+ /*Output the frame type (key frame or delta frame).*/
+ oggpackB_write(&_enc->opb,OC_INTER_FRAME,1);
+ /*Write out the current qi list.
+ We always use just 1 qi, to avoid wasting bits on the others.*/
+ oggpackB_write(&_enc->opb,_enc->state.qis[0],6);
+ oggpackB_write(&_enc->opb,0,1);
+ /*Coded block flags: everything is uncoded.*/
+ nsbs=_enc->state.nsbs;
+ /*No partially coded SBs.*/
+ oggpackB_write(&_enc->opb,0,1);
+ oc_sb_run_pack(&_enc->opb,nsbs,0,1);
+ /*No fully coded SBs.*/
+ oggpackB_write(&_enc->opb,0,1);
+ oc_sb_run_pack(&_enc->opb,nsbs,0,1);
+ /*MB modes: just need write which scheme to use.
+ Since we have no coded MBs, we can pick any of them except 0, which would
+ require writing out an additional mode list.*/
+ oggpackB_write(&_enc->opb,7,3);
+ /*MVs: just need write which scheme to use.
+ We can pick either one, since we have no MVs.*/
+ oggpackB_write(&_enc->opb,1,1);
+ /*Write the chosen DC token tables.*/
+ oggpackB_write(&_enc->opb,_enc->huff_idxs[OC_INTER_FRAME][0][0],4);
+ oggpackB_write(&_enc->opb,_enc->huff_idxs[OC_INTER_FRAME][0][1],4);
+ /*Write the chosen AC token tables.*/
+ oggpackB_write(&_enc->opb,_enc->huff_idxs[OC_INTER_FRAME][1][0],4);
+ oggpackB_write(&_enc->opb,_enc->huff_idxs[OC_INTER_FRAME][1][1],4);
+}
+
static void oc_enc_frame_pack(oc_enc_ctx *_enc){
+ /*musl libc malloc()/realloc() calls might use floating point, so make sure
+ we've cleared the MMX state for them.*/
+ oc_restore_fpu(&_enc->state);
oggpackB_reset(&_enc->opb);
- /*Only proceed if we have some coded blocks.
- If there are no coded blocks, we can drop this frame simply by emitting a
- 0 byte packet.*/
+ /*Only proceed if we have some coded blocks.*/
if(_enc->state.ntotal_coded_fragis>0){
oc_enc_frame_header_pack(_enc);
if(_enc->state.frame_type==OC_INTER_FRAME){
@@ -880,6 +924,10 @@ static void oc_enc_frame_pack(oc_enc_ctx *_enc){
oc_enc_tokenize_finish(_enc);
oc_enc_residual_tokens_pack(_enc);
}
+ /*If there are no coded blocks, we can drop this frame simply by emitting a
+ 0 byte packet.
+ We emit an inter frame with no coded blocks in VP3-compatibility mode.*/
+ else if(_enc->vp3_compatible)oc_enc_drop_frame_pack(_enc);
/*Success: Mark the packet as ready to be flushed.*/
_enc->packet_state=OC_PACKET_READY;
#if defined(OC_COLLECT_METRICS)
@@ -888,21 +936,31 @@ static void oc_enc_frame_pack(oc_enc_ctx *_enc){
}
-void oc_enc_vtable_init_c(oc_enc_ctx *_enc){
+void oc_enc_accel_init_c(oc_enc_ctx *_enc){
/*The implementations prefixed with oc_enc_ are encoder-specific.
The rest we re-use from the decoder.*/
+# if defined(OC_ENC_USE_VTABLE)
+ _enc->opt_vtable.frag_sub=oc_enc_frag_sub_c;
+ _enc->opt_vtable.frag_sub_128=oc_enc_frag_sub_128_c;
_enc->opt_vtable.frag_sad=oc_enc_frag_sad_c;
_enc->opt_vtable.frag_sad_thresh=oc_enc_frag_sad_thresh_c;
_enc->opt_vtable.frag_sad2_thresh=oc_enc_frag_sad2_thresh_c;
- _enc->opt_vtable.frag_satd_thresh=oc_enc_frag_satd_thresh_c;
- _enc->opt_vtable.frag_satd2_thresh=oc_enc_frag_satd2_thresh_c;
+ _enc->opt_vtable.frag_intra_sad=oc_enc_frag_intra_sad_c;
+ _enc->opt_vtable.frag_satd=oc_enc_frag_satd_c;
+ _enc->opt_vtable.frag_satd2=oc_enc_frag_satd2_c;
_enc->opt_vtable.frag_intra_satd=oc_enc_frag_intra_satd_c;
- _enc->opt_vtable.frag_sub=oc_enc_frag_sub_c;
- _enc->opt_vtable.frag_sub_128=oc_enc_frag_sub_128_c;
+ _enc->opt_vtable.frag_ssd=oc_enc_frag_ssd_c;
+ _enc->opt_vtable.frag_border_ssd=oc_enc_frag_border_ssd_c;
_enc->opt_vtable.frag_copy2=oc_enc_frag_copy2_c;
+ _enc->opt_vtable.enquant_table_init=oc_enc_enquant_table_init_c;
+ _enc->opt_vtable.enquant_table_fixup=oc_enc_enquant_table_fixup_c;
+ _enc->opt_vtable.quantize=oc_enc_quantize_c;
_enc->opt_vtable.frag_recon_intra=oc_frag_recon_intra_c;
_enc->opt_vtable.frag_recon_inter=oc_frag_recon_inter_c;
_enc->opt_vtable.fdct8x8=oc_enc_fdct8x8_c;
+# endif
+ _enc->opt_data.enquant_table_size=64*sizeof(oc_iquant);
+ _enc->opt_data.enquant_table_alignment=16;
}
/*Initialize the macro block neighbor lists for MC analysis.
@@ -1003,6 +1061,55 @@ static int oc_enc_set_huffman_codes(oc_enc_ctx *_enc,
return 0;
}
+static void oc_enc_enquant_tables_init(oc_enc_ctx *_enc,
+ const th_quant_info *_qinfo){
+ unsigned char *etd;
+ size_t ets;
+ int align;
+ int qii;
+ int qi;
+ int pli;
+ int qti;
+ for(qi=0;qi<64;qi++)for(pli=0;pli<3;pli++)for(qti=0;qti<2;qti++){
+ _enc->state.dequant_tables[qi][pli][qti]=
+ _enc->state.dequant_table_data[qi][pli][qti];
+ }
+ /*Initialize the dequantization tables.*/
+ oc_dequant_tables_init(_enc->state.dequant_tables,NULL,_qinfo);
+ /*And save off the DC values.*/
+ for(qi=0;qi<64;qi++)for(pli=0;pli<3;pli++)for(qti=0;qti<2;qti++){
+ _enc->dequant_dc[qi][pli][qti]=_enc->state.dequant_tables[qi][pli][qti][0];
+ }
+ /*Set up storage for the quantization tables.*/
+ etd=_enc->enquant_table_data;
+ ets=_enc->opt_data.enquant_table_size;
+ align=-(etd-(unsigned char *)0)&_enc->opt_data.enquant_table_alignment-1;
+ etd+=align;
+ /*Set up the main tables.*/
+ for(qi=0;qi<64;qi++)for(pli=0;pli<3;pli++)for(qti=0;qti<2;qti++){
+ _enc->enquant_tables[qi][pli][qti]=etd;
+ oc_enc_enquant_table_init(_enc,etd,
+ _enc->state.dequant_tables[qi][pli][qti]);
+ etd+=ets;
+ }
+ /*Set up storage for the local copies we modify for each frame.*/
+ for(pli=0;pli<3;pli++)for(qii=0;qii<3;qii++)for(qti=0;qti<2;qti++){
+ _enc->enquant[pli][qii][qti]=etd;
+ etd+=ets;
+ }
+}
+
+/*Updates the encoder state after the quantization parameters have been
+ changed.*/
+static void oc_enc_quant_params_updated(oc_enc_ctx *_enc,
+ const th_quant_info *_qinfo){
+ oc_enc_enquant_tables_init(_enc,_qinfo);
+ memcpy(_enc->state.loop_filter_limits,_qinfo->loop_filter_limits,
+ sizeof(_enc->state.loop_filter_limits));
+ oc_enquant_qavg_init(_enc->log_qavg,_enc->log_plq,_enc->chroma_rd_scale,
+ _enc->state.dequant_tables,_enc->state.info.pixel_fmt);
+}
+
/*Sets the quantization parameters to use.
This may only be called before the setup header is written.
If it is called multiple times, only the last call has any effect.
@@ -1012,25 +1119,20 @@ static int oc_enc_set_huffman_codes(oc_enc_ctx *_enc,
will be used.*/
static int oc_enc_set_quant_params(oc_enc_ctx *_enc,
const th_quant_info *_qinfo){
- int qi;
- int pli;
- int qti;
+ th_quant_info old_qinfo;
+ int ret;
if(_enc==NULL)return TH_EFAULT;
if(_enc->packet_state>OC_PACKET_SETUP_HDR)return TH_EINVAL;
if(_qinfo==NULL)_qinfo=&TH_DEF_QUANT_INFO;
- /*TODO: Analyze for packing purposes instead of just doing a shallow copy.*/
- memcpy(&_enc->qinfo,_qinfo,sizeof(_enc->qinfo));
- for(qi=0;qi<64;qi++)for(pli=0;pli<3;pli++)for(qti=0;qti<2;qti++){
- _enc->state.dequant_tables[qi][pli][qti]=
- _enc->state.dequant_table_data[qi][pli][qti];
- _enc->enquant_tables[qi][pli][qti]=_enc->enquant_table_data[qi][pli][qti];
+ memcpy(&old_qinfo,&_enc->qinfo,sizeof(old_qinfo));
+ ret=oc_quant_params_clone(&_enc->qinfo,_qinfo);
+ if(ret<0){
+ oc_quant_params_clear(&_enc->qinfo);
+ memcpy(&_enc->qinfo,&old_qinfo,sizeof(old_qinfo));
+ return ret;
}
- oc_enquant_tables_init(_enc->state.dequant_tables,
- _enc->enquant_tables,_qinfo);
- memcpy(_enc->state.loop_filter_limits,_qinfo->loop_filter_limits,
- sizeof(_enc->state.loop_filter_limits));
- oc_enquant_qavg_init(_enc->log_qavg,_enc->state.dequant_tables,
- _enc->state.info.pixel_fmt);
+ else oc_quant_params_clear(&old_qinfo);
+ oc_enc_quant_params_updated(_enc,_qinfo);
return 0;
}
@@ -1039,6 +1141,7 @@ static void oc_enc_clear(oc_enc_ctx *_enc);
static int oc_enc_init(oc_enc_ctx *_enc,const th_info *_info){
th_info info;
size_t mcu_nmbs;
+ ptrdiff_t mcu_ncfrags;
ptrdiff_t mcu_nfrags;
int hdec;
int vdec;
@@ -1053,8 +1156,9 @@ static int oc_enc_init(oc_enc_ctx *_enc,const th_info *_info){
if(info.quality<0)info.quality=32;
if(info.target_bitrate<0)info.target_bitrate=0;
/*Initialize the shared encoder/decoder state.*/
- ret=oc_state_init(&_enc->state,&info,4);
+ ret=oc_state_init(&_enc->state,&info,6);
if(ret<0)return ret;
+ oc_enc_accel_init(_enc);
_enc->mb_info=_ogg_calloc(_enc->state.nmbs,sizeof(*_enc->mb_info));
_enc->frag_dc=_ogg_calloc(_enc->state.nfrags,sizeof(*_enc->frag_dc));
_enc->coded_mbis=
@@ -1065,9 +1169,14 @@ static int oc_enc_init(oc_enc_ctx *_enc,const th_info *_info){
super block rows of Y' for each super block row of Cb and Cr.*/
_enc->mcu_nvsbs=1<<vdec;
mcu_nmbs=_enc->mcu_nvsbs*_enc->state.fplanes[0].nhsbs*(size_t)4;
- mcu_nfrags=4*mcu_nmbs+(8*mcu_nmbs>>hdec+vdec);
+ mcu_ncfrags=mcu_nmbs<<3-(hdec+vdec);
+ mcu_nfrags=4*mcu_nmbs+mcu_ncfrags;
_enc->mcu_skip_ssd=(unsigned *)_ogg_malloc(
mcu_nfrags*sizeof(*_enc->mcu_skip_ssd));
+ _enc->mcu_rd_scale=(ogg_uint16_t *)_ogg_malloc(
+ (mcu_ncfrags>>1)*sizeof(*_enc->mcu_rd_scale));
+ _enc->mcu_rd_iscale=(ogg_uint16_t *)_ogg_malloc(
+ (mcu_ncfrags>>1)*sizeof(*_enc->mcu_rd_iscale));
for(pli=0;pli<3;pli++){
_enc->dct_tokens[pli]=(unsigned char **)oc_malloc_2d(64,
_enc->state.fplanes[pli].nfrags,sizeof(**_enc->dct_tokens));
@@ -1075,34 +1184,22 @@ static int oc_enc_init(oc_enc_ctx *_enc,const th_info *_info){
_enc->state.fplanes[pli].nfrags,sizeof(**_enc->extra_bits));
}
#if defined(OC_COLLECT_METRICS)
+ _enc->frag_sad=_ogg_calloc(_enc->state.nfrags,sizeof(*_enc->frag_sad));
_enc->frag_satd=_ogg_calloc(_enc->state.nfrags,sizeof(*_enc->frag_satd));
_enc->frag_ssd=_ogg_calloc(_enc->state.nfrags,sizeof(*_enc->frag_ssd));
#endif
-#if defined(OC_X86_ASM)
- oc_enc_vtable_init_x86(_enc);
-#else
- oc_enc_vtable_init_c(_enc);
-#endif
+ _enc->enquant_table_data=(unsigned char *)_ogg_malloc(
+ (64+3)*3*2*_enc->opt_data.enquant_table_size
+ +_enc->opt_data.enquant_table_alignment-1);
_enc->keyframe_frequency_force=1<<_enc->state.info.keyframe_granule_shift;
_enc->state.qis[0]=_enc->state.info.quality;
_enc->state.nqis=1;
+ _enc->activity_avg=90<<12;
+ _enc->luma_avg=128<<8;
oc_rc_state_init(&_enc->rc,_enc);
oggpackB_writeinit(&_enc->opb);
- if(_enc->mb_info==NULL||_enc->frag_dc==NULL||_enc->coded_mbis==NULL||
- _enc->mcu_skip_ssd==NULL||_enc->dct_tokens[0]==NULL||
- _enc->dct_tokens[1]==NULL||_enc->dct_tokens[2]==NULL||
- _enc->extra_bits[0]==NULL||_enc->extra_bits[1]==NULL||
- _enc->extra_bits[2]==NULL
-#if defined(OC_COLLECT_METRICS)
- ||_enc->frag_satd==NULL||_enc->frag_ssd==NULL
-#endif
- ){
- oc_enc_clear(_enc);
- return TH_EFAULT;
- }
- oc_mode_scheme_chooser_init(&_enc->chooser);
- oc_enc_mb_info_init(_enc);
- memset(_enc->huff_idxs,0,sizeof(_enc->huff_idxs));
+ memcpy(_enc->huff_codes,TH_VP31_HUFF_CODES,sizeof(_enc->huff_codes));
+ memset(_enc->qinfo.qi_ranges,0,sizeof(_enc->qinfo.qi_ranges));
/*Reset the packet-out state machine.*/
_enc->packet_state=OC_PACKET_INFO_HDR;
_enc->dup_count=0;
@@ -1114,26 +1211,45 @@ static int oc_enc_init(oc_enc_ctx *_enc,const th_info *_info){
_enc->vp3_compatible=0;
/*No INTER frames coded yet.*/
_enc->coded_inter_frame=0;
- memcpy(_enc->huff_codes,TH_VP31_HUFF_CODES,sizeof(_enc->huff_codes));
- oc_enc_set_quant_params(_enc,NULL);
+ if(_enc->mb_info==NULL||_enc->frag_dc==NULL||_enc->coded_mbis==NULL
+ ||_enc->mcu_skip_ssd==NULL||_enc->dct_tokens[0]==NULL
+ ||_enc->dct_tokens[1]==NULL||_enc->dct_tokens[2]==NULL
+ ||_enc->extra_bits[0]==NULL||_enc->extra_bits[1]==NULL
+ ||_enc->extra_bits[2]==NULL
+#if defined(OC_COLLECT_METRICS)
+ ||_enc->frag_sad==NULL||_enc->frag_satd==NULL||_enc->frag_ssd==NULL
+#endif
+ ||oc_enc_set_quant_params(_enc,NULL)<0){
+ oc_enc_clear(_enc);
+ return TH_EFAULT;
+ }
+ oc_mode_scheme_chooser_init(&_enc->chooser);
+ oc_enc_mb_info_init(_enc);
+ memset(_enc->huff_idxs,0,sizeof(_enc->huff_idxs));
return 0;
}
static void oc_enc_clear(oc_enc_ctx *_enc){
int pli;
oc_rc_state_clear(&_enc->rc);
-#if defined(OC_COLLECT_METRICS)
- oc_enc_mode_metrics_dump(_enc);
-#endif
oggpackB_writeclear(&_enc->opb);
+ oc_quant_params_clear(&_enc->qinfo);
+ _ogg_free(_enc->enquant_table_data);
#if defined(OC_COLLECT_METRICS)
+ /*Save the collected metrics from this run.
+ Use tools/process_modedec_stats to actually generate modedec.h from the
+ resulting file.*/
+ oc_mode_metrics_dump();
_ogg_free(_enc->frag_ssd);
_ogg_free(_enc->frag_satd);
+ _ogg_free(_enc->frag_sad);
#endif
for(pli=3;pli-->0;){
oc_free_2d(_enc->extra_bits[pli]);
oc_free_2d(_enc->dct_tokens[pli]);
}
+ _ogg_free(_enc->mcu_rd_iscale);
+ _ogg_free(_enc->mcu_rd_scale);
_ogg_free(_enc->mcu_skip_ssd);
_ogg_free(_enc->coded_mbis);
_ogg_free(_enc->frag_dc);
@@ -1145,10 +1261,14 @@ static void oc_enc_drop_frame(th_enc_ctx *_enc){
/*Use the previous frame's reconstruction.*/
_enc->state.ref_frame_idx[OC_FRAME_SELF]=
_enc->state.ref_frame_idx[OC_FRAME_PREV];
+ _enc->state.ref_frame_data[OC_FRAME_SELF]=
+ _enc->state.ref_frame_data[OC_FRAME_PREV];
/*Flag motion vector analysis about the frame drop.*/
_enc->prevframe_dropped=1;
/*Zero the packet.*/
oggpackB_reset(&_enc->opb);
+ /*Emit an inter frame with no coded blocks in VP3-compatibility mode.*/
+ if(_enc->vp3_compatible)oc_enc_drop_frame_pack(_enc);
}
static void oc_enc_compress_keyframe(oc_enc_ctx *_enc,int _recode){
@@ -1222,9 +1342,9 @@ static void oc_enc_set_granpos(oc_enc_ctx *_enc){
th_enc_ctx *th_encode_alloc(const th_info *_info){
oc_enc_ctx *enc;
if(_info==NULL)return NULL;
- enc=_ogg_malloc(sizeof(*enc));
+ enc=oc_aligned_malloc(sizeof(*enc),16);
if(enc==NULL||oc_enc_init(enc,_info)<0){
- _ogg_free(enc);
+ oc_aligned_free(enc);
return NULL;
}
return enc;
@@ -1233,7 +1353,7 @@ th_enc_ctx *th_encode_alloc(const th_info *_info){
void th_encode_free(th_enc_ctx *_enc){
if(_enc!=NULL){
oc_enc_clear(_enc);
- _ogg_free(_enc);
+ oc_aligned_free(_enc);
}
}
@@ -1272,12 +1392,17 @@ int th_encode_ctl(th_enc_ctx *_enc,int _req,void *_buf,size_t _buf_sz){
}break;
case TH_ENCCTL_SET_VP3_COMPATIBLE:{
int vp3_compatible;
+ int ret;
if(_enc==NULL||_buf==NULL)return TH_EFAULT;
if(_buf_sz!=sizeof(vp3_compatible))return TH_EINVAL;
+ /*Try this before we change anything else, because it can fail.*/
+ ret=oc_enc_set_quant_params(_enc,&TH_VP31_QUANT_INFO);
+ /*If we can't allocate enough memory, don't change any of the state.*/
+ if(ret==TH_EFAULT)return ret;
vp3_compatible=*(int *)_buf;
_enc->vp3_compatible=vp3_compatible;
if(oc_enc_set_huffman_codes(_enc,TH_VP31_HUFF_CODES)<0)vp3_compatible=0;
- if(oc_enc_set_quant_params(_enc,&TH_VP31_QUANT_INFO)<0)vp3_compatible=0;
+ if(ret<0)vp3_compatible=0;
if(_enc->state.info.pixel_fmt!=TH_PF_420||
_enc->state.info.pic_width<_enc->state.info.frame_width||
_enc->state.info.pic_height<_enc->state.info.frame_height||
@@ -1386,6 +1511,44 @@ int th_encode_ctl(th_enc_ctx *_enc,int _req,void *_buf,size_t _buf_sz){
}
return oc_enc_rc_2pass_in(_enc,_buf,_buf_sz);
}break;
+ case TH_ENCCTL_SET_COMPAT_CONFIG:{
+ unsigned char buf[7];
+ oc_pack_buf opb;
+ th_quant_info qinfo;
+ th_huff_code huff_codes[TH_NHUFFMAN_TABLES][TH_NDCT_TOKENS];
+ int ret;
+ int i;
+ if(_enc==NULL||_buf==NULL)return TH_EFAULT;
+ if(_enc->packet_state>OC_PACKET_SETUP_HDR)return TH_EINVAL;
+ oc_pack_readinit(&opb,_buf,_buf_sz);
+ /*Validate the setup packet header.*/
+ for(i=0;i<7;i++)buf[i]=(unsigned char)oc_pack_read(&opb,8);
+ if(!(buf[0]&0x80)||memcmp(buf+1,"theora",6)!=0)return TH_ENOTFORMAT;
+ if(buf[0]!=0x82)return TH_EBADHEADER;
+ /*Reads its contents.*/
+ ret=oc_quant_params_unpack(&opb,&qinfo);
+ if(ret<0){
+ oc_quant_params_clear(&qinfo);
+ return ret;
+ }
+ ret=oc_huff_codes_unpack(&opb,huff_codes);
+ if(ret<0){
+ oc_quant_params_clear(&qinfo);
+ return ret;
+ }
+ /*Install the new state.*/
+ oc_quant_params_clear(&_enc->qinfo);
+ memcpy(&_enc->qinfo,&qinfo,sizeof(qinfo));
+ oc_enc_quant_params_updated(_enc,&qinfo);
+ memcpy(_enc->huff_codes,huff_codes,sizeof(_enc->huff_codes));
+ return 0;
+ }
+#if defined(OC_COLLECT_METRICS)
+ case TH_ENCCTL_SET_METRICS_FILE:{
+ OC_MODE_METRICS_FILENAME=(const char *)_buf;
+ return 0;
+ }
+#endif
default:return TH_EIMPL;
}
}
@@ -1477,6 +1640,12 @@ static void oc_img_plane_copy_pad(th_img_plane *_dst,th_img_plane *_src,
int th_encode_ycbcr_in(th_enc_ctx *_enc,th_ycbcr_buffer _img){
th_ycbcr_buffer img;
+ int frame_width;
+ int frame_height;
+ int pic_width;
+ int pic_height;
+ int pic_x;
+ int pic_y;
int cframe_width;
int cframe_height;
int cpic_width;
@@ -1492,53 +1661,94 @@ int th_encode_ycbcr_in(th_enc_ctx *_enc,th_ycbcr_buffer _img){
if(_enc==NULL||_img==NULL)return TH_EFAULT;
if(_enc->packet_state==OC_PACKET_DONE)return TH_EINVAL;
if(_enc->rc.twopass&&_enc->rc.twopass_buffer_bytes==0)return TH_EINVAL;
- if((ogg_uint32_t)_img[0].width!=_enc->state.info.frame_width||
- (ogg_uint32_t)_img[0].height!=_enc->state.info.frame_height){
- return TH_EINVAL;
- }
hdec=!(_enc->state.info.pixel_fmt&1);
vdec=!(_enc->state.info.pixel_fmt&2);
- cframe_width=_enc->state.info.frame_width>>hdec;
- cframe_height=_enc->state.info.frame_height>>vdec;
- if(_img[1].width!=cframe_width||_img[2].width!=cframe_width||
- _img[1].height!=cframe_height||_img[2].height!=cframe_height){
- return TH_EINVAL;
- }
- /*Step 2: Copy the input to our internal buffer.
- This lets us add padding, if necessary, so we don't have to worry about
- dereferencing possibly invalid addresses, and allows us to use the same
- strides and fragment offsets for both the input frame and the reference
- frames.*/
+ frame_width=_enc->state.info.frame_width;
+ frame_height=_enc->state.info.frame_height;
+ pic_x=_enc->state.info.pic_x;
+ pic_y=_enc->state.info.pic_y;
+ pic_width=_enc->state.info.pic_width;
+ pic_height=_enc->state.info.pic_height;
+ cframe_width=frame_width>>hdec;
+ cframe_height=frame_height>>vdec;
+ cpic_x=pic_x>>hdec;
+ cpic_y=pic_y>>vdec;
+ cpic_width=(pic_x+pic_width+hdec>>hdec)-cpic_x;
+ cpic_height=(pic_y+pic_height+vdec>>vdec)-cpic_y;
/*Flip the input buffer upside down.*/
oc_ycbcr_buffer_flip(img,_img);
- oc_img_plane_copy_pad(_enc->state.ref_frame_bufs[OC_FRAME_IO]+0,img+0,
- _enc->state.info.pic_x,_enc->state.info.pic_y,
- _enc->state.info.pic_width,_enc->state.info.pic_height);
- cpic_x=_enc->state.info.pic_x>>hdec;
- cpic_y=_enc->state.info.pic_y>>vdec;
- cpic_width=(_enc->state.info.pic_x+_enc->state.info.pic_width+hdec>>hdec)
- -cpic_x;
- cpic_height=(_enc->state.info.pic_y+_enc->state.info.pic_height+vdec>>vdec)
- -cpic_y;
- for(pli=1;pli<3;pli++){
- oc_img_plane_copy_pad(_enc->state.ref_frame_bufs[OC_FRAME_IO]+pli,img+pli,
- cpic_x,cpic_y,cpic_width,cpic_height);
+ if(img[0].width!=frame_width||img[0].height!=frame_height||
+ img[1].width!=cframe_width||img[2].width!=cframe_width||
+ img[1].height!=cframe_height||img[2].height!=cframe_height){
+ /*The buffer does not match the frame size.
+ Check to see if it matches the picture size.*/
+ if(img[0].width!=pic_width||img[0].height!=pic_height||
+ img[1].width!=cpic_width||img[2].width!=cpic_width||
+ img[1].height!=cpic_height||img[2].height!=cpic_height){
+ /*It doesn't; we don't know how to handle it.*/
+ return TH_EINVAL;
+ }
+ /*Adjust the pointers to address a full frame.
+ We still only use the picture region, however.*/
+ img[0].data-=pic_y*(ptrdiff_t)img[0].stride+pic_x;
+ img[1].data-=cpic_y*(ptrdiff_t)img[1].stride+cpic_x;
+ img[2].data-=cpic_y*(ptrdiff_t)img[2].stride+cpic_x;
}
- /*Step 3: Update the buffer state.*/
+ /*Step 2: Update the buffer state.*/
if(_enc->state.ref_frame_idx[OC_FRAME_SELF]>=0){
_enc->state.ref_frame_idx[OC_FRAME_PREV]=
_enc->state.ref_frame_idx[OC_FRAME_SELF];
+ _enc->state.ref_frame_data[OC_FRAME_PREV]=
+ _enc->state.ref_frame_data[OC_FRAME_SELF];
if(_enc->state.frame_type==OC_INTRA_FRAME){
/*The new frame becomes both the previous and gold reference frames.*/
_enc->state.keyframe_num=_enc->state.curframe_num;
_enc->state.ref_frame_idx[OC_FRAME_GOLD]=
_enc->state.ref_frame_idx[OC_FRAME_SELF];
+ _enc->state.ref_frame_data[OC_FRAME_GOLD]=
+ _enc->state.ref_frame_data[OC_FRAME_SELF];
+ }
+ }
+ if(_enc->state.ref_frame_idx[OC_FRAME_IO]>=0&&_enc->prevframe_dropped==0){
+ _enc->state.ref_frame_idx[OC_FRAME_PREV_ORIG]=
+ _enc->state.ref_frame_idx[OC_FRAME_IO];
+ _enc->state.ref_frame_data[OC_FRAME_PREV_ORIG]=
+ _enc->state.ref_frame_data[OC_FRAME_IO];
+ if(_enc->state.frame_type==OC_INTRA_FRAME){
+ /*The new input frame becomes both the previous and gold
+ original-reference frames.*/
+ _enc->state.ref_frame_idx[OC_FRAME_GOLD_ORIG]=
+ _enc->state.ref_frame_idx[OC_FRAME_IO];
+ _enc->state.ref_frame_data[OC_FRAME_GOLD_ORIG]=
+ _enc->state.ref_frame_data[OC_FRAME_IO];
}
}
+ /*Select a free buffer to use for the incoming frame*/
+ for(refi=3;refi==_enc->state.ref_frame_idx[OC_FRAME_GOLD_ORIG]||
+ refi==_enc->state.ref_frame_idx[OC_FRAME_PREV_ORIG];refi++);
+ _enc->state.ref_frame_idx[OC_FRAME_IO]=refi;
+ _enc->state.ref_frame_data[OC_FRAME_IO]=
+ _enc->state.ref_frame_bufs[refi][0].data;
+ /*Step 3: Copy the input to our internal buffer.
+ This lets us add padding, so we don't have to worry about dereferencing
+ possibly invalid addresses, and allows us to use the same strides and
+ fragment offsets for both the input frame and the reference frames.*/
+ oc_img_plane_copy_pad(_enc->state.ref_frame_bufs[refi]+0,img+0,
+ pic_x,pic_y,pic_width,pic_height);
+ oc_state_borders_fill_rows(&_enc->state,refi,0,0,frame_height);
+ oc_state_borders_fill_caps(&_enc->state,refi,0);
+ for(pli=1;pli<3;pli++){
+ oc_img_plane_copy_pad(_enc->state.ref_frame_bufs[refi]+pli,img+pli,
+ cpic_x,cpic_y,cpic_width,cpic_height);
+ oc_state_borders_fill_rows(&_enc->state,refi,pli,0,cframe_height);
+ oc_state_borders_fill_caps(&_enc->state,refi,pli);
+ }
/*Select a free buffer to use for the reconstructed version of this frame.*/
for(refi=0;refi==_enc->state.ref_frame_idx[OC_FRAME_GOLD]||
refi==_enc->state.ref_frame_idx[OC_FRAME_PREV];refi++);
_enc->state.ref_frame_idx[OC_FRAME_SELF]=refi;
+ _enc->state.ref_frame_data[OC_FRAME_SELF]=
+ _enc->state.ref_frame_bufs[refi][0].data;
_enc->state.curframe_num+=_enc->prev_dup_count+1;
/*Step 4: Compress the frame.*/
/*Start with a keyframe, and don't allow the generation of invalid files that
@@ -1575,11 +1785,11 @@ int th_encode_ycbcr_in(th_enc_ctx *_enc,th_ycbcr_buffer _img){
}
int th_encode_packetout(th_enc_ctx *_enc,int _last_p,ogg_packet *_op){
+ unsigned char *packet;
if(_enc==NULL||_op==NULL)return TH_EFAULT;
if(_enc->packet_state==OC_PACKET_READY){
_enc->packet_state=OC_PACKET_EMPTY;
if(_enc->rc.twopass!=1){
- unsigned char *packet;
packet=oggpackB_get_buffer(&_enc->opb);
/*If there's no packet, malloc failed while writing; it's lost forever.*/
if(packet==NULL)return TH_EFAULT;
@@ -1595,8 +1805,22 @@ int th_encode_packetout(th_enc_ctx *_enc,int _last_p,ogg_packet *_op){
else if(_enc->packet_state==OC_PACKET_EMPTY){
if(_enc->nqueued_dups>0){
_enc->nqueued_dups--;
- _op->packet=NULL;
- _op->bytes=0;
+ /*Emit an inter frame with no coded blocks in VP3-compatibility mode.*/
+ if(_enc->vp3_compatible){
+ oggpackB_reset(&_enc->opb);
+ oc_enc_drop_frame_pack(_enc);
+ packet=oggpackB_get_buffer(&_enc->opb);
+ /*If there's no packet, malloc failed while writing; it's lost
+ forever.*/
+ if(packet==NULL)return TH_EFAULT;
+ _op->packet=packet;
+ _op->bytes=oggpackB_bytes(&_enc->opb);
+ }
+ /*Otherwise emit a 0-byte packet.*/
+ else{
+ _op->packet=NULL;
+ _op->bytes=0;
+ }
}
else{
if(_last_p)_enc->packet_state=OC_PACKET_DONE;
diff --git a/thirdparty/libtheora/encoder_disabled.c b/thirdparty/libtheora/encoder_disabled.c
index 0cbf6645ac..ba6d995505 100644
--- a/thirdparty/libtheora/encoder_disabled.c
+++ b/thirdparty/libtheora/encoder_disabled.c
@@ -11,12 +11,15 @@
********************************************************************
function:
- last mod: $Id: encoder_disabled.c 16503 2009-08-22 18:14:02Z giles $
+ last mod: $Id$
********************************************************************/
#include "apiwrapper.h"
#include "encint.h"
+const th_quant_info TH_VP31_QUANT_INFO = {};
+const th_huff_code TH_VP31_HUFF_CODES[TH_NHUFFMAN_TABLES][TH_NDCT_TOKENS];
+
th_enc_ctx *th_encode_alloc(const th_info *_info){
return NULL;
}
diff --git a/thirdparty/libtheora/enquant.c b/thirdparty/libtheora/enquant.c
index 3372fed221..8fd220edd7 100644
--- a/thirdparty/libtheora/enquant.c
+++ b/thirdparty/libtheora/enquant.c
@@ -11,7 +11,7 @@
********************************************************************
function:
- last mod: $Id: enquant.c 16503 2009-08-22 18:14:02Z giles $
+ last mod: $Id$
********************************************************************/
#include <stdlib.h>
@@ -20,6 +20,69 @@
+int oc_quant_params_clone(th_quant_info *_dst,const th_quant_info *_src){
+ int i;
+ memcpy(_dst,_src,sizeof(*_dst));
+ memset(_dst->qi_ranges,0,sizeof(_dst->qi_ranges));
+ for(i=0;i<6;i++){
+ int nranges;
+ int qti;
+ int pli;
+ int qtj;
+ int plj;
+ int pdup;
+ int qdup;
+ qti=i/3;
+ pli=i%3;
+ qtj=(i-1)/3;
+ plj=(i-1)%3;
+ nranges=_src->qi_ranges[qti][pli].nranges;
+ /*Check for those duplicates that can be cleanly handled by
+ oc_quant_params_clear().*/
+ pdup=i>0&&nranges<=_src->qi_ranges[qtj][plj].nranges;
+ qdup=qti>0&&nranges<=_src->qi_ranges[0][pli].nranges;
+ _dst->qi_ranges[qti][pli].nranges=nranges;
+ if(pdup&&_src->qi_ranges[qti][pli].sizes==_src->qi_ranges[qtj][plj].sizes){
+ _dst->qi_ranges[qti][pli].sizes=_dst->qi_ranges[qtj][plj].sizes;
+ }
+ else if(qdup&&_src->qi_ranges[1][pli].sizes==_src->qi_ranges[0][pli].sizes){
+ _dst->qi_ranges[1][pli].sizes=_dst->qi_ranges[0][pli].sizes;
+ }
+ else{
+ int *sizes;
+ sizes=(int *)_ogg_malloc(nranges*sizeof(*sizes));
+ /*Note: The caller is responsible for cleaning up any partially
+ constructed qinfo.*/
+ if(sizes==NULL)return TH_EFAULT;
+ memcpy(sizes,_src->qi_ranges[qti][pli].sizes,nranges*sizeof(*sizes));
+ _dst->qi_ranges[qti][pli].sizes=sizes;
+ }
+ if(pdup&&_src->qi_ranges[qti][pli].base_matrices==
+ _src->qi_ranges[qtj][plj].base_matrices){
+ _dst->qi_ranges[qti][pli].base_matrices=
+ _dst->qi_ranges[qtj][plj].base_matrices;
+ }
+ else if(qdup&&_src->qi_ranges[1][pli].base_matrices==
+ _src->qi_ranges[0][pli].base_matrices){
+ _dst->qi_ranges[1][pli].base_matrices=
+ _dst->qi_ranges[0][pli].base_matrices;
+ }
+ else{
+ th_quant_base *base_matrices;
+ base_matrices=(th_quant_base *)_ogg_malloc(
+ (nranges+1)*sizeof(*base_matrices));
+ /*Note: The caller is responsible for cleaning up any partially
+ constructed qinfo.*/
+ if(base_matrices==NULL)return TH_EFAULT;
+ memcpy(base_matrices,_src->qi_ranges[qti][pli].base_matrices,
+ (nranges+1)*sizeof(*base_matrices));
+ _dst->qi_ranges[qti][pli].base_matrices=
+ (const th_quant_base *)base_matrices;
+ }
+ }
+ return 0;
+}
+
void oc_quant_params_pack(oggpack_buffer *_opb,const th_quant_info *_qinfo){
const th_quant_ranges *qranges;
const th_quant_base *base_mats[2*3*64];
@@ -119,7 +182,7 @@ void oc_quant_params_pack(oggpack_buffer *_opb,const th_quant_info *_qinfo){
}
}
-static void oc_iquant_init(oc_iquant *_this,ogg_uint16_t _d){
+void oc_iquant_init(oc_iquant *_this,ogg_uint16_t _d){
ogg_uint32_t t;
int l;
_d<<=1;
@@ -129,48 +192,61 @@ static void oc_iquant_init(oc_iquant *_this,ogg_uint16_t _d){
_this->l=l;
}
-/*See comments at oc_dequant_tables_init() for how the quantization tables'
- storage should be initialized.*/
-void oc_enquant_tables_init(ogg_uint16_t *_dequant[64][3][2],
- oc_iquant *_enquant[64][3][2],const th_quant_info *_qinfo){
- int qi;
+void oc_enc_enquant_table_init_c(void *_enquant,
+ const ogg_uint16_t _dequant[64]){
+ oc_iquant *enquant;
+ int zzi;
+ /*In the original VP3.2 code, the rounding offset and the size of the
+ dead zone around 0 were controlled by a "sharpness" parameter.
+ We now R-D optimize the tokens for each block after quantization,
+ so the rounding offset should always be 1/2, and an explicit dead
+ zone is unnecessary.
+ Hence, all of that VP3.2 code is gone from here, and the remaining
+ floating point code has been implemented as equivalent integer
+ code with exact precision.*/
+ enquant=(oc_iquant *)_enquant;
+ for(zzi=0;zzi<64;zzi++)oc_iquant_init(enquant+zzi,_dequant[zzi]);
+}
+
+void oc_enc_enquant_table_fixup_c(void *_enquant[3][3][2],int _nqis){
int pli;
+ int qii;
int qti;
- /*Initialize the dequantization tables first.*/
- oc_dequant_tables_init(_dequant,NULL,_qinfo);
- /*Derive the quantization tables directly from the dequantization tables.*/
- for(qi=0;qi<64;qi++)for(qti=0;qti<2;qti++)for(pli=0;pli<3;pli++){
- int zzi;
- int plj;
- int qtj;
- int dupe;
- dupe=0;
- for(qtj=0;qtj<=qti;qtj++){
- for(plj=0;plj<(qtj<qti?3:pli);plj++){
- if(_dequant[qi][pli][qti]==_dequant[qi][plj][qtj]){
- dupe=1;
- break;
- }
- }
- if(dupe)break;
- }
- if(dupe){
- _enquant[qi][pli][qti]=_enquant[qi][plj][qtj];
- continue;
- }
- /*In the original VP3.2 code, the rounding offset and the size of the
- dead zone around 0 were controlled by a "sharpness" parameter.
- We now R-D optimize the tokens for each block after quantization,
- so the rounding offset should always be 1/2, and an explicit dead
- zone is unnecessary.
- Hence, all of that VP3.2 code is gone from here, and the remaining
- floating point code has been implemented as equivalent integer
- code with exact precision.*/
- for(zzi=0;zzi<64;zzi++){
- oc_iquant_init(_enquant[qi][pli][qti]+zzi,
- _dequant[qi][pli][qti][zzi]);
+ for(pli=0;pli<3;pli++)for(qii=1;qii<_nqis;qii++)for(qti=0;qti<2;qti++){
+ *((oc_iquant *)_enquant[pli][qii][qti])=
+ *((oc_iquant *)_enquant[pli][0][qti]);
+ }
+}
+
+int oc_enc_quantize_c(ogg_int16_t _qdct[64],const ogg_int16_t _dct[64],
+ const ogg_uint16_t _dequant[64],const void *_enquant){
+ const oc_iquant *enquant;
+ int nonzero;
+ int zzi;
+ int val;
+ int d;
+ int s;
+ enquant=(const oc_iquant *)_enquant;
+ nonzero=0;
+ for(zzi=0;zzi<64;zzi++){
+ val=_dct[zzi];
+ d=_dequant[zzi];
+ val=val<<1;
+ if(abs(val)>=d){
+ s=OC_SIGNMASK(val);
+ /*The bias added here rounds ties away from zero, since token
+ optimization can only decrease the magnitude of the quantized
+ value.*/
+ val+=d+s^s;
+ /*Note the arithmetic right shift is not guaranteed by ANSI C.
+ Hopefully no one still uses ones-complement architectures.*/
+ val=((enquant[zzi].m*(ogg_int32_t)val>>16)+val>>enquant[zzi].l)-s;
+ _qdct[zzi]=(ogg_int16_t)val;
+ nonzero=zzi;
}
+ else _qdct[zzi]=0;
}
+ return nonzero;
}
@@ -226,7 +302,7 @@ static const ogg_uint16_t OC_RPSD[2][64]={
relative to the total, scaled by 2**16, for each pixel format.
These values were measured after motion-compensated prediction, before
quantization, over a large set of test video encoded at all possible rates.
- TODO: These values are only from INTER frames; it should be re-measured for
+ TODO: These values are only from INTER frames; they should be re-measured for
INTRA frames.*/
static const ogg_uint16_t OC_PCD[4][3]={
{59926, 3038, 2572},
@@ -236,38 +312,58 @@ static const ogg_uint16_t OC_PCD[4][3]={
};
-/*Compute an "average" quantizer for each qi level.
- We do one for INTER and one for INTRA, since their behavior is very
- different, but average across chroma channels.
+/*Compute "average" quantizers for each qi level to use for rate control.
+ We do one for each color channel, as well as an average across color
+ channels, separately for INTER and INTRA, since their behavior is very
+ different.
The basic approach is to compute a harmonic average of the squared quantizer,
weighted by the expected squared magnitude of the DCT coefficients.
Under the (not quite true) assumption that DCT coefficients are
Laplacian-distributed, this preserves the product Q*lambda, where
lambda=sqrt(2/sigma**2) is the Laplacian distribution parameter (not to be
confused with the lambda used in R-D optimization throughout most of the
- rest of the code).
- The value Q*lambda completely determines the entropy of the coefficients.*/
+ rest of the code), when the distributions from multiple coefficients are
+ pooled.
+ The value Q*lambda completely determines the entropy of coefficients drawn
+ from a Laplacian distribution, and thus the expected bitrate.*/
void oc_enquant_qavg_init(ogg_int64_t _log_qavg[2][64],
+ ogg_int16_t _log_plq[64][3][2],ogg_uint16_t _chroma_rd_scale[2][64][2],
ogg_uint16_t *_dequant[64][3][2],int _pixel_fmt){
int qi;
int pli;
int qti;
int ci;
for(qti=0;qti<2;qti++)for(qi=0;qi<64;qi++){
- ogg_int64_t q2;
+ ogg_int64_t q2;
+ ogg_uint32_t qp[3];
+ ogg_uint32_t cqp;
+ ogg_uint32_t d;
q2=0;
for(pli=0;pli<3;pli++){
- ogg_uint32_t qp;
- qp=0;
+ qp[pli]=0;
for(ci=0;ci<64;ci++){
unsigned rq;
unsigned qd;
qd=_dequant[qi][pli][qti][OC_IZIG_ZAG[ci]];
rq=(OC_RPSD[qti][ci]+(qd>>1))/qd;
- qp+=rq*(ogg_uint32_t)rq;
+ qp[pli]+=rq*(ogg_uint32_t)rq;
}
- q2+=OC_PCD[_pixel_fmt][pli]*(ogg_int64_t)qp;
+ q2+=OC_PCD[_pixel_fmt][pli]*(ogg_int64_t)qp[pli];
+ /*plq=1.0/sqrt(qp)*/
+ _log_plq[qi][pli][qti]=
+ (ogg_int16_t)(OC_Q10(32)-oc_blog32_q10(qp[pli])>>1);
}
+ d=OC_PCD[_pixel_fmt][1]+OC_PCD[_pixel_fmt][2];
+ cqp=(ogg_uint32_t)((OC_PCD[_pixel_fmt][1]*(ogg_int64_t)qp[1]+
+ OC_PCD[_pixel_fmt][2]*(ogg_int64_t)qp[2]+(d>>1))/d);
+ /*chroma_rd_scale=clamp(0.25,cqp/qp[0],4)*/
+ d=OC_MAXI(qp[0]+(1<<OC_RD_SCALE_BITS-1)>>OC_RD_SCALE_BITS,1);
+ d=OC_CLAMPI(1<<OC_RD_SCALE_BITS-2,(cqp+(d>>1))/d,4<<OC_RD_SCALE_BITS);
+ _chroma_rd_scale[qti][qi][0]=(ogg_int16_t)d;
+ /*chroma_rd_iscale=clamp(0.25,qp[0]/cqp,4)*/
+ d=OC_MAXI(OC_RD_ISCALE(cqp,1),1);
+ d=OC_CLAMPI(1<<OC_RD_ISCALE_BITS-2,(qp[0]+(d>>1))/d,4<<OC_RD_ISCALE_BITS);
+ _chroma_rd_scale[qti][qi][1]=(ogg_int16_t)d;
/*qavg=1.0/sqrt(q2).*/
_log_qavg[qti][qi]=OC_Q57(48)-oc_blog64(q2)>>1;
}
diff --git a/thirdparty/libtheora/enquant.h b/thirdparty/libtheora/enquant.h
index d62df10d1a..e5f78144cc 100644
--- a/thirdparty/libtheora/enquant.h
+++ b/thirdparty/libtheora/enquant.h
@@ -14,14 +14,13 @@ struct oc_iquant{
ogg_int16_t l;
};
-typedef oc_iquant oc_iquant_table[64];
-
+int oc_quant_params_clone(th_quant_info *_dst,const th_quant_info *_src);
void oc_quant_params_pack(oggpack_buffer *_opb,const th_quant_info *_qinfo);
-void oc_enquant_tables_init(ogg_uint16_t *_dequant[64][3][2],
- oc_iquant *_enquant[64][3][2],const th_quant_info *_qinfo);
+void oc_iquant_init(oc_iquant *_this,ogg_uint16_t _d);
void oc_enquant_qavg_init(ogg_int64_t _log_qavg[2][64],
+ ogg_int16_t _log_plq[64][3][2],ogg_uint16_t _pl_rd_scale[2][64][2],
ogg_uint16_t *_dequant[64][3][2],int _pixel_fmt);
#endif
diff --git a/thirdparty/libtheora/fdct.c b/thirdparty/libtheora/fdct.c
index dc3a66f245..9c2f8b0446 100644
--- a/thirdparty/libtheora/fdct.c
+++ b/thirdparty/libtheora/fdct.c
@@ -11,7 +11,7 @@
********************************************************************
function:
- last mod: $Id: fdct.c 16503 2009-08-22 18:14:02Z giles $
+ last mod: $Id$
********************************************************************/
#include "encint.h"
@@ -120,11 +120,6 @@ static void oc_fdct8(ogg_int16_t _y[8],const ogg_int16_t *_x){
_y[7]=v;
}
-void oc_enc_fdct8x8(const oc_enc_ctx *_enc,ogg_int16_t _y[64],
- const ogg_int16_t _x[64]){
- (*_enc->opt_vtable.fdct8x8)(_y,_x);
-}
-
/*Performs a forward 8x8 Type-II DCT transform.
The output is scaled by a factor of 4 relative to the orthonormal version
of the transform.
@@ -152,7 +147,7 @@ void oc_enc_fdct8x8_c(ogg_int16_t _y[64],const ogg_int16_t _x[64]){
/*Round the result back to the external working precision (which is still
scaled by four relative to the orthogonal result).
TODO: We should just update the external working precision.*/
- for(i=0;i<64;i++)_y[i]=w[i]+2>>2;
+ for(i=0;i<64;i++)_y[i]=w[OC_FZIG_ZAG[i]]+2>>2;
}
diff --git a/thirdparty/libtheora/fragment.c b/thirdparty/libtheora/fragment.c
index 15372e9d9f..14c38be507 100644
--- a/thirdparty/libtheora/fragment.c
+++ b/thirdparty/libtheora/fragment.c
@@ -11,17 +11,12 @@
********************************************************************
function:
- last mod: $Id: fragment.c 16503 2009-08-22 18:14:02Z giles $
+ last mod: $Id$
********************************************************************/
#include <string.h>
#include "internal.h"
-void oc_frag_copy(const oc_theora_state *_state,unsigned char *_dst,
- const unsigned char *_src,int _ystride){
- (*_state->opt_vtable.frag_copy)(_dst,_src,_ystride);
-}
-
void oc_frag_copy_c(unsigned char *_dst,const unsigned char *_src,int _ystride){
int i;
for(i=8;i-->0;){
@@ -31,9 +26,24 @@ void oc_frag_copy_c(unsigned char *_dst,const unsigned char *_src,int _ystride){
}
}
-void oc_frag_recon_intra(const oc_theora_state *_state,unsigned char *_dst,
- int _ystride,const ogg_int16_t _residue[64]){
- _state->opt_vtable.frag_recon_intra(_dst,_ystride,_residue);
+/*Copies the fragments specified by the lists of fragment indices from one
+ frame to another.
+ _dst_frame: The reference frame to copy to.
+ _src_frame: The reference frame to copy from.
+ _ystride: The row stride of the reference frames.
+ _fragis: A pointer to a list of fragment indices.
+ _nfragis: The number of fragment indices to copy.
+ _frag_buf_offs: The offsets of fragments in the reference frames.*/
+void oc_frag_copy_list_c(unsigned char *_dst_frame,
+ const unsigned char *_src_frame,int _ystride,
+ const ptrdiff_t *_fragis,ptrdiff_t _nfragis,const ptrdiff_t *_frag_buf_offs){
+ ptrdiff_t fragii;
+ for(fragii=0;fragii<_nfragis;fragii++){
+ ptrdiff_t frag_buf_off;
+ frag_buf_off=_frag_buf_offs[_fragis[fragii]];
+ oc_frag_copy_c(_dst_frame+frag_buf_off,
+ _src_frame+frag_buf_off,_ystride);
+ }
}
void oc_frag_recon_intra_c(unsigned char *_dst,int _ystride,
@@ -46,11 +56,6 @@ void oc_frag_recon_intra_c(unsigned char *_dst,int _ystride,
}
}
-void oc_frag_recon_inter(const oc_theora_state *_state,unsigned char *_dst,
- const unsigned char *_src,int _ystride,const ogg_int16_t _residue[64]){
- _state->opt_vtable.frag_recon_inter(_dst,_src,_ystride,_residue);
-}
-
void oc_frag_recon_inter_c(unsigned char *_dst,
const unsigned char *_src,int _ystride,const ogg_int16_t _residue[64]){
int i;
@@ -62,12 +67,6 @@ void oc_frag_recon_inter_c(unsigned char *_dst,
}
}
-void oc_frag_recon_inter2(const oc_theora_state *_state,unsigned char *_dst,
- const unsigned char *_src1,const unsigned char *_src2,int _ystride,
- const ogg_int16_t _residue[64]){
- _state->opt_vtable.frag_recon_inter2(_dst,_src1,_src2,_ystride,_residue);
-}
-
void oc_frag_recon_inter2_c(unsigned char *_dst,const unsigned char *_src1,
const unsigned char *_src2,int _ystride,const ogg_int16_t _residue[64]){
int i;
@@ -80,8 +79,4 @@ void oc_frag_recon_inter2_c(unsigned char *_dst,const unsigned char *_src1,
}
}
-void oc_restore_fpu(const oc_theora_state *_state){
- _state->opt_vtable.restore_fpu();
-}
-
void oc_restore_fpu_c(void){}
diff --git a/thirdparty/libtheora/huffdec.c b/thirdparty/libtheora/huffdec.c
index 8cf27f0341..5a83c5f150 100644
--- a/thirdparty/libtheora/huffdec.c
+++ b/thirdparty/libtheora/huffdec.c
@@ -11,7 +11,7 @@
********************************************************************
function:
- last mod: $Id: huffdec.c 16503 2009-08-22 18:14:02Z giles $
+ last mod: $Id$
********************************************************************/
@@ -22,14 +22,60 @@
#include "decint.h"
-/*The ANSI offsetof macro is broken on some platforms (e.g., older DECs).*/
-#define _ogg_offsetof(_type,_field)\
- ((size_t)((char *)&((_type *)0)->_field-(char *)0))
-/*The number of internal tokens associated with each of the spec tokens.*/
-static const unsigned char OC_DCT_TOKEN_MAP_ENTRIES[TH_NDCT_TOKENS]={
- 1,1,1,4,8,1,1,8,1,1,1,1,1,2,2,2,2,4,8,2,2,2,4,2,2,2,2,2,8,2,4,8
-};
+/*Instead of storing every branching in the tree, subtrees can be collapsed
+ into one node, with a table of size 1<<nbits pointing directly to its
+ descedents nbits levels down.
+ This allows more than one bit to be read at a time, and avoids following all
+ the intermediate branches with next to no increased code complexity once
+ the collapsed tree has been built.
+ We do _not_ require that a subtree be complete to be collapsed, but instead
+ store duplicate pointers in the table, and record the actual depth of the
+ node below its parent.
+ This tells us the number of bits to advance the stream after reaching it.
+
+ This turns out to be equivalent to the method described in \cite{Hash95},
+ without the requirement that codewords be sorted by length.
+ If the codewords were sorted by length (so-called ``canonical-codes''), they
+ could be decoded much faster via either Lindell and Moffat's approach or
+ Hashemian's Condensed Huffman Code approach, the latter of which has an
+ extremely small memory footprint.
+ We can't use Choueka et al.'s finite state machine approach, which is
+ extremely fast, because we can't allow multiple symbols to be output at a
+ time; the codebook can and does change between symbols.
+ It also has very large memory requirements, which impairs cache coherency.
+
+ We store the tree packed in an array of 16-bit integers (words).
+ Each node consists of a single word, followed consecutively by two or more
+ indices of its children.
+ Let n be the value of this first word.
+ This is the number of bits that need to be read to traverse the node, and
+ must be positive.
+ 1<<n entries follow in the array, each an index to a child node.
+ If the child is positive, then it is the index of another internal node in
+ the table.
+ If the child is negative or zero, then it is a leaf node.
+ These are stored directly in the child pointer to save space, since they only
+ require a single word.
+ If a leaf node would have been encountered before reading n bits, then it is
+ duplicated the necessary number of times in this table.
+ Leaf nodes pack both a token value and their actual depth in the tree.
+ The token in the leaf node is (-leaf&255).
+ The number of bits that need to be consumed to reach the leaf, starting from
+ the current node, is (-leaf>>8).
+
+ @ARTICLE{Hash95,
+ author="Reza Hashemian",
+ title="Memory Efficient and High-Speed Search {Huffman} Coding",
+ journal="{IEEE} Transactions on Communications",
+ volume=43,
+ number=10,
+ pages="2576--2581",
+ month=Oct,
+ year=1995
+ }*/
+
+
/*The map from external spec-defined tokens to internal tokens.
This is constructed so that any extra bits read with the original token value
@@ -99,391 +145,371 @@ static const unsigned char OC_DCT_TOKEN_MAP[TH_NDCT_TOKENS]={
40
};
-/*These three functions are really part of the bitpack.c module, but
- they are only used here.
- Declaring local static versions so they can be inlined saves considerable
- function call overhead.*/
-
-static oc_pb_window oc_pack_refill(oc_pack_buf *_b,int _bits){
- const unsigned char *ptr;
- const unsigned char *stop;
- oc_pb_window window;
- int available;
- window=_b->window;
- available=_b->bits;
- ptr=_b->ptr;
- stop=_b->stop;
- /*This version of _refill() doesn't bother setting eof because we won't
- check for it after we've started decoding DCT tokens.*/
- if(ptr>=stop)available=OC_LOTS_OF_BITS;
- while(available<=OC_PB_WINDOW_SIZE-8){
- available+=8;
- window|=(oc_pb_window)*ptr++<<OC_PB_WINDOW_SIZE-available;
- if(ptr>=stop)available=OC_LOTS_OF_BITS;
- }
- _b->ptr=ptr;
- if(_bits>available)window|=*ptr>>(available&7);
- _b->bits=available;
- return window;
-}
-
-
-/*Read in bits without advancing the bit pointer.
- Here we assume 0<=_bits&&_bits<=32.*/
-static long oc_pack_look(oc_pack_buf *_b,int _bits){
- oc_pb_window window;
- int available;
- long result;
- window=_b->window;
- available=_b->bits;
- if(_bits==0)return 0;
- if(_bits>available)_b->window=window=oc_pack_refill(_b,_bits);
- result=window>>OC_PB_WINDOW_SIZE-_bits;
- return result;
-}
-
-/*Advance the bit pointer.*/
-static void oc_pack_adv(oc_pack_buf *_b,int _bits){
- /*We ignore the special cases for _bits==0 and _bits==32 here, since they are
- never used actually used.
- OC_HUFF_SLUSH (defined below) would have to be at least 27 to actually read
- 32 bits in a single go, and would require a 32 GB lookup table (assuming
- 8 byte pointers, since 4 byte pointers couldn't fit such a table).*/
- _b->window<<=_bits;
- _b->bits-=_bits;
-}
+/*The log base 2 of number of internal tokens associated with each of the spec
+ tokens (i.e., how many of the extra bits are folded into the token value).
+ Increasing the maximum value beyond 3 will enlarge the amount of stack
+ required for tree construction.*/
+static const unsigned char OC_DCT_TOKEN_MAP_LOG_NENTRIES[TH_NDCT_TOKENS]={
+ 0,0,0,2,3,0,0,3,0,0,0,0,0,1,1,1,1,2,3,1,1,1,2,1,1,1,1,1,3,1,2,3
+};
-/*The log_2 of the size of a lookup table is allowed to grow to relative to
- the number of unique nodes it contains.
- E.g., if OC_HUFF_SLUSH is 2, then at most 75% of the space in the tree is
- wasted (each node will have an amortized cost of at most 20 bytes when using
- 4-byte pointers).
+/*The size a lookup table is allowed to grow to relative to the number of
+ unique nodes it contains.
+ E.g., if OC_HUFF_SLUSH is 4, then at most 75% of the space in the tree is
+ wasted (1/4 of the space must be used).
Larger numbers can decode tokens with fewer read operations, while smaller
- numbers may save more space (requiring as little as 8 bytes amortized per
- node, though there will be more nodes).
+ numbers may save more space.
With a sample file:
32233473 read calls are required when no tree collapsing is done (100.0%).
- 19269269 read calls are required when OC_HUFF_SLUSH is 0 (59.8%).
- 11144969 read calls are required when OC_HUFF_SLUSH is 1 (34.6%).
- 10538563 read calls are required when OC_HUFF_SLUSH is 2 (32.7%).
- 10192578 read calls are required when OC_HUFF_SLUSH is 3 (31.6%).
- Since a value of 1 gets us the vast majority of the speed-up with only a
- small amount of wasted memory, this is what we use.*/
-#define OC_HUFF_SLUSH (1)
-
-
-/*Determines the size in bytes of a Huffman tree node that represents a
- subtree of depth _nbits.
- _nbits: The depth of the subtree.
- If this is 0, the node is a leaf node.
- Otherwise 1<<_nbits pointers are allocated for children.
- Return: The number of bytes required to store the node.*/
-static size_t oc_huff_node_size(int _nbits){
- size_t size;
- size=_ogg_offsetof(oc_huff_node,nodes);
- if(_nbits>0)size+=sizeof(oc_huff_node *)*(1<<_nbits);
- return size;
-}
-
-static oc_huff_node *oc_huff_node_init(char **_storage,size_t _size,int _nbits){
- oc_huff_node *ret;
- ret=(oc_huff_node *)*_storage;
- ret->nbits=(unsigned char)_nbits;
- (*_storage)+=_size;
- return ret;
-}
-
-
-/*Determines the size in bytes of a Huffman tree.
- _nbits: The depth of the subtree.
- If this is 0, the node is a leaf node.
- Otherwise storage for 1<<_nbits pointers are added for children.
- Return: The number of bytes required to store the tree.*/
-static size_t oc_huff_tree_size(const oc_huff_node *_node){
- size_t size;
- size=oc_huff_node_size(_node->nbits);
- if(_node->nbits){
- int nchildren;
- int i;
- nchildren=1<<_node->nbits;
- for(i=0;i<nchildren;i+=1<<_node->nbits-_node->nodes[i]->depth){
- size+=oc_huff_tree_size(_node->nodes[i]);
- }
- }
- return size;
-}
-
-
-/*Unpacks a sub-tree from the given buffer.
- _opb: The buffer to unpack from.
- _binodes: The nodes to store the sub-tree in.
- _nbinodes: The number of nodes available for the sub-tree.
- Return: 0 on success, or a negative value on error.*/
-static int oc_huff_tree_unpack(oc_pack_buf *_opb,
- oc_huff_node *_binodes,int _nbinodes){
- oc_huff_node *binode;
- long bits;
- int nused;
- if(_nbinodes<1)return TH_EBADHEADER;
- binode=_binodes;
- nused=0;
- bits=oc_pack_read1(_opb);
- if(oc_pack_bytes_left(_opb)<0)return TH_EBADHEADER;
- /*Read an internal node:*/
- if(!bits){
- int ret;
- nused++;
- binode->nbits=1;
- binode->depth=1;
- binode->nodes[0]=_binodes+nused;
- ret=oc_huff_tree_unpack(_opb,_binodes+nused,_nbinodes-nused);
- if(ret>=0){
- nused+=ret;
- binode->nodes[1]=_binodes+nused;
- ret=oc_huff_tree_unpack(_opb,_binodes+nused,_nbinodes-nused);
- }
- if(ret<0)return ret;
- nused+=ret;
- }
- /*Read a leaf node:*/
- else{
- int ntokens;
- int token;
- int i;
- bits=oc_pack_read(_opb,OC_NDCT_TOKEN_BITS);
+ 19269269 read calls are required when OC_HUFF_SLUSH is 1 (59.8%).
+ 11144969 read calls are required when OC_HUFF_SLUSH is 2 (34.6%).
+ 10538563 read calls are required when OC_HUFF_SLUSH is 4 (32.7%).
+ 10192578 read calls are required when OC_HUFF_SLUSH is 8 (31.6%).
+ Since a value of 2 gets us the vast majority of the speed-up with only a
+ small amount of wasted memory, this is what we use.
+ This value must be less than 128, or you could create a tree with more than
+ 32767 entries, which would overflow the 16-bit words used to index it.*/
+#define OC_HUFF_SLUSH (2)
+/*The root of the tree is on the fast path, and a larger value here is more
+ beneficial than elsewhere in the tree.
+ 7 appears to give the best performance, trading off between increased use of
+ the single-read fast path and cache footprint for the tables, though
+ obviously this will depend on your cache size.
+ Using 7 here, the VP3 tables are about twice as large compared to using 2.*/
+#define OC_ROOT_HUFF_SLUSH (7)
+
+
+
+/*Unpacks a Huffman codebook.
+ _opb: The buffer to unpack from.
+ _tokens: Stores a list of internal tokens, in the order they were found in
+ the codebook, and the lengths of their corresponding codewords.
+ This is enough to completely define the codebook, while minimizing
+ stack usage and avoiding temporary allocations (for platforms
+ where free() is a no-op).
+ Return: The number of internal tokens in the codebook, or a negative value
+ on error.*/
+int oc_huff_tree_unpack(oc_pack_buf *_opb,unsigned char _tokens[256][2]){
+ ogg_uint32_t code;
+ int len;
+ int ntokens;
+ int nleaves;
+ code=0;
+ len=ntokens=nleaves=0;
+ for(;;){
+ long bits;
+ bits=oc_pack_read1(_opb);
+ /*Only process nodes so long as there's more bits in the buffer.*/
if(oc_pack_bytes_left(_opb)<0)return TH_EBADHEADER;
- /*Find out how many internal tokens we translate this external token into.*/
- ntokens=OC_DCT_TOKEN_MAP_ENTRIES[bits];
- if(_nbinodes<2*ntokens-1)return TH_EBADHEADER;
- /*Fill in a complete binary tree pointing to the internal tokens.*/
- for(i=1;i<ntokens;i<<=1){
- int j;
- binode=_binodes+nused;
- nused+=i;
- for(j=0;j<i;j++){
- binode[j].nbits=1;
- binode[j].depth=1;
- binode[j].nodes[0]=_binodes+nused+2*j;
- binode[j].nodes[1]=_binodes+nused+2*j+1;
- }
+ /*Read an internal node:*/
+ if(!bits){
+ len++;
+ /*Don't allow codewords longer than 32 bits.*/
+ if(len>32)return TH_EBADHEADER;
}
- /*And now the leaf nodes with those tokens.*/
- token=OC_DCT_TOKEN_MAP[bits];
- for(i=0;i<ntokens;i++){
- binode=_binodes+nused++;
- binode->nbits=0;
- binode->depth=1;
- binode->token=token+i;
+ /*Read a leaf node:*/
+ else{
+ ogg_uint32_t code_bit;
+ int neb;
+ int nentries;
+ int token;
+ /*Don't allow more than 32 spec-tokens per codebook.*/
+ if(++nleaves>32)return TH_EBADHEADER;
+ bits=oc_pack_read(_opb,OC_NDCT_TOKEN_BITS);
+ neb=OC_DCT_TOKEN_MAP_LOG_NENTRIES[bits];
+ token=OC_DCT_TOKEN_MAP[bits];
+ nentries=1<<neb;
+ while(nentries-->0){
+ _tokens[ntokens][0]=(unsigned char)token++;
+ _tokens[ntokens][1]=(unsigned char)(len+neb);
+ ntokens++;
+ }
+ code_bit=0x80000000U>>len-1;
+ while(len>0&&(code&code_bit)){
+ code^=code_bit;
+ code_bit<<=1;
+ len--;
+ }
+ if(len<=0)break;
+ code|=code_bit;
}
}
- return nused;
-}
-
-/*Finds the depth of shortest branch of the given sub-tree.
- The tree must be binary.
- _binode: The root of the given sub-tree.
- _binode->nbits must be 0 or 1.
- Return: The smallest depth of a leaf node in this sub-tree.
- 0 indicates this sub-tree is a leaf node.*/
-static int oc_huff_tree_mindepth(oc_huff_node *_binode){
- int depth0;
- int depth1;
- if(_binode->nbits==0)return 0;
- depth0=oc_huff_tree_mindepth(_binode->nodes[0]);
- depth1=oc_huff_tree_mindepth(_binode->nodes[1]);
- return OC_MINI(depth0,depth1)+1;
-}
-
-/*Finds the number of internal nodes at a given depth, plus the number of
- leaves at that depth or shallower.
- The tree must be binary.
- _binode: The root of the given sub-tree.
- _binode->nbits must be 0 or 1.
- Return: The number of entries that would be contained in a jump table of the
- given depth.*/
-static int oc_huff_tree_occupancy(oc_huff_node *_binode,int _depth){
- if(_binode->nbits==0||_depth<=0)return 1;
- else{
- return oc_huff_tree_occupancy(_binode->nodes[0],_depth-1)+
- oc_huff_tree_occupancy(_binode->nodes[1],_depth-1);
- }
+ return ntokens;
}
-/*Makes a copy of the given Huffman tree.
- _node: The Huffman tree to copy.
- Return: The copy of the Huffman tree.*/
-static oc_huff_node *oc_huff_tree_copy(const oc_huff_node *_node,
- char **_storage){
- oc_huff_node *ret;
- ret=oc_huff_node_init(_storage,oc_huff_node_size(_node->nbits),_node->nbits);
- ret->depth=_node->depth;
- if(_node->nbits){
- int nchildren;
- int i;
- int inext;
- nchildren=1<<_node->nbits;
- for(i=0;i<nchildren;){
- ret->nodes[i]=oc_huff_tree_copy(_node->nodes[i],_storage);
- inext=i+(1<<_node->nbits-ret->nodes[i]->depth);
- while(++i<inext)ret->nodes[i]=ret->nodes[i-1];
+/*Count how many tokens would be required to fill a subtree at depth _depth.
+ _tokens: A list of internal tokens, in the order they are found in the
+ codebook, and the lengths of their corresponding codewords.
+ _depth: The depth of the desired node in the corresponding tree structure.
+ Return: The number of tokens that belong to that subtree.*/
+static int oc_huff_subtree_tokens(unsigned char _tokens[][2],int _depth){
+ ogg_uint32_t code;
+ int ti;
+ code=0;
+ ti=0;
+ do{
+ if(_tokens[ti][1]-_depth<32)code+=0x80000000U>>_tokens[ti++][1]-_depth;
+ else{
+ /*Because of the expanded internal tokens, we can have codewords as long
+ as 35 bits.
+ A single recursion here is enough to advance past them.*/
+ code++;
+ ti+=oc_huff_subtree_tokens(_tokens+ti,_depth+31);
}
}
- else ret->token=_node->token;
- return ret;
+ while(code<0x80000000U);
+ return ti;
}
-static size_t oc_huff_tree_collapse_size(oc_huff_node *_binode,int _depth){
- size_t size;
- int mindepth;
- int depth;
- int loccupancy;
- int occupancy;
- if(_binode->nbits!=0&&_depth>0){
- return oc_huff_tree_collapse_size(_binode->nodes[0],_depth-1)+
- oc_huff_tree_collapse_size(_binode->nodes[1],_depth-1);
- }
- depth=mindepth=oc_huff_tree_mindepth(_binode);
- occupancy=1<<mindepth;
+/*Compute the number of bits to use for a collapsed tree node at the given
+ depth.
+ _tokens: A list of internal tokens, in the order they are found in the
+ codebook, and the lengths of their corresponding codewords.
+ _ntokens: The number of tokens corresponding to this tree node.
+ _depth: The depth of this tree node.
+ Return: The number of bits to use for a collapsed tree node rooted here.
+ This is always at least one, even if this was a leaf node.*/
+static int oc_huff_tree_collapse_depth(unsigned char _tokens[][2],
+ int _ntokens,int _depth){
+ int got_leaves;
+ int loccupancy;
+ int occupancy;
+ int slush;
+ int nbits;
+ int best_nbits;
+ slush=_depth>0?OC_HUFF_SLUSH:OC_ROOT_HUFF_SLUSH;
+ /*It's legal to have a tree with just a single node, which requires no bits
+ to decode and always returns the same token.
+ However, no encoder actually does this (yet).
+ To avoid a special case in oc_huff_token_decode(), we force the number of
+ lookahead bits to be at least one.
+ This will produce a tree that looks ahead one bit and then advances the
+ stream zero bits.*/
+ nbits=1;
+ occupancy=2;
+ got_leaves=1;
do{
+ int ti;
+ if(got_leaves)best_nbits=nbits;
+ nbits++;
+ got_leaves=0;
loccupancy=occupancy;
- occupancy=oc_huff_tree_occupancy(_binode,++depth);
- }
- while(occupancy>loccupancy&&occupancy>=1<<OC_MAXI(depth-OC_HUFF_SLUSH,0));
- depth--;
- size=oc_huff_node_size(depth);
- if(depth>0){
- size+=oc_huff_tree_collapse_size(_binode->nodes[0],depth-1);
- size+=oc_huff_tree_collapse_size(_binode->nodes[1],depth-1);
+ for(occupancy=ti=0;ti<_ntokens;occupancy++){
+ if(_tokens[ti][1]<_depth+nbits)ti++;
+ else if(_tokens[ti][1]==_depth+nbits){
+ got_leaves=1;
+ ti++;
+ }
+ else ti+=oc_huff_subtree_tokens(_tokens+ti,_depth+nbits);
+ }
}
- return size;
+ while(occupancy>loccupancy&&occupancy*slush>=1<<nbits);
+ return best_nbits;
}
-static oc_huff_node *oc_huff_tree_collapse(oc_huff_node *_binode,
- char **_storage);
-
-/*Fills the given nodes table with all the children in the sub-tree at the
- given depth.
- The nodes in the sub-tree with a depth less than that stored in the table
- are freed.
- The sub-tree must be binary and complete up until the given depth.
- _nodes: The nodes table to fill.
- _binode: The root of the sub-tree to fill it with.
- _binode->nbits must be 0 or 1.
- _level: The current level in the table.
- 0 indicates that the current node should be stored, regardless of
- whether it is a leaf node or an internal node.
- _depth: The depth of the nodes to fill the table with, relative to their
- parent.*/
-static void oc_huff_node_fill(oc_huff_node **_nodes,
- oc_huff_node *_binode,int _level,int _depth,char **_storage){
- if(_level<=0||_binode->nbits==0){
- int i;
- _binode->depth=(unsigned char)(_depth-_level);
- _nodes[0]=oc_huff_tree_collapse(_binode,_storage);
- for(i=1;i<1<<_level;i++)_nodes[i]=_nodes[0];
- }
- else{
- _level--;
- oc_huff_node_fill(_nodes,_binode->nodes[0],_level,_depth,_storage);
- _nodes+=1<<_level;
- oc_huff_node_fill(_nodes,_binode->nodes[1],_level,_depth,_storage);
- }
+/*Determines the size in words of a Huffman tree node that represents a
+ subtree of depth _nbits.
+ _nbits: The depth of the subtree.
+ This must be greater than zero.
+ Return: The number of words required to store the node.*/
+static size_t oc_huff_node_size(int _nbits){
+ return 1+(1<<_nbits);
}
-/*Finds the largest complete sub-tree rooted at the current node and collapses
- it into a single node.
- This procedure is then applied recursively to all the children of that node.
- _binode: The root of the sub-tree to collapse.
- _binode->nbits must be 0 or 1.
- Return: The new root of the collapsed sub-tree.*/
-static oc_huff_node *oc_huff_tree_collapse(oc_huff_node *_binode,
- char **_storage){
- oc_huff_node *root;
- size_t size;
- int mindepth;
- int depth;
- int loccupancy;
- int occupancy;
- depth=mindepth=oc_huff_tree_mindepth(_binode);
- occupancy=1<<mindepth;
+/*Produces a collapsed-tree representation of the given token list.
+ _tree: The storage for the collapsed Huffman tree.
+ This may be NULL to compute the required storage size instead of
+ constructing the tree.
+ _tokens: A list of internal tokens, in the order they are found in the
+ codebook, and the lengths of their corresponding codewords.
+ _ntokens: The number of tokens corresponding to this tree node.
+ Return: The number of words required to store the tree.*/
+static size_t oc_huff_tree_collapse(ogg_int16_t *_tree,
+ unsigned char _tokens[][2],int _ntokens){
+ ogg_int16_t node[34];
+ unsigned char depth[34];
+ unsigned char last[34];
+ size_t ntree;
+ int ti;
+ int l;
+ depth[0]=0;
+ last[0]=(unsigned char)(_ntokens-1);
+ ntree=0;
+ ti=0;
+ l=0;
do{
- loccupancy=occupancy;
- occupancy=oc_huff_tree_occupancy(_binode,++depth);
+ int nbits;
+ nbits=oc_huff_tree_collapse_depth(_tokens+ti,last[l]+1-ti,depth[l]);
+ node[l]=(ogg_int16_t)ntree;
+ ntree+=oc_huff_node_size(nbits);
+ if(_tree!=NULL)_tree[node[l]++]=(ogg_int16_t)nbits;
+ do{
+ while(ti<=last[l]&&_tokens[ti][1]<=depth[l]+nbits){
+ if(_tree!=NULL){
+ ogg_int16_t leaf;
+ int nentries;
+ nentries=1<<depth[l]+nbits-_tokens[ti][1];
+ leaf=(ogg_int16_t)-(_tokens[ti][1]-depth[l]<<8|_tokens[ti][0]);
+ while(nentries-->0)_tree[node[l]++]=leaf;
+ }
+ ti++;
+ }
+ if(ti<=last[l]){
+ /*We need to recurse*/
+ depth[l+1]=(unsigned char)(depth[l]+nbits);
+ if(_tree!=NULL)_tree[node[l]++]=(ogg_int16_t)ntree;
+ l++;
+ last[l]=
+ (unsigned char)(ti+oc_huff_subtree_tokens(_tokens+ti,depth[l])-1);
+ break;
+ }
+ /*Pop back up a level of recursion.*/
+ else if(l-->0)nbits=depth[l+1]-depth[l];
+ }
+ while(l>=0);
}
- while(occupancy>loccupancy&&occupancy>=1<<OC_MAXI(depth-OC_HUFF_SLUSH,0));
- depth--;
- if(depth<=1)return oc_huff_tree_copy(_binode,_storage);
- size=oc_huff_node_size(depth);
- root=oc_huff_node_init(_storage,size,depth);
- root->depth=_binode->depth;
- oc_huff_node_fill(root->nodes,_binode,depth,depth,_storage);
- return root;
+ while(l>=0);
+ return ntree;
}
/*Unpacks a set of Huffman trees, and reduces them to a collapsed
representation.
_opb: The buffer to unpack the trees from.
_nodes: The table to fill with the Huffman trees.
- Return: 0 on success, or a negative value on error.*/
+ Return: 0 on success, or a negative value on error.
+ The caller is responsible for cleaning up any partially initialized
+ _nodes on failure.*/
int oc_huff_trees_unpack(oc_pack_buf *_opb,
- oc_huff_node *_nodes[TH_NHUFFMAN_TABLES]){
+ ogg_int16_t *_nodes[TH_NHUFFMAN_TABLES]){
int i;
for(i=0;i<TH_NHUFFMAN_TABLES;i++){
- oc_huff_node nodes[511];
- char *storage;
- size_t size;
- int ret;
+ unsigned char tokens[256][2];
+ int ntokens;
+ ogg_int16_t *tree;
+ size_t size;
/*Unpack the full tree into a temporary buffer.*/
- ret=oc_huff_tree_unpack(_opb,nodes,sizeof(nodes)/sizeof(*nodes));
- if(ret<0)return ret;
- /*Figure out how big the collapsed tree will be.*/
- size=oc_huff_tree_collapse_size(nodes,0);
- storage=(char *)_ogg_calloc(1,size);
- if(storage==NULL)return TH_EFAULT;
- /*And collapse it.*/
- _nodes[i]=oc_huff_tree_collapse(nodes,&storage);
+ ntokens=oc_huff_tree_unpack(_opb,tokens);
+ if(ntokens<0)return ntokens;
+ /*Figure out how big the collapsed tree will be and allocate space for it.*/
+ size=oc_huff_tree_collapse(NULL,tokens,ntokens);
+ /*This should never happen; if it does it means you set OC_HUFF_SLUSH or
+ OC_ROOT_HUFF_SLUSH too large.*/
+ if(size>32767)return TH_EIMPL;
+ tree=(ogg_int16_t *)_ogg_malloc(size*sizeof(*tree));
+ if(tree==NULL)return TH_EFAULT;
+ /*Construct the collapsed the tree.*/
+ oc_huff_tree_collapse(tree,tokens,ntokens);
+ _nodes[i]=tree;
}
return 0;
}
+/*Determines the size in words of a Huffman subtree.
+ _tree: The complete Huffman tree.
+ _node: The index of the root of the desired subtree.
+ Return: The number of words required to store the tree.*/
+static size_t oc_huff_tree_size(const ogg_int16_t *_tree,int _node){
+ size_t size;
+ int nchildren;
+ int n;
+ int i;
+ n=_tree[_node];
+ size=oc_huff_node_size(n);
+ nchildren=1<<n;
+ i=0;
+ do{
+ int child;
+ child=_tree[_node+i+1];
+ if(child<=0)i+=1<<n-(-child>>8);
+ else{
+ size+=oc_huff_tree_size(_tree,child);
+ i++;
+ }
+ }
+ while(i<nchildren);
+ return size;
+}
+
/*Makes a copy of the given set of Huffman trees.
_dst: The array to store the copy in.
_src: The array of trees to copy.*/
-int oc_huff_trees_copy(oc_huff_node *_dst[TH_NHUFFMAN_TABLES],
- const oc_huff_node *const _src[TH_NHUFFMAN_TABLES]){
+int oc_huff_trees_copy(ogg_int16_t *_dst[TH_NHUFFMAN_TABLES],
+ const ogg_int16_t *const _src[TH_NHUFFMAN_TABLES]){
+ int total;
int i;
+ total=0;
for(i=0;i<TH_NHUFFMAN_TABLES;i++){
- size_t size;
- char *storage;
- size=oc_huff_tree_size(_src[i]);
- storage=(char *)_ogg_calloc(1,size);
- if(storage==NULL){
+ size_t size;
+ size=oc_huff_tree_size(_src[i],0);
+ total+=size;
+ _dst[i]=(ogg_int16_t *)_ogg_malloc(size*sizeof(*_dst[i]));
+ if(_dst[i]==NULL){
while(i-->0)_ogg_free(_dst[i]);
return TH_EFAULT;
}
- _dst[i]=oc_huff_tree_copy(_src[i],&storage);
+ memcpy(_dst[i],_src[i],size*sizeof(*_dst[i]));
}
return 0;
}
/*Frees the memory used by a set of Huffman trees.
_nodes: The array of trees to free.*/
-void oc_huff_trees_clear(oc_huff_node *_nodes[TH_NHUFFMAN_TABLES]){
+void oc_huff_trees_clear(ogg_int16_t *_nodes[TH_NHUFFMAN_TABLES]){
int i;
for(i=0;i<TH_NHUFFMAN_TABLES;i++)_ogg_free(_nodes[i]);
}
+
/*Unpacks a single token using the given Huffman tree.
_opb: The buffer to unpack the token from.
_node: The tree to unpack the token with.
Return: The token value.*/
-int oc_huff_token_decode(oc_pack_buf *_opb,const oc_huff_node *_node){
- long bits;
- while(_node->nbits!=0){
- bits=oc_pack_look(_opb,_node->nbits);
- _node=_node->nodes[bits];
- oc_pack_adv(_opb,_node->depth);
+int oc_huff_token_decode_c(oc_pack_buf *_opb,const ogg_int16_t *_tree){
+ const unsigned char *ptr;
+ const unsigned char *stop;
+ oc_pb_window window;
+ int available;
+ long bits;
+ int node;
+ int n;
+ ptr=_opb->ptr;
+ window=_opb->window;
+ stop=_opb->stop;
+ available=_opb->bits;
+ node=0;
+ for(;;){
+ n=_tree[node];
+ if(n>available){
+ unsigned shift;
+ shift=OC_PB_WINDOW_SIZE-available;
+ do{
+ /*We don't bother setting eof because we won't check for it after we've
+ started decoding DCT tokens.*/
+ if(ptr>=stop){
+ shift=(unsigned)-OC_LOTS_OF_BITS;
+ break;
+ }
+ shift-=8;
+ window|=(oc_pb_window)*ptr++<<shift;
+ }
+ while(shift>=8);
+ /*Note: We never request more than 24 bits, so there's no need to fill in
+ the last partial byte here.*/
+ available=OC_PB_WINDOW_SIZE-shift;
+ }
+ bits=window>>OC_PB_WINDOW_SIZE-n;
+ node=_tree[node+1+bits];
+ if(node<=0)break;
+ window<<=n;
+ available-=n;
}
- return _node->token;
+ node=-node;
+ n=node>>8;
+ window<<=n;
+ available-=n;
+ _opb->ptr=ptr;
+ _opb->window=window;
+ _opb->bits=available;
+ return node&255;
}
diff --git a/thirdparty/libtheora/huffdec.h b/thirdparty/libtheora/huffdec.h
index d7ffa0e99b..03d25dcd1e 100644
--- a/thirdparty/libtheora/huffdec.h
+++ b/thirdparty/libtheora/huffdec.h
@@ -11,7 +11,7 @@
********************************************************************
function:
- last mod: $Id: huffdec.h 16503 2009-08-22 18:14:02Z giles $
+ last mod: $Id$
********************************************************************/
@@ -22,71 +22,11 @@
-typedef struct oc_huff_node oc_huff_node;
-
-/*A node in the Huffman tree.
- Instead of storing every branching in the tree, subtrees can be collapsed
- into one node, with a table of size 1<<nbits pointing directly to its
- descedents nbits levels down.
- This allows more than one bit to be read at a time, and avoids following all
- the intermediate branches with next to no increased code complexity once
- the collapsed tree has been built.
- We do _not_ require that a subtree be complete to be collapsed, but instead
- store duplicate pointers in the table, and record the actual depth of the
- node below its parent.
- This tells us the number of bits to advance the stream after reaching it.
-
- This turns out to be equivalent to the method described in \cite{Hash95},
- without the requirement that codewords be sorted by length.
- If the codewords were sorted by length (so-called ``canonical-codes''), they
- could be decoded much faster via either Lindell and Moffat's approach or
- Hashemian's Condensed Huffman Code approach, the latter of which has an
- extremely small memory footprint.
- We can't use Choueka et al.'s finite state machine approach, which is
- extremely fast, because we can't allow multiple symbols to be output at a
- time; the codebook can and does change between symbols.
- It also has very large memory requirements, which impairs cache coherency.
-
- @ARTICLE{Hash95,
- author="Reza Hashemian",
- title="Memory Efficient and High-Speed Search {Huffman} Coding",
- journal="{IEEE} Transactions on Communications",
- volume=43,
- number=10,
- pages="2576--2581",
- month=Oct,
- year=1995
- }*/
-struct oc_huff_node{
- /*The number of bits of the code needed to descend through this node.
- 0 indicates a leaf node.
- Otherwise there are 1<<nbits nodes in the nodes table, which can be
- indexed by reading nbits bits from the stream.*/
- unsigned char nbits;
- /*The value of a token stored in a leaf node.
- The value in non-leaf nodes is undefined.*/
- unsigned char token;
- /*The depth of the current node, relative to its parent in the collapsed
- tree.
- This can be less than its parent's nbits value, in which case there are
- 1<<nbits-depth copies of this node in the table, and the bitstream should
- only be advanced depth bits after reaching this node.*/
- unsigned char depth;
- /*The table of child nodes.
- The ACTUAL size of this array is 1<<nbits, despite what the declaration
- below claims.
- The exception is that for leaf nodes the size is 0.*/
- oc_huff_node *nodes[2];
-};
-
-
-
int oc_huff_trees_unpack(oc_pack_buf *_opb,
- oc_huff_node *_nodes[TH_NHUFFMAN_TABLES]);
-int oc_huff_trees_copy(oc_huff_node *_dst[TH_NHUFFMAN_TABLES],
- const oc_huff_node *const _src[TH_NHUFFMAN_TABLES]);
-void oc_huff_trees_clear(oc_huff_node *_nodes[TH_NHUFFMAN_TABLES]);
-int oc_huff_token_decode(oc_pack_buf *_opb,const oc_huff_node *_node);
-
+ ogg_int16_t *_nodes[TH_NHUFFMAN_TABLES]);
+int oc_huff_trees_copy(ogg_int16_t *_dst[TH_NHUFFMAN_TABLES],
+ const ogg_int16_t *const _src[TH_NHUFFMAN_TABLES]);
+void oc_huff_trees_clear(ogg_int16_t *_nodes[TH_NHUFFMAN_TABLES]);
+int oc_huff_token_decode_c(oc_pack_buf *_opb,const ogg_int16_t *_node);
#endif
diff --git a/thirdparty/libtheora/huffenc.c b/thirdparty/libtheora/huffenc.c
index bf624e0523..77ab584a19 100644
--- a/thirdparty/libtheora/huffenc.c
+++ b/thirdparty/libtheora/huffenc.c
@@ -859,9 +859,10 @@ int oc_huff_codes_pack(oggpack_buffer *_opb,
/*First, find the maximum code length so we can align all the bit
patterns.*/
maxlen=_codes[i][0].nbits;
- for(j=1;j<TH_NDCT_TOKENS;j++){
- maxlen=OC_MAXI(_codes[i][j].nbits,maxlen);
- }
+ for(j=1;j<TH_NDCT_TOKENS;j++)maxlen=OC_MAXI(_codes[i][j].nbits,maxlen);
+ /*It's improbable that a code with more than 32 bits could pass the
+ validation below, but abort early in any case.*/
+ if(maxlen>32)return TH_EINVAL;
mask=(1<<(maxlen>>1)<<(maxlen+1>>1))-1;
/*Copy over the codes into our temporary workspace.
The bit patterns are aligned, and the original entry each code is from
@@ -877,34 +878,89 @@ int oc_huff_codes_pack(oggpack_buffer *_opb,
/*For each leaf of the tree:*/
bpos=maxlen;
for(j=0;j<TH_NDCT_TOKENS;j++){
- int bit;
- /*If this code has any bits at all.*/
- if(entries[j].shift<maxlen){
- /*Descend into the tree, writing a bit for each branch.*/
- for(;bpos>entries[j].shift;bpos--)oggpackB_write(_opb,0,1);
- /*Mark this as a leaf node, and write its value.*/
- oggpackB_write(_opb,1,1);
- oggpackB_write(_opb,entries[j].token,5);
- /*For each 1 branch we've descended, back up the tree until we reach a
- 0 branch.*/
- bit=1<<bpos;
- for(;entries[j].pattern&bit;bpos++)bit<<=1;
- /*Validate the code.*/
- if(j+1<TH_NDCT_TOKENS){
- mask=~(bit-1)<<1;
- /*The next entry should have a 1 bit where we had a 0, and should
- match our code above that bit.
- This verifies both fullness and prefix-freeness simultaneously.*/
- if(!(entries[j+1].pattern&bit)||
- (entries[j].pattern&mask)!=(entries[j+1].pattern&mask)){
- return TH_EINVAL;
- }
+ ogg_uint32_t bit;
+ /*Fail if this code has no bits at all.
+ Technically a codebook with a single 0-bit entry is legal, but the
+ encoder currently does not support codebooks which do not contain all
+ the tokens.*/
+ if(entries[j].shift>=maxlen)return TH_EINVAL;
+ /*Descend into the tree, writing a bit for each branch.*/
+ for(;bpos>entries[j].shift;bpos--)oggpackB_write(_opb,0,1);
+ /*Mark this as a leaf node, and write its value.*/
+ oggpackB_write(_opb,1,1);
+ oggpackB_write(_opb,entries[j].token,5);
+ /*For each 1 branch we've descended, back up the tree until we reach a
+ 0 branch.*/
+ bit=(ogg_uint32_t)1<<bpos;
+ for(;entries[j].pattern&bit;bpos++)bit<<=1;
+ /*Validate the code.*/
+ if(j+1<TH_NDCT_TOKENS){
+ mask=~(bit-1)<<1;
+ /*The next entry should have a 1 bit where we had a 0, and should
+ match our code above that bit.
+ This verifies both fullness and prefix-freeness simultaneously.*/
+ if(!(entries[j+1].pattern&bit)||
+ (entries[j].pattern&mask)!=(entries[j+1].pattern&mask)){
+ return TH_EINVAL;
+ }
+ }
+ /*If there are no more codes, we should have ascended back to the top
+ of the tree.*/
+ else if(bpos<maxlen)return TH_EINVAL;
+ }
+ }
+ return 0;
+}
+
+/*This is used to copy the configuration of an existing setup header for use by
+ the encoder.
+ The decoder uses a completely different data structure for the Huffman
+ codebooks.*/
+int oc_huff_codes_unpack(oc_pack_buf *_opb,
+ th_huff_code _codes[TH_NHUFFMAN_TABLES][TH_NDCT_TOKENS]){
+ int i;
+ for(i=0;i<TH_NHUFFMAN_TABLES;i++){
+ ogg_uint32_t code;
+ int len;
+ int nleaves;
+ code=0;
+ len=nleaves=0;
+ memset(_codes[i],0,TH_NDCT_TOKENS*sizeof(*_codes[i]));
+ for(;;){
+ long bits;
+ bits=oc_pack_read1(_opb);
+ /*Only process nodes so long as there's more bits in the buffer.*/
+ if(oc_pack_bytes_left(_opb)<0)return TH_EBADHEADER;
+ /*Read an internal node:*/
+ if(!bits){
+ len++;
+ /*Don't allow codewords longer than 32 bits.*/
+ if(len>32)return TH_EBADHEADER;
+ }
+ /*Read a leaf node:*/
+ else{
+ ogg_uint32_t code_bit;
+ /*Don't allow more than 32 tokens per codebook.*/
+ if(++nleaves>32)return TH_EBADHEADER;
+ bits=oc_pack_read(_opb,OC_NDCT_TOKEN_BITS);
+ /*The current encoder does not support codebooks that do not contain
+ all of the tokens.*/
+ if(_codes[i][bits].nbits>0)return TH_EINVAL;
+ _codes[i][bits].pattern=code>>32-len;
+ _codes[i][bits].nbits=len;
+ code_bit=0x80000000U>>len-1;
+ while(len>0&&(code&code_bit)){
+ code^=code_bit;
+ code_bit<<=1;
+ len--;
}
- /*If there are no more codes, we should have ascended back to the top
- of the tree.*/
- else if(bpos<maxlen)return TH_EINVAL;
+ if(len<=0)break;
+ code|=code_bit;
}
}
+ /*The current encoder does not support codebooks that do not contain all of
+ the tokens.*/
+ if(nleaves<32)return TH_EINVAL;
}
return 0;
}
diff --git a/thirdparty/libtheora/huffenc.h b/thirdparty/libtheora/huffenc.h
index c5a3956f1f..0554cc4060 100644
--- a/thirdparty/libtheora/huffenc.h
+++ b/thirdparty/libtheora/huffenc.h
@@ -1,6 +1,7 @@
#if !defined(_huffenc_H)
# define _huffenc_H (1)
# include "huffman.h"
+# include "bitpack.h"
@@ -15,5 +16,7 @@ extern const th_huff_code
int oc_huff_codes_pack(oggpack_buffer *_opb,
const th_huff_code _codes[TH_NHUFFMAN_TABLES][TH_NDCT_TOKENS]);
+int oc_huff_codes_unpack(oc_pack_buf *_opb,
+ th_huff_code _codes[TH_NHUFFMAN_TABLES][TH_NDCT_TOKENS]);
#endif
diff --git a/thirdparty/libtheora/huffman.h b/thirdparty/libtheora/huffman.h
index 36cf7572e5..eb805866b9 100644
--- a/thirdparty/libtheora/huffman.h
+++ b/thirdparty/libtheora/huffman.h
@@ -11,12 +11,12 @@
********************************************************************
function:
- last mod: $Id: huffman.h 16503 2009-08-22 18:14:02Z giles $
+ last mod: $Id$
********************************************************************/
#if !defined(_huffman_H)
-# define _hufffman_H (1)
+# define _huffman_H (1)
# include "theora/codec.h"
# include "ocintrin.h"
diff --git a/thirdparty/libtheora/idct.c b/thirdparty/libtheora/idct.c
index 0e68ac7658..838e3ad8ca 100644
--- a/thirdparty/libtheora/idct.c
+++ b/thirdparty/libtheora/idct.c
@@ -11,7 +11,7 @@
********************************************************************
function:
- last mod: $Id: idct.c 16503 2009-08-22 18:14:02Z giles $
+ last mod: $Id$
********************************************************************/
@@ -231,18 +231,18 @@ static void idct8_1(ogg_int16_t *_y,const ogg_int16_t _x[1]){
_y: The buffer to store the result in.
This may be the same as _x.
_x: The input coefficients.*/
-static void oc_idct8x8_3(ogg_int16_t _y[64],const ogg_int16_t _x[64]){
- const ogg_int16_t *in;
- ogg_int16_t *end;
- ogg_int16_t *out;
- ogg_int16_t w[64];
+static void oc_idct8x8_3(ogg_int16_t _y[64],ogg_int16_t _x[64]){
+ ogg_int16_t w[64];
+ int i;
/*Transform rows of x into columns of w.*/
idct8_2(w,_x);
idct8_1(w+1,_x+8);
/*Transform rows of w into columns of y.*/
- for(in=w,out=_y,end=out+8;out<end;in+=8,out++)idct8_2(out,in);
+ for(i=0;i<8;i++)idct8_2(_y+i,w+i*8);
/*Adjust for the scale factor.*/
- for(out=_y,end=out+64;out<end;out++)*out=(ogg_int16_t)(*out+8>>4);
+ for(i=0;i<64;i++)_y[i]=(ogg_int16_t)(_y[i]+8>>4);
+ /*Clear input data for next block.*/
+ _x[0]=_x[1]=_x[8]=0;
}
/*Performs an inverse 8x8 Type-II DCT transform.
@@ -260,20 +260,20 @@ static void oc_idct8x8_3(ogg_int16_t _y[64],const ogg_int16_t _x[64]){
_y: The buffer to store the result in.
This may be the same as _x.
_x: The input coefficients.*/
-static void oc_idct8x8_10(ogg_int16_t _y[64],const ogg_int16_t _x[64]){
- const ogg_int16_t *in;
- ogg_int16_t *end;
- ogg_int16_t *out;
- ogg_int16_t w[64];
+static void oc_idct8x8_10(ogg_int16_t _y[64],ogg_int16_t _x[64]){
+ ogg_int16_t w[64];
+ int i;
/*Transform rows of x into columns of w.*/
idct8_4(w,_x);
idct8_3(w+1,_x+8);
idct8_2(w+2,_x+16);
idct8_1(w+3,_x+24);
/*Transform rows of w into columns of y.*/
- for(in=w,out=_y,end=out+8;out<end;in+=8,out++)idct8_4(out,in);
+ for(i=0;i<8;i++)idct8_4(_y+i,w+i*8);
/*Adjust for the scale factor.*/
- for(out=_y,end=out+64;out<end;out++)*out=(ogg_int16_t)(*out+8>>4);
+ for(i=0;i<64;i++)_y[i]=(ogg_int16_t)(_y[i]+8>>4);
+ /*Clear input data for next block.*/
+ _x[0]=_x[1]=_x[2]=_x[3]=_x[8]=_x[9]=_x[10]=_x[16]=_x[17]=_x[24]=0;
}
/*Performs an inverse 8x8 Type-II DCT transform.
@@ -282,28 +282,23 @@ static void oc_idct8x8_10(ogg_int16_t _y[64],const ogg_int16_t _x[64]){
_y: The buffer to store the result in.
This may be the same as _x.
_x: The input coefficients.*/
-static void oc_idct8x8_slow(ogg_int16_t _y[64],const ogg_int16_t _x[64]){
- const ogg_int16_t *in;
- ogg_int16_t *end;
- ogg_int16_t *out;
- ogg_int16_t w[64];
+static void oc_idct8x8_slow(ogg_int16_t _y[64],ogg_int16_t _x[64]){
+ ogg_int16_t w[64];
+ int i;
/*Transform rows of x into columns of w.*/
- for(in=_x,out=w,end=out+8;out<end;in+=8,out++)idct8(out,in);
+ for(i=0;i<8;i++)idct8(w+i,_x+i*8);
/*Transform rows of w into columns of y.*/
- for(in=w,out=_y,end=out+8;out<end;in+=8,out++)idct8(out,in);
+ for(i=0;i<8;i++)idct8(_y+i,w+i*8);
/*Adjust for the scale factor.*/
- for(out=_y,end=out+64;out<end;out++)*out=(ogg_int16_t)(*out+8>>4);
-}
-
-void oc_idct8x8(const oc_theora_state *_state,ogg_int16_t _y[64],
- int _last_zzi){
- (*_state->opt_vtable.idct8x8)(_y,_last_zzi);
+ for(i=0;i<64;i++)_y[i]=(ogg_int16_t)(_y[i]+8>>4);
+ /*Clear input data for next block.*/
+ for(i=0;i<64;i++)_x[i]=0;
}
/*Performs an inverse 8x8 Type-II DCT transform.
The input is assumed to be scaled by a factor of 4 relative to orthonormal
version of the transform.*/
-void oc_idct8x8_c(ogg_int16_t _y[64],int _last_zzi){
+void oc_idct8x8_c(ogg_int16_t _y[64],ogg_int16_t _x[64],int _last_zzi){
/*_last_zzi is subtly different from an actual count of the number of
coefficients we decoded for this block.
It contains the value of zzi BEFORE the final token in the block was
@@ -329,7 +324,7 @@ void oc_idct8x8_c(ogg_int16_t _y[64],int _last_zzi){
gets.
Needless to say we inherited this approach from VP3.*/
/*Then perform the iDCT.*/
- if(_last_zzi<3)oc_idct8x8_3(_y,_y);
- else if(_last_zzi<10)oc_idct8x8_10(_y,_y);
- else oc_idct8x8_slow(_y,_y);
+ if(_last_zzi<=3)oc_idct8x8_3(_y,_x);
+ else if(_last_zzi<=10)oc_idct8x8_10(_y,_x);
+ else oc_idct8x8_slow(_y,_x);
}
diff --git a/thirdparty/libtheora/info.c b/thirdparty/libtheora/info.c
index 6b9762978b..e5cecd2de5 100644
--- a/thirdparty/libtheora/info.c
+++ b/thirdparty/libtheora/info.c
@@ -11,7 +11,7 @@
********************************************************************
function:
- last mod: $Id: info.c 16503 2009-08-22 18:14:02Z giles $
+ last mod: $Id$
********************************************************************/
@@ -54,7 +54,7 @@ void th_comment_init(th_comment *_tc){
memset(_tc,0,sizeof(*_tc));
}
-void th_comment_add(th_comment *_tc,char *_comment){
+void th_comment_add(th_comment *_tc,const char *_comment){
char **user_comments;
int *comment_lengths;
int comment_len;
@@ -75,7 +75,7 @@ void th_comment_add(th_comment *_tc,char *_comment){
_tc->user_comments[_tc->comments]=NULL;
}
-void th_comment_add_tag(th_comment *_tc,char *_tag,char *_val){
+void th_comment_add_tag(th_comment *_tc,const char *_tag,const char *_val){
char *comment;
int tag_len;
int val_len;
@@ -91,7 +91,7 @@ void th_comment_add_tag(th_comment *_tc,char *_tag,char *_val){
_ogg_free(comment);
}
-char *th_comment_query(th_comment *_tc,char *_tag,int _count){
+char *th_comment_query(th_comment *_tc,const char *_tag,int _count){
long i;
int found;
int tag_len;
@@ -107,7 +107,7 @@ char *th_comment_query(th_comment *_tc,char *_tag,int _count){
return NULL;
}
-int th_comment_query_count(th_comment *_tc,char *_tag){
+int th_comment_query_count(th_comment *_tc,const char *_tag){
long i;
int tag_len;
int count;
diff --git a/thirdparty/libtheora/internal.c b/thirdparty/libtheora/internal.c
index 0fe4f63e72..afbb6efae7 100644
--- a/thirdparty/libtheora/internal.c
+++ b/thirdparty/libtheora/internal.c
@@ -11,7 +11,7 @@
********************************************************************
function:
- last mod: $Id: internal.c 16503 2009-08-22 18:14:02Z giles $
+ last mod: $Id$
********************************************************************/
@@ -97,79 +97,29 @@ int oc_ilog(unsigned _v){
-/*The function used to fill in the chroma plane motion vectors for a macro
- block when 4 different motion vectors are specified in the luma plane.
- This version is for use with chroma decimated in the X and Y directions
- (4:2:0).
- _cbmvs: The chroma block-level motion vectors to fill in.
- _lbmvs: The luma block-level motion vectors.*/
-static void oc_set_chroma_mvs00(oc_mv _cbmvs[4],const oc_mv _lbmvs[4]){
- int dx;
- int dy;
- dx=_lbmvs[0][0]+_lbmvs[1][0]+_lbmvs[2][0]+_lbmvs[3][0];
- dy=_lbmvs[0][1]+_lbmvs[1][1]+_lbmvs[2][1]+_lbmvs[3][1];
- _cbmvs[0][0]=(signed char)OC_DIV_ROUND_POW2(dx,2,2);
- _cbmvs[0][1]=(signed char)OC_DIV_ROUND_POW2(dy,2,2);
-}
-
-/*The function used to fill in the chroma plane motion vectors for a macro
- block when 4 different motion vectors are specified in the luma plane.
- This version is for use with chroma decimated in the Y direction.
- _cbmvs: The chroma block-level motion vectors to fill in.
- _lbmvs: The luma block-level motion vectors.*/
-static void oc_set_chroma_mvs01(oc_mv _cbmvs[4],const oc_mv _lbmvs[4]){
- int dx;
- int dy;
- dx=_lbmvs[0][0]+_lbmvs[2][0];
- dy=_lbmvs[0][1]+_lbmvs[2][1];
- _cbmvs[0][0]=(signed char)OC_DIV_ROUND_POW2(dx,1,1);
- _cbmvs[0][1]=(signed char)OC_DIV_ROUND_POW2(dy,1,1);
- dx=_lbmvs[1][0]+_lbmvs[3][0];
- dy=_lbmvs[1][1]+_lbmvs[3][1];
- _cbmvs[1][0]=(signed char)OC_DIV_ROUND_POW2(dx,1,1);
- _cbmvs[1][1]=(signed char)OC_DIV_ROUND_POW2(dy,1,1);
-}
-
-/*The function used to fill in the chroma plane motion vectors for a macro
- block when 4 different motion vectors are specified in the luma plane.
- This version is for use with chroma decimated in the X direction (4:2:2).
- _cbmvs: The chroma block-level motion vectors to fill in.
- _lbmvs: The luma block-level motion vectors.*/
-static void oc_set_chroma_mvs10(oc_mv _cbmvs[4],const oc_mv _lbmvs[4]){
- int dx;
- int dy;
- dx=_lbmvs[0][0]+_lbmvs[1][0];
- dy=_lbmvs[0][1]+_lbmvs[1][1];
- _cbmvs[0][0]=(signed char)OC_DIV_ROUND_POW2(dx,1,1);
- _cbmvs[0][1]=(signed char)OC_DIV_ROUND_POW2(dy,1,1);
- dx=_lbmvs[2][0]+_lbmvs[3][0];
- dy=_lbmvs[2][1]+_lbmvs[3][1];
- _cbmvs[2][0]=(signed char)OC_DIV_ROUND_POW2(dx,1,1);
- _cbmvs[2][1]=(signed char)OC_DIV_ROUND_POW2(dy,1,1);
+void *oc_aligned_malloc(size_t _sz,size_t _align){
+ unsigned char *p;
+ if(_align-1>UCHAR_MAX||(_align&_align-1)||_sz>~(size_t)0-_align)return NULL;
+ p=(unsigned char *)_ogg_malloc(_sz+_align);
+ if(p!=NULL){
+ int offs;
+ offs=((p-(unsigned char *)0)-1&_align-1);
+ p[offs]=offs;
+ p+=offs+1;
+ }
+ return p;
}
-/*The function used to fill in the chroma plane motion vectors for a macro
- block when 4 different motion vectors are specified in the luma plane.
- This version is for use with no chroma decimation (4:4:4).
- _cbmvs: The chroma block-level motion vectors to fill in.
- _lmbmv: The luma macro-block level motion vector to fill in for use in
- prediction.
- _lbmvs: The luma block-level motion vectors.*/
-static void oc_set_chroma_mvs11(oc_mv _cbmvs[4],const oc_mv _lbmvs[4]){
- memcpy(_cbmvs,_lbmvs,4*sizeof(_lbmvs[0]));
+void oc_aligned_free(void *_ptr){
+ unsigned char *p;
+ p=(unsigned char *)_ptr;
+ if(p!=NULL){
+ int offs;
+ offs=*--p;
+ _ogg_free(p-offs);
+ }
}
-/*A table of functions used to fill in the chroma plane motion vectors for a
- macro block when 4 different motion vectors are specified in the luma
- plane.*/
-const oc_set_chroma_mvs_func OC_SET_CHROMA_MVS_TABLE[TH_PF_NFORMATS]={
- (oc_set_chroma_mvs_func)oc_set_chroma_mvs00,
- (oc_set_chroma_mvs_func)oc_set_chroma_mvs01,
- (oc_set_chroma_mvs_func)oc_set_chroma_mvs10,
- (oc_set_chroma_mvs_func)oc_set_chroma_mvs11
-};
-
-
void **oc_malloc_2d(size_t _height,size_t _width,size_t _sz){
size_t rowsz;
@@ -181,7 +131,6 @@ void **oc_malloc_2d(size_t _height,size_t _width,size_t _sz){
datsz=rowsz*_height;
/*Alloc array and row pointers.*/
ret=(char *)_ogg_malloc(datsz+colsz);
- if(ret==NULL)return NULL;
/*Initialize the array.*/
if(ret!=NULL){
size_t i;
@@ -204,7 +153,6 @@ void **oc_calloc_2d(size_t _height,size_t _width,size_t _sz){
datsz=rowsz*_height;
/*Alloc array and row pointers.*/
ret=(char *)_ogg_calloc(datsz+colsz,1);
- if(ret==NULL)return NULL;
/*Initialize the array.*/
if(ret!=NULL){
size_t i;
diff --git a/thirdparty/libtheora/internal.h b/thirdparty/libtheora/internal.h
index d81263e13e..53c77b88be 100644
--- a/thirdparty/libtheora/internal.h
+++ b/thirdparty/libtheora/internal.h
@@ -11,7 +11,7 @@
********************************************************************
function:
- last mod: $Id: internal.h 16503 2009-08-22 18:14:02Z giles $
+ last mod: $Id$
********************************************************************/
#if !defined(_internal_H)
@@ -19,10 +19,20 @@
# include <stdlib.h>
# include <limits.h>
# if defined(HAVE_CONFIG_H)
-# include <config.h>
+# include "config.h"
# endif
# include "theora/codec.h"
# include "theora/theora.h"
+# include "ocintrin.h"
+
+# if !defined(__GNUC_PREREQ)
+# if defined(__GNUC__)&&defined(__GNUC_MINOR__)
+# define __GNUC_PREREQ(_maj,_min) \
+ ((__GNUC__<<16)+__GNUC_MINOR__>=((_maj)<<16)+(_min))
+# else
+# define __GNUC_PREREQ(_maj,_min) 0
+# endif
+# endif
# if defined(_MSC_VER)
/*Disable missing EMMS warnings.*/
@@ -31,24 +41,25 @@
# pragma warning(disable:4554)
# endif
/*You, too, gcc.*/
-# if defined(__GNUC_PREREQ)
-# if __GNUC_PREREQ(4,2)
-# pragma GCC diagnostic ignored "-Wparentheses"
-# endif
+# if __GNUC_PREREQ(4,2)
+# pragma GCC diagnostic ignored "-Wparentheses"
# endif
-# include "ocintrin.h"
-# include "huffman.h"
-# include "quant.h"
-
-/*Some assembly constructs require aligned operands.*/
-# if defined(OC_X86_ASM)
+/*Some assembly constructs require aligned operands.
+ The following macros are _only_ intended for structure member declarations.
+ Although they will sometimes work on stack variables, gcc will often silently
+ ignore them.
+ A separate set of macros could be made for manual stack alignment, but we
+ don't actually require it anywhere.*/
+# if defined(OC_X86_ASM)||defined(OC_ARM_ASM)
# if defined(__GNUC__)
# define OC_ALIGN8(expr) expr __attribute__((aligned(8)))
# define OC_ALIGN16(expr) expr __attribute__((aligned(16)))
# elif defined(_MSC_VER)
# define OC_ALIGN8(expr) __declspec (align(8)) expr
# define OC_ALIGN16(expr) __declspec (align(16)) expr
+# else
+# error "Alignment macros required for this platform."
# endif
# endif
# if !defined(OC_ALIGN8)
@@ -60,19 +71,8 @@
-typedef struct oc_sb_flags oc_sb_flags;
-typedef struct oc_border_info oc_border_info;
-typedef struct oc_fragment oc_fragment;
-typedef struct oc_fragment_plane oc_fragment_plane;
-typedef struct oc_base_opt_vtable oc_base_opt_vtable;
-typedef struct oc_base_opt_data oc_base_opt_data;
-typedef struct oc_state_dispatch_vtable oc_state_dispatch_vtable;
-typedef struct oc_theora_state oc_theora_state;
-
-
-
/*This library's version.*/
-# define OC_VENDOR_STRING "Xiph.Org libtheora 1.1 20090822 (Thusnelda)"
+# define OC_VENDOR_STRING "Xiph.Org libtheora 1.2.0alpha 20100924 (Ptalarbvorm)"
/*Theora bitstream version.*/
# define TH_VERSION_MAJOR (3)
@@ -83,315 +83,6 @@ typedef struct oc_theora_state oc_theora_state;
((_info)->version_minor>(_min)||(_info)->version_minor==(_min)&& \
(_info)->version_subminor>=(_sub)))
-/*A keyframe.*/
-#define OC_INTRA_FRAME (0)
-/*A predicted frame.*/
-#define OC_INTER_FRAME (1)
-/*A frame of unknown type (frame type decision has not yet been made).*/
-#define OC_UNKWN_FRAME (-1)
-
-/*The amount of padding to add to the reconstructed frame buffers on all
- sides.
- This is used to allow unrestricted motion vectors without special casing.
- This must be a multiple of 2.*/
-#define OC_UMV_PADDING (16)
-
-/*Frame classification indices.*/
-/*The previous golden frame.*/
-#define OC_FRAME_GOLD (0)
-/*The previous frame.*/
-#define OC_FRAME_PREV (1)
-/*The current frame.*/
-#define OC_FRAME_SELF (2)
-
-/*The input or output buffer.*/
-#define OC_FRAME_IO (3)
-
-/*Macroblock modes.*/
-/*Macro block is invalid: It is never coded.*/
-#define OC_MODE_INVALID (-1)
-/*Encoded difference from the same macro block in the previous frame.*/
-#define OC_MODE_INTER_NOMV (0)
-/*Encoded with no motion compensated prediction.*/
-#define OC_MODE_INTRA (1)
-/*Encoded difference from the previous frame offset by the given motion
- vector.*/
-#define OC_MODE_INTER_MV (2)
-/*Encoded difference from the previous frame offset by the last coded motion
- vector.*/
-#define OC_MODE_INTER_MV_LAST (3)
-/*Encoded difference from the previous frame offset by the second to last
- coded motion vector.*/
-#define OC_MODE_INTER_MV_LAST2 (4)
-/*Encoded difference from the same macro block in the previous golden
- frame.*/
-#define OC_MODE_GOLDEN_NOMV (5)
-/*Encoded difference from the previous golden frame offset by the given motion
- vector.*/
-#define OC_MODE_GOLDEN_MV (6)
-/*Encoded difference from the previous frame offset by the individual motion
- vectors given for each block.*/
-#define OC_MODE_INTER_MV_FOUR (7)
-/*The number of (coded) modes.*/
-#define OC_NMODES (8)
-
-/*Determines the reference frame used for a given MB mode.*/
-#define OC_FRAME_FOR_MODE(_x) \
- OC_UNIBBLE_TABLE32(OC_FRAME_PREV,OC_FRAME_SELF,OC_FRAME_PREV,OC_FRAME_PREV, \
- OC_FRAME_PREV,OC_FRAME_GOLD,OC_FRAME_GOLD,OC_FRAME_PREV,(_x))
-
-/*Constants for the packet state machine common between encoder and decoder.*/
-
-/*Next packet to emit/read: Codec info header.*/
-#define OC_PACKET_INFO_HDR (-3)
-/*Next packet to emit/read: Comment header.*/
-#define OC_PACKET_COMMENT_HDR (-2)
-/*Next packet to emit/read: Codec setup header.*/
-#define OC_PACKET_SETUP_HDR (-1)
-/*No more packets to emit/read.*/
-#define OC_PACKET_DONE (INT_MAX)
-
-
-
-/*Super blocks are 32x32 segments of pixels in a single color plane indexed
- in image order.
- Internally, super blocks are broken up into four quadrants, each of which
- contains a 2x2 pattern of blocks, each of which is an 8x8 block of pixels.
- Quadrants, and the blocks within them, are indexed in a special order called
- a "Hilbert curve" within the super block.
-
- In order to differentiate between the Hilbert-curve indexing strategy and
- the regular image order indexing strategy, blocks indexed in image order
- are called "fragments".
- Fragments are indexed in image order, left to right, then bottom to top,
- from Y' plane to Cb plane to Cr plane.
-
- The co-located fragments in all image planes corresponding to the location
- of a single quadrant of a luma plane super block form a macro block.
- Thus there is only a single set of macro blocks for all planes, each of which
- contains between 6 and 12 fragments, depending on the pixel format.
- Therefore macro block information is kept in a separate set of arrays from
- super blocks to avoid unused space in the other planes.
- The lists are indexed in super block order.
- That is, the macro block corresponding to the macro block mbi in (luma plane)
- super block sbi is at index (sbi<<2|mbi).
- Thus the number of macro blocks in each dimension is always twice the number
- of super blocks, even when only an odd number fall inside the coded frame.
- These "extra" macro blocks are just an artifact of our internal data layout,
- and not part of the coded stream; they are flagged with a negative MB mode.*/
-
-
-
-/*A single quadrant of the map from a super block to fragment numbers.*/
-typedef ptrdiff_t oc_sb_map_quad[4];
-/*A map from a super block to fragment numbers.*/
-typedef oc_sb_map_quad oc_sb_map[4];
-/*A single plane of the map from a macro block to fragment numbers.*/
-typedef ptrdiff_t oc_mb_map_plane[4];
-/*A map from a macro block to fragment numbers.*/
-typedef oc_mb_map_plane oc_mb_map[3];
-/*A motion vector.*/
-typedef signed char oc_mv[2];
-
-
-
-/*Super block information.*/
-struct oc_sb_flags{
- unsigned char coded_fully:1;
- unsigned char coded_partially:1;
- unsigned char quad_valid:4;
-};
-
-
-
-/*Information about a fragment which intersects the border of the displayable
- region.
- This marks which pixels belong to the displayable region.*/
-struct oc_border_info{
- /*A bit mask marking which pixels are in the displayable region.
- Pixel (x,y) corresponds to bit (y<<3|x).*/
- ogg_int64_t mask;
- /*The number of pixels in the displayable region.
- This is always positive, and always less than 64.*/
- int npixels;
-};
-
-
-
-/*Fragment information.*/
-struct oc_fragment{
- /*A flag indicating whether or not this fragment is coded.*/
- unsigned coded:1;
- /*A flag indicating that this entire fragment lies outside the displayable
- region of the frame.
- Note the contrast with an invalid macro block, which is outside the coded
- frame, not just the displayable one.
- There are no fragments outside the coded frame by construction.*/
- unsigned invalid:1;
- /*The index of the quality index used for this fragment's AC coefficients.*/
- unsigned qii:6;
- /*The mode of the macroblock this fragment belongs to.*/
- unsigned mb_mode:3;
- /*The index of the associated border information for fragments which lie
- partially outside the displayable region.
- For fragments completely inside or outside this region, this is -1.
- Note that the C standard requires an explicit signed keyword for bitfield
- types, since some compilers may treat them as unsigned without it.*/
- signed int borderi:5;
- /*The prediction-corrected DC component.
- Note that the C standard requires an explicit signed keyword for bitfield
- types, since some compilers may treat them as unsigned without it.*/
- signed int dc:16;
-};
-
-
-
-/*A description of each fragment plane.*/
-struct oc_fragment_plane{
- /*The number of fragments in the horizontal direction.*/
- int nhfrags;
- /*The number of fragments in the vertical direction.*/
- int nvfrags;
- /*The offset of the first fragment in the plane.*/
- ptrdiff_t froffset;
- /*The total number of fragments in the plane.*/
- ptrdiff_t nfrags;
- /*The number of super blocks in the horizontal direction.*/
- unsigned nhsbs;
- /*The number of super blocks in the vertical direction.*/
- unsigned nvsbs;
- /*The offset of the first super block in the plane.*/
- unsigned sboffset;
- /*The total number of super blocks in the plane.*/
- unsigned nsbs;
-};
-
-
-
-/*The shared (encoder and decoder) functions that have accelerated variants.*/
-struct oc_base_opt_vtable{
- void (*frag_copy)(unsigned char *_dst,
- const unsigned char *_src,int _ystride);
- void (*frag_recon_intra)(unsigned char *_dst,int _ystride,
- const ogg_int16_t _residue[64]);
- void (*frag_recon_inter)(unsigned char *_dst,
- const unsigned char *_src,int _ystride,const ogg_int16_t _residue[64]);
- void (*frag_recon_inter2)(unsigned char *_dst,const unsigned char *_src1,
- const unsigned char *_src2,int _ystride,const ogg_int16_t _residue[64]);
- void (*idct8x8)(ogg_int16_t _y[64],int _last_zzi);
- void (*state_frag_recon)(const oc_theora_state *_state,ptrdiff_t _fragi,
- int _pli,ogg_int16_t _dct_coeffs[64],int _last_zzi,ogg_uint16_t _dc_quant);
- void (*state_frag_copy_list)(const oc_theora_state *_state,
- const ptrdiff_t *_fragis,ptrdiff_t _nfragis,
- int _dst_frame,int _src_frame,int _pli);
- void (*state_loop_filter_frag_rows)(const oc_theora_state *_state,
- int _bv[256],int _refi,int _pli,int _fragy0,int _fragy_end);
- void (*restore_fpu)(void);
-};
-
-/*The shared (encoder and decoder) tables that vary according to which variants
- of the above functions are used.*/
-struct oc_base_opt_data{
- const unsigned char *dct_fzig_zag;
-};
-
-
-/*State information common to both the encoder and decoder.*/
-struct oc_theora_state{
- /*The stream information.*/
- th_info info;
- /*Table for shared accelerated functions.*/
- oc_base_opt_vtable opt_vtable;
- /*Table for shared data used by accelerated functions.*/
- oc_base_opt_data opt_data;
- /*CPU flags to detect the presence of extended instruction sets.*/
- ogg_uint32_t cpu_flags;
- /*The fragment plane descriptions.*/
- oc_fragment_plane fplanes[3];
- /*The list of fragments, indexed in image order.*/
- oc_fragment *frags;
- /*The the offset into the reference frame buffer to the upper-left pixel of
- each fragment.*/
- ptrdiff_t *frag_buf_offs;
- /*The motion vector for each fragment.*/
- oc_mv *frag_mvs;
- /*The total number of fragments in a single frame.*/
- ptrdiff_t nfrags;
- /*The list of super block maps, indexed in image order.*/
- oc_sb_map *sb_maps;
- /*The list of super block flags, indexed in image order.*/
- oc_sb_flags *sb_flags;
- /*The total number of super blocks in a single frame.*/
- unsigned nsbs;
- /*The fragments from each color plane that belong to each macro block.
- Fragments are stored in image order (left to right then top to bottom).
- When chroma components are decimated, the extra fragments have an index of
- -1.*/
- oc_mb_map *mb_maps;
- /*The list of macro block modes.
- A negative number indicates the macro block lies entirely outside the
- coded frame.*/
- signed char *mb_modes;
- /*The number of macro blocks in the X direction.*/
- unsigned nhmbs;
- /*The number of macro blocks in the Y direction.*/
- unsigned nvmbs;
- /*The total number of macro blocks.*/
- size_t nmbs;
- /*The list of coded fragments, in coded order.
- Uncoded fragments are stored in reverse order from the end of the list.*/
- ptrdiff_t *coded_fragis;
- /*The number of coded fragments in each plane.*/
- ptrdiff_t ncoded_fragis[3];
- /*The total number of coded fragments.*/
- ptrdiff_t ntotal_coded_fragis;
- /*The index of the buffers being used for each OC_FRAME_* reference frame.*/
- int ref_frame_idx[4];
- /*The actual buffers used for the previously decoded frames.*/
- th_ycbcr_buffer ref_frame_bufs[4];
- /*The storage for the reference frame buffers.*/
- unsigned char *ref_frame_data[4];
- /*The strides for each plane in the reference frames.*/
- int ref_ystride[3];
- /*The number of unique border patterns.*/
- int nborders;
- /*The unique border patterns for all border fragments.
- The borderi field of fragments which straddle the border indexes this
- list.*/
- oc_border_info borders[16];
- /*The frame number of the last keyframe.*/
- ogg_int64_t keyframe_num;
- /*The frame number of the current frame.*/
- ogg_int64_t curframe_num;
- /*The granpos of the current frame.*/
- ogg_int64_t granpos;
- /*The type of the current frame.*/
- unsigned char frame_type;
- /*The bias to add to the frame count when computing granule positions.*/
- unsigned char granpos_bias;
- /*The number of quality indices used in the current frame.*/
- unsigned char nqis;
- /*The quality indices of the current frame.*/
- unsigned char qis[3];
- /*The dequantization tables, stored in zig-zag order, and indexed by
- qi, pli, qti, and zzi.*/
- ogg_uint16_t *dequant_tables[64][3][2];
- OC_ALIGN16(oc_quant_table dequant_table_data[64][3][2]);
- /*Loop filter strength parameters.*/
- unsigned char loop_filter_limits[64];
-};
-
-
-
-/*The function type used to fill in the chroma plane motion vectors for a
- macro block when 4 different motion vectors are specified in the luma
- plane.
- _cbmvs: The chroma block-level motion vectors to fill in.
- _lmbmv: The luma macro-block level motion vector to fill in for use in
- prediction.
- _lbmvs: The luma block-level motion vectors.*/
-typedef void (*oc_set_chroma_mvs_func)(oc_mv _cbmvs[4],const oc_mv _lbmvs[4]);
-
/*A map from the index in the zig zag scan to the coefficient number in a
@@ -409,14 +100,12 @@ extern const unsigned char OC_MB_MAP_IDXS[TH_PF_NFORMATS][12];
/*The number of indices in the oc_mb_map array that can be valid for each of
the various chroma decimation types.*/
extern const unsigned char OC_MB_MAP_NIDXS[TH_PF_NFORMATS];
-/*A table of functions used to fill in the Cb,Cr plane motion vectors for a
- macro block when 4 different motion vectors are specified in the luma
- plane.*/
-extern const oc_set_chroma_mvs_func OC_SET_CHROMA_MVS_TABLE[TH_PF_NFORMATS];
int oc_ilog(unsigned _v);
+void *oc_aligned_malloc(size_t _sz,size_t _align);
+void oc_aligned_free(void *_ptr);
void **oc_malloc_2d(size_t _height,size_t _width,size_t _sz);
void **oc_calloc_2d(size_t _height,size_t _width,size_t _sz);
void oc_free_2d(void *_ptr);
@@ -424,86 +113,4 @@ void oc_free_2d(void *_ptr);
void oc_ycbcr_buffer_flip(th_ycbcr_buffer _dst,
const th_ycbcr_buffer _src);
-int oc_state_init(oc_theora_state *_state,const th_info *_info,int _nrefs);
-void oc_state_clear(oc_theora_state *_state);
-void oc_state_vtable_init_c(oc_theora_state *_state);
-void oc_state_borders_fill_rows(oc_theora_state *_state,int _refi,int _pli,
- int _y0,int _yend);
-void oc_state_borders_fill_caps(oc_theora_state *_state,int _refi,int _pli);
-void oc_state_borders_fill(oc_theora_state *_state,int _refi);
-void oc_state_fill_buffer_ptrs(oc_theora_state *_state,int _buf_idx,
- th_ycbcr_buffer _img);
-int oc_state_mbi_for_pos(oc_theora_state *_state,int _mbx,int _mby);
-int oc_state_get_mv_offsets(const oc_theora_state *_state,int _offsets[2],
- int _pli,int _dx,int _dy);
-
-int oc_state_loop_filter_init(oc_theora_state *_state,int *_bv);
-void oc_state_loop_filter(oc_theora_state *_state,int _frame);
-#if defined(OC_DUMP_IMAGES)
-int oc_state_dump_frame(const oc_theora_state *_state,int _frame,
- const char *_suf);
-#endif
-
-/*Shared accelerated functions.*/
-void oc_frag_copy(const oc_theora_state *_state,unsigned char *_dst,
- const unsigned char *_src,int _ystride);
-void oc_frag_recon_intra(const oc_theora_state *_state,
- unsigned char *_dst,int _dst_ystride,const ogg_int16_t _residue[64]);
-void oc_frag_recon_inter(const oc_theora_state *_state,unsigned char *_dst,
- const unsigned char *_src,int _ystride,const ogg_int16_t _residue[64]);
-void oc_frag_recon_inter2(const oc_theora_state *_state,
- unsigned char *_dst,const unsigned char *_src1,const unsigned char *_src2,
- int _ystride,const ogg_int16_t _residue[64]);
-void oc_idct8x8(const oc_theora_state *_state,ogg_int16_t _y[64],int _last_zzi);
-void oc_state_frag_recon(const oc_theora_state *_state,ptrdiff_t _fragi,
- int _pli,ogg_int16_t _dct_coeffs[64],int _last_zzi,ogg_uint16_t _dc_quant);
-void oc_state_frag_copy_list(const oc_theora_state *_state,
- const ptrdiff_t *_fragis,ptrdiff_t _nfragis,
- int _dst_frame,int _src_frame,int _pli);
-void oc_state_loop_filter_frag_rows(const oc_theora_state *_state,
- int _bv[256],int _refi,int _pli,int _fragy0,int _fragy_end);
-void oc_restore_fpu(const oc_theora_state *_state);
-
-/*Default pure-C implementations.*/
-void oc_frag_copy_c(unsigned char *_dst,
- const unsigned char *_src,int _src_ystride);
-void oc_frag_recon_intra_c(unsigned char *_dst,int _dst_ystride,
- const ogg_int16_t _residue[64]);
-void oc_frag_recon_inter_c(unsigned char *_dst,
- const unsigned char *_src,int _ystride,const ogg_int16_t _residue[64]);
-void oc_frag_recon_inter2_c(unsigned char *_dst,const unsigned char *_src1,
- const unsigned char *_src2,int _ystride,const ogg_int16_t _residue[64]);
-void oc_idct8x8_c(ogg_int16_t _y[64],int _last_zzi);
-void oc_state_frag_recon_c(const oc_theora_state *_state,ptrdiff_t _fragi,
- int _pli,ogg_int16_t _dct_coeffs[64],int _last_zzi,ogg_uint16_t _dc_quant);
-void oc_state_frag_copy_list_c(const oc_theora_state *_state,
- const ptrdiff_t *_fragis,ptrdiff_t _nfragis,
- int _dst_frame,int _src_frame,int _pli);
-void oc_state_loop_filter_frag_rows_c(const oc_theora_state *_state,
- int _bv[256],int _refi,int _pli,int _fragy0,int _fragy_end);
-void oc_restore_fpu_c(void);
-
-/*We need a way to call a few encoder functions without introducing a link-time
- dependency into the decoder, while still allowing the old alpha API which
- does not distinguish between encoder and decoder objects to be used.
- We do this by placing a function table at the start of the encoder object
- which can dispatch into the encoder library.
- We do a similar thing for the decoder in case we ever decide to split off a
- common base library.*/
-typedef void (*oc_state_clear_func)(theora_state *_th);
-typedef int (*oc_state_control_func)(theora_state *th,int _req,
- void *_buf,size_t _buf_sz);
-typedef ogg_int64_t (*oc_state_granule_frame_func)(theora_state *_th,
- ogg_int64_t _granulepos);
-typedef double (*oc_state_granule_time_func)(theora_state *_th,
- ogg_int64_t _granulepos);
-
-
-struct oc_state_dispatch_vtable{
- oc_state_clear_func clear;
- oc_state_control_func control;
- oc_state_granule_frame_func granule_frame;
- oc_state_granule_time_func granule_time;
-};
-
#endif
diff --git a/thirdparty/libtheora/mathops.c b/thirdparty/libtheora/mathops.c
index d3fb909194..23c8f6e1ba 100644
--- a/thirdparty/libtheora/mathops.c
+++ b/thirdparty/libtheora/mathops.c
@@ -1,10 +1,8 @@
+#include "internal.h"
#include "mathops.h"
-#include <limits.h>
/*The fastest fallback strategy for platforms with fast multiplication appears
to be based on de Bruijn sequences~\cite{LP98}.
- Tests confirmed this to be true even on an ARM11, where it is actually faster
- than using the native clz instruction.
Define OC_ILOG_NODEBRUIJN to use a simpler fallback on platforms where
multiplication or table lookups are too expensive.
@@ -15,8 +13,7 @@
year=1998,
note="\url{http://supertech.csail.mit.edu/papers/debruijn.pdf}"
}*/
-#if !defined(OC_ILOG_NODEBRUIJN)&& \
- !defined(OC_CLZ32)||!defined(OC_CLZ64)&&LONG_MAX<9223372036854775807LL
+#if !defined(OC_ILOG_NODEBRUIJN)&&!defined(OC_CLZ32)
static const unsigned char OC_DEBRUIJN_IDX32[32]={
0, 1,28, 2,29,14,24, 3,30,22,20,15,25,17, 4, 8,
31,27,13,23,21,19,16, 7,26,12,18, 6,11, 5,10, 9
@@ -25,7 +22,7 @@ static const unsigned char OC_DEBRUIJN_IDX32[32]={
int oc_ilog32(ogg_uint32_t _v){
#if defined(OC_CLZ32)
- return (OC_CLZ32_OFFS-OC_CLZ32(_v))&-!!_v;
+ return OC_CLZ32_OFFS-OC_CLZ32(_v)&-!!_v;
#else
/*On a Pentium M, this branchless version tested as the fastest version without
multiplications on 1,000,000,000 random 32-bit integers, edging out a
@@ -51,12 +48,12 @@ int oc_ilog32(ogg_uint32_t _v){
/*This de Bruijn sequence version is faster if you have a fast multiplier.*/
# else
int ret;
- ret=_v>0;
_v|=_v>>1;
_v|=_v>>2;
_v|=_v>>4;
_v|=_v>>8;
_v|=_v>>16;
+ ret=_v&1;
_v=(_v>>1)+1;
ret+=OC_DEBRUIJN_IDX32[_v*0x77CB531U>>27&0x1F];
return ret;
@@ -66,16 +63,21 @@ int oc_ilog32(ogg_uint32_t _v){
int oc_ilog64(ogg_int64_t _v){
#if defined(OC_CLZ64)
- return (OC_CLZ64_OFFS-OC_CLZ64(_v))&-!!_v;
+ return OC_CLZ64_OFFS-OC_CLZ64(_v)&-!!_v;
#else
-# if defined(OC_ILOG_NODEBRUIJN)
+/*If we don't have a fast 64-bit word implementation, split it into two 32-bit
+ halves.*/
+# if defined(OC_ILOG_NODEBRUIJN)|| \
+ defined(OC_CLZ32)||LONG_MAX<9223372036854775807LL
ogg_uint32_t v;
int ret;
int m;
- ret=_v>0;
m=(_v>0xFFFFFFFFU)<<5;
v=(ogg_uint32_t)(_v>>m);
- ret|=m;
+# if defined(OC_CLZ32)
+ ret=m+OC_CLZ32_OFFS-OC_CLZ32(v)&-!!v;
+# elif defined(OC_ILOG_NODEBRUIJN)
+ ret=v>0|m;
m=(v>0xFFFFU)<<4;
v>>=m;
ret|=m;
@@ -90,26 +92,19 @@ int oc_ilog64(ogg_int64_t _v){
ret|=m;
ret+=v>1;
return ret;
-# else
-/*If we don't have a 64-bit word, split it into two 32-bit halves.*/
-# if LONG_MAX<9223372036854775807LL
- ogg_uint32_t v;
- int ret;
- int m;
- ret=_v>0;
- m=(_v>0xFFFFFFFFU)<<5;
- v=(ogg_uint32_t)(_v>>m);
- ret|=m;
+# else
v|=v>>1;
v|=v>>2;
v|=v>>4;
v|=v>>8;
v|=v>>16;
+ ret=v&1|m;
v=(v>>1)+1;
ret+=OC_DEBRUIJN_IDX32[v*0x77CB531U>>27&0x1F];
+# endif
return ret;
-/*Otherwise do it in one 64-bit operation.*/
-# else
+/*Otherwise do it in one 64-bit multiply.*/
+# else
static const unsigned char OC_DEBRUIJN_IDX64[64]={
0, 1, 2, 7, 3,13, 8,19, 4,25,14,28, 9,34,20,40,
5,17,26,38,15,46,29,48,10,31,35,54,21,50,41,57,
@@ -117,17 +112,16 @@ int oc_ilog64(ogg_int64_t _v){
62,11,23,32,36,44,52,55,61,22,43,51,60,42,59,58
};
int ret;
- ret=_v>0;
_v|=_v>>1;
_v|=_v>>2;
_v|=_v>>4;
_v|=_v>>8;
_v|=_v>>16;
_v|=_v>>32;
+ ret=(int)_v&1;
_v=(_v>>1)+1;
ret+=OC_DEBRUIJN_IDX64[_v*0x218A392CD3D5DBF>>58&0x3F];
return ret;
-# endif
# endif
#endif
}
@@ -294,3 +288,27 @@ ogg_int64_t oc_blog64(ogg_int64_t _w){
}
return OC_Q57(ipart)+z;
}
+
+/*Polynomial approximation of a binary exponential.
+ Q10 input, Q0 output.*/
+ogg_uint32_t oc_bexp32_q10(int _z){
+ unsigned n;
+ int ipart;
+ ipart=_z>>10;
+ n=(_z&(1<<10)-1)<<4;
+ n=(n*((n*((n*((n*3548>>15)+6817)>>15)+15823)>>15)+22708)>>15)+16384;
+ return 14-ipart>0?n+(1<<13-ipart)>>14-ipart:n<<ipart-14;
+}
+
+/*Polynomial approximation of a binary logarithm.
+ Q0 input, Q10 output.*/
+int oc_blog32_q10(ogg_uint32_t _w){
+ int n;
+ int ipart;
+ int fpart;
+ if(_w<=0)return -1;
+ ipart=OC_ILOGNZ_32(_w);
+ n=(ipart-16>0?_w>>ipart-16:_w<<16-ipart)-32768-16384;
+ fpart=(n*((n*((n*((n*-1402>>15)+2546)>>15)-5216)>>15)+15745)>>15)-6793;
+ return (ipart<<10)+(fpart>>4);
+}
diff --git a/thirdparty/libtheora/mathops.h b/thirdparty/libtheora/mathops.h
index efbc5377b0..a1a4f9df0e 100644
--- a/thirdparty/libtheora/mathops.h
+++ b/thirdparty/libtheora/mathops.h
@@ -2,29 +2,27 @@
# define _mathops_H (1)
# include <ogg/ogg.h>
-# ifdef __GNUC_PREREQ
-# if __GNUC_PREREQ(3,4)
-# include <limits.h>
+# if __GNUC_PREREQ(3,4)
+# include <limits.h>
/*Note the casts to (int) below: this prevents OC_CLZ{32|64}_OFFS from
"upgrading" the type of an entire expression to an (unsigned) size_t.*/
-# if INT_MAX>=2147483647
-# define OC_CLZ32_OFFS ((int)sizeof(unsigned)*CHAR_BIT)
-# define OC_CLZ32(_x) (__builtin_clz(_x))
-# elif LONG_MAX>=2147483647L
-# define OC_CLZ32_OFFS ((int)sizeof(unsigned long)*CHAR_BIT)
-# define OC_CLZ32(_x) (__builtin_clzl(_x))
-# endif
-# if INT_MAX>=9223372036854775807LL
-# define OC_CLZ64_OFFS ((int)sizeof(unsigned)*CHAR_BIT)
-# define OC_CLZ64(_x) (__builtin_clz(_x))
-# elif LONG_MAX>=9223372036854775807LL
-# define OC_CLZ64_OFFS ((int)sizeof(unsigned long)*CHAR_BIT)
-# define OC_CLZ64(_x) (__builtin_clzl(_x))
-# elif LLONG_MAX>=9223372036854775807LL|| \
- __LONG_LONG_MAX__>=9223372036854775807LL
-# define OC_CLZ64_OFFS ((int)sizeof(unsigned long long)*CHAR_BIT)
-# define OC_CLZ64(_x) (__builtin_clzll(_x))
-# endif
+# if INT_MAX>=2147483647
+# define OC_CLZ32_OFFS ((int)sizeof(unsigned)*CHAR_BIT)
+# define OC_CLZ32(_x) (__builtin_clz(_x))
+# elif LONG_MAX>=2147483647L
+# define OC_CLZ32_OFFS ((int)sizeof(unsigned long)*CHAR_BIT)
+# define OC_CLZ32(_x) (__builtin_clzl(_x))
+# endif
+# if INT_MAX>=9223372036854775807LL
+# define OC_CLZ64_OFFS ((int)sizeof(unsigned)*CHAR_BIT)
+# define OC_CLZ64(_x) (__builtin_clz(_x))
+# elif LONG_MAX>=9223372036854775807LL
+# define OC_CLZ64_OFFS ((int)sizeof(unsigned long)*CHAR_BIT)
+# define OC_CLZ64(_x) (__builtin_clzl(_x))
+# elif LLONG_MAX>=9223372036854775807LL|| \
+ __LONG_LONG_MAX__>=9223372036854775807LL
+# define OC_CLZ64_OFFS ((int)sizeof(unsigned long long)*CHAR_BIT)
+# define OC_CLZ64(_x) (__builtin_clzll(_x))
# endif
# endif
@@ -134,8 +132,12 @@ int oc_ilog64(ogg_int64_t _v);
# define OC_STATIC_ILOG_64(_v) (OC_STATIC_ILOG6((ogg_int64_t)(_v)))
#define OC_Q57(_v) ((ogg_int64_t)(_v)<<57)
+#define OC_Q10(_v) ((_v)<<10)
ogg_int64_t oc_bexp64(ogg_int64_t _z);
ogg_int64_t oc_blog64(ogg_int64_t _w);
+ogg_uint32_t oc_bexp32_q10(int _z);
+int oc_blog32_q10(ogg_uint32_t _w);
+
#endif
diff --git a/thirdparty/libtheora/mcenc.c b/thirdparty/libtheora/mcenc.c
index 797e81f4f9..82eb824a80 100644
--- a/thirdparty/libtheora/mcenc.c
+++ b/thirdparty/libtheora/mcenc.c
@@ -88,9 +88,11 @@ static const int OC_SQUARE_SITES[11][8]={
};
-static void oc_mcenc_find_candidates(oc_enc_ctx *_enc,oc_mcenc_ctx *_mcenc,
- int _accum[2],int _mbi,int _frame){
+static void oc_mcenc_find_candidates_a(oc_enc_ctx *_enc,oc_mcenc_ctx *_mcenc,
+ oc_mv _accum,int _mbi,int _frame){
oc_mb_enc_info *embs;
+ int accum_x;
+ int accum_y;
int a[3][2];
int ncandidates;
unsigned nmbi;
@@ -102,20 +104,24 @@ static void oc_mcenc_find_candidates(oc_enc_ctx *_enc,oc_mcenc_ctx *_mcenc,
/*Fill in the first part of set A: the vectors from adjacent blocks.*/
for(i=0;i<embs[_mbi].ncneighbors;i++){
nmbi=embs[_mbi].cneighbors[i];
- _mcenc->candidates[ncandidates][0]=embs[nmbi].analysis_mv[0][_frame][0];
- _mcenc->candidates[ncandidates][1]=embs[nmbi].analysis_mv[0][_frame][1];
+ _mcenc->candidates[ncandidates][0]=
+ OC_MV_X(embs[nmbi].analysis_mv[0][_frame]);
+ _mcenc->candidates[ncandidates][1]=
+ OC_MV_Y(embs[nmbi].analysis_mv[0][_frame]);
ncandidates++;
}
}
+ accum_x=OC_MV_X(_accum);
+ accum_y=OC_MV_Y(_accum);
/*Add a few additional vectors to set A: the vectors used in the previous
frames and the (0,0) vector.*/
- _mcenc->candidates[ncandidates][0]=OC_CLAMPI(-31,_accum[0],31);
- _mcenc->candidates[ncandidates][1]=OC_CLAMPI(-31,_accum[1],31);
+ _mcenc->candidates[ncandidates][0]=accum_x;
+ _mcenc->candidates[ncandidates][1]=accum_y;
ncandidates++;
_mcenc->candidates[ncandidates][0]=OC_CLAMPI(-31,
- embs[_mbi].analysis_mv[1][_frame][0]+_accum[0],31);
+ OC_MV_X(embs[_mbi].analysis_mv[1][_frame])+accum_x,31);
_mcenc->candidates[ncandidates][1]=OC_CLAMPI(-31,
- embs[_mbi].analysis_mv[1][_frame][1]+_accum[1],31);
+ OC_MV_Y(embs[_mbi].analysis_mv[1][_frame])+accum_y,31);
ncandidates++;
_mcenc->candidates[ncandidates][0]=0;
_mcenc->candidates[ncandidates][1]=0;
@@ -131,30 +137,33 @@ static void oc_mcenc_find_candidates(oc_enc_ctx *_enc,oc_mcenc_ctx *_mcenc,
OC_SORT2I(a[0][1],a[1][1]);
_mcenc->candidates[0][0]=a[1][0];
_mcenc->candidates[0][1]=a[1][1];
- /*Fill in set B: accelerated predictors for this and adjacent macro blocks.*/
_mcenc->setb0=ncandidates;
- /*The first time through the loop use the current macro block.*/
- nmbi=_mbi;
- for(i=0;;i++){
- _mcenc->candidates[ncandidates][0]=OC_CLAMPI(-31,
- 2*embs[_mbi].analysis_mv[1][_frame][0]
- -embs[_mbi].analysis_mv[2][_frame][0]+_accum[0],31);
- _mcenc->candidates[ncandidates][1]=OC_CLAMPI(-31,
- 2*embs[_mbi].analysis_mv[1][_frame][1]
- -embs[_mbi].analysis_mv[2][_frame][1]+_accum[1],31);
- ncandidates++;
- if(i>=embs[_mbi].npneighbors)break;
- nmbi=embs[_mbi].pneighbors[i];
- }
- /*Truncate to full-pel positions.*/
- for(i=0;i<ncandidates;i++){
- _mcenc->candidates[i][0]=OC_DIV2(_mcenc->candidates[i][0]);
- _mcenc->candidates[i][1]=OC_DIV2(_mcenc->candidates[i][1]);
- }
+}
+
+static void oc_mcenc_find_candidates_b(oc_enc_ctx *_enc,oc_mcenc_ctx *_mcenc,
+ oc_mv _accum,int _mbi,int _frame){
+ oc_mb_enc_info *embs;
+ int accum_x;
+ int accum_y;
+ int ncandidates;
+ embs=_enc->mb_info;
+ accum_x=OC_MV_X(_accum);
+ accum_y=OC_MV_Y(_accum);
+ /*Fill in set B: accelerated predictors for this and adjacent macro blocks.*/
+ ncandidates=_mcenc->setb0;
+ /*Use only the current block. Using more did not appear to be helpful
+ with the current selection logic due to escaping the local search too
+ quickly.*/
+ _mcenc->candidates[ncandidates][0]=OC_CLAMPI(-31,
+ 2*OC_MV_X(embs[_mbi].analysis_mv[1][_frame])
+ -OC_MV_X(embs[_mbi].analysis_mv[2][_frame])+accum_x,31);
+ _mcenc->candidates[ncandidates][1]=OC_CLAMPI(-31,
+ 2*OC_MV_Y(embs[_mbi].analysis_mv[1][_frame])
+ -OC_MV_Y(embs[_mbi].analysis_mv[2][_frame])+accum_y,31);
+ ncandidates++;
_mcenc->ncandidates=ncandidates;
}
-#if 0
static unsigned oc_sad16_halfpel(const oc_enc_ctx *_enc,
const ptrdiff_t *_frag_buf_offs,const ptrdiff_t _fragis[4],
int _mvoffset0,int _mvoffset1,const unsigned char *_src,
@@ -170,20 +179,21 @@ static unsigned oc_sad16_halfpel(const oc_enc_ctx *_enc,
}
return err;
}
-#endif
static unsigned oc_satd16_halfpel(const oc_enc_ctx *_enc,
const ptrdiff_t *_frag_buf_offs,const ptrdiff_t _fragis[4],
int _mvoffset0,int _mvoffset1,const unsigned char *_src,
const unsigned char *_ref,int _ystride,unsigned _best_err){
unsigned err;
+ int dc;
int bi;
err=0;
for(bi=0;bi<4;bi++){
ptrdiff_t frag_offs;
frag_offs=_frag_buf_offs[_fragis[bi]];
- err+=oc_enc_frag_satd2_thresh(_enc,_src+frag_offs,_ref+frag_offs+_mvoffset0,
- _ref+frag_offs+_mvoffset1,_ystride,_best_err-err);
+ err+=oc_enc_frag_satd2(_enc,&dc,_src+frag_offs,
+ _ref+frag_offs+_mvoffset0,_ref+frag_offs+_mvoffset1,_ystride);
+ err+=abs(dc);
}
return err;
}
@@ -219,9 +229,17 @@ static int oc_mcenc_ysatd_check_mbcandidate_fullpel(const oc_enc_ctx *_enc,
err=0;
for(bi=0;bi<4;bi++){
ptrdiff_t frag_offs;
+ int dc;
frag_offs=_frag_buf_offs[_fragis[bi]];
- err+=oc_enc_frag_satd_thresh(_enc,
- _src+frag_offs,_ref+frag_offs+mvoffset,_ystride,UINT_MAX);
+ if(_enc->sp_level<OC_SP_LEVEL_NOSATD){
+ err+=oc_enc_frag_satd(_enc,&dc,
+ _src+frag_offs,_ref+frag_offs+mvoffset,_ystride);
+ err+=abs(dc);
+ }
+ else{
+ err+=oc_enc_frag_sad(_enc,
+ _src+frag_offs,_ref+frag_offs+mvoffset,_ystride);
+ }
}
return err;
}
@@ -229,8 +247,11 @@ static int oc_mcenc_ysatd_check_mbcandidate_fullpel(const oc_enc_ctx *_enc,
static unsigned oc_mcenc_ysatd_check_bcandidate_fullpel(const oc_enc_ctx *_enc,
ptrdiff_t _frag_offs,int _dx,int _dy,
const unsigned char *_src,const unsigned char *_ref,int _ystride){
- return oc_enc_frag_satd_thresh(_enc,
- _src+_frag_offs,_ref+_frag_offs+_dx+_dy*_ystride,_ystride,UINT_MAX);
+ unsigned err;
+ int dc;
+ err=oc_enc_frag_satd(_enc,&dc,
+ _src+_frag_offs,_ref+_frag_offs+_dx+_dy*_ystride,_ystride);
+ return err+abs(dc);
}
/*Perform a motion vector search for this macro block against a single
@@ -239,11 +260,14 @@ static unsigned oc_mcenc_ysatd_check_bcandidate_fullpel(const oc_enc_ctx *_enc,
the work can be shared.
The actual motion vector is stored in the appropriate place in the
oc_mb_enc_info structure.
- _mcenc: The motion compensation context.
- _accum: Drop frame/golden MV accumulators.
- _mbi: The macro block index.
- _frame: The frame to search, either OC_FRAME_PREV or OC_FRAME_GOLD.*/
-void oc_mcenc_search_frame(oc_enc_ctx *_enc,int _accum[2],int _mbi,int _frame){
+ _accum: Drop frame/golden MV accumulators.
+ _mbi: The macro block index.
+ _frame: The frame to use for SATD calculations and refinement,
+ either OC_FRAME_PREV or OC_FRAME_GOLD.
+ _frame_full: The frame to perform the 1px search on, one of OC_FRAME_PREV,
+ OC_FRAME_GOLD, OC_FRAME_PREV_ORIG, or OC_FRAME_GOLD_ORIG.*/
+void oc_mcenc_search_frame(oc_enc_ctx *_enc,oc_mv _accum,int _mbi,int _frame,
+ int _frame_full){
/*Note: Traditionally this search is done using a rate-distortion objective
function of the form D+lambda*R.
However, xiphmont tested this and found it produced a small degredation,
@@ -264,6 +288,7 @@ void oc_mcenc_search_frame(oc_enc_ctx *_enc,int _accum[2],int _mbi,int _frame){
const ptrdiff_t *fragis;
const unsigned char *src;
const unsigned char *ref;
+ const unsigned char *satd_ref;
int ystride;
oc_mb_enc_info *embs;
ogg_int32_t hit_cache[31];
@@ -278,17 +303,18 @@ void oc_mcenc_search_frame(oc_enc_ctx *_enc,int _accum[2],int _mbi,int _frame){
int bi;
embs=_enc->mb_info;
/*Find some candidate motion vectors.*/
- oc_mcenc_find_candidates(_enc,&mcenc,_accum,_mbi,_frame);
+ oc_mcenc_find_candidates_a(_enc,&mcenc,_accum,_mbi,_frame);
/*Clear the cache of locations we've examined.*/
memset(hit_cache,0,sizeof(hit_cache));
/*Start with the median predictor.*/
- candx=mcenc.candidates[0][0];
- candy=mcenc.candidates[0][1];
+ candx=OC_DIV2(mcenc.candidates[0][0]);
+ candy=OC_DIV2(mcenc.candidates[0][1]);
hit_cache[candy+15]|=(ogg_int32_t)1<<candx+15;
frag_buf_offs=_enc->state.frag_buf_offs;
fragis=_enc->state.mb_maps[_mbi][0];
src=_enc->state.ref_frame_data[OC_FRAME_IO];
- ref=_enc->state.ref_frame_data[_enc->state.ref_frame_idx[_frame]];
+ ref=_enc->state.ref_frame_data[_frame_full];
+ satd_ref=_enc->state.ref_frame_data[_frame];
ystride=_enc->state.ref_ystride[0];
/*TODO: customize error function for speed/(quality+size) tradeoff.*/
best_err=oc_mcenc_ysad_check_mbcandidate_fullpel(_enc,
@@ -317,8 +343,8 @@ void oc_mcenc_search_frame(oc_enc_ctx *_enc,int _accum[2],int _mbi,int _frame){
t2+=(t2>>OC_YSAD_THRESH2_SCALE_BITS)+OC_YSAD_THRESH2_OFFSET;
/*Examine the candidates in set A.*/
for(ci=1;ci<mcenc.setb0;ci++){
- candx=mcenc.candidates[ci][0];
- candy=mcenc.candidates[ci][1];
+ candx=OC_DIV2(mcenc.candidates[ci][0]);
+ candy=OC_DIV2(mcenc.candidates[ci][1]);
/*If we've already examined this vector, then we would be using it if it
was better than what we are using.*/
hitbit=(ogg_int32_t)1<<candx+15;
@@ -340,10 +366,11 @@ void oc_mcenc_search_frame(oc_enc_ctx *_enc,int _accum[2],int _mbi,int _frame){
}
}
if(best_err>t2){
+ oc_mcenc_find_candidates_b(_enc,&mcenc,_accum,_mbi,_frame);
/*Examine the candidates in set B.*/
for(;ci<mcenc.ncandidates;ci++){
- candx=mcenc.candidates[ci][0];
- candy=mcenc.candidates[ci][1];
+ candx=OC_DIV2(mcenc.candidates[ci][0]);
+ candy=OC_DIV2(mcenc.candidates[ci][1]);
hitbit=(ogg_int32_t)1<<candx+15;
if(hit_cache[candy+15]&hitbit)continue;
hit_cache[candy+15]|=hitbit;
@@ -475,58 +502,50 @@ void oc_mcenc_search_frame(oc_enc_ctx *_enc,int _accum[2],int _mbi,int _frame){
candx=best_vec[0];
candy=best_vec[1];
embs[_mbi].satd[_frame]=oc_mcenc_ysatd_check_mbcandidate_fullpel(_enc,
- frag_buf_offs,fragis,candx,candy,src,ref,ystride);
- embs[_mbi].analysis_mv[0][_frame][0]=(signed char)(candx<<1);
- embs[_mbi].analysis_mv[0][_frame][1]=(signed char)(candy<<1);
- if(_frame==OC_FRAME_PREV){
+ frag_buf_offs,fragis,candx,candy,src,satd_ref,ystride);
+ embs[_mbi].analysis_mv[0][_frame]=OC_MV(candx<<1,candy<<1);
+ if(_frame==OC_FRAME_PREV&&_enc->sp_level<OC_SP_LEVEL_FAST_ANALYSIS){
for(bi=0;bi<4;bi++){
candx=best_block_vec[bi][0];
candy=best_block_vec[bi][1];
embs[_mbi].block_satd[bi]=oc_mcenc_ysatd_check_bcandidate_fullpel(_enc,
- frag_buf_offs[fragis[bi]],candx,candy,src,ref,ystride);
- embs[_mbi].block_mv[bi][0]=(signed char)(candx<<1);
- embs[_mbi].block_mv[bi][1]=(signed char)(candy<<1);
+ frag_buf_offs[fragis[bi]],candx,candy,src,satd_ref,ystride);
+ embs[_mbi].block_mv[bi]=OC_MV(candx<<1,candy<<1);
}
}
}
void oc_mcenc_search(oc_enc_ctx *_enc,int _mbi){
- oc_mv2 *mvs;
- int accum_p[2];
- int accum_g[2];
+ oc_mv2 *mvs;
+ oc_mv accum_p;
+ oc_mv accum_g;
+ oc_mv mv2_p;
mvs=_enc->mb_info[_mbi].analysis_mv;
- if(_enc->prevframe_dropped){
- accum_p[0]=mvs[0][OC_FRAME_PREV][0];
- accum_p[1]=mvs[0][OC_FRAME_PREV][1];
- }
- else accum_p[1]=accum_p[0]=0;
- accum_g[0]=mvs[2][OC_FRAME_GOLD][0];
- accum_g[1]=mvs[2][OC_FRAME_GOLD][1];
- mvs[0][OC_FRAME_PREV][0]-=mvs[2][OC_FRAME_PREV][0];
- mvs[0][OC_FRAME_PREV][1]-=mvs[2][OC_FRAME_PREV][1];
+ if(_enc->prevframe_dropped)accum_p=mvs[0][OC_FRAME_PREV];
+ else accum_p=0;
+ accum_g=mvs[2][OC_FRAME_GOLD];
/*Move the motion vector predictors back a frame.*/
- memmove(mvs+1,mvs,2*sizeof(*mvs));
+ mv2_p=mvs[2][OC_FRAME_PREV];
+ mvs[2][OC_FRAME_GOLD]=mvs[1][OC_FRAME_GOLD];
+ mvs[2][OC_FRAME_PREV]=mvs[1][OC_FRAME_PREV];
+ mvs[1][OC_FRAME_GOLD]=mvs[0][OC_FRAME_GOLD];
+ mvs[1][OC_FRAME_PREV]=OC_MV_SUB(mvs[0][OC_FRAME_PREV],mv2_p);
/*Search the last frame.*/
- oc_mcenc_search_frame(_enc,accum_p,_mbi,OC_FRAME_PREV);
- mvs[2][OC_FRAME_PREV][0]=accum_p[0];
- mvs[2][OC_FRAME_PREV][1]=accum_p[1];
+ oc_mcenc_search_frame(_enc,accum_p,_mbi,OC_FRAME_PREV,OC_FRAME_PREV_ORIG);
+ mvs[2][OC_FRAME_PREV]=accum_p;
/*GOLDEN MVs are different from PREV MVs in that they're each absolute
offsets from some frame in the past rather than relative offsets from the
frame before.
For predictor calculation to make sense, we need them to be in the same
form as PREV MVs.*/
- mvs[1][OC_FRAME_GOLD][0]-=mvs[2][OC_FRAME_GOLD][0];
- mvs[1][OC_FRAME_GOLD][1]-=mvs[2][OC_FRAME_GOLD][1];
- mvs[2][OC_FRAME_GOLD][0]-=accum_g[0];
- mvs[2][OC_FRAME_GOLD][1]-=accum_g[1];
+ mvs[1][OC_FRAME_GOLD]=OC_MV_SUB(mvs[1][OC_FRAME_GOLD],mvs[2][OC_FRAME_GOLD]);
+ mvs[2][OC_FRAME_GOLD]=OC_MV_SUB(mvs[2][OC_FRAME_GOLD],accum_g);
/*Search the golden frame.*/
- oc_mcenc_search_frame(_enc,accum_g,_mbi,OC_FRAME_GOLD);
+ oc_mcenc_search_frame(_enc,accum_g,_mbi,OC_FRAME_GOLD,OC_FRAME_GOLD_ORIG);
/*Put GOLDEN MVs back into absolute offset form.
The newest MV is already an absolute offset.*/
- mvs[2][OC_FRAME_GOLD][0]+=accum_g[0];
- mvs[2][OC_FRAME_GOLD][1]+=accum_g[1];
- mvs[1][OC_FRAME_GOLD][0]+=mvs[2][OC_FRAME_GOLD][0];
- mvs[1][OC_FRAME_GOLD][1]+=mvs[2][OC_FRAME_GOLD][1];
+ mvs[2][OC_FRAME_GOLD]=OC_MV_ADD(mvs[2][OC_FRAME_GOLD],accum_g);
+ mvs[1][OC_FRAME_GOLD]=OC_MV_ADD(mvs[1][OC_FRAME_GOLD],mvs[2][OC_FRAME_GOLD]);
}
#if 0
@@ -543,7 +562,7 @@ static int oc_mcenc_ysad_halfpel_mbrefine(const oc_enc_ctx *_enc,int _mbi,
int sitei;
int err;
src=_enc->state.ref_frame_data[OC_FRAME_IO];
- ref=_enc->state.ref_frame_data[_enc->state.ref_frame_idx[_framei]];
+ ref=_enc->state.ref_frame_data[_framei];
frag_buf_offs=_enc->state.frag_buf_offs;
fragis=_enc->state.mb_maps[_mbi][0];
ystride=_enc->state.ref_ystride[0];
@@ -598,7 +617,7 @@ static unsigned oc_mcenc_ysatd_halfpel_mbrefine(const oc_enc_ctx *_enc,
int sitei;
int err;
src=_enc->state.ref_frame_data[OC_FRAME_IO];
- ref=_enc->state.ref_frame_data[_enc->state.ref_frame_idx[_frame]];
+ ref=_enc->state.ref_frame_data[_frame];
frag_buf_offs=_enc->state.frag_buf_offs;
fragis=_enc->state.mb_maps[_mbi][0];
ystride=_enc->state.ref_ystride[0];
@@ -627,8 +646,14 @@ static unsigned oc_mcenc_ysatd_halfpel_mbrefine(const oc_enc_ctx *_enc,
ymask=OC_SIGNMASK(((_vec[1]<<1)+dy)^dy);
mvoffset0=mvoffset_base+(dx&xmask)+(offset_y[site]&ymask);
mvoffset1=mvoffset_base+(dx&~xmask)+(offset_y[site]&~ymask);
- err=oc_satd16_halfpel(_enc,frag_buf_offs,fragis,
- mvoffset0,mvoffset1,src,ref,ystride,_best_err);
+ if(_enc->sp_level<OC_SP_LEVEL_NOSATD){
+ err=oc_satd16_halfpel(_enc,frag_buf_offs,fragis,
+ mvoffset0,mvoffset1,src,ref,ystride,_best_err);
+ }
+ else{
+ err=oc_sad16_halfpel(_enc,frag_buf_offs,fragis,
+ mvoffset0,mvoffset1,src,ref,ystride,_best_err);
+ }
if(err<_best_err){
_best_err=err;
best_site=site;
@@ -643,12 +668,11 @@ void oc_mcenc_refine1mv(oc_enc_ctx *_enc,int _mbi,int _frame){
oc_mb_enc_info *embs;
int vec[2];
embs=_enc->mb_info;
- vec[0]=OC_DIV2(embs[_mbi].analysis_mv[0][_frame][0]);
- vec[1]=OC_DIV2(embs[_mbi].analysis_mv[0][_frame][1]);
+ vec[0]=OC_DIV2(OC_MV_X(embs[_mbi].analysis_mv[0][_frame]));
+ vec[1]=OC_DIV2(OC_MV_Y(embs[_mbi].analysis_mv[0][_frame]));
embs[_mbi].satd[_frame]=oc_mcenc_ysatd_halfpel_mbrefine(_enc,
_mbi,vec,embs[_mbi].satd[_frame],_frame);
- embs[_mbi].analysis_mv[0][_frame][0]=(signed char)vec[0];
- embs[_mbi].analysis_mv[0][_frame][1]=(signed char)vec[1];
+ embs[_mbi].analysis_mv[0][_frame]=OC_MV(vec[0],vec[1]);
}
#if 0
@@ -704,6 +728,7 @@ static unsigned oc_mcenc_ysatd_halfpel_brefine(const oc_enc_ctx *_enc,
best_site=4;
for(sitei=0;sitei<8;sitei++){
unsigned err;
+ int dc;
int site;
int xmask;
int ymask;
@@ -723,8 +748,9 @@ static unsigned oc_mcenc_ysatd_halfpel_brefine(const oc_enc_ctx *_enc,
ymask=OC_SIGNMASK(((_vec[1]<<1)+dy)^dy);
mvoffset0=mvoffset_base+(dx&xmask)+(_offset_y[site]&ymask);
mvoffset1=mvoffset_base+(dx&~xmask)+(_offset_y[site]&~ymask);
- err=oc_enc_frag_satd2_thresh(_enc,_src,
- _ref+mvoffset0,_ref+mvoffset1,_ystride,_best_err);
+ err=oc_enc_frag_satd2(_enc,&dc,_src,
+ _ref+mvoffset0,_ref+mvoffset1,_ystride);
+ err+=abs(dc);
if(err<_best_err){
_best_err=err;
best_site=site;
@@ -748,7 +774,7 @@ void oc_mcenc_refine4mv(oc_enc_ctx *_enc,int _mbi){
frag_buf_offs=_enc->state.frag_buf_offs;
fragis=_enc->state.mb_maps[_mbi][0];
src=_enc->state.ref_frame_data[OC_FRAME_IO];
- ref=_enc->state.ref_frame_data[_enc->state.ref_frame_idx[OC_FRAME_PREV]];
+ ref=_enc->state.ref_frame_data[OC_FRAME_PREV];
offset_y[0]=offset_y[1]=offset_y[2]=-ystride;
offset_y[3]=offset_y[5]=0;
offset_y[6]=offset_y[7]=offset_y[8]=ystride;
@@ -757,11 +783,10 @@ void oc_mcenc_refine4mv(oc_enc_ctx *_enc,int _mbi){
ptrdiff_t frag_offs;
int vec[2];
frag_offs=frag_buf_offs[fragis[bi]];
- vec[0]=OC_DIV2(embs[_mbi].block_mv[bi][0]);
- vec[1]=OC_DIV2(embs[_mbi].block_mv[bi][1]);
+ vec[0]=OC_DIV2(OC_MV_X(embs[_mbi].block_mv[bi]));
+ vec[1]=OC_DIV2(OC_MV_Y(embs[_mbi].block_mv[bi]));
embs[_mbi].block_satd[bi]=oc_mcenc_ysatd_halfpel_brefine(_enc,vec,
src+frag_offs,ref+frag_offs,ystride,offset_y,embs[_mbi].block_satd[bi]);
- embs[_mbi].ref_mv[bi][0]=(signed char)vec[0];
- embs[_mbi].ref_mv[bi][1]=(signed char)vec[1];
+ embs[_mbi].ref_mv[bi]=OC_MV(vec[0],vec[1]);
}
}
diff --git a/thirdparty/libtheora/modedec.h b/thirdparty/libtheora/modedec.h
index ea12c64afd..efe640e263 100644
--- a/thirdparty/libtheora/modedec.h
+++ b/thirdparty/libtheora/modedec.h
@@ -1,614 +1,91 @@
/*File generated by libtheora with OC_COLLECT_METRICS defined at compile time.*/
#if !defined(_modedec_H)
# define _modedec_H (1)
+# include "encint.h"
-# if defined(OC_COLLECT_METRICS)
-typedef struct oc_mode_metrics oc_mode_metrics;
+/*The log of the average quantizer for each of the OC_MODE_RD table rows
+ (e.g., for the represented qi's, and each pli and qti), in Q10 format.
+ The actual statistics used by the encoder will be interpolated from
+ that table based on log_plq for the actual quantization matrix used.*/
+# if !defined(OC_COLLECT_METRICS)
+static const
# endif
-typedef struct oc_mode_rd oc_mode_rd;
-
-
-
-/*The number of extra bits of precision at which to store rate metrics.*/
-# define OC_BIT_SCALE (6)
-/*The number of extra bits of precision at which to store RMSE metrics.
- This must be at least half OC_BIT_SCALE (rounded up).*/
-# define OC_RMSE_SCALE (5)
-/*The number of bins to partition statistics into.*/
-# define OC_SAD_BINS (24)
-/*The number of bits of precision to drop from SAD scores to assign them to a
- bin.*/
-# define OC_SAD_SHIFT (9)
-
-
-
-# if defined(OC_COLLECT_METRICS)
-struct oc_mode_metrics{
- double fragw;
- double satd;
- double rate;
- double rmse;
- double satd2;
- double satdrate;
- double rate2;
- double satdrmse;
- double rmse2;
+ogg_int16_t OC_MODE_LOGQ[OC_LOGQ_BINS][3][2]={
+ { {0x1F05,0x2101},{0x206E,0x2101},{0x206E,0x2101} },
+ { {0x1C9A,0x1EAC},{0x1E0E,0x1EAC},{0x1E0E,0x1EAC} },
+ { {0x1A31,0x1C48},{0x1B6F,0x1C48},{0x1B6F,0x1C48} },
+ { {0x17B0,0x19E7},{0x1938,0x19E7},{0x1938,0x19E7} },
+ { {0x152F,0x178F},{0x16AB,0x178F},{0x16AB,0x178F} },
+ { {0x12F1,0x1534},{0x145D,0x1534},{0x145D,0x1534} },
+ { {0x0FF3,0x1321},{0x11BE,0x1321},{0x11BE,0x1321} },
+ { {0x0E1F,0x1073},{0x0E93,0x1073},{0x0E93,0x1073} }
};
-
-int oc_has_mode_metrics;
-oc_mode_metrics OC_MODE_METRICS[64][3][2][OC_SAD_BINS];
-# endif
-
-
-
-struct oc_mode_rd{
- ogg_int16_t rate;
- ogg_int16_t rmse;
-};
-
-
# if !defined(OC_COLLECT_METRICS)
static const
# endif
-oc_mode_rd OC_MODE_RD[64][3][2][OC_SAD_BINS]={
+oc_mode_rd OC_MODE_RD_SATD[OC_LOGQ_BINS][3][2][OC_COMP_BINS]={
{
{
/*Y' qi=0 INTRA*/
{
- { 87, -66},{ 132, 1611},{ 197, 3474},{ 285, 5130},
- { 376, 6419},{ 450, 7545},{ 521, 8587},{ 600, 9587},
- { 689,10498},{ 790,11348},{ 899,12158},{ 1030,12855},
- { 1166,13459},{ 1276,14052},{ 1353,14732},{ 1444,15425},
- { 1535,16101},{ 1609,16856},{ 1697,17532},{ 1823,17995},
- { 1962,18426},{ 2085,18919},{ 2201,19503},{ 2304,20307}
+ { 57, 1550},{ 121, 2460},{ 185, 3901},{ 336, 5189},
+ { 406, 6243},{ 501, 7329},{ 565, 8292},{ 674, 9257},
+ { 746,10219},{ 843,11056},{ 961,11822},{ 1120,12512},
+ { 1208,13233},{ 1394,13600},{ 1409,14381},{ 1492,15129},
+ { 1593,15804},{ 1639,16573},{ 1731,17161},{ 1844,17707},
+ { 1949,18300},{ 2073,18654},{ 2140,19465},{ 2278,19794}
},
/*Y' qi=0 INTER*/
{
- { 32, -105},{ 40, 1268},{ 54, 2919},{ 91, 4559},
- { 118, 6244},{ 132, 7932},{ 142, 9514},{ 149,10989},
- { 155,12375},{ 161,13679},{ 168,14958},{ 176,16215},
- { 187,17431},{ 196,18623},{ 207,19790},{ 218,20941},
- { 230,22083},{ 246,23213},{ 265,24333},{ 292,25439},
- { 328,26512},{ 372,27538},{ 427,28522},{ 494,29479}
+ { -18, 1274},{ 23, 2505},{ 32, 3612},{ 57, 5153},
+ { 79, 6636},{ 97, 8082},{ 109, 9505},{ 122,10924},
+ { 134,12293},{ 145,13634},{ 158,14942},{ 172,16212},
+ { 186,17422},{ 198,18604},{ 209,19757},{ 218,20875},
+ { 235,21980},{ 253,23056},{ 276,24121},{ 305,25184},
+ { 342,26202},{ 393,27140},{ 439,28140},{ 556,28659}
}
},
{
/*Cb qi=0 INTRA*/
{
- { 1, 6},{ 27, 368},{ 52, 738},{ 67, 1171},
- { 80, 1642},{ 99, 2134},{ 110, 2642},{ 112, 3144},
- { 126, 3578},{ 154, 3967},{ 167, 4387},{ 172, 4839},
- { 191, 5278},{ 208, 5666},{ 220, 6036},{ 223, 6398},
- { 227, 6814},{ 253, 7157},{ 284, 7403},{ 292, 7699},
- { 314, 7983},{ 339, 8203},{ 363, 8460},{ 399, 8919}
+ { 32, 1763},{ 56, 2150},{ 78, 2336},{ 88, 2608},
+ { 105, 2975},{ 121, 3297},{ 113, 3460},{ 126, 3993},
+ { 142, 4432},{ 177, 4733},{ 185, 5058},{ 194, 5447},
+ { 220, 5812},{ 227, 6202},{ 246, 6415},{ 269, 6821},
+ { 279, 7026},{ 313, 7313},{ 321, 7708},{ 316, 8021},
+ { 370, 8203},{ 389, 8573},{ 410, 8607},{ 431, 8816}
},
/*Cb qi=0 INTER*/
{
- { 68, -55},{ 63, 275},{ 58, 602},{ 53, 936},
- { 50, 1290},{ 54, 1691},{ 58, 2116},{ 62, 2553},
- { 67, 2992},{ 72, 3422},{ 78, 3843},{ 84, 4253},
- { 89, 4658},{ 94, 5062},{ 98, 5455},{ 100, 5848},
- { 102, 6231},{ 104, 6604},{ 104, 6982},{ 105, 7359},
- { 105, 7733},{ 104, 8104},{ 105, 8465},{ 111, 8828}
+ { 3, 282},{ 3, 1200},{ 3, 1605},{ 6, 2190},
+ { 15, 2519},{ 18, 2798},{ 21, 3115},{ 25, 3460},
+ { 33, 3839},{ 40, 4217},{ 47, 4592},{ 51, 4958},
+ { 56, 5326},{ 59, 5710},{ 63, 6066},{ 65, 6412},
+ { 67, 6762},{ 68, 7104},{ 70, 7461},{ 72, 7829},
+ { 77, 8200},{ 80, 8566},{ 86, 8906},{ 90, 9203}
}
},
{
/*Cr qi=0 INTRA*/
{
- { 1, 8},{ 23, 375},{ 47, 759},{ 63, 1220},
- { 71, 1693},{ 82, 2171},{ 94, 2652},{ 109, 3103},
- { 125, 3567},{ 133, 3995},{ 151, 4375},{ 168, 4819},
- { 174, 5244},{ 190, 5635},{ 215, 6005},{ 242, 6347},
- { 257, 6758},{ 280, 7068},{ 311, 7336},{ 326, 7652},
- { 346, 7968},{ 372, 8213},{ 388, 8515},{ 408, 9060}
+ { 27, 1720},{ 44, 1920},{ 66, 2255},{ 73, 2429},
+ { 95, 2988},{ 103, 3279},{ 123, 3691},{ 129, 4012},
+ { 151, 4415},{ 150, 4760},{ 183, 5008},{ 193, 5351},
+ { 211, 5788},{ 235, 6134},{ 263, 6400},{ 276, 6711},
+ { 291, 7100},{ 346, 7285},{ 329, 7616},{ 387, 7827},
+ { 361, 8214},{ 430, 8534},{ 429, 8608},{ 450, 8823}
},
/*Cr qi=0 INTER*/
{
- { 69, 0},{ 60, 314},{ 49, 624},{ 45, 943},
- { 45, 1285},{ 49, 1691},{ 55, 2130},{ 62, 2560},
- { 71, 2973},{ 79, 3385},{ 85, 3800},{ 89, 4207},
- { 92, 4620},{ 95, 5037},{ 96, 5436},{ 97, 5839},
- { 98, 6252},{ 99, 6653},{ 99, 7038},{ 103, 7426},
- { 107, 7810},{ 108, 8178},{ 107, 8539},{ 106, 8937}
- }
- }
- },
- {
- {
- /*Y' qi=1 INTRA*/
- {
- { 81, -71},{ 133, 1610},{ 203, 3460},{ 296, 5083},
- { 392, 6342},{ 467, 7454},{ 541, 8486},{ 625, 9466},
- { 716,10352},{ 823,11181},{ 940,11961},{ 1074,12643},
- { 1211,13233},{ 1324,13807},{ 1408,14489},{ 1504,15167},
- { 1598,15824},{ 1679,16544},{ 1788,17161},{ 1928,17579},
- { 2070,17991},{ 2202,18456},{ 2324,19021},{ 2425,19894}
- },
- /*Y' qi=1 INTER*/
- {
- { 34, 4},{ 40, 1307},{ 55, 2914},{ 93, 4555},
- { 120, 6243},{ 134, 7912},{ 144, 9468},{ 152,10918},
- { 158,12275},{ 164,13569},{ 171,14846},{ 180,16098},
- { 191,17310},{ 204,18484},{ 216,19636},{ 228,20779},
- { 242,21912},{ 261,23036},{ 286,24146},{ 320,25221},
- { 363,26265},{ 418,27261},{ 485,28203},{ 551,29148}
- }
- },
- {
- /*Cb qi=1 INTRA*/
- {
- { 1, 6},{ 28, 367},{ 52, 738},{ 68, 1172},
- { 86, 1644},{ 106, 2135},{ 115, 2642},{ 119, 3141},
- { 132, 3569},{ 157, 3951},{ 172, 4366},{ 177, 4819},
- { 194, 5258},{ 211, 5638},{ 224, 6006},{ 233, 6367},
- { 236, 6784},{ 258, 7121},{ 299, 7357},{ 319, 7637},
- { 337, 7921},{ 358, 8141},{ 381, 8367},{ 401, 8768}
- },
- /*Cb qi=1 INTER*/
- {
- { 95, -31},{ 81, 295},{ 67, 614},{ 53, 953},
- { 48, 1305},{ 51, 1700},{ 56, 2125},{ 61, 2563},
- { 67, 3008},{ 73, 3435},{ 79, 3844},{ 85, 4251},
- { 90, 4663},{ 95, 5073},{ 98, 5458},{ 100, 5844},
- { 101, 6231},{ 102, 6606},{ 102, 6980},{ 103, 7347},
- { 104, 7726},{ 105, 8096},{ 105, 8453},{ 105, 8789}
- }
- },
- {
- /*Cr qi=1 INTRA*/
- {
- { 1, 8},{ 25, 375},{ 50, 759},{ 65, 1221},
- { 74, 1695},{ 86, 2172},{ 101, 2651},{ 117, 3101},
- { 129, 3561},{ 135, 3985},{ 153, 4368},{ 171, 4807},
- { 182, 5223},{ 202, 5608},{ 225, 5964},{ 251, 6300},
- { 271, 6697},{ 295, 6978},{ 324, 7235},{ 348, 7558},
- { 367, 7877},{ 394, 8101},{ 413, 8386},{ 409, 8945}
- },
- /*Cr qi=1 INTER*/
- {
- { 66, 11},{ 59, 323},{ 51, 631},{ 44, 949},
- { 44, 1292},{ 49, 1703},{ 56, 2140},{ 62, 2566},
- { 69, 2991},{ 77, 3397},{ 84, 3799},{ 89, 4211},
- { 93, 4634},{ 94, 5049},{ 95, 5444},{ 96, 5854},
- { 94, 6260},{ 95, 6640},{ 96, 7032},{ 101, 7423},
- { 104, 7790},{ 105, 8158},{ 109, 8527},{ 108, 8872}
- }
- }
- },
- {
- {
- /*Y' qi=2 INTRA*/
- {
- { 87, -72},{ 139, 1607},{ 213, 3426},{ 315, 4992},
- { 416, 6217},{ 495, 7315},{ 574, 8317},{ 666, 9265},
- { 763,10124},{ 875,10906},{ 1001,11654},{ 1147,12305},
- { 1289,12865},{ 1407,13424},{ 1503,14076},{ 1610,14724},
- { 1720,15342},{ 1815,16020},{ 1937,16579},{ 2084,16981},
- { 2236,17371},{ 2385,17779},{ 2536,18250},{ 2689,18931}
- },
- /*Y' qi=2 INTER*/
- {
- { 30, -2},{ 40, 1308},{ 57, 2921},{ 96, 4567},
- { 122, 6260},{ 136, 7902},{ 148, 9418},{ 156,10826},
- { 162,12157},{ 169,13448},{ 177,14709},{ 188,15938},
- { 200,17133},{ 213,18295},{ 228,19433},{ 245,20564},
- { 264,21685},{ 289,22790},{ 323,23876},{ 368,24916},
- { 427,25906},{ 499,26837},{ 585,27700},{ 680,28514}
- }
- },
- {
- /*Cb qi=2 INTRA*/
- {
- { 1, 6},{ 30, 367},{ 58, 738},{ 77, 1172},
- { 93, 1645},{ 111, 2137},{ 123, 2642},{ 126, 3133},
- { 136, 3553},{ 162, 3934},{ 178, 4352},{ 183, 4803},
- { 199, 5231},{ 220, 5596},{ 235, 5957},{ 245, 6314},
- { 256, 6718},{ 286, 7048},{ 320, 7285},{ 336, 7568},
- { 366, 7829},{ 387, 8045},{ 405, 8261},{ 445, 8550}
- },
- /*Cb qi=2 INTER*/
- {
- { 115, -61},{ 93, 277},{ 71, 609},{ 54, 963},
- { 49, 1329},{ 53, 1715},{ 58, 2138},{ 63, 2583},
- { 69, 3017},{ 75, 3442},{ 81, 3857},{ 88, 4263},
- { 93, 4667},{ 96, 5065},{ 101, 5451},{ 101, 5832},
- { 102, 6213},{ 103, 6593},{ 103, 6968},{ 104, 7336},
- { 104, 7710},{ 105, 8076},{ 106, 8440},{ 106, 8822}
- }
- },
- {
- /*Cr qi=2 INTRA*/
- {
- { 1, 8},{ 27, 375},{ 54, 759},{ 70, 1222},
- { 79, 1696},{ 89, 2173},{ 106, 2652},{ 123, 3098},
- { 135, 3553},{ 143, 3972},{ 161, 4348},{ 181, 4782},
- { 194, 5189},{ 213, 5565},{ 235, 5907},{ 266, 6229},
- { 286, 6618},{ 311, 6897},{ 339, 7152},{ 362, 7454},
- { 392, 7721},{ 416, 7946},{ 429, 8227},{ 458, 8540}
- },
- /*Cr qi=2 INTER*/
- {
- { 74, 20},{ 63, 330},{ 51, 635},{ 44, 942},
- { 47, 1287},{ 54, 1710},{ 59, 2147},{ 65, 2571},
- { 72, 2996},{ 79, 3413},{ 86, 3820},{ 91, 4230},
- { 93, 4642},{ 95, 5046},{ 95, 5442},{ 95, 5839},
- { 96, 6243},{ 97, 6641},{ 99, 7021},{ 101, 7396},
- { 103, 7764},{ 106, 8138},{ 109, 8507},{ 114, 8851}
- }
- }
- },
- {
- {
- /*Y' qi=3 INTRA*/
- {
- { 91, -67},{ 141, 1606},{ 219, 3405},{ 328, 4929},
- { 433, 6122},{ 515, 7209},{ 598, 8204},{ 693, 9145},
- { 796, 9986},{ 912,10756},{ 1045,11471},{ 1200,12079},
- { 1345,12640},{ 1471,13179},{ 1571,13809},{ 1678,14450},
- { 1798,15047},{ 1905,15701},{ 2043,16205},{ 2202,16569},
- { 2351,16971},{ 2501,17393},{ 2660,17851},{ 2825,18455}
- },
- /*Y' qi=3 INTER*/
- {
- { 53, -164},{ 38, 1314},{ 59, 2917},{ 99, 4563},
- { 124, 6253},{ 139, 7882},{ 150, 9375},{ 159,10749},
- { 166,12059},{ 173,13349},{ 183,14608},{ 194,15826},
- { 208,17003},{ 223,18150},{ 240,19287},{ 259,20411},
- { 284,21508},{ 317,22593},{ 359,23656},{ 414,24671},
- { 483,25634},{ 569,26519},{ 670,27332},{ 786,28072}
- }
- },
- {
- /*Cb qi=3 INTRA*/
- {
- { 1, 5},{ 31, 367},{ 58, 739},{ 78, 1173},
- { 96, 1645},{ 113, 2134},{ 125, 2638},{ 133, 3127},
- { 148, 3542},{ 171, 3915},{ 184, 4328},{ 192, 4776},
- { 209, 5197},{ 230, 5556},{ 245, 5909},{ 252, 6261},
- { 272, 6641},{ 304, 6942},{ 330, 7184},{ 342, 7477},
- { 380, 7736},{ 404, 7962},{ 428, 8151},{ 469, 8430}
- },
- /*Cb qi=3 INTER*/
- {
- { 86, -29},{ 72, 296},{ 58, 618},{ 46, 964},
- { 47, 1338},{ 51, 1743},{ 56, 2158},{ 63, 2594},
- { 69, 3035},{ 77, 3455},{ 84, 3859},{ 89, 4266},
- { 94, 4673},{ 98, 5074},{ 101, 5460},{ 101, 5842},
- { 101, 6217},{ 101, 6593},{ 102, 6964},{ 104, 7325},
- { 103, 7696},{ 103, 8056},{ 104, 8430},{ 103, 8792}
- }
- },
- {
- /*Cr qi=3 INTRA*/
- {
- { 1, 8},{ 27, 374},{ 56, 759},{ 74, 1221},
- { 83, 1696},{ 96, 2173},{ 113, 2650},{ 127, 3091},
- { 140, 3542},{ 151, 3960},{ 164, 4334},{ 188, 4764},
- { 208, 5144},{ 224, 5493},{ 250, 5841},{ 278, 6162},
- { 298, 6548},{ 334, 6816},{ 365, 7045},{ 388, 7343},
- { 419, 7613},{ 443, 7836},{ 455, 8105},{ 484, 8445}
- },
- /*Cr qi=3 INTER*/
- {
- { 76, 26},{ 65, 332},{ 53, 638},{ 45, 945},
- { 45, 1304},{ 53, 1725},{ 60, 2153},{ 68, 2584},
- { 74, 3007},{ 81, 3425},{ 87, 3844},{ 91, 4253},
- { 94, 4657},{ 95, 5061},{ 94, 5462},{ 94, 5856},
- { 95, 6250},{ 96, 6635},{ 97, 7014},{ 101, 7393},
- { 104, 7761},{ 106, 8137},{ 109, 8506},{ 111, 8823}
- }
- }
- },
- {
- {
- /*Y' qi=4 INTRA*/
- {
- { 80, -67},{ 143, 1603},{ 227, 3378},{ 344, 4861},
- { 454, 6026},{ 537, 7104},{ 626, 8089},{ 725, 9006},
- { 830, 9827},{ 950,10581},{ 1089,11270},{ 1257,11826},
- { 1409,12366},{ 1535,12912},{ 1640,13528},{ 1753,14173},
- { 1884,14756},{ 2007,15368},{ 2148,15852},{ 2307,16212},
- { 2464,16591},{ 2614,17019},{ 2785,17455},{ 2970,17963}
- },
- /*Y' qi=4 INTER*/
- {
- { 50, -145},{ 38, 1324},{ 61, 2921},{ 102, 4566},
- { 127, 6248},{ 142, 7845},{ 154, 9300},{ 163,10656},
- { 169,11965},{ 177,13246},{ 188,14495},{ 202,15702},
- { 218,16864},{ 236,18003},{ 256,19124},{ 278,20233},
- { 307,21330},{ 347,22398},{ 398,23437},{ 463,24429},
- { 546,25343},{ 649,26170},{ 767,26935},{ 888,27674}
- }
- },
- {
- /*Cb qi=4 INTRA*/
- {
- { 1, 5},{ 33, 367},{ 61, 739},{ 80, 1173},
- { 98, 1646},{ 114, 2136},{ 126, 2639},{ 137, 3124},
- { 152, 3535},{ 176, 3903},{ 194, 4307},{ 206, 4753},
- { 222, 5165},{ 242, 5508},{ 260, 5857},{ 272, 6205},
- { 294, 6559},{ 332, 6848},{ 356, 7104},{ 364, 7389},
- { 396, 7637},{ 415, 7878},{ 446, 8064},{ 506, 8294}
- },
- /*Cb qi=4 INTER*/
- {
- { 86, -15},{ 73, 308},{ 60, 627},{ 46, 967},
- { 47, 1343},{ 51, 1754},{ 56, 2183},{ 63, 2615},
- { 70, 3044},{ 79, 3459},{ 85, 3866},{ 90, 4276},
- { 94, 4686},{ 97, 5088},{ 100, 5467},{ 102, 5837},
- { 102, 6205},{ 101, 6569},{ 103, 6939},{ 104, 7317},
- { 105, 7690},{ 107, 8043},{ 107, 8394},{ 111, 8736}
- }
- },
- {
- /*Cr qi=4 INTRA*/
- {
- { 1, 7},{ 28, 375},{ 57, 759},{ 79, 1221},
- { 92, 1697},{ 105, 2174},{ 122, 2648},{ 135, 3085},
- { 146, 3530},{ 157, 3947},{ 171, 4316},{ 195, 4737},
- { 218, 5117},{ 239, 5445},{ 268, 5767},{ 295, 6074},
- { 315, 6460},{ 355, 6735},{ 392, 6933},{ 418, 7218},
- { 448, 7495},{ 471, 7688},{ 481, 7954},{ 504, 8313}
- },
- /*Cr qi=4 INTER*/
- {
- { 68, 28},{ 57, 334},{ 47, 639},{ 43, 953},
- { 48, 1314},{ 54, 1736},{ 59, 2169},{ 69, 2592},
- { 78, 3017},{ 84, 3434},{ 88, 3850},{ 92, 4260},
- { 95, 4663},{ 96, 5068},{ 95, 5455},{ 95, 5839},
- { 96, 6243},{ 97, 6626},{ 98, 7006},{ 101, 7390},
- { 104, 7755},{ 108, 8115},{ 111, 8471},{ 110, 8825}
- }
- }
- },
- {
- {
- /*Y' qi=5 INTRA*/
- {
- { 84, -69},{ 147, 1599},{ 237, 3350},{ 360, 4796},
- { 475, 5934},{ 562, 6992},{ 657, 7953},{ 765, 8837},
- { 874, 9641},{ 998,10384},{ 1146,11047},{ 1322,11572},
- { 1484,12076},{ 1617,12609},{ 1731,13203},{ 1856,13806},
- { 1995,14367},{ 2132,14936},{ 2289,15386},{ 2460,15721},
- { 2635,16066},{ 2802,16442},{ 2980,16805},{ 3177,17272}
- },
- /*Y' qi=5 INTER*/
- {
- { 38, -86},{ 37, 1349},{ 64, 2920},{ 105, 4563},
- { 129, 6236},{ 145, 7809},{ 158, 9236},{ 167,10572},
- { 174,11871},{ 182,13141},{ 195,14368},{ 212,15558},
- { 230,16706},{ 250,17828},{ 274,18944},{ 303,20041},
- { 342,21116},{ 394,22152},{ 460,23144},{ 543,24073},
- { 648,24919},{ 773,25673},{ 922,26323},{ 1084,26924}
- }
- },
- {
- /*Cb qi=5 INTRA*/
- {
- { 1, 5},{ 34, 367},{ 63, 739},{ 82, 1174},
- { 102, 1647},{ 119, 2137},{ 134, 2639},{ 145, 3121},
- { 161, 3529},{ 189, 3891},{ 207, 4290},{ 216, 4721},
- { 232, 5113},{ 258, 5455},{ 277, 5798},{ 294, 6124},
- { 322, 6427},{ 352, 6697},{ 370, 6982},{ 384, 7283},
- { 423, 7529},{ 448, 7766},{ 478, 7943},{ 527, 8151}
- },
- /*Cb qi=5 INTER*/
- {
- { 83, -49},{ 69, 284},{ 55, 611},{ 48, 961},
- { 49, 1355},{ 52, 1769},{ 58, 2191},{ 65, 2616},
- { 73, 3041},{ 80, 3460},{ 87, 3868},{ 92, 4276},
- { 95, 4682},{ 98, 5077},{ 100, 5459},{ 102, 5827},
- { 102, 6200},{ 102, 6568},{ 103, 6930},{ 103, 7303},
- { 104, 7672},{ 106, 8032},{ 106, 8391},{ 106, 8727}
- }
- },
- {
- /*Cr qi=5 INTRA*/
- {
- { 1, 8},{ 28, 375},{ 57, 760},{ 81, 1222},
- { 99, 1696},{ 111, 2175},{ 125, 2648},{ 140, 3079},
- { 152, 3520},{ 162, 3927},{ 179, 4294},{ 203, 4714},
- { 225, 5080},{ 254, 5389},{ 286, 5703},{ 318, 5997},
- { 342, 6364},{ 380, 6640},{ 416, 6837},{ 445, 7103},
- { 473, 7370},{ 497, 7562},{ 514, 7811},{ 549, 8148}
- },
- /*Cr qi=5 INTER*/
- {
- { 60, 6},{ 54, 323},{ 46, 638},{ 43, 958},
- { 45, 1329},{ 54, 1749},{ 61, 2175},{ 70, 2600},
- { 79, 3021},{ 85, 3437},{ 89, 3847},{ 93, 4254},
- { 95, 4660},{ 96, 5065},{ 95, 5456},{ 95, 5849},
- { 96, 6243},{ 96, 6621},{ 97, 6996},{ 101, 7366},
- { 104, 7722},{ 107, 8088},{ 111, 8448},{ 119, 8816}
- }
- }
- },
- {
- {
- /*Y' qi=6 INTRA*/
- {
- { 88, -69},{ 151, 1593},{ 251, 3294},{ 387, 4681},
- { 507, 5790},{ 601, 6837},{ 702, 7787},{ 813, 8648},
- { 927, 9427},{ 1059,10152},{ 1213,10787},{ 1399,11284},
- { 1568,11781},{ 1705,12312},{ 1823,12890},{ 1957,13482},
- { 2106,14036},{ 2249,14600},{ 2411,15042},{ 2588,15359},
- { 2772,15699},{ 2947,16062},{ 3127,16429},{ 3320,16849}
- },
- /*Y' qi=6 INTER*/
- {
- { 44, -80},{ 36, 1346},{ 69, 2919},{ 111, 4563},
- { 136, 6216},{ 154, 7746},{ 168, 9139},{ 178,10461},
- { 185,11747},{ 195,13007},{ 211,14229},{ 230,15408},
- { 250,16547},{ 274,17663},{ 302,18769},{ 339,19851},
- { 386,20907},{ 446,21933},{ 527,22884},{ 631,23746},
- { 760,24512},{ 914,25178},{ 1087,25758},{ 1278,26262}
- }
- },
- {
- /*Cb qi=6 INTRA*/
- {
- { 1, 4},{ 36, 367},{ 66, 739},{ 84, 1174},
- { 105, 1648},{ 126, 2139},{ 140, 2639},{ 149, 3116},
- { 164, 3523},{ 194, 3880},{ 217, 4271},{ 226, 4694},
- { 243, 5077},{ 270, 5407},{ 291, 5742},{ 310, 6061},
- { 340, 6340},{ 373, 6609},{ 394, 6890},{ 409, 7189},
- { 444, 7434},{ 469, 7652},{ 499, 7853},{ 559, 8135}
- },
- /*Cb qi=6 INTER*/
- {
- { 68, -46},{ 60, 291},{ 50, 623},{ 49, 971},
- { 50, 1357},{ 55, 1781},{ 61, 2211},{ 69, 2634},
- { 78, 3052},{ 86, 3466},{ 91, 3882},{ 95, 4292},
- { 98, 4691},{ 101, 5080},{ 102, 5458},{ 103, 5830},
- { 103, 6192},{ 104, 6554},{ 104, 6916},{ 106, 7278},
- { 108, 7641},{ 110, 8004},{ 112, 8371},{ 112, 8758}
- }
- },
- {
- /*Cr qi=6 INTRA*/
- {
- { 1, 8},{ 29, 375},{ 59, 760},{ 84, 1223},
- { 99, 1698},{ 112, 2176},{ 129, 2647},{ 143, 3076},
- { 156, 3510},{ 168, 3906},{ 189, 4269},{ 220, 4682},
- { 241, 5047},{ 266, 5342},{ 299, 5649},{ 331, 5954},
- { 357, 6309},{ 393, 6579},{ 431, 6765},{ 467, 6997},
- { 501, 7276},{ 520, 7488},{ 525, 7749},{ 548, 8146}
- },
- /*Cr qi=6 INTER*/
- {
- { 94, 31},{ 69, 335},{ 47, 641},{ 43, 967},
- { 50, 1350},{ 57, 1772},{ 65, 2197},{ 74, 2625},
- { 83, 3043},{ 90, 3454},{ 94, 3867},{ 97, 4273},
- { 98, 4671},{ 99, 5068},{ 99, 5461},{ 98, 5857},
- { 98, 6245},{ 99, 6610},{ 103, 6975},{ 105, 7345},
- { 108, 7712},{ 111, 8073},{ 113, 8415},{ 119, 8768}
- }
- }
- },
- {
- {
- /*Y' qi=7 INTRA*/
- {
- { 92, -70},{ 156, 1590},{ 261, 3267},{ 403, 4618},
- { 529, 5704},{ 628, 6730},{ 736, 7657},{ 856, 8491},
- { 978, 9246},{ 1118, 9943},{ 1281,10550},{ 1472,11028},
- { 1645,11507},{ 1793,12008},{ 1924,12565},{ 2067,13130},
- { 2229,13638},{ 2388,14160},{ 2558,14584},{ 2744,14886},
- { 2932,15194},{ 3116,15531},{ 3311,15858},{ 3538,16197}
- },
- /*Y' qi=7 INTER*/
- {
- { 43, -8},{ 36, 1351},{ 71, 2923},{ 112, 4568},
- { 138, 6201},{ 157, 7705},{ 171, 9083},{ 181,10390},
- { 189,11664},{ 202,12910},{ 220,14121},{ 241,15281},
- { 266,16401},{ 295,17507},{ 328,18608},{ 371,19677},
- { 430,20701},{ 508,21676},{ 604,22588},{ 727,23397},
- { 878,24093},{ 1055,24690},{ 1263,25151},{ 1496,25504}
- }
- },
- {
- /*Cb qi=7 INTRA*/
- {
- { 1, 5},{ 40, 367},{ 72, 740},{ 89, 1175},
- { 108, 1649},{ 129, 2140},{ 143, 2637},{ 154, 3110},
- { 169, 3507},{ 198, 3860},{ 224, 4237},{ 235, 4652},
- { 253, 5037},{ 282, 5358},{ 307, 5674},{ 329, 5986},
- { 361, 6273},{ 393, 6527},{ 419, 6777},{ 435, 7078},
- { 467, 7342},{ 495, 7554},{ 529, 7757},{ 591, 8053}
- },
- /*Cb qi=7 INTER*/
- {
- { 79, -33},{ 68, 299},{ 56, 627},{ 50, 978},
- { 51, 1366},{ 55, 1786},{ 61, 2213},{ 70, 2642},
- { 80, 3062},{ 87, 3474},{ 92, 3886},{ 96, 4292},
- { 99, 4684},{ 102, 5072},{ 103, 5450},{ 104, 5814},
- { 104, 6176},{ 104, 6538},{ 107, 6905},{ 110, 7270},
- { 110, 7625},{ 110, 7978},{ 111, 8340},{ 117, 8674}
- }
- },
- {
- /*Cr qi=7 INTRA*/
- {
- { 2, 7},{ 31, 375},{ 62, 760},{ 87, 1223},
- { 103, 1698},{ 115, 2175},{ 131, 2644},{ 147, 3066},
- { 161, 3494},{ 175, 3889},{ 199, 4250},{ 229, 4653},
- { 250, 5001},{ 279, 5275},{ 311, 5577},{ 343, 5889},
- { 376, 6227},{ 417, 6486},{ 457, 6689},{ 484, 6925},
- { 518, 7174},{ 544, 7393},{ 549, 7662},{ 577, 8050}
- },
- /*Cr qi=7 INTER*/
- {
- { 89, 22},{ 62, 332},{ 45, 641},{ 47, 976},
- { 52, 1363},{ 59, 1779},{ 67, 2203},{ 76, 2628},
- { 84, 3046},{ 90, 3460},{ 94, 3875},{ 98, 4272},
- { 99, 4666},{ 98, 5063},{ 98, 5459},{ 98, 5849},
- { 99, 6226},{ 101, 6594},{ 104, 6957},{ 109, 7324},
- { 109, 7686},{ 111, 8042},{ 115, 8379},{ 119, 8699}
- }
- }
- },
- {
- {
- /*Y' qi=8 INTRA*/
- {
- { 91, -69},{ 160, 1585},{ 274, 3226},{ 423, 4538},
- { 557, 5596},{ 664, 6595},{ 778, 7506},{ 905, 8319},
- { 1038, 9035},{ 1186, 9701},{ 1355,10292},{ 1554,10754},
- { 1739,11196},{ 1904,11639},{ 2047,12184},{ 2194,12763},
- { 2361,13256},{ 2529,13753},{ 2709,14155},{ 2902,14433},
- { 3100,14723},{ 3292,15026},{ 3489,15327},{ 3714,15705}
- },
- /*Y' qi=8 INTER*/
- {
- { 32, -157},{ 33, 1346},{ 74, 2914},{ 116, 4554},
- { 142, 6172},{ 162, 7648},{ 177, 9004},{ 186,10300},
- { 196,11570},{ 210,12808},{ 231,14001},{ 256,15150},
- { 285,16259},{ 319,17352},{ 359,18435},{ 415,19475},
- { 489,20470},{ 584,21400},{ 703,22246},{ 852,22968},
- { 1038,23556},{ 1253,24032},{ 1503,24367},{ 1778,24628}
- }
- },
- {
- /*Cb qi=8 INTRA*/
- {
- { 1, 4},{ 42, 367},{ 75, 740},{ 93, 1176},
- { 111, 1649},{ 128, 2139},{ 144, 2635},{ 157, 3103},
- { 174, 3494},{ 206, 3844},{ 233, 4207},{ 251, 4605},
- { 277, 4980},{ 304, 5284},{ 335, 5584},{ 359, 5888},
- { 393, 6152},{ 432, 6398},{ 455, 6656},{ 471, 6956},
- { 502, 7193},{ 528, 7405},{ 562, 7630},{ 603, 7922}
- },
- /*Cb qi=8 INTER*/
- {
- { 77, -37},{ 68, 299},{ 58, 632},{ 50, 991},
- { 50, 1382},{ 55, 1799},{ 62, 2226},{ 73, 2647},
- { 82, 3066},{ 90, 3480},{ 94, 3891},{ 96, 4296},
- { 98, 4687},{ 101, 5073},{ 103, 5456},{ 104, 5817},
- { 105, 6170},{ 106, 6523},{ 107, 6886},{ 108, 7250},
- { 109, 7600},{ 110, 7955},{ 111, 8305},{ 112, 8641}
- }
- },
- {
- /*Cr qi=8 INTRA*/
- {
- { 2, 7},{ 33, 375},{ 64, 760},{ 92, 1224},
- { 111, 1700},{ 122, 2173},{ 137, 2637},{ 156, 3055},
- { 172, 3476},{ 186, 3856},{ 211, 4211},{ 242, 4597},
- { 263, 4939},{ 292, 5214},{ 335, 5489},{ 376, 5772},
- { 406, 6099},{ 440, 6378},{ 483, 6578},{ 517, 6797},
- { 550, 7049},{ 571, 7283},{ 583, 7560},{ 618, 7967}
- },
- /*Cr qi=8 INTER*/
- {
- { 74, 25},{ 58, 328},{ 43, 637},{ 45, 980},
- { 51, 1371},{ 59, 1788},{ 69, 2207},{ 79, 2630},
- { 86, 3051},{ 91, 3470},{ 95, 3880},{ 97, 4280},
- { 98, 4680},{ 97, 5074},{ 96, 5456},{ 97, 5839},
- { 99, 6219},{ 101, 6583},{ 103, 6945},{ 106, 7312},
- { 110, 7671},{ 114, 8009},{ 115, 8345},{ 117, 8686}
+ { 4, 439},{ 2, 1131},{ 3, 1593},{ 6, 2130},
+ { 14, 2535},{ 17, 2786},{ 21, 3128},{ 27, 3494},
+ { 35, 3875},{ 42, 4256},{ 48, 4637},{ 53, 5019},
+ { 57, 5395},{ 61, 5777},{ 64, 6156},{ 66, 6512},
+ { 68, 6853},{ 71, 7183},{ 77, 7511},{ 81, 7841},
+ { 83, 8192},{ 88, 8510},{ 93, 8834},{ 98, 9138}
}
}
},
@@ -616,557 +93,61 @@ oc_mode_rd OC_MODE_RD[64][3][2][OC_SAD_BINS]={
{
/*Y' qi=9 INTRA*/
{
- { 104, -68},{ 164, 1580},{ 288, 3173},{ 448, 4439},
- { 587, 5485},{ 702, 6465},{ 824, 7351},{ 958, 8148},
- { 1096, 8845},{ 1253, 9480},{ 1432,10047},{ 1640,10494},
- { 1835,10926},{ 2015,11350},{ 2166,11871},{ 2321,12428},
- { 2508,12876},{ 2684,13345},{ 2866,13741},{ 3069,13991},
- { 3281,14243},{ 3487,14518},{ 3689,14813},{ 3911,15175}
+ { 76, 777},{ 178, 1995},{ 340, 3162},{ 591, 4097},
+ { 746, 4973},{ 916, 5847},{ 1047, 6687},{ 1218, 7430},
+ { 1385, 8079},{ 1566, 8685},{ 1755, 9167},{ 1992, 9572},
+ { 2164,10023},{ 2395,10270},{ 2536,10755},{ 2694,11285},
+ { 2895,11580},{ 3029,12143},{ 3182,12543},{ 3377,12800},
+ { 3525,13228},{ 3718,13463},{ 3878,13852},{ 4077,14001}
},
/*Y' qi=9 INTER*/
{
- { 47, -140},{ 34, 1348},{ 77, 2915},{ 119, 4552},
- { 145, 6150},{ 166, 7600},{ 182, 8936},{ 192,10221},
- { 203,11482},{ 220,12711},{ 244,13886},{ 274,15012},
- { 308,16111},{ 349,17190},{ 401,18244},{ 470,19257},
- { 561,20209},{ 680,21069},{ 830,21822},{ 1010,22463},
- { 1227,22971},{ 1482,23328},{ 1769,23544},{ 2077,23655}
+ { 10, 770},{ 45, 1845},{ 59, 3227},{ 99, 4708},
+ { 135, 6092},{ 164, 7425},{ 190, 8729},{ 218, 9991},
+ { 246,11234},{ 281,12427},{ 315,13573},{ 354,14678},
+ { 402,15734},{ 467,16728},{ 543,17709},{ 639,18610},
+ { 736,19503},{ 855,20312},{ 995,21033},{ 1151,21656},
+ { 1341,22130},{ 1525,22582},{ 1735,22922},{ 1922,23102}
}
},
{
/*Cb qi=9 INTRA*/
{
- { 1, 5},{ 43, 367},{ 76, 740},{ 95, 1176},
- { 114, 1649},{ 135, 2138},{ 153, 2629},{ 165, 3091},
- { 184, 3481},{ 217, 3831},{ 244, 4187},{ 260, 4572},
- { 290, 4930},{ 320, 5231},{ 351, 5521},{ 379, 5812},
- { 414, 6055},{ 452, 6307},{ 483, 6564},{ 502, 6848},
- { 525, 7115},{ 554, 7321},{ 589, 7533},{ 626, 7833}
+ { 41, 1227},{ 70, 1452},{ 102, 1697},{ 110, 1967},
+ { 134, 2326},{ 153, 2695},{ 160, 3007},{ 196, 3393},
+ { 232, 3769},{ 266, 4067},{ 297, 4376},{ 326, 4728},
+ { 351, 5040},{ 390, 5299},{ 398, 5538},{ 443, 5900},
+ { 448, 6107},{ 506, 6370},{ 519, 6636},{ 525, 6953},
+ { 567, 7177},{ 625, 7386},{ 622, 7613},{ 654, 7764}
},
/*Cb qi=9 INTER*/
{
- { 101, -43},{ 81, 298},{ 62, 637},{ 49, 989},
- { 51, 1381},{ 56, 1806},{ 65, 2231},{ 74, 2653},
- { 84, 3071},{ 91, 3482},{ 95, 3892},{ 97, 4293},
- { 99, 4684},{ 101, 5066},{ 103, 5437},{ 103, 5793},
- { 103, 6148},{ 104, 6511},{ 105, 6867},{ 107, 7221},
- { 110, 7572},{ 111, 7926},{ 112, 8283},{ 116, 8625}
+ { 7, 377},{ 2, 1102},{ 7, 1262},{ 19, 1693},
+ { 22, 1957},{ 27, 2302},{ 35, 2654},{ 43, 3034},
+ { 52, 3431},{ 58, 3826},{ 63, 4207},{ 67, 4570},
+ { 71, 4927},{ 75, 5283},{ 79, 5624},{ 82, 5944},
+ { 85, 6279},{ 88, 6616},{ 94, 6955},{ 102, 7284},
+ { 108, 7622},{ 116, 7944},{ 124, 8293},{ 133, 8568}
}
},
{
/*Cr qi=9 INTRA*/
{
- { 2, 7},{ 35, 375},{ 66, 761},{ 93, 1224},
- { 112, 1700},{ 126, 2173},{ 144, 2633},{ 165, 3047},
- { 183, 3458},{ 199, 3835},{ 224, 4191},{ 257, 4558},
- { 283, 4887},{ 309, 5176},{ 351, 5446},{ 397, 5713},
- { 433, 6017},{ 469, 6283},{ 508, 6480},{ 546, 6687},
- { 579, 6945},{ 600, 7182},{ 610, 7434},{ 623, 7793}
+ { 38, 1217},{ 61, 1473},{ 88, 1650},{ 100, 1908},
+ { 137, 2400},{ 147, 2777},{ 176, 3149},{ 205, 3433},
+ { 227, 3772},{ 249, 4092},{ 286, 4370},{ 313, 4746},
+ { 342, 5053},{ 368, 5261},{ 411, 5530},{ 442, 5859},
+ { 494, 6061},{ 526, 6340},{ 532, 6646},{ 580, 6799},
+ { 567, 7203},{ 649, 7357},{ 625, 7559},{ 660, 7709}
},
/*Cr qi=9 INTER*/
{
- { 77, 15},{ 57, 330},{ 45, 640},{ 48, 980},
- { 54, 1380},{ 61, 1802},{ 70, 2220},{ 80, 2639},
- { 87, 3057},{ 92, 3474},{ 94, 3882},{ 98, 4282},
- { 98, 4675},{ 97, 5062},{ 97, 5450},{ 98, 5829},
- { 100, 6197},{ 101, 6561},{ 104, 6927},{ 107, 7289},
- { 113, 7638},{ 117, 7978},{ 119, 8311},{ 117, 8629}
- }
- }
- },
- {
- {
- /*Y' qi=10 INTRA*/
- {
- { 101, -69},{ 168, 1574},{ 299, 3143},{ 465, 4386},
- { 610, 5410},{ 736, 6353},{ 866, 7207},{ 1006, 7982},
- { 1153, 8655},{ 1319, 9261},{ 1504, 9812},{ 1719,10248},
- { 1928,10653},{ 2116,11056},{ 2282,11550},{ 2458,12070},
- { 2654,12492},{ 2846,12923},{ 3043,13291},{ 3249,13537},
- { 3466,13764},{ 3682,13999},{ 3896,14268},{ 4145,14548}
- },
- /*Y' qi=10 INTER*/
- {
- { 48, -94},{ 34, 1355},{ 81, 2920},{ 124, 4545},
- { 151, 6113},{ 174, 7532},{ 190, 8850},{ 201,10125},
- { 214,11379},{ 235,12591},{ 264,13745},{ 299,14859},
- { 338,15948},{ 388,17008},{ 456,18029},{ 546,18988},
- { 661,19877},{ 808,20666},{ 993,21321},{ 1218,21835},
- { 1481,22203},{ 1783,22420},{ 2117,22504},{ 2469,22481}
- }
- },
- {
- /*Cb qi=10 INTRA*/
- {
- { 2, 4},{ 44, 367},{ 79, 740},{ 99, 1178},
- { 117, 1652},{ 137, 2141},{ 156, 2630},{ 170, 3089},
- { 192, 3474},{ 227, 3813},{ 259, 4157},{ 282, 4526},
- { 310, 4860},{ 342, 5140},{ 377, 5425},{ 400, 5714},
- { 436, 5952},{ 475, 6194},{ 496, 6468},{ 522, 6748},
- { 559, 6996},{ 587, 7216},{ 617, 7433},{ 673, 7678}
- },
- /*Cb qi=10 INTER*/
- {
- { 87, -37},{ 72, 301},{ 58, 636},{ 49, 995},
- { 51, 1394},{ 57, 1819},{ 66, 2241},{ 78, 2660},
- { 87, 3074},{ 93, 3482},{ 97, 3891},{ 99, 4294},
- { 101, 4678},{ 103, 5050},{ 105, 5414},{ 106, 5773},
- { 107, 6134},{ 108, 6485},{ 110, 6832},{ 113, 7187},
- { 113, 7547},{ 114, 7887},{ 117, 8230},{ 112, 8590}
- }
- },
- {
- /*Cr qi=10 INTRA*/
- {
- { 2, 7},{ 38, 375},{ 69, 761},{ 96, 1224},
- { 116, 1701},{ 131, 2175},{ 148, 2634},{ 168, 3041},
- { 190, 3439},{ 211, 3802},{ 238, 4151},{ 271, 4506},
- { 297, 4824},{ 331, 5103},{ 373, 5360},{ 415, 5632},
- { 459, 5928},{ 500, 6176},{ 535, 6386},{ 573, 6586},
- { 608, 6834},{ 629, 7079},{ 642, 7337},{ 686, 7680}
- },
- /*Cr qi=10 INTER*/
- {
- { 81, 34},{ 63, 333},{ 50, 633},{ 48, 987},
- { 53, 1397},{ 61, 1820},{ 71, 2237},{ 83, 2651},
- { 91, 3065},{ 95, 3479},{ 98, 3882},{ 100, 4279},
- { 101, 4673},{ 101, 5054},{ 100, 5429},{ 101, 5801},
- { 102, 6173},{ 104, 6541},{ 108, 6904},{ 110, 7264},
- { 114, 7609},{ 119, 7945},{ 123, 8275},{ 128, 8615}
- }
- }
- },
- {
- {
- /*Y' qi=11 INTRA*/
- {
- { 110, -66},{ 176, 1564},{ 316, 3087},{ 492, 4296},
- { 645, 5299},{ 781, 6217},{ 924, 7039},{ 1075, 7776},
- { 1232, 8421},{ 1410, 9005},{ 1607, 9532},{ 1834, 9929},
- { 2053,10300},{ 2249,10697},{ 2427,11184},{ 2619,11682},
- { 2826,12083},{ 3019,12508},{ 3225,12869},{ 3452,13064},
- { 3670,13280},{ 3890,13519},{ 4123,13750},{ 4367,14059}
- },
- /*Y' qi=11 INTER*/
- {
- { 72, -115},{ 32, 1354},{ 83, 2911},{ 126, 4534},
- { 154, 6080},{ 178, 7475},{ 194, 8779},{ 205,10047},
- { 222,11290},{ 246,12488},{ 281,13621},{ 322,14714},
- { 372,15786},{ 436,16821},{ 519,17813},{ 628,18728},
- { 770,19549},{ 950,20254},{ 1175,20800},{ 1443,21197},
- { 1752,21446},{ 2095,21555},{ 2457,21553},{ 2808,21544}
- }
- },
- {
- /*Cb qi=11 INTRA*/
- {
- { 2, 4},{ 45, 367},{ 81, 740},{ 101, 1177},
- { 121, 1650},{ 142, 2136},{ 159, 2621},{ 174, 3075},
- { 199, 3451},{ 234, 3778},{ 265, 4117},{ 297, 4473},
- { 333, 4789},{ 367, 5054},{ 402, 5319},{ 427, 5613},
- { 462, 5871},{ 503, 6107},{ 532, 6336},{ 560, 6584},
- { 601, 6842},{ 631, 7092},{ 662, 7292},{ 721, 7497}
- },
- /*Cb qi=11 INTER*/
- {
- { 117, -24},{ 93, 308},{ 69, 638},{ 52, 993},
- { 52, 1395},{ 58, 1822},{ 68, 2246},{ 80, 2665},
- { 89, 3082},{ 94, 3492},{ 96, 3900},{ 98, 4299},
- { 101, 4679},{ 103, 5047},{ 104, 5405},{ 106, 5763},
- { 106, 6120},{ 107, 6474},{ 109, 6823},{ 112, 7163},
- { 115, 7516},{ 117, 7868},{ 118, 8213},{ 119, 8561}
- }
- },
- {
- /*Cr qi=11 INTRA*/
- {
- { 2, 7},{ 40, 375},{ 75, 761},{ 100, 1224},
- { 119, 1700},{ 137, 2169},{ 154, 2622},{ 178, 3025},
- { 198, 3416},{ 220, 3770},{ 255, 4114},{ 294, 4459},
- { 323, 4756},{ 359, 5028},{ 399, 5292},{ 438, 5556},
- { 483, 5827},{ 518, 6073},{ 551, 6298},{ 598, 6501},
- { 634, 6754},{ 652, 6997},{ 670, 7211},{ 689, 7560}
- },
- /*Cr qi=11 INTER*/
- {
- { 75, 30},{ 61, 334},{ 51, 639},{ 49, 995},
- { 53, 1403},{ 62, 1821},{ 73, 2237},{ 84, 2654},
- { 91, 3070},{ 95, 3485},{ 96, 3890},{ 98, 4287},
- { 98, 4672},{ 99, 5050},{ 99, 5427},{ 100, 5798},
- { 103, 6169},{ 105, 6528},{ 107, 6881},{ 113, 7233},
- { 118, 7580},{ 121, 7916},{ 125, 8240},{ 130, 8551}
- }
- }
- },
- {
- {
- /*Y' qi=12 INTRA*/
- {
- { 104, -69},{ 182, 1557},{ 335, 3040},{ 521, 4205},
- { 684, 5178},{ 831, 6068},{ 986, 6854},{ 1151, 7559},
- { 1323, 8169},{ 1523, 8704},{ 1736, 9192},{ 1978, 9558},
- { 2213, 9908},{ 2421,10298},{ 2613,10757},{ 2822,11208},
- { 3042,11585},{ 3250,11991},{ 3474,12308},{ 3710,12480},
- { 3939,12687},{ 4174,12902},{ 4416,13102},{ 4672,13369}
- },
- /*Y' qi=12 INTER*/
- {
- { 52, -91},{ 34, 1355},{ 86, 2911},{ 129, 4518},
- { 159, 6037},{ 184, 7405},{ 200, 8694},{ 213, 9955},
- { 232,11185},{ 263,12360},{ 304,13479},{ 354,14555},
- { 415,15601},{ 495,16608},{ 601,17549},{ 738,18400},
- { 915,19136},{ 1139,19724},{ 1414,20150},{ 1731,20412},
- { 2090,20520},{ 2473,20509},{ 2851,20442},{ 3227,20328}
- }
- },
- {
- /*Cb qi=12 INTRA*/
- {
- { 1, 4},{ 46, 367},{ 85, 740},{ 109, 1178},
- { 126, 1650},{ 145, 2134},{ 165, 2617},{ 182, 3061},
- { 209, 3428},{ 245, 3749},{ 281, 4077},{ 316, 4417},
- { 354, 4718},{ 392, 4970},{ 430, 5217},{ 456, 5501},
- { 490, 5771},{ 534, 5996},{ 571, 6207},{ 600, 6458},
- { 644, 6697},{ 675, 6942},{ 707, 7151},{ 766, 7342}
- },
- /*Cb qi=12 INTER*/
- {
- { 84, -24},{ 73, 311},{ 60, 644},{ 52, 998},
- { 53, 1398},{ 60, 1825},{ 71, 2249},{ 83, 2665},
- { 90, 3081},{ 94, 3490},{ 97, 3893},{ 99, 4286},
- { 102, 4663},{ 104, 5032},{ 105, 5393},{ 106, 5751},
- { 107, 6102},{ 108, 6445},{ 111, 6788},{ 113, 7136},
- { 114, 7483},{ 117, 7828},{ 121, 8163},{ 122, 8496}
- }
- },
- {
- /*Cr qi=12 INTRA*/
- {
- { 3, 7},{ 41, 375},{ 78, 761},{ 106, 1225},
- { 124, 1700},{ 140, 2167},{ 163, 2616},{ 188, 3010},
- { 213, 3385},{ 240, 3718},{ 271, 4062},{ 309, 4406},
- { 345, 4691},{ 387, 4956},{ 430, 5212},{ 469, 5467},
- { 513, 5729},{ 554, 5970},{ 587, 6176},{ 633, 6395},
- { 673, 6659},{ 692, 6868},{ 712, 7061},{ 758, 7259}
- },
- /*Cr qi=12 INTER*/
- {
- { 73, 31},{ 59, 335},{ 48, 638},{ 50, 998},
- { 56, 1410},{ 65, 1827},{ 75, 2240},{ 85, 2657},
- { 92, 3073},{ 95, 3485},{ 97, 3888},{ 99, 4279},
- { 98, 4663},{ 99, 5042},{ 101, 5412},{ 102, 5779},
- { 105, 6142},{ 107, 6498},{ 108, 6848},{ 113, 7198},
- { 118, 7540},{ 121, 7867},{ 127, 8188},{ 132, 8508}
- }
- }
- },
- {
- {
- /*Y' qi=13 INTRA*/
- {
- { 109, -68},{ 187, 1551},{ 347, 3010},{ 541, 4153},
- { 709, 5107},{ 864, 5975},{ 1026, 6745},{ 1194, 7433},
- { 1375, 8021},{ 1581, 8550},{ 1803, 9026},{ 2054, 9371},
- { 2301, 9713},{ 2522,10082},{ 2728,10515},{ 2949,10956},
- { 3184,11297},{ 3408,11653},{ 3643,11946},{ 3886,12100},
- { 4124,12277},{ 4377,12459},{ 4632,12635},{ 4898,12861}
- },
- /*Y' qi=13 INTER*/
- {
- { 48, -78},{ 35, 1357},{ 89, 2914},{ 133, 4512},
- { 164, 6004},{ 190, 7348},{ 207, 8627},{ 222, 9881},
- { 247,11096},{ 284,12251},{ 333,13350},{ 392,14407},
- { 466,15426},{ 565,16391},{ 696,17279},{ 865,18058},
- { 1085,18689},{ 1358,19156},{ 1684,19456},{ 2050,19605},
- { 2447,19614},{ 2855,19524},{ 3243,19398},{ 3611,19201}
- }
- },
- {
- /*Cb qi=13 INTRA*/
- {
- { 2, 4},{ 47, 367},{ 86, 741},{ 108, 1179},
- { 127, 1651},{ 150, 2133},{ 173, 2611},{ 194, 3050},
- { 222, 3417},{ 262, 3733},{ 303, 4048},{ 337, 4375},
- { 378, 4657},{ 420, 4897},{ 456, 5148},{ 486, 5422},
- { 518, 5682},{ 558, 5903},{ 592, 6113},{ 623, 6372},
- { 662, 6628},{ 700, 6833},{ 751, 6989},{ 805, 7147}
- },
- /*Cb qi=13 INTER*/
- {
- { 94, -34},{ 78, 303},{ 60, 638},{ 51, 994},
- { 54, 1406},{ 61, 1836},{ 73, 2253},{ 84, 2668},
- { 92, 3082},{ 96, 3492},{ 99, 3894},{ 101, 4284},
- { 103, 4659},{ 105, 5023},{ 106, 5376},{ 108, 5726},
- { 109, 6070},{ 110, 6418},{ 113, 6765},{ 117, 7105},
- { 119, 7448},{ 122, 7784},{ 126, 8119},{ 131, 8463}
- }
- },
- {
- /*Cr qi=13 INTRA*/
- {
- { 3, 7},{ 43, 375},{ 80, 762},{ 110, 1226},
- { 131, 1701},{ 149, 2166},{ 172, 2610},{ 196, 2999},
- { 221, 3359},{ 254, 3679},{ 292, 4005},{ 332, 4329},
- { 369, 4612},{ 408, 4880},{ 456, 5139},{ 500, 5388},
- { 544, 5631},{ 581, 5877},{ 615, 6101},{ 660, 6316},
- { 692, 6594},{ 714, 6795},{ 736, 6997},{ 789, 7290}
- },
- /*Cr qi=13 INTER*/
- {
- { 73, 28},{ 61, 336},{ 46, 642},{ 50, 1003},
- { 58, 1414},{ 67, 1832},{ 79, 2245},{ 87, 2660},
- { 93, 3075},{ 97, 3484},{ 99, 3888},{ 100, 4277},
- { 100, 4651},{ 100, 5027},{ 101, 5403},{ 102, 5765},
- { 105, 6116},{ 109, 6470},{ 113, 6825},{ 119, 7163},
- { 124, 7497},{ 127, 7827},{ 131, 8137},{ 135, 8437}
- }
- }
- },
- {
- {
- /*Y' qi=14 INTRA*/
- {
- { 113, -68},{ 191, 1545},{ 358, 2981},{ 559, 4104},
- { 733, 5044},{ 896, 5890},{ 1066, 6636},{ 1241, 7304},
- { 1428, 7886},{ 1642, 8402},{ 1872, 8871},{ 2128, 9219},
- { 2380, 9547},{ 2609, 9908},{ 2825,10321},{ 3055,10728},
- { 3294,11076},{ 3523,11425},{ 3766,11689},{ 4013,11845},
- { 4254,12022},{ 4506,12209},{ 4759,12383},{ 5013,12637}
- },
- /*Y' qi=14 INTER*/
- {
- { 58, -82},{ 38, 1362},{ 93, 2914},{ 138, 4492},
- { 171, 5962},{ 198, 7289},{ 216, 8559},{ 234, 9804},
- { 263,11005},{ 306,12143},{ 363,13222},{ 434,14259},
- { 523,15255},{ 639,16188},{ 794,17021},{ 1000,17717},
- { 1262,18260},{ 1575,18645},{ 1943,18841},{ 2356,18872},
- { 2782,18802},{ 3194,18682},{ 3576,18559},{ 3923,18447}
- }
- },
- {
- /*Cb qi=14 INTRA*/
- {
- { 2, 3},{ 50, 367},{ 91, 741},{ 114, 1180},
- { 134, 1651},{ 157, 2131},{ 181, 2601},{ 208, 3028},
- { 239, 3391},{ 279, 3706},{ 322, 4000},{ 361, 4309},
- { 406, 4587},{ 445, 4822},{ 482, 5067},{ 515, 5344},
- { 546, 5612},{ 589, 5821},{ 626, 6020},{ 655, 6276},
- { 701, 6523},{ 748, 6717},{ 796, 6876},{ 815, 7151}
- },
- /*Cb qi=14 INTER*/
- {
- { 80, -43},{ 68, 301},{ 56, 644},{ 50, 1004},
- { 54, 1412},{ 63, 1836},{ 75, 2253},{ 87, 2670},
- { 94, 3083},{ 98, 3487},{ 101, 3885},{ 103, 4271},
- { 106, 4645},{ 107, 5004},{ 108, 5358},{ 109, 5705},
- { 112, 6047},{ 115, 6388},{ 118, 6731},{ 121, 7081},
- { 126, 7421},{ 129, 7747},{ 132, 8076},{ 137, 8419}
- }
- },
- {
- /*Cr qi=14 INTRA*/
- {
- { 3, 6},{ 45, 375},{ 85, 762},{ 116, 1226},
- { 138, 1700},{ 158, 2163},{ 180, 2602},{ 206, 2985},
- { 236, 3333},{ 270, 3639},{ 310, 3956},{ 359, 4258},
- { 397, 4524},{ 430, 4802},{ 478, 5068},{ 527, 5316},
- { 572, 5560},{ 613, 5802},{ 654, 6012},{ 699, 6216},
- { 734, 6489},{ 755, 6707},{ 775, 6898},{ 841, 7111}
- },
- /*Cr qi=14 INTER*/
- {
- { 78, 0},{ 59, 322},{ 46, 649},{ 51, 1016},
- { 58, 1422},{ 68, 1839},{ 81, 2253},{ 90, 2666},
- { 95, 3080},{ 98, 3486},{ 101, 3881},{ 102, 4268},
- { 102, 4644},{ 103, 5017},{ 105, 5382},{ 106, 5743},
- { 108, 6093},{ 112, 6442},{ 118, 6791},{ 124, 7130},
- { 127, 7463},{ 133, 7784},{ 138, 8085},{ 142, 8395}
- }
- }
- },
- {
- {
- /*Y' qi=15 INTRA*/
- {
- { 111, -66},{ 197, 1538},{ 370, 2949},{ 579, 4050},
- { 762, 4968},{ 933, 5798},{ 1112, 6520},{ 1299, 7161},
- { 1497, 7725},{ 1723, 8219},{ 1967, 8654},{ 2234, 8990},
- { 2499, 9302},{ 2740, 9637},{ 2968,10039},{ 3215,10414},
- { 3473,10709},{ 3721,11015},{ 3971,11270},{ 4228,11402},
- { 4487,11543},{ 4752,11707},{ 5011,11871},{ 5290,12099}
- },
- /*Y' qi=15 INTER*/
- {
- { 59, -113},{ 37, 1349},{ 95, 2904},{ 139, 4478},
- { 174, 5929},{ 201, 7244},{ 220, 8505},{ 241, 9736},
- { 275,10922},{ 327,12040},{ 395,13097},{ 477,14114},
- { 585,15071},{ 730,15947},{ 917,16714},{ 1162,17326},
- { 1468,17770},{ 1833,18029},{ 2251,18111},{ 2694,18068},
- { 3125,17968},{ 3529,17845},{ 3908,17713},{ 4260,17587}
- }
- },
- {
- /*Cb qi=15 INTRA*/
- {
- { 2, 3},{ 51, 367},{ 94, 741},{ 120, 1180},
- { 140, 1651},{ 160, 2129},{ 184, 2591},{ 213, 3010},
- { 246, 3371},{ 289, 3680},{ 335, 3969},{ 374, 4274},
- { 418, 4546},{ 460, 4783},{ 498, 5019},{ 532, 5280},
- { 565, 5553},{ 608, 5765},{ 647, 5958},{ 683, 6193},
- { 732, 6433},{ 782, 6620},{ 832, 6769},{ 848, 7027}
- },
- /*Cb qi=15 INTER*/
- {
- { 71, -52},{ 63, 296},{ 54, 644},{ 50, 1010},
- { 53, 1417},{ 64, 1837},{ 77, 2253},{ 88, 2666},
- { 95, 3079},{ 98, 3487},{ 100, 3882},{ 103, 4264},
- { 106, 4633},{ 108, 4991},{ 109, 5343},{ 109, 5693},
- { 112, 6038},{ 114, 6371},{ 119, 6709},{ 123, 7051},
- { 125, 7385},{ 130, 7716},{ 135, 8050},{ 140, 8374}
- }
- },
- {
- /*Cr qi=15 INTRA*/
- {
- { 2, 6},{ 47, 375},{ 87, 763},{ 119, 1225},
- { 143, 1699},{ 162, 2158},{ 185, 2595},{ 213, 2971},
- { 246, 3315},{ 279, 3618},{ 320, 3920},{ 372, 4210},
- { 409, 4480},{ 446, 4756},{ 496, 5017},{ 542, 5263},
- { 590, 5487},{ 639, 5721},{ 687, 5923},{ 724, 6132},
- { 753, 6417},{ 781, 6622},{ 805, 6806},{ 856, 6977}
- },
- /*Cr qi=15 INTER*/
- {
- { 71, 3},{ 61, 326},{ 52, 651},{ 50, 1017},
- { 58, 1422},{ 69, 1837},{ 82, 2251},{ 90, 2668},
- { 95, 3080},{ 98, 3484},{ 101, 3877},{ 102, 4257},
- { 102, 4632},{ 101, 5005},{ 103, 5370},{ 106, 5733},
- { 110, 6082},{ 116, 6424},{ 120, 6774},{ 124, 7106},
- { 130, 7427},{ 135, 7748},{ 141, 8052},{ 147, 8333}
- }
- }
- },
- {
- {
- /*Y' qi=16 INTRA*/
- {
- { 114, -63},{ 206, 1525},{ 396, 2887},{ 618, 3945},
- { 816, 4832},{ 1002, 5626},{ 1196, 6319},{ 1401, 6923},
- { 1616, 7458},{ 1857, 7928},{ 2121, 8334},{ 2405, 8645},
- { 2685, 8934},{ 2938, 9255},{ 3175, 9638},{ 3433, 9990},
- { 3707,10263},{ 3958,10577},{ 4218,10807},{ 4488,10906},
- { 4760,11028},{ 5037,11148},{ 5306,11286},{ 5625,11463}
- },
- /*Y' qi=16 INTER*/
- {
- { 69, -153},{ 39, 1348},{ 98, 2894},{ 144, 4448},
- { 181, 5872},{ 209, 7167},{ 228, 8422},{ 254, 9644},
- { 297,10810},{ 359,11908},{ 438,12944},{ 539,13930},
- { 672,14842},{ 850,15650},{ 1085,16318},{ 1391,16793},
- { 1769,17082},{ 2200,17198},{ 2659,17174},{ 3116,17072},
- { 3547,16948},{ 3943,16819},{ 4299,16701},{ 4611,16644}
- }
- },
- {
- /*Cb qi=16 INTRA*/
- {
- { 3, 4},{ 54, 367},{ 97, 742},{ 122, 1181},
- { 143, 1651},{ 168, 2123},{ 197, 2575},{ 226, 2985},
- { 263, 3338},{ 314, 3631},{ 367, 3903},{ 409, 4200},
- { 453, 4468},{ 491, 4703},{ 528, 4932},{ 566, 5188},
- { 601, 5459},{ 647, 5672},{ 693, 5844},{ 734, 6058},
- { 784, 6305},{ 836, 6460},{ 882, 6602},{ 905, 6891}
- },
- /*Cb qi=16 INTER*/
- {
- { 75, -64},{ 67, 292},{ 56, 645},{ 51, 1016},
- { 54, 1421},{ 66, 1842},{ 79, 2257},{ 89, 2670},
- { 95, 3082},{ 98, 3488},{ 101, 3879},{ 104, 4258},
- { 106, 4623},{ 108, 4974},{ 109, 5321},{ 113, 5664},
- { 116, 6001},{ 117, 6341},{ 123, 6677},{ 128, 7004},
- { 130, 7336},{ 136, 7671},{ 143, 7996},{ 148, 8310}
- }
- },
- {
- /*Cr qi=16 INTRA*/
- {
- { 4, 7},{ 50, 375},{ 90, 763},{ 124, 1225},
- { 148, 1698},{ 168, 2154},{ 195, 2582},{ 227, 2948},
- { 263, 3279},{ 302, 3575},{ 343, 3865},{ 394, 4137},
- { 439, 4402},{ 482, 4672},{ 533, 4925},{ 579, 5165},
- { 626, 5382},{ 675, 5616},{ 725, 5812},{ 769, 5991},
- { 810, 6242},{ 848, 6430},{ 868, 6615},{ 944, 6732}
- },
- /*Cr qi=16 INTER*/
- {
- { 78, 11},{ 62, 327},{ 49, 650},{ 50, 1025},
- { 59, 1431},{ 72, 1841},{ 83, 2253},{ 90, 2671},
- { 95, 3084},{ 98, 3487},{ 100, 3879},{ 101, 4254},
- { 102, 4625},{ 103, 4994},{ 106, 5355},{ 108, 5708},
- { 111, 6058},{ 115, 6400},{ 121, 6733},{ 128, 7058},
- { 134, 7374},{ 140, 7691},{ 146, 7993},{ 146, 8317}
- }
- }
- },
- {
- {
- /*Y' qi=17 INTRA*/
- {
- { 112, -59},{ 210, 1515},{ 409, 2850},{ 640, 3882},
- { 844, 4748},{ 1038, 5529},{ 1240, 6206},{ 1452, 6803},
- { 1676, 7330},{ 1925, 7792},{ 2194, 8201},{ 2483, 8512},
- { 2766, 8801},{ 3027, 9121},{ 3279, 9482},{ 3548, 9810},
- { 3825,10069},{ 4088,10345},{ 4362,10544},{ 4638,10644},
- { 4915,10744},{ 5196,10850},{ 5471,10981},{ 5802,11136}
- },
- /*Y' qi=17 INTER*/
- {
- { 70, -147},{ 45, 1349},{ 106, 2894},{ 155, 4425},
- { 195, 5818},{ 225, 7099},{ 247, 8348},{ 278, 9565},
- { 328,10717},{ 399,11794},{ 491,12807},{ 609,13760},
- { 766,14623},{ 984,15349},{ 1274,15902},{ 1642,16256},
- { 2082,16411},{ 2563,16409},{ 3048,16315},{ 3508,16194},
- { 3924,16064},{ 4306,15938},{ 4656,15828},{ 4966,15733}
- }
- },
- {
- /*Cb qi=17 INTRA*/
- {
- { 3, 4},{ 57, 367},{ 101, 742},{ 126, 1182},
- { 148, 1650},{ 175, 2118},{ 207, 2565},{ 241, 2966},
- { 279, 3307},{ 331, 3588},{ 389, 3845},{ 435, 4132},
- { 474, 4408},{ 517, 4641},{ 560, 4869},{ 602, 5122},
- { 638, 5389},{ 672, 5610},{ 716, 5787},{ 758, 6002},
- { 817, 6226},{ 869, 6393},{ 916, 6530},{ 950, 6799}
- },
- /*Cb qi=17 INTER*/
- {
- { 105, -65},{ 86, 288},{ 66, 638},{ 54, 1014},
- { 59, 1427},{ 71, 1844},{ 86, 2257},{ 95, 2668},
- { 100, 3075},{ 103, 3476},{ 106, 3867},{ 110, 4241},
- { 112, 4598},{ 114, 4948},{ 117, 5294},{ 121, 5633},
- { 123, 5968},{ 126, 6301},{ 131, 6637},{ 136, 6968},
- { 144, 7287},{ 152, 7606},{ 158, 7931},{ 162, 8262}
- }
- },
- {
- /*Cr qi=17 INTRA*/
- {
- { 4, 6},{ 55, 376},{ 97, 765},{ 128, 1226},
- { 152, 1696},{ 175, 2144},{ 204, 2568},{ 241, 2928},
- { 282, 3250},{ 323, 3530},{ 368, 3811},{ 420, 4089},
- { 463, 4347},{ 505, 4609},{ 562, 4860},{ 609, 5094},
- { 655, 5303},{ 709, 5535},{ 759, 5740},{ 803, 5913},
- { 844, 6153},{ 879, 6350},{ 905, 6527},{ 972, 6637}
- },
- /*Cr qi=17 INTER*/
- {
- { 88, 8},{ 68, 330},{ 51, 653},{ 54, 1028},
- { 65, 1433},{ 77, 1845},{ 89, 2257},{ 96, 2669},
- { 100, 3081},{ 102, 3481},{ 105, 3867},{ 106, 4245},
- { 108, 4613},{ 110, 4971},{ 112, 5328},{ 115, 5679},
- { 120, 6019},{ 127, 6355},{ 133, 6686},{ 140, 7007},
- { 149, 7316},{ 158, 7618},{ 166, 7924},{ 170, 8232}
+ { 5, 408},{ 3, 1197},{ 7, 1275},{ 16, 1695},
+ { 22, 1979},{ 30, 2324},{ 38, 2691},{ 47, 3071},
+ { 53, 3462},{ 59, 3857},{ 64, 4255},{ 69, 4612},
+ { 74, 4975},{ 76, 5347},{ 81, 5694},{ 86, 6020},
+ { 91, 6357},{ 96, 6687},{ 102, 7020},{ 108, 7351},
+ { 115, 7663},{ 122, 7979},{ 125, 8298},{ 136, 8576}
}
}
},
@@ -1174,557 +155,61 @@ oc_mode_rd OC_MODE_RD[64][3][2][OC_SAD_BINS]={
{
/*Y' qi=18 INTRA*/
{
- { 122, -58},{ 216, 1506},{ 425, 2815},{ 665, 3822},
- { 882, 4666},{ 1088, 5425},{ 1301, 6084},{ 1529, 6653},
- { 1766, 7162},{ 2026, 7611},{ 2312, 7987},{ 2612, 8278},
- { 2913, 8551},{ 3196, 8840},{ 3454, 9184},{ 3734, 9490},
- { 4030, 9725},{ 4305, 9973},{ 4585,10162},{ 4864,10251},
- { 5150,10324},{ 5443,10420},{ 5727,10536},{ 6053,10682}
+ { 83, 534},{ 261, 1697},{ 507, 2691},{ 852, 3418},
+ { 1127, 4094},{ 1378, 4775},{ 1626, 5442},{ 1905, 5975},
+ { 2164, 6468},{ 2445, 6913},{ 2704, 7301},{ 3001, 7631},
+ { 3285, 7934},{ 3536, 8217},{ 3837, 8489},{ 4076, 8814},
+ { 4325, 9046},{ 4590, 9313},{ 4794, 9546},{ 5062, 9751},
+ { 5285, 9963},{ 5578,10079},{ 5777,10302},{ 6054,10296}
},
/*Y' qi=18 INTER*/
{
- { 66, -143},{ 47, 1351},{ 108, 2886},{ 158, 4401},
- { 200, 5775},{ 232, 7044},{ 256, 8288},{ 292, 9493},
- { 351,10625},{ 434,11679},{ 541,12665},{ 681,13578},
- { 875,14379},{ 1136,15025},{ 1483,15475},{ 1914,15709},
- { 2399,15767},{ 2907,15699},{ 3400,15579},{ 3852,15453},
- { 4259,15332},{ 4630,15221},{ 4976,15121},{ 5294,15061}
+ { 33, 490},{ 62, 1599},{ 96, 3015},{ 164, 4378},
+ { 225, 5633},{ 285, 6831},{ 351, 7999},{ 427, 9133},
+ { 526,10181},{ 652,11141},{ 829,11991},{ 1049,12732},
+ { 1310,13367},{ 1592,13896},{ 1881,14350},{ 2207,14667},
+ { 2529,14877},{ 2873,14980},{ 3231,14949},{ 3571,14926},
+ { 3922,14816},{ 4246,14715},{ 4559,14579},{ 4778,14590}
}
},
{
/*Cb qi=18 INTRA*/
{
- { 2, 3},{ 61, 367},{ 107, 743},{ 131, 1182},
- { 155, 1648},{ 183, 2110},{ 220, 2542},{ 260, 2927},
- { 303, 3265},{ 359, 3540},{ 416, 3785},{ 462, 4063},
- { 506, 4334},{ 553, 4567},{ 595, 4797},{ 636, 5049},
- { 676, 5304},{ 717, 5516},{ 759, 5698},{ 801, 5904},
- { 861, 6133},{ 911, 6311},{ 962, 6443},{ 1021, 6645}
+ { 55, 825},{ 95, 1021},{ 131, 1276},{ 150, 1618},
+ { 180, 1958},{ 220, 2306},{ 256, 2608},{ 322, 2939},
+ { 385, 3239},{ 436, 3530},{ 475, 3771},{ 518, 4078},
+ { 557, 4348},{ 604, 4592},{ 620, 4851},{ 676, 5083},
+ { 704, 5363},{ 739, 5582},{ 788, 5782},{ 819, 6000},
+ { 893, 6158},{ 940, 6418},{ 984, 6499},{ 1035, 6596}
},
/*Cb qi=18 INTER*/
{
- { 126, 5},{ 95, 326},{ 66, 643},{ 55, 1015},
- { 60, 1427},{ 73, 1843},{ 87, 2256},{ 96, 2667},
- { 101, 3073},{ 104, 3470},{ 108, 3853},{ 111, 4226},
- { 114, 4584},{ 117, 4928},{ 119, 5274},{ 122, 5612},
- { 126, 5942},{ 130, 6271},{ 136, 6606},{ 141, 6931},
- { 148, 7247},{ 156, 7568},{ 164, 7891},{ 173, 8211}
+ { -2, 642},{ 12, 771},{ 20, 1054},{ 29, 1394},
+ { 35, 1721},{ 45, 2080},{ 53, 2450},{ 63, 2835},
+ { 73, 3225},{ 81, 3596},{ 87, 3952},{ 95, 4300},
+ { 102, 4634},{ 109, 4959},{ 115, 5283},{ 120, 5608},
+ { 130, 5931},{ 139, 6254},{ 152, 6571},{ 163, 6887},
+ { 179, 7204},{ 191, 7508},{ 198, 7834},{ 224, 8066}
}
},
{
/*Cr qi=18 INTRA*/
{
- { 4, 6},{ 59, 376},{ 104, 765},{ 133, 1226},
- { 156, 1692},{ 184, 2136},{ 218, 2548},{ 260, 2893},
- { 308, 3204},{ 348, 3481},{ 397, 3751},{ 448, 4024},
- { 490, 4281},{ 541, 4523},{ 593, 4776},{ 634, 5022},
- { 685, 5236},{ 748, 5455},{ 812, 5638},{ 856, 5818},
- { 891, 6048},{ 928, 6230},{ 961, 6405},{ 1055, 6449}
+ { 49, 780},{ 86, 986},{ 120, 1261},{ 137, 1588},
+ { 183, 1998},{ 228, 2339},{ 291, 2670},{ 334, 2938},
+ { 376, 3239},{ 412, 3522},{ 459, 3783},{ 490, 4113},
+ { 547, 4321},{ 593, 4571},{ 640, 4828},{ 675, 5137},
+ { 730, 5254},{ 774, 5524},{ 821, 5754},{ 859, 5911},
+ { 887, 6178},{ 982, 6266},{ 941, 6536},{ 996, 6630}
},
/*Cr qi=18 INTER*/
{
- { 81, 34},{ 68, 342},{ 57, 652},{ 59, 1027},
- { 67, 1439},{ 80, 1848},{ 91, 2257},{ 97, 2670},
- { 100, 3076},{ 103, 3473},{ 106, 3857},{ 108, 4231},
- { 109, 4599},{ 110, 4958},{ 113, 5307},{ 119, 5650},
- { 125, 5991},{ 130, 6325},{ 138, 6651},{ 147, 6971},
- { 153, 7278},{ 162, 7578},{ 172, 7874},{ 177, 8156}
- }
- }
- },
- {
- {
- /*Y' qi=19 INTRA*/
- {
- { 128, -55},{ 228, 1495},{ 448, 2775},{ 699, 3758},
- { 931, 4571},{ 1154, 5296},{ 1386, 5914},{ 1636, 6450},
- { 1894, 6930},{ 2177, 7342},{ 2479, 7698},{ 2792, 7976},
- { 3099, 8235},{ 3392, 8517},{ 3658, 8853},{ 3938, 9155},
- { 4242, 9371},{ 4527, 9605},{ 4810, 9781},{ 5089, 9853},
- { 5378, 9920},{ 5674,10009},{ 5972,10110},{ 6336,10196}
- },
- /*Y' qi=19 INTER*/
- {
- { 69, -147},{ 49, 1353},{ 111, 2883},{ 162, 4381},
- { 205, 5737},{ 237, 6996},{ 264, 8232},{ 307, 9421},
- { 376,10534},{ 472,11567},{ 596,12525},{ 761,13395},
- { 990,14130},{ 1298,14694},{ 1695,15053},{ 2172,15195},
- { 2696,15173},{ 3213,15075},{ 3696,14948},{ 4141,14829},
- { 4541,14721},{ 4910,14609},{ 5245,14506},{ 5536,14399}
- }
- },
- {
- /*Cb qi=19 INTRA*/
- {
- { 3, 3},{ 61, 367},{ 109, 743},{ 135, 1182},
- { 161, 1646},{ 191, 2101},{ 229, 2524},{ 273, 2898},
- { 318, 3221},{ 376, 3490},{ 436, 3731},{ 487, 3994},
- { 539, 4251},{ 584, 4485},{ 621, 4721},{ 664, 4967},
- { 709, 5225},{ 752, 5431},{ 801, 5595},{ 846, 5796},
- { 912, 6011},{ 959, 6193},{ 1015, 6321},{ 1121, 6504}
- },
- /*Cb qi=19 INTER*/
- {
- { 126, 4},{ 97, 329},{ 69, 649},{ 56, 1017},
- { 61, 1432},{ 74, 1846},{ 88, 2255},{ 98, 2663},
- { 103, 3065},{ 106, 3460},{ 110, 3844},{ 114, 4211},
- { 117, 4564},{ 120, 4911},{ 122, 5253},{ 125, 5588},
- { 129, 5916},{ 135, 6241},{ 142, 6567},{ 149, 6885},
- { 155, 7206},{ 163, 7527},{ 174, 7843},{ 188, 8145}
- }
- },
- {
- /*Cr qi=19 INTRA*/
- {
- { 5, 6},{ 61, 376},{ 106, 765},{ 135, 1225},
- { 160, 1689},{ 192, 2126},{ 229, 2531},{ 271, 2869},
- { 321, 3168},{ 370, 3433},{ 421, 3704},{ 476, 3965},
- { 520, 4212},{ 572, 4452},{ 629, 4691},{ 671, 4939},
- { 724, 5152},{ 792, 5347},{ 858, 5510},{ 895, 5696},
- { 939, 5905},{ 991, 6056},{ 1027, 6244},{ 1127, 6333}
- },
- /*Cr qi=19 INTER*/
- {
- { 80, 45},{ 66, 344},{ 55, 654},{ 56, 1030},
- { 66, 1440},{ 80, 1850},{ 91, 2259},{ 98, 2668},
- { 102, 3072},{ 104, 3466},{ 107, 3845},{ 109, 4215},
- { 110, 4578},{ 112, 4933},{ 116, 5283},{ 122, 5625},
- { 129, 5963},{ 136, 6287},{ 143, 6611},{ 151, 6927},
- { 160, 7229},{ 170, 7528},{ 181, 7818},{ 191, 8092}
- }
- }
- },
- {
- {
- /*Y' qi=20 INTRA*/
- {
- { 129, -50},{ 238, 1481},{ 469, 2728},{ 730, 3684},
- { 974, 4473},{ 1213, 5171},{ 1463, 5763},{ 1729, 6281},
- { 2002, 6744},{ 2299, 7146},{ 2613, 7492},{ 2940, 7746},
- { 3265, 7978},{ 3571, 8228},{ 3853, 8543},{ 4156, 8815},
- { 4476, 9001},{ 4775, 9218},{ 5070, 9373},{ 5352, 9446},
- { 5649, 9510},{ 5956, 9580},{ 6268, 9660},{ 6647, 9705}
- },
- /*Y' qi=20 INTER*/
- {
- { 64, -93},{ 52, 1340},{ 116, 2862},{ 170, 4344},
- { 216, 5678},{ 249, 6928},{ 281, 8155},{ 333, 9326},
- { 418,10410},{ 533,11411},{ 683,12329},{ 890,13127},
- { 1183,13750},{ 1579,14162},{ 2066,14357},{ 2611,14370},
- { 3159,14284},{ 3675,14167},{ 4142,14053},{ 4568,13953},
- { 4961,13852},{ 5320,13755},{ 5649,13675},{ 5933,13610}
- }
- },
- {
- /*Cb qi=20 INTRA*/
- {
- { 3, 3},{ 62, 367},{ 112, 743},{ 140, 1183},
- { 165, 1646},{ 196, 2099},{ 235, 2517},{ 284, 2883},
- { 334, 3198},{ 393, 3460},{ 457, 3690},{ 509, 3945},
- { 560, 4198},{ 605, 4435},{ 647, 4658},{ 699, 4888},
- { 742, 5155},{ 788, 5350},{ 835, 5517},{ 880, 5730},
- { 956, 5914},{ 1007, 6060},{ 1053, 6199},{ 1158, 6358}
- },
- /*Cb qi=20 INTER*/
- {
- { 128, -6},{ 96, 322},{ 66, 653},{ 54, 1025},
- { 63, 1431},{ 79, 1844},{ 91, 2256},{ 99, 2665},
- { 104, 3065},{ 107, 3455},{ 111, 3831},{ 115, 4189},
- { 120, 4539},{ 123, 4885},{ 126, 5219},{ 130, 5548},
- { 135, 5876},{ 141, 6199},{ 149, 6519},{ 156, 6837},
- { 166, 7153},{ 179, 7468},{ 189, 7784},{ 194, 8102}
- }
- },
- {
- /*Cr qi=20 INTRA*/
- {
- { 4, 6},{ 63, 376},{ 109, 765},{ 139, 1225},
- { 165, 1689},{ 199, 2124},{ 239, 2523},{ 285, 2852},
- { 340, 3140},{ 388, 3398},{ 438, 3662},{ 499, 3914},
- { 547, 4155},{ 596, 4392},{ 652, 4634},{ 699, 4877},
- { 759, 5074},{ 824, 5257},{ 883, 5428},{ 936, 5589},
- { 986, 5790},{ 1030, 5960},{ 1074, 6119},{ 1172, 6191}
- },
- /*Cr qi=20 INTER*/
- {
- { 92, 40},{ 70, 345},{ 55, 658},{ 57, 1034},
- { 69, 1441},{ 84, 1852},{ 94, 2261},{ 98, 2669},
- { 102, 3074},{ 105, 3465},{ 107, 3841},{ 110, 4206},
- { 112, 4562},{ 116, 4915},{ 121, 5260},{ 127, 5591},
- { 134, 5920},{ 142, 6246},{ 153, 6562},{ 163, 6870},
- { 173, 7170},{ 186, 7463},{ 198, 7746},{ 199, 8030}
- }
- }
- },
- {
- {
- /*Y' qi=21 INTRA*/
- {
- { 130, -51},{ 244, 1476},{ 483, 2705},{ 756, 3635},
- { 1013, 4396},{ 1266, 5070},{ 1530, 5647},{ 1806, 6153},
- { 2093, 6600},{ 2411, 6976},{ 2739, 7299},{ 3079, 7534},
- { 3422, 7744},{ 3738, 7987},{ 4032, 8274},{ 4348, 8533},
- { 4675, 8721},{ 4989, 8909},{ 5291, 9051},{ 5577, 9111},
- { 5879, 9163},{ 6190, 9228},{ 6506, 9286},{ 6899, 9295}
- },
- /*Y' qi=21 INTER*/
- {
- { 64, -56},{ 55, 1341},{ 119, 2859},{ 174, 4324},
- { 223, 5640},{ 258, 6880},{ 295, 8096},{ 359, 9246},
- { 460,10302},{ 595,11268},{ 778,12131},{ 1032,12857},
- { 1387,13385},{ 1850,13683},{ 2399,13774},{ 2976,13729},
- { 3527,13619},{ 4034,13504},{ 4492,13401},{ 4912,13291},
- { 5298,13209},{ 5648,13137},{ 5974,13046},{ 6308,12977}
- }
- },
- {
- /*Cb qi=21 INTRA*/
- {
- { 4, 3},{ 64, 367},{ 114, 743},{ 141, 1183},
- { 166, 1645},{ 201, 2092},{ 247, 2502},{ 299, 2856},
- { 352, 3158},{ 413, 3412},{ 480, 3642},{ 536, 3893},
- { 588, 4137},{ 637, 4367},{ 678, 4598},{ 725, 4834},
- { 774, 5083},{ 827, 5269},{ 883, 5420},{ 930, 5633},
- { 999, 5829},{ 1057, 5959},{ 1113, 6082},{ 1200, 6265}
- },
- /*Cb qi=21 INTER*/
- {
- { 109, -8},{ 84, 321},{ 62, 654},{ 54, 1028},
- { 64, 1434},{ 80, 1847},{ 92, 2259},{ 100, 2664},
- { 105, 3060},{ 109, 3445},{ 114, 3815},{ 118, 4172},
- { 122, 4519},{ 126, 4861},{ 128, 5194},{ 133, 5520},
- { 139, 5847},{ 146, 6169},{ 155, 6487},{ 166, 6801},
- { 177, 7114},{ 189, 7423},{ 201, 7729},{ 208, 8035}
- }
- },
- {
- /*Cr qi=21 INTRA*/
- {
- { 4, 6},{ 64, 377},{ 111, 766},{ 144, 1225},
- { 174, 1683},{ 206, 2114},{ 248, 2506},{ 302, 2824},
- { 357, 3099},{ 404, 3357},{ 455, 3622},{ 519, 3867},
- { 573, 4098},{ 625, 4331},{ 683, 4571},{ 733, 4802},
- { 793, 4994},{ 863, 5173},{ 926, 5337},{ 978, 5492},
- { 1030, 5685},{ 1079, 5856},{ 1126, 6027},{ 1217, 6159}
- },
- /*Cr qi=21 INTER*/
- {
- { 82, 29},{ 67, 341},{ 55, 660},{ 58, 1038},
- { 71, 1443},{ 85, 1851},{ 95, 2258},{ 99, 2666},
- { 103, 3069},{ 107, 3456},{ 110, 3826},{ 112, 4188},
- { 114, 4544},{ 118, 4891},{ 124, 5231},{ 132, 5567},
- { 139, 5894},{ 148, 6210},{ 159, 6520},{ 171, 6822},
- { 185, 7111},{ 196, 7403},{ 209, 7691},{ 225, 7945}
- }
- }
- },
- {
- {
- /*Y' qi=22 INTRA*/
- {
- { 128, -45},{ 254, 1463},{ 507, 2662},{ 794, 3562},
- { 1070, 4292},{ 1340, 4941},{ 1622, 5492},{ 1920, 5968},
- { 2229, 6387},{ 2565, 6742},{ 2911, 7047},{ 3263, 7264},
- { 3615, 7464},{ 3944, 7689},{ 4258, 7950},{ 4591, 8183},
- { 4934, 8347},{ 5259, 8517},{ 5573, 8634},{ 5870, 8683},
- { 6186, 8723},{ 6508, 8762},{ 6831, 8801},{ 7232, 8830}
- },
- /*Y' qi=22 INTER*/
- {
- { 77, -48},{ 57, 1343},{ 122, 2853},{ 180, 4299},
- { 231, 5597},{ 269, 6826},{ 314, 8025},{ 393, 9150},
- { 512,10179},{ 673,11103},{ 894,11908},{ 1207,12542},
- { 1635,12956},{ 2166,13148},{ 2755,13167},{ 3345,13088},
- { 3895,12966},{ 4386,12848},{ 4832,12746},{ 5252,12647},
- { 5634,12563},{ 5978,12497},{ 6299,12412},{ 6633,12338}
- }
- },
- {
- /*Cb qi=22 INTRA*/
- {
- { 4, 3},{ 66, 367},{ 122, 744},{ 153, 1182},
- { 177, 1640},{ 213, 2080},{ 263, 2475},{ 323, 2811},
- { 382, 3103},{ 451, 3346},{ 522, 3568},{ 581, 3814},
- { 633, 4054},{ 674, 4288},{ 719, 4523},{ 768, 4756},
- { 823, 4979},{ 883, 5162},{ 937, 5325},{ 996, 5510},
- { 1070, 5687},{ 1129, 5807},{ 1193, 5929},{ 1311, 6099}
- },
- /*Cb qi=22 INTER*/
- {
- { 107, -5},{ 83, 322},{ 61, 653},{ 55, 1030},
- { 66, 1436},{ 81, 1845},{ 94, 2253},{ 102, 2656},
- { 107, 3050},{ 111, 3435},{ 115, 3804},{ 119, 4158},
- { 124, 4501},{ 128, 4835},{ 132, 5164},{ 138, 5490},
- { 146, 5812},{ 154, 6128},{ 163, 6442},{ 174, 6754},
- { 188, 7060},{ 205, 7361},{ 219, 7662},{ 233, 7953}
- }
- },
- {
- /*Cr qi=22 INTRA*/
- {
- { 4, 6},{ 67, 378},{ 118, 767},{ 151, 1222},
- { 182, 1675},{ 221, 2097},{ 269, 2476},{ 329, 2774},
- { 389, 3039},{ 444, 3292},{ 500, 3545},{ 560, 3788},
- { 615, 4020},{ 671, 4251},{ 734, 4484},{ 781, 4712},
- { 850, 4887},{ 925, 5060},{ 981, 5229},{ 1031, 5369},
- { 1092, 5549},{ 1148, 5715},{ 1200, 5861},{ 1291, 5943}
- },
- /*Cr qi=22 INTER*/
- {
- { 88, 34},{ 69, 340},{ 57, 657},{ 60, 1039},
- { 73, 1445},{ 87, 1851},{ 96, 2257},{ 100, 2662},
- { 103, 3058},{ 107, 3442},{ 111, 3812},{ 115, 4172},
- { 118, 4524},{ 123, 4864},{ 129, 5199},{ 136, 5531},
- { 145, 5855},{ 156, 6168},{ 170, 6468},{ 184, 6765},
- { 193, 7066},{ 207, 7353},{ 222, 7628},{ 230, 7900}
- }
- }
- },
- {
- {
- /*Y' qi=23 INTRA*/
- {
- { 126, -40},{ 257, 1458},{ 521, 2636},{ 825, 3501},
- { 1111, 4207},{ 1391, 4842},{ 1684, 5385},{ 1992, 5858},
- { 2311, 6277},{ 2653, 6626},{ 3005, 6929},{ 3366, 7134},
- { 3729, 7311},{ 4071, 7526},{ 4396, 7770},{ 4734, 7986},
- { 5086, 8131},{ 5421, 8286},{ 5735, 8404},{ 6033, 8456},
- { 6357, 8486},{ 6682, 8525},{ 7003, 8573},{ 7387, 8604}
- },
- /*Y' qi=23 INTER*/
- {
- { 64, -57},{ 60, 1345},{ 124, 2853},{ 185, 4284},
- { 239, 5565},{ 282, 6783},{ 336, 7967},{ 429, 9069},
- { 568,10063},{ 758,10943},{ 1028,11679},{ 1407,12216},
- { 1909,12520},{ 2502,12616},{ 3126,12573},{ 3722,12461},
- { 4258,12344},{ 4742,12236},{ 5185,12136},{ 5590,12052},
- { 5970,11980},{ 6315,11901},{ 6631,11826},{ 6954,11769}
- }
- },
- {
- /*Cb qi=23 INTRA*/
- {
- { 3, 3},{ 70, 367},{ 124, 744},{ 151, 1182},
- { 181, 1637},{ 222, 2071},{ 276, 2460},{ 343, 2785},
- { 403, 3072},{ 468, 3317},{ 542, 3534},{ 605, 3773},
- { 659, 4009},{ 703, 4243},{ 747, 4479},{ 795, 4707},
- { 852, 4923},{ 908, 5105},{ 972, 5254},{ 1043, 5423},
- { 1118, 5594},{ 1172, 5731},{ 1240, 5853},{ 1365, 6005}
- },
- /*Cb qi=23 INTER*/
- {
- { 109, -10},{ 87, 325},{ 63, 650},{ 57, 1031},
- { 67, 1439},{ 83, 1847},{ 96, 2253},{ 103, 2652},
- { 109, 3041},{ 114, 3421},{ 117, 3789},{ 122, 4141},
- { 128, 4480},{ 134, 4811},{ 139, 5138},{ 144, 5463},
- { 152, 5781},{ 161, 6096},{ 174, 6404},{ 185, 6714},
- { 198, 7023},{ 216, 7320},{ 233, 7621},{ 245, 7935}
- }
- },
- {
- /*Cr qi=23 INTRA*/
- {
- { 5, 6},{ 70, 379},{ 122, 768},{ 155, 1222},
- { 187, 1671},{ 231, 2088},{ 283, 2459},{ 346, 2750},
- { 411, 3009},{ 465, 3261},{ 523, 3509},{ 585, 3746},
- { 639, 3980},{ 695, 4219},{ 754, 4449},{ 803, 4671},
- { 873, 4840},{ 953, 5001},{ 1015, 5156},{ 1071, 5286},
- { 1137, 5464},{ 1191, 5629},{ 1249, 5782},{ 1359, 5885}
- },
- /*Cr qi=23 INTER*/
- {
- { 84, 29},{ 69, 343},{ 58, 660},{ 62, 1041},
- { 75, 1448},{ 88, 1853},{ 97, 2258},{ 102, 2659},
- { 105, 3050},{ 108, 3430},{ 113, 3799},{ 116, 4155},
- { 121, 4505},{ 126, 4845},{ 132, 5176},{ 142, 5504},
- { 153, 5826},{ 165, 6133},{ 180, 6432},{ 197, 6722},
- { 212, 7005},{ 226, 7287},{ 244, 7555},{ 258, 7828}
- }
- }
- },
- {
- {
- /*Y' qi=24 INTRA*/
- {
- { 125, -34},{ 268, 1444},{ 547, 2590},{ 866, 3422},
- { 1172, 4098},{ 1476, 4702},{ 1790, 5222},{ 2117, 5678},
- { 2453, 6080},{ 2811, 6418},{ 3178, 6700},{ 3552, 6895},
- { 3928, 7055},{ 4286, 7243},{ 4627, 7477},{ 4981, 7674},
- { 5344, 7802},{ 5683, 7944},{ 6009, 8043},{ 6313, 8082},
- { 6633, 8111},{ 6959, 8151},{ 7280, 8197},{ 7660, 8221}
- },
- /*Y' qi=24 INTER*/
- {
- { 62, -63},{ 68, 1345},{ 134, 2840},{ 199, 4245},
- { 256, 5508},{ 304, 6715},{ 371, 7880},{ 484, 8950},
- { 652, 9899},{ 892,10709},{ 1238,11334},{ 1722,11722},
- { 2326,11875},{ 2983,11864},{ 3616,11783},{ 4189,11678},
- { 4707,11570},{ 5178,11476},{ 5617,11395},{ 6017,11319},
- { 6380,11252},{ 6720,11185},{ 7044,11126},{ 7377,11118}
- }
- },
- {
- /*Cb qi=24 INTRA*/
- {
- { 4, 3},{ 75, 367},{ 132, 745},{ 159, 1182},
- { 187, 1634},{ 230, 2061},{ 289, 2439},{ 361, 2753},
- { 425, 3034},{ 492, 3278},{ 566, 3490},{ 630, 3720},
- { 686, 3956},{ 732, 4190},{ 777, 4420},{ 829, 4637},
- { 894, 4840},{ 958, 5012},{ 1023, 5155},{ 1090, 5326},
- { 1165, 5502},{ 1226, 5622},{ 1299, 5717},{ 1408, 5887}
- },
- /*Cb qi=24 INTER*/
- {
- { 110, 35},{ 92, 337},{ 70, 651},{ 63, 1033},
- { 74, 1440},{ 91, 1846},{ 102, 2248},{ 109, 2644},
- { 114, 3031},{ 120, 3404},{ 127, 3762},{ 133, 4109},
- { 138, 4445},{ 144, 4772},{ 151, 5094},{ 159, 5411},
- { 168, 5728},{ 180, 6037},{ 195, 6338},{ 210, 6640},
- { 227, 6944},{ 249, 7236},{ 272, 7528},{ 299, 7809}
- }
- },
- {
- /*Cr qi=24 INTRA*/
- {
- { 5, 6},{ 72, 380},{ 124, 770},{ 158, 1222},
- { 195, 1668},{ 240, 2079},{ 297, 2438},{ 367, 2715},
- { 433, 2966},{ 488, 3218},{ 549, 3467},{ 609, 3701},
- { 664, 3935},{ 728, 4165},{ 792, 4379},{ 845, 4586},
- { 917, 4744},{ 995, 4898},{ 1063, 5049},{ 1120, 5187},
- { 1190, 5359},{ 1249, 5522},{ 1304, 5672},{ 1397, 5806}
- },
- /*Cr qi=24 INTER*/
- {
- { 91, 56},{ 73, 353},{ 61, 664},{ 66, 1045},
- { 80, 1449},{ 95, 1851},{ 103, 2250},{ 107, 2648},
- { 111, 3038},{ 116, 3413},{ 120, 3774},{ 124, 4128},
- { 130, 4471},{ 138, 4802},{ 145, 5130},{ 156, 5453},
- { 171, 5764},{ 187, 6061},{ 204, 6355},{ 220, 6643},
- { 238, 6923},{ 254, 7204},{ 275, 7475},{ 289, 7752}
- }
- }
- },
- {
- {
- /*Y' qi=25 INTRA*/
- {
- { 125, -28},{ 285, 1426},{ 582, 2540},{ 917, 3351},
- { 1244, 3997},{ 1569, 4570},{ 1903, 5071},{ 2258, 5498},
- { 2626, 5866},{ 3002, 6182},{ 3382, 6448},{ 3770, 6623},
- { 4162, 6760},{ 4528, 6934},{ 4882, 7144},{ 5249, 7328},
- { 5610, 7453},{ 5958, 7578},{ 6291, 7672},{ 6597, 7708},
- { 6928, 7715},{ 7258, 7737},{ 7575, 7781},{ 7950, 7829}
- },
- /*Y' qi=25 INTER*/
- {
- { 64, -16},{ 72, 1348},{ 139, 2832},{ 206, 4218},
- { 268, 5465},{ 322, 6659},{ 403, 7803},{ 540, 8838},
- { 747, 9734},{ 1044,10465},{ 1473,10981},{ 2048,11249},
- { 2717,11311},{ 3397,11257},{ 4025,11161},{ 4589,11052},
- { 5099,10947},{ 5560,10859},{ 5989,10786},{ 6389,10717},
- { 6753,10652},{ 7078,10592},{ 7389,10535},{ 7697,10460}
- }
- },
- {
- /*Cb qi=25 INTRA*/
- {
- { 3, 3},{ 78, 368},{ 133, 745},{ 159, 1180},
- { 193, 1627},{ 242, 2046},{ 304, 2411},{ 381, 2714},
- { 456, 2983},{ 527, 3224},{ 598, 3437},{ 667, 3655},
- { 726, 3888},{ 776, 4117},{ 826, 4333},{ 883, 4543},
- { 954, 4727},{ 1019, 4878},{ 1095, 5014},{ 1171, 5187},
- { 1255, 5342},{ 1319, 5458},{ 1396, 5546},{ 1536, 5678}
- },
- /*Cb qi=25 INTER*/
- {
- { 117, 32},{ 89, 342},{ 67, 660},{ 64, 1037},
- { 77, 1441},{ 93, 1845},{ 105, 2243},{ 113, 2633},
- { 120, 3016},{ 125, 3387},{ 131, 3739},{ 137, 4080},
- { 144, 4416},{ 152, 4741},{ 160, 5057},{ 169, 5369},
- { 180, 5680},{ 193, 5990},{ 209, 6294},{ 227, 6594},
- { 249, 6888},{ 269, 7180},{ 294, 7467},{ 317, 7768}
- }
- },
- {
- /*Cr qi=25 INTRA*/
- {
- { 6, 6},{ 74, 380},{ 129, 770},{ 165, 1220},
- { 201, 1658},{ 253, 2061},{ 315, 2410},{ 388, 2676},
- { 462, 2920},{ 523, 3166},{ 584, 3404},{ 647, 3637},
- { 701, 3870},{ 769, 4086},{ 838, 4296},{ 898, 4491},
- { 980, 4627},{ 1065, 4759},{ 1126, 4920},{ 1187, 5058},
- { 1283, 5180},{ 1347, 5332},{ 1404, 5475},{ 1527, 5534}
- },
- /*Cr qi=25 INTER*/
- {
- { 92, 41},{ 75, 347},{ 64, 664},{ 70, 1045},
- { 85, 1448},{ 98, 1849},{ 105, 2245},{ 110, 2637},
- { 115, 3023},{ 120, 3395},{ 126, 3753},{ 131, 4102},
- { 136, 4439},{ 145, 4768},{ 156, 5094},{ 168, 5410},
- { 184, 5717},{ 203, 6010},{ 221, 6300},{ 239, 6577},
- { 262, 6847},{ 282, 7123},{ 303, 7390},{ 322, 7665}
- }
- }
- },
- {
- {
- /*Y' qi=26 INTRA*/
- {
- { 130, -24},{ 292, 1423},{ 594, 2525},{ 943, 3307},
- { 1289, 3921},{ 1633, 4467},{ 1991, 4943},{ 2368, 5348},
- { 2753, 5696},{ 3148, 5991},{ 3545, 6247},{ 3942, 6415},
- { 4342, 6535},{ 4726, 6690},{ 5093, 6883},{ 5466, 7047},
- { 5840, 7159},{ 6202, 7274},{ 6545, 7351},{ 6855, 7375},
- { 7186, 7384},{ 7517, 7416},{ 7840, 7447},{ 8238, 7450}
- },
- /*Y' qi=26 INTER*/
- {
- { 52, 16},{ 75, 1336},{ 143, 2815},{ 213, 4191},
- { 278, 5427},{ 339, 6611},{ 436, 7734},{ 600, 8732},
- { 843, 9579},{ 1195,10243},{ 1702,10660},{ 2355,10825},
- { 3070,10820},{ 3755,10743},{ 4372,10643},{ 4925,10538},
- { 5426,10440},{ 5882,10354},{ 6296,10290},{ 6686,10224},
- { 7049,10163},{ 7380,10113},{ 7672,10062},{ 7937,10021}
- }
- },
- {
- /*Cb qi=26 INTRA*/
- {
- { 4, 3},{ 79, 368},{ 138, 745},{ 167, 1180},
- { 200, 1623},{ 252, 2034},{ 322, 2389},{ 403, 2682},
- { 480, 2941},{ 558, 3176},{ 631, 3393},{ 700, 3608},
- { 766, 3825},{ 819, 4046},{ 868, 4265},{ 926, 4472},
- { 1002, 4645},{ 1070, 4800},{ 1151, 4924},{ 1242, 5063},
- { 1325, 5221},{ 1393, 5338},{ 1464, 5431},{ 1595, 5559}
- },
- /*Cb qi=26 INTER*/
- {
- { 98, 33},{ 83, 343},{ 65, 662},{ 65, 1037},
- { 80, 1437},{ 96, 1839},{ 107, 2238},{ 115, 2628},
- { 122, 3007},{ 128, 3373},{ 134, 3722},{ 142, 4060},
- { 149, 4390},{ 158, 4713},{ 167, 5029},{ 178, 5341},
- { 191, 5647},{ 208, 5948},{ 227, 6244},{ 247, 6539},
- { 269, 6833},{ 295, 7114},{ 328, 7388},{ 369, 7658}
- }
- },
- {
- /*Cr qi=26 INTRA*/
- {
- { 5, 6},{ 75, 380},{ 133, 769},{ 172, 1217},
- { 212, 1652},{ 266, 2048},{ 333, 2384},{ 412, 2643},
- { 490, 2880},{ 552, 3124},{ 616, 3365},{ 681, 3594},
- { 739, 3816},{ 810, 4024},{ 880, 4224},{ 945, 4405},
- { 1029, 4538},{ 1114, 4674},{ 1183, 4822},{ 1254, 4946},
- { 1346, 5063},{ 1417, 5201},{ 1478, 5345},{ 1597, 5411}
- },
- /*Cr qi=26 INTER*/
- {
- { 97, 29},{ 75, 342},{ 62, 667},{ 70, 1047},
- { 87, 1447},{ 100, 1846},{ 107, 2242},{ 113, 2633},
- { 118, 3016},{ 123, 3382},{ 128, 3737},{ 135, 4082},
- { 142, 4417},{ 151, 4746},{ 162, 5066},{ 176, 5377},
- { 194, 5679},{ 217, 5963},{ 239, 6244},{ 260, 6522},
- { 284, 6789},{ 309, 7052},{ 335, 7313},{ 355, 7582}
+ { 0, 741},{ 9, 743},{ 16, 1034},{ 26, 1385},
+ { 39, 1741},{ 48, 2090},{ 56, 2459},{ 64, 2850},
+ { 72, 3242},{ 81, 3622},{ 89, 3980},{ 98, 4323},
+ { 104, 4667},{ 110, 5005},{ 118, 5337},{ 126, 5675},
+ { 137, 5998},{ 146, 6311},{ 156, 6621},{ 170, 6914},
+ { 181, 7205},{ 196, 7490},{ 203, 7779},{ 232, 8012}
}
}
},
@@ -1732,557 +217,61 @@ oc_mode_rd OC_MODE_RD[64][3][2][OC_SAD_BINS]={
{
/*Y' qi=27 INTRA*/
{
- { 118, -10},{ 308, 1404},{ 630, 2473},{ 997, 3227},
- { 1360, 3819},{ 1719, 4354},{ 2086, 4829},{ 2470, 5233},
- { 2863, 5576},{ 3267, 5870},{ 3677, 6117},{ 4085, 6268},
- { 4499, 6376},{ 4888, 6521},{ 5257, 6705},{ 5638, 6865},
- { 6020, 6962},{ 6394, 7056},{ 6744, 7130},{ 7051, 7158},
- { 7386, 7164},{ 7717, 7185},{ 8042, 7209},{ 8444, 7206}
+ { 121, 378},{ 379, 1464},{ 810, 2335},{ 1447, 2725},
+ { 1851, 3194},{ 2311, 3655},{ 2747, 4081},{ 3211, 4393},
+ { 3640, 4672},{ 4056, 4933},{ 4427, 5150},{ 4842, 5259},
+ { 5220, 5381},{ 5584, 5443},{ 5925, 5648},{ 6233, 5783},
+ { 6547, 5944},{ 6905, 6056},{ 7203, 6181},{ 7526, 6207},
+ { 7800, 6330},{ 8175, 6312},{ 8415, 6437},{ 8705, 6459}
},
/*Y' qi=27 INTER*/
{
- { 54, 19},{ 77, 1333},{ 147, 2806},{ 221, 4166},
- { 290, 5390},{ 360, 6564},{ 474, 7665},{ 664, 8630},
- { 949, 9423},{ 1370,10002},{ 1958,10323},{ 2670,10414},
- { 3406,10375},{ 4086,10285},{ 4691,10182},{ 5233,10085},
- { 5724, 9994},{ 6169, 9918},{ 6582, 9863},{ 6962, 9813},
- { 7316, 9759},{ 7645, 9707},{ 7948, 9660},{ 8262, 9623}
+ { 48, 199},{ 90, 1458},{ 167, 2824},{ 291, 4050},
+ { 434, 5144},{ 638, 6133},{ 901, 7011},{ 1249, 7743},
+ { 1726, 8280},{ 2317, 8616},{ 2957, 8789},{ 3561, 8896},
+ { 4126, 8936},{ 4646, 8933},{ 5115, 8931},{ 5579, 8890},
+ { 6008, 8804},{ 6411, 8744},{ 6774, 8646},{ 7153, 8549},
+ { 7475, 8462},{ 7790, 8372},{ 8069, 8280},{ 8299, 8278}
}
},
{
/*Cb qi=27 INTRA*/
{
- { 4, 3},{ 79, 368},{ 137, 745},{ 166, 1180},
- { 200, 1622},{ 253, 2030},{ 324, 2381},{ 407, 2671},
- { 487, 2925},{ 567, 3156},{ 640, 3372},{ 712, 3580},
- { 782, 3792},{ 833, 4015},{ 887, 4227},{ 954, 4422},
- { 1031, 4592},{ 1103, 4738},{ 1187, 4856},{ 1280, 4990},
- { 1371, 5135},{ 1442, 5244},{ 1520, 5321},{ 1684, 5398}
+ { 75, 612},{ 117, 751},{ 160, 1068},{ 195, 1406},
+ { 240, 1741},{ 305, 2066},{ 364, 2359},{ 454, 2639},
+ { 538, 2899},{ 609, 3149},{ 664, 3384},{ 730, 3625},
+ { 785, 3860},{ 836, 4094},{ 872, 4312},{ 948, 4507},
+ { 1023, 4677},{ 1081, 4843},{ 1165, 4985},{ 1238, 5092},
+ { 1316, 5235},{ 1418, 5345},{ 1430, 5478},{ 1505, 5538}
},
/*Cb qi=27 INTER*/
{
- { 113, 20},{ 90, 338},{ 66, 661},{ 67, 1034},
- { 82, 1438},{ 97, 1842},{ 108, 2238},{ 115, 2624},
- { 123, 3000},{ 130, 3361},{ 138, 3708},{ 146, 4040},
- { 155, 4367},{ 164, 4688},{ 174, 4999},{ 186, 5306},
- { 203, 5609},{ 222, 5908},{ 243, 6202},{ 268, 6494},
- { 295, 6781},{ 326, 7058},{ 367, 7319},{ 420, 7551}
+ { 16, 637},{ 13, 634},{ 32, 869},{ 46, 1230},
+ { 55, 1583},{ 67, 1950},{ 79, 2320},{ 93, 2690},
+ { 107, 3052},{ 120, 3399},{ 133, 3733},{ 146, 4054},
+ { 162, 4367},{ 175, 4679},{ 191, 4984},{ 211, 5285},
+ { 232, 5581},{ 252, 5875},{ 276, 6155},{ 305, 6433},
+ { 333, 6706},{ 364, 6967},{ 398, 7244},{ 474, 7394}
}
},
{
/*Cr qi=27 INTRA*/
{
- { 5, 6},{ 75, 380},{ 133, 770},{ 173, 1217},
- { 214, 1650},{ 268, 2040},{ 337, 2375},{ 418, 2631},
- { 496, 2862},{ 558, 3104},{ 625, 3346},{ 692, 3571},
- { 753, 3786},{ 825, 3989},{ 896, 4182},{ 969, 4352},
- { 1059, 4479},{ 1144, 4614},{ 1212, 4757},{ 1284, 4871},
- { 1380, 4982},{ 1457, 5125},{ 1528, 5267},{ 1651, 5346}
+ { 64, 632},{ 107, 763},{ 147, 1054},{ 176, 1411},
+ { 255, 1770},{ 324, 2079},{ 411, 2359},{ 475, 2621},
+ { 545, 2880},{ 590, 3158},{ 647, 3425},{ 709, 3648},
+ { 766, 3878},{ 831, 4082},{ 911, 4260},{ 960, 4493},
+ { 1042, 4558},{ 1115, 4760},{ 1200, 4852},{ 1280, 4950},
+ { 1327, 5186},{ 1445, 5157},{ 1443, 5431},{ 1518, 5493}
},
/*Cr qi=27 INTER*/
{
- { 92, 24},{ 74, 341},{ 61, 669},{ 71, 1049},
- { 88, 1448},{ 100, 1849},{ 107, 2243},{ 113, 2631},
- { 119, 3010},{ 125, 3373},{ 131, 3723},{ 137, 4064},
- { 146, 4396},{ 159, 4720},{ 172, 5033},{ 189, 5340},
- { 210, 5636},{ 233, 5920},{ 256, 6197},{ 282, 6465},
- { 310, 6730},{ 332, 7000},{ 359, 7259},{ 385, 7515}
- }
- }
- },
- {
- {
- /*Y' qi=28 INTRA*/
- {
- { 116, -8},{ 314, 1400},{ 640, 2458},{ 1013, 3197},
- { 1386, 3768},{ 1762, 4279},{ 2151, 4733},{ 2558, 5117},
- { 2970, 5442},{ 3393, 5714},{ 3820, 5935},{ 4243, 6069},
- { 4671, 6161},{ 5074, 6289},{ 5456, 6457},{ 5849, 6598},
- { 6244, 6689},{ 6632, 6777},{ 6984, 6833},{ 7294, 6855},
- { 7625, 6862},{ 7961, 6875},{ 8302, 6890},{ 8720, 6883}
- },
- /*Y' qi=28 INTER*/
- {
- { 54, 8},{ 81, 1333},{ 154, 2793},{ 231, 4138},
- { 304, 5352},{ 384, 6512},{ 519, 7585},{ 743, 8508},
- { 1082, 9236},{ 1587, 9717},{ 2267, 9928},{ 3034, 9944},
- { 3775, 9878},{ 4438, 9786},{ 5031, 9686},{ 5563, 9601},
- { 6042, 9523},{ 6481, 9456},{ 6890, 9405},{ 7266, 9356},
- { 7614, 9313},{ 7933, 9265},{ 8238, 9220},{ 8545, 9193}
- }
- },
- {
- /*Cb qi=28 INTRA*/
- {
- { 3, 3},{ 80, 368},{ 138, 746},{ 168, 1179},
- { 208, 1615},{ 268, 2014},{ 345, 2354},{ 432, 2637},
- { 515, 2884},{ 595, 3108},{ 669, 3323},{ 745, 3533},
- { 818, 3740},{ 876, 3953},{ 932, 4160},{ 1003, 4349},
- { 1088, 4501},{ 1154, 4648},{ 1241, 4768},{ 1349, 4889},
- { 1441, 5023},{ 1524, 5113},{ 1611, 5187},{ 1783, 5283}
- },
- /*Cb qi=28 INTER*/
- {
- { 117, 29},{ 91, 341},{ 65, 663},{ 68, 1038},
- { 85, 1440},{ 100, 1841},{ 110, 2234},{ 119, 2616},
- { 127, 2985},{ 135, 3342},{ 142, 3685},{ 151, 4015},
- { 162, 4337},{ 174, 4652},{ 186, 4960},{ 201, 5264},
- { 218, 5567},{ 239, 5863},{ 266, 6149},{ 295, 6434},
- { 328, 6715},{ 371, 6976},{ 409, 7239},{ 460, 7477}
- }
- },
- {
- /*Cr qi=28 INTRA*/
- {
- { 6, 7},{ 79, 381},{ 138, 771},{ 178, 1215},
- { 222, 1644},{ 285, 2026},{ 359, 2347},{ 441, 2597},
- { 521, 2827},{ 588, 3066},{ 655, 3303},{ 725, 3523},
- { 791, 3728},{ 870, 3920},{ 950, 4103},{ 1030, 4265},
- { 1121, 4388},{ 1198, 4520},{ 1266, 4659},{ 1356, 4759},
- { 1461, 4865},{ 1540, 4993},{ 1619, 5115},{ 1786, 5160}
- },
- /*Cr qi=28 INTER*/
- {
- { 96, 18},{ 78, 340},{ 66, 672},{ 74, 1051},
- { 90, 1450},{ 103, 1845},{ 110, 2235},{ 116, 2619},
- { 122, 2995},{ 129, 3356},{ 137, 3702},{ 146, 4038},
- { 156, 4365},{ 168, 4684},{ 182, 4995},{ 203, 5297},
- { 227, 5588},{ 253, 5866},{ 282, 6131},{ 311, 6394},
- { 339, 6664},{ 366, 6918},{ 400, 7171},{ 424, 7450}
- }
- }
- },
- {
- {
- /*Y' qi=29 INTRA*/
- {
- { 112, 7},{ 334, 1382},{ 681, 2410},{ 1081, 3112},
- { 1484, 3650},{ 1894, 4128},{ 2316, 4547},{ 2749, 4905},
- { 3188, 5208},{ 3634, 5458},{ 4079, 5666},{ 4517, 5791},
- { 4952, 5870},{ 5359, 5983},{ 5754, 6137},{ 6165, 6268},
- { 6568, 6351},{ 6958, 6423},{ 7320, 6471},{ 7638, 6490},
- { 7979, 6490},{ 8313, 6499},{ 8651, 6517},{ 9085, 6499}
- },
- /*Y' qi=29 INTER*/
- {
- { 55, 15},{ 85, 1336},{ 160, 2780},{ 242, 4104},
- { 323, 5302},{ 418, 6443},{ 586, 7480},{ 859, 8342},
- { 1278, 8982},{ 1888, 9347},{ 2658, 9457},{ 3457, 9425},
- { 4192, 9343},{ 4842, 9247},{ 5417, 9162},{ 5935, 9086},
- { 6404, 9011},{ 6841, 8952},{ 7241, 8907},{ 7609, 8867},
- { 7953, 8832},{ 8267, 8792},{ 8562, 8740},{ 8836, 8701}
- }
- },
- {
- /*Cb qi=29 INTRA*/
- {
- { 5, 3},{ 84, 368},{ 144, 746},{ 176, 1175},
- { 219, 1604},{ 285, 1991},{ 372, 2318},{ 462, 2591},
- { 546, 2833},{ 628, 3058},{ 704, 3274},{ 788, 3473},
- { 870, 3664},{ 935, 3865},{ 995, 4059},{ 1072, 4239},
- { 1167, 4388},{ 1248, 4518},{ 1334, 4634},{ 1429, 4765},
- { 1536, 4884},{ 1628, 4964},{ 1716, 5038},{ 1885, 5128}
- },
- /*Cb qi=29 INTER*/
- {
- { 126, 25},{ 95, 340},{ 69, 662},{ 71, 1039},
- { 88, 1440},{ 102, 1839},{ 113, 2227},{ 122, 2604},
- { 132, 2969},{ 141, 3320},{ 151, 3659},{ 161, 3985},
- { 172, 4301},{ 186, 4612},{ 200, 4917},{ 219, 5213},
- { 241, 5509},{ 265, 5800},{ 296, 6081},{ 329, 6360},
- { 369, 6633},{ 414, 6899},{ 465, 7148},{ 520, 7387}
- }
- },
- {
- /*Cr qi=29 INTRA*/
- {
- { 6, 7},{ 82, 382},{ 142, 772},{ 185, 1211},
- { 233, 1632},{ 303, 2000},{ 388, 2306},{ 475, 2550},
- { 556, 2779},{ 627, 3007},{ 707, 3237},{ 778, 3459},
- { 843, 3654},{ 927, 3834},{ 1012, 4012},{ 1101, 4152},
- { 1197, 4262},{ 1275, 4399},{ 1359, 4511},{ 1455, 4596},
- { 1562, 4708},{ 1644, 4833},{ 1719, 4954},{ 1888, 4988}
- },
- /*Cr qi=29 INTER*/
- {
- { 101, 28},{ 81, 343},{ 67, 673},{ 75, 1053},
- { 93, 1450},{ 106, 1844},{ 113, 2230},{ 119, 2610},
- { 127, 2980},{ 135, 3334},{ 143, 3676},{ 153, 4007},
- { 165, 4330},{ 180, 4645},{ 201, 4951},{ 224, 5243},
- { 253, 5522},{ 284, 5794},{ 314, 6060},{ 345, 6322},
- { 381, 6578},{ 419, 6828},{ 455, 7073},{ 495, 7316}
- }
- }
- },
- {
- {
- /*Y' qi=30 INTRA*/
- {
- { 112, 8},{ 335, 1380},{ 682, 2401},{ 1083, 3093},
- { 1489, 3619},{ 1902, 4092},{ 2332, 4511},{ 2777, 4865},
- { 3231, 5156},{ 3693, 5394},{ 4153, 5585},{ 4605, 5689},
- { 5049, 5764},{ 5468, 5871},{ 5875, 6004},{ 6295, 6120},
- { 6706, 6201},{ 7099, 6273},{ 7461, 6311},{ 7785, 6320},
- { 8128, 6322},{ 8469, 6331},{ 8806, 6342},{ 9220, 6338}
- },
- /*Y' qi=30 INTER*/
- {
- { 58, 8},{ 90, 1340},{ 169, 2771},{ 257, 4079},
- { 345, 5266},{ 459, 6387},{ 660, 7383},{ 990, 8180},
- { 1496, 8726},{ 2203, 8992},{ 3029, 9038},{ 3833, 8984},
- { 4549, 8900},{ 5183, 8813},{ 5745, 8735},{ 6250, 8674},
- { 6715, 8619},{ 7138, 8565},{ 7529, 8528},{ 7899, 8495},
- { 8234, 8465},{ 8550, 8429},{ 8856, 8395},{ 9160, 8374}
- }
- },
- {
- /*Cb qi=30 INTRA*/
- {
- { 7, 3},{ 88, 369},{ 149, 747},{ 185, 1175},
- { 232, 1599},{ 304, 1976},{ 392, 2293},{ 486, 2557},
- { 573, 2797},{ 656, 3027},{ 735, 3243},{ 819, 3442},
- { 903, 3629},{ 966, 3828},{ 1025, 4027},{ 1105, 4204},
- { 1201, 4343},{ 1282, 4469},{ 1379, 4575},{ 1486, 4689},
- { 1588, 4813},{ 1678, 4900},{ 1767, 4969},{ 1911, 5080}
- },
- /*Cb qi=30 INTER*/
- {
- { 120, 23},{ 96, 336},{ 72, 661},{ 75, 1043},
- { 91, 1441},{ 105, 1837},{ 117, 2221},{ 127, 2592},
- { 137, 2953},{ 148, 3301},{ 159, 3635},{ 170, 3959},
- { 184, 4271},{ 199, 4578},{ 216, 4879},{ 238, 5175},
- { 262, 5466},{ 294, 5750},{ 332, 6027},{ 373, 6298},
- { 421, 6559},{ 473, 6805},{ 526, 7053},{ 587, 7298}
- }
- },
- {
- /*Cr qi=30 INTRA*/
- {
- { 10, 7},{ 89, 384},{ 147, 773},{ 192, 1211},
- { 245, 1627},{ 322, 1984},{ 412, 2280},{ 501, 2520},
- { 583, 2750},{ 654, 2982},{ 736, 3207},{ 810, 3419},
- { 873, 3614},{ 957, 3794},{ 1048, 3965},{ 1139, 4102},
- { 1237, 4208},{ 1327, 4328},{ 1408, 4448},{ 1496, 4545},
- { 1604, 4652},{ 1699, 4760},{ 1780, 4877},{ 1937, 4942}
- },
- /*Cr qi=30 INTER*/
- {
- { 115, 26},{ 89, 342},{ 70, 672},{ 79, 1055},
- { 96, 1451},{ 108, 1841},{ 116, 2222},{ 124, 2599},
- { 132, 2965},{ 141, 3316},{ 151, 3655},{ 163, 3984},
- { 178, 4301},{ 197, 4609},{ 219, 4909},{ 247, 5195},
- { 280, 5469},{ 317, 5734},{ 351, 5991},{ 383, 6248},
- { 423, 6500},{ 467, 6744},{ 502, 6995},{ 558, 7226}
- }
- }
- },
- {
- {
- /*Y' qi=31 INTRA*/
- {
- { 116, 20},{ 359, 1361},{ 732, 2350},{ 1162, 3010},
- { 1597, 3507},{ 2042, 3950},{ 2503, 4339},{ 2974, 4670},
- { 3446, 4951},{ 3922, 5179},{ 4394, 5357},{ 4858, 5454},
- { 5313, 5519},{ 5734, 5626},{ 6154, 5755},{ 6585, 5859},
- { 7004, 5928},{ 7408, 5998},{ 7775, 6039},{ 8102, 6048},
- { 8442, 6051},{ 8790, 6054},{ 9136, 6057},{ 9554, 6041}
- },
- /*Y' qi=31 INTER*/
- {
- { 53, 12},{ 90, 1340},{ 169, 2765},{ 259, 4062},
- { 353, 5236},{ 483, 6340},{ 713, 7305},{ 1086, 8059},
- { 1651, 8548},{ 2423, 8751},{ 3288, 8754},{ 4106, 8674},
- { 4827, 8572},{ 5451, 8482},{ 6007, 8407},{ 6514, 8344},
- { 6970, 8282},{ 7397, 8225},{ 7795, 8193},{ 8159, 8161},
- { 8498, 8120},{ 8814, 8093},{ 9127, 8066},{ 9432, 8040}
- }
- },
- {
- /*Cb qi=31 INTRA*/
- {
- { 7, 3},{ 88, 369},{ 149, 746},{ 185, 1173},
- { 234, 1595},{ 308, 1967},{ 399, 2278},{ 494, 2537},
- { 583, 2774},{ 669, 2997},{ 755, 3204},{ 847, 3390},
- { 936, 3569},{ 1008, 3759},{ 1078, 3942},{ 1162, 4104},
- { 1262, 4238},{ 1352, 4364},{ 1442, 4470},{ 1557, 4567},
- { 1676, 4674},{ 1759, 4781},{ 1850, 4853},{ 2043, 4897}
- },
- /*Cb qi=31 INTER*/
- {
- { 121, 23},{ 96, 335},{ 72, 660},{ 74, 1043},
- { 90, 1440},{ 105, 1834},{ 116, 2217},{ 127, 2586},
- { 138, 2945},{ 148, 3293},{ 159, 3626},{ 172, 3945},
- { 185, 4256},{ 202, 4559},{ 223, 4856},{ 245, 5150},
- { 272, 5440},{ 306, 5719},{ 346, 5989},{ 391, 6253},
- { 443, 6511},{ 510, 6743},{ 583, 6965},{ 651, 7182}
- }
- },
- {
- /*Cr qi=31 INTRA*/
- {
- { 10, 7},{ 88, 384},{ 147, 773},{ 192, 1209},
- { 247, 1622},{ 326, 1974},{ 417, 2262},{ 509, 2500},
- { 596, 2726},{ 670, 2949},{ 754, 3170},{ 836, 3370},
- { 912, 3548},{ 999, 3724},{ 1093, 3888},{ 1198, 4000},
- { 1304, 4095},{ 1384, 4230},{ 1470, 4347},{ 1577, 4422},
- { 1696, 4513},{ 1798, 4620},{ 1869, 4746},{ 1991, 4798}
- },
- /*Cr qi=31 INTER*/
- {
- { 113, 32},{ 88, 345},{ 69, 674},{ 79, 1055},
- { 96, 1451},{ 108, 1839},{ 115, 2218},{ 123, 2592},
- { 132, 2957},{ 141, 3308},{ 151, 3643},{ 163, 3968},
- { 179, 4285},{ 200, 4590},{ 225, 4886},{ 254, 5169},
- { 291, 5436},{ 330, 5696},{ 368, 5951},{ 409, 6200},
- { 452, 6448},{ 493, 6695},{ 536, 6940},{ 571, 7204}
- }
- }
- },
- {
- {
- /*Y' qi=32 INTRA*/
- {
- { 123, 26},{ 370, 1356},{ 756, 2321},{ 1211, 2944},
- { 1674, 3408},{ 2148, 3826},{ 2639, 4193},{ 3138, 4504},
- { 3634, 4765},{ 4133, 4973},{ 4625, 5137},{ 5101, 5225},
- { 5567, 5274},{ 6002, 5363},{ 6437, 5482},{ 6885, 5566},
- { 7312, 5625},{ 7723, 5686},{ 8101, 5721},{ 8429, 5732},
- { 8769, 5728},{ 9120, 5726},{ 9472, 5723},{ 9918, 5700}
- },
- /*Y' qi=32 INTER*/
- {
- { 54, -3},{ 95, 1343},{ 179, 2750},{ 276, 4027},
- { 382, 5185},{ 543, 6256},{ 830, 7161},{ 1301, 7815},
- { 2003, 8172},{ 2883, 8266},{ 3779, 8217},{ 4578, 8127},
- { 5274, 8035},{ 5886, 7952},{ 6430, 7887},{ 6929, 7835},
- { 7380, 7779},{ 7796, 7737},{ 8190, 7705},{ 8552, 7672},
- { 8896, 7640},{ 9210, 7612},{ 9510, 7589},{ 9746, 7552}
- }
- },
- {
- /*Cb qi=32 INTRA*/
- {
- { 6, 3},{ 89, 369},{ 153, 746},{ 193, 1167},
- { 247, 1577},{ 330, 1935},{ 429, 2236},{ 528, 2494},
- { 620, 2732},{ 712, 2948},{ 801, 3146},{ 898, 3325},
- { 999, 3489},{ 1078, 3664},{ 1155, 3832},{ 1251, 3985},
- { 1360, 4115},{ 1451, 4236},{ 1549, 4338},{ 1667, 4433},
- { 1797, 4522},{ 1891, 4613},{ 1989, 4687},{ 2162, 4776}
- },
- /*Cb qi=32 INTER*/
- {
- { 116, -1},{ 98, 321},{ 80, 656},{ 80, 1042},
- { 96, 1438},{ 110, 1827},{ 122, 2205},{ 133, 2570},
- { 144, 2925},{ 157, 3268},{ 170, 3597},{ 185, 3911},
- { 202, 4216},{ 221, 4516},{ 244, 4809},{ 273, 5096},
- { 308, 5376},{ 350, 5644},{ 401, 5907},{ 459, 6160},
- { 520, 6401},{ 592, 6630},{ 676, 6837},{ 758, 7050}
- }
- },
- {
- /*Cr qi=32 INTRA*/
- {
- { 12, 7},{ 91, 386},{ 152, 773},{ 201, 1202},
- { 261, 1603},{ 347, 1942},{ 447, 2223},{ 540, 2460},
- { 626, 2684},{ 711, 2901},{ 801, 3115},{ 887, 3312},
- { 969, 3480},{ 1068, 3633},{ 1176, 3779},{ 1283, 3885},
- { 1392, 3969},{ 1485, 4090},{ 1573, 4206},{ 1686, 4274},
- { 1813, 4354},{ 1911, 4459},{ 2004, 4563},{ 2162, 4590}
- },
- /*Cr qi=32 INTER*/
- {
- { 129, 5},{ 98, 334},{ 75, 673},{ 84, 1055},
- { 101, 1448},{ 113, 1832},{ 121, 2206},{ 129, 2577},
- { 140, 2937},{ 151, 3282},{ 163, 3614},{ 179, 3932},
- { 198, 4240},{ 221, 4542},{ 252, 4830},{ 290, 5102},
- { 329, 5364},{ 373, 5618},{ 420, 5864},{ 468, 6105},
- { 513, 6351},{ 564, 6587},{ 624, 6810},{ 697, 7017}
- }
- }
- },
- {
- {
- /*Y' qi=33 INTRA*/
- {
- { 115, 36},{ 388, 1338},{ 791, 2289},{ 1258, 2899},
- { 1732, 3352},{ 2220, 3760},{ 2730, 4117},{ 3244, 4415},
- { 3751, 4662},{ 4261, 4858},{ 4766, 5012},{ 5249, 5094},
- { 5719, 5141},{ 6159, 5225},{ 6597, 5333},{ 7044, 5416},
- { 7474, 5472},{ 7893, 5531},{ 8268, 5570},{ 8591, 5580},
- { 8931, 5578},{ 9283, 5579},{ 9634, 5582},{10067, 5560}
- },
- /*Y' qi=33 INTER*/
- {
- { 65, -14},{ 102, 1345},{ 190, 2736},{ 294, 3999},
- { 411, 5146},{ 597, 6192},{ 934, 7045},{ 1488, 7622},
- { 2281, 7895},{ 3213, 7937},{ 4108, 7871},{ 4883, 7784},
- { 5556, 7709},{ 6150, 7643},{ 6685, 7585},{ 7176, 7539},
- { 7620, 7502},{ 8034, 7466},{ 8427, 7435},{ 8793, 7409},
- { 9136, 7386},{ 9446, 7364},{ 9743, 7339},{10025, 7303}
- }
- },
- {
- /*Cb qi=33 INTRA*/
- {
- { 5, 3},{ 92, 369},{ 159, 746},{ 203, 1163},
- { 263, 1564},{ 353, 1911},{ 458, 2204},{ 557, 2460},
- { 650, 2697},{ 744, 2913},{ 836, 3110},{ 934, 3292},
- { 1036, 3454},{ 1125, 3616},{ 1204, 3781},{ 1298, 3932},
- { 1410, 4058},{ 1507, 4170},{ 1606, 4265},{ 1725, 4358},
- { 1853, 4445},{ 1955, 4535},{ 2067, 4597},{ 2258, 4663}
- },
- /*Cb qi=33 INTER*/
- {
- { 109, 37},{ 94, 343},{ 81, 662},{ 85, 1042},
- { 102, 1436},{ 116, 1823},{ 128, 2195},{ 141, 2554},
- { 154, 2906},{ 167, 3246},{ 183, 3570},{ 202, 3881},
- { 220, 4185},{ 241, 4482},{ 268, 4772},{ 302, 5053},
- { 341, 5328},{ 388, 5592},{ 446, 5846},{ 507, 6096},
- { 581, 6328},{ 670, 6534},{ 762, 6731},{ 842, 6922}
- }
- },
- {
- /*Cr qi=33 INTRA*/
- {
- { 11, 7},{ 93, 387},{ 158, 774},{ 211, 1197},
- { 278, 1589},{ 372, 1917},{ 475, 2191},{ 569, 2429},
- { 658, 2655},{ 744, 2868},{ 835, 3083},{ 926, 3271},
- { 1010, 3430},{ 1110, 3586},{ 1224, 3724},{ 1336, 3826},
- { 1449, 3908},{ 1547, 4021},{ 1636, 4136},{ 1751, 4200},
- { 1886, 4277},{ 1977, 4384},{ 2070, 4474},{ 2232, 4510}
- },
- /*Cr qi=33 INTER*/
- {
- { 77, 9},{ 90, 347},{ 80, 674},{ 91, 1053},
- { 107, 1444},{ 119, 1825},{ 127, 2196},{ 137, 2563},
- { 149, 2919},{ 161, 3259},{ 176, 3588},{ 194, 3905},
- { 217, 4209},{ 246, 4504},{ 280, 4786},{ 320, 5055},
- { 364, 5316},{ 409, 5565},{ 460, 5804},{ 517, 6039},
- { 578, 6264},{ 640, 6489},{ 701, 6721},{ 772, 6948}
- }
- }
- },
- {
- {
- /*Y' qi=34 INTRA*/
- {
- { 124, 40},{ 401, 1333},{ 823, 2262},{ 1318, 2842},
- { 1823, 3265},{ 2339, 3650},{ 2872, 3991},{ 3405, 4274},
- { 3926, 4513},{ 4448, 4704},{ 4961, 4845},{ 5450, 4921},
- { 5925, 4971},{ 6372, 5053},{ 6813, 5160},{ 7264, 5242},
- { 7704, 5291},{ 8124, 5346},{ 8500, 5382},{ 8831, 5384},
- { 9178, 5380},{ 9525, 5387},{ 9869, 5389},{10310, 5356}
- },
- /*Y' qi=34 INTER*/
- {
- { 64, -17},{ 101, 1344},{ 190, 2730},{ 299, 3981},
- { 430, 5110},{ 648, 6127},{ 1036, 6933},{ 1664, 7445},
- { 2535, 7652},{ 3504, 7653},{ 4402, 7572},{ 5173, 7479},
- { 5843, 7400},{ 6441, 7334},{ 6976, 7280},{ 7464, 7231},
- { 7910, 7189},{ 8332, 7157},{ 8730, 7125},{ 9091, 7103},
- { 9422, 7086},{ 9753, 7061},{10067, 7036},{10316, 7029}
- }
- },
- {
- /*Cb qi=34 INTRA*/
- {
- { 5, 3},{ 91, 369},{ 158, 746},{ 204, 1162},
- { 266, 1561},{ 358, 1903},{ 466, 2189},{ 570, 2439},
- { 665, 2671},{ 765, 2880},{ 864, 3069},{ 970, 3238},
- { 1079, 3392},{ 1174, 3545},{ 1265, 3693},{ 1360, 3841},
- { 1471, 3968},{ 1572, 4083},{ 1675, 4181},{ 1804, 4255},
- { 1939, 4332},{ 2048, 4411},{ 2155, 4484},{ 2339, 4584}
- },
- /*Cb qi=34 INTER*/
- {
- { 99, 44},{ 92, 345},{ 82, 661},{ 86, 1043},
- { 101, 1436},{ 116, 1821},{ 128, 2191},{ 140, 2549},
- { 154, 2898},{ 168, 3235},{ 185, 3556},{ 203, 3865},
- { 224, 4166},{ 248, 4457},{ 278, 4741},{ 315, 5021},
- { 361, 5289},{ 416, 5546},{ 483, 5792},{ 559, 6025},
- { 651, 6237},{ 752, 6432},{ 849, 6626},{ 967, 6790}
- }
- },
- {
- /*Cr qi=34 INTRA*/
- {
- { 11, 7},{ 93, 387},{ 158, 773},{ 212, 1195},
- { 282, 1584},{ 378, 1909},{ 483, 2179},{ 578, 2414},
- { 671, 2633},{ 766, 2837},{ 866, 3038},{ 960, 3223},
- { 1049, 3376},{ 1158, 3520},{ 1285, 3644},{ 1400, 3740},
- { 1505, 3828},{ 1616, 3928},{ 1713, 4030},{ 1820, 4104},
- { 1957, 4185},{ 2063, 4280},{ 2160, 4355},{ 2320, 4341}
- },
- /*Cr qi=34 INTER*/
- {
- { 78, 11},{ 89, 347},{ 79, 674},{ 90, 1053},
- { 106, 1444},{ 117, 1823},{ 127, 2192},{ 137, 2558},
- { 149, 2912},{ 163, 3249},{ 178, 3574},{ 197, 3888},
- { 222, 4189},{ 252, 4481},{ 293, 4755},{ 341, 5013},
- { 386, 5268},{ 436, 5512},{ 498, 5743},{ 563, 5970},
- { 622, 6200},{ 694, 6415},{ 776, 6622},{ 871, 6818}
- }
- }
- },
- {
- {
- /*Y' qi=35 INTRA*/
- {
- { 116, 51},{ 433, 1312},{ 881, 2221},{ 1406, 2771},
- { 1948, 3156},{ 2511, 3501},{ 3085, 3811},{ 3654, 4066},
- { 4212, 4273},{ 4763, 4444},{ 5298, 4572},{ 5799, 4638},
- { 6285, 4678},{ 6747, 4746},{ 7203, 4838},{ 7673, 4905},
- { 8124, 4950},{ 8552, 5003},{ 8938, 5027},{ 9275, 5026},
- { 9628, 5019},{ 9981, 5024},{10331, 5030},{10795, 5000}
- },
- /*Y' qi=35 INTER*/
- {
- { 71, -10},{ 108, 1348},{ 203, 2710},{ 325, 3938},
- { 485, 5040},{ 766, 6000},{ 1267, 6706},{ 2048, 7089},
- { 3037, 7191},{ 4032, 7146},{ 4903, 7061},{ 5648, 6977},
- { 6301, 6912},{ 6884, 6857},{ 7413, 6812},{ 7898, 6775},
- { 8342, 6739},{ 8764, 6710},{ 9160, 6688},{ 9519, 6668},
- { 9859, 6646},{10190, 6625},{10492, 6612},{10755, 6595}
- }
- },
- {
- /*Cb qi=35 INTRA*/
- {
- { 6, 3},{ 95, 369},{ 164, 746},{ 214, 1156},
- { 287, 1542},{ 390, 1869},{ 504, 2143},{ 611, 2388},
- { 712, 2613},{ 822, 2811},{ 937, 2987},{ 1055, 3147},
- { 1174, 3285},{ 1286, 3420},{ 1386, 3560},{ 1488, 3698},
- { 1604, 3814},{ 1714, 3916},{ 1825, 4008},{ 1958, 4088},
- { 2101, 4159},{ 2224, 4226},{ 2339, 4292},{ 2538, 4383}
- },
- /*Cb qi=35 INTER*/
- {
- { 98, 41},{ 90, 348},{ 86, 665},{ 92, 1042},
- { 108, 1432},{ 122, 1812},{ 136, 2175},{ 151, 2528},
- { 165, 2872},{ 182, 3202},{ 202, 3516},{ 225, 3819},
- { 251, 4112},{ 281, 4398},{ 320, 4675},{ 367, 4944},
- { 421, 5204},{ 493, 5450},{ 579, 5679},{ 672, 5892},
- { 785, 6082},{ 906, 6258},{ 1026, 6432},{ 1153, 6592}
- }
- },
- {
- /*Cr qi=35 INTRA*/
- {
- { 12, 7},{ 98, 388},{ 166, 773},{ 226, 1187},
- { 306, 1563},{ 411, 1874},{ 524, 2134},{ 622, 2365},
- { 721, 2577},{ 826, 2768},{ 947, 2946},{ 1066, 3106},
- { 1163, 3250},{ 1274, 3395},{ 1417, 3508},{ 1539, 3590},
- { 1639, 3671},{ 1754, 3765},{ 1865, 3855},{ 1979, 3921},
- { 2127, 3998},{ 2249, 4085},{ 2346, 4172},{ 2473, 4210}
- },
- /*Cr qi=35 INTER*/
- {
- { 86, 12},{ 94, 354},{ 85, 677},{ 96, 1052},
- { 113, 1439},{ 125, 1811},{ 135, 2177},{ 147, 2537},
- { 160, 2884},{ 177, 3215},{ 195, 3535},{ 219, 3842},
- { 252, 4133},{ 292, 4413},{ 339, 4680},{ 396, 4928},
- { 455, 5169},{ 514, 5408},{ 588, 5626},{ 672, 5835},
- { 750, 6051},{ 837, 6257},{ 943, 6442},{ 1073, 6595}
+ { 12, 688},{ 11, 660},{ 28, 869},{ 46, 1227},
+ { 60, 1598},{ 68, 1954},{ 79, 2318},{ 93, 2693},
+ { 108, 3054},{ 123, 3406},{ 138, 3748},{ 151, 4078},
+ { 165, 4400},{ 180, 4716},{ 197, 5024},{ 217, 5314},
+ { 243, 5599},{ 275, 5866},{ 301, 6128},{ 327, 6394},
+ { 352, 6644},{ 375, 6894},{ 376, 7180},{ 458, 7334}
}
}
},
@@ -2290,557 +279,61 @@ oc_mode_rd OC_MODE_RD[64][3][2][OC_SAD_BINS]={
{
/*Y' qi=36 INTRA*/
{
- { 116, 52},{ 432, 1312},{ 881, 2215},{ 1407, 2759},
- { 1948, 3140},{ 2511, 3484},{ 3090, 3789},{ 3672, 4036},
- { 4243, 4236},{ 4803, 4397},{ 5346, 4517},{ 5856, 4581},
- { 6350, 4614},{ 6821, 4675},{ 7286, 4763},{ 7754, 4832},
- { 8201, 4875},{ 8631, 4922},{ 9015, 4948},{ 9351, 4945},
- { 9706, 4941},{10061, 4948},{10408, 4949},{10878, 4923}
+ { 156, 263},{ 484, 1370},{ 1174, 2110},{ 1914, 2456},
+ { 2601, 2695},{ 3221, 2984},{ 3865, 3284},{ 4450, 3530},
+ { 4979, 3739},{ 5470, 3928},{ 5905, 4080},{ 6375, 4200},
+ { 6761, 4373},{ 7175, 4429},{ 7615, 4616},{ 8069, 4687},
+ { 8417, 4820},{ 8813, 4908},{ 9211, 5001},{ 9508, 5073},
+ { 9888, 5133},{10209, 5140},{10529, 5196},{10830, 5173}
},
/*Y' qi=36 INTER*/
{
- { 63, -16},{ 114, 1332},{ 216, 2690},{ 343, 3914},
- { 515, 5009},{ 829, 5939},{ 1399, 6586},{ 2263, 6901},
- { 3290, 6967},{ 4272, 6920},{ 5115, 6847},{ 5839, 6779},
- { 6478, 6726},{ 7051, 6685},{ 7571, 6649},{ 8050, 6614},
- { 8495, 6587},{ 8908, 6567},{ 9298, 6550},{ 9673, 6530},
- {10005, 6512},{10324, 6499},{10640, 6483},{10936, 6487}
+ { 68, 151},{ 107, 1413},{ 262, 2665},{ 542, 3715},
+ { 946, 4584},{ 1508, 5279},{ 2167, 5829},{ 2968, 6179},
+ { 3758, 6392},{ 4481, 6517},{ 5139, 6577},{ 5706, 6636},
+ { 6271, 6612},{ 6746, 6585},{ 7216, 6533},{ 7622, 6496},
+ { 8045, 6403},{ 8393, 6389},{ 8799, 6272},{ 9062, 6281},
+ { 9436, 6184},{ 9637, 6238},{ 9864, 6215},{10147, 6215}
}
},
{
/*Cb qi=36 INTRA*/
{
- { 6, 3},{ 98, 370},{ 170, 746},{ 225, 1150},
- { 306, 1527},{ 416, 1845},{ 534, 2116},{ 642, 2363},
- { 743, 2591},{ 851, 2794},{ 964, 2972},{ 1081, 3133},
- { 1198, 3275},{ 1311, 3410},{ 1411, 3547},{ 1519, 3680},
- { 1642, 3789},{ 1750, 3892},{ 1860, 3982},{ 1998, 4054},
- { 2141, 4129},{ 2256, 4204},{ 2372, 4278},{ 2567, 4356}
+ { 91, 385},{ 138, 613},{ 205, 932},{ 265, 1239},
+ { 353, 1549},{ 443, 1839},{ 518, 2104},{ 655, 2341},
+ { 764, 2559},{ 876, 2756},{ 967, 2950},{ 1088, 3107},
+ { 1184, 3266},{ 1295, 3396},{ 1375, 3548},{ 1502, 3664},
+ { 1610, 3764},{ 1731, 3844},{ 1839, 3938},{ 1954, 4016},
+ { 2069, 4100},{ 2207, 4167},{ 2274, 4253},{ 2374, 4289}
},
/*Cb qi=36 INTER*/
{
- { 107, 30},{ 96, 346},{ 88, 667},{ 100, 1039},
- { 115, 1426},{ 128, 1804},{ 142, 2164},{ 158, 2512},
- { 176, 2851},{ 195, 3178},{ 218, 3491},{ 243, 3791},
- { 270, 4084},{ 307, 4365},{ 348, 4638},{ 397, 4908},
- { 464, 5157},{ 545, 5392},{ 635, 5620},{ 734, 5831},
- { 854, 6015},{ 993, 6170},{ 1124, 6327},{ 1234, 6502}
+ { 59, 18},{ 56, 463},{ 50, 790},{ 76, 1155},
+ { 90, 1515},{ 108, 1877},{ 125, 2226},{ 150, 2562},
+ { 177, 2890},{ 203, 3203},{ 231, 3501},{ 259, 3789},
+ { 289, 4074},{ 325, 4348},{ 367, 4608},{ 418, 4857},
+ { 486, 5093},{ 574, 5307},{ 677, 5494},{ 784, 5688},
+ { 914, 5844},{ 1033, 6004},{ 1142, 6179},{ 1307, 6220}
}
},
{
/*Cr qi=36 INTRA*/
{
- { 12, 7},{ 102, 388},{ 172, 773},{ 239, 1182},
- { 328, 1546},{ 439, 1848},{ 554, 2106},{ 651, 2341},
- { 747, 2561},{ 850, 2757},{ 972, 2934},{ 1086, 3097},
- { 1182, 3245},{ 1302, 3382},{ 1447, 3491},{ 1572, 3567},
- { 1677, 3641},{ 1793, 3733},{ 1899, 3828},{ 2013, 3894},
- { 2163, 3967},{ 2283, 4059},{ 2387, 4142},{ 2559, 4145}
+ { 87, 376},{ 132, 616},{ 190, 931},{ 268, 1260},
+ { 358, 1550},{ 457, 1833},{ 592, 2082},{ 685, 2318},
+ { 781, 2548},{ 867, 2757},{ 968, 2953},{ 1080, 3124},
+ { 1173, 3255},{ 1282, 3390},{ 1410, 3477},{ 1528, 3593},
+ { 1645, 3612},{ 1766, 3739},{ 1885, 3789},{ 1954, 3892},
+ { 2115, 3987},{ 2202, 4052},{ 2280, 4172},{ 2379, 4213}
},
/*Cr qi=36 INTER*/
{
- { 98, -10},{ 96, 347},{ 89, 676},{ 102, 1048},
- { 118, 1433},{ 130, 1804},{ 141, 2167},{ 154, 2523},
- { 171, 2866},{ 190, 3194},{ 212, 3508},{ 240, 3809},
- { 276, 4099},{ 320, 4377},{ 372, 4638},{ 428, 4887},
- { 492, 5122},{ 560, 5353},{ 638, 5572},{ 725, 5779},
- { 814, 5985},{ 902, 6192},{ 1013, 6377},{ 1155, 6527}
- }
- }
- },
- {
- {
- /*Y' qi=37 INTRA*/
- {
- { 109, 58},{ 445, 1302},{ 927, 2177},{ 1489, 2689},
- { 2053, 3052},{ 2632, 3387},{ 3230, 3683},{ 3830, 3922},
- { 4417, 4114},{ 4992, 4266},{ 5546, 4375},{ 6067, 4430},
- { 6571, 4459},{ 7046, 4516},{ 7513, 4599},{ 7991, 4663},
- { 8445, 4706},{ 8883, 4749},{ 9273, 4771},{ 9612, 4770},
- { 9970, 4765},{10325, 4773},{10672, 4778},{11106, 4758}
- },
- /*Y' qi=37 INTER*/
- {
- { 56, -14},{ 114, 1333},{ 218, 2683},{ 354, 3894},
- { 550, 4966},{ 916, 5854},{ 1569, 6437},{ 2520, 6685},
- { 3596, 6704},{ 4585, 6635},{ 5424, 6556},{ 6147, 6489},
- { 6787, 6437},{ 7358, 6395},{ 7876, 6358},{ 8361, 6325},
- { 8807, 6294},{ 9229, 6271},{ 9631, 6253},{10002, 6238},
- {10356, 6228},{10678, 6212},{10975, 6197},{11274, 6185}
- }
- },
- {
- /*Cb qi=37 INTRA*/
- {
- { 6, 3},{ 99, 370},{ 171, 746},{ 227, 1149},
- { 309, 1522},{ 421, 1836},{ 541, 2104},{ 652, 2347},
- { 757, 2572},{ 871, 2768},{ 989, 2936},{ 1111, 3087},
- { 1238, 3223},{ 1357, 3352},{ 1465, 3486},{ 1576, 3612},
- { 1709, 3705},{ 1828, 3801},{ 1937, 3895},{ 2076, 3967},
- { 2220, 4035},{ 2345, 4104},{ 2466, 4173},{ 2680, 4265}
- },
- /*Cb qi=37 INTER*/
- {
- { 111, 27},{ 97, 344},{ 87, 667},{ 99, 1038},
- { 115, 1425},{ 128, 1802},{ 143, 2160},{ 159, 2506},
- { 176, 2843},{ 198, 3167},{ 220, 3477},{ 247, 3774},
- { 280, 4061},{ 321, 4338},{ 368, 4608},{ 427, 4867},
- { 501, 5109},{ 595, 5332},{ 701, 5544},{ 818, 5738},
- { 956, 5905},{ 1105, 6066},{ 1248, 6217},{ 1381, 6353}
- }
- },
- {
- /*Cr qi=37 INTRA*/
- {
- { 12, 7},{ 102, 388},{ 173, 773},{ 242, 1180},
- { 331, 1541},{ 444, 1839},{ 562, 2095},{ 662, 2326},
- { 763, 2540},{ 871, 2728},{ 1003, 2892},{ 1130, 3045},
- { 1230, 3188},{ 1350, 3321},{ 1503, 3418},{ 1634, 3492},
- { 1737, 3568},{ 1856, 3653},{ 1970, 3744},{ 2091, 3802},
- { 2247, 3871},{ 2371, 3962},{ 2477, 4041},{ 2655, 4052}
- },
- /*Cr qi=37 INTER*/
- {
- { 89, -9},{ 97, 347},{ 88, 677},{ 102, 1048},
- { 118, 1432},{ 130, 1802},{ 141, 2163},{ 154, 2517},
- { 172, 2857},{ 192, 3181},{ 216, 3494},{ 246, 3793},
- { 286, 4074},{ 337, 4343},{ 395, 4600},{ 464, 4837},
- { 534, 5066},{ 608, 5289},{ 694, 5501},{ 788, 5704},
- { 893, 5901},{ 1010, 6088},{ 1151, 6249},{ 1331, 6374}
- }
- }
- },
- {
- {
- /*Y' qi=38 INTRA*/
- {
- { 107, 65},{ 476, 1286},{ 968, 2148},{ 1548, 2641},
- { 2141, 2979},{ 2757, 3289},{ 3390, 3564},{ 4020, 3784},
- { 4632, 3957},{ 5224, 4097},{ 5794, 4201},{ 6326, 4250},
- { 6828, 4274},{ 7309, 4322},{ 7790, 4401},{ 8271, 4463},
- { 8729, 4498},{ 9165, 4540},{ 9552, 4566},{ 9901, 4560},
- {10266, 4552},{10617, 4563},{10964, 4572},{11393, 4567}
- },
- /*Y' qi=38 INTER*/
- {
- { 57, -13},{ 118, 1332},{ 233, 2665},{ 386, 3856},
- { 620, 4899},{ 1070, 5722},{ 1849, 6211},{ 2898, 6384},
- { 3989, 6376},{ 4947, 6311},{ 5754, 6249},{ 6454, 6199},
- { 7077, 6161},{ 7640, 6132},{ 8159, 6101},{ 8639, 6076},
- { 9081, 6054},{ 9502, 6037},{ 9900, 6027},{10274, 6012},
- {10621, 5999},{10938, 5991},{11237, 5977},{11557, 5966}
- }
- },
- {
- /*Cb qi=38 INTRA*/
- {
- { 8, 3},{ 104, 370},{ 179, 744},{ 243, 1139},
- { 338, 1498},{ 458, 1801},{ 584, 2060},{ 700, 2297},
- { 812, 2514},{ 935, 2699},{ 1061, 2858},{ 1189, 3007},
- { 1321, 3141},{ 1446, 3266},{ 1563, 3388},{ 1684, 3512},
- { 1816, 3614},{ 1942, 3702},{ 2055, 3793},{ 2201, 3857},
- { 2357, 3923},{ 2477, 3994},{ 2593, 4061},{ 2768, 4178}
- },
- /*Cb qi=38 INTER*/
- {
- { 118, 24},{ 102, 342},{ 91, 663},{ 101, 1040},
- { 116, 1427},{ 131, 1799},{ 147, 2152},{ 168, 2491},
- { 191, 2822},{ 215, 3139},{ 244, 3441},{ 276, 3731},
- { 316, 4013},{ 363, 4286},{ 423, 4546},{ 495, 4795},
- { 584, 5028},{ 691, 5242},{ 814, 5439},{ 959, 5608},
- { 1119, 5759},{ 1277, 5906},{ 1449, 6035},{ 1655, 6144}
- }
- },
- {
- /*Cr qi=38 INTRA*/
- {
- { 12, 6},{ 106, 387},{ 182, 771},{ 261, 1168},
- { 364, 1514},{ 483, 1802},{ 603, 2053},{ 707, 2282},
- { 817, 2489},{ 933, 2670},{ 1074, 2825},{ 1210, 2967},
- { 1320, 3104},{ 1444, 3229},{ 1599, 3324},{ 1735, 3396},
- { 1846, 3464},{ 1971, 3547},{ 2086, 3646},{ 2206, 3711},
- { 2366, 3773},{ 2499, 3859},{ 2603, 3945},{ 2766, 3952}
- },
- /*Cr qi=38 INTER*/
- {
- { 86, -9},{ 91, 352},{ 85, 680},{ 102, 1053},
- { 119, 1435},{ 132, 1799},{ 146, 2153},{ 162, 2501},
- { 183, 2835},{ 209, 3154},{ 240, 3458},{ 278, 3751},
- { 327, 4025},{ 388, 4284},{ 455, 4532},{ 529, 4766},
- { 616, 4980},{ 711, 5188},{ 815, 5386},{ 920, 5583},
- { 1042, 5770},{ 1186, 5936},{ 1348, 6080},{ 1542, 6196}
- }
- }
- },
- {
- {
- /*Y' qi=39 INTRA*/
- {
- { 103, 66},{ 479, 1283},{ 998, 2125},{ 1610, 2591},
- { 2223, 2913},{ 2855, 3214},{ 3501, 3482},{ 4146, 3698},
- { 4772, 3868},{ 5376, 3999},{ 5956, 4095},{ 6496, 4140},
- { 7008, 4162},{ 7499, 4209},{ 7987, 4282},{ 8478, 4338},
- { 8947, 4374},{ 9385, 4417},{ 9783, 4437},{10143, 4433},
- {10504, 4424},{10866, 4435},{11225, 4444},{11665, 4430}
- },
- /*Y' qi=39 INTER*/
- {
- { 56, 2},{ 118, 1332},{ 235, 2660},{ 395, 3843},
- { 653, 4867},{ 1153, 5652},{ 2003, 6089},{ 3113, 6214},
- { 4228, 6178},{ 5189, 6102},{ 6002, 6031},{ 6707, 5976},
- { 7336, 5936},{ 7901, 5900},{ 8424, 5870},{ 8915, 5844},
- { 9361, 5822},{ 9784, 5807},{10187, 5794},{10571, 5778},
- {10931, 5763},{11264, 5751},{11582, 5742},{11916, 5730}
- }
- },
- {
- /*Cb qi=39 INTRA*/
- {
- { 8, 3},{ 104, 370},{ 179, 744},{ 244, 1138},
- { 340, 1496},{ 461, 1796},{ 588, 2053},{ 705, 2288},
- { 820, 2503},{ 945, 2684},{ 1073, 2840},{ 1210, 2981},
- { 1352, 3106},{ 1480, 3225},{ 1603, 3342},{ 1728, 3464},
- { 1865, 3559},{ 1990, 3645},{ 2106, 3734},{ 2258, 3796},
- { 2413, 3856},{ 2540, 3920},{ 2667, 3986},{ 2887, 4060}
- },
- /*Cb qi=39 INTER*/
- {
- { 119, 19},{ 103, 340},{ 90, 664},{ 100, 1040},
- { 115, 1426},{ 131, 1797},{ 148, 2148},{ 169, 2486},
- { 192, 2816},{ 217, 3131},{ 247, 3432},{ 282, 3721},
- { 324, 3999},{ 374, 4268},{ 435, 4526},{ 520, 4766},
- { 621, 4990},{ 738, 5194},{ 878, 5376},{ 1035, 5543},
- { 1202, 5686},{ 1374, 5819},{ 1545, 5950},{ 1729, 6064}
- }
- },
- {
- /*Cr qi=39 INTRA*/
- {
- { 12, 6},{ 106, 387},{ 182, 771},{ 262, 1167},
- { 365, 1512},{ 486, 1798},{ 608, 2047},{ 713, 2274},
- { 824, 2479},{ 945, 2655},{ 1091, 2804},{ 1231, 2941},
- { 1346, 3073},{ 1475, 3194},{ 1633, 3282},{ 1778, 3345},
- { 1891, 3414},{ 2013, 3501},{ 2138, 3584},{ 2266, 3640},
- { 2428, 3701},{ 2568, 3782},{ 2674, 3863},{ 2816, 3894}
- },
- /*Cr qi=39 INTER*/
- {
- { 88, -7},{ 92, 352},{ 85, 680},{ 102, 1053},
- { 119, 1434},{ 132, 1797},{ 146, 2151},{ 163, 2498},
- { 185, 2830},{ 211, 3147},{ 243, 3451},{ 285, 3735},
- { 337, 4005},{ 401, 4260},{ 477, 4499},{ 565, 4721},
- { 655, 4937},{ 749, 5148},{ 858, 5344},{ 979, 5529},
- { 1110, 5710},{ 1264, 5871},{ 1460, 5990},{ 1677, 6086}
- }
- }
- },
- {
- {
- /*Y' qi=40 INTRA*/
- {
- { 98, 71},{ 491, 1274},{ 1023, 2103},{ 1641, 2559},
- { 2257, 2877},{ 2898, 3171},{ 3566, 3429},{ 4233, 3629},
- { 4881, 3784},{ 5499, 3906},{ 6088, 3997},{ 6631, 4040},
- { 7145, 4060},{ 7640, 4107},{ 8128, 4178},{ 8618, 4233},
- { 9077, 4267},{ 9514, 4304},{ 9919, 4324},{10277, 4317},
- {10635, 4312},{10985, 4324},{11338, 4331},{11792, 4334}
- },
- /*Y' qi=40 INTER*/
- {
- { 63, -26},{ 125, 1331},{ 256, 2640},{ 439, 3801},
- { 757, 4782},{ 1391, 5474},{ 2399, 5805},{ 3582, 5870},
- { 4678, 5824},{ 5600, 5763},{ 6386, 5710},{ 7076, 5667},
- { 7693, 5637},{ 8252, 5610},{ 8775, 5586},{ 9255, 5571},
- { 9694, 5556},{10115, 5541},{10530, 5530},{10903, 5522},
- {11242, 5515},{11596, 5501},{11904, 5482},{12205, 5475}
- }
- },
- {
- /*Cb qi=40 INTRA*/
- {
- { 8, 3},{ 108, 371},{ 189, 743},{ 265, 1128},
- { 371, 1475},{ 499, 1767},{ 628, 2022},{ 746, 2256},
- { 864, 2467},{ 991, 2647},{ 1124, 2801},{ 1270, 2933},
- { 1412, 3054},{ 1547, 3165},{ 1677, 3277},{ 1804, 3393},
- { 1946, 3483},{ 2078, 3569},{ 2201, 3651},{ 2352, 3711},
- { 2513, 3766},{ 2643, 3826},{ 2775, 3880},{ 3025, 3919}
- },
- /*Cb qi=40 INTER*/
- {
- { 114, 35},{ 104, 349},{ 96, 667},{ 106, 1040},
- { 121, 1423},{ 138, 1789},{ 158, 2132},{ 184, 2464},
- { 212, 2787},{ 242, 3095},{ 279, 3389},{ 321, 3671},
- { 374, 3941},{ 438, 4199},{ 517, 4446},{ 617, 4673},
- { 740, 4881},{ 891, 5064},{ 1058, 5225},{ 1239, 5372},
- { 1441, 5499},{ 1638, 5610},{ 1840, 5719},{ 2076, 5814}
- }
- },
- {
- /*Cr qi=40 INTRA*/
- {
- { 14, 7},{ 114, 389},{ 193, 771},{ 283, 1156},
- { 399, 1488},{ 523, 1768},{ 643, 2018},{ 752, 2245},
- { 865, 2450},{ 984, 2626},{ 1139, 2763},{ 1290, 2887},
- { 1413, 3014},{ 1550, 3128},{ 1711, 3211},{ 1865, 3268},
- { 1981, 3334},{ 2103, 3415},{ 2237, 3486},{ 2365, 3543},
- { 2529, 3610},{ 2666, 3700},{ 2775, 3779},{ 2929, 3803}
- },
- /*Cr qi=40 INTER*/
- {
- { 89, -8},{ 95, 353},{ 90, 681},{ 107, 1053},
- { 124, 1430},{ 139, 1787},{ 156, 2136},{ 177, 2477},
- { 203, 2803},{ 237, 3112},{ 276, 3406},{ 329, 3683},
- { 395, 3942},{ 475, 4182},{ 567, 4407},{ 665, 4624},
- { 767, 4834},{ 879, 5032},{ 1011, 5213},{ 1169, 5375},
- { 1348, 5525},{ 1547, 5654},{ 1785, 5743},{ 2066, 5787}
- }
- }
- },
- {
- {
- /*Y' qi=41 INTRA*/
- {
- { 98, 71},{ 495, 1272},{ 1040, 2090},{ 1675, 2533},
- { 2302, 2842},{ 2953, 3132},{ 3631, 3381},{ 4309, 3574},
- { 4966, 3726},{ 5593, 3846},{ 6189, 3934},{ 6738, 3972},
- { 7256, 3991},{ 7754, 4036},{ 8250, 4099},{ 8747, 4150},
- { 9207, 4185},{ 9650, 4222},{10057, 4242},{10411, 4237},
- {10771, 4230},{11127, 4244},{11486, 4254},{11933, 4252}
- },
- /*Y' qi=41 INTER*/
- {
- { 65, -25},{ 125, 1331},{ 260, 2633},{ 457, 3782},
- { 807, 4740},{ 1499, 5397},{ 2562, 5693},{ 3766, 5743},
- { 4859, 5695},{ 5776, 5638},{ 6556, 5590},{ 7243, 5554},
- { 7859, 5529},{ 8417, 5506},{ 8935, 5486},{ 9419, 5473},
- { 9869, 5460},{10296, 5446},{10711, 5436},{11089, 5430},
- {11445, 5421},{11802, 5412},{12129, 5404},{12465, 5393}
- }
- },
- {
- /*Cb qi=41 INTRA*/
- {
- { 8, 3},{ 108, 371},{ 189, 743},{ 267, 1126},
- { 374, 1471},{ 504, 1760},{ 635, 2011},{ 758, 2241},
- { 881, 2447},{ 1013, 2621},{ 1147, 2773},{ 1293, 2906},
- { 1441, 3023},{ 1580, 3131},{ 1712, 3243},{ 1844, 3360},
- { 1985, 3451},{ 2114, 3532},{ 2240, 3613},{ 2390, 3680},
- { 2550, 3740},{ 2687, 3800},{ 2825, 3862},{ 3052, 3944}
- },
- /*Cb qi=41 INTER*/
- {
- { 104, 39},{ 100, 350},{ 95, 667},{ 105, 1040},
- { 121, 1422},{ 137, 1787},{ 159, 2129},{ 185, 2459},
- { 216, 2778},{ 249, 3083},{ 287, 3374},{ 335, 3653},
- { 393, 3920},{ 462, 4175},{ 549, 4414},{ 660, 4636},
- { 791, 4839},{ 952, 5014},{ 1135, 5166},{ 1337, 5297},
- { 1552, 5411},{ 1752, 5530},{ 1972, 5634},{ 2224, 5724}
- }
- },
- {
- /*Cr qi=41 INTRA*/
- {
- { 15, 7},{ 115, 389},{ 193, 770},{ 284, 1154},
- { 401, 1484},{ 528, 1761},{ 652, 2005},{ 764, 2228},
- { 882, 2427},{ 1008, 2599},{ 1167, 2734},{ 1320, 2859},
- { 1443, 2990},{ 1580, 3103},{ 1743, 3181},{ 1894, 3241},
- { 2012, 3309},{ 2141, 3385},{ 2272, 3459},{ 2398, 3519},
- { 2566, 3584},{ 2707, 3680},{ 2816, 3762},{ 2991, 3770}
- },
- /*Cr qi=41 INTER*/
- {
- { 92, -9},{ 98, 354},{ 90, 682},{ 107, 1052},
- { 124, 1429},{ 139, 1786},{ 156, 2132},{ 178, 2471},
- { 207, 2794},{ 241, 3100},{ 285, 3391},{ 345, 3662},
- { 417, 3915},{ 503, 4151},{ 600, 4375},{ 703, 4589},
- { 815, 4791},{ 942, 4981},{ 1088, 5155},{ 1250, 5316},
- { 1432, 5462},{ 1653, 5575},{ 1930, 5639},{ 2250, 5655}
- }
- }
- },
- {
- {
- /*Y' qi=42 INTRA*/
- {
- { 109, 75},{ 534, 1257},{ 1114, 2047},{ 1793, 2456},
- { 2461, 2735},{ 3157, 2994},{ 3879, 3221},{ 4595, 3396},
- { 5282, 3531},{ 5931, 3638},{ 6546, 3714},{ 7105, 3749},
- { 7633, 3766},{ 8147, 3803},{ 8652, 3865},{ 9148, 3915},
- { 9613, 3946},{10075, 3976},{10489, 3997},{10835, 3994},
- {11195, 3985},{11553, 3997},{11909, 4004},{12369, 3990}
- },
- /*Y' qi=42 INTER*/
- {
- { 69, -23},{ 134, 1332},{ 287, 2611},{ 521, 3730},
- { 970, 4624},{ 1827, 5176},{ 3028, 5382},{ 4262, 5389},
- { 5325, 5338},{ 6214, 5291},{ 6976, 5255},{ 7651, 5228},
- { 8260, 5206},{ 8821, 5190},{ 9343, 5177},{ 9823, 5165},
- {10273, 5152},{10709, 5143},{11121, 5136},{11502, 5129},
- {11857, 5125},{12193, 5115},{12520, 5107},{12802, 5097}
- }
- },
- {
- /*Cb qi=42 INTRA*/
- {
- { 9, 3},{ 113, 371},{ 199, 743},{ 279, 1123},
- { 390, 1462},{ 525, 1743},{ 662, 1986},{ 789, 2208},
- { 916, 2406},{ 1057, 2571},{ 1204, 2712},{ 1362, 2835},
- { 1524, 2943},{ 1676, 3040},{ 1815, 3145},{ 1959, 3249},
- { 2117, 3325},{ 2249, 3406},{ 2377, 3488},{ 2537, 3547},
- { 2706, 3597},{ 2854, 3646},{ 2999, 3705},{ 3236, 3759}
- },
- /*Cb qi=42 INTER*/
- {
- { 114, 44},{ 107, 353},{ 101, 670},{ 111, 1041},
- { 129, 1418},{ 148, 1775},{ 174, 2110},{ 208, 2432},
- { 244, 2746},{ 283, 3046},{ 330, 3330},{ 388, 3602},
- { 460, 3858},{ 546, 4101},{ 655, 4326},{ 793, 4530},
- { 966, 4703},{ 1165, 4851},{ 1388, 4980},{ 1630, 5088},
- { 1869, 5189},{ 2122, 5268},{ 2403, 5328},{ 2667, 5417}
- }
- },
- {
- /*Cr qi=42 INTRA*/
- {
- { 15, 7},{ 120, 390},{ 202, 771},{ 298, 1150},
- { 421, 1473},{ 553, 1743},{ 681, 1982},{ 796, 2199},
- { 923, 2388},{ 1062, 2547},{ 1225, 2678},{ 1392, 2792},
- { 1531, 2907},{ 1682, 3007},{ 1856, 3074},{ 2009, 3134},
- { 2138, 3192},{ 2274, 3257},{ 2407, 3333},{ 2536, 3393},
- { 2711, 3455},{ 2875, 3531},{ 3000, 3598},{ 3186, 3599}
- },
- /*Cr qi=42 INTER*/
- {
- { 87, -4},{ 95, 358},{ 97, 683},{ 113, 1052},
- { 131, 1423},{ 148, 1774},{ 170, 2116},{ 198, 2448},
- { 234, 2762},{ 276, 3062},{ 331, 3343},{ 404, 3603},
- { 494, 3844},{ 598, 4067},{ 715, 4276},{ 842, 4471},
- { 977, 4661},{ 1128, 4840},{ 1311, 4991},{ 1516, 5127},
- { 1759, 5233},{ 2050, 5300},{ 2377, 5323},{ 2710, 5304}
- }
- }
- },
- {
- {
- /*Y' qi=43 INTRA*/
- {
- { 99, 79},{ 557, 1244},{ 1175, 2016},{ 1882, 2408},
- { 2570, 2677},{ 3288, 2926},{ 4030, 3141},{ 4760, 3307},
- { 5458, 3435},{ 6115, 3537},{ 6743, 3608},{ 7312, 3636},
- { 7841, 3652},{ 8357, 3687},{ 8870, 3742},{ 9376, 3788},
- { 9850, 3821},{10315, 3853},{10734, 3873},{11084, 3870},
- {11442, 3862},{11800, 3874},{12160, 3879},{12618, 3876}
- },
- /*Y' qi=43 INTER*/
- {
- { 69, -22},{ 134, 1331},{ 294, 2601},{ 551, 3703},
- { 1056, 4563},{ 2003, 5061},{ 3276, 5215},{ 4534, 5194},
- { 5599, 5133},{ 6488, 5083},{ 7257, 5044},{ 7938, 5014},
- { 8556, 4992},{ 9124, 4975},{ 9648, 4960},{10138, 4948},
- {10594, 4939},{11039, 4926},{11462, 4919},{11847, 4912},
- {12216, 4904},{12570, 4896},{12883, 4889},{13189, 4879}
- }
- },
- {
- /*Cb qi=43 INTRA*/
- {
- { 9, 3},{ 114, 371},{ 202, 740},{ 294, 1110},
- { 417, 1440},{ 558, 1716},{ 700, 1956},{ 833, 2172},
- { 966, 2365},{ 1116, 2524},{ 1269, 2661},{ 1431, 2781},
- { 1599, 2885},{ 1756, 2980},{ 1902, 3082},{ 2051, 3185},
- { 2209, 3261},{ 2337, 3342},{ 2464, 3420},{ 2633, 3475},
- { 2809, 3525},{ 2948, 3579},{ 3094, 3633},{ 3347, 3678}
- },
- /*Cb qi=43 INTER*/
- {
- { 111, 44},{ 106, 353},{ 102, 670},{ 112, 1040},
- { 128, 1416},{ 148, 1771},{ 176, 2104},{ 211, 2424},
- { 250, 2734},{ 293, 3030},{ 347, 3309},{ 411, 3575},
- { 490, 3828},{ 589, 4064},{ 716, 4278},{ 869, 4472},
- { 1050, 4640},{ 1264, 4781},{ 1512, 4895},{ 1775, 4991},
- { 2042, 5069},{ 2310, 5141},{ 2593, 5207},{ 2912, 5239}
- }
- },
- {
- /*Cr qi=43 INTRA*/
- {
- { 15, 7},{ 121, 390},{ 208, 767},{ 315, 1135},
- { 449, 1449},{ 586, 1715},{ 718, 1950},{ 843, 2158},
- { 977, 2342},{ 1120, 2501},{ 1290, 2632},{ 1466, 2739},
- { 1613, 2845},{ 1763, 2945},{ 1937, 3015},{ 2093, 3070},
- { 2225, 3126},{ 2366, 3194},{ 2501, 3267},{ 2634, 3324},
- { 2815, 3385},{ 2964, 3466},{ 3087, 3538},{ 3263, 3555}
- },
- /*Cr qi=43 INTER*/
- {
- { 84, -4},{ 93, 358},{ 95, 683},{ 113, 1052},
- { 131, 1421},{ 148, 1770},{ 171, 2110},{ 201, 2439},
- { 240, 2750},{ 287, 3046},{ 348, 3322},{ 429, 3576},
- { 527, 3811},{ 641, 4029},{ 767, 4230},{ 904, 4422},
- { 1053, 4603},{ 1225, 4765},{ 1433, 4903},{ 1661, 5030},
- { 1928, 5121},{ 2252, 5160},{ 2604, 5164},{ 2979, 5125}
- }
- }
- },
- {
- {
- /*Y' qi=44 INTRA*/
- {
- { 103, 80},{ 560, 1244},{ 1183, 2009},{ 1891, 2391},
- { 2586, 2649},{ 3324, 2884},{ 4093, 3089},{ 4850, 3243},
- { 5575, 3358},{ 6252, 3452},{ 6886, 3518},{ 7459, 3546},
- { 7993, 3562},{ 8515, 3594},{ 9030, 3645},{ 9534, 3691},
- {10004, 3723},{10469, 3750},{10887, 3765},{11236, 3766},
- {11596, 3762},{11960, 3775},{12317, 3784},{12766, 3789}
- },
- /*Y' qi=44 INTER*/
- {
- { 77, -24},{ 145, 1332},{ 332, 2580},{ 642, 3649},
- { 1270, 4438},{ 2360, 4860},{ 3685, 4982},{ 4910, 4966},
- { 5929, 4928},{ 6785, 4900},{ 7529, 4880},{ 8198, 4863},
- { 8804, 4850},{ 9361, 4842},{ 9882, 4836},{10371, 4830},
- {10827, 4822},{11262, 4816},{11672, 4811},{12052, 4807},
- {12431, 4806},{12780, 4798},{13095, 4792},{13401, 4791}
- }
- },
- {
- /*Cb qi=44 INTRA*/
- {
- { 9, 2},{ 122, 371},{ 214, 741},{ 307, 1109},
- { 433, 1432},{ 576, 1704},{ 718, 1939},{ 855, 2152},
- { 991, 2340},{ 1141, 2497},{ 1298, 2632},{ 1463, 2749},
- { 1636, 2851},{ 1796, 2944},{ 1947, 3041},{ 2101, 3140},
- { 2260, 3219},{ 2392, 3297},{ 2527, 3366},{ 2693, 3424},
- { 2872, 3477},{ 3025, 3525},{ 3175, 3584},{ 3451, 3626}
- },
- /*Cb qi=44 INTER*/
- {
- { 111, 14},{ 110, 339},{ 109, 671},{ 120, 1040},
- { 139, 1410},{ 162, 1758},{ 197, 2084},{ 243, 2397},
- { 291, 2702},{ 342, 2992},{ 405, 3265},{ 484, 3521},
- { 584, 3760},{ 705, 3983},{ 855, 4185},{ 1048, 4356},
- { 1274, 4500},{ 1531, 4617},{ 1816, 4707},{ 2111, 4783},
- { 2409, 4846},{ 2720, 4901},{ 3044, 4957},{ 3391, 4985}
- }
- },
- {
- /*Cr qi=44 INTRA*/
- {
- { 17, 7},{ 128, 392},{ 219, 770},{ 329, 1135},
- { 465, 1442},{ 601, 1703},{ 734, 1935},{ 862, 2142},
- { 998, 2325},{ 1147, 2482},{ 1321, 2606},{ 1496, 2710},
- { 1649, 2813},{ 1809, 2908},{ 1984, 2977},{ 2143, 3032},
- { 2279, 3087},{ 2423, 3152},{ 2559, 3225},{ 2684, 3288},
- { 2866, 3351},{ 3025, 3426},{ 3161, 3492},{ 3372, 3500}
- },
- /*Cr qi=44 INTER*/
- {
- { 89, 0},{ 101, 352},{ 104, 683},{ 121, 1051},
- { 141, 1414},{ 163, 1757},{ 192, 2092},{ 231, 2415},
- { 278, 2720},{ 336, 3007},{ 412, 3273},{ 510, 3516},
- { 633, 3733},{ 769, 3936},{ 914, 4130},{ 1076, 4307},
- { 1256, 4472},{ 1469, 4617},{ 1723, 4732},{ 2012, 4822},
- { 2347, 4871},{ 2716, 4875},{ 3082, 4866},{ 3422, 4826}
+ { 53, 45},{ 50, 467},{ 45, 789},{ 76, 1150},
+ { 92, 1531},{ 107, 1877},{ 125, 2219},{ 147, 2561},
+ { 176, 2893},{ 206, 3209},{ 231, 3514},{ 260, 3808},
+ { 298, 4085},{ 350, 4344},{ 411, 4587},{ 475, 4814},
+ { 532, 5037},{ 587, 5261},{ 647, 5480},{ 707, 5694},
+ { 793, 5900},{ 891, 6093},{ 1017, 6292},{ 1205, 6307}
}
}
},
@@ -2848,557 +341,61 @@ oc_mode_rd OC_MODE_RD[64][3][2][OC_SAD_BINS]={
{
/*Y' qi=45 INTRA*/
{
- { 119, 78},{ 610, 1226},{ 1271, 1965},{ 2026, 2319},
- { 2768, 2550},{ 3556, 2757},{ 4369, 2938},{ 5157, 3076},
- { 5901, 3182},{ 6598, 3268},{ 7253, 3326},{ 7844, 3343},
- { 8392, 3356},{ 8922, 3386},{ 9453, 3433},{ 9973, 3474},
- {10457, 3503},{10929, 3530},{11351, 3543},{11709, 3541},
- {12068, 3537},{12434, 3547},{12805, 3555},{13268, 3563}
+ { 47, 170},{ 955, 1217},{ 1713, 2014},{ 3050, 2094},
+ { 3954, 2179},{ 4801, 2357},{ 5629, 2494},{ 6313, 2614},
+ { 6962, 2716},{ 7566, 2820},{ 8138, 2886},{ 8613, 2949},
+ { 9097, 3031},{ 9574, 3044},{10053, 3142},{10514, 3134},
+ {10897, 3241},{11397, 3275},{11775, 3297},{12200, 3350},
+ {12527, 3350},{12959, 3393},{13246, 3401},{13573, 3397}
},
/*Y' qi=45 INTER*/
{
- { 77, -20},{ 146, 1330},{ 342, 2566},{ 699, 3604},
- { 1439, 4332},{ 2669, 4672},{ 4075, 4727},{ 5318, 4679},
- { 6345, 4630},{ 7209, 4595},{ 7963, 4570},{ 8644, 4551},
- { 9262, 4535},{ 9831, 4525},{10370, 4515},{10872, 4506},
- {11334, 4500},{11783, 4492},{12219, 4489},{12617, 4483},
- {12995, 4477},{13350, 4472},{13674, 4466},{13968, 4468}
+ { 53, 73},{ 175, 1343},{ 649, 2439},{ 1339, 3250},
+ { 2297, 3837},{ 3395, 4203},{ 4438, 4400},{ 5401, 4529},
+ { 6222, 4588},{ 7018, 4564},{ 7713, 4532},{ 8378, 4464},
+ { 8959, 4414},{ 9464, 4364},{ 9980, 4315},{10401, 4291},
+ {10805, 4260},{11172, 4260},{11501, 4231},{11798, 4248},
+ {12082, 4254},{12381, 4262},{12572, 4285},{12877, 4289}
}
},
{
/*Cb qi=45 INTRA*/
{
- { 9, 2},{ 122, 370},{ 219, 735},{ 324, 1096},
- { 465, 1414},{ 619, 1679},{ 771, 1905},{ 920, 2103},
- { 1070, 2276},{ 1236, 2419},{ 1410, 2539},{ 1595, 2644},
- { 1784, 2736},{ 1949, 2831},{ 2104, 2931},{ 2275, 3021},
- { 2443, 3092},{ 2586, 3166},{ 2735, 3234},{ 2904, 3288},
- { 3093, 3338},{ 3262, 3382},{ 3419, 3427},{ 3708, 3456}
+ { 112, -14},{ 173, 495},{ 260, 827},{ 355, 1122},
+ { 451, 1420},{ 579, 1695},{ 697, 1934},{ 917, 2101},
+ { 1104, 2244},{ 1266, 2381},{ 1417, 2520},{ 1609, 2611},
+ { 1801, 2689},{ 1973, 2764},{ 2108, 2864},{ 2298, 2948},
+ { 2452, 3008},{ 2588, 3080},{ 2732, 3161},{ 2888, 3203},
+ { 3052, 3266},{ 3240, 3294},{ 3342, 3351},{ 3467, 3373}
},
/*Cb qi=45 INTER*/
{
- { 103, 0},{ 109, 339},{ 109, 670},{ 119, 1039},
- { 137, 1408},{ 162, 1754},{ 199, 2076},{ 248, 2386},
- { 301, 2684},{ 360, 2967},{ 433, 3234},{ 525, 3481},
- { 640, 3713},{ 780, 3924},{ 956, 4110},{ 1176, 4266},
- { 1438, 4390},{ 1736, 4481},{ 2057, 4553},{ 2385, 4613},
- { 2718, 4656},{ 3056, 4698},{ 3416, 4733},{ 3799, 4755}
+ { 41, -49},{ 52, 385},{ 87, 743},{ 110, 1102},
+ { 135, 1453},{ 162, 1788},{ 207, 2096},{ 272, 2391},
+ { 330, 2677},{ 392, 2950},{ 464, 3205},{ 556, 3442},
+ { 674, 3656},{ 827, 3847},{ 1030, 4006},{ 1275, 4132},
+ { 1544, 4234},{ 1809, 4317},{ 2089, 4408},{ 2377, 4456},
+ { 2647, 4532},{ 2919, 4595},{ 3256, 4659},{ 3465, 4657}
}
},
{
/*Cr qi=45 INTRA*/
{
- { 16, 7},{ 128, 391},{ 225, 763},{ 350, 1120},
- { 500, 1420},{ 649, 1673},{ 792, 1893},{ 929, 2089},
- { 1084, 2257},{ 1250, 2401},{ 1440, 2518},{ 1633, 2614},
- { 1799, 2708},{ 1968, 2798},{ 2151, 2863},{ 2314, 2914},
- { 2453, 2968},{ 2611, 3025},{ 2759, 3095},{ 2887, 3160},
- { 3082, 3210},{ 3259, 3278},{ 3403, 3342},{ 3593, 3354}
+ { 99, -14},{ 164, 493},{ 247, 832},{ 358, 1123},
+ { 468, 1416},{ 599, 1680},{ 795, 1886},{ 958, 2063},
+ { 1133, 2211},{ 1300, 2345},{ 1480, 2461},{ 1664, 2554},
+ { 1807, 2656},{ 1995, 2742},{ 2146, 2799},{ 2331, 2856},
+ { 2440, 2894},{ 2592, 2996},{ 2751, 3033},{ 2865, 3112},
+ { 3073, 3162},{ 3210, 3208},{ 3330, 3306},{ 3454, 3332}
},
/*Cr qi=45 INTER*/
{
- { 92, 0},{ 101, 352},{ 103, 682},{ 120, 1049},
- { 140, 1412},{ 163, 1752},{ 193, 2083},{ 234, 2402},
- { 287, 2702},{ 353, 2983},{ 442, 3240},{ 557, 3471},
- { 694, 3680},{ 846, 3873},{ 1014, 4056},{ 1200, 4224},
- { 1414, 4369},{ 1664, 4495},{ 1946, 4595},{ 2278, 4654},
- { 2654, 4673},{ 3047, 4658},{ 3438, 4627},{ 3825, 4585}
- }
- }
- },
- {
- {
- /*Y' qi=46 INTRA*/
- {
- { 119, 78},{ 610, 1227},{ 1277, 1960},{ 2043, 2309},
- { 2805, 2529},{ 3618, 2719},{ 4452, 2887},{ 5257, 3016},
- { 6017, 3115},{ 6727, 3195},{ 7392, 3248},{ 7984, 3267},
- { 8528, 3281},{ 9059, 3310},{ 9593, 3354},{10119, 3395},
- {10599, 3425},{11064, 3450},{11493, 3464},{11850, 3466},
- {12207, 3462},{12578, 3471},{12948, 3480},{13407, 3487}
- },
- /*Y' qi=46 INTER*/
- {
- { 74, -14},{ 149, 1326},{ 382, 2538},{ 807, 3541},
- { 1670, 4211},{ 3000, 4499},{ 4416, 4533},{ 5628, 4490},
- { 6628, 4453},{ 7479, 4425},{ 8228, 4406},{ 8902, 4393},
- { 9521, 4380},{10090, 4371},{10623, 4364},{11124, 4356},
- {11586, 4351},{12043, 4344},{12476, 4341},{12863, 4340},
- {13244, 4337},{13610, 4329},{13936, 4324},{14246, 4329}
- }
- },
- {
- /*Cb qi=46 INTRA*/
- {
- { 11, 2},{ 132, 371},{ 234, 737},{ 340, 1094},
- { 481, 1405},{ 637, 1667},{ 791, 1891},{ 944, 2084},
- { 1099, 2253},{ 1268, 2392},{ 1444, 2507},{ 1633, 2610},
- { 1825, 2700},{ 1990, 2794},{ 2147, 2895},{ 2321, 2984},
- { 2493, 3053},{ 2640, 3126},{ 2787, 3198},{ 2954, 3253},
- { 3146, 3297},{ 3313, 3344},{ 3473, 3393},{ 3757, 3434}
- },
- /*Cb qi=46 INTER*/
- {
- { 97, 0},{ 109, 339},{ 108, 669},{ 120, 1035},
- { 142, 1398},{ 173, 1737},{ 221, 2052},{ 281, 2353},
- { 345, 2646},{ 415, 2924},{ 504, 3183},{ 616, 3421},
- { 749, 3643},{ 914, 3842},{ 1123, 4012},{ 1379, 4150},
- { 1685, 4250},{ 2014, 4327},{ 2366, 4382},{ 2731, 4426},
- { 3083, 4470},{ 3445, 4490},{ 3805, 4511},{ 4146, 4539}
- }
- },
- {
- /*Cr qi=46 INTRA*/
- {
- { 19, 7},{ 137, 393},{ 237, 765},{ 364, 1116},
- { 516, 1411},{ 665, 1662},{ 809, 1880},{ 951, 2072},
- { 1109, 2236},{ 1278, 2378},{ 1474, 2491},{ 1669, 2584},
- { 1835, 2678},{ 2014, 2766},{ 2203, 2828},{ 2366, 2880},
- { 2506, 2933},{ 2661, 2988},{ 2810, 3053},{ 2941, 3116},
- { 3131, 3175},{ 3310, 3243},{ 3461, 3303},{ 3656, 3321}
- },
- /*Cr qi=46 INTER*/
- {
- { 91, 1},{ 103, 351},{ 104, 681},{ 121, 1046},
- { 144, 1401},{ 173, 1736},{ 213, 2060},{ 265, 2373},
- { 330, 2666},{ 410, 2938},{ 517, 3185},{ 655, 3404},
- { 815, 3601},{ 989, 3784},{ 1183, 3951},{ 1400, 4104},
- { 1649, 4241},{ 1933, 4352},{ 2261, 4427},{ 2646, 4458},
- { 3057, 4446},{ 3453, 4418},{ 3820, 4385},{ 4171, 4352}
- }
- }
- },
- {
- {
- /*Y' qi=47 INTRA*/
- {
- { 117, 83},{ 670, 1205},{ 1408, 1904},{ 2239, 2219},
- { 3049, 2414},{ 3905, 2584},{ 4775, 2734},{ 5610, 2852},
- { 6393, 2944},{ 7121, 3017},{ 7804, 3066},{ 8407, 3081},
- { 8957, 3093},{ 9498, 3119},{10043, 3160},{10582, 3199},
- {11083, 3226},{11561, 3250},{11993, 3263},{12352, 3264},
- {12711, 3259},{13092, 3266},{13463, 3271},{13918, 3275}
- },
- /*Y' qi=47 INTER*/
- {
- { 74, -11},{ 148, 1325},{ 404, 2518},{ 910, 3478},
- { 1916, 4080},{ 3369, 4298},{ 4823, 4292},{ 6035, 4238},
- { 7037, 4197},{ 7894, 4168},{ 8650, 4146},{ 9337, 4129},
- { 9968, 4116},{10549, 4105},{11096, 4096},{11605, 4089},
- {12081, 4083},{12547, 4076},{12990, 4070},{13399, 4070},
- {13776, 4065},{14133, 4059},{14486, 4057},{14842, 4053}
- }
- },
- {
- /*Cb qi=47 INTRA*/
- {
- { 11, 2},{ 133, 370},{ 242, 731},{ 367, 1077},
- { 524, 1378},{ 692, 1630},{ 860, 1844},{ 1028, 2024},
- { 1203, 2178},{ 1393, 2305},{ 1582, 2413},{ 1787, 2507},
- { 1992, 2590},{ 2175, 2676},{ 2351, 2767},{ 2534, 2851},
- { 2707, 2923},{ 2862, 2994},{ 3021, 3060},{ 3193, 3111},
- { 3396, 3147},{ 3573, 3184},{ 3752, 3220},{ 4038, 3255}
- },
- /*Cb qi=47 INTER*/
- {
- { 101, 0},{ 107, 339},{ 108, 667},{ 120, 1033},
- { 142, 1394},{ 175, 1729},{ 227, 2040},{ 295, 2335},
- { 369, 2619},{ 452, 2888},{ 556, 3138},{ 686, 3368},
- { 850, 3574},{ 1050, 3758},{ 1299, 3910},{ 1605, 4024},
- { 1950, 4104},{ 2317, 4163},{ 2689, 4210},{ 3077, 4239},
- { 3466, 4258},{ 3840, 4278},{ 4205, 4298},{ 4515, 4340}
- }
- },
- {
- /*Cr qi=47 INTRA*/
- {
- { 19, 7},{ 138, 392},{ 248, 758},{ 396, 1094},
- { 563, 1378},{ 723, 1621},{ 881, 1829},{ 1037, 2011},
- { 1214, 2165},{ 1410, 2290},{ 1623, 2393},{ 1834, 2480},
- { 2016, 2564},{ 2203, 2647},{ 2405, 2707},{ 2569, 2757},
- { 2709, 2810},{ 2871, 2860},{ 3027, 2924},{ 3178, 2980},
- { 3375, 3034},{ 3563, 3097},{ 3724, 3151},{ 3952, 3153}
- },
- /*Cr qi=47 INTER*/
- {
- { 91, 1},{ 100, 351},{ 102, 681},{ 120, 1043},
- { 144, 1397},{ 175, 1729},{ 219, 2049},{ 277, 2356},
- { 353, 2640},{ 451, 2902},{ 579, 3136},{ 739, 3342},
- { 926, 3525},{ 1125, 3698},{ 1343, 3859},{ 1595, 3998},
- { 1881, 4113},{ 2208, 4205},{ 2589, 4253},{ 3014, 4250},
- { 3444, 4220},{ 3838, 4183},{ 4196, 4147},{ 4521, 4116}
- }
- }
- },
- {
- {
- /*Y' qi=48 INTRA*/
- {
- { 107, 87},{ 681, 1200},{ 1456, 1883},{ 2306, 2193},
- { 3122, 2386},{ 3984, 2548},{ 4862, 2693},{ 5704, 2808},
- { 6495, 2899},{ 7232, 2970},{ 7915, 3018},{ 8524, 3034},
- { 9085, 3043},{ 9635, 3068},{10192, 3108},{10735, 3145},
- {11237, 3171},{11719, 3194},{12153, 3207},{12516, 3206},
- {12888, 3202},{13266, 3210},{13637, 3218},{14101, 3219}
- },
- /*Y' qi=48 INTER*/
- {
- { 83, -18},{ 147, 1328},{ 398, 2519},{ 923, 3468},
- { 1979, 4047},{ 3472, 4246},{ 4936, 4232},{ 6148, 4178},
- { 7150, 4139},{ 8007, 4111},{ 8765, 4091},{ 9458, 4076},
- {10090, 4063},{10676, 4054},{11226, 4045},{11742, 4038},
- {12223, 4033},{12686, 4029},{13127, 4022},{13527, 4015},
- {13915, 4012},{14277, 4007},{14619, 4004},{14966, 4001}
- }
- },
- {
- /*Cb qi=48 INTRA*/
- {
- { 11, 2},{ 134, 369},{ 245, 730},{ 373, 1075},
- { 531, 1374},{ 698, 1625},{ 865, 1839},{ 1033, 2019},
- { 1207, 2173},{ 1397, 2300},{ 1588, 2408},{ 1795, 2501},
- { 2003, 2581},{ 2187, 2666},{ 2362, 2757},{ 2548, 2841},
- { 2719, 2912},{ 2876, 2983},{ 3034, 3047},{ 3209, 3097},
- { 3409, 3137},{ 3589, 3178},{ 3762, 3216},{ 4004, 3252}
- },
- /*Cb qi=48 INTER*/
- {
- { 113, 26},{ 112, 344},{ 111, 668},{ 120, 1032},
- { 141, 1392},{ 173, 1727},{ 224, 2036},{ 290, 2330},
- { 363, 2612},{ 447, 2880},{ 551, 3130},{ 685, 3358},
- { 852, 3563},{ 1061, 3742},{ 1332, 3884},{ 1654, 3993},
- { 2011, 4068},{ 2394, 4120},{ 2782, 4160},{ 3172, 4186},
- { 3557, 4209},{ 3932, 4228},{ 4306, 4237},{ 4675, 4236}
- }
- },
- {
- /*Cr qi=48 INTRA*/
- {
- { 18, 7},{ 139, 389},{ 252, 755},{ 404, 1090},
- { 573, 1372},{ 732, 1615},{ 889, 1823},{ 1045, 2005},
- { 1222, 2159},{ 1417, 2285},{ 1631, 2387},{ 1843, 2474},
- { 2027, 2558},{ 2212, 2639},{ 2413, 2697},{ 2578, 2746},
- { 2720, 2798},{ 2887, 2852},{ 3040, 2913},{ 3181, 2970},
- { 3381, 3024},{ 3581, 3081},{ 3743, 3130},{ 3948, 3133}
- },
- /*Cr qi=48 INTER*/
- {
- { 89, 0},{ 106, 352},{ 105, 682},{ 120, 1044},
- { 144, 1395},{ 174, 1724},{ 215, 2044},{ 270, 2350},
- { 343, 2635},{ 441, 2895},{ 571, 3129},{ 735, 3334},
- { 926, 3518},{ 1139, 3684},{ 1371, 3836},{ 1628, 3977},
- { 1933, 4089},{ 2279, 4164},{ 2672, 4204},{ 3105, 4205},
- { 3533, 4176},{ 3931, 4135},{ 4290, 4089},{ 4624, 4057}
- }
- }
- },
- {
- {
- /*Y' qi=49 INTRA*/
- {
- { 120, 85},{ 706, 1194},{ 1485, 1875},{ 2348, 2187},
- { 3190, 2372},{ 4076, 2521},{ 4967, 2658},{ 5819, 2771},
- { 6611, 2861},{ 7345, 2936},{ 8026, 2990},{ 8626, 3013},
- { 9182, 3030},{ 9723, 3059},{10266, 3100},{10802, 3143},
- {11293, 3179},{11768, 3206},{12201, 3221},{12556, 3225},
- {12914, 3226},{13281, 3237},{13639, 3247},{14089, 3257}
- },
- /*Y' qi=49 INTER*/
- {
- { 72, -11},{ 155, 1320},{ 458, 2485},{ 1090, 3386},
- { 2284, 3907},{ 3835, 4075},{ 5272, 4064},{ 6449, 4026},
- { 7426, 4003},{ 8267, 3987},{ 9017, 3976},{ 9698, 3967},
- {10328, 3962},{10913, 3959},{11452, 3954},{11961, 3950},
- {12442, 3947},{12904, 3946},{13347, 3945},{13749, 3943},
- {14123, 3941},{14490, 3941},{14826, 3939},{15153, 3937}
- }
- },
- {
- /*Cb qi=49 INTRA*/
- {
- { 11, 2},{ 145, 369},{ 262, 729},{ 393, 1070},
- { 557, 1363},{ 731, 1607},{ 907, 1811},{ 1085, 1983},
- { 1268, 2130},{ 1465, 2251},{ 1658, 2359},{ 1868, 2454},
- { 2079, 2534},{ 2264, 2621},{ 2440, 2717},{ 2625, 2802},
- { 2792, 2878},{ 2945, 2954},{ 3106, 3021},{ 3277, 3075},
- { 3466, 3119},{ 3638, 3170},{ 3824, 3213},{ 4100, 3243}
- },
- /*Cb qi=49 INTER*/
- {
- { 98, -6},{ 113, 343},{ 110, 669},{ 122, 1029},
- { 149, 1380},{ 192, 1706},{ 258, 2007},{ 340, 2293},
- { 426, 2569},{ 525, 2831},{ 653, 3071},{ 814, 3287},
- { 1013, 3478},{ 1262, 3637},{ 1575, 3761},{ 1936, 3851},
- { 2328, 3910},{ 2741, 3949},{ 3163, 3970},{ 3559, 3994},
- { 3936, 4025},{ 4300, 4050},{ 4655, 4060},{ 4962, 4062}
- }
- },
- {
- /*Cr qi=49 INTRA*/
- {
- { 19, 7},{ 151, 389},{ 270, 753},{ 427, 1084},
- { 602, 1360},{ 767, 1595},{ 933, 1794},{ 1098, 1968},
- { 1285, 2115},{ 1489, 2237},{ 1699, 2342},{ 1912, 2435},
- { 2101, 2519},{ 2288, 2601},{ 2486, 2663},{ 2651, 2715},
- { 2799, 2769},{ 2958, 2825},{ 3106, 2890},{ 3257, 2948},
- { 3452, 3007},{ 3634, 3075},{ 3786, 3136},{ 3959, 3164}
- },
- /*Cr qi=49 INTER*/
- {
- { 85, 1},{ 103, 352},{ 104, 681},{ 121, 1039},
- { 152, 1382},{ 195, 1702},{ 248, 2015},{ 316, 2316},
- { 403, 2595},{ 520, 2847},{ 676, 3068},{ 870, 3258},
- { 1091, 3429},{ 1329, 3585},{ 1597, 3725},{ 1894, 3849},
- { 2242, 3940},{ 2656, 3984},{ 3098, 3992},{ 3531, 3981},
- { 3936, 3950},{ 4304, 3915},{ 4646, 3879},{ 4915, 3861}
- }
- }
- },
- {
- {
- /*Y' qi=50 INTRA*/
- {
- { 122, 89},{ 798, 1170},{ 1682, 1812},{ 2613, 2096},
- { 3501, 2260},{ 4430, 2388},{ 5352, 2510},{ 6228, 2613},
- { 7043, 2698},{ 7793, 2770},{ 8486, 2823},{ 9092, 2846},
- { 9652, 2865},{10210, 2895},{10773, 2936},{11315, 2979},
- {11817, 3014},{12297, 3041},{12734, 3057},{13097, 3064},
- {13443, 3067},{13813, 3078},{14190, 3088},{14646, 3103}
- },
- /*Y' qi=50 INTER*/
- {
- { 73, -11},{ 154, 1318},{ 501, 2457},{ 1281, 3291},
- { 2685, 3719},{ 4356, 3810},{ 5811, 3769},{ 6988, 3726},
- { 7976, 3700},{ 8835, 3682},{ 9606, 3669},{10307, 3659},
- {10953, 3652},{11556, 3645},{12115, 3643},{12641, 3640},
- {13138, 3636},{13613, 3634},{14068, 3629},{14488, 3627},
- {14876, 3625},{15237, 3621},{15585, 3623},{15922, 3629}
- }
- },
- {
- /*Cb qi=50 INTRA*/
- {
- { 11, 2},{ 148, 368},{ 278, 724},{ 431, 1052},
- { 613, 1334},{ 806, 1567},{ 1004, 1756},{ 1203, 1915},
- { 1405, 2051},{ 1621, 2163},{ 1833, 2262},{ 2059, 2347},
- { 2280, 2424},{ 2476, 2512},{ 2670, 2598},{ 2864, 2679},
- { 3037, 2754},{ 3201, 2826},{ 3376, 2887},{ 3562, 2936},
- { 3756, 2976},{ 3932, 3022},{ 4117, 3065},{ 4385, 3094}
- },
- /*Cb qi=50 INTER*/
- {
- { 92, -3},{ 112, 343},{ 109, 669},{ 121, 1027},
- { 149, 1375},{ 196, 1697},{ 270, 1992},{ 366, 2267},
- { 471, 2532},{ 594, 2782},{ 747, 3011},{ 942, 3212},
- { 1189, 3384},{ 1497, 3521},{ 1875, 3613},{ 2297, 3673},
- { 2739, 3710},{ 3195, 3725},{ 3644, 3737},{ 4057, 3751},
- { 4445, 3763},{ 4841, 3769},{ 5211, 3779},{ 5568, 3769}
- }
- },
- {
- /*Cr qi=50 INTRA*/
- {
- { 19, 7},{ 155, 388},{ 290, 744},{ 474, 1060},
- { 666, 1324},{ 847, 1549},{ 1033, 1737},{ 1219, 1898},
- { 1428, 2034},{ 1653, 2147},{ 1885, 2245},{ 2115, 2329},
- { 2316, 2410},{ 2517, 2486},{ 2730, 2539},{ 2901, 2586},
- { 3042, 2638},{ 3199, 2693},{ 3366, 2755},{ 3534, 2805},
- { 3738, 2858},{ 3934, 2916},{ 4079, 2975},{ 4257, 2992}
- },
- /*Cr qi=50 INTER*/
- {
- { 87, 1},{ 102, 353},{ 103, 680},{ 121, 1036},
- { 153, 1377},{ 199, 1694},{ 260, 1999},{ 339, 2291},
- { 446, 2559},{ 590, 2797},{ 780, 3003},{ 1010, 3176},
- { 1267, 3331},{ 1547, 3474},{ 1874, 3594},{ 2245, 3688},
- { 2666, 3742},{ 3130, 3758},{ 3594, 3748},{ 4028, 3711},
- { 4415, 3674},{ 4771, 3641},{ 5122, 3605},{ 5482, 3569}
- }
- }
- },
- {
- {
- /*Y' qi=51 INTRA*/
- {
- { 115, 93},{ 819, 1164},{ 1739, 1806},{ 2695, 2101},
- { 3612, 2257},{ 4552, 2374},{ 5479, 2490},{ 6352, 2593},
- { 7158, 2683},{ 7898, 2761},{ 8580, 2823},{ 9177, 2854},
- { 9728, 2880},{10268, 2917},{10816, 2966},{11350, 3016},
- {11834, 3058},{12311, 3089},{12741, 3109},{13092, 3119},
- {13434, 3126},{13791, 3142},{14156, 3155},{14590, 3171}
- },
- /*Y' qi=51 INTER*/
- {
- { 58, 0},{ 171, 1307},{ 610, 2407},{ 1563, 3175},
- { 3116, 3545},{ 4789, 3624},{ 6185, 3602},{ 7320, 3583},
- { 8282, 3574},{ 9124, 3569},{ 9878, 3567},{10569, 3565},
- {11207, 3563},{11801, 3564},{12359, 3566},{12884, 3567},
- {13373, 3568},{13841, 3567},{14289, 3566},{14699, 3568},
- {15086, 3568},{15446, 3566},{15788, 3564},{16103, 3568}
- }
- },
- {
- /*Cb qi=51 INTRA*/
- {
- { 14, 3},{ 161, 369},{ 297, 722},{ 454, 1047},
- { 639, 1325},{ 833, 1554},{ 1033, 1742},{ 1236, 1897},
- { 1440, 2032},{ 1653, 2148},{ 1860, 2253},{ 2077, 2347},
- { 2288, 2432},{ 2476, 2525},{ 2661, 2621},{ 2841, 2714},
- { 3010, 2797},{ 3170, 2876},{ 3333, 2945},{ 3510, 3000},
- { 3696, 3054},{ 3865, 3114},{ 4046, 3164},{ 4317, 3200}
- },
- /*Cb qi=51 INTER*/
- {
- { 88, -11},{ 109, 341},{ 109, 668},{ 126, 1019},
- { 168, 1358},{ 233, 1670},{ 329, 1955},{ 451, 2219},
- { 584, 2472},{ 736, 2711},{ 931, 2923},{ 1179, 3104},
- { 1480, 3254},{ 1846, 3368},{ 2265, 3448},{ 2714, 3501},
- { 3180, 3524},{ 3638, 3529},{ 4074, 3543},{ 4485, 3560},
- { 4868, 3571},{ 5238, 3581},{ 5597, 3594},{ 5953, 3591}
- }
- },
- {
- /*Cr qi=51 INTRA*/
- {
- { 24, 7},{ 168, 388},{ 309, 742},{ 496, 1054},
- { 688, 1316},{ 873, 1538},{ 1063, 1723},{ 1252, 1882},
- { 1460, 2018},{ 1682, 2134},{ 1907, 2238},{ 2125, 2332},
- { 2317, 2422},{ 2507, 2510},{ 2705, 2575},{ 2869, 2630},
- { 3015, 2684},{ 3178, 2744},{ 3329, 2815},{ 3477, 2878},
- { 3667, 2945},{ 3848, 3016},{ 3997, 3082},{ 4174, 3121}
- },
- /*Cr qi=51 INTER*/
- {
- { 83, -2},{ 102, 351},{ 102, 680},{ 126, 1029},
- { 172, 1359},{ 238, 1665},{ 321, 1962},{ 422, 2246},
- { 552, 2505},{ 733, 2728},{ 970, 2912},{ 1247, 3069},
- { 1552, 3209},{ 1876, 3338},{ 2251, 3440},{ 2692, 3502},
- { 3161, 3529},{ 3637, 3525},{ 4084, 3509},{ 4487, 3479},
- { 4850, 3444},{ 5181, 3419},{ 5507, 3406},{ 5786, 3398}
- }
- }
- },
- {
- {
- /*Y' qi=52 INTRA*/
- {
- { 117, 93},{ 814, 1168},{ 1729, 1822},{ 2706, 2119},
- { 3655, 2262},{ 4604, 2374},{ 5528, 2490},{ 6394, 2596},
- { 7189, 2691},{ 7921, 2777},{ 8596, 2846},{ 9184, 2885},
- { 9728, 2918},{10260, 2961},{10796, 3014},{11316, 3069},
- {11793, 3115},{12267, 3150},{12692, 3172},{13037, 3185},
- {13367, 3196},{13717, 3214},{14087, 3227},{14521, 3249}
- },
- /*Y' qi=52 INTER*/
- {
- { 52, 0},{ 169, 1308},{ 668, 2382},{ 1735, 3112},
- { 3384, 3451},{ 5077, 3519},{ 6461, 3506},{ 7587, 3496},
- { 8545, 3494},{ 9384, 3494},{10142, 3498},{10838, 3501},
- {11475, 3503},{12078, 3508},{12640, 3511},{13162, 3513},
- {13654, 3517},{14130, 3521},{14576, 3522},{14980, 3523},
- {15369, 3523},{15737, 3522},{16071, 3521},{16382, 3516}
- }
- },
- {
- /*Cb qi=52 INTRA*/
- {
- { 14, 3},{ 163, 369},{ 299, 722},{ 457, 1044},
- { 645, 1319},{ 843, 1545},{ 1050, 1728},{ 1261, 1879},
- { 1468, 2013},{ 1678, 2132},{ 1883, 2240},{ 2093, 2338},
- { 2301, 2428},{ 2488, 2523},{ 2667, 2619},{ 2843, 2718},
- { 3010, 2805},{ 3163, 2887},{ 3323, 2963},{ 3490, 3028},
- { 3665, 3087},{ 3841, 3145},{ 4011, 3197},{ 4289, 3230}
- },
- /*Cb qi=52 INTER*/
- {
- { 98, -7},{ 109, 342},{ 109, 668},{ 126, 1018},
- { 170, 1355},{ 242, 1663},{ 352, 1941},{ 490, 2195},
- { 642, 2439},{ 823, 2666},{ 1052, 2868},{ 1333, 3039},
- { 1670, 3178},{ 2074, 3280},{ 2524, 3348},{ 2996, 3390},
- { 3469, 3410},{ 3923, 3420},{ 4355, 3434},{ 4771, 3451},
- { 5166, 3468},{ 5532, 3483},{ 5885, 3499},{ 6263, 3501}
- }
- },
- {
- /*Cr qi=52 INTRA*/
- {
- { 25, 7},{ 170, 388},{ 312, 741},{ 500, 1051},
- { 694, 1310},{ 883, 1529},{ 1082, 1709},{ 1280, 1864},
- { 1491, 1998},{ 1710, 2117},{ 1932, 2225},{ 2143, 2324},
- { 2328, 2418},{ 2516, 2506},{ 2708, 2578},{ 2870, 2637},
- { 3017, 2693},{ 3170, 2758},{ 3312, 2835},{ 3455, 2901},
- { 3644, 2972},{ 3827, 3049},{ 3968, 3121},{ 4115, 3166}
- },
- /*Cr qi=52 INTER*/
- {
- { 86, -2},{ 101, 352},{ 100, 680},{ 126, 1028},
- { 175, 1356},{ 247, 1657},{ 341, 1948},{ 458, 2224},
- { 615, 2471},{ 828, 2681},{ 1091, 2857},{ 1395, 3008},
- { 1732, 3140},{ 2095, 3257},{ 2502, 3348},{ 2968, 3402},
- { 3457, 3420},{ 3926, 3413},{ 4360, 3388},{ 4759, 3357},
- { 5128, 3329},{ 5449, 3306},{ 5741, 3295},{ 6071, 3296}
- }
- }
- },
- {
- {
- /*Y' qi=53 INTRA*/
- {
- { 138, 93},{ 850, 1161},{ 1773, 1810},{ 2763, 2103},
- { 3722, 2245},{ 4675, 2360},{ 5600, 2483},{ 6464, 2597},
- { 7255, 2700},{ 7982, 2792},{ 8652, 2867},{ 9237, 2913},
- { 9775, 2950},{10302, 2998},{10834, 3058},{11347, 3121},
- {11826, 3169},{12299, 3207},{12713, 3235},{13054, 3250},
- {13387, 3265},{13744, 3286},{14110, 3302},{14515, 3323}
- },
- /*Y' qi=53 INTER*/
- {
- { 52, 2},{ 169, 1308},{ 680, 2377},{ 1763, 3103},
- { 3410, 3450},{ 5094, 3531},{ 6469, 3526},{ 7590, 3525},
- { 8547, 3530},{ 9385, 3534},{10139, 3540},{10835, 3548},
- {11479, 3553},{12075, 3559},{12634, 3565},{13159, 3570},
- {13650, 3573},{14124, 3576},{14575, 3580},{14993, 3583},
- {15375, 3584},{15744, 3584},{16091, 3583},{16421, 3586}
- }
- },
- {
- /*Cb qi=53 INTRA*/
- {
- { 14, 3},{ 167, 367},{ 317, 717},{ 492, 1033},
- { 687, 1306},{ 887, 1531},{ 1095, 1715},{ 1309, 1866},
- { 1517, 2000},{ 1729, 2119},{ 1932, 2227},{ 2146, 2325},
- { 2358, 2414},{ 2544, 2511},{ 2724, 2611},{ 2902, 2711},
- { 3070, 2800},{ 3227, 2878},{ 3381, 2954},{ 3548, 3021},
- { 3724, 3077},{ 3888, 3140},{ 4065, 3196},{ 4359, 3225}
- },
- /*Cb qi=53 INTER*/
- {
- { 93, -8},{ 110, 342},{ 108, 668},{ 125, 1018},
- { 170, 1355},{ 242, 1663},{ 353, 1939},{ 494, 2192},
- { 651, 2433},{ 838, 2658},{ 1076, 2856},{ 1368, 3022},
- { 1716, 3158},{ 2123, 3260},{ 2575, 3330},{ 3042, 3373},
- { 3507, 3396},{ 3962, 3413},{ 4394, 3430},{ 4797, 3452},
- { 5169, 3476},{ 5547, 3496},{ 5914, 3510},{ 6235, 3525}
- }
- },
- {
- /*Cr qi=53 INTRA*/
- {
- { 25, 7},{ 175, 386},{ 335, 734},{ 541, 1037},
- { 737, 1296},{ 926, 1516},{ 1125, 1696},{ 1324, 1851},
- { 1540, 1984},{ 1763, 2102},{ 1989, 2210},{ 2202, 2310},
- { 2386, 2404},{ 2572, 2495},{ 2768, 2569},{ 2929, 2627},
- { 3071, 2684},{ 3231, 2749},{ 3374, 2825},{ 3514, 2894},
- { 3703, 2963},{ 3882, 3040},{ 4024, 3111},{ 4190, 3150}
- },
- /*Cr qi=53 INTER*/
- {
- { 87, -1},{ 99, 352},{ 100, 680},{ 125, 1027},
- { 175, 1355},{ 249, 1657},{ 343, 1946},{ 462, 2220},
- { 624, 2465},{ 844, 2671},{ 1122, 2841},{ 1435, 2989},
- { 1768, 3125},{ 2134, 3243},{ 2545, 3334},{ 3002, 3393},
- { 3490, 3412},{ 3965, 3405},{ 4401, 3384},{ 4797, 3359},
- { 5156, 3328},{ 5482, 3297},{ 5800, 3292},{ 6135, 3293}
+ { 39, -33},{ 48, 403},{ 86, 744},{ 110, 1101},
+ { 134, 1461},{ 165, 1779},{ 205, 2095},{ 259, 2401},
+ { 318, 2686},{ 386, 2958},{ 481, 3204},{ 610, 3415},
+ { 753, 3603},{ 908, 3780},{ 1055, 3959},{ 1220, 4132},
+ { 1422, 4281},{ 1656, 4419},{ 1939, 4512},{ 2259, 4574},
+ { 2593, 4593},{ 2950, 4569},{ 3339, 4505},{ 3542, 4497}
}
}
},
@@ -3406,557 +403,563 @@ oc_mode_rd OC_MODE_RD[64][3][2][OC_SAD_BINS]={
{
/*Y' qi=54 INTRA*/
{
- { 184, 94},{ 902, 1151},{ 1876, 1776},{ 2881, 2057},
- { 3832, 2200},{ 4785, 2315},{ 5709, 2442},{ 6570, 2562},
- { 7362, 2672},{ 8092, 2771},{ 8760, 2852},{ 9337, 2901},
- { 9874, 2943},{10402, 2995},{10928, 3059},{11443, 3126},
- {11926, 3178},{12396, 3220},{12805, 3251},{13139, 3266},
- {13466, 3280},{13822, 3304},{14184, 3322},{14585, 3342}
+ { 339, 30},{ 785, 1251},{ 2395, 1971},{ 4075, 2063},
+ { 4924, 2135},{ 5806, 2270},{ 6604, 2372},{ 7224, 2497},
+ { 7879, 2608},{ 8400, 2729},{ 8951, 2829},{ 9379, 2864},
+ { 9782, 2955},{10230, 3020},{10704, 3132},{11264, 3272},
+ {11618, 3284},{12034, 3394},{12500, 3482},{12767, 3484},
+ {13162, 3580},{13552, 3565},{13997, 3732},{14320, 3715}
},
/*Y' qi=54 INTER*/
{
- { 60, 5},{ 169, 1308},{ 683, 2375},{ 1791, 3090},
- { 3478, 3412},{ 5184, 3470},{ 6568, 3455},{ 7697, 3446},
- { 8659, 3446},{ 9503, 3447},{10266, 3450},{10971, 3454},
- {11619, 3458},{12223, 3462},{12789, 3467},{13315, 3471},
- {13811, 3475},{14291, 3479},{14743, 3479},{15148, 3481},
- {15535, 3483},{15913, 3481},{16252, 3479},{16569, 3472}
+ { 65, 95},{ 269, 1312},{ 1152, 2242},{ 2336, 2863},
+ { 3728, 3239},{ 4944, 3439},{ 6034, 3543},{ 7064, 3580},
+ { 7991, 3586},{ 8849, 3568},{ 9605, 3561},{10306, 3550},
+ {10919, 3544},{11466, 3530},{11972, 3528},{12401, 3536},
+ {12818, 3511},{13185, 3522},{13523, 3505},{13827, 3505},
+ {14114, 3522},{14395, 3521},{14625, 3533},{14909, 3532}
}
},
{
/*Cb qi=54 INTRA*/
{
- { 13, 2},{ 165, 367},{ 318, 715},{ 498, 1030},
- { 698, 1301},{ 906, 1523},{ 1121, 1703},{ 1336, 1853},
- { 1549, 1984},{ 1765, 2100},{ 1974, 2207},{ 2192, 2306},
- { 2402, 2396},{ 2587, 2493},{ 2773, 2591},{ 2953, 2691},
- { 3119, 2778},{ 3277, 2858},{ 3430, 2940},{ 3603, 3004},
- { 3788, 3059},{ 3950, 3121},{ 4128, 3173},{ 4398, 3215}
+ { 148, -3},{ 218, 480},{ 351, 787},{ 437, 1069},
+ { 550, 1350},{ 730, 1592},{ 931, 1784},{ 1243, 1884},
+ { 1499, 1984},{ 1680, 2115},{ 1864, 2244},{ 2062, 2334},
+ { 2278, 2407},{ 2442, 2496},{ 2602, 2603},{ 2783, 2686},
+ { 2928, 2771},{ 3073, 2856},{ 3207, 2938},{ 3368, 2998},
+ { 3516, 3077},{ 3699, 3122},{ 3818, 3202},{ 3939, 3230}
},
/*Cb qi=54 INTER*/
{
- { 100, -3},{ 109, 343},{ 107, 668},{ 125, 1018},
- { 169, 1354},{ 241, 1662},{ 353, 1938},{ 496, 2190},
- { 655, 2431},{ 843, 2655},{ 1082, 2851},{ 1381, 3015},
- { 1739, 3146},{ 2154, 3243},{ 2610, 3310},{ 3094, 3344},
- { 3581, 3358},{ 4034, 3371},{ 4457, 3384},{ 4867, 3399},
- { 5255, 3413},{ 5630, 3425},{ 6003, 3440},{ 6346, 3440}
+ { 48, -11},{ 54, 407},{ 86, 743},{ 122, 1083},
+ { 176, 1400},{ 241, 1699},{ 347, 1968},{ 496, 2208},
+ { 664, 2431},{ 863, 2637},{ 1120, 2816},{ 1442, 2961},
+ { 1835, 3066},{ 2261, 3140},{ 2676, 3203},{ 3092, 3245},
+ { 3480, 3266},{ 3862, 3286},{ 4254, 3305},{ 4604, 3316},
+ { 4989, 3335},{ 5306, 3351},{ 5654, 3339},{ 5855, 3345}
}
},
{
/*Cr qi=54 INTRA*/
{
- { 23, 7},{ 174, 386},{ 338, 732},{ 549, 1034},
- { 751, 1289},{ 947, 1506},{ 1150, 1685},{ 1353, 1837},
- { 1572, 1969},{ 1800, 2087},{ 2031, 2192},{ 2248, 2291},
- { 2434, 2387},{ 2622, 2477},{ 2815, 2549},{ 2976, 2607},
- { 3126, 2663},{ 3286, 2727},{ 3427, 2807},{ 3569, 2877},
- { 3761, 2941},{ 3942, 3016},{ 4084, 3093},{ 4226, 3131}
+ { 137, 10},{ 212, 492},{ 315, 795},{ 470, 1061},
+ { 612, 1333},{ 821, 1539},{ 1105, 1680},{ 1335, 1811},
+ { 1566, 1927},{ 1773, 2038},{ 1973, 2153},{ 2148, 2259},
+ { 2311, 2352},{ 2474, 2460},{ 2647, 2516},{ 2810, 2607},
+ { 2928, 2638},{ 3085, 2742},{ 3232, 2815},{ 3348, 2899},
+ { 3533, 2993},{ 3679, 3029},{ 3803, 3138},{ 3925, 3170}
},
/*Cr qi=54 INTER*/
{
- { 88, -2},{ 99, 351},{ 100, 680},{ 125, 1027},
- { 175, 1354},{ 248, 1656},{ 343, 1945},{ 463, 2219},
- { 626, 2463},{ 850, 2668},{ 1128, 2837},{ 1445, 2983},
- { 1791, 3111},{ 2168, 3224},{ 2597, 3309},{ 3075, 3351},
- { 3560, 3364},{ 4029, 3356},{ 4464, 3335},{ 4858, 3307},
- { 5218, 3275},{ 5547, 3256},{ 5850, 3247},{ 6171, 3214}
+ { 46, 2},{ 47, 419},{ 87, 746},{ 125, 1083},
+ { 177, 1401},{ 249, 1687},{ 342, 1964},{ 453, 2226},
+ { 627, 2454},{ 869, 2641},{ 1152, 2800},{ 1455, 2942},
+ { 1776, 3077},{ 2135, 3187},{ 2524, 3287},{ 2984, 3325},
+ { 3425, 3344},{ 3881, 3328},{ 4313, 3274},{ 4701, 3218},
+ { 5027, 3171},{ 5299, 3130},{ 5597, 3107},{ 5791, 3120}
}
}
},
{
{
- /*Y' qi=55 INTRA*/
- {
- { 178, 95},{ 968, 1137},{ 2000, 1747},{ 3013, 2027},
- { 3966, 2173},{ 4920, 2294},{ 5842, 2427},{ 6702, 2553},
- { 7489, 2668},{ 8213, 2773},{ 8875, 2858},{ 9452, 2913},
- { 9986, 2959},{10504, 3016},{11023, 3085},{11530, 3157},
- {12011, 3213},{12480, 3257},{12882, 3291},{13214, 3310},
- {13542, 3325},{13890, 3350},{14248, 3371},{14671, 3398}
+ /*Y' qi=63 INTRA*/
+ {
+ { -86, 167},{ 2070, 1104},{ 5138, 1428},{ 7014, 1535},
+ { 8430, 1629},{ 9663, 1690},{10576, 1745},{11277, 1809},
+ {12003, 1869},{12663, 1925},{13258, 1983},{13701, 2016},
+ {14228, 2073},{14756, 2088},{15203, 2164},{15993, 2175},
+ {16378, 2256},{16917, 2240},{17361, 2332},{17782, 2312},
+ {18376, 2381},{18728, 2362},{19224, 2408},{19705, 2392}
},
- /*Y' qi=55 INTER*/
- {
- { 59, 5},{ 170, 1307},{ 725, 2358},{ 1886, 3058},
- { 3589, 3385},{ 5284, 3459},{ 6654, 3458},{ 7771, 3461},
- { 8727, 3470},{ 9564, 3478},{10322, 3488},{11019, 3497},
- {11658, 3505},{12258, 3513},{12819, 3520},{13344, 3527},
- {13840, 3533},{14314, 3537},{14755, 3541},{15161, 3544},
- {15552, 3548},{15916, 3548},{16257, 3548},{16576, 3540}
+ /*Y' qi=63 INTER*/
+ {
+ { -529, 154},{ 967, 1233},{ 4201, 1610},{ 6285, 1800},
+ { 8058, 1908},{ 9439, 1968},{10737, 1987},{11999, 1979},
+ {13003, 1972},{13854, 1963},{14584, 1965},{15217, 1955},
+ {15773, 1956},{16229, 1949},{16735, 1952},{17085, 1956},
+ {17508, 1956},{17821, 1961},{18191, 1961},{18465, 1982},
+ {18792, 1975},{19158, 1995},{19378, 2010},{19817, 2021}
}
},
{
- /*Cb qi=55 INTRA*/
- {
- { 13, 2},{ 167, 366},{ 322, 714},{ 508, 1026},
- { 716, 1292},{ 930, 1511},{ 1148, 1690},{ 1366, 1839},
- { 1578, 1972},{ 1793, 2090},{ 2001, 2199},{ 2217, 2300},
- { 2427, 2393},{ 2609, 2495},{ 2784, 2600},{ 2961, 2704},
- { 3121, 2797},{ 3268, 2884},{ 3423, 2965},{ 3590, 3032},
- { 3764, 3096},{ 3926, 3165},{ 4101, 3223},{ 4405, 3258}
+ /*Cb qi=63 INTRA*/
+ {
+ { 136, 4},{ 338, 438},{ 593, 730},{ 835, 974},
+ { 1168, 1188},{ 1602, 1345},{ 2004, 1467},{ 2465, 1505},
+ { 2799, 1574},{ 3091, 1669},{ 3384, 1758},{ 3673, 1817},
+ { 3950, 1861},{ 4190, 1924},{ 4444, 1993},{ 4701, 2051},
+ { 4915, 2123},{ 5119, 2166},{ 5329, 2231},{ 5576, 2259},
+ { 5793, 2310},{ 6001, 2334},{ 6198, 2384},{ 6344, 2401}
},
- /*Cb qi=55 INTER*/
- {
- { 90, -4},{ 109, 344},{ 107, 668},{ 126, 1017},
- { 172, 1351},{ 249, 1657},{ 370, 1928},{ 527, 2174},
- { 702, 2407},{ 909, 2624},{ 1170, 2814},{ 1493, 2970},
- { 1869, 3097},{ 2292, 3192},{ 2752, 3258},{ 3232, 3295},
- { 3709, 3314},{ 4156, 3335},{ 4592, 3355},{ 5004, 3373},
- { 5377, 3389},{ 5737, 3411},{ 6092, 3432},{ 6473, 3423}
+ /*Cb qi=63 INTER*/
+ {
+ { 49, 4},{ 51, 403},{ 98, 729},{ 185, 1034},
+ { 352, 1304},{ 622, 1533},{ 1068, 1696},{ 1604, 1821},
+ { 2203, 1924},{ 2890, 1988},{ 3622, 2017},{ 4359, 2019},
+ { 5025, 2005},{ 5586, 2002},{ 6090, 1989},{ 6519, 1977},
+ { 6927, 1977},{ 7305, 1968},{ 7730, 1984},{ 8087, 1981},
+ { 8435, 1991},{ 8822, 1987},{ 9155, 2008},{ 9392, 2011}
}
},
{
- /*Cr qi=55 INTRA*/
- {
- { 23, 7},{ 175, 385},{ 342, 730},{ 561, 1028},
- { 771, 1279},{ 973, 1493},{ 1181, 1669},{ 1384, 1822},
- { 1602, 1956},{ 1830, 2076},{ 2057, 2184},{ 2270, 2288},
- { 2452, 2389},{ 2637, 2484},{ 2823, 2559},{ 2983, 2621},
- { 3129, 2682},{ 3280, 2753},{ 3417, 2833},{ 3554, 2904},
- { 3743, 2977},{ 3921, 3060},{ 4055, 3137},{ 4185, 3186}
+ /*Cr qi=63 INTRA*/
+ {
+ { 131, 11},{ 334, 448},{ 569, 739},{ 929, 946},
+ { 1285, 1145},{ 1718, 1274},{ 2176, 1343},{ 2531, 1424},
+ { 2866, 1504},{ 3176, 1580},{ 3475, 1657},{ 3736, 1728},
+ { 3962, 1807},{ 4232, 1872},{ 4425, 1921},{ 4657, 1976},
+ { 4817, 2009},{ 5063, 2082},{ 5281, 2129},{ 5480, 2199},
+ { 5743, 2258},{ 5887, 2283},{ 6124, 2358},{ 6273, 2378}
},
- /*Cr qi=55 INTER*/
- {
- { 85, 0},{ 99, 352},{ 100, 679},{ 126, 1025},
- { 178, 1351},{ 256, 1650},{ 359, 1935},{ 493, 2202},
- { 675, 2439},{ 921, 2636},{ 1220, 2799},{ 1552, 2941},
- { 1910, 3068},{ 2303, 3177},{ 2735, 3262},{ 3206, 3311},
- { 3689, 3333},{ 4152, 3327},{ 4588, 3299},{ 4978, 3272},
- { 5325, 3243},{ 5651, 3221},{ 5969, 3210},{ 6218, 3185}
+ /*Cr qi=63 INTER*/
+ {
+ { 47, 15},{ 40, 405},{ 100, 730},{ 189, 1037},
+ { 351, 1303},{ 625, 1526},{ 984, 1719},{ 1512, 1862},
+ { 2189, 1947},{ 2895, 2003},{ 3576, 2046},{ 4249, 2072},
+ { 4901, 2068},{ 5514, 2043},{ 6079, 2009},{ 6528, 1977},
+ { 6927, 1940},{ 7274, 1915},{ 7580, 1894},{ 7910, 1910},
+ { 8211, 1902},{ 8472, 1920},{ 8742, 1926},{ 8981, 1930}
}
}
- },
+ }
+};
+
+# if !defined(OC_COLLECT_METRICS)
+static const
+# endif
+oc_mode_rd OC_MODE_RD_SAD[OC_LOGQ_BINS][3][2][OC_COMP_BINS]={
{
{
- /*Y' qi=56 INTRA*/
- {
- { 137, 104},{ 1048, 1128},{ 2147, 1760},{ 3261, 2029},
- { 4319, 2131},{ 5310, 2234},{ 6245, 2351},{ 7101, 2464},
- { 7886, 2572},{ 8610, 2675},{ 9270, 2762},{ 9840, 2818},
- {10365, 2869},{10875, 2928},{11393, 2997},{11900, 3071},
- {12371, 3128},{12834, 3172},{13233, 3208},{13562, 3228},
- {13878, 3245},{14221, 3271},{14584, 3292},{15008, 3320}
+ /*Y' qi=0 INTRA*/
+ {
+ { 33, 122},{ 57, 1297},{ 13, 2226},{ 157, 3890},
+ { 227, 3682},{ 169, 3084},{ 197, 2700},{ 227, 3238},
+ { 290, 4294},{ 354, 5230},{ 406, 5615},{ 417, 5322},
+ { 452, 5462},{ 455, 5683},{ 493, 5938},{ 553, 6374},
+ { 558, 6464},{ 606, 6493},{ 616, 6417},{ 643, 6557},
+ { 641, 6664},{ 716, 7285},{ 748, 7518},{ 747, 7502}
},
- /*Y' qi=56 INTER*/
- {
- { 19, 21},{ 207, 1292},{ 1031, 2252},{ 2553, 2846},
- { 4463, 3085},{ 6137, 3131},{ 7441, 3151},{ 8526, 3172},
- { 9468, 3193},{10301, 3209},{11059, 3224},{11760, 3237},
- {12405, 3249},{13008, 3261},{13570, 3270},{14100, 3278},
- {14597, 3284},{15074, 3289},{15524, 3297},{15929, 3302},
- {16314, 3306},{16675, 3307},{17004, 3305},{17288, 3301}
+ /*Y' qi=0 INTER*/
+ {
+ { 16, 205},{ 5, 1338},{ 16, 2554},{ 6, 3809},
+ { 9, 5188},{ 58, 6446},{ 76, 7561},{ 95, 8648},
+ { 124, 9713},{ 158,10787},{ 193,11887},{ 233,12991},
+ { 270,14116},{ 307,15236},{ 341,16346},{ 372,17426},
+ { 398,18499},{ 422,19594},{ 448,20669},{ 479,21732},
+ { 526,22720},{ 583,23572},{ 655,24516},{ 758,24647}
}
},
{
- /*Cb qi=56 INTRA*/
- {
- { 16, 3},{ 188, 367},{ 353, 712},{ 546, 1017},
- { 765, 1275},{ 989, 1484},{ 1221, 1653},{ 1459, 1791},
- { 1681, 1920},{ 1893, 2046},{ 2102, 2160},{ 2323, 2257},
- { 2534, 2347},{ 2720, 2447},{ 2902, 2549},{ 3075, 2654},
- { 3239, 2749},{ 3392, 2835},{ 3544, 2920},{ 3712, 2988},
- { 3882, 3052},{ 4052, 3123},{ 4227, 3181},{ 4483, 3213}
+ /*Cb qi=0 INTRA*/
+ {
+ { 26, 40},{ 23, 589},{ 27, 784},{ 27, 1079},
+ { 24, 1186},{ 25, 1641},{ 25, 1915},{ 29, 2207},
+ { 39, 2361},{ 39, 2746},{ 32, 3020},{ 16, 3387},
+ { 31, 3604},{ 36, 4076},{ 69, 4426},{ 102, 4724},
+ { 139, 4923},{ 196, 5061},{ 211, 5103},{ 214, 5063},
+ { 161, 4466},{ 208, 4793},{ 218, 4537},{ 219, 4539}
},
- /*Cb qi=56 INTER*/
- {
- { 92, -1},{ 111, 343},{ 114, 665},{ 148, 1003},
- { 224, 1321},{ 345, 1609},{ 526, 1858},{ 754, 2077},
- { 1009, 2281},{ 1319, 2464},{ 1702, 2614},{ 2145, 2732},
- { 2625, 2824},{ 3123, 2890},{ 3634, 2933},{ 4137, 2954},
- { 4614, 2965},{ 5052, 2988},{ 5468, 3015},{ 5852, 3035},
- { 6213, 3060},{ 6557, 3081},{ 6906, 3094},{ 7243, 3112}
+ /*Cb qi=0 INTER*/
+ {
+ { 3, 164},{ 1, 535},{ 1, 779},{ 2, 1048},
+ { 3, 1267},{ 1, 1625},{ 2, 1921},{ 5, 2224},
+ { 8, 2481},{ 8, 2813},{ 4, 3089},{ -2, 3386},
+ { -9, 3642},{ -14, 3993},{ -11, 4300},{ -6, 4628},
+ { 4, 4929},{ 25, 5299},{ 44, 5623},{ 83, 5915},
+ { 93, 6186},{ 91, 6483},{ 90, 6775},{ 95, 6952}
}
},
{
- /*Cr qi=56 INTRA*/
- {
- { 28, 8},{ 195, 385},{ 373, 727},{ 598, 1019},
- { 816, 1263},{ 1033, 1465},{ 1260, 1630},{ 1482, 1773},
- { 1717, 1900},{ 1949, 2018},{ 2178, 2128},{ 2393, 2233},
- { 2570, 2338},{ 2749, 2435},{ 2937, 2514},{ 3097, 2577},
- { 3240, 2638},{ 3398, 2709},{ 3540, 2791},{ 3673, 2865},
- { 3869, 2938},{ 4049, 3019},{ 4179, 3095},{ 4330, 3137}
+ /*Cr qi=0 INTRA*/
+ {
+ { 22, 49},{ 26, 579},{ 23, 762},{ 15, 1050},
+ { 20, 1191},{ 24, 1608},{ 26, 1875},{ 35, 2173},
+ { 39, 2359},{ 30, 2736},{ 16, 2987},{ 0, 3334},
+ { 14, 3625},{ 11, 4095},{ 57, 4512},{ 95, 4793},
+ { 141, 4949},{ 206, 5242},{ 230, 5191},{ 242, 5177},
+ { 178, 4775},{ 237, 5010},{ 223, 4656},{ 224, 4657}
},
- /*Cr qi=56 INTER*/
- {
- { 83, 0},{ 99, 353},{ 103, 676},{ 146, 1010},
- { 232, 1320},{ 355, 1601},{ 512, 1866},{ 713, 2109},
- { 988, 2312},{ 1344, 2471},{ 1750, 2602},{ 2180, 2719},
- { 2642, 2819},{ 3141, 2892},{ 3653, 2939},{ 4159, 2961},
- { 4636, 2961},{ 5072, 2945},{ 5464, 2917},{ 5813, 2895},
- { 6134, 2890},{ 6458, 2883},{ 6735, 2881},{ 6953, 2902}
+ /*Cr qi=0 INTER*/
+ {
+ { 3, 163},{ 1, 536},{ 1, 773},{ 3, 1023},
+ { 2, 1225},{ 1, 1607},{ 1, 1900},{ 5, 2204},
+ { 9, 2453},{ 8, 2781},{ 3, 3049},{ -5, 3338},
+ { -13, 3570},{ -17, 3950},{ -13, 4255},{ -6, 4596},
+ { 7, 4893},{ 33, 5300},{ 53, 5632},{ 97, 5942},
+ { 103, 6216},{ 96, 6522},{ 91, 6849},{ 98, 6995}
}
}
},
{
{
- /*Y' qi=57 INTRA*/
- {
- { 170, 106},{ 1106, 1120},{ 2246, 1740},{ 3399, 1993},
- { 4482, 2077},{ 5492, 2167},{ 6446, 2273},{ 7324, 2379},
- { 8130, 2482},{ 8866, 2578},{ 9537, 2661},{10119, 2715},
- {10646, 2762},{11161, 2820},{11694, 2886},{12214, 2957},
- {12693, 3013},{13166, 3053},{13569, 3087},{13897, 3106},
- {14224, 3122},{14568, 3148},{14931, 3167},{15390, 3192}
+ /*Y' qi=9 INTRA*/
+ {
+ { 47, 152},{ 50, 1213},{ 144, 2543},{ 242, 2332},
+ { 210, 1894},{ 250, 2386},{ 328, 3094},{ 407, 3419},
+ { 464, 3507},{ 522, 3770},{ 613, 4194},{ 657, 4618},
+ { 753, 5137},{ 796, 5248},{ 842, 5110},{ 927, 5330},
+ { 994, 5487},{ 1008, 5463},{ 1101, 5794},{ 1169, 5966},
+ { 1208, 6121},{ 1331, 6447},{ 1445, 6618},{ 1449, 6616}
},
- /*Y' qi=57 INTER*/
- {
- { 19, 20},{ 205, 1292},{ 1096, 2229},{ 2775, 2766},
- { 4811, 2943},{ 6512, 2964},{ 7832, 2976},{ 8940, 2990},
- { 9903, 3004},{10755, 3017},{11532, 3029},{12243, 3039},
- {12891, 3047},{13502, 3058},{14073, 3065},{14603, 3071},
- {15097, 3078},{15581, 3083},{16036, 3086},{16452, 3090},
- {16855, 3093},{17222, 3094},{17552, 3092},{17851, 3098}
+ /*Y' qi=9 INTER*/
+ {
+ { 4, 218},{ 16, 1314},{ 4, 2563},{ 37, 3882},
+ { 83, 5058},{ 109, 6184},{ 161, 7292},{ 224, 8389},
+ { 287, 9485},{ 349,10565},{ 411,11608},{ 464,12648},
+ { 518,13664},{ 575,14650},{ 649,15585},{ 742,16451},
+ { 862,17214},{ 1003,17860},{ 1179,18325},{ 1372,18648},
+ { 1576,18878},{ 1795,18903},{ 2040,18880},{ 2116,18759}
}
},
{
- /*Cb qi=57 INTRA*/
- {
- { 16, 3},{ 197, 365},{ 384, 704},{ 603, 1001},
- { 837, 1252},{ 1077, 1455},{ 1326, 1618},{ 1581, 1748},
- { 1819, 1871},{ 2042, 1993},{ 2264, 2104},{ 2500, 2196},
- { 2722, 2280},{ 2916, 2375},{ 3103, 2473},{ 3290, 2575},
- { 3456, 2667},{ 3612, 2748},{ 3775, 2829},{ 3958, 2896},
- { 4145, 2947},{ 4307, 3012},{ 4476, 3070},{ 4733, 3110}
+ /*Cb qi=9 INTRA*/
+ {
+ { 27, 42},{ 23, 587},{ 34, 782},{ 37, 1079},
+ { 34, 1204},{ 42, 1630},{ 37, 1887},{ 25, 2210},
+ { 40, 2455},{ 71, 2880},{ 112, 3193},{ 156, 3427},
+ { 168, 3403},{ 217, 3488},{ 203, 3335},{ 224, 3200},
+ { 191, 2742},{ 195, 2810},{ 207, 2665},{ 201, 2661},
+ { 169, 2078},{ 211, 2720},{ 226, 2813},{ 228, 2824}
},
- /*Cb qi=57 INTER*/
- {
- { 94, -1},{ 111, 344},{ 112, 665},{ 147, 1002},
- { 227, 1319},{ 353, 1604},{ 543, 1849},{ 785, 2062},
- { 1066, 2257},{ 1408, 2430},{ 1827, 2568},{ 2320, 2670},
- { 2848, 2743},{ 3386, 2791},{ 3934, 2812},{ 4453, 2820},
- { 4929, 2830},{ 5368, 2842},{ 5787, 2856},{ 6190, 2875},
- { 6554, 2896},{ 6895, 2913},{ 7229, 2927},{ 7572, 2932}
+ /*Cb qi=9 INTER*/
+ {
+ { 4, 158},{ 2, 537},{ 3, 779},{ 2, 1045},
+ { 3, 1284},{ 7, 1629},{ 7, 1917},{ 1, 2218},
+ { -4, 2497},{ -3, 2845},{ 6, 3162},{ 23, 3482},
+ { 42, 3788},{ 62, 4116},{ 76, 4416},{ 84, 4700},
+ { 91, 4975},{ 95, 5259},{ 97, 5518},{ 94, 5790},
+ { 99, 6052},{ 111, 6311},{ 126, 6601},{ 136, 6719}
}
},
{
- /*Cr qi=57 INTRA*/
- {
- { 28, 8},{ 207, 383},{ 413, 716},{ 661, 999},
- { 889, 1237},{ 1123, 1433},{ 1365, 1592},{ 1603, 1731},
- { 1853, 1852},{ 2103, 1965},{ 2345, 2072},{ 2571, 2173},
- { 2763, 2271},{ 2949, 2364},{ 3146, 2438},{ 3315, 2497},
- { 3459, 2552},{ 3618, 2616},{ 3767, 2697},{ 3906, 2773},
- { 4099, 2841},{ 4281, 2916},{ 4429, 2987},{ 4569, 3030}
+ /*Cr qi=9 INTRA*/
+ {
+ { 25, 50},{ 32, 576},{ 32, 762},{ 21, 1049},
+ { 28, 1207},{ 41, 1603},{ 36, 1839},{ 26, 2170},
+ { 34, 2462},{ 59, 2872},{ 109, 3176},{ 157, 3364},
+ { 188, 3397},{ 231, 3418},{ 250, 3341},{ 261, 3228},
+ { 222, 2814},{ 258, 3091},{ 234, 2915},{ 228, 3042},
+ { 210, 2610},{ 273, 3210},{ 274, 3231},{ 276, 3239}
},
- /*Cr qi=57 INTER*/
- {
- { 85, 0},{ 99, 352},{ 102, 675},{ 147, 1008},
- { 235, 1317},{ 363, 1597},{ 529, 1858},{ 748, 2094},
- { 1050, 2287},{ 1439, 2436},{ 1877, 2557},{ 2352, 2660},
- { 2869, 2740},{ 3413, 2791},{ 3962, 2815},{ 4485, 2819},
- { 4955, 2816},{ 5382, 2800},{ 5769, 2772},{ 6107, 2748},
- { 6443, 2740},{ 6754, 2739},{ 7029, 2737},{ 7284, 2745}
+ /*Cr qi=9 INTER*/
+ {
+ { 4, 156},{ 2, 538},{ 3, 772},{ 2, 1028},
+ { 3, 1254},{ 7, 1613},{ 7, 1893},{ 0, 2191},
+ { -8, 2454},{ -4, 2811},{ 7, 3121},{ 27, 3442},
+ { 48, 3749},{ 72, 4101},{ 88, 4410},{ 91, 4698},
+ { 99, 4988},{ 99, 5279},{ 101, 5542},{ 95, 5813},
+ { 99, 6088},{ 114, 6367},{ 125, 6683},{ 137, 6761}
}
}
},
{
{
- /*Y' qi=58 INTRA*/
- {
- { 164, 109},{ 1198, 1111},{ 2396, 1737},{ 3606, 1978},
- { 4727, 2048},{ 5749, 2138},{ 6708, 2243},{ 7584, 2347},
- { 8388, 2449},{ 9122, 2549},{ 9784, 2635},{10354, 2691},
- {10876, 2740},{11385, 2800},{11912, 2869},{12429, 2941},
- {12902, 2997},{13375, 3040},{13779, 3075},{14103, 3096},
- {14435, 3112},{14783, 3140},{15141, 3160},{15599, 3186}
+ /*Y' qi=18 INTRA*/
+ {
+ { 51, 88},{ 88, 1344},{ 258, 1643},{ 228, 1325},
+ { 372, 2208},{ 443, 2371},{ 520, 2382},{ 584, 2477},
+ { 739, 2906},{ 859, 3348},{ 1008, 3697},{ 1131, 3884},
+ { 1278, 4110},{ 1349, 4229},{ 1431, 4329},{ 1544, 4395},
+ { 1602, 4439},{ 1669, 4535},{ 1814, 4656},{ 1883, 4716},
+ { 1957, 4940},{ 2101, 5019},{ 2259, 5249},{ 2265, 5246}
},
- /*Y' qi=58 INTER*/
- {
- { 14, 23},{ 210, 1290},{ 1277, 2178},{ 3118, 2677},
- { 5207, 2834},{ 6902, 2857},{ 8218, 2878},{ 9323, 2900},
- {10285, 2919},{11132, 2934},{11899, 2949},{12599, 2961},
- {13235, 2971},{13835, 2982},{14394, 2991},{14917, 2997},
- {15412, 3005},{15882, 3009},{16325, 3013},{16735, 3016},
- {17131, 3018},{17501, 3021},{17824, 3021},{18125, 3016}
+ /*Y' qi=18 INTER*/
+ {
+ { 26, 195},{ 1, 1317},{ 45, 2595},{ 103, 3750},
+ { 168, 4903},{ 281, 6007},{ 397, 7062},{ 513, 8064},
+ { 630, 9010},{ 758, 9902},{ 906,10732},{ 1095,11463},
+ { 1338,12060},{ 1629,12490},{ 1969,12724},{ 2313,12842},
+ { 2666,12828},{ 2993,12747},{ 3294,12670},{ 3558,12553},
+ { 3813,12440},{ 3990,12379},{ 4177,12291},{ 4226,12265}
}
},
{
- /*Cb qi=58 INTRA*/
- {
- { 17, 3},{ 200, 365},{ 389, 703},{ 613, 996},
- { 853, 1243},{ 1095, 1445},{ 1349, 1604},{ 1613, 1731},
- { 1853, 1853},{ 2074, 1978},{ 2292, 2091},{ 2526, 2184},
- { 2750, 2266},{ 2945, 2360},{ 3134, 2458},{ 3320, 2561},
- { 3482, 2654},{ 3641, 2737},{ 3804, 2818},{ 3985, 2881},
- { 4168, 2935},{ 4331, 3003},{ 4499, 3060},{ 4751, 3100}
+ /*Cb qi=18 INTRA*/
+ {
+ { 31, 43},{ 33, 585},{ 40, 781},{ 58, 1077},
+ { 45, 1189},{ 58, 1655},{ 66, 1983},{ 123, 2221},
+ { 168, 2193},{ 227, 2321},{ 241, 2246},{ 250, 2208},
+ { 221, 1786},{ 250, 2087},{ 247, 2036},{ 250, 2164},
+ { 241, 2054},{ 287, 2453},{ 302, 2551},{ 335, 2758},
+ { 279, 2511},{ 379, 2973},{ 404, 3028},{ 406, 3029}
},
- /*Cb qi=58 INTER*/
- {
- { 94, -1},{ 112, 345},{ 112, 665},{ 152, 998},
- { 247, 1307},{ 406, 1580},{ 644, 1810},{ 938, 2007},
- { 1271, 2189},{ 1668, 2348},{ 2151, 2470},{ 2691, 2558},
- { 3249, 2619},{ 3798, 2659},{ 4334, 2682},{ 4849, 2692},
- { 5314, 2700},{ 5747, 2721},{ 6167, 2742},{ 6547, 2765},
- { 6902, 2790},{ 7251, 2804},{ 7583, 2819},{ 7924, 2833}
+ /*Cb qi=18 INTER*/
+ {
+ { 7, 153},{ 4, 537},{ 3, 777},{ 9, 1034},
+ { 6, 1282},{ 0, 1630},{ 0, 1943},{ 21, 2252},
+ { 48, 2567},{ 67, 2881},{ 83, 3178},{ 89, 3463},
+ { 92, 3738},{ 99, 4024},{ 114, 4289},{ 131, 4552},
+ { 153, 4814},{ 179, 5081},{ 207, 5333},{ 241, 5581},
+ { 273, 5822},{ 303, 6068},{ 335, 6368},{ 353, 6432}
}
},
{
- /*Cr qi=58 INTRA*/
- {
- { 29, 8},{ 210, 382},{ 419, 714},{ 671, 993},
- { 903, 1229},{ 1141, 1422},{ 1390, 1578},{ 1635, 1713},
- { 1889, 1833},{ 2140, 1946},{ 2379, 2055},{ 2604, 2157},
- { 2794, 2256},{ 2977, 2349},{ 3174, 2422},{ 3339, 2482},
- { 3483, 2537},{ 3643, 2604},{ 3790, 2684},{ 3927, 2757},
- { 4112, 2826},{ 4294, 2900},{ 4451, 2975},{ 4600, 3011}
+ /*Cr qi=18 INTRA*/
+ {
+ { 31, 49},{ 42, 575},{ 42, 763},{ 38, 1045},
+ { 41, 1184},{ 56, 1631},{ 87, 1968},{ 163, 2177},
+ { 191, 2188},{ 236, 2264},{ 240, 2101},{ 234, 2047},
+ { 206, 1651},{ 222, 1966},{ 238, 2013},{ 240, 2176},
+ { 229, 2098},{ 321, 2592},{ 341, 2748},{ 378, 3025},
+ { 367, 2849},{ 442, 3283},{ 453, 3315},{ 455, 3313}
},
- /*Cr qi=58 INTER*/
- {
- { 86, 0},{ 99, 352},{ 103, 675},{ 151, 1004},
- { 256, 1306},{ 417, 1573},{ 628, 1819},{ 901, 2040},
- { 1262, 2217},{ 1705, 2353},{ 2191, 2466},{ 2713, 2556},
- { 3268, 2622},{ 3831, 2664},{ 4374, 2682},{ 4881, 2686},
- { 5339, 2685},{ 5747, 2668},{ 6123, 2646},{ 6465, 2630},
- { 6783, 2618},{ 7082, 2623},{ 7366, 2632},{ 7673, 2654}
+ /*Cr qi=18 INTER*/
+ {
+ { 6, 151},{ 3, 539},{ 3, 775},{ 8, 1027},
+ { 6, 1260},{ -3, 1619},{ 0, 1927},{ 24, 2238},
+ { 58, 2558},{ 76, 2871},{ 92, 3173},{ 96, 3461},
+ { 98, 3742},{ 104, 4032},{ 116, 4306},{ 136, 4578},
+ { 158, 4839},{ 185, 5123},{ 217, 5383},{ 250, 5642},
+ { 279, 5910},{ 306, 6169},{ 333, 6502},{ 350, 6522}
}
}
},
{
{
- /*Y' qi=59 INTRA*/
- {
- { 142, 112},{ 1259, 1100},{ 2552, 1711},{ 3815, 1933},
- { 4955, 1987},{ 5983, 2068},{ 6949, 2165},{ 7832, 2263},
- { 8645, 2359},{ 9392, 2454},{10066, 2536},{10643, 2589},
- {11174, 2636},{11696, 2693},{12230, 2758},{12752, 2826},
- {13239, 2883},{13721, 2926},{14139, 2959},{14479, 2978},
- {14811, 2993},{15166, 3020},{15532, 3039},{16000, 3062}
+ /*Y' qi=27 INTRA*/
+ {
+ { 10, 85},{ 280, 1349},{ 278, 815},{ 497, 1699},
+ { 600, 1569},{ 744, 1944},{ 894, 2114},{ 1040, 2292},
+ { 1216, 2484},{ 1485, 2816},{ 1778, 3065},{ 1990, 3243},
+ { 2199, 3381},{ 2326, 3515},{ 2370, 3422},{ 2512, 3581},
+ { 2548, 3526},{ 2656, 3615},{ 2803, 3679},{ 2946, 3766},
+ { 3023, 3824},{ 3179, 3908},{ 3374, 4035},{ 3377, 4030}
},
- /*Y' qi=59 INTER*/
- {
- { 8, 25},{ 211, 1289},{ 1394, 2144},{ 3421, 2580},
- { 5611, 2689},{ 7316, 2701},{ 8643, 2717},{ 9762, 2734},
- {10735, 2750},{11587, 2763},{12353, 2775},{13056, 2785},
- {13693, 2793},{14288, 2805},{14843, 2814},{15361, 2821},
- {15857, 2827},{16328, 2831},{16763, 2834},{17171, 2838},
- {17568, 2840},{17941, 2842},{18285, 2843},{18586, 2839}
+ /*Y' qi=27 INTER*/
+ {
+ { -2, 172},{ 31, 1347},{ 117, 2488},{ 245, 3651},
+ { 448, 4719},{ 668, 5679},{ 918, 6524},{ 1204, 7255},
+ { 1557, 7848},{ 1998, 8281},{ 2511, 8531},{ 3055, 8642},
+ { 3582, 8648},{ 4062, 8611},{ 4482, 8582},{ 4845, 8560},
+ { 5140, 8560},{ 5423, 8581},{ 5645, 8596},{ 5855, 8586},
+ { 6061, 8608},{ 6211, 8558},{ 6402, 8583},{ 6472, 8575}
}
},
{
- /*Cb qi=59 INTRA*/
- {
- { 17, 3},{ 224, 363},{ 441, 696},{ 689, 982},
- { 945, 1222},{ 1204, 1416},{ 1474, 1571},{ 1751, 1695},
- { 2001, 1816},{ 2228, 1941},{ 2453, 2055},{ 2693, 2147},
- { 2924, 2227},{ 3125, 2321},{ 3321, 2416},{ 3510, 2520},
- { 3676, 2616},{ 3839, 2699},{ 4008, 2778},{ 4193, 2842},
- { 4371, 2898},{ 4535, 2965},{ 4710, 3023},{ 4921, 3068}
+ /*Cb qi=27 INTRA*/
+ {
+ { 47, 49},{ 35, 580},{ 64, 778},{ 69, 1071},
+ { 98, 1289},{ 186, 1556},{ 177, 1654},{ 197, 1736},
+ { 211, 1373},{ 284, 1742},{ 321, 1840},{ 344, 2024},
+ { 321, 1969},{ 386, 2254},{ 397, 2281},{ 425, 2320},
+ { 396, 2088},{ 448, 2284},{ 462, 2213},{ 482, 2274},
+ { 410, 1894},{ 513, 2310},{ 546, 2332},{ 549, 2334}
},
- /*Cb qi=59 INTER*/
- {
- { 95, -5},{ 111, 343},{ 112, 664},{ 157, 995},
- { 258, 1302},{ 429, 1569},{ 691, 1790},{ 1017, 1977},
- { 1387, 2148},{ 1832, 2294},{ 2368, 2401},{ 2961, 2472},
- { 3553, 2518},{ 4133, 2545},{ 4688, 2557},{ 5198, 2563},
- { 5663, 2574},{ 6100, 2590},{ 6511, 2608},{ 6898, 2621},
- { 7274, 2634},{ 7631, 2655},{ 7984, 2669},{ 8361, 2669}
+ /*Cb qi=27 INTER*/
+ {
+ { 11, 145},{ 5, 539},{ 11, 771},{ 0, 1033},
+ { 9, 1334},{ 44, 1644},{ 70, 1934},{ 87, 2227},
+ { 96, 2508},{ 113, 2812},{ 139, 3085},{ 174, 3352},
+ { 216, 3614},{ 261, 3873},{ 305, 4123},{ 349, 4372},
+ { 396, 4611},{ 442, 4853},{ 493, 5088},{ 543, 5313},
+ { 600, 5537},{ 662, 5752},{ 737, 6018},{ 775, 6037}
}
},
{
- /*Cr qi=59 INTRA*/
- {
- { 31, 8},{ 240, 379},{ 480, 706},{ 748, 978},
- { 993, 1208},{ 1250, 1394},{ 1519, 1543},{ 1779, 1674},
- { 2047, 1792},{ 2307, 1904},{ 2552, 2013},{ 2780, 2116},
- { 2973, 2216},{ 3165, 2309},{ 3362, 2383},{ 3528, 2444},
- { 3677, 2499},{ 3841, 2566},{ 3995, 2646},{ 4139, 2720},
- { 4324, 2793},{ 4504, 2867},{ 4658, 2939},{ 4806, 2975}
+ /*Cr qi=27 INTRA*/
+ {
+ { 49, 52},{ 57, 570},{ 61, 762},{ 44, 1048},
+ { 80, 1291},{ 196, 1513},{ 224, 1522},{ 242, 1532},
+ { 213, 1293},{ 260, 1639},{ 253, 1691},{ 291, 1915},
+ { 294, 1897},{ 367, 2178},{ 395, 2258},{ 432, 2310},
+ { 407, 2105},{ 503, 2369},{ 492, 2293},{ 552, 2421},
+ { 496, 2099},{ 598, 2549},{ 624, 2531},{ 627, 2532}
},
- /*Cr qi=59 INTER*/
- {
- { 89, -3},{ 98, 352},{ 103, 674},{ 156, 1002},
- { 268, 1300},{ 441, 1562},{ 673, 1801},{ 980, 2010},
- { 1385, 2175},{ 1868, 2301},{ 2401, 2402},{ 2984, 2474},
- { 3591, 2520},{ 4179, 2545},{ 4729, 2555},{ 5232, 2553},
- { 5679, 2545},{ 6081, 2530},{ 6447, 2510},{ 6791, 2496},
- { 7101, 2487},{ 7393, 2489},{ 7684, 2499},{ 7950, 2501}
+ /*Cr qi=27 INTER*/
+ {
+ { 10, 147},{ 4, 538},{ 11, 769},{ 0, 1022},
+ { 9, 1318},{ 51, 1635},{ 80, 1925},{ 97, 2214},
+ { 101, 2493},{ 115, 2805},{ 143, 3083},{ 182, 3361},
+ { 226, 3625},{ 270, 3898},{ 319, 4157},{ 366, 4405},
+ { 418, 4649},{ 467, 4904},{ 509, 5157},{ 548, 5412},
+ { 589, 5659},{ 636, 5909},{ 683, 6208},{ 710, 6190}
}
}
},
{
{
- /*Y' qi=60 INTRA*/
- {
- { 92, 116},{ 1361, 1085},{ 2746, 1686},{ 4050, 1895},
- { 5209, 1939},{ 6244, 2012},{ 7213, 2103},{ 8105, 2197},
- { 8928, 2290},{ 9685, 2381},{10371, 2460},{10952, 2511},
- {11487, 2556},{12026, 2611},{12574, 2674},{13102, 2739},
- {13597, 2793},{14092, 2831},{14523, 2862},{14862, 2881},
- {15198, 2897},{15568, 2923},{15949, 2941},{16416, 2964}
+ /*Y' qi=36 INTRA*/
+ {
+ { 86, 252},{ 345, 662},{ 476, 1143},{ 698, 1169},
+ { 894, 1457},{ 1218, 1728},{ 1465, 1849},{ 1731, 2019},
+ { 2183, 2298},{ 2666, 2511},{ 3116, 2731},{ 3371, 2813},
+ { 3621, 2923},{ 3675, 2949},{ 3710, 2921},{ 3740, 2896},
+ { 3746, 2895},{ 3886, 2978},{ 4069, 2991},{ 4229, 3016},
+ { 4338, 3102},{ 4530, 3124},{ 4751, 3248},{ 4753, 3244}
},
- /*Y' qi=60 INTER*/
- {
- { 4, 30},{ 215, 1287},{ 1547, 2104},{ 3729, 2491},
- { 5973, 2568},{ 7672, 2577},{ 9001, 2591},{10123, 2606},
- {11094, 2620},{11943, 2632},{12709, 2643},{13409, 2652},
- {14044, 2660},{14641, 2669},{15193, 2677},{15709, 2684},
- {16201, 2689},{16675, 2693},{17118, 2696},{17522, 2701},
- {17920, 2704},{18293, 2706},{18620, 2702},{18923, 2700}
+ /*Y' qi=36 INTER*/
+ {
+ { 0, 208},{ 73, 1293},{ 248, 2449},{ 616, 3461},
+ { 1061, 4329},{ 1601, 4986},{ 2189, 5447},{ 2875, 5723},
+ { 3620, 5844},{ 4328, 5879},{ 4954, 5880},{ 5490, 5890},
+ { 5934, 5901},{ 6353, 5926},{ 6706, 5924},{ 7036, 5930},
+ { 7338, 5938},{ 7600, 5930},{ 7870, 5939},{ 8065, 5921},
+ { 8318, 5914},{ 8451, 5912},{ 8648, 5923},{ 8734, 5926}
}
},
{
- /*Cb qi=60 INTRA*/
- {
- { 18, 3},{ 227, 362},{ 447, 694},{ 708, 974},
- { 981, 1207},{ 1252, 1397},{ 1532, 1547},{ 1822, 1663},
- { 2082, 1780},{ 2316, 1903},{ 2548, 2013},{ 2794, 2101},
- { 3029, 2178},{ 3242, 2266},{ 3445, 2360},{ 3638, 2459},
- { 3816, 2547},{ 3980, 2628},{ 4146, 2708},{ 4344, 2766},
- { 4546, 2812},{ 4725, 2872},{ 4880, 2930},{ 5054, 2966}
+ /*Cb qi=36 INTRA*/
+ {
+ { 52, 54},{ 52, 575},{ 103, 776},{ 185, 1072},
+ { 172, 1069},{ 211, 1302},{ 217, 1413},{ 285, 1586},
+ { 330, 1463},{ 453, 1694},{ 500, 1741},{ 545, 1852},
+ { 501, 1650},{ 584, 1874},{ 587, 1856},{ 638, 1919},
+ { 581, 1742},{ 670, 1953},{ 688, 1934},{ 731, 2030},
+ { 637, 1794},{ 806, 2123},{ 840, 2091},{ 843, 2091}
},
- /*Cb qi=60 INTER*/
- {
- { 97, -4},{ 112, 343},{ 114, 664},{ 162, 993},
- { 273, 1294},{ 472, 1553},{ 774, 1762},{ 1138, 1939},
- { 1543, 2102},{ 2034, 2236},{ 2620, 2329},{ 3244, 2389},
- { 3860, 2423},{ 4443, 2440},{ 4997, 2449},{ 5502, 2455},
- { 5962, 2458},{ 6413, 2466},{ 6836, 2485},{ 7217, 2506},
- { 7592, 2518},{ 7957, 2533},{ 8291, 2543},{ 8574, 2545}
+ /*Cb qi=36 INTER*/
+ {
+ { 19, 142},{ 17, 534},{ 6, 772},{ 44, 1023},
+ { 82, 1296},{ 94, 1614},{ 117, 1903},{ 158, 2187},
+ { 218, 2450},{ 285, 2703},{ 352, 2943},{ 421, 3181},
+ { 489, 3415},{ 564, 3644},{ 647, 3861},{ 748, 4060},
+ { 861, 4246},{ 993, 4419},{ 1132, 4576},{ 1282, 4744},
+ { 1445, 4894},{ 1600, 5034},{ 1782, 5211},{ 1837, 5200}
}
},
{
- /*Cr qi=60 INTRA*/
- {
- { 32, 8},{ 243, 379},{ 488, 702},{ 771, 968},
- { 1030, 1192},{ 1300, 1373},{ 1581, 1517},{ 1854, 1643},
- { 2127, 1757},{ 2393, 1864},{ 2645, 1968},{ 2879, 2068},
- { 3078, 2166},{ 3277, 2256},{ 3484, 2325},{ 3660, 2381},
- { 3808, 2433},{ 3970, 2496},{ 4138, 2571},{ 4288, 2643},
- { 4475, 2710},{ 4655, 2778},{ 4810, 2843},{ 4959, 2879}
+ /*Cr qi=36 INTRA*/
+ {
+ { 62, 55},{ 90, 561},{ 56, 767},{ 148, 1014},
+ { 207, 981},{ 258, 1216},{ 273, 1253},{ 326, 1392},
+ { 338, 1383},{ 417, 1613},{ 443, 1629},{ 497, 1734},
+ { 466, 1525},{ 561, 1778},{ 577, 1787},{ 631, 1892},
+ { 591, 1706},{ 715, 1980},{ 730, 1958},{ 822, 2113},
+ { 755, 1935},{ 928, 2228},{ 935, 2205},{ 938, 2205}
},
- /*Cr qi=60 INTER*/
- {
- { 86, -2},{ 99, 352},{ 103, 673},{ 160, 998},
- { 284, 1292},{ 484, 1546},{ 753, 1774},{ 1100, 1973},
- { 1546, 2129},{ 2072, 2246},{ 2652, 2334},{ 3279, 2392},
- { 3911, 2425},{ 4504, 2440},{ 5044, 2443},{ 5536, 2440},
- { 5979, 2430},{ 6381, 2413},{ 6735, 2397},{ 7062, 2382},
- { 7383, 2376},{ 7680, 2375},{ 7962, 2373},{ 8203, 2379}
+ /*Cr qi=36 INTER*/
+ {
+ { 14, 145},{ 16, 535},{ 5, 772},{ 44, 1017},
+ { 91, 1296},{ 100, 1605},{ 122, 1891},{ 163, 2174},
+ { 225, 2443},{ 294, 2707},{ 362, 2962},{ 436, 3210},
+ { 518, 3437},{ 607, 3664},{ 702, 3876},{ 795, 4094},
+ { 886, 4310},{ 980, 4538},{ 1089, 4749},{ 1216, 4927},
+ { 1357, 5116},{ 1506, 5247},{ 1758, 5338},{ 1787, 5306}
}
}
},
{
{
- /*Y' qi=61 INTRA*/
- {
- { 54, 121},{ 1477, 1069},{ 3061, 1638},{ 4465, 1808},
- { 5649, 1827},{ 6710, 1884},{ 7716, 1958},{ 8648, 2037},
- { 9514, 2116},{10311, 2192},{11033, 2261},{11641, 2305},
- {12202, 2342},{12771, 2387},{13356, 2440},{13924, 2493},
- {14444, 2541},{14951, 2576},{15409, 2600},{15779, 2615},
- {16131, 2626},{16521, 2648},{16921, 2663},{17409, 2694}
+ /*Y' qi=45 INTRA*/
+ {
+ { 185, 246},{ 513, 647},{ 883, 891},{ 1313, 1142},
+ { 1760, 1351},{ 2368, 1595},{ 2828, 1718},{ 3097, 1780},
+ { 3762, 1951},{ 4454, 2121},{ 4986, 2227},{ 5281, 2281},
+ { 5477, 2299},{ 5431, 2288},{ 5425, 2283},{ 5439, 2290},
+ { 5324, 2249},{ 5509, 2279},{ 5703, 2321},{ 5896, 2348},
+ { 6049, 2370},{ 6253, 2425},{ 6415, 2432},{ 6419, 2430}
},
- /*Y' qi=61 INTER*/
- {
- { -1, 32},{ 216, 1286},{ 1806, 2036},{ 4279, 2327},
- { 6629, 2352},{ 8347, 2352},{ 9707, 2357},{10860, 2364},
- {11857, 2372},{12726, 2377},{13508, 2382},{14225, 2387},
- {14877, 2392},{15484, 2398},{16048, 2401},{16581, 2405},
- {17092, 2409},{17573, 2409},{18016, 2410},{18427, 2413},
- {18829, 2415},{19221, 2415},{19578, 2415},{19980, 2413}
+ /*Y' qi=45 INTER*/
+ {
+ { 6, 215},{ 152, 1261},{ 691, 2314},{ 1538, 3095},
+ { 2505, 3632},{ 3475, 3935},{ 4355, 4084},{ 5209, 4139},
+ { 5985, 4162},{ 6644, 4185},{ 7235, 4190},{ 7768, 4196},
+ { 8266, 4200},{ 8736, 4210},{ 9143, 4207},{ 9511, 4215},
+ { 9828, 4209},{10112, 4224},{10374, 4226},{10642, 4232},
+ {10842, 4219},{10971, 4208},{11200, 4211},{11299, 4216}
}
},
{
- /*Cb qi=61 INTRA*/
- {
- { 19, 3},{ 231, 362},{ 456, 693},{ 733, 965},
- { 1032, 1188},{ 1330, 1369},{ 1637, 1508},{ 1956, 1612},
- { 2241, 1718},{ 2496, 1832},{ 2750, 1932},{ 3019, 2007},
- { 3274, 2074},{ 3505, 2154},{ 3725, 2236},{ 3943, 2323},
- { 4138, 2403},{ 4323, 2476},{ 4505, 2543},{ 4706, 2592},
- { 4909, 2630},{ 5109, 2675},{ 5292, 2724},{ 5495, 2768}
+ /*Cb qi=45 INTRA*/
+ {
+ { 58, 71},{ 66, 548},{ 155, 762},{ 213, 944},
+ { 192, 731},{ 324, 1147},{ 401, 1366},{ 481, 1480},
+ { 508, 1238},{ 657, 1522},{ 727, 1563},{ 794, 1611},
+ { 761, 1470},{ 885, 1710},{ 893, 1700},{ 958, 1760},
+ { 893, 1543},{ 985, 1719},{ 1014, 1732},{ 1082, 1784},
+ { 963, 1519},{ 1152, 1800},{ 1221, 1830},{ 1226, 1830}
},
- /*Cb qi=61 INTER*/
- {
- { 91, -2},{ 111, 344},{ 114, 663},{ 166, 989},
- { 291, 1285},{ 522, 1534},{ 875, 1729},{ 1302, 1889},
- { 1786, 2031},{ 2368, 2141},{ 3042, 2207},{ 3734, 2243},
- { 4388, 2259},{ 4982, 2264},{ 5533, 2265},{ 6043, 2262},
- { 6524, 2264},{ 6982, 2274},{ 7422, 2283},{ 7831, 2295},
- { 8198, 2308},{ 8593, 2319},{ 8965, 2329},{ 9258, 2340}
+ /*Cb qi=45 INTER*/
+ {
+ { 35, 135},{ 12, 532},{ 54, 769},{ 106, 1007},
+ { 127, 1258},{ 198, 1565},{ 289, 1832},{ 398, 2082},
+ { 520, 2302},{ 653, 2511},{ 800, 2705},{ 956, 2897},
+ { 1143, 3064},{ 1358, 3220},{ 1623, 3335},{ 1913, 3444},
+ { 2198, 3534},{ 2502, 3626},{ 2787, 3711},{ 3114, 3783},
+ { 3454, 3831},{ 3711, 3871},{ 4163, 3901},{ 4221, 3890}
}
},
{
- /*Cr qi=61 INTRA*/
- {
- { 33, 9},{ 245, 378},{ 497, 699},{ 801, 958},
- { 1087, 1171},{ 1384, 1342},{ 1692, 1474},{ 1992, 1589},
- { 2290, 1692},{ 2576, 1789},{ 2852, 1884},{ 3109, 1973},
- { 3324, 2061},{ 3544, 2142},{ 3763, 2199},{ 3945, 2244},
- { 4103, 2292},{ 4283, 2349},{ 4469, 2413},{ 4635, 2476},
- { 4836, 2534},{ 5038, 2592},{ 5210, 2649},{ 5358, 2682}
+ /*Cr qi=45 INTRA*/
+ {
+ { 93, 68},{ 72, 541},{ 154, 769},{ 239, 848},
+ { 214, 623},{ 377, 1060},{ 437, 1200},{ 514, 1280},
+ { 512, 1160},{ 625, 1453},{ 657, 1470},{ 718, 1516},
+ { 692, 1331},{ 831, 1617},{ 875, 1609},{ 944, 1678},
+ { 886, 1469},{ 1061, 1699},{ 1082, 1714},{ 1226, 1823},
+ { 1113, 1581},{ 1324, 1872},{ 1370, 1925},{ 1374, 1924}
},
- /*Cr qi=61 INTER*/
- {
- { 82, 0},{ 97, 353},{ 104, 672},{ 165, 995},
- { 303, 1284},{ 532, 1529},{ 852, 1742},{ 1273, 1921},
- { 1798, 2057},{ 2409, 2154},{ 3090, 2212},{ 3794, 2240},
- { 4460, 2251},{ 5057, 2249},{ 5596, 2249},{ 6085, 2245},
- { 6519, 2234},{ 6908, 2220},{ 7269, 2203},{ 7618, 2196},
- { 7949, 2198},{ 8269, 2195},{ 8554, 2196},{ 8928, 2217}
+ /*Cr qi=45 INTER*/
+ {
+ { 31, 140},{ 13, 533},{ 52, 770},{ 109, 1000},
+ { 134, 1253},{ 201, 1555},{ 298, 1821},{ 411, 2076},
+ { 525, 2314},{ 659, 2545},{ 828, 2747},{ 1019, 2918},
+ { 1205, 3082},{ 1405, 3266},{ 1609, 3443},{ 1847, 3606},
+ { 2085, 3730},{ 2404, 3835},{ 2709, 3876},{ 3049, 3886},
+ { 3381, 3821},{ 3708, 3780},{ 4026, 3663},{ 4043, 3646}
}
}
},
{
{
- /*Y' qi=62 INTRA*/
- {
- { 29, 124},{ 1527, 1067},{ 3221, 1618},{ 4703, 1751},
- { 5909, 1744},{ 7001, 1779},{ 8057, 1829},{ 9049, 1885},
- { 9968, 1943},{10813, 1999},{11572, 2050},{12206, 2082},
- {12801, 2107},{13402, 2140},{14020, 2180},{14625, 2223},
- {15179, 2260},{15718, 2288},{16196, 2305},{16581, 2313},
- {16963, 2324},{17382, 2341},{17800, 2351},{18318, 2376}
+ /*Y' qi=54 INTRA*/
+ {
+ { 316, 203},{ 720, 585},{ 1596, 1077},{ 2316, 1289},
+ { 2687, 1439},{ 3133, 1593},{ 3495, 1706},{ 3836, 1775},
+ { 4249, 1892},{ 4804, 2031},{ 5320, 2139},{ 5617, 2203},
+ { 5726, 2199},{ 5726, 2176},{ 5682, 2146},{ 5677, 2127},
+ { 5717, 2124},{ 5707, 2129},{ 5853, 2148},{ 6110, 2180},
+ { 6454, 2247},{ 6714, 2287},{ 6845, 2304},{ 6854, 2303}
},
- /*Y' qi=62 INTER*/
- {
- { -8, 36},{ 218, 1284},{ 2073, 1965},{ 4814, 2159},
- { 7237, 2138},{ 8979, 2124},{10378, 2115},{11570, 2109},
- {12601, 2106},{13503, 2103},{14320, 2103},{15064, 2103},
- {15746, 2103},{16384, 2104},{16975, 2105},{17534, 2105},
- {18062, 2106},{18564, 2107},{19035, 2106},{19471, 2107},
- {19890, 2107},{20288, 2107},{20651, 2107},{21012, 2108}
+ /*Y' qi=54 INTER*/
+ {
+ { -48, 217},{ 314, 1261},{ 1450, 2126},{ 2761, 2728},
+ { 4275, 3012},{ 5408, 3167},{ 6305, 3245},{ 7165, 3290},
+ { 7966, 3325},{ 8698, 3359},{ 9352, 3377},{ 9907, 3391},
+ {10389, 3390},{10856, 3395},{11170, 3385},{11530, 3385},
+ {11780, 3362},{12018, 3362},{12266, 3361},{12443, 3339},
+ {12683, 3342},{12713, 3317},{12967, 3325},{13082, 3332}
}
},
{
- /*Cb qi=62 INTRA*/
- {
- { 21, 3},{ 283, 360},{ 565, 683},{ 907, 938},
- { 1269, 1143},{ 1611, 1311},{ 1949, 1441},{ 2290, 1535},
- { 2596, 1632},{ 2877, 1738},{ 3162, 1828},{ 3458, 1893},
- { 3745, 1948},{ 4011, 2016},{ 4253, 2089},{ 4506, 2164},
- { 4734, 2233},{ 4943, 2294},{ 5162, 2353},{ 5381, 2393},
- { 5593, 2420},{ 5807, 2454},{ 6003, 2496},{ 6210, 2543}
+ /*Cb qi=54 INTRA*/
+ {
+ { 94, 73},{ 83, 557},{ 152, 818},{ 304, 919},
+ { 341, 819},{ 506, 1128},{ 593, 1281},{ 700, 1389},
+ { 714, 1225},{ 907, 1502},{ 981, 1549},{ 1062, 1641},
+ { 1032, 1523},{ 1170, 1710},{ 1217, 1727},{ 1258, 1714},
+ { 1216, 1575},{ 1309, 1682},{ 1331, 1656},{ 1393, 1712},
+ { 1247, 1456},{ 1469, 1728},{ 1530, 1711},{ 1532, 1711}
},
- /*Cb qi=62 INTER*/
- {
- { 91, -1},{ 110, 344},{ 113, 663},{ 169, 987},
- { 306, 1279},{ 562, 1519},{ 961, 1701},{ 1450, 1845},
- { 2013, 1967},{ 2686, 2053},{ 3437, 2095},{ 4171, 2109},
- { 4841, 2109},{ 5441, 2105},{ 6002, 2097},{ 6542, 2089},
- { 7028, 2087},{ 7491, 2088},{ 7949, 2090},{ 8377, 2089},
- { 8789, 2095},{ 9195, 2103},{ 9569, 2104},{ 9937, 2102}
+ /*Cb qi=54 INTER*/
+ {
+ { 33, 133},{ 12, 532},{ 70, 770},{ 171, 996},
+ { 279, 1233},{ 427, 1503},{ 600, 1736},{ 824, 1939},
+ { 1101, 2097},{ 1411, 2237},{ 1735, 2374},{ 2097, 2493},
+ { 2486, 2606},{ 2916, 2691},{ 3297, 2771},{ 3715, 2826},
+ { 4088, 2855},{ 4460, 2886},{ 4849, 2911},{ 5198, 2932},
+ { 5489, 2940},{ 5875, 2981},{ 6208, 3017},{ 6270, 3012}
}
},
{
- /*Cr qi=62 INTRA*/
- {
- { 38, 8},{ 308, 374},{ 619, 685},{ 984, 925},
- { 1326, 1126},{ 1662, 1285},{ 1999, 1407},{ 2328, 1512},
- { 2659, 1604},{ 2976, 1691},{ 3285, 1774},{ 3570, 1853},
- { 3815, 1931},{ 4068, 1998},{ 4304, 2044},{ 4491, 2082},
- { 4666, 2124},{ 4870, 2174},{ 5078, 2231},{ 5262, 2285},
- { 5480, 2335},{ 5703, 2378},{ 5905, 2423},{ 6075, 2454}
+ /*Cr qi=54 INTRA*/
+ {
+ { 103, 63},{ 83, 580},{ 258, 796},{ 301, 802},
+ { 361, 675},{ 538, 1001},{ 625, 1097},{ 713, 1171},
+ { 699, 1103},{ 868, 1380},{ 915, 1400},{ 970, 1491},
+ { 923, 1365},{ 1070, 1603},{ 1154, 1655},{ 1206, 1677},
+ { 1157, 1541},{ 1366, 1736},{ 1391, 1723},{ 1506, 1797},
+ { 1388, 1556},{ 1616, 1828},{ 1655, 1797},{ 1658, 1796}
},
- /*Cr qi=62 INTER*/
- {
- { 79, 1},{ 95, 353},{ 102, 671},{ 169, 992},
- { 318, 1277},{ 569, 1515},{ 936, 1716},{ 1428, 1876},
- { 2034, 1993},{ 2738, 2067},{ 3511, 2095},{ 4268, 2094},
- { 4943, 2087},{ 5543, 2079},{ 6074, 2074},{ 6552, 2069},
- { 6985, 2057},{ 7366, 2043},{ 7728, 2030},{ 8086, 2021},
- { 8423, 2017},{ 8752, 2016},{ 9057, 2014},{ 9376, 2008}
+ /*Cr qi=54 INTER*/
+ {
+ { 30, 138},{ 14, 532},{ 63, 771},{ 176, 990},
+ { 299, 1226},{ 438, 1496},{ 606, 1735},{ 814, 1950},
+ { 1089, 2127},{ 1417, 2281},{ 1761, 2421},{ 2104, 2571},
+ { 2467, 2701},{ 2881, 2827},{ 3303, 2900},{ 3735, 2917},
+ { 4183, 2913},{ 4529, 2882},{ 4915, 2844},{ 5168, 2796},
+ { 5410, 2763},{ 5562, 2753},{ 5815, 2764},{ 5832, 2755}
}
}
},
@@ -3964,61 +967,61 @@ oc_mode_rd OC_MODE_RD[64][3][2][OC_SAD_BINS]={
{
/*Y' qi=63 INTRA*/
{
- { -59, 134},{ 1734, 1036},{ 3743, 1521},{ 5309, 1618},
- { 6520, 1597},{ 7664, 1609},{ 8809, 1630},{ 9894, 1657},
- {10907, 1687},{11838, 1717},{12673, 1744},{13379, 1758},
- {14038, 1767},{14698, 1784},{15379, 1806},{16062, 1831},
- {16694, 1852},{17300, 1867},{17827, 1878},{18250, 1881},
- {18702, 1884},{19199, 1892},{19665, 1896},{20273, 1908}
+ { 421, 194},{ 1272, 564},{ 3016, 943},{ 3831, 1079},
+ { 4282, 1174},{ 4799, 1290},{ 5166, 1348},{ 5259, 1350},
+ { 5720, 1426},{ 6501, 1539},{ 7048, 1606},{ 7328, 1642},
+ { 7374, 1622},{ 7349, 1612},{ 7192, 1578},{ 7207, 1571},
+ { 7161, 1555},{ 7259, 1573},{ 7432, 1592},{ 7710, 1613},
+ { 8167, 1672},{ 8425, 1697},{ 8597, 1710},{ 8602, 1710}
},
/*Y' qi=63 INTER*/
{
- { -7, 33},{ 209, 1285},{ 2309, 1904},{ 5274, 2025},
- { 7801, 1966},{ 9637, 1924},{11126, 1892},{12403, 1868},
- {13515, 1849},{14491, 1834},{15380, 1822},{16197, 1814},
- {16944, 1806},{17645, 1799},{18303, 1794},{18916, 1789},
- {19494, 1785},{20056, 1782},{20568, 1779},{21047, 1776},
- {21508, 1775},{21925, 1772},{22327, 1770},{22678, 1771}
+ { -584, 286},{ 1231, 1186},{ 3939, 1663},{ 6096, 1865},
+ { 7849, 1929},{ 8934, 1995},{ 9962, 2039},{11038, 2078},
+ {12016, 2092},{12889, 2100},{13617, 2096},{14221, 2089},
+ {14743, 2083},{15240, 2081},{15619, 2074},{15992, 2065},
+ {16314, 2065},{16529, 2059},{16822, 2056},{17041, 2049},
+ {17321, 2052},{17408, 2043},{17670, 2051},{17801, 2053}
}
},
{
/*Cb qi=63 INTRA*/
{
- { 20, 3},{ 294, 357},{ 608, 673},{ 1047, 908},
- { 1501, 1090},{ 1898, 1240},{ 2275, 1353},{ 2654, 1427},
- { 3014, 1502},{ 3366, 1579},{ 3726, 1637},{ 4084, 1674},
- { 4425, 1703},{ 4752, 1743},{ 5058, 1791},{ 5377, 1838},
- { 5676, 1877},{ 5946, 1912},{ 6213, 1945},{ 6458, 1969},
- { 6704, 1982},{ 6969, 1997},{ 7210, 2017},{ 7439, 2037}
+ { 154, 55},{ 280, 582},{ 507, 731},{ 788, 853},
+ { 763, 738},{ 1141, 1008},{ 1323, 1090},{ 1540, 1220},
+ { 1487, 1089},{ 1861, 1322},{ 1983, 1347},{ 2145, 1425},
+ { 2047, 1317},{ 2334, 1475},{ 2352, 1413},{ 2458, 1467},
+ { 2243, 1270},{ 2464, 1413},{ 2423, 1335},{ 2506, 1385},
+ { 2182, 1180},{ 2565, 1376},{ 2555, 1321},{ 2557, 1321}
},
/*Cb qi=63 INTER*/
{
- { 86, 1},{ 108, 345},{ 111, 663},{ 168, 985},
- { 307, 1276},{ 577, 1513},{ 1007, 1688},{ 1550, 1819},
- { 2189, 1921},{ 2938, 1981},{ 3744, 2002},{ 4512, 2002},
- { 5199, 1996},{ 5824, 1986},{ 6419, 1971},{ 6978, 1954},
- { 7507, 1940},{ 8015, 1932},{ 8502, 1928},{ 8978, 1920},
- { 9410, 1915},{ 9842, 1910},{10262, 1901},{10634, 1896}
+ { 34, 133},{ 6, 531},{ 139, 767},{ 344, 975},
+ { 608, 1180},{ 1048, 1367},{ 1651, 1495},{ 2376, 1572},
+ { 3103, 1609},{ 3752, 1646},{ 4373, 1680},{ 4980, 1718},
+ { 5540, 1744},{ 6023, 1764},{ 6431, 1766},{ 6800, 1769},
+ { 7149, 1775},{ 7529, 1777},{ 7920, 1817},{ 8198, 1808},
+ { 8691, 1848},{ 8965, 1845},{ 9372, 1865},{ 9459, 1863}
}
},
{
/*Cr qi=63 INTRA*/
{
- { 38, 7},{ 324, 367},{ 677, 670},{ 1136, 892},
- { 1562, 1070},{ 1951, 1209},{ 2326, 1313},{ 2694, 1399},
- { 3074, 1471},{ 3460, 1531},{ 3850, 1575},{ 4214, 1622},
- { 4522, 1679},{ 4819, 1723},{ 5089, 1749},{ 5315, 1769},
- { 5530, 1792},{ 5756, 1825},{ 6006, 1860},{ 6244, 1889},
- { 6514, 1924},{ 6792, 1946},{ 7026, 1962},{ 7191, 1971}
+ { 121, 59},{ 392, 570},{ 609, 654},{ 800, 760},
+ { 720, 598},{ 1192, 892},{ 1298, 897},{ 1470, 1027},
+ { 1411, 962},{ 1761, 1184},{ 1826, 1197},{ 1981, 1308},
+ { 1854, 1198},{ 2229, 1427},{ 2269, 1365},{ 2428, 1453},
+ { 2217, 1265},{ 2558, 1435},{ 2541, 1356},{ 2660, 1417},
+ { 2337, 1199},{ 2688, 1382},{ 2603, 1301},{ 2605, 1300}
},
/*Cr qi=63 INTER*/
{
- { 80, 2},{ 95, 354},{ 101, 671},{ 167, 990},
- { 321, 1274},{ 585, 1509},{ 984, 1702},{ 1534, 1849},
- { 2217, 1947},{ 3005, 1995},{ 3839, 1999},{ 4619, 1986},
- { 5310, 1973},{ 5933, 1961},{ 6486, 1952},{ 6988, 1942},
- { 7435, 1927},{ 7817, 1911},{ 8198, 1900},{ 8552, 1895},
- { 8881, 1890},{ 9253, 1883},{ 9598, 1876},{ 9923, 1859}
+ { 31, 137},{ 10, 531},{ 136, 768},{ 360, 971},
+ { 638, 1166},{ 1029, 1373},{ 1604, 1519},{ 2351, 1595},
+ { 3129, 1640},{ 3861, 1691},{ 4491, 1751},{ 5101, 1783},
+ { 5635, 1784},{ 6136, 1779},{ 6550, 1763},{ 6905, 1746},
+ { 7172, 1726},{ 7495, 1732},{ 7738, 1735},{ 7949, 1735},
+ { 8211, 1744},{ 8424, 1740},{ 8779, 1764},{ 8812, 1760}
}
}
}
diff --git a/thirdparty/libtheora/ocintrin.h b/thirdparty/libtheora/ocintrin.h
index d49ebb2159..b200ceafce 100644
--- a/thirdparty/libtheora/ocintrin.h
+++ b/thirdparty/libtheora/ocintrin.h
@@ -11,7 +11,7 @@
********************************************************************
function:
- last mod: $Id: ocintrin.h 16503 2009-08-22 18:14:02Z giles $
+ last mod: $Id$
********************************************************************/
diff --git a/thirdparty/libtheora/patches/theora.git-0ae66d565e6bead8604d312bc1a4e9dccf245c88.patch b/thirdparty/libtheora/patches/theora.git-0ae66d565e6bead8604d312bc1a4e9dccf245c88.patch
deleted file mode 100644
index 1b9c8e20be..0000000000
--- a/thirdparty/libtheora/patches/theora.git-0ae66d565e6bead8604d312bc1a4e9dccf245c88.patch
+++ /dev/null
@@ -1,38 +0,0 @@
-From 0ae66d565e6bead8604d312bc1a4e9dccf245c88 Mon Sep 17 00:00:00 2001
-From: Tim Terriberry <tterribe@xiph.org>
-Date: Tue, 8 May 2012 02:51:57 +0000
-Subject: [PATCH] Fix pp_sharp_mod calculation.
-
-This was broken when the dequant_tables indexing changed in commit
- r16102, but it only affected post-processing quality, so we never
- noticed.
-With gcc 4.8.0, this can now trigger a segfault during decoder
- initialization.
-
-svn path=/trunk/theora/; revision=18268
----
- decode.c | 8 ++++----
- 1 file changed, 4 insertions(+), 4 deletions(-)
-
-diff --git a/decode.c b/decode.c
-index b803505..9f2516a 100644
---- a/decode.c
-+++ b/decode.c
-@@ -400,10 +400,10 @@ static int oc_dec_init(oc_dec_ctx *_dec,const th_info *_info,
- int qsum;
- qsum=0;
- for(qti=0;qti<2;qti++)for(pli=0;pli<3;pli++){
-- qsum+=_dec->state.dequant_tables[qti][pli][qi][12]+
-- _dec->state.dequant_tables[qti][pli][qi][17]+
-- _dec->state.dequant_tables[qti][pli][qi][18]+
-- _dec->state.dequant_tables[qti][pli][qi][24]<<(pli==0);
-+ qsum+=_dec->state.dequant_tables[qi][pli][qti][12]+
-+ _dec->state.dequant_tables[qi][pli][qti][17]+
-+ _dec->state.dequant_tables[qi][pli][qti][18]+
-+ _dec->state.dequant_tables[qi][pli][qti][24]<<(pli==0);
- }
- _dec->pp_sharp_mod[qi]=-(qsum>>11);
- }
---
-2.11.0
-
diff --git a/thirdparty/libtheora/quant.c b/thirdparty/libtheora/quant.c
index 8359f5abea..e206202844 100644
--- a/thirdparty/libtheora/quant.c
+++ b/thirdparty/libtheora/quant.c
@@ -11,7 +11,7 @@
********************************************************************
function:
- last mod: $Id: quant.c 16503 2009-08-22 18:14:02Z giles $
+ last mod: $Id$
********************************************************************/
@@ -21,6 +21,14 @@
#include "quant.h"
#include "decint.h"
+/*The maximum output of the DCT with +/- 255 inputs is +/- 8157.
+ These minimum quantizers ensure the result after quantization (and after
+ prediction for DC) will be no more than +/- 510.
+ The tokenization system can handle values up to +/- 580, so there is no need
+ to do any coefficient clamping.
+ I would rather have allowed smaller quantizers and had to clamp, but these
+ minimums were required when constructing the original VP3 matrices and have
+ been formalized in the spec.*/
static const unsigned OC_DC_QUANT_MIN[2]={4<<2,8<<2};
static const unsigned OC_AC_QUANT_MIN[2]={2<<2,4<<2};
diff --git a/thirdparty/libtheora/quant.h b/thirdparty/libtheora/quant.h
index 49ce13a65c..247210eaae 100644
--- a/thirdparty/libtheora/quant.h
+++ b/thirdparty/libtheora/quant.h
@@ -11,7 +11,7 @@
********************************************************************
function:
- last mod: $Id: quant.h 16503 2009-08-22 18:14:02Z giles $
+ last mod: $Id$
********************************************************************/
diff --git a/thirdparty/libtheora/rate.c b/thirdparty/libtheora/rate.c
index 4f43bb2e5f..bf2b1396a1 100644
--- a/thirdparty/libtheora/rate.c
+++ b/thirdparty/libtheora/rate.c
@@ -11,7 +11,7 @@
********************************************************************
function:
- last mod: $Id: rate.c 16503 2009-08-22 18:14:02Z giles $
+ last mod: $Id$
********************************************************************/
#include <stdlib.h>
@@ -190,7 +190,8 @@ void oc_enc_calc_lambda(oc_enc_ctx *_enc,int _qti){
This may need to be revised if the R-D cost estimation or qii flag
optimization strategies change.*/
nqis=1;
- if(lq<(OC_Q57(56)>>3)&&!_enc->vp3_compatible){
+ if(lq<(OC_Q57(56)>>3)&&!_enc->vp3_compatible&&
+ _enc->sp_level<OC_SP_LEVEL_FAST_ANALYSIS){
qi1=oc_enc_find_qi_for_target(_enc,_qti,OC_MAXI(qi-1,0),0,
lq+(OC_Q57(7)+5)/10);
if(qi1!=qi)_enc->state.qis[nqis++]=qi1;
@@ -761,6 +762,7 @@ int oc_enc_update_rc_state(oc_enc_ctx *_enc,
_enc->rc.cur_metrics.log_scale=oc_q57_to_q24(log_scale);
_enc->rc.cur_metrics.dup_count=_enc->dup_count;
_enc->rc.cur_metrics.frame_type=_enc->state.frame_type;
+ _enc->rc.cur_metrics.activity_avg=_enc->activity_avg;
_enc->rc.twopass_buffer_bytes=0;
}break;
case 2:{
@@ -863,9 +865,9 @@ int oc_enc_update_rc_state(oc_enc_ctx *_enc,
return dropped;
}
-#define OC_RC_2PASS_VERSION (1)
+#define OC_RC_2PASS_VERSION (2)
#define OC_RC_2PASS_HDR_SZ (38)
-#define OC_RC_2PASS_PACKET_SZ (8)
+#define OC_RC_2PASS_PACKET_SZ (12)
static void oc_rc_buffer_val(oc_rc_state *_rc,ogg_int64_t _val,int _bytes){
while(_bytes-->0){
@@ -900,6 +902,7 @@ int oc_enc_rc_2pass_out(oc_enc_ctx *_enc,unsigned char **_buf){
oc_rc_buffer_val(&_enc->rc,
_enc->rc.cur_metrics.dup_count|_enc->rc.cur_metrics.frame_type<<31,4);
oc_rc_buffer_val(&_enc->rc,_enc->rc.cur_metrics.log_scale,4);
+ oc_rc_buffer_val(&_enc->rc,_enc->rc.cur_metrics.activity_avg,4);
}
}
else if(_enc->packet_state==OC_PACKET_DONE&&
@@ -1050,16 +1053,19 @@ int oc_enc_rc_2pass_in(oc_enc_ctx *_enc,unsigned char *_buf,size_t _bytes){
if(_enc->rc.twopass_buffer_fill>=OC_RC_2PASS_PACKET_SZ){
ogg_uint32_t dup_count;
ogg_int32_t log_scale;
+ unsigned activity;
int qti;
int arg;
/*Read the metrics for the next frame.*/
dup_count=oc_rc_unbuffer_val(&_enc->rc,4);
log_scale=oc_rc_unbuffer_val(&_enc->rc,4);
+ activity=oc_rc_unbuffer_val(&_enc->rc,4);
_enc->rc.cur_metrics.log_scale=log_scale;
qti=(dup_count&0x80000000)>>31;
_enc->rc.cur_metrics.dup_count=dup_count&0x7FFFFFFF;
_enc->rc.cur_metrics.frame_type=qti;
_enc->rc.twopass_force_kf=qti==OC_INTRA_FRAME;
+ _enc->activity_avg=_enc->rc.cur_metrics.activity_avg=activity;
/*"Helpfully" set the dup count back to what it was in pass 1.*/
arg=_enc->rc.cur_metrics.dup_count;
th_encode_ctl(_enc,TH_ENCCTL_SET_DUP_COUNT,&arg,sizeof(arg));
@@ -1070,8 +1076,8 @@ int oc_enc_rc_2pass_in(oc_enc_ctx *_enc,unsigned char *_buf,size_t _bytes){
else{
int frames_needed;
/*We're using a finite buffer:*/
- frames_needed=OC_CLAMPI(0,_enc->rc.buf_delay
- -(_enc->rc.scale_window_end-_enc->rc.scale_window0),
+ frames_needed=OC_MINI(_enc->rc.buf_delay-OC_MINI(_enc->rc.buf_delay,
+ _enc->rc.scale_window_end-_enc->rc.scale_window0),
_enc->rc.frames_left[0]+_enc->rc.frames_left[1]
-_enc->rc.nframes[0]-_enc->rc.nframes[1]);
while(frames_needed>0){
@@ -1087,9 +1093,11 @@ int oc_enc_rc_2pass_in(oc_enc_ctx *_enc,unsigned char *_buf,size_t _bytes){
ogg_uint32_t dup_count;
ogg_int32_t log_scale;
int qti;
+ unsigned activity;
/*Read the metrics for the next frame.*/
dup_count=oc_rc_unbuffer_val(&_enc->rc,4);
log_scale=oc_rc_unbuffer_val(&_enc->rc,4);
+ activity=oc_rc_unbuffer_val(&_enc->rc,4);
/*Add the to the circular buffer.*/
fmi=_enc->rc.frame_metrics_head+_enc->rc.nframe_metrics++;
if(fmi>=_enc->rc.cframe_metrics)fmi-=_enc->rc.cframe_metrics;
@@ -1098,6 +1106,7 @@ int oc_enc_rc_2pass_in(oc_enc_ctx *_enc,unsigned char *_buf,size_t _bytes){
qti=(dup_count&0x80000000)>>31;
m->dup_count=dup_count&0x7FFFFFFF;
m->frame_type=qti;
+ m->activity_avg=activity;
/*And accumulate the statistics over the window.*/
_enc->rc.nframes[qti]++;
_enc->rc.nframes[2]+=m->dup_count;
@@ -1105,8 +1114,8 @@ int oc_enc_rc_2pass_in(oc_enc_ctx *_enc,unsigned char *_buf,size_t _bytes){
_enc->rc.scale_window_end+=m->dup_count+1;
/*Compute an upper bound on the number of remaining packets needed
for the current window.*/
- frames_needed=OC_CLAMPI(0,_enc->rc.buf_delay
- -(_enc->rc.scale_window_end-_enc->rc.scale_window0),
+ frames_needed=OC_MINI(_enc->rc.buf_delay-OC_MINI(_enc->rc.buf_delay,
+ _enc->rc.scale_window_end-_enc->rc.scale_window0),
_enc->rc.frames_left[0]+_enc->rc.frames_left[1]
-_enc->rc.nframes[0]-_enc->rc.nframes[1]);
/*Clear the buffer for the next frame.*/
@@ -1124,6 +1133,7 @@ int oc_enc_rc_2pass_in(oc_enc_ctx *_enc,unsigned char *_buf,size_t _bytes){
*(_enc->rc.frame_metrics+_enc->rc.frame_metrics_head);
_enc->rc.twopass_force_kf=
_enc->rc.cur_metrics.frame_type==OC_INTRA_FRAME;
+ _enc->activity_avg=_enc->rc.cur_metrics.activity_avg;
/*"Helpfully" set the dup count back to what it was in pass 1.*/
arg=_enc->rc.cur_metrics.dup_count;
th_encode_ctl(_enc,TH_ENCCTL_SET_DUP_COUNT,&arg,sizeof(arg));
diff --git a/thirdparty/libtheora/state.c b/thirdparty/libtheora/state.c
index 42ed33a9a3..f4c6240387 100644
--- a/thirdparty/libtheora/state.c
+++ b/thirdparty/libtheora/state.c
@@ -11,25 +11,93 @@
********************************************************************
function:
- last mod: $Id: state.c 16503 2009-08-22 18:14:02Z giles $
+ last mod: $Id$
********************************************************************/
#include <stdlib.h>
#include <string.h>
-#include "internal.h"
-#if defined(OC_X86_ASM)
-#if defined(_MSC_VER)
-# include "x86_vc/x86int.h"
-#else
-# include "x86/x86int.h"
-#endif
-#endif
+#include "state.h"
#if defined(OC_DUMP_IMAGES)
# include <stdio.h>
# include "png.h"
+# include "zlib.h"
#endif
+/*The function used to fill in the chroma plane motion vectors for a macro
+ block when 4 different motion vectors are specified in the luma plane.
+ This version is for use with chroma decimated in the X and Y directions
+ (4:2:0).
+ _cbmvs: The chroma block-level motion vectors to fill in.
+ _lbmvs: The luma block-level motion vectors.*/
+static void oc_set_chroma_mvs00(oc_mv _cbmvs[4],const oc_mv _lbmvs[4]){
+ int dx;
+ int dy;
+ dx=OC_MV_X(_lbmvs[0])+OC_MV_X(_lbmvs[1])
+ +OC_MV_X(_lbmvs[2])+OC_MV_X(_lbmvs[3]);
+ dy=OC_MV_Y(_lbmvs[0])+OC_MV_Y(_lbmvs[1])
+ +OC_MV_Y(_lbmvs[2])+OC_MV_Y(_lbmvs[3]);
+ _cbmvs[0]=OC_MV(OC_DIV_ROUND_POW2(dx,2,2),OC_DIV_ROUND_POW2(dy,2,2));
+}
+
+/*The function used to fill in the chroma plane motion vectors for a macro
+ block when 4 different motion vectors are specified in the luma plane.
+ This version is for use with chroma decimated in the Y direction.
+ _cbmvs: The chroma block-level motion vectors to fill in.
+ _lbmvs: The luma block-level motion vectors.*/
+static void oc_set_chroma_mvs01(oc_mv _cbmvs[4],const oc_mv _lbmvs[4]){
+ int dx;
+ int dy;
+ dx=OC_MV_X(_lbmvs[0])+OC_MV_X(_lbmvs[2]);
+ dy=OC_MV_Y(_lbmvs[0])+OC_MV_Y(_lbmvs[2]);
+ _cbmvs[0]=OC_MV(OC_DIV_ROUND_POW2(dx,1,1),OC_DIV_ROUND_POW2(dy,1,1));
+ dx=OC_MV_X(_lbmvs[1])+OC_MV_X(_lbmvs[3]);
+ dy=OC_MV_Y(_lbmvs[1])+OC_MV_Y(_lbmvs[3]);
+ _cbmvs[1]=OC_MV(OC_DIV_ROUND_POW2(dx,1,1),OC_DIV_ROUND_POW2(dy,1,1));
+}
+
+/*The function used to fill in the chroma plane motion vectors for a macro
+ block when 4 different motion vectors are specified in the luma plane.
+ This version is for use with chroma decimated in the X direction (4:2:2).
+ _cbmvs: The chroma block-level motion vectors to fill in.
+ _lbmvs: The luma block-level motion vectors.*/
+static void oc_set_chroma_mvs10(oc_mv _cbmvs[4],const oc_mv _lbmvs[4]){
+ int dx;
+ int dy;
+ dx=OC_MV_X(_lbmvs[0])+OC_MV_X(_lbmvs[1]);
+ dy=OC_MV_Y(_lbmvs[0])+OC_MV_Y(_lbmvs[1]);
+ _cbmvs[0]=OC_MV(OC_DIV_ROUND_POW2(dx,1,1),OC_DIV_ROUND_POW2(dy,1,1));
+ dx=OC_MV_X(_lbmvs[2])+OC_MV_X(_lbmvs[3]);
+ dy=OC_MV_Y(_lbmvs[2])+OC_MV_Y(_lbmvs[3]);
+ _cbmvs[2]=OC_MV(OC_DIV_ROUND_POW2(dx,1,1),OC_DIV_ROUND_POW2(dy,1,1));
+}
+
+/*The function used to fill in the chroma plane motion vectors for a macro
+ block when 4 different motion vectors are specified in the luma plane.
+ This version is for use with no chroma decimation (4:4:4).
+ _cbmvs: The chroma block-level motion vectors to fill in.
+ _lmbmv: The luma macro-block level motion vector to fill in for use in
+ prediction.
+ _lbmvs: The luma block-level motion vectors.*/
+static void oc_set_chroma_mvs11(oc_mv _cbmvs[4],const oc_mv _lbmvs[4]){
+ _cbmvs[0]=_lbmvs[0];
+ _cbmvs[1]=_lbmvs[1];
+ _cbmvs[2]=_lbmvs[2];
+ _cbmvs[3]=_lbmvs[3];
+}
+
+/*A table of functions used to fill in the chroma plane motion vectors for a
+ macro block when 4 different motion vectors are specified in the luma
+ plane.*/
+const oc_set_chroma_mvs_func OC_SET_CHROMA_MVS_TABLE[TH_PF_NFORMATS]={
+ (oc_set_chroma_mvs_func)oc_set_chroma_mvs00,
+ (oc_set_chroma_mvs_func)oc_set_chroma_mvs01,
+ (oc_set_chroma_mvs_func)oc_set_chroma_mvs10,
+ (oc_set_chroma_mvs_func)oc_set_chroma_mvs11
+};
+
+
+
/*Returns the fragment index of the top-left block in a macro block.
This can be used to test whether or not the whole macro block is valid.
_sb_map: The super block map.
@@ -92,7 +160,7 @@ static void oc_sb_create_plane_mapping(oc_sb_map _sb_maps[],
if(jmax>4)jmax=4;
else if(jmax<=0)break;
/*By default, set all fragment indices to -1.*/
- memset(_sb_maps[sbi][0],0xFF,sizeof(_sb_maps[sbi]));
+ memset(_sb_maps[sbi],0xFF,sizeof(_sb_maps[sbi]));
/*Fill in the fragment map for this super block.*/
xfrag=yfrag+x;
for(i=0;i<imax;i++){
@@ -186,10 +254,14 @@ static void oc_mb_fill_cmapping10(oc_mb_map_plane _mb_map[3],
This version is for use with no chroma decimation (4:4:4).
This uses the already filled-in luma plane values.
_mb_map: The macro block map to fill.
- _fplanes: The descriptions of the fragment planes.*/
+ _fplanes: The descriptions of the fragment planes.
+ _xfrag0: The X location of the upper-left hand fragment in the luma plane.
+ _yfrag0: The Y location of the upper-left hand fragment in the luma plane.*/
static void oc_mb_fill_cmapping11(oc_mb_map_plane _mb_map[3],
- const oc_fragment_plane _fplanes[3]){
+ const oc_fragment_plane _fplanes[3],int _xfrag0,int _yfrag0){
int k;
+ (void)_xfrag0;
+ (void)_yfrag0;
for(k=0;k<4;k++){
_mb_map[1][k]=_mb_map[0][k]+_fplanes[1].froffset;
_mb_map[2][k]=_mb_map[0][k]+_fplanes[2].froffset;
@@ -211,7 +283,7 @@ static const oc_mb_fill_cmapping_func OC_MB_FILL_CMAPPING_TABLE[4]={
oc_mb_fill_cmapping00,
oc_mb_fill_cmapping01,
oc_mb_fill_cmapping10,
- (oc_mb_fill_cmapping_func)oc_mb_fill_cmapping11
+ oc_mb_fill_cmapping11
};
/*Fills in the mapping from macro blocks to their corresponding fragment
@@ -469,7 +541,7 @@ static void oc_state_frarray_clear(oc_theora_state *_state){
unrestricted motion vectors without special casing the boundary.
If chroma is decimated in either direction, the padding is reduced by a
factor of 2 on the appropriate sides.
- _nrefs: The number of reference buffers to init; must be 3 or 4.*/
+ _nrefs: The number of reference buffers to init; must be in the range 3...6.*/
static int oc_state_ref_bufs_init(oc_theora_state *_state,int _nrefs){
th_info *info;
unsigned char *ref_frame_data;
@@ -481,6 +553,7 @@ static int oc_state_ref_bufs_init(oc_theora_state *_state,int _nrefs){
int yheight;
int chstride;
int cheight;
+ ptrdiff_t align;
ptrdiff_t yoffset;
ptrdiff_t coffset;
ptrdiff_t *frag_buf_offs;
@@ -489,33 +562,38 @@ static int oc_state_ref_bufs_init(oc_theora_state *_state,int _nrefs){
int vdec;
int rfi;
int pli;
- if(_nrefs<3||_nrefs>4)return TH_EINVAL;
+ if(_nrefs<3||_nrefs>6)return TH_EINVAL;
info=&_state->info;
/*Compute the image buffer parameters for each plane.*/
hdec=!(info->pixel_fmt&1);
vdec=!(info->pixel_fmt&2);
yhstride=info->frame_width+2*OC_UMV_PADDING;
yheight=info->frame_height+2*OC_UMV_PADDING;
- chstride=yhstride>>hdec;
+ /*Require 16-byte aligned rows in the chroma planes.*/
+ chstride=(yhstride>>hdec)+15&~15;
cheight=yheight>>vdec;
yplane_sz=yhstride*(size_t)yheight;
cplane_sz=chstride*(size_t)cheight;
yoffset=OC_UMV_PADDING+OC_UMV_PADDING*(ptrdiff_t)yhstride;
coffset=(OC_UMV_PADDING>>hdec)+(OC_UMV_PADDING>>vdec)*(ptrdiff_t)chstride;
- ref_frame_sz=yplane_sz+2*cplane_sz;
+ /*Although we guarantee the rows of the chroma planes are a multiple of 16
+ bytes, the initial padding on the first row may only be 8 bytes.
+ Compute the offset needed to the actual image data to a multiple of 16.*/
+ align=-coffset&15;
+ ref_frame_sz=yplane_sz+2*cplane_sz+16;
ref_frame_data_sz=_nrefs*ref_frame_sz;
/*Check for overflow.
The same caveats apply as for oc_state_frarray_init().*/
- if(yplane_sz/yhstride!=yheight||2*cplane_sz<cplane_sz||
+ if(yplane_sz/yhstride!=(size_t)yheight||2*cplane_sz+16<cplane_sz||
ref_frame_sz<yplane_sz||ref_frame_data_sz/_nrefs!=ref_frame_sz){
return TH_EIMPL;
}
- ref_frame_data=_ogg_malloc(ref_frame_data_sz);
+ ref_frame_data=oc_aligned_malloc(ref_frame_data_sz,16);
frag_buf_offs=_state->frag_buf_offs=
_ogg_malloc(_state->nfrags*sizeof(*frag_buf_offs));
if(ref_frame_data==NULL||frag_buf_offs==NULL){
_ogg_free(frag_buf_offs);
- _ogg_free(ref_frame_data);
+ oc_aligned_free(ref_frame_data);
return TH_EFAULT;
}
/*Set up the width, height and stride for the image buffers.*/
@@ -532,15 +610,15 @@ static int oc_state_ref_bufs_init(oc_theora_state *_state,int _nrefs){
memcpy(_state->ref_frame_bufs[rfi],_state->ref_frame_bufs[0],
sizeof(_state->ref_frame_bufs[0]));
}
+ _state->ref_frame_handle=ref_frame_data;
/*Set up the data pointers for the image buffers.*/
for(rfi=0;rfi<_nrefs;rfi++){
- _state->ref_frame_data[rfi]=ref_frame_data;
_state->ref_frame_bufs[rfi][0].data=ref_frame_data+yoffset;
- ref_frame_data+=yplane_sz;
+ ref_frame_data+=yplane_sz+align;
_state->ref_frame_bufs[rfi][1].data=ref_frame_data+coffset;
ref_frame_data+=cplane_sz;
_state->ref_frame_bufs[rfi][2].data=ref_frame_data+coffset;
- ref_frame_data+=cplane_sz;
+ ref_frame_data+=cplane_sz+(16-align);
/*Flip the buffer upside down.
This allows us to decode Theora's bottom-up frames in their natural
order, yet return a top-down buffer with a positive stride to the user.*/
@@ -550,7 +628,7 @@ static int oc_state_ref_bufs_init(oc_theora_state *_state,int _nrefs){
_state->ref_ystride[0]=-yhstride;
_state->ref_ystride[1]=_state->ref_ystride[2]=-chstride;
/*Initialize the fragment buffer offsets.*/
- ref_frame_data=_state->ref_frame_data[0];
+ ref_frame_data=_state->ref_frame_bufs[0][0].data;
fragi=0;
for(pli=0;pli<3;pli++){
th_img_plane *iplane;
@@ -576,41 +654,44 @@ static int oc_state_ref_bufs_init(oc_theora_state *_state,int _nrefs){
vpix+=stride<<3;
}
}
- /*Initialize the reference frame indices.*/
+ /*Initialize the reference frame pointers and indices.*/
_state->ref_frame_idx[OC_FRAME_GOLD]=
_state->ref_frame_idx[OC_FRAME_PREV]=
- _state->ref_frame_idx[OC_FRAME_SELF]=-1;
- _state->ref_frame_idx[OC_FRAME_IO]=_nrefs>3?3:-1;
+ _state->ref_frame_idx[OC_FRAME_GOLD_ORIG]=
+ _state->ref_frame_idx[OC_FRAME_PREV_ORIG]=
+ _state->ref_frame_idx[OC_FRAME_SELF]=
+ _state->ref_frame_idx[OC_FRAME_IO]=-1;
+ _state->ref_frame_data[OC_FRAME_GOLD]=
+ _state->ref_frame_data[OC_FRAME_PREV]=
+ _state->ref_frame_data[OC_FRAME_GOLD_ORIG]=
+ _state->ref_frame_data[OC_FRAME_PREV_ORIG]=
+ _state->ref_frame_data[OC_FRAME_SELF]=
+ _state->ref_frame_data[OC_FRAME_IO]=NULL;
return 0;
}
static void oc_state_ref_bufs_clear(oc_theora_state *_state){
_ogg_free(_state->frag_buf_offs);
- _ogg_free(_state->ref_frame_data[0]);
+ oc_aligned_free(_state->ref_frame_handle);
}
-void oc_state_vtable_init_c(oc_theora_state *_state){
+void oc_state_accel_init_c(oc_theora_state *_state){
+ _state->cpu_flags=0;
+#if defined(OC_STATE_USE_VTABLE)
_state->opt_vtable.frag_copy=oc_frag_copy_c;
+ _state->opt_vtable.frag_copy_list=oc_frag_copy_list_c;
_state->opt_vtable.frag_recon_intra=oc_frag_recon_intra_c;
_state->opt_vtable.frag_recon_inter=oc_frag_recon_inter_c;
_state->opt_vtable.frag_recon_inter2=oc_frag_recon_inter2_c;
_state->opt_vtable.idct8x8=oc_idct8x8_c;
_state->opt_vtable.state_frag_recon=oc_state_frag_recon_c;
- _state->opt_vtable.state_frag_copy_list=oc_state_frag_copy_list_c;
+ _state->opt_vtable.loop_filter_init=oc_loop_filter_init_c;
_state->opt_vtable.state_loop_filter_frag_rows=
oc_state_loop_filter_frag_rows_c;
_state->opt_vtable.restore_fpu=oc_restore_fpu_c;
- _state->opt_data.dct_fzig_zag=OC_FZIG_ZAG;
-}
-
-/*Initialize the accelerated function pointers.*/
-void oc_state_vtable_init(oc_theora_state *_state){
-#if defined(OC_X86_ASM)
- oc_state_vtable_init_x86(_state);
-#else
- oc_state_vtable_init_c(_state);
#endif
+ _state->opt_data.dct_fzig_zag=OC_FZIG_ZAG;
}
@@ -626,7 +707,8 @@ int oc_state_init(oc_theora_state *_state,const th_info *_info,int _nrefs){
how it is specified in the bitstream, because the Y axis is flipped in
the bitstream.
The displayable frame must fit inside the encoded frame.
- The color space must be one known by the encoder.*/
+ The color space must be one known by the encoder.
+ The framerate ratio must not contain a zero value.*/
if((_info->frame_width&0xF)||(_info->frame_height&0xF)||
_info->frame_width<=0||_info->frame_width>=0x100000||
_info->frame_height<=0||_info->frame_height>=0x100000||
@@ -639,7 +721,8 @@ int oc_state_init(oc_theora_state *_state,const th_info *_info,int _nrefs){
but there are a number of compilers which will mis-optimize this.
It's better to live with the spurious warnings.*/
_info->colorspace<0||_info->colorspace>=TH_CS_NSPACES||
- _info->pixel_fmt<0||_info->pixel_fmt>=TH_PF_NFORMATS){
+ _info->pixel_fmt<0||_info->pixel_fmt>=TH_PF_NFORMATS||
+ _info->fps_numerator<1||_info->fps_denominator<1){
return TH_EINVAL;
}
memset(_state,0,sizeof(*_state));
@@ -648,7 +731,7 @@ int oc_state_init(oc_theora_state *_state,const th_info *_info,int _nrefs){
system.*/
_state->info.pic_y=_info->frame_height-_info->pic_height-_info->pic_y;
_state->frame_type=OC_UNKWN_FRAME;
- oc_state_vtable_init(_state);
+ oc_state_accel_init(_state);
ret=oc_state_frarray_init(_state);
if(ret>=0)ret=oc_state_ref_bufs_init(_state,_nrefs);
if(ret<0){
@@ -758,11 +841,10 @@ void oc_state_borders_fill(oc_theora_state *_state,int _refi){
_offsets[1] is set if the motion vector has non-zero fractional
components.
_pli: The color plane index.
- _dx: The X component of the motion vector.
- _dy: The Y component of the motion vector.
+ _mv: The motion vector.
Return: The number of offsets returned: 1 or 2.*/
int oc_state_get_mv_offsets(const oc_theora_state *_state,int _offsets[2],
- int _pli,int _dx,int _dy){
+ int _pli,oc_mv _mv){
/*Here is a brief description of how Theora handles motion vectors:
Motion vector components are specified to half-pixel accuracy in
undecimated directions of each plane, and quarter-pixel accuracy in
@@ -785,21 +867,25 @@ int oc_state_get_mv_offsets(const oc_theora_state *_state,int _offsets[2],
int xfrac;
int yfrac;
int offs;
+ int dx;
+ int dy;
ystride=_state->ref_ystride[_pli];
/*These two variables decide whether we are in half- or quarter-pixel
precision in each component.*/
xprec=1+(_pli!=0&&!(_state->info.pixel_fmt&1));
yprec=1+(_pli!=0&&!(_state->info.pixel_fmt&2));
+ dx=OC_MV_X(_mv);
+ dy=OC_MV_Y(_mv);
/*These two variables are either 0 if all the fractional bits are zero or -1
if any of them are non-zero.*/
- xfrac=OC_SIGNMASK(-(_dx&(xprec|1)));
- yfrac=OC_SIGNMASK(-(_dy&(yprec|1)));
- offs=(_dx>>xprec)+(_dy>>yprec)*ystride;
+ xfrac=OC_SIGNMASK(-(dx&(xprec|1)));
+ yfrac=OC_SIGNMASK(-(dy&(yprec|1)));
+ offs=(dx>>xprec)+(dy>>yprec)*ystride;
if(xfrac||yfrac){
int xmask;
int ymask;
- xmask=OC_SIGNMASK(_dx);
- ymask=OC_SIGNMASK(_dy);
+ xmask=OC_SIGNMASK(dx);
+ ymask=OC_SIGNMASK(dy);
yfrac&=ystride;
_offsets[0]=offs-(xfrac&xmask)+(yfrac&ymask);
_offsets[1]=offs-(xfrac&~xmask)+(yfrac&~ymask);
@@ -848,13 +934,17 @@ int oc_state_get_mv_offsets(const oc_theora_state *_state,int _offsets[2],
int mx2;
int my2;
int offs;
+ int dx;
+ int dy;
ystride=_state->ref_ystride[_pli];
qpy=_pli!=0&&!(_state->info.pixel_fmt&2);
- my=OC_MVMAP[qpy][_dy+31];
- my2=OC_MVMAP2[qpy][_dy+31];
+ dx=OC_MV_X(_mv);
+ dy=OC_MV_Y(_mv);
+ my=OC_MVMAP[qpy][dy+31];
+ my2=OC_MVMAP2[qpy][dy+31];
qpx=_pli!=0&&!(_state->info.pixel_fmt&1);
- mx=OC_MVMAP[qpx][_dx+31];
- mx2=OC_MVMAP2[qpx][_dx+31];
+ mx=OC_MVMAP[qpx][dx+31];
+ mx2=OC_MVMAP2[qpx][dx+31];
offs=my*ystride+mx;
if(mx2||my2){
_offsets[1]=offs+my2*ystride+mx2;
@@ -866,18 +956,12 @@ int oc_state_get_mv_offsets(const oc_theora_state *_state,int _offsets[2],
#endif
}
-void oc_state_frag_recon(const oc_theora_state *_state,ptrdiff_t _fragi,
- int _pli,ogg_int16_t _dct_coeffs[64],int _last_zzi,ogg_uint16_t _dc_quant){
- _state->opt_vtable.state_frag_recon(_state,_fragi,_pli,_dct_coeffs,
- _last_zzi,_dc_quant);
-}
-
void oc_state_frag_recon_c(const oc_theora_state *_state,ptrdiff_t _fragi,
- int _pli,ogg_int16_t _dct_coeffs[64],int _last_zzi,ogg_uint16_t _dc_quant){
+ int _pli,ogg_int16_t _dct_coeffs[128],int _last_zzi,ogg_uint16_t _dc_quant){
unsigned char *dst;
ptrdiff_t frag_buf_off;
int ystride;
- int mb_mode;
+ int refi;
/*Apply the inverse transform.*/
/*Special case only having a DC component.*/
if(_last_zzi<2){
@@ -887,69 +971,35 @@ void oc_state_frag_recon_c(const oc_theora_state *_state,ptrdiff_t _fragi,
no iDCT rounding.*/
p=(ogg_int16_t)(_dct_coeffs[0]*(ogg_int32_t)_dc_quant+15>>5);
/*LOOP VECTORIZES.*/
- for(ci=0;ci<64;ci++)_dct_coeffs[ci]=p;
+ for(ci=0;ci<64;ci++)_dct_coeffs[64+ci]=p;
}
else{
/*First, dequantize the DC coefficient.*/
_dct_coeffs[0]=(ogg_int16_t)(_dct_coeffs[0]*(int)_dc_quant);
- oc_idct8x8(_state,_dct_coeffs,_last_zzi);
+ oc_idct8x8(_state,_dct_coeffs+64,_dct_coeffs,_last_zzi);
}
/*Fill in the target buffer.*/
frag_buf_off=_state->frag_buf_offs[_fragi];
- mb_mode=_state->frags[_fragi].mb_mode;
+ refi=_state->frags[_fragi].refi;
ystride=_state->ref_ystride[_pli];
- dst=_state->ref_frame_data[_state->ref_frame_idx[OC_FRAME_SELF]]+frag_buf_off;
- if(mb_mode==OC_MODE_INTRA)oc_frag_recon_intra(_state,dst,ystride,_dct_coeffs);
+ dst=_state->ref_frame_data[OC_FRAME_SELF]+frag_buf_off;
+ if(refi==OC_FRAME_SELF)oc_frag_recon_intra(_state,dst,ystride,_dct_coeffs+64);
else{
const unsigned char *ref;
int mvoffsets[2];
- ref=
- _state->ref_frame_data[_state->ref_frame_idx[OC_FRAME_FOR_MODE(mb_mode)]]
- +frag_buf_off;
+ ref=_state->ref_frame_data[refi]+frag_buf_off;
if(oc_state_get_mv_offsets(_state,mvoffsets,_pli,
- _state->frag_mvs[_fragi][0],_state->frag_mvs[_fragi][1])>1){
+ _state->frag_mvs[_fragi])>1){
oc_frag_recon_inter2(_state,
- dst,ref+mvoffsets[0],ref+mvoffsets[1],ystride,_dct_coeffs);
+ dst,ref+mvoffsets[0],ref+mvoffsets[1],ystride,_dct_coeffs+64);
+ }
+ else{
+ oc_frag_recon_inter(_state,dst,ref+mvoffsets[0],ystride,_dct_coeffs+64);
}
- else oc_frag_recon_inter(_state,dst,ref+mvoffsets[0],ystride,_dct_coeffs);
- }
-}
-
-/*Copies the fragments specified by the lists of fragment indices from one
- frame to another.
- _fragis: A pointer to a list of fragment indices.
- _nfragis: The number of fragment indices to copy.
- _dst_frame: The reference frame to copy to.
- _src_frame: The reference frame to copy from.
- _pli: The color plane the fragments lie in.*/
-void oc_state_frag_copy_list(const oc_theora_state *_state,
- const ptrdiff_t *_fragis,ptrdiff_t _nfragis,
- int _dst_frame,int _src_frame,int _pli){
- _state->opt_vtable.state_frag_copy_list(_state,_fragis,_nfragis,_dst_frame,
- _src_frame,_pli);
-}
-
-void oc_state_frag_copy_list_c(const oc_theora_state *_state,
- const ptrdiff_t *_fragis,ptrdiff_t _nfragis,
- int _dst_frame,int _src_frame,int _pli){
- const ptrdiff_t *frag_buf_offs;
- const unsigned char *src_frame_data;
- unsigned char *dst_frame_data;
- ptrdiff_t fragii;
- int ystride;
- dst_frame_data=_state->ref_frame_data[_state->ref_frame_idx[_dst_frame]];
- src_frame_data=_state->ref_frame_data[_state->ref_frame_idx[_src_frame]];
- ystride=_state->ref_ystride[_pli];
- frag_buf_offs=_state->frag_buf_offs;
- for(fragii=0;fragii<_nfragis;fragii++){
- ptrdiff_t frag_buf_off;
- frag_buf_off=frag_buf_offs[_fragis[fragii]];
- oc_frag_copy(_state,dst_frame_data+frag_buf_off,
- src_frame_data+frag_buf_off,ystride);
}
}
-static void loop_filter_h(unsigned char *_pix,int _ystride,int *_bv){
+static void loop_filter_h(unsigned char *_pix,int _ystride,signed char *_bv){
int y;
_pix-=2;
for(y=0;y<8;y++){
@@ -965,7 +1015,7 @@ static void loop_filter_h(unsigned char *_pix,int _ystride,int *_bv){
}
}
-static void loop_filter_v(unsigned char *_pix,int _ystride,int *_bv){
+static void loop_filter_v(unsigned char *_pix,int _ystride,signed char *_bv){
int x;
_pix-=_ystride*2;
for(x=0;x<8;x++){
@@ -982,20 +1032,16 @@ static void loop_filter_v(unsigned char *_pix,int _ystride,int *_bv){
/*Initialize the bounding values array used by the loop filter.
_bv: Storage for the array.
- Return: 0 on success, or a non-zero value if no filtering need be applied.*/
-int oc_state_loop_filter_init(oc_theora_state *_state,int _bv[256]){
- int flimit;
+ _flimit: The filter limit as defined in Section 7.10 of the spec.*/
+void oc_loop_filter_init_c(signed char _bv[256],int _flimit){
int i;
- flimit=_state->loop_filter_limits[_state->qis[0]];
- if(flimit==0)return 1;
memset(_bv,0,sizeof(_bv[0])*256);
- for(i=0;i<flimit;i++){
- if(127-i-flimit>=0)_bv[127-i-flimit]=i-flimit;
- _bv[127-i]=-i;
- _bv[127+i]=i;
- if(127+i+flimit<256)_bv[127+i+flimit]=flimit-i;
+ for(i=0;i<_flimit;i++){
+ if(127-i-_flimit>=0)_bv[127-i-_flimit]=(signed char)(i-_flimit);
+ _bv[127-i]=(signed char)(-i);
+ _bv[127+i]=(signed char)(i);
+ if(127+i+_flimit<256)_bv[127+i+_flimit]=(signed char)(_flimit-i);
}
- return 0;
}
/*Apply the loop filter to a given set of fragment rows in the given plane.
@@ -1006,14 +1052,8 @@ int oc_state_loop_filter_init(oc_theora_state *_state,int _bv[256]){
_pli: The color plane to filter.
_fragy0: The Y coordinate of the first fragment row to filter.
_fragy_end: The Y coordinate of the fragment row to stop filtering at.*/
-void oc_state_loop_filter_frag_rows(const oc_theora_state *_state,int _bv[256],
- int _refi,int _pli,int _fragy0,int _fragy_end){
- _state->opt_vtable.state_loop_filter_frag_rows(_state,_bv,_refi,_pli,
- _fragy0,_fragy_end);
-}
-
-void oc_state_loop_filter_frag_rows_c(const oc_theora_state *_state,int *_bv,
- int _refi,int _pli,int _fragy0,int _fragy_end){
+void oc_state_loop_filter_frag_rows_c(const oc_theora_state *_state,
+ signed char *_bv,int _refi,int _pli,int _fragy0,int _fragy_end){
const oc_fragment_plane *fplane;
const oc_fragment *frags;
const ptrdiff_t *frag_buf_offs;
@@ -1030,7 +1070,7 @@ void oc_state_loop_filter_frag_rows_c(const oc_theora_state *_state,int *_bv,
fragi_top=fplane->froffset;
fragi_bot=fragi_top+fplane->nfrags;
fragi0=fragi_top+_fragy0*(ptrdiff_t)nhfrags;
- fragi0_end=fragi0+(_fragy_end-_fragy0)*(ptrdiff_t)nhfrags;
+ fragi0_end=fragi_top+_fragy_end*(ptrdiff_t)nhfrags;
ystride=_state->ref_ystride[_pli];
frags=_state->frags;
frag_buf_offs=_state->frag_buf_offs;
diff --git a/thirdparty/libtheora/state.h b/thirdparty/libtheora/state.h
new file mode 100644
index 0000000000..f176a53ce9
--- /dev/null
+++ b/thirdparty/libtheora/state.h
@@ -0,0 +1,552 @@
+/********************************************************************
+ * *
+ * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. *
+ * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
+ * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
+ * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
+ * *
+ * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 *
+ * by the Xiph.Org Foundation and contributors http://www.xiph.org/ *
+ * *
+ ********************************************************************
+
+ function:
+ last mod: $Id: internal.h 17337 2010-07-19 16:08:54Z tterribe $
+
+ ********************************************************************/
+#if !defined(_state_H)
+# define _state_H (1)
+# include "internal.h"
+# include "huffman.h"
+# include "quant.h"
+
+
+
+/*A single quadrant of the map from a super block to fragment numbers.*/
+typedef ptrdiff_t oc_sb_map_quad[4];
+/*A map from a super block to fragment numbers.*/
+typedef oc_sb_map_quad oc_sb_map[4];
+/*A single plane of the map from a macro block to fragment numbers.*/
+typedef ptrdiff_t oc_mb_map_plane[4];
+/*A map from a macro block to fragment numbers.*/
+typedef oc_mb_map_plane oc_mb_map[3];
+/*A motion vector.*/
+typedef ogg_int16_t oc_mv;
+
+typedef struct oc_sb_flags oc_sb_flags;
+typedef struct oc_border_info oc_border_info;
+typedef struct oc_fragment oc_fragment;
+typedef struct oc_fragment_plane oc_fragment_plane;
+typedef struct oc_base_opt_vtable oc_base_opt_vtable;
+typedef struct oc_base_opt_data oc_base_opt_data;
+typedef struct oc_state_dispatch_vtable oc_state_dispatch_vtable;
+typedef struct oc_theora_state oc_theora_state;
+
+
+
+/*Shared accelerated functions.*/
+# if defined(OC_X86_ASM)
+# if defined(_MSC_VER)
+# include "x86_vc/x86int.h"
+# else
+# include "x86/x86int.h"
+# endif
+# endif
+# if defined(OC_ARM_ASM)
+# include "arm/armint.h"
+# endif
+# if defined(OC_C64X_ASM)
+# include "c64x/c64xint.h"
+# endif
+
+# if !defined(oc_state_accel_init)
+# define oc_state_accel_init oc_state_accel_init_c
+# endif
+# if defined(OC_STATE_USE_VTABLE)
+# if !defined(oc_frag_copy)
+# define oc_frag_copy(_state,_dst,_src,_ystride) \
+ ((*(_state)->opt_vtable.frag_copy)(_dst,_src,_ystride))
+# endif
+# if !defined(oc_frag_copy_list)
+# define oc_frag_copy_list(_state,_dst_frame,_src_frame,_ystride, \
+ _fragis,_nfragis,_frag_buf_offs) \
+ ((*(_state)->opt_vtable.frag_copy_list)(_dst_frame,_src_frame,_ystride, \
+ _fragis,_nfragis,_frag_buf_offs))
+# endif
+# if !defined(oc_frag_recon_intra)
+# define oc_frag_recon_intra(_state,_dst,_dst_ystride,_residue) \
+ ((*(_state)->opt_vtable.frag_recon_intra)(_dst,_dst_ystride,_residue))
+# endif
+# if !defined(oc_frag_recon_inter)
+# define oc_frag_recon_inter(_state,_dst,_src,_ystride,_residue) \
+ ((*(_state)->opt_vtable.frag_recon_inter)(_dst,_src,_ystride,_residue))
+# endif
+# if !defined(oc_frag_recon_inter2)
+# define oc_frag_recon_inter2(_state,_dst,_src1,_src2,_ystride,_residue) \
+ ((*(_state)->opt_vtable.frag_recon_inter2)(_dst, \
+ _src1,_src2,_ystride,_residue))
+# endif
+# if !defined(oc_idct8x8)
+# define oc_idct8x8(_state,_y,_x,_last_zzi) \
+ ((*(_state)->opt_vtable.idct8x8)(_y,_x,_last_zzi))
+# endif
+# if !defined(oc_state_frag_recon)
+# define oc_state_frag_recon(_state,_fragi, \
+ _pli,_dct_coeffs,_last_zzi,_dc_quant) \
+ ((*(_state)->opt_vtable.state_frag_recon)(_state,_fragi, \
+ _pli,_dct_coeffs,_last_zzi,_dc_quant))
+# endif
+# if !defined(oc_loop_filter_init)
+# define oc_loop_filter_init(_state,_bv,_flimit) \
+ ((*(_state)->opt_vtable.loop_filter_init)(_bv,_flimit))
+# endif
+# if !defined(oc_state_loop_filter_frag_rows)
+# define oc_state_loop_filter_frag_rows(_state, \
+ _bv,_refi,_pli,_fragy0,_fragy_end) \
+ ((*(_state)->opt_vtable.state_loop_filter_frag_rows)(_state, \
+ _bv,_refi,_pli,_fragy0,_fragy_end))
+# endif
+# if !defined(oc_restore_fpu)
+# define oc_restore_fpu(_state) \
+ ((*(_state)->opt_vtable.restore_fpu)())
+# endif
+# else
+# if !defined(oc_frag_copy)
+# define oc_frag_copy(_state,_dst,_src,_ystride) \
+ oc_frag_copy_c(_dst,_src,_ystride)
+# endif
+# if !defined(oc_frag_copy_list)
+# define oc_frag_copy_list(_state,_dst_frame,_src_frame,_ystride, \
+ _fragis,_nfragis,_frag_buf_offs) \
+ oc_frag_copy_list_c(_dst_frame,_src_frame,_ystride, \
+ _fragis,_nfragis,_frag_buf_offs)
+# endif
+# if !defined(oc_frag_recon_intra)
+# define oc_frag_recon_intra(_state,_dst,_dst_ystride,_residue) \
+ oc_frag_recon_intra_c(_dst,_dst_ystride,_residue)
+# endif
+# if !defined(oc_frag_recon_inter)
+# define oc_frag_recon_inter(_state,_dst,_src,_ystride,_residue) \
+ oc_frag_recon_inter_c(_dst,_src,_ystride,_residue)
+# endif
+# if !defined(oc_frag_recon_inter2)
+# define oc_frag_recon_inter2(_state,_dst,_src1,_src2,_ystride,_residue) \
+ oc_frag_recon_inter2_c(_dst,_src1,_src2,_ystride,_residue)
+# endif
+# if !defined(oc_idct8x8)
+# define oc_idct8x8(_state,_y,_x,_last_zzi) oc_idct8x8_c(_y,_x,_last_zzi)
+# endif
+# if !defined(oc_state_frag_recon)
+# define oc_state_frag_recon oc_state_frag_recon_c
+# endif
+# if !defined(oc_loop_filter_init)
+# define oc_loop_filter_init(_state,_bv,_flimit) \
+ oc_loop_filter_init_c(_bv,_flimit)
+# endif
+# if !defined(oc_state_loop_filter_frag_rows)
+# define oc_state_loop_filter_frag_rows oc_state_loop_filter_frag_rows_c
+# endif
+# if !defined(oc_restore_fpu)
+# define oc_restore_fpu(_state) do{}while(0)
+# endif
+# endif
+
+
+
+/*A keyframe.*/
+# define OC_INTRA_FRAME (0)
+/*A predicted frame.*/
+# define OC_INTER_FRAME (1)
+/*A frame of unknown type (frame type decision has not yet been made).*/
+# define OC_UNKWN_FRAME (-1)
+
+/*The amount of padding to add to the reconstructed frame buffers on all
+ sides.
+ This is used to allow unrestricted motion vectors without special casing.
+ This must be a multiple of 2.*/
+# define OC_UMV_PADDING (16)
+
+/*Frame classification indices.*/
+/*The previous golden frame.*/
+# define OC_FRAME_GOLD (0)
+/*The previous frame.*/
+# define OC_FRAME_PREV (1)
+/*The current frame.*/
+# define OC_FRAME_SELF (2)
+/*Used to mark uncoded fragments (for DC prediction).*/
+# define OC_FRAME_NONE (3)
+
+/*The input or output buffer.*/
+# define OC_FRAME_IO (3)
+/*Uncompressed prev golden frame.*/
+# define OC_FRAME_GOLD_ORIG (4)
+/*Uncompressed previous frame. */
+# define OC_FRAME_PREV_ORIG (5)
+
+/*Macroblock modes.*/
+/*Macro block is invalid: It is never coded.*/
+# define OC_MODE_INVALID (-1)
+/*Encoded difference from the same macro block in the previous frame.*/
+# define OC_MODE_INTER_NOMV (0)
+/*Encoded with no motion compensated prediction.*/
+# define OC_MODE_INTRA (1)
+/*Encoded difference from the previous frame offset by the given motion
+ vector.*/
+# define OC_MODE_INTER_MV (2)
+/*Encoded difference from the previous frame offset by the last coded motion
+ vector.*/
+# define OC_MODE_INTER_MV_LAST (3)
+/*Encoded difference from the previous frame offset by the second to last
+ coded motion vector.*/
+# define OC_MODE_INTER_MV_LAST2 (4)
+/*Encoded difference from the same macro block in the previous golden
+ frame.*/
+# define OC_MODE_GOLDEN_NOMV (5)
+/*Encoded difference from the previous golden frame offset by the given motion
+ vector.*/
+# define OC_MODE_GOLDEN_MV (6)
+/*Encoded difference from the previous frame offset by the individual motion
+ vectors given for each block.*/
+# define OC_MODE_INTER_MV_FOUR (7)
+/*The number of (coded) modes.*/
+# define OC_NMODES (8)
+
+/*Determines the reference frame used for a given MB mode.*/
+# define OC_FRAME_FOR_MODE(_x) \
+ OC_UNIBBLE_TABLE32(OC_FRAME_PREV,OC_FRAME_SELF,OC_FRAME_PREV,OC_FRAME_PREV, \
+ OC_FRAME_PREV,OC_FRAME_GOLD,OC_FRAME_GOLD,OC_FRAME_PREV,(_x))
+
+/*Constants for the packet state machine common between encoder and decoder.*/
+
+/*Next packet to emit/read: Codec info header.*/
+# define OC_PACKET_INFO_HDR (-3)
+/*Next packet to emit/read: Comment header.*/
+# define OC_PACKET_COMMENT_HDR (-2)
+/*Next packet to emit/read: Codec setup header.*/
+# define OC_PACKET_SETUP_HDR (-1)
+/*No more packets to emit/read.*/
+# define OC_PACKET_DONE (INT_MAX)
+
+
+
+#define OC_MV(_x,_y) ((oc_mv)((_x)&0xFF|(_y)<<8))
+#define OC_MV_X(_mv) ((signed char)(_mv))
+#define OC_MV_Y(_mv) ((_mv)>>8)
+#define OC_MV_ADD(_mv1,_mv2) \
+ OC_MV(OC_MV_X(_mv1)+OC_MV_X(_mv2), \
+ OC_MV_Y(_mv1)+OC_MV_Y(_mv2))
+#define OC_MV_SUB(_mv1,_mv2) \
+ OC_MV(OC_MV_X(_mv1)-OC_MV_X(_mv2), \
+ OC_MV_Y(_mv1)-OC_MV_Y(_mv2))
+
+
+
+/*Super blocks are 32x32 segments of pixels in a single color plane indexed
+ in image order.
+ Internally, super blocks are broken up into four quadrants, each of which
+ contains a 2x2 pattern of blocks, each of which is an 8x8 block of pixels.
+ Quadrants, and the blocks within them, are indexed in a special order called
+ a "Hilbert curve" within the super block.
+
+ In order to differentiate between the Hilbert-curve indexing strategy and
+ the regular image order indexing strategy, blocks indexed in image order
+ are called "fragments".
+ Fragments are indexed in image order, left to right, then bottom to top,
+ from Y' plane to Cb plane to Cr plane.
+
+ The co-located fragments in all image planes corresponding to the location
+ of a single quadrant of a luma plane super block form a macro block.
+ Thus there is only a single set of macro blocks for all planes, each of which
+ contains between 6 and 12 fragments, depending on the pixel format.
+ Therefore macro block information is kept in a separate set of arrays from
+ super blocks to avoid unused space in the other planes.
+ The lists are indexed in super block order.
+ That is, the macro block corresponding to the macro block mbi in (luma plane)
+ super block sbi is at index (sbi<<2|mbi).
+ Thus the number of macro blocks in each dimension is always twice the number
+ of super blocks, even when only an odd number fall inside the coded frame.
+ These "extra" macro blocks are just an artifact of our internal data layout,
+ and not part of the coded stream; they are flagged with a negative MB mode.*/
+
+
+
+/*Super block information.*/
+struct oc_sb_flags{
+ unsigned char coded_fully:1;
+ unsigned char coded_partially:1;
+ unsigned char quad_valid:4;
+};
+
+
+
+/*Information about a fragment which intersects the border of the displayable
+ region.
+ This marks which pixels belong to the displayable region.*/
+struct oc_border_info{
+ /*A bit mask marking which pixels are in the displayable region.
+ Pixel (x,y) corresponds to bit (y<<3|x).*/
+ ogg_int64_t mask;
+ /*The number of pixels in the displayable region.
+ This is always positive, and always less than 64.*/
+ int npixels;
+};
+
+
+
+/*Fragment information.*/
+struct oc_fragment{
+ /*A flag indicating whether or not this fragment is coded.*/
+ unsigned coded:1;
+ /*A flag indicating that this entire fragment lies outside the displayable
+ region of the frame.
+ Note the contrast with an invalid macro block, which is outside the coded
+ frame, not just the displayable one.
+ There are no fragments outside the coded frame by construction.*/
+ unsigned invalid:1;
+ /*The index of the quality index used for this fragment's AC coefficients.*/
+ unsigned qii:4;
+ /*The index of the reference frame this fragment is predicted from.*/
+ unsigned refi:2;
+ /*The mode of the macroblock this fragment belongs to.*/
+ unsigned mb_mode:3;
+ /*The index of the associated border information for fragments which lie
+ partially outside the displayable region.
+ For fragments completely inside or outside this region, this is -1.
+ Note that the C standard requires an explicit signed keyword for bitfield
+ types, since some compilers may treat them as unsigned without it.*/
+ signed int borderi:5;
+ /*The prediction-corrected DC component.
+ Note that the C standard requires an explicit signed keyword for bitfield
+ types, since some compilers may treat them as unsigned without it.*/
+ signed int dc:16;
+};
+
+
+
+/*A description of each fragment plane.*/
+struct oc_fragment_plane{
+ /*The number of fragments in the horizontal direction.*/
+ int nhfrags;
+ /*The number of fragments in the vertical direction.*/
+ int nvfrags;
+ /*The offset of the first fragment in the plane.*/
+ ptrdiff_t froffset;
+ /*The total number of fragments in the plane.*/
+ ptrdiff_t nfrags;
+ /*The number of super blocks in the horizontal direction.*/
+ unsigned nhsbs;
+ /*The number of super blocks in the vertical direction.*/
+ unsigned nvsbs;
+ /*The offset of the first super block in the plane.*/
+ unsigned sboffset;
+ /*The total number of super blocks in the plane.*/
+ unsigned nsbs;
+};
+
+
+typedef void (*oc_state_loop_filter_frag_rows_func)(
+ const oc_theora_state *_state,signed char _bv[256],int _refi,int _pli,
+ int _fragy0,int _fragy_end);
+
+/*The shared (encoder and decoder) functions that have accelerated variants.*/
+struct oc_base_opt_vtable{
+ void (*frag_copy)(unsigned char *_dst,
+ const unsigned char *_src,int _ystride);
+ void (*frag_copy_list)(unsigned char *_dst_frame,
+ const unsigned char *_src_frame,int _ystride,
+ const ptrdiff_t *_fragis,ptrdiff_t _nfragis,const ptrdiff_t *_frag_buf_offs);
+ void (*frag_recon_intra)(unsigned char *_dst,int _ystride,
+ const ogg_int16_t _residue[64]);
+ void (*frag_recon_inter)(unsigned char *_dst,
+ const unsigned char *_src,int _ystride,const ogg_int16_t _residue[64]);
+ void (*frag_recon_inter2)(unsigned char *_dst,const unsigned char *_src1,
+ const unsigned char *_src2,int _ystride,const ogg_int16_t _residue[64]);
+ void (*idct8x8)(ogg_int16_t _y[64],ogg_int16_t _x[64],int _last_zzi);
+ void (*state_frag_recon)(const oc_theora_state *_state,ptrdiff_t _fragi,
+ int _pli,ogg_int16_t _dct_coeffs[128],int _last_zzi,ogg_uint16_t _dc_quant);
+ void (*loop_filter_init)(signed char _bv[256],int _flimit);
+ oc_state_loop_filter_frag_rows_func state_loop_filter_frag_rows;
+ void (*restore_fpu)(void);
+};
+
+/*The shared (encoder and decoder) tables that vary according to which variants
+ of the above functions are used.*/
+struct oc_base_opt_data{
+ const unsigned char *dct_fzig_zag;
+};
+
+
+/*State information common to both the encoder and decoder.*/
+struct oc_theora_state{
+ /*The stream information.*/
+ th_info info;
+# if defined(OC_STATE_USE_VTABLE)
+ /*Table for shared accelerated functions.*/
+ oc_base_opt_vtable opt_vtable;
+# endif
+ /*Table for shared data used by accelerated functions.*/
+ oc_base_opt_data opt_data;
+ /*CPU flags to detect the presence of extended instruction sets.*/
+ ogg_uint32_t cpu_flags;
+ /*The fragment plane descriptions.*/
+ oc_fragment_plane fplanes[3];
+ /*The list of fragments, indexed in image order.*/
+ oc_fragment *frags;
+ /*The the offset into the reference frame buffer to the upper-left pixel of
+ each fragment.*/
+ ptrdiff_t *frag_buf_offs;
+ /*The motion vector for each fragment.*/
+ oc_mv *frag_mvs;
+ /*The total number of fragments in a single frame.*/
+ ptrdiff_t nfrags;
+ /*The list of super block maps, indexed in image order.*/
+ oc_sb_map *sb_maps;
+ /*The list of super block flags, indexed in image order.*/
+ oc_sb_flags *sb_flags;
+ /*The total number of super blocks in a single frame.*/
+ unsigned nsbs;
+ /*The fragments from each color plane that belong to each macro block.
+ Fragments are stored in image order (left to right then top to bottom).
+ When chroma components are decimated, the extra fragments have an index of
+ -1.*/
+ oc_mb_map *mb_maps;
+ /*The list of macro block modes.
+ A negative number indicates the macro block lies entirely outside the
+ coded frame.*/
+ signed char *mb_modes;
+ /*The number of macro blocks in the X direction.*/
+ unsigned nhmbs;
+ /*The number of macro blocks in the Y direction.*/
+ unsigned nvmbs;
+ /*The total number of macro blocks.*/
+ size_t nmbs;
+ /*The list of coded fragments, in coded order.
+ Uncoded fragments are stored in reverse order from the end of the list.*/
+ ptrdiff_t *coded_fragis;
+ /*The number of coded fragments in each plane.*/
+ ptrdiff_t ncoded_fragis[3];
+ /*The total number of coded fragments.*/
+ ptrdiff_t ntotal_coded_fragis;
+ /*The actual buffers used for the reference frames.*/
+ th_ycbcr_buffer ref_frame_bufs[6];
+ /*The index of the buffers being used for each OC_FRAME_* reference frame.*/
+ int ref_frame_idx[6];
+ /*The storage for the reference frame buffers.
+ This is just ref_frame_bufs[ref_frame_idx[i]][0].data, but is cached here
+ for faster look-up.*/
+ unsigned char *ref_frame_data[6];
+ /*The handle used to allocate the reference frame buffers.*/
+ unsigned char *ref_frame_handle;
+ /*The strides for each plane in the reference frames.*/
+ int ref_ystride[3];
+ /*The number of unique border patterns.*/
+ int nborders;
+ /*The unique border patterns for all border fragments.
+ The borderi field of fragments which straddle the border indexes this
+ list.*/
+ oc_border_info borders[16];
+ /*The frame number of the last keyframe.*/
+ ogg_int64_t keyframe_num;
+ /*The frame number of the current frame.*/
+ ogg_int64_t curframe_num;
+ /*The granpos of the current frame.*/
+ ogg_int64_t granpos;
+ /*The type of the current frame.*/
+ signed char frame_type;
+ /*The bias to add to the frame count when computing granule positions.*/
+ unsigned char granpos_bias;
+ /*The number of quality indices used in the current frame.*/
+ unsigned char nqis;
+ /*The quality indices of the current frame.*/
+ unsigned char qis[3];
+ /*The dequantization tables, stored in zig-zag order, and indexed by
+ qi, pli, qti, and zzi.*/
+ ogg_uint16_t *dequant_tables[64][3][2];
+ OC_ALIGN16(oc_quant_table dequant_table_data[64][3][2]);
+ /*Loop filter strength parameters.*/
+ unsigned char loop_filter_limits[64];
+};
+
+
+
+/*The function type used to fill in the chroma plane motion vectors for a
+ macro block when 4 different motion vectors are specified in the luma
+ plane.
+ _cbmvs: The chroma block-level motion vectors to fill in.
+ _lmbmv: The luma macro-block level motion vector to fill in for use in
+ prediction.
+ _lbmvs: The luma block-level motion vectors.*/
+typedef void (*oc_set_chroma_mvs_func)(oc_mv _cbmvs[4],const oc_mv _lbmvs[4]);
+
+
+
+/*A table of functions used to fill in the Cb,Cr plane motion vectors for a
+ macro block when 4 different motion vectors are specified in the luma
+ plane.*/
+extern const oc_set_chroma_mvs_func OC_SET_CHROMA_MVS_TABLE[TH_PF_NFORMATS];
+
+
+
+int oc_state_init(oc_theora_state *_state,const th_info *_info,int _nrefs);
+void oc_state_clear(oc_theora_state *_state);
+void oc_state_accel_init_c(oc_theora_state *_state);
+void oc_state_borders_fill_rows(oc_theora_state *_state,int _refi,int _pli,
+ int _y0,int _yend);
+void oc_state_borders_fill_caps(oc_theora_state *_state,int _refi,int _pli);
+void oc_state_borders_fill(oc_theora_state *_state,int _refi);
+void oc_state_fill_buffer_ptrs(oc_theora_state *_state,int _buf_idx,
+ th_ycbcr_buffer _img);
+int oc_state_mbi_for_pos(oc_theora_state *_state,int _mbx,int _mby);
+int oc_state_get_mv_offsets(const oc_theora_state *_state,int _offsets[2],
+ int _pli,oc_mv _mv);
+
+void oc_loop_filter_init_c(signed char _bv[256],int _flimit);
+void oc_state_loop_filter(oc_theora_state *_state,int _frame);
+# if defined(OC_DUMP_IMAGES)
+int oc_state_dump_frame(const oc_theora_state *_state,int _frame,
+ const char *_suf);
+# endif
+
+/*Default pure-C implementations of shared accelerated functions.*/
+void oc_frag_copy_c(unsigned char *_dst,
+ const unsigned char *_src,int _src_ystride);
+void oc_frag_copy_list_c(unsigned char *_dst_frame,
+ const unsigned char *_src_frame,int _ystride,
+ const ptrdiff_t *_fragis,ptrdiff_t _nfragis,const ptrdiff_t *_frag_buf_offs);
+void oc_frag_recon_intra_c(unsigned char *_dst,int _dst_ystride,
+ const ogg_int16_t _residue[64]);
+void oc_frag_recon_inter_c(unsigned char *_dst,
+ const unsigned char *_src,int _ystride,const ogg_int16_t _residue[64]);
+void oc_frag_recon_inter2_c(unsigned char *_dst,const unsigned char *_src1,
+ const unsigned char *_src2,int _ystride,const ogg_int16_t _residue[64]);
+void oc_idct8x8_c(ogg_int16_t _y[64],ogg_int16_t _x[64],int _last_zzi);
+void oc_state_frag_recon_c(const oc_theora_state *_state,ptrdiff_t _fragi,
+ int _pli,ogg_int16_t _dct_coeffs[128],int _last_zzi,ogg_uint16_t _dc_quant);
+void oc_state_loop_filter_frag_rows_c(const oc_theora_state *_state,
+ signed char _bv[256],int _refi,int _pli,int _fragy0,int _fragy_end);
+void oc_restore_fpu_c(void);
+
+/*We need a way to call a few encoder functions without introducing a link-time
+ dependency into the decoder, while still allowing the old alpha API which
+ does not distinguish between encoder and decoder objects to be used.
+ We do this by placing a function table at the start of the encoder object
+ which can dispatch into the encoder library.
+ We do a similar thing for the decoder in case we ever decide to split off a
+ common base library.*/
+typedef void (*oc_state_clear_func)(theora_state *_th);
+typedef int (*oc_state_control_func)(theora_state *th,int _req,
+ void *_buf,size_t _buf_sz);
+typedef ogg_int64_t (*oc_state_granule_frame_func)(theora_state *_th,
+ ogg_int64_t _granulepos);
+typedef double (*oc_state_granule_time_func)(theora_state *_th,
+ ogg_int64_t _granulepos);
+
+
+struct oc_state_dispatch_vtable{
+ oc_state_clear_func clear;
+ oc_state_control_func control;
+ oc_state_granule_frame_func granule_frame;
+ oc_state_granule_time_func granule_time;
+};
+
+#endif
diff --git a/thirdparty/libtheora/theora/codec.h b/thirdparty/libtheora/theora/codec.h
index 5c2669630c..29b8602325 100644
--- a/thirdparty/libtheora/theora/codec.h
+++ b/thirdparty/libtheora/theora/codec.h
@@ -16,11 +16,12 @@
********************************************************************/
/**\mainpage
- *
+ *
* \section intro Introduction
*
- * This is the documentation for <tt>libtheora</tt> C API.
- * The current reference
+ * This is the documentation for the <tt>libtheora</tt> C API.
+ *
+ * The \c libtheora package is the current reference
* implementation for <a href="http://www.theora.org/">Theora</a>, a free,
* patent-unencumbered video codec.
* Theora is derived from On2's VP3 codec with additional features and
@@ -30,29 +31,31 @@
* <a href="http://www.theora.org/doc/Theora.pdf">the Theora
* specification</a>.
*
- * \subsection Organization
+ * \section Organization
*
- * The functions documented here are actually subdivided into three
+ * The functions documented here are divided between two
* separate libraries:
- * - <tt>libtheoraenc</tt> contains the encoder interface,
+ * - \c libtheoraenc contains the encoder interface,
* described in \ref encfuncs.
- * - <tt>libtheoradec</tt> contains the decoder interface and
- * routines shared with the encoder.
- * You must also link to this if you link to <tt>libtheoraenc</tt>.
- * The routines in this library are described in \ref decfuncs and
- * \ref basefuncs.
- * - <tt>libtheora</tt> contains the \ref oldfuncs.
+ * - \c libtheoradec contains the decoder interface,
+ * described in \ref decfuncs, \n
+ * and additional \ref basefuncs.
+ *
+ * New code should link to \c libtheoradec. If using encoder
+ * features, it must also link to \c libtheoraenc.
*
- * New code should link to <tt>libtheoradec</tt> and, if using encoder
- * features, <tt>libtheoraenc</tt>. Together these two export both
- * the standard and the legacy API, so this is all that is needed by
- * any code. The older <tt>libtheora</tt> library is provided just for
- * compatibility with older build configurations.
+ * During initial development, prior to the 1.0 release,
+ * \c libtheora exported a different \ref oldfuncs which
+ * combined both encode and decode functions.
+ * In general, legacy API symbols can be indentified
+ * by their \c theora_ or \c OC_ namespace prefixes.
+ * The current API uses \c th_ or \c TH_ instead.
*
- * In general the recommended 1.x API symbols can be distinguished
- * by their <tt>th_</tt> or <tt>TH_</tt> namespace prefix.
- * The older, legacy API uses <tt>theora_</tt> or <tt>OC_</tt>
- * prefixes instead.
+ * While deprecated, \c libtheoraenc and \c libtheoradec
+ * together export the legacy api as well at the one documented above.
+ * Likewise, the legacy \c libtheora included with this package
+ * exports the new 1.x API. Older code and build scripts can therefore
+ * but updated independently to the current scheme.
*/
/**\file
@@ -168,7 +171,7 @@ typedef struct{
typedef th_img_plane th_ycbcr_buffer[3];
/**Theora bitstream information.
- * This contains the basic playback parameters for a stream, and corresponds to
+ * This contains the basic playback parameters for a stream, and corresponds to
* the initial 'info' header packet.
* To initialize an encoder, the application fills in this structure and
* passes it to th_encode_alloc().
@@ -317,7 +320,7 @@ typedef struct{
* In filling in this structure, th_decode_headerin() will null-terminate
* the user_comment strings for safety.
* However, the bitstream format itself treats them as 8-bit clean vectors,
- * possibly containing null characters, and so the length array should be
+ * possibly containing null characters, so the length array should be
* treated as their authoritative length.
*/
typedef struct th_comment{
@@ -448,7 +451,13 @@ typedef struct{
/**\defgroup basefuncs Functions Shared by Encode and Decode*/
/*@{*/
-/**\name Basic shared functions*/
+/**\name Basic shared functions
+ * These functions return information about the library itself,
+ * or provide high-level information about codec state
+ * and packet type.
+ *
+ * You must link to \c libtheoradec if you use any of the
+ * functions in this section.*/
/*@{*/
/**Retrieves a human-readable string to identify the library vendor and
* version.
@@ -510,7 +519,12 @@ extern int th_packet_iskeyframe(ogg_packet *_op);
/*@}*/
-/**\name Functions for manipulating header data*/
+/**\name Functions for manipulating header data
+ * These functions manipulate the #th_info and #th_comment structures
+ * which describe video parameters and key-value metadata, respectively.
+ *
+ * You must link to \c libtheoradec if you use any of the
+ * functions in this section.*/
/*@{*/
/**Initializes a th_info structure.
* This should be called on a freshly allocated #th_info structure before
@@ -537,7 +551,7 @@ extern void th_comment_init(th_comment *_tc);
* \param _tc The #th_comment struct to add the comment to.
* \param _comment Must be a null-terminated UTF-8 string containing the
* comment in "TAG=the value" form.*/
-extern void th_comment_add(th_comment *_tc, char *_comment);
+extern void th_comment_add(th_comment *_tc,const char *_comment);
/**Add a comment to an initialized #th_comment structure.
* \note Neither th_comment_add() nor th_comment_add_tag() support
* comments containing null values, although the bitstream format does
@@ -545,10 +559,11 @@ extern void th_comment_add(th_comment *_tc, char *_comment);
* To add such comments you will need to manipulate the #th_comment
* structure directly.
* \param _tc The #th_comment struct to add the comment to.
- * \param _tag A null-terminated string containing the tag associated with
+ * \param _tag A null-terminated string containing the tag associated with
* the comment.
* \param _val The corresponding value as a null-terminated string.*/
-extern void th_comment_add_tag(th_comment *_tc,char *_tag,char *_val);
+extern void th_comment_add_tag(th_comment *_tc,const char *_tag,
+ const char *_val);
/**Look up a comment value by its tag.
* \param _tc An initialized #th_comment structure.
* \param _tag The tag to look up.
@@ -564,15 +579,15 @@ extern void th_comment_add_tag(th_comment *_tc,char *_tag,char *_val);
* It should not be modified or freed by the application, and
* modifications to the structure may invalidate the pointer.
* \retval NULL If no matching tag is found.*/
-extern char *th_comment_query(th_comment *_tc,char *_tag,int _count);
+extern char *th_comment_query(th_comment *_tc,const char *_tag,int _count);
/**Look up the number of instances of a tag.
* Call this first when querying for a specific tag and then iterate over the
* number of instances with separate calls to th_comment_query() to
* retrieve all the values for that tag in order.
* \param _tc An initialized #th_comment structure.
* \param _tag The tag to look up.
- * \return The number on instances of this particular tag.*/
-extern int th_comment_query_count(th_comment *_tc,char *_tag);
+ * \return The number of instances of this particular tag.*/
+extern int th_comment_query_count(th_comment *_tc,const char *_tag);
/**Clears a #th_comment structure.
* This should be called on a #th_comment structure after it is no longer
* needed.
diff --git a/thirdparty/libtheora/theora/theora.h b/thirdparty/libtheora/theora/theora.h
index af6eb6f380..a729a76890 100644
--- a/thirdparty/libtheora/theora/theora.h
+++ b/thirdparty/libtheora/theora/theora.h
@@ -34,41 +34,41 @@ extern "C"
*
* \section intro Introduction
*
- * This is the documentation for the libtheora legacy C API, declared in
+ * This is the documentation for the libtheora legacy C API, declared in
* the theora.h header, which describes the old interface used before
* the 1.0 release. This API was widely deployed for several years and
- * remains supported, but for new code we recommend the cleaner API
+ * remains supported, but for new code we recommend the cleaner API
* declared in theoradec.h and theoraenc.h.
*
* libtheora is the reference implementation for
* <a href="http://www.theora.org/">Theora</a>, a free video codec.
* Theora is derived from On2's VP3 codec with improved integration with
* Ogg multimedia formats by <a href="http://www.xiph.org/">Xiph.Org</a>.
- *
+ *
* \section overview Overview
*
- * This library will both decode and encode theora packets to/from raw YUV
+ * This library will both decode and encode theora packets to/from raw YUV
* frames. In either case, the packets will most likely either come from or
- * need to be embedded in an Ogg stream. Use
- * <a href="http://xiph.org/ogg/">libogg</a> or
+ * need to be embedded in an Ogg stream. Use
+ * <a href="http://xiph.org/ogg/">libogg</a> or
* <a href="http://www.annodex.net/software/liboggz/index.html">liboggz</a>
* to extract/package these packets.
*
* \section decoding Decoding Process
*
* Decoding can be separated into the following steps:
- * -# initialise theora_info and theora_comment structures using
+ * -# initialise theora_info and theora_comment structures using
* theora_info_init() and theora_comment_init():
\verbatim
theora_info info;
theora_comment comment;
-
+
theora_info_init(&info);
theora_comment_init(&comment);
\endverbatim
- * -# retrieve header packets from Ogg stream (there should be 3) and decode
- * into theora_info and theora_comment structures using
- * theora_decode_header(). See \ref identification for more information on
+ * -# retrieve header packets from Ogg stream (there should be 3) and decode
+ * into theora_info and theora_comment structures using
+ * theora_decode_header(). See \ref identification for more information on
* identifying which packets are theora packets.
\verbatim
int i;
@@ -79,14 +79,14 @@ extern "C"
}
\endverbatim
* -# initialise the decoder based on the information retrieved into the
- * theora_info struct by theora_decode_header(). You will need a
+ * theora_info struct by theora_decode_header(). You will need a
* theora_state struct.
\verbatim
theora_state state;
-
+
theora_decode_init(&state, &info);
\endverbatim
- * -# pass in packets and retrieve decoded frames! See the yuv_buffer
+ * -# pass in packets and retrieve decoded frames! See the yuv_buffer
* documentation for information on how to retrieve raw YUV data.
\verbatim
yuf_buffer buffer;
@@ -96,20 +96,20 @@ extern "C"
theora_decode_YUVout(&state, &buffer);
}
\endverbatim
- *
+ *
*
* \subsection identification Identifying Theora Packets
*
- * All streams inside an Ogg file have a unique serial_no attached to the
- * stream. Typically, you will want to
- * - retrieve the serial_no for each b_o_s (beginning of stream) page
- * encountered within the Ogg file;
- * - test the first (only) packet on that page to determine if it is a theora
+ * All streams inside an Ogg file have a unique serial_no attached to the
+ * stream. Typically, you will want to
+ * - retrieve the serial_no for each b_o_s (beginning of stream) page
+ * encountered within the Ogg file;
+ * - test the first (only) packet on that page to determine if it is a theora
* packet;
- * - once you have found a theora b_o_s page then use the retrieved serial_no
+ * - once you have found a theora b_o_s page then use the retrieved serial_no
* to identify future packets belonging to the same theora stream.
- *
- * Note that you \e cannot use theora_packet_isheader() to determine if a
+ *
+ * Note that you \e cannot use theora_packet_isheader() to determine if a
* packet is a theora packet or not, as this function does not perform any
* checking beyond whether a header bit is present. Instead, use the
* theora_decode_header() function and check the return value; or examine the
@@ -124,9 +124,9 @@ extern "C"
* A YUV buffer for passing uncompressed frames to and from the codec.
* This holds a Y'CbCr frame in planar format. The CbCr planes can be
* subsampled and have their own separate dimensions and row stride
- * offsets. Note that the strides may be negative in some
+ * offsets. Note that the strides may be negative in some
* configurations. For theora the width and height of the largest plane
- * must be a multiple of 16. The actual meaningful picture size and
+ * must be a multiple of 16. The actual meaningful picture size and
* offset are stored in the theora_info structure; frames returned by
* the decoder may need to be cropped for display.
*
@@ -135,8 +135,8 @@ extern "C"
* are ordered from left to right.
*
* During decode, the yuv_buffer struct is allocated by the user, but all
- * fields (including luma and chroma pointers) are filled by the library.
- * These pointers address library-internal memory and their contents should
+ * fields (including luma and chroma pointers) are filled by the library.
+ * These pointers address library-internal memory and their contents should
* not be modified.
*
* Conversely, during encode the user allocates the struct and fills out all
@@ -179,14 +179,14 @@ typedef enum {
OC_PF_420, /**< Chroma subsampling by 2 in each direction (4:2:0) */
OC_PF_RSVD, /**< Reserved value */
OC_PF_422, /**< Horizonatal chroma subsampling by 2 (4:2:2) */
- OC_PF_444, /**< No chroma subsampling at all (4:4:4) */
+ OC_PF_444 /**< No chroma subsampling at all (4:4:4) */
} theora_pixelformat;
/**
* Theora bitstream info.
* Contains the basic playback parameters for a stream,
* corresponding to the initial 'info' header packet.
- *
+ *
* Encoded theora frames must be a multiple of 16 in width and height.
* To handle other frame sizes, a crop rectangle is specified in
* frame_height and frame_width, offset_x and * offset_y. The offset
@@ -198,10 +198,10 @@ typedef enum {
* fraction. Aspect ratio is also stored as a rational fraction, and
* refers to the aspect ratio of the frame pixels, not of the
* overall frame itself.
- *
+ *
* See <a href="http://svn.xiph.org/trunk/theora/examples/encoder_example.c">
* examples/encoder_example.c</a> for usage examples of the
- * other paramters and good default settings for the encoder parameters.
+ * other parameters and good default settings for the encoder parameters.
*/
typedef struct {
ogg_uint32_t width; /**< encoded frame width */
@@ -253,14 +253,14 @@ typedef struct{
} theora_state;
-/**
+/**
* Comment header metadata.
*
* This structure holds the in-stream metadata corresponding to
* the 'comment' header packet.
*
* Meta data is stored as a series of (tag, value) pairs, in
- * length-encoded string vectors. The first occurence of the
+ * length-encoded string vectors. The first occurence of the
* '=' character delimits the tag and value. A particular tag
* may occur more than once. The character set encoding for
* the strings is always UTF-8, but the tag names are limited
@@ -285,7 +285,7 @@ typedef struct theora_comment{
/* \anchor decctlcodes_old
* These are the available request codes for theora_control()
* when called with a decoder instance.
- * By convention decoder control codes are odd, to distinguish
+ * By convention decoder control codes are odd, to distinguish
* them from \ref encctlcodes_old "encoder control codes" which
* are even.
*
@@ -306,7 +306,7 @@ typedef struct theora_comment{
#define TH_DECCTL_GET_PPLEVEL_MAX (1)
/**Set the post-processing level.
- * Sets the level of post-processing to use when decoding the
+ * Sets the level of post-processing to use when decoding the
* compressed stream. This must be a value between zero (off)
* and the maximum returned by TH_DECCTL_GET_PPLEVEL_MAX.
*/
@@ -345,9 +345,9 @@ typedef struct theora_comment{
* \param[in] buf #th_quant_info
* \retval OC_FAULT \a theora_state is <tt>NULL</tt>.
* \retval OC_EINVAL Encoding has already begun, the quantization parameters
- * are not acceptable to this version of the encoder,
- * \a buf is <tt>NULL</tt> and \a buf_sz is not zero,
- * or \a buf is non-<tt>NULL</tt> and \a buf_sz is
+ * are not acceptable to this version of the encoder,
+ * \a buf is <tt>NULL</tt> and \a buf_sz is not zero,
+ * or \a buf is non-<tt>NULL</tt> and \a buf_sz is
* not <tt>sizeof(#th_quant_info)</tt>.
* \retval OC_IMPL Not supported by this implementation.*/
#define TH_ENCCTL_SET_QUANT_PARAMS (2)
@@ -424,7 +424,7 @@ typedef struct theora_comment{
#define OC_NEWPACKET -25 /**< Packet is an (ignorable) unhandled extension */
#define OC_DUPFRAME 1 /**< Packet is a dropped frame */
-/**
+/**
* Retrieve a human-readable string to identify the encoder vendor and version.
* \returns A version string.
*/
@@ -462,7 +462,7 @@ extern int theora_encode_init(theora_state *th, theora_info *ti);
extern int theora_encode_YUVin(theora_state *t, yuv_buffer *yuv);
/**
- * Request the next packet of encoded video.
+ * Request the next packet of encoded video.
* The encoded data is placed in a user-provided ogg_packet structure.
* \param t A theora_state handle previously initialized for encoding.
* \param last_p whether this is the last packet the encoder should produce.
@@ -496,7 +496,11 @@ extern int theora_encode_header(theora_state *t, ogg_packet *op);
* \param op An ogg_packet structure to fill. libtheora will set all
* elements of this structure, including a pointer to the encoded
* comment data. The memory for the comment data is owned by
- * libtheora.
+ * the application, and must be freed by it using _ogg_free().
+ * On some systems (such as Windows when using dynamic linking), this
+ * may mean the free is executed in a different module from the
+ * malloc, which will crash; there is no way to free this memory on
+ * such systems.
* \retval 0 Success
*/
extern int theora_encode_comment(theora_comment *tc, ogg_packet *op);
@@ -581,8 +585,8 @@ extern int theora_decode_packetin(theora_state *th,ogg_packet *op);
* \param th A theora_state handle previously initialized for decoding.
* \param yuv A yuv_buffer in which libtheora should place the decoded data.
* Note that the buffer struct itself is allocated by the user, but
- * that the luma and chroma pointers will be filled in by the
- * library. Also note that these luma and chroma regions should be
+ * that the luma and chroma pointers will be filled in by the
+ * library. Also note that these luma and chroma regions should be
* considered read-only by the user.
* \retval 0 Success
*/
@@ -617,22 +621,22 @@ extern int theora_packet_iskeyframe(ogg_packet *op);
/**
* Report the granulepos shift radix
*
- * When embedded in Ogg, Theora uses a two-part granulepos,
+ * When embedded in Ogg, Theora uses a two-part granulepos,
* splitting the 64-bit field into two pieces. The more-significant
* section represents the frame count at the last keyframe,
* and the less-significant section represents the count of
* frames since the last keyframe. In this way the overall
* field is still non-decreasing with time, but usefully encodes
* a pointer to the last keyframe, which is necessary for
- * correctly restarting decode after a seek.
+ * correctly restarting decode after a seek.
*
* This function reports the number of bits used to represent
* the distance to the last keyframe, and thus how the granulepos
* field must be shifted or masked to obtain the two parts.
- *
+ *
* Since libtheora returns compressed data in an ogg_packet
* structure, this may be generally useful even if the Theora
- * packets are not being used in an Ogg container.
+ * packets are not being used in an Ogg container.
*
* \param ti A previously initialized theora_info struct
* \returns The bit shift dividing the two granulepos fields
@@ -644,7 +648,7 @@ int theora_granule_shift(theora_info *ti);
/**
* Convert a granulepos to an absolute frame index, starting at 0.
* The granulepos is interpreted in the context of a given theora_state handle.
- *
+ *
* Note that while the granulepos encodes the frame count (i.e. starting
* from 1) this call returns the frame index, starting from zero. Thus
* One can calculate the presentation time by multiplying the index by
@@ -670,9 +674,7 @@ extern ogg_int64_t theora_granule_frame(theora_state *th,ogg_int64_t granulepos)
* This is the "end time" for the frame, or the latest time it should
* be displayed.
* It is not the presentation time.
- * \retval -1. The given granulepos is undefined (i.e. negative), or
- * \retval -1. The function has been disabled because floating
- * point support is not available.
+ * \retval -1. The given granulepos is undefined (i.e. negative).
*/
extern double theora_granule_time(theora_state *th,ogg_int64_t granulepos);
@@ -699,7 +701,7 @@ extern void theora_clear(theora_state *t);
/**
* Initialize an allocated theora_comment structure
- * \param tc An allocated theora_comment structure
+ * \param tc An allocated theora_comment structure
**/
extern void theora_comment_init(theora_comment *tc);
@@ -720,7 +722,7 @@ extern void theora_comment_add(theora_comment *tc, char *comment);
/**
* Add a comment to an initialized theora_comment structure.
* \param tc A previously initialized theora comment structure
- * \param tag A null-terminated string containing the tag
+ * \param tag A null-terminated string containing the tag
* associated with the comment.
* \param value The corresponding value as a null-terminated string
*
@@ -752,9 +754,9 @@ extern char *theora_comment_query(theora_comment *tc, char *tag, int count);
* \param tc An initialized theora_comment structure
* \param tag The tag to look up
* \returns The number on instances of a particular tag.
- *
+ *
* Call this first when querying for a specific tag and then interate
- * over the number of instances with separate calls to
+ * over the number of instances with separate calls to
* theora_comment_query() to retrieve all instances in order.
**/
extern int theora_comment_query_count(theora_comment *tc, char *tag);
@@ -769,7 +771,7 @@ extern void theora_comment_clear(theora_comment *tc);
* This is used to provide advanced control the encoding process.
* \param th A #theora_state handle.
* \param req The control code to process.
- * See \ref encctlcodes_old "the list of available
+ * See \ref encctlcodes_old "the list of available
* control codes" for details.
* \param buf The parameters for this control code.
* \param buf_sz The size of the parameter buffer.*/
diff --git a/thirdparty/libtheora/theora/theoradec.h b/thirdparty/libtheora/theora/theoradec.h
index b20f0e3a64..77bef81909 100644
--- a/thirdparty/libtheora/theora/theoradec.h
+++ b/thirdparty/libtheora/theora/theoradec.h
@@ -92,13 +92,17 @@ extern "C" {
* <tt>sizeof(th_stripe_callback)</tt>.*/
#define TH_DECCTL_SET_STRIPE_CB (7)
-/**Enables telemetry and sets the macroblock display mode */
+/**Sets the macroblock display mode. Set to 0 to disable displaying
+ * macroblocks.*/
#define TH_DECCTL_SET_TELEMETRY_MBMODE (9)
-/**Enables telemetry and sets the motion vector display mode */
+/**Sets the motion vector display mode. Set to 0 to disable displaying motion
+ * vectors.*/
#define TH_DECCTL_SET_TELEMETRY_MV (11)
-/**Enables telemetry and sets the adaptive quantization display mode */
+/**Sets the adaptive quantization display mode. Set to 0 to disable displaying
+ * adaptive quantization. */
#define TH_DECCTL_SET_TELEMETRY_QI (13)
-/**Enables telemetry and sets the bitstream breakdown visualization mode */
+/**Sets the bitstream breakdown visualization mode. Set to 0 to disable
+ * displaying bitstream breakdown.*/
#define TH_DECCTL_SET_TELEMETRY_BITS (15)
/*@}*/
@@ -171,7 +175,7 @@ typedef struct th_setup_info th_setup_info;
/**\defgroup decfuncs Functions for Decoding*/
/*@{*/
/**\name Functions for decoding
- * You must link to <tt>libtheoradec</tt> if you use any of the
+ * You must link to <tt>libtheoradec</tt> if you use any of the
* functions in this section.
*
* The functions are listed in the order they are used in a typical decode.
@@ -267,7 +271,10 @@ extern void th_setup_free(th_setup_info *_setup);
* See \ref decctlcodes "the list of available control codes"
* for details.
* \param _buf The parameters for this control code.
- * \param _buf_sz The size of the parameter buffer.*/
+ * \param _buf_sz The size of the parameter buffer.
+ * \return Possible return values depend on the control code used.
+ * See \ref decctlcodes "the list of control codes" for
+ * specific values. Generally 0 indicates success.*/
extern int th_decode_ctl(th_dec_ctx *_dec,int _req,void *_buf,
size_t _buf_sz);
/**Submits a packet containing encoded video data to the decoder.
@@ -283,7 +290,8 @@ extern int th_decode_ctl(th_dec_ctx *_dec,int _req,void *_buf,
* \retval 0 Success.
* A new decoded frame can be retrieved by calling
* th_decode_ycbcr_out().
- * \retval TH_DUPFRAME The packet represented a dropped (0-byte) frame.
+ * \retval TH_DUPFRAME The packet represented a dropped frame (either a
+ * 0-byte frame or an INTER frame with no coded blocks).
* The player can skip the call to th_decode_ycbcr_out(),
* as the contents of the decoded frame buffer have not
* changed.
diff --git a/thirdparty/libtheora/theora/theoraenc.h b/thirdparty/libtheora/theora/theoraenc.h
index fdf2ab21e2..79b1c2b880 100644
--- a/thirdparty/libtheora/theora/theoraenc.h
+++ b/thirdparty/libtheora/theora/theoraenc.h
@@ -43,7 +43,7 @@ extern "C" {
* <tt>NULL</tt> may be specified to revert to the default tables.
*
* \param[in] _buf <tt>#th_huff_code[#TH_NHUFFMAN_TABLES][#TH_NDCT_TOKENS]</tt>
- * \retval TH_EFAULT \a _enc_ctx is <tt>NULL</tt>.
+ * \retval TH_EFAULT \a _enc is <tt>NULL</tt>.
* \retval TH_EINVAL Encoding has already begun or one or more of the given
* tables is not full or prefix-free, \a _buf is
* <tt>NULL</tt> and \a _buf_sz is not zero, or \a _buf is
@@ -57,8 +57,8 @@ extern "C" {
* <tt>NULL</tt> may be specified to revert to the default parameters.
*
* \param[in] _buf #th_quant_info
- * \retval TH_EFAULT \a _enc_ctx is <tt>NULL</tt>.
- * \retval TH_EINVAL Encoding has already begun, \a _buf is
+ * \retval TH_EFAULT \a _enc is <tt>NULL</tt>.
+ * \retval TH_EINVAL Encoding has already begun, \a _buf is
* <tt>NULL</tt> and \a _buf_sz is not zero,
* or \a _buf is non-<tt>NULL</tt> and
* \a _buf_sz is not <tt>sizeof(#th_quant_info)</tt>.
@@ -73,7 +73,7 @@ extern "C" {
* \param[in] _buf <tt>ogg_uint32_t</tt>: The maximum distance between key
* frames.
* \param[out] _buf <tt>ogg_uint32_t</tt>: The actual maximum distance set.
- * \retval TH_EFAULT \a _enc_ctx or \a _buf is <tt>NULL</tt>.
+ * \retval TH_EFAULT \a _enc or \a _buf is <tt>NULL</tt>.
* \retval TH_EINVAL \a _buf_sz is not <tt>sizeof(ogg_uint32_t)</tt>.
* \retval TH_EIMPL Not supported by this implementation.*/
#define TH_ENCCTL_SET_KEYFRAME_FREQUENCY_FORCE (4)
@@ -101,7 +101,7 @@ extern "C" {
* 4:2:0, the picture region is smaller than the full frame,
* or if encoding has begun, preventing the quantization
* tables and codebooks from being set.
- * \retval TH_EFAULT \a _enc_ctx or \a _buf is <tt>NULL</tt>.
+ * \retval TH_EFAULT \a _enc or \a _buf is <tt>NULL</tt>.
* \retval TH_EINVAL \a _buf_sz is not <tt>sizeof(int)</tt>.
* \retval TH_EIMPL Not supported by this implementation.*/
#define TH_ENCCTL_SET_VP3_COMPATIBLE (10)
@@ -114,7 +114,7 @@ extern "C" {
* the current encoding mode (VBR vs. constant quality, etc.).
*
* \param[out] _buf <tt>int</tt>: The maximum encoding speed level.
- * \retval TH_EFAULT \a _enc_ctx or \a _buf is <tt>NULL</tt>.
+ * \retval TH_EFAULT \a _enc or \a _buf is <tt>NULL</tt>.
* \retval TH_EINVAL \a _buf_sz is not <tt>sizeof(int)</tt>.
* \retval TH_EIMPL Not supported by this implementation in the current
* encoding mode.*/
@@ -124,7 +124,7 @@ extern "C" {
*
* \param[in] _buf <tt>int</tt>: The new encoding speed level.
* 0 is slowest, larger values use less CPU.
- * \retval TH_EFAULT \a _enc_ctx or \a _buf is <tt>NULL</tt>.
+ * \retval TH_EFAULT \a _enc or \a _buf is <tt>NULL</tt>.
* \retval TH_EINVAL \a _buf_sz is not <tt>sizeof(int)</tt>, or the
* encoding speed level is out of bounds.
* The maximum encoding speed level may be
@@ -142,7 +142,7 @@ extern "C" {
*
* \param[out] _buf <tt>int</tt>: The current encoding speed level.
* 0 is slowest, larger values use less CPU.
- * \retval TH_EFAULT \a _enc_ctx or \a _buf is <tt>NULL</tt>.
+ * \retval TH_EFAULT \a _enc or \a _buf is <tt>NULL</tt>.
* \retval TH_EINVAL \a _buf_sz is not <tt>sizeof(int)</tt>.
* \retval TH_EIMPL Not supported by this implementation in the current
* encoding mode.*/
@@ -162,7 +162,7 @@ extern "C" {
*
* \param[in] _buf <tt>int</tt>: The number of duplicates to produce.
* If this is negative or zero, no duplicates will be produced.
- * \retval TH_EFAULT \a _enc_ctx or \a _buf is <tt>NULL</tt>.
+ * \retval TH_EFAULT \a _enc or \a _buf is <tt>NULL</tt>.
* \retval TH_EINVAL \a _buf_sz is not <tt>sizeof(int)</tt>, or the
* number of duplicates is greater than or equal to the
* maximum keyframe interval.
@@ -187,7 +187,7 @@ extern "C" {
* use.
* - #TH_RATECTL_CAP_UNDERFLOW: Don't try to make up shortfalls
* later.
- * \retval TH_EFAULT \a _enc_ctx or \a _buf is <tt>NULL</tt>.
+ * \retval TH_EFAULT \a _enc or \a _buf is <tt>NULL</tt>.
* \retval TH_EINVAL \a _buf_sz is not <tt>sizeof(int)</tt> or rate control
* is not enabled.
* \retval TH_EIMPL Not supported by this implementation in the current
@@ -211,7 +211,7 @@ extern "C" {
* \param[in] _buf <tt>int</tt>: Requested size of the reservoir measured in
* frames.
* \param[out] _buf <tt>int</tt>: The actual size of the reservoir set.
- * \retval TH_EFAULT \a _enc_ctx or \a _buf is <tt>NULL</tt>.
+ * \retval TH_EFAULT \a _enc or \a _buf is <tt>NULL</tt>.
* \retval TH_EINVAL \a _buf_sz is not <tt>sizeof(int)</tt>, or rate control
* is not enabled. The buffer has an implementation
* defined minimum and maximum size and the value in _buf
@@ -243,7 +243,7 @@ extern "C" {
* application.
* \retval >=0 The number of bytes of metric data available in the
* returned buffer.
- * \retval TH_EFAULT \a _enc_ctx or \a _buf is <tt>NULL</tt>.
+ * \retval TH_EFAULT \a _enc or \a _buf is <tt>NULL</tt>.
* \retval TH_EINVAL \a _buf_sz is not <tt>sizeof(char *)</tt>, no target
* bitrate has been set, or the first call was made after
* the first frame was submitted for encoding.
@@ -283,7 +283,7 @@ extern "C" {
* of bytes consumed.
* \retval >0 The number of bytes of metric data required/consumed.
* \retval 0 No more data is required before the next frame.
- * \retval TH_EFAULT \a _enc_ctx is <tt>NULL</tt>.
+ * \retval TH_EFAULT \a _enc is <tt>NULL</tt>.
* \retval TH_EINVAL No target bitrate has been set, or the first call was
* made after the first frame was submitted for
* encoding.
@@ -306,7 +306,7 @@ extern "C" {
* \param[in] _buf <tt>int</tt>: The new target quality, in the range 0...63,
* inclusive.
* \retval 0 Success.
- * \retval TH_EFAULT \a _enc_ctx or \a _buf is <tt>NULL</tt>.
+ * \retval TH_EFAULT \a _enc or \a _buf is <tt>NULL</tt>.
* \retval TH_EINVAL A target bitrate has already been specified, or the
* quality index was not in the range 0...63.
* \retval TH_EIMPL Not supported by this implementation.*/
@@ -328,10 +328,54 @@ extern "C" {
*
* \param[in] _buf <tt>long</tt>: The new target bitrate, in bits per second.
* \retval 0 Success.
- * \retval TH_EFAULT \a _enc_ctx or \a _buf is <tt>NULL</tt>.
+ * \retval TH_EFAULT \a _enc or \a _buf is <tt>NULL</tt>.
* \retval TH_EINVAL The target bitrate was not positive.
- * \retval TH_EIMPL Not supported by this implementation.*/
+ * A future version of this library may allow passing 0
+ * to disabled rate-controlled mode and return to a
+ * quality-based mode, in which case this function will
+ * not return an error for that value.
+ * \retval TH_EIMPL Not supported by this implementation.*/
#define TH_ENCCTL_SET_BITRATE (30)
+/**Sets the configuration to be compatible with that from the given setup
+ * header.
+ * This sets the Huffman codebooks and quantization parameters to match those
+ * found in the given setup header.
+ * This guarantees that packets encoded by this encoder will be decodable using
+ * a decoder configured with the passed-in setup header.
+ * It does <em>not</em> guarantee that th_encode_flushheader() will produce a
+ * bit-identical setup header, only that they will be compatible.
+ * If you need a bit-identical setup header, then use the one you passed into
+ * this command, and not the one returned by th_encode_flushheader().
+ *
+ * This also does <em>not</em> enable or disable VP3 compatibility; that is not
+ * signaled in the setup header (or anywhere else in the encoded stream), and
+ * is controlled independently by the #TH_ENCCTL_SET_VP3_COMPATIBLE function.
+ * If you wish to enable VP3 compatibility mode <em>and</em> want the codebooks
+ * and quantization parameters to match the given setup header, you should
+ * enable VP3 compatibility before invoking this command, otherwise the
+ * codebooks and quantization parameters will be reset to the VP3 defaults.
+ *
+ * The current encoder does not support Huffman codebooks which do not contain
+ * codewords for all 32 tokens.
+ * Such codebooks are legal, according to the specification, but cannot be
+ * configured with this function.
+ *
+ * \param[in] _buf <tt>unsigned char[]</tt>: The encoded setup header to copy
+ * the configuration from.
+ * This should be the original,
+ * undecoded setup header packet,
+ * and <em>not</em> a #th_setup_info
+ * structure filled in by
+ * th_decode_headerin().
+ * \retval TH_EFAULT \a _enc or \a _buf is <tt>NULL</tt>.
+ * \retval TH_EINVAL Encoding has already begun, so the codebooks and
+ * quantization parameters cannot be changed, or the
+ * data in the setup header was not supported by this
+ * encoder.
+ * \retval TH_EBADHEADER \a _buf did not contain a valid setup header packet.
+ * \retval TH_ENOTFORMAT \a _buf did not contain a Theora header at all.
+ * \retval TH_EIMPL Not supported by this implementation.*/
+#define TH_ENCCTL_SET_COMPAT_CONFIG (32)
/*@}*/
@@ -342,7 +386,8 @@ extern "C" {
/*@{*/
/**Drop frames to keep within bitrate buffer constraints.
* This can have a severe impact on quality, but is the only way to ensure that
- * bitrate targets are met at low rates during sudden bursts of activity.*/
+ * bitrate targets are met at low rates during sudden bursts of activity.
+ * It is enabled by default.*/
#define TH_RATECTL_DROP_FRAMES (0x1)
/**Ignore bitrate buffer overflows.
* If the encoder uses so few bits that the reservoir of available bits
@@ -350,14 +395,14 @@ extern "C" {
* The encoder will not try to use these extra bits in future frames.
* At high rates this may cause the result to be undersized, but allows a
* client to play the stream using a finite buffer; it should normally be
- * enabled.*/
+ * enabled, which is the default.*/
#define TH_RATECTL_CAP_OVERFLOW (0x2)
/**Ignore bitrate buffer underflows.
* If the encoder uses so many bits that the reservoir of available bits
* underflows, ignore the deficit.
* The encoder will not try to make up these extra bits in future frames.
* At low rates this may cause the result to be oversized; it should normally
- * be disabled.*/
+ * be disabled, which is the default.*/
#define TH_RATECTL_CAP_UNDERFLOW (0x4)
/*@}*/
@@ -401,8 +446,8 @@ typedef struct th_enc_ctx th_enc_ctx;
* packets.
* - For each uncompressed frame:
* - Submit the uncompressed frame via th_encode_ycbcr_in()
- * - Repeatedly call th_encode_packetout() to retrieve any video data packets
- * that are ready.
+ * - Repeatedly call th_encode_packetout() to retrieve any video
+ * data packets that are ready.
* - Call th_encode_free() to release all encoder memory.*/
/*@{*/
/**Allocates an encoder instance.
@@ -417,7 +462,10 @@ extern th_enc_ctx *th_encode_alloc(const th_info *_info);
* See \ref encctlcodes "the list of available control codes"
* for details.
* \param _buf The parameters for this control code.
- * \param _buf_sz The size of the parameter buffer.*/
+ * \param _buf_sz The size of the parameter buffer.
+ * \return Possible return values depend on the control code used.
+ * See \ref encctlcodes "the list of control codes" for
+ * specific values. Generally 0 indicates success.*/
extern int th_encode_ctl(th_enc_ctx *_enc,int _req,void *_buf,size_t _buf_sz);
/**Outputs the next header packet.
* This should be called repeatedly after encoder initialization until it
@@ -441,11 +489,25 @@ extern int th_encode_flushheader(th_enc_ctx *_enc,
/**Submits an uncompressed frame to the encoder.
* \param _enc A #th_enc_ctx handle.
* \param _ycbcr A buffer of Y'CbCr data to encode.
+ * If the width and height of the buffer matches the frame size
+ * the encoder was initialized with, the encoder will only
+ * reference the portion inside the picture region.
+ * Any data outside this region will be ignored, and need not map
+ * to a valid address.
+ * Alternatively, you can pass a buffer equal to the size of the
+ * picture region, if this is less than the full frame size.
+ * When using subsampled chroma planes, odd picture sizes or odd
+ * picture offsets may require an unexpected chroma plane size,
+ * and their use is generally discouraged, as they will not be
+ * well-supported by players and other media frameworks.
+ * See Section 4.4 of
+ * <a href="http://www.theora.org/doc/Theora.pdf">the Theora
+ * specification</a> for details if you wish to use them anyway.
* \retval 0 Success.
* \retval TH_EFAULT \a _enc or \a _ycbcr is <tt>NULL</tt>.
- * \retval TH_EINVAL The buffer size does not match the frame size the encoder
- * was initialized with, or encoding has already
- * completed.*/
+ * \retval TH_EINVAL The buffer size matches neither the frame size nor the
+ * picture size the encoder was initialized with, or
+ * encoding has already completed.*/
extern int th_encode_ycbcr_in(th_enc_ctx *_enc,th_ycbcr_buffer _ycbcr);
/**Retrieves encoded video data packets.
* This should be called repeatedly after each frame is submitted to flush any
diff --git a/thirdparty/libtheora/tokenize.c b/thirdparty/libtheora/tokenize.c
index 60574c3594..57b7aa8da9 100644
--- a/thirdparty/libtheora/tokenize.c
+++ b/thirdparty/libtheora/tokenize.c
@@ -11,7 +11,7 @@
********************************************************************
function:
- last mod: $Id: tokenize.c 16503 2009-08-22 18:14:02Z giles $
+ last mod: $Id$
********************************************************************/
#include <stdlib.h>
@@ -20,27 +20,26 @@
+static unsigned char OC_DCT_EOB_TOKEN[31]={
+ 0,1,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5
+};
+
static int oc_make_eob_token(int _run_count){
- if(_run_count<4)return OC_DCT_EOB1_TOKEN+_run_count-1;
- else{
- int cat;
- cat=OC_ILOGNZ_32(_run_count)-3;
- cat=OC_MINI(cat,3);
- return OC_DCT_REPEAT_RUN0_TOKEN+cat;
- }
+ return _run_count<32?OC_DCT_EOB_TOKEN[_run_count-1]:OC_DCT_REPEAT_RUN3_TOKEN;
}
+static unsigned char OC_DCT_EOB_EB[31]={
+ 0,0,0,0,1,2,3,0,1,2,3,4,5,6,7,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
+};
+
static int oc_make_eob_token_full(int _run_count,int *_eb){
- if(_run_count<4){
- *_eb=0;
- return OC_DCT_EOB1_TOKEN+_run_count-1;
+ if(_run_count<32){
+ *_eb=OC_DCT_EOB_EB[_run_count-1];
+ return OC_DCT_EOB_TOKEN[_run_count-1];
}
else{
- int cat;
- cat=OC_ILOGNZ_32(_run_count)-3;
- cat=OC_MINI(cat,3);
- *_eb=_run_count-OC_BYTE_TABLE32(4,8,16,0,cat);
- return OC_DCT_REPEAT_RUN0_TOKEN+cat;
+ *_eb=_run_count;
+ return OC_DCT_REPEAT_RUN3_TOKEN;
}
}
@@ -49,86 +48,330 @@ static int oc_decode_eob_token(int _token,int _eb){
return (0x20820C41U>>_token*5&0x1F)+_eb;
}
-/*TODO: This is now only used during DCT tokenization, and never for runs; it
- should be simplified.*/
-static int oc_make_dct_token_full(int _zzi,int _zzj,int _val,int *_eb){
- int neg;
- int zero_run;
- int token;
- int eb;
- neg=_val<0;
- _val=abs(_val);
- zero_run=_zzj-_zzi;
- if(zero_run>0){
- int adj;
- /*Implement a minor restriction on stack 1 so that we know during DC fixups
- that extending a dctrun token from stack 1 will never overflow.*/
- adj=_zzi!=1;
- if(_val<2&&zero_run<17+adj){
- if(zero_run<6){
- token=OC_DCT_RUN_CAT1A+zero_run-1;
- eb=neg;
- }
- else if(zero_run<10){
- token=OC_DCT_RUN_CAT1B;
- eb=zero_run-6+(neg<<2);
- }
- else{
- token=OC_DCT_RUN_CAT1C;
- eb=zero_run-10+(neg<<3);
- }
- }
- else if(_val<4&&zero_run<3+adj){
- if(zero_run<2){
- token=OC_DCT_RUN_CAT2A;
- eb=_val-2+(neg<<1);
- }
- else{
- token=OC_DCT_RUN_CAT2B;
- eb=zero_run-2+(_val-2<<1)+(neg<<2);
- }
- }
- else{
- if(zero_run<9)token=OC_DCT_SHORT_ZRL_TOKEN;
- else token=OC_DCT_ZRL_TOKEN;
- eb=zero_run-1;
- }
- }
- else if(_val<3){
- token=OC_ONE_TOKEN+(_val-1<<1)+neg;
- eb=0;
- }
- else if(_val<7){
- token=OC_DCT_VAL_CAT2+_val-3;
- eb=neg;
- }
- else if(_val<9){
- token=OC_DCT_VAL_CAT3;
- eb=_val-7+(neg<<1);
- }
- else if(_val<13){
- token=OC_DCT_VAL_CAT4;
- eb=_val-9+(neg<<2);
- }
- else if(_val<21){
- token=OC_DCT_VAL_CAT5;
- eb=_val-13+(neg<<3);
- }
- else if(_val<37){
- token=OC_DCT_VAL_CAT6;
- eb=_val-21+(neg<<4);
- }
- else if(_val<69){
- token=OC_DCT_VAL_CAT7;
- eb=_val-37+(neg<<5);
- }
- else{
- token=OC_DCT_VAL_CAT8;
- eb=_val-69+(neg<<9);
- }
- *_eb=eb;
- return token;
-}
+/*Some tables for fast construction of value tokens.*/
+
+static const unsigned char OC_DCT_VALUE_TOKEN[1161]={
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,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,21,21,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
+ 19,19,19,19,19,19,19,19,18,18,18,18,17,17,16,15,14,13,12,10,
+ 7,
+ 9,11,13,14,15,16,17,17,18,18,18,18,19,19,19,19,19,19,19,19,
+ 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,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,21,21,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22
+};
+
+static const ogg_uint16_t OC_DCT_VALUE_EB[1161]={
+ 1023,1022,1021,1020,1019,1018,1017,1016,1015,1014,
+ 1013,1012,1011,1010,1009,1008,1007,1006,1005,1004,
+ 1003,1002,1001,1000, 999, 998, 997, 996, 995, 994,
+ 993, 992, 991, 990, 989, 988, 987, 986, 985, 984,
+ 983, 982, 981, 980, 979, 978, 977, 976, 975, 974,
+ 973, 972, 971, 970, 969, 968, 967, 966, 965, 964,
+ 963, 962, 961, 960, 959, 958, 957, 956, 955, 954,
+ 953, 952, 951, 950, 949, 948, 947, 946, 945, 944,
+ 943, 942, 941, 940, 939, 938, 937, 936, 935, 934,
+ 933, 932, 931, 930, 929, 928, 927, 926, 925, 924,
+ 923, 922, 921, 920, 919, 918, 917, 916, 915, 914,
+ 913, 912, 911, 910, 909, 908, 907, 906, 905, 904,
+ 903, 902, 901, 900, 899, 898, 897, 896, 895, 894,
+ 893, 892, 891, 890, 889, 888, 887, 886, 885, 884,
+ 883, 882, 881, 880, 879, 878, 877, 876, 875, 874,
+ 873, 872, 871, 870, 869, 868, 867, 866, 865, 864,
+ 863, 862, 861, 860, 859, 858, 857, 856, 855, 854,
+ 853, 852, 851, 850, 849, 848, 847, 846, 845, 844,
+ 843, 842, 841, 840, 839, 838, 837, 836, 835, 834,
+ 833, 832, 831, 830, 829, 828, 827, 826, 825, 824,
+ 823, 822, 821, 820, 819, 818, 817, 816, 815, 814,
+ 813, 812, 811, 810, 809, 808, 807, 806, 805, 804,
+ 803, 802, 801, 800, 799, 798, 797, 796, 795, 794,
+ 793, 792, 791, 790, 789, 788, 787, 786, 785, 784,
+ 783, 782, 781, 780, 779, 778, 777, 776, 775, 774,
+ 773, 772, 771, 770, 769, 768, 767, 766, 765, 764,
+ 763, 762, 761, 760, 759, 758, 757, 756, 755, 754,
+ 753, 752, 751, 750, 749, 748, 747, 746, 745, 744,
+ 743, 742, 741, 740, 739, 738, 737, 736, 735, 734,
+ 733, 732, 731, 730, 729, 728, 727, 726, 725, 724,
+ 723, 722, 721, 720, 719, 718, 717, 716, 715, 714,
+ 713, 712, 711, 710, 709, 708, 707, 706, 705, 704,
+ 703, 702, 701, 700, 699, 698, 697, 696, 695, 694,
+ 693, 692, 691, 690, 689, 688, 687, 686, 685, 684,
+ 683, 682, 681, 680, 679, 678, 677, 676, 675, 674,
+ 673, 672, 671, 670, 669, 668, 667, 666, 665, 664,
+ 663, 662, 661, 660, 659, 658, 657, 656, 655, 654,
+ 653, 652, 651, 650, 649, 648, 647, 646, 645, 644,
+ 643, 642, 641, 640, 639, 638, 637, 636, 635, 634,
+ 633, 632, 631, 630, 629, 628, 627, 626, 625, 624,
+ 623, 622, 621, 620, 619, 618, 617, 616, 615, 614,
+ 613, 612, 611, 610, 609, 608, 607, 606, 605, 604,
+ 603, 602, 601, 600, 599, 598, 597, 596, 595, 594,
+ 593, 592, 591, 590, 589, 588, 587, 586, 585, 584,
+ 583, 582, 581, 580, 579, 578, 577, 576, 575, 574,
+ 573, 572, 571, 570, 569, 568, 567, 566, 565, 564,
+ 563, 562, 561, 560, 559, 558, 557, 556, 555, 554,
+ 553, 552, 551, 550, 549, 548, 547, 546, 545, 544,
+ 543, 542, 541, 540, 539, 538, 537, 536, 535, 534,
+ 533, 532, 531, 530, 529, 528, 527, 526, 525, 524,
+ 523, 522, 521, 520, 519, 518, 517, 516, 515, 514,
+ 513, 512, 63, 62, 61, 60, 59, 58, 57, 56,
+ 55, 54, 53, 52, 51, 50, 49, 48, 47, 46,
+ 45, 44, 43, 42, 41, 40, 39, 38, 37, 36,
+ 35, 34, 33, 32, 31, 30, 29, 28, 27, 26,
+ 25, 24, 23, 22, 21, 20, 19, 18, 17, 16,
+ 15, 14, 13, 12, 11, 10, 9, 8, 7, 6,
+ 5, 4, 3, 2, 1, 1, 1, 1, 0, 0,
+ 0,
+ 0, 0, 0, 0, 0, 0, 0, 1, 0, 1,
+ 2, 3, 0, 1, 2, 3, 4, 5, 6, 7,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 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, 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, 35, 36, 37, 38, 39, 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, 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, 110, 111,
+ 112, 113, 114, 115, 116, 117, 118, 119, 120, 121,
+ 122, 123, 124, 125, 126, 127, 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, 158, 159, 160, 161,
+ 162, 163, 164, 165, 166, 167, 168, 169, 170, 171,
+ 172, 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, 207, 208, 209, 210, 211,
+ 212, 213, 214, 215, 216, 217, 218, 219, 220, 221,
+ 222, 223, 224, 225, 226, 227, 228, 229, 230, 231,
+ 232, 233, 234, 235, 236, 237, 238, 239, 240, 241,
+ 242, 243, 244, 245, 246, 247, 248, 249, 250, 251,
+ 252, 253, 254, 255, 256, 257, 258, 259, 260, 261,
+ 262, 263, 264, 265, 266, 267, 268, 269, 270, 271,
+ 272, 273, 274, 275, 276, 277, 278, 279, 280, 281,
+ 282, 283, 284, 285, 286, 287, 288, 289, 290, 291,
+ 292, 293, 294, 295, 296, 297, 298, 299, 300, 301,
+ 302, 303, 304, 305, 306, 307, 308, 309, 310, 311,
+ 312, 313, 314, 315, 316, 317, 318, 319, 320, 321,
+ 322, 323, 324, 325, 326, 327, 328, 329, 330, 331,
+ 332, 333, 334, 335, 336, 337, 338, 339, 340, 341,
+ 342, 343, 344, 345, 346, 347, 348, 349, 350, 351,
+ 352, 353, 354, 355, 356, 357, 358, 359, 360, 361,
+ 362, 363, 364, 365, 366, 367, 368, 369, 370, 371,
+ 372, 373, 374, 375, 376, 377, 378, 379, 380, 381,
+ 382, 383, 384, 385, 386, 387, 388, 389, 390, 391,
+ 392, 393, 394, 395, 396, 397, 398, 399, 400, 401,
+ 402, 403, 404, 405, 406, 407, 408, 409, 410, 411,
+ 412, 413, 414, 415, 416, 417, 418, 419, 420, 421,
+ 422, 423, 424, 425, 426, 427, 428, 429, 430, 431,
+ 432, 433, 434, 435, 436, 437, 438, 439, 440, 441,
+ 442, 443, 444, 445, 446, 447, 448, 449, 450, 451,
+ 452, 453, 454, 455, 456, 457, 458, 459, 460, 461,
+ 462, 463, 464, 465, 466, 467, 468, 469, 470, 471,
+ 472, 473, 474, 475, 476, 477, 478, 479, 480, 481,
+ 482, 483, 484, 485, 486, 487, 488, 489, 490, 491,
+ 492, 493, 494, 495, 496, 497, 498, 499, 500, 501,
+ 502, 503, 504, 505, 506, 507, 508, 509, 510, 511
+};
+
+/*The first DCT coefficient that both has a smaller magnitude and gets coded
+ with a different token.*/
+static const ogg_int16_t OC_DCT_TRELLIS_ALT_VALUE[1161]={
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -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, -36,
+ -36, -36, -36, -36, -20, -20, -20, -20, -20, -20,
+ -20, -20, -20, -20, -20, -20, -20, -20, -20, -20,
+ -12, -12, -12, -12, -12, -12, -12, -12, -8, -8,
+ -8, -8, -6, -6, -5, -4, -3, -2, -1, 0,
+ 0,
+ 0, 1, 2, 3, 4, 5, 6, 6, 8, 8,
+ 8, 8, 12, 12, 12, 12, 12, 12, 12, 12,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 20, 20, 20, 20, 20, 20, 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, 36, 36, 36, 36, 36, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68
+};
+
+#define OC_DCT_VALUE_TOKEN_PTR (OC_DCT_VALUE_TOKEN+580)
+#define OC_DCT_VALUE_EB_PTR (OC_DCT_VALUE_EB+580)
+#define OC_DCT_TRELLIS_ALT_VALUE_PTR (OC_DCT_TRELLIS_ALT_VALUE+580)
+
+/*Some tables for fast construction of combo tokens.*/
+
+static const unsigned char OC_DCT_RUN_CAT1_TOKEN[17]={
+ 23,24,25,26,27,28,28,28,28,29,29,29,29,29,29,29,29
+};
+
+static const unsigned char OC_DCT_RUN_CAT1_EB[17][2]={
+ {0,1},{0,1},{0, 1},{0, 1},{0, 1},{0, 4},{1, 5},{2, 6},{3,7},
+ {0,8},{1,9},{2,10},{3,11},{4,12},{5,13},{6,14},{7,15}
+};
+
+static const unsigned char OC_DCT_RUN_CAT2_EB[3][2][2]={
+ { {0,1},{2,3} },{ {0,2},{4,6} },{ {1,3},{5,7} }
+};
/*Token logging to allow a few fragments of efficient rollback.
Late SKIP analysis is tied up in the tokenization process, so we need to be
@@ -211,10 +454,11 @@ struct oc_quant_token{
/*Tokenizes the AC coefficients, possibly adjusting the quantization, and then
dequantizes and de-zig-zags the result.
- The DC coefficient is not preserved; it should be restored by the caller.*/
+ The AC coefficients of _idct must be pre-initialized to zero.*/
int oc_enc_tokenize_ac(oc_enc_ctx *_enc,int _pli,ptrdiff_t _fragi,
- ogg_int16_t *_qdct,const ogg_uint16_t *_dequant,const ogg_int16_t *_dct,
- int _zzi,oc_token_checkpoint **_stack,int _acmin){
+ ogg_int16_t *_idct,const ogg_int16_t *_qdct,
+ const ogg_uint16_t *_dequant,const ogg_int16_t *_dct,
+ int _zzi,oc_token_checkpoint **_stack,int _lambda,int _acmin){
oc_token_checkpoint *stack;
ogg_int64_t zflags;
ogg_int64_t nzflags;
@@ -242,31 +486,29 @@ int oc_enc_tokenize_ac(oc_enc_ctx *_enc,int _pli,ptrdiff_t _fragi,
d2_accum[0]=0;
zzj=64;
for(zzi=OC_MINI(_zzi,63);zzi>0;zzi--){
- ogg_int32_t lambda;
ogg_uint32_t best_cost;
int best_bits=best_bits;
int best_next=best_next;
int best_token=best_token;
int best_eb=best_eb;
int best_qc=best_qc;
- int flush_bits;
ogg_uint32_t d2;
int dq;
+ int qc_m;
int e;
int c;
int s;
int tj;
- lambda=_enc->lambda;
qc=_qdct[zzi];
s=-(qc<0);
- qc=qc+s^s;
- c=_dct[OC_FZIG_ZAG[zzi]];
- if(qc<=1){
+ qc_m=qc+s^s;
+ c=_dct[zzi];
+ /*The hard case: try a zero run.*/
+ if(qc_m<=1){
ogg_uint32_t sum_d2;
int nzeros;
int dc_reserve;
- /*The hard case: try a zero run.*/
- if(!qc){
+ if(!qc_m){
/*Skip runs that are already quantized to zeros.
If we considered each zero coefficient in turn, we might
theoretically find a better way to partition long zero runs (e.g.,
@@ -281,15 +523,14 @@ int oc_enc_tokenize_ac(oc_enc_ctx *_enc,int _pli,ptrdiff_t _fragi,
d2=0;
}
else{
- c=c+s^s;
d2=c*(ogg_int32_t)c;
+ c=c+s^s;
}
eob=eob_run[zzi];
nzeros=zzj-zzi;
zzj&=63;
sum_d2=d2+d2_accum[zzj];
d2_accum[zzi]=sum_d2;
- flush_bits=eob>0?oc_token_bits(_enc,huffi,zzi,oc_make_eob_token(eob)):0;
/*We reserve 1 spot for combo run tokens that start in the 1st AC stack
to ensure they can be extended to include the DC coefficient if
necessary; this greatly simplifies stack-rewriting later on.*/
@@ -297,7 +538,6 @@ int oc_enc_tokenize_ac(oc_enc_ctx *_enc,int _pli,ptrdiff_t _fragi,
best_cost=0xFFFFFFFF;
for(;;){
if(nzflags>>zzj&1){
- int cat;
int val;
int val_s;
int zzk;
@@ -306,11 +546,10 @@ int oc_enc_tokenize_ac(oc_enc_ctx *_enc,int _pli,ptrdiff_t _fragi,
tk=next&1;
zzk=next>>1;
/*Try a pure zero run to this point.*/
- cat=nzeros+55>>6;
- token=OC_DCT_SHORT_ZRL_TOKEN+cat;
- bits=flush_bits+oc_token_bits(_enc,huffi,zzi,token);
+ token=OC_DCT_SHORT_ZRL_TOKEN+(nzeros+55>>6);
+ bits=oc_token_bits(_enc,huffi,zzi,token);
d2=sum_d2-d2_accum[zzj];
- cost=d2+lambda*bits+tokens[zzj][1].cost;
+ cost=d2+_lambda*bits+tokens[zzj][1].cost;
if(cost<=best_cost){
best_next=(zzj<<1)+1;
best_token=token;
@@ -319,25 +558,18 @@ int oc_enc_tokenize_ac(oc_enc_ctx *_enc,int _pli,ptrdiff_t _fragi,
best_bits=bits+tokens[zzj][1].bits;
best_qc=0;
}
- if(nzeros<16+dc_reserve){
+ if(nzeros<17+dc_reserve){
val=_qdct[zzj];
val_s=-(val<0);
val=val+val_s^val_s;
if(val<=2){
/*Try a +/- 1 combo token.*/
- if(nzeros<6){
- token=OC_DCT_RUN_CAT1A+nzeros-1;
- eb=-val_s;
- }
- else{
- cat=nzeros+54>>6;
- token=OC_DCT_RUN_CAT1B+cat;
- eb=(-val_s<<cat+2)+nzeros-6-(cat<<2);
- }
- e=(_dct[OC_FZIG_ZAG[zzj]]+val_s^val_s)-_dequant[zzj];
+ token=OC_DCT_RUN_CAT1_TOKEN[nzeros-1];
+ eb=OC_DCT_RUN_CAT1_EB[nzeros-1][-val_s];
+ e=_dct[zzj]-(_dequant[zzj]+val_s^val_s);
d2=e*(ogg_int32_t)e+sum_d2-d2_accum[zzj];
- bits=flush_bits+oc_token_bits(_enc,huffi,zzi,token);
- cost=d2+lambda*bits+tokens[zzk][tk].cost;
+ bits=oc_token_bits(_enc,huffi,zzi,token);
+ cost=d2+_lambda*bits+tokens[zzk][tk].cost;
if(cost<=best_cost){
best_next=next;
best_token=token;
@@ -347,22 +579,23 @@ int oc_enc_tokenize_ac(oc_enc_ctx *_enc,int _pli,ptrdiff_t _fragi,
best_qc=1+val_s^val_s;
}
}
- if(nzeros<2+dc_reserve&&2<=val&&val<=4){
+ if(nzeros<3+dc_reserve&&2<=val&&val<=4){
+ int sval;
/*Try a +/- 2/3 combo token.*/
- cat=nzeros>>1;
- token=OC_DCT_RUN_CAT2A+cat;
- bits=flush_bits+oc_token_bits(_enc,huffi,zzi,token);
- val=2+((val+val_s^val_s)>2);
- e=(_dct[OC_FZIG_ZAG[zzj]]+val_s^val_s)-_dequant[zzj]*val;
+ token=OC_DCT_RUN_CAT2A+(nzeros>>1);
+ bits=oc_token_bits(_enc,huffi,zzi,token);
+ val=2+(val>2);
+ sval=val+val_s^val_s;
+ e=_dct[zzj]-_dequant[zzj]*sval;
d2=e*(ogg_int32_t)e+sum_d2-d2_accum[zzj];
- cost=d2+lambda*bits+tokens[zzk][tk].cost;
+ cost=d2+_lambda*bits+tokens[zzk][tk].cost;
if(cost<=best_cost){
best_cost=cost;
best_bits=bits+tokens[zzk][tk].bits;
best_next=next;
best_token=token;
- best_eb=(-val_s<<1+cat)+(val-2<<cat)+(nzeros-1>>1);
- best_qc=val+val_s^val_s;
+ best_eb=OC_DCT_RUN_CAT2_EB[nzeros-1][-val_s][val-2];
+ best_qc=sval;
}
}
}
@@ -378,10 +611,10 @@ int oc_enc_tokenize_ac(oc_enc_ctx *_enc,int _pli,ptrdiff_t _fragi,
/*We made it all the way to the end of the block; try an EOB token.*/
if(eob<4095){
bits=oc_token_bits(_enc,huffi,zzi,oc_make_eob_token(eob+1))
- -flush_bits;
+ -(eob>0?oc_token_bits(_enc,huffi,zzi,oc_make_eob_token(eob)):0);
}
else bits=oc_token_bits(_enc,huffi,zzi,OC_DCT_EOB1_TOKEN);
- cost=sum_d2+bits*lambda;
+ cost=sum_d2+bits*_lambda;
/*If the best route so far is still a pure zero run to the end of the
block, force coding it as an EOB.
Even if it's not optimal for this block, it has a good chance of
@@ -408,20 +641,20 @@ int oc_enc_tokenize_ac(oc_enc_ctx *_enc,int _pli,ptrdiff_t _fragi,
tokens[zzi][0].bits=best_bits;
tokens[zzi][0].qc=best_qc;
zflags|=(ogg_int64_t)1<<zzi;
- if(qc){
+ if(qc_m){
dq=_dequant[zzi];
- if(zzi<_acmin)lambda=0;
+ if(zzi<_acmin)_lambda=0;
e=dq-c;
d2=e*(ogg_int32_t)e;
token=OC_ONE_TOKEN-s;
- bits=flush_bits+oc_token_bits(_enc,huffi,zzi,token);
+ bits=oc_token_bits(_enc,huffi,zzi,token);
zzj=zzi+1&63;
tj=best_flags>>zzj&1;
next=(zzj<<1)+tj;
tokens[zzi][1].next=(unsigned char)next;
tokens[zzi][1].token=(signed char)token;
tokens[zzi][1].eb=0;
- tokens[zzi][1].cost=d2+lambda*bits+tokens[zzj][tj].cost;
+ tokens[zzi][1].cost=d2+_lambda*bits+tokens[zzj][tj].cost;
tokens[zzi][1].bits=bits+tokens[zzj][tj].bits;
tokens[zzi][1].qc=1+s^s;
nzflags|=(ogg_int64_t)1<<zzi;
@@ -430,200 +663,38 @@ int oc_enc_tokenize_ac(oc_enc_ctx *_enc,int _pli,ptrdiff_t _fragi,
}
}
else{
+ int alt_qc;
eob=eob_run[zzi];
- if(zzi<_acmin)lambda=0;
- c=c+s^s;
+ if(zzi<_acmin)_lambda=0;
dq=_dequant[zzi];
/*No zero run can extend past this point.*/
d2_accum[zzi]=0;
- flush_bits=eob>0?oc_token_bits(_enc,huffi,zzi,oc_make_eob_token(eob)):0;
- if(qc<=2){
- e=2*dq-c;
- d2=e*(ogg_int32_t)e;
- best_token=OC_TWO_TOKEN-s;
- best_bits=flush_bits+oc_token_bits(_enc,huffi,zzi,best_token);
- best_cost=d2+lambda*best_bits;
- e-=dq;
- d2=e*(ogg_int32_t)e;
- token=OC_ONE_TOKEN-s;
- bits=flush_bits+oc_token_bits(_enc,huffi,zzi,token);
- cost=d2+lambda*bits;
- if(cost<=best_cost){
- best_token=token;
- best_bits=bits;
- best_cost=cost;
- qc--;
- }
- best_eb=0;
- }
- else if(qc<=3){
- e=3*dq-c;
- d2=e*(ogg_int32_t)e;
- best_token=OC_DCT_VAL_CAT2;
- best_eb=-s;
- best_bits=flush_bits+oc_token_bits(_enc,huffi,zzi,best_token);
- best_cost=d2+lambda*best_bits;
- e-=dq;
- d2=e*(ogg_int32_t)e;
- token=OC_TWO_TOKEN-s;
- bits=flush_bits+oc_token_bits(_enc,huffi,zzi,token);
- cost=d2+lambda*bits;
- if(cost<=best_cost){
- best_token=token;
- best_eb=0;
- best_bits=bits;
- best_cost=cost;
- qc--;
- }
- }
- else if(qc<=6){
- e=qc*dq-c;
- d2=e*(ogg_int32_t)e;
- best_token=OC_DCT_VAL_CAT2+qc-3;
- best_eb=-s;
- best_bits=flush_bits+oc_token_bits(_enc,huffi,zzi,best_token);
- best_cost=d2+lambda*best_bits;
- e-=dq;
- d2=e*(ogg_int32_t)e;
- token=best_token-1;
- bits=flush_bits+oc_token_bits(_enc,huffi,zzi,token);
- cost=d2+lambda*bits;
- if(cost<=best_cost){
- best_token=token;
- best_bits=bits;
- best_cost=cost;
- qc--;
- }
- }
- else if(qc<=8){
- e=qc*dq-c;
- d2=e*(ogg_int32_t)e;
- best_token=OC_DCT_VAL_CAT3;
- best_eb=(-s<<1)+qc-7;
- best_bits=flush_bits+oc_token_bits(_enc,huffi,zzi,best_token);
- best_cost=d2+lambda*best_bits;
- e=6*dq-c;
- d2=e*(ogg_int32_t)e;
- token=OC_DCT_VAL_CAT2+3;
- bits=flush_bits+oc_token_bits(_enc,huffi,zzi,token);
- cost=d2+lambda*bits;
- if(cost<=best_cost){
- best_token=token;
- best_eb=-s;
- best_bits=bits;
- best_cost=cost;
- qc=6;
- }
- }
- else if(qc<=12){
- e=qc*dq-c;
- d2=e*(ogg_int32_t)e;
- best_token=OC_DCT_VAL_CAT4;
- best_eb=(-s<<2)+qc-9;
- best_bits=flush_bits+oc_token_bits(_enc,huffi,zzi,best_token);
- best_cost=d2+lambda*best_bits;
- e=8*dq-c;
- d2=e*(ogg_int32_t)e;
- token=best_token-1;
- bits=flush_bits+oc_token_bits(_enc,huffi,zzi,token);
- cost=d2+lambda*bits;
- if(cost<=best_cost){
- best_token=token;
- best_eb=(-s<<1)+1;
- best_bits=bits;
- best_cost=cost;
- qc=8;
- }
- }
- else if(qc<=20){
- e=qc*dq-c;
- d2=e*(ogg_int32_t)e;
- best_token=OC_DCT_VAL_CAT5;
- best_eb=(-s<<3)+qc-13;
- best_bits=flush_bits+oc_token_bits(_enc,huffi,zzi,best_token);
- best_cost=d2+lambda*best_bits;
- e=12*dq-c;
- d2=e*(ogg_int32_t)e;
- token=best_token-1;
- bits=flush_bits+oc_token_bits(_enc,huffi,zzi,token);
- cost=d2+lambda*bits;
- if(cost<=best_cost){
- best_token=token;
- best_eb=(-s<<2)+3;
- best_bits=bits;
- best_cost=cost;
- qc=12;
- }
- }
- else if(qc<=36){
- e=qc*dq-c;
- d2=e*(ogg_int32_t)e;
- best_token=OC_DCT_VAL_CAT6;
- best_eb=(-s<<4)+qc-21;
- best_bits=flush_bits+oc_token_bits(_enc,huffi,zzi,best_token);
- best_cost=d2+lambda*best_bits;
- e=20*dq-c;
- d2=e*(ogg_int32_t)e;
- token=best_token-1;
- bits=flush_bits+oc_token_bits(_enc,huffi,zzi,token);
- cost=d2+lambda*bits;
- if(cost<=best_cost){
- best_token=token;
- best_eb=(-s<<3)+7;
- best_bits=bits;
- best_cost=cost;
- qc=20;
- }
- }
- else if(qc<=68){
- e=qc*dq-c;
- d2=e*(ogg_int32_t)e;
- best_token=OC_DCT_VAL_CAT7;
- best_eb=(-s<<5)+qc-37;
- best_bits=flush_bits+oc_token_bits(_enc,huffi,zzi,best_token);
- best_cost=d2+lambda*best_bits;
- e=36*dq-c;
- d2=e*(ogg_int32_t)e;
- token=best_token-1;
- bits=flush_bits+oc_token_bits(_enc,huffi,zzi,token);
- cost=d2+lambda*bits;
- if(cost<best_cost){
- best_token=token;
- best_eb=(-s<<4)+15;
- best_bits=bits;
- best_cost=cost;
- qc=36;
- }
- }
- else{
- e=qc*dq-c;
- d2=e*(ogg_int32_t)e;
- best_token=OC_DCT_VAL_CAT8;
- best_eb=(-s<<9)+qc-69;
- best_bits=flush_bits+oc_token_bits(_enc,huffi,zzi,best_token);
- best_cost=d2+lambda*best_bits;
- e=68*dq-c;
- d2=e*(ogg_int32_t)e;
- token=best_token-1;
- bits=flush_bits+oc_token_bits(_enc,huffi,zzi,token);
- cost=d2+lambda*bits;
- if(cost<best_cost){
- best_token=token;
- best_eb=(-s<<5)+31;
- best_bits=bits;
- best_cost=cost;
- qc=68;
- }
+ e=qc*dq-c;
+ d2=e*(ogg_int32_t)e;
+ best_token=*(OC_DCT_VALUE_TOKEN_PTR+qc);
+ best_bits=oc_token_bits(_enc,huffi,zzi,best_token);
+ best_cost=d2+_lambda*best_bits;
+ alt_qc=*(OC_DCT_TRELLIS_ALT_VALUE_PTR+qc);
+ e=alt_qc*dq-c;
+ d2=e*(ogg_int32_t)e;
+ token=*(OC_DCT_VALUE_TOKEN_PTR+alt_qc);
+ bits=oc_token_bits(_enc,huffi,zzi,token);
+ cost=d2+_lambda*bits;
+ if(cost<best_cost){
+ best_token=token;
+ best_bits=bits;
+ best_cost=cost;
+ qc=alt_qc;
}
zzj=zzi+1&63;
tj=best_flags>>zzj&1;
next=(zzj<<1)+tj;
tokens[zzi][1].next=(unsigned char)next;
tokens[zzi][1].token=(signed char)best_token;
- tokens[zzi][1].eb=best_eb;
+ tokens[zzi][1].eb=*(OC_DCT_VALUE_EB_PTR+qc);
tokens[zzi][1].cost=best_cost+tokens[zzj][tj].cost;
tokens[zzi][1].bits=best_bits+tokens[zzj][tj].bits;
- tokens[zzi][1].qc=qc+s^s;
+ tokens[zzi][1].qc=qc;
nzflags|=(ogg_int64_t)1<<zzi;
best_flags|=(ogg_int64_t)1<<zzi;
}
@@ -631,9 +702,6 @@ int oc_enc_tokenize_ac(oc_enc_ctx *_enc,int _pli,ptrdiff_t _fragi,
}
/*Emit the tokens from the best path through the trellis.*/
stack=*_stack;
- /*We blow away the first entry here so that things vectorize better.
- The DC coefficient is not actually stored in the array yet.*/
- for(zzi=0;zzi<64;zzi++)_qdct[zzi]=0;
dct_fzig_zag=_enc->state.opt_data.dct_fzig_zag;
zzi=1;
ti=best_flags>>1&1;
@@ -643,12 +711,15 @@ int oc_enc_tokenize_ac(oc_enc_ctx *_enc,int _pli,ptrdiff_t _fragi,
eob=eob_run[zzi];
if(tokens[zzi][ti].token<OC_NDCT_EOB_TOKEN_MAX){
if(++eob>=4095){
- oc_enc_eob_log(_enc,_pli,zzi,eob);
+ oc_enc_token_log(_enc,_pli,zzi,OC_DCT_REPEAT_RUN3_TOKEN,eob);
eob=0;
}
eob_run[zzi]=eob;
/*We don't include the actual EOB cost for this block in the return value.
- It will be paid for by the fragment that terminates the EOB run.*/
+ It is very likely to eventually be spread over several blocks, and
+ including it more harshly penalizes the first few blocks in a long EOB
+ run.
+ Omitting it here gives a small PSNR and SSIM gain.*/
bits-=tokens[zzi][ti].bits;
zzi=_zzi;
break;
@@ -664,7 +735,7 @@ int oc_enc_tokenize_ac(oc_enc_ctx *_enc,int _pli,ptrdiff_t _fragi,
zzj=(next>>1)-1&63;
/*TODO: It may be worth saving the dequantized coefficient in the trellis
above; we had to compute it to measure the error anyway.*/
- _qdct[dct_fzig_zag[zzj]]=(ogg_int16_t)(qc*(int)_dequant[zzj]);
+ _idct[dct_fzig_zag[zzj]]=(ogg_int16_t)(qc*(int)_dequant[zzj]);
zzi=next>>1;
ti=next&1;
}
@@ -673,6 +744,237 @@ int oc_enc_tokenize_ac(oc_enc_ctx *_enc,int _pli,ptrdiff_t _fragi,
return bits;
}
+/*Simplistic R/D tokenizer.
+ The AC coefficients of _idct must be pre-initialized to zero.
+ This could be made more accurate by using more sophisticated
+ rate predictions for zeros.
+ It could be made faster by switching from R/D decisions to static
+ lambda-derived rounding biases.*/
+int oc_enc_tokenize_ac_fast(oc_enc_ctx *_enc,int _pli,ptrdiff_t _fragi,
+ ogg_int16_t *_idct,const ogg_int16_t *_qdct,
+ const ogg_uint16_t *_dequant,const ogg_int16_t *_dct,
+ int _zzi,oc_token_checkpoint **_stack,int _lambda,int _acmin){
+ const unsigned char *dct_fzig_zag;
+ ogg_uint16_t *eob_run;
+ oc_token_checkpoint *stack;
+ int huffi;
+ int zzi;
+ int zzj;
+ int zzk;
+ int total_bits;
+ int zr[4];
+ stack=*_stack;
+ total_bits=0;
+ /*The apparent bit-cost of coding a zero from observing the trellis
+ quantizer is pre-combined with lambda.
+ Four predictive cases are considered: the last optimized value is zero (+2)
+ or non-zero and the non-optimized value is zero (+1) or non-zero.*/
+ zr[0]=3*_lambda>>1;
+ zr[1]=_lambda;
+ zr[2]=4*_lambda;
+ zr[3]=7*_lambda>>1;
+ eob_run=_enc->eob_run[_pli];
+ dct_fzig_zag=_enc->state.opt_data.dct_fzig_zag;
+ huffi=_enc->huff_idxs[_enc->state.frame_type][1][_pli+1>>1];
+ for(zzj=zzi=1;zzj<_zzi&&!_qdct[zzj];zzj++);
+ while(zzj<_zzi){
+ int v;
+ int d0;
+ int d1;
+ int sign;
+ int k;
+ int eob;
+ int dq0;
+ int dq1;
+ int dd0;
+ int dd1;
+ int next_zero;
+ int eob_bits;
+ int dct_fzig_zzj;
+ dct_fzig_zzj=dct_fzig_zag[zzj];
+ v=_dct[zzj];
+ d0=_qdct[zzj];
+ eob=eob_run[zzi];
+ for(zzk=zzj+1;zzk<_zzi&&!_qdct[zzk];zzk++);
+ next_zero=zzk-zzj+62>>6;
+ dq0=d0*_dequant[zzj];
+ dd0=dq0-v;
+ dd0*=dd0;
+ sign=-(d0<0);
+ k=d0+sign^sign;
+ d1=(k-(zzj>_acmin))+sign^sign;
+ dq1=d1*_dequant[zzj];
+ dd1=dq1-v;
+ dd1*=dd1;
+ /*The cost of ending an eob run is included when the alternative is to
+ extend this eob run.
+ A per qi/zzi weight would probably be useful.
+ Including it in the overall tokenization cost was not helpful.
+ The same is true at the far end of the zero run plus token case.*/
+ if(eob>0&&d1==0&&zzk==_zzi){
+ eob_bits=oc_token_bits(_enc,huffi,zzi,OC_DCT_EOB1_TOKEN);
+ }
+ else eob_bits=0;
+ if(zzj==zzi){
+ /*No active zero run.*/
+ int best_token;
+ int best_eb;
+ int token;
+ int best_bits;
+ int bits;
+ int cost;
+ best_token=*(OC_DCT_VALUE_TOKEN_PTR+d0);
+ best_bits=oc_token_bits(_enc,huffi,zzi,best_token);
+ if(d1!=0){
+ token=*(OC_DCT_VALUE_TOKEN_PTR+d1);
+ bits=oc_token_bits(_enc,huffi,zzi,token);
+ cost=dd1+(bits+eob_bits)*_lambda;
+ }
+ else{
+ token=bits=0;
+ cost=dd1+zr[next_zero];
+ }
+ if((dd0+(best_bits+eob_bits)*_lambda)>cost){
+ _idct[dct_fzig_zzj]=dq1;
+ if(d1==0){
+ zzj=zzk;
+ continue;
+ }
+ best_bits=bits;
+ best_token=token;
+ best_eb=*(OC_DCT_VALUE_EB_PTR+d1);
+ }
+ else{
+ best_eb=*(OC_DCT_VALUE_EB_PTR+d0);
+ _idct[dct_fzig_zzj]=dq0;
+ }
+ oc_enc_tokenlog_checkpoint(_enc,stack++,_pli,zzi);
+ if(eob>0){
+ oc_enc_eob_log(_enc,_pli,zzi,eob);
+ eob_run[zzi]=0;
+ }
+ oc_enc_token_log(_enc,_pli,zzi,best_token,best_eb);
+ total_bits+=best_bits;
+ }
+ else{
+ int d;
+ int dc_reserve;
+ int best_token;
+ int best_eb;
+ int best_bits;
+ int best_cost;
+ int best_bits1;
+ int best_token1;
+ int best_eb1;
+ int zr_bits;
+ int eob2;
+ int eob_bits2;
+ int bits;
+ int token;
+ int nzeros;
+ nzeros=zzj-zzi;
+ dc_reserve=zzi+62>>6;
+ /*A zero run, followed by the value alone.*/
+ best_token=best_token1=OC_DCT_SHORT_ZRL_TOKEN+(nzeros+55>>6);
+ best_eb=best_eb1=nzeros-1;
+ eob2=eob_run[zzj];
+ eob_bits2=eob2>0?oc_token_bits(_enc,huffi,zzj,OC_DCT_EOB1_TOKEN):0;
+ zr_bits=oc_token_bits(_enc,huffi,zzi,best_token)+eob_bits2;
+ best_bits=zr_bits
+ +oc_token_bits(_enc,huffi,zzj,*(OC_DCT_VALUE_TOKEN_PTR+d0));
+ d=d0;
+ best_bits1=0;
+ if(d1!=0){
+ best_bits1=zr_bits
+ +oc_token_bits(_enc,huffi,zzj,*(OC_DCT_VALUE_TOKEN_PTR+d1));
+ }
+ if(nzeros<17+dc_reserve){
+ if(k<=2){
+ /*+/- 1 combo token.*/
+ token=OC_DCT_RUN_CAT1_TOKEN[nzeros-1];
+ bits=oc_token_bits(_enc,huffi,zzi,token);
+ if(k==2&&bits<=best_bits1){
+ best_bits1=bits;
+ best_token1=token;
+ best_eb1=OC_DCT_RUN_CAT1_EB[nzeros-1][-sign];
+ }
+ if(k==1&&bits<=best_bits){
+ best_bits=bits;
+ best_token=token;
+ best_eb=OC_DCT_RUN_CAT1_EB[nzeros-1][-sign];
+ }
+ }
+ if(nzeros<3+dc_reserve&&2<=k&&k<=4){
+ /*+/- 2/3 combo token.*/
+ token=OC_DCT_RUN_CAT2A+(nzeros>>1);
+ bits=oc_token_bits(_enc,huffi,zzi,token);
+ if(k==4&&bits<=best_bits1){
+ best_bits1=bits;
+ best_token1=token;
+ best_eb1=OC_DCT_RUN_CAT2_EB[nzeros-1][-sign][1];
+ }
+ if(k!=4&&bits<=best_bits){
+ best_bits=bits;
+ best_token=token;
+ best_eb=OC_DCT_RUN_CAT2_EB[nzeros-1][-sign][k-2];
+ }
+ }
+ }
+ best_cost=dd0+(best_bits+eob_bits)*_lambda;
+ if(d1==0&&(dd1+zr[2+next_zero])<=best_cost){
+ zzj=zzk;
+ continue;
+ }
+ if(d1!=0&&dd1+(best_bits1+eob_bits)*_lambda<best_cost){
+ best_bits=best_bits1;
+ best_token=best_token1;
+ best_eb=best_eb1;
+ d=d1;
+ _idct[dct_fzig_zzj]=dq1;
+ }
+ else _idct[dct_fzig_zzj]=dq0;
+ oc_enc_tokenlog_checkpoint(_enc,stack++,_pli,zzi);
+ if(eob){
+ oc_enc_eob_log(_enc,_pli,zzi,eob);
+ eob_run[zzi]=0;
+ }
+ oc_enc_token_log(_enc,_pli,zzi,best_token,best_eb);
+ /*If a zero run won vs. the combo token we still need to code this
+ value.*/
+ if(best_token<=OC_DCT_ZRL_TOKEN){
+ oc_enc_tokenlog_checkpoint(_enc,stack++,_pli,zzj);
+ if(eob2){
+ oc_enc_eob_log(_enc,_pli,zzj,eob2);
+ /*The cost of any EOB run we disrupted is ignored because doing so
+ improved PSNR/SSIM by a small amount.*/
+ best_bits-=eob_bits2;
+ eob_run[zzj]=0;
+ }
+ oc_enc_token_log(_enc,_pli,zzj,
+ *(OC_DCT_VALUE_TOKEN_PTR+d),*(OC_DCT_VALUE_EB_PTR+d));
+ }
+ total_bits+=best_bits;
+ }
+ zzi=zzj+1;
+ zzj=zzk;
+ }
+ /*Code an EOB run to complete this block.
+ The cost of the EOB run is not included in the total as explained in
+ in a comment in the trellis tokenizer above.*/
+ if(zzi<64){
+ int eob;
+ eob=eob_run[zzi]+1;
+ oc_enc_tokenlog_checkpoint(_enc,stack++,_pli,zzi);
+ if(eob>=4095){
+ oc_enc_token_log(_enc,_pli,zzi,OC_DCT_REPEAT_RUN3_TOKEN,eob);
+ eob=0;
+ }
+ eob_run[zzi]=eob;
+ }
+ *_stack=stack;
+ return total_bits;
+}
+
void oc_enc_pred_dc_frag_rows(oc_enc_ctx *_enc,
int _pli,int _fragy0,int _frag_yend){
const oc_fragment_plane *fplane;
@@ -695,10 +997,10 @@ void oc_enc_pred_dc_frag_rows(oc_enc_ctx *_enc,
predictor for the same reference frame.*/
for(fragx=0;fragx<nhfrags;fragx++,fragi++){
if(frags[fragi].coded){
- int ref;
- ref=OC_FRAME_FOR_MODE(frags[fragi].mb_mode);
- frag_dc[fragi]=(ogg_int16_t)(frags[fragi].dc-pred_last[ref]);
- pred_last[ref]=frags[fragi].dc;
+ int refi;
+ refi=frags[fragi].refi;
+ frag_dc[fragi]=(ogg_int16_t)(frags[fragi].dc-pred_last[refi]);
+ pred_last[refi]=frags[fragi].dc;
}
}
}
@@ -710,27 +1012,24 @@ void oc_enc_pred_dc_frag_rows(oc_enc_ctx *_enc,
u_frags=frags-nhfrags;
l_ref=-1;
ul_ref=-1;
- u_ref=u_frags[fragi].coded?OC_FRAME_FOR_MODE(u_frags[fragi].mb_mode):-1;
+ u_ref=u_frags[fragi].refi;
for(fragx=0;fragx<nhfrags;fragx++,fragi++){
int ur_ref;
if(fragx+1>=nhfrags)ur_ref=-1;
- else{
- ur_ref=u_frags[fragi+1].coded?
- OC_FRAME_FOR_MODE(u_frags[fragi+1].mb_mode):-1;
- }
+ else ur_ref=u_frags[fragi+1].refi;
if(frags[fragi].coded){
int pred;
- int ref;
- ref=OC_FRAME_FOR_MODE(frags[fragi].mb_mode);
+ int refi;
+ refi=frags[fragi].refi;
/*We break out a separate case based on which of our neighbors use
the same reference frames.
This is somewhat faster than trying to make a generic case which
handles all of them, since it reduces lots of poorly predicted
jumps to one switch statement, and also lets a number of the
multiplications be optimized out by strength reduction.*/
- switch((l_ref==ref)|(ul_ref==ref)<<1|
- (u_ref==ref)<<2|(ur_ref==ref)<<3){
- default:pred=pred_last[ref];break;
+ switch((l_ref==refi)|(ul_ref==refi)<<1|
+ (u_ref==refi)<<2|(ur_ref==refi)<<3){
+ default:pred=pred_last[refi];break;
case 1:
case 3:pred=frags[fragi-1].dc;break;
case 2:pred=u_frags[fragi-1].dc;break;
@@ -764,8 +1063,8 @@ void oc_enc_pred_dc_frag_rows(oc_enc_ctx *_enc,
}break;
}
frag_dc[fragi]=(ogg_int16_t)(frags[fragi].dc-pred);
- pred_last[ref]=frags[fragi].dc;
- l_ref=ref;
+ pred_last[refi]=frags[fragi].dc;
+ l_ref=refi;
}
else l_ref=-1;
ul_ref=u_ref;
@@ -850,9 +1149,8 @@ void oc_enc_tokenize_dc_frag_list(oc_enc_ctx *_enc,int _pli,
ti0++;
eob_run0=0;
}
- token=oc_make_dct_token_full(0,0,val,&eb);
- dct_tokens0[ti0]=(unsigned char)token;
- extra_bits0[ti0]=(ogg_uint16_t)eb;
+ dct_tokens0[ti0]=*(OC_DCT_VALUE_TOKEN_PTR+val);
+ extra_bits0[ti0]=*(OC_DCT_VALUE_EB_PTR+val);
ti0++;
}
else{
@@ -863,9 +1161,8 @@ void oc_enc_tokenize_dc_frag_list(oc_enc_ctx *_enc,int _pli,
/*We're in the middle of an active EOB run in stack 1.
Move it to stack 0.*/
if(++eob_run0>=4095){
- token=oc_make_eob_token_full(eob_run0,&eb);
- dct_tokens0[ti0]=(unsigned char)token;
- extra_bits0[ti0]=(ogg_uint16_t)eb;
+ dct_tokens0[ti0]=OC_DCT_REPEAT_RUN3_TOKEN;
+ extra_bits0[ti0]=eob_run0;
ti0++;
eob_run0=0;
}
@@ -996,9 +1293,8 @@ void oc_enc_tokenize_dc_frag_list(oc_enc_ctx *_enc,int _pli,
neobs1--;
/*If we have more than 4095 EOBs outstanding in stack1, flush the run.*/
if(eob_run1-neobs1>=4095){
- token=oc_make_eob_token_full(4095,&eb);
- dct_tokens1[ti1w]=(unsigned char)token;
- extra_bits1[ti1w]=(ogg_uint16_t)eb;
+ dct_tokens1[ti1w]=OC_DCT_REPEAT_RUN3_TOKEN;
+ extra_bits1[ti1w]=4095;
ti1w++;
eob_run1-=4095;
}
diff --git a/thirdparty/libtheora/x86/mmxencfrag.c b/thirdparty/libtheora/x86/mmxencfrag.c
index c79ff01fcc..cc9be8d867 100644
--- a/thirdparty/libtheora/x86/mmxencfrag.c
+++ b/thirdparty/libtheora/x86/mmxencfrag.c
@@ -65,7 +65,7 @@ unsigned oc_enc_frag_sad_mmxext(const unsigned char *_src,
"paddw %%mm6,%%mm0\n\t"
"paddw %%mm2,%%mm0\n\t"
"movd %%mm0,%[ret]\n\t"
- :[ret]"=a"(ret),[src]"+%r"(_src),[ref]"+r"(_ref),[ystride3]"=&r"(ystride3)
+ :[ret]"=a"(ret),[src]"+r"(_src),[ref]"+r"(_ref),[ystride3]"=&r"(ystride3)
:[ystride]"r"((ptrdiff_t)_ystride)
);
return (unsigned)ret;
@@ -87,7 +87,9 @@ unsigned oc_enc_frag_sad_thresh_mmxext(const unsigned char *_src,
The latter is exactly 1 too large when the low bit of two corresponding \
bytes is only set in one of them. \
Therefore we pxor the operands, pand to mask out the low bits, and psubb to \
- correct the output of pavgb.*/ \
+ correct the output of pavgb. \
+ TODO: This should be rewritten to compute ~pavgb(~a,~b) instead, which \
+ schedules better; currently, however, this function is unused.*/ \
"movq %%mm0,%%mm6\n\t" \
"lea (%[ref1],%[ystride],2),%[ref1]\n\t" \
"pxor %%mm1,%%mm0\n\t" \
@@ -153,7 +155,7 @@ unsigned oc_enc_frag_sad2_thresh_mmxext(const unsigned char *_src,
OC_SAD2_LOOP
OC_SAD2_LOOP
OC_SAD2_TAIL
- :[ret]"=&a"(ret),[src]"+r"(_src),[ref1]"+%r"(_ref1),[ref2]"+r"(_ref2)
+ :[ret]"=&a"(ret),[src]"+r"(_src),[ref1]"+r"(_ref1),[ref2]"+r"(_ref2)
:[ystride]"r"((ptrdiff_t)_ystride)
);
return (unsigned)ret;
@@ -163,54 +165,54 @@ unsigned oc_enc_frag_sad2_thresh_mmxext(const unsigned char *_src,
16-bit difference in %%mm0...%%mm7.*/
#define OC_LOAD_SUB_8x4(_off) \
"#OC_LOAD_SUB_8x4\n\t" \
- "movd "_off"(%[src]),%%mm0\n\t" \
- "movd "_off"(%[ref]),%%mm4\n\t" \
- "movd "_off"(%[src],%[src_ystride]),%%mm1\n\t" \
+ "movd "#_off"(%[src]),%%mm0\n\t" \
+ "movd "#_off"(%[ref]),%%mm4\n\t" \
+ "movd "#_off"(%[src],%[src_ystride]),%%mm1\n\t" \
"lea (%[src],%[src_ystride],2),%[src]\n\t" \
- "movd "_off"(%[ref],%[ref_ystride]),%%mm5\n\t" \
+ "movd "#_off"(%[ref],%[ref_ystride]),%%mm5\n\t" \
"lea (%[ref],%[ref_ystride],2),%[ref]\n\t" \
- "movd "_off"(%[src]),%%mm2\n\t" \
- "movd "_off"(%[ref]),%%mm7\n\t" \
- "movd "_off"(%[src],%[src_ystride]),%%mm3\n\t" \
- "movd "_off"(%[ref],%[ref_ystride]),%%mm6\n\t" \
+ "movd "#_off"(%[src]),%%mm2\n\t" \
+ "movd "#_off"(%[ref]),%%mm7\n\t" \
+ "movd "#_off"(%[src],%[src_ystride]),%%mm3\n\t" \
+ "movd "#_off"(%[ref],%[ref_ystride]),%%mm6\n\t" \
"punpcklbw %%mm4,%%mm0\n\t" \
"lea (%[src],%[src_ystride],2),%[src]\n\t" \
"punpcklbw %%mm4,%%mm4\n\t" \
"lea (%[ref],%[ref_ystride],2),%[ref]\n\t" \
"psubw %%mm4,%%mm0\n\t" \
- "movd "_off"(%[src]),%%mm4\n\t" \
- "movq %%mm0,"_off"*2(%[buf])\n\t" \
- "movd "_off"(%[ref]),%%mm0\n\t" \
+ "movd "#_off"(%[src]),%%mm4\n\t" \
+ "movq %%mm0,"OC_MEM_OFFS(_off*2,buf)"\n\t" \
+ "movd "#_off"(%[ref]),%%mm0\n\t" \
"punpcklbw %%mm5,%%mm1\n\t" \
"punpcklbw %%mm5,%%mm5\n\t" \
"psubw %%mm5,%%mm1\n\t" \
- "movd "_off"(%[src],%[src_ystride]),%%mm5\n\t" \
+ "movd "#_off"(%[src],%[src_ystride]),%%mm5\n\t" \
"punpcklbw %%mm7,%%mm2\n\t" \
"punpcklbw %%mm7,%%mm7\n\t" \
"psubw %%mm7,%%mm2\n\t" \
- "movd "_off"(%[ref],%[ref_ystride]),%%mm7\n\t" \
+ "movd "#_off"(%[ref],%[ref_ystride]),%%mm7\n\t" \
"punpcklbw %%mm6,%%mm3\n\t" \
"lea (%[src],%[src_ystride],2),%[src]\n\t" \
"punpcklbw %%mm6,%%mm6\n\t" \
"psubw %%mm6,%%mm3\n\t" \
- "movd "_off"(%[src]),%%mm6\n\t" \
+ "movd "#_off"(%[src]),%%mm6\n\t" \
"punpcklbw %%mm0,%%mm4\n\t" \
"lea (%[ref],%[ref_ystride],2),%[ref]\n\t" \
"punpcklbw %%mm0,%%mm0\n\t" \
"lea (%[src],%[src_ystride],2),%[src]\n\t" \
"psubw %%mm0,%%mm4\n\t" \
- "movd "_off"(%[ref]),%%mm0\n\t" \
+ "movd "#_off"(%[ref]),%%mm0\n\t" \
"punpcklbw %%mm7,%%mm5\n\t" \
"neg %[src_ystride]\n\t" \
"punpcklbw %%mm7,%%mm7\n\t" \
"psubw %%mm7,%%mm5\n\t" \
- "movd "_off"(%[src],%[src_ystride]),%%mm7\n\t" \
+ "movd "#_off"(%[src],%[src_ystride]),%%mm7\n\t" \
"punpcklbw %%mm0,%%mm6\n\t" \
"lea (%[ref],%[ref_ystride],2),%[ref]\n\t" \
"punpcklbw %%mm0,%%mm0\n\t" \
"neg %[ref_ystride]\n\t" \
"psubw %%mm0,%%mm6\n\t" \
- "movd "_off"(%[ref],%[ref_ystride]),%%mm0\n\t" \
+ "movd "#_off"(%[ref],%[ref_ystride]),%%mm0\n\t" \
"lea (%[src],%[src_ystride],8),%[src]\n\t" \
"punpcklbw %%mm0,%%mm7\n\t" \
"neg %[src_ystride]\n\t" \
@@ -218,24 +220,24 @@ unsigned oc_enc_frag_sad2_thresh_mmxext(const unsigned char *_src,
"lea (%[ref],%[ref_ystride],8),%[ref]\n\t" \
"psubw %%mm0,%%mm7\n\t" \
"neg %[ref_ystride]\n\t" \
- "movq "_off"*2(%[buf]),%%mm0\n\t" \
+ "movq "OC_MEM_OFFS(_off*2,buf)",%%mm0\n\t" \
/*Load an 8x4 array of pixel values from %[src] into %%mm0...%%mm7.*/
#define OC_LOAD_8x4(_off) \
"#OC_LOAD_8x4\n\t" \
- "movd "_off"(%[src]),%%mm0\n\t" \
- "movd "_off"(%[src],%[ystride]),%%mm1\n\t" \
- "movd "_off"(%[src],%[ystride],2),%%mm2\n\t" \
+ "movd "#_off"(%[src]),%%mm0\n\t" \
+ "movd "#_off"(%[src],%[ystride]),%%mm1\n\t" \
+ "movd "#_off"(%[src],%[ystride],2),%%mm2\n\t" \
"pxor %%mm7,%%mm7\n\t" \
- "movd "_off"(%[src],%[ystride3]),%%mm3\n\t" \
+ "movd "#_off"(%[src],%[ystride3]),%%mm3\n\t" \
"punpcklbw %%mm7,%%mm0\n\t" \
- "movd "_off"(%[src4]),%%mm4\n\t" \
+ "movd "#_off"(%[src4]),%%mm4\n\t" \
"punpcklbw %%mm7,%%mm1\n\t" \
- "movd "_off"(%[src4],%[ystride]),%%mm5\n\t" \
+ "movd "#_off"(%[src4],%[ystride]),%%mm5\n\t" \
"punpcklbw %%mm7,%%mm2\n\t" \
- "movd "_off"(%[src4],%[ystride],2),%%mm6\n\t" \
+ "movd "#_off"(%[src4],%[ystride],2),%%mm6\n\t" \
"punpcklbw %%mm7,%%mm3\n\t" \
- "movd "_off"(%[src4],%[ystride3]),%%mm7\n\t" \
+ "movd "#_off"(%[src4],%[ystride3]),%%mm7\n\t" \
"punpcklbw %%mm4,%%mm4\n\t" \
"punpcklbw %%mm5,%%mm5\n\t" \
"psrlw $8,%%mm4\n\t" \
@@ -248,7 +250,7 @@ unsigned oc_enc_frag_sad2_thresh_mmxext(const unsigned char *_src,
/*Performs the first two stages of an 8-point 1-D Hadamard transform.
The transform is performed in place, except that outputs 0-3 are swapped with
outputs 4-7.
- Outputs 2, 3, 6 and 7 from the second stage are negated (which allows us to
+ Outputs 2, 3, 6, and 7 from the second stage are negated (which allows us to
perform this stage in place with no temporary registers).*/
#define OC_HADAMARD_AB_8x4 \
"#OC_HADAMARD_AB_8x4\n\t" \
@@ -281,7 +283,7 @@ unsigned oc_enc_frag_sad2_thresh_mmxext(const unsigned char *_src,
"psubw %%mm5,%%mm7\n\t" \
/*Performs the last stage of an 8-point 1-D Hadamard transform in place.
- Ouputs 1, 3, 5, and 7 are negated (which allows us to perform this stage in
+ Outputs 1, 3, 5, and 7 are negated (which allows us to perform this stage in
place with no temporary registers).*/
#define OC_HADAMARD_C_8x4 \
"#OC_HADAMARD_C_8x4\n\t" \
@@ -324,8 +326,8 @@ unsigned oc_enc_frag_sad2_thresh_mmxext(const unsigned char *_src,
Even with pabsw, it would be (3+1)*8+7=39 instructions (with no spills). \
This implementation is only 26 (+4 for spilling registers).*/ \
"#OC_HADAMARD_C_ABS_ACCUM_A_8x4\n\t" \
- "movq %%mm7,"_r7"(%[buf])\n\t" \
- "movq %%mm6,"_r6"(%[buf])\n\t" \
+ "movq %%mm7,"OC_MEM_OFFS(_r7,buf)"\n\t" \
+ "movq %%mm6,"OC_MEM_OFFS(_r6,buf)"\n\t" \
/*mm7={0x7FFF}x4 \
mm0=max(abs(mm0),abs(mm1))-0x7FFF*/ \
"pcmpeqb %%mm7,%%mm7\n\t" \
@@ -343,14 +345,14 @@ unsigned oc_enc_frag_sad2_thresh_mmxext(const unsigned char *_src,
"pmaxsw %%mm5,%%mm4\n\t" \
"paddw %%mm3,%%mm6\n\t" \
"paddw %%mm5,%%mm1\n\t" \
- "movq "_r7"(%[buf]),%%mm3\n\t" \
+ "movq "OC_MEM_OFFS(_r7,buf)",%%mm3\n\t" \
/*Performs the second part of the final stage of the Hadamard transform and
summing of absolute values.*/
#define OC_HADAMARD_C_ABS_ACCUM_B_8x4(_r6,_r7) \
"#OC_HADAMARD_C_ABS_ACCUM_B_8x4\n\t" \
"paddsw %%mm7,%%mm6\n\t" \
- "movq "_r6"(%[buf]),%%mm5\n\t" \
+ "movq "OC_MEM_OFFS(_r6,buf)",%%mm5\n\t" \
"paddsw %%mm7,%%mm1\n\t" \
"psubw %%mm6,%%mm2\n\t" \
"psubw %%mm1,%%mm4\n\t" \
@@ -391,7 +393,7 @@ unsigned oc_enc_frag_sad2_thresh_mmxext(const unsigned char *_src,
#define OC_TRANSPOSE_4x4x2(_off) \
"#OC_TRANSPOSE_4x4x2\n\t" \
/*First 4x4 transpose:*/ \
- "movq %%mm5,0x10+"_off"(%[buf])\n\t" \
+ "movq %%mm5,"OC_MEM_OFFS(0x10+(_off),buf)"\n\t" \
/*mm0 = e3 e2 e1 e0 \
mm1 = f3 f2 f1 f0 \
mm2 = g3 g2 g1 g0 \
@@ -411,13 +413,13 @@ unsigned oc_enc_frag_sad2_thresh_mmxext(const unsigned char *_src,
"punpckhdq %%mm2,%%mm1\n\t" \
"movq %%mm3,%%mm2\n\t" \
"punpckhdq %%mm5,%%mm3\n\t" \
- "movq %%mm0,0x40+"_off"(%[buf])\n\t" \
+ "movq %%mm0,"OC_MEM_OFFS(0x40+(_off),buf)"\n\t" \
"punpckldq %%mm5,%%mm2\n\t" \
/*mm0 = h0 g0 f0 e0 \
mm1 = h1 g1 f1 e1 \
mm2 = h2 g2 f2 e2 \
mm3 = h3 g3 f3 e3*/ \
- "movq 0x10+"_off"(%[buf]),%%mm5\n\t" \
+ "movq "OC_MEM_OFFS(0x10+(_off),buf)",%%mm5\n\t" \
/*Second 4x4 transpose:*/ \
/*mm4 = a3 a2 a1 a0 \
mm5 = b3 b2 b1 b0 \
@@ -425,11 +427,11 @@ unsigned oc_enc_frag_sad2_thresh_mmxext(const unsigned char *_src,
mm7 = d3 d2 d1 d0*/ \
"movq %%mm6,%%mm0\n\t" \
"punpcklwd %%mm7,%%mm6\n\t" \
- "movq %%mm1,0x50+"_off"(%[buf])\n\t" \
+ "movq %%mm1,"OC_MEM_OFFS(0x50+(_off),buf)"\n\t" \
"punpckhwd %%mm7,%%mm0\n\t" \
"movq %%mm4,%%mm7\n\t" \
"punpcklwd %%mm5,%%mm4\n\t" \
- "movq %%mm2,0x60+"_off"(%[buf])\n\t" \
+ "movq %%mm2,"OC_MEM_OFFS(0x60+(_off),buf)"\n\t" \
"punpckhwd %%mm5,%%mm7\n\t" \
/*mm4 = b1 a1 b0 a0 \
mm7 = b3 a3 b2 a2 \
@@ -437,7 +439,7 @@ unsigned oc_enc_frag_sad2_thresh_mmxext(const unsigned char *_src,
mm0 = d3 c3 d2 c2*/ \
"movq %%mm4,%%mm5\n\t" \
"punpckldq %%mm6,%%mm4\n\t" \
- "movq %%mm3,0x70+"_off"(%[buf])\n\t" \
+ "movq %%mm3,"OC_MEM_OFFS(0x70+(_off),buf)"\n\t" \
"punpckhdq %%mm6,%%mm5\n\t" \
"movq %%mm7,%%mm6\n\t" \
"punpckhdq %%mm0,%%mm7\n\t" \
@@ -447,100 +449,102 @@ unsigned oc_enc_frag_sad2_thresh_mmxext(const unsigned char *_src,
mm6 = d2 c2 b2 a2 \
mm7 = d3 c3 b3 a3*/ \
-static unsigned oc_int_frag_satd_thresh_mmxext(const unsigned char *_src,
- int _src_ystride,const unsigned char *_ref,int _ref_ystride,unsigned _thresh){
- OC_ALIGN8(ogg_int16_t buf[64]);
- ogg_int16_t *bufp;
- unsigned ret;
- unsigned ret2;
- bufp=buf;
+static unsigned oc_int_frag_satd_mmxext(int *_dc,
+ const unsigned char *_src,int _src_ystride,
+ const unsigned char *_ref,int _ref_ystride){
+ OC_ALIGN8(ogg_int16_t buf[64]);
+ unsigned ret;
+ unsigned ret2;
+ int dc;
__asm__ __volatile__(
- OC_LOAD_SUB_8x4("0x00")
+ OC_LOAD_SUB_8x4(0x00)
OC_HADAMARD_8x4
- OC_TRANSPOSE_4x4x2("0x00")
+ OC_TRANSPOSE_4x4x2(0x00)
/*Finish swapping out this 8x4 block to make room for the next one.
mm0...mm3 have been swapped out already.*/
- "movq %%mm4,0x00(%[buf])\n\t"
- "movq %%mm5,0x10(%[buf])\n\t"
- "movq %%mm6,0x20(%[buf])\n\t"
- "movq %%mm7,0x30(%[buf])\n\t"
- OC_LOAD_SUB_8x4("0x04")
+ "movq %%mm4,"OC_MEM_OFFS(0x00,buf)"\n\t"
+ "movq %%mm5,"OC_MEM_OFFS(0x10,buf)"\n\t"
+ "movq %%mm6,"OC_MEM_OFFS(0x20,buf)"\n\t"
+ "movq %%mm7,"OC_MEM_OFFS(0x30,buf)"\n\t"
+ OC_LOAD_SUB_8x4(0x04)
OC_HADAMARD_8x4
- OC_TRANSPOSE_4x4x2("0x08")
+ OC_TRANSPOSE_4x4x2(0x08)
/*Here the first 4x4 block of output from the last transpose is the second
4x4 block of input for the next transform.
We have cleverly arranged that it already be in the appropriate place, so
we only have to do half the loads.*/
- "movq 0x10(%[buf]),%%mm1\n\t"
- "movq 0x20(%[buf]),%%mm2\n\t"
- "movq 0x30(%[buf]),%%mm3\n\t"
- "movq 0x00(%[buf]),%%mm0\n\t"
- OC_HADAMARD_ABS_ACCUM_8x4("0x28","0x38")
+ "movq "OC_MEM_OFFS(0x10,buf)",%%mm1\n\t"
+ "movq "OC_MEM_OFFS(0x20,buf)",%%mm2\n\t"
+ "movq "OC_MEM_OFFS(0x30,buf)",%%mm3\n\t"
+ "movq "OC_MEM_OFFS(0x00,buf)",%%mm0\n\t"
+ /*We split out the stages here so we can save the DC coefficient in the
+ middle.*/
+ OC_HADAMARD_AB_8x4
+ OC_HADAMARD_C_ABS_ACCUM_A_8x4(0x28,0x38)
+ "movd %%mm1,%[dc]\n\t"
+ OC_HADAMARD_C_ABS_ACCUM_B_8x4(0x28,0x38)
/*Up to this point, everything fit in 16 bits (8 input + 1 for the
difference + 2*3 for the two 8-point 1-D Hadamards - 1 for the abs - 1
for the factor of two we dropped + 3 for the vertical accumulation).
Now we finally have to promote things to dwords.
We break this part out of OC_HADAMARD_ABS_ACCUM_8x4 to hide the long
latency of pmaddwd by starting the next series of loads now.*/
- "mov %[thresh],%[ret2]\n\t"
"pmaddwd %%mm7,%%mm0\n\t"
- "movq 0x50(%[buf]),%%mm1\n\t"
- "movq 0x58(%[buf]),%%mm5\n\t"
+ "movq "OC_MEM_OFFS(0x50,buf)",%%mm1\n\t"
+ "movq "OC_MEM_OFFS(0x58,buf)",%%mm5\n\t"
"movq %%mm0,%%mm4\n\t"
- "movq 0x60(%[buf]),%%mm2\n\t"
+ "movq "OC_MEM_OFFS(0x60,buf)",%%mm2\n\t"
"punpckhdq %%mm0,%%mm0\n\t"
- "movq 0x68(%[buf]),%%mm6\n\t"
+ "movq "OC_MEM_OFFS(0x68,buf)",%%mm6\n\t"
"paddd %%mm0,%%mm4\n\t"
- "movq 0x70(%[buf]),%%mm3\n\t"
- "movd %%mm4,%[ret]\n\t"
- "movq 0x78(%[buf]),%%mm7\n\t"
- /*The sums produced by OC_HADAMARD_ABS_ACCUM_8x4 each have an extra 4
- added to them, and a factor of two removed; correct the final sum here.*/
- "lea -32(%[ret],%[ret]),%[ret]\n\t"
- "movq 0x40(%[buf]),%%mm0\n\t"
- "cmp %[ret2],%[ret]\n\t"
- "movq 0x48(%[buf]),%%mm4\n\t"
- "jae 1f\n\t"
- OC_HADAMARD_ABS_ACCUM_8x4("0x68","0x78")
+ "movq "OC_MEM_OFFS(0x70,buf)",%%mm3\n\t"
+ "movd %%mm4,%[ret2]\n\t"
+ "movq "OC_MEM_OFFS(0x78,buf)",%%mm7\n\t"
+ "movq "OC_MEM_OFFS(0x40,buf)",%%mm0\n\t"
+ "movq "OC_MEM_OFFS(0x48,buf)",%%mm4\n\t"
+ OC_HADAMARD_ABS_ACCUM_8x4(0x68,0x78)
"pmaddwd %%mm7,%%mm0\n\t"
- /*There isn't much to stick in here to hide the latency this time, but the
- alternative to pmaddwd is movq->punpcklwd->punpckhwd->paddd, whose
- latency is even worse.*/
- "sub $32,%[ret]\n\t"
+ /*Subtract abs(dc) from 2*ret2.*/
+ "movsx %w[dc],%[dc]\n\t"
+ "cdq\n\t"
+ "lea (%[ret],%[ret2],2),%[ret2]\n\t"
"movq %%mm0,%%mm4\n\t"
"punpckhdq %%mm0,%%mm0\n\t"
+ "xor %[dc],%[ret]\n\t"
"paddd %%mm0,%%mm4\n\t"
- "movd %%mm4,%[ret2]\n\t"
- "lea (%[ret],%[ret2],2),%[ret]\n\t"
- ".p2align 4,,15\n\t"
- "1:\n\t"
- /*Although it looks like we're using 7 registers here, gcc can alias %[ret]
+ /*The sums produced by OC_HADAMARD_ABS_ACCUM_8x4 each have an extra 4
+ added to them, a factor of two removed, and the DC value included;
+ correct the final sum here.*/
+ "sub %[ret],%[ret2]\n\t"
+ "movd %%mm4,%[ret]\n\t"
+ "lea -64(%[ret2],%[ret],2),%[ret]\n\t"
+ /*Although it looks like we're using 8 registers here, gcc can alias %[ret]
and %[ret2] with some of the inputs, since for once we don't write to
- them until after we're done using everything but %[buf] (which is also
- listed as an output to ensure gcc _doesn't_ alias them against it).*/
+ them until after we're done using everything but %[buf].*/
/*Note that _src_ystride and _ref_ystride must be given non-overlapping
constraints, otherewise if gcc can prove they're equal it will allocate
them to the same register (which is bad); _src and _ref face a similar
problem, though those are never actually the same.*/
- :[ret]"=a"(ret),[ret2]"=r"(ret2),[buf]"+r"(bufp)
+ :[ret]"=d"(ret),[ret2]"=r"(ret2),[dc]"=a"(dc),
+ [buf]"=m"(OC_ARRAY_OPERAND(ogg_int16_t,buf,64))
:[src]"r"(_src),[src_ystride]"c"((ptrdiff_t)_src_ystride),
- [ref]"r"(_ref),[ref_ystride]"d"((ptrdiff_t)_ref_ystride),
- [thresh]"m"(_thresh)
+ [ref]"r"(_ref),[ref_ystride]"d"((ptrdiff_t)_ref_ystride)
/*We have to use neg, so we actually clobber the condition codes for once
(not to mention cmp, sub, and add).*/
:"cc"
);
+ *_dc=dc;
return ret;
}
-unsigned oc_enc_frag_satd_thresh_mmxext(const unsigned char *_src,
- const unsigned char *_ref,int _ystride,unsigned _thresh){
- return oc_int_frag_satd_thresh_mmxext(_src,_ystride,_ref,_ystride,_thresh);
+unsigned oc_enc_frag_satd_mmxext(int *_dc,const unsigned char *_src,
+ const unsigned char *_ref,int _ystride){
+ return oc_int_frag_satd_mmxext(_dc,_src,_ystride,_ref,_ystride);
}
/*Our internal implementation of frag_copy2 takes an extra stride parameter so
- we can share code with oc_enc_frag_satd2_thresh_mmxext().*/
-static void oc_int_frag_copy2_mmxext(unsigned char *_dst,int _dst_ystride,
+ we can share code with oc_enc_frag_satd2_mmxext().*/
+void oc_int_frag_copy2_mmxext(unsigned char *_dst,int _dst_ystride,
const unsigned char *_src1,const unsigned char *_src2,int _src_ystride){
__asm__ __volatile__(
/*Load the first 3 rows.*/
@@ -649,55 +653,53 @@ static void oc_int_frag_copy2_mmxext(unsigned char *_dst,int _dst_ystride,
"psubb %%mm4,%%mm2\n\t"
/*%%mm2 (row 7) is done, write it out.*/
"movq %%mm2,(%[dst],%[dst_ystride])\n\t"
- :[dst]"+r"(_dst),[src1]"+%r"(_src1),[src2]"+r"(_src2)
+ :[dst]"+r"(_dst),[src1]"+r"(_src1),[src2]"+r"(_src2)
:[dst_ystride]"r"((ptrdiff_t)_dst_ystride),
[src_ystride]"r"((ptrdiff_t)_src_ystride)
:"memory"
);
}
-unsigned oc_enc_frag_satd2_thresh_mmxext(const unsigned char *_src,
- const unsigned char *_ref1,const unsigned char *_ref2,int _ystride,
- unsigned _thresh){
+unsigned oc_enc_frag_satd2_mmxext(int *_dc,const unsigned char *_src,
+ const unsigned char *_ref1,const unsigned char *_ref2,int _ystride){
OC_ALIGN8(unsigned char ref[64]);
oc_int_frag_copy2_mmxext(ref,8,_ref1,_ref2,_ystride);
- return oc_int_frag_satd_thresh_mmxext(_src,_ystride,ref,8,_thresh);
+ return oc_int_frag_satd_mmxext(_dc,_src,_ystride,ref,8);
}
-unsigned oc_enc_frag_intra_satd_mmxext(const unsigned char *_src,
- int _ystride){
- OC_ALIGN8(ogg_int16_t buf[64]);
- ogg_int16_t *bufp;
- unsigned ret;
- unsigned ret2;
- bufp=buf;
+unsigned oc_enc_frag_intra_satd_mmxext(int *_dc,
+ const unsigned char *_src,int _ystride){
+ OC_ALIGN8(ogg_int16_t buf[64]);
+ unsigned ret;
+ unsigned ret2;
+ int dc;
__asm__ __volatile__(
- OC_LOAD_8x4("0x00")
+ OC_LOAD_8x4(0x00)
OC_HADAMARD_8x4
- OC_TRANSPOSE_4x4x2("0x00")
+ OC_TRANSPOSE_4x4x2(0x00)
/*Finish swapping out this 8x4 block to make room for the next one.
mm0...mm3 have been swapped out already.*/
- "movq %%mm4,0x00(%[buf])\n\t"
- "movq %%mm5,0x10(%[buf])\n\t"
- "movq %%mm6,0x20(%[buf])\n\t"
- "movq %%mm7,0x30(%[buf])\n\t"
- OC_LOAD_8x4("0x04")
+ "movq %%mm4,"OC_MEM_OFFS(0x00,buf)"\n\t"
+ "movq %%mm5,"OC_MEM_OFFS(0x10,buf)"\n\t"
+ "movq %%mm6,"OC_MEM_OFFS(0x20,buf)"\n\t"
+ "movq %%mm7,"OC_MEM_OFFS(0x30,buf)"\n\t"
+ OC_LOAD_8x4(0x04)
OC_HADAMARD_8x4
- OC_TRANSPOSE_4x4x2("0x08")
+ OC_TRANSPOSE_4x4x2(0x08)
/*Here the first 4x4 block of output from the last transpose is the second
4x4 block of input for the next transform.
We have cleverly arranged that it already be in the appropriate place, so
we only have to do half the loads.*/
- "movq 0x10(%[buf]),%%mm1\n\t"
- "movq 0x20(%[buf]),%%mm2\n\t"
- "movq 0x30(%[buf]),%%mm3\n\t"
- "movq 0x00(%[buf]),%%mm0\n\t"
+ "movq "OC_MEM_OFFS(0x10,buf)",%%mm1\n\t"
+ "movq "OC_MEM_OFFS(0x20,buf)",%%mm2\n\t"
+ "movq "OC_MEM_OFFS(0x30,buf)",%%mm3\n\t"
+ "movq "OC_MEM_OFFS(0x00,buf)",%%mm0\n\t"
/*We split out the stages here so we can save the DC coefficient in the
middle.*/
OC_HADAMARD_AB_8x4
- OC_HADAMARD_C_ABS_ACCUM_A_8x4("0x28","0x38")
- "movd %%mm1,%[ret]\n\t"
- OC_HADAMARD_C_ABS_ACCUM_B_8x4("0x28","0x38")
+ OC_HADAMARD_C_ABS_ACCUM_A_8x4(0x28,0x38)
+ "movd %%mm1,%[dc]\n\t"
+ OC_HADAMARD_C_ABS_ACCUM_B_8x4(0x28,0x38)
/*Up to this point, everything fit in 16 bits (8 input + 1 for the
difference + 2*3 for the two 8-point 1-D Hadamards - 1 for the abs - 1
for the factor of two we dropped + 3 for the vertical accumulation).
@@ -705,41 +707,43 @@ unsigned oc_enc_frag_intra_satd_mmxext(const unsigned char *_src,
We break this part out of OC_HADAMARD_ABS_ACCUM_8x4 to hide the long
latency of pmaddwd by starting the next series of loads now.*/
"pmaddwd %%mm7,%%mm0\n\t"
- "movq 0x50(%[buf]),%%mm1\n\t"
- "movq 0x58(%[buf]),%%mm5\n\t"
- "movq 0x60(%[buf]),%%mm2\n\t"
+ "movq "OC_MEM_OFFS(0x50,buf)",%%mm1\n\t"
+ "movq "OC_MEM_OFFS(0x58,buf)",%%mm5\n\t"
+ "movq "OC_MEM_OFFS(0x60,buf)",%%mm2\n\t"
"movq %%mm0,%%mm4\n\t"
- "movq 0x68(%[buf]),%%mm6\n\t"
+ "movq "OC_MEM_OFFS(0x68,buf)",%%mm6\n\t"
"punpckhdq %%mm0,%%mm0\n\t"
- "movq 0x70(%[buf]),%%mm3\n\t"
+ "movq "OC_MEM_OFFS(0x70,buf)",%%mm3\n\t"
"paddd %%mm0,%%mm4\n\t"
- "movq 0x78(%[buf]),%%mm7\n\t"
- "movd %%mm4,%[ret2]\n\t"
- "movq 0x40(%[buf]),%%mm0\n\t"
- "movq 0x48(%[buf]),%%mm4\n\t"
- OC_HADAMARD_ABS_ACCUM_8x4("0x68","0x78")
+ "movq "OC_MEM_OFFS(0x78,buf)",%%mm7\n\t"
+ "movd %%mm4,%[ret]\n\t"
+ "movq "OC_MEM_OFFS(0x40,buf)",%%mm0\n\t"
+ "movq "OC_MEM_OFFS(0x48,buf)",%%mm4\n\t"
+ OC_HADAMARD_ABS_ACCUM_8x4(0x68,0x78)
"pmaddwd %%mm7,%%mm0\n\t"
/*We assume that the DC coefficient is always positive (which is true,
because the input to the INTRA transform was not a difference).*/
- "movzx %w[ret],%[ret]\n\t"
- "add %[ret2],%[ret2]\n\t"
- "sub %[ret],%[ret2]\n\t"
+ "movzx %w[dc],%[dc]\n\t"
+ "add %[ret],%[ret]\n\t"
+ "sub %[dc],%[ret]\n\t"
"movq %%mm0,%%mm4\n\t"
"punpckhdq %%mm0,%%mm0\n\t"
"paddd %%mm0,%%mm4\n\t"
- "movd %%mm4,%[ret]\n\t"
- "lea -64(%[ret2],%[ret],2),%[ret]\n\t"
- /*Although it looks like we're using 7 registers here, gcc can alias %[ret]
+ "movd %%mm4,%[ret2]\n\t"
+ "lea -64(%[ret],%[ret2],2),%[ret]\n\t"
+ /*Although it looks like we're using 8 registers here, gcc can alias %[ret]
and %[ret2] with some of the inputs, since for once we don't write to
them until after we're done using everything but %[buf] (which is also
listed as an output to ensure gcc _doesn't_ alias them against it).*/
- :[ret]"=a"(ret),[ret2]"=r"(ret2),[buf]"+r"(bufp)
+ :[ret]"=a"(ret),[ret2]"=r"(ret2),[dc]"=r"(dc),
+ [buf]"=m"(OC_ARRAY_OPERAND(ogg_int16_t,buf,64))
:[src]"r"(_src),[src4]"r"(_src+4*_ystride),
[ystride]"r"((ptrdiff_t)_ystride),[ystride3]"r"((ptrdiff_t)3*_ystride)
/*We have to use sub, so we actually clobber the condition codes for once
(not to mention add).*/
:"cc"
);
+ *_dc=dc;
return ret;
}
diff --git a/thirdparty/libtheora/x86/mmxfdct.c b/thirdparty/libtheora/x86/mmxfdct.c
index 211875255e..17668358b8 100644
--- a/thirdparty/libtheora/x86/mmxfdct.c
+++ b/thirdparty/libtheora/x86/mmxfdct.c
@@ -12,6 +12,7 @@
/*MMX fDCT implementation for x86_32*/
/*$Id: fdct_ses2.c 14579 2008-03-12 06:42:40Z xiphmont $*/
#include "x86enc.h"
+#include "x86zigzag.h"
#if defined(OC_X86_ASM)
@@ -462,8 +463,9 @@
mm7 = d3 c3 b3 a3*/ \
/*MMX implementation of the fDCT.*/
-void oc_enc_fdct8x8_mmx(ogg_int16_t _y[64],const ogg_int16_t _x[64]){
- ptrdiff_t a;
+void oc_enc_fdct8x8_mmxext(ogg_int16_t _y[64],const ogg_int16_t _x[64]){
+ OC_ALIGN8(ogg_int16_t buf[64]);
+ ptrdiff_t a;
__asm__ __volatile__(
/*Add two extra bits of working precision to improve accuracy; any more and
we could overflow.*/
@@ -586,77 +588,88 @@ void oc_enc_fdct8x8_mmx(ogg_int16_t _y[64],const ogg_int16_t _x[64]){
"movq 0x30(%[y]),%%mm3\n\t"
OC_FDCT_STAGE1_8x4
OC_FDCT8x4("0x00","0x10","0x20","0x30","0x08","0x18","0x28","0x38")
- OC_TRANSPOSE8x4("0x00","0x10","0x20","0x30","0x08","0x18","0x28","0x38")
- /*mm0={-2}x4*/
- "pcmpeqw %%mm0,%%mm0\n\t"
- "paddw %%mm0,%%mm0\n\t"
- /*Round the results.*/
- "psubw %%mm0,%%mm1\n\t"
- "psubw %%mm0,%%mm2\n\t"
- "psraw $2,%%mm1\n\t"
- "psubw %%mm0,%%mm3\n\t"
- "movq %%mm1,0x18(%[y])\n\t"
- "psraw $2,%%mm2\n\t"
- "psubw %%mm0,%%mm4\n\t"
- "movq 0x08(%[y]),%%mm1\n\t"
- "psraw $2,%%mm3\n\t"
- "psubw %%mm0,%%mm5\n\t"
+ /*mm2={-2}x4*/
+ "pcmpeqw %%mm2,%%mm2\n\t"
+ "paddw %%mm2,%%mm2\n\t"
+ /*Round and store the results (no transpose).*/
+ "movq 0x10(%[y]),%%mm7\n\t"
+ "psubw %%mm2,%%mm4\n\t"
+ "psubw %%mm2,%%mm6\n\t"
"psraw $2,%%mm4\n\t"
- "psubw %%mm0,%%mm6\n\t"
- "psraw $2,%%mm5\n\t"
- "psubw %%mm0,%%mm7\n\t"
+ "psubw %%mm2,%%mm0\n\t"
+ "movq %%mm4,"OC_MEM_OFFS(0x00,buf)"\n\t"
+ "movq 0x30(%[y]),%%mm4\n\t"
"psraw $2,%%mm6\n\t"
- "psubw %%mm0,%%mm1\n\t"
+ "psubw %%mm2,%%mm5\n\t"
+ "movq %%mm6,"OC_MEM_OFFS(0x20,buf)"\n\t"
+ "psraw $2,%%mm0\n\t"
+ "psubw %%mm2,%%mm3\n\t"
+ "movq %%mm0,"OC_MEM_OFFS(0x40,buf)"\n\t"
+ "psraw $2,%%mm5\n\t"
+ "psubw %%mm2,%%mm1\n\t"
+ "movq %%mm5,"OC_MEM_OFFS(0x50,buf)"\n\t"
+ "psraw $2,%%mm3\n\t"
+ "psubw %%mm2,%%mm7\n\t"
+ "movq %%mm3,"OC_MEM_OFFS(0x60,buf)"\n\t"
+ "psraw $2,%%mm1\n\t"
+ "psubw %%mm2,%%mm4\n\t"
+ "movq %%mm1,"OC_MEM_OFFS(0x70,buf)"\n\t"
"psraw $2,%%mm7\n\t"
+ "movq %%mm7,"OC_MEM_OFFS(0x10,buf)"\n\t"
+ "psraw $2,%%mm4\n\t"
+ "movq %%mm4,"OC_MEM_OFFS(0x30,buf)"\n\t"
+ /*Load the next block.*/
"movq 0x40(%[y]),%%mm0\n\t"
- "psraw $2,%%mm1\n\t"
- "movq %%mm7,0x30(%[y])\n\t"
"movq 0x78(%[y]),%%mm7\n\t"
- "movq %%mm1,0x08(%[y])\n\t"
"movq 0x50(%[y]),%%mm1\n\t"
- "movq %%mm6,0x20(%[y])\n\t"
"movq 0x68(%[y]),%%mm6\n\t"
- "movq %%mm2,0x28(%[y])\n\t"
"movq 0x60(%[y]),%%mm2\n\t"
- "movq %%mm5,0x10(%[y])\n\t"
"movq 0x58(%[y]),%%mm5\n\t"
- "movq %%mm3,0x38(%[y])\n\t"
"movq 0x70(%[y]),%%mm3\n\t"
- "movq %%mm4,0x00(%[y])\n\t"
"movq 0x48(%[y]),%%mm4\n\t"
OC_FDCT_STAGE1_8x4
OC_FDCT8x4("0x40","0x50","0x60","0x70","0x48","0x58","0x68","0x78")
- OC_TRANSPOSE8x4("0x40","0x50","0x60","0x70","0x48","0x58","0x68","0x78")
- /*mm0={-2}x4*/
- "pcmpeqw %%mm0,%%mm0\n\t"
- "paddw %%mm0,%%mm0\n\t"
- /*Round the results.*/
- "psubw %%mm0,%%mm1\n\t"
- "psubw %%mm0,%%mm2\n\t"
- "psraw $2,%%mm1\n\t"
- "psubw %%mm0,%%mm3\n\t"
- "movq %%mm1,0x58(%[y])\n\t"
- "psraw $2,%%mm2\n\t"
- "psubw %%mm0,%%mm4\n\t"
- "movq 0x48(%[y]),%%mm1\n\t"
- "psraw $2,%%mm3\n\t"
- "psubw %%mm0,%%mm5\n\t"
- "movq %%mm2,0x68(%[y])\n\t"
+ /*mm2={-2}x4*/
+ "pcmpeqw %%mm2,%%mm2\n\t"
+ "paddw %%mm2,%%mm2\n\t"
+ /*Round and store the results (no transpose).*/
+ "movq 0x50(%[y]),%%mm7\n\t"
+ "psubw %%mm2,%%mm4\n\t"
+ "psubw %%mm2,%%mm6\n\t"
"psraw $2,%%mm4\n\t"
- "psubw %%mm0,%%mm6\n\t"
- "movq %%mm3,0x78(%[y])\n\t"
- "psraw $2,%%mm5\n\t"
- "psubw %%mm0,%%mm7\n\t"
- "movq %%mm4,0x40(%[y])\n\t"
+ "psubw %%mm2,%%mm0\n\t"
+ "movq %%mm4,"OC_MEM_OFFS(0x08,buf)"\n\t"
+ "movq 0x70(%[y]),%%mm4\n\t"
"psraw $2,%%mm6\n\t"
- "psubw %%mm0,%%mm1\n\t"
- "movq %%mm5,0x50(%[y])\n\t"
- "psraw $2,%%mm7\n\t"
- "movq %%mm6,0x60(%[y])\n\t"
+ "psubw %%mm2,%%mm5\n\t"
+ "movq %%mm6,"OC_MEM_OFFS(0x28,buf)"\n\t"
+ "psraw $2,%%mm0\n\t"
+ "psubw %%mm2,%%mm3\n\t"
+ "movq %%mm0,"OC_MEM_OFFS(0x48,buf)"\n\t"
+ "psraw $2,%%mm5\n\t"
+ "psubw %%mm2,%%mm1\n\t"
+ "movq %%mm5,"OC_MEM_OFFS(0x58,buf)"\n\t"
+ "psraw $2,%%mm3\n\t"
+ "psubw %%mm2,%%mm7\n\t"
+ "movq %%mm3,"OC_MEM_OFFS(0x68,buf)"\n\t"
"psraw $2,%%mm1\n\t"
- "movq %%mm7,0x70(%[y])\n\t"
- "movq %%mm1,0x48(%[y])\n\t"
- :[a]"=&r"(a)
+ "psubw %%mm2,%%mm4\n\t"
+ "movq %%mm1,"OC_MEM_OFFS(0x78,buf)"\n\t"
+ "psraw $2,%%mm7\n\t"
+ "movq %%mm7,"OC_MEM_OFFS(0x18,buf)"\n\t"
+ "psraw $2,%%mm4\n\t"
+ "movq %%mm4,"OC_MEM_OFFS(0x38,buf)"\n\t"
+ /*Final transpose and zig-zag.*/
+#define OC_ZZ_LOAD_ROW_LO(_row,_reg) \
+ "movq "OC_MEM_OFFS(16*_row,buf)","_reg"\n\t" \
+
+#define OC_ZZ_LOAD_ROW_HI(_row,_reg) \
+ "movq "OC_MEM_OFFS(16*_row+8,buf)","_reg"\n\t" \
+
+ OC_TRANSPOSE_ZIG_ZAG_MMXEXT
+#undef OC_ZZ_LOAD_ROW_LO
+#undef OC_ZZ_LOAD_ROW_HI
+ :[a]"=&r"(a),[buf]"=m"(OC_ARRAY_OPERAND(ogg_int16_t,buf,64))
:[y]"r"(_y),[x]"r"(_x)
:"memory"
);
diff --git a/thirdparty/libtheora/x86/mmxfrag.c b/thirdparty/libtheora/x86/mmxfrag.c
index 2c732939c3..b3ec508956 100644
--- a/thirdparty/libtheora/x86/mmxfrag.c
+++ b/thirdparty/libtheora/x86/mmxfrag.c
@@ -11,7 +11,7 @@
********************************************************************
function:
- last mod: $Id: mmxfrag.c 16503 2009-08-22 18:14:02Z giles $
+ last mod: $Id$
********************************************************************/
@@ -22,17 +22,92 @@
The iteration each instruction belongs to is marked in the comments as #i.*/
#include <stddef.h>
#include "x86int.h"
-#include "mmxfrag.h"
#if defined(OC_X86_ASM)
/*Copies an 8x8 block of pixels from _src to _dst, assuming _ystride bytes
between rows.*/
+# define OC_FRAG_COPY_MMX(_dst,_src,_ystride) \
+ do{ \
+ const unsigned char *src; \
+ unsigned char *dst; \
+ ptrdiff_t ystride3; \
+ src=(_src); \
+ dst=(_dst); \
+ __asm__ __volatile__( \
+ /*src+0*ystride*/ \
+ "movq (%[src]),%%mm0\n\t" \
+ /*src+1*ystride*/ \
+ "movq (%[src],%[ystride]),%%mm1\n\t" \
+ /*ystride3=ystride*3*/ \
+ "lea (%[ystride],%[ystride],2),%[ystride3]\n\t" \
+ /*src+2*ystride*/ \
+ "movq (%[src],%[ystride],2),%%mm2\n\t" \
+ /*src+3*ystride*/ \
+ "movq (%[src],%[ystride3]),%%mm3\n\t" \
+ /*dst+0*ystride*/ \
+ "movq %%mm0,(%[dst])\n\t" \
+ /*dst+1*ystride*/ \
+ "movq %%mm1,(%[dst],%[ystride])\n\t" \
+ /*Pointer to next 4.*/ \
+ "lea (%[src],%[ystride],4),%[src]\n\t" \
+ /*dst+2*ystride*/ \
+ "movq %%mm2,(%[dst],%[ystride],2)\n\t" \
+ /*dst+3*ystride*/ \
+ "movq %%mm3,(%[dst],%[ystride3])\n\t" \
+ /*Pointer to next 4.*/ \
+ "lea (%[dst],%[ystride],4),%[dst]\n\t" \
+ /*src+0*ystride*/ \
+ "movq (%[src]),%%mm0\n\t" \
+ /*src+1*ystride*/ \
+ "movq (%[src],%[ystride]),%%mm1\n\t" \
+ /*src+2*ystride*/ \
+ "movq (%[src],%[ystride],2),%%mm2\n\t" \
+ /*src+3*ystride*/ \
+ "movq (%[src],%[ystride3]),%%mm3\n\t" \
+ /*dst+0*ystride*/ \
+ "movq %%mm0,(%[dst])\n\t" \
+ /*dst+1*ystride*/ \
+ "movq %%mm1,(%[dst],%[ystride])\n\t" \
+ /*dst+2*ystride*/ \
+ "movq %%mm2,(%[dst],%[ystride],2)\n\t" \
+ /*dst+3*ystride*/ \
+ "movq %%mm3,(%[dst],%[ystride3])\n\t" \
+ :[dst]"+r"(dst),[src]"+r"(src),[ystride3]"=&r"(ystride3) \
+ :[ystride]"r"((ptrdiff_t)(_ystride)) \
+ :"memory" \
+ ); \
+ } \
+ while(0)
+
+/*Copies an 8x8 block of pixels from _src to _dst, assuming _ystride bytes
+ between rows.*/
void oc_frag_copy_mmx(unsigned char *_dst,
const unsigned char *_src,int _ystride){
OC_FRAG_COPY_MMX(_dst,_src,_ystride);
}
+/*Copies the fragments specified by the lists of fragment indices from one
+ frame to another.
+ _dst_frame: The reference frame to copy to.
+ _src_frame: The reference frame to copy from.
+ _ystride: The row stride of the reference frames.
+ _fragis: A pointer to a list of fragment indices.
+ _nfragis: The number of fragment indices to copy.
+ _frag_buf_offs: The offsets of fragments in the reference frames.*/
+void oc_frag_copy_list_mmx(unsigned char *_dst_frame,
+ const unsigned char *_src_frame,int _ystride,
+ const ptrdiff_t *_fragis,ptrdiff_t _nfragis,const ptrdiff_t *_frag_buf_offs){
+ ptrdiff_t fragii;
+ for(fragii=0;fragii<_nfragis;fragii++){
+ ptrdiff_t frag_buf_off;
+ frag_buf_off=_frag_buf_offs[_fragis[fragii]];
+ OC_FRAG_COPY_MMX(_dst_frame+frag_buf_off,
+ _src_frame+frag_buf_off,_ystride);
+ }
+}
+
+
void oc_frag_recon_intra_mmx(unsigned char *_dst,int _ystride,
const ogg_int16_t *_residue){
__asm__ __volatile__(
@@ -280,7 +355,7 @@ void oc_frag_recon_inter2_mmx(unsigned char *_dst,const unsigned char *_src1,
/*Advance dest ptr.*/
"lea (%[dst],%[ystride],2),%[dst]\n\t"
:[dst]"+r"(_dst),[residue]"+r"(_residue),
- [src1]"+%r"(_src1),[src2]"+r"(_src2)
+ [src1]"+r"(_src1),[src2]"+r"(_src2)
:[ystride]"r"((ptrdiff_t)_ystride)
:"memory"
);
diff --git a/thirdparty/libtheora/x86/mmxfrag.h b/thirdparty/libtheora/x86/mmxfrag.h
deleted file mode 100644
index a398427629..0000000000
--- a/thirdparty/libtheora/x86/mmxfrag.h
+++ /dev/null
@@ -1,64 +0,0 @@
-#if !defined(_x86_mmxfrag_H)
-# define _x86_mmxfrag_H (1)
-# include <stddef.h>
-# include "x86int.h"
-
-#if defined(OC_X86_ASM)
-
-/*Copies an 8x8 block of pixels from _src to _dst, assuming _ystride bytes
- between rows.*/
-#define OC_FRAG_COPY_MMX(_dst,_src,_ystride) \
- do{ \
- const unsigned char *src; \
- unsigned char *dst; \
- ptrdiff_t ystride3; \
- src=(_src); \
- dst=(_dst); \
- __asm__ __volatile__( \
- /*src+0*ystride*/ \
- "movq (%[src]),%%mm0\n\t" \
- /*src+1*ystride*/ \
- "movq (%[src],%[ystride]),%%mm1\n\t" \
- /*ystride3=ystride*3*/ \
- "lea (%[ystride],%[ystride],2),%[ystride3]\n\t" \
- /*src+2*ystride*/ \
- "movq (%[src],%[ystride],2),%%mm2\n\t" \
- /*src+3*ystride*/ \
- "movq (%[src],%[ystride3]),%%mm3\n\t" \
- /*dst+0*ystride*/ \
- "movq %%mm0,(%[dst])\n\t" \
- /*dst+1*ystride*/ \
- "movq %%mm1,(%[dst],%[ystride])\n\t" \
- /*Pointer to next 4.*/ \
- "lea (%[src],%[ystride],4),%[src]\n\t" \
- /*dst+2*ystride*/ \
- "movq %%mm2,(%[dst],%[ystride],2)\n\t" \
- /*dst+3*ystride*/ \
- "movq %%mm3,(%[dst],%[ystride3])\n\t" \
- /*Pointer to next 4.*/ \
- "lea (%[dst],%[ystride],4),%[dst]\n\t" \
- /*src+0*ystride*/ \
- "movq (%[src]),%%mm0\n\t" \
- /*src+1*ystride*/ \
- "movq (%[src],%[ystride]),%%mm1\n\t" \
- /*src+2*ystride*/ \
- "movq (%[src],%[ystride],2),%%mm2\n\t" \
- /*src+3*ystride*/ \
- "movq (%[src],%[ystride3]),%%mm3\n\t" \
- /*dst+0*ystride*/ \
- "movq %%mm0,(%[dst])\n\t" \
- /*dst+1*ystride*/ \
- "movq %%mm1,(%[dst],%[ystride])\n\t" \
- /*dst+2*ystride*/ \
- "movq %%mm2,(%[dst],%[ystride],2)\n\t" \
- /*dst+3*ystride*/ \
- "movq %%mm3,(%[dst],%[ystride3])\n\t" \
- :[dst]"+r"(dst),[src]"+r"(src),[ystride3]"=&r"(ystride3) \
- :[ystride]"r"((ptrdiff_t)(_ystride)) \
- :"memory" \
- ); \
- } \
- while(0)
-
-# endif
-#endif
diff --git a/thirdparty/libtheora/x86/mmxidct.c b/thirdparty/libtheora/x86/mmxidct.c
index 76424e6364..b8e3077066 100644
--- a/thirdparty/libtheora/x86/mmxidct.c
+++ b/thirdparty/libtheora/x86/mmxidct.c
@@ -11,7 +11,7 @@
********************************************************************
function:
- last mod: $Id: mmxidct.c 16503 2009-08-22 18:14:02Z giles $
+ last mod: $Id$
********************************************************************/
@@ -30,89 +30,66 @@
-/*A table of constants used by the MMX routines.*/
-static const ogg_uint16_t __attribute__((aligned(8),used))
- OC_IDCT_CONSTS[(7+1)*4]={
- (ogg_uint16_t)OC_C1S7,(ogg_uint16_t)OC_C1S7,
- (ogg_uint16_t)OC_C1S7,(ogg_uint16_t)OC_C1S7,
- (ogg_uint16_t)OC_C2S6,(ogg_uint16_t)OC_C2S6,
- (ogg_uint16_t)OC_C2S6,(ogg_uint16_t)OC_C2S6,
- (ogg_uint16_t)OC_C3S5,(ogg_uint16_t)OC_C3S5,
- (ogg_uint16_t)OC_C3S5,(ogg_uint16_t)OC_C3S5,
- (ogg_uint16_t)OC_C4S4,(ogg_uint16_t)OC_C4S4,
- (ogg_uint16_t)OC_C4S4,(ogg_uint16_t)OC_C4S4,
- (ogg_uint16_t)OC_C5S3,(ogg_uint16_t)OC_C5S3,
- (ogg_uint16_t)OC_C5S3,(ogg_uint16_t)OC_C5S3,
- (ogg_uint16_t)OC_C6S2,(ogg_uint16_t)OC_C6S2,
- (ogg_uint16_t)OC_C6S2,(ogg_uint16_t)OC_C6S2,
- (ogg_uint16_t)OC_C7S1,(ogg_uint16_t)OC_C7S1,
- (ogg_uint16_t)OC_C7S1,(ogg_uint16_t)OC_C7S1,
- 8, 8, 8, 8
-};
-
-/*Converts the expression in the argument to a string.*/
-#define OC_M2STR(_s) #_s
-
/*38 cycles*/
-#define OC_IDCT_BEGIN \
+#define OC_IDCT_BEGIN(_y,_x) \
"#OC_IDCT_BEGIN\n\t" \
- "movq "OC_I(3)",%%mm2\n\t" \
- "movq "OC_C(3)",%%mm6\n\t" \
+ "movq "OC_I(3,_x)",%%mm2\n\t" \
+ "movq "OC_MEM_OFFS(0x30,c)",%%mm6\n\t" \
"movq %%mm2,%%mm4\n\t" \
- "movq "OC_J(5)",%%mm7\n\t" \
+ "movq "OC_J(5,_x)",%%mm7\n\t" \
"pmulhw %%mm6,%%mm4\n\t" \
- "movq "OC_C(5)",%%mm1\n\t" \
+ "movq "OC_MEM_OFFS(0x50,c)",%%mm1\n\t" \
"pmulhw %%mm7,%%mm6\n\t" \
"movq %%mm1,%%mm5\n\t" \
"pmulhw %%mm2,%%mm1\n\t" \
- "movq "OC_I(1)",%%mm3\n\t" \
+ "movq "OC_I(1,_x)",%%mm3\n\t" \
"pmulhw %%mm7,%%mm5\n\t" \
- "movq "OC_C(1)",%%mm0\n\t" \
+ "movq "OC_MEM_OFFS(0x10,c)",%%mm0\n\t" \
"paddw %%mm2,%%mm4\n\t" \
"paddw %%mm7,%%mm6\n\t" \
"paddw %%mm1,%%mm2\n\t" \
- "movq "OC_J(7)",%%mm1\n\t" \
+ "movq "OC_J(7,_x)",%%mm1\n\t" \
"paddw %%mm5,%%mm7\n\t" \
"movq %%mm0,%%mm5\n\t" \
"pmulhw %%mm3,%%mm0\n\t" \
"paddw %%mm7,%%mm4\n\t" \
"pmulhw %%mm1,%%mm5\n\t" \
- "movq "OC_C(7)",%%mm7\n\t" \
+ "movq "OC_MEM_OFFS(0x70,c)",%%mm7\n\t" \
"psubw %%mm2,%%mm6\n\t" \
"paddw %%mm3,%%mm0\n\t" \
"pmulhw %%mm7,%%mm3\n\t" \
- "movq "OC_I(2)",%%mm2\n\t" \
+ "movq "OC_I(2,_x)",%%mm2\n\t" \
"pmulhw %%mm1,%%mm7\n\t" \
"paddw %%mm1,%%mm5\n\t" \
"movq %%mm2,%%mm1\n\t" \
- "pmulhw "OC_C(2)",%%mm2\n\t" \
+ "pmulhw "OC_MEM_OFFS(0x20,c)",%%mm2\n\t" \
"psubw %%mm5,%%mm3\n\t" \
- "movq "OC_J(6)",%%mm5\n\t" \
+ "movq "OC_J(6,_x)",%%mm5\n\t" \
"paddw %%mm7,%%mm0\n\t" \
"movq %%mm5,%%mm7\n\t" \
"psubw %%mm4,%%mm0\n\t" \
- "pmulhw "OC_C(2)",%%mm5\n\t" \
+ "pmulhw "OC_MEM_OFFS(0x20,c)",%%mm5\n\t" \
"paddw %%mm1,%%mm2\n\t" \
- "pmulhw "OC_C(6)",%%mm1\n\t" \
+ "pmulhw "OC_MEM_OFFS(0x60,c)",%%mm1\n\t" \
"paddw %%mm4,%%mm4\n\t" \
"paddw %%mm0,%%mm4\n\t" \
"psubw %%mm6,%%mm3\n\t" \
"paddw %%mm7,%%mm5\n\t" \
"paddw %%mm6,%%mm6\n\t" \
- "pmulhw "OC_C(6)",%%mm7\n\t" \
+ "pmulhw "OC_MEM_OFFS(0x60,c)",%%mm7\n\t" \
"paddw %%mm3,%%mm6\n\t" \
- "movq %%mm4,"OC_I(1)"\n\t" \
+ "movq %%mm4,"OC_I(1,_y)"\n\t" \
"psubw %%mm5,%%mm1\n\t" \
- "movq "OC_C(4)",%%mm4\n\t" \
+ "movq "OC_MEM_OFFS(0x40,c)",%%mm4\n\t" \
"movq %%mm3,%%mm5\n\t" \
"pmulhw %%mm4,%%mm3\n\t" \
"paddw %%mm2,%%mm7\n\t" \
- "movq %%mm6,"OC_I(2)"\n\t" \
+ "movq %%mm6,"OC_I(2,_y)"\n\t" \
"movq %%mm0,%%mm2\n\t" \
- "movq "OC_I(0)",%%mm6\n\t" \
+ "movq "OC_I(0,_x)",%%mm6\n\t" \
"pmulhw %%mm4,%%mm0\n\t" \
"paddw %%mm3,%%mm5\n\t" \
- "movq "OC_J(4)",%%mm3\n\t" \
+ "movq "OC_J(4,_x)",%%mm3\n\t" \
"psubw %%mm1,%%mm5\n\t" \
"paddw %%mm0,%%mm2\n\t" \
"psubw %%mm3,%%mm6\n\t" \
@@ -126,18 +103,18 @@ static const ogg_uint16_t __attribute__((aligned(8),used))
"paddw %%mm0,%%mm6\n\t" \
"psubw %%mm2,%%mm6\n\t" \
"paddw %%mm2,%%mm2\n\t" \
- "movq "OC_I(1)",%%mm0\n\t" \
+ "movq "OC_I(1,_y)",%%mm0\n\t" \
"paddw %%mm6,%%mm2\n\t" \
"paddw %%mm3,%%mm4\n\t" \
"psubw %%mm1,%%mm2\n\t" \
"#end OC_IDCT_BEGIN\n\t" \
/*38+8=46 cycles.*/
-#define OC_ROW_IDCT \
+#define OC_ROW_IDCT(_y,_x) \
"#OC_ROW_IDCT\n" \
- OC_IDCT_BEGIN \
+ OC_IDCT_BEGIN(_y,_x) \
/*r3=D'*/ \
- "movq "OC_I(2)",%%mm3\n\t" \
+ "movq "OC_I(2,_y)",%%mm3\n\t" \
/*r4=E'=E-G*/ \
"psubw %%mm7,%%mm4\n\t" \
/*r1=H'+H'*/ \
@@ -162,7 +139,7 @@ static const ogg_uint16_t __attribute__((aligned(8),used))
"psubw %%mm0,%%mm7\n\t" \
"paddw %%mm0,%%mm0\n\t" \
/*Save R1.*/ \
- "movq %%mm1,"OC_I(1)"\n\t" \
+ "movq %%mm1,"OC_I(1,_y)"\n\t" \
/*r0=R0=G.+C.*/ \
"paddw %%mm7,%%mm0\n\t" \
"#end OC_ROW_IDCT\n\t" \
@@ -195,11 +172,11 @@ static const ogg_uint16_t __attribute__((aligned(8),used))
Since r1 is free at entry, we calculate the Js first.*/
/*19 cycles.*/
-#define OC_TRANSPOSE \
+#define OC_TRANSPOSE(_y) \
"#OC_TRANSPOSE\n\t" \
"movq %%mm4,%%mm1\n\t" \
"punpcklwd %%mm5,%%mm4\n\t" \
- "movq %%mm0,"OC_I(0)"\n\t" \
+ "movq %%mm0,"OC_I(0,_y)"\n\t" \
"punpckhwd %%mm5,%%mm1\n\t" \
"movq %%mm6,%%mm0\n\t" \
"punpcklwd %%mm7,%%mm6\n\t" \
@@ -207,17 +184,17 @@ static const ogg_uint16_t __attribute__((aligned(8),used))
"punpckldq %%mm6,%%mm4\n\t" \
"punpckhdq %%mm6,%%mm5\n\t" \
"movq %%mm1,%%mm6\n\t" \
- "movq %%mm4,"OC_J(4)"\n\t" \
+ "movq %%mm4,"OC_J(4,_y)"\n\t" \
"punpckhwd %%mm7,%%mm0\n\t" \
- "movq %%mm5,"OC_J(5)"\n\t" \
+ "movq %%mm5,"OC_J(5,_y)"\n\t" \
"punpckhdq %%mm0,%%mm6\n\t" \
- "movq "OC_I(0)",%%mm4\n\t" \
+ "movq "OC_I(0,_y)",%%mm4\n\t" \
"punpckldq %%mm0,%%mm1\n\t" \
- "movq "OC_I(1)",%%mm5\n\t" \
+ "movq "OC_I(1,_y)",%%mm5\n\t" \
"movq %%mm4,%%mm0\n\t" \
- "movq %%mm6,"OC_J(7)"\n\t" \
+ "movq %%mm6,"OC_J(7,_y)"\n\t" \
"punpcklwd %%mm5,%%mm0\n\t" \
- "movq %%mm1,"OC_J(6)"\n\t" \
+ "movq %%mm1,"OC_J(6,_y)"\n\t" \
"punpckhwd %%mm5,%%mm4\n\t" \
"movq %%mm2,%%mm5\n\t" \
"punpcklwd %%mm3,%%mm2\n\t" \
@@ -225,20 +202,20 @@ static const ogg_uint16_t __attribute__((aligned(8),used))
"punpckldq %%mm2,%%mm0\n\t" \
"punpckhdq %%mm2,%%mm1\n\t" \
"movq %%mm4,%%mm2\n\t" \
- "movq %%mm0,"OC_I(0)"\n\t" \
+ "movq %%mm0,"OC_I(0,_y)"\n\t" \
"punpckhwd %%mm3,%%mm5\n\t" \
- "movq %%mm1,"OC_I(1)"\n\t" \
+ "movq %%mm1,"OC_I(1,_y)"\n\t" \
"punpckhdq %%mm5,%%mm4\n\t" \
"punpckldq %%mm5,%%mm2\n\t" \
- "movq %%mm4,"OC_I(3)"\n\t" \
- "movq %%mm2,"OC_I(2)"\n\t" \
+ "movq %%mm4,"OC_I(3,_y)"\n\t" \
+ "movq %%mm2,"OC_I(2,_y)"\n\t" \
"#end OC_TRANSPOSE\n\t" \
/*38+19=57 cycles.*/
-#define OC_COLUMN_IDCT \
+#define OC_COLUMN_IDCT(_y) \
"#OC_COLUMN_IDCT\n" \
- OC_IDCT_BEGIN \
- "paddw "OC_8",%%mm2\n\t" \
+ OC_IDCT_BEGIN(_y,_y) \
+ "paddw "OC_MEM_OFFS(0x00,c)",%%mm2\n\t" \
/*r1=H'+H'*/ \
"paddw %%mm1,%%mm1\n\t" \
/*r1=R1=A''+H'*/ \
@@ -250,18 +227,18 @@ static const ogg_uint16_t __attribute__((aligned(8),used))
/*r1=NR1*/ \
"psraw $4,%%mm1\n\t" \
/*r3=D'*/ \
- "movq "OC_I(2)",%%mm3\n\t" \
+ "movq "OC_I(2,_y)",%%mm3\n\t" \
/*r7=G+G*/ \
"paddw %%mm7,%%mm7\n\t" \
/*Store NR2 at I(2).*/ \
- "movq %%mm2,"OC_I(2)"\n\t" \
+ "movq %%mm2,"OC_I(2,_y)"\n\t" \
/*r7=G'=E+G*/ \
"paddw %%mm4,%%mm7\n\t" \
/*Store NR1 at I(1).*/ \
- "movq %%mm1,"OC_I(1)"\n\t" \
+ "movq %%mm1,"OC_I(1,_y)"\n\t" \
/*r4=R4=E'-D'*/ \
"psubw %%mm3,%%mm4\n\t" \
- "paddw "OC_8",%%mm4\n\t" \
+ "paddw "OC_MEM_OFFS(0x00,c)",%%mm4\n\t" \
/*r3=D'+D'*/ \
"paddw %%mm3,%%mm3\n\t" \
/*r3=R3=E'+D'*/ \
@@ -272,7 +249,7 @@ static const ogg_uint16_t __attribute__((aligned(8),used))
"psubw %%mm5,%%mm6\n\t" \
/*r3=NR3*/ \
"psraw $4,%%mm3\n\t" \
- "paddw "OC_8",%%mm6\n\t" \
+ "paddw "OC_MEM_OFFS(0x00,c)",%%mm6\n\t" \
/*r5=B''+B''*/ \
"paddw %%mm5,%%mm5\n\t" \
/*r5=R5=F'+B''*/ \
@@ -280,14 +257,14 @@ static const ogg_uint16_t __attribute__((aligned(8),used))
/*r6=NR6*/ \
"psraw $4,%%mm6\n\t" \
/*Store NR4 at J(4).*/ \
- "movq %%mm4,"OC_J(4)"\n\t" \
+ "movq %%mm4,"OC_J(4,_y)"\n\t" \
/*r5=NR5*/ \
"psraw $4,%%mm5\n\t" \
/*Store NR3 at I(3).*/ \
- "movq %%mm3,"OC_I(3)"\n\t" \
+ "movq %%mm3,"OC_I(3,_y)"\n\t" \
/*r7=R7=G'-C'*/ \
"psubw %%mm0,%%mm7\n\t" \
- "paddw "OC_8",%%mm7\n\t" \
+ "paddw "OC_MEM_OFFS(0x00,c)",%%mm7\n\t" \
/*r0=C'+C'*/ \
"paddw %%mm0,%%mm0\n\t" \
/*r0=R0=G'+C'*/ \
@@ -295,113 +272,121 @@ static const ogg_uint16_t __attribute__((aligned(8),used))
/*r7=NR7*/ \
"psraw $4,%%mm7\n\t" \
/*Store NR6 at J(6).*/ \
- "movq %%mm6,"OC_J(6)"\n\t" \
+ "movq %%mm6,"OC_J(6,_y)"\n\t" \
/*r0=NR0*/ \
"psraw $4,%%mm0\n\t" \
/*Store NR5 at J(5).*/ \
- "movq %%mm5,"OC_J(5)"\n\t" \
+ "movq %%mm5,"OC_J(5,_y)"\n\t" \
/*Store NR7 at J(7).*/ \
- "movq %%mm7,"OC_J(7)"\n\t" \
+ "movq %%mm7,"OC_J(7,_y)"\n\t" \
/*Store NR0 at I(0).*/ \
- "movq %%mm0,"OC_I(0)"\n\t" \
+ "movq %%mm0,"OC_I(0,_y)"\n\t" \
"#end OC_COLUMN_IDCT\n\t" \
-#define OC_MID(_m,_i) OC_M2STR(_m+(_i)*8)"(%[c])"
-#define OC_C(_i) OC_MID(OC_COSINE_OFFSET,_i-1)
-#define OC_8 OC_MID(OC_EIGHT_OFFSET,0)
-
-static void oc_idct8x8_slow(ogg_int16_t _y[64]){
+static void oc_idct8x8_slow_mmx(ogg_int16_t _y[64],ogg_int16_t _x[64]){
+ int i;
/*This routine accepts an 8x8 matrix, but in partially transposed form.
Every 4x4 block is transposed.*/
__asm__ __volatile__(
-#define OC_I(_k) OC_M2STR((_k*16))"(%[y])"
-#define OC_J(_k) OC_M2STR(((_k-4)*16)+8)"(%[y])"
- OC_ROW_IDCT
- OC_TRANSPOSE
+#define OC_I(_k,_y) OC_MEM_OFFS((_k)*16,_y)
+#define OC_J(_k,_y) OC_MEM_OFFS(((_k)-4)*16+8,_y)
+ OC_ROW_IDCT(y,x)
+ OC_TRANSPOSE(y)
#undef OC_I
#undef OC_J
-#define OC_I(_k) OC_M2STR((_k*16)+64)"(%[y])"
-#define OC_J(_k) OC_M2STR(((_k-4)*16)+72)"(%[y])"
- OC_ROW_IDCT
- OC_TRANSPOSE
+#define OC_I(_k,_y) OC_MEM_OFFS((_k)*16+64,_y)
+#define OC_J(_k,_y) OC_MEM_OFFS(((_k)-4)*16+72,_y)
+ OC_ROW_IDCT(y,x)
+ OC_TRANSPOSE(y)
#undef OC_I
#undef OC_J
-#define OC_I(_k) OC_M2STR((_k*16))"(%[y])"
-#define OC_J(_k) OC_I(_k)
- OC_COLUMN_IDCT
+#define OC_I(_k,_y) OC_MEM_OFFS((_k)*16,_y)
+#define OC_J(_k,_y) OC_I(_k,_y)
+ OC_COLUMN_IDCT(y)
#undef OC_I
#undef OC_J
-#define OC_I(_k) OC_M2STR((_k*16)+8)"(%[y])"
-#define OC_J(_k) OC_I(_k)
- OC_COLUMN_IDCT
+#define OC_I(_k,_y) OC_MEM_OFFS((_k)*16+8,_y)
+#define OC_J(_k,_y) OC_I(_k,_y)
+ OC_COLUMN_IDCT(y)
#undef OC_I
#undef OC_J
- :
- :[y]"r"(_y),[c]"r"(OC_IDCT_CONSTS)
+ :[y]"=m"OC_ARRAY_OPERAND(ogg_int16_t,_y,64)
+ :[x]"m"OC_CONST_ARRAY_OPERAND(ogg_int16_t,_x,64),
+ [c]"m"OC_CONST_ARRAY_OPERAND(ogg_int16_t,OC_IDCT_CONSTS,128)
);
+ __asm__ __volatile__("pxor %%mm0,%%mm0\n\t"::);
+ for(i=0;i<4;i++){
+ __asm__ __volatile__(
+ "movq %%mm0,"OC_MEM_OFFS(0x00,x)"\n\t"
+ "movq %%mm0,"OC_MEM_OFFS(0x08,x)"\n\t"
+ "movq %%mm0,"OC_MEM_OFFS(0x10,x)"\n\t"
+ "movq %%mm0,"OC_MEM_OFFS(0x18,x)"\n\t"
+ :[x]"=m"OC_ARRAY_OPERAND(ogg_int16_t,_x+16*i,16)
+ );
+ }
}
/*25 cycles.*/
-#define OC_IDCT_BEGIN_10 \
+#define OC_IDCT_BEGIN_10(_y,_x) \
"#OC_IDCT_BEGIN_10\n\t" \
- "movq "OC_I(3)",%%mm2\n\t" \
+ "movq "OC_I(3,_x)",%%mm2\n\t" \
"nop\n\t" \
- "movq "OC_C(3)",%%mm6\n\t" \
+ "movq "OC_MEM_OFFS(0x30,c)",%%mm6\n\t" \
"movq %%mm2,%%mm4\n\t" \
- "movq "OC_C(5)",%%mm1\n\t" \
+ "movq "OC_MEM_OFFS(0x50,c)",%%mm1\n\t" \
"pmulhw %%mm6,%%mm4\n\t" \
- "movq "OC_I(1)",%%mm3\n\t" \
+ "movq "OC_I(1,_x)",%%mm3\n\t" \
"pmulhw %%mm2,%%mm1\n\t" \
- "movq "OC_C(1)",%%mm0\n\t" \
+ "movq "OC_MEM_OFFS(0x10,c)",%%mm0\n\t" \
"paddw %%mm2,%%mm4\n\t" \
"pxor %%mm6,%%mm6\n\t" \
"paddw %%mm1,%%mm2\n\t" \
- "movq "OC_I(2)",%%mm5\n\t" \
+ "movq "OC_I(2,_x)",%%mm5\n\t" \
"pmulhw %%mm3,%%mm0\n\t" \
"movq %%mm5,%%mm1\n\t" \
"paddw %%mm3,%%mm0\n\t" \
- "pmulhw "OC_C(7)",%%mm3\n\t" \
+ "pmulhw "OC_MEM_OFFS(0x70,c)",%%mm3\n\t" \
"psubw %%mm2,%%mm6\n\t" \
- "pmulhw "OC_C(2)",%%mm5\n\t" \
+ "pmulhw "OC_MEM_OFFS(0x20,c)",%%mm5\n\t" \
"psubw %%mm4,%%mm0\n\t" \
- "movq "OC_I(2)",%%mm7\n\t" \
+ "movq "OC_I(2,_x)",%%mm7\n\t" \
"paddw %%mm4,%%mm4\n\t" \
"paddw %%mm5,%%mm7\n\t" \
"paddw %%mm0,%%mm4\n\t" \
- "pmulhw "OC_C(6)",%%mm1\n\t" \
+ "pmulhw "OC_MEM_OFFS(0x60,c)",%%mm1\n\t" \
"psubw %%mm6,%%mm3\n\t" \
- "movq %%mm4,"OC_I(1)"\n\t" \
+ "movq %%mm4,"OC_I(1,_y)"\n\t" \
"paddw %%mm6,%%mm6\n\t" \
- "movq "OC_C(4)",%%mm4\n\t" \
+ "movq "OC_MEM_OFFS(0x40,c)",%%mm4\n\t" \
"paddw %%mm3,%%mm6\n\t" \
"movq %%mm3,%%mm5\n\t" \
"pmulhw %%mm4,%%mm3\n\t" \
- "movq %%mm6,"OC_I(2)"\n\t" \
+ "movq %%mm6,"OC_I(2,_y)"\n\t" \
"movq %%mm0,%%mm2\n\t" \
- "movq "OC_I(0)",%%mm6\n\t" \
+ "movq "OC_I(0,_x)",%%mm6\n\t" \
"pmulhw %%mm4,%%mm0\n\t" \
"paddw %%mm3,%%mm5\n\t" \
"paddw %%mm0,%%mm2\n\t" \
"psubw %%mm1,%%mm5\n\t" \
"pmulhw %%mm4,%%mm6\n\t" \
- "paddw "OC_I(0)",%%mm6\n\t" \
+ "paddw "OC_I(0,_x)",%%mm6\n\t" \
"paddw %%mm1,%%mm1\n\t" \
"movq %%mm6,%%mm4\n\t" \
"paddw %%mm5,%%mm1\n\t" \
"psubw %%mm2,%%mm6\n\t" \
"paddw %%mm2,%%mm2\n\t" \
- "movq "OC_I(1)",%%mm0\n\t" \
+ "movq "OC_I(1,_y)",%%mm0\n\t" \
"paddw %%mm6,%%mm2\n\t" \
"psubw %%mm1,%%mm2\n\t" \
"nop\n\t" \
"#end OC_IDCT_BEGIN_10\n\t" \
/*25+8=33 cycles.*/
-#define OC_ROW_IDCT_10 \
+#define OC_ROW_IDCT_10(_y,_x) \
"#OC_ROW_IDCT_10\n\t" \
- OC_IDCT_BEGIN_10 \
+ OC_IDCT_BEGIN_10(_y,_x) \
/*r3=D'*/ \
- "movq "OC_I(2)",%%mm3\n\t" \
+ "movq "OC_I(2,_y)",%%mm3\n\t" \
/*r4=E'=E-G*/ \
"psubw %%mm7,%%mm4\n\t" \
/*r1=H'+H'*/ \
@@ -426,16 +411,16 @@ static void oc_idct8x8_slow(ogg_int16_t _y[64]){
"psubw %%mm0,%%mm7\n\t" \
"paddw %%mm0,%%mm0\n\t" \
/*Save R1.*/ \
- "movq %%mm1,"OC_I(1)"\n\t" \
+ "movq %%mm1,"OC_I(1,_y)"\n\t" \
/*r0=R0=G'+C'*/ \
"paddw %%mm7,%%mm0\n\t" \
"#end OC_ROW_IDCT_10\n\t" \
/*25+19=44 cycles'*/
-#define OC_COLUMN_IDCT_10 \
+#define OC_COLUMN_IDCT_10(_y) \
"#OC_COLUMN_IDCT_10\n\t" \
- OC_IDCT_BEGIN_10 \
- "paddw "OC_8",%%mm2\n\t" \
+ OC_IDCT_BEGIN_10(_y,_y) \
+ "paddw "OC_MEM_OFFS(0x00,c)",%%mm2\n\t" \
/*r1=H'+H'*/ \
"paddw %%mm1,%%mm1\n\t" \
/*r1=R1=A''+H'*/ \
@@ -447,18 +432,18 @@ static void oc_idct8x8_slow(ogg_int16_t _y[64]){
/*r1=NR1*/ \
"psraw $4,%%mm1\n\t" \
/*r3=D'*/ \
- "movq "OC_I(2)",%%mm3\n\t" \
+ "movq "OC_I(2,_y)",%%mm3\n\t" \
/*r7=G+G*/ \
"paddw %%mm7,%%mm7\n\t" \
/*Store NR2 at I(2).*/ \
- "movq %%mm2,"OC_I(2)"\n\t" \
+ "movq %%mm2,"OC_I(2,_y)"\n\t" \
/*r7=G'=E+G*/ \
"paddw %%mm4,%%mm7\n\t" \
/*Store NR1 at I(1).*/ \
- "movq %%mm1,"OC_I(1)"\n\t" \
+ "movq %%mm1,"OC_I(1,_y)"\n\t" \
/*r4=R4=E'-D'*/ \
"psubw %%mm3,%%mm4\n\t" \
- "paddw "OC_8",%%mm4\n\t" \
+ "paddw "OC_MEM_OFFS(0x00,c)",%%mm4\n\t" \
/*r3=D'+D'*/ \
"paddw %%mm3,%%mm3\n\t" \
/*r3=R3=E'+D'*/ \
@@ -469,7 +454,7 @@ static void oc_idct8x8_slow(ogg_int16_t _y[64]){
"psubw %%mm5,%%mm6\n\t" \
/*r3=NR3*/ \
"psraw $4,%%mm3\n\t" \
- "paddw "OC_8",%%mm6\n\t" \
+ "paddw "OC_MEM_OFFS(0x00,c)",%%mm6\n\t" \
/*r5=B''+B''*/ \
"paddw %%mm5,%%mm5\n\t" \
/*r5=R5=F'+B''*/ \
@@ -477,14 +462,14 @@ static void oc_idct8x8_slow(ogg_int16_t _y[64]){
/*r6=NR6*/ \
"psraw $4,%%mm6\n\t" \
/*Store NR4 at J(4).*/ \
- "movq %%mm4,"OC_J(4)"\n\t" \
+ "movq %%mm4,"OC_J(4,_y)"\n\t" \
/*r5=NR5*/ \
"psraw $4,%%mm5\n\t" \
/*Store NR3 at I(3).*/ \
- "movq %%mm3,"OC_I(3)"\n\t" \
+ "movq %%mm3,"OC_I(3,_y)"\n\t" \
/*r7=R7=G'-C'*/ \
"psubw %%mm0,%%mm7\n\t" \
- "paddw "OC_8",%%mm7\n\t" \
+ "paddw "OC_MEM_OFFS(0x00,c)",%%mm7\n\t" \
/*r0=C'+C'*/ \
"paddw %%mm0,%%mm0\n\t" \
/*r0=R0=G'+C'*/ \
@@ -492,46 +477,55 @@ static void oc_idct8x8_slow(ogg_int16_t _y[64]){
/*r7=NR7*/ \
"psraw $4,%%mm7\n\t" \
/*Store NR6 at J(6).*/ \
- "movq %%mm6,"OC_J(6)"\n\t" \
+ "movq %%mm6,"OC_J(6,_y)"\n\t" \
/*r0=NR0*/ \
"psraw $4,%%mm0\n\t" \
/*Store NR5 at J(5).*/ \
- "movq %%mm5,"OC_J(5)"\n\t" \
+ "movq %%mm5,"OC_J(5,_y)"\n\t" \
/*Store NR7 at J(7).*/ \
- "movq %%mm7,"OC_J(7)"\n\t" \
+ "movq %%mm7,"OC_J(7,_y)"\n\t" \
/*Store NR0 at I(0).*/ \
- "movq %%mm0,"OC_I(0)"\n\t" \
+ "movq %%mm0,"OC_I(0,_y)"\n\t" \
"#end OC_COLUMN_IDCT_10\n\t" \
-static void oc_idct8x8_10(ogg_int16_t _y[64]){
+static void oc_idct8x8_10_mmx(ogg_int16_t _y[64],ogg_int16_t _x[64]){
__asm__ __volatile__(
-#define OC_I(_k) OC_M2STR((_k*16))"(%[y])"
-#define OC_J(_k) OC_M2STR(((_k-4)*16)+8)"(%[y])"
+#define OC_I(_k,_y) OC_MEM_OFFS((_k)*16,_y)
+#define OC_J(_k,_y) OC_MEM_OFFS(((_k)-4)*16+8,_y)
/*Done with dequant, descramble, and partial transpose.
Now do the iDCT itself.*/
- OC_ROW_IDCT_10
- OC_TRANSPOSE
+ OC_ROW_IDCT_10(y,x)
+ OC_TRANSPOSE(y)
#undef OC_I
#undef OC_J
-#define OC_I(_k) OC_M2STR((_k*16))"(%[y])"
-#define OC_J(_k) OC_I(_k)
- OC_COLUMN_IDCT_10
+#define OC_I(_k,_y) OC_MEM_OFFS((_k)*16,_y)
+#define OC_J(_k,_y) OC_I(_k,_y)
+ OC_COLUMN_IDCT_10(y)
#undef OC_I
#undef OC_J
-#define OC_I(_k) OC_M2STR((_k*16)+8)"(%[y])"
-#define OC_J(_k) OC_I(_k)
- OC_COLUMN_IDCT_10
+#define OC_I(_k,_y) OC_MEM_OFFS((_k)*16+8,_y)
+#define OC_J(_k,_y) OC_I(_k,_y)
+ OC_COLUMN_IDCT_10(y)
#undef OC_I
#undef OC_J
- :
- :[y]"r"(_y),[c]"r"(OC_IDCT_CONSTS)
+ :[y]"=m"OC_ARRAY_OPERAND(ogg_int16_t,_y,64)
+ :[x]"m"OC_CONST_ARRAY_OPERAND(ogg_int16_t,_x,64),
+ [c]"m"OC_CONST_ARRAY_OPERAND(ogg_int16_t,OC_IDCT_CONSTS,128)
+ );
+ __asm__ __volatile__(
+ "pxor %%mm0,%%mm0\n\t"
+ "movq %%mm0,"OC_MEM_OFFS(0x00,x)"\n\t"
+ "movq %%mm0,"OC_MEM_OFFS(0x10,x)"\n\t"
+ "movq %%mm0,"OC_MEM_OFFS(0x20,x)"\n\t"
+ "movq %%mm0,"OC_MEM_OFFS(0x30,x)"\n\t"
+ :[x]"+m"OC_ARRAY_OPERAND(ogg_int16_t,_x,28)
);
}
/*Performs an inverse 8x8 Type-II DCT transform.
The input is assumed to be scaled by a factor of 4 relative to orthonormal
version of the transform.*/
-void oc_idct8x8_mmx(ogg_int16_t _y[64],int _last_zzi){
+void oc_idct8x8_mmx(ogg_int16_t _y[64],ogg_int16_t _x[64],int _last_zzi){
/*_last_zzi is subtly different from an actual count of the number of
coefficients we decoded for this block.
It contains the value of zzi BEFORE the final token in the block was
@@ -557,8 +551,8 @@ void oc_idct8x8_mmx(ogg_int16_t _y[64],int _last_zzi){
gets.
Needless to say we inherited this approach from VP3.*/
/*Then perform the iDCT.*/
- if(_last_zzi<10)oc_idct8x8_10(_y);
- else oc_idct8x8_slow(_y);
+ if(_last_zzi<=10)oc_idct8x8_10_mmx(_y,_x);
+ else oc_idct8x8_slow_mmx(_y,_x);
}
#endif
diff --git a/thirdparty/libtheora/x86/mmxloop.h b/thirdparty/libtheora/x86/mmxloop.h
index 2e870c795d..1f6090b567 100644
--- a/thirdparty/libtheora/x86/mmxloop.h
+++ b/thirdparty/libtheora/x86/mmxloop.h
@@ -9,88 +9,191 @@
On exit, mm1={b0+lflim(R_0,L),...,b7+lflim(R_7,L)} and
mm2={c0-lflim(R_0,L),...,c7-lflim(R_7,L)}; mm0 and mm3 are clobbered.*/
#define OC_LOOP_FILTER8_MMX \
- "#OC_LOOP_FILTER8_MMX\n\t" \
- /*mm7=0*/ \
- "pxor %%mm7,%%mm7\n\t" \
- /*mm6:mm0={a0,...,a7}*/ \
- "movq %%mm0,%%mm6\n\t" \
- "punpcklbw %%mm7,%%mm0\n\t" \
- "punpckhbw %%mm7,%%mm6\n\t" \
- /*mm3:mm5={d0,...,d7}*/ \
- "movq %%mm3,%%mm5\n\t" \
- "punpcklbw %%mm7,%%mm3\n\t" \
- "punpckhbw %%mm7,%%mm5\n\t" \
- /*mm6:mm0={a0-d0,...,a7-d7}*/ \
- "psubw %%mm3,%%mm0\n\t" \
- "psubw %%mm5,%%mm6\n\t" \
- /*mm3:mm1={b0,...,b7}*/ \
- "movq %%mm1,%%mm3\n\t" \
- "punpcklbw %%mm7,%%mm1\n\t" \
- "movq %%mm2,%%mm4\n\t" \
- "punpckhbw %%mm7,%%mm3\n\t" \
- /*mm5:mm4={c0,...,c7}*/ \
- "movq %%mm2,%%mm5\n\t" \
- "punpcklbw %%mm7,%%mm4\n\t" \
- "punpckhbw %%mm7,%%mm5\n\t" \
- /*mm7={3}x4 \
- mm5:mm4={c0-b0,...,c7-b7}*/ \
- "pcmpeqw %%mm7,%%mm7\n\t" \
- "psubw %%mm1,%%mm4\n\t" \
- "psrlw $14,%%mm7\n\t" \
- "psubw %%mm3,%%mm5\n\t" \
- /*Scale by 3.*/ \
- "pmullw %%mm7,%%mm4\n\t" \
- "pmullw %%mm7,%%mm5\n\t" \
- /*mm7={4}x4 \
- mm5:mm4=f={a0-d0+3*(c0-b0),...,a7-d7+3*(c7-b7)}*/ \
- "psrlw $1,%%mm7\n\t" \
- "paddw %%mm0,%%mm4\n\t" \
- "psllw $2,%%mm7\n\t" \
- "movq (%[ll]),%%mm0\n\t" \
- "paddw %%mm6,%%mm5\n\t" \
- /*R_i has the range [-127,128], so we compute -R_i instead. \
- mm4=-R_i=-(f+4>>3)=0xFF^(f-4>>3)*/ \
- "psubw %%mm7,%%mm4\n\t" \
- "psubw %%mm7,%%mm5\n\t" \
- "psraw $3,%%mm4\n\t" \
- "psraw $3,%%mm5\n\t" \
- "pcmpeqb %%mm7,%%mm7\n\t" \
- "packsswb %%mm5,%%mm4\n\t" \
- "pxor %%mm6,%%mm6\n\t" \
- "pxor %%mm7,%%mm4\n\t" \
- "packuswb %%mm3,%%mm1\n\t" \
- /*Now compute lflim of -mm4 cf. Section 7.10 of the sepc.*/ \
- /*There's no unsigned byte+signed byte with unsigned saturation op code, so \
- we have to split things by sign (the other option is to work in 16 bits, \
- but working in 8 bits gives much better parallelism). \
- We compute abs(R_i), but save a mask of which terms were negative in mm6. \
- Then we compute mm4=abs(lflim(R_i,L))=min(abs(R_i),max(2*L-abs(R_i),0)). \
- Finally, we split mm4 into positive and negative pieces using the mask in \
- mm6, and add and subtract them as appropriate.*/ \
- /*mm4=abs(-R_i)*/ \
- /*mm7=255-2*L*/ \
- "pcmpgtb %%mm4,%%mm6\n\t" \
- "psubb %%mm0,%%mm7\n\t" \
- "pxor %%mm6,%%mm4\n\t" \
- "psubb %%mm0,%%mm7\n\t" \
- "psubb %%mm6,%%mm4\n\t" \
- /*mm7=255-max(2*L-abs(R_i),0)*/ \
- "paddusb %%mm4,%%mm7\n\t" \
- /*mm4=min(abs(R_i),max(2*L-abs(R_i),0))*/ \
- "paddusb %%mm7,%%mm4\n\t" \
- "psubusb %%mm7,%%mm4\n\t" \
- /*Now split mm4 by the original sign of -R_i.*/ \
- "movq %%mm4,%%mm5\n\t" \
- "pand %%mm6,%%mm4\n\t" \
- "pandn %%mm5,%%mm6\n\t" \
- /*mm1={b0+lflim(R_0,L),...,b7+lflim(R_7,L)}*/ \
- /*mm2={c0-lflim(R_0,L),...,c7-lflim(R_7,L)}*/ \
- "paddusb %%mm4,%%mm1\n\t" \
- "psubusb %%mm4,%%mm2\n\t" \
- "psubusb %%mm6,%%mm1\n\t" \
- "paddusb %%mm6,%%mm2\n\t" \
+ "#OC_LOOP_FILTER8_MMX\n\t" \
+ /*mm7=0*/ \
+ "pxor %%mm7,%%mm7\n\t" \
+ /*mm6:mm0={a0,...,a7}*/ \
+ "movq %%mm0,%%mm6\n\t" \
+ "punpcklbw %%mm7,%%mm0\n\t" \
+ "punpckhbw %%mm7,%%mm6\n\t" \
+ /*mm3:mm5={d0,...,d7}*/ \
+ "movq %%mm3,%%mm5\n\t" \
+ "punpcklbw %%mm7,%%mm3\n\t" \
+ "punpckhbw %%mm7,%%mm5\n\t" \
+ /*mm6:mm0={a0-d0,...,a7-d7}*/ \
+ "psubw %%mm3,%%mm0\n\t" \
+ "psubw %%mm5,%%mm6\n\t" \
+ /*mm3:mm1={b0,...,b7}*/ \
+ "movq %%mm1,%%mm3\n\t" \
+ "punpcklbw %%mm7,%%mm1\n\t" \
+ "movq %%mm2,%%mm4\n\t" \
+ "punpckhbw %%mm7,%%mm3\n\t" \
+ /*mm5:mm4={c0,...,c7}*/ \
+ "movq %%mm2,%%mm5\n\t" \
+ "punpcklbw %%mm7,%%mm4\n\t" \
+ "punpckhbw %%mm7,%%mm5\n\t" \
+ /*mm7={3}x4 \
+ mm5:mm4={c0-b0,...,c7-b7}*/ \
+ "pcmpeqw %%mm7,%%mm7\n\t" \
+ "psubw %%mm1,%%mm4\n\t" \
+ "psrlw $14,%%mm7\n\t" \
+ "psubw %%mm3,%%mm5\n\t" \
+ /*Scale by 3.*/ \
+ "pmullw %%mm7,%%mm4\n\t" \
+ "pmullw %%mm7,%%mm5\n\t" \
+ /*mm7={4}x4 \
+ mm5:mm4=f={a0-d0+3*(c0-b0),...,a7-d7+3*(c7-b7)}*/ \
+ "psrlw $1,%%mm7\n\t" \
+ "paddw %%mm0,%%mm4\n\t" \
+ "psllw $2,%%mm7\n\t" \
+ "movq (%[ll]),%%mm0\n\t" \
+ "paddw %%mm6,%%mm5\n\t" \
+ /*R_i has the range [-127,128], so we compute -R_i instead. \
+ mm4=-R_i=-(f+4>>3)=0xFF^(f-4>>3)*/ \
+ "psubw %%mm7,%%mm4\n\t" \
+ "psubw %%mm7,%%mm5\n\t" \
+ "psraw $3,%%mm4\n\t" \
+ "psraw $3,%%mm5\n\t" \
+ "pcmpeqb %%mm7,%%mm7\n\t" \
+ "packsswb %%mm5,%%mm4\n\t" \
+ "pxor %%mm6,%%mm6\n\t" \
+ "pxor %%mm7,%%mm4\n\t" \
+ "packuswb %%mm3,%%mm1\n\t" \
+ /*Now compute lflim of -mm4 cf. Section 7.10 of the sepc.*/ \
+ /*There's no unsigned byte+signed byte with unsigned saturation op code, so \
+ we have to split things by sign (the other option is to work in 16 bits, \
+ but working in 8 bits gives much better parallelism). \
+ We compute abs(R_i), but save a mask of which terms were negative in mm6. \
+ Then we compute mm4=abs(lflim(R_i,L))=min(abs(R_i),max(2*L-abs(R_i),0)). \
+ Finally, we split mm4 into positive and negative pieces using the mask in \
+ mm6, and add and subtract them as appropriate.*/ \
+ /*mm4=abs(-R_i)*/ \
+ /*mm7=255-2*L*/ \
+ "pcmpgtb %%mm4,%%mm6\n\t" \
+ "psubb %%mm0,%%mm7\n\t" \
+ "pxor %%mm6,%%mm4\n\t" \
+ "psubb %%mm0,%%mm7\n\t" \
+ "psubb %%mm6,%%mm4\n\t" \
+ /*mm7=255-max(2*L-abs(R_i),0)*/ \
+ "paddusb %%mm4,%%mm7\n\t" \
+ /*mm4=min(abs(R_i),max(2*L-abs(R_i),0))*/ \
+ "paddusb %%mm7,%%mm4\n\t" \
+ "psubusb %%mm7,%%mm4\n\t" \
+ /*Now split mm4 by the original sign of -R_i.*/ \
+ "movq %%mm4,%%mm5\n\t" \
+ "pand %%mm6,%%mm4\n\t" \
+ "pandn %%mm5,%%mm6\n\t" \
+ /*mm1={b0+lflim(R_0,L),...,b7+lflim(R_7,L)}*/ \
+ /*mm2={c0-lflim(R_0,L),...,c7-lflim(R_7,L)}*/ \
+ "paddusb %%mm4,%%mm1\n\t" \
+ "psubusb %%mm4,%%mm2\n\t" \
+ "psubusb %%mm6,%%mm1\n\t" \
+ "paddusb %%mm6,%%mm2\n\t" \
-#define OC_LOOP_FILTER_V_MMX(_pix,_ystride,_ll) \
+/*On entry, mm0={a0,...,a7}, mm1={b0,...,b7}, mm2={c0,...,c7}, mm3={d0,...d7}.
+ On exit, mm1={b0+lflim(R_0,L),...,b7+lflim(R_7,L)} and
+ mm2={c0-lflim(R_0,L),...,c7-lflim(R_7,L)}.
+ All other MMX registers are clobbered.*/
+#define OC_LOOP_FILTER8_MMXEXT \
+ "#OC_LOOP_FILTER8_MMXEXT\n\t" \
+ /*R_i=(a_i-3*b_i+3*c_i-d_i+4>>3) has the range [-127,128], so we compute \
+ -R_i=(-a_i+3*b_i-3*c_i+d_i+3>>3) instead.*/ \
+ /*This first part is based on the transformation \
+ f = -(3*(c-b)+a-d+4>>3) \
+ = -(3*(c+255-b)+(a+255-d)+4-1020>>3) \
+ = -(3*(c+~b)+(a+~d)-1016>>3) \
+ = 127-(3*(c+~b)+(a+~d)>>3) \
+ = 128+~(3*(c+~b)+(a+~d)>>3) (mod 256). \
+ Although pavgb(a,b) = (a+b+1>>1) (biased up), we rely heavily on the \
+ fact that ~pavgb(~a,~b) = (a+b>>1) (biased down). \
+ Using this, the last expression above can be computed in 8 bits of working \
+ precision via: \
+ u = ~pavgb(~b,c); \
+ v = pavgb(b,~c); \
+ This mask is 0 or 0xFF, and controls whether t is biased up or down: \
+ m = u-v; \
+ t = m^pavgb(m^~a,m^d); \
+ f = 128+pavgb(pavgb(t,u),v); \
+ This required some careful analysis to ensure that carries are propagated \
+ correctly in all cases, but has been checked exhaustively.*/ \
+ /*input (a, b, c, d, ., ., ., .)*/ \
+ /*ff=0xFF; \
+ u=b; \
+ v=c; \
+ ll=255-2*L;*/ \
+ "pcmpeqb %%mm7,%%mm7\n\t" \
+ "movq %%mm1,%%mm4\n\t" \
+ "movq %%mm2,%%mm5\n\t" \
+ "movq (%[ll]),%%mm6\n\t" \
+ /*allocated u, v, ll, ff: (a, b, c, d, u, v, ll, ff)*/ \
+ /*u^=ff; \
+ v^=ff;*/ \
+ "pxor %%mm7,%%mm4\n\t" \
+ "pxor %%mm7,%%mm5\n\t" \
+ /*allocated ll: (a, b, c, d, u, v, ll, ff)*/ \
+ /*u=pavgb(u,c); \
+ v=pavgb(v,b);*/ \
+ "pavgb %%mm2,%%mm4\n\t" \
+ "pavgb %%mm1,%%mm5\n\t" \
+ /*u^=ff; \
+ a^=ff;*/ \
+ "pxor %%mm7,%%mm4\n\t" \
+ "pxor %%mm7,%%mm0\n\t" \
+ /*m=u-v;*/ \
+ "psubb %%mm5,%%mm4\n\t" \
+ /*freed u, allocated m: (a, b, c, d, m, v, ll, ff)*/ \
+ /*a^=m; \
+ d^=m;*/ \
+ "pxor %%mm4,%%mm0\n\t" \
+ "pxor %%mm4,%%mm3\n\t" \
+ /*t=pavgb(a,d);*/ \
+ "pavgb %%mm3,%%mm0\n\t" \
+ "psllw $7,%%mm7\n\t" \
+ /*freed a, d, ff, allocated t, of: (t, b, c, ., m, v, ll, of)*/ \
+ /*t^=m; \
+ u=m+v;*/ \
+ "pxor %%mm4,%%mm0\n\t" \
+ "paddb %%mm5,%%mm4\n\t" \
+ /*freed t, m, allocated f, u: (f, b, c, ., u, v, ll, of)*/ \
+ /*f=pavgb(f,u); \
+ of=128;*/ \
+ "pavgb %%mm4,%%mm0\n\t" \
+ "packsswb %%mm7,%%mm7\n\t" \
+ /*freed u, ff, allocated ll: (f, b, c, ., ll, v, ll, of)*/ \
+ /*f=pavgb(f,v);*/ \
+ "pavgb %%mm5,%%mm0\n\t" \
+ "movq %%mm7,%%mm3\n\t" \
+ "movq %%mm6,%%mm4\n\t" \
+ /*freed v, allocated of: (f, b, c, of, ll, ., ll, of)*/ \
+ /*Now compute lflim of R_i=-(128+mm0) cf. Section 7.10 of the sepc.*/ \
+ /*There's no unsigned byte+signed byte with unsigned saturation op code, so \
+ we have to split things by sign (the other option is to work in 16 bits, \
+ but staying in 8 bits gives much better parallelism).*/ \
+ /*Instead of adding the offset of 128 in mm3, we use it to split mm0. \
+ This is the same number of instructions as computing a mask and splitting \
+ after the lflim computation, but has shorter dependency chains.*/ \
+ /*mm0=R_i<0?-R_i:0 (denoted abs(R_i<0))\
+ mm3=R_i>0?R_i:0* (denoted abs(R_i>0))*/ \
+ "psubusb %%mm0,%%mm3\n\t" \
+ "psubusb %%mm7,%%mm0\n\t" \
+ /*mm6=255-max(2*L-abs(R_i<0),0) \
+ mm4=255-max(2*L-abs(R_i>0),0)*/ \
+ "paddusb %%mm3,%%mm4\n\t" \
+ "paddusb %%mm0,%%mm6\n\t" \
+ /*mm0=min(abs(R_i<0),max(2*L-abs(R_i<0),0)) \
+ mm3=min(abs(R_i>0),max(2*L-abs(R_i>0),0))*/ \
+ "paddusb %%mm4,%%mm3\n\t" \
+ "paddusb %%mm6,%%mm0\n\t" \
+ "psubusb %%mm4,%%mm3\n\t" \
+ "psubusb %%mm6,%%mm0\n\t" \
+ /*mm1={b0+lflim(R_0,L),...,b7+lflim(R_7,L)}*/ \
+ /*mm2={c0-lflim(R_0,L),...,c7-lflim(R_7,L)}*/ \
+ "paddusb %%mm3,%%mm1\n\t" \
+ "psubusb %%mm3,%%mm2\n\t" \
+ "psubusb %%mm0,%%mm1\n\t" \
+ "paddusb %%mm0,%%mm2\n\t" \
+
+#define OC_LOOP_FILTER_V(_filter,_pix,_ystride,_ll) \
do{ \
ptrdiff_t ystride3__; \
__asm__ __volatile__( \
@@ -104,7 +207,7 @@
"movq (%[pix],%[ystride]),%%mm1\n\t" \
/*mm2={c0,...,c7}*/ \
"movq (%[pix],%[ystride],2),%%mm2\n\t" \
- OC_LOOP_FILTER8_MMX \
+ _filter \
/*Write it back out.*/ \
"movq %%mm1,(%[pix],%[ystride])\n\t" \
"movq %%mm2,(%[pix],%[ystride],2)\n\t" \
@@ -116,7 +219,7 @@
} \
while(0)
-#define OC_LOOP_FILTER_H_MMX(_pix,_ystride,_ll) \
+#define OC_LOOP_FILTER_H(_filter,_pix,_ystride,_ll) \
do{ \
unsigned char *pix__; \
ptrdiff_t ystride3__; \
@@ -174,7 +277,7 @@
"punpckldq %%mm5,%%mm2\n\t" \
/*mm3=d7 d6 d5 d4 d3 d2 d1 d0*/ \
"punpckhdq %%mm5,%%mm3\n\t" \
- OC_LOOP_FILTER8_MMX \
+ _filter \
/*mm2={b0+R_0'',...,b7+R_7''}*/ \
"movq %%mm1,%%mm0\n\t" \
/*mm1={b0+R_0'',c0-R_0'',...,b3+R_3'',c3-R_3''}*/ \
diff --git a/thirdparty/libtheora/x86/mmxstate.c b/thirdparty/libtheora/x86/mmxstate.c
index 808b0a789b..eebea14fba 100644
--- a/thirdparty/libtheora/x86/mmxstate.c
+++ b/thirdparty/libtheora/x86/mmxstate.c
@@ -11,7 +11,7 @@
********************************************************************
function:
- last mod: $Id: mmxstate.c 16503 2009-08-22 18:14:02Z giles $
+ last mod: $Id$
********************************************************************/
@@ -19,23 +19,23 @@
Originally written by Rudolf Marek.*/
#include <string.h>
#include "x86int.h"
-#include "mmxfrag.h"
#include "mmxloop.h"
#if defined(OC_X86_ASM)
void oc_state_frag_recon_mmx(const oc_theora_state *_state,ptrdiff_t _fragi,
- int _pli,ogg_int16_t _dct_coeffs[64],int _last_zzi,ogg_uint16_t _dc_quant){
+ int _pli,ogg_int16_t _dct_coeffs[128],int _last_zzi,ogg_uint16_t _dc_quant){
unsigned char *dst;
ptrdiff_t frag_buf_off;
int ystride;
- int mb_mode;
+ int refi;
/*Apply the inverse transform.*/
/*Special case only having a DC component.*/
if(_last_zzi<2){
/*Note that this value must be unsigned, to keep the __asm__ block from
sign-extending it when it puts it in a register.*/
ogg_uint16_t p;
+ int i;
/*We round this dequant product (and not any of the others) because there's
no iDCT rounding.*/
p=(ogg_int16_t)(_dct_coeffs[0]*(ogg_int32_t)_dc_quant+15>>5);
@@ -47,81 +47,48 @@ void oc_state_frag_recon_mmx(const oc_theora_state *_state,ptrdiff_t _fragi,
"punpcklwd %%mm0,%%mm0\n\t"
/*mm0=AAAA AAAA AAAA AAAA*/
"punpckldq %%mm0,%%mm0\n\t"
- "movq %%mm0,(%[y])\n\t"
- "movq %%mm0,8(%[y])\n\t"
- "movq %%mm0,16(%[y])\n\t"
- "movq %%mm0,24(%[y])\n\t"
- "movq %%mm0,32(%[y])\n\t"
- "movq %%mm0,40(%[y])\n\t"
- "movq %%mm0,48(%[y])\n\t"
- "movq %%mm0,56(%[y])\n\t"
- "movq %%mm0,64(%[y])\n\t"
- "movq %%mm0,72(%[y])\n\t"
- "movq %%mm0,80(%[y])\n\t"
- "movq %%mm0,88(%[y])\n\t"
- "movq %%mm0,96(%[y])\n\t"
- "movq %%mm0,104(%[y])\n\t"
- "movq %%mm0,112(%[y])\n\t"
- "movq %%mm0,120(%[y])\n\t"
:
- :[y]"r"(_dct_coeffs),[p]"r"((unsigned)p)
- :"memory"
+ :[p]"r"((unsigned)p)
);
+ for(i=0;i<4;i++){
+ __asm__ __volatile__(
+ "movq %%mm0,"OC_MEM_OFFS(0x00,y)"\n\t"
+ "movq %%mm0,"OC_MEM_OFFS(0x08,y)"\n\t"
+ "movq %%mm0,"OC_MEM_OFFS(0x10,y)"\n\t"
+ "movq %%mm0,"OC_MEM_OFFS(0x18,y)"\n\t"
+ :[y]"=m"OC_ARRAY_OPERAND(ogg_int16_t,_dct_coeffs+64+16*i,16)
+ );
+ }
}
else{
/*Dequantize the DC coefficient.*/
_dct_coeffs[0]=(ogg_int16_t)(_dct_coeffs[0]*(int)_dc_quant);
- oc_idct8x8_mmx(_dct_coeffs,_last_zzi);
+ oc_idct8x8(_state,_dct_coeffs+64,_dct_coeffs,_last_zzi);
}
/*Fill in the target buffer.*/
frag_buf_off=_state->frag_buf_offs[_fragi];
- mb_mode=_state->frags[_fragi].mb_mode;
+ refi=_state->frags[_fragi].refi;
ystride=_state->ref_ystride[_pli];
- dst=_state->ref_frame_data[_state->ref_frame_idx[OC_FRAME_SELF]]+frag_buf_off;
- if(mb_mode==OC_MODE_INTRA)oc_frag_recon_intra_mmx(dst,ystride,_dct_coeffs);
+ dst=_state->ref_frame_data[OC_FRAME_SELF]+frag_buf_off;
+ if(refi==OC_FRAME_SELF)oc_frag_recon_intra_mmx(dst,ystride,_dct_coeffs+64);
else{
const unsigned char *ref;
int mvoffsets[2];
- ref=
- _state->ref_frame_data[_state->ref_frame_idx[OC_FRAME_FOR_MODE(mb_mode)]]
- +frag_buf_off;
+ ref=_state->ref_frame_data[refi]+frag_buf_off;
if(oc_state_get_mv_offsets(_state,mvoffsets,_pli,
- _state->frag_mvs[_fragi][0],_state->frag_mvs[_fragi][1])>1){
+ _state->frag_mvs[_fragi])>1){
oc_frag_recon_inter2_mmx(dst,ref+mvoffsets[0],ref+mvoffsets[1],ystride,
- _dct_coeffs);
+ _dct_coeffs+64);
}
- else oc_frag_recon_inter_mmx(dst,ref+mvoffsets[0],ystride,_dct_coeffs);
+ else oc_frag_recon_inter_mmx(dst,ref+mvoffsets[0],ystride,_dct_coeffs+64);
}
}
/*We copy these entire function to inline the actual MMX routines so that we
use only a single indirect call.*/
-/*Copies the fragments specified by the lists of fragment indices from one
- frame to another.
- _fragis: A pointer to a list of fragment indices.
- _nfragis: The number of fragment indices to copy.
- _dst_frame: The reference frame to copy to.
- _src_frame: The reference frame to copy from.
- _pli: The color plane the fragments lie in.*/
-void oc_state_frag_copy_list_mmx(const oc_theora_state *_state,
- const ptrdiff_t *_fragis,ptrdiff_t _nfragis,
- int _dst_frame,int _src_frame,int _pli){
- const ptrdiff_t *frag_buf_offs;
- const unsigned char *src_frame_data;
- unsigned char *dst_frame_data;
- ptrdiff_t fragii;
- int ystride;
- dst_frame_data=_state->ref_frame_data[_state->ref_frame_idx[_dst_frame]];
- src_frame_data=_state->ref_frame_data[_state->ref_frame_idx[_src_frame]];
- ystride=_state->ref_ystride[_pli];
- frag_buf_offs=_state->frag_buf_offs;
- for(fragii=0;fragii<_nfragis;fragii++){
- ptrdiff_t frag_buf_off;
- frag_buf_off=frag_buf_offs[_fragis[fragii]];
- OC_FRAG_COPY_MMX(dst_frame_data+frag_buf_off,
- src_frame_data+frag_buf_off,ystride);
- }
+void oc_loop_filter_init_mmx(signed char _bv[256],int _flimit){
+ memset(_bv,_flimit,8);
}
/*Apply the loop filter to a given set of fragment rows in the given plane.
@@ -133,7 +100,7 @@ void oc_state_frag_copy_list_mmx(const oc_theora_state *_state,
_fragy0: The Y coordinate of the first fragment row to filter.
_fragy_end: The Y coordinate of the fragment row to stop filtering at.*/
void oc_state_loop_filter_frag_rows_mmx(const oc_theora_state *_state,
- int _bv[256],int _refi,int _pli,int _fragy0,int _fragy_end){
+ signed char _bv[256],int _refi,int _pli,int _fragy0,int _fragy_end){
OC_ALIGN8(unsigned char ll[8]);
const oc_fragment_plane *fplane;
const oc_fragment *frags;
@@ -170,13 +137,84 @@ void oc_state_loop_filter_frag_rows_mmx(const oc_theora_state *_state,
if(frags[fragi].coded){
unsigned char *ref;
ref=ref_frame_data+frag_buf_offs[fragi];
- if(fragi>fragi0)OC_LOOP_FILTER_H_MMX(ref,ystride,ll);
- if(fragi0>fragi_top)OC_LOOP_FILTER_V_MMX(ref,ystride,ll);
+ if(fragi>fragi0){
+ OC_LOOP_FILTER_H(OC_LOOP_FILTER8_MMX,ref,ystride,ll);
+ }
+ if(fragi0>fragi_top){
+ OC_LOOP_FILTER_V(OC_LOOP_FILTER8_MMX,ref,ystride,ll);
+ }
+ if(fragi+1<fragi_end&&!frags[fragi+1].coded){
+ OC_LOOP_FILTER_H(OC_LOOP_FILTER8_MMX,ref+8,ystride,ll);
+ }
+ if(fragi+nhfrags<fragi_bot&&!frags[fragi+nhfrags].coded){
+ OC_LOOP_FILTER_V(OC_LOOP_FILTER8_MMX,ref+(ystride<<3),ystride,ll);
+ }
+ }
+ fragi++;
+ }
+ fragi0+=nhfrags;
+ }
+}
+
+void oc_loop_filter_init_mmxext(signed char _bv[256],int _flimit){
+ memset(_bv,~(_flimit<<1),8);
+}
+
+/*Apply the loop filter to a given set of fragment rows in the given plane.
+ The filter may be run on the bottom edge, affecting pixels in the next row of
+ fragments, so this row also needs to be available.
+ _bv: The bounding values array.
+ _refi: The index of the frame buffer to filter.
+ _pli: The color plane to filter.
+ _fragy0: The Y coordinate of the first fragment row to filter.
+ _fragy_end: The Y coordinate of the fragment row to stop filtering at.*/
+void oc_state_loop_filter_frag_rows_mmxext(const oc_theora_state *_state,
+ signed char _bv[256],int _refi,int _pli,int _fragy0,int _fragy_end){
+ const oc_fragment_plane *fplane;
+ const oc_fragment *frags;
+ const ptrdiff_t *frag_buf_offs;
+ unsigned char *ref_frame_data;
+ ptrdiff_t fragi_top;
+ ptrdiff_t fragi_bot;
+ ptrdiff_t fragi0;
+ ptrdiff_t fragi0_end;
+ int ystride;
+ int nhfrags;
+ fplane=_state->fplanes+_pli;
+ nhfrags=fplane->nhfrags;
+ fragi_top=fplane->froffset;
+ fragi_bot=fragi_top+fplane->nfrags;
+ fragi0=fragi_top+_fragy0*(ptrdiff_t)nhfrags;
+ fragi0_end=fragi_top+_fragy_end*(ptrdiff_t)nhfrags;
+ ystride=_state->ref_ystride[_pli];
+ frags=_state->frags;
+ frag_buf_offs=_state->frag_buf_offs;
+ ref_frame_data=_state->ref_frame_data[_refi];
+ /*The following loops are constructed somewhat non-intuitively on purpose.
+ The main idea is: if a block boundary has at least one coded fragment on
+ it, the filter is applied to it.
+ However, the order that the filters are applied in matters, and VP3 chose
+ the somewhat strange ordering used below.*/
+ while(fragi0<fragi0_end){
+ ptrdiff_t fragi;
+ ptrdiff_t fragi_end;
+ fragi=fragi0;
+ fragi_end=fragi+nhfrags;
+ while(fragi<fragi_end){
+ if(frags[fragi].coded){
+ unsigned char *ref;
+ ref=ref_frame_data+frag_buf_offs[fragi];
+ if(fragi>fragi0){
+ OC_LOOP_FILTER_H(OC_LOOP_FILTER8_MMXEXT,ref,ystride,_bv);
+ }
+ if(fragi0>fragi_top){
+ OC_LOOP_FILTER_V(OC_LOOP_FILTER8_MMXEXT,ref,ystride,_bv);
+ }
if(fragi+1<fragi_end&&!frags[fragi+1].coded){
- OC_LOOP_FILTER_H_MMX(ref+8,ystride,ll);
+ OC_LOOP_FILTER_H(OC_LOOP_FILTER8_MMXEXT,ref+8,ystride,_bv);
}
if(fragi+nhfrags<fragi_bot&&!frags[fragi+nhfrags].coded){
- OC_LOOP_FILTER_V_MMX(ref+(ystride<<3),ystride,ll);
+ OC_LOOP_FILTER_V(OC_LOOP_FILTER8_MMXEXT,ref+(ystride<<3),ystride,_bv);
}
}
fragi++;
diff --git a/thirdparty/libtheora/x86/sse2encfrag.c b/thirdparty/libtheora/x86/sse2encfrag.c
new file mode 100644
index 0000000000..43aeb17711
--- /dev/null
+++ b/thirdparty/libtheora/x86/sse2encfrag.c
@@ -0,0 +1,501 @@
+/********************************************************************
+ * *
+ * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. *
+ * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
+ * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
+ * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
+ * *
+ * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 *
+ * by the Xiph.Org Foundation http://www.xiph.org/ *
+ * *
+ ********************************************************************
+
+ function:
+ last mod: $Id: dsp_mmx.c 14579 2008-03-12 06:42:40Z xiphmont $
+
+ ********************************************************************/
+#include <stddef.h>
+#include "x86enc.h"
+#include "sse2trans.h"
+
+#if defined(OC_X86_ASM)
+
+/*Load a 4x8 array of pixels values from %[src] and %[ref] and compute their
+ 16-bit differences.
+ On output, these are stored in _m0, xmm1, xmm2, and xmm3.
+ xmm4 and xmm5 are clobbered.*/
+#define OC_LOAD_SUB_4x8(_m0) \
+ "#OC_LOAD_SUB_4x8\n\t" \
+ /*Load the first three rows.*/ \
+ "movq (%[src]),"_m0"\n\t" \
+ "movq (%[ref]),%%xmm4\n\t" \
+ "movq (%[src],%[ystride]),%%xmm1\n\t" \
+ "movq (%[ref],%[ystride]),%%xmm3\n\t" \
+ "movq (%[src],%[ystride],2),%%xmm2\n\t" \
+ "movq (%[ref],%[ystride],2),%%xmm5\n\t" \
+ /*Unpack and subtract.*/ \
+ "punpcklbw %%xmm4,"_m0"\n\t" \
+ "punpcklbw %%xmm4,%%xmm4\n\t" \
+ "punpcklbw %%xmm3,%%xmm1\n\t" \
+ "punpcklbw %%xmm3,%%xmm3\n\t" \
+ "psubw %%xmm4,"_m0"\n\t" \
+ "psubw %%xmm3,%%xmm1\n\t" \
+ /*Load the last row.*/ \
+ "movq (%[src],%[ystride3]),%%xmm3\n\t" \
+ "movq (%[ref],%[ystride3]),%%xmm4\n\t" \
+ /*Unpack, subtract, and advance the pointers.*/ \
+ "punpcklbw %%xmm5,%%xmm2\n\t" \
+ "punpcklbw %%xmm5,%%xmm5\n\t" \
+ "lea (%[src],%[ystride],4),%[src]\n\t" \
+ "psubw %%xmm5,%%xmm2\n\t" \
+ "punpcklbw %%xmm4,%%xmm3\n\t" \
+ "punpcklbw %%xmm4,%%xmm4\n\t" \
+ "lea (%[ref],%[ystride],4),%[ref]\n\t" \
+ "psubw %%xmm4,%%xmm3\n\t" \
+
+/*Square and accumulate four rows of differences in _m0, xmm1, xmm2, and xmm3.
+ On output, xmm0 contains the sum of two of the rows, and the other two are
+ added to xmm7.*/
+#define OC_SSD_4x8(_m0) \
+ "pmaddwd "_m0","_m0"\n\t" \
+ "pmaddwd %%xmm1,%%xmm1\n\t" \
+ "pmaddwd %%xmm2,%%xmm2\n\t" \
+ "pmaddwd %%xmm3,%%xmm3\n\t" \
+ "paddd %%xmm1,"_m0"\n\t" \
+ "paddd %%xmm3,%%xmm2\n\t" \
+ "paddd %%xmm2,%%xmm7\n\t" \
+
+unsigned oc_enc_frag_ssd_sse2(const unsigned char *_src,
+ const unsigned char *_ref,int _ystride){
+ unsigned ret;
+ __asm__ __volatile__(
+ OC_LOAD_SUB_4x8("%%xmm7")
+ OC_SSD_4x8("%%xmm7")
+ OC_LOAD_SUB_4x8("%%xmm0")
+ OC_SSD_4x8("%%xmm0")
+ "paddd %%xmm0,%%xmm7\n\t"
+ "movdqa %%xmm7,%%xmm6\n\t"
+ "punpckhqdq %%xmm7,%%xmm7\n\t"
+ "paddd %%xmm6,%%xmm7\n\t"
+ "pshufd $1,%%xmm7,%%xmm6\n\t"
+ "paddd %%xmm6,%%xmm7\n\t"
+ "movd %%xmm7,%[ret]\n\t"
+ :[ret]"=a"(ret)
+ :[src]"r"(_src),[ref]"r"(_ref),[ystride]"r"((ptrdiff_t)_ystride),
+ [ystride3]"r"((ptrdiff_t)_ystride*3)
+ );
+ return ret;
+}
+
+static const unsigned char __attribute__((aligned(16))) OC_MASK_CONSTS[8]={
+ 0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80
+};
+
+/*Load a 2x8 array of pixels values from %[src] and %[ref] and compute their
+ horizontal sums as well as their 16-bit differences subject to a mask.
+ %%xmm5 must contain OC_MASK_CONSTS[0...7] and %%xmm6 must contain 0.*/
+#define OC_LOAD_SUB_MASK_2x8 \
+ "#OC_LOAD_SUB_MASK_2x8\n\t" \
+ /*Start the loads and expand the next 8 bits of the mask.*/ \
+ "shl $8,%[m]\n\t" \
+ "movq (%[src]),%%xmm0\n\t" \
+ "mov %h[m],%b[m]\n\t" \
+ "movq (%[ref]),%%xmm2\n\t" \
+ "movd %[m],%%xmm4\n\t" \
+ "shr $8,%[m]\n\t" \
+ "pshuflw $0x00,%%xmm4,%%xmm4\n\t" \
+ "mov %h[m],%b[m]\n\t" \
+ "pand %%xmm6,%%xmm4\n\t" \
+ "pcmpeqb %%xmm6,%%xmm4\n\t" \
+ /*Perform the masking.*/ \
+ "pand %%xmm4,%%xmm0\n\t" \
+ "pand %%xmm4,%%xmm2\n\t" \
+ /*Finish the loads while unpacking the first set of rows, and expand the next
+ 8 bits of the mask.*/ \
+ "movd %[m],%%xmm4\n\t" \
+ "movq (%[src],%[ystride]),%%xmm1\n\t" \
+ "pshuflw $0x00,%%xmm4,%%xmm4\n\t" \
+ "movq (%[ref],%[ystride]),%%xmm3\n\t" \
+ "pand %%xmm6,%%xmm4\n\t" \
+ "punpcklbw %%xmm2,%%xmm0\n\t" \
+ "pcmpeqb %%xmm6,%%xmm4\n\t" \
+ "punpcklbw %%xmm2,%%xmm2\n\t" \
+ /*Mask and unpack the second set of rows.*/ \
+ "pand %%xmm4,%%xmm1\n\t" \
+ "pand %%xmm4,%%xmm3\n\t" \
+ "punpcklbw %%xmm3,%%xmm1\n\t" \
+ "punpcklbw %%xmm3,%%xmm3\n\t" \
+ "psubw %%xmm2,%%xmm0\n\t" \
+ "psubw %%xmm3,%%xmm1\n\t" \
+
+unsigned oc_enc_frag_border_ssd_sse2(const unsigned char *_src,
+ const unsigned char *_ref,int _ystride,ogg_int64_t _mask){
+ ptrdiff_t ystride;
+ unsigned ret;
+ int i;
+ ystride=_ystride;
+ __asm__ __volatile__(
+ "pxor %%xmm7,%%xmm7\n\t"
+ "movq %[c],%%xmm6\n\t"
+ :
+ :[c]"m"(OC_CONST_ARRAY_OPERAND(unsigned char,OC_MASK_CONSTS,8))
+ );
+ for(i=0;i<4;i++){
+ unsigned m;
+ m=_mask&0xFFFF;
+ _mask>>=16;
+ if(m){
+ __asm__ __volatile__(
+ OC_LOAD_SUB_MASK_2x8
+ "pmaddwd %%xmm0,%%xmm0\n\t"
+ "pmaddwd %%xmm1,%%xmm1\n\t"
+ "paddd %%xmm0,%%xmm7\n\t"
+ "paddd %%xmm1,%%xmm7\n\t"
+ :[src]"+r"(_src),[ref]"+r"(_ref),[ystride]"+r"(ystride),[m]"+Q"(m)
+ );
+ }
+ _src+=2*ystride;
+ _ref+=2*ystride;
+ }
+ __asm__ __volatile__(
+ "movdqa %%xmm7,%%xmm6\n\t"
+ "punpckhqdq %%xmm7,%%xmm7\n\t"
+ "paddd %%xmm6,%%xmm7\n\t"
+ "pshufd $1,%%xmm7,%%xmm6\n\t"
+ "paddd %%xmm6,%%xmm7\n\t"
+ "movd %%xmm7,%[ret]\n\t"
+ :[ret]"=a"(ret)
+ );
+ return ret;
+}
+
+
+/*Load an 8x8 array of pixel values from %[src] and %[ref] and compute their
+ 16-bit difference in %%xmm0...%%xmm7.*/
+#define OC_LOAD_SUB_8x8 \
+ "#OC_LOAD_SUB_8x8\n\t" \
+ "movq (%[src]),%%xmm0\n\t" \
+ "movq (%[ref]),%%xmm4\n\t" \
+ "movq (%[src],%[src_ystride]),%%xmm1\n\t" \
+ "lea (%[src],%[src_ystride],2),%[src]\n\t" \
+ "movq (%[ref],%[ref_ystride]),%%xmm5\n\t" \
+ "lea (%[ref],%[ref_ystride],2),%[ref]\n\t" \
+ "movq (%[src]),%%xmm2\n\t" \
+ "movq (%[ref]),%%xmm7\n\t" \
+ "movq (%[src],%[src_ystride]),%%xmm3\n\t" \
+ "movq (%[ref],%[ref_ystride]),%%xmm6\n\t" \
+ "punpcklbw %%xmm4,%%xmm0\n\t" \
+ "lea (%[src],%[src_ystride],2),%[src]\n\t" \
+ "punpcklbw %%xmm4,%%xmm4\n\t" \
+ "lea (%[ref],%[ref_ystride],2),%[ref]\n\t" \
+ "psubw %%xmm4,%%xmm0\n\t" \
+ "movq (%[src]),%%xmm4\n\t" \
+ "movdqa %%xmm0,"OC_MEM_OFFS(0x00,buf)"\n\t" \
+ "movq (%[ref]),%%xmm0\n\t" \
+ "punpcklbw %%xmm5,%%xmm1\n\t" \
+ "punpcklbw %%xmm5,%%xmm5\n\t" \
+ "psubw %%xmm5,%%xmm1\n\t" \
+ "movq (%[src],%[src_ystride]),%%xmm5\n\t" \
+ "punpcklbw %%xmm7,%%xmm2\n\t" \
+ "punpcklbw %%xmm7,%%xmm7\n\t" \
+ "psubw %%xmm7,%%xmm2\n\t" \
+ "movq (%[ref],%[ref_ystride]),%%xmm7\n\t" \
+ "punpcklbw %%xmm6,%%xmm3\n\t" \
+ "lea (%[src],%[src_ystride],2),%[src]\n\t" \
+ "punpcklbw %%xmm6,%%xmm6\n\t" \
+ "psubw %%xmm6,%%xmm3\n\t" \
+ "movq (%[src]),%%xmm6\n\t" \
+ "punpcklbw %%xmm0,%%xmm4\n\t" \
+ "lea (%[ref],%[ref_ystride],2),%[ref]\n\t" \
+ "punpcklbw %%xmm0,%%xmm0\n\t" \
+ "lea (%[src],%[src_ystride],2),%[src]\n\t" \
+ "psubw %%xmm0,%%xmm4\n\t" \
+ "movq (%[ref]),%%xmm0\n\t" \
+ "punpcklbw %%xmm7,%%xmm5\n\t" \
+ "neg %[src_ystride]\n\t" \
+ "punpcklbw %%xmm7,%%xmm7\n\t" \
+ "psubw %%xmm7,%%xmm5\n\t" \
+ "movq (%[src],%[src_ystride]),%%xmm7\n\t" \
+ "punpcklbw %%xmm0,%%xmm6\n\t" \
+ "lea (%[ref],%[ref_ystride],2),%[ref]\n\t" \
+ "punpcklbw %%xmm0,%%xmm0\n\t" \
+ "neg %[ref_ystride]\n\t" \
+ "psubw %%xmm0,%%xmm6\n\t" \
+ "movq (%[ref],%[ref_ystride]),%%xmm0\n\t" \
+ "punpcklbw %%xmm0,%%xmm7\n\t" \
+ "punpcklbw %%xmm0,%%xmm0\n\t" \
+ "psubw %%xmm0,%%xmm7\n\t" \
+ "movdqa "OC_MEM_OFFS(0x00,buf)",%%xmm0\n\t" \
+
+/*Load an 8x8 array of pixel values from %[src] into %%xmm0...%%xmm7.*/
+#define OC_LOAD_8x8 \
+ "#OC_LOAD_8x8\n\t" \
+ "movq (%[src]),%%xmm0\n\t" \
+ "movq (%[src],%[ystride]),%%xmm1\n\t" \
+ "movq (%[src],%[ystride],2),%%xmm2\n\t" \
+ "pxor %%xmm7,%%xmm7\n\t" \
+ "movq (%[src],%[ystride3]),%%xmm3\n\t" \
+ "punpcklbw %%xmm7,%%xmm0\n\t" \
+ "movq (%[src4]),%%xmm4\n\t" \
+ "punpcklbw %%xmm7,%%xmm1\n\t" \
+ "movq (%[src4],%[ystride]),%%xmm5\n\t" \
+ "punpcklbw %%xmm7,%%xmm2\n\t" \
+ "movq (%[src4],%[ystride],2),%%xmm6\n\t" \
+ "punpcklbw %%xmm7,%%xmm3\n\t" \
+ "movq (%[src4],%[ystride3]),%%xmm7\n\t" \
+ "punpcklbw %%xmm4,%%xmm4\n\t" \
+ "punpcklbw %%xmm5,%%xmm5\n\t" \
+ "psrlw $8,%%xmm4\n\t" \
+ "psrlw $8,%%xmm5\n\t" \
+ "punpcklbw %%xmm6,%%xmm6\n\t" \
+ "punpcklbw %%xmm7,%%xmm7\n\t" \
+ "psrlw $8,%%xmm6\n\t" \
+ "psrlw $8,%%xmm7\n\t" \
+
+/*Performs the first two stages of an 8-point 1-D Hadamard transform in place.
+ Outputs 1, 3, 4, and 5 from the second stage are negated (which allows us to
+ perform this stage in place with no temporary registers).*/
+#define OC_HADAMARD_AB_8x8 \
+ "#OC_HADAMARD_AB_8x8\n\t" \
+ /*Stage A:*/ \
+ "paddw %%xmm5,%%xmm1\n\t" \
+ "paddw %%xmm6,%%xmm2\n\t" \
+ "paddw %%xmm5,%%xmm5\n\t" \
+ "paddw %%xmm6,%%xmm6\n\t" \
+ "psubw %%xmm1,%%xmm5\n\t" \
+ "psubw %%xmm2,%%xmm6\n\t" \
+ "paddw %%xmm7,%%xmm3\n\t" \
+ "paddw %%xmm4,%%xmm0\n\t" \
+ "paddw %%xmm7,%%xmm7\n\t" \
+ "paddw %%xmm4,%%xmm4\n\t" \
+ "psubw %%xmm3,%%xmm7\n\t" \
+ "psubw %%xmm0,%%xmm4\n\t" \
+ /*Stage B:*/ \
+ "paddw %%xmm2,%%xmm0\n\t" \
+ "paddw %%xmm3,%%xmm1\n\t" \
+ "paddw %%xmm6,%%xmm4\n\t" \
+ "paddw %%xmm7,%%xmm5\n\t" \
+ "paddw %%xmm2,%%xmm2\n\t" \
+ "paddw %%xmm3,%%xmm3\n\t" \
+ "paddw %%xmm6,%%xmm6\n\t" \
+ "paddw %%xmm7,%%xmm7\n\t" \
+ "psubw %%xmm0,%%xmm2\n\t" \
+ "psubw %%xmm1,%%xmm3\n\t" \
+ "psubw %%xmm4,%%xmm6\n\t" \
+ "psubw %%xmm5,%%xmm7\n\t" \
+
+/*Performs the last stage of an 8-point 1-D Hadamard transform in place.
+ Outputs 1, 3, 5, and 7 are negated (which allows us to perform this stage in
+ place with no temporary registers).*/
+#define OC_HADAMARD_C_8x8 \
+ "#OC_HADAMARD_C_8x8\n\t" \
+ /*Stage C:*/ \
+ "paddw %%xmm1,%%xmm0\n\t" \
+ "paddw %%xmm3,%%xmm2\n\t" \
+ "paddw %%xmm5,%%xmm4\n\t" \
+ "paddw %%xmm7,%%xmm6\n\t" \
+ "paddw %%xmm1,%%xmm1\n\t" \
+ "paddw %%xmm3,%%xmm3\n\t" \
+ "paddw %%xmm5,%%xmm5\n\t" \
+ "paddw %%xmm7,%%xmm7\n\t" \
+ "psubw %%xmm0,%%xmm1\n\t" \
+ "psubw %%xmm2,%%xmm3\n\t" \
+ "psubw %%xmm4,%%xmm5\n\t" \
+ "psubw %%xmm6,%%xmm7\n\t" \
+
+/*Performs an 8-point 1-D Hadamard transform in place.
+ Outputs 1, 2, 4, and 7 are negated (which allows us to perform the transform
+ in place with no temporary registers).*/
+#define OC_HADAMARD_8x8 \
+ OC_HADAMARD_AB_8x8 \
+ OC_HADAMARD_C_8x8 \
+
+/*Performs the first part of the final stage of the Hadamard transform and
+ summing of absolute values.
+ At the end of this part, %%xmm1 will contain the DC coefficient of the
+ transform.*/
+#define OC_HADAMARD_C_ABS_ACCUM_A_8x8 \
+ /*We use the fact that \
+ (abs(a+b)+abs(a-b))/2=max(abs(a),abs(b)) \
+ to merge the final butterfly with the abs and the first stage of \
+ accumulation. \
+ Thus we can avoid using pabsw, which is not available until SSSE3. \
+ Emulating pabsw takes 3 instructions, so the straightforward SSE2 \
+ implementation would be (3+3)*8+7=55 instructions (+4 for spilling \
+ registers). \
+ Even with pabsw, it would be (3+1)*8+7=39 instructions (with no spills). \
+ This implementation is only 26 (+4 for spilling registers).*/ \
+ "#OC_HADAMARD_C_ABS_ACCUM_A_8x8\n\t" \
+ "movdqa %%xmm7,"OC_MEM_OFFS(0x10,buf)"\n\t" \
+ "movdqa %%xmm6,"OC_MEM_OFFS(0x00,buf)"\n\t" \
+ /*xmm7={0x7FFF}x4 \
+ xmm4=max(abs(xmm4),abs(xmm5))-0x7FFF*/ \
+ "pcmpeqb %%xmm7,%%xmm7\n\t" \
+ "movdqa %%xmm4,%%xmm6\n\t" \
+ "psrlw $1,%%xmm7\n\t" \
+ "paddw %%xmm5,%%xmm6\n\t" \
+ "pmaxsw %%xmm5,%%xmm4\n\t" \
+ "paddsw %%xmm7,%%xmm6\n\t" \
+ "psubw %%xmm6,%%xmm4\n\t" \
+ /*xmm2=max(abs(xmm2),abs(xmm3))-0x7FFF \
+ xmm0=max(abs(xmm0),abs(xmm1))-0x7FFF*/ \
+ "movdqa %%xmm2,%%xmm6\n\t" \
+ "movdqa %%xmm0,%%xmm5\n\t" \
+ "pmaxsw %%xmm3,%%xmm2\n\t" \
+ "pmaxsw %%xmm1,%%xmm0\n\t" \
+ "paddw %%xmm3,%%xmm6\n\t" \
+ "movdqa "OC_MEM_OFFS(0x10,buf)",%%xmm3\n\t" \
+ "paddw %%xmm5,%%xmm1\n\t" \
+ "movdqa "OC_MEM_OFFS(0x00,buf)",%%xmm5\n\t" \
+
+/*Performs the second part of the final stage of the Hadamard transform and
+ summing of absolute values.*/
+#define OC_HADAMARD_C_ABS_ACCUM_B_8x8 \
+ "#OC_HADAMARD_C_ABS_ACCUM_B_8x8\n\t" \
+ "paddsw %%xmm7,%%xmm6\n\t" \
+ "paddsw %%xmm7,%%xmm1\n\t" \
+ "psubw %%xmm6,%%xmm2\n\t" \
+ "psubw %%xmm1,%%xmm0\n\t" \
+ /*xmm7={1}x4 (needed for the horizontal add that follows) \
+ xmm0+=xmm2+xmm4+max(abs(xmm3),abs(xmm5))-0x7FFF*/ \
+ "movdqa %%xmm3,%%xmm6\n\t" \
+ "pmaxsw %%xmm5,%%xmm3\n\t" \
+ "paddw %%xmm2,%%xmm0\n\t" \
+ "paddw %%xmm5,%%xmm6\n\t" \
+ "paddw %%xmm4,%%xmm0\n\t" \
+ "paddsw %%xmm7,%%xmm6\n\t" \
+ "paddw %%xmm3,%%xmm0\n\t" \
+ "psrlw $14,%%xmm7\n\t" \
+ "psubw %%xmm6,%%xmm0\n\t" \
+
+/*Performs the last stage of an 8-point 1-D Hadamard transform, takes the
+ absolute value of each component, and accumulates everything into xmm0.*/
+#define OC_HADAMARD_C_ABS_ACCUM_8x8 \
+ OC_HADAMARD_C_ABS_ACCUM_A_8x8 \
+ OC_HADAMARD_C_ABS_ACCUM_B_8x8 \
+
+/*Performs an 8-point 1-D Hadamard transform, takes the absolute value of each
+ component, and accumulates everything into xmm0.
+ Note that xmm0 will have an extra 4 added to each column, and that after
+ removing this value, the remainder will be half the conventional value.*/
+#define OC_HADAMARD_ABS_ACCUM_8x8 \
+ OC_HADAMARD_AB_8x8 \
+ OC_HADAMARD_C_ABS_ACCUM_8x8
+
+static unsigned oc_int_frag_satd_sse2(int *_dc,
+ const unsigned char *_src,int _src_ystride,
+ const unsigned char *_ref,int _ref_ystride){
+ OC_ALIGN16(ogg_int16_t buf[16]);
+ unsigned ret;
+ unsigned ret2;
+ int dc;
+ __asm__ __volatile__(
+ OC_LOAD_SUB_8x8
+ OC_HADAMARD_8x8
+ OC_TRANSPOSE_8x8
+ /*We split out the stages here so we can save the DC coefficient in the
+ middle.*/
+ OC_HADAMARD_AB_8x8
+ OC_HADAMARD_C_ABS_ACCUM_A_8x8
+ "movd %%xmm1,%[dc]\n\t"
+ OC_HADAMARD_C_ABS_ACCUM_B_8x8
+ /*Up to this point, everything fit in 16 bits (8 input + 1 for the
+ difference + 2*3 for the two 8-point 1-D Hadamards - 1 for the abs - 1
+ for the factor of two we dropped + 3 for the vertical accumulation).
+ Now we finally have to promote things to dwords.
+ We break this part out of OC_HADAMARD_ABS_ACCUM_8x8 to hide the long
+ latency of pmaddwd by starting to compute abs(dc) here.*/
+ "pmaddwd %%xmm7,%%xmm0\n\t"
+ "movsx %w[dc],%[dc]\n\t"
+ "cdq\n\t"
+ "movdqa %%xmm0,%%xmm1\n\t"
+ "punpckhqdq %%xmm0,%%xmm0\n\t"
+ "paddd %%xmm1,%%xmm0\n\t"
+ "pshuflw $0xE,%%xmm0,%%xmm1\n\t"
+ "paddd %%xmm1,%%xmm0\n\t"
+ "movd %%xmm0,%[ret]\n\t"
+ /*The sums produced by OC_HADAMARD_ABS_ACCUM_8x8 each have an extra 4
+ added to them, a factor of two removed, and the DC value included;
+ correct the final sum here.*/
+ "lea -64(%[ret2],%[ret],2),%[ret]\n\t"
+ "xor %[dc],%[ret2]\n\t"
+ "sub %[ret2],%[ret]\n\t"
+ /*Although it looks like we're using 7 registers here, gcc can alias %[ret]
+ and %[dc] with some of the inputs, since for once we don't write to
+ them until after we're done using everything but %[buf].*/
+ /*Note that _src_ystride and _ref_ystride must be given non-overlapping
+ constraints, otherewise if gcc can prove they're equal it will allocate
+ them to the same register (which is bad); _src and _ref face a similar
+ problem.
+ All four are destructively modified, but if we list them as output
+ constraints, gcc can't alias them with other outputs.*/
+ :[ret]"=r"(ret),[ret2]"=d"(ret2),[dc]"=a"(dc),
+ [buf]"=m"(OC_ARRAY_OPERAND(ogg_int16_t,buf,16))
+ :[src]"S"(_src),[src_ystride]"c"((ptrdiff_t)_src_ystride),
+ [ref]"a"(_ref),[ref_ystride]"d"((ptrdiff_t)_ref_ystride)
+ /*We have to use neg, so we actually clobber the condition codes for once
+ (not to mention sub, and add).*/
+ :"cc"
+ );
+ *_dc=dc;
+ return ret;
+}
+
+unsigned oc_enc_frag_satd_sse2(int *_dc,const unsigned char *_src,
+ const unsigned char *_ref,int _ystride){
+ return oc_int_frag_satd_sse2(_dc,_src,_ystride,_ref,_ystride);
+}
+
+unsigned oc_enc_frag_satd2_sse2(int *_dc,const unsigned char *_src,
+ const unsigned char *_ref1,const unsigned char *_ref2,int _ystride){
+ OC_ALIGN8(unsigned char ref[64]);
+ oc_int_frag_copy2_mmxext(ref,8,_ref1,_ref2,_ystride);
+ return oc_int_frag_satd_sse2(_dc,_src,_ystride,ref,8);
+}
+
+unsigned oc_enc_frag_intra_satd_sse2(int *_dc,
+ const unsigned char *_src,int _ystride){
+ OC_ALIGN16(ogg_int16_t buf[16]);
+ unsigned ret;
+ int dc;
+ __asm__ __volatile__(
+ OC_LOAD_8x8
+ OC_HADAMARD_8x8
+ OC_TRANSPOSE_8x8
+ /*We split out the stages here so we can save the DC coefficient in the
+ middle.*/
+ OC_HADAMARD_AB_8x8
+ OC_HADAMARD_C_ABS_ACCUM_A_8x8
+ "movd %%xmm1,%[dc]\n\t"
+ OC_HADAMARD_C_ABS_ACCUM_B_8x8
+ /*Up to this point, everything fit in 16 bits (8 input + 1 for the
+ difference + 2*3 for the two 8-point 1-D Hadamards - 1 for the abs - 1
+ for the factor of two we dropped + 3 for the vertical accumulation).
+ Now we finally have to promote things to dwords.*/
+ "pmaddwd %%xmm7,%%xmm0\n\t"
+ /*We assume that the DC coefficient is always positive (which is true,
+ because the input to the INTRA transform was not a difference).*/
+ "movzx %w[dc],%[dc]\n\t"
+ "movdqa %%xmm0,%%xmm1\n\t"
+ "punpckhqdq %%xmm0,%%xmm0\n\t"
+ "paddd %%xmm1,%%xmm0\n\t"
+ "pshuflw $0xE,%%xmm0,%%xmm1\n\t"
+ "paddd %%xmm1,%%xmm0\n\t"
+ "movd %%xmm0,%[ret]\n\t"
+ "lea -64(%[ret],%[ret]),%[ret]\n\t"
+ "sub %[dc],%[ret]\n\t"
+ /*Although it looks like we're using 7 registers here, gcc can alias %[ret]
+ and %[dc] with some of the inputs, since for once we don't write to
+ them until after we're done using everything but %[buf].*/
+ :[ret]"=a"(ret),[dc]"=r"(dc),
+ [buf]"=m"(OC_ARRAY_OPERAND(ogg_int16_t,buf,16))
+ :[src]"r"(_src),[src4]"r"(_src+4*_ystride),
+ [ystride]"r"((ptrdiff_t)_ystride),[ystride3]"r"((ptrdiff_t)3*_ystride)
+ /*We have to use sub, so we actually clobber the condition codes for once.*/
+ :"cc"
+ );
+ *_dc=dc;
+ return ret;
+}
+
+#endif
diff --git a/thirdparty/libtheora/x86/sse2fdct.c b/thirdparty/libtheora/x86/sse2fdct.c
index 86c17d68b1..64c1d27372 100644
--- a/thirdparty/libtheora/x86/sse2fdct.c
+++ b/thirdparty/libtheora/x86/sse2fdct.c
@@ -13,12 +13,14 @@
/*$Id: fdct_ses2.c 14579 2008-03-12 06:42:40Z xiphmont $*/
#include <stddef.h>
#include "x86enc.h"
+#include "x86zigzag.h"
+#include "sse2trans.h"
#if defined(OC_X86_64_ASM)
-# define OC_FDCT8x8 \
+# define OC_FDCT_8x8 \
/*Note: xmm15={0}x8 and xmm14={-1}x8.*/ \
- "#OC_FDCT8x8\n\t" \
+ "#OC_FDCT_8x8\n\t" \
/*Stage 1:*/ \
"movdqa %%xmm0,%%xmm11\n\t" \
"movdqa %%xmm1,%%xmm10\n\t" \
@@ -349,81 +351,6 @@
"psubw %%xmm14,%%xmm10\n\t" \
"paddw %%xmm10,%%xmm7\n\t " \
-# define OC_TRANSPOSE8x8 \
- "#OC_TRANSPOSE8x8\n\t" \
- "movdqa %%xmm4,%%xmm8\n\t" \
- /*xmm4 = f3 e3 f2 e2 f1 e1 f0 e0*/ \
- "punpcklwd %%xmm5,%%xmm4\n\t" \
- /*xmm8 = f7 e7 f6 e6 f5 e5 f4 e4*/ \
- "punpckhwd %%xmm5,%%xmm8\n\t" \
- /*xmm5 is free.*/ \
- "movdqa %%xmm0,%%xmm5\n\t" \
- /*xmm0 = b3 a3 b2 a2 b1 a1 b0 a0*/ \
- "punpcklwd %%xmm1,%%xmm0\n\t" \
- /*xmm5 = b7 a7 b6 a6 b5 a5 b4 a4*/ \
- "punpckhwd %%xmm1,%%xmm5\n\t" \
- /*xmm1 is free.*/ \
- "movdqa %%xmm6,%%xmm1\n\t" \
- /*xmm6 = h3 g3 h2 g2 h1 g1 h0 g0*/ \
- "punpcklwd %%xmm7,%%xmm6\n\t" \
- /*xmm1 = h7 g7 h6 g6 h5 g5 h4 g4*/ \
- "punpckhwd %%xmm7,%%xmm1\n\t" \
- /*xmm7 is free.*/ \
- "movdqa %%xmm2,%%xmm7\n\t" \
- /*xmm7 = d3 c3 d2 c2 d1 c1 d0 c0*/ \
- "punpcklwd %%xmm3,%%xmm7\n\t" \
- /*xmm2 = d7 c7 d6 c6 d5 c5 d4 c4*/ \
- "punpckhwd %%xmm3,%%xmm2\n\t" \
- /*xmm3 is free.*/ \
- "movdqa %%xmm0,%%xmm3\n\t" \
- /*xmm0 = d1 c1 b1 a1 d0 c0 b0 a0*/ \
- "punpckldq %%xmm7,%%xmm0\n\t" \
- /*xmm3 = d3 c3 b3 a3 d2 c2 b2 a2*/ \
- "punpckhdq %%xmm7,%%xmm3\n\t" \
- /*xmm7 is free.*/ \
- "movdqa %%xmm5,%%xmm7\n\t" \
- /*xmm5 = d5 c5 b5 a5 d4 c4 b4 a4*/ \
- "punpckldq %%xmm2,%%xmm5\n\t" \
- /*xmm7 = d7 c7 b7 a7 d6 c6 b6 a6*/ \
- "punpckhdq %%xmm2,%%xmm7\n\t" \
- /*xmm2 is free.*/ \
- "movdqa %%xmm4,%%xmm2\n\t" \
- /*xmm2 = h1 g1 f1 e1 h0 g0 f0 e0*/ \
- "punpckldq %%xmm6,%%xmm2\n\t" \
- /*xmm4 = h3 g3 f3 e3 h2 g2 f2 e2*/ \
- "punpckhdq %%xmm6,%%xmm4\n\t" \
- /*xmm6 is free.*/ \
- "movdqa %%xmm8,%%xmm6\n\t" \
- /*xmm6 = h5 g5 f5 e5 h4 g4 f4 e4*/ \
- "punpckldq %%xmm1,%%xmm6\n\t" \
- /*xmm8 = h7 g7 f7 e7 h6 g6 f6 e6*/ \
- "punpckhdq %%xmm1,%%xmm8\n\t" \
- /*xmm1 is free.*/ \
- "movdqa %%xmm0,%%xmm1\n\t" \
- /*xmm0 = h0 g0 f0 e0 d0 c0 b0 a0*/ \
- "punpcklqdq %%xmm2,%%xmm0\n\t" \
- /*xmm1 = h1 g1 f1 e1 d1 c1 b1 a1*/ \
- "punpckhqdq %%xmm2,%%xmm1\n\t" \
- /*xmm2 is free.*/ \
- "movdqa %%xmm3,%%xmm2\n\t" \
- /*xmm2 = h2 g2 f2 e2 d2 c2 b2 a2*/ \
- "punpcklqdq %%xmm4,%%xmm2\n\t" \
- /*xmm3 = h3 g3 f3 e3 d3 c3 b3 a3*/ \
- "punpckhqdq %%xmm4,%%xmm3\n\t" \
- /*xmm4 is free.*/ \
- "movdqa %%xmm5,%%xmm4\n\t" \
- /*xmm4 = h4 g4 f4 e4 d4 c4 b4 a4*/ \
- "punpcklqdq %%xmm6,%%xmm4\n\t" \
- /*xmm5 = h5 g5 f5 e5 d5 c5 b5 a5*/ \
- "punpckhqdq %%xmm6,%%xmm5\n\t" \
- /*xmm6 is free.*/ \
- "movdqa %%xmm7,%%xmm6\n\t" \
- /*xmm6 = h6 g6 f6 e6 d6 c6 b6 a6*/ \
- "punpcklqdq %%xmm8,%%xmm6\n\t" \
- /*xmm7 = h7 g7 f7 e7 d7 c7 b7 a7*/ \
- "punpckhqdq %%xmm8,%%xmm7\n\t" \
- /*xmm8 is free.*/ \
-
/*SSE2 implementation of the fDCT for x86-64 only.
Because of the 8 extra XMM registers on x86-64, this version can operate
without any temporary stack access at all.*/
@@ -482,12 +409,10 @@ void oc_enc_fdct8x8_x86_64sse2(ogg_int16_t _y[64],const ogg_int16_t _x[64]){
/*xmm1=_x[15...8]-{0,0,0,0,0,0,0,1}*/
"psubw %%xmm9,%%xmm1\n\t"
/*Transform columns.*/
- OC_FDCT8x8
+ OC_FDCT_8x8
/*Transform rows.*/
- OC_TRANSPOSE8x8
- OC_FDCT8x8
- /*TODO: zig-zag ordering?*/
- OC_TRANSPOSE8x8
+ OC_TRANSPOSE_8x8
+ OC_FDCT_8x8
/*xmm14={-2,-2,-2,-2,-2,-2,-2,-2}*/
"paddw %%xmm14,%%xmm14\n\t"
"psubw %%xmm14,%%xmm0\n\t"
@@ -506,15 +431,19 @@ void oc_enc_fdct8x8_x86_64sse2(ogg_int16_t _y[64],const ogg_int16_t _x[64]){
"psubw %%xmm14,%%xmm7\n\t"
"psraw $2,%%xmm6\n\t"
"psraw $2,%%xmm7\n\t"
- /*Store the result.*/
- "movdqa %%xmm0,0x00(%[y])\n\t"
- "movdqa %%xmm1,0x10(%[y])\n\t"
- "movdqa %%xmm2,0x20(%[y])\n\t"
- "movdqa %%xmm3,0x30(%[y])\n\t"
- "movdqa %%xmm4,0x40(%[y])\n\t"
- "movdqa %%xmm5,0x50(%[y])\n\t"
- "movdqa %%xmm6,0x60(%[y])\n\t"
- "movdqa %%xmm7,0x70(%[y])\n\t"
+ /*Transpose, zig-zag, and store the result.*/
+ /*We could probably do better using SSSE3's palignr, but re-using MMXEXT
+ version will do for now.*/
+#define OC_ZZ_LOAD_ROW_LO(_row,_reg) \
+ "movdq2q %%xmm"#_row","_reg"\n\t" \
+
+#define OC_ZZ_LOAD_ROW_HI(_row,_reg) \
+ "punpckhqdq %%xmm"#_row",%%xmm"#_row"\n\t" \
+ "movdq2q %%xmm"#_row","_reg"\n\t" \
+
+ OC_TRANSPOSE_ZIG_ZAG_MMXEXT
+#undef OC_ZZ_LOAD_ROW_LO
+#undef OC_ZZ_LOAD_ROW_HI
:[a]"=&r"(a)
:[y]"r"(_y),[x]"r"(_x)
:"memory"
diff --git a/thirdparty/libtheora/x86/sse2idct.c b/thirdparty/libtheora/x86/sse2idct.c
new file mode 100644
index 0000000000..4597ab074f
--- /dev/null
+++ b/thirdparty/libtheora/x86/sse2idct.c
@@ -0,0 +1,456 @@
+/********************************************************************
+ * *
+ * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. *
+ * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
+ * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
+ * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
+ * *
+ * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 *
+ * by the Xiph.Org Foundation and contributors http://www.xiph.org/ *
+ * *
+ ********************************************************************
+
+ function:
+ last mod: $Id: mmxidct.c 16503 2009-08-22 18:14:02Z giles $
+
+ ********************************************************************/
+
+/*SSE2 acceleration of Theora's iDCT.*/
+#include "x86int.h"
+#include "sse2trans.h"
+#include "../dct.h"
+
+#if defined(OC_X86_ASM)
+
+/*A table of constants used by the MMX routines.*/
+const unsigned short __attribute__((aligned(16),used)) OC_IDCT_CONSTS[64]={
+ 8, 8, 8, 8, 8, 8, 8, 8,
+ OC_C1S7,OC_C1S7,OC_C1S7,OC_C1S7,OC_C1S7,OC_C1S7,OC_C1S7,OC_C1S7,
+ OC_C2S6,OC_C2S6,OC_C2S6,OC_C2S6,OC_C2S6,OC_C2S6,OC_C2S6,OC_C2S6,
+ OC_C3S5,OC_C3S5,OC_C3S5,OC_C3S5,OC_C3S5,OC_C3S5,OC_C3S5,OC_C3S5,
+ OC_C4S4,OC_C4S4,OC_C4S4,OC_C4S4,OC_C4S4,OC_C4S4,OC_C4S4,OC_C4S4,
+ OC_C5S3,OC_C5S3,OC_C5S3,OC_C5S3,OC_C5S3,OC_C5S3,OC_C5S3,OC_C5S3,
+ OC_C6S2,OC_C6S2,OC_C6S2,OC_C6S2,OC_C6S2,OC_C6S2,OC_C6S2,OC_C6S2,
+ OC_C7S1,OC_C7S1,OC_C7S1,OC_C7S1,OC_C7S1,OC_C7S1,OC_C7S1,OC_C7S1
+};
+
+
+/*Performs the first three stages of the iDCT.
+ xmm2, xmm6, xmm3, and xmm5 must contain the corresponding rows of the input
+ (accessed in that order).
+ The remaining rows must be in _x at their corresponding locations.
+ On output, xmm7 down to xmm4 contain rows 0 through 3, and xmm0 up to xmm3
+ contain rows 4 through 7.*/
+#define OC_IDCT_8x8_ABC(_x) \
+ "#OC_IDCT_8x8_ABC\n\t" \
+ /*Stage 1:*/ \
+ /*2-3 rotation by 6pi/16. \
+ xmm4=xmm7=C6, xmm0=xmm1=C2, xmm2=X2, xmm6=X6.*/ \
+ "movdqa "OC_MEM_OFFS(0x20,c)",%%xmm1\n\t" \
+ "movdqa "OC_MEM_OFFS(0x60,c)",%%xmm4\n\t" \
+ "movdqa %%xmm1,%%xmm0\n\t" \
+ "pmulhw %%xmm2,%%xmm1\n\t" \
+ "movdqa %%xmm4,%%xmm7\n\t" \
+ "pmulhw %%xmm6,%%xmm0\n\t" \
+ "pmulhw %%xmm2,%%xmm7\n\t" \
+ "pmulhw %%xmm6,%%xmm4\n\t" \
+ "paddw %%xmm6,%%xmm0\n\t" \
+ "movdqa "OC_MEM_OFFS(0x30,c)",%%xmm6\n\t" \
+ "paddw %%xmm1,%%xmm2\n\t" \
+ "psubw %%xmm0,%%xmm7\n\t" \
+ "movdqa %%xmm7,"OC_MEM_OFFS(0x00,buf)"\n\t" \
+ "paddw %%xmm4,%%xmm2\n\t" \
+ "movdqa "OC_MEM_OFFS(0x50,c)",%%xmm4\n\t" \
+ "movdqa %%xmm2,"OC_MEM_OFFS(0x10,buf)"\n\t" \
+ /*5-6 rotation by 3pi/16. \
+ xmm4=xmm2=C5, xmm1=xmm6=C3, xmm3=X3, xmm5=X5.*/ \
+ "movdqa %%xmm4,%%xmm2\n\t" \
+ "movdqa %%xmm6,%%xmm1\n\t" \
+ "pmulhw %%xmm3,%%xmm4\n\t" \
+ "pmulhw %%xmm5,%%xmm1\n\t" \
+ "pmulhw %%xmm3,%%xmm6\n\t" \
+ "pmulhw %%xmm5,%%xmm2\n\t" \
+ "paddw %%xmm3,%%xmm4\n\t" \
+ "paddw %%xmm5,%%xmm3\n\t" \
+ "paddw %%xmm6,%%xmm3\n\t" \
+ "movdqa "OC_MEM_OFFS(0x70,_x)",%%xmm6\n\t" \
+ "paddw %%xmm5,%%xmm1\n\t" \
+ "movdqa "OC_MEM_OFFS(0x10,_x)",%%xmm5\n\t" \
+ "paddw %%xmm3,%%xmm2\n\t" \
+ "movdqa "OC_MEM_OFFS(0x70,c)",%%xmm3\n\t" \
+ "psubw %%xmm4,%%xmm1\n\t" \
+ "movdqa "OC_MEM_OFFS(0x10,c)",%%xmm4\n\t" \
+ /*4-7 rotation by 7pi/16. \
+ xmm4=xmm7=C1, xmm3=xmm0=C7, xmm5=X1, xmm6=X7.*/ \
+ "movdqa %%xmm3,%%xmm0\n\t" \
+ "movdqa %%xmm4,%%xmm7\n\t" \
+ "pmulhw %%xmm5,%%xmm3\n\t" \
+ "pmulhw %%xmm5,%%xmm7\n\t" \
+ "pmulhw %%xmm6,%%xmm4\n\t" \
+ "pmulhw %%xmm6,%%xmm0\n\t" \
+ "paddw %%xmm6,%%xmm4\n\t" \
+ "movdqa "OC_MEM_OFFS(0x40,_x)",%%xmm6\n\t" \
+ "paddw %%xmm5,%%xmm7\n\t" \
+ "psubw %%xmm4,%%xmm3\n\t" \
+ "movdqa "OC_MEM_OFFS(0x40,c)",%%xmm4\n\t" \
+ "paddw %%xmm7,%%xmm0\n\t" \
+ "movdqa "OC_MEM_OFFS(0x00,_x)",%%xmm7\n\t" \
+ /*0-1 butterfly. \
+ xmm4=xmm5=C4, xmm7=X0, xmm6=X4.*/ \
+ "paddw %%xmm7,%%xmm6\n\t" \
+ "movdqa %%xmm4,%%xmm5\n\t" \
+ "pmulhw %%xmm6,%%xmm4\n\t" \
+ "paddw %%xmm7,%%xmm7\n\t" \
+ "psubw %%xmm6,%%xmm7\n\t" \
+ "paddw %%xmm6,%%xmm4\n\t" \
+ /*Stage 2:*/ \
+ /*4-5 butterfly: xmm3=t[4], xmm1=t[5] \
+ 7-6 butterfly: xmm2=t[6], xmm0=t[7]*/ \
+ "movdqa %%xmm3,%%xmm6\n\t" \
+ "paddw %%xmm1,%%xmm3\n\t" \
+ "psubw %%xmm1,%%xmm6\n\t" \
+ "movdqa %%xmm5,%%xmm1\n\t" \
+ "pmulhw %%xmm7,%%xmm5\n\t" \
+ "paddw %%xmm7,%%xmm5\n\t" \
+ "movdqa %%xmm0,%%xmm7\n\t" \
+ "paddw %%xmm2,%%xmm0\n\t" \
+ "psubw %%xmm2,%%xmm7\n\t" \
+ "movdqa %%xmm1,%%xmm2\n\t" \
+ "pmulhw %%xmm6,%%xmm1\n\t" \
+ "pmulhw %%xmm7,%%xmm2\n\t" \
+ "paddw %%xmm6,%%xmm1\n\t" \
+ "movdqa "OC_MEM_OFFS(0x00,buf)",%%xmm6\n\t" \
+ "paddw %%xmm7,%%xmm2\n\t" \
+ "movdqa "OC_MEM_OFFS(0x10,buf)",%%xmm7\n\t" \
+ /*Stage 3: \
+ 6-5 butterfly: xmm1=t[5], xmm2=t[6] -> xmm1=t[6]+t[5], xmm2=t[6]-t[5] \
+ 0-3 butterfly: xmm4=t[0], xmm7=t[3] -> xmm7=t[0]+t[3], xmm4=t[0]-t[3] \
+ 1-2 butterfly: xmm5=t[1], xmm6=t[2] -> xmm6=t[1]+t[2], xmm5=t[1]-t[2]*/ \
+ "paddw %%xmm2,%%xmm1\n\t" \
+ "paddw %%xmm5,%%xmm6\n\t" \
+ "paddw %%xmm4,%%xmm7\n\t" \
+ "paddw %%xmm2,%%xmm2\n\t" \
+ "paddw %%xmm4,%%xmm4\n\t" \
+ "paddw %%xmm5,%%xmm5\n\t" \
+ "psubw %%xmm1,%%xmm2\n\t" \
+ "psubw %%xmm7,%%xmm4\n\t" \
+ "psubw %%xmm6,%%xmm5\n\t" \
+
+/*Performs the last stage of the iDCT.
+ On input, xmm7 down to xmm4 contain rows 0 through 3, and xmm0 up to xmm3
+ contain rows 4 through 7.
+ On output, xmm0 through xmm7 contain the corresponding rows.*/
+#define OC_IDCT_8x8_D \
+ "#OC_IDCT_8x8_D\n\t" \
+ /*Stage 4: \
+ 0-7 butterfly: xmm7=t[0], xmm0=t[7] -> xmm0=t[0]+t[7], xmm7=t[0]-t[7] \
+ 1-6 butterfly: xmm6=t[1], xmm1=t[6] -> xmm1=t[1]+t[6], xmm6=t[1]-t[6] \
+ 2-5 butterfly: xmm5=t[2], xmm2=t[5] -> xmm2=t[2]+t[5], xmm5=t[2]-t[5] \
+ 3-4 butterfly: xmm4=t[3], xmm3=t[4] -> xmm3=t[3]+t[4], xmm4=t[3]-t[4]*/ \
+ "psubw %%xmm0,%%xmm7\n\t" \
+ "psubw %%xmm1,%%xmm6\n\t" \
+ "psubw %%xmm2,%%xmm5\n\t" \
+ "psubw %%xmm3,%%xmm4\n\t" \
+ "paddw %%xmm0,%%xmm0\n\t" \
+ "paddw %%xmm1,%%xmm1\n\t" \
+ "paddw %%xmm2,%%xmm2\n\t" \
+ "paddw %%xmm3,%%xmm3\n\t" \
+ "paddw %%xmm7,%%xmm0\n\t" \
+ "paddw %%xmm6,%%xmm1\n\t" \
+ "paddw %%xmm5,%%xmm2\n\t" \
+ "paddw %%xmm4,%%xmm3\n\t" \
+
+/*Performs the last stage of the iDCT.
+ On input, xmm7 down to xmm4 contain rows 0 through 3, and xmm0 up to xmm3
+ contain rows 4 through 7.
+ On output, xmm0 through xmm7 contain the corresponding rows.*/
+#define OC_IDCT_8x8_D_STORE \
+ "#OC_IDCT_8x8_D_STORE\n\t" \
+ /*Stage 4: \
+ 0-7 butterfly: xmm7=t[0], xmm0=t[7] -> xmm0=t[0]+t[7], xmm7=t[0]-t[7] \
+ 1-6 butterfly: xmm6=t[1], xmm1=t[6] -> xmm1=t[1]+t[6], xmm6=t[1]-t[6] \
+ 2-5 butterfly: xmm5=t[2], xmm2=t[5] -> xmm2=t[2]+t[5], xmm5=t[2]-t[5] \
+ 3-4 butterfly: xmm4=t[3], xmm3=t[4] -> xmm3=t[3]+t[4], xmm4=t[3]-t[4]*/ \
+ "psubw %%xmm3,%%xmm4\n\t" \
+ "movdqa %%xmm4,"OC_MEM_OFFS(0x40,y)"\n\t" \
+ "movdqa "OC_MEM_OFFS(0x00,c)",%%xmm4\n\t" \
+ "psubw %%xmm0,%%xmm7\n\t" \
+ "psubw %%xmm1,%%xmm6\n\t" \
+ "psubw %%xmm2,%%xmm5\n\t" \
+ "paddw %%xmm4,%%xmm7\n\t" \
+ "paddw %%xmm4,%%xmm6\n\t" \
+ "paddw %%xmm4,%%xmm5\n\t" \
+ "paddw "OC_MEM_OFFS(0x40,y)",%%xmm4\n\t" \
+ "paddw %%xmm0,%%xmm0\n\t" \
+ "paddw %%xmm1,%%xmm1\n\t" \
+ "paddw %%xmm2,%%xmm2\n\t" \
+ "paddw %%xmm3,%%xmm3\n\t" \
+ "paddw %%xmm7,%%xmm0\n\t" \
+ "paddw %%xmm6,%%xmm1\n\t" \
+ "psraw $4,%%xmm0\n\t" \
+ "paddw %%xmm5,%%xmm2\n\t" \
+ "movdqa %%xmm0,"OC_MEM_OFFS(0x00,y)"\n\t" \
+ "psraw $4,%%xmm1\n\t" \
+ "paddw %%xmm4,%%xmm3\n\t" \
+ "movdqa %%xmm1,"OC_MEM_OFFS(0x10,y)"\n\t" \
+ "psraw $4,%%xmm2\n\t" \
+ "movdqa %%xmm2,"OC_MEM_OFFS(0x20,y)"\n\t" \
+ "psraw $4,%%xmm3\n\t" \
+ "movdqa %%xmm3,"OC_MEM_OFFS(0x30,y)"\n\t" \
+ "psraw $4,%%xmm4\n\t" \
+ "movdqa %%xmm4,"OC_MEM_OFFS(0x40,y)"\n\t" \
+ "psraw $4,%%xmm5\n\t" \
+ "movdqa %%xmm5,"OC_MEM_OFFS(0x50,y)"\n\t" \
+ "psraw $4,%%xmm6\n\t" \
+ "movdqa %%xmm6,"OC_MEM_OFFS(0x60,y)"\n\t" \
+ "psraw $4,%%xmm7\n\t" \
+ "movdqa %%xmm7,"OC_MEM_OFFS(0x70,y)"\n\t" \
+
+static void oc_idct8x8_slow_sse2(ogg_int16_t _y[64],ogg_int16_t _x[64]){
+ OC_ALIGN16(ogg_int16_t buf[16]);
+ int i;
+ /*This routine accepts an 8x8 matrix pre-transposed.*/
+ __asm__ __volatile__(
+ /*Load rows 2, 3, 5, and 6 for the first stage of the iDCT.*/
+ "movdqa "OC_MEM_OFFS(0x20,x)",%%xmm2\n\t"
+ "movdqa "OC_MEM_OFFS(0x60,x)",%%xmm6\n\t"
+ "movdqa "OC_MEM_OFFS(0x30,x)",%%xmm3\n\t"
+ "movdqa "OC_MEM_OFFS(0x50,x)",%%xmm5\n\t"
+ OC_IDCT_8x8_ABC(x)
+ OC_IDCT_8x8_D
+ OC_TRANSPOSE_8x8
+ /*Clear out rows 0, 1, 4, and 7 for the first stage of the iDCT.*/
+ "movdqa %%xmm7,"OC_MEM_OFFS(0x70,y)"\n\t"
+ "movdqa %%xmm4,"OC_MEM_OFFS(0x40,y)"\n\t"
+ "movdqa %%xmm1,"OC_MEM_OFFS(0x10,y)"\n\t"
+ "movdqa %%xmm0,"OC_MEM_OFFS(0x00,y)"\n\t"
+ OC_IDCT_8x8_ABC(y)
+ OC_IDCT_8x8_D_STORE
+ :[buf]"=m"(OC_ARRAY_OPERAND(ogg_int16_t,buf,16)),
+ [y]"=m"(OC_ARRAY_OPERAND(ogg_int16_t,_y,64))
+ :[x]"m"(OC_CONST_ARRAY_OPERAND(ogg_int16_t,_x,64)),
+ [c]"m"(OC_CONST_ARRAY_OPERAND(ogg_int16_t,OC_IDCT_CONSTS,128))
+ );
+ __asm__ __volatile__("pxor %%xmm0,%%xmm0\n\t"::);
+ /*Clear input data for next block (decoder only).*/
+ for(i=0;i<2;i++){
+ __asm__ __volatile__(
+ "movdqa %%xmm0,"OC_MEM_OFFS(0x00,x)"\n\t"
+ "movdqa %%xmm0,"OC_MEM_OFFS(0x10,x)"\n\t"
+ "movdqa %%xmm0,"OC_MEM_OFFS(0x20,x)"\n\t"
+ "movdqa %%xmm0,"OC_MEM_OFFS(0x30,x)"\n\t"
+ :[x]"=m"(OC_ARRAY_OPERAND(ogg_int16_t,_x+i*32,32))
+ );
+ }
+}
+
+/*For the first step of the 10-coefficient version of the 8x8 iDCT, we only
+ need to work with four columns at a time.
+ Doing this in MMX is faster on processors with a 64-bit data path.*/
+#define OC_IDCT_8x8_10_MMX \
+ "#OC_IDCT_8x8_10_MMX\n\t" \
+ /*Stage 1:*/ \
+ /*2-3 rotation by 6pi/16. \
+ mm7=C6, mm6=C2, mm2=X2, X6=0.*/ \
+ "movq "OC_MEM_OFFS(0x60,c)",%%mm7\n\t" \
+ "movq "OC_MEM_OFFS(0x20,c)",%%mm6\n\t" \
+ "pmulhw %%mm2,%%mm6\n\t" \
+ "pmulhw %%mm2,%%mm7\n\t" \
+ "movq "OC_MEM_OFFS(0x50,c)",%%mm5\n\t" \
+ "paddw %%mm6,%%mm2\n\t" \
+ "movq %%mm2,"OC_MEM_OFFS(0x10,buf)"\n\t" \
+ "movq "OC_MEM_OFFS(0x30,c)",%%mm2\n\t" \
+ "movq %%mm7,"OC_MEM_OFFS(0x00,buf)"\n\t" \
+ /*5-6 rotation by 3pi/16. \
+ mm5=C5, mm2=C3, mm3=X3, X5=0.*/ \
+ "pmulhw %%mm3,%%mm5\n\t" \
+ "pmulhw %%mm3,%%mm2\n\t" \
+ "movq "OC_MEM_OFFS(0x10,c)",%%mm7\n\t" \
+ "paddw %%mm3,%%mm5\n\t" \
+ "paddw %%mm3,%%mm2\n\t" \
+ "movq "OC_MEM_OFFS(0x70,c)",%%mm3\n\t" \
+ /*4-7 rotation by 7pi/16. \
+ mm7=C1, mm3=C7, mm1=X1, X7=0.*/ \
+ "pmulhw %%mm1,%%mm3\n\t" \
+ "pmulhw %%mm1,%%mm7\n\t" \
+ "movq "OC_MEM_OFFS(0x40,c)",%%mm4\n\t" \
+ "movq %%mm3,%%mm6\n\t" \
+ "paddw %%mm1,%%mm7\n\t" \
+ /*0-1 butterfly. \
+ mm4=C4, mm0=X0, X4=0.*/ \
+ /*Stage 2:*/ \
+ /*4-5 butterfly: mm3=t[4], mm5=t[5] \
+ 7-6 butterfly: mm2=t[6], mm7=t[7]*/ \
+ "psubw %%mm5,%%mm3\n\t" \
+ "paddw %%mm5,%%mm6\n\t" \
+ "movq %%mm4,%%mm1\n\t" \
+ "pmulhw %%mm0,%%mm4\n\t" \
+ "paddw %%mm0,%%mm4\n\t" \
+ "movq %%mm7,%%mm0\n\t" \
+ "movq %%mm4,%%mm5\n\t" \
+ "paddw %%mm2,%%mm0\n\t" \
+ "psubw %%mm2,%%mm7\n\t" \
+ "movq %%mm1,%%mm2\n\t" \
+ "pmulhw %%mm6,%%mm1\n\t" \
+ "pmulhw %%mm7,%%mm2\n\t" \
+ "paddw %%mm6,%%mm1\n\t" \
+ "movq "OC_MEM_OFFS(0x00,buf)",%%mm6\n\t" \
+ "paddw %%mm7,%%mm2\n\t" \
+ "movq "OC_MEM_OFFS(0x10,buf)",%%mm7\n\t" \
+ /*Stage 3: \
+ 6-5 butterfly: mm1=t[5], mm2=t[6] -> mm1=t[6]+t[5], mm2=t[6]-t[5] \
+ 0-3 butterfly: mm4=t[0], mm7=t[3] -> mm7=t[0]+t[3], mm4=t[0]-t[3] \
+ 1-2 butterfly: mm5=t[1], mm6=t[2] -> mm6=t[1]+t[2], mm5=t[1]-t[2]*/ \
+ "paddw %%mm2,%%mm1\n\t" \
+ "paddw %%mm5,%%mm6\n\t" \
+ "paddw %%mm4,%%mm7\n\t" \
+ "paddw %%mm2,%%mm2\n\t" \
+ "paddw %%mm4,%%mm4\n\t" \
+ "paddw %%mm5,%%mm5\n\t" \
+ "psubw %%mm1,%%mm2\n\t" \
+ "psubw %%mm7,%%mm4\n\t" \
+ "psubw %%mm6,%%mm5\n\t" \
+ /*Stage 4: \
+ 0-7 butterfly: mm7=t[0], mm0=t[7] -> mm0=t[0]+t[7], mm7=t[0]-t[7] \
+ 1-6 butterfly: mm6=t[1], mm1=t[6] -> mm1=t[1]+t[6], mm6=t[1]-t[6] \
+ 2-5 butterfly: mm5=t[2], mm2=t[5] -> mm2=t[2]+t[5], mm5=t[2]-t[5] \
+ 3-4 butterfly: mm4=t[3], mm3=t[4] -> mm3=t[3]+t[4], mm4=t[3]-t[4]*/ \
+ "psubw %%mm0,%%mm7\n\t" \
+ "psubw %%mm1,%%mm6\n\t" \
+ "psubw %%mm2,%%mm5\n\t" \
+ "psubw %%mm3,%%mm4\n\t" \
+ "paddw %%mm0,%%mm0\n\t" \
+ "paddw %%mm1,%%mm1\n\t" \
+ "paddw %%mm2,%%mm2\n\t" \
+ "paddw %%mm3,%%mm3\n\t" \
+ "paddw %%mm7,%%mm0\n\t" \
+ "paddw %%mm6,%%mm1\n\t" \
+ "paddw %%mm5,%%mm2\n\t" \
+ "paddw %%mm4,%%mm3\n\t" \
+
+#define OC_IDCT_8x8_10_ABC \
+ "#OC_IDCT_8x8_10_ABC\n\t" \
+ /*Stage 1:*/ \
+ /*2-3 rotation by 6pi/16. \
+ xmm7=C6, xmm6=C2, xmm2=X2, X6=0.*/ \
+ "movdqa "OC_MEM_OFFS(0x60,c)",%%xmm7\n\t" \
+ "movdqa "OC_MEM_OFFS(0x20,c)",%%xmm6\n\t" \
+ "pmulhw %%xmm2,%%xmm6\n\t" \
+ "pmulhw %%xmm2,%%xmm7\n\t" \
+ "movdqa "OC_MEM_OFFS(0x50,c)",%%xmm5\n\t" \
+ "paddw %%xmm6,%%xmm2\n\t" \
+ "movdqa %%xmm2,"OC_MEM_OFFS(0x10,buf)"\n\t" \
+ "movdqa "OC_MEM_OFFS(0x30,c)",%%xmm2\n\t" \
+ "movdqa %%xmm7,"OC_MEM_OFFS(0x00,buf)"\n\t" \
+ /*5-6 rotation by 3pi/16. \
+ xmm5=C5, xmm2=C3, xmm3=X3, X5=0.*/ \
+ "pmulhw %%xmm3,%%xmm5\n\t" \
+ "pmulhw %%xmm3,%%xmm2\n\t" \
+ "movdqa "OC_MEM_OFFS(0x10,c)",%%xmm7\n\t" \
+ "paddw %%xmm3,%%xmm5\n\t" \
+ "paddw %%xmm3,%%xmm2\n\t" \
+ "movdqa "OC_MEM_OFFS(0x70,c)",%%xmm3\n\t" \
+ /*4-7 rotation by 7pi/16. \
+ xmm7=C1, xmm3=C7, xmm1=X1, X7=0.*/ \
+ "pmulhw %%xmm1,%%xmm3\n\t" \
+ "pmulhw %%xmm1,%%xmm7\n\t" \
+ "movdqa "OC_MEM_OFFS(0x40,c)",%%xmm4\n\t" \
+ "movdqa %%xmm3,%%xmm6\n\t" \
+ "paddw %%xmm1,%%xmm7\n\t" \
+ /*0-1 butterfly. \
+ xmm4=C4, xmm0=X0, X4=0.*/ \
+ /*Stage 2:*/ \
+ /*4-5 butterfly: xmm3=t[4], xmm5=t[5] \
+ 7-6 butterfly: xmm2=t[6], xmm7=t[7]*/ \
+ "psubw %%xmm5,%%xmm3\n\t" \
+ "paddw %%xmm5,%%xmm6\n\t" \
+ "movdqa %%xmm4,%%xmm1\n\t" \
+ "pmulhw %%xmm0,%%xmm4\n\t" \
+ "paddw %%xmm0,%%xmm4\n\t" \
+ "movdqa %%xmm7,%%xmm0\n\t" \
+ "movdqa %%xmm4,%%xmm5\n\t" \
+ "paddw %%xmm2,%%xmm0\n\t" \
+ "psubw %%xmm2,%%xmm7\n\t" \
+ "movdqa %%xmm1,%%xmm2\n\t" \
+ "pmulhw %%xmm6,%%xmm1\n\t" \
+ "pmulhw %%xmm7,%%xmm2\n\t" \
+ "paddw %%xmm6,%%xmm1\n\t" \
+ "movdqa "OC_MEM_OFFS(0x00,buf)",%%xmm6\n\t" \
+ "paddw %%xmm7,%%xmm2\n\t" \
+ "movdqa "OC_MEM_OFFS(0x10,buf)",%%xmm7\n\t" \
+ /*Stage 3: \
+ 6-5 butterfly: xmm1=t[5], xmm2=t[6] -> xmm1=t[6]+t[5], xmm2=t[6]-t[5] \
+ 0-3 butterfly: xmm4=t[0], xmm7=t[3] -> xmm7=t[0]+t[3], xmm4=t[0]-t[3] \
+ 1-2 butterfly: xmm5=t[1], xmm6=t[2] -> xmm6=t[1]+t[2], xmm5=t[1]-t[2]*/ \
+ "paddw %%xmm2,%%xmm1\n\t" \
+ "paddw %%xmm5,%%xmm6\n\t" \
+ "paddw %%xmm4,%%xmm7\n\t" \
+ "paddw %%xmm2,%%xmm2\n\t" \
+ "paddw %%xmm4,%%xmm4\n\t" \
+ "paddw %%xmm5,%%xmm5\n\t" \
+ "psubw %%xmm1,%%xmm2\n\t" \
+ "psubw %%xmm7,%%xmm4\n\t" \
+ "psubw %%xmm6,%%xmm5\n\t" \
+
+static void oc_idct8x8_10_sse2(ogg_int16_t _y[64],ogg_int16_t _x[64]){
+ OC_ALIGN16(ogg_int16_t buf[16]);
+ /*This routine accepts an 8x8 matrix pre-transposed.*/
+ __asm__ __volatile__(
+ "movq "OC_MEM_OFFS(0x20,x)",%%mm2\n\t"
+ "movq "OC_MEM_OFFS(0x30,x)",%%mm3\n\t"
+ "movq "OC_MEM_OFFS(0x10,x)",%%mm1\n\t"
+ "movq "OC_MEM_OFFS(0x00,x)",%%mm0\n\t"
+ OC_IDCT_8x8_10_MMX
+ OC_TRANSPOSE_8x4_MMX2SSE
+ OC_IDCT_8x8_10_ABC
+ OC_IDCT_8x8_D_STORE
+ :[buf]"=m"(OC_ARRAY_OPERAND(short,buf,16)),
+ [y]"=m"(OC_ARRAY_OPERAND(ogg_int16_t,_y,64))
+ :[x]"m"OC_CONST_ARRAY_OPERAND(ogg_int16_t,_x,64),
+ [c]"m"(OC_CONST_ARRAY_OPERAND(ogg_int16_t,OC_IDCT_CONSTS,128))
+ );
+ /*Clear input data for next block (decoder only).*/
+ __asm__ __volatile__(
+ "pxor %%mm0,%%mm0\n\t"
+ "movq %%mm0,"OC_MEM_OFFS(0x00,x)"\n\t"
+ "movq %%mm0,"OC_MEM_OFFS(0x10,x)"\n\t"
+ "movq %%mm0,"OC_MEM_OFFS(0x20,x)"\n\t"
+ "movq %%mm0,"OC_MEM_OFFS(0x30,x)"\n\t"
+ :[x]"+m"(OC_ARRAY_OPERAND(ogg_int16_t,_x,28))
+ );
+}
+
+/*Performs an inverse 8x8 Type-II DCT transform.
+ The input is assumed to be scaled by a factor of 4 relative to orthonormal
+ version of the transform.*/
+void oc_idct8x8_sse2(ogg_int16_t _y[64],ogg_int16_t _x[64],int _last_zzi){
+ /*_last_zzi is subtly different from an actual count of the number of
+ coefficients we decoded for this block.
+ It contains the value of zzi BEFORE the final token in the block was
+ decoded.
+ In most cases this is an EOB token (the continuation of an EOB run from a
+ previous block counts), and so this is the same as the coefficient count.
+ However, in the case that the last token was NOT an EOB token, but filled
+ the block up with exactly 64 coefficients, _last_zzi will be less than 64.
+ Provided the last token was not a pure zero run, the minimum value it can
+ be is 46, and so that doesn't affect any of the cases in this routine.
+ However, if the last token WAS a pure zero run of length 63, then _last_zzi
+ will be 1 while the number of coefficients decoded is 64.
+ Thus, we will trigger the following special case, where the real
+ coefficient count would not.
+ Note also that a zero run of length 64 will give _last_zzi a value of 0,
+ but we still process the DC coefficient, which might have a non-zero value
+ due to DC prediction.
+ Although convoluted, this is arguably the correct behavior: it allows us to
+ use a smaller transform when the block ends with a long zero run instead
+ of a normal EOB token.
+ It could be smarter... multiple separate zero runs at the end of a block
+ will fool it, but an encoder that generates these really deserves what it
+ gets.
+ Needless to say we inherited this approach from VP3.*/
+ /*Then perform the iDCT.*/
+ if(_last_zzi<=10)oc_idct8x8_10_sse2(_y,_x);
+ else oc_idct8x8_slow_sse2(_y,_x);
+}
+
+#endif
diff --git a/thirdparty/libtheora/x86/sse2trans.h b/thirdparty/libtheora/x86/sse2trans.h
new file mode 100644
index 0000000000..e76da5140b
--- /dev/null
+++ b/thirdparty/libtheora/x86/sse2trans.h
@@ -0,0 +1,242 @@
+/********************************************************************
+ * *
+ * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. *
+ * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
+ * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
+ * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
+ * *
+ * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 *
+ * by the Xiph.Org Foundation and contributors http://www.xiph.org/ *
+ * *
+ ********************************************************************
+
+ function:
+ last mod: $Id: sse2trans.h 15675 2009-02-06 09:43:27Z tterribe $
+
+ ********************************************************************/
+
+#if !defined(_x86_sse2trans_H)
+# define _x86_sse2trans_H (1)
+# include "x86int.h"
+
+# if defined(OC_X86_64_ASM)
+/*On x86-64 we can transpose in-place without spilling registers.
+ By clever choices of the order to apply the butterflies and the order of
+ their outputs, we can take the rows in order and output the columns in order
+ without any extra operations and using just one temporary register.*/
+# define OC_TRANSPOSE_8x8 \
+ "#OC_TRANSPOSE_8x8\n\t" \
+ "movdqa %%xmm4,%%xmm8\n\t" \
+ /*xmm4 = f3 e3 f2 e2 f1 e1 f0 e0*/ \
+ "punpcklwd %%xmm5,%%xmm4\n\t" \
+ /*xmm8 = f7 e7 f6 e6 f5 e5 f4 e4*/ \
+ "punpckhwd %%xmm5,%%xmm8\n\t" \
+ /*xmm5 is free.*/ \
+ "movdqa %%xmm0,%%xmm5\n\t" \
+ /*xmm0 = b3 a3 b2 a2 b1 a1 b0 a0*/ \
+ "punpcklwd %%xmm1,%%xmm0\n\t" \
+ /*xmm5 = b7 a7 b6 a6 b5 a5 b4 a4*/ \
+ "punpckhwd %%xmm1,%%xmm5\n\t" \
+ /*xmm1 is free.*/ \
+ "movdqa %%xmm6,%%xmm1\n\t" \
+ /*xmm6 = h3 g3 h2 g2 h1 g1 h0 g0*/ \
+ "punpcklwd %%xmm7,%%xmm6\n\t" \
+ /*xmm1 = h7 g7 h6 g6 h5 g5 h4 g4*/ \
+ "punpckhwd %%xmm7,%%xmm1\n\t" \
+ /*xmm7 is free.*/ \
+ "movdqa %%xmm2,%%xmm7\n\t" \
+ /*xmm2 = d7 c7 d6 c6 d5 c5 d4 c4*/ \
+ "punpckhwd %%xmm3,%%xmm2\n\t" \
+ /*xmm7 = d3 c3 d2 c2 d1 c1 d0 c0*/ \
+ "punpcklwd %%xmm3,%%xmm7\n\t" \
+ /*xmm3 is free.*/ \
+ "movdqa %%xmm0,%%xmm3\n\t" \
+ /*xmm0 = d1 c1 b1 a1 d0 c0 b0 a0*/ \
+ "punpckldq %%xmm7,%%xmm0\n\t" \
+ /*xmm3 = d3 c3 b3 a3 d2 c2 b2 a2*/ \
+ "punpckhdq %%xmm7,%%xmm3\n\t" \
+ /*xmm7 is free.*/ \
+ "movdqa %%xmm5,%%xmm7\n\t" \
+ /*xmm5 = d5 c5 b5 a5 d4 c4 b4 a4*/ \
+ "punpckldq %%xmm2,%%xmm5\n\t" \
+ /*xmm7 = d7 c7 b7 a7 d6 c6 b6 a6*/ \
+ "punpckhdq %%xmm2,%%xmm7\n\t" \
+ /*xmm2 is free.*/ \
+ "movdqa %%xmm4,%%xmm2\n\t" \
+ /*xmm4 = h3 g3 f3 e3 h2 g2 f2 e2*/ \
+ "punpckhdq %%xmm6,%%xmm4\n\t" \
+ /*xmm2 = h1 g1 f1 e1 h0 g0 f0 e0*/ \
+ "punpckldq %%xmm6,%%xmm2\n\t" \
+ /*xmm6 is free.*/ \
+ "movdqa %%xmm8,%%xmm6\n\t" \
+ /*xmm6 = h5 g5 f5 e5 h4 g4 f4 e4*/ \
+ "punpckldq %%xmm1,%%xmm6\n\t" \
+ /*xmm8 = h7 g7 f7 e7 h6 g6 f6 e6*/ \
+ "punpckhdq %%xmm1,%%xmm8\n\t" \
+ /*xmm1 is free.*/ \
+ "movdqa %%xmm0,%%xmm1\n\t" \
+ /*xmm0 = h0 g0 f0 e0 d0 c0 b0 a0*/ \
+ "punpcklqdq %%xmm2,%%xmm0\n\t" \
+ /*xmm1 = h1 g1 f1 e1 d1 c1 b1 a1*/ \
+ "punpckhqdq %%xmm2,%%xmm1\n\t" \
+ /*xmm2 is free.*/ \
+ "movdqa %%xmm3,%%xmm2\n\t" \
+ /*xmm3 = h3 g3 f3 e3 d3 c3 b3 a3*/ \
+ "punpckhqdq %%xmm4,%%xmm3\n\t" \
+ /*xmm2 = h2 g2 f2 e2 d2 c2 b2 a2*/ \
+ "punpcklqdq %%xmm4,%%xmm2\n\t" \
+ /*xmm4 is free.*/ \
+ "movdqa %%xmm5,%%xmm4\n\t" \
+ /*xmm5 = h5 g5 f5 e5 d5 c5 b5 a5*/ \
+ "punpckhqdq %%xmm6,%%xmm5\n\t" \
+ /*xmm4 = h4 g4 f4 e4 d4 c4 b4 a4*/ \
+ "punpcklqdq %%xmm6,%%xmm4\n\t" \
+ /*xmm6 is free.*/ \
+ "movdqa %%xmm7,%%xmm6\n\t" \
+ /*xmm7 = h7 g7 f7 e7 d7 c7 b7 a7*/ \
+ "punpckhqdq %%xmm8,%%xmm7\n\t" \
+ /*xmm6 = h6 g6 f6 e6 d6 c6 b6 a6*/ \
+ "punpcklqdq %%xmm8,%%xmm6\n\t" \
+ /*xmm8 is free.*/ \
+
+# else
+/*Otherwise, we need to spill some values to %[buf] temporarily.
+ Again, the butterflies are carefully arranged to get the columns to come out
+ in order, minimizing register spills and maximizing the delay between a load
+ and when the value loaded is actually used.*/
+# define OC_TRANSPOSE_8x8 \
+ "#OC_TRANSPOSE_8x8\n\t" \
+ /*buf[0] = a7 a6 a5 a4 a3 a2 a1 a0*/ \
+ "movdqa %%xmm0,"OC_MEM_OFFS(0x00,buf)"\n\t" \
+ /*xmm0 is free.*/ \
+ "movdqa %%xmm2,%%xmm0\n\t" \
+ /*xmm2 = d7 c7 d6 c6 d5 c5 d4 c4*/ \
+ "punpckhwd %%xmm3,%%xmm2\n\t" \
+ /*xmm0 = d3 c3 d2 c2 d1 c1 d0 c0*/ \
+ "punpcklwd %%xmm3,%%xmm0\n\t" \
+ /*xmm3 = a7 a6 a5 a4 a3 a2 a1 a0*/ \
+ "movdqa "OC_MEM_OFFS(0x00,buf)",%%xmm3\n\t" \
+ /*buf[1] = d7 c7 d6 c6 d5 c5 d4 c4*/ \
+ "movdqa %%xmm2,"OC_MEM_OFFS(0x10,buf)"\n\t" \
+ /*xmm2 is free.*/ \
+ "movdqa %%xmm6,%%xmm2\n\t" \
+ /*xmm6 = h3 g3 h2 g2 h1 g1 h0 g0*/ \
+ "punpcklwd %%xmm7,%%xmm6\n\t" \
+ /*xmm2 = h7 g7 h6 g6 h5 g5 h4 g4*/ \
+ "punpckhwd %%xmm7,%%xmm2\n\t" \
+ /*xmm7 is free.*/ \
+ "movdqa %%xmm4,%%xmm7\n\t" \
+ /*xmm4 = f3 e3 f2 e2 f1 e1 f0 e0*/ \
+ "punpcklwd %%xmm5,%%xmm4\n\t" \
+ /*xmm7 = f7 e7 f6 e6 f5 e5 f4 e4*/ \
+ "punpckhwd %%xmm5,%%xmm7\n\t" \
+ /*xmm5 is free.*/ \
+ "movdqa %%xmm3,%%xmm5\n\t" \
+ /*xmm3 = b3 a3 b2 a2 b1 a1 b0 a0*/ \
+ "punpcklwd %%xmm1,%%xmm3\n\t" \
+ /*xmm5 = b7 a7 b6 a6 b5 a5 b4 a4*/ \
+ "punpckhwd %%xmm1,%%xmm5\n\t" \
+ /*xmm1 is free.*/ \
+ "movdqa %%xmm7,%%xmm1\n\t" \
+ /*xmm7 = h5 g5 f5 e5 h4 g4 f4 e4*/ \
+ "punpckldq %%xmm2,%%xmm7\n\t" \
+ /*xmm1 = h7 g7 f7 e7 h6 g6 f6 e6*/ \
+ "punpckhdq %%xmm2,%%xmm1\n\t" \
+ /*xmm2 = d7 c7 d6 c6 d5 c5 d4 c4*/ \
+ "movdqa "OC_MEM_OFFS(0x10,buf)",%%xmm2\n\t" \
+ /*buf[0] = h7 g7 f7 e7 h6 g6 f6 e6*/ \
+ "movdqa %%xmm1,"OC_MEM_OFFS(0x00,buf)"\n\t" \
+ /*xmm1 is free.*/ \
+ "movdqa %%xmm3,%%xmm1\n\t" \
+ /*xmm3 = d3 c3 b3 a3 d2 c2 b2 a2*/ \
+ "punpckhdq %%xmm0,%%xmm3\n\t" \
+ /*xmm1 = d1 c1 b1 a1 d0 c0 b0 a0*/ \
+ "punpckldq %%xmm0,%%xmm1\n\t" \
+ /*xmm0 is free.*/ \
+ "movdqa %%xmm4,%%xmm0\n\t" \
+ /*xmm4 = h3 g3 f3 e3 h2 g2 f2 e2*/ \
+ "punpckhdq %%xmm6,%%xmm4\n\t" \
+ /*xmm0 = h1 g1 f1 e1 h0 g0 f0 e0*/ \
+ "punpckldq %%xmm6,%%xmm0\n\t" \
+ /*xmm6 is free.*/ \
+ "movdqa %%xmm5,%%xmm6\n\t" \
+ /*xmm5 = d5 c5 b5 a5 d4 c4 b4 a4*/ \
+ "punpckldq %%xmm2,%%xmm5\n\t" \
+ /*xmm6 = d7 c7 b7 a7 d6 c6 b6 a6*/ \
+ "punpckhdq %%xmm2,%%xmm6\n\t" \
+ /*xmm2 is free.*/ \
+ "movdqa %%xmm1,%%xmm2\n\t" \
+ /*xmm1 = h1 g1 f1 e1 d1 c1 b1 a1*/ \
+ "punpckhqdq %%xmm0,%%xmm1\n\t" \
+ /*xmm2 = h0 g0 f0 e0 d0 c0 b0 a0*/ \
+ "punpcklqdq %%xmm0,%%xmm2\n\t" \
+ /*xmm0 = h7 g7 f7 e7 h6 g6 f6 e6*/ \
+ "movdqa "OC_MEM_OFFS(0x00,buf)",%%xmm0\n\t" \
+ /*buf[1] = h0 g0 f0 e0 d0 c0 b0 a0*/ \
+ "movdqa %%xmm2,"OC_MEM_OFFS(0x10,buf)"\n\t" \
+ /*xmm2 is free.*/ \
+ "movdqa %%xmm3,%%xmm2\n\t" \
+ /*xmm3 = h3 g3 f3 e3 d3 c3 b3 a3*/ \
+ "punpckhqdq %%xmm4,%%xmm3\n\t" \
+ /*xmm2 = h2 g2 f2 e2 d2 c2 b2 a2*/ \
+ "punpcklqdq %%xmm4,%%xmm2\n\t" \
+ /*xmm4 is free.*/ \
+ "movdqa %%xmm5,%%xmm4\n\t" \
+ /*xmm5 = h5 g5 f5 e5 d5 c5 b5 a5*/ \
+ "punpckhqdq %%xmm7,%%xmm5\n\t" \
+ /*xmm4 = h4 g4 f4 e4 d4 c4 b4 a4*/ \
+ "punpcklqdq %%xmm7,%%xmm4\n\t" \
+ /*xmm7 is free.*/ \
+ "movdqa %%xmm6,%%xmm7\n\t" \
+ /*xmm6 = h6 g6 f6 e6 d6 c6 b6 a6*/ \
+ "punpcklqdq %%xmm0,%%xmm6\n\t" \
+ /*xmm7 = h7 g7 f7 e7 d7 c7 b7 a7*/ \
+ "punpckhqdq %%xmm0,%%xmm7\n\t" \
+ /*xmm0 = h0 g0 f0 e0 d0 c0 b0 a0*/ \
+ "movdqa "OC_MEM_OFFS(0x10,buf)",%%xmm0\n\t" \
+
+# endif
+
+/*Transpose 4 values in each of 8 MMX registers into 8 values in the first
+ four SSE registers.
+ No need to be clever here; we have plenty of room.*/
+# define OC_TRANSPOSE_8x4_MMX2SSE \
+ "#OC_TRANSPOSE_8x4_MMX2SSE\n\t" \
+ "movq2dq %%mm0,%%xmm0\n\t" \
+ "movq2dq %%mm1,%%xmm1\n\t" \
+ /*xmmA = b3 a3 b2 a2 b1 a1 b0 a0*/ \
+ "punpcklwd %%xmm1,%%xmm0\n\t" \
+ "movq2dq %%mm2,%%xmm3\n\t" \
+ "movq2dq %%mm3,%%xmm2\n\t" \
+ /*xmmC = d3 c3 d2 c2 d1 c1 d0 c0*/ \
+ "punpcklwd %%xmm2,%%xmm3\n\t" \
+ "movq2dq %%mm4,%%xmm4\n\t" \
+ "movq2dq %%mm5,%%xmm5\n\t" \
+ /*xmmE = f3 e3 f2 e2 f1 e1 f0 e0*/ \
+ "punpcklwd %%xmm5,%%xmm4\n\t" \
+ "movq2dq %%mm6,%%xmm7\n\t" \
+ "movq2dq %%mm7,%%xmm6\n\t" \
+ /*xmmG = h3 g3 h2 g2 h1 g1 h0 g0*/ \
+ "punpcklwd %%xmm6,%%xmm7\n\t" \
+ "movdqa %%xmm0,%%xmm2\n\t" \
+ /*xmm0 = d1 c1 b1 a1 d0 c0 b0 a0*/ \
+ "punpckldq %%xmm3,%%xmm0\n\t" \
+ /*xmm2 = d3 c3 b3 a3 d2 c2 b2 a2*/ \
+ "punpckhdq %%xmm3,%%xmm2\n\t" \
+ "movdqa %%xmm4,%%xmm5\n\t" \
+ /*xmm4 = h1 g1 f1 e1 h0 g0 f0 e0*/ \
+ "punpckldq %%xmm7,%%xmm4\n\t" \
+ /*xmm3 = h3 g3 f3 e3 h2 g2 f2 e2*/ \
+ "punpckhdq %%xmm7,%%xmm5\n\t" \
+ "movdqa %%xmm0,%%xmm1\n\t" \
+ /*xmm0 = h0 g0 f0 e0 d0 c0 b0 a0*/ \
+ "punpcklqdq %%xmm4,%%xmm0\n\t" \
+ /*xmm1 = h1 g1 f1 e1 d1 c1 b1 a1*/ \
+ "punpckhqdq %%xmm4,%%xmm1\n\t" \
+ "movdqa %%xmm2,%%xmm3\n\t" \
+ /*xmm2 = h2 g2 f2 e2 d2 c2 b2 a2*/ \
+ "punpcklqdq %%xmm5,%%xmm2\n\t" \
+ /*xmm3 = h3 g3 f3 e3 d3 c3 b3 a3*/ \
+ "punpckhqdq %%xmm5,%%xmm3\n\t" \
+
+#endif
diff --git a/thirdparty/libtheora/x86/x86cpu.c b/thirdparty/libtheora/x86/x86cpu.c
new file mode 100644
index 0000000000..49fd76d0ac
--- /dev/null
+++ b/thirdparty/libtheora/x86/x86cpu.c
@@ -0,0 +1,182 @@
+/********************************************************************
+ * *
+ * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. *
+ * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
+ * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
+ * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
+ * *
+ * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 *
+ * by the Xiph.Org Foundation and contributors http://www.xiph.org/ *
+ * *
+ ********************************************************************
+
+ CPU capability detection for x86 processors.
+ Originally written by Rudolf Marek.
+
+ function:
+ last mod: $Id$
+
+ ********************************************************************/
+
+#include "x86cpu.h"
+
+#if !defined(OC_X86_ASM)
+ogg_uint32_t oc_cpu_flags_get(void){
+ return 0;
+}
+#else
+# if defined(__amd64__)||defined(__x86_64__)
+/*On x86-64, gcc seems to be able to figure out how to save %rbx for us when
+ compiling with -fPIC.*/
+# define cpuid(_op,_eax,_ebx,_ecx,_edx) \
+ __asm__ __volatile__( \
+ "cpuid\n\t" \
+ :[eax]"=a"(_eax),[ebx]"=b"(_ebx),[ecx]"=c"(_ecx),[edx]"=d"(_edx) \
+ :"a"(_op) \
+ :"cc" \
+ )
+# else
+/*On x86-32, not so much.*/
+# define cpuid(_op,_eax,_ebx,_ecx,_edx) \
+ __asm__ __volatile__( \
+ "xchgl %%ebx,%[ebx]\n\t" \
+ "cpuid\n\t" \
+ "xchgl %%ebx,%[ebx]\n\t" \
+ :[eax]"=a"(_eax),[ebx]"=r"(_ebx),[ecx]"=c"(_ecx),[edx]"=d"(_edx) \
+ :"a"(_op) \
+ :"cc" \
+ )
+# endif
+
+static ogg_uint32_t oc_parse_intel_flags(ogg_uint32_t _edx,ogg_uint32_t _ecx){
+ ogg_uint32_t flags;
+ /*If there isn't even MMX, give up.*/
+ if(!(_edx&0x00800000))return 0;
+ flags=OC_CPU_X86_MMX;
+ if(_edx&0x02000000)flags|=OC_CPU_X86_MMXEXT|OC_CPU_X86_SSE;
+ if(_edx&0x04000000)flags|=OC_CPU_X86_SSE2;
+ if(_ecx&0x00000001)flags|=OC_CPU_X86_PNI;
+ if(_ecx&0x00000100)flags|=OC_CPU_X86_SSSE3;
+ if(_ecx&0x00080000)flags|=OC_CPU_X86_SSE4_1;
+ if(_ecx&0x00100000)flags|=OC_CPU_X86_SSE4_2;
+ return flags;
+}
+
+static ogg_uint32_t oc_parse_amd_flags(ogg_uint32_t _edx,ogg_uint32_t _ecx){
+ ogg_uint32_t flags;
+ /*If there isn't even MMX, give up.*/
+ if(!(_edx&0x00800000))return 0;
+ flags=OC_CPU_X86_MMX;
+ if(_edx&0x00400000)flags|=OC_CPU_X86_MMXEXT;
+ if(_edx&0x80000000)flags|=OC_CPU_X86_3DNOW;
+ if(_edx&0x40000000)flags|=OC_CPU_X86_3DNOWEXT;
+ if(_ecx&0x00000040)flags|=OC_CPU_X86_SSE4A;
+ if(_ecx&0x00000800)flags|=OC_CPU_X86_SSE5;
+ return flags;
+}
+
+ogg_uint32_t oc_cpu_flags_get(void){
+ ogg_uint32_t flags;
+ ogg_uint32_t eax;
+ ogg_uint32_t ebx;
+ ogg_uint32_t ecx;
+ ogg_uint32_t edx;
+# if !defined(__amd64__)&&!defined(__x86_64__)
+ /*Not all x86-32 chips support cpuid, so we have to check.*/
+ __asm__ __volatile__(
+ "pushfl\n\t"
+ "pushfl\n\t"
+ "popl %[a]\n\t"
+ "movl %[a],%[b]\n\t"
+ "xorl $0x200000,%[a]\n\t"
+ "pushl %[a]\n\t"
+ "popfl\n\t"
+ "pushfl\n\t"
+ "popl %[a]\n\t"
+ "popfl\n\t"
+ :[a]"=r"(eax),[b]"=r"(ebx)
+ :
+ :"cc"
+ );
+ /*No cpuid.*/
+ if(eax==ebx)return 0;
+# endif
+ cpuid(0,eax,ebx,ecx,edx);
+ /* l e t n I e n i u n e G*/
+ if(ecx==0x6C65746E&&edx==0x49656E69&&ebx==0x756E6547||
+ /* 6 8 x M T e n i u n e G*/
+ ecx==0x3638784D&&edx==0x54656E69&&ebx==0x756E6547){
+ int family;
+ int model;
+ /*Intel, Transmeta (tested with Crusoe TM5800):*/
+ cpuid(1,eax,ebx,ecx,edx);
+ flags=oc_parse_intel_flags(edx,ecx);
+ family=(eax>>8)&0xF;
+ model=(eax>>4)&0xF;
+ /*The SSE unit on the Pentium M and Core Duo is much slower than the MMX
+ unit, so don't use it.*/
+ if(family==6&&(model==9||model==13||model==14)){
+ flags&=~(OC_CPU_X86_SSE2|OC_CPU_X86_PNI);
+ }
+ }
+ /* D M A c i t n e h t u A*/
+ else if(ecx==0x444D4163&&edx==0x69746E65&&ebx==0x68747541||
+ /* C S N y b e d o e G*/
+ ecx==0x43534e20&&edx==0x79622065&&ebx==0x646f6547){
+ /*AMD, Geode:*/
+ cpuid(0x80000000,eax,ebx,ecx,edx);
+ if(eax<0x80000001)flags=0;
+ else{
+ cpuid(0x80000001,eax,ebx,ecx,edx);
+ flags=oc_parse_amd_flags(edx,ecx);
+ }
+ /*Also check for SSE.*/
+ cpuid(1,eax,ebx,ecx,edx);
+ flags|=oc_parse_intel_flags(edx,ecx);
+ }
+ /*Technically some VIA chips can be configured in the BIOS to return any
+ string here the user wants.
+ There is a special detection method that can be used to identify such
+ processors, but in my opinion, if the user really wants to change it, they
+ deserve what they get.*/
+ /* s l u a H r u a t n e C*/
+ else if(ecx==0x736C7561&&edx==0x48727561&&ebx==0x746E6543){
+ /*VIA:*/
+ /*I only have documentation for the C7 (Esther) and Isaiah (forthcoming)
+ chips (thanks to the engineers from Centaur Technology who provided it).
+ These chips support Intel-like cpuid info.
+ The C3-2 (Nehemiah) cores appear to, as well.*/
+ cpuid(1,eax,ebx,ecx,edx);
+ flags=oc_parse_intel_flags(edx,ecx);
+ if(eax>=0x80000001){
+ /*The (non-Nehemiah) C3 processors support AMD-like cpuid info.
+ We need to check this even if the Intel test succeeds to pick up 3DNow!
+ support on these processors.
+ Unlike actual AMD processors, we cannot _rely_ on this info, since
+ some cores (e.g., the 693 stepping of the Nehemiah) claim to support
+ this function, yet return edx=0, despite the Intel test indicating
+ MMX support.
+ Therefore the features detected here are strictly added to those
+ detected by the Intel test.*/
+ /*TODO: How about earlier chips?*/
+ cpuid(0x80000001,eax,ebx,ecx,edx);
+ /*Note: As of the C7, this function returns Intel-style extended feature
+ flags, not AMD-style.
+ Currently, this only defines bits 11, 20, and 29 (0x20100800), which
+ do not conflict with any of the AMD flags we inspect.
+ For the remaining bits, Intel tells us, "Do not count on their value",
+ but VIA assures us that they will all be zero (at least on the C7 and
+ Isaiah chips).
+ In the (unlikely) event a future processor uses bits 18, 19, 30, or 31
+ (0xC0C00000) for something else, we will have to add code to detect
+ the model to decide when it is appropriate to inspect them.*/
+ flags|=oc_parse_amd_flags(edx,ecx);
+ }
+ }
+ else{
+ /*Implement me.*/
+ flags=0;
+ }
+ return flags;
+}
+#endif
diff --git a/thirdparty/libtheora/cpu.h b/thirdparty/libtheora/x86/x86cpu.h
index a43c957a39..e0192d52e2 100644
--- a/thirdparty/libtheora/cpu.h
+++ b/thirdparty/libtheora/x86/x86cpu.h
@@ -10,13 +10,13 @@
* *
********************************************************************
function:
- last mod: $Id: cpu.h 16503 2009-08-22 18:14:02Z giles $
+ last mod: $Id$
********************************************************************/
-#if !defined(_x86_cpu_H)
-# define _x86_cpu_H (1)
-#include "internal.h"
+#if !defined(_x86_x86cpu_H)
+# define _x86_x86cpu_H (1)
+#include "../internal.h"
#define OC_CPU_X86_MMX (1<<0)
#define OC_CPU_X86_3DNOW (1<<1)
@@ -31,4 +31,6 @@
#define OC_CPU_X86_SSE4A (1<<10)
#define OC_CPU_X86_SSE5 (1<<11)
+ogg_uint32_t oc_cpu_flags_get(void);
+
#endif
diff --git a/thirdparty/libtheora/x86/x86enc.c b/thirdparty/libtheora/x86/x86enc.c
index 43b7be3ea3..ffa9c14a42 100644
--- a/thirdparty/libtheora/x86/x86enc.c
+++ b/thirdparty/libtheora/x86/x86enc.c
@@ -18,32 +18,46 @@
#if defined(OC_X86_ASM)
-#include "../cpu.c"
-
-void oc_enc_vtable_init_x86(oc_enc_ctx *_enc){
+void oc_enc_accel_init_x86(oc_enc_ctx *_enc){
ogg_uint32_t cpu_flags;
- cpu_flags=oc_cpu_flags_get();
- oc_enc_vtable_init_c(_enc);
+ cpu_flags=_enc->state.cpu_flags;
+ oc_enc_accel_init_c(_enc);
+# if defined(OC_ENC_USE_VTABLE)
if(cpu_flags&OC_CPU_X86_MMX){
_enc->opt_vtable.frag_sub=oc_enc_frag_sub_mmx;
_enc->opt_vtable.frag_sub_128=oc_enc_frag_sub_128_mmx;
_enc->opt_vtable.frag_recon_intra=oc_frag_recon_intra_mmx;
_enc->opt_vtable.frag_recon_inter=oc_frag_recon_inter_mmx;
- _enc->opt_vtable.fdct8x8=oc_enc_fdct8x8_mmx;
}
if(cpu_flags&OC_CPU_X86_MMXEXT){
_enc->opt_vtable.frag_sad=oc_enc_frag_sad_mmxext;
_enc->opt_vtable.frag_sad_thresh=oc_enc_frag_sad_thresh_mmxext;
_enc->opt_vtable.frag_sad2_thresh=oc_enc_frag_sad2_thresh_mmxext;
- _enc->opt_vtable.frag_satd_thresh=oc_enc_frag_satd_thresh_mmxext;
- _enc->opt_vtable.frag_satd2_thresh=oc_enc_frag_satd2_thresh_mmxext;
+ _enc->opt_vtable.frag_satd=oc_enc_frag_satd_mmxext;
+ _enc->opt_vtable.frag_satd2=oc_enc_frag_satd2_mmxext;
_enc->opt_vtable.frag_intra_satd=oc_enc_frag_intra_satd_mmxext;
_enc->opt_vtable.frag_copy2=oc_enc_frag_copy2_mmxext;
+ _enc->opt_vtable.fdct8x8=oc_enc_fdct8x8_mmxext;
}
if(cpu_flags&OC_CPU_X86_SSE2){
-# if defined(OC_X86_64_ASM)
- /*_enc->opt_vtable.fdct8x8=oc_enc_fdct8x8_x86_64sse2;*/
+# if defined(OC_X86_64_ASM)
+ _enc->opt_vtable.fdct8x8=oc_enc_fdct8x8_x86_64sse2;
+# endif
+ _enc->opt_vtable.frag_ssd=oc_enc_frag_ssd_sse2;
+ _enc->opt_vtable.frag_border_ssd=oc_enc_frag_border_ssd_sse2;
+ _enc->opt_vtable.frag_satd=oc_enc_frag_satd_sse2;
+ _enc->opt_vtable.frag_satd2=oc_enc_frag_satd2_sse2;
+ _enc->opt_vtable.frag_intra_satd=oc_enc_frag_intra_satd_sse2;
+ _enc->opt_vtable.enquant_table_init=oc_enc_enquant_table_init_x86;
+ _enc->opt_vtable.enquant_table_fixup=oc_enc_enquant_table_fixup_x86;
+ _enc->opt_vtable.quantize=oc_enc_quantize_sse2;
+# else
+ (void) cpu_flags;
# endif
+ _enc->opt_data.enquant_table_size=128*sizeof(ogg_uint16_t);
+ _enc->opt_data.enquant_table_alignment=16;
+# if defined(OC_ENC_USE_VTABLE)
}
+# endif
}
#endif
diff --git a/thirdparty/libtheora/x86/x86enc.h b/thirdparty/libtheora/x86/x86enc.h
index 06c3908bcd..c258247d67 100644
--- a/thirdparty/libtheora/x86/x86enc.h
+++ b/thirdparty/libtheora/x86/x86enc.h
@@ -17,11 +17,62 @@
#if !defined(_x86_x86enc_H)
# define _x86_x86enc_H (1)
-# include "../encint.h"
# include "x86int.h"
-void oc_enc_vtable_init_x86(oc_enc_ctx *_enc);
+# if defined(OC_X86_ASM)
+# define oc_enc_accel_init oc_enc_accel_init_x86
+# if defined(OC_X86_64_ASM)
+/*x86-64 guarantees SIMD support up through at least SSE2.
+ If the best routine we have available only needs SSE2 (which at the moment
+ covers all of them), then we can avoid runtime detection and the indirect
+ call.*/
+# define oc_enc_frag_sub(_enc,_diff,_x,_y,_stride) \
+ oc_enc_frag_sub_mmx(_diff,_x,_y,_stride)
+# define oc_enc_frag_sub_128(_enc,_diff,_x,_stride) \
+ oc_enc_frag_sub_128_mmx(_diff,_x,_stride)
+# define oc_enc_frag_sad(_enc,_src,_ref,_ystride) \
+ oc_enc_frag_sad_mmxext(_src,_ref,_ystride)
+# define oc_enc_frag_sad_thresh(_enc,_src,_ref,_ystride,_thresh) \
+ oc_enc_frag_sad_thresh_mmxext(_src,_ref,_ystride,_thresh)
+# define oc_enc_frag_sad2_thresh(_enc,_src,_ref1,_ref2,_ystride,_thresh) \
+ oc_enc_frag_sad2_thresh_mmxext(_src,_ref1,_ref2,_ystride,_thresh)
+# define oc_enc_frag_satd(_enc,_dc,_src,_ref,_ystride) \
+ oc_enc_frag_satd_sse2(_dc,_src,_ref,_ystride)
+# define oc_enc_frag_satd2(_enc,_dc,_src,_ref1,_ref2,_ystride) \
+ oc_enc_frag_satd2_sse2(_dc,_src,_ref1,_ref2,_ystride)
+# define oc_enc_frag_intra_satd(_enc,_dc,_src,_ystride) \
+ oc_enc_frag_intra_satd_sse2(_dc,_src,_ystride)
+# define oc_enc_frag_ssd(_enc,_src,_ref,_ystride) \
+ oc_enc_frag_ssd_sse2(_src,_ref,_ystride)
+# define oc_enc_frag_border_ssd(_enc,_src,_ref,_ystride,_mask) \
+ oc_enc_frag_border_ssd_sse2(_src,_ref,_ystride,_mask)
+# define oc_enc_frag_copy2(_enc,_dst,_src1,_src2,_ystride) \
+ oc_int_frag_copy2_mmxext(_dst,_ystride,_src1,_src2,_ystride)
+# define oc_enc_enquant_table_init(_enc,_enquant,_dequant) \
+ oc_enc_enquant_table_init_x86(_enquant,_dequant)
+# define oc_enc_enquant_table_fixup(_enc,_enquant,_nqis) \
+ oc_enc_enquant_table_fixup_x86(_enquant,_nqis)
+# define oc_enc_quantize(_enc,_qdct,_dct,_dequant,_enquant) \
+ oc_enc_quantize_sse2(_qdct,_dct,_dequant,_enquant)
+# define oc_enc_frag_recon_intra(_enc,_dst,_ystride,_residue) \
+ oc_frag_recon_intra_mmx(_dst,_ystride,_residue)
+# define oc_enc_frag_recon_inter(_enc,_dst,_src,_ystride,_residue) \
+ oc_frag_recon_inter_mmx(_dst,_src,_ystride,_residue)
+# define oc_enc_fdct8x8(_enc,_y,_x) \
+ oc_enc_fdct8x8_x86_64sse2(_y,_x)
+# else
+# define OC_ENC_USE_VTABLE (1)
+# endif
+# endif
+
+# include "../encint.h"
+void oc_enc_accel_init_x86(oc_enc_ctx *_enc);
+
+void oc_enc_frag_sub_mmx(ogg_int16_t _diff[64],
+ const unsigned char *_x,const unsigned char *_y,int _stride);
+void oc_enc_frag_sub_128_mmx(ogg_int16_t _diff[64],
+ const unsigned char *_x,int _stride);
unsigned oc_enc_frag_sad_mmxext(const unsigned char *_src,
const unsigned char *_ref,int _ystride);
unsigned oc_enc_frag_sad_thresh_mmxext(const unsigned char *_src,
@@ -29,19 +80,35 @@ unsigned oc_enc_frag_sad_thresh_mmxext(const unsigned char *_src,
unsigned oc_enc_frag_sad2_thresh_mmxext(const unsigned char *_src,
const unsigned char *_ref1,const unsigned char *_ref2,int _ystride,
unsigned _thresh);
-unsigned oc_enc_frag_satd_thresh_mmxext(const unsigned char *_src,
- const unsigned char *_ref,int _ystride,unsigned _thresh);
-unsigned oc_enc_frag_satd2_thresh_mmxext(const unsigned char *_src,
- const unsigned char *_ref1,const unsigned char *_ref2,int _ystride,
- unsigned _thresh);
-unsigned oc_enc_frag_intra_satd_mmxext(const unsigned char *_src,int _ystride);
-void oc_enc_frag_sub_mmx(ogg_int16_t _diff[64],
- const unsigned char *_x,const unsigned char *_y,int _stride);
-void oc_enc_frag_sub_128_mmx(ogg_int16_t _diff[64],
- const unsigned char *_x,int _stride);
+unsigned oc_enc_frag_satd_mmxext(int *_dc,const unsigned char *_src,
+ const unsigned char *_ref,int _ystride);
+unsigned oc_enc_frag_satd_sse2(int *_dc,const unsigned char *_src,
+ const unsigned char *_ref,int _ystride);
+unsigned oc_enc_frag_satd2_mmxext(int *_dc,const unsigned char *_src,
+ const unsigned char *_ref1,const unsigned char *_ref2,int _ystride);
+unsigned oc_enc_frag_satd2_sse2(int *_dc,const unsigned char *_src,
+ const unsigned char *_ref1,const unsigned char *_ref2,int _ystride);
+unsigned oc_enc_frag_intra_satd_mmxext(int *_dc,
+ const unsigned char *_src,int _ystride);
+unsigned oc_enc_frag_intra_satd_sse2(int *_dc,
+ const unsigned char *_src,int _ystride);
+unsigned oc_enc_frag_ssd_sse2(const unsigned char *_src,
+ const unsigned char *_ref,int _ystride);
+unsigned oc_enc_frag_border_ssd_sse2(const unsigned char *_src,
+ const unsigned char *_ref,int _ystride,ogg_int64_t _mask);
+void oc_int_frag_copy2_mmxext(unsigned char *_dst,int _dst_ystride,
+ const unsigned char *_src1,const unsigned char *_src2,int _src_ystride);
void oc_enc_frag_copy2_mmxext(unsigned char *_dst,
const unsigned char *_src1,const unsigned char *_src2,int _ystride);
-void oc_enc_fdct8x8_mmx(ogg_int16_t _y[64],const ogg_int16_t _x[64]);
+void oc_enc_enquant_table_init_x86(void *_enquant,
+ const ogg_uint16_t _dequant[64]);
+void oc_enc_enquant_table_fixup_x86(void *_enquant[3][3][2],int _nqis);
+int oc_enc_quantize_sse2(ogg_int16_t _qdct[64],const ogg_int16_t _dct[64],
+ const ogg_uint16_t _dequant[64],const void *_enquant);
+void oc_enc_fdct8x8_mmxext(ogg_int16_t _y[64],const ogg_int16_t _x[64]);
+
+# if defined(OC_X86_64_ASM)
void oc_enc_fdct8x8_x86_64sse2(ogg_int16_t _y[64],const ogg_int16_t _x[64]);
+# endif
#endif
diff --git a/thirdparty/libtheora/x86/x86enquant.c b/thirdparty/libtheora/x86/x86enquant.c
new file mode 100644
index 0000000000..39477ecc21
--- /dev/null
+++ b/thirdparty/libtheora/x86/x86enquant.c
@@ -0,0 +1,149 @@
+/********************************************************************
+ * *
+ * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. *
+ * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
+ * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
+ * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
+ * *
+ * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 *
+ * by the Xiph.Org Foundation and contributors http://www.xiph.org/ *
+ * *
+ ********************************************************************
+
+ function:
+ last mod: $Id: mmxstate.c 17247 2010-05-28 05:35:32Z tterribe $
+
+ ********************************************************************/
+
+#include "x86enc.h"
+
+#if defined(OC_X86_ASM)
+
+
+
+/*The default enquant table is not quite suitable for SIMD purposes.
+ First, the m and l parameters need to be separated so that an entire row full
+ of m's or l's can be loaded at a time.
+ Second, x86 SIMD has no element-wise arithmetic right-shift, so we have to
+ emulate one with a multiply.
+ Therefore we translate the shift count into a scale factor.*/
+void oc_enc_enquant_table_init_x86(void *_enquant,
+ const ogg_uint16_t _dequant[64]){
+ ogg_int16_t *m;
+ ogg_int16_t *l;
+ int zzi;
+ m=(ogg_int16_t *)_enquant;
+ l=m+64;
+ for(zzi=0;zzi<64;zzi++){
+ oc_iquant q;
+ oc_iquant_init(&q,_dequant[zzi]);
+ m[zzi]=q.m;
+ /*q.l must be at least 2 for this to work; fortunately, once all the scale
+ factors are baked in, the minimum quantizer is much larger than that.*/
+ l[zzi]=1<<16-q.l;
+ }
+}
+
+void oc_enc_enquant_table_fixup_x86(void *_enquant[3][3][2],int _nqis){
+ int pli;
+ int qii;
+ int qti;
+ for(pli=0;pli<3;pli++)for(qii=1;qii<_nqis;qii++)for(qti=0;qti<2;qti++){
+ ((ogg_int16_t *)_enquant[pli][qii][qti])[0]=
+ ((ogg_int16_t *)_enquant[pli][0][qti])[0];
+ ((ogg_int16_t *)_enquant[pli][qii][qti])[64]=
+ ((ogg_int16_t *)_enquant[pli][0][qti])[64];
+ }
+}
+
+int oc_enc_quantize_sse2(ogg_int16_t _qdct[64],const ogg_int16_t _dct[64],
+ const ogg_uint16_t _dequant[64],const void *_enquant){
+ ptrdiff_t r;
+ __asm__ __volatile__(
+ "xor %[r],%[r]\n\t"
+ /*Loop through two rows at a time.*/
+ ".p2align 4\n\t"
+ "0:\n\t"
+ /*Load the first two rows of the data and the quant matrices.*/
+ "movdqa 0x00(%[dct],%[r]),%%xmm0\n\t"
+ "movdqa 0x10(%[dct],%[r]),%%xmm1\n\t"
+ "movdqa 0x00(%[dq],%[r]),%%xmm2\n\t"
+ "movdqa 0x10(%[dq],%[r]),%%xmm3\n\t"
+ "movdqa 0x00(%[q],%[r]),%%xmm4\n\t"
+ "movdqa 0x10(%[q],%[r]),%%xmm5\n\t"
+ /*Double the input and propagate its sign to the rounding factor.
+ Using SSSE3's psignw would help here, but we need the mask later anyway.*/
+ "movdqa %%xmm0,%%xmm6\n\t"
+ "psraw $15,%%xmm0\n\t"
+ "movdqa %%xmm1,%%xmm7\n\t"
+ "paddw %%xmm6,%%xmm6\n\t"
+ "psraw $15,%%xmm1\n\t"
+ "paddw %%xmm7,%%xmm7\n\t"
+ "paddw %%xmm0,%%xmm2\n\t"
+ "paddw %%xmm1,%%xmm3\n\t"
+ "pxor %%xmm0,%%xmm2\n\t"
+ "pxor %%xmm1,%%xmm3\n\t"
+ /*Add the rounding factor and perform the first multiply.*/
+ "paddw %%xmm2,%%xmm6\n\t"
+ "paddw %%xmm3,%%xmm7\n\t"
+ "pmulhw %%xmm6,%%xmm4\n\t"
+ "pmulhw %%xmm7,%%xmm5\n\t"
+ "movdqa 0x80(%[q],%[r]),%%xmm2\n\t"
+ "movdqa 0x90(%[q],%[r]),%%xmm3\n\t"
+ "paddw %%xmm4,%%xmm6\n\t"
+ "paddw %%xmm5,%%xmm7\n\t"
+ /*Emulate an element-wise right-shift via a second multiply.*/
+ "pmulhw %%xmm2,%%xmm6\n\t"
+ "pmulhw %%xmm3,%%xmm7\n\t"
+ "add $32,%[r]\n\t"
+ "cmp $96,%[r]\n\t"
+ /*Correct for the sign.*/
+ "psubw %%xmm0,%%xmm6\n\t"
+ "psubw %%xmm1,%%xmm7\n\t"
+ /*Save the result.*/
+ "movdqa %%xmm6,-0x20(%[qdct],%[r])\n\t"
+ "movdqa %%xmm7,-0x10(%[qdct],%[r])\n\t"
+ "jle 0b\n\t"
+ /*Now find the location of the last non-zero value.*/
+ "movdqa 0x50(%[qdct]),%%xmm5\n\t"
+ "movdqa 0x40(%[qdct]),%%xmm4\n\t"
+ "packsswb %%xmm7,%%xmm6\n\t"
+ "packsswb %%xmm5,%%xmm4\n\t"
+ "pxor %%xmm0,%%xmm0\n\t"
+ "mov $-1,%k[dq]\n\t"
+ "pcmpeqb %%xmm0,%%xmm6\n\t"
+ "pcmpeqb %%xmm0,%%xmm4\n\t"
+ "pmovmskb %%xmm6,%k[q]\n\t"
+ "pmovmskb %%xmm4,%k[r]\n\t"
+ "shl $16,%k[q]\n\t"
+ "or %k[r],%k[q]\n\t"
+ "mov $32,%[r]\n\t"
+ /*We have to use xor here instead of not in order to set the flags.*/
+ "xor %k[dq],%k[q]\n\t"
+ "jnz 1f\n\t"
+ "movdqa 0x30(%[qdct]),%%xmm7\n\t"
+ "movdqa 0x20(%[qdct]),%%xmm6\n\t"
+ "movdqa 0x10(%[qdct]),%%xmm5\n\t"
+ "movdqa 0x00(%[qdct]),%%xmm4\n\t"
+ "packsswb %%xmm7,%%xmm6\n\t"
+ "packsswb %%xmm5,%%xmm4\n\t"
+ "pcmpeqb %%xmm0,%%xmm6\n\t"
+ "pcmpeqb %%xmm0,%%xmm4\n\t"
+ "pmovmskb %%xmm6,%k[q]\n\t"
+ "pmovmskb %%xmm4,%k[r]\n\t"
+ "shl $16,%k[q]\n\t"
+ "or %k[r],%k[q]\n\t"
+ "xor %[r],%[r]\n\t"
+ "not %k[q]\n\t"
+ "or $1,%k[q]\n\t"
+ "1:\n\t"
+ "bsr %k[q],%k[q]\n\t"
+ "add %k[q],%k[r]\n\t"
+ :[r]"=&a"(r),[q]"+r"(_enquant),[dq]"+r"(_dequant)
+ :[dct]"r"(_dct),[qdct]"r"(_qdct)
+ :"cc","memory"
+ );
+ return (int)r;
+}
+
+#endif
diff --git a/thirdparty/libtheora/x86/x86int.h b/thirdparty/libtheora/x86/x86int.h
index ede724f5aa..ceb2dbb0ec 100644
--- a/thirdparty/libtheora/x86/x86int.h
+++ b/thirdparty/libtheora/x86/x86int.h
@@ -11,7 +11,7 @@
********************************************************************
function:
- last mod: $Id: x86int.h 16503 2009-08-22 18:14:02Z giles $
+ last mod: $Id$
********************************************************************/
@@ -19,24 +19,104 @@
# define _x86_x86int_H (1)
# include "../internal.h"
-void oc_state_vtable_init_x86(oc_theora_state *_state);
+# if defined(OC_X86_ASM)
+# define oc_state_accel_init oc_state_accel_init_x86
+# if defined(OC_X86_64_ASM)
+/*x86-64 guarantees SIMD support up through at least SSE2.
+ If the best routine we have available only needs SSE2 (which at the moment
+ covers all of them), then we can avoid runtime detection and the indirect
+ call.*/
+# define oc_frag_copy(_state,_dst,_src,_ystride) \
+ oc_frag_copy_mmx(_dst,_src,_ystride)
+# define oc_frag_copy_list(_state,_dst_frame,_src_frame,_ystride, \
+ _fragis,_nfragis,_frag_buf_offs) \
+ oc_frag_copy_list_mmx(_dst_frame,_src_frame,_ystride, \
+ _fragis,_nfragis,_frag_buf_offs)
+# define oc_frag_recon_intra(_state,_dst,_ystride,_residue) \
+ oc_frag_recon_intra_mmx(_dst,_ystride,_residue)
+# define oc_frag_recon_inter(_state,_dst,_src,_ystride,_residue) \
+ oc_frag_recon_inter_mmx(_dst,_src,_ystride,_residue)
+# define oc_frag_recon_inter2(_state,_dst,_src1,_src2,_ystride,_residue) \
+ oc_frag_recon_inter2_mmx(_dst,_src1,_src2,_ystride,_residue)
+# define oc_idct8x8(_state,_y,_x,_last_zzi) \
+ oc_idct8x8_sse2(_y,_x,_last_zzi)
+# define oc_state_frag_recon oc_state_frag_recon_mmx
+# define oc_loop_filter_init(_state,_bv,_flimit) \
+ oc_loop_filter_init_mmxext(_bv,_flimit)
+# define oc_state_loop_filter_frag_rows oc_state_loop_filter_frag_rows_mmxext
+# define oc_restore_fpu(_state) \
+ oc_restore_fpu_mmx()
+# else
+# define OC_STATE_USE_VTABLE (1)
+# endif
+# endif
+
+# include "../state.h"
+# include "x86cpu.h"
+
+/*Converts the expression in the argument to a string.*/
+#define OC_M2STR(_s) #_s
+
+/*Memory operands do not always include an offset.
+ To avoid warnings, we force an offset with %H (which adds 8).*/
+# if __GNUC_PREREQ(4,0)
+# define OC_MEM_OFFS(_offs,_name) \
+ OC_M2STR(_offs-8+%H[_name])
+# endif
+/*If your gcc version does't support %H, then you get to suffer the warnings.
+ Note that Apple's gas breaks on things like _offs+(%esp): it throws away the
+ whole offset, instead of substituting in 0 for the missing operand to +.*/
+# if !defined(OC_MEM_OFFS)
+# define OC_MEM_OFFS(_offs,_name) \
+ OC_M2STR(_offs+%[_name])
+# endif
+
+/*Declare an array operand with an exact size.
+ This tells gcc we're going to clobber this memory region, without having to
+ clobber all of "memory" and lets us access local buffers directly using the
+ stack pointer, without allocating a separate register to point to them.*/
+#define OC_ARRAY_OPERAND(_type,_ptr,_size) \
+ (*({ \
+ struct{_type array_value__[(_size)];} *array_addr__=(void *)(_ptr); \
+ array_addr__; \
+ }))
+
+/*Declare an array operand with an exact size.
+ This tells gcc we're going to clobber this memory region, without having to
+ clobber all of "memory" and lets us access local buffers directly using the
+ stack pointer, without allocating a separate register to point to them.*/
+#define OC_CONST_ARRAY_OPERAND(_type,_ptr,_size) \
+ (*({ \
+ const struct{_type array_value__[(_size)];} *array_addr__= \
+ (const void *)(_ptr); \
+ array_addr__; \
+ }))
+
+extern const unsigned short __attribute__((aligned(16))) OC_IDCT_CONSTS[64];
+
+void oc_state_accel_init_x86(oc_theora_state *_state);
void oc_frag_copy_mmx(unsigned char *_dst,
const unsigned char *_src,int _ystride);
+void oc_frag_copy_list_mmx(unsigned char *_dst_frame,
+ const unsigned char *_src_frame,int _ystride,
+ const ptrdiff_t *_fragis,ptrdiff_t _nfragis,const ptrdiff_t *_frag_buf_offs);
void oc_frag_recon_intra_mmx(unsigned char *_dst,int _ystride,
const ogg_int16_t *_residue);
void oc_frag_recon_inter_mmx(unsigned char *_dst,
const unsigned char *_src,int _ystride,const ogg_int16_t *_residue);
void oc_frag_recon_inter2_mmx(unsigned char *_dst,const unsigned char *_src1,
const unsigned char *_src2,int _ystride,const ogg_int16_t *_residue);
-void oc_idct8x8_mmx(ogg_int16_t _y[64],int _last_zzi);
+void oc_idct8x8_mmx(ogg_int16_t _y[64],ogg_int16_t _x[64],int _last_zzi);
+void oc_idct8x8_sse2(ogg_int16_t _y[64],ogg_int16_t _x[64],int _last_zzi);
void oc_state_frag_recon_mmx(const oc_theora_state *_state,ptrdiff_t _fragi,
- int _pli,ogg_int16_t _dct_coeffs[64],int _last_zzi,ogg_uint16_t _dc_quant);
-void oc_state_frag_copy_list_mmx(const oc_theora_state *_state,
- const ptrdiff_t *_fragis,ptrdiff_t _nfragis,
- int _dst_frame,int _src_frame,int _pli);
+ int _pli,ogg_int16_t _dct_coeffs[128],int _last_zzi,ogg_uint16_t _dc_quant);
+void oc_loop_filter_init_mmx(signed char _bv[256],int _flimit);
+void oc_loop_filter_init_mmxext(signed char _bv[256],int _flimit);
void oc_state_loop_filter_frag_rows_mmx(const oc_theora_state *_state,
- int _bv[256],int _refi,int _pli,int _fragy0,int _fragy_end);
+ signed char _bv[256],int _refi,int _pli,int _fragy0,int _fragy_end);
+void oc_state_loop_filter_frag_rows_mmxext(const oc_theora_state *_state,
+ signed char _bv[256],int _refi,int _pli,int _fragy0,int _fragy_end);
void oc_restore_fpu_mmx(void);
#endif
diff --git a/thirdparty/libtheora/x86/x86state.c b/thirdparty/libtheora/x86/x86state.c
index a786bec284..9f8bceb534 100644
--- a/thirdparty/libtheora/x86/x86state.c
+++ b/thirdparty/libtheora/x86/x86state.c
@@ -11,7 +11,7 @@
********************************************************************
function:
- last mod: $Id: x86state.c 16503 2009-08-22 18:14:02Z giles $
+ last mod: $Id$
********************************************************************/
@@ -19,8 +19,7 @@
#if defined(OC_X86_ASM)
-#include "../cpu.c"
-
+#if defined(OC_STATE_USE_VTABLE)
/*This table has been modified from OC_FZIG_ZAG by baking a 4x4 transpose into
each quadrant of the destination.*/
static const unsigned char OC_FZIG_ZAG_MMX[128]={
@@ -39,24 +38,60 @@ static const unsigned char OC_FZIG_ZAG_MMX[128]={
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,64,64,64,64,64
+};
+#endif
+
+/*This table has been modified from OC_FZIG_ZAG by baking an 8x8 transpose into
+ the destination.*/
+static const unsigned char OC_FZIG_ZAG_SSE2[128]={
+ 0, 8, 1, 2, 9,16,24,17,
+ 10, 3, 4,11,18,25,32,40,
+ 33,26,19,12, 5, 6,13,20,
+ 27,34,41,48,56,49,42,35,
+ 28,21,14, 7,15,22,29,36,
+ 43,50,57,58,51,44,37,30,
+ 23,31,38,45,52,59,60,53,
+ 46,39,47,54,61,62,55,63,
+ 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,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,64,64,
+ 64,64,64,64,64,64,64,64
};
-void oc_state_vtable_init_x86(oc_theora_state *_state){
+void oc_state_accel_init_x86(oc_theora_state *_state){
+ oc_state_accel_init_c(_state);
_state->cpu_flags=oc_cpu_flags_get();
+# if defined(OC_STATE_USE_VTABLE)
if(_state->cpu_flags&OC_CPU_X86_MMX){
_state->opt_vtable.frag_copy=oc_frag_copy_mmx;
+ _state->opt_vtable.frag_copy_list=oc_frag_copy_list_mmx;
_state->opt_vtable.frag_recon_intra=oc_frag_recon_intra_mmx;
_state->opt_vtable.frag_recon_inter=oc_frag_recon_inter_mmx;
_state->opt_vtable.frag_recon_inter2=oc_frag_recon_inter2_mmx;
_state->opt_vtable.idct8x8=oc_idct8x8_mmx;
_state->opt_vtable.state_frag_recon=oc_state_frag_recon_mmx;
- _state->opt_vtable.state_frag_copy_list=oc_state_frag_copy_list_mmx;
+ _state->opt_vtable.loop_filter_init=oc_loop_filter_init_mmx;
_state->opt_vtable.state_loop_filter_frag_rows=
oc_state_loop_filter_frag_rows_mmx;
_state->opt_vtable.restore_fpu=oc_restore_fpu_mmx;
_state->opt_data.dct_fzig_zag=OC_FZIG_ZAG_MMX;
}
- else oc_state_vtable_init_c(_state);
+ if(_state->cpu_flags&OC_CPU_X86_MMXEXT){
+ _state->opt_vtable.loop_filter_init=oc_loop_filter_init_mmxext;
+ _state->opt_vtable.state_loop_filter_frag_rows=
+ oc_state_loop_filter_frag_rows_mmxext;
+ }
+ if(_state->cpu_flags&OC_CPU_X86_SSE2){
+ _state->opt_vtable.idct8x8=oc_idct8x8_sse2;
+# endif
+ _state->opt_data.dct_fzig_zag=OC_FZIG_ZAG_SSE2;
+# if defined(OC_STATE_USE_VTABLE)
+ }
+# endif
}
#endif
diff --git a/thirdparty/libtheora/x86/x86zigzag.h b/thirdparty/libtheora/x86/x86zigzag.h
new file mode 100644
index 0000000000..fb21e0bb43
--- /dev/null
+++ b/thirdparty/libtheora/x86/x86zigzag.h
@@ -0,0 +1,244 @@
+/********************************************************************
+ * *
+ * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. *
+ * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
+ * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
+ * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
+ * *
+ * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 *
+ * by the Xiph.Org Foundation and contributors http://www.xiph.org/ *
+ * *
+ ********************************************************************
+
+ function:
+ last mod: $Id: sse2trans.h 15675 2009-02-06 09:43:27Z tterribe $
+
+ ********************************************************************/
+
+#if !defined(_x86_x86zigzag_H)
+# define _x86_x86zigzag_H (1)
+# include "x86enc.h"
+
+
+/*Converts DCT coefficients from transposed order into zig-zag scan order and
+ stores them in %[y].
+ This relies on two macros to load the contents of each row:
+ OC_ZZ_LOAD_ROW_LO(row,"reg") and OC_ZZ_LOAD_ROW_HI(row,"reg"), which load
+ the first four and second four entries of each row into the specified
+ register, respectively.
+ OC_ZZ_LOAD_ROW_LO must be called before OC_ZZ_LOAD_ROW_HI for the same row
+ (because when the rows are already in SSE2 registers, loading the high half
+ destructively modifies the register).
+ The index of each output element in the original 64-element array should wind
+ up in the following 8x8 matrix (the letters indicate the order we compute
+ each 4-tuple below):
+ A 0 8 1 2 9 16 24 17 B
+ C 10 3 4 11 18 25 32 40 E
+ F 33 26 19 12 5 6 13 20 D
+ G 27 34 41 48 56 49 42 35 I
+ L 28 21 14 7 15 22 29 36 M
+ H 43 50 57 58 51 44 37 30 O
+ N 23 31 38 45 52 59 60 53 J
+ P 46 39 47 54 61 62 55 63 K
+ The order of the coefficients within each tuple is reversed in the comments
+ below to reflect the usual MSB to LSB notation.*/
+#define OC_TRANSPOSE_ZIG_ZAG_MMXEXT \
+ OC_ZZ_LOAD_ROW_LO(0,"%%mm0") /*mm0=03 02 01 00*/ \
+ OC_ZZ_LOAD_ROW_LO(1,"%%mm1") /*mm1=11 10 09 08*/ \
+ OC_ZZ_LOAD_ROW_LO(2,"%%mm2") /*mm2=19 18 17 16*/ \
+ OC_ZZ_LOAD_ROW_LO(3,"%%mm3") /*mm3=27 26 25 24*/ \
+ OC_ZZ_LOAD_ROW_HI(0,"%%mm4") /*mm4=07 06 05 04*/ \
+ OC_ZZ_LOAD_ROW_HI(1,"%%mm5") /*mm5=15 14 13 12*/ \
+ OC_ZZ_LOAD_ROW_HI(2,"%%mm6") /*mm6=23 22 21 20*/ \
+ "movq %%mm0,%%mm7\n\t" /*mm7=03 02 01 00*/ \
+ "punpckhdq %%mm1,%%mm0\n\t" /*mm0=11 10 03 02*/ \
+ "pshufw $0x39,%%mm4,%%mm4\n\t" /*mm4=04 07 06 05*/ \
+ "punpcklwd %%mm0,%%mm1\n\t" /*mm1=03 09 02 08*/ \
+ "pshufw $0x39,%%mm5,%%mm5\n\t" /*mm5=12 15 14 13*/ \
+ "punpcklwd %%mm1,%%mm7\n\t" /*mm7=02 01 08 00 *A*/ \
+ "movq %%mm7,0x00(%[y])\n\t" \
+ "punpckhwd %%mm4,%%mm1\n\t" /*mm1=04 03 07 09*/ \
+ "movq %%mm2,%%mm7\n\t" /*mm7=19 18 17 16*/ \
+ "punpckhdq %%mm1,%%mm0\n\t" /*mm0=04 03 11 10*/ \
+ "punpckhwd %%mm5,%%mm7\n\t" /*mm7=12 19 15 18*/ \
+ "punpcklwd %%mm3,%%mm1\n\t" /*mm1=25 07 24 09*/ \
+ "punpcklwd %%mm6,%%mm5\n\t" /*mm5=21 14 20 13*/ \
+ "punpcklwd %%mm2,%%mm1\n\t" /*mm1=17 24 16 09 *B*/ \
+ OC_ZZ_LOAD_ROW_LO(4,"%%mm2") /*mm2=35 34 33 32*/ \
+ "movq %%mm1,0x08(%[y])\n\t" \
+ OC_ZZ_LOAD_ROW_LO(5,"%%mm1") /*mm1=43 42 41 40*/ \
+ "pshufw $0x78,%%mm0,%%mm0\n\t" /*mm0=11 04 03 10 *C*/ \
+ "movq %%mm0,0x10(%[y])\n\t" \
+ "punpckhdq %%mm4,%%mm6\n\t" /*mm6=?? 07 23 22*/ \
+ "punpckldq %%mm5,%%mm4\n\t" /*mm4=20 13 06 05 *D*/ \
+ "movq %%mm4,0x28(%[y])\n\t" \
+ "psrlq $16,%%mm3\n\t" /*mm3=.. 27 26 25*/ \
+ "pshufw $0x0E,%%mm2,%%mm0\n\t" /*mm0=?? ?? 35 34*/ \
+ "movq %%mm7,%%mm4\n\t" /*mm4=12 19 15 18*/ \
+ "punpcklwd %%mm3,%%mm2\n\t" /*mm2=26 33 25 32*/ \
+ "punpcklwd %%mm1,%%mm4\n\t" /*mm4=41 15 40 18*/ \
+ "punpckhwd %%mm1,%%mm3\n\t" /*mm3=43 .. 42 27*/ \
+ "punpckldq %%mm2,%%mm4\n\t" /*mm4=25 32 40 18*/ \
+ "punpcklwd %%mm0,%%mm3\n\t" /*mm3=35 42 34 27*/ \
+ OC_ZZ_LOAD_ROW_LO(6,"%%mm0") /*mm0=51 50 49 48*/ \
+ "pshufw $0x6C,%%mm4,%%mm4\n\t" /*mm4=40 32 25 18 *E*/ \
+ "movq %%mm4,0x18(%[y])\n\t" \
+ OC_ZZ_LOAD_ROW_LO(7,"%%mm4") /*mm4=59 58 57 56*/ \
+ "punpckhdq %%mm7,%%mm2\n\t" /*mm2=12 19 26 33 *F*/ \
+ "movq %%mm2,0x20(%[y])\n\t" \
+ "pshufw $0xD0,%%mm1,%%mm1\n\t" /*mm1=43 41 ?? ??*/ \
+ "pshufw $0x87,%%mm0,%%mm0\n\t" /*mm0=50 48 49 51*/ \
+ "movq %%mm3,%%mm2\n\t" /*mm2=35 42 34 27*/ \
+ "punpckhwd %%mm0,%%mm1\n\t" /*mm1=50 43 48 41*/ \
+ "pshufw $0x93,%%mm4,%%mm4\n\t" /*mm4=58 57 56 59*/ \
+ "punpckldq %%mm1,%%mm3\n\t" /*mm3=48 41 34 27 *G*/ \
+ "movq %%mm3,0x30(%[y])\n\t" \
+ "punpckhdq %%mm4,%%mm1\n\t" /*mm1=58 57 50 43 *H*/ \
+ "movq %%mm1,0x50(%[y])\n\t" \
+ OC_ZZ_LOAD_ROW_HI(7,"%%mm1") /*mm1=63 62 61 60*/ \
+ "punpcklwd %%mm0,%%mm4\n\t" /*mm4=49 56 51 59*/ \
+ OC_ZZ_LOAD_ROW_HI(6,"%%mm0") /*mm0=55 54 53 52*/ \
+ "psllq $16,%%mm6\n\t" /*mm6=07 23 22 ..*/ \
+ "movq %%mm4,%%mm3\n\t" /*mm3=49 56 51 59*/ \
+ "punpckhdq %%mm2,%%mm4\n\t" /*mm4=35 42 49 56 *I*/ \
+ OC_ZZ_LOAD_ROW_HI(3,"%%mm2") /*mm2=31 30 29 28*/ \
+ "movq %%mm4,0x38(%[y])\n\t" \
+ "punpcklwd %%mm1,%%mm3\n\t" /*mm3=61 51 60 59*/ \
+ "punpcklwd %%mm6,%%mm7\n\t" /*mm7=22 15 .. ??*/ \
+ "movq %%mm3,%%mm4\n\t" /*mm4=61 51 60 59*/ \
+ "punpcklwd %%mm0,%%mm3\n\t" /*mm3=53 60 52 59*/ \
+ "punpckhwd %%mm0,%%mm4\n\t" /*mm4=55 61 54 51*/ \
+ OC_ZZ_LOAD_ROW_HI(4,"%%mm0") /*mm0=39 38 37 36*/ \
+ "pshufw $0xE1,%%mm3,%%mm3\n\t" /*mm3=53 60 59 52 *J*/ \
+ "movq %%mm3,0x68(%[y])\n\t" \
+ "movq %%mm4,%%mm3\n\t" /*mm3=?? ?? 54 51*/ \
+ "pshufw $0x39,%%mm2,%%mm2\n\t" /*mm2=28 31 30 29*/ \
+ "punpckhwd %%mm1,%%mm4\n\t" /*mm4=63 55 62 61 *K*/ \
+ OC_ZZ_LOAD_ROW_HI(5,"%%mm1") /*mm1=47 46 45 44*/ \
+ "movq %%mm4,0x78(%[y])\n\t" \
+ "punpckhwd %%mm2,%%mm6\n\t" /*mm6=28 07 31 23*/ \
+ "punpcklwd %%mm0,%%mm2\n\t" /*mm2=37 30 36 29*/ \
+ "punpckhdq %%mm6,%%mm5\n\t" /*mm5=28 07 21 14*/ \
+ "pshufw $0x4B,%%mm2,%%mm2\n\t" /*mm2=36 29 30 37*/ \
+ "pshufw $0x87,%%mm5,%%mm5\n\t" /*mm5=07 14 21 28 *L*/ \
+ "movq %%mm5,0x40(%[y])\n\t" \
+ "punpckhdq %%mm2,%%mm7\n\t" /*mm7=36 29 22 15 *M*/ \
+ "movq %%mm7,0x48(%[y])\n\t" \
+ "pshufw $0x9C,%%mm1,%%mm1\n\t" /*mm1=46 45 47 44*/ \
+ "punpckhwd %%mm1,%%mm0\n\t" /*mm0=46 39 45 38*/ \
+ "punpcklwd %%mm1,%%mm3\n\t" /*mm3=47 54 44 51*/ \
+ "punpckldq %%mm0,%%mm6\n\t" /*mm6=45 38 31 23 *N*/ \
+ "movq %%mm6,0x60(%[y])\n\t" \
+ "punpckhdq %%mm3,%%mm0\n\t" /*mm0=47 54 46 39*/ \
+ "punpckldq %%mm2,%%mm3\n\t" /*mm3=30 37 44 51 *O*/ \
+ "movq %%mm3,0x58(%[y])\n\t" \
+ "pshufw $0xB1,%%mm0,%%mm0\n\t" /*mm0=54 47 39 46 *P*/ \
+ "movq %%mm0,0x70(%[y])\n\t" \
+
+/*Converts DCT coefficients in %[dct] from natural order into zig-zag scan
+ order and stores them in %[qdct].
+ The index of each output element in the original 64-element array should wind
+ up in the following 8x8 matrix (the letters indicate the order we compute
+ each 4-tuple below):
+ A 0 1 8 16 9 2 3 10 B
+ C 17 24 32 25 18 11 4 5 D
+ E 12 19 26 33 40 48 41 34 I
+ H 27 20 13 6 7 14 21 28 G
+ K 35 42 49 56 57 50 43 36 J
+ F 29 22 15 23 30 37 44 51 M
+ P 58 59 52 45 38 31 39 46 L
+ N 53 60 61 54 47 55 62 63 O
+ The order of the coefficients within each tuple is reversed in the comments
+ below to reflect the usual MSB to LSB notation.*/
+#define OC_ZIG_ZAG_MMXEXT \
+ "movq 0x00(%[dct]),%%mm0\n\t" /*mm0=03 02 01 00*/ \
+ "movq 0x08(%[dct]),%%mm1\n\t" /*mm1=07 06 05 04*/ \
+ "movq 0x10(%[dct]),%%mm2\n\t" /*mm2=11 10 09 08*/ \
+ "movq 0x20(%[dct]),%%mm3\n\t" /*mm3=19 18 17 16*/ \
+ "movq 0x30(%[dct]),%%mm4\n\t" /*mm4=27 26 25 24*/ \
+ "movq 0x40(%[dct]),%%mm5\n\t" /*mm5=35 34 33 32*/ \
+ "movq %%mm2,%%mm7\n\t" /*mm7=11 10 09 08*/ \
+ "punpcklwd %%mm3,%%mm2\n\t" /*mm2=17 09 16 08*/ \
+ "movq %%mm0,%%mm6\n\t" /*mm6=03 02 01 00*/ \
+ "punpckldq %%mm2,%%mm0\n\t" /*mm0=16 08 01 00 *A*/ \
+ "movq %%mm0,0x00(%[qdct])\n\t" \
+ "movq 0x18(%[dct]),%%mm0\n\t" /*mm0=15 14 13 12*/ \
+ "punpckhdq %%mm6,%%mm6\n\t" /*mm6=03 02 03 02*/ \
+ "psrlq $16,%%mm7\n\t" /*mm7=.. 11 10 09*/ \
+ "punpckldq %%mm7,%%mm6\n\t" /*mm6=10 09 03 02*/ \
+ "punpckhwd %%mm7,%%mm3\n\t" /*mm3=.. 19 11 18*/ \
+ "pshufw $0xD2,%%mm6,%%mm6\n\t" /*mm6=10 03 02 09 *B*/ \
+ "movq %%mm6,0x08(%[qdct])\n\t" \
+ "psrlq $48,%%mm2\n\t" /*mm2=.. .. .. 17*/ \
+ "movq %%mm1,%%mm6\n\t" /*mm6=07 06 05 04*/ \
+ "punpcklwd %%mm5,%%mm2\n\t" /*mm2=33 .. 32 17*/ \
+ "movq %%mm3,%%mm7\n\t" /*mm7=.. 19 11 18*/ \
+ "punpckldq %%mm1,%%mm3\n\t" /*mm3=05 04 11 18 *C*/ \
+ "por %%mm2,%%mm7\n\t" /*mm7=33 19 ?? ??*/ \
+ "punpcklwd %%mm4,%%mm2\n\t" /*mm2=25 32 24 17 *D**/ \
+ "movq %%mm2,0x10(%[qdct])\n\t" \
+ "movq %%mm3,0x18(%[qdct])\n\t" \
+ "movq 0x28(%[dct]),%%mm2\n\t" /*mm2=23 22 21 20*/ \
+ "movq 0x38(%[dct]),%%mm1\n\t" /*mm1=31 30 29 28*/ \
+ "pshufw $0x9C,%%mm0,%%mm3\n\t" /*mm3=14 13 15 12*/ \
+ "punpckhdq %%mm7,%%mm7\n\t" /*mm7=33 19 33 19*/ \
+ "punpckhwd %%mm3,%%mm6\n\t" /*mm6=14 07 13 06*/ \
+ "punpckldq %%mm0,%%mm0\n\t" /*mm0=13 12 13 12*/ \
+ "punpcklwd %%mm1,%%mm3\n\t" /*mm3=29 15 28 12*/ \
+ "punpckhwd %%mm4,%%mm0\n\t" /*mm0=27 13 26 12*/ \
+ "pshufw $0xB4,%%mm3,%%mm3\n\t" /*mm3=15 29 28 12*/ \
+ "psrlq $48,%%mm4\n\t" /*mm4=.. .. .. 27*/ \
+ "punpcklwd %%mm7,%%mm0\n\t" /*mm0=33 26 19 12 *E*/ \
+ "punpcklwd %%mm1,%%mm4\n\t" /*mm4=29 .. 28 27*/ \
+ "punpckhwd %%mm2,%%mm3\n\t" /*mm3=23 15 22 29 *F*/ \
+ "movq %%mm0,0x20(%[qdct])\n\t" \
+ "movq %%mm3,0x50(%[qdct])\n\t" \
+ "movq 0x60(%[dct]),%%mm3\n\t" /*mm3=51 50 49 48*/ \
+ "movq 0x70(%[dct]),%%mm7\n\t" /*mm7=59 58 57 56*/ \
+ "movq 0x50(%[dct]),%%mm0\n\t" /*mm0=43 42 41 40*/ \
+ "punpcklwd %%mm4,%%mm2\n\t" /*mm2=28 21 27 20*/ \
+ "psrlq $32,%%mm5\n\t" /*mm5=.. .. 35 34*/ \
+ "movq %%mm2,%%mm4\n\t" /*mm4=28 21 27 20*/ \
+ "punpckldq %%mm6,%%mm2\n\t" /*mm2=13 06 27 20*/ \
+ "punpckhdq %%mm4,%%mm6\n\t" /*mm6=28 21 14 07 *G*/ \
+ "movq %%mm3,%%mm4\n\t" /*mm4=51 50 49 48*/ \
+ "pshufw $0xB1,%%mm2,%%mm2\n\t" /*mm2=06 13 20 27 *H*/ \
+ "movq %%mm2,0x30(%[qdct])\n\t" \
+ "movq %%mm6,0x38(%[qdct])\n\t" \
+ "movq 0x48(%[dct]),%%mm2\n\t" /*mm2=39 38 37 36*/ \
+ "punpcklwd %%mm5,%%mm4\n\t" /*mm4=35 49 34 48*/ \
+ "movq 0x58(%[dct]),%%mm5\n\t" /*mm5=47 46 45 44*/ \
+ "punpckldq %%mm7,%%mm6\n\t" /*mm6=57 56 14 07*/ \
+ "psrlq $32,%%mm3\n\t" /*mm3=.. .. 51 50*/ \
+ "punpckhwd %%mm0,%%mm6\n\t" /*mm6=43 57 42 56*/ \
+ "punpcklwd %%mm4,%%mm0\n\t" /*mm0=34 41 48 40 *I*/ \
+ "pshufw $0x4E,%%mm6,%%mm6\n\t" /*mm6=42 56 43 57*/ \
+ "movq %%mm0,0x28(%[qdct])\n\t" \
+ "punpcklwd %%mm2,%%mm3\n\t" /*mm3=37 51 36 50*/ \
+ "punpckhwd %%mm6,%%mm4\n\t" /*mm4=42 35 56 49*/ \
+ "punpcklwd %%mm3,%%mm6\n\t" /*mm6=36 43 50 57 *J*/ \
+ "pshufw $0x4E,%%mm4,%%mm4\n\t" /*mm4=56 49 42 35 *K*/ \
+ "movq %%mm4,0x40(%[qdct])\n\t" \
+ "movq %%mm6,0x48(%[qdct])\n\t" \
+ "movq 0x68(%[dct]),%%mm6\n\t" /*mm6=55 54 53 52*/ \
+ "movq 0x78(%[dct]),%%mm0\n\t" /*mm0=63 62 61 60*/ \
+ "psrlq $32,%%mm1\n\t" /*mm1=.. .. 31 30*/ \
+ "pshufw $0xD8,%%mm5,%%mm5\n\t" /*mm5=47 45 46 44*/ \
+ "pshufw $0x0B,%%mm3,%%mm3\n\t" /*mm3=50 50 51 37*/ \
+ "punpcklwd %%mm5,%%mm1\n\t" /*mm1=46 31 44 30*/ \
+ "pshufw $0xC9,%%mm6,%%mm6\n\t" /*mm6=55 52 54 53*/ \
+ "punpckhwd %%mm1,%%mm2\n\t" /*mm2=46 39 31 38 *L*/ \
+ "punpcklwd %%mm3,%%mm1\n\t" /*mm1=51 44 37 30 *M*/ \
+ "movq %%mm2,0x68(%[qdct])\n\t" \
+ "movq %%mm1,0x58(%[qdct])\n\t" \
+ "punpckhwd %%mm6,%%mm5\n\t" /*mm5=55 47 52 45*/ \
+ "punpckldq %%mm0,%%mm6\n\t" /*mm6=61 60 54 53*/ \
+ "pshufw $0x10,%%mm5,%%mm4\n\t" /*mm4=45 52 45 45*/ \
+ "pshufw $0x78,%%mm6,%%mm6\n\t" /*mm6=53 60 61 54 *N*/ \
+ "punpckhdq %%mm0,%%mm5\n\t" /*mm5=63 62 55 47 *O*/ \
+ "punpckhdq %%mm4,%%mm7\n\t" /*mm7=45 52 59 58 *P*/ \
+ "movq %%mm6,0x70(%[qdct])\n\t" \
+ "movq %%mm5,0x78(%[qdct])\n\t" \
+ "movq %%mm7,0x60(%[qdct])\n\t" \
+
+#endif
diff --git a/thirdparty/libtheora/x86_vc/mmxencfrag.c b/thirdparty/libtheora/x86_vc/mmxencfrag.c
index 94f1d06513..a6be819135 100644
--- a/thirdparty/libtheora/x86_vc/mmxencfrag.c
+++ b/thirdparty/libtheora/x86_vc/mmxencfrag.c
@@ -266,7 +266,7 @@ unsigned oc_enc_frag_sad2_thresh_mmxext(const unsigned char *_src,
/*Performs the first two stages of an 8-point 1-D Hadamard transform.
The transform is performed in place, except that outputs 0-3 are swapped with
outputs 4-7.
- Outputs 2, 3, 6 and 7 from the second stage are negated (which allows us to
+ Outputs 2, 3, 6, and 7 from the second stage are negated (which allows us to
perform this stage in place with no temporary registers).*/
#define OC_HADAMARD_AB_8x4 __asm{ \
/*Stage A: \
@@ -299,7 +299,7 @@ unsigned oc_enc_frag_sad2_thresh_mmxext(const unsigned char *_src,
}
/*Performs the last stage of an 8-point 1-D Hadamard transform in place.
- Ouputs 1, 3, 5, and 7 are negated (which allows us to perform this stage in
+ Outputs 1, 3, 5, and 7 are negated (which allows us to perform this stage in
place with no temporary registers).*/
#define OC_HADAMARD_C_8x4 __asm{ \
/*Stage C:*/ \
@@ -468,12 +468,14 @@ unsigned oc_enc_frag_sad2_thresh_mmxext(const unsigned char *_src,
mm7 = d3 c3 b3 a3*/ \
}
-static unsigned oc_int_frag_satd_thresh_mmxext(const unsigned char *_src,
- int _src_ystride,const unsigned char *_ref,int _ref_ystride,unsigned _thresh){
- OC_ALIGN8(ogg_int16_t buf[64]);
- ogg_int16_t *bufp;
- unsigned ret1;
- unsigned ret2;
+static unsigned oc_int_frag_satd_mmxext(int *_dc,
+ const unsigned char *_src,int _src_ystride,
+ const unsigned char *_ref,int _ref_ystride){
+ OC_ALIGN8(ogg_int16_t buf[64]);
+ ogg_int16_t *bufp;
+ unsigned ret;
+ unsigned ret2;
+ int dc;
bufp=buf;
__asm{
#define SRC esi
@@ -481,8 +483,10 @@ static unsigned oc_int_frag_satd_thresh_mmxext(const unsigned char *_src,
#define SRC_YSTRIDE ecx
#define REF_YSTRIDE edx
#define BUF edi
-#define RET eax
-#define RET2 edx
+#define RET edx
+#define RET2 ecx
+#define DC eax
+#define DC_WORD ax
mov SRC,_src
mov SRC_YSTRIDE,_src_ystride
mov REF,_ref
@@ -508,14 +512,18 @@ static unsigned oc_int_frag_satd_thresh_mmxext(const unsigned char *_src,
movq mm2,[0x20+BUF]
movq mm3,[0x30+BUF]
movq mm0,[0x00+BUF]
- OC_HADAMARD_ABS_ACCUM_8x4(0x28,0x38)
+ /*We split out the stages here so we can save the DC coefficient in the
+ middle.*/
+ OC_HADAMARD_AB_8x4
+ OC_HADAMARD_C_ABS_ACCUM_A_8x4(0x28,0x38)
+ movd DC,mm1
+ OC_HADAMARD_C_ABS_ACCUM_B_8x4(0x28,0x38)
/*Up to this point, everything fit in 16 bits (8 input + 1 for the
difference + 2*3 for the two 8-point 1-D Hadamards - 1 for the abs - 1
for the factor of two we dropped + 3 for the vertical accumulation).
Now we finally have to promote things to dwords.
We break this part out of OC_HADAMARD_ABS_ACCUM_8x4 to hide the long
latency of pmaddwd by starting the next series of loads now.*/
- mov RET2,_thresh
pmaddwd mm0,mm7
movq mm1,[0x50+BUF]
movq mm5,[0x58+BUF]
@@ -525,29 +533,28 @@ static unsigned oc_int_frag_satd_thresh_mmxext(const unsigned char *_src,
movq mm6,[0x68+BUF]
paddd mm4,mm0
movq mm3,[0x70+BUF]
- movd RET,mm4
+ movd RET2,mm4
movq mm7,[0x78+BUF]
- /*The sums produced by OC_HADAMARD_ABS_ACCUM_8x4 each have an extra 4
- added to them, and a factor of two removed; correct the final sum here.*/
- lea RET,[RET+RET-32]
movq mm0,[0x40+BUF]
- cmp RET,RET2
movq mm4,[0x48+BUF]
- jae at_end
OC_HADAMARD_ABS_ACCUM_8x4(0x68,0x78)
pmaddwd mm0,mm7
- /*There isn't much to stick in here to hide the latency this time, but the
- alternative to pmaddwd is movq->punpcklwd->punpckhwd->paddd, whose
- latency is even worse.*/
- sub RET,32
+ /*Subtract abs(dc) from 2*ret2.*/
+ movsx DC,DC_WORD
+ cdq
+ lea RET2,[RET+RET2*2]
movq mm4,mm0
punpckhdq mm0,mm0
+ xor RET,DC
paddd mm4,mm0
- movd RET2,mm4
- lea RET,[RET+RET2*2]
- align 16
-at_end:
- mov ret1,RET
+ /*The sums produced by OC_HADAMARD_ABS_ACCUM_8x4 each have an extra 4
+ added to them, a factor of two removed, and the DC value included;
+ correct the final sum here.*/
+ sub RET2,RET
+ movd RET,mm4
+ lea RET,[RET2+RET*2-64]
+ mov ret,RET
+ mov dc,DC
#undef SRC
#undef REF
#undef SRC_YSTRIDE
@@ -555,18 +562,21 @@ at_end:
#undef BUF
#undef RET
#undef RET2
+#undef DC
+#undef DC_WORD
}
- return ret1;
+ *_dc=dc;
+ return ret;
}
-unsigned oc_enc_frag_satd_thresh_mmxext(const unsigned char *_src,
- const unsigned char *_ref,int _ystride,unsigned _thresh){
- return oc_int_frag_satd_thresh_mmxext(_src,_ystride,_ref,_ystride,_thresh);
+unsigned oc_enc_frag_satd_mmxext(int *_dc,const unsigned char *_src,
+ const unsigned char *_ref,int _ystride){
+ return oc_int_frag_satd_mmxext(_dc,_src,_ystride,_ref,_ystride);
}
/*Our internal implementation of frag_copy2 takes an extra stride parameter so
- we can share code with oc_enc_frag_satd2_thresh_mmxext().*/
+ we can share code with oc_enc_frag_satd2_mmxext().*/
static void oc_int_frag_copy2_mmxext(unsigned char *_dst,int _dst_ystride,
const unsigned char *_src1,const unsigned char *_src2,int _src_ystride){
__asm{
@@ -694,30 +704,31 @@ static void oc_int_frag_copy2_mmxext(unsigned char *_dst,int _dst_ystride,
}
}
-unsigned oc_enc_frag_satd2_thresh_mmxext(const unsigned char *_src,
- const unsigned char *_ref1,const unsigned char *_ref2,int _ystride,
- unsigned _thresh){
+unsigned oc_enc_frag_satd2_mmxext(int *_dc,const unsigned char *_src,
+ const unsigned char *_ref1,const unsigned char *_ref2,int _ystride){
OC_ALIGN8(unsigned char ref[64]);
oc_int_frag_copy2_mmxext(ref,8,_ref1,_ref2,_ystride);
- return oc_int_frag_satd_thresh_mmxext(_src,_ystride,ref,8,_thresh);
+ return oc_int_frag_satd_mmxext(_dc,_src,_ystride,ref,8);
}
-unsigned oc_enc_frag_intra_satd_mmxext(const unsigned char *_src,
+unsigned oc_enc_frag_intra_satd_mmxext(int *_dc,const unsigned char *_src,
int _ystride){
- OC_ALIGN8(ogg_int16_t buf[64]);
- ogg_int16_t *bufp;
- unsigned ret1;
- unsigned ret2;
+ OC_ALIGN8(ogg_int16_t buf[64]);
+ ogg_int16_t *bufp;
+ unsigned ret1;
+ unsigned ret2;
+ int dc;
bufp=buf;
__asm{
#define SRC eax
#define SRC4 esi
#define BUF edi
-#define RET eax
-#define RET_WORD ax
-#define RET2 ecx
#define YSTRIDE edx
#define YSTRIDE3 ecx
+#define RET eax
+#define RET2 ecx
+#define DC edx
+#define DC_WORD dx
mov SRC,_src
mov BUF,bufp
mov YSTRIDE,_ystride
@@ -749,7 +760,7 @@ unsigned oc_enc_frag_intra_satd_mmxext(const unsigned char *_src,
middle.*/
OC_HADAMARD_AB_8x4
OC_HADAMARD_C_ABS_ACCUM_A_8x4(0x28,0x38)
- movd RET,mm1
+ movd DC,mm1
OC_HADAMARD_C_ABS_ACCUM_B_8x4(0x28,0x38)
/*Up to this point, everything fit in 16 bits (8 input + 1 for the
difference + 2*3 for the two 8-point 1-D Hadamards - 1 for the abs - 1
@@ -767,31 +778,34 @@ unsigned oc_enc_frag_intra_satd_mmxext(const unsigned char *_src,
movq mm3,[0x70+BUF]
paddd mm4,mm0
movq mm7,[0x78+BUF]
- movd RET2,mm4
+ movd RET,mm4
movq mm0,[0x40+BUF]
movq mm4,[0x48+BUF]
OC_HADAMARD_ABS_ACCUM_8x4(0x68,0x78)
pmaddwd mm0,mm7
/*We assume that the DC coefficient is always positive (which is true,
because the input to the INTRA transform was not a difference).*/
- movzx RET,RET_WORD
- add RET2,RET2
- sub RET2,RET
+ movzx DC,DC_WORD
+ add RET,RET
+ sub RET,DC
movq mm4,mm0
punpckhdq mm0,mm0
paddd mm4,mm0
- movd RET,mm4
- lea RET,[-64+RET2+RET*2]
+ movd RET2,mm4
+ lea RET,[-64+RET+RET2*2]
+ mov [dc],DC
mov [ret1],RET
#undef SRC
#undef SRC4
#undef BUF
-#undef RET
-#undef RET_WORD
-#undef RET2
#undef YSTRIDE
#undef YSTRIDE3
+#undef RET
+#undef RET2
+#undef DC
+#undef DC_WORD
}
+ *_dc=dc;
return ret1;
}
diff --git a/thirdparty/libtheora/x86_vc/mmxfdct.c b/thirdparty/libtheora/x86_vc/mmxfdct.c
index d908ce2413..c9ee530ea2 100644
--- a/thirdparty/libtheora/x86_vc/mmxfdct.c
+++ b/thirdparty/libtheora/x86_vc/mmxfdct.c
@@ -12,6 +12,7 @@
/*MMX fDCT implementation for x86_32*/
/*$Id: fdct_ses2.c 14579 2008-03-12 06:42:40Z xiphmont $*/
#include "x86enc.h"
+#include "x86zigzag.h"
#if defined(OC_X86_ASM)
@@ -462,18 +463,22 @@
}
/*MMX implementation of the fDCT.*/
-void oc_enc_fdct8x8_mmx(ogg_int16_t _y[64],const ogg_int16_t _x[64]){
- ptrdiff_t a;
+void oc_enc_fdct8x8_mmxext(ogg_int16_t _y[64],const ogg_int16_t _x[64]){
+ OC_ALIGN8(ogg_int16_t buf[64]);
+ ogg_int16_t *bufp;
+ bufp=buf;
__asm{
+#define X edx
#define Y eax
#define A ecx
-#define X edx
+#define BUF esi
/*Add two extra bits of working precision to improve accuracy; any more and
we could overflow.*/
/*We also add biases to correct for some systematic error that remains in
the full fDCT->iDCT round trip.*/
mov X, _x
mov Y, _y
+ mov BUF, bufp
movq mm0,[0x00+X]
movq mm1,[0x10+X]
movq mm2,[0x20+X]
@@ -591,79 +596,90 @@ void oc_enc_fdct8x8_mmx(ogg_int16_t _y[64],const ogg_int16_t _x[64]){
movq mm3,[0x30+Y]
OC_FDCT_STAGE1_8x4
OC_FDCT8x4(0x00,0x10,0x20,0x30,0x08,0x18,0x28,0x38)
- OC_TRANSPOSE8x4(0x00,0x10,0x20,0x30,0x08,0x18,0x28,0x38)
/*mm0={-2}x4*/
- pcmpeqw mm0,mm0
- paddw mm0,mm0
- /*Round the results.*/
- psubw mm1,mm0
- psubw mm2,mm0
- psraw mm1,2
- psubw mm3,mm0
- movq [0x18+Y],mm1
- psraw mm2,2
- psubw mm4,mm0
- movq mm1,[0x08+Y]
- psraw mm3,2
- psubw mm5,mm0
+ pcmpeqw mm2,mm2
+ paddw mm2,mm2
+ /*Round and store the results (no transpose).*/
+ movq mm7,[Y+0x10]
+ psubw mm4,mm2
+ psubw mm6,mm2
psraw mm4,2
- psubw mm6,mm0
- psraw mm5,2
- psubw mm7,mm0
+ psubw mm0,mm2
+ movq [BUF+0x00],mm4
+ movq mm4,[Y+0x30]
psraw mm6,2
- psubw mm1,mm0
+ psubw mm5,mm2
+ movq [BUF+0x20],mm6
+ psraw mm0,2
+ psubw mm3,mm2
+ movq [BUF+0x40],mm0
+ psraw mm5,2
+ psubw mm1,mm2
+ movq [BUF+0x50],mm5
+ psraw mm3,2
+ psubw mm7,mm2
+ movq [BUF+0x60],mm3
+ psraw mm1,2
+ psubw mm4,mm2
+ movq [BUF+0x70],mm1
psraw mm7,2
+ movq [BUF+0x10],mm7
+ psraw mm4,2
+ movq [BUF+0x30],mm4
+ /*Load the next block.*/
movq mm0,[0x40+Y]
- psraw mm1,2
- movq [0x30+Y],mm7
movq mm7,[0x78+Y]
- movq [0x08+Y],mm1
movq mm1,[0x50+Y]
- movq [0x20+Y],mm6
movq mm6,[0x68+Y]
- movq [0x28+Y],mm2
movq mm2,[0x60+Y]
- movq [0x10+Y],mm5
movq mm5,[0x58+Y]
- movq [0x38+Y],mm3
movq mm3,[0x70+Y]
- movq [0x00+Y],mm4
movq mm4,[0x48+Y]
OC_FDCT_STAGE1_8x4
OC_FDCT8x4(0x40,0x50,0x60,0x70,0x48,0x58,0x68,0x78)
- OC_TRANSPOSE8x4(0x40,0x50,0x60,0x70,0x48,0x58,0x68,0x78)
/*mm0={-2}x4*/
- pcmpeqw mm0,mm0
- paddw mm0,mm0
- /*Round the results.*/
- psubw mm1,mm0
- psubw mm2,mm0
- psraw mm1,2
- psubw mm3,mm0
- movq [0x58+Y],mm1
- psraw mm2,2
- psubw mm4,mm0
- movq mm1,[0x48+Y]
- psraw mm3,2
- psubw mm5,mm0
- movq [0x68+Y],mm2
+ pcmpeqw mm2,mm2
+ paddw mm2,mm2
+ /*Round and store the results (no transpose).*/
+ movq mm7,[Y+0x50]
+ psubw mm4,mm2
+ psubw mm6,mm2
psraw mm4,2
- psubw mm6,mm0
- movq [0x78+Y],mm3
- psraw mm5,2
- psubw mm7,mm0
- movq [0x40+Y],mm4
+ psubw mm0,mm2
+ movq [BUF+0x08],mm4
+ movq mm4,[Y+0x70]
psraw mm6,2
- psubw mm1,mm0
- movq [0x50+Y],mm5
- psraw mm7,2
- movq [0x60+Y],mm6
+ psubw mm5,mm2
+ movq [BUF+0x28],mm6
+ psraw mm0,2
+ psubw mm3,mm2
+ movq [BUF+0x48],mm0
+ psraw mm5,2
+ psubw mm1,mm2
+ movq [BUF+0x58],mm5
+ psraw mm3,2
+ psubw mm7,mm2
+ movq [BUF+0x68],mm3
psraw mm1,2
- movq [0x70+Y],mm7
- movq [0x48+Y],mm1
+ psubw mm4,mm2
+ movq [BUF+0x78],mm1
+ psraw mm7,2
+ movq [BUF+0x18],mm7
+ psraw mm4,2
+ movq [BUF+0x38],mm4
+#define OC_ZZ_LOAD_ROW_LO(_row,_reg) \
+ __asm movq _reg,[BUF+16*(_row)] \
+
+#define OC_ZZ_LOAD_ROW_HI(_row,_reg) \
+ __asm movq _reg,[BUF+16*(_row)+8] \
+
+ OC_TRANSPOSE_ZIG_ZAG_MMXEXT
+#undef OC_ZZ_LOAD_ROW_LO
+#undef OC_ZZ_LOAD_ROW_HI
+#undef X
#undef Y
#undef A
-#undef X
+#undef BUF
}
}
diff --git a/thirdparty/libtheora/x86_vc/mmxfrag.c b/thirdparty/libtheora/x86_vc/mmxfrag.c
index 4eb2084dc6..248312ff90 100644
--- a/thirdparty/libtheora/x86_vc/mmxfrag.c
+++ b/thirdparty/libtheora/x86_vc/mmxfrag.c
@@ -11,7 +11,7 @@
********************************************************************
function:
- last mod: $Id: mmxfrag.c 16578 2009-09-25 19:50:48Z cristianadam $
+ last mod: $Id$
********************************************************************/
@@ -22,12 +22,63 @@
The iteration each instruction belongs to is marked in the comments as #i.*/
#include <stddef.h>
#include "x86int.h"
-#include "mmxfrag.h"
#if defined(OC_X86_ASM)
/*Copies an 8x8 block of pixels from _src to _dst, assuming _ystride bytes
between rows.*/
+# define OC_FRAG_COPY_MMX(_dst,_src,_ystride) \
+ do{ \
+ const unsigned char *src; \
+ unsigned char *dst; \
+ src=(_src); \
+ dst=(_dst); \
+ __asm mov SRC,src \
+ __asm mov DST,dst \
+ __asm mov YSTRIDE,_ystride \
+ /*src+0*ystride*/ \
+ __asm movq mm0,[SRC] \
+ /*src+1*ystride*/ \
+ __asm movq mm1,[SRC+YSTRIDE] \
+ /*ystride3=ystride*3*/ \
+ __asm lea YSTRIDE3,[YSTRIDE+YSTRIDE*2] \
+ /*src+2*ystride*/ \
+ __asm movq mm2,[SRC+YSTRIDE*2] \
+ /*src+3*ystride*/ \
+ __asm movq mm3,[SRC+YSTRIDE3] \
+ /*dst+0*ystride*/ \
+ __asm movq [DST],mm0 \
+ /*dst+1*ystride*/ \
+ __asm movq [DST+YSTRIDE],mm1 \
+ /*Pointer to next 4.*/ \
+ __asm lea SRC,[SRC+YSTRIDE*4] \
+ /*dst+2*ystride*/ \
+ __asm movq [DST+YSTRIDE*2],mm2 \
+ /*dst+3*ystride*/ \
+ __asm movq [DST+YSTRIDE3],mm3 \
+ /*Pointer to next 4.*/ \
+ __asm lea DST,[DST+YSTRIDE*4] \
+ /*src+0*ystride*/ \
+ __asm movq mm0,[SRC] \
+ /*src+1*ystride*/ \
+ __asm movq mm1,[SRC+YSTRIDE] \
+ /*src+2*ystride*/ \
+ __asm movq mm2,[SRC+YSTRIDE*2] \
+ /*src+3*ystride*/ \
+ __asm movq mm3,[SRC+YSTRIDE3] \
+ /*dst+0*ystride*/ \
+ __asm movq [DST],mm0 \
+ /*dst+1*ystride*/ \
+ __asm movq [DST+YSTRIDE],mm1 \
+ /*dst+2*ystride*/ \
+ __asm movq [DST+YSTRIDE*2],mm2 \
+ /*dst+3*ystride*/ \
+ __asm movq [DST+YSTRIDE3],mm3 \
+ } \
+ while(0)
+
+/*Copies an 8x8 block of pixels from _src to _dst, assuming _ystride bytes
+ between rows.*/
void oc_frag_copy_mmx(unsigned char *_dst,
const unsigned char *_src,int _ystride){
#define SRC edx
@@ -41,6 +92,34 @@ void oc_frag_copy_mmx(unsigned char *_dst,
#undef YSTRIDE3
}
+/*Copies the fragments specified by the lists of fragment indices from one
+ frame to another.
+ _dst_frame: The reference frame to copy to.
+ _src_frame: The reference frame to copy from.
+ _ystride: The row stride of the reference frames.
+ _fragis: A pointer to a list of fragment indices.
+ _nfragis: The number of fragment indices to copy.
+ _frag_buf_offs: The offsets of fragments in the reference frames.*/
+void oc_frag_copy_list_mmx(unsigned char *_dst_frame,
+ const unsigned char *_src_frame,int _ystride,
+ const ptrdiff_t *_fragis,ptrdiff_t _nfragis,const ptrdiff_t *_frag_buf_offs){
+ ptrdiff_t fragii;
+ for(fragii=0;fragii<_nfragis;fragii++){
+ ptrdiff_t frag_buf_off;
+ frag_buf_off=_frag_buf_offs[_fragis[fragii]];
+#define SRC edx
+#define DST eax
+#define YSTRIDE ecx
+#define YSTRIDE3 edi
+ OC_FRAG_COPY_MMX(_dst_frame+frag_buf_off,
+ _src_frame+frag_buf_off,_ystride);
+#undef SRC
+#undef DST
+#undef YSTRIDE
+#undef YSTRIDE3
+ }
+}
+
void oc_frag_recon_intra_mmx(unsigned char *_dst,int _ystride,
const ogg_int16_t *_residue){
__asm{
diff --git a/thirdparty/libtheora/x86_vc/mmxfrag.h b/thirdparty/libtheora/x86_vc/mmxfrag.h
deleted file mode 100644
index 45ee93e777..0000000000
--- a/thirdparty/libtheora/x86_vc/mmxfrag.h
+++ /dev/null
@@ -1,61 +0,0 @@
-#if !defined(_x86_vc_mmxfrag_H)
-# define _x86_vc_mmxfrag_H (1)
-# include <stddef.h>
-# include "x86int.h"
-
-#if defined(OC_X86_ASM)
-
-/*Copies an 8x8 block of pixels from _src to _dst, assuming _ystride bytes
- between rows.*/
-#define OC_FRAG_COPY_MMX(_dst,_src,_ystride) \
- do{ \
- const unsigned char *src; \
- unsigned char *dst; \
- src=(_src); \
- dst=(_dst); \
- __asm mov SRC,src \
- __asm mov DST,dst \
- __asm mov YSTRIDE,_ystride \
- /*src+0*ystride*/ \
- __asm movq mm0,[SRC] \
- /*src+1*ystride*/ \
- __asm movq mm1,[SRC+YSTRIDE] \
- /*ystride3=ystride*3*/ \
- __asm lea YSTRIDE3,[YSTRIDE+YSTRIDE*2] \
- /*src+2*ystride*/ \
- __asm movq mm2,[SRC+YSTRIDE*2] \
- /*src+3*ystride*/ \
- __asm movq mm3,[SRC+YSTRIDE3] \
- /*dst+0*ystride*/ \
- __asm movq [DST],mm0 \
- /*dst+1*ystride*/ \
- __asm movq [DST+YSTRIDE],mm1 \
- /*Pointer to next 4.*/ \
- __asm lea SRC,[SRC+YSTRIDE*4] \
- /*dst+2*ystride*/ \
- __asm movq [DST+YSTRIDE*2],mm2 \
- /*dst+3*ystride*/ \
- __asm movq [DST+YSTRIDE3],mm3 \
- /*Pointer to next 4.*/ \
- __asm lea DST,[DST+YSTRIDE*4] \
- /*src+0*ystride*/ \
- __asm movq mm0,[SRC] \
- /*src+1*ystride*/ \
- __asm movq mm1,[SRC+YSTRIDE] \
- /*src+2*ystride*/ \
- __asm movq mm2,[SRC+YSTRIDE*2] \
- /*src+3*ystride*/ \
- __asm movq mm3,[SRC+YSTRIDE3] \
- /*dst+0*ystride*/ \
- __asm movq [DST],mm0 \
- /*dst+1*ystride*/ \
- __asm movq [DST+YSTRIDE],mm1 \
- /*dst+2*ystride*/ \
- __asm movq [DST+YSTRIDE*2],mm2 \
- /*dst+3*ystride*/ \
- __asm movq [DST+YSTRIDE3],mm3 \
- } \
- while(0)
-
-# endif
-#endif
diff --git a/thirdparty/libtheora/x86_vc/mmxidct.c b/thirdparty/libtheora/x86_vc/mmxidct.c
index 8f5ff6803c..55e00aedcf 100644
--- a/thirdparty/libtheora/x86_vc/mmxidct.c
+++ b/thirdparty/libtheora/x86_vc/mmxidct.c
@@ -11,7 +11,7 @@
********************************************************************
function:
- last mod: $Id: mmxidct.c 16503 2009-08-22 18:14:02Z giles $
+ last mod: $Id$
********************************************************************/
@@ -24,15 +24,15 @@
/*These are offsets into the table of constants below.*/
/*7 rows of cosines, in order: pi/16 * (1 ... 7).*/
-#define OC_COSINE_OFFSET (0)
+#define OC_COSINE_OFFSET (8)
/*A row of 8's.*/
-#define OC_EIGHT_OFFSET (56)
+#define OC_EIGHT_OFFSET (0)
/*A table of constants used by the MMX routines.*/
-static const __declspec(align(16))ogg_uint16_t
- OC_IDCT_CONSTS[(7+1)*4]={
+static const OC_ALIGN16(ogg_uint16_t) OC_IDCT_CONSTS[(1+7)*4]={
+ 8, 8, 8, 8,
(ogg_uint16_t)OC_C1S7,(ogg_uint16_t)OC_C1S7,
(ogg_uint16_t)OC_C1S7,(ogg_uint16_t)OC_C1S7,
(ogg_uint16_t)OC_C2S6,(ogg_uint16_t)OC_C2S6,
@@ -46,28 +46,27 @@ static const __declspec(align(16))ogg_uint16_t
(ogg_uint16_t)OC_C6S2,(ogg_uint16_t)OC_C6S2,
(ogg_uint16_t)OC_C6S2,(ogg_uint16_t)OC_C6S2,
(ogg_uint16_t)OC_C7S1,(ogg_uint16_t)OC_C7S1,
- (ogg_uint16_t)OC_C7S1,(ogg_uint16_t)OC_C7S1,
- 8, 8, 8, 8
+ (ogg_uint16_t)OC_C7S1,(ogg_uint16_t)OC_C7S1
};
/*38 cycles*/
-#define OC_IDCT_BEGIN __asm{ \
- __asm movq mm2,OC_I(3) \
+#define OC_IDCT_BEGIN(_y,_x) __asm{ \
+ __asm movq mm2,OC_I(3,_x) \
__asm movq mm6,OC_C(3) \
__asm movq mm4,mm2 \
- __asm movq mm7,OC_J(5) \
+ __asm movq mm7,OC_J(5,_x) \
__asm pmulhw mm4,mm6 \
__asm movq mm1,OC_C(5) \
__asm pmulhw mm6,mm7 \
__asm movq mm5,mm1 \
__asm pmulhw mm1,mm2 \
- __asm movq mm3,OC_I(1) \
+ __asm movq mm3,OC_I(1,_x) \
__asm pmulhw mm5,mm7 \
__asm movq mm0,OC_C(1) \
__asm paddw mm4,mm2 \
__asm paddw mm6,mm7 \
__asm paddw mm2,mm1 \
- __asm movq mm1,OC_J(7) \
+ __asm movq mm1,OC_J(7,_x) \
__asm paddw mm7,mm5 \
__asm movq mm5,mm0 \
__asm pmulhw mm0,mm3 \
@@ -77,13 +76,13 @@ static const __declspec(align(16))ogg_uint16_t
__asm psubw mm6,mm2 \
__asm paddw mm0,mm3 \
__asm pmulhw mm3,mm7 \
- __asm movq mm2,OC_I(2) \
+ __asm movq mm2,OC_I(2,_x) \
__asm pmulhw mm7,mm1 \
__asm paddw mm5,mm1 \
__asm movq mm1,mm2 \
__asm pmulhw mm2,OC_C(2) \
__asm psubw mm3,mm5 \
- __asm movq mm5,OC_J(6) \
+ __asm movq mm5,OC_J(6,_x) \
__asm paddw mm0,mm7 \
__asm movq mm7,mm5 \
__asm psubw mm0,mm4 \
@@ -97,18 +96,18 @@ static const __declspec(align(16))ogg_uint16_t
__asm paddw mm6,mm6 \
__asm pmulhw mm7,OC_C(6) \
__asm paddw mm6,mm3 \
- __asm movq OC_I(1),mm4 \
+ __asm movq OC_I(1,_y),mm4 \
__asm psubw mm1,mm5 \
__asm movq mm4,OC_C(4) \
__asm movq mm5,mm3 \
__asm pmulhw mm3,mm4 \
__asm paddw mm7,mm2 \
- __asm movq OC_I(2),mm6 \
+ __asm movq OC_I(2,_y),mm6 \
__asm movq mm2,mm0 \
- __asm movq mm6,OC_I(0) \
+ __asm movq mm6,OC_I(0,_x) \
__asm pmulhw mm0,mm4 \
__asm paddw mm5,mm3 \
- __asm movq mm3,OC_J(4) \
+ __asm movq mm3,OC_J(4,_x) \
__asm psubw mm5,mm1 \
__asm paddw mm2,mm0 \
__asm psubw mm6,mm3 \
@@ -122,17 +121,17 @@ static const __declspec(align(16))ogg_uint16_t
__asm paddw mm6,mm0 \
__asm psubw mm6,mm2 \
__asm paddw mm2,mm2 \
- __asm movq mm0,OC_I(1) \
+ __asm movq mm0,OC_I(1,_y) \
__asm paddw mm2,mm6 \
__asm paddw mm4,mm3 \
__asm psubw mm2,mm1 \
}
/*38+8=46 cycles.*/
-#define OC_ROW_IDCT __asm{ \
- OC_IDCT_BEGIN \
+#define OC_ROW_IDCT(_y,_x) __asm{ \
+ OC_IDCT_BEGIN(_y,_x) \
/*r3=D'*/ \
- __asm movq mm3,OC_I(2) \
+ __asm movq mm3,OC_I(2,_y) \
/*r4=E'=E-G*/ \
__asm psubw mm4,mm7 \
/*r1=H'+H'*/ \
@@ -157,7 +156,7 @@ static const __declspec(align(16))ogg_uint16_t
__asm psubw mm7,mm0 \
__asm paddw mm0,mm0 \
/*Save R1.*/ \
- __asm movq OC_I(1),mm1 \
+ __asm movq OC_I(1,_y),mm1 \
/*r0=R0=G.+C.*/ \
__asm paddw mm0,mm7 \
}
@@ -190,10 +189,10 @@ static const __declspec(align(16))ogg_uint16_t
Since r1 is free at entry, we calculate the Js first.*/
/*19 cycles.*/
-#define OC_TRANSPOSE __asm{ \
+#define OC_TRANSPOSE(_y) __asm{ \
__asm movq mm1,mm4 \
__asm punpcklwd mm4,mm5 \
- __asm movq OC_I(0),mm0 \
+ __asm movq OC_I(0,_y),mm0 \
__asm punpckhwd mm1,mm5 \
__asm movq mm0,mm6 \
__asm punpcklwd mm6,mm7 \
@@ -201,17 +200,17 @@ static const __declspec(align(16))ogg_uint16_t
__asm punpckldq mm4,mm6 \
__asm punpckhdq mm5,mm6 \
__asm movq mm6,mm1 \
- __asm movq OC_J(4),mm4 \
+ __asm movq OC_J(4,_y),mm4 \
__asm punpckhwd mm0,mm7 \
- __asm movq OC_J(5),mm5 \
+ __asm movq OC_J(5,_y),mm5 \
__asm punpckhdq mm6,mm0 \
- __asm movq mm4,OC_I(0) \
+ __asm movq mm4,OC_I(0,_y) \
__asm punpckldq mm1,mm0 \
- __asm movq mm5,OC_I(1) \
+ __asm movq mm5,OC_I(1,_y) \
__asm movq mm0,mm4 \
- __asm movq OC_J(7),mm6 \
+ __asm movq OC_J(7,_y),mm6 \
__asm punpcklwd mm0,mm5 \
- __asm movq OC_J(6),mm1 \
+ __asm movq OC_J(6,_y),mm1 \
__asm punpckhwd mm4,mm5 \
__asm movq mm5,mm2 \
__asm punpcklwd mm2,mm3 \
@@ -219,18 +218,18 @@ static const __declspec(align(16))ogg_uint16_t
__asm punpckldq mm0,mm2 \
__asm punpckhdq mm1,mm2 \
__asm movq mm2,mm4 \
- __asm movq OC_I(0),mm0 \
+ __asm movq OC_I(0,_y),mm0 \
__asm punpckhwd mm5,mm3 \
- __asm movq OC_I(1),mm1 \
+ __asm movq OC_I(1,_y),mm1 \
__asm punpckhdq mm4,mm5 \
__asm punpckldq mm2,mm5 \
- __asm movq OC_I(3),mm4 \
- __asm movq OC_I(2),mm2 \
+ __asm movq OC_I(3,_y),mm4 \
+ __asm movq OC_I(2,_y),mm2 \
}
/*38+19=57 cycles.*/
-#define OC_COLUMN_IDCT __asm{ \
- OC_IDCT_BEGIN \
+#define OC_COLUMN_IDCT(_y) __asm{ \
+ OC_IDCT_BEGIN(_y,_y) \
__asm paddw mm2,OC_8 \
/*r1=H'+H'*/ \
__asm paddw mm1,mm1 \
@@ -243,15 +242,15 @@ static const __declspec(align(16))ogg_uint16_t
/*r1=NR1*/ \
__asm psraw mm1,4 \
/*r3=D'*/ \
- __asm movq mm3,OC_I(2) \
+ __asm movq mm3,OC_I(2,_y) \
/*r7=G+G*/ \
__asm paddw mm7,mm7 \
/*Store NR2 at I(2).*/ \
- __asm movq OC_I(2),mm2 \
+ __asm movq OC_I(2,_y),mm2 \
/*r7=G'=E+G*/ \
__asm paddw mm7,mm4 \
/*Store NR1 at I(1).*/ \
- __asm movq OC_I(1),mm1 \
+ __asm movq OC_I(1,_y),mm1 \
/*r4=R4=E'-D'*/ \
__asm psubw mm4,mm3 \
__asm paddw mm4,OC_8 \
@@ -273,11 +272,11 @@ static const __declspec(align(16))ogg_uint16_t
/*r6=NR6*/ \
__asm psraw mm6,4 \
/*Store NR4 at J(4).*/ \
- __asm movq OC_J(4),mm4 \
+ __asm movq OC_J(4,_y),mm4 \
/*r5=NR5*/ \
__asm psraw mm5,4 \
/*Store NR3 at I(3).*/ \
- __asm movq OC_I(3),mm3 \
+ __asm movq OC_I(3,_y),mm3 \
/*r7=R7=G'-C'*/ \
__asm psubw mm7,mm0 \
__asm paddw mm7,OC_8 \
@@ -288,71 +287,89 @@ static const __declspec(align(16))ogg_uint16_t
/*r7=NR7*/ \
__asm psraw mm7,4 \
/*Store NR6 at J(6).*/ \
- __asm movq OC_J(6),mm6 \
+ __asm movq OC_J(6,_y),mm6 \
/*r0=NR0*/ \
__asm psraw mm0,4 \
/*Store NR5 at J(5).*/ \
- __asm movq OC_J(5),mm5 \
+ __asm movq OC_J(5,_y),mm5 \
/*Store NR7 at J(7).*/ \
- __asm movq OC_J(7),mm7 \
+ __asm movq OC_J(7,_y),mm7 \
/*Store NR0 at I(0).*/ \
- __asm movq OC_I(0),mm0 \
+ __asm movq OC_I(0,_y),mm0 \
}
#define OC_MID(_m,_i) [CONSTS+_m+(_i)*8]
#define OC_C(_i) OC_MID(OC_COSINE_OFFSET,_i-1)
#define OC_8 OC_MID(OC_EIGHT_OFFSET,0)
-static void oc_idct8x8_slow(ogg_int16_t _y[64]){
+static void oc_idct8x8_slow(ogg_int16_t _y[64],ogg_int16_t _x[64]){
+ int i;
/*This routine accepts an 8x8 matrix, but in partially transposed form.
Every 4x4 block is transposed.*/
__asm{
#define CONSTS eax
#define Y edx
+#define X ecx
mov CONSTS,offset OC_IDCT_CONSTS
mov Y,_y
-#define OC_I(_k) [Y+_k*16]
-#define OC_J(_k) [Y+(_k-4)*16+8]
- OC_ROW_IDCT
- OC_TRANSPOSE
+ mov X,_x
+#define OC_I(_k,_y) [(_y)+(_k)*16]
+#define OC_J(_k,_y) [(_y)+((_k)-4)*16+8]
+ OC_ROW_IDCT(Y,X)
+ OC_TRANSPOSE(Y)
#undef OC_I
#undef OC_J
-#define OC_I(_k) [Y+(_k*16)+64]
-#define OC_J(_k) [Y+(_k-4)*16+72]
- OC_ROW_IDCT
- OC_TRANSPOSE
+#define OC_I(_k,_y) [(_y)+(_k)*16+64]
+#define OC_J(_k,_y) [(_y)+((_k)-4)*16+72]
+ OC_ROW_IDCT(Y,X)
+ OC_TRANSPOSE(Y)
#undef OC_I
#undef OC_J
-#define OC_I(_k) [Y+_k*16]
-#define OC_J(_k) OC_I(_k)
- OC_COLUMN_IDCT
+#define OC_I(_k,_y) [(_y)+(_k)*16]
+#define OC_J(_k,_y) OC_I(_k,_y)
+ OC_COLUMN_IDCT(Y)
#undef OC_I
#undef OC_J
-#define OC_I(_k) [Y+_k*16+8]
-#define OC_J(_k) OC_I(_k)
- OC_COLUMN_IDCT
+#define OC_I(_k,_y) [(_y)+(_k)*16+8]
+#define OC_J(_k,_y) OC_I(_k,_y)
+ OC_COLUMN_IDCT(Y)
#undef OC_I
#undef OC_J
#undef CONSTS
#undef Y
+#undef X
+ }
+ __asm pxor mm0,mm0;
+ for(i=0;i<4;i++){
+ ogg_int16_t *x;
+ x=_x+16*i;
+#define X ecx
+ __asm{
+ mov X,x
+ movq [X+0x00],mm0
+ movq [X+0x08],mm0
+ movq [X+0x10],mm0
+ movq [X+0x18],mm0
+ }
+#undef X
}
}
/*25 cycles.*/
-#define OC_IDCT_BEGIN_10 __asm{ \
- __asm movq mm2,OC_I(3) \
+#define OC_IDCT_BEGIN_10(_y,_x) __asm{ \
+ __asm movq mm2,OC_I(3,_x) \
__asm nop \
__asm movq mm6,OC_C(3) \
__asm movq mm4,mm2 \
__asm movq mm1,OC_C(5) \
__asm pmulhw mm4,mm6 \
- __asm movq mm3,OC_I(1) \
+ __asm movq mm3,OC_I(1,_x) \
__asm pmulhw mm1,mm2 \
__asm movq mm0,OC_C(1) \
__asm paddw mm4,mm2 \
__asm pxor mm6,mm6 \
__asm paddw mm2,mm1 \
- __asm movq mm5,OC_I(2) \
+ __asm movq mm5,OC_I(2,_x) \
__asm pmulhw mm0,mm3 \
__asm movq mm1,mm5 \
__asm paddw mm0,mm3 \
@@ -360,43 +377,43 @@ static void oc_idct8x8_slow(ogg_int16_t _y[64]){
__asm psubw mm6,mm2 \
__asm pmulhw mm5,OC_C(2) \
__asm psubw mm0,mm4 \
- __asm movq mm7,OC_I(2) \
+ __asm movq mm7,OC_I(2,_x) \
__asm paddw mm4,mm4 \
__asm paddw mm7,mm5 \
__asm paddw mm4,mm0 \
__asm pmulhw mm1,OC_C(6) \
__asm psubw mm3,mm6 \
- __asm movq OC_I(1),mm4 \
+ __asm movq OC_I(1,_y),mm4 \
__asm paddw mm6,mm6 \
__asm movq mm4,OC_C(4) \
__asm paddw mm6,mm3 \
__asm movq mm5,mm3 \
__asm pmulhw mm3,mm4 \
- __asm movq OC_I(2),mm6 \
+ __asm movq OC_I(2,_y),mm6 \
__asm movq mm2,mm0 \
- __asm movq mm6,OC_I(0) \
+ __asm movq mm6,OC_I(0,_x) \
__asm pmulhw mm0,mm4 \
__asm paddw mm5,mm3 \
__asm paddw mm2,mm0 \
__asm psubw mm5,mm1 \
__asm pmulhw mm6,mm4 \
- __asm paddw mm6,OC_I(0) \
+ __asm paddw mm6,OC_I(0,_x) \
__asm paddw mm1,mm1 \
__asm movq mm4,mm6 \
__asm paddw mm1,mm5 \
__asm psubw mm6,mm2 \
__asm paddw mm2,mm2 \
- __asm movq mm0,OC_I(1) \
+ __asm movq mm0,OC_I(1,_y) \
__asm paddw mm2,mm6 \
__asm psubw mm2,mm1 \
__asm nop \
}
/*25+8=33 cycles.*/
-#define OC_ROW_IDCT_10 __asm{ \
- OC_IDCT_BEGIN_10 \
+#define OC_ROW_IDCT_10(_y,_x) __asm{ \
+ OC_IDCT_BEGIN_10(_y,_x) \
/*r3=D'*/ \
- __asm movq mm3,OC_I(2) \
+ __asm movq mm3,OC_I(2,_y) \
/*r4=E'=E-G*/ \
__asm psubw mm4,mm7 \
/*r1=H'+H'*/ \
@@ -421,14 +438,14 @@ static void oc_idct8x8_slow(ogg_int16_t _y[64]){
__asm psubw mm7,mm0 \
__asm paddw mm0,mm0 \
/*Save R1.*/ \
- __asm movq OC_I(1),mm1 \
+ __asm movq OC_I(1,_y),mm1 \
/*r0=R0=G'+C'*/ \
__asm paddw mm0,mm7 \
}
/*25+19=44 cycles'*/
-#define OC_COLUMN_IDCT_10 __asm{ \
- OC_IDCT_BEGIN_10 \
+#define OC_COLUMN_IDCT_10(_y) __asm{ \
+ OC_IDCT_BEGIN_10(_y,_y) \
__asm paddw mm2,OC_8 \
/*r1=H'+H'*/ \
__asm paddw mm1,mm1 \
@@ -441,15 +458,15 @@ static void oc_idct8x8_slow(ogg_int16_t _y[64]){
/*r1=NR1*/ \
__asm psraw mm1,4 \
/*r3=D'*/ \
- __asm movq mm3,OC_I(2) \
+ __asm movq mm3,OC_I(2,_y) \
/*r7=G+G*/ \
__asm paddw mm7,mm7 \
/*Store NR2 at I(2).*/ \
- __asm movq OC_I(2),mm2 \
+ __asm movq OC_I(2,_y),mm2 \
/*r7=G'=E+G*/ \
__asm paddw mm7,mm4 \
/*Store NR1 at I(1).*/ \
- __asm movq OC_I(1),mm1 \
+ __asm movq OC_I(1,_y),mm1 \
/*r4=R4=E'-D'*/ \
__asm psubw mm4,mm3 \
__asm paddw mm4,OC_8 \
@@ -471,11 +488,11 @@ static void oc_idct8x8_slow(ogg_int16_t _y[64]){
/*r6=NR6*/ \
__asm psraw mm6,4 \
/*Store NR4 at J(4).*/ \
- __asm movq OC_J(4),mm4 \
+ __asm movq OC_J(4,_y),mm4 \
/*r5=NR5*/ \
__asm psraw mm5,4 \
/*Store NR3 at I(3).*/ \
- __asm movq OC_I(3),mm3 \
+ __asm movq OC_I(3,_y),mm3 \
/*r7=R7=G'-C'*/ \
__asm psubw mm7,mm0 \
__asm paddw mm7,OC_8 \
@@ -486,50 +503,63 @@ static void oc_idct8x8_slow(ogg_int16_t _y[64]){
/*r7=NR7*/ \
__asm psraw mm7,4 \
/*Store NR6 at J(6).*/ \
- __asm movq OC_J(6),mm6 \
+ __asm movq OC_J(6,_y),mm6 \
/*r0=NR0*/ \
__asm psraw mm0,4 \
/*Store NR5 at J(5).*/ \
- __asm movq OC_J(5),mm5 \
+ __asm movq OC_J(5,_y),mm5 \
/*Store NR7 at J(7).*/ \
- __asm movq OC_J(7),mm7 \
+ __asm movq OC_J(7,_y),mm7 \
/*Store NR0 at I(0).*/ \
- __asm movq OC_I(0),mm0 \
+ __asm movq OC_I(0,_y),mm0 \
}
-static void oc_idct8x8_10(ogg_int16_t _y[64]){
+static void oc_idct8x8_10(ogg_int16_t _y[64],ogg_int16_t _x[64]){
__asm{
#define CONSTS eax
#define Y edx
+#define X ecx
mov CONSTS,offset OC_IDCT_CONSTS
mov Y,_y
-#define OC_I(_k) [Y+_k*16]
-#define OC_J(_k) [Y+(_k-4)*16+8]
+ mov X,_x
+#define OC_I(_k,_y) [(_y)+(_k)*16]
+#define OC_J(_k,_y) [(_y)+((_k)-4)*16+8]
/*Done with dequant, descramble, and partial transpose.
Now do the iDCT itself.*/
- OC_ROW_IDCT_10
- OC_TRANSPOSE
+ OC_ROW_IDCT_10(Y,X)
+ OC_TRANSPOSE(Y)
#undef OC_I
#undef OC_J
-#define OC_I(_k) [Y+_k*16]
-#define OC_J(_k) OC_I(_k)
- OC_COLUMN_IDCT_10
+#define OC_I(_k,_y) [(_y)+(_k)*16]
+#define OC_J(_k,_y) OC_I(_k,_y)
+ OC_COLUMN_IDCT_10(Y)
#undef OC_I
#undef OC_J
-#define OC_I(_k) [Y+_k*16+8]
-#define OC_J(_k) OC_I(_k)
- OC_COLUMN_IDCT_10
+#define OC_I(_k,_y) [(_y)+(_k)*16+8]
+#define OC_J(_k,_y) OC_I(_k,_y)
+ OC_COLUMN_IDCT_10(Y)
#undef OC_I
#undef OC_J
#undef CONSTS
#undef Y
+#undef X
+ }
+#define X ecx
+ __asm{
+ pxor mm0,mm0;
+ mov X,_x
+ movq [X+0x00],mm0
+ movq [X+0x10],mm0
+ movq [X+0x20],mm0
+ movq [X+0x30],mm0
}
+#undef X
}
/*Performs an inverse 8x8 Type-II DCT transform.
The input is assumed to be scaled by a factor of 4 relative to orthonormal
version of the transform.*/
-void oc_idct8x8_mmx(ogg_int16_t _y[64],int _last_zzi){
+void oc_idct8x8_mmx(ogg_int16_t _y[64],ogg_int16_t _x[64],int _last_zzi){
/*_last_zzi is subtly different from an actual count of the number of
coefficients we decoded for this block.
It contains the value of zzi BEFORE the final token in the block was
@@ -555,8 +585,8 @@ void oc_idct8x8_mmx(ogg_int16_t _y[64],int _last_zzi){
gets.
Needless to say we inherited this approach from VP3.*/
/*Perform the iDCT.*/
- if(_last_zzi<10)oc_idct8x8_10(_y);
- else oc_idct8x8_slow(_y);
+ if(_last_zzi<=10)oc_idct8x8_10(_y,_x);
+ else oc_idct8x8_slow(_y,_x);
}
#endif
diff --git a/thirdparty/libtheora/x86_vc/mmxstate.c b/thirdparty/libtheora/x86_vc/mmxstate.c
index 73bd1981cf..f532ee1b6f 100644
--- a/thirdparty/libtheora/x86_vc/mmxstate.c
+++ b/thirdparty/libtheora/x86_vc/mmxstate.c
@@ -11,7 +11,7 @@
********************************************************************
function:
- last mod: $Id: mmxstate.c 16584 2009-09-26 19:35:55Z tterribe $
+ last mod: $Id$
********************************************************************/
@@ -19,17 +19,16 @@
Originally written by Rudolf Marek.*/
#include <string.h>
#include "x86int.h"
-#include "mmxfrag.h"
#include "mmxloop.h"
#if defined(OC_X86_ASM)
void oc_state_frag_recon_mmx(const oc_theora_state *_state,ptrdiff_t _fragi,
- int _pli,ogg_int16_t _dct_coeffs[64],int _last_zzi,ogg_uint16_t _dc_quant){
+ int _pli,ogg_int16_t _dct_coeffs[128],int _last_zzi,ogg_uint16_t _dc_quant){
unsigned char *dst;
ptrdiff_t frag_buf_off;
int ystride;
- int mb_mode;
+ int refi;
/*Apply the inverse transform.*/
/*Special case only having a DC component.*/
if(_last_zzi<2){
@@ -45,6 +44,7 @@ void oc_state_frag_recon_mmx(const oc_theora_state *_state,ptrdiff_t _fragi,
#define P ecx
mov Y,_dct_coeffs
movzx P,p
+ lea Y,[Y+128]
/*mm0=0000 0000 0000 AAAA*/
movd mm0,P
/*mm0=0000 0000 AAAA AAAA*/
@@ -74,65 +74,32 @@ void oc_state_frag_recon_mmx(const oc_theora_state *_state,ptrdiff_t _fragi,
else{
/*Dequantize the DC coefficient.*/
_dct_coeffs[0]=(ogg_int16_t)(_dct_coeffs[0]*(int)_dc_quant);
- oc_idct8x8_mmx(_dct_coeffs,_last_zzi);
+ oc_idct8x8_mmx(_dct_coeffs+64,_dct_coeffs,_last_zzi);
}
/*Fill in the target buffer.*/
frag_buf_off=_state->frag_buf_offs[_fragi];
- mb_mode=_state->frags[_fragi].mb_mode;
+ refi=_state->frags[_fragi].refi;
ystride=_state->ref_ystride[_pli];
- dst=_state->ref_frame_data[_state->ref_frame_idx[OC_FRAME_SELF]]+frag_buf_off;
- if(mb_mode==OC_MODE_INTRA)oc_frag_recon_intra_mmx(dst,ystride,_dct_coeffs);
+ dst=_state->ref_frame_data[OC_FRAME_SELF]+frag_buf_off;
+ if(refi==OC_FRAME_SELF)oc_frag_recon_intra_mmx(dst,ystride,_dct_coeffs+64);
else{
const unsigned char *ref;
int mvoffsets[2];
- ref=
- _state->ref_frame_data[_state->ref_frame_idx[OC_FRAME_FOR_MODE(mb_mode)]]
- +frag_buf_off;
+ ref=_state->ref_frame_data[refi]+frag_buf_off;
if(oc_state_get_mv_offsets(_state,mvoffsets,_pli,
- _state->frag_mvs[_fragi][0],_state->frag_mvs[_fragi][1])>1){
+ _state->frag_mvs[_fragi])>1){
oc_frag_recon_inter2_mmx(dst,ref+mvoffsets[0],ref+mvoffsets[1],ystride,
- _dct_coeffs);
+ _dct_coeffs+64);
}
- else oc_frag_recon_inter_mmx(dst,ref+mvoffsets[0],ystride,_dct_coeffs);
+ else oc_frag_recon_inter_mmx(dst,ref+mvoffsets[0],ystride,_dct_coeffs+64);
}
}
/*We copy these entire function to inline the actual MMX routines so that we
use only a single indirect call.*/
-/*Copies the fragments specified by the lists of fragment indices from one
- frame to another.
- _fragis: A pointer to a list of fragment indices.
- _nfragis: The number of fragment indices to copy.
- _dst_frame: The reference frame to copy to.
- _src_frame: The reference frame to copy from.
- _pli: The color plane the fragments lie in.*/
-void oc_state_frag_copy_list_mmx(const oc_theora_state *_state,
- const ptrdiff_t *_fragis,ptrdiff_t _nfragis,
- int _dst_frame,int _src_frame,int _pli){
- const ptrdiff_t *frag_buf_offs;
- const unsigned char *src_frame_data;
- unsigned char *dst_frame_data;
- ptrdiff_t fragii;
- int ystride;
- dst_frame_data=_state->ref_frame_data[_state->ref_frame_idx[_dst_frame]];
- src_frame_data=_state->ref_frame_data[_state->ref_frame_idx[_src_frame]];
- ystride=_state->ref_ystride[_pli];
- frag_buf_offs=_state->frag_buf_offs;
- for(fragii=0;fragii<_nfragis;fragii++){
- ptrdiff_t frag_buf_off;
- frag_buf_off=frag_buf_offs[_fragis[fragii]];
-#define SRC edx
-#define DST eax
-#define YSTRIDE ecx
-#define YSTRIDE3 edi
- OC_FRAG_COPY_MMX(dst_frame_data+frag_buf_off,
- src_frame_data+frag_buf_off,ystride);
-#undef SRC
-#undef DST
-#undef YSTRIDE
-#undef YSTRIDE3
- }
+void oc_loop_filter_init_mmx(signed char _bv[256],int _flimit){
+ memset(_bv,~(_flimit<<1),8);
}
/*Apply the loop filter to a given set of fragment rows in the given plane.
@@ -144,8 +111,7 @@ void oc_state_frag_copy_list_mmx(const oc_theora_state *_state,
_fragy0: The Y coordinate of the first fragment row to filter.
_fragy_end: The Y coordinate of the fragment row to stop filtering at.*/
void oc_state_loop_filter_frag_rows_mmx(const oc_theora_state *_state,
- int _bv[256],int _refi,int _pli,int _fragy0,int _fragy_end){
- OC_ALIGN8(unsigned char ll[8]);
+ signed char _bv[256],int _refi,int _pli,int _fragy0,int _fragy_end){
const oc_fragment_plane *fplane;
const oc_fragment *frags;
const ptrdiff_t *frag_buf_offs;
@@ -156,13 +122,12 @@ void oc_state_loop_filter_frag_rows_mmx(const oc_theora_state *_state,
ptrdiff_t fragi0_end;
int ystride;
int nhfrags;
- memset(ll,_state->loop_filter_limits[_state->qis[0]],sizeof(ll));
fplane=_state->fplanes+_pli;
nhfrags=fplane->nhfrags;
fragi_top=fplane->froffset;
fragi_bot=fragi_top+fplane->nfrags;
fragi0=fragi_top+_fragy0*(ptrdiff_t)nhfrags;
- fragi0_end=fragi0+(_fragy_end-_fragy0)*(ptrdiff_t)nhfrags;
+ fragi0_end=fragi_top+_fragy_end*(ptrdiff_t)nhfrags;
ystride=_state->ref_ystride[_pli];
frags=_state->frags;
frag_buf_offs=_state->frag_buf_offs;
@@ -187,13 +152,13 @@ void oc_state_loop_filter_frag_rows_mmx(const oc_theora_state *_state,
#define LL edx
#define D esi
#define D_WORD si
- if(fragi>fragi0)OC_LOOP_FILTER_H_MMX(ref,ystride,ll);
- if(fragi0>fragi_top)OC_LOOP_FILTER_V_MMX(ref,ystride,ll);
+ if(fragi>fragi0)OC_LOOP_FILTER_H_MMX(ref,ystride,_bv);
+ if(fragi0>fragi_top)OC_LOOP_FILTER_V_MMX(ref,ystride,_bv);
if(fragi+1<fragi_end&&!frags[fragi+1].coded){
- OC_LOOP_FILTER_H_MMX(ref+8,ystride,ll);
+ OC_LOOP_FILTER_H_MMX(ref+8,ystride,_bv);
}
if(fragi+nhfrags<fragi_bot&&!frags[fragi+nhfrags].coded){
- OC_LOOP_FILTER_V_MMX(ref+(ystride<<3),ystride,ll);
+ OC_LOOP_FILTER_V_MMX(ref+(ystride<<3),ystride,_bv);
}
#undef PIX
#undef YSTRIDE3
diff --git a/thirdparty/libtheora/cpu.c b/thirdparty/libtheora/x86_vc/x86cpu.c
index a863aad7f3..6a1d8d850c 100644
--- a/thirdparty/libtheora/cpu.c
+++ b/thirdparty/libtheora/x86_vc/x86cpu.c
@@ -14,41 +14,17 @@
Originally written by Rudolf Marek.
function:
- last mod: $Id: cpu.c 16503 2009-08-22 18:14:02Z giles $
+ last mod: $Id$
********************************************************************/
-#include "cpu.h"
+#include "x86cpu.h"
#if !defined(OC_X86_ASM)
-static ogg_uint32_t oc_cpu_flags_get(void){
+ogg_uint32_t oc_cpu_flags_get(void){
return 0;
}
#else
-# if !defined(_MSC_VER)
-# if defined(__amd64__)||defined(__x86_64__)
-/*On x86-64, gcc seems to be able to figure out how to save %rbx for us when
- compiling with -fPIC.*/
-# define cpuid(_op,_eax,_ebx,_ecx,_edx) \
- __asm__ __volatile__( \
- "cpuid\n\t" \
- :[eax]"=a"(_eax),[ebx]"=b"(_ebx),[ecx]"=c"(_ecx),[edx]"=d"(_edx) \
- :"a"(_op) \
- :"cc" \
- )
-# else
-/*On x86-32, not so much.*/
-# define cpuid(_op,_eax,_ebx,_ecx,_edx) \
- __asm__ __volatile__( \
- "xchgl %%ebx,%[ebx]\n\t" \
- "cpuid\n\t" \
- "xchgl %%ebx,%[ebx]\n\t" \
- :[eax]"=a"(_eax),[ebx]"=r"(_ebx),[ecx]"=c"(_ecx),[edx]"=d"(_edx) \
- :"a"(_op) \
- :"cc" \
- )
-# endif
-# else
/*Why does MSVC need this complicated rigamarole?
At this point I honestly do not care.*/
@@ -95,7 +71,6 @@ static void oc_detect_cpuid_helper(ogg_uint32_t *_eax,ogg_uint32_t *_ebx){
mov [ecx],ebx
}
}
-# endif
static ogg_uint32_t oc_parse_intel_flags(ogg_uint32_t _edx,ogg_uint32_t _ecx){
ogg_uint32_t flags;
@@ -124,7 +99,7 @@ static ogg_uint32_t oc_parse_amd_flags(ogg_uint32_t _edx,ogg_uint32_t _ecx){
return flags;
}
-static ogg_uint32_t oc_cpu_flags_get(void){
+ogg_uint32_t oc_cpu_flags_get(void){
ogg_uint32_t flags;
ogg_uint32_t eax;
ogg_uint32_t ebx;
@@ -132,25 +107,7 @@ static ogg_uint32_t oc_cpu_flags_get(void){
ogg_uint32_t edx;
# if !defined(__amd64__)&&!defined(__x86_64__)
/*Not all x86-32 chips support cpuid, so we have to check.*/
-# if !defined(_MSC_VER)
- __asm__ __volatile__(
- "pushfl\n\t"
- "pushfl\n\t"
- "popl %[a]\n\t"
- "movl %[a],%[b]\n\t"
- "xorl $0x200000,%[a]\n\t"
- "pushl %[a]\n\t"
- "popfl\n\t"
- "pushfl\n\t"
- "popl %[a]\n\t"
- "popfl\n\t"
- :[a]"=r"(eax),[b]"=r"(ebx)
- :
- :"cc"
- );
-# else
oc_detect_cpuid_helper(&eax,&ebx);
-# endif
/*No cpuid.*/
if(eax==ebx)return 0;
# endif
@@ -159,9 +116,18 @@ static ogg_uint32_t oc_cpu_flags_get(void){
if(ecx==0x6C65746E&&edx==0x49656E69&&ebx==0x756E6547||
/* 6 8 x M T e n i u n e G*/
ecx==0x3638784D&&edx==0x54656E69&&ebx==0x756E6547){
+ int family;
+ int model;
/*Intel, Transmeta (tested with Crusoe TM5800):*/
cpuid(1,eax,ebx,ecx,edx);
flags=oc_parse_intel_flags(edx,ecx);
+ family=(eax>>8)&0xF;
+ model=(eax>>4)&0xF;
+ /*The SSE unit on the Pentium M and Core Duo is much slower than the MMX
+ unit, so don't use it.*/
+ if(family==6&&(model==9||model==13||model==14)){
+ flags&=~(OC_CPU_X86_SSE2|OC_CPU_X86_PNI);
+ }
}
/* D M A c i t n e h t u A*/
else if(ecx==0x444D4163&&edx==0x69746E65&&ebx==0x68747541||
diff --git a/thirdparty/libtheora/x86_vc/x86cpu.h b/thirdparty/libtheora/x86_vc/x86cpu.h
new file mode 100644
index 0000000000..eea261d448
--- /dev/null
+++ b/thirdparty/libtheora/x86_vc/x86cpu.h
@@ -0,0 +1,36 @@
+/********************************************************************
+ * *
+ * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. *
+ * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
+ * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
+ * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
+ * *
+ * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 *
+ * by the Xiph.Org Foundation and contributors http://www.xiph.org/ *
+ * *
+ ********************************************************************
+ function:
+ last mod: $Id$
+
+ ********************************************************************/
+
+#if !defined(_x86_vc_x86cpu_H)
+# define _x86_vc_x86cpu_H (1)
+#include "../internal.h"
+
+#define OC_CPU_X86_MMX (1<<0)
+#define OC_CPU_X86_3DNOW (1<<1)
+#define OC_CPU_X86_3DNOWEXT (1<<2)
+#define OC_CPU_X86_MMXEXT (1<<3)
+#define OC_CPU_X86_SSE (1<<4)
+#define OC_CPU_X86_SSE2 (1<<5)
+#define OC_CPU_X86_PNI (1<<6)
+#define OC_CPU_X86_SSSE3 (1<<7)
+#define OC_CPU_X86_SSE4_1 (1<<8)
+#define OC_CPU_X86_SSE4_2 (1<<9)
+#define OC_CPU_X86_SSE4A (1<<10)
+#define OC_CPU_X86_SSE5 (1<<11)
+
+ogg_uint32_t oc_cpu_flags_get(void);
+
+#endif
diff --git a/thirdparty/libtheora/x86_vc/x86enc.c b/thirdparty/libtheora/x86_vc/x86enc.c
index e1960e1f0b..e9d59e85e3 100644
--- a/thirdparty/libtheora/x86_vc/x86enc.c
+++ b/thirdparty/libtheora/x86_vc/x86enc.c
@@ -18,27 +18,25 @@
#if defined(OC_X86_ASM)
-#include "../cpu.c"
-
-void oc_enc_vtable_init_x86(oc_enc_ctx *_enc){
+void oc_enc_accel_init_x86(oc_enc_ctx *_enc){
ogg_uint32_t cpu_flags;
- cpu_flags=oc_cpu_flags_get();
- oc_enc_vtable_init_c(_enc);
+ cpu_flags=_enc->state.cpu_flags;
+ oc_enc_accel_init_c(_enc);
if(cpu_flags&OC_CPU_X86_MMX){
_enc->opt_vtable.frag_sub=oc_enc_frag_sub_mmx;
_enc->opt_vtable.frag_sub_128=oc_enc_frag_sub_128_mmx;
_enc->opt_vtable.frag_recon_intra=oc_frag_recon_intra_mmx;
_enc->opt_vtable.frag_recon_inter=oc_frag_recon_inter_mmx;
- _enc->opt_vtable.fdct8x8=oc_enc_fdct8x8_mmx;
}
if(cpu_flags&OC_CPU_X86_MMXEXT){
_enc->opt_vtable.frag_sad=oc_enc_frag_sad_mmxext;
_enc->opt_vtable.frag_sad_thresh=oc_enc_frag_sad_thresh_mmxext;
_enc->opt_vtable.frag_sad2_thresh=oc_enc_frag_sad2_thresh_mmxext;
- _enc->opt_vtable.frag_satd_thresh=oc_enc_frag_satd_thresh_mmxext;
- _enc->opt_vtable.frag_satd2_thresh=oc_enc_frag_satd2_thresh_mmxext;
+ _enc->opt_vtable.frag_satd=oc_enc_frag_satd_mmxext;
+ _enc->opt_vtable.frag_satd2=oc_enc_frag_satd2_mmxext;
_enc->opt_vtable.frag_intra_satd=oc_enc_frag_intra_satd_mmxext;
_enc->opt_vtable.frag_copy2=oc_enc_frag_copy2_mmxext;
+ _enc->opt_vtable.fdct8x8=oc_enc_fdct8x8_mmxext;
}
if(cpu_flags&OC_CPU_X86_SSE2){
# if defined(OC_X86_64_ASM)
diff --git a/thirdparty/libtheora/x86_vc/x86enc.h b/thirdparty/libtheora/x86_vc/x86enc.h
index 581484641f..885406a54d 100644
--- a/thirdparty/libtheora/x86_vc/x86enc.h
+++ b/thirdparty/libtheora/x86_vc/x86enc.h
@@ -17,10 +17,14 @@
#if !defined(_x86_vc_x86enc_H)
# define _x86_vc_x86enc_H (1)
-# include "../encint.h"
# include "x86int.h"
+# if defined(OC_X86_ASM)
+# define oc_enc_accel_init oc_enc_accel_init_x86
+# define OC_ENC_USE_VTABLE (1)
+# endif
+# include "../encint.h"
-void oc_enc_vtable_init_x86(oc_enc_ctx *_enc);
+void oc_enc_accel_init_x86(oc_enc_ctx *_enc);
unsigned oc_enc_frag_sad_mmxext(const unsigned char *_src,
const unsigned char *_ref,int _ystride);
@@ -29,19 +33,19 @@ unsigned oc_enc_frag_sad_thresh_mmxext(const unsigned char *_src,
unsigned oc_enc_frag_sad2_thresh_mmxext(const unsigned char *_src,
const unsigned char *_ref1,const unsigned char *_ref2,int _ystride,
unsigned _thresh);
-unsigned oc_enc_frag_satd_thresh_mmxext(const unsigned char *_src,
- const unsigned char *_ref,int _ystride,unsigned _thresh);
-unsigned oc_enc_frag_satd2_thresh_mmxext(const unsigned char *_src,
- const unsigned char *_ref1,const unsigned char *_ref2,int _ystride,
- unsigned _thresh);
-unsigned oc_enc_frag_intra_satd_mmxext(const unsigned char *_src,int _ystride);
+unsigned oc_enc_frag_satd_mmxext(unsigned *_dc,const unsigned char *_src,
+ const unsigned char *_ref,int _ystride);
+unsigned oc_enc_frag_satd2_mmxext(unsigned *_dc,const unsigned char *_src,
+ const unsigned char *_ref1,const unsigned char *_ref2,int _ystride);
+unsigned oc_enc_frag_intra_satd_mmxext(unsigned *_dc,
+ const unsigned char *_src,int _ystride);
void oc_enc_frag_sub_mmx(ogg_int16_t _diff[64],
const unsigned char *_x,const unsigned char *_y,int _stride);
void oc_enc_frag_sub_128_mmx(ogg_int16_t _diff[64],
const unsigned char *_x,int _stride);
void oc_enc_frag_copy2_mmxext(unsigned char *_dst,
const unsigned char *_src1,const unsigned char *_src2,int _ystride);
-void oc_enc_fdct8x8_mmx(ogg_int16_t _y[64],const ogg_int16_t _x[64]);
+void oc_enc_fdct8x8_mmxext(ogg_int16_t _y[64],const ogg_int16_t _x[64]);
void oc_enc_fdct8x8_x86_64sse2(ogg_int16_t _y[64],const ogg_int16_t _x[64]);
#endif
diff --git a/thirdparty/libtheora/x86_vc/x86int.h b/thirdparty/libtheora/x86_vc/x86int.h
index 4cca485311..318a09dca0 100644
--- a/thirdparty/libtheora/x86_vc/x86int.h
+++ b/thirdparty/libtheora/x86_vc/x86int.h
@@ -11,32 +11,39 @@
********************************************************************
function:
- last mod: $Id: x86int.h 16503 2009-08-22 18:14:02Z giles $
+ last mod: $Id$
********************************************************************/
#if !defined(_x86_vc_x86int_H)
# define _x86_vc_x86int_H (1)
# include "../internal.h"
+# if defined(OC_X86_ASM)
+# define oc_state_accel_init oc_state_accel_init_x86
+# define OC_STATE_USE_VTABLE (1)
+# endif
+# include "../state.h"
+# include "x86cpu.h"
-void oc_state_vtable_init_x86(oc_theora_state *_state);
+void oc_state_accel_init_x86(oc_theora_state *_state);
void oc_frag_copy_mmx(unsigned char *_dst,
const unsigned char *_src,int _ystride);
+void oc_frag_copy_list_mmx(unsigned char *_dst_frame,
+ const unsigned char *_src_frame,int _ystride,
+ const ptrdiff_t *_fragis,ptrdiff_t _nfragis,const ptrdiff_t *_frag_buf_offs);
void oc_frag_recon_intra_mmx(unsigned char *_dst,int _ystride,
const ogg_int16_t *_residue);
void oc_frag_recon_inter_mmx(unsigned char *_dst,
const unsigned char *_src,int _ystride,const ogg_int16_t *_residue);
void oc_frag_recon_inter2_mmx(unsigned char *_dst,const unsigned char *_src1,
const unsigned char *_src2,int _ystride,const ogg_int16_t *_residue);
-void oc_idct8x8_mmx(ogg_int16_t _y[64],int _last_zzi);
+void oc_idct8x8_mmx(ogg_int16_t _y[64],ogg_int16_t _x[64],int _last_zzi);
void oc_state_frag_recon_mmx(const oc_theora_state *_state,ptrdiff_t _fragi,
- int _pli,ogg_int16_t _dct_coeffs[64],int _last_zzi,ogg_uint16_t _dc_quant);
-void oc_state_frag_copy_list_mmx(const oc_theora_state *_state,
- const ptrdiff_t *_fragis,ptrdiff_t _nfragis,
- int _dst_frame,int _src_frame,int _pli);
+ int _pli,ogg_int16_t _dct_coeffs[128],int _last_zzi,ogg_uint16_t _dc_quant);
+void oc_loop_filter_init_mmx(signed char _bv[256],int _flimit);
void oc_state_loop_filter_frag_rows_mmx(const oc_theora_state *_state,
- int _bv[256],int _refi,int _pli,int _fragy0,int _fragy_end);
+ signed char _bv[256],int _refi,int _pli,int _fragy0,int _fragy_end);
void oc_restore_fpu_mmx(void);
#endif
diff --git a/thirdparty/libtheora/x86_vc/x86state.c b/thirdparty/libtheora/x86_vc/x86state.c
index a786bec284..fa3a0d42fc 100644
--- a/thirdparty/libtheora/x86_vc/x86state.c
+++ b/thirdparty/libtheora/x86_vc/x86state.c
@@ -11,7 +11,7 @@
********************************************************************
function:
- last mod: $Id: x86state.c 16503 2009-08-22 18:14:02Z giles $
+ last mod: $Id$
********************************************************************/
@@ -19,8 +19,6 @@
#if defined(OC_X86_ASM)
-#include "../cpu.c"
-
/*This table has been modified from OC_FZIG_ZAG by baking a 4x4 transpose into
each quadrant of the destination.*/
static const unsigned char OC_FZIG_ZAG_MMX[128]={
@@ -42,21 +40,22 @@ static const unsigned char OC_FZIG_ZAG_MMX[128]={
64,64,64,64,64,64,64,64,
};
-void oc_state_vtable_init_x86(oc_theora_state *_state){
+void oc_state_accel_init_x86(oc_theora_state *_state){
_state->cpu_flags=oc_cpu_flags_get();
if(_state->cpu_flags&OC_CPU_X86_MMX){
_state->opt_vtable.frag_copy=oc_frag_copy_mmx;
+ _state->opt_vtable.frag_copy_list=oc_frag_copy_list_mmx;
_state->opt_vtable.frag_recon_intra=oc_frag_recon_intra_mmx;
_state->opt_vtable.frag_recon_inter=oc_frag_recon_inter_mmx;
_state->opt_vtable.frag_recon_inter2=oc_frag_recon_inter2_mmx;
_state->opt_vtable.idct8x8=oc_idct8x8_mmx;
_state->opt_vtable.state_frag_recon=oc_state_frag_recon_mmx;
- _state->opt_vtable.state_frag_copy_list=oc_state_frag_copy_list_mmx;
+ _state->opt_vtable.loop_filter_init=oc_loop_filter_init_mmx;
_state->opt_vtable.state_loop_filter_frag_rows=
oc_state_loop_filter_frag_rows_mmx;
_state->opt_vtable.restore_fpu=oc_restore_fpu_mmx;
_state->opt_data.dct_fzig_zag=OC_FZIG_ZAG_MMX;
}
- else oc_state_vtable_init_c(_state);
+ else oc_state_accel_init_c(_state);
}
#endif
diff --git a/thirdparty/libtheora/x86_vc/x86zigzag.h b/thirdparty/libtheora/x86_vc/x86zigzag.h
new file mode 100644
index 0000000000..26f5ed2ea5
--- /dev/null
+++ b/thirdparty/libtheora/x86_vc/x86zigzag.h
@@ -0,0 +1,244 @@
+/********************************************************************
+ * *
+ * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. *
+ * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
+ * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
+ * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
+ * *
+ * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 *
+ * by the Xiph.Org Foundation and contributors http://www.xiph.org/ *
+ * *
+ ********************************************************************
+
+ function:
+ last mod: $Id: sse2trans.h 15675 2009-02-06 09:43:27Z tterribe $
+
+ ********************************************************************/
+
+#if !defined(_x86_vc_x86zigzag_H)
+# define _x86_vc_x86zigzag_H (1)
+# include "x86enc.h"
+
+
+/*Converts DCT coefficients from transposed order into zig-zag scan order and
+ stores them in Y.
+ This relies on two macros to load the contents of each row:
+ OC_ZZ_LOAD_ROW_LO(row,reg) and OC_ZZ_LOAD_ROW_HI(row,reg), which load the
+ first four and second four entries of each row into the specified register,
+ respectively.
+ OC_ZZ_LOAD_ROW_LO must be called before OC_ZZ_LOAD_ROW_HI for the same row
+ (because when the rows are already in SSE2 registers, loading the high half
+ destructively modifies the register).
+ The index of each output element in the original 64-element array should wind
+ up in the following 8x8 matrix (the letters indicate the order we compute
+ each 4-tuple below):
+ A 0 8 1 2 9 16 24 17 B
+ C 10 3 4 11 18 25 32 40 E
+ F 33 26 19 12 5 6 13 20 D
+ G 27 34 41 48 56 49 42 35 I
+ L 28 21 14 7 15 22 29 36 M
+ H 43 50 57 58 51 44 37 30 O
+ N 23 31 38 45 52 59 60 53 J
+ P 46 39 47 54 61 62 55 63 K
+ The order of the coefficients within each tuple is reversed in the comments
+ below to reflect the usual MSB to LSB notation.*/
+#define OC_TRANSPOSE_ZIG_ZAG_MMXEXT \
+ OC_ZZ_LOAD_ROW_LO(0,mm0) /*mm0=03 02 01 00*/ \
+ OC_ZZ_LOAD_ROW_LO(1,mm1) /*mm1=11 10 09 08*/ \
+ OC_ZZ_LOAD_ROW_LO(2,mm2) /*mm2=19 18 17 16*/ \
+ OC_ZZ_LOAD_ROW_LO(3,mm3) /*mm3=27 26 25 24*/ \
+ OC_ZZ_LOAD_ROW_HI(0,mm4) /*mm4=07 06 05 04*/ \
+ OC_ZZ_LOAD_ROW_HI(1,mm5) /*mm5=15 14 13 12*/ \
+ OC_ZZ_LOAD_ROW_HI(2,mm6) /*mm6=23 22 21 20*/ \
+ __asm movq mm7,mm0 /*mm7=03 02 01 00*/ \
+ __asm punpckhdq mm0,mm1 /*mm0=11 10 03 02*/ \
+ __asm pshufw mm4,mm4,0x39 /*mm4=04 07 06 05*/ \
+ __asm punpcklwd mm1,mm0 /*mm1=03 09 02 08*/ \
+ __asm pshufw mm5,mm5,0x39 /*mm5=12 15 14 13*/ \
+ __asm punpcklwd mm7,mm1 /*mm7=02 01 08 00 *A*/ \
+ __asm movq [Y+0x00],mm7 \
+ __asm punpckhwd mm1,mm4 /*mm1=04 03 07 09*/ \
+ __asm movq mm7,mm2 /*mm7=19 18 17 16*/ \
+ __asm punpckhdq mm0,mm1 /*mm0=04 03 11 10*/ \
+ __asm punpckhwd mm7,mm5 /*mm7=12 19 15 18*/ \
+ __asm punpcklwd mm1,mm3 /*mm1=25 07 24 09*/ \
+ __asm punpcklwd mm5,mm6 /*mm5=21 14 20 13*/ \
+ __asm punpcklwd mm1,mm2 /*mm1=17 24 16 09 *B*/ \
+ OC_ZZ_LOAD_ROW_LO(4,mm2) /*mm2=35 34 33 32*/ \
+ __asm movq [Y+0x08],mm1 \
+ OC_ZZ_LOAD_ROW_LO(5,mm1) /*mm1=43 42 41 40*/ \
+ __asm pshufw mm0,mm0,0x78 /*mm0=11 04 03 10 *C*/ \
+ __asm movq [Y+0x10],mm0 \
+ __asm punpckhdq mm6,mm4 /*mm6=?? 07 23 22*/ \
+ __asm punpckldq mm4,mm5 /*mm4=20 13 06 05 *D*/ \
+ __asm movq [Y+0x28],mm4 \
+ __asm psrlq mm3,16 /*mm3=.. 27 26 25*/ \
+ __asm pshufw mm0,mm2,0x0E /*mm0=?? ?? 35 34*/ \
+ __asm movq mm4,mm7 /*mm4=12 19 15 18*/ \
+ __asm punpcklwd mm2,mm3 /*mm2=26 33 25 32*/ \
+ __asm punpcklwd mm4,mm1 /*mm4=41 15 40 18*/ \
+ __asm punpckhwd mm3,mm1 /*mm3=43 .. 42 27*/ \
+ __asm punpckldq mm4,mm2 /*mm4=25 32 40 18*/ \
+ __asm punpcklwd mm3,mm0 /*mm3=35 42 34 27*/ \
+ OC_ZZ_LOAD_ROW_LO(6,mm0) /*mm0=51 50 49 48*/ \
+ __asm pshufw mm4,mm4,0x6C /*mm4=40 32 25 18 *E*/ \
+ __asm movq [Y+0x18],mm4 \
+ OC_ZZ_LOAD_ROW_LO(7,mm4) /*mm4=59 58 57 56*/ \
+ __asm punpckhdq mm2,mm7 /*mm2=12 19 26 33 *F*/ \
+ __asm movq [Y+0x20],mm2 \
+ __asm pshufw mm1,mm1,0xD0 /*mm1=43 41 ?? ??*/ \
+ __asm pshufw mm0,mm0,0x87 /*mm0=50 48 49 51*/ \
+ __asm movq mm2,mm3 /*mm2=35 42 34 27*/ \
+ __asm punpckhwd mm1,mm0 /*mm1=50 43 48 41*/ \
+ __asm pshufw mm4,mm4,0x93 /*mm4=58 57 56 59*/ \
+ __asm punpckldq mm3,mm1 /*mm3=48 41 34 27 *G*/ \
+ __asm movq [Y+0x30],mm3 \
+ __asm punpckhdq mm1,mm4 /*mm1=58 57 50 43 *H*/ \
+ __asm movq [Y+0x50],mm1 \
+ OC_ZZ_LOAD_ROW_HI(7,mm1) /*mm1=63 62 61 60*/ \
+ __asm punpcklwd mm4,mm0 /*mm4=49 56 51 59*/ \
+ OC_ZZ_LOAD_ROW_HI(6,mm0) /*mm0=55 54 53 52*/ \
+ __asm psllq mm6,16 /*mm6=07 23 22 ..*/ \
+ __asm movq mm3,mm4 /*mm3=49 56 51 59*/ \
+ __asm punpckhdq mm4,mm2 /*mm4=35 42 49 56 *I*/ \
+ OC_ZZ_LOAD_ROW_HI(3,mm2) /*mm2=31 30 29 28*/ \
+ __asm movq [Y+0x38],mm4 \
+ __asm punpcklwd mm3,mm1 /*mm3=61 51 60 59*/ \
+ __asm punpcklwd mm7,mm6 /*mm7=22 15 .. ??*/ \
+ __asm movq mm4,mm3 /*mm4=61 51 60 59*/ \
+ __asm punpcklwd mm3,mm0 /*mm3=53 60 52 59*/ \
+ __asm punpckhwd mm4,mm0 /*mm4=55 61 54 51*/ \
+ OC_ZZ_LOAD_ROW_HI(4,mm0) /*mm0=39 38 37 36*/ \
+ __asm pshufw mm3,mm3,0xE1 /*mm3=53 60 59 52 *J*/ \
+ __asm movq [Y+0x68],mm3 \
+ __asm movq mm3,mm4 /*mm3=?? ?? 54 51*/ \
+ __asm pshufw mm2,mm2,0x39 /*mm2=28 31 30 29*/ \
+ __asm punpckhwd mm4,mm1 /*mm4=63 55 62 61 *K*/ \
+ OC_ZZ_LOAD_ROW_HI(5,mm1) /*mm1=47 46 45 44*/ \
+ __asm movq [Y+0x78],mm4 \
+ __asm punpckhwd mm6,mm2 /*mm6=28 07 31 23*/ \
+ __asm punpcklwd mm2,mm0 /*mm2=37 30 36 29*/ \
+ __asm punpckhdq mm5,mm6 /*mm5=28 07 21 14*/ \
+ __asm pshufw mm2,mm2,0x4B /*mm2=36 29 30 37*/ \
+ __asm pshufw mm5,mm5,0x87 /*mm5=07 14 21 28 *L*/ \
+ __asm movq [Y+0x40],mm5 \
+ __asm punpckhdq mm7,mm2 /*mm7=36 29 22 15 *M*/ \
+ __asm movq [Y+0x48],mm7 \
+ __asm pshufw mm1,mm1,0x9C /*mm1=46 45 47 44*/ \
+ __asm punpckhwd mm0,mm1 /*mm0=46 39 45 38*/ \
+ __asm punpcklwd mm3,mm1 /*mm3=47 54 44 51*/ \
+ __asm punpckldq mm6,mm0 /*mm6=45 38 31 23 *N*/ \
+ __asm movq [Y+0x60],mm6 \
+ __asm punpckhdq mm0,mm3 /*mm0=47 54 46 39*/ \
+ __asm punpckldq mm3,mm2 /*mm3=30 37 44 51 *O*/ \
+ __asm movq [Y+0x58],mm3 \
+ __asm pshufw mm0,mm0,0xB1 /*mm0=54 47 39 46 *P*/ \
+ __asm movq [Y+0x70],mm0 \
+
+/*Converts DCT coefficients in %[dct] from natural order into zig-zag scan
+ order and stores them in %[qdct].
+ The index of each output element in the original 64-element array should wind
+ up in the following 8x8 matrix (the letters indicate the order we compute
+ each 4-tuple below):
+ A 0 1 8 16 9 2 3 10 B
+ C 17 24 32 25 18 11 4 5 D
+ E 12 19 26 33 40 48 41 34 I
+ H 27 20 13 6 7 14 21 28 G
+ K 35 42 49 56 57 50 43 36 J
+ F 29 22 15 23 30 37 44 51 M
+ P 58 59 52 45 38 31 39 46 L
+ N 53 60 61 54 47 55 62 63 O
+ The order of the coefficients within each tuple is reversed in the comments
+ below to reflect the usual MSB to LSB notation.*/
+#define OC_ZIG_ZAG_MMXEXT \
+ "movq 0x00(%[dct]),%%mm0\n\t" /*mm0=03 02 01 00*/ \
+ "movq 0x08(%[dct]),%%mm1\n\t" /*mm1=07 06 05 04*/ \
+ "movq 0x10(%[dct]),%%mm2\n\t" /*mm2=11 10 09 08*/ \
+ "movq 0x20(%[dct]),%%mm3\n\t" /*mm3=19 18 17 16*/ \
+ "movq 0x30(%[dct]),%%mm4\n\t" /*mm4=27 26 25 24*/ \
+ "movq 0x40(%[dct]),%%mm5\n\t" /*mm5=35 34 33 32*/ \
+ "movq %%mm2,%%mm7\n\t" /*mm7=11 10 09 08*/ \
+ "punpcklwd %%mm3,%%mm2\n\t" /*mm2=17 09 16 08*/ \
+ "movq %%mm0,%%mm6\n\t" /*mm6=03 02 01 00*/ \
+ "punpckldq %%mm2,%%mm0\n\t" /*mm0=16 08 01 00 *A*/ \
+ "movq %%mm0,0x00(%[qdct])\n\t" \
+ "movq 0x18(%[dct]),%%mm0\n\t" /*mm0=15 14 13 12*/ \
+ "punpckhdq %%mm6,%%mm6\n\t" /*mm6=03 02 03 02*/ \
+ "psrlq $16,%%mm7\n\t" /*mm7=.. 11 10 09*/ \
+ "punpckldq %%mm7,%%mm6\n\t" /*mm6=10 09 03 02*/ \
+ "punpckhwd %%mm7,%%mm3\n\t" /*mm3=.. 19 11 18*/ \
+ "pshufw $0xD2,%%mm6,%%mm6\n\t" /*mm6=10 03 02 09 *B*/ \
+ "movq %%mm6,0x08(%[qdct])\n\t" \
+ "psrlq $48,%%mm2\n\t" /*mm2=.. .. .. 17*/ \
+ "movq %%mm1,%%mm6\n\t" /*mm6=07 06 05 04*/ \
+ "punpcklwd %%mm5,%%mm2\n\t" /*mm2=33 .. 32 17*/ \
+ "movq %%mm3,%%mm7\n\t" /*mm7=.. 19 11 18*/ \
+ "punpckldq %%mm1,%%mm3\n\t" /*mm3=05 04 11 18 *C*/ \
+ "por %%mm2,%%mm7\n\t" /*mm7=33 19 ?? ??*/ \
+ "punpcklwd %%mm4,%%mm2\n\t" /*mm2=25 32 24 17 *D**/ \
+ "movq %%mm2,0x10(%[qdct])\n\t" \
+ "movq %%mm3,0x18(%[qdct])\n\t" \
+ "movq 0x28(%[dct]),%%mm2\n\t" /*mm2=23 22 21 20*/ \
+ "movq 0x38(%[dct]),%%mm1\n\t" /*mm1=31 30 29 28*/ \
+ "pshufw $0x9C,%%mm0,%%mm3\n\t" /*mm3=14 13 15 12*/ \
+ "punpckhdq %%mm7,%%mm7\n\t" /*mm7=33 19 33 19*/ \
+ "punpckhwd %%mm3,%%mm6\n\t" /*mm6=14 07 13 06*/ \
+ "punpckldq %%mm0,%%mm0\n\t" /*mm0=13 12 13 12*/ \
+ "punpcklwd %%mm1,%%mm3\n\t" /*mm3=29 15 28 12*/ \
+ "punpckhwd %%mm4,%%mm0\n\t" /*mm0=27 13 26 12*/ \
+ "pshufw $0xB4,%%mm3,%%mm3\n\t" /*mm3=15 29 28 12*/ \
+ "psrlq $48,%%mm4\n\t" /*mm4=.. .. .. 27*/ \
+ "punpcklwd %%mm7,%%mm0\n\t" /*mm0=33 26 19 12 *E*/ \
+ "punpcklwd %%mm1,%%mm4\n\t" /*mm4=29 .. 28 27*/ \
+ "punpckhwd %%mm2,%%mm3\n\t" /*mm3=23 15 22 29 *F*/ \
+ "movq %%mm0,0x20(%[qdct])\n\t" \
+ "movq %%mm3,0x50(%[qdct])\n\t" \
+ "movq 0x60(%[dct]),%%mm3\n\t" /*mm3=51 50 49 48*/ \
+ "movq 0x70(%[dct]),%%mm7\n\t" /*mm7=59 58 57 56*/ \
+ "movq 0x50(%[dct]),%%mm0\n\t" /*mm0=43 42 41 40*/ \
+ "punpcklwd %%mm4,%%mm2\n\t" /*mm2=28 21 27 20*/ \
+ "psrlq $32,%%mm5\n\t" /*mm5=.. .. 35 34*/ \
+ "movq %%mm2,%%mm4\n\t" /*mm4=28 21 27 20*/ \
+ "punpckldq %%mm6,%%mm2\n\t" /*mm2=13 06 27 20*/ \
+ "punpckhdq %%mm4,%%mm6\n\t" /*mm6=28 21 14 07 *G*/ \
+ "movq %%mm3,%%mm4\n\t" /*mm4=51 50 49 48*/ \
+ "pshufw $0xB1,%%mm2,%%mm2\n\t" /*mm2=06 13 20 27 *H*/ \
+ "movq %%mm2,0x30(%[qdct])\n\t" \
+ "movq %%mm6,0x38(%[qdct])\n\t" \
+ "movq 0x48(%[dct]),%%mm2\n\t" /*mm2=39 38 37 36*/ \
+ "punpcklwd %%mm5,%%mm4\n\t" /*mm4=35 49 34 48*/ \
+ "movq 0x58(%[dct]),%%mm5\n\t" /*mm5=47 46 45 44*/ \
+ "punpckldq %%mm7,%%mm6\n\t" /*mm6=57 56 14 07*/ \
+ "psrlq $32,%%mm3\n\t" /*mm3=.. .. 51 50*/ \
+ "punpckhwd %%mm0,%%mm6\n\t" /*mm6=43 57 42 56*/ \
+ "punpcklwd %%mm4,%%mm0\n\t" /*mm0=34 41 48 40 *I*/ \
+ "pshufw $0x4E,%%mm6,%%mm6\n\t" /*mm6=42 56 43 57*/ \
+ "movq %%mm0,0x28(%[qdct])\n\t" \
+ "punpcklwd %%mm2,%%mm3\n\t" /*mm3=37 51 36 50*/ \
+ "punpckhwd %%mm6,%%mm4\n\t" /*mm4=42 35 56 49*/ \
+ "punpcklwd %%mm3,%%mm6\n\t" /*mm6=36 43 50 57 *J*/ \
+ "pshufw $0x4E,%%mm4,%%mm4\n\t" /*mm4=56 49 42 35 *K*/ \
+ "movq %%mm4,0x40(%[qdct])\n\t" \
+ "movq %%mm6,0x48(%[qdct])\n\t" \
+ "movq 0x68(%[dct]),%%mm6\n\t" /*mm6=55 54 53 52*/ \
+ "movq 0x78(%[dct]),%%mm0\n\t" /*mm0=63 62 61 60*/ \
+ "psrlq $32,%%mm1\n\t" /*mm1=.. .. 31 30*/ \
+ "pshufw $0xD8,%%mm5,%%mm5\n\t" /*mm5=47 45 46 44*/ \
+ "pshufw $0x0B,%%mm3,%%mm3\n\t" /*mm3=50 50 51 37*/ \
+ "punpcklwd %%mm5,%%mm1\n\t" /*mm1=46 31 44 30*/ \
+ "pshufw $0xC9,%%mm6,%%mm6\n\t" /*mm6=55 52 54 53*/ \
+ "punpckhwd %%mm1,%%mm2\n\t" /*mm2=46 39 31 38 *L*/ \
+ "punpcklwd %%mm3,%%mm1\n\t" /*mm1=51 44 37 30 *M*/ \
+ "movq %%mm2,0x68(%[qdct])\n\t" \
+ "movq %%mm1,0x58(%[qdct])\n\t" \
+ "punpckhwd %%mm6,%%mm5\n\t" /*mm5=55 47 52 45*/ \
+ "punpckldq %%mm0,%%mm6\n\t" /*mm6=61 60 54 53*/ \
+ "pshufw $0x10,%%mm5,%%mm4\n\t" /*mm4=45 52 45 45*/ \
+ "pshufw $0x78,%%mm6,%%mm6\n\t" /*mm6=53 60 61 54 *N*/ \
+ "punpckhdq %%mm0,%%mm5\n\t" /*mm5=63 62 55 47 *O*/ \
+ "punpckhdq %%mm4,%%mm7\n\t" /*mm7=45 52 59 58 *P*/ \
+ "movq %%mm6,0x70(%[qdct])\n\t" \
+ "movq %%mm5,0x78(%[qdct])\n\t" \
+ "movq %%mm7,0x60(%[qdct])\n\t" \
+
+#endif
diff --git a/thirdparty/mbedtls/include/mbedtls/asn1write.h b/thirdparty/mbedtls/include/mbedtls/asn1write.h
index 44afae0e56..5da7654bb4 100644
--- a/thirdparty/mbedtls/include/mbedtls/asn1write.h
+++ b/thirdparty/mbedtls/include/mbedtls/asn1write.h
@@ -90,7 +90,7 @@ int mbedtls_asn1_write_raw_buffer( unsigned char **p, unsigned char *start,
#if defined(MBEDTLS_BIGNUM_C)
/**
- * \brief Write a arbitrary-precision number (#MBEDTLS_ASN1_INTEGER)
+ * \brief Write an arbitrary-precision number (#MBEDTLS_ASN1_INTEGER)
* in ASN.1 format.
*
* \note This function works backwards in data buffer.
diff --git a/thirdparty/mbedtls/include/mbedtls/bignum.h b/thirdparty/mbedtls/include/mbedtls/bignum.h
index dd594c512d..c61db82c6d 100644
--- a/thirdparty/mbedtls/include/mbedtls/bignum.h
+++ b/thirdparty/mbedtls/include/mbedtls/bignum.h
@@ -182,6 +182,20 @@
#endif /* !MBEDTLS_NO_UDBL_DIVISION */
#endif /* !MBEDTLS_HAVE_INT64 */
+/** \typedef mbedtls_mpi_uint
+ * \brief The type of machine digits in a bignum, called _limbs_.
+ *
+ * This is always an unsigned integer type with no padding bits. The size
+ * is platform-dependent.
+ */
+
+/** \typedef mbedtls_mpi_sint
+ * \brief The signed type corresponding to #mbedtls_mpi_uint.
+ *
+ * This is always a signed integer type with no padding bits. The size
+ * is platform-dependent.
+ */
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -191,9 +205,27 @@ extern "C" {
*/
typedef struct mbedtls_mpi
{
- int s; /*!< Sign: -1 if the mpi is negative, 1 otherwise */
- size_t n; /*!< total # of limbs */
- mbedtls_mpi_uint *p; /*!< pointer to limbs */
+ /** Sign: -1 if the mpi is negative, 1 otherwise.
+ *
+ * The number 0 must be represented with `s = +1`. Although many library
+ * functions treat all-limbs-zero as equivalent to a valid representation
+ * of 0 regardless of the sign bit, there are exceptions, so bignum
+ * functions and external callers must always set \c s to +1 for the
+ * number zero.
+ *
+ * Note that this implies that calloc() or `... = {0}` does not create
+ * a valid MPI representation. You must call mbedtls_mpi_init().
+ */
+ int s;
+
+ /** Total number of limbs in \c p. */
+ size_t n;
+
+ /** Pointer to limbs.
+ *
+ * This may be \c NULL if \c n is 0.
+ */
+ mbedtls_mpi_uint *p;
}
mbedtls_mpi;
@@ -280,7 +312,7 @@ void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y );
* \param Y The MPI to be assigned from. This must point to an
* initialized MPI.
* \param assign The condition deciding whether to perform the
- * assignment or not. Possible values:
+ * assignment or not. Must be either 0 or 1:
* * \c 1: Perform the assignment `X = Y`.
* * \c 0: Keep the original value of \p X.
*
@@ -291,6 +323,10 @@ void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y );
* information through branch prediction and/or memory access
* patterns analysis).
*
+ * \warning If \p assign is neither 0 nor 1, the result of this function
+ * is indeterminate, and the resulting value in \p X might be
+ * neither its original value nor the value in \p Y.
+ *
* \return \c 0 if successful.
* \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed.
* \return Another negative error code on other kinds of failure.
@@ -303,24 +339,28 @@ int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned
*
* \param X The first MPI. This must be initialized.
* \param Y The second MPI. This must be initialized.
- * \param assign The condition deciding whether to perform
- * the swap or not. Possible values:
+ * \param swap The condition deciding whether to perform
+ * the swap or not. Must be either 0 or 1:
* * \c 1: Swap the values of \p X and \p Y.
* * \c 0: Keep the original values of \p X and \p Y.
*
* \note This function is equivalent to
- * if( assign ) mbedtls_mpi_swap( X, Y );
+ * if( swap ) mbedtls_mpi_swap( X, Y );
* except that it avoids leaking any information about whether
- * the assignment was done or not (the above code may leak
+ * the swap was done or not (the above code may leak
* information through branch prediction and/or memory access
* patterns analysis).
*
+ * \warning If \p swap is neither 0 nor 1, the result of this function
+ * is indeterminate, and both \p X and \p Y might end up with
+ * values different to either of the original ones.
+ *
* \return \c 0 if successful.
* \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed.
* \return Another negative error code on other kinds of failure.
*
*/
-int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char assign );
+int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char swap );
/**
* \brief Store integer value in MPI.
@@ -753,11 +793,11 @@ int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A,
*
* \param Q The destination MPI for the quotient.
* This may be \c NULL if the value of the
- * quotient is not needed.
+ * quotient is not needed. This must not alias A or B.
* \param R The destination MPI for the remainder value.
* This may be \c NULL if the value of the
- * remainder is not needed.
- * \param A The dividend. This must point to an initialized MPi.
+ * remainder is not needed. This must not alias A or B.
+ * \param A The dividend. This must point to an initialized MPI.
* \param B The divisor. This must point to an initialized MPI.
*
* \return \c 0 if successful.
@@ -774,10 +814,10 @@ int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A,
*
* \param Q The destination MPI for the quotient.
* This may be \c NULL if the value of the
- * quotient is not needed.
+ * quotient is not needed. This must not alias A.
* \param R The destination MPI for the remainder value.
* This may be \c NULL if the value of the
- * remainder is not needed.
+ * remainder is not needed. This must not alias A.
* \param A The dividend. This must point to an initialized MPi.
* \param b The divisor.
*
@@ -832,6 +872,7 @@ int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A,
* \brief Perform a sliding-window exponentiation: X = A^E mod N
*
* \param X The destination MPI. This must point to an initialized MPI.
+ * This must not alias E or N.
* \param A The base of the exponentiation.
* This must point to an initialized MPI.
* \param E The exponent MPI. This must point to an initialized MPI.
diff --git a/thirdparty/mbedtls/include/mbedtls/bn_mul.h b/thirdparty/mbedtls/include/mbedtls/bn_mul.h
index 31137cd4c2..a3fc363815 100644
--- a/thirdparty/mbedtls/include/mbedtls/bn_mul.h
+++ b/thirdparty/mbedtls/include/mbedtls/bn_mul.h
@@ -95,12 +95,28 @@
( !defined(__ARMCC_VERSION) || __ARMCC_VERSION >= 6000000 )
/*
+ * GCC < 5.0 treated the x86 ebx (which is used for the GOT) as a
+ * fixed reserved register when building as PIC, leading to errors
+ * like: bn_mul.h:46:13: error: PIC register clobbered by 'ebx' in 'asm'
+ *
+ * This is fixed by an improved register allocator in GCC 5+. From the
+ * release notes:
+ * Register allocation improvements: Reuse of the PIC hard register,
+ * instead of using a fixed register, was implemented on x86/x86-64
+ * targets. This improves generated PIC code performance as more hard
+ * registers can be used.
+ */
+#if defined(__GNUC__) && __GNUC__ < 5 && defined(__PIC__)
+#define MULADDC_CANNOT_USE_EBX
+#endif
+
+/*
* Disable use of the i386 assembly code below if option -O0, to disable all
* compiler optimisations, is passed, detected with __OPTIMIZE__
* This is done as the number of registers used in the assembly code doesn't
* work with the -O0 option.
*/
-#if defined(__i386__) && defined(__OPTIMIZE__)
+#if defined(__i386__) && defined(__OPTIMIZE__) && !defined(MULADDC_CANNOT_USE_EBX)
#define MULADDC_INIT \
asm( \
@@ -563,10 +579,20 @@
"andi r7, r6, 0xffff \n\t" \
"bsrli r6, r6, 16 \n\t"
-#define MULADDC_CORE \
+#if(__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
+#define MULADDC_LHUI \
+ "lhui r9, r3, 0 \n\t" \
+ "addi r3, r3, 2 \n\t" \
+ "lhui r8, r3, 0 \n\t"
+#else
+#define MULADDC_LHUI \
"lhui r8, r3, 0 \n\t" \
"addi r3, r3, 2 \n\t" \
- "lhui r9, r3, 0 \n\t" \
+ "lhui r9, r3, 0 \n\t"
+#endif
+
+#define MULADDC_CORE \
+ MULADDC_LHUI \
"addi r3, r3, 2 \n\t" \
"mul r10, r9, r6 \n\t" \
"mul r11, r8, r7 \n\t" \
diff --git a/thirdparty/mbedtls/include/mbedtls/check_config.h b/thirdparty/mbedtls/include/mbedtls/check_config.h
index be5c548e56..7ae1ff94db 100644
--- a/thirdparty/mbedtls/include/mbedtls/check_config.h
+++ b/thirdparty/mbedtls/include/mbedtls/check_config.h
@@ -525,6 +525,20 @@
#error "MBEDTLS_PLATFORM_SNPRINTF_MACRO and MBEDTLS_PLATFORM_STD_SNPRINTF/MBEDTLS_PLATFORM_SNPRINTF_ALT cannot be defined simultaneously"
#endif
+#if defined(MBEDTLS_PLATFORM_VSNPRINTF_ALT) && !defined(MBEDTLS_PLATFORM_C)
+#error "MBEDTLS_PLATFORM_VSNPRINTF_ALT defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDTLS_PLATFORM_VSNPRINTF_MACRO) && !defined(MBEDTLS_PLATFORM_C)
+#error "MBEDTLS_PLATFORM_VSNPRINTF_MACRO defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDTLS_PLATFORM_VSNPRINTF_MACRO) &&\
+ ( defined(MBEDTLS_PLATFORM_STD_VSNPRINTF) ||\
+ defined(MBEDTLS_PLATFORM_VSNPRINTF_ALT) )
+#error "MBEDTLS_PLATFORM_VSNPRINTF_MACRO and MBEDTLS_PLATFORM_STD_VSNPRINTF/MBEDTLS_PLATFORM_VSNPRINTF_ALT cannot be defined simultaneously"
+#endif
+
#if defined(MBEDTLS_PLATFORM_STD_MEM_HDR) &&\
!defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS)
#error "MBEDTLS_PLATFORM_STD_MEM_HDR defined, but not all prerequisites"
@@ -650,10 +664,9 @@
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"
+#if defined(MBEDTLS_PSA_CRYPTO_C) && defined(MBEDTLS_RSA_C) && \
+ !( defined(MBEDTLS_PK_PARSE_C) && defined(MBEDTLS_PK_WRITE_C) )
+#error "MBEDTLS_PSA_CRYPTO_C with MBEDTLS_RSA_C requires MBEDTLS_PK_PARSE_C and MBEDTLS_PK_WRITE_C"
#endif
#if defined(MBEDTLS_RSA_C) && ( !defined(MBEDTLS_BIGNUM_C) || \
@@ -812,6 +825,11 @@
#error "MBEDTLS_SSL_TICKET_C defined, but not all prerequisites"
#endif
+#if defined(MBEDTLS_SSL_TICKET_C) && \
+ !( defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CCM_C) || defined(MBEDTLS_CHACHAPOLY_C) )
+#error "MBEDTLS_SSL_TICKET_C defined, but not all prerequisites"
+#endif
+
#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) && \
!defined(MBEDTLS_SSL_PROTO_SSL3) && !defined(MBEDTLS_SSL_PROTO_TLS1)
#error "MBEDTLS_SSL_CBC_RECORD_SPLITTING defined, but not all prerequisites"
@@ -926,6 +944,10 @@
#error "MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH defined, but not all prerequisites"
#endif
+#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) && !( defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CCM_C) || defined(MBEDTLS_CHACHAPOLY_C) )
+#error "MBEDTLS_SSL_CONTEXT_SERIALIZATION defined, but not all prerequisites"
+#endif
+
/*
* Avoid warning from -pedantic. This is a convenient place for this
* workaround since this is included by every single file before the
diff --git a/thirdparty/mbedtls/include/mbedtls/config.h b/thirdparty/mbedtls/include/mbedtls/config.h
index 1cd6eb6634..61db79362f 100644
--- a/thirdparty/mbedtls/include/mbedtls/config.h
+++ b/thirdparty/mbedtls/include/mbedtls/config.h
@@ -1329,7 +1329,7 @@
* Include backtrace information with each allocated block.
*
* Requires: MBEDTLS_MEMORY_BUFFER_ALLOC_C
- * GLIBC-compatible backtrace() an backtrace_symbols() support
+ * GLIBC-compatible backtrace() and backtrace_symbols() support
*
* Uncomment this macro to include backtrace information
*/
@@ -1620,6 +1620,8 @@
* saved after the handshake to allow for more efficient serialization, so if
* you don't need this feature you'll save RAM by disabling it.
*
+ * Requires: MBEDTLS_GCM_C or MBEDTLS_CCM_C or MBEDTLS_CHACHAPOLY_C
+ *
* Comment to disable the context serialization APIs.
*/
#define MBEDTLS_SSL_CONTEXT_SERIALIZATION
@@ -2425,7 +2427,7 @@
* MBEDTLS_TLS_PSK_WITH_RC4_128_SHA
*
* \warning ARC4 is considered a weak cipher and its use constitutes a
- * security risk. If possible, we recommend avoidng dependencies on
+ * security risk. If possible, we recommend avoiding dependencies on
* it, and considering stronger ciphers instead.
*
*/
@@ -3030,7 +3032,7 @@
*
* \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
+ * https://mbed-tls.readthedocs.io/en/latest/kb/how-to/how-do-i-port-mbed-tls-to-a-new-environment-OS
*
* Module: library/net_sockets.c
*
@@ -3400,7 +3402,8 @@
* Module: library/ssl_ticket.c
* Caller:
*
- * Requires: MBEDTLS_CIPHER_C
+ * Requires: MBEDTLS_CIPHER_C &&
+ * ( MBEDTLS_GCM_C || MBEDTLS_CCM_C || MBEDTLS_CHACHAPOLY_C )
*/
#define MBEDTLS_SSL_TICKET_C
@@ -3456,7 +3459,7 @@
* contexts are not shared between threads. If you do intend to use contexts
* between threads, you will need to enable this layer to prevent race
* conditions. See also our Knowledge Base article about threading:
- * https://tls.mbed.org/kb/development/thread-safety-and-multi-threading
+ * https://mbed-tls.readthedocs.io/en/latest/kb/development/thread-safety-and-multi-threading
*
* Module: library/threading.c
*
@@ -3488,7 +3491,7 @@
*
* \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
+ * https://mbed-tls.readthedocs.io/en/latest/kb/how-to/how-do-i-port-mbed-tls-to-a-new-environment-OS
*
* Module: library/timing.c
* Caller: library/havege.c
diff --git a/thirdparty/mbedtls/include/mbedtls/ecdsa.h b/thirdparty/mbedtls/include/mbedtls/ecdsa.h
index 264a638bb5..118f7cedb1 100644
--- a/thirdparty/mbedtls/include/mbedtls/ecdsa.h
+++ b/thirdparty/mbedtls/include/mbedtls/ecdsa.h
@@ -309,10 +309,8 @@ int mbedtls_ecdsa_sign_det_ext( mbedtls_ecp_group *grp, mbedtls_mpi *r,
* This must be initialized.
*
* \return \c 0 on success.
- * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if the signature
- * is invalid.
* \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX
- * error code on failure for any other reason.
+ * error code on failure.
*/
int mbedtls_ecdsa_verify( mbedtls_ecp_group *grp,
const unsigned char *buf, size_t blen,
diff --git a/thirdparty/mbedtls/include/mbedtls/md.h b/thirdparty/mbedtls/include/mbedtls/md.h
index 84fafd2ac7..9cea40a89c 100644
--- a/thirdparty/mbedtls/include/mbedtls/md.h
+++ b/thirdparty/mbedtls/include/mbedtls/md.h
@@ -215,7 +215,7 @@ MBEDTLS_CHECK_RETURN_TYPICAL
int mbedtls_md_setup( mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info, int hmac );
/**
- * \brief This function clones the state of an message-digest
+ * \brief This function clones the state of a message-digest
* context.
*
* \note You must call mbedtls_md_setup() on \c dst before calling
diff --git a/thirdparty/mbedtls/include/mbedtls/platform.h b/thirdparty/mbedtls/include/mbedtls/platform.h
index 06dd192eab..eaf5122bec 100644
--- a/thirdparty/mbedtls/include/mbedtls/platform.h
+++ b/thirdparty/mbedtls/include/mbedtls/platform.h
@@ -11,6 +11,13 @@
* implementations of these functions, or implementations specific to
* their platform, which can be statically linked to the library or
* dynamically configured at runtime.
+ *
+ * When all compilation options related to platform abstraction are
+ * disabled, this header just defines `mbedtls_xxx` function names
+ * as aliases to the standard `xxx` function.
+ *
+ * Most modules in the library and example programs are expected to
+ * include this header.
*/
/*
* Copyright The Mbed TLS Contributors
diff --git a/thirdparty/mbedtls/include/mbedtls/ripemd160.h b/thirdparty/mbedtls/include/mbedtls/ripemd160.h
index 63270d1239..f890aefaee 100644
--- a/thirdparty/mbedtls/include/mbedtls/ripemd160.h
+++ b/thirdparty/mbedtls/include/mbedtls/ripemd160.h
@@ -74,7 +74,7 @@ void mbedtls_ripemd160_init( mbedtls_ripemd160_context *ctx );
void mbedtls_ripemd160_free( mbedtls_ripemd160_context *ctx );
/**
- * \brief Clone (the state of) an RIPEMD-160 context
+ * \brief Clone (the state of) a RIPEMD-160 context
*
* \param dst The destination context
* \param src The context to be cloned
diff --git a/thirdparty/mbedtls/include/mbedtls/rsa.h b/thirdparty/mbedtls/include/mbedtls/rsa.h
index 062df73aa0..8559f67bb9 100644
--- a/thirdparty/mbedtls/include/mbedtls/rsa.h
+++ b/thirdparty/mbedtls/include/mbedtls/rsa.h
@@ -491,7 +491,7 @@ int mbedtls_rsa_check_pubkey( const mbedtls_rsa_context *ctx );
* the current function does not have access to them,
* and therefore cannot check them. See mbedtls_rsa_complete().
* If you want to check the consistency of the entire
- * content of an PKCS1-encoded RSA private key, for example, you
+ * content of a PKCS1-encoded RSA private key, for example, you
* should use mbedtls_rsa_validate_params() before setting
* up the RSA context.
* Additionally, if the implementation performs empirical checks,
diff --git a/thirdparty/mbedtls/include/mbedtls/ssl.h b/thirdparty/mbedtls/include/mbedtls/ssl.h
index 5064ec5689..aecac93f33 100644
--- a/thirdparty/mbedtls/include/mbedtls/ssl.h
+++ b/thirdparty/mbedtls/include/mbedtls/ssl.h
@@ -624,7 +624,7 @@ typedef int mbedtls_ssl_recv_t( void *ctx,
* \param ctx Context for the receive callback (typically a file descriptor)
* \param buf Buffer to write the received data to
* \param len Length of the receive buffer
- * \param timeout Maximum nomber of millisecondes to wait for data
+ * \param timeout Maximum number of milliseconds to wait for data
* 0 means no timeout (potentially waiting forever)
*
* \return The callback must return the number of bytes received,
@@ -652,7 +652,7 @@ typedef int mbedtls_ssl_recv_timeout_t( void *ctx,
* for the associated \c mbedtls_ssl_get_timer_t callback to
* return correct information.
*
- * \note If using a event-driven style of programming, an event must
+ * \note If using an event-driven style of programming, an event must
* be generated when the final delay is passed. The event must
* cause a call to \c mbedtls_ssl_handshake() with the proper
* SSL context to be scheduled. Care must be taken to ensure
@@ -2000,7 +2000,7 @@ int mbedtls_ssl_check_record( mbedtls_ssl_context const *ssl,
* here, except if using an event-driven style.
*
* \note See also the "DTLS tutorial" article in our knowledge base.
- * https://tls.mbed.org/kb/how-to/dtls-tutorial
+ * https://mbed-tls.readthedocs.io/en/latest/kb/how-to/dtls-tutorial
*/
void mbedtls_ssl_set_timer_cb( mbedtls_ssl_context *ssl,
void *p_timer,
diff --git a/thirdparty/mbedtls/include/mbedtls/ssl_internal.h b/thirdparty/mbedtls/include/mbedtls/ssl_internal.h
index 46ade67b9c..77ad755477 100644
--- a/thirdparty/mbedtls/include/mbedtls/ssl_internal.h
+++ b/thirdparty/mbedtls/include/mbedtls/ssl_internal.h
@@ -782,7 +782,7 @@ struct mbedtls_ssl_transform
#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
uint8_t in_cid_len;
uint8_t out_cid_len;
- unsigned char in_cid [ MBEDTLS_SSL_CID_OUT_LEN_MAX ];
+ unsigned char in_cid [ MBEDTLS_SSL_CID_IN_LEN_MAX ];
unsigned char out_cid[ MBEDTLS_SSL_CID_OUT_LEN_MAX ];
#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
diff --git a/thirdparty/mbedtls/include/mbedtls/version.h b/thirdparty/mbedtls/include/mbedtls/version.h
index 44adcbfe03..b3b441d46b 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 1
+#define MBEDTLS_VERSION_PATCH 2
/**
* The single version number has the following structure:
* MMNNPP00
* Major version | Minor version | Patch version
*/
-#define MBEDTLS_VERSION_NUMBER 0x021C0100
-#define MBEDTLS_VERSION_STRING "2.28.1"
-#define MBEDTLS_VERSION_STRING_FULL "mbed TLS 2.28.1"
+#define MBEDTLS_VERSION_NUMBER 0x021C0200
+#define MBEDTLS_VERSION_STRING "2.28.2"
+#define MBEDTLS_VERSION_STRING_FULL "mbed TLS 2.28.2"
#if defined(MBEDTLS_VERSION_C)
diff --git a/thirdparty/mbedtls/library/aes.c b/thirdparty/mbedtls/library/aes.c
index 03d8b7ea61..74ea2672b0 100644
--- a/thirdparty/mbedtls/library/aes.c
+++ b/thirdparty/mbedtls/library/aes.c
@@ -40,14 +40,7 @@
#include "mbedtls/aesni.h"
#endif
-#if defined(MBEDTLS_SELF_TEST)
-#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
-#else
-#include <stdio.h>
-#define mbedtls_printf printf
-#endif /* MBEDTLS_PLATFORM_C */
-#endif /* MBEDTLS_SELF_TEST */
#if !defined(MBEDTLS_AES_ALT)
@@ -1170,7 +1163,7 @@ int mbedtls_aes_crypt_xts( mbedtls_aes_xts_context *ctx,
{
/* We are on the last block in a decrypt operation that has
* leftover bytes, so we need to use the next tweak for this block,
- * and this tweak for the lefover bytes. Save the current tweak for
+ * and this tweak for the leftover bytes. Save the current tweak for
* the leftovers and then update the current tweak for use on this,
* the last full block. */
memcpy( prev_tweak, tweak, sizeof( tweak ) );
@@ -1770,7 +1763,8 @@ int mbedtls_aes_self_test( int verbose )
unsigned char key[32];
unsigned char buf[64];
const unsigned char *aes_tests;
-#if defined(MBEDTLS_CIPHER_MODE_CBC) || defined(MBEDTLS_CIPHER_MODE_CFB)
+#if defined(MBEDTLS_CIPHER_MODE_CBC) || defined(MBEDTLS_CIPHER_MODE_CFB) || \
+ defined(MBEDTLS_CIPHER_MODE_OFB)
unsigned char iv[16];
#endif
#if defined(MBEDTLS_CIPHER_MODE_CBC)
diff --git a/thirdparty/mbedtls/library/arc4.c b/thirdparty/mbedtls/library/arc4.c
index b34dc5e754..dcc13d539a 100644
--- a/thirdparty/mbedtls/library/arc4.c
+++ b/thirdparty/mbedtls/library/arc4.c
@@ -31,14 +31,7 @@
#include <string.h>
-#if defined(MBEDTLS_SELF_TEST)
-#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
-#else
-#include <stdio.h>
-#define mbedtls_printf printf
-#endif /* MBEDTLS_PLATFORM_C */
-#endif /* MBEDTLS_SELF_TEST */
#if !defined(MBEDTLS_ARC4_ALT)
diff --git a/thirdparty/mbedtls/library/aria.c b/thirdparty/mbedtls/library/aria.c
index bc05c4a319..5e52eea91e 100644
--- a/thirdparty/mbedtls/library/aria.c
+++ b/thirdparty/mbedtls/library/aria.c
@@ -31,24 +31,12 @@
#include <string.h>
-#if defined(MBEDTLS_SELF_TEST)
-#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
-#else
-#include <stdio.h>
-#define mbedtls_printf printf
-#endif /* MBEDTLS_PLATFORM_C */
-#endif /* MBEDTLS_SELF_TEST */
#if !defined(MBEDTLS_ARIA_ALT)
#include "mbedtls/platform_util.h"
-#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
- !defined(inline) && !defined(__cplusplus)
-#define inline __inline
-#endif
-
/* Parameter validation macros */
#define ARIA_VALIDATE_RET( cond ) \
MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ARIA_BAD_INPUT_DATA )
@@ -895,15 +883,17 @@ static const uint8_t aria_test2_ctr_ct[3][48] = // CTR ciphertext
};
#endif /* MBEDTLS_CIPHER_MODE_CFB */
-#define ARIA_SELF_TEST_IF_FAIL \
- { \
- if( verbose ) \
- mbedtls_printf( "failed\n" ); \
- goto exit; \
- } else { \
- if( verbose ) \
- mbedtls_printf( "passed\n" ); \
- }
+#define ARIA_SELF_TEST_ASSERT( cond ) \
+ do { \
+ if( cond ) { \
+ if( verbose ) \
+ mbedtls_printf( "failed\n" ); \
+ goto exit; \
+ } else { \
+ if( verbose ) \
+ mbedtls_printf( "passed\n" ); \
+ } \
+ } while( 0 )
/*
* Checkup routine
@@ -937,16 +927,18 @@ int mbedtls_aria_self_test( int verbose )
mbedtls_printf( " ARIA-ECB-%d (enc): ", 128 + 64 * i );
mbedtls_aria_setkey_enc( &ctx, aria_test1_ecb_key, 128 + 64 * i );
mbedtls_aria_crypt_ecb( &ctx, aria_test1_ecb_pt, blk );
- if( memcmp( blk, aria_test1_ecb_ct[i], MBEDTLS_ARIA_BLOCKSIZE ) != 0 )
- ARIA_SELF_TEST_IF_FAIL;
+ ARIA_SELF_TEST_ASSERT(
+ memcmp( blk, aria_test1_ecb_ct[i], MBEDTLS_ARIA_BLOCKSIZE )
+ != 0 );
/* test ECB decryption */
if( verbose )
mbedtls_printf( " ARIA-ECB-%d (dec): ", 128 + 64 * i );
mbedtls_aria_setkey_dec( &ctx, aria_test1_ecb_key, 128 + 64 * i );
mbedtls_aria_crypt_ecb( &ctx, aria_test1_ecb_ct[i], blk );
- if( memcmp( blk, aria_test1_ecb_pt, MBEDTLS_ARIA_BLOCKSIZE ) != 0 )
- ARIA_SELF_TEST_IF_FAIL;
+ ARIA_SELF_TEST_ASSERT(
+ memcmp( blk, aria_test1_ecb_pt, MBEDTLS_ARIA_BLOCKSIZE )
+ != 0 );
}
if( verbose )
mbedtls_printf( "\n" );
@@ -965,8 +957,8 @@ int mbedtls_aria_self_test( int verbose )
memset( buf, 0x55, sizeof( buf ) );
mbedtls_aria_crypt_cbc( &ctx, MBEDTLS_ARIA_ENCRYPT, 48, iv,
aria_test2_pt, buf );
- if( memcmp( buf, aria_test2_cbc_ct[i], 48 ) != 0 )
- ARIA_SELF_TEST_IF_FAIL;
+ ARIA_SELF_TEST_ASSERT( memcmp( buf, aria_test2_cbc_ct[i], 48 )
+ != 0 );
/* Test CBC decryption */
if( verbose )
@@ -976,8 +968,7 @@ int mbedtls_aria_self_test( int verbose )
memset( buf, 0xAA, sizeof( buf ) );
mbedtls_aria_crypt_cbc( &ctx, MBEDTLS_ARIA_DECRYPT, 48, iv,
aria_test2_cbc_ct[i], buf );
- if( memcmp( buf, aria_test2_pt, 48 ) != 0 )
- ARIA_SELF_TEST_IF_FAIL;
+ ARIA_SELF_TEST_ASSERT( memcmp( buf, aria_test2_pt, 48 ) != 0 );
}
if( verbose )
mbedtls_printf( "\n" );
@@ -996,8 +987,7 @@ int mbedtls_aria_self_test( int verbose )
j = 0;
mbedtls_aria_crypt_cfb128( &ctx, MBEDTLS_ARIA_ENCRYPT, 48, &j, iv,
aria_test2_pt, buf );
- if( memcmp( buf, aria_test2_cfb_ct[i], 48 ) != 0 )
- ARIA_SELF_TEST_IF_FAIL;
+ ARIA_SELF_TEST_ASSERT( memcmp( buf, aria_test2_cfb_ct[i], 48 ) != 0 );
/* Test CFB decryption */
if( verbose )
@@ -1008,8 +998,7 @@ int mbedtls_aria_self_test( int verbose )
j = 0;
mbedtls_aria_crypt_cfb128( &ctx, MBEDTLS_ARIA_DECRYPT, 48, &j,
iv, aria_test2_cfb_ct[i], buf );
- if( memcmp( buf, aria_test2_pt, 48 ) != 0 )
- ARIA_SELF_TEST_IF_FAIL;
+ ARIA_SELF_TEST_ASSERT( memcmp( buf, aria_test2_pt, 48 ) != 0 );
}
if( verbose )
mbedtls_printf( "\n" );
@@ -1027,8 +1016,7 @@ int mbedtls_aria_self_test( int verbose )
j = 0;
mbedtls_aria_crypt_ctr( &ctx, 48, &j, iv, blk,
aria_test2_pt, buf );
- if( memcmp( buf, aria_test2_ctr_ct[i], 48 ) != 0 )
- ARIA_SELF_TEST_IF_FAIL;
+ ARIA_SELF_TEST_ASSERT( memcmp( buf, aria_test2_ctr_ct[i], 48 ) != 0 );
/* Test CTR decryption */
if( verbose )
@@ -1039,8 +1027,7 @@ int mbedtls_aria_self_test( int verbose )
j = 0;
mbedtls_aria_crypt_ctr( &ctx, 48, &j, iv, blk,
aria_test2_ctr_ct[i], buf );
- if( memcmp( buf, aria_test2_pt, 48 ) != 0 )
- ARIA_SELF_TEST_IF_FAIL;
+ ARIA_SELF_TEST_ASSERT( memcmp( buf, aria_test2_pt, 48 ) != 0 );
}
if( verbose )
mbedtls_printf( "\n" );
diff --git a/thirdparty/mbedtls/library/asn1parse.c b/thirdparty/mbedtls/library/asn1parse.c
index 22747d3ba4..bf97585289 100644
--- a/thirdparty/mbedtls/library/asn1parse.c
+++ b/thirdparty/mbedtls/library/asn1parse.c
@@ -31,13 +31,7 @@
#include "mbedtls/bignum.h"
#endif
-#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
-#else
-#include <stdlib.h>
-#define mbedtls_calloc calloc
-#define mbedtls_free free
-#endif
/*
* ASN.1 DER decoding routines
diff --git a/thirdparty/mbedtls/library/asn1write.c b/thirdparty/mbedtls/library/asn1write.c
index afa26a6be9..4b59927cbb 100644
--- a/thirdparty/mbedtls/library/asn1write.c
+++ b/thirdparty/mbedtls/library/asn1write.c
@@ -26,13 +26,7 @@
#include <string.h>
-#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
-#else
-#include <stdlib.h>
-#define mbedtls_calloc calloc
-#define mbedtls_free free
-#endif
int mbedtls_asn1_write_len( unsigned char **p, unsigned char *start, size_t len )
{
@@ -78,9 +72,11 @@ int mbedtls_asn1_write_len( unsigned char **p, unsigned char *start, size_t len
return( 4 );
}
+ int len_is_valid = 1;
#if SIZE_MAX > 0xFFFFFFFF
- if( len <= 0xFFFFFFFF )
+ len_is_valid = ( len <= 0xFFFFFFFF );
#endif
+ if( len_is_valid )
{
if( *p - start < 5 )
return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
@@ -93,9 +89,7 @@ int mbedtls_asn1_write_len( unsigned char **p, unsigned char *start, size_t len
return( 5 );
}
-#if SIZE_MAX > 0xFFFFFFFF
return( MBEDTLS_ERR_ASN1_INVALID_LENGTH );
-#endif
}
int mbedtls_asn1_write_tag( unsigned char **p, unsigned char *start, unsigned char tag )
diff --git a/thirdparty/mbedtls/library/base64.c b/thirdparty/mbedtls/library/base64.c
index 83daa0bcc6..9021a041bb 100644
--- a/thirdparty/mbedtls/library/base64.c
+++ b/thirdparty/mbedtls/library/base64.c
@@ -28,12 +28,7 @@
#if defined(MBEDTLS_SELF_TEST)
#include <string.h>
-#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
-#else
-#include <stdio.h>
-#define mbedtls_printf printf
-#endif /* MBEDTLS_PLATFORM_C */
#endif /* MBEDTLS_SELF_TEST */
#define BASE64_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
diff --git a/thirdparty/mbedtls/library/bignum.c b/thirdparty/mbedtls/library/bignum.c
index 32578e2c68..37193f55a8 100644
--- a/thirdparty/mbedtls/library/bignum.c
+++ b/thirdparty/mbedtls/library/bignum.c
@@ -46,15 +46,7 @@
#include <limits.h>
#include <string.h>
-#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
-#else
-#include <stdio.h>
-#include <stdlib.h>
-#define mbedtls_printf printf
-#define mbedtls_calloc calloc
-#define mbedtls_free free
-#endif
#define MPI_VALIDATE_RET( cond ) \
MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_MPI_BAD_INPUT_DATA )
@@ -270,6 +262,17 @@ void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y )
memcpy( Y, &T, sizeof( mbedtls_mpi ) );
}
+static inline mbedtls_mpi_uint mpi_sint_abs( mbedtls_mpi_sint z )
+{
+ if( z >= 0 )
+ return( z );
+ /* Take care to handle the most negative value (-2^(biL-1)) correctly.
+ * A naive -z would have undefined behavior.
+ * Write this in a way that makes popular compilers happy (GCC, Clang,
+ * MSVC). */
+ return( (mbedtls_mpi_uint) 0 - (mbedtls_mpi_uint) z );
+}
+
/*
* Set value from integer
*/
@@ -281,7 +284,7 @@ int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z )
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) );
memset( X->p, 0, X->n * ciL );
- X->p[0] = ( z < 0 ) ? -z : z;
+ X->p[0] = mpi_sint_abs( z );
X->s = ( z < 0 ) ? -1 : 1;
cleanup:
@@ -1101,7 +1104,7 @@ int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
mbedtls_mpi_uint p[1];
MPI_VALIDATE_RET( X != NULL );
- *p = ( z < 0 ) ? -z : z;
+ *p = mpi_sint_abs( z );
Y.s = ( z < 0 ) ? -1 : 1;
Y.n = 1;
Y.p = p;
@@ -1138,6 +1141,11 @@ int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi
if( B->p[j - 1] != 0 )
break;
+ /* Exit early to avoid undefined behavior on NULL+0 when X->n == 0
+ * and B is 0 (of any size). */
+ if( j == 0 )
+ return( 0 );
+
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
o = B->p; p = X->p; c = 0;
@@ -1257,10 +1265,12 @@ cleanup:
return( ret );
}
-/*
- * Signed addition: X = A + B
+/* Common function for signed addition and subtraction.
+ * Calculate A + B * flip_B where flip_B is 1 or -1.
*/
-int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
+static int add_sub_mpi( mbedtls_mpi *X,
+ const mbedtls_mpi *A, const mbedtls_mpi *B,
+ int flip_B )
{
int ret, s;
MPI_VALIDATE_RET( X != NULL );
@@ -1268,16 +1278,21 @@ int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi
MPI_VALIDATE_RET( B != NULL );
s = A->s;
- if( A->s * B->s < 0 )
+ if( A->s * B->s * flip_B < 0 )
{
- if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
+ int cmp = mbedtls_mpi_cmp_abs( A, B );
+ if( cmp >= 0 )
{
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
- X->s = s;
+ /* If |A| = |B|, the result is 0 and we must set the sign bit
+ * to +1 regardless of which of A or B was negative. Otherwise,
+ * since |A| > |B|, the sign is the sign of A. */
+ X->s = cmp == 0 ? 1 : s;
}
else
{
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
+ /* Since |A| < |B|, the sign is the opposite of A. */
X->s = -s;
}
}
@@ -1293,38 +1308,19 @@ cleanup:
}
/*
+ * Signed addition: X = A + B
+ */
+int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
+{
+ return( add_sub_mpi( X, A, B, 1 ) );
+}
+
+/*
* Signed subtraction: X = A - B
*/
int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
{
- int ret, s;
- MPI_VALIDATE_RET( X != NULL );
- MPI_VALIDATE_RET( A != NULL );
- MPI_VALIDATE_RET( B != NULL );
-
- s = A->s;
- if( A->s * B->s > 0 )
- {
- if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
- {
- MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
- X->s = s;
- }
- else
- {
- MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
- X->s = -s;
- }
- }
- else
- {
- MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
- X->s = s;
- }
-
-cleanup:
-
- return( ret );
+ return( add_sub_mpi( X, A, B, -1 ) );
}
/*
@@ -1337,7 +1333,7 @@ int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint
MPI_VALIDATE_RET( X != NULL );
MPI_VALIDATE_RET( A != NULL );
- p[0] = ( b < 0 ) ? -b : b;
+ p[0] = mpi_sint_abs( b );
B.s = ( b < 0 ) ? -1 : 1;
B.n = 1;
B.p = p;
@@ -1355,7 +1351,7 @@ int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint
MPI_VALIDATE_RET( X != NULL );
MPI_VALIDATE_RET( A != NULL );
- p[0] = ( b < 0 ) ? -b : b;
+ p[0] = mpi_sint_abs( b );
B.s = ( b < 0 ) ? -1 : 1;
B.n = 1;
B.p = p;
@@ -1776,7 +1772,7 @@ int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R,
mbedtls_mpi_uint p[1];
MPI_VALIDATE_RET( A != NULL );
- p[0] = ( b < 0 ) ? -b : b;
+ p[0] = mpi_sint_abs( b );
B.s = ( b < 0 ) ? -1 : 1;
B.n = 1;
B.p = p;
@@ -2009,11 +2005,11 @@ int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,
mbedtls_mpi *prec_RR )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
- size_t wbits, wsize, one = 1;
+ size_t window_bitsize;
size_t i, j, nblimbs;
size_t bufsize, nbits;
mbedtls_mpi_uint ei, mm, state;
- mbedtls_mpi RR, T, W[ 1 << MBEDTLS_MPI_WINDOW_SIZE ], WW, Apos;
+ mbedtls_mpi RR, T, W[ (size_t) 1 << MBEDTLS_MPI_WINDOW_SIZE ], WW, Apos;
int neg;
MPI_VALIDATE_RET( X != NULL );
@@ -2042,21 +2038,59 @@ int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,
i = mbedtls_mpi_bitlen( E );
- wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
+ window_bitsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
#if( MBEDTLS_MPI_WINDOW_SIZE < 6 )
- if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
- wsize = MBEDTLS_MPI_WINDOW_SIZE;
+ if( window_bitsize > MBEDTLS_MPI_WINDOW_SIZE )
+ window_bitsize = MBEDTLS_MPI_WINDOW_SIZE;
#endif
+ const size_t w_table_used_size = (size_t) 1 << window_bitsize;
+
+ /*
+ * This function is not constant-trace: its memory accesses depend on the
+ * exponent value. To defend against timing attacks, callers (such as RSA
+ * and DHM) should use exponent blinding. However this is not enough if the
+ * adversary can find the exponent in a single trace, so this function
+ * takes extra precautions against adversaries who can observe memory
+ * access patterns.
+ *
+ * This function performs a series of multiplications by table elements and
+ * squarings, and we want the prevent the adversary from finding out which
+ * table element was used, and from distinguishing between multiplications
+ * and squarings. Firstly, when multiplying by an element of the window
+ * W[i], we do a constant-trace table lookup to obfuscate i. This leaves
+ * squarings as having a different memory access patterns from other
+ * multiplications. So secondly, we put the accumulator X in the table as
+ * well, and also do a constant-trace table lookup to multiply by X.
+ *
+ * This way, all multiplications take the form of a lookup-and-multiply.
+ * The number of lookup-and-multiply operations inside each iteration of
+ * the main loop still depends on the bits of the exponent, but since the
+ * other operations in the loop don't have an easily recognizable memory
+ * trace, an adversary is unlikely to be able to observe the exact
+ * patterns.
+ *
+ * An adversary may still be able to recover the exponent if they can
+ * observe both memory accesses and branches. However, branch prediction
+ * exploitation typically requires many traces of execution over the same
+ * data, which is defeated by randomized blinding.
+ *
+ * To achieve this, we make a copy of X and we use the table entry in each
+ * calculation from this point on.
+ */
+ const size_t x_index = 0;
+ mbedtls_mpi_init( &W[x_index] );
+ mbedtls_mpi_copy( &W[x_index], X );
+
j = N->n + 1;
/* All W[i] and X must have at least N->n limbs for the mpi_montmul()
* and mpi_montred() calls later. Here we ensure that W[1] and X are
* large enough, and later we'll grow other W[i] to the same length.
* They must not be shrunk midway through this function!
*/
- MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[x_index], j ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
@@ -2105,28 +2139,36 @@ int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,
mpi_montmul( &W[1], &RR, N, mm, &T );
/*
- * X = R^2 * R^-1 mod N = R mod N
+ * W[x_index] = R^2 * R^-1 mod N = R mod N
*/
- MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
- mpi_montred( X, N, mm, &T );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[x_index], &RR ) );
+ mpi_montred( &W[x_index], N, mm, &T );
+
- if( wsize > 1 )
+ if( window_bitsize > 1 )
{
/*
- * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
+ * W[i] = W[1] ^ i
+ *
+ * The first bit of the sliding window is always 1 and therefore we
+ * only need to store the second half of the table.
+ *
+ * (There are two special elements in the table: W[0] for the
+ * accumulator/result and W[1] for A in Montgomery form. Both of these
+ * are already set at this point.)
*/
- j = one << ( wsize - 1 );
+ j = w_table_used_size / 2;
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
- for( i = 0; i < wsize - 1; i++ )
+ for( i = 0; i < window_bitsize - 1; i++ )
mpi_montmul( &W[j], &W[j], N, mm, &T );
/*
* W[i] = W[i - 1] * W[1]
*/
- for( i = j + 1; i < ( one << wsize ); i++ )
+ for( i = j + 1; i < w_table_used_size; i++ )
{
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
@@ -2138,7 +2180,7 @@ int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,
nblimbs = E->n;
bufsize = 0;
nbits = 0;
- wbits = 0;
+ size_t exponent_bits_in_window = 0;
state = 0;
while( 1 )
@@ -2166,9 +2208,10 @@ int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,
if( ei == 0 && state == 1 )
{
/*
- * out of window, square X
+ * out of window, square W[x_index]
*/
- mpi_montmul( X, X, N, mm, &T );
+ MBEDTLS_MPI_CHK( mpi_select( &WW, W, w_table_used_size, x_index ) );
+ mpi_montmul( &W[x_index], &WW, N, mm, &T );
continue;
}
@@ -2178,25 +2221,30 @@ int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,
state = 2;
nbits++;
- wbits |= ( ei << ( wsize - nbits ) );
+ exponent_bits_in_window |= ( ei << ( window_bitsize - nbits ) );
- if( nbits == wsize )
+ if( nbits == window_bitsize )
{
/*
- * X = X^wsize R^-1 mod N
+ * W[x_index] = W[x_index]^window_bitsize R^-1 mod N
*/
- for( i = 0; i < wsize; i++ )
- mpi_montmul( X, X, N, mm, &T );
+ for( i = 0; i < window_bitsize; i++ )
+ {
+ MBEDTLS_MPI_CHK( mpi_select( &WW, W, w_table_used_size,
+ x_index ) );
+ mpi_montmul( &W[x_index], &WW, N, mm, &T );
+ }
/*
- * X = X * W[wbits] R^-1 mod N
+ * W[x_index] = W[x_index] * W[exponent_bits_in_window] R^-1 mod N
*/
- MBEDTLS_MPI_CHK( mpi_select( &WW, W, (size_t) 1 << wsize, wbits ) );
- mpi_montmul( X, &WW, N, mm, &T );
+ MBEDTLS_MPI_CHK( mpi_select( &WW, W, w_table_used_size,
+ exponent_bits_in_window ) );
+ mpi_montmul( &W[x_index], &WW, N, mm, &T );
state--;
nbits = 0;
- wbits = 0;
+ exponent_bits_in_window = 0;
}
}
@@ -2205,31 +2253,45 @@ int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,
*/
for( i = 0; i < nbits; i++ )
{
- mpi_montmul( X, X, N, mm, &T );
+ MBEDTLS_MPI_CHK( mpi_select( &WW, W, w_table_used_size, x_index ) );
+ mpi_montmul( &W[x_index], &WW, N, mm, &T );
- wbits <<= 1;
+ exponent_bits_in_window <<= 1;
- if( ( wbits & ( one << wsize ) ) != 0 )
- mpi_montmul( X, &W[1], N, mm, &T );
+ if( ( exponent_bits_in_window & ( (size_t) 1 << window_bitsize ) ) != 0 )
+ {
+ MBEDTLS_MPI_CHK( mpi_select( &WW, W, w_table_used_size, 1 ) );
+ mpi_montmul( &W[x_index], &WW, N, mm, &T );
+ }
}
/*
- * X = A^E * R * R^-1 mod N = A^E mod N
+ * W[x_index] = A^E * R * R^-1 mod N = A^E mod N
*/
- mpi_montred( X, N, mm, &T );
+ mpi_montred( &W[x_index], N, mm, &T );
if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
{
- X->s = -1;
- MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
+ W[x_index].s = -1;
+ MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &W[x_index], N, &W[x_index] ) );
}
+ /*
+ * Load the result in the output variable.
+ */
+ mbedtls_mpi_copy( X, &W[x_index] );
+
cleanup:
- for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
+ /* The first bit of the sliding window is always 1 and therefore the first
+ * half of the table was unused. */
+ for( i = w_table_used_size/2; i < w_table_used_size; i++ )
mbedtls_mpi_free( &W[i] );
- mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
+ mbedtls_mpi_free( &W[x_index] );
+ mbedtls_mpi_free( &W[1] );
+ mbedtls_mpi_free( &T );
+ mbedtls_mpi_free( &Apos );
mbedtls_mpi_free( &WW );
if( prec_RR == NULL || prec_RR->p == NULL )
@@ -2862,7 +2924,7 @@ int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int flags,
else
{
/*
- * An necessary condition for Y and X = 2Y + 1 to be prime
+ * A necessary condition for Y and X = 2Y + 1 to be prime
* is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
* Make sure it is satisfied, while keeping X = 3 mod 4
*/
diff --git a/thirdparty/mbedtls/library/camellia.c b/thirdparty/mbedtls/library/camellia.c
index 29d730ab53..e90cd7f134 100644
--- a/thirdparty/mbedtls/library/camellia.c
+++ b/thirdparty/mbedtls/library/camellia.c
@@ -32,14 +32,7 @@
#include <string.h>
-#if defined(MBEDTLS_SELF_TEST)
-#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
-#else
-#include <stdio.h>
-#define mbedtls_printf printf
-#endif /* MBEDTLS_PLATFORM_C */
-#endif /* MBEDTLS_SELF_TEST */
#if !defined(MBEDTLS_CAMELLIA_ALT)
diff --git a/thirdparty/mbedtls/library/ccm.c b/thirdparty/mbedtls/library/ccm.c
index a21a37f55f..e0d43334f9 100644
--- a/thirdparty/mbedtls/library/ccm.c
+++ b/thirdparty/mbedtls/library/ccm.c
@@ -36,14 +36,7 @@
#include <string.h>
-#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
-#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
-#else
-#include <stdio.h>
-#define mbedtls_printf printf
-#endif /* MBEDTLS_PLATFORM_C */
-#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
#if !defined(MBEDTLS_CCM_ALT)
diff --git a/thirdparty/mbedtls/library/chacha20.c b/thirdparty/mbedtls/library/chacha20.c
index 658f046901..bd0701482c 100644
--- a/thirdparty/mbedtls/library/chacha20.c
+++ b/thirdparty/mbedtls/library/chacha20.c
@@ -32,22 +32,10 @@
#include <stddef.h>
#include <string.h>
-#if defined(MBEDTLS_SELF_TEST)
-#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
-#else
-#include <stdio.h>
-#define mbedtls_printf printf
-#endif /* MBEDTLS_PLATFORM_C */
-#endif /* MBEDTLS_SELF_TEST */
#if !defined(MBEDTLS_CHACHA20_ALT)
-#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
- !defined(inline) && !defined(__cplusplus)
-#define inline __inline
-#endif
-
/* Parameter validation macros */
#define CHACHA20_VALIDATE_RET( cond ) \
MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA )
diff --git a/thirdparty/mbedtls/library/chachapoly.c b/thirdparty/mbedtls/library/chachapoly.c
index dc75b2030a..4adf846857 100644
--- a/thirdparty/mbedtls/library/chachapoly.c
+++ b/thirdparty/mbedtls/library/chachapoly.c
@@ -28,14 +28,7 @@
#include <string.h>
-#if defined(MBEDTLS_SELF_TEST)
-#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
-#else
-#include <stdio.h>
-#define mbedtls_printf printf
-#endif /* MBEDTLS_PLATFORM_C */
-#endif /* MBEDTLS_SELF_TEST */
#if !defined(MBEDTLS_CHACHAPOLY_ALT)
diff --git a/thirdparty/mbedtls/library/cipher.c b/thirdparty/mbedtls/library/cipher.c
index f3b4bd29ce..67e3274587 100644
--- a/thirdparty/mbedtls/library/cipher.c
+++ b/thirdparty/mbedtls/library/cipher.c
@@ -63,12 +63,7 @@
#include "mbedtls/nist_kw.h"
#endif
-#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
-#else
-#define mbedtls_calloc calloc
-#define mbedtls_free free
-#endif
#define CIPHER_VALIDATE_RET( cond ) \
MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA )
diff --git a/thirdparty/mbedtls/library/cipher_wrap.c b/thirdparty/mbedtls/library/cipher_wrap.c
index 57eb3cb67f..c76bdcc0f8 100644
--- a/thirdparty/mbedtls/library/cipher_wrap.c
+++ b/thirdparty/mbedtls/library/cipher_wrap.c
@@ -76,13 +76,7 @@
#include <string.h>
#endif
-#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
-#else
-#include <stdlib.h>
-#define mbedtls_calloc calloc
-#define mbedtls_free free
-#endif
#if defined(MBEDTLS_GCM_C)
/* shared by all GCM ciphers */
diff --git a/thirdparty/mbedtls/library/common.h b/thirdparty/mbedtls/library/common.h
index c06472418d..1663d50226 100644
--- a/thirdparty/mbedtls/library/common.h
+++ b/thirdparty/mbedtls/library/common.h
@@ -29,8 +29,15 @@
#include "mbedtls/config.h"
#endif
+#include <stddef.h>
#include <stdint.h>
+/* Define `inline` on some non-C99-compliant compilers. */
+#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
+ !defined(inline) && !defined(__cplusplus)
+#define inline __inline
+#endif
+
/** Helper to define a function as static except when building invasive tests.
*
* If a function is only used inside its own source file and should be
@@ -52,6 +59,44 @@
#define MBEDTLS_STATIC_TESTABLE static
#endif
+/** Return an offset into a buffer.
+ *
+ * This is just the addition of an offset to a pointer, except that this
+ * function also accepts an offset of 0 into a buffer whose pointer is null.
+ * (`p + n` has undefined behavior when `p` is null, even when `n == 0`.
+ * A null pointer is a valid buffer pointer when the size is 0, for example
+ * as the result of `malloc(0)` on some platforms.)
+ *
+ * \param p Pointer to a buffer of at least n bytes.
+ * This may be \p NULL if \p n is zero.
+ * \param n An offset in bytes.
+ * \return Pointer to offset \p n in the buffer \p p.
+ * Note that this is only a valid pointer if the size of the
+ * buffer is at least \p n + 1.
+ */
+static inline unsigned char *mbedtls_buffer_offset(
+ unsigned char *p, size_t n )
+{
+ return( p == NULL ? NULL : p + n );
+}
+
+/** Return an offset into a read-only buffer.
+ *
+ * Similar to mbedtls_buffer_offset(), but for const pointers.
+ *
+ * \param p Pointer to a buffer of at least n bytes.
+ * This may be \p NULL if \p n is zero.
+ * \param n An offset in bytes.
+ * \return Pointer to offset \p n in the buffer \p p.
+ * Note that this is only a valid pointer if the size of the
+ * buffer is at least \p n + 1.
+ */
+static inline const unsigned char *mbedtls_buffer_offset_const(
+ const unsigned char *p, size_t n )
+{
+ return( p == NULL ? NULL : p + n );
+}
+
/** Byte Reading Macros
*
* Given a multi-byte integer \p x, MBEDTLS_BYTE_n retrieves the n-th
diff --git a/thirdparty/mbedtls/library/constant_time.c b/thirdparty/mbedtls/library/constant_time.c
index e276d23ca0..2401b0434a 100644
--- a/thirdparty/mbedtls/library/constant_time.c
+++ b/thirdparty/mbedtls/library/constant_time.c
@@ -81,7 +81,7 @@ unsigned mbedtls_ct_uint_mask( unsigned value )
#endif
}
-#if defined(MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC)
+#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC)
size_t mbedtls_ct_size_mask( size_t value )
{
@@ -97,7 +97,7 @@ size_t mbedtls_ct_size_mask( size_t value )
#endif
}
-#endif /* MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC */
+#endif /* MBEDTLS_SSL_SOME_MODES_USE_MAC */
#if defined(MBEDTLS_BIGNUM_C)
@@ -272,7 +272,7 @@ unsigned mbedtls_ct_uint_if( unsigned condition,
* \note if1 and if0 must be either 1 or -1, otherwise the result
* is undefined.
*
- * \param condition Condition to test.
+ * \param condition Condition to test; must be either 0 or 1.
* \param if1 The first sign; must be either +1 or -1.
* \param if0 The second sign; must be either +1 or -1.
*
@@ -404,8 +404,7 @@ static void mbedtls_ct_mem_move_to_left( void *start,
#endif /* MBEDTLS_PKCS1_V15 && MBEDTLS_RSA_C && ! MBEDTLS_RSA_ALT */
-#if defined(MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC)
-
+#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC)
void mbedtls_ct_memcpy_if_eq( unsigned char *dest,
const unsigned char *src,
size_t len,
@@ -527,7 +526,7 @@ cleanup:
return( ret );
}
-#endif /* MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC */
+#endif /* MBEDTLS_SSL_SOME_MODES_USE_MAC */
#if defined(MBEDTLS_BIGNUM_C)
diff --git a/thirdparty/mbedtls/library/constant_time_internal.h b/thirdparty/mbedtls/library/constant_time_internal.h
index a550b38fa5..ff2d0ff92c 100644
--- a/thirdparty/mbedtls/library/constant_time_internal.h
+++ b/thirdparty/mbedtls/library/constant_time_internal.h
@@ -32,7 +32,6 @@
#include <stddef.h>
-
/** Turn a value into a mask:
* - if \p value == 0, return the all-bits 0 mask, aka 0
* - otherwise, return the all-bits 1 mask, aka (unsigned) -1
@@ -46,7 +45,7 @@
*/
unsigned mbedtls_ct_uint_mask( unsigned value );
-#if defined(MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC)
+#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC)
/** Turn a value into a mask:
* - if \p value == 0, return the all-bits 0 mask, aka 0
@@ -61,7 +60,7 @@ unsigned mbedtls_ct_uint_mask( unsigned value );
*/
size_t mbedtls_ct_size_mask( size_t value );
-#endif /* MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC */
+#endif /* MBEDTLS_SSL_SOME_MODES_USE_MAC */
#if defined(MBEDTLS_BIGNUM_C)
@@ -196,7 +195,7 @@ signed char mbedtls_ct_base64_dec_value( unsigned char c );
#endif /* MBEDTLS_BASE64_C */
-#if defined(MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC)
+#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC)
/** Conditional memcpy without branches.
*
@@ -292,7 +291,7 @@ int mbedtls_ct_hmac( mbedtls_md_context_t *ctx,
size_t max_data_len,
unsigned char *output );
-#endif /* MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC */
+#endif /* MBEDTLS_SSL_SOME_MODES_USE_MAC */
#if defined(MBEDTLS_PKCS1_V15) && defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_RSA_ALT)
diff --git a/thirdparty/mbedtls/library/ctr_drbg.c b/thirdparty/mbedtls/library/ctr_drbg.c
index a00d66ce87..ed31576a7b 100644
--- a/thirdparty/mbedtls/library/ctr_drbg.c
+++ b/thirdparty/mbedtls/library/ctr_drbg.c
@@ -36,14 +36,7 @@
#include <stdio.h>
#endif
-#if defined(MBEDTLS_SELF_TEST)
-#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
-#else
-#include <stdio.h>
-#define mbedtls_printf printf
-#endif /* MBEDTLS_PLATFORM_C */
-#endif /* MBEDTLS_SELF_TEST */
/*
* CTR_DRBG context initialization
diff --git a/thirdparty/mbedtls/library/debug.c b/thirdparty/mbedtls/library/debug.c
index e1086008af..353b4bf07b 100644
--- a/thirdparty/mbedtls/library/debug.c
+++ b/thirdparty/mbedtls/library/debug.c
@@ -21,16 +21,7 @@
#if defined(MBEDTLS_DEBUG_C)
-#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
-#else
-#include <stdlib.h>
-#define mbedtls_calloc calloc
-#define mbedtls_free free
-#define mbedtls_time_t time_t
-#define mbedtls_snprintf snprintf
-#define mbedtls_vsnprintf vsnprintf
-#endif
#include "mbedtls/debug.h"
#include "mbedtls/error.h"
@@ -39,11 +30,6 @@
#include <stdio.h>
#include <string.h>
-#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
- !defined(inline) && !defined(__cplusplus)
-#define inline __inline
-#endif
-
#define DEBUG_BUF_SIZE 512
static int debug_threshold = 0;
diff --git a/thirdparty/mbedtls/library/des.c b/thirdparty/mbedtls/library/des.c
index 91d22b5d90..65f5681cf1 100644
--- a/thirdparty/mbedtls/library/des.c
+++ b/thirdparty/mbedtls/library/des.c
@@ -33,14 +33,7 @@
#include <string.h>
-#if defined(MBEDTLS_SELF_TEST)
-#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
-#else
-#include <stdio.h>
-#define mbedtls_printf printf
-#endif /* MBEDTLS_PLATFORM_C */
-#endif /* MBEDTLS_SELF_TEST */
#if !defined(MBEDTLS_DES_ALT)
diff --git a/thirdparty/mbedtls/library/dhm.c b/thirdparty/mbedtls/library/dhm.c
index 88e148bb80..4d2e33e689 100644
--- a/thirdparty/mbedtls/library/dhm.c
+++ b/thirdparty/mbedtls/library/dhm.c
@@ -43,15 +43,7 @@
#include "mbedtls/asn1.h"
#endif
-#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
-#else
-#include <stdlib.h>
-#include <stdio.h>
-#define mbedtls_printf printf
-#define mbedtls_calloc calloc
-#define mbedtls_free free
-#endif
#if !defined(MBEDTLS_DHM_ALT)
diff --git a/thirdparty/mbedtls/library/ecdh.c b/thirdparty/mbedtls/library/ecdh.c
index 60c6e429de..724c938a71 100644
--- a/thirdparty/mbedtls/library/ecdh.c
+++ b/thirdparty/mbedtls/library/ecdh.c
@@ -77,10 +77,12 @@ static int ecdh_gen_public_restartable( mbedtls_ecp_group *grp,
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
- /* If multiplication is in progress, we already generated a privkey */
+ int restarting = 0;
#if defined(MBEDTLS_ECP_RESTARTABLE)
- if( rs_ctx == NULL || rs_ctx->rsm == NULL )
+ restarting = ( rs_ctx != NULL && rs_ctx->rsm != NULL );
#endif
+ /* If multiplication is in progress, we already generated a privkey */
+ if( !restarting )
MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, d, f_rng, p_rng ) );
MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, Q, d, &grp->G,
diff --git a/thirdparty/mbedtls/library/ecdsa.c b/thirdparty/mbedtls/library/ecdsa.c
index 640eb24a26..4bae6a93fd 100644
--- a/thirdparty/mbedtls/library/ecdsa.c
+++ b/thirdparty/mbedtls/library/ecdsa.c
@@ -36,13 +36,7 @@
#include "mbedtls/hmac_drbg.h"
#endif
-#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
-#else
-#include <stdlib.h>
-#define mbedtls_calloc calloc
-#define mbedtls_free free
-#endif
#include "mbedtls/platform_util.h"
#include "mbedtls/error.h"
diff --git a/thirdparty/mbedtls/library/ecjpake.c b/thirdparty/mbedtls/library/ecjpake.c
index 0b9bffb93e..fe0b9d93e9 100644
--- a/thirdparty/mbedtls/library/ecjpake.c
+++ b/thirdparty/mbedtls/library/ecjpake.c
@@ -794,12 +794,7 @@ cleanup:
#if defined(MBEDTLS_SELF_TEST)
-#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
-#else
-#include <stdio.h>
-#define mbedtls_printf printf
-#endif
#if !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \
!defined(MBEDTLS_SHA256_C)
diff --git a/thirdparty/mbedtls/library/ecp.c b/thirdparty/mbedtls/library/ecp.c
index 890f364a08..ad19e05fb2 100644
--- a/thirdparty/mbedtls/library/ecp.c
+++ b/thirdparty/mbedtls/library/ecp.c
@@ -90,15 +90,7 @@
#define ECP_VALIDATE( cond ) \
MBEDTLS_INTERNAL_VALIDATE( cond )
-#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
-#else
-#include <stdlib.h>
-#include <stdio.h>
-#define mbedtls_printf printf
-#define mbedtls_calloc calloc
-#define mbedtls_free free
-#endif
#include "mbedtls/ecp_internal.h"
@@ -112,11 +104,6 @@
#endif
#endif /* MBEDTLS_ECP_NO_INTERNAL_RNG */
-#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
- !defined(inline) && !defined(__cplusplus)
-#define inline __inline
-#endif
-
#if defined(MBEDTLS_SELF_TEST)
/*
* Counts of point addition and doubling, and field multiplications.
@@ -2056,9 +2043,13 @@ static int ecp_mul_comb_core( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R
i = d;
MBEDTLS_MPI_CHK( ecp_select_comb( grp, R, T, T_size, x[i] ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->Z, 1 ) );
+
+ int have_rng = 1;
#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
- if( f_rng != 0 )
+ if( f_rng == NULL )
+ have_rng = 0;
#endif
+ if( have_rng )
MBEDTLS_MPI_CHK( ecp_randomize_jac( grp, R, f_rng, p_rng ) );
}
@@ -2192,9 +2183,12 @@ final_norm:
*
* Avoid the leak by randomizing coordinates before we normalize them.
*/
+ int have_rng = 1;
#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
- if( f_rng != 0 )
+ if( f_rng == NULL )
+ have_rng = 0;
#endif
+ if( have_rng )
MBEDTLS_MPI_CHK( ecp_randomize_jac( grp, RR, f_rng, p_rng ) );
MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, RR ) );
@@ -2403,12 +2397,14 @@ cleanup:
mbedtls_free( T );
}
- /* don't free R while in progress in case R == P */
+ /* prevent caller from using invalid value */
+ int should_free_R = ( ret != 0 );
#if defined(MBEDTLS_ECP_RESTARTABLE)
- if( ret != MBEDTLS_ERR_ECP_IN_PROGRESS )
+ /* don't free R while in progress in case R == P */
+ if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
+ should_free_R = 0;
#endif
- /* prevent caller from using invalid value */
- if( ret != 0 )
+ if( should_free_R )
mbedtls_ecp_point_free( R );
ECP_RS_LEAVE( rsm );
@@ -2596,13 +2592,16 @@ static int ecp_mul_mxz( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
MOD_ADD( RP.X );
/* Randomize coordinates of the starting point */
+ int have_rng = 1;
#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
- if( f_rng != NULL )
+ if( f_rng == NULL )
+ have_rng = 0;
#endif
+ if( have_rng )
MBEDTLS_MPI_CHK( ecp_randomize_mxz( grp, &RP, f_rng, p_rng ) );
/* Loop invariant: R = result so far, RP = R + P */
- i = mbedtls_mpi_bitlen( m ); /* one past the (zero-based) most significant bit */
+ i = grp->nbits + 1; /* one past the (zero-based) required msb for private keys */
while( i-- > 0 )
{
b = mbedtls_mpi_get_bit( m, i );
@@ -2631,9 +2630,12 @@ static int ecp_mul_mxz( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
*
* Avoid the leak by randomizing coordinates before we normalize them.
*/
+ have_rng = 1;
#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
- if( f_rng != NULL )
+ if( f_rng == NULL )
+ have_rng = 0;
#endif
+ if( have_rng )
MBEDTLS_MPI_CHK( ecp_randomize_mxz( grp, R, f_rng, p_rng ) );
MBEDTLS_MPI_CHK( ecp_normalize_mxz( grp, R ) );
@@ -2680,10 +2682,12 @@ int mbedtls_ecp_mul_restartable( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
MBEDTLS_MPI_CHK( mbedtls_internal_ecp_init( grp ) );
#endif /* MBEDTLS_ECP_INTERNAL_ALT */
+ int restarting = 0;
#if defined(MBEDTLS_ECP_RESTARTABLE)
- /* skip argument check when restarting */
- if( rs_ctx == NULL || rs_ctx->rsm == NULL )
+ restarting = ( rs_ctx != NULL && rs_ctx->rsm != NULL );
#endif
+ /* skip argument check when restarting */
+ if( !restarting )
{
/* check_privkey is free */
MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_CHK );
@@ -2797,14 +2801,17 @@ static int mbedtls_ecp_mul_shortcuts( mbedtls_ecp_group *grp,
if( mbedtls_mpi_cmp_int( m, 0 ) == 0 )
{
+ MBEDTLS_MPI_CHK( mbedtls_ecp_check_pubkey( grp, P ) );
MBEDTLS_MPI_CHK( mbedtls_ecp_set_zero( R ) );
}
else if( mbedtls_mpi_cmp_int( m, 1 ) == 0 )
{
+ MBEDTLS_MPI_CHK( mbedtls_ecp_check_pubkey( grp, P ) );
MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, P ) );
}
else if( mbedtls_mpi_cmp_int( m, -1 ) == 0 )
{
+ MBEDTLS_MPI_CHK( mbedtls_ecp_check_pubkey( grp, P ) );
MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, P ) );
if( mbedtls_mpi_cmp_int( &R->Y, 0 ) != 0 )
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &R->Y, &grp->P, &R->Y ) );
diff --git a/thirdparty/mbedtls/library/ecp_curves.c b/thirdparty/mbedtls/library/ecp_curves.c
index 2199be6461..47761eef4e 100644
--- a/thirdparty/mbedtls/library/ecp_curves.c
+++ b/thirdparty/mbedtls/library/ecp_curves.c
@@ -38,11 +38,6 @@
#define ECP_VALIDATE( cond ) \
MBEDTLS_INTERNAL_VALIDATE( cond )
-#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
- !defined(inline) && !defined(__cplusplus)
-#define inline __inline
-#endif
-
#define ECP_MPI_INIT(s, n, p) {s, (n), (mbedtls_mpi_uint *)(p)}
#define ECP_MPI_INIT_ARRAY(x) \
diff --git a/thirdparty/mbedtls/library/entropy.c b/thirdparty/mbedtls/library/entropy.c
index 12fd3b9b5f..e3b337ff35 100644
--- a/thirdparty/mbedtls/library/entropy.c
+++ b/thirdparty/mbedtls/library/entropy.c
@@ -38,18 +38,9 @@
#include <stdio.h>
#endif
-#if defined(MBEDTLS_ENTROPY_NV_SEED)
#include "mbedtls/platform.h"
-#endif
-#if defined(MBEDTLS_SELF_TEST)
-#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
-#else
-#include <stdio.h>
-#define mbedtls_printf printf
-#endif /* MBEDTLS_PLATFORM_C */
-#endif /* MBEDTLS_SELF_TEST */
#if defined(MBEDTLS_HAVEGE_C)
#include "mbedtls/havege.h"
diff --git a/thirdparty/mbedtls/library/entropy_poll.c b/thirdparty/mbedtls/library/entropy_poll.c
index 40f23fd2a6..69ac29e4f7 100644
--- a/thirdparty/mbedtls/library/entropy_poll.c
+++ b/thirdparty/mbedtls/library/entropy_poll.c
@@ -38,9 +38,7 @@
#if defined(MBEDTLS_HAVEGE_C)
#include "mbedtls/havege.h"
#endif
-#if defined(MBEDTLS_ENTROPY_NV_SEED)
#include "mbedtls/platform.h"
-#endif
#if !defined(MBEDTLS_NO_PLATFORM_ENTROPY)
diff --git a/thirdparty/mbedtls/library/error.c b/thirdparty/mbedtls/library/error.c
index afad38904f..8573369a32 100644
--- a/thirdparty/mbedtls/library/error.c
+++ b/thirdparty/mbedtls/library/error.c
@@ -25,11 +25,7 @@
#if defined(MBEDTLS_ERROR_C)
-#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
-#else
-#define mbedtls_snprintf snprintf
-#endif
#include <stdio.h>
#include <string.h>
@@ -961,7 +957,7 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen )
#else /* MBEDTLS_ERROR_C */
/*
- * Provide an non-function in case MBEDTLS_ERROR_C is not defined
+ * Provide a dummy implementation when MBEDTLS_ERROR_C is not defined
*/
void mbedtls_strerror( int ret, char *buf, size_t buflen )
{
diff --git a/thirdparty/mbedtls/library/gcm.c b/thirdparty/mbedtls/library/gcm.c
index 43a5e1bec6..d0b73379a6 100644
--- a/thirdparty/mbedtls/library/gcm.c
+++ b/thirdparty/mbedtls/library/gcm.c
@@ -32,6 +32,7 @@
#if defined(MBEDTLS_GCM_C)
#include "mbedtls/gcm.h"
+#include "mbedtls/platform.h"
#include "mbedtls/platform_util.h"
#include "mbedtls/error.h"
@@ -41,15 +42,6 @@
#include "mbedtls/aesni.h"
#endif
-#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
-#include "mbedtls/aes.h"
-#include "mbedtls/platform.h"
-#if !defined(MBEDTLS_PLATFORM_C)
-#include <stdio.h>
-#define mbedtls_printf printf
-#endif /* MBEDTLS_PLATFORM_C */
-#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
-
#if !defined(MBEDTLS_GCM_ALT)
/* Parameter validation macros */
diff --git a/thirdparty/mbedtls/library/hmac_drbg.c b/thirdparty/mbedtls/library/hmac_drbg.c
index de9706885c..69272fa73d 100644
--- a/thirdparty/mbedtls/library/hmac_drbg.c
+++ b/thirdparty/mbedtls/library/hmac_drbg.c
@@ -37,14 +37,7 @@
#include <stdio.h>
#endif
-#if defined(MBEDTLS_SELF_TEST)
-#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
-#else
-#include <stdio.h>
-#define mbedtls_printf printf
-#endif /* MBEDTLS_SELF_TEST */
-#endif /* MBEDTLS_PLATFORM_C */
/*
* HMAC_DRBG context initialization
diff --git a/thirdparty/mbedtls/library/md.c b/thirdparty/mbedtls/library/md.c
index a10a835634..53a84b01c6 100644
--- a/thirdparty/mbedtls/library/md.c
+++ b/thirdparty/mbedtls/library/md.c
@@ -38,13 +38,7 @@
#include "mbedtls/sha256.h"
#include "mbedtls/sha512.h"
-#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
-#else
-#include <stdlib.h>
-#define mbedtls_calloc calloc
-#define mbedtls_free free
-#endif
#include <string.h>
diff --git a/thirdparty/mbedtls/library/md2.c b/thirdparty/mbedtls/library/md2.c
index 7264e30313..f8293a1df3 100644
--- a/thirdparty/mbedtls/library/md2.c
+++ b/thirdparty/mbedtls/library/md2.c
@@ -33,14 +33,7 @@
#include <string.h>
-#if defined(MBEDTLS_SELF_TEST)
-#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
-#else
-#include <stdio.h>
-#define mbedtls_printf printf
-#endif /* MBEDTLS_PLATFORM_C */
-#endif /* MBEDTLS_SELF_TEST */
#if !defined(MBEDTLS_MD2_ALT)
diff --git a/thirdparty/mbedtls/library/md4.c b/thirdparty/mbedtls/library/md4.c
index eaa679a0a6..a412213480 100644
--- a/thirdparty/mbedtls/library/md4.c
+++ b/thirdparty/mbedtls/library/md4.c
@@ -33,14 +33,7 @@
#include <string.h>
-#if defined(MBEDTLS_SELF_TEST)
-#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
-#else
-#include <stdio.h>
-#define mbedtls_printf printf
-#endif /* MBEDTLS_PLATFORM_C */
-#endif /* MBEDTLS_SELF_TEST */
#if !defined(MBEDTLS_MD4_ALT)
diff --git a/thirdparty/mbedtls/library/md5.c b/thirdparty/mbedtls/library/md5.c
index 4b53fcf367..e53bfe6306 100644
--- a/thirdparty/mbedtls/library/md5.c
+++ b/thirdparty/mbedtls/library/md5.c
@@ -32,14 +32,7 @@
#include <string.h>
-#if defined(MBEDTLS_SELF_TEST)
-#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
-#else
-#include <stdio.h>
-#define mbedtls_printf printf
-#endif /* MBEDTLS_PLATFORM_C */
-#endif /* MBEDTLS_SELF_TEST */
#if !defined(MBEDTLS_MD5_ALT)
diff --git a/thirdparty/mbedtls/library/mps_reader.c b/thirdparty/mbedtls/library/mps_reader.c
index 9af5073cc9..0c30a75d05 100644
--- a/thirdparty/mbedtls/library/mps_reader.c
+++ b/thirdparty/mbedtls/library/mps_reader.c
@@ -29,11 +29,6 @@
#include <string.h>
-#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
- !defined(inline) && !defined(__cplusplus)
-#define inline __inline
-#endif
-
#if defined(MBEDTLS_MPS_ENABLE_TRACE)
static int mbedtls_mps_trace_id = MBEDTLS_MPS_TRACE_BIT_READER;
#endif /* MBEDTLS_MPS_ENABLE_TRACE */
@@ -535,7 +530,7 @@ int mbedtls_mps_reader_reclaim( mbedtls_mps_reader *rd,
* of the accumulator. */
memmove( acc, acc + acc_backup_offset, acc_backup_len );
- /* Copy uncmmitted parts of the current fragment to the
+ /* Copy uncommitted parts of the current fragment to the
* accumulator. */
memcpy( acc + acc_backup_len,
frag + frag_backup_offset, frag_backup_len );
diff --git a/thirdparty/mbedtls/library/mps_trace.h b/thirdparty/mbedtls/library/mps_trace.h
index 7c2360118a..820a1b66c2 100644
--- a/thirdparty/mbedtls/library/mps_trace.h
+++ b/thirdparty/mbedtls/library/mps_trace.h
@@ -30,13 +30,7 @@
#include "mps_common.h"
#include "mps_trace.h"
-#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
-#else
-#include <stdio.h>
-#define mbedtls_printf printf
-#define mbedtls_vsnprintf vsnprintf
-#endif /* MBEDTLS_PLATFORM_C */
#if defined(MBEDTLS_MPS_ENABLE_TRACE)
diff --git a/thirdparty/mbedtls/library/net_sockets.c b/thirdparty/mbedtls/library/net_sockets.c
index 8c765e1c8c..b2cab503f2 100644
--- a/thirdparty/mbedtls/library/net_sockets.c
+++ b/thirdparty/mbedtls/library/net_sockets.c
@@ -37,11 +37,7 @@
#error "This module only works on Unix and Windows, see MBEDTLS_NET_C in config.h"
#endif
-#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
-#else
-#include <stdlib.h>
-#endif
#include "mbedtls/net_sockets.h"
#include "mbedtls/error.h"
diff --git a/thirdparty/mbedtls/library/nist_kw.c b/thirdparty/mbedtls/library/nist_kw.c
index 1aea0b6345..495c23d06a 100644
--- a/thirdparty/mbedtls/library/nist_kw.c
+++ b/thirdparty/mbedtls/library/nist_kw.c
@@ -39,14 +39,7 @@
#include <stdint.h>
#include <string.h>
-#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
-#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
-#else
-#include <stdio.h>
-#define mbedtls_printf printf
-#endif /* MBEDTLS_PLATFORM_C */
-#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
#if !defined(MBEDTLS_NIST_KW_ALT)
diff --git a/thirdparty/mbedtls/library/oid.c b/thirdparty/mbedtls/library/oid.c
index 19c8ac207c..53e5350eb3 100644
--- a/thirdparty/mbedtls/library/oid.c
+++ b/thirdparty/mbedtls/library/oid.c
@@ -30,11 +30,7 @@
#include <stdio.h>
#include <string.h>
-#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
-#else
-#define mbedtls_snprintf snprintf
-#endif
/*
* Macro to automatically add the size of #define'd OIDs
diff --git a/thirdparty/mbedtls/library/pem.c b/thirdparty/mbedtls/library/pem.c
index fcfde94799..cb1c82b3e4 100644
--- a/thirdparty/mbedtls/library/pem.c
+++ b/thirdparty/mbedtls/library/pem.c
@@ -32,13 +32,7 @@
#include <string.h>
-#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
-#else
-#include <stdlib.h>
-#define mbedtls_calloc calloc
-#define mbedtls_free free
-#endif
#if defined(MBEDTLS_PEM_PARSE_C)
void mbedtls_pem_init( mbedtls_pem_context *ctx )
diff --git a/thirdparty/mbedtls/library/pk_wrap.c b/thirdparty/mbedtls/library/pk_wrap.c
index 107e912ace..f35abf21a4 100644
--- a/thirdparty/mbedtls/library/pk_wrap.c
+++ b/thirdparty/mbedtls/library/pk_wrap.c
@@ -50,13 +50,7 @@
#include "mbedtls/asn1.h"
#endif
-#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
-#else
-#include <stdlib.h>
-#define mbedtls_calloc calloc
-#define mbedtls_free free
-#endif
#include <limits.h>
#include <stdint.h>
@@ -872,7 +866,7 @@ static void *pk_opaque_alloc_wrap( void )
{
void *ctx = mbedtls_calloc( 1, sizeof( psa_key_id_t ) );
- /* no _init() function to call, an calloc() already zeroized */
+ /* no _init() function to call, as calloc() already zeroized */
return( ctx );
}
diff --git a/thirdparty/mbedtls/library/pkcs11.c b/thirdparty/mbedtls/library/pkcs11.c
index 4deccf3f60..a7207cfc93 100644
--- a/thirdparty/mbedtls/library/pkcs11.c
+++ b/thirdparty/mbedtls/library/pkcs11.c
@@ -29,13 +29,7 @@
#include "mbedtls/oid.h"
#include "mbedtls/x509_crt.h"
-#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
-#else
-#include <stdlib.h>
-#define mbedtls_calloc calloc
-#define mbedtls_free free
-#endif
#include <string.h>
diff --git a/thirdparty/mbedtls/library/pkcs5.c b/thirdparty/mbedtls/library/pkcs5.c
index 2b014d91c8..f9d01371a7 100644
--- a/thirdparty/mbedtls/library/pkcs5.c
+++ b/thirdparty/mbedtls/library/pkcs5.c
@@ -42,12 +42,7 @@
#include <string.h>
-#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
-#else
-#include <stdio.h>
-#define mbedtls_printf printf
-#endif
#if defined(MBEDTLS_ASN1_PARSE_C)
static int pkcs5_parse_pbkdf2_params( const mbedtls_asn1_buf *params,
diff --git a/thirdparty/mbedtls/library/pkparse.c b/thirdparty/mbedtls/library/pkparse.c
index ea5c6b69cb..6170d6d012 100644
--- a/thirdparty/mbedtls/library/pkparse.c
+++ b/thirdparty/mbedtls/library/pkparse.c
@@ -48,13 +48,7 @@
#include "mbedtls/pkcs12.h"
#endif
-#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
-#else
-#include <stdlib.h>
-#define mbedtls_calloc calloc
-#define mbedtls_free free
-#endif
/* Parameter validation macros based on platform_util.h */
#define PK_VALIDATE_RET( cond ) \
diff --git a/thirdparty/mbedtls/library/pkwrite.c b/thirdparty/mbedtls/library/pkwrite.c
index 566153dd93..c1ce0e3f02 100644
--- a/thirdparty/mbedtls/library/pkwrite.c
+++ b/thirdparty/mbedtls/library/pkwrite.c
@@ -48,13 +48,7 @@
#include "psa/crypto.h"
#include "mbedtls/psa_util.h"
#endif
-#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
-#else
-#include <stdlib.h>
-#define mbedtls_calloc calloc
-#define mbedtls_free free
-#endif
/* Parameter validation macros based on platform_util.h */
#define PK_VALIDATE_RET( cond ) \
diff --git a/thirdparty/mbedtls/library/poly1305.c b/thirdparty/mbedtls/library/poly1305.c
index 7375a0c572..a1c5b19d8e 100644
--- a/thirdparty/mbedtls/library/poly1305.c
+++ b/thirdparty/mbedtls/library/poly1305.c
@@ -28,22 +28,10 @@
#include <string.h>
-#if defined(MBEDTLS_SELF_TEST)
-#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
-#else
-#include <stdio.h>
-#define mbedtls_printf printf
-#endif /* MBEDTLS_PLATFORM_C */
-#endif /* MBEDTLS_SELF_TEST */
#if !defined(MBEDTLS_POLY1305_ALT)
-#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
- !defined(inline) && !defined(__cplusplus)
-#define inline __inline
-#endif
-
/* Parameter validation macros */
#define POLY1305_VALIDATE_RET( cond ) \
MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA )
diff --git a/thirdparty/mbedtls/library/ripemd160.c b/thirdparty/mbedtls/library/ripemd160.c
index aed7322cff..55e259e192 100644
--- a/thirdparty/mbedtls/library/ripemd160.c
+++ b/thirdparty/mbedtls/library/ripemd160.c
@@ -33,14 +33,7 @@
#include <string.h>
-#if defined(MBEDTLS_SELF_TEST)
-#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
-#else
-#include <stdio.h>
-#define mbedtls_printf printf
-#endif /* MBEDTLS_PLATFORM_C */
-#endif /* MBEDTLS_SELF_TEST */
#if !defined(MBEDTLS_RIPEMD160_ALT)
diff --git a/thirdparty/mbedtls/library/rsa.c b/thirdparty/mbedtls/library/rsa.c
index d1f6ddb177..9c39fa5d91 100644
--- a/thirdparty/mbedtls/library/rsa.c
+++ b/thirdparty/mbedtls/library/rsa.c
@@ -57,14 +57,7 @@
#include <stdlib.h>
#endif
-#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
-#else
-#include <stdio.h>
-#define mbedtls_printf printf
-#define mbedtls_calloc calloc
-#define mbedtls_free free
-#endif
#if !defined(MBEDTLS_RSA_ALT)
diff --git a/thirdparty/mbedtls/library/sha1.c b/thirdparty/mbedtls/library/sha1.c
index 0a5edafaff..7f0c8757db 100644
--- a/thirdparty/mbedtls/library/sha1.c
+++ b/thirdparty/mbedtls/library/sha1.c
@@ -32,14 +32,7 @@
#include <string.h>
-#if defined(MBEDTLS_SELF_TEST)
-#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
-#else
-#include <stdio.h>
-#define mbedtls_printf printf
-#endif /* MBEDTLS_PLATFORM_C */
-#endif /* MBEDTLS_SELF_TEST */
#define SHA1_VALIDATE_RET(cond) \
MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_SHA1_BAD_INPUT_DATA )
diff --git a/thirdparty/mbedtls/library/sha256.c b/thirdparty/mbedtls/library/sha256.c
index db675efd1b..6f1306ee66 100644
--- a/thirdparty/mbedtls/library/sha256.c
+++ b/thirdparty/mbedtls/library/sha256.c
@@ -32,17 +32,7 @@
#include <string.h>
-#if defined(MBEDTLS_SELF_TEST)
-#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
-#else
-#include <stdio.h>
-#include <stdlib.h>
-#define mbedtls_printf printf
-#define mbedtls_calloc calloc
-#define mbedtls_free free
-#endif /* MBEDTLS_PLATFORM_C */
-#endif /* MBEDTLS_SELF_TEST */
#define SHA256_VALIDATE_RET(cond) \
MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_SHA256_BAD_INPUT_DATA )
diff --git a/thirdparty/mbedtls/library/sha512.c b/thirdparty/mbedtls/library/sha512.c
index 02a135ca92..1a6872c8aa 100644
--- a/thirdparty/mbedtls/library/sha512.c
+++ b/thirdparty/mbedtls/library/sha512.c
@@ -38,17 +38,7 @@
#include <string.h>
-#if defined(MBEDTLS_SELF_TEST)
-#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
-#else
-#include <stdio.h>
-#include <stdlib.h>
-#define mbedtls_printf printf
-#define mbedtls_calloc calloc
-#define mbedtls_free free
-#endif /* MBEDTLS_PLATFORM_C */
-#endif /* MBEDTLS_SELF_TEST */
#define SHA512_VALIDATE_RET(cond) \
MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_SHA512_BAD_INPUT_DATA )
@@ -428,9 +418,11 @@ int mbedtls_sha512_finish_ret( mbedtls_sha512_context *ctx,
sha512_put_uint64_be( ctx->state[4], output, 32 );
sha512_put_uint64_be( ctx->state[5], output, 40 );
+ int truncated = 0;
#if !defined(MBEDTLS_SHA512_NO_SHA384)
- if( ctx->is384 == 0 )
+ truncated = ctx->is384;
#endif
+ if( !truncated )
{
sha512_put_uint64_be( ctx->state[6], output, 48 );
sha512_put_uint64_be( ctx->state[7], output, 56 );
diff --git a/thirdparty/mbedtls/library/ssl_cache.c b/thirdparty/mbedtls/library/ssl_cache.c
index 32188cf3f6..7a600cad18 100644
--- a/thirdparty/mbedtls/library/ssl_cache.c
+++ b/thirdparty/mbedtls/library/ssl_cache.c
@@ -25,13 +25,7 @@
#if defined(MBEDTLS_SSL_CACHE_C)
-#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
-#else
-#include <stdlib.h>
-#define mbedtls_calloc calloc
-#define mbedtls_free free
-#endif
#include "mbedtls/ssl_cache.h"
#include "mbedtls/ssl_internal.h"
diff --git a/thirdparty/mbedtls/library/ssl_ciphersuites.c b/thirdparty/mbedtls/library/ssl_ciphersuites.c
index ceec77efb0..2bc8a9bba0 100644
--- a/thirdparty/mbedtls/library/ssl_ciphersuites.c
+++ b/thirdparty/mbedtls/library/ssl_ciphersuites.c
@@ -23,11 +23,7 @@
#if defined(MBEDTLS_SSL_TLS_C)
-#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
-#else
-#include <stdlib.h>
-#endif
#include "mbedtls/ssl_ciphersuites.h"
#include "mbedtls/ssl.h"
diff --git a/thirdparty/mbedtls/library/ssl_cli.c b/thirdparty/mbedtls/library/ssl_cli.c
index 72351c9757..b40ddb70b4 100644
--- a/thirdparty/mbedtls/library/ssl_cli.c
+++ b/thirdparty/mbedtls/library/ssl_cli.c
@@ -21,13 +21,7 @@
#if defined(MBEDTLS_SSL_CLI_C)
-#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
-#else
-#include <stdlib.h>
-#define mbedtls_calloc calloc
-#define mbedtls_free free
-#endif
#include "mbedtls/ssl.h"
#include "mbedtls/ssl_internal.h"
@@ -174,7 +168,7 @@ static int ssl_write_renegotiation_ext( mbedtls_ssl_context *ssl,
*olen = 0;
- /* We're always including an TLS_EMPTY_RENEGOTIATION_INFO_SCSV in the
+ /* We're always including a TLS_EMPTY_RENEGOTIATION_INFO_SCSV in the
* initial ClientHello, in which case also adding the renegotiation
* info extension is NOT RECOMMENDED as per RFC 5746 Section 3.4. */
if( ssl->renego_status != MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS )
@@ -1004,9 +998,12 @@ static int ssl_write_client_hello( mbedtls_ssl_context *ssl )
return( MBEDTLS_ERR_SSL_NO_RNG );
}
+ int renegotiating = 0;
#if defined(MBEDTLS_SSL_RENEGOTIATION)
- if( ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE )
+ if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE )
+ renegotiating = 1;
#endif
+ if( !renegotiating )
{
ssl->major_ver = ssl->conf->min_major_ver;
ssl->minor_ver = ssl->conf->min_minor_ver;
@@ -1092,9 +1089,7 @@ static int ssl_write_client_hello( mbedtls_ssl_context *ssl )
* RFC 5077 section 3.4: "When presenting a ticket, the client MAY
* generate and include a Session ID in the TLS ClientHello."
*/
-#if defined(MBEDTLS_SSL_RENEGOTIATION)
- if( ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE )
-#endif
+ if( !renegotiating )
{
if( ssl->session_negotiate->ticket != NULL &&
ssl->session_negotiate->ticket_len != 0 )
@@ -1209,9 +1204,7 @@ static int ssl_write_client_hello( mbedtls_ssl_context *ssl )
/*
* Add TLS_EMPTY_RENEGOTIATION_INFO_SCSV
*/
-#if defined(MBEDTLS_SSL_RENEGOTIATION)
- if( ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE )
-#endif
+ if( !renegotiating )
{
MBEDTLS_SSL_DEBUG_MSG( 3, ( "adding EMPTY_RENEGOTIATION_INFO_SCSV" ) );
MBEDTLS_SSL_CHK_BUF_PTR( p, end, 2 );
@@ -2062,6 +2055,30 @@ static int ssl_parse_hello_verify_request( mbedtls_ssl_context *ssl )
}
#endif /* MBEDTLS_SSL_PROTO_DTLS */
+static int is_compression_bad( mbedtls_ssl_context *ssl, unsigned char comp )
+{
+ int bad_comp = 0;
+
+ /* Suppress warnings in some configurations */
+ (void) ssl;
+#if defined(MBEDTLS_ZLIB_SUPPORT)
+ /* See comments in ssl_write_client_hello() */
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
+ comp != MBEDTLS_SSL_COMPRESS_NULL )
+ bad_comp = 1;
+#endif
+
+ if( comp != MBEDTLS_SSL_COMPRESS_NULL &&
+ comp != MBEDTLS_SSL_COMPRESS_DEFLATE )
+ bad_comp = 1;
+#else /* MBEDTLS_ZLIB_SUPPORT */
+ if( comp != MBEDTLS_SSL_COMPRESS_NULL )
+ bad_comp = 1;
+#endif/* MBEDTLS_ZLIB_SUPPORT */
+ return bad_comp;
+}
+
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_server_hello( mbedtls_ssl_context *ssl )
{
@@ -2070,9 +2087,6 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl )
size_t ext_len;
unsigned char *buf, *ext;
unsigned char comp;
-#if defined(MBEDTLS_ZLIB_SUPPORT)
- int accept_comp;
-#endif
#if defined(MBEDTLS_SSL_RENEGOTIATION)
int renegotiation_info_seen = 0;
#endif
@@ -2241,20 +2255,7 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl )
*/
comp = buf[37 + n];
-#if defined(MBEDTLS_ZLIB_SUPPORT)
- /* See comments in ssl_write_client_hello() */
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
- if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
- accept_comp = 0;
- else
-#endif
- accept_comp = 1;
-
- if( comp != MBEDTLS_SSL_COMPRESS_NULL &&
- ( comp != MBEDTLS_SSL_COMPRESS_DEFLATE || accept_comp == 0 ) )
-#else /* MBEDTLS_ZLIB_SUPPORT */
- if( comp != MBEDTLS_SSL_COMPRESS_NULL )
-#endif/* MBEDTLS_ZLIB_SUPPORT */
+ if( is_compression_bad( ssl, comp ) )
{
MBEDTLS_SSL_DEBUG_MSG( 1,
( "server hello, bad compression: %d", comp ) );
@@ -2687,7 +2688,7 @@ static int ssl_check_server_ecdh_params( const mbedtls_ssl_context *ssl )
grp_id = ssl->handshake->ecdh_ctx.grp.id;
#else
grp_id = ssl->handshake->ecdh_ctx.grp_id;
-#endif
+#endif /* MBEDTLS_ECDH_LEGACY_CONTEXT */
curve_info = mbedtls_ecp_curve_info_from_grp_id( grp_id );
if( curve_info == NULL )
@@ -2700,11 +2701,12 @@ static int ssl_check_server_ecdh_params( const mbedtls_ssl_context *ssl )
#if defined(MBEDTLS_ECP_C)
if( mbedtls_ssl_check_curve( ssl, grp_id ) != 0 )
+ return( -1 );
#else
if( ssl->handshake->ecdh_ctx.grp.nbits < 163 ||
ssl->handshake->ecdh_ctx.grp.nbits > 521 )
-#endif
return( -1 );
+#endif /* MBEDTLS_ECP_C */
MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx,
MBEDTLS_DEBUG_ECDH_QP );
@@ -2858,8 +2860,8 @@ static int ssl_parse_server_psk_hint( mbedtls_ssl_context *ssl,
}
/*
- * Note: we currently ignore the PKS identity hint, as we only allow one
- * PSK to be provisionned on the client. This could be changed later if
+ * Note: we currently ignore the PSK identity hint, as we only allow one
+ * PSK to be provisioned on the client. This could be changed later if
* someone needs that feature.
*/
*p += len;
@@ -3452,23 +3454,23 @@ start_processing:
#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)
if( ssl->handshake->ecrs_enabled )
rs_ctx = &ssl->handshake->ecrs_ctx.pk;
-#endif
+#endif /* MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED */
if( ( ret = mbedtls_pk_verify_restartable( peer_pk,
md_alg, hash, hashlen, p, sig_len, rs_ctx ) ) != 0 )
{
#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)
- if( ret != MBEDTLS_ERR_ECP_IN_PROGRESS )
-#endif
- mbedtls_ssl_send_alert_message(
- ssl,
- MBEDTLS_SSL_ALERT_LEVEL_FATAL,
- MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR );
- MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_verify", ret );
-#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)
if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
- ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS;
-#endif
+ {
+ MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_verify", ret );
+ return( MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS );
+ }
+#endif /* MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED */
+ mbedtls_ssl_send_alert_message(
+ ssl,
+ MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+ MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR );
+ MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_verify", ret );
return( ret );
}
diff --git a/thirdparty/mbedtls/library/ssl_cookie.c b/thirdparty/mbedtls/library/ssl_cookie.c
index 3781796b72..f12f28e849 100644
--- a/thirdparty/mbedtls/library/ssl_cookie.c
+++ b/thirdparty/mbedtls/library/ssl_cookie.c
@@ -25,12 +25,7 @@
#if defined(MBEDTLS_SSL_COOKIE_C)
-#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
-#else
-#define mbedtls_calloc calloc
-#define mbedtls_free free
-#endif
#include "mbedtls/ssl_cookie.h"
#include "mbedtls/ssl_internal.h"
diff --git a/thirdparty/mbedtls/library/ssl_msg.c b/thirdparty/mbedtls/library/ssl_msg.c
index e47c538888..d7bebe04d6 100644
--- a/thirdparty/mbedtls/library/ssl_msg.c
+++ b/thirdparty/mbedtls/library/ssl_msg.c
@@ -30,13 +30,7 @@
#if defined(MBEDTLS_SSL_TLS_C)
-#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
-#else
-#include <stdlib.h>
-#define mbedtls_calloc calloc
-#define mbedtls_free free
-#endif
#include "mbedtls/ssl.h"
#include "mbedtls/ssl_internal.h"
@@ -441,9 +435,12 @@ static void ssl_extract_add_data_from_record( unsigned char* add_data,
unsigned char *cur = add_data;
+ int is_tls13 = 0;
#if defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL)
- if( minor_ver != MBEDTLS_SSL_MINOR_VERSION_4 )
+ if( minor_ver == MBEDTLS_SSL_MINOR_VERSION_4 )
+ is_tls13 = 1;
#endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */
+ if( !is_tls13 )
{
((void) minor_ver);
memcpy( cur, rec->ctr, sizeof( rec->ctr ) );
@@ -1887,8 +1884,7 @@ int mbedtls_ssl_fetch_input( mbedtls_ssl_context *ssl, size_t nb_want )
if( ssl->f_recv == NULL && ssl->f_recv_timeout == NULL )
{
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "Bad usage of mbedtls_ssl_set_bio() "
- "or mbedtls_ssl_set_bio()" ) );
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "Bad usage of mbedtls_ssl_set_bio() " ) );
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
}
@@ -2103,8 +2099,7 @@ int mbedtls_ssl_flush_output( mbedtls_ssl_context *ssl )
if( ssl->f_send == NULL )
{
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "Bad usage of mbedtls_ssl_set_bio() "
- "or mbedtls_ssl_set_bio()" ) );
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "Bad usage of mbedtls_ssl_set_bio() " ) );
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
}
@@ -3950,8 +3945,8 @@ int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl,
if( ssl_record_is_in_progress( ssl ) == 0 )
{
+ int dtls_have_buffered = 0;
#if defined(MBEDTLS_SSL_PROTO_DTLS)
- int have_buffered = 0;
/* We only check for buffered messages if the
* current datagram is fully consumed. */
@@ -3959,11 +3954,11 @@ int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl,
ssl_next_record_is_in_datagram( ssl ) == 0 )
{
if( ssl_load_buffered_message( ssl ) == 0 )
- have_buffered = 1;
+ dtls_have_buffered = 1;
}
- if( have_buffered == 0 )
#endif /* MBEDTLS_SSL_PROTO_DTLS */
+ if( dtls_have_buffered == 0 )
{
ret = ssl_get_next_record( ssl );
if( ret == MBEDTLS_ERR_SSL_CONTINUE_PROCESSING )
@@ -4037,7 +4032,7 @@ static int ssl_load_buffered_message( mbedtls_ssl_context *ssl )
if( hs == NULL )
return( -1 );
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> ssl_load_buffered_messsage" ) );
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> ssl_load_buffered_message" ) );
if( ssl->state == MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC ||
ssl->state == MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC )
diff --git a/thirdparty/mbedtls/library/ssl_srv.c b/thirdparty/mbedtls/library/ssl_srv.c
index 2efb13cc33..0563c0b590 100644
--- a/thirdparty/mbedtls/library/ssl_srv.c
+++ b/thirdparty/mbedtls/library/ssl_srv.c
@@ -21,13 +21,7 @@
#if defined(MBEDTLS_SSL_SRV_C)
-#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
-#else
-#include <stdlib.h>
-#define mbedtls_calloc calloc
-#define mbedtls_free free
-#endif
#include "mbedtls/ssl.h"
#include "mbedtls/ssl_internal.h"
@@ -1460,6 +1454,7 @@ static int ssl_parse_client_hello( mbedtls_ssl_context *ssl )
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse client hello" ) );
+ int renegotiating = 0;
#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
read_record_header:
#endif
@@ -1469,8 +1464,10 @@ read_record_header:
* ClientHello, which doesn't use the same record layer format.
*/
#if defined(MBEDTLS_SSL_RENEGOTIATION)
- if( ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE )
+ if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE )
+ renegotiating = 1;
#endif
+ if( !renegotiating )
{
if( ( ret = mbedtls_ssl_fetch_input( ssl, 5 ) ) != 0 )
{
@@ -1483,9 +1480,12 @@ read_record_header:
buf = ssl->in_hdr;
#if defined(MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO)
+ int is_dtls = 0;
#if defined(MBEDTLS_SSL_PROTO_DTLS)
- if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_STREAM )
+ if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
+ is_dtls = 1;
#endif
+ if( !is_dtls )
if( ( buf[0] & 0x80 ) != 0 )
return( ssl_parse_client_hello_v2( ssl ) );
#endif
@@ -3903,8 +3903,14 @@ static int ssl_decrypt_encrypted_pms( mbedtls_ssl_context *ssl,
size_t peer_pmssize )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+ mbedtls_x509_crt *own_cert = mbedtls_ssl_own_cert( ssl );
+ if( own_cert == NULL ) {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no local certificate" ) );
+ return( MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE );
+ }
+ mbedtls_pk_context *public_key = &own_cert->pk;
mbedtls_pk_context *private_key = mbedtls_ssl_own_key( ssl );
- mbedtls_pk_context *public_key = &mbedtls_ssl_own_cert( ssl )->pk;
size_t len = mbedtls_pk_get_len( public_key );
#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
diff --git a/thirdparty/mbedtls/library/ssl_ticket.c b/thirdparty/mbedtls/library/ssl_ticket.c
index e0126cc9d1..8a57789f10 100644
--- a/thirdparty/mbedtls/library/ssl_ticket.c
+++ b/thirdparty/mbedtls/library/ssl_ticket.c
@@ -21,13 +21,7 @@
#if defined(MBEDTLS_SSL_TICKET_C)
-#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
-#else
-#include <stdlib.h>
-#define mbedtls_calloc calloc
-#define mbedtls_free free
-#endif
#include "mbedtls/ssl_internal.h"
#include "mbedtls/ssl_ticket.h"
@@ -152,27 +146,45 @@ int mbedtls_ssl_ticket_setup( mbedtls_ssl_ticket_context *ctx,
if( cipher_info->key_bitlen > 8 * MAX_KEY_BYTES )
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+ int do_mbedtls_cipher_setup = 1;
#if defined(MBEDTLS_USE_PSA_CRYPTO)
ret = mbedtls_cipher_setup_psa( &ctx->keys[0].ctx,
cipher_info, TICKET_AUTH_TAG_BYTES );
- if( ret != 0 && ret != MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE )
- return( ret );
- /* We don't yet expect to support all ciphers through PSA,
- * so allow fallback to ordinary mbedtls_cipher_setup(). */
- if( ret == MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE )
+
+ switch( ret )
+ {
+ case 0:
+ do_mbedtls_cipher_setup = 0;
+ break;
+ case MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE:
+ /* We don't yet expect to support all ciphers through PSA,
+ * so allow fallback to ordinary mbedtls_cipher_setup(). */
+ do_mbedtls_cipher_setup = 1;
+ break;
+ default:
+ return( ret );
+ }
#endif /* MBEDTLS_USE_PSA_CRYPTO */
- if( ( ret = mbedtls_cipher_setup( &ctx->keys[0].ctx, cipher_info ) ) != 0 )
- return( ret );
+ if( do_mbedtls_cipher_setup )
+ if( ( ret = mbedtls_cipher_setup( &ctx->keys[0].ctx, cipher_info ) )
+ != 0 )
+ return( ret );
+ do_mbedtls_cipher_setup = 1;
#if defined(MBEDTLS_USE_PSA_CRYPTO)
+ do_mbedtls_cipher_setup = 0;
+
ret = mbedtls_cipher_setup_psa( &ctx->keys[1].ctx,
cipher_info, TICKET_AUTH_TAG_BYTES );
if( ret != 0 && ret != MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE )
return( ret );
if( ret == MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE )
+ do_mbedtls_cipher_setup = 1;
#endif /* MBEDTLS_USE_PSA_CRYPTO */
- if( ( ret = mbedtls_cipher_setup( &ctx->keys[1].ctx, cipher_info ) ) != 0 )
- return( ret );
+ if( do_mbedtls_cipher_setup )
+ if( ( ret = mbedtls_cipher_setup( &ctx->keys[1].ctx, cipher_info ) )
+ != 0 )
+ return( ret );
if( ( ret = ssl_ticket_gen_key( ctx, 0 ) ) != 0 ||
( ret = ssl_ticket_gen_key( ctx, 1 ) ) != 0 )
diff --git a/thirdparty/mbedtls/library/ssl_tls.c b/thirdparty/mbedtls/library/ssl_tls.c
index 7badec51ae..70196a4861 100644
--- a/thirdparty/mbedtls/library/ssl_tls.c
+++ b/thirdparty/mbedtls/library/ssl_tls.c
@@ -29,13 +29,7 @@
#if defined(MBEDTLS_SSL_TLS_C)
-#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
-#else
-#include <stdlib.h>
-#define mbedtls_calloc calloc
-#define mbedtls_free free
-#endif
#include "mbedtls/ssl.h"
#include "mbedtls/ssl_internal.h"
@@ -766,7 +760,9 @@ static int tls_prf_generic( mbedtls_md_type_t md_type,
exit:
mbedtls_md_free( &md_ctx );
- mbedtls_platform_zeroize( tmp, tmp_len );
+ if ( tmp != NULL )
+ mbedtls_platform_zeroize( tmp, tmp_len );
+
mbedtls_platform_zeroize( h_i, sizeof( h_i ) );
mbedtls_free( tmp );
@@ -985,6 +981,7 @@ static int ssl_populate_transform( mbedtls_ssl_transform *transform,
#if defined(MBEDTLS_USE_PSA_CRYPTO)
int psa_fallthrough;
#endif /* MBEDTLS_USE_PSA_CRYPTO */
+ int do_mbedtls_cipher_setup;
unsigned char keyblk[256];
unsigned char *key1;
unsigned char *key2;
@@ -1363,6 +1360,7 @@ static int ssl_populate_transform( mbedtls_ssl_transform *transform,
}
#endif
+ do_mbedtls_cipher_setup = 1;
#if defined(MBEDTLS_USE_PSA_CRYPTO)
/* Only use PSA-based ciphers for TLS-1.2.
@@ -1398,15 +1396,18 @@ static int ssl_populate_transform( mbedtls_ssl_transform *transform,
psa_fallthrough = 1;
#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
- if( psa_fallthrough == 1 )
+ if( psa_fallthrough == 0 )
+ do_mbedtls_cipher_setup = 0;
#endif /* MBEDTLS_USE_PSA_CRYPTO */
- if( ( ret = mbedtls_cipher_setup( &transform->cipher_ctx_enc,
- cipher_info ) ) != 0 )
+ if( do_mbedtls_cipher_setup &&
+ ( ret = mbedtls_cipher_setup( &transform->cipher_ctx_enc,
+ cipher_info ) ) != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setup", ret );
goto end;
}
+ do_mbedtls_cipher_setup = 1;
#if defined(MBEDTLS_USE_PSA_CRYPTO)
/* Only use PSA-based ciphers for TLS-1.2.
* That's relevant at least for TLS-1.0, where
@@ -1441,10 +1442,12 @@ static int ssl_populate_transform( mbedtls_ssl_transform *transform,
psa_fallthrough = 1;
#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
- if( psa_fallthrough == 1 )
+ if( psa_fallthrough == 0 )
+ do_mbedtls_cipher_setup = 0;
#endif /* MBEDTLS_USE_PSA_CRYPTO */
- if( ( ret = mbedtls_cipher_setup( &transform->cipher_ctx_dec,
- cipher_info ) ) != 0 )
+ if( do_mbedtls_cipher_setup &&
+ ( ret = mbedtls_cipher_setup( &transform->cipher_ctx_dec,
+ cipher_info ) ) != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setup", ret );
goto end;
@@ -3411,7 +3414,7 @@ static void ssl_calc_finished_tls_sha384(
sha512.state, sizeof( sha512.state ) );
#endif
/* mbedtls_sha512_finish_ret's output parameter is declared as a
- * 64-byte buffer, but sice we're using SHA-384, we know that the
+ * 64-byte buffer, but since we're using SHA-384, we know that the
* output fits in 48 bytes. This is correct C, but GCC 11.1 warns
* about it.
*/
@@ -4089,9 +4092,12 @@ int mbedtls_ssl_session_reset_int( mbedtls_ssl_context *ssl, int partial )
memset( ssl->out_buf, 0, out_buf_len );
+ int clear_in_buf = 1;
#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C)
- if( partial == 0 )
+ if( partial != 0 )
+ clear_in_buf = 0;
#endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE && MBEDTLS_SSL_SRV_C */
+ if( clear_in_buf )
{
ssl->in_left = 0;
memset( ssl->in_buf, 0, in_buf_len );
@@ -4128,9 +4134,12 @@ int mbedtls_ssl_session_reset_int( mbedtls_ssl_context *ssl, int partial )
#endif
#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C)
+ int free_cli_id = 1;
#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE)
- if( partial == 0 )
+ if( partial != 0 )
+ free_cli_id = 0;
#endif
+ if( free_cli_id )
{
mbedtls_free( ssl->cli_id );
ssl->cli_id = NULL;
@@ -4471,7 +4480,7 @@ static void ssl_conf_remove_psk( mbedtls_ssl_config *conf )
conf->psk_opaque = MBEDTLS_SVC_KEY_ID_INIT;
}
/* This and the following branch should never
- * be taken simultaenously as we maintain the
+ * be taken simultaneously as we maintain the
* invariant that raw and opaque PSKs are never
* configured simultaneously. As a safeguard,
* though, `else` is omitted here. */
@@ -6335,7 +6344,7 @@ int mbedtls_ssl_context_save( mbedtls_ssl_context *ssl,
MBEDTLS_SSL_DEBUG_MSG( 1, ( "There is pending outgoing data" ) );
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
}
- /* Protocol must be DLTS, not TLS */
+ /* Protocol must be DTLS, not TLS */
if( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "Only DTLS is supported" ) );
@@ -6510,24 +6519,41 @@ int mbedtls_ssl_context_save( mbedtls_ssl_context *ssl,
* Helper to get TLS 1.2 PRF from ciphersuite
* (Duplicates bits of logic from ssl_set_handshake_prfs().)
*/
+#if defined(MBEDTLS_SHA256_C) || \
+ (defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384))
typedef int (*tls_prf_fn)( const unsigned char *secret, size_t slen,
const char *label,
const unsigned char *random, size_t rlen,
unsigned char *dstbuf, size_t dlen );
static tls_prf_fn ssl_tls12prf_from_cs( int ciphersuite_id )
{
-#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384)
const mbedtls_ssl_ciphersuite_t * const ciphersuite_info =
mbedtls_ssl_ciphersuite_from_id( ciphersuite_id );
+ if( ciphersuite_info == NULL )
+ return( NULL );
+
+#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384)
if( ciphersuite_info->mac == MBEDTLS_MD_SHA384 )
return( tls_prf_sha384 );
-#else
- (void) ciphersuite_id;
+ else
+#endif
+#if defined(MBEDTLS_SHA256_C)
+ {
+ if( ciphersuite_info->mac == MBEDTLS_MD_SHA256 )
+ return( tls_prf_sha256 );
+ }
#endif
- return( tls_prf_sha256 );
+#if !defined(MBEDTLS_SHA256_C) && \
+ (!defined(MBEDTLS_SHA512_C) || defined(MBEDTLS_SHA512_NO_SHA384))
+ (void) ciphersuite_info;
+#endif
+ return( NULL );
}
+#endif /* MBEDTLS_SHA256_C ||
+ (MBEDTLS_SHA512_C && !MBEDTLS_SHA512_NO_SHA384) */
+
/*
* Deserialize context, see mbedtls_ssl_context_save() for format.
*
@@ -6543,6 +6569,7 @@ static int ssl_context_load( mbedtls_ssl_context *ssl,
const unsigned char * const end = buf + len;
size_t session_len;
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+ tls_prf_fn prf_func = NULL;
/*
* The context should have been freshly setup or reset.
@@ -6630,6 +6657,10 @@ static int ssl_context_load( mbedtls_ssl_context *ssl,
ssl->transform_out = ssl->transform;
ssl->transform_negotiate = NULL;
+ prf_func = ssl_tls12prf_from_cs( ssl->session->ciphersuite );
+ if( prf_func == NULL )
+ return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+
/* Read random bytes and populate structure */
if( (size_t)( end - p ) < sizeof( ssl->transform->randbytes ) )
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
@@ -6648,7 +6679,7 @@ static int ssl_context_load( mbedtls_ssl_context *ssl,
#if defined(MBEDTLS_ZLIB_SUPPORT)
ssl->session->compression,
#endif
- ssl_tls12prf_from_cs( ssl->session->ciphersuite ),
+ prf_func,
p, /* currently pointing to randbytes */
MBEDTLS_SSL_MINOR_VERSION_3, /* (D)TLS 1.2 is forced */
ssl->conf->endpoint,
@@ -6921,7 +6952,7 @@ void mbedtls_ssl_free( mbedtls_ssl_context *ssl )
}
/*
- * Initialze mbedtls_ssl_config
+ * Initialize mbedtls_ssl_config
*/
void mbedtls_ssl_config_init( mbedtls_ssl_config *conf )
{
diff --git a/thirdparty/mbedtls/library/ssl_tls13_keys.c b/thirdparty/mbedtls/library/ssl_tls13_keys.c
index 3de6f03fb8..cc68773d3a 100644
--- a/thirdparty/mbedtls/library/ssl_tls13_keys.c
+++ b/thirdparty/mbedtls/library/ssl_tls13_keys.c
@@ -24,6 +24,7 @@
#include "mbedtls/hkdf.h"
#include "mbedtls/ssl_internal.h"
#include "ssl_tls13_keys.h"
+#include "psa/crypto_sizes.h"
#include <stdint.h>
#include <string.h>
@@ -31,6 +32,9 @@
#define MBEDTLS_SSL_TLS1_3_LABEL( name, string ) \
.name = string,
+#define TLS1_3_EVOLVE_INPUT_SIZE ( PSA_HASH_MAX_SIZE > PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE ) ? \
+ PSA_HASH_MAX_SIZE : PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE
+
struct mbedtls_ssl_tls1_3_labels_struct const mbedtls_ssl_tls1_3_labels =
{
/* This seems to work in C, despite the string literal being one
@@ -292,8 +296,8 @@ int mbedtls_ssl_tls1_3_evolve_secret(
{
int ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR;
size_t hlen, ilen;
- unsigned char tmp_secret[ MBEDTLS_MD_MAX_SIZE ] = { 0 };
- unsigned char tmp_input [ MBEDTLS_MD_MAX_SIZE ] = { 0 };
+ unsigned char tmp_secret[ PSA_MAC_MAX_SIZE ] = { 0 };
+ unsigned char tmp_input [ TLS1_3_EVOLVE_INPUT_SIZE ] = { 0 };
const mbedtls_md_info_t *md;
md = mbedtls_md_info_from_type( hash_alg );
diff --git a/thirdparty/mbedtls/library/timing.c b/thirdparty/mbedtls/library/timing.c
index 78bfa10cfb..151292e325 100644
--- a/thirdparty/mbedtls/library/timing.c
+++ b/thirdparty/mbedtls/library/timing.c
@@ -19,12 +19,7 @@
#include "common.h"
-#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
-#else
-#include <stdio.h>
-#define mbedtls_printf printf
-#endif
#if defined(MBEDTLS_TIMING_C)
@@ -269,7 +264,7 @@ static void TimerProc( void *TimerContext )
Sleep( alarmMs );
mbedtls_timing_alarmed = 1;
/* _endthread will be called implicitly on return
- * That ensures execution of thread funcition's epilogue */
+ * That ensures execution of thread function's epilogue */
}
void mbedtls_set_alarm( int seconds )
diff --git a/thirdparty/mbedtls/library/x509.c b/thirdparty/mbedtls/library/x509.c
index 3997ebd1f3..54c8666d23 100644
--- a/thirdparty/mbedtls/library/x509.c
+++ b/thirdparty/mbedtls/library/x509.c
@@ -43,16 +43,7 @@
#include "mbedtls/pem.h"
#endif
-#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
-#else
-#include <stdio.h>
-#include <stdlib.h>
-#define mbedtls_free free
-#define mbedtls_calloc calloc
-#define mbedtls_printf printf
-#define mbedtls_snprintf snprintf
-#endif
#if defined(MBEDTLS_HAVE_TIME)
#include "mbedtls/platform_time.h"
@@ -198,7 +189,7 @@ static int x509_get_hash_alg( const mbedtls_x509_buf *alg, mbedtls_md_type_t *md
*
* RFC 4055 (which defines use of RSASSA-PSS in PKIX) states that the value
* of trailerField MUST be 1, and PKCS#1 v2.2 doesn't even define any other
- * option. Enfore this at parsing time.
+ * option. Enforce this at parsing time.
*/
int mbedtls_x509_get_rsassa_pss_params( const mbedtls_x509_buf *params,
mbedtls_md_type_t *md_alg, mbedtls_md_type_t *mgf_md,
@@ -424,6 +415,11 @@ static int x509_get_attr_type_value( unsigned char **p,
* For the general case we still use a flat list, but we mark elements of the
* same set so that they are "merged" together in the functions that consume
* this list, eg mbedtls_x509_dn_gets().
+ *
+ * On success, this function may allocate a linked list starting at cur->next
+ * that must later be free'd by the caller using mbedtls_free(). In error
+ * cases, this function frees all allocated memory internally and the caller
+ * has no freeing responsibilities.
*/
int mbedtls_x509_get_name( unsigned char **p, const unsigned char *end,
mbedtls_x509_name *cur )
@@ -431,6 +427,8 @@ int mbedtls_x509_get_name( unsigned char **p, const unsigned char *end,
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t set_len;
const unsigned char *end_set;
+ mbedtls_x509_name *head = cur;
+ mbedtls_x509_name *prev, *allocated;
/* don't use recursion, we'd risk stack overflow if not optimized */
while( 1 )
@@ -440,14 +438,17 @@ int mbedtls_x509_get_name( unsigned char **p, const unsigned char *end,
*/
if( ( ret = mbedtls_asn1_get_tag( p, end, &set_len,
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET ) ) != 0 )
- return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_NAME, ret ) );
+ {
+ ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_NAME, ret );
+ goto error;
+ }
end_set = *p + set_len;
while( 1 )
{
if( ( ret = x509_get_attr_type_value( p, end_set, cur ) ) != 0 )
- return( ret );
+ goto error;
if( *p == end_set )
break;
@@ -458,7 +459,10 @@ int mbedtls_x509_get_name( unsigned char **p, const unsigned char *end,
cur->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_name ) );
if( cur->next == NULL )
- return( MBEDTLS_ERR_X509_ALLOC_FAILED );
+ {
+ ret = MBEDTLS_ERR_X509_ALLOC_FAILED;
+ goto error;
+ }
cur = cur->next;
}
@@ -472,10 +476,30 @@ int mbedtls_x509_get_name( unsigned char **p, const unsigned char *end,
cur->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_name ) );
if( cur->next == NULL )
- return( MBEDTLS_ERR_X509_ALLOC_FAILED );
+ {
+ ret = MBEDTLS_ERR_X509_ALLOC_FAILED;
+ goto error;
+ }
cur = cur->next;
}
+
+error:
+ /* Skip the first element as we did not allocate it */
+ allocated = head->next;
+
+ while( allocated != NULL )
+ {
+ prev = allocated;
+ allocated = allocated->next;
+
+ mbedtls_platform_zeroize( prev, sizeof( *prev ) );
+ mbedtls_free( prev );
+ }
+
+ mbedtls_platform_zeroize( head, sizeof( *head ) );
+
+ return( ret );
}
static int x509_parse_int( unsigned char **p, size_t n, int *res )
diff --git a/thirdparty/mbedtls/library/x509_crl.c b/thirdparty/mbedtls/library/x509_crl.c
index d2d8042029..b943a8d6da 100644
--- a/thirdparty/mbedtls/library/x509_crl.c
+++ b/thirdparty/mbedtls/library/x509_crl.c
@@ -1,5 +1,5 @@
/*
- * X.509 Certidicate Revocation List (CRL) parsing
+ * X.509 Certificate Revocation List (CRL) parsing
*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0
@@ -42,15 +42,7 @@
#include "mbedtls/pem.h"
#endif
-#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
-#else
-#include <stdlib.h>
-#include <stdio.h>
-#define mbedtls_free free
-#define mbedtls_calloc calloc
-#define mbedtls_snprintf snprintf
-#endif
#if defined(MBEDTLS_HAVE_TIME)
#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
diff --git a/thirdparty/mbedtls/library/x509_crt.c b/thirdparty/mbedtls/library/x509_crt.c
index 96477e4c9d..4361f43ed0 100644
--- a/thirdparty/mbedtls/library/x509_crt.c
+++ b/thirdparty/mbedtls/library/x509_crt.c
@@ -49,15 +49,7 @@
#include "mbedtls/psa_util.h"
#endif
-#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
-#else
-#include <stdio.h>
-#include <stdlib.h>
-#define mbedtls_free free
-#define mbedtls_calloc calloc
-#define mbedtls_snprintf snprintf
-#endif
#if defined(MBEDTLS_THREADING_C)
#include "mbedtls/threading.h"
@@ -90,6 +82,7 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
+#include <errno.h>
#endif /* !_WIN32 || EFIX64 || EFI32 */
#endif
@@ -1278,9 +1271,12 @@ static int x509_crt_parse_der_core( mbedtls_x509_crt *crt,
}
}
+ int extensions_allowed = 1;
#if !defined(MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3)
- if( crt->version == 3 )
+ if( crt->version != 3 )
+ extensions_allowed = 0;
#endif
+ if( extensions_allowed )
{
ret = x509_get_crt_ext( &p, end, crt, cb, p_ctx );
if( ret != 0 )
@@ -1668,8 +1664,22 @@ cleanup:
}
else if( stat( entry_name, &sb ) == -1 )
{
- ret = MBEDTLS_ERR_X509_FILE_IO_ERROR;
- goto cleanup;
+ if( errno == ENOENT )
+ {
+ /* Broken symbolic link - ignore this entry.
+ stat(2) will return this error for either (a) a dangling
+ symlink or (b) a missing file.
+ Given that we have just obtained the filename from readdir,
+ assume that it does exist and therefore treat this as a
+ dangling symlink. */
+ continue;
+ }
+ else
+ {
+ /* Some other file error; report the error. */
+ ret = MBEDTLS_ERR_X509_FILE_IO_ERROR;
+ goto cleanup;
+ }
}
if( !S_ISREG( sb.st_mode ) )
@@ -1798,6 +1808,7 @@ static int x509_info_subject_alt_name( char **buf, size_t *size,
const char *prefix )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+ size_t i;
size_t n = *size;
char *p = *buf;
const mbedtls_x509_sequence *cur = subject_alt_name;
@@ -1850,18 +1861,11 @@ static int x509_info_subject_alt_name( char **buf, size_t *size,
ret = mbedtls_snprintf( p, n, "\n%s hardware serial number : ", prefix );
MBEDTLS_X509_SAFE_SNPRINTF;
- if( other_name->value.hardware_module_name.val.len >= n )
+ for( i = 0; i < other_name->value.hardware_module_name.val.len; i++ )
{
- *p = '\0';
- return( MBEDTLS_ERR_X509_BUFFER_TOO_SMALL );
+ ret = mbedtls_snprintf( p, n, "%02X", other_name->value.hardware_module_name.val.p[i] );
+ MBEDTLS_X509_SAFE_SNPRINTF;
}
-
- memcpy( p, other_name->value.hardware_module_name.val.p,
- other_name->value.hardware_module_name.val.len );
- p += other_name->value.hardware_module_name.val.len;
-
- n -= other_name->value.hardware_module_name.val.len;
-
}/* MBEDTLS_OID_ON_HW_MODULE_NAME */
}
break;
diff --git a/thirdparty/mbedtls/library/x509_csr.c b/thirdparty/mbedtls/library/x509_csr.c
index e259410d07..1a22b77086 100644
--- a/thirdparty/mbedtls/library/x509_csr.c
+++ b/thirdparty/mbedtls/library/x509_csr.c
@@ -42,15 +42,7 @@
#include "mbedtls/pem.h"
#endif
-#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
-#else
-#include <stdlib.h>
-#include <stdio.h>
-#define mbedtls_free free
-#define mbedtls_calloc calloc
-#define mbedtls_snprintf snprintf
-#endif
#if defined(MBEDTLS_FS_IO) || defined(EFIX64) || defined(EFI32)
#include <stdio.h>
diff --git a/thirdparty/mbedtls/library/x509write_csr.c b/thirdparty/mbedtls/library/x509write_csr.c
index afda950341..707dd001f0 100644
--- a/thirdparty/mbedtls/library/x509write_csr.c
+++ b/thirdparty/mbedtls/library/x509write_csr.c
@@ -44,13 +44,7 @@
#include "mbedtls/pem.h"
#endif
-#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
-#else
-#include <stdlib.h>
-#define mbedtls_calloc calloc
-#define mbedtls_free free
-#endif
void mbedtls_x509write_csr_init( mbedtls_x509write_csr *ctx )
{
diff --git a/thirdparty/mbedtls/library/xtea.c b/thirdparty/mbedtls/library/xtea.c
index 77f6cb6f67..28e6972aa8 100644
--- a/thirdparty/mbedtls/library/xtea.c
+++ b/thirdparty/mbedtls/library/xtea.c
@@ -1,5 +1,5 @@
/*
- * An 32-bit implementation of the XTEA algorithm
+ * A 32-bit implementation of the XTEA algorithm
*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0
@@ -26,14 +26,7 @@
#include <string.h>
-#if defined(MBEDTLS_SELF_TEST)
-#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
-#else
-#include <stdio.h>
-#define mbedtls_printf printf
-#endif /* MBEDTLS_PLATFORM_C */
-#endif /* MBEDTLS_SELF_TEST */
#if !defined(MBEDTLS_XTEA_ALT)
diff --git a/thirdparty/mbedtls/patches/1453.diff b/thirdparty/mbedtls/patches/1453.diff
index b1c9c43ed2..4a7ca1570b 100644
--- a/thirdparty/mbedtls/patches/1453.diff
+++ b/thirdparty/mbedtls/patches/1453.diff
@@ -1,8 +1,8 @@
-diff --git a/library/entropy_poll.c b/library/entropy_poll.c
-index 4556f88a5..ba56b70f7 100644
---- a/library/entropy_poll.c
-+++ b/library/entropy_poll.c
-@@ -61,28 +61,43 @@
+diff --git a/thirdparty/mbedtls/library/entropy_poll.c b/thirdparty/mbedtls/library/entropy_poll.c
+index a858c1892b..69ac29e4f7 100644
+--- a/thirdparty/mbedtls/library/entropy_poll.c
++++ b/thirdparty/mbedtls/library/entropy_poll.c
+@@ -54,28 +54,43 @@
#define _WIN32_WINNT 0x0400
#endif
#include <windows.h>
@@ -53,12 +53,12 @@ index 4556f88a5..ba56b70f7 100644
*olen = len;
return( 0 );
-diff --git a/library/x509_crt.c b/library/x509_crt.c
-index 76558342e..35a134950 100644
---- a/library/x509_crt.c
-+++ b/library/x509_crt.c
-@@ -65,6 +65,19 @@
-
+diff --git a/thirdparty/mbedtls/library/x509_crt.c b/thirdparty/mbedtls/library/x509_crt.c
+index def1414eca..4361f43ed0 100644
+--- a/thirdparty/mbedtls/library/x509_crt.c
++++ b/thirdparty/mbedtls/library/x509_crt.c
+@@ -58,6 +58,19 @@
+ #if defined(MBEDTLS_HAVE_TIME)
#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
#include <windows.h>
+#if defined(_MSC_VER) && _MSC_VER <= 1600
@@ -77,7 +77,7 @@ index 76558342e..35a134950 100644
#else
#include <time.h>
#endif
-@@ -1278,6 +1291,7 @@ int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path )
+@@ -1549,6 +1562,7 @@ int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path )
char filename[MAX_PATH];
char *p;
size_t len = strlen( path );
@@ -85,7 +85,7 @@ index 76558342e..35a134950 100644
WIN32_FIND_DATAW file_data;
HANDLE hFind;
-@@ -1292,7 +1306,18 @@ int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path )
+@@ -1563,7 +1577,18 @@ int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path )
p = filename + len;
filename[len++] = '*';
@@ -105,7 +105,7 @@ index 76558342e..35a134950 100644
MAX_PATH - 3 );
if( w_ret == 0 )
return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
-@@ -1309,8 +1334,11 @@ int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path )
+@@ -1580,8 +1605,11 @@ int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path )
if( file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
continue;
diff --git a/thirdparty/mbedtls/patches/windows-arm64-hardclock.diff b/thirdparty/mbedtls/patches/windows-arm64-hardclock.diff
new file mode 100644
index 0000000000..c7c5a7e282
--- /dev/null
+++ b/thirdparty/mbedtls/patches/windows-arm64-hardclock.diff
@@ -0,0 +1,16 @@
+diff --git a/thirdparty/mbedtls/library/timing.c b/thirdparty/mbedtls/library/timing.c
+index 6c14a4fd01..151292e325 100644
+--- a/thirdparty/mbedtls/library/timing.c
++++ b/thirdparty/mbedtls/library/timing.c
+@@ -190,8 +190,10 @@ unsigned long mbedtls_timing_hardclock( void )
+ #endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM &&
+ __GNUC__ && __ia64__ */
+
+-#if !defined(HAVE_HARDCLOCK) && defined(_MSC_VER) && \
++// -- GODOT start --
++#if !defined(HAVE_HARDCLOCK) && defined(_WIN32) && \
+ !defined(EFIX64) && !defined(EFI32)
++// -- GODOT end --
+
+ #define HAVE_HARDCLOCK
+
diff --git a/thirdparty/miniupnpc/LICENSE b/thirdparty/miniupnpc/LICENSE
index fe9118c07e..67ff3bb627 100644
--- a/thirdparty/miniupnpc/LICENSE
+++ b/thirdparty/miniupnpc/LICENSE
@@ -1,26 +1,29 @@
-MiniUPnP Project
-Copyright (c) 2005-2020, Thomas BERNARD
+BSD 3-Clause License
+
+Copyright (c) 2005-2022, Thomas BERNARD
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
- * Redistributions of source code must retain the above copyright notice,
- this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
- * The name of the author may not be used to endorse or promote products
- derived from this software without specific prior written permission.
+1. Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/thirdparty/miniupnpc/include/miniupnpc.h b/thirdparty/miniupnpc/include/miniupnpc.h
index a10bd950a8..75fb8b702d 100644
--- a/thirdparty/miniupnpc/include/miniupnpc.h
+++ b/thirdparty/miniupnpc/include/miniupnpc.h
@@ -1,9 +1,9 @@
-/* $Id: miniupnpc.h,v 1.59 2021/09/28 21:39:17 nanard Exp $ */
+/* $Id: miniupnpc.h,v 1.61 2022/10/21 21:15:02 nanard Exp $ */
/* vim: tabstop=4 shiftwidth=4 noexpandtab
* Project: miniupnp
- * http://miniupnp.free.fr/
+ * http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/
* Author: Thomas Bernard
- * Copyright (c) 2005-2021 Thomas Bernard
+ * Copyright (c) 2005-2022 Thomas Bernard
* This software is subjects to the conditions detailed
* in the LICENCE file provided within this distribution */
#ifndef MINIUPNPC_H_INCLUDED
@@ -20,7 +20,7 @@
#define UPNPDISCOVER_MEMORY_ERROR (-102)
/* versions : */
-#define MINIUPNPC_VERSION "2.2.3"
+#define MINIUPNPC_VERSION "2.2.4"
#define MINIUPNPC_API_VERSION 17
/* Source port:
diff --git a/thirdparty/miniupnpc/src/miniupnpcstrings.h b/thirdparty/miniupnpc/src/miniupnpcstrings.h
index eefbc8dbdd..25abc1016e 100644
--- a/thirdparty/miniupnpc/src/miniupnpcstrings.h
+++ b/thirdparty/miniupnpc/src/miniupnpcstrings.h
@@ -4,7 +4,7 @@
#include "core/version.h"
#define OS_STRING VERSION_NAME "/1.0"
-#define MINIUPNPC_VERSION_STRING "2.2.3"
+#define MINIUPNPC_VERSION_STRING "2.2.4"
#if 0
/* according to "UPnP Device Architecture 1.0" */
diff --git a/thirdparty/miniupnpc/src/minixml.c b/thirdparty/miniupnpc/src/minixml.c
index ed2d3c759c..935ec443e7 100644
--- a/thirdparty/miniupnpc/src/minixml.c
+++ b/thirdparty/miniupnpc/src/minixml.c
@@ -1,4 +1,4 @@
-/* $Id: minixml.c,v 1.10 2012/03/05 19:42:47 nanard Exp $ */
+/* $Id: minixml.c,v 1.12 2017/12/12 11:17:40 nanard Exp $ */
/* vim: tabstop=4 shiftwidth=4 noexpandtab
* minixml.c : the minimum size a xml parser can be ! */
/* Project : miniupnp
diff --git a/thirdparty/openxr/include/openxr/openxr.h b/thirdparty/openxr/include/openxr/openxr.h
index 6f9b71aa68..3663f9f14d 100644
--- a/thirdparty/openxr/include/openxr/openxr.h
+++ b/thirdparty/openxr/include/openxr/openxr.h
@@ -25,7 +25,7 @@ extern "C" {
((((major) & 0xffffULL) << 48) | (((minor) & 0xffffULL) << 32) | ((patch) & 0xffffffffULL))
// OpenXR current version number.
-#define XR_CURRENT_API_VERSION XR_MAKE_VERSION(1, 0, 25)
+#define XR_CURRENT_API_VERSION XR_MAKE_VERSION(1, 0, 26)
#define XR_VERSION_MAJOR(version) (uint16_t)(((uint64_t)(version) >> 48)& 0xffffULL)
#define XR_VERSION_MINOR(version) (uint16_t)(((uint64_t)(version) >> 32) & 0xffffULL)
@@ -450,6 +450,15 @@ typedef enum XrStructureType {
XR_TYPE_VULKAN_SWAPCHAIN_CREATE_INFO_META = 1000227000,
XR_TYPE_PERFORMANCE_METRICS_STATE_META = 1000232001,
XR_TYPE_PERFORMANCE_METRICS_COUNTER_META = 1000232002,
+ XR_TYPE_SYSTEM_HEADSET_ID_PROPERTIES_META = 1000245000,
+ XR_TYPE_PASSTHROUGH_CREATE_INFO_HTC = 1000317001,
+ XR_TYPE_PASSTHROUGH_COLOR_HTC = 1000317002,
+ XR_TYPE_PASSTHROUGH_MESH_TRANSFORM_INFO_HTC = 1000317003,
+ XR_TYPE_COMPOSITION_LAYER_PASSTHROUGH_HTC = 1000317004,
+ XR_TYPE_FOVEATION_APPLY_INFO_HTC = 1000318000,
+ XR_TYPE_FOVEATION_DYNAMIC_MODE_INFO_HTC = 1000318001,
+ XR_TYPE_FOVEATION_CUSTOM_MODE_INFO_HTC = 1000318002,
+ XR_TYPE_ACTIVE_ACTION_SET_PRIORITIES_EXT = 1000373000,
XR_TYPE_GRAPHICS_BINDING_VULKAN2_KHR = XR_TYPE_GRAPHICS_BINDING_VULKAN_KHR,
XR_TYPE_SWAPCHAIN_IMAGE_VULKAN2_KHR = XR_TYPE_SWAPCHAIN_IMAGE_VULKAN_KHR,
XR_TYPE_GRAPHICS_REQUIREMENTS_VULKAN2_KHR = XR_TYPE_GRAPHICS_REQUIREMENTS_VULKAN_KHR,
@@ -536,6 +545,7 @@ typedef enum XrObjectType {
XR_OBJECT_TYPE_PASSTHROUGH_LAYER_FB = 1000118002,
XR_OBJECT_TYPE_GEOMETRY_INSTANCE_FB = 1000118004,
XR_OBJECT_TYPE_SPATIAL_ANCHOR_STORE_CONNECTION_MSFT = 1000142000,
+ XR_OBJECT_TYPE_PASSTHROUGH_HTC = 1000317000,
XR_OBJECT_TYPE_MAX_ENUM = 0x7FFFFFFF
} XrObjectType;
typedef XrFlags64 XrInstanceCreateFlags;
@@ -1631,7 +1641,7 @@ typedef struct XrBindingModificationsKHR {
#define XR_EXT_performance_settings 1
-#define XR_EXT_performance_settings_SPEC_VERSION 3
+#define XR_EXT_performance_settings_SPEC_VERSION 4
#define XR_EXT_PERFORMANCE_SETTINGS_EXTENSION_NAME "XR_EXT_performance_settings"
typedef enum XrPerfSettingsDomainEXT {
@@ -3007,7 +3017,7 @@ XRAPI_ATTR XrResult XRAPI_CALL xrRequestDisplayRefreshRateFB(
#define XR_HTCX_vive_tracker_interaction 1
-#define XR_HTCX_vive_tracker_interaction_SPEC_VERSION 1
+#define XR_HTCX_vive_tracker_interaction_SPEC_VERSION 2
#define XR_HTCX_VIVE_TRACKER_INTERACTION_EXTENSION_NAME "XR_HTCX_vive_tracker_interaction"
typedef struct XrViveTrackerPathsHTCX {
XrStructureType type;
@@ -3043,7 +3053,7 @@ XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateViveTrackerPathsHTCX(
#define XR_FACIAL_EXPRESSION_LIP_COUNT_HTC 37
XR_DEFINE_HANDLE(XrFacialTrackerHTC)
-#define XR_HTC_facial_tracking_SPEC_VERSION 1
+#define XR_HTC_facial_tracking_SPEC_VERSION 2
#define XR_HTC_FACIAL_TRACKING_EXTENSION_NAME "XR_HTC_facial_tracking"
typedef enum XrEyeExpressionHTC {
@@ -4508,7 +4518,7 @@ typedef struct XrCompositionLayerSettingsFB {
#define XR_META_performance_metrics 1
-#define XR_META_performance_metrics_SPEC_VERSION 1
+#define XR_META_performance_metrics_SPEC_VERSION 2
#define XR_META_PERFORMANCE_METRICS_EXTENSION_NAME "XR_META_performance_metrics"
typedef enum XrPerformanceMetricsCounterUnitMETA {
@@ -4570,10 +4580,167 @@ XRAPI_ATTR XrResult XRAPI_CALL xrQueryPerformanceMetricsCounterMETA(
#endif /* !XR_NO_PROTOTYPES */
+#define XR_META_headset_id 1
+#define XR_META_headset_id_SPEC_VERSION 1
+#define XR_META_HEADSET_ID_EXTENSION_NAME "XR_META_headset_id"
+// XrSystemHeadsetIdPropertiesMETA extends XrSystemProperties
+typedef struct XrSystemHeadsetIdPropertiesMETA {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ XrUuidEXT id;
+} XrSystemHeadsetIdPropertiesMETA;
+
+
+
#define XR_EXT_uuid 1
#define XR_EXT_uuid_SPEC_VERSION 1
#define XR_EXT_UUID_EXTENSION_NAME "XR_EXT_uuid"
+
+#define XR_HTC_passthrough 1
+XR_DEFINE_HANDLE(XrPassthroughHTC)
+#define XR_HTC_passthrough_SPEC_VERSION 1
+#define XR_HTC_PASSTHROUGH_EXTENSION_NAME "XR_HTC_passthrough"
+
+typedef enum XrPassthroughFormHTC {
+ XR_PASSTHROUGH_FORM_PLANAR_HTC = 0,
+ XR_PASSTHROUGH_FORM_PROJECTED_HTC = 1,
+ XR_PASSTHROUGH_FORM_MAX_ENUM_HTC = 0x7FFFFFFF
+} XrPassthroughFormHTC;
+typedef struct XrPassthroughCreateInfoHTC {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrPassthroughFormHTC form;
+} XrPassthroughCreateInfoHTC;
+
+typedef struct XrPassthroughColorHTC {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ float alpha;
+} XrPassthroughColorHTC;
+
+// XrPassthroughMeshTransformInfoHTC extends XrCompositionLayerPassthroughHTC
+typedef struct XrPassthroughMeshTransformInfoHTC {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ uint32_t vertexCount;
+ const XrVector3f* vertices;
+ uint32_t indexCount;
+ const uint32_t* indices;
+ XrSpace baseSpace;
+ XrTime time;
+ XrPosef pose;
+ XrVector3f scale;
+} XrPassthroughMeshTransformInfoHTC;
+
+typedef struct XrCompositionLayerPassthroughHTC {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrCompositionLayerFlags layerFlags;
+ XrSpace space;
+ XrPassthroughHTC passthrough;
+ XrPassthroughColorHTC color;
+} XrCompositionLayerPassthroughHTC;
+
+typedef XrResult (XRAPI_PTR *PFN_xrCreatePassthroughHTC)(XrSession session, const XrPassthroughCreateInfoHTC* createInfo, XrPassthroughHTC* passthrough);
+typedef XrResult (XRAPI_PTR *PFN_xrDestroyPassthroughHTC)(XrPassthroughHTC passthrough);
+
+#ifndef XR_NO_PROTOTYPES
+#ifdef XR_EXTENSION_PROTOTYPES
+XRAPI_ATTR XrResult XRAPI_CALL xrCreatePassthroughHTC(
+ XrSession session,
+ const XrPassthroughCreateInfoHTC* createInfo,
+ XrPassthroughHTC* passthrough);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrDestroyPassthroughHTC(
+ XrPassthroughHTC passthrough);
+#endif /* XR_EXTENSION_PROTOTYPES */
+#endif /* !XR_NO_PROTOTYPES */
+
+
+#define XR_HTC_foveation 1
+#define XR_HTC_foveation_SPEC_VERSION 1
+#define XR_HTC_FOVEATION_EXTENSION_NAME "XR_HTC_foveation"
+
+typedef enum XrFoveationModeHTC {
+ XR_FOVEATION_MODE_DISABLE_HTC = 0,
+ XR_FOVEATION_MODE_FIXED_HTC = 1,
+ XR_FOVEATION_MODE_DYNAMIC_HTC = 2,
+ XR_FOVEATION_MODE_CUSTOM_HTC = 3,
+ XR_FOVEATION_MODE_MAX_ENUM_HTC = 0x7FFFFFFF
+} XrFoveationModeHTC;
+
+typedef enum XrFoveationLevelHTC {
+ XR_FOVEATION_LEVEL_NONE_HTC = 0,
+ XR_FOVEATION_LEVEL_LOW_HTC = 1,
+ XR_FOVEATION_LEVEL_MEDIUM_HTC = 2,
+ XR_FOVEATION_LEVEL_HIGH_HTC = 3,
+ XR_FOVEATION_LEVEL_MAX_ENUM_HTC = 0x7FFFFFFF
+} XrFoveationLevelHTC;
+typedef XrFlags64 XrFoveationDynamicFlagsHTC;
+
+// Flag bits for XrFoveationDynamicFlagsHTC
+static const XrFoveationDynamicFlagsHTC XR_FOVEATION_DYNAMIC_LEVEL_ENABLED_BIT_HTC = 0x00000001;
+static const XrFoveationDynamicFlagsHTC XR_FOVEATION_DYNAMIC_CLEAR_FOV_ENABLED_BIT_HTC = 0x00000002;
+static const XrFoveationDynamicFlagsHTC XR_FOVEATION_DYNAMIC_FOCAL_CENTER_OFFSET_ENABLED_BIT_HTC = 0x00000004;
+
+typedef struct XrFoveationApplyInfoHTC {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrFoveationModeHTC mode;
+ uint32_t subImageCount;
+ XrSwapchainSubImage* subImages;
+} XrFoveationApplyInfoHTC;
+
+typedef struct XrFoveationConfigurationHTC {
+ XrFoveationLevelHTC level;
+ float clearFovDegree;
+ XrVector2f focalCenterOffset;
+} XrFoveationConfigurationHTC;
+
+// XrFoveationDynamicModeInfoHTC extends XrFoveationApplyInfoHTC
+typedef struct XrFoveationDynamicModeInfoHTC {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrFoveationDynamicFlagsHTC dynamicFlags;
+} XrFoveationDynamicModeInfoHTC;
+
+// XrFoveationCustomModeInfoHTC extends XrFoveationApplyInfoHTC
+typedef struct XrFoveationCustomModeInfoHTC {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ uint32_t configCount;
+ const XrFoveationConfigurationHTC* configs;
+} XrFoveationCustomModeInfoHTC;
+
+typedef XrResult (XRAPI_PTR *PFN_xrApplyFoveationHTC)(XrSession session, const XrFoveationApplyInfoHTC* applyInfo);
+
+#ifndef XR_NO_PROTOTYPES
+#ifdef XR_EXTENSION_PROTOTYPES
+XRAPI_ATTR XrResult XRAPI_CALL xrApplyFoveationHTC(
+ XrSession session,
+ const XrFoveationApplyInfoHTC* applyInfo);
+#endif /* XR_EXTENSION_PROTOTYPES */
+#endif /* !XR_NO_PROTOTYPES */
+
+
+#define XR_EXT_active_action_set_priority 1
+#define XR_EXT_active_action_set_priority_SPEC_VERSION 1
+#define XR_EXT_ACTIVE_ACTION_SET_PRIORITY_EXTENSION_NAME "XR_EXT_active_action_set_priority"
+typedef struct XrActiveActionSetPriorityEXT {
+ XrActionSet actionSet;
+ uint32_t priorityOverride;
+} XrActiveActionSetPriorityEXT;
+
+// XrActiveActionSetPrioritiesEXT extends XrActionsSyncInfo
+typedef struct XrActiveActionSetPrioritiesEXT {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ uint32_t actionSetPriorityCount;
+ const XrActiveActionSetPriorityEXT* actionSetPriorities;
+} XrActiveActionSetPrioritiesEXT;
+
+
#ifdef __cplusplus
}
#endif
diff --git a/thirdparty/openxr/include/openxr/openxr_reflection.h b/thirdparty/openxr/include/openxr/openxr_reflection.h
index ac6f452377..1a873c1770 100644
--- a/thirdparty/openxr/include/openxr/openxr_reflection.h
+++ b/thirdparty/openxr/include/openxr/openxr_reflection.h
@@ -351,6 +351,15 @@ XR_ENUM_STR(XrResult);
_(XR_TYPE_VULKAN_SWAPCHAIN_CREATE_INFO_META, 1000227000) \
_(XR_TYPE_PERFORMANCE_METRICS_STATE_META, 1000232001) \
_(XR_TYPE_PERFORMANCE_METRICS_COUNTER_META, 1000232002) \
+ _(XR_TYPE_SYSTEM_HEADSET_ID_PROPERTIES_META, 1000245000) \
+ _(XR_TYPE_PASSTHROUGH_CREATE_INFO_HTC, 1000317001) \
+ _(XR_TYPE_PASSTHROUGH_COLOR_HTC, 1000317002) \
+ _(XR_TYPE_PASSTHROUGH_MESH_TRANSFORM_INFO_HTC, 1000317003) \
+ _(XR_TYPE_COMPOSITION_LAYER_PASSTHROUGH_HTC, 1000317004) \
+ _(XR_TYPE_FOVEATION_APPLY_INFO_HTC, 1000318000) \
+ _(XR_TYPE_FOVEATION_DYNAMIC_MODE_INFO_HTC, 1000318001) \
+ _(XR_TYPE_FOVEATION_CUSTOM_MODE_INFO_HTC, 1000318002) \
+ _(XR_TYPE_ACTIVE_ACTION_SET_PRIORITIES_EXT, 1000373000) \
_(XR_STRUCTURE_TYPE_MAX_ENUM, 0x7FFFFFFF)
#define XR_LIST_ENUM_XrFormFactor(_) \
@@ -426,6 +435,7 @@ XR_ENUM_STR(XrResult);
_(XR_OBJECT_TYPE_PASSTHROUGH_LAYER_FB, 1000118002) \
_(XR_OBJECT_TYPE_GEOMETRY_INSTANCE_FB, 1000118004) \
_(XR_OBJECT_TYPE_SPATIAL_ANCHOR_STORE_CONNECTION_MSFT, 1000142000) \
+ _(XR_OBJECT_TYPE_PASSTHROUGH_HTC, 1000317000) \
_(XR_OBJECT_TYPE_MAX_ENUM, 0x7FFFFFFF)
#define XR_LIST_ENUM_XrAndroidThreadTypeKHR(_) \
@@ -748,6 +758,25 @@ XR_ENUM_STR(XrResult);
_(XR_PERFORMANCE_METRICS_COUNTER_UNIT_HERTZ_META, 4) \
_(XR_PERFORMANCE_METRICS_COUNTER_UNIT_MAX_ENUM_META, 0x7FFFFFFF)
+#define XR_LIST_ENUM_XrPassthroughFormHTC(_) \
+ _(XR_PASSTHROUGH_FORM_PLANAR_HTC, 0) \
+ _(XR_PASSTHROUGH_FORM_PROJECTED_HTC, 1) \
+ _(XR_PASSTHROUGH_FORM_MAX_ENUM_HTC, 0x7FFFFFFF)
+
+#define XR_LIST_ENUM_XrFoveationModeHTC(_) \
+ _(XR_FOVEATION_MODE_DISABLE_HTC, 0) \
+ _(XR_FOVEATION_MODE_FIXED_HTC, 1) \
+ _(XR_FOVEATION_MODE_DYNAMIC_HTC, 2) \
+ _(XR_FOVEATION_MODE_CUSTOM_HTC, 3) \
+ _(XR_FOVEATION_MODE_MAX_ENUM_HTC, 0x7FFFFFFF)
+
+#define XR_LIST_ENUM_XrFoveationLevelHTC(_) \
+ _(XR_FOVEATION_LEVEL_NONE_HTC, 0) \
+ _(XR_FOVEATION_LEVEL_LOW_HTC, 1) \
+ _(XR_FOVEATION_LEVEL_MEDIUM_HTC, 2) \
+ _(XR_FOVEATION_LEVEL_HIGH_HTC, 3) \
+ _(XR_FOVEATION_LEVEL_MAX_ENUM_HTC, 0x7FFFFFFF)
+
#define XR_LIST_BITS_XrInstanceCreateFlags(_)
#define XR_LIST_BITS_XrSessionCreateFlags(_)
@@ -891,6 +920,12 @@ XR_ENUM_STR(XrResult);
_(XR_PERFORMANCE_METRICS_COUNTER_UINT_VALUE_VALID_BIT_META, 0x00000002) \
_(XR_PERFORMANCE_METRICS_COUNTER_FLOAT_VALUE_VALID_BIT_META, 0x00000004) \
+#define XR_LIST_BITS_XrFoveationDynamicFlagsHTC(_) \
+ _(XR_FOVEATION_DYNAMIC_LEVEL_ENABLED_BIT_HTC, 0x00000001) \
+ _(XR_FOVEATION_DYNAMIC_CLEAR_FOV_ENABLED_BIT_HTC, 0x00000002) \
+ _(XR_FOVEATION_DYNAMIC_FOCAL_CENTER_OFFSET_ENABLED_BIT_HTC, 0x00000004) \
+
+/// Calls your macro with the name of each member of XrApiLayerProperties, in order.
#define XR_LIST_STRUCT_XrApiLayerProperties(_) \
_(type) \
_(next) \
@@ -899,12 +934,14 @@ XR_ENUM_STR(XrResult);
_(layerVersion) \
_(description) \
+/// Calls your macro with the name of each member of XrExtensionProperties, in order.
#define XR_LIST_STRUCT_XrExtensionProperties(_) \
_(type) \
_(next) \
_(extensionName) \
_(extensionVersion) \
+/// Calls your macro with the name of each member of XrApplicationInfo, in order.
#define XR_LIST_STRUCT_XrApplicationInfo(_) \
_(applicationName) \
_(applicationVersion) \
@@ -912,6 +949,7 @@ XR_ENUM_STR(XrResult);
_(engineVersion) \
_(apiVersion) \
+/// Calls your macro with the name of each member of XrInstanceCreateInfo, in order.
#define XR_LIST_STRUCT_XrInstanceCreateInfo(_) \
_(type) \
_(next) \
@@ -922,31 +960,37 @@ XR_ENUM_STR(XrResult);
_(enabledExtensionCount) \
_(enabledExtensionNames) \
+/// Calls your macro with the name of each member of XrInstanceProperties, in order.
#define XR_LIST_STRUCT_XrInstanceProperties(_) \
_(type) \
_(next) \
_(runtimeVersion) \
_(runtimeName) \
+/// Calls your macro with the name of each member of XrEventDataBuffer, in order.
#define XR_LIST_STRUCT_XrEventDataBuffer(_) \
_(type) \
_(next) \
_(varying) \
+/// Calls your macro with the name of each member of XrSystemGetInfo, in order.
#define XR_LIST_STRUCT_XrSystemGetInfo(_) \
_(type) \
_(next) \
_(formFactor) \
+/// Calls your macro with the name of each member of XrSystemGraphicsProperties, in order.
#define XR_LIST_STRUCT_XrSystemGraphicsProperties(_) \
_(maxSwapchainImageHeight) \
_(maxSwapchainImageWidth) \
_(maxLayerCount) \
+/// Calls your macro with the name of each member of XrSystemTrackingProperties, in order.
#define XR_LIST_STRUCT_XrSystemTrackingProperties(_) \
_(orientationTracking) \
_(positionTracking) \
+/// Calls your macro with the name of each member of XrSystemProperties, in order.
#define XR_LIST_STRUCT_XrSystemProperties(_) \
_(type) \
_(next) \
@@ -956,17 +1000,20 @@ XR_ENUM_STR(XrResult);
_(graphicsProperties) \
_(trackingProperties) \
+/// Calls your macro with the name of each member of XrSessionCreateInfo, in order.
#define XR_LIST_STRUCT_XrSessionCreateInfo(_) \
_(type) \
_(next) \
_(createFlags) \
_(systemId) \
+/// Calls your macro with the name of each member of XrVector3f, in order.
#define XR_LIST_STRUCT_XrVector3f(_) \
_(x) \
_(y) \
_(z) \
+/// Calls your macro with the name of each member of XrSpaceVelocity, in order.
#define XR_LIST_STRUCT_XrSpaceVelocity(_) \
_(type) \
_(next) \
@@ -974,26 +1021,31 @@ XR_ENUM_STR(XrResult);
_(linearVelocity) \
_(angularVelocity) \
+/// Calls your macro with the name of each member of XrQuaternionf, in order.
#define XR_LIST_STRUCT_XrQuaternionf(_) \
_(x) \
_(y) \
_(z) \
_(w) \
+/// Calls your macro with the name of each member of XrPosef, in order.
#define XR_LIST_STRUCT_XrPosef(_) \
_(orientation) \
_(position) \
+/// Calls your macro with the name of each member of XrReferenceSpaceCreateInfo, in order.
#define XR_LIST_STRUCT_XrReferenceSpaceCreateInfo(_) \
_(type) \
_(next) \
_(referenceSpaceType) \
_(poseInReferenceSpace) \
+/// Calls your macro with the name of each member of XrExtent2Df, in order.
#define XR_LIST_STRUCT_XrExtent2Df(_) \
_(width) \
_(height) \
+/// Calls your macro with the name of each member of XrActionSpaceCreateInfo, in order.
#define XR_LIST_STRUCT_XrActionSpaceCreateInfo(_) \
_(type) \
_(next) \
@@ -1001,18 +1053,21 @@ XR_ENUM_STR(XrResult);
_(subactionPath) \
_(poseInActionSpace) \
+/// Calls your macro with the name of each member of XrSpaceLocation, in order.
#define XR_LIST_STRUCT_XrSpaceLocation(_) \
_(type) \
_(next) \
_(locationFlags) \
_(pose) \
+/// Calls your macro with the name of each member of XrViewConfigurationProperties, in order.
#define XR_LIST_STRUCT_XrViewConfigurationProperties(_) \
_(type) \
_(next) \
_(viewConfigurationType) \
_(fovMutable) \
+/// Calls your macro with the name of each member of XrViewConfigurationView, in order.
#define XR_LIST_STRUCT_XrViewConfigurationView(_) \
_(type) \
_(next) \
@@ -1023,6 +1078,7 @@ XR_ENUM_STR(XrResult);
_(recommendedSwapchainSampleCount) \
_(maxSwapchainSampleCount) \
+/// Calls your macro with the name of each member of XrSwapchainCreateInfo, in order.
#define XR_LIST_STRUCT_XrSwapchainCreateInfo(_) \
_(type) \
_(next) \
@@ -1036,32 +1092,39 @@ XR_ENUM_STR(XrResult);
_(arraySize) \
_(mipCount) \
+/// Calls your macro with the name of each member of XrSwapchainImageBaseHeader, in order.
#define XR_LIST_STRUCT_XrSwapchainImageBaseHeader(_) \
_(type) \
_(next) \
+/// Calls your macro with the name of each member of XrSwapchainImageAcquireInfo, in order.
#define XR_LIST_STRUCT_XrSwapchainImageAcquireInfo(_) \
_(type) \
_(next) \
+/// Calls your macro with the name of each member of XrSwapchainImageWaitInfo, in order.
#define XR_LIST_STRUCT_XrSwapchainImageWaitInfo(_) \
_(type) \
_(next) \
_(timeout) \
+/// Calls your macro with the name of each member of XrSwapchainImageReleaseInfo, in order.
#define XR_LIST_STRUCT_XrSwapchainImageReleaseInfo(_) \
_(type) \
_(next) \
+/// Calls your macro with the name of each member of XrSessionBeginInfo, in order.
#define XR_LIST_STRUCT_XrSessionBeginInfo(_) \
_(type) \
_(next) \
_(primaryViewConfigurationType) \
+/// Calls your macro with the name of each member of XrFrameWaitInfo, in order.
#define XR_LIST_STRUCT_XrFrameWaitInfo(_) \
_(type) \
_(next) \
+/// Calls your macro with the name of each member of XrFrameState, in order.
#define XR_LIST_STRUCT_XrFrameState(_) \
_(type) \
_(next) \
@@ -1069,16 +1132,19 @@ XR_ENUM_STR(XrResult);
_(predictedDisplayPeriod) \
_(shouldRender) \
+/// Calls your macro with the name of each member of XrFrameBeginInfo, in order.
#define XR_LIST_STRUCT_XrFrameBeginInfo(_) \
_(type) \
_(next) \
+/// Calls your macro with the name of each member of XrCompositionLayerBaseHeader, in order.
#define XR_LIST_STRUCT_XrCompositionLayerBaseHeader(_) \
_(type) \
_(next) \
_(layerFlags) \
_(space) \
+/// Calls your macro with the name of each member of XrFrameEndInfo, in order.
#define XR_LIST_STRUCT_XrFrameEndInfo(_) \
_(type) \
_(next) \
@@ -1087,6 +1153,7 @@ XR_ENUM_STR(XrResult);
_(layerCount) \
_(layers) \
+/// Calls your macro with the name of each member of XrViewLocateInfo, in order.
#define XR_LIST_STRUCT_XrViewLocateInfo(_) \
_(type) \
_(next) \
@@ -1094,23 +1161,27 @@ XR_ENUM_STR(XrResult);
_(displayTime) \
_(space) \
+/// Calls your macro with the name of each member of XrViewState, in order.
#define XR_LIST_STRUCT_XrViewState(_) \
_(type) \
_(next) \
_(viewStateFlags) \
+/// Calls your macro with the name of each member of XrFovf, in order.
#define XR_LIST_STRUCT_XrFovf(_) \
_(angleLeft) \
_(angleRight) \
_(angleUp) \
_(angleDown) \
+/// Calls your macro with the name of each member of XrView, in order.
#define XR_LIST_STRUCT_XrView(_) \
_(type) \
_(next) \
_(pose) \
_(fov) \
+/// Calls your macro with the name of each member of XrActionSetCreateInfo, in order.
#define XR_LIST_STRUCT_XrActionSetCreateInfo(_) \
_(type) \
_(next) \
@@ -1118,6 +1189,7 @@ XR_ENUM_STR(XrResult);
_(localizedActionSetName) \
_(priority) \
+/// Calls your macro with the name of each member of XrActionCreateInfo, in order.
#define XR_LIST_STRUCT_XrActionCreateInfo(_) \
_(type) \
_(next) \
@@ -1127,10 +1199,12 @@ XR_ENUM_STR(XrResult);
_(subactionPaths) \
_(localizedActionName) \
+/// Calls your macro with the name of each member of XrActionSuggestedBinding, in order.
#define XR_LIST_STRUCT_XrActionSuggestedBinding(_) \
_(action) \
_(binding) \
+/// Calls your macro with the name of each member of XrInteractionProfileSuggestedBinding, in order.
#define XR_LIST_STRUCT_XrInteractionProfileSuggestedBinding(_) \
_(type) \
_(next) \
@@ -1138,23 +1212,27 @@ XR_ENUM_STR(XrResult);
_(countSuggestedBindings) \
_(suggestedBindings) \
+/// Calls your macro with the name of each member of XrSessionActionSetsAttachInfo, in order.
#define XR_LIST_STRUCT_XrSessionActionSetsAttachInfo(_) \
_(type) \
_(next) \
_(countActionSets) \
_(actionSets) \
+/// Calls your macro with the name of each member of XrInteractionProfileState, in order.
#define XR_LIST_STRUCT_XrInteractionProfileState(_) \
_(type) \
_(next) \
_(interactionProfile) \
+/// Calls your macro with the name of each member of XrActionStateGetInfo, in order.
#define XR_LIST_STRUCT_XrActionStateGetInfo(_) \
_(type) \
_(next) \
_(action) \
_(subactionPath) \
+/// Calls your macro with the name of each member of XrActionStateBoolean, in order.
#define XR_LIST_STRUCT_XrActionStateBoolean(_) \
_(type) \
_(next) \
@@ -1163,6 +1241,7 @@ XR_ENUM_STR(XrResult);
_(lastChangeTime) \
_(isActive) \
+/// Calls your macro with the name of each member of XrActionStateFloat, in order.
#define XR_LIST_STRUCT_XrActionStateFloat(_) \
_(type) \
_(next) \
@@ -1171,10 +1250,12 @@ XR_ENUM_STR(XrResult);
_(lastChangeTime) \
_(isActive) \
+/// Calls your macro with the name of each member of XrVector2f, in order.
#define XR_LIST_STRUCT_XrVector2f(_) \
_(x) \
_(y) \
+/// Calls your macro with the name of each member of XrActionStateVector2f, in order.
#define XR_LIST_STRUCT_XrActionStateVector2f(_) \
_(type) \
_(next) \
@@ -1183,67 +1264,81 @@ XR_ENUM_STR(XrResult);
_(lastChangeTime) \
_(isActive) \
+/// Calls your macro with the name of each member of XrActionStatePose, in order.
#define XR_LIST_STRUCT_XrActionStatePose(_) \
_(type) \
_(next) \
_(isActive) \
+/// Calls your macro with the name of each member of XrActiveActionSet, in order.
#define XR_LIST_STRUCT_XrActiveActionSet(_) \
_(actionSet) \
_(subactionPath) \
+/// Calls your macro with the name of each member of XrActionsSyncInfo, in order.
#define XR_LIST_STRUCT_XrActionsSyncInfo(_) \
_(type) \
_(next) \
_(countActiveActionSets) \
_(activeActionSets) \
+/// Calls your macro with the name of each member of XrBoundSourcesForActionEnumerateInfo, in order.
#define XR_LIST_STRUCT_XrBoundSourcesForActionEnumerateInfo(_) \
_(type) \
_(next) \
_(action) \
+/// Calls your macro with the name of each member of XrInputSourceLocalizedNameGetInfo, in order.
#define XR_LIST_STRUCT_XrInputSourceLocalizedNameGetInfo(_) \
_(type) \
_(next) \
_(sourcePath) \
_(whichComponents) \
+/// Calls your macro with the name of each member of XrHapticActionInfo, in order.
#define XR_LIST_STRUCT_XrHapticActionInfo(_) \
_(type) \
_(next) \
_(action) \
_(subactionPath) \
+/// Calls your macro with the name of each member of XrHapticBaseHeader, in order.
#define XR_LIST_STRUCT_XrHapticBaseHeader(_) \
_(type) \
_(next) \
+/// Calls your macro with the name of each member of XrBaseInStructure, in order.
#define XR_LIST_STRUCT_XrBaseInStructure(_) \
_(type) \
_(next) \
+/// Calls your macro with the name of each member of XrBaseOutStructure, in order.
#define XR_LIST_STRUCT_XrBaseOutStructure(_) \
_(type) \
_(next) \
+/// Calls your macro with the name of each member of XrOffset2Di, in order.
#define XR_LIST_STRUCT_XrOffset2Di(_) \
_(x) \
_(y) \
+/// Calls your macro with the name of each member of XrExtent2Di, in order.
#define XR_LIST_STRUCT_XrExtent2Di(_) \
_(width) \
_(height) \
+/// Calls your macro with the name of each member of XrRect2Di, in order.
#define XR_LIST_STRUCT_XrRect2Di(_) \
_(offset) \
_(extent) \
+/// Calls your macro with the name of each member of XrSwapchainSubImage, in order.
#define XR_LIST_STRUCT_XrSwapchainSubImage(_) \
_(swapchain) \
_(imageRect) \
_(imageArrayIndex) \
+/// Calls your macro with the name of each member of XrCompositionLayerProjectionView, in order.
#define XR_LIST_STRUCT_XrCompositionLayerProjectionView(_) \
_(type) \
_(next) \
@@ -1251,6 +1346,7 @@ XR_ENUM_STR(XrResult);
_(fov) \
_(subImage) \
+/// Calls your macro with the name of each member of XrCompositionLayerProjection, in order.
#define XR_LIST_STRUCT_XrCompositionLayerProjection(_) \
_(type) \
_(next) \
@@ -1259,6 +1355,7 @@ XR_ENUM_STR(XrResult);
_(viewCount) \
_(views) \
+/// Calls your macro with the name of each member of XrCompositionLayerQuad, in order.
#define XR_LIST_STRUCT_XrCompositionLayerQuad(_) \
_(type) \
_(next) \
@@ -1269,20 +1366,24 @@ XR_ENUM_STR(XrResult);
_(pose) \
_(size) \
+/// Calls your macro with the name of each member of XrEventDataBaseHeader, in order.
#define XR_LIST_STRUCT_XrEventDataBaseHeader(_) \
_(type) \
_(next) \
+/// Calls your macro with the name of each member of XrEventDataEventsLost, in order.
#define XR_LIST_STRUCT_XrEventDataEventsLost(_) \
_(type) \
_(next) \
_(lostEventCount) \
+/// Calls your macro with the name of each member of XrEventDataInstanceLossPending, in order.
#define XR_LIST_STRUCT_XrEventDataInstanceLossPending(_) \
_(type) \
_(next) \
_(lossTime) \
+/// Calls your macro with the name of each member of XrEventDataSessionStateChanged, in order.
#define XR_LIST_STRUCT_XrEventDataSessionStateChanged(_) \
_(type) \
_(next) \
@@ -1290,6 +1391,7 @@ XR_ENUM_STR(XrResult);
_(state) \
_(time) \
+/// Calls your macro with the name of each member of XrEventDataReferenceSpaceChangePending, in order.
#define XR_LIST_STRUCT_XrEventDataReferenceSpaceChangePending(_) \
_(type) \
_(next) \
@@ -1299,11 +1401,13 @@ XR_ENUM_STR(XrResult);
_(poseValid) \
_(poseInPreviousSpace) \
+/// Calls your macro with the name of each member of XrEventDataInteractionProfileChanged, in order.
#define XR_LIST_STRUCT_XrEventDataInteractionProfileChanged(_) \
_(type) \
_(next) \
_(session) \
+/// Calls your macro with the name of each member of XrHapticVibration, in order.
#define XR_LIST_STRUCT_XrHapticVibration(_) \
_(type) \
_(next) \
@@ -1311,26 +1415,31 @@ XR_ENUM_STR(XrResult);
_(frequency) \
_(amplitude) \
+/// Calls your macro with the name of each member of XrOffset2Df, in order.
#define XR_LIST_STRUCT_XrOffset2Df(_) \
_(x) \
_(y) \
+/// Calls your macro with the name of each member of XrRect2Df, in order.
#define XR_LIST_STRUCT_XrRect2Df(_) \
_(offset) \
_(extent) \
+/// Calls your macro with the name of each member of XrVector4f, in order.
#define XR_LIST_STRUCT_XrVector4f(_) \
_(x) \
_(y) \
_(z) \
_(w) \
+/// Calls your macro with the name of each member of XrColor4f, in order.
#define XR_LIST_STRUCT_XrColor4f(_) \
_(r) \
_(g) \
_(b) \
_(a) \
+/// Calls your macro with the name of each member of XrCompositionLayerCubeKHR, in order.
#define XR_LIST_STRUCT_XrCompositionLayerCubeKHR(_) \
_(type) \
_(next) \
@@ -1341,12 +1450,14 @@ XR_ENUM_STR(XrResult);
_(imageArrayIndex) \
_(orientation) \
+/// Calls your macro with the name of each member of XrInstanceCreateInfoAndroidKHR, in order.
#define XR_LIST_STRUCT_XrInstanceCreateInfoAndroidKHR(_) \
_(type) \
_(next) \
_(applicationVM) \
_(applicationActivity) \
+/// Calls your macro with the name of each member of XrCompositionLayerDepthInfoKHR, in order.
#define XR_LIST_STRUCT_XrCompositionLayerDepthInfoKHR(_) \
_(type) \
_(next) \
@@ -1356,12 +1467,14 @@ XR_ENUM_STR(XrResult);
_(nearZ) \
_(farZ) \
+/// Calls your macro with the name of each member of XrVulkanSwapchainFormatListCreateInfoKHR, in order.
#define XR_LIST_STRUCT_XrVulkanSwapchainFormatListCreateInfoKHR(_) \
_(type) \
_(next) \
_(viewFormatCount) \
_(viewFormats) \
+/// Calls your macro with the name of each member of XrCompositionLayerCylinderKHR, in order.
#define XR_LIST_STRUCT_XrCompositionLayerCylinderKHR(_) \
_(type) \
_(next) \
@@ -1374,6 +1487,7 @@ XR_ENUM_STR(XrResult);
_(centralAngle) \
_(aspectRatio) \
+/// Calls your macro with the name of each member of XrCompositionLayerEquirectKHR, in order.
#define XR_LIST_STRUCT_XrCompositionLayerEquirectKHR(_) \
_(type) \
_(next) \
@@ -1386,12 +1500,14 @@ XR_ENUM_STR(XrResult);
_(scale) \
_(bias) \
+/// Calls your macro with the name of each member of XrGraphicsBindingOpenGLWin32KHR, in order.
#define XR_LIST_STRUCT_XrGraphicsBindingOpenGLWin32KHR(_) \
_(type) \
_(next) \
_(hDC) \
_(hGLRC) \
+/// Calls your macro with the name of each member of XrGraphicsBindingOpenGLXlibKHR, in order.
#define XR_LIST_STRUCT_XrGraphicsBindingOpenGLXlibKHR(_) \
_(type) \
_(next) \
@@ -1401,6 +1517,7 @@ XR_ENUM_STR(XrResult);
_(glxDrawable) \
_(glxContext) \
+/// Calls your macro with the name of each member of XrGraphicsBindingOpenGLXcbKHR, in order.
#define XR_LIST_STRUCT_XrGraphicsBindingOpenGLXcbKHR(_) \
_(type) \
_(next) \
@@ -1411,22 +1528,26 @@ XR_ENUM_STR(XrResult);
_(glxDrawable) \
_(glxContext) \
+/// Calls your macro with the name of each member of XrGraphicsBindingOpenGLWaylandKHR, in order.
#define XR_LIST_STRUCT_XrGraphicsBindingOpenGLWaylandKHR(_) \
_(type) \
_(next) \
_(display) \
+/// Calls your macro with the name of each member of XrSwapchainImageOpenGLKHR, in order.
#define XR_LIST_STRUCT_XrSwapchainImageOpenGLKHR(_) \
_(type) \
_(next) \
_(image) \
+/// Calls your macro with the name of each member of XrGraphicsRequirementsOpenGLKHR, in order.
#define XR_LIST_STRUCT_XrGraphicsRequirementsOpenGLKHR(_) \
_(type) \
_(next) \
_(minApiVersionSupported) \
_(maxApiVersionSupported) \
+/// Calls your macro with the name of each member of XrGraphicsBindingOpenGLESAndroidKHR, in order.
#define XR_LIST_STRUCT_XrGraphicsBindingOpenGLESAndroidKHR(_) \
_(type) \
_(next) \
@@ -1434,17 +1555,20 @@ XR_ENUM_STR(XrResult);
_(config) \
_(context) \
+/// Calls your macro with the name of each member of XrSwapchainImageOpenGLESKHR, in order.
#define XR_LIST_STRUCT_XrSwapchainImageOpenGLESKHR(_) \
_(type) \
_(next) \
_(image) \
+/// Calls your macro with the name of each member of XrGraphicsRequirementsOpenGLESKHR, in order.
#define XR_LIST_STRUCT_XrGraphicsRequirementsOpenGLESKHR(_) \
_(type) \
_(next) \
_(minApiVersionSupported) \
_(maxApiVersionSupported) \
+/// Calls your macro with the name of each member of XrGraphicsBindingVulkanKHR, in order.
#define XR_LIST_STRUCT_XrGraphicsBindingVulkanKHR(_) \
_(type) \
_(next) \
@@ -1454,50 +1578,59 @@ XR_ENUM_STR(XrResult);
_(queueFamilyIndex) \
_(queueIndex) \
+/// Calls your macro with the name of each member of XrSwapchainImageVulkanKHR, in order.
#define XR_LIST_STRUCT_XrSwapchainImageVulkanKHR(_) \
_(type) \
_(next) \
_(image) \
+/// Calls your macro with the name of each member of XrGraphicsRequirementsVulkanKHR, in order.
#define XR_LIST_STRUCT_XrGraphicsRequirementsVulkanKHR(_) \
_(type) \
_(next) \
_(minApiVersionSupported) \
_(maxApiVersionSupported) \
+/// Calls your macro with the name of each member of XrGraphicsBindingD3D11KHR, in order.
#define XR_LIST_STRUCT_XrGraphicsBindingD3D11KHR(_) \
_(type) \
_(next) \
_(device) \
+/// Calls your macro with the name of each member of XrSwapchainImageD3D11KHR, in order.
#define XR_LIST_STRUCT_XrSwapchainImageD3D11KHR(_) \
_(type) \
_(next) \
_(texture) \
+/// Calls your macro with the name of each member of XrGraphicsRequirementsD3D11KHR, in order.
#define XR_LIST_STRUCT_XrGraphicsRequirementsD3D11KHR(_) \
_(type) \
_(next) \
_(adapterLuid) \
_(minFeatureLevel) \
+/// Calls your macro with the name of each member of XrGraphicsBindingD3D12KHR, in order.
#define XR_LIST_STRUCT_XrGraphicsBindingD3D12KHR(_) \
_(type) \
_(next) \
_(device) \
_(queue) \
+/// Calls your macro with the name of each member of XrSwapchainImageD3D12KHR, in order.
#define XR_LIST_STRUCT_XrSwapchainImageD3D12KHR(_) \
_(type) \
_(next) \
_(texture) \
+/// Calls your macro with the name of each member of XrGraphicsRequirementsD3D12KHR, in order.
#define XR_LIST_STRUCT_XrGraphicsRequirementsD3D12KHR(_) \
_(type) \
_(next) \
_(adapterLuid) \
_(minFeatureLevel) \
+/// Calls your macro with the name of each member of XrVisibilityMaskKHR, in order.
#define XR_LIST_STRUCT_XrVisibilityMaskKHR(_) \
_(type) \
_(next) \
@@ -1508,6 +1641,7 @@ XR_ENUM_STR(XrResult);
_(indexCountOutput) \
_(indices) \
+/// Calls your macro with the name of each member of XrEventDataVisibilityMaskChangedKHR, in order.
#define XR_LIST_STRUCT_XrEventDataVisibilityMaskChangedKHR(_) \
_(type) \
_(next) \
@@ -1515,22 +1649,26 @@ XR_ENUM_STR(XrResult);
_(viewConfigurationType) \
_(viewIndex) \
+/// Calls your macro with the name of each member of XrCompositionLayerColorScaleBiasKHR, in order.
#define XR_LIST_STRUCT_XrCompositionLayerColorScaleBiasKHR(_) \
_(type) \
_(next) \
_(colorScale) \
_(colorBias) \
+/// Calls your macro with the name of each member of XrLoaderInitInfoBaseHeaderKHR, in order.
#define XR_LIST_STRUCT_XrLoaderInitInfoBaseHeaderKHR(_) \
_(type) \
_(next) \
+/// Calls your macro with the name of each member of XrLoaderInitInfoAndroidKHR, in order.
#define XR_LIST_STRUCT_XrLoaderInitInfoAndroidKHR(_) \
_(type) \
_(next) \
_(applicationVM) \
_(applicationContext) \
+/// Calls your macro with the name of each member of XrVulkanInstanceCreateInfoKHR, in order.
#define XR_LIST_STRUCT_XrVulkanInstanceCreateInfoKHR(_) \
_(type) \
_(next) \
@@ -1540,6 +1678,7 @@ XR_ENUM_STR(XrResult);
_(vulkanCreateInfo) \
_(vulkanAllocator) \
+/// Calls your macro with the name of each member of XrVulkanDeviceCreateInfoKHR, in order.
#define XR_LIST_STRUCT_XrVulkanDeviceCreateInfoKHR(_) \
_(type) \
_(next) \
@@ -1550,12 +1689,14 @@ XR_ENUM_STR(XrResult);
_(vulkanCreateInfo) \
_(vulkanAllocator) \
+/// Calls your macro with the name of each member of XrVulkanGraphicsDeviceGetInfoKHR, in order.
#define XR_LIST_STRUCT_XrVulkanGraphicsDeviceGetInfoKHR(_) \
_(type) \
_(next) \
_(systemId) \
_(vulkanInstance) \
+/// Calls your macro with the name of each member of XrCompositionLayerEquirect2KHR, in order.
#define XR_LIST_STRUCT_XrCompositionLayerEquirect2KHR(_) \
_(type) \
_(next) \
@@ -1569,16 +1710,19 @@ XR_ENUM_STR(XrResult);
_(upperVerticalAngle) \
_(lowerVerticalAngle) \
+/// Calls your macro with the name of each member of XrBindingModificationBaseHeaderKHR, in order.
#define XR_LIST_STRUCT_XrBindingModificationBaseHeaderKHR(_) \
_(type) \
_(next) \
+/// Calls your macro with the name of each member of XrBindingModificationsKHR, in order.
#define XR_LIST_STRUCT_XrBindingModificationsKHR(_) \
_(type) \
_(next) \
_(bindingModificationCount) \
_(bindingModifications) \
+/// Calls your macro with the name of each member of XrEventDataPerfSettingsEXT, in order.
#define XR_LIST_STRUCT_XrEventDataPerfSettingsEXT(_) \
_(type) \
_(next) \
@@ -1587,6 +1731,7 @@ XR_ENUM_STR(XrResult);
_(fromLevel) \
_(toLevel) \
+/// Calls your macro with the name of each member of XrDebugUtilsObjectNameInfoEXT, in order.
#define XR_LIST_STRUCT_XrDebugUtilsObjectNameInfoEXT(_) \
_(type) \
_(next) \
@@ -1594,11 +1739,13 @@ XR_ENUM_STR(XrResult);
_(objectHandle) \
_(objectName) \
+/// Calls your macro with the name of each member of XrDebugUtilsLabelEXT, in order.
#define XR_LIST_STRUCT_XrDebugUtilsLabelEXT(_) \
_(type) \
_(next) \
_(labelName) \
+/// Calls your macro with the name of each member of XrDebugUtilsMessengerCallbackDataEXT, in order.
#define XR_LIST_STRUCT_XrDebugUtilsMessengerCallbackDataEXT(_) \
_(type) \
_(next) \
@@ -1610,6 +1757,7 @@ XR_ENUM_STR(XrResult);
_(sessionLabelCount) \
_(sessionLabels) \
+/// Calls your macro with the name of each member of XrDebugUtilsMessengerCreateInfoEXT, in order.
#define XR_LIST_STRUCT_XrDebugUtilsMessengerCreateInfoEXT(_) \
_(type) \
_(next) \
@@ -1618,28 +1766,33 @@ XR_ENUM_STR(XrResult);
_(userCallback) \
_(userData) \
+/// Calls your macro with the name of each member of XrSystemEyeGazeInteractionPropertiesEXT, in order.
#define XR_LIST_STRUCT_XrSystemEyeGazeInteractionPropertiesEXT(_) \
_(type) \
_(next) \
_(supportsEyeGazeInteraction) \
+/// Calls your macro with the name of each member of XrEyeGazeSampleTimeEXT, in order.
#define XR_LIST_STRUCT_XrEyeGazeSampleTimeEXT(_) \
_(type) \
_(next) \
_(time) \
+/// Calls your macro with the name of each member of XrSessionCreateInfoOverlayEXTX, in order.
#define XR_LIST_STRUCT_XrSessionCreateInfoOverlayEXTX(_) \
_(type) \
_(next) \
_(createFlags) \
_(sessionLayersPlacement) \
+/// Calls your macro with the name of each member of XrEventDataMainSessionVisibilityChangedEXTX, in order.
#define XR_LIST_STRUCT_XrEventDataMainSessionVisibilityChangedEXTX(_) \
_(type) \
_(next) \
_(visible) \
_(flags) \
+/// Calls your macro with the name of each member of XrSpatialAnchorCreateInfoMSFT, in order.
#define XR_LIST_STRUCT_XrSpatialAnchorCreateInfoMSFT(_) \
_(type) \
_(next) \
@@ -1647,17 +1800,20 @@ XR_ENUM_STR(XrResult);
_(pose) \
_(time) \
+/// Calls your macro with the name of each member of XrSpatialAnchorSpaceCreateInfoMSFT, in order.
#define XR_LIST_STRUCT_XrSpatialAnchorSpaceCreateInfoMSFT(_) \
_(type) \
_(next) \
_(anchor) \
_(poseInAnchorSpace) \
+/// Calls your macro with the name of each member of XrCompositionLayerImageLayoutFB, in order.
#define XR_LIST_STRUCT_XrCompositionLayerImageLayoutFB(_) \
_(type) \
_(next) \
_(flags) \
+/// Calls your macro with the name of each member of XrCompositionLayerAlphaBlendFB, in order.
#define XR_LIST_STRUCT_XrCompositionLayerAlphaBlendFB(_) \
_(type) \
_(next) \
@@ -1666,6 +1822,7 @@ XR_ENUM_STR(XrResult);
_(srcFactorAlpha) \
_(dstFactorAlpha) \
+/// Calls your macro with the name of each member of XrViewConfigurationDepthRangeEXT, in order.
#define XR_LIST_STRUCT_XrViewConfigurationDepthRangeEXT(_) \
_(type) \
_(next) \
@@ -1674,6 +1831,7 @@ XR_ENUM_STR(XrResult);
_(recommendedFarZ) \
_(maxFarZ) \
+/// Calls your macro with the name of each member of XrGraphicsBindingEGLMNDX, in order.
#define XR_LIST_STRUCT_XrGraphicsBindingEGLMNDX(_) \
_(type) \
_(next) \
@@ -1682,6 +1840,7 @@ XR_ENUM_STR(XrResult);
_(config) \
_(context) \
+/// Calls your macro with the name of each member of XrSpatialGraphNodeSpaceCreateInfoMSFT, in order.
#define XR_LIST_STRUCT_XrSpatialGraphNodeSpaceCreateInfoMSFT(_) \
_(type) \
_(next) \
@@ -1689,6 +1848,7 @@ XR_ENUM_STR(XrResult);
_(nodeId) \
_(pose) \
+/// Calls your macro with the name of each member of XrSpatialGraphStaticNodeBindingCreateInfoMSFT, in order.
#define XR_LIST_STRUCT_XrSpatialGraphStaticNodeBindingCreateInfoMSFT(_) \
_(type) \
_(next) \
@@ -1696,43 +1856,51 @@ XR_ENUM_STR(XrResult);
_(poseInSpace) \
_(time) \
+/// Calls your macro with the name of each member of XrSpatialGraphNodeBindingPropertiesGetInfoMSFT, in order.
#define XR_LIST_STRUCT_XrSpatialGraphNodeBindingPropertiesGetInfoMSFT(_) \
_(type) \
_(next) \
+/// Calls your macro with the name of each member of XrSpatialGraphNodeBindingPropertiesMSFT, in order.
#define XR_LIST_STRUCT_XrSpatialGraphNodeBindingPropertiesMSFT(_) \
_(type) \
_(next) \
_(nodeId) \
_(poseInNodeSpace) \
+/// Calls your macro with the name of each member of XrSystemHandTrackingPropertiesEXT, in order.
#define XR_LIST_STRUCT_XrSystemHandTrackingPropertiesEXT(_) \
_(type) \
_(next) \
_(supportsHandTracking) \
+/// Calls your macro with the name of each member of XrHandTrackerCreateInfoEXT, in order.
#define XR_LIST_STRUCT_XrHandTrackerCreateInfoEXT(_) \
_(type) \
_(next) \
_(hand) \
_(handJointSet) \
+/// Calls your macro with the name of each member of XrHandJointsLocateInfoEXT, in order.
#define XR_LIST_STRUCT_XrHandJointsLocateInfoEXT(_) \
_(type) \
_(next) \
_(baseSpace) \
_(time) \
+/// Calls your macro with the name of each member of XrHandJointLocationEXT, in order.
#define XR_LIST_STRUCT_XrHandJointLocationEXT(_) \
_(locationFlags) \
_(pose) \
_(radius) \
+/// Calls your macro with the name of each member of XrHandJointVelocityEXT, in order.
#define XR_LIST_STRUCT_XrHandJointVelocityEXT(_) \
_(velocityFlags) \
_(linearVelocity) \
_(angularVelocity) \
+/// Calls your macro with the name of each member of XrHandJointLocationsEXT, in order.
#define XR_LIST_STRUCT_XrHandJointLocationsEXT(_) \
_(type) \
_(next) \
@@ -1740,12 +1908,14 @@ XR_ENUM_STR(XrResult);
_(jointCount) \
_(jointLocations) \
+/// Calls your macro with the name of each member of XrHandJointVelocitiesEXT, in order.
#define XR_LIST_STRUCT_XrHandJointVelocitiesEXT(_) \
_(type) \
_(next) \
_(jointCount) \
_(jointVelocities) \
+/// Calls your macro with the name of each member of XrSystemHandTrackingMeshPropertiesMSFT, in order.
#define XR_LIST_STRUCT_XrSystemHandTrackingMeshPropertiesMSFT(_) \
_(type) \
_(next) \
@@ -1753,34 +1923,40 @@ XR_ENUM_STR(XrResult);
_(maxHandMeshIndexCount) \
_(maxHandMeshVertexCount) \
+/// Calls your macro with the name of each member of XrHandMeshSpaceCreateInfoMSFT, in order.
#define XR_LIST_STRUCT_XrHandMeshSpaceCreateInfoMSFT(_) \
_(type) \
_(next) \
_(handPoseType) \
_(poseInHandMeshSpace) \
+/// Calls your macro with the name of each member of XrHandMeshUpdateInfoMSFT, in order.
#define XR_LIST_STRUCT_XrHandMeshUpdateInfoMSFT(_) \
_(type) \
_(next) \
_(time) \
_(handPoseType) \
+/// Calls your macro with the name of each member of XrHandMeshIndexBufferMSFT, in order.
#define XR_LIST_STRUCT_XrHandMeshIndexBufferMSFT(_) \
_(indexBufferKey) \
_(indexCapacityInput) \
_(indexCountOutput) \
_(indices) \
+/// Calls your macro with the name of each member of XrHandMeshVertexMSFT, in order.
#define XR_LIST_STRUCT_XrHandMeshVertexMSFT(_) \
_(position) \
_(normal) \
+/// Calls your macro with the name of each member of XrHandMeshVertexBufferMSFT, in order.
#define XR_LIST_STRUCT_XrHandMeshVertexBufferMSFT(_) \
_(vertexUpdateTime) \
_(vertexCapacityInput) \
_(vertexCountOutput) \
_(vertices) \
+/// Calls your macro with the name of each member of XrHandMeshMSFT, in order.
#define XR_LIST_STRUCT_XrHandMeshMSFT(_) \
_(type) \
_(next) \
@@ -1790,29 +1966,34 @@ XR_ENUM_STR(XrResult);
_(indexBuffer) \
_(vertexBuffer) \
+/// Calls your macro with the name of each member of XrHandPoseTypeInfoMSFT, in order.
#define XR_LIST_STRUCT_XrHandPoseTypeInfoMSFT(_) \
_(type) \
_(next) \
_(handPoseType) \
+/// Calls your macro with the name of each member of XrSecondaryViewConfigurationSessionBeginInfoMSFT, in order.
#define XR_LIST_STRUCT_XrSecondaryViewConfigurationSessionBeginInfoMSFT(_) \
_(type) \
_(next) \
_(viewConfigurationCount) \
_(enabledViewConfigurationTypes) \
+/// Calls your macro with the name of each member of XrSecondaryViewConfigurationStateMSFT, in order.
#define XR_LIST_STRUCT_XrSecondaryViewConfigurationStateMSFT(_) \
_(type) \
_(next) \
_(viewConfigurationType) \
_(active) \
+/// Calls your macro with the name of each member of XrSecondaryViewConfigurationFrameStateMSFT, in order.
#define XR_LIST_STRUCT_XrSecondaryViewConfigurationFrameStateMSFT(_) \
_(type) \
_(next) \
_(viewConfigurationCount) \
_(viewConfigurationStates) \
+/// Calls your macro with the name of each member of XrSecondaryViewConfigurationLayerInfoMSFT, in order.
#define XR_LIST_STRUCT_XrSecondaryViewConfigurationLayerInfoMSFT(_) \
_(type) \
_(next) \
@@ -1821,28 +2002,33 @@ XR_ENUM_STR(XrResult);
_(layerCount) \
_(layers) \
+/// Calls your macro with the name of each member of XrSecondaryViewConfigurationFrameEndInfoMSFT, in order.
#define XR_LIST_STRUCT_XrSecondaryViewConfigurationFrameEndInfoMSFT(_) \
_(type) \
_(next) \
_(viewConfigurationCount) \
_(viewConfigurationLayersInfo) \
+/// Calls your macro with the name of each member of XrSecondaryViewConfigurationSwapchainCreateInfoMSFT, in order.
#define XR_LIST_STRUCT_XrSecondaryViewConfigurationSwapchainCreateInfoMSFT(_) \
_(type) \
_(next) \
_(viewConfigurationType) \
+/// Calls your macro with the name of each member of XrControllerModelKeyStateMSFT, in order.
#define XR_LIST_STRUCT_XrControllerModelKeyStateMSFT(_) \
_(type) \
_(next) \
_(modelKey) \
+/// Calls your macro with the name of each member of XrControllerModelNodePropertiesMSFT, in order.
#define XR_LIST_STRUCT_XrControllerModelNodePropertiesMSFT(_) \
_(type) \
_(next) \
_(parentNodeName) \
_(nodeName) \
+/// Calls your macro with the name of each member of XrControllerModelPropertiesMSFT, in order.
#define XR_LIST_STRUCT_XrControllerModelPropertiesMSFT(_) \
_(type) \
_(next) \
@@ -1850,11 +2036,13 @@ XR_ENUM_STR(XrResult);
_(nodeCountOutput) \
_(nodeProperties) \
+/// Calls your macro with the name of each member of XrControllerModelNodeStateMSFT, in order.
#define XR_LIST_STRUCT_XrControllerModelNodeStateMSFT(_) \
_(type) \
_(next) \
_(nodePose) \
+/// Calls your macro with the name of each member of XrControllerModelStateMSFT, in order.
#define XR_LIST_STRUCT_XrControllerModelStateMSFT(_) \
_(type) \
_(next) \
@@ -1862,23 +2050,27 @@ XR_ENUM_STR(XrResult);
_(nodeCountOutput) \
_(nodeStates) \
+/// Calls your macro with the name of each member of XrViewConfigurationViewFovEPIC, in order.
#define XR_LIST_STRUCT_XrViewConfigurationViewFovEPIC(_) \
_(type) \
_(next) \
_(recommendedFov) \
_(maxMutableFov) \
+/// Calls your macro with the name of each member of XrHolographicWindowAttachmentMSFT, in order.
#define XR_LIST_STRUCT_XrHolographicWindowAttachmentMSFT(_) \
_(type) \
_(next) \
_(holographicSpace) \
_(coreWindow) \
+/// Calls your macro with the name of each member of XrCompositionLayerReprojectionInfoMSFT, in order.
#define XR_LIST_STRUCT_XrCompositionLayerReprojectionInfoMSFT(_) \
_(type) \
_(next) \
_(reprojectionMode) \
+/// Calls your macro with the name of each member of XrCompositionLayerReprojectionPlaneOverrideMSFT, in order.
#define XR_LIST_STRUCT_XrCompositionLayerReprojectionPlaneOverrideMSFT(_) \
_(type) \
_(next) \
@@ -1886,20 +2078,24 @@ XR_ENUM_STR(XrResult);
_(normal) \
_(velocity) \
+/// Calls your macro with the name of each member of XrAndroidSurfaceSwapchainCreateInfoFB, in order.
#define XR_LIST_STRUCT_XrAndroidSurfaceSwapchainCreateInfoFB(_) \
_(type) \
_(next) \
_(createFlags) \
+/// Calls your macro with the name of each member of XrSwapchainStateBaseHeaderFB, in order.
#define XR_LIST_STRUCT_XrSwapchainStateBaseHeaderFB(_) \
_(type) \
_(next) \
+/// Calls your macro with the name of each member of XrCompositionLayerSecureContentFB, in order.
#define XR_LIST_STRUCT_XrCompositionLayerSecureContentFB(_) \
_(type) \
_(next) \
_(flags) \
+/// Calls your macro with the name of each member of XrInteractionProfileDpadBindingEXT, in order.
#define XR_LIST_STRUCT_XrInteractionProfileDpadBindingEXT(_) \
_(type) \
_(next) \
@@ -1913,6 +2109,7 @@ XR_ENUM_STR(XrResult);
_(onHaptic) \
_(offHaptic) \
+/// Calls your macro with the name of each member of XrInteractionProfileAnalogThresholdVALVE, in order.
#define XR_LIST_STRUCT_XrInteractionProfileAnalogThresholdVALVE(_) \
_(type) \
_(next) \
@@ -1923,35 +2120,43 @@ XR_ENUM_STR(XrResult);
_(onHaptic) \
_(offHaptic) \
+/// Calls your macro with the name of each member of XrHandJointsMotionRangeInfoEXT, in order.
#define XR_LIST_STRUCT_XrHandJointsMotionRangeInfoEXT(_) \
_(type) \
_(next) \
_(handJointsMotionRange) \
+/// Calls your macro with the name of each member of XrUuidMSFT, in order.
#define XR_LIST_STRUCT_XrUuidMSFT(_) \
_(bytes) \
+/// Calls your macro with the name of each member of XrSceneObserverCreateInfoMSFT, in order.
#define XR_LIST_STRUCT_XrSceneObserverCreateInfoMSFT(_) \
_(type) \
_(next) \
+/// Calls your macro with the name of each member of XrSceneCreateInfoMSFT, in order.
#define XR_LIST_STRUCT_XrSceneCreateInfoMSFT(_) \
_(type) \
_(next) \
+/// Calls your macro with the name of each member of XrSceneSphereBoundMSFT, in order.
#define XR_LIST_STRUCT_XrSceneSphereBoundMSFT(_) \
_(center) \
_(radius) \
+/// Calls your macro with the name of each member of XrSceneOrientedBoxBoundMSFT, in order.
#define XR_LIST_STRUCT_XrSceneOrientedBoxBoundMSFT(_) \
_(pose) \
_(extents) \
+/// Calls your macro with the name of each member of XrSceneFrustumBoundMSFT, in order.
#define XR_LIST_STRUCT_XrSceneFrustumBoundMSFT(_) \
_(pose) \
_(fov) \
_(farDistance) \
+/// Calls your macro with the name of each member of XrSceneBoundsMSFT, in order.
#define XR_LIST_STRUCT_XrSceneBoundsMSFT(_) \
_(space) \
_(time) \
@@ -1962,6 +2167,7 @@ XR_ENUM_STR(XrResult);
_(frustumCount) \
_(frustums) \
+/// Calls your macro with the name of each member of XrNewSceneComputeInfoMSFT, in order.
#define XR_LIST_STRUCT_XrNewSceneComputeInfoMSFT(_) \
_(type) \
_(next) \
@@ -1970,17 +2176,20 @@ XR_ENUM_STR(XrResult);
_(consistency) \
_(bounds) \
+/// Calls your macro with the name of each member of XrVisualMeshComputeLodInfoMSFT, in order.
#define XR_LIST_STRUCT_XrVisualMeshComputeLodInfoMSFT(_) \
_(type) \
_(next) \
_(lod) \
+/// Calls your macro with the name of each member of XrSceneComponentMSFT, in order.
#define XR_LIST_STRUCT_XrSceneComponentMSFT(_) \
_(componentType) \
_(id) \
_(parentId) \
_(updateTime) \
+/// Calls your macro with the name of each member of XrSceneComponentsMSFT, in order.
#define XR_LIST_STRUCT_XrSceneComponentsMSFT(_) \
_(type) \
_(next) \
@@ -1988,21 +2197,25 @@ XR_ENUM_STR(XrResult);
_(componentCountOutput) \
_(components) \
+/// Calls your macro with the name of each member of XrSceneComponentsGetInfoMSFT, in order.
#define XR_LIST_STRUCT_XrSceneComponentsGetInfoMSFT(_) \
_(type) \
_(next) \
_(componentType) \
+/// Calls your macro with the name of each member of XrSceneComponentLocationMSFT, in order.
#define XR_LIST_STRUCT_XrSceneComponentLocationMSFT(_) \
_(flags) \
_(pose) \
+/// Calls your macro with the name of each member of XrSceneComponentLocationsMSFT, in order.
#define XR_LIST_STRUCT_XrSceneComponentLocationsMSFT(_) \
_(type) \
_(next) \
_(locationCount) \
_(locations) \
+/// Calls your macro with the name of each member of XrSceneComponentsLocateInfoMSFT, in order.
#define XR_LIST_STRUCT_XrSceneComponentsLocateInfoMSFT(_) \
_(type) \
_(next) \
@@ -2011,63 +2224,75 @@ XR_ENUM_STR(XrResult);
_(componentIdCount) \
_(componentIds) \
+/// Calls your macro with the name of each member of XrSceneObjectMSFT, in order.
#define XR_LIST_STRUCT_XrSceneObjectMSFT(_) \
_(objectType) \
+/// Calls your macro with the name of each member of XrSceneObjectsMSFT, in order.
#define XR_LIST_STRUCT_XrSceneObjectsMSFT(_) \
_(type) \
_(next) \
_(sceneObjectCount) \
_(sceneObjects) \
+/// Calls your macro with the name of each member of XrSceneComponentParentFilterInfoMSFT, in order.
#define XR_LIST_STRUCT_XrSceneComponentParentFilterInfoMSFT(_) \
_(type) \
_(next) \
_(parentId) \
+/// Calls your macro with the name of each member of XrSceneObjectTypesFilterInfoMSFT, in order.
#define XR_LIST_STRUCT_XrSceneObjectTypesFilterInfoMSFT(_) \
_(type) \
_(next) \
_(objectTypeCount) \
_(objectTypes) \
+/// Calls your macro with the name of each member of XrScenePlaneMSFT, in order.
#define XR_LIST_STRUCT_XrScenePlaneMSFT(_) \
_(alignment) \
_(size) \
_(meshBufferId) \
_(supportsIndicesUint16) \
+/// Calls your macro with the name of each member of XrScenePlanesMSFT, in order.
#define XR_LIST_STRUCT_XrScenePlanesMSFT(_) \
_(type) \
_(next) \
_(scenePlaneCount) \
_(scenePlanes) \
+/// Calls your macro with the name of each member of XrScenePlaneAlignmentFilterInfoMSFT, in order.
#define XR_LIST_STRUCT_XrScenePlaneAlignmentFilterInfoMSFT(_) \
_(type) \
_(next) \
_(alignmentCount) \
_(alignments) \
+/// Calls your macro with the name of each member of XrSceneMeshMSFT, in order.
#define XR_LIST_STRUCT_XrSceneMeshMSFT(_) \
_(meshBufferId) \
_(supportsIndicesUint16) \
+/// Calls your macro with the name of each member of XrSceneMeshesMSFT, in order.
#define XR_LIST_STRUCT_XrSceneMeshesMSFT(_) \
_(type) \
_(next) \
_(sceneMeshCount) \
_(sceneMeshes) \
+/// Calls your macro with the name of each member of XrSceneMeshBuffersGetInfoMSFT, in order.
#define XR_LIST_STRUCT_XrSceneMeshBuffersGetInfoMSFT(_) \
_(type) \
_(next) \
_(meshBufferId) \
+/// Calls your macro with the name of each member of XrSceneMeshBuffersMSFT, in order.
#define XR_LIST_STRUCT_XrSceneMeshBuffersMSFT(_) \
_(type) \
_(next) \
+/// Calls your macro with the name of each member of XrSceneMeshVertexBufferMSFT, in order.
#define XR_LIST_STRUCT_XrSceneMeshVertexBufferMSFT(_) \
_(type) \
_(next) \
@@ -2075,6 +2300,7 @@ XR_ENUM_STR(XrResult);
_(vertexCountOutput) \
_(vertices) \
+/// Calls your macro with the name of each member of XrSceneMeshIndicesUint32MSFT, in order.
#define XR_LIST_STRUCT_XrSceneMeshIndicesUint32MSFT(_) \
_(type) \
_(next) \
@@ -2082,6 +2308,7 @@ XR_ENUM_STR(XrResult);
_(indexCountOutput) \
_(indices) \
+/// Calls your macro with the name of each member of XrSceneMeshIndicesUint16MSFT, in order.
#define XR_LIST_STRUCT_XrSceneMeshIndicesUint16MSFT(_) \
_(type) \
_(next) \
@@ -2089,44 +2316,52 @@ XR_ENUM_STR(XrResult);
_(indexCountOutput) \
_(indices) \
+/// Calls your macro with the name of each member of XrSerializedSceneFragmentDataGetInfoMSFT, in order.
#define XR_LIST_STRUCT_XrSerializedSceneFragmentDataGetInfoMSFT(_) \
_(type) \
_(next) \
_(sceneFragmentId) \
+/// Calls your macro with the name of each member of XrDeserializeSceneFragmentMSFT, in order.
#define XR_LIST_STRUCT_XrDeserializeSceneFragmentMSFT(_) \
_(bufferSize) \
_(buffer) \
+/// Calls your macro with the name of each member of XrSceneDeserializeInfoMSFT, in order.
#define XR_LIST_STRUCT_XrSceneDeserializeInfoMSFT(_) \
_(type) \
_(next) \
_(fragmentCount) \
_(fragments) \
+/// Calls your macro with the name of each member of XrEventDataDisplayRefreshRateChangedFB, in order.
#define XR_LIST_STRUCT_XrEventDataDisplayRefreshRateChangedFB(_) \
_(type) \
_(next) \
_(fromDisplayRefreshRate) \
_(toDisplayRefreshRate) \
+/// Calls your macro with the name of each member of XrViveTrackerPathsHTCX, in order.
#define XR_LIST_STRUCT_XrViveTrackerPathsHTCX(_) \
_(type) \
_(next) \
_(persistentPath) \
_(rolePath) \
+/// Calls your macro with the name of each member of XrEventDataViveTrackerConnectedHTCX, in order.
#define XR_LIST_STRUCT_XrEventDataViveTrackerConnectedHTCX(_) \
_(type) \
_(next) \
_(paths) \
+/// Calls your macro with the name of each member of XrSystemFacialTrackingPropertiesHTC, in order.
#define XR_LIST_STRUCT_XrSystemFacialTrackingPropertiesHTC(_) \
_(type) \
_(next) \
_(supportEyeFacialTracking) \
_(supportLipFacialTracking) \
+/// Calls your macro with the name of each member of XrFacialExpressionsHTC, in order.
#define XR_LIST_STRUCT_XrFacialExpressionsHTC(_) \
_(type) \
_(next) \
@@ -2135,22 +2370,26 @@ XR_ENUM_STR(XrResult);
_(expressionCount) \
_(expressionWeightings) \
+/// Calls your macro with the name of each member of XrFacialTrackerCreateInfoHTC, in order.
#define XR_LIST_STRUCT_XrFacialTrackerCreateInfoHTC(_) \
_(type) \
_(next) \
_(facialTrackingType) \
+/// Calls your macro with the name of each member of XrSystemColorSpacePropertiesFB, in order.
#define XR_LIST_STRUCT_XrSystemColorSpacePropertiesFB(_) \
_(type) \
_(next) \
_(colorSpace) \
+/// Calls your macro with the name of each member of XrVector4sFB, in order.
#define XR_LIST_STRUCT_XrVector4sFB(_) \
_(x) \
_(y) \
_(z) \
_(w) \
+/// Calls your macro with the name of each member of XrHandTrackingMeshFB, in order.
#define XR_LIST_STRUCT_XrHandTrackingMeshFB(_) \
_(type) \
_(next) \
@@ -2170,6 +2409,7 @@ XR_ENUM_STR(XrResult);
_(indexCountOutput) \
_(indices) \
+/// Calls your macro with the name of each member of XrHandTrackingScaleFB, in order.
#define XR_LIST_STRUCT_XrHandTrackingScaleFB(_) \
_(type) \
_(next) \
@@ -2178,6 +2418,7 @@ XR_ENUM_STR(XrResult);
_(overrideHandScale) \
_(overrideValueInput) \
+/// Calls your macro with the name of each member of XrHandTrackingAimStateFB, in order.
#define XR_LIST_STRUCT_XrHandTrackingAimStateFB(_) \
_(type) \
_(next) \
@@ -2188,21 +2429,25 @@ XR_ENUM_STR(XrResult);
_(pinchStrengthRing) \
_(pinchStrengthLittle) \
+/// Calls your macro with the name of each member of XrHandCapsuleFB, in order.
#define XR_LIST_STRUCT_XrHandCapsuleFB(_) \
_(points) \
_(radius) \
_(joint) \
+/// Calls your macro with the name of each member of XrHandTrackingCapsulesStateFB, in order.
#define XR_LIST_STRUCT_XrHandTrackingCapsulesStateFB(_) \
_(type) \
_(next) \
_(capsules) \
+/// Calls your macro with the name of each member of XrSystemSpatialEntityPropertiesFB, in order.
#define XR_LIST_STRUCT_XrSystemSpatialEntityPropertiesFB(_) \
_(type) \
_(next) \
_(supportsSpatialEntity) \
+/// Calls your macro with the name of each member of XrSpatialAnchorCreateInfoFB, in order.
#define XR_LIST_STRUCT_XrSpatialAnchorCreateInfoFB(_) \
_(type) \
_(next) \
@@ -2210,6 +2455,7 @@ XR_ENUM_STR(XrResult);
_(poseInSpace) \
_(time) \
+/// Calls your macro with the name of each member of XrSpaceComponentStatusSetInfoFB, in order.
#define XR_LIST_STRUCT_XrSpaceComponentStatusSetInfoFB(_) \
_(type) \
_(next) \
@@ -2217,15 +2463,18 @@ XR_ENUM_STR(XrResult);
_(enabled) \
_(timeout) \
+/// Calls your macro with the name of each member of XrSpaceComponentStatusFB, in order.
#define XR_LIST_STRUCT_XrSpaceComponentStatusFB(_) \
_(type) \
_(next) \
_(enabled) \
_(changePending) \
+/// Calls your macro with the name of each member of XrUuidEXT, in order.
#define XR_LIST_STRUCT_XrUuidEXT(_) \
_(data) \
+/// Calls your macro with the name of each member of XrEventDataSpatialAnchorCreateCompleteFB, in order.
#define XR_LIST_STRUCT_XrEventDataSpatialAnchorCreateCompleteFB(_) \
_(type) \
_(next) \
@@ -2234,6 +2483,7 @@ XR_ENUM_STR(XrResult);
_(space) \
_(uuid) \
+/// Calls your macro with the name of each member of XrEventDataSpaceSetStatusCompleteFB, in order.
#define XR_LIST_STRUCT_XrEventDataSpaceSetStatusCompleteFB(_) \
_(type) \
_(next) \
@@ -2244,21 +2494,25 @@ XR_ENUM_STR(XrResult);
_(componentType) \
_(enabled) \
+/// Calls your macro with the name of each member of XrFoveationProfileCreateInfoFB, in order.
#define XR_LIST_STRUCT_XrFoveationProfileCreateInfoFB(_) \
_(type) \
_(next) \
+/// Calls your macro with the name of each member of XrSwapchainCreateInfoFoveationFB, in order.
#define XR_LIST_STRUCT_XrSwapchainCreateInfoFoveationFB(_) \
_(type) \
_(next) \
_(flags) \
+/// Calls your macro with the name of each member of XrSwapchainStateFoveationFB, in order.
#define XR_LIST_STRUCT_XrSwapchainStateFoveationFB(_) \
_(type) \
_(next) \
_(flags) \
_(profile) \
+/// Calls your macro with the name of each member of XrFoveationLevelProfileCreateInfoFB, in order.
#define XR_LIST_STRUCT_XrFoveationLevelProfileCreateInfoFB(_) \
_(type) \
_(next) \
@@ -2266,27 +2520,32 @@ XR_ENUM_STR(XrResult);
_(verticalOffset) \
_(dynamic) \
+/// Calls your macro with the name of each member of XrSystemKeyboardTrackingPropertiesFB, in order.
#define XR_LIST_STRUCT_XrSystemKeyboardTrackingPropertiesFB(_) \
_(type) \
_(next) \
_(supportsKeyboardTracking) \
+/// Calls your macro with the name of each member of XrKeyboardTrackingDescriptionFB, in order.
#define XR_LIST_STRUCT_XrKeyboardTrackingDescriptionFB(_) \
_(trackedKeyboardId) \
_(size) \
_(flags) \
_(name) \
+/// Calls your macro with the name of each member of XrKeyboardSpaceCreateInfoFB, in order.
#define XR_LIST_STRUCT_XrKeyboardSpaceCreateInfoFB(_) \
_(type) \
_(next) \
_(trackedKeyboardId) \
+/// Calls your macro with the name of each member of XrKeyboardTrackingQueryFB, in order.
#define XR_LIST_STRUCT_XrKeyboardTrackingQueryFB(_) \
_(type) \
_(next) \
_(flags) \
+/// Calls your macro with the name of each member of XrTriangleMeshCreateInfoFB, in order.
#define XR_LIST_STRUCT_XrTriangleMeshCreateInfoFB(_) \
_(type) \
_(next) \
@@ -2297,21 +2556,25 @@ XR_ENUM_STR(XrResult);
_(triangleCount) \
_(indexBuffer) \
+/// Calls your macro with the name of each member of XrSystemPassthroughPropertiesFB, in order.
#define XR_LIST_STRUCT_XrSystemPassthroughPropertiesFB(_) \
_(type) \
_(next) \
_(supportsPassthrough) \
+/// Calls your macro with the name of each member of XrSystemPassthroughProperties2FB, in order.
#define XR_LIST_STRUCT_XrSystemPassthroughProperties2FB(_) \
_(type) \
_(next) \
_(capabilities) \
+/// Calls your macro with the name of each member of XrPassthroughCreateInfoFB, in order.
#define XR_LIST_STRUCT_XrPassthroughCreateInfoFB(_) \
_(type) \
_(next) \
_(flags) \
+/// Calls your macro with the name of each member of XrPassthroughLayerCreateInfoFB, in order.
#define XR_LIST_STRUCT_XrPassthroughLayerCreateInfoFB(_) \
_(type) \
_(next) \
@@ -2319,6 +2582,7 @@ XR_ENUM_STR(XrResult);
_(flags) \
_(purpose) \
+/// Calls your macro with the name of each member of XrCompositionLayerPassthroughFB, in order.
#define XR_LIST_STRUCT_XrCompositionLayerPassthroughFB(_) \
_(type) \
_(next) \
@@ -2326,6 +2590,7 @@ XR_ENUM_STR(XrResult);
_(space) \
_(layerHandle) \
+/// Calls your macro with the name of each member of XrGeometryInstanceCreateInfoFB, in order.
#define XR_LIST_STRUCT_XrGeometryInstanceCreateInfoFB(_) \
_(type) \
_(next) \
@@ -2335,6 +2600,7 @@ XR_ENUM_STR(XrResult);
_(pose) \
_(scale) \
+/// Calls your macro with the name of each member of XrGeometryInstanceTransformFB, in order.
#define XR_LIST_STRUCT_XrGeometryInstanceTransformFB(_) \
_(type) \
_(next) \
@@ -2343,22 +2609,26 @@ XR_ENUM_STR(XrResult);
_(pose) \
_(scale) \
+/// Calls your macro with the name of each member of XrPassthroughStyleFB, in order.
#define XR_LIST_STRUCT_XrPassthroughStyleFB(_) \
_(type) \
_(next) \
_(textureOpacityFactor) \
_(edgeColor) \
+/// Calls your macro with the name of each member of XrPassthroughColorMapMonoToRgbaFB, in order.
#define XR_LIST_STRUCT_XrPassthroughColorMapMonoToRgbaFB(_) \
_(type) \
_(next) \
_(textureColorMap) \
+/// Calls your macro with the name of each member of XrPassthroughColorMapMonoToMonoFB, in order.
#define XR_LIST_STRUCT_XrPassthroughColorMapMonoToMonoFB(_) \
_(type) \
_(next) \
_(textureColorMap) \
+/// Calls your macro with the name of each member of XrPassthroughBrightnessContrastSaturationFB, in order.
#define XR_LIST_STRUCT_XrPassthroughBrightnessContrastSaturationFB(_) \
_(type) \
_(next) \
@@ -2366,16 +2636,19 @@ XR_ENUM_STR(XrResult);
_(contrast) \
_(saturation) \
+/// Calls your macro with the name of each member of XrEventDataPassthroughStateChangedFB, in order.
#define XR_LIST_STRUCT_XrEventDataPassthroughStateChangedFB(_) \
_(type) \
_(next) \
_(flags) \
+/// Calls your macro with the name of each member of XrRenderModelPathInfoFB, in order.
#define XR_LIST_STRUCT_XrRenderModelPathInfoFB(_) \
_(type) \
_(next) \
_(path) \
+/// Calls your macro with the name of each member of XrRenderModelPropertiesFB, in order.
#define XR_LIST_STRUCT_XrRenderModelPropertiesFB(_) \
_(type) \
_(next) \
@@ -2385,6 +2658,7 @@ XR_ENUM_STR(XrResult);
_(modelVersion) \
_(flags) \
+/// Calls your macro with the name of each member of XrRenderModelBufferFB, in order.
#define XR_LIST_STRUCT_XrRenderModelBufferFB(_) \
_(type) \
_(next) \
@@ -2392,47 +2666,56 @@ XR_ENUM_STR(XrResult);
_(bufferCountOutput) \
_(buffer) \
+/// Calls your macro with the name of each member of XrRenderModelLoadInfoFB, in order.
#define XR_LIST_STRUCT_XrRenderModelLoadInfoFB(_) \
_(type) \
_(next) \
_(modelKey) \
+/// Calls your macro with the name of each member of XrSystemRenderModelPropertiesFB, in order.
#define XR_LIST_STRUCT_XrSystemRenderModelPropertiesFB(_) \
_(type) \
_(next) \
_(supportsRenderModelLoading) \
+/// Calls your macro with the name of each member of XrRenderModelCapabilitiesRequestFB, in order.
#define XR_LIST_STRUCT_XrRenderModelCapabilitiesRequestFB(_) \
_(type) \
_(next) \
_(flags) \
+/// Calls your macro with the name of each member of XrViewLocateFoveatedRenderingVARJO, in order.
#define XR_LIST_STRUCT_XrViewLocateFoveatedRenderingVARJO(_) \
_(type) \
_(next) \
_(foveatedRenderingActive) \
+/// Calls your macro with the name of each member of XrFoveatedViewConfigurationViewVARJO, in order.
#define XR_LIST_STRUCT_XrFoveatedViewConfigurationViewVARJO(_) \
_(type) \
_(next) \
_(foveatedRenderingActive) \
+/// Calls your macro with the name of each member of XrSystemFoveatedRenderingPropertiesVARJO, in order.
#define XR_LIST_STRUCT_XrSystemFoveatedRenderingPropertiesVARJO(_) \
_(type) \
_(next) \
_(supportsFoveatedRendering) \
+/// Calls your macro with the name of each member of XrCompositionLayerDepthTestVARJO, in order.
#define XR_LIST_STRUCT_XrCompositionLayerDepthTestVARJO(_) \
_(type) \
_(next) \
_(depthTestRangeNearZ) \
_(depthTestRangeFarZ) \
+/// Calls your macro with the name of each member of XrSystemMarkerTrackingPropertiesVARJO, in order.
#define XR_LIST_STRUCT_XrSystemMarkerTrackingPropertiesVARJO(_) \
_(type) \
_(next) \
_(supportsMarkerTracking) \
+/// Calls your macro with the name of each member of XrEventDataMarkerTrackingUpdateVARJO, in order.
#define XR_LIST_STRUCT_XrEventDataMarkerTrackingUpdateVARJO(_) \
_(type) \
_(next) \
@@ -2441,35 +2724,42 @@ XR_ENUM_STR(XrResult);
_(isPredicted) \
_(time) \
+/// Calls your macro with the name of each member of XrMarkerSpaceCreateInfoVARJO, in order.
#define XR_LIST_STRUCT_XrMarkerSpaceCreateInfoVARJO(_) \
_(type) \
_(next) \
_(markerId) \
_(poseInMarkerSpace) \
+/// Calls your macro with the name of each member of XrSpatialAnchorPersistenceNameMSFT, in order.
#define XR_LIST_STRUCT_XrSpatialAnchorPersistenceNameMSFT(_) \
_(name) \
+/// Calls your macro with the name of each member of XrSpatialAnchorPersistenceInfoMSFT, in order.
#define XR_LIST_STRUCT_XrSpatialAnchorPersistenceInfoMSFT(_) \
_(type) \
_(next) \
_(spatialAnchorPersistenceName) \
_(spatialAnchor) \
+/// Calls your macro with the name of each member of XrSpatialAnchorFromPersistedAnchorCreateInfoMSFT, in order.
#define XR_LIST_STRUCT_XrSpatialAnchorFromPersistedAnchorCreateInfoMSFT(_) \
_(type) \
_(next) \
_(spatialAnchorStore) \
_(spatialAnchorPersistenceName) \
+/// Calls your macro with the name of each member of XrSpaceQueryInfoBaseHeaderFB, in order.
#define XR_LIST_STRUCT_XrSpaceQueryInfoBaseHeaderFB(_) \
_(type) \
_(next) \
+/// Calls your macro with the name of each member of XrSpaceFilterInfoBaseHeaderFB, in order.
#define XR_LIST_STRUCT_XrSpaceFilterInfoBaseHeaderFB(_) \
_(type) \
_(next) \
+/// Calls your macro with the name of each member of XrSpaceQueryInfoFB, in order.
#define XR_LIST_STRUCT_XrSpaceQueryInfoFB(_) \
_(type) \
_(next) \
@@ -2479,26 +2769,31 @@ XR_ENUM_STR(XrResult);
_(filter) \
_(excludeFilter) \
+/// Calls your macro with the name of each member of XrSpaceStorageLocationFilterInfoFB, in order.
#define XR_LIST_STRUCT_XrSpaceStorageLocationFilterInfoFB(_) \
_(type) \
_(next) \
_(location) \
+/// Calls your macro with the name of each member of XrSpaceUuidFilterInfoFB, in order.
#define XR_LIST_STRUCT_XrSpaceUuidFilterInfoFB(_) \
_(type) \
_(next) \
_(uuidCount) \
_(uuids) \
+/// Calls your macro with the name of each member of XrSpaceComponentFilterInfoFB, in order.
#define XR_LIST_STRUCT_XrSpaceComponentFilterInfoFB(_) \
_(type) \
_(next) \
_(componentType) \
+/// Calls your macro with the name of each member of XrSpaceQueryResultFB, in order.
#define XR_LIST_STRUCT_XrSpaceQueryResultFB(_) \
_(space) \
_(uuid) \
+/// Calls your macro with the name of each member of XrSpaceQueryResultsFB, in order.
#define XR_LIST_STRUCT_XrSpaceQueryResultsFB(_) \
_(type) \
_(next) \
@@ -2506,17 +2801,20 @@ XR_ENUM_STR(XrResult);
_(resultCountOutput) \
_(results) \
+/// Calls your macro with the name of each member of XrEventDataSpaceQueryResultsAvailableFB, in order.
#define XR_LIST_STRUCT_XrEventDataSpaceQueryResultsAvailableFB(_) \
_(type) \
_(next) \
_(requestId) \
+/// Calls your macro with the name of each member of XrEventDataSpaceQueryCompleteFB, in order.
#define XR_LIST_STRUCT_XrEventDataSpaceQueryCompleteFB(_) \
_(type) \
_(next) \
_(requestId) \
_(result) \
+/// Calls your macro with the name of each member of XrSpaceSaveInfoFB, in order.
#define XR_LIST_STRUCT_XrSpaceSaveInfoFB(_) \
_(type) \
_(next) \
@@ -2524,12 +2822,14 @@ XR_ENUM_STR(XrResult);
_(location) \
_(persistenceMode) \
+/// Calls your macro with the name of each member of XrSpaceEraseInfoFB, in order.
#define XR_LIST_STRUCT_XrSpaceEraseInfoFB(_) \
_(type) \
_(next) \
_(space) \
_(location) \
+/// Calls your macro with the name of each member of XrEventDataSpaceSaveCompleteFB, in order.
#define XR_LIST_STRUCT_XrEventDataSpaceSaveCompleteFB(_) \
_(type) \
_(next) \
@@ -2539,6 +2839,7 @@ XR_ENUM_STR(XrResult);
_(uuid) \
_(location) \
+/// Calls your macro with the name of each member of XrEventDataSpaceEraseCompleteFB, in order.
#define XR_LIST_STRUCT_XrEventDataSpaceEraseCompleteFB(_) \
_(type) \
_(next) \
@@ -2548,6 +2849,7 @@ XR_ENUM_STR(XrResult);
_(uuid) \
_(location) \
+/// Calls your macro with the name of each member of XrSwapchainImageFoveationVulkanFB, in order.
#define XR_LIST_STRUCT_XrSwapchainImageFoveationVulkanFB(_) \
_(type) \
_(next) \
@@ -2555,12 +2857,14 @@ XR_ENUM_STR(XrResult);
_(width) \
_(height) \
+/// Calls your macro with the name of each member of XrSwapchainStateAndroidSurfaceDimensionsFB, in order.
#define XR_LIST_STRUCT_XrSwapchainStateAndroidSurfaceDimensionsFB(_) \
_(type) \
_(next) \
_(width) \
_(height) \
+/// Calls your macro with the name of each member of XrSwapchainStateSamplerOpenGLESFB, in order.
#define XR_LIST_STRUCT_XrSwapchainStateSamplerOpenGLESFB(_) \
_(type) \
_(next) \
@@ -2575,6 +2879,7 @@ XR_ENUM_STR(XrResult);
_(maxAnisotropy) \
_(borderColor) \
+/// Calls your macro with the name of each member of XrSwapchainStateSamplerVulkanFB, in order.
#define XR_LIST_STRUCT_XrSwapchainStateSamplerVulkanFB(_) \
_(type) \
_(next) \
@@ -2590,6 +2895,7 @@ XR_ENUM_STR(XrResult);
_(maxAnisotropy) \
_(borderColor) \
+/// Calls your macro with the name of each member of XrCompositionLayerSpaceWarpInfoFB, in order.
#define XR_LIST_STRUCT_XrCompositionLayerSpaceWarpInfoFB(_) \
_(type) \
_(next) \
@@ -2602,26 +2908,31 @@ XR_ENUM_STR(XrResult);
_(nearZ) \
_(farZ) \
+/// Calls your macro with the name of each member of XrSystemSpaceWarpPropertiesFB, in order.
#define XR_LIST_STRUCT_XrSystemSpaceWarpPropertiesFB(_) \
_(type) \
_(next) \
_(recommendedMotionVectorImageRectWidth) \
_(recommendedMotionVectorImageRectHeight) \
+/// Calls your macro with the name of each member of XrExtent3DfFB, in order.
#define XR_LIST_STRUCT_XrExtent3DfFB(_) \
_(width) \
_(height) \
_(depth) \
+/// Calls your macro with the name of each member of XrOffset3DfFB, in order.
#define XR_LIST_STRUCT_XrOffset3DfFB(_) \
_(x) \
_(y) \
_(z) \
+/// Calls your macro with the name of each member of XrRect3DfFB, in order.
#define XR_LIST_STRUCT_XrRect3DfFB(_) \
_(offset) \
_(extent) \
+/// Calls your macro with the name of each member of XrSemanticLabelsFB, in order.
#define XR_LIST_STRUCT_XrSemanticLabelsFB(_) \
_(type) \
_(next) \
@@ -2629,6 +2940,7 @@ XR_ENUM_STR(XrResult);
_(bufferCountOutput) \
_(buffer) \
+/// Calls your macro with the name of each member of XrRoomLayoutFB, in order.
#define XR_LIST_STRUCT_XrRoomLayoutFB(_) \
_(type) \
_(next) \
@@ -2638,6 +2950,7 @@ XR_ENUM_STR(XrResult);
_(wallUuidCountOutput) \
_(wallUuids) \
+/// Calls your macro with the name of each member of XrBoundary2DFB, in order.
#define XR_LIST_STRUCT_XrBoundary2DFB(_) \
_(type) \
_(next) \
@@ -2645,11 +2958,13 @@ XR_ENUM_STR(XrResult);
_(vertexCountOutput) \
_(vertices) \
+/// Calls your macro with the name of each member of XrDigitalLensControlALMALENCE, in order.
#define XR_LIST_STRUCT_XrDigitalLensControlALMALENCE(_) \
_(type) \
_(next) \
_(flags) \
+/// Calls your macro with the name of each member of XrSpaceContainerFB, in order.
#define XR_LIST_STRUCT_XrSpaceContainerFB(_) \
_(type) \
_(next) \
@@ -2657,28 +2972,33 @@ XR_ENUM_STR(XrResult);
_(uuidCountOutput) \
_(uuids) \
+/// Calls your macro with the name of each member of XrPassthroughKeyboardHandsIntensityFB, in order.
#define XR_LIST_STRUCT_XrPassthroughKeyboardHandsIntensityFB(_) \
_(type) \
_(next) \
_(leftHandIntensity) \
_(rightHandIntensity) \
+/// Calls your macro with the name of each member of XrCompositionLayerSettingsFB, in order.
#define XR_LIST_STRUCT_XrCompositionLayerSettingsFB(_) \
_(type) \
_(next) \
_(layerFlags) \
+/// Calls your macro with the name of each member of XrVulkanSwapchainCreateInfoMETA, in order.
#define XR_LIST_STRUCT_XrVulkanSwapchainCreateInfoMETA(_) \
_(type) \
_(next) \
_(additionalCreateFlags) \
_(additionalUsageFlags) \
+/// Calls your macro with the name of each member of XrPerformanceMetricsStateMETA, in order.
#define XR_LIST_STRUCT_XrPerformanceMetricsStateMETA(_) \
_(type) \
_(next) \
_(enabled) \
+/// Calls your macro with the name of each member of XrPerformanceMetricsCounterMETA, in order.
#define XR_LIST_STRUCT_XrPerformanceMetricsCounterMETA(_) \
_(type) \
_(next) \
@@ -2687,8 +3007,107 @@ XR_ENUM_STR(XrResult);
_(uintValue) \
_(floatValue) \
+/// Calls your macro with the name of each member of XrSystemHeadsetIdPropertiesMETA, in order.
+#define XR_LIST_STRUCT_XrSystemHeadsetIdPropertiesMETA(_) \
+ _(type) \
+ _(next) \
+ _(id) \
+
+/// Calls your macro with the name of each member of XrPassthroughCreateInfoHTC, in order.
+#define XR_LIST_STRUCT_XrPassthroughCreateInfoHTC(_) \
+ _(type) \
+ _(next) \
+ _(form) \
+
+/// Calls your macro with the name of each member of XrPassthroughColorHTC, in order.
+#define XR_LIST_STRUCT_XrPassthroughColorHTC(_) \
+ _(type) \
+ _(next) \
+ _(alpha) \
+
+/// Calls your macro with the name of each member of XrPassthroughMeshTransformInfoHTC, in order.
+#define XR_LIST_STRUCT_XrPassthroughMeshTransformInfoHTC(_) \
+ _(type) \
+ _(next) \
+ _(vertexCount) \
+ _(vertices) \
+ _(indexCount) \
+ _(indices) \
+ _(baseSpace) \
+ _(time) \
+ _(pose) \
+ _(scale) \
+
+/// Calls your macro with the name of each member of XrCompositionLayerPassthroughHTC, in order.
+#define XR_LIST_STRUCT_XrCompositionLayerPassthroughHTC(_) \
+ _(type) \
+ _(next) \
+ _(layerFlags) \
+ _(space) \
+ _(passthrough) \
+ _(color) \
+
+/// Calls your macro with the name of each member of XrFoveationApplyInfoHTC, in order.
+#define XR_LIST_STRUCT_XrFoveationApplyInfoHTC(_) \
+ _(type) \
+ _(next) \
+ _(mode) \
+ _(subImageCount) \
+ _(subImages) \
+
+/// Calls your macro with the name of each member of XrFoveationConfigurationHTC, in order.
+#define XR_LIST_STRUCT_XrFoveationConfigurationHTC(_) \
+ _(level) \
+ _(clearFovDegree) \
+ _(focalCenterOffset) \
+/// Calls your macro with the name of each member of XrFoveationDynamicModeInfoHTC, in order.
+#define XR_LIST_STRUCT_XrFoveationDynamicModeInfoHTC(_) \
+ _(type) \
+ _(next) \
+ _(dynamicFlags) \
+/// Calls your macro with the name of each member of XrFoveationCustomModeInfoHTC, in order.
+#define XR_LIST_STRUCT_XrFoveationCustomModeInfoHTC(_) \
+ _(type) \
+ _(next) \
+ _(configCount) \
+ _(configs) \
+
+/// Calls your macro with the name of each member of XrActiveActionSetPriorityEXT, in order.
+#define XR_LIST_STRUCT_XrActiveActionSetPriorityEXT(_) \
+ _(actionSet) \
+ _(priorityOverride) \
+
+/// Calls your macro with the name of each member of XrActiveActionSetPrioritiesEXT, in order.
+#define XR_LIST_STRUCT_XrActiveActionSetPrioritiesEXT(_) \
+ _(type) \
+ _(next) \
+ _(actionSetPriorityCount) \
+ _(actionSetPriorities) \
+
+
+
+/// Calls your macro with the structure type name and the XrStructureType constant for
+/// each known/available structure type, excluding those unavailable due to preprocessor definitions.
+#define XR_LIST_STRUCTURE_TYPES(_) \
+ XR_LIST_STRUCTURE_TYPES_CORE(_) \
+ XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_D3D11(_) \
+ XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_D3D12(_) \
+ XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL(_) \
+ XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_XR_USE_PLATFORM_WAYLAND(_) \
+ XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_XR_USE_PLATFORM_WIN32(_) \
+ XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_XR_USE_PLATFORM_XCB(_) \
+ XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_XR_USE_PLATFORM_XLIB(_) \
+ XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_ES(_) \
+ XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_ES_XR_USE_PLATFORM_ANDROID(_) \
+ XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_VULKAN(_) \
+ XR_LIST_STRUCTURE_TYPES_XR_USE_PLATFORM_ANDROID(_) \
+ XR_LIST_STRUCTURE_TYPES_XR_USE_PLATFORM_EGL(_) \
+ XR_LIST_STRUCTURE_TYPES_XR_USE_PLATFORM_WIN32(_) \
+
+
+/// Implementation detail of XR_LIST_STRUCTURE_TYPES() - structure types available without any preprocessor definitions
#define XR_LIST_STRUCTURE_TYPES_CORE(_) \
_(XrApiLayerProperties, XR_TYPE_API_LAYER_PROPERTIES) \
_(XrExtensionProperties, XR_TYPE_EXTENSION_PROPERTIES) \
@@ -2889,99 +3308,117 @@ XR_ENUM_STR(XrResult);
_(XrCompositionLayerSettingsFB, XR_TYPE_COMPOSITION_LAYER_SETTINGS_FB) \
_(XrPerformanceMetricsStateMETA, XR_TYPE_PERFORMANCE_METRICS_STATE_META) \
_(XrPerformanceMetricsCounterMETA, XR_TYPE_PERFORMANCE_METRICS_COUNTER_META) \
-
-
+ _(XrSystemHeadsetIdPropertiesMETA, XR_TYPE_SYSTEM_HEADSET_ID_PROPERTIES_META) \
+ _(XrPassthroughCreateInfoHTC, XR_TYPE_PASSTHROUGH_CREATE_INFO_HTC) \
+ _(XrPassthroughColorHTC, XR_TYPE_PASSTHROUGH_COLOR_HTC) \
+ _(XrPassthroughMeshTransformInfoHTC, XR_TYPE_PASSTHROUGH_MESH_TRANSFORM_INFO_HTC) \
+ _(XrCompositionLayerPassthroughHTC, XR_TYPE_COMPOSITION_LAYER_PASSTHROUGH_HTC) \
+ _(XrFoveationApplyInfoHTC, XR_TYPE_FOVEATION_APPLY_INFO_HTC) \
+ _(XrFoveationDynamicModeInfoHTC, XR_TYPE_FOVEATION_DYNAMIC_MODE_INFO_HTC) \
+ _(XrFoveationCustomModeInfoHTC, XR_TYPE_FOVEATION_CUSTOM_MODE_INFO_HTC) \
+ _(XrActiveActionSetPrioritiesEXT, XR_TYPE_ACTIVE_ACTION_SET_PRIORITIES_EXT) \
#if defined(XR_USE_GRAPHICS_API_D3D11)
+/// Implementation detail of XR_LIST_STRUCTURE_TYPES()
+/// Structure types available only when XR_USE_GRAPHICS_API_D3D11 is defined
#define XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_D3D11(_) \
_(XrGraphicsBindingD3D11KHR, XR_TYPE_GRAPHICS_BINDING_D3D11_KHR) \
_(XrSwapchainImageD3D11KHR, XR_TYPE_SWAPCHAIN_IMAGE_D3D11_KHR) \
_(XrGraphicsRequirementsD3D11KHR, XR_TYPE_GRAPHICS_REQUIREMENTS_D3D11_KHR) \
-
#else
#define XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_D3D11(_)
#endif
#if defined(XR_USE_GRAPHICS_API_D3D12)
+/// Implementation detail of XR_LIST_STRUCTURE_TYPES()
+/// Structure types available only when XR_USE_GRAPHICS_API_D3D12 is defined
#define XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_D3D12(_) \
_(XrGraphicsBindingD3D12KHR, XR_TYPE_GRAPHICS_BINDING_D3D12_KHR) \
_(XrSwapchainImageD3D12KHR, XR_TYPE_SWAPCHAIN_IMAGE_D3D12_KHR) \
_(XrGraphicsRequirementsD3D12KHR, XR_TYPE_GRAPHICS_REQUIREMENTS_D3D12_KHR) \
-
#else
#define XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_D3D12(_)
#endif
#if defined(XR_USE_GRAPHICS_API_OPENGL)
+/// Implementation detail of XR_LIST_STRUCTURE_TYPES()
+/// Structure types available only when XR_USE_GRAPHICS_API_OPENGL is defined
#define XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL(_) \
_(XrSwapchainImageOpenGLKHR, XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_KHR) \
_(XrGraphicsRequirementsOpenGLKHR, XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_KHR) \
-
#else
#define XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL(_)
#endif
#if defined(XR_USE_GRAPHICS_API_OPENGL) && defined(XR_USE_PLATFORM_WAYLAND)
+/// Implementation detail of XR_LIST_STRUCTURE_TYPES()
+/// Structure types available only when XR_USE_GRAPHICS_API_OPENGL and XR_USE_PLATFORM_WAYLAND are defined
#define XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_XR_USE_PLATFORM_WAYLAND(_) \
_(XrGraphicsBindingOpenGLWaylandKHR, XR_TYPE_GRAPHICS_BINDING_OPENGL_WAYLAND_KHR) \
-
#else
#define XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_XR_USE_PLATFORM_WAYLAND(_)
#endif
#if defined(XR_USE_GRAPHICS_API_OPENGL) && defined(XR_USE_PLATFORM_WIN32)
+/// Implementation detail of XR_LIST_STRUCTURE_TYPES()
+/// Structure types available only when XR_USE_GRAPHICS_API_OPENGL and XR_USE_PLATFORM_WIN32 are defined
#define XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_XR_USE_PLATFORM_WIN32(_) \
_(XrGraphicsBindingOpenGLWin32KHR, XR_TYPE_GRAPHICS_BINDING_OPENGL_WIN32_KHR) \
-
#else
#define XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_XR_USE_PLATFORM_WIN32(_)
#endif
#if defined(XR_USE_GRAPHICS_API_OPENGL) && defined(XR_USE_PLATFORM_XCB)
+/// Implementation detail of XR_LIST_STRUCTURE_TYPES()
+/// Structure types available only when XR_USE_GRAPHICS_API_OPENGL and XR_USE_PLATFORM_XCB are defined
#define XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_XR_USE_PLATFORM_XCB(_) \
_(XrGraphicsBindingOpenGLXcbKHR, XR_TYPE_GRAPHICS_BINDING_OPENGL_XCB_KHR) \
-
#else
#define XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_XR_USE_PLATFORM_XCB(_)
#endif
#if defined(XR_USE_GRAPHICS_API_OPENGL) && defined(XR_USE_PLATFORM_XLIB)
+/// Implementation detail of XR_LIST_STRUCTURE_TYPES()
+/// Structure types available only when XR_USE_GRAPHICS_API_OPENGL and XR_USE_PLATFORM_XLIB are defined
#define XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_XR_USE_PLATFORM_XLIB(_) \
_(XrGraphicsBindingOpenGLXlibKHR, XR_TYPE_GRAPHICS_BINDING_OPENGL_XLIB_KHR) \
-
#else
#define XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_XR_USE_PLATFORM_XLIB(_)
#endif
#if defined(XR_USE_GRAPHICS_API_OPENGL_ES)
+/// Implementation detail of XR_LIST_STRUCTURE_TYPES()
+/// Structure types available only when XR_USE_GRAPHICS_API_OPENGL_ES is defined
#define XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_ES(_) \
_(XrSwapchainImageOpenGLESKHR, XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_ES_KHR) \
_(XrGraphicsRequirementsOpenGLESKHR, XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_ES_KHR) \
_(XrSwapchainStateSamplerOpenGLESFB, XR_TYPE_SWAPCHAIN_STATE_SAMPLER_OPENGL_ES_FB) \
-
#else
#define XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_ES(_)
#endif
#if defined(XR_USE_GRAPHICS_API_OPENGL_ES) && defined(XR_USE_PLATFORM_ANDROID)
+/// Implementation detail of XR_LIST_STRUCTURE_TYPES()
+/// Structure types available only when XR_USE_GRAPHICS_API_OPENGL_ES and XR_USE_PLATFORM_ANDROID are defined
#define XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_ES_XR_USE_PLATFORM_ANDROID(_) \
_(XrGraphicsBindingOpenGLESAndroidKHR, XR_TYPE_GRAPHICS_BINDING_OPENGL_ES_ANDROID_KHR) \
-
#else
#define XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_ES_XR_USE_PLATFORM_ANDROID(_)
#endif
#if defined(XR_USE_GRAPHICS_API_VULKAN)
+/// Implementation detail of XR_LIST_STRUCTURE_TYPES()
+/// Structure types available only when XR_USE_GRAPHICS_API_VULKAN is defined
#define XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_VULKAN(_) \
_(XrVulkanSwapchainFormatListCreateInfoKHR, XR_TYPE_VULKAN_SWAPCHAIN_FORMAT_LIST_CREATE_INFO_KHR) \
_(XrGraphicsBindingVulkanKHR, XR_TYPE_GRAPHICS_BINDING_VULKAN_KHR) \
@@ -2994,58 +3431,47 @@ XR_ENUM_STR(XrResult);
_(XrSwapchainStateSamplerVulkanFB, XR_TYPE_SWAPCHAIN_STATE_SAMPLER_VULKAN_FB) \
_(XrVulkanSwapchainCreateInfoMETA, XR_TYPE_VULKAN_SWAPCHAIN_CREATE_INFO_META) \
-
#else
#define XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_VULKAN(_)
#endif
#if defined(XR_USE_PLATFORM_ANDROID)
+/// Implementation detail of XR_LIST_STRUCTURE_TYPES()
+/// Structure types available only when XR_USE_PLATFORM_ANDROID is defined
#define XR_LIST_STRUCTURE_TYPES_XR_USE_PLATFORM_ANDROID(_) \
_(XrInstanceCreateInfoAndroidKHR, XR_TYPE_INSTANCE_CREATE_INFO_ANDROID_KHR) \
_(XrLoaderInitInfoAndroidKHR, XR_TYPE_LOADER_INIT_INFO_ANDROID_KHR) \
_(XrAndroidSurfaceSwapchainCreateInfoFB, XR_TYPE_ANDROID_SURFACE_SWAPCHAIN_CREATE_INFO_FB) \
_(XrSwapchainStateAndroidSurfaceDimensionsFB, XR_TYPE_SWAPCHAIN_STATE_ANDROID_SURFACE_DIMENSIONS_FB) \
-
#else
#define XR_LIST_STRUCTURE_TYPES_XR_USE_PLATFORM_ANDROID(_)
#endif
#if defined(XR_USE_PLATFORM_EGL)
+/// Implementation detail of XR_LIST_STRUCTURE_TYPES()
+/// Structure types available only when XR_USE_PLATFORM_EGL is defined
#define XR_LIST_STRUCTURE_TYPES_XR_USE_PLATFORM_EGL(_) \
_(XrGraphicsBindingEGLMNDX, XR_TYPE_GRAPHICS_BINDING_EGL_MNDX) \
-
#else
#define XR_LIST_STRUCTURE_TYPES_XR_USE_PLATFORM_EGL(_)
#endif
#if defined(XR_USE_PLATFORM_WIN32)
+/// Implementation detail of XR_LIST_STRUCTURE_TYPES()
+/// Structure types available only when XR_USE_PLATFORM_WIN32 is defined
#define XR_LIST_STRUCTURE_TYPES_XR_USE_PLATFORM_WIN32(_) \
_(XrHolographicWindowAttachmentMSFT, XR_TYPE_HOLOGRAPHIC_WINDOW_ATTACHMENT_MSFT) \
-
#else
#define XR_LIST_STRUCTURE_TYPES_XR_USE_PLATFORM_WIN32(_)
#endif
-#define XR_LIST_STRUCTURE_TYPES(_) \
- XR_LIST_STRUCTURE_TYPES_CORE(_) \
- XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_D3D11(_) \
- XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_D3D12(_) \
- XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL(_) \
- XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_XR_USE_PLATFORM_WAYLAND(_) \
- XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_XR_USE_PLATFORM_WIN32(_) \
- XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_XR_USE_PLATFORM_XCB(_) \
- XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_XR_USE_PLATFORM_XLIB(_) \
- XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_ES(_) \
- XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_ES_XR_USE_PLATFORM_ANDROID(_) \
- XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_VULKAN(_) \
- XR_LIST_STRUCTURE_TYPES_XR_USE_PLATFORM_ANDROID(_) \
- XR_LIST_STRUCTURE_TYPES_XR_USE_PLATFORM_EGL(_) \
- XR_LIST_STRUCTURE_TYPES_XR_USE_PLATFORM_WIN32(_) \
+/// Calls your macro with the name and extension number of all known
+/// extensions in this version of the spec.
#define XR_LIST_EXTENSIONS(_) \
_(XR_KHR_android_thread_settings, 4) \
_(XR_KHR_android_surface_swapchain, 5) \
@@ -3151,7 +3577,11 @@ XR_ENUM_STR(XrResult);
_(XR_FB_composition_layer_settings, 205) \
_(XR_META_vulkan_swapchain_create_info, 228) \
_(XR_META_performance_metrics, 233) \
+ _(XR_META_headset_id, 246) \
_(XR_EXT_uuid, 300) \
+ _(XR_HTC_passthrough, 318) \
+ _(XR_HTC_foveation, 319) \
+ _(XR_EXT_active_action_set_priority, 374) \
#endif
diff --git a/thirdparty/openxr/include/openxr/openxr_reflection_parent_structs.h b/thirdparty/openxr/include/openxr/openxr_reflection_parent_structs.h
new file mode 100644
index 0000000000..19b0e1c3f6
--- /dev/null
+++ b/thirdparty/openxr/include/openxr/openxr_reflection_parent_structs.h
@@ -0,0 +1,261 @@
+#ifndef OPENXR_REFLECTION_PARENT_STRUCTS_H_
+#define OPENXR_REFLECTION_PARENT_STRUCTS_H_ 1
+
+/*
+** Copyright (c) 2017-2022, The Khronos Group Inc.
+**
+** SPDX-License-Identifier: Apache-2.0 OR MIT
+*/
+
+/*
+** This header is generated from the Khronos OpenXR XML API Registry.
+**
+*/
+
+#include "openxr.h"
+
+/*
+This file contains expansion macros (X Macros) for OpenXR structures that have a parent type.
+*/
+
+
+/// Like XR_LIST_ALL_STRUCTURE_TYPES, but only includes types whose parent struct type is XrCompositionLayerBaseHeader
+#define XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrCompositionLayerBaseHeader(_avail, _unavail) \
+ _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrCompositionLayerBaseHeader_CORE(_avail, _unavail) \
+
+
+// Implementation detail of XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrCompositionLayerBaseHeader()
+#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrCompositionLayerBaseHeader_CORE(_avail, _unavail) \
+ _avail(XrCompositionLayerProjection, XR_TYPE_COMPOSITION_LAYER_PROJECTION) \
+ _avail(XrCompositionLayerQuad, XR_TYPE_COMPOSITION_LAYER_QUAD) \
+ _avail(XrCompositionLayerCubeKHR, XR_TYPE_COMPOSITION_LAYER_CUBE_KHR) \
+ _avail(XrCompositionLayerCylinderKHR, XR_TYPE_COMPOSITION_LAYER_CYLINDER_KHR) \
+ _avail(XrCompositionLayerEquirectKHR, XR_TYPE_COMPOSITION_LAYER_EQUIRECT_KHR) \
+ _avail(XrCompositionLayerEquirect2KHR, XR_TYPE_COMPOSITION_LAYER_EQUIRECT2_KHR) \
+ _avail(XrCompositionLayerPassthroughHTC, XR_TYPE_COMPOSITION_LAYER_PASSTHROUGH_HTC) \
+
+
+
+
+
+/// Like XR_LIST_ALL_STRUCTURE_TYPES, but only includes types whose parent struct type is XrEventDataBaseHeader
+#define XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrEventDataBaseHeader(_avail, _unavail) \
+ _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrEventDataBaseHeader_CORE(_avail, _unavail) \
+
+
+// Implementation detail of XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrEventDataBaseHeader()
+#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrEventDataBaseHeader_CORE(_avail, _unavail) \
+ _avail(XrEventDataEventsLost, XR_TYPE_EVENT_DATA_EVENTS_LOST) \
+ _avail(XrEventDataInstanceLossPending, XR_TYPE_EVENT_DATA_INSTANCE_LOSS_PENDING) \
+ _avail(XrEventDataSessionStateChanged, XR_TYPE_EVENT_DATA_SESSION_STATE_CHANGED) \
+ _avail(XrEventDataReferenceSpaceChangePending, XR_TYPE_EVENT_DATA_REFERENCE_SPACE_CHANGE_PENDING) \
+ _avail(XrEventDataInteractionProfileChanged, XR_TYPE_EVENT_DATA_INTERACTION_PROFILE_CHANGED) \
+ _avail(XrEventDataVisibilityMaskChangedKHR, XR_TYPE_EVENT_DATA_VISIBILITY_MASK_CHANGED_KHR) \
+ _avail(XrEventDataPerfSettingsEXT, XR_TYPE_EVENT_DATA_PERF_SETTINGS_EXT) \
+ _avail(XrEventDataMainSessionVisibilityChangedEXTX, XR_TYPE_EVENT_DATA_MAIN_SESSION_VISIBILITY_CHANGED_EXTX) \
+ _avail(XrEventDataDisplayRefreshRateChangedFB, XR_TYPE_EVENT_DATA_DISPLAY_REFRESH_RATE_CHANGED_FB) \
+ _avail(XrEventDataViveTrackerConnectedHTCX, XR_TYPE_EVENT_DATA_VIVE_TRACKER_CONNECTED_HTCX) \
+ _avail(XrEventDataSpatialAnchorCreateCompleteFB, XR_TYPE_EVENT_DATA_SPATIAL_ANCHOR_CREATE_COMPLETE_FB) \
+ _avail(XrEventDataSpaceSetStatusCompleteFB, XR_TYPE_EVENT_DATA_SPACE_SET_STATUS_COMPLETE_FB) \
+ _avail(XrEventDataMarkerTrackingUpdateVARJO, XR_TYPE_EVENT_DATA_MARKER_TRACKING_UPDATE_VARJO) \
+ _avail(XrEventDataSpaceQueryResultsAvailableFB, XR_TYPE_EVENT_DATA_SPACE_QUERY_RESULTS_AVAILABLE_FB) \
+ _avail(XrEventDataSpaceQueryCompleteFB, XR_TYPE_EVENT_DATA_SPACE_QUERY_COMPLETE_FB) \
+ _avail(XrEventDataSpaceSaveCompleteFB, XR_TYPE_EVENT_DATA_SPACE_SAVE_COMPLETE_FB) \
+ _avail(XrEventDataSpaceEraseCompleteFB, XR_TYPE_EVENT_DATA_SPACE_ERASE_COMPLETE_FB) \
+
+
+
+
+
+/// Like XR_LIST_ALL_STRUCTURE_TYPES, but only includes types whose parent struct type is XrHapticBaseHeader
+#define XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrHapticBaseHeader(_avail, _unavail) \
+ _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrHapticBaseHeader_CORE(_avail, _unavail) \
+
+
+// Implementation detail of XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrHapticBaseHeader()
+#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrHapticBaseHeader_CORE(_avail, _unavail) \
+ _avail(XrHapticVibration, XR_TYPE_HAPTIC_VIBRATION) \
+
+
+
+
+
+/// Like XR_LIST_ALL_STRUCTURE_TYPES, but only includes types whose parent struct type is XrSwapchainImageBaseHeader
+#define XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainImageBaseHeader(_avail, _unavail) \
+ _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainImageBaseHeader_CORE(_avail, _unavail) \
+ _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainImageBaseHeader_XR_USE_GRAPHICS_API_D3D11(_avail, _unavail) \
+ _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainImageBaseHeader_XR_USE_GRAPHICS_API_D3D12(_avail, _unavail) \
+ _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainImageBaseHeader_XR_USE_GRAPHICS_API_OPENGL(_avail, _unavail) \
+ _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainImageBaseHeader_XR_USE_GRAPHICS_API_OPENGL_ES(_avail, _unavail) \
+ _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainImageBaseHeader_XR_USE_GRAPHICS_API_VULKAN(_avail, _unavail) \
+
+
+// Implementation detail of XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainImageBaseHeader()
+#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainImageBaseHeader_CORE(_avail, _unavail) \
+
+
+#if defined(XR_USE_GRAPHICS_API_D3D11)
+#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainImageBaseHeader_XR_USE_GRAPHICS_API_D3D11(_avail, _unavail) \
+ _avail(XrSwapchainImageD3D11KHR, XR_TYPE_SWAPCHAIN_IMAGE_D3D11_KHR) \
+
+#else
+#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainImageBaseHeader_XR_USE_GRAPHICS_API_D3D11(_avail, _unavail) \
+ _unavail(XrSwapchainImageD3D11KHR, XR_TYPE_SWAPCHAIN_IMAGE_D3D11_KHR) \
+
+#endif
+
+#if defined(XR_USE_GRAPHICS_API_D3D12)
+#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainImageBaseHeader_XR_USE_GRAPHICS_API_D3D12(_avail, _unavail) \
+ _avail(XrSwapchainImageD3D12KHR, XR_TYPE_SWAPCHAIN_IMAGE_D3D12_KHR) \
+
+#else
+#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainImageBaseHeader_XR_USE_GRAPHICS_API_D3D12(_avail, _unavail) \
+ _unavail(XrSwapchainImageD3D12KHR, XR_TYPE_SWAPCHAIN_IMAGE_D3D12_KHR) \
+
+#endif
+
+#if defined(XR_USE_GRAPHICS_API_OPENGL)
+#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainImageBaseHeader_XR_USE_GRAPHICS_API_OPENGL(_avail, _unavail) \
+ _avail(XrSwapchainImageOpenGLKHR, XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_KHR) \
+
+#else
+#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainImageBaseHeader_XR_USE_GRAPHICS_API_OPENGL(_avail, _unavail) \
+ _unavail(XrSwapchainImageOpenGLKHR, XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_KHR) \
+
+#endif
+
+#if defined(XR_USE_GRAPHICS_API_OPENGL_ES)
+#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainImageBaseHeader_XR_USE_GRAPHICS_API_OPENGL_ES(_avail, _unavail) \
+ _avail(XrSwapchainImageOpenGLESKHR, XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_ES_KHR) \
+
+#else
+#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainImageBaseHeader_XR_USE_GRAPHICS_API_OPENGL_ES(_avail, _unavail) \
+ _unavail(XrSwapchainImageOpenGLESKHR, XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_ES_KHR) \
+
+#endif
+
+#if defined(XR_USE_GRAPHICS_API_VULKAN)
+#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainImageBaseHeader_XR_USE_GRAPHICS_API_VULKAN(_avail, _unavail) \
+ _avail(XrSwapchainImageVulkanKHR, XR_TYPE_SWAPCHAIN_IMAGE_VULKAN_KHR) \
+
+#else
+#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainImageBaseHeader_XR_USE_GRAPHICS_API_VULKAN(_avail, _unavail) \
+ _unavail(XrSwapchainImageVulkanKHR, XR_TYPE_SWAPCHAIN_IMAGE_VULKAN_KHR) \
+
+#endif
+
+
+
+
+/// Like XR_LIST_ALL_STRUCTURE_TYPES, but only includes types whose parent struct type is XrLoaderInitInfoBaseHeaderKHR
+#define XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrLoaderInitInfoBaseHeaderKHR(_avail, _unavail) \
+ _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrLoaderInitInfoBaseHeaderKHR_CORE(_avail, _unavail) \
+ _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrLoaderInitInfoBaseHeaderKHR_XR_USE_PLATFORM_ANDROID(_avail, _unavail) \
+
+
+// Implementation detail of XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrLoaderInitInfoBaseHeaderKHR()
+#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrLoaderInitInfoBaseHeaderKHR_CORE(_avail, _unavail) \
+
+
+#if defined(XR_USE_PLATFORM_ANDROID)
+#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrLoaderInitInfoBaseHeaderKHR_XR_USE_PLATFORM_ANDROID(_avail, _unavail) \
+ _avail(XrLoaderInitInfoAndroidKHR, XR_TYPE_LOADER_INIT_INFO_ANDROID_KHR) \
+
+#else
+#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrLoaderInitInfoBaseHeaderKHR_XR_USE_PLATFORM_ANDROID(_avail, _unavail) \
+ _unavail(XrLoaderInitInfoAndroidKHR, XR_TYPE_LOADER_INIT_INFO_ANDROID_KHR) \
+
+#endif
+
+
+
+
+/// Like XR_LIST_ALL_STRUCTURE_TYPES, but only includes types whose parent struct type is XrBindingModificationBaseHeaderKHR
+#define XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrBindingModificationBaseHeaderKHR(_avail, _unavail) \
+ _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrBindingModificationBaseHeaderKHR_CORE(_avail, _unavail) \
+
+
+// Implementation detail of XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrBindingModificationBaseHeaderKHR()
+#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrBindingModificationBaseHeaderKHR_CORE(_avail, _unavail) \
+ _avail(XrInteractionProfileDpadBindingEXT, XR_TYPE_INTERACTION_PROFILE_DPAD_BINDING_EXT) \
+ _avail(XrInteractionProfileAnalogThresholdVALVE, XR_TYPE_INTERACTION_PROFILE_ANALOG_THRESHOLD_VALVE) \
+
+
+
+
+
+/// Like XR_LIST_ALL_STRUCTURE_TYPES, but only includes types whose parent struct type is XrSwapchainStateBaseHeaderFB
+#define XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainStateBaseHeaderFB(_avail, _unavail) \
+ _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainStateBaseHeaderFB_CORE(_avail, _unavail) \
+ _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainStateBaseHeaderFB_XR_USE_GRAPHICS_API_OPENGL_ES(_avail, _unavail) \
+ _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainStateBaseHeaderFB_XR_USE_GRAPHICS_API_VULKAN(_avail, _unavail) \
+ _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainStateBaseHeaderFB_XR_USE_PLATFORM_ANDROID(_avail, _unavail) \
+
+
+// Implementation detail of XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainStateBaseHeaderFB()
+#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainStateBaseHeaderFB_CORE(_avail, _unavail) \
+ _avail(XrSwapchainStateFoveationFB, XR_TYPE_SWAPCHAIN_STATE_FOVEATION_FB) \
+
+
+#if defined(XR_USE_GRAPHICS_API_OPENGL_ES)
+#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainStateBaseHeaderFB_XR_USE_GRAPHICS_API_OPENGL_ES(_avail, _unavail) \
+ _avail(XrSwapchainStateSamplerOpenGLESFB, XR_TYPE_SWAPCHAIN_STATE_SAMPLER_OPENGL_ES_FB) \
+
+#else
+#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainStateBaseHeaderFB_XR_USE_GRAPHICS_API_OPENGL_ES(_avail, _unavail) \
+ _unavail(XrSwapchainStateSamplerOpenGLESFB, XR_TYPE_SWAPCHAIN_STATE_SAMPLER_OPENGL_ES_FB) \
+
+#endif
+
+#if defined(XR_USE_GRAPHICS_API_VULKAN)
+#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainStateBaseHeaderFB_XR_USE_GRAPHICS_API_VULKAN(_avail, _unavail) \
+ _avail(XrSwapchainStateSamplerVulkanFB, XR_TYPE_SWAPCHAIN_STATE_SAMPLER_VULKAN_FB) \
+
+#else
+#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainStateBaseHeaderFB_XR_USE_GRAPHICS_API_VULKAN(_avail, _unavail) \
+ _unavail(XrSwapchainStateSamplerVulkanFB, XR_TYPE_SWAPCHAIN_STATE_SAMPLER_VULKAN_FB) \
+
+#endif
+
+#if defined(XR_USE_PLATFORM_ANDROID)
+#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainStateBaseHeaderFB_XR_USE_PLATFORM_ANDROID(_avail, _unavail) \
+ _avail(XrSwapchainStateAndroidSurfaceDimensionsFB, XR_TYPE_SWAPCHAIN_STATE_ANDROID_SURFACE_DIMENSIONS_FB) \
+
+#else
+#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainStateBaseHeaderFB_XR_USE_PLATFORM_ANDROID(_avail, _unavail) \
+ _unavail(XrSwapchainStateAndroidSurfaceDimensionsFB, XR_TYPE_SWAPCHAIN_STATE_ANDROID_SURFACE_DIMENSIONS_FB) \
+
+#endif
+
+
+
+
+/// Like XR_LIST_ALL_STRUCTURE_TYPES, but only includes types whose parent struct type is XrSpaceQueryInfoBaseHeaderFB
+#define XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSpaceQueryInfoBaseHeaderFB(_avail, _unavail) \
+ _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSpaceQueryInfoBaseHeaderFB_CORE(_avail, _unavail) \
+
+
+// Implementation detail of XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSpaceQueryInfoBaseHeaderFB()
+#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSpaceQueryInfoBaseHeaderFB_CORE(_avail, _unavail) \
+ _avail(XrSpaceQueryInfoFB, XR_TYPE_SPACE_QUERY_INFO_FB) \
+
+
+
+
+
+/// Like XR_LIST_ALL_STRUCTURE_TYPES, but only includes types whose parent struct type is XrSpaceFilterInfoBaseHeaderFB
+#define XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSpaceFilterInfoBaseHeaderFB(_avail, _unavail) \
+ _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSpaceFilterInfoBaseHeaderFB_CORE(_avail, _unavail) \
+
+
+// Implementation detail of XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSpaceFilterInfoBaseHeaderFB()
+#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSpaceFilterInfoBaseHeaderFB_CORE(_avail, _unavail) \
+ _avail(XrSpaceUuidFilterInfoFB, XR_TYPE_SPACE_UUID_FILTER_INFO_FB) \
+ _avail(XrSpaceComponentFilterInfoFB, XR_TYPE_SPACE_COMPONENT_FILTER_INFO_FB) \
+
+
+
+
+
+#endif
+
diff --git a/thirdparty/openxr/include/openxr/openxr_reflection_structs.h b/thirdparty/openxr/include/openxr/openxr_reflection_structs.h
new file mode 100644
index 0000000000..300bbbad6d
--- /dev/null
+++ b/thirdparty/openxr/include/openxr/openxr_reflection_structs.h
@@ -0,0 +1,427 @@
+#ifndef OPENXR_REFLECTION_STRUCTS_H_
+#define OPENXR_REFLECTION_STRUCTS_H_ 1
+
+/*
+** Copyright (c) 2017-2022, The Khronos Group Inc.
+**
+** SPDX-License-Identifier: Apache-2.0 OR MIT
+*/
+
+/*
+** This header is generated from the Khronos OpenXR XML API Registry.
+**
+*/
+
+#include "openxr.h"
+
+/*
+This file contains expansion macros (X Macros) for OpenXR structures.
+*/
+
+
+
+/// Calls one of your macros with the structure type name and the XrStructureType constant for
+/// each known structure type. The first macro (_avail) is called for those that are available,
+/// while the second macro (_unavail) is called for those unavailable due to preprocessor definitions.
+#define XR_LIST_ALL_STRUCTURE_TYPES(_avail, _unavail) \
+ _impl_XR_LIST_ALL_STRUCTURE_TYPES_CORE(_avail, _unavail) \
+ _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_D3D11(_avail, _unavail) \
+ _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_D3D12(_avail, _unavail) \
+ _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL(_avail, _unavail) \
+ _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_XR_USE_PLATFORM_WAYLAND(_avail, _unavail) \
+ _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_XR_USE_PLATFORM_WIN32(_avail, _unavail) \
+ _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_XR_USE_PLATFORM_XCB(_avail, _unavail) \
+ _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_XR_USE_PLATFORM_XLIB(_avail, _unavail) \
+ _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_ES(_avail, _unavail) \
+ _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_ES_XR_USE_PLATFORM_ANDROID(_avail, _unavail) \
+ _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_VULKAN(_avail, _unavail) \
+ _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_PLATFORM_ANDROID(_avail, _unavail) \
+ _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_PLATFORM_EGL(_avail, _unavail) \
+ _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_PLATFORM_WIN32(_avail, _unavail) \
+
+
+// Implementation detail of XR_LIST_ALL_STRUCTURE_TYPES()
+#define _impl_XR_LIST_ALL_STRUCTURE_TYPES_CORE(_avail, _unavail) \
+ _avail(XrApiLayerProperties, XR_TYPE_API_LAYER_PROPERTIES) \
+ _avail(XrExtensionProperties, XR_TYPE_EXTENSION_PROPERTIES) \
+ _avail(XrInstanceCreateInfo, XR_TYPE_INSTANCE_CREATE_INFO) \
+ _avail(XrInstanceProperties, XR_TYPE_INSTANCE_PROPERTIES) \
+ _avail(XrEventDataBuffer, XR_TYPE_EVENT_DATA_BUFFER) \
+ _avail(XrSystemGetInfo, XR_TYPE_SYSTEM_GET_INFO) \
+ _avail(XrSystemProperties, XR_TYPE_SYSTEM_PROPERTIES) \
+ _avail(XrSessionCreateInfo, XR_TYPE_SESSION_CREATE_INFO) \
+ _avail(XrSpaceVelocity, XR_TYPE_SPACE_VELOCITY) \
+ _avail(XrReferenceSpaceCreateInfo, XR_TYPE_REFERENCE_SPACE_CREATE_INFO) \
+ _avail(XrActionSpaceCreateInfo, XR_TYPE_ACTION_SPACE_CREATE_INFO) \
+ _avail(XrSpaceLocation, XR_TYPE_SPACE_LOCATION) \
+ _avail(XrViewConfigurationProperties, XR_TYPE_VIEW_CONFIGURATION_PROPERTIES) \
+ _avail(XrViewConfigurationView, XR_TYPE_VIEW_CONFIGURATION_VIEW) \
+ _avail(XrSwapchainCreateInfo, XR_TYPE_SWAPCHAIN_CREATE_INFO) \
+ _avail(XrSwapchainImageAcquireInfo, XR_TYPE_SWAPCHAIN_IMAGE_ACQUIRE_INFO) \
+ _avail(XrSwapchainImageWaitInfo, XR_TYPE_SWAPCHAIN_IMAGE_WAIT_INFO) \
+ _avail(XrSwapchainImageReleaseInfo, XR_TYPE_SWAPCHAIN_IMAGE_RELEASE_INFO) \
+ _avail(XrSessionBeginInfo, XR_TYPE_SESSION_BEGIN_INFO) \
+ _avail(XrFrameWaitInfo, XR_TYPE_FRAME_WAIT_INFO) \
+ _avail(XrFrameState, XR_TYPE_FRAME_STATE) \
+ _avail(XrFrameBeginInfo, XR_TYPE_FRAME_BEGIN_INFO) \
+ _avail(XrFrameEndInfo, XR_TYPE_FRAME_END_INFO) \
+ _avail(XrViewLocateInfo, XR_TYPE_VIEW_LOCATE_INFO) \
+ _avail(XrViewState, XR_TYPE_VIEW_STATE) \
+ _avail(XrView, XR_TYPE_VIEW) \
+ _avail(XrActionSetCreateInfo, XR_TYPE_ACTION_SET_CREATE_INFO) \
+ _avail(XrActionCreateInfo, XR_TYPE_ACTION_CREATE_INFO) \
+ _avail(XrInteractionProfileSuggestedBinding, XR_TYPE_INTERACTION_PROFILE_SUGGESTED_BINDING) \
+ _avail(XrSessionActionSetsAttachInfo, XR_TYPE_SESSION_ACTION_SETS_ATTACH_INFO) \
+ _avail(XrInteractionProfileState, XR_TYPE_INTERACTION_PROFILE_STATE) \
+ _avail(XrActionStateGetInfo, XR_TYPE_ACTION_STATE_GET_INFO) \
+ _avail(XrActionStateBoolean, XR_TYPE_ACTION_STATE_BOOLEAN) \
+ _avail(XrActionStateFloat, XR_TYPE_ACTION_STATE_FLOAT) \
+ _avail(XrActionStateVector2f, XR_TYPE_ACTION_STATE_VECTOR2F) \
+ _avail(XrActionStatePose, XR_TYPE_ACTION_STATE_POSE) \
+ _avail(XrActionsSyncInfo, XR_TYPE_ACTIONS_SYNC_INFO) \
+ _avail(XrBoundSourcesForActionEnumerateInfo, XR_TYPE_BOUND_SOURCES_FOR_ACTION_ENUMERATE_INFO) \
+ _avail(XrInputSourceLocalizedNameGetInfo, XR_TYPE_INPUT_SOURCE_LOCALIZED_NAME_GET_INFO) \
+ _avail(XrHapticActionInfo, XR_TYPE_HAPTIC_ACTION_INFO) \
+ _avail(XrCompositionLayerProjectionView, XR_TYPE_COMPOSITION_LAYER_PROJECTION_VIEW) \
+ _avail(XrCompositionLayerProjection, XR_TYPE_COMPOSITION_LAYER_PROJECTION) \
+ _avail(XrCompositionLayerQuad, XR_TYPE_COMPOSITION_LAYER_QUAD) \
+ _avail(XrEventDataEventsLost, XR_TYPE_EVENT_DATA_EVENTS_LOST) \
+ _avail(XrEventDataInstanceLossPending, XR_TYPE_EVENT_DATA_INSTANCE_LOSS_PENDING) \
+ _avail(XrEventDataSessionStateChanged, XR_TYPE_EVENT_DATA_SESSION_STATE_CHANGED) \
+ _avail(XrEventDataReferenceSpaceChangePending, XR_TYPE_EVENT_DATA_REFERENCE_SPACE_CHANGE_PENDING) \
+ _avail(XrEventDataInteractionProfileChanged, XR_TYPE_EVENT_DATA_INTERACTION_PROFILE_CHANGED) \
+ _avail(XrHapticVibration, XR_TYPE_HAPTIC_VIBRATION) \
+ _avail(XrCompositionLayerCubeKHR, XR_TYPE_COMPOSITION_LAYER_CUBE_KHR) \
+ _avail(XrCompositionLayerDepthInfoKHR, XR_TYPE_COMPOSITION_LAYER_DEPTH_INFO_KHR) \
+ _avail(XrCompositionLayerCylinderKHR, XR_TYPE_COMPOSITION_LAYER_CYLINDER_KHR) \
+ _avail(XrCompositionLayerEquirectKHR, XR_TYPE_COMPOSITION_LAYER_EQUIRECT_KHR) \
+ _avail(XrVisibilityMaskKHR, XR_TYPE_VISIBILITY_MASK_KHR) \
+ _avail(XrEventDataVisibilityMaskChangedKHR, XR_TYPE_EVENT_DATA_VISIBILITY_MASK_CHANGED_KHR) \
+ _avail(XrCompositionLayerColorScaleBiasKHR, XR_TYPE_COMPOSITION_LAYER_COLOR_SCALE_BIAS_KHR) \
+ _avail(XrCompositionLayerEquirect2KHR, XR_TYPE_COMPOSITION_LAYER_EQUIRECT2_KHR) \
+ _avail(XrBindingModificationsKHR, XR_TYPE_BINDING_MODIFICATIONS_KHR) \
+ _avail(XrEventDataPerfSettingsEXT, XR_TYPE_EVENT_DATA_PERF_SETTINGS_EXT) \
+ _avail(XrDebugUtilsObjectNameInfoEXT, XR_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT) \
+ _avail(XrDebugUtilsLabelEXT, XR_TYPE_DEBUG_UTILS_LABEL_EXT) \
+ _avail(XrDebugUtilsMessengerCallbackDataEXT, XR_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT) \
+ _avail(XrDebugUtilsMessengerCreateInfoEXT, XR_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT) \
+ _avail(XrSystemEyeGazeInteractionPropertiesEXT, XR_TYPE_SYSTEM_EYE_GAZE_INTERACTION_PROPERTIES_EXT) \
+ _avail(XrEyeGazeSampleTimeEXT, XR_TYPE_EYE_GAZE_SAMPLE_TIME_EXT) \
+ _avail(XrSessionCreateInfoOverlayEXTX, XR_TYPE_SESSION_CREATE_INFO_OVERLAY_EXTX) \
+ _avail(XrEventDataMainSessionVisibilityChangedEXTX, XR_TYPE_EVENT_DATA_MAIN_SESSION_VISIBILITY_CHANGED_EXTX) \
+ _avail(XrSpatialAnchorCreateInfoMSFT, XR_TYPE_SPATIAL_ANCHOR_CREATE_INFO_MSFT) \
+ _avail(XrSpatialAnchorSpaceCreateInfoMSFT, XR_TYPE_SPATIAL_ANCHOR_SPACE_CREATE_INFO_MSFT) \
+ _avail(XrCompositionLayerImageLayoutFB, XR_TYPE_COMPOSITION_LAYER_IMAGE_LAYOUT_FB) \
+ _avail(XrCompositionLayerAlphaBlendFB, XR_TYPE_COMPOSITION_LAYER_ALPHA_BLEND_FB) \
+ _avail(XrViewConfigurationDepthRangeEXT, XR_TYPE_VIEW_CONFIGURATION_DEPTH_RANGE_EXT) \
+ _avail(XrSpatialGraphNodeSpaceCreateInfoMSFT, XR_TYPE_SPATIAL_GRAPH_NODE_SPACE_CREATE_INFO_MSFT) \
+ _avail(XrSpatialGraphStaticNodeBindingCreateInfoMSFT, XR_TYPE_SPATIAL_GRAPH_STATIC_NODE_BINDING_CREATE_INFO_MSFT) \
+ _avail(XrSpatialGraphNodeBindingPropertiesGetInfoMSFT, XR_TYPE_SPATIAL_GRAPH_NODE_BINDING_PROPERTIES_GET_INFO_MSFT) \
+ _avail(XrSpatialGraphNodeBindingPropertiesMSFT, XR_TYPE_SPATIAL_GRAPH_NODE_BINDING_PROPERTIES_MSFT) \
+ _avail(XrSystemHandTrackingPropertiesEXT, XR_TYPE_SYSTEM_HAND_TRACKING_PROPERTIES_EXT) \
+ _avail(XrHandTrackerCreateInfoEXT, XR_TYPE_HAND_TRACKER_CREATE_INFO_EXT) \
+ _avail(XrHandJointsLocateInfoEXT, XR_TYPE_HAND_JOINTS_LOCATE_INFO_EXT) \
+ _avail(XrHandJointLocationsEXT, XR_TYPE_HAND_JOINT_LOCATIONS_EXT) \
+ _avail(XrHandJointVelocitiesEXT, XR_TYPE_HAND_JOINT_VELOCITIES_EXT) \
+ _avail(XrSystemHandTrackingMeshPropertiesMSFT, XR_TYPE_SYSTEM_HAND_TRACKING_MESH_PROPERTIES_MSFT) \
+ _avail(XrHandMeshSpaceCreateInfoMSFT, XR_TYPE_HAND_MESH_SPACE_CREATE_INFO_MSFT) \
+ _avail(XrHandMeshUpdateInfoMSFT, XR_TYPE_HAND_MESH_UPDATE_INFO_MSFT) \
+ _avail(XrHandMeshMSFT, XR_TYPE_HAND_MESH_MSFT) \
+ _avail(XrHandPoseTypeInfoMSFT, XR_TYPE_HAND_POSE_TYPE_INFO_MSFT) \
+ _avail(XrSecondaryViewConfigurationSessionBeginInfoMSFT, XR_TYPE_SECONDARY_VIEW_CONFIGURATION_SESSION_BEGIN_INFO_MSFT) \
+ _avail(XrSecondaryViewConfigurationStateMSFT, XR_TYPE_SECONDARY_VIEW_CONFIGURATION_STATE_MSFT) \
+ _avail(XrSecondaryViewConfigurationFrameStateMSFT, XR_TYPE_SECONDARY_VIEW_CONFIGURATION_FRAME_STATE_MSFT) \
+ _avail(XrSecondaryViewConfigurationLayerInfoMSFT, XR_TYPE_SECONDARY_VIEW_CONFIGURATION_LAYER_INFO_MSFT) \
+ _avail(XrSecondaryViewConfigurationFrameEndInfoMSFT, XR_TYPE_SECONDARY_VIEW_CONFIGURATION_FRAME_END_INFO_MSFT) \
+ _avail(XrSecondaryViewConfigurationSwapchainCreateInfoMSFT, XR_TYPE_SECONDARY_VIEW_CONFIGURATION_SWAPCHAIN_CREATE_INFO_MSFT) \
+ _avail(XrControllerModelKeyStateMSFT, XR_TYPE_CONTROLLER_MODEL_KEY_STATE_MSFT) \
+ _avail(XrControllerModelNodePropertiesMSFT, XR_TYPE_CONTROLLER_MODEL_NODE_PROPERTIES_MSFT) \
+ _avail(XrControllerModelPropertiesMSFT, XR_TYPE_CONTROLLER_MODEL_PROPERTIES_MSFT) \
+ _avail(XrControllerModelNodeStateMSFT, XR_TYPE_CONTROLLER_MODEL_NODE_STATE_MSFT) \
+ _avail(XrControllerModelStateMSFT, XR_TYPE_CONTROLLER_MODEL_STATE_MSFT) \
+ _avail(XrViewConfigurationViewFovEPIC, XR_TYPE_VIEW_CONFIGURATION_VIEW_FOV_EPIC) \
+ _avail(XrCompositionLayerReprojectionInfoMSFT, XR_TYPE_COMPOSITION_LAYER_REPROJECTION_INFO_MSFT) \
+ _avail(XrCompositionLayerReprojectionPlaneOverrideMSFT, XR_TYPE_COMPOSITION_LAYER_REPROJECTION_PLANE_OVERRIDE_MSFT) \
+ _avail(XrCompositionLayerSecureContentFB, XR_TYPE_COMPOSITION_LAYER_SECURE_CONTENT_FB) \
+ _avail(XrInteractionProfileDpadBindingEXT, XR_TYPE_INTERACTION_PROFILE_DPAD_BINDING_EXT) \
+ _avail(XrInteractionProfileAnalogThresholdVALVE, XR_TYPE_INTERACTION_PROFILE_ANALOG_THRESHOLD_VALVE) \
+ _avail(XrHandJointsMotionRangeInfoEXT, XR_TYPE_HAND_JOINTS_MOTION_RANGE_INFO_EXT) \
+ _avail(XrSceneObserverCreateInfoMSFT, XR_TYPE_SCENE_OBSERVER_CREATE_INFO_MSFT) \
+ _avail(XrSceneCreateInfoMSFT, XR_TYPE_SCENE_CREATE_INFO_MSFT) \
+ _avail(XrNewSceneComputeInfoMSFT, XR_TYPE_NEW_SCENE_COMPUTE_INFO_MSFT) \
+ _avail(XrVisualMeshComputeLodInfoMSFT, XR_TYPE_VISUAL_MESH_COMPUTE_LOD_INFO_MSFT) \
+ _avail(XrSceneComponentsMSFT, XR_TYPE_SCENE_COMPONENTS_MSFT) \
+ _avail(XrSceneComponentsGetInfoMSFT, XR_TYPE_SCENE_COMPONENTS_GET_INFO_MSFT) \
+ _avail(XrSceneComponentLocationsMSFT, XR_TYPE_SCENE_COMPONENT_LOCATIONS_MSFT) \
+ _avail(XrSceneComponentsLocateInfoMSFT, XR_TYPE_SCENE_COMPONENTS_LOCATE_INFO_MSFT) \
+ _avail(XrSceneObjectsMSFT, XR_TYPE_SCENE_OBJECTS_MSFT) \
+ _avail(XrSceneComponentParentFilterInfoMSFT, XR_TYPE_SCENE_COMPONENT_PARENT_FILTER_INFO_MSFT) \
+ _avail(XrSceneObjectTypesFilterInfoMSFT, XR_TYPE_SCENE_OBJECT_TYPES_FILTER_INFO_MSFT) \
+ _avail(XrScenePlanesMSFT, XR_TYPE_SCENE_PLANES_MSFT) \
+ _avail(XrScenePlaneAlignmentFilterInfoMSFT, XR_TYPE_SCENE_PLANE_ALIGNMENT_FILTER_INFO_MSFT) \
+ _avail(XrSceneMeshesMSFT, XR_TYPE_SCENE_MESHES_MSFT) \
+ _avail(XrSceneMeshBuffersGetInfoMSFT, XR_TYPE_SCENE_MESH_BUFFERS_GET_INFO_MSFT) \
+ _avail(XrSceneMeshBuffersMSFT, XR_TYPE_SCENE_MESH_BUFFERS_MSFT) \
+ _avail(XrSceneMeshVertexBufferMSFT, XR_TYPE_SCENE_MESH_VERTEX_BUFFER_MSFT) \
+ _avail(XrSceneMeshIndicesUint32MSFT, XR_TYPE_SCENE_MESH_INDICES_UINT32_MSFT) \
+ _avail(XrSceneMeshIndicesUint16MSFT, XR_TYPE_SCENE_MESH_INDICES_UINT16_MSFT) \
+ _avail(XrSerializedSceneFragmentDataGetInfoMSFT, XR_TYPE_SERIALIZED_SCENE_FRAGMENT_DATA_GET_INFO_MSFT) \
+ _avail(XrSceneDeserializeInfoMSFT, XR_TYPE_SCENE_DESERIALIZE_INFO_MSFT) \
+ _avail(XrEventDataDisplayRefreshRateChangedFB, XR_TYPE_EVENT_DATA_DISPLAY_REFRESH_RATE_CHANGED_FB) \
+ _avail(XrViveTrackerPathsHTCX, XR_TYPE_VIVE_TRACKER_PATHS_HTCX) \
+ _avail(XrEventDataViveTrackerConnectedHTCX, XR_TYPE_EVENT_DATA_VIVE_TRACKER_CONNECTED_HTCX) \
+ _avail(XrSystemFacialTrackingPropertiesHTC, XR_TYPE_SYSTEM_FACIAL_TRACKING_PROPERTIES_HTC) \
+ _avail(XrFacialExpressionsHTC, XR_TYPE_FACIAL_EXPRESSIONS_HTC) \
+ _avail(XrFacialTrackerCreateInfoHTC, XR_TYPE_FACIAL_TRACKER_CREATE_INFO_HTC) \
+ _avail(XrSystemColorSpacePropertiesFB, XR_TYPE_SYSTEM_COLOR_SPACE_PROPERTIES_FB) \
+ _avail(XrHandTrackingMeshFB, XR_TYPE_HAND_TRACKING_MESH_FB) \
+ _avail(XrHandTrackingScaleFB, XR_TYPE_HAND_TRACKING_SCALE_FB) \
+ _avail(XrHandTrackingAimStateFB, XR_TYPE_HAND_TRACKING_AIM_STATE_FB) \
+ _avail(XrHandTrackingCapsulesStateFB, XR_TYPE_HAND_TRACKING_CAPSULES_STATE_FB) \
+ _avail(XrSystemSpatialEntityPropertiesFB, XR_TYPE_SYSTEM_SPATIAL_ENTITY_PROPERTIES_FB) \
+ _avail(XrSpatialAnchorCreateInfoFB, XR_TYPE_SPATIAL_ANCHOR_CREATE_INFO_FB) \
+ _avail(XrSpaceComponentStatusSetInfoFB, XR_TYPE_SPACE_COMPONENT_STATUS_SET_INFO_FB) \
+ _avail(XrSpaceComponentStatusFB, XR_TYPE_SPACE_COMPONENT_STATUS_FB) \
+ _avail(XrEventDataSpatialAnchorCreateCompleteFB, XR_TYPE_EVENT_DATA_SPATIAL_ANCHOR_CREATE_COMPLETE_FB) \
+ _avail(XrEventDataSpaceSetStatusCompleteFB, XR_TYPE_EVENT_DATA_SPACE_SET_STATUS_COMPLETE_FB) \
+ _avail(XrFoveationProfileCreateInfoFB, XR_TYPE_FOVEATION_PROFILE_CREATE_INFO_FB) \
+ _avail(XrSwapchainCreateInfoFoveationFB, XR_TYPE_SWAPCHAIN_CREATE_INFO_FOVEATION_FB) \
+ _avail(XrSwapchainStateFoveationFB, XR_TYPE_SWAPCHAIN_STATE_FOVEATION_FB) \
+ _avail(XrFoveationLevelProfileCreateInfoFB, XR_TYPE_FOVEATION_LEVEL_PROFILE_CREATE_INFO_FB) \
+ _avail(XrSystemKeyboardTrackingPropertiesFB, XR_TYPE_SYSTEM_KEYBOARD_TRACKING_PROPERTIES_FB) \
+ _avail(XrKeyboardSpaceCreateInfoFB, XR_TYPE_KEYBOARD_SPACE_CREATE_INFO_FB) \
+ _avail(XrKeyboardTrackingQueryFB, XR_TYPE_KEYBOARD_TRACKING_QUERY_FB) \
+ _avail(XrTriangleMeshCreateInfoFB, XR_TYPE_TRIANGLE_MESH_CREATE_INFO_FB) \
+ _avail(XrSystemPassthroughPropertiesFB, XR_TYPE_SYSTEM_PASSTHROUGH_PROPERTIES_FB) \
+ _avail(XrSystemPassthroughProperties2FB, XR_TYPE_SYSTEM_PASSTHROUGH_PROPERTIES2_FB) \
+ _avail(XrPassthroughCreateInfoFB, XR_TYPE_PASSTHROUGH_CREATE_INFO_FB) \
+ _avail(XrPassthroughLayerCreateInfoFB, XR_TYPE_PASSTHROUGH_LAYER_CREATE_INFO_FB) \
+ _avail(XrCompositionLayerPassthroughFB, XR_TYPE_COMPOSITION_LAYER_PASSTHROUGH_FB) \
+ _avail(XrGeometryInstanceCreateInfoFB, XR_TYPE_GEOMETRY_INSTANCE_CREATE_INFO_FB) \
+ _avail(XrGeometryInstanceTransformFB, XR_TYPE_GEOMETRY_INSTANCE_TRANSFORM_FB) \
+ _avail(XrPassthroughStyleFB, XR_TYPE_PASSTHROUGH_STYLE_FB) \
+ _avail(XrPassthroughColorMapMonoToRgbaFB, XR_TYPE_PASSTHROUGH_COLOR_MAP_MONO_TO_RGBA_FB) \
+ _avail(XrPassthroughColorMapMonoToMonoFB, XR_TYPE_PASSTHROUGH_COLOR_MAP_MONO_TO_MONO_FB) \
+ _avail(XrPassthroughBrightnessContrastSaturationFB, XR_TYPE_PASSTHROUGH_BRIGHTNESS_CONTRAST_SATURATION_FB) \
+ _avail(XrEventDataPassthroughStateChangedFB, XR_TYPE_EVENT_DATA_PASSTHROUGH_STATE_CHANGED_FB) \
+ _avail(XrRenderModelPathInfoFB, XR_TYPE_RENDER_MODEL_PATH_INFO_FB) \
+ _avail(XrRenderModelPropertiesFB, XR_TYPE_RENDER_MODEL_PROPERTIES_FB) \
+ _avail(XrRenderModelBufferFB, XR_TYPE_RENDER_MODEL_BUFFER_FB) \
+ _avail(XrRenderModelLoadInfoFB, XR_TYPE_RENDER_MODEL_LOAD_INFO_FB) \
+ _avail(XrSystemRenderModelPropertiesFB, XR_TYPE_SYSTEM_RENDER_MODEL_PROPERTIES_FB) \
+ _avail(XrRenderModelCapabilitiesRequestFB, XR_TYPE_RENDER_MODEL_CAPABILITIES_REQUEST_FB) \
+ _avail(XrViewLocateFoveatedRenderingVARJO, XR_TYPE_VIEW_LOCATE_FOVEATED_RENDERING_VARJO) \
+ _avail(XrFoveatedViewConfigurationViewVARJO, XR_TYPE_FOVEATED_VIEW_CONFIGURATION_VIEW_VARJO) \
+ _avail(XrSystemFoveatedRenderingPropertiesVARJO, XR_TYPE_SYSTEM_FOVEATED_RENDERING_PROPERTIES_VARJO) \
+ _avail(XrCompositionLayerDepthTestVARJO, XR_TYPE_COMPOSITION_LAYER_DEPTH_TEST_VARJO) \
+ _avail(XrSystemMarkerTrackingPropertiesVARJO, XR_TYPE_SYSTEM_MARKER_TRACKING_PROPERTIES_VARJO) \
+ _avail(XrEventDataMarkerTrackingUpdateVARJO, XR_TYPE_EVENT_DATA_MARKER_TRACKING_UPDATE_VARJO) \
+ _avail(XrMarkerSpaceCreateInfoVARJO, XR_TYPE_MARKER_SPACE_CREATE_INFO_VARJO) \
+ _avail(XrSpatialAnchorPersistenceInfoMSFT, XR_TYPE_SPATIAL_ANCHOR_PERSISTENCE_INFO_MSFT) \
+ _avail(XrSpatialAnchorFromPersistedAnchorCreateInfoMSFT, XR_TYPE_SPATIAL_ANCHOR_FROM_PERSISTED_ANCHOR_CREATE_INFO_MSFT) \
+ _avail(XrSpaceQueryInfoFB, XR_TYPE_SPACE_QUERY_INFO_FB) \
+ _avail(XrSpaceStorageLocationFilterInfoFB, XR_TYPE_SPACE_STORAGE_LOCATION_FILTER_INFO_FB) \
+ _avail(XrSpaceUuidFilterInfoFB, XR_TYPE_SPACE_UUID_FILTER_INFO_FB) \
+ _avail(XrSpaceComponentFilterInfoFB, XR_TYPE_SPACE_COMPONENT_FILTER_INFO_FB) \
+ _avail(XrSpaceQueryResultsFB, XR_TYPE_SPACE_QUERY_RESULTS_FB) \
+ _avail(XrEventDataSpaceQueryResultsAvailableFB, XR_TYPE_EVENT_DATA_SPACE_QUERY_RESULTS_AVAILABLE_FB) \
+ _avail(XrEventDataSpaceQueryCompleteFB, XR_TYPE_EVENT_DATA_SPACE_QUERY_COMPLETE_FB) \
+ _avail(XrSpaceSaveInfoFB, XR_TYPE_SPACE_SAVE_INFO_FB) \
+ _avail(XrSpaceEraseInfoFB, XR_TYPE_SPACE_ERASE_INFO_FB) \
+ _avail(XrEventDataSpaceSaveCompleteFB, XR_TYPE_EVENT_DATA_SPACE_SAVE_COMPLETE_FB) \
+ _avail(XrEventDataSpaceEraseCompleteFB, XR_TYPE_EVENT_DATA_SPACE_ERASE_COMPLETE_FB) \
+ _avail(XrCompositionLayerSpaceWarpInfoFB, XR_TYPE_COMPOSITION_LAYER_SPACE_WARP_INFO_FB) \
+ _avail(XrSystemSpaceWarpPropertiesFB, XR_TYPE_SYSTEM_SPACE_WARP_PROPERTIES_FB) \
+ _avail(XrSemanticLabelsFB, XR_TYPE_SEMANTIC_LABELS_FB) \
+ _avail(XrRoomLayoutFB, XR_TYPE_ROOM_LAYOUT_FB) \
+ _avail(XrBoundary2DFB, XR_TYPE_BOUNDARY_2D_FB) \
+ _avail(XrDigitalLensControlALMALENCE, XR_TYPE_DIGITAL_LENS_CONTROL_ALMALENCE) \
+ _avail(XrSpaceContainerFB, XR_TYPE_SPACE_CONTAINER_FB) \
+ _avail(XrPassthroughKeyboardHandsIntensityFB, XR_TYPE_PASSTHROUGH_KEYBOARD_HANDS_INTENSITY_FB) \
+ _avail(XrCompositionLayerSettingsFB, XR_TYPE_COMPOSITION_LAYER_SETTINGS_FB) \
+ _avail(XrPerformanceMetricsStateMETA, XR_TYPE_PERFORMANCE_METRICS_STATE_META) \
+ _avail(XrPerformanceMetricsCounterMETA, XR_TYPE_PERFORMANCE_METRICS_COUNTER_META) \
+ _avail(XrSystemHeadsetIdPropertiesMETA, XR_TYPE_SYSTEM_HEADSET_ID_PROPERTIES_META) \
+ _avail(XrPassthroughCreateInfoHTC, XR_TYPE_PASSTHROUGH_CREATE_INFO_HTC) \
+ _avail(XrPassthroughColorHTC, XR_TYPE_PASSTHROUGH_COLOR_HTC) \
+ _avail(XrPassthroughMeshTransformInfoHTC, XR_TYPE_PASSTHROUGH_MESH_TRANSFORM_INFO_HTC) \
+ _avail(XrCompositionLayerPassthroughHTC, XR_TYPE_COMPOSITION_LAYER_PASSTHROUGH_HTC) \
+ _avail(XrFoveationApplyInfoHTC, XR_TYPE_FOVEATION_APPLY_INFO_HTC) \
+ _avail(XrFoveationDynamicModeInfoHTC, XR_TYPE_FOVEATION_DYNAMIC_MODE_INFO_HTC) \
+ _avail(XrFoveationCustomModeInfoHTC, XR_TYPE_FOVEATION_CUSTOM_MODE_INFO_HTC) \
+ _avail(XrActiveActionSetPrioritiesEXT, XR_TYPE_ACTIVE_ACTION_SET_PRIORITIES_EXT) \
+
+
+#if defined(XR_USE_GRAPHICS_API_D3D11)
+#define _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_D3D11(_avail, _unavail) \
+ _avail(XrGraphicsBindingD3D11KHR, XR_TYPE_GRAPHICS_BINDING_D3D11_KHR) \
+ _avail(XrSwapchainImageD3D11KHR, XR_TYPE_SWAPCHAIN_IMAGE_D3D11_KHR) \
+ _avail(XrGraphicsRequirementsD3D11KHR, XR_TYPE_GRAPHICS_REQUIREMENTS_D3D11_KHR) \
+
+#else
+#define _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_D3D11(_avail, _unavail) \
+ _unavail(XrGraphicsBindingD3D11KHR, XR_TYPE_GRAPHICS_BINDING_D3D11_KHR) \
+ _unavail(XrSwapchainImageD3D11KHR, XR_TYPE_SWAPCHAIN_IMAGE_D3D11_KHR) \
+ _unavail(XrGraphicsRequirementsD3D11KHR, XR_TYPE_GRAPHICS_REQUIREMENTS_D3D11_KHR) \
+
+#endif
+
+#if defined(XR_USE_GRAPHICS_API_D3D12)
+#define _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_D3D12(_avail, _unavail) \
+ _avail(XrGraphicsBindingD3D12KHR, XR_TYPE_GRAPHICS_BINDING_D3D12_KHR) \
+ _avail(XrSwapchainImageD3D12KHR, XR_TYPE_SWAPCHAIN_IMAGE_D3D12_KHR) \
+ _avail(XrGraphicsRequirementsD3D12KHR, XR_TYPE_GRAPHICS_REQUIREMENTS_D3D12_KHR) \
+
+#else
+#define _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_D3D12(_avail, _unavail) \
+ _unavail(XrGraphicsBindingD3D12KHR, XR_TYPE_GRAPHICS_BINDING_D3D12_KHR) \
+ _unavail(XrSwapchainImageD3D12KHR, XR_TYPE_SWAPCHAIN_IMAGE_D3D12_KHR) \
+ _unavail(XrGraphicsRequirementsD3D12KHR, XR_TYPE_GRAPHICS_REQUIREMENTS_D3D12_KHR) \
+
+#endif
+
+#if defined(XR_USE_GRAPHICS_API_OPENGL)
+#define _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL(_avail, _unavail) \
+ _avail(XrSwapchainImageOpenGLKHR, XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_KHR) \
+ _avail(XrGraphicsRequirementsOpenGLKHR, XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_KHR) \
+
+#else
+#define _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL(_avail, _unavail) \
+ _unavail(XrSwapchainImageOpenGLKHR, XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_KHR) \
+ _unavail(XrGraphicsRequirementsOpenGLKHR, XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_KHR) \
+
+#endif
+
+#if defined(XR_USE_GRAPHICS_API_OPENGL) && defined(XR_USE_PLATFORM_WAYLAND)
+#define _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_XR_USE_PLATFORM_WAYLAND(_avail, _unavail) \
+ _avail(XrGraphicsBindingOpenGLWaylandKHR, XR_TYPE_GRAPHICS_BINDING_OPENGL_WAYLAND_KHR) \
+
+#else
+#define _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_XR_USE_PLATFORM_WAYLAND(_avail, _unavail) \
+ _unavail(XrGraphicsBindingOpenGLWaylandKHR, XR_TYPE_GRAPHICS_BINDING_OPENGL_WAYLAND_KHR) \
+
+#endif
+
+#if defined(XR_USE_GRAPHICS_API_OPENGL) && defined(XR_USE_PLATFORM_WIN32)
+#define _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_XR_USE_PLATFORM_WIN32(_avail, _unavail) \
+ _avail(XrGraphicsBindingOpenGLWin32KHR, XR_TYPE_GRAPHICS_BINDING_OPENGL_WIN32_KHR) \
+
+#else
+#define _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_XR_USE_PLATFORM_WIN32(_avail, _unavail) \
+ _unavail(XrGraphicsBindingOpenGLWin32KHR, XR_TYPE_GRAPHICS_BINDING_OPENGL_WIN32_KHR) \
+
+#endif
+
+#if defined(XR_USE_GRAPHICS_API_OPENGL) && defined(XR_USE_PLATFORM_XCB)
+#define _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_XR_USE_PLATFORM_XCB(_avail, _unavail) \
+ _avail(XrGraphicsBindingOpenGLXcbKHR, XR_TYPE_GRAPHICS_BINDING_OPENGL_XCB_KHR) \
+
+#else
+#define _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_XR_USE_PLATFORM_XCB(_avail, _unavail) \
+ _unavail(XrGraphicsBindingOpenGLXcbKHR, XR_TYPE_GRAPHICS_BINDING_OPENGL_XCB_KHR) \
+
+#endif
+
+#if defined(XR_USE_GRAPHICS_API_OPENGL) && defined(XR_USE_PLATFORM_XLIB)
+#define _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_XR_USE_PLATFORM_XLIB(_avail, _unavail) \
+ _avail(XrGraphicsBindingOpenGLXlibKHR, XR_TYPE_GRAPHICS_BINDING_OPENGL_XLIB_KHR) \
+
+#else
+#define _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_XR_USE_PLATFORM_XLIB(_avail, _unavail) \
+ _unavail(XrGraphicsBindingOpenGLXlibKHR, XR_TYPE_GRAPHICS_BINDING_OPENGL_XLIB_KHR) \
+
+#endif
+
+#if defined(XR_USE_GRAPHICS_API_OPENGL_ES)
+#define _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_ES(_avail, _unavail) \
+ _avail(XrSwapchainImageOpenGLESKHR, XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_ES_KHR) \
+ _avail(XrGraphicsRequirementsOpenGLESKHR, XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_ES_KHR) \
+ _avail(XrSwapchainStateSamplerOpenGLESFB, XR_TYPE_SWAPCHAIN_STATE_SAMPLER_OPENGL_ES_FB) \
+
+#else
+#define _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_ES(_avail, _unavail) \
+ _unavail(XrSwapchainImageOpenGLESKHR, XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_ES_KHR) \
+ _unavail(XrGraphicsRequirementsOpenGLESKHR, XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_ES_KHR) \
+ _unavail(XrSwapchainStateSamplerOpenGLESFB, XR_TYPE_SWAPCHAIN_STATE_SAMPLER_OPENGL_ES_FB) \
+
+#endif
+
+#if defined(XR_USE_GRAPHICS_API_OPENGL_ES) && defined(XR_USE_PLATFORM_ANDROID)
+#define _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_ES_XR_USE_PLATFORM_ANDROID(_avail, _unavail) \
+ _avail(XrGraphicsBindingOpenGLESAndroidKHR, XR_TYPE_GRAPHICS_BINDING_OPENGL_ES_ANDROID_KHR) \
+
+#else
+#define _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_ES_XR_USE_PLATFORM_ANDROID(_avail, _unavail) \
+ _unavail(XrGraphicsBindingOpenGLESAndroidKHR, XR_TYPE_GRAPHICS_BINDING_OPENGL_ES_ANDROID_KHR) \
+
+#endif
+
+#if defined(XR_USE_GRAPHICS_API_VULKAN)
+#define _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_VULKAN(_avail, _unavail) \
+ _avail(XrVulkanSwapchainFormatListCreateInfoKHR, XR_TYPE_VULKAN_SWAPCHAIN_FORMAT_LIST_CREATE_INFO_KHR) \
+ _avail(XrGraphicsBindingVulkanKHR, XR_TYPE_GRAPHICS_BINDING_VULKAN_KHR) \
+ _avail(XrSwapchainImageVulkanKHR, XR_TYPE_SWAPCHAIN_IMAGE_VULKAN_KHR) \
+ _avail(XrGraphicsRequirementsVulkanKHR, XR_TYPE_GRAPHICS_REQUIREMENTS_VULKAN_KHR) \
+ _avail(XrVulkanInstanceCreateInfoKHR, XR_TYPE_VULKAN_INSTANCE_CREATE_INFO_KHR) \
+ _avail(XrVulkanDeviceCreateInfoKHR, XR_TYPE_VULKAN_DEVICE_CREATE_INFO_KHR) \
+ _avail(XrVulkanGraphicsDeviceGetInfoKHR, XR_TYPE_VULKAN_GRAPHICS_DEVICE_GET_INFO_KHR) \
+ _avail(XrSwapchainImageFoveationVulkanFB, XR_TYPE_SWAPCHAIN_IMAGE_FOVEATION_VULKAN_FB) \
+ _avail(XrSwapchainStateSamplerVulkanFB, XR_TYPE_SWAPCHAIN_STATE_SAMPLER_VULKAN_FB) \
+ _avail(XrVulkanSwapchainCreateInfoMETA, XR_TYPE_VULKAN_SWAPCHAIN_CREATE_INFO_META) \
+
+#else
+#define _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_VULKAN(_avail, _unavail) \
+ _unavail(XrVulkanSwapchainFormatListCreateInfoKHR, XR_TYPE_VULKAN_SWAPCHAIN_FORMAT_LIST_CREATE_INFO_KHR) \
+ _unavail(XrGraphicsBindingVulkanKHR, XR_TYPE_GRAPHICS_BINDING_VULKAN_KHR) \
+ _unavail(XrSwapchainImageVulkanKHR, XR_TYPE_SWAPCHAIN_IMAGE_VULKAN_KHR) \
+ _unavail(XrGraphicsRequirementsVulkanKHR, XR_TYPE_GRAPHICS_REQUIREMENTS_VULKAN_KHR) \
+ _unavail(XrVulkanInstanceCreateInfoKHR, XR_TYPE_VULKAN_INSTANCE_CREATE_INFO_KHR) \
+ _unavail(XrVulkanDeviceCreateInfoKHR, XR_TYPE_VULKAN_DEVICE_CREATE_INFO_KHR) \
+ _unavail(XrVulkanGraphicsDeviceGetInfoKHR, XR_TYPE_VULKAN_GRAPHICS_DEVICE_GET_INFO_KHR) \
+ _unavail(XrSwapchainImageFoveationVulkanFB, XR_TYPE_SWAPCHAIN_IMAGE_FOVEATION_VULKAN_FB) \
+ _unavail(XrSwapchainStateSamplerVulkanFB, XR_TYPE_SWAPCHAIN_STATE_SAMPLER_VULKAN_FB) \
+ _unavail(XrVulkanSwapchainCreateInfoMETA, XR_TYPE_VULKAN_SWAPCHAIN_CREATE_INFO_META) \
+
+#endif
+
+#if defined(XR_USE_PLATFORM_ANDROID)
+#define _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_PLATFORM_ANDROID(_avail, _unavail) \
+ _avail(XrInstanceCreateInfoAndroidKHR, XR_TYPE_INSTANCE_CREATE_INFO_ANDROID_KHR) \
+ _avail(XrLoaderInitInfoAndroidKHR, XR_TYPE_LOADER_INIT_INFO_ANDROID_KHR) \
+ _avail(XrAndroidSurfaceSwapchainCreateInfoFB, XR_TYPE_ANDROID_SURFACE_SWAPCHAIN_CREATE_INFO_FB) \
+ _avail(XrSwapchainStateAndroidSurfaceDimensionsFB, XR_TYPE_SWAPCHAIN_STATE_ANDROID_SURFACE_DIMENSIONS_FB) \
+
+#else
+#define _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_PLATFORM_ANDROID(_avail, _unavail) \
+ _unavail(XrInstanceCreateInfoAndroidKHR, XR_TYPE_INSTANCE_CREATE_INFO_ANDROID_KHR) \
+ _unavail(XrLoaderInitInfoAndroidKHR, XR_TYPE_LOADER_INIT_INFO_ANDROID_KHR) \
+ _unavail(XrAndroidSurfaceSwapchainCreateInfoFB, XR_TYPE_ANDROID_SURFACE_SWAPCHAIN_CREATE_INFO_FB) \
+ _unavail(XrSwapchainStateAndroidSurfaceDimensionsFB, XR_TYPE_SWAPCHAIN_STATE_ANDROID_SURFACE_DIMENSIONS_FB) \
+
+#endif
+
+#if defined(XR_USE_PLATFORM_EGL)
+#define _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_PLATFORM_EGL(_avail, _unavail) \
+ _avail(XrGraphicsBindingEGLMNDX, XR_TYPE_GRAPHICS_BINDING_EGL_MNDX) \
+
+#else
+#define _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_PLATFORM_EGL(_avail, _unavail) \
+ _unavail(XrGraphicsBindingEGLMNDX, XR_TYPE_GRAPHICS_BINDING_EGL_MNDX) \
+
+#endif
+
+#if defined(XR_USE_PLATFORM_WIN32)
+#define _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_PLATFORM_WIN32(_avail, _unavail) \
+ _avail(XrHolographicWindowAttachmentMSFT, XR_TYPE_HOLOGRAPHIC_WINDOW_ATTACHMENT_MSFT) \
+
+#else
+#define _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_PLATFORM_WIN32(_avail, _unavail) \
+ _unavail(XrHolographicWindowAttachmentMSFT, XR_TYPE_HOLOGRAPHIC_WINDOW_ATTACHMENT_MSFT) \
+
+#endif
+
+
+
+
+#endif
+
diff --git a/thirdparty/openxr/src/loader/loader_core.cpp b/thirdparty/openxr/src/loader/loader_core.cpp
index a8bbfb4de2..f2bc87d1fa 100644
--- a/thirdparty/openxr/src/loader/loader_core.cpp
+++ b/thirdparty/openxr/src/loader/loader_core.cpp
@@ -35,7 +35,7 @@
// Global loader lock to:
// 1. Ensure ActiveLoaderInstance get and set operations are done atomically.
// 2. Ensure RuntimeInterface isn't used to unload the runtime while the runtime is in use.
-std::mutex &GetGlobalLoaderMutex() {
+static std::mutex &GetGlobalLoaderMutex() {
static std::mutex loader_mutex;
return loader_mutex;
}
@@ -58,6 +58,8 @@ static XRAPI_ATTR XrResult XRAPI_CALL LoaderXrTermDestroyDebugUtilsMessengerEXT(
static XRAPI_ATTR XrResult XRAPI_CALL LoaderXrTermSubmitDebugUtilsMessageEXT(
XrInstance instance, XrDebugUtilsMessageSeverityFlagsEXT messageSeverity, XrDebugUtilsMessageTypeFlagsEXT messageTypes,
const XrDebugUtilsMessengerCallbackDataEXT *callbackData);
+static XRAPI_ATTR XrResult XRAPI_CALL LoaderXrGetInstanceProcAddr(XrInstance instance, const char *name,
+ PFN_xrVoidFunction *function);
// Utility template function meant to validate if a fixed size string contains
// a null-terminator.
diff --git a/thirdparty/openxr/src/loader/manifest_file.cpp b/thirdparty/openxr/src/loader/manifest_file.cpp
index df99d51f8f..1b0ef07848 100644
--- a/thirdparty/openxr/src/loader/manifest_file.cpp
+++ b/thirdparty/openxr/src/loader/manifest_file.cpp
@@ -348,14 +348,20 @@ static void ReadRuntimeDataFilesInRegistry(const std::string &runtime_registry_l
if (ERROR_SUCCESS != open_value) {
LoaderLogger::LogWarningMessage("",
"ReadRuntimeDataFilesInRegistry - failed to open registry key " + full_registry_location);
- } else if (ERROR_SUCCESS != RegGetValueW(hkey, nullptr, default_runtime_value_name_w.c_str(),
- RRF_RT_REG_SZ | REG_EXPAND_SZ | RRF_ZEROONFAILURE, NULL,
- reinterpret_cast<LPBYTE>(&value_w), &value_size_w)) {
+
+ return;
+ }
+
+ if (ERROR_SUCCESS != RegGetValueW(hkey, nullptr, default_runtime_value_name_w.c_str(),
+ RRF_RT_REG_SZ | REG_EXPAND_SZ | RRF_ZEROONFAILURE, NULL, reinterpret_cast<LPBYTE>(&value_w),
+ &value_size_w)) {
LoaderLogger::LogWarningMessage(
"", "ReadRuntimeDataFilesInRegistry - failed to read registry value " + default_runtime_value_name);
} else {
AddFilesInPath(wide_to_utf8(value_w), false, manifest_files);
}
+
+ RegCloseKey(hkey);
}
// Look for layer data files in the provided paths, but first check the environment override to determine
diff --git a/thirdparty/openxr/src/xr_generated_dispatch_table.c b/thirdparty/openxr/src/xr_generated_dispatch_table.c
index 91fa0c3ca0..094f9fbbda 100644
--- a/thirdparty/openxr/src/xr_generated_dispatch_table.c
+++ b/thirdparty/openxr/src/xr_generated_dispatch_table.c
@@ -354,6 +354,13 @@ void GeneratedXrPopulateDispatchTable(struct XrGeneratedDispatchTable *table,
(get_inst_proc_addr(instance, "xrGetAudioInputDeviceGuidOculus", (PFN_xrVoidFunction*)&table->GetAudioInputDeviceGuidOculus));
#endif // defined(XR_USE_PLATFORM_WIN32)
+ // ---- XR_FB_scene extension commands
+ (get_inst_proc_addr(instance, "xrGetSpaceBoundingBox2DFB", (PFN_xrVoidFunction*)&table->GetSpaceBoundingBox2DFB));
+ (get_inst_proc_addr(instance, "xrGetSpaceBoundingBox3DFB", (PFN_xrVoidFunction*)&table->GetSpaceBoundingBox3DFB));
+ (get_inst_proc_addr(instance, "xrGetSpaceSemanticLabelsFB", (PFN_xrVoidFunction*)&table->GetSpaceSemanticLabelsFB));
+ (get_inst_proc_addr(instance, "xrGetSpaceBoundary2DFB", (PFN_xrVoidFunction*)&table->GetSpaceBoundary2DFB));
+ (get_inst_proc_addr(instance, "xrGetSpaceRoomLayoutFB", (PFN_xrVoidFunction*)&table->GetSpaceRoomLayoutFB));
+
// ---- XR_ALMALENCE_digital_lens_control extension commands
(get_inst_proc_addr(instance, "xrSetDigitalLensControlALMALENCE", (PFN_xrVoidFunction*)&table->SetDigitalLensControlALMALENCE));
@@ -368,6 +375,13 @@ void GeneratedXrPopulateDispatchTable(struct XrGeneratedDispatchTable *table,
(get_inst_proc_addr(instance, "xrSetPerformanceMetricsStateMETA", (PFN_xrVoidFunction*)&table->SetPerformanceMetricsStateMETA));
(get_inst_proc_addr(instance, "xrGetPerformanceMetricsStateMETA", (PFN_xrVoidFunction*)&table->GetPerformanceMetricsStateMETA));
(get_inst_proc_addr(instance, "xrQueryPerformanceMetricsCounterMETA", (PFN_xrVoidFunction*)&table->QueryPerformanceMetricsCounterMETA));
+
+ // ---- XR_HTC_passthrough extension commands
+ (get_inst_proc_addr(instance, "xrCreatePassthroughHTC", (PFN_xrVoidFunction*)&table->CreatePassthroughHTC));
+ (get_inst_proc_addr(instance, "xrDestroyPassthroughHTC", (PFN_xrVoidFunction*)&table->DestroyPassthroughHTC));
+
+ // ---- XR_HTC_foveation extension commands
+ (get_inst_proc_addr(instance, "xrApplyFoveationHTC", (PFN_xrVoidFunction*)&table->ApplyFoveationHTC));
}
diff --git a/thirdparty/openxr/src/xr_generated_dispatch_table.h b/thirdparty/openxr/src/xr_generated_dispatch_table.h
index 51d48bef43..93d07a149e 100644
--- a/thirdparty/openxr/src/xr_generated_dispatch_table.h
+++ b/thirdparty/openxr/src/xr_generated_dispatch_table.h
@@ -357,6 +357,13 @@ struct XrGeneratedDispatchTable {
PFN_xrGetAudioInputDeviceGuidOculus GetAudioInputDeviceGuidOculus;
#endif // defined(XR_USE_PLATFORM_WIN32)
+ // ---- XR_FB_scene extension commands
+ PFN_xrGetSpaceBoundingBox2DFB GetSpaceBoundingBox2DFB;
+ PFN_xrGetSpaceBoundingBox3DFB GetSpaceBoundingBox3DFB;
+ PFN_xrGetSpaceSemanticLabelsFB GetSpaceSemanticLabelsFB;
+ PFN_xrGetSpaceBoundary2DFB GetSpaceBoundary2DFB;
+ PFN_xrGetSpaceRoomLayoutFB GetSpaceRoomLayoutFB;
+
// ---- XR_ALMALENCE_digital_lens_control extension commands
PFN_xrSetDigitalLensControlALMALENCE SetDigitalLensControlALMALENCE;
@@ -371,6 +378,13 @@ struct XrGeneratedDispatchTable {
PFN_xrSetPerformanceMetricsStateMETA SetPerformanceMetricsStateMETA;
PFN_xrGetPerformanceMetricsStateMETA GetPerformanceMetricsStateMETA;
PFN_xrQueryPerformanceMetricsCounterMETA QueryPerformanceMetricsCounterMETA;
+
+ // ---- XR_HTC_passthrough extension commands
+ PFN_xrCreatePassthroughHTC CreatePassthroughHTC;
+ PFN_xrDestroyPassthroughHTC DestroyPassthroughHTC;
+
+ // ---- XR_HTC_foveation extension commands
+ PFN_xrApplyFoveationHTC ApplyFoveationHTC;
};
diff --git a/thirdparty/recastnavigation/Recast/Include/Recast.h b/thirdparty/recastnavigation/Recast/Include/Recast.h
index 4d557389b5..246376bbee 100644
--- a/thirdparty/recastnavigation/Recast/Include/Recast.h
+++ b/thirdparty/recastnavigation/Recast/Include/Recast.h
@@ -22,13 +22,16 @@
/// The value of PI used by Recast.
static const float RC_PI = 3.14159265f;
+/// Used to ignore unused function parameters and silence any compiler warnings.
+template<class T> void rcIgnoreUnused(const T&) { }
+
/// Recast log categories.
/// @see rcContext
enum rcLogCategory
{
RC_LOG_PROGRESS = 1, ///< A progress log entry.
RC_LOG_WARNING, ///< A warning log entry.
- RC_LOG_ERROR, ///< An error log entry.
+ RC_LOG_ERROR ///< An error log entry.
};
/// Recast performance timer categories.
@@ -101,7 +104,6 @@ enum rcTimerLabel
class rcContext
{
public:
-
/// Contructor.
/// @param[in] state TRUE if the logging and performance timers should be enabled. [Default: true]
inline rcContext(bool state = true) : m_logEnabled(state), m_timerEnabled(state) {}
@@ -140,31 +142,30 @@ public:
inline int getAccumulatedTime(const rcTimerLabel label) const { return m_timerEnabled ? doGetAccumulatedTime(label) : -1; }
protected:
-
/// Clears all log entries.
- virtual void doResetLog() {}
+ virtual void doResetLog();
/// Logs a message.
/// @param[in] category The category of the message.
/// @param[in] msg The formatted message.
/// @param[in] len The length of the formatted message.
- virtual void doLog(const rcLogCategory /*category*/, const char* /*msg*/, const int /*len*/) {}
+ virtual void doLog(const rcLogCategory category, const char* msg, const int len) { rcIgnoreUnused(category); rcIgnoreUnused(msg); rcIgnoreUnused(len); }
/// Clears all timers. (Resets all to unused.)
virtual void doResetTimers() {}
/// Starts the specified performance timer.
/// @param[in] label The category of timer.
- virtual void doStartTimer(const rcTimerLabel /*label*/) {}
+ virtual void doStartTimer(const rcTimerLabel label) { rcIgnoreUnused(label); }
/// Stops the specified performance timer.
/// @param[in] label The category of the timer.
- virtual void doStopTimer(const rcTimerLabel /*label*/) {}
+ virtual void doStopTimer(const rcTimerLabel label) { rcIgnoreUnused(label); }
/// Returns the total accumulated time of the specified performance timer.
/// @param[in] label The category of the timer.
/// @return The accumulated time of the timer, or -1 if timers are disabled or the timer has never been started.
- virtual int doGetAccumulatedTime(const rcTimerLabel /*label*/) const { return -1; }
+ virtual int doGetAccumulatedTime(const rcTimerLabel label) const { rcIgnoreUnused(label); return -1; }
/// True if logging is enabled.
bool m_logEnabled;
@@ -564,7 +565,7 @@ static const int RC_AREA_BORDER = 0x20000;
enum rcBuildContoursFlags
{
RC_CONTOUR_TESS_WALL_EDGES = 0x01, ///< Tessellate solid (impassable) edges during contour simplification.
- RC_CONTOUR_TESS_AREA_EDGES = 0x02, ///< Tessellate edges between areas during contour simplification.
+ RC_CONTOUR_TESS_AREA_EDGES = 0x02 ///< Tessellate edges between areas during contour simplification.
};
/// Applied to the region id field of contour vertices in order to extract the region id.
@@ -595,11 +596,6 @@ static const int RC_NOT_CONNECTED = 0x3f;
/// @name General helper functions
/// @{
-/// Used to ignore a function parameter. VS complains about unused parameters
-/// and this silences the warning.
-/// @param [in] _ Unused parameter
-template<class T> void rcIgnoreUnused(const T&) { }
-
/// Swaps the values of the two parameters.
/// @param[in,out] a Value A
/// @param[in,out] b Value B
@@ -996,6 +992,7 @@ void rcMarkConvexPolyArea(rcContext* ctx, const float* verts, const int nverts,
/// @ingroup recast
/// @param[in] verts The vertices of the polygon [Form: (x, y, z) * @p nverts]
/// @param[in] nverts The number of vertices in the polygon.
+/// @param[in] offset How much to offset the polygon by. [Units: wu]
/// @param[out] outVerts The offset vertices (should hold up to 2 * @p nverts) [Form: (x, y, z) * return value]
/// @param[in] maxOutVerts The max number of vertices that can be stored to @p outVerts.
/// @returns Number of vertices in the offset polygon or 0 if too few vertices in @p outVerts.
diff --git a/thirdparty/recastnavigation/Recast/Include/RecastAlloc.h b/thirdparty/recastnavigation/Recast/Include/RecastAlloc.h
index 071278d659..8b166d736d 100644
--- a/thirdparty/recastnavigation/Recast/Include/RecastAlloc.h
+++ b/thirdparty/recastnavigation/Recast/Include/RecastAlloc.h
@@ -112,7 +112,7 @@ class rcVectorBase {
typedef rcSizeType size_type;
typedef T value_type;
- rcVectorBase() : m_size(0), m_cap(0), m_data(0) {};
+ rcVectorBase() : m_size(0), m_cap(0), m_data(0) {}
rcVectorBase(const rcVectorBase<T, H>& other) : m_size(0), m_cap(0), m_data(0) { assign(other.begin(), other.end()); }
explicit rcVectorBase(rcSizeType count) : m_size(0), m_cap(0), m_data(0) { resize(count); }
rcVectorBase(rcSizeType count, const T& value) : m_size(0), m_cap(0), m_data(0) { resize(count, value); }
@@ -142,8 +142,8 @@ class rcVectorBase {
const T& front() const { rcAssert(m_size); return m_data[0]; }
T& front() { rcAssert(m_size); return m_data[0]; }
- const T& back() const { rcAssert(m_size); return m_data[m_size - 1]; };
- T& back() { rcAssert(m_size); return m_data[m_size - 1]; };
+ const T& back() const { rcAssert(m_size); return m_data[m_size - 1]; }
+ T& back() { rcAssert(m_size); return m_data[m_size - 1]; }
const T* data() const { return m_data; }
T* data() { return m_data; }
diff --git a/thirdparty/recastnavigation/Recast/Source/Recast.cpp b/thirdparty/recastnavigation/Recast/Source/Recast.cpp
index 1b71710cdc..4cf145c981 100644
--- a/thirdparty/recastnavigation/Recast/Source/Recast.cpp
+++ b/thirdparty/recastnavigation/Recast/Source/Recast.cpp
@@ -94,6 +94,11 @@ void rcContext::log(const rcLogCategory category, const char* format, ...)
doLog(category, msg, len);
}
+void rcContext::doResetLog()
+{
+ // Defined out of line to fix the weak v-tables warning
+}
+
rcHeightfield* rcAllocHeightfield()
{
return rcNew<rcHeightfield>(RC_ALLOC_PERM);
diff --git a/thirdparty/recastnavigation/Recast/Source/RecastMesh.cpp b/thirdparty/recastnavigation/Recast/Source/RecastMesh.cpp
index e99eaebb79..ea09ee1de0 100644
--- a/thirdparty/recastnavigation/Recast/Source/RecastMesh.cpp
+++ b/thirdparty/recastnavigation/Recast/Source/RecastMesh.cpp
@@ -566,7 +566,6 @@ static bool canRemoveVertex(rcContext* ctx, rcPolyMesh& mesh, const unsigned sho
const int nvp = mesh.nvp;
// Count number of polygons to remove.
- int numRemovedVerts = 0;
int numTouchedVerts = 0;
int numRemainingEdges = 0;
for (int i = 0; i < mesh.npolys; ++i)
@@ -586,7 +585,6 @@ static bool canRemoveVertex(rcContext* ctx, rcPolyMesh& mesh, const unsigned sho
}
if (numRemoved)
{
- numRemovedVerts += numRemoved;
numRemainingEdges += numVerts-(numRemoved+1);
}
}
diff --git a/thirdparty/recastnavigation/Recast/Source/RecastMeshDetail.cpp b/thirdparty/recastnavigation/Recast/Source/RecastMeshDetail.cpp
index 1999200c1a..40bfc9b4bc 100644
--- a/thirdparty/recastnavigation/Recast/Source/RecastMeshDetail.cpp
+++ b/thirdparty/recastnavigation/Recast/Source/RecastMeshDetail.cpp
@@ -284,7 +284,7 @@ static unsigned short getHeight(const float fx, const float fy, const float fz,
enum EdgeValues
{
EV_UNDEF = -1,
- EV_HULL = -2,
+ EV_HULL = -2
};
static int findEdge(const int* edges, int nedges, int s, int t)
diff --git a/thirdparty/recastnavigation/Recast/Source/RecastRasterization.cpp b/thirdparty/recastnavigation/Recast/Source/RecastRasterization.cpp
index a4cef74909..673550e79e 100644
--- a/thirdparty/recastnavigation/Recast/Source/RecastRasterization.cpp
+++ b/thirdparty/recastnavigation/Recast/Source/RecastRasterization.cpp
@@ -264,7 +264,8 @@ static bool rasterizeTri(const float* v0, const float* v1, const float* v2,
// Calculate the footprint of the triangle on the grid's y-axis
int y0 = (int)((tmin[2] - bmin[2])*ics);
int y1 = (int)((tmax[2] - bmin[2])*ics);
- y0 = rcClamp(y0, 0, h-1);
+ // use -1 rather than 0 to cut the polygon properly at the start of the tile
+ y0 = rcClamp(y0, -1, h-1);
y1 = rcClamp(y1, 0, h-1);
// Clip the triangle into all grid cells it touches.
@@ -283,7 +284,7 @@ static bool rasterizeTri(const float* v0, const float* v1, const float* v2,
dividePoly(in, nvIn, inrow, &nvrow, p1, &nvIn, cz+cs, 2);
rcSwap(in, p1);
if (nvrow < 3) continue;
-
+ if (y < 0) continue;
// find the horizontal bounds in the row
float minX = inrow[0], maxX = inrow[0];
for (int i=1; i<nvrow; ++i)
@@ -293,7 +294,10 @@ static bool rasterizeTri(const float* v0, const float* v1, const float* v2,
}
int x0 = (int)((minX - bmin[0])*ics);
int x1 = (int)((maxX - bmin[0])*ics);
- x0 = rcClamp(x0, 0, w-1);
+ if (x1 < 0 || x0 >= w) {
+ continue;
+ }
+ x0 = rcClamp(x0, -1, w-1);
x1 = rcClamp(x1, 0, w-1);
int nv, nv2 = nvrow;
@@ -305,7 +309,7 @@ static bool rasterizeTri(const float* v0, const float* v1, const float* v2,
dividePoly(inrow, nv2, p1, &nv, p2, &nv2, cx+cs, 0);
rcSwap(inrow, p2);
if (nv < 3) continue;
-
+ if (x < 0) continue;
// Calculate min and max of the span.
float smin = p1[1], smax = p1[1];
for (int i = 1; i < nv; ++i)
diff --git a/thirdparty/thorvg/inc/config.h b/thirdparty/thorvg/inc/config.h
index 68935c583b..eda302aec0 100644
--- a/thirdparty/thorvg/inc/config.h
+++ b/thirdparty/thorvg/inc/config.h
@@ -13,5 +13,5 @@
#define THORVG_JPG_LOADER_SUPPORT 1
-#define THORVG_VERSION_STRING "0.8.2"
+#define THORVG_VERSION_STRING "0.8.3"
#endif
diff --git a/thirdparty/thorvg/inc/thorvg.h b/thirdparty/thorvg/inc/thorvg.h
index b08356d9d5..7e8988a65e 100644
--- a/thirdparty/thorvg/inc/thorvg.h
+++ b/thirdparty/thorvg/inc/thorvg.h
@@ -18,7 +18,7 @@
#include <string>
#ifdef TVG_BUILD
- #if defined(_MSC_VER) && !defined(__clang__)
+ #if defined(_WIN32) && !defined(__clang__)
#define TVG_EXPORT __declspec(dllexport)
#define TVG_DEPRECATED __declspec(deprecated)
#else
@@ -74,7 +74,7 @@ class Accessor;
/**
* @brief Enumeration specifying the result from the APIs.
*/
-enum class TVG_EXPORT Result
+enum class Result
{
Success = 0, ///< The value returned in case of a correct request execution.
InvalidArguments, ///< The value returned in the event of a problem with the arguments given to the API - e.g. empty paths or null pointers.
@@ -91,7 +91,7 @@ enum class TVG_EXPORT Result
* Not to be confused with the path commands from the svg path element (like M, L, Q, H and many others).
* TVG interprets all of them and translates to the ones from the PathCommand values.
*/
-enum class TVG_EXPORT PathCommand
+enum class PathCommand
{
Close = 0, ///< Ends the current sub-path and connects it with its initial point. This command doesn't expect any points.
MoveTo, ///< Sets a new initial point of the sub-path and a new current point. This command expects 1 point: the starting position.
@@ -102,7 +102,7 @@ enum class TVG_EXPORT PathCommand
/**
* @brief Enumeration determining the ending type of a stroke in the open sub-paths.
*/
-enum class TVG_EXPORT StrokeCap
+enum class StrokeCap
{
Square = 0, ///< The stroke is extended in both end-points of a sub-path by a rectangle, with the width equal to the stroke width and the length equal to the half of the stroke width. For zero length sub-paths the square is rendered with the size of the stroke width.
Round, ///< The stroke is extended in both end-points of a sub-path by a half circle, with a radius equal to the half of a stroke width. For zero length sub-paths a full circle is rendered.
@@ -112,7 +112,7 @@ enum class TVG_EXPORT StrokeCap
/**
* @brief Enumeration determining the style used at the corners of joined stroked path segments.
*/
-enum class TVG_EXPORT StrokeJoin
+enum class StrokeJoin
{
Bevel = 0, ///< The outer corner of the joined path segments is bevelled at the join point. The triangular region of the corner is enclosed by a straight line between the outer corners of each stroke.
Round, ///< The outer corner of the joined path segments is rounded. The circular region is centered at the join point.
@@ -122,7 +122,7 @@ enum class TVG_EXPORT StrokeJoin
/**
* @brief Enumeration specifying how to fill the area outside the gradient bounds.
*/
-enum class TVG_EXPORT FillSpread
+enum class FillSpread
{
Pad = 0, ///< The remaining area is filled with the closest stop color.
Reflect, ///< The gradient pattern is reflected outside the gradient area until the expected region is filled.
@@ -132,7 +132,7 @@ enum class TVG_EXPORT FillSpread
/**
* @brief Enumeration specifying the algorithm used to establish which parts of the shape are treated as the inside of the shape.
*/
-enum class TVG_EXPORT FillRule
+enum class FillRule
{
Winding = 0, ///< A line from the point to a location outside the shape is drawn. The intersections of the line with the path segment of the shape are counted. Starting from zero, if the path segment of the shape crosses the line clockwise, one is added, otherwise one is subtracted. If the resulting sum is non zero, the point is inside the shape.
EvenOdd ///< A line from the point to a location outside the shape is drawn and its intersections with the path segments of the shape are counted. If the number of intersections is an odd number, the point is inside the shape.
@@ -141,7 +141,7 @@ enum class TVG_EXPORT FillRule
/**
* @brief Enumeration indicating the method used in the composition of two objects - the target and the source.
*/
-enum class TVG_EXPORT CompositeMethod
+enum class CompositeMethod
{
None = 0, ///< No composition is applied.
ClipPath, ///< The intersection of the source and the target is determined and only the resulting pixels from the source are rendered.
@@ -153,7 +153,7 @@ enum class TVG_EXPORT CompositeMethod
/**
* @brief Enumeration specifying the engine type used for the graphics backend. For multiple backends bitwise operation is allowed.
*/
-enum class TVG_EXPORT CanvasEngine
+enum class CanvasEngine
{
Sw = (1 << 1), ///< CPU rasterizer.
Gl = (1 << 2) ///< OpenGL rasterizer.
diff --git a/thirdparty/thorvg/src/lib/sw_engine/tvgSwRaster.cpp b/thirdparty/thorvg/src/lib/sw_engine/tvgSwRaster.cpp
index bf1c10a0c3..ffd74bdd47 100644
--- a/thirdparty/thorvg/src/lib/sw_engine/tvgSwRaster.cpp
+++ b/thirdparty/thorvg/src/lib/sw_engine/tvgSwRaster.cpp
@@ -22,10 +22,10 @@
#ifdef _WIN32
#include <malloc.h>
-#elif __FreeBSD__
- #include<stdlib.h>
-#else
+#elif defined(__linux__)
#include <alloca.h>
+#else
+ #include <stdlib.h>
#endif
#include "tvgMath.h"
diff --git a/thirdparty/thorvg/src/lib/sw_engine/tvgSwRasterTexmapInternal.h b/thirdparty/thorvg/src/lib/sw_engine/tvgSwRasterTexmapInternal.h
index f31ea1eb97..50536299b1 100644
--- a/thirdparty/thorvg/src/lib/sw_engine/tvgSwRasterTexmapInternal.h
+++ b/thirdparty/thorvg/src/lib/sw_engine/tvgSwRasterTexmapInternal.h
@@ -30,7 +30,7 @@
int32_t dw = surface->stride;
int32_t x1, x2, x, y, ar, ab, iru, irv, px, ay;
int32_t vv = 0, uu = 0;
- int32_t minx, maxx;
+ int32_t minx = INT32_MAX, maxx = INT32_MIN;
float dx, u, v, iptr;
uint32_t* buf;
SwSpan* span = nullptr; //used only when rle based.
diff --git a/thirdparty/thorvg/src/lib/tvgLoadModule.h b/thirdparty/thorvg/src/lib/tvgLoadModule.h
index bfcc165f31..004983152b 100644
--- a/thirdparty/thorvg/src/lib/tvgLoadModule.h
+++ b/thirdparty/thorvg/src/lib/tvgLoadModule.h
@@ -36,7 +36,6 @@ public:
float vw = 0;
float vh = 0;
float w = 0, h = 0; //default image size
- bool preserveAspect = true; //keep aspect ratio by default.
virtual ~LoadModule() {}
diff --git a/thirdparty/thorvg/src/loaders/jpg/tvgJpgLoader.cpp b/thirdparty/thorvg/src/loaders/jpg/tvgJpgLoader.cpp
index ffdef3004c..d11dfc1e7c 100644
--- a/thirdparty/thorvg/src/loaders/jpg/tvgJpgLoader.cpp
+++ b/thirdparty/thorvg/src/loaders/jpg/tvgJpgLoader.cpp
@@ -118,9 +118,9 @@ unique_ptr<Surface> JpgLoader::bitmap()
auto surface = static_cast<Surface*>(malloc(sizeof(Surface)));
surface->buffer = (uint32_t*)(image);
- surface->stride = w;
- surface->w = w;
- surface->h = h;
+ surface->stride = static_cast<uint32_t>(w);
+ surface->w = static_cast<uint32_t>(w);
+ surface->h = static_cast<uint32_t>(h);
surface->cs = SwCanvas::ARGB8888;
return unique_ptr<Surface>(surface);
diff --git a/thirdparty/thorvg/src/loaders/jpg/tvgJpgd.cpp b/thirdparty/thorvg/src/loaders/jpg/tvgJpgd.cpp
index dacd45ed03..56b40acf0b 100644
--- a/thirdparty/thorvg/src/loaders/jpg/tvgJpgd.cpp
+++ b/thirdparty/thorvg/src/loaders/jpg/tvgJpgd.cpp
@@ -808,7 +808,7 @@ inline int jpeg_decoder::huff_decode(huff_tables *pH, int& extra_bits)
// Tables and macro used to fully decode the DPCM differences.
static const int s_extend_test[16] = { 0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000 };
-static const unsigned int s_extend_offset[16] = { 0, ((-1u)<<1) + 1, ((-1u)<<2) + 1, ((-1u)<<3) + 1, ((-1u)<<4) + 1, ((-1u)<<5) + 1, ((-1u)<<6) + 1, ((-1u)<<7) + 1, ((-1u)<<8) + 1, ((-1u)<<9) + 1, ((-1u)<<10) + 1, ((-1u)<<11) + 1, ((-1u)<<12) + 1, ((-1u)<<13) + 1, ((-1u)<<14) + 1, ((-1u)<<15) + 1 };
+static const unsigned int s_extend_offset[16] = { 0, ((~0u)<<1) + 1, ((~0u)<<2) + 1, ((~0u)<<3) + 1, ((~0u)<<4) + 1, ((~0u)<<5) + 1, ((~0u)<<6) + 1, ((~0u)<<7) + 1, ((~0u)<<8) + 1, ((~0u)<<9) + 1, ((~0u)<<10) + 1, ((~0u)<<11) + 1, ((~0u)<<12) + 1, ((~0u)<<13) + 1, ((~0u)<<14) + 1, ((~0u)<<15) + 1 };
// The logical AND's in this macro are to shut up static code analysis (aren't really necessary - couldn't find another way to do this)
#define JPGD_HUFF_EXTEND(x, s) (((x) < s_extend_test[s & 15]) ? ((x) + s_extend_offset[s & 15]) : (x))
diff --git a/thirdparty/thorvg/src/loaders/raw/tvgRawLoader.cpp b/thirdparty/thorvg/src/loaders/raw/tvgRawLoader.cpp
index 2da399d8c3..889f130ce9 100644
--- a/thirdparty/thorvg/src/loaders/raw/tvgRawLoader.cpp
+++ b/thirdparty/thorvg/src/loaders/raw/tvgRawLoader.cpp
@@ -78,9 +78,9 @@ unique_ptr<Surface> RawLoader::bitmap()
auto surface = static_cast<Surface*>(malloc(sizeof(Surface)));
surface->buffer = (uint32_t*)(content);
- surface->stride = w;
- surface->w = w;
- surface->h = h;
+ surface->stride = (uint32_t)w;
+ surface->w = (uint32_t)w;
+ surface->h = (uint32_t)h;
surface->cs = SwCanvas::ARGB8888;
return unique_ptr<Surface>(surface);
diff --git a/thirdparty/thorvg/src/loaders/svg/tvgSvgCssStyle.cpp b/thirdparty/thorvg/src/loaders/svg/tvgSvgCssStyle.cpp
index 8f46b62ce9..478ba5d3d1 100644
--- a/thirdparty/thorvg/src/loaders/svg/tvgSvgCssStyle.cpp
+++ b/thirdparty/thorvg/src/loaders/svg/tvgSvgCssStyle.cpp
@@ -42,7 +42,10 @@ static void _copyStyle(SvgStyleProperty* to, const SvgStyleProperty* from)
to->fill.paint.color = from->fill.paint.color;
to->fill.paint.none = from->fill.paint.none;
to->fill.paint.curColor = from->fill.paint.curColor;
- if (from->fill.paint.url) to->fill.paint.url = strdup(from->fill.paint.url);
+ if (from->fill.paint.url) {
+ if (to->fill.paint.url) free(to->fill.paint.url);
+ to->fill.paint.url = strdup(from->fill.paint.url);
+ }
to->fill.flags = (SvgFillFlags)((int)to->fill.flags | (int)SvgFillFlags::Paint);
to->flags = (SvgStyleFlags)((int)to->flags | (int)SvgStyleFlags::Fill);
}
@@ -61,7 +64,10 @@ static void _copyStyle(SvgStyleProperty* to, const SvgStyleProperty* from)
to->stroke.paint.color = from->stroke.paint.color;
to->stroke.paint.none = from->stroke.paint.none;
to->stroke.paint.curColor = from->stroke.paint.curColor;
- if (from->stroke.paint.url) to->stroke.paint.url = strdup(from->stroke.paint.url);
+ if (from->stroke.paint.url) {
+ if (to->stroke.paint.url) free(to->stroke.paint.url);
+ to->stroke.paint.url = strdup(from->stroke.paint.url);
+ }
to->stroke.flags = (SvgStrokeFlags)((int)to->stroke.flags | (int)SvgStrokeFlags::Paint);
to->flags = (SvgStyleFlags)((int)to->flags | (int)SvgStyleFlags::Stroke);
}
@@ -122,8 +128,14 @@ void cssCopyStyleAttr(SvgNode* to, const SvgNode* from)
//Copy style attribute
_copyStyle(to->style, from->style);
- if (from->style->clipPath.url) to->style->clipPath.url = strdup(from->style->clipPath.url);
- if (from->style->mask.url) to->style->mask.url = strdup(from->style->mask.url);
+ if (from->style->clipPath.url) {
+ if (to->style->clipPath.url) free(to->style->clipPath.url);
+ to->style->clipPath.url = strdup(from->style->clipPath.url);
+ }
+ if (from->style->mask.url) {
+ if (to->style->mask.url) free(to->style->mask.url);
+ to->style->mask.url = strdup(from->style->mask.url);
+ }
}
diff --git a/thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.cpp b/thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.cpp
index 42bfd4de70..737fd96455 100644
--- a/thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.cpp
+++ b/thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.cpp
@@ -115,9 +115,54 @@ static bool _parseNumber(const char** content, float* number)
if ((*content) == end) return false;
//Skip comma if any
*content = _skipComma(end);
+
return true;
}
+
+static constexpr struct
+{
+ AspectRatioAlign align;
+ const char* tag;
+} alignTags[] = {
+ { AspectRatioAlign::XMinYMin, "xMinYMin" },
+ { AspectRatioAlign::XMidYMin, "xMidYMin" },
+ { AspectRatioAlign::XMaxYMin, "xMaxYMin" },
+ { AspectRatioAlign::XMinYMid, "xMinYMid" },
+ { AspectRatioAlign::XMidYMid, "xMidYMid" },
+ { AspectRatioAlign::XMaxYMid, "xMaxYMid" },
+ { AspectRatioAlign::XMinYMax, "xMinYMax" },
+ { AspectRatioAlign::XMidYMax, "xMidYMax" },
+ { AspectRatioAlign::XMaxYMax, "xMaxYMax" },
+};
+
+
+static bool _parseAspectRatio(const char** content, AspectRatioAlign* align, AspectRatioMeetOrSlice* meetOrSlice)
+{
+ if (!strcmp(*content, "none")) {
+ *align = AspectRatioAlign::None;
+ return true;
+ }
+
+ for (unsigned int i = 0; i < sizeof(alignTags) / sizeof(alignTags[0]); i++) {
+ if (!strncmp(*content, alignTags[i].tag, 8)) {
+ *align = alignTags[i].align;
+ *content += 8;
+ *content = _skipSpace(*content, nullptr);
+ break;
+ }
+ }
+
+ if (!strcmp(*content, "meet")) {
+ *meetOrSlice = AspectRatioMeetOrSlice::Meet;
+ } else if (!strcmp(*content, "slice")) {
+ *meetOrSlice = AspectRatioMeetOrSlice::Slice;
+ }
+
+ return true;
+}
+
+
/**
* According to https://www.w3.org/TR/SVG/coords.html#Units
*/
@@ -554,6 +599,7 @@ static void _toColor(const char* str, uint8_t* r, uint8_t* g, uint8_t* b, char**
}
}
} else if (ref && len >= 3 && !strncmp(str, "url", 3)) {
+ if (*ref) free(*ref);
*ref = _idFromUrl((const char*)(str + 3));
} else {
//Handle named color
@@ -802,7 +848,7 @@ static bool _attrParseSvgNode(void* data, const char* key, const char* value)
}
loader->svgParse->global.x = (int)doc->vx;
} else if (!strcmp(key, "preserveAspectRatio")) {
- if (!strcmp(value, "none")) doc->preserveAspect = false;
+ _parseAspectRatio(&value, &doc->align, &doc->meetOrSlice);
} else if (!strcmp(key, "style")) {
return simpleXmlParseW3CAttribute(value, strlen(value), _parseStyleAttr, loader);
#ifdef THORVG_LOG_ENABLED
@@ -1156,7 +1202,7 @@ static bool _attrParseSymbolNode(void* data, const char* key, const char* value)
symbol->h = _toFloat(loader->svgParse, value, SvgParserLengthType::Vertical);
symbol->hasHeight = true;
} else if (!strcmp(key, "preserveAspectRatio")) {
- if (!strcmp(value, "none")) symbol->preserveAspect = false;
+ _parseAspectRatio(&value, &symbol->align, &symbol->meetOrSlice);
} else if (!strcmp(key, "overflow")) {
if (!strcmp(value, "visible")) symbol->overflowVisible = true;
} else {
@@ -1248,7 +1294,8 @@ static SvgNode* _createSvgNode(SvgLoaderData* loader, SvgNode* parent, const cha
loader->svgParse->global.w = 0;
loader->svgParse->global.h = 0;
- doc->preserveAspect = true;
+ doc->align = AspectRatioAlign::XMidYMid;
+ doc->meetOrSlice = AspectRatioMeetOrSlice::Meet;
func(buf, bufLength, _attrParseSvgNode, loader);
if (loader->svgParse->global.w == 0) {
@@ -1309,7 +1356,8 @@ static SvgNode* _createSymbolNode(SvgLoaderData* loader, SvgNode* parent, const
if (!loader->svgParse->node) return nullptr;
loader->svgParse->node->display = false;
- loader->svgParse->node->node.symbol.preserveAspect = true;
+ loader->svgParse->node->node.symbol.align = AspectRatioAlign::XMidYMid;
+ loader->svgParse->node->node.symbol.meetOrSlice = AspectRatioMeetOrSlice::Meet;
loader->svgParse->node->node.symbol.overflowVisible = false;
loader->svgParse->node->node.symbol.hasViewBox = false;
@@ -1331,6 +1379,7 @@ static bool _attrParsePathNode(void* data, const char* key, const char* value)
SvgPathNode* path = &(node->node.path);
if (!strcmp(key, "d")) {
+ if (path->path) free(path->path);
//Temporary: need to copy
path->path = _copyId(value);
} else if (!strcmp(key, "style")) {
@@ -1801,19 +1850,10 @@ static SvgNode* _getDefsNode(SvgNode* node)
}
-static SvgNode* _findChildById(const SvgNode* node, const char* id)
+static SvgNode* _findNodeById(SvgNode *node, const char* id)
{
if (!node) return nullptr;
- auto child = node->child.data;
- for (uint32_t i = 0; i < node->child.count; ++i, ++child) {
- if (((*child)->id) && !strcmp((*child)->id, id)) return (*child);
- }
- return nullptr;
-}
-
-static SvgNode* _findNodeById(SvgNode *node, const char* id)
-{
SvgNode* result = nullptr;
if (node->id && !strcmp(node->id, id)) return node;
@@ -1827,6 +1867,7 @@ static SvgNode* _findNodeById(SvgNode *node, const char* id)
return result;
}
+
static void _cloneGradStops(Array<Fill::ColorStop>& dst, const Array<Fill::ColorStop>& src)
{
for (uint32_t i = 0; i < src.count; ++i) {
@@ -1889,7 +1930,10 @@ static void _styleInherit(SvgStyleProperty* child, const SvgStyleProperty* paren
child->fill.paint.color = parent->fill.paint.color;
child->fill.paint.none = parent->fill.paint.none;
child->fill.paint.curColor = parent->fill.paint.curColor;
- if (parent->fill.paint.url) child->fill.paint.url = _copyId(parent->fill.paint.url);
+ if (parent->fill.paint.url) {
+ if (child->fill.paint.url) free(child->fill.paint.url);
+ child->fill.paint.url = _copyId(parent->fill.paint.url);
+ }
}
if (!((int)child->fill.flags & (int)SvgFillFlags::Opacity)) {
child->fill.opacity = parent->fill.opacity;
@@ -1902,7 +1946,12 @@ static void _styleInherit(SvgStyleProperty* child, const SvgStyleProperty* paren
child->stroke.paint.color = parent->stroke.paint.color;
child->stroke.paint.none = parent->stroke.paint.none;
child->stroke.paint.curColor = parent->stroke.paint.curColor;
- child->stroke.paint.url = parent->stroke.paint.url ? _copyId(parent->stroke.paint.url) : nullptr;
+ if (parent->stroke.paint.url) {
+ if (child->stroke.paint.url) free(child->stroke.paint.url);
+ child->stroke.paint.url = _copyId(parent->stroke.paint.url);
+ } else {
+ child->stroke.paint.url = nullptr;
+ }
}
if (!((int)child->stroke.flags & (int)SvgStrokeFlags::Opacity)) {
child->stroke.opacity = parent->stroke.opacity;
@@ -1942,7 +1991,10 @@ static void _styleCopy(SvgStyleProperty* to, const SvgStyleProperty* from)
to->fill.paint.color = from->fill.paint.color;
to->fill.paint.none = from->fill.paint.none;
to->fill.paint.curColor = from->fill.paint.curColor;
- if (from->fill.paint.url) to->fill.paint.url = _copyId(from->fill.paint.url);
+ if (from->fill.paint.url) {
+ if (to->fill.paint.url) free(to->fill.paint.url);
+ to->fill.paint.url = _copyId(from->fill.paint.url);
+ }
}
if (((int)from->fill.flags & (int)SvgFillFlags::Opacity)) {
to->fill.opacity = from->fill.opacity;
@@ -1956,7 +2008,12 @@ static void _styleCopy(SvgStyleProperty* to, const SvgStyleProperty* from)
to->stroke.paint.color = from->stroke.paint.color;
to->stroke.paint.none = from->stroke.paint.none;
to->stroke.paint.curColor = from->stroke.paint.curColor;
- to->stroke.paint.url = from->stroke.paint.url ? _copyId(from->stroke.paint.url) : nullptr;
+ if (from->stroke.paint.url) {
+ if (to->stroke.paint.url) free(to->stroke.paint.url);
+ to->stroke.paint.url = _copyId(from->stroke.paint.url);
+ } else {
+ to->stroke.paint.url = nullptr;
+ }
}
if (((int)from->stroke.flags & (int)SvgStrokeFlags::Opacity)) {
to->stroke.opacity = from->stroke.opacity;
@@ -1992,10 +2049,14 @@ static void _copyAttr(SvgNode* to, const SvgNode* from)
//Copy style attribute
_styleCopy(to->style, from->style);
to->style->flags = (SvgStyleFlags)((int)to->style->flags | (int)from->style->flags);
- if (from->style->fill.paint.url) to->style->fill.paint.url = strdup(from->style->fill.paint.url);
- if (from->style->stroke.paint.url) to->style->stroke.paint.url = strdup(from->style->stroke.paint.url);
- if (from->style->clipPath.url) to->style->clipPath.url = strdup(from->style->clipPath.url);
- if (from->style->mask.url) to->style->mask.url = strdup(from->style->mask.url);
+ if (from->style->clipPath.url) {
+ if (to->style->clipPath.url) free(to->style->clipPath.url);
+ to->style->clipPath.url = strdup(from->style->clipPath.url);
+ }
+ if (from->style->mask.url) {
+ if (to->style->mask.url) free(to->style->mask.url);
+ to->style->mask.url = strdup(from->style->mask.url);
+ }
//Copy node attribute
switch (from->type) {
@@ -2031,7 +2092,10 @@ static void _copyAttr(SvgNode* to, const SvgNode* from)
break;
}
case SvgNodeType::Path: {
- if (from->node.path.path) to->node.path.path = strdup(from->node.path.path);
+ if (from->node.path.path) {
+ if (to->node.path.path) free(to->node.path.path);
+ to->node.path.path = strdup(from->node.path.path);
+ }
break;
}
case SvgNodeType::Polygon: {
@@ -2053,7 +2117,10 @@ static void _copyAttr(SvgNode* to, const SvgNode* from)
to->node.image.y = from->node.image.y;
to->node.image.w = from->node.image.w;
to->node.image.h = from->node.image.h;
- if (from->node.image.href) to->node.image.href = strdup(from->node.image.href);
+ if (from->node.image.href) {
+ if (to->node.image.href) free(to->node.image.href);
+ to->node.image.href = strdup(from->node.image.href);
+ }
break;
}
default: {
@@ -2093,8 +2160,8 @@ static void _clonePostponedNodes(Array<SvgNodeIdPair>* cloneNodes, SvgNode* doc)
for (uint32_t i = 0; i < cloneNodes->count; ++i) {
auto nodeIdPair = cloneNodes->data[i];
auto defs = _getDefsNode(nodeIdPair.node);
- auto nodeFrom = _findChildById(defs, nodeIdPair.id);
- if (!nodeFrom) nodeFrom = _findChildById(doc, nodeIdPair.id);
+ auto nodeFrom = _findNodeById(defs, nodeIdPair.id);
+ if (!nodeFrom) nodeFrom = _findNodeById(doc, nodeIdPair.id);
_cloneNode(nodeFrom, nodeIdPair.node, 0);
if (nodeFrom && nodeFrom->type == SvgNodeType::Symbol && nodeIdPair.node->type == SvgNodeType::Use) {
nodeIdPair.node->node.use.symbol = nodeFrom;
@@ -2141,7 +2208,7 @@ static bool _attrParseUseNode(void* data, const char* key, const char* value)
if (!strcmp(key, "href") || !strcmp(key, "xlink:href")) {
id = _idFromHref(value);
defs = _getDefsNode(node);
- nodeFrom = _findChildById(defs, id);
+ nodeFrom = _findNodeById(defs, id);
if (nodeFrom) {
_cloneNode(nodeFrom, node, 0);
if (nodeFrom->type == SvgNodeType::Symbol) use->symbol = nodeFrom;
@@ -2695,10 +2762,14 @@ static void _svgLoaderParserXmlOpen(SvgLoaderData* loader, const char* content,
if (loader->stack.count > 0) parent = loader->stack.data[loader->stack.count - 1];
else parent = loader->doc;
if (!strcmp(tagName, "style")) {
- node = method(loader, nullptr, attrs, attrsLength, simpleXmlParseAttributes);
- loader->cssStyle = node;
- loader->doc->node.doc.style = node;
- loader->style = true;
+ // TODO: For now only the first style node is saved. After the css id selector
+ // is introduced this if condition shouldin't be necessary any more
+ if (!loader->cssStyle) {
+ node = method(loader, nullptr, attrs, attrsLength, simpleXmlParseAttributes);
+ loader->cssStyle = node;
+ loader->doc->node.doc.style = node;
+ loader->style = true;
+ }
} else {
node = method(loader, parent, attrs, attrsLength, simpleXmlParseAttributes);
}
@@ -3127,7 +3198,7 @@ void SvgLoader::run(unsigned tid)
_updateStyle(loaderData.doc, nullptr);
}
- root = svgSceneBuild(loaderData.doc, vx, vy, vw, vh, w, h, preserveAspect, svgPath);
+ root = svgSceneBuild(loaderData.doc, vx, vy, vw, vh, w, h, align, meetOrSlice, svgPath);
}
@@ -3160,7 +3231,8 @@ bool SvgLoader::header()
if (vh < FLT_EPSILON) vh = h;
}
- preserveAspect = loaderData.doc->node.doc.preserveAspect;
+ align = loaderData.doc->node.doc.align;
+ meetOrSlice = loaderData.doc->node.doc.meetOrSlice;
} else {
TVGLOG("SVG", "No SVG File. There is no <svg/>");
return false;
@@ -3215,31 +3287,9 @@ bool SvgLoader::resize(Paint* paint, float w, float h)
auto sx = w / this->w;
auto sy = h / this->h;
+ Matrix m = {sx, 0, 0, 0, sy, 0, 0, 0, 1};
+ paint->transform(m);
- if (preserveAspect) {
- //Scale
- auto scale = sx < sy ? sx : sy;
- paint->scale(scale);
- //Align
- auto tx = 0.0f;
- auto ty = 0.0f;
- auto tw = this->w * scale;
- auto th = this->h * scale;
- if (tw > th) ty -= (h - th) * 0.5f;
- else tx -= (w - tw) * 0.5f;
- paint->translate(-tx, -ty);
- } else {
- //Align
- auto tx = 0.0f;
- auto ty = 0.0f;
- auto tw = this->w * sx;
- auto th = this->h * sy;
- if (tw > th) ty -= (h - th) * 0.5f;
- else tx -= (w - tw) * 0.5f;
-
- Matrix m = {sx, 0, -tx, 0, sy, -ty, 0, 0, 1};
- paint->transform(m);
- }
return true;
}
diff --git a/thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.h b/thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.h
index 093fb671b3..f224d1a4ac 100644
--- a/thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.h
+++ b/thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.h
@@ -50,6 +50,9 @@ public:
unique_ptr<Paint> paint() override;
private:
+ AspectRatioAlign align = AspectRatioAlign::XMidYMid;
+ AspectRatioMeetOrSlice meetOrSlice = AspectRatioMeetOrSlice::Meet;
+
bool header();
void clear();
void run(unsigned tid) override;
diff --git a/thirdparty/thorvg/src/loaders/svg/tvgSvgLoaderCommon.h b/thirdparty/thorvg/src/loaders/svg/tvgSvgLoaderCommon.h
index dc9ed558c3..c657c0e21a 100644
--- a/thirdparty/thorvg/src/loaders/svg/tvgSvgLoaderCommon.h
+++ b/thirdparty/thorvg/src/loaders/svg/tvgSvgLoaderCommon.h
@@ -145,6 +145,26 @@ enum class SvgParserLengthType
Other
};
+enum class AspectRatioAlign
+{
+ None,
+ XMinYMin,
+ XMidYMin,
+ XMaxYMin,
+ XMinYMid,
+ XMidYMid,
+ XMaxYMid,
+ XMinYMax,
+ XMidYMax,
+ XMaxYMax
+};
+
+enum class AspectRatioMeetOrSlice
+{
+ Meet,
+ Slice
+};
+
struct SvgDocNode
{
float w;
@@ -155,7 +175,8 @@ struct SvgDocNode
float vh;
SvgNode* defs;
SvgNode* style;
- bool preserveAspect;
+ AspectRatioAlign align;
+ AspectRatioMeetOrSlice meetOrSlice;
};
struct SvgGNode
@@ -171,7 +192,8 @@ struct SvgSymbolNode
{
float w, h;
float vx, vy, vw, vh;
- bool preserveAspect;
+ AspectRatioAlign align;
+ AspectRatioMeetOrSlice meetOrSlice;
bool overflowVisible;
bool hasViewBox;
bool hasWidth;
diff --git a/thirdparty/thorvg/src/loaders/svg/tvgSvgSceneBuilder.cpp b/thirdparty/thorvg/src/loaders/svg/tvgSvgSceneBuilder.cpp
index a3f34fd46b..4cb4ffdaeb 100644
--- a/thirdparty/thorvg/src/loaders/svg/tvgSvgSceneBuilder.cpp
+++ b/thirdparty/thorvg/src/loaders/svg/tvgSvgSceneBuilder.cpp
@@ -49,9 +49,9 @@
*/
+#include "tvgMath.h" /* to include math.h before cstring */
#include <cstring>
#include <string>
-#include "tvgMath.h"
#include "tvgSvgLoaderCommon.h"
#include "tvgSvgSceneBuilder.h"
#include "tvgSvgPath.h"
@@ -68,7 +68,7 @@ struct Box
static bool _appendShape(SvgNode* node, Shape* shape, const Box& vBox, const string& svgPath);
-static unique_ptr<Scene> _sceneBuildHelper(const SvgNode* node, const Box& vBox, const string& svgPath, bool mask, bool* isMaskWhite = nullptr);
+static unique_ptr<Scene> _sceneBuildHelper(const SvgNode* node, const Box& vBox, const string& svgPath, bool mask, int depth, bool* isMaskWhite = nullptr);
static inline bool _isGroupType(SvgNodeType type)
@@ -282,7 +282,7 @@ static void _applyComposition(Paint* paint, const SvgNode* node, const Box& vBox
node->style->mask.applying = true;
bool isMaskWhite = true;
- auto comp = _sceneBuildHelper(compNode, vBox, svgPath, true, &isMaskWhite);
+ auto comp = _sceneBuildHelper(compNode, vBox, svgPath, true, 0, &isMaskWhite);
if (comp) {
if (node->transform) comp->transform(*node->transform);
@@ -560,10 +560,84 @@ static unique_ptr<Picture> _imageBuildHelper(SvgNode* node, const Box& vBox, con
}
-static unique_ptr<Scene> _useBuildHelper(const SvgNode* node, const Box& vBox, const string& svgPath, bool* isMaskWhite)
+static Matrix _calculateAspectRatioMatrix(AspectRatioAlign align, AspectRatioMeetOrSlice meetOrSlice, float width, float height, const Box& box)
+{
+ auto sx = width / box.w;
+ auto sy = height / box.h;
+ auto tvx = box.x * sx;
+ auto tvy = box.y * sy;
+
+ if (align == AspectRatioAlign::None)
+ return {sx, 0, -tvx, 0, sy, -tvy, 0, 0, 1};
+
+ //Scale
+ if (meetOrSlice == AspectRatioMeetOrSlice::Meet) {
+ if (sx < sy) sy = sx;
+ else sx = sy;
+ } else {
+ if (sx < sy) sx = sy;
+ else sy = sx;
+ }
+
+ //Align
+ tvx = box.x * sx;
+ tvy = box.y * sy;
+ auto tvw = box.w * sx;
+ auto tvh = box.h * sy;
+
+ switch (align) {
+ case AspectRatioAlign::XMinYMin: {
+ break;
+ }
+ case AspectRatioAlign::XMidYMin: {
+ tvx -= (width - tvw) * 0.5f;
+ break;
+ }
+ case AspectRatioAlign::XMaxYMin: {
+ tvx -= width - tvw;
+ break;
+ }
+ case AspectRatioAlign::XMinYMid: {
+ tvy -= (height - tvh) * 0.5f;
+ break;
+ }
+ case AspectRatioAlign::XMidYMid: {
+ tvx -= (width - tvw) * 0.5f;
+ tvy -= (height - tvh) * 0.5f;
+ break;
+ }
+ case AspectRatioAlign::XMaxYMid: {
+ tvx -= width - tvw;
+ tvy -= (height - tvh) * 0.5f;
+ break;
+ }
+ case AspectRatioAlign::XMinYMax: {
+ tvy -= height - tvh;
+ break;
+ }
+ case AspectRatioAlign::XMidYMax: {
+ tvx -= (width - tvw) * 0.5f;
+ tvy -= height - tvh;
+ break;
+ }
+ case AspectRatioAlign::XMaxYMax: {
+ tvx -= width - tvw;
+ tvy -= height - tvh;
+ break;
+ }
+ default: {
+ break;
+ }
+ }
+
+ return {sx, 0, -tvx, 0, sy, -tvy, 0, 0, 1};
+}
+
+
+static unique_ptr<Scene> _useBuildHelper(const SvgNode* node, const Box& vBox, const string& svgPath, int depth, bool* isMaskWhite)
{
unique_ptr<Scene> finalScene;
- auto scene = _sceneBuildHelper(node, vBox, svgPath, false, isMaskWhite);
+ auto scene = _sceneBuildHelper(node, vBox, svgPath, false, depth + 1, isMaskWhite);
// mUseTransform = mUseTransform * mTranslate
Matrix mUseTransform = {1, 0, 0, 0, 1, 0, 0, 0, 1};
@@ -585,20 +659,8 @@ static unique_ptr<Scene> _useBuildHelper(const SvgNode* node, const Box& vBox, c
Matrix mViewBox = {1, 0, 0, 0, 1, 0, 0, 0, 1};
if ((!mathEqual(width, vw) || !mathEqual(height, vh)) && vw > 0 && vh > 0) {
- auto sx = width / vw;
- auto sy = height / vh;
- if (symbol.preserveAspect) {
- if (sx < sy) sy = sx;
- else sx = sy;
- }
-
- auto tvx = symbol.vx * sx;
- auto tvy = symbol.vy * sy;
- auto tvw = vw * sx;
- auto tvh = vh * sy;
- tvy -= (symbol.h - tvh) * 0.5f;
- tvx -= (symbol.w - tvw) * 0.5f;
- mViewBox = {sx, 0, -tvx, 0, sy, -tvy, 0, 0, 1};
+ Box box = {symbol.vx, symbol.vy, vw, vh};
+ mViewBox = _calculateAspectRatioMatrix(symbol.align, symbol.meetOrSlice, width, height, box);
} else if (!mathZero(symbol.vx) || !mathZero(symbol.vy)) {
mViewBox = {1, 0, -symbol.vx, 0, 1, -symbol.vy, 0, 0, 1};
}
@@ -642,8 +704,15 @@ static unique_ptr<Scene> _useBuildHelper(const SvgNode* node, const Box& vBox, c
}
-static unique_ptr<Scene> _sceneBuildHelper(const SvgNode* node, const Box& vBox, const string& svgPath, bool mask, bool* isMaskWhite)
+static unique_ptr<Scene> _sceneBuildHelper(const SvgNode* node, const Box& vBox, const string& svgPath, bool mask, int depth, bool* isMaskWhite)
{
+ /* Exception handling: Prevent invalid SVG data input.
+ The size is the arbitrary value, we need an experimental size. */
+ if (depth > 2192) {
+ TVGERR("SVG", "Infinite recursive call - stopped after %d calls! Svg file may be incorrectly formatted.", depth);
+ return nullptr;
+ }
+
if (_isGroupType(node->type) || mask) {
auto scene = Scene::gen();
// For a Symbol node, the viewBox transformation has to be applied first - see _useBuildHelper()
@@ -654,12 +723,15 @@ static unique_ptr<Scene> _sceneBuildHelper(const SvgNode* node, const Box& vBox,
for (uint32_t i = 0; i < node->child.count; ++i, ++child) {
if (_isGroupType((*child)->type)) {
if ((*child)->type == SvgNodeType::Use)
- scene->push(_useBuildHelper(*child, vBox, svgPath, isMaskWhite));
+ scene->push(_useBuildHelper(*child, vBox, svgPath, depth + 1, isMaskWhite));
else
- scene->push(_sceneBuildHelper(*child, vBox, svgPath, false, isMaskWhite));
+ scene->push(_sceneBuildHelper(*child, vBox, svgPath, false, depth + 1, isMaskWhite));
} else if ((*child)->type == SvgNodeType::Image) {
auto image = _imageBuildHelper(*child, vBox, svgPath);
- if (image) scene->push(move(image));
+ if (image) {
+ scene->push(move(image));
+ if (isMaskWhite) *isMaskWhite = false;
+ }
} else if ((*child)->type != SvgNodeType::Mask) {
auto shape = _shapeBuildHelper(*child, vBox, svgPath);
if (shape) {
@@ -688,36 +760,18 @@ static unique_ptr<Scene> _sceneBuildHelper(const SvgNode* node, const Box& vBox,
/* External Class Implementation */
/************************************************************************/
-unique_ptr<Scene> svgSceneBuild(SvgNode* node, float vx, float vy, float vw, float vh, float w, float h, bool preserveAspect, const string& svgPath)
+unique_ptr<Scene> svgSceneBuild(SvgNode* node, float vx, float vy, float vw, float vh, float w, float h, AspectRatioAlign align, AspectRatioMeetOrSlice meetOrSlice, const string& svgPath)
{
+ //TODO: aspect ratio is valid only if viewBox was set
+
if (!node || (node->type != SvgNodeType::Doc)) return nullptr;
Box vBox = {vx, vy, vw, vh};
- auto docNode = _sceneBuildHelper(node, vBox, svgPath, false);
+ auto docNode = _sceneBuildHelper(node, vBox, svgPath, false, 0);
if (!mathEqual(w, vw) || !mathEqual(h, vh)) {
- auto sx = w / vw;
- auto sy = h / vh;
-
- if (preserveAspect) {
- //Scale
- auto scale = sx < sy ? sx : sy;
- docNode->scale(scale);
- //Align
- auto tvx = vx * scale;
- auto tvy = vy * scale;
- auto tvw = vw * scale;
- auto tvh = vh * scale;
- tvx -= (w - tvw) * 0.5f;
- tvy -= (h - tvh) * 0.5f;
- docNode->translate(-tvx, -tvy);
- } else {
- //Align
- auto tvx = vx * sx;
- auto tvy = vy * sy;
- Matrix m = {sx, 0, -tvx, 0, sy, -tvy, 0, 0, 1};
- docNode->transform(m);
- }
+ Matrix m = _calculateAspectRatioMatrix(align, meetOrSlice, w, h, vBox);
+ docNode->transform(m);
} else if (!mathZero(vx) || !mathZero(vy)) {
docNode->translate(-vx, -vy);
}
diff --git a/thirdparty/thorvg/src/loaders/svg/tvgSvgSceneBuilder.h b/thirdparty/thorvg/src/loaders/svg/tvgSvgSceneBuilder.h
index cecbbf02a8..311f3c80e6 100644
--- a/thirdparty/thorvg/src/loaders/svg/tvgSvgSceneBuilder.h
+++ b/thirdparty/thorvg/src/loaders/svg/tvgSvgSceneBuilder.h
@@ -25,6 +25,6 @@
#include "tvgCommon.h"
-unique_ptr<Scene> svgSceneBuild(SvgNode* node, float vx, float vy, float vw, float vh, float w, float h, bool preserveAspect, const string& svgPath);
+unique_ptr<Scene> svgSceneBuild(SvgNode* node, float vx, float vy, float vw, float vh, float w, float h, AspectRatioAlign align, AspectRatioMeetOrSlice meetOrSlice, const string& svgPath);
#endif //_TVG_SVG_SCENE_BUILDER_H_
diff --git a/thirdparty/thorvg/src/loaders/svg/tvgXmlParser.cpp b/thirdparty/thorvg/src/loaders/svg/tvgXmlParser.cpp
index c373da2dd5..231badd27d 100644
--- a/thirdparty/thorvg/src/loaders/svg/tvgXmlParser.cpp
+++ b/thirdparty/thorvg/src/loaders/svg/tvgXmlParser.cpp
@@ -26,10 +26,10 @@
#ifdef _WIN32
#include <malloc.h>
-#elif __FreeBSD__
- #include<stdlib.h>
-#else
+#elif defined(__linux__)
#include <alloca.h>
+#else
+ #include <stdlib.h>
#endif
#include "tvgXmlParser.h"
diff --git a/thirdparty/thorvg/src/loaders/tvg/tvgTvgBinInterpreter.cpp b/thirdparty/thorvg/src/loaders/tvg/tvgTvgBinInterpreter.cpp
index 62a75ecd3d..01a39b6e17 100644
--- a/thirdparty/thorvg/src/loaders/tvg/tvgTvgBinInterpreter.cpp
+++ b/thirdparty/thorvg/src/loaders/tvg/tvgTvgBinInterpreter.cpp
@@ -23,10 +23,10 @@
#ifdef _WIN32
#include <malloc.h>
-#elif __FreeBSD__
- #include<stdlib.h>
-#else
+#elif defined(__linux__)
#include <alloca.h>
+#else
+ #include <stdlib.h>
#endif
#include "tvgTvgCommon.h"
diff --git a/thirdparty/thorvg/src/savers/tvg/tvgTvgSaver.cpp b/thirdparty/thorvg/src/savers/tvg/tvgTvgSaver.cpp
index adf85836c3..57a21dcce1 100644
--- a/thirdparty/thorvg/src/savers/tvg/tvgTvgSaver.cpp
+++ b/thirdparty/thorvg/src/savers/tvg/tvgTvgSaver.cpp
@@ -28,10 +28,10 @@
#ifdef _WIN32
#include <malloc.h>
-#elif __FreeBSD__
- #include<stdlib.h>
-#else
+#elif defined(__linux__)
#include <alloca.h>
+#else
+ #include <stdlib.h>
#endif
static FILE* _fopen(const char* filename, const char* mode)
diff --git a/thirdparty/thorvg/update-thorvg.sh b/thirdparty/thorvg/update-thorvg.sh
index f2fd2a80e4..8cccc947ce 100755
--- a/thirdparty/thorvg/update-thorvg.sh
+++ b/thirdparty/thorvg/update-thorvg.sh
@@ -1,4 +1,4 @@
-VERSION=0.8.2
+VERSION=0.8.3
rm -rf AUTHORS inc LICENSE src *.zip
curl -L -O https://github.com/Samsung/thorvg/archive/v$VERSION.zip
bsdtar --strip-components=1 -xvf *.zip
@@ -26,3 +26,6 @@ cat << EOF > inc/config.h
#define THORVG_VERSION_STRING "$VERSION"
#endif
EOF
+for source in $(find ./ -type f \( -iname \*.h -o -iname \*.cpp \)); do
+ sed -i -e '$a\' $source
+done